fix: missing files in first version
This commit is contained in:
parent
966d4819b4
commit
ce32292935
2
.gitignore
vendored
2
.gitignore
vendored
@ -14,8 +14,6 @@ dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
|
37
lib/audio_plugin.py
Normal file
37
lib/audio_plugin.py
Normal file
@ -0,0 +1,37 @@
|
||||
from debuggable import Debuggable
|
||||
from random import randint, choice
|
||||
from math import sqrt
|
||||
from datetime import datetime, timedelta
|
||||
from planning import Planning
|
||||
from schedule import Schedule
|
||||
|
||||
|
||||
class audioPlugin(Debuggable):
|
||||
"""Planner for general slots allocations"""
|
||||
|
||||
name = "audioPlugin"
|
||||
|
||||
def __init__(self):
|
||||
super(MyPlugin, self).__init__()
|
||||
|
||||
def sensor_base(self, blackboard):
|
||||
# redis.get("redilysis.key")
|
||||
# blackboard["audio_analysis"] = redilysis
|
||||
pass
|
||||
|
||||
def planner_base(self, blackboard, planning: Planning):
|
||||
|
||||
interesting_list = []
|
||||
for schedule in planning.schedules:
|
||||
start_at = schedule.start_at
|
||||
now = datetime.now()
|
||||
if (now - start_at).total_seconds() < 3 :
|
||||
continue
|
||||
interesting_list.append(schedule)
|
||||
|
||||
mood = get_mood_from_audio()
|
||||
for schedule in interesting_list:
|
||||
schedule.content["mood"] = mood
|
||||
|
||||
|
||||
|
5
lib/blackboard.py
Normal file
5
lib/blackboard.py
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
class Blackboard(object):
|
||||
|
||||
def __init__( self ):
|
||||
pass
|
14
lib/debuggable.py
Normal file
14
lib/debuggable.py
Normal file
@ -0,0 +1,14 @@
|
||||
import debugger
|
||||
# from var_dump import var_dump
|
||||
class Debuggable(object):
|
||||
|
||||
def __init__(self):
|
||||
self._debugger = debugger.instance
|
||||
|
||||
def debug(self, tags, msg):
|
||||
if not self._debugger:
|
||||
print(self, " missing debugger")
|
||||
self._debugger.debug(tags, msg)
|
||||
|
||||
# def var_dump(self,var):
|
||||
# return var_dump(var)
|
176
lib/debugger.py
Normal file
176
lib/debugger.py
Normal file
@ -0,0 +1,176 @@
|
||||
import asyncio
|
||||
import inspect
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
|
||||
instance = object()
|
||||
|
||||
def init():
|
||||
global instance
|
||||
instance = Debugger()
|
||||
|
||||
|
||||
class Debugger(object):
|
||||
"""A socket based debugger """
|
||||
|
||||
""" a list of tags to debug """
|
||||
tags = {}
|
||||
knownTags = []
|
||||
selectedTags = []
|
||||
|
||||
# subscribed = {}
|
||||
|
||||
def __init__(self):
|
||||
self.socket_file = '/tmp/._my_debug_socket'
|
||||
print('\nStarting the debugger on socket file \'{}\'.\nRequest help with \n echo help | nc -U {}\'\n '.format(
|
||||
self.socket_file,
|
||||
self.socket_file
|
||||
))
|
||||
|
||||
def cleanup(self):
|
||||
if os.path.exists(self.socket_file):
|
||||
os.remove(self.socket_file)
|
||||
|
||||
|
||||
def add_known_tags(self, tags):
|
||||
if isinstance(tags, str):
|
||||
tags = [tags]
|
||||
self.tags = set(list(self.tags) + tags)
|
||||
|
||||
def add_selected_tags(self, tags):
|
||||
if isinstance(tags, str):
|
||||
tags = [tags]
|
||||
self.selectedTags = set(list(self.selectedTags)).union(set(tags))
|
||||
|
||||
def debug(self, tags, message):
|
||||
if isinstance(tags, str):
|
||||
tags = [tags]
|
||||
self.add_known_tags(tags)
|
||||
if len(set(tags) & set(self.selectedTags)):
|
||||
print(message)
|
||||
# else :
|
||||
# print( "skipping message %s vs. %s" % (self.selectedTags, tags ))
|
||||
|
||||
async def server(self):
|
||||
|
||||
async def handler(reader, writer):
|
||||
data = await reader.read(100)
|
||||
if data:
|
||||
msg = ""
|
||||
req = data.split()
|
||||
if not len(req):
|
||||
msg = "Error: empty request"
|
||||
else:
|
||||
cmd = "cmd_" + str(req.pop(0), "utf-8")
|
||||
print("Debugger server command: %s" % (cmd))
|
||||
if not hasattr(self, cmd):
|
||||
msg = "Error: Invalid command '%s'" % (cmd)
|
||||
else:
|
||||
method = getattr(self, cmd)
|
||||
if not callable(method):
|
||||
msg = "Error: Called a property"
|
||||
else:
|
||||
try:
|
||||
req = [str(i, 'utf-8') for i in req]
|
||||
msg = method(req)
|
||||
except Exception as e:
|
||||
msg = "Error : %s " % (e)
|
||||
print("Response:\n%s" % (msg))
|
||||
writer.write(bytes(msg, "utf-8"))
|
||||
await writer.drain()
|
||||
writer.close()
|
||||
|
||||
self.cleanup()
|
||||
return await asyncio.start_unix_server(handler, path=self.socket_file)
|
||||
|
||||
def cmd_help(self, params):
|
||||
"""
|
||||
request general help
|
||||
"""
|
||||
members = inspect.getmembers(self)
|
||||
out = []
|
||||
for name, obj in members:
|
||||
if not re.match("^cmd_", name):
|
||||
continue
|
||||
out.append(
|
||||
"- " + re.sub("^cmd_(.*)", lambda m: m.group(1), name) + (str(obj.__doc__) if obj.__doc__ else ""))
|
||||
|
||||
return "\n".join(out) + "\n"
|
||||
|
||||
def cmd_list_tags(self, params):
|
||||
"""
|
||||
List available debug tags
|
||||
"""
|
||||
msg = ""
|
||||
if not len(self.tags):
|
||||
msg += "No tags yet\n"
|
||||
else:
|
||||
msg += "Tags:"
|
||||
for flag in sorted(self.tags):
|
||||
msg += "\n - %s" % (flag)
|
||||
msg += "\n"
|
||||
return msg
|
||||
|
||||
def cmd_add_tags(self, params):
|
||||
"""
|
||||
Add a debug tag
|
||||
"""
|
||||
msg = ""
|
||||
if not len(params):
|
||||
msg = "No flag provided"
|
||||
else:
|
||||
for flag in params:
|
||||
if flag in self.selectedTags:
|
||||
msg += "Noop: flag '%s' already added" % (flag)
|
||||
else:
|
||||
self.add_selected_tags([flag])
|
||||
msg += "Added flag '%s'" % (flag)
|
||||
return msg
|
||||
|
||||
def cmd_del_tags(self, params):
|
||||
"""
|
||||
Removes a tag
|
||||
"""
|
||||
msg = ""
|
||||
if not len(params):
|
||||
msg = "No flag provided"
|
||||
else:
|
||||
for flag in params:
|
||||
if flag not in self.selectedTags:
|
||||
msg += "Noop: flag '%s' not added" % (flag)
|
||||
else:
|
||||
self.selectedTags.remove(flag)
|
||||
msg += "Removed flag '%s'" % (flag)
|
||||
return msg
|
||||
|
||||
# def cmd_list_objs(self, params):
|
||||
# """
|
||||
# List available objects
|
||||
# """
|
||||
# if not len(self.subscribed ):
|
||||
# msg += "No subscribed object yet\n"
|
||||
# else:
|
||||
# msg += "Subscribed objects:"
|
||||
# for i, (oid, obj) in enumerate(self.subscribed.items()) :
|
||||
# msg+="\n - %s\t%s" % (oid,obj)
|
||||
#
|
||||
# return "\n".msg
|
||||
#
|
||||
#
|
||||
# def cmd_add_objs(self, params):
|
||||
# """
|
||||
# Debug a precise object
|
||||
# """
|
||||
# oid = params[0]
|
||||
# msg = "Unknown error"
|
||||
# if not self.subscribed[oid]:
|
||||
#
|
||||
# msg = "No such object"
|
||||
# else :
|
||||
# obj = self.subscribed[oid]
|
||||
# msg = obj.debugSelf()
|
||||
# return msg
|
||||
|
||||
# def subscribe( self, oid, obj ):
|
||||
# self.subscribed[ oid ] = obj
|
73
lib/director.py
Normal file
73
lib/director.py
Normal file
@ -0,0 +1,73 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
|
||||
import asyncio
|
||||
import inspect
|
||||
import re
|
||||
|
||||
from debuggable import Debuggable
|
||||
from plan import Plan
|
||||
from blackboard import Blackboard
|
||||
from schedule import Schedule
|
||||
from planning import Planning
|
||||
|
||||
|
||||
class Director(Debuggable):
|
||||
|
||||
def __init__(self, debug_tags=[]):
|
||||
super(Director, self).__init__()
|
||||
if len(debug_tags):
|
||||
self._debugger.add_selected_tags(debug_tags)
|
||||
|
||||
self.plugins = {}
|
||||
self.sensors = []
|
||||
self.planners = []
|
||||
self.communicators = []
|
||||
self.blackboard = {} # Blackboard()
|
||||
self.planning = Planning()
|
||||
|
||||
async def tick(self):
|
||||
self.on_perceive()
|
||||
self.on_plan()
|
||||
self.on_communicate()
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
def on_perceive(self):
|
||||
"""Sensors are required to update the blackboard
|
||||
"""
|
||||
# Pass the World State to all sensors
|
||||
for obj, meth in self.sensors:
|
||||
getattr(self.plugins[obj], meth)(blackboard=self.blackboard)
|
||||
|
||||
def on_plan(self):
|
||||
"""Planifiers are called
|
||||
"""
|
||||
for obj, meth in self.planners:
|
||||
getattr(self.plugins[obj], meth)(blackboard=self.blackboard, planning=self.planning)
|
||||
|
||||
def on_communicate(self):
|
||||
"""Communicators are called
|
||||
"""
|
||||
for obj, meth in self.communicators:
|
||||
getattr(self.plugins[obj], meth)(planning=self.planning)
|
||||
|
||||
async def run(self):
|
||||
while 1:
|
||||
await self.tick()
|
||||
|
||||
def add_plugin(self, plugin):
|
||||
if not hasattr(plugin, "name"):
|
||||
raise Exception("No property 'name' in plugin '{}'".format(plugin))
|
||||
plugin_name = plugin.name
|
||||
self.plugins[plugin_name] = plugin
|
||||
for method_name, prop in inspect.getmembers(plugin):
|
||||
if re.match("^(sensor.*)", method_name):
|
||||
self.sensors.append((plugin_name, method_name))
|
||||
self.debug("config", "Added sensor {}::{}".format(plugin_name, method_name))
|
||||
elif re.match("^(planner.*)", method_name):
|
||||
self.planners.append((plugin_name, method_name))
|
||||
self.debug("config", "Added planner {}::{}".format(plugin_name, method_name))
|
||||
elif re.match("^(communicator.*)", method_name):
|
||||
self.communicators.append((plugin_name, method_name))
|
||||
self.debug("config", "Added communicator {}::{}".format(plugin_name, method_name))
|
121
lib/my_plugin.py
Normal file
121
lib/my_plugin.py
Normal file
@ -0,0 +1,121 @@
|
||||
from debuggable import Debuggable
|
||||
from random import randint, choice
|
||||
from math import sqrt
|
||||
from datetime import datetime, timedelta
|
||||
from planning import Planning
|
||||
from schedule import Schedule
|
||||
|
||||
def gen(N, n):
|
||||
""" returns a list of integer numbers between 1 and n with exhaustion level N """
|
||||
res = []
|
||||
i = 0
|
||||
while N > 1:
|
||||
r = randint(1, n)
|
||||
N /= r
|
||||
res.append(r)
|
||||
i += 1
|
||||
return res
|
||||
|
||||
|
||||
def abba(lst, item):
|
||||
return [item, *lst, item]
|
||||
|
||||
|
||||
def abab(lst, item):
|
||||
return [item, *lst, item, *lst]
|
||||
|
||||
|
||||
def baa(lst, item):
|
||||
return [*lst, item, item]
|
||||
|
||||
|
||||
def ab(lst, item):
|
||||
return [item, *lst]
|
||||
|
||||
|
||||
def ba(lst, item):
|
||||
return [*lst, item]
|
||||
|
||||
|
||||
def struct(lst):
|
||||
fnList = ['abba', 'abab', 'baa', 'ab', 'ba']
|
||||
ret = []
|
||||
for i, w in enumerate(lst):
|
||||
fn_name = choice(fnList)
|
||||
fn = globals().copy().get(fn_name)
|
||||
ret = fn(ret, {'id': i, 'weight': w})
|
||||
return ret
|
||||
|
||||
|
||||
class MyPlugin(Debuggable):
|
||||
"""Planner for general slots allocations"""
|
||||
|
||||
name = "myPlugin"
|
||||
|
||||
def __init__(self):
|
||||
super(MyPlugin, self).__init__()
|
||||
self.updated = False
|
||||
|
||||
def sensor_base(self, blackboard):
|
||||
pass
|
||||
|
||||
def communicator_base(self, planning):
|
||||
if self.updated:
|
||||
self.updated = False
|
||||
self.debug("my_plugin_schedules", "Rescheduling at {}.".format(datetime.now().isoformat()))
|
||||
for schedule in planning.schedules:
|
||||
self.debug("my_plugin_schedules", schedule.to_string())
|
||||
|
||||
def planner_base(self, blackboard, planning: Planning):
|
||||
"""
|
||||
duration = 5
|
||||
L = [4, 2, 2]
|
||||
C = [{2: 3}, {1: 2}, {0: 4}, {0: 4}, {2: 3}]
|
||||
where each item of C is an {pattern_id: weight}
|
||||
duration of a stitch = 1 / sqrt(weight)
|
||||
R = [ 0.57, 0.7, 0.5, 0.5, 0.57]
|
||||
Sum of duration weights = 2.84
|
||||
each stitch lasts for a fraction of the total length
|
||||
comp = [{2: [3, 1.0]}, {1: [2, 1.23]}, {0: [4, 0.88]}, {0: [4, 0.88]}, {2: [3, 1.0]}]
|
||||
|
||||
"""
|
||||
last_schedule: Schedule = planning.get_last_schedule()
|
||||
|
||||
if last_schedule:
|
||||
self.debug("my_plugin_last_schedule","last_schedule end at {}".format(last_schedule.end_at.isoformat()))
|
||||
start_at_base = last_schedule.end_at
|
||||
if start_at_base > datetime.now():
|
||||
self.debug("my_plugin_skip","skip")
|
||||
return
|
||||
else:
|
||||
start_at_base = datetime.now()
|
||||
|
||||
duration = 10
|
||||
L = gen(randint(12, 20), randint(3, 5))
|
||||
C = struct(L)
|
||||
R = []
|
||||
Rsum = 0
|
||||
Ret = []
|
||||
for i in C:
|
||||
R.append(1 / sqrt(i['weight']))
|
||||
Rsum = sum(R)
|
||||
for i, j in enumerate(C):
|
||||
C[i]['duration'] = R[i] * duration / Rsum
|
||||
|
||||
# [{'id': 1, 'weight': 4, 'duration': 0.11670090144936807}, {'id': 0, 'weight': 1, 'duration': 0.23340180289873613}, {'id': 0, 'weight': 1, 'duration': 0.23340180289873613}, {'id': 1, 'weight': 4, 'duration': 0.11670090144936807}, {'id': 2, 'weight': 2, 'duration': 0.1650399975708623}, {'id': 3, 'weight': 3, 'duration': 0.1347545937329293}]
|
||||
|
||||
schedules = []
|
||||
elapsed: float = 0
|
||||
for item in C:
|
||||
duration = item["duration"]
|
||||
start_at = start_at_base + timedelta( seconds=elapsed)
|
||||
schedules.append(Schedule(
|
||||
start_at=start_at,
|
||||
end_at=start_at + timedelta( seconds=duration),
|
||||
name=item['id'],
|
||||
content=item
|
||||
))
|
||||
elapsed += duration
|
||||
|
||||
planning.add(schedules)
|
||||
self.updated = True
|
5
lib/plan.py
Normal file
5
lib/plan.py
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
class Plan( object ):
|
||||
|
||||
def __init__( self ):
|
||||
pass
|
65
lib/planner_content.py
Normal file
65
lib/planner_content.py
Normal file
@ -0,0 +1,65 @@
|
||||
from debuggable import Debuggable
|
||||
|
||||
|
||||
class Pattern(Debuggable):
|
||||
def __init__(self, arg):
|
||||
super(Pattern, self).__init__()
|
||||
for i in arg:
|
||||
setattr(self, i, arg[i])
|
||||
|
||||
class ContentPlanner(Debuggable):
|
||||
"""Planner for slots content allocation """
|
||||
|
||||
# def __init__(self):
|
||||
|
||||
# the patterns memory
|
||||
# patternsList = []
|
||||
|
||||
# define the possible schedule contents
|
||||
|
||||
# min_weight
|
||||
# max_weight
|
||||
# score_first
|
||||
# score_same
|
||||
# score_different
|
||||
# score_final
|
||||
|
||||
|
||||
|
||||
def plan(self,state, memory, plan):
|
||||
|
||||
# Read previous actions from memory
|
||||
actionsMemory = memory.getActionsMemory()
|
||||
finished = False
|
||||
energy = state.energy()
|
||||
|
||||
finished = False
|
||||
while not finished and energy > 0:
|
||||
|
||||
actionsWeightSum = sum(actionsMemory.values()) if actionsMemory else 1
|
||||
print(__file__,actionsMemory, actionsWeightSum, self.weightTable)
|
||||
|
||||
for action in self.actions:
|
||||
if energy + action.energy < 0 :
|
||||
continue
|
||||
action_weight = ( (actionsWeightSum - actionsMemory[action.name] ) / actionsWeightSum ) if action.name in actionsMemory else 1
|
||||
print(__file__, action.name, actionsMemory,action.name in actionsMemory,action_weight)
|
||||
self.weightTable[action.name] = action_weight
|
||||
print( self.weightTable)
|
||||
|
||||
high_score = max(self.weightTable, key=self.weightTable.get)
|
||||
chosen_action = self.actions[self.actionsIndex[high_score]]
|
||||
|
||||
energy += chosen_action.energy
|
||||
plan.addAction( chosen_action )
|
||||
print ( energy, chosen_action.name )
|
||||
|
||||
if action.name in actionsMemory:
|
||||
actionsMemory[chosen_action.name] += 1
|
||||
else :
|
||||
actionsMemory[chosen_action.name] = 1
|
||||
if energy < 0:
|
||||
finished = True
|
||||
|
||||
|
||||
return plan
|
33
lib/schedule.py
Normal file
33
lib/schedule.py
Normal file
@ -0,0 +1,33 @@
|
||||
from debuggable import Debuggable
|
||||
from datetime import datetime, timedelta
|
||||
import json
|
||||
|
||||
class Schedule(Debuggable):
|
||||
start_at = datetime.now()
|
||||
end_at = datetime.now()
|
||||
content = {}
|
||||
name = "default"
|
||||
|
||||
def __init__(self, start_at=None, end_at=None, content={}, name=None):
|
||||
super(Schedule, self).__init__()
|
||||
self.start_at = start_at
|
||||
self.end_at = end_at
|
||||
self.content = content
|
||||
self.name = name
|
||||
self.debug("new_schedules","New schedule: {}".format(self.to_string()))
|
||||
|
||||
def elapsed(self):
|
||||
delta = datetime.now() - self.end_at
|
||||
if delta.total_seconds() > 0 :
|
||||
self.debug("schedule_elapsed_true","delta is {} for {}".format(delta, self.end_at.isoformat()))
|
||||
return True
|
||||
return False
|
||||
|
||||
def to_string(self):
|
||||
return json.dumps({
|
||||
"start_at": self.start_at.isoformat(),
|
||||
"end_at": self.end_at.isoformat(),
|
||||
"name": self.name,
|
||||
"content": self.content
|
||||
})
|
||||
|
50
lib/test.py
Normal file
50
lib/test.py
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
def gen( N, n ):
|
||||
res = []
|
||||
i = 0
|
||||
while N > 1:
|
||||
r = randint(1,n)
|
||||
N /= r
|
||||
res.append(r)
|
||||
i += 1
|
||||
return res
|
||||
|
||||
def abba( lst, item ):
|
||||
return [ item, *lst, item]
|
||||
|
||||
def abab( lst, item ):
|
||||
return [ item, *lst, item, *lst]
|
||||
|
||||
def baa( lst, item ):
|
||||
return [ *lst, item, item ]
|
||||
|
||||
def ab( lst, item ):
|
||||
return [ item, *lst ]
|
||||
|
||||
def ba( lst, item ):
|
||||
return [ *lst, item ]
|
||||
|
||||
def struct( lst ):
|
||||
fnList = ['abba','abab','baa','ab','ba']
|
||||
ret = []
|
||||
for i,v in enumerate(lst):
|
||||
fn_name = choice(fnList)
|
||||
fn = globals().copy().get(fn_name)
|
||||
ret = fn(ret,{i:v})
|
||||
return ret
|
||||
|
||||
|
||||
L = gen(randint(12,20),randint(3,5))
|
||||
C = struct(L)
|
||||
R = []
|
||||
Rsum = 0
|
||||
Ret = []
|
||||
for i in C :
|
||||
R.append( 1/ sqrt(sum(i.values()) ))
|
||||
Rsum = sum(R)
|
||||
for i,j in enumerate(C) :
|
||||
length = R[i] * duration / Rsum
|
||||
print(i,j,length)
|
||||
for id in j.keys():
|
||||
print(id)
|
||||
Ret.append( { id : [j[id],length]} )
|
Loading…
Reference in New Issue
Block a user