record.cc
Go to the documentation of this file.
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(&copy);
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& /*irs*/){
00066     // irs.save(this);
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       // go through
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         // go through
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         // go through
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);        // XXX: RecordVisitor should have NumEffectState
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(" << // mr.getMove() << ',' <<
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 } // namespace record
00283 } // namespace osl
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 // ;;; Local Variables:
00318 // ;;; mode:c++
00319 // ;;; c-basic-offset:2
00320 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines