From 1b5b9d7f9ad89928cef93475064a7701f2b35ef1 Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 11 Jun 2024 01:06:24 +0200 Subject: [PATCH 1/8] very basic diva frontend --- example_config/core.yaml | 6 +-- titles/diva/__init__.py | 2 + titles/diva/frontend.py | 52 ++++++++++++++++++++++++ titles/diva/templates/css/diva_style.css | 0 titles/diva/templates/diva_index.jinja | 15 +++++++ 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 titles/diva/frontend.py create mode 100644 titles/diva/templates/css/diva_style.css create mode 100644 titles/diva/templates/diva_index.jinja diff --git a/example_config/core.yaml b/example_config/core.yaml index 758a089..8f1ae3c 100644 --- a/example_config/core.yaml +++ b/example_config/core.yaml @@ -21,7 +21,7 @@ title: reboot_end_time: "05:00" database: - host: "localhost" + host: "192.168.192.12" username: "aime" password: "aime" name: "aime" @@ -33,7 +33,7 @@ database: memcached_host: "localhost" frontend: - enable: False + enable: True port: 8080 loglevel: "info" secret: "" @@ -58,7 +58,7 @@ aimedb: listen_address: "" loglevel: "info" port: 22345 - key: "" + key: "Copyright(C)SEGA" id_secret: "" id_lifetime_seconds: 86400 diff --git a/titles/diva/__init__.py b/titles/diva/__init__.py index d298ba2..7bfa2cc 100644 --- a/titles/diva/__init__.py +++ b/titles/diva/__init__.py @@ -2,8 +2,10 @@ from titles.diva.index import DivaServlet from titles.diva.const import DivaConstants from titles.diva.database import DivaData from titles.diva.read import DivaReader +from .frontend import DivaFrontend index = DivaServlet database = DivaData reader = DivaReader +frontend = DivaFrontend game_codes = [DivaConstants.GAME_CODE] diff --git a/titles/diva/frontend.py b/titles/diva/frontend.py new file mode 100644 index 0000000..ca93ca0 --- /dev/null +++ b/titles/diva/frontend.py @@ -0,0 +1,52 @@ +from typing import List +from starlette.routing import Route, Mount +from starlette.requests import Request +from starlette.responses import Response, RedirectResponse +from os import path +import yaml +import jinja2 + +from core.frontend import FE_Base, UserSession +from core.config import CoreConfig +from .database import DivaData +from .config import DivaConfig +from .const import DivaConstants + +class DivaFrontend(FE_Base): + def __init__( + self, cfg: CoreConfig, environment: jinja2.Environment, cfg_dir: str + ) -> None: + super().__init__(cfg, environment) + self.data = DivaData(cfg) + self.game_cfg = DivaConfig() + if path.exists(f"{cfg_dir}/{DivaConstants.CONFIG_NAME}"): + self.game_cfg.update( + yaml.safe_load(open(f"{cfg_dir}/{DivaConstants.CONFIG_NAME}")) + ) + self.nav_name = "diva" + + def get_routes(self) -> List[Route]: + return [ + Route("/", self.render_GET, methods=['GET']) + ] + + async def render_GET(self, request: Request) -> bytes: + template = self.environment.get_template( + "titles/diva/templates/diva_index.jinja" + ) + usr_sesh = self.validate_session(request) + if not usr_sesh: + usr_sesh = UserSession() + + if usr_sesh.user_id > 0: + profile = self.data.profile + + resp = Response(template.render( + title=f"{self.core_config.server.name} | {self.nav_name}", + game_list=self.environment.globals["game_list"], + sesh=vars(usr_sesh), + profile=profile + )) + return resp + else: + return RedirectResponse("/login") \ No newline at end of file diff --git a/titles/diva/templates/css/diva_style.css b/titles/diva/templates/css/diva_style.css new file mode 100644 index 0000000..e69de29 diff --git a/titles/diva/templates/diva_index.jinja b/titles/diva/templates/diva_index.jinja new file mode 100644 index 0000000..aa698b4 --- /dev/null +++ b/titles/diva/templates/diva_index.jinja @@ -0,0 +1,15 @@ +{% extends "core/templates/index.jinja" %} +{% block content %} + + +
+
+
+

{{ title }}

+

{{ description }}

+
+
+
+{% endblock %} \ No newline at end of file From 1f9c1798c47d7622a0092c0304a0676699ebb39b Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 11 Jun 2024 21:48:34 +0200 Subject: [PATCH 2/8] Basic working diva frontend with name editing and lv string editing. Working on playlog page --- titles/diva/frontend.py | 138 +++++++++++++++- titles/diva/schema/profile.py | 2 +- titles/diva/schema/score.py | 20 +++ titles/diva/templates/css/diva_style.css | 195 +++++++++++++++++++++++ titles/diva/templates/diva_header.jinja | 17 ++ titles/diva/templates/diva_index.jinja | 92 ++++++++++- titles/diva/templates/diva_playlog.jinja | 114 +++++++++++++ 7 files changed, 569 insertions(+), 9 deletions(-) create mode 100644 titles/diva/templates/diva_header.jinja create mode 100644 titles/diva/templates/diva_playlog.jinja diff --git a/titles/diva/frontend.py b/titles/diva/frontend.py index ca93ca0..2015c22 100644 --- a/titles/diva/frontend.py +++ b/titles/diva/frontend.py @@ -27,7 +27,13 @@ class DivaFrontend(FE_Base): def get_routes(self) -> List[Route]: return [ - Route("/", self.render_GET, methods=['GET']) + Route("/", self.render_GET, methods=['GET']), + Mount("/playlog", routes=[ + Route("/", self.render_GET_playlog, methods=['GET']), + Route("/{index}", self.render_GET_playlog, methods=['GET']), + ]), + Route("/update.name", self.update_name, methods=['POST']), + Route("/update.lv", self.update_lv, methods=['POST']), ] async def render_GET(self, request: Request) -> bytes: @@ -39,14 +45,138 @@ class DivaFrontend(FE_Base): usr_sesh = UserSession() if usr_sesh.user_id > 0: - profile = self.data.profile + profile = await self.data.profile.get_profile(usr_sesh.user_id, 1) resp = Response(template.render( title=f"{self.core_config.server.name} | {self.nav_name}", game_list=self.environment.globals["game_list"], sesh=vars(usr_sesh), + user_id=usr_sesh.user_id, profile=profile - )) + ), media_type="text/html; charset=utf-8") return resp else: - return RedirectResponse("/login") \ No newline at end of file + return RedirectResponse("/login") + + async def render_GET_playlog(self, request: Request) -> bytes: + template = self.environment.get_template( + "titles/diva/templates/diva_playlog.jinja" + ) + usr_sesh = self.validate_session(request) + if not usr_sesh: + usr_sesh = UserSession() + + if usr_sesh.user_id > 0: + path_index = request.path_params.get("index") + if not path_index or int(path_index) < 1: + index = 0 + else: + index = int(path_index) - 1 # 0 and 1 are 1st page + user_id = usr_sesh.user_id + playlog_count = await self.data.score.get_user_playlogs_count(user_id) + if playlog_count < index * 20 : + return Response(template.render( + title=f"{self.core_config.server.name} | {self.nav_name}", + game_list=self.environment.globals["game_list"], + sesh=vars(usr_sesh), + score_count=0 + ), media_type="text/html; charset=utf-8") + playlog = await self.data.score.get_playlogs(user_id, index, 20) #Maybe change to the playlog instead of direct scores + playlog_with_title = [] + for record in playlog: + song = await self.data.static.get_music_chart(record[2], record[3], record[4]) + if song: + title = song[4] + artist = song[5] + else: + title = "Unknown" + artist = "Unknown" + playlog_with_title.append({ + "raw": record, + "title": title, + "artist": artist + }) + return Response(template.render( + title=f"{self.core_config.server.name} | {self.nav_name}", + game_list=self.environment.globals["game_list"], + sesh=vars(usr_sesh), + user_id=usr_sesh.user_id, + playlog=playlog_with_title, + playlog_count=playlog_count + ), media_type="text/html; charset=utf-8") + else: + return RedirectResponse("/gate/", 300) + + async def update_name(self, request: Request) -> Response: + usr_sesh = self.validate_session(request) + if not usr_sesh: + return RedirectResponse("/login") + + form_data = await request.form() + new_name: str = form_data.get("new_name") + new_name_full = "" + + if not new_name: + return RedirectResponse("/gate/?e=4", 303) + + if len(new_name) > 8: + return RedirectResponse("/gate/?e=8", 303) + + for x in new_name: # FIXME: This will let some invalid characters through atm + o = ord(x) + try: + if o == 0x20: + new_name_full += chr(0x3000) + elif o < 0x7F and o > 0x20: + new_name_full += chr(o + 0xFEE0) + elif o <= 0x7F: + self.logger.warn(f"Invalid ascii character {o:02X}") + return RedirectResponse("/gate/?e=4", 303) + else: + new_name_full += x + + except Exception as e: + self.logger.error(f"Something went wrong parsing character {o:04X} - {e}") + return RedirectResponse("/gate/?e=4", 303) + + if not await self.data.profile.update_profile(usr_sesh.user_id, player_name=new_name_full): + return RedirectResponse("/gate/?e=999", 303) + + return RedirectResponse("/game/diva", 303) + + async def update_lv(self, request: Request) -> Response: + usr_sesh = self.validate_session(request) + if not usr_sesh: + return RedirectResponse("/login") + + form_data = await request.form() + new_lv: str = form_data.get("new_lv") + new_lv_full = "" + + if not new_lv: + return RedirectResponse("/gate/?e=4", 303) + + if len(new_lv) > 8: + return RedirectResponse("/gate/?e=8", 303) + + for x in new_lv: # FIXME: This will let some invalid characters through atm + o = ord(x) + try: + if o == 0x20: + new_lv_full += chr(0x3000) + elif o < 0x7F and o > 0x20: + new_lv_full += chr(o + 0xFEE0) + elif o <= 0x7F: + self.logger.warn(f"Invalid ascii character {o:02X}") + return RedirectResponse("/gate/?e=4", 303) + else: + new_lv_full += x + + except Exception as e: + self.logger.error(f"Something went wrong parsing character {o:04X} - {e}") + return RedirectResponse("/gate/?e=4", 303) + + if not await self.data.profile.update_profile(usr_sesh.user_id, lv_str=new_lv_full): + return RedirectResponse("/gate/?e=999", 303) + + return RedirectResponse("/game/diva", 303) diff --git a/titles/diva/schema/profile.py b/titles/diva/schema/profile.py index f3d00ae..06e20be 100644 --- a/titles/diva/schema/profile.py +++ b/titles/diva/schema/profile.py @@ -102,7 +102,7 @@ class DivaProfileData(BaseData): self.logger.error( f"update_profile: failed to update profile! profile: {aime_id}" ) - return None + return result async def get_profile(self, aime_id: int, version: int) -> Optional[List[Dict]]: """ diff --git a/titles/diva/schema/score.py b/titles/diva/schema/score.py index e802a41..65ff99c 100644 --- a/titles/diva/schema/score.py +++ b/titles/diva/schema/score.py @@ -239,3 +239,23 @@ class DivaScoreData(BaseData): if result is None: return None return result.fetchall() + + async def get_playlogs(self, user_id: int, idx: int = 0, limit: int = 0) -> Optional[List[Row]]: + sql = playlog.select(playlog.c.user == user_id) + + if limit: + sql = sql.limit(limit) + if idx: + sql = sql.offset(idx) + + result = await self.execute(sql) + if result: + return result.fetchall() + + async def get_user_playlogs_count(self, aime_id: int) -> Optional[int]: + sql = select(func.count()).where(playlog.c.user == aime_id) + result = await self.execute(sql) + if result is None: + self.logger.warning(f"aimu_id {aime_id} has no scores ") + return None + return result.scalar() diff --git a/titles/diva/templates/css/diva_style.css b/titles/diva/templates/css/diva_style.css index e69de29..672db0f 100644 --- a/titles/diva/templates/css/diva_style.css +++ b/titles/diva/templates/css/diva_style.css @@ -0,0 +1,195 @@ +.diva-header { + text-align: center; +} + +ul.diva-navi { + list-style-type: none; + padding: 0; + overflow: hidden; + background-color: #333; + text-align: center; + display: inline-block; +} + +ul.diva-navi li { + display: inline-block; +} + +ul.diva-navi li a { + display: block; + color: white; + text-align: center; + padding: 14px 16px; + text-decoration: none; +} + +ul.diva-navi li a:hover:not(.active) { + background-color: #111; +} + +ul.diva-navi li a.active { + background-color: #4CAF50; +} + +ul.diva-navi li.right { + float: right; +} + +@media screen and (max-width: 600px) { + + ul.diva-navi li.right, + ul.diva-navi li { + float: none; + display: block; + text-align: center; + } +} + +table { + border-collapse: collapse; + border-spacing: 0; + border-collapse: separate; + overflow: hidden; + background-color: #555555; + +} + +th, td { + text-align: left; + border: none; + +} + +th { + color: white; +} + +.table-rowdistinct tr:nth-child(even) { + background-color: #303030; +} + +.table-rowdistinct tr:nth-child(odd) { + background-color: #555555; +} + +caption { + text-align: center; + color: white; + font-size: 18px; + font-weight: bold; +} + +.table-large { + margin: 16px; +} + +.table-large th, +.table-large td { + padding: 8px; +} + +.table-small { + width: 100%; + margin: 4px; +} + +.table-small th, +.table-small td { + padding: 2px; +} + +.bg-card { + background-color: #555555; +} + +.card-hover { + transition: all 0.2s ease-in-out; +} + +.card-hover:hover { + transform: scale(1.02); +} + +.basic { + color: #28a745; + font-weight: bold; +} + +.hard { + color: #ffc107; + + font-weight: bold; +} + +.expert { + color: #dc3545; + font-weight: bold; +} + +.master { + color: #dd09e8; + font-weight: bold; +} + +.ultimate { + color: #000000; + font-weight: bold; +} + +.score { + color: #ffffff; + font-weight: bold; +} + +.rainbow { + background: linear-gradient(to right, red, yellow, lime, aqua, blue, fuchsia) 0 / 5em; + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-weight: bold; +} + +.platinum { + color: #FFFF00; + font-weight: bold; +} + +.gold { + color: #FFFF00; + font-weight: bold; +} + +.scrolling-text { + overflow: hidden; +} + +.scrolling-text p { + white-space: nowrap; + display: inline-block; + +} + +.scrolling-text h6 { + white-space: nowrap; + display: inline-block; + +} + +.scrolling-text h5 { + white-space: nowrap; + display: inline-block; + +} + +.scrolling { + animation: scroll 10s linear infinite; +} + +@keyframes scroll { + 0% { + transform: translateX(100%); + } + 100% { + transform: translateX(-100%); + } +} \ No newline at end of file diff --git a/titles/diva/templates/diva_header.jinja b/titles/diva/templates/diva_header.jinja new file mode 100644 index 0000000..b92379a --- /dev/null +++ b/titles/diva/templates/diva_header.jinja @@ -0,0 +1,17 @@ +
+

diva

+ +
+ \ No newline at end of file diff --git a/titles/diva/templates/diva_index.jinja b/titles/diva/templates/diva_index.jinja index aa698b4..0cba3f4 100644 --- a/titles/diva/templates/diva_index.jinja +++ b/titles/diva/templates/diva_index.jinja @@ -3,12 +3,96 @@ -
+ {% include 'titles/diva/templates/diva_header.jinja' %} + {% if profile is defined and profile is not none and profile|length > 0 %}
-
-

{{ title }}

-

{{ description }}

+
+
+ + + + + + + + + + + + + + + + + + + + + + +
OVERVIEW
Player name:{{ profile[3] }} + + Level string:{{ profile[4] }} + +
Lvl:{{ profile[5] }}
Lvl points:{{ profile[6] }}
Vocaloid points:{{ profile[7] }}
+
+
+
+ {% if error is defined %} + {% include "core/templates/widgets/err_banner.jinja" %} + {% endif %} + {% elif sesh is defined and sesh is not none and sesh.user_id > 0 %} + No profile information found for this account. + {% else %} + Login to view profile information. + {% endif %} +
+ + diff --git a/titles/diva/templates/diva_playlog.jinja b/titles/diva/templates/diva_playlog.jinja new file mode 100644 index 0000000..cb63a00 --- /dev/null +++ b/titles/diva/templates/diva_playlog.jinja @@ -0,0 +1,114 @@ +{% extends "core/templates/index.jinja" %} +{% block content %} + +
+ {% include 'titles/diva/templates/diva_header.jinja' %} + {% if playlog is defined and playlog is not none %} +
+

Score counts: {{ playlog_count }}

+ {% set difficultyName = ['easy', 'normal', 'hard', 'extreme', 'extra extreme'] %} + {% for record in playlog %} +
+
+
+
{{ record.title }}
+
+
{{ record.artist }}
+
+
+
{{ difficultyName[record.raw[4]] }}
+
+
+
+ {% endfor %} +
+ {% set playlog_pages = playlog_count // 20 + 1 %} + {% elif sesh is defined and sesh is not none and sesh.user_id > 0 %} + No Score information found for this account. + {% else %} + Login to view profile information. + {% endif %} +
+ + + +{% endblock content %} \ No newline at end of file From 7d8093bb5403840d34b8f55f2c25c7e511f47c5b Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 11 Jun 2024 21:56:29 +0200 Subject: [PATCH 3/8] accidentally changed example config --- example_config/core.yaml | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/example_config/core.yaml b/example_config/core.yaml index 8f1ae3c..21b1a9d 100644 --- a/example_config/core.yaml +++ b/example_config/core.yaml @@ -1,66 +1,65 @@ server: - listen_address: "127.0.0.1" - hostname: "localhost" - port: 80 - ssl_key: "cert/title.key" - ssl_cert: "cert/title.crt" + listen_address: "127.0.0.1" allow_user_registration: True allow_unregistered_serials: True name: "ARTEMiS" is_develop: True is_using_proxy: False - proxy_port: 0 - proxy_port_ssl: 0 + threading: False log_dir: "logs" check_arcade_ip: False strict_ip_checking: False title: loglevel: "info" + hostname: "localhost" + port: 8080 + port_ssl: 0 + ssl_cert: "cert/title.crt" + ssl_key: "cert/title.key" reboot_start_time: "04:00" reboot_end_time: "05:00" + database: - host: "192.168.192.12" + host: "localhost" username: "aime" password: "aime" name: "aime" port: 3306 protocol: "mysql" sha2_password: False - loglevel: "info" + loglevel: "warn" + user_table_autoincrement_start: 10000 enable_memcached: True memcached_host: "localhost" frontend: - enable: True - port: 8080 + enable: False + port: 8090 loglevel: "info" - secret: "" allnet: - standalone: False - port: 80 loglevel: "info" + port: 80 + ip_check: False allow_online_updates: False update_cfg_folder: "" billing: - standalone: True - loglevel: "info" port: 8443 ssl_key: "cert/server.key" ssl_cert: "cert/server.pem" signing_key: "cert/billing.key" aimedb: - enable: True - listen_address: "" loglevel: "info" port: 22345 - key: "Copyright(C)SEGA" + key: "" id_secret: "" id_lifetime_seconds: 86400 mucha: + enable: False + hostname: "localhost" loglevel: "info" From da55e3e877f53492ddd45301730a8c6d9d105e1d Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 11 Jun 2024 21:57:40 +0200 Subject: [PATCH 4/8] develop branch config --- example_config/core.yaml | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/example_config/core.yaml b/example_config/core.yaml index 21b1a9d..758a089 100644 --- a/example_config/core.yaml +++ b/example_config/core.yaml @@ -1,26 +1,25 @@ server: - listen_address: "127.0.0.1" + listen_address: "127.0.0.1" + hostname: "localhost" + port: 80 + ssl_key: "cert/title.key" + ssl_cert: "cert/title.crt" allow_user_registration: True allow_unregistered_serials: True name: "ARTEMiS" is_develop: True is_using_proxy: False - threading: False + proxy_port: 0 + proxy_port_ssl: 0 log_dir: "logs" check_arcade_ip: False strict_ip_checking: False title: loglevel: "info" - hostname: "localhost" - port: 8080 - port_ssl: 0 - ssl_cert: "cert/title.crt" - ssl_key: "cert/title.key" reboot_start_time: "04:00" reboot_end_time: "05:00" - database: host: "localhost" username: "aime" @@ -29,30 +28,34 @@ database: port: 3306 protocol: "mysql" sha2_password: False - loglevel: "warn" - user_table_autoincrement_start: 10000 + loglevel: "info" enable_memcached: True memcached_host: "localhost" frontend: enable: False - port: 8090 + port: 8080 loglevel: "info" + secret: "" allnet: - loglevel: "info" + standalone: False port: 80 - ip_check: False + loglevel: "info" allow_online_updates: False update_cfg_folder: "" billing: + standalone: True + loglevel: "info" port: 8443 ssl_key: "cert/server.key" ssl_cert: "cert/server.pem" signing_key: "cert/billing.key" aimedb: + enable: True + listen_address: "" loglevel: "info" port: 22345 key: "" @@ -60,6 +63,4 @@ aimedb: id_lifetime_seconds: 86400 mucha: - enable: False - hostname: "localhost" loglevel: "info" From d456ed365cf69233eae2095d1b6355c661148ccd Mon Sep 17 00:00:00 2001 From: = <=> Date: Sun, 16 Jun 2024 14:08:59 +0200 Subject: [PATCH 5/8] Working diva frontend --- changelog.md | 4 ++ titles/diva/frontend.py | 14 ++--- titles/diva/schema/score.py | 4 +- titles/diva/templates/diva_index.jinja | 12 +++++ titles/diva/templates/diva_playlog.jinja | 67 +++++++++++++++++++++--- 5 files changed, 86 insertions(+), 15 deletions(-) diff --git a/changelog.md b/changelog.md index 3f8c6ba..c00c489 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,10 @@ # Changelog Documenting updates to ARTEMiS, to be updated every time the master branch is pushed to. +## 20240616 +### DIVA ++ Working frontend with name and level strings edit and playlog + ## 20240530 ### DIVA + Fix reader for when dificulty is not a int diff --git a/titles/diva/frontend.py b/titles/diva/frontend.py index 2015c22..cc5c332 100644 --- a/titles/diva/frontend.py +++ b/titles/diva/frontend.py @@ -56,7 +56,7 @@ class DivaFrontend(FE_Base): ), media_type="text/html; charset=utf-8") return resp else: - return RedirectResponse("/login") + return RedirectResponse("/gate") async def render_GET_playlog(self, request: Request) -> bytes: template = self.environment.get_template( @@ -86,15 +86,15 @@ class DivaFrontend(FE_Base): for record in playlog: song = await self.data.static.get_music_chart(record[2], record[3], record[4]) if song: - title = song[4] - artist = song[5] + title = song.title + vocaloid_arranger = song.vocaloid_arranger else: title = "Unknown" - artist = "Unknown" + vocaloid_arranger = "Unknown" playlog_with_title.append({ "raw": record, "title": title, - "artist": artist + "vocaloid_arranger": vocaloid_arranger }) return Response(template.render( title=f"{self.core_config.server.name} | {self.nav_name}", @@ -110,7 +110,7 @@ class DivaFrontend(FE_Base): async def update_name(self, request: Request) -> Response: usr_sesh = self.validate_session(request) if not usr_sesh: - return RedirectResponse("/login") + return RedirectResponse("/gate") form_data = await request.form() new_name: str = form_data.get("new_name") @@ -147,7 +147,7 @@ class DivaFrontend(FE_Base): async def update_lv(self, request: Request) -> Response: usr_sesh = self.validate_session(request) if not usr_sesh: - return RedirectResponse("/login") + return RedirectResponse("/gate") form_data = await request.form() new_lv: str = form_data.get("new_lv") diff --git a/titles/diva/schema/score.py b/titles/diva/schema/score.py index 65ff99c..ce89f74 100644 --- a/titles/diva/schema/score.py +++ b/titles/diva/schema/score.py @@ -240,8 +240,8 @@ class DivaScoreData(BaseData): return None return result.fetchall() - async def get_playlogs(self, user_id: int, idx: int = 0, limit: int = 0) -> Optional[List[Row]]: - sql = playlog.select(playlog.c.user == user_id) + async def get_playlogs(self, aime_id: int, idx: int = 0, limit: int = 0) -> Optional[Row]: + sql = select(playlog).where(playlog.c.user == aime_id).order_by(playlog.c.date_scored.desc()) if limit: sql = sql.limit(limit) diff --git a/titles/diva/templates/diva_index.jinja b/titles/diva/templates/diva_index.jinja index 0cba3f4..c2f0888 100644 --- a/titles/diva/templates/diva_index.jinja +++ b/titles/diva/templates/diva_index.jinja @@ -28,14 +28,26 @@ Lvl: {{ profile[5] }} + + + + Lvl points: {{ profile[6] }} + + + + Vocaloid points: {{ profile[7] }} + + + +
diff --git a/titles/diva/templates/diva_playlog.jinja b/titles/diva/templates/diva_playlog.jinja index cb63a00..c5a5618 100644 --- a/titles/diva/templates/diva_playlog.jinja +++ b/titles/diva/templates/diva_playlog.jinja @@ -9,17 +9,72 @@

Score counts: {{ playlog_count }}

{% set difficultyName = ['easy', 'normal', 'hard', 'extreme', 'extra extreme'] %} + {% set clearState = ['MISSxTAKE', 'STANDARD', 'GREAT', 'EXELLENT', 'PERFECT'] %} {% for record in playlog %}
-
-
{{ record.title }}
-
-
{{ record.artist }}
+
+
+
+
{{ record.title }}
+
+
{{ record.vocaloid_arranger }}
+
+
+
{{record.raw.date_scored}}
+
-
-
{{ difficultyName[record.raw[4]] }}
+
+
+

{{ record.raw.score }}

+

{{ record.raw.atn_pnt / 100 }}%

+
{{ difficultyName[record.raw.difficulty] }}
+
+
+ + + + + + + + + + + + + + + + + + + + + +
COOL{{ record.raw.cool }}
FINE{{ record.raw.fine }}
SAFE{{ record.raw.safe }}
SAD{{ record.raw.sad }}
WORST{{ record.raw.worst }}
+
+
+
{{ record.raw.max_combo }}
+ {% if record.raw.clr_kind == -1 %} +
{{ clearState[0] }}
+ {% elif record.raw.clr_kind == 2 %} +
{{ clearState[1] }}
+ {% elif record.raw.clr_kind == 3 %} +
{{ clearState[2] }}
+ {% elif record.raw.clr_kind == 4 %} +
{{ clearState[3] }}
+ {% elif record.raw.clr_kind == 5 %} +
{{ clearState[4] }}
+ {% endif %} + {% if record.raw.clr_kind == -1 %} +
NOT CLEAR
+ {% else %} +
CLEAR
+ {% endif %} +
+
{% endfor %} From a6ca1b33928aaffa051668385fd0fd9679a2fdf9 Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 17 Jun 2024 22:23:53 +0200 Subject: [PATCH 6/8] Changed return from full result to just True or False --- titles/diva/schema/profile.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/titles/diva/schema/profile.py b/titles/diva/schema/profile.py index 06e20be..10d3b51 100644 --- a/titles/diva/schema/profile.py +++ b/titles/diva/schema/profile.py @@ -90,7 +90,7 @@ class DivaProfileData(BaseData): return None return result.lastrowid - async def update_profile(self, aime_id: int, **profile_args) -> None: + async def update_profile(self, aime_id: int, **profile_args) -> bool: """ Given an aime_id update the profile corresponding to the arguments which are the diva_profile Columns @@ -102,7 +102,9 @@ class DivaProfileData(BaseData): self.logger.error( f"update_profile: failed to update profile! profile: {aime_id}" ) - return result + return False + + return True async def get_profile(self, aime_id: int, version: int) -> Optional[List[Dict]]: """ From e0e63a9a13070d271e0f01dfdf5d033ac5a3d978 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sun, 30 Jun 2024 00:23:10 +0200 Subject: [PATCH 7/8] configurable festa options --- changelog.md | 4 ++++ docs/game_specific_info.md | 12 ++++++++---- example_config/diva.yaml | 4 ++++ titles/diva/base.py | 11 ++++++++--- titles/diva/config.py | 23 +++++++++++++++++++++++ 5 files changed, 47 insertions(+), 7 deletions(-) diff --git a/changelog.md b/changelog.md index 8148a9d..08b5b6d 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,10 @@ # Changelog Documenting updates to ARTEMiS, to be updated every time the master branch is pushed to. +## 20240630 +### DIVA ++ Added configurable festa options + ## 20240620 ### CHUNITHM + CHUNITHM LUMINOUS support diff --git a/docs/game_specific_info.md b/docs/game_specific_info.md index 53c076c..158930e 100644 --- a/docs/game_specific_info.md +++ b/docs/game_specific_info.md @@ -255,10 +255,14 @@ 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 | +| Option | Info | +| -------------------- | ------------------------------------------------------------------------------------------------ | +| `festaEnable` | Enable or disable the ingame festa | +| `festaAddVP` | Set the extra VP you get when clearing a song, if festa is not enabled no extra VP will be given | +| `festaMultiplyVP` | Multiplier for festa add VP | +| `festaEndTime` | Set the date time for when festa will end and not show up in game anymore | +| `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 | ### Custom PV Lists (databanks) diff --git a/example_config/diva.yaml b/example_config/diva.yaml index ad1842a..465ab93 100644 --- a/example_config/diva.yaml +++ b/example_config/diva.yaml @@ -1,6 +1,10 @@ server: enable: True loglevel: "info" + festaEnable: True + festaAddVP: "20,5" + festaMultiplyVP: "1,2" + festaEndTime: "2029-01-01 00:00:00.0" mods: unlock_all_modules: True diff --git a/titles/diva/base.py b/titles/diva/base.py index 3b96848..e07c81d 100644 --- a/titles/diva/base.py +++ b/titles/diva/base.py @@ -264,6 +264,11 @@ class DivaBase: return response async def handle_festa_info_request(self, data: Dict) -> Dict: + if self.game_config.server.festaEnable: + festa_end_time = self.game_config.server.festaEndTime + else: + festa_end_time = (datetime.datetime.now() + datetime.timedelta(days=365*2)).strftime("%Y-%m-%d %H:%M:%S") + ".0" + encoded = "&" params = { "fi_id": "1,2", @@ -273,10 +278,10 @@ class DivaBase: "fi_difficulty": "-1,-1", "fi_pv_id_lst": "ALL,ALL", "fi_attr": "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - "fi_add_vp": "20,5", - "fi_mul_vp": "1,2", + "fi_add_vp": f"{self.game_config.server.festaAddVP}", + "fi_mul_vp": f"{self.game_config.server.festaMultiplyVP}", "fi_st": "2019-01-01 00:00:00.0,2019-01-01 00:00:00.0", - "fi_et": "2029-01-01 00:00:00.0,2029-01-01 00:00:00.0", + "fi_et": f"{festa_end_time},{festa_end_time}", "fi_lut": "{self.time_lut}", } diff --git a/titles/diva/config.py b/titles/diva/config.py index efa327e..269041a 100644 --- a/titles/diva/config.py +++ b/titles/diva/config.py @@ -19,6 +19,29 @@ class DivaServerConfig: ) ) + @property + def festaEnable(self) -> bool: + return CoreConfig.get_config_field( + self.__config, "diva", "server", "festaEnable", default=True + ) + + @property + def festaAddVP(self) -> str: + return CoreConfig.get_config_field( + self.__config, "diva", "server", "festaAddVP", default="20,5" + ) + + @property + def festaMultiplyVP(self) -> str: + return CoreConfig.get_config_field( + self.__config, "diva", "server", "festaMultiplyVP", default="1,2" + ) + + @property + def festaEndTime(self) -> str: + return CoreConfig.get_config_field( + self.__config, "diva", "server", "festaEndTime", default="2029-01-01 00:00:00.0" + ) class DivaModsConfig: def __init__(self, parent_config: "DivaConfig") -> None: From 97e1d5da058953491cc71cd54359e4cfdbbb2bda Mon Sep 17 00:00:00 2001 From: = <=> Date: Sun, 30 Jun 2024 12:54:44 +0200 Subject: [PATCH 8/8] fix disable. Fix casing in options --- docs/game_specific_info.md | 8 ++++---- example_config/diva.yaml | 8 ++++---- titles/diva/base.py | 10 +++++----- titles/diva/config.py | 16 ++++++++-------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/game_specific_info.md b/docs/game_specific_info.md index ecd92e2..33d5710 100644 --- a/docs/game_specific_info.md +++ b/docs/game_specific_info.md @@ -271,10 +271,10 @@ Config file is located in `config/diva.yaml`. | Option | Info | | -------------------- | ------------------------------------------------------------------------------------------------ | -| `festaEnable` | Enable or disable the ingame festa | -| `festaAddVP` | Set the extra VP you get when clearing a song, if festa is not enabled no extra VP will be given | -| `festaMultiplyVP` | Multiplier for festa add VP | -| `festaEndTime` | Set the date time for when festa will end and not show up in game anymore | +| `festa_enable` | Enable or disable the ingame festa | +| `festa_add_VP` | Set the extra VP you get when clearing a song, if festa is not enabled no extra VP will be given | +| `festa_multiply_VP` | Multiplier for festa add VP | +| `festa_end_time` | Set the date time for when festa will end and not show up in game anymore | | `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 | diff --git a/example_config/diva.yaml b/example_config/diva.yaml index 465ab93..7b8bdcb 100644 --- a/example_config/diva.yaml +++ b/example_config/diva.yaml @@ -1,10 +1,10 @@ server: enable: True loglevel: "info" - festaEnable: True - festaAddVP: "20,5" - festaMultiplyVP: "1,2" - festaEndTime: "2029-01-01 00:00:00.0" + festa_enable: True + festa_add_VP: "20,5" + festa_multiply_VP: "1,2" + festa_end_time: "2029-01-01 00:00:00.0" mods: unlock_all_modules: True diff --git a/titles/diva/base.py b/titles/diva/base.py index e07c81d..be7a241 100644 --- a/titles/diva/base.py +++ b/titles/diva/base.py @@ -264,10 +264,10 @@ class DivaBase: return response async def handle_festa_info_request(self, data: Dict) -> Dict: - if self.game_config.server.festaEnable: - festa_end_time = self.game_config.server.festaEndTime + if self.game_config.server.festa_enable: + festa_end_time = self.game_config.server.festa_end_time else: - festa_end_time = (datetime.datetime.now() + datetime.timedelta(days=365*2)).strftime("%Y-%m-%d %H:%M:%S") + ".0" + festa_end_time = (datetime.datetime.now() - datetime.timedelta(days=365)).strftime("%Y-%m-%d %H:%M:%S") + ".0" encoded = "&" params = { @@ -278,8 +278,8 @@ class DivaBase: "fi_difficulty": "-1,-1", "fi_pv_id_lst": "ALL,ALL", "fi_attr": "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - "fi_add_vp": f"{self.game_config.server.festaAddVP}", - "fi_mul_vp": f"{self.game_config.server.festaMultiplyVP}", + "fi_add_vp": f"{self.game_config.server.festa_add_VP}", + "fi_mul_vp": f"{self.game_config.server.festa_multiply_VP}", "fi_st": "2019-01-01 00:00:00.0,2019-01-01 00:00:00.0", "fi_et": f"{festa_end_time},{festa_end_time}", "fi_lut": "{self.time_lut}", diff --git a/titles/diva/config.py b/titles/diva/config.py index 269041a..48b5c0f 100644 --- a/titles/diva/config.py +++ b/titles/diva/config.py @@ -20,27 +20,27 @@ class DivaServerConfig: ) @property - def festaEnable(self) -> bool: + def festa_enable(self) -> bool: return CoreConfig.get_config_field( - self.__config, "diva", "server", "festaEnable", default=True + self.__config, "diva", "server", "festa_enable", default=True ) @property - def festaAddVP(self) -> str: + def festa_add_VP(self) -> str: return CoreConfig.get_config_field( - self.__config, "diva", "server", "festaAddVP", default="20,5" + self.__config, "diva", "server", "festa_add_VP", default="20,5" ) @property - def festaMultiplyVP(self) -> str: + def festa_multiply_VP(self) -> str: return CoreConfig.get_config_field( - self.__config, "diva", "server", "festaMultiplyVP", default="1,2" + self.__config, "diva", "server", "festa_multiply_VP", default="1,2" ) @property - def festaEndTime(self) -> str: + def festa_end_time(self) -> str: return CoreConfig.get_config_field( - self.__config, "diva", "server", "festaEndTime", default="2029-01-01 00:00:00.0" + self.__config, "diva", "server", "festa_end_time", default="2029-01-01 00:00:00.0" ) class DivaModsConfig: