All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
record.cc
Go to the documentation of this file.
1 #include "osl/record/record.h"
3 #include "osl/record/kanjiCode.h"
4 #include "osl/misc/eucToLang.h"
5 #include <boost/algorithm/string/classification.hpp>
6 #include <boost/algorithm/string/split.hpp>
7 #include <boost/algorithm/string/replace.hpp>
8 #include <boost/lexical_cast.hpp>
9 #include <boost/foreach.hpp>
10 #include <stack>
11 #include <iostream>
12 
14 MoveRecord::MoveRecord(const Move& mv, int ni)
15  : move(mv), nodeIndex(ni), time(0)
16 {
17 }
18 
19 namespace osl
20 {
21 namespace record
22 {
24 
26 
27  const Move MoveRecord::getMove() const { return move; }
28 
29  int MoveRecord::getNodeIndex() const { return nodeIndex; }
30 
31  void MoveRecord::setTime(int t){
32  time=t;
33  }
34 
35  void NodeRecord::addMoveRecord(int moveIndex){
36  moves.push_back(moveIndex);
37  }
38 
39 
40  Record::Record(){ init(); }
41  Record::Record(const SimpleState& initial, const vector<Move>& moves)
42  {
43  init();
44  NumEffectState copy(initial);
45  RecordVisitor visitor;
46  visitor.setState(&copy);
47  visitor.setRecord(this);
48  BOOST_FOREACH(Move move, moves) {
49  visitor.addMoveAndAdvance(move);
50  }
51  }
52  void Record::init(){
53  version="";
54  playerNames[0]=playerNames[1]="";
55  nrs.clear();
56  nrs.push_back(NodeRecord());
57  initialState.init(HIRATE);
58  result = UNKNOWN;
59  start_date = boost::gregorian::date();
60  }
61 
63  irs.load(this);
64  }
65  void Record::save(ORecordStream& /*irs*/){
66  // irs.save(this);
67  }
68 
69  void Record::setVersion(const std::string& str){
70  version=str;
71  }
72  void Record::setPlayer(Player player,const std::string& str){
73  playerNames[player]=str;
74  }
75  const std::string& Record::getPlayer(Player player) const{
76  return playerNames[player];
77  }
78  void Record::setInitialState(const SimpleState& state){
79  initialState=state;
80  initialState.initPawnMask();
81  }
82  const NumEffectState Record::getInitialState() const {
83  if (! initialState.isConsistent(true))
84  {
85  const char *msg = "Record: bad initial state";
86  std::cerr << msg << " " << __FILE__ << " " << __LINE__ << "\n";
87  throw CsaIOError(msg);
88  }
89  return NumEffectState(initialState);
90  }
92  nrs.push_back(NodeRecord());
93  return nrs.size()-1;
94  }
95  int Record::addMoveRecord(const MoveRecord& moveRecord){
96  mrs.push_back(moveRecord);
97  return mrs.size()-1;
98  }
100  return &nrs.at(index);
101  }
102  const NodeRecord* Record::nodeOf(int index) const{
103  return &nrs.at(index);
104  }
106  if (static_cast<size_t>(index) >= mrs.size())
107  return NULL;
108  else
109  return &mrs.at(index);
110  }
111  const MoveRecord* Record::moveOf(int index) const {
112  if (static_cast<size_t>(index) >= mrs.size())
113  return NULL;
114  else
115  return &mrs.at(index);
116  }
118  return nrs.at(index);
119  }
120  void Record::setDate(const std::string& date_str)
121  {
122  std::vector<std::string> values;
123  boost::algorithm::split(values, date_str, boost::algorithm::is_any_of("/"));
124  if (values.size() < 3) {
125  std::cerr << "ERROR: Invalid date format found: "
126 #ifndef MINIMAL
127  << misc::eucToLang(date_str)
128 #endif
129  << "\n";
130  return;
131  } else if (values.size() > 3) {
132  std::cerr << "WARNING: Invalid date format found: "
133 #ifndef MINIMAL
134  << misc::eucToLang(date_str)
135 #endif
136  << "\n";
137  // go through
138  }
139  BOOST_FOREACH(std::string& value, values) {
140  static const CArray<const char *,9> kanji = {{
141  K_R1, K_R2, K_R3, K_R4, K_R5, K_R6, K_R7, K_R8, K_R9,
142  }};
143  for (size_t i=0; i<kanji.size(); ++i)
144  boost::algorithm::replace_all(value, kanji[i], std::string(1, char('0'+i)));
145  }
146  int year = 0;
147  int month = 0;
148  int day = 0;
149  try {
150  year = boost::lexical_cast<int>(values[0]);
151  month = boost::lexical_cast<int>(values[1]);
152  if (month == 0) month = 1;
153  if ("??" == values[2]) {
154  std::cerr << "WARNING: Invalid date format found: "
155 #ifndef MINIMAL
156  << misc::eucToLang(values[2])
157 #endif
158  << "\n";
159  // go through
160  day = 1;
161  } else if (values[2].size() > 2) {
162  std::cerr << "WARNING: Invalid date format found: "
163 #ifndef MINIMAL
164  << misc::eucToLang(values[2])
165 #endif
166  << "\n";
167  // go through
168  day = boost::lexical_cast<int>(values[2].substr(0,2));
169  } else {
170  day = boost::lexical_cast<int>(values[2]);
171  }
172  if (day == 0) day = 1;
173  start_date = boost::gregorian::date(year, month, day);
174  assert(!start_date.is_special());
175  } catch (boost::bad_lexical_cast& e) {
176  std::cerr << "Invalid date format found: "
177 #ifndef MINIMAL
178  << misc::eucToLang(date_str)
179 #endif
180  << "\n"
181  << e.what() << std::endl;
182  } catch (boost::gregorian::bad_day_of_month& ebdm) {
183  std::cerr << "Bad day of month: "
184 #ifndef MINIMAL
185  << misc::eucToLang(date_str)
186 #endif
187  << "\n"
188  << ebdm.what() << std::endl;
189  }
190  return;
191  }
192  void Record::setDate(const boost::gregorian::date& date)
193  {
194  start_date = date;
195  }
196  boost::gregorian::date Record::getDate() const
197  {
198  return start_date;
199  }
200 
202  assert(state->isValidMove(move));
203 
204  int newNode=rec->addNodeRecord();
205  int newMove=rec->addMoveRecord(MoveRecord(move,newNode));
206  (*rec)[nodeIndex].addMoveRecord(newMove);
207  nodeIndex=newNode;
208  lastMoveIndex=newMove;
209 
210  assert(state->isConsistent() || ((std::cerr << move <<"\n"<< *state),0));
211  NumEffectState copy(*state);
212  copy.makeMove(move); // XXX: RecordVisitor should have NumEffectState
213  *state = copy;
214  assert(state->isConsistent() || ((std::cerr << move <<"\n"<< *state),0));
215  for(boost::ptr_vector<record::RecordVisitorObserver>::iterator each = observers.begin(); each != observers.end(); ++each){
216  each->update(this);
217  }
218  }
219 
220 
221  std::ostream& operator<<(std::ostream& os,const MoveRecord & mr){
222  return os << "MoveRecord(" << // mr.getMove() << ',' <<
223  mr.getNodeIndex() << ')';
224  }
225 #ifndef MINIMAL
226  std::ostream& operator<<(std::ostream& os,Record & r){
227  os << "Record(";
228  os << "version=" << r.getVersion()
229  << ",BLACK=" << r.getPlayer(BLACK)
230  << ",WHITE=" << r.getPlayer(WHITE);
231  os << ",initial=" << std:: endl << r.getInitialState() << std::endl;
232  SimpleState initial_state=r.getInitialState();
233  NumEffectState state(initial_state);
234  RecordVisitor visitor;
235  visitor.setState(&state);
236  visitor.setRecord(&r);
237  NodeRecord* node=visitor.getNode();
238  while(node->size()>0){
239  int moveIndex=node->at(0);
240  MoveRecord* mr=r.moveOf(moveIndex);
241  Move move=mr->getMove();
242  os << move << "," << mr->getTime() << "," << mr->getComment() << std::endl;
243  node=r.nodeOf(mr->getNodeIndex());
244  state.makeMove(move);
245  assert(state.isConsistent());
246  }
247  os << state;
248  os << initial_state;
249  return os << ')';
250  }
251 #endif
252 
253  const vector<Move> Record::getMoves() const {
254  vector<Move> moves;
255  vector<int> dummy_time;
256  getMoves(moves, dummy_time);
257  return moves;
258  }
259 
260  int readInt(std::istream& is)
261  {
262  int ret=0;
263  CArray<char,4> cs;
264  is.read(&cs[0],4);
265  for (int i=0;i<4;i++) {
266  ret = (ret<<8)|(cs[i]&255);
267  }
268  return ret;
269  }
270 
271  void
272  writeInt(std::ostream& os, int n)
273  {
274  CArray<char,4> buf;
275  for (int i = 0; i < 4; i++)
276  {
277  buf[i] = (n >> (8 * (4 - i - 1))) & 255;
278  }
279  os.write(&buf[0], 4);
280  }
281 
282 } // namespace record
283 } // namespace osl
284 
285 void osl::record::
286 Record::getMoves(vector<Move>& moves, vector<int>& times,
287  vector<std::string>& comments,
288  vector<SearchInfo>& info) const
289 {
290  const NodeRecord* node=nodeOf(0);
291  while(node->size()>0){
292  const int moveIndex=node->at(0);
293  const MoveRecord* mr=moveOf(moveIndex);
294  const Move move=mr->getMove();
295  moves.push_back(move);
296  times.push_back(mr->getTime());
297  comments.push_back(mr->getComment());
298  info.push_back(mr->info);
299 
300  node=nodeOf(mr->getNodeIndex());
301  }
302 }
303 
304 void osl::record::
305 Record::getMoves(vector<Move>& moves, vector<int>& times) const
306 {
307  vector<std::string> dummy_comments;
308  vector<SearchInfo> dummy_info;
309  getMoves(moves, times, dummy_comments, dummy_info);
310 }
311 
314 {
315 }
316 
317 // ;;; Local Variables:
318 // ;;; mode:c++
319 // ;;; c-basic-offset:2
320 // ;;; End: