1
0
mirror of synced 2024-11-12 00:40:50 +01:00

add back games, conform them to new title dispatch

This commit is contained in:
Hay1tsme 2023-02-17 01:02:21 -05:00
parent f18e939dd0
commit 7e3396a7ff
214 changed files with 15949 additions and 21 deletions

View File

@ -1,4 +1,4 @@
from twisted.web import resource
from typing import Dict, Any
import logging, coloredlogs
from logging.handlers import TimedRotatingFileHandler
from twisted.web.http import Request
@ -13,6 +13,7 @@ class TitleServlet():
self.config = core_cfg
self.config_folder = cfg_folder
self.data = Data(core_cfg)
self.title_registry: Dict[str, Any] = {}
self.logger = logging.getLogger("title")
if not hasattr(self.logger, "initialized"):
@ -35,8 +36,31 @@ class TitleServlet():
if "game_registry" not in globals():
globals()["game_registry"] = Utils.get_all_titles()
def handle_GET(self, request: Request):
pass
for folder, mod in globals()["game_registry"].items():
if hasattr(mod, "game_codes") and hasattr(mod, "index"):
handler_cls = mod.index(self.config, self.config_folder)
if hasattr(handler_cls, "setup"):
handler_cls.setup()
def handle_POST(self, request: Request):
pass
for code in mod.game_codes:
self.title_registry[code] = handler_cls
else:
self.logger.error(f"{folder} missing game_code or index in __init__.py")
self.logger.info(f"Serving {len(globals()['game_registry'])} game codes")
def render_GET(self, request: Request, endpoints: dict) -> bytes:
print(endpoints)
def render_POST(self, request: Request, endpoints: dict) -> bytes:
print(endpoints)
code = endpoints["game"]
if code not in self.title_registry:
self.logger.warn(f"Unknown game code {code}")
index = self.title_registry[code]
if not hasattr(index, "render_POST"):
self.logger.warn(f"{code} does not dispatch on POST")
return index.render_POST(request, endpoints["version"], endpoints["endpoint"])

View File

@ -18,4 +18,5 @@ class Utils:
except ImportError as e:
print(f"{dir} - {e}")
raise
return ret

View File

@ -1,6 +1,47 @@
import yaml
import argparse
from core.config import CoreConfig
from core.data import Data
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="ARTEMiS main entry point")
parser.add_argument("--config", "-c", type=str, default="config", help="Configuration folder")
if __name__=='__main__':
parser = argparse.ArgumentParser(description="Database utilities")
parser.add_argument("--config", "-c", type=str, help="Config folder to use", default="config")
parser.add_argument("--version", "-v", type=str, help="Version of the database to upgrade/rollback to")
parser.add_argument("--game", "-g", type=str, help="Game code of the game who's schema will be updated/rolled back. Ex. SDFE")
parser.add_argument("action", type=str, help="DB Action, create, recreate, upgrade, or rollback")
args = parser.parse_args()
cfg = CoreConfig()
cfg.update(yaml.safe_load(open(f"{args.config}/core.yaml")))
data = Data(cfg)
if args.action == "create":
data.create_database()
elif args.action == "recreate":
data.recreate_database()
elif args.action == "upgrade" or args.action == "rollback":
if args.version is None:
print("Must set game and version to migrate to")
exit(0)
if args.game is None:
print("No game set, upgrading core schema")
data.migrate_database("CORE", int(args.version))
else:
data.migrate_database(args.game, int(args.version), args.action)
elif args.action == "migrate":
print("Migrating from old schema to new schema")
data.restore_from_old_schema()
elif args.action == "dump":
print("Dumping old schema to migrate to new schema")
data.dump_db()
elif args.action == "generate":
pass
data.logger.info("Done")

View File

@ -0,0 +1,6 @@
server:
enable: True
loglevel: "info"
crypto:
encrypted_only: False

9
example_config/cxb.yaml Normal file
View File

@ -0,0 +1,9 @@
server:
enable: True
loglevel: "info"
hostname: "localhost"
ssl_enable: False
port: 8082
port_secure: 443
ssl_cert: "cert/title.crt"
ssl_key: "cert/title.key"

4
example_config/diva.yaml Normal file
View File

@ -0,0 +1,4 @@
server:
enable: True
loglevel: "info"

3
example_config/mai2.yaml Normal file
View File

@ -0,0 +1,3 @@
server:
enable: True
loglevel: "info"

View File

@ -0,0 +1,60 @@
# Allnet
server {
listen 80;
server_name naominet.jp;
location / {
proxy_pass http://localhost:8000/;
}
}
# Non-SSL titles
server {
listen 80;
server_name your.hostname.here;
location / {
proxy_pass http://localhost:8080/;
}
}
# SSL titles
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name your.hostname.here;
ssl_certificate /path/to/cert/title.crt;
ssl_certificate_key /path/to/cert/title.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers "ALL:@SECLEVEL=0";
ssl_prefer_server_ciphers off;
location / {
proxy_pass http://localhost:8080/;
}
}
# Billing
server {
listen 8443 ssl;
server_name ib.naominet.jp;
ssl_certificate /path/to/cert/server.pem;
ssl_certificate_key /path/to/cert/server.key;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers "ALL:@SECLEVEL=1";
ssl_prefer_server_ciphers off;
location / {
proxy_pass http://localhost:8444/;
}
}

View File

@ -0,0 +1,3 @@
server:
enable: True
loglevel: "info"

32
example_config/wacca.yaml Normal file
View File

@ -0,0 +1,32 @@
server:
enable: True
loglevel: "info"
mods:
always_vip: True
infinite_tickets: True
infinite_wp: True
gates:
enabled_gates:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 21
- 22

View File

@ -4,9 +4,82 @@ import yaml
from os import path, mkdir, access, W_OK
from core import *
from twisted.web import server
from twisted.web import server, resource
from twisted.internet import reactor, endpoints
from txroutes import Dispatcher
from twisted.web.http import Request
from routes import Mapper
class HttpDispatcher(resource.Resource):
def __init__(self, cfg: CoreConfig, config_dir: str):
super().__init__()
self.config = cfg
self.isLeaf = True
self.map_get = Mapper()
self.map_post = Mapper()
self.allnet = AllnetServlet(cfg, config_dir)
self.title = TitleServlet(cfg, config_dir)
self.map_post.connect('allnet_poweron', '/sys/servlet/PowerOn', controller="allnet", action='handle_poweron', conditions=dict(method=['POST']))
self.map_post.connect('allnet_downloadorder', '/sys/servlet/DownloadOrder', controller="allnet", action='handle_dlorder', conditions=dict(method=['POST']))
self.map_post.connect('allnet_billing', '/request', controller="allnet", action='handle_billing_request', conditions=dict(method=['POST']))
self.map_get.connect("title_get", "/{game}/{version}/{endpoint:.*?}", controller="title", action="render_GET", requirements=dict(game=R"S..."))
self.map_post.connect("title_post", "/{game}/{version}/{endpoint:.*?}", controller="title", action="render_POST", requirements=dict(game=R"S..."))
def render_POST(self, request: Request) -> bytes:
test = self.map_get.match(request.uri.decode())
if test is None:
return b""
controller = getattr(self, test["controller"], None)
if controller is None:
return b""
handler = getattr(controller, test["action"], None)
if handler is None:
return b""
url_vars = test
url_vars.pop("controller")
url_vars.pop("action")
if len(url_vars) > 0:
ret = handler(request, url_vars)
else:
ret = handler(request)
if type(ret) == str:
return ret.encode()
elif type(ret) == bytes:
return ret
else:
return b""
def render_POST(self, request: Request) -> bytes:
test = self.map_post.match(request.uri.decode())
if test is None:
return b""
controller = getattr(self, test["controller"], None)
if controller is None:
return b""
handler = getattr(controller, test["action"], None)
if handler is None:
return b""
url_vars = test
url_vars.pop("controller")
url_vars.pop("action")
ret = handler(request, url_vars)
if type(ret) == str:
return ret.encode()
elif type(ret) == bytes:
return ret
else:
return b""
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="ARTEMiS main entry point")
@ -42,15 +115,7 @@ if __name__ == "__main__":
billing_server_str = f"ssl:{cfg.billing.port}:interface={cfg.server.listen_address}"\
f":privateKey={cfg.billing.ssl_key}:certKey={cfg.billing.ssl_cert}"
allnet_cls = AllnetServlet(cfg, args.config)
title_cls = TitleServlet(cfg, args.config)
dispatcher = Dispatcher()
dispatcher.connect('allnet_poweron', '/sys/servlet/PowerOn', allnet_cls, action='handle_poweron', conditions=dict(method=['POST']))
dispatcher.connect('allnet_downloadorder', '/sys/servlet/DownloadOrder', allnet_cls, action='handle_dlorder', conditions=dict(method=['POST']))
dispatcher.connect('allnet_billing', '/request', allnet_cls, action='handle_billing_request', conditions=dict(method=['POST']))
dispatcher.connect("title_get", "/{game}/{version}/{endpoint}", title_cls, action="handle_GET", conditions=dict(method=['GET']))
dispatcher.connect("title_post", "/{game}/{version}/{endpoint}", title_cls, action="handle_POST", conditions=dict(method=['POST']))
dispatcher = HttpDispatcher(cfg, args.config)
endpoints.serverFromString(reactor, allnet_server_str).listen(server.Site(dispatcher))
endpoints.serverFromString(reactor, adb_server_str).listen(AimedbFactory(cfg))

129
read.py Normal file
View File

@ -0,0 +1,129 @@
# vim: set fileencoding=utf-8
import argparse
import re
import os
import yaml
import importlib
import logging, coloredlogs
from logging.handlers import TimedRotatingFileHandler
from typing import List, Optional
from core import CoreConfig
from core.utils import Utils
class BaseReader():
def __init__(self, config: CoreConfig, version: int, bin_dir: Optional[str], opt_dir: Optional[str], extra: Optional[str]) -> None:
self.logger = logging.getLogger("reader")
self.config = config
self.bin_dir = bin_dir
self.opt_dir = opt_dir
self.version = version
self.extra = extra
def get_data_directories(self, directory: str) -> List[str]:
ret: List[str] = []
for root, dirs, files in os.walk(directory):
for dir in dirs:
if re.fullmatch("[A-Z0-9]{4,4}", dir) is not None:
ret.append(f"{root}/{dir}")
return ret
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Import Game Information')
parser.add_argument(
'--series',
action='store',
type=str,
required=True,
help='The game series we are importing.',
)
parser.add_argument(
'--version',
dest='version',
action='store',
type=int,
required=True,
help='The game version we are importing.',
)
parser.add_argument(
'--binfolder',
dest='bin',
action='store',
type=str,
help='Folder containing A000 base data',
)
parser.add_argument(
'--optfolder',
dest='opt',
action='store',
type=str,
help='Folder containing Option data folders',
)
parser.add_argument(
"--config",
type=str,
default="config",
help="Folder containing the core configuration for importing to DB. Defaults to 'config'.",
)
parser.add_argument(
"--extra",
type=str,
help="Any extra data that a reader might require.",
)
# Parse args, validate invariants.
args = parser.parse_args()
config = CoreConfig()
config.update(yaml.safe_load(open(f"{args.config}/core.yaml")))
log_fmt_str = "[%(asctime)s] Reader | %(levelname)s | %(message)s"
log_fmt = logging.Formatter(log_fmt_str)
logger = logging.getLogger("reader")
fileHandler = TimedRotatingFileHandler("{0}/{1}.log".format(config.server.logs, "reader"), when="d", backupCount=10)
fileHandler.setFormatter(log_fmt)
consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(log_fmt)
logger.addHandler(fileHandler)
logger.addHandler(consoleHandler)
logger.setLevel(logging.INFO)
coloredlogs.install(level=logging.INFO, logger=logger, fmt=log_fmt_str)
if args.series is None or args.version is None:
logger.error("Game or version not specified")
parser.print_help()
exit(1)
if args.bin is None and args.opt is None:
logger.error("Must specify either bin or opt directory")
parser.print_help()
exit(1)
if args.bin is not None and (args.bin.endswith("\\") or args.bin.endswith("/")):
bin_arg = args.bin[:-1]
else:
bin_arg = args.bin
if args.opt is not None and (args.opt.endswith("\\") or args.opt.endswith("/")):
opt_arg = args.opt[:-1]
else:
opt_arg = args.opt
logger.info("Starting importer...")
titles = Utils.get_all_titles()
for dir, mod in titles.items():
if args.series in mod.game_codes:
handler = mod.reader(config, args.version, bin_arg, opt_arg, args.extra)
handler.read()
logger.info("Done")

Binary file not shown.

Binary file not shown.

18
titles/chuni/__init__.py Normal file
View File

@ -0,0 +1,18 @@
from titles.chuni.index import ChuniServlet
from titles.chuni.const import ChuniConstants
from titles.chuni.database import ChuniData
from titles.chuni.read import ChuniReader
index = ChuniServlet
database = ChuniData
reader = ChuniReader
use_default_title = True
include_protocol = True
title_secure = False
game_codes = [ChuniConstants.GAME_CODE, ChuniConstants.GAME_CODE_NEW]
trailing_slash = True
use_default_host = False
host = ""
current_schema_version = 1

16
titles/chuni/air.py Normal file
View File

@ -0,0 +1,16 @@
from typing import Dict
from core.config import CoreConfig
from titles.chuni.base import ChuniBase
from titles.chuni.const import ChuniConstants
from titles.chuni.config import ChuniConfig
class ChuniAir(ChuniBase):
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_AIR
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.10.00"
return ret

16
titles/chuni/airplus.py Normal file
View File

@ -0,0 +1,16 @@
from typing import Dict
from core.config import CoreConfig
from titles.chuni.base import ChuniBase
from titles.chuni.const import ChuniConstants
from titles.chuni.config import ChuniConfig
class ChuniAirPlus(ChuniBase):
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_AIR_PLUS
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.15.00"
return ret

18
titles/chuni/amazon.py Normal file
View File

@ -0,0 +1,18 @@
from datetime import datetime, timedelta
from typing import Dict, Any
import pytz
from core.config import CoreConfig
from titles.chuni.base import ChuniBase
from titles.chuni.const import ChuniConstants
from titles.chuni.config import ChuniConfig
class ChuniAmazon(ChuniBase):
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_AMAZON
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.30.00"
return ret

View File

@ -0,0 +1,18 @@
from datetime import datetime, timedelta
from typing import Dict, Any
import pytz
from core.config import CoreConfig
from titles.chuni.base import ChuniBase
from titles.chuni.const import ChuniConstants
from titles.chuni.config import ChuniConfig
class ChuniAmazonPlus(ChuniBase):
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_AMAZON_PLUS
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.35.00"
return ret

572
titles/chuni/base.py Normal file
View File

@ -0,0 +1,572 @@
import logging
import json
from datetime import datetime, timedelta
from time import strftime
import pytz
from typing import Dict, Any
from core.config import CoreConfig
from titles.chuni.const import ChuniConstants
from titles.chuni.database import ChuniData
from titles.chuni.config import ChuniConfig
class ChuniBase():
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
self.core_cfg = core_cfg
self.game_cfg = game_cfg
self.data = ChuniData(core_cfg)
self.date_time_format = "%Y-%m-%d %H:%M:%S"
self.logger = logging.getLogger("chuni")
self.game = ChuniConstants.GAME_CODE
self.version = ChuniConstants.VER_CHUNITHM
def handle_game_login_api_request(self, data: Dict) -> Dict:
#self.data.base.log_event("chuni", "login", logging.INFO, {"version": self.version, "user": data["userId"]})
return { "returnCode": 1 }
def handle_game_logout_api_request(self, data: Dict) -> Dict:
#self.data.base.log_event("chuni", "logout", logging.INFO, {"version": self.version, "user": data["userId"]})
return { "returnCode": 1 }
def handle_get_game_charge_api_request(self, data: Dict) -> Dict:
game_charge_list = self.data.static.get_enabled_charges(self.version)
charges = []
for x in range(len(game_charge_list)):
charges.append({
"orderId": x,
"chargeId": game_charge_list[x]["chargeId"],
"price": 1,
"startDate": "2017-12-05 07:00:00.0",
"endDate": "2099-12-31 00:00:00.0",
"salePrice": 1,
"saleStartDate": "2017-12-05 07:00:00.0",
"saleEndDate": "2099-12-31 00:00:00.0"
})
return {
"length": len(charges),
"gameChargeList": charges
}
def handle_get_game_event_api_request(self, data: Dict) -> Dict:
game_events = self.data.static.get_enabled_events(self.version)
event_list = []
for evt_row in game_events:
tmp = {}
tmp["id"] = evt_row["eventId"]
tmp["type"] = evt_row["type"]
tmp["startDate"] = "2017-12-05 07:00:00.0"
tmp["endDate"] = "2099-12-31 00:00:00.0"
event_list.append(tmp)
return {
"type": data["type"],
"length": len(event_list),
"gameEventList": event_list
}
def handle_get_game_idlist_api_request(self, data: Dict) -> Dict:
return { "type": data["type"], "length": 0, "gameIdlistList": [] }
def handle_get_game_message_api_request(self, data: Dict) -> Dict:
return { "type": data["type"], "length": "0", "gameMessageList": [] }
def handle_get_game_ranking_api_request(self, data: Dict) -> Dict:
return { "type": data["type"], "gameRankingList": [] }
def handle_get_game_sale_api_request(self, data: Dict) -> Dict:
return { "type": data["type"], "length": 0, "gameSaleList": [] }
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
reboot_start = datetime.strftime(datetime.now() - timedelta(hours=4), self.date_time_format)
reboot_end = datetime.strftime(datetime.now() - timedelta(hours=3), self.date_time_format)
return {
"gameSetting": {
"dataVersion": "1.00.00",
"isMaintenance": "false",
"requestInterval": 10,
"rebootStartTime": reboot_start,
"rebootEndTime": reboot_end,
"isBackgroundDistribute": "false",
"maxCountCharacter": 300,
"maxCountItem": 300,
"maxCountMusic": 300,
},
"isDumpUpload": "false",
"isAou": "false",
}
def handle_get_user_activity_api_request(self, data: Dict) -> Dict:
user_activity_list = self.data.profile.get_profile_activity(data["userId"], data["kind"])
activity_list = []
for activity in user_activity_list:
tmp = activity._asdict()
tmp.pop("user")
tmp["id"] = tmp["activityId"]
tmp.pop("activityId")
activity_list.append(tmp)
return {
"userId": data["userId"],
"length": len(activity_list),
"kind": data["kind"],
"userActivityList": activity_list
}
def handle_get_user_character_api_request(self, data: Dict) -> Dict:
characters = self.data.item.get_characters(data["userId"])
if characters is None: return {}
next_idx = -1
characterList = []
for x in range(int(data["nextIndex"]), len(characters)):
tmp = characters[x]._asdict()
tmp.pop("user")
tmp.pop("id")
characterList.append(tmp)
if len(characterList) >= int(data["maxCount"]):
break
if len(characterList) >= int(data["maxCount"]) and len(characters) > int(data["maxCount"]) + int(data["nextIndex"]):
next_idx = int(data["maxCount"]) + int(data["nextIndex"]) + 1
return {
"userId": data["userId"],
"length": len(characterList),
"nextIndex": next_idx,
"userCharacterList": characterList
}
def handle_get_user_charge_api_request(self, data: Dict) -> Dict:
user_charge_list = self.data.profile.get_profile_charge(data["userId"])
charge_list = []
for charge in user_charge_list:
tmp = charge._asdict()
tmp.pop("id")
tmp.pop("user")
charge_list.append(tmp)
return {
"userId": data["userId"],
"length": len(charge_list),
"userChargeList": charge_list
}
def handle_get_user_course_api_request(self, data: Dict) -> Dict:
user_course_list = self.data.score.get_courses(data["userId"])
if user_course_list is None:
return {
"userId": data["userId"],
"length": 0,
"nextIndex": -1,
"userCourseList": []
}
course_list = []
next_idx = int(data["nextIndex"])
max_ct = int(data["maxCount"])
for x in range(next_idx, len(user_course_list)):
tmp = user_course_list[x]._asdict()
tmp.pop("user")
tmp.pop("id")
course_list.append(tmp)
if len(user_course_list) >= max_ct:
break
if len(user_course_list) >= max_ct:
next_idx = next_idx + max_ct
else:
next_idx = -1
return {
"userId": data["userId"],
"length": len(course_list),
"nextIndex": next_idx,
"userCourseList": course_list
}
def handle_get_user_data_api_request(self, data: Dict) -> Dict:
p = self.data.profile.get_profile_data(data["userId"], self.version)
if p is None: return {}
profile = p._asdict()
profile.pop("id")
profile.pop("user")
profile.pop("version")
return {
"userId": data["userId"],
"userData": profile
}
def handle_get_user_data_ex_api_request(self, data: Dict) -> Dict:
p = self.data.profile.get_profile_data_ex(data["userId"], self.version)
if p is None: return {}
profile = p._asdict()
profile.pop("id")
profile.pop("user")
profile.pop("version")
return {
"userId": data["userId"],
"userDataEx": profile
}
def handle_get_user_duel_api_request(self, data: Dict) -> Dict:
user_duel_list = self.data.item.get_duels(data["userId"])
if user_duel_list is None: return {}
duel_list = []
for duel in user_duel_list:
tmp = duel._asdict()
tmp.pop("id")
tmp.pop("user")
duel_list.append(tmp)
return {
"userId": data["userId"],
"length": len(duel_list),
"userDuelList": duel_list
}
def handle_get_user_favorite_item_api_request(self, data: Dict) -> Dict:
return {
"userId": data["userId"],
"length": 0,
"kind": data["kind"],
"nextIndex": -1,
"userFavoriteItemList": []
}
def handle_get_user_favorite_music_api_request(self, data: Dict) -> Dict:
"""
This is handled via the webui, which we don't have right now
"""
return {
"userId": data["userId"],
"length": 0,
"userFavoriteMusicList": []
}
def handle_get_user_item_api_request(self, data: Dict) -> Dict:
kind = int(int(data["nextIndex"]) / 10000000000)
next_idx = int(int(data["nextIndex"]) % 10000000000)
user_item_list = self.data.item.get_items(data["userId"], kind)
if user_item_list is None or len(user_item_list) == 0:
return {"userId": data["userId"], "nextIndex": -1, "itemKind": kind, "userItemList": []}
items: list[Dict[str, Any]] = []
for i in range(next_idx, len(user_item_list)):
tmp = user_item_list[i]._asdict()
tmp.pop("user")
tmp.pop("id")
items.append(tmp)
if len(items) >= int(data["maxCount"]):
break
xout = kind * 10000000000 + next_idx + len(items)
if len(items) < int(data["maxCount"]): nextIndex = 0
else: nextIndex = xout
return {"userId": data["userId"], "nextIndex": nextIndex, "itemKind": kind, "length": len(items), "userItemList": items}
def handle_get_user_login_bonus_api_request(self, data: Dict) -> Dict:
"""
Unsure how to get this to trigger...
"""
return {
"userId": data["userId"],
"length": 2,
"userLoginBonusList": [
{
"presetId": '10',
"bonusCount": '0',
"lastUpdateDate": "1970-01-01 09:00:00",
"isWatched": "true"
},
{
"presetId": '20',
"bonusCount": '0',
"lastUpdateDate": "1970-01-01 09:00:00",
"isWatched": "true"
},
]
}
def handle_get_user_map_api_request(self, data: Dict) -> Dict:
user_map_list = self.data.item.get_maps(data["userId"])
if user_map_list is None: return {}
map_list = []
for map in user_map_list:
tmp = map._asdict()
tmp.pop("id")
tmp.pop("user")
map_list.append(tmp)
return {
"userId": data["userId"],
"length": len(map_list),
"userMapList": map_list
}
def handle_get_user_music_api_request(self, data: Dict) -> Dict:
music_detail = self.data.score.get_scores(data["userId"])
if music_detail is None:
return {
"userId": data["userId"],
"length": 0,
"nextIndex": -1,
"userMusicList": [] #240
}
song_list = []
next_idx = int(data["nextIndex"])
max_ct = int(data["maxCount"])
for x in range(next_idx, len(music_detail)):
found = False
tmp = music_detail[x]._asdict()
tmp.pop("user")
tmp.pop("id")
for song in song_list:
if song["userMusicDetailList"][0]["musicId"] == tmp["musicId"]:
found = True
song["userMusicDetailList"].append(tmp)
song["length"] = len(song["userMusicDetailList"])
if not found:
song_list.append({
"length": 1,
"userMusicDetailList": [tmp]
})
if len(song_list) >= max_ct:
break
if len(song_list) >= max_ct:
next_idx += max_ct
else:
next_idx = 0
return {
"userId": data["userId"],
"length": len(song_list),
"nextIndex": next_idx,
"userMusicList": song_list #240
}
def handle_get_user_option_api_request(self, data: Dict) -> Dict:
p = self.data.profile.get_profile_option(data["userId"])
option = p._asdict()
option.pop("id")
option.pop("user")
return {
"userId": data["userId"],
"userGameOption": option
}
def handle_get_user_option_ex_api_request(self, data: Dict) -> Dict:
p = self.data.profile.get_profile_option_ex(data["userId"])
option = p._asdict()
option.pop("id")
option.pop("user")
return {
"userId": data["userId"],
"userGameOptionEx": option
}
def read_wtf8(self, src):
return bytes([ord(c) for c in src]).decode("utf-8")
def handle_get_user_preview_api_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile_preview(data["userId"], self.version)
if profile is None: return None
profile_character = self.data.item.get_character(data["userId"], profile["characterId"])
if profile_character is None:
chara = {}
else:
chara = profile_character._asdict()
chara.pop("id")
chara.pop("user")
return {
"userId": data["userId"],
# Current Login State
"isLogin": False,
"lastLoginDate": profile["lastPlayDate"],
# User Profile
"userName": profile["userName"],
"reincarnationNum": profile["reincarnationNum"],
"level": profile["level"],
"exp": profile["exp"],
"playerRating": profile["playerRating"],
"lastGameId": profile["lastGameId"],
"lastRomVersion": profile["lastRomVersion"],
"lastDataVersion": profile["lastDataVersion"],
"lastPlayDate": profile["lastPlayDate"],
"trophyId": profile["trophyId"],
"nameplateId": profile["nameplateId"],
# Current Selected Character
"userCharacter": chara,
# User Game Options
"playerLevel": profile["playerLevel"],
"rating": profile["rating"],
"headphone": profile["headphone"],
"chargeState": "1",
"userNameEx": profile["userName"],
}
def handle_get_user_recent_rating_api_request(self, data: Dict) -> Dict:
recet_rating_list = self.data.profile.get_profile_recent_rating(data["userId"])
if recet_rating_list is None:
return {
"userId": data["userId"],
"length": 0,
"userRecentRatingList": [],
}
return {
"userId": data["userId"],
"length": len(recet_rating_list["recentRating"]),
"userRecentRatingList": recet_rating_list["recentRating"],
}
def handle_get_user_region_api_request(self, data: Dict) -> Dict:
# TODO: Region
return {
"userId": data["userId"],
"length": 0,
"userRegionList": [],
}
def handle_get_user_team_api_request(self, data: Dict) -> Dict:
# TODO: Team
return {
"userId": data["userId"],
"teamId": 0
}
def handle_get_team_course_setting_api_request(self, data: Dict) -> Dict:
return {
"userId": data["userId"],
"length": 0,
"nextIndex": 0,
"teamCourseSettingList": [],
}
def handle_get_team_course_rule_api_request(self, data: Dict) -> Dict:
return {
"userId": data["userId"],
"length": 0,
"nextIndex": 0,
"teamCourseRuleList": [],
}
def handle_upsert_user_all_api_request(self, data: Dict) -> Dict:
upsert = data["upsertUserAll"]
user_id = data["userId"]
if "userData" in upsert:
try:
upsert["userData"][0]["userName"] = self.read_wtf8(upsert["userData"][0]["userName"])
except: pass
self.data.profile.put_profile_data(user_id, self.version, upsert["userData"][0])
if "userDataEx" in upsert:
self.data.profile.put_profile_data_ex(user_id, self.version, upsert["userDataEx"][0])
if "userGameOption" in upsert:
self.data.profile.put_profile_option(user_id, upsert["userGameOption"][0])
if "userGameOptionEx" in upsert:
self.data.profile.put_profile_option_ex(user_id, upsert["userGameOptionEx"][0])
if "userRecentRatingList" in upsert:
self.data.profile.put_profile_recent_rating(user_id, upsert["userRecentRatingList"])
if "userCharacterList" in upsert:
for character in upsert["userCharacterList"]:
self.data.item.put_character(user_id, character)
if "userMapList" in upsert:
for map in upsert["userMapList"]:
self.data.item.put_map(user_id, map)
if "userCourseList" in upsert:
for course in upsert["userCourseList"]:
self.data.score.put_course(user_id, course)
if "userDuelList" in upsert:
for duel in upsert["userDuelList"]:
self.data.item.put_duel(user_id, duel)
if "userItemList" in upsert:
for item in upsert["userItemList"]:
self.data.item.put_item(user_id, item)
if "userActivityList" in upsert:
for activity in upsert["userActivityList"]:
self.data.profile.put_profile_activity(user_id, activity)
if "userChargeList" in upsert:
for charge in upsert["userChargeList"]:
self.data.profile.put_profile_charge(user_id, charge)
if "userMusicDetailList" in upsert:
for song in upsert["userMusicDetailList"]:
self.data.score.put_score(user_id, song)
if "userPlaylogList" in upsert:
for playlog in upsert["userPlaylogList"]:
self.data.score.put_playlog(user_id, playlog)
if "userTeamPoint" in upsert:
# TODO: team stuff
pass
if "userMapAreaList" in upsert:
for map_area in upsert["userMapAreaList"]:
self.data.item.put_map_area(user_id, map_area)
if "userOverPowerList" in upsert:
for overpower in upsert["userOverPowerList"]:
self.data.profile.put_profile_overpower(user_id, overpower)
if "userEmoneyList" in upsert:
for emoney in upsert["userEmoneyList"]:
self.data.profile.put_profile_emoney(user_id, emoney)
return { "returnCode": "1" }
def handle_upsert_user_chargelog_api_request(self, data: Dict) -> Dict:
return { "returnCode": "1" }
def handle_upsert_client_bookkeeping_api_request(self, data: Dict) -> Dict:
return { "returnCode": "1" }
def handle_upsert_client_develop_api_request(self, data: Dict) -> Dict:
return { "returnCode": "1" }
def handle_upsert_client_error_api_request(self, data: Dict) -> Dict:
return { "returnCode": "1" }
def handle_upsert_client_setting_api_request(self, data: Dict) -> Dict:
return { "returnCode": "1" }
def handle_upsert_client_testmode_api_request(self, data: Dict) -> Dict:
return { "returnCode": "1" }

36
titles/chuni/config.py Normal file
View File

@ -0,0 +1,36 @@
from core.config import CoreConfig
from typing import Dict
class ChuniServerConfig():
def __init__(self, parent_config: "ChuniConfig") -> None:
self.__config = parent_config
@property
def enable(self) -> bool:
return CoreConfig.get_config_field(self.__config, 'chuni', 'server', 'enable', default=True)
@property
def loglevel(self) -> int:
return CoreConfig.str_to_loglevel(CoreConfig.get_config_field(self.__config, 'chuni', 'server', 'loglevel', default="info"))
class ChuniCryptoConfig():
def __init__(self, parent_config: "ChuniConfig") -> None:
self.__config = parent_config
@property
def keys(self) -> Dict:
"""
in the form of:
internal_version: [key, iv]
all values are hex strings
"""
return CoreConfig.get_config_field(self.__config, 'chuni', 'crypto', 'keys', default={})
@property
def encrypted_only(self) -> bool:
return CoreConfig.get_config_field(self.__config, 'chuni', 'crypto', 'encrypted_only', default=False)
class ChuniConfig(dict):
def __init__(self) -> None:
self.server = ChuniServerConfig(self)
self.crypto = ChuniCryptoConfig(self)

24
titles/chuni/const.py Normal file
View File

@ -0,0 +1,24 @@
class ChuniConstants():
GAME_CODE = "SDBT"
GAME_CODE_NEW = "SDHD"
VER_CHUNITHM = 0
VER_CHUNITHM_PLUS = 1
VER_CHUNITHM_AIR = 2
VER_CHUNITHM_AIR_PLUS = 3
VER_CHUNITHM_STAR = 4
VER_CHUNITHM_STAR_PLUS = 5
VER_CHUNITHM_AMAZON = 6
VER_CHUNITHM_AMAZON_PLUS = 7
VER_CHUNITHM_CRYSTAL = 8
VER_CHUNITHM_CRYSTAL_PLUS = 9
VER_CHUNITHM_PARADISE = 10
VER_CHUNITHM_NEW = 11
VER_CHUNITHM_NEW_PLUS = 12
VERSION_NAMES = ["Chunithm", "Chunithm+", "Chunithm Air", "Chunithm Air+", "Chunithm Star", "Chunithm Star+", "Chunithm Amazon",
"Chunithm Amazon+", "Chunithm Crystal", "Chunithm Crystal+", "Chunithm Paradise", "Chunithm New!!", "Chunithm New!!+"]
@classmethod
def game_ver_to_string(cls, ver: int):
return cls.VERSION_NAMES[ver]

18
titles/chuni/crystal.py Normal file
View File

@ -0,0 +1,18 @@
from datetime import datetime, timedelta
from typing import Dict, Any
import pytz
from core.config import CoreConfig
from titles.chuni.base import ChuniBase
from titles.chuni.const import ChuniConstants
from titles.chuni.config import ChuniConfig
class ChuniCrystal(ChuniBase):
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_CRYSTAL
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.40.00"
return ret

View File

@ -0,0 +1,18 @@
from datetime import datetime, timedelta
from typing import Dict, Any
import pytz
from core.config import CoreConfig
from titles.chuni.base import ChuniBase
from titles.chuni.const import ChuniConstants
from titles.chuni.config import ChuniConfig
class ChuniCrystalPlus(ChuniBase):
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_CRYSTAL_PLUS
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.45.00"
return ret

12
titles/chuni/database.py Normal file
View File

@ -0,0 +1,12 @@
from core.data import Data
from core.config import CoreConfig
from titles.chuni.schema import *
class ChuniData(Data):
def __init__(self, cfg: CoreConfig) -> None:
super().__init__(cfg)
self.item = ChuniItemData(cfg, self.session)
self.profile = ChuniProfileData(cfg, self.session)
self.score = ChuniScoreData(cfg, self.session)
self.static = ChuniStaticData(cfg, self.session)

172
titles/chuni/index.py Normal file
View File

@ -0,0 +1,172 @@
from twisted.web.http import Request
import logging, coloredlogs
from logging.handlers import TimedRotatingFileHandler
import zlib
import yaml
import json
import inflection
import string
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from core import CoreConfig
from titles.chuni.config import ChuniConfig
from titles.chuni.const import ChuniConstants
from titles.chuni.base import ChuniBase
from titles.chuni.plus import ChuniPlus
from titles.chuni.air import ChuniAir
from titles.chuni.airplus import ChuniAirPlus
from titles.chuni.star import ChuniStar
from titles.chuni.starplus import ChuniStarPlus
from titles.chuni.amazon import ChuniAmazon
from titles.chuni.amazonplus import ChuniAmazonPlus
from titles.chuni.crystal import ChuniCrystal
from titles.chuni.crystalplus import ChuniCrystalPlus
from titles.chuni.paradise import ChuniParadise
from titles.chuni.new import ChuniNew
from titles.chuni.newplus import ChuniNewPlus
class ChuniServlet():
def __init__(self, core_cfg: CoreConfig, cfg_dir: str) -> None:
self.core_cfg = core_cfg
self.game_cfg = ChuniConfig()
self.game_cfg.update(yaml.safe_load(open(f"{cfg_dir}/chuni.yaml")))
self.versions = [
ChuniBase(core_cfg, self.game_cfg),
ChuniPlus(core_cfg, self.game_cfg),
ChuniAir(core_cfg, self.game_cfg),
ChuniAirPlus(core_cfg, self.game_cfg),
ChuniStar(core_cfg, self.game_cfg),
ChuniStarPlus(core_cfg, self.game_cfg),
ChuniAmazon(core_cfg, self.game_cfg),
ChuniAmazonPlus(core_cfg, self.game_cfg),
ChuniCrystal(core_cfg, self.game_cfg),
ChuniCrystalPlus(core_cfg, self.game_cfg),
ChuniParadise(core_cfg, self.game_cfg),
ChuniNew(core_cfg, self.game_cfg),
ChuniNewPlus(core_cfg, self.game_cfg),
]
self.logger = logging.getLogger("chuni")
if not hasattr(self.logger, "inited"):
log_fmt_str = "[%(asctime)s] Chunithm | %(levelname)s | %(message)s"
log_fmt = logging.Formatter(log_fmt_str)
fileHandler = TimedRotatingFileHandler("{0}/{1}.log".format(self.core_cfg.server.log_dir, "chuni"), 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)
self.logger.inited = True
def render_POST(self, request: Request, version: int, url_path: str) -> bytes:
req_raw = request.content.getvalue()
url_split = url_path.split("/")
encrtped = False
internal_ver = 0
endpoint = url_split[len(url_split) - 1]
if version < 105: # 1.0
internal_ver = ChuniConstants.VER_CHUNITHM
elif version >= 105 and version < 110: # Plus
internal_ver = ChuniConstants.VER_CHUNITHM_PLUS
elif version >= 110 and version < 115: # Air
internal_ver = ChuniConstants.VER_CHUNITHM_AIR
elif version >= 115 and version < 120: # Air Plus
internal_ver = ChuniConstants.VER_CHUNITHM_AIR_PLUS
elif version >= 120 and version < 125: # Star
internal_ver = ChuniConstants.VER_CHUNITHM_STAR
elif version >= 125 and version < 130: # Star Plus
internal_ver = ChuniConstants.VER_CHUNITHM_STAR_PLUS
elif version >= 130 and version < 135: # Amazon
internal_ver = ChuniConstants.VER_CHUNITHM_AMAZON
elif version >= 135 and version < 140: # Amazon Plus
internal_ver = ChuniConstants.VER_CHUNITHM_AMAZON_PLUS
elif version >= 140 and version < 145: # Crystal
internal_ver = ChuniConstants.VER_CHUNITHM_CRYSTAL
elif version >= 145 and version < 150: # Crystal Plus
internal_ver = ChuniConstants.VER_CHUNITHM_CRYSTAL_PLUS
elif version >= 150 and version < 200: # Paradise
internal_ver = ChuniConstants.VER_CHUNITHM_PARADISE
elif version >= 200 and version < 205: # New
internal_ver = ChuniConstants.VER_CHUNITHM_NEW
elif version >= 205 and version < 210: # New Plus
internal_ver = ChuniConstants.VER_CHUNITHM_NEW_PLUS
if all(c in string.hexdigits for c in endpoint) and len(endpoint) == 32:
# If we get a 32 character long hex string, it's a hash and we're
# doing encrypted. The likelyhood of false positives is low but
# technically not 0
endpoint = request.getHeader("User-Agent").split("#")[0]
try:
crypt = AES.new(
bytes.fromhex(self.game_cfg.crypto.keys[str(internal_ver)][0]),
AES.MODE_CBC,
bytes.fromhex(self.game_cfg.crypto.keys[str(internal_ver)][1])
)
req_raw = crypt.decrypt(req_raw)
except:
self.logger.error(f"Failed to decrypt v{version} request to {endpoint} -> {req_raw}")
return zlib.compress("{\"stat\": \"0\"}".encode("utf-8"))
encrtped = True
if not encrtped and self.game_cfg.crypto.encrypted_only:
self.logger.error(f"Unencrypted v{version} {endpoint} request, but config is set to encrypted only: {req_raw}")
return zlib.compress("{\"stat\": \"0\"}".encode("utf-8"))
try:
unzip = zlib.decompress(req_raw)
except zlib.error as e:
self.logger.error(f"Failed to decompress v{version} {endpoint} request -> {e}")
return b""
req_data = json.loads(unzip)
self.logger.info(f"v{version} {endpoint} request - {req_data}")
func_to_find = "handle_" + inflection.underscore(endpoint) + "_request"
try:
handler = getattr(self.versions[internal_ver], func_to_find)
resp = handler(req_data)
except AttributeError as e:
self.logger.warning(f"Unhandled v{version} request {endpoint} - {e}")
return zlib.compress("{\"stat\": \"0\"}".encode("utf-8"))
except Exception as e:
self.logger.error(f"Error handling v{version} method {endpoint} - {e}")
return zlib.compress("{\"stat\": \"0\"}".encode("utf-8"))
if resp == None:
resp = {'returnCode': 1}
self.logger.info(f"Response {resp}")
zipped = zlib.compress(json.dumps(resp, ensure_ascii=False).encode("utf-8"))
if not encrtped:
return zipped
padded = pad(zipped, 16)
crypt = AES.new(
bytes.fromhex(self.game_cfg.crypto.keys[str(internal_ver)][0]),
AES.MODE_CBC,
bytes.fromhex(self.game_cfg.crypto.keys[str(internal_ver)][1])
)
return crypt.encrypt(padded)

128
titles/chuni/new.py Normal file
View File

@ -0,0 +1,128 @@
import logging
from datetime import datetime, timedelta
from typing import Dict
from core.config import CoreConfig
from titles.chuni.const import ChuniConstants
from titles.chuni.database import ChuniData
from titles.chuni.base import ChuniBase
from titles.chuni.config import ChuniConfig
class ChuniNew(ChuniBase):
ITEM_TYPE = {
"character": 20,
"story": 21,
"card": 22
}
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
self.core_cfg = core_cfg
self.game_cfg = game_cfg
self.data = ChuniData(core_cfg)
self.date_time_format = "%Y-%m-%d %H:%M:%S"
self.logger = logging.getLogger("chuni")
self.game = ChuniConstants.GAME_CODE
self.version = ChuniConstants.VER_CHUNITHM_NEW
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
match_start = datetime.strftime(datetime.now() - timedelta(hours=10), self.date_time_format)
match_end = datetime.strftime(datetime.now() + timedelta(hours=10), self.date_time_format)
reboot_start = datetime.strftime(datetime.now() - timedelta(hours=11), self.date_time_format)
reboot_end = datetime.strftime(datetime.now() - timedelta(hours=10), self.date_time_format)
return {
"gameSetting": {
"isMaintenance": "false",
"requestInterval": 10,
"rebootStartTime": reboot_start,
"rebootEndTime": reboot_end,
"isBackgroundDistribute": "false",
"maxCountCharacter": 300,
"maxCountItem": 300,
"maxCountMusic": 300,
"matchStartTime": match_start,
"matchEndTime": match_end,
"matchTimeLimit": 99,
"matchErrorLimit": 9999,
"romVersion": "2.00.00",
"dataVersion": "2.00.00",
"matchingUri": f"http://{self.core_cfg.server.hostname}:{self.core_cfg.title.port}/SDHD/200/ChuniServlet/",
"matchingUriX": f"http://{self.core_cfg.server.hostname}:{self.core_cfg.title.port}/SDHD/200/ChuniServlet/",
"udpHolePunchUri": f"http://{self.core_cfg.server.hostname}:{self.core_cfg.title.port}/SDHD/200/ChuniServlet/",
"reflectorUri": f"http://{self.core_cfg.server.hostname}:{self.core_cfg.title.port}/SDHD/200/ChuniServlet/",
},
"isDumpUpload": "false",
"isAou": "false",
}
def handle_delete_token_api_request(self, data: Dict) -> Dict:
return { "returnCode": "1" }
def handle_create_token_api_request(self, data: Dict) -> Dict:
return { "returnCode": "1" }
def handle_get_user_map_area_api_request(self, data: Dict) -> Dict:
user_map_areas = self.data.item.get_map_areas(data["userId"])
map_areas = []
for map_area in user_map_areas:
tmp = map_area._asdict()
tmp.pop("id")
tmp.pop("user")
map_areas.append(tmp)
return {
"userId": data["userId"],
"userMapAreaList": map_areas
}
def handle_get_user_symbol_chat_setting_api_request(self, data: Dict) -> Dict:
return {
"userId": data["userId"],
"symbolCharInfoList": []
}
def handle_get_user_preview_api_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile_preview(data["userId"], self.version)
if profile is None: return None
profile_character = self.data.item.get_character(data["userId"], profile["characterId"])
if profile_character is None:
chara = {}
else:
chara = profile_character._asdict()
chara.pop("id")
chara.pop("user")
data1 = {
"userId": data["userId"],
# Current Login State
"isLogin": False,
"lastLoginDate": profile["lastPlayDate"],
# User Profile
"userName": profile["userName"],
"reincarnationNum": profile["reincarnationNum"],
"level": profile["level"],
"exp": profile["exp"],
"playerRating": profile["playerRating"],
"lastGameId": profile["lastGameId"],
"lastRomVersion": profile["lastRomVersion"],
"lastDataVersion": profile["lastDataVersion"],
"lastPlayDate": profile["lastPlayDate"],
"emoneyBrandId": 0,
"trophyId": profile["trophyId"],
# Current Selected Character
"userCharacter": chara,
# User Game Options
"playerLevel": profile["playerLevel"],
"rating": profile["rating"],
"headphone": profile["headphone"],
"chargeState": 0,
"userNameEx": "0",
"banState": 0,
"classEmblemMedal": profile["classEmblemMedal"],
"classEmblemBase": profile["classEmblemBase"],
"battleRankId": profile["battleRankId"],
}
return data1

23
titles/chuni/newplus.py Normal file
View File

@ -0,0 +1,23 @@
from datetime import datetime, timedelta
from typing import Dict, Any
import pytz
from core.config import CoreConfig
from titles.chuni.new import ChuniNew
from titles.chuni.const import ChuniConstants
from titles.chuni.config import ChuniConfig
class ChuniNewPlus(ChuniNew):
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_NEW_PLUS
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["romVersion"] = "2.05.00"
ret["gameSetting"]["dataVersion"] = "2.05.00"
ret["gameSetting"]["matchingUri"] = f"http://{self.core_cfg.server.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
ret["gameSetting"]["matchingUriX"] = f"http://{self.core_cfg.server.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
ret["gameSetting"]["udpHolePunchUri"] = f"http://{self.core_cfg.server.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
ret["gameSetting"]["reflectorUri"] = f"http://{self.core_cfg.server.hostname}:{self.core_cfg.title.port}/SDHD/205/ChuniServlet/"
return ret

18
titles/chuni/paradise.py Normal file
View File

@ -0,0 +1,18 @@
from datetime import datetime, timedelta
from typing import Dict, Any
import pytz
from core.config import CoreConfig
from titles.chuni.base import ChuniBase
from titles.chuni.const import ChuniConstants
from titles.chuni.config import ChuniConfig
class ChuniParadise(ChuniBase):
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_PARADISE
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.50.00"
return ret

16
titles/chuni/plus.py Normal file
View File

@ -0,0 +1,16 @@
from typing import Dict
from core.config import CoreConfig
from titles.chuni.base import ChuniBase
from titles.chuni.const import ChuniConstants
from titles.chuni.config import ChuniConfig
class ChuniPlus(ChuniBase):
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_PLUS
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.05.00"
return ret

157
titles/chuni/read.py Normal file
View File

@ -0,0 +1,157 @@
from typing import Optional
from os import walk, path
import xml.etree.ElementTree as ET
from read import BaseReader
from core.config import CoreConfig
from titles.chuni.database import ChuniData
from titles.chuni.const import ChuniConstants
class ChuniReader(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 = ChuniData(config)
try:
self.logger.info(f"Start importer for {ChuniConstants.game_ver_to_string(version)}")
except IndexError:
self.logger.error(f"Invalid chunithm version {version}")
exit(1)
def read(self) -> None:
data_dirs = []
if self.bin_dir is not None:
data_dirs += self.get_data_directories(self.bin_dir)
if self.opt_dir is not None:
data_dirs += self.get_data_directories(self.opt_dir)
for dir in data_dirs:
self.logger.info(f"Read from {dir}")
self.read_events(f"{dir}/event")
self.read_music(f"{dir}/music")
self.read_charges(f"{dir}/chargeItem")
self.read_avatar(f"{dir}/avatarAccessory")
def read_events(self, evt_dir: str) -> None:
for root, dirs, files in walk(evt_dir):
for dir in dirs:
if path.exists(f"{root}/{dir}/Event.xml"):
with open(f"{root}/{dir}/Event.xml", 'rb') as fp:
bytedata = fp.read()
strdata = bytedata.decode('UTF-8')
xml_root = ET.fromstring(strdata)
for name in xml_root.findall('name'):
id = name.find('id').text
name = name.find('str').text
for substances in xml_root.findall('substances'):
event_type = substances.find('type').text
result = self.data.static.put_event(self.version, id, event_type, name)
if result is not None:
self.logger.info(f"Inserted event {id}")
else:
self.logger.warn(f"Failed to insert event {id}")
def read_music(self, music_dir: str) -> None:
for root, dirs, files in walk(music_dir):
for dir in dirs:
if path.exists(f"{root}/{dir}/Music.xml"):
with open(f"{root}/{dir}/Music.xml", 'rb') as fp:
bytedata = fp.read()
strdata = bytedata.decode('UTF-8')
xml_root = ET.fromstring(strdata)
for name in xml_root.findall('name'):
song_id = name.find('id').text
title = name.find('str').text
for artistName in xml_root.findall('artistName'):
artist = artistName.find('str').text
for genreNames in xml_root.findall('genreNames'):
for list_ in genreNames.findall('list'):
for StringID in list_.findall('StringID'):
genre = StringID.find('str').text
for jaketFile in xml_root.findall('jaketFile'): #nice typo, SEGA
jacket_path = jaketFile.find('path').text
for fumens in xml_root.findall('fumens'):
for MusicFumenData in fumens.findall('MusicFumenData'):
fumen_path = MusicFumenData.find('file').find("path")
if fumen_path.text is not None:
chart_id = MusicFumenData.find('type').find('id').text
if chart_id == "4":
level = float(xml_root.find("starDifType").text)
we_chara = xml_root.find("worldsEndTagName").find("str").text
else:
level = float(f"{MusicFumenData.find('level').text}.{MusicFumenData.find('levelDecimal').text}")
we_chara = None
result = self.data.static.put_music(
self.version,
song_id,
chart_id,
title,
artist,
level,
genre,
jacket_path,
we_chara
)
if result is not None:
self.logger.info(f"Inserted music {song_id} chart {chart_id}")
else:
self.logger.warn(f"Failed to insert music {song_id} chart {chart_id}")
def read_charges(self, charge_dir: str) -> None:
for root, dirs, files in walk(charge_dir):
for dir in dirs:
if path.exists(f"{root}/{dir}/ChargeItem.xml"):
with open(f"{root}/{dir}/ChargeItem.xml", 'rb') as fp:
bytedata = fp.read()
strdata = bytedata.decode('UTF-8')
xml_root = ET.fromstring(strdata)
for name in xml_root.findall('name'):
id = name.find('id').text
name = name.find('str').text
expirationDays = xml_root.find('expirationDays').text
consumeType = xml_root.find('consumeType').text
sellingAppeal = bool(xml_root.find('sellingAppeal').text)
result = self.data.static.put_charge(self.version, id, name, expirationDays, consumeType, sellingAppeal)
if result is not None:
self.logger.info(f"Inserted charge {id}")
else:
self.logger.warn(f"Failed to insert charge {id}")
def read_avatar(self, avatar_dir: str) -> None:
for root, dirs, files in walk(avatar_dir):
for dir in dirs:
if path.exists(f"{root}/{dir}/AvatarAccessory.xml"):
with open(f"{root}/{dir}/AvatarAccessory.xml", 'rb') as fp:
bytedata = fp.read()
strdata = bytedata.decode('UTF-8')
xml_root = ET.fromstring(strdata)
for name in xml_root.findall('name'):
id = name.find('id').text
name = name.find('str').text
category = xml_root.find('category').text
for image in xml_root.findall('image'):
iconPath = image.find('path').text
for texture in xml_root.findall('texture'):
texturePath = texture.find('path').text
result = self.data.static.put_avatar(self.version, id, name, category, iconPath, texturePath)
if result is not None:
self.logger.info(f"Inserted avatarAccessory {id}")
else:
self.logger.warn(f"Failed to insert avatarAccessory {id}")

View File

@ -0,0 +1,6 @@
from titles.chuni.schema.profile import ChuniProfileData
from titles.chuni.schema.score import ChuniScoreData
from titles.chuni.schema.item import ChuniItemData
from titles.chuni.schema.static import ChuniStaticData
__all__ = ["ChuniProfileData", "ChuniScoreData", "ChuniItemData", "ChuniStaticData"]

207
titles/chuni/schema/item.py Normal file
View File

@ -0,0 +1,207 @@
from typing import Dict, List, Optional
from sqlalchemy import Table, Column, UniqueConstraint, PrimaryKeyConstraint, and_
from sqlalchemy.types import Integer, String, TIMESTAMP, Boolean, JSON
from sqlalchemy.engine.base import Connection
from sqlalchemy.schema import ForeignKey
from sqlalchemy.sql import func, select
from sqlalchemy.dialects.mysql import insert
from sqlalchemy.engine import Row
from core.data.schema import BaseData, metadata
character = Table(
"chuni_item_character",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("characterId", Integer),
Column("level", Integer),
Column("param1", Integer),
Column("param2", Integer),
Column("isValid", Boolean),
Column("skillId", Integer),
Column("isNewMark", Boolean),
Column("playCount", Integer),
Column("friendshipExp", Integer),
Column("assignIllust", Integer),
Column("exMaxLv", Integer),
UniqueConstraint("user", "characterId", name="chuni_item_character_uk"),
mysql_charset='utf8mb4'
)
item = Table(
"chuni_item_item",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("itemId", Integer),
Column("itemKind", Integer),
Column("stock", Integer),
Column("isValid", Boolean),
UniqueConstraint("user", "itemId", "itemKind", name="chuni_item_item_uk"),
mysql_charset='utf8mb4'
)
duel = Table(
"chuni_item_duel",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("duelId", Integer),
Column("progress", Integer),
Column("point", Integer),
Column("isClear", Boolean),
Column("lastPlayDate", String(25)),
Column("param1", Integer),
Column("param2", Integer),
Column("param3", Integer),
Column("param4", Integer),
UniqueConstraint("user", "duelId", name="chuni_item_duel_uk"),
mysql_charset='utf8mb4'
)
map = Table(
"chuni_item_map",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("mapId", Integer),
Column("position", Integer),
Column("isClear", Boolean),
Column("areaId", Integer),
Column("routeNumber", Integer),
Column("eventId", Integer),
Column("rate", Integer),
Column("statusCount", Integer),
Column("isValid", Boolean),
UniqueConstraint("user", "mapId", name="chuni_item_map_uk"),
mysql_charset='utf8mb4'
)
map_area = Table(
"chuni_item_map_area",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("mapAreaId", Integer),
Column("rate", Integer),
Column("isClear", Boolean),
Column("isLocked", Boolean),
Column("position", Integer),
Column("statusCount", Integer),
Column("remainGridCount", Integer),
UniqueConstraint("user", "mapAreaId", name="chuni_item_map_area_uk"),
mysql_charset='utf8mb4'
)
class ChuniItemData(BaseData):
def put_character(self, user_id: int, character_data: Dict) -> Optional[int]:
character_data["user"] = user_id
character_data = self.fix_bools(character_data)
sql = insert(character).values(**character_data)
conflict = sql.on_duplicate_key_update(**character_data)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid
def get_character(self, user_id: int, character_id: int) -> Optional[Dict]:
sql = select(character).where(and_(
character.c.user == user_id,
character.c.characterId == character_id
))
result = self.execute(sql)
if result is None: return None
return result.fetchone()
def get_characters(self, user_id: int) -> Optional[List[Row]]:
sql = select(character).where(character.c.user == user_id)
result = self.execute(sql)
if result is None: return None
return result.fetchall()
def put_item(self, user_id: int, item_data: Dict) -> Optional[int]:
item_data["user"] = user_id
item_data = self.fix_bools(item_data)
sql = insert(item).values(**item_data)
conflict = sql.on_duplicate_key_update(**item_data)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid
def get_items(self, user_id: int, kind: int = None) -> Optional[List[Row]]:
if kind is None:
sql = select(item).where(item.c.user == user_id)
else:
sql = select(item).where(and_(
item.c.user == user_id,
item.c.itemKind == kind
))
result = self.execute(sql)
if result is None: return None
return result.fetchall()
def put_duel(self, user_id: int, duel_data: Dict) -> Optional[int]:
duel_data["user"] = user_id
duel_data = self.fix_bools(duel_data)
sql = insert(duel).values(**duel_data)
conflict = sql.on_duplicate_key_update(**duel_data)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid
def get_duels(self, user_id: int) -> Optional[List[Row]]:
sql = select(duel).where(duel.c.user == user_id)
result = self.execute(sql)
if result is None: return None
return result.fetchall()
def put_map(self, user_id: int, map_data: Dict) -> Optional[int]:
map_data["user"] = user_id
map_data = self.fix_bools(map_data)
sql = insert(map).values(**map_data)
conflict = sql.on_duplicate_key_update(**map_data)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid
def get_maps(self, user_id: int) -> Optional[List[Row]]:
sql = select(map).where(map.c.user == user_id)
result = self.execute(sql)
if result is None: return None
return result.fetchall()
def put_map_area(self, user_id: int, map_area_data: Dict) -> Optional[int]:
map_area_data["user"] = user_id
map_area_data = self.fix_bools(map_area_data)
sql = insert(map_area).values(**map_area_data)
conflict = sql.on_duplicate_key_update(**map_area_data)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid
def get_map_areas(self, user_id: int) -> Optional[List[Row]]:
sql = select(map_area).where(map_area.c.user == user_id)
result = self.execute(sql)
if result is None: return None
return result.fetchall()

View File

@ -0,0 +1,551 @@
from typing import Dict, List, Optional
from sqlalchemy import Table, Column, UniqueConstraint, PrimaryKeyConstraint, and_
from sqlalchemy.types import Integer, String, TIMESTAMP, Boolean, JSON, BigInteger
from sqlalchemy.engine.base import Connection
from sqlalchemy.schema import ForeignKey
from sqlalchemy.engine import Row
from sqlalchemy.sql import func, select
from sqlalchemy.dialects.mysql import insert
from core.data.schema import BaseData, metadata
profile = Table(
"chuni_profile_data",
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("exp", Integer),
Column("level", Integer),
Column("point", Integer),
Column("frameId", Integer),
Column("isMaimai", Boolean),
Column("trophyId", Integer),
Column("userName", String(25)),
Column("isWebJoin", Boolean),
Column("playCount", Integer),
Column("lastGameId", String(25)),
Column("totalPoint", BigInteger),
Column("characterId", Integer),
Column("firstGameId", String(25)),
Column("friendCount", Integer),
Column("lastPlaceId", Integer),
Column("nameplateId", Integer),
Column("totalMapNum", Integer),
Column("lastAllNetId", Integer),
Column("lastClientId", String(25)),
Column("lastPlayDate", String(25)),
Column("lastRegionId", Integer),
Column("playerRating", Integer),
Column("totalHiScore", Integer),
Column("webLimitDate", String(25)),
Column("firstPlayDate", String(25)),
Column("highestRating", Integer),
Column("lastPlaceName", String(25)),
Column("multiWinCount", Integer),
Column("acceptResCount", Integer),
Column("lastRegionName", String(25)),
Column("lastRomVersion", String(25)),
Column("multiPlayCount", Integer),
Column("firstRomVersion", String(25)),
Column("lastDataVersion", String(25)),
Column("requestResCount", Integer),
Column("successResCount", Integer),
Column("eventWatchedDate", String(25)),
Column("firstDataVersion", String(25)),
Column("reincarnationNum", Integer),
Column("playedTutorialBit", Integer),
Column("totalBasicHighScore", Integer),
Column("totalExpertHighScore", Integer),
Column("totalMasterHighScore", Integer),
Column("totalRepertoireCount", Integer),
Column("firstTutorialCancelNum", Integer),
Column("totalAdvancedHighScore", Integer),
Column("masterTutorialCancelNum", Integer),
Column("ext1", Integer), # Added in chunew
Column("ext2", Integer),
Column("ext3", Integer),
Column("ext4", Integer),
Column("ext5", Integer),
Column("ext6", Integer),
Column("ext7", Integer),
Column("ext8", Integer),
Column("ext9", Integer),
Column("ext10", Integer),
Column("extStr1", String(255)),
Column("extStr2", String(255)),
Column("extLong1", Integer),
Column("extLong2", Integer),
Column("mapIconId", Integer),
Column("compatibleCmVersion", String(25)),
Column("medal", Integer),
Column("voiceId", Integer),
Column("teamId", Integer, ForeignKey("chuni_profile_team.id", ondelete="SET NULL", onupdate="SET NULL")),
Column("avatarBack", Integer, server_default="0"),
Column("avatarFace", Integer, server_default="0"),
Column("eliteRankPoint", Integer, server_default="0"),
Column("stockedGridCount", Integer, server_default="0"),
Column("netBattleLoseCount", Integer, server_default="0"),
Column("netBattleHostErrCnt", Integer, server_default="0"),
Column("netBattle4thCount", Integer, server_default="0"),
Column("overPowerRate", Integer, server_default="0"),
Column("battleRewardStatus", Integer, server_default="0"),
Column("avatarPoint", Integer, server_default="0"),
Column("netBattle1stCount", Integer, server_default="0"),
Column("charaIllustId", Integer, server_default="0"),
Column("avatarItem", Integer, server_default="0"),
Column("userNameEx", String(8), server_default=""),
Column("netBattleWinCount", Integer, server_default="0"),
Column("netBattleCorrection", Integer, server_default="0"),
Column("classEmblemMedal", Integer, server_default="0"),
Column("overPowerPoint", Integer, server_default="0"),
Column("netBattleErrCnt", Integer, server_default="0"),
Column("battleRankId", Integer, server_default="0"),
Column("netBattle3rdCount", Integer, server_default="0"),
Column("netBattleConsecutiveWinCount", Integer, server_default="0"),
Column("overPowerLowerRank", Integer, server_default="0"),
Column("avatarWear", Integer, server_default="0"),
Column("classEmblemBase", Integer, server_default="0"),
Column("battleRankPoint", Integer, server_default="0"),
Column("netBattle2ndCount", Integer, server_default="0"),
Column("totalUltimaHighScore", Integer, server_default="0"),
Column("skillId", Integer, server_default="0"),
Column("lastCountryCode", String(5), server_default="JPN"),
Column("isNetBattleHost", Boolean, server_default="0"),
Column("avatarFront", Integer, server_default="0"),
Column("avatarSkin", Integer, server_default="0"),
Column("battleRewardCount", Integer, server_default="0"),
Column("battleRewardIndex", Integer, server_default="0"),
Column("netBattlePlayCount", Integer, server_default="0"),
Column("exMapLoopCount", Integer, server_default="0"),
Column("netBattleEndState", Integer, server_default="0"),
Column("avatarHead", Integer, server_default="0"),
UniqueConstraint("user", "version", name="chuni_profile_profile_uk"),
mysql_charset='utf8mb4'
)
profile_ex = Table(
"chuni_profile_data_ex",
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("ext1", Integer),
Column("ext2", Integer),
Column("ext3", Integer),
Column("ext4", Integer),
Column("ext5", Integer),
Column("ext6", Integer),
Column("ext7", Integer),
Column("ext8", Integer),
Column("ext9", Integer),
Column("ext10", Integer),
Column("ext11", Integer),
Column("ext12", Integer),
Column("ext13", Integer),
Column("ext14", Integer),
Column("ext15", Integer),
Column("ext16", Integer),
Column("ext17", Integer),
Column("ext18", Integer),
Column("ext19", Integer),
Column("ext20", Integer),
Column("medal", Integer),
Column("extStr1", String(255)),
Column("extStr2", String(255)),
Column("extStr3", String(255)),
Column("extStr4", String(255)),
Column("extStr5", String(255)),
Column("voiceId", Integer),
Column("extLong1", Integer),
Column("extLong2", Integer),
Column("extLong3", Integer),
Column("extLong4", Integer),
Column("extLong5", Integer),
Column("mapIconId", Integer),
Column("compatibleCmVersion", String(25)),
UniqueConstraint("user", "version", name="chuni_profile_data_ex_uk"),
mysql_charset='utf8mb4'
)
option = Table(
"chuni_profile_option",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("speed", Integer),
Column("bgInfo", Integer),
Column("rating", Integer),
Column("privacy", Integer),
Column("judgePos", Integer),
Column("matching", Integer),
Column("guideLine", Integer),
Column("headphone", Integer),
Column("optionSet", Integer),
Column("fieldColor", Integer),
Column("guideSound", Integer),
Column("successAir", Integer),
Column("successTap", Integer),
Column("judgeAttack", Integer),
Column("playerLevel", Integer),
Column("soundEffect", Integer),
Column("judgeJustice", Integer),
Column("successExTap", Integer),
Column("successFlick", Integer),
Column("successSkill", Integer),
Column("successSlideHold", Integer),
Column("successTapTimbre", Integer),
Column("ext1", Integer), # Added in chunew
Column("ext2", Integer),
Column("ext3", Integer),
Column("ext4", Integer),
Column("ext5", Integer),
Column("ext6", Integer),
Column("ext7", Integer),
Column("ext8", Integer),
Column("ext9", Integer),
Column("ext10", Integer),
Column("categoryDetail", Integer, server_default="0"),
Column("judgeTimingOffset_120", Integer, server_default="0"),
Column("resultVoiceShort", Integer, server_default="0"),
Column("judgeAppendSe", Integer, server_default="0"),
Column("judgeCritical", Integer, server_default="0"),
Column("trackSkip", Integer, server_default="0"),
Column("selectMusicFilterLv", Integer, server_default="0"),
Column("sortMusicFilterLv", Integer, server_default="0"),
Column("sortMusicGenre", Integer, server_default="0"),
Column("speed_120", Integer, server_default="0"),
Column("judgeTimingOffset", Integer, server_default="0"),
Column("mirrorFumen", Integer, server_default="0"),
Column("playTimingOffset_120", Integer, server_default="0"),
Column("hardJudge", Integer, server_default="0"),
Column("notesThickness", Integer, server_default="0"),
Column("fieldWallPosition", Integer, server_default="0"),
Column("playTimingOffset", Integer, server_default="0"),
Column("fieldWallPosition_120", Integer, server_default="0"),
UniqueConstraint("user", name="chuni_profile_option_uk"),
mysql_charset='utf8mb4'
)
option_ex = Table(
"chuni_profile_option_ex",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("ext1", Integer),
Column("ext2", Integer),
Column("ext3", Integer),
Column("ext4", Integer),
Column("ext5", Integer),
Column("ext6", Integer),
Column("ext7", Integer),
Column("ext8", Integer),
Column("ext9", Integer),
Column("ext10", Integer),
Column("ext11", Integer),
Column("ext12", Integer),
Column("ext13", Integer),
Column("ext14", Integer),
Column("ext15", Integer),
Column("ext16", Integer),
Column("ext17", Integer),
Column("ext18", Integer),
Column("ext19", Integer),
Column("ext20", Integer),
UniqueConstraint("user", name="chuni_profile_option_ex_uk"),
mysql_charset='utf8mb4'
)
recent_rating = Table(
"chuni_profile_recent_rating",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("recentRating", JSON),
UniqueConstraint("user", name="chuni_profile_recent_rating_uk"),
mysql_charset='utf8mb4'
)
region = Table(
"chuni_profile_region",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("regionId", Integer),
Column("playCount", Integer),
UniqueConstraint("user", "regionId", name="chuni_profile_region_uk"),
mysql_charset='utf8mb4'
)
activity = Table(
"chuni_profile_activity",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("kind", Integer),
Column("activityId", Integer), # Reminder: Change this to ID in base.py or the game will be sad
Column("sortNumber", Integer),
Column("param1", Integer),
Column("param2", Integer),
Column("param3", Integer),
Column("param4", Integer),
UniqueConstraint("user", "kind", "activityId", name="chuni_profile_activity_uk"),
mysql_charset='utf8mb4'
)
charge = Table(
"chuni_profile_charge",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("chargeId", Integer),
Column("stock", Integer),
Column("purchaseDate", String(25)),
Column("validDate", String(25)),
Column("param1", Integer),
Column("param2", Integer),
Column("paramDate", String(25)),
UniqueConstraint("user", "chargeId", name="chuni_profile_charge_uk"),
mysql_charset='utf8mb4'
)
emoney = Table(
"chuni_profile_emoney",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("ext1", Integer),
Column("ext2", Integer),
Column("ext3", Integer),
Column("type", Integer),
Column("emoneyBrand", Integer),
Column("emoneyCredit", Integer),
UniqueConstraint("user", "emoneyBrand", name="chuni_profile_emoney_uk"),
mysql_charset='utf8mb4'
)
overpower = Table(
"chuni_profile_overpower",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("genreId", Integer),
Column("difficulty", Integer),
Column("rate", Integer),
Column("point", Integer),
UniqueConstraint("user", "genreId", "difficulty", name="chuni_profile_emoney_uk"),
mysql_charset='utf8mb4'
)
team = Table(
"chuni_profile_team",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("teamName", String(255)),
Column("teamPoint", Integer),
mysql_charset='utf8mb4'
)
class ChuniProfileData(BaseData):
def put_profile_data(self, aime_id: int, version: int, profile_data: Dict) -> Optional[int]:
profile_data["user"] = aime_id
profile_data["version"] = version
if "accessCode" in profile_data:
profile_data.pop("accessCode")
profile_data = self.fix_bools(profile_data)
sql = insert(profile).values(**profile_data)
conflict = sql.on_duplicate_key_update(**profile_data)
result = self.execute(conflict)
if result is None:
self.logger.warn(f"put_profile_data: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_profile_preview(self, aime_id: int, version: int) -> Optional[Row]:
sql = select([profile, option]).join(option, profile.c.user == option.c.user).filter(
and_(profile.c.user == aime_id, profile.c.version == version)
)
result = self.execute(sql)
if result is None: return None
return result.fetchone()
def get_profile_data(self, aime_id: int, version: int) -> Optional[Row]:
sql = select(profile).where(and_(
profile.c.user == aime_id,
profile.c.version == version,
))
result = self.execute(sql)
if result is None: return None
return result.fetchone()
def put_profile_data_ex(self, aime_id: int, version: int, profile_ex_data: Dict) -> Optional[int]:
profile_ex_data["user"] = aime_id
profile_ex_data["version"] = version
if "accessCode" in profile_ex_data:
profile_ex_data.pop("accessCode")
sql = insert(profile_ex).values(**profile_ex_data)
conflict = sql.on_duplicate_key_update(**profile_ex_data)
result = self.execute(conflict)
if result is None:
self.logger.warn(f"put_profile_data_ex: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_profile_data_ex(self, aime_id: int, version: int) -> Optional[Row]:
sql = select(profile_ex).where(and_(
profile_ex.c.user == aime_id,
profile_ex.c.version == version,
))
result = self.execute(sql)
if result is None: return None
return result.fetchone()
def put_profile_option(self, aime_id: int, option_data: Dict) -> Optional[int]:
option_data["user"] = aime_id
sql = insert(option).values(**option_data)
conflict = sql.on_duplicate_key_update(**option_data)
result = self.execute(conflict)
if result is None:
self.logger.warn(f"put_profile_option: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_profile_option(self, aime_id: int) -> Optional[Row]:
sql = select(option).where(option.c.user == aime_id)
result = self.execute(sql)
if result is None: return None
return result.fetchone()
def put_profile_option_ex(self, aime_id: int, option_ex_data: Dict) -> Optional[int]:
option_ex_data["user"] = aime_id
sql = insert(option_ex).values(**option_ex_data)
conflict = sql.on_duplicate_key_update(**option_ex_data)
result = self.execute(conflict)
if result is None:
self.logger.warn(f"put_profile_option_ex: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_profile_option_ex(self, aime_id: int) -> Optional[Row]:
sql = select(option_ex).where(option_ex.c.user == aime_id)
result = self.execute(sql)
if result is None: return None
return result.fetchone()
def put_profile_recent_rating(self, aime_id: int, recent_rating_data: List[Dict]) -> Optional[int]:
sql = insert(recent_rating).values(
user = aime_id,
recentRating = recent_rating_data
)
conflict = sql.on_duplicate_key_update(recentRating = recent_rating_data)
result = self.execute(conflict)
if result is None:
self.logger.warn(f"put_profile_recent_rating: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_profile_recent_rating(self, aime_id: int) -> Optional[Row]:
sql = select(recent_rating).where(recent_rating.c.user == aime_id)
result = self.execute(sql)
if result is None: return None
return result.fetchone()
def put_profile_activity(self, aime_id: int, activity_data: Dict) -> Optional[int]:
# The game just uses "id" but we need to distinguish that from the db column "id"
activity_data["user"] = aime_id
activity_data["activityId"] = activity_data["id"]
activity_data.pop("id")
sql = insert(activity).values(**activity_data)
conflict = sql.on_duplicate_key_update(**activity_data)
result = self.execute(conflict)
if result is None:
self.logger.warn(f"put_profile_activity: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_profile_activity(self, aime_id: int, kind: int) -> Optional[List[Row]]:
sql = select(activity).where(and_(
activity.c.user == aime_id,
activity.c.kind == kind
))
result = self.execute(sql)
if result is None: return None
return result.fetchall()
def put_profile_charge(self, aime_id: int, charge_data: Dict) -> Optional[int]:
charge_data["user"] = aime_id
sql = insert(charge).values(**charge_data)
conflict = sql.on_duplicate_key_update(**charge_data)
result = self.execute(conflict)
if result is None:
self.logger.warn(f"put_profile_charge: Failed to update! aime_id: {aime_id}")
return None
return result.lastrowid
def get_profile_charge(self, aime_id: int) -> Optional[List[Row]]:
sql = select(charge).where(charge.c.user == aime_id)
result = self.execute(sql)
if result is None: return None
return result.fetchall()
def add_profile_region(self, aime_id: int, region_id: int) -> Optional[int]:
pass
def get_profile_regions(self, aime_id: int) -> Optional[List[Row]]:
pass
def put_profile_emoney(self, aime_id: int, emoney_data: Dict) -> Optional[int]:
emoney_data["user"] = aime_id
sql = insert(emoney).values(**emoney_data)
conflict = sql.on_duplicate_key_update(**emoney_data)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid
def get_profile_emoney(self, aime_id: int) -> Optional[List[Row]]:
sql = select(emoney).where(emoney.c.user == aime_id)
result = self.execute(sql)
if result is None: return None
return result.fetchall()
def put_profile_overpower(self, aime_id: int, overpower_data: Dict) -> Optional[int]:
overpower_data["user"] = aime_id
sql = insert(overpower).values(**overpower_data)
conflict = sql.on_duplicate_key_update(**overpower_data)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid
def get_profile_overpower(self, aime_id: int) -> Optional[List[Row]]:
sql = select(overpower).where(overpower.c.user == aime_id)
result = self.execute(sql)
if result is None: return None
return result.fetchall()

View File

@ -0,0 +1,178 @@
from typing import Dict, List, Optional
from sqlalchemy import Table, Column, UniqueConstraint, PrimaryKeyConstraint, and_
from sqlalchemy.types import Integer, String, TIMESTAMP, Boolean, JSON, BigInteger
from sqlalchemy.engine.base import Connection
from sqlalchemy.schema import ForeignKey
from sqlalchemy.engine import Row
from sqlalchemy.sql import func, select
from sqlalchemy.dialects.mysql import insert
from core.data.schema import BaseData, metadata
course = Table(
"chuni_score_course",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("courseId", Integer),
Column("classId", Integer),
Column("playCount", Integer),
Column("scoreMax", Integer),
Column("isFullCombo", Boolean),
Column("isAllJustice", Boolean),
Column("isSuccess", Boolean),
Column("scoreRank", Integer),
Column("eventId", Integer),
Column("lastPlayDate", String(25)),
Column("param1", Integer),
Column("param2", Integer),
Column("param3", Integer),
Column("param4", Integer),
Column("isClear", Boolean),
UniqueConstraint("user", "courseId", name="chuni_score_course_uk"),
mysql_charset='utf8mb4'
)
best_score = Table(
"chuni_score_best",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("musicId", Integer),
Column("level", Integer),
Column("playCount", Integer),
Column("scoreMax", Integer),
Column("resRequestCount", Integer),
Column("resAcceptCount", Integer),
Column("resSuccessCount", Integer),
Column("missCount", Integer),
Column("maxComboCount", Integer),
Column("isFullCombo", Boolean),
Column("isAllJustice", Boolean),
Column("isSuccess", Boolean),
Column("fullChain", Integer),
Column("maxChain", Integer),
Column("scoreRank", Integer),
Column("isLock", Boolean),
Column("ext1", Integer),
Column("theoryCount", Integer),
UniqueConstraint("user", "musicId", "level", name="chuni_score_best_uk"),
mysql_charset='utf8mb4'
)
playlog = Table(
"chuni_score_playlog",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("orderId", Integer),
Column("sortNumber", Integer),
Column("placeId", Integer),
Column("playDate", String(20)),
Column("userPlayDate", String(20)),
Column("musicId", Integer),
Column("level", Integer),
Column("customId", Integer),
Column("playedUserId1", Integer),
Column("playedUserId2", Integer),
Column("playedUserId3", Integer),
Column("playedUserName1", String(20)),
Column("playedUserName2", String(20)),
Column("playedUserName3", String(20)),
Column("playedMusicLevel1", Integer),
Column("playedMusicLevel2", Integer),
Column("playedMusicLevel3", Integer),
Column("playedCustom1", Integer),
Column("playedCustom2", Integer),
Column("playedCustom3", Integer),
Column("track", Integer),
Column("score", Integer),
Column("rank", Integer),
Column("maxCombo", Integer),
Column("maxChain", Integer),
Column("rateTap", Integer),
Column("rateHold", Integer),
Column("rateSlide", Integer),
Column("rateAir", Integer),
Column("rateFlick", Integer),
Column("judgeGuilty", Integer),
Column("judgeAttack", Integer),
Column("judgeJustice", Integer),
Column("judgeCritical", Integer),
Column("eventId", Integer),
Column("playerRating", Integer),
Column("isNewRecord", Boolean),
Column("isFullCombo", Boolean),
Column("fullChainKind", Integer),
Column("isAllJustice", Boolean),
Column("isContinue", Boolean),
Column("isFreeToPlay", Boolean),
Column("characterId", Integer),
Column("skillId", Integer),
Column("playKind", Integer),
Column("isClear", Boolean),
Column("skillLevel", Integer),
Column("skillEffect", Integer),
Column("placeName", String(255)),
Column("isMaimai", Boolean),
Column("commonId", Integer),
Column("charaIllustId", Integer),
Column("romVersion", String(255)),
Column("judgeHeaven", Integer),
mysql_charset='utf8mb4'
)
class ChuniScoreData(BaseData):
def get_courses(self, aime_id: int) -> Optional[Row]:
sql = select(course).where(course.c.user == aime_id)
result = self.execute(sql)
if result is None: return None
return result.fetchall()
def put_course(self, aime_id: int, course_data: Dict) -> Optional[int]:
course_data["user"] = aime_id
course_data = self.fix_bools(course_data)
sql = insert(course).values(**course_data)
conflict = sql.on_duplicate_key_update(**course_data)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid
def get_scores(self, aime_id: int) -> Optional[Row]:
sql = select(best_score).where(best_score.c.user == aime_id)
result = self.execute(sql)
if result is None: return None
return result.fetchall()
def put_score(self, aime_id: int, score_data: Dict) -> Optional[int]:
score_data["user"] = aime_id
score_data = self.fix_bools(score_data)
sql = insert(best_score).values(**score_data)
conflict = sql.on_duplicate_key_update(**score_data)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid
def get_playlogs(self, aime_id: int) -> Optional[Row]:
sql = select(playlog).where(playlog.c.user == aime_id)
result = self.execute(sql)
if result is None: return None
return result.fetchall()
def put_playlog(self, aime_id: int, playlog_data: Dict) -> Optional[int]:
playlog_data["user"] = aime_id
playlog_data = self.fix_bools(playlog_data)
sql = insert(playlog).values(**playlog_data)
conflict = sql.on_duplicate_key_update(**playlog_data)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid

View File

@ -0,0 +1,223 @@
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
events = Table(
"chuni_static_events",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("version", Integer, nullable=False),
Column("eventId", Integer),
Column("type", Integer),
Column("name", String(255)),
Column("enabled", Boolean, server_default="1"),
UniqueConstraint("version", "eventId", name="chuni_static_events_uk"),
mysql_charset='utf8mb4'
)
music = Table(
"chuni_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("artist", String(255)),
Column("level", Float),
Column("genre", String(255)),
Column("jacketPath", String(255)),
Column("worldsEndTag", String(20)),
UniqueConstraint("version", "songId", "chartId", name="chuni_static_music_uk"),
mysql_charset='utf8mb4'
)
charge = Table(
"chuni_static_charge",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("version", Integer, nullable=False),
Column("chargeId", Integer),
Column("name", String(255)),
Column("expirationDays", Integer),
Column("consumeType", Integer),
Column("sellingAppeal", Boolean),
Column("enabled", Boolean, server_default="1"),
UniqueConstraint("version", "chargeId", name="chuni_static_charge_uk"),
mysql_charset='utf8mb4'
)
avatar = Table(
"chuni_static_avatar",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("version", Integer, nullable=False),
Column("avatarAccessoryId", Integer),
Column("name", String(255)),
Column("category", Integer),
Column("iconPath", String(255)),
Column("texturePath", String(255)),
UniqueConstraint("version", "avatarAccessoryId", name="chuni_static_avatar_uk"),
mysql_charset='utf8mb4'
)
class ChuniStaticData(BaseData):
def put_event(self, version: int, event_id: int, type: int, name: str) -> Optional[int]:
sql = insert(events).values(
version = version,
eventId = event_id,
type = type,
name = name
)
conflict = sql.on_duplicate_key_update(
name = name
)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid
def update_event(self, version: int, event_id: int, enabled: bool) -> Optional[bool]:
sql = events.update(and_(events.c.version == version, events.c.eventId == event_id)).values(
enabled = enabled
)
result = self.execute(sql)
if result is None:
self.logger.warn(f"update_event: failed to update event! version: {version}, event_id: {event_id}, enabled: {enabled}")
return None
event = self.get_event(version, event_id)
if event is None:
self.logger.warn(f"update_event: failed to fetch event {event_id} after updating")
return None
return event["enabled"]
def get_event(self, version: int, event_id: int) -> Optional[Row]:
sql = select(events).where(and_(events.c.version == version, events.c.eventId == event_id))
result = self.execute(sql)
if result is None: return None
return result.fetchone()
def get_enabled_events(self, version: int) -> Optional[List[Row]]:
sql = select(events).where(and_(events.c.version == version, events.c.enabled == True))
result = self.execute(sql)
if result is None: return None
return result.fetchall()
def get_events(self, version: int) -> Optional[List[Row]]:
sql = select(events).where(events.c.version == version)
result = self.execute(sql)
if result is None: return None
return result.fetchall()
def put_music(self, version: int, song_id: int, chart_id: int, title: int, artist: str,
level: float, genre: str, jacketPath: str, we_tag: str) -> Optional[int]:
sql = insert(music).values(
version = version,
songId = song_id,
chartId = chart_id,
title = title,
artist = artist,
level = level,
genre = genre,
jacketPath = jacketPath,
worldsEndTag = we_tag,
)
conflict = sql.on_duplicate_key_update(
title = title,
artist = artist,
level = level,
genre = genre,
jacketPath = jacketPath,
worldsEndTag = we_tag,
)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid
def put_charge(self, version: int, charge_id: int, name: str, expiration_days: int,
consume_type: int, selling_appeal: bool) -> Optional[int]:
sql = insert(charge).values(
version = version,
chargeId = charge_id,
name = name,
expirationDays = expiration_days,
consumeType = consume_type,
sellingAppeal = selling_appeal,
)
conflict = sql.on_duplicate_key_update(
name = name,
expirationDays = expiration_days,
consumeType = consume_type,
sellingAppeal = selling_appeal,
)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid
def get_enabled_charges(self, version: int) -> Optional[List[Row]]:
sql = select(charge).where(and_(
charge.c.version == version,
charge.c.enabled == True
))
result = self.execute(sql)
if result is None: return None
return result.fetchall()
def get_charges(self, version: int) -> Optional[List[Row]]:
sql = select(charge).where(charge.c.version == version)
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()
def put_avatar(self, version: int, avatarAccessoryId: int, name: str, category: int, iconPath: str, texturePath: str) -> Optional[int]:
sql = insert(avatar).values(
version = version,
avatarAccessoryId = avatarAccessoryId,
name = name,
category = category,
iconPath = iconPath,
texturePath = texturePath,
)
conflict = sql.on_duplicate_key_update(
name = name,
category = category,
iconPath = iconPath,
texturePath = texturePath,
)
result = self.execute(conflict)
if result is None: return None
return result.lastrowid

16
titles/chuni/star.py Normal file
View File

@ -0,0 +1,16 @@
from typing import Dict
from core.config import CoreConfig
from titles.chuni.base import ChuniBase
from titles.chuni.const import ChuniConstants
from titles.chuni.config import ChuniConfig
class ChuniStar(ChuniBase):
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_STAR
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.20.00"
return ret

16
titles/chuni/starplus.py Normal file
View File

@ -0,0 +1,16 @@
from typing import Dict
from core.config import CoreConfig
from titles.chuni.base import ChuniBase
from titles.chuni.const import ChuniConstants
from titles.chuni.config import ChuniConfig
class ChuniStarPlus(ChuniBase):
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
super().__init__(core_cfg, game_cfg)
self.version = ChuniConstants.VER_CHUNITHM_STAR_PLUS
def handle_get_game_setting_api_request(self, data: Dict) -> Dict:
ret = super().handle_get_game_setting_api_request(data)
ret["gameSetting"]["dataVersion"] = "1.25.00"
return ret

21
titles/cxb/__init__.py Normal file
View File

@ -0,0 +1,21 @@
from titles.cxb.index import CxbServlet
from titles.cxb.const import CxbConstants
from titles.cxb.database import CxbData
from titles.cxb.read import CxbReader
index = CxbServlet
database = CxbData
reader = CxbReader
use_default_title = False
include_protocol = True
title_secure = True
game_codes = [CxbConstants.GAME_CODE]
trailing_slash = True
use_default_host = False
include_port = True
uri = "http://$h:$p/" # If you care about the allnet response you're probably running with no SSL
host = ""
current_schema_version = 1

426
titles/cxb/base.py Normal file
View File

@ -0,0 +1,426 @@
import logging
import json
from decimal import Decimal
from base64 import b64encode
from typing import Any, Dict
from hashlib import md5
from datetime import datetime
from core.config import CoreConfig
from titles.cxb.config import CxbConfig
from titles.cxb.const import CxbConstants
from titles.cxb.database import CxbData
class CxbBase():
def __init__(self, cfg: CoreConfig, game_cfg: CxbConfig) -> None:
self.config = cfg # Config file
self.game_config = game_cfg
self.data = CxbData(cfg) # Database
self.game = CxbConstants.GAME_CODE
self.logger = logging.getLogger("cxb")
self.version = CxbConstants.VER_CROSSBEATS_REV
def handle_action_rpreq_request(self, data: Dict) -> Dict:
return({})
def handle_action_hitreq_request(self, data: Dict) -> Dict:
return({"data":[]})
def handle_auth_usercheck_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile_index(0, data["usercheck"]["authid"], self.version)
if profile is not None:
self.logger.info(f"User {data['usercheck']['authid']} has CXB profile")
return({"exist": "true", "logout": "true"})
self.logger.info(f"No profile for aime id {data['usercheck']['authid']}")
return({"exist": "false", "logout": "true"})
def handle_auth_entry_request(self, data: Dict) -> Dict:
self.logger.info(f"New profile for {data['entry']['authid']}")
return({"token": data["entry"]["authid"], "uid": data["entry"]["authid"]})
def handle_auth_login_request(self, data: Dict) -> Dict:
profile = self.data.profile.get_profile_index(0, data["login"]["authid"], self.version)
if profile is not None:
self.logger.info(f"Login user {data['login']['authid']}")
return({"token": data["login"]["authid"], "uid": data["login"]["authid"]})
self.logger.warn(f"User {data['login']['authid']} does not have a profile")
return({})
def handle_action_loadrange_request(self, data: Dict) -> Dict:
range_start = data['loadrange']['range'][0]
range_end = data['loadrange']['range'][1]
uid = data['loadrange']['uid']
self.logger.info(f"Load data for {uid}")
profile = self.data.profile.get_profile(uid, self.version)
songs = self.data.score.get_best_scores(uid)
data1 = []
index = []
versionindex = []
for profile_index in profile:
profile_data = profile_index["data"]
if int(range_start) == 800000:
return({"index":range_start, "data":[], "version":10400})
if not ( int(range_start) <= int(profile_index[3]) <= int(range_end) ):
continue
#Prevent loading of the coupons within the profile to use the force unlock instead
elif 500 <= int(profile_index[3]) <= 510:
continue
#Prevent loading of songs saved in the profile
elif 100000 <= int(profile_index[3]) <= 110000:
continue
#Prevent loading of the shop list / unlocked titles & icons saved in the profile
elif 200000 <= int(profile_index[3]) <= 210000:
continue
#Prevent loading of stories in the profile
elif 900000 <= int(profile_index[3]) <= 900200:
continue
else:
index.append(profile_index[3])
data1.append(b64encode(bytes(json.dumps(profile_data, separators=(',', ':')), 'utf-8')).decode('utf-8'))
'''
100000 = Songs
200000 = Shop
300000 = Courses
400000 = Events
500000 = Challenges
600000 = Bonuses
700000 = rcLog
800000 = Partners
900000 = Stories
'''
# Coupons
for i in range(500,510):
index.append(str(i))
couponid = int(i) - 500
dataValue = [{
"couponId":str(couponid),
"couponNum":"1",
"couponLog":[],
}]
data1.append(b64encode(bytes(json.dumps(dataValue[0], separators=(',', ':')), 'utf-8')).decode('utf-8'))
# ShopList_Title
for i in range(200000,201451):
index.append(str(i))
shopid = int(i) - 200000
dataValue = [{
"shopId":shopid,
"shopState":"2",
"isDisable":"t",
"isDeleted":"f",
"isSpecialFlag":"f"
}]
data1.append(b64encode(bytes(json.dumps(dataValue[0], separators=(',', ':')), 'utf-8')).decode('utf-8'))
#ShopList_Icon
for i in range(202000,202264):
index.append(str(i))
shopid = int(i) - 200000
dataValue = [{
"shopId":shopid,
"shopState":"2",
"isDisable":"t",
"isDeleted":"f",
"isSpecialFlag":"f"
}]
data1.append(b64encode(bytes(json.dumps(dataValue[0], separators=(',', ':')), 'utf-8')).decode('utf-8'))
#Stories
for i in range(900000,900003):
index.append(str(i))
storyid = int(i) - 900000
dataValue = [{
"storyId":storyid,
"unlockState1":["t"] * 10,
"unlockState2":["t"] * 10,
"unlockState3":["t"] * 10,
"unlockState4":["t"] * 10,
"unlockState5":["t"] * 10,
"unlockState6":["t"] * 10,
"unlockState7":["t"] * 10,
"unlockState8":["t"] * 10,
"unlockState9":["t"] * 10,
"unlockState10":["t"] * 10,
"unlockState11":["t"] * 10,
"unlockState12":["t"] * 10,
"unlockState13":["t"] * 10,
"unlockState14":["t"] * 10,
"unlockState15":["t"] * 10,
"unlockState16":["t"] * 10
}]
data1.append(b64encode(bytes(json.dumps(dataValue[0], separators=(',', ':')), 'utf-8')).decode('utf-8'))
for song in songs:
song_data = song["data"]
songCode = []
songCode.append({
"mcode": song_data['mcode'],
"musicState": song_data['musicState'],
"playCount": song_data['playCount'],
"totalScore": song_data['totalScore'],
"highScore": song_data['highScore'],
"everHighScore": song_data['everHighScore'] if 'everHighScore' in song_data else ["0","0","0","0","0"],
"clearRate": song_data['clearRate'],
"rankPoint": song_data['rankPoint'],
"normalCR": song_data['normalCR'] if 'normalCR' in song_data else ["0","0","0","0","0"],
"survivalCR": song_data['survivalCR'] if 'survivalCR' in song_data else ["0","0","0","0","0"],
"ultimateCR": song_data['ultimateCR'] if 'ultimateCR' in song_data else ["0","0","0","0","0"],
"nohopeCR": song_data['nohopeCR'] if 'nohopeCR' in song_data else ["0","0","0","0","0"],
"combo": song_data['combo'],
"coupleUserId": song_data['coupleUserId'],
"difficulty": song_data['difficulty'],
"isFullCombo": song_data['isFullCombo'],
"clearGaugeType": song_data['clearGaugeType'],
"fieldType": song_data['fieldType'],
"gameType": song_data['gameType'],
"grade": song_data['grade'],
"unlockState": song_data['unlockState'],
"extraState": song_data['extraState']
})
index.append(song_data['index'])
data1.append(b64encode(bytes(json.dumps(songCode[0], separators=(',', ':')), 'utf-8')).decode('utf-8'))
for v in index:
try:
v_profile = self.data.profile.get_profile_index(0, uid, self.version)
v_profile_data = v_profile["data"]
versionindex.append(int(v_profile_data["appVersion"]))
except:
versionindex.append('10400')
return({"index":index, "data":data1, "version":versionindex})
def handle_action_saveindex_request(self, data: Dict) -> Dict:
save_data = data['saveindex']
try:
#REV Omnimix Version Fetcher
gameversion = data['saveindex']['data'][0][2]
self.logger.warning(f"Game Version is {gameversion}")
except:
pass
if "10205" in gameversion:
self.logger.info(f"Saving CrossBeats REV profile for {data['saveindex']['uid']}")
#Alright.... time to bring the jank code
for value in data['saveindex']['data']:
if 'playedUserId' in value[1]:
self.data.profile.put_profile(data['saveindex']['uid'], self.version, value[0], value[1])
if 'mcode' not in value[1]:
self.data.profile.put_profile(data['saveindex']['uid'], self.version, value[0], value[1])
if 'shopId' in value:
continue
if 'mcode' in value[1] and 'musicState' in value[1]:
song_json = json.loads(value[1])
songCode = []
songCode.append({
"mcode": song_json['mcode'],
"musicState": song_json['musicState'],
"playCount": song_json['playCount'],
"totalScore": song_json['totalScore'],
"highScore": song_json['highScore'],
"clearRate": song_json['clearRate'],
"rankPoint": song_json['rankPoint'],
"combo": song_json['combo'],
"coupleUserId": song_json['coupleUserId'],
"difficulty": song_json['difficulty'],
"isFullCombo": song_json['isFullCombo'],
"clearGaugeType": song_json['clearGaugeType'],
"fieldType": song_json['fieldType'],
"gameType": song_json['gameType'],
"grade": song_json['grade'],
"unlockState": song_json['unlockState'],
"extraState": song_json['extraState'],
"index": value[0]
})
self.data.score.put_best_score(data['saveindex']['uid'], song_json['mcode'], self.version, value[0], songCode[0])
return({})
else:
self.logger.info(f"Saving CrossBeats REV Sunrise profile for {data['saveindex']['uid']}")
#Sunrise
try:
profileIndex = save_data['index'].index('0')
except:
return({"data":""}) #Maybe
profile = json.loads(save_data["data"][profileIndex])
aimeId = profile["aimeId"]
i = 0
for index, value in enumerate(data["saveindex"]["data"]):
if int(data["saveindex"]["index"][index]) == 101:
self.data.profile.put_profile(aimeId, self.version, data["saveindex"]["index"][index], value)
if int(data["saveindex"]["index"][index]) >= 700000 and int(data["saveindex"]["index"][index])<= 701000:
self.data.profile.put_profile(aimeId, self.version, data["saveindex"]["index"][index], value)
if int(data["saveindex"]["index"][index]) >= 500 and int(data["saveindex"]["index"][index]) <= 510:
self.data.profile.put_profile(aimeId, self.version, data["saveindex"]["index"][index], value)
if 'playedUserId' in value:
self.data.profile.put_profile(aimeId, self.version, data["saveindex"]["index"][index], json.loads(value))
if 'mcode' not in value and "normalCR" not in value:
self.data.profile.put_profile(aimeId, self.version, data["saveindex"]["index"][index], json.loads(value))
if 'shopId' in value:
continue
# MusicList Index for the profile
indexSongList = []
for value in data["saveindex"]["index"]:
if int(value) in range(100000,110000):
indexSongList.append(value)
for index, value in enumerate(data["saveindex"]["data"]):
if 'mcode' not in value:
continue
if 'playedUserId' in value:
continue
data1 = json.loads(value)
songCode = []
songCode.append({
"mcode": data1['mcode'],
"musicState": data1['musicState'],
"playCount": data1['playCount'],
"totalScore": data1['totalScore'],
"highScore": data1['highScore'],
"everHighScore": data1['everHighScore'],
"clearRate": data1['clearRate'],
"rankPoint": data1['rankPoint'],
"normalCR": data1['normalCR'],
"survivalCR": data1['survivalCR'],
"ultimateCR": data1['ultimateCR'],
"nohopeCR": data1['nohopeCR'],
"combo": data1['combo'],
"coupleUserId": data1['coupleUserId'],
"difficulty": data1['difficulty'],
"isFullCombo": data1['isFullCombo'],
"clearGaugeType": data1['clearGaugeType'],
"fieldType": data1['fieldType'],
"gameType": data1['gameType'],
"grade": data1['grade'],
"unlockState": data1['unlockState'],
"extraState": data1['extraState'],
"index": indexSongList[i]
})
self.data.score.put_best_score(aimeId, data1['mcode'], self.version, indexSongList[i], songCode[0])
i += 1
return({})
def handle_action_sprankreq_request(self, data: Dict) -> Dict:
uid = data['sprankreq']['uid']
self.logger.info(f"Get best rankings for {uid}")
p = self.data.score.get_best_rankings(uid)
rankList: list[Dict[str, Any]] = []
for rank in p:
if rank["song_id"] is not None:
rankList.append({
"sc": [rank["score"],rank["song_id"]],
"rid": rank["rev_id"],
"clear": rank["clear"]
})
else:
rankList.append({
"sc": [rank["score"]],
"rid": rank["rev_id"],
"clear": rank["clear"]
})
return({
"uid": data["sprankreq"]["uid"],
"aid": data["sprankreq"]["aid"],
"rank": rankList,
"rankx":[1,1,1]
})
def handle_action_getadv_request(self, data: Dict) -> Dict:
return({"data":[{"r":"1","i":"100300","c":"20"}]})
def handle_action_getmsg_request(self, data: Dict) -> Dict:
return({"msgs":[]})
def handle_auth_logout_request(self, data: Dict) -> Dict:
return({"auth":True})
def handle_action_rankreg_request(self, data: Dict) -> Dict:
uid = data['rankreg']['uid']
self.logger.info(f"Put {len(data['rankreg']['data'])} rankings for {uid}")
for rid in data['rankreg']['data']:
#REV S2
if "clear" in rid:
try:
self.data.score.put_ranking(user_id=uid, rev_id=int(rid["rid"]), song_id=int(rid["sc"][1]), score=int(rid["sc"][0]), clear=rid["clear"])
except:
self.data.score.put_ranking(user_id=uid, rev_id=int(rid["rid"]), song_id=0, score=int(rid["sc"][0]), clear=rid["clear"])
#REV
else:
try:
self.data.score.put_ranking(user_id=uid, rev_id=int(rid["rid"]), song_id=int(rid["sc"][1]), score=int(rid["sc"][0]), clear=0)
except:
self.data.score.put_ranking(user_id=uid, rev_id=int(rid["rid"]), song_id=0, score=int(rid["sc"][0]), clear=0)
return({})
def handle_action_addenergy_request(self, data: Dict) -> Dict:
uid = data['addenergy']['uid']
self.logger.info(f"Add energy to user {uid}")
profile = self.data.profile.get_profile_index(0, uid, self.version)
data1 = profile["data"]
p = self.data.item.get_energy(uid)
energy = p["energy"]
if not p:
self.data.item.put_energy(uid, 5)
return({
"class": data1["myClass"],
"granted": "5",
"total": "5",
"threshold": "1000"
})
array = []
newenergy = int(energy) + 5
self.data.item.put_energy(uid, newenergy)
if int(energy) <= 995:
array.append({
"class": data1["myClass"],
"granted": "5",
"total": str(energy),
"threshold": "1000"
})
else:
array.append({
"class": data1["myClass"],
"granted": "0",
"total": str(energy),
"threshold": "1000"
})
return array[0]
def handle_action_eventreq_request(self, data: Dict) -> Dict:
self.logger.info(data)
return {"eventreq": ""}
def handle_action_stampreq_request(self, data: Dict) -> Dict:
self.logger.info(data)
return {"stampreq": ""}

41
titles/cxb/config.py Normal file
View File

@ -0,0 +1,41 @@
from core.config import CoreConfig
class CxbServerConfig():
def __init__(self, parent_config: "CxbConfig"):
self.__config = parent_config
@property
def enable(self) -> bool:
return CoreConfig.get_config_field(self.__config, 'cxb', 'server', 'enable', default=True)
@property
def loglevel(self) -> int:
return CoreConfig.str_to_loglevel(CoreConfig.get_config_field(self.__config, 'cxb', 'server', 'loglevel', default="info"))
@property
def hostname(self) -> str:
return CoreConfig.get_config_field(self.__config, 'cxb', 'server', 'hostname', default="localhost")
@property
def ssl_enable(self) -> bool:
return CoreConfig.get_config_field(self.__config, 'cxb', 'server', 'ssl_enable', default=False)
@property
def port(self) -> int:
return CoreConfig.get_config_field(self.__config, 'cxb', 'server', 'port', default=8082)
@property
def port_secure(self) -> int:
return CoreConfig.get_config_field(self.__config, 'cxb', 'server', 'port_secure', default=443)
@property
def ssl_cert(self) -> str:
return CoreConfig.get_config_field(self.__config, 'cxb', 'server', 'ssl_cert', default="cert/title.crt")
@property
def ssl_key(self) -> str:
return CoreConfig.get_config_field(self.__config, 'cxb', 'server', 'ssl_key', default="cert/title.key")
class CxbConfig(dict):
def __init__(self) -> None:
self.server = CxbServerConfig(self)

15
titles/cxb/const.py Normal file
View File

@ -0,0 +1,15 @@
class CxbConstants():
GAME_CODE = "SDCA"
CONFIG_NAME = "cxb.yaml"
VER_CROSSBEATS_REV = 0
VER_CROSSBEATS_REV_SUNRISE_S1 = 1
VER_CROSSBEATS_REV_SUNRISE_S2 = 2
VER_CROSSBEATS_REV_SUNRISE_S2_OMNI = 3
VERSION_NAMES = ("crossbeats REV.", "crossbeats REV. SUNRISE", "crossbeats REV. SUNRISE S2", "crossbeats REV. SUNRISE S2 Omnimix")
@classmethod
def game_ver_to_string(cls, ver: int):
return cls.VERSION_NAMES[ver]

13
titles/cxb/database.py Normal file
View File

@ -0,0 +1,13 @@
from core.data import Data
from core.config import CoreConfig
from titles.cxb.schema import CxbProfileData, CxbScoreData, CxbItemData, CxbStaticData
class CxbData(Data):
def __init__(self, cfg: CoreConfig) -> None:
super().__init__(cfg)
self.profile = CxbProfileData(self.config, self.session)
self.score = CxbScoreData(self.config, self.session)
self.item = CxbItemData(self.config, self.session)
self.static = CxbStaticData(self.config, self.session)

145
titles/cxb/index.py Normal file
View File

@ -0,0 +1,145 @@
from twisted.web.http import Request
from twisted.web import resource, server
from twisted.internet import reactor, endpoints
import yaml
import json
import re
import inflection
import logging, coloredlogs
from logging.handlers import TimedRotatingFileHandler
from typing import Dict
from core.config import CoreConfig
from titles.cxb.config import CxbConfig
from titles.cxb.const import CxbConstants
from titles.cxb.rev import CxbRev
from titles.cxb.rss1 import CxbRevSunriseS1
from titles.cxb.rss2 import CxbRevSunriseS2
class CxbServlet(resource.Resource):
def __init__(self, core_cfg: CoreConfig, cfg_dir: str) -> None:
self.isLeaf = True
self.cfg_dir = cfg_dir
self.core_cfg = core_cfg
self.game_cfg = CxbConfig()
self.game_cfg.update(yaml.safe_load(open(f"{cfg_dir}/cxb.yaml")))
self.logger = logging.getLogger("cxb")
log_fmt_str = "[%(asctime)s] CXB | %(levelname)s | %(message)s"
log_fmt = logging.Formatter(log_fmt_str)
fileHandler = TimedRotatingFileHandler("{0}/{1}.log".format(self.core_cfg.server.log_dir, "cxb"), 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)
self.versions = [
CxbRev(core_cfg, self.game_cfg),
CxbRevSunriseS1(core_cfg, self.game_cfg),
CxbRevSunriseS2(core_cfg, self.game_cfg),
]
def setup(self):
if self.game_cfg.server.enable:
endpoints.serverFromString(reactor, f"tcp:{self.game_cfg.server.port}:interface={self.core_cfg.server.listen_address}")\
.listen(server.Site(CxbServlet(self.core_cfg, self.cfg_dir)))
if self.core_cfg.server.is_develop and self.game_cfg.server.ssl_enable:
endpoints.serverFromString(reactor, f"ssl:{self.game_cfg.server.port_secure}"\
f":interface={self.core_cfg.server.listen_address}:privateKey={self.game_cfg.server.ssl_key}:"\
f"certKey={self.game_cfg.server.ssl_cert}")\
.listen(server.Site(CxbServlet(self.core_cfg, self.cfg_dir)))
self.logger.info(f"Crossbeats title server ready on port {self.game_cfg.server.port} & {self.game_cfg.server.port_secure}")
else:
self.logger.info(f"Crossbeats title server ready on port {self.game_cfg.server.port}")
def render_POST(self, request: Request):
version = 0
internal_ver = 0
func_to_find = ""
cmd = ""
subcmd = ""
req_url = request.uri.decode()
url_split = req_url.split("/")
req_bytes = request.content.getvalue()
try:
req_json: Dict = json.loads(req_bytes)
except Exception as e:
try:
req_json: Dict = json.loads(req_bytes.decode().replace('"', '\\"').replace("'", '"'))
except Exception as f:
self.logger.warn(f"Error decoding json: {e} / {f} - {req_url} - {req_bytes}")
return b""
if req_json == {}:
self.logger.warn(f"Empty json request to {req_url}")
return b""
cmd = url_split[len(url_split) - 1]
subcmd = list(req_json.keys())[0]
if subcmd == "dldate":
if not type(req_json["dldate"]) is dict or "filetype" not in req_json["dldate"]:
self.logger.warn(f"Malformed dldate request: {req_url} {req_json}")
return b""
filetype = req_json["dldate"]["filetype"]
filetype_split = filetype.split("/")
version = int(filetype_split[0])
filetype_inflect_split = inflection.underscore(filetype).split("/")
match = re.match("^([A-Za-z]*)(\d\d\d\d)$", filetype_split[len(filetype_split) - 1])
if match:
subcmd = f"{inflection.underscore(match.group(1))}xxxx"
else:
subcmd = f"{filetype_inflect_split[len(filetype_inflect_split) - 1]}"
else:
filetype = subcmd
func_to_find = f"handle_{cmd}_{subcmd}_request"
if version <= 10102:
version_string = "Rev"
internal_ver = CxbConstants.VER_CROSSBEATS_REV
elif version == 10113 or version == 10103:
version_string = "Rev SunriseS1"
internal_ver = CxbConstants.VER_CROSSBEATS_REV_SUNRISE_S1
elif version >= 10114 or version == 10104:
version_string = "Rev SunriseS2"
internal_ver = CxbConstants.VER_CROSSBEATS_REV_SUNRISE_S2
else:
version_string = "Base"
self.logger.info(f"{version_string} Request {req_url} -> {filetype}")
self.logger.debug(req_json)
try:
handler = getattr(self.versions[internal_ver], func_to_find)
resp = handler(req_json)
except AttributeError as e:
self.logger.warning(f"Unhandled {version_string} request {req_url} - {e}")
resp = {}
except Exception as e:
self.logger.error(f"Error handling {version_string} method {req_url} - {e}")
raise
self.logger.debug(f"{version_string} Response {resp}")
return json.dumps(resp, ensure_ascii=False).encode("utf-8")

62
titles/cxb/read.py Normal file
View File

@ -0,0 +1,62 @@
from typing import Optional, Dict, List
from os import walk, path
import urllib
import csv
from read import BaseReader
from core.config import CoreConfig
from titles.cxb.database import CxbData
from titles.cxb.const import CxbConstants
class CxbReader(BaseReader):
def __init__(self, config: CoreConfig, version: int, bin_arg: Optional[str], opt_arg: Optional[str], extra: Optional[str]) -> None:
super().__init__(config, version, bin_arg, opt_arg, extra)
self.data = CxbData(config)
try:
self.logger.info(f"Start importer for {CxbConstants.game_ver_to_string(version)}")
except IndexError:
self.logger.error(f"Invalid project cxb version {version}")
exit(1)
def read(self) -> None:
pull_bin_ram = True
if not path.exists(f"{self.bin_dir}"):
self.logger.warn(f"Couldn't find csv file in {self.bin_dir}, skipping")
pull_bin_ram = False
if pull_bin_ram:
self.read_csv(f"{self.bin_dir}")
def read_csv(self, bin_dir: str) -> None:
self.logger.info(f"Read csv from {bin_dir}")
try:
fullPath = bin_dir + "/export.csv"
with open(fullPath, encoding="UTF-8") as fp:
reader = csv.DictReader(fp)
for row in reader:
song_id = row["mcode"]
index = row["index"]
title = row["name"]
artist = row["artist"]
genre = row["category"]
if not "N/A" in row["standard"]:
self.logger.info(f"Added song {song_id} chart 0")
self.data.static.put_music(self.version, song_id, index, 0, title, artist, genre, int(row["standard"].replace("Standard ","").replace("N/A","0")))
if not "N/A" in row["hard"]:
self.logger.info(f"Added song {song_id} chart 1")
self.data.static.put_music(self.version, song_id, index, 1, title, artist, genre, int(row["hard"].replace("Hard ","").replace("N/A","0")))
if not "N/A" in row["master"]:
self.logger.info(f"Added song {song_id} chart 2")
self.data.static.put_music(self.version, song_id, index, 2, title, artist, genre, int(row["master"].replace("Master ","").replace("N/A","0")))
if not "N/A" in row["unlimited"]:
self.logger.info(f"Added song {song_id} chart 3")
self.data.static.put_music(self.version, song_id, index, 3, title, artist, genre, int(row["unlimited"].replace("Unlimited ","").replace("N/A","0")))
if not "N/A" in row["easy"]:
self.logger.info(f"Added song {song_id} chart 4")
self.data.static.put_music(self.version, song_id, index, 4, title, artist, genre, int(row["easy"].replace("Easy ","").replace("N/A","0")))
except:
self.logger.warn(f"Couldn't read csv file in {self.bin_dir}, skipping")

256
titles/cxb/rev.py Normal file
View File

@ -0,0 +1,256 @@
import json
from decimal import Decimal
from base64 import b64encode
from typing import Any, Dict
from hashlib import md5
from datetime import datetime
from core.config import CoreConfig
from core.data import Data, cached
from titles.cxb.config import CxbConfig
from titles.cxb.base import CxbBase
from titles.cxb.const import CxbConstants
class CxbRev(CxbBase):
def __init__(self, cfg: CoreConfig, game_cfg: CxbConfig) -> None:
super().__init__(cfg, game_cfg)
self.version = CxbConstants.VER_CROSSBEATS_REV
def handle_data_path_list_request(self, data: Dict) -> Dict:
return { "data": "" }
def handle_data_putlog_request(self, data: Dict) -> Dict:
if data["putlog"]["type"] == "ResultLog":
score_data = json.loads(data["putlog"]["data"])
userid = score_data['usid']
self.data.score.put_playlog(userid, score_data['mcode'], score_data['difficulty'], score_data["score"], int(Decimal(score_data["clearrate"]) * 100), score_data["flawless"], score_data["super"], score_data["cool"], score_data["fast"], score_data["fast2"], score_data["slow"], score_data["slow2"], score_data["fail"], score_data["combo"])
return({"data":True})
return {"data": True }
@cached(lifetime=86400)
def handle_data_music_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/rev_data/MusicArchiveList.csv") as music:
lines = music.readlines()
for line in lines:
line_split = line.split(',')
ret_str += f"{line_split[0]},{line_split[1]},{line_split[2]},{line_split[3]},{line_split[4]},{line_split[5]},{line_split[6]},{line_split[7]},{line_split[8]},{line_split[9]},{line_split[10]},{line_split[11]},{line_split[12]},{line_split[13]},{line_split[14]},\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_item_list_icon_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ItemListIcon\r\n"
with open(r"titles/cxb/rev_data/Item/ItemArchiveList_Icon.csv", encoding="utf-8") as item:
lines = item.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_item_list_skin_notes_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ItemListSkinNotes\r\n"
with open(r"titles/cxb/rev_data/Item/ItemArchiveList_SkinNotes.csv", encoding="utf-8") as item:
lines = item.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_item_list_skin_effect_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ItemListSkinEffect\r\n"
with open(r"titles/cxb/rev_data/Item/ItemArchiveList_SkinEffect.csv", encoding="utf-8") as item:
lines = item.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_item_list_skin_bg_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ItemListSkinBg\r\n"
with open(r"titles/cxb/rev_data/Item/ItemArchiveList_SkinBg.csv", encoding="utf-8") as item:
lines = item.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_item_list_title_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ItemListTitle\r\n"
with open(r"titles/cxb/rev_data/Item/ItemList_Title.csv", encoding="shift-jis") as item:
lines = item.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_shop_list_music_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ShopListMusic\r\n"
with open(r"titles/cxb/rev_data/Shop/ShopList_Music.csv", encoding="shift-jis") as shop:
lines = shop.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_shop_list_icon_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ShopListIcon\r\n"
with open(r"titles/cxb/rev_data/Shop/ShopList_Icon.csv", encoding="shift-jis") as shop:
lines = shop.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_shop_list_title_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ShopListTitle\r\n"
with open(r"titles/cxb/rev_data/Shop/ShopList_Title.csv", encoding="shift-jis") as shop:
lines = shop.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
def handle_data_shop_list_skin_hud_request(self, data: Dict) -> Dict:
return({"data":""})
def handle_data_shop_list_skin_arrow_request(self, data: Dict) -> Dict:
return({"data":""})
def handle_data_shop_list_skin_hit_request(self, data: Dict) -> Dict:
return({"data":""})
@cached(lifetime=86400)
def handle_data_shop_list_sale_request(self, data: Dict) -> Dict:
ret_str = "\r\n#ShopListSale\r\n"
with open(r"titles/cxb/rev_data/Shop/ShopList_Sale.csv", encoding="shift-jis") as shop:
lines = shop.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
def handle_data_extra_stage_list_request(self, data: Dict) -> Dict:
return({"data":""})
@cached(lifetime=86400)
def handle_data_exxxxx_request(self, data: Dict) -> Dict:
extra_num = int(data["dldate"]["filetype"][-4:])
ret_str = ""
with open(fr"titles/cxb/rev_data/Ex000{extra_num}.csv", encoding="shift-jis") as stage:
lines = stage.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
def handle_data_bonus_list10100_request(self, data: Dict) -> Dict:
return({"data": ""})
def handle_data_free_coupon_request(self, data: Dict) -> Dict:
return({"data": ""})
@cached(lifetime=86400)
def handle_data_news_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/rev_data/NewsList.csv", encoding="UTF-8") as news:
lines = news.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
def handle_data_tips_request(self, data: Dict) -> Dict:
return({"data":""})
@cached(lifetime=86400)
def handle_data_license_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/rev_data/License_Offline.csv", encoding="UTF-8") as lic:
lines = lic.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_course_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/rev_data/Course/CourseList.csv", encoding="UTF-8") as course:
lines = course.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_csxxxx_request(self, data: Dict) -> Dict:
# Removed the CSVs since the format isnt quite right
extra_num = int(data["dldate"]["filetype"][-4:])
ret_str = ""
with open(fr"titles/cxb/rev_data/Course/Cs000{extra_num}.csv", encoding="shift-jis") as course:
lines = course.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_mission_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/rev_data/MissionList.csv", encoding="shift-jis") as mission:
lines = mission.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
def handle_data_mission_bonus_request(self, data: Dict) -> Dict:
return({"data": ""})
def handle_data_unlimited_mission_request(self, data: Dict) -> Dict:
return({"data": ""})
@cached(lifetime=86400)
def handle_data_event_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/rev_data/Event/EventArchiveList.csv", encoding="shift-jis") as mission:
lines = mission.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
def handle_data_event_music_list_request(self, data: Dict) -> Dict:
return({"data": ""})
def handle_data_event_mission_list_request(self, data: Dict) -> Dict:
return({"data": ""})
def handle_data_event_achievement_single_high_score_list_request(self, data: Dict) -> Dict:
return({"data": ""})
def handle_data_event_achievement_single_accumulation_request(self, data: Dict) -> Dict:
return({"data": ""})
def handle_data_event_ranking_high_score_list_request(self, data: Dict) -> Dict:
return({"data": ""})
def handle_data_event_ranking_accumulation_list_request(self, data: Dict) -> Dict:
return({"data": ""})
def handle_data_event_ranking_stamp_list_request(self, data: Dict) -> Dict:
return({"data": ""})
def handle_data_event_ranking_store_list_request(self, data: Dict) -> Dict:
return({"data": ""})
def handle_data_event_ranking_area_list_request(self, data: Dict) -> Dict:
return({"data": ""})
@cached(lifetime=86400)
def handle_data_event_stamp_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/rev_data/Event/EventStampList.csv", encoding="shift-jis") as event:
lines = event.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
def handle_data_event_stamp_map_list_csxxxx_request(self, data: Dict) -> Dict:
return({"data": "1,2,1,1,2,3,9,5,6,7,8,9,10,\r\n"})
def handle_data_server_state_request(self, data: Dict) -> Dict:
return({"data": True})

Binary file not shown.
1 Cs0000 0 10001 1422284400 4096483201 0 -1 -1 100 0 クリアすると段位が「見習い」に昇格します。 -1
2 Cs0001 1 10001 1422284400 4096483201 0 -1 -1 110 0 クリアすると段位が「初段」に昇格します。 -1
3 Cs0002 2 10001 1422284400 4096483201 0 -1 -1 120 0 クリアすると段位が「二段」に昇格します。 -1
4 Cs0003 3 10001 1422284400 4096483201 0 -1 -1 130 0 クリアすると段位が「三段」に昇格します。 -1
5 Cs0004 4 10001 1422284400 4096483201 0 -1 -1 140 0 クリアすると段位が「四段」に昇格します。 -1
6 Cs0005 5 10001 1422284400 4096483201 0 -1 -1 150 0 クリアすると段位が「五段」に昇格します。 -1
7 Cs0006 6 10001 1422284400 4096483201 0 -1 -1 160 0 クリアすると段位が「六段」に昇格します。 -1
8 Cs0007 7 10001 1422284400 4096483201 0 -1 -1 170 0 クリアすると段位が「七段」に昇格します。 -1
9 Cs0008 8 10001 1422284400 4096483201 0 -1 -1 180 0 クリアすると段位が「八段」に昇格します。 -1
10 Cs0009 9 10001 1422284400 4096483201 0 -1 -1 190 0 クリアすると段位が「九段」に昇格します。 -1

Binary file not shown.
1 1 dazzli 4 1 - -1 -1 2 -1 1 -1 1
2 2 hokoro 0 1 - -1 -1 -1 -1 -1 -1 -1
3 3 sundro 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 sundro 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 1 dazzli 4 1 - -1 -1 2 -1 1 -1 1
2 2 hokoro 0 1 - -1 -1 -1 -1 -1 -1 -1
3 3 sundro 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 sundro 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 1 dazzli 4 1 - -1 -1 2 -1 1 -1 1
2 2 hokoro 0 1 - -1 -1 -1 -1 -1 -1 -1
3 3 sundro 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 sundro 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 1 dazzli 4 1 - -1 -1 2 -1 1 -1 1
2 2 hokoro 0 1 - -1 -1 -1 -1 -1 -1 -1
3 3 sundro 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 sundro 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 1 dazzli 4 1 - -1 -1 2 -1 1 -1 1
2 2 hokoro 0 1 - -1 -1 -1 -1 -1 -1 -1
3 3 sundro 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 sundro 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 1 dazzli 4 1 - -1 -1 2 -1 1 -1 1
2 2 hokoro 0 1 - -1 -1 -1 -1 -1 -1 -1
3 3 sundro 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 sundro 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 1 dazzli 4 1 - -1 -1 2 -1 1 -1 1
2 2 hokoro 0 1 - -1 -1 -1 -1 -1 -1 -1
3 3 sundro 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 sundro 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 1 dazzli 4 1 - -1 -1 2 -1 1 -1 1
2 2 hokoro 0 1 - -1 -1 -1 -1 -1 -1 -1
3 3 sundro 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 sundro 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 1 dazzli 4 1 - -1 -1 2 -1 1 -1 1
2 2 hokoro 0 1 - -1 -1 -1 -1 -1 -1 -1
3 3 sundro 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 sundro 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 1 dazzli 4 1 - -1 -1 2 -1 1 -1 1
2 2 hokoro 0 1 - -1 -1 -1 -1 -1 -1 -1
3 3 sundro 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 sundro 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 Cs1000 0 10000 1443233520 4096483201 1 ev000 1
2 Cs1001 0 10000 1443233520 4096483201 1 ev001 1
3 Cs1002 0 10000 1443233520 4096483201 1 ev002 1
4 Cs1003 0 10000 1443233520 4096483201 1 ev003 1
5 Cs1004 0 10000 1443233520 4096483201 1 ev004 1
6 Cs1005 0 10000 1443233520 4096483201 1 ev005 1
7 Cs1006 0 10000 1443233520 4096483201 1 ev006 1
8 Cs1007 0 10000 1443233520 4096483201 1 ev007 1
9 Cs1008 0 10000 1443233520 4096483201 1 ev008 1
10 Cs1009 0 10000 1443233520 4096483201 1 ev009 1
11 Cs1010 0 10000 1443233520 4096483201 1 ev010 1
12 Cs1011 0 10000 1443233520 4096483201 1 ev011 1
13 Cs1012 0 10000 1443233520 4096483201 1 ev012 1
14 Cs1013 0 10000 1443233520 4096483201 1 ev013 1
15 Cs1014 0 10000 1443233520 4096483201 1 ev014 1
16 Cs1015 0 10000 1443233520 4096483201 1 ev015 1
17 Cs1016 0 10000 1443233520 4096483201 1 ev016 1
18 Cs1017 0 10000 1443233520 4096483201 1 ev017 1
19 Cs1018 0 10000 1443233520 4096483201 1 ev018 1
20 Cs1019 0 10000 1443233520 4096483201 1 ev019 1
21 Cs1020 0 10000 1443233520 4096483201 1 ev020 1
22 Cs1021 0 10000 1443233520 4096483201 1 ev021 1
23 Cs1022 0 10000 1443233520 4096483201 1 ev022 1
24 Cs1023 0 10000 1443233520 4096483201 1 ev023 1
25 Cs1024 0 10000 1443233520 4096483201 1 ev024 1
26 Cs1025 0 10000 1443233520 4096483201 1 ev025 1
27 Cs1026 0 10000 1443233520 4096483201 1 ev026 1
28 Cs1027 0 10000 1443233520 4096483201 1 ev027 1
29 Cs1028 0 10000 1443233520 4096483201 1 ev028 1
30 Cs1029 0 10000 1443233520 4096483201 1 ev029 1
31 Cs1030 0 10000 1443233520 4096483201 1 ev030 1
32 Cs1031 0 10000 1443233520 4096483201 1 ev031 1
33 Cs1032 0 10000 1443233520 4096483201 1 ev032 1
34 Cs1033 0 10000 1443233520 4096483201 1 ev033 1
35 Cs1034 0 10000 1443233520 4096483201 1 ev034 1
36 Cs1035 0 10000 1443233520 4096483201 1 ev035 1
37 Cs1036 0 10000 1443233520 4096483201 1 ev036 1
38 Cs1037 0 10000 1443233520 4096483201 1 ev037 1
39 Cs1038 0 10000 1443233520 4096483201 1 ev038 1

Binary file not shown.
1 Cs1000 1 1 1 1 1 1 1 1 1 1
2 Cs1001 1 1 1 1 1 1 1 1 1 1
3 Cs1002 1 1 1 1 1 1 1 1 1 1
4 Cs1003 1 1 1 1 1 1 1 1 1 1
5 Cs1004 1 1 1 1 1 1 1 1 1 1
6 Cs1005 1 1 1 1 1 1 1 1 1 1
7 Cs1006 1 1 1 1 1 1 1 1 1 1
8 Cs1007 1 1 1 1 1 1 1 1 1 1
9 Cs1008 1 1 1 1 1 1 1 1 1 1
10 Cs1009 1 1 1 1 1 1 1 1 1 1
11 Cs1010 1 1 1 1 1 1 1 1 1 1
12 Cs1011 1 1 1 1 1 1 1 1 1 1
13 Cs1012 1 1 1 1 1 1 1 1 1 1
14 Cs1013 1 1 1 1 1 1 1 1 1 1
15 Cs1014 1 1 1 1 1 1 1 1 1 1
16 Cs1015 1 1 1 1 1 1 1 1 1 1
17 Cs1016 1 1 1 1 1 1 1 1 1 1
18 Cs1017 1 1 1 1 1 1 1 1 1 1
19 Cs1018 1 1 1 1 1 1 1 1 1 1
20 Cs1019 1 1 1 1 1 1 1 1 1 1
21 Cs1020 1 1 1 1 1 1 1 1 1 1
22 Cs1021 1 1 1 1 1 1 1 1 1 1
23 Cs1022 1 1 1 1 1 1 1 1 1 1
24 Cs1023 1 1 1 1 1 1 1 1 1 1
25 Cs1024 1 1 1 1 1 1 1 1 1 1
26 Cs1025 1 1 1 1 1 1 1 1 1 1
27 Cs1026 1 1 1 1 1 1 1 1 1 1
28 Cs1027 1 1 1 1 1 1 1 1 1 1
29 Cs1028 1 1 1 1 1 1 1 1 1 1
30 Cs1029 1 1 1 1 1 1 1 1 1 1
31 Cs1030 1 1 1 1 1 1 1 1 1 1
32 Cs1031 1 1 1 1 1 1 1 1 1 1
33 Cs1032 1 1 1 1 1 1 1 1 1 1
34 Cs1033 1 1 1 1 1 1 1 1 1 1
35 Cs1034 1 1 1 1 1 1 1 1 1 1
36 Cs1035 1 1 1 1 1 1 1 1 1 1
37 Cs1036 1 1 1 1 1 1 1 1 1 1
38 Cs1037 1 1 1 1 1 1 1 1 1 1
39 Cs1038 1 1 1 1 1 1 1 1 1 1

Binary file not shown.
1 StageMax,ClearCount,StageNo.,MCODE,Diff(std),Diff(hrd),Diff(mas),Diff(ulm),Diff(esy),Level(op), Level(val), Grade(op),Grade(val),GT(nml),GT(svl),GT(ult),GT(nhp),GT(esy),HS(op),HS(val),APP,DAP,F-V,F-H,FT(ac),FT(tab),FT(pho),Combo(op),Combo(val),FullCombo,ClearRate(op),ClearRate(val)
2 2,1,1,-,2,2,2,1,2,-1,-,1,1,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,1,300,-1,-1,-,
3 2,-,2,-,2,2,2,1,2,-1,-,1,1,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,1,300,-1,-1,-,
4 3,3,1,-,2,2,1,1,2,-1,-,1,2,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
5 3,-,2,-,2,2,1,1,2,-1,-,1,2,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
6 3,-,3,-,2,2,1,1,2,1,50,1,2,2,2,1,2,2,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
7 4,4,1,dynami:fronti:rebell:fronti2:auflcb:auflcb2,2,2,1,1,2,-1,-,1,-1,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
8 4,-,2,-,2,2,1,1,2,-1,-,1,-1,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
9 4,-,3,-,2,2,1,1,2,-1,-,1,-1,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
10 4,-,4,-,2,2,1,1,2,-1,-,1,-1,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,

Binary file not shown.
1 StageMax,ClearCount,StageNo.,MCODE,Diff(std),Diff(hrd),Diff(mas),Diff(ulm),Diff(esy),Level(op), Level(val), Grade(op),Grade(val),GT(nml),GT(svl),GT(ult),GT(nhp),GT(esy),HS(op),HS(val),APP,DAP,F-V,F-H,FT(ac),FT(tab),FT(pho),Combo(op),Combo(val),FullCombo,ClearRate(op),ClearRate(val)
2 2,1,1,-,2,2,1,1,2,1,50,-1,-,2,2,1,2,2,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,1,-1,-,
3 2,-,2,-,2,2,1,1,2,1,50,-1,-,2,2,1,2,2,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,1,-1,-,
4 3,3,1,-,2,2,1,1,2,1,,-1,-,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
5 3,-,2,-,2,2,1,1,2,1,,-1,-,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
6 3,-,3,-,2,2,1,1,2,1,,-1,-,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
7 4,4,1,dynami:fronti:rebell:fronti2:auflcb:auflcb2,2,2,1,1,2,1,,-1,-,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
8 4,-,2,-,2,2,1,1,2,1,,-1,-,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
9 4,-,3,-,2,2,1,1,2,1,,-1,-,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
10 4,-,4,-,2,2,1,1,2,1,,-1,-,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,

Binary file not shown.
1 No.,Ver.,ESID,Title,StartTime,EndTime,出現曲MCODE,出現RP,出現エフェクト,Diff(std),Diff(hrd),Diff(mas),Diff(ulm),Diff(esy),GT(nml),GT(svl),GT(ult),GT(nhp),GT(esy),HS(op),HS(val),APP,DAP,F-V,F-H,FT(ac),FT(tab),FT(pho)
2 1,1000,Ex0000,MEGALOMAN[i]A出現,1411697520.0288,1443233520.0288,megaro,0,3,2,2,1,2,2,2,2,1,2,2,1,-2,-1,-1,-1,-1,-1,-1,-1,

Binary file not shown.
1 1000 ic0000 IconName0000
2 1001 ic0001 IconName0001
3 1002 ic0002 IconName0002

Binary file not shown.
1 3000 skb0000 SkinName0000
2 3001 skb0001 SkinName0001
3 3002 skb0002 SkinName0002

Binary file not shown.
1 5000 ske0000 SkinName0000
2 5001 ske0001 SkinName0001
3 5002 ske0002 SkinName0002

Binary file not shown.
1 4000 skt0000 SkinName0000
2 4001 skt0001 SkinName0001
3 4002 skt0002 SkinName0002

Binary file not shown.
1 2000 スーパーゴリラ 4
2 2001 ふつうのゴリラ 3
3 2002 モンキー 0

Binary file not shown.
1 英雄の証 ~ 4Version/カプコンサウンドチーム
2 © CAPCOM CO., LTD. ALL RIGHTS RESERVED.
3
4 灼熱の刃 ~ ディノバルド
5 © CAPCOM CO., LTD. ALL RIGHTS RESERVED.
6
7 古代の息吹き
8 © CAPCOM CO., LTD. ALL RIGHTS RESERVED.
9
10 Theme of Ryu -SFIV Arrange-/Capcom Sound Team / Hideyuki Fukasawa
11 ©CAPCOM U.S.A., INC. ALL RIGHTS RESERVED.
12
13 Ultra Street Fighter IV/Hideyuki Fukasawa
14 ©CAPCOM U.S.A., INC. ALL RIGHTS RESERVED.
15
16 Theme of Chun-Li -SFIV Arrange-/Capcom Sound Team / Hideyuki Fukasawa
17 ©CAPCOM U.S.A., INC. ALL RIGHTS RESERVED.
18
19 Street Fighter V/Masahiro Aoki
20 ©CAPCOM U.S.A., INC. ALL RIGHTS RESERVED.
21
22 英雄の証/MHF-G 2015 Version
23 © CAPCOM CO., LTD. ALL RIGHTS RESERVED.
24
25 異ヲ辿リシモノ -対峙-/若林タカツグ
26 © CAPCOM CO., LTD. ALL RIGHTS RESERVED.
27
28
29
30
31
32
33
34
35
36
37
38
39
40 QLWA(グルーヴコースター 3 リンクフィーバーより)/t+pazolite
41 © TAITO CORPORATION 1978,2016 ALL RIGHTS RESERVED.
42
43 グルーヴ・ザ・ハート(グルーヴコースター 3 リンクフィーバーより)/ビートまりお+あまね
44 © TAITO CORPORATION 1978,2016 ALL RIGHTS RESERVED.
45
46 Got hive of Ra(グルーヴコースター 3 リンクフィーバーより)/E.G.G.
47 © TAITO CORPORATION 1978,2016 ALL RIGHTS RESERVED.
48
49 LINK LINK FEVER!!!(グルーヴコースター 3 リンクフィーバーより)/リンカ (CV:豊田萌絵)
50 © TAITO CORPORATION 1978,2016 ALL RIGHTS RESERVED.
51
52 SAKURA EXHAUST/RIO HAMAMOTO(BNSI)「太鼓の達人」より
53 ©BANDAI NAMCO Entertainment Inc.
54
55 カリソメ(グルーヴコースター 3 リンクフィーバーより)/コンプ(豚乙女) × ichigo(岸田教団 & THE明星ロケッツ)
56 ©上海アリス幻樂団
57 © TAITO CORPORATION 1978,2016 ALL RIGHTS RESERVED.
58
59 そして誰もいなくなった(グルーヴコースター 3 リンクフィーバーより)/コバヤシユウヤ(IOSYS) × あにー(TaNaBaTa)
60 ©上海アリス幻樂団
61 © TAITO CORPORATION 1978,2016 ALL RIGHTS RESERVED.
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 Font Design by Fontworks Inc.
80 DynaFont is a registered Trademark of DynaComware Taiwan Inc.
81 Ogg Vorbis is Copyright ©2015, Xiph. Org Foundation
82 The font used on this product is provided by Hakusyu Fonts co,.Ltd.
83 キャスティング・ライツクリアランス
84 株式会社ビーイング
85 JASRAC許諾第V-1512134号
86 e-License許諾番号GS35000
87 VOCALOID and VOCALO are trademarks of Yamaha Corporation.
88
89 OMNiMIX v1.2

Binary file not shown.
1 MissionID,Text,Type,Value_op,Value,Mcode,Difficulty_op,Difficulty,Level_op,Level,Grade_op,Grade,GaugeType_op,GaugeType,HiSpeed_op,HiSpeed,APP,DAP,FlipV,FlipH,Fullcombo,Combo_op,Combo,ClearRate_op,ClearRate,StartTime,StartEnd,District,CoupleId
2 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,
3 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,
4 2,ExtraStage‚ÅMEGALOMAN[i]A‚ðƒNƒŠƒA‚·‚é,0,-1,-1,megaro,-1,-1,-1,-1,1,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

Binary file not shown.
1 tutori2 10000 100000 10 10 10 10 10 0 0 0 0 0 0 100000
2 tutori3 10000 100000 10 10 10 10 10 0 0 0 0 0 0 100000
3 tutori4 10000 100000 10 10 10 10 10 0 0 0 0 0 0 100000
4 tutori8 10000 1000000 30 150 350 0 0 1 1 1 0 0 0 100345
5 sateli 10000 100000 280 490 770 820 170 1 1 1 1 1 0 100300
6 nature 10000 100000 140 240 530 750 50 1 1 1 1 1 3 100301
7 purple 10000 100000 220 540 640 730 140 1 1 1 1 1 0 100307
8 hearts 10000 100000 180 380 680 770 80 1 1 1 1 1 0 100308
9 phasea 10000 100000 160 380 650 750 90 1 1 1 1 1 0 100310
10 planet 10000 100000 170 360 490 710 100 1 1 1 1 1 1 100311
11 firefo 10000 100000 130 360 570 830 70 1 1 1 1 1 0 100314
12 kounen 10000 100000 210 400 660 780 100 1 1 1 1 1 3 100315
13 essenc 10000 100000 250 500 700 760 110 1 1 1 1 1 0 100316
14 summer 10000 100000 230 570 790 890 130 1 1 1 1 1 0 100317
15 tanosi 10000 100000 250 450 700 800 160 1 1 1 1 1 7 100319
16 picora 10000 100000 150 380 660 750 80 1 1 1 1 1 1 100320
17 devils 10000 100000 270 400 800 0 150 1 1 1 0 1 0 100323
18 techno 10000 100000 160 380 510 740 90 1 1 1 1 1 1 100328
19 glowww 10000 100000 170 280 420 600 80 1 1 1 1 1 7 100335
20 powerr 10000 100000 190 380 690 790 120 1 1 1 1 1 0 100336
21 amater 10000 100000 210 480 650 790 130 1 1 1 1 1 0 100340
22 advers 10000 100000 150 480 710 830 90 1 1 1 1 1 1 100349
23 venera 10000 100000 150 430 680 750 80 1 1 1 1 1 0 100353
24 dazaii 10000 100000 210 430 730 770 120 1 1 1 1 1 3 100357
25 thesig 10000 100000 210 380 560 730 100 1 1 1 1 1 3 100365
26 hosita 10000 100000 160 360 480 650 100 1 1 1 1 1 9999 100344
27 bluede 10000 100000 220 410 580 700 120 1 1 1 1 1 5 100372
28 emerao 10000 100000 300 530 850 0 190 1 1 1 0 1 1 100373
29 megaro 10000 100000 550 800 930 980 0 1 1 1 1 0 0 100129
30 angeli 10000 100000 330 560 820 900 220 1 1 1 1 1 0 100330
31 moonli 10000 100000 140 430 610 730 80 1 1 1 1 1 9999 100342
32 yumemi 10000 100000 120 350 590 690 60 1 1 1 1 1 9999 100369
33 pinkym 10000 100000 240 440 740 810 160 1 1 1 1 1 0 100348
34 dynami2 10000 100000 180 510 780 800 80 1 1 1 1 1 0 100370
35 reseed3 10000 100000 200 550 760 800 100 1 1 1 1 1 0 100306
36 toucho 10000 200000 90 280 440 650 50 1 1 1 1 1 1 100002
37 ameoto 10000 200000 120 260 470 630 60 1 1 1 1 1 1 100003
38 kimito 10000 200000 100 260 490 660 70 1 1 1 1 1 1 100004
39 giantk 10000 200000 250 530 710 780 110 1 1 1 1 1 3 100021
40 breakd 10000 200000 230 340 570 740 110 1 1 1 1 1 2 100015
41 dazzlj 10000 200000 350 600 800 900 160 1 1 1 1 1 1 100028
42 ididid 10000 200000 290 460 720 810 160 1 1 1 1 1 1 100093
43 sundro 10000 200000 240 470 750 830 140 1 1 1 1 1 3 100042
44 auflcb 10000 200000 130 430 810 0 80 1 1 1 0 1 0 100063
45 dennou 10000 200000 290 600 760 870 150 1 1 1 1 1 1 100045
46 hokoro 10000 200000 290 570 710 810 140 1 1 1 1 1 1 100068
47 landin 10000 200000 260 330 490 670 130 1 1 1 1 1 1 100005
48 tomorr 10000 100000 150 240 440 620 80 1 1 1 1 1 7 100362
49 daybyd 10000 100000 130 260 380 590 60 1 1 1 1 1 7 100363
50 syoujo 10000 100000 190 350 530 780 80 1 1 1 1 1 1 100309
51 destru 10000 100000 190 410 620 720 100 1 1 1 1 1 0 100352
52 gingat 10000 200000 130 290 460 610 50 1 1 1 1 1 0 100041
53 daisak 10000 200000 280 360 600 750 120 1 1 1 1 1 0 100066
54 paradi 10000 100000 160 280 530 640 100 1 1 1 1 1 3 100376
55 pigooo 10000 100000 190 340 590 840 130 1 1 1 1 1 6 100377
56 season 10000 300000 150 280 440 650 80 1 1 1 1 1 1 100386
57 canonn 10000 300000 170 280 500 830 70 1 1 1 1 1 1 100387
58 rhapso 10000 300000 180 340 620 740 60 1 1 1 1 1 1 100388
59 turkis 10000 300000 190 390 640 840 110 1 1 1 1 1 1 100389
60 biohaz 10000 300000 150 300 510 640 60 1 1 1 1 1 9999 100390
61 monhan 10000 300000 100 260 360 540 50 1 1 1 1 1 9999 100391
62 gyakut2 10000 300000 130 350 430 560 50 1 1 1 1 1 9999 100392
63 street 10000 300000 130 340 470 660 70 1 1 1 1 1 9999 100393
64 rockma2 10000 300000 210 340 490 760 140 1 1 1 1 1 9999 100394
65 auflcb3 10000 100000 160 360 660 860 60 1 1 1 1 1 9999 100374
66 irohaa 10000 100000 190 410 550 760 120 1 1 1 1 1 0 100325
67 ibelie 10000 100000 270 470 780 820 140 1 1 1 1 1 0 100326
68 monhan2 10000 300000 120 240 430 680 60 1 1 1 1 1 9999 100409
69 monhan3 10000 300000 180 280 450 730 80 1 1 1 1 1 9999 100410
70 yejiii 10000 100000 220 360 630 790 100 1 1 1 1 1 0 100418
71 histor 10000 100000 200 360 560 820 110 1 1 1 1 1 0 100419
72 chaset 10000 100000 150 310 580 760 80 1 1 1 1 1 9999 100338
73 metall 10000 100000 160 280 570 770 80 1 1 1 1 1 1 100412
74 letmeg 10000 100000 180 320 500 720 120 1 1 1 1 1 1 100327
75 hontno 10000 200000 120 260 530 660 90 1 1 1 1 1 1 100010
76 azitat 10000 200000 240 550 700 830 140 1 1 1 1 1 0 100024
77 hellom 10000 100000 180 370 580 720 70 1 1 1 1 1 1 100360
78 laught 10000 100000 200 350 510 710 70 1 1 1 1 1 1 100337
79 bluede2 10000 100000 160 360 560 810 90 1 1 1 1 1 1 100426
80 street2 10000 300000 210 370 550 730 140 1 1 1 1 1 9999 100423
81 street3 10000 300000 240 380 570 740 130 1 1 1 1 1 9999 100424
82 street4 10000 300000 170 320 510 780 110 1 1 1 1 1 9999 100425
83 silbur 10000 100000 200 350 540 750 90 1 1 1 1 1 1 100421
84 spicaa 10000 100000 230 360 560 780 100 1 1 1 1 1 1 100422
85 tricko 10000 100000 230 340 560 750 110 1 1 1 1 1 0 100438
86 thisis 10000 100000 230 370 600 740 120 1 1 1 1 1 4 100435
87 rising 10000 100000 230 380 660 850 140 1 1 1 1 1 4 100436
88 orbita 10000 100000 200 380 620 740 120 1 1 1 1 1 5 100411
89 dddddd 10000 100000 130 330 530 690 90 1 1 1 1 1 5 100433
90 pyroma 10000 100000 220 420 700 840 80 1 1 1 1 1 4 100427
91 touchn 10000 100000 270 460 680 860 150 1 1 1 1 1 8 100312
92 onlyll 10000 100000 210 320 560 690 130 1 1 1 1 1 9999 100359
93 upside 10000 100000 180 270 480 670 80 1 1 1 1 1 1 100313
94 istanb 10000 100000 410 490 900 980 230 1 1 1 1 1 3 100322
95 memori 10000 100000 260 380 650 840 130 1 1 1 1 1 9999 100371
96 straye 10000 100000 250 360 610 730 140 1 1 1 1 1 4 100350
97 rearhy 10000 100000 170 320 520 690 70 1 1 1 1 1 9999 100358
98 hereco 10000 100000 160 340 510 680 110 1 1 1 1 1 4 100432
99 thesun 10000 100000 250 400 720 870 130 1 1 1 1 1 4 100441
100 sayona 10000 100000 200 340 530 710 100 1 1 1 1 1 9999 100343
101 flameu 10000 100000 180 360 570 650 100 1 1 1 1 1 1 100380
102 raidon 10000 100000 300 380 580 870 130 1 1 1 1 1 1 100434
103 riseup 10000 100000 180 410 670 770 70 1 1 1 1 1 4 100437
104 sunglo 10000 100000 180 390 590 720 100 1 1 1 1 1 7 100431
105 kinbos 10000 100000 220 380 640 770 120 1 1 1 1 1 3 100439
106 densho 10000 100000 280 420 740 900 170 1 1 1 1 1 5 100430
107 aiohoo 10000 300000 180 290 420 660 100 1 1 1 1 1 1 100471
108 entert 10000 300000 150 330 540 870 90 1 1 1 1 1 6 100472
109 takeit 10000 100000 200 380 650 830 120 1 1 1 1 1 4 100457
110 harmon 10000 100000 200 360 490 650 120 1 1 1 1 1 7 100449
111 avemar 10000 300000 160 310 530 750 80 1 1 1 1 1 5 100428
112 mateki 10000 300000 180 350 540 790 100 1 1 1 1 1 5 100429
113 lovech 10000 100000 160 300 460 680 80 1 1 1 1 1 7 100445
114 akaihe 10000 300000 210 320 500 690 80 1 1 1 1 1 1 100473
115 juicys 10000 300000 180 260 450 830 100 1 1 1 1 1 7 100474
116 codena 10000 100000 180 350 480 680 90 1 1 1 1 1 1 100468
117 groove 10000 300000 220 400 520 730 100 1 1 1 1 1 103 100475
118 kansho 10000 100000 130 270 550 740 70 1 1 1 1 1 9999 100450
119 overcl2 10000 100000 230 420 580 740 120 1 1 1 1 1 3 100486
120 taikoo 10000 300000 130 390 500 750 60 1 1 1 1 1 104 100483
121 groove2 10000 300000 150 400 580 850 90 1 1 1 1 1 9999 100480
122 overcl 10000 100000 120 350 570 860 80 1 1 1 1 1 4 100487
123 notoss 10000 100000 120 420 650 910 80 1 1 1 1 1 4 100466
124 machup 10000 100000 170 320 410 710 90 1 1 1 1 1 6 100447
125 groove3 10000 300000 180 340 640 850 100 1 1 1 1 1 105 100488
126 groove4 10000 300000 220 350 500 750 120 1 1 1 1 1 106 100489
127 everyt 10000 100000 220 300 740 0 130 1 1 1 0 1 5 100482
128 lespri 10000 100000 250 570 800 0 130 1 1 1 0 1 5 100465
129 groove5 10000 300000 240 370 670 0 140 1 1 1 0 1 0 100491
130 honeyo 10000 100000 320 630 880 930 240 1 1 1 1 1 6 100490
131 groove6 10000 300000 300 640 790 0 220 1 1 1 0 1 3 100494
132 sunglo2 10000 100000 210 360 670 810 110 1 1 1 1 1 6 100495
133 fourte 10000 100000 240 500 740 800 140 1 1 1 1 1 5 100498
134 monhan4 10000 300000 120 400 510 620 50 1 1 1 1 1 9999 100496
135 monhan5 10000 300000 120 350 420 650 100 1 1 1 1 1 9999 100497
136 darkpa 10000 100000 260 390 700 840 160 1 1 1 1 1 3 100504
137 hervor 10000 100000 280 390 730 810 180 1 1 1 1 1 5 100505
138 cirnon 10000 300000 240 400 600 790 170 1 1 1 1 1 9999 100499
139 marisa 10000 300000 250 410 620 850 180 1 1 1 1 1 9999 100500
140 yakini 10000 300000 250 340 580 820 130 1 1 1 1 1 9999 100501
141 justic 10000 300000 190 360 570 830 140 1 1 1 1 1 1 100502
142 sintyo 10000 300000 250 460 700 830 160 1 1 1 1 1 6 100503
143 ascand 10000 100000 320 540 800 900 180 1 1 1 1 1 0 100347
144 blackl 10000 100000 190 410 730 840 120 1 1 1 1 1 3 100506
145 childr 10000 200000 240 390 560 620 140 1 1 1 1 1 0 100043
146 tsukai 10000 200000 190 440 720 760 130 1 1 1 1 1 1 100044
147 rideon 10000 200000 290 410 600 800 160 1 1 1 1 1 1 100067
148 minest 10000 100000 210 390 620 760 130 1 1 1 1 1 1 100507
149 ordine 10000 100000 250 430 730 820 190 1 1 1 1 1 3 100508
150 dreamw 10000 100000 260 370 620 750 160 1 1 1 1 1 0 100509
151 minerv 10000 100000 320 610 900 0 250 1 1 1 0 1 4 100510
152 wannab 10000 200000 90 230 400 650 50 1 1 1 1 1 3 100001
153 sekain 10000 100000 260 390 690 780 160 1 1 1 1 1 1 100511
154 farawa 10000 100000 230 360 600 760 180 1 1 1 1 1 7 100512
155 crissc 10000 200000 370 630 860 910 170 1 1 1 1 1 4 100100
156 speedy 10000 100000 220 550 770 0 110 1 1 1 0 1 8 100324
157 xxxrev 10000 100000 210 340 560 730 150 1 1 1 1 1 0 100513
158 higame 10000 200000 200 300 580 710 130 1 1 1 1 1 3 100016
159 theepi 10000 200000 190 400 610 750 140 1 1 1 1 1 3 100022
160 anomie 10000 200000 220 380 610 770 150 1 1 1 1 1 0 100023
161 crocus 10000 100000 260 370 600 720 150 1 1 1 1 1 7 100524
162 lavien 10000 100000 270 410 710 800 180 1 1 1 1 1 5 100546
163 megaro2 10000 100000 0 0 990 1000 0 0 0 1 1 0 4 100361
164 chipnn 10000 100000 270 340 610 790 160 1 1 1 1 1 6 100541
165 yiyoyi 10000 200000 140 330 560 700 70 1 1 1 1 1 3 100007
166 binary 10000 200000 170 350 640 890 140 1 1 1 1 1 1 100014
167 makaim 10000 200000 300 500 770 0 230 1 1 1 0 1 3 100054
168 gyakut 10000 200000 150 210 460 640 60 1 1 1 1 1 1 100055
169 basara 10000 200000 190 370 640 730 140 1 1 1 1 1 0 100056
170 daybre 10000 300000 160 320 530 720 90 1 1 1 1 1 0 100514
171 umiyur 10000 300000 140 280 460 640 80 1 1 1 1 1 1 100515
172 chalur 10000 300000 180 400 600 720 140 1 1 1 1 1 9999 100516
173 melanc 10000 300000 150 300 500 630 100 1 1 1 1 1 7 100517
174 konofu 10000 300000 230 350 620 810 110 1 1 1 1 1 1 100518
175 bladem 10000 100000 280 380 630 750 170 1 1 1 1 1 4 100526
176 southw 10000 100000 180 270 570 680 120 1 1 1 1 1 7 100536
177 ryuuse 10000 100000 210 320 590 0 130 1 1 1 0 1 1 100537
178 redhea 10000 300000 270 390 590 720 100 1 1 1 1 1 0 100519
179 warnin 10000 300000 250 360 610 740 120 1 1 1 1 1 9999 100520
180 topsec 10000 300000 240 340 510 640 130 1 1 1 1 1 9999 100521
181 dddoll 10000 300000 260 380 550 630 140 1 1 1 1 1 9999 100522
182 tracee 10000 300000 190 310 490 650 90 1 1 1 1 1 0 100548
183 drivin 10000 200000 230 400 660 760 80 1 1 1 1 1 7 100111
184 genzit 10000 200000 180 460 730 820 120 1 1 1 1 1 0 100118
185 aerial 10000 200000 110 280 560 710 50 1 1 1 1 1 1 100039
186 einher 10000 100000 290 400 740 800 160 1 1 1 1 1 4 100532
187 ariell 10000 100000 190 320 640 730 150 1 1 1 1 1 7 100540
188 firstl 10000 100000 250 360 650 770 170 1 1 1 1 1 1 100542
189 heartl 10000 100000 230 300 640 0 110 1 1 1 0 1 1 100550
190 erasee 10000 100000 220 350 580 680 120 1 1 1 1 1 0 100551
191 regene 10000 100000 200 300 560 700 130 1 1 1 1 1 0 100530
192 allelu 10000 100000 280 350 640 750 160 1 1 1 1 1 9999 100549
193 lighto 10000 100000 250 330 600 740 120 1 1 1 1 1 1 100543
194 termin 10000 100000 240 340 630 790 130 1 1 1 1 1 7 100552
195 ryuuse2 10000 100000 200 360 620 750 130 1 1 1 1 1 1 100556
196 prizmm 10000 100000 210 300 540 0 120 1 1 1 0 1 1 100547
197 samalv 10000 200000 190 390 580 770 130 1 1 1 1 1 6 100098
198 palpit 10000 100000 290 550 840 920 180 1 1 1 1 1 8 100544
199 gainen 10000 100000 260 370 630 0 150 1 1 1 0 1 9999 100558
200 moonsh 10000 100000 230 360 620 0 100 1 1 1 0 1 3 100525
201 moonki 10000 100000 250 390 640 0 130 1 1 1 0 1 1 100559
202 moonri 10000 200000 210 380 580 850 140 1 1 1 1 1 0 100560
203 goaway 10000 100000 230 450 590 700 100 1 1 1 1 1 0 100561
204 itback 10000 100000 230 380 710 0 120 1 1 1 0 1 3 100567
205 redhhh 10000 100000 240 390 770 0 130 1 1 1 0 1 4 100569
206 actual 10000 100000 250 380 800 0 140 1 1 1 0 1 0 100568
207 zonzon 10000 200000 160 330 630 670 50 1 1 1 1 1 1 100367
208 memorm 10000 100000 260 370 730 0 150 1 1 1 0 1 0 100565
209 kokoro 10000 100000 200 430 650 690 120 1 1 1 1 1 1 100554
210 poweri 10000 100000 260 490 750 910 130 1 1 1 1 1 4 100563
211 nisenn 10000 100000 0 0 760 0 0 0 0 1 0 0 8 100555
212 yukiya 10000 200000 190 400 610 0 110 1 1 1 0 1 3 100096
213 zankyo 10000 200000 180 380 570 740 100 1 1 1 1 1 5 100124
214 overlp 10000 200000 170 300 510 0 90 1 1 1 0 1 7 100119
215 fracta 10000 100000 310 520 830 0 190 1 1 1 0 1 3 100529
216 cantst 10000 100000 230 420 650 0 110 1 1 1 0 1 0 100455
217 primaa 10000 100000 180 350 540 750 120 1 1 1 1 1 0 100527
218 cyberg 10000 100000 230 350 600 0 120 1 1 1 0 1 0 100448
219 freakw 10000 200000 220 420 650 660 130 1 1 1 1 1 0 100018
220 aquali 10000 200000 160 340 580 0 110 1 1 1 0 1 4 100006
221 takesc 10000 100000 270 370 690 0 100 1 1 1 0 1 1 100572
222 cthugh 10000 100000 250 480 730 0 140 1 1 1 0 1 0 100531
223 thetaa 10000 100000 210 340 620 0 110 1 1 1 0 1 1 100571
224 nekofu 10000 300000 220 340 570 800 100 1 1 1 1 1 6 100493
225 howtru 10000 200000 120 250 530 740 80 1 1 1 1 1 0 100057
226 romanc 10000 200000 280 550 780 0 100 1 1 1 0 1 0 100047
227 kotobu 10000 200000 320 710 900 0 250 1 1 1 0 1 0 100573
228 xmasss 10000 300000 180 380 560 770 80 1 1 1 1 1 101 100417
229 galaxy 10000 300000 160 320 430 670 100 1 1 1 1 1 0 100600
230 rebell 10000 1000000 490 630 910 0 0 1 1 1 0 0 0 100601
231 anothe 10000 1000000 270 370 730 760 0 1 1 1 1 0 0 100602
232 addict 10000 1000000 200 340 520 620 0 1 1 1 1 0 0 100603
233 dirtyy 10000 1000000 150 280 590 740 0 1 1 1 1 0 0 100604
234 levelf 10000 300000 110 280 450 630 50 1 1 1 1 1 0 100605
235 omnive 10000 1000000 340 520 830 860 0 1 1 1 1 0 0 100606
236 kakuse 10000 1000000 170 550 750 0 0 1 1 1 0 0 0 100607
237 unbeli 10000 300000 130 260 380 620 70 1 1 1 1 1 0 100608
238 sonzai 10000 1000000 260 400 590 660 0 1 1 1 1 0 0 100609
239 okonik 10000 1000000 260 450 670 0 0 1 1 1 0 0 0 100610
240 crssho 10000 1000000 350 600 850 0 100 1 1 1 0 1 0 100611
241 reanim 10000 1000000 280 440 700 800 0 1 1 1 1 0 0 100612
242 kamino 10000 1000000 400 620 780 0 150 1 1 1 0 1 0 100613
243 fiveee 10000 300000 180 370 610 710 100 1 1 1 1 1 0 100614
244 granda 10000 1000000 210 380 790 0 0 1 1 1 0 0 0 100615
245 fronti2 10000 1000000 460 690 890 0 90 1 1 1 0 1 0 100616
246 saigon 10000 1000000 190 310 570 0 0 1 1 1 0 0 0 100617
247 replay 10000 300000 180 440 630 700 80 1 1 1 1 1 0 100618
248 mousou 10000 1000000 160 260 540 0 0 1 1 1 0 0 0 100619
249 aheadd 10000 300000 130 250 350 580 70 1 1 1 1 1 0 100620
250 musicr1 10000 100000 220 330 580 740 120 1 1 1 1 1 0 100621
251 getthe 10000 300000 170 370 490 660 60 1 1 1 1 1 0 100622
252 design 10000 1000000 150 390 680 690 0 1 1 1 1 0 0 100623
253 garnet 10000 1000000 260 460 700 940 0 1 1 1 1 0 0 100624
254 hopesb 10000 300000 100 250 440 610 70 1 1 1 1 1 0 100625
255 shooti 10000 300000 150 370 490 690 70 1 1 1 1 1 0 100626
256 dangan 10000 1000000 280 580 810 0 0 1 1 1 0 0 0 100627
257 impact 10000 1000000 240 600 720 900 200 1 1 1 1 1 0 100628
258 lightm 10000 300000 260 330 540 710 110 1 1 1 1 1 0 100629
259 miiroo 10000 300000 220 390 580 680 110 1 1 1 1 1 0 100630
260 voiceo 10000 1000000 180 340 580 590 0 1 1 1 1 0 0 100631
261 cosmol 10000 1000000 360 640 870 0 250 1 1 1 0 1 0 100632
262 vividd 10000 300000 160 350 550 650 90 1 1 1 1 1 0 100633
263 splash 10000 1000000 260 500 710 0 0 1 1 1 0 0 0 100634
264 donuth 10000 300000 220 400 540 800 110 1 1 1 1 1 0 100635
265 senbon 10000 300000 200 280 540 740 120 1 1 1 1 1 0 100636
266 kmtyju 10000 300000 240 310 570 740 120 1 1 1 1 1 0 100637
267 fronti 10000 1000000 480 650 820 0 130 1 1 1 0 1 0 100638
268 nueraa 10000 1000000 220 430 750 530 0 1 1 1 1 0 0 100639
269 childe 10000 300000 90 240 340 560 40 1 1 1 1 1 0 100640
270 dazzli2 10000 1000000 350 600 820 0 190 1 1 1 0 1 0 100641
271 perfec 10000 1000000 390 640 780 0 0 1 1 1 0 0 0 100642
272 flower 10000 300000 70 200 400 650 60 1 1 1 1 1 0 100643
273 frgmnt 10000 1000000 330 630 740 650 100 1 1 1 1 1 0 100644
274 headph 10000 1000000 240 320 520 0 0 1 1 1 0 0 0 100645
275 crsang 10000 1000000 270 530 670 0 130 1 1 1 0 1 0 100646
276 musicr4 10000 100000 190 320 580 0 120 1 1 1 0 1 0 100647
277 imaxim 10000 1000000 440 690 900 870 0 1 1 1 1 0 0 100648
278 azitat2 10000 1000000 230 520 660 0 80 1 1 1 0 1 0 100649
279 dynami 10000 1000000 260 540 680 0 110 1 1 1 0 1 0 100650
280 incave 10000 1000000 220 440 760 780 0 1 1 1 1 0 0 100651
281 aktuki 10000 1000000 260 580 840 0 100 1 1 1 0 1 0 100652
282 kindof 10000 1000000 140 290 480 0 0 1 1 1 0 0 0 100653
283 mikaku 10000 1000000 190 310 540 0 0 1 1 1 0 0 0 100654
284 strang 10000 1000000 120 280 550 0 0 1 1 1 0 0 0 100655
285 hesper 10000 1000000 360 610 920 930 0 1 1 1 1 0 0 100656
286 breaka 10000 300000 150 310 450 680 70 1 1 1 1 1 0 100657
287 myname 10000 1000000 60 140 300 570 0 1 1 1 1 0 0 100658
288 amaiko 10000 1000000 150 370 600 0 0 1 1 1 0 0 0 100659
289 reseed2 10000 1000000 220 470 630 0 0 1 1 1 0 0 0 100660
290 kingst 10000 1000000 380 630 740 0 120 1 1 1 0 1 0 100661
291 ramram 10000 1000000 230 340 670 0 0 1 1 1 0 0 0 100662
292 murasa 10000 1000000 280 410 760 0 0 1 1 1 0 0 0 100663
293 happyd 10000 1100000 220 410 730 790 180 1 1 1 1 1 0 100664
294 izimed 10000 300000 190 390 690 770 90 1 1 1 1 1 0 100665
295 wastel 10000 1000000 40 120 230 400 0 1 1 1 1 0 0 100666
296 assign 10000 1000000 260 430 610 620 0 1 1 1 1 0 0 100667
297 jahaci 10000 1000000 170 290 590 0 0 1 1 1 0 0 0 100668
298 hisuii 10000 1000000 220 470 700 0 0 1 1 1 0 0 0 100669
299 godkno 10000 300000 100 260 450 640 60 1 1 1 1 1 0 100670
300 roadof 10000 300000 150 360 500 750 70 1 1 1 1 1 0 100671
301 rokuch 10000 300000 210 350 620 810 110 1 1 1 1 1 0 100672
302 valent 10000 300000 270 330 590 770 100 1 1 1 1 1 0 100673
303 unfini 10000 300000 160 320 500 710 80 1 1 1 1 1 0 100674
304 auflcb2 10000 1000000 220 370 750 0 100 1 1 1 0 1 0 100675
305 burnin 10000 1000000 180 280 600 850 150 1 1 1 1 1 0 100676
306 sphere 10000 1000000 200 380 730 0 0 1 1 1 0 0 0 100677
307 dropou 10000 300000 170 310 460 690 140 1 1 1 1 1 0 100678
308 xencou 10000 300000 200 320 520 600 80 1 1 1 1 1 0 100679
309 killyk 10000 300000 130 420 630 760 60 1 1 1 1 1 0 100680
310 missil 10000 1000000 160 380 590 0 0 1 1 1 0 0 0 100681
311 burstt 10000 300000 120 250 460 630 70 1 1 1 1 1 0 100682
312 musicr2 10000 100000 220 330 580 0 120 1 1 1 0 1 0 100683
313 isingl 10000 1000000 250 440 800 0 120 1 1 1 0 1 0 100684
314 lvless 10000 1000000 230 380 600 0 0 1 1 1 0 0 0 100685
315 sapphi 10000 1000000 290 440 810 0 0 1 1 1 0 0 0 100686
316 musicr3 10000 100000 190 320 580 720 120 1 1 1 1 1 0 100687
317 deeout 10000 1000000 180 340 630 810 0 1 1 1 1 0 0 100688
318 sugars 10000 300000 170 300 420 660 60 1 1 1 1 1 0 100689
319 mercur 10000 1000000 140 350 660 0 0 1 1 1 0 0 0 100690
320 zizizi 10000 1000000 300 570 880 960 0 1 1 1 1 0 0 100691
321 wegooo 10000 300000 180 340 540 680 100 1 1 1 1 1 0 100692
322 alonee 10000 300000 110 210 360 480 50 1 1 1 1 1 0 100693
323 nuheat 10000 1000000 290 440 650 850 0 1 1 1 1 0 0 100694
324 granro 10000 300000 150 280 430 600 80 1 1 1 1 1 0 100695
325 sister 10000 300000 100 270 460 630 70 1 1 1 1 1 0 100696
326 lotusl 10000 1000000 200 360 640 0 0 1 1 1 0 0 0 100697
327 yukari 10000 1000000 310 500 760 840 0 1 1 1 1 0 0 100698
328 flawli 10000 300000 170 300 400 590 80 1 1 1 1 1 0 100699
329 nightf 10000 1000000 150 280 460 710 0 1 1 1 1 0 0 100700
330 random 10000 100000 0 0 0 0 0 0 0 0 0 0 0 100701
331 wiwwtw 10000 1000000 260 380 620 0 0 1 1 1 0 0 0 100702
332 inneru 10000 300000 220 360 480 670 90 1 1 1 1 1 0 100703
333 taishi 10000 1000000 190 350 580 0 0 1 1 1 0 0 0 100704
334 daysss 10000 1000000 380 590 810 810 0 1 1 1 1 0 0 100705
335 bokuwa 10000 300000 230 340 550 690 160 1 1 1 1 1 0 100706
336 showww 10000 300000 180 350 510 790 150 1 1 1 1 1 0 100707
337 nevers 10000 300000 260 320 650 750 150 1 1 1 1 1 0 100708
338 bleeze 10000 300000 160 310 470 620 90 1 1 1 1 1 0 100709
339 dreami 10000 1000000 140 370 650 0 0 1 1 1 0 0 0 100710
340 allune 10000 1000000 140 350 710 0 0 1 1 1 0 0 0 100711
341 always 10000 1000000 130 270 490 0 0 1 1 1 0 0 0 100712
342 anomie2 10000 1000000 160 430 840 0 0 1 1 1 0 0 0 100713
343 aquali2 10000 1000000 220 430 600 810 0 1 1 1 1 0 0 100714
344 astaro 10000 1000000 230 400 740 0 0 1 1 1 0 0 0 100715
345 bassan 10000 1000000 200 320 660 0 0 1 1 1 0 0 0 100716
346 zonzon2 10000 1000000 130 270 680 750 0 1 1 1 1 0 0 100717
347 bouled 10000 1000000 190 300 570 0 0 1 1 1 0 0 0 100718
348 brandn 10000 1000000 90 390 660 720 0 1 1 1 1 0 0 100719
349 bravee 10000 1000000 350 600 820 0 250 1 1 1 0 -1 0 100720
350 breakd2 10000 1000000 340 640 740 0 0 1 1 1 0 0 0 100721
351 buffet 10000 1000000 380 550 680 0 300 1 1 1 0 -1 0 100722
352 buzzke 10000 1000000 180 330 580 770 0 1 1 1 1 0 0 100723
353 cashhh 10000 1000000 190 250 640 0 0 1 1 1 0 0 0 100724
354 cloudb 10000 1000000 370 660 740 0 250 1 1 1 0 -1 0 100725
355 clouds 10000 1000000 130 250 470 0 0 1 1 1 0 0 0 100726
356 codepa 10000 1000000 290 550 700 0 150 1 1 1 0 -1 0 100727
357 comear 10000 1000000 380 560 830 0 250 1 1 1 0 -1 0 100728
358 crysta 10000 1000000 370 560 810 0 300 1 1 1 0 -1 0 100729
359 curseo 10000 1000000 220 360 740 0 0 1 1 1 0 0 0 100730
360 datami 10000 1000000 180 360 660 0 0 1 1 1 0 0 0 100731
361 defaul 10000 1000000 210 330 480 0 0 1 1 1 0 0 0 100732
362 design2 10000 1000000 250 430 680 0 0 1 1 1 0 0 0 100733
363 diamon 10000 1000000 100 260 330 0 0 1 1 1 0 0 0 100734
364 dispel 10000 1000000 280 480 800 0 0 1 1 1 0 0 0 100735
365 distan 10000 1000000 200 300 680 0 0 1 1 1 0 0 0 100736
366 dokibl 10000 1000000 150 230 670 0 0 1 1 1 0 0 0 100737
367 dontwa 10000 1000000 130 340 690 0 0 1 1 1 0 0 0 100738
368 drgirl 10000 1000000 190 350 540 730 0 1 1 1 1 0 0 100739
369 eterna 10000 1000000 120 210 390 0 0 1 1 1 0 0 0 100740
370 everkr 10000 1000000 180 290 410 0 0 1 1 1 0 0 0 100741
371 everwh 10000 1000000 200 310 580 0 0 1 1 1 0 0 0 100742
372 farthe 10000 1000000 300 560 780 870 0 1 1 1 1 0 0 100743
373 filame 10000 1000000 230 380 630 0 0 1 1 1 0 0 0 100744
374 flameu2 10000 1000000 170 240 590 0 0 1 1 1 0 0 0 100745
375 freeee 10000 1000000 190 390 690 0 0 1 1 1 0 0 0 100746
376 funkyb2 10000 1000000 210 340 560 0 0 1 1 1 0 0 0 100747
377 granda2 10000 1000000 240 410 730 830 0 1 1 1 1 0 0 100748
378 hsphsp 10000 1000000 120 250 690 0 0 1 1 1 0 0 0 100749
379 halluc 10000 1000000 400 520 870 0 0 1 1 1 0 0 0 100750
380 indigo 10000 1000000 170 330 500 750 0 1 1 1 1 0 0 100751
381 inters 10000 1000000 250 420 770 0 0 1 1 1 0 0 0 100752
382 incave2 10000 1000000 310 570 880 0 0 1 1 1 0 0 0 100753
383 ioniza 10000 1000000 170 340 700 850 0 1 1 1 1 0 0 100754
384 guilty 10000 1000000 150 280 500 0 0 1 1 1 0 0 0 100755
385 keraun 10000 1000000 250 520 790 0 0 1 1 1 0 0 0 100756
386 landin2 10000 1000000 200 340 590 660 0 1 1 1 1 0 0 100757
387 videog 10000 1000000 210 370 620 0 0 1 1 1 0 0 0 100758
388 loseyo 10000 1000000 200 300 710 0 0 1 1 1 0 0 0 100759
389 machin 10000 1000000 120 280 720 0 0 1 1 1 0 0 0 100760
390 makeit 10000 1000000 110 240 480 0 0 1 1 1 0 0 0 100761
391 daydre 10000 1000000 190 360 800 0 0 1 1 1 0 0 0 100762
392 metron 10000 1000000 200 440 710 0 0 1 1 1 0 0 0 100763
393 milkyw 10000 1000000 220 310 600 0 0 1 1 1 0 0 0 100764
394 nayuta 10000 1000000 170 370 680 0 0 1 1 1 0 0 0 100766
395 nightm 10000 1000000 200 490 730 0 0 1 1 1 0 0 0 100767
396 otherw 10000 1000000 230 410 760 0 0 1 1 1 0 0 0 100768
397 overth 10000 1000000 330 570 820 0 250 1 1 1 0 -1 0 100769
398 uuuuuu 10000 1000000 230 370 740 0 0 1 1 1 0 0 0 100770
399 rainin 10000 1000000 160 410 690 0 0 1 1 1 0 0 0 100771
400 raisey 10000 1000000 230 550 750 0 150 1 1 1 0 -1 0 100772
401 resona 10000 1000000 170 320 640 0 0 1 1 1 0 0 0 100773
402 reuniv 10000 1000000 140 230 410 0 0 1 1 1 0 0 0 100774
403 rhythm 10000 1000000 370 560 780 0 250 1 1 1 0 -1 0 100775
404 rushhh 10000 1000000 250 370 750 0 0 1 1 1 0 0 0 100776
405 steeee 10000 1000000 300 580 870 0 0 1 1 1 0 0 0 100777
406 sangey 10000 1000000 270 470 850 0 0 1 1 1 0 0 0 100778
407 senpai 10000 1000000 380 540 770 0 250 1 1 1 0 -1 0 100779
408 sestea 10000 1000000 270 470 760 0 0 1 1 1 0 0 0 100780
409 silver 10000 1000000 280 400 690 0 0 1 1 1 0 0 0 100781
410 sodama 10000 1000000 200 400 650 0 0 1 1 1 0 0 0 100782
411 stardu 10000 1000000 190 330 640 0 0 1 1 1 0 0 0 100783
412 starti 10000 1000000 170 310 540 700 0 1 1 1 1 0 0 100784
413 sunday 10000 1000000 180 290 460 670 0 1 1 1 1 0 0 100785
414 sundro2 10000 1000000 300 480 790 820 0 1 1 1 1 0 0 100786
415 sunnyd 10000 1000000 230 380 590 0 0 1 1 1 0 0 0 100787
416 superl 10000 1000000 150 320 590 0 0 1 1 1 0 0 0 100788
417 switch 10000 1000000 160 350 690 0 0 1 1 1 0 0 0 100789
418 theepi2 10000 1000000 220 370 650 0 0 1 1 1 0 0 0 100790
419 epipha 10000 1000000 150 300 700 0 0 1 1 1 0 0 0 100791
420 thekin 10000 1000000 220 520 750 0 0 1 1 1 0 0 0 100792
421 timele 10000 1000000 160 330 720 0 0 1 1 1 0 0 0 100793
422 tokyoo 10000 1000000 150 330 710 0 0 1 1 1 0 0 0 100794
423 toooma 10000 1000000 300 510 770 0 0 1 1 1 0 0 0 100795
424 toucho2 10000 1000000 170 320 520 780 0 1 1 1 1 0 0 100796
425 tayuta 10000 1000000 260 350 720 0 0 1 1 1 0 0 0 100797
426 ultrix 10000 1000000 270 450 760 0 0 1 1 1 0 0 0 100798
427 underw 10000 1000000 290 460 690 860 0 1 1 1 1 0 0 100799
428 virtua 10000 1000000 150 350 630 0 0 1 1 1 0 0 0 100800
429 voiceo2 10000 1000000 140 380 670 0 0 1 1 1 0 0 0 100801
430 wannab2 10000 1000000 260 410 690 0 0 1 1 1 0 0 0 100802
431 wiwwtw2 10000 1000000 200 430 670 720 0 1 1 1 1 0 0 100803
432 wingso 10000 1000000 200 530 710 0 0 1 1 1 0 0 0 100804
433 winter 10000 1000000 140 240 410 0 0 1 1 1 0 0 0 100805
434 iineee 10000 1000000 210 400 810 0 0 1 1 1 0 0 0 100806
435 illumi 10000 1000000 100 250 460 630 0 1 1 1 1 0 0 100807
436 yellll 10000 1000000 80 170 520 0 0 1 1 1 0 0 0 100808
437 eschat 10000 1000000 360 570 770 0 250 1 1 1 0 -1 0 100809
438 counte 10000 1000000 290 340 710 0 0 1 1 1 0 0 0 100810
439 gimcho 10000 1000000 180 390 700 0 0 1 1 1 0 0 0 100811
440 surviv 10000 1000000 240 400 650 0 0 1 1 1 0 0 0 100812
441 turkis3 10000 1000000 60 200 480 0 0 1 1 1 0 0 0 100814
442 picora2 10000 1000000 280 530 800 0 0 1 1 1 0 0 0 100815
443 fortis 10000 1000000 200 370 530 0 0 1 1 1 0 0 0 100816
444 hedban 10000 1000000 160 430 660 0 0 1 1 1 0 0 0 100817
445 megitu 10000 1000000 150 300 490 0 0 1 1 1 0 0 0 100818
446 rockma 10000 1000000 270 480 730 0 0 1 1 1 0 0 0 100819
447 kounen2 10000 1000000 210 430 730 0 0 1 1 1 0 0 0 100820
448 saisyu 10000 1000000 180 360 560 0 0 1 1 1 0 0 0 100821
449 yuukan 10000 1000000 220 330 780 0 0 1 1 1 0 0 0 100822
450 modern 10000 1000000 200 320 560 0 0 1 1 1 0 0 0 100823
451 miraie 10000 1000000 210 350 660 0 0 1 1 1 0 0 0 100824
452 ranfes 10000 1000000 200 420 650 0 0 1 1 1 0 0 0 100825
453 nemure 10000 1000000 150 380 670 760 0 1 1 1 1 0 0 100826
454 yuwaku 10000 1000000 150 260 430 0 0 1 1 1 0 0 0 100827
455 dontst 10000 1000000 150 320 560 700 0 1 1 1 1 0 0 100828
456 mottai 10000 1000000 100 260 360 0 0 1 1 1 0 0 0 100829
457 slysly 10000 1000000 100 330 580 0 0 1 1 1 0 0 0 100830
458 lookam 10000 1000000 170 340 670 0 0 1 1 1 0 0 0 100831
459 feverr 10000 1000000 280 480 680 0 0 1 1 1 0 0 0 100832
460 fashio 10000 1000000 80 240 390 0 0 1 1 1 0 0 0 100833
461 hagito 10000 1000000 120 260 500 0 0 1 1 1 0 0 0 100834
462 invade 10000 1000000 100 280 470 0 0 1 1 1 0 0 0 100835
463 ainoch 10000 1000000 170 400 590 0 0 1 1 1 0 0 0 100836
464 nakama 10000 1000000 140 320 530 0 0 1 1 1 0 0 0 100837
465 ninjar 10000 1000000 80 230 410 650 0 1 1 1 1 0 0 100838
466 parall 10000 1000000 140 350 610 0 0 1 1 1 0 0 0 100839
467 yukifu 10000 1000000 130 290 510 0 0 1 1 1 0 0 0 100840
468 furiso 10000 1000000 120 240 440 740 0 1 1 1 1 0 0 100841
469 honeyj 10000 100000 320 630 880 930 240 1 1 1 1 1 6 100842
470 emeraj 10000 100000 300 530 850 0 190 1 1 1 0 1 1 100843
471 dazzlo 10000 200000 350 600 800 900 160 1 1 1 1 1 1 100844

Binary file not shown.
1 1 1 1601510400 4096483201 1 0 0 0 1 0 news0001 1 1
2 2 1 1601510400 4096483201 1 0 0 0 1 0 news0002 1 1
3 3 1 1601510400 4096483201 1 0 0 0 1 0 news0003 1 1
4 4 1 1601510400 4096483201 1 0 0 0 1 0 news0004 1 1
5 5 1 1601510400 4096483201 0 0 0 1 1 0 news0005 1 1
6 6 1 1601510400 4096483201 1 0 0 0 1 0 news0006 1 1
7 7 1 1601510400 4096483201 1 0 0 0 1 0 news0007 1 1
8 8 1 1601510400 4096483201 1 0 0 0 1 0 news0008 1 1
9 9 1 1601510400 4096483201 1 0 0 0 1 0 news0009 1 1
10 10 1 1601510400 4096483201 1 0 0 0 1 0 news0010 1 1

Binary file not shown.
1 shopID. 整理用No. Ver. 出現フラグ 出現フラグ参照ID 条件 出現時間 消滅時間 ItemCode 価格 表示タイプ Text Type Value(op) Value 対象曲 Difficulty(op) Difficulty Level(op) Level Grade(Op) Grade GaugeType(op) GaugeType HS(op)i HS APP DAP F-V F-H FullCombo Combo(op) Combo ClearRate(op) ClearRate プレイ日 地域
2 1000 1 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 ic0000 10 1 MASTER以上の2曲S+以上フルコンボクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
3 1001 2 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 ic0001 10 1 Next Frontier (Master)をクリア 0 -1 -1 megaro -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
4 1002 3 1.00.00 1 -1 - 1412103600.0288 1443639598.992 ic0002 10 2 Master以上を1曲をS+以上でクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1

Binary file not shown.
1 shopID. 整理用No. Ver. 出現フラグ 出現フラグ参照ID 条件 出現時間 消滅時間 MusicCode 価格 表示タイプ Text Type Value(op) Value 対象曲 Difficulty(op) Difficulty Level(op) Level Grade(Op) Grade GaugeType(op) GaugeType HS(op) HS APP DAP F-V F-H FullCombo Combo(op) Combo ClearRate(op) ClearRate プレイ日 地域
2 0 1 1.00.00 3 1 - 1411697520.0288 1443233520.0288 megaro 0 0 - -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
3 1 2 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 nature 10 2 ??? -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
4 2 3 1.00.00 2 -1 - 1412103600.0288 1443639598.992 hopesb 30 1 「Landing on the moon」をSTANDARD以上でクリアする。 0 -1 -1 landin 1 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
5 3 4 1.00.00 1 -1 - 1412103600.0288 1443639598.992 flower 10 0 - -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
6 4 5 1.00.02 1 -1 1&2&3 1412103600.0288 1443639598.992 reseed3 10 0 「Human Nature」「Hopes Bright」「Flowerwall」をクリアする。 -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
7 5 6 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 dennou 20 1 - 0 -1 -1 flower 1 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 -1 -1 -1 -1
8 6 7 1.00.00 2 -1 5&7 1411697520.0288 1443233520.0288 romanc 10 1 - -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
9 7 8 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 landin 40 1 - -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
10 8 9 1.00.00 1 -1 7 1411697520.0288 1443233520.0288 ididid 50 0 - -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 -1 -1 -1 -1
11 9 10 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 crissc 60 0 MASTER以上の2曲S+以上フルコンボクリアする。 1 1 2 - 1 2 -1 0 1 1 1 2 -1 -1 -1 -1 -1 -1 1 -1 -1 -1 -1
12 10 11 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 dazzli 70 1 MASTER以上の4曲S+以上クリアする。 1 1 4 - 1 2 -1 0 1 1 1 2 -1 -1 -1 -1 -1 -1 2 -1 -1 -1 -1
13 11 12 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 izimed 987654 1 MASTER以上の7曲S+以上クリアする。 1 1 7 - 1 2 -1 0 1 1 1 2 -1 -1 -1 -1 -1 -1 2 -1 -1 -1 -1

Binary file not shown.
1 saleID. 開始日 終了日 ShopID Price
2 0 1411696799.9712 1443236400 0 7000
3 1 1411783199.9712 1443322800 1 7000

Binary file not shown.
1 shopID. 整理用No. Ver. 出現フラグ 出現フラグ参照ID 条件 出現時間 消滅時間 ItemCode 価格 表示タイプ Text Type Value(op) Value 対象曲 Difficulty(op) Difficulty Level(op) Level Grade(Op) Grade GaugeType(op) GaugeType HS(op)i HS APP DAP F-V F-H FullCombo Combo(op) Combo ClearRate(op) ClearRate プレイ日 地域
2 3000 1 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 skb0000 10 1 MASTER以上の2曲S+以上フルコンボクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
3 3001 2 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 skb0001 10 1 Next Frontier (Master)をクリア 0 -1 -1 bleeze 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
4 3002 3 1.00.00 1 -1 - 1412103600.0288 1443639598.992 skb0002 10 2 Master以上を1曲をS+以上でクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1

Binary file not shown.
1 shopID. 整理用No. Ver. 出現フラグ 出現フラグ参照ID 条件 出現時間 消滅時間 ItemCode 価格 表示タイプ Text Type Value(op) Value 対象曲 Difficulty(op) Difficulty Level(op) Level Grade(Op) Grade GaugeType(op) GaugeType HS(op)i HS APP DAP F-V F-H FullCombo Combo(op) Combo ClearRate(op) ClearRate プレイ日 地域
2 5000 1 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 ske0000 10 1 MASTER以上の2曲S+以上フルコンボクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
3 5001 2 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 ske0001 10 1 Next Frontier (Master)をクリア 0 -1 -1 megaro -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
4 5002 3 1.00.00 1 -1 - 1412103600.0288 1443639598.992 ske0002 10 2 Master以上を1曲をS+以上でクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1
5 5003 4 1.00.00 1 -1 - 1412103600.0288 1443639598.992 ske0003 10 0 Master以上を1曲をS+以上でクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
6 5004 5 1.00.00 1 -1 - 1412103600.0288 1443639598.992 ske0004 10 2 2曲クリア 1 1 2 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
7 5005 5 1.00.00 1 -1 - 1412103600.0288 1443639598.992 ske0005 10 2 3曲クリア 1 1 3 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
8 5006 5 1.00.00 1 -1 - 1412103600.0288 1443639598.992 ske0006 10 2 4曲クリア 1 1 4 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
9 5007 5 1.00.00 1 -1 - 1412103600.0288 1443639598.992 ske0007 10 2 5曲クリア 1 1 5 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
10 5008 5 1.00.00 1 -1 - 1412103600.0288 1443639598.992 ske0008 10 2 6曲クリア 1 1 6 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
11 5009 5 1.00.00 1 -1 - 1412103600.0288 1443639598.992 ske0009 10 2 7曲クリア 1 1 7 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 shopID. 整理用No. Ver. 出現フラグ 出現フラグ参照ID 条件 出現時間 消滅時間 ItemCode 価格 表示タイプ Text Type Value(op) Value 対象曲 Difficulty(op) Difficulty Level(op) Level Grade(Op) Grade GaugeType(op) GaugeType HS(op)i HS APP DAP F-V F-H FullCombo Combo(op) Combo ClearRate(op) ClearRate プレイ日 地域
2 4000 1 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 skt0000 10 1 MASTER以上の2曲S+以上フルコンボクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
3 4001 2 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 skt0001 10 1 Next Frontier (Master)をクリア 0 -1 -1 megaro -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
4 4002 3 1.00.00 1 -1 - 1412103600.0288 1443639598.992 skt0002 10 2 Master以上を1曲をS+以上でクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1
5 4003 4 1.00.00 1 -1 - 1412103600.0288 1443639598.992 skt0003 10 0 Master以上を1曲をS+以上でクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
6 4004 5 1.00.00 1 -1 - 1412103600.0288 1443639598.992 skt0004 10 2 aaaaaaaaaaaaaaaaa 1 1 20 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 shopID. 整理用No. Ver. 出現フラグ 出現フラグ参照ID 条件 出現時間 消滅時間 ItemCode 価格 表示タイプ Text Type Value(op) Value 対象曲 Difficulty(op) Difficulty Level(op) Level Grade(Op) Grade GaugeType(op) GaugeType HS(op)i HS APP DAP F-V F-H FullCombo Combo(op) Combo ClearRate(op) ClearRate プレイ日 地域
2 2000 1 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 10 1 MASTER以上の2曲S+以上フルコンボクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
3 2001 2 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 10 1 Next Frontier (Master)をクリア 0 -1 -1 megaro -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
4 2002 3 1.00.00 1 -1 - 1412103600.0288 1443639598.992 10 2 Master以上を1曲をS+以上でクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1

Binary file not shown.
1 mu000 01e0caad-eaee-4810-90ae-6f45abe5c266
2 ig000 dcac41a7-7816-406e-b750-283e06e77a1b
3 bg000 e3dc498b-79bd-4110-a0a9-7ab6538ec6a6
4 mu001 c4dc9846-df4b-4c3d-89b7-e19ae9288de1
5 ig001 13bc8578-e2bf-45ba-ad10-23831e95f8de
6 bg001 19a69ba1-a408-4f0c-a923-1d42e7d9eb0e
7 mu999 3e83ee1c-6936-4e21-a10c-5d359749bb83
8 ig002 73a5a9d6-c862-4cd0-a36f-26fe73da78de
9 ig003 9e1d3817-ef60-4d8d-9beb-c0749b6b51fd
10 ig004 90e6f2da-9678-4847-8435-30f238f214ab
11 ig005 681c7bb1-8f73-4753-8945-f46572716bff
12 th000 6a422181-03e0-4b97-b443-22ad0004e85a
13 th001 ad9dfefd-a687-4cca-8e89-6245c94e52c9
14 th999 fbf16d3c-1718-4b7d-af3d-68f8b8e18867
15 ig006 578d6c5c-10f6-4c0e-a99b-29bab4938ade
16 ev999 a02c3fb7-53bc-4380-93da-57988ed3b9d2
17 mu002 aef73754-f2e7-47c4-bfb3-eb5366aa2b6d
18 ig007 3ac11d24-3dbe-4800-a2ed-6bbc4e093c6d
19 bg002 70ae1a4e-1c4d-4f12-a326-c3fac0e87045
20 th002 9ee6fd76-4b9c-44c2-90be-a50530f0313f
21 mu003 09c4fd8b-111b-4dbb-92c3-94fcfb14a311
22 ig008 869bb37b-0abb-4c4f-a56a-03f7ee98ea14
23 bg003 d4165292-3140-41e4-bde9-a1a530c462ab
24 th003 6053e709-d3c5-4110-9b07-47876bba00cf
25 ig009 b8e368c3-085c-467b-9654-90c63cb390f7
26 ig010 7e3e2b96-0cf9-4920-9264-6f284019dee7
27 bg999 5ba48136-a854-4299-8790-c1c371945eb0
28 bg004 25cb7abb-ad50-469a-9d28-440f3ffec9e8
29 ig011 7b92ac76-9750-4efe-ad92-e43844d8e9e2
30 mu004 abfa94c5-a303-4c7a-bacd-bbbda7d3877e
31 ig012 de774207-7a71-42cd-b54e-054b67199f7d
32 bg005 2aa16e78-893a-4e34-95ef-c7d205a40ea3
33 th004 6589a0cc-0b2d-46b2-a21c-49ad68deeff5
34 mu005 f1ce21fc-f512-43e5-af39-001278d6e8ac
35 ig013 364a9449-bb7b-47ed-b72b-4f7a5583966b
36 bg006 b2212579-69b0-480e-a4ab-685bf5c2599d
37 th005 9392bbee-3762-4d19-a382-1bc1e4d38dc5
38 ig014 45ecd41a-976f-42cb-bbb7-9c70946f7793
39 ig015 a2f8cb15-e579-41d4-958a-42cfb3db08f2
40 ig016 fd991b2f-22a2-4b4b-95ec-06ae70fa4cf8
41 ig020 b0d366c4-644f-403f-aa0b-87ec781c5a47
42 ig030 c3a59d08-0c9b-4577-9e3c-3b828a5dbae4
43 mu007 cc4d20dd-0db2-4128-b366-cc466c074edd
44 mu008 873550c2-8c69-4d32-9af0-b1193a3297ff
45 mu009 966b2c02-f467-4b12-811c-d5df28378b88
46 mu010 93b7cf77-5f4e-4060-839c-d07ea1cb9293
47 mu011 8fa1af29-61d4-4ed3-bf5d-1755cc63f597
48 mu013 e62242b0-22c5-435c-a904-97fc815113b3
49 mu014 f5ba080a-be40-4d99-a7b5-65ac370c6625
50 mu015 492e20bb-5394-4159-938e-0c626a69fbb8
51 mu016 c3db7891-26f1-4070-bd58-fb193c3d6b98
52 mu017 c43be79b-90ff-4a3c-90a0-4b01f16175b8
53 mu018 3cbc6540-95c5-40ba-a17b-b37044695bbd
54 mu012 d4407594-5928-4606-8831-0becd9a82e79
55 th007 4db1a0a5-f0a8-4909-83eb-d5a53de174fc
56 ig017 52c31a94-ef44-4dbd-a26a-4aa43590c998
57 ig018 2ea1ba61-352c-4ff3-8854-ae34ec6a3cb8
58 ig019 f79e01a8-f325-409c-8b55-b40fd09f485b
59 ig021 0abe9547-fc5d-4677-8469-7da6b0dcc46d
60 ig022 b2eba0ca-08f3-412b-a4ff-df301aef59a5
61 ig023 2a615618-df3c-4eb5-8f9a-cdceed2f70b2
62 ig024 bac5cd51-1ae3-483e-bac0-ddd0aa79a544
63 ig025 39241b3b-c3bb-4852-9bc1-b5ad4950788d
64 ig026 c5e90844-2e42-4702-95c0-536f1f707b69
65 ig027 243e96c0-c3bb-4cbf-8714-39e637a1fc4c
66 ig028 c9663a15-3379-4c26-833e-c0cbe75f1725
67 ig029 bd4f1868-530f-47ff-8ad9-331f025a30cd
68 ig031 a50830c8-85cf-4b90-9f76-369c6786aa10
69 ig032 7547c19d-c0e8-4fa2-bb02-a0818c908f1d
70 ig033 f8163e70-a91b-4c37-8ff0-c519ac41789d
71 ig034 32649798-7da7-4bef-94ae-eac2823dbdca
72 ig035 f61efc53-582e-424b-9c6a-27b714414ac7
73 ig036 31c83605-88f3-4190-a875-40afca619bc7
74 ig037 c7c94234-e593-47cc-9440-3ae6e5700d4e
75 ig038 414fed22-596a-4b82-b322-0592b6284c6c
76 ig039 6832ca35-7187-4ca9-a677-c5587f3dfc37
77 ig040 3e1a72fd-de2a-4de1-b9cb-c6b70e8dd865
78 ig042 6b689c36-f388-48e8-93d3-2c73c71b2279
79 ig043 f5d69985-5662-40e2-a184-2da3258f77ea
80 ig044 8b0605fe-06de-4b2a-9c31-a229b8b5da3f
81 mu019 31ad932c-990e-4967-90b6-188f2c656dbb
82 bg007 28f01dfc-e73d-4701-a2d1-ac929785ea98
83 bg008 ba10a865-19f1-4953-a115-3b711768f9bf
84 bg009 7459ec1c-07dd-43fd-89ad-7cd5a6acf704
85 bg010 d464e672-3b16-4b18-966e-55822d831023
86 bg011 8a8558b8-da63-4efe-90ee-42da6aa742c4
87 bg012 9aac6c96-38d4-4869-a255-bffa2a941bd7
88 bg013 a7afb95b-d57d-4530-86e9-4930e2eaaff5
89 bg014 17369ad5-64fb-43c6-a13b-1427187c4711
90 bg015 594e5fa6-ebdf-495d-84c7-c4680d5e754b
91 bg016 e1cb508a-2644-4a75-9d9f-1458e3e8cf96
92 bg017 27a7bfbd-2fef-4254-86d3-60d4e279cfed
93 bg018 4d8f37e0-eb2e-4286-a4eb-3fd378ad94cc
94 bg019 dc582ac8-1fa8-438f-a791-d486f17c9029
95 mu006 f068ffc0-87c5-4caf-b206-dc1ba5516c99
96 th998 141f4a98-09bf-4a52-b42e-571fadcc53eb
97 ig045 a8b3d9ff-839d-4016-9ce6-9d9bb63d1d36
98 ig046 a2e9997b-64a8-4874-b0c5-17093441a2f5
99 th006 2bd08a14-c84e-47d2-b0d5-e9f0c8937b98
100 ig047 a210e6d6-82af-4081-aeae-196e6b3528c0
101 th008 cd740e0a-d10c-47cc-a7b8-bff2d03977cb
102 th009 a0b39026-4615-4087-b3de-4bced4ec926d
103 th010 013cfef7-029c-448d-9740-e649b89baa28
104 th011 caf1bf2d-9e04-4b12-a13b-502fe9abbd99
105 th012 3689be3f-33bd-4672-b78c-5ea4d46cd15d
106 th013 c8ea8eac-b71d-446e-827b-e6092892a086
107 th014 64af0cbc-ba40-4794-8197-496a2109d4ec
108 th015 b3d4fc6b-4aba-4c80-8bd0-5b4fce6bf57b
109 th016 513f56cc-a5d9-4bd1-8209-29b2b87fac53
110 th017 0803f23d-587b-443d-a9c4-0fce063be8fc
111 th018 7abbeec8-9a22-4f83-9116-14274cf64479
112 th019 78ef3012-f687-46a1-ad64-a8ae20f33319
113 ig049 c37a2a37-e42b-4adf-85f4-86509032b42d
114 ig050 1368f1bd-a407-4273-ae4b-db6bec4d2cf9
115 ig051 a64f5b47-5e2e-442d-95e3-2be7c7071253
116 ig052 a419e87c-6187-4a2f-bd22-e86c92153395

257
titles/cxb/rss1.py Normal file
View File

@ -0,0 +1,257 @@
import json
from decimal import Decimal
from base64 import b64encode
from typing import Any, Dict
from hashlib import md5
from datetime import datetime
from core.config import CoreConfig
from core.data import Data, cached
from titles.cxb.config import CxbConfig
from titles.cxb.base import CxbBase
from titles.cxb.const import CxbConstants
class CxbRevSunriseS1(CxbBase):
def __init__(self, cfg: CoreConfig, game_cfg: CxbConfig) -> None:
super().__init__(cfg, game_cfg)
self.version = CxbConstants.VER_CROSSBEATS_REV_SUNRISE_S1
def handle_data_path_list_request(self, data: Dict) -> Dict:
return { "data": "" }
@cached(lifetime=86400)
def handle_data_music_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/rss1_data/MusicArchiveList.csv") as music:
lines = music.readlines()
for line in lines:
line_split = line.split(',')
ret_str += f"{line_split[0]},{line_split[1]},{line_split[2]},{line_split[3]},{line_split[4]},{line_split[5]},{line_split[6]},{line_split[7]},{line_split[8]},{line_split[9]},{line_split[10]},{line_split[11]},{line_split[12]},{line_split[13]},{line_split[14]},\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_item_list_detail_request(self, data: Dict) -> Dict:
#ItemListIcon load
ret_str = "#ItemListIcon\r\n"
with open(r"titles/cxb/rss1_data/Item/ItemList_Icon.csv", encoding="shift-jis") as item:
lines = item.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
#ItemListTitle load
ret_str += "\r\n#ItemListTitle\r\n"
with open(r"titles/cxb/rss1_data/Item/ItemList_Title.csv", encoding="shift-jis") as item:
lines = item.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_shop_list_detail_request(self, data: Dict) -> Dict:
#ShopListIcon load
ret_str = "#ShopListIcon\r\n"
with open(r"titles/cxb/rss1_data/Shop/ShopList_Icon.csv", encoding="utf-8") as shop:
lines = shop.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
#ShopListMusic load
ret_str += "\r\n#ShopListMusic\r\n"
with open(r"titles/cxb/rss1_data/Shop/ShopList_Music.csv", encoding="utf-8") as shop:
lines = shop.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
#ShopListSale load
ret_str += "\r\n#ShopListSale\r\n"
with open(r"titles/cxb/rss1_data/Shop/ShopList_Sale.csv", encoding="shift-jis") as shop:
lines = shop.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
#ShopListSkinBg load
ret_str += "\r\n#ShopListSkinBg\r\n"
with open(r"titles/cxb/rss1_data/Shop/ShopList_SkinBg.csv", encoding="shift-jis") as shop:
lines = shop.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
#ShopListSkinEffect load
ret_str += "\r\n#ShopListSkinEffect\r\n"
with open(r"titles/cxb/rss1_data/Shop/ShopList_SkinEffect.csv", encoding="shift-jis") as shop:
lines = shop.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
#ShopListSkinNotes load
ret_str += "\r\n#ShopListSkinNotes\r\n"
with open(r"titles/cxb/rss1_data/Shop/ShopList_SkinNotes.csv", encoding="shift-jis") as shop:
lines = shop.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
#ShopListTitle load
ret_str += "\r\n#ShopListTitle\r\n"
with open(r"titles/cxb/rss1_data/Shop/ShopList_Title.csv", encoding="utf-8") as shop:
lines = shop.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
def handle_data_extra_stage_list_request(self, data: Dict) -> Dict:
return({"data":""})
def handle_data_ex0001_request(self, data: Dict) -> Dict:
return({"data":""})
def handle_data_one_more_extra_list_request(self, data: Dict) -> Dict:
return({"data":""})
def handle_data_bonus_list10100_request(self, data: Dict) -> Dict:
return({"data":""})
def handle_data_oe0001_request(self, data: Dict) -> Dict:
return({"data":""})
def handle_data_free_coupon_request(self, data: Dict) -> Dict:
return({"data":""})
@cached(lifetime=86400)
def handle_data_news_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/rss1_data/NewsList.csv", encoding="UTF-8") as news:
lines = news.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
def handle_data_tips_request(self, data: Dict) -> Dict:
return({"data":""})
def handle_data_release_info_list_request(self, data: Dict) -> Dict:
return({"data":""})
@cached(lifetime=86400)
def handle_data_random_music_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/rss1_data/MusicArchiveList.csv") as music:
lines = music.readlines()
count = 0
for line in lines:
line_split = line.split(",")
ret_str += str(count) + "," + line_split[0] + "," + line_split[0] + ",\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_license_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/rss1_data/License.csv", encoding="UTF-8") as licenses:
lines = licenses.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_course_list_request(self, data: Dict) -> Dict:
ret_str = ""
with open(r"titles/cxb/rss1_data/Course/CourseList.csv", encoding="UTF-8") as course:
lines = course.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
@cached(lifetime=86400)
def handle_data_csxxxx_request(self, data: Dict) -> Dict:
extra_num = int(data["dldate"]["filetype"][-4:])
ret_str = ""
with open(fr"titles/cxb/rss1_data/Course/Cs{extra_num}.csv", encoding="shift-jis") as course:
lines = course.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data":ret_str})
def handle_data_mission_list_request(self, data: Dict) -> Dict:
return({"data":""})
def handle_data_mission_bonus_request(self, data: Dict) -> Dict:
return({"data":""})
def handle_data_unlimited_mission_request(self, data: Dict) -> Dict:
return({"data":""})
def handle_data_partner_list_request(self, data: Dict) -> Dict:
ret_str = ""
# Lord forgive me for the sins I am about to commit
for i in range(0,10):
ret_str += f"80000{i},{i},{i},0,10000,,\r\n"
ret_str += f"80000{i},{i},{i},1,10500,,\r\n"
ret_str += f"80000{i},{i},{i},2,10500,,\r\n"
for i in range(10,13):
ret_str += f"8000{i},{i},{i},0,10000,,\r\n"
ret_str += f"8000{i},{i},{i},1,10500,,\r\n"
ret_str += f"8000{i},{i},{i},2,10500,,\r\n"
ret_str +="\r\n---\r\n0,150,100,100,100,100,\r\n"
for i in range(1,130):
ret_str +=f"{i},100,100,100,100,100,\r\n"
ret_str += "---\r\n"
return({"data": ret_str})
@cached(lifetime=86400)
def handle_data_partnerxxxx_request(self, data: Dict) -> Dict:
partner_num = int(data["dldate"]["filetype"][-4:])
ret_str = f"{partner_num},,{partner_num},1,10000,\r\n"
with open(r"titles/cxb/rss1_data/Partner0000.csv") as partner:
lines = partner.readlines()
for line in lines:
ret_str += f"{line[:-1]}\r\n"
return({"data": ret_str})
def handle_data_server_state_request(self, data: Dict) -> Dict:
return({"data": True})
def handle_data_settings_request(self, data: Dict) -> Dict:
return({"data": "2,\r\n"})
def handle_data_story_list_request(self, data: Dict) -> Dict:
#story id, story name, game version, start time, end time, course arc, unlock flag, song mcode for menu
ret_str = "\r\n"
ret_str += f"st0000,RISING PURPLE,10104,1464370990,4096483201,Cs1000,-1,purple,\r\n"
ret_str += f"st0001,REBEL YELL,10104,1467999790,4096483201,Cs1000,-1,chaset,\r\n"
ret_str += f"st0002,REMNANT,10104,1502127790,4096483201,Cs1000,-1,overcl,\r\n"
return({"data": ret_str})
def handle_data_stxxxx_request(self, data: Dict) -> Dict:
story_num = int(data["dldate"]["filetype"][-4:])
ret_str = ""
for i in range(1,11):
ret_str +=f"{i},st000{story_num}_{i-1},,,,,,,,,,,,,,,,1,,-1,1,\r\n"
return({"data": ret_str})
def handle_data_event_stamp_list_request(self, data: Dict) -> Dict:
return({"data":"Cs1032,1,1,1,1,1,1,1,1,1,1,\r\n"})
def handle_data_premium_list_request(self, data: Dict) -> Dict:
return({"data": "1,,,,10,,,,,99,,,,,,,,,100,,\r\n"})
def handle_data_event_list_request(self, data: Dict) -> Dict:
return({"data":""})
def handle_data_event_detail_list_request(self, data: Dict) -> Dict:
event_id = data["dldate"]["filetype"].split("/")[2]
if "EventStampMapListCs1002" in event_id:
return({"data":"1,2,1,1,2,3,9,5,6,7,8,9,10,\r\n"})
elif "EventStampList" in event_id:
return({"data":"Cs1002,1,1,1,1,1,1,1,1,1,1,\r\n"})
else:
return({"data":""})
def handle_data_event_stamp_map_list_csxxxx_request(self, data: Dict) -> Dict:
event_id = data["dldate"]["filetype"].split("/")[2]
if "EventStampMapListCs1002" in event_id:
return({"data":"1,2,1,1,2,3,9,5,6,7,8,9,10,\r\n"})
else:
return({"data":""})

Binary file not shown.
1 Cs0000 0 10001 1422284400 4096483201 0 -1 -1 100 5 クリアすると段位が「見習い」に昇格します。 -1
2 Cs0001 1 10001 1422284400 4096483201 0 -1 -1 110 5 クリアすると段位が「初段」に昇格します。 -1
3 Cs0002 2 10001 1422284400 4096483201 0 -1 -1 120 5 クリアすると段位が「二段」に昇格します。 -1
4 Cs0003 3 10001 1422284400 4096483201 0 -1 -1 130 5 クリアすると段位が「三段」に昇格します。 -1
5 Cs0004 4 10001 1422284400 4096483201 0 -1 -1 140 5 クリアすると段位が「四段」に昇格します。 -1

Binary file not shown.
1 1 okonik 4 -1 - -1 -1 -1 -1 -1 -1 -1
2 2 okonik 0 -1 - -1 -1 -1 -1 -1 -1 -1
3 3 okonik 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 okonik 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 1 okonik 4 -1 - -1 -1 -1 -1 -1 -1 -1
2 2 okonik 0 -1 - -1 -1 -1 -1 -1 -1 -1
3 3 okonik 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 okonik 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 1 okonik 4 -1 - -1 -1 -1 -1 -1 -1 -1
2 2 okonik 0 -1 - -1 -1 -1 -1 -1 -1 -1
3 3 okonik 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 okonik 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 1 okonik 4 -1 - -1 -1 -1 -1 -1 -1 -1
2 2 okonik 0 -1 - -1 -1 -1 -1 -1 -1 -1
3 3 okonik 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 okonik 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 1 okonik 4 -1 - -1 -1 -1 -1 -1 -1 -1
2 2 okonik 0 -1 - -1 -1 -1 -1 -1 -1 -1
3 3 okonik 1 -1 - -1 -1 -1 -1 -1 -1 -1
4 4 okonik 3 -1 - -1 -1 -1 -1 -1 -1 -1

Binary file not shown.
1 StageMax,ClearCount,StageNo.,MCODE,Diff(std),Diff(hrd),Diff(mas),Diff(ulm),Diff(esy),Level(op), Level(val), Grade(op),Grade(val),GT(nml),GT(svl),GT(ult),GT(nhp),GT(esy),HS(op),HS(val),APP,DAP,F-V,F-H,FT(ac),FT(tab),FT(pho),Combo(op),Combo(val),FullCombo,ClearRate(op),ClearRate(val)
2 2,1,1,-,2,2,2,1,2,-1,-,1,1,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,1,300,-1,-1,-,
3 2,-,2,-,2,2,2,1,2,-1,-,1,1,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,1,300,-1,-1,-,
4 3,3,1,-,2,2,1,1,2,-1,-,1,2,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
5 3,-,2,-,2,2,1,1,2,-1,-,1,2,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
6 3,-,3,-,2,2,1,1,2,1,50,1,2,2,2,1,2,2,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
7 4,4,1,dynami:fronti:rebell:fronti2:auflcb:auflcb2,2,2,1,1,2,-1,-,1,-1,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
8 4,-,2,-,2,2,1,1,2,-1,-,1,-1,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
9 4,-,3,-,2,2,1,1,2,-1,-,1,-1,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,
10 4,-,4,-,2,2,1,1,2,-1,-,1,-1,-1,-1,-1,-1,-1,1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-,-1,-1,-,

Binary file not shown.
1 No.,Ver.,ESID,Title,StartTime,EndTime,出現曲MCODE,出現RP,出現エフェクト,Diff(std),Diff(hrd),Diff(mas),Diff(ulm),Diff(esy),GT(nml),GT(svl),GT(ult),GT(nhp),GT(esy),HS(op),HS(val),APP,DAP,F-V,F-H,FT(ac),FT(tab),FT(pho)
2 1,1000,Ex0000,MEGALOMAN[i]A出現,1411697520.0288,1443233520.0288,megaro,0,3,2,2,1,2,2,2,2,1,2,2,1,-2,-1,-1,-1,-1,-1,-1,-1,

Binary file not shown.
1 1000 ic0000 IconName0000
2 1001 ic0001 IconName0001
3 1002 ic0002 IconName0002

Binary file not shown.
1 2000 スーパーゴリラ 4
2 2001 ふつうのゴリラ 3
3 2002 モンキー 0

Binary file not shown.
1 英雄の証 ~ 4Version/カプコンサウンドチーム
2 © CAPCOM CO., LTD. ALL RIGHTS RESERVED.
3
4 灼熱の刃 ~ ディノバルド
5 © CAPCOM CO., LTD. ALL RIGHTS RESERVED.
6
7 古代の息吹き
8 © CAPCOM CO., LTD. ALL RIGHTS RESERVED.
9
10 Theme of Ryu -SFIV Arrange-/Capcom Sound Team / Hideyuki Fukasawa
11 ©CAPCOM U.S.A., INC. ALL RIGHTS RESERVED.
12
13 Ultra Street Fighter IV/Hideyuki Fukasawa
14 ©CAPCOM U.S.A., INC. ALL RIGHTS RESERVED.
15
16 Theme of Chun-Li -SFIV Arrange-/Capcom Sound Team / Hideyuki Fukasawa
17 ©CAPCOM U.S.A., INC. ALL RIGHTS RESERVED.
18
19 Street Fighter V/Masahiro Aoki
20 ©CAPCOM U.S.A., INC. ALL RIGHTS RESERVED.
21
22 英雄の証/MHF-G 2015 Version
23 © CAPCOM CO., LTD. ALL RIGHTS RESERVED.
24
25 異ヲ辿リシモノ -対峙-/若林タカツグ
26 © CAPCOM CO., LTD. ALL RIGHTS RESERVED.
27
28
29
30
31
32
33
34
35
36
37
38
39
40 QLWA(グルーヴコースター 3 リンクフィーバーより)/t+pazolite
41 © TAITO CORPORATION 1978,2016 ALL RIGHTS RESERVED.
42
43 グルーヴ・ザ・ハート(グルーヴコースター 3 リンクフィーバーより)/ビートまりお+あまね
44 © TAITO CORPORATION 1978,2016 ALL RIGHTS RESERVED.
45
46 Got hive of Ra(グルーヴコースター 3 リンクフィーバーより)/E.G.G.
47 © TAITO CORPORATION 1978,2016 ALL RIGHTS RESERVED.
48
49 LINK LINK FEVER!!!(グルーヴコースター 3 リンクフィーバーより)/リンカ (CV:豊田萌絵)
50 © TAITO CORPORATION 1978,2016 ALL RIGHTS RESERVED.
51
52 SAKURA EXHAUST/RIO HAMAMOTO(BNSI)「太鼓の達人」より
53 ©BANDAI NAMCO Entertainment Inc.
54
55 カリソメ(グルーヴコースター 3 リンクフィーバーより)/コンプ(豚乙女) × ichigo(岸田教団 & THE明星ロケッツ)
56 ©上海アリス幻樂団
57 © TAITO CORPORATION 1978,2016 ALL RIGHTS RESERVED.
58
59 そして誰もいなくなった(グルーヴコースター 3 リンクフィーバーより)/コバヤシユウヤ(IOSYS) × あにー(TaNaBaTa)
60 ©上海アリス幻樂団
61 © TAITO CORPORATION 1978,2016 ALL RIGHTS RESERVED.
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 Font Design by Fontworks Inc.
80 DynaFont is a registered Trademark of DynaComware Taiwan Inc.
81 Ogg Vorbis is Copyright ©2015, Xiph. Org Foundation
82 The font used on this product is provided by Hakusyu Fonts co,.Ltd.
83 キャスティング・ライツクリアランス
84 株式会社ビーイング
85 JASRAC許諾第V-1512134号
86 e-License許諾番号GS35000
87 VOCALOID and VOCALO are trademarks of Yamaha Corporation.
88
89 OMNiMIX v1.2

Binary file not shown.
1 MissionID,Text,Type,Value_op,Value,Mcode,Difficulty_op,Difficulty,Level_op,Level,Grade_op,Grade,GaugeType_op,GaugeType,HiSpeed_op,HiSpeed,APP,DAP,FlipV,FlipH,Fullcombo,Combo_op,Combo,ClearRate_op,ClearRate,StartTime,StartEnd,District,CoupleId
2 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,
3 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,
4 2,ExtraStageでMEGALOMAN[i]Aをクリアする,0,-1,-1,megaro,-1,-1,-1,-1,1,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

Binary file not shown.
1 tutori2 10000 100000 10 10 10 10 10 0 0 0 0 0 0 100000
2 tutori3 10000 100000 10 10 10 10 10 0 0 0 0 0 0 100000
3 tutori4 10000 100000 10 10 10 10 10 0 0 0 0 0 0 100000
4 tutori6 10000 100000 10 10 10 10 10 0 0 0 0 0 0 100000
5 tutori8 10000 1000000 30 150 350 0 0 1 1 1 0 0 0 100345
6 sateli 10000 100000 280 490 770 820 170 1 1 1 1 1 0 100300
7 nature 10000 100000 140 240 530 750 50 1 1 1 1 1 3 100301
8 purple 10000 100000 220 540 640 730 140 1 1 1 1 1 0 100307
9 hearts 10000 100000 180 380 680 770 80 1 1 1 1 1 0 100308
10 phasea 10000 100000 160 380 650 750 90 1 1 1 1 1 0 100310
11 planet 10000 100000 170 360 490 710 100 1 1 1 1 1 1 100311
12 firefo 10000 100000 130 360 570 830 70 1 1 1 1 1 0 100314
13 kounen 10000 100000 210 400 660 780 100 1 1 1 1 1 3 100315
14 essenc 10000 100000 250 500 700 760 110 1 1 1 1 1 0 100316
15 summer 10000 100000 230 570 790 890 130 1 1 1 1 1 0 100317
16 tanosi 10000 100000 250 450 700 800 160 1 1 1 1 1 7 100319
17 picora 10000 100000 150 380 660 750 80 1 1 1 1 1 1 100320
18 devils 10000 100000 270 400 800 0 150 1 1 1 0 1 0 100323
19 techno 10000 100000 160 380 510 740 90 1 1 1 1 1 1 100328
20 glowww 10000 100000 170 280 420 600 80 1 1 1 1 1 7 100335
21 powerr 10000 100000 190 380 690 790 120 1 1 1 1 1 0 100336
22 amater 10000 100000 210 480 650 790 130 1 1 1 1 1 0 100340
23 advers 10000 100000 150 480 710 830 90 1 1 1 1 1 1 100349
24 venera 10000 100000 150 430 680 750 80 1 1 1 1 1 0 100353
25 dazaii 10000 100000 210 430 730 770 120 1 1 1 1 1 3 100357
26 thesig 10000 100000 210 380 560 730 100 1 1 1 1 1 3 100365
27 hosita 10000 100000 160 360 480 650 100 1 1 1 1 1 9999 100344
28 bluede 10000 100000 220 410 580 700 120 1 1 1 1 1 5 100372
29 emerao 10000 100000 300 530 850 0 190 1 1 1 0 1 1 100373
30 megaro 10000 100000 550 800 930 980 0 1 1 1 1 0 0 100129
31 angeli 10000 100000 330 560 820 900 220 1 1 1 1 1 0 100330
32 moonli 10000 100000 140 430 610 730 80 1 1 1 1 1 9999 100342
33 yumemi 10000 100000 120 350 590 690 60 1 1 1 1 1 9999 100369
34 pinkym 10000 100000 240 440 740 810 160 1 1 1 1 1 0 100348
35 dynami2 10000 100000 180 510 780 800 80 1 1 1 1 1 0 100370
36 reseed3 10000 100000 200 550 760 800 100 1 1 1 1 1 0 100306
37 toucho 10000 200000 90 280 440 650 50 1 1 1 1 1 1 100002
38 ameoto 10000 200000 120 260 470 630 60 1 1 1 1 1 1 100003
39 kimito 10000 200000 100 260 490 660 70 1 1 1 1 1 1 100004
40 giantk 10000 200000 250 530 710 780 110 1 1 1 1 1 3 100021
41 breakd 10000 200000 230 340 570 740 110 1 1 1 1 1 2 100015
42 dazzlj 10000 200000 350 600 800 900 160 1 1 1 1 1 1 100028
43 ididid 10000 200000 290 460 720 810 160 1 1 1 1 1 1 100093
44 sundro 10000 200000 240 470 750 830 140 1 1 1 1 1 3 100042
45 auflcb 10000 200000 130 430 810 0 80 1 1 1 0 1 0 100063
46 dennou 10000 200000 290 600 760 870 150 1 1 1 1 1 1 100045
47 hokoro 10000 200000 290 570 710 810 140 1 1 1 1 1 1 100068
48 landin 10000 200000 260 330 490 670 130 1 1 1 1 1 1 100005
49 tomorr 10000 100000 150 240 440 620 80 1 1 1 1 1 7 100362
50 daybyd 10000 100000 130 260 380 590 60 1 1 1 1 1 7 100363
51 syoujo 10000 100000 190 350 530 780 80 1 1 1 1 1 1 100309
52 destru 10000 100000 190 410 620 720 100 1 1 1 1 1 0 100352
53 gingat 10000 200000 130 290 460 610 50 1 1 1 1 1 0 100041
54 daisak 10000 200000 280 360 600 750 120 1 1 1 1 1 0 100066
55 paradi 10000 100000 160 280 530 640 100 1 1 1 1 1 3 100376
56 pigooo 10000 100000 190 340 590 840 130 1 1 1 1 1 6 100377
57 season 10000 300000 150 280 440 650 80 1 1 1 1 1 1 100386
58 canonn 10000 300000 170 280 500 830 70 1 1 1 1 1 1 100387
59 rhapso 10000 300000 180 340 620 740 60 1 1 1 1 1 1 100388
60 turkis 10000 300000 190 390 640 840 110 1 1 1 1 1 1 100389
61 biohaz 10000 300000 150 300 510 640 60 1 1 1 1 1 9999 100390
62 monhan 10000 300000 100 260 360 540 50 1 1 1 1 1 9999 100391
63 gyakut2 10000 300000 130 350 430 560 50 1 1 1 1 1 9999 100392
64 street 10000 300000 130 340 470 660 70 1 1 1 1 1 9999 100393
65 rockma2 10000 300000 210 340 490 760 140 1 1 1 1 1 9999 100394
66 auflcb3 10000 100000 160 360 660 860 60 1 1 1 1 1 9999 100374
67 irohaa 10000 100000 190 410 550 760 120 1 1 1 1 1 0 100325
68 ibelie 10000 100000 270 470 780 820 140 1 1 1 1 1 0 100326
69 monhan2 10000 300000 120 240 430 680 60 1 1 1 1 1 9999 100409
70 monhan3 10000 300000 180 280 450 730 80 1 1 1 1 1 9999 100410
71 yejiii 10000 100000 220 360 630 790 100 1 1 1 1 1 0 100418
72 histor 10000 100000 200 360 560 820 110 1 1 1 1 1 0 100419
73 chaset 10000 100000 150 310 580 760 80 1 1 1 1 1 9999 100338
74 metall 10000 100000 160 280 570 770 80 1 1 1 1 1 1 100412
75 letmeg 10000 100000 180 320 500 720 120 1 1 1 1 1 1 100327
76 hontno 10000 200000 120 260 530 660 90 1 1 1 1 1 1 100010
77 azitat 10000 200000 240 550 700 830 140 1 1 1 1 1 0 100024
78 hellom 10000 100000 180 370 580 720 70 1 1 1 1 1 1 100360
79 laught 10000 100000 200 350 510 710 70 1 1 1 1 1 1 100337
80 bluede2 10000 100000 160 360 560 810 90 1 1 1 1 1 1 100426
81 street2 10000 300000 210 370 550 730 140 1 1 1 1 1 9999 100423
82 street3 10000 300000 240 380 570 740 130 1 1 1 1 1 9999 100424
83 street4 10000 300000 170 320 510 780 110 1 1 1 1 1 9999 100425
84 silbur 10000 100000 200 350 540 750 90 1 1 1 1 1 1 100421
85 spicaa 10000 100000 230 360 560 780 100 1 1 1 1 1 1 100422
86 tricko 10000 100000 230 340 560 750 110 1 1 1 1 1 0 100438
87 thisis 10000 100000 230 370 600 740 120 1 1 1 1 1 4 100435
88 rising 10000 100000 230 380 660 850 140 1 1 1 1 1 4 100436
89 orbita 10000 100000 200 380 620 740 120 1 1 1 1 1 5 100411
90 dddddd 10000 100000 130 330 530 690 90 1 1 1 1 1 5 100433
91 pyroma 10000 100000 220 420 700 840 80 1 1 1 1 1 4 100427
92 touchn 10000 100000 270 460 680 860 150 1 1 1 1 1 8 100312
93 onlyll 10000 100000 210 320 560 690 130 1 1 1 1 1 9999 100359
94 upside 10000 100000 180 270 480 670 80 1 1 1 1 1 1 100313
95 istanb 10000 100000 410 490 900 980 230 1 1 1 1 1 3 100322
96 memori 10000 100000 260 380 650 840 130 1 1 1 1 1 9999 100371
97 straye 10000 100000 250 360 610 730 140 1 1 1 1 1 4 100350
98 rearhy 10000 100000 170 320 520 690 70 1 1 1 1 1 9999 100358
99 hereco 10000 100000 160 340 510 680 110 1 1 1 1 1 4 100432
100 thesun 10000 100000 250 400 720 870 130 1 1 1 1 1 4 100441
101 sayona 10000 100000 200 340 530 710 100 1 1 1 1 1 9999 100343
102 flameu 10000 100000 180 360 570 650 100 1 1 1 1 1 1 100380
103 raidon 10000 100000 300 380 580 870 130 1 1 1 1 1 1 100434
104 riseup 10000 100000 180 410 670 770 70 1 1 1 1 1 4 100437
105 sunglo 10000 100000 180 390 590 720 100 1 1 1 1 1 7 100431
106 kinbos 10000 100000 220 380 640 770 120 1 1 1 1 1 3 100439
107 densho 10000 100000 280 420 740 900 170 1 1 1 1 1 5 100430
108 aiohoo 10000 300000 180 290 420 660 100 1 1 1 1 1 1 100471
109 entert 10000 300000 150 330 540 870 90 1 1 1 1 1 6 100472
110 takeit 10000 100000 200 380 650 830 120 1 1 1 1 1 4 100457
111 harmon 10000 100000 200 360 490 650 120 1 1 1 1 1 7 100449
112 avemar 10000 300000 160 310 530 750 80 1 1 1 1 1 5 100428
113 mateki 10000 300000 180 350 540 790 100 1 1 1 1 1 5 100429
114 lovech 10000 100000 160 300 460 680 80 1 1 1 1 1 7 100445
115 akaihe 10000 300000 210 320 500 690 80 1 1 1 1 1 1 100473
116 juicys 10000 300000 180 260 450 830 100 1 1 1 1 1 7 100474
117 codena 10000 100000 180 350 480 680 90 1 1 1 1 1 1 100468
118 groove 10000 300000 220 400 520 730 100 1 1 1 1 1 103 100475
119 kansho 10000 100000 130 270 550 740 70 1 1 1 1 1 9999 100450
120 overcl2 10000 100000 230 420 580 740 120 1 1 1 1 1 3 100486
121 taikoo 10000 300000 130 390 500 750 60 1 1 1 1 1 104 100483
122 groove2 10000 300000 150 400 580 850 90 1 1 1 1 1 9999 100480
123 overcl 10000 100000 120 350 570 860 80 1 1 1 1 1 4 100487
124 notoss 10000 100000 120 420 650 910 80 1 1 1 1 1 4 100466
125 machup 10000 100000 170 320 410 710 90 1 1 1 1 1 6 100447
126 groove3 10000 300000 180 340 640 850 100 1 1 1 1 1 105 100488
127 groove4 10000 300000 220 350 500 750 120 1 1 1 1 1 106 100489
128 everyt 10000 100000 220 300 740 0 130 1 1 1 0 1 5 100482
129 lespri 10000 100000 250 570 800 0 130 1 1 1 0 1 5 100465
130 groove5 10000 300000 240 370 670 0 140 1 1 1 0 1 0 100491
131 honeyo 10000 100000 320 630 880 930 240 1 1 1 1 1 6 100490
132 groove6 10000 300000 300 640 790 0 220 1 1 1 0 1 3 100494
133 sunglo2 10000 100000 210 360 670 810 110 1 1 1 1 1 6 100495
134 fourte 10000 100000 240 500 740 800 140 1 1 1 1 1 5 100498
135 monhan4 10000 300000 120 400 510 620 50 1 1 1 1 1 9999 100496
136 monhan5 10000 300000 120 350 420 650 100 1 1 1 1 1 9999 100497
137 darkpa 10000 100000 260 390 700 840 160 1 1 1 1 1 3 100504
138 hervor 10000 100000 280 390 730 810 180 1 1 1 1 1 5 100505
139 cirnon 10000 300000 240 400 600 790 170 1 1 1 1 1 9999 100499
140 marisa 10000 300000 250 410 620 850 180 1 1 1 1 1 9999 100500
141 yakini 10000 300000 250 340 580 820 130 1 1 1 1 1 9999 100501
142 justic 10000 300000 190 360 570 830 140 1 1 1 1 1 1 100502
143 sintyo 10000 300000 250 460 700 830 160 1 1 1 1 1 6 100503
144 ascand 10000 100000 320 540 800 900 180 1 1 1 1 1 0 100347
145 blackl 10000 100000 190 410 730 840 120 1 1 1 1 1 3 100506
146 childr 10000 200000 240 390 560 620 140 1 1 1 1 1 0 100043
147 tsukai 10000 200000 190 440 720 760 130 1 1 1 1 1 1 100044
148 rideon 10000 200000 290 410 600 800 160 1 1 1 1 1 1 100067
149 minest 10000 100000 210 390 620 760 130 1 1 1 1 1 1 100507
150 ordine 10000 100000 250 430 730 820 190 1 1 1 1 1 3 100508
151 dreamw 10000 100000 260 370 620 750 160 1 1 1 1 1 0 100509
152 minerv 10000 100000 320 610 900 0 250 1 1 1 0 1 4 100510
153 wannab 10000 200000 90 230 400 650 50 1 1 1 1 1 3 100001
154 sekain 10000 100000 260 390 690 780 160 1 1 1 1 1 1 100511
155 farawa 10000 100000 230 360 600 760 180 1 1 1 1 1 7 100512
156 crissc 10000 200000 370 630 860 910 170 1 1 1 1 1 4 100100
157 speedy 10000 100000 220 550 770 0 110 1 1 1 0 1 8 100324
158 xxxrev 10000 100000 210 340 560 730 150 1 1 1 1 1 0 100513
159 higame 10000 200000 200 300 580 710 130 1 1 1 1 1 3 100016
160 theepi 10000 200000 190 400 610 750 140 1 1 1 1 1 3 100022
161 anomie 10000 200000 220 380 610 770 150 1 1 1 1 1 0 100023
162 crocus 10000 100000 260 370 600 720 150 1 1 1 1 1 7 100524
163 lavien 10000 100000 270 410 710 800 180 1 1 1 1 1 5 100546
164 megaro2 10000 100000 0 0 990 1000 0 0 0 1 1 0 4 100361
165 chipnn 10000 100000 270 340 610 790 160 1 1 1 1 1 6 100541
166 yiyoyi 10000 200000 140 330 560 700 70 1 1 1 1 1 3 100007
167 binary 10000 200000 170 350 640 890 140 1 1 1 1 1 1 100014
168 makaim 10000 200000 300 500 770 0 230 1 1 1 0 1 3 100054
169 gyakut 10000 200000 150 210 460 640 60 1 1 1 1 1 1 100055
170 basara 10000 200000 190 370 640 730 140 1 1 1 1 1 0 100056
171 daybre 10000 300000 160 320 530 720 90 1 1 1 1 1 0 100514
172 umiyur 10000 300000 140 280 460 640 80 1 1 1 1 1 1 100515
173 chalur 10000 300000 180 400 600 720 140 1 1 1 1 1 9999 100516
174 melanc 10000 300000 150 300 500 630 100 1 1 1 1 1 7 100517
175 konofu 10000 300000 230 350 620 810 110 1 1 1 1 1 1 100518
176 bladem 10000 100000 280 380 630 750 170 1 1 1 1 1 4 100526
177 southw 10000 100000 180 270 570 680 120 1 1 1 1 1 7 100536
178 ryuuse 10000 100000 210 320 590 0 130 1 1 1 0 1 1 100537
179 redhea 10000 300000 270 390 590 720 100 1 1 1 1 1 0 100519
180 warnin 10000 300000 250 360 610 740 120 1 1 1 1 1 9999 100520
181 topsec 10000 300000 240 340 510 640 130 1 1 1 1 1 9999 100521
182 dddoll 10000 300000 260 380 550 630 140 1 1 1 1 1 9999 100522
183 tracee 10000 300000 190 310 490 650 90 1 1 1 1 1 0 100548
184 drivin 10000 200000 230 400 660 760 80 1 1 1 1 1 7 100111
185 genzit 10000 200000 180 460 730 820 120 1 1 1 1 1 0 100118
186 aerial 10000 200000 110 280 560 710 50 1 1 1 1 1 1 100039
187 einher 10000 100000 290 400 740 800 160 1 1 1 1 1 4 100532
188 ariell 10000 100000 190 320 640 730 150 1 1 1 1 1 7 100540
189 firstl 10000 100000 250 360 650 770 170 1 1 1 1 1 1 100542
190 heartl 10000 100000 230 300 640 0 110 1 1 1 0 1 1 100550
191 erasee 10000 100000 220 350 580 680 120 1 1 1 1 1 0 100551
192 regene 10000 100000 200 300 560 700 130 1 1 1 1 1 0 100530
193 allelu 10000 100000 280 350 640 750 160 1 1 1 1 1 9999 100549
194 lighto 10000 100000 250 330 600 740 120 1 1 1 1 1 1 100543
195 termin 10000 100000 240 340 630 790 130 1 1 1 1 1 7 100552
196 ryuuse2 10000 100000 200 360 620 750 130 1 1 1 1 1 1 100556
197 prizmm 10000 100000 210 300 540 0 120 1 1 1 0 1 1 100547
198 samalv 10000 200000 190 390 580 770 130 1 1 1 1 1 6 100098
199 palpit 10000 100000 290 550 840 920 180 1 1 1 1 1 8 100544
200 gainen 10000 100000 260 370 630 0 150 1 1 1 0 1 9999 100558
201 moonsh 10000 100000 230 360 620 0 100 1 1 1 0 1 3 100525
202 moonki 10000 100000 250 390 640 0 130 1 1 1 0 1 1 100559
203 moonri 10000 200000 210 380 580 850 140 1 1 1 1 1 0 100560
204 goaway 10000 100000 230 450 590 700 100 1 1 1 1 1 0 100561
205 itback 10000 100000 230 380 710 0 120 1 1 1 0 1 3 100567
206 redhhh 10000 100000 240 390 770 0 130 1 1 1 0 1 4 100569
207 actual 10000 100000 250 380 800 0 140 1 1 1 0 1 0 100568
208 zonzon 10000 200000 160 330 630 670 50 1 1 1 1 1 1 100367
209 memorm 10000 100000 260 370 730 0 150 1 1 1 0 1 0 100565
210 kokoro 10000 100000 200 430 650 690 120 1 1 1 1 1 1 100554
211 poweri 10000 100000 260 490 750 910 130 1 1 1 1 1 4 100563
212 nisenn 10000 100000 0 0 760 0 0 0 0 1 0 0 8 100555
213 yukiya 10000 200000 190 400 610 0 110 1 1 1 0 1 3 100096
214 zankyo 10000 200000 180 380 570 740 100 1 1 1 1 1 5 100124
215 overlp 10000 200000 170 300 510 0 90 1 1 1 0 1 7 100119
216 fracta 10000 100000 310 520 830 0 190 1 1 1 0 1 3 100529
217 cantst 10000 100000 230 420 650 0 110 1 1 1 0 1 0 100455
218 primaa 10000 100000 180 350 540 750 120 1 1 1 1 1 0 100527
219 cyberg 10000 100000 230 350 600 0 120 1 1 1 0 1 0 100448
220 freakw 10000 200000 220 420 650 660 130 1 1 1 1 1 0 100018
221 aquali 10000 200000 160 340 580 0 110 1 1 1 0 1 4 100006
222 takesc 10000 100000 270 370 690 0 100 1 1 1 0 1 1 100572
223 cthugh 10000 100000 250 480 730 0 140 1 1 1 0 1 0 100531
224 thetaa 10000 100000 210 340 620 0 110 1 1 1 0 1 1 100571
225 nekofu 10000 300000 220 340 570 800 100 1 1 1 1 1 6 100493
226 howtru 10000 200000 120 250 530 740 80 1 1 1 1 1 0 100057
227 romanc 10000 200000 280 550 780 0 100 1 1 1 0 1 0 100047
228 kotobu 10000 200000 320 710 900 0 250 1 1 1 0 1 0 100573
229 xmasss 10000 300000 180 380 560 770 80 1 1 1 1 1 101 100417
230 galaxy 10000 300000 160 320 430 670 100 1 1 1 1 1 0 100600
231 rebell 10000 1000000 490 630 910 0 0 1 1 1 0 0 0 100601
232 anothe 10000 1000000 270 370 730 760 0 1 1 1 1 0 0 100602
233 addict 10000 1000000 200 340 520 620 0 1 1 1 1 0 0 100603
234 dirtyy 10000 1000000 150 280 590 740 0 1 1 1 1 0 0 100604
235 levelf 10000 300000 110 280 450 630 50 1 1 1 1 1 0 100605
236 omnive 10000 1000000 340 520 830 860 0 1 1 1 1 0 0 100606
237 kakuse 10000 1000000 170 550 750 0 0 1 1 1 0 0 0 100607
238 unbeli 10000 300000 130 260 380 620 70 1 1 1 1 1 0 100608
239 sonzai 10000 1000000 260 400 590 660 0 1 1 1 1 0 0 100609
240 okonik 10000 1000000 260 450 670 0 0 1 1 1 0 0 0 100610
241 crssho 10000 1000000 350 600 850 0 100 1 1 1 0 1 0 100611
242 reanim 10000 1000000 280 440 700 800 0 1 1 1 1 0 0 100612
243 kamino 10000 1000000 400 620 780 0 150 1 1 1 0 1 0 100613
244 fiveee 10000 300000 180 370 610 710 100 1 1 1 1 1 0 100614
245 granda 10000 1000000 210 380 790 0 0 1 1 1 0 0 0 100615
246 fronti2 10000 1000000 460 690 890 0 90 1 1 1 0 1 0 100616
247 saigon 10000 1000000 190 310 570 0 0 1 1 1 0 0 0 100617
248 replay 10000 300000 180 440 630 700 80 1 1 1 1 1 0 100618
249 mousou 10000 1000000 160 260 540 0 0 1 1 1 0 0 0 100619
250 aheadd 10000 300000 130 250 350 580 70 1 1 1 1 1 0 100620
251 musicr1 10000 100000 220 330 580 740 120 1 1 1 1 1 0 100621
252 getthe 10000 300000 170 370 490 660 60 1 1 1 1 1 0 100622
253 design 10000 1000000 150 390 680 690 0 1 1 1 1 0 0 100623
254 garnet 10000 1000000 260 460 700 940 0 1 1 1 1 0 0 100624
255 hopesb 10000 300000 100 250 440 610 70 1 1 1 1 1 0 100625
256 shooti 10000 300000 150 370 490 690 70 1 1 1 1 1 0 100626
257 dangan 10000 1000000 280 580 810 0 0 1 1 1 0 0 0 100627
258 impact 10000 1000000 240 600 720 900 200 1 1 1 1 1 0 100628
259 lightm 10000 300000 260 330 540 710 110 1 1 1 1 1 0 100629
260 miiroo 10000 300000 220 390 580 680 110 1 1 1 1 1 0 100630
261 voiceo 10000 1000000 180 340 580 590 0 1 1 1 1 0 0 100631
262 cosmol 10000 1000000 360 640 870 0 250 1 1 1 0 1 0 100632
263 vividd 10000 300000 160 350 550 650 90 1 1 1 1 1 0 100633
264 splash 10000 1000000 260 500 710 0 0 1 1 1 0 0 0 100634
265 donuth 10000 300000 220 400 540 800 110 1 1 1 1 1 0 100635
266 senbon 10000 300000 200 280 540 740 120 1 1 1 1 1 0 100636
267 kmtyju 10000 300000 240 310 570 740 120 1 1 1 1 1 0 100637
268 fronti 10000 1000000 480 650 820 0 130 1 1 1 0 1 0 100638
269 nueraa 10000 1000000 220 430 750 530 0 1 1 1 1 0 0 100639
270 childe 10000 300000 90 240 340 560 40 1 1 1 1 1 0 100640
271 dazzli2 10000 1000000 350 600 820 0 190 1 1 1 0 1 0 100641
272 perfec 10000 1000000 390 640 780 0 0 1 1 1 0 0 0 100642
273 flower 10000 300000 70 200 400 650 60 1 1 1 1 1 0 100643
274 frgmnt 10000 1000000 330 630 740 650 100 1 1 1 1 1 0 100644
275 headph 10000 1000000 240 320 520 0 0 1 1 1 0 0 0 100645
276 crsang 10000 1000000 270 530 670 0 130 1 1 1 0 1 0 100646
277 musicr4 10000 100000 190 320 580 0 120 1 1 1 0 1 0 100647
278 imaxim 10000 1000000 440 690 900 870 0 1 1 1 1 0 0 100648
279 azitat2 10000 1000000 230 520 660 0 80 1 1 1 0 1 0 100649
280 dynami 10000 1000000 260 540 680 0 110 1 1 1 0 1 0 100650
281 incave 10000 1000000 220 440 760 780 0 1 1 1 1 0 0 100651
282 aktuki 10000 1000000 260 580 840 0 100 1 1 1 0 1 0 100652
283 kindof 10000 1000000 140 290 480 0 0 1 1 1 0 0 0 100653
284 mikaku 10000 1000000 190 310 540 0 0 1 1 1 0 0 0 100654
285 strang 10000 1000000 120 280 550 0 0 1 1 1 0 0 0 100655
286 hesper 10000 1000000 360 610 920 930 0 1 1 1 1 0 0 100656
287 breaka 10000 300000 150 310 450 680 70 1 1 1 1 1 0 100657
288 myname 10000 1000000 60 140 300 570 0 1 1 1 1 0 0 100658
289 amaiko 10000 1000000 150 370 600 0 0 1 1 1 0 0 0 100659
290 reseed2 10000 1000000 220 470 630 0 0 1 1 1 0 0 0 100660
291 kingst 10000 1000000 380 630 740 0 120 1 1 1 0 1 0 100661
292 ramram 10000 1000000 230 340 670 0 0 1 1 1 0 0 0 100662
293 murasa 10000 1000000 280 410 760 0 0 1 1 1 0 0 0 100663
294 happyd 10000 1100000 220 410 730 790 180 1 1 1 1 1 0 100664
295 izimed 10000 300000 190 390 690 770 90 1 1 1 1 1 0 100665
296 wastel 10000 1000000 40 120 230 400 0 1 1 1 1 0 0 100666
297 assign 10000 1000000 260 430 610 620 0 1 1 1 1 0 0 100667
298 jahaci 10000 1000000 170 290 590 0 0 1 1 1 0 0 0 100668
299 hisuii 10000 1000000 220 470 700 0 0 1 1 1 0 0 0 100669
300 godkno 10000 300000 100 260 450 640 60 1 1 1 1 1 0 100670
301 roadof 10000 300000 150 360 500 750 70 1 1 1 1 1 0 100671
302 rokuch 10000 300000 210 350 620 810 110 1 1 1 1 1 0 100672
303 valent 10000 300000 270 330 590 770 100 1 1 1 1 1 0 100673
304 unfini 10000 300000 160 320 500 710 80 1 1 1 1 1 0 100674
305 auflcb2 10000 1000000 220 370 750 0 100 1 1 1 0 1 0 100675
306 burnin 10000 1000000 180 280 600 850 150 1 1 1 1 1 0 100676
307 sphere 10000 1000000 200 380 730 0 0 1 1 1 0 0 0 100677
308 dropou 10000 300000 170 310 460 690 140 1 1 1 1 1 0 100678
309 xencou 10000 300000 200 320 520 600 80 1 1 1 1 1 0 100679
310 killyk 10000 300000 130 420 630 760 60 1 1 1 1 1 0 100680
311 missil 10000 1000000 160 380 590 0 0 1 1 1 0 0 0 100681
312 burstt 10000 300000 120 250 460 630 70 1 1 1 1 1 0 100682
313 musicr2 10000 100000 220 330 580 0 120 1 1 1 0 1 0 100683
314 isingl 10000 1000000 250 440 800 0 120 1 1 1 0 1 0 100684
315 lvless 10000 1000000 230 380 600 0 0 1 1 1 0 0 0 100685
316 sapphi 10000 1000000 290 440 810 0 0 1 1 1 0 0 0 100686
317 musicr3 10000 100000 190 320 580 720 120 1 1 1 1 1 0 100687
318 deeout 10000 1000000 180 340 630 810 0 1 1 1 1 0 0 100688
319 sugars 10000 300000 170 300 420 660 60 1 1 1 1 1 0 100689
320 mercur 10000 1000000 140 350 660 0 0 1 1 1 0 0 0 100690
321 zizizi 10000 1000000 300 570 880 960 0 1 1 1 1 0 0 100691
322 wegooo 10000 300000 180 340 540 680 100 1 1 1 1 1 0 100692
323 alonee 10000 300000 110 210 360 480 50 1 1 1 1 1 0 100693
324 nuheat 10000 1000000 290 440 650 850 0 1 1 1 1 0 0 100694
325 granro 10000 300000 150 280 430 600 80 1 1 1 1 1 0 100695
326 sister 10000 300000 100 270 460 630 70 1 1 1 1 1 0 100696
327 lotusl 10000 1000000 200 360 640 0 0 1 1 1 0 0 0 100697
328 yukari 10000 1000000 310 500 760 840 0 1 1 1 1 0 0 100698
329 flawli 10000 300000 170 300 400 590 80 1 1 1 1 1 0 100699
330 nightf 10000 1000000 150 280 460 710 0 1 1 1 1 0 0 100700
331 random 10000 100000 0 0 0 0 0 0 0 0 0 0 0 100701
332 wiwwtw 10000 1000000 260 380 620 0 0 1 1 1 0 0 0 100702
333 inneru 10000 300000 220 360 480 670 90 1 1 1 1 1 0 100703
334 taishi 10000 1000000 190 350 580 0 0 1 1 1 0 0 0 100704
335 daysss 10000 1000000 380 590 810 810 0 1 1 1 1 0 0 100705
336 bokuwa 10000 300000 230 340 550 690 160 1 1 1 1 1 0 100706
337 showww 10000 300000 180 350 510 790 150 1 1 1 1 1 0 100707
338 nevers 10000 300000 260 320 650 750 150 1 1 1 1 1 0 100708
339 bleeze 10000 300000 160 310 470 620 90 1 1 1 1 1 0 100709
340 dreami 10000 1000000 140 370 650 0 0 1 1 1 0 0 0 100710
341 allune 10000 1000000 140 350 710 0 0 1 1 1 0 0 0 100711
342 always 10000 1000000 130 270 490 0 0 1 1 1 0 0 0 100712
343 anomie2 10000 1000000 160 430 840 0 0 1 1 1 0 0 0 100713
344 aquali2 10000 1000000 220 430 600 810 0 1 1 1 1 0 0 100714
345 astaro 10000 1000000 230 400 740 0 0 1 1 1 0 0 0 100715
346 bassan 10000 1000000 200 320 660 0 0 1 1 1 0 0 0 100716
347 zonzon2 10000 1000000 130 270 680 750 0 1 1 1 1 0 0 100717
348 bouled 10000 1000000 190 300 570 0 0 1 1 1 0 0 0 100718
349 brandn 10000 1000000 90 390 660 720 0 1 1 1 1 0 0 100719
350 bravee 10000 1000000 350 600 820 0 250 1 1 1 0 -1 0 100720
351 breakd2 10000 1000000 340 640 740 0 0 1 1 1 0 0 0 100721
352 buffet 10000 1000000 380 550 680 0 300 1 1 1 0 -1 0 100722
353 buzzke 10000 1000000 180 330 580 770 0 1 1 1 1 0 0 100723
354 cashhh 10000 1000000 190 250 640 0 0 1 1 1 0 0 0 100724
355 cloudb 10000 1000000 370 660 740 0 250 1 1 1 0 -1 0 100725
356 clouds 10000 1000000 130 250 470 0 0 1 1 1 0 0 0 100726
357 codepa 10000 1000000 290 550 700 0 150 1 1 1 0 -1 0 100727
358 comear 10000 1000000 380 560 830 0 250 1 1 1 0 -1 0 100728
359 crysta 10000 1000000 370 560 810 0 300 1 1 1 0 -1 0 100729
360 curseo 10000 1000000 220 360 740 0 0 1 1 1 0 0 0 100730
361 datami 10000 1000000 180 360 660 0 0 1 1 1 0 0 0 100731
362 defaul 10000 1000000 210 330 480 0 0 1 1 1 0 0 0 100732
363 design2 10000 1000000 250 430 680 0 0 1 1 1 0 0 0 100733
364 diamon 10000 1000000 100 260 330 0 0 1 1 1 0 0 0 100734
365 dispel 10000 1000000 280 480 800 0 0 1 1 1 0 0 0 100735
366 distan 10000 1000000 200 300 680 0 0 1 1 1 0 0 0 100736
367 dokibl 10000 1000000 150 230 670 0 0 1 1 1 0 0 0 100737
368 dontwa 10000 1000000 130 340 690 0 0 1 1 1 0 0 0 100738
369 drgirl 10000 1000000 190 350 540 730 0 1 1 1 1 0 0 100739
370 eterna 10000 1000000 120 210 390 0 0 1 1 1 0 0 0 100740
371 everkr 10000 1000000 180 290 410 0 0 1 1 1 0 0 0 100741
372 everwh 10000 1000000 200 310 580 0 0 1 1 1 0 0 0 100742
373 farthe 10000 1000000 300 560 780 870 0 1 1 1 1 0 0 100743
374 filame 10000 1000000 230 380 630 0 0 1 1 1 0 0 0 100744
375 flameu2 10000 1000000 170 240 590 0 0 1 1 1 0 0 0 100745
376 freeee 10000 1000000 190 390 690 0 0 1 1 1 0 0 0 100746
377 funkyb2 10000 1000000 210 340 560 0 0 1 1 1 0 0 0 100747
378 granda2 10000 1000000 240 410 730 830 0 1 1 1 1 0 0 100748
379 hsphsp 10000 1000000 120 250 690 0 0 1 1 1 0 0 0 100749
380 halluc 10000 1000000 400 520 870 0 0 1 1 1 0 0 0 100750
381 indigo 10000 1000000 170 330 500 750 0 1 1 1 1 0 0 100751
382 inters 10000 1000000 250 420 770 0 0 1 1 1 0 0 0 100752
383 incave2 10000 1000000 310 570 880 0 0 1 1 1 0 0 0 100753
384 ioniza 10000 1000000 170 340 700 850 0 1 1 1 1 0 0 100754
385 guilty 10000 1000000 150 280 500 0 0 1 1 1 0 0 0 100755
386 keraun 10000 1000000 250 520 790 0 0 1 1 1 0 0 0 100756
387 landin2 10000 1000000 200 340 590 660 0 1 1 1 1 0 0 100757
388 videog 10000 1000000 210 370 620 0 0 1 1 1 0 0 0 100758
389 loseyo 10000 1000000 200 300 710 0 0 1 1 1 0 0 0 100759
390 machin 10000 1000000 120 280 720 0 0 1 1 1 0 0 0 100760
391 makeit 10000 1000000 110 240 480 0 0 1 1 1 0 0 0 100761
392 daydre 10000 1000000 190 360 800 0 0 1 1 1 0 0 0 100762
393 metron 10000 1000000 200 440 710 0 0 1 1 1 0 0 0 100763
394 milkyw 10000 1000000 220 310 600 0 0 1 1 1 0 0 0 100764
395 nayuta 10000 1000000 170 370 680 0 0 1 1 1 0 0 0 100766
396 nightm 10000 1000000 200 490 730 0 0 1 1 1 0 0 0 100767
397 otherw 10000 1000000 230 410 760 0 0 1 1 1 0 0 0 100768
398 overth 10000 1000000 330 570 820 0 250 1 1 1 0 -1 0 100769
399 uuuuuu 10000 1000000 230 370 740 0 0 1 1 1 0 0 0 100770
400 rainin 10000 1000000 160 410 690 0 0 1 1 1 0 0 0 100771
401 raisey 10000 1000000 230 550 750 0 150 1 1 1 0 -1 0 100772
402 resona 10000 1000000 170 320 640 0 0 1 1 1 0 0 0 100773
403 reuniv 10000 1000000 140 230 410 0 0 1 1 1 0 0 0 100774
404 rhythm 10000 1000000 370 560 780 0 250 1 1 1 0 -1 0 100775
405 rushhh 10000 1000000 250 370 750 0 0 1 1 1 0 0 0 100776
406 steeee 10000 1000000 300 580 870 0 0 1 1 1 0 0 0 100777
407 sangey 10000 1000000 270 470 850 0 0 1 1 1 0 0 0 100778
408 senpai 10000 1000000 380 540 770 0 250 1 1 1 0 -1 0 100779
409 sestea 10000 1000000 270 470 760 0 0 1 1 1 0 0 0 100780
410 silver 10000 1000000 280 400 690 0 0 1 1 1 0 0 0 100781
411 sodama 10000 1000000 200 400 650 0 0 1 1 1 0 0 0 100782
412 stardu 10000 1000000 190 330 640 0 0 1 1 1 0 0 0 100783
413 starti 10000 1000000 170 310 540 700 0 1 1 1 1 0 0 100784
414 sunday 10000 1000000 180 290 460 670 0 1 1 1 1 0 0 100785
415 sundro2 10000 1000000 300 480 790 820 0 1 1 1 1 0 0 100786
416 sunnyd 10000 1000000 230 380 590 0 0 1 1 1 0 0 0 100787
417 superl 10000 1000000 150 320 590 0 0 1 1 1 0 0 0 100788
418 switch 10000 1000000 160 350 690 0 0 1 1 1 0 0 0 100789
419 theepi2 10000 1000000 220 370 650 0 0 1 1 1 0 0 0 100790
420 epipha 10000 1000000 150 300 700 0 0 1 1 1 0 0 0 100791
421 thekin 10000 1000000 220 520 750 0 0 1 1 1 0 0 0 100792
422 timele 10000 1000000 160 330 720 0 0 1 1 1 0 0 0 100793
423 tokyoo 10000 1000000 150 330 710 0 0 1 1 1 0 0 0 100794
424 toooma 10000 1000000 300 510 770 0 0 1 1 1 0 0 0 100795
425 toucho2 10000 1000000 170 320 520 780 0 1 1 1 1 0 0 100796
426 tayuta 10000 1000000 260 350 720 0 0 1 1 1 0 0 0 100797
427 ultrix 10000 1000000 270 450 760 0 0 1 1 1 0 0 0 100798
428 underw 10000 1000000 290 460 690 860 0 1 1 1 1 0 0 100799
429 virtua 10000 1000000 150 350 630 0 0 1 1 1 0 0 0 100800
430 voiceo2 10000 1000000 140 380 670 0 0 1 1 1 0 0 0 100801
431 wannab2 10000 1000000 260 410 690 0 0 1 1 1 0 0 0 100802
432 wiwwtw2 10000 1000000 200 430 670 720 0 1 1 1 1 0 0 100803
433 wingso 10000 1000000 200 530 710 0 0 1 1 1 0 0 0 100804
434 winter 10000 1000000 140 240 410 0 0 1 1 1 0 0 0 100805
435 iineee 10000 1000000 210 400 810 0 0 1 1 1 0 0 0 100806
436 illumi 10000 1000000 100 250 460 630 0 1 1 1 1 0 0 100807
437 yellll 10000 1000000 80 170 520 0 0 1 1 1 0 0 0 100808
438 eschat 10000 1000000 360 570 770 0 250 1 1 1 0 -1 0 100809
439 counte 10000 1000000 290 340 710 0 0 1 1 1 0 0 0 100810
440 gimcho 10000 1000000 180 390 700 0 0 1 1 1 0 0 0 100811
441 surviv 10000 1000000 240 400 650 0 0 1 1 1 0 0 0 100812
442 turkis3 10000 1000000 60 200 480 0 0 1 1 1 0 0 0 100814
443 picora2 10000 1000000 280 530 800 0 0 1 1 1 0 0 0 100815
444 fortis 10000 1000000 200 370 530 0 0 1 1 1 0 0 0 100816
445 hedban 10000 1000000 160 430 660 0 0 1 1 1 0 0 0 100817
446 megitu 10000 1000000 150 300 490 0 0 1 1 1 0 0 0 100818
447 rockma 10000 1000000 270 480 730 0 0 1 1 1 0 0 0 100819
448 kounen2 10000 1000000 210 430 730 0 0 1 1 1 0 0 0 100820
449 saisyu 10000 1000000 180 360 560 0 0 1 1 1 0 0 0 100821
450 yuukan 10000 1000000 220 330 780 0 0 1 1 1 0 0 0 100822
451 modern 10000 1000000 200 320 560 0 0 1 1 1 0 0 0 100823
452 miraie 10000 1000000 210 350 660 0 0 1 1 1 0 0 0 100824
453 ranfes 10000 1000000 200 420 650 0 0 1 1 1 0 0 0 100825
454 nemure 10000 1000000 150 380 670 760 0 1 1 1 1 0 0 100826
455 yuwaku 10000 1000000 150 260 430 0 0 1 1 1 0 0 0 100827
456 dontst 10000 1000000 150 320 560 700 0 1 1 1 1 0 0 100828
457 mottai 10000 1000000 100 260 360 0 0 1 1 1 0 0 0 100829
458 slysly 10000 1000000 100 330 580 0 0 1 1 1 0 0 0 100830
459 lookam 10000 1000000 170 340 670 0 0 1 1 1 0 0 0 100831
460 feverr 10000 1000000 280 480 680 0 0 1 1 1 0 0 0 100832
461 fashio 10000 1000000 80 240 390 0 0 1 1 1 0 0 0 100833
462 hagito 10000 1000000 120 260 500 0 0 1 1 1 0 0 0 100834
463 invade 10000 1000000 100 280 470 0 0 1 1 1 0 0 0 100835
464 ainoch 10000 1000000 170 400 590 0 0 1 1 1 0 0 0 100836
465 nakama 10000 1000000 140 320 530 0 0 1 1 1 0 0 0 100837
466 ninjar 10000 1000000 80 230 410 650 0 1 1 1 1 0 0 100838
467 parall 10000 1000000 140 350 610 0 0 1 1 1 0 0 0 100839
468 yukifu 10000 1000000 130 290 510 0 0 1 1 1 0 0 0 100840
469 furiso 10000 1000000 120 240 440 740 0 1 1 1 1 0 0 100841
470 honeyj 10000 100000 320 630 880 930 240 1 1 1 1 1 6 100842
471 emeraj 10000 100000 300 530 850 0 190 1 1 1 0 1 1 100843
472 dazzlo 10000 200000 350 600 800 900 160 1 1 1 1 1 1 100844

Binary file not shown.
1 1 1 1601510400 4096483201 1 0 0 0 1 0 news1069 1 1
2 2 1 1601510400 4096483201 1 0 0 0 1 0 news1070 1 1

Binary file not shown.
1 1 0 100 100 100 100 100 100 100 100 0 0
2 2 100 110 101 101 103 101 101 101 101 1000 0
3 3 210 120 102 102 106 102 102 102 102 0 0
4 4 331 130 103 103 109 103 103 103 103 0 0
5 5 464 140 104 104 112 104 104 104 104 1001 0
6 6 610 150 105 105 115 105 105 105 105 1002 0
7 7 771 160 106 106 118 106 106 106 106 1003 0
8 8 948 170 107 107 121 107 107 107 107 0 0
9 9 1143 180 108 108 124 108 108 108 108 0 0
10 10 1357 190 109 109 127 109 109 109 109 1004 0
11 11 1593 200 110 110 130 110 110 110 110 0 0
12 12 1853 210 111 111 133 111 111 111 111 0 0
13 13 2138 220 112 112 136 112 112 112 112 0 0
14 14 2452 230 113 113 139 113 113 113 113 0 0
15 15 2797 240 114 114 142 114 114 114 114 1005 0
16 16 3177 250 115 115 145 115 115 115 115 0 0
17 17 3594 260 116 116 148 116 116 116 116 0 0
18 18 4054 270 117 117 151 117 117 117 117 0 0
19 19 4559 280 118 118 154 118 118 118 118 0 0
20 20 5115 290 119 119 157 119 119 119 119 1006 1
21 21 5727 300 120 120 160 120 120 120 120 0 1
22 22 6400 310 121 121 163 121 121 121 121 0 1
23 23 7140 320 122 122 166 122 122 122 122 0 1
24 24 7954 330 123 123 169 123 123 123 123 0 1
25 25 8849 340 124 124 172 124 124 124 124 0 1
26 26 9834 350 125 125 175 125 125 125 125 0 1
27 27 10918 360 126 126 178 126 126 126 126 0 1
28 28 12109 370 127 127 181 127 127 127 127 0 1
29 29 13420 380 128 128 184 128 128 128 128 0 1
30 30 14863 390 129 129 187 129 129 129 129 0 1
31 31 16449 400 130 130 190 130 130 130 130 0 1
32 32 18194 410 131 131 193 131 131 131 131 0 1
33 33 20113 420 132 132 196 132 132 132 132 0 1
34 34 22225 430 133 133 199 133 133 133 133 0 1
35 35 24547 440 134 134 202 134 134 134 134 0 1
36 36 27102 450 135 135 205 135 135 135 135 0 1
37 37 29912 460 136 136 208 136 136 136 136 0 1
38 38 33003 470 137 137 211 137 137 137 137 0 1
39 39 36404 480 138 138 214 138 138 138 138 0 1
40 40 40144 490 139 139 217 139 139 139 139 0 1
41 41 44259 500 140 140 220 140 140 140 140 0 1
42 42 48785 510 141 141 223 141 141 141 141 0 1
43 43 53763 520 142 142 226 142 142 142 142 0 1
44 44 59240 530 143 143 229 143 143 143 143 0 1
45 45 65264 540 144 144 232 144 144 144 144 0 1
46 46 71890 550 145 145 235 145 145 145 145 0 1
47 47 79179 560 146 146 238 146 146 146 146 0 1
48 48 87197 570 147 147 241 147 147 147 147 0 1
49 49 96017 580 148 148 244 148 148 148 148 0 1
50 50 105718 590 149 149 247 149 149 149 149 0 2
51 51 116390 600 150 150 250 150 150 150 150 0 2
52 52 128129 610 151 151 253 151 151 151 151 0 2
53 53 141042 620 152 152 256 152 152 152 152 0 2
54 54 155247 630 153 153 259 153 153 153 153 0 2
55 55 170871 640 154 154 262 154 154 154 154 0 2
56 56 188059 650 155 155 265 155 155 155 155 0 2
57 57 206965 660 156 156 268 156 156 156 156 0 2
58 58 227761 670 157 157 271 157 157 157 157 0 2
59 59 250637 680 158 158 274 158 158 158 158 0 2
60 60 275801 690 159 159 277 159 159 159 159 0 2
61 61 303481 700 160 160 280 160 160 160 160 0 2
62 62 333929 710 161 161 283 161 161 161 161 0 2
63 63 367422 720 162 162 286 162 162 162 162 0 2
64 64 404265 730 163 163 289 163 163 163 163 0 2
65 65 444791 740 164 164 292 164 164 164 164 0 2
66 66 489370 750 165 165 295 165 165 165 165 0 2
67 67 538407 760 166 166 298 166 166 166 166 0 2
68 68 592348 770 167 167 301 167 167 167 167 0 2
69 69 651683 780 168 168 304 168 168 168 168 0 2
70 70 716951 790 169 169 307 169 169 169 169 0 2
71 71 788746 800 170 170 310 170 170 170 170 0 2
72 72 867721 810 171 171 313 171 171 171 171 0 2
73 73 954593 820 172 172 316 172 172 172 172 0 2
74 74 1050153 830 173 173 319 173 173 173 173 0 2
75 75 1155268 840 174 174 322 174 174 174 174 0 2
76 76 1270895 850 175 175 325 175 175 175 175 0 2
77 77 1398084 860 176 176 328 176 176 176 176 0 2
78 78 1537993 870 177 177 331 177 177 177 177 0 2
79 79 1691892 880 178 178 334 178 178 178 178 0 2
80 80 1861182 890 179 179 337 179 179 179 179 0 2
81 81 2047400 900 180 180 340 180 180 180 180 0 2
82 82 2252240 910 181 181 343 181 181 181 181 0 2
83 83 2477564 920 182 182 346 182 182 182 182 0 2
84 84 2725420 930 183 183 349 183 183 183 183 0 2
85 85 2998062 940 184 184 352 184 184 184 184 0 2
86 86 3297969 950 185 185 355 185 185 185 185 0 2
87 87 3627865 960 186 186 358 186 186 186 186 0 2
88 88 3990752 970 187 187 361 187 187 187 187 0 2
89 89 4389927 980 188 188 364 188 188 188 188 0 2
90 90 4829020 990 189 189 367 189 189 189 189 0 2
91 91 5312022 1000 190 190 370 190 190 190 190 0 2
92 92 5843324 1010 191 191 373 191 191 191 191 0 2
93 93 6427757 1020 192 192 376 192 192 192 192 0 2
94 94 7070633 1030 193 193 379 193 193 193 193 0 2
95 95 7777796 1040 194 194 382 194 194 194 194 0 2
96 96 8555676 1050 195 195 385 195 195 195 195 0 2
97 97 9411343 1060 196 196 388 196 196 196 196 0 2
98 98 10352578 1070 197 197 391 197 197 197 197 0 2
99 99 11387935 1080 198 198 394 198 198 198 198 0 2
100 100 12526829 1090 199 199 397 199 199 199 199 0 2

Binary file not shown.
1 1000 1 10000 1 -1 - 1411697520 1670178694 ic0000 10 1 1 先行解禁 1 -
2 1001 2 10000 1 -1 - 1411697520 1670178694 ic0001 10 1 1 先行解禁 1 -
3 1002 3 10000 1 -1 - 1412103600 1670178694 ic0002 10 2 1 先行解禁 1 -

Binary file not shown.
1 shopID. 整理用No. Ver. 出現フラグ 出現フラグ参照ID 条件 出現時間 消滅時間 MusicCode 価格 表示タイプ Text Type Value(op) Value 対象曲 Difficulty(op) Difficulty Level(op) Level Grade(Op) Grade GaugeType(op) GaugeType HS(op) HS APP DAP F-V F-H FullCombo Combo(op) Combo ClearRate(op) ClearRate プレイ日 地域
2 0 1 1.00.00 3 1 - 1411697520.0288 1443233520.0288 megaro 0 0 - -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
3 1 2 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 nature 10 2 ??? -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
4 2 3 1.00.00 2 -1 - 1412103600.0288 1443639598.992 hopesb 30 1 「Landing on the moon」をSTANDARD以上でクリアする。 0 -1 -1 landin 1 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
5 3 4 1.00.00 1 -1 - 1412103600.0288 1443639598.992 flower 10 0 - -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
6 4 5 1.00.02 1 -1 1&2&3 1412103600.0288 1443639598.992 reseed3 10 0 「Human Nature」「Hopes Bright」「Flowerwall」をクリアする。 -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
7 5 6 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 dennou 20 1 - 0 -1 -1 flower 1 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 -1 -1 -1 -1
8 6 7 1.00.00 2 -1 5&7 1411697520.0288 1443233520.0288 romanc 10 1 - -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
9 7 8 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 landin 40 1 - -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
10 8 9 1.00.00 1 -1 7 1411697520.0288 1443233520.0288 ididid 50 0 - -1 -1 -1 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 2 -1 -1 -1 -1
11 9 10 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 crissc 60 0 MASTER以上の2曲S+以上フルコンボクリアする。 1 1 2 - 1 2 -1 0 1 1 1 2 -1 -1 -1 -1 -1 -1 1 -1 -1 -1 -1
12 10 11 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 dazzli 70 1 MASTER以上の4曲S+以上クリアする。 1 1 4 - 1 2 -1 0 1 1 1 2 -1 -1 -1 -1 -1 -1 2 -1 -1 -1 -1
13 11 12 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 izimed 987654 1 MASTER以上の7曲S+以上クリアする。 1 1 7 - 1 2 -1 0 1 1 1 2 -1 -1 -1 -1 -1 -1 2 -1 -1 -1 -1

Binary file not shown.
1 saleID. �J�n�� �I���� ShopID Price
2 0 1411696799 1443236400 0 7000
3 1 1411783199 1443322800 1 7000

Binary file not shown.
1 shopID. 整理用No. Ver. 出現フラグ 出現フラグ参照ID 条件 出現時間 消滅時間 ItemCode 価格 表示タイプ Text Type Value(op) Value 対象曲 Difficulty(op) Difficulty Level(op) Level Grade(Op) Grade GaugeType(op) GaugeType HS(op)i HS APP DAP F-V F-H FullCombo Combo(op) Combo ClearRate(op) ClearRate プレイ日 地域
2 3000 1 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 skb0000 10 1 MASTER以上の2曲S+以上フルコンボクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
3 3001 2 1.00.00 1 -1 - 1411697520.0288 1443233520.0288 skb0001 10 1 Next Frontier (Master)をクリア 0 -1 -1 bleeze 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
4 3002 3 1.00.00 1 -1 - 1412103600.0288 1443639598.992 skb0002 10 2 Master以上を1曲をS+以上でクリアする。 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1

Binary file not shown.
1 shopID. �����pNo. Ver. �o���t���O �o���t���O�Q��ID ���� �o������ ���Ŏ��� ItemCode ���i �\���^�C�v Text Type Value(op) Value �Ώۋ� Difficulty(op) Difficulty Level(op) Level Grade(Op) Grade GaugeType(op) GaugeType HS(op)i HS APP DAP F-V F-H FullCombo Combo(op) Combo ClearRate(op) ClearRate �v���C�� �n��
2 5000 1 10000 1 -1 - 1411697520 1443233520 ske0000 10 1 MASTER�ȏ��2��S+�ȏ�t���R���{�N���A����B 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
3 5001 2 10000 1 -1 - 1411697520 1443233520 ske0001 10 1 Next Frontier (Master�j���N���A 0 -1 -1 megaro -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
4 5002 3 10000 1 -1 - 1412103600 1443639598 ske0002 10 2 Master�ȏ��1�Ȃ�S+�ȏ�ŃN���A����B 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1
5 5003 4 10000 1 -1 - 1412103600 1443639598 ske0003 10 0 Master�ȏ��1�Ȃ�S+�ȏ�ŃN���A����B 1 1 1 - 1 2 -1 -1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
6 5004 5 10000 1 -1 - 1412103600 1443639598 ske0004 10 2 2�ȃN���A 1 1 2 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
7 5005 5 10000 1 -1 - 1412103600 1443639598 ske0005 10 2 3�ȃN���A 1 1 3 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
8 5006 5 10000 1 -1 - 1412103600 1443639598 ske0006 10 2 4�ȃN���A 1 1 4 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
9 5007 5 10000 1 -1 - 1412103600 1443639598 ske0007 10 2 5�ȃN���A 1 1 5 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
10 5008 5 10000 1 -1 - 1412103600 1443639598 ske0008 10 2 6�ȃN���A 1 1 6 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
11 5009 5 10000 1 -1 - 1412103600 1443639598 ske0009 10 2 7�ȃN���A 1 1 7 - -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1

Some files were not shown because too many files have changed in this diff Show More