forked from Hay1tsme/artemis
round database implenments
This commit is contained in:
parent
f6cc1422ae
commit
a245f3add4
|
@ -0,0 +1,22 @@
|
|||
-- Create the new table idac_round_info
|
||||
CREATE TABLE idac_round_info (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
round_id INT,
|
||||
name VARCHAR(64),
|
||||
season INT,
|
||||
start_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
end_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Create the new table idac_user_round_info
|
||||
CREATE TABLE idac_user_round_info (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
user INT,
|
||||
round_id INT,
|
||||
count INT,
|
||||
win INT,
|
||||
point INT,
|
||||
play_dt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT idac_user_vs_course_info_fk FOREIGN KEY (user) REFERENCES aime_user(id) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
UNIQUE KEY idac_user_vs_course_info_uk (user, round_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
@ -2,6 +2,7 @@ from core.data import Data
|
|||
from core.config import CoreConfig
|
||||
from titles.idac.schema.profile import IDACProfileData
|
||||
from titles.idac.schema.item import IDACItemData
|
||||
from titles.idac.schema.rounds import IDACOnlineRounds
|
||||
|
||||
|
||||
class IDACData(Data):
|
||||
|
@ -10,3 +11,4 @@ class IDACData(Data):
|
|||
|
||||
self.profile = IDACProfileData(cfg, self.session)
|
||||
self.item = IDACItemData(cfg, self.session)
|
||||
self.rounds = IDACOnlineRounds(cfg, self.session)
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
from typing import Dict, List, Optional
|
||||
from sqlalchemy import Table, Column, UniqueConstraint, PrimaryKeyConstraint, and_, update
|
||||
from sqlalchemy.types import Integer, String, TIMESTAMP, Boolean, JSON, BigInteger
|
||||
from sqlalchemy.engine.base import Connection
|
||||
from sqlalchemy.schema import ForeignKey
|
||||
from sqlalchemy.sql import func, select
|
||||
from sqlalchemy.engine import Row
|
||||
from sqlalchemy.dialects.mysql import insert
|
||||
|
||||
from core.data.schema import BaseData, metadata
|
||||
from core.config import CoreConfig
|
||||
|
||||
round_details = Table(
|
||||
"idac_round_info",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("name", String(64)),
|
||||
Column("season", Integer),
|
||||
Column("start_dt", TIMESTAMP, server_default=func.now()),
|
||||
Column("end_dt", TIMESTAMP, server_default=func.now()),
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
round_info = Table(
|
||||
"idac_user_round_info",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")),
|
||||
Column("round_id", Integer),
|
||||
Column("count", Integer),
|
||||
Column("win", Integer),
|
||||
Column("point", Integer),
|
||||
Column("play_dt", TIMESTAMP, server_default=func.now()),
|
||||
UniqueConstraint("user", "round_id", name="idac_user_round_info_uk"),
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
class IDACOnlineRounds(BaseData):
|
||||
# get player's ranking from a specified round event
|
||||
async def get_round_rank_by_id(self, aime_id: int, round_event_id: int) -> Optional[Row]:
|
||||
subquery = (
|
||||
select([func.group_concat(func.concat(round_info.c.user, '|', round_info.c.point),order_by=[round_info.c.point.desc(), round_info.c.play_dt])])
|
||||
.select_from(round_info)
|
||||
.where(round_info.c.round_id == round_event_id)
|
||||
.as_scalar()
|
||||
)
|
||||
|
||||
sql = (
|
||||
select([func.find_in_set(func.concat(round_info.c.user, '|', round_info.c.point), subquery.label('rank'))])
|
||||
.select_from(round_info)
|
||||
.where(
|
||||
and_(
|
||||
round_info.c.user == aime_id,
|
||||
round_info.c.round_id == round_event_id
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
|
||||
# get player's info from a specified round event
|
||||
async def get_round_info_by_id(self, aime_id: int, round_event_id: int) -> Optional[Row]:
|
||||
sql = select(round_info).where(
|
||||
and_(
|
||||
round_info.c.user == aime_id,
|
||||
round_info.c.round_id == round_event_id
|
||||
)
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
# save players info to a specified round event
|
||||
async def put_round_event(
|
||||
self, aime_id: int, round_id: int, round_data: Dict
|
||||
) -> Optional[int]:
|
||||
round_data["user"] = aime_id
|
||||
round_data["round_id"] = round_id
|
||||
|
||||
sql = insert(round_info).values(**round_data)
|
||||
conflict = sql.on_duplicate_key_update(**round_data)
|
||||
result = self.execute(conflict)
|
||||
|
||||
if result is None:
|
||||
self.logger.warn(f"putround: Failed to update! aime_id: {aime_id}")
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
#TODO: get top five players of last round event for Boot/GetConfigData
|
|
@ -843,6 +843,60 @@ class IDACSeason2(IDACBase):
|
|||
vs_info["course_select_priority"] = data.get("course_select_priority")
|
||||
return vs_info
|
||||
|
||||
async def _update_round_info(
|
||||
self, user_id: int, round_event_id: int, point: int, win: int
|
||||
) -> Dict:
|
||||
|
||||
# get the round info data from database
|
||||
round_info = []
|
||||
ri = await self.data.rounds.get_round_info_by_id(user_id, round_event_id)
|
||||
if ri is not None:
|
||||
tmp = ri._asdict()
|
||||
|
||||
del tmp["id"]
|
||||
|
||||
# calculate new round points and info
|
||||
tmp["point"] = 0 if tmp["point"] + point < 1 else tmp["point"] + point
|
||||
tmp["count"] += 1
|
||||
tmp["win"] += win
|
||||
tmp["play_dt"] = datetime.now()
|
||||
|
||||
# update players round info
|
||||
await self.data.rounds.put_round_event(user_id, round_event_id, tmp)
|
||||
|
||||
del tmp["play_dt"]
|
||||
|
||||
# get players new round ranking
|
||||
r = await self.data.rounds.get_round_rank_by_id(user_id, round_event_id)
|
||||
round_ranking = r._asdict()
|
||||
tmp["rank"] = round_ranking["find_in_set_1"] if tmp["point"] > 0 else 0
|
||||
|
||||
# TODO: get players historical earned points
|
||||
tmp["total_round_point"] = 0
|
||||
|
||||
round_info.append(tmp)
|
||||
else:
|
||||
# new player of now-going round event
|
||||
tmp = {}
|
||||
tmp["point"] = 0 if point < 1 else point
|
||||
tmp["count"] = 1
|
||||
tmp["win"] = win
|
||||
tmp["play_dt"] = datetime.now()
|
||||
await self.data.rounds.put_round_event(user_id, round_event_id, tmp)
|
||||
|
||||
del tmp["play_dt"]
|
||||
|
||||
r = await self.data.rounds.get_round_rank_by_id(user_id, round_event_id)
|
||||
round_ranking = r._asdict()
|
||||
tmp["rank"] = round_ranking["find_in_set_1"] if tmp["point"] > 0 else 0
|
||||
|
||||
# TODO: get players historical earned points
|
||||
tmp["total_round_point"] = 0
|
||||
|
||||
round_info.append(tmp)
|
||||
return round_info
|
||||
|
||||
|
||||
def _choose_gift_id(self) -> Dict:
|
||||
gift_data = self.battle_gift_event["gift_data"]
|
||||
# calculate the total_rate based on the first_distribution_rate
|
||||
|
@ -2849,6 +2903,7 @@ class IDACSeason2(IDACBase):
|
|||
}
|
||||
|
||||
async def handle_user_updateonlinebattle_request(self, data: Dict, headers: Dict):
|
||||
#TODO: voiding cheaters' result. which will need to analysis historical battle results returned by the game.
|
||||
return {
|
||||
"status_code": "0",
|
||||
"bothwin_penalty": 1,
|
||||
|
@ -2922,18 +2977,12 @@ class IDACSeason2(IDACBase):
|
|||
user_id, self.version, {"online_battle_play_count": tips["online_battle_play_count"] + 1}
|
||||
)
|
||||
|
||||
round_info = await self._update_round_info(user_id, self.round_event_id, data.pop("round_point"), data.pop("win_flg"))
|
||||
|
||||
return {
|
||||
"status_code": "0",
|
||||
"vsinfo_data": vs_info,
|
||||
"round_event": [
|
||||
{
|
||||
"count": 1,
|
||||
"win": 1,
|
||||
"rank": 1,
|
||||
"point": 1,
|
||||
"total_round_point": 1,
|
||||
}
|
||||
],
|
||||
"round_event": round_info,
|
||||
"car_use_count": [],
|
||||
"maker_use_count": [],
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue