All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
csa-to-kisen.cc
Go to the documentation of this file.
2 #include "osl/hash/hashKey.h"
4 #include "osl/record/ki2.h"
5 #include "osl/record/kisen.h"
6 #include "osl/record/kakinoki.h"
7 #include "osl/record/csaRecord.h"
10 #include "osl/record/kanjiCode.h"
11 #include "osl/misc/filePath.h"
12 //#include "osl/misc/eucToLang.h"
13 
14 #include <boost/algorithm/string/predicate.hpp>
15 #include <boost/algorithm/string/trim.hpp>
16 #include <boost/date_time/gregorian/gregorian.hpp>
17 #include <boost/scoped_ptr.hpp>
18 #include <boost/program_options.hpp>
19 #include <boost/filesystem/convenience.hpp>
20 #include <boost/foreach.hpp>
21 #include <boost/format.hpp>
22 #include <boost/progress.hpp>
23 #include <boost/regex.hpp>
24 #include <deque>
25 #include <exception>
26 #include <iostream>
27 #include <fstream>
28 #include <tr1/unordered_map>
29 
30 std::vector<std::string> good_tournaments;
31 bool accept_tournament(const std::string& name)
32 {
33  BOOST_FOREACH(const std::string& tournament, good_tournaments) {
34  if (tournament.find(name) == 0)
35  return true;
36  else if (tournament.find(name) != tournament.npos)
37  std::cerr << tournament << " != " << name << "\n";
38  }
39  return good_tournaments.empty();
40 }
41 
42 std::string heuristic_find_title(osl::Record& record, osl::Player player)
43 {
44  static const osl::CArray<const char*,25> titles = {{
47  K_MEIJIN, K_PROOK2 K_KING2, K_KING2 K_KURAI, K_KING2 K_SHOU, K_KING2 K_ZA,
51  K_JORYUU,
52  }};
53  std::string name = record.getPlayer(player);
54  std::string title_found = "";
55  BOOST_FOREACH(const char *title, titles) {
56  if (boost::algorithm::iends_with(name, title)) {
57  title_found = title + title_found;
58  name.resize(name.size() - strlen(title));
59  }
60  }
61  record.setPlayer(player, name);
62  return title_found;
63 }
64 
65 void run(osl::record::Record& record,
67  boost::scoped_ptr<osl::record::KisenIpxWriter>& ipx_writer,
68  osl::record::CheckDuplicate& check_duplicates,
69  int default_rating, int min_year, int max_year)
70 {
71  boost::gregorian::date date = record.getDate();
72  if (min_year > 0 && (date.is_special() || date.year() < min_year))
73  return;
74  if (max_year > 0 && (date.is_special() || date.year() > max_year))
75  return;
76  // 重複チェック
77  const osl::vector<osl::Move>& moves = record.getMoves();
78  if (check_duplicates.regist(moves))
79  return;
80 
81  std::string black_title = heuristic_find_title(record, osl::BLACK);
82  std::string white_title = heuristic_find_title(record, osl::WHITE);
83  ks.save(&record);
84  if (ipx_writer)
85  {
86  ipx_writer->save(record, default_rating, default_rating,
87  black_title, white_title);
88  }
89 }
90 static void convert(const std::string &kisen_filename,
91  const std::vector<std::string> &files,
92  bool output_ipx,
93  osl::record::CheckDuplicate& check_duplicates,
94  int default_rating, int min_year, int max_year)
95 {
96  std::ofstream ofs(kisen_filename.c_str());
98 
99  boost::scoped_ptr<osl::record::KisenIpxWriter> ipx_writer;
100  boost::scoped_ptr<std::ofstream> ipx_ofs;
101  if (output_ipx)
102  {
103  const boost::filesystem::path ipx_path =
104  boost::filesystem::change_extension(boost::filesystem::path(kisen_filename), ".ipx");
105  const std::string ipx = osl::misc::file_string(ipx_path);
106  ipx_ofs.reset(new std::ofstream(ipx.c_str()));
107  ipx_writer.reset(new osl::record::KisenIpxWriter(*ipx_ofs));
108  }
109 
110  boost::progress_display progress(files.size());
111  boost::regex date_time_regex("/(20[0-9][0-9]/[0-9][0-9]/[0-9][0-9])/");
112  // boost::regex date_time_regex(".");
113  for (size_t i = 0; i < files.size(); ++i, ++progress)
114  {
115  try
116  {
117  osl::record::Record record;
118  const std::string& filename = files[i];
119  if (boost::algorithm::iends_with(filename, ".kif"))
120  {
121  try
122  {
123  osl::KisenFile kisen(filename);
124  osl::KisenIpxFile ipx(kisen.ipxFileName());
125  for (size_t j=0; j<kisen.size(); ++j) {
126  osl::record::Record record(kisen.getInitialState(), kisen.getMoves(j));
127  record.setPlayer(osl::BLACK, ipx.getPlayer(j, osl::BLACK)
128  + ipx.getTitle(j, osl::BLACK));
129  record.setPlayer(osl::WHITE, ipx.getPlayer(j, osl::WHITE)
130  + ipx.getTitle(j, osl::WHITE));
131  record.setDate(ipx.getStartDate(j));
132  run(record, ks, ipx_writer, check_duplicates,
133  default_rating, min_year, max_year);
134  }
135  if (kisen.size() > 0)
136  continue; // it was actually kisen file, going to next file
137  }
138  catch (...)
139  {
140  }
141  // fall through
142  }
143  if (boost::algorithm::iends_with(filename, ".csa"))
144  {
145  const osl::record::csa::CsaFile csa(filename);
146  record = csa.getRecord();
147  }
148  else if (boost::algorithm::iends_with(filename, ".ki2"))
149  {
150  const osl::Ki2File ki2(filename);
151  record = ki2.getRecord();
152  // std::cerr << osl::misc::eucToLang(record.tounamentName()) << "\n";
153  if (! accept_tournament(record.tounamentName()))
154  continue;
155  }
156  else if (boost::algorithm::iends_with(filename, ".kif"))
157  {
158  const osl::KakinokiFile kif(filename);
159  record = kif.getRecord();
160  }
161  else
162  {
163  std::cerr << "Unknown file type: " << filename << "\n";
164  continue;
165  }
166  if (record.getDate().is_special()) {
167  boost::smatch match;
168  if (boost::regex_search(filename, match, date_time_regex)) {
169  std::string s(match[1].first, match[1].second);
170  std::cerr << "use date in path " << s << "\n";
171  record.setDate(boost::gregorian::from_string(s));
172  }
173  }
174  run(record, ks, ipx_writer, check_duplicates, default_rating, min_year, max_year);
175  }
176  catch(std::exception& e)
177  {
178  std::cerr << "ERROR: reading " << files[i] << "; " <<
179  e.what() << std::endl;
180  continue;
181  }
182  }
183 }
184 
185 int main(int argc, char **argv)
186 {
187  bool output_ipx;
188  std::string kisen_filename, tournament_filename;
189  int default_rating, year, min_year, max_year;
190  boost::program_options::options_description command_line_options;
191  command_line_options.add_options()
192  ("output-ipx",
193  boost::program_options::value<bool>(&output_ipx)->default_value(true),
194  "Whether output IPX file in addition to KIF file")
195  ("tournament-file", boost::program_options::value<std::string>(&tournament_filename)
196  ->default_value(""),
197  "ignore records unless the name of their tournament is listed in the file in EUC-JP")
198  ("year", boost::program_options::value<int>(&year)->default_value(0),
199  "year to select (0 for all)")
200  ("min-year", boost::program_options::value<int>(&min_year)->default_value(0),
201  "min year to select (0 for all)")
202  ("max-year", boost::program_options::value<int>(&max_year)->default_value(0),
203  "max year to select (0 for all)")
204  ("kisen-filename,o",
205  boost::program_options::value<std::string>(&kisen_filename)->
206  default_value("test.kif"),
207  "Output filename of Kisen file")
208  ("input-file", boost::program_options::value< std::vector<std::string> >(),
209  "input files in kisen format")
210  ("default-rating", boost::program_options::value<int>(&default_rating)->
211  default_value(0),
212  "default rating")
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-files | ki2-files \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-files | ki2-files\n";
237  std::cerr << " " << argv[0] << " [options]\n";
238  std::cerr << command_line_options << std::endl;
239  return 1;
240  }
241 
242  if (tournament_filename != "")
243  {
244  std::ifstream is(tournament_filename.c_str());
245  std::string name;
246  while(std::getline(is, name))
247  {
248  boost::algorithm::trim(name);
249  good_tournaments.push_back(name);
250  }
251  if (good_tournaments.empty())
252  throw std::runtime_error("read failed "+tournament_filename);
253  }
254  if (year)
255  min_year = max_year = year;
256 
257  std::vector<std::string> files;
258  if (vm.count("input-file"))
259  {
260  const std::vector<std::string> temp = vm["input-file"].as<std::vector<std::string> >();
261  files.insert(files.end(), temp.begin(), temp.end());
262  }
263  else
264  {
265  std::string line;
266  while(std::getline(std::cin , line))
267  {
268  boost::algorithm::trim(line);
269  files.push_back(line);
270  }
271  }
272 
274  convert(kisen_filename, files, output_ipx, check_duplicate, default_rating,
275  min_year, max_year);
276 
277  std::locale::global(std::locale(""));
278  check_duplicate.print(std::cout);
279 
280  return 0;
281 }
282 // ;;; Local Variables:
283 // ;;; mode:c++
284 // ;;; c-basic-offset:2
285 // ;;; coding:utf-8
286 // ;;; End: