From 1d6530b4ddfdd919acb353f18a72052fe4a06d5f Mon Sep 17 00:00:00 2001 From: 573dev <> Date: Thu, 12 Nov 2020 22:02:20 -0600 Subject: [PATCH] Save more game end data --- v8_server/eamuse/services/cardutil.py | 26 ++++++++- v8_server/eamuse/services/customize.py | 11 ++++ v8_server/eamuse/services/gameend.py | 55 ++++++++++++++----- v8_server/eamuse/services/gametop.py | 28 ++++------ .../eamuse/xml/templates/cardutil/check.xml | 8 +-- v8_server/model/types.py | 24 ++++++++ v8_server/model/user.py | 41 ++++++++++++++ 7 files changed, 156 insertions(+), 37 deletions(-) create mode 100644 v8_server/model/types.py diff --git a/v8_server/eamuse/services/cardutil.py b/v8_server/eamuse/services/cardutil.py index 66e5d9f..e5d3397 100644 --- a/v8_server/eamuse/services/cardutil.py +++ b/v8_server/eamuse/services/cardutil.py @@ -6,7 +6,7 @@ from lxml import etree from v8_server import db from v8_server.eamuse.services.services import ServiceRequest from v8_server.eamuse.xml.utils import get_xml_attrib, load_xml_template -from v8_server.model.user import User, UserAccount +from v8_server.model.user import User, UserAccount, UserData from v8_server.utils.convert import int_to_bool as itob @@ -81,10 +81,16 @@ class Check(object): } # Existing User - if not new_user and account is not None: + if not new_user and account is not None and user is not None: + user_data = user.user_data + # TODO: Add GDP, skill, all_skill here args = { "state": CheckStatus.EXISTING_USER, "name": account.name, + "gdp": 0, + "skill": 0, + "all_skill": 0, + "syogo": " ".join(map(str, user_data.syogo)), "chara": account.chara, } drop_children = None @@ -156,6 +162,22 @@ class Regist(object): is_succession=self.data.is_succession, ) db.session.add(user_account) + + user_data = UserData( + userid=user.userid, + style=2097152, + style_2=0, + secret_music=[0 for _ in range(0, 32)], + secret_chara=0, + syogo=[0, 0], + perfect=0, + great=0, + good=0, + poor=0, + miss=0, + time=0, + ) + db.session.add(user_data) db.session.commit() return load_xml_template("cardutil", "regist") diff --git a/v8_server/eamuse/services/customize.py b/v8_server/eamuse/services/customize.py index 5a5bcbc..929087b 100644 --- a/v8_server/eamuse/services/customize.py +++ b/v8_server/eamuse/services/customize.py @@ -2,8 +2,10 @@ import logging from lxml import etree +from v8_server import db from v8_server.eamuse.services.services import ServiceRequest from v8_server.eamuse.xml.utils import get_xml_attrib, load_xml_template +from v8_server.model.user import User logger = logging.getLogger(__name__) @@ -79,4 +81,13 @@ class Regist(object): return f"Customize.Regist" def response(self) -> etree: + # Save the syogo data (assume single player right now) + user = User.from_refid(self.players[0].refid) + if user is None: + raise Exception("user should not be none") + + user_data = user.user_data + user_data.syogo = self.players[0].syogodata.get.syogo + db.session.commit() + return load_xml_template("customize", "regist") diff --git a/v8_server/eamuse/services/gameend.py b/v8_server/eamuse/services/gameend.py index 4959884..df70a71 100644 --- a/v8_server/eamuse/services/gameend.py +++ b/v8_server/eamuse/services/gameend.py @@ -7,7 +7,7 @@ from v8_server import db from v8_server.eamuse.services.services import ServiceRequest from v8_server.eamuse.xml.utils import get_xml_attrib, load_xml_template from v8_server.model.song import HitChart -from v8_server.model.user import User, UserData +from v8_server.model.user import PlayData, User, UserData from v8_server.utils.convert import int_to_bool as itob @@ -247,12 +247,12 @@ class Playdata(object): def __init__(self, root: etree) -> None: self.no = int(root.find("no").text) self.seqmode = int(root.find("seqmode").text) - self.clear = int(root.find("clear").text) - self.auto_clear = int(root.find("auto_clear").text) + self.clear = itob(int(root.find("clear").text)) + self.auto_clear = itob(int(root.find("auto_clear").text)) self.score = int(root.find("score").text) self.flags = int(root.find("flags").text) - self.fullcombo = int(root.find("fullcombo").text) - self.excellent = int(root.find("excellent").text) + self.fullcombo = itob(int(root.find("fullcombo").text)) + self.excellent = itob(int(root.find("excellent").text)) self.combo = int(root.find("combo").text) self.skill_point = int(root.find("skill_point").text) self.skill_perc = int(root.find("skill_perc").text) @@ -456,20 +456,47 @@ class Regist(object): user_data = UserData.from_userid(user.userid) if user_data is None: - user_data = UserData( - userid=user.userid, - style=playerinfo.styles, - style_2=playerinfo.styles_2, - ) - db.session.add(user_data) - else: - user_data.style = playerinfo.styles - user_data.style_2 = playerinfo.styles_2 + raise Exception("user data shouldn't be none here") + user_data.style = playerinfo.styles + user_data.style_2 = playerinfo.styles_2 + user_data.secret_music = playerinfo.secret_music + user_data.secret_chara = playerinfo.secret_chara + user_data.perfect = playerinfo.perfect + user_data.great = playerinfo.great + user_data.good = playerinfo.good + user_data.poor = playerinfo.poor + user_data.miss = playerinfo.miss + user_data.time = playerinfo.time db.session.commit() else: raise Exception("This user doesn't exist") + # Save playdata + for idx, data in enumerate(self.player.playdata): + musicid = self.modedata.stages[idx].musicid + play_data = PlayData( + userid=user.userid, + no=data.no, + musicid=musicid, + seqmode=data.seqmode, + clear=data.clear, + auto_clear=data.auto_clear, + score=data.score, + flags=data.flags, + fullcombo=data.fullcombo, + excellent=data.excellent, + combo=data.combo, + skill_point=data.skill_point, + skill_perc=data.skill_perc, + result_rank=data.result_rank, + difficulty=data.difficulty, + combo_rate=data.combo_rate, + perfect_rate=data.perfect_rate, + ) + db.session.add(play_data) + db.session.commit() + # Just send back a dummy object for now now_time = datetime.now().strftime(self.DT_FMT) diff --git a/v8_server/eamuse/services/gametop.py b/v8_server/eamuse/services/gametop.py index f3620f6..8fdaeda 100644 --- a/v8_server/eamuse/services/gametop.py +++ b/v8_server/eamuse/services/gametop.py @@ -4,8 +4,8 @@ from lxml import etree from v8_server.eamuse.services.services import ServiceRequest from v8_server.eamuse.utils.crc import calculate_crc8 -from v8_server.eamuse.xml.utils import fill, get_xml_attrib, load_xml_template -from v8_server.model.user import User, UserData +from v8_server.eamuse.xml.utils import get_xml_attrib, load_xml_template +from v8_server.model.user import User logger = logging.getLogger(__name__) @@ -77,14 +77,10 @@ class Get(object): def response(self) -> etree: # Grab user_data user = User.from_refid(self.player.refid) - style = 2097152 - style_2 = 0 - if user is not None: - user_data = UserData.from_userid(user.userid) + if user is None: + raise Exception("User should not be none here") - if user_data is not None: - style = user_data.style - style_2 = user_data.style_2 + user_data = user.user_data # Generate history rounds (blank for now) history_rounds = "" @@ -99,16 +95,14 @@ class Get(object): load_xml_template("gametop", "get.music_hist.round") ).decode("UTF-8") - secret_music = fill(32) - secret_chara = 0 - tag = calculate_crc8( - str(sum(int(x) for x in secret_music.split()) + secret_chara) - ) + secret_music = user_data.secret_music + secret_chara = user_data.secret_chara + tag = calculate_crc8(str(sum(secret_music) + secret_chara)) args = { - "secret_music": secret_music, - "style": style, - "style_2": style_2, + "secret_music": " ".join(map(str, secret_music)), + "style": user_data.style, + "style_2": user_data.style_2, "secret_chara": secret_chara, "tag": tag, "history_rounds": history_rounds, diff --git a/v8_server/eamuse/xml/templates/cardutil/check.xml b/v8_server/eamuse/xml/templates/cardutil/check.xml index 371c1bd..bee7267 100644 --- a/v8_server/eamuse/xml/templates/cardutil/check.xml +++ b/v8_server/eamuse/xml/templates/cardutil/check.xml @@ -3,11 +3,11 @@ 0 {name} - 0 - 0 - 0 + {gdp} + {skill} + {all_skill} {chara} - 0 0 + {syogo} 0 diff --git a/v8_server/model/types.py b/v8_server/model/types.py new file mode 100644 index 0000000..59381c2 --- /dev/null +++ b/v8_server/model/types.py @@ -0,0 +1,24 @@ +from typing import List + +from sqlalchemy.types import String, TypeDecorator + + +class IntArray(TypeDecorator): + impl = String + + def __init__(self, **kwargs) -> None: + super().__init__(None, **kwargs) + + def process_literal_param(self, value, dialect) -> str: + # Value will be an int array + if value is None: + return "" + return " ".join(map(str, value)) + + process_bind_param = process_literal_param + + def process_result_value(self, value, dialect) -> List[int]: + # Convert SQL String to Int List + if value is None: + return [] + return [int(x) for x in value.split()] diff --git a/v8_server/model/user.py b/v8_server/model/user.py index a4e6d51..7888990 100644 --- a/v8_server/model/user.py +++ b/v8_server/model/user.py @@ -9,6 +9,7 @@ from sqlalchemy.orm import relationship from sqlalchemy.types import Boolean, Integer, String from v8_server import db +from v8_server.model.types import IntArray BaseModel: DefaultMeta = db.Model @@ -31,6 +32,8 @@ class User(BaseModel): extids = relationship("ExtID", back_populates="user") refids = relationship("RefID", back_populates="user") user_account = relationship("UserAccount", uselist=False, back_populates="user") + user_data = relationship("UserData", uselist=False, back_populates="user") + play_data = relationship("PlayData", back_populates="user") def __repr__(self) -> str: return f'User' @@ -81,6 +84,16 @@ class UserData(BaseModel): userid = Column(Integer, ForeignKey("users.userid"), primary_key=True) style = Column(Integer, nullable=False) style_2 = Column(Integer, nullable=False) + secret_music = Column(IntArray, nullable=False) + secret_chara = Column(Integer, nullable=False) + syogo = Column(IntArray, nullable=False) + perfect = Column(Integer, nullable=False) + great = Column(Integer, nullable=False) + good = Column(Integer, nullable=False) + poor = Column(Integer, nullable=False) + miss = Column(Integer, nullable=False) + time = Column(Integer, nullable=False) + user = relationship("User", back_populates="user_data") @classmethod def from_userid(cls, userid: int) -> Optional[UserData]: @@ -88,6 +101,34 @@ class UserData(BaseModel): return q.one_or_none() +class PlayData(BaseModel): + """ + Store play data, every stage that a user has played + """ + + __tablename__ = "play_data" + + playid = Column(Integer, primary_key=True) + userid = Column(Integer, ForeignKey("users.userid"), nullable=False) + no = Column(Integer, nullable=False) + musicid = Column(Integer, nullable=False) + seqmode = Column(Integer, nullable=False) + clear = Column(Boolean, nullable=False) + auto_clear = Column(Boolean, nullable=False) + score = Column(Integer, nullable=False) + flags = Column(Integer, nullable=False) + fullcombo = Column(Boolean, nullable=False) + excellent = Column(Boolean, nullable=False) + combo = Column(Integer, nullable=False) + skill_point = Column(Integer, nullable=False) + skill_perc = Column(Integer, nullable=False) + result_rank = Column(Integer, nullable=False) + difficulty = Column(Integer, nullable=False) + combo_rate = Column(Integer, nullable=False) + perfect_rate = Column(Integer, nullable=False) + user = relationship("User", back_populates="play_data") + + class Card(BaseModel): """ Table representing a card associated with a user. Users may have zero or more cards