From 76eeba667f15c0c281bf79198737704e2319bd45 Mon Sep 17 00:00:00 2001 From: sui-feng-cb <2518179942@qq.com> Date: Tue, 17 Feb 2026 20:58:33 +0800 Subject: [PATCH] Add: Island Pearl Daemon --- alas.py | 4 + assets/cn/island/ISLAND_FRIEND.png | Bin 0 -> 4000 bytes assets/cn/island/ISLAND_FRIEND_CHECK.png | Bin 0 -> 5332 bytes assets/cn/island/ISLAND_FRIEND_LEAVE.png | Bin 0 -> 3348 bytes assets/cn/island/ISLAND_FRIEND_SCROLL.png | Bin 0 -> 3948 bytes assets/cn/island/PEARL_CHECK.png | Bin 0 -> 9129 bytes assets/cn/island/PEARL_ENTER.png | Bin 0 -> 4229 bytes assets/cn/island/PEARL_PRICE_OCR.png | Bin 0 -> 4126 bytes assets/cn/island/TEMPLATE_FRIEND_VISIT.png | Bin 0 -> 1528 bytes config/template.json | 5 + module/config/argument/args.json | 10 + module/config/argument/menu.json | 1 + module/config/argument/task.yaml | 2 + module/config/i18n/en-US.json | 4 + module/config/i18n/ja-JP.json | 4 + module/config/i18n/zh-CN.json | 4 + module/config/i18n/zh-TW.json | 4 + module/device/control.py | 5 +- module/device/method/minitouch.py | 5 +- module/island/assets.py | 8 + module/island/pearl_daemon.py | 277 +++++++++++++++++++++ module/island/ui.py | 64 ++++- module/submodule/utils.py | 1 + 23 files changed, 394 insertions(+), 4 deletions(-) create mode 100644 assets/cn/island/ISLAND_FRIEND.png create mode 100644 assets/cn/island/ISLAND_FRIEND_CHECK.png create mode 100644 assets/cn/island/ISLAND_FRIEND_LEAVE.png create mode 100644 assets/cn/island/ISLAND_FRIEND_SCROLL.png create mode 100644 assets/cn/island/PEARL_CHECK.png create mode 100644 assets/cn/island/PEARL_ENTER.png create mode 100644 assets/cn/island/PEARL_PRICE_OCR.png create mode 100644 assets/cn/island/TEMPLATE_FRIEND_VISIT.png create mode 100644 module/island/pearl_daemon.py diff --git a/alas.py b/alas.py index a6ce89ba6..b71fa27ee 100644 --- a/alas.py +++ b/alas.py @@ -434,6 +434,10 @@ class AzurLaneAutoScript: from module.storage.box_disassemble import StorageBox StorageBox(config=self.config, device=self.device, task="BoxDisassemble").run() + def island_pearl(self): + from module.island.pearl_daemon import IslandPearl + IslandPearl(config=self.config, device=self.device, task="IslandPearl").run() + def azur_lane_uncensored(self): from module.daemon.uncensored import AzurLaneUncensored AzurLaneUncensored(config=self.config, device=self.device, task="AzurLaneUncensored").run() diff --git a/assets/cn/island/ISLAND_FRIEND.png b/assets/cn/island/ISLAND_FRIEND.png new file mode 100644 index 0000000000000000000000000000000000000000..c820c720dfa4ad274cdc6981e8bf56fc1d88b3e1 GIT binary patch literal 4000 zcmeI#|3A}t902eS@--vLsg!cb6+2&gD9oJZLACNF-OabKxjRt|CE6FZ6&@ZTTpTr) z%C~No-I>mpnXOy1)0%H1)i#VGq&eTlkQ@KQ{cw-RUcbEGKfE9B_v`h1ydLkz`+fVo z|7noHUIPFCK=3o(7XUz8HP!6V(^L&751iEi0OJ_AH|z(@yBVo8P8_mV7j?%qCCdc1 zEy~yNaPj%GZ*w1klUs<&26H^(<@pk;;^&z=yc}WMOfv(+t%4eU;=@Ih8hC3v#xnC4 z${~v`A6L(zc@rPi_Ucdzs0GvlY5}!?T0kwJ7Wi)jI0~hYIRMPQudi>HtW+gT2?TRV zX=y>b7@=m_g)wi-)_d!shNce-PJEz2A(V1o8(w2xW$ZV8I!vs%2EDQv(3ZC1<*B9V z2mlw&NyhxKg6uIWl{`Mqjnu!X3PGch08kFDoPHr3<)6Le8K?^fPXMQV~gvl6*Njc^G1f zF^p5K#Y9%ZEMGGtrJ+FEm7*GWS>iO#38`GVAmcI6UPfB;6*u{T8aluT7L>}MIJ3Zl z*uZzJ<1B2-Mk>)WGofh$Ys#~FOX~y6k)U~~VD!zb+45Ce6#|q_xZ6f#RxF9|V{v8K z#;3Tw59>ZZFcYl=Z%-HNph<*PT>thyhb>*{(%h#e_DsyAM=k~_2Mx2`LWYnf2v2=k zs(*q=K0Lg?k=|;8sX|^?{R09%PfZEN#UEB!4C;6Hcg6TP(V0z5_sQ5oIhytfO@0!W zW}M;Eu1mVW(@^D8+OI5jAjvZwxIyvPdgydM%LQW#kG>yF4=qLeWeQw=4S5W z%gRI#v{556-C$>vrr-gnWwU_s7;5JY7gdq?`m$3w=rzPTWUZ8`~I^oz$1|>n3 z=wknL`s4dHSG$^&39 z!=(MEV|dH7*yOnca+?LnMZwQ8H?0yUt}d@!Z^>{b0fqpl#Ck*tS$~aa3=!ftQt;=< zWALlaM<4TAo-^w*h|C2G2PBt970b)JqfsXT9RL+qUT%&EehQMB5i2z%?e?je`Q~Wy zkt^vSbYF9MSGenF7na&IYvN)CqX+3IPX#hHhz`?+0+o$bts*N^quR)i4;Pw4N( zxPJdo)y6n0qjl>R_t~}K!Kvrq8B5wYB6*?(VTQR^z3y$Li&ay#aWK#a#Lk@at7%C*ONL5~!dY*WJJ3q`OJUdJCCuAA;|fK+>9vD#g?8N@;7 zvzo!|f%u5AJEMh}g>q|bNypXZBZ9F`Ty5Pn&0_S4ADb%$Pk!5_L73dP1vIi@Nuswy i6#<*K!v7=Isy8&hPVXFz?x?WZ%oy(D?_KYOy7e!Iw!uOG literal 0 HcmV?d00001 diff --git a/assets/cn/island/ISLAND_FRIEND_CHECK.png b/assets/cn/island/ISLAND_FRIEND_CHECK.png new file mode 100644 index 0000000000000000000000000000000000000000..83eca57dbf000064acce6bd40bb425b8c18464c9 GIT binary patch literal 5332 zcmeH|`#%%-%5`}ujjUY`s{C`3j|NeTb} z$XMU7bOr#v6L0tbd1$|Q`59=l4*)n`WNm5g8be*4MLo@B+?HJ9BqE{_#s+<1#tSXV z$M-#xGJpTQmDKS!c>STuYu*PDfI3x#}B@fAZ&?c#+Gto3lm?Wh*!b1 zv*P>wk4uO;Bsh4o#cFWk;q6?@l>;l}8ZSs}&{yKr$w0 zP2O|ZMp5r_rjGmDr5ZG@85cZF3}=Sx=-b;m?1KCKs$_bMT6!~# zYo54nq;ffYNeJwPDK?VM!=~AiY8}9^!7k>&-OH1r6@(WDW6u#zr^1>|P4eT!Z*Bl1g-Vc_n_kt>=BB%Db)F5u{Nd}@ zHRw5g_jLh)vjDvh5nQcm$+u5A4Qd2lxBB z{p5WNJ~!LO$sb^}s3!gAuLi>lFF?DQ6?3}*6hnu*0|dDIQPYynr=bj z?gT=-h*iX~N7xJ(O`FLj!+goN8h&#xj^nhqqkMcq^#SN7xpQWeP3j1}e(Jyx0KiU7 zuj?dX*Jpi8WPHiFE=^vf7`E+KbGFdVz|hdjsaCxx7^->W1~DaE)Smg@!u*;P5ScH(&7dX2tRjj_HySqgBxSaMOz(@2yC=5xUSND$aM`w$E<>Dsz2*nHvHEZx+Q#Oi7{B< z)p&b3e0VhpxhnMLNq(^Jh~3D|7Q61CPu0YyLcRLg(0j^`bar+&erf3w<#d3gyMi>y zlrQ^jivgle`{MAu(PG6FXVC%51+HIAqT=JiWinpB%&Hz1+=&0d*q~VI;kD>!2cqK) zYHckgH9ZI8!ToYm^H*xKXk8S?E1pbu(v5o8RQGR7XBU^ag>oybTm9quF_zdtFDFMv zeh*$AW)cW(rNZ@aRA|qVM+a49oUGay$XLh+R<@uY^`wIG1&PbxYrTHDuP3_5iJG84tPY=Te zN99IwERG`l#ZI*^%+t(QJ;r>3rIHsSeroVr*pIGDMGV!S93CfT zjdN&x$zM%Jr#ZBK@`_~ATQzO}qOApWp5UftfqjzIWp|T(nn~L{wt*L?-@f7@GRL0v zZN-$o${U?*n`2Sr#2E$nG%nQ>a0S{;NmGBKRGxMg+Lag9p?e71y=WzEfLiHwO_WEJ zC;c9tfE+BHb3FVd-RBG_iWlLnoE)fG)_1}Hede5LtW)?M4N7r;vC$NFC%>8ijYOa5 zMe^i}401KQ3!VEVe8hhVz<1!)7)Bg1$WZ(9$ATMSY&F*Q_7rlzijs!1kTlY^%I)L1 zJuQz7XL^b-_OHU$#hTSRo<=X{@cDBISUqK#c3>0QP&wX;@Jel(LJ@qxm$r|MnRv8( zd#4sS`KBg!5dH=w&IWN9rfPzT8!I|9`8N(aITp=l&BpY=g=>wIc{Yq{{OWF7J*v75 z?$+^JBzM%-@Qt^Z`UwD~+J z@)^{^QGtNl00=sE3IO;%xzIUrl@YZ%b=oRp$!_VLTIOTYqR;}e=;@(d&_*CIKN0;B zZic_Y;nebMTs2tusYVICha-LIk4c^(^QnEmSmfGOk#iqUDGq5(eI2Rj8~71UM_!gA z)spH@V^Gf4Lb3J#wqLgeWW^{#^~ig)7x7zmXUoOO(oQy_lR8}_eg6yf3b1o^+S|6W zSHc>U_tCcz=_w!^u3(;Am|{jP6PcQGN{Wh#LvI&$ROZE&XAJ7_^I98AQ44w5+f%HF z#lP4W&UYH#%=tKJR_)5Pz45Owu;+6!TF*3^fIzZ{Id_Ln+aK#3E^(2&CYfR4plEgx}k%J%LolhLr1&#Fi|j3 zBt=^Erg0f5Db!EFryfw&iYbGItU^2<&y@ywz#4~Fsqu5E=%%3nFI*UD#WWt>i3}_E zu&~H2G}E$C4Qnly{U=q(=|&nXG9Af6bpj3PKJ0kM-A1~I;?!&S|qky^9&oY(&}Ms zyw7BMH3V3pP{hq;7lL@O?~{#zOOZ|9jmY3uPa5$K)8VCH)ni4bqLFI=?VvPN!fIV@ zUWK)~%GNkVmPZ7+A(kD6Swx6%69S&z8r9?(%Ln0^x z_oC+_VJ^_I~_Eiedto6>IJa`585p4);=aWwp#1Z`*WY!s1274QkXxjHnV0?HWGAd|2 zeCt5k4I>sJvOH*a3_@u*OkX#l%okwObBd%Z)@D+6s44IWvC{TxkH8**Jpy|K_6Y0| l*dwq<;QyOIm#9qiUGb&S-gEB`RsB7RwH4H|?wZg2{{j+Gq9gzS literal 0 HcmV?d00001 diff --git a/assets/cn/island/ISLAND_FRIEND_LEAVE.png b/assets/cn/island/ISLAND_FRIEND_LEAVE.png new file mode 100644 index 0000000000000000000000000000000000000000..dba54f65b10527ece3a34d951ed4a165cdfe92ce GIT binary patch literal 3348 zcmeAS@N?(olHy`uVBq!ia0y~yUB9!JY6yXh;6@>avr|+~-j6xN z)Gfil&@QUUcp>FyO>dEIlC*WN0S2YGB5}3KF$98SSpp7;lYlQ zkOtvz>-1)yy|=S?_44KBU2D7<82$)b9XR00)pYm#w=&iF^LNz#o;HhtL4kpJ`TcW! zd(Sa2a2z=BUyH*iv3BjO`SZhh85md+9!yEO`?otpqO`2cOpfvIo14Ls5)2K>pEpP@ zczUGp>+9>E?mhhS<#Ex@n3YqcB`Yd_{=IR-Hk66Mfr0H-+{!Ph6%`hq-|q9vux$0! z&cDA;T6XX3)3yN`3=ID|bT2sk{`n#C=hfBIUokKokiW>t7Ud_AwrltKWs_A-UO676 zZNYIUXyp_?E2~3J4@2fm21nJw6DK^Z_EmhWNlObe9YR@P)TyH(Fd71*Aut*OqaiRF i0;3@?G((_4?I&B+w|x;jO->I$KJaw)b6Mw<&;$T0+Esc0 literal 0 HcmV?d00001 diff --git a/assets/cn/island/ISLAND_FRIEND_SCROLL.png b/assets/cn/island/ISLAND_FRIEND_SCROLL.png new file mode 100644 index 0000000000000000000000000000000000000000..781cfc799837246719dbc32862700e216bad6626 GIT binary patch literal 3948 zcmeHJZERCj7``nX)Rv{4nGCl9*HvYX0V58WqRHK?vOzX09~;q4uOe|HnGQuW77d3* zn=K$)0wO=Qcq1f|fTRSC17j#3F-8-t9|>fv;$kL5G~&nnU`%|^d%}J1J>JqrqrdEr zvv;TG{d%6~J*VA~y2aVPe4nBy*)`SSWr~soraR$v!yj$N5|^R`Zm$Vfu4o_pE;(=O znX+K?f#Zqsz^iNL#@6({-=EcSW_x$#=HtJgU8MM*ol#Mkd=ec0|NMstA7OUe=*U9R1g?2-Wx&?C>C>n6V21Z*jRY{6jlpb!lvL^cItv#4!o( zSRj-D@``n{9rp6nO?INquToP^naOhO^yUHyWuoZx{KhOUsj7TfXnW7f{pd0+8@8K{ ztwe?G2CW%O2Yfp0y;u%QX`taD!xW$#=-US^F)-Q!UjuK8_1asdv=UB^AWN-~3t4HX z?6?tQWR;o>VIpG+vVwN=V*@TIQY~UL`$PO#7j74~ZduNu2nOTZPUge`f^cq(PpI+S zm3&U18e-@A&|%NC_`-$!#N*YIYHJMG+Ky0#6%cRlBM-vTTqXNv}5NNZ@ZWu-^? zlY_)QeM20~^Ubh`D0eK4flVpNVi#%$J8?z?v|YtQ8(XhpBrEy1u%#l$-p@wO%Tmkx zDwmhy`T6_Z&xqo2eY^IsdkX&|jP+5NHWw*55uMG)lhh~VQ9sZz0o1ES@8M`-^Two* z{bX+*YMu=`hgdDsH*f+u@s@pEXptEa{-y5=GZ{i0ue&_SdgFMZj9|Lcg^M` ze}E--dH>P8v8E4k@Qqy%QGemkbW$qTAgHR;`?A61BTofzB1C%{nbuEwMt9_``3AS^Cl&&7#=5(~b;C8Dw%Q=)G@>aoio zE-8srLBEx|eNXuLT#$TDytJ1G)~c^6gZU?$H#nPfYm>{bgF_K|EcuDoB1XNnookBy zfrBF+1Z_I^)LQV0h=?mhlu1ZP>{0H$(_} z{U|gT8A2f=dWOJztjx`yL~LoKgky_JjO=Zs+dXw3?H@^XY-(@Zvfc zMGd=$Hur<(l-Gu-1@Q#La*kBO#jGAp7U*!GNIYnp@SiH;uH2&krqgC~Y|fB+I`9sb|hu6{wS)ZRZw&zFXKOabl7RH@;lW?-|jL?${S(&&<&S_l!t`sxK zk_iwb4zf}MLA{WbCd)74T}Lr=>|F1{A4KBmpcwkDHoTm?EubRWHtH?+49O{Vr76L@ p*hBC3HAZJ{<14eEf`9e%d?H{RZ0+1|xnc#+Q*&=!cz>1N`6n1k*t`G$ literal 0 HcmV?d00001 diff --git a/assets/cn/island/PEARL_CHECK.png b/assets/cn/island/PEARL_CHECK.png new file mode 100644 index 0000000000000000000000000000000000000000..346b3407f14b44d7f4d3fc749af957c5cd17746a GIT binary patch literal 9129 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 Hqi6pQ>f7>? literal 0 HcmV?d00001 diff --git a/assets/cn/island/PEARL_ENTER.png b/assets/cn/island/PEARL_ENTER.png new file mode 100644 index 0000000000000000000000000000000000000000..995aad162bbe5edd5d115cac7b0e665f2949bd17 GIT binary patch literal 4229 zcmeH|=~L6!8pnT$qPby_Rs~v=RBsC*sKhj#AYdaG$_}zbV?+cRORhkWEkdO+j1*8= zEX5coSXyx-fEad3LSm^45F?9#K!LD?Eo38sK-e1Xbf*77-{ibGXU>cBo#*p>zt6cA z;O}7!{TK=WfU%dSTMz&k=#Jn{2w1lrgL#7hz|_~v%>|b-C>h+QPt9SLn_QZygHbv%XK``yw%x9Um7XVOWDK5` zf+|9SjgZuMof@(rGc)swNQj=24uzFhR1`a5lwyYKc9T6#mlo%4H(C0|oem+t4lM+uKdPX#4&V!AS zq3&rQAo4VkI5G7K>-C_=(7f-!={kpkHbF6?@;l1fvXXX|ebQE=R&!Qmseut2Ym*h# zvZ$!2pO$}wqq3f-fvhtB>bP=`=o85GXJ7BnhqQiDYF~0Rb*Znan6-eORkxIKzd#~8 zFHU+Ug`A*AogZL-_wD*kdqHF_u;o2BC*XK@PfwzHCO@d0)0;@4P;kq06$_l1{;*Lt zv)tCo=l5|I60$WM09gPcr3s(Ka{V!HZ?v6RHhn0=F#6*B+ddpYW9ff}ee&8)aPI6MMAlJ^9FNy8h4l7)gN)|y=x|{uQ#o)Q@iTfY^PG} z=Vxie<>&Itsv$f4rPjEhZ4E2C`Hc}!w9Xkt3D6`G>BVdhX>P71b!B1H=U#X4aq-FO z&|sPJx7;>(jkp+O5V?erpHs$ytkW^1yA5E_77_e(fp)$r7IveyTB0s(mo&r-IG0DL*F+-z(@`Fk_==`%+a z36`bW#n*lVoa$=%Ojql~&by#O6U!N${~iX}!goO@W-(SfrgIK@cSKfb<_Cs5J5w54 zoDG{#9kBk8)z#(1#$wmi-E=#=+iYW_2F5tFUe(a>3l^m7Wf}odDv!E=JyM=9!kLr} zvn3JbrAxHVVMJUYsrekY(T2{ERZZZhUt3sPEEo!X$J}nTlM#UWrKc(xz zpRd-)9)&tFncb`flkR6bZAM_DXvxYn#(m(_-+{I+7-(6i)9oZv!d#D1U+dw)!NIq0 zPaS!a?EUIh^pc!r$LPq2Snl$mN#_tba_VB*N#LEOZ=9k~{B&b7QKczc=&4*IQ90a7LqdIc`8iAw^||01zoqDB_ZGZ9c@r?poDq5vgBhu`WRBCS1(| z3(mxzpO>j3OwZNo=JCJwZ|H^f1oQ;-1pY~2ZBx4gTJ+g}!NoGmclTaj`MW*(U-*?j E0dA*6WB>pF literal 0 HcmV?d00001 diff --git a/assets/cn/island/PEARL_PRICE_OCR.png b/assets/cn/island/PEARL_PRICE_OCR.png new file mode 100644 index 0000000000000000000000000000000000000000..8de1ea57ad9dcc8c68ff0dc1cfbc067dd478fa58 GIT binary patch literal 4126 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 eSu&ApUiJ^6 %s, %s' % (point2str(*p1), point2str(*p2), duration)) @@ -107,7 +108,7 @@ class Control(Hermit, Minitouch, Scrcpy, MaaTouch, NemuIpc): return if method == 'minitouch': - self.swipe_minitouch(p1, p2) + self.swipe_minitouch(p1, p2, hold_time=hold_time) elif method == 'uiautomator2': self.swipe_uiautomator2(p1, p2, duration=duration) elif method == 'scrcpy': diff --git a/module/device/method/minitouch.py b/module/device/method/minitouch.py index d97c2ca88..ef726edf9 100644 --- a/module/device/method/minitouch.py +++ b/module/device/method/minitouch.py @@ -679,7 +679,7 @@ class Minitouch(Connection): builder.send() @retry - def swipe_minitouch(self, p1, p2): + def swipe_minitouch(self, p1, p2, hold_time): points = insert_swipe(p0=p1, p3=p2) builder = self.minitouch_builder @@ -689,6 +689,9 @@ class Minitouch(Connection): for point in points[1:]: builder.move(*point).commit().wait(10) builder.send() + + if hold_time > 0: + builder.wait(hold_time) builder.up().commit() builder.send() diff --git a/module/island/assets.py b/module/island/assets.py index 63329a674..71aea6d88 100644 --- a/module/island/assets.py +++ b/module/island/assets.py @@ -7,6 +7,10 @@ from module.base.template import Template GET_ITEMS_ISLAND = Button(area={'cn': (588, 260, 692, 289), 'en': (588, 260, 692, 289), 'jp': (588, 260, 692, 289), 'tw': (588, 260, 692, 289)}, color={'cn': (178, 180, 180), 'en': (149, 151, 152), 'jp': (178, 180, 180), 'tw': (178, 180, 180)}, button={'cn': (0, 263, 129, 555), 'en': (588, 260, 692, 289), 'jp': (0, 263, 129, 555), 'tw': (0, 263, 129, 555)}, file={'cn': './assets/cn/island/GET_ITEMS_ISLAND.png', 'en': './assets/en/island/GET_ITEMS_ISLAND.png', 'jp': './assets/cn/island/GET_ITEMS_ISLAND.png', 'tw': './assets/cn/island/GET_ITEMS_ISLAND.png'}) ISLAND_AMOUNT_MAX = Button(area={'cn': (960, 382, 988, 405), 'en': (960, 382, 988, 405), 'jp': (960, 382, 988, 405), 'tw': (960, 382, 988, 405)}, color={'cn': (72, 72, 78), 'en': (78, 78, 84), 'jp': (72, 72, 78), 'tw': (72, 72, 78)}, button={'cn': (960, 382, 988, 405), 'en': (960, 382, 988, 405), 'jp': (960, 382, 988, 405), 'tw': (960, 382, 988, 405)}, file={'cn': './assets/cn/island/ISLAND_AMOUNT_MAX.png', 'en': './assets/en/island/ISLAND_AMOUNT_MAX.png', 'jp': './assets/cn/island/ISLAND_AMOUNT_MAX.png', 'tw': './assets/cn/island/ISLAND_AMOUNT_MAX.png'}) ISLAND_CLICK_SAFE_AREA = Button(area={'cn': (0, 263, 129, 555), 'en': (0, 263, 129, 555), 'jp': (0, 263, 129, 555), 'tw': (0, 263, 129, 555)}, color={'cn': (50, 52, 56), 'en': (50, 52, 56), 'jp': (50, 52, 56), 'tw': (50, 52, 56)}, button={'cn': (0, 263, 129, 555), 'en': (0, 263, 129, 555), 'jp': (0, 263, 129, 555), 'tw': (0, 263, 129, 555)}, file={'cn': './assets/cn/island/ISLAND_CLICK_SAFE_AREA.png', 'en': './assets/cn/island/ISLAND_CLICK_SAFE_AREA.png', 'jp': './assets/cn/island/ISLAND_CLICK_SAFE_AREA.png', 'tw': './assets/cn/island/ISLAND_CLICK_SAFE_AREA.png'}) +ISLAND_FRIEND = Button(area={'cn': (887, 648, 920, 675), 'en': (887, 648, 920, 675), 'jp': (887, 648, 920, 675), 'tw': (887, 648, 920, 675)}, color={'cn': (203, 213, 219), 'en': (203, 213, 219), 'jp': (203, 213, 219), 'tw': (203, 213, 219)}, button={'cn': (887, 648, 920, 675), 'en': (887, 648, 920, 675), 'jp': (887, 648, 920, 675), 'tw': (887, 648, 920, 675)}, file={'cn': './assets/cn/island/ISLAND_FRIEND.png', 'en': './assets/cn/island/ISLAND_FRIEND.png', 'jp': './assets/cn/island/ISLAND_FRIEND.png', 'tw': './assets/cn/island/ISLAND_FRIEND.png'}) +ISLAND_FRIEND_CHECK = Button(area={'cn': (171, 22, 217, 45), 'en': (171, 22, 217, 45), 'jp': (171, 22, 217, 45), 'tw': (171, 22, 217, 45)}, color={'cn': (96, 102, 115), 'en': (96, 102, 115), 'jp': (96, 102, 115), 'tw': (96, 102, 115)}, button={'cn': (171, 22, 217, 45), 'en': (171, 22, 217, 45), 'jp': (171, 22, 217, 45), 'tw': (171, 22, 217, 45)}, file={'cn': './assets/cn/island/ISLAND_FRIEND_CHECK.png', 'en': './assets/cn/island/ISLAND_FRIEND_CHECK.png', 'jp': './assets/cn/island/ISLAND_FRIEND_CHECK.png', 'tw': './assets/cn/island/ISLAND_FRIEND_CHECK.png'}) +ISLAND_FRIEND_LEAVE = Button(area={'cn': (380, 47, 406, 71), 'en': (380, 47, 406, 71), 'jp': (380, 47, 406, 71), 'tw': (380, 47, 406, 71)}, color={'cn': (183, 183, 183), 'en': (183, 183, 183), 'jp': (183, 183, 183), 'tw': (183, 183, 183)}, button={'cn': (380, 47, 406, 71), 'en': (380, 47, 406, 71), 'jp': (380, 47, 406, 71), 'tw': (380, 47, 406, 71)}, file={'cn': './assets/cn/island/ISLAND_FRIEND_LEAVE.png', 'en': './assets/cn/island/ISLAND_FRIEND_LEAVE.png', 'jp': './assets/cn/island/ISLAND_FRIEND_LEAVE.png', 'tw': './assets/cn/island/ISLAND_FRIEND_LEAVE.png'}) +ISLAND_FRIEND_SCROLL = Button(area={'cn': (1256, 98, 1257, 694), 'en': (1256, 98, 1257, 694), 'jp': (1256, 98, 1257, 694), 'tw': (1256, 98, 1257, 694)}, color={'cn': (200, 199, 193), 'en': (200, 199, 193), 'jp': (200, 199, 193), 'tw': (200, 199, 193)}, button={'cn': (1256, 98, 1257, 694), 'en': (1256, 98, 1257, 694), 'jp': (1256, 98, 1257, 694), 'tw': (1256, 98, 1257, 694)}, file={'cn': './assets/cn/island/ISLAND_FRIEND_SCROLL.png', 'en': './assets/cn/island/ISLAND_FRIEND_SCROLL.png', 'jp': './assets/cn/island/ISLAND_FRIEND_SCROLL.png', 'tw': './assets/cn/island/ISLAND_FRIEND_SCROLL.png'}) ISLAND_INFO_EXIT = Button(area={'cn': (907, 160, 933, 187), 'en': (907, 160, 933, 187), 'jp': (907, 160, 933, 187), 'tw': (907, 160, 933, 187)}, color={'cn': (96, 96, 96), 'en': (96, 96, 96), 'jp': (96, 96, 96), 'tw': (96, 96, 96)}, button={'cn': (907, 160, 933, 187), 'en': (907, 160, 933, 187), 'jp': (907, 160, 933, 187), 'tw': (907, 160, 933, 187)}, file={'cn': './assets/cn/island/ISLAND_INFO_EXIT.png', 'en': './assets/cn/island/ISLAND_INFO_EXIT.png', 'jp': './assets/cn/island/ISLAND_INFO_EXIT.png', 'tw': './assets/cn/island/ISLAND_INFO_EXIT.png'}) ISLAND_MANAGEMENT = Button(area={'cn': (1077, 493, 1119, 533), 'en': (1077, 493, 1119, 533), 'jp': (1077, 493, 1119, 533), 'tw': (1077, 493, 1119, 533)}, color={'cn': (187, 224, 135), 'en': (187, 224, 135), 'jp': (187, 224, 135), 'tw': (187, 224, 135)}, button={'cn': (1077, 493, 1119, 533), 'en': (1077, 493, 1119, 533), 'jp': (1077, 493, 1119, 533), 'tw': (1077, 493, 1119, 533)}, file={'cn': './assets/cn/island/ISLAND_MANAGEMENT.png', 'en': './assets/cn/island/ISLAND_MANAGEMENT.png', 'jp': './assets/cn/island/ISLAND_MANAGEMENT.png', 'tw': './assets/cn/island/ISLAND_MANAGEMENT.png'}) ISLAND_MANAGEMENT_CHECK = Button(area={'cn': (123, 21, 304, 47), 'en': (123, 21, 304, 47), 'jp': (123, 21, 304, 47), 'tw': (123, 21, 304, 47)}, color={'cn': (77, 83, 96), 'en': (90, 96, 108), 'jp': (77, 83, 96), 'tw': (77, 83, 96)}, button={'cn': (123, 21, 304, 47), 'en': (123, 21, 304, 47), 'jp': (123, 21, 304, 47), 'tw': (123, 21, 304, 47)}, file={'cn': './assets/cn/island/ISLAND_MANAGEMENT_CHECK.png', 'en': './assets/en/island/ISLAND_MANAGEMENT_CHECK.png', 'jp': './assets/cn/island/ISLAND_MANAGEMENT_CHECK.png', 'tw': './assets/cn/island/ISLAND_MANAGEMENT_CHECK.png'}) @@ -20,6 +24,9 @@ OCR_PRODUCTION_TIME_REMAIN = Button(area={'cn': (621, 427, 666, 439), 'en': (621 OCR_TRANSPORT_REFRESH = Button(area={'cn': (716, 211, 805, 231), 'en': (716, 211, 805, 231), 'jp': (716, 211, 805, 231), 'tw': (716, 211, 805, 231)}, color={'cn': (176, 177, 175), 'en': (176, 177, 175), 'jp': (176, 177, 175), 'tw': (176, 177, 175)}, button={'cn': (716, 211, 805, 231), 'en': (716, 211, 805, 231), 'jp': (716, 211, 805, 231), 'tw': (716, 211, 805, 231)}, file={'cn': './assets/cn/island/OCR_TRANSPORT_REFRESH.png', 'en': './assets/cn/island/OCR_TRANSPORT_REFRESH.png', 'jp': './assets/cn/island/OCR_TRANSPORT_REFRESH.png', 'tw': './assets/cn/island/OCR_TRANSPORT_REFRESH.png'}) OCR_TRANSPORT_TIME = Button(area={'cn': (611, 139, 687, 154), 'en': (611, 139, 687, 154), 'jp': (611, 139, 687, 154), 'tw': (611, 139, 687, 154)}, color={'cn': (119, 119, 120), 'en': (119, 119, 120), 'jp': (119, 119, 120), 'tw': (119, 119, 120)}, button={'cn': (611, 139, 687, 154), 'en': (611, 139, 687, 154), 'jp': (611, 139, 687, 154), 'tw': (611, 139, 687, 154)}, file={'cn': './assets/cn/island/OCR_TRANSPORT_TIME.png', 'en': './assets/cn/island/OCR_TRANSPORT_TIME.png', 'jp': './assets/cn/island/OCR_TRANSPORT_TIME.png', 'tw': './assets/cn/island/OCR_TRANSPORT_TIME.png'}) OCR_TRANSPORT_TIME_REMAIN = Button(area={'cn': (753, 210, 842, 230), 'en': (753, 210, 842, 230), 'jp': (753, 210, 842, 230), 'tw': (753, 210, 842, 230)}, color={'cn': (252, 203, 127), 'en': (252, 203, 127), 'jp': (252, 203, 127), 'tw': (252, 203, 127)}, button={'cn': (753, 210, 842, 230), 'en': (753, 210, 842, 230), 'jp': (753, 210, 842, 230), 'tw': (753, 210, 842, 230)}, file={'cn': './assets/cn/island/OCR_TRANSPORT_TIME_REMAIN.png', 'en': './assets/cn/island/OCR_TRANSPORT_TIME_REMAIN.png', 'jp': './assets/cn/island/OCR_TRANSPORT_TIME_REMAIN.png', 'tw': './assets/cn/island/OCR_TRANSPORT_TIME_REMAIN.png'}) +PEARL_CHECK = Button(area={'cn': (113, 22, 228, 45), 'en': (113, 22, 228, 45), 'jp': (113, 22, 228, 45), 'tw': (113, 22, 228, 45)}, color={'cn': (93, 98, 110), 'en': (93, 98, 110), 'jp': (93, 98, 110), 'tw': (93, 98, 110)}, button={'cn': (113, 22, 228, 45), 'en': (113, 22, 228, 45), 'jp': (113, 22, 228, 45), 'tw': (113, 22, 228, 45)}, file={'cn': './assets/cn/island/PEARL_CHECK.png', 'en': './assets/cn/island/PEARL_CHECK.png', 'jp': './assets/cn/island/PEARL_CHECK.png', 'tw': './assets/cn/island/PEARL_CHECK.png'}) +PEARL_ENTER = Button(area={'cn': (809, 380, 836, 407), 'en': (809, 380, 836, 407), 'jp': (809, 380, 836, 407), 'tw': (809, 380, 836, 407)}, color={'cn': (192, 192, 192), 'en': (192, 192, 192), 'jp': (192, 192, 192), 'tw': (192, 192, 192)}, button={'cn': (809, 380, 836, 407), 'en': (809, 380, 836, 407), 'jp': (809, 380, 836, 407), 'tw': (809, 380, 836, 407)}, file={'cn': './assets/cn/island/PEARL_ENTER.png', 'en': './assets/cn/island/PEARL_ENTER.png', 'jp': './assets/cn/island/PEARL_ENTER.png', 'tw': './assets/cn/island/PEARL_ENTER.png'}) +PEARL_PRICE_OCR = Button(area={'cn': (257, 357, 300, 377), 'en': (257, 357, 300, 377), 'jp': (257, 357, 300, 377), 'tw': (257, 357, 300, 377)}, color={'cn': (147, 148, 148), 'en': (147, 148, 148), 'jp': (147, 148, 148), 'tw': (147, 148, 148)}, button={'cn': (257, 357, 300, 377), 'en': (257, 357, 300, 377), 'jp': (257, 357, 300, 377), 'tw': (257, 357, 300, 377)}, file={'cn': './assets/cn/island/PEARL_PRICE_OCR.png', 'en': './assets/cn/island/PEARL_PRICE_OCR.png', 'jp': './assets/cn/island/PEARL_PRICE_OCR.png', 'tw': './assets/cn/island/PEARL_PRICE_OCR.png'}) PRODUCT_MANJUU_CHECK = Button(area={'cn': (535, 107, 575, 138), 'en': (535, 107, 575, 138), 'jp': (535, 107, 575, 138), 'tw': (535, 107, 575, 138)}, color={'cn': (199, 181, 124), 'en': (199, 181, 124), 'jp': (199, 181, 124), 'tw': (199, 181, 124)}, button={'cn': (535, 107, 575, 138), 'en': (535, 107, 575, 138), 'jp': (535, 107, 575, 138), 'tw': (535, 107, 575, 138)}, file={'cn': './assets/cn/island/PRODUCT_MANJUU_CHECK.png', 'en': './assets/cn/island/PRODUCT_MANJUU_CHECK.png', 'jp': './assets/cn/island/PRODUCT_MANJUU_CHECK.png', 'tw': './assets/cn/island/PRODUCT_MANJUU_CHECK.png'}) PROJECT_AKASHI_CHECK = Button(area={'cn': (1157, 176, 1217, 209), 'en': (1157, 176, 1217, 209), 'jp': (1157, 176, 1217, 209), 'tw': (1157, 176, 1217, 209)}, color={'cn': (173, 183, 168), 'en': (173, 183, 168), 'jp': (173, 183, 168), 'tw': (173, 183, 168)}, button={'cn': (1157, 176, 1217, 209), 'en': (1157, 176, 1217, 209), 'jp': (1157, 176, 1217, 209), 'tw': (1157, 176, 1217, 209)}, file={'cn': './assets/cn/island/PROJECT_AKASHI_CHECK.png', 'en': './assets/cn/island/PROJECT_AKASHI_CHECK.png', 'jp': './assets/cn/island/PROJECT_AKASHI_CHECK.png', 'tw': './assets/cn/island/PROJECT_AKASHI_CHECK.png'}) PROJECT_AMAGI_CHAN_CHECK = Button(area={'cn': (1152, 167, 1229, 215), 'en': (1152, 167, 1229, 215), 'jp': (1152, 167, 1229, 215), 'tw': (1152, 167, 1229, 215)}, color={'cn': (136, 114, 106), 'en': (136, 114, 106), 'jp': (136, 114, 106), 'tw': (136, 114, 106)}, button={'cn': (1152, 167, 1229, 215), 'en': (1152, 167, 1229, 215), 'jp': (1152, 167, 1229, 215), 'tw': (1152, 167, 1229, 215)}, file={'cn': './assets/cn/island/PROJECT_AMAGI_CHAN_CHECK.png', 'en': './assets/cn/island/PROJECT_AMAGI_CHAN_CHECK.png', 'jp': './assets/cn/island/PROJECT_AMAGI_CHAN_CHECK.png', 'tw': './assets/cn/island/PROJECT_AMAGI_CHAN_CHECK.png'}) @@ -57,6 +64,7 @@ TEMPLATE_COTTON = Template(file={'cn': './assets/cn/island/TEMPLATE_COTTON.png', TEMPLATE_FLEX = Template(file={'cn': './assets/cn/island/TEMPLATE_FLEX.png', 'en': './assets/cn/island/TEMPLATE_FLEX.png', 'jp': './assets/cn/island/TEMPLATE_FLEX.png', 'tw': './assets/cn/island/TEMPLATE_FLEX.png'}) TEMPLATE_FRESH_MEAT = Template(file={'cn': './assets/cn/island/TEMPLATE_FRESH_MEAT.png', 'en': './assets/cn/island/TEMPLATE_FRESH_MEAT.png', 'jp': './assets/cn/island/TEMPLATE_FRESH_MEAT.png', 'tw': './assets/cn/island/TEMPLATE_FRESH_MEAT.png'}) TEMPLATE_FRIEDRICH_DER_GROBE = Template(file={'cn': './assets/cn/island/TEMPLATE_FRIEDRICH_DER_GROBE.png', 'en': './assets/cn/island/TEMPLATE_FRIEDRICH_DER_GROBE.png', 'jp': './assets/cn/island/TEMPLATE_FRIEDRICH_DER_GROBE.png', 'tw': './assets/cn/island/TEMPLATE_FRIEDRICH_DER_GROBE.png'}) +TEMPLATE_FRIEND_VISIT = Template(file={'cn': './assets/cn/island/TEMPLATE_FRIEND_VISIT.png', 'en': './assets/cn/island/TEMPLATE_FRIEND_VISIT.png', 'jp': './assets/cn/island/TEMPLATE_FRIEND_VISIT.png', 'tw': './assets/cn/island/TEMPLATE_FRIEND_VISIT.png'}) TEMPLATE_HELENA = Template(file={'cn': './assets/cn/island/TEMPLATE_HELENA.png', 'en': './assets/cn/island/TEMPLATE_HELENA.png', 'jp': './assets/cn/island/TEMPLATE_HELENA.png', 'tw': './assets/cn/island/TEMPLATE_HELENA.png'}) TEMPLATE_ITEM_SATISFIED = Template(file={'cn': './assets/cn/island/TEMPLATE_ITEM_SATISFIED.png', 'en': './assets/cn/island/TEMPLATE_ITEM_SATISFIED.png', 'jp': './assets/cn/island/TEMPLATE_ITEM_SATISFIED.png', 'tw': './assets/cn/island/TEMPLATE_ITEM_SATISFIED.png'}) TEMPLATE_LEMALIN = Template(file={'cn': './assets/cn/island/TEMPLATE_LEMALIN.png', 'en': './assets/cn/island/TEMPLATE_LEMALIN.png', 'jp': './assets/cn/island/TEMPLATE_LEMALIN.png', 'tw': './assets/cn/island/TEMPLATE_LEMALIN.png'}) diff --git a/module/island/pearl_daemon.py b/module/island/pearl_daemon.py new file mode 100644 index 000000000..d83c0c0d4 --- /dev/null +++ b/module/island/pearl_daemon.py @@ -0,0 +1,277 @@ +from rich.table import Table +from rich.text import Text + +from module.base.timer import Timer +from module.island.assets import * +from module.island.ui import IslandUI +from module.logger import logger +from module.map.map_grids import SelectedGrids +from module.ocr.ocr import Digit, Ocr +from module.ui.page import page_island, page_island_phone +from module.ui.scroll import Scroll + + +ISLAND_FRIEND_SCROLL = Scroll(ISLAND_FRIEND_SCROLL, color=(255, 255, 255)) +ISLAND_FRIEND_SCROLL.drag_threshold = 0.05 +ISLAND_FRIEND_SCROLL.edge_threshold = 0.05 + +PEARL_PRICE_OCR = Digit(PEARL_PRICE_OCR, letter=(255, 255, 255), threshold=128) + + +class FriendNameOcr(Ocr): + def after_process(self, result): + result = super().after_process(result) + result = result.replace('/', '').replace('\\', '').replace('`', '').replace('_', '') + return result + + +class IslandFriend: + # If success to parse project + valid: bool + # button to visit + visit_button: Button + # OCR result + name: str + # if visited + visited: bool + # pearl price on this island + pearl_price: int + + def __init__(self, image, visit_button, crop_area): + """ + Args: + image: + visit_button: + crop_area: + """ + self.image = image + self.visit_button = visit_button.move((crop_area[0], crop_area[1])) + self.crop_area = crop_area + self.x1, self.y1, self.x2, self.y2 = self.visit_button.area + self.valid = True + self.visited = False + self.pearl_price = 0 + self.friend_parse() + + def friend_parse(self): + area = (self.x1 - 504, self.y1 - 25, self.x1 - 504 + 168, self.y1 - 25 + 22) + + if area[0] < 360 or area[1] < 98 or area[2] > 593 or area[3] > 693: + self.valid = False + return + + button = Button(area=area, color=(), button=area, name='FRIEND_NAME') + ocr = FriendNameOcr(button, lang='cnocr', letter=(63, 64, 66), threshold=128) + self.name = ocr.ocr(self.image) + if not self.name: + self.valid = False + return + + def __eq__(self, other): + """ + Args: + other (IslandFriend): + + Returns: + bool: + """ + if not isinstance(other, IslandFriend): + return False + if not self.valid or not other.valid: + return False + if self.name != other.name: + return False + + return True + + def __str__(self): + return self.name + + +class IslandPearl(IslandUI): + def pearl_enter(self): + """ + Pages: + in: ISLAND_FRIEND_LEAVE + out: PEARL_CHECK + """ + logger.hr('Pearl Enter') + self.move_up(2.8) + self.move_right(1.6) + self.move_down(1.8) + + for _ in self.loop(): + if self.appear_then_click(PEARL_ENTER, offset=(20, 20), interval=2): + continue + if self.appear(PEARL_CHECK, offset=(20, 20)): + break + + def pearl_price_get(self): + """ + Returns: + int: pearl price ocr result + """ + ocr = 0 + for _ in self.loop(timeout=1.5): + ocr = PEARL_PRICE_OCR.ocr(self.device.image) + if ocr >= 200: + break + + return ocr + + def friend_detect(self): + """ + Get all friends from an image. + + Args: + image (np.ndarray): + + Returns: + SelectedGrids: + """ + self.handle_info_bar() + area = (880, 98, 960, 693) + friends = SelectedGrids( + [IslandFriend(self.device.image, button, area) for button in + TEMPLATE_FRIEND_VISIT.match_multi(self.image_crop(area, copy=False))] + ) + return friends.select(valid=True) + + def _friend_visit(self, friend): + """ + Args: + friend (IslandFriend): + + Returns: + bool: if visited + """ + logger.info(f'Visiting {friend}') + confirm_timer = Timer(1, count=2).start() + for _ in self.loop(): + if self.island_in_friend(interval=5): + self.device.click(friend.visit_button) + continue + + if self.info_bar_count(): + return False + + if self.appear(ISLAND_FRIEND_LEAVE, offset=(20, 20)): + if confirm_timer.reached(): + break + continue + else: + confirm_timer.reset() + return True + + def friend_leave(self): + logger.hr('Friend Leave') + self.island_ui_back() + for _ in self.loop(): + if self.appear_then_click(ISLAND_FRIEND_LEAVE, offset=(20, 20), interval=2): + continue + + if self.ui_page_appear(page_island): + break + if self.ui_page_appear(page_island_phone): + break + self.device.sleep(1.5) + self.device.click_record_clear() + self.ui_ensure_friend_page() + # ISLAND_FRIEND_SCROLL.set_top(main=self) + + def friend_visit(self, current_friends, friends): + """ + Visit a friend's island, get the pearl price then leave + + Args: + current_friends (SelectedGrids): + friends (SelectedGrids): + + Returns: + SelectedGrids: + """ + logger.hr('Friend Visit') + friend: IslandFriend = friends.intersect_by_eq(current_friends).select(visited=False).first_or_none() + if friend is None or friend.name not in current_friends.get('name'): + return friends + + if self._friend_visit(friend): + self.device.sleep(2) + self.pearl_enter() + friend.pearl_price = self.pearl_price_get() + print(friend.name) + self.friend_leave() + friend.visited = True + return friends + + def pearl_run(self): + """ + Visit each friend's island, get the pearl price, and show in the logger + + Returns: + SelectedGrids: + """ + logger.hr('Island Pearl', level=1) + bottom = False + friends = SelectedGrids([]) + if ISLAND_FRIEND_SCROLL.appear(main=self): + ISLAND_FRIEND_SCROLL.set_top(main=self) + count = 0 + for _ in self.loop(): + if count > 2: + break + current_friends = self.friend_detect() + friends = friends.add_by_eq(current_friends) + friends = self.friend_visit(current_friends, friends) + current_friends = friends.intersect_by_eq(current_friends) + + if ISLAND_FRIEND_SCROLL.appear(main=self): + if ISLAND_FRIEND_SCROLL.at_bottom(main=self): + if not bottom: + ISLAND_FRIEND_SCROLL.drag_threshold = 0.01 + ISLAND_FRIEND_SCROLL.edge_threshold = 0.01 + bottom = True + continue + logger.info('Island friend reach bottom, stop') + break + elif not current_friends.select(visited=False): + ISLAND_FRIEND_SCROLL.next_page(main=self) + count += 1 + + return friends + + @staticmethod + def show(data): + """ + +----------+---------------+ + | Player | Pearl Price | + +----------+---------------+ + | a | 200 | + | b | 300 | + | c | 400 | + +----------+---------------+ + """ + table = Table(show_lines=True) + table.add_column( + 'Player', header_style="bright_cyan", style="cyan", no_wrap=True + ) + table.add_column("Pearl Price", style="magenta") + for row in zip(data.get('name'), data.get('pearl_price')): + table.add_row( + row[0], + str(row[1]), + ) + logger.print(table, justify='center') + + def run(self): + self.device.screenshot() + self.ui_ensure_friend_page() + friends = self.pearl_run() + friends = friends.select(visited=True) + self.show(friends) + + +if __name__ == '__main__': + self = IslandPearl('alas') + self.device.screenshot() + self.run() diff --git a/module/island/ui.py b/module/island/ui.py index 08117267d..17b79e4f2 100644 --- a/module/island/ui.py +++ b/module/island/ui.py @@ -28,6 +28,16 @@ class IslandUI(UI): """ return self.match_template_color(ISLAND_TRANSPORT_CHECK, offset=(20, 20), interval=interval) + def island_in_friend(self, interval=0): + """ + Args: + interval (int): + + Returns: + bool: if in page ISLAND_FRIEND_CHECK + """ + return self.appear(ISLAND_FRIEND_CHECK, offset=(20, 20), interval=interval) + def island_management_enter(self): """ Enter island management page. @@ -73,6 +83,27 @@ class IslandUI(UI): ) return True + def island_friend_enter(self): + """ + Enter island friend page. + + Returns: + bool: if success + + Pages: + in: page_island_phone + out: ISLAND_FRIEND_CHECK + """ + logger.info('Island friend enter') + self.ui_click( + click_button=ISLAND_FRIEND, + check_button=self.island_in_friend, + offset=(20, 20), + retry_wait=2, + skip_first_screenshot=True + ) + return True + def island_ui_back(self): """ Pages: @@ -82,7 +113,7 @@ class IslandUI(UI): logger.info('Island UI back') self.ui_click( click_button=SHOP_BACK_ARROW, - check_button=page_island_phone.check_button, + check_button=[page_island_phone.check_button, ISLAND_FRIEND_LEAVE], offset=(20, 20), retry_wait=2, skip_first_screenshot=True @@ -111,6 +142,17 @@ class IslandUI(UI): if self.appear_then_click(ISLAND_MANAGEMENT, offset=(20, 20), interval=2): continue + def ui_ensure_friend_page(self): + """ + Pages: + in: Any + out: ISLAND_FRIEND_CHECK + """ + logger.info('UI ensure friend page') + if not self.island_in_friend(): + self.ui_ensure(page_island_phone) + self.island_friend_enter() + def handle_get_items(self): if self.appear_then_click(GET_ITEMS_ISLAND, offset=(20, 20), interval=2): return True @@ -138,3 +180,23 @@ class IslandUI(UI): return True return super().ui_additional(get_ship=False) + + def move_up(self, hold_time=0): + p1 = (217, 507) + p2 = (217, 507 - 36) + self.device.swipe(p1, p2, hold_time=hold_time) + + def move_down(self, hold_time=0): + p1 = (217, 507) + p2 = (217, 507 + 36) + self.device.swipe(p1, p2, hold_time=hold_time) + + def move_left(self, hold_time=0): + p1 = (217, 507) + p2 = (217 - 36, 507) + self.device.swipe(p1, p2, hold_time=hold_time) + + def move_right(self, hold_time=0): + p1 = (217, 507) + p2 = (217 + 36, 507) + self.device.swipe(p1, p2, hold_time=hold_time) diff --git a/module/submodule/utils.py b/module/submodule/utils.py index cbe65139c..d7a87d916 100644 --- a/module/submodule/utils.py +++ b/module/submodule/utils.py @@ -19,6 +19,7 @@ def get_available_func(): 'OpsiDaemon', 'EventStory', 'BoxDisassemble', + 'IslandPearl', 'AzurLaneUncensored', 'Benchmark', 'GameManager',