1/*
2 *  pgn4web javascript chessboard
3 *  copyright (C) 2009-2013 Paolo Casaschi
4 *  see README file and http://pgn4web.casaschi.net
5 *  for credits, license and more details
6 *
7 *  Huffman encoding/decoding derived from code at http://rumkin.com/tools/compression/compress_huff.php
8 */
9
10// version 1 of PGN encoding:
11//   encodedPGN = nnn$xxx0
12//   nnn = number representing bytes length of the decoded message
13//   $ = dollar char (delimiter for length info)
14//   xxx = encoded text (using LetterCodes below)
15//   0 = zero char (version marker)
16
17"use strict";
18
19var encodingCharSet_dec;
20var encodingCharSet_enc;
21var encodingCharSet = encodingCharSet_enc = "$0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
22var encodingVersion_dec;
23var encodingVersion_enc;
24var encodingVersion = encodingVersion_enc = 1;
25var errorString;
26
27if (((encodingCharSet_dec != undefined) && (encodingCharSet_enc != encodingCharSet_dec)) ||
28    ((encodingVersion_dec != undefined) && (encodingVersion_enc != encodingVersion_dec))) {
29  errorString = "error: PGN encoding/decoding version/charset mismatch";
30  if (typeof myAlert == "function") { myAlert(errorString); }
31  else { alert(errorString); }
32}
33
34function EncodePGN(ov) {
35
36  function BitsToBytes(i) {
37    var o = 0;
38    if (i.charAt(0) == '1') { o += 32; }
39    if (i.charAt(1) == '1') { o += 16; }
40    if (i.charAt(2) == '1') { o +=  8; }
41    if (i.charAt(3) == '1') { o +=  4; }
42    if (i.charAt(4) == '1') { o +=  2; }
43    if (i.charAt(5) == '1') { o +=  1; }
44    return encodingCharSet.charAt(o);
45  }
46
47  var LetterCodes = new Array(256);
48  LetterCodes[0]   = '00111111111111110';
49  LetterCodes[1]   = '0101101';
50  LetterCodes[2]   = '00111111111111111';
51  LetterCodes[3]   = '00111111111111100';
52  LetterCodes[4]   = '00111111111111101';
53  LetterCodes[5]   = '000011111111111010';
54  LetterCodes[6]   = '000011111111111011';
55  LetterCodes[7]   = '000011111111111000';
56  LetterCodes[8]   = '000011111111111001';
57  LetterCodes[9]   = '000011111111111110';
58  LetterCodes[10]  = '0101100';
59  LetterCodes[11]  = '000011111111111111';
60  LetterCodes[12]  = '000011111111111100';
61  LetterCodes[13]  = '0011100';
62  LetterCodes[14]  = '000011111111111101';
63  LetterCodes[15]  = '000011111111110010';
64  LetterCodes[16]  = '000011111111110011';
65  LetterCodes[17]  = '000011111111110000';
66  LetterCodes[18]  = '000011111111110001';
67  LetterCodes[19]  = '000011111111110110';
68  LetterCodes[20]  = '000011111111110111';
69  LetterCodes[21]  = '000011111111110100';
70  LetterCodes[22]  = '000011111111110101';
71  LetterCodes[23]  = '1111111111110101010';
72  LetterCodes[24]  = '1111111111110101011';
73  LetterCodes[25]  = '1111111111110101000';
74  LetterCodes[26]  = '1111111111110101001';
75  LetterCodes[27]  = '1111111111110101110';
76  LetterCodes[28]  = '1111111111110101111';
77  LetterCodes[29]  = '1111111111110101100';
78  LetterCodes[30]  = '1111111111110101101';
79  LetterCodes[31]  = '1111111111110100010';
80  LetterCodes[32]  = '1000';
81  LetterCodes[33]  = '101111111110';
82  LetterCodes[34]  = '00010';
83  LetterCodes[35]  = '11111111110';
84  LetterCodes[36]  = '0011111111110';
85  LetterCodes[37]  = '1011111111110';
86  LetterCodes[38]  = '00001111111110';
87  LetterCodes[39]  = '00111111110';
88  LetterCodes[40]  = '0011101';
89  LetterCodes[41]  = '111111110';
90  LetterCodes[42]  = '11001111111110';
91  LetterCodes[43]  = '1111110';
92  LetterCodes[44]  = '000011110';
93  LetterCodes[45]  = '0011110';
94  LetterCodes[46]  = '00000';
95  LetterCodes[47]  = '0110110';
96  LetterCodes[48]  = '010100';
97  LetterCodes[49]  = '00110';
98  LetterCodes[50]  = '01000';
99  LetterCodes[51]  = '01100';
100  LetterCodes[52]  = '11000';
101  LetterCodes[53]  = '11010';
102  LetterCodes[54]  = '11100';
103  LetterCodes[55]  = '001010';
104  LetterCodes[56]  = '011100';
105  LetterCodes[57]  = '0001110';
106  LetterCodes[58]  = '001111111110';
107  LetterCodes[59]  = '1111111111100';
108  LetterCodes[60]  = '10111111110';
109  LetterCodes[61]  = '1100110100';
110  LetterCodes[62]  = '000011111110';
111  LetterCodes[63]  = '00011110';
112  LetterCodes[64]  = '1100111111110';
113  LetterCodes[65]  = '110011100';
114  LetterCodes[66]  = '000010';
115  LetterCodes[67]  = '10111110';
116  LetterCodes[68]  = '00111110';
117  LetterCodes[69]  = '0010110';
118  LetterCodes[70]  = '110011101';
119  LetterCodes[71]  = '110011110';
120  LetterCodes[72]  = '1100110101';
121  LetterCodes[73]  = '0010111110';
122  LetterCodes[74]  = '11001111110';
123  LetterCodes[75]  = '101110';
124  LetterCodes[76]  = '1100111110';
125  LetterCodes[77]  = '101111110';
126  LetterCodes[78]  = '000110';
127  LetterCodes[79]  = '0101110';
128  LetterCodes[80]  = '1011110';
129  LetterCodes[81]  = '011101';
130  LetterCodes[82]  = '11101';
131  LetterCodes[83]  = '11001100';
132  LetterCodes[84]  = '001111110';
133  LetterCodes[85]  = '0000111110';
134  LetterCodes[86]  = '1111111110';
135  LetterCodes[87]  = '11111110';
136  LetterCodes[88]  = '110011111110';
137  LetterCodes[89]  = '0000111111110';
138  LetterCodes[90]  = '1011111110';
139  LetterCodes[91]  = '10010';
140  LetterCodes[92]  = '00111111111110';
141  LetterCodes[93]  = '10011';
142  LetterCodes[94]  = '11001111111111';
143  LetterCodes[95]  = '11111111111010';
144  LetterCodes[96]  = '10111111111110';
145  LetterCodes[97]  = '11110';
146  LetterCodes[98]  = '011010';
147  LetterCodes[99]  = '10100';
148  LetterCodes[100] = '11011';
149  LetterCodes[101] = '00100';
150  LetterCodes[102] = '010010';
151  LetterCodes[103] = '010011';
152  LetterCodes[104] = '011110';
153  LetterCodes[105] = '0000110';
154  LetterCodes[106] = '00001111110';
155  LetterCodes[107] = '00001110';
156  LetterCodes[108] = '110010';
157  LetterCodes[109] = '000111110';
158  LetterCodes[110] = '010101';
159  LetterCodes[111] = '111110';
160  LetterCodes[112] = '0110111';
161  LetterCodes[113] = '1100110110';
162  LetterCodes[114] = '0111110';
163  LetterCodes[115] = '0111111';
164  LetterCodes[116] = '10110';
165  LetterCodes[117] = '0101111';
166  LetterCodes[118] = '00101110';
167  LetterCodes[119] = '000111111';
168  LetterCodes[120] = '10101';
169  LetterCodes[121] = '001011110';
170  LetterCodes[122] = '1100110111';
171  LetterCodes[123] = '0010111111';
172  LetterCodes[124] = '001111111111110';
173  LetterCodes[125] = '0011111110';
174  LetterCodes[126] = '111111111110110';
175  LetterCodes[127] = '1111111111110100011';
176  LetterCodes[128] = '1111111111110100000';
177  LetterCodes[129] = '1111111111110100001';
178  LetterCodes[130] = '1111111111110100110';
179  LetterCodes[131] = '1111111111110100111';
180  LetterCodes[132] = '1111111111110100100';
181  LetterCodes[133] = '1111111111110100101';
182  LetterCodes[134] = '1111111111110111010';
183  LetterCodes[135] = '1111111111110111011';
184  LetterCodes[136] = '1111111111110111000';
185  LetterCodes[137] = '1111111111110111001';
186  LetterCodes[138] = '1111111111110111110';
187  LetterCodes[139] = '1111111111110111111';
188  LetterCodes[140] = '1111111111110111100';
189  LetterCodes[141] = '1111111111110111101';
190  LetterCodes[142] = '1111111111110110010';
191  LetterCodes[143] = '1111111111110110011';
192  LetterCodes[144] = '1111111111110110000';
193  LetterCodes[145] = '1111111111110110001';
194  LetterCodes[146] = '1111111111110110110';
195  LetterCodes[147] = '1111111111110110111';
196  LetterCodes[148] = '1111111111110110100';
197  LetterCodes[149] = '1111111111110110101';
198  LetterCodes[150] = '1111111111110001010';
199  LetterCodes[151] = '1111111111110001011';
200  LetterCodes[152] = '1111111111110001000';
201  LetterCodes[153] = '1111111111110001001';
202  LetterCodes[154] = '1111111111110001110';
203  LetterCodes[155] = '1111111111110001111';
204  LetterCodes[156] = '1111111111110001100';
205  LetterCodes[157] = '1111111111110001101';
206  LetterCodes[158] = '1111111111110000010';
207  LetterCodes[159] = '1111111111110000011';
208  LetterCodes[160] = '1111111111110000000';
209  LetterCodes[161] = '1111111111110000001';
210  LetterCodes[162] = '1111111111110000110';
211  LetterCodes[163] = '1111111111110000111';
212  LetterCodes[164] = '1111111111110000100';
213  LetterCodes[165] = '1111111111110000101';
214  LetterCodes[166] = '1111111111110011010';
215  LetterCodes[167] = '1111111111110011011';
216  LetterCodes[168] = '1111111111110011000';
217  LetterCodes[169] = '1111111111110011001';
218  LetterCodes[170] = '1111111111110011110';
219  LetterCodes[171] = '1111111111110011111';
220  LetterCodes[172] = '1111111111110011100';
221  LetterCodes[173] = '1111111111110011101';
222  LetterCodes[174] = '1111111111110010010';
223  LetterCodes[175] = '1111111111110010011';
224  LetterCodes[176] = '1111111111110010000';
225  LetterCodes[177] = '1111111111110010001';
226  LetterCodes[178] = '1111111111110010110';
227  LetterCodes[179] = '1111111111110010111';
228  LetterCodes[180] = '1111111111110010100';
229  LetterCodes[181] = '1111111111110010101';
230  LetterCodes[182] = '1111111111111101010';
231  LetterCodes[183] = '1111111111111101011';
232  LetterCodes[184] = '1111111111111101000';
233  LetterCodes[185] = '1111111111111101001';
234  LetterCodes[186] = '1111111111111101110';
235  LetterCodes[187] = '1111111111111101111';
236  LetterCodes[188] = '1111111111111101100';
237  LetterCodes[189] = '1111111111111101101';
238  LetterCodes[190] = '1111111111111100010';
239  LetterCodes[191] = '1111111111111100011';
240  LetterCodes[192] = '1111111111111100000';
241  LetterCodes[193] = '1111111111111100001';
242  LetterCodes[194] = '1111111111111100110';
243  LetterCodes[195] = '1111111111111100111';
244  LetterCodes[196] = '1111111111111100100';
245  LetterCodes[197] = '1111111111111100101';
246  LetterCodes[198] = '1111111111111111010';
247  LetterCodes[199] = '1111111111111111011';
248  LetterCodes[200] = '1111111111111111000';
249  LetterCodes[201] = '1111111111111111001';
250  LetterCodes[202] = '1111111111111111110';
251  LetterCodes[203] = '1111111111111111111';
252  LetterCodes[204] = '1111111111111111100';
253  LetterCodes[205] = '1111111111111111101';
254  LetterCodes[206] = '1111111111111110010';
255  LetterCodes[207] = '1111111111111110011';
256  LetterCodes[208] = '1111111111111110000';
257  LetterCodes[209] = '1111111111111110001';
258  LetterCodes[210] = '1111111111111110110';
259  LetterCodes[211] = '1111111111111110111';
260  LetterCodes[212] = '1111111111111110100';
261  LetterCodes[213] = '1111111111111110101';
262  LetterCodes[214] = '1111111111111001010';
263  LetterCodes[215] = '1111111111111001011';
264  LetterCodes[216] = '1111111111111001000';
265  LetterCodes[217] = '1111111111111001001';
266  LetterCodes[218] = '1111111111111001110';
267  LetterCodes[219] = '1111111111111001111';
268  LetterCodes[220] = '1111111111111001100';
269  LetterCodes[221] = '1111111111111001101';
270  LetterCodes[222] = '1111111111111000010';
271  LetterCodes[223] = '1111111111111000011';
272  LetterCodes[224] = '1111111111111000000';
273  LetterCodes[225] = '1111111111111000001';
274  LetterCodes[226] = '1111111111111000110';
275  LetterCodes[227] = '1111111111111000111';
276  LetterCodes[228] = '1111111111111000100';
277  LetterCodes[229] = '1111111111111000101';
278  LetterCodes[230] = '1111111111111011010';
279  LetterCodes[231] = '1111111111111011011';
280  LetterCodes[232] = '1111111111111011000';
281  LetterCodes[233] = '1111111111111011001';
282  LetterCodes[234] = '1111111111111011110';
283  LetterCodes[235] = '1111111111111011111';
284  LetterCodes[236] = '1111111111111011100';
285  LetterCodes[237] = '1111111111111011101';
286  LetterCodes[238] = '1111111111111010010';
287  LetterCodes[239] = '1111111111111010011';
288  LetterCodes[240] = '1111111111111010000';
289  LetterCodes[241] = '1111111111111010001';
290  LetterCodes[242] = '1111111111111010110';
291  LetterCodes[243] = '1111111111111010111';
292  LetterCodes[244] = '1111111111111010100';
293  LetterCodes[245] = '1111111111111010101';
294  LetterCodes[246] = '10111111111111010';
295  LetterCodes[247] = '10111111111111011';
296  LetterCodes[248] = '10111111111111000';
297  LetterCodes[249] = '10111111111111001';
298  LetterCodes[250] = '10111111111111110';
299  LetterCodes[251] = '10111111111111111';
300  LetterCodes[252] = '10111111111111100';
301  LetterCodes[253] = '10111111111111101';
302  LetterCodes[254] = '1111111111101110';
303  LetterCodes[255] = '1111111111101111';
304
305  // Build resulting data stream
306  // The bits string could get very large
307  var bits = "";
308  var bytes = ov.length + "$";
309  for (var i = 0; i < ov.length; i ++) {
310    // converts ASCII chars above 255 to a star (code 42) avoiding decoding failure
311    if (ov.charCodeAt(i) > 255) { bits += LetterCodes[42]; }
312    else { bits += LetterCodes[ov.charCodeAt(i)]; }
313    while (bits.length > 5) {
314      bytes += BitsToBytes(bits);
315      bits = bits.slice(6, bits.length);
316    }
317  }
318  bytes += BitsToBytes(bits);
319
320  bytes += encodingCharSet.charAt(encodingVersion);
321
322  return bytes;
323}
324
325