# vim: set fileencoding=utf-8 import copy from typing import Any, Dict, List, Tuple from bemani.backend.sdvx.gravitywars import SoundVoltexGravityWars from bemani.common import ID, Time, ValidatedDict from bemani.data import Score, UserID from bemani.protocol import Node class SoundVoltexGravityWarsSeason2( SoundVoltexGravityWars, ): def _get_skill_analyzer_seasons(self) -> Dict[int, str]: return { 1: 'SKILL ANALYZER 第1回 Aコース', 2: 'SKILL ANALYZER 第1回 Bコース', 3: 'SKILL ANALYZER 第1回 Cコース', 4: 'The 4th KAC コース', 5: 'SKILL ANALYZER 第2回 Aコース', 6: 'SKILL ANALYZER 第2回 Bコース', 7: 'SKILL ANALYZER 第2回 Cコース', 8: 'SKILL ANALYZER 第3回 Aコース', 9: 'SKILL ANALYZER 第3回 Bコース', 10: 'SKILL ANALYZER 第3回 Cコース', 11: 'SKILL ANALYZER 第4回', 12: 'SKILL ANALYZER 第5回 Aコース', 13: 'SKILL ANALYZER 第5回 Bコース', 14: 'SKILL ANALYZER 第5回 Cコース', 15: 'SKILL ANALYZER 第6回 Aコース', 16: 'SKILL ANALYZER 第6回 Bコース', 17: '天下一コース', 18: 'The 5th KAC コース', 19: 'VOLTEXES コース', 20: 'SKILL ANALYZER 第7回', 21: 'SKILL ANALYZER 第8回', } def _get_skill_analyzer_courses(self) -> List[Dict[str, Any]]: return [ { 'level': 0, 'season_id': 1, 'tracks': [ { 'id': 109, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 283, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 279, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 1, 'tracks': [ { 'id': 76, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 196, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 8, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 1, 'tracks': [ { 'id': 90, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 228, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 80, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 3, 'season_id': 1, 'tracks': [ { 'id': 125, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 201, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 237, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 1, 'tracks': [ { 'id': 393, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 352, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 66, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 5, 'season_id': 1, 'tracks': [ { 'id': 383, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 511, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 331, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 6, 'season_id': 1, 'tracks': [ { 'id': 422, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 445, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 71, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 1, 'tracks': [ { 'id': 454, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 158, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 173, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 8, 'season_id': 1, 'tracks': [ { 'id': 322, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 63, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 124, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 1, 'tracks': [ { 'id': 348, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 73, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 259, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 0, 'season_id': 2, 'tracks': [ { 'id': 374, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 84, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 303, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 2, 'tracks': [ { 'id': 22, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 274, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 183, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 2, 'tracks': [ { 'id': 56, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 244, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 4, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 3, 'season_id': 2, 'tracks': [ { 'id': 414, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 209, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 334, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 2, 'tracks': [ { 'id': 123, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 403, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 23, 'type': self.CHART_TYPE_INFINITE, }, ], }, { 'level': 5, 'season_id': 2, 'tracks': [ { 'id': 391, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 239, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 426, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 6, 'season_id': 2, 'tracks': [ { 'id': 389, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 89, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 246, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 2, 'tracks': [ { 'id': 419, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 299, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 341, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 8, 'season_id': 2, 'tracks': [ { 'id': 394, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 466, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 47, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 2, 'tracks': [ { 'id': 500, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 247, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 229, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 0, 'season_id': 3, 'tracks': [ { 'id': 36, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 189, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 171, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 3, 'tracks': [ { 'id': 182, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 3, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 105, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 3, 'tracks': [ { 'id': 14, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 120, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 86, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 3, 'season_id': 3, 'tracks': [ { 'id': 390, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 243, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 186, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 3, 'tracks': [ { 'id': 36, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 423, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 59, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 5, 'season_id': 3, 'tracks': [ { 'id': 452, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 262, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 480, 'type': self.CHART_TYPE_INFINITE, }, ], }, { 'level': 6, 'season_id': 3, 'tracks': [ { 'id': 411, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 70, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 211, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 3, 'tracks': [ { 'id': 30, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 72, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 293, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 8, 'season_id': 3, 'tracks': [ { 'id': 87, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 117, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 269, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 3, 'tracks': [ { 'id': 498, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 437, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 126, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 0, 'level': -1, 'skill_name': 'エンジョイ♪ごりらコースA', 'skill_name_id': 12, 'season_id': 4, 'tracks': [ { 'id': 466, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 273, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 470, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 1, 'level': -1, 'skill_name': 'エンジョイ♪ごりらコースB', 'skill_name_id': 12, 'season_id': 4, 'tracks': [ { 'id': 194, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 343, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 501, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 2, 'level': -1, 'skill_name': 'エンジョイ♪ごりらコースC', 'skill_name_id': 12, 'season_id': 4, 'tracks': [ { 'id': 356, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 7, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 472, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 3, 'level': -1, 'skill_name': 'エンジョイ♪ごりらコースD', 'skill_name_id': 12, 'season_id': 4, 'tracks': [ { 'id': 299, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 333, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 583, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 4, 'level': -1, 'skill_name': 'チャレンジ★ごりらコースA', 'skill_name_id': 12, 'season_id': 4, 'tracks': [ { 'id': 466, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 273, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 470, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 5, 'level': -1, 'skill_name': 'チャレンジ★ごりらコースB', 'skill_name_id': 12, 'season_id': 4, 'tracks': [ { 'id': 194, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 343, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 501, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 6, 'level': -1, 'skill_name': 'チャレンジ★ごりらコースC', 'skill_name_id': 12, 'season_id': 4, 'tracks': [ { 'id': 356, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 7, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 472, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 7, 'level': -1, 'skill_name': 'チャレンジ★ごりらコースD', 'skill_name_id': 12, 'season_id': 4, 'tracks': [ { 'id': 299, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 333, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 583, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 0, 'season_id': 5, 'tracks': [ { 'id': 47, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 334, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 10, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 5, 'tracks': [ { 'id': 11, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 224, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 132, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 5, 'tracks': [ { 'id': 137, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 336, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 380, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 3, 'season_id': 5, 'tracks': [ { 'id': 109, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 308, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 113, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 5, 'tracks': [ { 'id': 101, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 200, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 478, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 5, 'season_id': 5, 'tracks': [ { 'id': 487, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 254, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 410, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 6, 'season_id': 5, 'tracks': [ { 'id': 196, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 170, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 218, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 5, 'tracks': [ { 'id': 489, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 519, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 373, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 8, 'season_id': 5, 'tracks': [ { 'id': 456, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 263, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 390, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 5, 'tracks': [ { 'id': 19, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 116, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 508, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 0, 'season_id': 6, 'tracks': [ { 'id': 123, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 231, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 185, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 6, 'tracks': [ { 'id': 65, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 386, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 92, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 6, 'tracks': [ { 'id': 379, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 225, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 427, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 3, 'season_id': 6, 'tracks': [ { 'id': 122, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 249, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 185, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 6, 'tracks': [ { 'id': 413, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 157, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 402, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 5, 'season_id': 6, 'tracks': [ { 'id': 412, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 323, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 256, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 6, 'season_id': 6, 'tracks': [ { 'id': 400, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 368, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 241, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 6, 'tracks': [ { 'id': 453, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 442, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 216, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 8, 'season_id': 6, 'tracks': [ { 'id': 370, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 244, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 252, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 6, 'tracks': [ { 'id': 359, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 214, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 506, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 0, 'season_id': 7, 'tracks': [ { 'id': 124, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 446, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 34, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 7, 'tracks': [ { 'id': 113, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 309, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 42, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 7, 'tracks': [ { 'id': 353, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 246, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 130, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 3, 'season_id': 7, 'tracks': [ { 'id': 63, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 219, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 153, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 7, 'tracks': [ { 'id': 418, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 369, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 385, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 5, 'season_id': 7, 'tracks': [ { 'id': 226, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 301, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 159, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 6, 'season_id': 7, 'tracks': [ { 'id': 311, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 255, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 213, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 7, 'tracks': [ { 'id': 357, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 268, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 304, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 8, 'season_id': 7, 'tracks': [ { 'id': 295, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 36, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 302, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 7, 'tracks': [ { 'id': 7, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 208, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 376, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 0, 'season_id': 8, 'tracks': [ { 'id': 101, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 219, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 159, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 8, 'tracks': [ { 'id': 87, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 337, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 403, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 8, 'tracks': [ { 'id': 30, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 596, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 39, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 3, 'season_id': 8, 'tracks': [ { 'id': 430, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 561, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 328, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 8, 'tracks': [ { 'id': 444, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 618, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 100, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 5, 'season_id': 8, 'tracks': [ { 'id': 447, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 545, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 94, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 6, 'season_id': 8, 'tracks': [ { 'id': 291, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 2, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 475, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 8, 'tracks': [ { 'id': 627, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 624, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 427, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 8, 'season_id': 8, 'tracks': [ { 'id': 464, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 122, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 591, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 8, 'tracks': [ { 'id': 381, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 463, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 507, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 0, 'season_id': 9, 'tracks': [ { 'id': 468, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 243, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 388, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 9, 'tracks': [ { 'id': 167, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 486, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 75, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 9, 'tracks': [ { 'id': 96, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 557, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 55, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 3, 'season_id': 9, 'tracks': [ { 'id': 116, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 520, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 314, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 9, 'tracks': [ { 'id': 507, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 567, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 205, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 5, 'season_id': 9, 'tracks': [ { 'id': 86, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 488, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 80, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 6, 'season_id': 9, 'tracks': [ { 'id': 184, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 130, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 524, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 9, 'tracks': [ { 'id': 521, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 576, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 503, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 8, 'season_id': 9, 'tracks': [ { 'id': 473, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 125, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 538, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 9, 'tracks': [ { 'id': 407, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 472, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 363, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 0, 'season_id': 10, 'tracks': [ { 'id': 122, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 209, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 24, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 10, 'tracks': [ { 'id': 405, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 554, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 77, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 10, 'tracks': [ { 'id': 426, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 262, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 194, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 3, 'season_id': 10, 'tracks': [ { 'id': 343, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 564, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 248, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 10, 'tracks': [ { 'id': 126, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 471, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 276, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 5, 'season_id': 10, 'tracks': [ { 'id': 476, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 120, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 57, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 6, 'season_id': 10, 'tracks': [ { 'id': 146, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 622, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 152, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 10, 'tracks': [ { 'id': 562, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 531, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 449, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 8, 'season_id': 10, 'tracks': [ { 'id': 404, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 123, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 607, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 10, 'tracks': [ { 'id': 469, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 496, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 289, 'type': self.CHART_TYPE_EXHAUST, }, ], }, # Manually specify IDs here since this has more than one level 11. { 'id': 0, 'level': 0, 'season_id': 11, 'tracks': [ { 'id': 190, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 568, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 191, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 1, 'level': 1, 'season_id': 11, 'tracks': [ { 'id': 278, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 41, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 18, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 2, 'level': 2, 'season_id': 11, 'tracks': [ { 'id': 15, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 483, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 467, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 3, 'level': 3, 'season_id': 11, 'tracks': [ { 'id': 585, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 486, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 48, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 4, 'level': 4, 'season_id': 11, 'tracks': [ { 'id': 103, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 335, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 224, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 5, 'level': 5, 'season_id': 11, 'tracks': [ { 'id': 275, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 438, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 67, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 6, 'level': 6, 'season_id': 11, 'tracks': [ { 'id': 202, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 264, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 526, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 7, 'level': 7, 'season_id': 11, 'tracks': [ { 'id': 131, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 155, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 394, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 8, 'level': 8, 'season_id': 11, 'tracks': [ { 'id': 396, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 346, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 510, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 9, 'level': 9, 'season_id': 11, 'tracks': [ { 'id': 326, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 470, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 362, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 10, 'level': 10, 'season_id': 11, 'tracks': [ { 'id': 339, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 418, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 525, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 11, 'level': 10, 'season_id': 11, 'tracks': [ { 'id': 36, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 47, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 73, 'type': self.CHART_TYPE_INFINITE, }, ], }, { 'id': 12, 'level': 11, 'season_id': 11, 'tracks': [ { 'id': 126, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 367, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 636, 'type': self.CHART_TYPE_INFINITE, }, ], }, { 'level': 0, 'season_id': 12, 'tracks': [ { 'id': 507, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 671, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 176, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 12, 'tracks': [ { 'id': 27, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 520, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 103, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 12, 'tracks': [ { 'id': 478, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 264, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 322, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 3, 'season_id': 12, 'tracks': [ { 'id': 107, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 520, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 163, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 12, 'tracks': [ { 'id': 408, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 34, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 678, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 5, 'season_id': 12, 'tracks': [ { 'id': 481, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 436, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 104, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 6, 'season_id': 12, 'tracks': [ { 'id': 55, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 415, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 512, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 12, 'tracks': [ { 'id': 483, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 509, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 557, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 8, 'season_id': 12, 'tracks': [ { 'id': 497, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 58, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 166, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 12, 'tracks': [ { 'id': 581, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 439, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 443, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 0, 'season_id': 13, 'tracks': [ { 'id': 250, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 245, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 186, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 13, 'tracks': [ { 'id': 13, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 618, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 31, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 13, 'tracks': [ { 'id': 436, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 144, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 79, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 3, 'season_id': 13, 'tracks': [ { 'id': 489, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 245, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 222, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 13, 'tracks': [ { 'id': 556, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 233, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 565, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 5, 'season_id': 13, 'tracks': [ { 'id': 354, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 281, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 2, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 6, 'season_id': 13, 'tracks': [ { 'id': 14, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 267, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 490, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 13, 'tracks': [ { 'id': 467, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 585, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 560, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 8, 'season_id': 13, 'tracks': [ { 'id': 599, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 101, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 109, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 13, 'tracks': [ { 'id': 630, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 408, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 393, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 0, 'season_id': 14, 'tracks': [ { 'id': 63, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 328, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 266, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 14, 'tracks': [ { 'id': 23, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 453, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 153, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 14, 'tracks': [ { 'id': 458, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 514, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 71, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 3, 'season_id': 14, 'tracks': [ { 'id': 392, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 388, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 569, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 14, 'tracks': [ { 'id': 508, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 405, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 266, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 5, 'season_id': 14, 'tracks': [ { 'id': 50, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 172, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 33, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 6, 'season_id': 14, 'tracks': [ { 'id': 210, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 232, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 485, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 14, 'tracks': [ { 'id': 457, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 514, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 556, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 8, 'season_id': 14, 'tracks': [ { 'id': 534, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 273, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 220, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 14, 'tracks': [ { 'id': 420, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 444, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 151, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 0, 'season_id': 15, 'tracks': [ { 'id': 117, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 564, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 318, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 15, 'tracks': [ { 'id': 93, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 308, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 49, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 15, 'tracks': [ { 'id': 317, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 335, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 239, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 3, 'season_id': 15, 'tracks': [ { 'id': 439, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 44, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 243, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 15, 'tracks': [ { 'id': 158, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 175, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 150, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 5, 'season_id': 15, 'tracks': [ { 'id': 162, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 79, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 386, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 6, 'season_id': 15, 'tracks': [ { 'id': 99, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 22, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 164, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 15, 'tracks': [ { 'id': 406, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 344, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 6, 'type': self.CHART_TYPE_INFINITE, }, ], }, { 'level': 8, 'season_id': 15, 'tracks': [ { 'id': 660, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 378, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 465, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 15, 'tracks': [ { 'id': 413, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 221, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 342, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 10, 'season_id': 15, 'tracks': [ { 'id': 125, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 123, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 124, 'type': self.CHART_TYPE_INFINITE, }, ], }, { 'level': 11, 'season_id': 15, 'tracks': [ { 'id': 366, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 695, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 692, 'type': self.CHART_TYPE_INFINITE, }, ], }, { 'level': 0, 'season_id': 16, 'tracks': [ { 'id': 343, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 144, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 569, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 1, 'season_id': 16, 'tracks': [ { 'id': 515, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 254, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 354, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 2, 'season_id': 16, 'tracks': [ { 'id': 441, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 524, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 187, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'level': 3, 'season_id': 16, 'tracks': [ { 'id': 117, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 446, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 435, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 4, 'season_id': 16, 'tracks': [ { 'id': 180, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 260, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 451, 'type': self.CHART_TYPE_EXHAUST, }, ], }, # The level 6 course for this version is intentionally missing, # as a song that it included was removed and thus the course was # as well. { 'level': 6, 'season_id': 16, 'tracks': [ { 'id': 440, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 112, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 401, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 7, 'season_id': 16, 'tracks': [ { 'id': 325, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 387, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 42, 'type': self.CHART_TYPE_INFINITE, }, ], }, { 'level': 8, 'season_id': 16, 'tracks': [ { 'id': 676, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 494, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 234, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 9, 'season_id': 16, 'tracks': [ { 'id': 155, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 623, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 329, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 10, 'season_id': 16, 'tracks': [ { 'id': 450, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 634, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 360, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'level': 11, 'season_id': 16, 'tracks': [ { 'id': 116, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 693, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 694, 'type': self.CHART_TYPE_INFINITE, }, ], }, { 'id': 0, 'level': -1, 'skill_name': '天下一 (梅)コース', 'skill_name_id': 13, 'season_id': 17, 'tracks': [ { 'id': 625, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 697, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 708, 'type': self.CHART_TYPE_NOVICE, }, ], }, { 'id': 1, 'level': -1, 'skill_name': '天下一 (竹)コース', 'skill_name_id': 13, 'season_id': 17, 'tracks': [ { 'id': 625, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 697, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 708, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 2, 'level': -1, 'skill_name': '天下一 (松)コース', 'skill_name_id': 13, 'season_id': 17, 'tracks': [ { 'id': 625, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 697, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 708, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 0, 'level': -1, 'skill_name': '青龍の戯れ', 'skill_name_id': 14, 'season_id': 18, 'tracks': [ { 'id': 439, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 675, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 692, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 1, 'level': -1, 'skill_name': '朱雀の戯れ', 'skill_name_id': 16, 'season_id': 18, 'tracks': [ { 'id': 587, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 543, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 693, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 2, 'level': -1, 'skill_name': '玄武の戯れ', 'skill_name_id': 17, 'season_id': 18, 'tracks': [ { 'id': 696, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 697, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 695, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 3, 'level': -1, 'skill_name': '白虎の戯れ', 'skill_name_id': 15, 'season_id': 18, 'tracks': [ { 'id': 606, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 593, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 694, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 4, 'level': -1, 'skill_name': '青龍の戯れ', 'skill_name_id': 14, 'season_id': 18, 'tracks': [ { 'id': 439, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 675, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 692, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 5, 'level': -1, 'skill_name': '朱雀の戯れ', 'skill_name_id': 16, 'season_id': 18, 'tracks': [ { 'id': 587, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 543, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 693, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 6, 'level': -1, 'skill_name': '玄武の戯れ', 'skill_name_id': 17, 'season_id': 18, 'tracks': [ { 'id': 696, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 697, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 695, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 7, 'level': -1, 'skill_name': '白虎の戯れ', 'skill_name_id': 15, 'season_id': 18, 'tracks': [ { 'id': 606, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 593, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 694, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 0, 'level': -1, 'skill_name': 'RANK 名も無き草', 'skill_name_id': 18, 'season_id': 19, 'tracks': [ { 'id': 783, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 784, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 785, 'type': self.CHART_TYPE_NOVICE, }, ], }, { 'id': 1, 'level': -1, 'skill_name': 'RANK 雪月花', 'skill_name_id': 18, 'season_id': 19, 'tracks': [ { 'id': 783, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 784, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 785, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 2, 'level': -1, 'skill_name': 'RANK 金剛雲', 'skill_name_id': 18, 'season_id': 19, 'tracks': [ { 'id': 783, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 784, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 785, 'type': self.CHART_TYPE_EXHAUST, }, ], }, # Manually specify IDs here since this has more than one level 11. { 'id': 0, 'level': 0, 'season_id': 20, 'tracks': [ { 'id': 657, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 285, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 491, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 1, 'level': 1, 'season_id': 20, 'tracks': [ { 'id': 446, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 588, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 21, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 2, 'level': 2, 'season_id': 20, 'tracks': [ { 'id': 560, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 602, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 88, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 3, 'level': 3, 'season_id': 20, 'tracks': [ { 'id': 470, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 515, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 65, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 4, 'level': 4, 'season_id': 20, 'tracks': [ { 'id': 499, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 358, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 72, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 5, 'level': 5, 'season_id': 20, 'tracks': [ { 'id': 573, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 559, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 602, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 6, 'level': 6, 'season_id': 20, 'tracks': [ { 'id': 255, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 164, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 783, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 7, 'level': 7, 'season_id': 20, 'tracks': [ { 'id': 425, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 54, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 771, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 8, 'level': 8, 'season_id': 20, 'tracks': [ { 'id': 589, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 592, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 776, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 9, 'level': 9, 'season_id': 20, 'tracks': [ { 'id': 779, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 611, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 670, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 10, 'level': 10, 'season_id': 20, 'tracks': [ { 'id': 522, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 543, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 610, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 11, 'level': 10, 'season_id': 20, 'tracks': [ { 'id': 122, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 180, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 214, 'type': self.CHART_TYPE_INFINITE, }, ], }, { 'id': 12, 'level': 11, 'season_id': 20, 'tracks': [ { 'id': 661, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 258, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 791, 'type': self.CHART_TYPE_INFINITE, }, ], }, # Manually specify IDs here since this has more than one level 11. { 'id': 0, 'level': 0, 'season_id': 21, 'tracks': [ { 'id': 697, 'type': self.CHART_TYPE_NOVICE, }, { 'id': 314, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 768, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 1, 'level': 1, 'season_id': 21, 'tracks': [ { 'id': 16, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 528, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 118, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 2, 'level': 2, 'season_id': 21, 'tracks': [ { 'id': 330, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 644, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 74, 'type': self.CHART_TYPE_ADVANCED, }, ], }, { 'id': 3, 'level': 3, 'season_id': 21, 'tracks': [ { 'id': 494, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 294, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 61, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 4, 'level': 4, 'season_id': 21, 'tracks': [ { 'id': 498, 'type': self.CHART_TYPE_ADVANCED, }, { 'id': 177, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 212, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 5, 'level': 5, 'season_id': 21, 'tracks': [ { 'id': 319, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 53, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 603, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 6, 'level': 6, 'season_id': 21, 'tracks': [ { 'id': 688, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 261, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 784, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 7, 'level': 7, 'season_id': 21, 'tracks': [ { 'id': 777, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 387, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 659, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 8, 'level': 8, 'season_id': 21, 'tracks': [ { 'id': 518, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 714, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 681, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 9, 'level': 9, 'season_id': 21, 'tracks': [ { 'id': 529, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 682, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 597, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 10, 'level': 10, 'season_id': 21, 'tracks': [ { 'id': 600, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 758, 'type': self.CHART_TYPE_EXHAUST, }, { 'id': 816, 'type': self.CHART_TYPE_EXHAUST, }, ], }, { 'id': 11, 'level': 10, 'season_id': 21, 'tracks': [ { 'id': 829, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 830, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 831, 'type': self.CHART_TYPE_INFINITE, }, ], }, { 'id': 12, 'level': 11, 'season_id': 21, 'tracks': [ { 'id': 914, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 913, 'type': self.CHART_TYPE_INFINITE, }, { 'id': 915, 'type': self.CHART_TYPE_INFINITE, }, ], }, ] def _get_extra_events(self) -> List[int]: return [ 62, # Navigator select (empty by itself) 65, # Navigator crew recruitments bottom half 66, # Enable Tenkaichi Mode 69, # Season 2 differences ] def handle_game_3_hiscore_request(self, request: Node) -> Node: # Grab location for local scores locid = ID.parse_machine_id(request.child_value('locid')) # Start the response packet game = Node.void('game_3') # First, grab hit chart playcounts = self.data.local.music.get_hit_chart(self.game, self.version, 1024) hitchart = Node.void('hit') game.add_child(hitchart) for (songid, count) in playcounts: info = Node.void('d') hitchart.add_child(info) info.add_child(Node.u32('id', songid)) info.add_child(Node.u32('cnt', count)) # Now, grab global and local scores as well as clear rates global_records = self.data.remote.music.get_all_records(self.game, self.version) users = { uid: prof for (uid, prof) in self.data.local.user.get_all_profiles(self.game, self.version) } area_users = [ uid for uid in users if users[uid].get_int('loc', -1) == locid ] area_records = self.data.local.music.get_all_records(self.game, self.version, userlist=area_users) clears = self.get_clear_rates() records: Dict[int, Dict[int, Dict[str, Tuple[UserID, Score]]]] = {} missing_users = ( [userid for (userid, _) in global_records if userid not in users] + [userid for (userid, _) in area_records if userid not in users] ) for (userid, profile) in self.get_any_profiles(missing_users): users[userid] = profile for (userid, score) in global_records: if userid not in users: raise Exception('Logic error, missing profile for user!') if score.id not in records: records[score.id] = {} if score.chart not in records[score.id]: records[score.id][score.chart] = {} records[score.id][score.chart]['global'] = (userid, score) for (userid, score) in area_records: if userid not in users: raise Exception('Logic error, missing profile for user!') if score.id not in records: records[score.id] = {} if score.chart not in records[score.id]: records[score.id][score.chart] = {} records[score.id][score.chart]['area'] = (userid, score) # Output it to the game highscores = Node.void('sc') game.add_child(highscores) for musicid in records: for chart in records[musicid]: (globaluserid, globalscore) = records[musicid][chart]['global'] global_profile = users[globaluserid] if clears[musicid][chart]['total'] > 0: clear_rate = float(clears[musicid][chart]['clears']) / float(clears[musicid][chart]['total']) else: clear_rate = 0.0 info = Node.void('d') highscores.add_child(info) info.add_child(Node.u32('id', musicid)) info.add_child(Node.u32('ty', chart)) info.add_child(Node.string('a_sq', ID.format_extid(global_profile.get_int('extid')))) info.add_child(Node.string('a_nm', global_profile.get_str('name'))) info.add_child(Node.u32('a_sc', globalscore.points)) info.add_child(Node.s32('cr', int(clear_rate * 10000))) if 'area' in records[musicid][chart]: (localuserid, localscore) = records[musicid][chart]['area'] local_profile = users[localuserid] info.add_child(Node.string('l_sq', ID.format_extid(local_profile.get_int('extid')))) info.add_child(Node.string('l_nm', local_profile.get_str('name'))) info.add_child(Node.u32('l_sc', localscore.points)) return game def handle_game_3_load_r_request(self, request: Node) -> Node: refid = request.child_value('dataid') game = Node.void('game_3') if refid is not None: userid = self.data.remote.user.from_refid(self.game, self.version, refid) else: userid = None if userid is not None: links = self.data.local.user.get_links(self.game, self.version, userid) for index, link in enumerate(links): if link.type != 'rival': continue other_profile = self.get_profile(link.other_userid) if other_profile is None: continue # Base information about rival rival = Node.void('rival') game.add_child(rival) rival.add_child(Node.s16('no', index)) rival.add_child(Node.string('seq', ID.format_extid(other_profile.get_int('extid')))) rival.add_child(Node.string('name', other_profile.get_str('name'))) # Return scores for this user on random charts scores = self.data.remote.music.get_scores(self.game, self.version, link.other_userid) for score in scores: music = Node.void('music') rival.add_child(music) music.set_attribute('id', str(score.id)) music.set_attribute('type', str(score.chart)) music.set_attribute('sc', str(score.points)) return game def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node: game = Node.void('game_3') # Generic profile stuff game.add_child(Node.string('name', profile.get_str('name'))) game.add_child(Node.string('code', ID.format_extid(profile.get_int('extid')))) game.add_child(Node.u32('gamecoin_packet', profile.get_int('packet'))) game.add_child(Node.u32('gamecoin_block', profile.get_int('block'))) game.add_child(Node.s16('skill_name_id', profile.get_int('chosen_skill_id', profile.get_int('skill_name_id', -1)))) game.add_child(Node.s32_array('hidden_param', profile.get_int_array('hidden_param', 20))) game.add_child(Node.u32('blaster_energy', profile.get_int('blaster_energy'))) game.add_child(Node.u32('blaster_count', profile.get_int('blaster_count'))) # Play statistics statistics = self.get_play_statistics(userid) last_play_date = statistics.get_int_array('last_play_date', 3) today_play_date = Time.todays_date() if ( last_play_date[0] == today_play_date[0] and last_play_date[1] == today_play_date[1] and last_play_date[2] == today_play_date[2] ): today_count = statistics.get_int('today_plays', 0) else: today_count = 0 game.add_child(Node.u32('play_count', statistics.get_int('total_plays', 0))) game.add_child(Node.u32('daily_count', today_count)) game.add_child(Node.u32('play_chain', statistics.get_int('consecutive_days', 0))) # Last played stuff if 'last' in profile: lastdict = profile.get_dict('last') last = Node.void('last') game.add_child(last) last.add_child(Node.s32('music_id', lastdict.get_int('music_id', -1))) last.add_child(Node.u8('music_type', lastdict.get_int('music_type'))) last.add_child(Node.u8('sort_type', lastdict.get_int('sort_type'))) last.add_child(Node.u8('narrow_down', lastdict.get_int('narrow_down'))) last.add_child(Node.u8('headphone', lastdict.get_int('headphone'))) last.add_child(Node.u16('appeal_id', lastdict.get_int('appeal_id', 1001))) last.add_child(Node.u16('comment_id', lastdict.get_int('comment_id'))) last.add_child(Node.u8('gauge_option', lastdict.get_int('gauge_option'))) # Item unlocks itemnode = Node.void('item') game.add_child(itemnode) game_config = self.get_game_config() achievements = self.data.local.user.get_achievements(self.game, self.version, userid) for item in achievements: if item.type[:5] != 'item_': continue itemtype = int(item.type[5:]) if game_config.get_bool('force_unlock_songs') and itemtype == self.GAME_CATALOG_TYPE_SONG: # Don't echo unlocked songs, we will add all of them later continue if game_config.get_bool('force_unlock_cards') and itemtype == self.GAME_CATALOG_TYPE_APPEAL_CARD: # Don't echo unlocked appeal cards, we will add all of them later continue if game_config.get_bool('force_unlock_crew') and itemtype == self.GAME_CATALOG_TYPE_CREW: # Don't echo unlocked crew, we will add all of them later continue info = Node.void('info') itemnode.add_child(info) info.add_child(Node.u8('type', itemtype)) info.add_child(Node.u32('id', item.id)) info.add_child(Node.u32('param', item.data.get_int('param'))) if game_config.get_bool('force_unlock_songs'): ids: Dict[int, int] = {} songs = self.data.local.music.get_all_songs(self.game, self.version) for song in songs: if song.id not in ids: ids[song.id] = 0 if song.data.get_int('difficulty') > 0: ids[song.id] = ids[song.id] | (1 << song.chart) for itemid in ids: if ids[itemid] == 0: continue info = Node.void('info') itemnode.add_child(info) info.add_child(Node.u8('type', self.GAME_CATALOG_TYPE_SONG)) info.add_child(Node.u32('id', itemid)) info.add_child(Node.u32('param', ids[itemid])) if game_config.get_bool('force_unlock_cards'): catalog = self.data.local.game.get_items(self.game, self.version) for unlock in catalog: if unlock.type != 'appealcard': continue info = Node.void('info') itemnode.add_child(info) info.add_child(Node.u8('type', self.GAME_CATALOG_TYPE_APPEAL_CARD)) info.add_child(Node.u32('id', unlock.id)) info.add_child(Node.u32('param', 1)) if game_config.get_bool('force_unlock_crew'): for crewid in range(1, 781): info = Node.void('info') itemnode.add_child(info) info.add_child(Node.u8('type', self.GAME_CATALOG_TYPE_CREW)) info.add_child(Node.u32('id', crewid)) info.add_child(Node.u32('param', 1)) # Skill courses skill = Node.void('skill') game.add_child(skill) course_all = Node.void('course_all') skill.add_child(course_all) skill_level = -1 for course in achievements: if course.type != 'course': continue course_id = course.id % 100 season_id = int(course.id / 100) if course.data.get_int('clear_type') >= 2: # The user cleared this, lets take the highest level clear for this courselist = [ c for c in self._get_skill_analyzer_courses() if c.get('id', c['level']) == course_id and c['season_id'] == season_id ] if len(courselist) > 0: skill_level = max(skill_level, courselist[0]['level']) info = Node.void('d') course_all.add_child(info) info.add_child(Node.s16('crsid', course_id)) info.add_child(Node.s16('ct', course.data.get_int('clear_type'))) info.add_child(Node.s16('ar', course.data.get_int('achievement_rate'))) info.add_child(Node.s32('ssnid', season_id)) # Calculated skill level game.add_child(Node.s16('skill_level', skill_level)) # Story mode unlocks storynode = Node.void('story') game.add_child(storynode) for story in achievements: if story.type != 'story': continue info = Node.void('info') storynode.add_child(info) info.add_child(Node.s32('story_id', story.id)) info.add_child(Node.s32('progress_id', story.data.get_int('progress_id'))) info.add_child(Node.s32('progress_param', story.data.get_int('progress_param'))) info.add_child(Node.s32('clear_cnt', story.data.get_int('clear_cnt'))) info.add_child(Node.u32('route_flg', story.data.get_int('route_flg'))) # Game parameters paramnode = Node.void('param') game.add_child(paramnode) for param in achievements: if param.type[:6] != 'param_': continue paramtype = int(param.type[6:]) info = Node.void('info') paramnode.add_child(info) info.add_child(Node.s32('id', param.id)) info.add_child(Node.s32('type', paramtype)) info.add_child(Node.s32_array('param', param.data['param'])) # This looks to be variable, so no validation on length return game def unformat_profile(self, userid: UserID, request: Node, oldprofile: ValidatedDict) -> ValidatedDict: newprofile = copy.deepcopy(oldprofile) # Update blaster energy and in-game currencies earned_gamecoin_packet = request.child_value('earned_gamecoin_packet') if earned_gamecoin_packet is not None: newprofile.replace_int('packet', newprofile.get_int('packet') + earned_gamecoin_packet) earned_gamecoin_block = request.child_value('earned_gamecoin_block') if earned_gamecoin_block is not None: newprofile.replace_int('block', newprofile.get_int('block') + earned_gamecoin_block) earned_blaster_energy = request.child_value('earned_blaster_energy') if earned_blaster_energy is not None: newprofile.replace_int('blaster_energy', newprofile.get_int('blaster_energy') + earned_blaster_energy) # Miscelaneous stuff newprofile.replace_int('blaster_count', request.child_value('blaster_count')) newprofile.replace_int('chosen_skill_id', request.child_value('skill_name_id')) newprofile.replace_int_array('hidden_param', 20, request.child_value('hidden_param')) # Update user's unlock status if we aren't force unlocked game_config = self.get_game_config() if request.child('item') is not None: for child in request.child('item').children: if child.name != 'info': continue item_id = child.child_value('id') item_type = child.child_value('type') param = child.child_value('param') if game_config.get_bool('force_unlock_cards') and item_type == self.GAME_CATALOG_TYPE_APPEAL_CARD: # Don't save back appeal cards because they were force unlocked continue if game_config.get_bool('force_unlock_songs') and item_type == self.GAME_CATALOG_TYPE_SONG: # Don't save back songs, because they were force unlocked continue if game_config.get_bool('force_unlock_crew') and item_type == self.GAME_CATALOG_TYPE_CREW: # Don't save back crew, because they were force unlocked continue self.data.local.user.put_achievement( self.game, self.version, userid, item_id, f'item_{item_type}', { 'param': param, }, ) # Update story progress if request.child('story') is not None: for child in request.child('story').children: if child.name != 'info': continue story_id = child.child_value('story_id') progress_id = child.child_value('progress_id') progress_param = child.child_value('progress_param') clear_cnt = child.child_value('clear_cnt') route_flg = child.child_value('route_flg') self.data.local.user.put_achievement( self.game, self.version, userid, story_id, 'story', { 'progress_id': progress_id, 'progress_param': progress_param, 'clear_cnt': clear_cnt, 'route_flg': route_flg, }, ) # Update params if request.child('param') is not None: for child in request.child('param').children: if child.name != 'info': continue param_id = child.child_value('id') param_type = child.child_value('type') param_param = child.child_value('param') self.data.local.user.put_achievement( self.game, self.version, userid, param_id, f'param_{param_type}', { 'param': param_param, }, ) # Grab last information. lastdict = newprofile.get_dict('last') lastdict.replace_int('headphone', request.child_value('headphone')) lastdict.replace_int('appeal_id', request.child_value('appeal_id')) lastdict.replace_int('comment_id', request.child_value('comment_id')) lastdict.replace_int('music_id', request.child_value('music_id')) lastdict.replace_int('music_type', request.child_value('music_type')) lastdict.replace_int('sort_type', request.child_value('sort_type')) lastdict.replace_int('narrow_down', request.child_value('narrow_down')) lastdict.replace_int('gauge_option', request.child_value('gauge_option')) # Save back last information gleaned from results newprofile.replace_dict('last', lastdict) # Keep track of play statistics self.update_play_statistics(userid) return newprofile