mirror of
https://github.com/TheFunny/ArisuAutoSweeper
synced 2025-12-16 13:25:13 +00:00
335 lines
9.0 KiB
Python
335 lines
9.0 KiB
Python
from datetime import datetime
|
|
from functools import cached_property as functools_cached_property
|
|
|
|
from module.base.decorator import cached_property
|
|
from module.config.utils import DEFAULT_TIME, deep_get, get_server_last_monday_update, get_server_last_update
|
|
|
|
|
|
# from module.exception import ScriptError
|
|
|
|
|
|
def now():
|
|
return datetime.now().replace(microsecond=0)
|
|
|
|
|
|
def iter_attribute(cls):
|
|
"""
|
|
Args:
|
|
cls: Class or object
|
|
|
|
Yields:
|
|
str, obj: Attribute name, attribute value
|
|
"""
|
|
for attr in dir(cls):
|
|
if attr.startswith('_'):
|
|
continue
|
|
value = getattr(cls, attr)
|
|
if type(value).__name__ in ['function', 'property']:
|
|
continue
|
|
yield attr, value
|
|
|
|
|
|
class StoredBase:
|
|
time = DEFAULT_TIME
|
|
|
|
def __init__(self, key):
|
|
self._key = key
|
|
self._config = None
|
|
|
|
@cached_property
|
|
def _name(self):
|
|
return self._key.split('.')[-1]
|
|
|
|
def _bind(self, config):
|
|
"""
|
|
Args:
|
|
config (AzurLaneConfig):
|
|
"""
|
|
self._config = config
|
|
|
|
@functools_cached_property
|
|
def _stored(self):
|
|
assert self._config is not None, 'StoredBase._bind() must be called before getting stored data'
|
|
from module.logger import logger
|
|
|
|
out = {}
|
|
stored = deep_get(self._config.data, keys=self._key, default={})
|
|
for attr, default in self._attrs.items():
|
|
value = stored.get(attr, default)
|
|
if attr == 'time':
|
|
if not isinstance(value, datetime):
|
|
try:
|
|
value = datetime.fromisoformat(value)
|
|
except ValueError:
|
|
logger.warning(f'{self._name} has invalid attr: {attr}={value}, use default={default}')
|
|
value = default
|
|
else:
|
|
if not isinstance(value, type(default)):
|
|
logger.warning(f'{self._name} has invalid attr: {attr}={value}, use default={default}')
|
|
value = default
|
|
|
|
out[attr] = value
|
|
return out
|
|
|
|
@cached_property
|
|
def _attrs(self) -> dict:
|
|
"""
|
|
All attributes defined
|
|
"""
|
|
attrs = {
|
|
# time is the first one
|
|
'time': DEFAULT_TIME
|
|
}
|
|
for attr, value in iter_attribute(self.__class__):
|
|
if attr.islower():
|
|
attrs[attr] = value
|
|
return attrs
|
|
|
|
def __setattr__(self, key, value):
|
|
if key in self._attrs:
|
|
stored = self._stored
|
|
stored['time'] = now()
|
|
stored[key] = value
|
|
self._config.modified[self._key] = stored
|
|
if self._config.auto_update:
|
|
self._config.update()
|
|
else:
|
|
super().__setattr__(key, value)
|
|
|
|
def __getattribute__(self, item):
|
|
if not item.startswith('_') and item in self._attrs:
|
|
return self._stored[item]
|
|
else:
|
|
return super().__getattribute__(item)
|
|
|
|
def is_expired(self) -> bool:
|
|
return False
|
|
|
|
def show(self):
|
|
"""
|
|
Log self
|
|
"""
|
|
from module.logger import logger
|
|
logger.attr(self._name, self._stored)
|
|
|
|
|
|
class StoredExpiredAt0400(StoredBase):
|
|
def is_expired(self):
|
|
from module.logger import logger
|
|
self.show()
|
|
expired = self.time < get_server_last_update('04:00')
|
|
logger.attr(f'{self._name} expired', expired)
|
|
return expired
|
|
|
|
|
|
class StoredExpiredAtMonday0400(StoredBase):
|
|
def is_expired(self):
|
|
from module.logger import logger
|
|
self.show()
|
|
expired = self.time < get_server_last_monday_update('04:00')
|
|
logger.attr(f'{self._name} expired', expired)
|
|
return expired
|
|
|
|
|
|
class StoredInt(StoredBase):
|
|
value = 0
|
|
|
|
|
|
class StoredCounter(StoredBase):
|
|
value = 0
|
|
total = 0
|
|
|
|
FIXED_TOTAL = 0
|
|
|
|
def set(self, value, total=0):
|
|
if self.FIXED_TOTAL:
|
|
total = self.FIXED_TOTAL
|
|
with self._config.multi_set():
|
|
self.value = value
|
|
self.total = total
|
|
|
|
def to_counter(self) -> str:
|
|
return f'{self.value}/{self.total}'
|
|
|
|
def is_full(self) -> bool:
|
|
return self.value >= self.total
|
|
|
|
def get_remain(self) -> int:
|
|
return self.total - self.value
|
|
|
|
@cached_property
|
|
def _attrs(self) -> dict:
|
|
attrs = super()._attrs
|
|
if self.FIXED_TOTAL:
|
|
attrs['total'] = self.FIXED_TOTAL
|
|
return attrs
|
|
|
|
@functools_cached_property
|
|
def _stored(self):
|
|
stored = super()._stored
|
|
if self.FIXED_TOTAL:
|
|
stored['total'] = self.FIXED_TOTAL
|
|
return stored
|
|
|
|
|
|
class StoredAP(StoredCounter):
|
|
pass
|
|
|
|
|
|
class StoredBountyTicket(StoredCounter, StoredExpiredAt0400):
|
|
FIXED_TOTAL = 6
|
|
pass
|
|
|
|
|
|
class StoredScrimmageTicket(StoredCounter, StoredExpiredAt0400):
|
|
FIXED_TOTAL = 6
|
|
|
|
|
|
class StoredTacticalChallengeTicket(StoredCounter, StoredExpiredAt0400):
|
|
FIXED_TOTAL = 5
|
|
|
|
|
|
# class StoredDailyActivity(StoredCounter, StoredExpiredAt0400):
|
|
# FIXED_TOTAL = 500
|
|
#
|
|
#
|
|
# class StoredTrailblazePower(StoredCounter):
|
|
# FIXED_TOTAL = 240
|
|
#
|
|
#
|
|
# class StoredSimulatedUniverse(StoredCounter, StoredExpiredAt0400):
|
|
# pass
|
|
#
|
|
#
|
|
# class StoredAssignment(StoredCounter):
|
|
# pass
|
|
#
|
|
#
|
|
# class StoredDaily(StoredCounter, StoredExpiredAt0400):
|
|
# quest1 = ''
|
|
# quest2 = ''
|
|
# quest3 = ''
|
|
# quest4 = ''
|
|
# quest5 = ''
|
|
# quest6 = ''
|
|
#
|
|
# FIXED_TOTAL = 6
|
|
#
|
|
# def load_quests(self):
|
|
# """
|
|
# Returns:
|
|
# list[DailyQuest]: Note that must check if quests are expired
|
|
# """
|
|
# # DailyQuest should be lazy loaded
|
|
# from tasks.daily.keywords import DailyQuest
|
|
# quests = []
|
|
# for name in [self.quest1, self.quest2, self.quest3, self.quest4, self.quest5, self.quest6]:
|
|
# if not name:
|
|
# continue
|
|
# try:
|
|
# quest = DailyQuest.find(name)
|
|
# quests.append(quest)
|
|
# except ScriptError:
|
|
# pass
|
|
# return quests
|
|
#
|
|
# def write_quests(self, quests):
|
|
# """
|
|
# Args:
|
|
# quests (list[DailyQuest, str]):
|
|
# """
|
|
# from tasks.daily.keywords import DailyQuest
|
|
# quests = [q.name if isinstance(q, DailyQuest) else q for q in quests]
|
|
# with self._config.multi_set():
|
|
# self.set(value=max(self.FIXED_TOTAL - len(quests), 0))
|
|
# try:
|
|
# self.quest1 = quests[0]
|
|
# except IndexError:
|
|
# self.quest1 = ''
|
|
# try:
|
|
# self.quest2 = quests[1]
|
|
# except IndexError:
|
|
# self.quest2 = ''
|
|
# try:
|
|
# self.quest3 = quests[2]
|
|
# except IndexError:
|
|
# self.quest3 = ''
|
|
# try:
|
|
# self.quest4 = quests[3]
|
|
# except IndexError:
|
|
# self.quest4 = ''
|
|
# try:
|
|
# self.quest5 = quests[4]
|
|
# except IndexError:
|
|
# self.quest5 = ''
|
|
# try:
|
|
# self.quest6 = quests[5]
|
|
# except IndexError:
|
|
# self.quest6 = ''
|
|
#
|
|
#
|
|
# class StoredDungeonDouble(StoredExpiredAt0400):
|
|
# calyx = 0
|
|
# relic = 0
|
|
#
|
|
#
|
|
# class StoredEchoOfWar(StoredCounter, StoredExpiredAtMonday0400):
|
|
# FIXED_TOTAL = 3
|
|
#
|
|
#
|
|
# class StoredBattlePassLevel(StoredCounter):
|
|
# FIXED_TOTAL = 50
|
|
#
|
|
#
|
|
# class StoredBattlePassTodayQuest(StoredCounter, StoredExpiredAt0400):
|
|
# quest1 = ''
|
|
# quest2 = ''
|
|
# quest3 = ''
|
|
# quest4 = ''
|
|
#
|
|
# FIXED_TOTAL = 4
|
|
#
|
|
# def load_quests(self):
|
|
# """
|
|
# Returns:
|
|
# list[DailyQuest]: Note that must check if quests are expired
|
|
# """
|
|
# # BattlePassQuest should be lazy loaded
|
|
# from tasks.battle_pass.keywords import BattlePassQuest
|
|
# quests = []
|
|
# for name in [self.quest1, self.quest2, self.quest3, self.quest4]:
|
|
# if not name:
|
|
# continue
|
|
# try:
|
|
# quest = BattlePassQuest.find(name)
|
|
# quests.append(quest)
|
|
# except ScriptError:
|
|
# pass
|
|
# return quests
|
|
#
|
|
# def write_quests(self, quests):
|
|
# """
|
|
# Args:
|
|
# quests (list[DailyQuest, str]):
|
|
# """
|
|
# from tasks.battle_pass.keywords import BattlePassQuest
|
|
# quests = [q.name if isinstance(q, BattlePassQuest) else q for q in quests]
|
|
# with self._config.multi_set():
|
|
# self.set(value=max(self.FIXED_TOTAL - len(quests), 0))
|
|
# try:
|
|
# self.quest1 = quests[0]
|
|
# except IndexError:
|
|
# self.quest1 = ''
|
|
# try:
|
|
# self.quest2 = quests[1]
|
|
# except IndexError:
|
|
# self.quest2 = ''
|
|
# try:
|
|
# self.quest3 = quests[2]
|
|
# except IndexError:
|
|
# self.quest3 = ''
|
|
# try:
|
|
# self.quest4 = quests[3]
|
|
# except IndexError:
|
|
# self.quest4 = ''
|