player.py 4.79 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
#!/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
Antoine Lima's avatar
Antoine Lima committed
11 12 13 14

from PyQt5.QtCore import Qt, QCoreApplication
from PyQt5.QtWidgets import QDialog

15 16 17
from Babyfut.babyfut import getMainWin
from Babyfut.core.database import Database, DatabaseError
from Babyfut.ui.consent_dialog_ui import Ui_Dialog as ConsentDialogUI
18 19

class Side(Enum):
20 21 22 23 24 25
	'''
	Values of the enum are used throughout the code for indexing purposes, not to be changed
	'''
	Undef = -1
	Left  = 0
	Right = 1
26

Antoine Lima's avatar
Antoine Lima committed
27 28
	@property
	def opposite(self):
29
		return Side.Right if self==Side.Left else Side.Left
30

Antoine Lima's avatar
Antoine Lima committed
31 32 33 34 35
class ConsentDialog(QDialog):
	def __init__(self, parent):
		QDialog.__init__(self, parent)
		self.ui = ConsentDialogUI()
		self.ui.setupUi(self)
36

Antoine Lima's avatar
Antoine Lima committed
37 38 39 40 41 42 43
		self.ui.txtConsent.setHtml(QCoreApplication.translate('consent', '''<p>
			You are about to connect yourself for the first time. We will need to access:
			<ul>
				<li>Your Name and Surname</li>
				<li>Your Picture (if public)</li>
				<li>...</li>
			</ul>
44
			</p>
45

Antoine Lima's avatar
Antoine Lima committed
46 47 48 49 50
			<p>
			It is possible to play withtout connecting yourslef, but this will allow you to keep track of your score and to provide a better experience for you and the ones you play with!
			<br/><br/>
			Do you agree with this?
			</p>'''))
51

Antoine Lima's avatar
Antoine Lima committed
52 53 54 55 56
	def keyPressEvent(self, e):
		if e.key()==Qt.Key_Return:
			self.accept()
		else:
			self.reject()
57

58
class Player():
Antoine Lima's avatar
Antoine Lima committed
59 60 61 62 63
	__query_infos = 'SELECT id, fname, lname, pic FROM Players WHERE rfid==?'
	__query_time_goals_games = 'SELECT SUM(Matchs.duration) AS timePlayed, SUM(Teams.nGoals) AS goalsScored, COUNT(*) AS gamesPlayed FROM Teams INNER JOIN  Matchs ON (Teams.id==Matchs.winningTeam OR Teams.id==Matchs.losingTeam) WHERE (Teams.player1==? OR player2==?)'
	__query_victories = 'SELECT COUNT(*) AS victories FROM Players INNER JOIN Teams ON (Players.id==Teams.player1 OR Players.id==Teams.player2) INNER JOIN  Matchs ON (Teams.id==Matchs.winningTeam) WHERE Players.id==?'

	_placeholder_pic_path = ':ui/img/placeholder_head.jpg'
64

65
	def __init__(self, id, rfid, fname, lname, pic_path, stats):
66
		self.id = id
67
		self.rfid = rfid
68 69
		self.fname = fname
		self.lname = lname
Antoine Lima's avatar
Antoine Lima committed
70 71
		self.pic_path = pic_path if pic_path else Player._placeholder_pic_path # Default pic if None
		self.stats = stats
72

73
	@staticmethod
Antoine Lima's avatar
Antoine Lima committed
74 75
	def fromRFID(rfid):
		db = Database.instance()
76

Antoine Lima's avatar
Antoine Lima committed
77 78 79 80
		if db.rfid_exists(rfid):
			try:
				# Retrieve generic informations
				id, fname, lname, pic = db.select_one(Player.__query_infos, rfid)
81

Antoine Lima's avatar
Antoine Lima committed
82 83 84 85
				# Retrieve stats
				stats = {}
				stats['time_played'], stats['goals_scored'], stats['games_played'] = db.select_one(Player.__query_time_goals_games, id, id)
				stats['victories'], = db.select_one(Player.__query_victories, id)
86

Antoine Lima's avatar
Antoine Lima committed
87 88 89
				for key, val in stats.items():
					if val==None:
						stats[key] = 0
90

Antoine Lima's avatar
Antoine Lima committed
91
				return Player(id, rfid, fname, lname, pic, stats)
92

Antoine Lima's avatar
Antoine Lima committed
93 94 95
			except DatabaseError as e:
				logging.warn('DB Error: {}'.format(e))
				return PlayerGuest
96

Antoine Lima's avatar
Antoine Lima committed
97 98 99 100 101
		else:
			### Retrieve player from API
			# Ask for consent
			consentDialog = ConsentDialog(getMainWin())
			consentDialog.exec()
102

Antoine Lima's avatar
Antoine Lima committed
103 104 105 106 107
			if consentDialog.result()==QDialog.Accepted:
				print('todo')
				return PlayerGuest
			else:
				return PlayerGuest
108 109 110 111 112 113 114

	def displayImg(self, container_widget):
		self.pic_container = container_widget

		if self.pic_path.startswith('http'):
			# Download from the internet
			container_widget.setStyleSheet('border-image: url({});'.format(Player._placeholder_pic_path))
Antoine Lima's avatar
Antoine Lima committed
115
			# TODO DOWNLOAD
116 117 118 119
		else:
			# Already downloaded and stored locally
			container_widget.setStyleSheet('border-image: url({});'.format(self.pic_path))

120 121 122 123
	def save(self):
		'''
		Update or create the player in database
		'''
124 125 126
		pass
		# DONT SAVE PIC PATH, IT IS CHANGED FOR THE LOCAL PATH

Antoine Lima's avatar
Antoine Lima committed
127 128 129 130 131 132 133 134
	def forgetPicture():
		self.pic_path = Player._placeholder_pic_path
		Database.instance().delete_playerpic(self.id)

	def make_private():
		self.private = True
		Database.instance().make_player_private(self.id)

135 136
	@property
	def name(self):
137
		return '{} {}'.format(self.fname, self.lname.upper())
138

139
	@property
Antoine Lima's avatar
Antoine Lima committed
140
	def stats_property(self):
141 142 143 144 145
		'''
		Compatibility property allowing to access stats as a object member and not dict
		ex: player.stats['victories'] can be accessed with player.stats_property.victories'
		This is mostly used for sorting players in leaderboard.py
		'''
Antoine Lima's avatar
Antoine Lima committed
146 147 148 149 150 151
		class Stat:
			def __init__(self, stats):
				self.victories = stats['victories']
				self.time_played = stats['time_played']
				self.goals_scored = stats['goals_scored']
				self.games_played = stats['games_played']
152

Antoine Lima's avatar
Antoine Lima committed
153
		return Stat(self.stats)
154

155
	@staticmethod
Antoine Lima's avatar
Antoine Lima committed
156
	def allStoredPlayers():
157
		return [Player.fromRFID(rfid) for rfid, in Database.instance().select_all_rfid()]
158

159
PlayerGuest = Player.fromRFID(-1)
160
PlayerEmpty = Player(-1, -42, '', '', Player._placeholder_pic_path, {'time_played':'', 'goals_scored':'', 'games_played':'', 'victories': ''})