238 lines
7.8 KiB
Python
238 lines
7.8 KiB
Python
import random
|
|
import sys
|
|
import os
|
|
|
|
from PySide2.QtCore import (QAbstractAnimation, Qt, QPropertyAnimation, Property, Signal, QTimer)
|
|
from PySide2.QtWidgets import (QWidget, QLineEdit, QHBoxLayout, QGridLayout, QVBoxLayout, QPushButton, QLabel, QApplication)
|
|
|
|
if not __name__ == "__main__":
|
|
current_dir = os.getcwd()
|
|
sys.path.append(current_dir)
|
|
hs_file = current_dir + "/general/highscore.txt"
|
|
else:
|
|
hs_file = "./sudoku/general/highscore.txt"
|
|
|
|
from general import highscore as hs
|
|
from .textbox import AnimatedLabel
|
|
|
|
if not os.path.exists(hs_file):
|
|
print('Missing High Score file. Generating one. ')
|
|
hs.generate_highscore_file(hs_file)
|
|
|
|
BACKWARD = 1
|
|
FORWARD = -1
|
|
|
|
|
|
class HighScoreBoard(QWidget):
|
|
highScoreSet = Signal()
|
|
|
|
def __init__(self, width, height):
|
|
super().__init__()
|
|
|
|
self.final_time = "00:10:00"
|
|
self.current_difficulty = hs.DIFFICULTIES[1]
|
|
self.layout = QVBoxLayout(self)
|
|
self.layout.setAlignment(Qt.AlignCenter)
|
|
self.layout.addWidget(QLabel('Score Board', self, alignment=Qt.AlignCenter))
|
|
self.diff_switch = DifficultySwitch()
|
|
self.layout.addLayout(self.diff_switch)
|
|
self.score_grid = ScoreGrid()
|
|
self.layout.addLayout(self.score_grid)
|
|
self.name_input = NameInput()
|
|
self.layout.addWidget(self.name_input)
|
|
|
|
self.setFixedSize(width, height)
|
|
|
|
self.setStyleSheet("""
|
|
background-color: rgb(0, 0, 0);
|
|
color: rgb(255, 255, 255);
|
|
""")
|
|
|
|
self.name_input.setVisible(False)
|
|
|
|
self.diff_switch.difficultySelected.connect(self.change_score_board)
|
|
self.name_input.nameReceived.connect(self.set_score)
|
|
self.score_grid.scoreUpdate.connect(self.diff_switch.go_to_difficulty)
|
|
|
|
def change_score_board(self, difficulty):
|
|
self.score_grid.replace_scores(difficulty)
|
|
|
|
def show_scores(self, toggle):
|
|
if self.isVisible():
|
|
self.score_grid.show_score_info(toggle)
|
|
|
|
def set_score(self, name):
|
|
self.score_grid.set_highscore(self.current_difficulty, name, self.final_time)
|
|
self.name_input.setVisible(False)
|
|
self.highScoreSet.emit()
|
|
|
|
def check_ranking(self, difficulty, time):
|
|
self.current_difficulty = difficulty
|
|
self.final_time = time
|
|
rank = self.score_grid.get_rank(difficulty, time)
|
|
if rank >= 0:
|
|
self.diff_switch.go_to_difficulty(difficulty)
|
|
self.score_grid.replace_scores(difficulty)
|
|
self.name_input.setVisible(True)
|
|
self.name_input.rank_label.setText(str(rank+1))
|
|
self.name_input.time_display.setText(time)
|
|
return True
|
|
return False
|
|
|
|
|
|
class DifficultySwitch(QHBoxLayout):
|
|
difficultySelected = Signal(str)
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
circular_text = hs.DIFFICULTIES.copy()
|
|
circular_text.insert(0, hs.DIFFICULTIES[-1])
|
|
circular_text.append(hs.DIFFICULTIES[0])
|
|
self.max_length = max(len(diff) for diff in hs.DIFFICULTIES)
|
|
self.full_text = ''.join(d.center(self.max_length) for d in circular_text[::-1])
|
|
left_btn = QPushButton('<')
|
|
left_btn.setFixedSize(20, 20)
|
|
self.difficulty_display = QLabel('Normal')
|
|
self.difficulty_display.setAlignment(Qt.AlignCenter)
|
|
right_btn = QPushButton('>')
|
|
right_btn.setFixedSize(20, 20)
|
|
|
|
self.addWidget(left_btn)
|
|
self.addWidget(self.difficulty_display)
|
|
self.addWidget(right_btn)
|
|
self.layout().setStretch(1, 2)
|
|
|
|
self.shift_direction = FORWARD
|
|
self.show_pos = self.max_length * len(hs.DIFFICULTIES)
|
|
self.next_pos = self.max_length * len(hs.DIFFICULTIES)
|
|
self.timer = QTimer(self)
|
|
self.timer.setInterval(20)
|
|
self.timer.timeout.connect(self.shift_pos)
|
|
left_btn.clicked.connect(lambda: self.shift_difficulty(BACKWARD))
|
|
right_btn.clicked.connect(lambda: self.shift_difficulty(FORWARD))
|
|
|
|
@Property(int)
|
|
def show_pos(self):
|
|
"""
|
|
int : The value for the animation
|
|
|
|
When the value is set, the text to be shown is selected from the full text.
|
|
"""
|
|
return self._shown_length
|
|
|
|
@show_pos.setter
|
|
def show_pos(self, value):
|
|
self._shown_length = value
|
|
self.difficulty_display.setText(self.full_text[value:value+self.max_length])
|
|
|
|
def shift_difficulty(self, direction):
|
|
if not self.timer.isActive():
|
|
self.shift_direction = direction
|
|
self.next_pos = self.circular_value(self.next_pos + direction * self.max_length)
|
|
self.timer.start()
|
|
|
|
def go_to_difficulty(self, difficulty):
|
|
pos = (hs.DIFFICULTIES[::-1].index(difficulty) + 1) * self.max_length
|
|
self.show_pos = pos
|
|
self.next_pos = pos
|
|
|
|
def shift_pos(self):
|
|
self.show_pos = self.circular_value(self.show_pos + self.shift_direction)
|
|
if self.show_pos == self.next_pos:
|
|
self.timer.stop()
|
|
self.difficultySelected.emit(self.difficulty_display.text().strip(' '))
|
|
|
|
def circular_value(self, value):
|
|
if value == (len(hs.DIFFICULTIES)+1) * self.max_length:
|
|
value = self.max_length
|
|
elif value == 0:
|
|
value = len(hs.DIFFICULTIES) * self.max_length
|
|
return value
|
|
|
|
|
|
class ScoreGrid(QGridLayout):
|
|
scoreUpdate = Signal(str)
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
try:
|
|
self.highscore_list = hs.read_highscore_file(hs_file)
|
|
except Exception as e:
|
|
print('Cannot open file', e)
|
|
|
|
for i in range(5):
|
|
label = QLabel(str(i+1)+'.')
|
|
self.addWidget(label, i, 0)
|
|
|
|
self.animated_labels = []
|
|
for i, name in enumerate('ABCDE'):
|
|
label1 = AnimatedLabel(name * 7)
|
|
label1.setAlignment(Qt.AlignCenter)
|
|
label2 = AnimatedLabel('0'*5)
|
|
label2.setAlignment(Qt.AlignRight)
|
|
self.addWidget(label1, i, 1)
|
|
self.addWidget(label2, i, 2)
|
|
self.animated_labels.append(label1)
|
|
self.animated_labels.append(label2)
|
|
|
|
self.replace_scores(hs.DIFFICULTIES[0])
|
|
|
|
def show_score_info(self, toggle):
|
|
for label in self.animated_labels:
|
|
label.toggle_anim(toggle)
|
|
|
|
def replace_scores(self, difficulty):
|
|
scores = self.highscore_list[difficulty]
|
|
for i in range(len(scores)):
|
|
self.animated_labels[2*i].replace_text(scores[i]['name'])
|
|
self.animated_labels[2*i+1].replace_text(scores[i]['time'])
|
|
|
|
def set_highscore(self, difficulty, name, time):
|
|
hs.replace_placing(self.highscore_list, difficulty, name, time)
|
|
hs.write_highscore_file(hs_file, self.highscore_list)
|
|
self.replace_scores(difficulty)
|
|
self.scoreUpdate.emit(difficulty)
|
|
|
|
def get_rank(self, difficulty, time):
|
|
return hs.check_ranking(self.highscore_list, difficulty, time)
|
|
|
|
|
|
class NameInput(QWidget):
|
|
nameReceived = Signal(str)
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
self.layout = QHBoxLayout(self)
|
|
|
|
self.rank_label = QLabel('-')
|
|
self.layout.addWidget(self.rank_label)
|
|
|
|
self.name_input = QLineEdit(self)
|
|
self.name_input.setMaxLength(13)
|
|
self.layout.addWidget(self.name_input)
|
|
|
|
self.time_display = QLabel('-:-:-')
|
|
self.layout.addWidget(self.time_display)
|
|
self.name_input.returnPressed.connect(self.receive_name_input)
|
|
|
|
self.name_input.setStyleSheet("""
|
|
border-top: 1px solid white;
|
|
""")
|
|
|
|
def receive_name_input(self):
|
|
print(self.name_input.text().strip(' '))
|
|
name = self.name_input.text().strip(' ')
|
|
if name:
|
|
self.nameReceived.emit(name)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
app = 0
|
|
app = QApplication(sys.argv)
|
|
|
|
ex = HighScoreBoard(500, 500)
|
|
ex.show()
|
|
sys.exit(app.exec_())
|