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& ){
00052
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
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
00127 day = 1;
00128 } else if (values[2].size() > 2) {
00129 std::cerr << "WARNING: Invalid date format found: " << values[2] << "\n";
00130
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);
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(" <<
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 }
00238 }
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
00273
00274
00275