-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathViolla.py
420 lines (345 loc) · 12.4 KB
/
Violla.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
#from clusters import cluster_deducer
#TODO from API import api
#TODO move all imports to some other place
#from ConsoleAPI import *
from TelegramAPI import *
import Core.LinguisticsBase
from Core.LinguisticsBase import Semantics
import time
import subprocess
import os
from ViollaRoutines import MindState
from ViollaRoutines import MindReflection
from ViollaRoutines import Mood as _M
from ViollaRoutines import Phrase as _P
from ViollaRoutines import Topics as _T
from ViollaRoutines import PATH_TO_PLANNER, PATH_TO_CLUSTERS
from ViollaRoutines import CORE_CLUSTERS
from ViollaRoutines import DEDUCTION
from ViollaRoutines import INTUITION
#TODO rewrite all "import *"
from Core.ClusterController import *
#TODO Move to ViollaRoutines
import threading
import json
from Core.Planner import *
import random
#for multi users launch another copy of violla
#or multi copies of general processing threads
#with separation for users inside of clusters
#or just multiple versions of clusters
class Violla():
def __init__(self):
#TODO move it to some other place
self.last_heard = ""
self.mindState = MindState.Idle
self.mood = _M.Cold
#TODO MAKE API CALLS ABSTRACT
self.interface = TelagramBotWrapper()
#self.interface = CLIBotWrapper()
self.semantics = Semantics()
self.deduction = DEDUCTION
self.intuition = INTUITION
# TODO Fix This later
self.patience = random.randint(100,250)
self.assemble_core()
#self.planner = Planner()
#self.planner_cluster = None
#self.start_planning()
#launch acting client-like and server like threads
self.say(_T.Awake)
#TODO Launch Planner cluster
# TODO Make all parts of Violla clusters // modules which could be easylly be
# loaded and unloaded
def assemble_core(self):
for core_cluster in CORE_CLUSTERS:
self.intuition.register_cluster(core_cluster.description, link = core_cluster.Cluster)
# TODO all Violla methods should be void like
# No returns
# So no recursion exception processing isuses
def confidence(f, *args, **kwards):
def confident_action(self, *args, **kwards):
try:
return f(self, *args, **kwards)
except Exception as e:
#print(repr(e))
self.say(message=str(e))
self.say(topic=_T.Error)
return confident_action
#TODO probably delete
#@confidence
#def start_planning(self):
#TODO - probably move to some other place. But planner cluster is special to Violla
#And it's supposed to be always up
#Launchlib maybe
# self.say(message=PATH_TO_PLANNER)
# self.say(message=PATH_TO_CLUSTERS)
# p = subprocess.Popen(["python3", PATH_TO_PLANNER+"/cluster.py", PATH_TO_CLUSTERS])
#TODO description to launch params maybe
#TODO keywords from linguistsics base
#or all of above from planner params
# planner_description = open(os.path.join(PATH_TO_PLANNER,"description.json"))
# planner_description = json.load(planner_description)
# self.deduction.register_cluster(planner_description)
@confidence
def think(self, topic, message):
return self.semantics(topic, message, self.mood)
@confidence
#TODO Synchronisation
# ONLY BYSY//IDLE
# TODO process security
def setMind(self, mind_state):
self.mindState = mind_state
return MindReflection.DoingThis
#if self.mindState != MindState.Idle:
# return MindReflection.Busy
#else:
# self.mindState = mind_state
# return MindReflection.DoingThis
@confidence
def say(self, topic=None, message=None, think_loudly=False):
# TODO rewrite
if(think_loudly):
if(random.randint(1,100000)>99985):
self.interface.send_update(self.think(topic, message))
else:
self.interface.send_update(self.think(topic, message))
@confidence
def listen(self):
#TODO - better parsing. Return class instead of just string.
#TODO - rewrite from altered ClusterController
new_request = self.interface.check_last_update()
if new_request:
return new_request
def listening(self):
while True:
heared = self.listen()
if heared:
yield heared
time.sleep(1)
@confidence
def act(self):
internal_motive_flow = threading.Thread(target = self.internal_motive)
external_motive_flow = threading.Thread(target = self.external_motive)
internal_motive_flow.start()
external_motive_flow.start()
internal_motive_flow.join()
external_motive_flow.join()
def select_motives(self, idea_type):
# TODO refactor on namings "idea//motive//etc"
return self.intuition.focus(idea_type) + self.deduction.focus(idea_type)
@confidence
def process_active_motive(self, motive):
# TODO probably replace with async approach
# TODO switch to constant reflection with timer updates
# TODO with patience
#while True:
# TODO patience and motives reentrance processing
if motive.direction == IDEA_DIRECTION.REFLECT:
print("Asking cluster for some responce on " + motive.inner_memory)
#TODO wrap everything
motive.inner_memory = motive.cluster.link.actor.send(motive.inner_memory)
next(motive.cluster.link.actor)
motive.direction = IDEA_DIRECTION.COVER
# TODO more explicit way to clear buffer and change motive state
#motive.inner_memory = ""
elif motive.direction == IDEA_DIRECTION.COVER:
# TODO dispatch motive responce
# it could be done
# or ask for some additional data
# or just idle ???
# TODO linguistics
# print("Probably place of exception 1")
# print(motive.cluster.link.actor)
# motive_reflection = next(motive.cluster.link.actor)
# print(motive_reflection)
# if not motive_reflection:
# motive_reflection = next(motive.cluster.link.actor)
# print("Probably place of exception 2")
# print(motive_reflection)
# motive.inner_memory = motive_reflection
# print(motive.inner_memory)
# print("Probably place of exception 3")
# TODO check on "Done"
# if not done - rise up this question
# TODO make namedtuple
if motive.inner_memory:
data = json.loads(motive.inner_memory)
if(data["type"]!="done"):
self.say(message = random.choice(["Listen. ", "Let me see. ", "So... ", "Well. ", "You know... ", "Hey. ", "Be focused. "]) + data["message"])
motive.inner_memory = ""
else:
self.say(message = data["message"])
self.setMind(MindState.Idle)
#TODO wrap everything
motive.cluster.controller.close(motive)
else:
if self.last_heard:
motive.direction = IDEA_DIRECTION.REFLECT
motive.inner_memory = self.last_heard
self.last_heard = ""
else:
self.patience-=1
# TODO Patience
# TODO Linguistics
# ESCALATE MODULE LOGICS BY HERSELF
#self.say(message = "I'm waiting...", think_loudly=True)
# On done switch to IDLE
#if not done
# TODO start patience mechanism
if self.patience == 0:
self.patience = random.randint(100,250)
self.last_heard = "No responce"
# TODO internal motive is processing itself
# TODO add sort of events instead of time.sleep
# TODO Move it to some module. i.e. refactor
# TODO new become selected if there are no too much of selected
# TODO selected with most priority become actuall
# TODO work with actuall untill "Done"
@confidence
def internal_motive(self):
while True:
time.sleep(1)
# TODO complete state machine
# focus on intuition
# focus on deduction
# psocess active
# if no active process selected
# if no selected process new
# if no new process delayed
# if no delayed proces denied
# TODO merge deduction and intuition
active_motives = self.select_motives(IDEA_TYPE.ACTIVE)
if not active_motives:
# TODO to linguistics
# or more like sort of self-reflection core cluster
self.say(message="So... we're up for nothing.", think_loudly=True)
elif len(active_motives)>1:
raise Exception("Somehow now i'm on multiple tasks. This is definitely not ok.")
else:
# TODO write a config or some logics to control number of such a messages
self.say(message="I'm up for something.", think_loudly=True)
self.process_active_motive(active_motives[0])
continue
# TODO Condition for changing idea type
selected_motives = self.select_motives(IDEA_TYPE.SELECTED)
if not selected_motives:
self.say(message="I have no plans...", think_loudly=True)
else:
for motive in selected_motives:
#TODO select the most actual one
#TODO all into linguistics
self.say(message=random.choice(["About... ", "Speaking of. ", "And. "]) + idea.cluster.name, think_loudly=True)
self_reflection = self.setMind(MindState.Busy)
if(self_reflection == MindReflection.DoingThis):
motive.idea_type = IDEA_TYPE.ACTIVE
#TODO correct cycle processing
continue
new_motives = self.select_motives(IDEA_TYPE.NEW)
if not new_motives:
self.say(message="No intentions...", think_loudly=True)
else:
self.say(message="All i have now is just some intentions...", think_loudly=True)
for idea in new_motives:
# TODO check if it's still actuall
# TODO select only valid ones
#self.say(message="So... " + idea.cluster.name + "...")#\n" + "We're stopped when you said \"" + idea.inner_memory + "\".")
idea.idea_type = IDEA_TYPE.SELECTED
continue
denied_motives = self.select_motives(IDEA_TYPE.DENIED)
if not denied_motives:
self.say(message="I'm open to just any activities...", think_loudly=True)
delayed_motives = self.select_motives(IDEA_TYPE.DELAYED)
if not delayed_motives:
self.say(message="I tracked... Well... Nothing.", think_loudly=True)
#time.sleep(10)
#TODO update with altered cluster controller
# ...
#self.deduction.check()
#run in thread
#act like server
# TODO Horisontal refactoring
@confidence
def deduce(self, request):
# TODO move to violla routines
cluster_reflection = None
cluster_reflection = self.intuition(request)
#print(cluster_reflection)
if not cluster_reflection:
cluster_reflection = self.deduction(request)
#print(cluster_reflection)
if not cluster_reflection:
print("Method just returning None type object")
return None
#TODO - make it confident
#raise Exception("I don't know what this is supposed to mean.")
return cluster_reflection
# TODO it's not processing
# just registration of external events -> search for cluster -> register it's as idea
def external_motive(self):
for request in self.listening():
print("*"+request)
# TODO detect wether it's related to some other cluster
if self.mindState == MindState.Busy:
self.last_heard = request
continue
#TODO wrap try -> catch -> blame into
#class with context manager
#with target function as a parameter
#TODO change this if to something else
#maybe use telegram "/" sentinel in some form
deduction = self.deduce(request)
# It could be unknown cluster -> send error
# Or ask processor wether such cluster exists
# ...
# It could be known cluster
# but not idea
# wrap to idea ...
# wait
# ...
# It could be idea
# ...
# active -> send request for it
# delayed -> decide what to do
# denied -> ignore
# new -> if there is no active ideas - make it active
# TODO if there are an active idea
# interpret this as message for idea
# and not as invocation of a new idea
if not deduction:
# TODO into linguistics
self.say(message="I don't know what this is supposed to mean.")
#raise Exception("I don't know what this is supposed to mean.")
#TODO fix this
#time.sleep(1)
# TODO Raise as exception
#print("Unknown phrase. It's neither idea nor cluster")
continue
if deduction.type == DEDUCTION_TYPE.CLUSTER:
print("Cluster")
deduction.object.register_as_idea(idea_type=IDEA_TYPE.NEW, idea_direction=IDEA_DIRECTION.REFLECT, inner_memory = request)
if deduction.type == DEDUCTION_TYPE.IDEA:
print(deduction.object.idea_type)
print("Idea")
# TODO raise exception - cause it's already an idea
# Sort of "i know"
# TODO And that's it
# External motive should not trigger immediately
# TODO just somehow "freeze" initial message in idea
# TODO check wether it's right moment
# Register as idea and process immediately
# Register as idea and set status of delayed
# Or register as idea and set status of denied
# Controller will clean it later
# TODO Check for duplicates or whatever
# TODO Probably not wery correct eay to handle this
# HARDCODE just for now it's active status
#cluster.register_as_idea()
#else:
# print("Cluster not found")
...
#run in thread
#act client like
if __name__ == '__main__':
v = Violla()
v.act()