wip(ui): play result delegate

This commit is contained in:
2025-11-16 16:38:31 +08:00
parent a086573c0a
commit 2819c12ce0
4 changed files with 147 additions and 0 deletions

View File

@ -75,6 +75,8 @@ files = [
"ui/qmls/App.qml", "ui/qmls/App.qml",
"ui/qmls/AppMain.qml", "ui/qmls/AppMain.qml",
"ui/qmls/Components/PlayResultDelegate.qml",
"ui/viewmodels/overview.py", "ui/viewmodels/overview.py",
"ui/qmls/Overview.qml", "ui/qmls/Overview.qml",

View File

@ -0,0 +1,124 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.VectorImage
import "../libs/formatters.mjs" as Formatters
RowLayout {
id: root
required property var playResult
property alias pr: root.playResult
spacing: 8
SystemPalette {
id: systemPalette
}
component PFLLabel: RowLayout {
required property string label
required property var value
property color color: systemPalette.text
spacing: 0.5
Label {
Layout.alignment: Qt.AlignBaseline
text: parent.label
font.pointSize: 8
font.bold: true
color: parent.color
}
Label {
Layout.alignment: Qt.AlignBaseline
text: parent.value ?? '-'
color: parent.color
}
}
function getGradeIcon(gradeLabel: string): string {
const scheme = Application.styleHints.colorScheme == Qt.ColorScheme.Dark ? 'dark' : 'light';
const filenameMap = {
'EX+': 'ex-plus',
'EX': 'ex',
'AA': 'aa',
'A': 'a',
'B': 'b',
'C': 'c',
'D': 'd'
};
let filenameBase = filenameMap[gradeLabel];
if (scheme === 'dark') {
filenameBase += '-dark';
}
return `qrc:/images/grades/${filenameBase}.svg`;
}
TextMetrics {
id: gradeTextMetrics
text: 'EX+'
font.pointSize: 18
font.bold: true
}
VectorImage {
id: gradeIcon
Layout.preferredWidth: gradeTextMetrics.width
Layout.preferredHeight: gradeTextMetrics.width
fillMode: VectorImage.PreserveAspectFit
preferredRendererType: VectorImage.CurveRenderer
source: root.getGradeIcon(Formatters.scoreToGrade(root.pr.score))
}
ColumnLayout {
Layout.fillWidth: true
spacing: 1
Label {
Layout.fillWidth: true
text: root.pr.score
font.pointSize: 16
}
RowLayout {
Layout.fillWidth: true
Layout.leftMargin: 2
spacing: 5
PFLLabel {
label: 'P'
value: root.pr.pure
color: appTheme.pure
}
PFLLabel {
label: 'F'
value: root.pr.far
color: appTheme.far
}
PFLLabel {
label: 'L'
value: root.pr.lost
color: appTheme.lost
}
}
PFLLabel {
Layout.fillWidth: true
Layout.leftMargin: 2
label: 'MR'
value: root.pr.maxRecall
}
}
}

View File

@ -1,6 +1,9 @@
module Components module Components
internal SelectorBase SelectorBase.qml internal SelectorBase SelectorBase.qml
DirectorySelector 1.0 DirectorySelector.qml DirectorySelector 1.0 DirectorySelector.qml
FileSelector 1.0 FileSelector.qml FileSelector 1.0 FileSelector.qml
SectionTitle 1.0 SectionTitle.qml SectionTitle 1.0 SectionTitle.qml
PlayResultDelegate 1.0 PlayResultDelegate.qml

View File

@ -0,0 +1,18 @@
export function scoreToGrade(score) {
const gradeThresholds = [
{ minimum: 9900000, grade: "EX+" },
{ minimum: 9800000, grade: "EX" },
{ minimum: 9500000, grade: "AA" },
{ minimum: 9200000, grade: "A" },
{ minimum: 8900000, grade: "B" },
{ minimum: 8600000, grade: "C" },
];
for (const threshold of gradeThresholds) {
if (score >= threshold.minimum) {
return threshold.grade;
}
}
return "D";
}