From: Ralf Jung Date: Thu, 17 Jul 2014 12:19:54 +0000 (+0200) Subject: add proper states and a sane API for players X-Git-Url: https://git.ralfj.de/multypo.git/commitdiff_plain/318e322c3cd72e6a7f692c6f7c7770c0e15720c8?ds=inline add proper states and a sane API for players --- diff --git a/play.sh b/play.sh index d9367ef..128a25d 100755 --- a/play.sh +++ b/play.sh @@ -2,6 +2,8 @@ # you should probably download a txt dictionary of your favourite language and use that as a words.txt +cd "$(readlink -e $(dirname "$0"))" + WORDSTOPLAY=10 WORDSFILE="$1" if [[ -z "$WORDSFILE" ]]; then @@ -9,5 +11,9 @@ if [[ -z "$WORDSFILE" ]]; then fi export LC_ALL=C # dont do unicode stuff in egrep -sort -R "$WORDSFILE" | sed 's/\/.*//' | egrep '^[A-Za-z]{5,}$' | head -n $WORDSTOPLAY | tr [:upper:] [:lower:] | qt/multypo +while true; do + sort -R "$WORDSFILE" | sed 's/\/.*//' | egrep '^[A-Za-z]{5,}$' | head -n "$WORDSTOPLAY" | tr [:upper:] [:lower:] | qt/multypo + echo "Press Ctrl-C to quit" + sleep 3 +done diff --git a/qt/multypo.cpp b/qt/multypo.cpp index 5ccfed8..d58d247 100644 --- a/qt/multypo.cpp +++ b/qt/multypo.cpp @@ -12,8 +12,8 @@ MultypoWindow::MultypoWindow(QWidget *parent) : QWidget(parent), - xiInited(false), - gameStarted(false) + state(Naming), + xiInited(false) { /* Prepare colors */ setStyleSheet("background-color: black; color: green; font-size: 45pt"); @@ -29,37 +29,48 @@ MultypoWindow::MultypoWindow(QWidget *parent) : setCursor(QCursor(Qt::BlankCursor)); words.open(stdin,QIODevice::ReadOnly); - - typingPlayers = 0; } MultypoWindow::~MultypoWindow() { } -void MultypoWindow::resetPlayerText() { - for (QMap::Iterator it = players.begin(); it != players.end(); ++it) { - it.value()->resetText(); - } -} - void MultypoWindow::nextWord() { QByteArray tmp = words.readLine().trimmed(); - QString word = QString::fromUtf8(tmp); - qDebug() << "New word" << word; - if (word.isEmpty()) { // game over + currentWord = QString::fromUtf8(tmp); + qDebug() << "New word" << currentWord; + if (currentWord.isEmpty()) { // game over mainLabel->setText("GAME OVER"); for (QMap::Iterator it = players.begin(); it != players.end(); ++it) { - QString tmp = QString ("Spieler %1 hat %2 Punkte.").arg(it.value()->getName()).arg(it.value()->score); - it.value()->setWaiting(tmp); + it.value()->showScore(); } + state = Scoring; } else { - resetPlayerText(); - mainLabel->setText(word); - typingPlayers = players.size(); + for (QMap::Iterator it = players.begin(); it != players.end(); ++it) { + it.value()->nextWord(); + } + mainLabel->setText(currentWord); + state = Playing; } } +bool MultypoWindow::allPlayersWaiting() +{ + for (QMap::Iterator it = players.begin(); it != players.end(); ++it) { + if (it.value()->getState() != Player::Waiting) return false; + } + return true; +} + +int MultypoWindow::typingPlayers() +{ + int n = 0; + for (QMap::Iterator it = players.begin(); it != players.end(); ++it) { + if (it.value()->getState() == Player::Typing) ++n; + } + return n; +} + void MultypoWindow::handleKeyPress(int device, QString string) { qDebug() << "Device" << device << "String" << string; @@ -70,40 +81,31 @@ void MultypoWindow::handleKeyPress(int device, QString string) } if (!players.contains(device)) { - if (gameStarted) + if (state > Naming) return; players[device] = new Player(this); } - bool newChar = players[device]->handleKey(string); - - if (gameStarted) { // ingame - qDebug() << "current player line" << players[device]->getCurrentLine(); - qDebug() << "current word" << mainLabel->text(); - if (newChar && players[device]->getCurrentLine() == mainLabel->text()) { - players[device]->score += typingPlayers; - QString readyString = QString("READY: %1 points").arg(typingPlayers); - players[device]->setWaiting(readyString); - qDebug() << "typingPlayers " << typingPlayers; - typingPlayers--; - qDebug() << "typingPlayers " << typingPlayers; - if (typingPlayers <= 0) { + Player *player = players[device]; + player->handleKey(string); + + if (state == Naming) { + // someone's still naming (or nobody's there yet) + qDebug() << "checking for game started"; + if (!players.empty() && allPlayersWaiting()) { + nextWord(); + } + } + else if (state == Playing) { // all players are waiting or typing + qDebug() << "current player line" << player->getCurrentWord(); + qDebug() << "current word" << currentWord; + if (player->getState() == Player::Typing && player->getCurrentWord() == currentWord) { + int points = typingPlayers()+1; + player->wordComplete(points); + QString readyString = QString("READY: %1 points").arg(points); + if (allPlayersWaiting()) { nextWord(); } } - } else { // name entering phase - qDebug() << "checking for game started"; - bool allHaveNames = true; - for (QMap::Iterator it = players.begin(); it != players.end(); ++it) { - if (! it.value()->hasName()) { - allHaveNames = false; - break; - } - } - qDebug() << "Players empty?" << players.empty() << "All have names?" << allHaveNames; - if (!players.empty() && allHaveNames) { - gameStarted = true; - nextWord(); - } } } diff --git a/qt/multypo.h b/qt/multypo.h index 1a088bd..3117c9f 100644 --- a/qt/multypo.h +++ b/qt/multypo.h @@ -12,6 +12,12 @@ class MultypoWindow : public QWidget Q_OBJECT public: + enum State { + Naming, + Playing, + Scoring + }; + explicit MultypoWindow(QWidget *parent = 0); ~MultypoWindow(); @@ -20,16 +26,17 @@ public: private: void handleKeyPress(int device, QString string); void nextWord(); - void resetPlayerText(); + bool allPlayersWaiting(); + int typingPlayers(); -private: + State state; // naming iff (no players or any player is naming) + QString currentWord; // defined iff state == Playing + QMap players; + bool xiInited; int xiOpcode; - bool gameStarted; QLabel *mainLabel; QFile words; - QMap players; - int typingPlayers; // how many are not ready yet }; #endif // MULTIKBD_H diff --git a/qt/player.cpp b/qt/player.cpp index 69e7651..4853823 100644 --- a/qt/player.cpp +++ b/qt/player.cpp @@ -3,57 +3,58 @@ #include #include -static QString colorToString(QColor col) -{ - return QString("#%1%2%3").arg(col.red(), 2, 16, QChar('0')) - .arg(col.green(), 2, 16, QChar('0')) - .arg(col.blue(), 2, 16, QChar('0')); -} - -Player::Player(QWidget* parent) : score(0) { +Player::Player(QWidget* parent) : score(0), state(Naming) { theLabel = new QLabel (parent); parent->layout()->addWidget(theLabel); - modifyable = true; qDebug() << "Player created"; } -bool Player::hasName() { - return !name.isEmpty(); -} - -QString Player::getName() { - return name; -} - -QString Player::getCurrentLine() { - return currentLine; +void Player::handleKey(QString str) +{ + // edit "current line" + if (str.length() == 1) { + currentWord += str; + } + else if (str == "BackSpace") { + currentWord.chop(1); + } + // see if this does anything useful + switch (state) { + case Naming: + theLabel->setText(currentWord); + if (str == "Return") { + name = currentWord; + state = Waiting; + theLabel->setText(""); + } + break; + case Waiting: + break; + case Typing: + theLabel->setText(currentWord); + break; + } +} + +void Player::wordComplete(int points) +{ + score += points; + state = Waiting; + theLabel->setText(""); } -void Player::setWaiting(QString labeltext) { - theLabel->setText(labeltext); - modifyable = false; +QString Player::getCurrentWord() { + Q_ASSERT(state == Typing); + return currentWord; } -void Player::resetText() { - currentLine.clear(); - theLabel->setText(currentLine); - modifyable = true; +void Player::nextWord() { + currentWord = ""; + theLabel->setText(currentWord); + state = Typing; } -bool Player::handleKey(QString str) { - if (!modifyable) - return false; - bool newChar = false; - if (str.length() == 1) { - currentLine += str; - newChar = true; - } else if (!hasName() && str == "Return") { - // set name - name = currentLine; - currentLine = ""; - } else if (str == "BackSpace") { - currentLine.chop(1); - } - theLabel->setText(currentLine); - return newChar; +void Player::showScore() { + Q_ASSERT(state == Waiting); + theLabel->setText(QString ("Spieler %1 hat %2 Punkte.").arg(name).arg(score)); } diff --git a/qt/player.h b/qt/player.h index 0facdd5..3817866 100644 --- a/qt/player.h +++ b/qt/player.h @@ -6,21 +6,32 @@ class Player { -private: - QString name; - QString currentLine; - QLabel* theLabel; - bool modifyable; public: + enum State { + Naming, + Waiting, + Typing + }; + Player(QWidget* parent); - bool handleKey(QString); /* returns whether a char was added */ - void resetText(); - bool hasName(); - QString getName(); - QString getCurrentLine(); - void setWaiting(QString labeltext); + + void handleKey(QString); + State getState() { return state; } + + void nextWord(); + QString getCurrentWord(); + void wordComplete(int points); + void showScore(); - int score; +private: + int score; + QString name; + QString currentWord; + QLabel* theLabel; + + State state; + + void updateLabel(); }; #endif // PLAYER_H