Work with specifications partly added
This commit is contained in:
		@@ -5,7 +5,8 @@ import wx.gizmos
 | 
			
		||||
import wx.propgrid as wxpg
 | 
			
		||||
 | 
			
		||||
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_DELETE_MODEL         = wx.NewId()
 | 
			
		||||
ID_PROCESS_MODEL        = wx.NewId()
 | 
			
		||||
@@ -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))
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										168
									
								
								trunk/opal.py
									
									
									
									
									
								
							
							
						
						
									
										168
									
								
								trunk/opal.py
									
									
									
									
									
								
							@@ -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,6 +72,19 @@ 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
 | 
			
		||||
@@ -74,33 +97,102 @@ class MainFrame(forms.MainFrame):
 | 
			
		||||
                    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)
 | 
			
		||||
                            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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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):
 | 
			
		||||
 
 | 
			
		||||
@@ -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):
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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))
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user