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

@ -4,11 +4,12 @@ import wx
import wx.gizmos
import wx.propgrid as wxpg
ID_TEST = wx.NewId()
ID_DUPLICATE = wx.NewId()
ID_DUPLICATE_MODEL = wx.NewId()
ID_DELETE_MODEL = wx.NewId()
ID_PROCESS_MODEL = wx.NewId()
ID_TEST = wx.NewId()
ID_ADD_MODEL_ROOT = wx.NewId()
ID_ADD_MODEL_SELECTED = wx.NewId()
ID_DUPLICATE_MODEL = wx.NewId()
ID_DELETE_MODEL = wx.NewId()
ID_PROCESS_MODEL = wx.NewId()
class MyTreeListCtrl(wx.gizmos.TreeListCtrl):
def Refresh(self, erase, rect):
@ -23,7 +24,7 @@ class MainFrame (wx.Frame):
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))
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 = MyTreeListCtrl(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.AddColumn("Model name")
self.m_user_models.AddColumn("Status")
self.m_user_models.AddColumn("Progress")
self.m_user_models.AddColumn("Comment")
bSizer4.Add(self.m_user_models, 0, wx.ALL|wx.EXPAND, 1)
@ -59,6 +62,7 @@ class MainFrame (wx.Frame):
mbar = self.BuildMenu()
self.SetMenuBar(mbar)
self.BuildContextMenu()
self.SetSizer(bSizer3)
self.Layout()
@ -76,8 +80,14 @@ class MainFrame (wx.Frame):
menubar.Append(menu, '&File')
menu = wx.Menu()
menu.Append(ID_TEST, "&Test\tCtrl+U")
menu.Append(ID_DUPLICATE, "&Duplicate\tCtrl+D")
menu.Append(ID_TEST, "&Test\tCtrl+T")
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')
menu = wx.Menu()
@ -86,3 +96,11 @@ class MainFrame (wx.Frame):
menubar.Append(menu, '&Help')
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))

172
opal.py
View File

@ -20,6 +20,7 @@ import time
import datetime
import os
import threading
import re
#-----------------------------------------------------------------------------
# Главная форма
@ -29,6 +30,8 @@ class MainFrame(forms.MainFrame):
def __init__(self):
forms.MainFrame.__init__(self, None)
self.name_id = 1
s = server.LocalServer()
s.LoadModels()
models = s.GetModels()
@ -45,7 +48,14 @@ class MainFrame(forms.MainFrame):
self.OnParamChanged)
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_IDLE, self.OnIdle)
@ -62,45 +72,127 @@ class MainFrame(forms.MainFrame):
self.Destroy()
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:
um = self.m_user_models
cycle_count = 0
while True:
wx.MutexGuiEnter()
print 'cycle {:-8} '.format(cycle_count)
print 'cycle{:-8}'.format(cycle_count)
cycle_count += 1
item = um.GetRootItem()
while item.IsOk():
data = um.GetPyData(item)
if data:
jid = data[1]
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)
um.SetItemText(item, str(state[0]), 1)
um.SetItemText(item, '{}: {:%}'.format(t, state[1]), 2)
state = self.server.GetJobState(jid)
um.SetItemText(item, StateToStr(state[0]), 1)
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
item = um.GetNext(item)
wx.MutexGuiLeave()
time.sleep(0.1)
time.sleep(0.2)
except Exception, 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. загрузить спецификации модели
# 2. создать одну модель по умолчанию
model = project
um = self.m_user_models
root = um.AddRoot('Root')
data = task.DataDefinition(model)
child = um.AppendItem(root, 'Default')
jid = self.server.CreateJob()
um.SetPyData(child, [data, jid])
self.BuildSpecs(model)
um = self.m_user_models
um.DeleteAllItems()
um.AddRoot('Root')
self.AddModelToRoot(model)
return True # Project(model)
def SelectUserModel(self, model_def, jid):
@ -165,12 +257,41 @@ class MainFrame(forms.MainFrame):
data[param] = value
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
id = um.GetSelection()
data, jid = um.GetItemPyData(id)
item = um.GetSelection()
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):
um = self.m_user_models
@ -178,11 +299,18 @@ class MainFrame(forms.MainFrame):
title = um.GetItemText(id)
parent = um.GetItemParent(id)
md, jid = um.GetItemPyData(id)
child = um.AppendItem(parent, title + ' Copy')
child = um.AppendItem(parent, self.GenerateName(title))
jid = self.server.CreateJob()
um.SetPyData(child, [md.Copy(), jid])
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):
pass

View File

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

View File

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

View File

@ -1,13 +1,13 @@
{
"title": "Example task",
"author": "Anton Vakhrushev",
"meta": "av-example-task",
"meta": "av-example-task-version-00-10",
"models": {
"sintaylor": {
"title": "Simple model for example",
"title": "Simple model",
"author": "Anton Vakhrushev",
"date": "2012-03-08",
@ -31,10 +31,25 @@
"n": {
"type": "int",
"default": 10,
"default": 100,
"title": "Steps",
"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
return s
def answer(p):
def answer(p, c = ''):
return json.dumps({
"answer": "ok",
"value": p
"value": p,
"comment": c
})
def error(msg):
@ -61,7 +62,7 @@ def main():
textdata = raw_input()
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'))
sys.exit(1)
@ -76,9 +77,9 @@ def main():
while l <= r:
y = sin_taylor(l, d)
res.append([l, y])
write(answer(l / r))
write(answer(l / r, data[-1]['label']))
l += h
#time.sleep(0.1)
time.sleep(0.1)
write(result(res))