model states ench
This commit is contained in:
		@@ -18,7 +18,9 @@ ID_ADD_MODEL_SELECTED   = wx.NewId()
 | 
			
		||||
ID_DUPLICATE_MODEL      = wx.NewId()
 | 
			
		||||
ID_DUPLICATE_TREE       = wx.NewId()
 | 
			
		||||
ID_DELETE_MODEL         = wx.NewId()
 | 
			
		||||
 | 
			
		||||
ID_PROCESS_MODEL        = wx.NewId()
 | 
			
		||||
ID_STOP_MODEL           = wx.NewId()
 | 
			
		||||
 | 
			
		||||
ID_SHOW_RESULT          = wx.NewId()
 | 
			
		||||
 | 
			
		||||
@@ -152,6 +154,8 @@ class MainFrame(wx.Frame):
 | 
			
		||||
        icons.mready    = ilist.Add(wx.Bitmap('share/model-ready.png'))
 | 
			
		||||
        icons.mrun      = ilist.Add(wx.Bitmap('share/model-run.png'))
 | 
			
		||||
        icons.mcomplete = ilist.Add(wx.Bitmap('share/model-complete.png'))
 | 
			
		||||
        icons.mstopped  = ilist.Add(wx.Bitmap('share/model-stop.png'))
 | 
			
		||||
        icons.mnoexec   = ilist.Add(wx.Bitmap('share/model-no-exec.png'))
 | 
			
		||||
 | 
			
		||||
        icons.porg      = ilist.Add(wx.Bitmap('share/plot-org.png'))
 | 
			
		||||
        icons.pline     = ilist.Add(wx.Bitmap('share/plot-line.png'))
 | 
			
		||||
@@ -182,6 +186,7 @@ class MainFrame(wx.Frame):
 | 
			
		||||
 | 
			
		||||
        menu = wx.Menu()
 | 
			
		||||
        menu.Append(ID_PROCESS_MODEL, 'Process\tF5')
 | 
			
		||||
        menu.Append(ID_STOP_MODEL, 'Stop\tF6')
 | 
			
		||||
        #menu.AppendSeparator()
 | 
			
		||||
        menubar.Append(menu, '&Run')
 | 
			
		||||
 | 
			
		||||
@@ -237,7 +242,9 @@ class MainFrame(wx.Frame):
 | 
			
		||||
            'Delete selected model')
 | 
			
		||||
        tb1.AddSeparator()
 | 
			
		||||
        tb1.AddSimpleTool(ID_PROCESS_MODEL, "model-go", wx.Bitmap('share/model-go.png'),
 | 
			
		||||
            'Start process selected model')
 | 
			
		||||
            'Start processing of selected models')
 | 
			
		||||
        tb1.AddSimpleTool(ID_STOP_MODEL, "model-stop", wx.Bitmap('share/model-cancel.png'),
 | 
			
		||||
            'Stop processing of selected models')
 | 
			
		||||
        tb1.AddSeparator()
 | 
			
		||||
        tb1.AddSimpleTool(ID_SHOW_PLOT, "plot-quick", wx.Bitmap('share/plot-line.png'),
 | 
			
		||||
            'Show quick plot for selected model')
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										152
									
								
								trunk/opal.py
									
									
									
									
									
								
							
							
						
						
									
										152
									
								
								trunk/opal.py
									
									
									
									
									
								
							@@ -27,21 +27,43 @@ import json
 | 
			
		||||
import zlib
 | 
			
		||||
from pprint import pprint
 | 
			
		||||
 | 
			
		||||
# состояния модели, унаследованные от состояния задачи
 | 
			
		||||
MODEL_READY = server.JOB_READY
 | 
			
		||||
MODEL_RUNNING = server.JOB_RUNNING
 | 
			
		||||
MODEL_STOPPED = server.JOB_STOPPED
 | 
			
		||||
MODEL_COMPLETED = server.JOB_COMPLETED
 | 
			
		||||
# собственные состояния модели
 | 
			
		||||
MODEL_NO_EXEC = 101
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------------
 | 
			
		||||
# Данные о пользовательской модели
 | 
			
		||||
