diff --git a/src/arcaea_offline/calculate/__init__.py b/src/arcaea_offline/calculate/__init__.py index 6ac8f2e..f1904a8 100644 --- a/src/arcaea_offline/calculate/__init__.py +++ b/src/arcaea_offline/calculate/__init__.py @@ -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, +) diff --git a/src/arcaea_offline/database.py b/src/arcaea_offline/database.py index a5eca23..397b8a1 100644 --- a/src/arcaea_offline/database.py +++ b/src/arcaea_offline/database.py @@ -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):