From e0265485ffbbdcdce7d83ec93891a64e9f95f977 Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Sun, 1 Oct 2023 03:54:23 +0200 Subject: [PATCH 01/18] Initial D THE ARCADE S2 support added --- docs/game_specific_info.md | 144 +- example_config/idac.yaml | 22 + readme.md | 3 + titles/idac/__init__.py | 12 + titles/idac/base.py | 16 + titles/idac/config.py | 121 + titles/idac/const.py | 16 + titles/idac/data/avatarGacha.json | Bin 0 -> 262275 bytes titles/idac/data/create_delivery_images.py | 36 + .../data/stamps/touhou_flandre_scarlet.json | Bin 0 -> 10735 bytes .../data/stamps/touhou_remilia_scarlet.json | Bin 0 -> 10669 bytes .../data/stamps/touhou_sakuya_izayoi.json | Bin 0 -> 10622 bytes titles/idac/data/timeRelease_v0100.json | Bin 0 -> 1286433 bytes titles/idac/data/timeRelease_v0131.json | Bin 0 -> 1863979 bytes titles/idac/data/timeRelease_v0141.json | Bin 0 -> 1864737 bytes titles/idac/data/timeRelease_v0150.json | Bin 0 -> 1354135 bytes .../timetrial/touhou_remilia_scarlet.json | Bin 0 -> 1131 bytes titles/idac/database.py | 12 + titles/idac/echo.py | 64 + titles/idac/frontend.py | 140 ++ titles/idac/frontend/idac_index.jinja | 132 ++ titles/idac/frontend/js/idac_scripts.js | 10 + titles/idac/index.py | 166 ++ titles/idac/matching.py | 72 + titles/idac/read.py | 161 ++ titles/idac/schema/item.py | 964 ++++++++ titles/idac/schema/profile.py | 440 ++++ titles/idac/season2.py | 2106 +++++++++++++++++ 28 files changed, 4608 insertions(+), 29 deletions(-) create mode 100644 example_config/idac.yaml create mode 100644 titles/idac/__init__.py create mode 100644 titles/idac/base.py create mode 100644 titles/idac/config.py create mode 100644 titles/idac/const.py create mode 100644 titles/idac/data/avatarGacha.json create mode 100644 titles/idac/data/create_delivery_images.py create mode 100644 titles/idac/data/stamps/touhou_flandre_scarlet.json create mode 100644 titles/idac/data/stamps/touhou_remilia_scarlet.json create mode 100644 titles/idac/data/stamps/touhou_sakuya_izayoi.json create mode 100644 titles/idac/data/timeRelease_v0100.json create mode 100644 titles/idac/data/timeRelease_v0131.json create mode 100644 titles/idac/data/timeRelease_v0141.json create mode 100644 titles/idac/data/timeRelease_v0150.json create mode 100644 titles/idac/data/timetrial/touhou_remilia_scarlet.json create mode 100644 titles/idac/database.py create mode 100644 titles/idac/echo.py create mode 100644 titles/idac/frontend.py create mode 100644 titles/idac/frontend/idac_index.jinja create mode 100644 titles/idac/frontend/js/idac_scripts.js create mode 100644 titles/idac/index.py create mode 100644 titles/idac/matching.py create mode 100644 titles/idac/read.py create mode 100644 titles/idac/schema/item.py create mode 100644 titles/idac/schema/profile.py create mode 100644 titles/idac/season2.py diff --git a/docs/game_specific_info.md b/docs/game_specific_info.md index 8f52807..2baa12c 100644 --- a/docs/game_specific_info.md +++ b/docs/game_specific_info.md @@ -16,6 +16,7 @@ using the megaime database. Clean installations always create the latest databas - [Card Maker](#card-maker) - [WACCA](#wacca) - [Sword Art Online Arcade](#sao) + - [Initial D THE ARCADE](#initial-d-the-arcade) # Supported Games @@ -27,7 +28,7 @@ Games listed below have been tested and confirmed working. ### SDBT | Version ID | Version Name | -|------------|-----------------------| +| ---------- | --------------------- | | 0 | CHUNITHM | | 1 | CHUNITHM PLUS | | 2 | CHUNITHM AIR | @@ -43,7 +44,7 @@ Games listed below have been tested and confirmed working. ### SDHD/SDBT | Version ID | Version Name | -|------------|---------------------| +| ---------- | ------------------- | | 11 | CHUNITHM NEW!! | | 12 | CHUNITHM NEW PLUS!! | | 13 | CHUNITHM SUN | @@ -94,7 +95,7 @@ After a failed Online Battle the room will be deleted. The host is used for the ### SDCA | Version ID | Version Name | -|------------|------------------------------------| +| ---------- | ---------------------------------- | | 0 | crossbeats REV. | | 1 | crossbeats REV. SUNRISE | | 2 | crossbeats REV. SUNRISE S2 | @@ -114,26 +115,26 @@ The importer for crossbeats REV. will import Music. Config file is located in `config/cxb.yaml`. -| Option | Info | -|------------------------|------------------------------------------------------------| -| `hostname` | Requires a proper `hostname` (not localhost!) to run | -| `ssl_enable` | Enables/Disables the use of the `ssl_cert` and `ssl_key` | -| `port` | Set your unsecure port number | -| `port_secure` | Set your secure/SSL port number | -| `ssl_cert`, `ssl_key` | Enter your SSL certificate (requires not self signed cert) | +| Option | Info | +| --------------------- | ---------------------------------------------------------- | +| `hostname` | Requires a proper `hostname` (not localhost!) to run | +| `ssl_enable` | Enables/Disables the use of the `ssl_cert` and `ssl_key` | +| `port` | Set your unsecure port number | +| `port_secure` | Set your secure/SSL port number | +| `ssl_cert`, `ssl_key` | Enter your SSL certificate (requires not self signed cert) | ## maimai DX ### SDEZ -| Game Code | Version ID | Version Name | -|-----------|------------|-------------------------| +| Game Code | Version ID | Version Name | +| --------- | ---------- | ------------ | For versions pre-dx | Game Code | Version ID | Version Name | -|-----------|------------|-------------------------| +| --------- | ---------- | ----------------------- | | SBXL | 0 | maimai | | SBXL | 1 | maimai PLUS | | SBZF | 2 | maimai GreeN | @@ -186,7 +187,7 @@ Pre-Dx uses the same database as DX, so only upgrade using the SDEZ game code! ### SBZV | Version ID | Version Name | -|------------|---------------------------------| +| ---------- | ------------------------------- | | 0 | Project Diva Arcade | | 1 | Project Diva Arcade Future Tone | @@ -207,7 +208,7 @@ the Shop, Modules and Customizations. Config file is located in `config/diva.yaml`. | Option | Info | -|----------------------|-------------------------------------------------------------------------------------------------| +| -------------------- | ----------------------------------------------------------------------------------------------- | | `unlock_all_modules` | Unlocks all modules (costumes) by default, if set to `False` all modules need to be purchased | | `unlock_all_items` | Unlocks all items (customizations) by default, if set to `False` all items need to be purchased | @@ -227,7 +228,7 @@ python dbutils.py --game SBZV upgrade ### SDDT | Version ID | Version Name | -|------------|----------------------------| +| ---------- | -------------------------- | | 0 | O.N.G.E.K.I. | | 1 | O.N.G.E.K.I. + | | 2 | O.N.G.E.K.I. SUMMER | @@ -255,7 +256,7 @@ The importer for O.N.G.E.K.I. will all all Cards, Music and Events. Config file is located in `config/ongeki.yaml`. | Option | Info | -|------------------|----------------------------------------------------------------------------------------------------------------| +| ---------------- | -------------------------------------------------------------------------------------------------------------- | | `enabled_gachas` | Enter all gacha IDs for Card Maker to work, other than default may not work due to missing cards added to them | Note: 1149 and higher are only for Card Maker 1.35 and higher and will be ignored on lower versions. @@ -275,7 +276,7 @@ python dbutils.py --game SDDT upgrade ### SDED | Version ID | Version Name | -|------------|-----------------| +| ---------- | --------------- | | 0 | Card Maker 1.30 | | 1 | Card Maker 1.35 | @@ -391,7 +392,7 @@ Gacha IDs up to 1140 will be loaded for CM 1.34 and all gachas will be loaded fo ### SDFE | Version ID | Version Name | -|------------|---------------| +| ---------- | ------------- | | 0 | WACCA | | 1 | WACCA S | | 2 | WACCA Lily | @@ -414,7 +415,7 @@ The importer for WACCA will import all Music data. Config file is located in `config/wacca.yaml`. | Option | Info | -|--------------------|-----------------------------------------------------------------------------| +| ------------------ | --------------------------------------------------------------------------- | | `always_vip` | Enables/Disables VIP, if disabled it needs to be purchased manually in game | | `infinite_tickets` | Always set the "unlock expert" tickets to 5 | | `infinite_wp` | Sets the user WP to `999999` | @@ -468,9 +469,9 @@ Below is a list of VIP rewards. Currently, VIP is not implemented, and thus thes ### SDEW -| Version ID | Version Name | -|------------|---------------| -| 0 | SAO | +| Version ID | Version Name | +| ---------- | ------------ | +| 0 | SAO | ### Importer @@ -487,11 +488,11 @@ The importer for SAO will import all items, heroes, support skills and titles da Config file is located in `config/sao.yaml`. -| Option | Info | -|--------------------|-----------------------------------------------------------------------------| -| `hostname` | Changes the server listening address for Mucha | -| `port` | Changes the listing port | -| `auto_register` | Allows the game to handle the automatic registration of new cards | +| Option | Info | +| --------------- | ----------------------------------------------------------------- | +| `hostname` | Changes the server listening address for Mucha | +| `port` | Changes the listing port | +| `auto_register` | Allows the game to handle the automatic registration of new cards | ### Database upgrade @@ -513,4 +514,89 @@ python dbutils.py --game SDEW upgrade - Midorica - Limited Network Support - Dniel97 - Helping with network base -- tungnotpunk - Source \ No newline at end of file +- tungnotpunk - Source + +## Initial D THE ARCADE + +### SDGT + +| Version ID | Version Name | +| ---------- | ----------------------------- | +| 0 | Initial D THE ARCADE Season 1 | +| 1 | Initial D THE ARCADE Season 2 | + +**Important: Only version 1.50.00 (Season 2) is currently working and actively supported!** + +### Profile Importer + +In order to use the profile importer download the `idac_profile.json` file from the frontend +and either directly use the folder path with `idac_profile.json` in it or specify the complete +path to the `.json` file + +```shell +python read.py --game SDGT --version --optfolder /path/to/game/download/folder +``` + +The importer for SDGT will import the complete profile data with personal high scores as well. + +### Config + +Config file is located in `config/idac.yaml`. + +| Option | Info | +| ----------------------------- | ----------------------------------------------------------------------------------------------------------- | +| `ssl` | Enables/Disables the use of the `ssl_cert` and `ssl_key` (currently unsuported) | +| `matching_host` | IPv4 address of your PC for the Online Battle (currently unsupported) | +| `port_matching` | Port number for the Online Battle Matching | +| `port_echo1/2` | Port numbers for Echos | +| `port_matching_p2p` | Port number for Online Battle (currently unsupported) | +| `stamp.enabled` | Enables/Disabled the play stamp events | +| `stamp.enabled_stamps` | Define up to 3 play stamp events (without `.json` extension, which are placed in `titles/idac/data/stamps`) | +| `timetrial.enabled` | Enables/Disables the time trial event | +| `timetrial.enabled_timetrial` | Define one! trial event (without `.json` extension, which are placed in `titles/idac/data/timetrial`) | + + +### Database upgrade + +Always make sure your database (tables) are up-to-date + +```shell +python dbutils.py --game SDGT upgrade +``` + +### Notes +- Online Battle is not supported +- Online Battle Matching is not supported + +### Item categories + +1. D Coin +3. Car Dressup Token +5. Avatar Dressup Token +6. Tachometer +7. Aura +8. Aura Color +9. Avatar Face +10. Avatar Eye +11. Avatar Mouth +12. Avatar Hair +13. Avatar Glasses +14. Avatar Face accessories +15. Avatar Body +18. Avatar Background +21. Chat Stamp +22. Keychain +24. Title +25. Full Tune Ticket +26. Paper Cup +27. BGM +28. Drifting Text +31. Start Menu BG +32. Car Color/Paint +33. Aura Level? +34. Full Tune Ticket Fragment +35. Underneon Lights + +### Credits + +A huge thanks to all people who helped shaping this project to what it is now and don't want to be mentioned here. diff --git a/example_config/idac.yaml b/example_config/idac.yaml new file mode 100644 index 0000000..04ea1e0 --- /dev/null +++ b/example_config/idac.yaml @@ -0,0 +1,22 @@ +server: + enabled: True + loglevel: "debug" + ssl: False + ssl_key: "cert/idac.key" + ssl_cert: "cert/idac.crt" + matching_host: "127.0.0.1" + port_matching: 20000 + port_echo1: 20001 + port_echo2: 20002 + port_matching_p2p: 20003 + +stamp: + enabled: True + enabled_stamps: # max 3 play stamps + - "touhou_remilia_scarlet" + - "touhou_flandre_scarlet" + - "touhou_sakuya_izayoi" + +timetrial: + enabled: True + enabled_timetrial: "touhou_remilia_scarlet" diff --git a/readme.md b/readme.md index 2c49faa..0875b55 100644 --- a/readme.md +++ b/readme.md @@ -33,6 +33,9 @@ Games listed below have been tested and confirmed working. Only game versions ol + Sword Art Online Arcade (partial support) + Final ++ Initial D THE ARCADE + + Season 2 + ## Requirements - python 3 (tested working with 3.9 and 3.10, other versions YMMV) - pip diff --git a/titles/idac/__init__.py b/titles/idac/__init__.py new file mode 100644 index 0000000..0c632bd --- /dev/null +++ b/titles/idac/__init__.py @@ -0,0 +1,12 @@ +from titles.idac.index import IDACServlet +from titles.idac.const import IDACConstants +from titles.idac.database import IDACData +from titles.idac.read import IDACReader +from titles.idac.frontend import IDACFrontend + +index = IDACServlet +database = IDACData +reader = IDACReader +frontend = IDACFrontend +game_codes = [IDACConstants.GAME_CODE] +current_schema_version = 1 diff --git a/titles/idac/base.py b/titles/idac/base.py new file mode 100644 index 0000000..c556aff --- /dev/null +++ b/titles/idac/base.py @@ -0,0 +1,16 @@ +import logging + +from core.config import CoreConfig +from titles.idac.config import IDACConfig +from titles.idac.const import IDACConstants +from titles.idac.database import IDACData + + +class IDACBase: + def __init__(self, cfg: CoreConfig, game_cfg: IDACConfig) -> None: + self.core_cfg = cfg + self.game_config = game_cfg + self.game = IDACConstants.GAME_CODE + self.version = IDACConstants.VER_IDAC_SEASON_1 + self.data = IDACData(cfg) + self.logger = logging.getLogger("idac") diff --git a/titles/idac/config.py b/titles/idac/config.py new file mode 100644 index 0000000..e685e2e --- /dev/null +++ b/titles/idac/config.py @@ -0,0 +1,121 @@ +from core.config import CoreConfig + + +class IDACServerConfig: + def __init__(self, parent: "IDACConfig") -> None: + self.__config = parent + + @property + def enable(self) -> bool: + return CoreConfig.get_config_field( + self.__config, "idac", "server", "enable", default=True + ) + + @property + def loglevel(self) -> int: + return CoreConfig.str_to_loglevel( + CoreConfig.get_config_field( + self.__config, "idac", "server", "loglevel", default="info" + ) + ) + + @property + def ssl(self) -> bool: + return CoreConfig.get_config_field( + self.__config, "idac", "server", "ssl", default=False + ) + + @property + def ssl_cert(self) -> str: + return CoreConfig.get_config_field( + self.__config, "idac", "server", "ssl_cert", default="cert/title.crt" + ) + + @property + def ssl_key(self) -> str: + return CoreConfig.get_config_field( + self.__config, "idac", "server", "ssl_key", default="cert/title.key" + ) + + @property + def matching_host(self) -> str: + return CoreConfig.get_config_field( + self.__config, "idac", "server", "matching_host", default="127.0.0.1" + ) + + @property + def matching(self) -> int: + return CoreConfig.get_config_field( + self.__config, "idac", "server", "port_matching", default=20000 + ) + + @property + def echo1(self) -> int: + return CoreConfig.get_config_field( + self.__config, "idac", "server", "port_echo1", default=20001 + ) + + @property + def echo2(self) -> int: + return CoreConfig.get_config_field( + self.__config, "idac", "server", "port_echo2", default=20002 + ) + + @property + def matching_p2p(self) -> int: + return CoreConfig.get_config_field( + self.__config, "idac", "server", "port_matching_p2p", default=20003 + ) + + +class IDACStampConfig: + def __init__(self, parent: "IDACConfig") -> None: + self.__config = parent + + @property + def enable(self) -> bool: + return CoreConfig.get_config_field( + self.__config, "idac", "stamp", "enable", default=True + ) + + @property + def enabled_stamps(self) -> list: + return CoreConfig.get_config_field( + self.__config, + "idac", + "stamp", + "enabled_stamps", + default=[ + "touhou_remilia_scarlet", + "touhou_flandre_scarlet", + "touhou_sakuya_izayoi", + ], + ) + + +class IDACTimetrialConfig: + def __init__(self, parent: "IDACConfig") -> None: + self.__config = parent + + @property + def enable(self) -> bool: + return CoreConfig.get_config_field( + self.__config, "idac", "timetrial", "enable", default=True + ) + + @property + def enabled_timetrial(self) -> str: + return CoreConfig.get_config_field( + self.__config, + "idac", + "timetrial", + "enabled_stamps", + default="touhou_remilia_scarlet", + ) + + +class IDACConfig(dict): + def __init__(self) -> None: + self.server = IDACServerConfig(self) + self.stamp = IDACStampConfig(self) + self.timetrial = IDACTimetrialConfig(self) diff --git a/titles/idac/const.py b/titles/idac/const.py new file mode 100644 index 0000000..cfae20e --- /dev/null +++ b/titles/idac/const.py @@ -0,0 +1,16 @@ +class IDACConstants(): + GAME_CODE = "SDGT" + + CONFIG_NAME = "idac.yaml" + + VER_IDAC_SEASON_1 = 0 + VER_IDAC_SEASON_2 = 1 + + VERSION_STRING = ( + "Initial D THE ARCADE Season 1", + "Initial D THE ARCADE Season 2", + ) + + @classmethod + def game_ver_to_string(cls, ver: int): + return cls.VERSION_STRING[ver] diff --git a/titles/idac/data/avatarGacha.json b/titles/idac/data/avatarGacha.json new file mode 100644 index 0000000000000000000000000000000000000000..91bb516a9d64ff6a5aa4d1ac400e4214172c0f09 GIT binary patch literal 262275 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 literal 0 HcmV?d00001 diff --git a/titles/idac/data/create_delivery_images.py b/titles/idac/data/create_delivery_images.py new file mode 100644 index 0000000..196081e --- /dev/null +++ b/titles/idac/data/create_delivery_images.py @@ -0,0 +1,36 @@ +import os +import hashlib + + +def prepare_images(image_folder="./images"): + print(f"Preparing image delivery files in {image_folder}...") + + for file in os.listdir(image_folder): + if file.endswith(".png") or file.endswith(".jpg"): + dpg_name = "adv-" + file[:-4].upper() + if file.endswith(".png"): + dpg_name += ".dpg" + else: + dpg_name += ".djg" + + if os.path.exists(os.path.join(image_folder, dpg_name)): + continue + else: + with open( + os.path.join(image_folder, file), "rb" + ) as original_image_file: + original_image = original_image_file.read() + image_hash = hashlib.md5(original_image).hexdigest() + print( + f"DPG for {file} not found, creating with hash {image_hash}..." + ) + md5_buf = bytes.fromhex(image_hash) + dpg_buf = md5_buf + original_image + with open(os.path.join(image_folder, dpg_name), "wb") as dpg_file: + dpg_file.write(dpg_buf) + + print(f"Created {dpg_name}.") + + +# Call the function to execute it +prepare_images() diff --git a/titles/idac/data/stamps/touhou_flandre_scarlet.json b/titles/idac/data/stamps/touhou_flandre_scarlet.json new file mode 100644 index 0000000000000000000000000000000000000000..31638e1c8ecf2d6e1c31b307b4c3193d28e203db GIT binary patch literal 10735 zcmeHNUvJb#5P#=WM1GyT-Z7P@N8ed#seZxIY2lptSqv$S*enHVI6x~2kjH2f#`V)nRD8ygz&wUg{ zDB7ki@2J?Gl4|Ss+C;^=@4MdR`FYz}>t3`S+qaFjX{=uItd?=<8+X3Z&}#F_g*k3Q z&(}>K-&t=q7Z-0TxXL^Ha*zM!iM%sGK zvaSv_t7)@gnq0xx)EMHg>--z_9({toYWP;G+uOj8soMmgU(k2a9nWX)}Gsu>}ef_AKJt!T~ZNr;BA$FS3E* zp|!hRR|kWHVYBhjn={(s=Byi`Rq0vRjGn1un|#}8=^exClLrev6UD*(x`BloDSjXX zSJ3TmxE2*u7nT;XR*Rxs?+Vr{v4N@`L(cYe*IvEacjYRXoNn443m>Cn;hU8A;j<4f z?x5gc@bpmOaR9b&jt;4muN#taa-Wp*wOSLR2kZq{xZW{*coJVr9$(;V6z!t$8BSy8 zNAuoiN4vib-tOfqouPr#0*>^)H%MAIH)MP;Ug5?LLsgd zarL-O{)aDd!u@Nno&)xo@=C%M?ss)TlRz|W*GrHuA{OyGPG&o}i2w4dGn?TAw^o#N zLTdQLNJrLg`*e+l*@xF_d)1;|UBahh>NO>WNQQZ1sU_uw+LRbDd3iCo^~c{oZhhE~ zaUuWyhutK`sZT68lK4hW4&?PDiOG`Hr7*0Da!*n+a`a1qFDX8#(lOQ^lOs=P7u`qU z@3eq?o{N0$o=Sc=RCG#Ql7N^Y<`l4zs4SQgkDdmDcQ?`2OloZuFk zEw^@0nV5pNDoV_Tq|o5ZR6lk_bTaq}?eHh~o_<~){Tz^OmV-Aa+)m<$Igp(E>N-jiORcjK_X=hqVPAJHr(>?X1k!01$TU z%HB0VTglRMDT~~Ho_7nHFe2~^?8{V@cgKtV3R7=3*+Do>M7s1%Dd?&w>1KHr0Akmn z7e&xfYLb)fbMVYW-r>!d20otD?WNw@%witgp2qwnHNAL1prUzhMm50vOsQ7pM2Ik9 zg1yzQ>5}-@Bz}^_kMYJ;65mPUdr5qEaQK>REx&qn^!ht=>ibo7VbzymoY?pA4g>wK zvuqOIo^4qHgW(EH9^S`4;bvjsmQ}vvizYbQzRXs~3OS2t4xL;~O{4APxFeisgm!j3 h&+T>B?G@W!>sb~#D@F;o+U+~!Xy2OA_N;T8{{Ubk1!e#M literal 0 HcmV?d00001 diff --git a/titles/idac/data/stamps/touhou_remilia_scarlet.json b/titles/idac/data/stamps/touhou_remilia_scarlet.json new file mode 100644 index 0000000000000000000000000000000000000000..82eeff481d160bea35ce9a09d96d04112d6b028c GIT binary patch literal 10669 zcmeHN-EP}96u$3M6uR1mwXq#fiF&=g!+;?Wlt^*3+OlBDD}o|`CGIB;=AlD@1sF1< z-7*wy+O*gPti{~zVvlm*WWCBOjHGmAiod#ob=y>~U9ME$kM0fMaT@fF@*a>!Kn{UCgz!foe?a&g!ebykUQU4Q@{+%R z{0d}WiQ8$n>a6mX@4Mc$r6t?hY+kV)+qaFnX>45eteSE4Q+KIS($poaL!aI9b+4OY?XjA11=FzWgVIV|dc(4=4;AC6 z4bw~-_=E$&fV!Fd;;`{2=o^M_)taqs`lwRWD7(o%N@T!$}*eW?TzbgSKee~r<=AHxsTDXXeH(J>9d!?T?mfP ze)|G~&->4N5Ohxuc9p~@a2z{nQdn^=+$)kXC-~&Uy;_>I-3joV26w@c5iX>C4DLX> z5I&?4?VaJ^_wHHum;Rso8Q`brSWEsJA|*{mtVb?2!7&RewX)Dn5y(Vpn)<=0D>7?@ zJnaw^W?N*v=5h)?yK7mefc0YjNq<{DgguCax!`H03ji3EdL6NJ&n@ z%rrq((&RX@Svq+eLYg_!TymHF4WH1M`}cl1gX}b4OjH*rvp6qA>EabbSb}?XS(BJv zH1rbY$3f3l)U6&(2WL{-heYTf!bU^o2AfUUNdl38p!Iuy`&Y*mrvXe+D!Tzm8o~IoXr~9)^d+}Ci z6o>u;o0rv+Br&~csY(28+{}lYXdh0x!kDMlB#^%4TAL!*pG9%P-ds`VHc5h?a88%? zLJUb_N&MELsEQjb>kBEm#RP|r6uryC|8lPD;+LXWyP$GgL|7y!x(>Y!!W+3(aI&3@ zBqp&}bPJ^+#jlli=MnbU=V!?(#IpbejdKgBA?I_ITAsrnLVk+K(CZRzD7yOhXC+b!I0`EEYIg3wYPV6+nLy4+7IbVLy^SsY{KJQ+;4j-wdI#uaqUY`#vd#Hn`-=*{1WjJQTf?|v=l1$$5+5#ym>=+o^)DA|4tTvR1QH(kUU2C@6wn`1+x*he0R8F)` zD<@&3sZz(dqjhu@Y;sMjp|&)qi(kxP#uumXs~Qxp#Qf1h^hw)xcWr|dl&dwaM|@G% z?k2P=uz@r?Lpjq?ZFB2(*A_P!l~Z-oiQGqP8Bj?Yzr1&T_Qm<}3G#kH!4JqkM!~+s z9D;UYFUbf_&IEcz&|wBnM$qfAda0fCN%>*z&H!c}&;^{QfR2Jb@}EICdy9*6Z;$&g z!aoO7@J}$Z!G2BflH?=SBavDhniw|4lv9pmrZzrZZQhvT09ugx6>!Z zDnWrj`+0OHXfj227sJER*Z%pVhv9x7d8gs0zmFfkMBV^-KOqlNo=w4@Ney=~qwuOp z@(Mb}y_d9-r;?E_aE@Y9j{F}{@Hv@04p9I~8zTQXMBcv#J>6Xy^sZr>KqK4%3MP6r6tW;c|vL4%31vPCzGPUV!_eY0npAVg87MpUH|1q!+-7 ztysD%&l>M!MF2no|CyS_^9)%L(0{e_jL}hlN}!u(RO9d~sKx{n6sECEBnupZG&;jd z;|dst4Uym*S-tvVc1vtG6$a z_W=3(=e+=VhwugY;1CaxcQWdIi@YbWwzwF6HzfowbFRsSY+hfC5CL(;q$ArDf1Z(# z^VXuuPY_KR+p=5|?71wOaDl(2=#Oomy`N!Ku}rxMCU}ehLH8Gpe!l3JXMR7A=xRyk z-gwbf>)a^LN8?4)F7Uck(ZMcCyqYhn?pDJb^`+<_kN(QIZONUf6jX7mAWP|uo)bqw zG$YgIrDy|#g(ZAMw^AC#cwX2u9nh?Np28mc{5%s2{vtp@hVk1;I=+@jZywV0=o+2fY44burn}uS X41A}H2xhC@weS_ZZLR4T*Y^GaH*B_i literal 0 HcmV?d00001 diff --git a/titles/idac/data/timeRelease_v0100.json b/titles/idac/data/timeRelease_v0100.json new file mode 100644 index 0000000000000000000000000000000000000000..283693566dbccf0f631adb79e894d266e5c4dc0b GIT binary patch literal 1286433 zcmeI*(T-f#m1gUEJ%ylaT`-wUQtVeL6a==cQ#Oue8Is%w?n1qLld{X+o?(w=LRF{Z zn@n9*_oh?(-y_CiGDigU@1K4C{+};?{OR3KfB5n1Z@&N4w_p5^&%b!_#g~8j|Nqr* ze*FD!-~I9HpMLY*w?BOQ+i&0f`0dxf`PGMC^7()Ml5gJq@bzzh^W#tN|3Clb=l{`% zFZl0&`M>`B<^TBGZ@>QVD}VkUzxdNv|8VKUKVSUkSN_voy#GQEH^1PU@4x%*+uwco zH_vOo`}Y6)`Y->(7k~Np{>NXxMBmKgUw`4p-^^U{OK;}QJ>AU9r?+=?JFh4Dk9ytw zSEG7*czI7x=gsS{e#!03NBc`($PX{Snh*T{Dy`Q~Pp@A8k_R-`{L%;X`svNvS9f(o zuODAL-Pa90y`E3~qh3S*)vxK-ZysO%BFW~OU-}w)czk&A=B|GK`uUFT>Sg`@j_!}z zhC%%)sezEz@z%RP9{9+$_XH&;tbZ7a+KK9P$Z^*ys&hm?W?48YH{ukX@ zezA|evxoVc$S=CJ{%Rk6Z~40YSUqpPzy6!0AAN86%Khkj%dhs)_m;2SkG{A3Y9D=X z`Re`Xd&{r(vG?|vOF#DB`m25Pz2(x6zPJ2pAA4`F@~eI9z4cf7*n4~WFFoJ-t6lEx zZ@)45^}FBy^zHe_TGyY7{rJ=OKYaKmWd5P!`fI-V)7Sm*tNw}aF0TK}kNfH`|69NM zi68%%le_+Yq{U-VHFZunuAKrcU@c!R3|M&CPy!`MYeR29# zkAM1Af4S#>`iHLb3;+4I_MdNmeiJco?apt1erJH){`@T!yZ!k)8+Q9Q-;ZnekIVaj z+xvj)`+)oVa{k7K`TG+0_a*M{OWfa^K7zgeA8~&laep6ie{X({=UNf zeTDmb^Bxh*-XQN zum3l|_s_GiUfU6V`@rc_PaimZ>h^)Nr*0qk)}d}+NMCvXxV%F8%IA;kE2OV_{zCf7 z`^Wti(pNrz++QJm)$|D>8oBpLi)=4$N%&zq_2GbxW7XB zs^|ZN|NbkauYCUa@4rI&s^>4Hue^WUUm<MNf=?yr!(>iG-lEAJooS4dy^{BeJU^i|JaNMCvX zxWB@uzVi9w{tD@qu)$Pxh)*b%zylx*j zeCqar^i{VH96fdWLi)=4$K@5$S3ZASU*S_<_56kOmG_VPD}3rJpFi%e@TsqQ{zCf7 z`^WtiKJ}H)ANN=I)K@)!A${fj2!c8BF|-s1Je1Dri|`#}1t z+ZWPT-ajs{kiPQyiG-lEAJooS4dy^{BeJU^i|JaNMCvXxW7XB%IA;!E2OV_{zCeiFA*$#)$IeP zPu)I{zUubpwL2_#^A@kKeIR|+?F;EE?;n>}NMHH<=S56kA$`q9d_8`I^p*FI`zxfc zeE#zy=C6>x<|DrPE2OWyf81XoedY6?7cqZ@^fe#x)n6ff<^ALS3h67K|GbF#E2OXa zh_C(%=_~Ia_g6??`TXZa%wHjW%}0FoS4dxZ|G2+G`pV}&FJk@*>1#gXtG`0}dSid; zt8O1Sed_js^i{V%#kj+>r*0oeUv>LJ`pWyq1+Oo|C;WAzwoebA2@yL_JQb^G($ z9hSR!i&u4p^p*FI%PXX>eEzt;Li(!bFQl)$f81XoedY7V{T0$zJ%1s6<^ALS3h67K zKkl!PzUui4=_~Ia_g6??`TTKzh4fX=Ur1kh|G2+G`pV~z`zxfcdj3NC%KOLt71CEe zf81Xoebw_9($`!2Q(txa!0A)B52UZUecf* zp1+X3^8Rsuh4hurANN;CU-kTj^p*FI`zxfceEztb_Dp?SKdEx z{^b1w^(*fmIDhi~f&P{Ee{=B;1K!O&UJsxL-C!YsH38jWA%Z0Vp@Q`QU1FhwH33~> zp@by?A%*n-U1A}IH33~>A%`Uap@;PVU1Fh#H33~>p@}5{A&T_?U1A}NH33~>A&eyf zp^WtaU1Fh)H33~>p^ha1B9A@T9}Rn``xnljx_=>$)%^=6P~E?f$LjuXPN#d!V>v)K zn8;&EKzEqPV?}_-V>v*Vn8;&EK$n=vV?}_-V>v*Vn8;&EK$n=vV?}_-V>v*Vn8;&E zK$n=vV?}_-V>v*Vn8;&EK$n=vV?}_-V>v*Vn8;&EK$n=vV?{v7V=tfP%jEj$4dCNr zJped`dH_(!dcb^n-C?2W0YD?`0YW4@EZ{X3GTDIvFR~EInt@Qt4hwjbg;sW8z?&@8 zvSuLUvcm%2WFeRx81NH+hxVNNBl$*VssC$$%HxNNB~tNNBl$H`z#N$$&T6NNB~tNNBl$ zH`z#N$$&T6NNB~tNNBl$H`z#N$$&T6NNB~tNNBl$H`z#N$$&T6NNB~tNNBl$H`z#N z$$&T6NNB~tNN8{MPodQS;v}j8L_(_p#5q(0rr~#)&}x8@&~gEK>jzkb{}x&f5Kf{TASARLAe=)v zKuBmgfJkV)fY+EvXw85ZnMi2KfJkV)fH#>)Xw85(nMi2KfJkV)fH#>)Xw85(nMi2K zfJkV)fH#>)Xw85(nMi2KfJkV)fH#>)Xw85(nMi2K;O62zzU}?yCa*tuf6bdrB(!G0 zn@l9MWMCw;2mDiLuWJBt64d}Aq16E59I63CLaPBrLdylb#zsO*2E52dLMsMFLdylb z$wop;2E55eLMsMFLdylb$wop;2E55eLMsMFLdylb$wop;2E55eLMsMFLdylb$wop; z2E55eLMsM0Kb61Bgq90+tI3bN$wope21Y{51@j_jvXRi{W4@aFiZ|IvXvM%tXt`isEHwKqRyp zK%7H0fJkUHz({DhfY;baXvu&V*+^)`z({DhfH&DlXvu&#*+^)`z({DhfH&DlXvu&# z*+^)`z({DhfH&DlXvu&#*+^)`z({DhfH&DlXvu&#*+^)`z({DhfH&DlXvu&#*+^)` zz({B_(p*C<@hP+#K%7K1U|ze+1~_l>`Vu0}p&CFWv>IR}v|PYzY$UW~z>91ov|?Z+ zv|PZOY$UW~z?*C&v|?Z+v|PZOY$UW~z?*C&v|?Z+v|PZOY$UW~z?*C&v|?Z+v|PZO zY$UW~z?*C&v|?Z+v|PZOY$UW~z?*C&v|?Z+v?u*jXf=R1iE6-necfe3s{zD0R0D{F zRs)QLmJ4`|jf9pAc#(~SRt$`UmJ4{3jf9pAc$1BURt$`UmJ4{3jf9pAc$1BURt$`U zmJ4{3jf9pAc$1BURt$`UmJ4{3jf9pAc$1BURt$`UmJ4{3jf9pAc$1BURt$uM_Vh4i zy?%rU_!L?XnB(rSK=lA1q4faZ9O?l;LhAuSLOU$rH5L-ufdMbFkkFcekkAebc$0;M zc3{ApEF`pMASATI0^VdHp&c0TCJPCz83+mOuz)vNNN5KJyvagBYX(9>J1pQ$782Tl z0dKO9(3*je&<+cDlZAwKV8EL!B(!E=B((agD2aqt1BjET1`r9Y1`y{^4ImO)4KNZ~ zF5opb5?V6gMK%&zF)$KZF5pcz5?V6gO*Rr*F)$KZF5pcz5?V6gO*Rr*F)$KZF5pcz z5?V6gO*Rr*F)$KZF5pcz5?V6gO*Rr*F)$KZF5pcz5?V6gO*Rr*F)$L^j5OS*&}sm2 z64iit?Jhq?H*fO#5+cr_8bBnp8ek-}T)=B=B(!9}i)-bB(!9}n`|Vs zVqhe+T)>-bB(!9}n`|VsVqhe+T)>-bB(!9}n`|VsVqhe+T)>-bB(!9}n`|VsVqhe+ zT)>-bB(!9}n`|VsVqhe+`l~33PodQS;v}j8^YwL?39SYY=THqG5?T!~5?U_cH8v7j zGT=ov5?V1Z5?U_cO*Rr*GT==%5?V1Z5?U_cO*Rr*GT==%5?V1Z5?U_cO*Rr*GT==% z5?V1Z5?U_cO*Rr*GT==%5?V1Z5?U_cO*Rr*GT==%5?V1Z654#BTt7lYB(xepoJ2K% zNN6=+Uc1W%IB)Xm0FlsYfRWI00k5%<(2~Kt$cbzuwE38?N0E`xash9$kLP9$%;7t}1+JOOYvXIc4fsoJ+ z3wV=-gmz%Sn=B->W*{WA!vfx9A)y@@@Foihtr-Xj?XZA1Sx9IH2E55aLTd&>LOU$r zO%@W`fdOywP21sq_--V$w_kqt`Q@K4xP(>%h?A%W5DBdY5a&=0AQD;)FcMlW;59Z9 zS~B28HWFGfFcMlW;7v9XS~B2GHWFGfFcMlW;7v9XS~B2GHWFGfFcMlW;7v9XS~B2G zHWFGfFcMlW;7v9XS~B2GHWFGfFcMlW;7v9XS~B2GHWFGfAQIZmO=<}(2M8xo4iFMr z4iL_v93UjL96%(rUchTiB(!G0i%cZ6WI!aeUcj47B(!G0n@l9MWI!aeUcj47B(!G0 zn@l9MWI!aeUcj47B(!G0n@l9MWI!aeUcj47B(!G0n@l9MWI!aeUcj47B(!G0n@l9M zWN>rw9zRF-<^lf{S`Hviq9Q;fv>HI1Lp6X%Xf?n{Xt{vb*hpx}fEU?FXvM%tXt{tl z*+^)~fH&DlXvM%tXt{tl*+^)~fH&DlXvM%tXt{tl*+^)~fH&DlXvM%tXt{tl*+^)~ zfH&DlXvM%tXt{tl*+^)~fH&DlXvM%tXj4}1Q)o3{Uc1YPIdAexfJkUHfH;S00FlsY zfRWI0!Mw<6Y$UY#n6C%X123|X(29YP&~m}N$eC;;wE38?CcorOHWFGfFcMlWm=`&d zjf6HI^VQ@>-ee=86$2xo<$`&UGucRJ^D$pde#M(?B(!2+B(z*GFLEXu32i>+tI1Ei z$wope21Y{51@j_jvXRi{W4@aFnm5@-bB(!9}n`|VsVqhe+T)>-bB(!9}n`|VsVqhe+ zT)>-bB(!9}n`|VsVqhe+T)>-bB(!9}n`|VsVqhe+T)>-bB(!9}n`|VsVjv{6hZi?L z6S|hz7o)G;VS+j=0M4Sr0-&ND7650_VFA$54hw{kcADV3ETps(1>a^NrX45~fr76yk=dF8k=YIte4UBRcA((vOk}pEKxDSV1Yc(&vmGe-Iun_# zDG-_MFu~WE$ZQ7+zRpBuYYIqad%*wF$d_N$0^>ZY1x9A81;%Mq3yjQG3y{o~6MUDE z%$5{b|X=;@4Pw)vp1IzRb3BbluzAek*E%!{7RNM@T4`l|D5UuPt<6$K=-J@TJss|6F# zeV#|Pz{qU1z&MR+fsxs20g~Brg6}et*^+{9Gm_bg0+QKsg0C}@*^+{ZyKGLqSnf^RdD*@^;^*>ZxfGm_bog0C}@*@^;^*>ZxfGm_bo zg0C}@*@^;^*>ZxfGm_bog0C}@*@^;^*>ZxfGm_bog0C}@*@^;^*>ZxfGm_bog0C}@ z*@^;^+2(8I`Z*-y(`>cCIFD+9k=bg&ymp_VaNgzB10%E50wlBL1m9&Ovn7Rj(X$!J zZ1X{14(;3NZ z^Fd#ACNkU8&3`oeIzh;6y+AmRdV!GHdcljlDT)C+{n)(eQtc9`J1Ok}nL1>a^Ovo!@GvmGY*Iun`gK*86U$ZSo4$ZUrRzRpBu zJ5ca-CNf)7ATrxwg0C}?*$xzZor%oW6o|}rnBeP7WVQnZUuPn-H3cHG9VYlX6PfKm z!Pl9{Y)wJPY%gEjd>e#iw!;G8JUT1@GTUJRa2g#J0GaKuK*(&T3BJohW;;>vZ5A@y zfr60PP7{2ch0J!M;Oi`8wgUwrvz;dRIt!WYM8Vft$ZQ7+LS{Qn@O2h4+lhj&^Ucqf z?(mJy2MR)FJ5BI)7Bbt3g0HiX*$xzh%yydK>nvop69r#qA+sGQAers$m!Exp`R5BS zv(*CQJgNmoW~&9pX;cf0%vKAK%$5^;myyht6nvYJ%vKbT%$5^;osrCz6nveL%vKbT z%$5^;osrCz6nveL%vKbT%$5^;osrCz6nveL%vKbT%$5^;osrCz6nveL%vKbT%$5^; zosrCz6nveL%vKbP%y#oV1ee)z0dXGX0wS~J0^&5v1w>}c1x9A;3BJolW@`$*%|>QR z3Pxt@3BJxoW@`$*&PHZS3Pxt@3BJxoW@`$*&PHZS3Pxt@3BJxoW@`$*&PHZS3O5(; z@&kD{cX|Cm-jlDhk=dGpud|Wal7f-hdV;UBk=dGpud|Wak^++19`sMMJ=Fr^JgNmo zW~&9pX;cf0%vKAK%$5^;myyht6nvYJ%vKbT%$5^;osrCz6nveL%vKbT%$5^;osrCz z6nveL%vKbT%$5^;osrCz6nveL%vKa`e#&>BnJp*yIwP4aDfl`gnXM=wnJp*yIwP4a zDfl`gnXM=wnQa<-eG|-!k>Kw0`-@sIuXziM%r>9%^;Kk?Mzz4mY_$N%Y&l_G^jtBgm>5OEy`Jk^lKl(Z& znXM=wnJp*Gi=NI%W}6TCs`D#fXC$)~1thcOgn7}^8Odz(L0@%#@^wZsTTwtVTTYl4 zJ)M!vHXrm==hwc@NM9*)dJ%@ss-~UcAuH878s{dEif`$EkH6`PVikuGFwvcZALO% zQ9v?VPVjX`GFwvcbw)Bvl+>3^Fdz^BqX!t1Yc()vn7Rj(bE~pZ1X{1 zbw)BcCIFD+9k=bg&l;l27 zqgr5OwpxH>ww&O*jAXW?;MC?=q6vl7eqDlG%y^lG$>C zuQQU_l7g=@lG%y^lG$>CuQQU_l7g=@lG%y^lG$>CuQQU_l7g=@lG%y^lG$>CuQQU_ zl7g=@lG%y^lG$>CuQQU_l7g=@lG%y^k=Y(!%#3sW;k=O9dVz2r^@7Rg9urS55Kg0B zFg5oW5SgtZJoqjXne9Nqx0%RnO@YX4hY7yUL}ois@O36KTT>u1+hKyQGm+U26nveD z%+?f$%yyXI>r7;}0|j4aBC|CGBC{PP_&O7r?LfiTnaFHSfyiu!3BJxmW;;;ubtW=f zQxG!S>!+v3`C`F3+i3!DBAq4xrR_9fzR2z{RGlUOt?e{Hh;7FW3xpPO+mXWprG?;j z;vf{a^bvtnovfFXP0;h%WcI2?YX(7FxI0)_SxM6|QLVY`OSm3nK z-%cEa0C(K5z-b}D9XTv;T8MBb4nl=HZdl;7(BY087C0@GxDy8@#noSq34G-31BRM_ zoJutTNpUp+Ig@GvlHzKDlHzj10-==@mmC%-t)#f(prp9mu)t|0#U+OYPAe&{I4CJD zH!N^kNpZvx*sYJ!sDa>D|ll@ym87AUQxxZj58@G7%46%AStdl zED#z=am`_Y(nyL+4oHgY4GWw`Qe1Ob;53rrk^_?Bdcy*zkrdY)7C4Qhxa4qi@jljWgl)db{BstHJns|iYq%MJ4)D72E|=A*tIN)HQ^R#IGXP*PlOm={5(l@vE0_0{Q@ z3!GL`TyaoRTyB^bL8p}zHy`!Y>Bj|5D=DrxC@C&C%!{DYN{XA0`s(zn1x_m|t~e+u zE;r1JpwmiTl@wPTloXd6=0(tHCB@B0eRcZv0;iP}R~(cS_vn8rt|m-G zcX}$-1SG}P1msMr2}p{o2}+8~4GV-;Qe1LaptO?Wii48ka>D|rl@ym87C5b>xZxa6?FX(h!K2PMVjh6PS5DK0rIa9T-m#X(7NxnY6R zN{UMk3!GL`TyaoRTy9w4w36bI!vd$36jvOS6qg$oIIX0(D|rl@ym87C5b>xZ>W*2H<6R~L{JR}+*J zmm3xct)#f*FfW2iD=BV1>g%zjq`2I$z-cALC5L$tbXrMq^HE=&R#IGUSm3mh;*!I> z2s*8#xcR8BPAe%cH!N^kNpZZ{XA zipvcPoK{j?a+nuErq_{V4r?%Ie zNPH@;C(LYv+aVGTyBE|ItBgGvyED+jAaR&|ylr~aab1+ieVZ#EajTCp_ zu)t{}#We>b#T_;*aN0<52M!CIHd0)3FjCxM!vd#`6nEgTz-c4JH3uWb9X2d*+DLH+ z4hx(%Qe1N|Qruy~0;i1>ci^zVX(Poo2PMTl>Ys{x^R^}+r&3KoQd~_y&ZL@vq_~=( zq`2I$Kxie!C5Ht{D=DrxC@C&CEO1&$amitU(@Kgf4oZs44GWxBQe1La;IxwBii48k za>D|rl@ym87C5b>xZ{-@$<0&*(Vg!wAF(-c<|kTaD|rl@ym87C5b>xZxZJS7X(h!a zhj|fnT1j#9QD2=_Qe19W;IxwBlEb_RI<2I*`KYf>D=98FEO1&$amis`1f5n=+D|rl@ym87C5b>xZD|rl@ym87C5b> zxZ*H9<*nxnY6ON{UMk3zSw;TyaoRTy9w4 zw36bI!vd$36jvOS6qg$oIIX0(Yv+ zaVGTyBE|ItBgGvyED+jAaR&|ylr~aab1+ieVZ#EajTCp_u)t{}#We>b#T_;*aN0<5 z2M!CIHd0)3FjCxM!vd#`6nEgTz-c4JH3uWb9X2d*+DLH+4hx(%Qe1N|Qruy~0;i1> zci^zVX(Poo2PMTl=%0%F>P1aJPNkZFq_~=ZoJlnSNpUqnNpZPhfzV2dOAZT^R#IGX zP*PlOSm3mh;*!GxrK%}_Sh6PR&DelB!fzvlXce=;Fap}N;NO7kP3!ElW+=;^ir->AI z;6S9f(}o336DjV*VS&>`iaT&nQe6Edo5EjE`5r?}Ku)EafTXyZfSgG+0ZDN+K}m7B zVS&&}ic1a)lvYw)aZplRZdl;7lH!uX0;iP}R~(cSmm3y1t)#f*u)t|0#T5r7#pQ+t zPAe%cIV^BmNpZzNNpZPhfzwKgOAZU1R#IGXP*PlOSm3mh;*!GxrYX!lHz*90-=!<*Bllojik8bfTXzIu)t{~#WjZoP9rHU zIUp&nH!N@(Npa0#fzwEeOAbhi>kSK>Mp9gJSl~30;*!J7#rynZ-_31af5i8+z-c7K zHHQUGBPlL9AStdlEN~i0am`_Y(@2U-4oZrvzhu++RNPZdKu)EafTXyZfSgG+0ZDN+ zK}m7BVS&&}ic1a)lvYw)aZplRZdl;7lH!uX0;iP}R~(cSmm3y1t)#f*u)t|0#T5r7 z#pQ+tPAe%cIV^BmNpZ#D=I4KRn&NW90;iP}mmC&2t)#f(prp9mu)t|0#U+OYPAe&{ zI4CJ@YI}Xl43gq%!n}5;-!0ACyi!0?TungEq?&-FxSF7(xZE%=fYxxi^9#T5r7#pQ;15p-Hfar04Moqk;4w36bAgOcKM z!@LMOt)#g5sIN}HTHv&j;);Wk;&Q{h2s*8#xcR8BPCqShT1j!mK}m7BVO|8CR#M!2 z)K{lpFK}8(amB$%agQ%%=()a@h!ocoCZfAMm3qP?1Wq8%q^3ZmxSn97xWk48LK`XW zz+r*XMv7|=Mv6OZSm3mg;tm`ZIBlf3=3u0_!-fS;8!7I|ifax=iaTsr;IxtA z4jdLZZKSy7V5GRih6PR=Dek~wfzw8cYYs+=J8W3sw2|Tt92Pijq`2mwq`0RqKl}Xh z&lg~ds|m=dR1=UCR}+vksU{#Pt|llcE;lR?T1j!qVS&<0iYpFEipvcPoK{j?a#-NB zlH!VklHzj10;iP}mmC&2t)#f(prp9mu)t|0#U+OYPAe&{I4CJDH!N^kNpZ zxZJS7X(h!ahj|fnT1j#9QD2=_QrsK=Q*ku`IhASxlHzK@6y;9Oq?&-FxSF7(xZJQn zXeGrZhXqP2DXusuDK0lGa9T-m$zg%hN{TBEN{Y)33!GL`Tyj|8w36bAgOcKM!vd$3 z6qg(pIIX0(;-I9s+_1oDCB-F&1x_m|t~e+uE;lT2T1j!qVS&?1iYpFEikpeyniG-# zR$NU$PNkZFq_~=ZoJlodUc1wpIB)Z+vy$R+!vdj|6qg(pD6OQp;-I9s+_1oDCB-F& z1x_m|t~e+uE;lT2T1j!qVS&?1iYpFEipvcPoK{j?a#-NBlH!VklHzj10;iP}mmC&2 zt)#f(prp9mu)t|0#U+OYPAe&{I4CLZt^cXGnt+^2H33O+H32!3YQl8=PE%Y>P*PlO zSRk~L;*!GxrIi#{9F!E78x}aNq`2g;z-cAL6$d57<%R`LD=98HEO1&$am7JNak*iE z(@Kg<4hx)CQe1IRQe19W;IxwBlEVV0l@wPTloXd67C5b>xa6?FX(h!K2P4Hj-5fpF zkI@jHit7o)snipQ6xS1oGpQ#KDXu3NDekagfzU>ZJ8)Q_w2|VPgOTD68x}Ziq__iz z1x_0&t~nSf?yzBj(?*Ira9H59k>Z+zk>U;;7C3FBxC4g;P8%t%IT$JKuwjAIMv6Od zSm3mg;+n(F&%^KXE%%2F3!FAm+=0Uar;QZX9F!FIpnodv>2*y&PNkZFq_~=ZoJlnS zNpUqnNpZPhfzV2dOAZT^R#IGXP*PlOSm3mh;*!Gxrh#kBrM0a{B)dVEP)db{BstHJns|iYq%MA;JR#IGYSfI3$;);Wk z;&Q_RrD|rl@ym87C5b>xZ|iaT&v;IxtAnuC$z4jUFYZKSvZhXqa>DXuvfDekagfzw8c zJ8)Rww2|VPgOTD68x}Ziq__iz1x_0&t~nSf?yzBj(?*Ira9H59k>Z+zlH%Uze?jF} z4>bWfm1+W#;%WkNCe;Ka#nl8Q#pQ+tLMtgQIV@0GNpZzNNpZPhfzwKgOAZU1R#IGX zP*PlOSm3mh;*!Gxr>Wel~I5=2d4U#pQ+t zLMtgQIV@0GNpZzNNpZPhfzwKgOAZU1R#IGXP*PlOSm3mh;*!GxrH3|fxSF7(xZJQnXeGrZhXqP2DXusuDK0lGa9T-m$zg%hN{TBE zN{Y)33!GL`Tyj|8w36bAgOcKM!vd$36qg(pIIX0(;-I9s+_1oDCB-F&1x_m|t~e+u zE;lT2T1j!qVS&?1iYpFCio5wy-t}WN#(yg=Cm5$vPB2njPB6}-oM5E5oPeab-mpMu zB*is{1xh0+E;-y>ywA4?+}!5%+l-eBoJLYyb6DUslH!sBlHz*90;iD_*Bll&jik8b zfTXzIu)t{~#WjZoP9rHUIUp&nH!N@(Npa0#fzwEeOAbhi>kSK>Mp9gJSl~30;*x`s z;vV=<#l5Tv$f;BlkQ7%FkTaD|rl@ym87C5b>xZ>W{-ko==9L1H;%WkN zCe;Ka#nl8Q#pQ;15foZUar04M52c3%N-HU@I4CJDH_VHm(@Kh)kNWEL%LPs=DXusu zDK0n6i=fj=ikpx6>h$9RrGcT++o6;caNvi zVS%?(ybF7uT#yq`00yoJu``NO3)ZIFot;k>YxSk>U;; z76@&mxC4g;N*gJzIT$JKuwjAIMv6OdSm5-{_p^8T-mB(dq`1R|1x_0&?!aMz(?*JG z4n~SQY*^s5k>U;<7C3FBxaMG_xWk48P8%uiz+r*YMv7|=Mv6OZSm3mg;tm`ZIBlf3 z=3u0_r>|z{;Zj^rAWo&8FbUn|50`oZaVGTyBE|ItBgGvyED+jAaR&|ylr~aab1+ie zVZ#EajTCp_u)t{}#We>b#T_;*aN0<52M!CIHd0)3FjCxM!vd#`6nEgTz-c4JH3uWb z9X2d*+DLH+4hx(%Qe1N|Qruy~0;i1>ci^zVX(Poo2PMTlefinvmw&zhQ(R3zPNkZF zq_~=ZoJlnSNpUqnNpZPhfzV2dOAZT^R#IGXP*PlOSm3mh;*!Gxr2s*8#xcR8BPAe%cH!N^kNpZZ{XAipvcPoK{j?a+nuErD|rl@ym87C5b>xZ0yD=N{TBEN{Y)3^CIZ9lH%s0zB>JK zfzwKgD-KGE%MJ4)=(LjJ=A*tk{kXtsCB+p7CB@~2c@cD4NpbU0U!8unz-cAL6$d57 z<%W3?bXrMq^HE=&ep=wPlH!VklHzj1ya+n2q`3L0uTH;S;IxwBii48k9{o?n)r5)Y zPEVzpfTXyZfSgG+0ZDN+K}m7BVS&&}ic1a)lvYw)aZplRZdl;7lH!uX0;iP}R~(cS zmm3y1t)#f*u)t|0#T5r7#pQ+tPAe%cIV^BmNpZzNNpZPhfzwKgOAZU1R#IGXP*PlO zSm3mh;*!Gxr^ zu|aGh&YekY5L?J|M-oDxJCE2PwovHKBsPdGG`b@RA<~^kY!F+>bY~J9#1=x`k%Um{ z&LcL6Ews8bi49^4weCoQ$#wNNaRMKm`x!)SP|l{>pyayRpqxy#LCJNsfys3_VuRI8 zu1gXdyk>G;kzjINj@TeJlk1Yi2C2OA;HzW^!GTU~*lK*dR8O>ypFxu-E>vF^fv6)<#BsPf6AKpWoK3Z1zR>P9*VP8)WU38H zuB#19uFDY{tY&gulGxxilk18Elk0NC2C2D-uku%MlyIW^!GU*dR8O>xu-E>vF^fv6)<#BsPf6pyayRFt6Qfa-8>h^+CyXwSmcXIbws=Os-23^P=cAlk4Wgz8+3Y zuFDY{#Ab3`l9(4ov6);qANEyjCfDVN4PrC7E=kObqS#EXn-BXcHk0de#0IgMT$d!~ zMNw=f*Ug806`RR*Ibws@Os-23^P(s=lk4WgzKYG{x*V}VY$n$wiFr{Jo5^+aVPC~& za^0H+pRTJ7%Gp#Klw4OErY!e*GSvnp*VP6l*X4)}Rx`OSNo??%$#q47$#pqmgV;>2 zOA;HzW^!GTU~*lK*dR8O>ypFNF)nOv77Hi*sSx+1~kx*V}VY$n$wi49^i zxvoesxh_X+5Sz($Nn(T8Os*>uOs>lj8^mUEU6R-!Hk0d$1e5D>#0IgMT$dy^h|T1> zBEjUkw+lX9R~wYGsWvFNt~MwqQ*D^S-)pX`4NR`f5gV*#a$SNF) znOv77Hi*sSx+1~kx*V}VY$n$wi49^ixvoesxh_X+5Sz($Nn(T8Os*>uOs>lj8^mUE zU6R-!Hk0d$1e5D>#0IgMT$dy^h|T1>BBA8EujVJ{uAju2*X}e=n5UvB7I4*Ch!h*Y$`EVk^0>No){X$#qFW$#p$qgV;*0YZ4p8 zR&rgEP;y<5*dVr&>zc#{v6WnxB$Qm&BQ}Vw%OWD%Gp#Klw4OEl#{78D7mgSFu5*AY_OWibxC4_*G#S}5=^ek5gWv2 za$SNF)nOv77Hi*sSx+1~kx*V}VY$n$wi49^ixvoesxh_X+5Sz($ zNn(T8Os*>uOs>lj8^mUEU6R-!Hk0d$1e5EgyW*$oYQwyCub&W{_j%=@uOs>lj z^P(s=lk4WgzKZ?0L2M@16$vKS<%oGv6r0I)^I>1bezietCf5}SCfDVNc~KOb$#wH# zU&VgfAU2chiUgDEa>TqSip}J@`LM5Izuq7=lk18Elj|NAe7deSOi1^7Hq{0t*VP8) zWU38HuB#19uFDY{tY&gulGxxilk18Elk0NC2C2D-uku%MlyIW^!GU*dR8O>xu-E>vF^fv6)<#BsPf6 zkY=))EkUk*BgwJsW%w8t~VgL?l5A5)kv;8kl5fglIxlT zlIsp5Hi(Vnx&w&~V&8msd!KLCY7$7UJB-*MHj?WOBsPeRmMZ^H;Ap|x+bwfY$ewv2_@I{hz(*Z zxvoiU5L?N0NkYkWJz|5{O0H`X8^l&}U6N38U60rxwvy|b#0IgIT$d!6T=(FAy6&+y zC}&e`P;y;uP)?@WpyayRz~s6dvB7F4*CmM!UNgC_NHDoBM{E$A$#qF$gV;>2D-t(< z&bZfHmm@Za&E&cyu|aGm*A)pS*X4)}Vl%leNo)|C$#q47$#pqmgV;>2OA;HzW^!GT zU~*lK*dR8O>ypF(TVE!D}Yh6$vKS<%oGv6r0I)^I>1bez`$xCf5}SCfDVN zc~KOb$#wH#U&VghAU2chiUgDEa>TqSip}J@`LM5IzuF)+lk18Elk0NCyeNvzuQ5? zGSvnp*VP6l*X4)}Rx`OSNo??%$#q47$#pqmgV;>2OA;HzW^!GTU~*lK*dR8O>ypF< zv6);~B$!;6BQ}W5xu-E>vF^fv6)<#BsPf6NF!nOv77Hh9hCx+1~kx*V}VY$n$wi49^ixvoesxh_X+5Sz($ zNn(T8Os*>uOs>lj8^mUEU6R-!Hk0d$1e5D>#0IgMT$dy^h|T1>BEjUk9I-)cCf6m2 z4PrC7u1GMsZoXo!pNLXET~`~Fv#B;HxvnypI0 zD0NF)nOv77=0#C#CfCh}eHEL@bva^#*i5cV67!-cHk0e-!@i2m z1bW^!GQ*dR8O>ypI0D2mPGy7{oLVl%leM{E$A$#qF$ zUKGVuQ5?Hq{0t*VTq8%e|gVwL!^swSmcXIbws=Os-238@y(6 zU6EjNU5?lwHk0d;#0IgMTvsHRT$dv@h|T1>B(XtkCf5}SCfDVN4PrC7E=g<J_w?0FLD%MJe7deT7-v&& zn2hc-b@c}0WagV;!}YZ6GV zJB-*MHj?WOBsPeRNF)nOv77Hi*sSx+1~k zx*V}VY$n$wi49^ixvoesxh_X+5Sz($Nn(T8Os*>uOs>lj8^mUEU6R-!Hk0d$1e5D> z#0IgMT$dy^h|T1>BEjUknINvsQOR|+K{=ahgOclNgK{#}hI#E?ljFS4tJ6%b%Mlx_ zW^!GU*x)sj>xu-E>vF^fv6)<#BsPf6NF)nOv77Hi*sSx*~z(y032j$Z-A9 zzLD#CgK;+X1|!$?2IFMv4O960%yqp1$#sVj8>~ih-GRgguaR8WB#>Np7_mWYB-b5C zY!DmCbxi`vb%zlf#71)6fy4%}kzCg#ZvN~o{(0in2CEv#B;Hxvn-S zCsS=ua$Rj;a$SztU^SELlEenDnOs*Sm|T}5Hi*sSx+JkdY$n$g2`1O&hz(*hxh_d; z5Sz($MS{t7Ibws@Os-238^mUEU6EjNU5?lwHk0d;#0IgMTvsHRT$dv@h|T1>B(Xtk zCf5}SCf7}O#ave#=Cyl$2jjfYD+eXl)duBcstro6s|`%9%MtUUXf>1T=EJ@oO%EHq zW^!GTU~*lKm={H{nOrv?_Eqec8^mUEU6EjNU5=O+MX{M&Hy`#@?8gmaGr6uvFu5*A z%!{JfOs<;``zrRU4PrC7u1GMsE=SCZqS#EXn-BXc_R|KjnOs*Sm|T}5=0#C#CfCh} zeHHul2C2OA;HzW^!GT zU~*lK*dR8O>ypFNF)nOv77Hi*sSx+1~kx*V}VY$n$wi49^ixvoesxh_X+5Sz($Nn(T8Os*>uOs>lj z8^mUEU6R-!Hk0d$1e5EY7JRy{HYjIPZI~~#d(CyVK{=UfgOclN1C#4=#0IOGT$dy^ zc+KRxBEjUk9I-)cCf6m24PrC7u1GMsE=Oz-o5^)aVuRRBt}7BuuFDY{#Ab3`lGq?N zlk18Elk0NC2CrNv!SZ(CG6NwF88@cX4!pL=}5gWuda@~o< z2CdaVjH>cL}G*3My@-MFml~##0IgATz4X|L2M(}9Y`3t?lfY9*ha29 zk=P)%k?Rg5j9hmbu|aGj*PTdg5ZlOg2NF!Kd!v84?mdXwpqx#$LCJNsK{=UfgOclN z1C#4=#0IOGT$dy^c+KRxBEjUk9I-)cCf6m24PrC7u1GMsE=Oz-o5^)aVuRRBt}7Bu zuFDY{#Ab3`lGq?Nlk18Elk0NC2C zCJ6DuQ5?GS!B8?Os12IPdf7G?VLc#0IOGT$dy^c+KRxBEjUk9I-)c zCf6m24PrC7u1GMsE=Oz-o5^)aVuRRBt}7BuuFDY{#Ab3`lGq?Nlk18Elk0NC2CzV|T>kcC}h>hgB1Bne{Be||gAi3`GX}as>y52DN-Dh&_4Mwi( z4aUjT8;o4n8<1Rg7_q@>B-b5CZ15V%bxi`vb%zlf#71)6fy4%}kzCg#kX&~du|aGk z*BwY~5F5#LO#;bvhY=gZMsnSO#0IgET-PL!Tz43;L2M+~9Y|~t8_9J|0?BoU5gWut za@~Q%2CB(XtkCf5}S zCfDVN4PrC7E=g<uQ5?Hr0lC?Os12 zIPdfNT2fA?+MwjR+Q8(x9I?S_Cf6m24PG<3u1GMsE=Oz-o5^)aVuRRBt}7BuuFDY{ z#Ab3`lGq?Nlk18Elk0NC2C2D-ukuds^`6y4s+eO|@aZ(C#(Y)duBcstro6s|`%9%Mlx_W^!GU*x)sj z>xu-E>vF^fv6)<#BsPf6NF)nOv77Hi*sSx+1~ky7`K^ej@6{NO|{~iE4v# zHq{0t*VTr3O?)jWxo$q|tJ6%b%Mlx_W^!GUm={H_nOrv?_El^q*X4)}Vl%leNz99) z*i5dQ5Bn-Mlk0NC2C*mA0ip}J@ z9I-)cCf6m2c~KOb$#wH#U&Ur}U5?lwHk0d;#Jnhq&E&fIu&-h>x$ezKa@P?`uB#2o z*;E^pTvr>WEcbdc)dnTk)dnWl<%kVdGr2BFZ19@Nbwz^7bva^#*i5cV5*x&3a$S*N za$SztAU2chlEenFnOs*Sm|T}5Hi*sSx+JkdY$n$g2`1O&hz(*hxh_d;5Sz($MS{t7 zIbws@Os-238^mUEU6EjN-AoW-uB#2o*;E^pTvr>Elc_e$YxkNQ=Y3wCW^!GQ*kCo2 z>ypFvzhrYrZE>v{u{>kcC}SdHYm1Bne@Be||gAi3@^VuRR7t~-#}AU2Zg zngo*T4kI>*jpVumi49^Sxvohdx$ZDxgV;!}JCN8QHj?X_1d{6xBQ}VQw{dV`VcdIOT{ z4kI>LjpVumi49&Oxvohdx$ZDxgV;!}JCN8QHj?X_1d{6xBQ}VQu=I!gV;u{JCWERwvp=&B#c~l8nHoaBiEfsY!KVXbq5kgt~-s`Ahwa~P9!#n zZRENG2_x5?Mr;t<$aNrNv!h;8J$6NwFC8@cX4g2{CcUw-!a<)1Ia zTvr>Ev#B;Hxvn-SCsS=ua$Rj;a$SztU^SELlEenDnOs*Sm|T}5Hi*sSx+JkdY$n$g z2`1O&hz(*hxh_d;5Sz($MS{t7Ibws@Os-238^mUEU6EjNU5?lwHk0d;#0IgMTvsHR zT$dv@h|T1>B(XtkCf5}SCf7}O#ave#=CynM%)z|RD+eXl)duBcstro6s|`%9%MtUU zXf>1T=EJ@oO%EHqW^!GTU~*lKm={H{nOrv?_Eqec8^mUEU6EjNU5=O+MX{M&Hy`#@ z?8gmaGr6uvFu5*A%!{JfOs<;``zrRU4PrC7u1GMsE=SCZqS#EXn-BXc_R|KjnOs*S zm|T}5=0#C#CfCh}eHHul2C2OA;HzW^!GTU~*lK*dR8O>ypF2D-uku%MlyIW^!GU*dR8O>xu-E>vF^fv6)<# zBsPf6Fkfi*n(JzVax&Eh zCD+vkCfDVN4OTO`E=g?gn#pxVg2{C`VuRRBu1gXd#Ab3`kzjINj@TeJlk1Yi2C2OA;HzW^!GT zU~=7j#fZ7CHYjIPZBTMuZJ5{YH95}vy!xQzy4t|xx*V~=Y9`kuiFr}2D-uku%MlyIW^!GU*dR8O>xu-E>vF^fv6)<# zBsPf6Elc_dL;qNuq)dnWl<%kVdGr2BFZ19@Nbwz^7bva^# z*i5cV5*x&3a$S*Na$SztAU2chlEenFnOs*Sm|T}5Hi*sSx+JkdY$n$g2`1O&hz(*h zxh_d;5Sz($MS{t7Ibws@Os-238^mUEU6D|7-ObMeuAjs~K3$g^kh3W_Ah|9#ASY99 zKyqDfP;y<5*kHAi>zc#{ua#VvB$Qm&BQ}VwkcF~c#Y(`CV}L-!-x%HBf0KCVuRR7u4@uEf6frUbwYC8fy9Py#2+_^jpVw1IU%|3 zFk-{+*hsEBkk}wLlIxlTlIsp5Hi(Vnx&w&~Vk5b(Ng%oIFk*w)NUl4O*dR8N>zc&> z&0P1{=kNdd*FXIwmtV|3+rRqae|-KgKmUpkzv|!r@_&8!e|=G{?tgy&{f|Grc>lkC zcri2H&zBzl@uipl_|oG)zVzWv|G~fO=^tNu{ijQR+4UcP{mVXM>^#9%kG=T=`|htgs^S-FnYj55_wR-K%dl`1G{j|Q9`lS9;aPu|_ z^_86O$@uVghUfQW%r~HXTHkzpQis^hr!7>i|EV_@eNsP>{G?vTpVaTg&+p0D`~Ju0 z_hc+)`$?Tr&+p0D`$~R(PsU!h&+o}t%=VM|6VUT}GWNcbZ$5Oo`Ue-!@5$KvN`8J% z#$LA1@5$K9_U7-sTKzlF^LsM(zLKBcld+fW>rW~J-TaLetIy<5<2@N4{vL_v_hdZ3 zC*#B4i}L4xzF4jG^LsMZ{_QrO)NjV0RPB6zPsZNwp`YKAv6$^AbxJ+ICu8p``T0E= zd)Yp}Cu1?&=l5i+{qx@Q-;=S|+voRW>}C7>o{YV0pWl}C7> zo{YV0pWl%ie_4mJj|LY$9`kzVo@cxA_-uwkOq&9C46oy*_6zxL;^@DHy3zu*4x z*Wds4SKt2dcdmc;?N8tS@bx!;`0=Ojzx&Pq{`T+uig$nb;a&cM-@p6)w?BOI{{F9D zWxmbg&m*qCWbS-F@29VS{OR3yfBTi@FZ=F~KmF#X-+ucy|F-#S-hY)Je){_7hkyMy z&YSw(yYJqAonOEE-M{@j{OAAb%!fz*AAj@TpZWd!ul3{Czx~aRKfQlC|MIV&{m1_S DB4?_a literal 0 HcmV?d00001 diff --git a/titles/idac/data/timeRelease_v0131.json b/titles/idac/data/timeRelease_v0131.json new file mode 100644 index 0000000000000000000000000000000000000000..184e6d272d6b16475ec524dc42e2f9339d2288cf GIT binary patch literal 1863979 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 YjBa1w|7rTI-kf}^pC9Fa{qV>C4*`RJ(f|Me literal 0 HcmV?d00001 diff --git a/titles/idac/data/timeRelease_v0150.json b/titles/idac/data/timeRelease_v0150.json new file mode 100644 index 0000000000000000000000000000000000000000..02d6bf3ec0bdf8cf6f4136a6debb784303ae9950 GIT binary patch literal 1354135 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 literal 0 HcmV?d00001 diff --git a/titles/idac/database.py b/titles/idac/database.py new file mode 100644 index 0000000..dac4556 --- /dev/null +++ b/titles/idac/database.py @@ -0,0 +1,12 @@ +from core.data import Data +from core.config import CoreConfig +from titles.idac.schema.profile import IDACProfileData +from titles.idac.schema.item import IDACItemData + + +class IDACData(Data): + def __init__(self, cfg: CoreConfig) -> None: + super().__init__(cfg) + + self.profile = IDACProfileData(cfg, self.session) + self.item = IDACItemData(cfg, self.session) diff --git a/titles/idac/echo.py b/titles/idac/echo.py new file mode 100644 index 0000000..88151a7 --- /dev/null +++ b/titles/idac/echo.py @@ -0,0 +1,64 @@ +import logging +from random import randbytes +import socket + +from twisted.internet.protocol import DatagramProtocol +from socketserver import BaseRequestHandler, TCPServer +from typing import Tuple + +from core.config import CoreConfig +from titles.idac.config import IDACConfig +from titles.idac.database import IDACData + + +class IDACEchoUDP(DatagramProtocol): + def __init__(self, cfg: CoreConfig, game_cfg: IDACConfig, port: int) -> None: + super().__init__() + self.port = port + self.core_config = cfg + self.game_config = game_cfg + self.logger = logging.getLogger("idac") + + def datagramReceived(self, data, addr): + self.logger.info( + f"UDP Ping from from {addr[0]}:{addr[1]} -> {self.port} - {data.hex()}" + ) + self.transport.write(data, addr) + + +class IDACEchoTCP(BaseRequestHandler): + def __init__( + self, request, client_address, server, cfg: CoreConfig, game_cfg: IDACConfig + ) -> None: + self.core_config = cfg + self.game_config = game_cfg + self.logger = logging.getLogger("idac") + self.data = IDACData(cfg) + super().__init__(request, client_address, server) + + def handle(self): + data = self.request.recv(1024).strip() + self.logger.debug( + f"TCP Ping from {self.client_address[0]}:{self.client_address[1]} -> {self.server.server_address[1]}: {data.hex()}" + ) + self.request.sendall(data) + self.request.shutdown(socket.SHUT_WR) + + +class IDACEchoTCPFactory(TCPServer): + def __init__( + self, + server_address: Tuple[str, int], + RequestHandlerClass, + cfg: CoreConfig, + game_cfg: IDACConfig, + bind_and_activate: bool = ..., + ) -> None: + super().__init__(server_address, RequestHandlerClass, bind_and_activate) + self.core_config = cfg + self.game_config = game_cfg + + def finish_request(self, request, client_address): + self.RequestHandlerClass( + request, client_address, self, self.core_config, self.game_config + ) diff --git a/titles/idac/frontend.py b/titles/idac/frontend.py new file mode 100644 index 0000000..32b1467 --- /dev/null +++ b/titles/idac/frontend.py @@ -0,0 +1,140 @@ +import json +import yaml +import jinja2 +from os import path +from twisted.web.util import redirectTo +from twisted.web.http import Request +from twisted.web.server import Session + +from core.frontend import FE_Base, IUserSession +from core.config import CoreConfig +from titles.idac.database import IDACData +from titles.idac.schema.profile import * +from titles.idac.schema.item import * +from titles.idac.config import IDACConfig +from titles.idac.const import IDACConstants + + +class IDACFrontend(FE_Base): + def __init__( + self, cfg: CoreConfig, environment: jinja2.Environment, cfg_dir: str + ) -> None: + super().__init__(cfg, environment) + self.data = IDACData(cfg) + self.game_cfg = IDACConfig() + if path.exists(f"{cfg_dir}/{IDACConstants.CONFIG_NAME}"): + self.game_cfg.update( + yaml.safe_load(open(f"{cfg_dir}/{IDACConstants.CONFIG_NAME}")) + ) + self.nav_name = "頭文字D THE ARCADE" + # TODO: Add version list + self.version = IDACConstants.VER_IDAC_SEASON_2 + + self.ticket_names = { + 3: "car_dressup_points", + 5: "avatar_points", + 25: "full_tune_tickets", + 34: "full_tune_fragments", + } + + def generate_all_tables_json(self, user_id: int): + json_export = {} + + idac_tables = { + profile, + config, + avatar, + rank, + stock, + theory, + car, + ticket, + story, + episode, + difficulty, + course, + trial, + challenge, + theory_course, + theory_partner, + theory_running, + vs_info, + stamp, + timetrial_event + } + + for table in idac_tables: + sql = select(table).where( + table.c.user == user_id, + ) + + # check if the table has a version column + if "version" in table.c: + sql = sql.where(table.c.version == self.version) + + # lol use the profile connection for items, dirty hack + result = self.data.profile.execute(sql) + data_list = result.fetchall() + + # add the list to the json export with the correct table name + json_export[table.name] = [] + for data in data_list: + tmp = data._asdict() + tmp.pop("id") + tmp.pop("user") + json_export[table.name].append(tmp) + + return json.dumps(json_export, indent=4, default=str, ensure_ascii=False) + + def render_GET(self, request: Request) -> bytes: + uri: str = request.uri.decode() + + template = self.environment.get_template( + "titles/idac/frontend/idac_index.jinja" + ) + sesh: Session = request.getSession() + usr_sesh = IUserSession(sesh) + + # profile export + if uri.startswith("/game/idac/export"): + if usr_sesh.user_id == 0: + return redirectTo(b"/game/idac", request) + + # set the file name, content type and size to download the json + content = self.generate_all_tables_json(usr_sesh.user_id).encode("utf-8") + request.responseHeaders.addRawHeader( + b"content-type", b"application/octet-stream" + ) + request.responseHeaders.addRawHeader( + b"content-disposition", b"attachment; filename=idac_profile.json" + ) + request.responseHeaders.addRawHeader( + b"content-length", str(len(content)).encode("utf-8") + ) + + self.logger.info(f"User {usr_sesh.user_id} exported their IDAC data") + return content + + profile_data, tickets, rank = None, None, None + if usr_sesh.user_id > 0: + profile_data = self.data.profile.get_profile(usr_sesh.user_id, self.version) + ticket_data = self.data.item.get_tickets(usr_sesh.user_id) + rank = self.data.profile.get_profile_rank(usr_sesh.user_id, self.version) + + tickets = { + self.ticket_names[ticket["ticket_id"]]: ticket["ticket_cnt"] + for ticket in ticket_data + } + + return template.render( + title=f"{self.core_config.server.name} | {self.nav_name}", + game_list=self.environment.globals["game_list"], + profile=profile_data, + tickets=tickets, + rank=rank, + sesh=vars(usr_sesh), + active_page="idac", + ).encode("utf-16") + + def render_POST(self, request: Request) -> bytes: + pass diff --git a/titles/idac/frontend/idac_index.jinja b/titles/idac/frontend/idac_index.jinja new file mode 100644 index 0000000..4bd10ca --- /dev/null +++ b/titles/idac/frontend/idac_index.jinja @@ -0,0 +1,132 @@ +{% extends "core/frontend/index.jinja" %} +{% block content %} +

頭文字D THE ARCADE

+ +{% if sesh is defined and sesh["user_id"] > 0 %} +
+
+
+
+

{{ sesh["username"] }}'s Profile

+
+
+ + +
+
+
+
+ + {% if profile is defined and profile is not none %} +
+
+
+
+
Information
+
+
Username
+

{{ profile.username }}

+
Grade
+

+ {% set grade = rank.grade %} + {% if grade >= 1 and grade <= 72 %} + {% set grade_number = (grade - 1) // 9 %} + {% set grade_letters = ['E', 'D', 'C', 'B', 'A', 'S', 'SS', 'X'] %} + {{ grade_letters[grade_number] }}{{ 9 - ((grade-1) % 9) }} + {% else %} + Unknown + {% endif %} +

+
+
+
+
+
+ +
+
Statistics
+
+
+
+
Total Plays
+

{{ profile.total_play }}

+
+
+
Last Played
+

{{ profile.last_play_date }}

+
+
+
Mileage
+

{{ profile.mileage }} m

+
+
+ {% if tickets is defined and tickets|length > 0 %} +
Tokens/Tickets
+
+
+
+
Avatar Tokens
+

{{ tickets.avatar_points }}/30

+
+
+
Car Dressup Tokens
+

{{ tickets.car_dressup_points }}/30

+
+
+
FullTune Tickets
+

{{ tickets.full_tune_tickets }}/99

+
+
+
FullTune Fragments
+

{{ tickets.full_tune_fragments }}/10

+
+
+ {% endif %} +
+
+
+
+ {% else %} + + {% endif %} + +
+
+{% else %} +
+{% endif %} + + + + + +{% endblock content %} \ No newline at end of file diff --git a/titles/idac/frontend/js/idac_scripts.js b/titles/idac/frontend/js/idac_scripts.js new file mode 100644 index 0000000..111fea6 --- /dev/null +++ b/titles/idac/frontend/js/idac_scripts.js @@ -0,0 +1,10 @@ +$(document).ready(function () { + $('#exportBtn').click(function () { + window.location = "/game/idac/export"; + + // appendAlert('Successfully exported the profile', 'success'); + + // Close the modal on success + $('#export').modal('hide'); + }); +}); \ No newline at end of file diff --git a/titles/idac/index.py b/titles/idac/index.py new file mode 100644 index 0000000..29ecb67 --- /dev/null +++ b/titles/idac/index.py @@ -0,0 +1,166 @@ +import json +import traceback +import inflection +import yaml +import logging +import coloredlogs + +from os import path +from typing import Dict, Tuple +from logging.handlers import TimedRotatingFileHandler +from twisted.web import server +from twisted.web.http import Request +from twisted.internet import reactor, endpoints + +from core.config import CoreConfig +from core.utils import Utils +from titles.idac.base import IDACBase +from titles.idac.season2 import IDACSeason2 +from titles.idac.config import IDACConfig +from titles.idac.const import IDACConstants +from titles.idac.echo import IDACEchoUDP +from titles.idac.matching import IDACMatching + + +class IDACServlet: + def __init__(self, core_cfg: CoreConfig, cfg_dir: str) -> None: + self.core_cfg = core_cfg + self.game_cfg = IDACConfig() + self.game_cfg.update( + yaml.safe_load(open(f"{cfg_dir}/{IDACConstants.CONFIG_NAME}")) + ) + + self.versions = [ + IDACBase(core_cfg, self.game_cfg), + IDACSeason2(core_cfg, self.game_cfg) + ] + + self.logger = logging.getLogger("idac") + log_fmt_str = "[%(asctime)s] IDAC | %(levelname)s | %(message)s" + log_fmt = logging.Formatter(log_fmt_str) + fileHandler = TimedRotatingFileHandler( + "{0}/{1}.log".format(self.core_cfg.server.log_dir, "idac"), + 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 + ) + + @classmethod + def get_allnet_info( + cls, game_code: str, core_cfg: CoreConfig, cfg_dir: str + ) -> Tuple[bool, str, str]: + game_cfg = IDACConfig() + + if path.exists(f"{cfg_dir}/{IDACConstants.CONFIG_NAME}"): + game_cfg.update( + yaml.safe_load(open(f"{cfg_dir}/{IDACConstants.CONFIG_NAME}")) + ) + + if not game_cfg.server.enable: + return (False, "", "") + + if core_cfg.server.is_develop: + return ( + True, + f"", + # requires http or else it defautls to https + f"http://{core_cfg.title.hostname}:{core_cfg.title.port}/{game_code}/$v/", + ) + + return ( + True, + f"", + # requires http or else it defautls to https + f"http://{core_cfg.title.hostname}/{game_code}/$v/", + ) + + def render_POST(self, request: Request, version: int, url_path: str) -> bytes: + req_raw = request.content.getvalue() + url_split = url_path.split("/") + internal_ver = 0 + endpoint = url_split[len(url_split) - 1] + client_ip = Utils.get_ip_addr(request) + + if version >= 100 and version < 140: # IDAC Season 1 + internal_ver = IDACConstants.VER_IDAC_SEASON_1 + elif version >= 140 and version < 171: # IDAC Season 2 + internal_ver = IDACConstants.VER_IDAC_SEASON_2 + + if url_split[0] == "initiald": + header_application = self.decode_header(request.getAllHeaders()) + + req_data = json.loads(req_raw) + + self.logger.info(f"v{version} {endpoint} request from {client_ip}") + self.logger.debug(f"Headers: {header_application}") + self.logger.debug(req_data) + + # func_to_find = "handle_" + inflection.underscore(endpoint) + "_request" + func_to_find = "handle_" + for x in url_split: + func_to_find += f"{x.lower()}_" if not x == "" and not x == "initiald" else "" + func_to_find += f"request" + + if not hasattr(self.versions[internal_ver], func_to_find): + self.logger.warning(f"Unhandled v{version} request {endpoint}") + return '{"status_code": "0"}'.encode("utf-8") + + resp = None + try: + handler = getattr(self.versions[internal_ver], func_to_find) + resp = handler(req_data, header_application) + + except Exception as e: + traceback.print_exc() + self.logger.error(f"Error handling v{version} method {endpoint} - {e}") + return '{"status_code": "0"}'.encode("utf-8") + + if resp is None: + resp = {"status_code": "0"} + + self.logger.debug(f"Response {resp}") + return json.dumps(resp, ensure_ascii=False).encode("utf-8") + + self.logger.warning( + f"IDAC unknown request {url_path} - {request.content.getvalue().decode()}" + ) + return '{"status_code": "0"}'.encode("utf-8") + + def decode_header(self, data: Dict) -> Dict: + app: str = data[b"application"].decode() + ret = {} + + for x in app.split(", "): + y = x.split("=") + ret[y[0]] = y[1].replace('"', "") + + return ret + + def setup(self): + if self.game_cfg.server.enable: + endpoints.serverFromString( + reactor, + f"tcp:{self.game_cfg.server.matching}:interface={self.core_cfg.server.listen_address}", + ).listen(server.Site(IDACMatching(self.core_cfg, self.game_cfg))) + + reactor.listenUDP( + self.game_cfg.server.echo1, + IDACEchoUDP(self.core_cfg, self.game_cfg, self.game_cfg.server.echo1), + ) + reactor.listenUDP( + self.game_cfg.server.echo2, + IDACEchoUDP(self.core_cfg, self.game_cfg, self.game_cfg.server.echo2), + ) diff --git a/titles/idac/matching.py b/titles/idac/matching.py new file mode 100644 index 0000000..fb9f56d --- /dev/null +++ b/titles/idac/matching.py @@ -0,0 +1,72 @@ +import json +import logging + +from typing import Dict +from twisted.web import resource + +from core import CoreConfig +from titles.idac.season2 import IDACBase +from titles.idac.config import IDACConfig + + +class IDACMatching(resource.Resource): + isLeaf = True + + def __init__(self, cfg: CoreConfig, game_cfg: IDACConfig) -> None: + self.core_config = cfg + self.game_config = game_cfg + self.base = IDACBase(cfg, game_cfg) + self.logger = logging.getLogger("idac") + + self.queue = 0 + + def get_matching_state(self): + if self.queue >= 1: + self.queue -= 1 + return 0 + else: + return 1 + + def render_POST(self, req) -> bytes: + url = req.uri.decode() + req_data = json.loads(req.content.getvalue().decode()) + header_application = self.decode_header(req.getAllHeaders()) + user_id = int(header_application["session"]) + + # self.getMatchingStatus(user_id) + + self.logger.info( + f"IDAC Matching request from {req.getClientIP()}: {url} - {req_data}" + ) + + resp = {"status_code": "0"} + if url == "/regist": + self.queue = self.queue + 1 + elif url == "/status": + if req_data.get("cancel_flag"): + self.queue = self.queue - 1 + self.logger.info( + f"IDAC Matching endpoint {req.getClientIP()} had quited" + ) + + resp = { + "status_code": "0", + # Only IPv4 is supported + "host": self.game_config.server.matching_host, + "port": self.game_config.server.matching_p2p, + "room_name": "INDTA", + "state": self.get_matching_state(), + } + + self.logger.debug(f"Response {resp}") + return json.dumps(resp, ensure_ascii=False).encode("utf-8") + + def decode_header(self, data: Dict) -> Dict: + app: str = data[b"application"].decode() + ret = {} + + for x in app.split(", "): + y = x.split("=") + ret[y[0]] = y[1].replace('"', "") + + return ret diff --git a/titles/idac/read.py b/titles/idac/read.py new file mode 100644 index 0000000..8798e9b --- /dev/null +++ b/titles/idac/read.py @@ -0,0 +1,161 @@ +import json +import logging +import os +from typing import Any, Dict, List, Optional + +from read import BaseReader +from core.data import Data +from core.config import CoreConfig +from titles.idac.const import IDACConstants +from titles.idac.database import IDACData +from titles.idac.schema.profile import * +from titles.idac.schema.item import * + + +class IDACReader(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.card_data = Data(config).card + self.data = IDACData(config) + + try: + self.logger.info( + f"Start importer for {IDACConstants.game_ver_to_string(version)}" + ) + except IndexError: + self.logger.error(f"Invalid Initial D THE ARCADE version {version}") + exit(1) + + def read(self) -> None: + if self.bin_dir is None and self.opt_dir is None: + self.logger.error( + ( + "To import your profile specify the '--optfolder'", + " path to your idac_profile.json file, exiting", + ) + ) + exit(1) + + if self.opt_dir is not None: + if not os.path.exists(self.opt_dir): + self.logger.error( + f"Path to idac_profile.json does not exist: {self.opt_dir}" + ) + exit(1) + + if os.path.isdir(self.opt_dir): + self.opt_dir = os.path.join(self.opt_dir, "idac_profile.json") + + if not os.path.isfile(self.opt_dir) or self.opt_dir[-5:] != ".json": + self.logger.error( + f"Path to idac_profile.json does not exist: {self.opt_dir}" + ) + exit(1) + + self.read_idac_profile(self.opt_dir) + + def read_idac_profile(self, file_path: str) -> None: + self.logger.info(f"Reading profile from {file_path}...") + + # read it as binary to avoid encoding issues + profile_data: Dict[str, Any] = {} + with open(file_path, "rb") as f: + profile_data = json.loads(f.read().decode("utf-8")) + + if not profile_data: + self.logger.error("Profile could not be parsed, exiting") + exit(1) + + access_code = None + while access_code is None: + access_code = input("Enter your 20 digits access code: ") + if len(access_code) != 20 or not access_code.isdigit(): + access_code = None + self.logger.warning("Invalid access code, please try again.") + + # check if access code already exists, if not create a new profile + user_id = self.card_data.get_user_id_from_card(access_code) + if user_id is None: + choice = input("Access code does not exist, do you want to create a new profile? (Y/n): ") + if choice.lower() == "n": + self.logger.info("Exiting...") + exit(0) + + user_id = self.data.user.create_user() + + if user_id is None: + self.logger.error("Failed to register user!") + user_id = -1 + + else: + card_id = self.data.card.create_card(user_id, access_code) + + if card_id is None: + self.logger.error("Failed to register card!") + user_id = -1 + + if user_id == -1: + self.logger.error("Failed to create profile, exiting") + exit(1) + + # table mapping to insert the data properly + tables = { + "idac_profile": profile, + "idac_profile_config": config, + "idac_profile_avatar": avatar, + "idac_profile_rank": rank, + "idac_profile_stock": stock, + "idac_profile_theory": theory, + "idac_user_car": car, + "idac_user_ticket": ticket, + "idac_user_story": story, + "idac_user_story_episode": episode, + "idac_user_story_episode_difficulty": difficulty, + "idac_user_course": course, + "idac_user_time_trial": trial, + "idac_user_challenge": challenge, + "idac_user_theory_course": theory_course, + "idac_user_theory_partner": theory_partner, + "idac_user_theory_running": theory_running, + "idac_user_vs_info": vs_info, + "idac_user_stamp": stamp, + "idac_user_timetrial_event": timetrial_event, + } + + for name, data_list in profile_data.items(): + # get the SQLAlchemy table object from the name + table = tables.get(name) + if table is None: + self.logger.warning(f"Unknown table {name}, skipping") + continue + + for data in data_list: + # add user to the data + data["user"] = user_id + + # check if the table has a version column + if "version" in table.c: + data["version"] = self.version + + sql = insert(table).values( + **data + ) + + # lol use the profile connection for items, dirty hack + conflict = sql.on_duplicate_key_update(**data) + result = self.data.profile.execute(conflict) + + if result is None: + self.logger.error(f"Failed to insert data into table {name}") + exit(1) + + self.logger.info(f"Inserted data into table {name}") + + self.logger.info("Profile import complete!") diff --git a/titles/idac/schema/item.py b/titles/idac/schema/item.py new file mode 100644 index 0000000..ae49c74 --- /dev/null +++ b/titles/idac/schema/item.py @@ -0,0 +1,964 @@ +from typing import Dict, Optional, List +from sqlalchemy import ( + Table, + Column, + UniqueConstraint, + PrimaryKeyConstraint, + and_, + update, +) +from sqlalchemy.types import Integer, String, TIMESTAMP, Boolean, JSON +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 + +car = Table( + "idac_user_car", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")), + Column("version", Integer, nullable=False), + Column("car_id", Integer), + Column("style_car_id", Integer), + Column("color", Integer), + Column("bureau", Integer), + Column("kana", Integer), + Column("s_no", Integer), + Column("l_no", Integer), + Column("car_flag", Integer), + Column("tune_point", Integer), + Column("tune_level", Integer, server_default="1"), + Column("tune_parts", Integer), + Column("infinity_tune", Integer, server_default="0"), + Column("online_vs_win", Integer, server_default="0"), + Column( + "pickup_seq", Integer, server_default="1" + ), # the order in which the car was picked up + Column( + "purchase_seq", Integer, server_default="1" + ), # the order in which the car was purchased + Column("color_stock_list", String(32)), + Column("color_stock_new_list", String(32)), + Column("parts_stock_list", String(48)), + Column("parts_stock_new_list", String(48)), + Column("parts_set_equip_list", String(48)), + Column("parts_list", JSON), + Column("equip_parts_count", Integer, server_default="0"), + Column("total_car_parts_count", Integer, server_default="0"), + Column("use_count", Integer, server_default="0"), + Column("story_use_count", Integer, server_default="0"), + Column("timetrial_use_count", Integer, server_default="0"), + Column("vs_use_count", Integer, server_default="0"), + Column("net_vs_use_count", Integer, server_default="0"), + Column("theory_use_count", Integer, server_default="0"), + Column("car_mileage", Integer, server_default="0"), + UniqueConstraint("user", "version", "style_car_id", name="idac_user_car_uk"), + mysql_charset="utf8mb4", +) + +ticket = Table( + "idac_user_ticket", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")), + Column("ticket_id", Integer), + Column("ticket_cnt", Integer), + UniqueConstraint("user", "ticket_id", name="idac_user_ticket_uk"), + mysql_charset="utf8mb4", +) + +story = Table( + "idac_user_story", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")), + Column("story_type", Integer), + Column("chapter", Integer), + Column("loop_count", Integer, server_default="1"), + UniqueConstraint("user", "chapter", name="idac_user_story_uk"), + mysql_charset="utf8mb4", +) + +episode = Table( + "idac_user_story_episode", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")), + Column("chapter", Integer), + Column("episode", Integer), + Column("play_status", Integer), + UniqueConstraint("user", "chapter", "episode", name="idac_user_story_episode_uk"), + mysql_charset="utf8mb4", +) + +difficulty = Table( + "idac_user_story_episode_difficulty", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")), + Column("episode", Integer), + Column("difficulty", Integer), + Column("play_count", Integer), + Column("clear_count", Integer), + Column("play_status", Integer), + Column("play_score", Integer), + UniqueConstraint( + "user", "episode", "difficulty", name="idac_user_story_episode_difficulty_uk" + ), + mysql_charset="utf8mb4", +) + +course = Table( + "idac_user_course", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")), + Column("course_id", Integer), + Column("run_counts", Integer, server_default="1"), + Column("skill_level_exp", Integer, server_default="0"), + UniqueConstraint("user", "course_id", name="idac_user_course_uk"), + mysql_charset="utf8mb4", +) + +trial = Table( + "idac_user_time_trial", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")), + Column("version", Integer, nullable=False), + Column("style_car_id", Integer), + Column("course_id", Integer), + Column("eval_id", Integer, server_default="0"), + Column("goal_time", Integer), + Column("section_time_1", Integer), + Column("section_time_2", Integer), + Column("section_time_3", Integer), + Column("section_time_4", Integer), + Column("mission", Integer), + Column("play_dt", TIMESTAMP, server_default=func.now()), + UniqueConstraint( + "user", "version", "course_id", "style_car_id", name="idac_user_time_trial_uk" + ), + mysql_charset="utf8mb4", +) + +challenge = Table( + "idac_user_challenge", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")), + Column("vs_type", Integer), + Column("play_difficulty", Integer), + Column("cleared_difficulty", Integer), + Column("story_type", Integer), + Column("play_count", Integer, server_default="1"), + Column("weak_difficulty", Integer, server_default="0"), + Column("eval_id", Integer), + Column("advantage", Integer), + Column("sec1_advantage_avg", Integer), + Column("sec2_advantage_avg", Integer), + Column("sec3_advantage_avg", Integer), + Column("sec4_advantage_avg", Integer), + Column("nearby_advantage_rate", Integer), + Column("win_flag", Integer), + Column("result", Integer), + Column("record", Integer), + Column("course_id", Integer), + Column("last_play_course_id", Integer), + Column("style_car_id", Integer), + Column("course_day", Integer), + UniqueConstraint( + "user", "vs_type", "play_difficulty", name="idac_user_challenge_uk" + ), + mysql_charset="utf8mb4", +) + +theory_course = Table( + "idac_user_theory_course", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")), + Column("course_id", Integer), + Column("max_victory_grade", Integer, server_default="0"), + Column("run_count", Integer, server_default="1"), + Column("powerhouse_lv", Integer), + Column("powerhouse_exp", Integer), + Column("played_powerhouse_lv", Integer), + Column("update_dt", TIMESTAMP, server_default=func.now()), + UniqueConstraint("user", "course_id", name="idac_user_theory_course_uk"), + mysql_charset="utf8mb4", +) + +theory_partner = Table( + "idac_user_theory_partner", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")), + Column("partner_id", Integer), + Column("fellowship_lv", Integer), + Column("fellowship_exp", Integer), + UniqueConstraint("user", "partner_id", name="idac_user_theory_partner_uk"), + mysql_charset="utf8mb4", +) + +theory_running = Table( + "idac_user_theory_running", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")), + Column("course_id", Integer), + Column("attack", Integer), + Column("defense", Integer), + Column("safety", Integer), + Column("runaway", Integer), + Column("trick_flag", Integer), + UniqueConstraint("user", "course_id", name="idac_user_theory_running_uk"), + mysql_charset="utf8mb4", +) + +vs_info = Table( + "idac_user_vs_info", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade")), + Column("group_key", String(25)), + Column("win_flg", Integer), + Column("style_car_id", Integer), + Column("course_id", Integer), + Column("course_day", Integer), + Column("players_num", Integer), + Column("winning", Integer), + Column("advantage_1", Integer), + Column("advantage_2", Integer), + Column("advantage_3", Integer), + Column("advantage_4", Integer), + Column("select_course_id", Integer), + Column("select_course_day", Integer), + Column("select_course_random", Integer), + Column("matching_success_sec", Integer), + Column("boost_flag", Integer), + Column("vs_history", Integer), + Column("break_count", Integer), + Column("break_penalty_flag", Integer), + UniqueConstraint("user", "group_key", name="idac_user_vs_info_uk"), + mysql_charset="utf8mb4", +) + +stamp = Table( + "idac_user_stamp", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column( + "user", + ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), + nullable=False, + ), + Column("m_stamp_event_id", Integer), + Column("select_flag", Integer), + Column("stamp_masu", Integer), + Column("daily_bonus", Integer), + Column("weekly_bonus", Integer), + Column("weekday_bonus", Integer), + Column("weekend_bonus", Integer), + Column("total_bonus", Integer), + Column("day_total_bonus", Integer), + Column("store_battle_bonus", Integer), + Column("story_bonus", Integer), + Column("online_battle_bonus", Integer), + Column("timetrial_bonus", Integer), + Column("fasteststreetlegaltheory_bonus", Integer), + Column("collaboration_bonus", Integer), + Column("add_bonus_daily_flag_1", Integer), + Column("add_bonus_daily_flag_2", Integer), + Column("add_bonus_daily_flag_3", Integer), + Column("create_date_daily", TIMESTAMP, server_default=func.now()), + Column("create_date_weekly", TIMESTAMP, server_default=func.now()), + UniqueConstraint("user", "m_stamp_event_id", name="idac_user_stamp_uk"), + mysql_charset="utf8mb4", +) + +timetrial_event = Table( + "idac_user_timetrial_event", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column( + "user", + ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), + nullable=False, + ), + Column("timetrial_event_id", Integer), + Column("point", Integer), + UniqueConstraint("user", "timetrial_event_id", name="idac_user_timetrial_event_uk"), + mysql_charset="utf8mb4", +) + + +class IDACItemData(BaseData): + def get_random_user_car(self, aime_id: int, version: int) -> Optional[List[Row]]: + sql = ( + select(car) + .where(and_(car.c.user == aime_id, car.c.version == version)) + .order_by(func.rand()) + .limit(1) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_random_car(self, version: int) -> Optional[List[Row]]: + sql = select(car).where(car.c.version == version).order_by(func.rand()).limit(1) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_car( + self, aime_id: int, version: int, style_car_id: int + ) -> Optional[List[Row]]: + sql = select(car).where( + and_( + car.c.user == aime_id, + car.c.version == version, + car.c.style_car_id == style_car_id, + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_cars( + self, version: int, aime_id: int, only_pickup: bool = False + ) -> Optional[List[Row]]: + if only_pickup: + sql = select(car).where( + and_( + car.c.user == aime_id, + car.c.version == version, + car.c.pickup_seq != 0, + ) + ) + else: + sql = select(car).where( + and_(car.c.user == aime_id, car.c.version == version) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_ticket(self, aime_id: int, ticket_id: int) -> Optional[Row]: + sql = select(ticket).where( + ticket.c.user == aime_id, ticket.c.ticket_id == ticket_id + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_tickets(self, aime_id: int) -> Optional[List[Row]]: + sql = select(ticket).where(ticket.c.user == aime_id) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_story(self, aime_id: int, chapter_id: int) -> Optional[Row]: + sql = select(story).where( + and_(story.c.user == aime_id, story.c.chapter == chapter_id) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_stories(self, aime_id: int) -> Optional[List[Row]]: + sql = select(story).where(story.c.user == aime_id) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_story_episodes(self, aime_id: int, chapter_id: int) -> Optional[List[Row]]: + sql = select(episode).where( + and_(episode.c.user == aime_id, episode.c.chapter == chapter_id) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_story_episode(self, aime_id: int, episode_id: int) -> Optional[Row]: + sql = select(episode).where( + and_(episode.c.user == aime_id, episode.c.episode == episode_id) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_story_episode_difficulties( + self, aime_id: int, episode_id: int + ) -> Optional[List[Row]]: + sql = select(difficulty).where( + and_(difficulty.c.user == aime_id, difficulty.c.episode == episode_id) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_courses(self, aime_id: int) -> Optional[List[Row]]: + sql = select(course).where(course.c.user == aime_id) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_course(self, aime_id: int, course_id: int) -> Optional[Row]: + sql = select(course).where( + and_(course.c.user == aime_id, course.c.course_id == course_id) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_time_trial_courses(self, version: int) -> Optional[List[Row]]: + sql = select(trial.c.course_id).where(trial.c.version == version).distinct() + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_time_trial_user_best_time_by_course_car( + self, version: int, aime_id: int, course_id: int, style_car_id: int + ) -> Optional[Row]: + sql = select(trial).where( + and_( + trial.c.user == aime_id, + trial.c.version == version, + trial.c.course_id == course_id, + trial.c.style_car_id == style_car_id, + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_time_trial_user_best_courses( + self, version: int, aime_id: int + ) -> Optional[List[Row]]: + # get for a given aime_id the best time for each course + subquery = ( + select( + trial.c.version, + func.min(trial.c.goal_time).label("min_goal_time"), + trial.c.course_id, + ) + .where(and_(trial.c.version == version, trial.c.user == aime_id)) + .group_by(trial.c.course_id) + .subquery() + ) + + # now get the full row for each best time + sql = select(trial).where( + and_( + trial.c.version == subquery.c.version, + trial.c.goal_time == subquery.c.min_goal_time, + trial.c.course_id == subquery.c.course_id, + trial.c.user == aime_id, + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_time_trial_best_cars_by_course( + self, version: int, aime_id: int, course_id: int + ) -> Optional[List[Row]]: + subquery = ( + select( + trial.c.version, + func.min(trial.c.goal_time).label("min_goal_time"), + trial.c.style_car_id, + ) + .where( + and_( + trial.c.version == version, + trial.c.user == aime_id, + trial.c.course_id == course_id, + ) + ) + .group_by(trial.c.style_car_id) + .subquery() + ) + + sql = select(trial).where( + and_( + trial.c.version == subquery.c.version, + trial.c.goal_time == subquery.c.min_goal_time, + trial.c.style_car_id == subquery.c.style_car_id, + trial.c.course_id == course_id, + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_time_trial_ranking_by_course( + self, + version: int, + course_id: int, + style_car_id: Optional[int] = None, + limit: Optional[int] = 10, + ) -> Optional[List[Row]]: + # get the top 10 ranking by goal_time for a given course which is grouped by user + subquery = select( + trial.c.version, + trial.c.user, + func.min(trial.c.goal_time).label("min_goal_time"), + ).where(and_(trial.c.version == version, trial.c.course_id == course_id)) + + # if wantd filter only by style_car_id + if style_car_id is not None: + subquery = subquery.where(trial.c.style_car_id == style_car_id) + + subquery = subquery.group_by(trial.c.user).subquery() + + sql = ( + select(trial) + .where( + and_( + trial.c.version == subquery.c.version, + trial.c.user == subquery.c.user, + trial.c.goal_time == subquery.c.min_goal_time, + ), + ) + .order_by(trial.c.goal_time) + ) + + # limit the result if needed + if limit is not None: + sql = sql.limit(limit) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_time_trial_best_ranking_by_course( + self, version: int, aime_id: int, course_id: int + ) -> Optional[Row]: + sql = ( + select(trial) + .where( + and_( + trial.c.version == version, + trial.c.user == aime_id, + trial.c.course_id == course_id, + ), + ) + .order_by(trial.c.goal_time) + .limit(1) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_challenge( + self, aime_id: int, vs_type: int, play_difficulty: int + ) -> Optional[Row]: + sql = select(challenge).where( + and_( + challenge.c.user == aime_id, + challenge.c.vs_type == vs_type, + challenge.c.play_difficulty == play_difficulty, + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_challenges(self, aime_id: int) -> Optional[List[Row]]: + sql = select(challenge).where(challenge.c.user == aime_id) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_best_challenges_by_vs_type( + self, aime_id: int, story_type: int = 4 + ) -> Optional[List[Row]]: + sql = ( + select( + challenge.c.story_type, + challenge.c.vs_type, + func.max(challenge.c.cleared_difficulty).label("max_clear_lv"), + func.max(challenge.c.play_difficulty).label("last_play_lv"), + challenge.c.course_id, + challenge.c.play_count, + ) + .where( + and_(challenge.c.user == aime_id, challenge.c.story_type == story_type) + ) + .group_by(challenge.c.vs_type, challenge.c.course_id, challenge.c.play_count) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_theory_courses(self, aime_id: int) -> Optional[List[Row]]: + sql = select(theory_course).where(theory_course.c.user == aime_id) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_theory_course_by_powerhouse_lv( + self, aime_id: int, course_id: int, powerhouse_lv: int, count: int = 3 + ) -> Optional[List[Row]]: + sql = ( + select(theory_course) + .where( + and_( + theory_course.c.user != aime_id, + theory_course.c.course_id == course_id, + theory_course.c.powerhouse_lv == powerhouse_lv, + ) + ) + .order_by(func.rand()) + .limit(count) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_theory_course(self, aime_id: int, course_id: int) -> Optional[List[Row]]: + sql = select(theory_course).where( + and_( + theory_course.c.user == aime_id, theory_course.c.course_id == course_id + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_theory_partners(self, aime_id: int) -> Optional[List[Row]]: + sql = select(theory_partner).where(theory_partner.c.user == aime_id) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_theory_running(self, aime_id: int) -> Optional[List[Row]]: + sql = select(theory_running).where(theory_running.c.user == aime_id) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_theory_running_by_course( + self, aime_id: int, course_id: int + ) -> Optional[Row]: + sql = select(theory_running).where( + and_( + theory_running.c.user == aime_id, + theory_running.c.course_id == course_id, + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_vs_infos(self, aime_id: int) -> Optional[List[Row]]: + sql = select(vs_info).where(vs_info.c.user == aime_id) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_stamps(self, aime_id: int) -> Optional[List[Row]]: + sql = select(stamp).where( + and_( + stamp.c.user == aime_id, + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_timetrial_event(self, aime_id: int, timetrial_event_id: int) -> Optional[Row]: + sql = select(timetrial_event).where( + and_( + timetrial_event.c.user == aime_id, + timetrial_event.c.timetrial_event_id == timetrial_event_id, + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def put_car(self, aime_id: int, version: int, car_data: Dict) -> Optional[int]: + car_data["user"] = aime_id + car_data["version"] = version + + sql = insert(car).values(**car_data) + conflict = sql.on_duplicate_key_update(**car_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn(f"put_car: Failed to update! aime_id: {aime_id}") + return None + return result.lastrowid + + def put_ticket(self, aime_id: int, ticket_data: Dict) -> Optional[int]: + ticket_data["user"] = aime_id + + sql = insert(ticket).values(**ticket_data) + conflict = sql.on_duplicate_key_update(**ticket_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn(f"put_ticket: Failed to update! aime_id: {aime_id}") + return None + return result.lastrowid + + def put_story(self, aime_id: int, story_data: Dict) -> Optional[int]: + story_data["user"] = aime_id + + sql = insert(story).values(**story_data) + conflict = sql.on_duplicate_key_update(**story_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn(f"put_story: Failed to update! aime_id: {aime_id}") + return None + return result.lastrowid + + def put_story_episode_play_status( + self, aime_id: int, chapter_id: int, play_status: int = 1 + ) -> Optional[int]: + sql = ( + update(episode) + .where(and_(episode.c.user == aime_id, episode.c.chapter == chapter_id)) + .values(play_status=play_status) + ) + + result = self.execute(sql) + if result is None: + self.logger.warn( + f"put_story_episode_play_status: Failed to update! aime_id: {aime_id}" + ) + return None + return result.lastrowid + + def put_story_episode( + self, aime_id: int, chapter_id: int, episode_data: Dict + ) -> Optional[int]: + episode_data["user"] = aime_id + episode_data["chapter"] = chapter_id + + sql = insert(episode).values(**episode_data) + conflict = sql.on_duplicate_key_update(**episode_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn(f"put_story_episode: Failed to update! aime_id: {aime_id}") + return None + return result.lastrowid + + def put_story_episode_difficulty( + self, aime_id: int, episode_id: int, difficulty_data: Dict + ) -> Optional[int]: + difficulty_data["user"] = aime_id + difficulty_data["episode"] = episode_id + + sql = insert(difficulty).values(**difficulty_data) + conflict = sql.on_duplicate_key_update(**difficulty_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn( + f"put_story_episode_difficulty: Failed to update! aime_id: {aime_id}" + ) + return None + return result.lastrowid + + def put_course(self, aime_id: int, course_data: Dict) -> Optional[int]: + course_data["user"] = aime_id + + sql = insert(course).values(**course_data) + conflict = sql.on_duplicate_key_update(**course_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn(f"put_course: Failed to update! aime_id: {aime_id}") + return None + return result.lastrowid + + def put_time_trial( + self, version: int, aime_id: int, time_trial_data: Dict + ) -> Optional[int]: + time_trial_data["user"] = aime_id + time_trial_data["version"] = version + + sql = insert(trial).values(**time_trial_data) + conflict = sql.on_duplicate_key_update(**time_trial_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn(f"put_time_trial: Failed to update! aime_id: {aime_id}") + return None + return result.lastrowid + + def put_challenge(self, aime_id: int, challenge_data: Dict) -> Optional[int]: + challenge_data["user"] = aime_id + + sql = insert(challenge).values(**challenge_data) + conflict = sql.on_duplicate_key_update(**challenge_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn(f"put_challenge: Failed to update! aime_id: {aime_id}") + return None + return result.lastrowid + + def put_theory_course( + self, aime_id: int, theory_course_data: Dict + ) -> Optional[int]: + theory_course_data["user"] = aime_id + + sql = insert(theory_course).values(**theory_course_data) + conflict = sql.on_duplicate_key_update(**theory_course_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn(f"put_theory_course: Failed to update! aime_id: {aime_id}") + return None + return result.lastrowid + + def put_theory_partner( + self, aime_id: int, theory_partner_data: Dict + ) -> Optional[int]: + theory_partner_data["user"] = aime_id + + sql = insert(theory_partner).values(**theory_partner_data) + conflict = sql.on_duplicate_key_update(**theory_partner_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn( + f"put_theory_partner: Failed to update! aime_id: {aime_id}" + ) + return None + return result.lastrowid + + def put_theory_running( + self, aime_id: int, theory_running_data: Dict + ) -> Optional[int]: + theory_running_data["user"] = aime_id + + sql = insert(theory_running).values(**theory_running_data) + conflict = sql.on_duplicate_key_update(**theory_running_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn( + f"put_theory_running: Failed to update! aime_id: {aime_id}" + ) + return None + return result.lastrowid + + def put_vs_info(self, aime_id: int, vs_info_data: Dict) -> Optional[int]: + vs_info_data["user"] = aime_id + + sql = insert(vs_info).values(**vs_info_data) + conflict = sql.on_duplicate_key_update(**vs_info_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn(f"put_vs_info: Failed to update! aime_id: {aime_id}") + return None + return result.lastrowid + + def put_stamp( + self, aime_id: int, stamp_data: Dict + ) -> Optional[int]: + stamp_data["user"] = aime_id + + sql = insert(stamp).values(**stamp_data) + conflict = sql.on_duplicate_key_update(**stamp_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn( + f"putstamp: Failed to update! aime_id: {aime_id}" + ) + return None + return result.lastrowid + + def put_timetrial_event( + self, aime_id: int, time_trial_event_id: int, point: int + ) -> Optional[int]: + timetrial_event_data = { + "user": aime_id, + "timetrial_event_id": time_trial_event_id, + "point": point, + } + + sql = insert(timetrial_event).values(**timetrial_event_data) + conflict = sql.on_duplicate_key_update(**timetrial_event_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn( + f"put_timetrial_event: Failed to update! aime_id: {aime_id}" + ) + return None + return result.lastrowid diff --git a/titles/idac/schema/profile.py b/titles/idac/schema/profile.py new file mode 100644 index 0000000..5e363ca --- /dev/null +++ b/titles/idac/schema/profile.py @@ -0,0 +1,440 @@ +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.sql import func, select +from sqlalchemy.engine import Row +from sqlalchemy.dialects.mysql import insert + +from core.data.schema import BaseData, metadata +from core.config import CoreConfig + +profile = Table( + "idac_profile", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column( + "user", + ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), + nullable=False, + ), + Column("version", Integer, nullable=False), + Column("username", String(8)), + Column("country", Integer), + Column("store", Integer), + Column("team_id", Integer, server_default="0"), + Column("total_play", Integer, server_default="0"), + Column("daily_play", Integer, server_default="0"), + Column("day_play", Integer, server_default="0"), + Column("mileage", Integer, server_default="0"), + Column("asset_version", Integer, server_default="1"), + Column("last_play_date", TIMESTAMP, server_default=func.now()), + Column("mytitle_id", Integer, server_default="0"), + Column("mytitle_efffect_id", Integer, server_default="0"), + Column("sticker_id", Integer, server_default="0"), + Column("sticker_effect_id", Integer, server_default="0"), + Column("papercup_id", Integer, server_default="0"), + Column("tachometer_id", Integer, server_default="0"), + Column("aura_id", Integer, server_default="0"), + Column("aura_color_id", Integer, server_default="0"), + Column("aura_line_id", Integer, server_default="0"), + Column("bgm_id", Integer, server_default="0"), + Column("keyholder_id", Integer, server_default="0"), + Column("start_menu_bg_id", Integer, server_default="0"), + Column("use_car_id", Integer, server_default="1"), + Column("use_style_car_id", Integer, server_default="1"), + Column("bothwin_count", Integer, server_default="0"), + Column("bothwin_score", Integer, server_default="0"), + Column("subcard_count", Integer, server_default="0"), + Column("vs_history", Integer, server_default="0"), + Column("stamp_key_assign_0", Integer), + Column("stamp_key_assign_1", Integer), + Column("stamp_key_assign_2", Integer), + Column("stamp_key_assign_3", Integer), + Column("name_change_category", Integer, server_default="0"), + Column("factory_disp", Integer, server_default="0"), + Column("create_date", TIMESTAMP, server_default=func.now()), + Column("cash", Integer, server_default="0"), + Column("dressup_point", Integer, server_default="0"), + Column("avatar_point", Integer, server_default="0"), + Column("total_cash", Integer, server_default="0"), + UniqueConstraint("user", "version", name="idac_profile_uk"), + mysql_charset="utf8mb4", +) + +# No point setting defaults since the game sends everything on profile creation anyway +config = Table( + "idac_profile_config", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column( + "user", + ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), + nullable=False, + ), + Column("config_id", Integer), + Column("steering_intensity", Integer), + Column("transmission_type", Integer), + Column("default_viewpoint", Integer), + Column("favorite_bgm", Integer), + Column("bgm_volume", Integer), + Column("se_volume", Integer), + Column("master_volume", Integer), + Column("store_battle_policy", Integer), + Column("battle_onomatope_display", Integer), + Column("cornering_guide", Integer), + Column("minimap", Integer), + Column("line_guide", Integer), + Column("ghost", Integer), + Column("race_exit", Integer), + Column("result_skip", Integer), + Column("stamp_select_skip", Integer), + UniqueConstraint("user", name="idac_profile_config_uk"), + mysql_charset="utf8mb4", +) + +# No point setting defaults since the game sends everything on profile creation anyway +avatar = Table( + "idac_profile_avatar", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column( + "user", + ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), + nullable=False, + ), + Column("sex", Integer), + Column("face", Integer), + Column("eye", Integer), + Column("mouth", Integer), + Column("hair", Integer), + Column("glasses", Integer), + Column("face_accessory", Integer), + Column("body", Integer), + Column("body_accessory", Integer), + Column("behind", Integer), + Column("bg", Integer), + Column("effect", Integer), + Column("special", Integer), + UniqueConstraint("user", name="idac_profile_avatar_uk"), + mysql_charset="utf8mb4", +) + +rank = Table( + "idac_profile_rank", + 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("story_rank_exp", Integer, server_default="0"), + Column("story_rank", Integer, server_default="1"), + Column("time_trial_rank_exp", Integer, server_default="0"), + Column("time_trial_rank", Integer, server_default="1"), + Column("online_battle_rank_exp", Integer, server_default="0"), + Column("online_battle_rank", Integer, server_default="1"), + Column("store_battle_rank_exp", Integer, server_default="0"), + Column("store_battle_rank", Integer, server_default="1"), + Column("theory_exp", Integer, server_default="0"), + Column("theory_rank", Integer, server_default="1"), + Column("pride_group_id", Integer, server_default="0"), + Column("pride_point", Integer, server_default="0"), + Column("grade_exp", Integer, server_default="0"), + Column("grade", Integer, server_default="1"), + Column("grade_reward_dist", Integer, server_default="0"), + Column("story_rank_reward_dist", Integer, server_default="0"), + Column("time_trial_rank_reward_dist", Integer, server_default="0"), + Column("online_battle_rank_reward_dist", Integer, server_default="0"), + Column("store_battle_rank_reward_dist", Integer, server_default="0"), + Column("theory_rank_reward_dist", Integer, server_default="0"), + Column("max_attained_online_battle_rank", Integer, server_default="1"), + Column("max_attained_pride_point", Integer, server_default="0"), + Column("is_last_max", Integer, server_default="0"), + UniqueConstraint("user", "version", name="idac_profile_rank_uk"), + mysql_charset="utf8mb4", +) + +stock = Table( + "idac_profile_stock", + 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("mytitle_list", String(1024), server_default=""), + Column("mytitle_new_list", String(1024), server_default=""), + Column("avatar_face_list", String(255), server_default=""), + Column("avatar_face_new_list", String(255), server_default=""), + Column("avatar_eye_list", String(255), server_default=""), + Column("avatar_eye_new_list", String(255), server_default=""), + Column("avatar_hair_list", String(255), server_default=""), + Column("avatar_hair_new_list", String(255), server_default=""), + Column("avatar_body_list", String(255), server_default=""), + Column("avatar_body_new_list", String(255), server_default=""), + Column("avatar_mouth_list", String(255), server_default=""), + Column("avatar_mouth_new_list", String(255), server_default=""), + Column("avatar_glasses_list", String(255), server_default=""), + Column("avatar_glasses_new_list", String(255), server_default=""), + Column("avatar_face_accessory_list", String(255), server_default=""), + Column("avatar_face_accessory_new_list", String(255), server_default=""), + Column("avatar_body_accessory_list", String(255), server_default=""), + Column("avatar_body_accessory_new_list", String(255), server_default=""), + Column("avatar_behind_list", String(255), server_default=""), + Column("avatar_behind_new_list", String(255), server_default=""), + Column("avatar_bg_list", String(255), server_default=""), + Column("avatar_bg_new_list", String(255), server_default=""), + Column("avatar_effect_list", String(255), server_default=""), + Column("avatar_effect_new_list", String(255), server_default=""), + Column("avatar_special_list", String(255), server_default=""), + Column("avatar_special_new_list", String(255), server_default=""), + Column("stamp_list", String(255), server_default=""), + Column("stamp_new_list", String(255), server_default=""), + Column("keyholder_list", String(256), server_default=""), + Column("keyholder_new_list", String(256), server_default=""), + Column("papercup_list", String(255), server_default=""), + Column("papercup_new_list", String(255), server_default=""), + Column("tachometer_list", String(255), server_default=""), + Column("tachometer_new_list", String(255), server_default=""), + Column("aura_list", String(255), server_default=""), + Column("aura_new_list", String(255), server_default=""), + Column("aura_color_list", String(255), server_default=""), + Column("aura_color_new_list", String(255), server_default=""), + Column("aura_line_list", String(255), server_default=""), + Column("aura_line_new_list", String(255), server_default=""), + Column("bgm_list", String(255), server_default=""), + Column("bgm_new_list", String(255), server_default=""), + Column("dx_color_list", String(255), server_default=""), + Column("dx_color_new_list", String(255), server_default=""), + Column("start_menu_bg_list", String(255), server_default=""), + Column("start_menu_bg_new_list", String(255), server_default=""), + Column("under_neon_list", String(255), server_default=""), + UniqueConstraint("user", "version", name="idac_profile_stock_uk"), + mysql_charset="utf8mb4", +) + +theory = Table( + "idac_profile_theory", + 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("play_count", Integer, server_default="0"), + Column("play_count_multi", Integer, server_default="0"), + Column("partner_id", Integer), + Column("partner_progress", Integer), + Column("partner_progress_score", Integer), + Column("practice_start_rank", Integer, server_default="0"), + Column("general_flag", Integer, server_default="0"), + Column("vs_history", Integer, server_default="0"), + Column("vs_history_multi", Integer, server_default="0"), + Column("win_count", Integer, server_default="0"), + Column("win_count_multi", Integer, server_default="0"), + UniqueConstraint("user", "version", name="idac_profile_theory_uk"), + mysql_charset="utf8mb4", +) + + +class IDACProfileData(BaseData): + def __init__(self, cfg: CoreConfig, conn: Connection) -> None: + super().__init__(cfg, conn) + self.date_time_format_ext = ( + "%Y-%m-%d %H:%M:%S.%f" # needs to be lopped off at [:-5] + ) + self.date_time_format_short = "%Y-%m-%d" + + def get_profile(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 get_different_random_profiles( + self, aime_id: int, version: int, count: int = 9 + ) -> Optional[Row]: + sql = ( + select(profile) + .where( + and_( + profile.c.user != aime_id, + profile.c.version == version, + ) + ) + .order_by(func.rand()) + .limit(count) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchall() + + def get_profile_config(self, aime_id: int) -> Optional[Row]: + sql = select(config).where( + and_( + config.c.user == aime_id, + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_profile_avatar(self, aime_id: int) -> Optional[Row]: + sql = select(avatar).where( + and_( + avatar.c.user == aime_id, + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_profile_rank(self, aime_id: int, version: int) -> Optional[Row]: + sql = select(rank).where( + and_( + rank.c.user == aime_id, + rank.c.version == version, + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_profile_stock(self, aime_id: int, version: int) -> Optional[Row]: + sql = select(stock).where( + and_( + stock.c.user == aime_id, + stock.c.version == version, + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def get_profile_theory(self, aime_id: int, version: int) -> Optional[Row]: + sql = select(theory).where( + and_( + theory.c.user == aime_id, + theory.c.version == version, + ) + ) + + result = self.execute(sql) + if result is None: + return None + return result.fetchone() + + def put_profile( + self, aime_id: int, version: int, profile_data: Dict + ) -> Optional[int]: + profile_data["user"] = aime_id + profile_data["version"] = version + + 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: Failed to update! aime_id: {aime_id}") + return None + return result.lastrowid + + def put_profile_config(self, aime_id: int, config_data: Dict) -> Optional[int]: + config_data["user"] = aime_id + + sql = insert(config).values(**config_data) + conflict = sql.on_duplicate_key_update(**config_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn( + f"put_profile_config: Failed to update! aime_id: {aime_id}" + ) + return None + return result.lastrowid + + def put_profile_avatar(self, aime_id: int, avatar_data: Dict) -> Optional[int]: + avatar_data["user"] = aime_id + + sql = insert(avatar).values(**avatar_data) + conflict = sql.on_duplicate_key_update(**avatar_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn( + f"put_profile_avatar: Failed to update! aime_id: {aime_id}" + ) + return None + return result.lastrowid + + def put_profile_rank( + self, aime_id: int, version: int, rank_data: Dict + ) -> Optional[int]: + rank_data["user"] = aime_id + rank_data["version"] = version + + sql = insert(rank).values(**rank_data) + conflict = sql.on_duplicate_key_update(**rank_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn(f"put_profile_rank: Failed to update! aime_id: {aime_id}") + return None + return result.lastrowid + + def put_profile_stock( + self, aime_id: int, version: int, stock_data: Dict + ) -> Optional[int]: + stock_data["user"] = aime_id + stock_data["version"] = version + + sql = insert(stock).values(**stock_data) + conflict = sql.on_duplicate_key_update(**stock_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn(f"put_profile_stock: Failed to update! aime_id: {aime_id}") + return None + return result.lastrowid + + def put_profile_theory( + self, aime_id: int, version: int, theory_data: Dict + ) -> Optional[int]: + theory_data["user"] = aime_id + theory_data["version"] = version + + sql = insert(theory).values(**theory_data) + conflict = sql.on_duplicate_key_update(**theory_data) + result = self.execute(conflict) + + if result is None: + self.logger.warn( + f"put_profile_theory: Failed to update! aime_id: {aime_id}" + ) + return None + return result.lastrowid diff --git a/titles/idac/season2.py b/titles/idac/season2.py new file mode 100644 index 0000000..8e548e5 --- /dev/null +++ b/titles/idac/season2.py @@ -0,0 +1,2106 @@ +from datetime import datetime, timedelta +import os +from random import choice +from typing import Any, Dict, List +import json +import logging + +from core.config import CoreConfig +from titles.idac.const import IDACConstants +from titles.idac.config import IDACConfig +from titles.idac.base import IDACBase + + +class IDACSeason2(IDACBase): + def __init__(self, core_cfg: CoreConfig, game_cfg: IDACConfig) -> None: + super().__init__(core_cfg, game_cfg) + self.version = IDACConstants.VER_IDAC_SEASON_2 + + # load the play stamps and timetrial events into memory + self.stamp_info = [] + if self.game_config.stamp.enable: + for stamp in self.game_config.stamp.enabled_stamps: + if not os.path.exists(f"./titles/idac/data/stamps/{stamp}.json"): + self.logger.warning(f"Stamp {stamp} is enabled but does not exist!") + continue + + with open(f"./titles/idac/data/stamps/{stamp}.json", "rb") as f: + self.logger.debug(f"Loading stamp {stamp}") + self.stamp_info.append( + self._fix_dates(json.loads(f.read().decode("utf-8"))) + ) + + self.timetrial_event = {} + self.timetrial_event_id = None + if self.game_config.timetrial.enable: + timetrial = self.game_config.timetrial.enabled_timetrial + if timetrial is not None: + if not os.path.exists(f"./titles/idac/data/timetrial/{timetrial}.json"): + self.logger.warning( + f"Timetrial {timetrial} is enabled but does not exist!" + ) + else: + self.logger.debug(f"Loading timetrial {timetrial}") + with open(f"./titles/idac/data/timetrial/{timetrial}.json", "rb") as f: + self.timetrial_event = self._fix_dates( + json.loads(f.read().decode("utf-8")) + ) + + # required for saving + self.timetrial_event_id = self.timetrial_event.get("timetrial_event_id") + + def handle_alive_get_request(self, data: Dict, headers: Dict): + return { + "status_code": "0", + # 1 = success, 0 = failed + "server_status": 1, + "force_reboot_time": int(datetime.now().timestamp()) - 86400, + } + + def _fix_dates(self, input: dict): + """ + Fix "start_dt" and "end_dt" dates in a JSON file. + """ + output = {} + + self.logger.debug(f"Fixing dates in {type(input)}") + for key, value in input.items(): + if key in {"start_dt", "end_dt"}: + if isinstance(value, str): + value = int(datetime.strptime(value, "%Y-%m-%d").timestamp()) + + output[key] = value + return output + + def handle_boot_getconfigdata_request(self, data: Dict, headers: Dict): + """ + category: + 1 = D Coin + 3 = Car Dressup Token + 5 = Avatar Dressup Token + 6 = Tachometer + 7 = Aura + 8 = Aura Color + 9 = Avatar Face + 10 = Avatar Eye + 11 = Avatar Mouth + 12 = Avatar Hair + 13 = Avatar Glasses + 14 = Avatar Face accessories + 15 = Avatar Body + 18 = Avatar Background + 21 = Chat Stamp + 22 = Keychain + 24 = Title + 25 = Full Tune Ticket + 26 = Paper Cup + 27 = BGM + 28 = Drifting Text + 31 = Start Menu BG + 32 = Car Color/Paint + 33 = Aura Level? + 34 = Full Tune Ticket Fragment + 35 = Underneon Lights + """ + version = headers["device_version"] + ver_str = version.replace(".", "")[:3] + + if self.core_cfg.server.is_develop: + domain_api_game = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDGT/{ver_str}/" + else: + domain_api_game = ( + f"http://{self.core_cfg.title.hostname}/SDGT/{ver_str}/" + ) + + return { + "status_code": "0", + "free_continue_enable": 1, + "free_continue_new": 1, + "free_continue_play": 1, + "difference_time_to_jp": 0, + # has to match the game asset version to show theory of street + "asset_version": "1", + # option version? MV01? + "optional_version": "1", + "disconnect_offset": 0, + "boost_balance_version": "0", + "time_release_number": "0", + "play_stamp_enable": 1, + "play_stamp_bonus_coin": 1, + "gacha_chara_needs": 1, + "both_win_system_control": 1, + "subcard_system_congrol": 1, + "server_maintenance_start_hour": 0, + "server_maintenance_start_minutes": 0, + "server_maintenance_end_hour": 0, + "server_maintenance_end_minutes": 0, + "domain_api_game": domain_api_game, + "domain_matching": f"http://{self.core_cfg.title.hostname}:{self.game_config.server.matching}", + "domain_echo1": f"{self.core_cfg.title.hostname}:{self.game_config.server.echo1}", + "domain_echo2": f"{self.core_cfg.title.hostname}:{self.game_config.server.echo2}", + "domain_ping": f"{self.core_cfg.title.hostname}", + "battle_gift_event_master": [], + "round_event": [], + "last_round_event": [], + "last_round_event_ranking": [], + "round_event_exp": [], + "stamp_info": self.stamp_info, + # 0 = use default data, 1+ = server version of timereleasedata response + "timerelease_no": 5, + # 0 = use default data, 1+ = server version of gachadata response + "timerelease_avatar_gacha_no": 5, + "takeover_reward": [], + "subcard_judge": [ + { + "condition_id": 1, + "lower_rank": 0, + "higher_rank": 10, + "condition_start": 2, + "condition_end": 3, + } + ], + "special_promote": [{"counter": 1, "online_rank_id": 1}], + "matching_id": 1, + "matching_group": [ + { + "group_id": 1, + "group_percent": 1, + } + ], + "timetrial_disp_date": int( + datetime.strptime("2023-10-01", "%Y-%m-%d").timestamp() + ), + # price for every car + "buy_car_need_cash": 5000, + # number of buyable shop/customization time limits + "time_extension_limit": 1, + "collabo_id": 0, + "driver_debut_end_date": int( + datetime.strptime("2029-01-01", "%Y-%m-%d").timestamp() + ), + "online_battle_param1": 1, + "online_battle_param2": 1, + "online_battle_param3": 1, + "online_battle_param4": 1, + "online_battle_param5": 1, + "online_battle_param6": 1, + "online_battle_param7": 1, + "online_battle_param8": 1, + "theory_open_version": "1.30", + "theory_close_version": "1.50", + "special_mode_data": { + "start_dt": int( + datetime.strptime("2023-01-01", "%Y-%m-%d").timestamp() + ), + "end_dt": int(datetime.strptime("2029-01-01", "%Y-%m-%d").timestamp()), + "story_type": 4, # touhou special event + }, + "timetrial_event_data": self.timetrial_event, + } + + def handle_boot_bookkeep_request(self, data: Dict, headers: Dict): + pass + + def handle_boot_getgachadata_request(self, data: Dict, headers: Dict): + """ + Reward category types: + 9: Face + 10: Eye + 11: Mouth + 12: Hair + 13: Glasses + 14: Face accessories + 15: Body + 18: Background + """ + + with open("./titles/idac/data/avatarGacha.json") as f: + avatar_gacha_data = json.load(f) + + # avatar_gacha_data = { + # "status_code": "0", + # "avatar_gacha_data": [ + # { + # "avatar_gacha_id": 0, + # "avatar_gacha_nm": "Standard", + # "gacha_type": 0, + # "save_filename": "0", + # "use_ticket_cnt": 1, + # "start_dt": int( + # datetime.strptime("2019-01-01", "%Y-%m-%d").timestamp() + # ), + # "end_dt": int( + # datetime.strptime("2029-01-01", "%Y-%m-%d").timestamp() + # ), + # "gacha_reward": [ + # { + # "reward_id": 117, + # "reward_type": 118, + # "reward_category": 18, + # "rate": 1000, + # "pickup_flag": 0, + # }, + # ], + # } + # ], + # } + + self.logger.debug( + f'Available avatar gacha items: {len(avatar_gacha_data["avatar_gacha_data"][0]["gacha_reward"])}' + ) + + return avatar_gacha_data + + def handle_boot_gettimereleasedata_request(self, data: Dict, headers: Dict): + """ + timerelease_story: + 1 = Story: 1, 2, 3, 4, 5, 6, 7, 8, 9, 19 (Chapter 10), (29 Chapter 11 lol?) + 2 = MF Ghost: 10, 11, 12, 13, 14, 15 + 3 = Bunta: 15, 16, 17, 18, 19, 20, (21, 21, 22?) + 4 = Special Event: 23, 24, 25, 26, 27, 28 (Touhou Project) + """ + path = "./titles/idac/data/" + + # 1.00.00 is default + device_version_data = headers.get("device_version", "1.00.00") + device_version = int(device_version_data.replace(".", "")[:-2]) + + timerelease_filename = f"timeRelease_v{device_version:04d}" + timerelease_path = f"{path}{timerelease_filename}.json" + + # if the file doesn't exist, try to find the next lowest version + if not os.path.exists(timerelease_path): + while device_version > 100: + device_version -= 1 + timerelease_filename = f"timeRelease_v{device_version:04d}" + timerelease_path = f"{path}{timerelease_filename}.json" + + # if the file exists, break out of the loop + if os.path.exists(timerelease_path): + break + + self.logger.debug(f"Using time release file: {timerelease_filename}") + # load the time release data + with open(f"{path}{timerelease_filename}.json") as f: + time_release_data = json.load(f) + + return time_release_data + + def handle_advertise_getrankingdata_request(self, data: Dict, headers: Dict): + best_data = [] + for last_update in data.get("last_update_date"): + course_id = last_update.get("course_id") + + ranking = self.data.item.get_time_trial_ranking_by_course( + self.version, course_id + ) + ranking_data = [] + for i, rank in enumerate(ranking): + user_id = rank["user"] + + # get the username, country and store from the profile + profile = self.data.profile.get_profile(user_id, self.version) + + # should never happen + if profile is None: + continue + + ranking_data.append( + { + "course_id": course_id, + "rank": i + 1, + "username": profile["username"], + "value": rank["goal_time"], + # gat the store name from the profile + "store": self.core_cfg.server.name, + # get the country id from the profile, 9 is JPN + "country": 9, + "style_car_id": rank["style_car_id"], + # convert the dateimt to a timestamp + "play_dt": int(rank["play_dt"].timestamp()), + "section_time_1": rank["section_time_1"], + "section_time_2": rank["section_time_2"], + "section_time_3": rank["section_time_3"], + "section_time_4": rank["section_time_4"], + "mission": rank["mission"], + } + ) + + best_data.append( + { + "course_id": course_id, + "ranking_data": ranking_data, + } + ) + + return { + "status_code": "0", + "national_best_data": best_data, + "shop_best_data": best_data, + "rank_management_flag": 0, + } + + def handle_login_checklock_request(self, data: Dict, headers: Dict): + access_code = data["accesscode"] + user_id = data["id"] + + # check if an IDAC profile already exists + p = self.data.profile.get_profile(user_id, self.version) + is_new_player = 1 if p is None else 0 + + # other: in use + return { + "status_code": "0", + # 0 = already in use, 1 = good, 2 = too new + "lock_result": 1, + "lock_date": int(datetime.now().timestamp()), + "daily_play": 1, + "session": f"{user_id}", + "shared_security_key": "a", + "session_procseq": "a", + "new_player": is_new_player, + "server_status": 1, + } + + def handle_login_unlock_request(self, data: Dict, headers: Dict): + return { + "status_code": "0", + "lock_result": 1, + } + + def handle_login_relock_request(self, data: Dict, headers: Dict): + return { + "status_code": "0", + "lock_result": 1, + "lock_date": int(datetime.now().timestamp()), + } + + def handle_login_guestplay_request(self, data: Dict, headers: Dict): + # TODO + pass + + def _generate_story_data(self, user_id: int) -> Dict: + stories = self.data.item.get_stories(user_id) + + story_data = [] + for s in stories: + chapter_id = s["chapter"] + episodes = self.data.item.get_story_episodes(user_id, chapter_id) + + episode_data = [] + for e in episodes: + episode_id = e["episode"] + difficulties = self.data.item.get_story_episode_difficulties( + user_id, episode_id + ) + + difficulty_data = [] + for d in difficulties: + difficulty_data.append( + { + "difficulty": d["difficulty"], + "play_count": d["play_count"], + "clear_count": d["clear_count"], + "play_status": d["play_status"], + "play_score": d["play_score"], + } + ) + + episode_data.append( + { + "episode": e["episode"], + "play_status": e["play_status"], + "difficulty_data": difficulty_data, + } + ) + + story_data.append( + { + "story_type": s["story_type"], + "chapter": s["chapter"], + "loop_count": s["loop_count"], + "episode_data": episode_data, + } + ) + + return story_data + + def _generate_special_data(self, user_id: int) -> Dict: + # 4 = special mode + specials = self.data.item.get_best_challenges_by_vs_type(user_id, story_type=4) + + special_data = [] + for s in specials: + special_data.append( + { + "story_type": s["story_type"], + "vs_type": s["vs_type"], + "max_clear_lv": s["max_clear_lv"], + "last_play_lv": s["last_play_lv"], + # change to last_play_course_id? + "last_play_course_id": s["course_id"], + } + ) + + return special_data + + def _generate_challenge_data(self, user_id: int) -> Dict: + # challenge mode (Bunta challenge only right now) + challenges = self.data.item.get_best_challenges_by_vs_type( + user_id, story_type=3 + ) + + challenge_data = [] + for c in challenges: + challenge_data.append( + { + "story_type": c["story_type"], + "vs_type": c["vs_type"], + "max_clear_lv": c["max_clear_lv"], + "last_play_lv": c["last_play_lv"], + # change to last_play_course_id? + "last_play_course_id": c["course_id"], + "play_count": c["play_count"], + } + ) + + return challenge_data + + def _save_stock_data(self, user_id: int, stock_data: Dict): + updated_stock_data = {} + for k, v in stock_data.items(): + if v != "": + updated_stock_data[k] = v + + if updated_stock_data: + self.data.profile.put_profile_stock( + user_id, self.version, updated_stock_data + ) + + def handle_user_getdata_request(self, data: Dict, headers: Dict): + user_id = int(headers["session"]) + + # get the user's profile, can never be None + p = self.data.profile.get_profile(user_id, self.version) + user_data = p._asdict() + del user_data["id"] + del user_data["user"] + del user_data["version"] + user_data["id"] = user_id + user_data["store_name"] = self.core_cfg.server.name + user_data["last_play_date"] = int(user_data["last_play_date"].timestamp()) + user_data["create_date"] = int(user_data["create_date"].timestamp()) + + # get the user's rank + r = self.data.profile.get_profile_rank(user_id, self.version) + rank_data = r._asdict() + del rank_data["id"] + del rank_data["user"] + del rank_data["version"] + + # add the mode_rank_data to the user_data + user_data["mode_rank_data"] = rank_data + + # get the user's avatar + a = self.data.profile.get_profile_avatar(user_id) + avatar_data = a._asdict() + del avatar_data["id"] + del avatar_data["user"] + + # get the user's stock + s = self.data.profile.get_profile_stock(user_id, self.version) + stock_data = s._asdict() + del stock_data["id"] + del stock_data["user"] + del stock_data["version"] + + # get the user's config + c = self.data.profile.get_profile_config(user_id) + config_data = c._asdict() + del config_data["id"] + del config_data["user"] + config_data["id"] = config_data.pop("config_id") + + # get the user's ticket + tickets: list = self.data.item.get_tickets(user_id) + + """ + ticket_id: + 3 = Car Dressup Points + 5 = Avatar Dressup Points + 25 = Full Tune Tickets + 34 = Full Tune Fragments + """ + + ticket_data = [] + for ticket in tickets: + ticket_data.append( + { + "ticket_id": ticket["ticket_id"], + "ticket_cnt": ticket["ticket_cnt"], + } + ) + + # get the user's course, required for the "course proeficiency" + courses = self.data.item.get_courses(user_id) + course_data = [] + for course in courses: + course_data.append( + { + "id": 0, # no clue, always 0? + "course_id": course["course_id"], + "run_counts": course["run_counts"], + # "course proeficiency" in exp points + "skill_level_exp": course["skill_level_exp"], + } + ) + + # get the profile theory data + theory_data = {} + theory = self.data.profile.get_profile_theory(user_id, self.version) + if theory is not None: + theory_data = theory._asdict() + del theory_data["id"] + del theory_data["user"] + del theory_data["version"] + + # get the users theory course data + theory_course_data = [] + theory_courses = self.data.item.get_theory_courses(user_id) + for course in theory_courses: + tmp = course._asdict() + del tmp["id"] + del tmp["user"] + tmp["update_dt"] = int(tmp["update_dt"].timestamp()) + + theory_course_data.append(tmp) + + # get the users theory partner data + theory_partner_data = [] + theory_partners = self.data.item.get_theory_partners(user_id) + for partner in theory_partners: + tmp = partner._asdict() + del tmp["id"] + del tmp["user"] + + theory_partner_data.append(tmp) + + # get the users theory running pram data + theory_running_pram_data = [] + theory_running = self.data.item.get_theory_running(user_id) + for running in theory_running: + tmp = running._asdict() + del tmp["id"] + del tmp["user"] + + theory_running_pram_data.append(tmp) + + # get the users vs info data + vs_info_data = [] + vs_info = self.data.item.get_vs_infos(user_id) + for vs in vs_info: + vs_info_data.append( + { + "battle_mode": 1, + "vs_cnt": 1, + "vs_win": vs["win_flg"], + "invalid": 0, + "str": 0, + "str_now": 0, + "lose_now": 0, + "vs_history": vs["vs_history"], + "course_select_priority": 0, + "vsinfo_course_data": [ + { + "course_id": vs["course_id"], + "vs_cnt": 1, + "vs_win": vs["win_flg"], + } + ], + } + ) + + # get the user's car + cars = self.data.item.get_cars(self.version, user_id, only_pickup=True) + fulltune_count = 0 + total_car_parts_count = 0 + car_data = [] + for car in cars: + tmp = car._asdict() + del tmp["id"] + del tmp["user"] + del tmp["version"] + + car_data.append(tmp) + # tune_level of 16 means fully tuned, so add 1 to fulltune_count + if car["tune_level"] >= 16: + fulltune_count += 1 + + # add the number of car parts to total_car_parts_count? + # total_car_parts_count += tmp["total_car_parts_count"] + + car_data.append(tmp) + + # update user profile car count + user_data["have_car_cnt"] = len(car_data) + + # get the user's play stamps + stamps = self.data.item.get_stamps(user_id) + stamp_event_data = [] + for stamp in stamps: + tmp = stamp._asdict() + del tmp["id"] + del tmp["user"] + + now = datetime.now() + + # create timestamp for today at 1am + this_day = now.replace(hour=1, minute=0, second=0, microsecond=0) + + # check if this_day is greater than or equal to create_date_daily + if this_day >= tmp["create_date_daily"]: + # reset the daily stamp + tmp["create_date_daily"] = now + tmp["daily_bonus"] = 0 + + # create a timestamp for this monday at 1am + this_monday = now - timedelta(days=now.weekday()) + this_monday = this_monday.replace(hour=1, minute=0, second=0, microsecond=0) + + # check if this_monday is greater than or equal to create_date_weekly + if this_monday >= tmp["create_date_weekly"]: + # reset the weekly stamp + tmp["create_date_weekly"] = now + tmp["weekly_bonus"] = 0 + + # update the play stamp in the database + self.data.item.put_stamp(user_id, tmp) + + del tmp["create_date_daily"] + del tmp["create_date_weekly"] + stamp_event_data.append(tmp) + + # get the user's timetrial event data + timetrial_event_data = {} + timetrial = self.data.item.get_timetrial_event(user_id, self.timetrial_event_id) + if timetrial is not None: + timetrial_event_data = { + "timetrial_event_id": timetrial["timetrial_event_id"], + "point": timetrial["point"], + } + + return { + "status_code": "0", + "user_base_data": user_data, + "avatar_data": avatar_data, + "pick_up_car_data": car_data, + "story_data": self._generate_story_data(user_id), + "vsinfo_data": vs_info_data, + "stock_data": stock_data, + "mission_data": { + "id": 0, + "achieve_flag": 0, + "received_flag": 0, + "update_dt": int(datetime.now().timestamp() - 86400), + }, + "weekly_mission_data": [], + "course_data": course_data, + "toppatu_event_data": { + "id": 0, + "event_id": 0, + "count1": 0, + "count2": 0, + "count3": 0, + "accept_flag": 0, + }, + "event_data": { + "id": 0, + "active_event_id": 0, + "dialog_show_date": int(datetime.now().timestamp() - 86400), + "show_start_dialog_flag": 1, + "show_progress_dialog_flag": 1, + "show_end_dialog_flag": 1, + "end_event_id": 0, + }, + "rewards_data": {}, + "login_bonus_data": { + "gacha_id": 0, + "gacha_item_id": 0, + "category": 0, + "type": 0, + }, + "frozen_data": {"frozen_status": 2}, + "penalty_data": {"penalty_flag": 0, "penalty_2_level": 0}, + "config_data": config_data, + "battle_gift_data": [], + "ticket_data": ticket_data, + "round_event": [], + "last_round_event": [], + "past_round_event": [], + "total_round_point": 0, + "stamp_event_data": stamp_event_data, + "avatar_gacha_lottery_data": {"avatar_gacha_id": 0}, + "fulltune_count": fulltune_count, + "total_car_parts_count": total_car_parts_count, + "car_layout_count": [], + "car_style_count": [], + "car_use_count": [], + "maker_use_count": [], + "story_course": [{"course_id": 0, "count": 1}], + # TODO! + # "driver_debut": { + # "play_count": 137, + # "daily_play": 5, + # "last_play_dt": 0, + # "use_start_date": 0, + # "use_end_date": 0, + # "use_dt": 0, + # "ticket_cnt": 0, + # "ticket_get_bit": 0, + # }, + "theory_data": theory_data, + "theory_course_data": theory_course_data, + "theory_partner_data": theory_partner_data, + "theory_running_pram_data": theory_running_pram_data, + "special_mode_data": self._generate_special_data(user_id), + "challenge_mode_data": self._generate_challenge_data(user_id), + "season_rewards_data": [], + "timetrial_event_data": timetrial_event_data, + "special_mode_hint_data": {"story_type": 0, "hint_display_flag": 0}, + } + + def handle_timetrial_getbestrecordpreta_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + for car_id in data["car_ids"]: + pass + + course_mybest_data = [] + courses = self.data.item.get_time_trial_user_best_courses(self.version, user_id) + for course in courses: + course_mybest_data.append( + { + "course_id": course["course_id"], + # local rank, store rank, worldwide rank? + "rank": 1, + # no clue + "member": 10000, + # goal_time in ms + "value": course["goal_time"], + # total number of entries per course? + "total": 10, + "store": self.core_cfg.server.name, + # use car_id from request? + "car_id": 0, + "style_car_id": course["style_car_id"], + "play_dt": course["play_dt"].timestamp(), + "section_time_1": course["section_time_1"], + "section_time_2": course["section_time_2"], + "section_time_3": course["section_time_3"], + "section_time_4": course["section_time_4"], + # no clue + "mission": course["mission"], + } + ) + + course_pickup_car_best_data = [] + courses = self.data.item.get_time_trial_courses(self.version) + for course in courses: + car_list = [] + best_cars = self.data.item.get_time_trial_best_cars_by_course( + self.version, user_id, course["course_id"] + ) + + for car in best_cars: + car_list.append( + { + "rank": 1, + # no clue + "member": user_id, + "value": car["goal_time"], + "store": self.core_cfg.server.name, + # use car_id from request? + "car_id": 0, + "style_car_id": car["style_car_id"], + "play_dt": car["play_dt"].timestamp(), + "section_time_1": car["section_time_1"], + "section_time_2": car["section_time_2"], + "section_time_3": car["section_time_3"], + "section_time_4": car["section_time_4"], + "mission": car["mission"], + } + ) + + course_pickup_car_best_data.append( + { + "course_id": course["course_id"], + "car_list": car_list, + } + ) + + return { + "status_code": "0", + "course_mybest_data": course_mybest_data, + # "course_car_best_data": course_car_best_data, + # "course_best_data": course_best_data, + "location_course_store_best_data": [], + "course_pickup_car_best_data": course_pickup_car_best_data, + } + + def handle_timetrial_getbestrecordprerace_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + for car_id in data["car_ids"]: + pass + + course_best_data = [ + { + "course_id": 56, + "rank": 1, + "member": user_id, + "value": 118016, + "store": self.core_cfg.server.name, + "car_id": 0, + "style_car_id": 0, + "play_dt": int(datetime.now().timestamp() - 86400), + "section_time_1": 45205, + "section_time_2": 47779, + "section_time_3": 43480, + "section_time_4": 41552, + "mission": 1, + } + ] + + return { + "status_code": "0", + # "course_car_best_data": course_car_best_data, + "course_best_data": course_best_data, + } + + def handle_user_createaccount_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + car_data: Dict = data.pop("car_obj") + parts_data: List = car_data.pop("parts_list") + avatar_data: Dict = data.pop("avatar_obj") + config_data: Dict = data.pop("config_obj") + + rank_data: Dict = data.pop("mode_rank_data") + stock_data: Dict = data.pop("takeover_stock_obj") + takeover_ticket_list: List = data.pop("takeover_ticket") + + # not required? + use_ticket = data.pop("use_ticket") + + # save profile in database + data["store"] = headers.get("a_store", 0) + data["country"] = headers.get("a_country", 0) + data["asset_version"] = headers.get("asset_version", 1) + self.data.profile.put_profile(user_id, self.version, data) + + # save rank data in database + self.data.profile.put_profile_rank(user_id, self.version, rank_data) + + # save stock data in database + self._save_stock_data(user_id, stock_data) + + # save tickets in database + for ticket in takeover_ticket_list: + self.data.item.put_ticket(user_id, ticket) + + config_data["config_id"] = config_data.pop("id") + self.data.profile.put_profile_config(user_id, config_data) + self.data.profile.put_profile_avatar(user_id, avatar_data) + + # save car data and car parts in database + car_data["parts_list"] = parts_data + self.data.item.put_car(user_id, self.version, car_data) + + return {"status_code": "0"} + + def handle_user_updatelogin_request(self, data: Dict, headers: Dict): + pass + + def handle_timetrial_getcarbest_request(self, data: Dict, headers: Dict): + pass + + def handle_factory_avatargacharesult_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + stock_data: Dict = data.pop("stock_obj") + use_ticket_cnt = data["use_ticket_cnt"] + + # save stock data in database + self._save_stock_data(user_id, stock_data) + + # get the user's ticket + tickets: list = self.data.item.get_tickets(user_id) + ticket_list = [] + for ticket in tickets: + # avatar tickets + if ticket["ticket_id"] == 5: + ticket_data = { + "ticket_id": ticket["ticket_id"], + "ticket_cnt": ticket["ticket_cnt"] - use_ticket_cnt, + } + + # update the ticket in the database + self.data.item.put_ticket(user_id, ticket_data) + ticket_list.append(ticket_data) + + continue + + ticket_list.append( + { + "ticket_id": ticket["ticket_id"], + "ticket_cnt": ticket["ticket_cnt"], + } + ) + + return {"status_code": "0", "ticket_data": ticket_list} + + def handle_factory_savefavoritecar_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + # save favorite cars in database + for car in data["pickup_on_car_ids"]: + self.data.item.put_car(user_id, self.version, car) + + for car in data["pickup_off_car_ids"]: + self.data.item.put_car( + user_id, + self.version, + {"style_car_id": car["style_car_id"], "pickup_seq": 0}, + ) + + return {"status_code": "0"} + + def handle_factory_updatemultiplecustomizeresult_request( + self, data: Dict, headers: Dict + ): + user_id = headers["session"] + + car_list = data.pop("car_list") + ticket_data: List = data.pop("ticket_data") + + # unused + total_car_parts_count = data.pop("total_car_parts_count") + + # save tickets in database + for ticket in ticket_data: + self.data.item.put_ticket(user_id, ticket) + + for car in car_list: + # save car data and car parts in database + self.data.item.put_car(user_id, self.version, car) + + return {"status_code": "0"} + + def handle_factory_updatecustomizeresult_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + parts_data: List = data.pop("parts_list") + ticket_data: List = data.pop("ticket_data") + + # save tickets in database + for ticket in ticket_data: + self.data.item.put_ticket(user_id, ticket) + + # save car data in database + data["parts_list"] = parts_data + self.data.item.put_car(user_id, self.version, data) + + return {"status_code": "0"} + + def handle_factory_getcardata_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + cars = self.data.item.get_cars(self.version, user_id) + car_data = [] + for car in cars: + tmp = car._asdict() + del tmp["id"] + del tmp["user"] + del tmp["version"] + + car_data.append(tmp) + + return { + "status_code": "0", + "car_data": car_data, + } + + def handle_factory_renamebefore_request(self, data: Dict, headers: Dict): + pass + + def handle_factory_buycarresult_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + parts_data: List = data.pop("parts_list") + pickup_on_list: List = data.pop("pickup_on_car_ids") + pickup_off_list: List = data.pop("pickup_off_car_ids") + + style_car_id = data.get("style_car_id") + + # get the pickup_seq for the new car + pickup_seq = 0 + # save favorite cars in database + for car in pickup_on_list: + # if the new car is a favorite get the new pickup_seqn for later + if car["style_car_id"] == style_car_id: + pickup_seq = car["pickup_seq"] + else: + self.data.item.put_car(user_id, self.version, car) + + data["pickup_seq"] = pickup_seq + + cash = data.pop("cash") + total_cash = data.pop("total_cash") + + # save the new cash in database + self.data.profile.put_profile( + user_id, self.version, {"total_cash": total_cash, "cash": cash} + ) + + # full tune ticket + use_ticket = data.pop("use_ticket") + if use_ticket: + # get the user's tickets, full tune ticket id is 25 + ticket = self.data.item.get_ticket(user_id, ticket_id=25) + + # update the ticket in the database + self.data.item.put_ticket( + user_id, + { + "ticket_id": ticket["ticket_id"], + "ticket_cnt": ticket["ticket_cnt"] - 1, + }, + ) + + # also set the tune_level to 16 (fully tuned) + data["tune_level"] = 16 + + # save car data and car parts in database + data["parts_list"] = parts_data + self.data.item.put_car(user_id, self.version, data) + + for car in pickup_off_list: + self.data.item.put_car( + user_id, + self.version, + {"style_car_id": car["style_car_id"], "pickup_seq": 0}, + ) + + # get the user's car + cars = self.data.item.get_cars(self.version, user_id) + fulltune_count = 0 + total_car_parts_count = 0 + for car in cars: + # tune_level of 16 means fully tuned, so add 1 to fulltune_count + if car["tune_level"] >= 16: + fulltune_count += 1 + + # add the number of car parts to total_car_parts_count + # total_car_parts_count += car["total_car_parts_count"] + + # get the user's ticket + tickets = self.data.item.get_tickets(user_id) + ticket_data = [] + for ticket in tickets: + ticket_data.append( + { + "ticket_id": ticket["ticket_id"], + "ticket_cnt": ticket["ticket_cnt"], + } + ) + + return { + "status_code": "0", + "ticket_data": ticket_data, + "fulltune_count": fulltune_count, + "total_car_parts_count": total_car_parts_count, + "car_layout_count": [], + "car_style_count": [], + } + + def handle_factory_renameresult_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + new_username = data.get("username") + + # save new username in database + if new_username: + self.data.profile.put_profile(user_id, self.version, data) + + return {"status_code": "0"} + + def handle_factory_updatecustomizeavatar_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + avatar_data: Dict = data.pop("avatar_obj") + stock_data: Dict = data.pop("stock_obj") + + # update the stock data in database + self._save_stock_data(user_id, stock_data) + + # save avatar data and avatar parts in database + self.data.profile.put_profile_avatar(user_id, avatar_data) + + return {"status_code": "0"} + + def handle_factory_updatecustomizeuser_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + stock_data: Dict = data.pop("stock_obj") + + # update the stock data in database + self._save_stock_data(user_id, stock_data) + + # update profile data and config in database + self.data.profile.put_profile(user_id, self.version, data) + + return {"status_code": "0"} + + def handle_user_updatestampinfo_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + stamp_event_data = data.pop("stamp_event_data") + for stamp in stamp_event_data: + self.data.item.put_stamp(user_id, stamp) + + return {"status_code": "0"} + + def handle_user_updatetimetrialresult_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + stock_data: Dict = data.pop("stock_obj") + ticket_data: List = data.pop("ticket_data") + reward_dist_data: Dict = data.pop("reward_dist_obj") + driver_debut_data = data.pop("driver_debut_obj") + rank_data: Dict = data.pop("mode_rank_obj") + + # time trial event points + event_point = data.pop("event_point") + + # save stock data in database + self._save_stock_data(user_id, stock_data) + + # save tickets in database + for ticket in ticket_data: + self.data.item.put_ticket(user_id, ticket) + + # save mode rank data in database + rank_data.update(reward_dist_data) + self.data.profile.put_profile_rank(user_id, self.version, rank_data) + + # get the profile data, update total_play and daily_play, and save it + profile = self.data.profile.get_profile(user_id, self.version) + total_play = profile["total_play"] + 1 + + # update profile + self.data.profile.put_profile( + user_id, + self.version, + { + "total_play": total_play, + "last_play_date": datetime.now(), + "aura_id": data.pop("aura_id"), + "aura_color_id": data.pop("aura_color_id"), + "aura_line_id": data.pop("aura_line_id"), + "cash": data.pop("cash"), + "total_cash": data.pop("total_cash"), + "dressup_point": data.pop("dressup_point"), + "avatar_point": data.pop("avatar_point"), + "mileage": data.pop("mileage"), + }, + ) + + # get the use_count and story_use_count of the used car + style_car_id = data.get("style_car_id") + car_mileage = data.pop("car_mileage") + used_car = self.data.item.get_car(user_id, self.version, style_car_id)._asdict() + + # increase the use_count and story_use_count of the used car + used_car["use_count"] += 1 + used_car["timetrial_use_count"] += 1 + used_car["car_mileage"] = car_mileage + + # save the used car in database + self.data.item.put_car(user_id, self.version, used_car) + + # skill_level_exp is the "course proeficiency" and is saved + # in the course table + course_id = data.get("course_id") + run_counts = 1 + skill_level_exp = data.pop("skill_level_exp") + + # get the course data + course = self.data.item.get_course(user_id, course_id) + if course: + # update run_counts + run_counts = course["run_counts"] + 1 + + self.data.item.put_course( + user_id, + { + "course_id": course_id, + "run_counts": run_counts, + "skill_level_exp": skill_level_exp, + }, + ) + + goal_time = data.get("goal_time") + # grab the ranking data and count the numbers of rows with a faster time + # than the current goal_time + course_rank = self.data.item.get_time_trial_ranking_by_course( + self.version, course_id, limit=None + ) + course_rank = len([r for r in course_rank if r["goal_time"] < goal_time]) + 1 + + car_course_rank = self.data.item.get_time_trial_ranking_by_course( + self.version, course_id, style_car_id, limit=None + ) + car_course_rank = ( + len([r for r in car_course_rank if r["goal_time"] < goal_time]) + 1 + ) + + # only update the time if its better than the best time and also not 0 + if data.get("goal_time") > 0: + # get the current best goal time + best_time_trial = ( + self.data.item.get_time_trial_user_best_time_by_course_car( + self.version, user_id, course_id, style_car_id + ) + ) + + if ( + best_time_trial is None + or data.get("goal_time") < best_time_trial["goal_time"] + ): + # now finally save the time trial with updated timestamp + data["play_dt"] = datetime.now() + self.data.item.put_time_trial(self.version, user_id, data) + + # update the timetrial event points + self.data.item.put_timetrial_event(user_id, self.timetrial_event_id, event_point) + + return { + "status_code": "0", + "course_rank": course_rank, + "course_car_rank": car_course_rank, + "location_course_store_rank": course_rank, + "car_use_count": [], + "maker_use_count": [], + } + + def handle_user_updatestoryresult_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + stock_data: Dict = data.pop("stock_obj") + ticket_data: List = data.pop("ticket_data") + reward_dist_data: Dict = data.pop("reward_dist_obj") + driver_debut_data = data.pop("driver_debut_obj") + rank_data: Dict = data.pop("mode_rank_obj") + # stamp_event_data = data.pop("stamp_event_data") + + # save stock data in database + self._save_stock_data(user_id, stock_data) + + # save tickets in database + for ticket in ticket_data: + self.data.item.put_ticket(user_id, ticket) + + # save mode rank data in database + rank_data.update(reward_dist_data) + self.data.profile.put_profile_rank(user_id, self.version, rank_data) + + # save the current story progress in database + max_loop = data.get("chapter_loop_max") + chapter_id = data.get("chapter") + + episode_id = data.get("episode") + difficulty = data.get("difficulty") + play_status = data.get("play_status") + + # get the current loop from the database + story_data = self.data.item.get_story(user_id, chapter_id) + # 1 = active, 2+ = cleared? + loop_count = 1 + if story_data: + loop_count = story_data["loop_count"] + + # if the played difficulty is smaller than loop_count you cannot clear + # (play_status = 2) the episode otherwise the following difficulties + # won't earn any EXP? + if difficulty < loop_count: + play_status = 1 + + # if the episode has already been cleared, set the play_status to 2 + # so it won't be set to unplayed (play_status = 1) + episode_data = self.data.item.get_story_episode(user_id, episode_id) + if episode_data: + if play_status < episode_data["play_status"]: + play_status = 2 + + # save the current episode progress in database + self.data.item.put_story_episode( + user_id, + chapter_id, + { + "episode": episode_id, + "play_status": play_status, + }, + ) + + if loop_count < max_loop and data.get("chapter_clear") == 1: + # increase the loop count + loop_count += 1 + + # for the current chapter set all episode play_status back to 1 + self.data.item.put_story_episode_play_status(user_id, chapter_id, 1) + + self.data.item.put_story( + user_id, + { + "story_type": data.get("story_type"), + "chapter": chapter_id, + "loop_count": loop_count, + }, + ) + + # save the current episode difficulty progress in database + self.data.item.put_story_episode_difficulty( + user_id, + episode_id, + { + "difficulty": difficulty, + "play_count": 1, # no idea where this comes from + "clear_count": 1, # no idea where this comes from + "play_status": data.get("play_status"), + "play_score": data.get("play_score"), + }, + ) + + # get the use_count and story_use_count of the used car + style_car_id = data.get("style_car_id") + car_mileage = data.get("car_mileage") + used_car = self.data.item.get_car(user_id, self.version, style_car_id)._asdict() + + # increase the use_count and story_use_count of the used car + used_car["use_count"] += 1 + used_car["story_use_count"] += 1 + used_car["car_mileage"] = car_mileage + + # save the used car in database + self.data.item.put_car(user_id, self.version, used_car) + + # get the profile data, update total_play and daily_play, and save it + profile = self.data.profile.get_profile(user_id, self.version) + total_play = profile["total_play"] + 1 + + # save user profile in database + self.data.profile.put_profile( + user_id, + self.version, + { + "total_play": total_play, + "last_play_date": datetime.now(), + "mileage": data.pop("mileage"), + "cash": data.pop("cash"), + "total_cash": data.pop("total_cash"), + "dressup_point": data.pop("dressup_point"), + "avatar_point": data.pop("avatar_point"), + "aura_id": data.pop("aura_id"), + "aura_color_id": data.pop("aura_color_id"), + "aura_line_id": data.pop("aura_line_id"), + }, + ) + + return { + "status_code": "0", + "story_data": self._generate_story_data(user_id), + "car_use_count": [], + "maker_use_count": [], + } + + def handle_user_updatespecialmoderesult_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + stock_data: Dict = data.pop("stock_obj") + ticket_data: List = data.pop("ticket_data") + reward_dist_data: Dict = data.pop("reward_dist_obj") + driver_debut_data = data.pop("driver_debut_obj") + rank_data: Dict = data.pop("mode_rank_obj") + + # unused + hint_display_flag: int = data.pop("hint_display_flag") + + # get the vs use count from database and update it + style_car_id = data.pop("style_car_id") + car_data = self.data.item.get_car(user_id, self.version, style_car_id) + vs_use_count = car_data["vs_use_count"] + 1 + + # save car data in database + self.data.item.put_car( + user_id, + self.version, + { + "style_car_id": style_car_id, + "car_mileage": data.pop("car_mileage"), + "vs_use_count": vs_use_count, + }, + ) + + # get the profile data, update total_play and daily_play, and save it + profile = self.data.profile.get_profile(user_id, self.version) + total_play = profile["total_play"] + 1 + + # save user profile in database + self.data.profile.put_profile( + user_id, + self.version, + { + "total_play": total_play, + "last_play_date": datetime.now(), + "mileage": data.pop("mileage"), + "cash": data.pop("cash"), + "total_cash": data.pop("total_cash"), + "dressup_point": data.pop("dressup_point"), + "avatar_point": data.pop("avatar_point"), + "aura_id": data.pop("aura_id"), + "aura_color_id": data.pop("aura_color_id"), + "aura_line_id": data.pop("aura_line_id"), + }, + ) + + # save stock data in database + self._save_stock_data(user_id, stock_data) + + # save ticket data in database + for ticket in ticket_data: + self.data.item.put_ticket(user_id, ticket) + + # save mode_rank and reward_dist data in database + rank_data.update(reward_dist_data) + self.data.profile.put_profile_rank(user_id, self.version, rank_data) + + # finally save the special mode with story_type=4 in database + self.data.item.put_challenge(user_id, data) + + return { + "status_code": "0", + "special_mode_data": self._generate_special_data(user_id), + "car_use_count": [], + "maker_use_count": [], + } + + def handle_user_updatechallengemoderesult_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + stock_data: Dict = data.pop("stock_obj") + ticket_data: List = data.pop("ticket_data") + reward_dist_data: Dict = data.pop("reward_dist_obj") + driver_debut_data = data.pop("driver_debut_obj") + rank_data: Dict = data.pop("mode_rank_obj") + + # get the vs use count from database and update it + style_car_id = data.get("style_car_id") + car_data = self.data.item.get_car(user_id, self.version, style_car_id) + vs_use_count = car_data["vs_use_count"] + 1 + + # save car data in database + self.data.item.put_car( + user_id, + self.version, + { + "style_car_id": style_car_id, + "car_mileage": data.pop("car_mileage"), + "vs_use_count": vs_use_count, + }, + ) + + # get the profile data, update total_play and daily_play, and save it + profile = self.data.profile.get_profile(user_id, self.version) + total_play = profile["total_play"] + 1 + + # save user profile in database + self.data.profile.put_profile( + user_id, + self.version, + { + "total_play": total_play, + "last_play_date": datetime.now(), + "mileage": data.pop("mileage"), + "cash": data.pop("cash"), + "total_cash": data.pop("total_cash"), + "dressup_point": data.pop("dressup_point"), + "avatar_point": data.pop("avatar_point"), + "aura_id": data.pop("aura_id"), + "aura_color_id": data.pop("aura_color_id"), + "aura_line_id": data.pop("aura_line_id"), + }, + ) + + # save stock data in database + self._save_stock_data(user_id, stock_data) + + # save ticket data in database + for ticket in ticket_data: + self.data.item.put_ticket(user_id, ticket) + + # save mode_rank and reward_dist data in database + rank_data.update(reward_dist_data) + self.data.profile.put_profile_rank(user_id, self.version, rank_data) + + # get the challenge mode data from database + challenge_data = self.data.item.get_challenge( + user_id, data.get("vs_type"), data.get("play_difficulty") + ) + + if challenge_data: + # update play count + play_count = challenge_data["play_count"] + 1 + data["play_count"] = play_count + + # finally save the challenge mode with story_type=3 in database + self.data.item.put_challenge(user_id, data) + + return { + "status_code": "0", + "challenge_mode_data": self._generate_challenge_data(user_id), + "car_use_count": [], + "maker_use_count": [], + } + + def handle_user_updatecartune_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + # full tune ticket + use_ticket = data.pop("use_ticket") + if use_ticket: + # get the user's tickets, full tune ticket id is 25 + ticket = self.data.item.get_ticket(user_id, ticket_id=25) + + # update the ticket in the database + self.data.item.put_ticket( + user_id, + { + "ticket_id": ticket["ticket_id"], + "ticket_cnt": ticket["ticket_cnt"] - 1, + }, + ) + + # also set the tune_level to 16 (fully tuned) + data["tune_level"] = 16 + + self.data.item.put_car(user_id, self.version, data) + + return { + "status_code": "0", + "story_data": self._generate_story_data(user_id), + "car_use_count": [], + "maker_use_count": [], + } + + def handle_log_saveplaylog_request(self, data: Dict, headers: Dict): + pass + + def handle_log_saveendlog_request(self, data: Dict, headers: Dict): + pass + + def handle_user_updatemoderesult_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + config_data: Dict = data.pop("config_obj") + stock_data: Dict = data.pop("stock_obj") + ticket_data: List = data.pop("ticket_data") + reward_dist_data: Dict = data.pop("reward_dist_obj") + + # not required? + mode_id = data.pop("mode_id") + standby_play_flag = data.pop("standby_play_flag") + tips_list = data.pop("tips_list") + + # save stock data in database + self._save_stock_data(user_id, stock_data) + + # save tickets in database + for ticket in ticket_data: + self.data.item.put_ticket(user_id, ticket) + + # save rank dist data in database + self.data.profile.put_profile_rank(user_id, self.version, reward_dist_data) + + # update profile data and config in database + self.data.profile.put_profile(user_id, self.version, data) + config_data["config_id"] = config_data.pop("id") + self.data.profile.put_profile_config(user_id, config_data) + + return {"status_code": "0", "server_status": 1} + + def _generate_theory_rival_data( + self, user_list: list, course_id: int, req_user_id: int + ) -> list: + rival_data = [] + for user_id in user_list: + # if not enough players are available just use the data from the req_user + if user_id == -1: + profile = self.data.profile.get_profile(req_user_id, self.version) + profile = profile._asdict() + # set the name to CPU + profile["username"] = f"CPU" + # also reset stamps to default + profile["stamp_key_assign_0"] = 0 + profile["stamp_key_assign_1"] = 1 + profile["stamp_key_assign_2"] = 2 + profile["stamp_key_assign_3"] = 3 + profile["mytitle_id"] = 0 + else: + profile = self.data.profile.get_profile(user_id, self.version) + + rank = self.data.profile.get_profile_rank(profile["user"], self.version) + + avatars = [ + { + "sex": 0, + "face": 1, + "eye": 1, + "mouth": 1, + "hair": 1, + "glasses": 0, + "face_accessory": 0, + "body": 1, + "body_accessory": 0, + "behind": 0, + "bg": 1, + "effect": 0, + "special": 0, + }, + { + "sex": 0, + "face": 1, + "eye": 1, + "mouth": 1, + "hair": 19, + "glasses": 0, + "face_accessory": 0, + "body": 2, + "body_accessory": 0, + "behind": 0, + "bg": 1, + "effect": 0, + "special": 0, + }, + { + "sex": 1, + "face": 91, + "eye": 265, + "mouth": 13, + "hair": 369, + "glasses": 0, + "face_accessory": 0, + "body": 113, + "body_accessory": 0, + "behind": 0, + "bg": 1, + "effect": 0, + "special": 0, + }, + { + "sex": 1, + "face": 91, + "eye": 265, + "mouth": 13, + "hair": 387, + "glasses": 0, + "face_accessory": 0, + "body": 114, + "body_accessory": 0, + "behind": 0, + "bg": 1, + "effect": 0, + "special": 0, + }, + ] + + if user_id == -1: + # get a random avatar from the list and some random car from all users + avatar = choice(avatars) + car = self.data.item.get_random_car(self.version) + else: + avatar = self.data.profile.get_profile_avatar(profile["user"]) + car = self.data.item.get_random_user_car(profile["user"], self.version) + + parts_list = [] + for part in car["parts_list"]: + parts_list.append(part["parts"]) + + course = self.data.item.get_theory_course(profile["user"], course_id) + powerhose_lv = 0 + if course: + powerhose_lv = course["powerhouse_lv"] + + theory_running = self.data.item.get_theory_running_by_course( + profile["user"], course_id + ) + + # normally it's 127 after the first play so we set it to 128 + attack = 128 + defense = 128 + safety = 128 + runaway = 128 + trick_flag = 0 + if theory_running and user_id != -1: + attack = theory_running["attack"] + defense = theory_running["defense"] + safety = theory_running["safety"] + runaway = theory_running["runaway"] + trick_flag = theory_running["trick_flag"] + + # get the time trial ranking medal + eval_id = 0 + time_trial = self.data.item.get_time_trial_best_ranking_by_course( + self.version, profile["user"], course_id + ) + if time_trial: + eval_id = time_trial["eval_id"] + + rival_data.append( + { + "id": profile["user"], + "name": profile["username"], + "grade": rank["grade"], + # only needed for power match + "powerhouseLv": powerhose_lv, + "mytitleId": profile["mytitle_id"], + "country": 9, + "auraId": profile["aura_id"], + "auraColor": profile["aura_color_id"], + "auraLine": profile["aura_line_id"], + # not sure? + "roundRanking": 0, + "storeName": self.core_cfg.server.name, + "sex": avatar["sex"], + "face": avatar["face"], + "eye": avatar["eye"], + "mouth": avatar["mouth"], + "hair": avatar["hair"], + "glasses": avatar["glasses"], + "faceAccessory": avatar["face_accessory"], + "body": avatar["body"], + "bodyAccessory": avatar["body_accessory"], + "behind": avatar["behind"], + "bg": avatar["bg"], + "effect": avatar["effect"], + "special": avatar["special"], + "styleCarId": car["style_car_id"], + "color": car["color"], + "bureau": car["bureau"], + "kana": car["kana"], + "sNo": car["s_no"], + "lNo": car["l_no"], + "tuneLv": car["tune_level"], + "carFlag": car["car_flag"], + "tunePoint": car["tune_point"], + "infinityTune": car["infinity_tune"], + "tuneParts": car["tune_parts"], + "partsList": parts_list, + "partsCount": car["equip_parts_count"], + "stamp0": profile["stamp_key_assign_0"], + "stamp1": profile["stamp_key_assign_1"], + "stamp2": profile["stamp_key_assign_2"], + "stamp3": profile["stamp_key_assign_3"], + "attack": attack, + "defense": defense, + "safety": safety, + "runaway": runaway, + "trickFlg": trick_flag, + # time trial ranking medal + "taEval": eval_id, + } + ) + + return rival_data + + def handle_theory_matching_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + course_id = data.pop("course_id") + # no idea why thats needed? + grade = data.pop("grade") + + # number of auto_matches and power_matches, official values are: + count_auto_match = 9 + count_power_match = 3 + + # required for the power_match list? + powerhose_lv = data.pop("powerhouse_lv") + + # get random profiles for auto match + profiles = self.data.profile.get_different_random_profiles( + user_id, self.version, count=count_auto_match + ) + + user_list = [profile["user"] for profile in profiles] + # if user_list is not count_auto_match long, fill it up with -1 + while len(user_list) < count_auto_match: + user_list.append(-1) + + auto_match = self._generate_theory_rival_data(user_list, course_id, user_id) + + # get profiles with the same powerhouse_lv for power match + theory_courses = self.data.item.get_theory_course_by_powerhouse_lv( + user_id, course_id, powerhose_lv, count=count_power_match + ) + user_list = [course["user"] for course in theory_courses] + + # if user_list is not count_power_match long, fill it up with -1 + while len(user_list) < count_power_match: + user_list.append(-1) + + power_match = self._generate_theory_rival_data(user_list, course_id, user_id) + + return { + "status_code": "0", + "server_status": 1, + "rival_data": { + "auto_match": auto_match, + "power_match": power_match, + }, + } + + def handle_user_updatetheoryresult_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + stock_data: Dict = data.pop("stock_obj") + ticket_data: List = data.pop("ticket_data") + reward_dist_data: Dict = data.pop("reward_dist_obj") + rank_data: Dict = data.pop("mode_rank_obj") + driver_debut_data: Dict = data.pop("driver_debut_obj") + + # save stock data in database + self._save_stock_data(user_id, stock_data) + + # save tickets in database + for ticket in ticket_data: + self.data.item.put_ticket(user_id, ticket) + + # save rank dist data in database + rank_data.update(reward_dist_data) + self.data.profile.put_profile_rank(user_id, self.version, rank_data) + + # save the profile theory data in database + play_count = 1 + play_count_multi = 1 + win_count = 0 + win_count_multi = 0 + + theory_data = self.data.profile.get_profile_theory(user_id, self.version) + if theory_data: + play_count = theory_data["play_count"] + 1 + play_count_multi = theory_data["play_count_multi"] + 1 + win_count = theory_data["win_count"] + win_count_multi = theory_data["win_count_multi"] + + # check all advantages and see if one of them is larger than 0 + # if so, we won + if ( + data.get("advantage_1") > 0 + or data.get("advantage_2") > 0 + or data.get("advantage_3") > 0 + or data.get("advantage_4") > 0 + ): + win_count += 1 + win_count_multi += 1 + + self.data.profile.put_profile_theory( + user_id, + self.version, + { + "play_count": play_count, + "play_count_multi": play_count_multi, + "partner_id": data.get("partner_id"), + "partner_progress": data.get("partner_progress"), + "partner_progress_score": data.get("partner_progress_score"), + "practice_start_rank": data.get("practice_start_rank"), + "general_flag": data.get("general_flag"), + "vs_history": data.get("vs_history"), + # no idea? + "vs_history_multi": data.get("vs_history"), + "win_count": win_count, + "win_count_multi": win_count_multi, + }, + ) + + # save theory course in database + self.data.item.put_theory_course( + user_id, + { + "course_id": data.get("course_id"), + "max_victory_grade": data.get("max_victory_grade"), + # always add 1? + "run_count": 1, + "powerhouse_lv": data.get("powerhouse_lv"), + "powerhouse_exp": data.get("powerhouse_exp"), + # not sure if the played_powerhouse_lv is the same as powerhouse_lv + "played_powerhouse_lv": data.get("powerhouse_lv"), + }, + ) + + # save the theory partner in database + self.data.item.put_theory_partner( + user_id, + { + "partner_id": data.get("partner_id"), + "fellowship_lv": data.get("fellowship_lv"), + "fellowship_exp": data.get("fellowship_exp"), + }, + ) + + # save the theory running in database? + self.data.item.put_theory_running( + user_id, + { + "course_id": data.get("course_id"), + "attack": data.get("attack"), + "defense": data.get("defense"), + "safety": data.get("safety"), + "runaway": data.get("runaway"), + "trick_flag": data.get("trick_flag"), + }, + ) + + # get the use_count and theory_use_count of the used car + style_car_id = data.get("style_car_id") + car_mileage = data.get("car_mileage") + used_car = self.data.item.get_car(user_id, self.version, style_car_id)._asdict() + + # increase the use_count and theory_use_count of the used car + used_car["use_count"] += 1 + used_car["theory_use_count"] += 1 + used_car["car_mileage"] = car_mileage + + # save the used car in database + self.data.item.put_car(user_id, self.version, used_car) + + # get the profile data, update total_play and daily_play, and save it + profile = self.data.profile.get_profile(user_id, self.version) + total_play = profile["total_play"] + 1 + + # save the profile in database + self.data.profile.put_profile( + user_id, + self.version, + { + "total_play": total_play, + "last_play_date": datetime.now(), + "mileage": data.get("mileage"), + "aura_id": data.get("aura_id"), + "aura_color_id": data.get("aura_color_id"), + "aura_line_id": data.get("aura_line_id"), + "cash": data.get("cash"), + "total_cash": data.get("total_cash"), + "dressup_point": data.get("dressup_point"), + "avatar_point": data.get("avatar_point"), + }, + ) + + return { + "status_code": "0", + "played_powerhouse_lv": data.get("powerhouse_lv"), + "car_use_count": [], + "maker_use_count": [], + "play_count": play_count, + "play_count_multi": play_count_multi, + "win_count": win_count, + "win_count_multi": win_count_multi, + } + + def handle_user_updatestorebattleresult_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + stock_data: Dict = data.pop("stock_obj") + ticket_data: List = data.pop("ticket_data") + reward_dist_data: Dict = data.pop("reward_dist_obj") + rank_data: Dict = data.pop("mode_rank_obj") + driver_debut_data: Dict = data.pop("driver_debut_obj") + + # no idea? + result = data.pop("result") + battle_gift_event_id = data.pop("battle_gift_event_id") + gift_id = data.pop("gift_id") + + # save stock data in database + self._save_stock_data(user_id, stock_data) + + # save tickets in database + for ticket in ticket_data: + self.data.item.put_ticket(user_id, ticket) + + # save rank dist data in database + rank_data.update(reward_dist_data) + self.data.profile.put_profile_rank(user_id, self.version, rank_data) + + # get the use_count and net_vs_use_count of the used car + style_car_id = data.get("style_car_id") + car_mileage = data.pop("car_mileage") + used_car = self.data.item.get_car(user_id, self.version, style_car_id)._asdict() + + # increase the use_count and net_vs_use_count of the used car + used_car["use_count"] += 1 + used_car["net_vs_use_count"] += 1 + used_car["car_mileage"] = car_mileage + + # save the used car in database + self.data.item.put_car(user_id, self.version, used_car) + + # get the profile data, update total_play and daily_play, and save it + profile = self.data.profile.get_profile(user_id, self.version) + total_play = profile["total_play"] + 1 + + # save the profile in database + self.data.profile.put_profile( + user_id, + self.version, + { + "total_play": total_play, + "last_play_date": datetime.now(), + "mileage": data.pop("mileage"), + "aura_id": data.pop("aura_id"), + "aura_color_id": data.pop("aura_color_id"), + "aura_line_id": data.pop("aura_line_id"), + "cash": data.pop("cash"), + "total_cash": data.pop("total_cash"), + "dressup_point": data.pop("dressup_point"), + "avatar_point": data.pop("avatar_point"), + }, + ) + + # save vs_info in database + self.data.item.put_vs_info(user_id, data) + + vs_info = { + "battle_mode": 0, + "vs_cnt": 1, + "vs_win": data.get("win_flg"), + "invalid": 0, + "str": 0, + "str_now": 0, + "lose_now": 0, + "vs_history": data.get("vs_history"), + "course_select_priority": 0, + "vsinfo_course_data": [ + { + "course_id": data.get("course_id"), + "vs_cnt": 1, + "vs_win": data.get("win_flg"), + } + ], + } + + return { + "status_code": "0", + "vsinfo_data": vs_info, + "car_use_count": [], + "maker_use_count": [], + } From 7033234b23a268b7f70284beae018ac1149f4cf9 Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Sun, 1 Oct 2023 21:41:08 +0200 Subject: [PATCH 02/18] IDAC: Added better doc, fixed timetrial event --- docs/game_specific_info.md | 42 ++++++++++++++++++ .../data/stamps/touhou_flandre_scarlet.json | Bin 10735 -> 10737 bytes .../data/stamps/touhou_remilia_scarlet.json | Bin 10669 -> 10695 bytes .../data/stamps/touhou_sakuya_izayoi.json | Bin 10622 -> 10684 bytes titles/idac/season2.py | 6 ++- 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/docs/game_specific_info.md b/docs/game_specific_info.md index 2baa12c..20d4a23 100644 --- a/docs/game_specific_info.md +++ b/docs/game_specific_info.md @@ -597,6 +597,48 @@ python dbutils.py --game SDGT upgrade 34. Full Tune Ticket Fragment 35. Underneon Lights +### TimeRelease Chapter: + +1. Story: 1, 2, 3, 4, 5, 6, 7, 8, 9, 19 (Chapter 10), (29 Chapter 11?) +2. MF Ghost: 10, 11, 12, 13, 14, 15 +3. Bunta: 15, 16, 17, 18, 19, 20, (21, 21, 22?) +4. Special Event: 23, 24, 25, 26, 27, 28 (Touhou Project) + +### TimeRelease Courses: + + +| Course ID | Course Name | Direction | +| --------- | ------------------------- | ------------------------ | +| 0 | Akina Lake(秋名湖) | CounterClockwise(左周り) | +| 2 | Akina Lake(秋名湖) | Clockwise(右周り) | +| 52 | Hakone(箱根) | Downhill(下り) | +| 54 | Hakone(箱根) | Hillclimb(上り) | +| 36 | Usui(碓氷) | CounterClockwise(左周り) | +| 38 | Usui(碓氷) | Clockwise(右周り) | +| 4 | Myogi(妙義) | Downhill(下り) | +| 6 | Myogi(妙義) | Hillclimb(上り) | +| 8 | Akagi(赤城) | Downhill(下り) | +| 10 | Akagi(赤城) | Hillclimb(上り) | +| 12 | Akina(秋名) | Downhill(下り) | +| 14 | Akina(秋名) | Hillclimb(上り) | +| 16 | Irohazaka(いろは坂) | Downhill(下り) | +| 18 | Irohazaka(いろは坂) | Reverse(逆走) | +| 56 | Momiji Line(もみじライン) | Downhill(下り) | +| 58 | Momiji Line(もみじライン) | Hillclimb(上り) | +| 20 | Tsukuba(筑波) | Outbound(往路) | +| 22 | Tsukuba(筑波) | Inbound(復路) | +| 24 | Happogahara(八方ヶ原) | Outbound(往路) | +| 26 | Happogahara(八方ヶ原) | Inbound(復路) | +| 40 | Sadamine(定峰) | Downhill(下り) | +| 42 | Sadamine(定峰) | Hillclimb(上り) | +| 44 | Tsuchisaka(土坂) | Outbound(往路) | +| 46 | Tsuchisaka(土坂) | Inbound(復路) | +| 48 | Akina Snow(秋名雪) | Downhill(下り) | +| 50 | Akina Snow(秋名雪) | Hillclimb(上り) | +| 68 | Odawara(小田原) | Forward(順走) | +| 70 | Odawara(小田原) | Reverse(逆走) | + ### Credits +- Kinako: For helping with the timeRelease unlocking of courses and special mode A huge thanks to all people who helped shaping this project to what it is now and don't want to be mentioned here. diff --git a/titles/idac/data/stamps/touhou_flandre_scarlet.json b/titles/idac/data/stamps/touhou_flandre_scarlet.json index 31638e1c8ecf2d6e1c31b307b4c3193d28e203db..23d2a7d61f0b163210d92b70b806df91199addc0 100644 GIT binary patch delta 23 ecmaDK{4sdKMjj<210!QyLjzp{L#2(oO*8>(6bHlr delta 21 ccmewu{62WXMlM4$GjnrGb3-%BjeAWr0br8{xBvhE diff --git a/titles/idac/data/stamps/touhou_remilia_scarlet.json b/titles/idac/data/stamps/touhou_remilia_scarlet.json index 82eeff481d160bea35ce9a09d96d04112d6b028c..3d917a9201e693a63746cef62ec21c03ea3f7d55 100644 GIT binary patch delta 64 zcmV-G0KfmOQ^!+~sth7BFfubOF)%GKF(R?FC;4Uf9fQ^%(4^OlGC9nf-JRZ;h delta 37 tcmX>eyf%2kDlS7aGjnrGb3-%BjoUOB8O=A}XS}F9*+AHTv$)y@W&rt{43Pi; diff --git a/titles/idac/data/stamps/touhou_sakuya_izayoi.json b/titles/idac/data/stamps/touhou_sakuya_izayoi.json index 029358c702d4bdd867c74bedf4b153d033dc1543..7b98fb31486110eed551a2f2e07b631baec3516b 100644 GIT binary patch delta 35 rcmewtv?qAN3?3yT10!QyLjzp{L#2(2-l Date: Sun, 1 Oct 2023 22:17:06 +0200 Subject: [PATCH 03/18] IDAC: Fixed time trial events config, added new events --- titles/idac/config.py | 2 +- .../timetrial/touhou_flandre_scarlet.json | Bin 0 -> 1189 bytes .../timetrial/touhou_remilia_scarlet.json | Bin 1131 -> 1183 bytes .../data/timetrial/touhou_sakuya_izayoi.json | Bin 0 -> 1165 bytes 4 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 titles/idac/data/timetrial/touhou_flandre_scarlet.json create mode 100644 titles/idac/data/timetrial/touhou_sakuya_izayoi.json diff --git a/titles/idac/config.py b/titles/idac/config.py index e685e2e..2f97219 100644 --- a/titles/idac/config.py +++ b/titles/idac/config.py @@ -109,7 +109,7 @@ class IDACTimetrialConfig: self.__config, "idac", "timetrial", - "enabled_stamps", + "enabled_timetrial", default="touhou_remilia_scarlet", ) diff --git a/titles/idac/data/timetrial/touhou_flandre_scarlet.json b/titles/idac/data/timetrial/touhou_flandre_scarlet.json new file mode 100644 index 0000000000000000000000000000000000000000..314881aa584a8266de554ffc54ea2c4f79549fda GIT binary patch literal 1189 zcmb_bOK!s;6x`<&5$ifOBzBWrC8{iH)08T~7ACEtD4Vcp570wY?XIh;y$u&B_=Azs zR746ZM#Ib--hs231)O$4WSm6AuoL`rioAI4V=$?%$J2$XzP@=eK4C0~^MQSx2M zZ*}-m2ffkoLrJORGiYTSzA~zNAkzLBws Rss2P?V`fWTgN@BEm;tH-6(0Zq delta 17 ZcmbQw`I=)w=)_KKW@BB$joV)^0{}b)2CV=9 diff --git a/titles/idac/data/timetrial/touhou_sakuya_izayoi.json b/titles/idac/data/timetrial/touhou_sakuya_izayoi.json new file mode 100644 index 0000000000000000000000000000000000000000..9cf05850515d83b6ac5346c0350d2089a32bef0b GIT binary patch literal 1165 zcmb_ay-ve07~K05Rc6xICaKcC3PO=dOfhPm$oUGYstyc{EX<6oEWA_R13N#?C($4y zHACdn`OfG2e4NeA7l7Oe(2{R6@gx*vvIy4mi8Yi(nX4f)8k!PMhT%#HQ4Tj2jz9$1&nfaHvGPAx_itJDkm( yu|b{va%p*&@ie+k1UC<2!p#g;P13izoN%oK7_AI;S+bZ1V02%}zg)$N5qK literal 0 HcmV?d00001 From ee5f13a3bb7e93618217e7334ba3027e706d49c2 Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Sun, 1 Oct 2023 22:29:50 +0200 Subject: [PATCH 04/18] IDAC: Added changelog, fixed doc --- changelog.md | 12 ++++++++++++ docs/game_specific_info.md | 27 ++++++++++++++------------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/changelog.md b/changelog.md index 40d2e48..e1ecbb9 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,18 @@ # Changelog Documenting updates to ARTEMiS, to be updated every time the master branch is pushed to. +## 20231001 +### Initial D THE ARCADE ++ Added support for Initial D THE ARCADE S2 + + Story mode progress added + + Bunta Challenge/Touhou Project modes added + + Time Trials added + + Leaderboards added, but doesn't refresh sometimes + + Theory of Street mode added (with CPUs) + + Play Stamp/Timetrial events added + + Frontend to download profile added + + Importer to import profiles added + ## 20230716 ### General + Docker files added (#19) diff --git a/docs/game_specific_info.md b/docs/game_specific_info.md index 20d4a23..c328ce2 100644 --- a/docs/game_specific_info.md +++ b/docs/game_specific_info.md @@ -6,6 +6,12 @@ the corresponding importer and database upgrades. **Important: The described database upgrades are only required if you are using an old database schema, f.e. still using the megaime database. Clean installations always create the latest database structure!** +To upgrade the core database and the database for every game, execute: + +```shell +python dbutils.py autoupgrade +``` + # Table of content - [Supported Games](#supported-games) @@ -62,9 +68,7 @@ The importer for Chunithm will import: Events, Music, Charge Items and Avatar Ac ### Database upgrade -Always make sure your database (tables) are up-to-date, to do so go to the `core/data/schema/versions` folder and see -which version is the latest, f.e. `SDBT_4_upgrade.sql`. In order to upgrade to version 4 in this case you need to -perform all previous updates as well: +Always make sure your database (tables) are up-to-date: ```shell python dbutils.py --game SDBT upgrade @@ -175,11 +179,12 @@ The importer for maimai Pre-DX will import Events and Music. Not all games will ### Database upgrade -Always make sure your database (tables) are up-to-date, to do so go to the `core/data/schema/versions` folder and see which version is the latest, f.e. `SDEZ_2_upgrade.sql`. In order to upgrade to version 2 in this case you need to perform all previous updates as well: +Always make sure your database (tables) are up-to-date: ```shell python dbutils.py --game SDEZ upgrade ``` + Pre-Dx uses the same database as DX, so only upgrade using the SDEZ game code! ## Hatsune Miku Project Diva @@ -215,9 +220,7 @@ Config file is located in `config/diva.yaml`. ### Database upgrade -Always make sure your database (tables) are up-to-date, to do so go to the `core/data/schema/versions` folder and see -which version is the latest, f.e. `SBZV_4_upgrade.sql`. In order to upgrade to version 4 in this case you need to -perform all previous updates as well: +Always make sure your database (tables) are up-to-date: ```shell python dbutils.py --game SBZV upgrade @@ -263,9 +266,7 @@ Note: 1149 and higher are only for Card Maker 1.35 and higher and will be ignore ### Database upgrade -Always make sure your database (tables) are up-to-date, to do so go to the `core/data/schema/versions` folder and see -which version is the latest, f.e. `SDDT_4_upgrade.sql`. In order to upgrade to version 4 in this case you need to -perform all previous updates as well: +Always make sure your database (tables) are up-to-date: ```shell python dbutils.py --game SDDT upgrade @@ -424,7 +425,7 @@ Config file is located in `config/wacca.yaml`. ### Database upgrade -Always make sure your database (tables) are up-to-date, to do so go to the `core/data/schema/versions` folder and see which version is the latest, f.e. `SDFE_3_upgrade.sql`. In order to upgrade to version 3 in this case you need to perform all previous updates as well: +Always make sure your database (tables) are up-to-date: ```shell python dbutils.py --game SDFE upgrade @@ -497,7 +498,7 @@ Config file is located in `config/sao.yaml`. ### Database upgrade -Always make sure your database (tables) are up-to-date, to do so go to the `core/data/schema/versions` folder and see which version is the latest, f.e. `SDEW_1_upgrade.sql`. In order to upgrade to version 3 in this case you need to perform all previous updates as well: +Always make sure your database (tables) are up-to-date: ```shell python dbutils.py --game SDEW upgrade @@ -558,7 +559,7 @@ Config file is located in `config/idac.yaml`. ### Database upgrade -Always make sure your database (tables) are up-to-date +Always make sure your database (tables) are up-to-date: ```shell python dbutils.py --game SDGT upgrade From 0e664e03f979e73c80e927925894ff4275ce2d2f Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Tue, 3 Oct 2023 16:50:52 +0200 Subject: [PATCH 05/18] IDAC: Updated docs, added TA Data Known issue: after selecting Season 1, the TA Data for Season 2 will not be shown --- docs/INSTALL_WINDOWS.md | 51 ++++++++++----- docs/game_specific_info.md | 54 ++++++++-------- example_config/idac.yaml | 2 +- titles/idac/season2.py | 124 ++++++++++++++++++++++++++++--------- 4 files changed, 158 insertions(+), 73 deletions(-) diff --git a/docs/INSTALL_WINDOWS.md b/docs/INSTALL_WINDOWS.md index e88def3..b976b26 100644 --- a/docs/INSTALL_WINDOWS.md +++ b/docs/INSTALL_WINDOWS.md @@ -10,11 +10,11 @@ This step-by-step guide assumes that you are using a fresh install of Windows 10 3. Make sure that you enable "Create shortcuts for installed applications" and "Add Python to environment variables" and hit Install ## Install MySQL 8.0 -1. Download MySQL 8.0 Server : [Link](https://cdn.mysql.com//Downloads/MySQLInstaller/mysql-installer-web-community-8.0.31.0.msi) -2. Install mysql-installer-web-community-8.0.31.0.msi +1. Download MySQL 8.0 Server : [Link](https://dev.mysql.com/get/Downloads/MySQLInstaller/mysql-installer-community-8.0.34.0.msi) +2. Install mysql-installer-web-community-8.0.34.0.msi 1. Click on "Add ..." on the side 2. Click on the "+" next to MySQL Servers - 3. Make sure MySQL Server 8.0.29 - X64 is under the products to be installed. + 3. Make sure MySQL Server 8.0.34 - X64 is under the products to be installed. 4. Hit Next and Next once installed 5. Select the configuration type "Development Computer" 6. Hit Next @@ -23,9 +23,10 @@ This step-by-step guide assumes that you are using a fresh install of Windows 10 9. Leave everything under Windows Service as default and hit Next > 10. Click on Execute and for it to finish and hit Next> and then Finish 3. Open MySQL 8.0 Command Line Client and login as your root user -4. Type those commands to create your user and the database -``` -CREATE USER 'aime'@'localhost' IDENTIFIED BY 'MyStrongPass.'; +4. Change `` to a new password for the user aime, type those commands to create your user and the database + +```sql +CREATE USER 'aime'@'localhost' IDENTIFIED BY ''; CREATE DATABASE aime; GRANT Alter,Create,Delete,Drop,Index,Insert,References,Select,Update ON aime.* TO 'aime'@'localhost'; FLUSH PRIVILEGES; @@ -34,33 +35,50 @@ exit; ## Install Python modules 1. Change your work path to the artemis-master folder using 'cd' and install the requirements: -> pip install -r requirements.txt -## Copy/Rename the folder example_config to config +```shell +pip install -r requirements.txt +``` -## Adjust /config/core.yaml +## Copy/Rename the folder `example_config` to `config` -1. Make sure to change the server listen_address to be set to your local machine IP (ex.: 192.168.1.xxx) +## Adjust `config/core.yaml` + +1. Make sure to change the server `hostname` to be set to your local machine IP (ex.: 192.168.xxx.xxx) - In case you want to run this only locally, set the following values: -``` + +```yaml server: listen_address: 0.0.0.0 title: - hostname: localhost + hostname: 192.168.xxx.xxx +``` + +1. Adjust the proper MySQL information you created earlier +```yaml +database: + host: "localhost" + username: "aime" + password: "" + name: "aime" ``` -2. Adjust the proper MySQL information you created earlier 3. Add the AimeDB key at the bottom of the file 4. If the webui is needed, change the flag from False to True ## Create the database tables for ARTEMiS -> python dbutils.py create + +```shell +python dbutils.py create +``` ## Firewall Adjustements Make sure the following ports are open both on your router and local Windows firewall in case you want to use this for public use (NOT recommended): > Port 80 (TCP), 443 (TCP), 8443 (TCP), 22345 (TCP), 8080 (TCP), 8090 (TCP) **webui, 8444 (TCP) **mucha ## Running the ARTEMiS instance -> python index.py +```shell +python index.py +``` # Troubleshooting @@ -78,6 +96,7 @@ Make sure the following ports are open both on your router and local Windows fir ## AttributeError: module 'collections' has no attribute 'Hashable' 1. This means the pyYAML module is obsolete, simply rerun pip with the -U (force update) flag, as shown below. - Change your work path to the artemis-master (or artemis-develop) folder using 'cd' and run the following commands: -``` + +```shell pip install -r requirements.txt -U ``` diff --git a/docs/game_specific_info.md b/docs/game_specific_info.md index c328ce2..615f10b 100644 --- a/docs/game_specific_info.md +++ b/docs/game_specific_info.md @@ -571,32 +571,34 @@ python dbutils.py --game SDGT upgrade ### Item categories -1. D Coin -3. Car Dressup Token -5. Avatar Dressup Token -6. Tachometer -7. Aura -8. Aura Color -9. Avatar Face -10. Avatar Eye -11. Avatar Mouth -12. Avatar Hair -13. Avatar Glasses -14. Avatar Face accessories -15. Avatar Body -18. Avatar Background -21. Chat Stamp -22. Keychain -24. Title -25. Full Tune Ticket -26. Paper Cup -27. BGM -28. Drifting Text -31. Start Menu BG -32. Car Color/Paint -33. Aura Level? -34. Full Tune Ticket Fragment -35. Underneon Lights +| Category ID | Category Name | +| ----------- | ------------------------ | +| 1 | D Coin | +| 3 | Car Dressup Token | +| 5 | Avatar Dressup Token | +| 6 | Tachometer | +| 7 | Aura | +| 8 | Aura Color | +| 9 | Avatar Face | +| 10 | Avatar Eye | +| 11 | Avatar Mouth | +| 12 | Avatar Hair | +| 13 | Avatar Glasses | +| 14 | Avatar Face accessories | +| 15 | Avatar Body | +| 18 | Avatar Background | +| 21 | Chat Stamp | +| 22 | Keychain | +| 24 | Title | +| 25 | FullTune Ticket | +| 26 | Paper Cup | +| 27 | BGM | +| 28 | Drifting Text | +| 31 | Start Menu BG | +| 32 | Car Color/Paint | +| 33 | Aura Level | +| 34 | FullTune Ticket Fragment | +| 35 | Underneon Lights | ### TimeRelease Chapter: diff --git a/example_config/idac.yaml b/example_config/idac.yaml index 04ea1e0..331ae82 100644 --- a/example_config/idac.yaml +++ b/example_config/idac.yaml @@ -1,6 +1,6 @@ server: enabled: True - loglevel: "debug" + loglevel: "info" ssl: False ssl_key: "cert/idac.key" ssl_cert: "cert/idac.crt" diff --git a/titles/idac/season2.py b/titles/idac/season2.py index 3142d49..5717978 100644 --- a/titles/idac/season2.py +++ b/titles/idac/season2.py @@ -75,32 +75,32 @@ class IDACSeason2(IDACBase): def handle_boot_getconfigdata_request(self, data: Dict, headers: Dict): """ category: - 1 = D Coin - 3 = Car Dressup Token - 5 = Avatar Dressup Token - 6 = Tachometer - 7 = Aura - 8 = Aura Color - 9 = Avatar Face - 10 = Avatar Eye - 11 = Avatar Mouth - 12 = Avatar Hair - 13 = Avatar Glasses - 14 = Avatar Face accessories - 15 = Avatar Body - 18 = Avatar Background - 21 = Chat Stamp - 22 = Keychain - 24 = Title - 25 = Full Tune Ticket - 26 = Paper Cup - 27 = BGM - 28 = Drifting Text - 31 = Start Menu BG - 32 = Car Color/Paint - 33 = Aura Level? - 34 = Full Tune Ticket Fragment - 35 = Underneon Lights + 1 = D Coin + 3 = Car Dressup Token + 5 = Avatar Dressup Token + 6 = Tachometer + 7 = Aura + 8 = Aura Color + 9 = Avatar Face + 10 = Avatar Eye + 11 = Avatar Mouth + 12 = Avatar Hair + 13 = Avatar Glasses + 14 = Avatar Face accessories + 15 = Avatar Body + 18 = Avatar Background + 21 = Chat Stamp + 22 = Keychain + 24 = Title + 25 = FullTune Ticket + 26 = Paper Cup + 27 = BGM + 28 = Drifting Text + 31 = Start Menu BG + 32 = Car Color/Paint + 33 = Aura Level + 34 = FullTune Ticket Fragment + 35 = Underneon Lights """ version = headers["device_version"] ver_str = version.replace(".", "")[:3] @@ -146,9 +146,9 @@ class IDACSeason2(IDACBase): "round_event_exp": [], "stamp_info": self.stamp_info, # 0 = use default data, 1+ = server version of timereleasedata response - "timerelease_no": 5, + "timerelease_no": 1, # 0 = use default data, 1+ = server version of gachadata response - "timerelease_avatar_gacha_no": 5, + "timerelease_avatar_gacha_no": 1, "takeover_reward": [], "subcard_judge": [ { @@ -316,7 +316,7 @@ class IDACSeason2(IDACBase): # get the country id from the profile, 9 is JPN "country": 9, "style_car_id": rank["style_car_id"], - # convert the dateimt to a timestamp + # convert the datetime to a timestamp "play_dt": int(rank["play_dt"].timestamp()), "section_time_1": rank["section_time_1"], "section_time_2": rank["section_time_2"], @@ -341,7 +341,6 @@ class IDACSeason2(IDACBase): } def handle_login_checklock_request(self, data: Dict, headers: Dict): - access_code = data["accesscode"] user_id = data["id"] # check if an IDAC profile already exists @@ -1576,6 +1575,71 @@ class IDACSeason2(IDACBase): "maker_use_count": [], } + def _generate_time_trial_data(self, season_id: int, user_id: int) -> List[Dict]: + # get the season time trial data from database + timetrial_data = [] + + courses = self.data.item.get_courses(user_id) + if courses is None or len(courses) == 0: + return {"status_code": "0", "timetrial_data": timetrial_data} + + for course in courses: + # grab the course id and course proeficiency + course_id = course["course_id"] + skill_level_exp = course["skill_level_exp"] + + # get the best time for the current course for the current user + best_trial = self.data.item.get_time_trial_best_ranking_by_course(season_id, user_id, course_id) + if not best_trial: + continue + + goal_time = best_trial["goal_time"] + # get the rank for the current course + course_rank = self.data.item.get_time_trial_ranking_by_course( + season_id, course_id, limit=None + ) + course_rank = len([r for r in course_rank if r["goal_time"] < goal_time]) + 1 + + timetrial_data.append( + { + "style_car_id": best_trial["style_car_id"], + "course_id": course_id, + "skill_level_exp": skill_level_exp, + "goal_time": goal_time, + "rank": course_rank, + "rank_dt": int(best_trial["play_dt"].timestamp()), + }) + + return timetrial_data + + def handle_user_getpastseasontadata_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + season_id = data.get("season_id") + + # so to get the season 1 data just subtract 1 from the season id + past_timetrial_data = self._generate_time_trial_data(season_id - 1, user_id) + + # TODO: get the current season timetrial data somehow, because after requesting + # GetPastSeasonTAData the game will NOT request GetTAData?! + return { + "status_code": "0", + "season_id": season_id, + "past_season_timetrial_data": past_timetrial_data, + } + + def handle_user_gettadata_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + timetrial_data = self._generate_time_trial_data(self.version, user_id) + + # TODO: get the past season timetrial data somehow, because after requesting + # GetTAData the game will NOT request GetPastSeasonTAData?! + return { + "status_code": "0", + "timetrial_data": timetrial_data, + # "past_season_timetrial_data": timetrial_data, + } + def handle_user_updatecartune_request(self, data: Dict, headers: Dict): user_id = headers["session"] From 8ccb7f08f24ca3a684f8c52d1c4123f4b695b124 Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Tue, 3 Oct 2023 17:00:59 +0200 Subject: [PATCH 06/18] IDAC: Fixed frontend `user_id` not found --- titles/idac/frontend.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/titles/idac/frontend.py b/titles/idac/frontend.py index 32b1467..78abae8 100644 --- a/titles/idac/frontend.py +++ b/titles/idac/frontend.py @@ -94,14 +94,16 @@ class IDACFrontend(FE_Base): ) sesh: Session = request.getSession() usr_sesh = IUserSession(sesh) + user_id = usr_sesh.userId + # user_id = usr_sesh.user_id # profile export if uri.startswith("/game/idac/export"): - if usr_sesh.user_id == 0: + if user_id == 0: return redirectTo(b"/game/idac", request) # set the file name, content type and size to download the json - content = self.generate_all_tables_json(usr_sesh.user_id).encode("utf-8") + content = self.generate_all_tables_json(user_id).encode("utf-8") request.responseHeaders.addRawHeader( b"content-type", b"application/octet-stream" ) @@ -112,14 +114,14 @@ class IDACFrontend(FE_Base): b"content-length", str(len(content)).encode("utf-8") ) - self.logger.info(f"User {usr_sesh.user_id} exported their IDAC data") + self.logger.info(f"User {user_id} exported their IDAC data") return content profile_data, tickets, rank = None, None, None - if usr_sesh.user_id > 0: - profile_data = self.data.profile.get_profile(usr_sesh.user_id, self.version) - ticket_data = self.data.item.get_tickets(usr_sesh.user_id) - rank = self.data.profile.get_profile_rank(usr_sesh.user_id, self.version) + if user_id > 0: + profile_data = self.data.profile.get_profile(user_id, self.version) + ticket_data = self.data.item.get_tickets(user_id) + rank = self.data.profile.get_profile_rank(user_id, self.version) tickets = { self.ticket_names[ticket["ticket_id"]]: ticket["ticket_cnt"] From d55ada2538b4edac06d5655f6e98d3966a8d3e44 Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Sun, 8 Oct 2023 19:56:04 +0200 Subject: [PATCH 07/18] IDAC: Improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed play stamp event name not shown - Fixed broken cars such as: LEVIN SR (AE85), SKYLINE 25GT TURBO (ER34), S2000 (AP1), GR SUPRA (DB42), SWIFT Sport (ZC33S), LANCER RS EVOLUTION Ⅴ (CP9A), LANCER GSR EVOLUTION Ⅵ TMEDITION (CP9A) - Fixed bunta/special mode not properly updating - Fixed frontend (for real this time) --- titles/idac/data/create_delivery_images.py | 8 ++++-- .../data/stamps/touhou_flandre_scarlet.json | Bin 10737 -> 10736 bytes .../data/stamps/touhou_remilia_scarlet.json | Bin 10695 -> 10694 bytes .../data/stamps/touhou_sakuya_izayoi.json | Bin 10684 -> 10683 bytes titles/idac/data/timeRelease_v0150.json | Bin 1354135 -> 1354811 bytes titles/idac/frontend/idac_index.jinja | 8 ++++-- titles/idac/schema/item.py | 27 ++++++++++++++---- titles/idac/season2.py | 4 +-- 8 files changed, 34 insertions(+), 13 deletions(-) diff --git a/titles/idac/data/create_delivery_images.py b/titles/idac/data/create_delivery_images.py index 196081e..ac37925 100644 --- a/titles/idac/data/create_delivery_images.py +++ b/titles/idac/data/create_delivery_images.py @@ -2,12 +2,13 @@ import os import hashlib -def prepare_images(image_folder="./images"): +def prepare_images(image_folder="titles/idac/data/images"): print(f"Preparing image delivery files in {image_folder}...") for file in os.listdir(image_folder): if file.endswith(".png") or file.endswith(".jpg"): - dpg_name = "adv-" + file[:-4].upper() + # dpg_name = "adv-" + file[:-4].upper() + dpg_name = file[:-4] if file.endswith(".png"): dpg_name += ".dpg" else: @@ -22,10 +23,11 @@ def prepare_images(image_folder="./images"): original_image = original_image_file.read() image_hash = hashlib.md5(original_image).hexdigest() print( - f"DPG for {file} not found, creating with hash {image_hash}..." + f"DPG for {file} not found, creating with hash {image_hash.upper()} ..." ) md5_buf = bytes.fromhex(image_hash) dpg_buf = md5_buf + original_image + dpg_name = "adv-" + image_hash.upper() + dpg_name[:-4] with open(os.path.join(image_folder, dpg_name), "wb") as dpg_file: dpg_file.write(dpg_buf) diff --git a/titles/idac/data/stamps/touhou_flandre_scarlet.json b/titles/idac/data/stamps/touhou_flandre_scarlet.json index 23d2a7d61f0b163210d92b70b806df91199addc0..da642f659648e2a507afbf9781cff478e7a22a53 100644 GIT binary patch delta 18 acmewu{2_RP>10KA;mPv_MK;Dx(F6cZ90xrB delta 16 Xcmewm{4scfDWlfpZb9{pF;g@FK9mNS diff --git a/titles/idac/data/stamps/touhou_remilia_scarlet.json b/titles/idac/data/stamps/touhou_remilia_scarlet.json index 3d917a9201e693a63746cef62ec21c03ea3f7d55..a6fe329374319b6804a918885cebfb9eec7edea2 100644 GIT binary patch delta 14 VcmX>ed@Oi^>EsSU#f{+wngB7X1?K<& delta 16 XcmX>Wd^~u9DWlfpc0t9BVFj81ITQvE diff --git a/titles/idac/data/stamps/touhou_sakuya_izayoi.json b/titles/idac/data/stamps/touhou_sakuya_izayoi.json index 7b98fb31486110eed551a2f2e07b631baec3516b..05d1e2877f3573663d16d43687d853f400f90978 100644 GIT binary patch delta 10 RcmdlJygPV;=|;0QO#mBi1bF}e delta 12 TcmdlTyeD{qDWld#(>6^2A_oMc diff --git a/titles/idac/data/timeRelease_v0150.json b/titles/idac/data/timeRelease_v0150.json index 02d6bf3ec0bdf8cf6f4136a6debb784303ae9950..694c81957b003e3c2a834dcabe8505174834ce7a 100644 GIT binary patch delta 333 zcmbP!IcWEdpbgzj(4%_l%ryj({=~f}>ChdY4WW11o zsGqO{Ny&lBOq`nqSOS@+Uod3l+^oe>%{YC7FgyF?6GCCr3$)m|H?QGrW|=-=KPSZ4 z3zA0D4L);nZ?@o@3v|aCZZ5FZAmRU~xVhn+fREfPjK-5M@@h>6$t@7!;of{-;1%bz zej!ev*%p(ZNGeWmScSxiKM3U95RI5#AR+=WbOWp8=0fQtq2{Z)?N@afftU%1nSq!E wh*^P{4T#x+m;;D8ftU-3xq+Amh42Ou*=N+%XC=Sq^hKX1cTUARa78x5XA11AV@es^#((NKvYyr!hZ!+ zLo%WQLDL%$3=-D^^a6Z{$G-33GU4-N{~>tvA803K&V!!NZdcEFzZKfs(1yIKMcS42 z)g4ubpSuycjmo+65|QtzWx(UUl%8lE@?4O1!xWW-Vqe-f!A;X3_ooWJ&J5vD@Xx1- zUHLfW)t9+H3(ig^_QQ0c{QDEN(O6g6rpf{kP=gR6sDlIr8VF)&fPn|F(1Zk9(EhHn H^mlm!u3$(m diff --git a/titles/idac/frontend/idac_index.jinja b/titles/idac/frontend/idac_index.jinja index 4bd10ca..eeecc65 100644 --- a/titles/idac/frontend/idac_index.jinja +++ b/titles/idac/frontend/idac_index.jinja @@ -2,7 +2,7 @@ {% block content %}

頭文字D THE ARCADE

-{% if sesh is defined and sesh["user_id"] > 0 %} +{% if sesh is defined and sesh["userId"] > 0 %}
@@ -27,6 +27,8 @@
Username

{{ profile.username }}

+
Cash
+

{{ profile.cash }} D

Grade

{% set grade = rank.grade %} @@ -37,7 +39,7 @@ {% else %} Unknown {% endif %} -

+
@@ -58,7 +60,7 @@
Mileage
-

{{ profile.mileage }} m

+

{{ profile.mileage / 1000}} km

{% if tickets is defined and tickets|length > 0 %} diff --git a/titles/idac/schema/item.py b/titles/idac/schema/item.py index ae49c74..e16bfa3 100644 --- a/titles/idac/schema/item.py +++ b/titles/idac/schema/item.py @@ -619,19 +619,36 @@ class IDACItemData(BaseData): def get_best_challenges_by_vs_type( self, aime_id: int, story_type: int = 4 ) -> Optional[List[Row]]: - sql = ( + subquery = ( select( challenge.c.story_type, + challenge.c.user, challenge.c.vs_type, - func.max(challenge.c.cleared_difficulty).label("max_clear_lv"), func.max(challenge.c.play_difficulty).label("last_play_lv"), - challenge.c.course_id, - challenge.c.play_count, ) .where( and_(challenge.c.user == aime_id, challenge.c.story_type == story_type) ) - .group_by(challenge.c.vs_type, challenge.c.course_id, challenge.c.play_count) + .group_by(challenge.c.vs_type) + ) + + sql = ( + select( + challenge.c.story_type, + challenge.c.vs_type, + challenge.c.cleared_difficulty.label("max_clear_lv"), + challenge.c.play_difficulty.label("last_play_lv"), + challenge.c.course_id, + challenge.c.play_count, + ) + .where( + and_( + challenge.c.user == subquery.c.user, + challenge.c.vs_type == subquery.c.vs_type, + challenge.c.play_difficulty == subquery.c.last_play_lv, + ), + ) + .order_by(challenge.c.vs_type) ) result = self.execute(sql) diff --git a/titles/idac/season2.py b/titles/idac/season2.py index 5717978..6ce6b37 100644 --- a/titles/idac/season2.py +++ b/titles/idac/season2.py @@ -146,9 +146,9 @@ class IDACSeason2(IDACBase): "round_event_exp": [], "stamp_info": self.stamp_info, # 0 = use default data, 1+ = server version of timereleasedata response - "timerelease_no": 1, + "timerelease_no": 2, # 0 = use default data, 1+ = server version of gachadata response - "timerelease_avatar_gacha_no": 1, + "timerelease_avatar_gacha_no": 2, "takeover_reward": [], "subcard_judge": [ { From 31188ccce6570b005d9afa4286edeb009b96fe8c Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Tue, 10 Oct 2023 16:06:58 +0200 Subject: [PATCH 08/18] IDAC: Hotfix to block amdaemon_emu users without correct access code --- titles/idac/season2.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/titles/idac/season2.py b/titles/idac/season2.py index 6ce6b37..537ea0d 100644 --- a/titles/idac/season2.py +++ b/titles/idac/season2.py @@ -342,16 +342,25 @@ class IDACSeason2(IDACBase): def handle_login_checklock_request(self, data: Dict, headers: Dict): user_id = data["id"] + access_code = data["accesscode"] + is_new_player = 0 - # check if an IDAC profile already exists - p = self.data.profile.get_profile(user_id, self.version) - is_new_player = 1 if p is None else 0 + # check that the user_id from access_code matches the user_id + if user_id == self.data.card.get_user_id_from_card(access_code): + lock_result = 1 + + # check if an IDAC profile already exists + p = self.data.profile.get_profile(user_id, self.version) + is_new_player = 1 if p is None else 0 + else: + lock_result = 0 + user_id = "" # other: in use return { "status_code": "0", # 0 = already in use, 1 = good, 2 = too new - "lock_result": 1, + "lock_result": lock_result, "lock_date": int(datetime.now().timestamp()), "daily_play": 1, "session": f"{user_id}", From 3ee1801ee6fc3effc6a1ca20d82929303df48555 Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Tue, 10 Oct 2023 17:58:20 +0200 Subject: [PATCH 09/18] IDAC: Hotfix for play stamp and time trials --- .../data/stamps/touhou_remilia_scarlet.json | Bin 10694 -> 10694 bytes .../timetrial/touhou_flandre_scarlet.json | Bin 1189 -> 1163 bytes .../timetrial/touhou_remilia_scarlet.json | Bin 1183 -> 1157 bytes .../data/timetrial/touhou_sakuya_izayoi.json | Bin 1165 -> 1139 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/titles/idac/data/stamps/touhou_remilia_scarlet.json b/titles/idac/data/stamps/touhou_remilia_scarlet.json index a6fe329374319b6804a918885cebfb9eec7edea2..93369e8a86d46f0591fd8bdd975fd459f849b16c 100644 GIT binary patch delta 14 WcmX>Wd@OjwT}DQe&G#5zr~?2r&jyzO delta 14 WcmX>Wd@OjwT}DQ;&G#5zr~?2r+Xk5c diff --git a/titles/idac/data/timetrial/touhou_flandre_scarlet.json b/titles/idac/data/timetrial/touhou_flandre_scarlet.json index 314881aa584a8266de554ffc54ea2c4f79549fda..e7bab3d4bbf589aa4fbc1b7f042b054cd5c08455 100644 GIT binary patch delta 12 TcmZ3=+0D7ZfoXFTlQ$Cp8oL9L delta 12 TcmeC?T*|q@foZcEQz{bx8S4Xg diff --git a/titles/idac/data/timetrial/touhou_remilia_scarlet.json b/titles/idac/data/timetrial/touhou_remilia_scarlet.json index 35c855ef491ff50fc5006fa79068297b9986ebba..2414f4a125e537b8f102c07dea83bdb7300084ae 100644 GIT binary patch delta 12 TcmbQw*~+=WifMBQlQ$Cp8TA8s delta 16 XcmZqWoX@$zifOVg6YpkSrU)hgD7pkL diff --git a/titles/idac/data/timetrial/touhou_sakuya_izayoi.json b/titles/idac/data/timetrial/touhou_sakuya_izayoi.json index 9cf05850515d83b6ac5346c0350d2089a32bef0b..b817f5edfb0450c7f69d1fb602c8780881cfbb31 100644 GIT binary patch delta 12 TcmeC>{LHaIgK4u9lQ$Cp9GU~L delta 16 Xcmey&(aX6(gK4rf6YpkerU)hgEb# Date: Thu, 19 Oct 2023 18:52:10 +0200 Subject: [PATCH 10/18] IDAC: avatar gacha updated (HUGE PAIN), config fixes --- Dockerfile | 4 ++-- docs/game_specific_info.md | 5 +++-- example_config/idac.yaml | 6 +++--- titles/idac/data/avatarGacha.json | Bin 262275 -> 847892 bytes 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index e34dfec..d55c9e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM python:3.9.15-slim-bullseye -RUN apt update && apt install default-libmysqlclient-dev build-essential libtk nodejs npm -y +RUN apt update && apt install default-libmysqlclient-dev build-essential libtk nodejs npm pkg-config -y WORKDIR /app COPY requirements.txt requirements.txt @@ -15,7 +15,7 @@ COPY dbutils.py dbutils.py ADD core core ADD titles titles ADD config config -ADD log log +ADD logs logs ADD cert cert ENTRYPOINT [ "/app/entrypoint.sh" ] \ No newline at end of file diff --git a/docs/game_specific_info.md b/docs/game_specific_info.md index 615f10b..545a877 100644 --- a/docs/game_specific_info.md +++ b/docs/game_specific_info.md @@ -551,9 +551,9 @@ Config file is located in `config/idac.yaml`. | `port_matching` | Port number for the Online Battle Matching | | `port_echo1/2` | Port numbers for Echos | | `port_matching_p2p` | Port number for Online Battle (currently unsupported) | -| `stamp.enabled` | Enables/Disabled the play stamp events | +| `stamp.enable` | Enables/Disabled the play stamp events | | `stamp.enabled_stamps` | Define up to 3 play stamp events (without `.json` extension, which are placed in `titles/idac/data/stamps`) | -| `timetrial.enabled` | Enables/Disables the time trial event | +| `timetrial.enable` | Enables/Disables the time trial event | | `timetrial.enabled_timetrial` | Define one! trial event (without `.json` extension, which are placed in `titles/idac/data/timetrial`) | @@ -642,6 +642,7 @@ python dbutils.py --game SDGT upgrade | 70 | Odawara(小田原) | Reverse(逆走) | ### Credits +- Bottersnike: For the HUGE Reverse Engineering help - Kinako: For helping with the timeRelease unlocking of courses and special mode A huge thanks to all people who helped shaping this project to what it is now and don't want to be mentioned here. diff --git a/example_config/idac.yaml b/example_config/idac.yaml index 331ae82..626565e 100644 --- a/example_config/idac.yaml +++ b/example_config/idac.yaml @@ -1,5 +1,5 @@ server: - enabled: True + enable: True loglevel: "info" ssl: False ssl_key: "cert/idac.key" @@ -11,12 +11,12 @@ server: port_matching_p2p: 20003 stamp: - enabled: True + enable: True enabled_stamps: # max 3 play stamps - "touhou_remilia_scarlet" - "touhou_flandre_scarlet" - "touhou_sakuya_izayoi" timetrial: - enabled: True + enable: True enabled_timetrial: "touhou_remilia_scarlet" diff --git a/titles/idac/data/avatarGacha.json b/titles/idac/data/avatarGacha.json index 91bb516a9d64ff6a5aa4d1ac400e4214172c0f09..bcfba2f5def63c2d68f86b286d3afeaa8de2af02 100644 GIT binary patch literal 847892 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 From b5e3bf6f80b9d49ccbdbb413ab2e00eca5673f8d Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Thu, 19 Oct 2023 19:04:06 +0200 Subject: [PATCH 11/18] IDAC: Hotfix for UTF-8 encoding --- titles/idac/season2.py | 48 ++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/titles/idac/season2.py b/titles/idac/season2.py index 537ea0d..a5d9961 100644 --- a/titles/idac/season2.py +++ b/titles/idac/season2.py @@ -24,11 +24,11 @@ class IDACSeason2(IDACBase): self.logger.warning(f"Stamp {stamp} is enabled but does not exist!") continue - with open(f"./titles/idac/data/stamps/{stamp}.json", "rb") as f: + with open( + f"./titles/idac/data/stamps/{stamp}.json", encoding="UTF-8" + ) as f: self.logger.debug(f"Loading stamp {stamp}") - self.stamp_info.append( - self._fix_dates(json.loads(f.read().decode("utf-8"))) - ) + self.stamp_info.append(self._fix_dates(json.load(f))) self.timetrial_event = {} self.timetrial_event_id = None @@ -41,13 +41,16 @@ class IDACSeason2(IDACBase): ) else: self.logger.debug(f"Loading timetrial {timetrial}") - with open(f"./titles/idac/data/timetrial/{timetrial}.json", "rb") as f: - self.timetrial_event = self._fix_dates( - json.loads(f.read().decode("utf-8")) - ) + with open( + f"./titles/idac/data/timetrial/{timetrial}.json", + encoding="UTF-8", + ) as f: + self.timetrial_event = self._fix_dates(json.load(f)) # required for saving - self.timetrial_event_id = self.timetrial_event.get("timetrial_event_id") + self.timetrial_event_id = self.timetrial_event.get( + "timetrial_event_id" + ) def handle_alive_get_request(self, data: Dict, headers: Dict): return { @@ -108,9 +111,7 @@ class IDACSeason2(IDACBase): if self.core_cfg.server.is_develop: domain_api_game = f"http://{self.core_cfg.title.hostname}:{self.core_cfg.title.port}/SDGT/{ver_str}/" else: - domain_api_game = ( - f"http://{self.core_cfg.title.hostname}/SDGT/{ver_str}/" - ) + domain_api_game = f"http://{self.core_cfg.title.hostname}/SDGT/{ver_str}/" return { "status_code": "0", @@ -146,9 +147,9 @@ class IDACSeason2(IDACBase): "round_event_exp": [], "stamp_info": self.stamp_info, # 0 = use default data, 1+ = server version of timereleasedata response - "timerelease_no": 2, + "timerelease_no": 3, # 0 = use default data, 1+ = server version of gachadata response - "timerelease_avatar_gacha_no": 2, + "timerelease_avatar_gacha_no": 3, "takeover_reward": [], "subcard_judge": [ { @@ -214,7 +215,7 @@ class IDACSeason2(IDACBase): 18: Background """ - with open("./titles/idac/data/avatarGacha.json") as f: + with open("./titles/idac/data/avatarGacha.json", encoding="UTF-8") as f: avatar_gacha_data = json.load(f) # avatar_gacha_data = { @@ -1290,7 +1291,9 @@ class IDACSeason2(IDACBase): self.data.item.put_time_trial(self.version, user_id, data) # update the timetrial event points - self.data.item.put_timetrial_event(user_id, self.timetrial_event_id, event_point) + self.data.item.put_timetrial_event( + user_id, self.timetrial_event_id, event_point + ) return { "status_code": "0", @@ -1302,7 +1305,7 @@ class IDACSeason2(IDACBase): "timetrial_event_data": { "timetrial_event_id": self.timetrial_event_id, "point": event_point, - } + }, } def handle_user_updatestoryresult_request(self, data: Dict, headers: Dict): @@ -1598,7 +1601,9 @@ class IDACSeason2(IDACBase): skill_level_exp = course["skill_level_exp"] # get the best time for the current course for the current user - best_trial = self.data.item.get_time_trial_best_ranking_by_course(season_id, user_id, course_id) + best_trial = self.data.item.get_time_trial_best_ranking_by_course( + season_id, user_id, course_id + ) if not best_trial: continue @@ -1607,7 +1612,9 @@ class IDACSeason2(IDACBase): course_rank = self.data.item.get_time_trial_ranking_by_course( season_id, course_id, limit=None ) - course_rank = len([r for r in course_rank if r["goal_time"] < goal_time]) + 1 + course_rank = ( + len([r for r in course_rank if r["goal_time"] < goal_time]) + 1 + ) timetrial_data.append( { @@ -1617,7 +1624,8 @@ class IDACSeason2(IDACBase): "goal_time": goal_time, "rank": course_rank, "rank_dt": int(best_trial["play_dt"].timestamp()), - }) + } + ) return timetrial_data From 4fc4d98a746e025a7fccc1ef46bd8599fffd0e68 Mon Sep 17 00:00:00 2001 From: UncleJim Date: Thu, 26 Oct 2023 10:21:01 +0000 Subject: [PATCH 12/18] Always return matching state to keep players out of looping back to matching screen (#6) Reviewed-on: https://gitea.tendokyu.moe/Dniel97/artemis/pulls/6 Co-authored-by: UncleJim Co-committed-by: UncleJim --- titles/idac/matching.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/titles/idac/matching.py b/titles/idac/matching.py index fb9f56d..396eec8 100644 --- a/titles/idac/matching.py +++ b/titles/idac/matching.py @@ -55,7 +55,7 @@ class IDACMatching(resource.Resource): "host": self.game_config.server.matching_host, "port": self.game_config.server.matching_p2p, "room_name": "INDTA", - "state": self.get_matching_state(), + "state": 1, } self.logger.debug(f"Response {resp}") From 3f192bd84a2c80304e8719d7c24126bab6363ba4 Mon Sep 17 00:00:00 2001 From: UncleJim Date: Fri, 27 Oct 2023 11:05:55 +0000 Subject: [PATCH 13/18] Proper store name and region handling (#4) Now the code will read store name from `aime.arcade` table instead of putting `self.core_cfg.server.name` into it braindead-ly Reviewed-on: https://gitea.tendokyu.moe/Dniel97/artemis/pulls/4 Co-authored-by: UncleJim Co-committed-by: UncleJim --- titles/idac/season2.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/titles/idac/season2.py b/titles/idac/season2.py index a5d9961..13017b0 100644 --- a/titles/idac/season2.py +++ b/titles/idac/season2.py @@ -301,6 +301,11 @@ class IDACSeason2(IDACBase): # get the username, country and store from the profile profile = self.data.profile.get_profile(user_id, self.version) + arcade = self.data.arcade.get_arcade(profile["store"]) + + if arcade is None: + arcade = {} + arcade["name"] = self.core_cfg.server.name # should never happen if profile is None: @@ -313,9 +318,9 @@ class IDACSeason2(IDACBase): "username": profile["username"], "value": rank["goal_time"], # gat the store name from the profile - "store": self.core_cfg.server.name, + "store": arcade["name"], # get the country id from the profile, 9 is JPN - "country": 9, + "country": profile["country"], "style_car_id": rank["style_car_id"], # convert the datetime to a timestamp "play_dt": int(rank["play_dt"].timestamp()), @@ -492,11 +497,13 @@ class IDACSeason2(IDACBase): # get the user's profile, can never be None p = self.data.profile.get_profile(user_id, self.version) user_data = p._asdict() + arcade = self.data.arcade.get_arcade(user_data["store"]) + del user_data["id"] del user_data["user"] del user_data["version"] user_data["id"] = user_id - user_data["store_name"] = self.core_cfg.server.name + user_data["store_name"] = self.core_cfg.server.name if arcade is None else arcade["name"] user_data["last_play_date"] = int(user_data["last_play_date"].timestamp()) user_data["create_date"] = int(user_data["create_date"].timestamp()) @@ -1735,6 +1742,8 @@ class IDACSeason2(IDACBase): # set the name to CPU profile["username"] = f"CPU" # also reset stamps to default + profile["country"] = 9 + profile["store"] = 0 profile["stamp_key_assign_0"] = 0 profile["stamp_key_assign_1"] = 1 profile["stamp_key_assign_2"] = 2 @@ -1850,6 +1859,11 @@ class IDACSeason2(IDACBase): if time_trial: eval_id = time_trial["eval_id"] + arcade = self.data.arcade.get_arcade(profile["store"]) + if arcade is None: + arcade = {} + arcade["name"] = self.core_cfg.server.name + rival_data.append( { "id": profile["user"], @@ -1858,13 +1872,13 @@ class IDACSeason2(IDACBase): # only needed for power match "powerhouseLv": powerhose_lv, "mytitleId": profile["mytitle_id"], - "country": 9, + "country": profile["country"], "auraId": profile["aura_id"], "auraColor": profile["aura_color_id"], "auraLine": profile["aura_line_id"], # not sure? "roundRanking": 0, - "storeName": self.core_cfg.server.name, + "storeName": arcade["name"], "sex": avatar["sex"], "face": avatar["face"], "eye": avatar["eye"], From 1224baeade962c5174cbbccfbe81c662fcd60792 Mon Sep 17 00:00:00 2001 From: UncleJim Date: Mon, 6 Nov 2023 15:32:40 +0000 Subject: [PATCH 14/18] Experimental online match API support and car use countting fix (#5) Reviewed-on: https://gitea.tendokyu.moe/Dniel97/artemis/pulls/5 Co-authored-by: UncleJim Co-committed-by: UncleJim --- titles/idac/season2.py | 399 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 393 insertions(+), 6 deletions(-) diff --git a/titles/idac/season2.py b/titles/idac/season2.py index 13017b0..53818c8 100644 --- a/titles/idac/season2.py +++ b/titles/idac/season2.py @@ -141,7 +141,249 @@ class IDACSeason2(IDACBase): "domain_echo2": f"{self.core_cfg.title.hostname}:{self.game_config.server.echo2}", "domain_ping": f"{self.core_cfg.title.hostname}", "battle_gift_event_master": [], - "round_event": [], + "round_event":[ + { + "round_event_id":30, + "round_event_nm":"ARTEMiS Event", + "start_dt":int( + datetime.strptime("2023-01-01", "%Y-%m-%d").timestamp() + ), + "end_dt":int( + datetime.strptime("2029-01-01", "%Y-%m-%d").timestamp() + ), + "round_start_rank":0, + "save_filename":"Round_Event_djg_Or_dpg", + "vscount":[ + { + "reward_upper_limit":10, + "reward_lower_limit":10, + "reward":[ + { + "reward_category":1, + "reward_type":1 + } + ] + } + ], + "rank":[ + + ], + "point":[ + + ], + "playable_course_list":[ + { + "course_id":4, + "course_day":0 + }, + { + "course_id":4, + "course_day":1 + }, + { + "course_id":6, + "course_day":0 + }, + { + "course_id":6, + "course_day":1 + }, + { + "course_id":8, + "course_day":0 + }, + { + "course_id":8, + "course_day":1 + }, + { + "course_id":10, + "course_day":0 + }, + { + "course_id":10, + "course_day":1 + }, + { + "course_id":12, + "course_day":0 + }, + { + "course_id":12, + "course_day":1 + }, + { + "course_id":14, + "course_day":0 + }, + { + "course_id":14, + "course_day":1 + }, + { + "course_id":16, + "course_day":0 + }, + { + "course_id":16, + "course_day":1 + }, + { + "course_id":18, + "course_day":0 + }, + { + "course_id":18, + "course_day":1 + }, + { + "course_id":20, + "course_day":0 + }, + { + "course_id":20, + "course_day":1 + }, + { + "course_id":22, + "course_day":0 + }, + { + "course_id":22, + "course_day":1 + }, + { + "course_id":24, + "course_day":0 + }, + { + "course_id":24, + "course_day":1 + }, + { + "course_id":26, + "course_day":0 + }, + { + "course_id":26, + "course_day":1 + }, + { + "course_id":36, + "course_day":0 + }, + { + "course_id":36, + "course_day":1 + }, + { + "course_id":38, + "course_day":0 + }, + { + "course_id":38, + "course_day":1 + }, + { + "course_id":40, + "course_day":0 + }, + { + "course_id":40, + "course_day":1 + }, + { + "course_id":42, + "course_day":0 + }, + { + "course_id":42, + "course_day":1 + }, + { + "course_id":44, + "course_day":0 + }, + { + "course_id":44, + "course_day":1 + }, + { + "course_id":46, + "course_day":0 + }, + { + "course_id":46, + "course_day":1 + }, + { + "course_id":48, + "course_day":0 + }, + { + "course_id":48, + "course_day":1 + }, + { + "course_id":50, + "course_day":0 + }, + { + "course_id":50, + "course_day":1 + }, + { + "course_id":52, + "course_day":0 + }, + { + "course_id":52, + "course_day":1 + }, + { + "course_id":54, + "course_day":0 + }, + { + "course_id":54, + "course_day":1 + }, + { + "course_id":56, + "course_day":0 + }, + { + "course_id":56, + "course_day":1 + }, + { + "course_id":58, + "course_day":0 + }, + { + "course_id":58, + "course_day":1 + }, + { + "course_id":68, + "course_day":0 + }, + { + "course_id":68, + "course_day":1 + }, + { + "course_id":70, + "course_day":0 + }, + { + "course_id":70, + "course_day":1 + } + ] + } + ], + "last_round_event": [], "last_round_event_ranking": [], "round_event_exp": [], @@ -1460,7 +1702,7 @@ class IDACSeason2(IDACBase): # get the vs use count from database and update it style_car_id = data.pop("style_car_id") car_data = self.data.item.get_car(user_id, self.version, style_car_id) - vs_use_count = car_data["vs_use_count"] + 1 + story_use_count = car_data["story_use_count"] + 1 # save car data in database self.data.item.put_car( @@ -1469,7 +1711,7 @@ class IDACSeason2(IDACBase): { "style_car_id": style_car_id, "car_mileage": data.pop("car_mileage"), - "vs_use_count": vs_use_count, + "story_use_count": story_use_count, }, ) @@ -1528,7 +1770,7 @@ class IDACSeason2(IDACBase): # get the vs use count from database and update it style_car_id = data.get("style_car_id") car_data = self.data.item.get_car(user_id, self.version, style_car_id) - vs_use_count = car_data["vs_use_count"] + 1 + story_use_count = car_data["story_use_count"] + 1 # save car data in database self.data.item.put_car( @@ -1537,7 +1779,7 @@ class IDACSeason2(IDACBase): { "style_car_id": style_car_id, "car_mileage": data.pop("car_mileage"), - "vs_use_count": vs_use_count, + "story_use_count": story_use_count, }, ) @@ -2115,6 +2357,151 @@ class IDACSeason2(IDACBase): "win_count_multi": win_count_multi, } + def handle_timetrial_getbestrecordprebattle_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + course_pickup_car_best_data = [] + courses = self.data.item.get_time_trial_courses(self.version) + for course in courses: + car_list = [] + best_cars = self.data.item.get_time_trial_best_cars_by_course( + self.version, user_id, course["course_id"] + ) + + for car in best_cars: + car_list.append( + { + "rank": 1, + # no clue + "member": user_id, + "value": car["goal_time"], + "store": self.core_cfg.server.name, + # use car_id from request? + "car_id": 0, + "style_car_id": car["style_car_id"], + "play_dt": car["play_dt"].timestamp(), + "section_time_1": car["section_time_1"], + "section_time_2": car["section_time_2"], + "section_time_3": car["section_time_3"], + "section_time_4": car["section_time_4"], + "mission": car["mission"], + } + ) + + course_pickup_car_best_data.append( + { + "course_id": course["course_id"], + "car_list": car_list, + } + ) + + return { + "status_code": "0", + # "course_car_best_data": course_car_best_data, + # "course_best_data": course_best_data, + "course_pickup_car_best_data": course_pickup_car_best_data, + } + + + def handle_user_updateonlinebattle_request(self, data: Dict, headers: Dict): + return { + "status_code": "0", + "bothwin_penalty": 1, + } + + def handle_user_updateonlinebattleresult_request(self, data: Dict, headers: Dict): + user_id = headers["session"] + + stock_data: Dict = data.pop("stock_obj") + # save stock data in database + self._save_stock_data(user_id, stock_data) + + ticket_data: List = data.pop("ticket_data") + for ticket in ticket_data: + self.data.item.put_ticket(user_id, ticket) + + reward_dist_data: Dict = data.pop("reward_dist_obj") + rank_data: Dict = data.pop("mode_rank_obj") + + # save rank dist data in database + rank_data.update(reward_dist_data) + self.data.profile.put_profile_rank(user_id, self.version, rank_data) + + driver_debut_data = data.pop("driver_debut_obj") + + # get the use_count and net_vs_use_count of the used car + style_car_id = data.get("style_car_id") + car_mileage = data.pop("car_mileage") + used_car = self.data.item.get_car(user_id, self.version, style_car_id)._asdict() + + # increase the use_count and net_vs_use_count of the used car + used_car["use_count"] += 1 + used_car["net_vs_use_count"] += 1 + used_car["car_mileage"] = car_mileage + + # save the used car in database + self.data.item.put_car(user_id, self.version, used_car) + + # get the profile data, update total_play and daily_play, and save it + profile = self.data.profile.get_profile(user_id, self.version) + total_play = profile["total_play"] + 1 + + # save the profile in database + self.data.profile.put_profile( + user_id, + self.version, + { + "total_play": total_play, + "last_play_date": datetime.now(), + "mileage": data.pop("mileage"), + "aura_id": data.pop("aura_id"), + "aura_color_id": data.pop("aura_color_id"), + "aura_line_id": data.pop("aura_line_id"), + "cash": data.pop("cash"), + "total_cash": data.pop("total_cash"), + "dressup_point": data.pop("dressup_point"), + "avatar_point": data.pop("avatar_point"), + }, + ) + + self.data.item.put_vs_info(user_id, data) + + vs_info = { + "battle_mode": 0, + "vs_cnt": 1, + "vs_win": data.get("win_flg"), + "invalid": 0, + "str": 0, + "str_now": 0, + "lose_now": 0, + "vs_history": data.get("vs_history"), + "course_select_priority": data.get("course_select_priority"), + "vsinfo_course_data": [ + { + "course_id": data.get("course_id"), + "vs_cnt": 1, + "vs_win": data.get("win_flg"), + } + ], + } + + return { + "status_code": "0", + "vsinfo_data": vs_info, + "round_event": [ + { + "count": 1, + "win": 1, + "rank": 1, + "point": 1, + "total_round_point": 1, + } + ], + "car_use_count": [], + "maker_use_count": [], + } + + def handle_user_updatestorebattleresult_request(self, data: Dict, headers: Dict): user_id = headers["session"] @@ -2147,7 +2534,7 @@ class IDACSeason2(IDACBase): # increase the use_count and net_vs_use_count of the used car used_car["use_count"] += 1 - used_car["net_vs_use_count"] += 1 + used_car["vs_use_count"] += 1 used_car["car_mileage"] = car_mileage # save the used car in database From acac2c46706a8852dde3abfc69b56d05a99f510d Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Mon, 6 Nov 2023 18:11:30 +0100 Subject: [PATCH 15/18] IDAC: time trial should display car time now --- titles/idac/base.py | 6 +- titles/idac/schema/item.py | 10 +- titles/idac/season2.py | 452 ++++++++++++++----------------------- 3 files changed, 181 insertions(+), 287 deletions(-) diff --git a/titles/idac/base.py b/titles/idac/base.py index c556aff..eb75b93 100644 --- a/titles/idac/base.py +++ b/titles/idac/base.py @@ -7,10 +7,10 @@ from titles.idac.database import IDACData class IDACBase: - def __init__(self, cfg: CoreConfig, game_cfg: IDACConfig) -> None: - self.core_cfg = cfg + def __init__(self, core_cfg: CoreConfig, game_cfg: IDACConfig) -> None: + self.core_cfg = core_cfg self.game_config = game_cfg self.game = IDACConstants.GAME_CODE self.version = IDACConstants.VER_IDAC_SEASON_1 - self.data = IDACData(cfg) + self.data = IDACData(core_cfg) self.logger = logging.getLogger("idac") diff --git a/titles/idac/schema/item.py b/titles/idac/schema/item.py index e16bfa3..80ee7ba 100644 --- a/titles/idac/schema/item.py +++ b/titles/idac/schema/item.py @@ -497,7 +497,7 @@ class IDACItemData(BaseData): return result.fetchall() def get_time_trial_best_cars_by_course( - self, version: int, aime_id: int, course_id: int + self, version: int, course_id: int, aime_id: Optional[int] = None ) -> Optional[List[Row]]: subquery = ( select( @@ -508,14 +508,16 @@ class IDACItemData(BaseData): .where( and_( trial.c.version == version, - trial.c.user == aime_id, trial.c.course_id == course_id, ) ) - .group_by(trial.c.style_car_id) - .subquery() ) + if aime_id is not None: + subquery = subquery.where(trial.c.user == aime_id) + + subquery = subquery.group_by(trial.c.style_car_id).subquery() + sql = select(trial).where( and_( trial.c.version == subquery.c.version, diff --git a/titles/idac/season2.py b/titles/idac/season2.py index 53818c8..61109da 100644 --- a/titles/idac/season2.py +++ b/titles/idac/season2.py @@ -141,249 +141,83 @@ class IDACSeason2(IDACBase): "domain_echo2": f"{self.core_cfg.title.hostname}:{self.game_config.server.echo2}", "domain_ping": f"{self.core_cfg.title.hostname}", "battle_gift_event_master": [], - "round_event":[ + "round_event": [ { - "round_event_id":30, - "round_event_nm":"ARTEMiS Event", - "start_dt":int( - datetime.strptime("2023-01-01", "%Y-%m-%d").timestamp() - ), - "end_dt":int( - datetime.strptime("2029-01-01", "%Y-%m-%d").timestamp() - ), - "round_start_rank":0, - "save_filename":"Round_Event_djg_Or_dpg", - "vscount":[ + "round_event_id": 30, + "round_event_nm": f"{self.core_cfg.server.name} Event", + "start_dt": int( + datetime.strptime("2023-01-01", "%Y-%m-%d").timestamp() + ), + "end_dt": int( + datetime.strptime("2029-01-01", "%Y-%m-%d").timestamp() + ), + "round_start_rank": 0, + "save_filename": "Round_Event_djg_Or_dpg", + "vscount": [ { - "reward_upper_limit":10, - "reward_lower_limit":10, - "reward":[ - { - "reward_category":1, - "reward_type":1 - } - ] + "reward_upper_limit": 10, + "reward_lower_limit": 10, + "reward": [{"reward_category": 1, "reward_type": 1}], } ], - "rank":[ - + "rank": [], + "point": [], + "playable_course_list": [ + {"course_id": 4, "course_day": 0}, + {"course_id": 4, "course_day": 1}, + {"course_id": 6, "course_day": 0}, + {"course_id": 6, "course_day": 1}, + {"course_id": 8, "course_day": 0}, + {"course_id": 8, "course_day": 1}, + {"course_id": 10, "course_day": 0}, + {"course_id": 10, "course_day": 1}, + {"course_id": 12, "course_day": 0}, + {"course_id": 12, "course_day": 1}, + {"course_id": 14, "course_day": 0}, + {"course_id": 14, "course_day": 1}, + {"course_id": 16, "course_day": 0}, + {"course_id": 16, "course_day": 1}, + {"course_id": 18, "course_day": 0}, + {"course_id": 18, "course_day": 1}, + {"course_id": 20, "course_day": 0}, + {"course_id": 20, "course_day": 1}, + {"course_id": 22, "course_day": 0}, + {"course_id": 22, "course_day": 1}, + {"course_id": 24, "course_day": 0}, + {"course_id": 24, "course_day": 1}, + {"course_id": 26, "course_day": 0}, + {"course_id": 26, "course_day": 1}, + {"course_id": 36, "course_day": 0}, + {"course_id": 36, "course_day": 1}, + {"course_id": 38, "course_day": 0}, + {"course_id": 38, "course_day": 1}, + {"course_id": 40, "course_day": 0}, + {"course_id": 40, "course_day": 1}, + {"course_id": 42, "course_day": 0}, + {"course_id": 42, "course_day": 1}, + {"course_id": 44, "course_day": 0}, + {"course_id": 44, "course_day": 1}, + {"course_id": 46, "course_day": 0}, + {"course_id": 46, "course_day": 1}, + {"course_id": 48, "course_day": 0}, + {"course_id": 48, "course_day": 1}, + {"course_id": 50, "course_day": 0}, + {"course_id": 50, "course_day": 1}, + {"course_id": 52, "course_day": 0}, + {"course_id": 52, "course_day": 1}, + {"course_id": 54, "course_day": 0}, + {"course_id": 54, "course_day": 1}, + {"course_id": 56, "course_day": 0}, + {"course_id": 56, "course_day": 1}, + {"course_id": 58, "course_day": 0}, + {"course_id": 58, "course_day": 1}, + {"course_id": 68, "course_day": 0}, + {"course_id": 68, "course_day": 1}, + {"course_id": 70, "course_day": 0}, + {"course_id": 70, "course_day": 1}, ], - "point":[ - - ], - "playable_course_list":[ - { - "course_id":4, - "course_day":0 - }, - { - "course_id":4, - "course_day":1 - }, - { - "course_id":6, - "course_day":0 - }, - { - "course_id":6, - "course_day":1 - }, - { - "course_id":8, - "course_day":0 - }, - { - "course_id":8, - "course_day":1 - }, - { - "course_id":10, - "course_day":0 - }, - { - "course_id":10, - "course_day":1 - }, - { - "course_id":12, - "course_day":0 - }, - { - "course_id":12, - "course_day":1 - }, - { - "course_id":14, - "course_day":0 - }, - { - "course_id":14, - "course_day":1 - }, - { - "course_id":16, - "course_day":0 - }, - { - "course_id":16, - "course_day":1 - }, - { - "course_id":18, - "course_day":0 - }, - { - "course_id":18, - "course_day":1 - }, - { - "course_id":20, - "course_day":0 - }, - { - "course_id":20, - "course_day":1 - }, - { - "course_id":22, - "course_day":0 - }, - { - "course_id":22, - "course_day":1 - }, - { - "course_id":24, - "course_day":0 - }, - { - "course_id":24, - "course_day":1 - }, - { - "course_id":26, - "course_day":0 - }, - { - "course_id":26, - "course_day":1 - }, - { - "course_id":36, - "course_day":0 - }, - { - "course_id":36, - "course_day":1 - }, - { - "course_id":38, - "course_day":0 - }, - { - "course_id":38, - "course_day":1 - }, - { - "course_id":40, - "course_day":0 - }, - { - "course_id":40, - "course_day":1 - }, - { - "course_id":42, - "course_day":0 - }, - { - "course_id":42, - "course_day":1 - }, - { - "course_id":44, - "course_day":0 - }, - { - "course_id":44, - "course_day":1 - }, - { - "course_id":46, - "course_day":0 - }, - { - "course_id":46, - "course_day":1 - }, - { - "course_id":48, - "course_day":0 - }, - { - "course_id":48, - "course_day":1 - }, - { - "course_id":50, - "course_day":0 - }, - { - "course_id":50, - "course_day":1 - }, - { - "course_id":52, - "course_day":0 - }, - { - "course_id":52, - "course_day":1 - }, - { - "course_id":54, - "course_day":0 - }, - { - "course_id":54, - "course_day":1 - }, - { - "course_id":56, - "course_day":0 - }, - { - "course_id":56, - "course_day":1 - }, - { - "course_id":58, - "course_day":0 - }, - { - "course_id":58, - "course_day":1 - }, - { - "course_id":68, - "course_day":0 - }, - { - "course_id":68, - "course_day":1 - }, - { - "course_id":70, - "course_day":0 - }, - { - "course_id":70, - "course_day":1 - } - ] } ], - "last_round_event": [], "last_round_event_ranking": [], "round_event_exp": [], @@ -740,12 +574,14 @@ class IDACSeason2(IDACBase): p = self.data.profile.get_profile(user_id, self.version) user_data = p._asdict() arcade = self.data.arcade.get_arcade(user_data["store"]) - + del user_data["id"] del user_data["user"] del user_data["version"] user_data["id"] = user_id - user_data["store_name"] = self.core_cfg.server.name if arcade is None else arcade["name"] + user_data["store_name"] = ( + self.core_cfg.server.name if arcade is None else arcade["name"] + ) user_data["last_play_date"] = int(user_data["last_play_date"].timestamp()) user_data["create_date"] = int(user_data["create_date"].timestamp()) @@ -1066,13 +902,13 @@ class IDACSeason2(IDACBase): for course in courses: car_list = [] best_cars = self.data.item.get_time_trial_best_cars_by_course( - self.version, user_id, course["course_id"] + self.version, course["course_id"], user_id ) - for car in best_cars: + for i, car in enumerate(best_cars): car_list.append( { - "rank": 1, + "rank": i + 1, # no clue "member": user_id, "value": car["goal_time"], @@ -1099,39 +935,97 @@ class IDACSeason2(IDACBase): return { "status_code": "0", "course_mybest_data": course_mybest_data, - # "course_car_best_data": course_car_best_data, - # "course_best_data": course_best_data, - "location_course_store_best_data": [], "course_pickup_car_best_data": course_pickup_car_best_data, } def handle_timetrial_getbestrecordprerace_request(self, data: Dict, headers: Dict): user_id = headers["session"] - for car_id in data["car_ids"]: - pass + course_id = data["course_id"] + for car in data["car_ids"]: + # TODO: get the best record for this car + style_car_id = car["style_car_id"] - course_best_data = [ - { - "course_id": 56, - "rank": 1, - "member": user_id, - "value": 118016, - "store": self.core_cfg.server.name, - "car_id": 0, - "style_car_id": 0, - "play_dt": int(datetime.now().timestamp() - 86400), - "section_time_1": 45205, - "section_time_2": 47779, - "section_time_3": 43480, - "section_time_4": 41552, - "mission": 1, - } - ] + # Not sure if this is actually correct + ranking = self.data.item.get_time_trial_ranking_by_course( + self.version, course_id + ) + course_best_data = [] + for i, rank in enumerate(ranking): + car_user_id = rank["user"] + + # get the username, country and store from the profile + profile = self.data.profile.get_profile(car_user_id, self.version) + arcade = self.data.arcade.get_arcade(profile["store"]) + + if arcade is None: + arcade = {} + arcade["name"] = self.core_cfg.server.name + + # should never happen + if profile is None: + continue + + course_best_data.append( + { + "course_id": course_id, + "rank": i + 1, + "member": car_user_id, + "value": rank["goal_time"], + "store": arcade["name"], + # use car_id from request? + "car_id": 0, + "style_car_id": rank["style_car_id"], + "play_dt": rank["play_dt"].timestamp(), + "section_time_1": rank["section_time_1"], + "section_time_2": rank["section_time_2"], + "section_time_3": rank["section_time_3"], + "section_time_4": rank["section_time_4"], + "mission": rank["mission"], + } + ) + + best_cars = self.data.item.get_time_trial_best_cars_by_course( + self.version, course_id + ) + + car_list = [] + for i, rank in enumerate(best_cars): + car_user_id = rank["user"] + # get the username, country and store from the profile + profile = self.data.profile.get_profile(car_user_id, self.version) + arcade = self.data.arcade.get_arcade(profile["store"]) + + if arcade is None: + arcade = {} + arcade["name"] = self.core_cfg.server.name + + # should never happen + if profile is None: + continue + + car_list.append( + { + "rank": i + 1, + # no clue + "member": car_user_id, + "value": rank["goal_time"], + "store": arcade["name"], + # use car_id from request? + "car_id": 0, + "style_car_id": rank["style_car_id"], + "play_dt": rank["play_dt"].timestamp(), + "section_time_1": rank["section_time_1"], + "section_time_2": rank["section_time_2"], + "section_time_3": rank["section_time_3"], + "section_time_4": rank["section_time_4"], + "mission": rank["mission"], + } + ) return { "status_code": "0", - # "course_car_best_data": course_car_best_data, + "course_car_best_data": [{"course_id": course_id, "car_list": car_list}], "course_best_data": course_best_data, } @@ -2357,7 +2251,9 @@ class IDACSeason2(IDACBase): "win_count_multi": win_count_multi, } - def handle_timetrial_getbestrecordprebattle_request(self, data: Dict, headers: Dict): + def handle_timetrial_getbestrecordprebattle_request( + self, data: Dict, headers: Dict + ): user_id = headers["session"] course_pickup_car_best_data = [] @@ -2365,13 +2261,13 @@ class IDACSeason2(IDACBase): for course in courses: car_list = [] best_cars = self.data.item.get_time_trial_best_cars_by_course( - self.version, user_id, course["course_id"] + self.version, course["course_id"], user_id ) - for car in best_cars: + for i, car in enumerate(best_cars): car_list.append( { - "rank": 1, + "rank": i + 1, # no clue "member": user_id, "value": car["goal_time"], @@ -2397,13 +2293,10 @@ class IDACSeason2(IDACBase): return { "status_code": "0", - # "course_car_best_data": course_car_best_data, - # "course_best_data": course_best_data, "course_pickup_car_best_data": course_pickup_car_best_data, } - - def handle_user_updateonlinebattle_request(self, data: Dict, headers: Dict): + def handle_user_updateonlinebattle_request(self, data: Dict, headers: Dict): return { "status_code": "0", "bothwin_penalty": 1, @@ -2415,20 +2308,20 @@ class IDACSeason2(IDACBase): stock_data: Dict = data.pop("stock_obj") # save stock data in database self._save_stock_data(user_id, stock_data) - + ticket_data: List = data.pop("ticket_data") for ticket in ticket_data: self.data.item.put_ticket(user_id, ticket) - + reward_dist_data: Dict = data.pop("reward_dist_obj") rank_data: Dict = data.pop("mode_rank_obj") # save rank dist data in database rank_data.update(reward_dist_data) self.data.profile.put_profile_rank(user_id, self.version, rank_data) - + driver_debut_data = data.pop("driver_debut_obj") - + # get the use_count and net_vs_use_count of the used car style_car_id = data.get("style_car_id") car_mileage = data.pop("car_mileage") @@ -2441,7 +2334,7 @@ class IDACSeason2(IDACBase): # save the used car in database self.data.item.put_car(user_id, self.version, used_car) - + # get the profile data, update total_play and daily_play, and save it profile = self.data.profile.get_profile(user_id, self.version) total_play = profile["total_play"] + 1 @@ -2463,7 +2356,7 @@ class IDACSeason2(IDACBase): "avatar_point": data.pop("avatar_point"), }, ) - + self.data.item.put_vs_info(user_id, data) vs_info = { @@ -2484,7 +2377,7 @@ class IDACSeason2(IDACBase): } ], } - + return { "status_code": "0", "vsinfo_data": vs_info, @@ -2501,7 +2394,6 @@ class IDACSeason2(IDACBase): "maker_use_count": [], } - def handle_user_updatestorebattleresult_request(self, data: Dict, headers: Dict): user_id = headers["session"] From 4c3852d6d40eb7716c5f3740960b11f2d9e66bbc Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Mon, 6 Nov 2023 19:54:13 +0100 Subject: [PATCH 16/18] IDAC: Added round event "Season 2 2nd" --- titles/idac/season2.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/titles/idac/season2.py b/titles/idac/season2.py index 61109da..ca57392 100644 --- a/titles/idac/season2.py +++ b/titles/idac/season2.py @@ -152,12 +152,33 @@ class IDACSeason2(IDACBase): datetime.strptime("2029-01-01", "%Y-%m-%d").timestamp() ), "round_start_rank": 0, - "save_filename": "Round_Event_djg_Or_dpg", + "save_filename": "0", + # https://info-initialdac.sega.jp/1898/ "vscount": [ { "reward_upper_limit": 10, "reward_lower_limit": 10, - "reward": [{"reward_category": 1, "reward_type": 1}], + "reward": [{"reward_category": 21, "reward_type": 483}], + }, + { + "reward_upper_limit": 40, + "reward_lower_limit": 40, + "reward": [{"reward_category": 21, "reward_type": 484}], + }, + { + "reward_upper_limit": 80, + "reward_lower_limit": 80, + "reward": [{"reward_category": 22, "reward_type": 516}], + }, + { + "reward_upper_limit": 120, + "reward_lower_limit": 120, + "reward": [{"reward_category": 21, "reward_type": 461}], + }, + { + "reward_upper_limit": 180, + "reward_lower_limit": 180, + "reward": [{"reward_category": 21, "reward_type": 462}], } ], "rank": [], From e561f8f15d76e58f840813402c25945247a66a45 Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Mon, 13 Nov 2023 17:27:14 +0100 Subject: [PATCH 17/18] idac: updated to latest develop branch, minified timeRelease json --- titles/idac/data/timeRelease_v0100.json | Bin 1286433 -> 703770 bytes titles/idac/data/timeRelease_v0131.json | Bin 1863979 -> 1072598 bytes titles/idac/data/timeRelease_v0141.json | Bin 1864737 -> 1072936 bytes titles/idac/data/timeRelease_v0150.json | Bin 1354811 -> 1074358 bytes titles/idac/index.py | 105 ++++++++++++------------ 5 files changed, 52 insertions(+), 53 deletions(-) diff --git a/titles/idac/data/timeRelease_v0100.json b/titles/idac/data/timeRelease_v0100.json index 283693566dbccf0f631adb79e894d266e5c4dc0b..acb5209a0865e049f764e6af09ca17cff2565a5b 100644 GIT binary patch literal 703770 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 literal 1286433 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 DB4?_a diff --git a/titles/idac/data/timeRelease_v0131.json b/titles/idac/data/timeRelease_v0131.json index 184e6d272d6b16475ec524dc42e2f9339d2288cf..4798c30a89f04a4c8035317d003377f7e9ff5e46 100644 GIT binary patch literal 1072598 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 TkNo)j?x&BRmhb<+|M>p^$QS>3 literal 1863979 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 YjBa1w|7rTI-kf}^pC9Fa{qV>C4*`RJ(f|Me diff --git a/titles/idac/data/timeRelease_v0150.json b/titles/idac/data/timeRelease_v0150.json index 694c81957b003e3c2a834dcabe8505174834ce7a..539c138ecb366438140bda29cbf6742c9d097fca 100644 GIT binary patch literal 1074358 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 BVMqV~ literal 1354811 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 diff --git a/titles/idac/index.py b/titles/idac/index.py index 29ecb67..fb3890d 100644 --- a/titles/idac/index.py +++ b/titles/idac/index.py @@ -6,7 +6,7 @@ import logging import coloredlogs from os import path -from typing import Dict, Tuple +from typing import Dict, List, Tuple from logging.handlers import TimedRotatingFileHandler from twisted.web import server from twisted.web.http import Request @@ -26,9 +26,10 @@ class IDACServlet: def __init__(self, core_cfg: CoreConfig, cfg_dir: str) -> None: self.core_cfg = core_cfg self.game_cfg = IDACConfig() - self.game_cfg.update( - yaml.safe_load(open(f"{cfg_dir}/{IDACConstants.CONFIG_NAME}")) - ) + if path.exists(f"{cfg_dir}/{IDACConstants.CONFIG_NAME}"): + self.game_cfg.update( + yaml.safe_load(open(f"{cfg_dir}/{IDACConstants.CONFIG_NAME}")) + ) self.versions = [ IDACBase(core_cfg, self.game_cfg), @@ -59,9 +60,7 @@ class IDACServlet: ) @classmethod - def get_allnet_info( - cls, game_code: str, core_cfg: CoreConfig, cfg_dir: str - ) -> Tuple[bool, str, str]: + def is_game_enabled(cls, game_code: str, core_cfg: CoreConfig, cfg_dir: str) -> bool: game_cfg = IDACConfig() if path.exists(f"{cfg_dir}/{IDACConstants.CONFIG_NAME}"): @@ -70,28 +69,34 @@ class IDACServlet: ) if not game_cfg.server.enable: - return (False, "", "") - - if core_cfg.server.is_develop: - return ( - True, - f"", - # requires http or else it defautls to https - f"http://{core_cfg.title.hostname}:{core_cfg.title.port}/{game_code}/$v/", - ) + return False + + return True + def get_endpoint_matchers(self) -> Tuple[List[Tuple[str, str, Dict]], List[Tuple[str, str, Dict]]]: return ( - True, - f"", - # requires http or else it defautls to https - f"http://{core_cfg.title.hostname}/{game_code}/$v/", + [], + [("render_POST", "/SDGT/{version}/initiald/{category}/{endpoint}", {})] ) - def render_POST(self, request: Request, version: int, url_path: str) -> bytes: + def get_allnet_info( + self, game_code: str, game_ver: int, keychip: str + ) -> Tuple[bool, str, str]: + title_port_int = Utils.get_title_port(self.core_cfg) + t_port = f":{title_port_int}" if title_port_int != 80 and not self.core_cfg.server.is_using_proxy else "" + + return ( + f"", + # requires http or else it defaults to https + f"http://{self.core_cfg.title.hostname}{t_port}/{game_code}/{game_ver}/", + ) + + def render_POST(self, request: Request, game_code: int, matchers: Dict) -> bytes: req_raw = request.content.getvalue() - url_split = url_path.split("/") internal_ver = 0 - endpoint = url_split[len(url_split) - 1] + version = int(matchers['version']) + category = matchers['category'] + endpoint = matchers['endpoint'] client_ip = Utils.get_ip_addr(request) if version >= 100 and version < 140: # IDAC Season 1 @@ -99,45 +104,39 @@ class IDACServlet: elif version >= 140 and version < 171: # IDAC Season 2 internal_ver = IDACConstants.VER_IDAC_SEASON_2 - if url_split[0] == "initiald": - header_application = self.decode_header(request.getAllHeaders()) + header_application = self.decode_header(request.getAllHeaders()) - req_data = json.loads(req_raw) + req_data = json.loads(req_raw) - self.logger.info(f"v{version} {endpoint} request from {client_ip}") - self.logger.debug(f"Headers: {header_application}") - self.logger.debug(req_data) + self.logger.info(f"v{version} {endpoint} request from {client_ip}") + self.logger.debug(f"Headers: {header_application}") + self.logger.debug(req_data) - # func_to_find = "handle_" + inflection.underscore(endpoint) + "_request" - func_to_find = "handle_" - for x in url_split: - func_to_find += f"{x.lower()}_" if not x == "" and not x == "initiald" else "" - func_to_find += f"request" + # func_to_find = "handle_" + inflection.underscore(endpoint) + "_request" + func_to_find = "handle_" + func_to_find += f"{category.lower()}_" if not category == "" else "" + func_to_find += f"{endpoint.lower()}_request" - if not hasattr(self.versions[internal_ver], func_to_find): - self.logger.warning(f"Unhandled v{version} request {endpoint}") - return '{"status_code": "0"}'.encode("utf-8") + if not hasattr(self.versions[internal_ver], func_to_find): + self.logger.warning(f"Unhandled v{version} request {endpoint}") + return '{"status_code": "0"}'.encode("utf-8") - resp = None - try: - handler = getattr(self.versions[internal_ver], func_to_find) - resp = handler(req_data, header_application) + resp = None + try: + handler = getattr(self.versions[internal_ver], func_to_find) + resp = handler(req_data, header_application) - except Exception as e: - traceback.print_exc() - self.logger.error(f"Error handling v{version} method {endpoint} - {e}") - return '{"status_code": "0"}'.encode("utf-8") + except Exception as e: + traceback.print_exc() + self.logger.error(f"Error handling v{version} method {endpoint} - {e}") + return '{"status_code": "0"}'.encode("utf-8") - if resp is None: - resp = {"status_code": "0"} + if resp is None: + resp = {"status_code": "0"} - self.logger.debug(f"Response {resp}") - return json.dumps(resp, ensure_ascii=False).encode("utf-8") + self.logger.debug(f"Response {resp}") + return json.dumps(resp, ensure_ascii=False).encode("utf-8") - self.logger.warning( - f"IDAC unknown request {url_path} - {request.content.getvalue().decode()}" - ) - return '{"status_code": "0"}'.encode("utf-8") def decode_header(self, data: Dict) -> Dict: app: str = data[b"application"].decode() From d1a7b898a734025b2034c9bf278b173447156120 Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Mon, 13 Nov 2023 17:32:39 +0100 Subject: [PATCH 18/18] idac: hotfix for title port and changelog --- changelog.md | 14 +++++++------- titles/idac/index.py | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/changelog.md b/changelog.md index d33d08c..9ad97c5 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,13 @@ # Changelog Documenting updates to ARTEMiS, to be updated every time the master branch is pushed to. +## 20231015 +### maimai DX ++ Added support for FESTiVAL PLUS + +### Card Maker ++ Added support for maimai DX FESTiVAL PLUS + ## 20231001 ### Initial D THE ARCADE + Added support for Initial D THE ARCADE S2 @@ -13,13 +20,6 @@ Documenting updates to ARTEMiS, to be updated every time the master branch is pu + Frontend to download profile added + Importer to import profiles added -## 20231015 -### maimai DX -+ Added support for FESTiVAL PLUS - -### Card Maker -+ Added support for maimai DX FESTiVAL PLUS - ## 20230716 ### General + Docker files added (#19) diff --git a/titles/idac/index.py b/titles/idac/index.py index fb3890d..3080f50 100644 --- a/titles/idac/index.py +++ b/titles/idac/index.py @@ -83,7 +83,7 @@ class IDACServlet: self, game_code: str, game_ver: int, keychip: str ) -> Tuple[bool, str, str]: title_port_int = Utils.get_title_port(self.core_cfg) - t_port = f":{title_port_int}" if title_port_int != 80 and not self.core_cfg.server.is_using_proxy else "" + t_port = f":{title_port_int}" if title_port_int and not self.core_cfg.server.is_using_proxy else "" return ( f"",