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
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
00071 winloss[black][white][0][static_cast<unsigned int>(gr)] += 1;
00072
00073 if (gr == BLACK_WIN)
00074 {
00075 winloss[white][black][1][1] += 1;
00076 }
00077 else if (gr == WHITE_WIN)
00078 {
00079 winloss[white][black][1][0] += 1;
00080 }
00081 else
00082 {
00083 assert(gr == OTHERS);
00084 winloss[white][black][1][2] += 1;
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];
00156 wins += winloss[player_a][player_b][1][0];
00157 losses += winloss[player_a][player_b][0][1];
00158 losses += winloss[player_a][player_b][1][1];
00159 others += winloss[player_a][player_b][0][2];
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
00274
00275
00276