# --------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
            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 else None
 | 
			
		||||
            self.jid = server.CreateJob() if model.jid else None
 | 
			
		||||
        else:
 | 
			
		||||
            self.mdef = None
 | 
			
		||||
            self.jid  = None
 | 
			
		||||
            self.jid = None
 | 
			
		||||
 | 
			
		||||
        self.res  = None
 | 
			
		||||
        assert self.mdef
 | 
			
		||||
 | 
			
		||||
        self.res  = None            # результаты выполнения работы
 | 
			
		||||
        if self.jid:
 | 
			
		||||
            self.state = MODEL_READY    # состояние модели
 | 
			
		||||
        else:
 | 
			
		||||
            self.state = MODEL_NO_EXEC  # состояние модели
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------------
 | 
			
		||||
# Данные о линии в графике
 | 
			
		||||
# --------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
LINE_CURVE     = 1
 | 
			
		||||
LINE_MARKER    = 2
 | 
			
		||||
@@ -96,6 +118,10 @@ class LineData:
 | 
			
		||||
        assert data.res # если результата нет, то а-та-та
 | 
			
		||||
        return data.res.Zip(*self.columns)
 | 
			
		||||
 | 
			
		||||
# --------------------------------------------------------------------------
 | 
			
		||||
# Ошибки доступа к элементам в контейнерах
 | 
			
		||||
# --------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class ItemError(Exception):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
@@ -156,8 +182,11 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
            id = forms.ID_DUPLICATE_TREE)
 | 
			
		||||
        self.Bind(wx.EVT_MENU, self.OnDeleteModel,
 | 
			
		||||
            id = forms.ID_DELETE_MODEL)
 | 
			
		||||
 | 
			
		||||
        self.Bind(wx.EVT_MENU, self.OnModelProcess,
 | 
			
		||||
            id = forms.ID_PROCESS_MODEL)
 | 
			
		||||
        self.Bind(wx.EVT_MENU, self.OnModelStop,
 | 
			
		||||
            id = forms.ID_STOP_MODEL)
 | 
			
		||||
 | 
			
		||||
        self.Bind(wx.EVT_MENU, self.OnShowResult,
 | 
			
		||||
            id = forms.ID_SHOW_RESULT)
 | 
			
		||||
@@ -214,19 +243,6 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
        состояние окружения, выводит информацию, подгружает результаты
 | 
			
		||||
        выполнения работ и др.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
@@ -247,25 +263,29 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
                        if not data:
 | 
			
		||||
                            continue
 | 
			
		||||
                        jid = data.jid
 | 
			
		||||
                        if jid != None and self.server.IsJobChanged(jid):
 | 
			
		||||
                        if jid and self.server.IsJobChanged(jid):
 | 
			
		||||
                            # таким образом, тут мы обрабатываем новое состояние
 | 
			
		||||
                            # работы (модели)
 | 
			
		||||
 | 
			
		||||
                            state, percent, comment = self.server.GetJobState(jid)
 | 
			
		||||
                            um.SetItemText(item, StateToStr(state), 1)
 | 
			
		||||
 | 
			
		||||
                            data.state = state
 | 
			
		||||
                            self.SetModelState(item, data.state)
 | 
			
		||||
 | 
			
		||||
                            p = 'Unknown' if percent < 0 else '{:%}'.format(percent)
 | 
			
		||||
                            um.SetItemText(item, p, 2)
 | 
			
		||||
                            um.SetItemText(item, comment, 3)
 | 
			
		||||
 | 
			
		||||
                            print 'JID', jid, (state, percent, comment)
 | 
			
		||||
 | 
			
		||||
                            # завершающие действия по окончанию выполнения работы
 | 
			
		||||
                            if state == server.JOB_COMPLETED:
 | 
			
		||||
                                # устанавливаем иконку для завершенной модели
 | 
			
		||||
                                um.SetItemImage(item, self.icons.mcomplete)
 | 
			
		||||
                                # получаем результаты выполнения
 | 
			
		||||
                                data.res = self.server.GetJobResult(jid)
 | 
			
		||||
                                # если завершившаяся задача в данный момент выделена
 | 
			
		||||
                                # то сразу же показываем этот результат
 | 
			
		||||
                                if um.IsSelected(item):
 | 
			
		||||
                                    self.ShowQuickResult(data.res)
 | 
			
		||||
                            else:
 | 
			
		||||
                                um.SetItemImage(item, self.icons.mrun)
 | 
			
		||||
                finally:
 | 
			
		||||
                    wx.MutexGuiLeave()
 | 
			
		||||
                    pass
 | 
			
		||||
