ksaa 2025.7.5.0__py3-none-any.whl → 2025.7.9.0__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 (205) hide show
  1. kotonebot/backend/bot.py +13 -2
  2. kotonebot/backend/context/context.py +42 -9
  3. kotonebot/config/base_config.py +2 -0
  4. kotonebot/kaa/common.py +2 -968
  5. kotonebot/kaa/config/__init__.py +62 -0
  6. kotonebot/kaa/config/const.py +255 -0
  7. kotonebot/kaa/config/migrations/__init__.py +28 -0
  8. kotonebot/kaa/config/migrations/_idol.py +106 -0
  9. kotonebot/kaa/config/migrations/_v1_to_v2.py +203 -0
  10. kotonebot/kaa/config/migrations/_v2_to_v3.py +126 -0
  11. kotonebot/kaa/config/migrations/_v3_to_v4.py +29 -0
  12. kotonebot/kaa/config/migrations/_v4_to_v5.py +26 -0
  13. kotonebot/kaa/config/migrations/_v5_to_v6.py +134 -0
  14. kotonebot/kaa/config/produce.py +255 -0
  15. kotonebot/kaa/config/schema.py +236 -0
  16. kotonebot/kaa/config/upgrade.py +63 -0
  17. kotonebot/kaa/game_ui/commu_event_buttons.py +3 -0
  18. kotonebot/kaa/game_ui/schedule.py +1 -1
  19. kotonebot/kaa/main/gr.py +841 -176
  20. kotonebot/kaa/main/kaa.py +39 -12
  21. kotonebot/kaa/metadata.py +49 -0
  22. kotonebot/kaa/resources/__pycache__/__init__.cpython-310.pyc +0 -0
  23. kotonebot/kaa/resources/game.db +0 -0
  24. kotonebot/kaa/resources/game_ver.txt +0 -0
  25. kotonebot/kaa/resources/idol_cards/i_card-skin-hmsz-3-001_0.png +0 -0
  26. kotonebot/kaa/resources/idol_cards/i_card-skin-hmsz-3-001_1.png +0 -0
  27. kotonebot/kaa/resources/idol_cards/i_card-skin-jsna-3-007_0.png +0 -0
  28. kotonebot/kaa/resources/idol_cards/i_card-skin-jsna-3-007_1.png +0 -0
  29. kotonebot/kaa/sprites/0d9ac648-eefa-4869-ac99-1b0c83649681.png +0 -0
  30. kotonebot/kaa/sprites/185f7838-92a7-460b-9340-f60858948ce9.png +0 -0
  31. kotonebot/kaa/sprites/213016c2-c3a2-43d8-86a3-ab4d27666ced.png +0 -0
  32. kotonebot/kaa/sprites/24dc7158-036c-4a66-9280-e934f470be53.png +0 -0
  33. kotonebot/kaa/sprites/3942ae40-7f22-412c-aebe-4b064f68db9b.png +0 -0
  34. kotonebot/kaa/sprites/5031808b-5525-4118-92b4-317ec8bda985.png +0 -0
  35. kotonebot/kaa/sprites/5d36b880-7b3f-49b1-a018-7de59867d376.png +0 -0
  36. kotonebot/kaa/sprites/81c97cd3-df53-44d3-bf3d-1eb4dc67b62a.png +0 -0
  37. kotonebot/kaa/sprites/8f8b7b46-53bb-42ab-907a-4ea87eb09ab4.png +0 -0
  38. kotonebot/kaa/sprites/921eefeb-730e-46fc-9924-d338fb286592.png +0 -0
  39. kotonebot/kaa/sprites/ae9fe233-9acc-4e96-ba8e-1fb1d9bc2ea5.png +0 -0
  40. kotonebot/kaa/sprites/cb3d0ca7-8d14-408a-a2f5-2e25f7b86d6c.png +0 -0
  41. kotonebot/kaa/sprites/cc60b509-2ed5-493d-bb9f-333c6d2a6006.png +0 -0
  42. kotonebot/kaa/tasks/R.py +143 -151
  43. kotonebot/kaa/tasks/daily/acquire_activity_funds.py +13 -11
  44. kotonebot/kaa/tasks/daily/acquire_presents.py +1 -1
  45. kotonebot/kaa/tasks/daily/assignment.py +1 -1
  46. kotonebot/kaa/tasks/daily/capsule_toys.py +1 -1
  47. kotonebot/kaa/tasks/daily/club_reward.py +1 -1
  48. kotonebot/kaa/tasks/daily/contest.py +1 -1
  49. kotonebot/kaa/tasks/daily/mission_reward.py +1 -1
  50. kotonebot/kaa/tasks/daily/purchase.py +53 -29
  51. kotonebot/kaa/tasks/daily/upgrade_support_card.py +1 -1
  52. kotonebot/kaa/tasks/end_game.py +1 -1
  53. kotonebot/kaa/tasks/produce/cards.py +1 -1
  54. kotonebot/kaa/tasks/produce/common.py +3 -2
  55. kotonebot/kaa/tasks/produce/in_purodyuusu.py +9 -7
  56. kotonebot/kaa/tasks/produce/non_lesson_actions.py +3 -2
  57. kotonebot/kaa/tasks/produce/produce.py +27 -22
  58. kotonebot/kaa/tasks/start_game.py +1 -1
  59. {ksaa-2025.7.5.0.dist-info → ksaa-2025.7.9.0.dist-info}/METADATA +1 -1
  60. {ksaa-2025.7.5.0.dist-info → ksaa-2025.7.9.0.dist-info}/RECORD +190 -176
  61. kotonebot/kaa/sprites/135ee57a-d30d-4ba8-83f0-9f1681a49ff7.png +0 -0
  62. kotonebot/kaa/sprites/18a02cbe-5d07-487c-866b-62b9609ee02f.png +0 -0
  63. kotonebot/kaa/sprites/1c53ee9f-9dda-43bb-b788-de675c7ebfbe.png +0 -0
  64. kotonebot/kaa/sprites/278b7d9c-707e-4392-9677-74574b5cdf42.png +0 -0
  65. kotonebot/kaa/sprites/2bc00520-0afe-40e5-8743-d33fc6b2945a.png +0 -0
  66. kotonebot/kaa/sprites/3a234f56-2287-4ced-8093-253ece372af2.png +0 -0
  67. kotonebot/kaa/sprites/6720b6e8-ae80-4cc0-a885-518efe12b707.png +0 -0
  68. kotonebot/kaa/sprites/68f109c1-297e-4aa8-b472-372f1d689b33.png +0 -0
  69. kotonebot/kaa/sprites/74ff07b3-d91c-4579-80cd-379ed7020622.png +0 -0
  70. kotonebot/kaa/sprites/7669d1f5-d778-4694-87ae-9bb08e7f1265.png +0 -0
  71. kotonebot/kaa/sprites/868b97a9-492e-4712-b47f-82b97495b019.png +0 -0
  72. kotonebot/kaa/sprites/9d21d43f-4bf9-4081-951f-d208e0273e1f.png +0 -0
  73. kotonebot/kaa/sprites/a7f5abf1-982f-4a55-8d41-3ad6f56798e0.png +0 -0
  74. kotonebot/kaa/sprites/afa06fdc-a345-4384-b25d-b16540830256.png +0 -0
  75. kotonebot/kaa/sprites/d15959bf-d07b-4f07-948a-c0aeaf17756a.png +0 -0
  76. /kotonebot/kaa/sprites/{e6f0ca18-546c-4463-96b6-5866fe4d1ff2.png → 02cf0df9-37d6-4387-b8eb-c92589264c2a.png} +0 -0
  77. /kotonebot/kaa/sprites/{d8caa8b8-6f45-4bcc-89c6-4d4522db14c0.png → 02d4e179-912e-4e1f-ba7d-ea37fe87279e.png} +0 -0
  78. /kotonebot/kaa/sprites/{ffacd169-0e30-4e43-a4dc-46dd85711ba7.png → 037cb117-8521-4670-b3ec-ee0e260c1d62.png} +0 -0
  79. /kotonebot/kaa/sprites/{de87abe3-482a-4fc0-ace2-bc436036ddf5.png → 04be14b5-4169-4b3e-ab14-224db52c9a39.png} +0 -0
  80. /kotonebot/kaa/sprites/{9aabd1cd-fa2f-4b4d-9ca0-5cd0a02cdeeb.png → 06bb9a6e-1dbe-48db-91d7-51d9fc3ffcce.png} +0 -0
  81. /kotonebot/kaa/sprites/{6f72ab34-1c37-42d8-81c0-d0e0e573fc80.png → 08444afd-90d4-43ac-b3ee-128a5bdef4a2.png} +0 -0
  82. /kotonebot/kaa/sprites/{2ad5f996-e825-4c91-bf84-b3a139d7f1e9.png → 0910c5f3-7f72-4385-967c-4bf226c9861b.png} +0 -0
  83. /kotonebot/kaa/sprites/{bdd7e868-0cb2-4da2-9055-6cf9eae5869b.png → 0b332c2c-aa57-4f10-aa55-8e981f2e7c27.png} +0 -0
  84. /kotonebot/kaa/sprites/{46800ab2-388f-4945-941a-3e18607c9676.png → 0c4ee900-3e44-4e37-a199-32d66daa2025.png} +0 -0
  85. /kotonebot/kaa/sprites/{10e06d0b-9cef-489c-8468-adad39067d8a.png → 0cfd52cc-1f38-4804-bc1f-8da9cc51d969.png} +0 -0
  86. /kotonebot/kaa/sprites/{78c1bd53-771f-4809-bbda-39f8dd6395c1.png → 131d5c1b-70b3-47d3-b6d6-318045629037.png} +0 -0
  87. /kotonebot/kaa/sprites/{80feee6f-d7dd-499c-bd91-cc1e191dd945.png → 133dbdd9-23fa-4157-9f9e-fd1728207bd0.png} +0 -0
  88. /kotonebot/kaa/sprites/{b64f8cc6-4ef9-4f43-95e6-d508364faff1.png → 17d2730b-e56e-4956-973d-5f822490a2c5.png} +0 -0
  89. /kotonebot/kaa/sprites/{482b5f67-1680-4a93-8bb2-2a357dfd8d8d.png → 231b3e86-cfc5-4e08-803b-63ed680ab1ad.png} +0 -0
  90. /kotonebot/kaa/sprites/{2a08cc2b-5cba-4771-a351-94121c52308c.png → 2569011c-3bad-416c-b358-ceaf313507e8.png} +0 -0
  91. /kotonebot/kaa/sprites/{6be7624f-c0ac-4605-b8ba-56f8b07d7de0.png → 26dd326a-a6da-4350-8140-217e9d6a6109.png} +0 -0
  92. /kotonebot/kaa/sprites/{3305dc0c-d721-4e82-a5f8-4b8d96eea228.png → 29119167-eb9c-4c35-9c63-9c9967f85163.png} +0 -0
  93. /kotonebot/kaa/sprites/{cae49b6a-cc4e-49d9-9dd6-d528510bd262.png → 2b8385d8-ea7e-4675-9d16-57b905a18d90.png} +0 -0
  94. /kotonebot/kaa/sprites/{9fb5da56-41a8-4a83-8ae8-338a124ecd03.png → 2cd2047f-91af-4632-8cb2-eb2fc4b4c808.png} +0 -0
  95. /kotonebot/kaa/sprites/{bd408633-6ca9-4cb0-9b11-695616496b48.png → 314bc3ab-8c73-4517-ae7c-75d21ac61448.png} +0 -0
  96. /kotonebot/kaa/sprites/{d09a9154-0280-40f9-9802-2d2fa01c03df.png → 33e4e6c9-d245-4174-8303-04019ce20136.png} +0 -0
  97. /kotonebot/kaa/sprites/{c4cc6dcd-6301-4d02-942e-8e49475ec3e9.png → 34cce4b7-53fe-4ea2-82d8-d31fe7b9abcd.png} +0 -0
  98. /kotonebot/kaa/sprites/{2cf84d6e-5212-4da5-8a01-cfdab00a8d1b.png → 3820d53e-5b87-4a35-9472-e90498225853.png} +0 -0
  99. /kotonebot/kaa/sprites/{d25bd995-1139-4909-84e2-85260a27d46f.png → 38e35291-2a94-4261-9b58-80d7b17165c9.png} +0 -0
  100. /kotonebot/kaa/sprites/{24a955bb-feff-4ace-a38c-8a6c3e6d4e95.png → 3ae6e096-42e4-4ac4-ad79-6f2529925c16.png} +0 -0
  101. /kotonebot/kaa/sprites/{e8e1bb95-6260-4e60-aa5a-972869fa2791.png → 3c41fb45-6400-4818-9066-e03d60d2a895.png} +0 -0
  102. /kotonebot/kaa/sprites/{e2929240-db44-42fb-be5a-3a397c2fe2ac.png → 3e9adf0f-f6c5-4d68-9667-97ea2f82bb51.png} +0 -0
  103. /kotonebot/kaa/sprites/{593442ad-94f8-4d68-b986-8cf92e74e76d.png → 3ef649e7-c03a-40d1-9a76-653faaf799df.png} +0 -0
  104. /kotonebot/kaa/sprites/{f22e46af-f72e-4978-a4be-8cfa68e4e85e.png → 43226a61-3d61-4acb-afbb-812bf9e97843.png} +0 -0
  105. /kotonebot/kaa/sprites/{09934d4f-a1a1-47c6-8127-32247b3144a6.png → 443a5dbf-e2fb-4d34-bb09-c21e1437f715.png} +0 -0
  106. /kotonebot/kaa/sprites/{c1e18236-0488-4025-b2f6-ce75d13b861f.png → 459851f5-fa20-45c4-a6d2-1018b3976fcd.png} +0 -0
  107. /kotonebot/kaa/sprites/{5365f6d2-17e2-4d51-a2c0-535007949cb3.png → 46c520e7-7b97-43be-8cc2-21e478b5d844.png} +0 -0
  108. /kotonebot/kaa/sprites/{a9c95639-fb97-4d1c-8f8c-53337570c7a7.png → 4867e835-c805-463e-9a53-1e677e3d140f.png} +0 -0
  109. /kotonebot/kaa/sprites/{0ab2fef6-759e-41a7-a078-c71a09acc829.png → 48ebb790-2310-436d-a31c-dba4db034cbc.png} +0 -0
  110. /kotonebot/kaa/sprites/{561b20a8-1faa-4be9-8861-7132ce1836ed.png → 4b8ebe86-7a0d-474a-abac-b4a45fda5e88.png} +0 -0
  111. /kotonebot/kaa/sprites/{b5e1e9ee-eab0-476c-8e35-e9760935942c.png → 4c235498-622f-4f74-9ebb-df3fcd3306ab.png} +0 -0
  112. /kotonebot/kaa/sprites/{6f3a4ad7-0949-4a1d-a0ea-1daa4148b9c9.png → 4f3d2710-5626-4471-9b21-cd01b8c542d1.png} +0 -0
  113. /kotonebot/kaa/sprites/{8fd4ee16-be10-438d-b0e0-b728723961fe.png → 4f4e3cf3-b1d9-436b-9477-5f2244c20d6b.png} +0 -0
  114. /kotonebot/kaa/sprites/{ced15f67-03ed-48a7-a0a5-24d29ec9a8f9.png → 4f891dc4-71c0-4492-a8d1-0c52978e75e1.png} +0 -0
  115. /kotonebot/kaa/sprites/{1bc32bd5-c429-490f-8a52-fd52d4e27ff8.png → 4ff46fa5-fe9e-4103-8012-451adc14dc43.png} +0 -0
  116. /kotonebot/kaa/sprites/{7d9c26a1-69e3-4c28-b794-66c81ee171d5.png → 5399e464-1ee6-406b-acab-7826e30f3fd9.png} +0 -0
  117. /kotonebot/kaa/sprites/{a8e36d55-5095-485e-a1f1-283c362352f1.png → 540a64f4-8111-4df4-abfe-0e62e0f8c7af.png} +0 -0
  118. /kotonebot/kaa/sprites/{34dc26b6-237e-4932-a009-8c03f4a4841f.png → 5422d945-aa90-443e-bf79-f8ab93ec9411.png} +0 -0
  119. /kotonebot/kaa/sprites/{b54448c1-460d-4ab3-b220-ff4c82e7cea5.png → 585c7846-f353-448f-8eb9-1ceafec94555.png} +0 -0
  120. /kotonebot/kaa/sprites/{3ed00c80-7b46-4eba-9df7-89de8161150f.png → 5a87228a-ec5d-4ffc-951a-1454c9c03bdc.png} +0 -0
  121. /kotonebot/kaa/sprites/{511408bd-a212-4261-b4f1-b6c592e44c52.png → 5b14a452-ea54-4804-8ec0-3cd916cd8e88.png} +0 -0
  122. /kotonebot/kaa/sprites/{1062488e-eb7c-42e0-bb3d-675d88992dc5.png → 5cc8ccda-2cf7-4956-b67d-15327bc75ed6.png} +0 -0
  123. /kotonebot/kaa/sprites/{8b9fddd0-4a17-4bc3-ac8f-cd6fa21058b2.png → 5e27d1c5-cc3f-4aee-8d79-69c09206fa3d.png} +0 -0
  124. /kotonebot/kaa/sprites/{068d9a7a-2920-44ab-8fe4-b48bec98b837.png → 64938ad2-442f-41eb-a544-4d2611e8012f.png} +0 -0
  125. /kotonebot/kaa/sprites/{13f72533-c91e-412d-8b43-208e2128cd16.png → 65223004-722e-4003-af09-c7769e8a7cb2.png} +0 -0
  126. /kotonebot/kaa/sprites/{31fedc14-7e32-4547-a97d-4b76aa8e9ca5.png → 659a1775-7001-4add-96e9-292693a26b60.png} +0 -0
  127. /kotonebot/kaa/sprites/{ac3f3385-0281-4e45-87fa-e9b4fcf81688.png → 6626694b-1394-44af-b76b-791c5bb2428b.png} +0 -0
  128. /kotonebot/kaa/sprites/{fd5890f6-f437-47cc-85d6-54745864075c.png → 6a202eb6-dd41-4675-a840-99dde2b2efa4.png} +0 -0
  129. /kotonebot/kaa/sprites/{23d99912-0b9f-434c-bd90-9ab71e70e6f4.png → 6b2e887b-e113-4280-9779-6795c2782c58.png} +0 -0
  130. /kotonebot/kaa/sprites/{3d2ce9cb-39a0-4b2f-ab96-39ded89a67c3.png → 6eb959e1-ee64-4fa6-a20f-8ee4e51f2c6a.png} +0 -0
  131. /kotonebot/kaa/sprites/{3a5b5966-b641-42b1-816e-aa0ae465ad66.png → 7098fbf7-b8cc-4933-bfec-12a2ac98e38c.png} +0 -0
  132. /kotonebot/kaa/sprites/{736def6e-bb5e-445b-b2a6-7b8670c7cbb3.png → 712e9223-4dd2-4ff6-887b-4182fd243d78.png} +0 -0
  133. /kotonebot/kaa/sprites/{fa57193f-5654-4b9d-8a9a-67211e7b5aff.png → 7256a95e-24b8-40fd-bd8e-73a1572c3f93.png} +0 -0
  134. /kotonebot/kaa/sprites/{aaa4ac00-3da2-468d-b2c3-f69b0ccaff2c.png → 73f89439-c4e3-4263-8fa7-229cde98aa99.png} +0 -0
  135. /kotonebot/kaa/sprites/{2a07a1e9-8033-492a-80de-8269a94abc85.png → 74efd362-4cc1-4b9f-8032-e5bc45c2af5c.png} +0 -0
  136. /kotonebot/kaa/sprites/{86584eea-2d90-4ab5-916a-0d29ec4edcde.png → 756ac796-ce43-4ddb-989e-13bf07cbe3b7.png} +0 -0
  137. /kotonebot/kaa/sprites/{b6040e31-b183-4520-ad2a-966612c60f86.png → 77193249-7e2a-4652-ab6d-a463350ca226.png} +0 -0
  138. /kotonebot/kaa/sprites/{ec96a180-1c0f-4bd2-8b21-6b31eac39ef5.png → 784a91b2-4d24-461f-8bd3-2f02b9bc193f.png} +0 -0
  139. /kotonebot/kaa/sprites/{b0a9ad98-2e2c-4dbb-b1e6-c93a4f6f92d4.png → 83c67f2a-0f73-4238-a5a8-8ebb839ed99a.png} +0 -0
  140. /kotonebot/kaa/sprites/{acb66482-748f-487f-bcd3-a400fb9b70ba.png → 86b3bab1-c5f6-48b2-b810-c3ec55c32314.png} +0 -0
  141. /kotonebot/kaa/sprites/{a97fe010-f776-4ab4-88f5-4d0cceecc7ba.png → 872838c5-47c6-4f78-b105-0a72b5459f16.png} +0 -0
  142. /kotonebot/kaa/sprites/{877b36cd-07f9-425c-be1d-5e1925dc2f4f.png → 93f03304-5609-4f4f-9ac8-a46e7b883960.png} +0 -0
  143. /kotonebot/kaa/sprites/{bfa32df6-16ba-406a-be3c-7e5248d9cd0c.png → 97e96ecf-e51b-4a09-ab11-3c164196747f.png} +0 -0
  144. /kotonebot/kaa/sprites/{9b8ebc2e-a8a3-458a-a840-54c7a5ad0119.png → 992473c3-df0a-4c72-8134-f2aac9e7b0f6.png} +0 -0
  145. /kotonebot/kaa/sprites/{57f56121-cdc4-4c29-8fcd-9d4f872c98e7.png → 9d86ab77-de0b-433d-9b0e-5aba283309a6.png} +0 -0
  146. /kotonebot/kaa/sprites/{da8f3c98-de95-4be0-88e7-de5e7ef90649.png → 9eb202c8-c61a-4918-beb9-b0f03739b0b3.png} +0 -0
  147. /kotonebot/kaa/sprites/{c689a3e0-d0ad-49e7-b5d9-66ff7e34fd2a.png → a4e02797-2c5d-4860-aaa4-c20c43be7500.png} +0 -0
  148. /kotonebot/kaa/sprites/{25bf9c17-099b-437e-ae0f-8226c7c0faa9.png → a5c582f5-3627-44be-b574-a4e4287376e0.png} +0 -0
  149. /kotonebot/kaa/sprites/{59067ba8-2bfe-4bc8-b028-90ccb1acf5f6.png → a914da74-9752-42be-913b-86514eb4b589.png} +0 -0
  150. /kotonebot/kaa/sprites/{6514f807-0a12-4338-a3be-9f0a2bc22e7e.png → aacb651b-9a3d-42a1-9fc0-9187dc8cded7.png} +0 -0
  151. /kotonebot/kaa/sprites/{304df45b-b744-427e-ba79-9f57a2313776.png → ae146d94-5e69-4970-b175-d7c8c4f9a9cd.png} +0 -0
  152. /kotonebot/kaa/sprites/{ed82be6d-7c5d-42fd-bdd1-8ad20076f480.png → ae57e1fb-c42f-4401-93a1-76d4591b5fad.png} +0 -0
  153. /kotonebot/kaa/sprites/{b0404967-c93e-4900-beeb-26717ae13c4a.png → b1878d2b-4908-4342-b395-864aafa5c54b.png} +0 -0
  154. /kotonebot/kaa/sprites/{e26d7a9a-f8fe-4092-b3fc-0647b34c984e.png → b26e3c78-a6be-4ad1-8992-c3245b1a6f9b.png} +0 -0
  155. /kotonebot/kaa/sprites/{da1a9ce5-0032-413c-ae26-2a5d27efe7ef.png → b3a41d58-f375-4882-bebb-57f72322d016.png} +0 -0
  156. /kotonebot/kaa/sprites/{cc6e472b-7f6f-4f34-8fb4-c2c15913cda5.png → b4905122-7d97-4561-a14a-b8a9a5cd9227.png} +0 -0
  157. /kotonebot/kaa/sprites/{e3e6fe61-afa3-4a6b-810b-c87d599f5868.png → b534423c-2024-4234-9886-f49e17dd96e7.png} +0 -0
  158. /kotonebot/kaa/sprites/{c7fb79d2-9335-4d86-afaf-abc537394cbf.png → b6680d31-8552-4111-bc39-0867c06bf94a.png} +0 -0
  159. /kotonebot/kaa/sprites/{7cf3da78-a825-4e5e-8210-d6ebc3e7ab6b.png → b6c637bf-5fdd-4e68-b4d8-b403bf611f3b.png} +0 -0
  160. /kotonebot/kaa/sprites/{a010517f-6ee1-4924-8385-1f5fb879e08f.png → b9e19bda-3793-4cf4-928a-fc43642b32e6.png} +0 -0
  161. /kotonebot/kaa/sprites/{09ea0d24-9412-4f0e-bbe8-9227687b9cb5.png → bc1c640a-87d8-47af-9fcc-8681acac7b27.png} +0 -0
  162. /kotonebot/kaa/sprites/{dbc0975e-e9f2-4db8-a0df-f16711606165.png → bc25ed87-50a7-4aa8-b743-505450677b00.png} +0 -0
  163. /kotonebot/kaa/sprites/{a7c14f96-6b0e-4065-96e7-04058c0ab1c0.png → bcf2f87a-de7f-4fb9-aa6c-0b4f6bff921e.png} +0 -0
  164. /kotonebot/kaa/sprites/{9d99fa4f-ca9e-4e19-97b2-7cbef502b73c.png → bdd0e8f8-3d35-48e8-b735-66eaf2ece2e6.png} +0 -0
  165. /kotonebot/kaa/sprites/{c07de7e7-263b-4b82-ab04-e31bec40b524.png → bec6c0cf-40f6-446d-85b3-c692d3322a51.png} +0 -0
  166. /kotonebot/kaa/sprites/{a57a3a56-8509-4e98-b438-0848e6fe091a.png → bf19069d-e044-4f76-93f7-f2ecd3214e47.png} +0 -0
  167. /kotonebot/kaa/sprites/{a4128c6e-4a40-4d2d-aa1d-597e70e718fb.png → c1274e01-2cc7-432f-b244-65ffe8269656.png} +0 -0
  168. /kotonebot/kaa/sprites/{60a3bc3c-099b-4090-9f6f-253c963e9fa4.png → c65d71af-ffb3-4992-b954-c59ae48615b8.png} +0 -0
  169. /kotonebot/kaa/sprites/{22672fe7-40d8-425f-a465-b19af092cb2f.png → c67852a2-30a9-4fd6-a4c2-83870a658998.png} +0 -0
  170. /kotonebot/kaa/sprites/{07ffe5a8-f817-4087-a7ce-da19516b9f55.png → c705eece-67d8-4017-a4d9-a7f1337f67be.png} +0 -0
  171. /kotonebot/kaa/sprites/{a8efadec-4461-4a34-bf20-801ba7a545aa.png → c86a3385-407e-40d5-b519-1927406d5b09.png} +0 -0
  172. /kotonebot/kaa/sprites/{e81bb7c7-aae0-4280-86e7-2c15fba205f1.png → ca42ca0c-3829-4e43-88c9-db4939cfa982.png} +0 -0
  173. /kotonebot/kaa/sprites/{f87af019-34ee-428d-8d11-dc77a2c41be5.png → cba7528d-ae17-4a37-b388-6f86e1a590f4.png} +0 -0
  174. /kotonebot/kaa/sprites/{f7c89d72-ca8e-46a9-ab49-b7775dfbf37f.png → cc1767ec-77db-49ac-8c9e-f48d1fb7b071.png} +0 -0
  175. /kotonebot/kaa/sprites/{38018b98-4f03-43f5-8fa2-ba739a1edd7e.png → ce282e51-7067-4293-ad26-24dbba172a08.png} +0 -0
  176. /kotonebot/kaa/sprites/{d04c4883-0d15-4bd8-918e-065db19bf145.png → d1e5672d-df91-4316-984c-48550c5d1931.png} +0 -0
  177. /kotonebot/kaa/sprites/{ab01298b-f04f-4b12-a256-efd1122f5fdc.png → d2d99405-7927-47fc-be4c-a7591b339a6c.png} +0 -0
  178. /kotonebot/kaa/sprites/{8c3c7599-0cbd-4ba8-9635-23eb6bb965b1.png → d356fc84-a8c0-4d0f-a3ed-c7ff5ccd276c.png} +0 -0
  179. /kotonebot/kaa/sprites/{45353fcd-59ea-4b15-93f7-8591adfa7af8.png → d477e49c-37cc-4e71-a8e6-6633f044260a.png} +0 -0
  180. /kotonebot/kaa/sprites/{063825e2-f4c7-4047-8958-7cc0a8cf32fb.png → d4b1e48b-bf9c-4f44-9ddb-3af8eb4ea464.png} +0 -0
  181. /kotonebot/kaa/sprites/{815d0dc2-5aa1-43be-8316-88d24c4c8c81.png → d6d6229a-2345-4fe7-b2c5-109fcdb37c39.png} +0 -0
  182. /kotonebot/kaa/sprites/{112c76ba-0409-4ba9-b485-19500003a60b.png → d953cdee-08b5-45fb-908b-2644220b0f07.png} +0 -0
  183. /kotonebot/kaa/sprites/{0ae22f69-b9e4-43c5-8c95-53360c0d4b35.png → de069910-6085-45a9-ba96-64bc7aeead77.png} +0 -0
  184. /kotonebot/kaa/sprites/{61feefa4-f5ec-4a99-b8fc-19deefa8d1cd.png → dea4c704-5739-423f-a15c-f31a4a93d64f.png} +0 -0
  185. /kotonebot/kaa/sprites/{90356864-a48e-4d0a-8ca3-8443524ac414.png → debc6a94-9bf1-46d7-b0b0-0c55cb367f12.png} +0 -0
  186. /kotonebot/kaa/sprites/{901fd5e9-a0d6-4774-bafe-4b3f6dedf006.png → e0555145-9446-4ebe-965b-f46b458e5681.png} +0 -0
  187. /kotonebot/kaa/sprites/{dc826aa1-4d2f-49f0-9c78-cec45b77f49d.png → e19c5f10-5f93-4431-9bf3-4f92512eab6e.png} +0 -0
  188. /kotonebot/kaa/sprites/{60b5e390-c956-4e7b-9a3c-3db0c2481d5b.png → e353b4cb-ea6d-4fc4-91ec-c19582e9507c.png} +0 -0
  189. /kotonebot/kaa/sprites/{2919b90c-64b6-4961-b2a9-edea29cda27b.png → e6554fee-c6fd-49ee-8c32-b4932fc701da.png} +0 -0
  190. /kotonebot/kaa/sprites/{7c4fcaae-44c8-429b-989c-d17fd07734f9.png → e916a5ca-287c-4cbe-93ca-22b439c5ffab.png} +0 -0
  191. /kotonebot/kaa/sprites/{67cce3d0-3c80-44a0-9193-18d00f9712af.png → ed4a2db1-ab2e-4b36-8d6f-5b7961501475.png} +0 -0
  192. /kotonebot/kaa/sprites/{866b2bda-fdfd-4cde-b6a5-8dc396d7bef3.png → ed4a318e-f69a-4fb9-9853-9746f01c6015.png} +0 -0
  193. /kotonebot/kaa/sprites/{ceb65e4a-c59b-4580-9360-ba1fd600846a.png → efe68984-8dbc-417e-924c-87c6860c58ef.png} +0 -0
  194. /kotonebot/kaa/sprites/{e61a092f-1717-4672-943b-71f061ce2717.png → f165bf01-9e9d-4afb-87d9-4a26318140cf.png} +0 -0
  195. /kotonebot/kaa/sprites/{7609a3df-963d-4c1a-ae2d-3bc6bc7a05b9.png → f2846992-402e-4f50-b74e-91d6f3b8994d.png} +0 -0
  196. /kotonebot/kaa/sprites/{5568e31d-9d55-4435-8cef-ef8b6fc8d2d8.png → f4227a80-f62d-4daf-83d0-c7b5500088ee.png} +0 -0
  197. /kotonebot/kaa/sprites/{a7755ce2-9f05-455b-8c8f-e3cf803d03de.png → f496a454-5cf5-4b6b-aedb-1dad58c85035.png} +0 -0
  198. /kotonebot/kaa/sprites/{cdb09691-5c2a-4bb4-8ae8-01fd865ba3e6.png → f4af8fb2-6270-4b75-8b24-d0e49daebac1.png} +0 -0
  199. /kotonebot/kaa/sprites/{9a57d7b4-722a-4f77-9f5f-635092154ec3.png → f60c40a1-750b-41ac-9d24-2d7ffce44166.png} +0 -0
  200. /kotonebot/kaa/sprites/{f188d7ad-cd46-4342-ae70-cc2d5abb87d9.png → f6c3bd48-fe1e-4fe3-bf58-13422b5b4a99.png} +0 -0
  201. /kotonebot/kaa/sprites/{7ceec350-8f7d-4786-a477-2f0ea6b81748.png → ffaffa14-22dd-4397-8dc1-7b94fd4cf06b.png} +0 -0
  202. {ksaa-2025.7.5.0.dist-info → ksaa-2025.7.9.0.dist-info}/WHEEL +0 -0
  203. {ksaa-2025.7.5.0.dist-info → ksaa-2025.7.9.0.dist-info}/entry_points.txt +0 -0
  204. {ksaa-2025.7.5.0.dist-info → ksaa-2025.7.9.0.dist-info}/licenses/LICENSE +0 -0
  205. {ksaa-2025.7.5.0.dist-info → ksaa-2025.7.9.0.dist-info}/top_level.txt +0 -0
kotonebot/kaa/main/gr.py CHANGED
@@ -21,12 +21,13 @@ from kotonebot.config.base_config import UserConfig, BackendConfig
21
21
  from kotonebot.backend.context import task_registry, ContextStackVars
22
22
  from kotonebot.backend.context.context import vars
23
23
  from kotonebot.client.host import Mumu12Host, LeidianHost
24
- from kotonebot.kaa.common import (
24
+ from kotonebot.kaa.config import (
25
25
  BaseConfig, APShopItems, CapsuleToysConfig, ClubRewardConfig, PurchaseConfig, ActivityFundsConfig,
26
26
  PresentsConfig, AssignmentConfig, ContestConfig, ProduceConfig,
27
27
  MissionRewardConfig, DailyMoneyShopItems, ProduceAction,
28
28
  RecommendCardDetectionMode, TraceConfig, StartGameConfig, EndGameConfig, UpgradeSupportCardConfig, MiscConfig,
29
29
  )
30
+ from kotonebot.kaa.config.produce import ProduceSolution, ProduceSolutionManager, ProduceData
30
31
 
31
32
  logger = logging.getLogger(__name__)
32
33
  GradioInput = gr.Textbox | gr.Number | gr.Checkbox | gr.Dropdown | gr.Radio | gr.Slider | gr.Tabs | gr.Tab
@@ -37,12 +38,12 @@ ConfigKey = Literal[
37
38
  'check_emulator', 'emulator_path',
38
39
  'adb_emulator_name', 'emulator_args',
39
40
  '_mumu_index', '_leidian_index',
40
- 'mumu_background_mode',
41
+ 'mumu_background_mode', 'target_screenshot_interval',
41
42
 
42
43
  # purchase
43
44
  'purchase_enabled',
44
45
  'money_enabled', 'ap_enabled',
45
- 'ap_items', 'money_items',
46
+ 'ap_items', 'money_items', 'money_refresh',
46
47
 
47
48
  # assignment
48
49
  'assignment_enabled',
@@ -52,14 +53,7 @@ ConfigKey = Literal[
52
53
  'select_which_contestant',
53
54
 
54
55
  # produce
55
- 'produce_enabled', 'produce_mode',
56
- 'produce_count', 'produce_idols',
57
- 'memory_sets', 'auto_set_memory',
58
- 'auto_set_support', 'use_pt_boost',
59
- 'use_note_boost', 'follow_producer',
60
- 'self_study_lesson', 'prefer_lesson_ap',
61
- 'actions_order', 'recommend_card_detection_mode',
62
- 'use_ap_drink', 'skip_commu',
56
+ 'produce_enabled', 'selected_solution_id', 'produce_count',
63
57
  'mission_reward_enabled',
64
58
 
65
59
  # club reward
@@ -92,8 +86,8 @@ ConfigKey = Literal[
92
86
  'trace_recommend_card_detection',
93
87
 
94
88
  # misc
95
- 'check_update', 'auto_install_update',
96
-
89
+ 'check_update', 'auto_install_update', 'expose_to_lan',
90
+
97
91
  '_selected_backend_index'
98
92
 
99
93
  ]
@@ -395,6 +389,33 @@ class KotoneBotUI:
395
389
  interactive = not (self.is_stopping or self.is_single_task_stopping)
396
390
  return gr.Button(value=text, interactive=interactive)
397
391
 
392
+ def reload_config(self) -> bool:
393
+ """
394
+ 重新加载配置并重新初始化相关组件
395
+
396
+ :return: 是否成功重新加载
397
+ """
398
+ try:
399
+ # 重新加载配置文件
400
+ self._load_config()
401
+
402
+ # 重新设置 kaa 的配置
403
+ self._kaa.config_path = "config.json"
404
+ self._kaa.config_type = BaseConfig
405
+
406
+ # 重新初始化 kaa(这会重新创建设备和 Context)
407
+ self._setup_kaa()
408
+
409
+ # 重新加载 Context 中的配置数据
410
+ from kotonebot.backend.context.context import config
411
+ config.load()
412
+
413
+ logger.info("配置已成功重新加载")
414
+ return True
415
+ except Exception as e:
416
+ logger.error(f"重新加载配置失败:{str(e)}")
417
+ return False
418
+
398
419
  def save_settings2(self, return_values: list[ConfigBuilderReturnValue], *args) -> str:
399
420
  options = BaseConfig()
400
421
  # return_values: (set_func, { 'key': component })
@@ -406,45 +427,50 @@ class KotoneBotUI:
406
427
  assert key in CONFIG_KEY_VALUE, f"未知的配置项:{key}"
407
428
  key = cast(ConfigKey, key)
408
429
  data[key] = value
409
-
430
+
410
431
  # 先设置options
411
432
  for (set_func, _) in return_values:
412
433
  set_func(options, data)
413
-
434
+
414
435
  # 验证规则1:截图方法验证
415
436
  screenshot_method = self.current_config.backend.screenshot_impl
416
437
  backend_type = self.current_config.backend.type
417
-
438
+
418
439
  valid_screenshot_methods = {
419
440
  'mumu12': ['adb', 'adb_raw', 'uiautomator2', 'nemu_ipc'],
420
441
  'leidian': ['adb', 'adb_raw', 'uiautomator2'],
421
442
  'custom': ['adb', 'adb_raw', 'uiautomator2'],
422
443
  'dmm': ['remote_windows', 'windows']
423
444
  }
424
-
445
+
425
446
  if screenshot_method not in valid_screenshot_methods.get(backend_type, []):
426
447
  gr.Warning(f"截图方法 '{screenshot_method}' 不适用于当前选择的模拟器类型,配置未保存。")
427
448
  return ""
428
-
429
- # 验证规则2:若启用培育,那么培育偶像不能为空
430
- if options.produce.enabled and not options.produce.idols:
431
- gr.Warning("启用培育时,培育偶像不能为空,配置未保存。")
449
+
450
+ # 验证规则2:若启用培育,那么必须选择培育方案
451
+ if options.produce.enabled and not options.produce.selected_solution_id:
452
+ gr.Warning("启用培育时,必须选择培育方案,配置未保存。")
432
453
  return ""
433
-
454
+
434
455
  # 验证规则3:若启用AP/金币购买,对应的商品不能为空
435
456
  if options.purchase.ap_enabled and not options.purchase.ap_items:
436
457
  gr.Warning("启用AP购买时,AP商店购买物品不能为空,配置未保存。")
437
458
  return ""
438
-
459
+
439
460
  if options.purchase.money_enabled and not options.purchase.money_items:
440
461
  gr.Warning("启用金币购买时,金币商店购买物品不能为空,配置未保存。")
441
462
  return ""
442
-
463
+
443
464
  # 验证通过,保存配置
444
465
  self.current_config.options = options
445
466
  try:
446
467
  save_config(self.config, "config.json")
447
- gr.Success("设置已保存,请重启程序!")
468
+
469
+ # 尝试热重载配置
470
+ if self.reload_config():
471
+ gr.Success("设置已保存并应用!")
472
+ else:
473
+ gr.Warning("设置已保存,但重新加载失败,请重启程序。")
448
474
  return ""
449
475
  except Exception as e:
450
476
  gr.Warning(f"保存设置失败:{str(e)}")
@@ -457,11 +483,76 @@ class KotoneBotUI:
457
483
  with gr.Row():
458
484
  run_btn = gr.Button("启动", scale=2)
459
485
  pause_btn = gr.Button("暂停", scale=1)
486
+
487
+ # 快速功能启停控制区域
488
+ gr.Markdown("### 快速功能启停")
489
+ with gr.Row(elem_classes=["quick-controls-row"]):
490
+ purchase_quick = gr.Checkbox(
491
+ label="商店",
492
+ value=self.current_config.options.purchase.enabled,
493
+ interactive=True,
494
+ elem_classes=["quick-checkbox"]
495
+ )
496
+ assignment_quick = gr.Checkbox(
497
+ label="工作",
498
+ value=self.current_config.options.assignment.enabled,
499
+ interactive=True,
500
+ elem_classes=["quick-checkbox"]
501
+ )
502
+ contest_quick = gr.Checkbox(
503
+ label="竞赛",
504
+ value=self.current_config.options.contest.enabled,
505
+ interactive=True,
506
+ elem_classes=["quick-checkbox"]
507
+ )
508
+ produce_quick = gr.Checkbox(
509
+ label="培育",
510
+ value=self.current_config.options.produce.enabled,
511
+ interactive=True,
512
+ elem_classes=["quick-checkbox"]
513
+ )
514
+ mission_reward_quick = gr.Checkbox(
515
+ label="任务",
516
+ value=self.current_config.options.mission_reward.enabled,
517
+ interactive=True,
518
+ elem_classes=["quick-checkbox"]
519
+ )
520
+ club_reward_quick = gr.Checkbox(
521
+ label="社团",
522
+ value=self.current_config.options.club_reward.enabled,
523
+ interactive=True,
524
+ elem_classes=["quick-checkbox"]
525
+ )
526
+ activity_funds_quick = gr.Checkbox(
527
+ label="活动费",
528
+ value=self.current_config.options.activity_funds.enabled,
529
+ interactive=True,
530
+ elem_classes=["quick-checkbox"]
531
+ )
532
+ presents_quick = gr.Checkbox(
533
+ label="礼物",
534
+ value=self.current_config.options.presents.enabled,
535
+ interactive=True,
536
+ elem_classes=["quick-checkbox"]
537
+ )
538
+ capsule_toys_quick = gr.Checkbox(
539
+ label="扭蛋",
540
+ value=self.current_config.options.capsule_toys.enabled,
541
+ interactive=True,
542
+ elem_classes=["quick-checkbox"]
543
+ )
544
+ upgrade_support_card_quick = gr.Checkbox(
545
+ label="支援卡",
546
+ value=self.current_config.options.upgrade_support_card.enabled,
547
+ interactive=True,
548
+ elem_classes=["quick-checkbox"]
549
+ )
550
+
460
551
  if self._kaa.upgrade_msg:
461
552
  gr.Markdown('### 配置升级报告')
462
553
  gr.Markdown(self._kaa.upgrade_msg)
463
554
  gr.Markdown('脚本报错或者卡住?前往"反馈"选项卡可以快速导出报告!')
464
-
555
+
465
556
  # 添加调试模式警告
466
557
  if self.current_config.keep_screenshots:
467
558
  gr.Markdown(
@@ -485,6 +576,45 @@ class KotoneBotUI:
485
576
  def on_pause_click(evt: gr.EventData) -> str:
486
577
  return self.toggle_pause()
487
578
 
579
+ # 快速功能控制的事件处理函数
580
+ def save_quick_setting(field_name: str, value: bool, display_name: str):
581
+ """保存快速设置并立即应用"""
582
+ try:
583
+ # 更新配置
584
+ if field_name == 'purchase':
585
+ self.current_config.options.purchase.enabled = value
586
+ elif field_name == 'assignment':
587
+ self.current_config.options.assignment.enabled = value
588
+ elif field_name == 'contest':
589
+ self.current_config.options.contest.enabled = value
590
+ elif field_name == 'produce':
591
+ self.current_config.options.produce.enabled = value
592
+ elif field_name == 'mission_reward':
593
+ self.current_config.options.mission_reward.enabled = value
594
+ elif field_name == 'club_reward':
595
+ self.current_config.options.club_reward.enabled = value
596
+ elif field_name == 'activity_funds':
597
+ self.current_config.options.activity_funds.enabled = value
598
+ elif field_name == 'presents':
599
+ self.current_config.options.presents.enabled = value
600
+ elif field_name == 'capsule_toys':
601
+ self.current_config.options.capsule_toys.enabled = value
602
+ elif field_name == 'upgrade_support_card':
603
+ self.current_config.options.upgrade_support_card.enabled = value
604
+ elif field_name == 'start_game':
605
+ self.current_config.options.start_game.enabled = value
606
+
607
+ # 保存配置
608
+ save_config(self.config, "config.json")
609
+
610
+ # 尝试热重载配置
611
+ if self.reload_config():
612
+ gr.Success(f"✓ {display_name} 已{'启用' if value else '禁用'}")
613
+ else:
614
+ gr.Warning(f"⚠ {display_name} 已保存,但重新加载失败")
615
+ except Exception as e:
616
+ gr.Error(f"✗ 保存失败:{str(e)}")
617
+
488
618
  run_btn.click(
489
619
  fn=on_run_click,
490
620
  outputs=[run_btn, task_status]
@@ -495,11 +625,68 @@ class KotoneBotUI:
495
625
  outputs=[pause_btn]
496
626
  )
497
627
 
628
+ # 绑定快速功能控制的事件
629
+ purchase_quick.change(
630
+ fn=lambda x: save_quick_setting('purchase', x, '商店'),
631
+ inputs=[purchase_quick]
632
+ )
633
+ assignment_quick.change(
634
+ fn=lambda x: save_quick_setting('assignment', x, '工作'),
635
+ inputs=[assignment_quick]
636
+ )
637
+ contest_quick.change(
638
+ fn=lambda x: save_quick_setting('contest', x, '竞赛'),
639
+ inputs=[contest_quick]
640
+ )
641
+ produce_quick.change(
642
+ fn=lambda x: save_quick_setting('produce', x, '培育'),
643
+ inputs=[produce_quick]
644
+ )
645
+ mission_reward_quick.change(
646
+ fn=lambda x: save_quick_setting('mission_reward', x, '任务奖励'),
647
+ inputs=[mission_reward_quick]
648
+ )
649
+ club_reward_quick.change(
650
+ fn=lambda x: save_quick_setting('club_reward', x, '社团奖励'),
651
+ inputs=[club_reward_quick]
652
+ )
653
+ activity_funds_quick.change(
654
+ fn=lambda x: save_quick_setting('activity_funds', x, '活动费'),
655
+ inputs=[activity_funds_quick]
656
+ )
657
+ presents_quick.change(
658
+ fn=lambda x: save_quick_setting('presents', x, '礼物'),
659
+ inputs=[presents_quick]
660
+ )
661
+ capsule_toys_quick.change(
662
+ fn=lambda x: save_quick_setting('capsule_toys', x, '扭蛋'),
663
+ inputs=[capsule_toys_quick]
664
+ )
665
+ upgrade_support_card_quick.change(
666
+ fn=lambda x: save_quick_setting('upgrade_support_card', x, '支援卡升级'),
667
+ inputs=[upgrade_support_card_quick]
668
+ )
669
+
498
670
  # 添加定时器,分别更新按钮状态和任务状态
499
671
  def update_run_button_status():
500
672
  text, interactive = self.get_button_status()
501
673
  return gr.Button(value=text, interactive=interactive)
502
674
 
675
+ def update_quick_checkboxes():
676
+ """更新快速功能控制的 checkbox 状态,确保与设置同步"""
677
+ return [
678
+ gr.Checkbox(value=self.current_config.options.purchase.enabled),
679
+ gr.Checkbox(value=self.current_config.options.assignment.enabled),
680
+ gr.Checkbox(value=self.current_config.options.contest.enabled),
681
+ gr.Checkbox(value=self.current_config.options.produce.enabled),
682
+ gr.Checkbox(value=self.current_config.options.mission_reward.enabled),
683
+ gr.Checkbox(value=self.current_config.options.club_reward.enabled),
684
+ gr.Checkbox(value=self.current_config.options.activity_funds.enabled),
685
+ gr.Checkbox(value=self.current_config.options.presents.enabled),
686
+ gr.Checkbox(value=self.current_config.options.capsule_toys.enabled),
687
+ gr.Checkbox(value=self.current_config.options.upgrade_support_card.enabled),
688
+ ]
689
+
503
690
  gr.Timer(1.0).tick(
504
691
  fn=update_run_button_status,
505
692
  outputs=[run_btn]
@@ -508,6 +695,14 @@ class KotoneBotUI:
508
695
  fn=self.get_pause_button_with_interactive,
509
696
  outputs=[pause_btn]
510
697
  )
698
+ gr.Timer(2.0).tick(
699
+ fn=update_quick_checkboxes,
700
+ outputs=[
701
+ purchase_quick, assignment_quick, contest_quick, produce_quick,
702
+ mission_reward_quick, club_reward_quick, activity_funds_quick, presents_quick,
703
+ capsule_toys_quick, upgrade_support_card_quick
704
+ ]
705
+ )
511
706
  gr.Timer(1.0).tick(
512
707
  fn=self.update_task_status,
513
708
  outputs=[task_status]
@@ -761,6 +956,15 @@ class KotoneBotUI:
761
956
  interactive=True
762
957
  )
763
958
 
959
+ target_screenshot_interval = gr.Number(
960
+ label="最小截图间隔(秒)",
961
+ value=self.current_config.backend.target_screenshot_interval,
962
+ info=BackendConfig.model_fields['target_screenshot_interval'].description,
963
+ minimum=0,
964
+ step=0.1,
965
+ interactive=True
966
+ )
967
+
764
968
  tab_mumu12.select(fn=partial(_update_emulator_tab_options, selected_index=0), inputs=[screenshot_impl], outputs=[screenshot_impl])
765
969
  tab_leidian.select(fn=partial(_update_emulator_tab_options, selected_index=1), inputs=[screenshot_impl], outputs=[screenshot_impl])
766
970
  tab_custom.select(fn=partial(_update_emulator_tab_options, selected_index=2), inputs=[screenshot_impl], outputs=[screenshot_impl])
@@ -814,12 +1018,14 @@ class KotoneBotUI:
814
1018
 
815
1019
  # Common settings for all backend types
816
1020
  self.current_config.backend.screenshot_impl = data['screenshot_method']
1021
+ self.current_config.backend.target_screenshot_interval = data['target_screenshot_interval']
817
1022
  self.current_config.keep_screenshots = data['keep_screenshots'] # This is a UserConfig field
818
1023
 
819
1024
  return set_config, {
820
1025
  'adb_ip': adb_ip,
821
1026
  'adb_port': adb_port,
822
1027
  'screenshot_method': screenshot_impl, # screenshot_impl is the component
1028
+ 'target_screenshot_interval': target_screenshot_interval,
823
1029
  'keep_screenshots': keep_screenshots,
824
1030
  'check_emulator': check_emulator,
825
1031
  'emulator_path': emulator_path,
@@ -854,6 +1060,12 @@ class KotoneBotUI:
854
1060
  info=PurchaseConfig.model_fields['money_items'].description
855
1061
  )
856
1062
 
1063
+ money_refresh = gr.Checkbox(
1064
+ label="每日一次免费刷新金币商店",
1065
+ value=self.current_config.options.purchase.money_refresh,
1066
+ info=PurchaseConfig.model_fields['money_refresh'].description
1067
+ )
1068
+
857
1069
  ap_enabled = gr.Checkbox(
858
1070
  label="启用AP购买",
859
1071
  value=self.current_config.options.purchase.ap_enabled,
@@ -891,6 +1103,7 @@ class KotoneBotUI:
891
1103
  config.purchase.enabled = data['purchase_enabled']
892
1104
  config.purchase.money_enabled = data['money_enabled']
893
1105
  config.purchase.money_items = [DailyMoneyShopItems(x) for x in data['money_items']]
1106
+ config.purchase.money_refresh = data['money_refresh']
894
1107
  config.purchase.ap_enabled = data['ap_enabled']
895
1108
  ap_items_enum: List[Literal[0, 1, 2, 3]] = []
896
1109
  ap_items_map: Dict[str, APShopItems] = {
@@ -909,7 +1122,8 @@ class KotoneBotUI:
909
1122
  'money_enabled': money_enabled,
910
1123
  'ap_enabled': ap_enabled,
911
1124
  'ap_items': ap_items,
912
- 'money_items': money_items
1125
+ 'money_items': money_items,
1126
+ 'money_refresh': money_refresh
913
1127
  }
914
1128
 
915
1129
  def _create_work_settings(self) -> ConfigBuilderReturnValue:
@@ -1010,13 +1224,21 @@ class KotoneBotUI:
1010
1224
  value=self.current_config.options.produce.enabled,
1011
1225
  info=ProduceConfig.model_fields['enabled'].description
1012
1226
  )
1227
+
1013
1228
  with gr.Group(visible=self.current_config.options.produce.enabled) as produce_group:
1014
- produce_mode = gr.Dropdown(
1015
- choices=["regular", "pro", "master"],
1016
- value=self.current_config.options.produce.mode,
1017
- label="培育模式",
1018
- info=ProduceConfig.model_fields['mode'].description
1229
+ # 培育方案管理区域
1230
+ solution_manager = ProduceSolutionManager()
1231
+ solutions = solution_manager.list()
1232
+ solution_choices = [(f"{sol.name} - {sol.description or '无描述'}", sol.id) for sol in solutions]
1233
+
1234
+ selected_solution_id = self.current_config.options.produce.selected_solution_id
1235
+ solution_dropdown = gr.Dropdown(
1236
+ choices=solution_choices,
1237
+ value=selected_solution_id,
1238
+ label="当前使用的培育方案",
1239
+ interactive=True
1019
1240
  )
1241
+
1020
1242
  produce_count = gr.Number(
1021
1243
  minimum=1,
1022
1244
  value=self.current_config.options.produce.produce_count,
@@ -1024,106 +1246,523 @@ class KotoneBotUI:
1024
1246
  interactive=True,
1025
1247
  info=ProduceConfig.model_fields['produce_count'].description
1026
1248
  )
1027
- # 添加偶像选择
1028
- idol_choices = []
1029
- for idol in IdolCard.all():
1030
- if idol.is_another:
1031
- idol_choices.append((f'{idol.name} 「{idol.another_name}」', idol.skin_id))
1032
- else:
1033
- idol_choices.append((f'{idol.name}', idol.skin_id))
1034
- selected_idols = self.current_config.options.produce.idols
1035
- produce_idols = gr.Dropdown(
1036
- choices=idol_choices,
1037
- value=selected_idols,
1038
- label="选择要培育的偶像",
1039
- multiselect=True,
1040
- interactive=True,
1041
- info=ProduceConfig.model_fields['idols'].description
1042
- )
1043
- has_kotone = any("藤田ことね" in idol for idol in selected_idols)
1044
- is_strict_mode = self.current_config.options.produce.recommend_card_detection_mode == RecommendCardDetectionMode.STRICT
1045
- kotone_warning = gr.Markdown(
1046
- visible=has_kotone and not is_strict_mode,
1047
- value="使用「藤田ことね」进行培育时,确保将「推荐卡检测模式」设置为「严格模式」"
1048
- )
1049
- auto_set_memory = gr.Checkbox(
1050
- label="自动编成回忆",
1051
- value=self.current_config.options.produce.auto_set_memory,
1052
- info=ProduceConfig.model_fields['auto_set_memory'].description
1053
- )
1054
- with gr.Group(visible=not self.current_config.options.produce.auto_set_memory) as memory_sets_group:
1055
- memory_sets = gr.Dropdown(
1056
- choices=[str(i) for i in range(1, 11)], # 假设最多10个编成位
1057
- value=[str(i) for i in self.current_config.options.produce.memory_sets],
1058
- label="回忆编成编号",
1249
+
1250
+ # 绑定启用状态变化事件
1251
+ def on_produce_enabled_change(enabled):
1252
+ return gr.Group(visible=enabled)
1253
+
1254
+ produce_enabled.change(
1255
+ fn=on_produce_enabled_change,
1256
+ inputs=[produce_enabled],
1257
+ outputs=[produce_group]
1258
+ )
1259
+
1260
+ # 存储设置Tab中的下拉框引用,供培育Tab使用
1261
+ self._settings_solution_dropdown = solution_dropdown
1262
+
1263
+ def set_config(config: BaseConfig, data: dict[ConfigKey, Any]) -> None:
1264
+ config.produce.enabled = data['produce_enabled']
1265
+ config.produce.selected_solution_id = data.get('selected_solution_id')
1266
+ config.produce.produce_count = data.get('produce_count', 1)
1267
+
1268
+ return set_config, {
1269
+ 'produce_enabled': produce_enabled,
1270
+ 'selected_solution_id': solution_dropdown,
1271
+ 'produce_count': produce_count
1272
+ }
1273
+
1274
+
1275
+ def _create_produce_tab(self) -> None:
1276
+ """创建培育Tab"""
1277
+ with gr.Tab("培育"):
1278
+ gr.Markdown("## 培育管理")
1279
+
1280
+ # 培育方案管理区域
1281
+ solution_manager = ProduceSolutionManager()
1282
+ solutions = solution_manager.list()
1283
+ solution_choices = [(f"{sol.name} - {sol.description or '无描述'}", sol.id) for sol in solutions]
1284
+
1285
+ selected_solution_id = self.current_config.options.produce.selected_solution_id
1286
+ solution_dropdown = gr.Dropdown(
1287
+ choices=solution_choices,
1288
+ value=selected_solution_id,
1289
+ label="选择培育方案",
1290
+ interactive=True
1291
+ )
1292
+
1293
+ # 获取设置Tab中的下拉框引用
1294
+ settings_dropdown = getattr(self, '_settings_solution_dropdown', None)
1295
+
1296
+ with gr.Row():
1297
+ new_solution_btn = gr.Button("新建培育", scale=1)
1298
+ delete_solution_btn = gr.Button("删除当前培育", scale=1)
1299
+
1300
+ # 培育方案详细设置区域
1301
+ with gr.Group() as solution_settings_group:
1302
+ # 获取当前选中的方案数据
1303
+ current_solution = None
1304
+ if selected_solution_id:
1305
+ try:
1306
+ current_solution = solution_manager.read(selected_solution_id)
1307
+ except FileNotFoundError:
1308
+ pass
1309
+
1310
+ if current_solution is None:
1311
+ # 如果没有选中方案,隐藏所有设置组件
1312
+ solution_name = gr.Textbox(label="方案名称", value="", visible=False)
1313
+ solution_description = gr.Textbox(label="方案描述", value="", visible=False)
1314
+ # 其他设置组件都设为不可见
1315
+ produce_mode = gr.Dropdown(
1316
+ choices=["regular", "pro", "master"],
1317
+ label="培育模式",
1318
+ info="进行一次 REGULAR 培育需要 ~30min,进行一次 PRO 培育需要 ~1h(具体视设备性能而定)。",
1319
+ visible=False
1320
+ )
1321
+ produce_count = gr.Number(
1322
+ minimum=1,
1323
+ label="培育次数",
1324
+ info="培育的次数。",
1325
+ visible=False
1326
+ )
1327
+
1328
+ # 添加偶像选择
1329
+ idol_choices = []
1330
+ for idol in IdolCard.all():
1331
+ if idol.is_another:
1332
+ idol_choices.append((f'{idol.name} 「{idol.another_name}」', idol.skin_id))
1333
+ else:
1334
+ idol_choices.append((f'{idol.name}', idol.skin_id))
1335
+
1336
+ produce_idols = gr.Dropdown(
1337
+ choices=idol_choices,
1338
+ label="选择要培育的偶像",
1339
+ multiselect=False,
1340
+ info="要培育偶像的 IdolCardSkin.id。",
1341
+ visible=False
1342
+ )
1343
+ kotone_warning = gr.Markdown(visible=False)
1344
+ auto_set_memory = gr.Checkbox(
1345
+ label="自动编成回忆",
1346
+ info="是否自动编成回忆。此选项优先级高于回忆编成编号。",
1347
+ visible=False
1348
+ )
1349
+ with gr.Group(visible=False) as memory_sets_group:
1350
+ memory_sets = gr.Dropdown(
1351
+ choices=[str(i) for i in range(1, 11)],
1352
+ label="回忆编成编号",
1353
+ multiselect=False,
1354
+ info="要使用的回忆编成编号,从 1 开始。",
1355
+ visible=False
1356
+ )
1357
+ auto_set_support = gr.Checkbox(
1358
+ label="自动编成支援卡",
1359
+ info="是否自动编成支援卡。此选项优先级高于支援卡编成编号。",
1360
+ visible=False
1361
+ )
1362
+ with gr.Group(visible=False) as support_card_sets_group:
1363
+ support_card_sets = gr.Dropdown(
1364
+ choices=[str(i) for i in range(1, 11)],
1365
+ label="支援卡编成编号",
1366
+ multiselect=False,
1367
+ info="要使用的支援卡编成编号,从 1 开始。",
1368
+ visible=False
1369
+ )
1370
+ use_pt_boost = gr.Checkbox(
1371
+ label="使用支援强化 Pt 提升",
1372
+ info="是否使用支援强化 Pt 提升。",
1373
+ visible=False
1374
+ )
1375
+ use_note_boost = gr.Checkbox(
1376
+ label="使用笔记数提升",
1377
+ info="是否使用笔记数提升。",
1378
+ visible=False
1379
+ )
1380
+ follow_producer = gr.Checkbox(
1381
+ label="关注租借了支援卡的制作人",
1382
+ info="是否关注租借了支援卡的制作人。",
1383
+ visible=False
1384
+ )
1385
+ self_study_lesson = gr.Dropdown(
1386
+ choices=['dance', 'visual', 'vocal'],
1387
+ label='文化课自习时选项',
1388
+ info='自习课类型。',
1389
+ visible=False
1390
+ )
1391
+ prefer_lesson_ap = gr.Checkbox(
1392
+ label="SP 课程优先",
1393
+ info="优先 SP 课程。启用后,若出现 SP 课程,则会优先执行 SP 课程,而不是推荐课程。若出现多个 SP 课程,随机选择一个。",
1394
+ visible=False
1395
+ )
1396
+ actions_order = gr.Dropdown(
1397
+ choices=[(action.display_name, action.value) for action in ProduceAction],
1398
+ label="行动优先级",
1399
+ info="每一周的行动将会按这里设置的优先级执行。",
1059
1400
  multiselect=True,
1401
+ visible=False
1402
+ )
1403
+ recommend_card_detection_mode = gr.Dropdown(
1404
+ choices=[
1405
+ (RecommendCardDetectionMode.NORMAL.display_name, RecommendCardDetectionMode.NORMAL.value),
1406
+ (RecommendCardDetectionMode.STRICT.display_name, RecommendCardDetectionMode.STRICT.value)
1407
+ ],
1408
+ label="推荐卡检测模式",
1409
+ info="推荐卡检测模式。严格模式下,识别速度会降低,但识别准确率会提高。",
1410
+ visible=False
1411
+ )
1412
+ use_ap_drink = gr.Checkbox(
1413
+ label="AP 不足时自动使用 AP 饮料",
1414
+ info="AP 不足时自动使用 AP 饮料",
1415
+ visible=False
1416
+ )
1417
+ skip_commu = gr.Checkbox(
1418
+ label="检测并跳过交流",
1419
+ info="检测并跳过交流",
1420
+ visible=False
1421
+ )
1422
+ save_solution_btn = gr.Button("保存培育方案", variant="primary", visible=False)
1423
+ else:
1424
+ # 显示选中方案的设置
1425
+ solution_name = gr.Textbox(
1426
+ label="方案名称",
1427
+ value=current_solution.name,
1428
+ interactive=True
1429
+ )
1430
+ solution_description = gr.Textbox(
1431
+ label="方案描述",
1432
+ value=current_solution.description or "",
1433
+ interactive=True
1434
+ )
1435
+
1436
+ produce_mode = gr.Dropdown(
1437
+ choices=["regular", "pro", "master"],
1438
+ value=current_solution.data.mode,
1439
+ label="培育模式",
1440
+ info="进行一次 REGULAR 培育需要 ~30min,进行一次 PRO 培育需要 ~1h(具体视设备性能而定)。"
1441
+ )
1442
+ produce_count = gr.Number(
1443
+ minimum=1,
1444
+ value=self.current_config.options.produce.produce_count,
1445
+ label="培育次数",
1060
1446
  interactive=True,
1061
- info=ProduceConfig.model_fields['memory_sets'].description
1447
+ info="培育的次数。"
1062
1448
  )
1063
1449
 
1064
- # 添加偶像选择变化时的回调
1065
- def update_kotone_warning(selected_idols, recommend_card_detection_mode):
1066
- has_kotone = any("藤田ことね" in idol for idol in selected_idols)
1067
- is_strict_mode = recommend_card_detection_mode == RecommendCardDetectionMode.STRICT.value
1068
- return gr.Markdown(visible=has_kotone and not is_strict_mode)
1450
+ # 添加偶像选择
1451
+ idol_choices = []
1452
+ for idol in IdolCard.all():
1453
+ if idol.is_another:
1454
+ idol_choices.append((f'{idol.name} 「{idol.another_name}」', idol.skin_id))
1455
+ else:
1456
+ idol_choices.append((f'{idol.name}', idol.skin_id))
1457
+
1458
+ produce_idols = gr.Dropdown(
1459
+ choices=idol_choices,
1460
+ value=current_solution.data.idol,
1461
+ label="选择要培育的偶像",
1462
+ multiselect=False,
1463
+ interactive=True,
1464
+ info="要培育偶像的 IdolCardSkin.id。"
1465
+ )
1069
1466
 
1070
- auto_set_support = gr.Checkbox(
1071
- label="自动编成支援卡",
1072
- value=self.current_config.options.produce.auto_set_support_card,
1073
- info=ProduceConfig.model_fields['auto_set_support_card'].description
1074
- )
1075
- use_pt_boost = gr.Checkbox(
1076
- label="使用支援强化 Pt 提升",
1077
- value=self.current_config.options.produce.use_pt_boost,
1078
- info=ProduceConfig.model_fields['use_pt_boost'].description
1079
- )
1080
- use_note_boost = gr.Checkbox(
1081
- label="使用笔记数提升",
1082
- value=self.current_config.options.produce.use_note_boost,
1083
- info=ProduceConfig.model_fields['use_note_boost'].description
1084
- )
1085
- follow_producer = gr.Checkbox(
1086
- label="关注租借了支援卡的制作人",
1087
- value=self.current_config.options.produce.follow_producer,
1088
- info=ProduceConfig.model_fields['follow_producer'].description
1089
- )
1090
- self_study_lesson = gr.Dropdown(
1091
- choices=['dance', 'visual', 'vocal'],
1092
- value=self.current_config.options.produce.self_study_lesson,
1093
- label='文化课自习时选项',
1094
- info='选择自习课类型'
1095
- )
1096
- prefer_lesson_ap = gr.Checkbox(
1097
- label="SP 课程优先",
1098
- value=self.current_config.options.produce.prefer_lesson_ap,
1099
- info=ProduceConfig.model_fields['prefer_lesson_ap'].description
1100
- )
1101
- actions_order = gr.Dropdown(
1102
- choices=[(action.display_name, action.value) for action in ProduceAction],
1103
- value=[action.value for action in self.current_config.options.produce.actions_order],
1104
- label="行动优先级",
1105
- info="设置每周行动的优先级顺序",
1106
- multiselect=True
1107
- )
1108
- recommend_card_detection_mode = gr.Dropdown(
1109
- choices=[
1110
- (RecommendCardDetectionMode.NORMAL.display_name, RecommendCardDetectionMode.NORMAL.value),
1111
- (RecommendCardDetectionMode.STRICT.display_name, RecommendCardDetectionMode.STRICT.value)
1112
- ],
1113
- value=self.current_config.options.produce.recommend_card_detection_mode.value,
1114
- label="推荐卡检测模式",
1115
- info=ProduceConfig.model_fields['recommend_card_detection_mode'].description
1116
- )
1117
- use_ap_drink = gr.Checkbox(
1118
- label="AP 不足时自动使用 AP 饮料",
1119
- value=self.current_config.options.produce.use_ap_drink,
1120
- info=ProduceConfig.model_fields['use_ap_drink'].description
1121
- )
1122
- skip_commu = gr.Checkbox(
1123
- label="检测并跳过交流",
1124
- value=self.current_config.options.produce.skip_commu,
1125
- info=ProduceConfig.model_fields['skip_commu'].description
1126
- )
1467
+ has_kotone = bool(current_solution.data.idol and "藤田ことね" in current_solution.data.idol)
1468
+ is_strict_mode = current_solution.data.recommend_card_detection_mode == RecommendCardDetectionMode.STRICT
1469
+ kotone_warning = gr.Markdown(
1470
+ visible=has_kotone and not is_strict_mode,
1471
+ value="使用「藤田ことね」进行培育时,确保将「推荐卡检测模式」设置为「严格模式」"
1472
+ )
1473
+
1474
+ auto_set_memory = gr.Checkbox(
1475
+ label="自动编成回忆",
1476
+ value=current_solution.data.auto_set_memory,
1477
+ info="是否自动编成回忆。此选项优先级高于回忆编成编号。"
1478
+ )
1479
+
1480
+ with gr.Group(visible=not current_solution.data.auto_set_memory) as memory_sets_group:
1481
+ memory_sets = gr.Dropdown(
1482
+ choices=[str(i) for i in range(1, 11)], # 假设最多10个编成位
1483
+ value=str(current_solution.data.memory_set) if current_solution.data.memory_set else None,
1484
+ label="回忆编成编号",
1485
+ multiselect=False,
1486
+ interactive=True,
1487
+ info="要使用的回忆编成编号,从 1 开始。"
1488
+ )
1489
+
1490
+ auto_set_support = gr.Checkbox(
1491
+ label="自动编成支援卡",
1492
+ value=current_solution.data.auto_set_support_card,
1493
+ info="是否自动编成支援卡。此选项优先级高于支援卡编成编号。"
1494
+ )
1495
+
1496
+ with gr.Group(visible=not current_solution.data.auto_set_support_card) as support_card_sets_group:
1497
+ support_card_sets = gr.Dropdown(
1498
+ choices=[str(i) for i in range(1, 11)], # 假设最多10个编成位
1499
+ value=str(current_solution.data.support_card_set) if current_solution.data.support_card_set else None,
1500
+ label="支援卡编成编号",
1501
+ multiselect=False,
1502
+ interactive=True,
1503
+ info="要使用的支援卡编成编号,从 1 开始。"
1504
+ )
1505
+ use_pt_boost = gr.Checkbox(
1506
+ label="使用支援强化 Pt 提升",
1507
+ value=current_solution.data.use_pt_boost,
1508
+ info="是否使用支援强化 Pt 提升。"
1509
+ )
1510
+ use_note_boost = gr.Checkbox(
1511
+ label="使用笔记数提升",
1512
+ value=current_solution.data.use_note_boost,
1513
+ info="是否使用笔记数提升。"
1514
+ )
1515
+ follow_producer = gr.Checkbox(
1516
+ label="关注租借了支援卡的制作人",
1517
+ value=current_solution.data.follow_producer,
1518
+ info="是否关注租借了支援卡的制作人。"
1519
+ )
1520
+ self_study_lesson = gr.Dropdown(
1521
+ choices=['dance', 'visual', 'vocal'],
1522
+ value=current_solution.data.self_study_lesson,
1523
+ label='文化课自习时选项',
1524
+ info='自习课类型。'
1525
+ )
1526
+ prefer_lesson_ap = gr.Checkbox(
1527
+ label="SP 课程优先",
1528
+ value=current_solution.data.prefer_lesson_ap,
1529
+ info="优先 SP 课程。启用后,若出现 SP 课程,则会优先执行 SP 课程,而不是推荐课程。若出现多个 SP 课程,随机选择一个。"
1530
+ )
1531
+ actions_order = gr.Dropdown(
1532
+ choices=[(action.display_name, action.value) for action in ProduceAction],
1533
+ value=[action.value for action in current_solution.data.actions_order],
1534
+ label="行动优先级",
1535
+ info="每一周的行动将会按这里设置的优先级执行。",
1536
+ multiselect=True
1537
+ )
1538
+ recommend_card_detection_mode = gr.Dropdown(
1539
+ choices=[
1540
+ (RecommendCardDetectionMode.NORMAL.display_name, RecommendCardDetectionMode.NORMAL.value),
1541
+ (RecommendCardDetectionMode.STRICT.display_name, RecommendCardDetectionMode.STRICT.value)
1542
+ ],
1543
+ value=current_solution.data.recommend_card_detection_mode.value,
1544
+ label="推荐卡检测模式",
1545
+ info="推荐卡检测模式。严格模式下,识别速度会降低,但识别准确率会提高。"
1546
+ )
1547
+ use_ap_drink = gr.Checkbox(
1548
+ label="AP 不足时自动使用 AP 饮料",
1549
+ value=current_solution.data.use_ap_drink,
1550
+ info="AP 不足时自动使用 AP 饮料"
1551
+ )
1552
+ skip_commu = gr.Checkbox(
1553
+ label="检测并跳过交流",
1554
+ value=current_solution.data.skip_commu,
1555
+ info="检测并跳过交流"
1556
+ )
1557
+
1558
+ # 添加保存按钮
1559
+ save_solution_btn = gr.Button("保存培育方案", variant="primary")
1560
+
1561
+ # 添加事件处理
1562
+ def update_kotone_warning(selected_idol, recommend_card_detection_mode):
1563
+ # Handle case where selected_idol is None (no selection)
1564
+ # selected_idol is a single string (skin_id), not a list
1565
+ if selected_idol is None:
1566
+ has_kotone = False
1567
+ else:
1568
+ has_kotone = "藤田ことね" in selected_idol
1569
+ is_strict_mode = recommend_card_detection_mode == RecommendCardDetectionMode.STRICT.value
1570
+ return gr.Markdown(visible=has_kotone and not is_strict_mode)
1571
+
1572
+ def on_solution_change(solution_id):
1573
+ """当选择的培育方案改变时,更新所有设置组件"""
1574
+ if not solution_id:
1575
+ return [
1576
+ gr.Textbox(value="", visible=False), # solution_name
1577
+ gr.Textbox(value="", visible=False), # solution_description
1578
+ gr.Dropdown(visible=False), # produce_mode
1579
+ gr.Number(visible=False), # produce_count
1580
+ gr.Dropdown(visible=False), # produce_idols
1581
+ gr.Markdown(visible=False), # kotone_warning
1582
+ gr.Checkbox(visible=False), # auto_set_memory
1583
+ gr.Group(visible=False), # memory_sets_group
1584
+ gr.Dropdown(visible=False), # memory_sets
1585
+ gr.Checkbox(visible=False), # auto_set_support
1586
+ gr.Checkbox(visible=False), # use_pt_boost
1587
+ gr.Checkbox(visible=False), # use_note_boost
1588
+ gr.Checkbox(visible=False), # follow_producer
1589
+ gr.Dropdown(visible=False), # self_study_lesson
1590
+ gr.Checkbox(visible=False), # prefer_lesson_ap
1591
+ gr.Dropdown(visible=False), # actions_order
1592
+ gr.Dropdown(visible=False), # recommend_card_detection_mode
1593
+ gr.Checkbox(visible=False), # use_ap_drink
1594
+ gr.Checkbox(visible=False), # skip_commu
1595
+ gr.Button(visible=False), # save_solution_btn
1596
+ ]
1597
+
1598
+ try:
1599
+ solution = solution_manager.read(solution_id)
1600
+ has_kotone = bool(solution.data.idol and "藤田ことね" in solution.data.idol)
1601
+ is_strict_mode = solution.data.recommend_card_detection_mode == RecommendCardDetectionMode.STRICT
1602
+
1603
+ return [
1604
+ gr.Textbox(value=solution.name, visible=True),
1605
+ gr.Textbox(value=solution.description or "", visible=True),
1606
+ gr.Dropdown(value=solution.data.mode, visible=True),
1607
+ gr.Number(value=self.current_config.options.produce.produce_count, visible=True),
1608
+ gr.Dropdown(value=solution.data.idol, visible=True),
1609
+ gr.Markdown(visible=has_kotone and not is_strict_mode),
1610
+ gr.Checkbox(value=solution.data.auto_set_memory, visible=True),
1611
+ gr.Group(visible=not solution.data.auto_set_memory),
1612
+ gr.Dropdown(value=str(solution.data.memory_set) if solution.data.memory_set else None, visible=True),
1613
+ gr.Checkbox(value=solution.data.auto_set_support_card, visible=True),
1614
+ gr.Group(visible=not solution.data.auto_set_support_card),
1615
+ gr.Dropdown(value=str(solution.data.support_card_set) if solution.data.support_card_set else None, visible=True),
1616
+ gr.Checkbox(value=solution.data.use_pt_boost, visible=True),
1617
+ gr.Checkbox(value=solution.data.use_note_boost, visible=True),
1618
+ gr.Checkbox(value=solution.data.follow_producer, visible=True),
1619
+ gr.Dropdown(value=solution.data.self_study_lesson, visible=True),
1620
+ gr.Checkbox(value=solution.data.prefer_lesson_ap, visible=True),
1621
+ gr.Dropdown(value=[action.value for action in solution.data.actions_order], visible=True),
1622
+ gr.Dropdown(value=solution.data.recommend_card_detection_mode.value, visible=True),
1623
+ gr.Checkbox(value=solution.data.use_ap_drink, visible=True),
1624
+ gr.Checkbox(value=solution.data.skip_commu, visible=True),
1625
+ gr.Button(visible=True), # save_solution_btn
1626
+ ]
1627
+ except FileNotFoundError:
1628
+ gr.Warning(f"培育方案 {solution_id} 不存在")
1629
+ return on_solution_change(None)
1630
+ except Exception as e:
1631
+ gr.Error(f"加载培育方案失败:{str(e)}")
1632
+ return on_solution_change(None)
1633
+
1634
+ def on_new_solution():
1635
+ """创建新的培育方案"""
1636
+ try:
1637
+ new_solution = solution_manager.new("新培育方案")
1638
+ solution_manager.save(new_solution.id, new_solution)
1639
+
1640
+ # 重新列出所有方案
1641
+ solutions = solution_manager.list()
1642
+ solution_choices = [(f"{sol.name} - {sol.description or '无描述'}", sol.id) for sol in solutions]
1643
+
1644
+ gr.Success("新培育方案创建成功")
1645
+ # 根据是否有设置Tab的下拉框来决定返回值
1646
+ updated_dropdown = gr.Dropdown(choices=solution_choices, value=new_solution.id)
1647
+ if settings_dropdown is not None:
1648
+ return [updated_dropdown, updated_dropdown]
1649
+ else:
1650
+ return updated_dropdown
1651
+ except Exception as e:
1652
+ gr.Error(f"创建培育方案失败:{str(e)}")
1653
+ if settings_dropdown is not None:
1654
+ return [gr.Dropdown(), gr.Dropdown()]
1655
+ else:
1656
+ return gr.Dropdown()
1657
+
1658
+ def on_delete_solution(solution_id):
1659
+ """删除当前培育方案"""
1660
+ if not solution_id:
1661
+ gr.Warning("请先选择要删除的培育方案")
1662
+ if settings_dropdown is not None:
1663
+ return [gr.Dropdown(), gr.Dropdown()]
1664
+ else:
1665
+ return gr.Dropdown()
1666
+
1667
+ try:
1668
+ solution_manager.delete(solution_id)
1669
+
1670
+ # 重新列出所有方案
1671
+ solutions = solution_manager.list()
1672
+ solution_choices = [(f"{sol.name} - {sol.description or '无描述'}", sol.id) for sol in solutions]
1673
+
1674
+ gr.Success("培育方案删除成功")
1675
+ # 根据是否有设置Tab的下拉框来决定返回值
1676
+ updated_dropdown = gr.Dropdown(choices=solution_choices, value=None)
1677
+ if settings_dropdown is not None:
1678
+ return [updated_dropdown, updated_dropdown]
1679
+ else:
1680
+ return updated_dropdown
1681
+ except Exception as e:
1682
+ gr.Error(f"删除培育方案失败:{str(e)}")
1683
+ if settings_dropdown is not None:
1684
+ return [gr.Dropdown(), gr.Dropdown()]
1685
+ else:
1686
+ return gr.Dropdown()
1687
+
1688
+ def on_save_solution(solution_id, name, description, mode, count, idols, auto_memory, memory_sets,
1689
+ auto_support, support_card_sets, pt_boost, note_boost, follow_producer, study_lesson, prefer_ap,
1690
+ actions, detection_mode, ap_drink, skip_commu_val):
1691
+ """保存培育方案"""
1692
+ if not solution_id:
1693
+ gr.Warning("请先选择要保存的培育方案")
1694
+ if settings_dropdown is not None:
1695
+ return [gr.Dropdown(), gr.Dropdown()]
1696
+ else:
1697
+ return gr.Dropdown()
1698
+
1699
+ try:
1700
+ # 构建培育数据
1701
+ produce_data = ProduceData(
1702
+ mode=mode,
1703
+ idol=idols if idols else None,
1704
+ memory_set=int(memory_sets) if memory_sets else None,
1705
+ support_card_set=int(support_card_sets) if support_card_sets else None,
1706
+ auto_set_memory=auto_memory,
1707
+ auto_set_support_card=auto_support,
1708
+ use_pt_boost=pt_boost,
1709
+ use_note_boost=note_boost,
1710
+ follow_producer=follow_producer,
1711
+ self_study_lesson=study_lesson,
1712
+ prefer_lesson_ap=prefer_ap,
1713
+ actions_order=[ProduceAction(action) for action in actions] if actions else [],
1714
+ recommend_card_detection_mode=RecommendCardDetectionMode(detection_mode),
1715
+ use_ap_drink=ap_drink,
1716
+ skip_commu=skip_commu_val
1717
+ )
1718
+
1719
+ # 构建方案对象
1720
+ solution = ProduceSolution(
1721
+ id=solution_id,
1722
+ name=name or "未命名方案",
1723
+ description=description,
1724
+ data=produce_data
1725
+ )
1726
+
1727
+ # 保存方案
1728
+ solution_manager.save(solution_id, solution)
1729
+
1730
+ # 同时更新配置中的 produce_count
1731
+ self.current_config.options.produce.produce_count = int(count)
1732
+
1733
+ # 重新列出所有方案(确保没有重复项)
1734
+ solutions = solution_manager.list()
1735
+ solution_choices = [(f"{sol.name} - {sol.description or '无描述'}", sol.id) for sol in solutions]
1736
+
1737
+ gr.Success("培育方案保存成功")
1738
+ # 根据是否有设置Tab的下拉框来决定返回值
1739
+ updated_dropdown = gr.Dropdown(choices=solution_choices, value=solution_id)
1740
+ if settings_dropdown is not None:
1741
+ return [updated_dropdown, updated_dropdown]
1742
+ else:
1743
+ return updated_dropdown
1744
+ except Exception as e:
1745
+ gr.Error(f"保存培育方案失败:{str(e)}")
1746
+ if settings_dropdown is not None:
1747
+ return [gr.Dropdown(), gr.Dropdown()]
1748
+ else:
1749
+ return gr.Dropdown()
1750
+
1751
+ # 绑定事件
1752
+ # 为所有控件绑定change事件,无论是否有选中方案
1753
+ auto_set_memory.change(
1754
+ fn=lambda x: gr.Group(visible=not x),
1755
+ inputs=[auto_set_memory],
1756
+ outputs=[memory_sets_group]
1757
+ )
1758
+
1759
+ auto_set_support.change(
1760
+ fn=lambda x: gr.Group(visible=not x),
1761
+ inputs=[auto_set_support],
1762
+ outputs=[support_card_sets_group]
1763
+ )
1764
+
1765
+ if current_solution is not None:
1127
1766
  recommend_card_detection_mode.change(
1128
1767
  fn=update_kotone_warning,
1129
1768
  inputs=[produce_idols, recommend_card_detection_mode],
@@ -1135,54 +1774,56 @@ class KotoneBotUI:
1135
1774
  outputs=kotone_warning
1136
1775
  )
1137
1776
 
1138
- produce_enabled.change(
1139
- fn=lambda x: gr.Group(visible=x),
1140
- inputs=[produce_enabled],
1141
- outputs=[produce_group]
1777
+ # 绑定方案管理事件
1778
+ solution_dropdown.change(
1779
+ fn=on_solution_change,
1780
+ inputs=[solution_dropdown],
1781
+ outputs=[
1782
+ solution_name, solution_description,
1783
+ produce_mode, produce_count, produce_idols, kotone_warning,
1784
+ auto_set_memory, memory_sets_group, memory_sets,
1785
+ auto_set_support, support_card_sets_group, support_card_sets,
1786
+ use_pt_boost, use_note_boost, follow_producer,
1787
+ self_study_lesson, prefer_lesson_ap, actions_order,
1788
+ recommend_card_detection_mode, use_ap_drink, skip_commu,
1789
+ save_solution_btn
1790
+ ]
1142
1791
  )
1143
1792
 
1144
- auto_set_memory.change(
1145
- fn=lambda x: gr.Group(visible=not x),
1146
- inputs=[auto_set_memory],
1147
- outputs=[memory_sets_group]
1793
+ # 准备输出列表,如果设置Tab的下拉框存在,则同时更新
1794
+ outputs_for_new = [solution_dropdown]
1795
+ outputs_for_delete = [solution_dropdown]
1796
+ outputs_for_save = [solution_dropdown]
1797
+
1798
+ if settings_dropdown is not None:
1799
+ outputs_for_new.append(settings_dropdown)
1800
+ outputs_for_delete.append(settings_dropdown)
1801
+ outputs_for_save.append(settings_dropdown)
1802
+
1803
+ new_solution_btn.click(
1804
+ fn=on_new_solution,
1805
+ outputs=outputs_for_new
1806
+ )
1807
+
1808
+ delete_solution_btn.click(
1809
+ fn=on_delete_solution,
1810
+ inputs=[solution_dropdown],
1811
+ outputs=outputs_for_delete
1812
+ )
1813
+
1814
+ # 绑定保存按钮事件
1815
+ save_solution_btn.click(
1816
+ fn=on_save_solution,
1817
+ inputs=[
1818
+ solution_dropdown, solution_name, solution_description,
1819
+ produce_mode, produce_count, produce_idols,
1820
+ auto_set_memory, memory_sets, auto_set_support, support_card_sets,
1821
+ use_pt_boost, use_note_boost, follow_producer,
1822
+ self_study_lesson, prefer_lesson_ap, actions_order,
1823
+ recommend_card_detection_mode, use_ap_drink, skip_commu
1824
+ ],
1825
+ outputs=outputs_for_save
1148
1826
  )
1149
-
1150
- def set_config(config: BaseConfig, data: dict[ConfigKey, Any]) -> None:
1151
- config.produce.enabled = data['produce_enabled']
1152
- config.produce.mode = data['produce_mode']
1153
- config.produce.produce_count = data['produce_count']
1154
- config.produce.idols = data['produce_idols']
1155
- config.produce.memory_sets = [int(i) for i in data['memory_sets']]
1156
- config.produce.auto_set_memory = data['auto_set_memory']
1157
- config.produce.auto_set_support_card = data['auto_set_support']
1158
- config.produce.use_pt_boost = data['use_pt_boost']
1159
- config.produce.use_note_boost = data['use_note_boost']
1160
- config.produce.follow_producer = data['follow_producer']
1161
- config.produce.self_study_lesson = data['self_study_lesson']
1162
- config.produce.prefer_lesson_ap = data['prefer_lesson_ap']
1163
- config.produce.actions_order = [ProduceAction(action) for action in data['actions_order']]
1164
- config.produce.recommend_card_detection_mode = RecommendCardDetectionMode(data['recommend_card_detection_mode'])
1165
- config.produce.use_ap_drink = data['use_ap_drink']
1166
- config.produce.skip_commu = data['skip_commu']
1167
-
1168
- return set_config, {
1169
- 'produce_enabled': produce_enabled,
1170
- 'produce_mode': produce_mode,
1171
- 'produce_count': produce_count,
1172
- 'produce_idols': produce_idols,
1173
- 'memory_sets': memory_sets,
1174
- 'auto_set_memory': auto_set_memory,
1175
- 'auto_set_support': auto_set_support,
1176
- 'use_pt_boost': use_pt_boost,
1177
- 'use_note_boost': use_note_boost,
1178
- 'follow_producer': follow_producer,
1179
- 'self_study_lesson': self_study_lesson,
1180
- 'prefer_lesson_ap': prefer_lesson_ap,
1181
- 'actions_order': actions_order,
1182
- 'recommend_card_detection_mode': recommend_card_detection_mode,
1183
- 'use_ap_drink': use_ap_drink,
1184
- 'skip_commu': skip_commu
1185
- }
1186
1827
 
1187
1828
  def _create_club_reward_settings(self) -> ConfigBuilderReturnValue:
1188
1829
  with gr.Column():
@@ -1494,14 +2135,22 @@ class KotoneBotUI:
1494
2135
  info=MiscConfig.model_fields['auto_install_update'].description,
1495
2136
  interactive=True
1496
2137
  )
1497
-
2138
+ expose_to_lan = gr.Checkbox(
2139
+ label="允许局域网访问",
2140
+ value=self.current_config.options.misc.expose_to_lan,
2141
+ info=MiscConfig.model_fields['expose_to_lan'].description,
2142
+ interactive=True
2143
+ )
2144
+
1498
2145
  def set_config(config: BaseConfig, data: dict[ConfigKey, Any]) -> None:
1499
2146
  config.misc.check_update = data['check_update']
1500
2147
  config.misc.auto_install_update = data['auto_install_update']
2148
+ config.misc.expose_to_lan = data['expose_to_lan']
1501
2149
 
1502
2150
  return set_config, {
1503
2151
  'check_update': check_update,
1504
- 'auto_install_update': auto_install_update
2152
+ 'auto_install_update': auto_install_update,
2153
+ 'expose_to_lan': expose_to_lan
1505
2154
  }
1506
2155
 
1507
2156
  def _create_settings_tab(self) -> None:
@@ -1870,7 +2519,20 @@ class KotoneBotUI:
1870
2519
  self.current_config = self.config.user_configs[0]
1871
2520
 
1872
2521
  def create_ui(self) -> gr.Blocks:
1873
- with gr.Blocks(title="琴音小助手", css="#container { max-width: 800px; margin: auto; padding: 20px; }") as app:
2522
+ custom_css = """
2523
+ #container { max-width: 800px; margin: auto; padding: 20px; }
2524
+ .quick-controls-row > div {
2525
+ display: flex !important;
2526
+ flex-wrap: nowrap !important;
2527
+ gap: 0 !important;
2528
+ overflow-x: auto !important;
2529
+ }
2530
+ .quick-controls-row > div > div {
2531
+ min-width: auto !important;
2532
+ padding: 0;
2533
+ }
2534
+ """
2535
+ with gr.Blocks(title="琴音小助手", css=custom_css) as app:
1874
2536
  with gr.Column(elem_id="container"):
1875
2537
  gr.Markdown(f"# 琴音小助手 v{self._kaa.version}")
1876
2538
 
@@ -1878,6 +2540,7 @@ class KotoneBotUI:
1878
2540
  self._create_status_tab()
1879
2541
  self._create_task_tab()
1880
2542
  self._create_settings_tab()
2543
+ self._create_produce_tab()
1881
2544
  self._create_log_tab()
1882
2545
  self._create_whats_new_tab()
1883
2546
  self._create_screen_tab()
@@ -1888,7 +2551,9 @@ def main(kaa: Kaa | None = None) -> None:
1888
2551
  kaa = kaa or Kaa('./config.json')
1889
2552
  ui = KotoneBotUI(kaa)
1890
2553
  app = ui.create_ui()
1891
- app.launch(inbrowser=True, show_error=True)
2554
+
2555
+ server_name = "0.0.0.0" if ui.current_config.options.misc.expose_to_lan else "127.0.0.1"
2556
+ app.launch(inbrowser=True, show_error=True, server_name=server_name)
1892
2557
 
1893
2558
  if __name__ == "__main__":
1894
2559
  main()