json serialization for requests and responses
This commit is contained in:
parent
8736aee27c
commit
4b80878d33
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
bin/*
|
||||
*.swp
|
||||
|
1
Makefile
1
Makefile
@ -1,2 +1,3 @@
|
||||
azool:
|
||||
mkdir -p bin
|
||||
g++ src/*.cc -I./include -o bin/azool -Werror -Weffc++ -std=c++11
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <ostream>
|
||||
#include <cstring>
|
||||
#include <random>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include "tile_utils.h"
|
||||
|
||||
class GameBoard {
|
||||
@ -22,6 +23,8 @@ public:
|
||||
bool takeTilesFromPool(azool::TileColor color, int& numTiles, bool& poolPenalty);
|
||||
void returnTilesToBag(int numTiles, azool::TileColor color);
|
||||
void dealTiles();
|
||||
void handleRequest(std::stringstream);
|
||||
boost::property_tree::ptree serializeBoard() const;
|
||||
int numFactories() {
|
||||
return tileFactories.size();
|
||||
}
|
||||
@ -39,6 +42,7 @@ private:
|
||||
// - vector of factories?
|
||||
std::vector<Factory> tileFactories;
|
||||
int maxNumFactories;
|
||||
int myNumPlayers;
|
||||
int pool[azool::NUMCOLORS]; // stores the count of each color currently in the pool; initialize to 0s
|
||||
bool whiteTileInPool; // initialize to true
|
||||
std::vector<azool::TileColor> tileBag; // initialize to 20 of each color
|
||||
|
@ -25,6 +25,7 @@ public:
|
||||
const std::string getPlayerName() const {
|
||||
return myName;
|
||||
}
|
||||
void sendRequest(/*string or stringstream?*/);
|
||||
|
||||
private:
|
||||
Player(const Player&) = delete;
|
||||
|
@ -19,5 +19,11 @@ const std::string TileColorStrings[NUMCOLORS] = {
|
||||
};
|
||||
|
||||
const char TileColorSyms[NUMCOLORS] = { 'r', 'b', 'g', 'y', 'k' };
|
||||
const int MAXPLAYERS = 4;
|
||||
|
||||
const std::string REQ_TYPE_DRAW_FROM_FACTORY = "DRAW_FROM_FACTORY";
|
||||
const std::string REQ_TYPE_DRAW_FROM_POOL = "DRAW_FROM_POOL";
|
||||
const std::string REQ_TYPE_RETURN_TO_BAG = "RETURN_TO_BAG";
|
||||
const std::string REQ_TYPE_GET_BOARD = "GET_BOARD";
|
||||
}
|
||||
#endif // TILE_UTILS_H_
|
||||
|
@ -1,9 +1,14 @@
|
||||
#include "GameBoard.h"
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace pt = boost::property_tree;
|
||||
|
||||
GameBoard::GameBoard(int numPlayers) :
|
||||
tileFactories(),
|
||||
myNumPlayers(numPlayers),
|
||||
maxNumFactories(numPlayers*2+1),
|
||||
pool(),
|
||||
whiteTileInPool(true),
|
||||
@ -40,6 +45,7 @@ std::ostream& operator<<(std::ostream& out, const GameBoard& board) {
|
||||
bool GameBoard::validFactoryRequest(int factoryIdx, azool::TileColor color) {
|
||||
// check if color exists on specified factory
|
||||
bool retVal = factoryIdx < tileFactories.size() and
|
||||
factoryIdx > -1 and
|
||||
tileFactories[factoryIdx].tileCounts[color] > 0;
|
||||
return retVal;
|
||||
}
|
||||
@ -72,12 +78,12 @@ bool GameBoard::takeTilesFromPool(azool::TileColor color, int& numTiles, bool& p
|
||||
poolPenalty = whiteTileInPool;
|
||||
whiteTileInPool = false;
|
||||
return true;
|
||||
}
|
||||
} // GameBoard::takeTilesFromPool
|
||||
void GameBoard::returnTilesToBag(int numTiles, azool::TileColor color) {
|
||||
for (int ii = 0; ii < numTiles; ++ii) {
|
||||
tileBag.emplace_back(color);
|
||||
}
|
||||
}
|
||||
} // GameBoard::returnTilesToBag
|
||||
|
||||
// random shuffle then read from the beginning of the vector?
|
||||
void GameBoard::dealTiles() {
|
||||
@ -102,6 +108,91 @@ void GameBoard::dealTiles() {
|
||||
}
|
||||
} // GameBoard::dealTiles
|
||||
|
||||
pt::ptree GameBoard::serializeBoard() const {
|
||||
pt::ptree outTree;
|
||||
// factories
|
||||
pt::ptree factTree;
|
||||
int factCt = 1;
|
||||
for (auto factory : tileFactories) {
|
||||
std::stringstream factSS;
|
||||
for (int ii = 0; ii < azool::NUMCOLORS; ++ii) {
|
||||
for (int jj = 0; jj < factory.tileCounts[ii]; ++jj) {
|
||||
factSS << azool::TileColorStrings[ii] << ",";
|
||||
}
|
||||
}
|
||||
factTree.put(std::to_string(factCt), factSS.str());
|
||||
factCt++;
|
||||
}
|
||||
outTree.add_child("factories", factTree);
|
||||
outTree.put("num_factories", tileFactories.size());
|
||||
// pool
|
||||
pt::ptree poolTree;
|
||||
for (int ii = 0; ii < azool::NUMCOLORS; ++ii) {
|
||||
poolTree.put(azool::TileColorStrings[ii], pool[ii]);
|
||||
}
|
||||
if (whiteTileInPool) {
|
||||
poolTree.put("penalty", -1);
|
||||
}
|
||||
else {
|
||||
poolTree.put("penalty", 0);
|
||||
}
|
||||
outTree.add_child("pool", poolTree);
|
||||
outTree.put("end_of_round", endOfRound());
|
||||
return outTree;
|
||||
} // GameBoard::serializeBoard
|
||||
|
||||
void GameBoard::handleRequest(std::stringstream iss) {
|
||||
pt::ptree inTree;
|
||||
pt::read_json(iss, inTree);
|
||||
pt::ptree outTree;
|
||||
std::string req_type = inTree.get<std::string>("req_type");
|
||||
// check type of request; check that required parameters are present; etc
|
||||
// return: json with results, status, error msg if any
|
||||
if (req_type.compare(azool::REQ_TYPE_DRAW_FROM_FACTORY) == 0) {
|
||||
int idx = inTree.get<int>("factory_idx", -1);
|
||||
int numTiles = 0;
|
||||
azool::TileColor color = static_cast<azool::TileColor>(inTree.get<int>("tile_color"));
|
||||
bool success = takeTilesFromFactory(idx, color, numTiles);
|
||||
outTree.put("status", success ? "success" : "fail");
|
||||
outTree.put("success", success);
|
||||
outTree.put("num_tiles_returned", numTiles);
|
||||
if (!success) {
|
||||
outTree.put("error_msg", "INVALID FACTORY REQUEST");
|
||||
}
|
||||
}
|
||||
else if (req_type.compare(azool::REQ_TYPE_DRAW_FROM_POOL) == 0) {
|
||||
azool::TileColor color = static_cast<azool::TileColor>(inTree.get<int>("tile_color"));
|
||||
int numTiles = 0;
|
||||
bool penalty = false;
|
||||
bool success = takeTilesFromPool(color, numTiles, penalty);
|
||||
outTree.put("success", success);
|
||||
outTree.put("status", success ? "success" : "fail");
|
||||
outTree.put("num_tiles_returned", numTiles);
|
||||
outTree.put("pool_penalty", penalty);
|
||||
if (!success) {
|
||||
outTree.put("error_msg", "INVALID POOL REQUEST");
|
||||
}
|
||||
}
|
||||
else if (req_type.compare(azool::REQ_TYPE_RETURN_TO_BAG) == 0) {
|
||||
int numTiles = inTree.get<int>("num_tiles_returned", 0);
|
||||
azool::TileColor color = static_cast<azool::TileColor>(inTree.get<int>("tile_color"));
|
||||
returnTilesToBag(numTiles, color);
|
||||
outTree.put("success", true); // no reason for this to fail
|
||||
outTree.put("status", "success");
|
||||
}
|
||||
else if (req_type.compare(azool::REQ_TYPE_GET_BOARD) == 0) {
|
||||
outTree = serializeBoard();
|
||||
}
|
||||
else {
|
||||
// ERROR, BAD THINGS
|
||||
outTree.put("error_msg", "INVALID REQUEST TYPE");
|
||||
}
|
||||
outTree.put("req_type", req_type); // include request type in returned data
|
||||
std::stringstream oss;
|
||||
pt::write_json(oss, outTree);
|
||||
// send oss over socket
|
||||
} // GameBoard::handleRequest
|
||||
|
||||
void GameBoard::resetBoard() {
|
||||
memset(pool, 0, azool::NUMCOLORS*sizeof(int));
|
||||
tileBag.clear();
|
||||
|
@ -41,7 +41,14 @@ bool Player::checkValidMove(azool::TileColor color, int rowIdx) const {
|
||||
} // Player::checkValidMove
|
||||
|
||||
bool Player::takeTilesFromFactory(int factoryIdx, azool::TileColor color, int rowIdx) {
|
||||
// call game board -> takeTiles(factoryIdx, color)
|
||||
// pt::ptree request;
|
||||
// request.put("req_type", azool::REQ_TYPE_DRAW_FROM_POOL);
|
||||
// request.put("tile_color", color);
|
||||
// request.put("factory_idx", factoryIdx);
|
||||
// std::stringstream oss;
|
||||
// pt::write_json(request, oss);
|
||||
// send request to board
|
||||
// recieve response
|
||||
int numTiles = 0;
|
||||
if (checkValidMove(color, rowIdx) and
|
||||
myBoardPtr->takeTilesFromFactory(factoryIdx, color, numTiles)) {
|
||||
@ -58,6 +65,16 @@ bool Player::takeTilesFromPool(azool::TileColor color, int rowIdx) {
|
||||
if (!checkValidMove(color, rowIdx)) {
|
||||
return false;
|
||||
}
|
||||
// pt::ptree request;
|
||||
// request.put("req_type", azool::REQ_TYPE_DRAW_FROM_POOL);
|
||||
// request.put("tile_color", color);
|
||||
// std::stringstream oss;
|
||||
// pt::write_json(request, oss);
|
||||
// send request to board
|
||||
// recieve response
|
||||
// bool success = inTree.get<bool>("success");
|
||||
// int numTiles = inTree.get<int>("num_tiles_returned");
|
||||
// bool poolPenalty = inTree.get<bool>("pool_penalty");
|
||||
if (!myBoardPtr->takeTilesFromPool(color, numTiles, poolPenalty)) {
|
||||
return false; // couldn't get that tile from the pool
|
||||
}
|
||||
@ -98,6 +115,11 @@ void Player::endRound(bool& fullRow) {
|
||||
myGrid[rowIdx][col] = true;
|
||||
myScore += scoreTile(rowIdx, col);
|
||||
// return extra tiles -- rowIdx = the number of leftover tiles
|
||||
// pt::ptree request;
|
||||
// request.put("req_type", azool::REQ_TYPE_RETURN_TO_BAG);
|
||||
// request.put("num_tiles_returned", rowIdx);
|
||||
// request.put("tile_color", myRows[rowIdx].second);
|
||||
// send request to gameboard
|
||||
myBoardPtr->returnTilesToBag(rowIdx, myRows[rowIdx].second);
|
||||
// reset rows for next turn
|
||||
myRows[rowIdx].first = 0;
|
||||
@ -235,6 +257,8 @@ void Player::finalizeScore() {
|
||||
} // Player::finalizeScore
|
||||
|
||||
std::string Player::printMyBoard() const {
|
||||
// pt::ptree request;
|
||||
// request.put("req_type", REQ_TYPE_GET_BOARD);
|
||||
std::ostringstream oss;
|
||||
oss << "*******************************\n";
|
||||
oss << "PLAYER: " << myName << "\n";
|
||||
@ -275,6 +299,17 @@ std::string Player::printMyBoard() const {
|
||||
|
||||
bool Player::discardFromFactory(int factoryIdx, azool::TileColor color) {
|
||||
int numTiles = -1;
|
||||
// pt::ptree request;
|
||||
// request.put("req_type", azool::REQ_TYPE_DRAW_FROM_FACTORY);
|
||||
// request.put("factory_idx", factoryIdx);
|
||||
// request.put("tile_color", color);
|
||||
// std::stringstream oss;
|
||||
// pt::write_json(request, oss);
|
||||
// send request to board
|
||||
// recieve response
|
||||
// bool success = inTree.get<bool>("success");
|
||||
// int numTiles = inTree.get<int>("num_tiles_returned");
|
||||
// if (success) myNumPenaltiesForRound += numTiles;
|
||||
if (myBoardPtr->takeTilesFromFactory(factoryIdx, color, numTiles)) {
|
||||
myNumPenaltiesForRound += numTiles;
|
||||
return true;
|
||||
@ -283,6 +318,16 @@ bool Player::discardFromFactory(int factoryIdx, azool::TileColor color) {
|
||||
} // Player::discardFromFactory
|
||||
|
||||
bool Player::discardFromPool(azool::TileColor color) {
|
||||
// pt::ptree request;
|
||||
// request.put("req_type", azool::REQ_TYPE_DRAW_FROM_POOL);
|
||||
// request.put("tile_color", color);
|
||||
// std::stringstream oss;
|
||||
// pt::write_json(request, oss);
|
||||
// send request to board
|
||||
// recieve response
|
||||
// bool success = inTree.get<bool>("success");
|
||||
// int numTiles = inTree.get<int>("num_tiles_returned");
|
||||
// bool poolPenalty = inTree.get<bool>("pool_penalty");
|
||||
bool poolPenalty = false;
|
||||
int numTiles = -1;
|
||||
if (myBoardPtr->takeTilesFromPool(color, numTiles, poolPenalty)) {
|
||||
@ -296,13 +341,13 @@ bool Player::discardFromPool(azool::TileColor color) {
|
||||
} // Player::discardFromPool
|
||||
|
||||
namespace {
|
||||
int promptForFactoryIdx(int maxNumFactories) {
|
||||
int promptForFactoryIdx(int maxFactIdx) {
|
||||
static const char* promptFactoryIdxDraw = "Which factory? enter index\n";
|
||||
char factInput; // TODO can we safely say there will never be more than 9 possible?
|
||||
std::cout << promptFactoryIdxDraw << std::flush;
|
||||
std::cin >> factInput;
|
||||
int factIdx = std::atoi(&factInput);
|
||||
if (factIdx < 1 or factIdx > maxNumFactories) {
|
||||
if (factIdx < 1 or factIdx > maxFactIdx) {
|
||||
return -1;
|
||||
}
|
||||
return factIdx;
|
||||
@ -348,6 +393,11 @@ int promptForRow() {
|
||||
|
||||
void Player::takeTurn() {
|
||||
// print game board, handle user input
|
||||
// pt::ptree request;
|
||||
// request.put("req_type", REQ_TYPE_GET_BOARD);
|
||||
// bool endOfRound = inTree.get<bool>("end_of_round");
|
||||
// // max idx for input - users use 1-indexing
|
||||
// int maxFactIdx = inTree.get<int>("num_factories");
|
||||
if (myBoardPtr->endOfRound()) return;
|
||||
std::cout << printMyBoard();
|
||||
static const char* promptDrawInput = "What would you like to do?\n"
|
||||
|
@ -26,7 +26,7 @@ void playGame(GameBoard* game) {
|
||||
secondPlayer->takeTurn();
|
||||
}
|
||||
// check who took penalty
|
||||
// nees to be done before claling player->endRound()
|
||||
// needs to be done before claling player->endRound()
|
||||
if (players[0]->tookPenalty()) {
|
||||
firstPlayer = players[0];
|
||||
secondPlayer = players[1];
|
||||
|
Loading…
x
Reference in New Issue
Block a user