impr: DbScoreTableModel database access

This commit is contained in:
283375 2023-10-17 19:58:14 +08:00
parent b1af1f622e
commit 52e618e664
Signed by: 283375
SSH Key Fingerprint: SHA256:UcX0qg6ZOSDOeieKPGokA5h7soykG61nz2uxuQgVLSk
2 changed files with 79 additions and 75 deletions

View File

@ -1,8 +1,8 @@
import logging import logging
from arcaea_offline.calculate import calculate_play_rating from arcaea_offline.models import Chart, Difficulty, Score, ScoreCalculated, Song
from arcaea_offline.models import Chart, Score
from PySide6.QtCore import QCoreApplication, QModelIndex, QSortFilterProxyModel, Qt from PySide6.QtCore import QCoreApplication, QModelIndex, QSortFilterProxyModel, Qt
from sqlalchemy import select
from .base import DbTableModel from .base import DbTableModel
@ -14,6 +14,8 @@ class DbScoreTableModel(DbTableModel):
ChartRole = Qt.ItemDataRole.UserRole + 11 ChartRole = Qt.ItemDataRole.UserRole + 11
ScoreRole = Qt.ItemDataRole.UserRole + 12 ScoreRole = Qt.ItemDataRole.UserRole + 12
PttRole = Qt.ItemDataRole.UserRole + 13 PttRole = Qt.ItemDataRole.UserRole + 13
SongRole = Qt.ItemDataRole.UserRole + 14
DifficultyRole = Qt.ItemDataRole.UserRole + 15
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
@ -31,81 +33,73 @@ class DbScoreTableModel(DbTableModel):
] ]
def syncDb(self): def syncDb(self):
newScores = self._db.get_scores() self.beginResetModel()
newScores = sorted(newScores, key=lambda x: x.id) self.beginRemoveRows(QModelIndex(), 0, self.rowCount())
newCharts = [] self.__items.clear()
for score in newScores: self.endRemoveRows()
dbChart = self._db.get_chart(score.song_id, score.rating_class) self.endResetModel()
newCharts.append(
dbChart with self._db.sessionmaker() as session:
if isinstance(dbChart, Chart) stmt = (
else Chart( select(Score, Chart, Song, Difficulty, ScoreCalculated.potential)
song_id=score.song_id, .join(
rating_class=score.rating_class, ScoreCalculated,
title=score.song_id, (Score.id == ScoreCalculated.id),
set="unknown", isouter=True,
)
.join(
Chart,
(Score.song_id == Chart.song_id)
& (Score.rating_class == Chart.rating_class),
isouter=True,
)
.join(
Song,
(Score.song_id == Song.id),
isouter=True,
)
.join(
Difficulty,
(Score.song_id == Difficulty.song_id)
& (Score.rating_class == Difficulty.rating_class),
isouter=True,
) )
) )
newPtts = [] results = session.execute(stmt).all()
for chart, score in zip(newCharts, newScores):
if (
isinstance(chart, Chart)
and chart.constant is not None
and isinstance(score, Score)
):
newPtts.append(calculate_play_rating(chart.constant, score.score))
else:
newPtts.append(None)
newScoreIds = [score.id for score in newScores] self.beginInsertRows(QModelIndex(), 0, len(results) - 1)
oldScoreIds = [item[self.ScoreRole].id for item in self.__items] for result in results:
score, chart, song, difficulty, potential = result
deleteIds = list(set(oldScoreIds) - set(newScoreIds)) if chart:
newIds = list(set(newScoreIds) - set(oldScoreIds)) chartInModel = chart
deleteRowIndexes = [oldScoreIds.index(deleteId) for deleteId in deleteIds] elif song and difficulty:
chartInModel = Chart(
song_id=song.id,
rating_class=difficulty.rating_class,
title=difficulty.title or song.title,
set=song.set,
)
else:
chartInModel = Chart(
song_id=score.song_id,
rating_class=score.rating_class,
title=score.song_id,
set="unknown",
)
# first delete rows self.__items.append(
for deleteRowIndex in sorted(deleteRowIndexes, reverse=True): {
self.beginRemoveRows(QModelIndex(), deleteRowIndex, deleteRowIndex) self.IdRole: score.id,
self.__items.pop(deleteRowIndex) self.ScoreRole: score,
self.endRemoveRows() self.ChartRole: chartInModel,
self.SongRole: song,
# now update existing datas self.DifficultyRole: difficulty,
for oldItem, newChart, newScore, newPtt in zip( self.PttRole: potential,
self.__items, newCharts, newScores, newPtts }
): )
oldItem[self.IdRole] = newScore.id
oldItem[self.ChartRole] = newChart
oldItem[self.ScoreRole] = newScore
oldItem[self.PttRole] = newPtt
# finally insert new rows
for newId in newIds:
insertRowIndex = self.rowCount()
itemListIndex = newScoreIds.index(newId)
score = newScores[itemListIndex]
chart = newCharts[itemListIndex]
ptt = newPtts[itemListIndex]
self.beginInsertRows(QModelIndex(), insertRowIndex, insertRowIndex)
self.__items.append(
{
self.IdRole: score.id,
self.ChartRole: chart,
self.ScoreRole: score,
self.PttRole: ptt,
}
)
self.endInsertRows() self.endInsertRows()
# trigger view update
topLeft = self.index(0, 0)
bottomRight = self.index(self.rowCount() - 1, self.columnCount() - 1)
self.dataChanged.emit(
topLeft,
bottomRight,
[Qt.ItemDataRole.DisplayRole, self.IdRole, self.ChartRole, self.ScoreRole],
)
def rowCount(self, *args): def rowCount(self, *args):
return len(self.__items) return len(self.__items)
@ -116,8 +110,12 @@ class DbScoreTableModel(DbTableModel):
self.IdRole, self.IdRole,
]: ]:
return self.__items[index.row()][self.IdRole] return self.__items[index.row()][self.IdRole]
elif index.column() == 1 and role == self.ChartRole: elif index.column() == 1 and role in [
return self.__items[index.row()][self.ChartRole] self.ChartRole,
self.SongRole,
self.DifficultyRole,
]:
return self.__items[index.row()][role]
elif index.column() == 2 and role in [self.ChartRole, self.ScoreRole]: elif index.column() == 2 and role in [self.ChartRole, self.ScoreRole]:
return self.__items[index.row()][role] return self.__items[index.row()][role]
elif index.column() == 3: elif index.column() == 3:
@ -185,7 +183,7 @@ class DbScoreTableSortFilterProxyModel(QSortFilterProxyModel):
Sort_C2_ScoreRole = Qt.ItemDataRole.UserRole + 75 Sort_C2_ScoreRole = Qt.ItemDataRole.UserRole + 75
Sort_C2_TimeRole = Qt.ItemDataRole.UserRole + 76 Sort_C2_TimeRole = Qt.ItemDataRole.UserRole + 76
def lessThan(self, sourceLeft, sourceRight) -> bool: def lessThan(self, sourceLeft: QModelIndex, sourceRight: QModelIndex) -> bool:
if sourceLeft.column() != sourceRight.column(): if sourceLeft.column() != sourceRight.column():
return return

View File

@ -1,5 +1,4 @@
from arcaea_offline.models import Score from PySide6.QtCore import Qt, Slot
from PySide6.QtCore import QModelIndex, Qt, Slot
from PySide6.QtGui import QColor, QPalette from PySide6.QtGui import QColor, QPalette
from PySide6.QtWidgets import QMessageBox from PySide6.QtWidgets import QMessageBox
@ -17,6 +16,12 @@ class TableChartDelegate(ChartDelegate):
def getChart(self, index): def getChart(self, index):
return index.data(DbScoreTableModel.ChartRole) return index.data(DbScoreTableModel.ChartRole)
def getSong(self, index):
return index.data(DbScoreTableModel.SongRole)
def getDifficulty(self, index):
return index.data(DbScoreTableModel.DifficultyRole)
class TableScoreDelegate(ScoreDelegate): class TableScoreDelegate(ScoreDelegate):
def getChart(self, index): def getChart(self, index):
@ -49,6 +54,7 @@ class DbScoreTableViewer(DbTableViewer):
highlightColor.setAlpha(25) highlightColor.setAlpha(25)
tableViewPalette.setColor(QPalette.ColorRole.Highlight, highlightColor) tableViewPalette.setColor(QPalette.ColorRole.Highlight, highlightColor)
self.tableView.setPalette(tableViewPalette) self.tableView.setPalette(tableViewPalette)
self.tableModel.rowsInserted.connect(self.resizeTableView)
self.tableModel.dataChanged.connect(self.resizeTableView) self.tableModel.dataChanged.connect(self.resizeTableView)
self.fillSortComboBox() self.fillSortComboBox()