ksaa 2025.5.16.1__py3-none-any.whl → 2025.5.23.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. kotonebot/__init__.py +0 -2
  2. kotonebot/backend/bot.py +19 -34
  3. kotonebot/backend/color.py +20 -17
  4. kotonebot/backend/context/context.py +41 -8
  5. kotonebot/backend/core.py +7 -30
  6. kotonebot/backend/dispatch.py +1 -1
  7. kotonebot/backend/image.py +26 -26
  8. kotonebot/backend/ocr.py +18 -17
  9. kotonebot/backend/preprocessor.py +0 -1
  10. kotonebot/client/__init__.py +8 -1
  11. kotonebot/client/device.py +7 -20
  12. kotonebot/client/factory.py +33 -5
  13. kotonebot/client/host/__init__.py +8 -1
  14. kotonebot/client/host/custom.py +7 -2
  15. kotonebot/client/host/leidian_host.py +200 -0
  16. kotonebot/client/host/mumu12_host.py +177 -0
  17. kotonebot/client/host/protocol.py +68 -38
  18. kotonebot/client/implements/adb.py +1 -1
  19. kotonebot/client/protocol.py +1 -1
  20. kotonebot/config/base_config.py +8 -3
  21. kotonebot/interop/win/reg.py +37 -0
  22. kotonebot/kaa/common.py +18 -2
  23. kotonebot/kaa/game_ui/badge.py +6 -6
  24. kotonebot/kaa/game_ui/common.py +6 -6
  25. kotonebot/kaa/game_ui/commu_event_buttons.py +4 -3
  26. kotonebot/kaa/game_ui/idols_overview.py +6 -6
  27. kotonebot/kaa/game_ui/schedule.py +162 -0
  28. kotonebot/kaa/game_ui/scrollable.py +7 -6
  29. kotonebot/kaa/kaa_context.py +8 -0
  30. kotonebot/kaa/main/cli.py +7 -0
  31. kotonebot/kaa/main/dmm_host.py +53 -0
  32. kotonebot/kaa/main/gr.py +508 -298
  33. kotonebot/kaa/main/kaa.py +77 -1
  34. kotonebot/kaa/metadata.py +26 -0
  35. kotonebot/kaa/resources/__pycache__/__init__.cpython-310.pyc +0 -0
  36. kotonebot/kaa/resources/game.db +0 -0
  37. kotonebot/kaa/resources/game_ver.txt +0 -0
  38. kotonebot/kaa/sprites/4503db6b-7224-4b81-9971-e7cfa56e10f2.png +0 -0
  39. kotonebot/kaa/tasks/R.py +137 -133
  40. kotonebot/kaa/tasks/daily/contest.py +123 -89
  41. kotonebot/kaa/tasks/daily/mission_reward.py +4 -4
  42. kotonebot/kaa/tasks/end_game.py +2 -9
  43. kotonebot/kaa/tasks/produce/cards.py +7 -6
  44. kotonebot/kaa/tasks/produce/common.py +16 -12
  45. kotonebot/kaa/tasks/produce/in_purodyuusu.py +5 -5
  46. kotonebot/kaa/tasks/produce/p_drink.py +4 -3
  47. kotonebot/kaa/tasks/produce/produce.py +5 -3
  48. kotonebot/kaa/tasks/start_game.py +2 -2
  49. kotonebot/primitives/__init__.py +17 -0
  50. kotonebot/primitives/geometry.py +290 -0
  51. kotonebot/primitives/visual.py +63 -0
  52. kotonebot/util.py +20 -20
  53. {ksaa-2025.5.16.1.dist-info → ksaa-2025.5.23.1.dist-info}/METADATA +1 -1
  54. {ksaa-2025.5.16.1.dist-info → ksaa-2025.5.23.1.dist-info}/RECORD +191 -183
  55. {ksaa-2025.5.16.1.dist-info → ksaa-2025.5.23.1.dist-info}/WHEEL +1 -1
  56. /kotonebot/{client/host/mumu_host.py → interop/win/__init__.py} +0 -0
  57. /kotonebot/kaa/sprites/{7971b595-44d3-4ce7-91ae-a8e5a25c543b.png → 02ff2b86-db5a-4850-ac98-4288a3f71ed8.png} +0 -0
  58. /kotonebot/kaa/sprites/{bc64dd37-48ba-45a5-af6d-457a7fb2c9fd.png → 04422a5d-2499-40fd-a08f-095ecbd051a8.png} +0 -0
  59. /kotonebot/kaa/sprites/{17da97eb-93c5-438f-8688-0be5b0756019.png → 0672e1c6-6abc-452c-82b3-af6eb7454cfa.png} +0 -0
  60. /kotonebot/kaa/sprites/{5089ea64-3f32-4520-a252-4ee278815cdd.png → 07960be4-b575-4f7f-be64-7e344dc118e0.png} +0 -0
  61. /kotonebot/kaa/sprites/{0f67c0a6-45d0-4953-b1a9-b5eb2c916173.png → 09cd4336-7d2a-4bce-9d08-8ac64a2bdcc3.png} +0 -0
  62. /kotonebot/kaa/sprites/{5ed9bef4-ab11-4186-9b21-a479eec687ce.png → 09fda5a8-c546-48f0-ae29-ebe4f4208d8b.png} +0 -0
  63. /kotonebot/kaa/sprites/{7dec3bd9-f8ee-430f-af54-0c03c4c91546.png → 0b5c2d3f-28b1-456f-a452-05ca006f8b33.png} +0 -0
  64. /kotonebot/kaa/sprites/{76b0e3b3-3438-4e88-aca8-da18c8e50ddd.png → 0c359f2a-72d4-4203-9ca3-968a1948eee8.png} +0 -0
  65. /kotonebot/kaa/sprites/{9e110778-1b66-4700-b462-64c1dea368da.png → 0ecc3e37-189c-40ad-9ee6-fb576b72a13b.png} +0 -0
  66. /kotonebot/kaa/sprites/{bbcb97e2-89b7-4de2-b480-a0442fc33b1e.png → 11c2ff97-3303-4d6d-8e4f-6da2148bbe20.png} +0 -0
  67. /kotonebot/kaa/sprites/{36d712ce-9227-4aef-86ee-4f78415b0c80.png → 128886a7-7629-4158-9538-3619542f775b.png} +0 -0
  68. /kotonebot/kaa/sprites/{ba07fa5e-3451-4520-8b10-0b240e5decec.png → 13a85dbd-e226-47cc-b6f5-c0d3b40654f5.png} +0 -0
  69. /kotonebot/kaa/sprites/{f71df091-fc71-48d4-8124-b3c46f4c4436.png → 13c8fa4a-0ae5-4ee1-a433-20f6c724466e.png} +0 -0
  70. /kotonebot/kaa/sprites/{02e69560-ec42-4453-b771-8600b5726b93.png → 18042dda-0222-4333-9d79-3afc3dc75220.png} +0 -0
  71. /kotonebot/kaa/sprites/{420e4ff4-82a3-4ea3-98a7-63efe65003a6.png → 18670c18-07e3-4378-a8fc-4f9b331db00f.png} +0 -0
  72. /kotonebot/kaa/sprites/{027dd54f-09d8-452d-8eff-66b06aecd264.png → 1959c932-1bbf-4fee-b3a1-2ecfbc6d4209.png} +0 -0
  73. /kotonebot/kaa/sprites/{b673cc06-14ef-4a22-b484-13a17b01b0d4.png → 1a8ec83b-ebba-4ff7-9737-104d3aa2ff98.png} +0 -0
  74. /kotonebot/kaa/sprites/{1e6d734e-7bc5-4f3f-a717-3931f44a7709.png → 1b6bc9ae-3f4e-4722-ae6f-d76bd65b071e.png} +0 -0
  75. /kotonebot/kaa/sprites/{0bd326fd-fad0-4e6c-957c-da08583ef231.png → 1e4671aa-2cdc-4432-9d83-c635e0a3d09d.png} +0 -0
  76. /kotonebot/kaa/sprites/{e941ae91-59bf-4a69-945b-1bcd7cf241c6.png → 2490bd58-bcf7-4c94-ab24-04e752137939.png} +0 -0
  77. /kotonebot/kaa/sprites/{f790aed5-b9f3-4c93-a14f-47629f53052d.png → 25cfb896-fed1-4361-ae64-fc45fc8a98dd.png} +0 -0
  78. /kotonebot/kaa/sprites/{6e81e54e-b69b-434a-8bbf-6e2551bddeb8.png → 2730beb1-a6c5-463d-9748-393764bc8e34.png} +0 -0
  79. /kotonebot/kaa/sprites/{3f0b91e1-898a-4f44-b116-38483bc30461.png → 2766af5c-4ad1-44e2-ab84-e8a6ac7bb172.png} +0 -0
  80. /kotonebot/kaa/sprites/{4fca090a-b94a-433a-8438-832a54ff65e8.png → 2cc68858-7af0-4a12-8c78-c4e4dcf9fff1.png} +0 -0
  81. /kotonebot/kaa/sprites/{04b4ccde-a374-4df3-b0fa-552ae1518348.png → 2e68066d-9a56-48cc-8711-1d4c080ee320.png} +0 -0
  82. /kotonebot/kaa/sprites/{4a9e612b-9e52-4eb5-a851-3e5ad68030e9.png → 32d50687-b3a2-4b34-a2f9-4418b5e14fff.png} +0 -0
  83. /kotonebot/kaa/sprites/{2179ff5c-7964-42b1-9a95-c0bd8af1b692.png → 344bedf1-fcca-4025-9ff6-cea99c91ddb4.png} +0 -0
  84. /kotonebot/kaa/sprites/{99e95c59-d5da-448d-b839-51428b2686f0.png → 346da82f-bfca-4a0f-bae4-ca9c8e4b794e.png} +0 -0
  85. /kotonebot/kaa/sprites/{be7504d5-48e5-404c-a74d-f7fa86acf276.png → 379a8811-932c-4c75-854f-943631c921d5.png} +0 -0
  86. /kotonebot/kaa/sprites/{d11d8839-90ef-433c-8555-fad5478009a0.png → 38f8f55f-e9dc-4c10-b97a-b7254d871ae9.png} +0 -0
  87. /kotonebot/kaa/sprites/{03c9182c-b5ba-4404-b6f9-50b06a86e102.png → 39b1738f-af9a-4c85-9315-2858f0b1d1ab.png} +0 -0
  88. /kotonebot/kaa/sprites/{fb529219-fc53-43e1-83ca-2313d1d33636.png → 3a58e019-6328-412a-9d2f-85a73900371e.png} +0 -0
  89. /kotonebot/kaa/sprites/{d4673e38-cf76-4062-9a71-0f31936fe49b.png → 3c2f70b5-9095-48d6-a012-4d68a6b0a975.png} +0 -0
  90. /kotonebot/kaa/sprites/{e753b92e-99bf-4d81-9673-92b5f67d129b.png → 3d016208-f8ed-45be-bfb1-ed15b231d0b8.png} +0 -0
  91. /kotonebot/kaa/sprites/{0b0e76ce-60cc-45cc-b204-227e59d39c26.png → 3e2af23e-041f-4128-8a78-cbd1297538cf.png} +0 -0
  92. /kotonebot/kaa/sprites/{edb144e1-7c82-4fcf-b426-c6294ad2112d.png → 429c30b5-7d3a-40a1-853a-ec51c8f238e7.png} +0 -0
  93. /kotonebot/kaa/sprites/{de619141-10a4-4447-89b3-6cabcbf52d8a.png → 440eeea3-b710-485e-ab40-80e2b6ce66f0.png} +0 -0
  94. /kotonebot/kaa/sprites/{1607c23d-3ab4-418b-8114-1a3bb782d246.png → 46f24175-8657-497d-97e6-1c1ee356e4cd.png} +0 -0
  95. /kotonebot/kaa/sprites/{3eb037db-4cd8-4c00-a655-fa73f612adfd.png → 4a128979-bf11-42fe-a966-a8f5ee143128.png} +0 -0
  96. /kotonebot/kaa/sprites/{7b07a31c-9e2b-4ce0-8998-ccc0592de5e0.png → 4a5ec641-38ec-46b0-83c4-d7edacb754b0.png} +0 -0
  97. /kotonebot/kaa/sprites/{e97e58cb-3412-4a8c-9a9e-dd45daa5ae02.png → 4a9c1ac7-0a61-4d40-b749-e8896322581f.png} +0 -0
  98. /kotonebot/kaa/sprites/{9fd268df-96b7-4b48-a6d1-b5da2161da8e.png → 4af7631b-3674-4491-a3fb-a514bfd6b204.png} +0 -0
  99. /kotonebot/kaa/sprites/{32a1072b-c359-4dad-80f6-c9ca558e5f99.png → 4c2c5378-d946-41c2-980e-afb8493f71ee.png} +0 -0
  100. /kotonebot/kaa/sprites/{1a668ad4-d6b0-4aed-bb99-8b1ac85659d3.png → 4c4dd8e5-5370-4381-b6d4-c260b32015cf.png} +0 -0
  101. /kotonebot/kaa/sprites/{32793e3b-613b-4b6d-bc2e-25f9993f6274.png → 4c5b8c40-3dfa-4091-95c3-257a36e9a6d3.png} +0 -0
  102. /kotonebot/kaa/sprites/{d3fa5988-1184-4478-abb9-1c9799bd4100.png → 4d0b8533-b3e2-4ea1-8204-a8d5e67e1f64.png} +0 -0
  103. /kotonebot/kaa/sprites/{0de838fb-24e9-4fe8-8e2a-cc26bce6d7d8.png → 50e462d5-ca14-4934-b35a-da3ebb8fb33f.png} +0 -0
  104. /kotonebot/kaa/sprites/{d2830bf7-e0c4-4d00-868a-6df22bdf6fcd.png → 557389eb-d0da-4c5a-a322-de3e32a81909.png} +0 -0
  105. /kotonebot/kaa/sprites/{979c7468-d9ef-4cc1-9449-2aa716caabb0.png → 57b7006a-ada9-4d9d-9655-71765251882e.png} +0 -0
  106. /kotonebot/kaa/sprites/{8f39322e-92d2-4cc6-80ef-341884b0a598.png → 59ef821b-4803-4fe3-83b8-305902f8459a.png} +0 -0
  107. /kotonebot/kaa/sprites/{a0b83694-4945-4476-aa2e-f268841ac372.png → 5af71b93-310c-48ab-b438-dba296fb9e52.png} +0 -0
  108. /kotonebot/kaa/sprites/{a03e79b3-7f44-4211-b625-2510ba8031bc.png → 5b6b5bf8-cd03-4360-9550-e15d8db6241a.png} +0 -0
  109. /kotonebot/kaa/sprites/{2fd33c51-b3a7-4ffb-9555-d25961186eee.png → 5d963589-623d-4a49-9c72-af91134720b0.png} +0 -0
  110. /kotonebot/kaa/sprites/{f4c8a757-674e-45ca-af2c-0bc409b7bca8.png → 5f01b811-9aad-4439-a70b-c099a42c36fa.png} +0 -0
  111. /kotonebot/kaa/sprites/{a1c29e77-138c-4580-a777-666815039524.png → 601d0743-7143-4c04-989b-b80fc620e678.png} +0 -0
  112. /kotonebot/kaa/sprites/{4aed7e90-76b1-4837-a6ad-e2ed2e3240ec.png → 63e71ec7-6290-4efa-89cf-69c53d805a58.png} +0 -0
  113. /kotonebot/kaa/sprites/{c15ad104-3814-467c-a211-1e54be35fc66.png → 66f5fab8-274c-4ab9-983d-ca2f8d90ea94.png} +0 -0
  114. /kotonebot/kaa/sprites/{8031a52b-afe1-4ebd-9599-1d123bc0e48b.png → 6abb63c1-025a-425e-8f33-29f83f504d75.png} +0 -0
  115. /kotonebot/kaa/sprites/{ad26884a-8371-420f-be89-7fe82ddaf1e8.png → 6d6550a6-f270-474e-b55c-b2017ef87ab2.png} +0 -0
  116. /kotonebot/kaa/sprites/{bf158b17-4d93-40f1-b9cf-4ae9226bcfc1.png → 7057e165-9ed4-485e-9609-94854ef269dd.png} +0 -0
  117. /kotonebot/kaa/sprites/{fa64ed03-4277-4ae2-a958-adb93c393457.png → 78c2c39e-6621-41d1-9a1e-7e171b001795.png} +0 -0
  118. /kotonebot/kaa/sprites/{f32e04e8-2e9a-49c2-9734-d0a02ed2d892.png → 798a9587-3f8c-424e-90af-89a08ed62ced.png} +0 -0
  119. /kotonebot/kaa/sprites/{b677c2ba-62da-4afd-8ba7-a9b40362b5bb.png → 7bbac9cd-417f-4bd5-975a-a8a25c7bd922.png} +0 -0
  120. /kotonebot/kaa/sprites/{d1a8f72b-813b-4d8a-a596-5576758d7fe2.png → 7c2f9216-56f2-4eec-8a45-1bd864316dad.png} +0 -0
  121. /kotonebot/kaa/sprites/{fe7e4f2b-b795-43b6-bf0a-4e65c9133a40.png → 7c992bae-5ded-473b-8e60-4dede8434e5d.png} +0 -0
  122. /kotonebot/kaa/sprites/{e73cacc9-08aa-4b7a-acd3-3dbe95d9f51c.png → 7e7e8772-b31a-4bbe-919e-90373a4ad5a7.png} +0 -0
  123. /kotonebot/kaa/sprites/{39151ffc-365e-45b2-a2f4-9d4c76d41524.png → 80171520-d132-4395-b2ed-e6451335b3d5.png} +0 -0
  124. /kotonebot/kaa/sprites/{04180b4a-1532-42dd-9280-0f47c1e68959.png → 82cf688e-ac85-4425-917d-10b6db9b6cc3.png} +0 -0
  125. /kotonebot/kaa/sprites/{ebcaaba7-57f8-4bcb-93da-a288a0fcc95e.png → 87292951-43c1-4039-9b92-c59c1b25b5f7.png} +0 -0
  126. /kotonebot/kaa/sprites/{4dd7db2d-3107-4fc5-8f30-cfa70bc28de1.png → 893a6bba-905e-4123-9e35-f829fd6c8b2a.png} +0 -0
  127. /kotonebot/kaa/sprites/{f9e0be54-237b-4092-8784-1a4d2eb43097.png → 8a605d31-3160-49d1-9098-45d8ee18e8d6.png} +0 -0
  128. /kotonebot/kaa/sprites/{334d4915-4600-4c81-bbb0-c52291b7d089.png → 8cb3b6c2-7fae-41cf-8f33-a0e3ea668f25.png} +0 -0
  129. /kotonebot/kaa/sprites/{6abe81b7-1a04-44e9-b390-affe47799c46.png → 8e1ca316-39e6-4b9f-b497-84ad8848a3e1.png} +0 -0
  130. /kotonebot/kaa/sprites/{f14cc536-f38c-4568-9812-d3ed95e639d3.png → 8f675963-122a-4932-9f33-07dcdcb3a51a.png} +0 -0
  131. /kotonebot/kaa/sprites/{0df088e0-737f-44ec-b39f-76239d087382.png → 907dc373-e2f5-4959-84cb-d7971a7fefd8.png} +0 -0
  132. /kotonebot/kaa/sprites/{7d5b4d44-cb46-49fb-96be-edaab5396836.png → 9359526e-c5db-4d63-adc4-08b7d704b422.png} +0 -0
  133. /kotonebot/kaa/sprites/{2860421f-2db8-4850-9f0c-0aca8bbf16d0.png → 96178cef-4868-4378-9f9c-c08780def3d6.png} +0 -0
  134. /kotonebot/kaa/sprites/{a477c873-98bd-45f0-a9a6-324e714c69cd.png → 985ec867-bc7c-47c5-8fcd-75f736f27507.png} +0 -0
  135. /kotonebot/kaa/sprites/{669f9e7c-b665-47a8-b4f5-fb2748bf88af.png → 9c98c4e6-5335-4c8b-92fa-24ec440b055e.png} +0 -0
  136. /kotonebot/kaa/sprites/{1373ec63-fd98-4be9-a925-08144f1d5ba5.png → a015cea0-d2c7-439a-b942-d4d2dad276e5.png} +0 -0
  137. /kotonebot/kaa/sprites/{6fec0efa-336f-4726-b1d9-dc83c23b297d.png → a05abc9d-9f0e-4d83-94bb-4f0b1e061035.png} +0 -0
  138. /kotonebot/kaa/sprites/{957dbdc4-8367-4a59-9bfc-d35ea11af9b8.png → a2e41d98-dd91-4e51-ba57-4f8ddfd07cfa.png} +0 -0
  139. /kotonebot/kaa/sprites/{8e78e1f1-ea2f-4779-a8cd-56336f936c81.png → a402b549-a4dd-4ff3-ad51-2aa5f8e620af.png} +0 -0
  140. /kotonebot/kaa/sprites/{ff493975-0f30-468f-a3ea-17505a2b0385.png → a5efb332-8452-49d8-ade3-882bbd445553.png} +0 -0
  141. /kotonebot/kaa/sprites/{dfe2fc89-eaf7-4027-bb53-dd17a9741e01.png → a9f47d53-fbef-4cb0-9d2d-845ef3d1f719.png} +0 -0
  142. /kotonebot/kaa/sprites/{45ae4d17-1887-4f2e-8cce-e5a4cc42e10b.png → b10596fe-22fa-4284-ab4b-1d653d4f0f07.png} +0 -0
  143. /kotonebot/kaa/sprites/{9cc7997f-3aeb-4b20-ae42-468ebfbc851e.png → b326c50f-c88c-4b99-80a7-046053423a19.png} +0 -0
  144. /kotonebot/kaa/sprites/{6d706642-441f-4bcc-b377-0fce3484be22.png → b44085c7-9777-415a-aae1-aae47c2f7321.png} +0 -0
  145. /kotonebot/kaa/sprites/{54d57991-e5d0-4346-b1f8-63e429d8a3fe.png → b629f0a7-df4f-4407-908b-a031c70e8b6f.png} +0 -0
  146. /kotonebot/kaa/sprites/{63f28640-766f-4698-b556-f0a0cbac6a1a.png → b8165178-a9ce-491a-ba57-d25c7af8533f.png} +0 -0
  147. /kotonebot/kaa/sprites/{0c3cc689-90f5-4c29-be80-04e2f2ab799a.png → b8eeacac-5679-42b9-a5b9-138598c8c6b6.png} +0 -0
  148. /kotonebot/kaa/sprites/{f89cafb7-657b-4ab4-8917-1964b242ff2e.png → b9ad5832-889a-4a5f-adc0-5dfd55126d6a.png} +0 -0
  149. /kotonebot/kaa/sprites/{16576157-f99b-4a64-b41b-3ee712c2304e.png → bcb95d32-32e1-4251-83de-ef5164d22a48.png} +0 -0
  150. /kotonebot/kaa/sprites/{7e64561b-0dab-420a-8f79-45ed6801939b.png → c0ddf15a-a6f6-42f6-86b7-e17cde60b437.png} +0 -0
  151. /kotonebot/kaa/sprites/{6d4f414d-ccd8-4a25-aa32-1b77ce0035d6.png → c24e874e-6a3e-472c-8745-edf7cac88954.png} +0 -0
  152. /kotonebot/kaa/sprites/{2b87ed7c-b01b-4ea7-ab34-ec4e37e036c0.png → c362b54d-d535-4227-8612-9bfe11fd7891.png} +0 -0
  153. /kotonebot/kaa/sprites/{1e7924dc-9dd4-4d54-add8-b394c75af1c7.png → c51132e9-f45c-40c9-8026-7d70b13dca8b.png} +0 -0
  154. /kotonebot/kaa/sprites/{5663551f-5abc-4ef8-a3fd-ba57b20cb35c.png → c60bec93-231f-498d-b3c6-0a78c9b8f37f.png} +0 -0
  155. /kotonebot/kaa/sprites/{89d6407a-982c-4dbc-8dd7-89cf79429eec.png → c64ff0a8-9f96-4ca7-902b-4f7298c1c431.png} +0 -0
  156. /kotonebot/kaa/sprites/{bda40c0d-55a9-41ad-ba8a-e8aafc52608b.png → c819d999-fef6-47bb-a94f-055d616033c7.png} +0 -0
  157. /kotonebot/kaa/sprites/{1b8b2a66-fb45-41d7-8441-04425a47bdeb.png → c85e58d3-ec5a-43ea-aa2a-04ee28e9ea21.png} +0 -0
  158. /kotonebot/kaa/sprites/{b332eb23-6653-4d17-b779-2451a3b261ab.png → c883049b-187c-4685-a63a-cff516851a95.png} +0 -0
  159. /kotonebot/kaa/sprites/{60f292d1-6c2d-4cfb-af76-568610817722.png → c8f0cc49-5df8-4d7a-9ef6-2f021c2380a5.png} +0 -0
  160. /kotonebot/kaa/sprites/{7383d7d0-8ee2-4413-b590-51cff541cab3.png → c9a8d73f-f487-45ff-aa05-a61393d27f66.png} +0 -0
  161. /kotonebot/kaa/sprites/{817c22a3-ecfe-4949-a784-59342e61a880.png → cb4c357f-b01b-4b95-b928-5affdf4ae684.png} +0 -0
  162. /kotonebot/kaa/sprites/{dff3509c-f0ec-44e2-8e0b-3c6b465d45f3.png → cc0e38b2-c2ae-4fe1-adb0-6ea73a602563.png} +0 -0
  163. /kotonebot/kaa/sprites/{c7a33e9e-2f1c-4171-b1f7-7d7dcc1a7bd3.png → cdd40676-b49d-42ad-9972-7149aa13d9bb.png} +0 -0
  164. /kotonebot/kaa/sprites/{5d912f4e-c319-4d45-85e6-de6e684a6278.png → cf76eb98-44ff-406e-913a-503a0233b4cd.png} +0 -0
  165. /kotonebot/kaa/sprites/{7b195535-7362-492f-8d87-b8eed15c6fc0.png → d21117c2-3679-4bb0-a5b3-5af5d12d8d3e.png} +0 -0
  166. /kotonebot/kaa/sprites/{7d778f82-f908-4edb-9b12-d8460589ab11.png → d37bc673-9668-4b7e-bc9d-54495129dcc0.png} +0 -0
  167. /kotonebot/kaa/sprites/{08750a02-0881-443a-9c69-c90a2ccf2a63.png → dac24ef9-e53d-4d95-aa09-fa694606c3ab.png} +0 -0
  168. /kotonebot/kaa/sprites/{31271771-5149-447c-8fae-ccc308c0a838.png → dd084696-be33-4a00-b6df-b25131b78b40.png} +0 -0
  169. /kotonebot/kaa/sprites/{a35aed53-ff78-41f0-9a19-c69fda40aeef.png → de1e3c4a-f6ed-467a-889c-25c01a613477.png} +0 -0
  170. /kotonebot/kaa/sprites/{639465a0-3c63-4307-a72c-4f9e543d2095.png → e1eb4596-73a1-471e-892b-c83cfb706bb3.png} +0 -0
  171. /kotonebot/kaa/sprites/{91940a9e-2cfc-423a-86d6-49429c051ea0.png → e1ec3ee5-e73c-44b6-b173-ab1c9382cba4.png} +0 -0
  172. /kotonebot/kaa/sprites/{096d3df5-2c95-41dd-bcc3-2e3afab47420.png → e4d076bd-7824-4496-a498-d6dc01ad90ba.png} +0 -0
  173. /kotonebot/kaa/sprites/{50a9e2a0-1166-4f1d-ad15-d8493ce0e49e.png → e551148d-1b0d-4518-8711-4161863c93ef.png} +0 -0
  174. /kotonebot/kaa/sprites/{45671af1-d731-4bb1-83f7-c9d23348308f.png → e61d855e-84d3-4a0e-b996-43fce262c2c3.png} +0 -0
  175. /kotonebot/kaa/sprites/{608217f6-b880-42ab-9be9-b4d56df87be2.png → e795f9c5-fdda-4fbc-8d38-a92512a590f4.png} +0 -0
  176. /kotonebot/kaa/sprites/{7d4d708f-c629-4f52-a0af-11aee7fcb878.png → eb446c0a-1dd2-4693-838e-98a76c02eac5.png} +0 -0
  177. /kotonebot/kaa/sprites/{35e6ad3a-8020-4619-b8ec-6506a8aa51fc.png → eb4bde42-de6e-4c62-8dc4-8885efc834a8.png} +0 -0
  178. /kotonebot/kaa/sprites/{9a5e7bc9-830f-4b01-8f94-6d4f589754c0.png → ec547e11-4952-4089-9744-1e89bd44389c.png} +0 -0
  179. /kotonebot/kaa/sprites/{40e3dac1-74fb-4501-a20f-18422d070554.png → ed4a8cff-b3df-4d7a-bfc4-8da776a8e548.png} +0 -0
  180. /kotonebot/kaa/sprites/{39d57097-6839-4030-bb51-24d6cd880897.png → efc08f1c-e78f-4df8-bff9-b45cde37f9dd.png} +0 -0
  181. /kotonebot/kaa/sprites/{9f56889b-0251-4ec1-8ccb-5cfd3bddd396.png → f02d997a-a3a8-4e18-96f1-e4176c14a5e0.png} +0 -0
  182. /kotonebot/kaa/sprites/{97bbc57d-780a-40f4-8fe1-bcaef697b601.png → f5e2e4e1-40be-481d-9293-9d47a5bce7cc.png} +0 -0
  183. /kotonebot/kaa/sprites/{bee4fbe2-365f-4145-b8f4-87c2c460cd71.png → f62dd2a2-bac6-4dc8-9a19-3e995ab80a3b.png} +0 -0
  184. /kotonebot/kaa/sprites/{666b1e8c-19fb-49e9-a761-1069f635f450.png → f64cfd95-8c87-47e6-96c3-8b7df2624ae3.png} +0 -0
  185. /kotonebot/kaa/sprites/{847cb208-a71c-42e3-97f1-18d4aa886b41.png → f8bcbc2c-9831-4e8d-9ffd-e532aa3193c3.png} +0 -0
  186. /kotonebot/kaa/sprites/{9e5c5ffc-450d-4ddc-a4ae-27c33267b056.png → fb50c7d1-b983-4e36-a998-ea17a1bdb18b.png} +0 -0
  187. /kotonebot/kaa/sprites/{f1a60528-1f35-451f-92e3-b1d5407e0f4e.png → fb97d804-42e4-45e2-8b22-01d16b5d0b6b.png} +0 -0
  188. /kotonebot/kaa/sprites/{a3140a53-ffb4-4094-a39c-240e9fe42308.png → fe337541-a6a3-4325-97b4-2bf27f51f39f.png} +0 -0
  189. /kotonebot/kaa/sprites/{1a0f2a10-c23b-47c7-aa7e-89b606f4d8ae.png → ffd3c6b7-cac2-4d45-ae37-792404ea2b40.png} +0 -0
  190. {ksaa-2025.5.16.1.dist-info → ksaa-2025.5.23.1.dist-info}/entry_points.txt +0 -0
  191. {ksaa-2025.5.16.1.dist-info → ksaa-2025.5.23.1.dist-info}/top_level.txt +0 -0
@@ -7,11 +7,11 @@ from kotonebot.kaa.common import conf
7
7
  from kotonebot.kaa.game_ui import WhiteFilter
8
8
  from ..actions.scenes import at_home, goto_home
9
9
  from ..actions.loading import wait_loading_end
10
- from kotonebot import device, image, ocr, color, action, task, user, rect_expand, sleep, contains
10
+ from kotonebot import device, image, ocr, color, action, task, user, rect_expand, sleep, contains, Interval
11
11
 
12
12
  logger = logging.getLogger(__name__)
13
13
 
14
- @action('前往竞赛页面')
14
+ @action('前往竞赛页面', screenshot_mode='manual-inherit')
15
15
  def goto_contest() -> bool:
16
16
  """
17
17
  前置条件:位于首页 \n
@@ -19,103 +19,134 @@ def goto_contest() -> bool:
19
19
 
20
20
  :return: 是否存在未完成的挑战
21
21
  """
22
- # TODO: 优化这一部分,加入区域检测,提高速度
23
- device.click(image.expect(R.Common.ButtonContest))
24
- ocr.expect_wait(contains('CONTEST'))
25
- btn_contest = ocr.expect_wait(contains('コンテスト'))
26
- has_ongoing_contest = image.find(R.Daily.TextContestLastOngoing) is not None
27
- device.click(btn_contest)
28
- if not has_ongoing_contest:
29
- while not image.find(R.Daily.ButtonContestRanking):
22
+ it = Interval()
23
+ has_ongoing_contest = None
24
+ while True:
25
+ device.screenshot()
26
+ it.wait()
27
+
28
+ if image.find(R.Common.ButtonContest):
29
+ device.click()
30
+ elif image.find(R.Daily.TextRoadToIdol):
31
+ # 已进入竞赛 Tab
32
+ if image.find(R.Daily.TextContestLastOngoing):
33
+ logger.info('Ongoing contest found.')
34
+ has_ongoing_contest = True
35
+ else:
36
+ has_ongoing_contest = False
37
+ # 点击进入竞赛页面
38
+ logger.debug('Clicked on Contest.')
39
+ device.click(R.Daily.PointContest)
40
+ continue
41
+
42
+ # 有未完成的挑战
43
+ if has_ongoing_contest is True:
44
+ if image.find(R.Daily.ButtonContestChallengeStart):
45
+ logger.info('Challenging.')
46
+ break
47
+ # 新开挑战
48
+ elif has_ongoing_contest is False:
49
+ if image.find(R.Daily.ButtonContestRanking):
50
+ logger.info('Now at pick contestant screen.')
51
+ break
52
+ # 跳过奖励领取
30
53
  # [kotonebot-resource\sprites\jp\daily\screenshot_contest_season_reward.png]
31
54
  # [screenshots/contest/acquire2.png]
32
55
  device.click(R.Daily.PointDissmissContestReward)
33
- sleep(1)
34
- # [screenshots/contest/main.png]
35
- else:
36
- image.expect_wait(R.Daily.ButtonContestChallengeStart)
37
56
  return has_ongoing_contest
38
57
 
39
- @action('选择并挑战')
40
- def pick_and_contest(has_ongoing_contest: bool = False) -> bool:
58
+ @action('处理竞赛挑战', screenshot_mode='manual-inherit')
59
+ def handle_challenge() -> bool:
41
60
  """
42
- 选择并挑战
43
61
 
44
- 前置条件:位于竞赛界面 \n
45
- 结束状态:位于竞赛界面
46
-
47
- :param has_ongoing_contest: 是否有中断未完成的挑战
48
- :return: 如果返回假,说明今天挑战次数已经用完了
62
+ 前置条件:- \n
63
+ 结束状态:位于竞赛选择对手界面
64
+ :return: 是否命中任何处理
49
65
  """
50
- # 判断是否有中断未完成的挑战
51
- # [screenshots/contest/ongoing.png]
52
- if not has_ongoing_contest:
53
- image.expect_wait(R.Daily.ButtonContestRanking)
54
- sleep(3) # 等待动画
55
- # 随机选一个对手 [screenshots/contest/main.png]
56
- logger.debug('Clicking on contestant.')
57
- contestant_list = image.find_all(R.Daily.TextContestOverallStats)
58
- if contestant_list is None or len(contestant_list) == 0:
59
- logger.info('No contestant found. Today\'s challenge points used up.')
60
- return False
61
- # 按照y坐标从上到下排序对手列表
62
- contestant_list.sort(key=lambda x: x.position[1])
63
- if len(contestant_list) != 3:
64
- logger.warning('Cannot find all 3 contestants.')
65
- # 选择配置文件中对应的对手顺序(1最强,3最弱)
66
- target = conf().contest.select_which_contestant
67
- if target >= 1 and target <= 3 and target <= len(contestant_list):
68
- target -= 1 # [1, 3]映射至[0, 2]
69
- else:
70
- target = 0 # 出错则默认选择第一个
71
- contestant = contestant_list[target]
72
- logger.info('Picking up contestant #%d.', target + 1)
73
- device.click(contestant)
74
- # 挑战开始 [screenshots/contest/start1.png]
66
+ # 挑战开始 [screenshots/contest/start1.png]
67
+ if image.find(R.Daily.ButtonContestStart, threshold=0.75): # TODO: 为什么默认阈值找不到?
75
68
  logger.debug('Clicking on start button.')
