const WIDTH_TBL = [ '212222' , '222122' , '222221' , '121223' , '121322' , '131222' , '122213' , '122312' , '132212' , '221213' , '221312' , '231212' , '112232' , '122132' , '122231' , '113222' , '123122' , '123221' , '223211' , '221132' , '221231' , '213212' , '223112' , '312131' , '311222' , '321122' , '321221' , '312212' , '322112' , '322211' , '212123' , '212321' , '232121' , '111323' , '131123' , '131321' , '112313' , '132113' , '132311' , '211313' , '231113' , '231311' , '112133' , '112331' , '132131' , '113123' , '113321' , '133121' , '313121' , '211331' , '231131' , '213113' , '213311' , '213131' , '311123' , '311321' , '331121' , '312113' , '312311' , '332111' , '314111' , '221411' , '431111' , '111224' , '111422' , '121124' , '121421' , '141122' , '141221' , '112214' , '112412' , '122114' , '122411' , '142112' , '142211' , '241211' , '221114' , '413111' , '241112' , '134111' , '111242' , '121142' , '121241' , '114212' , '124112' , '124211' , '411212' , '421112' , '421211' , '212141' , '214121' , '412121' , '111143' , '111341' , '131141' , '114113' , '114311' , '411113' , '411311' , '113141' , '114131' , '311141' , '411131' , '211412' , '211214' , '211232' , '233111' , '211133' , '2331112' , ] ; const TBL_A = [ ' ' , '!' , '"' , '#' , '$' , '%' , '&' , "'" , '(' , ')' , '*' , '+' , ',' , '-' , '.' , '/' , '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , ':' , ';' , '<' , '=' , '>' , '?' , '@' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z' , '[' , '\\' , ']' , '^' , '_' , 'NUL' , 'SOH' , 'STX' , 'ETX' , 'EOT' , 'ENQ' , 'ACK' , 'BEL' , 'BS' , 'HT' , 'LF' , 'VT' , 'FF' , 'CR' , 'SO' , 'SI' , 'DLE' , 'DC1' , 'DC2' , 'DC3' , 'DC4' , 'NAK' , 'SYN' , 'ETB' , 'CAN' , 'EM' , 'SUB' , 'ESC' , 'FS' , 'GS' , 'RS' , 'US' , 'FNC 3' , 'FNC 2' , 'Shift B' , 'Code C' , 'Code B' , 'FNC 4' , 'FNC 1' , 'Code A' , 'Code B' , 'Code C' , 'Stop' , 'Reverse Stop' , ] ; const TBL_B = [ ' ' , '!' , '"' , '#' , '$' , '%' , '&' , "'" , '(' , ')' , '*' , '+' , ',' , '-' , '.' , '/' , '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , ':' , ';' , '<' , '=' , '>' , '?' , '@' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' , 'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' , 'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' , 'X' , 'Y' , 'Z' , '[' , '\\' , ']' , '^' , '_' , '`' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z' , '{' , '|' , '}' , '~' , 'DEL' , 'FNC 3' , 'FNC 2' , 'Shift A' , 'Code C' , 'FNC 4' , 'Code A' , 'FNC 1' , 'Code A' , 'Code B' , 'Code C' , 'Stop' , 'Reverse Stop' , ] ; const TBL_C = [ '00' , '01' , '02' , '03' , '04' , '05' , '06' , '07' , '08' , '09' , '10' , '11' , '12' , '13' , '14' , '15' , '16' , '17' , '18' , '19' , '20' , '21' , '22' , '23' , '24' , '25' , '26' , '27' , '28' , '29' , '30' , '31' , '32' , '33' , '34' , '35' , '36' , '37' , '38' , '39' , '40' , '41' , '42' , '43' , '44' , '45' , '46' , '47' , '48' , '49' , '50' , '51' , '52' , '53' , '54' , '55' , '56' , '57' , '58' , '59' , '60' , '61' , '62' , '63' , '64' , '65' , '66' , '67' , '68' , '69' , '70' , '71' , '72' , '73' , '74' , '75' , '76' , '77' , '78' , '79' , '80' , '81' , '82' , '83' , '84' , '85' , '86' , '87' , '88' , '89' , '90' , '91' , '92' , '93' , '94' , '95' , '96' , '97' , '98' , '99' , 'Code B' , 'Code A' , 'FNC 1' , 'Code A' , 'Code B' , 'Code C' , 'Stop' , 'Reverse Stop' , ] ; const computeGroup = ( lines ) : number [ ] => { const count = lines . length - 13 ; const factor = lines . reduce ( ( pre , item , i ) => { if ( i >= count ) return pre ; return pre + item ; } , 0 ) / ( Math . ceil ( count / 6 ) * 11 ) ; return lines . map ( item => Math . round ( item / factor ) || 1 ) ; } ; export function decoder ( lines ) { const code = [ ] ; let lookupTBL = TBL_B ; let letterKey ; let letterCodePrev ; const computedLines = computeGroup ( lines ) ; if ( ! computedLines ) return '' ; computedLines . pop ( ) ; for ( let i = 0 ; i * 6 < computedLines . length - 13 ; i += 1 ) { letterKey = computedLines . slice ( i * 6 , ( i + 1 ) * 6 ) . join ( '' ) ; const keyIndex = WIDTH_TBL . indexOf ( letterKey ) ; const letterCode = lookupTBL [ keyIndex ] ; switch ( letterCode ) { case 'Code A' : lookupTBL = TBL_A ; break ; case 'Code B' : lookupTBL = TBL_B ; break ; case 'Code C' : lookupTBL = TBL_C ; break ; case 'FNC 4' : break ; default : if ( letterCode ) { if ( letterCodePrev === 'FNC 4' ) { code . push ( letterCode . charCodeAt ( 0 ) + 128 ) ; } else { code . push ( letterCode ) ; } letterCodePrev = letterCode ; } else { code . push ( '?' ) ; } break ; } } return code . join ( '' ) ; }