From abc5ef5ddc9bd1db5fcefdbd720ba0e42b26cccb Mon Sep 17 00:00:00 2001 From: Sebastian Lohff Date: Wed, 6 Nov 2013 20:42:00 +0100 Subject: [PATCH] Scaffold --- buttonreader.py | 8 ++++++ game.py | 67 ++++++++++++++++++++++++++++++++++++++++++++ gamestate.py | 5 ++++ player.py | 48 +++++++++++++++++++++++++++++++ question.py | 8 +++++- questions/template.q | 2 +- seopardy.py | 42 +++++++++++++++++++++++++++ windows.py | 50 +++++++++++++++++++++++++++++++++ 8 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 buttonreader.py create mode 100644 game.py create mode 100644 gamestate.py create mode 100644 player.py create mode 100644 seopardy.py create mode 100644 windows.py diff --git a/buttonreader.py b/buttonreader.py new file mode 100644 index 0000000..34ad2e5 --- /dev/null +++ b/buttonreader.py @@ -0,0 +1,8 @@ +# write a thread that reads buttoninput from fifo or pyserial or something +# https://gist.github.com/elshaka/2999082 +# and make this configureable +from __future__ import print_function +from PySide import QtCore + +class SerialThread(QtCore.QThread): + dataReady = QtCore.Signal(str) diff --git a/game.py b/game.py new file mode 100644 index 0000000..c1c181c --- /dev/null +++ b/game.py @@ -0,0 +1,67 @@ +from __future__ import print_function + +from PySide import QtCore, QtGui + +from player import Player +from windows import QuestionWindow + +class SeopardyGame(QtGui.QWidget): + def __init__(self, questions, gamestate, parent=None): + super(SeopardyGame, self).__init__(parent) + + self.questions = questions + self.gamestate = gamestate + self.players = [Player.gen_player(i) for i in range(1, 4)] + + self._createGui() + + self.showFullScreen() + + def _createGui(self): + """ Create the board from questions. """ + + layout = QtGui.QVBoxLayout() + headerLayout = QtGui.QHBoxLayout() + header = QtGui.QLabel("Header") + headerLayout.addWidget(header) + headerLayout.setSizeConstraint(QtGui.QLayout.SetMinimumSize) + layout.addWidget(header, alignment=QtCore.Qt.AlignCenter) + + # create board + #board = QtGui.QGridLayout(6, len(self.questions.get_sections())) + board = QtGui.QGridLayout() + board.setSizeConstraint(QtGui.QLayout.SetMaximumSize) + for i, sec in enumerate(self.questions.get_sections()): + seclabel = QtGui.QLabel(sec, alignment=QtCore.Qt.AlignCenter) + seclabel.setStyleSheet("QLabel { font-size: 30px; }") + board.addWidget(seclabel, 0, i) + for j in range(5): + b = QtGui.QPushButton(str((j+1)*100)) + b.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + b.setAutoDefault(False) + b.setStyleSheet("QPushButton { font-size: 60px; }") + b.clicked.connect(lambda sec=sec, j=j: self.tfunc(sec, j+1)) + board.addWidget(b, j+1, i) + layout.addLayout(board) + + # create player bar + self.playerBar = QtGui.QHBoxLayout() + for i, player in enumerate(self.players): + self.playerBar.addWidget(player) + if i != len(self.players)-1: + self.playerBar.addStretch() + layout.addLayout(self.playerBar) + + self.setLayout(layout) + + def tfunc(self, section, number): + print("question window", section, number) + + qwin = QuestionWindow(section, self.questions.get_question(section, number), self) + qwin.showFullScreen() + qwin.exec_() + + results = qwin.get_results() + for result in results: + print("result", result) + diff --git a/gamestate.py b/gamestate.py new file mode 100644 index 0000000..6ebab99 --- /dev/null +++ b/gamestate.py @@ -0,0 +1,5 @@ +from __future__ import print_function + +class GameState(object): + def __init__(self, statefile=None): + pass diff --git a/player.py b/player.py new file mode 100644 index 0000000..aabab52 --- /dev/null +++ b/player.py @@ -0,0 +1,48 @@ +from __future__ import print_function + +from PySide import QtGui, QtCore + +class Player(QtGui.QWidget): + DEFAULT_PLAYERS = [ + ("Foo", QtGui.QColor(255, 0, 0)), + ("Bar", QtGui.QColor(0, 255, 0)), + ("Baz", QtGui.QColor(0, 0, 255)), + ("Blubb", QtGui.QColor(0, 255, 255)), + ("Murr", QtGui.QColor(255, 0, 255)), + ] + + def __init__(self, name, color, points=0, parent=None): + super(Player, self).__init__(parent) + self.name = name + self.color = color + self.points = points + + self.setup_gui() + + def setup_gui(self): + self.layout = QtGui.QVBoxLayout() + self.name_label = QtGui.QLabel(self.name) + self.name_label.setStyleSheet("QLabel { font-size: 40px; background-color: %s; color: white; }" % (self.color.name(),)) + self.layout.addWidget(self.name_label) + + self.points_label = QtGui.QLabel(str(self.points)) + self.points_label.setStyleSheet("QLabel { font-size: 40px;}") + self.layout.addWidget(self.points_label, alignment=QtCore.Qt.AlignRight) + + self.setLayout(self.layout) + + def change_name(self, new_name): + self.name = new_name + self.name_label.set_text(new_name) + + def add_points(self, amount): + self.points += amount + self.points_label.set_text(str(self.points)) + + @classmethod + def gen_player(clazz, num): + if num > len(clazz.DEFAULT_PLAYERS): + raise ValueError("You tried to generate too many players") + + return clazz(*clazz.DEFAULT_PLAYERS[num-1]) + diff --git a/question.py b/question.py index 479389b..913ec85 100644 --- a/question.py +++ b/question.py @@ -1,12 +1,18 @@ import os import yaml + class QuestionException(Exception): + """ Exception to be thrown when there is something wrong with + the question file. """ pass class Questions(object): + """ Object holding all the questions """ + QUESTION_TYPES = ["Text", "Image", "Music"] QUESTION_KEYS = ["Name", "Question", "Answer", "Type", "Double-Jeopardy"] + def __init__(self, qfile): self.qfile = qfile self._questions = None @@ -80,7 +86,7 @@ class Questions(object): raise QuestionException("Section %d (%s) needs to have exactly %d questions (has %d)" % (i, sec["Section"], 5, j)) # check for only having unique section names - sections = [s["Section"] for s in self._questions] + sections = [s["Section"] for s in ysrc] if len(sections) != len(set(sections)): raise QuestionException("All section names must be unique") diff --git a/questions/template.q b/questions/template.q index acca42a..04ead25 100644 --- a/questions/template.q +++ b/questions/template.q @@ -1,7 +1,7 @@ - Section: A Questions: - Name: Question 1 - Question: Foo. + Question: Foo. Bar. Lange Frage. Ich meine warum sollte das Jeopardy nicht auch mal so ne richtig lange frage haben? ;) Answer: Bar? Type: Text diff --git a/seopardy.py b/seopardy.py new file mode 100644 index 0000000..edb0474 --- /dev/null +++ b/seopardy.py @@ -0,0 +1,42 @@ +#!/usr/bin/python +from __future__ import print_function + +import argparse +import os +import sys +#from PySide import QtCore, QtGui +from PySide import QtGui + +from question import Questions +from gamestate import GameState +from game import SeopardyGame + +def _parser(): + parser = argparse.ArgumentParser(description="Sebas jeopardy/beopardy clone") + parser.add_argument("--fifo", action="store", default="/tmp/seopardy-fifo", help="Name of the fifo to create") + parser.add_argument("--gamestate", action="store", default=None, help="Gamestate to load to recover a crashed game") + parser.add_argument("questions", action="store", help="Path to questionfile") + + return parser + +if __name__ == '__main__': + parser = _parser() + args = parser.parse_args() + + fifo = None + try: + if os.path.exists(args.fifo): + os.unlink(args.fifo) + os.mkfifo(args.fifo) + except OSError as e: + print("Error: Could not create fifo: %s" % (str(e),), file=sys.stderr) + + questions = Questions(args.questions) + gamestate = GameState(args.gamestate) + + # start gui + app = QtGui.QApplication([]) + board = SeopardyGame(questions, gamestate) + board.show() + app.exec_() + sys.exit() diff --git a/windows.py b/windows.py new file mode 100644 index 0000000..deedbf5 --- /dev/null +++ b/windows.py @@ -0,0 +1,50 @@ +from PySide import QtGui, QtCore + +#class QuestionWindow(QtGui.QWidget): +class QuestionWindow(QtGui.QDialog): + def __init__(self, section, question, parent=None): + super(QuestionWindow, self).__init__(parent) + + self.section = section + self.question = question + self.results = [] + + self._setupGui() + self.setWindowTitle("Seopardy") + + def get_results(self): + return self.results + + def _mkQuestionLabel(self, text): + question = QtGui.QLabel(text, alignment=QtCore.Qt.AlignCenter) + question.setWordWrap(True) + question.setStyleSheet("QLabel { font-size: 40px; }") + + return question + + def _setupGui(self): + self.layout = QtGui.QVBoxLayout() + + seclabel = QtGui.QLabel(self.section) + seclabel.setStyleSheet("QLabel { font-size: 30px; }") + self.layout.addWidget(seclabel, alignment=QtCore.Qt.AlignCenter) + self.layout.addStretch() + + qlabel = None + if self.question["Type"] == "Text": + qlabel = self.mkQuestionLabel(self.question["Question"]) + elif self.question["Type"] == "Music": + qlabel = self.mkQuestionLabel("Listen...") + elif self.question["Type"] == "Image": + qlabel = QtGui.QLabel() + pixmap = QtGui.QPixmap() + pixmap.loadFromData(open(self.question["Question"]).read()) + qlabel.setPixmap(pixmap) + else: + raise ValueError("%s is an unknown type for section %s question name %s" % (self.question["Type"], self.section, self.question["Name"])) + + self.layout.addWidget(qlabel, alignment=QtCore.Qt.AlignCenter) + self.layout.addStretch() + + self.setLayout(self.layout) +