forked from Dniel97/artemis
CHUNITHM & O.N.G.E.K.I.: Handle userRatingBase*List (#113)
These tables are not used by the game, but are useful for anyone wanting to develop a web UI showing what the player's rating consists of. As such, instead of storing them in JSON columns, I've split them out, one row per each entry. Reviewed-on: Hay1tsme/artemis#113 Co-authored-by: beerpsi <beerpsi@duck.com> Co-committed-by: beerpsi <beerpsi@duck.com>
This commit is contained in:
parent
346f82a32a
commit
40a0817009
@ -0,0 +1,56 @@
|
|||||||
|
"""GekiChu rating tables
|
||||||
|
|
||||||
|
Revision ID: 6a7e8277763b
|
||||||
|
Revises: d8950c7ce2fc
|
||||||
|
Create Date: 2024-03-13 12:18:53.210018
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
from sqlalchemy import Column, Integer, String
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '6a7e8277763b'
|
||||||
|
down_revision = 'd8950c7ce2fc'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
GEKICHU_RATING_TABLE_NAMES = [
|
||||||
|
"chuni_profile_rating",
|
||||||
|
"ongeki_profile_rating",
|
||||||
|
]
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
for table_name in GEKICHU_RATING_TABLE_NAMES:
|
||||||
|
op.create_table(
|
||||||
|
table_name,
|
||||||
|
Column("id", Integer, primary_key=True, nullable=False),
|
||||||
|
Column("user", Integer, nullable=False),
|
||||||
|
Column("version", Integer, nullable=False),
|
||||||
|
Column("type", String(255), nullable=False),
|
||||||
|
Column("index", Integer, nullable=False),
|
||||||
|
Column("musicId", Integer),
|
||||||
|
Column("difficultId", Integer),
|
||||||
|
Column("romVersionCode", Integer),
|
||||||
|
Column("score", Integer),
|
||||||
|
mysql_charset="utf8mb4",
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
None,
|
||||||
|
table_name,
|
||||||
|
"aime_user",
|
||||||
|
["user"],
|
||||||
|
["id"],
|
||||||
|
ondelete="cascade",
|
||||||
|
onupdate="cascade",
|
||||||
|
)
|
||||||
|
op.create_unique_constraint(
|
||||||
|
f"{table_name}_uk",
|
||||||
|
table_name,
|
||||||
|
["user", "version", "type", "index"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
for table_name in GEKICHU_RATING_TABLE_NAMES:
|
||||||
|
op.drop_table(table_name)
|
@ -925,6 +925,17 @@ class ChuniBase:
|
|||||||
for rp in upsert["userRecentPlayerList"]:
|
for rp in upsert["userRecentPlayerList"]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
for rating_type in {"userRatingBaseList", "userRatingBaseHotList", "userRatingBaseNextList"}:
|
||||||
|
if rating_type not in upsert:
|
||||||
|
continue
|
||||||
|
|
||||||
|
await self.data.profile.put_profile_rating(
|
||||||
|
user_id,
|
||||||
|
self.version,
|
||||||
|
rating_type,
|
||||||
|
upsert[rating_type],
|
||||||
|
)
|
||||||
|
|
||||||
return {"returnCode": "1"}
|
return {"returnCode": "1"}
|
||||||
|
|
||||||
async def handle_upsert_user_chargelog_api_request(self, data: Dict) -> Dict:
|
async def handle_upsert_user_chargelog_api_request(self, data: Dict) -> Dict:
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
from typing import Dict, List, Optional
|
from typing import Dict, List, Optional
|
||||||
from sqlalchemy import Table, Column, UniqueConstraint, PrimaryKeyConstraint, and_
|
from sqlalchemy import Table, Column, UniqueConstraint, and_
|
||||||
from sqlalchemy.types import Integer, String, TIMESTAMP, Boolean, JSON, BigInteger
|
from sqlalchemy.types import Integer, String, Boolean, JSON, BigInteger
|
||||||
from sqlalchemy.engine.base import Connection
|
|
||||||
from sqlalchemy.schema import ForeignKey
|
from sqlalchemy.schema import ForeignKey
|
||||||
from sqlalchemy.engine import Row
|
from sqlalchemy.engine import Row
|
||||||
from sqlalchemy.sql import func, select
|
from sqlalchemy.sql import select, delete
|
||||||
from sqlalchemy.dialects.mysql import insert
|
from sqlalchemy.dialects.mysql import insert
|
||||||
|
|
||||||
from core.data.schema import BaseData, metadata
|
from core.data.schema import BaseData, metadata
|
||||||
@ -393,6 +392,26 @@ team = Table(
|
|||||||
mysql_charset="utf8mb4",
|
mysql_charset="utf8mb4",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rating = Table(
|
||||||
|
"chuni_profile_rating",
|
||||||
|
metadata,
|
||||||
|
Column("id", Integer, primary_key=True, nullable=False),
|
||||||
|
Column(
|
||||||
|
"user",
|
||||||
|
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||||
|
nullable=False,
|
||||||
|
),
|
||||||
|
Column("version", Integer, nullable=False),
|
||||||
|
Column("type", String(255), nullable=False),
|
||||||
|
Column("index", Integer, nullable=False),
|
||||||
|
Column("musicId", Integer),
|
||||||
|
Column("difficultId", Integer),
|
||||||
|
Column("romVersionCode", Integer),
|
||||||
|
Column("score", Integer),
|
||||||
|
UniqueConstraint("user", "version", "type", "index", name="chuni_profile_rating_best_uk"),
|
||||||
|
mysql_charset="utf8mb4",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ChuniProfileData(BaseData):
|
class ChuniProfileData(BaseData):
|
||||||
async def update_name(self, user_id: int, new_name: str) -> bool:
|
async def update_name(self, user_id: int, new_name: str) -> bool:
|
||||||
@ -714,3 +733,27 @@ class ChuniProfileData(BaseData):
|
|||||||
return {
|
return {
|
||||||
"total_play_count": total_play_count
|
"total_play_count": total_play_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async def put_profile_rating(
|
||||||
|
self,
|
||||||
|
aime_id: int,
|
||||||
|
version: int,
|
||||||
|
rating_type: str,
|
||||||
|
rating_data: List[Dict],
|
||||||
|
):
|
||||||
|
inserted_values = [
|
||||||
|
{"user": aime_id, "version": version, "type": rating_type, "index": i, **x}
|
||||||
|
for (i, x) in enumerate(rating_data)
|
||||||
|
]
|
||||||
|
sql = insert(rating).values(inserted_values)
|
||||||
|
update_dict = {x.name: x for x in sql.inserted if x.name != "id"}
|
||||||
|
sql = sql.on_duplicate_key_update(**update_dict)
|
||||||
|
result = await self.execute(sql)
|
||||||
|
|
||||||
|
if result is None:
|
||||||
|
self.logger.warn(
|
||||||
|
f"put_profile_rating: Could not insert {rating_type}, aime_id: {aime_id}",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
return result.lastrowid
|
||||||
|
@ -1068,6 +1068,24 @@ class OngekiBase:
|
|||||||
for x in upsert["userKopList"]:
|
for x in upsert["userKopList"]:
|
||||||
await self.data.profile.put_kop(user_id, x)
|
await self.data.profile.put_kop(user_id, x)
|
||||||
|
|
||||||
|
for rating_type in {
|
||||||
|
"userRatingBaseBestList",
|
||||||
|
"userRatingBaseBestNewList",
|
||||||
|
"userRatingBaseHotList",
|
||||||
|
"userRatingBaseNextList",
|
||||||
|
"userRatingBaseNextNewList",
|
||||||
|
"userRatingBaseHotNextList",
|
||||||
|
}:
|
||||||
|
if rating_type not in upsert:
|
||||||
|
continue
|
||||||
|
|
||||||
|
await self.data.profile.put_profile_rating(
|
||||||
|
user_id,
|
||||||
|
self.version,
|
||||||
|
rating_type,
|
||||||
|
upsert[rating_type],
|
||||||
|
)
|
||||||
|
|
||||||
return {"returnCode": 1, "apiName": "upsertUserAll"}
|
return {"returnCode": 1, "apiName": "upsertUserAll"}
|
||||||
|
|
||||||
async def handle_get_user_rival_api_request(self, data: Dict) -> Dict:
|
async def handle_get_user_rival_api_request(self, data: Dict) -> Dict:
|
||||||
|
@ -246,6 +246,26 @@ rival = Table(
|
|||||||
mysql_charset="utf8mb4",
|
mysql_charset="utf8mb4",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rating = Table(
|
||||||
|
"ongeki_profile_rating",
|
||||||
|
metadata,
|
||||||
|
Column("id", Integer, primary_key=True, nullable=False),
|
||||||
|
Column(
|
||||||
|
"user",
|
||||||
|
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||||
|
nullable=False,
|
||||||
|
),
|
||||||
|
Column("version", Integer, nullable=False),
|
||||||
|
Column("type", String(255), nullable=False),
|
||||||
|
Column("index", Integer, nullable=False),
|
||||||
|
Column("musicId", Integer),
|
||||||
|
Column("difficultId", Integer),
|
||||||
|
Column("romVersionCode", Integer),
|
||||||
|
Column("score", Integer),
|
||||||
|
UniqueConstraint("user", "version", "type", "index", name="ongeki_profile_rating_best_uk"),
|
||||||
|
mysql_charset="utf8mb4",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class OngekiProfileData(BaseData):
|
class OngekiProfileData(BaseData):
|
||||||
def __init__(self, cfg: CoreConfig, conn: Connection) -> None:
|
def __init__(self, cfg: CoreConfig, conn: Connection) -> None:
|
||||||
@ -508,6 +528,7 @@ class OngekiProfileData(BaseData):
|
|||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
return result.lastrowid
|
return result.lastrowid
|
||||||
|
|
||||||
async def delete_rival(self, aime_id: int, rival_id: int) -> Optional[int]:
|
async def delete_rival(self, aime_id: int, rival_id: int) -> Optional[int]:
|
||||||
sql = delete(rival).where(rival.c.user==aime_id, rival.c.rivalUserId==rival_id)
|
sql = delete(rival).where(rival.c.user==aime_id, rival.c.rivalUserId==rival_id)
|
||||||
result = await self.execute(sql)
|
result = await self.execute(sql)
|
||||||
@ -515,3 +536,27 @@ class OngekiProfileData(BaseData):
|
|||||||
self.logger.error(f"delete_rival: failed to delete! aime_id: {aime_id}, rival_id: {rival_id}")
|
self.logger.error(f"delete_rival: failed to delete! aime_id: {aime_id}, rival_id: {rival_id}")
|
||||||
else:
|
else:
|
||||||
return result.rowcount
|
return result.rowcount
|
||||||
|
|
||||||
|
async def put_profile_rating(
|
||||||
|
self,
|
||||||
|
aime_id: int,
|
||||||
|
version: int,
|
||||||
|
rating_type: str,
|
||||||
|
rating_data: List[Dict],
|
||||||
|
):
|
||||||
|
inserted_values = [
|
||||||
|
{"user": aime_id, "version": version, "type": rating_type, "index": i, **x}
|
||||||
|
for (i, x) in enumerate(rating_data)
|
||||||
|
]
|
||||||
|
sql = insert(rating).values(inserted_values)
|
||||||
|
update_dict = {x.name: x for x in sql.inserted if x.name != "id"}
|
||||||
|
sql = sql.on_duplicate_key_update(**update_dict)
|
||||||
|
result = await self.execute(sql)
|
||||||
|
|
||||||
|
if result is None:
|
||||||
|
self.logger.warn(
|
||||||
|
f"put_profile_rating_{rating_type}: Could not insert rating entries, aime_id: {aime_id}",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
return result.lastrowid
|
||||||
|
Loading…
Reference in New Issue
Block a user