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