ksaa 2025.7.7.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 (169) hide show
  1. kotonebot/backend/context/context.py +19 -6
  2. kotonebot/kaa/common.py +2 -976
  3. kotonebot/kaa/config/__init__.py +62 -0
  4. kotonebot/kaa/config/const.py +255 -0
  5. kotonebot/kaa/config/migrations/__init__.py +28 -0
  6. kotonebot/kaa/config/migrations/_idol.py +106 -0
  7. kotonebot/kaa/config/migrations/_v1_to_v2.py +203 -0
  8. kotonebot/kaa/config/migrations/_v2_to_v3.py +126 -0
  9. kotonebot/kaa/config/migrations/_v3_to_v4.py +29 -0
  10. kotonebot/kaa/config/migrations/_v4_to_v5.py +26 -0
  11. kotonebot/kaa/config/migrations/_v5_to_v6.py +134 -0
  12. kotonebot/kaa/config/produce.py +255 -0
  13. kotonebot/kaa/config/schema.py +236 -0
  14. kotonebot/kaa/config/upgrade.py +63 -0
  15. kotonebot/kaa/game_ui/commu_event_buttons.py +3 -0
  16. kotonebot/kaa/game_ui/schedule.py +1 -1
  17. kotonebot/kaa/main/gr.py +804 -168
  18. kotonebot/kaa/main/kaa.py +19 -13
  19. kotonebot/kaa/metadata.py +31 -0
  20. kotonebot/kaa/resources/__pycache__/__init__.cpython-310.pyc +0 -0
  21. kotonebot/kaa/tasks/R.py +126 -126
  22. kotonebot/kaa/tasks/daily/acquire_activity_funds.py +1 -1
  23. kotonebot/kaa/tasks/daily/acquire_presents.py +1 -1
  24. kotonebot/kaa/tasks/daily/assignment.py +1 -1
  25. kotonebot/kaa/tasks/daily/capsule_toys.py +1 -1
  26. kotonebot/kaa/tasks/daily/club_reward.py +1 -1
  27. kotonebot/kaa/tasks/daily/contest.py +1 -1
  28. kotonebot/kaa/tasks/daily/mission_reward.py +1 -1
  29. kotonebot/kaa/tasks/daily/purchase.py +1 -1
  30. kotonebot/kaa/tasks/daily/upgrade_support_card.py +1 -1
  31. kotonebot/kaa/tasks/end_game.py +1 -1
  32. kotonebot/kaa/tasks/produce/cards.py +1 -1
  33. kotonebot/kaa/tasks/produce/common.py +3 -2
  34. kotonebot/kaa/tasks/produce/in_purodyuusu.py +9 -7
  35. kotonebot/kaa/tasks/produce/non_lesson_actions.py +3 -2
  36. kotonebot/kaa/tasks/produce/produce.py +27 -22
  37. kotonebot/kaa/tasks/start_game.py +1 -1
  38. {ksaa-2025.7.7.0.dist-info → ksaa-2025.7.9.0.dist-info}/METADATA +1 -1
  39. {ksaa-2025.7.7.0.dist-info → ksaa-2025.7.9.0.dist-info}/RECORD +169 -157
  40. /kotonebot/kaa/sprites/{21fe29c2-f49b-473f-8ac3-896b4d3c72f5.png → 02cf0df9-37d6-4387-b8eb-c92589264c2a.png} +0 -0
  41. /kotonebot/kaa/sprites/{d07f0d30-465e-4b4e-803f-a81aeabdd1e8.png → 02d4e179-912e-4e1f-ba7d-ea37fe87279e.png} +0 -0
  42. /kotonebot/kaa/sprites/{87a59b06-0ac7-4a35-93c4-3705bf9e774a.png → 037cb117-8521-4670-b3ec-ee0e260c1d62.png} +0 -0
  43. /kotonebot/kaa/sprites/{835a1f3e-5a06-4490-bc2e-c6d3d8edc1fd.png → 04be14b5-4169-4b3e-ab14-224db52c9a39.png} +0 -0
  44. /kotonebot/kaa/sprites/{6faf9942-994d-418a-ae42-25c5fcffa79e.png → 06bb9a6e-1dbe-48db-91d7-51d9fc3ffcce.png} +0 -0
  45. /kotonebot/kaa/sprites/{308818b7-a252-45a6-868d-553c078b3752.png → 08444afd-90d4-43ac-b3ee-128a5bdef4a2.png} +0 -0
  46. /kotonebot/kaa/sprites/{f957edb2-3534-4d1d-a9be-70b478b2ff63.png → 0910c5f3-7f72-4385-967c-4bf226c9861b.png} +0 -0
  47. /kotonebot/kaa/sprites/{20748b0c-889f-4706-857b-48fc921a88e3.png → 0b332c2c-aa57-4f10-aa55-8e981f2e7c27.png} +0 -0
  48. /kotonebot/kaa/sprites/{e007420c-b92b-414c-96a3-d556e3c25cb2.png → 0c4ee900-3e44-4e37-a199-32d66daa2025.png} +0 -0
  49. /kotonebot/kaa/sprites/{688d653e-7ee7-4d41-ac79-b4efd6c3cadd.png → 0cfd52cc-1f38-4804-bc1f-8da9cc51d969.png} +0 -0
  50. /kotonebot/kaa/sprites/{4d3e267c-552c-4a65-840a-dc72a61c8db1.png → 131d5c1b-70b3-47d3-b6d6-318045629037.png} +0 -0
  51. /kotonebot/kaa/sprites/{d5899bda-b311-469d-b4fb-963799ef1720.png → 133dbdd9-23fa-4157-9f9e-fd1728207bd0.png} +0 -0
  52. /kotonebot/kaa/sprites/{f2d614b3-d3bf-4340-b261-f4c385a59e4e.png → 17d2730b-e56e-4956-973d-5f822490a2c5.png} +0 -0
  53. /kotonebot/kaa/sprites/{d7d6ace9-35f1-4c71-b4c1-9de938b254f4.png → 231b3e86-cfc5-4e08-803b-63ed680ab1ad.png} +0 -0
  54. /kotonebot/kaa/sprites/{5efa51e6-5cb7-4843-9397-8d71c6175fcf.png → 2569011c-3bad-416c-b358-ceaf313507e8.png} +0 -0
  55. /kotonebot/kaa/sprites/{466524da-0d9e-424f-82eb-d6e6d3145bd3.png → 26dd326a-a6da-4350-8140-217e9d6a6109.png} +0 -0
  56. /kotonebot/kaa/sprites/{2712893d-0219-43e1-8de7-c2761456719e.png → 29119167-eb9c-4c35-9c63-9c9967f85163.png} +0 -0
  57. /kotonebot/kaa/sprites/{99b58811-42ff-415b-9229-f5c75cbe1a1a.png → 2b8385d8-ea7e-4675-9d16-57b905a18d90.png} +0 -0
  58. /kotonebot/kaa/sprites/{b974e1ac-1f24-4498-aa84-62cb5c0984e7.png → 2cd2047f-91af-4632-8cb2-eb2fc4b4c808.png} +0 -0
  59. /kotonebot/kaa/sprites/{e6a16a1e-e821-45f0-bc64-f2e0dab7efd7.png → 314bc3ab-8c73-4517-ae7c-75d21ac61448.png} +0 -0
  60. /kotonebot/kaa/sprites/{8308964d-96d1-4b7e-b0fa-b20163311153.png → 33e4e6c9-d245-4174-8303-04019ce20136.png} +0 -0
  61. /kotonebot/kaa/sprites/{774ca489-09c2-414e-b27b-f32d3bf6894d.png → 34cce4b7-53fe-4ea2-82d8-d31fe7b9abcd.png} +0 -0
  62. /kotonebot/kaa/sprites/{cdc6e5e2-5b38-4471-b23f-17ec229268db.png → 3820d53e-5b87-4a35-9472-e90498225853.png} +0 -0
  63. /kotonebot/kaa/sprites/{f26d4e09-2511-48e4-9c69-ba413ddf65e1.png → 38e35291-2a94-4261-9b58-80d7b17165c9.png} +0 -0
  64. /kotonebot/kaa/sprites/{bcb990e6-58ae-460d-859a-812b4121e716.png → 3ae6e096-42e4-4ac4-ad79-6f2529925c16.png} +0 -0
  65. /kotonebot/kaa/sprites/{80c45554-0758-47eb-b9d7-d8c10f462ae5.png → 3c41fb45-6400-4818-9066-e03d60d2a895.png} +0 -0
  66. /kotonebot/kaa/sprites/{b2f31f86-b7ae-4eb1-8042-d14c5b226714.png → 3e9adf0f-f6c5-4d68-9667-97ea2f82bb51.png} +0 -0
  67. /kotonebot/kaa/sprites/{18369504-36b1-4b10-93e6-878c2cae6c8f.png → 3ef649e7-c03a-40d1-9a76-653faaf799df.png} +0 -0
  68. /kotonebot/kaa/sprites/{23464a7b-dc7a-439c-86b7-04a5dd506412.png → 43226a61-3d61-4acb-afbb-812bf9e97843.png} +0 -0
  69. /kotonebot/kaa/sprites/{1762b8dc-abb8-402e-88b9-22111b054d27.png → 443a5dbf-e2fb-4d34-bb09-c21e1437f715.png} +0 -0
  70. /kotonebot/kaa/sprites/{76f43a30-b76d-4648-91b6-49f2786e668d.png → 459851f5-fa20-45c4-a6d2-1018b3976fcd.png} +0 -0
  71. /kotonebot/kaa/sprites/{bbfb7670-2537-4a92-9a39-487d174f27a0.png → 46c520e7-7b97-43be-8cc2-21e478b5d844.png} +0 -0
  72. /kotonebot/kaa/sprites/{6d4337f4-e30c-44eb-bab9-220a46c0c96f.png → 4867e835-c805-463e-9a53-1e677e3d140f.png} +0 -0
  73. /kotonebot/kaa/sprites/{2f4f3d81-2a8c-49d3-84a8-4d1205237ed4.png → 48ebb790-2310-436d-a31c-dba4db034cbc.png} +0 -0
  74. /kotonebot/kaa/sprites/{c692a9b3-8a2a-42f1-8f63-ad8bd553272d.png → 4b8ebe86-7a0d-474a-abac-b4a45fda5e88.png} +0 -0
  75. /kotonebot/kaa/sprites/{6f638005-aa18-4804-a5fe-269de4d1ad9e.png → 4c235498-622f-4f74-9ebb-df3fcd3306ab.png} +0 -0
  76. /kotonebot/kaa/sprites/{05d933de-6274-4d46-a81b-860de1981ebc.png → 4f3d2710-5626-4471-9b21-cd01b8c542d1.png} +0 -0
  77. /kotonebot/kaa/sprites/{dfb1d18d-b768-46c4-9d31-b654ba7a2b6d.png → 4f4e3cf3-b1d9-436b-9477-5f2244c20d6b.png} +0 -0
  78. /kotonebot/kaa/sprites/{1cede0b7-5042-481c-b507-957dd98ec17a.png → 4f891dc4-71c0-4492-a8d1-0c52978e75e1.png} +0 -0
  79. /kotonebot/kaa/sprites/{30ff50f2-7ab2-4a1d-88db-fd6deaba328e.png → 4ff46fa5-fe9e-4103-8012-451adc14dc43.png} +0 -0
  80. /kotonebot/kaa/sprites/{e798ff2f-6f30-4536-923a-a65433817423.png → 5399e464-1ee6-406b-acab-7826e30f3fd9.png} +0 -0
  81. /kotonebot/kaa/sprites/{51eac702-ca23-4aba-b75a-cdb03a93a117.png → 540a64f4-8111-4df4-abfe-0e62e0f8c7af.png} +0 -0
  82. /kotonebot/kaa/sprites/{c9e507d5-94dd-4ff3-b995-70c6cb360095.png → 5422d945-aa90-443e-bf79-f8ab93ec9411.png} +0 -0
  83. /kotonebot/kaa/sprites/{31dd40b0-1c07-4d6c-aabe-fd3e4895f4df.png → 585c7846-f353-448f-8eb9-1ceafec94555.png} +0 -0
  84. /kotonebot/kaa/sprites/{e87f0760-4bc9-4d7f-91e2-5452ba0fcd9d.png → 5a87228a-ec5d-4ffc-951a-1454c9c03bdc.png} +0 -0
  85. /kotonebot/kaa/sprites/{b73fa422-bf9c-43aa-ad80-ae92286042e6.png → 5b14a452-ea54-4804-8ec0-3cd916cd8e88.png} +0 -0
  86. /kotonebot/kaa/sprites/{467fe027-96ba-48b1-963b-75a5c41277c4.png → 5cc8ccda-2cf7-4956-b67d-15327bc75ed6.png} +0 -0
  87. /kotonebot/kaa/sprites/{e614c8e1-1d7b-4535-a8ba-cbf09fd5b163.png → 5e27d1c5-cc3f-4aee-8d79-69c09206fa3d.png} +0 -0
  88. /kotonebot/kaa/sprites/{c1336997-ea27-4d53-9c64-826ca7eca11f.png → 64938ad2-442f-41eb-a544-4d2611e8012f.png} +0 -0
  89. /kotonebot/kaa/sprites/{f9b38a5e-72cb-4b18-8817-18473effd41d.png → 65223004-722e-4003-af09-c7769e8a7cb2.png} +0 -0
  90. /kotonebot/kaa/sprites/{6f06519d-4f33-4418-b4cb-35a7356cc121.png → 659a1775-7001-4add-96e9-292693a26b60.png} +0 -0
  91. /kotonebot/kaa/sprites/{e64c9477-35f7-4f05-995f-f3f38bb7db66.png → 6626694b-1394-44af-b76b-791c5bb2428b.png} +0 -0
  92. /kotonebot/kaa/sprites/{5cff1e6f-81ea-4d4a-88ba-209cf3bbb165.png → 6a202eb6-dd41-4675-a840-99dde2b2efa4.png} +0 -0
  93. /kotonebot/kaa/sprites/{10713c56-e462-4543-8a51-02f220ed6943.png → 6b2e887b-e113-4280-9779-6795c2782c58.png} +0 -0
  94. /kotonebot/kaa/sprites/{6df0db09-9159-43b5-a6b9-43a2dfdafdab.png → 6eb959e1-ee64-4fa6-a20f-8ee4e51f2c6a.png} +0 -0
  95. /kotonebot/kaa/sprites/{7dd1c478-719f-4432-891f-9543064fd1fc.png → 7098fbf7-b8cc-4933-bfec-12a2ac98e38c.png} +0 -0
  96. /kotonebot/kaa/sprites/{c7e90767-3661-4e86-8c54-8e1d1e83d113.png → 712e9223-4dd2-4ff6-887b-4182fd243d78.png} +0 -0
  97. /kotonebot/kaa/sprites/{acd1a611-f93d-4d32-8070-dc325b42eeb9.png → 7256a95e-24b8-40fd-bd8e-73a1572c3f93.png} +0 -0
  98. /kotonebot/kaa/sprites/{6490c5b2-2ed8-44d6-93b8-72d88434b49e.png → 73f89439-c4e3-4263-8fa7-229cde98aa99.png} +0 -0
  99. /kotonebot/kaa/sprites/{2154ebd3-9c89-4355-b4f4-a5e18ecf728d.png → 74efd362-4cc1-4b9f-8032-e5bc45c2af5c.png} +0 -0
  100. /kotonebot/kaa/sprites/{a586f586-85e9-439e-ab3f-905d6cbe6746.png → 756ac796-ce43-4ddb-989e-13bf07cbe3b7.png} +0 -0
  101. /kotonebot/kaa/sprites/{78c0f6b4-c09d-4b44-9b5e-35e1e40dd748.png → 77193249-7e2a-4652-ab6d-a463350ca226.png} +0 -0
  102. /kotonebot/kaa/sprites/{0eb4e53c-f0af-4c86-870c-b1db087d53db.png → 784a91b2-4d24-461f-8bd3-2f02b9bc193f.png} +0 -0
  103. /kotonebot/kaa/sprites/{f18c683d-1eb2-4279-a05c-c411683354df.png → 83c67f2a-0f73-4238-a5a8-8ebb839ed99a.png} +0 -0
  104. /kotonebot/kaa/sprites/{3ddd0976-7c8b-4c67-bac7-a0cc1af3bfad.png → 86b3bab1-c5f6-48b2-b810-c3ec55c32314.png} +0 -0
  105. /kotonebot/kaa/sprites/{bfd495eb-7ec2-47d7-aff2-59c1a663be5d.png → 872838c5-47c6-4f78-b105-0a72b5459f16.png} +0 -0
  106. /kotonebot/kaa/sprites/{b720a22b-a2f1-4686-969d-2a2edd8fb96b.png → 93f03304-5609-4f4f-9ac8-a46e7b883960.png} +0 -0
  107. /kotonebot/kaa/sprites/{4e040068-e2ae-4348-80a2-f113c2426d46.png → 97e96ecf-e51b-4a09-ab11-3c164196747f.png} +0 -0
  108. /kotonebot/kaa/sprites/{5367d7ad-5a27-42e4-a7d9-5bf27102f502.png → 992473c3-df0a-4c72-8134-f2aac9e7b0f6.png} +0 -0
  109. /kotonebot/kaa/sprites/{c686d99a-248a-460b-a4fe-2fa5b8e9660b.png → 9d86ab77-de0b-433d-9b0e-5aba283309a6.png} +0 -0
  110. /kotonebot/kaa/sprites/{5d5db2d4-2648-40fe-bd17-05aea9afbc7d.png → 9eb202c8-c61a-4918-beb9-b0f03739b0b3.png} +0 -0
  111. /kotonebot/kaa/sprites/{f3e4e9ec-ddd6-42c4-9638-b93ff4e6b514.png → a4e02797-2c5d-4860-aaa4-c20c43be7500.png} +0 -0
  112. /kotonebot/kaa/sprites/{2d4001e6-137e-40b2-94b0-ba3ae9e397e4.png → a5c582f5-3627-44be-b574-a4e4287376e0.png} +0 -0
  113. /kotonebot/kaa/sprites/{b2743383-a3e4-43ff-82a3-3c7c6450fc50.png → a914da74-9752-42be-913b-86514eb4b589.png} +0 -0
  114. /kotonebot/kaa/sprites/{9d94c24c-5aab-4fb6-8fa7-902cebac134c.png → aacb651b-9a3d-42a1-9fc0-9187dc8cded7.png} +0 -0
  115. /kotonebot/kaa/sprites/{7315c6b9-6fda-4790-8e9a-c8c4220834e1.png → ae146d94-5e69-4970-b175-d7c8c4f9a9cd.png} +0 -0
  116. /kotonebot/kaa/sprites/{acd01a53-c689-4ffd-ae45-744a37c70197.png → ae57e1fb-c42f-4401-93a1-76d4591b5fad.png} +0 -0
  117. /kotonebot/kaa/sprites/{d108794a-60b8-4637-bced-84f46140eaac.png → b1878d2b-4908-4342-b395-864aafa5c54b.png} +0 -0
  118. /kotonebot/kaa/sprites/{fffa0118-dd3a-4d01-8c4e-d43182778391.png → b26e3c78-a6be-4ad1-8992-c3245b1a6f9b.png} +0 -0
  119. /kotonebot/kaa/sprites/{f5917c99-185e-4bd9-b367-972c77accb44.png → b3a41d58-f375-4882-bebb-57f72322d016.png} +0 -0
  120. /kotonebot/kaa/sprites/{59997849-5a5a-4589-a4ff-e91a789fc68d.png → b4905122-7d97-4561-a14a-b8a9a5cd9227.png} +0 -0
  121. /kotonebot/kaa/sprites/{2d0ed04f-777a-4a69-9a58-0be791260dca.png → b534423c-2024-4234-9886-f49e17dd96e7.png} +0 -0
  122. /kotonebot/kaa/sprites/{898325da-307d-4108-ab4c-25d9ae94ee24.png → b6680d31-8552-4111-bc39-0867c06bf94a.png} +0 -0
  123. /kotonebot/kaa/sprites/{5587551f-011c-4f94-86e8-7e81d08c4be2.png → b6c637bf-5fdd-4e68-b4d8-b403bf611f3b.png} +0 -0
  124. /kotonebot/kaa/sprites/{4abd8e80-83ef-4d1a-b143-e6ad0ac189ab.png → b9e19bda-3793-4cf4-928a-fc43642b32e6.png} +0 -0
  125. /kotonebot/kaa/sprites/{9e861b2e-f896-4738-b0d0-9b703395720d.png → bc1c640a-87d8-47af-9fcc-8681acac7b27.png} +0 -0
  126. /kotonebot/kaa/sprites/{54d71b39-a3f2-4f20-a294-b6b5ef9c56f3.png → bc25ed87-50a7-4aa8-b743-505450677b00.png} +0 -0
  127. /kotonebot/kaa/sprites/{4112f697-094b-4046-bfac-409f156784b0.png → bcf2f87a-de7f-4fb9-aa6c-0b4f6bff921e.png} +0 -0
  128. /kotonebot/kaa/sprites/{54f5e4d6-44f9-4249-bf80-aaaacf0a8d52.png → bdd0e8f8-3d35-48e8-b735-66eaf2ece2e6.png} +0 -0
  129. /kotonebot/kaa/sprites/{1e398be7-49ac-4eb6-b828-b935f042037a.png → bec6c0cf-40f6-446d-85b3-c692d3322a51.png} +0 -0
  130. /kotonebot/kaa/sprites/{af0f65a5-8d32-4211-86df-66b3fa609462.png → bf19069d-e044-4f76-93f7-f2ecd3214e47.png} +0 -0
  131. /kotonebot/kaa/sprites/{4eb9a3a1-da46-493b-a17d-5eb9ef53524c.png → c1274e01-2cc7-432f-b244-65ffe8269656.png} +0 -0
  132. /kotonebot/kaa/sprites/{177ee196-1013-487e-9944-64c4a9b803ef.png → c65d71af-ffb3-4992-b954-c59ae48615b8.png} +0 -0
  133. /kotonebot/kaa/sprites/{f9e8cde8-fda0-4436-8072-6bc32c3c0b8e.png → c67852a2-30a9-4fd6-a4c2-83870a658998.png} +0 -0
  134. /kotonebot/kaa/sprites/{3de5ce1b-f72b-450a-a1de-5a841fbd507a.png → c705eece-67d8-4017-a4d9-a7f1337f67be.png} +0 -0
  135. /kotonebot/kaa/sprites/{5200fbda-653d-4b6f-84d8-15793cc53684.png → c86a3385-407e-40d5-b519-1927406d5b09.png} +0 -0
  136. /kotonebot/kaa/sprites/{08f93e03-18c9-42e3-9a2f-7d7954f585b0.png → ca42ca0c-3829-4e43-88c9-db4939cfa982.png} +0 -0
  137. /kotonebot/kaa/sprites/{3e9bdd08-3a74-40b3-8320-05ed4e8fe5d7.png → cba7528d-ae17-4a37-b388-6f86e1a590f4.png} +0 -0
  138. /kotonebot/kaa/sprites/{1cd922b1-cd9c-4b60-b7e7-014c59217cb0.png → cc1767ec-77db-49ac-8c9e-f48d1fb7b071.png} +0 -0
  139. /kotonebot/kaa/sprites/{2ffd9c12-0520-4f9c-92b1-bfdef0681583.png → ce282e51-7067-4293-ad26-24dbba172a08.png} +0 -0
  140. /kotonebot/kaa/sprites/{1d714b45-6b20-40ba-8e0b-e7c106f0c8f3.png → d1e5672d-df91-4316-984c-48550c5d1931.png} +0 -0
  141. /kotonebot/kaa/sprites/{126f5161-3567-4c76-8e91-371392e39a9c.png → d2d99405-7927-47fc-be4c-a7591b339a6c.png} +0 -0
  142. /kotonebot/kaa/sprites/{489feedd-f44e-4714-ad24-b53630dfcf27.png → d356fc84-a8c0-4d0f-a3ed-c7ff5ccd276c.png} +0 -0
  143. /kotonebot/kaa/sprites/{0089161a-0dac-41da-97af-b9200339a383.png → d477e49c-37cc-4e71-a8e6-6633f044260a.png} +0 -0
  144. /kotonebot/kaa/sprites/{2ed453f3-9c31-4c96-95dd-1a6aa68302f7.png → d4b1e48b-bf9c-4f44-9ddb-3af8eb4ea464.png} +0 -0
  145. /kotonebot/kaa/sprites/{6a45398a-4240-4fb7-8926-fa1254125bbf.png → d6d6229a-2345-4fe7-b2c5-109fcdb37c39.png} +0 -0
  146. /kotonebot/kaa/sprites/{adf0eea7-a052-410b-b479-8c672ae38268.png → d953cdee-08b5-45fb-908b-2644220b0f07.png} +0 -0
  147. /kotonebot/kaa/sprites/{3091351b-ab63-4688-8082-32545052d7a8.png → de069910-6085-45a9-ba96-64bc7aeead77.png} +0 -0
  148. /kotonebot/kaa/sprites/{7c40ea85-87f6-4531-a25a-896dd70b49d1.png → dea4c704-5739-423f-a15c-f31a4a93d64f.png} +0 -0
  149. /kotonebot/kaa/sprites/{dd431a8a-3ffa-43d6-96c6-4e84aa946b72.png → debc6a94-9bf1-46d7-b0b0-0c55cb367f12.png} +0 -0
  150. /kotonebot/kaa/sprites/{06e7d3f6-1ab8-4714-8ab5-8af71dcbfa78.png → e0555145-9446-4ebe-965b-f46b458e5681.png} +0 -0
  151. /kotonebot/kaa/sprites/{025f1786-cd28-4a08-ad81-178d267dbb1a.png → e19c5f10-5f93-4431-9bf3-4f92512eab6e.png} +0 -0
  152. /kotonebot/kaa/sprites/{2146a037-c3ad-4c33-834c-ddd7f3b7876c.png → e353b4cb-ea6d-4fc4-91ec-c19582e9507c.png} +0 -0
  153. /kotonebot/kaa/sprites/{d43f214a-4db4-4222-941c-3d3216a0c0c3.png → e6554fee-c6fd-49ee-8c32-b4932fc701da.png} +0 -0
  154. /kotonebot/kaa/sprites/{0913f34e-1790-4afb-af31-9a5e94d54b05.png → e916a5ca-287c-4cbe-93ca-22b439c5ffab.png} +0 -0
  155. /kotonebot/kaa/sprites/{899ad2c0-7b23-4b77-aed4-34ba4911672b.png → ed4a2db1-ab2e-4b36-8d6f-5b7961501475.png} +0 -0
  156. /kotonebot/kaa/sprites/{e93a983d-b869-45e4-8a5c-cd1c9d511b11.png → ed4a318e-f69a-4fb9-9853-9746f01c6015.png} +0 -0
  157. /kotonebot/kaa/sprites/{4670fd78-3748-4df3-968b-25c8246da92b.png → efe68984-8dbc-417e-924c-87c6860c58ef.png} +0 -0
  158. /kotonebot/kaa/sprites/{e6d0979a-cd27-4933-b528-7777be525ace.png → f165bf01-9e9d-4afb-87d9-4a26318140cf.png} +0 -0
  159. /kotonebot/kaa/sprites/{fc44214e-ef8a-4ea1-baec-35674ce0c4d6.png → f2846992-402e-4f50-b74e-91d6f3b8994d.png} +0 -0
  160. /kotonebot/kaa/sprites/{bad07ebd-c8e7-4721-ab74-a38fa30e0401.png → f4227a80-f62d-4daf-83d0-c7b5500088ee.png} +0 -0
  161. /kotonebot/kaa/sprites/{97e33fa0-1442-418d-b393-3b916312c9e1.png → f496a454-5cf5-4b6b-aedb-1dad58c85035.png} +0 -0
  162. /kotonebot/kaa/sprites/{119f04e2-3871-46a8-9d5c-808c641f7aae.png → f4af8fb2-6270-4b75-8b24-d0e49daebac1.png} +0 -0
  163. /kotonebot/kaa/sprites/{0a3c0a4e-a979-401c-9bf3-a389e8a74e7b.png → f60c40a1-750b-41ac-9d24-2d7ffce44166.png} +0 -0
  164. /kotonebot/kaa/sprites/{c639b2f6-35f2-4924-9e81-878637c176a6.png → f6c3bd48-fe1e-4fe3-bf58-13422b5b4a99.png} +0 -0
  165. /kotonebot/kaa/sprites/{84c0f8bf-c670-47d4-8d5c-06de599f7c40.png → ffaffa14-22dd-4397-8dc1-7b94fd4cf06b.png} +0 -0
  166. {ksaa-2025.7.7.0.dist-info → ksaa-2025.7.9.0.dist-info}/WHEEL +0 -0
  167. {ksaa-2025.7.7.0.dist-info → ksaa-2025.7.9.0.dist-info}/entry_points.txt +0 -0
  168. {ksaa-2025.7.7.0.dist-info → ksaa-2025.7.9.0.dist-info}/licenses/LICENSE +0 -0
  169. {ksaa-2025.7.7.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
@@ -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
@@ -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]
@@ -1029,13 +1224,21 @@ class KotoneBotUI:
1029
1224
  value=self.current_config.options.produce.enabled,
