arcaea-offline-pyside-ui/ui/implements/tabs/tabTools/tabTools_ChartRecommend.py

174 lines
6.7 KiB
Python

import logging
from arcaea_offline.calculate import calculate_constants_from_play_rating
from arcaea_offline.database import Database
from arcaea_offline.models import Chart, Score
from arcaea_offline.utils.rating import rating_class_to_text
from PySide6.QtCore import QModelIndex, Qt, Slot
from PySide6.QtGui import QColor, QPalette
from PySide6.QtWidgets import QDialog, QLabel, QVBoxLayout, QWidget
from ui.designer.tabs.tabTools.tabTools_ChartRecommend_ui import (
Ui_TabTools_ChartRecommend,
)
from ui.extends.tabs.tabTools.tabTools_ChartRecommend import (
ChartsModel,
ChartsWithScoreBestModel,
CustomChartDelegate,
CustomScoreBestDelegate,
)
from ui.implements.components.playRatingCalculator import PlayRatingCalculator
logger = logging.getLogger(__name__)
class QuickPlayRatingCalculatorDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.verticalLayout = QVBoxLayout(self)
self.chartLabel = QLabel(self)
self.verticalLayout.addWidget(self.chartLabel)
self.playRatingCalculator = PlayRatingCalculator(self)
self.verticalLayout.addWidget(self.playRatingCalculator)
self.setMinimumWidth(400)
self.playRatingCalculator.arcaeaScoreLineEdit.setFocus(
Qt.FocusReason.PopupFocusReason
)
def setChart(self, chart: Chart):
self.chartLabel.setText(
f"{chart.title} {rating_class_to_text(chart.rating_class)} {chart.constant / 10}"
)
self.playRatingCalculator.setConstant(chart.constant)
def setScore(self, score: Score):
self.playRatingCalculator.arcaeaScoreLineEdit.setText(str(score))
class TabTools_ChartRecommend(Ui_TabTools_ChartRecommend, QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.db = Database()
self.chartsByConstantModel = ChartsModel(self)
self.chartsRecommendFromPlayRatingModel = ChartsWithScoreBestModel(self)
self.numLabelFormatString = "{} charts"
self.chartDelegate = CustomChartDelegate(self)
self.scoreBestDelegate = CustomScoreBestDelegate(self)
self.chartsByConstant_modelView.setModel(self.chartsByConstantModel)
self.chartsByConstant_modelView.setItemDelegate(self.chartDelegate)
self.chartsRecommendFromPlayRating_modelView.setModel(
self.chartsRecommendFromPlayRatingModel
)
self.chartsRecommendFromPlayRating_modelView.setItemDelegateForColumn(
0, self.chartDelegate
)
self.chartsRecommendFromPlayRating_modelView.setItemDelegateForColumn(
1, self.scoreBestDelegate
)
self.chartsRecommendFromPlayRating_playRatingSpinBox.valueChanged.connect(
self.updateChartsRecommendFromPlayRating
)
self.chartsRecommendFromPlayRating_boundsSpinBox.valueChanged.connect(
self.updateChartsRecommendFromPlayRating
)
self.chartsByConstant_modelView.doubleClicked.connect(
self.openQuickPlayRatingCalculator_chartsByConstant
)
self.chartsRecommendFromPlayRating_modelView.doubleClicked.connect(
self.openQuickPlayRatingCalculator_chartsRecommendFromPlayRating
)
@Slot(float)
def on_rangeFromPlayRating_playRatingSpinBox_valueChanged(self, value: float):
try:
constant = round(
value, self.rangeFromPlayRating_playRatingSpinBox.decimals()
)
result = calculate_constants_from_play_rating(constant)
labels = [
self.rangeFromPlayRating_ExPlusLabel,
self.rangeFromPlayRating_ExLabel,
self.rangeFromPlayRating_AaLabel,
self.rangeFromPlayRating_ALabel,
self.rangeFromPlayRating_BLabel,
self.rangeFromPlayRating_CLabel,
]
for label, constantRange in zip(
labels,
[result.EXPlus, result.EX, result.AA, result.A, result.B, result.C],
):
label.setText(f"{constantRange[0]:.3f}~{constantRange[1]:.3f}")
except Exception:
logging.exception("Cannot calculate constant from play rating:")
self.rangeFromPlayRating_ExPlusLabel.setText("...")
self.rangeFromPlayRating_ExLabel.setText("...")
self.rangeFromPlayRating_AaLabel.setText("...")
@Slot(float)
def on_chartsByConstant_constantSpinBox_valueChanged(self, value: float):
constant = round(value, self.chartsByConstant_constantSpinBox.decimals())
charts = self.db.get_charts_by_constant(int(constant * 10))
chartsNum = len(charts)
self.chartsByConstant_numLabel.setText(
self.numLabelFormatString.format(chartsNum)
)
self.chartsByConstantModel.setCharts(charts)
def updateChartsRecommendFromPlayRating(self):
playRating = self.chartsRecommendFromPlayRating_playRatingSpinBox.value()
bounds = self.chartsRecommendFromPlayRating_boundsSpinBox.value()
charts = self.db.recommend_charts(
round(
playRating,
self.chartsRecommendFromPlayRating_playRatingSpinBox.decimals(),
),
round(
bounds,
self.chartsRecommendFromPlayRating_boundsSpinBox.decimals(),
),
)
chartsNum = len(charts)
self.chartsRecommendFromPlayRating_numLabel.setText(
self.numLabelFormatString.format(chartsNum)
)
scores = [self.db.get_score_best(c.song_id, c.rating_class) for c in charts]
self.chartsRecommendFromPlayRatingModel.setChartAndScore(charts, scores)
self.chartsRecommendFromPlayRating_modelView.resizeRowsToContents()
self.chartsRecommendFromPlayRating_modelView.resizeColumnsToContents()
@Slot(QModelIndex)
def openQuickPlayRatingCalculator_chartsByConstant(self, index: QModelIndex):
dialog = QuickPlayRatingCalculatorDialog(self)
chart = index.data(ChartsModel.ChartRole)
dialog.setChart(chart)
dialog.show()
@Slot(QModelIndex)
def openQuickPlayRatingCalculator_chartsRecommendFromPlayRating(
self, index: QModelIndex
):
dialog = QuickPlayRatingCalculatorDialog(self)
row = index.row()
chartIndex = self.chartsRecommendFromPlayRatingModel.item(row, 0)
scoreIndex = self.chartsRecommendFromPlayRatingModel.item(row, 1)
chart = chartIndex.data(ChartsWithScoreBestModel.ChartRole)
score: Score = scoreIndex.data(ChartsWithScoreBestModel.ScoreBestRole)
dialog.setChart(chart)
dialog.setScore(score.score)
dialog.show()