1 /*
  2 * Copyright (c) 2014 Nonki Takahashi. All rights reserved.
  3 *
  4 * History:
  5 *  0.2 2014-03-28 Bug fixed in Entry and toSGF.
  6 *  0.1 2014-01-28 Created. Ported from GoSimulator03.smallbasic .
  7 */
  8 
  9 /**
 10  * @fileOverview Rec - Game Record Object
 11  * @version 0.2
 12  * @author Nonki Takahashi
 13  */
 14 
 15 /**
 16  * Record Entry
 17  * @example
 18  * var e1 = new Entry(3, 4, BLACK);             // col = 3, row = 4, turn = BLACK
 19  * var e2 = new Entry(PASS, BLACK);             // means pass for BLACK
 20  * var e3 = new Entry(new Move(1, 2), WHITE);   // col = 1, row = 2, turn = WHITE
 21  * @class Represents Game Record Entry
 22  * @this {Entry}
 23  * @property {Number} x column co-ordinate of move (1 origin)
 24  * @property {Number} y row co-ordinate of move (1 origin)
 25  * @property {Number} turn turn BLACK or WHITE
 26  * @since 0.1
 27  */
 28 Entry = function() {
 29     if (arguments.length == 3) {
 30         this.mv = new Move(arguments[0], arguments[1]);
 31         this.turn = arguments[2];
 32     } else if (arguments.length == 2) {
 33         if (arguments[0] == PASS) {
 34             this.mv = new Move(PASS);
 35             this.turn = arguments[1];
 36         } else if (arguments[0] instanceof Object) {
 37             this.mv = arguments[0];
 38             this.turn = arguments[1];
 39         }
 40     }
 41 };
 42 
 43 /**
 44  * Game Record Object
 45  * @example
 46  * var rec1 = new Rec(sgfString);   // src = sgfString
 47  * var rec2 = new Rec(19);          // ro = 19
 48  * @class Represents Game Record Object
 49  * @this {Rec}
 50  * @property {Number} ro number of lines on board
 51  * @property {String[]} players names of players
 52  * @property {Number} numMove number of moves
 53  * @property {Entry[]} record game record
 54  * @property {String} score score string of the game
 55  * @property {Number} ptr pointer for replay
 56  * @since 0.1
 57  */
 58 Rec = function() {
 59     if ( typeof arguments[0] == "number") {
 60         this.ro = arguments[0];
 61         this.players = ["CPU", "CPU"];
 62         this.numMove = 0;
 63         this.score = "0";
 64         this.record = [];
 65         this.ptr = 0;
 66         this.from = BLACK;
 67         this.turn = BLACK;
 68         this.date = new Date();
 69     } else if ( typeof arguments[0] == "string") {
 70         this.players = [];
 71 		this.record = [];
 72         var parser = new SGFParser(arguments[0], this);
 73         parser.Collection();
 74     }
 75 };
 76 
 77 Rec.prototype = {
 78 
 79     /**
 80      * Generate SGF File Name
 81      * @return {String} SGF file name
 82      * @since 0.1
 83      */
 84     genSGFname : function() {
 85         var d = this.date;
 86         var fname = d.getFullYear().toString();
 87         if (d.getMonth().toString().length == 1)
 88             fname += "0";
 89         fname += d.getMonth().toString();
 90         if (d.getDate().toString().length == 1)
 91             fname += "0";
 92         fname += d.getDate().toString();
 93         fname += "_";
 94         if (d.getHours().toString().length == 1)
 95             fname += "0";
 96         fname += d.getHours().toString();
 97         if (d.getMinutes().toString().length == 1)
 98             fname += "0";
 99         fname += d.getMinutes().toString();
100         if (d.getSeconds().toString().length == 1)
101             fname += "0";
102         fname += d.getSeconds().toString();
103         fname += "_";
104         fname += this.ro.toString();
105         fname += this.players[P_BLACK].charAt(0);
106         fname += this.players[P_WHITE].charAt(0);
107         fname += this.numMove;
108         if (this.score == "0")
109             fname += "D";
110         else {
111             fname += this.score.charAt(0);
112             fname += this.score.substr(2);
113         }
114         fname += ".sgf";
115         return fname;
116     },
117 
118     /**
119      * Rewind
120      * @since 0.1
121      */
122     rewind : function() {
123         this.ptr = 0;
124         this.turn = this.from;
125     },
126 
127     /**
128      * Replay - get next move from record
129      * @return {Move} next move
130      * @since 0.1
131      */
132     replay : function() {
133         return this.record[this.ptr++].mv;
134     },
135 
136     /**
137      * End of data
138      * @return {Boolean} true if end of data
139      * @since 0.1
140      */
141     eod : function() {
142         return (this.record.length <= this.ptr);
143     },
144 
145     /**
146      * Add a move to record
147      * @example
148      * move(col, row);
149      * move(PASS);
150      * move(new Move(col, row));
151      * @since 0.1
152      */
153     move : function() {
154         var entry;
155         if (arguments.length == 2)
156             entry = new Entry(arguments[0], arguments[1], this.turn);
157         else
158             entry = new Entry(arguments[0], this.turn);
159         var numRec = this.record.length;
160         this.record[numRec] = entry;
161         this.turn = OPPOSITE - this.turn; 
162     },
163 
164     /**
165      * Convert to SGF
166      * @return {String} SGF string
167      * @since 0.1
168      */
169     toSGF : function() {
170         // game of Go, format version, size of board
171         var buf = "(;GM[1]FF[4]SZ[" + this.ro + "]";
172         // player name
173         buf += "PB[" + this.players[P_BLACK] + "]PW[" + this.players[P_WHITE] + "]";
174         // score
175         buf += "RE[" + this.score + "]\n";
176         buf += "DT[";
177         var d = this.date;
178         buf += d.getFullYear().toString() + "-";
179         if (d.getMonth().toString().length == 1)
180             buf += "0";
181         buf += d.getMonth().toString() + "-";
182         if (d.getDate().toString().length == 1)
183             buf += "0";
184         buf += d.getDate().toString();
185         buf += "]KM[0.0]RU[Chinese]\n";
186         buf += "AP[" + programName + ":" + programVer + "]CA[UTF-8]\n";
187         for (var i = 1; i < this.record.length; i++) {
188             var turn = this.record[i].turn;
189             if (turn == BLACK)
190                 buf += ";B[";
191             else if (turn == WHITE)
192                 buf += ";W[";
193             if (!this.record[i].mv.isPass) {
194                 var col = this.record[i].mv.col;
195                 var row = this.record[i].mv.row;
196                 buf += ALPHA.charAt(col - 1) + ALPHA.charAt(row - 1);
197             }
198             buf += "]";
199             if (i % 10 == 0) {
200                 buf += "\n";
201             }
202         }
203         buf += ")\n";
204         return buf;
205     }
206 };
207