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