1030
1225
  info=ProduceConfig.model_fields['enabled'].description
1031
1226
  )
1227
+
1032
1228
  with gr.Group(visible=self.current_config.options.produce.enabled) as produce_group:
1033
- produce_mode = gr.Dropdown(
1034
- choices=["regular", "pro", "master"],
1035
- value=self.current_config.options.produce.mode,
1036
- label="培育模式",
1037
- 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
1038
1240
  )
1241
+
1039
1242
  produce_count = gr.Number(
1040
1243
  minimum=1,
1041
1244
  value=self.current_config.options.produce.produce_count,
@@ -1043,106 +1246,523 @@ class KotoneBotUI:
1043
1246
  interactive=True,
1044
1247
  info=ProduceConfig.model_fields['produce_count'].description
1045
1248
  )
1046
- # 添加偶像选择
1047
- idol_choices = []
1048
- for idol in IdolCard.all():
1049
- if idol.is_another:
1050
- idol_choices.append((f'{idol.name} 「{idol.another_name}」', idol.skin_id))
1051
- else:
1052
- idol_choices.append((f'{idol.name}', idol.skin_id))
1053
- selected_idols = self.current_config.options.produce.idols
1054
- produce_idols = gr.Dropdown(
1055
- choices=idol_choices,
1056
- value=selected_idols,
1057
- label="选择要培育的偶像",
1058
- multiselect=True,
1059
- interactive=True,
1060
- info=ProduceConfig.model_fields['idols'].description
1061
- )
1062
- has_kotone = any("藤田ことね" in idol for idol in selected_idols)
1063
- is_strict_mode = self.current_config.options.produce.recommend_card_detection_mode == RecommendCardDetectionMode.STRICT
1064
- kotone_warning = gr.Markdown(
1065
- visible=has_kotone and not is_strict_mode,
1066
- value="使用「藤田ことね」进行培育时,确保将「推荐卡检测模式」设置为「严格模式」"
1067
- )
1068
- auto_set_memory = gr.Checkbox(
1069
- label="自动编成回忆",
1070
- value=self.current_config.options.produce.auto_set_memory,
1071
- info=ProduceConfig.model_fields['auto_set_memory'].description
1072
- )
1073
- with gr.Group(visible=not self.current_config.options.produce.auto_set_memory) as memory_sets_group:
1074
- memory_sets = gr.Dropdown(
1075
- choices=[str(i) for i in range(1, 11)], # 假设最多10个编成位
1076
- value=[str(i) for i in self.current_config.options.produce.memory_sets],
1077
- 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="每一周的行动将会按这里设置的优先级执行。",
1078
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="培育次数",
1079
1446
  interactive=True,
1080
- info=ProduceConfig.model_fields['memory_sets'].description
1447
+ info="培育的次数。"
1081
1448
  )
1082
1449
 
1083
- # 添加偶像选择变化时的回调
1084
- def update_kotone_warning(selected_idols, recommend_card_detection_mode):
1085
- has_kotone = any("藤田ことね" in idol for idol in selected_idols)
1086
- is_strict_mode = recommend_card_detection_mode == RecommendCardDetectionMode.STRICT.value
1087
- 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
+ )
1088
1466
 
1089
- auto_set_support = gr.Checkbox(
1090
- label="自动编成支援卡",
1091
- value=self.current_config.options.produce.auto_set_support_card,
1092
- info=ProduceConfig.model_fields['auto_set_support_card'].description
1093
- )
1094
- use_pt_boost = gr.Checkbox(
1095
- label="使用支援强化 Pt 提升",
1096
- value=self.current_config.options.produce.use_pt_boost,
1097
- info=ProduceConfig.model_fields['use_pt_boost'].description
1098
- )
1099
- use_note_boost = gr.Checkbox(
1100
- label="使用笔记数提升",
1101
- value=self.current_config.options.produce.use_note_boost,
1102
- info=ProduceConfig.model_fields['use_note_boost'].description
1103
- )
1104
- follow_producer = gr.Checkbox(
1105
- label="关注租借了支援卡的制作人",
1106
- value=self.current_config.options.produce.follow_producer,
1107
- info=ProduceConfig.model_fields['follow_producer'].description
1108
- )
1109
- self_study_lesson = gr.Dropdown(
1110
- choices=['dance', 'visual', 'vocal'],
1111
- value=self.current_config.options.produce.self_study_lesson,
1112
- label='文化课自习时选项',
1113
- info='选择自习课类型'
1114
- )
1115
- prefer_lesson_ap = gr.Checkbox(
1116
- label="SP 课程优先",
1117
- value=self.current_config.options.produce.prefer_lesson_ap,
1118
- info=ProduceConfig.model_fields['prefer_lesson_ap'].description
1119
- )
1120
- actions_order = gr.Dropdown(
1121
- choices=[(action.display_name, action.value) for action in ProduceAction],
1122
- value=[action.value for action in self.current_config.options.produce.actions_order],
1123
- label="行动优先级",
1124
- info="设置每周行动的优先级顺序",
1125
- multiselect=True
1126
- )
1127
- recommend_card_detection_mode = gr.Dropdown(
1128
- choices=[
1129
- (RecommendCardDetectionMode.NORMAL.display_name, RecommendCardDetectionMode.NORMAL.value),
1130
- (RecommendCardDetectionMode.STRICT.display_name, RecommendCardDetectionMode.STRICT.value)
1131
- ],
1132
- value=self.current_config.options.produce.recommend_card_detection_mode.value,
1133
- label="推荐卡检测模式",
1134
- info=ProduceConfig.model_fields['recommend_card_detection_mode'].description
1135
- )
1136
- use_ap_drink = gr.Checkbox(
1137
- label="AP 不足时自动使用 AP 饮料",
1138
- value=self.current_config.options.produce.use_ap_drink,
1139
- info=ProduceConfig.model_fields['use_ap_drink'].description
1140
- )
1141
- skip_commu = gr.Checkbox(
1142
- label="检测并跳过交流",
1143
- value=self.current_config.options.produce.skip_commu,
1144
- info=ProduceConfig.model_fields['skip_commu'].description
1145
- )
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:
1146
1766
  recommend_card_detection_mode.change(
1147
1767
  fn=update_kotone_warning,
1148
1768
  inputs=[produce_idols, recommend_card_detection_mode],
@@ -1154,54 +1774,56 @@ class KotoneBotUI:
1154
1774
  outputs=kotone_warning
1155
1775
  )
1156
1776
 
1157
- produce_enabled.change(
1158
- fn=lambda x: gr.Group(visible=x),
1159
- inputs=[produce_enabled],
1160
- 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
+ ]
1161
1791
  )
1162
1792
 
1163
- auto_set_memory.change(
1164
- fn=lambda x: gr.Group(visible=not x),
1165
- inputs=[auto_set_memory],
1166
- 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
1167
1826
  )
1168
-
1169
- def set_config(config: BaseConfig, data: dict[ConfigKey, Any]) -> None:
1170
- config.produce.enabled = data['produce_enabled']
1171
- config.produce.mode = data['produce_mode']
1172
- config.produce.produce_count = data['produce_count']
1173
- config.produce.idols = data['produce_idols']
1174
- config.produce.memory_sets = [int(i) for i in data['memory_sets']]
1175
- config.produce.auto_set_memory = data['auto_set_memory']
1176
- config.produce.auto_set_support_card = data['auto_set_support']
1177
- config.produce.use_pt_boost = data['use_pt_boost']
1178
- config.produce.use_note_boost = data['use_note_boost']
1179
- config.produce.follow_producer = data['follow_producer']
1180
- config.produce.self_study_lesson = data['self_study_lesson']
1181
- config.produce.prefer_lesson_ap = data['prefer_lesson_ap']
1182
- config.produce.actions_order = [ProduceAction(action) for action in data['actions_order']]
1183
- config.produce.recommend_card_detection_mode = RecommendCardDetectionMode(data['recommend_card_detection_mode'])
1184
- config.produce.use_ap_drink = data['use_ap_drink']
1185
- config.produce.skip_commu = data['skip_commu']
1186
-
1187
- return set_config, {
1188
- 'produce_enabled': produce_enabled,
1189
- 'produce_mode': produce_mode,
1190
- 'produce_count': produce_count,
1191
- 'produce_idols': produce_idols,
1192
- 'memory_sets': memory_sets,
1193
- 'auto_set_memory': auto_set_memory,
1194
- 'auto_set_support': auto_set_support,
1195
- 'use_pt_boost': use_pt_boost,
1196
- 'use_note_boost': use_note_boost,
1197
- 'follow_producer': follow_producer,
1198
- 'self_study_lesson': self_study_lesson,
1199
- 'prefer_lesson_ap': prefer_lesson_ap,
1200
- 'actions_order': actions_order,
1201
- 'recommend_card_detection_mode': recommend_card_detection_mode,
1202
- 'use_ap_drink': use_ap_drink,
1203
- 'skip_commu': skip_commu
1204
- }
1205
1827
 
1206
1828
  def _create_club_reward_settings(self) -> ConfigBuilderReturnValue:
1207
1829
  with gr.Column():
@@ -1897,7 +2519,20 @@ class KotoneBotUI:
1897
2519
  self.current_config = self.config.user_configs[0]
1898
2520
 
1899
2521
  def create_ui(self) -> gr.Blocks:
1900
- 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:
1901
2536
  with gr.Column(elem_id="container"):
1902
2537
  gr.Markdown(f"# 琴音小助手 v{self._kaa.version}")
1903
2538
 
@@ -1905,6 +2540,7 @@ class KotoneBotUI:
1905
2540
  self._create_status_tab()
1906
2541
  self._create_task_tab()
1907
2542
  self._create_settings_tab()
2543
+ self._create_produce_tab()
1908
2544
  self._create_log_tab()
1909
2545
  self._create_whats_new_tab()
1910
2546
  self._create_screen_tab()