record.cc Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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"
2 #include "osl/record/csaIOError.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
13 osl::record::
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 {
23 IRecordStream::~IRecordStream(){}
24
25 ORecordStream::~ORecordStream(){}
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
62 void Record::load(IRecordStream& irs){
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 }
91 int Record::addNodeRecord(){
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 }
99 NodeRecord* Record::nodeOf(int index){
100 return &nrs.at(index);
101 }
102 const NodeRecord* Record::nodeOf(int index) const{
103 return &nrs.at(index);
104 }
105 MoveRecord* Record::moveOf(int index){
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 }
117 NodeRecord& Record::operator[](int index){
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
201 void RecordVisitor::addMoveAndAdvance(Move move){
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
312 osl::record::
313 RecordVisitor::~RecordVisitor()
314 {
315 }
316
317 // ;;; Local Variables:
318 // ;;; mode:c++
319 // ;;; c-basic-offset:2
320 // ;;; End: