GameState loading/saving works
This commit is contained in:
parent
13690e493e
commit
d26c7a3a88
43
game.py
43
game.py
|
@ -13,9 +13,11 @@ class SeopardyGame(QtGui.QWidget):
|
||||||
self.questions = questions
|
self.questions = questions
|
||||||
self.gamestate = gamestate
|
self.gamestate = gamestate
|
||||||
#self.players = [Player.gen_player(i, parent=self) for i in range(1, 4)]
|
#self.players = [Player.gen_player(i, parent=self) for i in range(1, 4)]
|
||||||
self.players = []
|
self.players = self.gamestate.get_players()
|
||||||
|
if len(self.players) == 0:
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
self.add_player()
|
self.add_player()
|
||||||
|
|
||||||
self.currentPlayer = None
|
self.currentPlayer = None
|
||||||
|
|
||||||
self._inOtherWindow = False
|
self._inOtherWindow = False
|
||||||
|
@ -23,6 +25,7 @@ class SeopardyGame(QtGui.QWidget):
|
||||||
self.showFullScreen()
|
self.showFullScreen()
|
||||||
|
|
||||||
# initiate starting the game!
|
# initiate starting the game!
|
||||||
|
if self.gamestate.get_state() == "start":
|
||||||
QtCore.QCoreApplication.postEvent(self, GameStartEvent())
|
QtCore.QCoreApplication.postEvent(self, GameStartEvent())
|
||||||
|
|
||||||
def add_player(self):
|
def add_player(self):
|
||||||
|
@ -40,22 +43,22 @@ class SeopardyGame(QtGui.QWidget):
|
||||||
|
|
||||||
# create board
|
# create board
|
||||||
#board = QtGui.QGridLayout(6, len(self.questions.get_sections()))
|
#board = QtGui.QGridLayout(6, len(self.questions.get_sections()))
|
||||||
board = QtGui.QGridLayout()
|
self.board = QtGui.QGridLayout()
|
||||||
board.setSizeConstraint(QtGui.QLayout.SetMaximumSize)
|
self.board.setSizeConstraint(QtGui.QLayout.SetMaximumSize)
|
||||||
for i, sec in enumerate(self.questions.get_sections()):
|
for i, sec in enumerate(self.questions.get_sections()):
|
||||||
seclabel = QtGui.QLabel(sec, alignment=QtCore.Qt.AlignCenter)
|
seclabel = QtGui.QLabel(sec, alignment=QtCore.Qt.AlignCenter)
|
||||||
seclabel.setStyleSheet("QLabel { font-size: 30px; }")
|
seclabel.setStyleSheet("QLabel { font-size: 30px; }")
|
||||||
board.addWidget(seclabel, 0, i)
|
self.board.addWidget(seclabel, 0, i)
|
||||||
for j in range(5):
|
for j in range(5):
|
||||||
b = QtGui.QPushButton(str((j+1)*100))
|
b = QtGui.QPushButton(str((j+1)*100))
|
||||||
b.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
b.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
||||||
b.setAutoDefault(False)
|
b.setAutoDefault(False)
|
||||||
b.setStyleSheet("QPushButton { font-size: 60px; }")
|
#b.setStyleSheet("QPushButton { font-size: 60px; }")
|
||||||
b.installEventFilter(FocusKeyGrabber(i+1, j+1, self))
|
b.installEventFilter(FocusKeyGrabber(i+1, j+1, self))
|
||||||
b.clicked.connect(lambda sec=sec, j=j: self.go_to_question(sec, j+1))
|
b.clicked.connect(lambda sec=sec, j=j: self.go_to_question(sec, j+1))
|
||||||
board.addWidget(b, j+1, i)
|
self.board.addWidget(b, j+1, i)
|
||||||
layout.addLayout(board)
|
self._restyle_button(sec, j+1, self.gamestate.get_answers(sec, j+1))
|
||||||
self.board = board
|
layout.addLayout(self.board)
|
||||||
|
|
||||||
# create player bar
|
# create player bar
|
||||||
self.playerBar = QtGui.QHBoxLayout()
|
self.playerBar = QtGui.QHBoxLayout()
|
||||||
|
@ -81,6 +84,8 @@ class SeopardyGame(QtGui.QWidget):
|
||||||
x = PlayerStartWindow(self.players, self)
|
x = PlayerStartWindow(self.players, self)
|
||||||
x.exec_()
|
x.exec_()
|
||||||
self._inOtherWindow = False
|
self._inOtherWindow = False
|
||||||
|
self.gamestate.set_state("playing")
|
||||||
|
self.gamestate.save()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
@ -136,6 +141,7 @@ class SeopardyGame(QtGui.QWidget):
|
||||||
self._set_player_points(newAnswers)
|
self._set_player_points(newAnswers)
|
||||||
self.gamestate.set_answers(section, number, newAnswers)
|
self.gamestate.set_answers(section, number, newAnswers)
|
||||||
self._restyle_button(section, number, newAnswers)
|
self._restyle_button(section, number, newAnswers)
|
||||||
|
self.gamestate.save()
|
||||||
|
|
||||||
def show_victory_window(self):
|
def show_victory_window(self):
|
||||||
self._inOtherWindow = True
|
self._inOtherWindow = True
|
||||||
|
@ -176,6 +182,23 @@ class SeopardyGame(QtGui.QWidget):
|
||||||
# restyle the button
|
# restyle the button
|
||||||
self._restyle_button(section, number, answers)
|
self._restyle_button(section, number, answers)
|
||||||
|
|
||||||
|
# safe current gamestate
|
||||||
|
self.gamestate.save()
|
||||||
|
|
||||||
|
# check if we are done
|
||||||
|
foundUnanswered = False
|
||||||
|
for sec in self.questions.get_sections():
|
||||||
|
for j in range(5):
|
||||||
|
boardAnswers = self.gamestate.get_answers(sec, j+1)
|
||||||
|
if boardAnswers is None or not answers.is_answered():
|
||||||
|
foundUnanswered = True
|
||||||
|
if foundUnanswered:
|
||||||
|
break
|
||||||
|
|
||||||
|
if not foundUnanswered:
|
||||||
|
self.show_victory_window()
|
||||||
|
|
||||||
|
|
||||||
def _set_player_points(self, answers, rollback=False):
|
def _set_player_points(self, answers, rollback=False):
|
||||||
for i, (player, correct) in enumerate(answers.get_tries()):
|
for i, (player, correct) in enumerate(answers.get_tries()):
|
||||||
prefix = 1
|
prefix = 1
|
||||||
|
@ -199,8 +222,8 @@ class SeopardyGame(QtGui.QWidget):
|
||||||
btnstr = ""
|
btnstr = ""
|
||||||
btncolor = None
|
btncolor = None
|
||||||
|
|
||||||
if not answers.is_answered():
|
if answers is None or not answers.is_answered():
|
||||||
btn.setText(str(answers.points()))
|
btn.setText(str(qno*100))
|
||||||
btn.setStyleSheet("QPushButton { font-size: 60px; }")
|
btn.setStyleSheet("QPushButton { font-size: 60px; }")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
51
gamestate.py
51
gamestate.py
|
@ -1,6 +1,8 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import datetime
|
||||||
import os
|
import os
|
||||||
|
import yaml
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
class GameState(object):
|
class GameState(object):
|
||||||
|
@ -10,17 +12,30 @@ class GameState(object):
|
||||||
savedir: dir to save gamestate into, should be overwritable
|
savedir: dir to save gamestate into, should be overwritable
|
||||||
board: dict of section with list of questions
|
board: dict of section with list of questions
|
||||||
"""
|
"""
|
||||||
|
GAMESTATE = ["start", "playing", "end"]
|
||||||
|
|
||||||
def __init__(self, savedir):
|
def __init__(self, savedir):
|
||||||
self.savedir = savedir
|
self.savedir = savedir
|
||||||
|
|
||||||
self._board = defaultdict(lambda: [None]*5)
|
#self._board = defaultdict(lambda: [None]*5)
|
||||||
self._players = None
|
self._board = defaultdict(_mk_empty_board_column)
|
||||||
|
self._players = []
|
||||||
|
self._state = self.GAMESTATE[0]
|
||||||
|
|
||||||
if not os.path.exists(self.savedir):
|
if not os.path.exists(self.savedir):
|
||||||
os.mkdir(self.savedir)
|
os.mkdir(self.savedir)
|
||||||
elif not os.path.isdir(self.savedir):
|
elif not os.path.isdir(self.savedir):
|
||||||
raise ValueError("'%s' is not a directory but something else!" % self.savedir)
|
raise ValueError("'%s' is not a directory but something else!" % self.savedir)
|
||||||
|
|
||||||
|
|
||||||
|
def set_state(self, state):
|
||||||
|
if state not in self.GAMESTATE:
|
||||||
|
raise ValueError("'%s' is not a valid gamestate, valid choices are %s" % (state, self.GAMESTATE))
|
||||||
|
self._state = state
|
||||||
|
|
||||||
|
def get_state(self):
|
||||||
|
return self._state
|
||||||
|
|
||||||
def set_answers(self, section, qnumber, answers):
|
def set_answers(self, section, qnumber, answers):
|
||||||
self._board[section][qnumber-1] = answers
|
self._board[section][qnumber-1] = answers
|
||||||
|
|
||||||
|
@ -28,14 +43,38 @@ class GameState(object):
|
||||||
return self._board[section][qnumber-1]
|
return self._board[section][qnumber-1]
|
||||||
|
|
||||||
def set_players(self, players):
|
def set_players(self, players):
|
||||||
self.players = players
|
self._players = players
|
||||||
|
|
||||||
|
def get_players(self):
|
||||||
|
return self._players
|
||||||
|
|
||||||
|
def _make_structure(self):
|
||||||
|
return {
|
||||||
|
"state": self._state,
|
||||||
|
"players": self._players,
|
||||||
|
"board": self._board
|
||||||
|
}
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
pass
|
fname = datetime.datetime.now().strftime("seopardy.%Y-%m-%d-_%H:%M:%S.save")
|
||||||
|
fstream = open("%s/%s" % (self.savedir, fname), "w")
|
||||||
|
yaml.dump(self._make_structure(), fstream)
|
||||||
|
fstream.close()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(clazz, fpath):
|
def load(clazz, sstream, savedir):
|
||||||
pass
|
gs = clazz(savedir)
|
||||||
|
data = yaml.load(sstream)
|
||||||
|
gs._state = data["state"]
|
||||||
|
gs._players = data["players"]
|
||||||
|
gs._board = data["board"]
|
||||||
|
|
||||||
|
return gs
|
||||||
|
|
||||||
|
def _mk_empty_board_column():
|
||||||
|
""" We can't use a lambda here, as we want the default dict to be
|
||||||
|
easily serializeable by yaml. """
|
||||||
|
return [None]*5
|
||||||
|
|
||||||
class QuestionAnswers(object):
|
class QuestionAnswers(object):
|
||||||
def __init__(self, section, qnumber, dj_points=None):
|
def __init__(self, section, qnumber, dj_points=None):
|
||||||
|
|
21
player.py
21
player.py
|
@ -1,5 +1,6 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import yaml
|
||||||
from PySide import QtGui, QtCore
|
from PySide import QtGui, QtCore
|
||||||
|
|
||||||
class Player(QtGui.QWidget):
|
class Player(QtGui.QWidget):
|
||||||
|
@ -9,6 +10,7 @@ class Player(QtGui.QWidget):
|
||||||
("Baz", QtGui.QColor(0, 0, 255)),
|
("Baz", QtGui.QColor(0, 0, 255)),
|
||||||
("Blubb", QtGui.QColor(0, 255, 255)),
|
("Blubb", QtGui.QColor(0, 255, 255)),
|
||||||
("Murr", QtGui.QColor(255, 0, 255)),
|
("Murr", QtGui.QColor(255, 0, 255)),
|
||||||
|
("Maunz", QtGui.QColor(255, 255, 0)),
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, name, color, points=0, parent=None):
|
def __init__(self, name, color, points=0, parent=None):
|
||||||
|
@ -46,6 +48,21 @@ class Player(QtGui.QWidget):
|
||||||
|
|
||||||
return clazz(*clazz.DEFAULT_PLAYERS[num-1], parent=parent)
|
return clazz(*clazz.DEFAULT_PLAYERS[num-1], parent=parent)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _yaml_representer(clazz, dumper, data):
|
||||||
|
#def __init__(self, name, color, points=0, parent=None):
|
||||||
|
return dumper.represent_mapping(u'!player', {
|
||||||
|
'name': data.name,
|
||||||
|
'points': data.points,
|
||||||
|
'color': data.color.name()
|
||||||
|
})
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _yaml_constructor(clazz, loader, node):
|
||||||
|
pdict = loader.construct_mapping(node)
|
||||||
|
pdict["color"] = QtGui.QColor(pdict["color"])
|
||||||
|
return Player(**pdict)
|
||||||
|
|
||||||
|
|
||||||
class ButtonEvent(QtCore.QEvent):
|
class ButtonEvent(QtCore.QEvent):
|
||||||
eventType = QtCore.QEvent.Type(QtCore.QEvent.registerEventType())
|
eventType = QtCore.QEvent.Type(QtCore.QEvent.registerEventType())
|
||||||
|
@ -60,3 +77,7 @@ class ButtonEvent(QtCore.QEvent):
|
||||||
return self.playerno
|
return self.playerno
|
||||||
|
|
||||||
nobodyColor = QtGui.QColor(128, 128, 128)
|
nobodyColor = QtGui.QColor(128, 128, 128)
|
||||||
|
|
||||||
|
# yaml dumpers/loaders
|
||||||
|
yaml.add_representer(Player, Player._yaml_representer)
|
||||||
|
yaml.add_constructor(u'!player', Player._yaml_constructor)
|
||||||
|
|
17
seopardy.py
17
seopardy.py
|
@ -31,12 +31,27 @@ if __name__ == '__main__':
|
||||||
os.mkfifo(args.fifo)
|
os.mkfifo(args.fifo)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
print("Error: Could not create fifo: %s" % (str(e),), file=sys.stderr)
|
print("Error: Could not create fifo: %s" % (str(e),), file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
questions = Questions(args.questions)
|
questions = Questions(args.questions)
|
||||||
gamestate = GameState(args.savedir)
|
|
||||||
|
|
||||||
# start gui
|
# start gui
|
||||||
app = QtGui.QApplication([])
|
app = QtGui.QApplication([])
|
||||||
|
|
||||||
|
# create or load gamestate
|
||||||
|
gamestate = None
|
||||||
|
if args.gamestate:
|
||||||
|
sstream = None
|
||||||
|
try:
|
||||||
|
sstream = open(args.gamestate, "r")
|
||||||
|
except IOError as e:
|
||||||
|
print("Error: Could not load gamestate: %s" % (str(e),), file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
gamestate = GameState.load(sstream, args.savedir)
|
||||||
|
else:
|
||||||
|
gamestate = GameState(args.savedir)
|
||||||
|
|
||||||
|
# create board
|
||||||
board = SeopardyGame(questions, gamestate)
|
board = SeopardyGame(questions, gamestate)
|
||||||
board.show()
|
board.show()
|
||||||
app.exec_()
|
app.exec_()
|
||||||
|
|
Loading…
Reference in New Issue