[{"server":null,"owner":null,"id":"00fa79b4-334f-4fdd-a82f-09edf851cb6c","params":{"result":{"value":"","datetime":1584089006,"status":null,"version":0},"hash":{"value":"aa0w3sRU2hwydFSXl/KZOA==","datetime":1584089006,"status":null,"version":0},"enabled":{"value":true,"datetime":1584171821,"status":null,"version":0},"error_text":{"value":null,"datetime":1584166736,"status":null,"version":0},"type":{"value":"EgsScenario","datetime":1584174379,"status":null,"version":0},"settings":{"value":"{\r\n  \"state event\": {\r\n    \"enabled\": true,\r\n    \"source\": [\r\n      \"BaseObject\"\r\n    ],\r\n    \"target\": [\r\n      \"StateEvent\"\r\n    ],\r\n    \"condition\": \"(it is {0}) and (it[\\\"state\\\"].Text like \\\"{1}\\\")\",\r\n    \"action\": \"owner = string(source.Id); server = string(source.ServerId); position = source.position; state = source[\\\"state\\\"].Text?.Replace?('_', '.'); datetime = source[\\\"state\\\"].DateTime; version  = source.Version; itemtype = source.GetType().Name; name = source.name\\r\\n\",\r\n    \"params\": {\r\n      \"server\": \"51cc14bb-1fb6-44f9-a05d-6707ca5a28e0\"\r\n    },\r\n    \"tree\": {\r\n      \"VideoCamera\": {\r\n        \"alarm_*\": {}\r\n      }\r\n    },\r\n    \"operation\": [\r\n      \"update\"\r\n    ],\r\n    \"schedule\": [],\r\n    \"comment\": \"Если состояние  видеокамеры тревожное, то происходит трансляция данного состояния в менеджер событий\"\r\n  },\r\n  \"param translator for state\": {\r\n    \"enabled\": true,\r\n    \"source\": [\r\n      \"StilSoftRelay\"\r\n    ],\r\n    \"target\": [\r\n      \"Pin\",\r\n      \"Space\",\r\n      \"Pin\",\r\n      \"StreetLighting\"\r\n    ],\r\n    \"condition\": \"string({param}) like \\\"{0}\\\"\",\r\n    \"action\": \"{param} = \\\"{1}\\\"\",\r\n    \"params\": {\r\n      \"param\": \"state\"\r\n    },\r\n    \"tree\": {\r\n      \"ok_true\": {\r\n        \"ok_active\": {}\r\n      },\r\n      \"ok_false\": {\r\n        \"ok_inactive\": {}\r\n      },\r\n      \"none_unknown\": {\r\n        \"none_unknown\": {}\r\n      },\r\n      \"error_defective\": {\r\n        \"error_defective\": {}\r\n      }\r\n    },\r\n    \"operation\": [\r\n      \"update\"\r\n    ],\r\n    \"schedule\": [],\r\n    \"comment\": \"Транслирование состояний от реле стилсофт к уличному освещению\"\r\n  }\r\n}","datetime":1584176630,"status":null,"version":0},"state":{"value":"ok.normal","datetime":1584166736,"status":null,"version":0},"script":{"value":"# имя: 'Reflex Center'\r\n# описание: подсистема реакций и сценариев\r\n# тип триггера: 'EgsScenario'\r\n# создан: 2019.11.27 14:22:07, Сельченков Н.Ю.\r\n# изменен: '2019.12.27 12.40.32', Сельченков Н.Ю.\r\n# подробности: https://redmine.integra-s.com:11000/projects/eilyacuario/wiki/Reflex_Center\r\n\r\nuse System.Random\r\nuse System.Activator\r\nuse System.Linq.Expressions.Expression\r\nuse acuario2.dynamic.DynamicExpression\r\nuse acuario2.dynamic.ParseException\r\nuse acuario2.utils.ReflectionExtension\r\nuse acuario2.utils.TextExtension\r\nuse System.Collections.Generic.List(Object) as ObjectList\r\nuse System.Collections.Generic.List(Type) as TypeList\r\nuse System.Collections.Generic.List(string) as StringList\r\nuse System.Collections.Generic.List(string[]) as StringArrayList\r\nuse System.Collections.Generic.Dictionary(string, object) as GenericDictionary\r\n\r\nuse json_schema\r\n`\r\n{\r\n    \"type\": \"object\", \r\n    \"properties\": {}, \r\n    \"additionalProperties\": \r\n    {\r\n        \"type\": \"object\",\r\n        \"properties\":\r\n        {\r\n            \"enabled\":   { \"type\": \"boolean\" },\r\n            \"source\":    { \"type\": \"array\", \"items\": { \"type\": \"string\" } },\r\n            \"target\":    { \"type\": \"array\", \"items\": { \"type\": \"string\" } },\r\n            \"condition\": { \"type\": \"string\", \"format\": \"EGS\" },\r\n            \"action\":    { \"type\": \"string\", \"format\": \"EGS\" },\r\n            \"params\":    { \"type\": \"object\", \"additionalProperties\": { \"type\": \"string\" } },\r\n            \"tree\":      \r\n            { \r\n                \"type\": \"object\",\r\n                \"additionalProperties\": \r\n                { \r\n                    \"type\": \"object\",\r\n                    \"additionalProperties\": \r\n                    {\r\n                        \"type\": \"object\",\r\n                        \"additionalProperties\": { \"type\": \"string\" }\r\n                    }\r\n                }\r\n            },\r\n            \"operation\": \r\n            {\r\n                \"type\": \"array\",\r\n                \"items\": { \"type\": \"string\", \"format\": \"Protocol+Operation\" }\r\n            }, \r\n            \"schedule\":  \r\n            {\r\n                \"type\": \"array\",\r\n                \"items\": { \"type\": \"string\" }\r\n            },\r\n            \"comment\":  { \"type\": \"string\" }\r\n        }\r\n    }   \r\n}\r\n` as SETTINGS\r\n\r\nconst false_condition(source as Object, changes as string[]) = false\r\nconst Condition = typeof(false_condition)\r\n\r\nconst false_action(target as Object, source as Object) = false\r\nconst Action = typeof(false_action)\r\n\r\n####################################################################    \r\n    \r\nlet settings = SETTINGS(trigger.settings)\r\n\r\nfrom settings where Value.enabled do \r\n    let scope  = Key.Replace(' ', '_')\r\n    this.Scope = scope\r\n    with Value do\r\n        let externals = GenericDictionary()\r\n        let myprint(line as int, msg as string) = print(msg) \r\n        externals[\"print\"] = myprint\r\n\r\n        let source_params = StringList()\r\n        let source_objs   = ObjectList()\r\n        let source_types  = TypeList()\r\n        \r\n        this.Scope = scope..\"/source\"\r\n        from source do\r\n            try\r\n                let obj = graph[Guid(it)] as Object\r\n                source_types.Add(obj.GetType())\r\n                source_objs.Add(obj) \r\n            else\r\n            source_types.Add(Type(it))\r\n        now\r\n        \r\n        let source_type = from ReflectionExtension.GetCommonBaseInterfaces(source_types) single\r\n\r\n        let allowed_source_type(type as Type) = from source_types any it.IsAssignableFrom(type)\r\n        let allowed_source_obj(obj as Object) = (source_objs is empty) or (obj in source_objs)\r\n        let allowed_source(obj as Object)     = (obj isnt null) and (obj.GetType() is allowed_source_type) and (obj is allowed_source_obj)\r\n\r\n        let target_type_name = from target try last\r\n        let target_type      = Type(target_type_name)\r\n        let allowed_target_type(type as Type) = target_type.IsAssignableFrom(type)\r\n        let allowed_target(obj as Object)     = (obj isnt null) and (obj.GetType() is allowed_target_type)\r\n        \r\n        let process_targets(source as Object, action as Action) = \r\n            from graph.Find(source, target) of type Object \r\n                where it is allowed_target \r\n                all action(it, source)\r\n        end\r\n        \r\n        let target_is_event = Type(Event).IsAssignableFrom(target_type)\r\n        if target_is_event then \r\n            target_type = Type.GetType(\"acuario2.client.\"..target_type_name..\",acuario2.types\", true) \r\n            let proc(source as Object, action as Action) = \r\n                let event    = Activator.CreateInstance(target_type) as Object\r\n                let continue = action(event, source)\r\n                let server   = params[\"server\"]\r\n                let server   = Guid(if '-' in server then server else event[server]?.Text)\r\n                let request  = event.ExportCreate(server)\r\n                let channel  = this.Module.GetWampChannel(server)\r\n                Protocol.Put(channel.RealmProxy.RpcCatalog, request)\r\n                continue\r\n            end\r\n            process_targets = proc\r\n        end    \r\n        \r\n        print scope..\" source: \"..source_type\r\n        print scope..\" target: \"..target_type\r\n        \r\n        let compile_condition(code as string) = \r\n            let args = new [ Expression.Parameter(source_type), Expression.Parameter(string[] as Type, \"changes\") ]\r\n            let lambda   = DynamicExpression.TryParseLambda(args, bool, code, externals, source_params) \r\n            let delegate = lambda.Compile()\r\n            let proc(source as Object, changes as string[]) = delegate.DynamicInvoke(new [source, changes]) as bool\r\n        end\r\n\r\n        let compile_action(code as string) = \r\n            let args     = new [ Expression.Parameter(target_type), Expression.Parameter(source_type, \"source\") ]\r\n            let lambda   = DynamicExpression.TryParseLambda(args, null, code, externals, null) \r\n            let delegate = lambda.Compile()\r\n            let proc(target as Object, source as Object) = \r\n                let continue = delegate.DynamicInvoke(new [target, source])\r\n                (continue isnt bool) or (continue as bool)\r\n        end\r\n        \r\n        let replace(text as string, key as string, value as string) = \r\n            text.Replace(\"{\" ..key..\"}\",  value) \r\n                .Replace(\"{↑\"..key..\"}\", TextExtension.UppercaseFirst(value))\r\n                .Replace(\"{↓\"..key..\"}\", TextExtension.LowercaseFirst(value))\r\n        end\r\n        \r\n        let replace_params(text as string) = \r\n            from params do text = replace(text, Key, Value) now\r\n            text\r\n        end\r\n\r\n        let condition = replace_params(it.condition)\r\n        let action    = replace_params(it.action)\r\n\r\n        print scope..\" condition: \"..condition\r\n        print scope..\" action: \"..action\r\n\r\n        let replace_flow(text as string, flow as string[]) = \r\n            from 0 to flow.Length - 1 do text = replace(text, string(it), flow[it]) now\r\n            text\r\n        end\r\n        \r\n        let compile_flow(flow as string[]) =\r\n            this.Scope    = scope..\"/tree/\"..string.Join(\"/\", flow) \r\n            let scope     = this.Scope\r\n            let condition = compile_condition(replace_params(replace_flow(condition, flow)))\r\n            let action    = compile_action   (replace_params(replace_flow(action,    flow)))\r\n            let proc(source as Object, changes as string[]) =\r\n                this.Scope = scope\r\n                condition(source, changes) and process_targets(source, action)\r\n        end\r\n        \r\n        let flows = StringArrayList()\r\n        from tree do\r\n            let keys = new [ Key ] \r\n            if Value is empty then flows.Add(keys) \r\n            else \r\n                from Value do\r\n                    let keys = from keys concat new [ Key ] to array\r\n                    if Value is empty then flows.Add(keys)\r\n                    else \r\n                        from Value do \r\n                            let keys = from keys concat new [ Key, Value ] to array\r\n                            flows.Add(keys) \r\n                        now\r\n                now\r\n        now\r\n        \r\n        let flows = from flows select compile_flow(it) to list\r\n        \r\n        if flows is empty then flows.Add(compile_flow(string[](0)))\r\n\r\n        this.Scope = scope\r\n        let expected(changes) = from source_params any it in changes\r\n        \r\n        print scope..\" source params used: \"..string.Join(\", \", source_params)\r\n        \r\n        let execute(source as Object, changes as string[]) = \r\n            if source is allowed_source then\r\n                from flows where Invoke(source, changes) try first\r\n                this.Scope = scope\r\n            void()\r\n        end\r\n\r\n        let no_changes = string[](0) \r\n        let on_update(source as AbstractObject, changes as string[]) = if changes is expected then execute(source as Object, changes)\r\n        let on_delete(source as AbstractObject)                      = execute(source as Object, no_changes)\r\n        let on_schedule()                                            = from graph.Values of type Object do execute(it, no_changes) now\r\n\r\n        from operation do\r\n            print scope..\" runs on \"..it\r\n            switch it\r\n                when \"create\" then this.RunOnCreated(on_update)\r\n                when \"update\" then this.RunOnUpdated(on_update)\r\n                when \"delete\" then this.RunOnDeleted(on_delete)\r\n        now \r\n\r\n        from schedule do \r\n            print scope..\" runs on \"..it\r\n            this.RunOnSchedule(it, on_schedule) \r\n        now\r\n        \r\nnow\r\n","datetime":1584089006,"status":null,"version":0},"name":{"value":"Reflex Center","datetime":1584089006,"status":null,"version":0}},"entity":"item","operation":"create"}]