Code refactoring
This commit is contained in:
parent
d859399249
commit
20e9beaf69
74
forms.py
74
forms.py
@ -2,18 +2,40 @@
|
|||||||
|
|
||||||
import wx
|
import wx
|
||||||
import wx.gizmos
|
import wx.gizmos
|
||||||
|
import wx.grid
|
||||||
import wx.propgrid as wxpg
|
import wx.propgrid as wxpg
|
||||||
|
import wx.lib.plot as wxplot
|
||||||
|
|
||||||
ID_TEST = wx.NewId()
|
ID_TEST = wx.NewId()
|
||||||
ID_ADD_MODEL_ROOT = wx.NewId()
|
ID_ADD_MODEL_ROOT = wx.NewId()
|
||||||
ID_ADD_MODEL_SELECTED = wx.NewId()
|
ID_ADD_MODEL_SELECTED = wx.NewId()
|
||||||
ID_DUPLICATE_MODEL = wx.NewId()
|
ID_DUPLICATE_MODEL = wx.NewId()
|
||||||
|
ID_DUPLICATE_TREE = wx.NewId()
|
||||||
ID_DELETE_MODEL = wx.NewId()
|
ID_DELETE_MODEL = wx.NewId()
|
||||||
ID_PROCESS_MODEL = wx.NewId()
|
ID_PROCESS_MODEL = wx.NewId()
|
||||||
|
ID_SHOW_RESULT = wx.NewId()
|
||||||
|
ID_SHOW_PLOT = wx.NewId()
|
||||||
|
|
||||||
|
class TreeListCtrl(wx.gizmos.TreeListCtrl):
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return TreeListCtrlIterator(self)
|
||||||
|
|
||||||
|
class TreeListCtrlIterator:
|
||||||
|
def __init__(self, owner):
|
||||||
|
self.owner = owner
|
||||||
|
self.item = self.owner.GetRootItem()
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
if not self.item.IsOk():
|
||||||
|
raise StopIteration
|
||||||
|
item = self.item
|
||||||
|
self.item = self.owner.GetNext(self.item)
|
||||||
|
return item
|
||||||
|
|
||||||
class MyTreeListCtrl(wx.gizmos.TreeListCtrl):
|
|
||||||
def Refresh(self, erase, rect):
|
|
||||||
wx.gizmos.TreeListCtrl.Refresh(False, rect)
|
|
||||||
|
|
||||||
class MainFrame (wx.Frame):
|
class MainFrame (wx.Frame):
|
||||||
|
|
||||||
@ -31,9 +53,7 @@ class MainFrame (wx.Frame):
|
|||||||
|
|
||||||
bSizer4 = wx.BoxSizer(wx.VERTICAL)
|
bSizer4 = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
|
||||||
self.m_user_models = wx.gizmos.TreeListCtrl(self,
|
self.m_user_models = TreeListCtrl(self,
|
||||||
#self.m_user_models = MyTreeListCtrl(self,
|
|
||||||
#self.m_user_models = wx.TreeCtrl(self,
|
|
||||||
style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT
|
style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT
|
||||||
| wx.TR_EDIT_LABELS | wx.TR_ROW_LINES | wx.TR_MULTIPLE)
|
| 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))
|
||||||
@ -45,8 +65,7 @@ class MainFrame (wx.Frame):
|
|||||||
bSizer4.Add(self.m_user_models, 0, wx.ALL|wx.EXPAND, 1)
|
bSizer4.Add(self.m_user_models, 0, wx.ALL|wx.EXPAND, 1)
|
||||||
|
|
||||||
# WARNING: wxPython code generation isn't supported for this widget yet.
|
# WARNING: wxPython code generation isn't supported for this widget yet.
|
||||||
self.m_params = wxpg.PropertyGridManager(self,
|
self.m_params = wxpg.PropertyGridManager(self)
|
||||||
style = wxpg.PG_TOOLBAR)
|
|
||||||
self.m_params.AddPage('fp')
|
self.m_params.AddPage('fp')
|
||||||
bSizer4.Add(self.m_params, 1, wx.EXPAND |wx.ALL, 1)
|
bSizer4.Add(self.m_params, 1, wx.EXPAND |wx.ALL, 1)
|
||||||
|
|
||||||
@ -80,14 +99,18 @@ class MainFrame (wx.Frame):
|
|||||||
menubar.Append(menu, '&File')
|
menubar.Append(menu, '&File')
|
||||||
|
|
||||||
menu = wx.Menu()
|
menu = wx.Menu()
|
||||||
menu.Append(ID_TEST, "&Test\tCtrl+T")
|
menu.Append(ID_PROCESS_MODEL, 'Process\tCtrl+R')
|
||||||
|
menu.Append(ID_SHOW_RESULT, 'Show result\tCtrl+S')
|
||||||
|
menu.Append(ID_SHOW_PLOT, 'Show plot\tCtrl+G')
|
||||||
|
menu.AppendSeparator()
|
||||||
menu.Append(ID_ADD_MODEL_ROOT, 'Add model to root')
|
menu.Append(ID_ADD_MODEL_ROOT, 'Add model to root')
|
||||||
menu.Append(ID_ADD_MODEL_SELECTED, 'Append model to selected')
|
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.AppendSeparator()
|
||||||
menu.Append(ID_PROCESS_MODEL, 'Process\tCtrl+R')
|
menu.Append(ID_DUPLICATE_MODEL, "&Duplicate\tCtrl+D")
|
||||||
|
menu.Append(ID_DUPLICATE_TREE, "&Duplicate with subitems\tCtrl+Shift+D")
|
||||||
|
menu.Append(ID_DELETE_MODEL, 'Delete\tCtrl+E')
|
||||||
|
menu.AppendSeparator()
|
||||||
|
menu.Append(ID_TEST, "&Test\tCtrl+T")
|
||||||
menubar.Append(menu, '&Model')
|
menubar.Append(menu, '&Model')
|
||||||
|
|
||||||
menu = wx.Menu()
|
menu = wx.Menu()
|
||||||
@ -104,3 +127,28 @@ class MainFrame (wx.Frame):
|
|||||||
menu.Append(ID_ADD_MODEL_SELECTED, 'Add model to selected')
|
menu.Append(ID_ADD_MODEL_SELECTED, 'Add model to selected')
|
||||||
self.m_specs.Bind(wx.EVT_CONTEXT_MENU,
|
self.m_specs.Bind(wx.EVT_CONTEXT_MENU,
|
||||||
lambda x: self.m_specs.PopupMenu(menu))
|
lambda x: self.m_specs.PopupMenu(menu))
|
||||||
|
|
||||||
|
class ResultFrame(wx.Frame):
|
||||||
|
def __init__(self, parent, title):
|
||||||
|
wx.Frame.__init__ (self, parent, -1, title, size = wx.Size(600, 400))
|
||||||
|
|
||||||
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
|
||||||
|
self.scalar = wxpg.PropertyGridManager(self)
|
||||||
|
self.scalar.AddPage('fp')
|
||||||
|
|
||||||
|
self.table = wx.grid.Grid(self)
|
||||||
|
self.table.SetDefaultCellAlignment(wx.ALIGN_CENTER, wx.ALIGN_CENTER)
|
||||||
|
|
||||||
|
sizer.Add(self.scalar, 0, wx.EXPAND |wx.ALL, 1)
|
||||||
|
sizer.Add(self.table, 1, wx.EXPAND |wx.ALL, 1)
|
||||||
|
|
||||||
|
self.SetSizer(sizer)
|
||||||
|
self.Layout()
|
||||||
|
self.Centre(wx.BOTH)
|
||||||
|
|
||||||
|
class PlotFrame(wx.Frame):
|
||||||
|
def __init__(self, parent, title):
|
||||||
|
wx.Frame.__init__ (self, parent, -1, title, size = wx.Size(600, 400))
|
||||||
|
|
||||||
|
self.plot = wxplot.PlotCanvas(self)
|
247
opal.py
247
opal.py
@ -22,6 +22,25 @@ import os
|
|||||||
import threading
|
import threading
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
class ModelData:
|
||||||
|
def __init__(self, server, model, parent_data = None):
|
||||||
|
# если мы создаем новый набор данных из описания модели
|
||||||
|
if isinstance(model, task.DataDescription):
|
||||||
|
self.mdef = task.DataDefinition(model, parent_data)
|
||||||
|
self.jid = server.CreateJob() if model.IsExecutable() else None
|
||||||
|
# если мы создаем набор данных из другого набора данных
|
||||||
|
elif isinstance(model, ModelData):
|
||||||
|
self.mdef = model.mdef.Copy()
|
||||||
|
self.jid = server.CreateJob() if model.jid != None else None
|
||||||
|
else:
|
||||||
|
self.mdef = None
|
||||||
|
self.jid = None
|
||||||
|
|
||||||
|
self.res = None
|
||||||
|
|
||||||
|
class ItemError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
# Главная форма
|
# Главная форма
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
@ -47,21 +66,28 @@ class MainFrame(forms.MainFrame):
|
|||||||
self.m_params.Bind(wxpg.EVT_PG_CHANGED,
|
self.m_params.Bind(wxpg.EVT_PG_CHANGED,
|
||||||
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.OnAddModelToRoot,
|
self.Bind(wx.EVT_MENU, self.OnAddModelToRoot,
|
||||||
id = forms.ID_ADD_MODEL_ROOT)
|
id = forms.ID_ADD_MODEL_ROOT)
|
||||||
self.Bind(wx.EVT_MENU, self.OnAddModelToSelected,
|
self.Bind(wx.EVT_MENU, self.OnAddModelToSelected,
|
||||||
id = forms.ID_ADD_MODEL_SELECTED)
|
id = forms.ID_ADD_MODEL_SELECTED)
|
||||||
self.Bind(wx.EVT_MENU, self.OnDuplicate,
|
self.Bind(wx.EVT_MENU, self.OnDuplicate,
|
||||||
id = forms.ID_DUPLICATE_MODEL)
|
id = forms.ID_DUPLICATE_MODEL)
|
||||||
|
self.Bind(wx.EVT_MENU, self.OnDuplicateTree,
|
||||||
|
id = forms.ID_DUPLICATE_TREE)
|
||||||
|
self.Bind(wx.EVT_MENU, self.OnDeleteModel,
|
||||||
|
id = forms.ID_DELETE_MODEL)
|
||||||
self.Bind(wx.EVT_MENU, self.OnModelProcess,
|
self.Bind(wx.EVT_MENU, self.OnModelProcess,
|
||||||
id = forms.ID_PROCESS_MODEL)
|
id = forms.ID_PROCESS_MODEL)
|
||||||
|
self.Bind(wx.EVT_MENU, self.OnShowResult,
|
||||||
|
id = forms.ID_SHOW_RESULT)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
ov = threading.Thread(target = self.Overseer)
|
ov = threading.Thread(target = self.Overseer)
|
||||||
ov.daemon = 1
|
ov.daemon = True
|
||||||
ov.start()
|
ov.start()
|
||||||
|
|
||||||
self.NewProject(model)
|
self.NewProject(model)
|
||||||
@ -72,6 +98,12 @@ class MainFrame(forms.MainFrame):
|
|||||||
self.Destroy()
|
self.Destroy()
|
||||||
|
|
||||||
def Overseer(self):
|
def Overseer(self):
|
||||||
|
"""
|
||||||
|
Функция-надсмотрщик, которая периодически проверяет состояние
|
||||||
|
всех пользовательских моделей, в зависимости от этого изменяет
|
||||||
|
состояние окружения, выводит информацию, подгружает результаты
|
||||||
|
выполнения работ и др.
|
||||||
|
"""
|
||||||
|
|
||||||
def StateToStr(state):
|
def StateToStr(state):
|
||||||
if state == server.JOB_READY:
|
if state == server.JOB_READY:
|
||||||
@ -90,25 +122,26 @@ class MainFrame(forms.MainFrame):
|
|||||||
cycle_count = 0
|
cycle_count = 0
|
||||||
while True:
|
while True:
|
||||||
wx.MutexGuiEnter()
|
wx.MutexGuiEnter()
|
||||||
print 'cycle{:-8}'.format(cycle_count)
|
#print 'cycle{:-8}'.format(cycle_count)
|
||||||
cycle_count += 1
|
cycle_count += 1
|
||||||
item = um.GetRootItem()
|
# просматриваем всю иерархию моделей
|
||||||
while item.IsOk():
|
for item in um:
|
||||||
data = um.GetPyData(item)
|
data = um.GetPyData(item)
|
||||||
if data:
|
if not data:
|
||||||
jid = data[1]
|
continue
|
||||||
if jid != None and self.server.IsJobChanged(jid):
|
jid = data.jid
|
||||||
state = self.server.GetJobState(jid)
|
if jid != None and self.server.IsJobChanged(jid):
|
||||||
um.SetItemText(item, StateToStr(state[0]), 1)
|
state, percent, comment = self.server.GetJobState(jid)
|
||||||
p = state[1]
|
um.SetItemText(item, StateToStr(state), 1)
|
||||||
p = 'Unknown' if p < 0 else '{:%}'.format(p)
|
p = 'Unknown' if percent < 0 else '{:%}'.format(percent)
|
||||||
um.SetItemText(item, p, 2)
|
um.SetItemText(item, p, 2)
|
||||||
um.SetItemText(item, state[2], 3)
|
um.SetItemText(item, comment, 3)
|
||||||
print jid, state
|
print jid, (state, percent, comment)
|
||||||
|
if state == server.JOB_COMPLETED:
|
||||||
|
data.res = self.server.GetJobResult(jid)
|
||||||
|
|
||||||
item = um.GetNext(item)
|
|
||||||
wx.MutexGuiLeave()
|
wx.MutexGuiLeave()
|
||||||
time.sleep(0.2)
|
time.sleep(0.1)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print 'Error in overseer: ', e
|
print 'Error in overseer: ', e
|
||||||
|
|
||||||
@ -118,12 +151,10 @@ class MainFrame(forms.MainFrame):
|
|||||||
Возвращает True, если имя уникально, иначе False.
|
Возвращает True, если имя уникально, иначе False.
|
||||||
"""
|
"""
|
||||||
um = self.m_user_models
|
um = self.m_user_models
|
||||||
item = um.GetRootItem()
|
for item in um:
|
||||||
while item.IsOk():
|
|
||||||
item_name = um.GetItemText(item)
|
item_name = um.GetItemText(item)
|
||||||
if item_name == name:
|
if item_name == name:
|
||||||
return False
|
return False
|
||||||
item = um.GetNext(item)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def GenerateName(self, name):
|
def GenerateName(self, name):
|
||||||
@ -131,7 +162,7 @@ class MainFrame(forms.MainFrame):
|
|||||||
На основе переданного имени генерирует новое имя модели таким образом,
|
На основе переданного имени генерирует новое имя модели таким образом,
|
||||||
чтобы оно осталось уникальным в рамках существующей иерархии моделей.
|
чтобы оно осталось уникальным в рамках существующей иерархии моделей.
|
||||||
"""
|
"""
|
||||||
m = re.match(r'(.+)\s+\d*', name)
|
m = re.match(r'^(.+)\s+\d*$', name, re.UNICODE)
|
||||||
basename = m.group(1) if m else name
|
basename = m.group(1) if m else name
|
||||||
while True:
|
while True:
|
||||||
name = basename + ' ' + str(self.name_id)
|
name = basename + ' ' + str(self.name_id)
|
||||||
@ -172,13 +203,17 @@ class MainFrame(forms.MainFrame):
|
|||||||
um = self.m_user_models
|
um = self.m_user_models
|
||||||
item = um.GetRootItem()
|
item = um.GetRootItem()
|
||||||
defparent = None
|
defparent = None
|
||||||
for m in ms:
|
root = None
|
||||||
|
for i, m in enumerate(ms):
|
||||||
name = self.GenerateName(m.GetTitle())
|
name = self.GenerateName(m.GetTitle())
|
||||||
item = um.AppendItem(item, name)
|
item = um.AppendItem(item, name)
|
||||||
data = task.DataDefinition(m, defparent)
|
if not i:
|
||||||
defparent = data
|
root = item
|
||||||
jid = self.server.CreateJob() if m.IsExecutable() else None
|
data = ModelData(self.server, m, defparent)
|
||||||
um.SetPyData(item, [data, jid])
|
defparent = data.mdef
|
||||||
|
um.SetPyData(item, data)
|
||||||
|
if root:
|
||||||
|
um.Expand(root)
|
||||||
|
|
||||||
def NewProject(self, model):
|
def NewProject(self, model):
|
||||||
# 1. загрузить спецификации модели
|
# 1. загрузить спецификации модели
|
||||||
@ -194,7 +229,7 @@ class MainFrame(forms.MainFrame):
|
|||||||
|
|
||||||
return True # Project(model)
|
return True # Project(model)
|
||||||
|
|
||||||
def SelectUserModel(self, model_def, jid):
|
def SelectUserModel(self, model_def):
|
||||||
|
|
||||||
def SelectProperty(param_type):
|
def SelectProperty(param_type):
|
||||||
"""
|
"""
|
||||||
@ -220,23 +255,42 @@ class MainFrame(forms.MainFrame):
|
|||||||
msg = model_def.PackParams()
|
msg = model_def.PackParams()
|
||||||
pg = self.m_params
|
pg = self.m_params
|
||||||
pg.ClearPage(0)
|
pg.ClearPage(0)
|
||||||
#pg.Append(wxpg.PropertyCategory('Model properties'))
|
for label, value in model_def.params.iteritems():
|
||||||
for k, v in model_def.params.iteritems():
|
param = model_def.DD[label]
|
||||||
p = model_def.DD[k]
|
title = param.GetTitle() or label
|
||||||
title = p.GetTitle() or k
|
prop = SelectProperty(param.GetType())
|
||||||
prop = SelectProperty(p.GetType())
|
pid = pg.Append(prop(title, value = value))
|
||||||
pid = pg.Append(prop(title, value = v))
|
pg.SetPropertyClientData(pid, label)
|
||||||
pg.SetPropertyClientData(pid, k)
|
pg.SetPropertyHelpString(pid, param.GetComment())
|
||||||
pg.SetPropertyHelpString(pid, p.GetComment())
|
|
||||||
|
self.SetStatusText(model_def.PackParams(), 0)
|
||||||
|
|
||||||
|
def GetSelectedItem(self, source):
|
||||||
|
item = source.GetSelection()
|
||||||
|
if not item.IsOk():
|
||||||
|
raise ItemError('Invalid item')
|
||||||
|
return item
|
||||||
|
|
||||||
|
def GetSelectedData(self, source):
|
||||||
|
item = self.GetSelectedItem(source)
|
||||||
|
data = source.GetPyData(item)
|
||||||
|
if not data:
|
||||||
|
raise ItemError('Empty data')
|
||||||
|
return data
|
||||||
|
|
||||||
|
def GetSelectedItemData(self, source):
|
||||||
|
item = self.GetSelectedItem(source)
|
||||||
|
data = source.GetPyData(item)
|
||||||
|
if not data:
|
||||||
|
raise ItemError('Empty data')
|
||||||
|
return (item, data)
|
||||||
|
|
||||||
pd = model_def.PackParams()
|
|
||||||
self.SetStatusText(pd, 0)
|
|
||||||
|
|
||||||
def OnModelActivated(self, event):
|
def OnModelActivated(self, event):
|
||||||
item = event.GetItem()
|
item = event.GetItem()
|
||||||
data = self.m_user_models.GetPyData(item)
|
data = self.m_user_models.GetPyData(item)
|
||||||
if data:
|
if data:
|
||||||
self.SelectUserModel(data[0], data[1])
|
self.SelectUserModel(data.mdef)
|
||||||
|
|
||||||
def OnParamChanging(self, event):
|
def OnParamChanging(self, event):
|
||||||
#value = event.GetValue()
|
#value = event.GetValue()
|
||||||
@ -251,69 +305,112 @@ class MainFrame(forms.MainFrame):
|
|||||||
return
|
return
|
||||||
value = prop.GetValue()
|
value = prop.GetValue()
|
||||||
param = prop.GetClientData()
|
param = prop.GetClientData()
|
||||||
um = self.m_user_models
|
data = self.GetSelectedData(self.m_user_models)
|
||||||
id = um.GetSelection()
|
data.mdef[param] = value
|
||||||
data, jid = um.GetItemPyData(id)
|
|
||||||
data[param] = value
|
|
||||||
|
|
||||||
def OnTest(self, event):
|
def OnTest(self, event):
|
||||||
um = self.m_user_models
|
um = self.m_user_models
|
||||||
|
|
||||||
def OnAddModelToRoot(self, event):
|
def OnAddModelToRoot(self, event):
|
||||||
item = self.m_specs.GetSelection()
|
model = self.GetSelectedData(self.m_specs)
|
||||||
if not item.IsOk():
|
|
||||||
return
|
|
||||||
print self.m_specs.GetItemText(item)
|
|
||||||
model = self.m_specs.GetPyData(item)
|
|
||||||
self.AddModelToRoot(model)
|
self.AddModelToRoot(model)
|
||||||
|
|
||||||
def OnAddModelToSelected(self, event):
|
def OnAddModelToSelected(self, event):
|
||||||
"""
|
"""
|
||||||
Добавляет пользовательскую спецификацию к указанной модели или в уже
|
Добавляет пользовательскую спецификацию к указанной модели
|
||||||
существующую иерархию спецификаций.
|
|
||||||
"""
|
"""
|
||||||
item = self.m_specs.GetSelection()
|
# получаем модель, которая будет добавлена к пользовательским
|
||||||
if not item.IsOk():
|
model = self.GetSelectedData(self.m_specs)
|
||||||
return
|
# получаем пользовательскую модель, к которой хотим присоединить новую
|
||||||
model = self.m_specs.GetPyData(item)
|
item, data = self.GetSelectedItemData(self.m_user_models)
|
||||||
|
pmdef = data.mdef
|
||||||
um = self.m_user_models
|
um = self.m_user_models
|
||||||
item = um.GetSelection()
|
# если новая модель может быть присоединена...
|
||||||
if not item.IsOk():
|
|
||||||
return
|
|
||||||
|
|
||||||
pmdef, _ = um.GetPyData(item)
|
|
||||||
|
|
||||||
if pmdef.DD == model.parent:
|
if pmdef.DD == model.parent:
|
||||||
modeldef = task.DataDefinition(model, pmdef)
|
name = self.GenerateName(model.GetTitle())
|
||||||
name = self.GenerateName(model.GetTitle())
|
child = um.AppendItem(item, name)
|
||||||
item = um.AppendItem(item, name)
|
new_data = ModelData(self.server, model, pmdef)
|
||||||
jid = self.server.CreateJob() if model.IsExecutable() else None
|
um.SetPyData(child, new_data)
|
||||||
um.SetPyData(item, [modeldef, jid])
|
um.Expand(item)
|
||||||
else:
|
else:
|
||||||
wx.MessageBox('It\'s impossible to append model', 'Error')
|
wx.MessageBox('It\'s impossible to append model', 'Error')
|
||||||
|
|
||||||
def OnDuplicate(self, event):
|
def OnDuplicate(self, event):
|
||||||
um = self.m_user_models
|
"""
|
||||||
id = um.GetSelection()
|
Обработчик события "дублирование модели"
|
||||||
title = um.GetItemText(id)
|
|
||||||
parent = um.GetItemParent(id)
|
|
||||||
md, jid = um.GetItemPyData(id)
|
|
||||||
|
|
||||||
child = um.AppendItem(parent, self.GenerateName(title))
|
Когда модель дублируется, ее параметры копируются в новую модель,
|
||||||
jid = self.server.CreateJob()
|
при неоходимости выделяется слот для работ на сервере.
|
||||||
um.SetPyData(child, [md.Copy(), jid])
|
Результаты модели-оригинала не копируются.
|
||||||
|
"""
|
||||||
|
um = self.m_user_models
|
||||||
|
item, data = self.GetSelectedItemData(self.m_user_models)
|
||||||
|
title = um.GetItemText(item)
|
||||||
|
parent = um.GetItemParent(item)
|
||||||
|
child = um.AppendItem(parent, self.GenerateName(title))
|
||||||
|
new_data = ModelData(self.server, data)
|
||||||
|
um.SetPyData(child, new_data)
|
||||||
self.SetStatusText('Copy for "{}" created'.format(title), 0)
|
self.SetStatusText('Copy for "{}" created'.format(title), 0)
|
||||||
|
|
||||||
|
def OnDuplicateTree(self, event):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def OnDeleteModel(self, event):
|
||||||
|
item, data = self.GetSelectedItemData(self.m_user_models)
|
||||||
|
self.server.DeleteJob(data.jid)
|
||||||
|
self.m_user_models.Delete(item)
|
||||||
|
|
||||||
def OnModelProcess(self, event):
|
def OnModelProcess(self, event):
|
||||||
um = self.m_user_models
|
um = self.m_user_models
|
||||||
for i in um.GetSelections():
|
for i in um.GetSelections():
|
||||||
data, jid = um.GetItemPyData(i)
|
data = um.GetItemPyData(i)
|
||||||
self.server.LaunchJob(jid, data)
|
self.server.LaunchJob(data.jid, data.mdef)
|
||||||
|
|
||||||
|
def OnShowResult(self, event):
|
||||||
|
item, data = self.GetSelectedItemData(self.m_user_models)
|
||||||
|
title = self.m_user_models.GetItemText(item)
|
||||||
|
title = 'Result for model "{}"'.format(title)
|
||||||
|
rframe = ResultFrame(self, title, data.res)
|
||||||
|
rframe.Show()
|
||||||
|
|
||||||
def OnIdle(self, event):
|
def OnIdle(self, event):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Форма с результатами выполнения работы
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class ResultFrame(forms.ResultFrame):
|
||||||
|
def __init__(self, parent, title, result):
|
||||||
|
forms.ResultFrame.__init__(self, parent, title)
|
||||||
|
self.result = result
|
||||||
|
self.UpdateResults()
|
||||||
|
|
||||||
|
def UpdateResults(self):
|
||||||
|
self.scalar.ClearPage(0)
|
||||||
|
self.table.ClearGrid()
|
||||||
|
if self.result:
|
||||||
|
table = self.result.get('table', [])
|
||||||
|
if table and len(table):
|
||||||
|
cols = len(table[0])
|
||||||
|
rows = len(table) - 1
|
||||||
|
self.table.CreateGrid(rows, cols)
|
||||||
|
#
|
||||||
|
for i, col in enumerate(table[0]):
|
||||||
|
label = "{} ({})".format(col[0], col[1])
|
||||||
|
self.table.SetColLabelValue(i, label)
|
||||||
|
#
|
||||||
|
for ri, row in enumerate(table[1:]):
|
||||||
|
for ci, value in enumerate(row):
|
||||||
|
self.table.SetCellValue(ri, ci, str(value))
|
||||||
|
|
||||||
|
self.table.AutoSize()
|
||||||
|
|
||||||
|
data = self.result.get('data', {})
|
||||||
|
pg = self.scalar
|
||||||
|
for label, value in data.iteritems():
|
||||||
|
pid = pg.Append(wxpg.StringProperty(label, value = str(value)))
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
# Приложение
|
# Приложение
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
12
server.py
12
server.py
@ -42,7 +42,7 @@ class LocalServer:
|
|||||||
self.workers = workers # количество потоков выполнения
|
self.workers = workers # количество потоков выполнения
|
||||||
self.tasks_meta = {} # идентификаор задачи
|
self.tasks_meta = {} # идентификаор задачи
|
||||||
self.models = [] # список моделей
|
self.models = [] # список моделей
|
||||||
self.next_job_id = 0 # очередной идентификатор работы
|
self.next_job_id = 1 # очередной идентификатор работы
|
||||||
self.jobs = {} # очередб работ
|
self.jobs = {} # очередб работ
|
||||||
self.log = None #
|
self.log = None #
|
||||||
self.running = False #
|
self.running = False #
|
||||||
@ -168,6 +168,12 @@ class LocalServer:
|
|||||||
if job != None:
|
if job != None:
|
||||||
job.Stop()
|
job.Stop()
|
||||||
|
|
||||||
|
def DeleteJob(self, jid):
|
||||||
|
job = self.jobs.get(jid)
|
||||||
|
if job != None:
|
||||||
|
job.Stop()
|
||||||
|
del self.jobs[jid]
|
||||||
|
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
|
|
||||||
def Start(self):
|
def Start(self):
|
||||||
@ -343,13 +349,13 @@ def main():
|
|||||||
md['d'] = 10
|
md['d'] = 10
|
||||||
md['r'] = 3.14
|
md['r'] = 3.14
|
||||||
|
|
||||||
slots = [ s.CreateJob() for i in xrange(5) ]
|
slots = [ s.CreateJob() for i in xrange(1) ]
|
||||||
for jid in slots:
|
for jid in slots:
|
||||||
md['n'] = random.randint(20, 30)
|
md['n'] = random.randint(20, 30)
|
||||||
print jid, md['n']
|
print jid, md['n']
|
||||||
s.LaunchJob(jid, md)
|
s.LaunchJob(jid, md)
|
||||||
|
|
||||||
time.sleep(30)
|
time.sleep(5)
|
||||||
|
|
||||||
for jid in slots:
|
for jid in slots:
|
||||||
pprint(s.GetJobResult(jid))
|
pprint(s.GetJobResult(jid))
|
||||||
|
21
task.py
21
task.py
@ -32,17 +32,12 @@ class Parameter:
|
|||||||
def GetDefault(self):
|
def GetDefault(self):
|
||||||
return self.data.get('default')
|
return self.data.get('default')
|
||||||
|
|
||||||
def GetTestExpresion(self):
|
def GetTestExpression(self):
|
||||||
return self.data.get('test')
|
return self.data.get('test')
|
||||||
|
|
||||||
def Test(self, value):
|
def Test(self, value):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
#def __repr__(self):
|
|
||||||
# return "'{}'".format(
|
|
||||||
# self.GetType()
|
|
||||||
# )
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
class DataDescription:
|
class DataDescription:
|
||||||
@ -88,6 +83,9 @@ class DataDescription:
|
|||||||
def __getitem__(self, label):
|
def __getitem__(self, label):
|
||||||
return self.pdata.get(label)
|
return self.pdata.get(label)
|
||||||
|
|
||||||
|
def type(self):
|
||||||
|
return 'data-def'
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
class DataDefinition:
|
class DataDefinition:
|
||||||
@ -124,3 +122,14 @@ class DataDefinition:
|
|||||||
package.reverse()
|
package.reverse()
|
||||||
return json.dumps(package)
|
return json.dumps(package)
|
||||||
|
|
||||||
|
def type(self):
|
||||||
|
return 'data-def'
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class ResultData:
|
||||||
|
def __init__(self, data):
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def GetColumns(self):
|
||||||
|
pass
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
"sintaylor": {
|
"sintaylor": {
|
||||||
|
|
||||||
"title": "Simple model",
|
"title": "Sin Taylor",
|
||||||
"author": "Anton Vakhrushev",
|
"author": "Anton Vakhrushev",
|
||||||
"date": "2012-03-08",
|
"date": "2012-03-08",
|
||||||
|
|
||||||
@ -40,11 +40,11 @@
|
|||||||
"spec": {
|
"spec": {
|
||||||
|
|
||||||
"left": {
|
"left": {
|
||||||
"title": "Left"
|
"title": "Left rectangles"
|
||||||
},
|
},
|
||||||
|
|
||||||
"right": {
|
"right": {
|
||||||
"title": "Right"
|
"title": "Right rectangles"
|
||||||
},
|
},
|
||||||
|
|
||||||
"trapezium": {
|
"trapezium": {
|
||||||
|
@ -39,13 +39,20 @@ def error(msg):
|
|||||||
"comment": msg
|
"comment": msg
|
||||||
})
|
})
|
||||||
|
|
||||||
def result(r):
|
def result(s, t):
|
||||||
return json.dumps({
|
return json.dumps({
|
||||||
"answer": "result",
|
"answer": "result",
|
||||||
"result": {
|
"result": {
|
||||||
"table": [[ {"x": "double"}, {"y": "double"} ]] + r
|
"data": s,
|
||||||
}
|
"table": t
|
||||||
})
|
}})
|
||||||
|
|
||||||
|
def serie(n, d, h, l = 0):
|
||||||
|
for i in xrange(n):
|
||||||
|
y = sin_taylor(l, d)
|
||||||
|
yield (l, y)
|
||||||
|
l += h
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
@ -62,26 +69,55 @@ def main():
|
|||||||
textdata = raw_input()
|
textdata = raw_input()
|
||||||
data = json.loads(textdata)
|
data = json.loads(textdata)
|
||||||
|
|
||||||
if not len(data) or data[-1]['label'] != 'sintaylor':
|
|
||||||
write(error('Unknown model'))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
params = data[0]['params']
|
params = data[0]['params']
|
||||||
l = 0 # левая граница
|
|
||||||
r = params['r'] # правая граница
|
r = params['r'] # правая граница
|
||||||
n = params['n'] # количество шагов
|
n = params['n'] # количество шагов
|
||||||
d = params['d'] # количество членов в разложении Тейлора
|
d = params['d'] # количество членов в разложении Тейлора
|
||||||
h = float(r - l) / n # шаг сетки по х
|
h = r / n
|
||||||
res = [] # таблица резултатов
|
res = [] # таблица резултатов
|
||||||
|
|
||||||
while l <= r:
|
label = data[-1]['label']
|
||||||
y = sin_taylor(l, d)
|
sum = 0
|
||||||
res.append([l, y])
|
|
||||||
write(answer(l / r, data[-1]['label']))
|
if label == 'sintaylor':
|
||||||
l += h
|
for x, y in serie(n, d, h):
|
||||||
time.sleep(0.1)
|
res.append([x, y])
|
||||||
|
write(answer(x / r, label))
|
||||||
|
write(result({},
|
||||||
|
[[ ['x', 'double'], [ 'y', 'double' ] ]] + res))
|
||||||
|
|
||||||
|
elif label == 'left':
|
||||||
|
for x, y in serie(n-1, d, h):
|
||||||
|
s = y * h
|
||||||
|
res.append([x, y, s])
|
||||||
|
write(answer(x / r, label))
|
||||||
|
sum += s
|
||||||
|
write(result(
|
||||||
|
{ 'sum': sum },
|
||||||
|
[[ ['x', 'double'], [ 'y', 'double' ], [ 's', 'double' ] ]] + res))
|
||||||
|
|
||||||
|
elif label == 'right':
|
||||||
|
for x, y in serie(n-1, d, h, h):
|
||||||
|
s = y * h
|
||||||
|
res.append([x, y, s])
|
||||||
|
write(answer(x / r, label))
|
||||||
|
sum += s
|
||||||
|
write(result(
|
||||||
|
{ 'sum': sum },
|
||||||
|
[[ ['x', 'double'], [ 'y', 'double' ], [ 's', 'double' ] ]] + res))
|
||||||
|
|
||||||
|
elif label == 'trapezium':
|
||||||
|
prev = 0
|
||||||
|
for x, y in serie(n + 1, d, h):
|
||||||
|
s = 0.5 * (y + prev) * h
|
||||||
|
res.append([x, y, s])
|
||||||
|
write(answer(x / r, label))
|
||||||
|
sum += s
|
||||||
|
prev = y
|
||||||
|
write(result(
|
||||||
|
{ 'sum': sum },
|
||||||
|
[[ ['x', 'double'], [ 'y', 'double' ], [ 's', 'double' ] ]] + res))
|
||||||
|
|
||||||
write(result(res))
|
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
write(error('Fatal error: ' + str(e)))
|
write(error('Fatal error: ' + str(e)))
|
||||||
|
Loading…
Reference in New Issue
Block a user