diff --git a/README.md b/README.md index 286f84b..4f4ce70 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,15 @@ package by specifying the `TEST` variable. For example below, only #### Run -`go run api.go` +Environment variables for plugins +``` +export ELASTICFEED_PLUGIN_MIN_PORT=40000 +export ELASTICFEED_PLUGIN_MAX_PORT=41000 +``` +Compilation and running +``` +go run api.go +``` #### Dependencies * `go get github.com/feedlabs/feedify` [repo](https://github.com/feedlabs/feedify) diff --git a/common/config/general.go b/common/config/general.go index 8913fe6..d3d9577 100644 --- a/common/config/general.go +++ b/common/config/general.go @@ -3,6 +3,7 @@ package config import ( "fmt" "os" + "strconv" "github.com/feedlabs/feedify" ) @@ -30,6 +31,26 @@ func GetPluginStoragePath() string { return feedify.GetConfigKey("plugin-manager::storage") } +func GetPluginPortMin() uint { + port, err := strconv.ParseUint(feedify.GetConfigKey("plugin-manager::port_min"), 10, 0) + + if err == nil { + return uint(port) + } + + return 40000 +} + +func GetPluginPortMax() uint { + port, err := strconv.ParseUint(feedify.GetConfigKey("plugin-manager::port_max"), 10, 0) + + if err == nil { + return uint(port) + } + + return 41000 +} + func GetHomeAbsolutePath() string { pwd, _ := os.Getwd() return pwd @@ -43,7 +64,7 @@ func init() { os.Exit(1) } - path := GetHomeAbsolutePath() + "/" + feedify.GetConfigKey("plugin-manager::storage") + path := GetHomeAbsolutePath() + "/" + GetPluginStoragePath() if _, err := os.Stat(path); err != nil { if os.IsNotExist(err) { err = os.MkdirAll(path, 0777) diff --git a/conf/app.conf b/conf/app.conf index 6117fe7..0a774f1 100644 --- a/conf/app.conf +++ b/conf/app.conf @@ -1,58 +1,69 @@ -appname=feedify +appname=elasticfeed runmode=dev autorender=false copyrequestbody=true +# Global configuration [feedify] port=10100 # enable restful api rest=on # enable websocket interface websocket=on -# enable scenario engine -scenario=off -# enable crwaler and indexer -crawler=off [api] su=x-super-user key=supersecret whitelist=127.0.0.1 +# Cluster configuration [cluster] # communication platform nsq|redis|none middleware=none +# Authentication configuration [auth] # type can by basic|digest|none type=digest realm=localhost +# Service Manager configuration [service] cache=memcache graph=graph stream=stream js=otto -[redis] -host=localhost -port=6379 -protocol=tcp - +# Streaming configuration [stream] message_adapter=socket_redis +# Graph database configuration +[graph] +storage_adapter=neo4j_cypher + +# Neo4j graph database configuration [neo4j] host=localhost port=7474 db=db/data +# Redis configuration +[redis] +host=localhost +port=6379 +protocol=tcp + +# Memcache configuration [memcache] host=localhost port=11211 -[graph] -storage_adapter=neo4j_cypher +# Plugin Manager configuration +[plugin-manager] +storage=public/userfiles/plugin/imports +port_min=40000 +port_max=41000 # for distributed cluster if # scenario mode is enabled (see [feedify]) @@ -62,5 +73,3 @@ host=localhost port=1111 topic=feed -[plugin-manager] -storage=public/userfiles/plugin/imports diff --git a/elasticfeed/elasticfeed.go b/elasticfeed/elasticfeed.go index 5628668..a899969 100644 --- a/elasticfeed/elasticfeed.go +++ b/elasticfeed/elasticfeed.go @@ -8,6 +8,7 @@ import ( "github.com/feedlabs/elasticfeed/service" "github.com/feedlabs/elasticfeed/event" "github.com/feedlabs/elasticfeed/resource" + "github.com/feedlabs/elasticfeed/population" "github.com/feedlabs/feedify" ) @@ -18,6 +19,7 @@ type Elasticfeed struct { S model.ServiceManager P model.PluginManager W model.WorkflowManager + PP model.PopulationManager } func (this *Elasticfeed) GetEventManager() model.EventManager { @@ -40,6 +42,10 @@ func (this *Elasticfeed) GetWorkflowManager() model.WorkflowManager { return this.W } +func (this *Elasticfeed) GetPopulationManager() model.PopulationManager { + return this.PP +} + func (this *Elasticfeed) GetConfig() map[string]interface {} { return make(map[string]interface {}) } @@ -49,6 +55,7 @@ func (this *Elasticfeed) Run() { this.GetServiceManager().Init() this.GetWorkflowManager().Init() this.GetEventManager().Init() + this.GetPopulationManager().Init() feedify.SetStaticPath("/static", "public") feedify.Run() @@ -63,6 +70,7 @@ func NewElasticfeed() model.Elasticfeed { engine.P = plugin.NewPluginManager(engine) engine.W = workflow.NewWorkflowManager(engine) engine.S = service.NewServiceManager(engine) + engine.PP = population.NewPopulationManager(engine) return engine } diff --git a/elasticfeed/model/population.go b/elasticfeed/model/population.go new file mode 100644 index 0000000..f883e26 --- /dev/null +++ b/elasticfeed/model/population.go @@ -0,0 +1,6 @@ +package model + +type PopulationManager interface { + + Init() +} diff --git a/plugin/manager.go b/plugin/manager.go index 6bd61c6..ae63e29 100644 --- a/plugin/manager.go +++ b/plugin/manager.go @@ -211,9 +211,9 @@ func (c *PluginManager) pluginClient(path string) *Client { func NewPluginManager(engine emodel.Elasticfeed) emodel.PluginManager { - pm := &PluginManager{engine, nil, nil, nil, nil, nil, nil, 40000, 41000} + pm := &PluginManager{engine, nil, nil, nil, nil, nil, nil, config.GetPluginPortMin(), config.GetPluginPortMax()} - pm.discover(filepath.Join(config.GetHomeAbsolutePath(), "public/userfiles/plugin/imports")) + pm.discover(filepath.Join(config.GetPluginStoragePath())) return pm } diff --git a/plugin/model/resource_api.go b/plugin/model/resource_api.go index 6c90251..7234f5e 100644 --- a/plugin/model/resource_api.go +++ b/plugin/model/resource_api.go @@ -7,6 +7,7 @@ type ResourceApi struct { func (this *ResourceApi) CreateEntryMetric() {} func (this *ResourceApi) DeleteEntryMetric() {} func (this *ResourceApi) UpdateEntryMetric() {} +func (this *ResourceApi) GetEntryMetric() {} func (this *ResourceApi) ClearFeed() {} func (this *ResourceApi) ReorderFeed() {} diff --git a/plugin/model/viewer.go b/plugin/model/viewer.go new file mode 100644 index 0000000..d078b3c --- /dev/null +++ b/plugin/model/viewer.go @@ -0,0 +1,103 @@ +package model + +/* + TODO: + + ********************************************************** + + SHOULD BE BASICALLY A BRIDGE TO PUPULATION/PERSON CLASS + + ********************************************************** + + - VIEWER IS USED IN DISTRIBUTION/PIPELINE WORKFLOW + - VIEWER IS USED IN LEARNING/EVOLUTION/SCENARIO WORKFLOW + - VIEWER IS UPDATED/USED IN SENSOR UPDATE WORKFLOW + + ***************************************************************************************** + VIEWER SHOULD BE GLOBALY REGISTERED AND UPDATED WITH SENSOR STATE BY SCHEDULE + ***************************************************************************************** + */ + +type IViewer interface { +} + +type Viewer struct { +} + +func (this *Viewer) GetMetrics() { + + /* + - GET HEAT MAPS + - GET ACTIONS + - GET HABITS + - GET BEHAVIOURS + - ... + */ + +} + +func (this *Viewer) GetMetricsStats() {} + +func (this *Viewer) GetMetricsForEntry() { + + /* + - ENTRY METRICS/INDICES FOR SPECIFIC VIEWER + */ + +} + +func (this *Viewer) GetMetricsForFeed() { + + /* + - FEED METRICS/INDICES FOR SPECIFIC VIEWER + */ + +} + +func (this *Viewer) GetGlobalIndicesForEntry() { + + /* + - IT SHOULD BE A PROXY TO RESOURCE-API + - IT SHOUD GET ALL MINDICES FOR ENTRY + */ + +} + +func (this *Viewer) GetGlobalIndicesForFeed() {} + +func (this *Viewer) GetStorages() { + + /* + - GET ANNs BRAINS + - GET SVMs + - ... + */ + +} + +func (this *Viewer) GetCurrentContext() { + + /* + - IP + - LOCATION + - BROWSER + - OS + - SENSORS + - WEATHER + - DAY PART + - BIORYTHM + - ... + */ + +} + +func (this *Viewer) GetEnvironment() { + + /* + - SHOULD COMBINE + - CURRENT CONTEXT WITH... + - SENSORS WITH... + - METRICS... + */ + +} diff --git a/plugin/rpc_data.go b/plugin/rpc_data.go deleted file mode 100644 index 4af435e..0000000 --- a/plugin/rpc_data.go +++ /dev/null @@ -1,19 +0,0 @@ -package plugin - -import ( - "net/rpc" - "github.com/feedlabs/elasticfeed/plugin/model" -) - -// An implementation of packer.Cache where the RpcData is actually executed -// over an RPC connection. -type RpcData struct { - client *rpc.Client - endpoint string -} - -// CacheRpcServer wraps a packer.Cache implementation and makes it exportable -// as part of a Golang RPC server. -type DataRpcServer struct { - data model.Data -} diff --git a/population/human.go b/population/human.go new file mode 100644 index 0000000..236c298 --- /dev/null +++ b/population/human.go @@ -0,0 +1,47 @@ +package population + +/* + IT DESCRIBE PERSON AS ENTITY OF PERSONALITY + + IT HAS: + - HABITS + - ACTIONS + - BEHAVIOURS + - MOODS + - PHASES + - ... + */ + +const ( + HUMAN_SEX_FEMALE = 1 + HUMAN_SEX_MALE = 2 +) + +type HumanController struct { + UID string + + pvps map[string]*PVPController + + sex int +} + +func (this *HumanController) GetSex() int { + return this.sex +} + +func (this *HumanController) SetSex(sex int) { + this.sex = sex +} + +// experimental thinking... +func (this *HumanController) GetMoods() {} +func (this *HumanController) GetLActivityHours() {} + +// SUPER SUPER GOAL: Private Virtual Personality +func (this *HumanController) GetNewPVP() *PVPController { + return NewPrivateVirtualPersonality() +} + +func NewHumanController() *HumanController { + return &HumanController{"0", nil, 0} +} diff --git a/population/manager.go b/population/manager.go new file mode 100644 index 0000000..65578ad --- /dev/null +++ b/population/manager.go @@ -0,0 +1,21 @@ +package population + +import ( + emodel "github.com/feedlabs/elasticfeed/elasticfeed/model" +) + +type PopulationManager struct { + engine emodel.Elasticfeed + + people map[string]*HumanController + societies map[string]*SocietyController +} + +func (this *PopulationManager) Init() { + this.people = make(map[string]*HumanController) + this.societies = make(map[string]*SocietyController) +} + +func NewPopulationManager(engine emodel.Elasticfeed) *PopulationManager { + return &PopulationManager{engine, nil, nil} +} diff --git a/population/pvp.go b/population/pvp.go new file mode 100644 index 0000000..d4ba3ae --- /dev/null +++ b/population/pvp.go @@ -0,0 +1,89 @@ +package population + +/* + *********************************** + * Private Virtual Personality * + *********************************** + + https://en.wikipedia.org/wiki/Talk%3APrivate_virtual_personality + + VI vs AI + + A VI is restricted to certain responses and actions, and can't become self-aware, + while an AI is free to think how it likes and is self-aware. + + */ + +type PVPController struct { + + /* + Basic: + - SHOULD LEARNs FROM HUMAN + - SHOULD SERVEs HUMAN + - SHOULD ADVISEs HUMAN + - SHOULD TEACHes HUMAN + + Advnaced: + - SHOULD TALK TO OTHER PVPs + - SHOULD ANSWER QUESTIONS + + Intelligence: + - Intelligence Quotient (IQ) + - Emotional Intelligence (EI) + */ + +} + +func (this *PVPController) Train() { + /* + PVP LEARNS VIA HUMAN TEACHING + - CARROT/STICK METHOD + - MOOD DETECTION + - ... + */ +} + +func (this *PVPController) Query() { + /* + QUESTION WITH LOGIC ANSWER: YES/NO + + QUESTION WITH PROBABILITY ANSWER: MAYBE YES, MAYBE NOT + + QUESTION ABOUT LIKENESS OF SUBJECT: LIKE/DISLIKE + + QUESTION ABOUT LIKENESS OF PRICE: LIKE/DISLIKE + + QUESTION ABOUT MOOD: GOOD, BAD, SAD + */ +} + +// SUPER GOAL: Artificial Intelligence +func (this *PVPController) GetAI() { + /* + SHOULD IMPLEMENT BRIDGE TO AI FRAMEWORK + - SHOULD ALLOW TO REGISTER BRAINS + - SHOULD ALLOW TO TRAIN/FORWARD OVER BRAINS + - SHOULD ALLOW FOR EVOLVING + - SHOULD ALLOW FOR GENETIC ALGORITHMS + - SHOULD ALLOW FOR SIMPLE SVM + - SHOULD ALLOW FOR ANY KIND OF AI + + ******************************************** + LOOKS LIKE IMPORTANT PART + IT WILL BE THE GOAL OF ELASTICFEED + TO MAKE IT WORKING. + + THE COMBINATION OF: + - TRAINING USING CURRENT SENSORS + - CURRENT BRAIN STATE + - CURRENT INDICES + - CURRENT METRICS OF ACTIONS, BEHAVIOURS + - CURRENT HABITS + - ... + ******************************************** + */ +} + +func NewPrivateVirtualPersonality() *PVPController { + return &PVPController{} +} diff --git a/population/society.go b/population/society.go new file mode 100644 index 0000000..54bd2c3 --- /dev/null +++ b/population/society.go @@ -0,0 +1,13 @@ +package population + +type SocietyController struct { + people map[string]*HumanController +} + +func (this *SocietyController) Init() { + this.people = make(map[string]*HumanController) +} + +func NewSocietyController() *SocietyController { + return &SocietyController{nil} +} diff --git a/population/trait/behaviour.go b/population/trait/behaviour.go new file mode 100644 index 0000000..d8a3c89 --- /dev/null +++ b/population/trait/behaviour.go @@ -0,0 +1,3 @@ +package trait + +type BehaviourController struct {} diff --git a/population/trait/decision.go b/population/trait/decision.go new file mode 100644 index 0000000..a4aebc0 --- /dev/null +++ b/population/trait/decision.go @@ -0,0 +1,3 @@ +package trait + +type DecisionController struct {} diff --git a/population/trait/fact.go b/population/trait/fact.go new file mode 100644 index 0000000..5b5e940 --- /dev/null +++ b/population/trait/fact.go @@ -0,0 +1,3 @@ +package trait + +type FactController struct {} diff --git a/population/trait/habit.go b/population/trait/habit.go new file mode 100644 index 0000000..1c741a5 --- /dev/null +++ b/population/trait/habit.go @@ -0,0 +1,3 @@ +package trait + +type HabitController struct {} diff --git a/population/trait/location.go b/population/trait/location.go new file mode 100644 index 0000000..2af8c28 --- /dev/null +++ b/population/trait/location.go @@ -0,0 +1,3 @@ +package trait + +type LocationController struct {} diff --git a/population/trait/mood.go b/population/trait/mood.go new file mode 100644 index 0000000..2334cfa --- /dev/null +++ b/population/trait/mood.go @@ -0,0 +1,3 @@ +package trait + +type MoodController struct {} diff --git a/workflow/workflow.go b/workflow/workflow.go index a53ea43..bee0cad 100644 --- a/workflow/workflow.go +++ b/workflow/workflow.go @@ -1,7 +1,7 @@ package workflow import ( - "fmt" +// "fmt" "encoding/json" "time" @@ -9,6 +9,7 @@ import ( "github.com/feedlabs/elasticfeed/plugin/model" "github.com/feedlabs/elasticfeed/resource" + "github.com/feedlabs/elasticfeed/population" jsonutil "github.com/mitchellh/packer/common/json" "github.com/mitchellh/mapstructure" @@ -18,10 +19,21 @@ import ( "github.com/feedlabs/elasticfeed/service/stream/controller/room" ) +/* + WORKFLOW CONTROLLER SHOULD + - REGISTER FEED WORKFLOW + - SHOULD STORE SUBSCRIBED HUMANS/VIEWERS + - SHOULD BE ABLE TO READ/WRTIE METRICS/INDICES/STORAGES + - SHOULD BE ABLE TO ACCESS SENSORS STATUS FOR SPECIFIC WORKFLOW + + */ + type WorkflowController struct { feed *resource.Feed manager *WorkflowManager + population map[string]*population.HumanController + profiler *model.Profiler IndexerTimeout int @@ -74,8 +86,8 @@ func (this *WorkflowController) Init() { var rawTplInterface interface{} err := jsonutil.Unmarshal(data, &rawTplInterface) if err != nil { - fmt.Println(data) - fmt.Println(err) + // fmt.Println(data) + // fmt.Println(err) return } @@ -90,15 +102,15 @@ func (this *WorkflowController) Init() { decoder, err := mapstructure.NewDecoder(decoderConfig) if err != nil { - fmt.Println("err2") - fmt.Println(err) + // fmt.Println("err2") + // fmt.Println(err) return } err = decoder.Decode(rawTplInterface) if err != nil { - fmt.Println("err3") - fmt.Println(err) + // fmt.Println("err3") + // fmt.Println(err) return } @@ -108,9 +120,9 @@ func (this *WorkflowController) Init() { - PLUGINS SHOULD BE ABLE TO RUN FOR SPECIFIC WORKFLOW */ - fmt.Println(rawTpl) - fmt.Println(rawTpl.Storing.NewEntryEvent.Indexers[0]["type"]) - fmt.Println(rawTpl.Storing.NewEntryEvent.Crawlers[0]["type"]) + // fmt.Println(rawTpl) + // fmt.Println(rawTpl.Storing.NewEntryEvent.Indexers[0]["type"]) + // fmt.Println(rawTpl.Storing.NewEntryEvent.Crawlers[0]["type"]) } @@ -229,10 +241,24 @@ func (this *WorkflowController) ExecutePipelineChain(socketEvent smodel.SocketEv } } +func (this * WorkflowController) GetHumanByUID(uid string) *population.HumanController { + return this.population[uid] +} + +func (this * WorkflowController) RegisterHuman(human *population.HumanController) { + this.population[human.UID] = human +} + +func (this * WorkflowController) UnregisterHuman(human *population.HumanController) { + delete(this.population, human.UID) +} + func NewWorkflowController(feed *resource.Feed, wm *WorkflowManager) *WorkflowController { + population := make(map[string]*population.HumanController) + data := feed.GetWorkflow().GetProfilerRawData() p := model.NewProfiler(data) - w := &WorkflowController{feed, wm, p, 100, 100, 100, 50, 100} + w := &WorkflowController{feed, wm, population, p, 100, 100, 100, 50, 100} w.Init()