diff --git a/ui/designer/tabs/tabTools/tabTools_ChartRecommend.ui b/ui/designer/tabs/tabTools/tabTools_ChartRecommend.ui
new file mode 100644
index 0000000..4e5da0f
--- /dev/null
+++ b/ui/designer/tabs/tabTools/tabTools_ChartRecommend.ui
@@ -0,0 +1,297 @@
+
+
+ TabTools_ChartRecommend
+
+
+
+ 0
+ 0
+ 668
+ 546
+
+
+
+ TabTools_ChartRecommend
+
+
+ -
+
+
+ constantRangeFromPlayRating
+
+
+
-
+
+
+
+ 100
+ 0
+
+
+
+
+ 100
+ 16777215
+
+
+
+ 3
+
+
+ 100.000000000000000
+
+
+ 0.100000000000000
+
+
+
+ -
+
+
-
+
+
+ AA
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+ -
+
+
+ EX
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+ -
+
+
+ EX+
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+ -
+
+
+ ...
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+
+ -
+
+
+ ...
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+
+ -
+
+
+ ...
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+
+
+
+
+
+
+ -
+
+
+ chartsByConstant
+
+
+
-
+
+
-
+
+
+
+ 100
+ 0
+
+
+
+
+ 100
+ 16777215
+
+
+
+ 1
+
+
+ 100.000000000000000
+
+
+ 0.100000000000000
+
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ false
+
+
+ refreshButton
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
+ -
+
+
+ chartsRecommendFromPlayRating
+
+
+
-
+
+
-
+
+
+
+ 100
+ 0
+
+
+
+
+ 100
+ 16777215
+
+
+
+ 3
+
+
+ 100.000000000000000
+
+
+ 0.100000000000000
+
+
+
+ -
+
+
+ ±
+
+
+
+ -
+
+
+ 2.000000000000000
+
+
+ 0.010000000000000
+
+
+ 0.100000000000000
+
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ false
+
+
+ refreshButton
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/designer/tabs/tabTools/tabTools_ChartRecommend_ui.py b/ui/designer/tabs/tabTools/tabTools_ChartRecommend_ui.py
new file mode 100644
index 0000000..92fc2cc
--- /dev/null
+++ b/ui/designer/tabs/tabTools/tabTools_ChartRecommend_ui.py
@@ -0,0 +1,219 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'tabTools_ChartRecommend.ui'
+##
+## Created by: Qt User Interface Compiler version 6.5.2
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+ QMetaObject, QObject, QPoint, QRect,
+ QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+ QFont, QFontDatabase, QGradient, QIcon,
+ QImage, QKeySequence, QLinearGradient, QPainter,
+ QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QDoubleSpinBox, QGridLayout, QGroupBox,
+ QHBoxLayout, QLabel, QPushButton, QSizePolicy,
+ QSpacerItem, QVBoxLayout, QWidget)
+
+class Ui_TabTools_ChartRecommend(object):
+ def setupUi(self, TabTools_ChartRecommend):
+ if not TabTools_ChartRecommend.objectName():
+ TabTools_ChartRecommend.setObjectName(u"TabTools_ChartRecommend")
+ TabTools_ChartRecommend.resize(668, 546)
+ TabTools_ChartRecommend.setWindowTitle(u"TabTools_ChartRecommend")
+ self.verticalLayout = QVBoxLayout(TabTools_ChartRecommend)
+ self.verticalLayout.setObjectName(u"verticalLayout")
+ self.groupBox = QGroupBox(TabTools_ChartRecommend)
+ self.groupBox.setObjectName(u"groupBox")
+ self.verticalLayout_2 = QVBoxLayout(self.groupBox)
+ self.verticalLayout_2.setObjectName(u"verticalLayout_2")
+ self.rangeFromPlayRating_playRatingSpinBox = QDoubleSpinBox(self.groupBox)
+ self.rangeFromPlayRating_playRatingSpinBox.setObjectName(u"rangeFromPlayRating_playRatingSpinBox")
+ self.rangeFromPlayRating_playRatingSpinBox.setMinimumSize(QSize(100, 0))
+ self.rangeFromPlayRating_playRatingSpinBox.setMaximumSize(QSize(100, 16777215))
+ self.rangeFromPlayRating_playRatingSpinBox.setDecimals(3)
+ self.rangeFromPlayRating_playRatingSpinBox.setMaximum(100.000000000000000)
+ self.rangeFromPlayRating_playRatingSpinBox.setSingleStep(0.100000000000000)
+
+ self.verticalLayout_2.addWidget(self.rangeFromPlayRating_playRatingSpinBox)
+
+ self.gridLayout_3 = QGridLayout()
+ self.gridLayout_3.setObjectName(u"gridLayout_3")
+ self.label_3 = QLabel(self.groupBox)
+ self.label_3.setObjectName(u"label_3")
+ self.label_3.setText(u"AA")
+ self.label_3.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft)
+
+ self.gridLayout_3.addWidget(self.label_3, 0, 2, 1, 1)
+
+ self.label_2 = QLabel(self.groupBox)
+ self.label_2.setObjectName(u"label_2")
+ self.label_2.setText(u"EX")
+ self.label_2.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft)
+
+ self.gridLayout_3.addWidget(self.label_2, 0, 1, 1, 1)
+
+ self.label = QLabel(self.groupBox)
+ self.label.setObjectName(u"label")
+ self.label.setText(u"EX+")
+ self.label.setAlignment(Qt.AlignBottom|Qt.AlignLeading|Qt.AlignLeft)
+
+ self.gridLayout_3.addWidget(self.label, 0, 0, 1, 1)
+
+ self.rangeFromPlayRating_ExPlusLabel = QLabel(self.groupBox)
+ self.rangeFromPlayRating_ExPlusLabel.setObjectName(u"rangeFromPlayRating_ExPlusLabel")
+ self.rangeFromPlayRating_ExPlusLabel.setText(u"...")
+ self.rangeFromPlayRating_ExPlusLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
+
+ self.gridLayout_3.addWidget(self.rangeFromPlayRating_ExPlusLabel, 1, 0, 1, 1)
+
+ self.rangeFromPlayRating_ExLabel = QLabel(self.groupBox)
+ self.rangeFromPlayRating_ExLabel.setObjectName(u"rangeFromPlayRating_ExLabel")
+ self.rangeFromPlayRating_ExLabel.setText(u"...")
+ self.rangeFromPlayRating_ExLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
+
+ self.gridLayout_3.addWidget(self.rangeFromPlayRating_ExLabel, 1, 1, 1, 1)
+
+ self.rangeFromPlayRating_AaLabel = QLabel(self.groupBox)
+ self.rangeFromPlayRating_AaLabel.setObjectName(u"rangeFromPlayRating_AaLabel")
+ self.rangeFromPlayRating_AaLabel.setText(u"...")
+ self.rangeFromPlayRating_AaLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
+
+ self.gridLayout_3.addWidget(self.rangeFromPlayRating_AaLabel, 1, 2, 1, 1)
+
+
+ self.verticalLayout_2.addLayout(self.gridLayout_3)
+
+
+ self.verticalLayout.addWidget(self.groupBox)
+
+ self.groupBox_2 = QGroupBox(TabTools_ChartRecommend)
+ self.groupBox_2.setObjectName(u"groupBox_2")
+ self.verticalLayout_3 = QVBoxLayout(self.groupBox_2)
+ self.verticalLayout_3.setObjectName(u"verticalLayout_3")
+ self.horizontalLayout_3 = QHBoxLayout()
+ self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
+ self.chartsByConstant_constantSpinBox = QDoubleSpinBox(self.groupBox_2)
+ self.chartsByConstant_constantSpinBox.setObjectName(u"chartsByConstant_constantSpinBox")
+ self.chartsByConstant_constantSpinBox.setMinimumSize(QSize(100, 0))
+ self.chartsByConstant_constantSpinBox.setMaximumSize(QSize(100, 16777215))
+ self.chartsByConstant_constantSpinBox.setDecimals(1)
+ self.chartsByConstant_constantSpinBox.setMaximum(100.000000000000000)
+ self.chartsByConstant_constantSpinBox.setSingleStep(0.100000000000000)
+
+ self.horizontalLayout_3.addWidget(self.chartsByConstant_constantSpinBox)
+
+ self.chartsByConstant_numLabel = QLabel(self.groupBox_2)
+ self.chartsByConstant_numLabel.setObjectName(u"chartsByConstant_numLabel")
+ self.chartsByConstant_numLabel.setText(u"...")
+
+ self.horizontalLayout_3.addWidget(self.chartsByConstant_numLabel)
+
+ self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
+
+ self.horizontalLayout_3.addItem(self.horizontalSpacer)
+
+ self.chartsByConstant_refreshButton = QPushButton(self.groupBox_2)
+ self.chartsByConstant_refreshButton.setObjectName(u"chartsByConstant_refreshButton")
+ self.chartsByConstant_refreshButton.setEnabled(False)
+
+ self.horizontalLayout_3.addWidget(self.chartsByConstant_refreshButton)
+
+
+ self.verticalLayout_3.addLayout(self.horizontalLayout_3)
+
+ self.widget = QWidget(self.groupBox_2)
+ self.widget.setObjectName(u"widget")
+ sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.widget.sizePolicy().hasHeightForWidth())
+ self.widget.setSizePolicy(sizePolicy)
+ self.chartsByConstant_gridLayout = QGridLayout(self.widget)
+ self.chartsByConstant_gridLayout.setObjectName(u"chartsByConstant_gridLayout")
+
+ self.verticalLayout_3.addWidget(self.widget)
+
+
+ self.verticalLayout.addWidget(self.groupBox_2)
+
+ self.groupBox_3 = QGroupBox(TabTools_ChartRecommend)
+ self.groupBox_3.setObjectName(u"groupBox_3")
+ self.verticalLayout_4 = QVBoxLayout(self.groupBox_3)
+ self.verticalLayout_4.setObjectName(u"verticalLayout_4")
+ self.horizontalLayout_2 = QHBoxLayout()
+ self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
+ self.chartsRecommendFromPlayRating_playRatingSpinBox = QDoubleSpinBox(self.groupBox_3)
+ self.chartsRecommendFromPlayRating_playRatingSpinBox.setObjectName(u"chartsRecommendFromPlayRating_playRatingSpinBox")
+ self.chartsRecommendFromPlayRating_playRatingSpinBox.setMinimumSize(QSize(100, 0))
+ self.chartsRecommendFromPlayRating_playRatingSpinBox.setMaximumSize(QSize(100, 16777215))
+ self.chartsRecommendFromPlayRating_playRatingSpinBox.setDecimals(3)
+ self.chartsRecommendFromPlayRating_playRatingSpinBox.setMaximum(100.000000000000000)
+ self.chartsRecommendFromPlayRating_playRatingSpinBox.setSingleStep(0.100000000000000)
+
+ self.horizontalLayout_2.addWidget(self.chartsRecommendFromPlayRating_playRatingSpinBox)
+
+ self.label_4 = QLabel(self.groupBox_3)
+ self.label_4.setObjectName(u"label_4")
+ self.label_4.setText(u"\u00b1")
+
+ self.horizontalLayout_2.addWidget(self.label_4)
+
+ self.chartsRecommendFromPlayRating_boundsSpinBox = QDoubleSpinBox(self.groupBox_3)
+ self.chartsRecommendFromPlayRating_boundsSpinBox.setObjectName(u"chartsRecommendFromPlayRating_boundsSpinBox")
+ self.chartsRecommendFromPlayRating_boundsSpinBox.setMaximum(2.000000000000000)
+ self.chartsRecommendFromPlayRating_boundsSpinBox.setSingleStep(0.010000000000000)
+ self.chartsRecommendFromPlayRating_boundsSpinBox.setValue(0.100000000000000)
+
+ self.horizontalLayout_2.addWidget(self.chartsRecommendFromPlayRating_boundsSpinBox)
+
+ self.chartsRecommendFromPlayRating_numLabel = QLabel(self.groupBox_3)
+ self.chartsRecommendFromPlayRating_numLabel.setObjectName(u"chartsRecommendFromPlayRating_numLabel")
+ self.chartsRecommendFromPlayRating_numLabel.setText(u"...")
+
+ self.horizontalLayout_2.addWidget(self.chartsRecommendFromPlayRating_numLabel)
+
+ self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
+
+ self.horizontalLayout_2.addItem(self.horizontalSpacer_2)
+
+ self.chartsRecommendFromPlayRating_refreshButton = QPushButton(self.groupBox_3)
+ self.chartsRecommendFromPlayRating_refreshButton.setObjectName(u"chartsRecommendFromPlayRating_refreshButton")
+ self.chartsRecommendFromPlayRating_refreshButton.setEnabled(False)
+
+ self.horizontalLayout_2.addWidget(self.chartsRecommendFromPlayRating_refreshButton)
+
+
+ self.verticalLayout_4.addLayout(self.horizontalLayout_2)
+
+ self.widget_2 = QWidget(self.groupBox_3)
+ self.widget_2.setObjectName(u"widget_2")
+ sizePolicy.setHeightForWidth(self.widget_2.sizePolicy().hasHeightForWidth())
+ self.widget_2.setSizePolicy(sizePolicy)
+ self.chartsRecommendFromPlayRating_gridLayout = QGridLayout(self.widget_2)
+ self.chartsRecommendFromPlayRating_gridLayout.setObjectName(u"chartsRecommendFromPlayRating_gridLayout")
+
+ self.verticalLayout_4.addWidget(self.widget_2)
+
+
+ self.verticalLayout.addWidget(self.groupBox_3)
+
+
+ self.retranslateUi(TabTools_ChartRecommend)
+
+ QMetaObject.connectSlotsByName(TabTools_ChartRecommend)
+ # setupUi
+
+ def retranslateUi(self, TabTools_ChartRecommend):
+ self.groupBox.setTitle(QCoreApplication.translate("TabTools_ChartRecommend", u"constantRangeFromPlayRating", None))
+ self.groupBox_2.setTitle(QCoreApplication.translate("TabTools_ChartRecommend", u"chartsByConstant", None))
+ self.chartsByConstant_refreshButton.setText(QCoreApplication.translate("TabTools_ChartRecommend", u"refreshButton", None))
+ self.groupBox_3.setTitle(QCoreApplication.translate("TabTools_ChartRecommend", u"chartsRecommendFromPlayRating", None))
+ self.chartsRecommendFromPlayRating_refreshButton.setText(QCoreApplication.translate("TabTools_ChartRecommend", u"refreshButton", None))
+ pass
+ # retranslateUi
+
diff --git a/ui/designer/tabs/tabToolsEntry.ui b/ui/designer/tabs/tabToolsEntry.ui
index ae30179..83be3bf 100644
--- a/ui/designer/tabs/tabToolsEntry.ui
+++ b/ui/designer/tabs/tabToolsEntry.ui
@@ -29,6 +29,11 @@
tab.stepCalculator
+
+
+ tab.chartRecommend
+
+
tab.andreal
@@ -57,6 +62,12 @@
ui.implements.tabs.tabTools.tabTools_Andreal
1
+
+ TabTools_ChartRecommend
+ QWidget
+ ui.implements.tabs.tabTools.tabTools_ChartRecommend
+ 1
+
diff --git a/ui/designer/tabs/tabToolsEntry_ui.py b/ui/designer/tabs/tabToolsEntry_ui.py
index 7607b9c..c963061 100644
--- a/ui/designer/tabs/tabToolsEntry_ui.py
+++ b/ui/designer/tabs/tabToolsEntry_ui.py
@@ -19,6 +19,7 @@ from PySide6.QtWidgets import (QApplication, QSizePolicy, QTabWidget, QVBoxLayou
QWidget)
from ui.implements.tabs.tabTools.tabTools_Andreal import TabTools_Andreal
+from ui.implements.tabs.tabTools.tabTools_ChartRecommend import TabTools_ChartRecommend
from ui.implements.tabs.tabTools.tabTools_InfoLookup import TabTools_InfoLookup
from ui.implements.tabs.tabTools.tabTools_StepCalculator import TabTools_StepCalculator
@@ -38,6 +39,9 @@ class Ui_TabToolsEntry(object):
self.tab_2 = TabTools_StepCalculator()
self.tab_2.setObjectName(u"tab_2")
self.tabWidget.addTab(self.tab_2, "")
+ self.tab_4 = TabTools_ChartRecommend()
+ self.tab_4.setObjectName(u"tab_4")
+ self.tabWidget.addTab(self.tab_4, "")
self.tab_3 = TabTools_Andreal()
self.tab_3.setObjectName(u"tab_3")
self.tabWidget.addTab(self.tab_3, "")
@@ -56,6 +60,7 @@ class Ui_TabToolsEntry(object):
def retranslateUi(self, TabToolsEntry):
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("TabToolsEntry", u"tab.infoLookup", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("TabToolsEntry", u"tab.stepCalculator", None))
+ self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), QCoreApplication.translate("TabToolsEntry", u"tab.chartRecommend", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), QCoreApplication.translate("TabToolsEntry", u"tab.andreal", None))
pass
# retranslateUi
diff --git a/ui/implements/tabs/tabTools/tabTools_ChartRecommend.py b/ui/implements/tabs/tabTools/tabTools_ChartRecommend.py
new file mode 100644
index 0000000..a9a1b82
--- /dev/null
+++ b/ui/implements/tabs/tabTools/tabTools_ChartRecommend.py
@@ -0,0 +1,123 @@
+import logging
+import random
+
+from arcaea_offline.calculate import calculate_constants_from_play_rating
+from arcaea_offline.database import Database
+from arcaea_offline.models import Chart, ScoreBest
+from arcaea_offline.utils.rating import rating_class_to_text
+from arcaea_offline.utils.score import score_to_grade_text
+from PySide6.QtCore import Slot
+from PySide6.QtWidgets import QLabel, QWidget
+
+from ui.designer.tabs.tabTools.tabTools_ChartRecommend_ui import (
+ Ui_TabTools_ChartRecommend,
+)
+
+logger = logging.getLogger(__name__)
+
+
+def chartToText(chart: Chart):
+ return f"{chart.artist} - {chart.title}
({chart.song_id}) {rating_class_to_text(chart.rating_class)}"
+
+
+def scoreBestToText(score: ScoreBest):
+ return f"{score_to_grade_text(score.score)} {score.score} > {score.potential:.4f}"
+
+
+class TabTools_ChartRecommend(Ui_TabTools_ChartRecommend, QWidget):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.setupUi(self)
+
+ self.db = Database()
+
+ self.chartsByConstant = []
+ self.chartsRecommendFromPlayRating = []
+
+ self.numLabelFormatString = "{} charts"
+
+ self.chartsRecommendFromPlayRating_playRatingSpinBox.valueChanged.connect(
+ self.updateChartsRecommendFromPlayRating
+ )
+ self.chartsRecommendFromPlayRating_boundsSpinBox.valueChanged.connect(
+ self.updateChartsRecommendFromPlayRating
+ )
+
+ self.chartsByConstant_refreshButton.clicked.connect(self.fillChartsByConstant)
+ self.chartsRecommendFromPlayRating_refreshButton.clicked.connect(
+ self.fillChartsRecommendFromPlayRating
+ )
+
+ @Slot(float)
+ def on_rangeFromPlayRating_playRatingSpinBox_valueChanged(self, value: float):
+ try:
+ result = calculate_constants_from_play_rating(value)
+ exPlusLower, exPlusUpper = result.EXPlus
+ exLower, exUpper = result.EX
+ aaLower, aaUpper = result.AA
+
+ self.rangeFromPlayRating_ExPlusLabel.setText(
+ f"{exPlusLower:.3f}~{exPlusUpper:.3f}"
+ )
+ self.rangeFromPlayRating_ExLabel.setText(f"{exLower:.3f}~{exUpper:.3f}")
+ self.rangeFromPlayRating_AaLabel.setText(f"{aaLower:.3f}~{aaUpper:.3f}")
+ except Exception:
+ logging.exception("cannot calculate constant from play rating")
+ self.rangeFromPlayRating_ExPlusLabel.setText("...")
+ self.rangeFromPlayRating_ExLabel.setText("...")
+ self.rangeFromPlayRating_AaLabel.setText("...")
+
+ def fillChartsByConstant(self):
+ while item := self.chartsByConstant_gridLayout.takeAt(0):
+ item.widget().deleteLater()
+
+ charts = random.sample(
+ self.chartsByConstant, k=min(len(self.chartsByConstant), 6)
+ )
+ row = 0
+ for i, chart in enumerate(charts):
+ if i % 3 == 0:
+ row += 1
+ label = QLabel(self)
+ label.setText(chartToText(chart))
+ self.chartsByConstant_gridLayout.addWidget(label, row, i % 3)
+
+ @Slot(float)
+ def on_chartsByConstant_constantSpinBox_valueChanged(self, value: float):
+ self.chartsByConstant = self.db.get_charts_by_constant(int(value * 10))
+ chartsNum = len(self.chartsByConstant)
+ self.chartsByConstant_refreshButton.setEnabled(chartsNum > 6)
+ self.chartsByConstant_numLabel.setText(
+ self.numLabelFormatString.format(chartsNum)
+ )
+ self.fillChartsByConstant()
+
+ def fillChartsRecommendFromPlayRating(self):
+ while item := self.chartsRecommendFromPlayRating_gridLayout.takeAt(0):
+ item.widget().deleteLater()
+
+ charts = random.sample(
+ self.chartsRecommendFromPlayRating,
+ k=min(len(self.chartsRecommendFromPlayRating), 6),
+ )
+ row = 0
+ for i, chart in enumerate(charts):
+ if i % 3 == 0:
+ row += 1
+ scoreBest = self.db.get_score_best(chart.song_id, chart.rating_class)
+ label = QLabel(self)
+ label.setText(f"{chartToText(chart)}
-
{scoreBestToText(scoreBest)}")
+ self.chartsRecommendFromPlayRating_gridLayout.addWidget(label, row, i % 3)
+
+ def updateChartsRecommendFromPlayRating(self):
+ playRating = self.chartsRecommendFromPlayRating_playRatingSpinBox.value()
+ bounds = self.chartsRecommendFromPlayRating_boundsSpinBox.value()
+ self.chartsRecommendFromPlayRating = self.db.recommend_charts(
+ playRating, bounds
+ )
+ chartsNum = len(self.chartsRecommendFromPlayRating)
+ self.chartsRecommendFromPlayRating_refreshButton.setEnabled(chartsNum > 6)
+ self.chartsRecommendFromPlayRating_numLabel.setText(
+ self.numLabelFormatString.format(chartsNum)
+ )
+ self.fillChartsRecommendFromPlayRating()
diff --git a/ui/resources/lang/en_US.ts b/ui/resources/lang/en_US.ts
index 59fb82e..d6765f0 100644
--- a/ui/resources/lang/en_US.ts
+++ b/ui/resources/lang/en_US.ts
@@ -89,12 +89,12 @@
Continue
-
+
dialog.tryInitExistingDatabase
The existing database doesn't seem to be initialized properly, try initialize again?
-
+
dialog.confirmNewDatabase
Database file does not exist. Create now?
@@ -283,22 +283,22 @@ validation
OcrTableModel
-
+
horizontalHeader.title.select
Select
-
+
horizontalHeader.title.imagePreview
Image Preview
-
+
horizontalHeader.title.chart
Chart
-
+
horizontalHeader.title.score
Score
@@ -314,54 +314,54 @@ validation
ScoreEditor
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
setNone
None
-
+
formLabel.date
Time
-
+
formLabel.comment
Comment
-
+
formLabel.preview
Preview
-
+
formLabel.score
Score
-
+
idAutoInsert
(Auto insert)
-
+
warnIfIncomplete
Warn if incomplete
-
+
commitButton
Commit
-
+
validate.ok
OK
@@ -406,57 +406,57 @@ validation
Cannot verify an incomplete score. Commit anyway?
-
+
confirmDialog.chartNotSet.title
Chart not set
-
+
confirmDialog.chartNotSet.text
Chart not set, cannot commit.
-
+
confirmDialog.scoreIncomplete.title
Score incomplete
-
+
confirmDialog.scoreIncomplete.text
Necessary score field missing, cannot commit.
-
+
validate.chartNotSet
Chart not set
-
+
validate.chartIncomple
No chart data, cannot verify
-
+
validate.scoreMismatch
Possible invalid score
-
+
validate.scoreEmpty
Empty score
-
+
validate.scoreIncomplete
Missing necessary score field
-
+
validate.scoreIncompleteForValidate
Score incomplete, cannot verify
-
+
validate.unknownState
Unknown
@@ -581,12 +581,12 @@ validation
Manage
-
+
tab.scoreTableViewer
Table [Score]
-
+
tab.b30TableViewer
Table [B30]
@@ -769,6 +769,11 @@ validation
+ tab.chartRecommend
+ Chart Recommend
+
+
+
tab.andreal
Andreal Image Generator
@@ -836,11 +841,35 @@ validation
Generate
-
+
imageWhatIsThisDialog.description
Generate image of...<ul><li>/a - the most recent score</li><li>/a b30 - best30 image</li><li>/a info - best score of the selected chart</li></ul>
+
+ TabTools_ChartRecommend
+
+
+ constantRangeFromPlayRating
+ Chart Constant Range from Play Rating
+
+
+
+ chartsByConstant
+ Charts by Constant
+
+
+
+
+ refreshButton
+ Roll
+
+
+
+ chartsRecommendFromPlayRating
+ Chart from Play Rating Based on Best Score
+
+
TabTools_InfoLookup
@@ -1008,6 +1037,11 @@ validation
difficulty.title
Title
+
+
+ playRatingCalculate
+
+
TabTools_StepCalculator
diff --git a/ui/resources/lang/zh_CN.ts b/ui/resources/lang/zh_CN.ts
index 1d74fd2..d4d4fbc 100644
--- a/ui/resources/lang/zh_CN.ts
+++ b/ui/resources/lang/zh_CN.ts
@@ -89,12 +89,12 @@
继续
-
+
dialog.tryInitExistingDatabase
现有的数据库似乎没有正确初始化,是否尝试再次初始化?
-
+
dialog.confirmNewDatabase
数据库文件不存在,是否创建?
@@ -282,22 +282,22 @@
OcrTableModel
-
+
horizontalHeader.title.select
选择
-
+
horizontalHeader.title.imagePreview
图像预览
-
+
horizontalHeader.title.chart
谱面
-
+
horizontalHeader.title.score
分数
@@ -313,54 +313,54 @@
ScoreEditor
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
setNone
置空
-
+
formLabel.date
时间
-
+
formLabel.comment
注释
-
+
formLabel.preview
预览
-
+
formLabel.score
分数
-
+
idAutoInsert
(自动插入)
-
+
warnIfIncomplete
不完整时要求确认
-
+
commitButton
提交
-
+
validate.ok
OK
@@ -405,57 +405,57 @@
无法验证不完整的分数。继续提交吗?
-
+
confirmDialog.chartNotSet.title
未指定谱面
-
+
confirmDialog.chartNotSet.text
未指定谱面,无法提交。
-
+
confirmDialog.scoreIncomplete.title
分数不完整
-
+
confirmDialog.scoreIncomplete.text
缺失必要的分数数据,无法提交。
-
+
validate.chartNotSet
未指定谱面
-
+
validate.chartIncomple
谱面数据缺失,无法验证分数
-
+
validate.scoreMismatch
分数可能有误
-
+
validate.scoreEmpty
分数为空
-
+
validate.scoreIncomplete
缺失必要分数数据
-
+
validate.scoreIncompleteForValidate
分数不完整,无法验证
-
+
validate.unknownState
未知
@@ -580,12 +580,12 @@
管理
-
+
tab.scoreTableViewer
表 [分数]
-
+
tab.b30TableViewer
表 [B30]
@@ -768,6 +768,11 @@
+ tab.chartRecommend
+ 谱面推荐
+
+
+
tab.andreal
Andreal 图片生成
@@ -835,11 +840,35 @@
生成
-
+
imageWhatIsThisDialog.description
生成……<ul><li>/a - 最近一次成绩</li><li>/a b30 - /a b30</li><li>/a info - 所选谱面的最好成绩</li></ul>
+
+ TabTools_ChartRecommend
+
+
+ constantRangeFromPlayRating
+ 由单曲 PTT 逆算谱面定数范围
+
+
+
+ chartsByConstant
+ 按定数查谱
+
+
+
+
+ refreshButton
+ 换一批
+
+
+
+ chartsRecommendFromPlayRating
+ 由单曲 PTT 结合最好成绩推荐谱面
+
+
TabTools_InfoLookup
@@ -1007,6 +1036,11 @@
difficulty.title
标题
+
+
+ playRatingCalculate
+
+
TabTools_StepCalculator