diff --git a/ui/extends/components/chartSelector.py b/ui/extends/components/chartSelector.py
index abf69cc..ea4437b 100644
--- a/ui/extends/components/chartSelector.py
+++ b/ui/extends/components/chartSelector.py
@@ -1,6 +1,6 @@
from arcaea_offline.database import Database
from arcaea_offline.models import Chart
-from arcaea_offline.utils import rating_class_to_short_text
+from arcaea_offline.utils.rating import rating_class_to_short_text
from PySide6.QtCore import Qt
from PySide6.QtGui import QStandardItem, QStandardItemModel
diff --git a/ui/extends/components/ocrQueue.py b/ui/extends/components/ocrQueue.py
index 3e4d731..0ed77f6 100644
--- a/ui/extends/components/ocrQueue.py
+++ b/ui/extends/components/ocrQueue.py
@@ -3,7 +3,7 @@ from typing import Any, Callable, Optional, overload
from arcaea_offline.calculate import calculate_score_range
from arcaea_offline.database import Database
-from arcaea_offline.models import Chart, ScoreInsert
+from arcaea_offline.models import Chart, Score
from arcaea_offline_ocr.b30.shared import B30OcrResultItem
from arcaea_offline_ocr.device.shared import DeviceOcrResult
from PySide6.QtCore import (
@@ -47,14 +47,14 @@ class OcrQueueModel(QAbstractListModel):
ImagePixmapRole = Qt.ItemDataRole.UserRole + 3
OcrResultRole = Qt.ItemDataRole.UserRole + 10
- ScoreInsertRole = Qt.ItemDataRole.UserRole + 11
+ ScoreRole = Qt.ItemDataRole.UserRole + 11
ChartRole = Qt.ItemDataRole.UserRole + 12
ScoreValidateOkRole = Qt.ItemDataRole.UserRole + 13
OcrRunnableRole = Qt.ItemDataRole.UserRole + 20
ProcessOcrResultFuncRole = (
Qt.ItemDataRole.UserRole + 21
- ) # Callable[[imageStr, DeviceOcrResult], tuple[Chart, ScoreInsert]]
+ ) # Callable[[imageStr, DeviceOcrResult], tuple[Chart, Score]]
started = Signal()
progress = Signal(int)
@@ -107,8 +107,8 @@ class OcrQueueModel(QAbstractListModel):
self.updateScoreValidateOk(index.row())
updateRole = role
- if role == self.ScoreInsertRole and isinstance(value, ScoreInsert):
- item[self.ScoreInsertRole] = value
+ if role == self.ScoreRole and isinstance(value, Score):
+ item[self.ScoreRole] = value
self.updateScoreValidateOk(index.row())
updateRole = role
@@ -138,7 +138,7 @@ class OcrQueueModel(QAbstractListModel):
self,
image: str,
runnable: OcrRunnable = None,
- process_func: Callable[[Optional[str], QImage, Any], ScoreInsert] = None,
+ process_func: Callable[[Optional[str], QImage, Any], Score] = None,
):
...
@@ -147,7 +147,7 @@ class OcrQueueModel(QAbstractListModel):
self,
image: QImage,
runnable: OcrRunnable = None,
- process_func: Callable[[Optional[str], QImage, Any], ScoreInsert] = None,
+ process_func: Callable[[Optional[str], QImage, Any], Score] = None,
):
...
@@ -178,7 +178,7 @@ class OcrQueueModel(QAbstractListModel):
self.ImageQImageRole: qImage,
self.ImagePixmapRole: qPixmap,
self.OcrResultRole: None,
- self.ScoreInsertRole: None,
+ self.ScoreRole: None,
self.ChartRole: None,
self.ScoreValidateOkRole: False,
self.OcrRunnableRole: runnable,
@@ -201,7 +201,7 @@ class OcrQueueModel(QAbstractListModel):
self.setData(index, result, self.OcrResultRole)
self.setData(index, chart, self.ChartRole)
- self.setData(index, scoreInsert, self.ScoreInsertRole)
+ self.setData(index, scoreInsert, self.ScoreRole)
return True
@Slot(DeviceOcrResult)
@@ -234,8 +234,8 @@ class OcrQueueModel(QAbstractListModel):
index = self.index(row, 0)
chart = index.data(self.ChartRole)
- score = index.data(self.ScoreInsertRole)
- if isinstance(chart, Chart) and isinstance(score, ScoreInsert):
+ score = index.data(self.ScoreRole)
+ if isinstance(chart, Chart) and isinstance(score, Score):
scoreRange = calculate_score_range(chart, score.pure, score.far)
scoreValidateOk = scoreRange[0] <= score.score <= scoreRange[1]
self.setData(index, scoreValidateOk, self.ScoreValidateOkRole)
@@ -247,8 +247,8 @@ class OcrQueueModel(QAbstractListModel):
return
item = self.__items[row]
- score = item[self.ScoreInsertRole]
- if not isinstance(score, ScoreInsert) or (
+ score = item[self.ScoreRole]
+ if not isinstance(score, Score) or (
not item[self.ScoreValidateOkRole] and not ignoreValidate
):
return
@@ -301,7 +301,7 @@ class OcrQueueTableProxyModel(QAbstractTableModel):
],
[
OcrQueueModel.OcrResultRole,
- OcrQueueModel.ScoreInsertRole,
+ OcrQueueModel.ScoreRole,
OcrQueueModel.ChartRole,
OcrQueueModel.ScoreValidateOkRole,
],
@@ -364,7 +364,7 @@ class OcrQueueTableProxyModel(QAbstractTableModel):
def setData(self, index, value, role):
if index.column() == 2 and role == OcrQueueModel.ChartRole:
return self.sourceModel().setData(index, value, role)
- if index.column() == 3 and role == OcrQueueModel.ScoreInsertRole:
+ if index.column() == 3 and role == OcrQueueModel.ScoreRole:
return self.sourceModel().setData(index, value, role)
return False
@@ -403,8 +403,8 @@ class OcrChartDelegate(ChartDelegate):
class OcrScoreDelegate(ScoreDelegate):
- def getScoreInsert(self, index: QModelIndex):
- return index.data(OcrQueueModel.ScoreInsertRole)
+ def getScore(self, index: QModelIndex):
+ return index.data(OcrQueueModel.ScoreRole)
def getChart(self, index: QModelIndex):
return index.data(OcrQueueModel.ChartRole)
@@ -415,7 +415,7 @@ class OcrScoreDelegate(ScoreDelegate):
def paintWarningBackground(self, index: QModelIndex) -> bool:
return True
# return isinstance(self.getChart(index), Chart) and isinstance(
- # self.getScore(index), ScoreInsert
+ # self.getScore(index), Score
# )
# return isinstance(
# index.data(OcrQueueModel.OcrResultRole), (DeviceOcrResult, B30OcrResultItem)
@@ -423,4 +423,4 @@ class OcrScoreDelegate(ScoreDelegate):
def setModelData(self, editor, model: OcrQueueTableProxyModel, index):
if super().confirmSetModelData(editor):
- model.setData(index, editor.value(), OcrQueueModel.ScoreInsertRole)
+ model.setData(index, editor.value(), OcrQueueModel.ScoreRole)
diff --git a/ui/extends/shared/database.py b/ui/extends/shared/database.py
new file mode 100644
index 0000000..e6a623c
--- /dev/null
+++ b/ui/extends/shared/database.py
@@ -0,0 +1,11 @@
+from typing import Type
+
+from PySide6.QtCore import QUrl
+from sqlalchemy import Engine
+from sqlalchemy import create_engine as sa_create_engine
+from sqlalchemy.pool import NullPool, Pool
+
+
+def create_engine(_url: str | QUrl, pool: Type[Pool] = NullPool) -> Engine:
+ url = _url.toString() if isinstance(_url, QUrl) else _url
+ return sa_create_engine(url, poolclass=pool)
diff --git a/ui/extends/shared/delegates/chartDelegate.py b/ui/extends/shared/delegates/chartDelegate.py
index 93ca7a4..36934ff 100644
--- a/ui/extends/shared/delegates/chartDelegate.py
+++ b/ui/extends/shared/delegates/chartDelegate.py
@@ -1,9 +1,7 @@
-from typing import Union
-
from arcaea_offline.models import Chart
-from arcaea_offline.utils import rating_class_to_short_text, rating_class_to_text
-from PySide6.QtCore import QDateTime, QModelIndex, Qt, Signal
-from PySide6.QtGui import QBrush, QColor
+from arcaea_offline.utils.rating import rating_class_to_short_text, rating_class_to_text
+from PySide6.QtCore import QModelIndex, Qt, Signal
+from PySide6.QtGui import QColor
from PySide6.QtWidgets import (
QFrame,
QHBoxLayout,
diff --git a/ui/extends/shared/delegates/scoreDelegate.py b/ui/extends/shared/delegates/scoreDelegate.py
index 381a65e..db59fc7 100644
--- a/ui/extends/shared/delegates/scoreDelegate.py
+++ b/ui/extends/shared/delegates/scoreDelegate.py
@@ -1,16 +1,12 @@
from typing import Union
from arcaea_offline.calculate import calculate_score_range
-from arcaea_offline.models import Chart, Score, ScoreInsert
-from arcaea_offline.utils import (
- rating_class_to_text,
- score_to_grade_text,
- zip_score_grade,
-)
+from arcaea_offline.models import Chart, Score
+from arcaea_offline.utils.rating import rating_class_to_text
+from arcaea_offline.utils.score import score_to_grade_text, zip_score_grade
from PySide6.QtCore import QAbstractItemModel, QDateTime, QModelIndex, Qt, Signal
from PySide6.QtGui import QColor, QFont, QLinearGradient
from PySide6.QtWidgets import (
- QAbstractItemDelegate,
QFrame,
QHBoxLayout,
QLabel,
@@ -53,7 +49,7 @@ class ScoreEditorDelegateWrapper(ScoreEditor):
self.formLayout.insertRow(0, self.delegateHeader)
- def setText(self, score: Score | ScoreInsert, _extra: str = None):
+ def setText(self, score: Score, _extra: str = None):
text = "Editing "
text += _extra or ""
text += f"score {score.score}"
@@ -91,22 +87,14 @@ class ScoreDelegate(TextSegmentDelegate):
def getScore(self, index: QModelIndex) -> Score | None:
return None
- def getScoreInsert(self, index: QModelIndex) -> ScoreInsert | None:
- return None
-
- def _getScore(self, index: QModelIndex):
- score = self.getScore(index)
- scoreInsert = self.getScoreInsert(index)
- return scoreInsert if score is None else score
-
def getChart(self, index: QModelIndex) -> Chart | None:
return None
def getScoreValidateOk(self, index: QModelIndex) -> bool | None:
- score = self._getScore(index)
+ score = self.getScore(index)
chart = self.getChart(index)
- if isinstance(score, (Score, ScoreInsert)) and isinstance(chart, Chart):
+ if isinstance(score, Score) and isinstance(chart, Chart):
scoreRange = calculate_score_range(chart, score.pure, score.far)
return scoreRange[0] <= score.score <= scoreRange[1]
@@ -114,9 +102,9 @@ class ScoreDelegate(TextSegmentDelegate):
return zip_score_grade(score, self.GradeGradientsWrappers)
def getTextSegments(self, index, option):
- score = self._getScore(index)
+ score = self.getScore(index)
chart = self.getChart(index)
- if not (isinstance(score, (Score, ScoreInsert)) and isinstance(chart, Chart)):
+ if not (isinstance(score, Score) and isinstance(chart, Chart)):
return [
[
{
@@ -176,10 +164,10 @@ class ScoreDelegate(TextSegmentDelegate):
def paint(self, painter, option, index):
# draw scoreMismatch warning background
- score = self._getScore(index)
+ score = self.getScore(index)
chart = self.getChart(index)
if (
- isinstance(score, (Score, ScoreInsert))
+ isinstance(score, Score)
and isinstance(chart, Chart)
and self.paintWarningBackground(index)
):
@@ -206,16 +194,16 @@ class ScoreDelegate(TextSegmentDelegate):
self.closeEditor.emit(editor)
def createEditor(self, parent, option, index) -> ScoreEditorDelegateWrapper:
- score = self._getScore(index)
+ score = self.getScore(index)
chart = self.getChart(index)
- if isinstance(score, (Score, ScoreInsert)) and isinstance(chart, Chart):
+ if isinstance(score, Score) and isinstance(chart, Chart):
editor = ScoreEditorDelegateWrapper(parent)
editor.setWindowFlag(Qt.WindowType.Sheet, True)
editor.setWindowFlag(Qt.WindowType.FramelessWindowHint, True)
editor.setWindowTitle(
f"{chart.name_en}({chart.song_id}) | {rating_class_to_text(chart.rating_class)} | {chart.package_id}"
)
- editor.setText(self._getScore(index))
+ editor.setText(self.getScore(index))
editor.setValidateBeforeAccept(False)
editor.move(parent.mapToGlobal(parent.pos()))
editor.accepted.connect(self._commitEditor)
@@ -231,9 +219,9 @@ class ScoreDelegate(TextSegmentDelegate):
keepWidgetInScreen(editor)
def setEditorData(self, editor: ScoreEditorDelegateWrapper, index) -> None:
- score = self._getScore(index)
+ score = self.getScore(index)
chart = self.getChart(index)
- if isinstance(score, (Score, ScoreInsert)) and isinstance(chart, Chart):
+ if isinstance(score, Score) and isinstance(chart, Chart):
editor.setChart(chart)
editor.setValue(score)
diff --git a/ui/extends/shared/models/tables/score.py b/ui/extends/shared/models/tables/score.py
index 69f3f11..b22cdcf 100644
--- a/ui/extends/shared/models/tables/score.py
+++ b/ui/extends/shared/models/tables/score.py
@@ -1,5 +1,5 @@
-from arcaea_offline.calculate import calculate_score
-from arcaea_offline.models import Chart, Score, ScoreInsert
+# from arcaea_offline.calculate import calculate_score
+from arcaea_offline.models import Chart, Score
from PySide6.QtCore import QCoreApplication, QModelIndex, QSortFilterProxyModel, Qt
from .base import DbTableModel
diff --git a/ui/extends/shared/settings.py b/ui/extends/shared/settings.py
index 0d56844..ddbdb68 100644
--- a/ui/extends/shared/settings.py
+++ b/ui/extends/shared/settings.py
@@ -1,7 +1,7 @@
-from PySide6.QtCore import QDir, QSettings
+from PySide6.QtCore import QDir, QSettings, QUrl
__all__ = [
- "DATABASE_PATH",
+ "DATABASE_URL",
"DEVICES_JSON_FILE",
"DEVICE_UUID",
"TESSERACT_FILE",
@@ -10,7 +10,7 @@ __all__ = [
"Settings",
]
-DATABASE_PATH = "General/DatabasePath"
+DATABASE_URL = "General/DatabaseUrl"
DEVICES_JSON_FILE = "Ocr/DevicesJsonFile"
DEVICE_UUID = "Ocr/DeviceUuid"
@@ -27,6 +27,13 @@ class Settings(QSettings):
parent,
)
+ def databaseUrl(self) -> str | None:
+ return self.value(DATABASE_URL, None, str)
+
+ def setDatabaseUrl(self, value: str):
+ self.setValue(DATABASE_URL, value)
+ self.sync()
+
def devicesJsonFile(self) -> str | None:
return self.value(DEVICES_JSON_FILE, None, str)
diff --git a/ui/extends/tabs/tabOcr/tabOcr_B30.py b/ui/extends/tabs/tabOcr/tabOcr_B30.py
index c58dab2..b0d7b62 100644
--- a/ui/extends/tabs/tabOcr/tabOcr_B30.py
+++ b/ui/extends/tabs/tabOcr/tabOcr_B30.py
@@ -1,7 +1,7 @@
import logging
from arcaea_offline.database import Database
-from arcaea_offline.models import Chart, ScoreInsert
+from arcaea_offline.models import Chart, Score
from arcaea_offline_ocr.b30.chieri.v4.ocr import ChieriBotV4Ocr
from arcaea_offline_ocr.b30.shared import B30OcrResultItem
from PySide6.QtGui import QImage
diff --git a/ui/extends/tabs/tabOcr/tabOcr_Device.py b/ui/extends/tabs/tabOcr/tabOcr_Device.py
index 14a0598..eadde12 100644
--- a/ui/extends/tabs/tabOcr/tabOcr_Device.py
+++ b/ui/extends/tabs/tabOcr/tabOcr_Device.py
@@ -3,7 +3,7 @@ import logging
from typing import Tuple
from arcaea_offline.database import Database
-from arcaea_offline.models import Chart, ScoreInsert
+from arcaea_offline.models import Chart, Score
from arcaea_offline_ocr.device.shared import DeviceOcrResult
from arcaea_offline_ocr.device.v2.ocr import DeviceV2Ocr
from arcaea_offline_ocr.device.v2.rois import DeviceV2Rois
@@ -52,9 +52,7 @@ def getImageDate(imagePath: str) -> QDateTime:
class ScoreInsertConverter:
@staticmethod
- def deviceV2(
- imagePath: str, _, result: DeviceOcrResult
- ) -> Tuple[Chart, ScoreInsert]:
+ def deviceV2(imagePath: str, _, result: DeviceOcrResult) -> Tuple[Chart, Score]:
db = Database()
scoreInsert = ScoreInsert(
song_id=result.song_id,
diff --git a/ui/implements/components/chartSelector.py b/ui/implements/components/chartSelector.py
index 8e3208a..687c48b 100644
--- a/ui/implements/components/chartSelector.py
+++ b/ui/implements/components/chartSelector.py
@@ -1,10 +1,11 @@
+import re
from typing import Literal
from arcaea_offline.database import Database
-from arcaea_offline.models import Chart, Package
-from arcaea_offline.utils import rating_class_to_text
+from arcaea_offline.models import Chart, Pack
+from arcaea_offline.utils.rating import rating_class_to_text
from PySide6.QtCore import QModelIndex, Qt, Signal, Slot
-from PySide6.QtGui import QColor
+from PySide6.QtGui import QColor, QShowEvent
from PySide6.QtWidgets import QCompleter, QWidget
from ui.designer.components.chartSelector_ui import Ui_ChartSelector
@@ -19,7 +20,6 @@ class ChartSelector(Ui_ChartSelector, QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.db = Database()
- self.db.register_update_hook(self.fillPackageComboBox)
self.setupUi(self)
self.pstButton.setColors(QColor("#399bb2"), QColor("#f0f8fa"))
@@ -107,19 +107,28 @@ class ChartSelector(Ui_ChartSelector, QWidget):
ratingClass = self.selectedRatingClass()
if packageId and songId and isinstance(ratingClass, int):
- return Chart.from_db_row(self.db.get_chart(songId, ratingClass))
+ return self.db.get_chart(songId, ratingClass)
return None
+ def showEvent(self, event: QShowEvent):
+ # update database results when widget visible
+ self.fillPackageComboBox()
+ return super().showEvent(event)
+
@Slot()
def updateResultLabel(self):
chart = self.value()
if isinstance(chart, Chart):
- package = Package.from_db_row(
- self.db.get_package_by_package_id(chart.package_id)
- )
+ pack = self.db.get_pack_by_id(chart.set)
texts = [
- [package.name, chart.name_en, rating_class_to_text(chart.rating_class)],
- [package.id, chart.song_id, str(chart.rating_class)],
+ [
+ pack.name,
+ chart.title,
+ f"{rating_class_to_text(chart.rating_class)} "
+ f"{chart.rating}{'+' if chart.rating_plus else ''}"
+ f"({chart.constant / 10})",
+ ],
+ [pack.id, chart.song_id, str(chart.rating_class)],
]
texts = [" | ".join(t) for t in texts]
text = f'{texts[0]}
{texts[1]}'
@@ -129,37 +138,41 @@ class ChartSelector(Ui_ChartSelector, QWidget):
def fillPackageComboBox(self):
self.packageComboBox.clear()
- packages = [Package.from_db_row(dbRow) for dbRow in self.db.get_packages()]
- for package in packages:
- self.packageComboBox.addItem(f"{package.name} ({package.id})", package.id)
+ packs = self.db.get_packs()
+ for pack in packs:
+ isAppendPack = re.search(r"_append_.*$", pack.id)
+ if isAppendPack:
+ basePackId = re.sub(r"_append_.*$", "", pack.id)
+ basePackName = self.db.get_pack_by_id(basePackId).name
+ packName = f"{basePackName} - {pack.name}"
+ else:
+ packName = pack.name
+ self.packageComboBox.addItem(f"{packName} ({pack.id})", pack.id)
row = self.packageComboBox.count() - 1
self.packageComboBox.setItemData(
- row, package.name, DescriptionDelegate.MainTextRole
+ row, packName, DescriptionDelegate.MainTextRole
)
self.packageComboBox.setItemData(
- row, package.id, DescriptionDelegate.DescriptionTextRole
+ row, pack.id, DescriptionDelegate.DescriptionTextRole
)
self.packageComboBox.setCurrentIndex(-1)
def fillSongIdComboBox(self):
self.songIdComboBox.clear()
- packageId = self.packageComboBox.currentData()
- if packageId:
- charts = [
- Chart.from_db_row(dbRow)
- for dbRow in self.db.get_charts_by_package_id(packageId)
- ]
+ packId = self.packageComboBox.currentData()
+ if packId:
+ charts = self.db.get_charts_by_pack_id(packId)
inserted_song_ids = []
for chart in charts:
if chart.song_id not in inserted_song_ids:
self.songIdComboBox.addItem(
- f"{chart.name_en} ({chart.song_id})", chart.song_id
+ f"{chart.title} ({chart.song_id})", chart.song_id
)
inserted_song_ids.append(chart.song_id)
row = self.songIdComboBox.count() - 1
self.songIdComboBox.setItemData(
- row, chart.name_en, DescriptionDelegate.MainTextRole
+ row, chart.title, DescriptionDelegate.MainTextRole
)
self.songIdComboBox.setItemData(
row, chart.song_id, DescriptionDelegate.DescriptionTextRole
@@ -174,12 +187,7 @@ class ChartSelector(Ui_ChartSelector, QWidget):
def on_songIdComboBox_currentIndexChanged(self, index: int):
rating_classes = []
if index > -1:
- charts = [
- Chart.from_db_row(dbRow)
- for dbRow in self.db.get_charts_by_song_id(
- self.songIdComboBox.currentData()
- )
- ]
+ charts = self.db.get_charts_by_song_id(self.songIdComboBox.currentData())
rating_classes = [chart.rating_class for chart in charts]
self.updateRatingClassButtonsEnabled(rating_classes)
@@ -196,7 +204,7 @@ class ChartSelector(Ui_ChartSelector, QWidget):
self.fuzzySearchCompleterModel.clear()
def selectChart(self, chart: Chart):
- packageIdIndex = self.packageComboBox.findData(chart.package_id)
+ packageIdIndex = self.packageComboBox.findData(chart.set)
if packageIdIndex > -1:
self.packageComboBox.setCurrentIndex(packageIdIndex)
else:
diff --git a/ui/implements/components/scoreEditor.py b/ui/implements/components/scoreEditor.py
index 0ed7803..bdd7233 100644
--- a/ui/implements/components/scoreEditor.py
+++ b/ui/implements/components/scoreEditor.py
@@ -2,7 +2,7 @@ from enum import IntEnum
from typing import Optional
from arcaea_offline.calculate import calculate_score_range
-from arcaea_offline.models import Chart, Score, ScoreInsert
+from arcaea_offline.models import Chart, Score
from PySide6.QtCore import QCoreApplication, QDateTime, Signal, Slot
from PySide6.QtWidgets import QMessageBox, QWidget
@@ -37,9 +37,9 @@ class ScoreEditor(Ui_ScoreEditor, QWidget):
self.valueChanged.connect(self.validateScore)
self.valueChanged.connect(self.updateValidateLabel)
- self.clearTypeComboBox.addItem("HARD LOST", -1)
self.clearTypeComboBox.addItem("TRACK LOST", 0)
self.clearTypeComboBox.addItem("TRACK COMPLETE", 1)
+ self.clearTypeComboBox.addItem("HARD LOST", 2)
self.clearTypeComboBox.setCurrentIndex(-1)
def setValidateBeforeAccept(self, __bool: bool):
@@ -159,33 +159,33 @@ class ScoreEditor(Ui_ScoreEditor, QWidget):
def value(self):
if isinstance(self.__chart, Chart):
- return ScoreInsert(
+ return Score(
song_id=self.__chart.song_id,
rating_class=self.__chart.rating_class,
score=self.score(),
pure=self.pureSpinBox.value(),
far=self.farSpinBox.value(),
lost=self.lostSpinBox.value(),
- time=self.dateTimeEdit.dateTime().toSecsSinceEpoch(),
+ date=self.dateTimeEdit.dateTime().toSecsSinceEpoch(),
max_recall=self.maxRecallSpinBox.value()
if self.maxRecallSpinBox.value() > -1
else None,
- clear_type=None,
+ r10_clear_type=None,
)
- def setValue(self, score: Score | ScoreInsert):
- if isinstance(score, (Score, ScoreInsert)):
+ def setValue(self, score: Score):
+ if isinstance(score, Score):
scoreText = str(score.score)
scoreText = scoreText.rjust(8, "0")
self.scoreLineEdit.setText(scoreText)
self.pureSpinBox.setValue(score.pure)
self.farSpinBox.setValue(score.far)
self.lostSpinBox.setValue(score.lost)
- self.dateTimeEdit.setDateTime(QDateTime.fromSecsSinceEpoch(score.time))
+ self.dateTimeEdit.setDateTime(QDateTime.fromSecsSinceEpoch(score.date))
if score.max_recall is not None:
self.maxRecallSpinBox.setValue(score.max_recall)
- if score.clear_type is not None:
- self.clearTypeComboBox.setCurrentIndex(score.clear_type)
+ if score.r10_clear_type is not None:
+ self.clearTypeComboBox.setCurrentIndex(score.r10_clear_type)
def reset(self):
self.setChart(None)
diff --git a/ui/implements/tabs/tabDb/tabDb_B30TableViewer.py b/ui/implements/tabs/tabDb/tabDb_B30TableViewer.py
index b113d2d..8d8aafc 100644
--- a/ui/implements/tabs/tabDb/tabDb_B30TableViewer.py
+++ b/ui/implements/tabs/tabDb/tabDb_B30TableViewer.py
@@ -1,4 +1,3 @@
-from arcaea_offline.models import ScoreInsert
from PySide6.QtCore import QModelIndex, Qt, Slot
from PySide6.QtGui import QColor, QPalette
from PySide6.QtWidgets import QMessageBox
@@ -21,7 +20,7 @@ class TableScoreDelegate(ScoreDelegate):
def getChart(self, index):
return index.data(DbB30TableModel.ChartRole)
- def getScoreInsert(self, index: QModelIndex) -> ScoreInsert | None:
+ def getScoreInsert(self, index: QModelIndex):
return super().getScoreInsert(index)
def getScore(self, index):
diff --git a/ui/implements/tabs/tabDb/tabDb_Manage.py b/ui/implements/tabs/tabDb/tabDb_Manage.py
index 986ca47..59c78c5 100644
--- a/ui/implements/tabs/tabDb/tabDb_Manage.py
+++ b/ui/implements/tabs/tabDb/tabDb_Manage.py
@@ -2,7 +2,8 @@ import logging
import traceback
from arcaea_offline.database import Database
-from arcaea_offline.external import St3ScoreSource
+from arcaea_offline.external.arcaea.st3 import St3ScoreParser
+from arcaea_offline.external.arcsong import ArcsongDbParser
from PySide6.QtCore import Slot
from PySide6.QtWidgets import QFileDialog, QMessageBox, QWidget
@@ -26,7 +27,11 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
return
try:
- Database().update_arcsong_db(dbFile)
+ db = Database()
+ parser = ArcsongDbParser(dbFile)
+ with db.sessionmaker() as session:
+ parser.write_database(session)
+ session.commit()
QMessageBox.information(self, None, "OK")
except Exception as e:
logging.exception("Sync arcsong.db error")
@@ -42,11 +47,14 @@ class TabDb_Manage(Ui_TabDb_Manage, QWidget):
return
try:
- scores = St3ScoreSource(dbFile).get_score_items()
+ db = Database()
+ parser = St3ScoreParser(dbFile)
logger.info(
- f"Got {len(scores)} items from {dbFile}, writing into database..."
+ f"Got {len(parser.parse())} items from {dbFile}, writing into database..."
)
- Database().import_external(scores)
+ with db.sessionmaker() as session:
+ parser.write_database(session)
+ session.commit()
QMessageBox.information(self, None, "OK")
except Exception as e:
logging.exception("import st3 error")
diff --git a/ui/implements/tabs/tabDb/tabDb_ScoreTableViewer.py b/ui/implements/tabs/tabDb/tabDb_ScoreTableViewer.py
index 8e117fe..36982bd 100644
--- a/ui/implements/tabs/tabDb/tabDb_ScoreTableViewer.py
+++ b/ui/implements/tabs/tabDb/tabDb_ScoreTableViewer.py
@@ -1,4 +1,4 @@
-from arcaea_offline.models import ScoreInsert
+from arcaea_offline.models import Score
from PySide6.QtCore import QModelIndex, Qt, Slot
from PySide6.QtGui import QColor, QPalette
from PySide6.QtWidgets import QMessageBox
@@ -21,9 +21,6 @@ class TableScoreDelegate(ScoreDelegate):
def getChart(self, index):
return index.data(DbScoreTableModel.ChartRole)
- def getScoreInsert(self, index: QModelIndex) -> ScoreInsert | None:
- return super().getScoreInsert(index)
-
def getScore(self, index):
return index.data(DbScoreTableModel.ScoreRole)
diff --git a/ui/implements/tabs/tabOcr/tabOcr_Device.py b/ui/implements/tabs/tabOcr/tabOcr_Device.py
index a06a768..87fd302 100644
--- a/ui/implements/tabs/tabOcr/tabOcr_Device.py
+++ b/ui/implements/tabs/tabOcr/tabOcr_Device.py
@@ -1,7 +1,6 @@
import logging
import cv2
-import pytesseract
# from arcaea_offline_ocr_device_creation_wizard.implements.wizard import Wizard
from arcaea_offline_ocr.device.v1.definition import DeviceV1
diff --git a/ui/implements/tabs/tabOverview.py b/ui/implements/tabs/tabOverview.py
index 7ef4d44..757f106 100644
--- a/ui/implements/tabs/tabOverview.py
+++ b/ui/implements/tabs/tabOverview.py
@@ -1,4 +1,5 @@
from arcaea_offline.database import Database
+from PySide6.QtGui import QShowEvent
from PySide6.QtWidgets import QWidget
from ui.designer.tabs.tabOverview_ui import Ui_TabOverview
@@ -10,8 +11,12 @@ class TabOverview(Ui_TabOverview, QWidget):
self.setupUi(self)
self.db = Database()
- self.db.register_update_hook(self.updateOverview)
+ # self.db.register_update_hook(self.updateOverview)
+ # self.updateOverview()
+
+ def showEvent(self, event: QShowEvent) -> None:
self.updateOverview()
+ return super().showEvent(event)
def updateOverview(self):
b30 = self.db.get_b30() or 0.00
diff --git a/ui/startup/databaseChecker_ui.py b/ui/startup/databaseChecker_ui.py
index 8feeb4a..41b5eb1 100644
--- a/ui/startup/databaseChecker_ui.py
+++ b/ui/startup/databaseChecker_ui.py
@@ -8,119 +8,173 @@
## 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, QFormLayout, QFrame, QHBoxLayout,
- QLabel, QLineEdit, QPushButton, QSizePolicy,
- QSpacerItem, QWidget)
+from PySide6.QtCore import (
+ QCoreApplication,
+ QDate,
+ QDateTime,
+ QLocale,
+ QMetaObject,
+ QObject,
+ QPoint,
+ QRect,
+ QSize,
+ Qt,
+ QTime,
+ QUrl,
+)
+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,
+ QFormLayout,
+ QFrame,
+ QHBoxLayout,
+ QLabel,
+ QLineEdit,
+ QPushButton,
+ QSizePolicy,
+ QSpacerItem,
+ QWidget,
+)
from ui.implements.components.fileSelector import FileSelector
+
class Ui_DatabaseChecker(object):
def setupUi(self, DatabaseChecker):
if not DatabaseChecker.objectName():
- DatabaseChecker.setObjectName(u"DatabaseChecker")
+ DatabaseChecker.setObjectName("DatabaseChecker")
DatabaseChecker.resize(350, 250)
- DatabaseChecker.setWindowTitle(u"DatabaseChecker")
+ DatabaseChecker.setWindowTitle("DatabaseChecker")
self.formLayout = QFormLayout(DatabaseChecker)
- self.formLayout.setObjectName(u"formLayout")
- self.formLayout.setLabelAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
+ self.formLayout.setObjectName("formLayout")
+ self.formLayout.setLabelAlignment(
+ Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter
+ )
self.label = QLabel(DatabaseChecker)
- self.label.setObjectName(u"label")
+ self.label.setObjectName("label")
self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label)
self.dbDirSelector = FileSelector(DatabaseChecker)
- self.dbDirSelector.setObjectName(u"dbDirSelector")
+ self.dbDirSelector.setObjectName("dbDirSelector")
self.formLayout.setWidget(0, QFormLayout.FieldRole, self.dbDirSelector)
self.label_3 = QLabel(DatabaseChecker)
- self.label_3.setObjectName(u"label_3")
+ self.label_3.setObjectName("label_3")
self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_3)
self.dbFilenameLineEdit = QLineEdit(DatabaseChecker)
- self.dbFilenameLineEdit.setObjectName(u"dbFilenameLineEdit")
+ self.dbFilenameLineEdit.setObjectName("dbFilenameLineEdit")
self.formLayout.setWidget(1, QFormLayout.FieldRole, self.dbFilenameLineEdit)
self.horizontalLayout = QHBoxLayout()
- self.horizontalLayout.setObjectName(u"horizontalLayout")
- self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.horizontalSpacer = QSpacerItem(
+ 40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum
+ )
self.horizontalLayout.addItem(self.horizontalSpacer)
self.confirmDbPathButton = QPushButton(DatabaseChecker)
- self.confirmDbPathButton.setObjectName(u"confirmDbPathButton")
+ self.confirmDbPathButton.setObjectName("confirmDbPathButton")
sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
- sizePolicy.setHeightForWidth(self.confirmDbPathButton.sizePolicy().hasHeightForWidth())
+ sizePolicy.setHeightForWidth(
+ self.confirmDbPathButton.sizePolicy().hasHeightForWidth()
+ )
self.confirmDbPathButton.setSizePolicy(sizePolicy)
self.horizontalLayout.addWidget(self.confirmDbPathButton)
-
self.formLayout.setLayout(2, QFormLayout.FieldRole, self.horizontalLayout)
self.dbVersionLabel = QLabel(DatabaseChecker)
- self.dbVersionLabel.setObjectName(u"dbVersionLabel")
- self.dbVersionLabel.setText(u"-")
+ self.dbVersionLabel.setObjectName("dbVersionLabel")
+ self.dbVersionLabel.setText("-")
self.formLayout.setWidget(4, QFormLayout.FieldRole, self.dbVersionLabel)
- self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
+ self.verticalSpacer = QSpacerItem(
+ 20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding
+ )
self.formLayout.setItem(6, QFormLayout.FieldRole, self.verticalSpacer)
self.label_5 = QLabel(DatabaseChecker)
- self.label_5.setObjectName(u"label_5")
+ self.label_5.setObjectName("label_5")
self.formLayout.setWidget(7, QFormLayout.LabelRole, self.label_5)
self.dbCheckConnLabel = QLabel(DatabaseChecker)
- self.dbCheckConnLabel.setObjectName(u"dbCheckConnLabel")
- self.dbCheckConnLabel.setText(u"...")
+ self.dbCheckConnLabel.setObjectName("dbCheckConnLabel")
+ self.dbCheckConnLabel.setText("...")
self.formLayout.setWidget(7, QFormLayout.FieldRole, self.dbCheckConnLabel)
self.continueButton = QPushButton(DatabaseChecker)
- self.continueButton.setObjectName(u"continueButton")
+ self.continueButton.setObjectName("continueButton")
self.continueButton.setEnabled(False)
self.formLayout.setWidget(8, QFormLayout.SpanningRole, self.continueButton)
self.label_2 = QLabel(DatabaseChecker)
- self.label_2.setObjectName(u"label_2")
+ self.label_2.setObjectName("label_2")
self.formLayout.setWidget(4, QFormLayout.LabelRole, self.label_2)
self.line = QFrame(DatabaseChecker)
- self.line.setObjectName(u"line")
+ self.line.setObjectName("line")
self.line.setFrameShape(QFrame.HLine)
self.line.setFrameShadow(QFrame.Sunken)
self.formLayout.setWidget(3, QFormLayout.SpanningRole, self.line)
-
self.retranslateUi(DatabaseChecker)
QMetaObject.connectSlotsByName(DatabaseChecker)
+
# setupUi
def retranslateUi(self, DatabaseChecker):
- self.label.setText(QCoreApplication.translate("DatabaseChecker", u"dbPathLabel", None))
- self.label_3.setText(QCoreApplication.translate("DatabaseChecker", u"dbFilenameLabel", None))
- self.confirmDbPathButton.setText(QCoreApplication.translate("DatabaseChecker", u"confirmDbPathButton", None))
- self.label_5.setText(QCoreApplication.translate("DatabaseChecker", u"dbCheckConnLabel", None))
- self.continueButton.setText(QCoreApplication.translate("DatabaseChecker", u"continueButton", None))
- self.label_2.setText(QCoreApplication.translate("DatabaseChecker", u"dbVersionLabel", None))
+ self.label.setText(
+ QCoreApplication.translate("DatabaseChecker", "dbPathLabel", None)
+ )
+ self.label_3.setText(
+ QCoreApplication.translate("DatabaseChecker", "dbFilenameLabel", None)
+ )
+ self.confirmDbPathButton.setText(
+ QCoreApplication.translate("DatabaseChecker", "confirmDbPathButton", None)
+ )
+ self.label_5.setText(
+ QCoreApplication.translate("DatabaseChecker", "dbCheckConnLabel", None)
+ )
+ self.continueButton.setText(
+ QCoreApplication.translate("DatabaseChecker", "continueButton", None)
+ )
+ self.label_2.setText(
+ QCoreApplication.translate("DatabaseChecker", "dbVersionLabel", None)
+ )
pass
- # retranslateUi
+ # retranslateUi