feat(db): recommend charts based on score

This commit is contained in:
283375 2023-09-18 20:41:57 +08:00
parent bed9e14368
commit ec9926993c
Signed by: 283375
SSH Key Fingerprint: SHA256:UcX0qg6ZOSDOeieKPGokA5h7soykG61nz2uxuQgVLSk
2 changed files with 52 additions and 1 deletions

View File

@ -1,2 +1,13 @@
from .b30 import calculate_b30, get_b30_calculated_list
from .score import calculate_play_rating, calculate_score_range, calculate_shiny_pure
from .score import (
calculate_constants_from_play_rating,
calculate_play_rating,
calculate_score_modifier,
calculate_score_range,
calculate_shiny_pure,
)
from .world_step import (
calculate_play_rating_from_step,
calculate_step,
calculate_step_original,
)

View File

@ -1,9 +1,11 @@
import logging
import math
from typing import Iterable, List, Optional, Type, Union
from sqlalchemy import Engine, func, inspect, select
from sqlalchemy.orm import DeclarativeBase, InstrumentedAttribute, sessionmaker
from .calculate import calculate_score_modifier
from .external.arcsong.arcsong_json import ArcSongJsonBuilder
from .external.exports import ScoreExport, exporters
from .models.config import *
@ -227,6 +229,12 @@ class Database(metaclass=Singleton):
results = list(session.scalars(stmt))
return results
def get_charts_by_constant(self, constant: int):
stmt = select(Chart).where(Chart.constant == constant)
with self.sessionmaker() as session:
results = list(session.scalars(stmt))
return results
def get_chart(self, song_id: str, rating_class: int):
stmt = select(Chart).where(
(Chart.song_id == song_id) & (Chart.rating_class == rating_class)
@ -275,6 +283,38 @@ class Database(metaclass=Singleton):
session.delete(score)
session.commit()
def recommend_charts(self, play_result: float):
base_constant = math.ceil(play_result * 10)
results = []
results_id = []
with self.sessionmaker() as session:
for constant in range(base_constant - 20, base_constant + 1):
# from Pure Memory(EX+) to AA
score_modifier = (play_result * 10 - constant) / 10
if score_modifier >= 2.0:
min_score = 10000000
elif score_modifier >= 1.0:
min_score = 200000 * (score_modifier - 1) + 9800000
else:
min_score = 300000 * score_modifier + 9500000
min_score = int(min_score)
charts = self.get_charts_by_constant(constant)
for chart in charts:
score_best_stmt = select(ScoreBest).where(
(ScoreBest.song_id == chart.song_id)
& (ScoreBest.rating_class == chart.rating_class)
& (ScoreBest.score >= min_score)
)
if session.scalar(score_best_stmt):
chart_id = f"{chart.song_id},{chart.rating_class}"
if chart_id not in results_id:
results.append(chart)
results_id.append(chart_id)
return results
# endregion
def get_b30(self):