Skip to content

Commit

Permalink
part 1 of clanbattlev3
Browse files Browse the repository at this point in the history
  • Loading branch information
Ice9Coffee committed Aug 9, 2020
1 parent 72acaa0 commit 3bb614d
Show file tree
Hide file tree
Showing 21 changed files with 1,016 additions and 415 deletions.
25 changes: 25 additions & 0 deletions hoshino/config_example/clanbattle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class JP:
BOSS_HP = [
[6000000, 8000000, 10000000, 12000000, 15000000],
[6000000, 8000000, 10000000, 12000000, 15000000],
[7000000, 9000000, 13000000, 15000000, 20000000],
[15000000, 16000000, 18000000, 19000000, 20000000],
]


class TW:
BOSS_HP = [
[6000000, 8000000, 10000000, 12000000, 15000000],
[6000000, 8000000, 10000000, 12000000, 15000000],
[7000000, 9000000, 13000000, 15000000, 20000000],
[15000000, 16000000, 18000000, 19000000, 20000000],
]


class BL:
BOSS_HP = [
[6000000, 8000000, 10000000, 12000000, 20000000],
[6000000, 8000000, 10000000, 12000000, 20000000],
[6000000, 8000000, 10000000, 12000000, 20000000],
[6000000, 8000000, 10000000, 12000000, 20000000],
]
52 changes: 52 additions & 0 deletions hoshino/modules/pcrclanbattle/clanbattlev3/argparser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from typing import Dict, List

from .exception import ParseError


class ArgHolder:
__slots__ = ("type", "default", "tip")

def __init__(self, tip, type_=str, default=None):
self.type = type_
self.default = default
self.tip = tip


class ArgParser:
def __init__(self, arg_dict=None):
self.arg_dict: Dict[str, ArgHolder] = arg_dict or {}

def add_arg(self, prompt, tip, type_=str, default=None):
self.arg_dict[prompt] = ArgHolder(tip, type_, default)

def parse(self, args: List[str]) -> dict:
result = {}

# 解析参数,以一个字符开头,或无前缀
for arg in args:
prompt, x = arg[0].upper(), arg[1:]
if prompt in self.arg_dict:
holder = self.arg_dict[prompt]
elif "" in self.arg_dict:
holder = self.arg_dict[""]
prompt, x = "", arg
else:
raise ParseError(f"未知参数:{arg}")

try:
result.setdefault(prompt, holder.type(x)) # 多个参数只取第1个
except ParseError:
raise
except Exception:
raise ParseError(f"解析{holder.tip}失败")

# 检查所有参数是否以赋值
for prompt, holder in self.arg_dict.items():
if prompt not in result:
if holder.default is None: # 缺失必要参数 抛异常
msg = f"缺少参数:{holder.tip}"
raise ParseError(msg)
else:
result[prompt] = holder.default

return result
140 changes: 44 additions & 96 deletions hoshino/modules/pcrclanbattle/clanbattlev3/battlemaster.py
Original file line number Diff line number Diff line change
@@ -1,109 +1,57 @@
import os
import sqlite3
from datetime import datetime, timedelta, timezone
from .model import *
from datetime import datetime
from . import helper
from .table import *

DB_FOLDER = os.path.expanduser('~/.hoshino/clanbattlev3/')
DB_FOLDER = os.path.expanduser("~/.hoshino/clanbattlev3/")
os.makedirs(DB_FOLDER, exist_ok=True)


def get_yyyymmdd(time, zone_num:int=8):
'''返回time对应的会战年月日。
其中,年月为该期会战的年月;日为刷新周期对应的日期。
会战为每月最后一星期,编程时认为mm月的会战一定在mm月20日至mm+1月10日之间,每日以5:00 UTC+8为界。
注意:返回的年月日并不一定是自然时间,如2019年9月2日04:00:00我们认为对应2019年8月会战,日期仍为1号,将返回(2019,8,1)
'''
# 日台服均为当地时间凌晨5点更新,故减5
time = time.astimezone(timezone(timedelta(hours=zone_num - 5)))
yyyy = time.year
mm = time.month
dd = time.day
if dd < 20:
mm = mm - 1
if mm < 1:
mm = 12
yyyy = yyyy - 1
return (yyyy, mm, dd)


class BattleMaster:
def __init__(self, gid, time):
def __init__(self, gid, time=None):
self.gid = gid
self.yyyy, self.mm, _ = get_yyyymmdd(time)
self.year, self.month, _ = helper.yyyymmdd(time or datetime.now())
self.clan = ClanTable()
self.member = MemberTable()
self.challenge = ChallengeTable(gid)
self.progress = ProgressTable(gid)
self.pause = PauseTable(gid)
self.sos = SosTable()
self.sl = SlTable()
self.subr = SubrTable()
self._create_tables()

def connect_clan_db(self):
db = os.path.join(DB_FOLDER, "clan.db")
return sqlite3.connect(
db, detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES
)

def _connect_clan_db(self):
db = os.path.join(DB_FOLDER, 'clan.db')
return sqlite3.connect(db, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)


def _connect_battle_db(self):
db = os.path.join(DB_FOLDER, f'battle{self.yyyy:04d}{self.mm:02d}.db')
return sqlite3.connect(db, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)

def connect_battle_db(self):
db = os.path.join(DB_FOLDER, f"battle{self.year:04d}{self.month:02d}.db")
return sqlite3.connect(
db, detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES
)

def _create_tables(self):
with self._connect_clan_db() as conn:
sql = "CREATE TABLE IF NOT EXISTS clan" \
"(gid INT PRIMARY KEY NOT NULL, name TEXT NOT NULL, server INT NOT NULL)"
conn.execute(sql)
sql = "CREATE TABLE IF NOT EXISTS member" \
"(gid INT NOT NULL, uid INT NOT NULL, name TEXT NOT NULL, PRIMARY KEY (gid, uid))"
conn.execute(sql)

with self._connect_battle_db() as conn:
sql = f"CREATE TABLE IF NOT EXISTS challenge_{self.gid}" \
"(eid INTEGER PRIMARY KEY AUTOINCREMENT, uid INT NOT NULL, time DATETIME NOT NULL, round INT NOT NULL, boss INT NOT NULL, dmg INT NOT NULL, flag INT NOT NULL)"
conn.execute(sql)
sql = "CREATE TABLE IF NOT EXISTS progress" \
"(gid INT PRIMARY KEY NOT NULL, round INT NOT NULL, boss INT NOT NULL, hp INT NOT NULL)"
conn.execute(sql)
sql = "CREATE TABLE IF NOT EXISTS pause" \
"(gid INT NOT NULL, uid INT NOT NULL, dmg INT NOT NULL, second_left INT NOT NULL)"
conn.execute(sql)
sql = "CREATE TABLE IF NOT EXISTS sos" \
"(gid INT NOT NULL, uid INT NOT NULL, time DATETIME NOT NULL, round INT NOT NULL, boss INT NOT NULL)"
conn.execute(sql)
sql = "CREATE TABLE IF NOT EXISTS sl" \
"(gid INT NOT NULL, uid INT NOT NULL, time DATETIME NOT NULL, round INT NOT NULL, boss INT NOT NULL)"
conn.execute(sql)
sql = "CREATE TABLE IF NOT EXISTS subscribe" \
"(gid INT NOT NULL, uid INT NOT NULL, time DATETIME NOT NULL, round INT NOT NULL, boss INT NOT NULL)"
conn.execute(sql)


def get_clan(self):
with self._connect_clan_db() as conn:
clan = conn.execute("SELECT gid, name, server FROM clan WHERE gid=?",
(self.gid, )).fetchone()
return Clan(*clan) if clan else None


def add_clan(self, clan: Clan):
with self._connect_clan_db() as conn:
conn.execute("INSERT OR REPLACE INTO clan (gid, name, server) VALUES (?, ?, ?)",
(clan.gid, clan.name, clan.server))


def get_member(self, uid):
with self._connect_clan_db() as conn:
m = conn.execute("SELECT uid, gid, name FROM member WHERE gid=? and uid=?",
(self.gid, uid)).fetchone()
return Member(*m) if m else None


def add_member(self, member: Member):
with self._connect_clan_db() as conn:
conn.execute("INSERT OR REPLACE INTO member (uid, gid, name) VALUES (?, ?, ?)",
(member.uid, member.gid, member.name))


def del_member(self, uid):
with self._connect_clan_db() as conn:
conn.execute("DELETE FROM member WHERE uid=?", (uid, ))




with self.connect_clan_db() as conn:
self.clan.create(conn)
self.member.create(conn)

with self.connect_battle_db() as conn:
self.challenge.create(conn)
self.progress.create(conn)
self.pause.create(conn)
self.sos.create(conn)
self.sl.create(conn)
self.subr.create(conn)

def uid2name(self, conn, uids):
names = []
for uid in uids:
x = conn.execute(
"SELECT name FROM member WHERE gid=? AND uid=?", (self.gid, uid)
).fetchone()
names.append(x[0] if x else str(uid))
return names
Loading

0 comments on commit 3bb614d

Please sign in to comment.