All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
win-rate-openingbook-weight-level.cc
Go to the documentation of this file.
2 #include "osl/oslConfig.h"
4 #include "osl/record/csaRecord.h"
7 
8 #include <boost/algorithm/string/trim.hpp>
9 #include <boost/foreach.hpp>
10 #include <boost/format.hpp>
11 #include <boost/multi_array.hpp>
12 #include <boost/program_options.hpp>
13 #include <fstream>
14 #include <iostream>
15 #include <vector>
16 
17 using namespace osl;
18 
20 {
21  BLACK_WIN = 0,
24 };
25 
26 struct WinLoss
27 {
28  unsigned int wins;
29  unsigned int losses;
30 
32  : wins(0), losses(0)
33  {}
34 
35  double getRate() const
36  {
37  if (isEmpty())
38  return 0.0;
39 
40  return 1.0*wins/(wins+losses);
41  }
42 
43  bool isEmpty() const
44  {
45  return (wins + losses) == 0;
46  }
47 };
48 
49 std::ostream& operator<<(std::ostream& out, const WinLoss& wl)
50 {
51  out << boost::format("%5.3f (#wins=%6d, #losses=%6d)")
52  % wl.getRate() % wl.wins % wl.losses;
53  return out;
54 }
55 
56 struct Result
57 {
58  enum {MAX_LEVEL = 99,
59  MAX_DEPTH = 999};
61  typedef boost::multi_array<unsigned int, 3> array_t;
63  unsigned int top_level;
64  unsigned int top_depth;
65 
67  : winloss(boost::extents[MAX_DEPTH][MAX_LEVEL][2]),
68  top_level(0), top_depth(0)
69  {}
70 
71  void add(const unsigned int depth,
72  const unsigned int level,
73  const bool win)
74  {
75  assert(depth < MAX_DEPTH);
76  assert(level < MAX_LEVEL);
77  if (win)
78  winloss[depth][level][0] += 1;
79  else
80  winloss[depth][level][1] += 1;
81 
82  top_level = std::max(top_level, level);
83  top_depth = std::max(top_depth, depth);
84  }
85 
86  bool printAtDepth(std::ostream& out, const unsigned int depth) const;
87  void printByLevel(std::ostream& out) const;
88  void printByDepth(std::ostream& out) const;
89  void showLevels(std::ostream& out,
90  std::vector<WinLoss>& vector) const;
91 };
92 
93 void Result::showLevels(std::ostream& out,
94  std::vector<WinLoss>& vector) const
95 {
96  // GC
97  std::vector<WinLoss>::reverse_iterator empty = vector.rbegin();
98  for (/*none*/; empty != vector.rend(); ++empty) {
99  if (!empty->isEmpty())
100  break;
101  }
102  vector.erase(empty.base(), vector.end());
103 
104  unsigned int level = 1;
105  BOOST_FOREACH(const WinLoss& wl, vector) {
106  out << boost::format("%2d: %s\n") % level++ % wl;
107  }
108 }
109 
110 bool Result::printAtDepth(std::ostream& out,
111  const unsigned int depth) const
112 {
113  std::vector<WinLoss> vector;
114  for(unsigned int level=0; level < MAX_LEVEL; ++level) {
115  WinLoss wl;
116  wl.wins += winloss[depth][level][0];
117  wl.losses += winloss[depth][level][1];
118  vector.push_back(wl);
119  }
120 
121  showLevels(out, vector);
122  return vector.empty();
123 }
124 
125 void Result::printByDepth(std::ostream& out) const
126 {
127  for (unsigned int depth=1; depth < top_depth; ++depth) {
128  out << boost::format("\n>> Depth %2d\n") % depth;
129  printAtDepth(out, depth);
130  }
131 }
132 
133 void Result::printByLevel(std::ostream& out) const
134 {
135  std::vector<WinLoss> vector;
136  for(unsigned int level=0; level < MAX_LEVEL; ++level) {
137  WinLoss wl;
138  for (unsigned int depth=0; depth < MAX_DEPTH; ++depth) {
139  wl.wins += winloss[depth][level][0];
140  wl.losses += winloss[depth][level][1];
141  }
142  vector.push_back(wl);
143  }
144 
145  showLevels(out, vector);
146 }
147 
148 // ==============================================
149 // Global variables
150 // ==============================================
151 static Result result;
153 
154 
155 // ==============================================
156 // Functions
157 // ==============================================
158 
159 GameResult getGameResult(const std::string& csa_file,
160  const vector<Move>& moves)
161 {
162  std::ifstream in(csa_file.c_str());
163  if (!in)
164  {
165  std::cerr << "File not found: " << csa_file << "\n";
166  exit(-1);
167  }
168 
169  bool hit = false;
170  std::string line;
171  while (std::getline(in, line))
172  {
173  if (line.find("%TORYO") != std::string::npos)
174  {
175  hit = true;
176  break;
177  }
178  }
179 
180  if (hit)
181  {
182  return (moves.size() % 2 == 1 ? BLACK_WIN : WHITE_WIN);
183  }
184  else
185  {
186  return OTHERS;
187  }
188 }
189 
190 
191 void increment(const vector<Move>& moves,
192  const Player player,
193  const bool win)
194 {
195  int stateIndex = book.getStartState();
196  Player turn = BLACK;
197  unsigned int depth = 1;
198 
199  BOOST_FOREACH(const Move& move, moves) {
201  book.getMoves(stateIndex, (player == turn ? false : true));
202  std::sort(wmoves.begin(), wmoves.end(),
204 
205  /*
206  * It ends if a move that is not included in the book is played.
207  */
208  osl::record::opening::WeightedBook::WMoveContainer::iterator found =
209  wmoves.begin();
210  for (/*none*/; found != wmoves.end(); ++found) {
211  if (found->getMove() == move)
212  break;
213  }
214  if (found == wmoves.end())
215  return; // finish this record
216 
217  /*
218  * Increment
219  */
220  if (turn == player) {
221  const unsigned int level = std::distance(wmoves.begin(), found); // 1, 2, ...
222  result.add(depth, level, win);
223  }
224 
225  /*
226  * Prepare for the next iteration
227  */
228  turn = alt(turn);
229  depth += 1;
230  stateIndex = found->getStateIndex();
231  } // each move
232 }
233 
234 
235 void readFile(const std::string& player_name,
236  const std::string& csa_file,
237  osl::record::CheckDuplicate& duplicates)
238 {
239  const osl::record::csa::CsaFile csa(csa_file);
240  const osl::record::Record& record = csa.getRecord();
241  const vector<Move> moves = record.getMoves();
242 
243  const GameResult gr = getGameResult(csa_file, moves);
244  if (gr == OTHERS)
245  return;
246 
247  if (duplicates.regist(moves))
248  return;
249 
250  const std::string& black = record.getPlayer(BLACK);
251  const std::string& white = record.getPlayer(WHITE);
252 
253  Player player = BLACK;
254  bool win = true;
255  if (black.find(player_name) != std::string::npos) {
256  player = BLACK;
257  win = (gr == BLACK_WIN);
258  }
259  else if (white.find(player_name) != std::string::npos) {
260  player = WHITE;
261  win = (gr == WHITE_WIN);
262  }
263  else {
264  std::cerr << "Ignore this play: " << csa_file << "\n";
265  return;
266  }
267 
268  increment(moves, player, win);
269 }
270 
271 
272 int main(int argc, char **argv)
273 {
274  std::string player_name;
275 
276  boost::program_options::options_description command_line_options;
277  command_line_options.add_options()
278  ("input-file", boost::program_options::value<std::vector<std::string> >(),
279  "input files in the CSA format")
280  ("player", boost::program_options::value<std::string>(&player_name)->default_value("gps"),
281  "input files in the CSA format")
282  ("help", "Show help message");
283  boost::program_options::variables_map vm;
284  boost::program_options::positional_options_description p;
285  p.add("input-file", -1);
286 
287  try
288  {
290  boost::program_options::command_line_parser(
291  argc, argv).options(command_line_options).positional(p).run(), vm);
292  boost::program_options::notify(vm);
293  if (vm.count("help"))
294  {
295  std::cerr << "Usage: " << argv[0] << " [options] csa-file [...]\n";
296  std::cerr << " " << argv[0] << " [options]\n";
297  std::cout << command_line_options << std::endl;
298  return 0;
299  }
300  }
301  catch (std::exception &e)
302  {
303  std::cerr << "error in parsing options" << std::endl
304  << e.what() << std::endl;
305  std::cerr << "Usage: " << argv[0] << " [options] csa-file [...]\n";
306  std::cerr << " " << argv[0] << " [options]\n";
307  std::cerr << command_line_options << std::endl;
308  return 1;
309  }
310 
311  std::vector<std::string> files;
312  if (vm.count("input-file"))
313  {
314  const std::vector<std::string> temp = vm["input-file"].as<std::vector<std::string> >();
315  files.insert(files.end(), temp.begin(), temp.end());
316  }
317  else
318  {
319  std::string line;
320  while(std::getline(std::cin , line))
321  {
322  boost::algorithm::trim(line);
323  files.push_back(line);
324  }
325  }
326 
328 
329  BOOST_FOREACH(const std::string& file, files)
330  {
331  readFile(player_name, file, check_duplicate);
332  }
333 
334  result.printByLevel(std::cout);
335  result.printByDepth(std::cout);
336 
337  std::locale::global(std::locale(""));
338  check_duplicate.print(std::cout);
339 
340  return 0;
341 }
342 
343 /* vim: set ts=2 sw=2 ft=cpp : */
344 // ;;; Local Variables:
345 // ;;; mode:c++
346 // ;;; c-basic-offset:2