All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
count-win-loss.cc
Go to the documentation of this file.
2 #include "osl/record/csaRecord.h"
4 
5 #include <boost/algorithm/string/trim.hpp>
6 #include <boost/functional/hash.hpp>
7 #include "boost/foreach.hpp"
8 #include "boost/format.hpp"
9 #include "boost/multi_array.hpp"
10 #include <boost/program_options.hpp>
11 #include <fstream>
12 #include <iostream>
13 #include <vector>
14 
16 static const unsigned int MAX_PLAYERS = 20;
17 
21 
23 typedef boost::multi_array<unsigned int, 4> array_t;
24 array_t winloss(boost::extents[MAX_PLAYERS][MAX_PLAYERS][2][3]);
25 
27 {
28  BLACK_WIN = 0,
31 };
32 
33 const std::string& getPlayerName(const unsigned int id)
34 {
35  players_t::const_iterator each_player = players.begin();
36  for (; each_player != players.end(); ++each_player)
37  {
38  if (each_player->second == id)
39  break;
40  }
41  assert(each_player != players.end());
42  return each_player->first;
43 }
44 
45 unsigned int setPlayer(const std::string& player)
46 {
47  players_t::const_iterator hit = players.find(player);
48  if (hit == players.end())
49  {
50  // new player
51  if (players.size() >= MAX_PLAYERS)
52  {
53  std::cerr << "No longer accomodate a new player.\n";
54  exit(-1);
55  }
56  const unsigned int new_id = players.size();
57  players.insert(std::make_pair(player, new_id));
58  return new_id;
59  }
60  else
61  {
62  return hit->second;
63  }
64 }
65 
66 void increment(unsigned int black,
67  unsigned int white,
68  GameResult gr)
69 {
70  // player_a is black
71  winloss[black][white][0][static_cast<unsigned int>(gr)] += 1;
72  // player_a is white
73  if (gr == BLACK_WIN)
74  {
75  winloss[white][black][1][1] += 1; // player_a lost
76  }
77  else if (gr == WHITE_WIN)
78  {
79  winloss[white][black][1][0] += 1; // player_a won
80  }
81  else
82  {
83  assert(gr == OTHERS);
84  winloss[white][black][1][2] += 1; // others
85  }
86 }
87 
88 GameResult getGameResult(const std::string& csa_file,
89  const osl::vector<osl::Move>& moves)
90 {
91  std::ifstream in(csa_file.c_str());
92  if (!in)
93  {
94  std::cerr << "File not found: " << csa_file << "\n";
95  exit(-1);
96  }
97 
98  bool hit = false;
99  std::string line;
100  while (std::getline(in, line))
101  {
102  if (line.find("%TORYO") != std::string::npos)
103  {
104  hit = true;
105  break;
106  }
107  }
108 
109  if (hit)
110  {
111  return (moves.size() % 2 == 1 ? BLACK_WIN : WHITE_WIN);
112  }
113  else
114  {
115  return OTHERS;
116  }
117 }
118 
119 
120 void readFile(const std::string& csa_file,
121  osl::record::CheckDuplicate& duplicates)
122 {
123  const osl::record::csa::CsaFile csa(csa_file);
124  const osl::record::Record& record = csa.getRecord();
125  const osl::vector<osl::Move> moves = record.getMoves();
126 
127  if (duplicates.regist(moves))
128  return;
129 
130  const std::string& black = record.getPlayer(osl::BLACK);
131  const std::string& white = record.getPlayer(osl::WHITE);
132 
133  const unsigned int black_id = setPlayer(black);
134  const unsigned int white_id = setPlayer(white);
135 
136  const GameResult gr = getGameResult(csa_file, moves);
137  increment(black_id, white_id, gr);
138 }
139 
140 void printTotal(std::ostream& out)
141 {
142  out << "=== Total [ #wins / #losses / #others ] ===\n";
143 
144  for (unsigned int player_a = 0; player_a < players.size(); ++player_a)
145  {
146 
147  for (unsigned int player_b = 0; player_b < players.size(); ++player_b)
148  {
149  if (player_a == player_b)
150  continue;
151 
152  out << boost::format("%- 17s ") % getPlayerName(player_a);
153 
154  unsigned int wins = 0, losses = 0, others = 0;
155  wins += winloss[player_a][player_b][0][0]; // a is black
156  wins += winloss[player_a][player_b][1][0]; // a is white
157  losses += winloss[player_a][player_b][0][1]; // a is black
158  losses += winloss[player_a][player_b][1][1];
159  others += winloss[player_a][player_b][0][2]; // a is black
160  others += winloss[player_a][player_b][1][2];
161 
162  out << boost::format("%5d/%5d/%5d ")
163  % wins % losses % others;
164 
165  out << boost::format("%- 17s ") % getPlayerName(player_b);
166  }
167  out << "\n";
168  }
169  out << "\n";
170 }
171 
172 void printResult(std::ostream& out)
173 {
174  out << "=== Left players are BLACK [ #wins / #losses / #others ] ===\n";
175  out << boost::format("%= 17s ") % "";
176  for (unsigned int player_a = 0; player_a < players.size(); ++player_a)
177  {
178  out << boost::format("%= 17s ") % getPlayerName(player_a);
179  }
180  out << "\n";
181 
182  for (unsigned int player_a = 0; player_a < players.size(); ++player_a)
183  {
184  out << boost::format("%= 17s ") % getPlayerName(player_a);
185 
186  for (unsigned int player_b = 0; player_b < players.size(); ++player_b)
187  {
188  if (player_a == player_b)
189  {
190  out << boost::format("%= 17s ") % "-";
191  continue;
192  }
193 
194  out << boost::format("%5d/%5d/%5d ")
195  % winloss[player_a][player_b][0][0]
196  % winloss[player_a][player_b][0][1]
197  % winloss[player_a][player_b][0][2];
198  }
199  out << "\n";
200  }
201  out << "\n";
202 }
203 
204 
205 int main(int argc, char **argv)
206 {
207  std::string kisen_filename;
208 
209  boost::program_options::options_description command_line_options;
210  command_line_options.add_options()
211  ("input-file", boost::program_options::value<std::vector<std::string> >(),
212  "input files in the CSA format")
213  ("help", "Show help message");
214  boost::program_options::variables_map vm;
215  boost::program_options::positional_options_description p;
216  p.add("input-file", -1);
217 
218  try
219  {
221  boost::program_options::command_line_parser(
222  argc, argv).options(command_line_options).positional(p).run(), vm);
223  boost::program_options::notify(vm);
224  if (vm.count("help"))
225  {
226  std::cerr << "Usage: " << argv[0] << " [options] csa-file [...]\n";
227  std::cerr << " " << argv[0] << " [options]\n";
228  std::cout << command_line_options << std::endl;
229  return 0;
230  }
231  }
232  catch (std::exception &e)
233  {
234  std::cerr << "error in parsing options" << std::endl
235  << e.what() << std::endl;
236  std::cerr << "Usage: " << argv[0] << " [options] csa-file [...]\n";
237  std::cerr << " " << argv[0] << " [options]\n";
238  std::cerr << command_line_options << std::endl;
239  return 1;
240  }
241 
242  std::vector<std::string> files;
243  if (vm.count("input-file"))
244  {
245  const std::vector<std::string> temp = vm["input-file"].as<std::vector<std::string> >();
246  files.insert(files.end(), temp.begin(), temp.end());
247  }
248  else
249  {
250  std::string line;
251  while(std::getline(std::cin , line))
252  {
253  boost::algorithm::trim(line);
254  files.push_back(line);
255  }
256  }
257 
259 
260  BOOST_FOREACH(const std::string& file, files)
261  {
262  readFile(file, check_duplicate);
263  }
264 
265  std::locale::global(std::locale(""));
266  printResult(std::cout);
267  printTotal(std::cout);
268  check_duplicate.print(std::cout);
269 
270  return 0;
271 }
272 
273 /* vim: set ts=2 sw=2 ft=cpp : */
274 // ;;; Local Variables:
275 // ;;; mode:c++
276 // ;;; c-basic-offset:2