3 Commits

3 changed files with 86 additions and 76 deletions

View File

@ -95,6 +95,7 @@ class ScoreDelegate(TextSegmentDelegate):
self.isScoreInstance(index) self.isScoreInstance(index)
and isinstance(chart, Chart) and isinstance(chart, Chart)
and chart.notes is not None and chart.notes is not None
and chart.notes != 0
and score.pure is not None and score.pure is not None
and score.far is not None and score.far is not None
): ):

View File

@ -1,15 +1,21 @@
from arcaea_offline.calculate import calculate_play_rating import logging
from arcaea_offline.models import Chart, Score
from arcaea_offline.models import Chart, Difficulty, Score, ScoreCalculated, Song
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
logger = logging.getLogger(__name__)
class DbScoreTableModel(DbTableModel): class DbScoreTableModel(DbTableModel):
IdRole = Qt.ItemDataRole.UserRole + 10 IdRole = Qt.ItemDataRole.UserRole + 10
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)
@ -27,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)
@ -112,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:
@ -147,11 +149,12 @@ class DbScoreTableModel(DbTableModel):
return False return False
try: try:
self._db.delete_score(self.__items[row][self.IdRole]) self._db.delete_score(self.__items[row][self.ScoreRole])
if syncDb: if syncDb:
self.syncDb() self.syncDb()
return True return True
except Exception: except Exception:
logger.exception(f"Table[Score]: Cannot remove row {row}")
return False return False
def removeRow(self, row: int, parent=...): def removeRow(self, row: int, parent=...):
@ -180,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()