76
- device.click(image.expect_wait(R.Daily.ButtonContestStart))
77
- sleep(3) # 多延迟一点
78
- # 进入挑战页面 [screenshots/contest/contest1.png]
79
- # [screenshots/contest/contest2.png]
80
- while not image.find(R.Daily.ButtonContestChallengeStart):
81
- # 记忆未编成 [screenshots/contest/no_memo.png]
82
- if image.find(R.Daily.TextContestNoMemory):
83
- logger.debug('Memory not set. Using auto-compilation.')
84
- user.warning('竞赛未编成', _('记忆未编成。将使用自动编成。'), once=True)
85
- device.click(image.expect(R.Daily.ButtonContestChallenge))
86
- logger.debug('Waiting for challenge start screen.')
69
+ device.click()
70
+
71
+ # 记忆未编成 [screenshots/contest/no_memo.png]
72
+ if image.find(R.Daily.TextContestNoMemory):
73
+ logger.debug('Memory not set. Using auto-compilation.')
74
+ user.warning('竞赛未编成', _('记忆未编成。将使用自动编成。'), once=True)
75
+ if image.find(R.Daily.ButtonContestChallenge):
76
+ device.click()
77
+ return True
78
+
87
79
  # 勾选跳过所有
88
- if image.find(R.Common.CheckboxUnchecked):
80
+ # [screenshots/contest/contest2.png]
81
+ if image.find(R.Common.CheckboxUnchecked, colored=True):
89
82
  logger.debug('Checking skip all.')
90
83
  device.click()
91
- sleep(0.5)
92
- # 点击 SKIP
93
- logger.debug('Clicking on SKIP.')
94
- device.click(image.expect_wait(R.Daily.ButtonIconSkip, timeout=10, preprocessors=[WhiteFilter()]))
95
- while not image.wait_for(R.Common.ButtonNextNoIcon, timeout=2):
96
- device.click_center()
97
- logger.debug('Waiting for the result.')
98
- # [screenshots/contest/after_contest1.png]
99
- # 点击 次へ [screenshots/contest/after_contest2.png]
100
- logger.debug('Challenge finished. Clicking on next.')
101
- device.click()
102
- # 点击 終了 [screenshots/contest/after_contest3.png]
103
- logger.debug('Clicking on end.')
104
- device.click(image.expect_wait(R.Common.ButtonEnd))
84
+ return True
85
+
86
+ # 跳过所有
87
+ # [screenshots/contest/contest1.png]
88
+ if image.find(R.Daily.ButtonIconSkip, preprocessors=[WhiteFilter()]):
89
+ logger.debug('Skipping all.')
90
+ device.click()
91
+ return True
92
+
93
+ if image.find(R.Common.ButtonNextNoIcon):
94
+ logger.debug('Clicking on next.')
95
+ device.click()
96
+
97
+ # 終了 [screenshots/contest/after_contest3.png]
98
+ if image.find(R.Common.ButtonEnd):
99
+ logger.debug('Clicking on end.')
100
+ device.click()
101
+ return True
102
+
105
103
  # 可能出现的奖励弹窗 [screenshots/contest/after_contest4.png]