@@ -396,7 +416,6 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
        except Exception, e:
 | 
			
		||||
            print 'Oops', type(e), e
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def OnSaveProject(self, event):
 | 
			
		||||
 | 
			
		||||
        def WalkModels(item, dest):
 | 
			
		||||
@@ -407,7 +426,8 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
                dest[title] = {
 | 
			
		||||
                    'model': mdef.DD.GetLabel(),
 | 
			
		||||
                    'data': mdef.params,
 | 
			
		||||
                    'um': {}
 | 
			
		||||
                    'um': {},
 | 
			
		||||
                    'state': data.state,
 | 
			
		||||
                }
 | 
			
		||||
                if data.res:
 | 
			
		||||
                    dest[title]['result'] = data.res.DumpData()
 | 
			
		||||
@@ -457,9 +477,9 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
 | 
			
		||||
        # pprint(data)
 | 
			
		||||
        dump = json.dumps(data, indent = 2)
 | 
			
		||||
        with open('data.opl', 'wb') as f:
 | 
			
		||||
            f.write(zlib.compress(dump, 9))
 | 
			
		||||
            # f.write(dump)
 | 
			
		||||
        with open('data.opl', 'w') as f:
 | 
			
		||||
            # f.write(zlib.compress(dump, 9))
 | 
			
		||||
            f.write(dump)
 | 
			
		||||
 | 
			
		||||
        wx.EndBusyCursor()
 | 
			
		||||
 | 
			
		||||
