kotones-auto-assistant/kotonebot/tasks/common.py

433 lines
19 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
from importlib import resources
from typing import Literal, Dict, NamedTuple, Tuple, TypeVar, Generic
from enum import IntEnum, Enum
from pydantic import BaseModel, ConfigDict
# TODO: from kotonebot import config (context) 会和 kotonebot.config 冲突
from kotonebot.backend.context import config
T = TypeVar('T')
class ConfigEnum(Enum):
def display(self) -> str:
return self.value[1]
class Priority(IntEnum):
START_GAME = 1
DEFAULT = 0
CLAIM_MISSION_REWARD = -1
class APShopItems(IntEnum):
PRODUCE_PT_UP = 0
"""获取支援强化 Pt 提升"""
PRODUCE_NOTE_UP = 1
"""获取笔记数提升"""
RECHALLENGE = 2
"""再挑战券"""
REGENERATE_MEMORY = 3
"""回忆再生成券"""
class PIdol(Enum):
"""P偶像"""
倉本千奈_Campusmode = ["倉本千奈", "Campus mode!!"]
倉本千奈_WonderScale = ["倉本千奈", "Wonder Scale"]
倉本千奈_ようこそ初星温泉 = ["倉本千奈", "ようこそ初星温泉"]
倉本千奈_仮装狂騒曲 = ["倉本千奈", "仮装狂騒曲"]
倉本千奈_初心 = ["倉本千奈", "初心"]
倉本千奈_学園生活 = ["倉本千奈", "学園生活"]
倉本千奈_日々_発見的ステップ = ["倉本千奈", "日々、発見的ステップ!"]
倉本千奈_胸を張って一歩ずつ = ["倉本千奈", "胸を張って一歩ずつ"]
十王星南_Campusmode = ["十王星南", "Campus mode!!"]
十王星南_一番星 = ["十王星南", "一番星"]
十王星南_学園生活 = ["十王星南", "学園生活"]
十王星南_小さな野望 = ["十王星南", "小さな野望"]
姫崎莉波_clumsytrick = ["姫崎莉波", "clumsy trick"]
姫崎莉波_私らしさのはじまり = ["姫崎莉波", "『私らしさ』のはじまり"]
姫崎莉波_キミとセミブルー = ["姫崎莉波", "キミとセミブルー"]
姫崎莉波_Campusmode = ["姫崎莉波", "Campus mode!!"]
姫崎莉波_LUV = ["姫崎莉波", "L.U.V"]
姫崎莉波_ようこそ初星温泉 = ["姫崎莉波", "ようこそ初星温泉"]
姫崎莉波_ハッピーミルフィーユ = ["姫崎莉波", "ハッピーミルフィーユ"]
姫崎莉波_初心 = ["姫崎莉波", "初心"]
姫崎莉波_学園生活 = ["姫崎莉波", "学園生活"]
月村手毬_Lunasaymaybe = ["月村手毬", "Luna say maybe"]
月村手毬_一匹狼 = ["月村手毬", "一匹狼"]
月村手毬_Campusmode = ["月村手毬", "Campus mode!!"]
月村手毬_アイヴイ = ["月村手毬", "アイヴイ"]
月村手毬_初声 = ["月村手毬", "初声"]
月村手毬_学園生活 = ["月村手毬", "学園生活"]
月村手毬_仮装狂騒曲 = ["月村手毬", "仮装狂騒曲"]
有村麻央_Fluorite = ["有村麻央", "Fluorite"]
有村麻央_はじまりはカッコよく = ["有村麻央", "はじまりはカッコよく"]
有村麻央_Campusmode = ["有村麻央", "Campus mode!!"]
有村麻央_FeelJewelDream = ["有村麻央", "Feel Jewel Dream"]
有村麻央_キミとセミブルー = ["有村麻央", "キミとセミブルー"]
有村麻央_初恋 = ["有村麻央", "初恋"]
有村麻央_学園生活 = ["有村麻央", "学園生活"]
篠泽广_コントラスト = ["篠泽广", "コントラスト"]
篠泽广_一番向いていないこと = ["篠泽广", "一番向いていないこと"]
篠泽广_光景 = ["篠泽广", "光景"]
篠泽广_Campusmode = ["篠泽广", "Campus mode!!"]
篠泽广_仮装狂騒曲 = ["篠泽广", "仮装狂騒曲"]
篠泽广_ハッピーミルフィーユ = ["篠泽广", "ハッピーミルフィーユ"]
篠泽广_初恋 = ["篠泽广", "初恋"]
篠泽广_学園生活 = ["篠泽广", "学園生活"]
紫云清夏_TameLieOneStep = ["紫云清夏", "Tame-Lie-One-Step"]
紫云清夏_カクシタワタシ = ["紫云清夏", "カクシタワタシ"]
紫云清夏_夢へのリスタート = ["紫云清夏", "夢へのリスタート"]
紫云清夏_Campusmode = ["紫云清夏", "Campus mode!!"]
紫云清夏_キミとセミブルー = ["紫云清夏", "キミとセミブルー"]
紫云清夏_初恋 = ["紫云清夏", "初恋"]
紫云清夏_学園生活 = ["紫云清夏", "学園生活"]
花海佑芽_WhiteNightWhiteWish = ["花海佑芽", "White Night! White Wish!"]
花海佑芽_学園生活 = ["花海佑芽", "学園生活"]
花海佑芽_Campusmode = ["花海佑芽", "Campus mode!!"]
花海佑芽_TheRollingRiceball = ["花海佑芽", "The Rolling Riceball"]
花海佑芽_アイドル_はじめっ = ["花海佑芽", "アイドル、はじめっ!"]
花海咲季_BoomBoomPow = ["花海咲季", "Boom Boom Pow"]
花海咲季_Campusmode = ["花海咲季", "Campus mode!!"]
花海咲季_FightingMyWay = ["花海咲季", "Fighting My Way"]
花海咲季_わたしが一番 = ["花海咲季", "わたしが一番!"]
花海咲季_冠菊 = ["花海咲季", "冠菊"]
花海咲季_初声 = ["花海咲季", "初声"]
花海咲季_古今東西ちょちょいのちょい = ["花海咲季", "古今東西ちょちょいのちょい"]
花海咲季_学園生活 = ["花海咲季", "学園生活"]
葛城リーリヤ_一つ踏み出した先に = ["葛城リーリヤ", "一つ踏み出した先に"]
葛城リーリヤ_白線 = ["葛城リーリヤ", "白線"]
葛城リーリヤ_Campusmode = ["葛城リーリヤ", "Campus mode!!"]
葛城リーリヤ_WhiteNightWhiteWish = ["葛城リーリヤ", "White Night! White Wish!"]
葛城リーリヤ_冠菊 = ["葛城リーリヤ", "冠菊"]
葛城リーリヤ_初心 = ["葛城リーリヤ", "初心"]
葛城リーリヤ_学園生活 = ["葛城リーリヤ", "学園生活"]
藤田ことね_カワイイ_はじめました = ["藤田ことね", "カワイイ", "はじめました"]
藤田ことね_世界一可愛い私 = ["藤田ことね", "世界一可愛い私"]
藤田ことね_Campusmode = ["藤田ことね", "Campus mode!!"]
藤田ことね_YellowBigBang = ["藤田ことね", "Yellow Big Bang"]
藤田ことね_WhiteNightWhiteWish = ["藤田ことね", "White Night! White Wish!"]
藤田ことね_冠菊 = ["藤田ことね", "冠菊"]
藤田ことね_初声 = ["藤田ことね", "初声"]
藤田ことね_学園生活 = ["藤田ことね", "学園生活"]
class DailyMoneyShopItems(IntEnum):
"""日常商店物品"""
Recommendations = -1
"""所有推荐商品"""
LessonNote = 0
"""レッスンノート"""
VeteranNote = 1
"""ベテランノート"""
SupportEnhancementPt = 2
"""サポート強化Pt 支援强化Pt"""
SenseNoteVocal = 3
"""センスノート(ボーカル)感性笔记(声乐)"""
SenseNoteDance = 4
"""センスノート(ダンス)感性笔记(舞蹈)"""
SenseNoteVisual = 5
"""センスノート(ビジュアル)感性笔记(形象)"""
LogicNoteVocal = 6
"""ロジックノート(ボーカル)理性笔记(声乐)"""
LogicNoteDance = 7
"""ロジックノート(ダンス)理性笔记(舞蹈)"""
LogicNoteVisual = 8
"""ロジックノート(ビジュアル)理性笔记(形象)"""
AnomalyNoteVocal = 9
"""アノマリーノート(ボーカル)非凡笔记(声乐)"""
AnomalyNoteDance = 10
"""アノマリーノート(ダンス)非凡笔记(舞蹈)"""
AnomalyNoteVisual = 11
"""アノマリーノート(ビジュアル)非凡笔记(形象)"""
RechallengeTicket = 12
"""再挑戦チケット 重新挑战券"""
RecordKey = 13
"""記録の鍵 解锁交流的物品"""
# 碎片
IdolPiece_倉本千奈_WonderScale = 14
"""倉本千奈 WonderScale 碎片"""
IdolPiece_篠泽广_光景 = 15
"""篠泽广 光景 碎片"""
IdolPiece_紫云清夏_TameLieOneStep = 16
"""紫云清夏 Tame-Lie-One-Step 碎片"""
IdolPiece_葛城リーリヤ_白線 = 17
"""葛城リーリヤ 白線 碎片"""
IdolPiece_姫崎薪波_cIclumsy_trick = 18
"""姫崎薪波 cIclumsy trick 碎片"""
IdolPiece_花海咲季_FightingMyWay = 19
"""花海咲季 FightingMyWay 碎片"""
IdolPiece_藤田ことね_世界一可愛い私 = 20
"""藤田ことね 世界一可愛い私 碎片"""
IdolPiece_花海佑芽_TheRollingRiceball = 21
"""花海佑芽 The Rolling Riceball 碎片"""
IdolPiece_月村手毬_LunaSayMaybe = 22
"""月村手毬 Luna say maybe 碎片"""
@classmethod
def to_ui_text(cls, item: "DailyMoneyShopItems") -> str:
"""获取枚举值对应的UI显示文本"""
MAP = {
cls.Recommendations: "所有推荐商品",
cls.LessonNote: "课程笔记",
cls.VeteranNote: "老手笔记",
cls.SupportEnhancementPt: "支援强化点数",
cls.SenseNoteVocal: "感性笔记(声乐)",
cls.SenseNoteDance: "感性笔记(舞蹈)",
cls.SenseNoteVisual: "感性笔记(形象)",
cls.LogicNoteVocal: "理性笔记(声乐)",
cls.LogicNoteDance: "理性笔记(舞蹈)",
cls.LogicNoteVisual: "理性笔记(形象)",
cls.AnomalyNoteVocal: "非凡笔记(声乐)",
cls.AnomalyNoteDance: "非凡笔记(舞蹈)",
cls.AnomalyNoteVisual: "非凡笔记(形象)",
cls.RechallengeTicket: "重新挑战券",
cls.RecordKey: "记录钥匙",
cls.IdolPiece_倉本千奈_WonderScale: "倉本千奈 WonderScale 碎片",
cls.IdolPiece_篠泽广_光景: "篠泽广 光景 碎片",
cls.IdolPiece_紫云清夏_TameLieOneStep: "紫云清夏 Tame-Lie-One-Step 碎片",
cls.IdolPiece_葛城リーリヤ_白線: "葛城リーリヤ 白線 碎片",
cls.IdolPiece_姫崎薪波_cIclumsy_trick: "姫崎薪波 cIclumsy trick 碎片",
cls.IdolPiece_花海咲季_FightingMyWay: "花海咲季 FightingMyWay 碎片",
cls.IdolPiece_藤田ことね_世界一可愛い私: "藤田ことね 世界一可愛い私 碎片",
cls.IdolPiece_花海佑芽_TheRollingRiceball: "花海佑芽 The Rolling Riceball 碎片",
cls.IdolPiece_月村手毬_LunaSayMaybe: "月村手毬 Luna say maybe 碎片"
}
return MAP.get(item, str(item))
@classmethod
def all(cls) -> list[tuple[str, 'DailyMoneyShopItems']]:
"""获取所有枚举值及其对应的UI显示文本"""
return [(cls.to_ui_text(item), item) for item in cls]
def to_resource(self):
from . import R
match self:
case DailyMoneyShopItems.Recommendations:
return R.Daily.TextShopRecommended
case DailyMoneyShopItems.LessonNote:
return R.Shop.ItemLessonNote
case DailyMoneyShopItems.VeteranNote:
return R.Shop.ItemVeteranNote
case DailyMoneyShopItems.SupportEnhancementPt:
return R.Shop.ItemSupportEnhancementPt
case DailyMoneyShopItems.SenseNoteVocal:
return R.Shop.ItemSenseNoteVocal
case DailyMoneyShopItems.SenseNoteDance:
return R.Shop.ItemSenseNoteDance
case DailyMoneyShopItems.SenseNoteVisual:
return R.Shop.ItemSenseNoteVisual
case DailyMoneyShopItems.LogicNoteVocal:
return R.Shop.ItemLogicNoteVocal
case DailyMoneyShopItems.LogicNoteDance:
return R.Shop.ItemLogicNoteDance
case DailyMoneyShopItems.LogicNoteVisual:
return R.Shop.ItemLogicNoteVisual
case DailyMoneyShopItems.AnomalyNoteVocal:
return R.Shop.ItemAnomalyNoteVocal
case DailyMoneyShopItems.AnomalyNoteDance:
return R.Shop.ItemAnomalyNoteDance
case DailyMoneyShopItems.AnomalyNoteVisual:
return R.Shop.ItemAnomalyNoteVisual
case DailyMoneyShopItems.RechallengeTicket:
return R.Shop.ItemRechallengeTicket
case DailyMoneyShopItems.RecordKey:
return R.Shop.ItemRecordKey
case DailyMoneyShopItems.IdolPiece_倉本千奈_WonderScale:
return R.Shop.IdolPiece.倉本千奈_WonderScale
case DailyMoneyShopItems.IdolPiece_篠泽广_光景:
return R.Shop.IdolPiece.篠泽广_光景
case DailyMoneyShopItems.IdolPiece_紫云清夏_TameLieOneStep:
return R.Shop.IdolPiece.紫云清夏_TameLieOneStep
case DailyMoneyShopItems.IdolPiece_葛城リーリヤ_白線:
return R.Shop.IdolPiece.葛城リーリヤ_白線
case DailyMoneyShopItems.IdolPiece_姫崎薪波_cIclumsy_trick:
return R.Shop.IdolPiece.姫崎薪波_cIclumsy_trick
case DailyMoneyShopItems.IdolPiece_花海咲季_FightingMyWay:
return R.Shop.IdolPiece.花海咲季_FightingMyWay
case DailyMoneyShopItems.IdolPiece_藤田ことね_世界一可愛い私:
return R.Shop.IdolPiece.藤田ことね_世界一可愛い私
case DailyMoneyShopItems.IdolPiece_花海佑芽_TheRollingRiceball:
return R.Shop.IdolPiece.花海佑芽_TheRollingRiceball
case DailyMoneyShopItems.IdolPiece_月村手毬_LunaSayMaybe:
return R.Shop.IdolPiece.月村手毬_LunaSayMaybe
case _:
raise ValueError(f"Unknown daily shop item: {self}")
class ConfigBaseModel(BaseModel):
model_config = ConfigDict(use_attribute_docstrings=True)
class PurchaseConfig(ConfigBaseModel):
enabled: bool = False
"""是否启用商店购买"""
money_enabled: bool = False
"""是否启用金币购买"""
money_items: list[DailyMoneyShopItems] = []
"""金币商店要购买的物品"""
money_refresh_on: Literal['never', 'not_found', 'always'] = 'never'
"""
金币商店刷新逻辑。
* never: 从不刷新。
* not_found: 仅当要购买的物品不存在时刷新。
* always: 总是刷新。
"""
ap_enabled: bool = False
"""是否启用AP购买"""
ap_items: list[Literal[0, 1, 2, 3]] = []
"""AP商店要购买的物品"""
class ActivityFundsConfig(ConfigBaseModel):
enabled: bool = False
"""是否启用收取活动费"""
class PresentsConfig(ConfigBaseModel):
enabled: bool = False
"""是否启用收取礼物"""
class AssignmentConfig(ConfigBaseModel):
enabled: bool = False
"""是否启用工作"""
mini_live_reassign_enabled: bool = False
"""是否启用重新分配 MiniLive"""
mini_live_duration: Literal[4, 6, 12] = 12
"""MiniLive 工作时长"""
online_live_reassign_enabled: bool = False
"""是否启用重新分配 OnlineLive"""
online_live_duration: Literal[4, 6, 12] = 12
"""OnlineLive 工作时长"""
class ContestConfig(ConfigBaseModel):
enabled: bool = False
"""是否启用竞赛"""
class ProduceAction(Enum):
RECOMMENDED = 'recommended'
VISUAL = 'visual'
VOCAL = 'vocal'
DANCE = 'dance'
# VISUAL_SP = 'visual_sp'
# VOCAL_SP = 'vocal_sp'
# DANCE_SP = 'dance_sp'
OUTING = 'outing'
STUDY = 'study'
ALLOWANCE = 'allowance'
REST = 'rest'
@property
def display_name(self):
MAP = {
ProduceAction.RECOMMENDED: '推荐行动',
ProduceAction.VISUAL: '形象课程',
ProduceAction.VOCAL: '声乐课程',
ProduceAction.DANCE: '舞蹈课程',
ProduceAction.OUTING: '外出(おでかけ)',
ProduceAction.STUDY: '自习(授業)',
ProduceAction.ALLOWANCE: '活动支给(活動支給)',
ProduceAction.REST: '休息',
}
return MAP[self]
class ProduceConfig(ConfigBaseModel):
enabled: bool = False
"""是否启用培育"""
mode: Literal['regular', 'pro'] = 'regular'
"""
培育模式。
进行一次 REGULAR 培育需要 ~30min进行一次 PRO 培育需要 ~1h。
"""
produce_count: int = 1
"""培育的次数。"""
idols: list[PIdol] = []
"""
要培育的偶像。将会按顺序循环选择培育。
若未选择任何偶像,则使用游戏默认选择的偶像(为上次培育偶像)。
"""
memory_sets: list[int] = []
"""要使用的回忆编成编号,从 1 开始。将会按顺序循环选择使用。"""
support_card_sets: list[int] = []
"""要使用的支援卡编成编号,从 1 开始。将会按顺序循环选择使用。"""
auto_set_memory: bool = False
"""是否自动编成回忆。此选项优先级高于回忆编成编号。"""
auto_set_support_card: bool = False
"""是否自动编成支援卡。此选项优先级高于支援卡编成编号。"""
use_pt_boost: bool = False
"""是否使用支援强化 Pt 提升。"""
use_note_boost: bool = False
"""是否使用笔记数提升。"""
follow_producer: bool = False
"""是否关注租借了支援卡的制作人。"""
self_study_lesson: Literal['dance', 'visual', 'vocal'] = 'dance'
"""自习课类型。"""
prefer_lesson_ap: bool = False
"""
优先 SP 课程。
启用后,若出现 SP 课程,则会优先执行 SP 课程,而不是推荐课程。
若出现多个 SP 课程,随机选择一个。
"""
actions_order: list[ProduceAction] = [
ProduceAction.RECOMMENDED,
ProduceAction.VISUAL,
ProduceAction.VOCAL,
ProduceAction.DANCE,
ProduceAction.ALLOWANCE,
ProduceAction.OUTING,
ProduceAction.STUDY,
ProduceAction.REST,
]
"""
行动优先级
每一周的行动将会按这里设置的优先级执行。
"""
class MissionRewardConfig(ConfigBaseModel):
enabled: bool = False
"""是否启用领取任务奖励"""
class BaseConfig(ConfigBaseModel):
purchase: PurchaseConfig = PurchaseConfig()
"""商店购买配置"""
activity_funds: ActivityFundsConfig = ActivityFundsConfig()
"""活动费配置"""
presents: PresentsConfig = PresentsConfig()
"""收取礼物配置"""
assignment: AssignmentConfig = AssignmentConfig()
"""工作配置"""
contest: ContestConfig = ContestConfig()
"""竞赛配置"""
produce: ProduceConfig = ProduceConfig()
"""培育配置"""
mission_reward: MissionRewardConfig = MissionRewardConfig()
"""领取任务奖励配置"""
def conf() -> BaseConfig:
"""获取当前配置数据"""
c = config.to(BaseConfig).current
return c.options
def sprite_path(path: str) -> str:
standalone = os.path.join('kotonebot/tasks/sprites', path)
if os.path.exists(standalone):
return standalone
return str(resources.files('kotonebot.tasks.sprites') / path)
if __name__ == '__main__':
print(PurchaseConfig.model_fields['money_refresh_on'].description)