<!DOCTYPE HTML> <html> <!-- pgn4web javascript chessboard copyright (C) 2009-2013 Paolo Casaschi see README file and http://pgn4web.casaschi.net for credits, license and more details Huffman encoding/decoding derived from code at http://rumkin.com/tools/compression/compress_huff.php PLEASE NOTE THIS FILE IS USED ONLY TO FINE TUNE HUFFMANN ENCODING: actual functions for PGN encoding/decoding are contained in pgn-decoder.js and pgn-encoder.js --> <head> <title>pgn4web PGN encoder/decoder test</title> <link rel="shortcut icon" href="pawn.ico" /> <script type="text/javascript"> "use strict"; // fix this to use customized letter distribution var USE_PRESET_LETTER_DISTRIBUTION = true; // fix this once you have the letter codes corresponding to the letter distribution above var USE_PRESET_LETTER_CODES = true; // fix this once you have the decoding values l[] corresponding to the letter codes above var USE_PRESET_DECODING_SET = true; var encodingCharSet = "$0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"; var encodingVersion = 1; // version 1 of PGN encoding: // encodedPGN = nnn$xxx0 // nnn = number representing bytes length of the decoded message // $ = dollar char (delimiter for length info) // xxx = encoded text (using LetterCodes below) // 0 = zero char (version marker) function BitsToBytes(i) { var o = 0; if (i.charAt(0) == '1') { o += 32; } if (i.charAt(1) == '1') { o += 16; } if (i.charAt(2) == '1') { o += 8; } if (i.charAt(3) == '1') { o += 4; } if (i.charAt(4) == '1') { o += 2; } if (i.charAt(5) == '1') { o += 1; } return encodingCharSet.charAt(o); } function EncodePGN(ov) { var i, idx, c; var Letters = new Array(256); var LetterCodes = new Array(256); for (i = 0; i < 256; i ++) { Letters[i] = 0; } for (i = 0; i < ov.length; i ++) { Letters[ov.charCodeAt(i)]++; } if (USE_PRESET_LETTER_DISTRIBUTION) { Letters[0] = 1; Letters[1] = 1; Letters[2] = 1; Letters[3] = 1; Letters[4] = 1; Letters[5] = 1; Letters[6] = 1; Letters[7] = 1; Letters[8] = 1; Letters[9] = 1; Letters[10] = 25000; Letters[11] = 1; Letters[12] = 1; Letters[13] = 25000; Letters[14] = 1; Letters[15] = 1; Letters[16] = 1; Letters[17] = 1; Letters[18] = 1; Letters[19] = 1; Letters[20] = 1; Letters[21] = 1; Letters[22] = 1; Letters[23] = 1; Letters[24] = 1; Letters[25] = 1; Letters[26] = 1; Letters[27] = 1; Letters[28] = 1; Letters[29] = 1; Letters[30] = 1; Letters[31] = 1; Letters[32] = 273240; Letters[33] = 200; // ! Letters[34] = 64928; // " Letters[35] = 326; // # Letters[36] = 163; // $ Letters[37] = 25; // % Letters[38] = 25; // & Letters[39] = 500; // ' Letters[40] = 1607; // ( Letters[41] = 1592; // ) Letters[42] = 10; // * Letters[43] = 9086; // + Letters[44] = 4231; // , Letters[45] = 11848; // - Letters[46] = 91283; // . Letters[47] = 9685; // / Letters[48] = 27308; // 0 Letters[49] = 57229; // 1 Letters[50] = 57065; // 2 Letters[51] = 49049; // 3 Letters[52] = 46441; // 4 Letters[53] = 42430; // 5 Letters[54] = 38872; // 6 Letters[55] = 27853; // 7 Letters[56] = 21292; // 8 Letters[57] = 14627; // 9 Letters[58] = 270; // : Letters[59] = 136; // ; Letters[60] = 290; // < Letters[61] = 1015; // = Letters[62] = 290; // > Letters[63] = 7511; // ? Letters[64] = 100; // @ Letters[65] = 3580; // A Letters[66] = 31461; // B Letters[67] = 4369; // C Letters[68] = 6993; // D Letters[69] = 13777; // E Letters[70] = 1719; // F Letters[71] = 1902; // G Letters[72] = 639; // H Letters[73] = 1054; // I Letters[74] = 420; // J Letters[75] = 16962; // K Letters[76] = 961; // L Letters[77] = 1378; // M Letters[78] = 29494; // N Letters[79] = 10671; // O Letters[80] = 7817; // P Letters[81] = 19645; // Q Letters[82] = 34436; // R Letters[83] = 5795; // S Letters[84] = 2037; // T Letters[85] = 1364; // U Letters[86] = 621; // V Letters[87] = 5270; // W Letters[88] = 249; // X Letters[89] = 185; // Y Letters[90] = 620; // Z Letters[91] = 31633; // [ Letters[92] = 15; // \ Letters[93] = 31628; // ] Letters[94] = 10; // ^ Letters[95] = 15; // _ Letters[96] = 10; // ` Letters[97] = 35573; // a Letters[98] = 19456; // b Letters[99] = 33228; // c Letters[100] = 36380; // d Letters[101] = 64738; // e Letters[102] = 25736; // f Letters[103] = 19801; // g Letters[104] = 20415; // h Letters[105] = 16706; // i Letters[106] = 530; // j Letters[107] = 7806; // k Letters[108] = 18510; // l Letters[109] = 3044; // m Letters[110] = 20680; // n Letters[111] = 17771; // o Letters[112] = 9101; // p Letters[113] = 903; // q Letters[114] = 10153; // r Letters[115] = 9963; // s Letters[116] = 32763; // t Letters[117] = 10268; // u Letters[118] = 7508; // v Letters[119] = 2173; // w Letters[120] = 32913; // x Letters[121] = 2135; // y Letters[122] = 722; // z Letters[123] = 1000; // { Letters[124] = 10; // | Letters[125] = 1000; // } Letters[126] = 10; // ~ Letters[127] = 1; Letters[128] = 1; Letters[129] = 1; Letters[130] = 1; Letters[131] = 1; Letters[132] = 1; Letters[133] = 1; Letters[134] = 1; Letters[135] = 1; Letters[136] = 1; Letters[137] = 1; Letters[138] = 1; Letters[139] = 1; Letters[140] = 1; Letters[141] = 1; Letters[142] = 1; Letters[143] = 1; Letters[144] = 1; Letters[145] = 1; Letters[146] = 1; Letters[147] = 1; Letters[148] = 1; Letters[149] = 1; Letters[150] = 1; Letters[151] = 1; Letters[152] = 1; Letters[153] = 1; Letters[154] = 1; Letters[155] = 1; Letters[156] = 1; Letters[157] = 1; Letters[158] = 1; Letters[159] = 1; Letters[160] = 1; Letters[161] = 1; Letters[162] = 1; Letters[163] = 1; Letters[164] = 1; Letters[165] = 1; Letters[166] = 1; Letters[167] = 1; Letters[168] = 1; Letters[169] = 1; Letters[170] = 1; Letters[171] = 1; Letters[172] = 1; Letters[173] = 1; Letters[174] = 1; Letters[175] = 1; Letters[176] = 1; Letters[177] = 1; Letters[178] = 1; Letters[179] = 1; Letters[180] = 1; Letters[181] = 1; Letters[182] = 1; Letters[183] = 1; Letters[184] = 1; Letters[185] = 1; Letters[186] = 1; Letters[187] = 1; Letters[188] = 1; Letters[189] = 1; Letters[190] = 1; Letters[191] = 1; Letters[192] = 1; Letters[193] = 1; Letters[194] = 1; Letters[195] = 1; Letters[196] = 1; Letters[197] = 1; Letters[198] = 1; Letters[199] = 1; Letters[200] = 1; Letters[201] = 1; Letters[202] = 1; Letters[203] = 1; Letters[204] = 1; Letters[205] = 1; Letters[206] = 1; Letters[207] = 1; Letters[208] = 1; Letters[209] = 1; Letters[210] = 1; Letters[211] = 1; Letters[212] = 1; Letters[213] = 1; Letters[214] = 1; Letters[215] = 1; Letters[216] = 1; Letters[217] = 1; Letters[218] = 1; Letters[219] = 1; Letters[220] = 1; Letters[221] = 1; Letters[222] = 1; Letters[223] = 1; Letters[224] = 1; Letters[225] = 1; Letters[226] = 1; Letters[227] = 1; Letters[228] = 1; Letters[229] = 1; Letters[230] = 1; Letters[231] = 1; Letters[232] = 1; Letters[233] = 1; Letters[234] = 1; Letters[235] = 1; Letters[236] = 1; Letters[237] = 1; Letters[238] = 1; Letters[239] = 1; Letters[240] = 1; Letters[241] = 1; Letters[242] = 1; Letters[243] = 1; Letters[244] = 1; Letters[245] = 1; Letters[246] = 1; Letters[247] = 1; Letters[248] = 1; Letters[249] = 1; Letters[250] = 1; Letters[251] = 1; Letters[252] = 1; Letters[253] = 1; Letters[254] = 1; Letters[255] = 1; } // Build a Huffman tree from the letter count frequencies var NodeLetter = new Array(512); var NodeCount = new Array(512); var NodeChild1 = new Array(512); var NodeChild2 = new Array(512); var NextParent = 0; for (i = 0; i < 256; i ++) { if (Letters[i] > 0) { NodeLetter[NextParent] = i; NodeCount[NextParent] = Letters[i]; NodeChild1[NextParent] = -1; NodeChild2[NextParent] = -1; NextParent ++; } } // Built node list. Now combine nodes to make a tree var SmallestNode1; var SmallestNode2 = 1; while (SmallestNode2 != -1) { SmallestNode1 = -1; SmallestNode2 = -1; for (i = 0; i < NextParent; i ++) { if (NodeCount[i] > 0) { if (SmallestNode1 == -1) { SmallestNode1 = i; } else if (SmallestNode2 == -1) { if (NodeCount[i] < NodeCount[SmallestNode1]) { SmallestNode2 = SmallestNode1; SmallestNode1 = i; } else { SmallestNode2 = i; } } else if (NodeCount[i] <= NodeCount[SmallestNode1]) { SmallestNode2 = SmallestNode1; SmallestNode1 = i; } } } if (SmallestNode2 != -1) { NodeCount[NextParent] = NodeCount[SmallestNode1] + NodeCount[SmallestNode2]; NodeCount[SmallestNode1] = 0; NodeCount[SmallestNode2] = 0; // Reversed SmallestNode numbers here for ordering in the tree NodeChild1[NextParent] = SmallestNode2; NodeChild2[NextParent] = SmallestNode1; NextParent ++; } } // We have constructed the nodes. Now rewrite the list into a single array. // The value of an array element will be positive if it is the character // code we want. Otherwise, it branches. The left branch will be the next // array element. The value of the array will be (offset * -1), which is // the right branch. var FinalNodes = Array(NextParent); var DepthIndex = Array(256); var Depth = 0; var NextFinal = 0; DepthIndex[Depth] = SmallestNode1; while (Depth >= 0) { if (NodeChild1[DepthIndex[Depth]] > -1 && NodeChild2[DepthIndex[Depth]] > -1) { // If there is a left and right, push them on the stack idx = NodeChild1[DepthIndex[Depth]]; NodeChild1[DepthIndex[Depth]] = -2 - NextFinal; Depth ++; DepthIndex[Depth] = idx; NextFinal ++; } else if (NodeChild1[DepthIndex[Depth]] < 0 && NodeChild2[DepthIndex[Depth]] > -1) { // If there is a left and a right, but the left was taken, // push the right on the stack. // Update the FinalNodes[] with the location for the right branch. idx = NodeChild1[DepthIndex[Depth]]; idx = 0 - idx; idx -= 2; FinalNodes[idx] = - NextFinal; // Traverse right branch idx = NodeChild2[DepthIndex[Depth]]; NodeChild2[DepthIndex[Depth]] = -2; Depth ++; DepthIndex[Depth] = idx; } else if (NodeChild1[DepthIndex[Depth]] < -1 && NodeChild2[DepthIndex[Depth]] < -1) { // If there was a left and a right, but they were both taken, pop up a level Depth --; } else if (NodeChild1[DepthIndex[Depth]] == -1 && NodeChild2[DepthIndex[Depth]] == -1) { // If we have a child here, add it to the final nodes, pop up FinalNodes[NextFinal] = NodeLetter[DepthIndex[Depth]]; NextFinal ++; Depth --; } else { // This shouldn't ever happen alert('Bad algorithm!'); return new Array ("", "", ""); } } // We have the tree. Associate codes with the letters. var CodeIndex = new Array(256); DepthIndex[0] = 0; CodeIndex[0] = ""; Depth = 0; while (Depth >= 0) { if (FinalNodes[DepthIndex[Depth]] < 0) { c = CodeIndex[Depth]; idx = DepthIndex[Depth]; DepthIndex[Depth + 1] = DepthIndex[Depth] + 1; CodeIndex[Depth + 1] = c + '0'; DepthIndex[Depth] = 0 - FinalNodes[idx]; CodeIndex[Depth] = c + '1'; Depth ++; } else { LetterCodes[FinalNodes[DepthIndex[Depth]]] = CodeIndex[Depth]; Depth --; } } if (USE_PRESET_LETTER_CODES) { LetterCodes[0] = '00111111111111110'; LetterCodes[1] = '0101101'; LetterCodes[2] = '00111111111111111'; LetterCodes[3] = '00111111111111100'; LetterCodes[4] = '00111111111111101'; LetterCodes[5] = '000011111111111010'; LetterCodes[6] = '000011111111111011'; LetterCodes[7] = '000011111111111000'; LetterCodes[8] = '000011111111111001'; LetterCodes[9] = '000011111111111110'; LetterCodes[10] = '0101100'; LetterCodes[11] = '000011111111111111'; LetterCodes[12] = '000011111111111100'; LetterCodes[13] = '0011100'; LetterCodes[14] = '000011111111111101'; LetterCodes[15] = '000011111111110010'; LetterCodes[16] = '000011111111110011'; LetterCodes[17] = '000011111111110000'; LetterCodes[18] = '000011111111110001'; LetterCodes[19] = '000011111111110110'; LetterCodes[20] = '000011111111110111'; LetterCodes[21] = '000011111111110100'; LetterCodes[22] = '000011111111110101'; LetterCodes[23] = '1111111111110101010'; LetterCodes[24] = '1111111111110101011'; LetterCodes[25] = '1111111111110101000'; LetterCodes[26] = '1111111111110101001'; LetterCodes[27] = '1111111111110101110'; LetterCodes[28] = '1111111111110101111'; LetterCodes[29] = '1111111111110101100'; LetterCodes[30] = '1111111111110101101'; LetterCodes[31] = '1111111111110100010'; LetterCodes[32] = '1000'; LetterCodes[33] = '101111111110'; LetterCodes[34] = '00010'; LetterCodes[35] = '11111111110'; LetterCodes[36] = '0011111111110'; LetterCodes[37] = '1011111111110'; LetterCodes[38] = '00001111111110'; LetterCodes[39] = '00111111110'; LetterCodes[40] = '0011101'; LetterCodes[41] = '111111110'; LetterCodes[42] = '11001111111110'; LetterCodes[43] = '1111110'; LetterCodes[44] = '000011110'; LetterCodes[45] = '0011110'; LetterCodes[46] = '00000'; LetterCodes[47] = '0110110'; LetterCodes[48] = '010100'; LetterCodes[49] = '00110'; LetterCodes[50] = '01000'; LetterCodes[51] = '01100'; LetterCodes[52] = '11000'; LetterCodes[53] = '11010'; LetterCodes[54] = '11100'; LetterCodes[55] = '001010'; LetterCodes[56] = '011100'; LetterCodes[57] = '0001110'; LetterCodes[58] = '001111111110'; LetterCodes[59] = '1111111111100'; LetterCodes[60] = '10111111110'; LetterCodes[61] = '1100110100'; LetterCodes[62] = '000011111110'; LetterCodes[63] = '00011110'; LetterCodes[64] = '1100111111110'; LetterCodes[65] = '110011100'; LetterCodes[66] = '000010'; LetterCodes[67] = '10111110'; LetterCodes[68] = '00111110'; LetterCodes[69] = '0010110'; LetterCodes[70] = '110011101'; LetterCodes[71] = '110011110'; LetterCodes[72] = '1100110101'; LetterCodes[73] = '0010111110'; LetterCodes[74] = '11001111110'; LetterCodes[75] = '101110'; LetterCodes[76] = '1100111110'; LetterCodes[77] = '101111110'; LetterCodes[78] = '000110'; LetterCodes[79] = '0101110'; LetterCodes[80] = '1011110'; LetterCodes[81] = '011101'; LetterCodes[82] = '11101'; LetterCodes[83] = '11001100'; LetterCodes[84] = '001111110'; LetterCodes[85] = '0000111110'; LetterCodes[86] = '1111111110'; LetterCodes[87] = '11111110'; LetterCodes[88] = '110011111110'; LetterCodes[89] = '0000111111110'; LetterCodes[90] = '1011111110'; LetterCodes[91] = '10010'; LetterCodes[92] = '00111111111110'; LetterCodes[93] = '10011'; LetterCodes[94] = '11001111111111'; LetterCodes[95] = '11111111111010'; LetterCodes[96] = '10111111111110'; LetterCodes[97] = '11110'; LetterCodes[98] = '011010'; LetterCodes[99] = '10100'; LetterCodes[100] = '11011'; LetterCodes[101] = '00100'; LetterCodes[102] = '010010'; LetterCodes[103] = '010011'; LetterCodes[104] = '011110'; LetterCodes[105] = '0000110'; LetterCodes[106] = '00001111110'; LetterCodes[107] = '00001110'; LetterCodes[108] = '110010'; LetterCodes[109] = '000111110'; LetterCodes[110] = '010101'; LetterCodes[111] = '111110'; LetterCodes[112] = '0110111'; LetterCodes[113] = '1100110110'; LetterCodes[114] = '0111110'; LetterCodes[115] = '0111111'; LetterCodes[116] = '10110'; LetterCodes[117] = '0101111'; LetterCodes[118] = '00101110'; LetterCodes[119] = '000111111'; LetterCodes[120] = '10101'; LetterCodes[121] = '001011110'; LetterCodes[122] = '1100110111'; LetterCodes[123] = '0010111111'; LetterCodes[124] = '001111111111110'; LetterCodes[125] = '0011111110'; LetterCodes[126] = '111111111110110'; LetterCodes[127] = '1111111111110100011'; LetterCodes[128] = '1111111111110100000'; LetterCodes[129] = '1111111111110100001'; LetterCodes[130] = '1111111111110100110'; LetterCodes[131] = '1111111111110100111'; LetterCodes[132] = '1111111111110100100'; LetterCodes[133] = '1111111111110100101'; LetterCodes[134] = '1111111111110111010'; LetterCodes[135] = '1111111111110111011'; LetterCodes[136] = '1111111111110111000'; LetterCodes[137] = '1111111111110111001'; LetterCodes[138] = '1111111111110111110'; LetterCodes[139] = '1111111111110111111'; LetterCodes[140] = '1111111111110111100'; LetterCodes[141] = '1111111111110111101'; LetterCodes[142] = '1111111111110110010'; LetterCodes[143] = '1111111111110110011'; LetterCodes[144] = '1111111111110110000'; LetterCodes[145] = '1111111111110110001'; LetterCodes[146] = '1111111111110110110'; LetterCodes[147] = '1111111111110110111'; LetterCodes[148] = '1111111111110110100'; LetterCodes[149] = '1111111111110110101'; LetterCodes[150] = '1111111111110001010'; LetterCodes[151] = '1111111111110001011'; LetterCodes[152] = '1111111111110001000'; LetterCodes[153] = '1111111111110001001'; LetterCodes[154] = '1111111111110001110'; LetterCodes[155] = '1111111111110001111'; LetterCodes[156] = '1111111111110001100'; LetterCodes[157] = '1111111111110001101'; LetterCodes[158] = '1111111111110000010'; LetterCodes[159] = '1111111111110000011'; LetterCodes[160] = '1111111111110000000'; LetterCodes[161] = '1111111111110000001'; LetterCodes[162] = '1111111111110000110'; LetterCodes[163] = '1111111111110000111'; LetterCodes[164] = '1111111111110000100'; LetterCodes[165] = '1111111111110000101'; LetterCodes[166] = '1111111111110011010'; LetterCodes[167] = '1111111111110011011'; LetterCodes[168] = '1111111111110011000'; LetterCodes[169] = '1111111111110011001'; LetterCodes[170] = '1111111111110011110'; LetterCodes[171] = '1111111111110011111'; LetterCodes[172] = '1111111111110011100'; LetterCodes[173] = '1111111111110011101'; LetterCodes[174] = '1111111111110010010'; LetterCodes[175] = '1111111111110010011'; LetterCodes[176] = '1111111111110010000'; LetterCodes[177] = '1111111111110010001'; LetterCodes[178] = '1111111111110010110'; LetterCodes[179] = '1111111111110010111'; LetterCodes[180] = '1111111111110010100'; LetterCodes[181] = '1111111111110010101'; LetterCodes[182] = '1111111111111101010'; LetterCodes[183] = '1111111111111101011'; LetterCodes[184] = '1111111111111101000'; LetterCodes[185] = '1111111111111101001'; LetterCodes[186] = '1111111111111101110'; LetterCodes[187] = '1111111111111101111'; LetterCodes[188] = '1111111111111101100'; LetterCodes[189] = '1111111111111101101'; LetterCodes[190] = '1111111111111100010'; LetterCodes[191] = '1111111111111100011'; LetterCodes[192] = '1111111111111100000'; LetterCodes[193] = '1111111111111100001'; LetterCodes[194] = '1111111111111100110'; LetterCodes[195] = '1111111111111100111'; LetterCodes[196] = '1111111111111100100'; LetterCodes[197] = '1111111111111100101'; LetterCodes[198] = '1111111111111111010'; LetterCodes[199] = '1111111111111111011'; LetterCodes[200] = '1111111111111111000'; LetterCodes[201] = '1111111111111111001'; LetterCodes[202] = '1111111111111111110'; LetterCodes[203] = '1111111111111111111'; LetterCodes[204] = '1111111111111111100'; LetterCodes[205] = '1111111111111111101'; LetterCodes[206] = '1111111111111110010'; LetterCodes[207] = '1111111111111110011'; LetterCodes[208] = '1111111111111110000'; LetterCodes[209] = '1111111111111110001'; LetterCodes[210] = '1111111111111110110'; LetterCodes[211] = '1111111111111110111'; LetterCodes[212] = '1111111111111110100'; LetterCodes[213] = '1111111111111110101'; LetterCodes[214] = '1111111111111001010'; LetterCodes[215] = '1111111111111001011'; LetterCodes[216] = '1111111111111001000'; LetterCodes[217] = '1111111111111001001'; LetterCodes[218] = '1111111111111001110'; LetterCodes[219] = '1111111111111001111'; LetterCodes[220] = '1111111111111001100'; LetterCodes[221] = '1111111111111001101'; LetterCodes[222] = '1111111111111000010'; LetterCodes[223] = '1111111111111000011'; LetterCodes[224] = '1111111111111000000'; LetterCodes[225] = '1111111111111000001'; LetterCodes[226] = '1111111111111000110'; LetterCodes[227] = '1111111111111000111'; LetterCodes[228] = '1111111111111000100'; LetterCodes[229] = '1111111111111000101'; LetterCodes[230] = '1111111111111011010'; LetterCodes[231] = '1111111111111011011'; LetterCodes[232] = '1111111111111011000'; LetterCodes[233] = '1111111111111011001'; LetterCodes[234] = '1111111111111011110'; LetterCodes[235] = '1111111111111011111'; LetterCodes[236] = '1111111111111011100'; LetterCodes[237] = '1111111111111011101'; LetterCodes[238] = '1111111111111010010'; LetterCodes[239] = '1111111111111010011'; LetterCodes[240] = '1111111111111010000'; LetterCodes[241] = '1111111111111010001'; LetterCodes[242] = '1111111111111010110'; LetterCodes[243] = '1111111111111010111'; LetterCodes[244] = '1111111111111010100'; LetterCodes[245] = '1111111111111010101'; LetterCodes[246] = '10111111111111010'; LetterCodes[247] = '10111111111111011'; LetterCodes[248] = '10111111111111000'; LetterCodes[249] = '10111111111111001'; LetterCodes[250] = '10111111111111110'; LetterCodes[251] = '10111111111111111'; LetterCodes[252] = '10111111111111100'; LetterCodes[253] = '10111111111111101'; LetterCodes[254] = '1111111111101110'; LetterCodes[255] = '1111111111101111'; } // Build resulting data stream // The bits string could get very large var bits = ""; var bytes = ov.length + "$"; for (i = 0; i < ov.length; i ++) { // converts ASCII chars above 255 to a star (code 42) avoiding decoding failure if (ov.charCodeAt(i) > 255) { bits += LetterCodes[42]; } else { bits += LetterCodes[ov.charCodeAt(i)]; } while (bits.length > 5) { bytes += BitsToBytes(bits); bits = bits.slice(6, bits.length); } } bytes += BitsToBytes(bits); var encodedNodes = ""; for (i = 0; i < FinalNodes.length; i ++) { var x, y; x = FinalNodes[i] + 512; y = x & 0x3F; x >>= 6; x &= 0x3F; encodedNodes += encodingCharSet.charAt(x) + encodingCharSet.charAt(y); } bytes += encodingCharSet.charAt(encodingVersion); return new Array (bytes, encodedNodes, LetterCodes); } function DecodePGN(bytes, encodedNodes) { if (bytes.charAt(bytes.length - 1) != encodingCharSet.charAt(encodingVersion)) { alert("ERROR: PGN encoding version mismatch (e:" + bytes.charAt(bytes.length - 1) + " d:" + encodingCharSet.charAt(encodingVersion) + ")"); } var originalLength = parseInt(bytes.match(/^[0-9]*/), 10); bytes = bytes.replace(/^[0-9]*\$/,""); var l = new Array(); while(encodedNodes.length) { l.push((encodingCharSet.indexOf(encodedNodes.charAt(0))<<6)+encodingCharSet.indexOf(encodedNodes.charAt(1))-512); encodedNodes = encodedNodes.slice(2,encodedNodes.length); } if (USE_PRESET_DECODING_SET) { l[0] = -146; l[1] = -111; l[2] = -66; l[3] = -55; l[4] = -6; l[5] = 46; l[6] = -8; l[7] = 66; l[8] = -10; l[9] = 105; l[10] = -12; l[11] = 107; l[12] = -14; l[13] = 44; l[14] = -16; l[15] = 85; l[16] = -18; l[17] = 106; l[18] = -20; l[19] = 62; l[20] = -22; l[21] = 89; l[22] = -24; l[23] = 38; l[24] = -40; l[25] = -33; l[26] = -30; l[27] = -29; l[28] = 17; l[29] = 18; l[30] = -32; l[31] = 15; l[32] = 16; l[33] = -37; l[34] = -36; l[35] = 21; l[36] = 22; l[37] = -39; l[38] = 19; l[39] = 20; l[40] = -48; l[41] = -45; l[42] = -44; l[43] = 7; l[44] = 8; l[45] = -47; l[46] = 5; l[47] = 6; l[48] = -52; l[49] = -51; l[50] = 12; l[51] = 14; l[52] = -54; l[53] = 9; l[54] = 11; l[55] = -57; l[56] = 34; l[57] = -59; l[58] = 78; l[59] = -61; l[60] = 57; l[61] = -63; l[62] = 63; l[63] = -65; l[64] = 109; l[65] = 119; l[66] = -80; l[67] = -69; l[68] = 101; l[69] = -71; l[70] = 55; l[71] = -73; l[72] = 69; l[73] = -75; l[74] = 118; l[75] = -77; l[76] = 121; l[77] = -79; l[78] = 73; l[79] = 123; l[80] = -82; l[81] = 49; l[82] = -86; l[83] = -85; l[84] = 13; l[85] = 40; l[86] = -88; l[87] = 45; l[88] = -90; l[89] = 68; l[90] = -92; l[91] = 84; l[92] = -94; l[93] = 125; l[94] = -96; l[95] = 39; l[96] = -98; l[97] = 58; l[98] = -100; l[99] = 36; l[100] = -102; l[101] = 92; l[102] = -104; l[103] = 124; l[104] = -108; l[105] = -107; l[106] = 3; l[107] = 4; l[108] = -110; l[109] = 0; l[110] = 2; l[111] = -129; l[112] = -118; l[113] = -115; l[114] = 50; l[115] = -117; l[116] = 102; l[117] = 103; l[118] = -122; l[119] = -121; l[120] = 48; l[121] = 110; l[122] = -126; l[123] = -125; l[124] = 10; l[125] = 1; l[126] = -128; l[127] = 79; l[128] = 117; l[129] = -137; l[130] = -132; l[131] = 51; l[132] = -134; l[133] = 98; l[134] = -136; l[135] = 47; l[136] = 112; l[137] = -141; l[138] = -140; l[139] = 56; l[140] = 81; l[141] = -143; l[142] = 104; l[143] = -145; l[144] = 114; l[145] = 115; l[146] = -192; l[147] = -153; l[148] = -150; l[149] = 32; l[150] = -152; l[151] = 91; l[152] = 93; l[153] = -157; l[154] = -156; l[155] = 99; l[156] = 120; l[157] = -159; l[158] = 116; l[159] = -161; l[160] = 75; l[161] = -163; l[162] = 80; l[163] = -165; l[164] = 67; l[165] = -167; l[166] = 77; l[167] = -169; l[168] = 90; l[169] = -171; l[170] = 60; l[171] = -173; l[172] = 33; l[173] = -175; l[174] = 37; l[175] = -177; l[176] = 96; l[177] = -185; l[178] = -182; l[179] = -181; l[180] = 248; l[181] = 249; l[182] = -184; l[183] = 246; l[184] = 247; l[185] = -189; l[186] = -188; l[187] = 252; l[188] = 253; l[189] = -191; l[190] = 250; l[191] = 251; l[192] = -228; l[193] = -225; l[194] = -196; l[195] = 52; l[196] = -198; l[197] = 108; l[198] = -208; l[199] = -201; l[200] = 83; l[201] = -205; l[202] = -204; l[203] = 61; l[204] = 72; l[205] = -207; l[206] = 113; l[207] = 122; l[208] = -212; l[209] = -211; l[210] = 65; l[211] = 70; l[212] = -214; l[213] = 71; l[214] = -216; l[215] = 76; l[216] = -218; l[217] = 74; l[218] = -220; l[219] = 88; l[220] = -222; l[221] = 64; l[222] = -224; l[223] = 42; l[224] = 94; l[225] = -227; l[226] = 53; l[227] = 100; l[228] = -232; l[229] = -231; l[230] = 54; l[231] = 82; l[232] = -234; l[233] = 97; l[234] = -236; l[235] = 111; l[236] = -238; l[237] = 43; l[238] = -240; l[239] = 87; l[240] = -242; l[241] = 41; l[242] = -244; l[243] = 86; l[244] = -246; l[245] = 35; l[246] = -256; l[247] = -249; l[248] = 59; l[249] = -251; l[250] = 95; l[251] = -253; l[252] = 126; l[253] = -255; l[254] = 254; l[255] = 255; l[256] = -384; l[257] = -321; l[258] = -290; l[259] = -275; l[260] = -268; l[261] = -265; l[262] = -264; l[263] = 160; l[264] = 161; l[265] = -267; l[266] = 158; l[267] = 159; l[268] = -272; l[269] = -271; l[270] = 164; l[271] = 165; l[272] = -274; l[273] = 162; l[274] = 163; l[275] = -283; l[276] = -280; l[277] = -279; l[278] = 152; l[279] = 153; l[280] = -282; l[281] = 150; l[282] = 151; l[283] = -287; l[284] = -286; l[285] = 156; l[286] = 157; l[287] = -289; l[288] = 154; l[289] = 155; l[290] = -306; l[291] = -299; l[292] = -296; l[293] = -295; l[294] = 176; l[295] = 177; l[296] = -298; l[297] = 174; l[298] = 175; l[299] = -303; l[300] = -302; l[301] = 180; l[302] = 181; l[303] = -305; l[304] = 178; l[305] = 179; l[306] = -314; l[307] = -311; l[308] = -310; l[309] = 168; l[310] = 169; l[311] = -313; l[312] = 166; l[313] = 167; l[314] = -318; l[315] = -317; l[316] = 172; l[317] = 173; l[318] = -320; l[319] = 170; l[320] = 171; l[321] = -353; l[322] = -338; l[323] = -331; l[324] = -328; l[325] = -327; l[326] = 128; l[327] = 129; l[328] = -330; l[329] = 31; l[330] = 127; l[331] = -335; l[332] = -334; l[333] = 132; l[334] = 133; l[335] = -337; l[336] = 130; l[337] = 131; l[338] = -346; l[339] = -343; l[340] = -342; l[341] = 25; l[342] = 26; l[343] = -345; l[344] = 23; l[345] = 24; l[346] = -350; l[347] = -349; l[348] = 29; l[349] = 30; l[350] = -352; l[351] = 27; l[352] = 28; l[353] = -369; l[354] = -362; l[355] = -359; l[356] = -358; l[357] = 144; l[358] = 145; l[359] = -361; l[360] = 142; l[361] = 143; l[362] = -366; l[363] = -365; l[364] = 148; l[365] = 149; l[366] = -368; l[367] = 146; l[368] = 147; l[369] = -377; l[370] = -374; l[371] = -373; l[372] = 136; l[373] = 137; l[374] = -376; l[375] = 134; l[376] = 135; l[377] = -381; l[378] = -380; l[379] = 140; l[380] = 141; l[381] = -383; l[382] = 138; l[383] = 139; l[384] = -448; l[385] = -417; l[386] = -402; l[387] = -395; l[388] = -392; l[389] = -391; l[390] = 224; l[391] = 225; l[392] = -394; l[393] = 222; l[394] = 223; l[395] = -399; l[396] = -398; l[397] = 228; l[398] = 229; l[399] = -401; l[400] = 226; l[401] = 227; l[402] = -410; l[403] = -407; l[404] = -406; l[405] = 216; l[406] = 217; l[407] = -409; l[408] = 214; l[409] = 215; l[410] = -414; l[411] = -413; l[412] = 220; l[413] = 221; l[414] = -416; l[415] = 218; l[416] = 219; l[417] = -433; l[418] = -426; l[419] = -423; l[420] = -422; l[421] = 240; l[422] = 241; l[423] = -425; l[424] = 238; l[425] = 239; l[426] = -430; l[427] = -429; l[428] = 244; l[429] = 245; l[430] = -432; l[431] = 242; l[432] = 243; l[433] = -441; l[434] = -438; l[435] = -437; l[436] = 232; l[437] = 233; l[438] = -440; l[439] = 230; l[440] = 231; l[441] = -445; l[442] = -444; l[443] = 236; l[444] = 237; l[445] = -447; l[446] = 234; l[447] = 235; l[448] = -480; l[449] = -465; l[450] = -458; l[451] = -455; l[452] = -454; l[453] = 192; l[454] = 193; l[455] = -457; l[456] = 190; l[457] = 191; l[458] = -462; l[459] = -461; l[460] = 196; l[461] = 197; l[462] = -464; l[463] = 194; l[464] = 195; l[465] = -473; l[466] = -470; l[467] = -469; l[468] = 184; l[469] = 185; l[470] = -472; l[471] = 182; l[472] = 183; l[473] = -477; l[474] = -476; l[475] = 188; l[476] = 189; l[477] = -479; l[478] = 186; l[479] = 187; l[480] = -496; l[481] = -489; l[482] = -486; l[483] = -485; l[484] = 208; l[485] = 209; l[486] = -488; l[487] = 206; l[488] = 207; l[489] = -493; l[490] = -492; l[491] = 212; l[492] = 213; l[493] = -495; l[494] = 210; l[495] = 211; l[496] = -504; l[497] = -501; l[498] = -500; l[499] = 200; l[500] = 201; l[501] = -503; l[502] = 198; l[503] = 199; l[504] = -508; l[505] = -507; l[506] = 204; l[507] = 205; l[508] = -510; l[509] = 202; l[510] = 203; } var a=0, b=0, e=0, i, o=""; function B() { if (a===0) { b=encodingCharSet.indexOf(bytes.charAt(e++)); a=6; } return ((b>>--a)&0x01); } while(originalLength>0) { i=0; while(l[i]<0) { if (B()) { i=-l[i]; } else { i++; } } o+=String.fromCharCode(l[i]); originalLength--; } return o; } </script> </head> <body style="margin: 0px; padding: 1.75em; font-family: sans-serif;"> <h1 style="margin-top:0px; padding-top:0px;">pgn4web PGN encoder/decoder test</h1> <center> <textarea id="textArea" style="height:300px; width:900px;"></textarea> <form> <input type="button" style="width:700px;" onClick="javascript: testPGNencode();" value="pgn4web PGN encoder/decoder test"> <input type="button" style="width:200px;" onClick="javascript: document.getElementById('textArea').value = '';" value="clear form"> </form> <div style="width: 900px; text-align: left"><b>status: </b><span id="status">enter PGN data and press the test button</span></div> <br> <table cellspacing=2 cellpadding=0 border=1> <tr style="font-weight: bold; text-align: center;"> <td>original</td> <td>decoded</td> </tr> <tr> <td> <textarea id="original" readonly style="height:300px; width:447px;"> </textarea> </td> <td> <textarea id="decoded" readonly style="height:300px; width:447px;"> </textarea> </td> </tr> </table> <br> <table cellspacing=2 cellpadding=0 border=1> <tr style="font-weight: bold; text-align: center;"> <td>encoded</td> </tr> <tr> <td> <textarea id="encoded" readonly style="height:80px; width:896px;"> </textarea> </td> </tr> <tr style="font-weight: bold; text-align: center;"> <td>decoding key</td> </tr> <tr> <td> <textarea id="decodingKey" readonly style="height:80px; width:896px;"> </textarea> </td> </tr> </table> <br> <table cellspacing=2 cellpadding=0 border=1> <tr style="font-weight: bold; text-align: center;"> <td>original letters</td> <td>letter codes</td> <td>decoding values</td> <td>encoded letters</td> </tr> <tr> <td> <textarea id="originalLetters" readonly style="height:300px; width:195px;"> </textarea> </td> <td> <textarea id="LetterCodes" readonly style="height:300px; width:335px;"> </textarea> </td> <td> <textarea id="decodingValues" readonly style="height:300px; width:165px;"> </textarea> </td> <td> <textarea id="encodedLetters" readonly style="height:300px; width:195px;"> </textarea> </td> </tr> </table> <br> </center> <script type="text/javascript"> function testPGNencode() { document.getElementById("status").innerHTML = "encoding data, please wait..."; if (document.getElementById("textArea").value === "") { document.getElementById("original").value = document.getElementById("originalInput").innerHTML; } else { document.getElementById("original").value = document.getElementById("textArea").value; } original_var = document.getElementById("original").value; ret = new Array(3); ret = EncodePGN(original_var); test_bytes = ret[0]; test_encodedNodes = ret[1]; test_LetterCodes = ret[2]; document.getElementById("status").innerHTML = "decoding data, please wait..."; document.getElementById("encoded").value = test_bytes; document.getElementById("decoded").value = DecodePGN(test_bytes, test_encodedNodes); compressPerc = Math.floor(100 * (document.getElementById("original").value.length - document.getElementById("encoded").value.length) / document.getElementById("original").value.length); document.getElementById("status").innerHTML = "encoding/decoding test completed;" + " original: " + document.getElementById("original").value.length + ";" + " encoded: " + document.getElementById("encoded").value.length + ";" + " compression rate: " + compressPerc + "%"; if (document.getElementById("decoded").value != document.getElementById("original").value) { document.getElementById("status").innerHTML += "<br><span style='font-weight: bold; color: red;'>error: decoded different from original, please check for ASCII chars greater than 255 in the original input</span>"; } document.getElementById("originalLetters").value = letter_frequency(document.getElementById("original").value); document.getElementById("encodedLetters").value = letter_frequency(document.getElementById("encoded").value); document.getElementById("decodingKey").value = test_encodedNodes; l = new Array(); while(test_encodedNodes.length) { l.push((encodingCharSet.indexOf(test_encodedNodes.charAt(0))<<6)+encodingCharSet.indexOf(test_encodedNodes.charAt(1))-512); test_encodedNodes = test_encodedNodes.slice(2,test_encodedNodes.length); } o = ""; for (i=0; i<l.length; i++) { o += "l[" + i + "]"; if (i < 10) { o += " "; } else { if (i < 100) { o += " "; } } o += " = " + l[i] + ";\n"; } document.getElementById("decodingValues").value = o; o = ""; for (i=0; i<test_LetterCodes.length; i++) { o += "LetterCodes[" + i + "]"; if (i < 10) { o += " "; } else { if (i < 100) { o += " "; } } o += " = '" + test_LetterCodes[i] + "';\n"; } document.getElementById("LetterCodes").innerHTML = o; } function letter_frequency(s) { var thisLetters = new Array(256); for (i = 0; i < thisLetters.length; i ++) { thisLetters[i]=0; } var o = ""; for (i = 0; i < s.length; i ++) { thisLetters[s.charCodeAt(i)]++; } for (i = 0; i < thisLetters.length; i ++) { o += "Letters[" + i + "]"; if (i < 10) { o += " "; } else { if (i < 100) { o += " "; } } o += " = " + thisLetters[i] + ";"; if (i > 32) { o += " // " + String.fromCharCode(i); } o += "\n"; } return o; } </script> <textarea id="originalInput" style="display:none;"> [White "Spassky, Boris"] [Black "Fischer, Robert"] [Result "0-1"] [Date "1972"] [Event "World Championship"] [Site "Reykjavik"] [Round "13"] 1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. Nf3 g6 5. Bc4 Nb6 6. Bb3 Bg7 7. Nbd2 O-O 8. h3 a5 9. a4 dxe5 10. dxe5 Na6 11. O-O Nc5 12. Qe2 Qe8 13. Ne4 Nbxa4 14. Bxa4 Nxa4 15. Re1 Nb6 16. Bd2 a4 17. Bg5 h6 18. Bh4 Bf5 19. g4 Be6 20. Nd4 Bc4 21. Qd2 Qd7 22. Rad1 Rfe8 23. f4 Bd5 24. Nc5 Qc8 25. Qc3 e6 26. Kh2 Nd7 27. Nd3 c5 28. Nb5 Qc6 29. Nd6 Qxd6 30. exd6 Bxc3 31. bxc3 f6 32. g5 hxg5 33. fxg5 f5 34. Bg3 Kf7 35. Ne5 Nxe5 36. Bxe5 b5 37. Rf1 Rh8 38. Bf6 a3 39. Rf4 a2 40. c4 Bxc4 41. d7 Bd5 42. Kg3 Ra3 43. c3 Rha8 44. Rh4 e5 45. Rh7 Ke6 46. Re7 Kd6 47. Rxe5 Rxc3 48. Kf2 Rc2 49. Ke1 Kxd7 50. Rexd5 Kc6 51. Rd6 Kb7 52. Rd7 Ka6 53. R7d2 Rxd2 54. Kxd2 b4 55. h4 Kb5 56. h5 c4 57. Ra1 gxh5 58. g6 h4 59. g7 h3 60. Be7 Rg8 61. Bf8 h2 62. Kc2 Kc6 63. Rd1 b3 64. Kc3 h1Q 65. Rxh1 Kd5 66. Kb2 f4 67. Rd1 Ke4 68. Rc1 Kd3 69. Rd1 Ke2 70. Rc1 f3 71. Bc5 Rxg7 72. Rxc4 Rd7 73. Re4 Kf1 74. Bd4 f2 0-1 </textarea> </body> </html>