@@ -495,6 +515,41 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
 | 
			
		||||
    # Добавление новых моделей
 | 
			
		||||
 | 
			
		||||
    def SetModelState(self, item, state):
 | 
			
		||||
        if state == MODEL_READY:
 | 
			
		||||
            icon = self.icons.mready
 | 
			
		||||
            text = 'Ready'
 | 
			
		||||
 | 
			
		||||
        elif state == MODEL_RUNNING:
 | 
			
		||||
            icon = self.icons.mrun
 | 
			
		||||
            text = 'Running'
 | 
			
		||||
 | 
			
		||||
        elif state == MODEL_COMPLETED:
 | 
			
		||||
            icon = self.icons.mcomplete
 | 
			
		||||
            text = 'Completed'
 | 
			
		||||
 | 
			
		||||
        elif state == MODEL_STOPPED:
 | 
			
		||||
            icon = self.icons.mstopped
 | 
			
		||||
            text = 'Stopped'
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
            icon = self.icons.mnoexec
 | 
			
		||||
            text = 'No executable'
 | 
			
		||||
 | 
			
		||||
        self.m_user_models.SetItemImage(item, icon)
 | 
			
		||||
        self.m_user_models.SetItemText(item, text, 1)
 | 
			
		||||
 | 
			
		||||
    def AddModel(self, item, title, model_data):
 | 
			
		||||
        """
 | 
			
		||||
        Добавляет модель к указанной,
 | 
			
		||||
        устанавливает имя, данные, состояние, иконку
 | 
			
		||||
        """
 | 
			
		||||
        um = self.m_user_models
 | 
			
		||||
        item = um.AppendItem(item, title)
 | 
			
		||||
        um.SetPyData(item, model_data)
 | 
			
		||||
        self.SetModelState(item, model_data.state)
 | 
			
		||||
        return item
 | 
			
		||||
 | 
			
		||||
    def AddModelToRoot(self, model):
 | 
			
		||||
        """
 | 
			
		||||
        Добавляет пользовательскую модель или спецификацию
 | 
			
		||||
@@ -514,13 +569,11 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
        root = None
 | 
			
		||||
        for i, m in enumerate(ms):
 | 
			
		||||
            name = self.GenerateName(m.GetTitle())
 | 
			
		||||
            item = um.AppendItem(item, name)
 | 
			
		||||
            um.SetItemImage(item, self.icons.mready)
 | 
			
		||||
            if not i:
 | 
			
		||||
                root = item
 | 
			
		||||
            data = ModelData(self.server, m, defparent)
 | 
			
		||||
            item = self.AddModel(item, name, data)
 | 
			
		||||
            defparent = data.mdef
 | 
			
		||||
            um.SetPyData(item, data)
 | 
			
		||||
        if root:
 | 
			
		||||
            um.Expand(root)
 | 
			
		||||
        um.SelectItem(item)
 | 
			
		||||
@@ -543,10 +596,8 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
        # если новая модель может быть присоединена...
 | 
			
		||||
        if pmdef.DD == model.parent:
 | 
			
		||||
            name     = self.GenerateName(model.GetTitle())
 | 
			
		||||
            child    = um.AppendItem(item, name)
 | 
			
		||||
            new_data = ModelData(self.server, model, pmdef)
 | 
			
		||||
            um.SetPyData(child, new_data)
 | 
			
		||||
            um.SetItemImage(child, self.icons.mready)
 | 
			
		||||
            child = self.AddModel(item, name, new_data)
 | 
			
		||||
            um.SetFocus()
 | 
			
		||||
            um.Expand(item)
 | 
			
		||||
            um.SelectItem(child)
 | 
			
		||||
@@ -616,7 +667,11 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
    def OnParamChanged(self, event):
 | 
			
		||||
 | 
			
		||||
        def Walk(item):
 | 
			
		||||
            um.SetItemImage(item, self.icons.mready)
 | 
			
		||||
            data = um.GetPyData(item)
 | 
			
		||||
            if data.state != MODEL_NO_EXEC:
 | 
			
		||||
                data.state = MODEL_READY
 | 
			
		||||
                self.SetModelState(item, data.state)
 | 
			
		||||
 | 
			
		||||
            child, _ = um.GetFirstChild(item)
 | 
			
		||||
            while child.IsOk():
 | 
			
		||||
                Walk(child)
 | 
			
		||||
@@ -635,17 +690,7 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
        Walk(item)
 | 
			
		||||
 | 
			
		||||
    def OnTest(self, event):
 | 
			
		||||
 | 
			
		||||
        def Walk(item):
 | 
			
		||||
            print um.GetItemText(item)
 | 
			
		||||
            um.SetItemImage(item, self.icons.mready)
 | 
			
		||||
            child, cookie = um.GetFirstChild(item)
 | 
			
		||||
            while child.IsOk():
 | 
			
		||||
                Walk(child)
 | 
			
		||||
                child = um.GetNextSibling(child)
 | 
			
		||||
 | 
			
		||||
        um = self.m_user_models
 | 
			
		||||
        Walk(um.GetRootItem())
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    # Получение данных выбранной модели
 | 
			
		||||
 | 
			
		||||
@@ -678,7 +723,7 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
        new_data = ModelData(self.server, data)
 | 
			
		||||
        um.SetItemText(item_dst, self.GenerateName(title))
 | 
			
		||||
        um.SetPyData(item_dst, new_data)
 | 
			
		||||
        um.SetItemImage(item_dst, self.icons.mready)
 | 
			
		||||
        self.SetModelState(item_dst, new_data.state)
 | 
			
		||||
 | 
			
		||||
    def OnDuplicate(self, event):
 | 
			
		||||
        """
 | 
			
		||||
@@ -731,7 +776,15 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
        um = self.m_user_models
 | 
			
		||||
        for i in um.GetSelections():
 | 
			
		||||
            data = um.GetItemPyData(i)
 | 
			
		||||
            self.server.LaunchJob(data.jid, data.mdef)
 | 
			
		||||
            if data.jid:
 | 
			
		||||
                self.server.LaunchJob(data.jid, data.mdef)
 | 
			
		||||
 | 
			
		||||
    def OnModelStop(self, event):
 | 
			
		||||
        um = self.m_user_models
 | 
			
		||||
        for i in um.GetSelections():
 | 
			
		||||
            data = um.GetItemPyData(i)
 | 
			
		||||
            if data.jid:
 | 
			
		||||
                self.server.StopJob(data.jid)
 | 
			
		||||
 | 
			
		||||
    # Функции управления таблицами и отчетами
 | 
			
		||||
 | 
			
		||||
