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.
- kotonebot/backend/bot.py +13 -2
- kotonebot/backend/context/context.py +42 -9
- kotonebot/config/base_config.py +2 -0
- kotonebot/kaa/common.py +2 -968
- kotonebot/kaa/config/__init__.py +62 -0
- kotonebot/kaa/config/const.py +255 -0
- kotonebot/kaa/config/migrations/__init__.py +28 -0
- kotonebot/kaa/config/migrations/_idol.py +106 -0
- kotonebot/kaa/config/migrations/_v1_to_v2.py +203 -0
- kotonebot/kaa/config/migrations/_v2_to_v3.py +126 -0
- kotonebot/kaa/config/migrations/_v3_to_v4.py +29 -0
- kotonebot/kaa/config/migrations/_v4_to_v5.py +26 -0
- kotonebot/kaa/config/migrations/_v5_to_v6.py +134 -0
- kotonebot/kaa/config/produce.py +255 -0
- kotonebot/kaa/config/schema.py +236 -0
- kotonebot/kaa/config/upgrade.py +63 -0
- kotonebot/kaa/game_ui/commu_event_buttons.py +3 -0
- kotonebot/kaa/game_ui/schedule.py +1 -1
- kotonebot/kaa/main/gr.py +841 -176
- kotonebot/kaa/main/kaa.py +39 -12
- kotonebot/kaa/metadata.py +49 -0
- kotonebot/kaa/resources/__pycache__/__init__.cpython-310.pyc +0 -0
- kotonebot/kaa/resources/game.db +0 -0
- kotonebot/kaa/resources/game_ver.txt +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-hmsz-3-001_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-hmsz-3-001_1.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-jsna-3-007_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-jsna-3-007_1.png +0 -0
- kotonebot/kaa/sprites/0d9ac648-eefa-4869-ac99-1b0c83649681.png +0 -0
- kotonebot/kaa/sprites/185f7838-92a7-460b-9340-f60858948ce9.png +0 -0
- kotonebot/kaa/sprites/213016c2-c3a2-43d8-86a3-ab4d27666ced.png +0 -0
- kotonebot/kaa/sprites/24dc7158-036c-4a66-9280-e934f470be53.png +0 -0
- kotonebot/kaa/sprites/3942ae40-7f22-412c-aebe-4b064f68db9b.png +0 -0
- kotonebot/kaa/sprites/5031808b-5525-4118-92b4-317ec8bda985.png +0 -0
- kotonebot/kaa/sprites/5d36b880-7b3f-49b1-a018-7de59867d376.png +0 -0
- kotonebot/kaa/sprites/81c97cd3-df53-44d3-bf3d-1eb4dc67b62a.png +0 -0
- kotonebot/kaa/sprites/8f8b7b46-53bb-42ab-907a-4ea87eb09ab4.png +0 -0
- kotonebot/kaa/sprites/921eefeb-730e-46fc-9924-d338fb286592.png +0 -0
- kotonebot/kaa/sprites/ae9fe233-9acc-4e96-ba8e-1fb1d9bc2ea5.png +0 -0
- kotonebot/kaa/sprites/cb3d0ca7-8d14-408a-a2f5-2e25f7b86d6c.png +0 -0
- kotonebot/kaa/sprites/cc60b509-2ed5-493d-bb9f-333c6d2a6006.png +0 -0
- kotonebot/kaa/tasks/R.py +143 -151
- kotonebot/kaa/tasks/daily/acquire_activity_funds.py +13 -11
- kotonebot/kaa/tasks/daily/acquire_presents.py +1 -1
- kotonebot/kaa/tasks/daily/assignment.py +1 -1
- kotonebot/kaa/tasks/daily/capsule_toys.py +1 -1
- kotonebot/kaa/tasks/daily/club_reward.py +1 -1
- kotonebot/kaa/tasks/daily/contest.py +1 -1
- kotonebot/kaa/tasks/daily/mission_reward.py +1 -1
- kotonebot/kaa/tasks/daily/purchase.py +53 -29
- kotonebot/kaa/tasks/daily/upgrade_support_card.py +1 -1
- kotonebot/kaa/tasks/end_game.py +1 -1
- kotonebot/kaa/tasks/produce/cards.py +1 -1
- kotonebot/kaa/tasks/produce/common.py +3 -2
- kotonebot/kaa/tasks/produce/in_purodyuusu.py +9 -7
- kotonebot/kaa/tasks/produce/non_lesson_actions.py +3 -2
- kotonebot/kaa/tasks/produce/produce.py +27 -22
- kotonebot/kaa/tasks/start_game.py +1 -1
- {ksaa-2025.7.5.0.dist-info → ksaa-2025.7.9.0.dist-info}/METADATA +1 -1
- {ksaa-2025.7.5.0.dist-info → ksaa-2025.7.9.0.dist-info}/RECORD +190 -176
- kotonebot/kaa/sprites/135ee57a-d30d-4ba8-83f0-9f1681a49ff7.png +0 -0
- kotonebot/kaa/sprites/18a02cbe-5d07-487c-866b-62b9609ee02f.png +0 -0
- kotonebot/kaa/sprites/1c53ee9f-9dda-43bb-b788-de675c7ebfbe.png +0 -0
- kotonebot/kaa/sprites/278b7d9c-707e-4392-9677-74574b5cdf42.png +0 -0
- kotonebot/kaa/sprites/2bc00520-0afe-40e5-8743-d33fc6b2945a.png +0 -0
- kotonebot/kaa/sprites/3a234f56-2287-4ced-8093-253ece372af2.png +0 -0
- kotonebot/kaa/sprites/6720b6e8-ae80-4cc0-a885-518efe12b707.png +0 -0
- kotonebot/kaa/sprites/68f109c1-297e-4aa8-b472-372f1d689b33.png +0 -0
- kotonebot/kaa/sprites/74ff07b3-d91c-4579-80cd-379ed7020622.png +0 -0
- kotonebot/kaa/sprites/7669d1f5-d778-4694-87ae-9bb08e7f1265.png +0 -0
- kotonebot/kaa/sprites/868b97a9-492e-4712-b47f-82b97495b019.png +0 -0
- kotonebot/kaa/sprites/9d21d43f-4bf9-4081-951f-d208e0273e1f.png +0 -0
- kotonebot/kaa/sprites/a7f5abf1-982f-4a55-8d41-3ad6f56798e0.png +0 -0
- kotonebot/kaa/sprites/afa06fdc-a345-4384-b25d-b16540830256.png +0 -0
- kotonebot/kaa/sprites/d15959bf-d07b-4f07-948a-c0aeaf17756a.png +0 -0
- /kotonebot/kaa/sprites/{e6f0ca18-546c-4463-96b6-5866fe4d1ff2.png → 02cf0df9-37d6-4387-b8eb-c92589264c2a.png} +0 -0
- /kotonebot/kaa/sprites/{d8caa8b8-6f45-4bcc-89c6-4d4522db14c0.png → 02d4e179-912e-4e1f-ba7d-ea37fe87279e.png} +0 -0
- /kotonebot/kaa/sprites/{ffacd169-0e30-4e43-a4dc-46dd85711ba7.png → 037cb117-8521-4670-b3ec-ee0e260c1d62.png} +0 -0
- /kotonebot/kaa/sprites/{de87abe3-482a-4fc0-ace2-bc436036ddf5.png → 04be14b5-4169-4b3e-ab14-224db52c9a39.png} +0 -0
- /kotonebot/kaa/sprites/{9aabd1cd-fa2f-4b4d-9ca0-5cd0a02cdeeb.png → 06bb9a6e-1dbe-48db-91d7-51d9fc3ffcce.png} +0 -0
- /kotonebot/kaa/sprites/{6f72ab34-1c37-42d8-81c0-d0e0e573fc80.png → 08444afd-90d4-43ac-b3ee-128a5bdef4a2.png} +0 -0
- /kotonebot/kaa/sprites/{2ad5f996-e825-4c91-bf84-b3a139d7f1e9.png → 0910c5f3-7f72-4385-967c-4bf226c9861b.png} +0 -0
- /kotonebot/kaa/sprites/{bdd7e868-0cb2-4da2-9055-6cf9eae5869b.png → 0b332c2c-aa57-4f10-aa55-8e981f2e7c27.png} +0 -0
- /kotonebot/kaa/sprites/{46800ab2-388f-4945-941a-3e18607c9676.png → 0c4ee900-3e44-4e37-a199-32d66daa2025.png} +0 -0
- /kotonebot/kaa/sprites/{10e06d0b-9cef-489c-8468-adad39067d8a.png → 0cfd52cc-1f38-4804-bc1f-8da9cc51d969.png} +0 -0
- /kotonebot/kaa/sprites/{78c1bd53-771f-4809-bbda-39f8dd6395c1.png → 131d5c1b-70b3-47d3-b6d6-318045629037.png} +0 -0
- /kotonebot/kaa/sprites/{80feee6f-d7dd-499c-bd91-cc1e191dd945.png → 133dbdd9-23fa-4157-9f9e-fd1728207bd0.png} +0 -0
- /kotonebot/kaa/sprites/{b64f8cc6-4ef9-4f43-95e6-d508364faff1.png → 17d2730b-e56e-4956-973d-5f822490a2c5.png} +0 -0
- /kotonebot/kaa/sprites/{482b5f67-1680-4a93-8bb2-2a357dfd8d8d.png → 231b3e86-cfc5-4e08-803b-63ed680ab1ad.png} +0 -0
- /kotonebot/kaa/sprites/{2a08cc2b-5cba-4771-a351-94121c52308c.png → 2569011c-3bad-416c-b358-ceaf313507e8.png} +0 -0
- /kotonebot/kaa/sprites/{6be7624f-c0ac-4605-b8ba-56f8b07d7de0.png → 26dd326a-a6da-4350-8140-217e9d6a6109.png} +0 -0
- /kotonebot/kaa/sprites/{3305dc0c-d721-4e82-a5f8-4b8d96eea228.png → 29119167-eb9c-4c35-9c63-9c9967f85163.png} +0 -0
- /kotonebot/kaa/sprites/{cae49b6a-cc4e-49d9-9dd6-d528510bd262.png → 2b8385d8-ea7e-4675-9d16-57b905a18d90.png} +0 -0
- /kotonebot/kaa/sprites/{9fb5da56-41a8-4a83-8ae8-338a124ecd03.png → 2cd2047f-91af-4632-8cb2-eb2fc4b4c808.png} +0 -0
- /kotonebot/kaa/sprites/{bd408633-6ca9-4cb0-9b11-695616496b48.png → 314bc3ab-8c73-4517-ae7c-75d21ac61448.png} +0 -0
- /kotonebot/kaa/sprites/{d09a9154-0280-40f9-9802-2d2fa01c03df.png → 33e4e6c9-d245-4174-8303-04019ce20136.png} +0 -0
- /kotonebot/kaa/sprites/{c4cc6dcd-6301-4d02-942e-8e49475ec3e9.png → 34cce4b7-53fe-4ea2-82d8-d31fe7b9abcd.png} +0 -0
- /kotonebot/kaa/sprites/{2cf84d6e-5212-4da5-8a01-cfdab00a8d1b.png → 3820d53e-5b87-4a35-9472-e90498225853.png} +0 -0
- /kotonebot/kaa/sprites/{d25bd995-1139-4909-84e2-85260a27d46f.png → 38e35291-2a94-4261-9b58-80d7b17165c9.png} +0 -0
- /kotonebot/kaa/sprites/{24a955bb-feff-4ace-a38c-8a6c3e6d4e95.png → 3ae6e096-42e4-4ac4-ad79-6f2529925c16.png} +0 -0
- /kotonebot/kaa/sprites/{e8e1bb95-6260-4e60-aa5a-972869fa2791.png → 3c41fb45-6400-4818-9066-e03d60d2a895.png} +0 -0
- /kotonebot/kaa/sprites/{e2929240-db44-42fb-be5a-3a397c2fe2ac.png → 3e9adf0f-f6c5-4d68-9667-97ea2f82bb51.png} +0 -0
- /kotonebot/kaa/sprites/{593442ad-94f8-4d68-b986-8cf92e74e76d.png → 3ef649e7-c03a-40d1-9a76-653faaf799df.png} +0 -0
- /kotonebot/kaa/sprites/{f22e46af-f72e-4978-a4be-8cfa68e4e85e.png → 43226a61-3d61-4acb-afbb-812bf9e97843.png} +0 -0
- /kotonebot/kaa/sprites/{09934d4f-a1a1-47c6-8127-32247b3144a6.png → 443a5dbf-e2fb-4d34-bb09-c21e1437f715.png} +0 -0
- /kotonebot/kaa/sprites/{c1e18236-0488-4025-b2f6-ce75d13b861f.png → 459851f5-fa20-45c4-a6d2-1018b3976fcd.png} +0 -0
- /kotonebot/kaa/sprites/{5365f6d2-17e2-4d51-a2c0-535007949cb3.png → 46c520e7-7b97-43be-8cc2-21e478b5d844.png} +0 -0
- /kotonebot/kaa/sprites/{a9c95639-fb97-4d1c-8f8c-53337570c7a7.png → 4867e835-c805-463e-9a53-1e677e3d140f.png} +0 -0
- /kotonebot/kaa/sprites/{0ab2fef6-759e-41a7-a078-c71a09acc829.png → 48ebb790-2310-436d-a31c-dba4db034cbc.png} +0 -0
- /kotonebot/kaa/sprites/{561b20a8-1faa-4be9-8861-7132ce1836ed.png → 4b8ebe86-7a0d-474a-abac-b4a45fda5e88.png} +0 -0
- /kotonebot/kaa/sprites/{b5e1e9ee-eab0-476c-8e35-e9760935942c.png → 4c235498-622f-4f74-9ebb-df3fcd3306ab.png} +0 -0
- /kotonebot/kaa/sprites/{6f3a4ad7-0949-4a1d-a0ea-1daa4148b9c9.png → 4f3d2710-5626-4471-9b21-cd01b8c542d1.png} +0 -0
- /kotonebot/kaa/sprites/{8fd4ee16-be10-438d-b0e0-b728723961fe.png → 4f4e3cf3-b1d9-436b-9477-5f2244c20d6b.png} +0 -0
- /kotonebot/kaa/sprites/{ced15f67-03ed-48a7-a0a5-24d29ec9a8f9.png → 4f891dc4-71c0-4492-a8d1-0c52978e75e1.png} +0 -0
- /kotonebot/kaa/sprites/{1bc32bd5-c429-490f-8a52-fd52d4e27ff8.png → 4ff46fa5-fe9e-4103-8012-451adc14dc43.png} +0 -0
- /kotonebot/kaa/sprites/{7d9c26a1-69e3-4c28-b794-66c81ee171d5.png → 5399e464-1ee6-406b-acab-7826e30f3fd9.png} +0 -0
- /kotonebot/kaa/sprites/{a8e36d55-5095-485e-a1f1-283c362352f1.png → 540a64f4-8111-4df4-abfe-0e62e0f8c7af.png} +0 -0
- /kotonebot/kaa/sprites/{34dc26b6-237e-4932-a009-8c03f4a4841f.png → 5422d945-aa90-443e-bf79-f8ab93ec9411.png} +0 -0
- /kotonebot/kaa/sprites/{b54448c1-460d-4ab3-b220-ff4c82e7cea5.png → 585c7846-f353-448f-8eb9-1ceafec94555.png} +0 -0
- /kotonebot/kaa/sprites/{3ed00c80-7b46-4eba-9df7-89de8161150f.png → 5a87228a-ec5d-4ffc-951a-1454c9c03bdc.png} +0 -0
- /kotonebot/kaa/sprites/{511408bd-a212-4261-b4f1-b6c592e44c52.png → 5b14a452-ea54-4804-8ec0-3cd916cd8e88.png} +0 -0
- /kotonebot/kaa/sprites/{1062488e-eb7c-42e0-bb3d-675d88992dc5.png → 5cc8ccda-2cf7-4956-b67d-15327bc75ed6.png} +0 -0
- /kotonebot/kaa/sprites/{8b9fddd0-4a17-4bc3-ac8f-cd6fa21058b2.png → 5e27d1c5-cc3f-4aee-8d79-69c09206fa3d.png} +0 -0
- /kotonebot/kaa/sprites/{068d9a7a-2920-44ab-8fe4-b48bec98b837.png → 64938ad2-442f-41eb-a544-4d2611e8012f.png} +0 -0
- /kotonebot/kaa/sprites/{13f72533-c91e-412d-8b43-208e2128cd16.png → 65223004-722e-4003-af09-c7769e8a7cb2.png} +0 -0
- /kotonebot/kaa/sprites/{31fedc14-7e32-4547-a97d-4b76aa8e9ca5.png → 659a1775-7001-4add-96e9-292693a26b60.png} +0 -0
- /kotonebot/kaa/sprites/{ac3f3385-0281-4e45-87fa-e9b4fcf81688.png → 6626694b-1394-44af-b76b-791c5bb2428b.png} +0 -0
- /kotonebot/kaa/sprites/{fd5890f6-f437-47cc-85d6-54745864075c.png → 6a202eb6-dd41-4675-a840-99dde2b2efa4.png} +0 -0
- /kotonebot/kaa/sprites/{23d99912-0b9f-434c-bd90-9ab71e70e6f4.png → 6b2e887b-e113-4280-9779-6795c2782c58.png} +0 -0
- /kotonebot/kaa/sprites/{3d2ce9cb-39a0-4b2f-ab96-39ded89a67c3.png → 6eb959e1-ee64-4fa6-a20f-8ee4e51f2c6a.png} +0 -0
- /kotonebot/kaa/sprites/{3a5b5966-b641-42b1-816e-aa0ae465ad66.png → 7098fbf7-b8cc-4933-bfec-12a2ac98e38c.png} +0 -0
- /kotonebot/kaa/sprites/{736def6e-bb5e-445b-b2a6-7b8670c7cbb3.png → 712e9223-4dd2-4ff6-887b-4182fd243d78.png} +0 -0
- /kotonebot/kaa/sprites/{fa57193f-5654-4b9d-8a9a-67211e7b5aff.png → 7256a95e-24b8-40fd-bd8e-73a1572c3f93.png} +0 -0
- /kotonebot/kaa/sprites/{aaa4ac00-3da2-468d-b2c3-f69b0ccaff2c.png → 73f89439-c4e3-4263-8fa7-229cde98aa99.png} +0 -0
- /kotonebot/kaa/sprites/{2a07a1e9-8033-492a-80de-8269a94abc85.png → 74efd362-4cc1-4b9f-8032-e5bc45c2af5c.png} +0 -0
- /kotonebot/kaa/sprites/{86584eea-2d90-4ab5-916a-0d29ec4edcde.png → 756ac796-ce43-4ddb-989e-13bf07cbe3b7.png} +0 -0
- /kotonebot/kaa/sprites/{b6040e31-b183-4520-ad2a-966612c60f86.png → 77193249-7e2a-4652-ab6d-a463350ca226.png} +0 -0
- /kotonebot/kaa/sprites/{ec96a180-1c0f-4bd2-8b21-6b31eac39ef5.png → 784a91b2-4d24-461f-8bd3-2f02b9bc193f.png} +0 -0
- /kotonebot/kaa/sprites/{b0a9ad98-2e2c-4dbb-b1e6-c93a4f6f92d4.png → 83c67f2a-0f73-4238-a5a8-8ebb839ed99a.png} +0 -0
- /kotonebot/kaa/sprites/{acb66482-748f-487f-bcd3-a400fb9b70ba.png → 86b3bab1-c5f6-48b2-b810-c3ec55c32314.png} +0 -0
- /kotonebot/kaa/sprites/{a97fe010-f776-4ab4-88f5-4d0cceecc7ba.png → 872838c5-47c6-4f78-b105-0a72b5459f16.png} +0 -0
- /kotonebot/kaa/sprites/{877b36cd-07f9-425c-be1d-5e1925dc2f4f.png → 93f03304-5609-4f4f-9ac8-a46e7b883960.png} +0 -0
- /kotonebot/kaa/sprites/{bfa32df6-16ba-406a-be3c-7e5248d9cd0c.png → 97e96ecf-e51b-4a09-ab11-3c164196747f.png} +0 -0
- /kotonebot/kaa/sprites/{9b8ebc2e-a8a3-458a-a840-54c7a5ad0119.png → 992473c3-df0a-4c72-8134-f2aac9e7b0f6.png} +0 -0
- /kotonebot/kaa/sprites/{57f56121-cdc4-4c29-8fcd-9d4f872c98e7.png → 9d86ab77-de0b-433d-9b0e-5aba283309a6.png} +0 -0
- /kotonebot/kaa/sprites/{da8f3c98-de95-4be0-88e7-de5e7ef90649.png → 9eb202c8-c61a-4918-beb9-b0f03739b0b3.png} +0 -0
- /kotonebot/kaa/sprites/{c689a3e0-d0ad-49e7-b5d9-66ff7e34fd2a.png → a4e02797-2c5d-4860-aaa4-c20c43be7500.png} +0 -0
- /kotonebot/kaa/sprites/{25bf9c17-099b-437e-ae0f-8226c7c0faa9.png → a5c582f5-3627-44be-b574-a4e4287376e0.png} +0 -0
- /kotonebot/kaa/sprites/{59067ba8-2bfe-4bc8-b028-90ccb1acf5f6.png → a914da74-9752-42be-913b-86514eb4b589.png} +0 -0
- /kotonebot/kaa/sprites/{6514f807-0a12-4338-a3be-9f0a2bc22e7e.png → aacb651b-9a3d-42a1-9fc0-9187dc8cded7.png} +0 -0
- /kotonebot/kaa/sprites/{304df45b-b744-427e-ba79-9f57a2313776.png → ae146d94-5e69-4970-b175-d7c8c4f9a9cd.png} +0 -0
- /kotonebot/kaa/sprites/{ed82be6d-7c5d-42fd-bdd1-8ad20076f480.png → ae57e1fb-c42f-4401-93a1-76d4591b5fad.png} +0 -0
- /kotonebot/kaa/sprites/{b0404967-c93e-4900-beeb-26717ae13c4a.png → b1878d2b-4908-4342-b395-864aafa5c54b.png} +0 -0
- /kotonebot/kaa/sprites/{e26d7a9a-f8fe-4092-b3fc-0647b34c984e.png → b26e3c78-a6be-4ad1-8992-c3245b1a6f9b.png} +0 -0
- /kotonebot/kaa/sprites/{da1a9ce5-0032-413c-ae26-2a5d27efe7ef.png → b3a41d58-f375-4882-bebb-57f72322d016.png} +0 -0
- /kotonebot/kaa/sprites/{cc6e472b-7f6f-4f34-8fb4-c2c15913cda5.png → b4905122-7d97-4561-a14a-b8a9a5cd9227.png} +0 -0
- /kotonebot/kaa/sprites/{e3e6fe61-afa3-4a6b-810b-c87d599f5868.png → b534423c-2024-4234-9886-f49e17dd96e7.png} +0 -0
- /kotonebot/kaa/sprites/{c7fb79d2-9335-4d86-afaf-abc537394cbf.png → b6680d31-8552-4111-bc39-0867c06bf94a.png} +0 -0
- /kotonebot/kaa/sprites/{7cf3da78-a825-4e5e-8210-d6ebc3e7ab6b.png → b6c637bf-5fdd-4e68-b4d8-b403bf611f3b.png} +0 -0
- /kotonebot/kaa/sprites/{a010517f-6ee1-4924-8385-1f5fb879e08f.png → b9e19bda-3793-4cf4-928a-fc43642b32e6.png} +0 -0
- /kotonebot/kaa/sprites/{09ea0d24-9412-4f0e-bbe8-9227687b9cb5.png → bc1c640a-87d8-47af-9fcc-8681acac7b27.png} +0 -0
- /kotonebot/kaa/sprites/{dbc0975e-e9f2-4db8-a0df-f16711606165.png → bc25ed87-50a7-4aa8-b743-505450677b00.png} +0 -0
- /kotonebot/kaa/sprites/{a7c14f96-6b0e-4065-96e7-04058c0ab1c0.png → bcf2f87a-de7f-4fb9-aa6c-0b4f6bff921e.png} +0 -0
- /kotonebot/kaa/sprites/{9d99fa4f-ca9e-4e19-97b2-7cbef502b73c.png → bdd0e8f8-3d35-48e8-b735-66eaf2ece2e6.png} +0 -0
- /kotonebot/kaa/sprites/{c07de7e7-263b-4b82-ab04-e31bec40b524.png → bec6c0cf-40f6-446d-85b3-c692d3322a51.png} +0 -0
- /kotonebot/kaa/sprites/{a57a3a56-8509-4e98-b438-0848e6fe091a.png → bf19069d-e044-4f76-93f7-f2ecd3214e47.png} +0 -0
- /kotonebot/kaa/sprites/{a4128c6e-4a40-4d2d-aa1d-597e70e718fb.png → c1274e01-2cc7-432f-b244-65ffe8269656.png} +0 -0
- /kotonebot/kaa/sprites/{60a3bc3c-099b-4090-9f6f-253c963e9fa4.png → c65d71af-ffb3-4992-b954-c59ae48615b8.png} +0 -0
- /kotonebot/kaa/sprites/{22672fe7-40d8-425f-a465-b19af092cb2f.png → c67852a2-30a9-4fd6-a4c2-83870a658998.png} +0 -0
- /kotonebot/kaa/sprites/{07ffe5a8-f817-4087-a7ce-da19516b9f55.png → c705eece-67d8-4017-a4d9-a7f1337f67be.png} +0 -0
- /kotonebot/kaa/sprites/{a8efadec-4461-4a34-bf20-801ba7a545aa.png → c86a3385-407e-40d5-b519-1927406d5b09.png} +0 -0
- /kotonebot/kaa/sprites/{e81bb7c7-aae0-4280-86e7-2c15fba205f1.png → ca42ca0c-3829-4e43-88c9-db4939cfa982.png} +0 -0
- /kotonebot/kaa/sprites/{f87af019-34ee-428d-8d11-dc77a2c41be5.png → cba7528d-ae17-4a37-b388-6f86e1a590f4.png} +0 -0
- /kotonebot/kaa/sprites/{f7c89d72-ca8e-46a9-ab49-b7775dfbf37f.png → cc1767ec-77db-49ac-8c9e-f48d1fb7b071.png} +0 -0
- /kotonebot/kaa/sprites/{38018b98-4f03-43f5-8fa2-ba739a1edd7e.png → ce282e51-7067-4293-ad26-24dbba172a08.png} +0 -0
- /kotonebot/kaa/sprites/{d04c4883-0d15-4bd8-918e-065db19bf145.png → d1e5672d-df91-4316-984c-48550c5d1931.png} +0 -0
- /kotonebot/kaa/sprites/{ab01298b-f04f-4b12-a256-efd1122f5fdc.png → d2d99405-7927-47fc-be4c-a7591b339a6c.png} +0 -0
- /kotonebot/kaa/sprites/{8c3c7599-0cbd-4ba8-9635-23eb6bb965b1.png → d356fc84-a8c0-4d0f-a3ed-c7ff5ccd276c.png} +0 -0
- /kotonebot/kaa/sprites/{45353fcd-59ea-4b15-93f7-8591adfa7af8.png → d477e49c-37cc-4e71-a8e6-6633f044260a.png} +0 -0
- /kotonebot/kaa/sprites/{063825e2-f4c7-4047-8958-7cc0a8cf32fb.png → d4b1e48b-bf9c-4f44-9ddb-3af8eb4ea464.png} +0 -0
- /kotonebot/kaa/sprites/{815d0dc2-5aa1-43be-8316-88d24c4c8c81.png → d6d6229a-2345-4fe7-b2c5-109fcdb37c39.png} +0 -0
- /kotonebot/kaa/sprites/{112c76ba-0409-4ba9-b485-19500003a60b.png → d953cdee-08b5-45fb-908b-2644220b0f07.png} +0 -0
- /kotonebot/kaa/sprites/{0ae22f69-b9e4-43c5-8c95-53360c0d4b35.png → de069910-6085-45a9-ba96-64bc7aeead77.png} +0 -0
- /kotonebot/kaa/sprites/{61feefa4-f5ec-4a99-b8fc-19deefa8d1cd.png → dea4c704-5739-423f-a15c-f31a4a93d64f.png} +0 -0
- /kotonebot/kaa/sprites/{90356864-a48e-4d0a-8ca3-8443524ac414.png → debc6a94-9bf1-46d7-b0b0-0c55cb367f12.png} +0 -0
- /kotonebot/kaa/sprites/{901fd5e9-a0d6-4774-bafe-4b3f6dedf006.png → e0555145-9446-4ebe-965b-f46b458e5681.png} +0 -0
- /kotonebot/kaa/sprites/{dc826aa1-4d2f-49f0-9c78-cec45b77f49d.png → e19c5f10-5f93-4431-9bf3-4f92512eab6e.png} +0 -0
- /kotonebot/kaa/sprites/{60b5e390-c956-4e7b-9a3c-3db0c2481d5b.png → e353b4cb-ea6d-4fc4-91ec-c19582e9507c.png} +0 -0
- /kotonebot/kaa/sprites/{2919b90c-64b6-4961-b2a9-edea29cda27b.png → e6554fee-c6fd-49ee-8c32-b4932fc701da.png} +0 -0
- /kotonebot/kaa/sprites/{7c4fcaae-44c8-429b-989c-d17fd07734f9.png → e916a5ca-287c-4cbe-93ca-22b439c5ffab.png} +0 -0
- /kotonebot/kaa/sprites/{67cce3d0-3c80-44a0-9193-18d00f9712af.png → ed4a2db1-ab2e-4b36-8d6f-5b7961501475.png} +0 -0
- /kotonebot/kaa/sprites/{866b2bda-fdfd-4cde-b6a5-8dc396d7bef3.png → ed4a318e-f69a-4fb9-9853-9746f01c6015.png} +0 -0
- /kotonebot/kaa/sprites/{ceb65e4a-c59b-4580-9360-ba1fd600846a.png → efe68984-8dbc-417e-924c-87c6860c58ef.png} +0 -0
- /kotonebot/kaa/sprites/{e61a092f-1717-4672-943b-71f061ce2717.png → f165bf01-9e9d-4afb-87d9-4a26318140cf.png} +0 -0
- /kotonebot/kaa/sprites/{7609a3df-963d-4c1a-ae2d-3bc6bc7a05b9.png → f2846992-402e-4f50-b74e-91d6f3b8994d.png} +0 -0
- /kotonebot/kaa/sprites/{5568e31d-9d55-4435-8cef-ef8b6fc8d2d8.png → f4227a80-f62d-4daf-83d0-c7b5500088ee.png} +0 -0
- /kotonebot/kaa/sprites/{a7755ce2-9f05-455b-8c8f-e3cf803d03de.png → f496a454-5cf5-4b6b-aedb-1dad58c85035.png} +0 -0
- /kotonebot/kaa/sprites/{cdb09691-5c2a-4bb4-8ae8-01fd865ba3e6.png → f4af8fb2-6270-4b75-8b24-d0e49daebac1.png} +0 -0
- /kotonebot/kaa/sprites/{9a57d7b4-722a-4f77-9f5f-635092154ec3.png → f60c40a1-750b-41ac-9d24-2d7ffce44166.png} +0 -0
- /kotonebot/kaa/sprites/{f188d7ad-cd46-4342-ae70-cc2d5abb87d9.png → f6c3bd48-fe1e-4fe3-bf58-13422b5b4a99.png} +0 -0
- /kotonebot/kaa/sprites/{7ceec350-8f7d-4786-a477-2f0ea6b81748.png → ffaffa14-22dd-4397-8dc1-7b94fd4cf06b.png} +0 -0
- {ksaa-2025.7.5.0.dist-info → ksaa-2025.7.9.0.dist-info}/WHEEL +0 -0
- {ksaa-2025.7.5.0.dist-info → ksaa-2025.7.9.0.dist-info}/entry_points.txt +0 -0
- {ksaa-2025.7.5.0.dist-info → ksaa-2025.7.9.0.dist-info}/licenses/LICENSE +0 -0
- {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
|