diff --git a/alas.py b/alas.py index 8657170b9..e102d013e 100644 --- a/alas.py +++ b/alas.py @@ -407,6 +407,10 @@ class AzurLaneAutoScript: GemsFarming(config=self.config, device=self.device).run( name=self.config.Campaign_Name, folder=self.config.Campaign_Event, mode=self.config.Campaign_Mode) + def island_production(self): + from module.island.production import IslandProduction + IslandProduction(config=self.config, device=self.device).run() + def island_freebie(self): from module.island.freebie import IslandFreebie IslandFreebie(config=self.config, device=self.device).run() diff --git a/assets/cn/island/ISLAND_PRODUCTION_RECEIVE.png b/assets/cn/island/ISLAND_PRODUCTION_RECEIVE.png new file mode 100644 index 000000000..6fb5eb9a5 Binary files /dev/null and b/assets/cn/island/ISLAND_PRODUCTION_RECEIVE.png differ diff --git a/assets/cn/island/ISLAND_PRODUCTION_RERUN.png b/assets/cn/island/ISLAND_PRODUCTION_RERUN.png new file mode 100644 index 000000000..8b074a6c3 Binary files /dev/null and b/assets/cn/island/ISLAND_PRODUCTION_RERUN.png differ diff --git a/assets/cn/island/ISLAND_PRODUCTION_RUNNING.png b/assets/cn/island/ISLAND_PRODUCTION_RUNNING.png new file mode 100644 index 000000000..3f4dbbd7a Binary files /dev/null and b/assets/cn/island/ISLAND_PRODUCTION_RUNNING.png differ diff --git a/assets/cn/island/ISLAND_PRODUCTION_SELECT_CHARACTER.png b/assets/cn/island/ISLAND_PRODUCTION_SELECT_CHARACTER.png new file mode 100644 index 000000000..4a10aca87 Binary files /dev/null and b/assets/cn/island/ISLAND_PRODUCTION_SELECT_CHARACTER.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ANCHOR_ICON.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ANCHOR_ICON.png new file mode 100644 index 000000000..c1894721f Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ANCHOR_ICON.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_BEAR.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_BEAR.png new file mode 100644 index 000000000..a5fd3fa02 Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_BEAR.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_CAFE.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_CAFE.png new file mode 100644 index 000000000..9d69b0124 Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_CAFE.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_CRAFTS.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_CRAFTS.png new file mode 100644 index 000000000..7941eef9b Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_CRAFTS.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_EATERY.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_EATERY.png new file mode 100644 index 000000000..20e534a46 Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_EATERY.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ELECTRONIC.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ELECTRONIC.png new file mode 100644 index 000000000..694d6de4c Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ELECTRONIC.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_FIELD.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_FIELD.png new file mode 100644 index 000000000..2b6d3b2ea Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_FIELD.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_FISHERY.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_FISHERY.png new file mode 100644 index 000000000..2d3ffd420 Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_FISHERY.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_GRILL.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_GRILL.png new file mode 100644 index 000000000..572e15d35 Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_GRILL.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_KOI.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_KOI.png new file mode 100644 index 000000000..5b3eb379a Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_KOI.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_LUMBER.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_LUMBER.png new file mode 100644 index 000000000..41a0d5da5 Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_LUMBER.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_MACHINERY.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_MACHINERY.png new file mode 100644 index 000000000..764712856 Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_MACHINERY.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_MINE.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_MINE.png new file mode 100644 index 000000000..5f2d21aad Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_MINE.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_NURSERY.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_NURSERY.png new file mode 100644 index 000000000..203155f66 Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_NURSERY.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ORCHARD.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ORCHARD.png new file mode 100644 index 000000000..ae292a149 Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ORCHARD.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_RANCH.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_RANCH.png new file mode 100644 index 000000000..61ece8d05 Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_RANCH.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_SLOT_EMPTY.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_SLOT_EMPTY.png new file mode 100644 index 000000000..4416e7a4c Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_SLOT_EMPTY.png differ diff --git a/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_WOOD.png b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_WOOD.png new file mode 100644 index 000000000..03f121899 Binary files /dev/null and b/assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_WOOD.png differ diff --git a/assets/jp/island/ISLAND_PRODUCTION_RECEIVE.png b/assets/jp/island/ISLAND_PRODUCTION_RECEIVE.png new file mode 100644 index 000000000..397b2ea28 Binary files /dev/null and b/assets/jp/island/ISLAND_PRODUCTION_RECEIVE.png differ diff --git a/assets/jp/island/ISLAND_PRODUCTION_RERUN.png b/assets/jp/island/ISLAND_PRODUCTION_RERUN.png new file mode 100644 index 000000000..d70af40d8 Binary files /dev/null and b/assets/jp/island/ISLAND_PRODUCTION_RERUN.png differ diff --git a/assets/jp/island/ISLAND_PRODUCTION_SELECT_CHARACTER.png b/assets/jp/island/ISLAND_PRODUCTION_SELECT_CHARACTER.png new file mode 100644 index 000000000..8580019bb Binary files /dev/null and b/assets/jp/island/ISLAND_PRODUCTION_SELECT_CHARACTER.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_BEAR.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_BEAR.png new file mode 100644 index 000000000..586c1ac94 Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_BEAR.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_CAFE.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_CAFE.png new file mode 100644 index 000000000..a6fe42d2c Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_CAFE.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_CRAFTS.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_CRAFTS.png new file mode 100644 index 000000000..2a4d486d6 Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_CRAFTS.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_EATERY.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_EATERY.png new file mode 100644 index 000000000..8db4da0b5 Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_EATERY.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_ELECTRONIC.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_ELECTRONIC.png new file mode 100644 index 000000000..cfbddadee Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_ELECTRONIC.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_FIELD.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_FIELD.png new file mode 100644 index 000000000..6ddf4ff2f Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_FIELD.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_FISHERY.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_FISHERY.png new file mode 100644 index 000000000..b8a57cc14 Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_FISHERY.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_GRILL.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_GRILL.png new file mode 100644 index 000000000..a45c9bcf2 Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_GRILL.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_KOI.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_KOI.png new file mode 100644 index 000000000..5d3b34f35 Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_KOI.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_LUMBER.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_LUMBER.png new file mode 100644 index 000000000..794990dcb Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_LUMBER.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_MACHINERY.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_MACHINERY.png new file mode 100644 index 000000000..2ad0f6126 Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_MACHINERY.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_MINE.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_MINE.png new file mode 100644 index 000000000..ffc142a50 Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_MINE.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_NURSERY.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_NURSERY.png new file mode 100644 index 000000000..6ad2821f7 Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_NURSERY.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_ORCHARD.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_ORCHARD.png new file mode 100644 index 000000000..ca33262e4 Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_ORCHARD.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_RANCH.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_RANCH.png new file mode 100644 index 000000000..7594505df Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_RANCH.png differ diff --git a/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_WOOD.png b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_WOOD.png new file mode 100644 index 000000000..1671e3dc7 Binary files /dev/null and b/assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_WOOD.png differ diff --git a/module/config/config_manual.py b/module/config/config_manual.py index 871e67795..f8a9f6583 100644 --- a/module/config/config_manual.py +++ b/module/config/config_manual.py @@ -24,6 +24,7 @@ class ManualConfig: > OpsiAbyssal > OpsiStronghold > OpsiObscure > OpsiArchive > IslandFreebie > IslandCollect > IslandBusiness > IslandSeasonTask + > IslandProduction > Daily > Hard > OpsiAshBeacon > OpsiAshAssist > OpsiMonthBoss > Sos > EventSp > EventA > EventB > EventC > EventD > RaidDaily > CoalitionSp > WarArchives > MaritimeEscort diff --git a/module/island/assets.py b/module/island/assets.py index 4ea462b0f..79de277c4 100644 --- a/module/island/assets.py +++ b/module/island/assets.py @@ -23,6 +23,10 @@ ISLAND_FREEBIE_SHARE_ALL = Button(area={'cn': (728, 588, 810, 611), 'en': (728, ISLAND_FREEBIE_SHARE_BACK = Button(area={'cn': (844, 101, 878, 135), 'en': (844, 101, 878, 135), 'jp': (844, 101, 878, 135), 'tw': (844, 101, 878, 135)}, color={'cn': (170, 213, 232), 'en': (170, 213, 232), 'jp': (170, 213, 232), 'tw': (170, 213, 232)}, button={'cn': (844, 101, 878, 135), 'en': (844, 101, 878, 135), 'jp': (844, 101, 878, 135), 'tw': (844, 101, 878, 135)}, file={'cn': './assets/cn/island/ISLAND_FREEBIE_SHARE_BACK.png', 'en': './assets/cn/island/ISLAND_FREEBIE_SHARE_BACK.png', 'jp': './assets/cn/island/ISLAND_FREEBIE_SHARE_BACK.png', 'tw': './assets/cn/island/ISLAND_FREEBIE_SHARE_BACK.png'}) ISLAND_FREEBIE_UNAVAILABLE = Button(area={'cn': (36, 631, 88, 683), 'en': (36, 631, 88, 683), 'jp': (36, 631, 88, 683), 'tw': (36, 631, 88, 683)}, color={'cn': (122, 122, 122), 'en': (122, 122, 122), 'jp': (122, 122, 122), 'tw': (122, 122, 122)}, button={'cn': (36, 631, 88, 683), 'en': (36, 631, 88, 683), 'jp': (36, 631, 88, 683), 'tw': (36, 631, 88, 683)}, file={'cn': './assets/cn/island/ISLAND_FREEBIE_UNAVAILABLE.png', 'en': './assets/cn/island/ISLAND_FREEBIE_UNAVAILABLE.png', 'jp': './assets/cn/island/ISLAND_FREEBIE_UNAVAILABLE.png', 'tw': './assets/cn/island/ISLAND_FREEBIE_UNAVAILABLE.png'}) ISLAND_LEVEL_UP = Button(area={'cn': (616, 339, 662, 377), 'en': (616, 339, 662, 377), 'jp': (616, 339, 662, 377), 'tw': (616, 339, 662, 377)}, color={'cn': (186, 213, 226), 'en': (186, 213, 226), 'jp': (186, 213, 226), 'tw': (186, 213, 226)}, button={'cn': (616, 339, 662, 377), 'en': (616, 339, 662, 377), 'jp': (616, 339, 662, 377), 'tw': (616, 339, 662, 377)}, file={'cn': './assets/cn/island/ISLAND_LEVEL_UP.png', 'en': './assets/cn/island/ISLAND_LEVEL_UP.png', 'jp': './assets/cn/island/ISLAND_LEVEL_UP.png', 'tw': './assets/cn/island/ISLAND_LEVEL_UP.png'}) +ISLAND_PRODUCTION_RECEIVE = Button(area={'cn': (612, 547, 657, 571), 'en': (612, 547, 657, 571), 'jp': (591, 549, 630, 570), 'tw': (612, 547, 657, 571)}, color={'cn': (119, 209, 255), 'en': (119, 209, 255), 'jp': (83, 197, 255), 'tw': (119, 209, 255)}, button={'cn': (612, 547, 657, 571), 'en': (612, 547, 657, 571), 'jp': (591, 549, 630, 570), 'tw': (612, 547, 657, 571)}, file={'cn': './assets/cn/island/ISLAND_PRODUCTION_RECEIVE.png', 'en': './assets/cn/island/ISLAND_PRODUCTION_RECEIVE.png', 'jp': './assets/jp/island/ISLAND_PRODUCTION_RECEIVE.png', 'tw': './assets/cn/island/ISLAND_PRODUCTION_RECEIVE.png'}) +ISLAND_PRODUCTION_RERUN = Button(area={'cn': (596, 537, 685, 565), 'en': (596, 537, 685, 565), 'jp': (596, 540, 684, 565), 'tw': (596, 537, 685, 565)}, color={'cn': (247, 210, 138), 'en': (247, 210, 138), 'jp': (247, 211, 142), 'tw': (247, 210, 138)}, button={'cn': (596, 537, 685, 565), 'en': (596, 537, 685, 565), 'jp': (596, 540, 684, 565), 'tw': (596, 537, 685, 565)}, file={'cn': './assets/cn/island/ISLAND_PRODUCTION_RERUN.png', 'en': './assets/cn/island/ISLAND_PRODUCTION_RERUN.png', 'jp': './assets/jp/island/ISLAND_PRODUCTION_RERUN.png', 'tw': './assets/cn/island/ISLAND_PRODUCTION_RERUN.png'}) +ISLAND_PRODUCTION_RUNNING = Button(area={'cn': (527, 155, 553, 181), 'en': (527, 155, 553, 181), 'jp': (527, 155, 553, 181), 'tw': (527, 155, 553, 181)}, color={'cn': (156, 222, 255), 'en': (156, 222, 255), 'jp': (156, 222, 255), 'tw': (156, 222, 255)}, button={'cn': (527, 155, 553, 181), 'en': (527, 155, 553, 181), 'jp': (527, 155, 553, 181), 'tw': (527, 155, 553, 181)}, file={'cn': './assets/cn/island/ISLAND_PRODUCTION_RUNNING.png', 'en': './assets/cn/island/ISLAND_PRODUCTION_RUNNING.png', 'jp': './assets/cn/island/ISLAND_PRODUCTION_RUNNING.png', 'tw': './assets/cn/island/ISLAND_PRODUCTION_RUNNING.png'}) +ISLAND_PRODUCTION_SELECT_CHARACTER = Button(area={'cn': (582, 318, 610, 346), 'en': (582, 318, 610, 346), 'jp': (579, 315, 607, 348), 'tw': (582, 318, 610, 346)}, color={'cn': (244, 244, 242), 'en': (244, 244, 242), 'jp': (246, 246, 245), 'tw': (244, 244, 242)}, button={'cn': (582, 318, 610, 346), 'en': (582, 318, 610, 346), 'jp': (579, 315, 607, 348), 'tw': (582, 318, 610, 346)}, file={'cn': './assets/cn/island/ISLAND_PRODUCTION_SELECT_CHARACTER.png', 'en': './assets/cn/island/ISLAND_PRODUCTION_SELECT_CHARACTER.png', 'jp': './assets/jp/island/ISLAND_PRODUCTION_SELECT_CHARACTER.png', 'tw': './assets/cn/island/ISLAND_PRODUCTION_SELECT_CHARACTER.png'}) ISLAND_SEASON_TASK_RECEIVE_ALL = Button(area={'cn': (1059, 618, 1093, 646), 'en': (1059, 618, 1093, 646), 'jp': (1059, 618, 1093, 646), 'tw': (1059, 618, 1093, 646)}, color={'cn': (247, 220, 119), 'en': (247, 220, 119), 'jp': (247, 220, 119), 'tw': (247, 220, 119)}, button={'cn': (1059, 618, 1093, 646), 'en': (1059, 618, 1093, 646), 'jp': (1059, 618, 1093, 646), 'tw': (1059, 618, 1093, 646)}, file={'cn': './assets/cn/island/ISLAND_SEASON_TASK_RECEIVE_ALL.png', 'en': './assets/cn/island/ISLAND_SEASON_TASK_RECEIVE_ALL.png', 'jp': './assets/cn/island/ISLAND_SEASON_TASK_RECEIVE_ALL.png', 'tw': './assets/cn/island/ISLAND_SEASON_TASK_RECEIVE_ALL.png'}) ISLAND_SEASON_TASK_SCROLL_AREA = Button(area={'cn': (1236, 171, 1237, 604), 'en': (1236, 171, 1237, 604), 'jp': (1236, 171, 1237, 604), 'tw': (1236, 171, 1237, 604)}, color={'cn': (191, 195, 192), 'en': (191, 195, 192), 'jp': (191, 195, 192), 'tw': (191, 195, 192)}, button={'cn': (1236, 171, 1237, 604), 'en': (1236, 171, 1237, 604), 'jp': (1236, 171, 1237, 604), 'tw': (1236, 171, 1237, 604)}, file={'cn': './assets/cn/island/ISLAND_SEASON_TASK_SCROLL_AREA.png', 'en': './assets/cn/island/ISLAND_SEASON_TASK_SCROLL_AREA.png', 'jp': './assets/cn/island/ISLAND_SEASON_TASK_SCROLL_AREA.png', 'tw': './assets/cn/island/ISLAND_SEASON_TASK_SCROLL_AREA.png'}) TEMPLATE_ISLAND_BUSINESS_BEAR = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_BUSINESS_BEAR.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_BUSINESS_BEAR.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_BUSINESS_BEAR.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_BUSINESS_BEAR.png'}) @@ -32,5 +36,23 @@ TEMPLATE_ISLAND_BUSINESS_GRILL = Template(file={'cn': './assets/cn/island/TEMPLA TEMPLATE_ISLAND_BUSINESS_KOI = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_BUSINESS_KOI.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_BUSINESS_KOI.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_BUSINESS_KOI.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_BUSINESS_KOI.png'}) TEMPLATE_ISLAND_BUSINESS_RESTING = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_BUSINESS_RESTING.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_BUSINESS_RESTING.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_BUSINESS_RESTING.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_BUSINESS_RESTING.png'}) TEMPLATE_ISLAND_BUSINESS_RUNNING = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_BUSINESS_RUNNING.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_BUSINESS_RUNNING.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_BUSINESS_RUNNING.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_BUSINESS_RUNNING.png'}) +TEMPLATE_ISLAND_PRODUCTION_ANCHOR_ICON = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ANCHOR_ICON.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ANCHOR_ICON.png', 'jp': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ANCHOR_ICON.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ANCHOR_ICON.png'}) +TEMPLATE_ISLAND_PRODUCTION_BEAR = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_BEAR.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_BEAR.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_BEAR.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_BEAR.png'}) +TEMPLATE_ISLAND_PRODUCTION_CAFE = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_CAFE.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_CAFE.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_CAFE.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_CAFE.png'}) +TEMPLATE_ISLAND_PRODUCTION_CRAFTS = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_CRAFTS.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_CRAFTS.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_CRAFTS.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_CRAFTS.png'}) +TEMPLATE_ISLAND_PRODUCTION_EATERY = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_EATERY.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_EATERY.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_EATERY.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_EATERY.png'}) +TEMPLATE_ISLAND_PRODUCTION_ELECTRONIC = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ELECTRONIC.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ELECTRONIC.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_ELECTRONIC.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ELECTRONIC.png'}) +TEMPLATE_ISLAND_PRODUCTION_FIELD = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_FIELD.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_FIELD.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_FIELD.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_FIELD.png'}) +TEMPLATE_ISLAND_PRODUCTION_FISHERY = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_FISHERY.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_FISHERY.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_FISHERY.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_FISHERY.png'}) +TEMPLATE_ISLAND_PRODUCTION_GRILL = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_GRILL.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_GRILL.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_GRILL.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_GRILL.png'}) +TEMPLATE_ISLAND_PRODUCTION_KOI = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_KOI.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_KOI.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_KOI.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_KOI.png'}) +TEMPLATE_ISLAND_PRODUCTION_LUMBER = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_LUMBER.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_LUMBER.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_LUMBER.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_LUMBER.png'}) +TEMPLATE_ISLAND_PRODUCTION_MACHINERY = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_MACHINERY.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_MACHINERY.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_MACHINERY.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_MACHINERY.png'}) +TEMPLATE_ISLAND_PRODUCTION_MINE = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_MINE.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_MINE.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_MINE.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_MINE.png'}) +TEMPLATE_ISLAND_PRODUCTION_NURSERY = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_NURSERY.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_NURSERY.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_NURSERY.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_NURSERY.png'}) +TEMPLATE_ISLAND_PRODUCTION_ORCHARD = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ORCHARD.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ORCHARD.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_ORCHARD.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_ORCHARD.png'}) +TEMPLATE_ISLAND_PRODUCTION_RANCH = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_RANCH.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_RANCH.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_RANCH.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_RANCH.png'}) +TEMPLATE_ISLAND_PRODUCTION_SLOT_EMPTY = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_SLOT_EMPTY.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_SLOT_EMPTY.png', 'jp': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_SLOT_EMPTY.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_SLOT_EMPTY.png'}) +TEMPLATE_ISLAND_PRODUCTION_WOOD = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_WOOD.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_WOOD.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_PRODUCTION_WOOD.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_PRODUCTION_WOOD.png'}) TEMPLATE_ISLAND_SEASON_REWARD = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_SEASON_REWARD.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_SEASON_REWARD.png', 'jp': './assets/cn/island/TEMPLATE_ISLAND_SEASON_REWARD.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_SEASON_REWARD.png'}) TEMPLATE_ISLAND_SEASON_TASK_OBTAINED = Template(file={'cn': './assets/cn/island/TEMPLATE_ISLAND_SEASON_TASK_OBTAINED.png', 'en': './assets/cn/island/TEMPLATE_ISLAND_SEASON_TASK_OBTAINED.png', 'jp': './assets/jp/island/TEMPLATE_ISLAND_SEASON_TASK_OBTAINED.png', 'tw': './assets/cn/island/TEMPLATE_ISLAND_SEASON_TASK_OBTAINED.png'}) diff --git a/module/island/production.py b/module/island/production.py new file mode 100644 index 000000000..f8e0d24c0 --- /dev/null +++ b/module/island/production.py @@ -0,0 +1,318 @@ +from datetime import datetime + +from module.base.button import ButtonGrid +from module.base.decorator import cached_property, del_cached_property, has_cached_property +from module.base.timer import Timer +from module.base.utils import random_rectangle_vector_opted +from module.exception import RequestHumanTakeover +from module.island.assets import * +from module.island.data import DIC_ISLAND_PRODUCTION_PLACE +from module.island_handler.dock import IslandDock +from module.island_handler.dock_scanner import CharacterScanner +from module.island_handler.recipe import IslandProductionRestart, IslandRecipe +from module.logger import logger +from module.map_detection.utils import Points +from module.ui.page import page_island, page_island_manage + + +ANCHOR_AREA = (452, 7, 481, 36) +DETECT_AREA = (192, 69, 1221, 653) +NAME_AREA = (0, 0, 240, 39) +TAB_SIZE = (490, 159) +TAB_DELTA = (539, 183.5) +SLOT_ORIGIN = (62, 59) +SLOT_SIZE = (86, 86) +SLOT_DELTA = (95 - 1/3, 0) +TICK_AREA = (30, 35, 52, 51) +CHARACTER_SELECT_TITLE_AREA = (515, 144, 765, 202) + + +class IslandProduction(IslandRecipe, IslandDock): + slot_finish_time = {} + # main menu related methods + def _get_tabs(self): + area = (DETECT_AREA[0] + ANCHOR_AREA[0], DETECT_AREA[1] + ANCHOR_AREA[1], DETECT_AREA[2] - TAB_SIZE[0] + ANCHOR_AREA[2], DETECT_AREA[3] - TAB_SIZE[1] + ANCHOR_AREA[3]) + image = self.image_crop(area, copy=True) + anchors = TEMPLATE_ISLAND_PRODUCTION_ANCHOR_ICON.match_multi(image, similarity=0.92, threshold=5) + logger.attr('Production_tabs', len(anchors)) + rows = Points([(0., a.area[1]) for a in anchors]).group(threshold=5) + return rows + + @cached_property + def production_grid(self): + for _ in self.loop(timeout=6): + grid = self.get_production_grid() + if len(grid.buttons) >= 4: + return grid + return grid + + def get_production_grid(self): + rows = self._get_tabs() + count = len(rows) + if count < 2: + logger.warning('Unable to find enough production tab anchors, assume tabs are at top') + origin_y = 70 + delta_y = TAB_DELTA[1] + elif count < 4: + y_list = rows[:, 1] + y1, y2 = y_list[0], y_list[-1] + origin_y = min(y1, y2) + DETECT_AREA[1] + delta_y = TAB_DELTA[1] + else: + logger.warning(f'Unexpected production tab anchor match result: {[a for a in rows]}') + origin_y = 70 + delta_y = TAB_DELTA[1] + + production_grid = ButtonGrid( + origin=(192, origin_y), delta=(TAB_DELTA[0], delta_y), button_shape=TAB_SIZE, + grid_shape=(2, count), name='PRODUCTION_GRID' + ) + return production_grid + + @cached_property + def production_names(self): + return self.get_production_codename() + + def get_production_codename(self): + template_to_codename = { + TEMPLATE_ISLAND_PRODUCTION_FIELD: 101, + TEMPLATE_ISLAND_PRODUCTION_RANCH: 102, + TEMPLATE_ISLAND_PRODUCTION_FISHERY: 201, + TEMPLATE_ISLAND_PRODUCTION_MINE: 401, + TEMPLATE_ISLAND_PRODUCTION_WOOD: 402, + TEMPLATE_ISLAND_PRODUCTION_ORCHARD: 501, + TEMPLATE_ISLAND_PRODUCTION_NURSERY: 502, + TEMPLATE_ISLAND_PRODUCTION_KOI: 601, + TEMPLATE_ISLAND_PRODUCTION_BEAR: 602, + TEMPLATE_ISLAND_PRODUCTION_EATERY: 603, + TEMPLATE_ISLAND_PRODUCTION_GRILL: 604, + TEMPLATE_ISLAND_PRODUCTION_LUMBER: 703, + TEMPLATE_ISLAND_PRODUCTION_MACHINERY: 704, + TEMPLATE_ISLAND_PRODUCTION_ELECTRONIC: 705, + TEMPLATE_ISLAND_PRODUCTION_CRAFTS: 706, + TEMPLATE_ISLAND_PRODUCTION_CAFE: 901, + } + name_grid = self.production_grid.crop(NAME_AREA, name='PRODUCTION_NAME_GRID') + name_images = [self.image_crop(button.area, copy=True) for button in name_grid.buttons] + codenames = [] + for image in name_images: + for template, codename in template_to_codename.items(): + if template.match(image): + codenames.append(codename) + break + else: + logger.warning('Failed to recognize production name') + codenames.append(None) + logger.attr('Codenames', codenames) + return codenames + + @cached_property + def slot_grids(self): + return self.get_production_slot_grids() + + def get_production_slot_grids(self): + slot_grids = {} + names = self.production_names + for codename, button in zip(names, self.production_grid.buttons): + if codename not in DIC_ISLAND_PRODUCTION_PLACE: + logger.warning(f'Codename {codename} not found in DIC_ISLAND_PRODUCTION_PLACE, skip slot grid creation') + continue + slot_length = len(DIC_ISLAND_PRODUCTION_PLACE[codename]['slot']) + slot_grid = ButtonGrid( + origin=(button.area[0] + SLOT_ORIGIN[0], button.area[1] + SLOT_ORIGIN[1]), delta=SLOT_DELTA, button_shape=SLOT_SIZE, + grid_shape=(slot_length, 1), name=f'{codename}_SLOT_GRID' + ) + slot_grids[codename] = slot_grid + return slot_grids + + def is_slot_finished(self, slot_button: Button): + tick_button = slot_button.crop(area=TICK_AREA, name=f'{slot_button.name}_TICK') + return self.image_color_count(tick_button, (255, 255, 255), threshold=240, count=85) + + def is_slot_empty(self, slot_button: Button): + image = self.image_crop(slot_button.area, copy=True) + return TEMPLATE_ISLAND_PRODUCTION_SLOT_EMPTY.match(image) + + def next_page(self): + if 901 in self.production_names: + logger.info('Already at last page, cannot swipe to next page') + return False + p1, p2 = random_rectangle_vector_opted((0, -450), box=(690, 70, 720, 650), padding=0) + self.device.drag(p1, p2, hold_duration=0.1, name='PRODUCTION_NEXT_PAGE_SWIPE') + del_cached_property(self, 'production_grid') + del_cached_property(self, 'production_names') + del_cached_property(self, 'slot_grids') + for _ in self.loop(timeout=1): + if self.handle_island_additional(): + break + return True + + def prev_page(self): + if 101 in self.production_names: + logger.info('Already at first page, cannot swipe to previous page') + return False + p1, p2 = random_rectangle_vector_opted((0, 450), box=(690, 70, 720, 650), padding=0) + self.device.drag(p1, p2, name='PRODUCTION_PREV_PAGE_SWIPE') + del_cached_property(self, 'production_grid') + del_cached_property(self, 'production_names') + del_cached_property(self, 'slot_grids') + for _ in self.loop(timeout=1): + if self.handle_island_additional(): + break + return True + + def ensure_top_page(self): + for _ in self.loop(): + if 101 in self.production_names: + break + if not self.prev_page(): + break + self.device.click_record_clear() + + def is_enter_window_shown(self): + return self.image_color_count(CHARACTER_SELECT_TITLE_AREA, (62, 193, 255), threshold=221, count=6000) + + def claim_slot_reward(self, slot_button: Button): + if not self.is_slot_finished(slot_button): + logger.warning(f'Slot {slot_button} is not finished, cannot receive reward') + return False + for _ in self.loop(timeout=4): + if self.handle_island_additional(): + continue + if self.appear_then_click(ISLAND_PRODUCTION_RECEIVE, offset=(120, 20), interval=2): + continue + if self.ui_page_appear(page_island_manage, interval=2) and not self.is_enter_window_shown(): + self.device.click(slot_button) + continue + if self.is_enter_window_shown() and self.appear(ISLAND_PRODUCTION_SELECT_CHARACTER, offset=(60, 20)): + break + for _ in self.loop(): + if self.handle_island_additional(): + continue + if self.is_enter_window_shown() or self.appear(ISLAND_PRODUCTION_RERUN, offset=(20, 20)): + self.device.click(ISLAND_CLICK_SAFE_AREA) + continue + if self.match_template_color(page_island_manage.check_button) and not self.is_enter_window_shown() and not self.appear(ISLAND_PRODUCTION_SELECT_CHARACTER, offset=(60, 20)): + return True + + def claim_reward_in_page(self, finished_slots=[]): + for place_id, slot_grid in self.slot_grids.items(): + for slot_id, slot_button in zip(DIC_ISLAND_PRODUCTION_PLACE[place_id]['slot'], slot_grid.buttons): + if self.is_slot_finished(slot_button) or self.slot_finish_time.get(slot_id, datetime.max) <= datetime.now(): + self.claim_slot_reward(slot_button) + if slot_id in self.slot_finish_time: + del self.slot_finish_time[slot_id] + + def claim_all_rewards(self): + logger.hr("Claim Production Rewards", level=2) + self.ensure_top_page() + while 1: + self.claim_reward_in_page() + if not self.next_page(): + break + + def dispatch_slot(self, slot_id, slot_button, worker='manjuu'): + if slot_id in DIC_ISLAND_PRODUCTION_PLACE[102]['slot']: + del_cached_property(super(), 'recipe_id_sequence') + del_cached_property(super(), 'all_recipe_stocks') + for _ in self.loop(): + if self.is_in_island_dock(): + break + if self.appear_then_click(ISLAND_PRODUCTION_SELECT_CHARACTER, offset=(60, 20), interval=1): + continue + if self.match_template_color(page_island_manage.check_button, interval=1) and not self.is_enter_window_shown(): + self.device.click(slot_button) + continue + if worker != 'manjuu': + character = self.island_dock_find_character(worker) + if not character or character.status != 'free': + logger.warning(f'Failed to select character {worker} for slot {slot_id}, try to select manjuu instead') + worker = 'manjuu' + self.ensure_dock_page_at_top() + if worker == 'manjuu': + self.island_dock_select_manjuu() + self.island_dock_select_confirm(self.is_in_recipe_menu) + target_time = super().run(slot_id=slot_id) + if target_time is not None: + target_time = target_time.replace(microsecond=0) + self.slot_finish_time[slot_id] = target_time + for _ in self.loop(timeout=5): + if self.handle_island_additional(): + continue + if self.match_template_color(page_island_manage.check_button, offset=(0, 20)): + return True + else: + logger.warning(f'Failed to start production for slot {slot_id}') + if slot_id in [9031, 9032, 9033, 9034]: + del_cached_property(super(), 'recipe_id_sequence') + del_cached_property(super(), 'all_recipe_stocks') + self.ui_back(check_button=page_island_manage.check_button) + self.ensure_island_production_page() + return False + + def dispatch_place(self, place_id): + if place_id not in self.slot_grids: + logger.error(f'Place id {place_id} not found in current production page') + return False + slot_grid = self.slot_grids[place_id] + is_first = True + for slot_id, slot_button in zip(DIC_ISLAND_PRODUCTION_PLACE[place_id]['slot'], slot_grid.buttons): + if not is_first and has_cached_property(super(), 'recipe_id_sequence') and not self.recipe_id_sequence: + logger.info(f'No more recipe for place {place_id}, skip remaining slots') + break + if self.is_slot_empty(slot_button): + self.dispatch_slot(slot_id=slot_id, slot_button=slot_button, worker='manjuu') + if is_first: + is_first = False + del_cached_property(super(), 'recipe_id_sequence') + del_cached_property(super(), 'all_recipe_stocks') + + def dispatch_all(self): + logger.hr("Dispatch Production", level=2) + self.ensure_top_page() + self.failed_buy_items = set() + dispatched_places = set() + while 1: + try: + for place_id in self.slot_grids.keys(): + if place_id not in dispatched_places: + self.dispatch_place(place_id) + dispatched_places.add(place_id) + if not self.next_page(): + break + except IslandProductionRestart as e: + if not e.success: + self.failed_buy_items.add(e.item_id) + logger.info('Production restarted, continue from current page') + del_cached_property(self, 'production_grid') + del_cached_property(self, 'production_names') + del_cached_property(self, 'slot_grids') + continue + + def ensure_island_production_page(self): + self.ui_ensure(page_island_manage) + for _ in self.loop(timeout=10): + if self.ui_page_appear(page_island_manage, offset=(0, 20)): + break + self.island_manage_side_navbar_ensure(upper=1, skip_first_screenshot=False) + for _ in self.loop(): + rows = self._get_tabs() + count = len(rows) + if count >= 2: + break + + def run(self): + self.ensure_island_production_page() + slot_finish_time = self.config.cross_get("IslandProduction.Storage.Storage.SlotFinishTime", default={}) + self.slot_finish_time = {int(k): datetime.fromisoformat(v) for k, v in slot_finish_time.items()} + self.claim_all_rewards() + self.dispatch_all() + next_run_time = list(self.slot_finish_time.values()) + with self.config.multi_set(): + sorted_items = sorted(self.slot_finish_time.items(), key=lambda kv: (kv[1], kv[0])) + slot_finish_time = {k: v.isoformat(sep=' ') for k, v in sorted_items} + self.config.cross_set("IslandProduction.Storage.Storage.SlotFinishTime", slot_finish_time) + if next_run_time: + self.config.task_delay(target=next_run_time) + else: + self.config.task_delay(minute=30)