@@ -842,7 +895,8 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
    def ShowPlot(self, lines, plot_title = ''):
 | 
			
		||||
        if lines:
 | 
			
		||||
            p = PlotFrame(self, 'Plot', lines)
 | 
			
		||||
            p.Show()
 | 
			
		||||
            wx.FutureCall(20, p.Show)
 | 
			
		||||
            # p.Show()
 | 
			
		||||
 | 
			
		||||
    def OnQuickShowPlot(self, event):
 | 
			
		||||
        lines = self.GetLines(LINE_CURVE)
 | 
			
		||||
 
 | 
			
		||||
@@ -219,16 +219,23 @@ class Worker(threading.Thread):
 | 
			
		||||
            proc.stdin.flush()
 | 
			
		||||
            # пока процесс не завершится (или его не прибьют)
 | 
			
		||||
            while proc.poll() == None:
 | 
			
		||||
                # читаем и обрабатываем сообщение
 | 
			
		||||
                msg = proc.stdout.readline()
 | 
			
		||||
                self.ProcessMessage(job, msg)
 | 
			
		||||
 | 
			
		||||
                # сервер был остановлен, завершаем выполнение всех работ
 | 
			
		||||
                if not self.server.running:
 | 
			
		||||
                    proc.kill()
 | 
			
		||||
                    raise KeyError
 | 
			
		||||
                    
 | 
			
		||||
        except Exception, e:
 | 
			
		||||
            # любая нестандартная исключительная ситуация
 | 
			
		||||
            # приводит к немедленному завершанию работы
 | 
			
		||||
            WriteToLog('Job loop failed: ' + str(e))
 | 
			
		||||
            job.Finish(JOB_STOPPED)
 | 
			
		||||
        else:
 | 
			
		||||
            job.Finish(JOB_COMPLETED, 1.0)
 | 
			
		||||
            # только если работа уже не была остановлена
 | 
			
		||||
            if job.state != JOB_STOPPED:
 | 
			
		||||
                job.Finish(JOB_COMPLETED, 1.0)
 | 
			
		||||
 | 
			
		||||
    def ProcessMessage(self, job, msg):
 | 
			
		||||
        try:
 | 
			
		||||
@@ -246,7 +253,10 @@ class Worker(threading.Thread):
 | 
			
		||||
                job.result = task.ResultData(data['result'])
 | 
			
		||||
            # произошла ошибка
 | 
			
		||||
            elif ans == 'error':
 | 
			
		||||
                # произошла серьезная ошибка
 | 
			
		||||
                # завршаем выполнение работы
 | 
			
		||||
                WriteToLog('Error! ' + msg)
 | 
			
		||||
                raise RuntimeError, msg
 | 
			
		||||
            # недокументированный ответ приложения
 | 
			
		||||
            else:
 | 
			
		||||
                pass
 | 
			
		||||
@@ -318,7 +328,7 @@ class Job:
 | 
			
		||||
        if self.proc and self.proc.poll() == None:
 | 
			
		||||
            WriteToLog('Try to kill')
 | 
			
		||||
            self.proc.kill()
 | 
			
		||||
            self.ChangeState()
 | 
			
		||||
            self.Finish(JOB_STOPPED)
 | 
			
		||||
            WriteToLog('Job killed')
 | 
			
		||||
 | 
			
		||||
    def Finish(self, state, percent = None):
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								trunk/share/model-cancel.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								trunk/share/model-cancel.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 727 B  | 
							
								
								
									
										
											BIN
										
									
								
								trunk/share/model-no-exec.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								trunk/share/model-no-exec.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 518 B  | 
							
								
								
									
										
											BIN
										
									
								
								trunk/share/model-stop.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								trunk/share/model-stop.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 560 B  | 
@@ -52,7 +52,8 @@ def serie(n, d, h, l = 0):
 | 
			
		||||
        y = sin_taylor(l, d)
 | 
			
		||||
        yield (l, y)
 | 
			
		||||
        l += h
 | 
			
		||||
        # time.sleep(0.002)
 | 
			
		||||
        # assert 0
 | 
			
		||||
        time.sleep(0.002)
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user