ksaa 2025.11b1__py3-none-any.whl → 2025.11.post1__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.
- kaa/__init__.py +0 -0
- kaa/application/__init__.py +0 -0
- kaa/application/core/misc_core.py +4 -1
- kaa/application/services/__init__.py +0 -0
- kaa/application/services/config_service.py +112 -0
- kaa/application/services/feedback_service.py +121 -0
- kaa/application/services/produce_solution_service.py +83 -0
- kaa/application/services/task_service.py +145 -0
- kaa/application/services/update_service.py +208 -0
- kaa/application/ui/__init__.py +0 -0
- kaa/application/ui/common.py +123 -0
- kaa/application/ui/components/alert.py +251 -0
- kaa/application/ui/components/alert.pyi +257 -0
- kaa/application/ui/components/categorized_select.pyi +697 -0
- kaa/application/ui/facade.py +189 -0
- kaa/application/ui/gradio_view.py +135 -0
- kaa/application/ui/views/__init__.py +0 -0
- kaa/application/ui/views/feedback_view.py +65 -0
- kaa/application/ui/views/produce_view.py +251 -0
- kaa/application/ui/views/settings_view.py +581 -0
- kaa/application/ui/views/status_view.py +171 -0
- kaa/application/ui/views/task_view.py +102 -0
- kaa/application/ui/views/update_view.py +106 -0
- kaa/config/schema.py +8 -0
- kaa/db/constants.py +3 -2
- kaa/errors.py +60 -0
- kaa/main/gr.py +60 -3132
- kaa/main/kaa.py +11 -3
- kaa/metadata.py +80 -0
- kaa/resources/__pycache__/__init__.cpython-310.pyc +0 -0
- kaa/resources/game.db +0 -0
- kaa/resources/game_ver.txt +0 -0
- kaa/resources/idol_cards/i_card-skin-amao-3-014_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-amao-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-1-000_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-1-000_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-2-000_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-2-000_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-3-000_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-3-000_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-fktn-3-016_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-fktn-3-016_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-003_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-003_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-009_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-009_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-013_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-013_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hrnm-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hrnm-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hski-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hski-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hume-3-009_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hume-3-009_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hume-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hume-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-jsna-3-009_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-jsna-3-009_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-jsna-3-014_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-jsna-3-014_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kcna-3-014_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kcna-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kcna-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kllj-3-014_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kllj-3-014_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-shro-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-shro-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-ssmk-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-ssmk-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-ttmr-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-ttmr-3-015_1.png +0 -0
- kaa/sprites/052ab0f5-8d95-4b5d-8678-3838322d9e5e.png +0 -0
- kaa/sprites/18adb1a5-b95d-41ff-9cb9-16613fa4cf6a.png +0 -0
- kaa/sprites/2aac3a97-435e-4c02-925f-e2d1673b7982.png +0 -0
- kaa/sprites/2cc63c6d-5988-4f72-ae88-b03b8246ad97.png +0 -0
- kaa/sprites/3208d803-2c92-4775-80dc-0527df4b63d9.png +0 -0
- kaa/sprites/345435d0-5a5c-494b-95ab-1e086fb88f51.png +0 -0
- kaa/sprites/3ad30d90-8b57-4641-a9e2-33970e5cea1d.png +0 -0
- kaa/sprites/3e0da5df-a4de-42bd-83bd-13df3c393af4.png +0 -0
- kaa/sprites/41904062-e218-4b28-972a-b5cfcd058d2c.png +0 -0
- kaa/sprites/44a50906-1835-4e29-ae97-496b4cdde9e9.png +0 -0
- kaa/sprites/488a1403-d300-4fa6-94c7-da71d09fd4bb.png +0 -0
- kaa/sprites/48c16d60-05d6-43bc-97c3-7f099bfc0881.png +0 -0
- kaa/sprites/4e3dbeb5-70bb-4642-9f73-01f9f98bc3aa.png +0 -0
- kaa/sprites/54987de4-3e1b-4640-b203-1e4c82d7e98d.png +0 -0
- kaa/sprites/5a0bfeac-fb22-4b0c-b775-4aa6220bae89.png +0 -0
- kaa/sprites/5aad0930-54a3-4b6d-bec8-250228963f69.png +0 -0
- kaa/sprites/5c49d3b3-656e-4c8c-ae1a-9b0209b9dcc3.png +0 -0
- kaa/sprites/5c9a1581-a14a-449b-a1b0-7a31a965facc.png +0 -0
- kaa/sprites/62411b55-7be8-46d9-aa4a-fb56dab6658c.png +0 -0
- kaa/sprites/6580ea89-553e-4445-a855-f834d580e6e6.png +0 -0
- kaa/sprites/686a2bf5-0498-4d53-8ba1-1110ff36f046.png +0 -0
- kaa/sprites/699ca639-3006-45c1-b5fd-8cf9631fd3ea.png +0 -0
- kaa/sprites/6e8325f9-7fdb-4729-ac13-ca67244d97bc.png +0 -0
- kaa/sprites/71051aa7-81f1-4144-9318-4405e10547ee.png +0 -0
- kaa/sprites/732ffc6c-6a17-41f8-9cd1-f218ebc0c23f.png +0 -0
- kaa/sprites/744ea25a-9b6e-4f8f-9a00-0ac714571b09.png +0 -0
- kaa/sprites/74b50642-0b18-45c3-8a5d-013ef1e0eb78.png +0 -0
- kaa/sprites/77e7262f-0d12-4bd9-9f22-e8f41a600bf8.png +0 -0
- kaa/sprites/78b928c6-0d24-4e87-a84f-0091d42f8e49.png +0 -0
- kaa/sprites/7c193df5-0a1d-444d-9f92-e9c0db79e53a.png +0 -0
- kaa/sprites/7e729638-f54a-48bb-8bbf-eeaa4d697502.png +0 -0
- kaa/sprites/802e717f-d70a-4f34-8b96-be586a8dfde9.png +0 -0
- kaa/sprites/831cac7e-49e9-45d1-bb65-b1db733cda90.png +0 -0
- kaa/sprites/8411b102-866d-4e41-ab12-507397b80ca5.png +0 -0
- kaa/sprites/84b3c8e2-6e37-443c-be9b-8a95aedc6f37.png +0 -0
- kaa/sprites/85308e03-ba72-499a-9d12-870269fa3cd0.png +0 -0
- kaa/sprites/8922feef-17db-4b10-93da-1bad30492ac2.png +0 -0
- kaa/sprites/8a6ed80c-79c6-4df6-ab65-64d67afb2d5b.png +0 -0
- kaa/sprites/8c0439d9-9eb7-43f3-8d1e-7e41c57c1bbd.png +0 -0
- kaa/sprites/8dd3de6d-07d5-4d93-9663-71a3a4c57a32.png +0 -0
- kaa/sprites/9009323d-1418-4aed-8a93-075b326d2e7a.png +0 -0
- kaa/sprites/904d22f7-51be-486f-8dd1-1871c0cf28e3.png +0 -0
- kaa/sprites/90943f62-0a03-4a75-804a-0c2fa7b27af4.png +0 -0
- kaa/sprites/9180e0e7-2cc4-46c7-95ff-fbe83806baf2.png +0 -0
- kaa/sprites/93f5c33e-ec81-4a70-a11f-b2e8cb1751ee.png +0 -0
- kaa/sprites/9558b2a5-3961-4ad0-9ce8-379d71920d78.png +0 -0
- kaa/sprites/968dff88-5a2f-42c7-b64b-406801e22c87.png +0 -0
- kaa/sprites/99d99d78-ee37-4e84-8768-b5a7f4f9bd51.png +0 -0
- kaa/sprites/9caa102c-70af-4a8c-b595-82df9f4c05d8.png +0 -0
- kaa/sprites/9e06b7d6-5d15-4844-bbfe-ad1af7da3113.png +0 -0
- kaa/sprites/__pycache__/__init__.cpython-310.pyc +0 -0
- kaa/sprites/a04ed558-25e3-42d7-a662-250cad9fa5df.png +0 -0
- kaa/sprites/a0a62dbf-a027-4b63-86e4-2e863b2edb01.png +0 -0
- kaa/sprites/a4b898aa-405e-4235-8075-a34640a2b023.png +0 -0
- kaa/sprites/a5c3108f-c92d-4ce7-8c4e-93b79f55ceb3.png +0 -0
- kaa/sprites/a7e6222f-f8ca-47c2-af1e-f158a87f6a03.png +0 -0
- kaa/sprites/ab3d3301-8297-43a8-bf0b-85413c115a7d.png +0 -0
- kaa/sprites/ad589feb-6d19-47c7-a582-55ee130ee89d.png +0 -0
- kaa/sprites/ae4742aa-acda-442d-bf73-b3fe7b66e85c.png +0 -0
- kaa/sprites/aed87cd4-eb05-4c24-8adf-cd3fab20e9a3.png +0 -0
- kaa/sprites/afb9e4a9-29a5-4202-9f75-e7d2f1b64aa4.png +0 -0
- kaa/sprites/b1f547d4-c1ba-43fc-9398-4ccdc25b8b62.png +0 -0
- kaa/sprites/b61bd48f-1fe7-49fd-a588-09aac3b66f5a.png +0 -0
- kaa/sprites/b6219452-323a-44eb-9f44-97b2ad0ee49a.png +0 -0
- kaa/sprites/b7550a50-5943-45e7-9c1b-771117364844.png +0 -0
- kaa/sprites/b865eedf-7bea-46f6-bf14-7f8f4e9ab000.png +0 -0
- kaa/sprites/b8f0ed47-6115-4b88-848a-2fc4a1ab25d8.png +0 -0
- kaa/sprites/b9224799-d0c1-43d9-9f11-1d35903fc4d9.png +0 -0
- kaa/sprites/baa9c530-68cb-4111-85f6-060823ad32c4.png +0 -0
- kaa/sprites/bed54f67-d828-403c-9cb3-6a7c85695c2a.png +0 -0
- kaa/sprites/befadc5e-862a-4818-9223-5d58e4ac03cb.png +0 -0
- kaa/sprites/c0d1896c-71a1-47d6-9847-b87543a942e9.png +0 -0
- kaa/sprites/c2984c0f-3e17-45c3-9d7c-dc4f14440b13.png +0 -0
- kaa/sprites/c6b53acc-bc89-465e-9814-0138513327ac.png +0 -0
- kaa/sprites/c72a4609-6bf0-4568-8ebc-73c30d67c61e.png +0 -0
- kaa/sprites/c7829f82-bfce-4259-9ec6-f1cfb7bac925.png +0 -0
- kaa/sprites/c82ebc01-0127-417f-831a-9d17a84b2691.png +0 -0
- kaa/sprites/c8747b3b-745c-45ed-84b6-dde1b2558ce8.png +0 -0
- kaa/sprites/c98ef89e-4a1c-40f0-a82e-6851f7b6bbc9.png +0 -0
- kaa/sprites/cb04d87c-f5a9-405c-92ac-b3603e482221.png +0 -0
- kaa/sprites/cb43f670-6623-4af9-ac1d-746372e40511.png +0 -0
- kaa/sprites/ce357023-436b-4a39-882f-8410acd8f0d7.png +0 -0
- kaa/sprites/cea9f5ea-5923-4c6e-bd24-90d2e084112c.png +0 -0
- kaa/sprites/cf62e2df-3be1-4d03-9f34-1518280abd90.png +0 -0
- kaa/sprites/d0a483a9-400f-4b6e-87a0-9781b4454da0.png +0 -0
- kaa/sprites/d10d480c-e96e-475e-815c-0969f37fe3bc.png +0 -0
- kaa/sprites/d1839450-8d60-41a4-b035-8e1acd0f1c7a.png +0 -0
- kaa/sprites/d19859f3-f7cc-46ef-8bc6-86df7856fd53.png +0 -0
- kaa/sprites/d2d3d77d-a06f-4167-b02b-5ca688c0c0c3.png +0 -0
- kaa/sprites/d38c5015-e461-4e09-8b56-731472bdf59e.png +0 -0
- kaa/sprites/d473b5bd-4be3-4f0f-bb92-b909050f273a.png +0 -0
- kaa/sprites/d609a029-5407-43c2-a9a9-07bfd43fcbb8.png +0 -0
- kaa/sprites/d6491f82-9637-47eb-8f35-eb272b5ef8df.png +0 -0
- kaa/sprites/d8dd8b59-c05c-4350-a15d-be75c94d46cc.png +0 -0
- kaa/sprites/d98263bf-15fb-430e-ba39-2558fa99cac0.png +0 -0
- kaa/sprites/d9bc9bbb-9a1a-4cbe-b6ed-24112d7c5ac7.png +0 -0
- kaa/sprites/da922566-97ba-4477-bcad-35ea02a3ee48.png +0 -0
- kaa/sprites/dac8d8fd-006c-4f50-a4e0-d79dbf3f5915.png +0 -0
- kaa/sprites/db33ab8d-160d-48c7-b464-dfe194e762d4.png +0 -0
- kaa/sprites/dcfdfab4-8dfb-4069-bf88-8e8401ef86f3.png +0 -0
- kaa/sprites/de354b53-2fd0-4039-87e2-fcad2e070579.png +0 -0
- kaa/sprites/e28ea25e-0bcf-4d52-b501-9ef7a4863870.png +0 -0
- kaa/sprites/e2ac927f-257e-4537-995d-fbfbe4983b70.png +0 -0
- kaa/sprites/e642b9ef-c8a7-41d5-8d71-5cfbaf3017a1.png +0 -0
- kaa/sprites/e749feec-6bf2-4c24-bb12-948e696b8116.png +0 -0
- kaa/sprites/ed3aa6e6-4256-416b-9d04-d57ca340e39d.png +0 -0
- kaa/sprites/ed4c0554-84df-4c29-af18-7c38523cc59b.png +0 -0
- kaa/sprites/ef1bfd47-78e9-4cb7-a344-53d980fc3e5e.png +0 -0
- kaa/sprites/ef1ddc7d-75f9-4798-afa1-733e16794a81.png +0 -0
- kaa/sprites/efb01328-b6e1-438e-9471-bef3ea77a22c.png +0 -0
- kaa/sprites/f06b1a4f-eeb6-4dea-9543-5ec27640bdd9.png +0 -0
- kaa/sprites/f07bac27-9201-498f-9f26-a58291a70542.png +0 -0
- kaa/sprites/f0fd613b-d2f8-4b18-90d8-0b328373e715.png +0 -0
- kaa/sprites/f1fbe46a-759d-467d-b8ca-2158f530f7c5.png +0 -0
- kaa/sprites/f2314c76-3a2b-4644-831a-343a601145df.png +0 -0
- kaa/sprites/f329d4ba-e836-4be6-a05b-879b53667df3.png +0 -0
- kaa/sprites/f469d235-552f-4b07-9d03-9bcae425b6d8.png +0 -0
- kaa/sprites/f5177258-a3cf-4d4f-9c69-0b49556f754f.png +0 -0
- kaa/sprites/f5dcac82-7c54-4020-84c5-b1334b595612.png +0 -0
- kaa/sprites/f6656842-1460-41ab-95ed-561aefaf08e2.png +0 -0
- kaa/sprites/f70e9455-7cc8-449c-8282-89a9e69f7ac3.png +0 -0
- kaa/sprites/f7fd469f-791e-4bf7-ae3f-b5aaed92f999.png +0 -0
- kaa/sprites/f873280f-bc68-40d1-8d8d-3d86964264f0.png +0 -0
- kaa/sprites/f9da6eeb-ff9e-45b3-94b0-e7ba34938dec.png +0 -0
- kaa/sprites/fa24f5d5-d7e5-4421-8cbc-2ce3a0189654.png +0 -0
- kaa/sprites/fb61dbf3-fbc1-400a-adde-83ea08b5027d.png +0 -0
- kaa/sprites/fc8457b6-f8a3-4b01-9864-0cd624c312b6.png +0 -0
- kaa/sprites/fdbf6a89-b95a-481f-a269-be53e05b18de.png +0 -0
- kaa/sprites/fed11307-2186-4ede-875f-ffa0383f410c.png +0 -0
- kaa/sprites/ff0d3db2-c4e5-41e7-a85b-df4fd392924c.png +0 -0
- kaa/sprites/ff40ff91-4e8c-46cb-a254-66cd5ffd363e.png +0 -0
- kaa/sprites/ff614071-c318-4263-af3e-01ea0ab45b73.png +0 -0
- kaa/tasks/R.py +136 -128
- kaa/tasks/R2.py +24 -0
- kaa/tasks/common.py +5 -0
- kaa/tasks/daily/club_reward.py +1 -0
- kaa/tasks/daily/contest.py +2 -1
- kaa/tasks/daily/purchase.py +33 -1
- kaa/tasks/daily/upgrade_support_card.py +12 -2
- kaa/tasks/produce/cards.py +5 -4
- kaa/tasks/produce/common.py +202 -105
- kaa/tasks/produce/in_purodyuusu.py +35 -17
- kaa/tasks/produce/non_lesson_actions.py +10 -33
- kaa/tasks/produce/p_drink.py +5 -1
- kaa/tasks/produce/produce.py +2 -1
- kaa/tasks/start_game.py +2 -1
- kaa/util/reactive.py +182 -0
- {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/METADATA +27 -24
- {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/RECORD +352 -181
- /kaa/sprites/{35341839-4469-4ab6-aa40-33642fe43e82.png → 01e93c2c-28dc-41f8-8f9a-ec62ec12aa01.png} +0 -0
- /kaa/sprites/{68d9f340-a3d2-4708-8eb1-c1ed857decda.png → 02ac01e0-00b0-46d8-a6db-56248c843c6d.png} +0 -0
- /kaa/sprites/{39f6d657-3b3e-40aa-849b-7ad87a0be1d0.png → 033e73d1-9f45-4bca-bf96-6778410f2fc4.png} +0 -0
- /kaa/sprites/{799fe395-2264-4bc5-b515-813dadda8fe1.png → 04036690-5b0f-4ee0-a9d0-022ee822bf0e.png} +0 -0
- /kaa/sprites/{256ffeba-8e9e-4cc5-8a1c-9eaee427f1a5.png → 041bd3fc-d040-4773-8641-4e4509300d2f.png} +0 -0
- /kaa/sprites/{5ffd3f29-db4f-4f66-b9ed-be5a70b7ebf9.png → 04974917-b1e8-4ccc-807b-6f651026c955.png} +0 -0
- /kaa/sprites/{8be81341-a74d-42c8-8231-5d1854bc08e7.png → 04c4e4c2-9908-4be7-bcbe-4d926ca76737.png} +0 -0
- /kaa/sprites/{043e753e-db15-45ba-8513-53c3fc9c7f3c.png → 05b97cdf-f7df-4d91-9ec8-5e9594a46382.png} +0 -0
- /kaa/sprites/{5431dc38-c257-40b3-8f7b-8bceaa7fe587.png → 061b032f-860b-4c53-889b-aa126797f062.png} +0 -0
- /kaa/sprites/{cb6dffd9-6474-4d09-aee6-26352ea51d31.png → 07b43eb9-db32-4046-96d3-9f4314bfd80a.png} +0 -0
- /kaa/sprites/{3e087b8d-420d-48ff-b526-29c4a65d8cbe.png → 08b12ded-8230-4c7e-bb9f-27c85b0fdabb.png} +0 -0
- /kaa/sprites/{68e20ebf-02fd-46a1-88d7-b4472824e7bc.png → 09364c3a-f892-4911-abdc-2f5fea09289f.png} +0 -0
- /kaa/sprites/{c69dcdcf-42a7-420e-aa8e-bb8639ea80b6.png → 09d2a63d-d2f0-4b97-b3cb-22a61b1530f7.png} +0 -0
- /kaa/sprites/{d644faa3-ff16-417f-928c-4c62b040bfdb.png → 0cad6e46-276f-424e-a79e-d272ebaa7c8e.png} +0 -0
- /kaa/sprites/{db6707a2-2964-4919-9992-4d801fa43dae.png → 0e49fbde-6be6-42b3-b8d1-36e0cb9cc35d.png} +0 -0
- /kaa/sprites/{cd00a2d7-af48-48b1-b2e1-5360ceed249f.png → 0e51d671-928c-4972-8ac0-de446202070b.png} +0 -0
- /kaa/sprites/{736a9daf-05d6-46ba-810b-5a8f509152d1.png → 0e6f8981-f46c-4c7d-9d90-fe349f0a1d77.png} +0 -0
- /kaa/sprites/{92c3de1b-eed1-45b9-82e0-c9e97bb479e7.png → 0e9e3dbf-6e94-4a12-b558-3d8ab500c0a6.png} +0 -0
- /kaa/sprites/{913dbd4e-ebb1-4c9f-b145-9960cde59c17.png → 0eafb6c1-9d85-4fe0-8011-7235704ca9d3.png} +0 -0
- /kaa/sprites/{ec3cad5f-e0c9-4577-8499-79b50248344e.png → 1002a830-1ad5-47a7-b7dd-ed2989e6fc1b.png} +0 -0
- /kaa/sprites/{e5e49b44-dcc2-4e77-9180-0d2beaa3f9ad.png → 10943367-c1d8-41c7-a831-d5d05288875a.png} +0 -0
- /kaa/sprites/{c1d502eb-c77f-45cb-86b5-11b4a8a3aef5.png → 10f37db0-8c3e-4790-a5c3-cdb841f106a7.png} +0 -0
- /kaa/sprites/{802db04f-77c2-46a4-a6eb-f81d48ea03ce.png → 11f65378-b982-4936-9ac7-68560a74a042.png} +0 -0
- /kaa/sprites/{1befe09b-cb77-417a-b21e-7746804d4e03.png → 1660acf7-a420-4d92-a90c-55c5ff208da6.png} +0 -0
- /kaa/sprites/{16a0fd47-e85b-4848-8894-9d071ea993ac.png → 170d28bf-d262-4bf1-b35f-8f3d4b4fff6e.png} +0 -0
- /kaa/sprites/{5906d986-d0e5-452d-a7c4-ddeb7af8751d.png → 182d8c71-5ce5-4ee1-9f66-ef99aadae654.png} +0 -0
- /kaa/sprites/{cfe3563d-a24b-4197-a0cb-5628bd990c08.png → 18d26894-fd12-4644-8269-a09d11be9520.png} +0 -0
- /kaa/sprites/{8e5e968b-edad-4c03-abc8-3f2a7e8879ae.png → 1b0dd18b-eb41-4c9c-b031-bab91c93fd5d.png} +0 -0
- /kaa/sprites/{3fa5f81c-9223-44ba-bf07-71932350e845.png → 1e7a6e19-760c-4fbc-b0f1-f620f51056b9.png} +0 -0
- /kaa/sprites/{9e7eaa8e-3178-44da-a5ec-34b889f8facf.png → 1fbe13d6-3a4d-4935-b687-a76a76a1e32c.png} +0 -0
- /kaa/sprites/{1ad89ee4-1bb1-41d2-a92c-79caf6baa38a.png → 1fe31432-a050-48db-acc1-becde42deaf9.png} +0 -0
- /kaa/sprites/{94d54ba7-0ccf-4fd9-a5bf-488bac1364c8.png → 20146fe6-e62b-4c57-b229-901994903b70.png} +0 -0
- /kaa/sprites/{6c926e92-9af9-402d-8512-6417ca116928.png → 20c673e9-fcbe-469b-be35-7844a1d5a9cd.png} +0 -0
- /kaa/sprites/{572a921d-633f-4465-b177-7a0d9ad7e099.png → 21747ae5-d94d-45d1-bda8-939389dc4874.png} +0 -0
- /kaa/sprites/{aa1624ff-88b0-447b-8e2b-8a50fd9e4062.png → 21fbbe96-02bf-4835-aa04-068bc5cc6ca3.png} +0 -0
- /kaa/sprites/{3b4dc708-1d34-4a88-9fe3-d8de2ec1d5c8.png → 24be7d90-7944-4a0a-a60c-67c9737b322c.png} +0 -0
- /kaa/sprites/{b59c0e9b-1f20-4194-ab37-286f505fa656.png → 24d6a47c-2099-45e2-9a67-b37767f459fc.png} +0 -0
- /kaa/sprites/{023b8f4c-15ab-4845-b141-446c861ad475.png → 2568d3d3-b642-4ea4-b929-4dee0b09738a.png} +0 -0
- /kaa/sprites/{7d7df15f-707e-4e27-826f-21e42af1dae0.png → 263b1037-fb51-4eb1-8c71-5232b03235d2.png} +0 -0
- /kaa/sprites/{f0aef696-2106-46a4-8b7f-9f16b6c89d3f.png → 27dbd535-7f95-4698-8fea-2bed67dd6968.png} +0 -0
- /kaa/sprites/{81686816-c723-47d1-9824-a68d9ebe1bd4.png → 286801f7-3af5-4cd0-9c25-46c12c2cd8f8.png} +0 -0
- /kaa/sprites/{dc97fea3-898f-4135-9c40-ad41570ab4ae.png → 298182ae-747a-44e3-8511-a64d3532b8ac.png} +0 -0
- /kaa/sprites/{8e019262-ad23-4cbb-84da-86b34775a91e.png → 2d3470f8-a714-4175-a8fe-71eef80921b6.png} +0 -0
- /kaa/sprites/{01247ebe-8d63-4573-90f4-d8dc2b7ca14c.png → 2e3b2982-d14b-4b49-bb64-da8178311d75.png} +0 -0
- /kaa/sprites/{fcc72120-2a77-4c26-a27e-e1027c6088c0.png → 2e41df89-a8d7-4e7e-96cb-7f551414823b.png} +0 -0
- /kaa/sprites/{31f2de0a-567b-425a-9be6-536e4532d813.png → 31e02e56-f266-47b5-8b10-fe79fe06d614.png} +0 -0
- /kaa/sprites/{7daaca55-e3fd-4e12-bf31-872105ceb726.png → 3314dc6c-868f-4045-9f60-1f3a17fed324.png} +0 -0
- /kaa/sprites/{fdf0da06-f088-424f-9941-8c883fea3db3.png → 358f1561-c16f-45a0-842d-d62fc735dc80.png} +0 -0
- /kaa/sprites/{51b95c81-4ff9-434c-ade2-3518e63337cb.png → 3782897a-f1c2-4f05-a02d-4c760672f52a.png} +0 -0
- /kaa/sprites/{847eb5c0-0350-4b7c-9c9c-43c796709795.png → 385e60df-2063-4caf-b1ea-e6ac909bc49d.png} +0 -0
- /kaa/sprites/{8e4d8a0f-4a9d-4562-9234-63806b11d85f.png → 39450419-26b5-4fbd-a5d4-1bab369ced30.png} +0 -0
- /kaa/sprites/{424a0ef5-102d-4734-a731-2b3b3c7c9682.png → 397c0e24-f35a-48c9-a576-aa1fcfc517b5.png} +0 -0
- /kaa/sprites/{23b9cda9-8be8-438e-8e54-57d91a4bd875.png → 3adef8f4-629d-4cb7-b54a-dadabfea155e.png} +0 -0
- /kaa/sprites/{2234f709-1703-4589-905c-175f4db09b1b.png → 3b86b4ac-aa29-4309-82da-f47a174d88cc.png} +0 -0
- /kaa/sprites/{e933cd55-e47a-4327-89d7-b25995cb4a3f.png → 3c6bbcea-488d-4df8-ab40-21e263aa0b16.png} +0 -0
- /kaa/sprites/{49bde219-f9a3-41b5-84b8-e417160a0f40.png → 3db54e0b-672d-4dfd-8a9b-5db37a08be74.png} +0 -0
- /kaa/sprites/{2204967a-a0ee-4dd3-aecb-4d531e8e954c.png → 402d430d-b507-4aa6-b3e1-db66b38c71b4.png} +0 -0
- /kaa/sprites/{70768479-5d7a-4941-8774-ad556c47bee2.png → 414140a2-de67-4c7f-a7f6-c8b30a6c8d6a.png} +0 -0
- /kaa/sprites/{dd7bd6cd-90f1-4773-9b68-5df7f2f84da5.png → 4147514f-4f3f-4dd5-952b-0f2cf5f62181.png} +0 -0
- /kaa/sprites/{0562f69f-0300-4a2b-8252-63f3e7180e4c.png → 43e53b71-9d69-4f4f-b217-a1abeea8991e.png} +0 -0
- /kaa/sprites/{55c3af20-58dc-4407-a383-312a57417c39.png → 44fab632-3920-4cd8-9967-f7a8a1ee29a0.png} +0 -0
- /kaa/sprites/{645909d7-b960-46c7-b208-db44b6b7feec.png → 45f705f9-58fb-4729-ae55-ee10848678d6.png} +0 -0
- /kaa/sprites/{da48db0d-09d9-47c3-9e08-8b69ad547be6.png → 4678a5fa-5b1c-4fdc-b7c4-e0b820039546.png} +0 -0
- /kaa/sprites/{37215a56-f8e1-4f22-a148-9894136f6ab1.png → 4738974e-60b8-4583-8548-94211c164291.png} +0 -0
- /kaa/sprites/{338d7e71-98ce-4cd1-9954-bf7155150780.png → 474c1678-9c36-495b-aef2-cadbb47b237d.png} +0 -0
- /kaa/sprites/{01256311-237c-476f-96ce-4136dc4bfbd3.png → 47783412-9cc7-4ba0-904d-8cd300222889.png} +0 -0
- /kaa/sprites/{9f7150bc-c0b8-48d6-862c-456aaf518b2b.png → 47ed66a4-9e7e-4646-b554-469dc86322db.png} +0 -0
- /kaa/sprites/{5930140e-effe-4bcf-b0be-c20d3990d833.png → 4d0074ad-6db4-4060-b71a-05c0e36e57a6.png} +0 -0
- /kaa/sprites/{22dc4cfe-8c66-4461-8660-e2d11bbe6154.png → 4f2f8328-a698-40d3-a40f-1f1ae77dc843.png} +0 -0
- /kaa/sprites/{694879e8-ecca-45e2-8ea4-1b447fd43ace.png → 52d0ff68-7a55-4d53-bc20-a1fa05cfe876.png} +0 -0
- /kaa/sprites/{962aa0b9-1dd3-4260-a4fb-c069c26e5a84.png → 52d737a7-5b0b-4ce0-ae3f-5d4048060f12.png} +0 -0
- /kaa/sprites/{87f3c1ae-5117-4871-a7d6-3f5ff0c9f9fb.png → 54a9cae1-62e5-4546-a46a-a5157f51e8b4.png} +0 -0
- /kaa/sprites/{e7f2734f-9fdc-4521-8d7e-8b0fe270a223.png → 56d35e14-ada9-4bfa-a48f-e4601054e7eb.png} +0 -0
- /kaa/sprites/{3b4f90c9-6de7-4ac3-8e41-5f8757bf3f3e.png → 575784c1-7c4a-4484-9f38-aa3c280ce56e.png} +0 -0
- /kaa/sprites/{57c81080-7b53-4286-8fa5-848ad63e4774.png → 577417ee-6635-4cb4-9f28-d1e1b47ae2cd.png} +0 -0
- /kaa/sprites/{72634cb3-4c76-4ca2-8898-ebb837ec19e3.png → 58358122-984b-4c31-91d7-eaf5c8c9353d.png} +0 -0
- /kaa/sprites/{179c0fff-ebd2-4a16-8db2-297552cca218.png → 5a06a662-ffa9-49a9-a86d-136e5983abdd.png} +0 -0
- /kaa/sprites/{2b6d2eb0-bcf7-4bea-b037-6293d9c6d728.png → 5c8eebc5-6d5e-445e-a3d1-66dce2bb6338.png} +0 -0
- /kaa/sprites/{2a8626df-056c-46a2-aaf3-0060a5aef6a3.png → 5d2b03a2-acb6-4bd2-86e8-1b203d1aeaec.png} +0 -0
- /kaa/sprites/{0af1d573-1dc7-427e-997d-173308ea3649.png → 5f02656f-1314-44d0-ae31-a176c24d758c.png} +0 -0
- /kaa/sprites/{84cabff2-7a1b-4018-b74b-46f4db06304f.png → 608c12e2-95dd-4efa-93b2-e648e9583062.png} +0 -0
- /kaa/sprites/{8f7b55d8-0143-4d27-bef8-560d4d510500.png → 647bb09a-13f8-4d54-a8ac-5b534f1a8d87.png} +0 -0
- /kaa/sprites/{1cf03f98-63e9-467c-804d-c74dd97b69bd.png → 6483c406-26cc-44ee-ad12-2a30ec47aedb.png} +0 -0
- /kaa/sprites/{889a4153-b713-49cb-a4d5-e302bcdd002d.png → 67d6a201-dfb9-4c88-b42b-d968cf9a034c.png} +0 -0
- /kaa/sprites/{ea430652-e263-4a15-bb6f-8a8807be6c8f.png → 6a93b483-0848-45e4-a937-51850f296c3d.png} +0 -0
- /kaa/sprites/{e4dc3b35-195c-415f-9484-c2459bd8675a.png → 6b4e4351-b370-48cd-8e8f-ca663d44aa0c.png} +0 -0
- /kaa/sprites/{f6b042a8-a91e-4811-99f9-18bbb5197468.png → 6c961dee-87f3-42f1-acef-9fe7d6be4df1.png} +0 -0
- /kaa/sprites/{ab237c6d-c4d8-4716-8ef7-99b8e995c9a7.png → 6d22b7ee-6e0f-4f5d-96a4-d4cba26a4d04.png} +0 -0
- /kaa/sprites/{d7750f81-de10-4d6f-9cc7-35223bda9d70.png → 6d5a3e08-257c-4394-96a6-e0719a66e5ae.png} +0 -0
- /kaa/sprites/{847226a3-b7d2-4156-b732-9215a3e14f3a.png → 71d0d086-50f1-4f50-bb24-a0190827bd08.png} +0 -0
- /kaa/sprites/{2cec1d6a-9e8c-49b3-b885-0b0d7c4b95ee.png → 71f87e1c-77f1-45c7-bb9c-16f14498682b.png} +0 -0
- /kaa/sprites/{30e12bf1-8fa5-4de1-8d7b-28fa0fec0cb6.png → 737570a7-b8f9-4cd7-b5bd-f40cd51b49f8.png} +0 -0
- /kaa/sprites/{ae1e70bc-f735-4749-8c23-95735b91897a.png → 745ee069-0f22-4b99-9327-513f365eb922.png} +0 -0
- /kaa/sprites/{8bd22fe1-b544-4d2e-b74a-34f3cf0eb512.png → 7601152e-a216-4bf8-92a6-4e3e6ea01d3d.png} +0 -0
- /kaa/sprites/{bfdc9b53-2fe5-43f1-8588-7ab71217d31c.png → 7a23d548-4395-40cc-ac19-4497fa3d9fe2.png} +0 -0
- /kaa/sprites/{96704aa3-b5ad-4e34-bb88-fad766415362.png → 7a7871dd-fd07-4234-bd01-c3c9e41bad45.png} +0 -0
- /kaa/sprites/{43a367e1-91dd-495e-8c30-41903f75a99a.png → 7d3c3a12-8d0f-48a7-9fd4-66db5e58488f.png} +0 -0
- /kaa/sprites/{756f4ca7-acac-48e1-8bcd-1c5cd8937e3a.png → 7d9f8ea3-1fdf-4675-8ddf-38393e235746.png} +0 -0
- /kaa/sprites/{31e3ac2b-ecd4-4c37-88bc-985ef32e73a3.png → 83f258af-35b8-4918-a971-80ea938a854e.png} +0 -0
- /kaa/sprites/{91b30f5e-31b2-4756-a3f7-f0f82a335442.png → 848a6c94-97a5-44f7-b84b-2f3283dc446b.png} +0 -0
- /kaa/sprites/{8ed51be4-815c-4a3d-805e-030fdfa341e2.png → 86a56df9-47ff-4741-822d-5b7e024d1598.png} +0 -0
- /kaa/sprites/{f0462447-5226-4819-a39b-19ab90583f83.png → 8b04d1a8-6cd6-4d2e-91e7-bdc58c46d939.png} +0 -0
- /kaa/sprites/{4a081370-b0a1-4067-8470-e3007cc68a12.png → 8b60ce9f-09c0-48a0-93f0-d51e0aa16afb.png} +0 -0
- /kaa/sprites/{91a50322-52d9-4516-9e46-bc121f20667d.png → 8c59d3ca-baff-4260-aa0a-6cedac1c2771.png} +0 -0
- /kaa/sprites/{f635499a-943d-47da-952a-1feb58daa25b.png → 8d7b4761-2555-4398-bb74-b70de3b75e22.png} +0 -0
- /kaa/sprites/{13cb0309-b713-4725-b10b-26afe46eb9c0.png → 901a2e7a-37f3-4dda-a58b-5a7644ead6b9.png} +0 -0
- /kaa/sprites/{cd0e8663-2ea1-436a-b9fb-3caa0c3ed9e8.png → 9cc77f5e-e7d0-4de4-aeb8-587ab8cb212a.png} +0 -0
- /kaa/sprites/{9991b19c-7330-42c4-9d7d-db3cb00103b7.png → 9e45adeb-4637-4b8b-a687-f1d2cd8c6c18.png} +0 -0
- /kaa/sprites/{5734e48a-1e58-42de-be7b-b7db67db4a01.png → a006054e-61fb-4d2b-a98e-45ce3c663662.png} +0 -0
- /kaa/sprites/{d1ea0ea6-4a6a-4036-b140-922c95a648b5.png → a0f98517-e4cf-422c-b29f-395a55939772.png} +0 -0
- /kaa/sprites/{3aed50a2-d640-4178-9b8a-4dd7973eebf1.png → a94d76ef-db70-45a9-aeca-ba16344cc572.png} +0 -0
- /kaa/sprites/{978873bb-e4d0-451b-9126-6977144f5395.png → afe7f086-723e-4999-a7aa-3342a797d828.png} +0 -0
- /kaa/sprites/{dce410ee-fa56-41c4-b75e-e1bff79cd94f.png → b2036053-36fb-4aa7-8348-e31942731a93.png} +0 -0
- /kaa/sprites/{ad94041c-f30b-40b9-b11a-1a26e9962274.png → b6da02bf-3f43-4ed0-9b13-f15becb42ce9.png} +0 -0
- /kaa/sprites/{a5694c76-3c5d-462e-81d5-1e0e6cef0ec9.png → ba2fd21c-6228-4e2d-b2db-a6d085cb38a6.png} +0 -0
- /kaa/sprites/{cba0646d-dffe-4c5b-a44d-1f8d827624a6.png → bb224de8-828e-4bc5-a986-632c72fc9157.png} +0 -0
- /kaa/sprites/{5bf2a814-df85-4d0a-b4b5-8883ac2ee434.png → bcc6ee72-ad5a-4d5c-b6c7-1b3fdfc5fa81.png} +0 -0
- /kaa/sprites/{edcec31d-d5de-4f22-b666-3e3c656e06d8.png → bebf9f6d-7cca-44c5-9b9f-fa36e29e97b3.png} +0 -0
- /kaa/sprites/{9008fbb2-f23f-424f-9be7-5bae6a3697ab.png → c4d0b0c9-ffbe-4b6c-9bf3-b05919e1a07c.png} +0 -0
- /kaa/sprites/{f32a41a2-c482-41ba-b718-28f048f5148c.png → c893e762-f328-4ef6-b862-5da8eb049f9c.png} +0 -0
- /kaa/sprites/{2d0e9d49-365a-4bcb-a416-38b87defaa3c.png → c944d298-a46b-4799-aea3-eec22fc7d4ac.png} +0 -0
- /kaa/sprites/{5c310fe5-7e92-4167-9eba-6e8e14a2863a.png → d28a18db-0f66-45a6-b3cd-69173ecdd790.png} +0 -0
- /kaa/sprites/{464b1dd8-ca2e-41e9-a5b5-90545c584db7.png → d8d5019c-52e6-4767-a9aa-d8da6ffcbd00.png} +0 -0
- /kaa/sprites/{dd873ac0-ffba-4335-9cf2-2162c6835ed8.png → d9cb2f43-2786-48d8-90f8-8cf1929f6172.png} +0 -0
- /kaa/sprites/{e13fc34b-accc-4986-865d-f8d8410b45e9.png → dbc5db78-81f5-41e6-bdc4-dafaa9173320.png} +0 -0
- /kaa/sprites/{e9310e38-a418-4561-bf33-eb3e6dccf477.png → e2ac106f-edeb-4375-af8c-45f33e9bfae6.png} +0 -0
- /kaa/sprites/{d81b1325-e57a-4f22-93e1-6ad4baa28935.png → e8a33d3f-a4fb-4851-b47a-b5f3d85e882f.png} +0 -0
- /kaa/sprites/{2289d38f-dc98-4310-9f34-4cf5023f8545.png → f7facb3a-1b41-4409-b128-d4ad03245845.png} +0 -0
- {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/WHEEL +0 -0
- {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/entry_points.txt +0 -0
- {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/licenses/LICENSE +0 -0
- {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import zipfile
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any, Dict, List, Tuple
|
|
6
|
+
|
|
7
|
+
from kaa.main.kaa import Kaa
|
|
8
|
+
from kaa.application.services.config_service import ConfigService, ConfigValidationError
|
|
9
|
+
from kaa.application.services.produce_solution_service import ProduceSolutionService
|
|
10
|
+
from kaa.application.services.task_service import TaskService
|
|
11
|
+
from kaa.application.services.update_service import UpdateService
|
|
12
|
+
from kaa.application.services.feedback_service import FeedbackService
|
|
13
|
+
from kaa.application.core.idle_mode import IdleModeManager
|
|
14
|
+
from kaa.config.produce import ProduceSolution
|
|
15
|
+
from kotonebot.errors import ContextNotInitializedError
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
class KaaFacade:
|
|
20
|
+
"""
|
|
21
|
+
The Facade provides a simplified interface to the application's core services,
|
|
22
|
+
acting as a single bridge between the UI (View) and the business logic (Services).
|
|
23
|
+
It orchestrates service interactions and manages application state flow.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, kaa_instance: Kaa):
|
|
27
|
+
# Core services
|
|
28
|
+
self.config_service = ConfigService()
|
|
29
|
+
self.produce_solution_service = ProduceSolutionService()
|
|
30
|
+
self.task_service = TaskService(kaa_instance)
|
|
31
|
+
|
|
32
|
+
# Other existing services
|
|
33
|
+
self.update_service = UpdateService()
|
|
34
|
+
self.feedback_service = FeedbackService()
|
|
35
|
+
self.idle_mgr = self._setup_idle_manager()
|
|
36
|
+
|
|
37
|
+
self._kaa = kaa_instance
|
|
38
|
+
|
|
39
|
+
def _setup_idle_manager(self) -> IdleModeManager:
|
|
40
|
+
"""Initializes and configures the IdleModeManager."""
|
|
41
|
+
|
|
42
|
+
def is_task_running():
|
|
43
|
+
try:
|
|
44
|
+
return self.task_service.is_running() and not self.task_service.is_stopping
|
|
45
|
+
except ContextNotInitializedError:
|
|
46
|
+
return False
|
|
47
|
+
|
|
48
|
+
def is_task_paused():
|
|
49
|
+
try:
|
|
50
|
+
status = self.task_service.get_pause_status()
|
|
51
|
+
return status is True
|
|
52
|
+
except ContextNotInitializedError:
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
return IdleModeManager(
|
|
56
|
+
get_is_running=is_task_running,
|
|
57
|
+
get_is_paused=is_task_paused,
|
|
58
|
+
get_config=lambda: self.config_service.get_options().idle,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# --- Task Control ---
|
|
62
|
+
|
|
63
|
+
def start_all_tasks(self):
|
|
64
|
+
"""Starts all tasks and notifies the idle manager."""
|
|
65
|
+
self.task_service.start_all_tasks()
|
|
66
|
+
self.idle_mgr.notify_on_start()
|
|
67
|
+
|
|
68
|
+
def stop_all_tasks(self):
|
|
69
|
+
"""Stops all running tasks and notifies the idle manager."""
|
|
70
|
+
self.task_service.stop_tasks()
|
|
71
|
+
self.idle_mgr.notify_on_stop()
|
|
72
|
+
|
|
73
|
+
def get_run_status(self) -> Dict[str, Any]:
|
|
74
|
+
"""
|
|
75
|
+
Gets the comprehensive status for the main run button.
|
|
76
|
+
:return: A dictionary with 'text' and 'interactive' keys for the button.
|
|
77
|
+
"""
|
|
78
|
+
tcs = self.task_service
|
|
79
|
+
if not tcs.is_running_all:
|
|
80
|
+
return {"text": "启动", "interactive": True}
|
|
81
|
+
if tcs.is_stopping:
|
|
82
|
+
return {"text": "停止中...", "interactive": False}
|
|
83
|
+
return {"text": "停止", "interactive": True}
|
|
84
|
+
|
|
85
|
+
def get_task_statuses(self) -> List[Tuple[str, str]]:
|
|
86
|
+
"""Gets a list of all tasks and their current statuses."""
|
|
87
|
+
return self.task_service.get_task_statuses()
|
|
88
|
+
|
|
89
|
+
def toggle_pause(self) -> bool | None:
|
|
90
|
+
"""Toggles the pause/resume state of tasks."""
|
|
91
|
+
return self.task_service.toggle_pause()
|
|
92
|
+
|
|
93
|
+
def get_pause_button_status(self) -> Dict[str, Any]:
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
Gets the status for the pause button.
|
|
97
|
+
:return: A dictionary with 'text' and 'interactive' keys for the button.
|
|
98
|
+
"""
|
|
99
|
+
pause_status = self.task_service.get_pause_status()
|
|
100
|
+
is_paused = pause_status is True
|
|
101
|
+
is_stoppable = not self.task_service.is_stopping
|
|
102
|
+
can_pause = self.task_service.is_running() and is_stoppable
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
"text": "恢复" if is_paused else "暂停",
|
|
106
|
+
"interactive": can_pause,
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
def get_task_runtime(self) -> str:
|
|
110
|
+
"""
|
|
111
|
+
Gets the current task runtime as a formatted string.
|
|
112
|
+
:return: A string representing the runtime (e.g., "00:05:23"), or "未运行" if no task is running.
|
|
113
|
+
"""
|
|
114
|
+
runtime = self.task_service.get_task_runtime()
|
|
115
|
+
if runtime is None:
|
|
116
|
+
return "未运行"
|
|
117
|
+
|
|
118
|
+
total_seconds = int(runtime.total_seconds())
|
|
119
|
+
hours = total_seconds // 3600
|
|
120
|
+
minutes = (total_seconds % 3600) // 60
|
|
121
|
+
seconds = total_seconds % 60
|
|
122
|
+
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
|
|
123
|
+
|
|
124
|
+
# --- Configuration ---
|
|
125
|
+
|
|
126
|
+
def get_all_configs(self) -> Tuple[Any, Any]:
|
|
127
|
+
"""
|
|
128
|
+
Gets all configuration objects.
|
|
129
|
+
:return: A tuple of (root_config, current_user_config).
|
|
130
|
+
"""
|
|
131
|
+
return self.config_service.get_root_config(), self.config_service.get_current_user_config()
|
|
132
|
+
|
|
133
|
+
def save_configs(self):
|
|
134
|
+
"""
|
|
135
|
+
Saves the current configuration and re-initializes Kaa.
|
|
136
|
+
The UI is responsible for updating the config object in ConfigService before calling this.
|
|
137
|
+
"""
|
|
138
|
+
try:
|
|
139
|
+
self.config_service.save()
|
|
140
|
+
logger.info("Configuration saved and Kaa re-initialized.")
|
|
141
|
+
return "设置已保存并应用!"
|
|
142
|
+
except ConfigValidationError as e:
|
|
143
|
+
logger.warning(f"Configuration validation failed: {e}")
|
|
144
|
+
raise # Re-raise for the view to handle
|
|
145
|
+
except Exception as e:
|
|
146
|
+
logger.error(f"Failed to save or reload config: {e}", exc_info=True)
|
|
147
|
+
raise RuntimeError("设置已保存,但重新加载失败,请重启程序。") from e
|
|
148
|
+
|
|
149
|
+
# --- Produce Solutions ---
|
|
150
|
+
|
|
151
|
+
def list_produce_solutions(self) -> List[ProduceSolution]:
|
|
152
|
+
"""Lists all produce solutions."""
|
|
153
|
+
return self.produce_solution_service.list_solutions()
|
|
154
|
+
|
|
155
|
+
def get_produce_solution(self, solution_id: str) -> ProduceSolution:
|
|
156
|
+
"""Gets a single produce solution by ID."""
|
|
157
|
+
return self.produce_solution_service.get_solution(solution_id)
|
|
158
|
+
|
|
159
|
+
def create_produce_solution(self, name: str) -> ProduceSolution:
|
|
160
|
+
"""Creates a new produce solution."""
|
|
161
|
+
return self.produce_solution_service.create_solution(name)
|
|
162
|
+
|
|
163
|
+
def delete_produce_solution(self, solution_id: str):
|
|
164
|
+
"""Deletes a produce solution."""
|
|
165
|
+
# Prevent deleting the currently selected solution
|
|
166
|
+
selected_id = self.config_service.get_options().produce.selected_solution_id
|
|
167
|
+
if solution_id == selected_id:
|
|
168
|
+
raise ValueError("不可删除当前正在使用的培育方案。")
|
|
169
|
+
self.produce_solution_service.delete_solution(solution_id)
|
|
170
|
+
|
|
171
|
+
def save_produce_solution(self, solution: ProduceSolution):
|
|
172
|
+
"""Saves a produce solution."""
|
|
173
|
+
self.produce_solution_service.save_solution(solution)
|
|
174
|
+
|
|
175
|
+
# --- Misc ---
|
|
176
|
+
def export_logs_as_zip(self) -> str:
|
|
177
|
+
# This logic was in gr.py, moving it here.
|
|
178
|
+
# It doesn't neatly fit a service, but facade is ok for now.
|
|
179
|
+
if not os.path.exists('logs'):
|
|
180
|
+
return "logs 文件夹不存在"
|
|
181
|
+
timestamp = datetime.now().strftime('%y-%m-%d-%H-%M-%S')
|
|
182
|
+
zip_filename = f'logs-{timestamp}.zip'
|
|
183
|
+
with zipfile.ZipFile(zip_filename, 'w', zipfile.ZIP_DEFLATED, compresslevel=9) as zipf:
|
|
184
|
+
for root, _, files in os.walk('logs'):
|
|
185
|
+
for file in files:
|
|
186
|
+
file_path = os.path.join(root, file)
|
|
187
|
+
arcname = os.path.relpath(file_path, 'logs')
|
|
188
|
+
zipf.write(file_path, arcname)
|
|
189
|
+
return f"已导出到 {zip_filename}"
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import gradio as gr
|
|
3
|
+
|
|
4
|
+
from kaa.application.ui.facade import KaaFacade
|
|
5
|
+
from kaa.application.ui.common import GradioComponents, ConfigBuilderReturnValue
|
|
6
|
+
from kaa.application.ui.views.status_view import StatusView
|
|
7
|
+
from kaa.application.ui.views.task_view import TaskView
|
|
8
|
+
from kaa.application.ui.views.produce_view import ProduceView
|
|
9
|
+
from kaa.application.ui.views.settings_view import SettingsView
|
|
10
|
+
from kaa.application.ui.views.feedback_view import FeedbackView
|
|
11
|
+
from kaa.application.ui.views.update_view import UpdateView
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
class KaaGradioView:
|
|
16
|
+
"""
|
|
17
|
+
The View layer for the kaa application, responsible for rendering the UI
|
|
18
|
+
and delegating all user actions to the Facade.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, facade: KaaFacade):
|
|
22
|
+
self.facade = facade
|
|
23
|
+
# A dataclass to hold all UI components that need to be accessed later
|
|
24
|
+
self.components = GradioComponents()
|
|
25
|
+
# A list to hold all the config builder return values for the save function
|
|
26
|
+
self.config_builders: list[ConfigBuilderReturnValue] = []
|
|
27
|
+
|
|
28
|
+
# Initialize sub-views
|
|
29
|
+
self.status_view = StatusView(facade, self.components)
|
|
30
|
+
self.task_view = TaskView(facade, self.components)
|
|
31
|
+
self.produce_view = ProduceView(facade, self.components)
|
|
32
|
+
self.settings_view = SettingsView(facade, self.components, self.config_builders)
|
|
33
|
+
self.feedback_view = FeedbackView(facade, self.components)
|
|
34
|
+
self.update_view = UpdateView(facade, self.components)
|
|
35
|
+
|
|
36
|
+
def create_ui(self) -> gr.Blocks:
|
|
37
|
+
"""
|
|
38
|
+
Builds the entire Gradio UI and returns the final Blocks object.
|
|
39
|
+
"""
|
|
40
|
+
with gr.Blocks(title=f"琴音小助手 v{self.facade._kaa.version}") as blocks:
|
|
41
|
+
self._create_header()
|
|
42
|
+
with gr.Tabs() as tabs:
|
|
43
|
+
self.components.tabs = tabs
|
|
44
|
+
with gr.Tab("状态", id="status"):
|
|
45
|
+
self.status_view.create_ui()
|
|
46
|
+
with gr.Tab("任务", id="tasks"):
|
|
47
|
+
self.task_view.create_ui()
|
|
48
|
+
with gr.Tab("设置", id="settings"):
|
|
49
|
+
self.settings_view.create_ui()
|
|
50
|
+
with gr.Tab("方案", id="produce"):
|
|
51
|
+
self.produce_view.create_ui()
|
|
52
|
+
with gr.Tab("反馈", id="feedback"):
|
|
53
|
+
self.feedback_view.create_ui()
|
|
54
|
+
# Update tab is created inside the view itself because it's a single tab
|
|
55
|
+
self.update_view.create_ui()
|
|
56
|
+
|
|
57
|
+
self._setup_timers()
|
|
58
|
+
return blocks
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _create_header(self):
|
|
62
|
+
gr.Markdown(f"# 琴音小助手 v{self.facade._kaa.version}")
|
|
63
|
+
|
|
64
|
+
def _setup_timers(self):
|
|
65
|
+
"""Sets up all the UI polling timers."""
|
|
66
|
+
|
|
67
|
+
# Timer for run/pause buttons
|
|
68
|
+
def update_run_buttons():
|
|
69
|
+
run_status = self.facade.get_run_status()
|
|
70
|
+
pause_status = self.facade.get_pause_button_status()
|
|
71
|
+
return {
|
|
72
|
+
self.components.run_btn: gr.Button(value=run_status['text'], interactive=run_status['interactive']),
|
|
73
|
+
self.components.pause_btn: gr.Button(value=pause_status['text'], interactive=pause_status['interactive']),
|
|
74
|
+
}
|
|
75
|
+
gr.Timer(1.0).tick(
|
|
76
|
+
fn=update_run_buttons,
|
|
77
|
+
outputs=[self.components.run_btn, self.components.pause_btn]
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Timer for task status dataframe
|
|
81
|
+
def update_task_status_df():
|
|
82
|
+
statuses = self.facade.get_task_statuses()
|
|
83
|
+
# Convert status keys to display text
|
|
84
|
+
status_map = {
|
|
85
|
+
'pending': '等待中', 'running': '运行中', 'finished': '已完成',
|
|
86
|
+
'error': '出错', 'cancelled': '已取消'
|
|
87
|
+
}
|
|
88
|
+
display_statuses = [[name, status_map.get(status, '未知')] for name, status in statuses]
|
|
89
|
+
return gr.Dataframe(value=display_statuses)
|
|
90
|
+
|
|
91
|
+
gr.Timer(1.0).tick(
|
|
92
|
+
fn=update_task_status_df,
|
|
93
|
+
outputs=[self.components.task_status_df]
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Timer for task runtime
|
|
97
|
+
def update_task_runtime():
|
|
98
|
+
runtime_str = self.facade.get_task_runtime()
|
|
99
|
+
return gr.Textbox(value=runtime_str)
|
|
100
|
+
|
|
101
|
+
gr.Timer(1.0).tick(
|
|
102
|
+
fn=update_task_runtime,
|
|
103
|
+
outputs=[self.components.task_runtime_text]
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Timer for quick-setting checkboxes
|
|
107
|
+
def update_quick_checkboxes():
|
|
108
|
+
opts = self.facade.config_service.get_options()
|
|
109
|
+
|
|
110
|
+
end_game_opts = opts.end_game
|
|
111
|
+
if end_game_opts.shutdown:
|
|
112
|
+
end_action_val = "完成后关机"
|
|
113
|
+
elif end_game_opts.hibernate:
|
|
114
|
+
end_action_val = "完成后休眠"
|
|
115
|
+
else:
|
|
116
|
+
end_action_val = "完成后什么都不做"
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
self.components.quick_checkboxes[0]: gr.Checkbox(value=opts.purchase.enabled),
|
|
120
|
+
self.components.quick_checkboxes[1]: gr.Checkbox(value=opts.assignment.enabled),
|
|
121
|
+
self.components.quick_checkboxes[2]: gr.Checkbox(value=opts.contest.enabled),
|
|
122
|
+
self.components.quick_checkboxes[3]: gr.Checkbox(value=opts.produce.enabled),
|
|
123
|
+
self.components.quick_checkboxes[4]: gr.Checkbox(value=opts.mission_reward.enabled),
|
|
124
|
+
self.components.quick_checkboxes[5]: gr.Checkbox(value=opts.club_reward.enabled),
|
|
125
|
+
self.components.quick_checkboxes[6]: gr.Checkbox(value=opts.activity_funds.enabled),
|
|
126
|
+
self.components.quick_checkboxes[7]: gr.Checkbox(value=opts.presents.enabled),
|
|
127
|
+
self.components.quick_checkboxes[8]: gr.Checkbox(value=opts.capsule_toys.enabled),
|
|
128
|
+
self.components.quick_checkboxes[9]: gr.Checkbox(value=opts.upgrade_support_card.enabled),
|
|
129
|
+
self.components.end_action_dropdown: gr.Dropdown(value=end_action_val),
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
gr.Timer(2.0).tick(
|
|
133
|
+
fn=update_quick_checkboxes,
|
|
134
|
+
outputs=self.components.quick_checkboxes + [self.components.end_action_dropdown]
|
|
135
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import gradio as gr
|
|
2
|
+
from typing import Dict, Any
|
|
3
|
+
from functools import partial
|
|
4
|
+
from kaa.application.ui.facade import KaaFacade
|
|
5
|
+
from kaa.application.ui.common import GradioComponents
|
|
6
|
+
from kaa.errors import FeedbackServiceError
|
|
7
|
+
|
|
8
|
+
class FeedbackView:
|
|
9
|
+
def __init__(self, facade: KaaFacade, components: GradioComponents):
|
|
10
|
+
self.facade = facade
|
|
11
|
+
self.components = components
|
|
12
|
+
|
|
13
|
+
def create_ui(self) -> None:
|
|
14
|
+
gr.Markdown("## 反馈")
|
|
15
|
+
gr.Markdown('脚本报错或者卡住?在这里填写信息可以快速反馈!')
|
|
16
|
+
with gr.Column():
|
|
17
|
+
report_title = gr.Textbox(label="标题", placeholder="用一句话概括问题")
|
|
18
|
+
report_type = gr.Dropdown(label="反馈类型", choices=["bug"], value="bug", interactive=False)
|
|
19
|
+
report_description = gr.Textbox(label="描述", lines=5, placeholder="详细描述问题。例如:什么时候出错、是否每次都出错、出错时的步骤是什么")
|
|
20
|
+
with gr.Row():
|
|
21
|
+
upload_report_btn = gr.Button("上传")
|
|
22
|
+
save_local_report_btn = gr.Button("保存至本地")
|
|
23
|
+
|
|
24
|
+
result_text = gr.Markdown("等待操作\n\n\n")
|
|
25
|
+
|
|
26
|
+
def create_report(title: str, description: str, upload: bool, progress=gr.Progress()):
|
|
27
|
+
|
|
28
|
+
def on_progress(data: Dict[str, Any]):
|
|
29
|
+
progress_val = data['step'] / data['total_steps']
|
|
30
|
+
if data['type'] == 'packing':
|
|
31
|
+
desc = f"({data['step']}/{data['total_steps']}) 正在打包 {data['item']}"
|
|
32
|
+
elif data['type'] == 'uploading':
|
|
33
|
+
desc = f"({data['step']}/{data['total_steps']}) 正在上传 {data['item']}"
|
|
34
|
+
elif data['type'] == 'done':
|
|
35
|
+
if 'url' in data:
|
|
36
|
+
desc = "上传完成"
|
|
37
|
+
else:
|
|
38
|
+
desc = "已保存至本地"
|
|
39
|
+
else:
|
|
40
|
+
desc = "正在处理..."
|
|
41
|
+
progress(progress_val, desc=desc)
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
result = self.facade.feedback_service.report(
|
|
45
|
+
title=title,
|
|
46
|
+
description=description,
|
|
47
|
+
version=self.facade._kaa.version,
|
|
48
|
+
upload=upload,
|
|
49
|
+
on_progress=on_progress
|
|
50
|
+
)
|
|
51
|
+
return result.message
|
|
52
|
+
except FeedbackServiceError as e:
|
|
53
|
+
gr.Error(str(e))
|
|
54
|
+
return f"### 操作失败\n\n{e}"
|
|
55
|
+
|
|
56
|
+
upload_report_btn.click(
|
|
57
|
+
fn=partial(create_report, upload=True),
|
|
58
|
+
inputs=[report_title, report_description],
|
|
59
|
+
outputs=[result_text]
|
|
60
|
+
)
|
|
61
|
+
save_local_report_btn.click(
|
|
62
|
+
fn=partial(create_report, upload=False),
|
|
63
|
+
inputs=[report_title, report_description],
|
|
64
|
+
outputs=[result_text]
|
|
65
|
+
)
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import gradio as gr
|
|
2
|
+
from kaa.application.ui.components.alert import Alert
|
|
3
|
+
from kaa.application.ui.facade import KaaFacade
|
|
4
|
+
from kaa.application.ui.common import GradioComponents
|
|
5
|
+
from kaa.config.produce import ProduceData, ProduceSolution
|
|
6
|
+
from kaa.config.const import ProduceAction, RecommendCardDetectionMode
|
|
7
|
+
from kaa.db.idol_card import IdolCard
|
|
8
|
+
|
|
9
|
+
class ProduceView:
|
|
10
|
+
def __init__(self, facade: KaaFacade, components: GradioComponents):
|
|
11
|
+
self.facade = facade
|
|
12
|
+
self.components = components
|
|
13
|
+
|
|
14
|
+
def create_ui(self):
|
|
15
|
+
"""Creates the content for the 'Produce' tab for managing solutions."""
|
|
16
|
+
gr.Markdown("## 培育方案管理")
|
|
17
|
+
|
|
18
|
+
solutions = self.facade.list_produce_solutions()
|
|
19
|
+
solution_choices = [(f"{sol.name}{f' - {sol.description}' if sol.description else ''}", sol.id) for sol in solutions]
|
|
20
|
+
|
|
21
|
+
solution_dropdown = gr.Dropdown(
|
|
22
|
+
choices=solution_choices,
|
|
23
|
+
value=None,
|
|
24
|
+
label="选择培育方案",
|
|
25
|
+
interactive=True
|
|
26
|
+
)
|
|
27
|
+
self.components.produce_tab_solution_dropdown = solution_dropdown
|
|
28
|
+
|
|
29
|
+
with gr.Row():
|
|
30
|
+
new_solution_btn = gr.Button("新建培育", scale=1)
|
|
31
|
+
delete_solution_btn = gr.Button("删除当前培育", scale=1)
|
|
32
|
+
|
|
33
|
+
# Solution details group
|
|
34
|
+
with gr.Group(visible=False) as solution_settings_group:
|
|
35
|
+
self.components.produce_solution_settings_group = solution_settings_group
|
|
36
|
+
|
|
37
|
+
solution_name = gr.Textbox(label="方案名称", interactive=True)
|
|
38
|
+
self.components.produce_solution_name = solution_name
|
|
39
|
+
|
|
40
|
+
solution_description = gr.Textbox(label="方案描述", interactive=True)
|
|
41
|
+
self.components.produce_solution_description = solution_description
|
|
42
|
+
|
|
43
|
+
produce_mode = gr.Dropdown(choices=["regular", "pro", "master"], label="培育模式", interactive=True)
|
|
44
|
+
self.components.produce_mode = produce_mode
|
|
45
|
+
|
|
46
|
+
idol_choices = [(f'{idol.name}{f" 「{idol.another_name}」" if idol.is_another and idol.another_name else ""}', idol.skin_id) for idol in IdolCard.all()]
|
|
47
|
+
produce_idols = gr.Dropdown(choices=idol_choices, label="选择要培育的偶像", multiselect=False, interactive=True)
|
|
48
|
+
self.components.produce_idols = produce_idols
|
|
49
|
+
|
|
50
|
+
auto_set_memory = gr.Checkbox(label="自动编成回忆", interactive=True)
|
|
51
|
+
self.components.produce_auto_set_memory = auto_set_memory
|
|
52
|
+
|
|
53
|
+
with gr.Group() as memory_sets_group:
|
|
54
|
+
self.components.produce_memory_sets_group = memory_sets_group
|
|
55
|
+
memory_sets = gr.Dropdown(choices=[str(i) for i in range(1, 21)], label="回忆编成编号", multiselect=False, interactive=True)
|
|
56
|
+
self.components.produce_memory_sets = memory_sets
|
|
57
|
+
|
|
58
|
+
auto_set_support = gr.Checkbox(label="自动编成支援卡", interactive=True)
|
|
59
|
+
self.components.produce_auto_set_support = auto_set_support
|
|
60
|
+
|
|
61
|
+
Alert('目前只能自动编成支援卡,无论是否勾选“自动编成支援卡”', variant="info")
|
|
62
|
+
|
|
63
|
+
with gr.Group() as support_card_sets_group:
|
|
64
|
+
self.components.produce_support_card_sets_group = support_card_sets_group
|
|
65
|
+
support_card_sets = gr.Dropdown(choices=[str(i) for i in range(1, 21)], label="支援卡编成编号", multiselect=False, interactive=True)
|
|
66
|
+
self.components.produce_support_card_sets = support_card_sets
|
|
67
|
+
|
|
68
|
+
use_pt_boost = gr.Checkbox(label="使用支援强化 Pt 提升", interactive=True)
|
|
69
|
+
self.components.produce_use_pt_boost = use_pt_boost
|
|
70
|
+
|
|
71
|
+
use_note_boost = gr.Checkbox(label="使用笔记数提升", interactive=True)
|
|
72
|
+
self.components.produce_use_note_boost = use_note_boost
|
|
73
|
+
|
|
74
|
+
follow_producer = gr.Checkbox(label="关注租借了支援卡的制作人", interactive=True)
|
|
75
|
+
self.components.produce_follow_producer = follow_producer
|
|
76
|
+
|
|
77
|
+
self_study_lesson = gr.Dropdown(choices=['dance', 'visual', 'vocal'], label='文化课自习时选项', interactive=True)
|
|
78
|
+
self.components.produce_self_study_lesson = self_study_lesson
|
|
79
|
+
|
|
80
|
+
prefer_lesson_ap = gr.Checkbox(label="SP 课程优先", interactive=True)
|
|
81
|
+
self.components.produce_prefer_lesson_ap = prefer_lesson_ap
|
|
82
|
+
|
|
83
|
+
actions_order = gr.Dropdown(
|
|
84
|
+
choices=[(action.display_name, action.value) for action in ProduceAction],
|
|
85
|
+
label="行动优先级", multiselect=True, interactive=True
|
|
86
|
+
)
|
|
87
|
+
self.components.produce_actions_order = actions_order
|
|
88
|
+
|
|
89
|
+
recommend_card_detection_mode = gr.Dropdown(
|
|
90
|
+
choices=[(mode.display_name, mode.value) for mode in RecommendCardDetectionMode],
|
|
91
|
+
label="推荐卡检测模式", interactive=True
|
|
92
|
+
)
|
|
93
|
+
self.components.produce_recommend_card_detection_mode = recommend_card_detection_mode
|
|
94
|
+
|
|
95
|
+
use_ap_drink = gr.Checkbox(label="AP 不足时自动使用 AP 饮料", interactive=True)
|
|
96
|
+
self.components.produce_use_ap_drink = use_ap_drink
|
|
97
|
+
|
|
98
|
+
skip_commu = gr.Checkbox(label="检测并跳过交流", interactive=True)
|
|
99
|
+
self.components.produce_skip_commu = skip_commu
|
|
100
|
+
@gr.render([skip_commu])
|
|
101
|
+
def _tip(skip):
|
|
102
|
+
if not skip: return
|
|
103
|
+
Alert(
|
|
104
|
+
variant="warning",
|
|
105
|
+
value="建议关闭此处设置,转而开启游戏内快进所有交流,效果更佳。",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
save_solution_btn = gr.Button("保存培育方案", variant="primary")
|
|
109
|
+
|
|
110
|
+
# --- Event Handlers ---
|
|
111
|
+
|
|
112
|
+
all_detail_components = [
|
|
113
|
+
solution_settings_group, solution_name, solution_description, produce_mode, produce_idols,
|
|
114
|
+
auto_set_memory, memory_sets_group, memory_sets, auto_set_support, support_card_sets_group,
|
|
115
|
+
support_card_sets, use_pt_boost, use_note_boost, follow_producer, self_study_lesson,
|
|
116
|
+
prefer_lesson_ap, actions_order, recommend_card_detection_mode, use_ap_drink, skip_commu
|
|
117
|
+
]
|
|
118
|
+
self.components.produce_all_detail_components = all_detail_components
|
|
119
|
+
|
|
120
|
+
def on_new_solution():
|
|
121
|
+
"""Creates a new solution and refreshes the dropdowns."""
|
|
122
|
+
new_solution = self.facade.create_produce_solution("新培育方案")
|
|
123
|
+
solutions = self.facade.list_produce_solutions()
|
|
124
|
+
choices = [(f"{s.name}{f' - {s.description}' if s.description else ''}", s.id) for s in solutions]
|
|
125
|
+
gr.Success("新培育方案创建成功")
|
|
126
|
+
# TODO: 创建一个 state 用于记录当前选中的培育 id
|
|
127
|
+
# Return an update for the solution dropdown (use gr.update for better typing)
|
|
128
|
+
return gr.update(choices=choices, value=new_solution.id)
|
|
129
|
+
|
|
130
|
+
def on_delete_solution(solution_id):
|
|
131
|
+
"""Deletes the selected solution and refreshes dropdowns."""
|
|
132
|
+
if not solution_id:
|
|
133
|
+
gr.Warning("请先选择要删除的培育方案")
|
|
134
|
+
# No change to dropdown
|
|
135
|
+
return gr.update()
|
|
136
|
+
try:
|
|
137
|
+
self.facade.delete_produce_solution(solution_id)
|
|
138
|
+
solutions = self.facade.list_produce_solutions()
|
|
139
|
+
choices = [(f"{s.name}{f' - {s.description}' if s.description else ''}", s.id) for s in solutions]
|
|
140
|
+
gr.Success("培育方案删除成功")
|
|
141
|
+
return gr.update(choices=choices, value=None)
|
|
142
|
+
except ValueError as e:
|
|
143
|
+
gr.Warning(str(e))
|
|
144
|
+
return gr.update()
|
|
145
|
+
except Exception as e:
|
|
146
|
+
gr.Error(f"删除失败: {e}")
|
|
147
|
+
return gr.update()
|
|
148
|
+
|
|
149
|
+
def on_save_solution(solution_id, name, desc, mode, idol, auto_mem, mem_set, auto_sup, sup_set, pt_boost, note_boost, follow, study, pref_ap, actions, detect_mode, ap_drink, skip):
|
|
150
|
+
if not solution_id:
|
|
151
|
+
gr.Warning("没有选择要保存的方案")
|
|
152
|
+
return gr.update()
|
|
153
|
+
try:
|
|
154
|
+
produce_data = ProduceData(
|
|
155
|
+
mode=mode, idol=idol,
|
|
156
|
+
auto_set_memory=auto_mem, memory_set=int(mem_set) if mem_set else None,
|
|
157
|
+
auto_set_support_card=auto_sup, support_card_set=int(sup_set) if sup_set else None,
|
|
158
|
+
use_pt_boost=pt_boost, use_note_boost=note_boost, follow_producer=follow,
|
|
159
|
+
self_study_lesson=study, prefer_lesson_ap=pref_ap,
|
|
160
|
+
actions_order=[ProduceAction(a) for a in actions],
|
|
161
|
+
recommend_card_detection_mode=RecommendCardDetectionMode(detect_mode),
|
|
162
|
+
use_ap_drink=ap_drink, skip_commu=skip
|
|
163
|
+
)
|
|
164
|
+
solution = ProduceSolution(id=solution_id, name=name, description=desc, data=produce_data)
|
|
165
|
+
self.facade.save_produce_solution(solution)
|
|
166
|
+
gr.Success("培育方案保存成功")
|
|
167
|
+
# Refresh dropdowns to reflect name/desc changes
|
|
168
|
+
solutions = self.facade.list_produce_solutions()
|
|
169
|
+
choices = [(f"{s.name} - {s.description or '无描述'}", s.id) for s in solutions]
|
|
170
|
+
return gr.update(choices=choices, value=solution_id)
|
|
171
|
+
except Exception as e:
|
|
172
|
+
gr.Error(f"保存失败: {e}")
|
|
173
|
+
return gr.update()
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# --- UI Callbacks ---
|
|
177
|
+
|
|
178
|
+
solution_dropdown.change(
|
|
179
|
+
fn=self.update_produce_solution_details,
|
|
180
|
+
inputs=[solution_dropdown],
|
|
181
|
+
outputs=all_detail_components
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
auto_set_memory.change(fn=lambda x: gr.update(visible=not x), inputs=[auto_set_memory], outputs=[memory_sets_group])
|
|
185
|
+
auto_set_support.change(fn=lambda x: gr.update(visible=not x), inputs=[auto_set_support], outputs=[support_card_sets_group])
|
|
186
|
+
|
|
187
|
+
new_solution_btn.click(fn=on_new_solution, outputs=[solution_dropdown])
|
|
188
|
+
delete_solution_btn.click(fn=on_delete_solution, inputs=[solution_dropdown], outputs=[solution_dropdown])
|
|
189
|
+
|
|
190
|
+
save_inputs = [
|
|
191
|
+
solution_dropdown, solution_name, solution_description, produce_mode, produce_idols,
|
|
192
|
+
auto_set_memory, memory_sets, auto_set_support, support_card_sets,
|
|
193
|
+
use_pt_boost, use_note_boost, follow_producer, self_study_lesson,
|
|
194
|
+
prefer_lesson_ap, actions_order, recommend_card_detection_mode,
|
|
195
|
+
use_ap_drink, skip_commu
|
|
196
|
+
]
|
|
197
|
+
save_solution_btn.click(fn=on_save_solution, inputs=save_inputs, outputs=[solution_dropdown])
|
|
198
|
+
|
|
199
|
+
def update_produce_solution_details(self, solution_id: str):
|
|
200
|
+
"""Updates the produce solution detail view when the selected solution changes."""
|
|
201
|
+
if not solution_id:
|
|
202
|
+
# Return a default/empty state for all components in the form
|
|
203
|
+
return {
|
|
204
|
+
self.components.produce_solution_settings_group: gr.Group(visible=False),
|
|
205
|
+
self.components.produce_solution_name: gr.Textbox(value=""),
|
|
206
|
+
self.components.produce_solution_description: gr.Textbox(value=""),
|
|
207
|
+
self.components.produce_mode: gr.Dropdown(value=None),
|
|
208
|
+
self.components.produce_idols: gr.Dropdown(value=None),
|
|
209
|
+
self.components.produce_auto_set_memory: gr.Checkbox(value=False),
|
|
210
|
+
self.components.produce_memory_sets_group: gr.Group(visible=True),
|
|
211
|
+
self.components.produce_memory_sets: gr.Dropdown(value=None),
|
|
212
|
+
self.components.produce_auto_set_support: gr.Checkbox(value=False),
|
|
213
|
+
self.components.produce_support_card_sets_group: gr.Group(visible=True),
|
|
214
|
+
self.components.produce_support_card_sets: gr.Dropdown(value=None),
|
|
215
|
+
self.components.produce_use_pt_boost: gr.Checkbox(value=False),
|
|
216
|
+
self.components.produce_use_note_boost: gr.Checkbox(value=False),
|
|
217
|
+
self.components.produce_follow_producer: gr.Checkbox(value=False),
|
|
218
|
+
self.components.produce_self_study_lesson: gr.Dropdown(value=None),
|
|
219
|
+
self.components.produce_prefer_lesson_ap: gr.Checkbox(value=False),
|
|
220
|
+
self.components.produce_actions_order: gr.Dropdown(value=[]),
|
|
221
|
+
self.components.produce_recommend_card_detection_mode: gr.Dropdown(value=None),
|
|
222
|
+
self.components.produce_use_ap_drink: gr.Checkbox(value=False),
|
|
223
|
+
self.components.produce_skip_commu: gr.Checkbox(value=False),
|
|
224
|
+
}
|
|
225
|
+
try:
|
|
226
|
+
solution = self.facade.get_produce_solution(solution_id)
|
|
227
|
+
return {
|
|
228
|
+
self.components.produce_solution_settings_group: gr.Group(visible=True),
|
|
229
|
+
self.components.produce_solution_name: gr.Textbox(value=solution.name),
|
|
230
|
+
self.components.produce_solution_description: gr.Textbox(value=solution.description),
|
|
231
|
+
self.components.produce_mode: gr.Dropdown(value=solution.data.mode),
|
|
232
|
+
self.components.produce_idols: gr.Dropdown(value=solution.data.idol),
|
|
233
|
+
self.components.produce_auto_set_memory: gr.Checkbox(value=solution.data.auto_set_memory),
|
|
234
|
+
self.components.produce_memory_sets_group: gr.Group(visible=not solution.data.auto_set_memory),
|
|
235
|
+
self.components.produce_memory_sets: gr.Dropdown(value=str(solution.data.memory_set) if solution.data.memory_set else None),
|
|
236
|
+
self.components.produce_auto_set_support: gr.Checkbox(value=solution.data.auto_set_support_card),
|
|
237
|
+
self.components.produce_support_card_sets_group: gr.Group(visible=not solution.data.auto_set_support_card),
|
|
238
|
+
self.components.produce_support_card_sets: gr.Dropdown(value=str(solution.data.support_card_set) if solution.data.support_card_set else None),
|
|
239
|
+
self.components.produce_use_pt_boost: gr.Checkbox(value=solution.data.use_pt_boost),
|
|
240
|
+
self.components.produce_use_note_boost: gr.Checkbox(value=solution.data.use_note_boost),
|
|
241
|
+
self.components.produce_follow_producer: gr.Checkbox(value=solution.data.follow_producer),
|
|
242
|
+
self.components.produce_self_study_lesson: gr.Dropdown(value=solution.data.self_study_lesson),
|
|
243
|
+
self.components.produce_prefer_lesson_ap: gr.Checkbox(value=solution.data.prefer_lesson_ap),
|
|
244
|
+
self.components.produce_actions_order: gr.Dropdown(value=[action.value for action in solution.data.actions_order]),
|
|
245
|
+
self.components.produce_recommend_card_detection_mode: gr.Dropdown(value=solution.data.recommend_card_detection_mode.value),
|
|
246
|
+
self.components.produce_use_ap_drink: gr.Checkbox(value=solution.data.use_ap_drink),
|
|
247
|
+
self.components.produce_skip_commu: gr.Checkbox(value=solution.data.skip_commu),
|
|
248
|
+
}
|
|
249
|
+
except Exception as e:
|
|
250
|
+
gr.Error(f"加载培育方案失败: {e}")
|
|
251
|
+
return {self.components.produce_solution_settings_group: gr.Group(visible=False)}
|