def runwith(self, tt=None, sched_cfg=None): import schedule import timeutil _logger.info("Current time: %s", tt) sched = schedule.Schedule(sched_cfg) agenda = sched.next(tt) for next_tt, task in agenda: secs = timeutil.mktime(next_tt) - timeutil.mktime(tt) _logger.info( "At {next_tt!s:32} (T minus {secs:5d} seconds), {task}". format(next_tt=next_tt, task=task, secs=secs)) next_tt, task = agenda[0] secs = timeutil.mktime(next_tt) - timeutil.mktime(tt) ms = secs * 1000 # Deep sleep is not really worth it for less than ~30 sec. # Instead, light sleep and then go back to checking the schedule. if ms < self.MIN_DEEPSLEEP_MS: _logger.info("Light sleeping only %d seconds until %s", secs, task) utime.sleep_ms(ms) return [CheckSchedule, SleepUntilScheduled] if hw: _logger.info("Preparing for shutdown") hw.prepare_for_shutdown() _logger.info("Sleeping %d seconds until %s", secs, task) machine.deepsleep(ms)
def _create(self) -> None: if self._name.get().replace(' ', '') == '': tkmsg.showerror('Warning', '"Name" entry cannot be left blank.') else: try: int(self._units.get()) except (NameError, ValueError): tkmsg.showerror('Warning', '"Units" entry must be an integer.') else: try: if float(self._gpa.get()) < 0 or float( self._gpa.get()) > 5: raise NameError except (NameError, ValueError): tkmsg.showerror( 'Warning', '"GPA" entry must be a number between 0 and 5.') else: schedule.save_schedule( schedule.Schedule(self._name.get(), self._units.get(), self._gpa.get())) schedule.open_schedule( self._root, self._root_frame, open(f'schedules/{self._name.get()}.json'), self._start_page)
def dump_schedule_stringvars(): ''' self.__id = '' self.__date_created = '' self.__date_modified = '' self.__academic_year = '' self.__student_id = '' self.__metadata = '' self.__quarters = [] ''' finalS = schedule.Schedule() finalS.id = schdl.id.get() finalS.date_created = schdl.date_created.get() finalS.date_modified = schdl.date_modified.get() finalS.academic_year = schdl.academic_year.get() finalS.metadata = schdl.metadata.get() for quarter in range(0, len(schdl.quarters)): new_q = schedule.Quarter() new_q.id = schdl.quarters[quarter].id.get() new_q.title = schdl.quarters[quarter].title.get() new_q.year = schdl.quarters[quarter].year.get() for course in range(0, len(schdl.quarters[quarter].courses)): new_c = schedule.Course() new_c.id = schdl.quarters[quarter].courses[course].id.get() new_c.title = schdl.quarters[quarter].courses[course].title.get() new_c.description = schdl.quarters[quarter].courses[ course].description.get() new_q.add_course(new_c) finalS.add_quarter(new_q) return finalS
def testDoWork(): tr = os.environ.get('THRILLE_ROOT') test_src = os.path.join(tr, "tests", "fwdrev", "chess", "01.sched") assert os.path.exists(test_src) test_sched = schedule.Schedule(test_src) test_el = SearchStackElement(test_sched.schedule[2], False) try: test_el.doWork() except AssertionError: pass else: assert False test_el = SearchStackElement(test_sched.schedule[2], True) test_el.doWork() assert test_el.chosen == "4" assert len(test_el.done) == 1 assert test_el.done[0] == "3" assert len(test_el.todo) == 2 assert test_el.todo[0] == "0" assert test_el.todo[1] == "2" test_el = SearchStackElement(test_sched.schedule[1], False) test_el.doWork() assert test_el.chosen == "1" assert len(test_el.done) == 1 assert test_el.done[0] == "0" assert len(test_el.todo) == 0 return 1
def testCalculatePreemptions(): tr = os.environ.get('THRILLE_ROOT') test_src = os.path.join(tr, "tests", "fwdrev", "chess", "02.sched") assert os.path.exists(test_src) test_sched = schedule.Schedule(test_src) my_stack = ChessSearchStack(0, ["0x100"]).generateSearchStack(1, test_sched) my_stack.calculatePreemptions() assert my_stack.current_preempts == 1 my_stack.stack[0].chosen = "0" my_stack.calculatePreemptions() assert my_stack.current_preempts == 0 my_stack.stack[0].chosen = "2" my_stack.preempt_bound = 0 try: my_stack.calculatePreemptions() except AssertionError: pass else: assert False return 1
def test_sched(self): sched = schedule.Schedule([ ["Communicate", 'daily', 3, 15], ["TakeMeasurement", 'minutes', 30, 0], ]) tt = parse_time("2020-08-27 01:53:20") self.assertEqual(sched.check(tt), []) self.assertEqual(sched.next(tt), [ [parse_time("2020-08-27 02:00:00"), "TakeMeasurement"], [parse_time("2020-08-27 03:15:00"), "Communicate"], ]) tt = parse_time("2020-08-27 03:00:00") self.assertEqual(sched.check(tt), ["TakeMeasurement"]) self.assertEqual(sched.next(tt), [ [parse_time("2020-08-27 03:15:00"), "Communicate"], [parse_time("2020-08-27 03:30:00"), "TakeMeasurement"], ]) tt = parse_time("2020-08-27 03:15:00") self.assertEqual(sched.check(tt), ["Communicate"]) self.assertEqual(sched.next(tt), [ [parse_time("2020-08-27 03:30:00"), "TakeMeasurement"], [parse_time("2020-08-28 03:15:00"), "Communicate"], ])
async def root(ws, _): print("New Client.") while True: try: string_data = await ws.recv() except websockets.exceptions.ConnectionClosed: print("Client closed connection.") break json_data = json.loads(string_data) personnel = [] for n in json_data: days = [] for i in range(28): days.append(n[str(i)]) personnel.append( staff.Staff(n['First'], n['Last'], n['Seniority'], n['WeekendType'], n['Charge'], n['Vent'], days)) print("\nMaking schedule.\n") s = schedule.Schedule(personnel) s.gen_schedule() print("Checking schedule for penalties.\n") s.check_schedule() print("Sending to client.\n") await ws.send(json.dumps(s.json_representation()))
def simplify(self, debug=True): if self.start_schedule.error is None: return self.start_schedule last_sched = schedule.Schedule() current_sched = self.start_schedule.cloneThyself() i = 0 while current_sched.getContextSwitches( ) != last_sched.getContextSwitches(): if i == 0: self.printScheduleInfo(current_sched) tmp_sched = current_sched rtmp_sched = self.blockRemoveDebug(tmp_sched, debug) ftmp_sched = self.simplifyForwardTwoStage(rtmp_sched) self.printEffect("Forward Consolidation2", rtmp_sched, ftmp_sched) btmp_sched = self.simplifyBackward(ftmp_sched) self.printEffect("Backward Consolidation", ftmp_sched, btmp_sched) last_sched = current_sched current_sched = btmp_sched i += 1 self.iterations = i assert current_sched.error == self.start_schedule.error tmp_error = self.testScheduleStrict(current_sched).error assert tmp_error == self.start_schedule.error self.ensureSanity(current_sched) return current_sched
def genSchedule(self, request=True, respond=True): ''' generate a schedule for this human signoff ''' sched = schedule.Schedule() if request: request_dt = max( 0, random.normalvariate(self.requestTimeout, self.requestJitter)) request = schedule.WriteLabel(request_dt, self.graceDBevent, self.request(), gdb_url=self.gdb_url) sched.insert(request) if respond and (random.random() < self.respondProb): respond_dt = max( 0, random.normalvariate(self.respondTimeout, self.respondJitter)) if request: respond_dt = max(request_dt, respond_dt) ### currently, RemoveLable is not implemented... # remove = schedule.RemoveLabel( respond_dt, self.graceDBevent, self.request(), gdb_url=self.gdb_url ) # sched.insert( remove ) respond = schedule.WriteSignoff(respond_dt, self.graceDBevent, self.instrument, self.signoff_type, self.decide(), gdb_url=self.gdb_url) sched.insert(respond) return sched
def testRegenerate(): tr = os.environ.get('THRILLE_ROOT') test_src = os.path.join(tr, "tests", "fwdrev", "chess", "02.sched") assert os.path.exists(test_src) test_sched = schedule.Schedule(test_src) my_stack = \ ChessSearchStack(0, ["0x100"]).generateSearchStack(1, test_sched) gen_sched = copy.deepcopy(test_sched) gen_sched.schedule.pop() gen_sched.schedule.pop() my_stack.pop() my_stack.pop() my_stack.pop() assert len(my_stack) == 1 assert len(gen_sched.schedule) == 1 my_stack.regenerate(gen_sched, test_sched) assert len(my_stack) == 4 assert my_stack.stack[2].isSignal() assert my_stack.stack[3].chosen == "1" return 1
def __init__(self, tr, preemption_bound, addrlist, results, \ initial_schedule, bin, binflags): chess.ChessChecker.__init__(self, tr, preemption_bound, addrlist, \ results, bin, binflags) self.search_stack = \ searchstack.ChessCheckpointedSearchStack(0, self.addrlist) assert os.path.exists(initial_schedule) self.initial_schedule = schedule.Schedule(initial_schedule)
def test_calculateRedZoneScore(self): """ calculateRedZoneScore should return correct value. """ c1_1 = coursedataparser.toClass( "", ("52111", "RedIn", "1", "0", "STAFF", "TuTh 6:10- 7:00", "ICS 189", "", "44", "10/15", "n/a", "9", "0", "A&N", "OPEN")) c1_2 = coursedataparser.toClass( "", ("10010", "OK", "1", "0", "STAFF", "MWF 9:10- 10:00", "ICS 189", "", "44", "10/15", "n/a", "9", "0", "A&N", "OPEN")) c1_3 = coursedataparser.toClass( "", ("11112", "RedIn", "1", "0", "STAFF", "MWF 3:10- 4:00p", "ICS 189", "", "44", "10/15", "n/a", "9", "0", "A&N", "OPEN")) c1_4 = coursedataparser.toClass( "", ("20010", "RedOv", "1", "0", "STAFF", "MWF 4:10- 5:10p", "ICS 189", "", "44", "10/15", "n/a", "9", "0", "A&N", "OPEN")) c1_5 = coursedataparser.toClass( "", ("42111", "RedOv", "1", "0", "STAFF", "TuTh 9:10- 10:30p", "ICS 189", "", "44", "10/15", "n/a", "9", "0", "A&N", "OPEN")) c2_1 = coursedataparser.toClass( "", ("52111", "OK", "1", "0", "STAFF", "TuTh 10:10- 11:00", "ICS 189", "", "44", "10/15", "n/a", "9", "0", "A&N", "OPEN")) c2_2 = coursedataparser.toClass( "", ("10010", "OK", "1", "0", "STAFF", "MWF 9:10- 10:00", "ICS 189", "", "44", "10/15", "n/a", "9", "0", "A&N", "OPEN")) c2_3 = coursedataparser.toClass( "", ("11112", "RedIn", "1", "0", "STAFF", "MWF 3:10- 4:00p", "ICS 189", "", "44", "10/15", "n/a", "9", "0", "A&N", "OPEN")) c2_4 = coursedataparser.toClass( "", ("20010", "RedOv", "1", "0", "STAFF", "MWF 4:10- 5:10p", "ICS 189", "", "44", "10/15", "n/a", "9", "0", "A&N", "OPEN")) c2_5 = coursedataparser.toClass( "", ("42111", "RedOv", "1", "0", "STAFF", "TuTh 9:10- 10:30p", "ICS 189", "", "44", "10/15", "n/a", "9", "0", "A&N", "OPEN")) schedule1 = schedule.Schedule([c1_1, c1_2, c1_3, c1_4, c1_5]) schedule2 = schedule.Schedule([c2_1, c2_2, c2_3, c2_4, c2_5]) schedules = [schedule1, schedule2] redZones = [ coursedataparser.toClassTime("1:00- 9:00"), coursedataparser.toClassTime("3:00- 5:00p"), coursedataparser.toClassTime("10:00- 11:00p") ] self.assertEqual(schedule1.calculateRedZoneScore(redZones), -6) self.assertEqual(schedule2.calculateRedZoneScore(redZones), -4)
def genSchedule(self, directory='.', lvem=True): ''' generate a schedule for Bayestar ''' sched = schedule.Schedule() if random.random() < self.startProb: start_dt = max( 0, random.normalvariate(self.startTimeout, self.startJitter)) message = 'BayesWaveBurst launched' sched.insert( schedule.WriteLog(start_dt, self.graceDBevent, message, gdb_url=self.gdb_url)) if random.random() < self.finishProb: finish_dt = max( start_dt, random.normalvariate(self.finishTimeout, self.finishJitter)) for message in [ 'BWB Follow-up results', 'BWB parameter estimation', 'BWB Bayes Factors' ]: sched.insert( schedule.WriteLog(finish_dt, self.graceDBevent, message, tagname=['pe'], gdb_url=self.gdb_url)) if random.random() < self.skymapProb: skymap_dt = max( finish_dt, random.normalvariate(self.skymapTimeout, self.skymapJitter)) message = 'BWB' fitsname = self.writeFITS(directory=directory) tagname = ['sky_loc'] if lvem: tagname.append('lvem') sched.insert( schedule.WriteLog(skymap_dt, self.graceDBevent, message, filename=fitsname, tagname=tagname, gdb_url=self.gdb_url)) ### add in plotting and skyviewer agenda = PlotSkymaps(self.graceDBevent, timeout=self.plotSkymapTimeout, jitter=self.plotSkymapJitter, probOfSuccess=self.plotSkymapProb, gdb_url=self.gdb_url).genSchedule(fitsname, tagname=tagname) \ + Skyviewer(self.graceDBevent, timeout=self.skyviewerTimeout, jitter=self.skyviewerJitter, probOfSuccess=self.skyviewerProb, gdb_url=self.gdb_url).genSchedule(fitsname, tagname=tagname) agenda.bump(skymap_dt) sched += agenda return sched
def genSchedule(self, directory='.', lvem=True): ''' generate a schedule for Bayestar ''' sched = schedule.Schedule() if random.random() < self.startProb: start_dt = max( 0, random.normalvariate(self.startTimeout, self.startJitter)) for message in [ 'INFO:BAYESTAR:by your command...', 'INFO:BAYESTAR:starting sky localization' ]: sched.insert( schedule.WriteLog(start_dt, self.graceDBevent, message, gdb_url=self.gdb_url)) if random.random() < self.finishProb: finish_dt = max( start_dt, random.normalvariate(self.finishTimeout, self.finishJitter)) message = 'INFO:BAYESTAR:sky localization complete' sched.insert( schedule.WriteLog(finish_dt, self.graceDBevent, message, gdb_url=self.gdb_url)) if random.random() < self.skymapProb: skymap_dt = max( finish_dt, random.normalvariate(self.skymapTimeout, self.skymapJitter)) message = 'INFO:BAYESTAR:uploaded sky map' fitsname = self.writeFITS(directory=directory) tagname = ['sky_loc'] if lvem: tagname.append('lvem') sched.insert( schedule.WriteLog(skymap_dt, self.graceDBevent, message, filename=fitsname, tagname=tagname, gdb_url=self.gdb_url)) ### add in plotting and skyviewer agenda = PlotSkymaps(self.graceDBevent, timeout=self.plotSkymapTimeout, jitter=self.plotSkymapJitter, probOfSuccess=self.plotSkymapProb, gdb_url=self.gdb_url).genSchedule(fitsname, tagname=tagname) \ + Skyviewer(self.graceDBevent, timeout=self.skyviewerTimeout, jitter=self.skyviewerJitter, probOfSuccess=self.skyviewerProb, gdb_url=self.gdb_url).genSchedule(fitsname, tagname=tagname) agenda.bump(skymap_dt) sched += agenda return sched
def __init__(self): self.schedule = schedule.Schedule() self.street = location.Location(name="street", description="You are outside.") self.hero = actor.Hero(self.street, name="john", sched=self.schedule) self.parser = self.hero.ai self.hero.spells_known = {spells.Shock, spells.Fireball} phrase.QuitPhrase(self.parser, ["quit", "exit"]) phrase.InventoryPhrase(self.parser, ["i", "inventory"])
def create_schedule(self): games_data = self.schedule_data['matches'] schedule = s.Schedule() for game_data in games_data: if game_data['status'] != 'FINISHED': schedule.add_game(game_data['homeTeam']['name'], game_data['awayTeam']['name']) return schedule
def genSchedule(self): sched = schedule.Schedule() if random.random() < self.probOfReport: sched.insert( schedule.WriteLog( max(0, random.normalvariate(self.timeout, self.jitter)), self.graceDBevent, self.genMessage(), gdb_url=self.gdb_url, )) return sched
def get_optimal_schedules(opt_dir): assert os.path.exists(opt_dir) schedule_list = [] for file in os.listdir(opt_dir): if "trace" in file: trace_path = os.path.join(opt_dir, file) tmp_sched = schedule.Schedule(trace_path) for s in schedule_list: assert s.error != tmp_sched.error schedule_list.append(tmp_sched) return schedule_list
def genSchedule(self, directory='.', lvem=True): ''' generate a schedule for Bayestar ''' sched = schedule.Schedule() if random.random() < self.startProb: start_dt = max( 0, random.normalvariate(self.startTimeout, self.startJitter)) message = 'LALInference online estimation started' sched.insert( schedule.WriteLog(start_dt, self.graceDBevent, message, gdb_url=self.gdb_url)) if random.random() < self.finishProb: finish_dt = max( start_dt, random.normalvariate(self.finishTimeout, self.finishJitter)) message = 'LALInference online estimation finished' filename = self.writeDat(directory=directory) sched.insert( schedule.WriteLog(finish_dt, self.graceDBevent, message, gdb_url=self.gdb_url)) if random.random() < self.skymapProb: skymap_dt = max( finish_dt, random.normalvariate(self.skymapTimeout, self.skymapJitter)) message = 'LALInference' fitsname = self.writeFITS(directory=directory) tagname = ['sky_loc'] if lvem: tagname.append('lvem') sched.insert( schedule.WriteLog(skymap_dt, self.graceDBevent, message, filename=fitsname, tagname=tagname, gdb_url=self.gdb_url)) ### add in plotting and skyviewer agenda = PlotSkymaps(self.graceDBevent, timeout=self.plotSkymapTimeout, jitter=self.plotSkymapJitter, probOfSuccess=self.plotSkymapProb, gdb_url=self.gdb_url).genSchedule(fitsname, tagname=tagname) \ + Skyviewer(self.graceDBevent, timeout=self.skyviewerTimeout, jitter=self.skyviewerJitter, probOfSuccess=self.skyviewerProb, gdb_url=self.gdb_url).genSchedule(fitsname, tagname=tagname) agenda.bump(skymap_dt) sched += agenda return sched
def genSchedule(self, fits, tagname=['sky_loc']): sched = schedule.Schedule() if random.random() < self.prob: sched.insert( schedule.WriteLog(max( 0, random.normalvariate(self.timeout, self.jitter)), self.graceDBevent, self.genMessage(), filename=self.genJSON(fits), tagname=tagname, gdb_url=self.gdb_url)) return sched
def testGenerateSearchStack(): tr = os.environ.get('THRILLE_ROOT') test_src = os.path.join(tr, "tests", "fwdrev", "chess", "02.sched") assert os.path.exists(test_src) test_sched = schedule.Schedule(test_src) my_stack = ChessSearchStack(0, ["0x100"]).generateSearchStack(1, test_sched) assert my_stack.preempt_bound == 1 assert my_stack.current_preempts == 1 assert my_stack.addrlist == ["0x100"] assert len(my_stack.stack) == 4 return 1
def testScheduleRelaxed(self, sched): if sched == schedule.Schedule(): self.empty_schedules += 1 return sched # timeouts time_start = time.time() mysched = self.testScheduleWithThriller(sched, self.relaxedserial) time_end = time.time() time_diff = time_end - time_start if time_diff > 35: self.time_fails += 1 return schedule.Schedule() if mysched.error is None: self.no_bug_count += 1 else: if mysched.error == self.start_schedule.error: self.our_bug_count += 1 else: self.other_bug_count += 1 self.executions += 1 return mysched
def simplifyForwardFixpoint(self, sched, debug): j = 0 for_last = schedule.Schedule() for_current = sched while for_last != for_current: for_last = for_current for_current = self.simplifyForward(for_current) for_current = self.preemptExtendSimple(for_current) j += 1 if debug: self.printEffect("Forward Consolidation", \ sched , for_current) print "\t\tIterations until forward simplification", print "hit a fix point:", j return for_current
def simplifyBackwardFixpoint(self, sched, debug): j = 0 back_last = schedule.Schedule() back_current = sched while back_last != back_current: back_last = back_current back_current = self.simplifyBackward(back_current) back_current = self.preemptExtendSimple(back_current) j += 1 if debug: self.printEffect("Backward Consolidation", \ sched, back_current) print "\t\tIterations until backward simplification", print "hit a fix point:", j return back_current
def test_getClassCodes(self): """ Schedule should return correct class codes. """ classRawTuple1 = ("10000", "LEC", "1", "0", "STAFF", "MWF 8:00- 9:50", "ICS 189", "", "44", "10/15", "n/a", "9", "0", "A&N", "OPEN") classRawTuple2 = ("20000", "LEC", "2", "0", "STAFF", "MWF 1:00- 2:50p", "ICS 180", "", "44", "10/15", "n/a", "9", "0", "A&N", "OPEN") sched = schedule.Schedule([ coursedataparser.toClass("", classRawTuple1), coursedataparser.toClass("", classRawTuple2) ]) self.assertEqual(sched.getClassCodes(), [10000, 20000])
def get_schedule(sid, pin, Next): """ Function to set our schedule variable. Get current schedule if next schedule flag not set """ login_number = 2 term = '' for i in range(login_number): html = fetch_html.setup_schedule_page() title = parse_html.get_page_title(html) if title != 'Login': if title == 'Select Term ': term = parse_html.get_current_term(html) if Next: term = to_next_term(term) else: courses = parse_html.get_current_classes(html) return schedule.Schedule(html, courses, term) else: login(sid, pin) continue html = fetch_html.get_schedule(term) courses = parse_html.get_current_classes(html) return schedule.Schedule(html, courses, term)
def __init__(self, use_web_output=False, save_manager=None): super().__init__(save_manager=save_manager) self.schedule = schedule.Schedule() world_map = wide.Overworld( sched=self.schedule, width=50, height=50, ) world_events = agent.WorldEvents(world_map) town_n = 10 cave_n = 24 caves = [ sites.RuneCave.at_point(location=world_map, coordinates=world_map.random_point(), direction=direction.down, landmark_name=namemaker.make_name() + "cave") for i in range(cave_n) ] towns = [ agent.Town( name=namemaker.make_name(), location=world_map, coordinates=world_map.random_point(), ) for i in range(town_n) ] for i in range(20): testing_shopkeeper_agent = agent.ShopkeeperAgent.in_world( world_map) self.schedule.run_game(250 * day) self.actor = make_player( location=world_map, postures=(posture.random_posture(), ), coordinates=world_map.random_point(), landmarks=set(town.site.landmark for town in towns), use_web_output=use_web_output, ) if self.save_manager: phrase.SpecialPhrase(callback=self.save, parser=self.actor.ai, synonyms=["<<save>>"])
def buildSchedule(self): return_schedule = schedule.Schedule() return_schedule.error = None return_schedule.addrlist = self.addrlist tmp_sched = [x.makeSchedulePoint() for x in self.stack] while len(tmp_sched) > 0: elem = tmp_sched.pop(0) if elem.isSignal(): if len(tmp_sched) > 0: following_elem = tmp_sched.pop(0) assert following_elem.signalled == elem.signalled assert following_elem.caller == elem.caller elem = following_elem else: elem.chosen = None return_schedule.schedule.append(elem) return return_schedule
def testIsPreempt(): tr = os.environ.get('THRILLE_ROOT') test_src = os.path.join(tr, "tests", "fwdrev", "chess", "01.sched") assert os.path.exists(test_src) test_sched = schedule.Schedule(test_src) test_el = SearchStackElement(test_sched.schedule[0], False) assert test_el.isPreempt() test_el = SearchStackElement(test_sched.schedule[1], False) assert not test_el.isPreempt() test_el = SearchStackElement(test_sched.schedule[2], True) assert not test_el.isPreempt() test_el = SearchStackElement(test_sched.schedule[2], False) assert not test_el.isPreempt() return 1
def testChosenIsDone(): tr = os.environ.get('THRILLE_ROOT') test_src = os.path.join(tr, "tests", "fwdrev", "chess", "01.sched") assert os.path.exists(test_src) test_sched = schedule.Schedule(test_src) test_el = SearchStackElement(test_sched.schedule[0], False) assert len(test_el.done) == 1 test_el.chosenIsDone() assert len(test_el.done) == 1 test_el.chosen = "0" assert "0" not in test_el.done test_el.chosenIsDone() assert "0" in test_el.done return 1