mirror of
https://github.com/PaiGramTeam/SIMNet.git
synced 2024-11-25 23:51:12 +00:00
420 lines
15 KiB
Python
420 lines
15 KiB
Python
from datetime import timedelta, datetime
|
|
from enum import Enum
|
|
from typing import Union, Literal, Tuple, List, Optional, Dict, Any
|
|
|
|
from pydantic import Field, root_validator
|
|
|
|
from simnet.models.base import APIModel
|
|
|
|
__all__ = [
|
|
"TaskRewardStatus",
|
|
"TaskReward",
|
|
"AttendanceRewardStatus",
|
|
"AttendanceReward",
|
|
"DailyTask",
|
|
"Expedition",
|
|
"Notes",
|
|
"ExpeditionWidget",
|
|
"NotesWidget",
|
|
"NotesOverseaWidget",
|
|
"NotesOverseaWidgetResin",
|
|
"NotesOverseaWidgetRealm",
|
|
]
|
|
|
|
|
|
def _process_timedelta(time: Union[int, timedelta, datetime]) -> datetime:
|
|
"""A helper function that processes time inputs.
|
|
|
|
Args:
|
|
time (Union[int, timedelta, datetime]): The time input to process.
|
|
|
|
Returns:
|
|
datetime: The processed datetime.
|
|
|
|
Raises:
|
|
ValueError: If the input time is less than January 1, 2000.
|
|
"""
|
|
if isinstance(time, int):
|
|
time = datetime.fromtimestamp(time).astimezone()
|
|
|
|
if isinstance(time, timedelta):
|
|
time = datetime.now().astimezone() + time
|
|
|
|
if time < datetime(2000, 1, 1).astimezone():
|
|
delta = timedelta(seconds=int(time.timestamp()))
|
|
time = datetime.now().astimezone() + delta
|
|
|
|
time = time.replace(second=0, microsecond=0)
|
|
|
|
return time
|
|
|
|
|
|
class Expedition(APIModel):
|
|
"""The model for a real-time expedition.
|
|
|
|
Attributes:
|
|
character (str): The expedition character icon url.
|
|
status (Literal["Ongoing", "Finished"]): The status of the expedition.
|
|
remaining_time (timedelta): The remaining time of the expedition.
|
|
"""
|
|
|
|
character: str = Field(alias="avatar_side_icon")
|
|
status: Literal["Ongoing", "Finished"]
|
|
remaining_time: timedelta = Field(alias="remained_time")
|
|
|
|
@property
|
|
def finished(self) -> bool:
|
|
"""A property that returns whether the expedition has finished."""
|
|
return self.remaining_time <= timedelta(0)
|
|
|
|
@property
|
|
def completion_time(self) -> datetime:
|
|
"""A property that returns the completion time of the expedition."""
|
|
return datetime.now().astimezone() + self.remaining_time
|
|
|
|
|
|
class TransformerTimedelta(timedelta):
|
|
"""The model for a transformer recovery time."""
|
|
|
|
@property
|
|
def timedata(self) -> Tuple[int, int, int, int]:
|
|
"""A property that returns the transformer recovery time in days, hours, minutes, and seconds."""
|
|
seconds: int = super().seconds
|
|
days: int = super().days
|
|
hour, second = divmod(seconds, 3600)
|
|
minute, second = divmod(second, 60)
|
|
|
|
return days, hour, minute, second
|
|
|
|
@property
|
|
def hours(self) -> int:
|
|
"""A property that returns the transformer recovery time in hours."""
|
|
return self.timedata[1]
|
|
|
|
@property
|
|
def minutes(self) -> int:
|
|
"""A property that returns the transformer recovery time in minutes."""
|
|
return self.timedata[2]
|
|
|
|
@property
|
|
def seconds(self) -> int:
|
|
"""A property that returns the transformer recovery time in seconds."""
|
|
return self.timedata[3]
|
|
|
|
|
|
class TaskRewardStatus(str, Enum):
|
|
"""The enum for task reward statuses."""
|
|
|
|
Invalid = "TaskRewardStatusInvalid"
|
|
TakenAward = "TaskRewardStatusTakenAward"
|
|
Finished = "TaskRewardStatusFinished"
|
|
Unfinished = "TaskRewardStatusUnfinished"
|
|
|
|
|
|
class TaskReward(APIModel):
|
|
"""The model for a task reward.
|
|
|
|
Attributes:
|
|
status (TaskRewardStatus): The status of the task reward.
|
|
"""
|
|
|
|
status: TaskRewardStatus
|
|
|
|
|
|
class AttendanceRewardStatus(str, Enum):
|
|
"""The enum for attendance reward statuses."""
|
|
|
|
Invalid = "AttendanceRewardStatusInvalid"
|
|
TakenAward = "AttendanceRewardStatusTakenAward"
|
|
WaitTaken = "AttendanceRewardStatusWaitTaken"
|
|
Unfinished = "AttendanceRewardStatusUnfinished"
|
|
FinishedNonReward = "AttendanceRewardStatusFinishedNonReward"
|
|
Forbid = "AttendanceRewardStatusForbid"
|
|
|
|
|
|
class AttendanceReward(APIModel):
|
|
"""The model for an attendance reward.
|
|
|
|
Attributes:
|
|
status (AttendanceRewardStatus): The status of the attendance reward.
|
|
progress (int): The progress of the attendance reward.
|
|
"""
|
|
|
|
status: AttendanceRewardStatus
|
|
progress: int
|
|
|
|
|
|
class DailyTask(APIModel):
|
|
"""The model for a daily task.
|
|
|
|
Attributes:
|
|
total_num (int): The total number of daily tasks.
|
|
finished_num (int): The number of finished daily tasks.
|
|
is_extra_task_reward_received (bool): Whether the extra task reward has been received.
|
|
task_rewards (List[TaskReward]): The list of task rewards.
|
|
attendance_rewards (List[AttendanceReward]): The list of attendance rewards.
|
|
attendance_visible (bool): Whether the attendance rewards are visible.
|
|
"""
|
|
|
|
total_num: int
|
|
finished_num: int
|
|
is_extra_task_reward_received: bool
|
|
task_rewards: List[TaskReward]
|
|
attendance_rewards: List[AttendanceReward]
|
|
attendance_visible: bool
|
|
stored_attendance: float
|
|
stored_attendance_refresh_countdown: timedelta
|
|
|
|
|
|
class ArchonStatusEnum(str, Enum):
|
|
"""The enum for archon statuses."""
|
|
|
|
StatusFinished = "StatusFinished"
|
|
StatusOngoing = "StatusOngoing"
|
|
StatusNotOpen = "StatusNotOpen"
|
|
|
|
|
|
class ArchonStatus(APIModel):
|
|
"""The model for archon status.
|
|
|
|
Attributes:
|
|
status (ArchonStatusEnum): The status of the archon.
|
|
chapter_num (str): The chapter number.
|
|
chapter_title (str): The chapter title.
|
|
id (int): The archon id.
|
|
"""
|
|
|
|
status: ArchonStatusEnum
|
|
chapter_num: str
|
|
chapter_title: str
|
|
id: int
|
|
|
|
|
|
class ArchonQuestProgress(APIModel):
|
|
"""The model for archon quest progress.
|
|
|
|
Attributes:
|
|
list (List[ArchonStatus]): The list of archon status.
|
|
is_open_archon_quest (bool): Whether the archon quest is open. (魔神任务)
|
|
is_finish_all_mainline (bool): Whether all mainline quests are finished. (主线)
|
|
is_finish_all_interchapter (bool): Whether all interchapter quests are finished. (间章)
|
|
wiki_url (str): The wiki url.
|
|
"""
|
|
|
|
list: List[ArchonStatus]
|
|
is_open_archon_quest: bool
|
|
is_finish_all_mainline: bool
|
|
is_finish_all_interchapter: bool
|
|
wiki_url: str
|
|
|
|
@property
|
|
def all_completed(self) -> bool:
|
|
return self.is_finish_all_mainline and self.is_finish_all_interchapter
|
|
|
|
|
|
class Notes(APIModel):
|
|
"""The model for real-time notes.
|
|
|
|
Attributes:
|
|
current_resin (int): The current amount of resin.
|
|
max_resin (int): The maximum amount of resin.
|
|
remaining_resin_recovery_time (timedelta): The remaining time until resin recovery.
|
|
current_realm_currency (int): The current amount of realm currency.
|
|
max_realm_currency (int): The maximum amount of realm currency.
|
|
remaining_realm_currency_recovery_time (timedelta): The remaining time until realm currency recovery.
|
|
completed_commissions (int): The number of completed commissions.
|
|
max_commissions (int): The maximum number of commissions.
|
|
claimed_commission_reward (bool): Whether the commission reward has been claimed.
|
|
remaining_resin_discounts (int): The number of remaining resin discounts.
|
|
max_resin_discounts (int): The maximum number of resin discounts.
|
|
remaining_transformer_recovery_time (Optional[TransformerTimedelta]): The remaining time until
|
|
transformer recovery.
|
|
expeditions (List[Expedition]): The list of expeditions.
|
|
max_expeditions (int): The maximum number of expeditions.
|
|
|
|
Raises:
|
|
ValueError: If the remaining resin recovery time is less than 0 or greater than 8 hours,
|
|
or if the remaining realm currency recovery time is less than 0 or greater than 24 hours.
|
|
"""
|
|
|
|
current_resin: int
|
|
max_resin: int
|
|
remaining_resin_recovery_time: timedelta = Field(alias="resin_recovery_time")
|
|
|
|
current_realm_currency: int = Field(alias="current_home_coin")
|
|
max_realm_currency: int = Field(alias="max_home_coin")
|
|
remaining_realm_currency_recovery_time: timedelta = Field(alias="home_coin_recovery_time")
|
|
|
|
completed_commissions: int = Field(alias="finished_task_num")
|
|
max_commissions: int = Field(alias="total_task_num")
|
|
claimed_commission_reward: bool = Field(alias="is_extra_task_reward_received")
|
|
|
|
remaining_resin_discounts: int = Field(alias="remain_resin_discount_num")
|
|
max_resin_discounts: int = Field(alias="resin_discount_num_limit")
|
|
|
|
remaining_transformer_recovery_time: Optional[TransformerTimedelta]
|
|
|
|
expeditions: List[Expedition]
|
|
max_expeditions: int = Field(alias="max_expedition_num")
|
|
|
|
daily_task: DailyTask
|
|
archon_quest_progress: ArchonQuestProgress
|
|
|
|
@property
|
|
def resin_recovery_time(self) -> datetime:
|
|
"""A property that returns the time when resin will be fully recovered."""
|
|
return datetime.now().astimezone() + self.remaining_resin_recovery_time
|
|
|
|
@property
|
|
def realm_currency_recovery_time(self) -> datetime:
|
|
"""A property that returns the time when realm currency will be fully recovered."""
|
|
return datetime.now().astimezone() + self.remaining_realm_currency_recovery_time
|
|
|
|
@property
|
|
def transformer_recovery_time(self) -> Optional[datetime]:
|
|
"""A property that returns the time when the transformer will be fully recovered."""
|
|
if self.remaining_transformer_recovery_time is None:
|
|
return None
|
|
|
|
remaining = datetime.now().astimezone() + self.remaining_transformer_recovery_time
|
|
return remaining
|
|
|
|
@root_validator(pre=True)
|
|
def flatten_transformer(cls, values: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""A validator that flattens the transformer recovery time.
|
|
|
|
This method flattens the transformer recovery time from a dictionary format to a TransformerTimedelta format.
|
|
|
|
Args:
|
|
values (Dict[str, Any]): The input values.
|
|
|
|
Returns:
|
|
Dict[str, Any]: The values with the transformer recovery time flattened.
|
|
|
|
Raises:
|
|
ValueError: If the transformer recovery time is less than 0 or greater than 7 days.
|
|
"""
|
|
if "transformer_recovery_time" in values:
|
|
return values
|
|
|
|
if values.get("transformer") and values["transformer"]["obtained"]:
|
|
t = values["transformer"]["recovery_time"]
|
|
delta = TransformerTimedelta(days=t["Day"], hours=t["Hour"], minutes=t["Minute"], seconds=t["Second"])
|
|
values["remaining_transformer_recovery_time"] = delta
|
|
else:
|
|
values["remaining_transformer_recovery_time"] = None
|
|
|
|
if (
|
|
values["remaining_transformer_recovery_time"] is not None
|
|
and values["remaining_transformer_recovery_time"].days > 7
|
|
):
|
|
raise ValueError("Transformer recovery time cannot exceed 7 days.")
|
|
|
|
return values
|
|
|
|
|
|
class ExpeditionWidget(APIModel):
|
|
"""The model for a real-time expedition.
|
|
|
|
Attributes:
|
|
character (str): The expedition character icon url.
|
|
status (Literal["Ongoing", "Finished"]): The status of the expedition.
|
|
"""
|
|
|
|
character: str = Field(alias="avatar_side_icon")
|
|
status: Literal["Ongoing", "Finished"]
|
|
|
|
|
|
class NotesWidget(APIModel):
|
|
"""The model for real-time notes.
|
|
|
|
Attributes:
|
|
current_resin (int): The current amount of resin.
|
|
max_resin (int): The maximum amount of resin.
|
|
remaining_resin_recovery_time (timedelta): The remaining time until resin recovery.
|
|
current_realm_currency (int): The current amount of realm currency.
|
|
max_realm_currency (int): The maximum amount of realm currency.
|
|
completed_commissions (int): The number of completed commissions.
|
|
max_commissions (int): The maximum number of commissions.
|
|
claimed_commission_reward (bool): Whether the commission reward has been claimed.
|
|
expeditions (List[Expedition]): The list of expeditions.
|
|
max_expeditions (int): The maximum number of expeditions.
|
|
|
|
Raises:
|
|
ValueError: If the remaining resin recovery time is less than 0 or greater than 8 hours,
|
|
or if the remaining realm currency recovery time is less than 0 or greater than 24 hours.
|
|
"""
|
|
|
|
current_resin: int
|
|
max_resin: int
|
|
remaining_resin_recovery_time: timedelta = Field(alias="resin_recovery_time")
|
|
|
|
current_realm_currency: int = Field(alias="current_home_coin")
|
|
max_realm_currency: int = Field(alias="max_home_coin")
|
|
|
|
completed_commissions: int = Field(alias="finished_task_num")
|
|
max_commissions: int = Field(alias="total_task_num")
|
|
claimed_commission_reward: bool = Field(alias="is_extra_task_reward_received")
|
|
|
|
expeditions: List[ExpeditionWidget]
|
|
max_expeditions: int = Field(alias="max_expedition_num")
|
|
|
|
@property
|
|
def resin_recovery_time(self) -> datetime:
|
|
"""A property that returns the time when resin will be fully recovered."""
|
|
return datetime.now().astimezone() + self.remaining_resin_recovery_time
|
|
|
|
|
|
class NotesOverseaWidgetResin(APIModel):
|
|
"""The model for real-time notes resin.
|
|
|
|
Attributes:
|
|
current_val (int): The current amount of resin.
|
|
max_val (int): The maximum amount of resin.
|
|
remaining_resin_recovery_time (timedelta): The remaining time until resin recovery.
|
|
"""
|
|
|
|
current_val: int
|
|
max_val: int
|
|
remaining_resin_recovery_time: timedelta = Field(alias="recovery_time")
|
|
|
|
@property
|
|
def resin_recovery_time(self) -> datetime:
|
|
"""A property that returns the time when resin will be fully recovered."""
|
|
return datetime.now().astimezone() + self.remaining_resin_recovery_time
|
|
|
|
|
|
class NotesOverseaWidgetRealm(APIModel):
|
|
"""The model for real-time notes realm currency.
|
|
|
|
Attributes:
|
|
current_val (int): The current amount of realm currency.
|
|
max_val (int): The maximum amount of realm currency.
|
|
remaining_realm_currency_recovery_time (timedelta): The remaining time until realm currency recovery.
|
|
"""
|
|
|
|
current_val: int
|
|
max_val: int
|
|
remaining_realm_currency_recovery_time: timedelta = Field(alias="recovery_time")
|
|
|
|
@property
|
|
def realm_currency_recovery_time(self) -> datetime:
|
|
"""A property that returns the time when realm currency will be fully recovered."""
|
|
return datetime.now().astimezone() + self.remaining_realm_currency_recovery_time
|
|
|
|
|
|
class NotesOverseaWidget(APIModel):
|
|
"""The model for real-time notes.
|
|
|
|
Attributes:
|
|
resin (NotesOverseaWidgetResin): The resin information.
|
|
home_coin (NotesOverseaWidgetRealm): The realm currency information.
|
|
|
|
Raises:
|
|
ValueError: If the remaining resin recovery time is less than 0 or greater than 8 hours,
|
|
or if the remaining realm currency recovery time is less than 0 or greater than 24 hours.
|
|
"""
|
|
|
|
resin: NotesOverseaWidgetResin
|
|
home_coin: NotesOverseaWidgetRealm
|