Move current client code out to server file, still uses old file-system method

This commit is contained in:
mdiluzio 2015-01-02 14:04:37 +00:00
parent 3b5599ffad
commit 0962546a82
3 changed files with 230 additions and 218 deletions

View file

@ -1,16 +1,8 @@
#include <iostream>
#include <fstream>
#include <chrono>
#include <thread>
#include <sys/stat.h>
#include <stdio.h>
#include <stdbool.h>
#include <formatters.h>
#include <unistd.h>
#include <stdlib.h>
#include "game.h" #include "game.h"
#include "server.h"
#include <iostream>
#include <unistd.h>
#define STRINGIFY(x) _STRINGIFY(x) #define STRINGIFY(x) _STRINGIFY(x)
#define _STRINGIFY(x) #x #define _STRINGIFY(x) #x
@ -18,45 +10,6 @@
static const char* sk_usage = static const char* sk_usage =
#include "usage.h" #include "usage.h"
; ;
// Verbose mode
static const bool env_verbose = getenv("VERBOSE");
// time for waiting between file stats
static const std::chrono::milliseconds sk_waitTime = std::chrono::milliseconds(100);
// Check if a file exists
inline bool FileExists( const std::string& name )
{
struct stat buffer;
return (stat (name.c_str(), &buffer) == 0);
}
// Wait for a file to exist
inline void WaitForFile( const std::string& name, const std::chrono::milliseconds& time )
{
while( !FileExists(name) ) std::this_thread::sleep_for(time);
}
bool OutputGameStateFile(CTTRTSGame &game, std::string &gameDir)
{
char turnFileName[128];
snprintf(turnFileName,128,"%s/Turn_%i.txt",gameDir.c_str(),game.GetTurn());
std::ofstream turnFile(turnFileName, std::ios_base::trunc); // truncate to overwrite if a file exists
if ( turnFile.bad() )
{
return false;
}
// Output the turn description
std::string turnDescriptor = GetStringFromGame(game);
turnFile<<turnDescriptor;
turnFile.close();
return true;
}
// Main program entry point // Main program entry point
int main(int argc, char* argv[]) int main(int argc, char* argv[])
@ -107,171 +60,6 @@ int main(int argc, char* argv[])
return -1; return -1;
} }
std::ifstream file(gameFile); return runServer(ttrts_games_dir, gameFile);
std::cout<<"Launching TTRTS with "<<gameFile<<std::endl;
std::string gameDescriptor;
// Reserve the string needed up front
file.seekg(0, std::ios::end);
gameDescriptor.reserve(file.tellg());
file.seekg(0, std::ios::beg);
// Grab the string from the file
gameDescriptor.assign((std::istreambuf_iterator<char>(file)),std::istreambuf_iterator<char>());
if( gameDescriptor.size() == 0 )
{
std::cerr<<"Error: failed to read in any information from "<<gameFile<<std::endl;
return -1;
}
// Create the game
CTTRTSGame game = GetGameFromString(gameDescriptor);
// Grab the players involved
auto players = game.GetPlayers();
// Current game directory
std::string gameDir = ttrts_games_dir + game.GetName();
// Empty the current game directory
struct stat info;
int ret = stat( gameDir.c_str(), &info );
if( ret == 0 && info.st_mode & S_IFDIR )
{
std::cout<< gameDir << " game directory already exists"<<std::endl;
std::cout<<"Confirm to delete contents [y/N] ";
std::string input;
std::cin>>input;
if( !input.size() || std::tolower(input[0]) != 'y' )
{
std::cerr<<"Aborting..."<<std::endl;
return -1;
}
}
else if ( ret == 0 )
{
std::cerr<< gameDir << " exists but is not directory \nAborting..."<<std::endl;
return -1;
}
// Create the game directory
char cmd2[128];
snprintf(cmd2,128, "test -d %s || mkdir %s",gameDir.c_str(),gameDir.c_str());
if( system(cmd2) == -1)
{
std::cerr<<"Error: Failed to create the game directory"<<std::endl;
return -1;
}
// Clean out the game directory
char cmd1[128];
snprintf(cmd1,128, "rm -rf %s/*",gameDir.c_str());
if ( system(cmd1) == -1 )
{
std::cerr<<"Error: Failed to clean the game directory"<<std::endl;
return -1;
}
// While the game isn't finished
while ( ! game.GameOver() )
{
std::cout<<"Starting turn "<<game.GetTurn()<<std::endl;
// Create a turn file
if( !OutputGameStateFile(game, gameDir))
{
std::cerr<<"Error: Failed to output new turn file" << std::endl;
return 1;
}
// Wait for order files
for( player_t player : players)
{
// Construct the player order filename
char playerOrderFileName[128];
snprintf(playerOrderFileName, 128, "%s/Player_%i_Turn_%i.txt", gameDir.c_str(), (int) player, game.GetTurn());
// Wait for the player order file to be created
std::cout<<"Waiting for "<< playerOrderFileName <<std::endl;
bool hasOrderFile = false;
while(!hasOrderFile)
{
WaitForFile(playerOrderFileName,sk_waitTime); // Wait for the file
// File must have END
// Method taken from http://stackoverflow.com/questions/11876290/c-fastest-way-to-read-only-last-line-of-text-file
std::ifstream turnFile(playerOrderFileName);
turnFile.seekg(-1,std::ios_base::end);
// Loop back from the end of file
bool keepLooping = true;
while(keepLooping) {
char ch;
turnFile.get(ch); // Get current byte's data
if((int)turnFile.tellg() <= 1) { // If the data was at or before the 0th byte
turnFile.seekg(0); // The first line is the last line
keepLooping = false; // So stop there
}
else if(ch == '\n') { // If the data was a newline
keepLooping = false; // Stop at the current position.
}
else { // If the data was neither a newline nor at the 0 byte
turnFile.seekg(-2,std::ios_base::cur); // Move to the front of that data, then to the front of the data before it
}
}
// Grab this line
std::string lastLine;
std::getline(turnFile,lastLine);
if(lastLine == "END")
hasOrderFile = true;
}
std::ifstream turnFile(playerOrderFileName);
// Reserve the full order string
std::string orders;
turnFile.seekg(0, std::ios::end);
orders.reserve(turnFile.tellg());
turnFile.seekg(0, std::ios::beg);
// Grab the string from the file
orders.assign((std::istreambuf_iterator<char>(turnFile)),std::istreambuf_iterator<char>());
// Issue the orders to the game
if( game.IssueOrders(player, orders) )
std::cerr<<"Warning: Orders for player "<<(int) player <<" failed to correctly parse"<<std::endl;
}
// Simulate turn
std::cout<<"Simulating this turn!"<<std::endl;
if ( game.SimulateToNextTurn() )
{
std::cerr << "Error: Failed to simulate for turn "<<game.GetTurn()<<std::endl;
return -1;
}
}
// Output final gamestate
OutputGameStateFile(game, gameDir);
// Get the winning player
player_t winningPlayer = game.GetWinningPlayer();
// Print the winner!
if ( winningPlayer != player_t::NUM_INVALID )
{
std::cout<<"Game over! Winner:"<<(int) winningPlayer <<std::endl;
}
else
{
std::cout<<"Game over! It was a draw!"<<std::endl;
}
return (int)winningPlayer;
}; };

