From 6aefad8ab18467ed89b819dd5712d743b2306b35 Mon Sep 17 00:00:00 2001 From: anwinged Date: Tue, 24 Apr 2012 14:02:32 +0000 Subject: [PATCH] Data wrapper for result object --- forms.py | 28 ++++++++++++-------- opal.py | 66 +++++++++++++++++++++++++++++++----------------- server.py | 2 +- task.py | 58 ++++++++++++++++++++++++++++++++++++++---- tasks/testt.json | 4 +-- tasks/testt.py | 16 ++++++------ 6 files changed, 125 insertions(+), 49 deletions(-) diff --git a/forms.py b/forms.py index 77d1663..a1e06af 100644 --- a/forms.py +++ b/forms.py @@ -47,7 +47,7 @@ class MainFrame (wx.Frame): bSizer3 = wx.BoxSizer(wx.HORIZONTAL) 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(200,-1)) bSizer3.Add(self.m_specs, 0, wx.ALL|wx.EXPAND, 1) @@ -56,25 +56,32 @@ class MainFrame (wx.Frame): self.m_user_models = TreeListCtrl(self, 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, 300)) 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) + bSizer4.Add(self.m_user_models, 0, wx.ALL | wx.EXPAND, 1) # WARNING: wxPython code generation isn't supported for this widget yet. self.m_params = wxpg.PropertyGridManager(self) 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) bSizer3.Add(bSizer4, 1, wx.EXPAND, 5) - self.m_job_list = wx.ListBox(self)#, style = wx.LC_LIST) - self.m_job_list.SetMinSize(wx.Size(200,-1)) + bSizer5 = wx.BoxSizer(wx.VERTICAL) - bSizer3.Add(self.m_job_list, 0, wx.ALL|wx.EXPAND, 1) + self.m_quick_result = wxpg.PropertyGridManager(self) + self.m_quick_result.AddPage('fp') + self.m_quick_result.SetMinSize(wx.Size(200, -1)) + bSizer5.Add(self.m_quick_result, 1, wx.EXPAND | wx.ALL, 1) + + self.m_plots = wx.TreeCtrl(self, style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT) + bSizer5.Add(self.m_plots, 1, wx.EXPAND | wx.ALL, 1) + + bSizer3.Add(bSizer5, 0, wx.ALL | wx.EXPAND, 1) sbar = wx.StatusBar(self) self.SetStatusBar(sbar) @@ -130,7 +137,8 @@ class MainFrame (wx.Frame): class ResultFrame(wx.Frame): def __init__(self, parent, title): - wx.Frame.__init__ (self, parent, -1, title, size = wx.Size(600, 400)) + wx.Frame.__init__ (self, parent, -1, title, size = wx.Size(500, 500), + style = wx.DEFAULT_FRAME_STYLE) sizer = wx.BoxSizer(wx.VERTICAL) @@ -140,8 +148,8 @@ class ResultFrame(wx.Frame): 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) + 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() diff --git a/opal.py b/opal.py index aa2c764..9c55b49 100644 --- a/opal.py +++ b/opal.py @@ -65,6 +65,11 @@ class MainFrame(forms.MainFrame): self.OnParamChanging) self.m_params.Bind(wxpg.EVT_PG_CHANGED, self.OnParamChanged) + self.m_specs.Bind(wx.EVT_TREE_ITEM_ACTIVATED, + self.OnAddModelToSelected) + self.m_user_models.Bind(wx.EVT_TREE_ITEM_ACTIVATED, + self.OnModelProcess) + self.Bind(wx.EVT_MENU, self.OnTest, id = forms.ID_TEST) @@ -136,9 +141,15 @@ class MainFrame(forms.MainFrame): p = 'Unknown' if percent < 0 else '{:%}'.format(percent) um.SetItemText(item, p, 2) um.SetItemText(item, comment, 3) - print jid, (state, percent, comment) + print 'JID', jid, (state, percent, comment) + # завершающие действия по окончанию выполнения работы if state == server.JOB_COMPLETED: + # получаем результаты выполнения data.res = self.server.GetJobResult(jid) + # если завершившаяся задача в данный момент выделена + # то сразу же показываем этот результат + if um.IsSelected(item): + self.ShowQuickResult(data.res) wx.MutexGuiLeave() time.sleep(0.1) @@ -238,13 +249,13 @@ class MainFrame(forms.MainFrame): Смотри руководство пользователя для того, чтобы получить полную информацию о всех типах данных, используемых в Opal. """ - if param_type == 'bool': + if param_type == 'bool' or param_type == 'boolean': return wxpg.BoolProperty elif param_type == 'int': return wxpg.IntProperty elif param_type == 'float' or param_type == 'double': return wxpg.FloatProperty - elif param_type == 'string': + elif param_type == 'str' or param_type == 'string': return wxpg.StringProperty elif param_type == 'list': return wxpg.ArrayStringProperty @@ -257,7 +268,7 @@ class MainFrame(forms.MainFrame): pg.ClearPage(0) for label, value in model_def.params.iteritems(): param = model_def.DD[label] - title = param.GetTitle() or label + title = param.GetTitle() prop = SelectProperty(param.GetType()) pid = pg.Append(prop(title, value = value)) pg.SetPropertyClientData(pid, label) @@ -265,6 +276,15 @@ class MainFrame(forms.MainFrame): self.SetStatusText(model_def.PackParams(), 0) + def ShowQuickResult(self, result): + if not result: + return + pg = self.m_quick_result + pg.ClearPage(0) + for label, param in result.data.iteritems(): + pg.Append(wxpg.StringProperty(label, value = str(param.GetValue()))) + pg.SetSplitterLeft() + def GetSelectedItem(self, source): item = source.GetSelection() if not item.IsOk(): @@ -291,6 +311,7 @@ class MainFrame(forms.MainFrame): data = self.m_user_models.GetPyData(item) if data: self.SelectUserModel(data.mdef) + self.ShowQuickResult(data.res) def OnParamChanging(self, event): #value = event.GetValue() @@ -389,27 +410,26 @@ class ResultFrame(forms.ResultFrame): 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)) + if not self.result: + return - self.table.AutoSize() + cols = len(self.result.columns) + rows = len(self.result.rows) + self.table.CreateGrid(rows, cols) + # + for i, col in enumerate(self.result.columns): + label = "{} ({} {})".format(col.GetTitle(), col.GetType(), col.GetLabel()) + self.table.SetColLabelValue(i, label) + # + for i, row in enumerate(self.result.rows): + for j, value in enumerate(row): + self.table.SetCellValue(i, j, str(value)) - data = self.result.get('data', {}) - pg = self.scalar - for label, value in data.iteritems(): - pid = pg.Append(wxpg.StringProperty(label, value = str(value))) + self.table.AutoSize() + + pg = self.scalar + for label, param in self.result.data.iteritems(): + pg.Append(wxpg.StringProperty(label, value = str(param.GetValue()))) #----------------------------------------------------------------------------- # Приложение diff --git a/server.py b/server.py index 5ddd350..c4ce5d1 100644 --- a/server.py +++ b/server.py @@ -246,7 +246,7 @@ class Worker(threading.Thread): # в ответе пришел результат вычислений # помещаем в секцию результата elif ans == 'result': - job.result = data['result'] + job.result = task.ResultData(data['result']) # произошла ошибка elif ans == 'error': WriteToLog('Error! ' + msg) diff --git a/task.py b/task.py index e01244e..ea28bc0 100644 --- a/task.py +++ b/task.py @@ -17,14 +17,18 @@ import json #------------------------------------------------------------------------------- class Parameter: - def __init__(self, data): + def __init__(self, label, data): self.data = data + self.data['label'] = label + + def GetLabel(self): + return self.data['label'] def GetType(self): return self.data['type'] def GetTitle(self): - return self.data.get('title', '') + return self.data.get('title', self.GetLabel()) def GetComment(self): return self.data.get('comment', '') @@ -38,6 +42,34 @@ class Parameter: def Test(self, value): return True +class Value(Parameter): + def __init__(self, label, value): + if isinstance(value, dict): + self.data = value + else: + self.data = { + 'value': value, + 'type': value.__class__.__name__ + } + self.data['label'] = label + + def GetType(self): + return self.data.get('type', 'unknown') + + def GetValue(self): + return self.data['value'] + +class Column(Parameter): + def __init__(self, colvalues): + self.data = {} + # следующие два поля должны обязательно присутствовать + self.data['label'] = colvalues[0] + self.data['type'] = colvalues[1] + try: + self.data['title'] = colvalues[2] + except: + pass + #------------------------------------------------------------------------------- class DataDescription: @@ -51,7 +83,7 @@ class DataDescription: self.pdata = self.data.get('params', {}) # заменяем текстовое описание на объект-параметр for label in self.pdata: - par = Parameter(self.pdata[label]) + par = Parameter(label, self.pdata[label]) self.pdata[label] = par self.specs = [] @@ -129,7 +161,23 @@ class DataDefinition: class ResultData: def __init__(self, data): - self.data = data + self.data = {} + for key, value in data.get('data', {}).iteritems(): + self.data[key] = Value(key, value) + + table = data.get('table', []) + self.head = {} + self.table = [] + if table: + self.head = [ Column(item) for item in table[0] ] + self.table = table[1:] def GetColumns(self): - pass \ No newline at end of file + return self.head + + columns = property(GetColumns) + + def GetRows(self): + return self.table + + rows = property(GetRows) diff --git a/tasks/testt.json b/tasks/testt.json index 4f6b333..cdae21a 100644 --- a/tasks/testt.json +++ b/tasks/testt.json @@ -11,13 +11,13 @@ "author": "Anton Vakhrushev", "date": "2012-03-08", - "exec": true, + "exec": false, "params": { "r": { "type": "float", - "default": 6.28, + "default": 6.283185307, "title": "Right edge", "comment": "Right edge" }, diff --git a/tasks/testt.py b/tasks/testt.py index 6456567..f1cbecb 100644 --- a/tasks/testt.py +++ b/tasks/testt.py @@ -2,8 +2,8 @@ # Тестовое приложение для проекта Opal # Вычисление значений синуса по формулам Тейлора -# Вычисляет значения для указанного диапазона с заданной точностью -# и нужным количеством шагов +# Вычисляет значения для указанного диапазона +# с заданной точностью и нужным количеством шагов import sys import json @@ -43,12 +43,12 @@ def result(s, t): return json.dumps({ "answer": "result", "result": { - "data": s, + "data": s, "table": t }}) def serie(n, d, h, l = 0): - for i in xrange(n): + for i in xrange(n + 1): y = sin_taylor(l, d) yield (l, y) l += h @@ -87,17 +87,17 @@ def main(): [[ ['x', 'double'], [ 'y', 'double' ] ]] + res)) elif label == 'left': - for x, y in serie(n-1, d, h): + 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)) + [[ ['x', 'double'], [ 'y', 'double' ], [ 's', 'double', 'Delta sum' ] ]] + res)) elif label == 'right': - for x, y in serie(n-1, d, h, h): + for x, y in serie(n - 1, d, h, h): s = y * h res.append([x, y, s]) write(answer(x / r, label)) @@ -108,7 +108,7 @@ def main(): elif label == 'trapezium': prev = 0 - for x, y in serie(n + 1, d, h): + for x, y in serie(n, d, h): s = 0.5 * (y + prev) * h res.append([x, y, s]) write(answer(x / r, label))