106
- sleep(1)
107
104
  if image.find(R.Common.ButtonClose):
108
105
  logger.debug('Clicking on close.')
109
106
  device.click()
110
- # 等待返回竞赛界面
111
- wait_loading_end()
112
- image.expect_wait(R.Daily.ButtonContestRanking)
113
- logger.info('Challenge finished.')
114
- return True
107
+
108
+ return False
109
+
110
+ @action('选择对手')
111
+ def handle_pick_contestant(has_ongoing_contest: bool = False) -> tuple[bool, bool]:
112
+ """
113
+ 选择并挑战
114
+
115
+ 前置条件:位于竞赛界面 \n
116
+ 结束状态:位于竞赛界面
117
+
118
+ :param has_ongoing_contest: 是否有中断未完成的挑战
119
+ :return: 二元组。第一个值表示是否命中任何处理。
120
+ 第二个值表示是否应该继续挑战,为 False 表示今天挑战次数已经用完了。
121
+ """
122
+ if image.find(R.Daily.ButtonContestRanking):
123
+ # 无进行中挑战,说明要选择对手
124
+ if not has_ongoing_contest:
125
+ # 随机选一个对手 [screenshots/contest/main.png]
126
+ logger.debug('Clicking on contestant.')
127
+ contestant_list = image.find_all(R.Daily.TextContestOverallStats)
128
+ if contestant_list is None or len(contestant_list) == 0:
129
+ logger.info('No contestant found. Today\'s challenge points used up.')
130
+ return True, False
131
+ # 按照y坐标从上到下排序对手列表
132
+ contestant_list.sort(key=lambda x: x.position[1])
133
+ if len(contestant_list) != 3:
134
+ logger.warning('Cannot find all 3 contestants.')
135
+ # 选择配置文件中对应的对手顺序(1最强,3最弱)
136
+ target = conf().contest.select_which_contestant
137
+ if target >= 1 and target <= 3 and target <= len(contestant_list):
138
+ target -= 1 # [1, 3]映射至[0, 2]
139
+ else:
140
+ target = 0 # 出错则默认选择第一个
141
+ contestant = contestant_list[target]
142
+ logger.info('Picking up contestant #%d.', target + 1)
143
+ device.click(contestant)
144
+ sleep(2)
145
+ return True, True
146
+ return False, True
115
147
 
116
148
  @task('竞赛')
117
149
  def contest():
118
- """"""
119
150
  if not conf().contest.enabled:
120
151
  logger.info('Contest is disabled.')
121
152
  return
@@ -129,17 +160,20 @@ def contest():
129
160
  logger.info('No action needed.')
130
161
  return
131
162
  has_ongoing_contest = goto_contest()
132
- while pick_and_contest(has_ongoing_contest):
133
- sleep(1.3)
163
+ while True:
164
+ device.screenshot()
165
+ handled, should_continue = handle_pick_contestant(has_ongoing_contest)
166
+ if not should_continue:
167
+ break
168
+ if not handled:
169
+ handled = handle_challenge()
170
+ if not handled:
171
+ device.click(10, 10)
134
172
  has_ongoing_contest = False
135
173
  goto_home()
136
174
  logger.info('Contest all finished.')
137
-
138
175
 
139
176
  if __name__ == '__main__':
140
- import logging
141
- logging.basicConfig(level=logging.INFO, format='[%(asctime)s] [%(levelname)s] [%(name)s] [%(funcName)s] [%(lineno)d] %(message)s')
142
- logging.getLogger('kotonebot').setLevel(logging.DEBUG)
143
- logger.setLevel(logging.DEBUG)
144
-
145
- contest()
177
+ from kotonebot.kaa.main import Kaa
178
+ from kotonebot.backend.context import tasks_from_id
179
+ Kaa('config.json').run(tasks_from_id(['contest']))
@@ -2,6 +2,8 @@
2
2
  import logging
