forked from Hay1tsme/artemis
add back games, conform them to new title dispatch
This commit is contained in:
18
titles/diva/__init__.py
Normal file
18
titles/diva/__init__.py
Normal file
@ -0,0 +1,18 @@
|
||||
from titles.diva.index import DivaServlet
|
||||
from titles.diva.const import DivaConstants
|
||||
from titles.diva.database import DivaData
|
||||
from titles.diva.read import DivaReader
|
||||
|
||||
index = DivaServlet
|
||||
database = DivaData
|
||||
reader = DivaReader
|
||||
|
||||
use_default_title = True
|
||||
include_protocol = True
|
||||
title_secure = False
|
||||
game_codes = [DivaConstants.GAME_CODE]
|
||||
trailing_slash = True
|
||||
use_default_host = False
|
||||
host = ""
|
||||
|
||||
current_schema_version = 1
|
506
titles/diva/base.py
Normal file
506
titles/diva/base.py
Normal file
@ -0,0 +1,506 @@
|
||||
import datetime
|
||||
from typing import Any, List, Dict
|
||||
import logging
|
||||
import json
|
||||
import urllib
|
||||
|
||||
from core.config import CoreConfig
|
||||
from titles.diva.config import DivaConfig
|
||||
from titles.diva.const import DivaConstants
|
||||
from titles.diva.database import DivaData
|
||||
|
||||
class DivaBase():
|
||||
def __init__(self, cfg: CoreConfig, game_cfg: DivaConfig) -> None:
|
||||
self.core_cfg = cfg # Config file
|
||||
self.game_config = game_cfg
|
||||
self.data = DivaData(cfg) # Database
|
||||
self.date_time_format = "%Y-%m-%d %H:%M:%S"
|
||||
self.logger = logging.getLogger("diva")
|
||||
self.game = DivaConstants.GAME_CODE
|
||||
self.version = DivaConstants.VER_PROJECT_DIVA_ARCADE_FUTURE_TONE
|
||||
|
||||
dt = datetime.datetime.now()
|
||||
self.time_lut=urllib.parse.quote(dt.strftime("%Y-%m-%d %H:%M:%S:16.0"))
|
||||
|
||||
def handle_test_request(self, data: Dict) -> Dict:
|
||||
return ""
|
||||
|
||||
def handle_game_init_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_attend_request(self, data: Dict) -> Dict:
|
||||
encoded = "&"
|
||||
params = {
|
||||
'atnd_prm1': '0,1,1,0,0,0,1,0,100,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1',
|
||||
'atnd_prm2': '30,10,100,4,1,50,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1',
|
||||
'atnd_prm3': '100,0,1,1,1,1,1,1,1,1,2,3,4,1,1,1,3,4,5,1,1,1,4,5,6,1,1,1,5,6,7,4,4,4,9,10,14,5,10,10,25,20,50,30,90,5,10,10,25,20,50,30,90,5,10,10,25,20,50,30,90,5,10,10,25,20,50,30,90,5,10,10,25,20,50,30,90,10,30,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0',
|
||||
'atnd_lut': f'{self.time_lut}',
|
||||
}
|
||||
|
||||
encoded += urllib.parse.urlencode(params)
|
||||
encoded = encoded.replace("%2C", ",")
|
||||
|
||||
return encoded
|
||||
|
||||
def handle_ping_request(self, data: Dict) -> Dict:
|
||||
encoded = "&"
|
||||
params = {
|
||||
'ping_b_msg': f'Welcome to {self.core_cfg.server.name} network!',
|
||||
'ping_m_msg': 'xxx',
|
||||
'atnd_lut': f'{self.time_lut}',
|
||||
'fi_lut': f'{self.time_lut}',
|
||||
'ci_lut': f'{self.time_lut}',
|
||||
'qi_lut': f'{self.time_lut}',
|
||||
'pvl_lut': '2021-05-22 12:08:16.0',
|
||||
'shp_ctlg_lut': '2020-06-10 19:44:16.0',
|
||||
'cstmz_itm_ctlg_lut': '2019-10-08 20:23:12.0',
|
||||
'ngwl_lut': '2019-10-08 20:23:12.0',
|
||||
'rnk_nv_lut': '2020-06-10 19:51:30.0',
|
||||
'rnk_ps_lut': f'{self.time_lut}',
|
||||
'bi_lut': '2020-09-18 10:00:00.0',
|
||||
'cpi_lut': '2020-10-25 09:25:10.0',
|
||||
'bdlol_lut': '2020-09-18 10:00:00.0',
|
||||
'p_std_hc_lut': '2019-08-01 04:00:36.0',
|
||||
'p_std_i_n_lut': '2019-08-01 04:00:36.0',
|
||||
'pdcl_lut': '2019-08-01 04:00:36.0',
|
||||
'pnml_lut': '2019-08-01 04:00:36.0',
|
||||
'cinml_lut': '2019-08-01 04:00:36.0',
|
||||
'rwl_lut': '2019-08-01 04:00:36.0',
|
||||
'req_inv_cmd_num': '-1,-1,-1,-1,-1,-1,-1,-1,-1,-1',
|
||||
'req_inv_cmd_prm1': '-1,-1,-1,-1,-1,-1,-1,-1,-1,-1',
|
||||
'req_inv_cmd_prm2': '-1,-1,-1,-1,-1,-1,-1,-1,-1,-1',
|
||||
'req_inv_cmd_prm3': '-1,-1,-1,-1,-1,-1,-1,-1,-1,-1',
|
||||
'req_inv_cmd_prm4': '-1,-1,-1,-1,-1,-1,-1,-1,-1,-1',
|
||||
'pow_save_flg': 0,
|
||||
'nblss_dnt_p': 100,
|
||||
'nblss_ltt_rl_vp': 1500,
|
||||
'nblss_ex_ltt_flg': 1,
|
||||
'nblss_dnt_st_tm': "2019-07-15 12:00:00.0",
|
||||
'nblss_dnt_ed_tm': "2019-09-17 12:00:00.0",
|
||||
'nblss_ltt_st_tm': "2019-09-18 12:00:00.0",
|
||||
'nblss_ltt_ed_tm': "2019-09-22 12:00:00.0",
|
||||
}
|
||||
|
||||
encoded += urllib.parse.urlencode(params)
|
||||
encoded = encoded.replace("+", "%20")
|
||||
encoded = encoded.replace("%2C", ",")
|
||||
|
||||
return encoded
|
||||
|
||||
def handle_pv_list_request(self, data: Dict) -> Dict:
|
||||
pvlist = ""
|
||||
with open(r"titles/diva/data/PvList0.dat", encoding="utf-8") as shop:
|
||||
lines = shop.readlines()
|
||||
for line in lines:
|
||||
pvlist += f"{line}"
|
||||
pvlist += ","
|
||||
|
||||
with open(r"titles/diva/data/PvList1.dat", encoding="utf-8") as shop:
|
||||
lines = shop.readlines()
|
||||
for line in lines:
|
||||
pvlist += f"{line}"
|
||||
pvlist += ","
|
||||
|
||||
with open(r"titles/diva/data/PvList2.dat", encoding="utf-8") as shop:
|
||||
lines = shop.readlines()
|
||||
for line in lines:
|
||||
pvlist += f"{line}"
|
||||
pvlist += ","
|
||||
|
||||
with open(r"titles/diva/data/PvList3.dat", encoding="utf-8") as shop:
|
||||
lines = shop.readlines()
|
||||
for line in lines:
|
||||
pvlist += f"{line}"
|
||||
pvlist += ","
|
||||
|
||||
with open(r"titles/diva/data/PvList4.dat", encoding="utf-8") as shop:
|
||||
lines = shop.readlines()
|
||||
for line in lines:
|
||||
pvlist += f"{line}"
|
||||
|
||||
response = ""
|
||||
response += f"&pvl_lut={self.time_lut}"
|
||||
response += f"&pv_lst={pvlist}"
|
||||
|
||||
return ( response )
|
||||
|
||||
def handle_shop_catalog_request(self, data: Dict) -> Dict:
|
||||
catalog = ""
|
||||
|
||||
shopList = self.data.static.get_enabled_shop(self.version)
|
||||
if not shopList:
|
||||
with open(r"titles/diva/data/ShopCatalog.dat", encoding="utf-8") as shop:
|
||||
lines = shop.readlines()
|
||||
for line in lines:
|
||||
line = urllib.parse.quote(line) + ","
|
||||
catalog += f"{urllib.parse.quote(line)}"
|
||||
catalog = catalog.replace("+", "%20")
|
||||
|
||||
response = ""
|
||||
response += f"&shp_ctlg_lut={self.time_lut}"
|
||||
response += f"&shp_ctlg={catalog[:-3]}"
|
||||
else:
|
||||
for shop in shopList:
|
||||
line = str(shop["shopId"]) + "," + str(shop['unknown_0']) + "," + shop['name'] + "," + str(shop['points']) + "," + shop['start_date'] + "," + shop['end_date'] + "," + str(shop["type"])
|
||||
line = urllib.parse.quote(line) + ","
|
||||
catalog += f"{urllib.parse.quote(line)}"
|
||||
|
||||
catalog = catalog.replace("+", "%20")
|
||||
|
||||
response = ""
|
||||
response += f"&shp_ctlg_lut={self.time_lut}"
|
||||
response += f"&shp_ctlg={catalog[:-3]}"
|
||||
|
||||
return ( response )
|
||||
|
||||
def handle_cstmz_itm_ctlg_request(self, data: Dict) -> Dict:
|
||||
catalog = ""
|
||||
|
||||
itemList = self.data.static.get_enabled_items(self.version)
|
||||
if not itemList:
|
||||
with open(r"titles/diva/data/ItemCatalog.dat", encoding="utf-8") as item:
|
||||
lines = item.readlines()
|
||||
for line in lines:
|
||||
line = urllib.parse.quote(line) + ","
|
||||
catalog += f"{urllib.parse.quote(line)}"
|
||||
catalog = catalog.replace("+", "%20")
|
||||
|
||||
response = ""
|
||||
response += f"&cstmz_itm_ctlg_lut={self.time_lut}"
|
||||
response += f"&cstmz_itm_ctlg={catalog[:-3]}"
|
||||
else:
|
||||
for item in itemList:
|
||||
line = str(item["itemId"]) + "," + str(item['unknown_0']) + "," + item['name'] + "," + str(item['points']) + "," + item['start_date'] + "," + item['end_date'] + "," + str(item["type"])
|
||||
line = urllib.parse.quote(line) + ","
|
||||
catalog += f"{urllib.parse.quote(line)}"
|
||||
|
||||
catalog = catalog.replace("+", "%20")
|
||||
|
||||
response = ""
|
||||
response += f"&cstmz_itm_ctlg_lut={self.time_lut}"
|
||||
response += f"&cstmz_itm_ctlg={catalog[:-3]}"
|
||||
|
||||
return ( response )
|
||||
|
||||
def handle_festa_info_request(self, data: Dict) -> Dict:
|
||||
encoded = "&"
|
||||
params = {
|
||||
'fi_id': '1,-1',
|
||||
'fi_name': f'{self.core_cfg.server.name} Opening,xxx',
|
||||
'fi_kind': '0,0',
|
||||
'fi_difficulty': '-1,-1',
|
||||
'fi_pv_id_lst': 'ALL,ALL',
|
||||
'fi_attr': '7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',
|
||||
'fi_add_vp': '10,0',
|
||||
'fi_mul_vp': '1,1',
|
||||
'fi_st': '2022-06-17 17:00:00.0,2014-07-08 18:10:11.0',
|
||||
'fi_et': '2029-01-01 10:00:00.0,2014-07-08 18:10:11.0',
|
||||
'fi_lut': '{self.time_lut}',
|
||||
}
|
||||
|
||||
encoded += urllib.parse.urlencode(params)
|
||||
encoded = encoded.replace("+", "%20")
|
||||
encoded = encoded.replace("%2C", ",")
|
||||
|
||||
return encoded
|
||||
|
||||
def handle_contest_info_request(self, data: Dict) -> Dict:
|
||||
response = ""
|
||||
|
||||
response += f"&ci_lut={self.time_lut}"
|
||||
response += "&ci_str=%2A%2A%2A,%2A%2A%2A,%2A%2A%2A,%2A%2A%2A,%2A%2A%2A,%2A%2A%2A,%2A%2A%2A,%2A%2A%2A"
|
||||
|
||||
return ( response )
|
||||
|
||||
def handle_qst_inf_request(self, data: Dict) -> Dict:
|
||||
quest = ""
|
||||
|
||||
questList = self.data.static.get_enabled_quests(self.version)
|
||||
if not questList:
|
||||
with open(r"titles/diva/data/QuestInfo.dat", encoding="utf-8") as shop:
|
||||
lines = shop.readlines()
|
||||
for line in lines:
|
||||
quest += f"{urllib.parse.quote(line)},"
|
||||
|
||||
response = ""
|
||||
response += f"&qi_lut={self.time_lut}"
|
||||
response += f"&qhi_str={quest[:-1]}"
|
||||
else:
|
||||
for quests in questList:
|
||||
line = str(quests["questId"]) + "," + str(quests['quest_order']) + "," + str(quests['kind']) + "," + str(quests['unknown_0']) + "," + quests['start_datetime'] + "," + quests['end_datetime'] + "," + quests["name"] + "," + str(quests["unknown_1"]) + "," + str(quests["unknown_2"]) + "," + str(quests["quest_enable"])
|
||||
quest += f"{urllib.parse.quote(line)}%0A,"
|
||||
|
||||
responseline = f"{quest[:-1]},"
|
||||
for i in range(len(questList),59):
|
||||
responseline += "%2A%2A%2A%0A,"
|
||||
|
||||
response = ""
|
||||
response += f"&qi_lut={self.time_lut}"
|
||||
response += f"&qhi_str={responseline}%2A%2A%2A"
|
||||
|
||||
response += "&qrai_str=%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1,%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1,%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1%2C%2D1"
|
||||
|
||||
return ( response )
|
||||
|
||||
def handle_nv_ranking_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_ps_ranking_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_ng_word_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_rmt_wp_list_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_pv_def_chr_list_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_pv_ng_mdl_list_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_cstmz_itm_ng_mdl_lst_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_banner_info_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_banner_data_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_cm_ply_info_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_pstd_h_ctrl_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_pstd_item_ng_lst_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_pre_start_request(self, data: Dict) -> Dict:
|
||||
profile = self.data.profile.get_profile(data["aime_id"], self.version)
|
||||
profile_shop = self.data.item.get_shop(data["aime_id"], self.version)
|
||||
if profile is None:
|
||||
return ( f"&ps_result=-3")
|
||||
else:
|
||||
response = ""
|
||||
response += "&ps_result=1"
|
||||
response += f"&pd_id={data['aime_id']}"
|
||||
response += "&nblss_ltt_stts=-1"
|
||||
response += "&nblss_ltt_tckt=-1"
|
||||
response += "&nblss_ltt_is_opn=-1"
|
||||
response += f"&vcld_pts={profile['vcld_pts']}"
|
||||
response += f"&player_name={profile['player_name']}"
|
||||
response += f"&lv_efct_id={profile['lv_efct_id']}"
|
||||
response += f"&lv_plt_id={profile['lv_plt_id']}"
|
||||
response += f"&lv_str={profile['lv_str']}"
|
||||
response += f"&lv_num={profile['lv_num']}"
|
||||
response += f"&lv_pnt={profile['lv_pnt']}"
|
||||
|
||||
#Store stuff to add to rework
|
||||
response += f"&mdl_eqp_tm={self.time_lut}"
|
||||
|
||||
if profile_shop:
|
||||
response += f"&mdl_eqp_ary={profile_shop['mdl_eqp_ary']}"
|
||||
|
||||
response += f"&c_itm_eqp_ary=-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999"
|
||||
response += f"&ms_itm_flg_ary=1,1,1,1,1,1,1,1,1,1,1,1"
|
||||
|
||||
return ( response )
|
||||
|
||||
def handle_registration_request(self, data: Dict) -> Dict: #DONE
|
||||
self.data.profile.create_profile(self.version, data["aime_id"], data["player_name"])
|
||||
return ( f"&cd_adm_result=1&pd_id={data['aime_id']}")
|
||||
|
||||
def handle_start_request(self, data: Dict) -> Dict:
|
||||
profile = self.data.profile.get_profile(data["pd_id"], self.version)
|
||||
profile_shop = self.data.item.get_shop(data["pd_id"], self.version)
|
||||
if profile is None: return
|
||||
|
||||
response = ""
|
||||
response += f"&pd_id={data['pd_id']}"
|
||||
response += "&start_result=1"
|
||||
|
||||
response += "&accept_idx=100"
|
||||
response += f"&hp_vol={profile['hp_vol']}"
|
||||
response += f"&btn_se_vol={profile['btn_se_vol']}"
|
||||
response += f"&btn_se_vol2={profile['btn_se_vol2']}"
|
||||
response += f"&sldr_se_vol2={profile['sldr_se_vol2']}"
|
||||
response += f"&sort_kind={profile['sort_kind']}"
|
||||
response += f"&player_name={profile['player_name']}"
|
||||
response += f"&lv_num={profile['lv_num']}"
|
||||
response += f"&lv_pnt={profile['lv_pnt']}"
|
||||
response += f"&lv_efct_id={profile['lv_efct_id']}"
|
||||
response += f"&lv_plt_id={profile['lv_plt_id']}"
|
||||
response += "&mdl_have=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
response += "&cstmz_itm_have=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
response += f"&use_pv_mdl_eqp={profile['use_pv_mdl_eqp']}"
|
||||
response += f"&use_pv_btn_se_eqp={profile['use_pv_btn_se_eqp']}"
|
||||
response += f"&use_pv_sld_se_eqp={profile['use_pv_sld_se_eqp']}"
|
||||
response += f"&use_pv_chn_sld_se_eqp={profile['use_pv_chn_sld_se_eqp']}"
|
||||
response += f"&use_pv_sldr_tch_se_eqp={profile['use_pv_sldr_tch_se_eqp']}"
|
||||
response += f"&vcld_pts={profile['lv_efct_id']}"
|
||||
response += f"&nxt_pv_id={profile['nxt_pv_id']}"
|
||||
response += f"&nxt_dffclty={profile['nxt_dffclty']}"
|
||||
response += f"&nxt_edtn={profile['nxt_edtn']}"
|
||||
response += f"&dsp_clr_brdr={profile['dsp_clr_brdr']}"
|
||||
response += f"&dsp_intrm_rnk={profile['dsp_intrm_rnk']}"
|
||||
response += f"&dsp_clr_sts={profile['dsp_clr_sts']}"
|
||||
response += f"&rgo_sts={profile['rgo_sts']}"
|
||||
|
||||
#To be fully fixed
|
||||
if "my_qst_id" not in profile:
|
||||
response += f"&my_qst_id=-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
|
||||
response += f"&my_qst_sts=0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
|
||||
else:
|
||||
response += f"&my_qst_id={profile['my_qst_id']}"
|
||||
response += f"&my_qst_sts={profile['my_qst_sts']}"
|
||||
|
||||
response += f"&my_qst_prgrs=0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
|
||||
response += f"&my_qst_et=2022-06-19%2010%3A28%3A52.0,2022-06-19%2010%3A28%3A52.0,2022-06-19%2010%3A28%3A52.0,2100-01-01%2008%3A59%3A59.0,2100-01-01%2008%3A59%3A59.0,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx,xxx"
|
||||
response += f"&clr_sts=0,0,0,0,0,0,0,0,56,52,35,6,6,3,1,0,0,0,0,0"
|
||||
|
||||
#Store stuff to add to rework
|
||||
response += f"&mdl_eqp_tm={self.time_lut}"
|
||||
|
||||
if profile_shop:
|
||||
response += f"&mdl_eqp_ary={profile_shop['mdl_eqp_ary']}"
|
||||
|
||||
response += f"&c_itm_eqp_ary=-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999"
|
||||
response += f"&ms_itm_flg_ary=1,1,1,1,1,1,1,1,1,1,1,1"
|
||||
|
||||
return ( response )
|
||||
|
||||
def handle_pd_unlock_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_spend_credit_request(self, data: Dict) -> Dict:
|
||||
profile = self.data.profile.get_profile(data["pd_id"], self.version)
|
||||
if profile is None: return
|
||||
|
||||
response = ""
|
||||
|
||||
response += "&cmpgn_rslt=-1,-1,x,-1,-1,x,x,-1,x,-1,-1,x,-1,-1,x,x,-1,x,-1,-1,x,-1,-1,x,x,-1,x,-1,-1,x,-1,-1,x,x,-1,x,-1,-1,x,-1,-1,x,x,-1,x,-1,-1,x,-1,-1,x,x,-1,x"
|
||||
response += "&cmpgn_rslt_num=0"
|
||||
response += f"&vcld_pts={profile['vcld_pts']}"
|
||||
response += f"&lv_str={profile['lv_str']}"
|
||||
response += f"&lv_efct_id={profile['lv_efct_id']}"
|
||||
response += f"&lv_plt_id={profile['lv_plt_id']}"
|
||||
|
||||
return ( response )
|
||||
|
||||
def handle_get_pv_pd_request(self, data: Dict) -> Dict:
|
||||
song_id = data["pd_pv_id_lst"].split(",")
|
||||
pv = ""
|
||||
|
||||
for song in song_id:
|
||||
if int(song) > 0:
|
||||
pd_db_song = self.data.score.get_best_score(data["pd_id"], int(song), data["difficulty"])
|
||||
if pd_db_song is not None:
|
||||
|
||||
pv += urllib.parse.quote(f"{song},0,{pd_db_song['clr_kind']},{pd_db_song['score']},{pd_db_song['atn_pnt']},{pd_db_song['sort_kind']},-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,1,1,1,1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1337,1,1,1,0,0,0")
|
||||
|
||||
else:
|
||||
#self.logger.debug(f"No score saved for ID: {song}!")
|
||||
pv += urllib.parse.quote(f"{song},0,-1,-1,-1,0,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,1,1,1,1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,0,0,0")
|
||||
|
||||
#pv_no, edition, rslt, max_score, max_atn_pnt, challenge_kind, module_eqp[-999,-999,-999], customize_eqp[-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999], customize_flag[1,1,1,1,1,1,1,1,1,1,1,1], skin, btn_se, sld_se, chsld_se, sldtch_se, rvl_pd_id, rvl_score, rvl_attn_pnt, countrywide_ranking, rgo_hispeed, rgo_hidden, rgo_sudden, rgo_hispeed_cleared, rgo_hidden_cleared, rgo_sudden_cleared, chain_challenge_num, chain_challenge_max, chain_challenge_open, version
|
||||
else:
|
||||
pv += urllib.parse.quote(f"{song}***")
|
||||
pv += ","
|
||||
|
||||
response = ""
|
||||
response += f"&pd_by_pv_id={pv[:-1]}"
|
||||
response += "&pdddt_flg=0"
|
||||
response += f"&pdddt_tm={self.time_lut}"
|
||||
|
||||
return ( response )
|
||||
|
||||
def handle_stage_start_request(self, data: Dict) -> Dict:
|
||||
return ( f'' )
|
||||
|
||||
def handle_stage_result_request(self, data: Dict) -> Dict:
|
||||
|
||||
profile = self.data.profile.get_profile(data["pd_id"], self.version)
|
||||
|
||||
pd_song_list = data["stg_ply_pv_id"].split(",")
|
||||
pd_song_difficulty = data["stg_difficulty"].split(",")
|
||||
pd_song_max_score = data["stg_score"].split(",")
|
||||
pd_song_max_atn_pnt = data["stg_atn_pnt"].split(",")
|
||||
pd_song_ranking = data["stg_clr_kind"].split(",")
|
||||
pd_song_sort_kind = data["sort_kind"]
|
||||
pd_song_cool_cnt = data["stg_cool_cnt"].split(",")
|
||||
pd_song_fine_cnt = data["stg_fine_cnt"].split(",")
|
||||
pd_song_safe_cnt = data["stg_safe_cnt"].split(",")
|
||||
pd_song_sad_cnt = data["stg_sad_cnt"].split(",")
|
||||
pd_song_worst_cnt = data["stg_wt_wg_cnt"].split(",")
|
||||
pd_song_max_combo = data["stg_max_cmb"].split(",")
|
||||
|
||||
for index, value in enumerate(pd_song_list):
|
||||
if "-1" not in pd_song_list[index]:
|
||||
profile_pd_db_song = self.data.score.get_best_score(data["pd_id"], pd_song_list[index], pd_song_difficulty[index])
|
||||
if profile_pd_db_song is None:
|
||||
self.data.score.put_best_score(data["pd_id"], self.version, pd_song_list[index], pd_song_difficulty[index], pd_song_max_score[index], pd_song_max_atn_pnt[index], pd_song_ranking[index], pd_song_sort_kind, pd_song_cool_cnt[index], pd_song_fine_cnt[index], pd_song_safe_cnt[index], pd_song_sad_cnt[index], pd_song_worst_cnt[index], pd_song_max_combo[index])
|
||||
self.data.score.put_playlog(data["pd_id"], self.version, pd_song_list[index], pd_song_difficulty[index], pd_song_max_score[index], pd_song_max_atn_pnt[index], pd_song_ranking[index], pd_song_sort_kind, pd_song_cool_cnt[index], pd_song_fine_cnt[index], pd_song_safe_cnt[index], pd_song_sad_cnt[index], pd_song_worst_cnt[index], pd_song_max_combo[index])
|
||||
elif int(pd_song_max_score[index]) >= int(profile_pd_db_song["score"]):
|
||||
self.data.score.put_best_score(data["pd_id"], self.version, pd_song_list[index], pd_song_difficulty[index], pd_song_max_score[index], pd_song_max_atn_pnt[index], pd_song_ranking[index], pd_song_sort_kind, pd_song_cool_cnt[index], pd_song_fine_cnt[index], pd_song_safe_cnt[index], pd_song_sad_cnt[index], pd_song_worst_cnt[index], pd_song_max_combo[index])
|
||||
self.data.score.put_playlog(data["pd_id"], self.version, pd_song_list[index], pd_song_difficulty[index], pd_song_max_score[index], pd_song_max_atn_pnt[index], pd_song_ranking[index], pd_song_sort_kind, pd_song_cool_cnt[index], pd_song_fine_cnt[index], pd_song_safe_cnt[index], pd_song_sad_cnt[index], pd_song_worst_cnt[index], pd_song_max_combo[index])
|
||||
elif int(pd_song_max_score[index]) != int(profile_pd_db_song["score"]):
|
||||
self.data.score.put_playlog(data["pd_id"], self.version, pd_song_list[index], pd_song_difficulty[index], pd_song_max_score[index], pd_song_max_atn_pnt[index], pd_song_ranking[index], pd_song_sort_kind, pd_song_cool_cnt[index], pd_song_fine_cnt[index], pd_song_safe_cnt[index], pd_song_sad_cnt[index], pd_song_worst_cnt[index], pd_song_max_combo[index])
|
||||
|
||||
# Profile saving based on registration list
|
||||
|
||||
old_level = int(profile['lv_num'])
|
||||
new_level = (int(data["ttl_vp_add"]) + int(profile["lv_pnt"])) / 12
|
||||
|
||||
self.data.profile.update_profile(data["pd_id"], int(new_level), int(profile["lv_pnt"]) + int(data["ttl_vp_add"]), int(data["vcld_pts"]), int(data["hp_vol"]), int(data["btn_se_vol"]), int(data["btn_se_vol2"]), int(data["sldr_se_vol2"]), int(data["sort_kind"]), int(data["use_pv_mdl_eqp"]), profile["use_pv_btn_se_eqp"], profile["use_pv_sld_se_eqp"], profile["use_pv_chn_sld_se_eqp"], profile["use_pv_sldr_tch_se_eqp"], int(data["ply_pv_id"]), int(data["nxt_dffclty"]), int(data["nxt_edtn"]), profile["dsp_clr_brdr"], profile["dsp_intrm_rnk"], profile["dsp_clr_sts"], profile["rgo_sts"], profile["lv_efct_id"], profile["lv_plt_id"], data["my_qst_id"], data["my_qst_sts"])
|
||||
|
||||
response = ""
|
||||
|
||||
response += "&chllng_kind=-1"
|
||||
response += f"&lv_num_old={int(old_level)}"
|
||||
response += f"&lv_pnt_old={int(profile['lv_pnt'])}"
|
||||
response += f"&lv_num={int(profile['lv_num'])}"
|
||||
response += f"&lv_str={profile['lv_str']}"
|
||||
response += f"&lv_pnt={int(profile['lv_pnt']) + int(data['ttl_vp_add'])}"
|
||||
response += f"&lv_efct_id={int(profile['lv_efct_id'])}"
|
||||
response += f"&lv_plt_id={int(profile['lv_plt_id'])}"
|
||||
response += f"&vcld_pts={int(data['vcld_pts'])}"
|
||||
response += f"&prsnt_vcld_pts={int(profile['vcld_pts'])}"
|
||||
response += "&cerwd_kind=-1"
|
||||
response += "&cerwd_value=-1"
|
||||
response += "&cerwd_str_0=***"
|
||||
response += "&cerwd_str_1=***"
|
||||
response += "&ttl_str_ary=xxx,xxx,xxx,xxx,xxx"
|
||||
response += "&ttl_plt_id_ary=-1,-1,-1,-1,-1"
|
||||
response += "&ttl_desc_ary=xxx,xxx,xxx,xxx,xxx"
|
||||
response += "&skin_id_ary=xxx,xxx,xxx,xxx,xxx"
|
||||
response += "&skin_name_ary=xxx,xxx,xxx,xxx,xxx"
|
||||
response += "&skin_illust_ary=xxx,xxx,xxx,xxx,xxx"
|
||||
response += "&skin_desc_ary=xxx,xxx,xxx,xxx,xxx"
|
||||
if "my_qst_id" not in profile:
|
||||
response += f"&my_qst_id=-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
|
||||
else:
|
||||
response += f"&my_qst_id={profile['my_qst_id']}"
|
||||
response += "&my_qst_r_qid=-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
|
||||
response += "&my_qst_r_knd=-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
|
||||
response += "&my_qst_r_vl=-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
|
||||
response += "&my_qst_r_nflg=-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
|
||||
response += "&my_ccd_r_qid=-1,-1,-1,-1,-1"
|
||||
response += "&my_ccd_r_hnd=-1,-1,-1,-1,-1"
|
||||
response += "&my_ccd_r_vp=-1,-1,-1,-1,-1"
|
||||
|
||||
return ( response )
|
||||
|
||||
def handle_end_request(self, data: Dict) -> Dict:
|
||||
profile = self.data.profile.get_profile(data["pd_id"], self.version)
|
||||
self.data.profile.update_profile(data["pd_id"], profile["lv_num"], profile["lv_pnt"], profile["vcld_pts"], profile["hp_vol"], profile["btn_se_vol"], profile["btn_se_vol2"], profile["sldr_se_vol2"], profile["sort_kind"], profile["use_pv_mdl_eqp"], profile["use_pv_btn_se_eqp"], profile["use_pv_sld_se_eqp"], profile["use_pv_chn_sld_se_eqp"], profile["use_pv_sldr_tch_se_eqp"], profile["nxt_pv_id"], profile["nxt_dffclty"], profile["nxt_edtn"], profile["dsp_clr_brdr"], profile["dsp_intrm_rnk"], profile["dsp_clr_sts"], profile["rgo_sts"], profile["lv_efct_id"], profile["lv_plt_id"], data["my_qst_id"], data["my_qst_sts"])
|
||||
return ( f'' )
|
||||
|
||||
def handle_shop_exit_request(self, data: Dict) -> Dict:
|
||||
self.data.item.put_shop(data["pd_id"], self.version, data["mdl_eqp_cmn_ary"])
|
||||
|
||||
response = ""
|
||||
response += "&shp_rslt=1"
|
||||
return ( response )
|
17
titles/diva/config.py
Normal file
17
titles/diva/config.py
Normal file
@ -0,0 +1,17 @@
|
||||
from core.config import CoreConfig
|
||||
|
||||
class DivaServerConfig():
|
||||
def __init__(self, parent_config: "DivaConfig") -> None:
|
||||
self.__config = parent_config
|
||||
|
||||
@property
|
||||
def enable(self) -> bool:
|
||||
return CoreConfig.get_config_field(self.__config, 'diva', 'server', 'enable', default=True)
|
||||
|
||||
@property
|
||||
def loglevel(self) -> int:
|
||||
return CoreConfig.str_to_loglevel(CoreConfig.get_config_field(self.__config, 'diva', 'server', 'loglevel', default="info"))
|
||||
|
||||
class DivaConfig(dict):
|
||||
def __init__(self) -> None:
|
||||
self.server = DivaServerConfig(self)
|
11
titles/diva/const.py
Normal file
11
titles/diva/const.py
Normal file
@ -0,0 +1,11 @@
|
||||
class DivaConstants():
|
||||
GAME_CODE = "SBZV"
|
||||
|
||||
VER_PROJECT_DIVA_ARCADE = 0
|
||||
VER_PROJECT_DIVA_ARCADE_FUTURE_TONE = 1
|
||||
|
||||
VERSION_NAMES = ("Project Diva Arcade", "Project Diva Arcade Future Tone")
|
||||
|
||||
@classmethod
|
||||
def game_ver_to_string(cls, ver: int):
|
||||
return cls.VERSION_NAMES[ver]
|
204
titles/diva/data/ItemCatalog.dat
Normal file
204
titles/diva/data/ItemCatalog.dat
Normal file
@ -0,0 +1,204 @@
|
||||
0,0,縁なしメガネ(銀),50,2013-09-13,2029-01-01,0
|
||||
1,0,縁なしメガネ(赤),50,2013-09-13,2029-01-01,1
|
||||
2,0,ナイロールメガネ(銀),100,2013-09-13,2029-01-01,2
|
||||
3,0,ナイロールメガネ(茶),100,2014-03-18,2029-01-01,3
|
||||
4,0,フルフレームメガネ(橙),100,2014-03-18,2029-01-01,4
|
||||
5,0,フルフレームメガネ(黒),100,2013-09-13,2029-01-01,5
|
||||
6,0,アンダーリムメガネ(青),50,2014-02-12,2029-01-01,8
|
||||
7,0,アンダーリムメガネ(ピンク),50,2014-05-15,2029-01-01,9
|
||||
8,0,ぐるぐるメガネ,150,2014-09-26,2029-01-01,15
|
||||
9,0,三角メガネ(黒),100,2013-12-25,2029-01-01,10
|
||||
10,0,三角メガネ(赤),100,2014-03-18,2029-01-01,11
|
||||
11,0,サングラス,150,2015-01-09,2029-01-01,16
|
||||
12,0,ゴーグル,150,2014-12-02,2029-01-01,17
|
||||
13,0,電脳バイザー,150,2015-01-09,2029-01-01,18
|
||||
14,0,片眼鏡,150,2015-04-01,2029-01-01,14
|
||||
15,0,アイマスク,150,2014-10-23,2029-01-01,19
|
||||
16,0,キラ目マスク,200,2015-05-20,2029-01-01,20
|
||||
17,0,眼帯(黒),150,2013-09-13,2029-01-01,23
|
||||
18,0,眼帯(緑),150,2013-12-25,2029-01-01,24
|
||||
19,0,眼帯(黄),150,2014-02-12,2029-01-01,25
|
||||
20,0,眼帯(オレンジ),150,2014-05-15,2029-01-01,26
|
||||
21,0,眼帯(ピンク),150,2014-05-15,2029-01-01,27
|
||||
22,0,眼帯(青),150,2013-09-13,2029-01-01,28
|
||||
23,0,眼帯(赤),150,2013-09-13,2029-01-01,29
|
||||
24,0,眼帯(白),150,2015-07-22,2029-01-01,22
|
||||
25,0,京劇仮面(青),200,2016-01-08,2029-01-01,33
|
||||
26,0,京劇仮面(赤),200,2016-01-08,2029-01-01,34
|
||||
27,0,バタフライマスク,200,2015-07-22,2029-01-01,30
|
||||
28,0,マスカレードマスク,200,2014-07-24,2029-01-01,31
|
||||
30,0,ガスマスク,200,2015-07-22,2029-01-01,39
|
||||
31,0,能面(般若),200,2015-07-22,2029-01-01,40
|
||||
32,0,能面(女),200,2015-05-20,2029-01-01,41
|
||||
33,0,能面(翁),200,2015-05-20,2029-01-01,42
|
||||
34,0,白マスク,150,2014-07-24,2029-01-01,35
|
||||
35,0,白マスク(ペロ舌),200,2014-09-26,2029-01-01,36
|
||||
36,0,白マスク(ω),200,2014-12-02,2029-01-01,37
|
||||
37,0,白マスク(ε),200,2015-05-20,2029-01-01,38
|
||||
38,0,ネコひげ,50,2015-04-01,2029-01-01,43
|
||||
39,0,天使の輪,200,2015-07-22,2029-01-01,10
|
||||
40,0,ひよこ,200,2014-07-24,2029-01-01,11
|
||||
41,0,ナースキャップ,100,2013-09-13,2029-01-01,0
|
||||
42,0,メイドカチューシャ,100,2013-12-25,2029-01-01,1
|
||||
43,0,ネコミミ(黒),200,2013-09-13,2029-01-01,2
|
||||
44,0,ネコミミ(白),200,2013-12-25,2029-01-01,3
|
||||
45,0,ネコミミ(トラ),200,2014-03-18,2029-01-01,4
|
||||
46,0,ウサミミ(黒),200,2014-02-12,2029-01-01,5
|
||||
47,0,ウサミミ(白),200,2013-09-13,2029-01-01,6
|
||||
48,0,ウサミミ(ピンク),200,2014-09-26,2029-01-01,7
|
||||
49,0,一本角,150,2014-03-18,2029-01-01,8
|
||||
50,0,悪魔の角,200,2015-05-20,2029-01-01,9
|
||||
51,0,クセ毛 A(緑),150,2014-05-15,2029-01-01,12
|
||||
52,0,クセ毛 B(黄),150,2014-07-24,2029-01-01,22
|
||||
53,0,クセ毛 C(黄),150,2014-09-26,2029-01-01,31
|
||||
54,0,クセ毛 D(ピンク),150,2014-10-23,2029-01-01,41
|
||||
55,0,クセ毛 E(青),150,2014-12-02,2029-01-01,51
|
||||
56,0,クセ毛 F(こげ茶),150,2015-01-09,2029-01-01,61
|
||||
57,0,蝶ネクタイ(金),100,2013-12-25,2029-01-01,0
|
||||
58,0,蝶ネクタイ(黒),100,2013-09-13,2029-01-01,1
|
||||
59,0,蝶ネクタイ(赤),100,2013-09-13,2029-01-01,2
|
||||
60,0,リボン(青),150,2014-02-12,2029-01-01,3
|
||||
61,0,リボン(黄),150,2013-09-13,2029-01-01,4
|
||||
62,0,リボン(ピンク),150,2013-09-13,2029-01-01,5
|
||||
67,0,鈴(金),150,2014-10-23,2029-01-01,6
|
||||
68,0,鈴(銀),150,2014-10-23,2029-01-01,7
|
||||
69,0,光の翼,200,2014-12-02,2029-01-01,1
|
||||
70,0,天使の翼,200,2015-07-22,2029-01-01,0
|
||||
71,0,蝶の羽根,200,2015-04-01,2029-01-01,3
|
||||
72,0,悪魔の翼,200,2015-05-20,2029-01-01,2
|
||||
73,0,ぬいぐるみ,200,2013-09-13,2029-01-01,8
|
||||
74,0,リュックサック,150,2013-09-13,2029-01-01,4
|
||||
75,0,ナップサック,100,2013-12-25,2029-01-01,5
|
||||
76,0,ランドセル(黒),150,2014-02-12,2029-01-01,6
|
||||
77,0,ランドセル(赤),150,2014-02-12,2029-01-01,7
|
||||
78,0,ロケット,150,2014-07-24,2029-01-01,9
|
||||
79,0,ネコしっぽ(黒),200,2013-09-13,2029-01-01,11
|
||||
80,0,ネコしっぽ(白),200,2013-12-25,2029-01-01,12
|
||||
81,0,ネコしっぽ(トラ),200,2014-03-18,2029-01-01,13
|
||||
82,0,ウサしっぽ(黒),200,2014-02-12,2029-01-01,14
|
||||
83,0,ウサしっぽ(白),200,2013-09-13,2029-01-01,15
|
||||
84,0,ウサしっぽ(ピンク),200,2014-09-26,2029-01-01,16
|
||||
85,0,狐しっぽ,350,2014-05-15,2029-01-01,17
|
||||
86,0,悪魔の尾,200,2015-01-09,2029-01-01,18
|
||||
87,0,赤ぷよぼう,400,2016-09-21,2029-01-01,66
|
||||
88,0,緑ぷよのかみどめ,400,2016-09-21,2029-01-01,67
|
||||
89,0,ゼンマイ,150,2015-07-22,2029-01-01,10
|
||||
97,0,ゴールドクラウン,350,2016-01-08,2029-01-01,70
|
||||
98,0,プラチナクラウン,350,2016-01-08,2029-01-01,71
|
||||
99,0,シャープメガネ(藍),100,2014-09-26,2029-01-01,6
|
||||
100,0,シャープメガネ(紫),100,2013-12-25,2029-01-01,7
|
||||
101,0,丸メガネ(銀),150,2013-12-25,2029-01-01,12
|
||||
102,0,丸メガネ(べっ甲),150,2014-03-18,2029-01-01,13
|
||||
103,0,たこルカ,400,2016-05-18,2029-01-01,68
|
||||
104,0,シテヤンヨ,400,2016-03-17,2029-01-01,69
|
||||
105,0,はちゅねミク,400,2014-12-02,2029-01-01,19
|
||||
106,0,リンの幼虫,400,2016-01-08,2029-01-01,20
|
||||
107,0,劇画マスク,200,2016-01-08,2029-01-01,21
|
||||
115,0,シャープサングラス,150,2014-07-24,2029-01-01,45
|
||||
116,0,水中メガネ,200,2014-12-02,2029-01-01,44
|
||||
117,0,パーティー眼鏡,100,2015-04-01,2029-01-01,48
|
||||
118,0,ピエロ鼻,50,2015-05-20,2029-01-01,46
|
||||
119,0,キツネ面,200,2016-03-17,2029-01-01,47
|
||||
120,0,ミニシルクハット,350,2014-05-15,2029-01-01,74
|
||||
121,0,コック帽,50,2013-09-13,2029-01-01,73
|
||||
122,0,烏帽子,50,2015-04-01,2029-01-01,72
|
||||
123,0,ミクダヨー,1500,2015-04-01,2029-01-01,76
|
||||
124,0,記章,100,2014-10-23,2029-01-01,8
|
||||
131,0,ポスター付リュックサック,150,2014-03-18,2029-01-01,21
|
||||
132,0,リコーダー付ランドセル(黒),150,2015-01-09,2029-01-01,22
|
||||
133,0,リコーダー付ランドセル(赤),150,2015-01-09,2029-01-01,23
|
||||
134,0,ミクダヨー(ミニ),500,2014-10-23,2029-01-01,75
|
||||
135,0,クセ毛 A(黄),150,2014-05-15,2029-01-01,13
|
||||
136,0,クセ毛 A(ピンク),150,2014-05-15,2029-01-01,14
|
||||
137,0,クセ毛 A(青),150,2014-05-15,2029-01-01,15
|
||||
138,0,クセ毛 A(こげ茶),150,2014-05-15,2029-01-01,16
|
||||
139,0,クセ毛 A(金),150,2014-05-15,2029-01-01,17
|
||||
140,0,クセ毛 A(銀),150,2014-05-15,2029-01-01,18
|
||||
141,0,クセ毛 A(茶),150,2014-05-15,2029-01-01,19
|
||||
142,0,クセ毛 A(赤),150,2014-05-15,2029-01-01,20
|
||||
143,0,クセ毛 B(緑),150,2014-07-24,2029-01-01,21
|
||||
144,0,クセ毛 B(ピンク),150,2014-07-24,2029-01-01,23
|
||||
145,0,クセ毛 B(青),150,2014-07-24,2029-01-01,24
|
||||
146,0,クセ毛 B(こげ茶),150,2014-07-24,2029-01-01,25
|
||||
147,0,クセ毛 B(金),150,2014-07-24,2029-01-01,26
|
||||
148,0,クセ毛 B(銀),150,2014-07-24,2029-01-01,27
|
||||
149,0,クセ毛 B(茶),150,2014-07-24,2029-01-01,28
|
||||
150,0,クセ毛 B(赤),150,2014-07-24,2029-01-01,29
|
||||
151,0,クセ毛 C(緑),150,2014-09-26,2029-01-01,30
|
||||
152,0,クセ毛 C(ピンク),150,2014-09-26,2029-01-01,32
|
||||
153,0,クセ毛 C(青),150,2014-09-26,2029-01-01,33
|
||||
154,0,クセ毛 C(こげ茶),150,2014-09-26,2029-01-01,34
|
||||
155,0,クセ毛 C(金),150,2014-09-26,2029-01-01,35
|
||||
156,0,クセ毛 C(銀),150,2014-09-26,2029-01-01,36
|
||||
157,0,クセ毛 C(茶),150,2014-09-26,2029-01-01,37
|
||||
158,0,クセ毛 C(赤),150,2014-09-26,2029-01-01,38
|
||||
159,0,クセ毛 D(緑),150,2014-10-23,2029-01-01,39
|
||||
160,0,クセ毛 D(黄),150,2014-10-23,2029-01-01,40
|
||||
161,0,クセ毛 D(青),150,2014-10-23,2029-01-01,42
|
||||
162,0,クセ毛 D(こげ茶),150,2014-10-23,2029-01-01,43
|
||||
163,0,クセ毛 D(金),150,2014-10-23,2029-01-01,44
|
||||
164,0,クセ毛 D(銀),150,2014-10-23,2029-01-01,45
|
||||
165,0,クセ毛 D(茶),150,2014-10-23,2029-01-01,46
|
||||
166,0,クセ毛 D(赤),150,2014-10-23,2029-01-01,47
|
||||
167,0,クセ毛 E(緑),150,2014-12-02,2029-01-01,48
|
||||
168,0,クセ毛 E(黄),150,2014-12-02,2029-01-01,49
|
||||
169,0,クセ毛 E(ピンク),150,2014-12-02,2029-01-01,50
|
||||
170,0,クセ毛 E(こげ茶),150,2014-12-02,2029-01-01,52
|
||||
171,0,クセ毛 E(金),150,2014-12-02,2029-01-01,53
|
||||
172,0,クセ毛 E(銀),150,2014-12-02,2029-01-01,54
|
||||
173,0,クセ毛 E(茶),150,2014-12-02,2029-01-01,55
|
||||
174,0,クセ毛 E(赤),150,2014-12-02,2029-01-01,56
|
||||
175,0,クセ毛 F(緑),150,2015-01-09,2029-01-01,57
|
||||
176,0,クセ毛 F(黄),150,2015-01-09,2029-01-01,58
|
||||
177,0,クセ毛 F(ピンク),150,2015-01-09,2029-01-01,59
|
||||
178,0,クセ毛 F(青),150,2015-01-09,2029-01-01,60
|
||||
179,0,クセ毛 F(金),150,2015-01-09,2029-01-01,62
|
||||
180,0,クセ毛 F(銀),150,2015-01-09,2029-01-01,63
|
||||
181,0,クセ毛 F(茶),150,2015-01-09,2029-01-01,64
|
||||
182,0,クセ毛 F(赤),150,2015-01-09,2029-01-01,65
|
||||
183,0,イヌミミ,200,2015-10-15,2029-01-01,77
|
||||
184,0,羊角,200,2016-09-21,2029-01-01,78
|
||||
185,0,悪魔の頭羽,200,2016-09-21,2029-01-01,79
|
||||
186,0,とりの巣,200,2016-03-17,2029-01-01,80
|
||||
187,0,おばけの三角ずきん,200,2016-07-20,2029-01-01,81
|
||||
188,0,パラボラアンテナ,200,2016-11-24,2029-01-01,82
|
||||
189,0,パーティ帽(赤),100,2016-12-15,2029-01-01,83
|
||||
190,0,パーティ帽(青),100,2016-12-15,2029-01-01,84
|
||||
191,0,パーティ帽(黄),100,2016-12-15,2029-01-01,85
|
||||
192,0,ホホジロザメ,300,2016-07-20,2029-01-01,86
|
||||
193,0,パンプキンヘッド,300,2015-10-15,2029-01-01,87
|
||||
194,0,雪だるまヘッド(ノーマル),300,2016-12-15,2029-01-01,88
|
||||
195,0,雪だるまヘッド(笑顔),300,2016-12-15,2029-01-01,89
|
||||
196,0,ハート(頭),200,2017-01-18,2029-01-01,90
|
||||
197,0,ぷんぷん,200,2016-11-24,2029-01-01,91
|
||||
198,0,汗(右),100,2015-10-15,2029-01-01,92
|
||||
199,0,汗(左),100,2015-10-15,2029-01-01,93
|
||||
200,0,!?,200,2016-11-24,2029-01-01,94
|
||||
201,0,でかメガネ,150,2016-07-20,2029-01-01,49
|
||||
204,0,つけひげ,150,2016-12-15,2029-01-01,52
|
||||
205,0,くちばし,100,2016-03-17,2029-01-01,53
|
||||
208,0,目隠し線,200,2016-05-18,2029-01-01,56
|
||||
210,0,つけえり,150,2015-04-01,2029-01-01,15
|
||||
211,0,ハーモニカ,150,2016-03-17,2029-01-01,16
|
||||
212,0,金メダル,200,2016-05-18,2029-01-01,17
|
||||
213,0,銀メダル,150,2016-05-18,2029-01-01,18
|
||||
214,0,銅メダル,100,2016-05-18,2029-01-01,19
|
||||
215,0,前かけ(緑),100,2016-11-24,2029-01-01,20
|
||||
216,0,前かけ(黄),100,2016-11-24,2029-01-01,21
|
||||
217,0,前かけ(橙),100,2016-11-24,2029-01-01,22
|
||||
218,0,前かけ(ピンク),100,2016-11-24,2029-01-01,23
|
||||
219,0,前かけ(青),100,2016-11-24,2029-01-01,24
|
||||
220,0,前かけ(赤),100,2016-11-24,2029-01-01,25
|
||||
221,0,初心者マーク,150,2016-07-20,2029-01-01,26
|
||||
222,0,タイマー(緑),50,2015-10-15,2029-01-01,27
|
||||
223,0,タイマー(赤),50,2015-10-15,2029-01-01,28
|
||||
224,0,ハート(胸),200,2017-01-18,2029-01-01,29
|
||||
225,0,失恋ハート,200,2017-01-18,2029-01-01,30
|
||||
226,0,機械の翼,200,2016-03-17,2029-01-01,24
|
||||
227,0,スクールバッグ,150,2017-01-18,2029-01-01,25
|
||||
228,0,押しボタン,200,2016-05-18,2029-01-01,26
|
||||
229,0,イヌしっぽ,200,2015-10-15,2029-01-01,27
|
||||
230,0,恐竜しっぽ,200,2016-07-20,2029-01-01,28
|
||||
231,0,猫又しっぽ,300,2016-09-21,2029-01-01,29
|
||||
232,0,九尾しっぽ,300,2016-12-15,2029-01-01,30
|
||||
233,0,ぶらさがりネコ,300,2017-01-18,2029-01-01,31
|
1
titles/diva/data/PvList0.dat
Normal file
1
titles/diva/data/PvList0.dat
Normal file
File diff suppressed because one or more lines are too long
1
titles/diva/data/PvList1.dat
Normal file
1
titles/diva/data/PvList1.dat
Normal file
File diff suppressed because one or more lines are too long
1
titles/diva/data/PvList2.dat
Normal file
1
titles/diva/data/PvList2.dat
Normal file
File diff suppressed because one or more lines are too long
1
titles/diva/data/PvList3.dat
Normal file
1
titles/diva/data/PvList3.dat
Normal file
File diff suppressed because one or more lines are too long
1
titles/diva/data/PvList4.dat
Normal file
1
titles/diva/data/PvList4.dat
Normal file
@ -0,0 +1 @@
|
||||
%2A%2A%2A
|
60
titles/diva/data/QuestInfo.dat
Normal file
60
titles/diva/data/QuestInfo.dat
Normal file
@ -0,0 +1,60 @@
|
||||
1001,1,0,0,2022-06-18 09:00:00.0,2022-06-20 09:00:00.0,Play in the Simple Mode or Contest Mode,1,1,1
|
||||
1010,10,0,0,2022-06-18 09:00:00.0,2022-06-20 09:00:00.0,Play with a randomly selected Miku module,1,1,1
|
||||
1011,11,0,0,2022-06-18 09:00:00.0,2022-06-20 09:00:00.0,Hit COOL 500 times or more,1,3,1
|
||||
1012,12,0,0,2022-06-18 09:00:00.0,2022-06-20 09:00:00.0,Take a photo in the PV watching mode,1,1,1
|
||||
1013,13,0,0,2022-06-18 09:00:00.0,2022-06-20 09:00:00.0,Play with the SE turned OFF,1,1,1
|
||||
1002,2,0,0,2022-06-18 09:00:00.0,2022-06-20 09:00:00.0,Do some Max Chain Slides,1,1,1
|
||||
1003,3,0,0,2022-06-18 09:00:00.0,2022-06-20 09:00:00.0,Challenge yourself to beat a trial,1,1,1
|
||||
1004,4,0,0,2022-06-18 09:00:00.0,2022-06-20 09:00:00.0,Play a song on <EX_EXT>,1,2,1
|
||||
1005,5,0,0,2022-06-18 09:00:00.0,2022-06-20 09:00:00.0,Play a chart by Misora,1,2,1
|
||||
1006,6,0,0,2022-06-18 09:00:00.0,2022-06-20 09:00:00.0,Score at least 390390 pts in any song,1,1,1
|
||||
1007,7,0,0,2022-06-18 09:00:00.0,2022-06-20 09:00:00.0,Play a song chosen at random,1,1,1
|
||||
1008,8,0,0,2022-06-18 09:00:00.0,2022-06-20 09:00:00.0,Play with at least 100 percent result,1,1,1
|
||||
1009,9,0,0,2022-06-18 09:00:00.0,2022-06-20 09:00:00.0,Play with the <MDLID>169</MDLID> module,1,1,1
|
||||
3001,1,2,0,2001-01-01 09:00:00.0,2100-01-01 08:59:59.0,Clear a song with the HISPEED mode,1,2,1
|
||||
3002,2,2,0,2001-01-01 09:00:00.0,2100-01-01 08:59:59.0,Clear a song with the HIDDEN mode,1,2,1
|
||||
3003,3,2,0,2001-01-01 09:00:00.0,2100-01-01 08:59:59.0,Clear a song with the SUDDEN mode,1,2,1
|
||||
3004,4,2,0,2001-01-01 09:00:00.0,2100-01-01 08:59:59.0,Enhance your Chain-Perfect Trial streak,1,4,1
|
||||
3005,5,2,0,2001-01-01 09:00:00.0,2100-01-01 08:59:59.0,Beat your rival in a song by percentage,1,4,1
|
||||
2001,1,1,0,2022-06-18 09:00:00.0,2022-06-25 09:00:00.0,Hit COOL at least 1300 times,1,3,1
|
||||
2002,2,1,0,2022-06-18 09:00:00.0,2022-06-25 09:00:00.0,Hit COOL at least 2000 times,1,3,1
|
||||
2003,3,1,0,2022-06-18 09:00:00.0,2022-06-25 09:00:00.0,Achieve a sum of MAX COMBO of 730 or more,1,3,1
|
||||
2004,4,1,0,2022-06-18 09:00:00.0,2022-06-25 09:00:00.0,Achieve a sum of MAX COMBO of 960 or more,1,3,1
|
||||
2005,5,1,0,2022-06-18 09:00:00.0,2022-06-25 09:00:00.0,Score at least 440000 pts in any song,1,1,1
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
||||
***
|
401
titles/diva/data/ShopCatalog.dat
Normal file
401
titles/diva/data/ShopCatalog.dat
Normal file
@ -0,0 +1,401 @@
|
||||
0,0,初音ミク,0,2009-01-01,2029-01-01,1
|
||||
1,0,弱音ハク,50,2009-01-01,2029-01-01,1
|
||||
2,0,亞北ネル,50,2009-01-01,2029-01-01,4
|
||||
3,0,メイコスタイル,100,2009-01-01,2029-01-01,2
|
||||
4,0,リンスタイル,100,2009-01-01,2029-01-01,3
|
||||
5,0,スペチャン5,100,2009-01-01,2029-01-01,4
|
||||
6,0,スペチャン39,50,2009-01-01,2029-01-01,5
|
||||
7,0,ガリア軍第7小隊,100,2009-01-01,2029-01-01,6
|
||||
8,0,P-スタイルPB,50,2009-01-01,2029-01-01,31
|
||||
9,0,P-スタイルCW,50,2009-01-01,2029-01-01,32
|
||||
10,0,P-スタイルIS,50,2009-01-01,2029-01-01,33
|
||||
11,0,P-スタイルRP,50,2009-01-01,2029-01-01,34
|
||||
12,0,P-スタイルLP,50,2009-01-01,2029-01-01,35
|
||||
13,0,P-スタイルFB,50,2009-01-01,2029-01-01,36
|
||||
14,0,P-スタイルMG,50,2009-01-01,2029-01-01,37
|
||||
15,0,P-スタイルCG,300,2009-01-01,2029-01-01,38
|
||||
16,0,チア,50,2009-01-01,2029-01-01,7
|
||||
17,0,プラグイン,100,2009-01-01,2029-01-01,8
|
||||
18,0,ゴシック,100,2009-01-01,2029-01-01,9
|
||||
19,0,プリンセス,50,2009-01-01,2029-01-01,10
|
||||
20,0,ミコ,100,2009-01-01,2029-01-01,11
|
||||
21,0,にゃんこ,50,2009-01-01,2029-01-01,12
|
||||
22,0,ねむねむ,100,2009-01-01,2029-01-01,13
|
||||
23,0,ハートハンター,100,2009-01-01,2029-01-01,14
|
||||
24,0,ボーカル,50,2009-01-01,2029-01-01,15
|
||||
25,0,パンク,100,2009-01-01,2029-01-01,16
|
||||
26,0,ダンサー,50,2009-01-01,2029-01-01,17
|
||||
27,0,スター,100,2009-01-01,2029-01-01,18
|
||||
28,0,フェアリー,100,2009-01-01,2029-01-01,19
|
||||
29,0,スクール,100,2009-01-01,2029-01-01,20
|
||||
30,0,スノウ,50,2009-01-01,2029-01-01,21
|
||||
31,0,アラビアン,100,2009-01-01,2029-01-01,22
|
||||
32,0,みやび,50,2009-01-01,2029-01-01,23
|
||||
33,0,チャイナ,300,2009-01-01,2029-01-01,24
|
||||
34,0,マジシャン,50,2009-01-01,2029-01-01,25
|
||||
35,0,ホワイトドレス,100,2009-01-01,2029-01-01,26
|
||||
36,0,パイレーツ,50,2009-01-01,2029-01-01,27
|
||||
37,0,VN02,100,2009-01-01,2029-01-01,28
|
||||
38,0,ギャラクシー,100,2009-01-01,2029-01-01,29
|
||||
39,0,ハツネミク,100,2009-01-01,2029-01-01,30
|
||||
40,0,鏡音リン,50,2009-01-01,2029-01-01,1
|
||||
41,0,鏡音レン,50,2009-01-01,2029-01-01,1
|
||||
42,0,巡音ルカ,50,2009-01-01,2029-01-01,1
|
||||
43,0,咲音メイコ,300,2009-01-01,2029-01-01,7
|
||||
44,0,メイコ,50,2009-01-01,2029-01-01,1
|
||||
45,0,カイト,50,2009-01-01,2029-01-01,1
|
||||
46,0,初音ミク スイムウェアS,1000,2009-01-01,2029-01-01,140
|
||||
47,0,初音ミク スイムウェア,1000,2009-01-01,2029-01-01,141
|
||||
48,0,鏡音リン スイムウェア,1000,2009-01-01,2029-01-01,39
|
||||
49,0,鏡音レン スイムウェア,300,2009-01-01,2029-01-01,33
|
||||
50,0,巡音ルカ スイムウェア,1000,2009-01-01,2029-01-01,31
|
||||
51,0,メイコ スイムウェア,1000,2009-01-01,2029-01-01,24
|
||||
52,0,カイト スイムウェア,300,2009-01-01,2029-01-01,31
|
||||
53,0,初音ミク アペンド,300,2010-08-31,2029-01-01,152
|
||||
54,0,ホワイトワンピース,100,2010-11-16,2029-01-01,49
|
||||
55,0,ナチュラル,200,2010-11-16,2029-01-01,48
|
||||
56,0,スピリチュアル,200,2010-11-16,2029-01-01,41
|
||||
57,0,カラフルドロップ,200,2010-12-27,2029-01-01,57
|
||||
58,0,初音ミク 蝶,100,2010-11-16,2029-01-01,40
|
||||
59,0,チアフルキャンディ,200,2010-12-27,2029-01-01,6
|
||||
60,0,スクールジャージ,100,2010-12-27,2029-01-01,3
|
||||
61,0,巡音ルカ 華,100,2010-11-16,2029-01-01,2
|
||||
62,0,初音ミク クリスマス,150,2010-11-30,2029-01-01,153
|
||||
63,0,鏡音リン クリスマス,150,2010-11-30,2029-01-01,50
|
||||
64,0,鏡音レン クリスマス,150,2010-11-30,2029-01-01,41
|
||||
65,0,巡音ルカ クリスマス,150,2010-11-30,2029-01-01,40
|
||||
66,0,メイコ クリスマス,150,2010-11-30,2029-01-01,32
|
||||
67,0,カイト クリスマス,150,2010-11-30,2029-01-01,41
|
||||
68,0,雪ミク 2010,300,2011-01-31,2029-01-01,154
|
||||
69,0,ヴィンテージドレス,200,2011-02-17,2029-01-01,39
|
||||
70,0,ピンクポップス,100,2011-01-31,2029-01-01,55
|
||||
71,0,ピンクポップス AS,100,2011-01-31,2029-01-01,56
|
||||
72,0,リアクター,200,2011-02-24,2029-01-01,3
|
||||
73,0,パンキッシュ,200,2011-02-24,2029-01-01,2
|
||||
74,0,ハードロック,200,2011-01-31,2029-01-01,5
|
||||
75,0,クラシック,200,2011-02-17,2029-01-01,2
|
||||
76,0,スカーレット,200,2011-02-17,2029-01-01,3
|
||||
77,0,雪ミク 2011,300,2011-01-31,2029-01-01,155
|
||||
78,0,おさんぽスタイル,150,2011-07-26,2029-01-01,42
|
||||
79,0,みくずきん,150,2011-05-20,2029-01-01,43
|
||||
80,0,イエロー,150,2011-11-01,2029-01-01,44
|
||||
81,0,ジャー★ジ,150,2011-09-08,2029-01-01,45
|
||||
82,0,ノーブル,150,2011-05-20,2029-01-01,46
|
||||
83,0,パウダー,150,2011-09-08,2029-01-01,47
|
||||
84,0,エールダンジュ,150,2011-11-01,2029-01-01,50
|
||||
85,0,スペイシーナース,200,2012-03-13,2029-01-01,51
|
||||
86,0,初音ミク キュート,200,2011-07-26,2029-01-01,52
|
||||
87,0,エンジェル,200,2012-01-10,2029-01-01,53
|
||||
88,0,サイハテミク,150,2011-07-26,2029-01-01,54
|
||||
89,0,∞,200,2012-02-14,2029-01-01,58
|
||||
90,0,初音ミク スイムウェアB,1000,2011-07-26,2029-01-01,143
|
||||
91,0,アシンメトリーR,200,2011-09-08,2029-01-01,2
|
||||
92,0,EoEスタイル,200,2011-11-01,2029-01-01,4
|
||||
93,0,鏡音リン キュート,200,2011-07-26,2029-01-01,5
|
||||
94,0,鏡音リン スイムウェアT,1000,2011-07-26,2029-01-01,41
|
||||
95,0,アシンメトリーL,200,2011-09-08,2029-01-01,4
|
||||
96,0,鏡音レン スイムウェアWS,750,2011-07-26,2029-01-01,35
|
||||
97,0,シフォンワンピース,150,2011-06-21,2029-01-01,3
|
||||
98,0,フロイライン,200,2011-09-08,2029-01-01,4
|
||||
99,0,VFスーツ,200,2012-01-10,2029-01-01,6
|
||||
100,0,巡音ルカ スイムウェアP,1000,2011-07-26,2029-01-01,32
|
||||
101,0,キャンパス,200,2012-02-14,2029-01-01,3
|
||||
102,0,ネコサイバー,300,2011-06-21,2029-01-01,4
|
||||
103,0,カイト スイムウェアV,750,2011-07-26,2029-01-01,32
|
||||
104,0,カイト スイムウェアV AS,750,2011-07-26,2029-01-01,34
|
||||
105,0,ふわふわコート,200,2011-11-01,2029-01-01,2
|
||||
106,0,モダンガール,150,2012-03-13,2029-01-01,4
|
||||
107,0,モダンガール AS,150,2012-03-13,2029-01-01,5
|
||||
108,0,メイコ スイムウェアB,1000,2011-07-26,2029-01-01,26
|
||||
109,0,エスニック,200,2011-05-20,2029-01-01,5
|
||||
110,0,亞北ネル スイムウェア,1000,2011-07-26,2029-01-01,12
|
||||
111,0,サイバーダイブ,200,2011-05-20,2029-01-01,2
|
||||
112,0,弱音ハク スイムウェア,1000,2011-07-26,2029-01-01,11
|
||||
113,0,ブラックワンピース,300,2011-05-20,2029-01-01,8
|
||||
114,0,ブラックワンピース NS,300,2011-05-20,2029-01-01,9
|
||||
115,0,咲音メイコ スイムウェア,1000,2011-07-26,2029-01-01,13
|
||||
116,0,メイコ 大正浪漫,250,2011-11-01,2029-01-01,30
|
||||
117,0,鏡音リン スクールウェア,250,2011-12-06,2029-01-01,45
|
||||
118,0,鏡音レン スクールウェア,250,2011-12-06,2029-01-01,40
|
||||
119,0,巡音ルカ 魔女っ娘Style,250,2012-01-31,2029-01-01,37
|
||||
120,0,カイト ホワイトブレザー,250,2012-02-14,2029-01-01,38
|
||||
121,0,フェアリーマカロン,300,2011-06-21,2029-01-01,41
|
||||
122,0,セクシープディング,300,2011-06-21,2029-01-01,33
|
||||
124,0,ホワイト・イヴ,250,2012-11-05,2029-01-01,61
|
||||
125,0,Hello World.,250,2012-10-04,2029-01-01,68
|
||||
126,0,レーシングミク2010ver.,200,2012-11-22,2029-01-01,62
|
||||
127,0,レーシングミク2011ver.,250,2012-12-06,2029-01-01,63
|
||||
128,0,フェイ・イェン スタイル,250,2012-11-22,2029-01-01,66
|
||||
129,0,回転少女,250,2012-11-05,2029-01-01,71
|
||||
130,0,ラセツトムクロ,250,2012-05-24,2029-01-01,69
|
||||
131,0,オービット,250,2012-11-05,2029-01-01,60
|
||||
132,0,パッチワーク,250,2012-04-26,2029-01-01,65
|
||||
133,0,ソニックスタイル,250,2012-08-31,2029-01-01,59
|
||||
134,0,チロル,250,2012-10-04,2029-01-01,64
|
||||
135,0,コンフリクト,200,2012-04-26,2029-01-01,70
|
||||
136,0,シャイニー,250,2012-07-05,2029-01-01,72
|
||||
137,0,TYPE2020,250,2012-08-31,2029-01-01,67
|
||||
138,0,部活少女,250,2012-07-31,2029-01-01,6
|
||||
139,0,ゴシック・パープル,250,2012-07-31,2029-01-01,3
|
||||
141,0,鏡音リン アペンド,300,2011-12-27,2029-01-01,51
|
||||
142,0,ネームレス No.1,200,2012-12-27,2029-01-01,8
|
||||
143,0,レーシングリン2010ver.,200,2012-11-22,2029-01-01,12
|
||||
144,0,ブラックスター,250,2012-09-14,2029-01-01,7
|
||||
145,0,陽炎,250,2012-04-26,2029-01-01,11
|
||||
146,0,鏡音リン 蘇芳,150,2012-04-05,2029-01-01,9
|
||||
147,0,鏡音レン アペンド,300,2011-12-27,2029-01-01,42
|
||||
148,0,ブルームーン,250,2012-09-14,2029-01-01,5
|
||||
149,0,鏡音レン 藍鉄,150,2012-04-05,2029-01-01,6
|
||||
150,0,ストレンジダーク,250,2012-07-05,2029-01-01,8
|
||||
151,0,ネームレス No.7,200,2012-12-27,2029-01-01,9
|
||||
153,0,サイレンス,250,2012-07-05,2029-01-01,7
|
||||
154,0,レーシングルカ2010ver.,200,2012-11-22,2029-01-01,10
|
||||
155,0,サイバーネイション,300,2011-12-15,2029-01-01,42
|
||||
156,0,ナギサ・レプカ,200,2012-10-04,2029-01-01,8
|
||||
157,0,ナギサ・レプカ AS,200,2012-10-04,2029-01-01,9
|
||||
158,0,時雨,250,2012-05-24,2029-01-01,6
|
||||
159,0,スミレ,250,2012-07-05,2029-01-01,5
|
||||
160,0,VFニンジャ,200,2013-02-15,2029-01-01,7
|
||||
161,0,VFニンジャ AS,200,2013-02-15,2029-01-01,8
|
||||
162,0,怪盗ブラックテール,250,2012-11-05,2029-01-01,6
|
||||
163,0,紅葉,250,2012-05-24,2029-01-01,8
|
||||
164,0,レーシングメイコ2010ver.,200,2012-11-22,2029-01-01,9
|
||||
165,0,ローレライ,250,2012-08-31,2029-01-01,7
|
||||
166,0,ノスタルジー,250,2012-07-31,2029-01-01,10
|
||||
167,0,雪ミク 2012,300,2011-12-19,2029-01-01,156
|
||||
168,0,AMERICANA,300,2012-07-31,2029-01-01,167
|
||||
169,0,桜ミク,300,2012-04-05,2029-01-01,168
|
||||
170,0,巡音ルカ コンフリクト,300,2012-04-26,2029-01-01,43
|
||||
171,0,鏡音リン 蘇芳 妖狐,200,2012-04-05,2029-01-01,10
|
||||
172,0,鏡音レン 藍鉄 妖狐,200,2012-04-05,2029-01-01,7
|
||||
188,0,ドリーマー,250,2013-01-30,2029-01-01,120
|
||||
189,0,初音ミク 妄想ガール,250,2012-12-06,2029-01-01,121
|
||||
190,0,雪ミク 2013,300,2012-12-17,2029-01-01,157
|
||||
191,0,鏡音リン 妄想ガール,250,2012-12-06,2029-01-01,29
|
||||
192,0,ロジカリスト,250,2012-12-06,2029-01-01,25
|
||||
193,0,オンザロック,250,2013-01-30,2029-01-01,22
|
||||
194,0,雪ミク 2013 AS,300,2012-12-17,2029-01-01,158
|
||||
195,0,ディープスカイ,250,2014-02-25,2029-01-01,73
|
||||
196,0,紫揚羽,250,2015-04-23,2029-01-01,74
|
||||
197,0,メモリア,250,2015-03-26,2029-01-01,75
|
||||
198,0,理系少女,250,2014-06-10,2029-01-01,76
|
||||
199,0,ピエレッタ,250,2013-09-25,2029-01-01,77
|
||||
200,0,イノセント,250,2014-04-17,2029-01-01,78
|
||||
201,0,堕悪天使,250,2014-04-17,2029-01-01,79
|
||||
202,0,サマーメモリー,250,2014-08-28,2029-01-01,80
|
||||
203,0,初音ミク 翠玉,250,2016-05-26,2029-01-01,81
|
||||
204,0,ソリチュード,250,2015-04-23,2029-01-01,82
|
||||
205,0,ホーリーゴッデス,250,2015-05-28,2029-01-01,83
|
||||
206,0,フォニュエールスタイル,250,2014-07-29,2029-01-01,84
|
||||
207,0,ねこねこケープ,250,2014-06-10,2029-01-01,85
|
||||
208,0,アジテーション,250,2013-09-25,2029-01-01,86
|
||||
209,0,スターヴォイス,200,2013-09-25,2029-01-01,87
|
||||
210,0,ハートビート,250,2014-09-17,2029-01-01,89
|
||||
211,0,パンジー,250,2013-09-25,2029-01-01,90
|
||||
212,0,レーシングミク2012ver.,250,2013-03-12,2029-01-01,91
|
||||
213,0,わがまま工場長,250,2015-05-28,2029-01-01,92
|
||||
214,0,Hello,Good night.,250,2014-02-25,2029-01-01,93
|
||||
215,0,初音ミク みずたまビキニ,1000,2013-07-04,2029-01-01,145
|
||||
216,0,初音ミク スクール競泳,1000,2013-06-06,2029-01-01,144
|
||||
217,0,初音ミク 浴衣スタイル,200,2013-07-31,2029-01-01,94
|
||||
218,0,らんみんぐ,250,2013-04-26,2029-01-01,95
|
||||
219,0,リボンガール,250,2013-01-30,2029-01-01,96
|
||||
220,0,メランコリー,250,2014-01-15,2029-01-01,13
|
||||
221,0,トランスミッター,250,2014-04-17,2029-01-01,14
|
||||
222,0,鏡音リン 桜月,250,2013-12-10,2029-01-01,15
|
||||
223,0,鏡音リン 雨,250,2014-07-29,2029-01-01,16
|
||||
224,0,鏡音リン しましまビキニ,1000,2013-07-04,2029-01-01,42
|
||||
225,0,鏡音リン SW スクール,1000,2013-06-06,2029-01-01,43
|
||||
226,0,鏡音リン 浴衣スタイル,150,2013-07-31,2029-01-01,17
|
||||
227,0,魔導師のタマゴ,250,2013-09-11,2029-01-01,19
|
||||
228,0,スタイリッシュエナジーR,250,2013-04-05,2029-01-01,20
|
||||
229,0,トラッドスクール,250,2012-12-27,2029-01-01,21
|
||||
230,0,スターマイン,250,2013-09-25,2029-01-01,10
|
||||
231,0,レシーバー,250,2014-04-17,2029-01-01,11
|
||||
232,0,鏡音レン 鳳月,250,2014-07-29,2029-01-01,12
|
||||
233,0,鏡音レン 鶴,250,2013-12-10,2029-01-01,13
|
||||
234,0,バッドボーイ,200,2013-09-25,2029-01-01,14
|
||||
235,0,鏡音レン SW ボクサー,1000,2013-06-06,2029-01-01,36
|
||||
236,0,鏡音レン 浴衣スタイル,200,2013-07-31,2029-01-01,16
|
||||
237,0,スタイリッシュエナジーL,250,2013-04-05,2029-01-01,17
|
||||
238,0,生徒会執行部,250,2012-12-27,2029-01-01,18
|
||||
239,0,バッドボーイ AS,200,2013-09-25,2029-01-01,15
|
||||
240,0,ゆるふわコーデ,250,2014-06-25,2029-01-01,11
|
||||
241,0,エターナルホワイト,250,2013-12-10,2029-01-01,12
|
||||
242,0,アムール,250,2014-04-17,2029-01-01,13
|
||||
243,0,巡音ルカ 紅玉,250,2016-05-26,2029-01-01,14
|
||||
244,0,巡音ルカ リゾートビキニ,1000,2013-07-04,2029-01-01,34
|
||||
245,0,巡音ルカ 競泳タイプ,1000,2013-06-06,2029-01-01,35
|
||||
246,0,巡音ルカ 浴衣スタイル,200,2013-07-31,2029-01-01,15
|
||||
247,0,森の妖精姫,250,2013-09-11,2029-01-01,16
|
||||
248,0,クイン・ビー,250,2013-04-26,2029-01-01,17
|
||||
249,0,放課後モード,250,2013-01-30,2029-01-01,18
|
||||
250,0,レクイエム,250,2013-12-17,2029-01-01,9
|
||||
251,0,ギルティ,250,2014-04-17,2029-01-01,10
|
||||
252,0,ジェネラル,200,2013-09-25,2029-01-01,11
|
||||
253,0,KAITO ハーフスパッツ,1000,2013-06-06,2029-01-01,36
|
||||
254,0,KAITO 浴衣スタイル,200,2013-07-31,2029-01-01,13
|
||||
255,0,ジーニアス,250,2013-05-15,2029-01-01,14
|
||||
256,0,学ラン★パーカー,250,2013-02-15,2029-01-01,15
|
||||
257,0,ジェネラル AS,200,2013-09-25,2029-01-01,12
|
||||
258,0,ブルークリスタル,250,2014-11-05,2029-01-01,10
|
||||
259,0,ノエル・ルージュ,250,2013-12-10,2029-01-01,11
|
||||
260,0,MEIKO ロングパレオ,1000,2013-07-04,2029-01-01,27
|
||||
261,0,MEIKO ウォーターポロ,1000,2013-06-06,2029-01-01,28
|
||||
262,0,MEIKO 浴衣スタイル,200,2013-07-31,2029-01-01,12
|
||||
263,0,ホイッスル,250,2013-05-15,2029-01-01,13
|
||||
264,0,グラデュエート,250,2013-02-15,2029-01-01,14
|
||||
265,0,BBオペレーター,250,2013-03-12,2029-01-01,15
|
||||
266,0,鏡音リン 浴衣スタイル AS,150,2013-07-31,2029-01-01,18
|
||||
267,0,カイト V3,300,2013-03-12,2029-01-01,42
|
||||
268,0,深海少女,250,2013-07-31,2029-01-01,169
|
||||
269,0,ハニーウィップ,250,2014-10-02,2029-01-01,148
|
||||
270,0,壱ノ桜・桜花,150,2015-03-26,2029-01-01,149
|
||||
271,0,リンちゃん愛し隊1号,200,2014-12-18,2029-01-01,151
|
||||
272,0,シザーズ,250,2014-06-25,2029-01-01,46
|
||||
273,0,弐ノ桜・胡蝶,200,2015-03-26,2029-01-01,47
|
||||
274,0,鏡音リン Future Style,300,2014-12-18,2029-01-01,49
|
||||
275,0,トリッカー,250,2014-12-18,2029-01-01,38
|
||||
276,0,弐ノ桜・扇舞,200,2015-03-26,2029-01-01,39
|
||||
277,0,参ノ桜・楓香,200,2015-03-26,2029-01-01,38
|
||||
278,0,リンちゃん愛し隊2号,200,2014-12-18,2029-01-01,39
|
||||
279,0,零ノ桜・蒼雪,150,2015-03-26,2029-01-01,39
|
||||
280,0,零ノ桜・紅椿,200,2015-03-26,2029-01-01,31
|
||||
281,0,リンケージ,250,2013-12-17,2029-01-01,147
|
||||
282,0,スターヴォイス AS,200,2013-09-25,2029-01-01,88
|
||||
283,0,重音テト,300,2013-09-25,2029-01-01,14
|
||||
284,0,雪ミク 2014,300,2013-12-17,2029-01-01,159
|
||||
285,0,雪ミク 2014 AS,100,2029-01-01,2029-01-01,160
|
||||
286,0,CA 初音ミク,250,2014-01-15,2029-01-01,122
|
||||
287,0,CA 鏡音リン,250,2014-01-15,2029-01-01,30
|
||||
288,0,CA 巡音ルカ,250,2014-01-15,2029-01-01,26
|
||||
289,0,CA メイコ,250,2014-01-15,2029-01-01,19
|
||||
290,0,マジカルミライ,300,2014-02-12,2029-01-01,170
|
||||
291,0,Cheerful ミク,150,2014-02-25,2029-01-01,123
|
||||
292,0,Cheerful ミク AS,150,2014-02-25,2029-01-01,124
|
||||
293,0,Cheerful リン,200,2014-02-25,2029-01-01,31
|
||||
294,0,Cheerful レン,200,2014-02-25,2029-01-01,26
|
||||
295,0,Cheerful ルカ,200,2014-02-25,2029-01-01,27
|
||||
296,0,Cheerful カイト,200,2014-02-25,2029-01-01,23
|
||||
297,0,Cheerful メイコ,200,2014-02-25,2029-01-01,20
|
||||
298,0,Cheerful カイト AS,200,2029-01-01,2029-01-01,24
|
||||
299,0,初音ミク V3,300,2014-08-28,2029-01-01,171
|
||||
300,0,アバンガード,250,2015-07-30,2029-01-01,97
|
||||
301,0,ナナイロライン,250,2015-08-28,2029-01-01,98
|
||||
302,0,ブレス・ユー,250,2015-10-08,2029-01-01,99
|
||||
303,0,花詞,250,2015-11-05,2029-01-01,100
|
||||
304,0,華車,250,2015-11-05,2029-01-01,101
|
||||
305,0,リグレット,250,2015-11-05,2029-01-01,102
|
||||
306,0,マリオネット,250,2015-11-05,2029-01-01,104
|
||||
308,0,ライアー,250,2016-01-28,2029-01-01,105
|
||||
309,0,月光アゲハ,250,2015-12-22,2029-01-01,106
|
||||
310,0,サイレン,250,2015-10-08,2029-01-01,107
|
||||
311,0,ローザ・ビアンカ,250,2016-06-30,2029-01-01,108
|
||||
313,0,メテオライト,250,2015-07-30,2029-01-01,111
|
||||
314,0,シャノワール,200,2015-06-26,2029-01-01,112
|
||||
315,0,シャノワール AS,200,2015-06-26,2029-01-01,113
|
||||
316,0,シュープリーム,250,2016-04-01,2029-01-01,114
|
||||
317,0,オレンジブロッサム,250,2015-08-28,2029-01-01,115
|
||||
318,0,ディメンション,250,2015-07-30,2029-01-01,116
|
||||
319,0,ストリートポップ,250,2016-01-28,2029-01-01,117
|
||||
320,0,ゆるふわパステル,250,2016-01-28,2029-01-01,118
|
||||
321,0,夢見るパンダ,250,2015-06-26,2029-01-01,22
|
||||
322,0,フェイカー,250,2016-01-28,2029-01-01,23
|
||||
323,0,ヒマワリ,200,2015-12-22,2029-01-01,24
|
||||
324,0,ソレイユ,250,2015-12-22,2029-01-01,26
|
||||
325,0,フェアリーワンピース,250,2015-12-22,2029-01-01,27
|
||||
326,0,恋するシロクマ,250,2015-06-26,2029-01-01,19
|
||||
327,0,アヤサキ,200,2015-12-22,2029-01-01,20
|
||||
328,0,シエル,250,2015-12-22,2029-01-01,22
|
||||
329,0,イレイザー,250,2016-01-28,2029-01-01,23
|
||||
330,0,ホワイトエッジ,250,2015-12-22,2029-01-01,24
|
||||
331,0,サクセサー,250,2015-07-30,2029-01-01,19
|
||||
332,0,テンプテーション,250,2016-01-28,2029-01-01,20
|
||||
334,0,リクルーター,250,2015-01-27,2029-01-01,22
|
||||
335,0,フローラル,250,2016-01-28,2029-01-01,23
|
||||
336,0,ローザ・ブルー,250,2016-06-30,2029-01-01,16
|
||||
338,0,オリジネイター,250,2016-01-28,2029-01-01,19
|
||||
339,0,ホリデイ,250,2015-11-05,2029-01-01,20
|
||||
340,0,ブレイジング,250,2015-11-05,2029-01-01,16
|
||||
341,0,マリーン・リボン,250,2015-11-05,2029-01-01,17
|
||||
343,0,うさみみパーカー,250,2016-08-31,2029-01-01,119
|
||||
344,0,アルパーカー R,250,2016-09-29,2029-01-01,28
|
||||
345,0,アルパーカー L,250,2016-09-29,2029-01-01,25
|
||||
346,0,ねこみみパーカー,250,2016-08-31,2029-01-01,24
|
||||
347,0,おサカナつなぎ,250,2016-10-27,2029-01-01,21
|
||||
348,0,ひつじさんウェア,250,2016-10-27,2029-01-01,18
|
||||
349,0,初音ミク スイムウェア/ST,1000,2016-07-28,2029-01-01,142
|
||||
350,0,鏡音リン スイムウェア/ST,1000,2016-07-28,2029-01-01,40
|
||||
351,0,鏡音レン スイムウェア/ST,300,2016-07-28,2029-01-01,34
|
||||
352,0,巡音ルカ スイムウェアP/ST,1000,2016-07-28,2029-01-01,33
|
||||
353,0,KAITO スイムウェアV/ST,750,2016-07-28,2029-01-01,33
|
||||
354,0,KAITO スイムウェアV AS/ST,750,2016-07-28,2029-01-01,35
|
||||
355,0,MEIKO スイムウェア/ST,1000,2016-07-28,2029-01-01,25
|
||||
356,0,M・S・J,300,2016-04-01,2029-01-01,15
|
||||
359,0,out of the gravity,250,2014-08-28,2029-01-01,126
|
||||
360,0,インタビュア ミク,250,2014-10-02,2029-01-01,127
|
||||
361,0,インタビュア ルカ,250,2014-10-02,2029-01-01,28
|
||||
362,0,スイートパンプキン,300,2014-10-02,2029-01-01,172
|
||||
363,0,MEIKO V3,300,2014-11-05,2029-01-01,34
|
||||
364,0,雪ミク 2015,300,2014-12-18,2029-01-01,161
|
||||
365,0,壱ノ桜・白桜花,150,2015-03-26,2029-01-01,150
|
||||
366,0,零ノ桜・白雪,150,2015-03-26,2029-01-01,40
|
||||
367,0,ダイヤモンドダスト,250,2015-01-27,2029-01-01,25
|
||||
368,0,アイスフォグ,250,2015-01-27,2029-01-01,27
|
||||
369,0,テレカクシパーカー 黄色,250,2015-04-23,2029-01-01,28
|
||||
370,0,テレカクシパーカー 青色,250,2015-04-23,2029-01-01,26
|
||||
371,0,スチャラカハツネ,250,2015-05-28,2029-01-01,130
|
||||
372,0,マジックシェフ,250,2015-06-26,2029-01-01,32
|
||||
373,0,グラデーションリゾート,1000,2015-08-06,2029-01-01,146
|
||||
374,0,ミラクルスターリゾート,1000,2015-08-06,2029-01-01,44
|
||||
375,0,ポップスターリゾート,1000,2015-08-06,2029-01-01,37
|
||||
376,0,トゥインクルリゾート,1000,2015-08-06,2029-01-01,36
|
||||
377,0,プレイドリゾート,1000,2015-08-06,2029-01-01,37
|
||||
378,0,バイカラーリボンリゾート,1000,2015-08-06,2029-01-01,29
|
||||
379,0,ありふれミク,250,2015-08-28,2029-01-01,128
|
||||
380,0,P4Dスタイル,300,2016-06-23,2029-01-01,173
|
||||
381,0,PIANO*GIRL,250,2015-10-08,2029-01-01,129
|
||||
382,0,重音テト スイムウェア,1000,2015-11-05,2029-01-01,16
|
||||
383,0,巡音ルカV4X,300,2016-01-28,2029-01-01,44
|
||||
385,0,Trip The Light Fantastic,250,2016-04-27,2029-01-01,132
|
||||
386,0,Poppin Delight,250,2016-04-27,2029-01-01,33
|
||||
387,0,Bebop Knave,250,2016-04-27,2029-01-01,29
|
||||
389,0,プランセス・ブランシュ,250,2016-04-27,2029-01-01,133
|
||||
390,0,プランス・ブラン,250,2016-04-27,2029-01-01,27
|
||||
391,0,アドレサンスプリンセス,250,2016-04-27,2029-01-01,343
|
||||
392,0,アドレサンスナイト,250,2016-04-27,2029-01-01,30
|
||||
393,0,マーチ・ヘイヤ,250,2016-08-31,2029-01-01,136
|
||||
394,0,アゲアゲアゲイン,250,2016-02-26,2029-01-01,131
|
||||
395,0,エトワール,250,2016-06-30,2029-01-01,135
|
||||
398,0,フェアウェル,250,2016-06-30,2029-01-01,134
|
||||
399,0,天袖,250,2016-12-21,2029-01-01,36
|
||||
402,0,雪ミク 2016,300,2015-12-22,2029-01-01,162
|
||||
403,0,パジャマパーティ ミク,250,2017-01-26,2029-01-01,139
|
||||
404,0,パジャマパーティ リン,250,2017-01-26,2029-01-01,38
|
||||
405,0,パジャマパーティ レン,250,2017-01-26,2029-01-01,32
|
||||
406,0,パジャマパーティ ルカ,250,2017-01-26,2029-01-01,30
|
||||
407,0,パジャマパーティ カイト,250,2017-01-26,2029-01-01,30
|
||||
408,0,パジャマパーティ メイコ,250,2017-01-26,2029-01-01,23
|
||||
409,0,Phantom Thief ミク,250,2016-10-27,2029-01-01,137
|
||||
410,0,Phantom Thief リン,250,2016-10-27,2029-01-01,35
|
||||
411,0,Phantom Thief メイコ,250,2016-10-27,2029-01-01,21
|
||||
412,0,Phantom Thief カイト,250,2016-10-27,2029-01-01,28
|
||||
413,0,鉄道員・鶯,250,2016-12-21,2029-01-01,138
|
||||
414,0,鉄道員・金糸雀,250,2016-12-21,2029-01-01,37
|
||||
415,0,鉄道員・銀朱,250,2016-12-21,2029-01-01,31
|
||||
416,0,鉄道員・薔薇,250,2016-12-21,2029-01-01,29
|
||||
417,0,鉄道員・空,250,2016-12-21,2029-01-01,29
|
||||
418,0,鉄道員・紅葡萄,250,2016-12-21,2029-01-01,22
|
||||
419,0,雪ミク 2017,300,2016-12-21,2029-01-01,163
|
||||
420,0,ヒマワリ AS,200,2015-12-22,2029-01-01,25
|
||||
421,0,アヤサキ AS,200,2015-12-22,2029-01-01,21
|
||||
422,0,みくりすたる☆,300,2016-05-26,2029-01-01,125
|
||||
423,0,マイディアバニー,1000,2017-08-31,2029-01-01,174
|
||||
424,0,ローザ・ノッテ,250,2016-12-21,2029-01-01,110
|
||||
425,0,ローザ・ルーノ,250,2016-12-21,2029-01-01,18
|
||||
426,0,GHOST,250,2017-12-13,2029-01-01,175
|
||||
427,0,セレブレーション,300,2017-12-13,2029-01-01,176
|
||||
428,0,雪ミク 2018 AS,300,2019-04-24,2029-01-01,165
|
||||
429,0,雪ミク 2019,300,2019-04-24,2029-01-01,166
|
||||
430,0,雪ミク 2018,300,2019-04-24,2029-01-01,164
|
||||
431,0,Catch The Wave,900,2020-02-20,2029-01-01,177
|
12
titles/diva/database.py
Normal file
12
titles/diva/database.py
Normal file
@ -0,0 +1,12 @@
|
||||
from core.data import Data
|
||||
from core.config import CoreConfig
|
||||
from titles.diva.schema import DivaProfileData, DivaScoreData, DivaItemData, DivaStaticData
|
||||
|
||||
class DivaData(Data):
|
||||
def __init__(self, cfg: CoreConfig) -> None:
|
||||
super().__init__(cfg)
|
||||
|
||||
self.profile = DivaProfileData(self.config, self.session)
|
||||
self.score = DivaScoreData(self.config, self.session)
|
||||
self.item = DivaItemData(self.config, self.session)
|
||||
self.static = DivaStaticData(self.config, self.session)
|
105
titles/diva/index.py
Normal file
105
titles/diva/index.py
Normal file
@ -0,0 +1,105 @@
|
||||
from twisted.web.http import Request
|
||||
import yaml
|
||||
import logging, coloredlogs
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
import zlib
|
||||
import json
|
||||
import urllib.parse
|
||||
import base64
|
||||
|
||||
from core.config import CoreConfig
|
||||
from titles.diva.config import DivaConfig
|
||||
from titles.diva.base import DivaBase
|
||||
|
||||
class DivaServlet():
|
||||
def __init__(self, core_cfg: CoreConfig, cfg_dir: str) -> None:
|
||||
self.core_cfg = core_cfg
|
||||
self.game_cfg = DivaConfig()
|
||||
self.game_cfg.update(yaml.safe_load(open(f"{cfg_dir}/diva.yaml")))
|
||||
|
||||
self.base = DivaBase(core_cfg, self.game_cfg)
|
||||
|
||||
self.logger = logging.getLogger("diva")
|
||||
log_fmt_str = "[%(asctime)s] Diva | %(levelname)s | %(message)s"
|
||||
log_fmt = logging.Formatter(log_fmt_str)
|
||||
fileHandler = TimedRotatingFileHandler("{0}/{1}.log".format(self.core_cfg.server.log_dir, "diva"), encoding='utf8',
|
||||
when="d", backupCount=10)
|
||||
|
||||
fileHandler.setFormatter(log_fmt)
|
||||
|
||||
consoleHandler = logging.StreamHandler()
|
||||
consoleHandler.setFormatter(log_fmt)
|
||||
|
||||
self.logger.addHandler(fileHandler)
|
||||
self.logger.addHandler(consoleHandler)
|
||||
|
||||
self.logger.setLevel(self.game_cfg.server.loglevel)
|
||||
coloredlogs.install(level=self.game_cfg.server.loglevel, logger=self.logger, fmt=log_fmt_str)
|
||||
|
||||
def render_POST(self, req: Request, version: int, url_path: str) -> bytes:
|
||||
req_raw = req.content.getvalue()
|
||||
url_header = req.getAllHeaders()
|
||||
|
||||
#Ping Dispatch
|
||||
if "THIS_STRING_SEPARATES"in str(url_header):
|
||||
binary_request = req_raw.splitlines()
|
||||
binary_cmd_decoded = binary_request[3].decode("utf-8")
|
||||
binary_array = binary_cmd_decoded.split('&')
|
||||
|
||||
bin_req_data = {}
|
||||
|
||||
for kvp in binary_array:
|
||||
split_bin = kvp.split("=")
|
||||
bin_req_data[split_bin[0]] = split_bin[1]
|
||||
|
||||
self.logger.info(f"Binary {bin_req_data['cmd']} Request")
|
||||
self.logger.debug(bin_req_data)
|
||||
|
||||
handler = getattr(self.base, f"handle_{bin_req_data['cmd']}_request")
|
||||
resp = handler(bin_req_data)
|
||||
|
||||
self.logger.debug(f"Response cmd={bin_req_data['cmd']}&req_id={bin_req_data['req_id']}&stat=ok{resp}")
|
||||
return f"cmd={bin_req_data['cmd']}&req_id={bin_req_data['req_id']}&stat=ok{resp}".encode('utf-8')
|
||||
|
||||
#Main Dispatch
|
||||
json_string = json.dumps(req_raw.decode("utf-8")) #Take the response and decode as UTF-8 and dump
|
||||
b64string = json_string.replace(r'\n', '\n') # Remove all \n and separate them as new lines
|
||||
gz_string = base64.b64decode(b64string) # Decompressing the base64 string
|
||||
|
||||
try:
|
||||
url_data = zlib.decompress( gz_string ).decode("utf-8") # Decompressing the gzip
|
||||
except zlib.error as e:
|
||||
self.logger.error(f"Failed to defalte! {e} -> {gz_string}")
|
||||
return "stat=0"
|
||||
|
||||
req_kvp = urllib.parse.unquote(url_data)
|
||||
req_data = {}
|
||||
|
||||
# We then need to split each parts with & so we can reuse them to fill out the requests
|
||||
splitted_request = str.split(req_kvp, "&")
|
||||
for kvp in splitted_request:
|
||||
split = kvp.split("=")
|
||||
req_data[split[0]] = split[1]
|
||||
|
||||
self.logger.info(f"{req_data['cmd']} Request")
|
||||
self.logger.debug(req_data)
|
||||
|
||||
func_to_find = f"handle_{req_data['cmd']}_request"
|
||||
|
||||
# Load the requests
|
||||
try:
|
||||
handler = getattr(self.base, func_to_find)
|
||||
resp = handler(req_data)
|
||||
|
||||
except AttributeError as e:
|
||||
self.logger.warning(f"Unhandled {req_data['cmd']} request {e}")
|
||||
return f"cmd={req_data['cmd']}&req_id={req_data['req_id']}&stat=ok".encode('utf-8')
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error handling method {func_to_find} {e}")
|
||||
return f"cmd={req_data['cmd']}&req_id={req_data['req_id']}&stat=ok".encode('utf-8')
|
||||
|
||||
req.responseHeaders.addRawHeader(b"content-type", b"text/plain")
|
||||
self.logger.debug(f"Response cmd={req_data['cmd']}&req_id={req_data['req_id']}&stat=ok{resp}")
|
||||
|
||||
return f"cmd={req_data['cmd']}&req_id={req_data['req_id']}&stat=ok{resp}".encode('utf-8')
|
203
titles/diva/read.py
Normal file
203
titles/diva/read.py
Normal file
@ -0,0 +1,203 @@
|
||||
from typing import Optional, Dict, List
|
||||
from os import walk, path
|
||||
import urllib
|
||||
|
||||
from read import BaseReader
|
||||
from core.config import CoreConfig
|
||||
from titles.diva.database import DivaData
|
||||
from titles.diva.const import DivaConstants
|
||||
|
||||
class DivaReader(BaseReader):
|
||||
def __init__(self, config: CoreConfig, version: int, bin_dir: Optional[str], opt_dir: Optional[str], extra: Optional[str]) -> None:
|
||||
super().__init__(config, version, bin_dir, opt_dir, extra)
|
||||
self.data = DivaData(config)
|
||||
|
||||
try:
|
||||
self.logger.info(f"Start importer for {DivaConstants.game_ver_to_string(version)}")
|
||||
except IndexError:
|
||||
self.logger.error(f"Invalid project diva version {version}")
|
||||
exit(1)
|
||||
|
||||
def read(self) -> None:
|
||||
pull_bin_ram = True
|
||||
pull_bin_rom = True
|
||||
pull_opt_rom = True
|
||||
|
||||
if not path.exists(f"{self.bin_dir}/ram"):
|
||||
self.logger.warn(f"Couldn't find ram folder in {self.bin_dir}, skipping")
|
||||
pull_bin_ram = False
|
||||
|
||||
if not path.exists(f"{self.bin_dir}/rom"):
|
||||
self.logger.warn(f"Couldn't find rom folder in {self.bin_dir}, skipping")
|
||||
pull_bin_rom = False
|
||||
|
||||
if self.opt_dir is not None:
|
||||
opt_dirs = self.get_data_directories(self.opt_dir)
|
||||
else:
|
||||
pull_opt_rom = False
|
||||
self.logger.warn("No option directory specified, skipping")
|
||||
|
||||
if pull_bin_ram:
|
||||
self.read_ram(f"{self.bin_dir}/ram")
|
||||
if pull_bin_rom:
|
||||
self.read_rom(f"{self.bin_dir}/rom")
|
||||
if pull_opt_rom:
|
||||
for dir in opt_dirs:
|
||||
self.read_rom(f"{dir}/rom")
|
||||
|
||||
def read_ram(self, ram_root_dir: str) -> None:
|
||||
self.logger.info(f"Read RAM from {ram_root_dir}")
|
||||
|
||||
if path.exists(f"{ram_root_dir}/databank"):
|
||||
for root, dirs, files in walk(f"{ram_root_dir}/databank"):
|
||||
for file in files:
|
||||
if file.startswith("ShopCatalog_") or file.startswith("CustomizeItemCatalog_") or \
|
||||
(file.startswith("QuestInfo") and not file.startswith("QuestInfoTm")):
|
||||
|
||||
with open(f"{root}/{file}", "r") as f:
|
||||
file_data: str = urllib.parse.unquote(urllib.parse.unquote(f.read()))
|
||||
if file_data == "***":
|
||||
self.logger.info(f"{file} is empty, skipping")
|
||||
continue
|
||||
|
||||
file_lines: List[str] = file_data.split("\n")
|
||||
|
||||
for line in file_lines:
|
||||
split = line.split(",")
|
||||
|
||||
if not split[0]:
|
||||
split.pop(0)
|
||||
|
||||
if file.startswith("ShopCatalog_"):
|
||||
for x in range(0, len(split), 7):
|
||||
self.logger.info(f"Added shop item {split[x+0]}")
|
||||
|
||||
self.data.static.put_shop(self.version, split[x+0], split[x+2], split[x+6], split[x+3],
|
||||
split[x+1], split[x+4], split[x+5])
|
||||
|
||||
elif file.startswith("CustomizeItemCatalog_") and len(split) >= 7:
|
||||
for x in range(0, len(split), 7):
|
||||
self.logger.info(f"Added item {split[x+0]}")
|
||||
|
||||
self.data.static.put_items(self.version, split[x+0], split[x+2], split[x+6], split[x+3],
|
||||
split[x+1], split[x+4], split[x+5])
|
||||
|
||||
elif file.startswith("QuestInfo") and len(split) >= 9:
|
||||
self.logger.info(f"Added quest {split[0]}")
|
||||
|
||||
self.data.static.put_quests(self.version, split[0], split[6], split[2], split[3],
|
||||
split[7], split[8], split[1], split[4], split[5])
|
||||
|
||||
else:
|
||||
continue
|
||||
else:
|
||||
self.logger.warn(f"Databank folder not found in {ram_root_dir}, skipping")
|
||||
|
||||
def read_rom(self, rom_root_dir: str) -> None:
|
||||
self.logger.info(f"Read ROM from {rom_root_dir}")
|
||||
pv_list: Dict[str, Dict] = {}
|
||||
|
||||
if path.exists(f"{rom_root_dir}/mdata_pv_db.txt"):
|
||||
file_path = f"{rom_root_dir}/mdata_pv_db.txt"
|
||||
elif path.exists(f"{rom_root_dir}/pv_db.txt"):
|
||||
file_path = f"{rom_root_dir}/pv_db.txt"
|
||||
else:
|
||||
self.logger.warn(f"Cannot find pv_db.txt or mdata_pv_db.txt in {rom_root_dir}, skipping")
|
||||
return
|
||||
|
||||
with open(file_path, "r", encoding="utf-8") as f:
|
||||
|
||||
for line in f.readlines():
|
||||
|
||||
if line.startswith("#") or not line:
|
||||
continue
|
||||
|
||||
line_split = line.split("=")
|
||||
if len(line_split) != 2:
|
||||
continue
|
||||
|
||||
key = line_split[0]
|
||||
val = line_split[1]
|
||||
if val.endswith("\n"):
|
||||
val = val[:-1]
|
||||
|
||||
key_split = key.split(".")
|
||||
pv_id = key_split[0]
|
||||
key_args = []
|
||||
|
||||
for x in range(1, len(key_split)):
|
||||
key_args.append(key_split[x])
|
||||
|
||||
try:
|
||||
pv_list[pv_id] = self.add_branch(pv_list[pv_id], key_args, val)
|
||||
except KeyError:
|
||||
pv_list[pv_id] = {}
|
||||
pv_list[pv_id] = self.add_branch(pv_list[pv_id], key_args, val)
|
||||
|
||||
|
||||
for pv_id, pv_data in pv_list.items():
|
||||
song_id = int(pv_id.split("_")[1])
|
||||
if "songinfo" not in pv_data:
|
||||
continue
|
||||
if "illustrator" not in pv_data["songinfo"]:
|
||||
pv_data["songinfo"]["illustrator"] = "-"
|
||||
if "arranger" not in pv_data["songinfo"]:
|
||||
pv_data["songinfo"]["arranger"] = "-"
|
||||
if "lyrics" not in pv_data["songinfo"]:
|
||||
pv_data["songinfo"]["lyrics"] = "-"
|
||||
if "music" not in pv_data["songinfo"]:
|
||||
pv_data["songinfo"]["music"] = "-"
|
||||
|
||||
if "easy" in pv_data['difficulty'] and '0' in pv_data['difficulty']['easy']:
|
||||
diff = pv_data['difficulty']['easy']['0']['level'].split('_')
|
||||
self.logger.info(f"Added song {song_id} chart 0")
|
||||
|
||||
self.data.static.put_music(self.version, song_id, 0, pv_data["song_name"], pv_data["songinfo"]["arranger"],
|
||||
pv_data["songinfo"]["illustrator"], pv_data["songinfo"]["lyrics"], pv_data["songinfo"]["music"],
|
||||
float(f"{diff[2]}.{diff[3]}"), pv_data["bpm"], pv_data["date"])
|
||||
|
||||
if "normal" in pv_data['difficulty'] and '0' in pv_data['difficulty']['normal']:
|
||||
diff = pv_data['difficulty']['normal']['0']['level'].split('_')
|
||||
self.logger.info(f"Added song {song_id} chart 1")
|
||||
|
||||
self.data.static.put_music(self.version, song_id, 1, pv_data["song_name"], pv_data["songinfo"]["arranger"],
|
||||
pv_data["songinfo"]["illustrator"], pv_data["songinfo"]["lyrics"], pv_data["songinfo"]["music"],
|
||||
float(f"{diff[2]}.{diff[3]}"), pv_data["bpm"], pv_data["date"])
|
||||
|
||||
if "hard" in pv_data['difficulty'] and '0' in pv_data['difficulty']['hard']:
|
||||
diff = pv_data['difficulty']['hard']['0']['level'].split('_')
|
||||
self.logger.info(f"Added song {song_id} chart 2")
|
||||
|
||||
self.data.static.put_music(self.version, song_id, 2, pv_data["song_name"], pv_data["songinfo"]["arranger"],
|
||||
pv_data["songinfo"]["illustrator"], pv_data["songinfo"]["lyrics"], pv_data["songinfo"]["music"],
|
||||
float(f"{diff[2]}.{diff[3]}"), pv_data["bpm"], pv_data["date"])
|
||||
|
||||
if "extreme" in pv_data['difficulty']:
|
||||
if "0" in pv_data['difficulty']['extreme']:
|
||||
diff = pv_data['difficulty']['extreme']['0']['level'].split('_')
|
||||
self.logger.info(f"Added song {song_id} chart 3")
|
||||
|
||||
self.data.static.put_music(self.version, song_id, 3, pv_data["song_name"], pv_data["songinfo"]["arranger"],
|
||||
pv_data["songinfo"]["illustrator"], pv_data["songinfo"]["lyrics"], pv_data["songinfo"]["music"],
|
||||
float(f"{diff[2]}.{diff[3]}"), pv_data["bpm"], pv_data["date"])
|
||||
|
||||
if "1" in pv_data['difficulty']['extreme']:
|
||||
diff = pv_data['difficulty']['extreme']['1']['level'].split('_')
|
||||
self.logger.info(f"Added song {song_id} chart 4")
|
||||
|
||||
self.data.static.put_music(self.version, song_id, 4, pv_data["song_name"], pv_data["songinfo"]["arranger"],
|
||||
pv_data["songinfo"]["illustrator"], pv_data["songinfo"]["lyrics"], pv_data["songinfo"]["music"],
|
||||
float(f"{diff[2]}.{diff[3]}"), pv_data["bpm"], pv_data["date"])
|
||||
|
||||
def add_branch(self, tree: Dict, vector: List, value: str):
|
||||
"""
|
||||
Recursivly adds nodes to a dictionary
|
||||
Author: iJames on StackOverflow
|
||||
"""
|
||||
key = vector[0]
|
||||
tree[key] = value \
|
||||
if len(vector) == 1 \
|
||||
else self.add_branch(tree[key] if key in tree else {},
|
||||
vector[1:],
|
||||
value)
|
||||
return tree
|
6
titles/diva/schema/__init__.py
Normal file
6
titles/diva/schema/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
from titles.diva.schema.profile import DivaProfileData
|
||||
from titles.diva.schema.score import DivaScoreData
|
||||
from titles.diva.schema.item import DivaItemData
|
||||
from titles.diva.schema.static import DivaStaticData
|
||||
|
||||
__all__ = [DivaProfileData, DivaScoreData, DivaItemData, DivaStaticData]
|
50
titles/diva/schema/item.py
Normal file
50
titles/diva/schema/item.py
Normal file
@ -0,0 +1,50 @@
|
||||
from typing import Optional, Dict, List
|
||||
from sqlalchemy import Table, Column, UniqueConstraint, PrimaryKeyConstraint, and_, case
|
||||
from sqlalchemy.types import Integer, String, TIMESTAMP, Boolean
|
||||
from sqlalchemy.schema import ForeignKey
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.dialects.mysql import insert
|
||||
|
||||
from core.data.schema import BaseData, metadata
|
||||
|
||||
shop = Table(
|
||||
"diva_profile_shop",
|
||||
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("mdl_eqp_ary", String(32)),
|
||||
UniqueConstraint("user", "version", name="diva_profile_shop_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
)
|
||||
|
||||
class DivaItemData(BaseData):
|
||||
def put_shop(self, aime_id: int, version: int, mdl_eqp_ary: str) -> None:
|
||||
sql = insert(shop).values(
|
||||
version=version,
|
||||
user=aime_id,
|
||||
mdl_eqp_ary=mdl_eqp_ary
|
||||
)
|
||||
|
||||
conflict = sql.on_duplicate_key_update(
|
||||
mdl_eqp_ary = sql.inserted.mdl_eqp_ary
|
||||
)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None:
|
||||
self.logger.error(f"{__name__} Failed to insert diva profile! aime id: {aime_id} array: {mdl_eqp_ary}")
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
def get_shop(self, aime_id: int, version: int) -> Optional[List[Dict]]:
|
||||
"""
|
||||
Given a game version and either a profile or aime id, return the profile
|
||||
"""
|
||||
sql = shop.select(and_(
|
||||
shop.c.version == version,
|
||||
shop.c.user == aime_id
|
||||
))
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
return result.fetchone()
|
113
titles/diva/schema/profile.py
Normal file
113
titles/diva/schema/profile.py
Normal file
@ -0,0 +1,113 @@
|
||||
from typing import Optional, Dict, List
|
||||
from sqlalchemy import Table, Column, UniqueConstraint, PrimaryKeyConstraint, and_
|
||||
from sqlalchemy.types import Integer, String, TIMESTAMP, Boolean, JSON
|
||||
from sqlalchemy.schema import ForeignKey
|
||||
from sqlalchemy.sql import func, select
|
||||
from sqlalchemy.dialects.mysql import insert
|
||||
|
||||
from core.data.schema import BaseData, metadata
|
||||
|
||||
profile = Table(
|
||||
"diva_profile",
|
||||
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("player_name", String(8), nullable=False),
|
||||
Column("lv_str", String(24), nullable=False, server_default="Dab on 'em"),
|
||||
Column("lv_num", Integer, nullable=False, server_default="0"),
|
||||
Column("lv_pnt", Integer, nullable=False, server_default="0"),
|
||||
Column("vcld_pts", Integer, nullable=False, server_default="0"),
|
||||
Column("hp_vol", Integer, nullable=False, server_default="100"),
|
||||
Column("btn_se_vol", Integer, nullable=False, server_default="100"),
|
||||
Column("btn_se_vol2", Integer, nullable=False, server_default="100"),
|
||||
Column("sldr_se_vol2", Integer, nullable=False, server_default="100"),
|
||||
Column("sort_kind", Integer, nullable=False, server_default="2"),
|
||||
Column("use_pv_mdl_eqp", String(8), nullable=False, server_default="true"),
|
||||
Column("use_pv_btn_se_eqp", String(8), nullable=False, server_default="true"),
|
||||
Column("use_pv_sld_se_eqp", String(8), nullable=False, server_default="false"),
|
||||
Column("use_pv_chn_sld_se_eqp", String(8), nullable=False, server_default="false"),
|
||||
Column("use_pv_sldr_tch_se_eqp", String(8), nullable=False, server_default="false"),
|
||||
Column("nxt_pv_id", Integer, nullable=False, server_default="708"),
|
||||
Column("nxt_dffclty", Integer, nullable=False, server_default="2"),
|
||||
Column("nxt_edtn", Integer, nullable=False, server_default="0"),
|
||||
Column("dsp_clr_brdr", Integer, nullable=False, server_default="7"),
|
||||
Column("dsp_intrm_rnk", Integer, nullable=False, server_default="1"),
|
||||
Column("dsp_clr_sts", Integer, nullable=False, server_default="1"),
|
||||
Column("rgo_sts", Integer, nullable=False, server_default="1"),
|
||||
Column("lv_efct_id", Integer, nullable=False, server_default="0"),
|
||||
Column("lv_plt_id", Integer, nullable=False, server_default="1"),
|
||||
Column("my_qst_id", String(128), server_default="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"),
|
||||
Column("my_qst_sts", String(128), server_default="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"),
|
||||
UniqueConstraint("user", "version", name="diva_profile_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
)
|
||||
|
||||
class DivaProfileData(BaseData):
|
||||
def create_profile(self, version: int, aime_id: int, player_name: str) -> Optional[int]:
|
||||
"""
|
||||
Given a game version, aime id, and player_name, create a profile and return it's ID
|
||||
"""
|
||||
sql = insert(profile).values(
|
||||
version=version,
|
||||
user=aime_id,
|
||||
player_name=player_name
|
||||
)
|
||||
|
||||
conflict = sql.on_duplicate_key_update(
|
||||
player_name = sql.inserted.player_name
|
||||
)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None:
|
||||
self.logger.error(f"{__name__} Failed to insert diva profile! aime id: {aime_id} username: {player_name}")
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
def update_profile(self, profile_id: int, lv_num: int, lv_pnt: int, vcld_pts: int, hp_vol: int, btn_se_vol: int, btn_se_vol2: int, sldr_se_vol2: int, sort_kind: int, use_pv_mdl_eqp: str, use_pv_btn_se_eqp: str, use_pv_sld_se_eqp: str, use_pv_chn_sld_se_eqp: str, use_pv_sldr_tch_se_eqp: str, nxt_pv_id: int, nxt_dffclty: int, nxt_edtn: int, dsp_clr_brdr: int, dsp_intrm_rnk: int, dsp_clr_sts: int, rgo_sts: int, lv_efct_id: int, lv_plt_id: int, my_qst_id: str, my_qst_sts: str) -> None:
|
||||
sql = profile.update(profile.c.user == profile_id).values(
|
||||
|
||||
lv_num = lv_num,
|
||||
lv_pnt = lv_pnt,
|
||||
vcld_pts = vcld_pts,
|
||||
hp_vol = hp_vol,
|
||||
btn_se_vol = btn_se_vol,
|
||||
btn_se_vol2 = btn_se_vol2,
|
||||
sldr_se_vol2 = sldr_se_vol2,
|
||||
sort_kind = sort_kind,
|
||||
use_pv_mdl_eqp = use_pv_mdl_eqp,
|
||||
use_pv_btn_se_eqp = use_pv_btn_se_eqp,
|
||||
use_pv_sld_se_eqp = use_pv_sld_se_eqp,
|
||||
use_pv_chn_sld_se_eqp = use_pv_chn_sld_se_eqp,
|
||||
use_pv_sldr_tch_se_eqp = use_pv_sldr_tch_se_eqp,
|
||||
nxt_pv_id = nxt_pv_id,
|
||||
nxt_dffclty = nxt_dffclty,
|
||||
nxt_edtn = nxt_edtn,
|
||||
dsp_clr_brdr = dsp_clr_brdr,
|
||||
dsp_intrm_rnk = dsp_intrm_rnk,
|
||||
dsp_clr_sts = dsp_clr_sts,
|
||||
rgo_sts = rgo_sts,
|
||||
lv_efct_id = lv_efct_id,
|
||||
lv_plt_id = lv_plt_id,
|
||||
my_qst_id = my_qst_id,
|
||||
my_qst_sts = my_qst_sts
|
||||
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None:
|
||||
self.logger.error(f"update_profile: failed to update profile! profile: {profile_id}")
|
||||
return None
|
||||
|
||||
def get_profile(self, aime_id: int, version: int) -> Optional[List[Dict]]:
|
||||
"""
|
||||
Given a game version and either a profile or aime id, return the profile
|
||||
"""
|
||||
sql = profile.select(and_(
|
||||
profile.c.version == version,
|
||||
profile.c.user == aime_id
|
||||
))
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
return result.fetchone()
|
141
titles/diva/schema/score.py
Normal file
141
titles/diva/schema/score.py
Normal file
@ -0,0 +1,141 @@
|
||||
from sqlalchemy import Table, Column, UniqueConstraint, PrimaryKeyConstraint, and_
|
||||
from sqlalchemy.types import Integer, String, TIMESTAMP, JSON, Boolean
|
||||
from sqlalchemy.schema import ForeignKey
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.dialects.mysql import insert
|
||||
from typing import Optional, List, Dict, Any
|
||||
|
||||
from core.data.schema import BaseData, metadata
|
||||
from core.data import cached
|
||||
|
||||
score = Table(
|
||||
"diva_score",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade"), nullable=False),
|
||||
Column("version", Integer),
|
||||
Column("pv_id", Integer),
|
||||
Column("difficulty", Integer),
|
||||
Column("score", Integer),
|
||||
Column("atn_pnt", Integer),
|
||||
Column("clr_kind", Integer),
|
||||
Column("sort_kind", Integer),
|
||||
Column("cool", Integer),
|
||||
Column("fine", Integer),
|
||||
Column("safe", Integer),
|
||||
Column("sad", Integer),
|
||||
Column("worst", Integer),
|
||||
Column("max_combo", Integer),
|
||||
UniqueConstraint("user", "pv_id", "difficulty", name="diva_score_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
)
|
||||
|
||||
playlog = Table(
|
||||
"diva_playlog",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("user", ForeignKey("aime_user.id", ondelete="cascade"), nullable=False),
|
||||
Column("version", Integer),
|
||||
Column("pv_id", Integer),
|
||||
Column("difficulty", Integer),
|
||||
Column("score", Integer),
|
||||
Column("atn_pnt", Integer),
|
||||
Column("clr_kind", Integer),
|
||||
Column("sort_kind", Integer),
|
||||
Column("cool", Integer),
|
||||
Column("fine", Integer),
|
||||
Column("safe", Integer),
|
||||
Column("sad", Integer),
|
||||
Column("worst", Integer),
|
||||
Column("max_combo", Integer),
|
||||
Column("date_scored", TIMESTAMP, server_default=func.now()),
|
||||
mysql_charset='utf8mb4'
|
||||
)
|
||||
|
||||
class DivaScoreData(BaseData):
|
||||
def put_best_score(self, user_id: int, game_version: int, song_id: int, difficulty: int, song_score: int, atn_pnt: int,
|
||||
clr_kind: int, sort_kind:int, cool: int, fine: int, safe: int, sad: int, worst: int, max_combo: int) -> Optional[int]:
|
||||
"""
|
||||
Update the user's best score for a chart
|
||||
"""
|
||||
sql = insert(score).values(
|
||||
user=user_id,
|
||||
version=game_version,
|
||||
pv_id = song_id,
|
||||
difficulty=difficulty,
|
||||
score=song_score,
|
||||
atn_pnt = atn_pnt,
|
||||
clr_kind = clr_kind,
|
||||
sort_kind = sort_kind,
|
||||
cool = cool,
|
||||
fine = fine,
|
||||
safe = safe,
|
||||
sad = sad,
|
||||
worst = worst,
|
||||
max_combo = max_combo,
|
||||
)
|
||||
|
||||
conflict = sql.on_duplicate_key_update(
|
||||
score=song_score,
|
||||
atn_pnt = atn_pnt,
|
||||
clr_kind = clr_kind,
|
||||
sort_kind = sort_kind,
|
||||
cool = cool,
|
||||
fine = fine,
|
||||
safe = safe,
|
||||
sad = sad,
|
||||
worst = worst,
|
||||
max_combo = max_combo,
|
||||
)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None:
|
||||
self.logger.error(f"{__name__} failed to insert best score! profile: {user_id}, song: {song_id}")
|
||||
return None
|
||||
|
||||
return result.lastrowid
|
||||
|
||||
def put_playlog(self, user_id: int, game_version: int, song_id: int, difficulty: int, song_score: int, atn_pnt: int,
|
||||
clr_kind: int, sort_kind:int, cool: int, fine: int, safe: int, sad: int, worst: int, max_combo: int) -> Optional[int]:
|
||||
"""
|
||||
Add an entry to the user's play log
|
||||
"""
|
||||
sql = playlog.insert().values(
|
||||
user=user_id,
|
||||
version=game_version,
|
||||
pv_id = song_id,
|
||||
difficulty=difficulty,
|
||||
score=song_score,
|
||||
atn_pnt = atn_pnt,
|
||||
clr_kind = clr_kind,
|
||||
sort_kind = sort_kind,
|
||||
cool = cool,
|
||||
fine = fine,
|
||||
safe = safe,
|
||||
sad = sad,
|
||||
worst = worst,
|
||||
max_combo = max_combo
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None:
|
||||
self.logger.error(f"{__name__} failed to insert playlog! profile: {user_id}, song: {song_id}, chart: {difficulty}")
|
||||
return None
|
||||
|
||||
return result.lastrowid
|
||||
|
||||
def get_best_score(self, user_id: int, pv_id: int, chart_id: int) -> Optional[Dict]:
|
||||
sql = score.select(
|
||||
and_(score.c.user == user_id, score.c.pv_id == pv_id, score.c.difficulty == chart_id)
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
return result.fetchone()
|
||||
|
||||
def get_best_scores(self, user_id: int) -> Optional[Dict]:
|
||||
sql = score.select(score.c.user == user_id)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
return result.fetchall()
|
222
titles/diva/schema/static.py
Normal file
222
titles/diva/schema/static.py
Normal file
@ -0,0 +1,222 @@
|
||||
from typing import Dict, List, Optional
|
||||
from sqlalchemy import Table, Column, UniqueConstraint, PrimaryKeyConstraint, and_
|
||||
from sqlalchemy.types import Integer, String, TIMESTAMP, Boolean, JSON, Float
|
||||
from sqlalchemy.engine.base import Connection
|
||||
from sqlalchemy.engine import Row
|
||||
from sqlalchemy.schema import ForeignKey
|
||||
from sqlalchemy.sql import func, select
|
||||
from sqlalchemy.dialects.mysql import insert
|
||||
|
||||
from core.data.schema import BaseData, metadata
|
||||
|
||||
music = Table(
|
||||
"diva_static_music",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("version", Integer, nullable=False),
|
||||
Column("songId", Integer),
|
||||
Column("chartId", Integer),
|
||||
Column("title", String(255)),
|
||||
Column("vocaloid_arranger", String(255)),
|
||||
Column("pv_illustrator", String(255)),
|
||||
Column("lyrics", String(255)),
|
||||
Column("bg_music", String(255)),
|
||||
Column("level", Float),
|
||||
Column("bpm", Integer),
|
||||
Column("date", String(255)),
|
||||
UniqueConstraint("version", "songId", "chartId", name="diva_static_music_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
)
|
||||
|
||||
quests = Table(
|
||||
"diva_static_quests",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("version", Integer, nullable=False),
|
||||
Column("questId", Integer),
|
||||
Column("name", String(255)),
|
||||
Column("quest_enable", Boolean, server_default="1"),
|
||||
Column("kind", Integer),
|
||||
Column("unknown_0", Integer),
|
||||
Column("unknown_1", Integer),
|
||||
Column("unknown_2", Integer),
|
||||
Column("quest_order", Integer),
|
||||
Column("start_datetime", String(255)),
|
||||
Column("end_datetime", String(255)),
|
||||
|
||||
UniqueConstraint("version", "questId", name="diva_static_quests_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
)
|
||||
|
||||
shop = Table(
|
||||
"diva_static_shop",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("version", Integer, nullable=False),
|
||||
Column("shopId", Integer),
|
||||
Column("name", String(255)),
|
||||
Column("type", Integer),
|
||||
Column("points", Integer),
|
||||
Column("unknown_0", Integer),
|
||||
Column("start_date", String(255)),
|
||||
Column("end_date", String(255)),
|
||||
Column("enabled", Boolean, server_default="1"),
|
||||
UniqueConstraint("version", "shopId", name="diva_static_shop_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
)
|
||||
|
||||
items = Table(
|
||||
"diva_static_items",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column("version", Integer, nullable=False),
|
||||
Column("itemId", Integer),
|
||||
Column("name", String(255)),
|
||||
Column("type", Integer),
|
||||
Column("points", Integer),
|
||||
Column("unknown_0", Integer),
|
||||
Column("start_date", String(255)),
|
||||
Column("end_date", String(255)),
|
||||
Column("enabled", Boolean, server_default="1"),
|
||||
UniqueConstraint("version", "itemId", name="diva_static_items_uk"),
|
||||
mysql_charset='utf8mb4'
|
||||
)
|
||||
|
||||
class DivaStaticData(BaseData):
|
||||
def put_quests(self, version: int, questId: int, name: str, kind: int, unknown_0: int, unknown_1: int, unknown_2: int, quest_order: int, start_datetime: str, end_datetime: str) -> Optional[int]:
|
||||
sql = insert(quests).values(
|
||||
version = version,
|
||||
questId = questId,
|
||||
name = name,
|
||||
kind = kind,
|
||||
unknown_0 = unknown_0,
|
||||
unknown_1 = unknown_1,
|
||||
unknown_2 = unknown_2,
|
||||
quest_order = quest_order,
|
||||
start_datetime = start_datetime,
|
||||
end_datetime = end_datetime
|
||||
)
|
||||
|
||||
conflict = sql.on_duplicate_key_update(
|
||||
name = name
|
||||
)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
return result.lastrowid
|
||||
|
||||
def get_enabled_quests(self, version: int) -> Optional[List[Row]]:
|
||||
sql = select(quests).where(and_(quests.c.version == version, quests.c.quest_enable == True))
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
return result.fetchall()
|
||||
|
||||
def put_shop(self, version: int, shopId: int, name: str, type: int, points: int, unknown_0: int, start_date: str, end_date: str) -> Optional[int]:
|
||||
sql = insert(shop).values(
|
||||
version = version,
|
||||
shopId = shopId,
|
||||
name = name,
|
||||
type = type,
|
||||
points = points,
|
||||
unknown_0 = unknown_0,
|
||||
start_date = start_date,
|
||||
end_date = end_date
|
||||
)
|
||||
|
||||
conflict = sql.on_duplicate_key_update(
|
||||
name = name
|
||||
)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
return result.lastrowid
|
||||
|
||||
def get_enabled_shop(self, version: int) -> Optional[List[Row]]:
|
||||
sql = select(shop).where(and_(shop.c.version == version, shop.c.enabled == True))
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
return result.fetchall()
|
||||
|
||||
def put_items(self, version: int, itemId: int, name: str, type: int, points: int, unknown_0: int, start_date: str, end_date: str) -> Optional[int]:
|
||||
sql = insert(items).values(
|
||||
version = version,
|
||||
itemId = itemId,
|
||||
name = name,
|
||||
type = type,
|
||||
points = points,
|
||||
unknown_0 = unknown_0,
|
||||
start_date = start_date,
|
||||
end_date = end_date
|
||||
)
|
||||
|
||||
conflict = sql.on_duplicate_key_update(
|
||||
name = name
|
||||
)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
return result.lastrowid
|
||||
|
||||
def get_enabled_items(self, version: int) -> Optional[List[Row]]:
|
||||
sql = select(items).where(and_(items.c.version == version, items.c.enabled == True))
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
return result.fetchall()
|
||||
|
||||
def put_music(self, version: int, song: int, chart: int, title: str, arranger: str, illustrator: str,
|
||||
lyrics: str, music_comp: str, level: float, bpm: int, date: str) -> Optional[int]:
|
||||
sql = insert(music).values(
|
||||
version = version,
|
||||
songId = song,
|
||||
chartId = chart,
|
||||
title = title,
|
||||
vocaloid_arranger = arranger,
|
||||
pv_illustrator = illustrator,
|
||||
lyrics = lyrics,
|
||||
bg_music = music_comp,
|
||||
level = level,
|
||||
bpm = bpm,
|
||||
date = date
|
||||
)
|
||||
|
||||
conflict = sql.on_duplicate_key_update(
|
||||
title = title,
|
||||
vocaloid_arranger = arranger,
|
||||
pv_illustrator = illustrator,
|
||||
lyrics = lyrics,
|
||||
bg_music = music_comp,
|
||||
level = level,
|
||||
bpm = bpm,
|
||||
date = date
|
||||
)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None: return None
|
||||
return result.lastrowid
|
||||
|
||||
def get_music(self, version: int, song_id: Optional[int] = None) -> Optional[List[Row]]:
|
||||
if song_id is None:
|
||||
sql = select(music).where(music.c.version == version)
|
||||
else:
|
||||
sql = select(music).where(and_(
|
||||
music.c.version == version,
|
||||
music.c.songId == song_id,
|
||||
))
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
return result.fetchall()
|
||||
|
||||
def get_music_chart(self, version: int, song_id: int, chart_id: int) -> Optional[List[Row]]:
|
||||
sql = select(music).where(and_(
|
||||
music.c.version == version,
|
||||
music.c.songId == song_id,
|
||||
music.c.chartId == chart_id
|
||||
))
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None: return None
|
||||
return result.fetchone()
|
Reference in New Issue
Block a user