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
@@ -0,0 +1,126 @@
1
+ """v2 → v3 迁移脚本
2
+
3
+ 引入游戏解包数据后,`produce.idols` 不再使用 `PIdol` 枚举,而是直接使用
4
+ 游戏内的 idol skin id (字符串)。这里负责完成枚举到字符串的转换。
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import logging
10
+ from typing import Any
11
+
12
+ from ._idol import PIdol
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ # 枚举 → skin_id 映射表(复制自旧实现)。
18
+ _PIDOL_TO_SKIN: dict[PIdol, str] = {
19
+ PIdol.倉本千奈_Campusmode: "i_card-skin-kcna-3-007",
20
+ PIdol.倉本千奈_WonderScale: "i_card-skin-kcna-3-000",
21
+ PIdol.倉本千奈_ようこそ初星温泉: "i_card-skin-kcna-3-005",
22
+ PIdol.倉本千奈_仮装狂騒曲: "i_card-skin-kcna-3-002",
23
+ PIdol.倉本千奈_初心: "i_card-skin-kcna-1-001",
24
+ PIdol.倉本千奈_学園生活: "i_card-skin-kcna-1-000",
25
+ PIdol.倉本千奈_日々_発見的ステップ: "i_card-skin-kcna-3-001",
26
+ PIdol.倉本千奈_胸を張って一歩ずつ: "i_card-skin-kcna-2-000",
27
+ PIdol.十王星南_Campusmode: "i_card-skin-jsna-3-002",
28
+ PIdol.十王星南_一番星: "i_card-skin-jsna-2-000",
29
+ PIdol.十王星南_学園生活: "i_card-skin-jsna-1-000",
30
+ PIdol.十王星南_小さな野望: "i_card-skin-jsna-3-000",
31
+ PIdol.姫崎莉波_clumsytrick: "i_card-skin-hrnm-3-000",
32
+ PIdol.姫崎莉波_私らしさのはじまり: "i_card-skin-hrnm-2-000",
33
+ PIdol.姫崎莉波_キミとセミブルー: "i_card-skin-hrnm-3-001",
34
+ PIdol.姫崎莉波_Campusmode: "i_card-skin-hrnm-3-007",
35
+ PIdol.姫崎莉波_LUV: "i_card-skin-hrnm-3-002",
36
+ PIdol.姫崎莉波_ようこそ初星温泉: "i_card-skin-hrnm-3-004",
37
+ PIdol.姫崎莉波_ハッピーミルフィーユ: "i_card-skin-hrnm-3-008",
38
+ PIdol.姫崎莉波_初心: "i_card-skin-hrnm-1-001",
39
+ PIdol.姫崎莉波_学園生活: "i_card-skin-hrnm-1-000",
40
+ PIdol.月村手毬_Lunasaymaybe: "i_card-skin-ttmr-3-000",
41
+ PIdol.月村手毬_一匹狼: "i_card-skin-ttmr-2-000",
42
+ PIdol.月村手毬_Campusmode: "i_card-skin-ttmr-3-007",
43
+ PIdol.月村手毬_アイヴイ: "i_card-skin-ttmr-3-001",
44
+ PIdol.月村手毬_初声: "i_card-skin-ttmr-1-001",
45
+ PIdol.月村手毬_学園生活: "i_card-skin-ttmr-1-000",
46
+ PIdol.月村手毬_仮装狂騒曲: "i_card-skin-ttmr-3-002",
47
+ PIdol.有村麻央_Fluorite: "i_card-skin-amao-3-000",
48
+ PIdol.有村麻央_はじまりはカッコよく: "i_card-skin-amao-2-000",
49
+ PIdol.有村麻央_Campusmode: "i_card-skin-amao-3-007",
50
+ PIdol.有村麻央_FeelJewelDream: "i_card-skin-amao-3-002",
51
+ PIdol.有村麻央_キミとセミブルー: "i_card-skin-amao-3-001",
52
+ PIdol.有村麻央_初恋: "i_card-skin-amao-1-001",
53
+ PIdol.有村麻央_学園生活: "i_card-skin-amao-1-000",
54
+ PIdol.篠泽广_コントラスト: "i_card-skin-shro-3-001",
55
+ PIdol.篠泽广_一番向いていないこと: "i_card-skin-shro-2-000",
56
+ PIdol.篠泽广_光景: "i_card-skin-shro-3-000",
57
+ PIdol.篠泽广_Campusmode: "i_card-skin-shro-3-007",
58
+ PIdol.篠泽广_仮装狂騒曲: "i_card-skin-shro-3-002",
59
+ PIdol.篠泽广_ハッピーミルフィーユ: "i_card-skin-shro-3-008",
60
+ PIdol.篠泽广_初恋: "i_card-skin-shro-1-001",
61
+ PIdol.篠泽广_学園生活: "i_card-skin-shro-1-000",
62
+ PIdol.紫云清夏_TameLieOneStep: "i_card-skin-ssmk-3-000",
63
+ PIdol.紫云清夏_カクシタワタシ: "i_card-skin-ssmk-3-002",
64
+ PIdol.紫云清夏_夢へのリスタート: "i_card-skin-ssmk-2-000",
65
+ PIdol.紫云清夏_Campusmode: "i_card-skin-ssmk-3-007",
66
+ PIdol.紫云清夏_キミとセミブルー: "i_card-skin-ssmk-3-001",
67
+ PIdol.紫云清夏_初恋: "i_card-skin-ssmk-1-001",
68
+ PIdol.紫云清夏_学園生活: "i_card-skin-ssmk-1-000",
69
+ PIdol.花海佑芽_WhiteNightWhiteWish: "i_card-skin-hume-3-005",
70
+ PIdol.花海佑芽_学園生活: "i_card-skin-hume-1-000",
71
+ PIdol.花海佑芽_Campusmode: "i_card-skin-hume-3-006",
72
+ PIdol.花海佑芽_TheRollingRiceball: "i_card-skin-hume-3-000",
73
+ PIdol.花海佑芽_アイドル_はじめっ: "i_card-skin-hume-2-000",
74
+ PIdol.花海咲季_BoomBoomPow: "i_card-skin-hski-3-001",
75
+ PIdol.花海咲季_Campusmode: "i_card-skin-hski-3-008",
76
+ PIdol.花海咲季_FightingMyWay: "i_card-skin-hski-3-000",
77
+ PIdol.花海咲季_わたしが一番: "i_card-skin-hski-2-000",
78
+ PIdol.花海咲季_冠菊: "i_card-skin-hski-3-001",
79
+ PIdol.花海咲季_初声: "i_card-skin-hski-1-001",
80
+ PIdol.花海咲季_古今東西ちょちょいのちょい: "i_card-skin-hski-3-006",
81
+ PIdol.花海咲季_学園生活: "i_card-skin-hski-1-000",
82
+ PIdol.葛城リーリヤ_一つ踏み出した先に: "i_card-skin-kllj-2-000",
83
+ PIdol.葛城リーリヤ_白線: "i_card-skin-kllj-3-000",
84
+ PIdol.葛城リーリヤ_Campusmode: "i_card-skin-kllj-3-006",
85
+ PIdol.葛城リーリヤ_WhiteNightWhiteWish: "i_card-skin-kllj-3-005",
86
+ PIdol.葛城リーリヤ_冠菊: "i_card-skin-kllj-3-001",
87
+ PIdol.葛城リーリヤ_初心: "i_card-skin-kllj-1-001",
88
+ PIdol.葛城リーリヤ_学園生活: "i_card-skin-kllj-1-000",
89
+ PIdol.藤田ことね_カワイイ_はじめました: "i_card-skin-fktn-2-000",
90
+ PIdol.藤田ことね_世界一可愛い私: "i_card-skin-fktn-3-000",
91
+ PIdol.藤田ことね_Campusmode: "i_card-skin-fktn-3-007",
92
+ PIdol.藤田ことね_YellowBigBang: "i_card-skin-fktn-3-001",
93
+ PIdol.藤田ことね_WhiteNightWhiteWish: "i_card-skin-fktn-3-006",
94
+ PIdol.藤田ことね_冠菊: "i_card-skin-fktn-3-002",
95
+ PIdol.藤田ことね_初声: "i_card-skin-fktn-1-001",
96
+ PIdol.藤田ことね_学園生活: "i_card-skin-fktn-1-000",
97
+ }
98
+
99
+
100
+ def migrate(user_config: dict[str, Any]) -> str | None: # noqa: D401
101
+ """执行 v2→v3 迁移。"""
102
+ options = user_config.get("options")
103
+ if options is None:
104
+ logger.debug("No 'options' in user_config, skip v2→v3 migration.")
105
+ return None
106
+
107
+ produce_conf = options.get("produce", {})
108
+ old_idols = produce_conf.get("idols", [])
109
+ msg = ""
110
+
111
+ new_idols: list[str] = []
112
+ for idol in old_idols:
113
+ if isinstance(idol, int): # 原本已是 int(PIdol)
114
+ try:
115
+ skin = _PIDOL_TO_SKIN[PIdol(idol)]
116
+ new_idols.append(skin)
117
+ except (ValueError, KeyError):
118
+ msg += f"未知 PIdol: {idol}\n"
119
+ else:
120
+ msg += f"旧 idol 数据格式异常: {idol}\n"
121
+
122
+ produce_conf["idols"] = new_idols
123
+ options["produce"] = produce_conf
124
+ user_config["options"] = options
125
+
126
+ return msg or None
@@ -0,0 +1,29 @@
1
+ """v3 -> v4 迁移脚本
2
+
3
+ 修正游戏包名错误。
4
+ """
5
+ from __future__ import annotations
6
+
7
+ import logging
8
+ from typing import Any
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ def migrate(user_config: dict[str, Any]) -> str | None: # noqa: D401
14
+ """执行 v3→v4 迁移:修正错误的游戏包名。"""
15
+ options = user_config.get("options")
16
+ if options is None:
17
+ logger.debug("No 'options' in user_config, skip v3→v4 migration.")
18
+ return None
19
+
20
+ start_conf = options.get("start_game", {})
21
+ old_pkg = start_conf.get("game_package_name")
22
+ if old_pkg == "com.bandinamcoent.idolmaster_gakuen":
23
+ start_conf["game_package_name"] = "com.bandainamcoent.idolmaster_gakuen"
24
+ logger.info("Corrected game package name to com.bandainamcoent.idolmaster_gakuen")
25
+
26
+ options["start_game"] = start_conf
27
+ user_config["options"] = options
28
+
29
+ return None
@@ -0,0 +1,26 @@
1
+ """v4 -> v5 迁移脚本
2
+
3
+ 为 Windows 截图方式的配置统一设置 backend.type = 'dmm'。
4
+ """
5
+ from __future__ import annotations
6
+
7
+ import logging
8
+ from typing import Any
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ def migrate(user_config: dict[str, Any]) -> str | None: # noqa: D401
14
+ """执行 v4→v5 迁移:
15
+
16
+ 当截图方式为 windows / remote_windows 时,将 backend.type 统一设置为 'dmm'。
17
+ """
18
+ backend = user_config.get("backend", {})
19
+ impl = backend.get("screenshot_impl")
20
+ if impl in {"windows", "remote_windows"}:
21
+ logger.info("Set backend type to dmm for screenshot_impl=%s", impl)
22
+ backend["type"] = "dmm"
23
+ user_config["backend"] = backend
24
+
25
+ # v4→v5 无 options 结构更改,直接返回
26
+ return None
@@ -0,0 +1,134 @@
1
+ """v5 -> v6 迁移脚本
2
+
3
+ 重构培育配置:将原有的 ProduceConfig 中的培育参数迁移到新的 ProduceSolution 结构中。
4
+ """
5
+ from __future__ import annotations
6
+
7
+ import logging
8
+ import os
9
+ import json
10
+ import uuid
11
+ import re
12
+ from typing import Any
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ def _sanitize_filename(name: str) -> str:
18
+ """
19
+ 清理文件名中的非法字符
20
+
21
+ :param name: 原始名称
22
+ :return: 清理后的文件名
23
+ """
24
+ # 替换 \/:*?"<>| 为下划线
25
+ return re.sub(r'[\\/:*?"<>|]', '_', name)
26
+
27
+
28
+ def _create_default_solution(old_produce_config: dict[str, Any]) -> tuple[dict[str, Any], str]:
29
+ """
30
+ 根据旧的培育配置创建默认的培育方案
31
+
32
+ :param old_produce_config: 旧的培育配置
33
+ :return: (新的培育方案数据, 方案ID)
34
+ """
35
+ # 生成唯一ID
36
+ solution_id = uuid.uuid4().hex
37
+
38
+ # 构建培育数据
39
+ produce_data = {
40
+ "mode": old_produce_config.get("mode", "regular"),
41
+ "idol": old_produce_config.get("idols", [None])[0] if old_produce_config.get("idols") else None,
42
+ "memory_set": old_produce_config.get("memory_sets", [None])[0] if old_produce_config.get("memory_sets") else None,
43
+ "support_card_set": old_produce_config.get("support_card_sets", [None])[0] if old_produce_config.get("support_card_sets") else None,
44
+ "auto_set_memory": old_produce_config.get("auto_set_memory", False),
45
+ "auto_set_support_card": old_produce_config.get("auto_set_support_card", False),
46
+ "use_pt_boost": old_produce_config.get("use_pt_boost", False),
47
+ "use_note_boost": old_produce_config.get("use_note_boost", False),
48
+ "follow_producer": old_produce_config.get("follow_producer", False),
49
+ "self_study_lesson": old_produce_config.get("self_study_lesson", "dance"),
50
+ "prefer_lesson_ap": old_produce_config.get("prefer_lesson_ap", False),
51
+ "actions_order": old_produce_config.get("actions_order", [
52
+ "recommended", "visual", "vocal", "dance",
53
+ "allowance", "outing", "study", "consult", "rest"
54
+ ]),
55
+ "recommend_card_detection_mode": old_produce_config.get("recommend_card_detection_mode", "normal"),
56
+ "use_ap_drink": old_produce_config.get("use_ap_drink", False),
57
+ "skip_commu": old_produce_config.get("skip_commu", True)
58
+ }
59
+
60
+ # 构建方案对象
61
+ solution = {
62
+ "type": "produce_solution",
63
+ "id": solution_id,
64
+ "name": "默认方案",
65
+ "description": "从旧配置迁移的默认培育方案",
66
+ "data": produce_data
67
+ }
68
+
69
+ return solution, solution_id
70
+
71
+
72
+ def _save_solution_to_file(solution: dict[str, Any]) -> None:
73
+ """
74
+ 将培育方案保存到文件
75
+
76
+ :param solution: 培育方案数据
77
+ """
78
+ solutions_dir = "conf/produce"
79
+ os.makedirs(solutions_dir, exist_ok=True)
80
+
81
+ safe_name = _sanitize_filename(solution["name"])
82
+ file_path = os.path.join(solutions_dir, f"{safe_name}.json")
83
+
84
+ with open(file_path, 'w', encoding='utf-8') as f:
85
+ json.dump(solution, f, ensure_ascii=False, indent=4)
86
+
87
+
88
+ def migrate(user_config: dict[str, Any]) -> str | None: # noqa: D401
89
+ """执行 v5→v6 迁移:重构培育配置结构。
90
+
91
+ 将原有的 ProduceConfig 中的培育参数迁移到新的 ProduceSolution 结构中。
92
+ """
93
+ options = user_config.get("options")
94
+ if options is None:
95
+ logger.debug("No 'options' in user_config, skip v5→v6 migration.")
96
+ return None
97
+
98
+ produce_conf = options.get("produce", {})
99
+ if not produce_conf:
100
+ logger.debug("No 'produce' config found, skip v5→v6 migration.")
101
+ return None
102
+
103
+ # 检查是否已经是新格式(有 selected_solution_id 字段)
104
+ if "selected_solution_id" in produce_conf:
105
+ logger.debug("Produce config already in v6 format, skip migration.")
106
+ return None
107
+
108
+ msg = ""
109
+
110
+ try:
111
+ # 创建默认培育方案
112
+ solution, solution_id = _create_default_solution(produce_conf)
113
+
114
+ # 保存方案到文件
115
+ _save_solution_to_file(solution)
116
+
117
+ # 更新配置为新格式
118
+ new_produce_conf = {
119
+ "enabled": produce_conf.get("enabled", False),
120
+ "selected_solution_id": solution_id,
121
+ "produce_count": produce_conf.get("produce_count", 1)
122
+ }
123
+
124
+ options["produce"] = new_produce_conf
125
+ user_config["options"] = options
126
+
127
+ msg = f"已将培育配置迁移到新的方案系统。默认方案已创建并保存为 '{solution['name']}'。"
128
+ logger.info("Successfully migrated produce config to v6 format with solution ID: %s", solution_id)
129
+
130
+ except Exception as e:
131
+ logger.error("Failed to migrate produce config: %s", e)
132
+ msg = f"培育配置迁移失败:{e}"
133
+
134
+ return msg or None
@@ -0,0 +1,255 @@
1
+ import os
2
+ import json
3
+ import uuid
4
+ import re
5
+ import logging
6
+ from typing import Literal
7
+ from pydantic import BaseModel, ConfigDict, field_serializer, field_validator
8
+
9
+ from .const import ProduceAction, RecommendCardDetectionMode
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ class ConfigBaseModel(BaseModel):
14
+ model_config = ConfigDict(use_attribute_docstrings=True)
15
+
16
+
17
+ class ProduceData(ConfigBaseModel):
18
+ mode: Literal['regular', 'pro', 'master'] = 'regular'
19
+ """
20
+ 培育模式。
21
+ 进行一次 REGULAR 培育需要 ~30min,进行一次 PRO 培育需要 ~1h(具体视设备性能而定)。
22
+ """
23
+ idol: str | None = None
24
+ """
25
+ 要培育偶像的 IdolCardSkin.id。
26
+ """
27
+ memory_set: int | None = None
28
+ """要使用的回忆编成编号,从 1 开始。"""
29
+ support_card_set: int | None = None
30
+ """要使用的支援卡编成编号,从 1 开始。"""
31
+ auto_set_memory: bool = False
32
+ """是否自动编成回忆。此选项优先级高于回忆编成编号。"""
33
+ auto_set_support_card: bool = False
34
+ """是否自动编成支援卡。此选项优先级高于支援卡编成编号。"""
35
+ use_pt_boost: bool = False
36
+ """是否使用支援强化 Pt 提升。"""
37
+ use_note_boost: bool = False
38
+ """是否使用笔记数提升。"""
39
+ follow_producer: bool = False
40
+ """是否关注租借了支援卡的制作人。"""
41
+ self_study_lesson: Literal['dance', 'visual', 'vocal'] = 'dance'
42
+ """自习课类型。"""
43
+ prefer_lesson_ap: bool = False
44
+ """
45
+ 优先 SP 课程。
46
+
47
+ 启用后,若出现 SP 课程,则会优先执行 SP 课程,而不是推荐课程。
48
+ 若出现多个 SP 课程,随机选择一个。
49
+ """
50
+ actions_order: list[ProduceAction] = [
51
+ ProduceAction.RECOMMENDED,
52
+ ProduceAction.VISUAL,
53
+ ProduceAction.VOCAL,
54
+ ProduceAction.DANCE,
55
+ ProduceAction.ALLOWANCE,
56
+ ProduceAction.OUTING,
57
+ ProduceAction.STUDY,
58
+ ProduceAction.CONSULT,
59
+ ProduceAction.REST,
60
+ ]
61
+ """
62
+ 行动优先级
63
+
64
+ 每一周的行动将会按这里设置的优先级执行。
65
+ """
66
+ recommend_card_detection_mode: RecommendCardDetectionMode = RecommendCardDetectionMode.NORMAL
67
+ """
68
+ 推荐卡检测模式
69
+
70
+ 严格模式下,识别速度会降低,但识别准确率会提高。
71
+ """
72
+ use_ap_drink: bool = False
73
+ """
74
+ AP 不足时自动使用 AP 饮料
75
+ """
76
+ skip_commu: bool = True
77
+ """检测并跳过交流"""
78
+
79
+ class ProduceSolution(ConfigBaseModel):
80
+ """培育方案"""
81
+ type: Literal['produce_solution'] = 'produce_solution'
82
+ """方案类型标识"""
83
+ id: str
84
+ """方案唯一标识符"""
85
+ name: str
86
+ """方案名称"""
87
+ description: str | None = None
88
+ """方案描述"""
89
+ data: ProduceData
90
+ """培育数据"""
91
+
92
+
93
+ class ProduceSolutionManager:
94
+ """培育方案管理器"""
95
+
96
+ SOLUTIONS_DIR = "conf/produce"
97
+
98
+ def __init__(self):
99
+ """初始化管理器,确保目录存在"""
100
+ os.makedirs(self.SOLUTIONS_DIR, exist_ok=True)
101
+
102
+ def _sanitize_filename(self, name: str) -> str:
103
+ """
104
+ 清理文件名中的非法字符
105
+
106
+ :param name: 原始名称
107
+ :return: 清理后的文件名
108
+ """
109
+ # 替换 \/:*?"<>| 为下划线
110
+ return re.sub(r'[\\/:*?"<>|]', '_', name)
111
+
112
+ def _get_file_path(self, name: str) -> str:
113
+ """
114
+ 根据方案名称获取文件路径
115
+
116
+ :param name: 方案名称
117
+ :return: 文件路径
118
+ """
119
+ safe_name = self._sanitize_filename(name)
120
+ return os.path.join(self.SOLUTIONS_DIR, f"{safe_name}.json")
121
+
122
+ def _find_file_path_by_id(self, id: str) -> str | None:
123
+ """
124
+ 根据方案ID查找文件路径
125
+
126
+ :param id: 方案ID
127
+ :return: 文件路径,如果未找到则返回 None
128
+ """
129
+ if not os.path.exists(self.SOLUTIONS_DIR):
130
+ return None
131
+
132
+ for filename in os.listdir(self.SOLUTIONS_DIR):
133
+ if filename.endswith('.json'):
134
+ try:
135
+ file_path = os.path.join(self.SOLUTIONS_DIR, filename)
136
+ with open(file_path, 'r', encoding='utf-8') as f:
137
+ data = json.load(f)
138
+ if data.get('id') == id:
139
+ return file_path
140
+ except Exception:
141
+ continue
142
+ return None
143
+
144
+ def new(self, name: str) -> ProduceSolution:
145
+ """
146
+ 创建新的培育方案
147
+
148
+ :param name: 方案名称
149
+ :return: 新创建的方案
150
+ """
151
+ solution = ProduceSolution(
152
+ id=uuid.uuid4().hex,
153
+ name=name,
154
+ data=ProduceData()
155
+ )
156
+ return solution
157
+
158
+ def list(self) -> list[ProduceSolution]:
159
+ """
160
+ 列出所有培育方案
161
+
162
+ :return: 方案列表
163
+ """
164
+ solutions = []
165
+ if not os.path.exists(self.SOLUTIONS_DIR):
166
+ return solutions
167
+
168
+ for filename in os.listdir(self.SOLUTIONS_DIR):
169
+ if filename.endswith('.json'):
170
+ try:
171
+ file_path = os.path.join(self.SOLUTIONS_DIR, filename)
172
+ with open(file_path, 'r', encoding='utf-8') as f:
173
+ solution = ProduceSolution.model_validate_json(f.read())
174
+ solutions.append(solution)
175
+ logger.info(f"Loaded produce solution from {file_path}")
176
+ except Exception:
177
+ logger.warning(f"Failed to load produce solution from {file_path}")
178
+ continue
179
+
180
+ return solutions
181
+
182
+ def delete(self, id: str) -> None:
183
+ """
184
+ 删除指定ID的培育方案
185
+
186
+ :param id: 方案ID
187
+ """
188
+ file_path = self._find_file_path_by_id(id)
189
+ if file_path:
190
+ os.remove(file_path)
191
+
192
+ def save(self, id: str, solution: ProduceSolution) -> None:
193
+ """
194
+ 保存培育方案
195
+
196
+ :param id: 方案ID
197
+ :param solution: 方案对象
198
+ """
199
+ # 确保ID一致
200
+ solution.id = id
201
+
202
+ # 先删除具有相同ID的旧文件(如果存在),避免名称变更时产生重复文件
203
+ old_file_path = self._find_file_path_by_id(id)
204
+ if old_file_path:
205
+ os.remove(old_file_path)
206
+
207
+ # 保存新文件
208
+ file_path = self._get_file_path(solution.name)
209
+ with open(file_path, 'w', encoding='utf-8') as f:
210
+ # 使用 model_dump 并指定 mode='json' 来正确序列化枚举
211
+ data = solution.model_dump(mode='json')
212
+ json.dump(data, f, ensure_ascii=False, indent=4)
213
+
214
+ def read(self, id: str) -> ProduceSolution:
215
+ """
216
+ 读取指定ID的培育方案
217
+
218
+ :param id: 方案ID
219
+ :return: 方案对象
220
+ :raises FileNotFoundError: 当方案不存在时
221
+ """
222
+ file_path = self._find_file_path_by_id(id)
223
+ if not file_path:
224
+ raise FileNotFoundError(f"Solution with id '{id}' not found")
225
+
226
+ try:
227
+ with open(file_path, 'r', encoding='utf-8') as f:
228
+ return ProduceSolution.model_validate_json(f.read())
229
+ except Exception as e:
230
+ raise FileNotFoundError(f"Failed to read solution with id '{id}': {e}")
231
+
232
+ def duplicate(self, id: str) -> ProduceSolution:
233
+ """
234
+ 复制指定ID的培育方案
235
+
236
+ :param id: 要复制的方案ID
237
+ :return: 新的方案对象(具有新的ID和名称)
238
+ :raises FileNotFoundError: 当原方案不存在时
239
+ """
240
+ original = self.read(id)
241
+
242
+ # 生成新的ID和名称
243
+ new_id = uuid.uuid4().hex
244
+ new_name = f"{original.name} - 副本"
245
+
246
+ # 创建新的方案对象
247
+ new_solution = ProduceSolution(
248
+ type=original.type,
249
+ id=new_id,
250
+ name=new_name,
251
+ description=original.description,
252
+ data=original.data.model_copy() # 深拷贝数据
253
+ )
254
+
255
+ return new_solution