@@ -26,6 +26,7 @@ def __init__(self, config_name='alas'):
2626 # Failure count of tasks
2727 # Key: str, task name, value: int, failure count
2828 self .failure_record = {}
29+ self .first_check = True
2930
3031 @cached_property
3132 def config (self ):
@@ -62,11 +63,11 @@ def checker(self):
6263 logger .exception (e )
6364 exit (1 )
6465
65- def run (self , command , skip_first_screenshot = False ):
66+ def run (self , command , * args , skip_first_screenshot = False , ** kwargs ):
6667 try :
6768 if not skip_first_screenshot :
6869 self .device .screenshot ()
69- self . __getattribute__ ( command )()
70+ getattr ( self , command )(* args , ** kwargs )
7071 return True
7172 except TaskEnd :
7273 return True
@@ -90,47 +91,42 @@ def run(self, command, skip_first_screenshot=False):
9091 self .config .task_call ('Restart' )
9192 self .device .sleep (10 )
9293 return False
93- except GamePageUnknownError :
94+ except GamePageUnknownError as e :
9495 logger .info ('Game server may be under maintenance or network may be broken, check server status now' )
9596 self .checker .check_now ()
9697 if self .checker .is_available ():
97- logger .critical ('Game page unknown' )
98- self .save_error_log ()
99- handle_notify (
100- self .config .Error_OnePushConfig ,
101- title = f"Alas <{ self .config_name } > crashed" ,
102- content = f"<{ self .config_name } > GamePageUnknownError" ,
103- )
104- exit (1 )
105- else :
106- self .checker .wait_until_available ()
107- return False
98+ self .crash_exit (e , save = True )
99+ self .checker .wait_until_available ()
100+ return False
108101 except ScriptError as e :
109- logger .exception (e )
110- logger .critical ('This is likely to be a mistake of developers, but sometimes just random issues' )
111- handle_notify (
112- self .config .Error_OnePushConfig ,
113- title = f"Alas <{ self .config_name } > crashed" ,
114- content = f"<{ self .config_name } > ScriptError" ,
115- )
116- exit (1 )
117- except RequestHumanTakeover :
118- logger .critical ('Request human takeover' )
119- handle_notify (
120- self .config .Error_OnePushConfig ,
121- title = f"Alas <{ self .config_name } > crashed" ,
122- content = f"<{ self .config_name } > RequestHumanTakeover" ,
123- )
124- exit (1 )
102+ self .crash_exit (e , 'This is likely to be a mistake of developers, but sometimes just random issues' ,
103+ log_exc = True )
104+ except ALASBaseError as e :
105+ if not self .device .emulator_check ():
106+ self .reboot ()
107+ return False
108+ self .crash_exit (e )
125109 except Exception as e :
110+ if not self .device .emulator_check ():
111+ self .reboot ()
112+ return False
113+ self .crash_exit (e , log_exc = True , save = True )
114+
115+ def crash_exit (self , e , * args , log_exc = False , save = False , msg = '' ):
116+ if log_exc :
126117 logger .exception (e )
118+ else :
119+ logger .critical (e )
120+ for arg in args :
121+ logger .critical (arg )
122+ if save :
127123 self .save_error_log ()
128- handle_notify (
129- self .config .Error_OnePushConfig ,
130- title = f"Alas <{ self .config_name } > crashed" ,
131- content = f"<{ self .config_name } > Exception occured" ,
132- )
133- exit (1 )
124+ handle_notify (
125+ self .config .Error_OnePushConfig ,
126+ title = f"Alas <{ self .config_name } > crashed" ,
127+ content = f"<{ self .config_name } > { e . __class__ . __name__ } { msg } "
128+ )
129+ exit (1 )
134130
135131 def save_error_log (self ):
136132 """
@@ -162,7 +158,16 @@ def save_error_log(self):
162158 with open (f'{ folder } /log.txt' , 'w' , encoding = 'utf-8' ) as f :
163159 f .writelines (lines )
164160
165- def restart (self ):
161+ def reboot (self , use_log = True ):
162+ if use_log :
163+ logger .warning ('Emulator is not running' )
164+ self .device .emulator_stop ()
165+ self .device .emulator_start ()
166+ del_cached_property (self , 'config' )
167+
168+ def restart (self , reboot = False ):
169+ if reboot :
170+ self .reboot (use_log = False )
166171 from module .handler .login import LoginHandler
167172 LoginHandler (self .config , device = self .device ).app_restart ()
168173
@@ -455,42 +460,76 @@ def get_next_task(self):
455460 if self .config .task .command != 'Alas' :
456461 release_resources (next_task = task .command )
457462
458- if task .next_run > datetime .now ():
459- logger .info (f'Wait until { task .next_run } for task `{ task .command } `' )
460- self .is_first_task = False
461- method = self .config .Optimization_WhenTaskQueueEmpty
462- if method == 'close_game' :
463- logger .info ('Close game during wait' )
464- self .device .app_stop ()
465- release_resources ()
466- self .device .release_during_wait ()
467- if not self .wait_until (task .next_run ):
468- del_cached_property (self , 'config' )
469- continue
470- if task .command != 'Restart' :
471- self .run ('start' )
472- elif method == 'goto_main' :
473- logger .info ('Goto main page during wait' )
474- self .run ('goto_main' )
475- release_resources ()
476- self .device .release_during_wait ()
477- if not self .wait_until (task .next_run ):
478- del_cached_property (self , 'config' )
479- continue
480- elif method == 'stay_there' :
481- logger .info ('Stay there during wait' )
482- release_resources ()
483- self .device .release_during_wait ()
484- if not self .wait_until (task .next_run ):
485- del_cached_property (self , 'config' )
486- continue
487- else :
488- logger .warning (f'Invalid Optimization_WhenTaskQueueEmpty: { method } , fallback to stay_there' )
489- release_resources ()
490- self .device .release_during_wait ()
491- if not self .wait_until (task .next_run ):
492- del_cached_property (self , 'config' )
493- continue
463+ if task .next_run <= datetime .now ():
464+ break
465+
466+ logger .info (f'Wait until { task .next_run } for task `{ task .command } `' )
467+ self .is_first_task = False
468+
469+ method : str = self .config .Optimization_WhenTaskQueueEmpty
470+ remainingtime : float = (task .next_run - datetime .now ()).total_seconds () / 60
471+ buffertime : int = self .config .Optimization_ProcessBufferTime
472+ if (
473+ method == 'stop_emulator' and
474+ self .device .emulator_check () and
475+ remainingtime <= buffertime
476+ ):
477+ method = self .config .Optimization_BufferMethod
478+ logger .info (
479+ f"The time to next task `{ task .command } ` is { remainingtime :.2f} minutes, "
480+ f"less than { buffertime } minutes, fallback to \" { method } \" "
481+ )
482+
483+ if method == 'close_game' :
484+ logger .info ('Close game during wait' )
485+ self .device .app_stop ()
486+ release_resources ()
487+ self .device .release_during_wait ()
488+ if not self .wait_until (task .next_run ):
489+ del_cached_property (self , 'config' )
490+ continue
491+ if task .command != 'Restart' :
492+ self .run ('start' )
493+ elif method == 'goto_main' :
494+ logger .info ('Goto main page during wait' )
495+ self .run ('goto_main' )
496+ release_resources ()
497+ self .device .release_during_wait ()
498+ if not self .wait_until (task .next_run ):
499+ del_cached_property (self , 'config' )
500+ continue
501+ elif method == 'stay_there' :
502+ logger .info ('Stay there during wait' )
503+ release_resources ()
504+ self .device .release_during_wait ()
505+ if not self .wait_until (task .next_run ):
506+ del_cached_property (self , 'config' )
507+ continue
508+ elif method == 'stop_emulator' :
509+ logger .info ('Stop emulator during wait' )
510+ self .device .emulator_stop ()
511+ release_resources ()
512+ self .device .release_during_wait ()
513+ if not self .wait_until (task .next_run ):
514+ del_cached_property (self , 'config' )
515+ method : str = self .config .Optimization_WhenTaskQueueEmpty
516+ if (
517+ not self .device .emulator_check () and
518+ method != 'stop_emulator'
519+ ):
520+ self .run ('reboot' , skip_first_screenshot = True , use_log = False )
521+ continue
522+ if not self .device .emulator_check ():
523+ self .run ('reboot' , skip_first_screenshot = True , use_log = False )
524+ self .run ('start' , skip_first_screenshot = True )
525+ else :
526+ logger .warning (f'Invalid Optimization_WhenTaskQueueEmpty: { method } , fallback to stay_there' )
527+ release_resources ()
528+ self .device .release_during_wait ()
529+ if not self .wait_until (task .next_run ):
530+ del_cached_property (self , 'config' )
531+ continue
532+
494533 break
495534
496535 AzurLaneConfig .is_hoarding_task = False
@@ -502,11 +541,10 @@ def loop(self):
502541
503542 while 1 :
504543 # Check update event from GUI
505- if self .stop_event is not None :
506- if self .stop_event .is_set ():
507- logger .info ("Update event detected" )
508- logger .info (f"Alas [{ self .config_name } ] exited." )
509- break
544+ if self .stop_event is not None and self .stop_event .is_set ():
545+ logger .info ("Update event detected" )
546+ logger .info (f"Alas [{ self .config_name } ] exited." )
547+ break
510548 # Check game server maintenance
511549 self .checker .wait_until_available ()
512550 if self .checker .is_recovered ():
@@ -517,10 +555,14 @@ def loop(self):
517555 del_cached_property (self , 'config' )
518556 logger .info ('Server or network is recovered. Restart game client' )
519557 self .config .task_call ('Restart' )
520- # Get task
521- task = self .get_next_task ()
522558 # Init device and change server
523559 _ = self .device
560+ # Get task
561+ task = self .get_next_task ()
562+ if self .first_check :
563+ if not self .device .emulator_check ():
564+ self .run ('reboot' , skip_first_screenshot = True )
565+ self .first_check = False
524566 self .device .config = self .config
525567 # Skip first restart
526568 if self .is_first_task and task == 'Restart' :
@@ -548,13 +590,8 @@ def loop(self):
548590 "Please read the help text of the options." )
549591 logger .critical ("Possible reason #2: There is a problem with this task. "
550592 "Please contact developers or try to fix it yourself." )
551- logger .critical ('Request human takeover' )
552- handle_notify (
553- self .config .Error_OnePushConfig ,
554- title = f"Alas <{ self .config_name } > crashed" ,
555- content = f"<{ self .config_name } > RequestHumanTakeover\n Task `{ task } ` failed 3 or more times." ,
556- )
557- exit (1 )
593+ self .crash_exit (RequestHumanTakeover ('Request human takeover' ),
594+ msg = f"\n Task `{ task } ` failed 3 or more times." )
558595
559596 if success :
560597 del_cached_property (self , 'config' )
0 commit comments