View file

@ -1 +1,221 @@
#include "server.h" #include "server.h"
#include <iostream>
#include <fstream>
#include <chrono>
#include <thread>
#include <sys/stat.h>
#include <stdio.h>
#include <stdbool.h>
#include <formatters.h>
#include <unistd.h>
#include <stdlib.h>
// time for waiting between file stats
static const std::chrono::milliseconds sk_waitTime = std::chrono::milliseconds(100);
// Check if a file exists
inline bool FileExists( const std::string& name )
{
struct stat buffer;
return (stat (name.c_str(), &buffer) == 0);
}
// Wait for a file to exist
inline void WaitForFile( const std::string& name, const std::chrono::milliseconds& time )
{
while( !FileExists(name) ) std::this_thread::sleep_for(time);
}
bool OutputGameStateFile(CTTRTSGame &game, const std::string &gameDir)
{
char turnFileName[128];
snprintf(turnFileName,128,"%s/Turn_%i.txt",gameDir.c_str(),game.GetTurn());
std::ofstream turnFile(turnFileName, std::ios_base::trunc); // truncate to overwrite if a file exists
if ( turnFile.bad() )
{
return false;
}
// Output the turn description
std::string turnDescriptor = GetStringFromGame(game);
turnFile<<turnDescriptor;
turnFile.close();
return true;
}
int runServer(const std::string& ttrts_dir,const std::string& gameFile)
{
std::ifstream file(gameFile);
std::cout<<"Launching TTRTS with "<<gameFile<<std::endl;
std::string gameDescriptor;
// Reserve the string needed up front
file.seekg(0, std::ios::end);
gameDescriptor.reserve(file.tellg());
file.seekg(0, std::ios::beg);
// Grab the string from the file
gameDescriptor.assign((std::istreambuf_iterator<char>(file)),std::istreambuf_iterator<char>());
if( gameDescriptor.size() == 0 )
{
std::cerr<<"Error: failed to read in any information from "<<gameFile<<std::endl;
return -1;
}
// Create the game
CTTRTSGame game = GetGameFromString(gameDescriptor);
// Grab the players involved
auto players = game.GetPlayers();
// Current game directory
std::string gameDir = ttrts_dir + game.GetName();
// Empty the current game directory
struct stat info;
int ret = stat( gameDir.c_str(), &info );
if( ret == 0 && info.st_mode & S_IFDIR )
{
std::cout<< gameDir << " game directory already exists"<<std::endl;
std::cout<<"Confirm to delete contents [y/N] ";
std::string input;
std::cin>>input;
if( !input.size() || std::tolower(input[0]) != 'y' )
{
std::cerr<<"Aborting..."<<std::endl;
return -1;
}
}
else if ( ret == 0 )
{
std::cerr<< gameDir << " exists but is not directory \nAborting..."<<std::endl;
return -1;
}
// Create the game directory
char cmd2[128];
snprintf(cmd2,128, "test -d %s || mkdir %s",gameDir.c_str(),gameDir.c_str());
if( system(cmd2) == -1)
{
std::cerr<<"Error: Failed to create the game directory"<<std::endl;
return -1;
}
// Clean out the game directory
char cmd1[128];
snprintf(cmd1,128, "rm -rf %s/*",gameDir.c_str());
if ( system(cmd1) == -1 )
{
std::cerr<<"Error: Failed to clean the game directory"<<std::endl;
return -1;
}
// While the game isn't finished
while ( ! game.GameOver() )
{
std::cout<<"Starting turn "<<game.GetTurn()<<std::endl;
// Create a turn file
if( !OutputGameStateFile(game, gameDir))
{
std::cerr<<"Error: Failed to output new turn file" << std::endl;
return 1;
}
// Wait for order files
for( player_t player : players)
{
// Construct the player order filename
char playerOrderFileName[128];
snprintf(playerOrderFileName, 128, "%s/Player_%i_Turn_%i.txt", gameDir.c_str(), (int) player, game.GetTurn());
// Wait for the player order file to be created
std::cout<<"Waiting for "<< playerOrderFileName <<std::endl;
bool hasOrderFile = false;
while(!hasOrderFile)
{
WaitForFile(playerOrderFileName,sk_waitTime); // Wait for the file
// File must have END
// Method taken from http://stackoverflow.com/questions/11876290/c-fastest-way-to-read-only-last-line-of-text-file
std::ifstream turnFile(playerOrderFileName);
turnFile.seekg(-1,std::ios_base::end);
// Loop back from the end of file
bool keepLooping = true;
while(keepLooping) {
char ch;
turnFile.get(ch); // Get current byte's data
if((int)turnFile.tellg() <= 1) { // If the data was at or before the 0th byte
turnFile.seekg(0); // The first line is the last line
keepLooping = false; // So stop there
}
else if(ch == '\n') { // If the data was a newline
keepLooping = false; // Stop at the current position.
}
else { // If the data was neither a newline nor at the 0 byte
turnFile.seekg(-2,std::ios_base::cur); // Move to the front of that data, then to the front of the data before it
}
}
// Grab this line
std::string lastLine;
std::getline(turnFile,lastLine);
if(lastLine == "END")
hasOrderFile = true;
}
std::ifstream turnFile(playerOrderFileName);
// Reserve the full order string
std::string orders;
turnFile.seekg(0, std::ios::end);
orders.reserve(turnFile.tellg());
turnFile.seekg(0, std::ios::beg);
// Grab the string from the file
orders.assign((std::istreambuf_iterator<char>(turnFile)),std::istreambuf_iterator<char>());
// Issue the orders to the game
if( game.IssueOrders(player, orders) )
std::cerr<<"Warning: Orders for player "<<(int) player <<" failed to correctly parse"<<std::endl;
}
// Simulate turn
std::cout<<"Simulating this turn!"<<std::endl;
if ( game.SimulateToNextTurn() )
{
std::cerr << "Error: Failed to simulate for turn "<<game.GetTurn()<<std::endl;
return -1;
}
}
// Output final gamestate
OutputGameStateFile(game, gameDir);
// Get the winning player
player_t winningPlayer = game.GetWinningPlayer();
// Print the winner!
if ( winningPlayer != player_t::NUM_INVALID )
{
std::cout<<"Game over! Winner:"<<(int) winningPlayer <<std::endl;
}
else
{
std::cout<<"Game over! It was a draw!"<<std::endl;
}
return (int)winningPlayer;
}

View file

@ -1,4 +1,8 @@
#ifndef _TTRTS_SERVER_H_ #ifndef _TTRTS_SERVER_H_
#define _TTRTS_SERVER_H_ #define _TTRTS_SERVER_H_
#include <string>
int runServer(const std::string& dir,const std::string& file);
#endif #endif