count-win-loss.cc
Go to the documentation of this file.
00001 #include "osl/container/moveVector.h"
00002 #include "osl/record/csaRecord.h"
00003 #include "osl/record/checkDuplicate.h"
00004 
00005 #include <boost/algorithm/string/trim.hpp>
00006 #include <boost/functional/hash.hpp>
00007 #include "boost/foreach.hpp"
00008 #include "boost/format.hpp"
00009 #include "boost/multi_array.hpp"
00010 #include <boost/program_options.hpp>
00011 #include <fstream>
00012 #include <iostream>
00013 #include <vector>
00014 
00016 static const unsigned int MAX_PLAYERS = 20; 
00017 
00019 typedef osl::stl::hash_map<std::string, unsigned int, boost::hash<std::string> > players_t;
00020 static players_t players;
00021 
00023 typedef boost::multi_array<unsigned int, 4> array_t;
00024 array_t winloss(boost::extents[MAX_PLAYERS][MAX_PLAYERS][2][3]);
00025 
00026 enum GameResult
00027 {
00028   BLACK_WIN = 0,
00029   WHITE_WIN,
00030   OTHERS
00031 };
00032 
00033 const std::string& getPlayerName(const unsigned int id)
00034 {
00035   players_t::const_iterator each_player = players.begin();
00036   for (; each_player != players.end(); ++each_player)
00037   {
00038     if (each_player->second == id)
00039       break;
00040   }
00041   assert(each_player != players.end());
00042   return each_player->first;
00043 }
00044 
00045 unsigned int setPlayer(const std::string& player)
00046 {
00047   players_t::const_iterator hit = players.find(player);
00048   if (hit == players.end())
00049   {
00050     // new player
00051     if (players.size() >= MAX_PLAYERS)
00052     {
00053       std::cerr << "No longer accomodate a new player.\n";
00054       exit(-1);
00055     }
00056     const unsigned int new_id = players.size();
00057     players.insert(std::make_pair(player, new_id));
00058     return new_id;
00059   }
00060   else
00061   {
00062     return hit->second;
00063   }
00064 }
00065 
00066 void increment(unsigned int black,
00067                unsigned int white,
00068                GameResult gr)
00069 {
00070   // player_a is black
00071   winloss[black][white][0][static_cast<unsigned int>(gr)] += 1;
00072   // player_a is white
00073   if (gr == BLACK_WIN)
00074   {
00075     winloss[white][black][1][1] += 1;  // player_a lost
00076   }
00077   else if (gr == WHITE_WIN)
00078   {
00079     winloss[white][black][1][0] += 1;  // player_a won
00080   }
00081   else
00082   {
00083     assert(gr == OTHERS);
00084     winloss[white][black][1][2] += 1;  // others
00085   }
00086 }
00087 
00088 GameResult getGameResult(const std::string& csa_file,
00089                          const osl::vector<osl::Move>& moves)
00090 {
00091   std::ifstream in(csa_file.c_str());
00092   if (!in)
00093   {
00094     std::cerr << "File not found: " << csa_file << "\n";
00095     exit(-1);
00096   }
00097   
00098   bool hit = false;
00099   std::string line;
00100   while (std::getline(in, line))
00101   {
00102     if (line.find("%TORYO") != std::string::npos)
00103     {
00104       hit = true;
00105       break;
00106     }
00107   }
00108 
00109   if (hit)
00110   {
00111     return (moves.size() % 2 == 1 ? BLACK_WIN : WHITE_WIN);
00112   }
00113   else
00114   {
00115     return OTHERS;
00116   }
00117 }
00118 
00119 
00120 void readFile(const std::string& csa_file,
00121               osl::record::CheckDuplicate& duplicates)
00122 {
00123   const osl::record::csa::CsaFile csa(csa_file);
00124   const osl::record::Record& record = csa.getRecord();
00125   const osl::vector<osl::Move> moves = record.getMoves();
00126  
00127   if (duplicates.regist(moves))
00128     return;
00129 
00130   const std::string& black = record.getPlayer(osl::BLACK);
00131   const std::string& white = record.getPlayer(osl::WHITE);
00132 
00133   const unsigned int black_id = setPlayer(black);
00134   const unsigned int white_id = setPlayer(white);
00135   
00136   const GameResult gr = getGameResult(csa_file, moves);
00137   increment(black_id, white_id, gr);
00138 }
00139 
00140 void printTotal(std::ostream& out)
00141 {
00142   out << "=== Total [ #wins / #losses / #others ] ===\n";
00143 
00144   for (unsigned int player_a = 0; player_a < players.size(); ++player_a)
00145   {
00146 
00147     for (unsigned int player_b = 0; player_b < players.size(); ++player_b)
00148     {
00149       if (player_a == player_b)
00150         continue;
00151 
00152       out << boost::format("%- 17s ") % getPlayerName(player_a);
00153 
00154       unsigned int wins = 0, losses = 0, others = 0;
00155       wins += winloss[player_a][player_b][0][0];   // a is black
00156       wins += winloss[player_a][player_b][1][0];   // a is white
00157       losses += winloss[player_a][player_b][0][1]; // a is black
00158       losses += winloss[player_a][player_b][1][1];
00159       others += winloss[player_a][player_b][0][2]; // a is black
00160       others += winloss[player_a][player_b][1][2];
00161 
00162       out << boost::format("%5d/%5d/%5d ") 
00163         % wins % losses % others;
00164 
00165       out << boost::format("%- 17s ") % getPlayerName(player_b);
00166     }
00167     out << "\n";
00168   }
00169   out << "\n";
00170 }
00171 
00172 void printResult(std::ostream& out)
00173 {
00174   out << "=== Left players are BLACK [ #wins / #losses / #others ] ===\n";
00175   out << boost::format("%= 17s ") % "";
00176   for (unsigned int player_a = 0; player_a < players.size(); ++player_a)
00177   {
00178     out << boost::format("%= 17s ") % getPlayerName(player_a);
00179   }
00180   out << "\n";
00181 
00182   for (unsigned int player_a = 0; player_a < players.size(); ++player_a)
00183   {
00184     out << boost::format("%= 17s ") % getPlayerName(player_a);
00185 
00186     for (unsigned int player_b = 0; player_b < players.size(); ++player_b)
00187     {
00188       if (player_a == player_b)
00189       {
00190         out << boost::format("%= 17s ") % "-";
00191         continue;
00192       }
00193 
00194       out << boost::format("%5d/%5d/%5d ") 
00195         % winloss[player_a][player_b][0][0]
00196         % winloss[player_a][player_b][0][1]
00197         % winloss[player_a][player_b][0][2];
00198     }
00199     out << "\n";
00200   }
00201   out << "\n";
00202 }
00203 
00204 
00205 int main(int argc, char **argv)
00206 {
00207   std::string kisen_filename;
00208 
00209   boost::program_options::options_description command_line_options;
00210   command_line_options.add_options()
00211     ("input-file", boost::program_options::value<std::vector<std::string> >(),
00212      "input files in the CSA format")
00213     ("help", "Show help message");
00214   boost::program_options::variables_map vm;
00215   boost::program_options::positional_options_description p;
00216   p.add("input-file", -1);
00217 
00218   try
00219   {
00220     boost::program_options::store(
00221       boost::program_options::command_line_parser(
00222         argc, argv).options(command_line_options).positional(p).run(), vm);
00223     boost::program_options::notify(vm);
00224     if (vm.count("help"))
00225     {
00226       std::cerr << "Usage: " << argv[0] << " [options] csa-file [...]\n";
00227       std::cerr << "       " << argv[0] << " [options]\n";
00228       std::cout << command_line_options << std::endl;
00229       return 0;
00230     }
00231   }
00232   catch (std::exception &e)
00233   {
00234     std::cerr << "error in parsing options" << std::endl
00235               << e.what() << std::endl;
00236     std::cerr << "Usage: " << argv[0] << " [options] csa-file [...]\n";
00237     std::cerr << "       " << argv[0] << " [options]\n";
00238     std::cerr << command_line_options << std::endl;
00239     return 1;
00240   }
00241 
00242   std::vector<std::string> files;
00243   if (vm.count("input-file"))
00244   {
00245     const std::vector<std::string> temp = vm["input-file"].as<std::vector<std::string> >();
00246     files.insert(files.end(), temp.begin(), temp.end());
00247   }
00248   else
00249   {
00250     std::string line;
00251     while(std::getline(std::cin , line))
00252     {
00253       boost::algorithm::trim(line);
00254       files.push_back(line);
00255     }
00256   }
00257 
00258   osl::record::CheckDuplicate check_duplicate;
00259 
00260   BOOST_FOREACH(const std::string& file, files)
00261   {
00262     readFile(file, check_duplicate);
00263   }
00264 
00265   std::locale::global(std::locale(""));
00266   printResult(std::cout);
00267   printTotal(std::cout);
00268   check_duplicate.print(std::cout);
00269 
00270   return 0;
00271 }
00272 
00273 /* vim: set ts=2 sw=2 ft=cpp : */
00274 // ;;; Local Variables:
00275 // ;;; mode:c++
00276 // ;;; c-basic-offset:2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines