Commit f39dcfb9 authored by Antoine Lima's avatar Antoine Lima
Browse files

Player class, leaderboards (+ sorting)

parent f43cc32f
#! /bin/sh #! /bin/sh
# Modules
pyuic5 --import-from=ui ui/main.ui -o ui/main_ui.py pyuic5 --import-from=ui ui/main.ui -o ui/main_ui.py
pyuic5 --import-from=ui ui/menu.ui -o ui/menu_ui.py pyuic5 --import-from=ui ui/menu.ui -o ui/menu_ui.py
pyuic5 --import-from=ui ui/game.ui -o ui/game_ui.py pyuic5 --import-from=ui ui/game.ui -o ui/game_ui.py
...@@ -8,4 +9,7 @@ pyuic5 --import-from=ui ui/options.ui -o ui/options_ui.py ...@@ -8,4 +9,7 @@ pyuic5 --import-from=ui ui/options.ui -o ui/options_ui.py
pyuic5 --import-from=ui ui/auth2p.ui -o ui/auth2p_ui.py pyuic5 --import-from=ui ui/auth2p.ui -o ui/auth2p_ui.py
pyuic5 --import-from=ui ui/leaderboard.ui -o ui/leaderboard_ui.py pyuic5 --import-from=ui ui/leaderboard.ui -o ui/leaderboard_ui.py
# Custom widgets
pyuic5 --import-from=ui ui/playerlist.ui -o ui/playerlist_ui.py
pyrcc5 -root /ui ui/assets.qrc -o ui/assets_rc.py pyrcc5 -root /ui ui/assets.qrc -o ui/assets_rc.py
...@@ -11,6 +11,7 @@ import logging ...@@ -11,6 +11,7 @@ import logging
from PyQt5.QtCore import QTime, Qt from PyQt5.QtCore import QTime, Qt
from module import Module from module import Module
from player import Side
import modules import modules
from ui.auth2p_ui import Ui_Form as Auth2pWidget from ui.auth2p_ui import Ui_Form as Auth2pWidget
...@@ -20,21 +21,29 @@ class AuthModule(Module): ...@@ -20,21 +21,29 @@ class AuthModule(Module):
def load(self): def load(self):
logging.debug('Loading AuthModule') logging.debug('Loading AuthModule')
self.players = {Side.Left: list(), Side.Right: list()}
def unload(self): def unload(self):
logging.debug('Unloading AuthModule') logging.debug('Unloading AuthModule')
del self.players
def other(self, **kwargs): def other(self, **kwargs):
logging.debug('Other AuthModule') logging.debug('Other AuthModule')
for key, val in kwargs.items():
if key=='ardl_rfid' or key=='ardr_rfid':
side = Side.Left if key.startswith('ardl') else Side.Right
self.players.append(Player(val))
def keyPressEvent(self, e): def keyPressEvent(self, e):
if e.key() == Qt.Key_Escape: if e.key() == Qt.Key_Escape:
self.ui_handleClick_btnCancel() self.handleCancel()
elif e.key() == Qt.Key_Enter or e.key() == Qt.Key_Return: elif e.key() == Qt.Key_Return:
self.ui_handleClick_btnDone() self.handleDone()
def ui_handleClick_btnCancel(self): def handleCancel(self):
self.switchModule(modules.MenuModule) self.switchModule(modules.MenuModule)
def ui_handleClick_btnDone(self): def handleDone(self):
self.send(modules.GameModule, players=self.players)
self.switchModule(modules.GameModule) self.switchModule(modules.GameModule)
...@@ -12,6 +12,7 @@ from PyQt5 import QtWidgets ...@@ -12,6 +12,7 @@ from PyQt5 import QtWidgets
from PyQt5.QtGui import QRegion from PyQt5.QtGui import QRegion
from PyQt5.QtCore import QTime, QTimer, QRect, Qt from PyQt5.QtCore import QTime, QTimer, QRect, Qt
from player import Side
from module import Module from module import Module
import modules import modules
from ui.endgame_ui import Ui_Form as GameWidget from ui.endgame_ui import Ui_Form as GameWidget
...@@ -20,31 +21,50 @@ class EndGameModule(Module): ...@@ -20,31 +21,50 @@ class EndGameModule(Module):
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent, GameWidget()) super().__init__(parent, GameWidget())
self.screenTimeout = QTimer() self.screenTimeout = QTimer()
self.screenTimeout.timeout.connect(self.ui_handleClick_btnQuit) self.screenTimeout.timeout.connect(self.handleQuit)
self.screenTimeout.setSingleShot(True) self.screenTimeout.setSingleShot(True)
def load(self): def load(self):
logging.debug('Loading EndGameModule') logging.debug('Loading EndGameModule')
self.ui.lblP2_2.setText('Player {}'.format(self.winner+1)) if len(self.players[self.winSide])>1:
self.ui.lblP2_2.setText('{} Side'.format(self.winSide.name))
for side in [Side.Left, Side.Right]:
for player in self.players[side]:
player.victories += 1 if side==self.winSide else 0
player.goals_scored += self.scores[side]
player.time_played += self.time
player.games_played += 1
player.save()
# Quit the screen after 5 seconds if the user doesn't do it before # Quit the screen after 5 seconds if the user doesn't do it before
self.screenTimeout.start(5000) #self.screenTimeout.start(5000)
def unload(self): def unload(self):
logging.debug('Unloading EndGameModule') logging.debug('Unloading EndGameModule')
self.screenTimeout.stop() self.screenTimeout.stop()
self.winner = -1 del self.players
del self.winSide
def other(self, **kwargs): def other(self, **kwargs):
logging.debug('Other EndGameModule') logging.debug('Other EndGameModule')
if 'winner' in kwargs: for key, val in kwargs.items():
self.winner = kwargs['winner'] if key=='players':
self.players = val
elif key=='winSide':
self.winSide = val
elif key=='scores':
self.scores = val
elif key=='time':
self.time = val
#else:
# raise ValueError('Unknown message identifier {}'.format(kwargs)
def keyPressEvent(self, e): def keyPressEvent(self, e):
if e.key() == Qt.Key_Escape or e.key() == Qt.Key_Return: if e.key() == Qt.Key_Escape or e.key() == Qt.Key_Return:
self.ui_handleClick_btnQuit() self.handleQuit()
def ui_handleClick_btnQuit(self): def handleQuit(self):
self.switchModule(modules.MenuModule) self.switchModule(modules.MenuModule)
...@@ -15,6 +15,7 @@ from PyQt5.QtCore import QTime, QTimer, QRect, Qt, QUrl ...@@ -15,6 +15,7 @@ from PyQt5.QtCore import QTime, QTimer, QRect, Qt, QUrl
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget from PyQt5.QtMultimediaWidgets import QVideoWidget
from player import Side
from replay import Replay from replay import Replay
from module import Module from module import Module
import modules import modules
...@@ -28,20 +29,20 @@ class GameOverChecker(): ...@@ -28,20 +29,20 @@ class GameOverChecker():
def check(self, time, scores): def check(self, time, scores):
''' '''
Checks if a game is over and return the winner if that's the case Checks if a game is over and return the winner if that's the case
Either returns -1 if the game is not finished or the highest score's index (0 or 1) Returns the winning side or Side.Undef otherwise
Takes the game time is seconds and a list containing the two scores Takes the game time is seconds and a list containing the two scores
''' '''
# Gets the index of the highest scoring player (either 0 or 1) # Gets the index of the highest scoring player
bestPlayer = scores.index(max(scores)) bestPlayer = max(scores, key=scores.get)
if self.conditionType=='score' and scores[bestPlayer]>=self.limit: if self.conditionType=='score' and scores[bestPlayer]>=self.limit:
return bestPlayer return bestPlayer
elif self.conditionType=='time' and time>self.limit: elif self.conditionType=='time' and time>self.limit:
return bestPlayer return bestPlayer
else: else:
return -1 return Side.Undef
class GameModule(Module): class GameModule(Module):
def __init__(self, parent=None): def __init__(self, parent=None):
...@@ -52,8 +53,8 @@ class GameModule(Module): ...@@ -52,8 +53,8 @@ class GameModule(Module):
self.timerUpdateChrono.timeout.connect(self.updateChrono) self.timerUpdateChrono.timeout.connect(self.updateChrono)
# Button connections # Button connections
self.ui.btnScore1.clicked.connect(lambda: self.goal(0)) self.ui.btnScore1.clicked.connect(lambda: self.goal(Side.Left))
self.ui.btnScore2.clicked.connect(lambda: self.goal(1)) self.ui.btnScore2.clicked.connect(lambda: self.goal(Side.Right))
self.replayer = Replay() self.replayer = Replay()
...@@ -64,9 +65,10 @@ class GameModule(Module): ...@@ -64,9 +65,10 @@ class GameModule(Module):
self.timerUpdateChrono.start(1000) self.timerUpdateChrono.start(1000)
self.ui.lcdChrono.display(QTime(0,0).toString("hh:mm:ss")) self.ui.lcdChrono.display(QTime(0,0).toString("hh:mm:ss"))
self.showingReplay = False
self.gameoverChecker = GameOverChecker('score', 10) self.gameoverChecker = GameOverChecker('score', 10)
self.scores = [0, 0] self.scores = {Side.Left: 0, Side.Right: 0}
self.updateScores() self.updateScores()
def unload(self): def unload(self):
...@@ -76,6 +78,9 @@ class GameModule(Module): ...@@ -76,6 +78,9 @@ class GameModule(Module):
def other(self, **kwargs): def other(self, **kwargs):
logging.debug('Other GameModule') logging.debug('Other GameModule')
if 'players' in kwargs:
self.players = kwargs['players']
def resizeEvent(self, event): def resizeEvent(self, event):
# 40% of the window width to have (5% margin)-(40% circle)-(10% middle)-(40% circle)-(5% margin) # 40% of the window width to have (5% margin)-(40% circle)-(10% middle)-(40% circle)-(5% margin)
...@@ -90,11 +95,11 @@ class GameModule(Module): ...@@ -90,11 +95,11 @@ class GameModule(Module):
def keyPressEvent(self, e): def keyPressEvent(self, e):
if e.key() == Qt.Key_Escape: if e.key() == Qt.Key_Escape:
self.ui_handleClick_btnCancel() self.handleCancel()
elif e.key() == Qt.Key_Left: elif e.key() == Qt.Key_Left:
self.goal(0) self.goal(Side.Left)
elif e.key() == Qt.Key_Right: elif e.key() == Qt.Key_Right:
self.goal(1) self.goal(Side.Right)
def updateChrono(self): def updateChrono(self):
# Updated each second # Updated each second
...@@ -108,30 +113,32 @@ class GameModule(Module): ...@@ -108,30 +113,32 @@ class GameModule(Module):
return self.gameStartTime.secsTo(QTime.currentTime()) return self.gameStartTime.secsTo(QTime.currentTime())
def updateScores(self): def updateScores(self):
self.ui.btnScore1.setText(str(self.scores[0])) self.ui.btnScore1.setText(str(self.scores[Side.Left]))
self.ui.btnScore2.setText(str(self.scores[1])) self.ui.btnScore2.setText(str(self.scores[Side.Right]))
self.checkEndGame() self.checkEndGame()
def goal(self, side): def goal(self, side):
if side!=0 and side!=1: if side not in Side:
logging.error('Wrong goal side: {}'.format(side)) logging.error('Wrong goal side: {}'.format(side))
else: else:
self.scores[side] += 1 self.scores[side] += 1
# Show replay # Show replay
# May require `sudo apt-get install qtmultimedia5-examples` in order to install the right libraries # May require `sudo apt-get install qtmultimedia5-examples` in order to install the right libraries
replayFile = self.mainwin.getContent("replay{}.mp4".format(side)) replayFile = self.mainwin.getContent('Replay {}.mp4'.format(side.name))
if os.path.exists(replayFile): if os.path.exists(replayFile):
self.showingReplay = True if True: # Debug Mode
self.updateScores()
self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface) else:
self.player.stateChanged.connect(self.endOfReplay) self.showingReplay = True
self.player.setMuted(True) self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
self.player.setVideoOutput(self.ui.videoWidget) self.player.stateChanged.connect(self.endOfReplay)
self.player.setMedia(QMediaContent(QUrl.fromLocalFile(replayFile))) self.player.setMuted(True)
self.player.play() self.player.setVideoOutput(self.ui.videoWidget)
self.ui.videoWidget.setFullScreen(True) self.player.setMedia(QMediaContent(QUrl.fromLocalFile(replayFile)))
self.player.play()
self.ui.videoWidget.setFullScreen(True)
def endOfReplay(self, status): def endOfReplay(self, status):
if status!=QMediaPlayer.PlayingState: if status!=QMediaPlayer.PlayingState:
...@@ -140,12 +147,12 @@ class GameModule(Module): ...@@ -140,12 +147,12 @@ class GameModule(Module):
self.updateScores() self.updateScores()
def ui_handleClick_btnCancel(self): def handleCancel(self):
self.switchModule(modules.MenuModule) self.switchModule(modules.MenuModule)
def checkEndGame(self): def checkEndGame(self):
win = self.gameoverChecker.check(self.getGameTime(), self.scores) winSide = self.gameoverChecker.check(self.getGameTime(), self.scores)
if win>=0: if winSide!=Side.Undef:
self.send(modules.EndGameModule, winner=win) self.send(modules.EndGameModule, players=self.players, winSide=winSide, scores=self.scores, time=self.getGameTime())
self.switchModule(modules.EndGameModule) self.switchModule(modules.EndGameModule)
...@@ -7,29 +7,117 @@ Created on Wed Apr 18 18:34:40 2018 ...@@ -7,29 +7,117 @@ Created on Wed Apr 18 18:34:40 2018
""" """
import logging import logging
from operator import attrgetter
from PyQt5.QtCore import QTime, Qt from PyQt5 import QtWidgets
from PyQt5.QtCore import QTime, Qt, QSize, QItemSelectionModel
from module import Module from module import Module
import modules import modules
from player import PlayerGuest, Player
from ui.leaderboard_ui import Ui_Form as LeaderboardWidget from ui.leaderboard_ui import Ui_Form as LeaderboardWidget
from ui.playerlist_ui import Ui_Form as PlayerListWidget
class LeaderboardItemWidget(QtWidgets.QWidget):
def __init__(self, parent, player):
QtWidgets.QWidget.__init__(self, parent)
self.ui = PlayerListWidget()
self.ui.setupUi(self)
self.ui.picHolder.setStyleSheet('border-image: url({});'.format(player.pic_path))
self.ui.lblFName.setText(player.fname)
self.ui.lblLName.setText(player.lname)
self.ui.lblVictories.setText (self.ui.lblVictories.text().replace('####', str(player.stats.victories)))
self.ui.lblGamesPlayed.setText (self.ui.lblGamesPlayed.text().replace('####', str(player.stats.games_played)))
self.ui.lblGoalsScored.setText (self.ui.lblGoalsScored.text().replace('####', str(player.stats.goals_scored)))
self.ui.lblMinutesPlayed.setText(self.ui.lblMinutesPlayed.text().replace('####', str(player.stats.time_played)))
self.ui.pushButton.clicked.connect(lambda: logging.debug('clicked'))
class LeaderboardModule(Module): class LeaderboardModule(Module):
def __init__(self, parent): def __init__(self, parent):
super().__init__(parent, LeaderboardWidget()) super().__init__(parent, LeaderboardWidget())
self.players = []
self.ui.rbName.clicked.connect(lambda: self.changeSort(self.ui.rbName))
self.ui.rbVictories.clicked.connect(lambda: self.changeSort(self.ui.rbVictories))
self.ui.rbScore.clicked.connect(lambda: self.changeSort(self.ui.rbScore))
self.ui.rbGamesPlayed.clicked.connect(lambda: self.changeSort(self.ui.rbGamesPlayed))
self.ui.rbTimePlayed.clicked.connect(lambda: self.changeSort(self.ui.rbTimePlayed))
self.selectedSort = 0
self.sortMethodRB = [self.ui.rbName, self.ui.rbVictories, self.ui.rbScore, self.ui.rbGamesPlayed, self.ui.rbTimePlayed]
self.sortMethodAttr = ['lname', 'stats.victories', 'stats.goals_scored', 'stats.games_played', 'stats.time_played']
self.sortMethodRB[self.selectedSort].setChecked(True)
def load(self): def load(self):
logging.debug('Loading LeaderboardModule') logging.debug('Loading LeaderboardModule')
self.loadList()
def unload(self): def unload(self):
logging.debug('Unloading LeaderboardModule') logging.debug('Unloading LeaderboardModule')
self.players = []
def other(self, **kwargs): def other(self, **kwargs):
logging.debug('Other LeaderboardModule') logging.debug('Other LeaderboardModule')
def changeSort(self, rbSort):
self.selectedSort = self.sortMethodRB.index(rbSort)
self.loadList()
def loadList(self):
if self.players:
self.ui.listWidget.clear()
else:
# Load from DB
dummy1 = Player(0, 'A', 'E', ':ui/img/placeholder_head.jpg')
dummy2 = Player(1, 'B', 'D', ':ui/img/placeholder_head.jpg')
dummy3 = Player(2, 'C', 'C', ':ui/img/placeholder_head.jpg')
dummy4 = Player(3, 'D', 'B', ':ui/img/placeholder_head.jpg')
dummy5 = Player(4, 'E', 'A', ':ui/img/placeholder_head.jpg')
dummy2.stats.victories = 1
dummy3.stats.time_played = 1
dummy4.stats.games_played = 1
dummy5.stats.goals_scored = 1
self.players = [PlayerGuest, dummy1, dummy2, dummy3, dummy4, dummy5]
self.players.sort(key=attrgetter(self.sortMethodAttr[self.selectedSort]), reverse=True)
for player in self.players:
item = QtWidgets.QListWidgetItem()
playerWidget = LeaderboardItemWidget(self.ui.listWidget, player)
item.setSizeHint(playerWidget.size())
self.ui.listWidget.addItem(item)
self.ui.listWidget.setItemWidget(item, playerWidget)
self.ui.listWidget.setCurrentRow(0, QItemSelectionModel.Select)
def keyPressEvent(self, e): def keyPressEvent(self, e):
curRow = self.ui.listWidget.currentRow()
curSort = self.selectedSort
if e.key() == Qt.Key_Escape: if e.key() == Qt.Key_Escape:
self.ui_handleClick_btnExit() self.handleExit()
elif e.key() == Qt.Key_Up:
newRow = curRow-1 if curRow!=0 else self.ui.listWidget.count()-1
self.ui.listWidget.setCurrentRow(newRow, QItemSelectionModel.SelectCurrent)
elif e.key() == Qt.Key_Down:
newRow = curRow+1 if curRow!=self.ui.listWidget.count()-1 else 0
self.ui.listWidget.setCurrentRow(newRow, QItemSelectionModel.SelectCurrent)
elif e.key() == Qt.Key_Left:
newSort = curSort-1 if curSort!=0 else len(self.sortMethodRB)-1
self.sortMethodRB[newSort].animateClick()
elif e.key() == Qt.Key_Right:
newSort = curSort+1 if curSort!=len(self.sortMethodRB)-1 else 0
self.sortMethodRB[newSort].animateClick()
def ui_handleClick_btnExit(self): def handleExit(self):
self.switchModule(modules.MenuModule) self.switchModule(modules.MenuModule)
...@@ -39,7 +39,7 @@ class MenuModule(Module): ...@@ -39,7 +39,7 @@ class MenuModule(Module):
def keyPressEvent(self, e): def keyPressEvent(self, e):
if e.key() == Qt.Key_Escape: if e.key() == Qt.Key_Escape:
self.ui_handleClick_btnExit() self.handleExit()
elif e.key() == Qt.Key_Up: elif e.key() == Qt.Key_Up:
self.parent().focusPreviousChild() self.parent().focusPreviousChild()
elif e.key() == Qt.Key_Down: elif e.key() == Qt.Key_Down:
...@@ -50,6 +50,6 @@ class MenuModule(Module): ...@@ -50,6 +50,6 @@ class MenuModule(Module):
else: else:
QApplication.focusWidget().animateClick() QApplication.focusWidget().animateClick()
def ui_handleClick_btnExit(self): def handleExit(self):
logging.info('Closing..') logging.info('Closing..')
self.mainwin.close() self.mainwin.close()
...@@ -21,8 +21,8 @@ class OptionsModule(Module): ...@@ -21,8 +21,8 @@ class OptionsModule(Module):
super().__init__(parent, OptionsWidget()) super().__init__(parent, OptionsWidget())
# Button connections # Button connections
self.ui.btnSave.clicked.connect(self.ui_handleClick_btnSave) self.ui.btnSave.clicked.connect(self.handleSave)
self.ui.btnBack.clicked.connect(self.ui_handleClick_btnBack) self.ui.btnBack.clicked.connect(self.handleBack)
def load(self): def load(self):
logging.debug('Loading OptionsModule') logging.debug('Loading OptionsModule')
...@@ -43,15 +43,15 @@ class OptionsModule(Module): ...@@ -43,15 +43,15 @@ class OptionsModule(Module):
def keyPressEvent(self, e): def keyPressEvent(self, e):
if e.key() == Qt.Key_Escape: if e.key() == Qt.Key_Escape:
self.ui_handleClick_btnBack() self.handleBack()
elif e.key() == Qt.Key_Return: elif e.key() == Qt.Key_Return:
self.ui_handleClick_btnSave() self.handleSave()
def ui_handleClick_btnSave(self): def handleSave(self):
Settings['ui.fullscreen'] = self.ui.options.cellWidget(0, 1).currentText().lower() == 'true' Settings['ui.fullscreen'] = self.ui.options.cellWidget(0, 1).currentText().lower() == 'true'
self.mainwin._refreshAfterSettings() self.mainwin._refreshAfterSettings()
self.switchModule(modules.MenuModule) self.switchModule(modules.MenuModule)
def ui_handleClick_btnBack(self): def handleBack(self):
# ToDo: Maybe add a warning # ToDo: Maybe add a warning
self.switchModule(modules.MenuModule) self.switchModule(modules.MenuModule)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Apr 18 18:34:40 2018
@author: Antoine Lima, Leo Reynaert, Domitille Jehenne
"""
import logging
from enum import Enum
class Side(Enum):
Undef = 0
Left = 1
Right = 2
class Player():