mirror of
https://github.com/283375/arcaea-offline-pyside-ui.git
synced 2025-04-16 07:40:18 +00:00
365 lines
14 KiB
Python
365 lines
14 KiB
Python
import logging
|
|
|
|
from arcaea_offline.calculate.world_step import (
|
|
AmaneBelowExPartnerBonus,
|
|
AwakenedEtoPartnerBonus,
|
|
AwakenedIlithPartnerBonus,
|
|
AwakenedLunaPartnerBonus,
|
|
LegacyMapStepBooster,
|
|
MayaPartnerBonus,
|
|
MemoriesStepBooster,
|
|
PartnerBonus,
|
|
PlayResult,
|
|
calculate_play_rating_from_step,
|
|
calculate_step,
|
|
calculate_step_original,
|
|
)
|
|
from PySide6.QtCore import (
|
|
QCoreApplication,
|
|
QEasingCurve,
|
|
QObject,
|
|
QSize,
|
|
QTimeLine,
|
|
Signal,
|
|
)
|
|
from PySide6.QtGui import QIcon, QPixmap
|
|
from PySide6.QtWidgets import (
|
|
QAbstractButton,
|
|
QButtonGroup,
|
|
QDialog,
|
|
QGraphicsColorizeEffect,
|
|
QPushButton,
|
|
QVBoxLayout,
|
|
QWidget,
|
|
)
|
|
|
|
from ui.designer.tabs.tabTools.tabTools_StepCalculator_ui import (
|
|
Ui_TabTools_StepCalculator,
|
|
)
|
|
from ui.extends.shared.language import LanguageChangeEventFilter
|
|
from ui.implements.components.chartSelector import ChartSelector
|
|
from ui.implements.components.playRatingCalculator import PlayRatingCalculator
|
|
from ui.implements.components.songIdSelector import SongIdSelectorMode
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ButtonGrayscaleEffectApplier(QObject):
|
|
def __init__(self, parent: QAbstractButton):
|
|
super().__init__(parent)
|
|
self.timeline = QTimeLine(500, self)
|
|
self.timeline.setEasingCurve(QEasingCurve.Type.OutCubic)
|
|
self.timeline.frameChanged.connect(self.applyGrayscaleEffect)
|
|
|
|
parent.toggled.connect(self.triggerEffectAnimation)
|
|
self.triggerEffectAnimation(parent.isChecked())
|
|
|
|
def triggerEffectAnimation(self, buttonEnabled: bool):
|
|
if self.timeline.state() == QTimeLine.State.Running:
|
|
self.timeline.stop()
|
|
startFrame = self.timeline.currentFrame()
|
|
stopFrame = 0 if buttonEnabled else 100
|
|
|
|
self.timeline.setFrameRange(startFrame, stopFrame)
|
|
self.timeline.start()
|
|
|
|
def applyGrayscaleEffect(self, frame: int):
|
|
target: QAbstractButton = self.parent()
|
|
value = frame / 100
|
|
|
|
effect = QGraphicsColorizeEffect(target)
|
|
effect.setColor("#000000")
|
|
effect.setStrength(value)
|
|
target.setGraphicsEffect(effect)
|
|
|
|
|
|
class PlayRatingCalculatorDialog(QDialog):
|
|
accepted = Signal()
|
|
|
|
def __init__(self, parent=None):
|
|
super().__init__(parent)
|
|
|
|
self.verticalLayout = QVBoxLayout(self)
|
|
|
|
self.chartSelector = ChartSelector(self)
|
|
self.chartSelector.setSongIdSelectorMode(SongIdSelectorMode.Chart)
|
|
self.verticalLayout.addWidget(self.chartSelector)
|
|
|
|
self.playRatingCalculator = PlayRatingCalculator(self)
|
|
self.verticalLayout.addWidget(self.playRatingCalculator)
|
|
|
|
self.acceptButton = QPushButton(self)
|
|
self.acceptButton.setText(
|
|
# fmt: off
|
|
QCoreApplication.translate("StepCalculator", "playRatingCalculatorDialog.acceptButton")
|
|
# fmt: on
|
|
)
|
|
self.acceptButton.setEnabled(False)
|
|
self.verticalLayout.addWidget(self.acceptButton)
|
|
|
|
self.chartSelector.valueChanged.connect(self.updatePlayRatingCalculator)
|
|
self.playRatingCalculator.arcaeaScoreLineEdit.textChanged.connect(
|
|
self.updateAcceptButton
|
|
)
|
|
self.acceptButton.clicked.connect(self.accepted)
|
|
|
|
def updatePlayRatingCalculator(self):
|
|
chart = self.chartSelector.value()
|
|
if chart is None:
|
|
self.playRatingCalculator.setConstant(None)
|
|
else:
|
|
self.playRatingCalculator.setConstant(chart.constant)
|
|
self.updateAcceptButton()
|
|
|
|
def updateAcceptButton(self):
|
|
if self.playRatingCalculator.result is None:
|
|
self.acceptButton.setEnabled(False)
|
|
else:
|
|
self.acceptButton.setEnabled(True)
|
|
|
|
def reset(self):
|
|
self.chartSelector.resetButton.click()
|
|
self.playRatingCalculator.arcaeaScoreLineEdit.clear()
|
|
|
|
def value(self):
|
|
return self.playRatingCalculator.result
|
|
|
|
|
|
class TabTools_StepCalculator(Ui_TabTools_StepCalculator, QWidget):
|
|
def __init__(self, parent=None):
|
|
super().__init__(parent)
|
|
self.setupUi(self)
|
|
|
|
self.languageChangeEventFilter = LanguageChangeEventFilter(self)
|
|
self.installEventFilter(self.languageChangeEventFilter)
|
|
|
|
self.calculate_toStep_calculatePlayResultFromScoreButton.clicked.connect(
|
|
self.openChartAndScoreInputDialog
|
|
)
|
|
|
|
# set icons
|
|
staminaIcon = QIcon(":/images/stepCalculator/stamina.png")
|
|
for radioButton in [
|
|
self.legacyPlayPlus_x2StaminaRadioButton,
|
|
self.legacyPlayPlus_x4StaminaRadioButton,
|
|
self.legacyPlayPlus_x6StaminaRadioButton,
|
|
]:
|
|
radioButton.setIcon(staminaIcon)
|
|
radioButton.setIconSize(QSize(25, 15))
|
|
|
|
memoryBoostIcon = QIcon(":/images/stepCalculator/memory-boost.png")
|
|
self.play_memoryBoostCheckBox.setIcon(memoryBoostIcon)
|
|
self.play_memoryBoostCheckBox.setIconSize(QSize(75, 100))
|
|
|
|
mapTypeIconSize = QSize(150, 50)
|
|
|
|
for button, pixmap in zip(
|
|
[
|
|
self.mapTypeLegacyPlayRadioButton,
|
|
self.mapTypeLegacyPlayPlusRadioButton,
|
|
self.mapTypePlayRadioButton,
|
|
],
|
|
[
|
|
QPixmap(":/images/stepCalculator/legacy-play.png"),
|
|
QPixmap(":/images/stepCalculator/legacy-play-plus.png"),
|
|
QPixmap(":/images/stepCalculator/play.png"),
|
|
],
|
|
):
|
|
button.setIconSize(mapTypeIconSize)
|
|
button.setIcon(pixmap)
|
|
|
|
# apply grayscale effects
|
|
self.buttonGrayscaleEffectAppliers = []
|
|
for button in [
|
|
self.mapTypeLegacyPlayRadioButton,
|
|
self.mapTypeLegacyPlayPlusRadioButton,
|
|
self.mapTypePlayRadioButton,
|
|
self.legacyPlayPlus_x2StaminaRadioButton,
|
|
self.legacyPlayPlus_x4StaminaRadioButton,
|
|
self.legacyPlayPlus_x6StaminaRadioButton,
|
|
self.play_memoryBoostCheckBox,
|
|
]:
|
|
applier = ButtonGrayscaleEffectApplier(button)
|
|
self.buttonGrayscaleEffectAppliers.append(applier)
|
|
|
|
# create button groups
|
|
self.mapTypeButtonGroup = QButtonGroup(self)
|
|
self.mapTypeButtonGroup.addButton(self.mapTypeLegacyPlayRadioButton, 0)
|
|
self.mapTypeButtonGroup.addButton(self.mapTypeLegacyPlayPlusRadioButton, 1)
|
|
self.mapTypeButtonGroup.addButton(self.mapTypePlayRadioButton, 2)
|
|
self.mapTypeButtonGroup.idToggled.connect(self.stackedWidget.setCurrentIndex)
|
|
self.mapTypePlayRadioButton.setChecked(True)
|
|
|
|
self.legacyPlayPlusStaminaButtonGroup = QButtonGroup(self)
|
|
self.legacyPlayPlusStaminaButtonGroup.addButton(
|
|
self.legacyPlayPlus_x2StaminaRadioButton, 2
|
|
)
|
|
self.legacyPlayPlusStaminaButtonGroup.addButton(
|
|
self.legacyPlayPlus_x4StaminaRadioButton, 4
|
|
)
|
|
self.legacyPlayPlusStaminaButtonGroup.addButton(
|
|
self.legacyPlayPlus_x6StaminaRadioButton, 6
|
|
)
|
|
self.legacyPlayPlus_x2StaminaRadioButton.setChecked(True)
|
|
|
|
self.legacyPlayPlusFragmentsButtonGroup = QButtonGroup(self)
|
|
self.legacyPlayPlusFragmentsButtonGroup.addButton(
|
|
self.legacyPlayPlus_x11fragRadioButton, 100
|
|
)
|
|
self.legacyPlayPlusFragmentsButtonGroup.addButton(
|
|
self.legacyPlayPlus_x125fragRadioButton, 250
|
|
)
|
|
self.legacyPlayPlusFragmentsButtonGroup.addButton(
|
|
self.legacyPlayPlus_x15fragRadioButton, 500
|
|
)
|
|
|
|
# bind calculate functions
|
|
self.mapTypeButtonGroup.buttonToggled.connect(self.tryCalculate)
|
|
self.legacyPlayPlusStaminaButtonGroup.buttonToggled.connect(self.tryCalculate)
|
|
self.legacyPlayPlusFragmentsButtonGroup.buttonToggled.connect(self.tryCalculate)
|
|
self.play_memoryBoostCheckBox.toggled.connect(self.tryCalculate)
|
|
self.partnerStepValueSpinBox.valueChanged.connect(self.tryCalculate)
|
|
self.partnerSkillGroupBox.toggled.connect(self.tryCalculate)
|
|
self.partnerSkillStepBonusLineEdit.textChanged.connect(self.tryCalculate)
|
|
self.partnerSkillFinalMultiplierLineEdit.textChanged.connect(self.tryCalculate)
|
|
self.calculate_toStep_playResultSpinBox.valueChanged.connect(self.tryCalculate)
|
|
self.calculate_fromStep_targetStepSpinBox.valueChanged.connect(
|
|
self.tryCalculate
|
|
)
|
|
|
|
# connect partner skill preset buttons
|
|
self.partnerSkillPresetButton_awakenedIlith.clicked.connect(
|
|
self.applyPartnerPreset
|
|
)
|
|
self.partnerSkillPresetButton_awakenedEto.clicked.connect(
|
|
self.applyPartnerPreset
|
|
)
|
|
self.partnerSkillPresetButton_awakenedLuna.clicked.connect(
|
|
self.applyPartnerPreset
|
|
)
|
|
self.partnerSkillPresetButton_amaneBelowEx.clicked.connect(
|
|
self.applyPartnerPreset
|
|
)
|
|
self.partnerSkillPresetButton_maya.clicked.connect(self.applyPartnerPreset)
|
|
|
|
self.playRatingCalculatorDialog = PlayRatingCalculatorDialog(self)
|
|
self.playRatingCalculatorDialog.accepted.connect(self.set_toStep_PlayRating)
|
|
|
|
def openChartAndScoreInputDialog(self):
|
|
self.playRatingCalculatorDialog.reset()
|
|
self.playRatingCalculatorDialog.show()
|
|
|
|
def set_toStep_PlayRating(self):
|
|
result = self.playRatingCalculatorDialog.value()
|
|
if result is not None:
|
|
self.calculate_toStep_playResultSpinBox.setValue(result)
|
|
self.playRatingCalculatorDialog.close()
|
|
|
|
def applyPartnerPreset(self):
|
|
if not self.sender():
|
|
return
|
|
|
|
objectName = self.sender().objectName()
|
|
|
|
if not objectName:
|
|
return
|
|
|
|
formatString = "partnerSkillPresetButton_{}"
|
|
if objectName == formatString.format("awakenedIlith"):
|
|
pb = AwakenedIlithPartnerBonus
|
|
elif objectName == formatString.format("awakenedEto"):
|
|
pb = AwakenedEtoPartnerBonus
|
|
elif objectName == formatString.format("awakenedLuna"):
|
|
pb = AwakenedLunaPartnerBonus
|
|
elif objectName == formatString.format("amaneBelowEx"):
|
|
pb = AmaneBelowExPartnerBonus
|
|
elif objectName == formatString.format("maya"):
|
|
pb = MayaPartnerBonus
|
|
else:
|
|
return
|
|
|
|
self.partnerSkillStepBonusLineEdit.setText(str(pb.step_bonus))
|
|
self.partnerSkillFinalMultiplierLineEdit.setText(str(pb.final_multiplier))
|
|
|
|
def toStepPlayResult(self):
|
|
return PlayResult(
|
|
play_rating=self.calculate_toStep_playResultSpinBox.value(),
|
|
partner_step=self.partnerStepValueSpinBox.value(),
|
|
)
|
|
|
|
def partnerBonus(self):
|
|
if self.partnerSkillGroupBox.isChecked():
|
|
try:
|
|
partnerBonus = PartnerBonus(
|
|
step_bonus=self.partnerSkillStepBonusLineEdit.text(),
|
|
final_multiplier=self.partnerSkillFinalMultiplierLineEdit.text(),
|
|
)
|
|
partnerBonus.step_bonus
|
|
partnerBonus.final_multiplier
|
|
return partnerBonus
|
|
except Exception:
|
|
if self.detailedLogOutputCheckBox.isChecked():
|
|
logger.exception("Cannot parse PartnerBonus input")
|
|
return PartnerBonus()
|
|
|
|
return PartnerBonus()
|
|
|
|
def stepBooster(self):
|
|
if self.mapTypeButtonGroup.checkedId() == 1:
|
|
# Legacy Play+
|
|
stamina = self.legacyPlayPlusStaminaButtonGroup.checkedId()
|
|
if self.legacyPlayPlus_useFragmentsGroupBox.isChecked():
|
|
fragment = self.legacyPlayPlusFragmentsButtonGroup.checkedId()
|
|
fragment = fragment if fragment > -1 else None
|
|
else:
|
|
fragment = None
|
|
return None if stamina < 0 else LegacyMapStepBooster(stamina, fragment)
|
|
elif self.mapTypeButtonGroup.checkedId() == 2:
|
|
# General Music Play
|
|
if self.play_memoryBoostCheckBox.isChecked():
|
|
return MemoriesStepBooster()
|
|
else:
|
|
return None
|
|
else:
|
|
return None
|
|
|
|
def tryCalculate(self):
|
|
if self.partnerStepValueSpinBox.value() <= 0.0:
|
|
self.calculate_toStep_resultLabel.setText("...")
|
|
self.calculate_fromStep_resultLabel.setText("...")
|
|
return
|
|
|
|
# toStep
|
|
try:
|
|
playResult = self.toStepPlayResult()
|
|
partnerBonus = self.partnerBonus()
|
|
stepBooster = self.stepBooster()
|
|
|
|
stepOriginal = calculate_step_original(
|
|
playResult, partner_bonus=partnerBonus, step_booster=stepBooster
|
|
)
|
|
step = calculate_step(
|
|
playResult, partner_bonus=partnerBonus, step_booster=stepBooster
|
|
)
|
|
self.calculate_toStep_resultLabel.setText(str(step))
|
|
self.calculate_toStep_detailedResultLabel.setText(str(stepOriginal))
|
|
except Exception:
|
|
if self.detailedLogOutputCheckBox.isChecked():
|
|
logger.exception("Cannot calculate toStep")
|
|
self.calculate_toStep_resultLabel.setText("...")
|
|
|
|
# fromStep
|
|
try:
|
|
fromStepResult = calculate_play_rating_from_step(
|
|
self.calculate_fromStep_targetStepSpinBox.value(),
|
|
self.partnerStepValueSpinBox.value(),
|
|
partner_bonus=partnerBonus,
|
|
step_booster=stepBooster,
|
|
)
|
|
self.calculate_fromStep_resultLabel.setText(str(round(fromStepResult, 2)))
|
|
self.calculate_fromStep_detailedResultLabel.setText(str(fromStepResult))
|
|
except Exception:
|
|
if self.detailedLogOutputCheckBox.isChecked():
|
|
logger.exception("Cannot calculate fromStep")
|
|
self.calculate_fromStep_resultLabel.setText("...")
|