Work with specifications partly added

This commit is contained in:
anwinged 2012-04-23 07:02:06 +00:00
parent 42d7aa9573
commit d859399249
6 changed files with 212 additions and 40 deletions

View File

@ -5,7 +5,8 @@ import wx.gizmos
import wx.propgrid as wxpg import wx.propgrid as wxpg
ID_TEST = wx.NewId() ID_TEST = wx.NewId()
ID_DUPLICATE = wx.NewId() ID_ADD_MODEL_ROOT = wx.NewId()
ID_ADD_MODEL_SELECTED = wx.NewId()
ID_DUPLICATE_MODEL = wx.NewId() ID_DUPLICATE_MODEL = wx.NewId()
ID_DELETE_MODEL = wx.NewId() ID_DELETE_MODEL = wx.NewId()
ID_PROCESS_MODEL = wx.NewId() ID_PROCESS_MODEL = wx.NewId()
@ -23,7 +24,7 @@ class MainFrame (wx.Frame):
bSizer3 = wx.BoxSizer(wx.HORIZONTAL) bSizer3 = wx.BoxSizer(wx.HORIZONTAL)
self.m_specs = wx.TreeCtrl(self, style = wx.TR_DEFAULT_STYLE|wx.TR_HIDE_ROOT) self.m_specs = wx.TreeCtrl(self, style = wx.TR_DEFAULT_STYLE)
self.m_specs.SetMinSize(wx.Size(150,-1)) self.m_specs.SetMinSize(wx.Size(150,-1))
bSizer3.Add(self.m_specs, 0, wx.ALL|wx.EXPAND, 1) bSizer3.Add(self.m_specs, 0, wx.ALL|wx.EXPAND, 1)
@ -33,11 +34,13 @@ class MainFrame (wx.Frame):
self.m_user_models = wx.gizmos.TreeListCtrl(self, self.m_user_models = wx.gizmos.TreeListCtrl(self,
#self.m_user_models = MyTreeListCtrl(self, #self.m_user_models = MyTreeListCtrl(self,
#self.m_user_models = wx.TreeCtrl(self, #self.m_user_models = wx.TreeCtrl(self,
style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.TR_EDIT_LABELS | wx.TR_ROW_LINES) style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT
| wx.TR_EDIT_LABELS | wx.TR_ROW_LINES | wx.TR_MULTIPLE)
self.m_user_models.SetMinSize(wx.Size(-1, 200)) self.m_user_models.SetMinSize(wx.Size(-1, 200))
self.m_user_models.AddColumn("Model name") self.m_user_models.AddColumn("Model name")
self.m_user_models.AddColumn("Status") self.m_user_models.AddColumn("Status")
self.m_user_models.AddColumn("Progress") self.m_user_models.AddColumn("Progress")
self.m_user_models.AddColumn("Comment")
bSizer4.Add(self.m_user_models, 0, wx.ALL|wx.EXPAND, 1) bSizer4.Add(self.m_user_models, 0, wx.ALL|wx.EXPAND, 1)
@ -59,6 +62,7 @@ class MainFrame (wx.Frame):
mbar = self.BuildMenu() mbar = self.BuildMenu()
self.SetMenuBar(mbar) self.SetMenuBar(mbar)
self.BuildContextMenu()
self.SetSizer(bSizer3) self.SetSizer(bSizer3)
self.Layout() self.Layout()
@ -76,8 +80,14 @@ class MainFrame (wx.Frame):
menubar.Append(menu, '&File') menubar.Append(menu, '&File')
menu = wx.Menu() menu = wx.Menu()
menu.Append(ID_TEST, "&Test\tCtrl+U") menu.Append(ID_TEST, "&Test\tCtrl+T")
menu.Append(ID_DUPLICATE, "&Duplicate\tCtrl+D") menu.Append(ID_ADD_MODEL_ROOT, 'Add model to root')
menu.Append(ID_ADD_MODEL_SELECTED, 'Append model to selected')
#menu.AppendSeparator()
menu.Append(ID_DUPLICATE_MODEL, "&Duplicate\tCtrl+D")
menu.Append(ID_DELETE_MODEL, 'Delete')
menu.AppendSeparator()
menu.Append(ID_PROCESS_MODEL, 'Process\tCtrl+R')
menubar.Append(menu, '&Model') menubar.Append(menu, '&Model')
menu = wx.Menu() menu = wx.Menu()
@ -86,3 +96,11 @@ class MainFrame (wx.Frame):
menubar.Append(menu, '&Help') menubar.Append(menu, '&Help')
return menubar return menubar
def BuildContextMenu(self):
menu = wx.Menu()
menu.Append(ID_ADD_MODEL_ROOT, 'Add model to root')
menu.Append(ID_ADD_MODEL_SELECTED, 'Add model to selected')
self.m_specs.Bind(wx.EVT_CONTEXT_MENU,
lambda x: self.m_specs.PopupMenu(menu))

168
opal.py
View File

@ -20,6 +20,7 @@ import time
import datetime import datetime
import os import os
import threading import threading
import re
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# Главная форма # Главная форма
@ -29,6 +30,8 @@ class MainFrame(forms.MainFrame):
def __init__(self): def __init__(self):
forms.MainFrame.__init__(self, None) forms.MainFrame.__init__(self, None)
self.name_id = 1
s = server.LocalServer() s = server.LocalServer()
s.LoadModels() s.LoadModels()
models = s.GetModels() models = s.GetModels()
@ -45,7 +48,14 @@ class MainFrame(forms.MainFrame):
self.OnParamChanged) self.OnParamChanged)
self.Bind(wx.EVT_MENU, self.OnTest, id = forms.ID_TEST) self.Bind(wx.EVT_MENU, self.OnTest, id = forms.ID_TEST)
self.Bind(wx.EVT_MENU, self.OnDuplicate, id = forms.ID_DUPLICATE) self.Bind(wx.EVT_MENU, self.OnAddModelToRoot,
id = forms.ID_ADD_MODEL_ROOT)
self.Bind(wx.EVT_MENU, self.OnAddModelToSelected,
id = forms.ID_ADD_MODEL_SELECTED)
self.Bind(wx.EVT_MENU, self.OnDuplicate,
id = forms.ID_DUPLICATE_MODEL)
self.Bind(wx.EVT_MENU, self.OnModelProcess,
id = forms.ID_PROCESS_MODEL)
self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(wx.EVT_CLOSE, self.OnClose)
self.Bind(wx.EVT_IDLE, self.OnIdle) self.Bind(wx.EVT_IDLE, self.OnIdle)
@ -62,6 +72,19 @@ class MainFrame(forms.MainFrame):
self.Destroy() self.Destroy()
def Overseer(self): def Overseer(self):
def StateToStr(state):
if state == server.JOB_READY:
return 'Ready'
elif state == server.JOB_RUNNING:
return 'Running'
elif state == server.JOB_STOPPED:
return 'Stopped'
elif state == server.JOB_COMPLETED:
return 'Completed'
else:
return 'Unknown'
try: try:
um = self.m_user_models um = self.m_user_models
cycle_count = 0 cycle_count = 0
@ -74,33 +97,102 @@ class MainFrame(forms.MainFrame):
data = um.GetPyData(item) data = um.GetPyData(item)
if data: if data:
jid = data[1] jid = data[1]
if jid != None and self.server.IsJobChanged(jid): if jid != None and self.server.IsJobChanged(jid):
tid = self.server.GetJobTID(jid)
meta = self.server.GetTaskMeta(tid)
t = os.path.basename(meta['exec'])
state = self.server.GetJobState(jid) state = self.server.GetJobState(jid)
um.SetItemText(item, str(state[0]), 1) um.SetItemText(item, StateToStr(state[0]), 1)
um.SetItemText(item, '{}: {:%}'.format(t, state[1]), 2) p = state[1]
p = 'Unknown' if p < 0 else '{:%}'.format(p)
um.SetItemText(item, p, 2)
um.SetItemText(item, state[2], 3)
print jid, state print jid, state
item = um.GetNext(item) item = um.GetNext(item)
wx.MutexGuiLeave() wx.MutexGuiLeave()
time.sleep(0.1) time.sleep(0.2)
except Exception, e: except Exception, e:
print 'Error in overseer: ', e print 'Error in overseer: ', e
def NewProject(self, project): def CheckName(self, name):
"""
Проверяет имя на уникальность в иерархии пользовательских моделей.
Возвращает True, если имя уникально, иначе False.
"""
um = self.m_user_models
item = um.GetRootItem()
while item.IsOk():
item_name = um.GetItemText(item)
if item_name == name:
return False
item = um.GetNext(item)
return True
def GenerateName(self, name):
"""
На основе переданного имени генерирует новое имя модели таким образом,
чтобы оно осталось уникальным в рамках существующей иерархии моделей.
"""
m = re.match(r'(.+)\s+\d*', name)
basename = m.group(1) if m else name
while True:
name = basename + ' ' + str(self.name_id)
if self.CheckName(name):
return name
self.name_id += 1
def BuildSpecs(self, model):
"""
Выстраивает иерархию спецификаций для выбранной модели
"""
def DoItem(item, model):
sp.SetPyData(item, model)
for spec in model.GetSpecs():
child = sp.AppendItem(item, spec.GetTitle())
DoItem(child, spec)
sp = self.m_specs
sp.DeleteAllItems()
root = sp.AddRoot(model.GetTitle())
DoItem(root, model)
sp.ExpandAll()
sp.SortChildren(root)
def AddModelToRoot(self, model):
"""
Добавляет пользовательскую модель или спецификацию
в корень дерева моделей.
"""
ms = []
while model:
ms.append(model)
model = model.GetParent()
ms.reverse()
# ms: [root-model, child, child-of-child1, ..., model]
um = self.m_user_models
item = um.GetRootItem()
defparent = None
for m in ms:
name = self.GenerateName(m.GetTitle())
item = um.AppendItem(item, name)
data = task.DataDefinition(m, defparent)
defparent = data
jid = self.server.CreateJob() if m.IsExecutable() else None
um.SetPyData(item, [data, jid])
def NewProject(self, model):
# 1. загрузить спецификации модели # 1. загрузить спецификации модели
# 2. создать одну модель по умолчанию # 2. создать одну модель по умолчанию
model = project
um = self.m_user_models
root = um.AddRoot('Root')
data = task.DataDefinition(model)
child = um.AppendItem(root, 'Default') self.BuildSpecs(model)
jid = self.server.CreateJob()
um.SetPyData(child, [data, jid]) um = self.m_user_models
um.DeleteAllItems()
um.AddRoot('Root')
self.AddModelToRoot(model)
return True # Project(model)
def SelectUserModel(self, model_def, jid): def SelectUserModel(self, model_def, jid):
@ -165,12 +257,41 @@ class MainFrame(forms.MainFrame):
data[param] = value data[param] = value
def OnTest(self, event): def OnTest(self, event):
um = self.m_user_models
def OnAddModelToRoot(self, event):
item = self.m_specs.GetSelection()
if not item.IsOk():
return
print self.m_specs.GetItemText(item)
model = self.m_specs.GetPyData(item)
self.AddModelToRoot(model)
def OnAddModelToSelected(self, event):
"""
Добавляет пользовательскую спецификацию к указанной модели или в уже
существующую иерархию спецификаций.
"""
item = self.m_specs.GetSelection()
if not item.IsOk():
return
model = self.m_specs.GetPyData(item)
um = self.m_user_models um = self.m_user_models
id = um.GetSelection() item = um.GetSelection()
data, jid = um.GetItemPyData(id) if not item.IsOk():
return
self.server.LaunchJob(jid, data) pmdef, _ = um.GetPyData(item)
if pmdef.DD == model.parent:
modeldef = task.DataDefinition(model, pmdef)
name = self.GenerateName(model.GetTitle())
item = um.AppendItem(item, name)
jid = self.server.CreateJob() if model.IsExecutable() else None
um.SetPyData(item, [modeldef, jid])
else:
wx.MessageBox('It\'s impossible to append model', 'Error')
def OnDuplicate(self, event): def OnDuplicate(self, event):
um = self.m_user_models um = self.m_user_models
@ -178,11 +299,18 @@ class MainFrame(forms.MainFrame):
title = um.GetItemText(id) title = um.GetItemText(id)
parent = um.GetItemParent(id) parent = um.GetItemParent(id)
md, jid = um.GetItemPyData(id) md, jid = um.GetItemPyData(id)
child = um.AppendItem(parent, title + ' Copy')
child = um.AppendItem(parent, self.GenerateName(title))
jid = self.server.CreateJob() jid = self.server.CreateJob()
um.SetPyData(child, [md.Copy(), jid]) um.SetPyData(child, [md.Copy(), jid])
self.SetStatusText('Copy for "{}" created'.format(title), 0) self.SetStatusText('Copy for "{}" created'.format(title), 0)
def OnModelProcess(self, event):
um = self.m_user_models
for i in um.GetSelections():
data, jid = um.GetItemPyData(i)
self.server.LaunchJob(jid, data)
def OnIdle(self, event): def OnIdle(self, event):
pass pass

View File

@ -30,6 +30,9 @@ def WriteToLog(msg):
#self.log.write(msg + '\n') #self.log.write(msg + '\n')
print msg print msg
class JIDError(Exception):
def __str__(self):
return 'Invalid jid'
class LocalServer: class LocalServer:
def __init__(self, conf = 'tasks.conf', workers = 2): def __init__(self, conf = 'tasks.conf', workers = 2):
@ -127,6 +130,9 @@ class LocalServer:
def GetJobsCount(self): def GetJobsCount(self):
return len(self.jobs) return len(self.jobs)
#def CheckJID(self, func):
# def
def GetJobState(self, jid): def GetJobState(self, jid):
job = self.jobs.get(jid) job = self.jobs.get(jid)
if job != None: if job != None:
@ -302,6 +308,7 @@ class Job:
self.tid = tid self.tid = tid
self.datadump = datadump self.datadump = datadump
self.state = JOB_READY self.state = JOB_READY
self.percent = -1.0
self.ChangeState() self.ChangeState()
def Stop(self): def Stop(self):

View File

@ -76,7 +76,10 @@ class DataDescription:
def GetId(self): def GetId(self):
return None return None
def GetSpecifications(self): def GetParent(self):
return self.parent
def GetSpecs(self):
return self.specs return self.specs
def IsExecutable(self): def IsExecutable(self):

View File

@ -1,13 +1,13 @@
{ {
"title": "Example task", "title": "Example task",
"author": "Anton Vakhrushev", "author": "Anton Vakhrushev",
"meta": "av-example-task", "meta": "av-example-task-version-00-10",
"models": { "models": {
"sintaylor": { "sintaylor": {
"title": "Simple model for example", "title": "Simple model",
"author": "Anton Vakhrushev", "author": "Anton Vakhrushev",
"date": "2012-03-08", "date": "2012-03-08",
@ -31,10 +31,25 @@
"n": { "n": {
"type": "int", "type": "int",
"default": 10, "default": 100,
"title": "Steps", "title": "Steps",
"comment": "Number of steps for algorithm" "comment": "Number of steps for algorithm"
} }
},
"spec": {
"left": {
"title": "Left"
},
"right": {
"title": "Right"
},
"trapezium": {
"title": "Trapezium"
}
} }
} }
} }

View File

@ -26,10 +26,11 @@ def sin_taylor(x, n):
e *= -1 e *= -1
return s return s
def answer(p): def answer(p, c = ''):
return json.dumps({ return json.dumps({
"answer": "ok", "answer": "ok",
"value": p "value": p,
"comment": c
}) })
def error(msg): def error(msg):
@ -61,7 +62,7 @@ def main():
textdata = raw_input() textdata = raw_input()
data = json.loads(textdata) data = json.loads(textdata)
if not len(data) and data[0]['label'] != 'sintaylor': if not len(data) or data[-1]['label'] != 'sintaylor':
write(error('Unknown model')) write(error('Unknown model'))
sys.exit(1) sys.exit(1)
@ -76,9 +77,9 @@ def main():
while l <= r: while l <= r:
y = sin_taylor(l, d) y = sin_taylor(l, d)
res.append([l, y]) res.append([l, y])
write(answer(l / r)) write(answer(l / r, data[-1]['label']))
l += h l += h
#time.sleep(0.1) time.sleep(0.1)
write(result(res)) write(result(res))