00001 #include "osl/record/record.h"
00002 #include "osl/record/csaIOError.h"
00003 #include "osl/record/kanjiCode.h"
00004 #include "osl/misc/iconvConvert.h"
00005 #include <boost/algorithm/string/classification.hpp>
00006 #include <boost/algorithm/string/split.hpp>
00007 #include <boost/algorithm/string/replace.hpp>
00008 #include <boost/lexical_cast.hpp>
00009 #include <boost/foreach.hpp>
00010 #include <stack>
00011 #include <iostream>
00012
00013 osl::record::
00014 MoveRecord::MoveRecord(const Move& mv, int ni)
00015 : move(mv), nodeIndex(ni), time(0)
00016 {
00017 }
00018
00019 namespace osl
00020 {
00021 namespace record
00022 {
00023 IRecordStream::~IRecordStream(){}
00024
00025 ORecordStream::~ORecordStream(){}
00026
00027 const Move MoveRecord::getMove() const { return move; }
00028
00029 int MoveRecord::getNodeIndex() const { return nodeIndex; }
00030
00031 void MoveRecord::setTime(int t){
00032 time=t;
00033 }
00034
00035 void NodeRecord::addMoveRecord(int moveIndex){
00036 moves.push_back(moveIndex);
00037 }
00038
00039
00040 Record::Record(){ init(); }
00041 Record::Record(const SimpleState& initial, const vector<Move>& moves)
00042 {
00043 init();
00044 NumEffectState copy(initial);
00045 RecordVisitor visitor;
00046 visitor.setState(©);
00047 visitor.setRecord(this);
00048 BOOST_FOREACH(Move move, moves) {
00049 visitor.addMoveAndAdvance(move);
00050 }
00051 }
00052 void Record::init(){
00053 version="";
00054 playerNames[0]=playerNames[1]="";
00055 nrs.clear();
00056 nrs.push_back(NodeRecord());
00057 initialState.init(HIRATE);
00058 result = UNKNOWN;
00059 start_date = boost::gregorian::date();
00060 }
00061
00062 void Record::load(IRecordStream& irs){
00063 irs.load(this);
00064 }
00065 void Record::save(ORecordStream& ){
00066
00067 }
00068
00069 void Record::setVersion(const std::string& str){
00070 version=str;
00071 }
00072 void Record::setPlayer(Player player,const std::string& str){
00073 playerNames[player]=str;
00074 }
00075 const std::string& Record::getPlayer(Player player) const{
00076 return playerNames[player];
00077 }
00078 void Record::setInitialState(const SimpleState& state){
00079 initialState=state;
00080 initialState.initPawnMask();
00081 }
00082 const NumEffectState Record::getInitialState() const {
00083 if (! initialState.isConsistent(true))
00084 {
00085 const char *msg = "Record: bad initial state";
00086 std::cerr << msg << " " << __FILE__ << " " << __LINE__ << "\n";
00087 throw CsaIOError(msg);
00088 }
00089 return NumEffectState(initialState);
00090 }
00091 int Record::addNodeRecord(){
00092 nrs.push_back(NodeRecord());
00093 return nrs.size()-1;
00094 }
00095 int Record::addMoveRecord(const MoveRecord& moveRecord){
00096 mrs.push_back(moveRecord);
00097 return mrs.size()-1;
00098 }
00099 NodeRecord* Record::nodeOf(int index){
00100 return &nrs.at(index);
00101 }
00102 const NodeRecord* Record::nodeOf(int index) const{
00103 return &nrs.at(index);
00104 }
00105 MoveRecord* Record::moveOf(int index){
00106 if (static_cast<size_t>(index) >= mrs.size())
00107 return NULL;
00108 else
00109 return &mrs.at(index);
00110 }
00111 const MoveRecord* Record::moveOf(int index) const {
00112 if (static_cast<size_t>(index) >= mrs.size())
00113 return NULL;
00114 else
00115 return &mrs.at(index);
00116 }
00117 NodeRecord& Record::operator[](int index){
00118 return nrs.at(index);
00119 }
00120 void Record::setDate(const std::string& date_str)
00121 {
00122 std::vector<std::string> values;
00123 boost::algorithm::split(values, date_str, boost::algorithm::is_any_of("/"));
00124 if (values.size() < 3) {
00125 std::cerr << "ERROR: Invalid date format found: "
00126 #ifndef MINIMAL
00127 << IconvConvert::eucToLang(date_str)
00128 #endif
00129 << "\n";
00130 return;
00131 } else if (values.size() > 3) {
00132 std::cerr << "WARNING: Invalid date format found: "
00133 #ifndef MINIMAL
00134 << IconvConvert::eucToLang(date_str)
00135 #endif
00136 << "\n";
00137
00138 }
00139 BOOST_FOREACH(std::string& value, values) {
00140 static const CArray<const char *,9> kanji = {{
00141 K_R1, K_R2, K_R3, K_R4, K_R5, K_R6, K_R7, K_R8, K_R9,
00142 }};
00143 for (size_t i=0; i<kanji.size(); ++i)
00144 boost::algorithm::replace_all(value, kanji[i], std::string(1, char('0'+i)));
00145 }
00146 int year = 0;
00147 int month = 0;
00148 int day = 0;
00149 try {
00150 year = boost::lexical_cast<int>(values[0]);
00151 month = boost::lexical_cast<int>(values[1]);
00152 if (month == 0) month = 1;
00153 if ("??" == values[2]) {
00154 std::cerr << "WARNING: Invalid date format found: "
00155 #ifndef MINIMAL
00156 << IconvConvert::eucToLang(values[2])
00157 #endif
00158 << "\n";
00159
00160 day = 1;
00161 } else if (values[2].size() > 2) {
00162 std::cerr << "WARNING: Invalid date format found: "
00163 #ifndef MINIMAL
00164 << IconvConvert::eucToLang(values[2])
00165 #endif
00166 << "\n";
00167
00168 day = boost::lexical_cast<int>(values[2].substr(0,2));
00169 } else {
00170 day = boost::lexical_cast<int>(values[2]);
00171 }
00172 if (day == 0) day = 1;
00173 start_date = boost::gregorian::date(year, month, day);
00174 assert(!start_date.is_special());
00175 } catch (boost::bad_lexical_cast& e) {
00176 std::cerr << "Invalid date format found: "
00177 #ifndef MINIMAL
00178 << IconvConvert::eucToLang(date_str)
00179 #endif
00180 << "\n"
00181 << e.what() << std::endl;
00182 } catch (boost::gregorian::bad_day_of_month& ebdm) {
00183 std::cerr << "Bad day of month: "
00184 #ifndef MINIMAL
00185 << IconvConvert::eucToLang(date_str)
00186 #endif
00187 << "\n"
00188 << ebdm.what() << std::endl;
00189 }
00190 return;
00191 }
00192 void Record::setDate(const boost::gregorian::date& date)
00193 {
00194 start_date = date;
00195 }
00196 boost::gregorian::date Record::getDate() const
00197 {
00198 return start_date;
00199 }
00200
00201 void RecordVisitor::addMoveAndAdvance(Move move){
00202 assert(state->isValidMove(move));
00203
00204 int newNode=rec->addNodeRecord();
00205 int newMove=rec->addMoveRecord(MoveRecord(move,newNode));
00206 (*rec)[nodeIndex].addMoveRecord(newMove);
00207 nodeIndex=newNode;
00208 lastMoveIndex=newMove;
00209
00210 assert(state->isConsistent() || ((std::cerr << move <<"\n"<< *state),0));
00211 NumEffectState copy(*state);
00212 copy.makeMove(move);
00213 *state = copy;
00214 assert(state->isConsistent() || ((std::cerr << move <<"\n"<< *state),0));
00215 for(boost::ptr_vector<record::RecordVisitorObserver>::iterator each = observers.begin(); each != observers.end(); ++each){
00216 each->update(this);
00217 }
00218 }
00219
00220
00221 std::ostream& operator<<(std::ostream& os,const MoveRecord & mr){
00222 return os << "MoveRecord(" <<
00223 mr.getNodeIndex() << ')';
00224 }
00225 #ifndef MINIMAL
00226 std::ostream& operator<<(std::ostream& os,Record & r){
00227 os << "Record(";
00228 os << "version=" << r.getVersion()
00229 << ",BLACK=" << r.getPlayer(BLACK)
00230 << ",WHITE=" << r.getPlayer(WHITE);
00231 os << ",initial=" << std:: endl << r.getInitialState() << std::endl;
00232 SimpleState initial_state=r.getInitialState();
00233 NumEffectState state(initial_state);
00234 RecordVisitor visitor;
00235 visitor.setState(&state);
00236 visitor.setRecord(&r);
00237 NodeRecord* node=visitor.getNode();
00238 while(node->size()>0){
00239 int moveIndex=node->at(0);
00240 MoveRecord* mr=r.moveOf(moveIndex);
00241 Move move=mr->getMove();
00242 os << move << "," << mr->getTime() << "," << mr->getComment() << std::endl;
00243 node=r.nodeOf(mr->getNodeIndex());
00244 state.makeMove(move);
00245 assert(state.isConsistent());
00246 }
00247 os << state;
00248 os << initial_state;
00249 return os << ')';
00250 }
00251 #endif
00252
00253 const vector<Move> Record::getMoves() const {
00254 vector<Move> moves;
00255 vector<int> dummy_time;
00256 getMoves(moves, dummy_time);
00257 return moves;
00258 }
00259
00260 int readInt(std::istream& is)
00261 {
00262 int ret=0;
00263 CArray<char,4> cs;
00264 is.read(&cs[0],4);
00265 for (int i=0;i<4;i++) {
00266 ret = (ret<<8)|(cs[i]&255);
00267 }
00268 return ret;
00269 }
00270
00271 void
00272 writeInt(std::ostream& os, int n)
00273 {
00274 CArray<char,4> buf;
00275 for (int i = 0; i < 4; i++)
00276 {
00277 buf[i] = (n >> (8 * (4 - i - 1))) & 255;
00278 }
00279 os.write(&buf[0], 4);
00280 }
00281
00282 }
00283 }
00284
00285 void osl::record::
00286 Record::getMoves(vector<Move>& moves, vector<int>& times,
00287 vector<std::string>& comments,
00288 vector<SearchInfo>& info) const
00289 {
00290 const NodeRecord* node=nodeOf(0);
00291 while(node->size()>0){
00292 const int moveIndex=node->at(0);
00293 const MoveRecord* mr=moveOf(moveIndex);
00294 const Move move=mr->getMove();
00295 moves.push_back(move);
00296 times.push_back(mr->getTime());
00297 comments.push_back(mr->getComment());
00298 info.push_back(mr->info);
00299
00300 node=nodeOf(mr->getNodeIndex());
00301 }
00302 }
00303
00304 void osl::record::
00305 Record::getMoves(vector<Move>& moves, vector<int>& times) const
00306 {
00307 vector<std::string> dummy_comments;
00308 vector<SearchInfo> dummy_info;
00309 getMoves(moves, times, dummy_comments, dummy_info);
00310 }
00311
00312 osl::record::
00313 RecordVisitor::~RecordVisitor()
00314 {
00315 }
00316
00317
00318
00319
00320