mirror of
https://gitea.tendokyu.moe/AttackVector/AVNetwork.git
synced 2026-09-22 22:27:58 +03:00
480 lines
19 KiB
Python
480 lines
19 KiB
Python
import re
|
|
from database import (
|
|
getDMGFPlaylogbyToken,
|
|
getDMGFProfileDetailsbyToken,
|
|
getDMGFProfileExtbyToken,
|
|
getEacnetProfilebyToken,
|
|
getDMGFProfilebyToken,
|
|
add_user_DMGF,
|
|
manage_user_DMGF,
|
|
manage_user_DMGF_Details,
|
|
update_DMGF_playlog,
|
|
)
|
|
from variables.strings.games.gitadora import (
|
|
gitadoraNewPlayerData,
|
|
gitadoraPlayerData,
|
|
gitadoraRegisterData,
|
|
gitadoraMusicDB,
|
|
gitadoraFullPlayerData,
|
|
gitadoraGameStatus,
|
|
gitadoraGameEnd,
|
|
gitadoraStageResult,
|
|
gitadoraMusicItem,
|
|
customDataDefault,
|
|
favMusicDefault
|
|
)
|
|
from variables.strings.common import genericError
|
|
from variables.protocols import EAC_XML, EAC_RESULT
|
|
from time import time
|
|
from random import choices
|
|
import xmltodict
|
|
|
|
|
|
def clamp_u64(value):
|
|
"""Clamp value to valid u64 range"""
|
|
try:
|
|
val = int(float(value))
|
|
return max(0, min(val, 18446744073709551615))
|
|
except:
|
|
return 0
|
|
|
|
def knst_cardutil_return(playStyle, userProfile, playerIdentification):
|
|
skill = 0
|
|
allSkill = 0
|
|
if playStyle == "GF":
|
|
skill = userProfile.GFskill
|
|
allSkill = userProfile.GFallSkill
|
|
elif playStyle == "DM":
|
|
skill = userProfile.DMskill
|
|
allSkill = userProfile.DMallSkill
|
|
return gitadoraPlayerData.format(refid=playerIdentification.refid,snsid=playerIdentification.snsid,usercode=userProfile.usercode,skill=skill,allSkill=allSkill).encode()
|
|
|
|
def gitadoraRelay(module, method, data, playerToken):
|
|
print(f"{module} {method}")
|
|
playerIdentification = getEacnetProfilebyToken(playerToken)
|
|
|
|
playStyle = data.get("gametype", {}).get("#text", "U32:J:A") # Default to GF if playstyle is not avalible
|
|
match playStyle:
|
|
case "U32:J:A":
|
|
playStyle = "GF"
|
|
case "U32:J:B":
|
|
playStyle = "DM"
|
|
|
|
match module:
|
|
case "knst_playablemusic":
|
|
match method:
|
|
case "get":
|
|
return gitadoraMusicDB
|
|
case "knst_gameinfo":
|
|
match method:
|
|
case "get":
|
|
return gitadoraGameStatus
|
|
case "knst_cardutil":
|
|
match method:
|
|
case "check":
|
|
userProfile = getDMGFProfilebyToken(playerToken)
|
|
if userProfile is None:
|
|
return gitadoraNewPlayerData
|
|
return knst_cardutil_return(playStyle,userProfile,playerIdentification)
|
|
|
|
case "regist":
|
|
newUserCode = ''.join(choices('0123456789ABCDEF', k=10))
|
|
userProfile = getDMGFProfilebyToken(playerToken)
|
|
userProfileExt = getDMGFProfileExtbyToken(playerToken)
|
|
userProfileDetails = getDMGFProfileDetailsbyToken(playerToken)
|
|
if userProfile is None:
|
|
manage_user_DMGF_Details(playerIdentification.refid,playerToken,[],"")
|
|
manage_user_DMGF(playerIdentification.refid,playerToken,"","","","")
|
|
newUser = add_user_DMGF(playerIdentification.refid,playerToken,playerIdentification.snsid,newUserCode)
|
|
if newUser is not None:
|
|
return gitadoraRegisterData.format(refid=playerIdentification.refid,snsid=playerIdentification.snsid,usercode=newUserCode).encode()
|
|
else:
|
|
print("throwing generic error")
|
|
return genericError.format(protocol=EAC_XML,result=EAC_RESULT)
|
|
# Something went wrong with the user Registration, and it needs to start over again.
|
|
else:
|
|
print("Registering new card for user ")
|
|
return gitadoraRegisterData.format(refid=playerIdentification.refid,snsid=playerIdentification.snsid,usercode=newUserCode).encode()
|
|
case "knst_gametop":
|
|
match method:
|
|
case "get":
|
|
userProfile = getDMGFProfilebyToken(playerToken)
|
|
userProfileExt = getDMGFProfileExtbyToken(playerToken)
|
|
userProfileDetails = getDMGFProfileDetailsbyToken(playerToken)
|
|
stageResult = '<stage_result />'
|
|
musiclist = '<musiclist nr="0" />'
|
|
playlogs = getDMGFPlaylogbyToken(playerToken, playStyle)
|
|
playstyle = customDataDefault
|
|
custom = customDataDefault
|
|
lastCategory = 0
|
|
lastMusicID = -1
|
|
lastSeq = 0
|
|
dispLevel = 0
|
|
cabid = 0
|
|
play = 0
|
|
playtime = 0
|
|
playterm = 0
|
|
session_cnt = 0
|
|
matching_num = 0
|
|
extra_stage = 0
|
|
extra_play = 0
|
|
extra_clear = 0
|
|
encore_play = 0
|
|
encore_clear = 0
|
|
pencore_play = 0
|
|
pencore_clear = 0
|
|
max_clear_diff = 0
|
|
max_full_diff = 0
|
|
max_exce_diff = 0
|
|
clear_num = 0
|
|
full_num = 0
|
|
exce_num = 0
|
|
no_num = 0
|
|
e_num = 0
|
|
d_num = 0
|
|
c_num = 0
|
|
b_num = 0
|
|
a_num = 0
|
|
s_num = 0
|
|
ss_num = 0
|
|
musicFavorites1 = favMusicDefault
|
|
musicFavorites2 = favMusicDefault
|
|
musicFavorites3 = favMusicDefault
|
|
|
|
if playlogs and len(playlogs) > 0:
|
|
gitadoraMusicDBdict = xmltodict.parse(gitadoraMusicDB.decode())
|
|
# Generate stage results
|
|
musicItems = {} # Dictionary to store music data grouped by musicid
|
|
|
|
# Group playlogs by musicid
|
|
for playlog in playlogs:
|
|
if playlog.musicid not in musicItems:
|
|
musicItems[playlog.musicid] = {
|
|
'musicid': playlog.musicid,
|
|
'sequences': {
|
|
1: None, # Guitar Basic
|
|
2: None, # Guitar Advanced
|
|
3: None, # Guitar Extreme
|
|
4: None, # Guitar Master
|
|
5: None, # Bass Basic
|
|
6: None, # Bass Advanced
|
|
7: None, # Bass Extreme
|
|
8: None # Bass Master
|
|
}
|
|
}
|
|
|
|
# Get current data for this sequence
|
|
current_data = musicItems[playlog.musicid]['sequences'][playlog.seq]
|
|
|
|
# Determine if we should replace the existing data
|
|
should_replace = False
|
|
if current_data is None:
|
|
should_replace = True
|
|
else:
|
|
# Check importance ladder
|
|
if playlog.excellent:
|
|
# Replace if current isn't excellent or if both excellent but new perc is higher
|
|
if not current_data['excellent'] or (current_data['excellent'] and playlog.perc > current_data['perc']):
|
|
should_replace = True
|
|
elif playlog.fullcombo:
|
|
# Replace if current isn't excellent and isn't fullcombo
|
|
if not current_data['excellent'] and not current_data['fullcombo']:
|
|
should_replace = True
|
|
elif playlog.clear:
|
|
# Replace if current isn't excellent, isn't fullcombo, and isn't clear
|
|
if not current_data['excellent'] and not current_data['fullcombo'] and not current_data['clear']:
|
|
should_replace = True
|
|
|
|
# Only update if we should replace
|
|
if should_replace:
|
|
musicItems[playlog.musicid]['sequences'][playlog.seq] = {
|
|
'stage_no': playlog.stage_no,
|
|
'skill': playlog.skill,
|
|
'new_skill': playlog.new_skill,
|
|
'clear': playlog.clear,
|
|
'auto_clear': playlog.auto_clear,
|
|
'fullcombo': playlog.fullcombo,
|
|
'excellent': playlog.excellent,
|
|
'medal': playlog.medal,
|
|
'perc': playlog.perc,
|
|
'new_perc': playlog.new_perc,
|
|
'rank': playlog.rank,
|
|
'score': playlog.score,
|
|
'combo': playlog.combo,
|
|
'max_combo_perc': playlog.max_combo_perc,
|
|
'flags': playlog.flags,
|
|
'phrase_combo_perc': playlog.phrase_combo_perc,
|
|
'meter': playlog.meter,
|
|
'meter_prog': playlog.meter_prog
|
|
}
|
|
|
|
musiclistPrep = ""
|
|
musiclistLength = 0
|
|
for musicid, data in musicItems.items():
|
|
print(musicid)
|
|
|
|
flagFC = 0
|
|
flagEX = 0
|
|
flagCLR = 0
|
|
|
|
# Initialize arrays with correct length and default values
|
|
meter = ["0"]*8 # Array of 8 zeros as strings
|
|
meterProg = [0]*8 # Array of 8 zeros
|
|
mdata = [-1] + [-1]*14 + [0]*2 # 17 elements total
|
|
|
|
sdataSeq = -1
|
|
sdataSkill = -1
|
|
best_skill = -1 # Track the best skill
|
|
|
|
for seq, seqData in data["sequences"].items():
|
|
try:
|
|
seq = int(seq)
|
|
print(f"Processing sequence {seq} with data:", seqData)
|
|
|
|
if seqData is not None:
|
|
# Update skill data if this sequence has a higher skill
|
|
if seqData["skill"] > best_skill:
|
|
best_skill = seqData["skill"]
|
|
sdataSeq = seq
|
|
sdataSkill = seqData["skill"]
|
|
|
|
flagFC += seqData["fullcombo"] * 2**seq
|
|
flagEX += seqData["excellent"] * 2**seq
|
|
flagCLR += seqData["clear"] * 2**seq
|
|
|
|
# Safely handle meter values
|
|
if seqData["meter"]:
|
|
try:
|
|
# Clamp meter value to valid u64 range
|
|
meter[seq-1] = str(clamp_u64(seqData["meter"]))
|
|
except Exception as e:
|
|
print(f"Error processing meter for seq {seq}: {e}")
|
|
meter[seq-1] = "0"
|
|
|
|
try:
|
|
meterProg[seq-1] = int(seqData["meter_prog"])
|
|
except (ValueError, TypeError):
|
|
print(f"Invalid meter_prog value for seq {seq}: {seqData['meter_prog']}")
|
|
meterProg[seq-1] = 0
|
|
|
|
# Only set perc/rank if the chart was cleared
|
|
if seqData["clear"]:
|
|
try:
|
|
mdata[seq] = int(seqData.get("perc", -2))
|
|
mdata[seq+8] = int(seqData.get("rank", 0))
|
|
except (ValueError, TypeError) as e:
|
|
print(f"Error processing perc/rank for seq {seq}: {e}")
|
|
mdata[seq] = -2
|
|
mdata[seq+8] = 0
|
|
|
|
except Exception as e:
|
|
print(f"Error processing sequence {seq}: {e}")
|
|
continue
|
|
|
|
# Format the music item
|
|
musiclistPrep += gitadoraMusicItem.format(
|
|
musicId=musicid,
|
|
flag=f"{flagFC} {flagEX} {flagCLR} 0",
|
|
sdata=f"{sdataSeq} {sdataSkill}",
|
|
mdata=" ".join(str(x) for x in mdata),
|
|
meter=" ".join(meter),
|
|
meterProg=" ".join(str(x) for x in meterProg)
|
|
)
|
|
musiclistLength += 1
|
|
|
|
musiclist = f'<musiclist nr="{musiclistLength}">{musiclistPrep}</musiclist>'
|
|
# constructing the stageResults
|
|
stageResults = ""
|
|
for playlog in playlogs:
|
|
# Find the musicid in the gitadoraMusicDBdict
|
|
# Find the matching music entry in the musicinfo list
|
|
music_info = None
|
|
for music in gitadoraMusicDBdict["eacnet"]["response"]["knst_playablemusic"]["musicinfo"]["music"]:
|
|
if music["id"]["#text"] == str(playlog.musicid):
|
|
music_info = music
|
|
break
|
|
stageResults += gitadoraStageResult.format(
|
|
dateMs=playlog.date_ms,
|
|
stage=playlog.stage_no,
|
|
skill=playlog.skill,
|
|
musicId=playlog.musicid,
|
|
diff=music_info["diff"]["#text"].split()[playlog.seq], # Get difficulty from music_info
|
|
seqmode=playlog.seq,
|
|
musicTitle=music_info.get("music_title", {}).get("#text", ""),
|
|
musicArtist=music_info.get("artist", {}).get("#text", ""),
|
|
rightsCredits=music_info.get("right_credit", {}).get("#text", ""),
|
|
clearStatus=playlog.clear,
|
|
rank=playlog.rank,
|
|
perfect=playlog.perfect,
|
|
great=playlog.great,
|
|
good=playlog.good,
|
|
ok=playlog.ok,
|
|
miss=playlog.miss,
|
|
perfectPerc=playlog.perfect_perc,
|
|
greatPerc=playlog.great_perc,
|
|
goodPerc=playlog.good_perc,
|
|
okPerc=playlog.ok_perc,
|
|
missPerc=playlog.miss_perc,
|
|
maxCombo=playlog.combo,
|
|
maxComboPerc=playlog.max_combo_perc,
|
|
score=playlog.score,
|
|
flags=playlog.flags,
|
|
point=playlog.skill, # Using skill as point
|
|
newPoint=playlog.new_skill,
|
|
perc=playlog.perc,
|
|
newPerc=playlog.new_perc,
|
|
meter=playlog.meter,
|
|
meterProg=playlog.meter_prog,
|
|
beforeMeter=playlog.before_meter,
|
|
beforeMeterProg=playlog.before_meter_prog,
|
|
isNewMeter=playlog.is_new_meter,
|
|
phraseDataNum=playlog.phrase_data_num,
|
|
phraseAddr=playlog.phrase_addr,
|
|
phraseType=playlog.phrase_type,
|
|
phraseStatus=playlog.phrase_status,
|
|
phraseEndAddr=playlog.phrase_end_addr,
|
|
phraseComboPerc=playlog.phrase_combo_perc
|
|
)
|
|
|
|
if stageResults:
|
|
stageResult = f"<stage_result>{stageResults}</stage_result>"
|
|
else:
|
|
stageResult = "<stage_result />"
|
|
|
|
if playStyle == "GF":
|
|
playstyle = userProfileExt.GFplaystyle
|
|
custom = userProfileExt.GFcustom
|
|
lastCategory = userProfileExt.GFlastCategory
|
|
lastMusicID = userProfileExt.GFlastMusic
|
|
lastSeq = userProfileExt.GFlastSeq
|
|
dispLevel = userProfileExt.GFdisplayLevel
|
|
cabid = userProfileDetails.GFcabid
|
|
play = userProfileDetails.GFplay
|
|
playtime = userProfileDetails.GFplaytime
|
|
playterm = userProfileDetails.GFplayterm
|
|
session_cnt = userProfileDetails.GFsession_cnt
|
|
matching_num = userProfileDetails.GFmatching_num
|
|
extra_stage = userProfileDetails.GFextra_stage
|
|
extra_play = userProfileDetails.GFextra_play
|
|
extra_clear = userProfileDetails.GFextra_clear
|
|
encore_play = userProfileDetails.GFencore_play
|
|
encore_clear = userProfileDetails.GFencore_clear
|
|
pencore_play = userProfileDetails.GFpencore_play
|
|
pencore_clear = userProfileDetails.GFpencore_clear
|
|
max_clear_diff = userProfileDetails.GFmax_clear_diff
|
|
max_full_diff = userProfileDetails.GFmax_full_diff
|
|
max_exce_diff = userProfileDetails.GFmax_exce_diff
|
|
clear_num = userProfileDetails.GFclear_num
|
|
full_num = userProfileDetails.GFfull_num
|
|
exce_num = userProfileDetails.GFexce_num
|
|
no_num = userProfileDetails.GFno_num
|
|
e_num = userProfileDetails.GFe_num
|
|
d_num = userProfileDetails.GFd_num
|
|
c_num = userProfileDetails.GFc_num
|
|
b_num = userProfileDetails.GFb_num
|
|
a_num = userProfileDetails.GFa_num
|
|
s_num = userProfileDetails.GFs_num
|
|
ss_num = userProfileDetails.GFss_num
|
|
musicFavorites1 = userProfileExt.GFmusicFavorites1
|
|
musicFavorites2 = userProfileExt.GFmusicFavorites2
|
|
musicFavorites3 = userProfileExt.GFmusicFavorites3
|
|
elif playStyle == "DM":
|
|
playstyle = userProfileExt.DMplaystyle
|
|
custom = userProfileExt.DMcustom
|
|
lastCategory = userProfileExt.DMlastCategory
|
|
lastMusicID = userProfileExt.DMlastMusic
|
|
lastSeq = userProfileExt.DMlastSeq
|
|
dispLevel = userProfileExt.DMdisplayLevel
|
|
cabid = userProfileDetails.DMcabid
|
|
play = userProfileDetails.DMplay
|
|
playtime = userProfileDetails.DMplaytime
|
|
playterm = userProfileDetails.DMplayterm
|
|
session_cnt = userProfileDetails.DMsession_cnt
|
|
matching_num = userProfileDetails.DMmatching_num
|
|
extra_stage = userProfileDetails.DMextra_stage
|
|
extra_play = userProfileDetails.DMextra_play
|
|
extra_clear = userProfileDetails.DMextra_clear
|
|
encore_play = userProfileDetails.DMencore_play
|
|
encore_clear = userProfileDetails.DMencore_clear
|
|
pencore_play = userProfileDetails.DMpencore_play
|
|
pencore_clear = userProfileDetails.DMpencore_clear
|
|
max_clear_diff = userProfileDetails.DMmax_clear_diff
|
|
max_full_diff = userProfileDetails.DMmax_full_diff
|
|
max_exce_diff = userProfileDetails.DMmax_exce_diff
|
|
clear_num = userProfileDetails.DMclear_num
|
|
full_num = userProfileDetails.DMfull_num
|
|
exce_num = userProfileDetails.DMexce_num
|
|
no_num = userProfileDetails.DMno_num
|
|
e_num = userProfileDetails.DMe_num
|
|
d_num = userProfileDetails.DMd_num
|
|
c_num = userProfileDetails.DMc_num
|
|
b_num = userProfileDetails.DMb_num
|
|
a_num = userProfileDetails.DMa_num
|
|
s_num = userProfileDetails.DMs_num
|
|
ss_num = userProfileDetails.DMss_num
|
|
musicFavorites1 = userProfileExt.DMmusicFavorites1
|
|
musicFavorites2 = userProfileExt.DMmusicFavorites2
|
|
musicFavorites3 = userProfileExt.DMmusicFavorites3
|
|
return gitadoraFullPlayerData.format(
|
|
refid=playerIdentification.refid,
|
|
snsid=playerIdentification.snsid,
|
|
usercode=userProfile.usercode,
|
|
time=int(time()),
|
|
playstyle=playstyle,
|
|
custom=custom,
|
|
lastCategory=lastCategory,
|
|
lastMusicID=lastMusicID,
|
|
lastSeq=lastSeq,
|
|
dispLevel=dispLevel,
|
|
cabid=cabid,
|
|
play=play,
|
|
playtime=playtime,
|
|
playterm=playterm,
|
|
session_cnt=session_cnt,
|
|
matching_num=matching_num,
|
|
extra_stage=extra_stage,
|
|
extra_play=extra_play,
|
|
extra_clear=extra_clear,
|
|
encore_play=encore_play,
|
|
encore_clear=encore_clear,
|
|
pencore_play=pencore_play,
|
|
pencore_clear=pencore_clear,
|
|
max_clear_diff=max_clear_diff,
|
|
max_full_diff=max_full_diff,
|
|
max_exce_diff=max_exce_diff,
|
|
clear_num=clear_num,
|
|
full_num=full_num,
|
|
exce_num=exce_num,
|
|
no_num=no_num,
|
|
e_num=e_num,
|
|
d_num=d_num,
|
|
c_num=c_num,
|
|
b_num=b_num,
|
|
a_num=a_num,
|
|
s_num=s_num,
|
|
ss_num=ss_num,
|
|
musicFavorites1=musicFavorites1,
|
|
musicFavorites2=musicFavorites2,
|
|
musicFavorites3=musicFavorites3,
|
|
stageResult=stageResult,
|
|
musicList=musiclist
|
|
).encode()
|
|
case "knst_gameend":
|
|
match method:
|
|
case "regist": # game is saved here, every time you complete a song
|
|
playerData = data["player"]
|
|
customData = playerData["customdata"]
|
|
skillData = playerData["skilldata"]
|
|
record = playerData["record"]
|
|
favoritemusic = playerData["favoritemusic"]
|
|
playinfo = playerData["playinfo"]
|
|
stage = playerData.get("stage", {})
|
|
|
|
manage_user_DMGF(playerIdentification.refid,playerToken,customData,favoritemusic,playinfo,playStyle)
|
|
manage_user_DMGF_Details(playerIdentification.refid,playerToken,playinfo,playStyle)
|
|
if stage:
|
|
update_DMGF_playlog(playerIdentification.refid, playerToken, stage,playStyle)
|
|
return gitadoraGameEnd
|
|
case _: # Backup Case
|
|
return b"NoMatches"
|