3
3
 
4
4
  from kotonebot.kaa.tasks import R
5
+
6
+ from kotonebot.primitives import Rect
5
7
  from kotonebot.kaa.common import conf, Priority
6
8
  from ..actions.loading import wait_loading_end
7
9
  from ..actions.scenes import at_home, goto_home
@@ -70,8 +72,8 @@ def claim_pass_reward():
70
72
  # [screenshots/mission/daily.png]
71
73
  pass_rect = image.expect_wait(R.Daily.ButtonIconPass, timeout=1).rect
72
74
  # 向右扩展 150px,向上扩展 35px
73
- color_rect = (pass_rect[0], pass_rect[1] - 35, pass_rect[2] + 150, pass_rect[3] + 35)
74
- if not color.find('#ff1249', rect=color_rect):
75
+ color_rect = (pass_rect.x1, pass_rect.y1 - 35, pass_rect.w + 150, pass_rect.h + 35)
76
+ if not color.find('#ff1249', rect=Rect(xywh=color_rect)):
75
77
  logger.info('No pass reward to claim.')
76
78
  return
77
79
  logger.info('Claiming pass reward.')
@@ -130,8 +132,6 @@ if __name__ == '__main__':
130
132
  logging.basicConfig(level=logging.INFO, format='[%(asctime)s] [%(levelname)s] [%(name)s] [%(funcName)s] [%(lineno)d] %(message)s')
131
133
  logging.getLogger('kotonebot').setLevel(logging.DEBUG)
132
134
  logger.setLevel(logging.DEBUG)
133
- from .common import conf
134
- conf().mission_reward.enabled = True
135
135
 
136
136
  # if image.find(R.Common.CheckboxUnchecked):
137
137
  # logger.debug('Checking skip all.')
@@ -6,6 +6,7 @@ import _thread
6
6
  import threading
7
7
 
8
8
  from kotonebot.ui import user
9
+ from ..kaa_context import instance
9
10
  from kotonebot.kaa.common import Priority, conf
10
11
  from kotonebot import task, action, config, device
11
12
 
@@ -56,15 +57,7 @@ def end_game():
56
57
 
57
58
  # 关闭模拟器
58
59
  if conf().end_game.kill_emulator:
59
- emulator_path = config.current.backend.emulator_path
60
- if emulator_path is None:
61
- logger.warning("Emulator path is not set. Skipping")
62
- user.info("「关闭模拟器」功能需要配置「模拟器 exe 文件路径」。")
63
- else:
64
- exe_name = os.path.basename(emulator_path)
65
- os.system(f"taskkill /f /im {exe_name}")
66
- logger.info("Emulator closed")
67
- # TODO: 实现关闭模拟器
60
+ instance().stop()
68
61
 
69
62
  # 关机
70
63
  if conf().end_game.shutdown:
@@ -10,7 +10,8 @@ from kotonebot.kaa.tasks import R
10
10
  from kotonebot.kaa.common import conf
11
11
  from kotonebot.kaa.game_ui import dialog
12
12
  from kotonebot.kaa.util.trace import trace
13
- from kotonebot import action, Interval, Countdown, device, image, sleep, ocr, contains, use_screenshot, color, Rect
13
+ from kotonebot.primitives import RectTuple, Rect
14
+ from kotonebot import action, Interval, Countdown, device, image, sleep, ocr, contains, use_screenshot, color
14
15
 
15
16
  class SkillCard(NamedTuple):
16
17
  available: bool
@@ -159,7 +160,7 @@ def do_cards(
159
160
  if no_remaining_card and no_card_cd.expired():
160
161
  logger.debug('No remaining card detected. Skip this turn.')
161
162
  # TODO: HARD CODEDED
162
- SKIP_POSITION = (621, 739, 85, 85)
163
+ SKIP_POSITION = Rect(621, 739, 85, 85)
163
164
  device.click(SKIP_POSITION)
164
165
  no_card_cd.reset()
165
166
  continue
@@ -185,7 +186,7 @@ def do_cards(
185
186
  continue
186
187
  card_rects = calc_card_position(card_count)
187
188
  card_rect = card_rects[0]
188
- device.double_click(card_rect[:4])
189
+ device.double_click(Rect(xywh=card_rect[:4]))
189
190
  sleep(2)
190
191
  timeout_cd.reset()
191
192
  # 结束条件
@@ -277,7 +278,7 @@ def handle_recommended_card(
277
278
  def skill_card_count(img: MatLike | None = None):
278
279
  """获取当前持有的技能卡数量"""
279
280
  img = use_screenshot(img)
280
- x, y, w, h = R.InPurodyuusu.BoxCardLetter
281
+ x, y, w, h = R.InPurodyuusu.BoxCardLetter.xywh
281
282
  img = img[y:y+h, x:x+w]
282
283
  count = image.raw().count(img, R.InPurodyuusu.A)
283
284
  count += image.raw().count(img, R.InPurodyuusu.M)
@@ -346,7 +347,7 @@ def detect_recommended_card(
346
347
  right_score,
347
348
  top_score,
348
349
  bottom_score,
349
- (x, y, w, h)
350
+ Rect(x, y, w, h)
350
351
  ))
351
352
  img = original_image.copy()
352
353
  # cv2.imshow(f"card detect {return_value}", cv2.cvtColor(glow_area, cv2.COLOR_HSV2BGR))
@@ -376,7 +377,7 @@ def detect_recommended_card(
376
377
  )
377
378
  # 跟踪检测结果
378
379
  if conf().trace.recommend_card_detection:
379
- x, y, w, h = filtered_results[0].rect
380
+ x, y, w, h = filtered_results[0].rect.xywh
380
381
  cv2.rectangle(original_image, (x, y), (x+w, y+h), (0, 0, 255), 3)
381
382
  trace('rec-card', original_image, {
382
383
  'card_count': card_count,
@@ -1,7 +1,6 @@
1
1
  from typing import Literal
2
2
  from logging import getLogger
3
3
 
4
- from kotonebot.kaa.tasks import R
5
4
  from kotonebot import (
6
5
  ocr,
7
6
  device,
@@ -10,6 +9,8 @@ from kotonebot import (
10
9
  sleep,
11
10
  Interval,
12
11
  )
12
+ from kotonebot.primitives import Rect
13
+ from kotonebot.kaa.tasks import R
13
14
  from .p_drink import acquire_p_drink
14
15
  from kotonebot.util import measure_time
15
16
  from kotonebot.kaa.common import conf
@@ -89,16 +90,17 @@ def select_p_item():
89
90
  # 前置条件 [screenshots/produce/in_produce/claim_p_item.png]
90
91
 
91
92
  POSTIONS = [
92
- (157, 820, 128, 128), # x, y, w, h
93
- (296, 820, 128, 128),
94
- (435, 820, 128, 128),
93
+ Rect(157, 820, 128, 128), # x, y, w, h
94
+ Rect(296, 820, 128, 128),
95
+ Rect(435, 820, 128, 128),
95
96
  ] # TODO: HARD CODED
96
97
  device.click(POSTIONS[0])
97
98
  sleep(0.5)
98
99
  device.click(ocr.expect_wait('受け取る'))
99
100
 
101
+
100
102
  @action('技能卡自选强化', screenshot_mode='manual-inherit')
101
- def hanlde_skill_card_enhance():
103
+ def handle_skill_card_enhance():
102
104
  """
103
105
  前置条件:技能卡强化对话框\n
104
106
  结束状态:技能卡强化动画结束后瞬间
@@ -107,24 +109,26 @@ def hanlde_skill_card_enhance():
107
109
  """
108
110
  # 前置条件 [kotonebot-resource\sprites\jp\in_purodyuusu\screenshot_skill_card_enhane.png]
109
111
  # 结束状态 [screenshots/produce/in_produce/skill_card_enhance.png]
110
- cards = image.find_multi([
112
+ cards = image.find_all_multi([
111
113
  R.InPurodyuusu.A,
112
114
  R.InPurodyuusu.M
113
115
  ])
114
116
  if cards is None:
115
117
  logger.info("No skill cards found")
116
118
  return False
117
- logger.debug("Clicking first skill card.")
118
- device.click(cards)
119
- it = Interval()
120
- while True:
119
+ cards = sorted(cards, key=lambda x: (x.position[1], x.position[0]))
120
+ it = Interval(0.5)
121
+ for card in reversed(cards):
122
+ device.click(card)
123
+ it.wait()
121
124
  device.screenshot()
122
125
  if image.find(R.InPurodyuusu.ButtonEnhance, colored=True):
123
126
  logger.debug("Enhance button found")
124
127
  device.click()
128
+ it.wait()
125
129
  break
126
- it.wait()
127
130
  logger.debug("Handle skill card enhance finished.")
131
+ return True
128
132
 
129
133
  @action('技能卡自选删除', screenshot_mode='manual-inherit')
130
134
  def handle_skill_card_removal():
@@ -220,7 +224,7 @@ def fast_acquisitions() -> AcquisitionType | None:
220
224
 
221
225
  # 技能卡自选强化
222
226
  if image.find(R.InPurodyuusu.IconTitleSkillCardEnhance):
223
- if hanlde_skill_card_enhance():
227
+ if handle_skill_card_enhance():
224
228
  return "PSkillCardEnhanceSelect"
225
229
  device.click(10, 10)
226
230
 
@@ -2,6 +2,7 @@ import logging
2
2
  from typing_extensions import assert_never
3
3
  from typing import Literal
4
4
 
5
+ from kotonebot.kaa.game_ui.schedule import Schedule
5
6
  from kotonebot.kaa.tasks import R
6
7
  from ..actions import loading
7
8
  from kotonebot.kaa.game_ui import WhiteFilter, dialog
@@ -33,11 +34,10 @@ def handle_sp_lesson():
33
34
  前置条件:行动页面\n
34
35
  结束状态:练习场景,以及中间可能出现的加载、支援卡奖励、交流等
35
36
  """
36
- if (sp := image.find(R.InPurodyuusu.IconSp)) is not None:
37
- # 取 SP 图标中心点向左、向下偏移 30px
38
- rect = sp.rect
39
- pt = (rect[0] + rect[2] // 2, rect[1] + rect[3] // 2)
40
- device.double_click(pt[0] + 30, pt[1] + 30)
37
+ schedule = Schedule()
38
+ if schedule.have_lesson():
39
+ lesson = schedule.select_lesson()
40
+ device.double_click(lesson.rect)
41
41
  return True
42
42
  else:
43
43
  return False
@@ -1,15 +1,16 @@
1
1
  from logging import getLogger
2
2
 
3
3
  from kotonebot.kaa.tasks import R
4
+ from kotonebot.primitives import Rect
4
5
  from kotonebot import device, image, action, sleep
5
6
 
6
7
  logger = getLogger(__name__)
7
8
 
8
9
  # 三个饮料的坐标
9
10
  POSTIONS = [
10
- (157, 820, 128, 128), # x, y, w, h
11
- (296, 820, 128, 128),
12
- (435, 820, 128, 128),
11
+ Rect(157, 820, 128, 128), # x, y, w, h
12
+ Rect(296, 820, 128, 128),
13
+ Rect(435, 820, 128, 128),
13
14
  ] # TODO: HARD CODED
14
15
 
15
16
  @action('领取 P 饮料')
@@ -15,7 +15,7 @@ from ..actions.scenes import at_home, goto_home
15
15
  from kotonebot.kaa.game_ui.idols_overview import locate_idol
16
16
  from ..produce.in_purodyuusu import hajime_pro, hajime_regular, hajime_master, resume_pro_produce, resume_regular_produce, \
17
17
  resume_master_produce
18
- from kotonebot import device, image, ocr, task, action, sleep, contains
18
+ from kotonebot import device, image, ocr, task, action, sleep, contains, regex
19
19
 
20
20
  logger = logging.getLogger(__name__)
21
21
 
@@ -159,7 +159,7 @@ def resume_produce():
159
159
  current_week = int(weeks[0])
160
160
  break
161
161
  retry_count += 1
162
- logger.warning(f'Failed to detect weeks. Retrying... ({retry_count}/{max_retries})')
162
+ logger.warning(f'Failed to detect weeks. week_text="{week_text}". Retrying... ({retry_count}/{max_retries})')
163
163
  sleep(0.5)
164
164
  device.screenshot()
165
165
 
@@ -209,10 +209,12 @@ def do_produce(
209
209
 
210
210
  # 0. 进入培育页面
211
211
  mode_text = mode.upper()
212
+ if mode_text == 'MASTER':
213
+ mode_text = 'MASTER|MIASTER'
212
214
  logger.info(f'Enter produce page. Mode: {mode_text}')
213
215
  result = (SimpleDispatcher('enter_produce')
214
216
  .click(R.Produce.ButtonProduce)
215
- .click(contains(mode_text))
217
+ .click(regex(mode_text))
216
218
  .until(R.Produce.ButtonPIdolOverview, result=True)
217
219
  .until(R.Produce.TextAPInsufficient, result=False)
218
220
  ).run()
@@ -112,7 +112,7 @@ def windows_launch():
112
112
  ahk_path = str(resources.files('kaa.res.bin') / 'AutoHotkey.exe')
113
113
  ahk = AHK(executable_path=ahk_path)
114
114
 
115
- if ahk.find_window(title='gakumas'):
115
+ if ahk.find_window(title='gakumas', title_match_mode=3): # 3=精确匹配
116
116
  logger.debug('Game already started.')
117
117
  return
118
118
 
@@ -121,7 +121,7 @@ def windows_launch():
121
121
  # 等待游戏窗口出现
122
122
  it = Interval()
123
123
  while True:
124
- if ahk.find_window(title='gakumas'):
124
+ if ahk.find_window(title='gakumas', title_match_mode=3):
125
125
  logger.debug('Game window found.')
126
126
  break
127
127
  logger.debug('Waiting for game window...')
@@ -0,0 +1,17 @@
1
+ from .visual import Image, Template
2
+ from .geometry import Point, Rect, Size, Vector2D, Vector3D, is_point, is_rect
3
+ from .geometry import RectTuple, PointTuple
4
+
5
+ __all__ = [
6
+ 'Image',
7
+ 'Template',
8
+ 'Point',
9
+ 'Rect',
10
+ 'Size',
11
+ 'Vector2D',
12
+ 'Vector3D',
13
+ 'is_point',
14
+ 'is_rect',
15
+ 'RectTuple',
16
+ 'PointTuple'
17
+ ]