From 7bbf061f8d6c22321d369e0ec1797aea3772d2f6 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Thu, 19 Dec 2019 16:14:59 +0500 Subject: [PATCH 01/44] functions for delta-strings (compressing delta-string) --- scripts/encode.js | 52 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/scripts/encode.js b/scripts/encode.js index 8b87a8a..d0a17d6 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -27,20 +27,20 @@ const encode = tokens => { */ const encodeString = tokens => { const min = tokens[0]; - const sortedtokens = tokens.sort((a, b) => a - b); + const sortedTokens = tokens.sort((a, b) => a - b); let compressedString = `${min}`; let rangeStart = false; let values = []; - sortedtokens.forEach((id, index) => { + sortedTokens.forEach((id, index) => { const newId = id - min; - if (rangeStart === false && sortedtokens[index + 1] === id + 1) { + if (rangeStart === false && sortedTokens[index + 1] === id + 1) { rangeStart = newId; - } else if (rangeStart === false && sortedtokens[index + 1] !== id + 1) { + } else if (rangeStart === false && sortedTokens[index + 1] !== id + 1) { values.push(newId); - } else if (rangeStart !== false && sortedtokens[index + 1] !== id + 1) { + } else if (rangeStart !== false && sortedTokens[index + 1] !== id + 1) { values.push([rangeStart, newId]); rangeStart = false; } @@ -60,9 +60,10 @@ const encodeString = tokens => { * @return {string} compressed string */ const encodeDelta = tokens => { - const sortedtokens = tokens.sort((a, b) => a - b); - - _xBlocks(_deltaCompression(sortedtokens)); + const sortedTokens = tokens.sort((a, b) => a - b); + const chunks = _xBlocks(sortedTokens); + const compressedString = _compressToString(chunks); + return compressedString; }; /** @@ -74,7 +75,6 @@ const encodeDelta = tokens => { */ const _xBlocks = tokens => { let buf = [], - last, tokensCopy = []; tokens.forEach((token, i) => { if (i !== 0 && (token !== tokens[i - 1] || i === tokens.length - 1)) { @@ -86,6 +86,38 @@ const _xBlocks = tokens => { return tokensCopy; }; +/** + * Compress chunks to delta-strings + * + * @param chunks + * @return {string} compressedString + * @private + */ +const _compressToString = chunks => { + let del = ',', + newDel = null, + compressedString = ''; + + chunks.forEach((chunk) => { + if (chunk.indexOf('x') > -1) { + let [x, val] = chunk.split('x'); + if (x.length === val.length) { + newDel = (val.length===1 ? '.' : (val.length===2 ? ':' : ',')); + } else { + newDel = ','; + } + } else { + newDel = (chunk.length===1 ? '.' : (chunk.length===2 ? ':' : ',')); + } + if (newDel === ',' || newDel !== del) { + compressedString += newDel; + } + compressedString += chunk; + del = newDel; + }); + return `~${compressedString}`; +}; + // Tests DONE // encode([]); @@ -96,5 +128,5 @@ const _xBlocks = tokens => { // encode([1, 3, 5, 7]); // encode([1, 2, 3, 5, 6, 7]); // encode([1, 2, 3, 5, 6, 7, 9]); -_xBlocks([1, 1, 2]); + From c4cff193afca8003ec6f2a0f48dfe61efd9f11db Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Thu, 19 Dec 2019 16:41:12 +0500 Subject: [PATCH 02/44] function deltaCompression (sorting array and return array of differences) --- scripts/encode.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/scripts/encode.js b/scripts/encode.js index d0a17d6..79e5b34 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -60,12 +60,28 @@ const encodeString = tokens => { * @return {string} compressed string */ const encodeDelta = tokens => { - const sortedTokens = tokens.sort((a, b) => a - b); + const sortedTokens = _deltaCompression(tokens); const chunks = _xBlocks(sortedTokens); const compressedString = _compressToString(chunks); return compressedString; }; +/** + * Converting array of tokens to sorted array of difference tokens + * + * @param tokens + * @return {[]} sorted array of difference tokens + * @private + */ +const _deltaCompression = tokens => { + tokens.sort(); + let diffTokens = []; + tokens.forEach((token, i) => { + i !== 0 ? diffTokens.push(token-tokens[i-1]) : diffTokens.push(token); + }); + return diffTokens; +}; + /** * Forming x-blocks from difference tokens * @@ -129,4 +145,3 @@ const _compressToString = chunks => { // encode([1, 2, 3, 5, 6, 7]); // encode([1, 2, 3, 5, 6, 7, 9]); - From 4f65c1c2456d3b029bb55d1970dde53112a86ca6 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Thu, 19 Dec 2019 17:03:14 +0500 Subject: [PATCH 03/44] selecting modes (simple_string=1, delta_string=2) --- scripts/encode.js | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/scripts/encode.js b/scripts/encode.js index 79e5b34..26129bd 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -1,22 +1,25 @@ +const MODE_SIMPLE_STRING = 1; +const MODE_DELTA_STRING = 2; + /** * Encode array tokens to string * * @param tokens array of tokens + * @param mode where 1 - encode to simple string, 2 - encode to delta string * @return {string} encoding string */ -const encode = tokens => { +const encode = (tokens, mode = MODE_SIMPLE_STRING) => { if (!tokens || !Array.isArray(tokens)) { console.error('tokens argument should be an array of integers'); } - if (tokens.length === 0) return ''; - - if (tokens.length < 3) { - return tokens.join(','); + if (mode === MODE_SIMPLE_STRING) { + return(encodeString(tokens)); } - - encodeString(tokens); - encodeDelta(tokens); + else if (mode === MODE_DELTA_STRING) { + return(encodeDelta(tokens)); + } + else console.error('you must select 1 or 2 at second parameter (1 - simple string, 2 - delta string)'); }; /** @@ -26,6 +29,9 @@ const encode = tokens => { * @return {string} compressed string */ const encodeString = tokens => { + if (tokens.length < 3) { + return tokens.join(','); + } const min = tokens[0]; const sortedTokens = tokens.sort((a, b) => a - b); @@ -48,8 +54,6 @@ const encodeString = tokens => { values = values.map(item => (typeof item === 'number' ? item : `${item[0]}-${item[1]}`)); compressedString = `${compressedString}(${values.join(',')})`; - - console.log(compressedString); return compressedString; }; @@ -143,5 +147,7 @@ const _compressToString = chunks => { // encode([1, 2, 3, 4]); // encode([1, 3, 5, 7]); // encode([1, 2, 3, 5, 6, 7]); -// encode([1, 2, 3, 5, 6, 7, 9]); +encode([1, 2, 3, 5, 6, 7, 9], 1); +encode([1, 2, 3, 5, 6, 7, 9], 2); + From c4fdc6af2d80f615eb75cd6b2fc3f4c1f097ad61 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Thu, 19 Dec 2019 17:50:08 +0500 Subject: [PATCH 04/44] add parameter baseInt ( works "Strings with base of numbers" ) --- scripts/decode.js | 59 +++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/scripts/decode.js b/scripts/decode.js index c188ac2..e2717e2 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -4,6 +4,7 @@ const DELTA_LIST_BY_TWO = ':'; const ZIP_START_DELIMITER = '('; const ZIP_END_DELIMITER = ')'; +const intBase = 10; /** * Parse string to array of encoding numbers @@ -17,9 +18,13 @@ const decode = string => { } let items; + let intBase = 10; + // Parse base for int if (string.startsWith('x')) { - // Дописать функционал + let base; + [base, string] = string.split('x'); + intBase = base.slice(1); } // Parse empty string as empty list @@ -83,14 +88,14 @@ const parseToken = token => { } if (token.indexOf('-') > -1) { let [start, stop] = token.split('-'); - start = parseInt(start, 10); - stop = parseInt(stop, 10); + start = parseInt(start, intBase); + stop = parseInt(stop, intBase); for (let i = start; i <= stop; i += 1) { tokens.push(i); } } - else tokens = [parseInt(token)]; + else tokens = [parseInt(token, intBase)]; return tokens; }; @@ -139,12 +144,12 @@ const parseDeltaChunks = chunk => { } else if (blocks.length === 2) { - let num = parseInt(blocks[1], 10); + let num = parseInt(blocks[1], intBase); for (let i = 0; i < blocks[0]; i++) { tokens.push(num); } } - else tokens = [parseInt(chunk, 10)]; + else tokens = [parseInt(chunk, intBase)]; return tokens; @@ -186,7 +191,7 @@ const deltaChunks = string => { const wrap = (string, count) => { let list = []; for (let i = 0; i { // Tests // Done -decode('123'); -decode('123,456'); -decode('1-3'); -decode('1-3,5-9'); -decode('120(0,3,5,8,9)'); -decode('12(1,4),140(0,2,5)'); -decode('120(0,3,6),130-132'); -decode('120(0-6)'); -decode('~155'); -decode('~1,2,3'); -decode('~1'); -decode('~.1'); -decode('~.123'); -decode('~.123:1012'); -decode('~.12:10.45'); -decode('~.12:10.45,146,234.14'); -decode('~3x1'); -decode('1-10'); -decode('1,2,5,7-13'); -decode('14(0-8,18)'); +// decode('123'); +// decode('123,456'); +// decode('1-3'); +// decode('1-3,5-9'); +// decode('120(0,3,5,8,9)'); +// decode('12(1,4),140(0,2,5)'); +// decode('120(0,3,6),130-132'); +// decode('120(0-6)'); +// decode('~155'); +// decode('~1,2,3'); +// decode('~1'); +// decode('~.1'); +// decode('~.123'); +// decode('~.123:1012'); +// decode('~.12:10.45'); +// decode('~.12:10.45,146,234.14'); +// decode('~3x1'); +// decode('1-10'); +// decode('1,2,5,7-13'); +// decode('14(0-8,18)'); // In process // Strings with base of numbers // decode('x16;3,f'); From c1eebf3c2fc2fef6faa21bf0bc0e857acf25d9fb Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Thu, 19 Dec 2019 18:53:46 +0500 Subject: [PATCH 05/44] add function for Delta strings with x-ranges --- scripts/decode.js | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/scripts/decode.js b/scripts/decode.js index e2717e2..d93f35d 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -139,9 +139,38 @@ const parseDeltaChunks = chunk => { tokens = wrap(chunk, listBy); } else { - // Дописать функционал - } + let items = []; + items = blocks.map((block, i) => (wrap(block, listBy))); + items.forEach((item, i) => { + if (i > 0) { + let c = tokens.pop(); + for (let j = 0; j < c; j++) + tokens.push(item[0]); + item = item.slice(1); + } + tokens.push(...item); + }); + return tokens; + // let nums = wrap(blocks[1], listBy); + // let num = _getInt(nums[0]); + // let list = []; + // for (let i = 0; i < blocks[0]; i++) { + // items.push(num); + // } + // items.push(...nums.slice(1)); + // + // let tokens = []; + // blocks.forEach((block) => items = items.concat(wrap(block,listBy))); + // items.forEach((block, i) => { + // if (i > 0) { + // let c = items.pop(); + // for (let j=0; j < c; j++) items.push(block[0]); + // block = block.split(1); + // } + // items.push(...block); + // }); + } } else if (blocks.length === 2) { let num = parseInt(blocks[1], intBase); @@ -152,7 +181,6 @@ const parseDeltaChunks = chunk => { else tokens = [parseInt(chunk, intBase)]; return tokens; - }; /** @@ -219,14 +247,16 @@ const wrap = (string, count) => { // decode('1-10'); // decode('1,2,5,7-13'); // decode('14(0-8,18)'); +// decode('~.13x3'); +// decode('~.2x12'); +// decode('~12,3x4,'); +// decode('~.54x13:1010x11'); + // In process // Strings with base of numbers // decode('x16;3,f'); // decode('x2;11,101'); -// Delta strings with x-ranges -// decode('~.13x3'); -// decode('~.2x12'); -// decode('~12,3x4,'); + From 481acd3a1b05493395338b4ab590b9f5429385fa Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Thu, 19 Dec 2019 18:54:15 +0500 Subject: [PATCH 06/44] fix parameter intBase in decode.js --- scripts/decode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/decode.js b/scripts/decode.js index d93f35d..56da1e3 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -18,7 +18,7 @@ const decode = string => { } let items; - let intBase = 10; + var intBase = 10; // Parse base for int if (string.startsWith('x')) { From 1987410d7bd595dd46069264afc2343ba38ce91f Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Thu, 19 Dec 2019 19:26:57 +0500 Subject: [PATCH 07/44] fix files with eslint --- scripts/decode.js | 272 ++++++++++++++++++++-------------------------- scripts/encode.js | 166 ++++++++++++++-------------- 2 files changed, 201 insertions(+), 237 deletions(-) diff --git a/scripts/decode.js b/scripts/decode.js index 56da1e3..ebf8979 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -4,7 +4,7 @@ const DELTA_LIST_BY_TWO = ':'; const ZIP_START_DELIMITER = '('; const ZIP_END_DELIMITER = ')'; -const intBase = 10; +let intBase = 10; /** * Parse string to array of encoding numbers @@ -12,32 +12,27 @@ const intBase = 10; * @param string * @returns {[]|*[]} */ -const decode = string => { - if (!string) { - return []; - } - let items; - - var intBase = 10; - - // Parse base for int - if (string.startsWith('x')) { - let base; - [base, string] = string.split('x'); - intBase = base.slice(1); - } - - // Parse empty string as empty list - if (string.startsWith('~')) { - items = parseDelta(string.slice(1)); - console.log(items); - } - else { - items = parseString(string); - console.log(items) - } - - return items; +const decode = (string) => { + if (!string) { + return []; + } + let items; + + // Parse base for int + if (string.startsWith('x')) { + let base; + [base, string] = string.split('x'); + intBase = base.slice(1); + } + + // Parse empty string as empty list + if (string.startsWith('~')) { + items = parseDelta(string.slice(1)); + } else { + items = parseString(string); + } + + return items; }; /** @@ -46,28 +41,28 @@ const decode = string => { * @param string * @return {[]} */ -const parseString = string => { - let buff = '', tokens = [], zipBuff = []; - - for (const ltr of string) { - if (ltr === ZIP_START_DELIMITER) zipBuff.push(1); - if (ltr === ZIP_END_DELIMITER) zipBuff.pop(); - if (zipBuff.length === 0 && ltr === NUM_DELIMITER) { - parseToken(buff).forEach((item) => { - tokens.push(item); - }); - buff = ''; - } - else buff += ltr; - } - - if (buff) { - parseToken(buff).forEach((item) => { - tokens.push(item); - }); - } +const parseString = (string) => { + let buff = ''; const tokens = []; const + zipBuff = []; + + for (const ltr of string) { + if (ltr === ZIP_START_DELIMITER) zipBuff.push(1); + if (ltr === ZIP_END_DELIMITER) zipBuff.pop(); + if (zipBuff.length === 0 && ltr === NUM_DELIMITER) { + parseToken(buff).forEach((item) => { + tokens.push(item); + }); + buff = ''; + } else buff += ltr; + } + + if (buff) { + parseToken(buff).forEach((item) => { + tokens.push(item); + }); + } - return tokens; + return tokens; }; @@ -77,26 +72,25 @@ const parseString = string => { * @param token * @return {[]} array with tokens */ -const parseToken = token => { - let tokens = []; - if (token.indexOf(ZIP_START_DELIMITER) > -1) { - let [base, subString] = token.split(ZIP_START_DELIMITER); - base = parseInt(base, 10); - let items = parseString(subString.slice(0, subString.length-1)); - items.forEach((item) => tokens.push(item+base)); - return tokens; - } - if (token.indexOf('-') > -1) { - let [start, stop] = token.split('-'); - start = parseInt(start, intBase); - stop = parseInt(stop, intBase); - - for (let i = start; i <= stop; i += 1) { - tokens.push(i); - } - } - else tokens = [parseInt(token, intBase)]; +const parseToken = (token) => { + let tokens = []; + if (token.indexOf(ZIP_START_DELIMITER) > -1) { + let [base, subString] = token.split(ZIP_START_DELIMITER); + base = parseInt(base, 10); + const items = parseString(subString.slice(0, subString.length - 1)); + items.forEach((item) => tokens.push(item + base)); return tokens; + } + if (token.indexOf('-') > -1) { + let [start, stop] = token.split('-'); + start = parseInt(start, intBase); + stop = parseInt(stop, intBase); + + for (let i = start; i <= stop; i += 1) { + tokens.push(i); + } + } else tokens = [parseInt(token, intBase)]; + return tokens; }; /** @@ -105,19 +99,19 @@ const parseToken = token => { * @param string * @return {[]} array with tokens */ -const parseDelta = string => { - let tokens = [], - chunks = deltaChunks(string); +const parseDelta = (string) => { + let tokens = []; + const chunks = deltaChunks(string); - chunks.forEach((chunk) => tokens = tokens.concat(parseDeltaChunks(chunk))); + chunks.forEach((chunk) => tokens = tokens.concat(parseDeltaChunks(chunk))); - let last = 0; - tokens.forEach((token, i) => { - tokens[i]=token+last; - last=tokens[i]; - }); + let last = 0; + tokens.forEach((token, i) => { + tokens[i] = token + last; + last = tokens[i]; + }); - return tokens; + return tokens; }; @@ -127,60 +121,38 @@ const parseDelta = string => { * @param chunk * @return {[]} array with tokens */ -const parseDeltaChunks = chunk => { - let listBy, blocks, tokens = []; - if (chunk.startsWith(DELTA_LIST_BY_ONE)) listBy = 1; - if (chunk.startsWith(DELTA_LIST_BY_TWO)) listBy = 2; - if (listBy) chunk = chunk.slice(1); - blocks = chunk.split('x'); - - if (listBy) { - if (blocks.length === 1) { - tokens = wrap(chunk, listBy); - } - else { - let items = []; - items = blocks.map((block, i) => (wrap(block, listBy))); - items.forEach((item, i) => { - if (i > 0) { - let c = tokens.pop(); - for (let j = 0; j < c; j++) - tokens.push(item[0]); - item = item.slice(1); - } - tokens.push(...item); - }); - return tokens; - - // let nums = wrap(blocks[1], listBy); - // let num = _getInt(nums[0]); - // let list = []; - // for (let i = 0; i < blocks[0]; i++) { - // items.push(num); - // } - // items.push(...nums.slice(1)); - // - // let tokens = []; - // blocks.forEach((block) => items = items.concat(wrap(block,listBy))); - // items.forEach((block, i) => { - // if (i > 0) { - // let c = items.pop(); - // for (let j=0; j < c; j++) items.push(block[0]); - // block = block.split(1); - // } - // items.push(...block); - // }); +const parseDeltaChunks = (chunk) => { + let listBy; + let tokens = []; + if (chunk.startsWith(DELTA_LIST_BY_ONE)) listBy = 1; + if (chunk.startsWith(DELTA_LIST_BY_TWO)) listBy = 2; + if (listBy) chunk = chunk.slice(1); + const blocks = chunk.split('x'); + + if (listBy) { + if (blocks.length === 1) { + tokens = wrap(chunk, listBy); + } else { + let items = []; + items = blocks.map((block, i) => (wrap(block, listBy))); + items.forEach((item, i) => { + if (i > 0) { + const c = tokens.pop(); + for (let j = 0; j < c; j++) tokens.push(item[0]); + item = item.slice(1); } + tokens.push(...item); + }); + return tokens; } - else if (blocks.length === 2) { - let num = parseInt(blocks[1], intBase); - for (let i = 0; i < blocks[0]; i++) { - tokens.push(num); - } + } else if (blocks.length === 2) { + const num = parseInt(blocks[1], intBase); + for (let i = 0; i < blocks[0]; i++) { + tokens.push(num); } - else tokens = [parseInt(chunk, intBase)]; + } else tokens = [parseInt(chunk, intBase)]; - return tokens; + return tokens; }; /** @@ -189,24 +161,22 @@ const parseDeltaChunks = chunk => { * @param string for split into chunks * @return [] of chunks */ -const deltaChunks = string => { - let chunks = [], - buf = ''; - for (let ltr of string) { - if (ltr === NUM_DELIMITER) { - (buf!=='') && chunks.push(buf); - buf = ''; - } - else if (ltr === DELTA_LIST_BY_ONE || ltr === DELTA_LIST_BY_TWO) { - (buf!=='') && chunks.push(buf); - buf = ltr; - } - else { - buf += ltr; - } +const deltaChunks = (string) => { + const chunks = []; + let buf = ''; + for (const ltr of string) { + if (ltr === NUM_DELIMITER) { + (buf !== '') && chunks.push(buf); + buf = ''; + } else if (ltr === DELTA_LIST_BY_ONE || ltr === DELTA_LIST_BY_TWO) { + (buf !== '') && chunks.push(buf); + buf = ltr; + } else { + buf += ltr; } - if (buf !== '') chunks.push(buf); - return chunks; + } + if (buf !== '') chunks.push(buf); + return chunks; }; /** @@ -217,11 +187,11 @@ const deltaChunks = string => { * @returns {[]} list of several strings */ const wrap = (string, count) => { - let list = []; - for (let i = 0; i { // Strings with base of numbers // decode('x16;3,f'); // decode('x2;11,101'); - - - - diff --git a/scripts/encode.js b/scripts/encode.js index 26129bd..eff6222 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -9,17 +9,17 @@ const MODE_DELTA_STRING = 2; * @return {string} encoding string */ const encode = (tokens, mode = MODE_SIMPLE_STRING) => { - if (!tokens || !Array.isArray(tokens)) { - console.error('tokens argument should be an array of integers'); - } - if (tokens.length === 0) return ''; - if (mode === MODE_SIMPLE_STRING) { - return(encodeString(tokens)); - } - else if (mode === MODE_DELTA_STRING) { - return(encodeDelta(tokens)); - } - else console.error('you must select 1 or 2 at second parameter (1 - simple string, 2 - delta string)'); + if (!tokens || !Array.isArray(tokens)) { + console.error('tokens argument should be an array of integers'); + } + if (tokens.length === 0) return ''; + if (mode === MODE_SIMPLE_STRING) { + return (encodeString(tokens)); + } + if (mode === MODE_DELTA_STRING) { + return (encodeDelta(tokens)); + } + console.error('you must select 1 or 2 at second parameter (1 - simple string, 2 - delta string)'); }; /** @@ -28,33 +28,33 @@ const encode = (tokens, mode = MODE_SIMPLE_STRING) => { * @param tokens * @return {string} compressed string */ -const encodeString = tokens => { - if (tokens.length < 3) { - return tokens.join(','); - } - const min = tokens[0]; - const sortedTokens = tokens.sort((a, b) => a - b); +const encodeString = (tokens) => { + if (tokens.length < 3) { + return tokens.join(','); + } + const min = tokens[0]; + const sortedTokens = tokens.sort((a, b) => a - b); - let compressedString = `${min}`; - let rangeStart = false; - let values = []; + let compressedString = `${min}`; + let rangeStart = false; + let values = []; - sortedTokens.forEach((id, index) => { - const newId = id - min; + sortedTokens.forEach((id, index) => { + const newId = id - min; - if (rangeStart === false && sortedTokens[index + 1] === id + 1) { - rangeStart = newId; - } else if (rangeStart === false && sortedTokens[index + 1] !== id + 1) { - values.push(newId); - } else if (rangeStart !== false && sortedTokens[index + 1] !== id + 1) { - values.push([rangeStart, newId]); - rangeStart = false; - } - }); + if (rangeStart === false && sortedTokens[index + 1] === id + 1) { + rangeStart = newId; + } else if (rangeStart === false && sortedTokens[index + 1] !== id + 1) { + values.push(newId); + } else if (rangeStart !== false && sortedTokens[index + 1] !== id + 1) { + values.push([rangeStart, newId]); + rangeStart = false; + } + }); - values = values.map(item => (typeof item === 'number' ? item : `${item[0]}-${item[1]}`)); - compressedString = `${compressedString}(${values.join(',')})`; - return compressedString; + values = values.map((item) => (typeof item === 'number' ? item : `${item[0]}-${item[1]}`)); + compressedString = `${compressedString}(${values.join(',')})`; + return compressedString; }; /** @@ -63,11 +63,11 @@ const encodeString = tokens => { * @param tokens * @return {string} compressed string */ -const encodeDelta = tokens => { - const sortedTokens = _deltaCompression(tokens); - const chunks = _xBlocks(sortedTokens); - const compressedString = _compressToString(chunks); - return compressedString; +const encodeDelta = (tokens) => { + const sortedTokens = _deltaCompression(tokens); + const chunks = _xBlocks(sortedTokens); + const compressedString = _compressToString(chunks); + return compressedString; }; /** @@ -77,13 +77,13 @@ const encodeDelta = tokens => { * @return {[]} sorted array of difference tokens * @private */ -const _deltaCompression = tokens => { - tokens.sort(); - let diffTokens = []; - tokens.forEach((token, i) => { - i !== 0 ? diffTokens.push(token-tokens[i-1]) : diffTokens.push(token); - }); - return diffTokens; +const _deltaCompression = (tokens) => { + tokens.sort(); + const diffTokens = []; + tokens.forEach((token, i) => { + i !== 0 ? diffTokens.push(token - tokens[i - 1]) : diffTokens.push(token); + }); + return diffTokens; }; /** @@ -93,17 +93,17 @@ const _deltaCompression = tokens => { * @return {[]} * @private */ -const _xBlocks = tokens => { - let buf = [], - tokensCopy = []; - tokens.forEach((token, i) => { - if (i !== 0 && (token !== tokens[i - 1] || i === tokens.length - 1)) { - buf.length > 1 ? tokensCopy.push(`${buf.length}x${buf[0]}`) : tokensCopy.push(`${buf[0]}`); - buf = [token]; - } else buf.push(token); - }); - if (buf.length !== 0) tokensCopy.push(`${buf}`); - return tokensCopy; +const _xBlocks = (tokens) => { + let buf = []; + const tokensCopy = []; + tokens.forEach((token, i) => { + if (i !== 0 && (token !== tokens[i - 1] || i === tokens.length - 1)) { + buf.length > 1 ? tokensCopy.push(`${buf.length}x${buf[0]}`) : tokensCopy.push(`${buf[0]}`); + buf = [token]; + } else buf.push(token); + }); + if (buf.length !== 0) tokensCopy.push(`${buf}`); + return tokensCopy; }; /** @@ -113,29 +113,29 @@ const _xBlocks = tokens => { * @return {string} compressedString * @private */ -const _compressToString = chunks => { - let del = ',', - newDel = null, - compressedString = ''; +const _compressToString = (chunks) => { + let del = ','; + let newDel = null; + let compressedString = ''; - chunks.forEach((chunk) => { - if (chunk.indexOf('x') > -1) { - let [x, val] = chunk.split('x'); - if (x.length === val.length) { - newDel = (val.length===1 ? '.' : (val.length===2 ? ':' : ',')); - } else { - newDel = ','; - } - } else { - newDel = (chunk.length===1 ? '.' : (chunk.length===2 ? ':' : ',')); - } - if (newDel === ',' || newDel !== del) { - compressedString += newDel; - } - compressedString += chunk; - del = newDel; - }); - return `~${compressedString}`; + chunks.forEach((chunk) => { + if (chunk.indexOf('x') > -1) { + const [x, val] = chunk.split('x'); + if (x.length === val.length) { + newDel = (val.length === 1 ? '.' : (val.length === 2 ? ':' : ',')); + } else { + newDel = ','; + } + } else { + newDel = (chunk.length === 1 ? '.' : (chunk.length === 2 ? ':' : ',')); + } + if (newDel === ',' || newDel !== del) { + compressedString += newDel; + } + compressedString += chunk; + del = newDel; + }); + return `~${compressedString}`; }; @@ -144,10 +144,8 @@ const _compressToString = chunks => { // encode([1]); // encode([1, 2]); // encode([1, 2, 3]); -// encode([1, 2, 3, 4]); +console.log(encode([1, 2, 3, 4])); // encode([1, 3, 5, 7]); // encode([1, 2, 3, 5, 6, 7]); -encode([1, 2, 3, 5, 6, 7, 9], 1); -encode([1, 2, 3, 5, 6, 7, 9], 2); - - +console.log(encode([1, 2, 3, 5, 6, 7, 9], 1)); +console.log(encode([1, 2, 3, 5, 6, 7, 9], 2)); From 504ce26435de6733e9a11ddd1282ef8027ccf1c0 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 11:07:42 +0500 Subject: [PATCH 08/44] encode to class --- scripts/encode.js | 274 ++++++++++++++++++++++++---------------------- 1 file changed, 145 insertions(+), 129 deletions(-) diff --git a/scripts/encode.js b/scripts/encode.js index eff6222..93cc3b0 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -1,142 +1,155 @@ -const MODE_SIMPLE_STRING = 1; -const MODE_DELTA_STRING = 2; +class Encode { + /** + * @return {string} + */ + constructor( + tokens, + mode, + ) { + this.MODE_SIMPLE_STRING = 1; + this.MODE_DELTA_STRING = 2; -/** - * Encode array tokens to string - * - * @param tokens array of tokens - * @param mode where 1 - encode to simple string, 2 - encode to delta string - * @return {string} encoding string - */ -const encode = (tokens, mode = MODE_SIMPLE_STRING) => { - if (!tokens || !Array.isArray(tokens)) { - console.error('tokens argument should be an array of integers'); + this.tokens = tokens; + this.mode = mode ? mode : this.MODE_SIMPLE_STRING; } - if (tokens.length === 0) return ''; - if (mode === MODE_SIMPLE_STRING) { - return (encodeString(tokens)); - } - if (mode === MODE_DELTA_STRING) { - return (encodeDelta(tokens)); - } - console.error('you must select 1 or 2 at second parameter (1 - simple string, 2 - delta string)'); -}; -/** - * Encoding to simple string - * - * @param tokens - * @return {string} compressed string - */ -const encodeString = (tokens) => { - if (tokens.length < 3) { - return tokens.join(','); + /** + * Encode array tokens to string + * + * @param tokens array of tokens + * @param mode where 1 - encode to simple string, 2 - encode to delta string + * @return {string} encoding string + */ + parse(tokens = this.tokens, mode = this.mode) { + if (!tokens || !Array.isArray(tokens)) { + console.error('tokens argument should be an array of integers'); + } + if (tokens.length === 0) return ''; + if (mode === this.MODE_SIMPLE_STRING) { + return (this.constructor.encodeString(tokens)); + } + if (mode === this.MODE_DELTA_STRING) { + return (this.constructor.encodeDelta(tokens)); + } + console.error('you must select 1 or 2 at second parameter (1 - simple string, 2 - delta string)'); + return ''; } - const min = tokens[0]; - const sortedTokens = tokens.sort((a, b) => a - b); - let compressedString = `${min}`; - let rangeStart = false; - let values = []; + /** + * Encoding to simple string + * + * @param tokens + * @return {string} compressed string + */ + static encodeString(tokens) { + if (tokens.length < 3) { + return tokens.join(','); + } + const min = tokens[0]; + const sortedTokens = tokens.sort((a, b) => a - b); - sortedTokens.forEach((id, index) => { - const newId = id - min; + let compressedString = `${min}`; + let rangeStart = false; + let values = []; - if (rangeStart === false && sortedTokens[index + 1] === id + 1) { - rangeStart = newId; - } else if (rangeStart === false && sortedTokens[index + 1] !== id + 1) { - values.push(newId); - } else if (rangeStart !== false && sortedTokens[index + 1] !== id + 1) { - values.push([rangeStart, newId]); - rangeStart = false; - } - }); + sortedTokens.forEach((id, index) => { + const newId = id - min; + + if (rangeStart === false && sortedTokens[index + 1] === id + 1) { + rangeStart = newId; + } else if (rangeStart === false && sortedTokens[index + 1] !== id + 1) { + values.push(newId); + } else if (rangeStart !== false && sortedTokens[index + 1] !== id + 1) { + values.push([rangeStart, newId]); + rangeStart = false; + } + }); - values = values.map((item) => (typeof item === 'number' ? item : `${item[0]}-${item[1]}`)); - compressedString = `${compressedString}(${values.join(',')})`; - return compressedString; -}; + values = values.map((item) => (typeof item === 'number' ? item : `${item[0]}-${item[1]}`)); + compressedString = `${compressedString}(${values.join(',')})`; + return compressedString; + } -/** - * Encoding to delta-string - * - * @param tokens - * @return {string} compressed string - */ -const encodeDelta = (tokens) => { - const sortedTokens = _deltaCompression(tokens); - const chunks = _xBlocks(sortedTokens); - const compressedString = _compressToString(chunks); - return compressedString; -}; + /** + * Encoding to delta-string + * + * @param tokens + * @return {string} compressed string + */ + static encodeDelta(tokens) { + const sortedTokens = this.deltaCompression(tokens); + const chunks = this.xBlocks(sortedTokens); + return this.compressToString(chunks); + } -/** - * Converting array of tokens to sorted array of difference tokens - * - * @param tokens - * @return {[]} sorted array of difference tokens - * @private - */ -const _deltaCompression = (tokens) => { - tokens.sort(); - const diffTokens = []; - tokens.forEach((token, i) => { - i !== 0 ? diffTokens.push(token - tokens[i - 1]) : diffTokens.push(token); - }); - return diffTokens; -}; + /** + * Converting array of tokens to sorted array of difference tokens + * + * @param tokens + * @return {[]} sorted array of difference tokens + * @private + */ + static deltaCompression(tokens) { + tokens.sort(); + const diffTokens = []; + tokens.forEach((token, i) => { + i !== 0 ? diffTokens.push(token - tokens[i - 1]) : diffTokens.push(token); + }); + return diffTokens; + } -/** - * Forming x-blocks from difference tokens - * - * @param tokens - * @return {[]} - * @private - */ -const _xBlocks = (tokens) => { - let buf = []; - const tokensCopy = []; - tokens.forEach((token, i) => { - if (i !== 0 && (token !== tokens[i - 1] || i === tokens.length - 1)) { - buf.length > 1 ? tokensCopy.push(`${buf.length}x${buf[0]}`) : tokensCopy.push(`${buf[0]}`); - buf = [token]; - } else buf.push(token); - }); - if (buf.length !== 0) tokensCopy.push(`${buf}`); - return tokensCopy; -}; + /** + * Forming x-blocks from difference tokens + * + * @param tokens + * @return {[]} + * @private + */ + static xBlocks(tokens) { + let buf = []; + const tokensCopy = []; + tokens.forEach((token, i) => { + if (i !== 0 && (token !== tokens[i - 1] || i === tokens.length - 1)) { + buf.length > 1 ? tokensCopy.push(`${buf.length}x${buf[0]}`) : tokensCopy.push(`${buf[0]}`); + buf = [token]; + } else buf.push(token); + }); + if (buf.length !== 0) tokensCopy.push(`${buf}`); + return tokensCopy; + } -/** - * Compress chunks to delta-strings - * - * @param chunks - * @return {string} compressedString - * @private - */ -const _compressToString = (chunks) => { - let del = ','; - let newDel = null; - let compressedString = ''; + /** + * Compress chunks to delta-strings + * + * @param chunks + * @return {string} compressedString + * @private + */ + static compressToString(chunks) { + let del = ','; + let newDel = null; + let compressedString = ''; - chunks.forEach((chunk) => { - if (chunk.indexOf('x') > -1) { - const [x, val] = chunk.split('x'); - if (x.length === val.length) { - newDel = (val.length === 1 ? '.' : (val.length === 2 ? ':' : ',')); + chunks.forEach((chunk) => { + if (chunk.indexOf('x') > -1) { + const [x, val] = chunk.split('x'); + if (x.length === val.length) { + newDel = (val.length === 1 ? '.' : (val.length === 2 ? ':' : ',')); + } else { + newDel = ','; + } } else { - newDel = ','; + newDel = (chunk.length === 1 ? '.' : (chunk.length === 2 ? ':' : ',')); } - } else { - newDel = (chunk.length === 1 ? '.' : (chunk.length === 2 ? ':' : ',')); - } - if (newDel === ',' || newDel !== del) { - compressedString += newDel; - } - compressedString += chunk; - del = newDel; - }); - return `~${compressedString}`; -}; + if (newDel === ',' || newDel !== del) { + compressedString += newDel; + } + compressedString += chunk; + del = newDel; + }); + return `~${compressedString}`; + } +} // Tests DONE @@ -144,8 +157,11 @@ const _compressToString = (chunks) => { // encode([1]); // encode([1, 2]); // encode([1, 2, 3]); -console.log(encode([1, 2, 3, 4])); -// encode([1, 3, 5, 7]); -// encode([1, 2, 3, 5, 6, 7]); -console.log(encode([1, 2, 3, 5, 6, 7, 9], 1)); -console.log(encode([1, 2, 3, 5, 6, 7, 9], 2)); +// console.log(encode([1, 2, 3, 4])); +// // encode([1, 3, 5, 7]); +// // encode([1, 2, 3, 5, 6, 7]); +// console.log(encode([1, 2, 3, 5, 6, 7, 9], 1)); +// console.log(encode([1, 2, 3, 5, 6, 7, 9], 2)); + +console.log(new Encode([1, 3, 5, 7], 1).parse()); +console.log(new Encode([1, 3, 5, 7], 2).parse()); From db3fb19b5bb05532600a408f7ccb12607edfc456 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 11:42:54 +0500 Subject: [PATCH 09/44] fix encode to class --- scripts/encode.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/scripts/encode.js b/scripts/encode.js index 93cc3b0..7d530a7 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -3,14 +3,11 @@ class Encode { * @return {string} */ constructor( - tokens, - mode, + maxLength = 1000000, ) { this.MODE_SIMPLE_STRING = 1; this.MODE_DELTA_STRING = 2; - - this.tokens = tokens; - this.mode = mode ? mode : this.MODE_SIMPLE_STRING; + this.maxLength = maxLength; } /** @@ -20,11 +17,16 @@ class Encode { * @param mode where 1 - encode to simple string, 2 - encode to delta string * @return {string} encoding string */ - parse(tokens = this.tokens, mode = this.mode) { + parse(tokens, mode = this.MODE_SIMPLE_STRING) { + if (tokens.length === 0) return ''; if (!tokens || !Array.isArray(tokens)) { console.error('tokens argument should be an array of integers'); + return ''; + } + if (tokens.length > this.maxLength) { + console.error('array size is higher than allowed') + return ''; } - if (tokens.length === 0) return ''; if (mode === this.MODE_SIMPLE_STRING) { return (this.constructor.encodeString(tokens)); } @@ -163,5 +165,7 @@ class Encode { // console.log(encode([1, 2, 3, 5, 6, 7, 9], 1)); // console.log(encode([1, 2, 3, 5, 6, 7, 9], 2)); -console.log(new Encode([1, 3, 5, 7], 1).parse()); -console.log(new Encode([1, 3, 5, 7], 2).parse()); + +const obj = new Encode(); +console.log(obj.parse([1, 3, 5, 7], 1)); +console.log(obj.parse([1, 3, 5, 7], 2)); From 77cf8c3198902e772b8cd15e94480640621d407c Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 11:43:20 +0500 Subject: [PATCH 10/44] decode to class --- scripts/decode.js | 556 +++++++++++++++++++++++++++++++--------------- 1 file changed, 379 insertions(+), 177 deletions(-) diff --git a/scripts/decode.js b/scripts/decode.js index ebf8979..bf8bbda 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -1,198 +1,396 @@ -const NUM_DELIMITER = ','; -const DELTA_LIST_BY_ONE = '.'; -const DELTA_LIST_BY_TWO = ':'; -const ZIP_START_DELIMITER = '('; -const ZIP_END_DELIMITER = ')'; - -let intBase = 10; - -/** - * Parse string to array of encoding numbers - * - * @param string - * @returns {[]|*[]} - */ -const decode = (string) => { - if (!string) { - return []; +class Decode { + constructor(maxLength = 1000000) { + this.NUM_DELIMITER = ','; + this.DELTA_LIST_BY_ONE = '.'; + this.DELTA_LIST_BY_TWO = ':'; + this.ZIP_START_DELIMITER = '('; + this.ZIP_END_DELIMITER = ')'; + this.intBase = 10; + this.maxLength = maxLength; + this.countTokens = 0; } - let items; - // Parse base for int - if (string.startsWith('x')) { - let base; - [base, string] = string.split('x'); - intBase = base.slice(1); - } + /** + * Parse string to array of encoding numbers + * + * @param string + * @returns {[]|*[]} + */ + parse(string) { + if (!string) { + return []; + } + let items; - // Parse empty string as empty list - if (string.startsWith('~')) { - items = parseDelta(string.slice(1)); - } else { - items = parseString(string); + // Parse base for int + if (string.startsWith('x')) { + let base; + [base, string] = string.split('x'); + this.intBase = base.slice(1); + } + + // Parse empty string as empty list + if (string.startsWith('~')) { + items = this.parseDelta(string.slice(1)); + } else { + items = this.parseString(string); + } + + return items; } - return items; -}; - -/** - * Parse string to tokens - * - * @param string - * @return {[]} - */ -const parseString = (string) => { - let buff = ''; const tokens = []; const - zipBuff = []; - - for (const ltr of string) { - if (ltr === ZIP_START_DELIMITER) zipBuff.push(1); - if (ltr === ZIP_END_DELIMITER) zipBuff.pop(); - if (zipBuff.length === 0 && ltr === NUM_DELIMITER) { - parseToken(buff).forEach((item) => { + /** + * Parse string to tokens + * + * @param string + * @return {[]} + */ + parseString(string) { + let buff = ''; const tokens = []; const + zipBuff = []; + + for (const ltr of string) { + if (ltr === this.ZIP_START_DELIMITER) zipBuff.push(1); + if (ltr === this.ZIP_END_DELIMITER) zipBuff.pop(); + if (zipBuff.length === 0 && ltr === this.NUM_DELIMITER) { + this.parseToken(buff).forEach((item) => { + tokens.push(item); + }); + buff = ''; + } else buff += ltr; + } + + if (buff) { + this.parseToken(buff).forEach((item) => { tokens.push(item); }); - buff = ''; - } else buff += ltr; + } + return tokens; + } + + /** + * Parse token from string + * + * @param token + * @return {[]} array with tokens + */ + parseToken(token) { + let tokens = []; + if (token.indexOf(this.ZIP_START_DELIMITER) > -1) { + let [base, subString] = token.split(this.ZIP_START_DELIMITER); + base = parseInt(base, 10); + const items = this.parseString(subString.slice(0, subString.length - 1)); + items.forEach((item) => tokens.push(item + base)); + return tokens; + } + if (token.indexOf('-') > -1) { + let [start, stop] = token.split('-'); + start = parseInt(start, this.intBase); + stop = parseInt(stop, this.intBase); + + for (let i = start; i <= stop; i += 1) { + tokens.push(i); + } + } else tokens = [parseInt(token, this.intBase)]; + return tokens; } - if (buff) { - parseToken(buff).forEach((item) => { - tokens.push(item); + /** + * Parse string by delta + * + * @param string + * @return {[]} array with tokens + */ + parseDelta(string) { + let tokens = []; + const chunks = this.deltaChunks(string); + + chunks.forEach((chunk) => tokens = tokens.concat(this.parseDeltaChunks(chunk))); + + let last = 0; + tokens.forEach((token, i) => { + tokens[i] = token + last; + last = tokens[i]; }); + + return tokens; } - return tokens; -}; - - -/** - * Parse token from string - * - * @param token - * @return {[]} array with tokens - */ -const parseToken = (token) => { - let tokens = []; - if (token.indexOf(ZIP_START_DELIMITER) > -1) { - let [base, subString] = token.split(ZIP_START_DELIMITER); - base = parseInt(base, 10); - const items = parseString(subString.slice(0, subString.length - 1)); - items.forEach((item) => tokens.push(item + base)); + /** + * Parse chunk of delta + * + * @param chunk + * @return {[]} array with tokens + */ + parseDeltaChunks(chunk) { + let listBy; + let tokens = []; + if (chunk.startsWith(this.DELTA_LIST_BY_ONE)) listBy = 1; + if (chunk.startsWith(this.DELTA_LIST_BY_TWO)) listBy = 2; + if (listBy) chunk = chunk.slice(1); + const blocks = chunk.split('x'); + + if (listBy) { + if (blocks.length === 1) { + tokens = this.wrap(chunk, listBy); + } else { + let items = []; + items = blocks.map((block) => (this.wrap(block, listBy))); + items.forEach((item, i) => { + if (i > 0) { + const c = tokens.pop(); + for (let j = 0; j < c; j++) tokens.push(item[0]); + item = item.slice(1); + } + tokens.push(...item); + }); + return tokens; + } + } else if (blocks.length === 2) { + const num = parseInt(blocks[1], this.intBase); + for (let i = 0; i < blocks[0]; i++) { + tokens.push(num); + } + } else tokens = [parseInt(chunk, this.intBase)]; + return tokens; } - if (token.indexOf('-') > -1) { - let [start, stop] = token.split('-'); - start = parseInt(start, intBase); - stop = parseInt(stop, intBase); - for (let i = start; i <= stop; i += 1) { - tokens.push(i); - } - } else tokens = [parseInt(token, intBase)]; - return tokens; -}; - -/** - * Parse string by delta - * - * @param string - * @return {[]} array with tokens - */ -const parseDelta = (string) => { - let tokens = []; - const chunks = deltaChunks(string); - - chunks.forEach((chunk) => tokens = tokens.concat(parseDeltaChunks(chunk))); - - let last = 0; - tokens.forEach((token, i) => { - tokens[i] = token + last; - last = tokens[i]; - }); - - return tokens; -}; - - -/** - * Parse chunk of delta - * - * @param chunk - * @return {[]} array with tokens - */ -const parseDeltaChunks = (chunk) => { - let listBy; - let tokens = []; - if (chunk.startsWith(DELTA_LIST_BY_ONE)) listBy = 1; - if (chunk.startsWith(DELTA_LIST_BY_TWO)) listBy = 2; - if (listBy) chunk = chunk.slice(1); - const blocks = chunk.split('x'); - - if (listBy) { - if (blocks.length === 1) { - tokens = wrap(chunk, listBy); - } else { - let items = []; - items = blocks.map((block, i) => (wrap(block, listBy))); - items.forEach((item, i) => { - if (i > 0) { - const c = tokens.pop(); - for (let j = 0; j < c; j++) tokens.push(item[0]); - item = item.slice(1); - } - tokens.push(...item); - }); - return tokens; - } - } else if (blocks.length === 2) { - const num = parseInt(blocks[1], intBase); - for (let i = 0; i < blocks[0]; i++) { - tokens.push(num); - } - } else tokens = [parseInt(chunk, intBase)]; - - return tokens; -}; - -/** - * Yield chunks for delta string - * - * @param string for split into chunks - * @return [] of chunks - */ -const deltaChunks = (string) => { - const chunks = []; - let buf = ''; - for (const ltr of string) { - if (ltr === NUM_DELIMITER) { - (buf !== '') && chunks.push(buf); - buf = ''; - } else if (ltr === DELTA_LIST_BY_ONE || ltr === DELTA_LIST_BY_TWO) { - (buf !== '') && chunks.push(buf); - buf = ltr; - } else { - buf += ltr; + /** + * Yield chunks for delta string + * + * @param string for split into chunks + * @return [] of chunks + */ + deltaChunks(string) { + const chunks = []; + let buf = ''; + for (const ltr of string) { + if (ltr === this.NUM_DELIMITER) { + (buf !== '') && chunks.push(buf); + buf = ''; + } else if (ltr === this.DELTA_LIST_BY_ONE || ltr === this.DELTA_LIST_BY_TWO) { + (buf !== '') && chunks.push(buf); + buf = ltr; + } else { + buf += ltr; + } } + if (buf !== '') chunks.push(buf); + return chunks; } - if (buf !== '') chunks.push(buf); - return chunks; -}; - -/** - * Convert string to several strings of length of count symbols - * - * @param string - * @param count symbols - * @returns {[]} list of several strings - */ -const wrap = (string, count) => { - const list = []; - for (let i = 0; i < string.length; i += count) { - list.push(parseInt(string.slice(i, i + count), intBase)); + + /** + * Convert string to several strings of length of count symbols + * + * @param string + * @param count symbols + * @returns {[]} list of several strings + */ + wrap(string, count) { + const list = []; + for (let i = 0; i < string.length; i += count) { + list.push(parseInt(string.slice(i, i + count), this.intBase)); + } + return list; } - return list; -}; +} + +// const NUM_DELIMITER = ','; +// const DELTA_LIST_BY_ONE = '.'; +// const DELTA_LIST_BY_TWO = ':'; +// const ZIP_START_DELIMITER = '('; +// const ZIP_END_DELIMITER = ')'; +// +// let intBase = 10; +// +// /** +// * Parse string to array of encoding numbers +// * +// * @param string +// * @returns {[]|*[]} +// */ +// const decode = (string) => { +// if (!string) { +// return []; +// } +// let items; +// +// // Parse base for int +// if (string.startsWith('x')) { +// let base; +// [base, string] = string.split('x'); +// intBase = base.slice(1); +// } +// +// // Parse empty string as empty list +// if (string.startsWith('~')) { +// items = parseDelta(string.slice(1)); +// } else { +// items = parseString(string); +// } +// +// return items; +// }; + +// /** +// * Parse string to tokens +// * +// * @param string +// * @return {[]} +// */ +// const parseString = (string) => { +// let buff = ''; const tokens = []; const +// zipBuff = []; +// +// for (const ltr of string) { +// if (ltr === ZIP_START_DELIMITER) zipBuff.push(1); +// if (ltr === ZIP_END_DELIMITER) zipBuff.pop(); +// if (zipBuff.length === 0 && ltr === NUM_DELIMITER) { +// parseToken(buff).forEach((item) => { +// tokens.push(item); +// }); +// buff = ''; +// } else buff += ltr; +// } +// +// if (buff) { +// parseToken(buff).forEach((item) => { +// tokens.push(item); +// }); +// } +// +// return tokens; +// }; +// +// +// /** +// * Parse token from string +// * +// * @param token +// * @return {[]} array with tokens +// */ +// const parseToken = (token) => { +// let tokens = []; +// if (token.indexOf(ZIP_START_DELIMITER) > -1) { +// let [base, subString] = token.split(ZIP_START_DELIMITER); +// base = parseInt(base, 10); +// const items = parseString(subString.slice(0, subString.length - 1)); +// items.forEach((item) => tokens.push(item + base)); +// return tokens; +// } +// if (token.indexOf('-') > -1) { +// let [start, stop] = token.split('-'); +// start = parseInt(start, intBase); +// stop = parseInt(stop, intBase); +// +// for (let i = start; i <= stop; i += 1) { +// tokens.push(i); +// } +// } else tokens = [parseInt(token, intBase)]; +// return tokens; +// }; +// +// /** +// * Parse string by delta +// * +// * @param string +// * @return {[]} array with tokens +// */ +// const parseDelta = (string) => { +// let tokens = []; +// const chunks = deltaChunks(string); +// +// chunks.forEach((chunk) => tokens = tokens.concat(parseDeltaChunks(chunk))); +// +// let last = 0; +// tokens.forEach((token, i) => { +// tokens[i] = token + last; +// last = tokens[i]; +// }); +// +// return tokens; +// }; +// +// +// /** +// * Parse chunk of delta +// * +// * @param chunk +// * @return {[]} array with tokens +// */ +// const parseDeltaChunks = (chunk) => { +// let listBy; +// let tokens = []; +// if (chunk.startsWith(DELTA_LIST_BY_ONE)) listBy = 1; +// if (chunk.startsWith(DELTA_LIST_BY_TWO)) listBy = 2; +// if (listBy) chunk = chunk.slice(1); +// const blocks = chunk.split('x'); +// +// if (listBy) { +// if (blocks.length === 1) { +// tokens = wrap(chunk, listBy); +// } else { +// let items = []; +// items = blocks.map((block, i) => (wrap(block, listBy))); +// items.forEach((item, i) => { +// if (i > 0) { +// const c = tokens.pop(); +// for (let j = 0; j < c; j++) tokens.push(item[0]); +// item = item.slice(1); +// } +// tokens.push(...item); +// }); +// return tokens; +// } +// } else if (blocks.length === 2) { +// const num = parseInt(blocks[1], intBase); +// for (let i = 0; i < blocks[0]; i++) { +// tokens.push(num); +// } +// } else tokens = [parseInt(chunk, intBase)]; +// +// return tokens; +// }; +// +// /** +// * Yield chunks for delta string +// * +// * @param string for split into chunks +// * @return [] of chunks +// */ +// const deltaChunks = (string) => { +// const chunks = []; +// let buf = ''; +// for (const ltr of string) { +// if (ltr === NUM_DELIMITER) { +// (buf !== '') && chunks.push(buf); +// buf = ''; +// } else if (ltr === DELTA_LIST_BY_ONE || ltr === DELTA_LIST_BY_TWO) { +// (buf !== '') && chunks.push(buf); +// buf = ltr; +// } else { +// buf += ltr; +// } +// } +// if (buf !== '') chunks.push(buf); +// return chunks; +// }; +// +// /** +// * Convert string to several strings of length of count symbols +// * +// * @param string +// * @param count symbols +// * @returns {[]} list of several strings +// */ +// const wrap = (string, count) => { +// const list = []; +// for (let i = 0; i < string.length; i += count) { +// list.push(parseInt(string.slice(i, i + count), intBase)); +// } +// return list; +// }; // Tests @@ -226,3 +424,7 @@ const wrap = (string, count) => { // Strings with base of numbers // decode('x16;3,f'); // decode('x2;11,101'); + +let obj = new Decode(); +console.log(obj.parse('1(0,2,4,6)')); +console.log(obj.parse('~.12x22')); From 91f6ac49bc2f642bb9732ccf8aefe55fe7344b36 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 11:55:11 +0500 Subject: [PATCH 11/44] add methods with underscore (private methods) --- scripts/encode.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/encode.js b/scripts/encode.js index 7d530a7..c0afcec 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -79,9 +79,9 @@ class Encode { * @return {string} compressed string */ static encodeDelta(tokens) { - const sortedTokens = this.deltaCompression(tokens); - const chunks = this.xBlocks(sortedTokens); - return this.compressToString(chunks); + const sortedTokens = this._deltaCompression(tokens); + const chunks = this._xBlocks(sortedTokens); + return this._compressToString(chunks); } /** @@ -91,7 +91,7 @@ class Encode { * @return {[]} sorted array of difference tokens * @private */ - static deltaCompression(tokens) { + static _deltaCompression(tokens) { tokens.sort(); const diffTokens = []; tokens.forEach((token, i) => { @@ -107,7 +107,7 @@ class Encode { * @return {[]} * @private */ - static xBlocks(tokens) { + static _xBlocks(tokens) { let buf = []; const tokensCopy = []; tokens.forEach((token, i) => { @@ -127,7 +127,7 @@ class Encode { * @return {string} compressedString * @private */ - static compressToString(chunks) { + static _compressToString(chunks) { let del = ','; let newDel = null; let compressedString = ''; From 8b39ce11cc9c70cdf9b3397550a1e13e25b75a0c Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 11:57:58 +0500 Subject: [PATCH 12/44] add methods with underscore (private methods) --- scripts/decode.js | 78 +++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/scripts/decode.js b/scripts/decode.js index bf8bbda..5e6bd1d 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -53,7 +53,7 @@ class Decode { if (ltr === this.ZIP_START_DELIMITER) zipBuff.push(1); if (ltr === this.ZIP_END_DELIMITER) zipBuff.pop(); if (zipBuff.length === 0 && ltr === this.NUM_DELIMITER) { - this.parseToken(buff).forEach((item) => { + this._parseToken(buff).forEach((item) => { tokens.push(item); }); buff = ''; @@ -61,20 +61,41 @@ class Decode { } if (buff) { - this.parseToken(buff).forEach((item) => { + this._parseToken(buff).forEach((item) => { tokens.push(item); }); } return tokens; } + /** + * Parse string by delta + * + * @param string + * @return {[]} array with tokens + */ + parseDelta(string) { + let tokens = []; + const chunks = this._deltaChunks(string); + + chunks.forEach((chunk) => tokens = tokens.concat(this._parse_deltaChunks(chunk))); + + let last = 0; + tokens.forEach((token, i) => { + tokens[i] = token + last; + last = tokens[i]; + }); + + return tokens; + } + /** * Parse token from string * * @param token * @return {[]} array with tokens */ - parseToken(token) { + _parseToken(token) { let tokens = []; if (token.indexOf(this.ZIP_START_DELIMITER) > -1) { let [base, subString] = token.split(this.ZIP_START_DELIMITER); @@ -95,34 +116,13 @@ class Decode { return tokens; } - /** - * Parse string by delta - * - * @param string - * @return {[]} array with tokens - */ - parseDelta(string) { - let tokens = []; - const chunks = this.deltaChunks(string); - - chunks.forEach((chunk) => tokens = tokens.concat(this.parseDeltaChunks(chunk))); - - let last = 0; - tokens.forEach((token, i) => { - tokens[i] = token + last; - last = tokens[i]; - }); - - return tokens; - } - /** * Parse chunk of delta * * @param chunk * @return {[]} array with tokens */ - parseDeltaChunks(chunk) { + _parse_deltaChunks(chunk) { let listBy; let tokens = []; if (chunk.startsWith(this.DELTA_LIST_BY_ONE)) listBy = 1; @@ -132,10 +132,10 @@ class Decode { if (listBy) { if (blocks.length === 1) { - tokens = this.wrap(chunk, listBy); + tokens = this._wrap(chunk, listBy); } else { let items = []; - items = blocks.map((block) => (this.wrap(block, listBy))); + items = blocks.map((block) => (this._wrap(block, listBy))); items.forEach((item, i) => { if (i > 0) { const c = tokens.pop(); @@ -162,7 +162,7 @@ class Decode { * @param string for split into chunks * @return [] of chunks */ - deltaChunks(string) { + _deltaChunks(string) { const chunks = []; let buf = ''; for (const ltr of string) { @@ -187,7 +187,7 @@ class Decode { * @param count symbols * @returns {[]} list of several strings */ - wrap(string, count) { + _wrap(string, count) { const list = []; for (let i = 0; i < string.length; i += count) { list.push(parseInt(string.slice(i, i + count), this.intBase)); @@ -247,7 +247,7 @@ class Decode { // if (ltr === ZIP_START_DELIMITER) zipBuff.push(1); // if (ltr === ZIP_END_DELIMITER) zipBuff.pop(); // if (zipBuff.length === 0 && ltr === NUM_DELIMITER) { -// parseToken(buff).forEach((item) => { +// _parseToken(buff).forEach((item) => { // tokens.push(item); // }); // buff = ''; @@ -255,7 +255,7 @@ class Decode { // } // // if (buff) { -// parseToken(buff).forEach((item) => { +// _parseToken(buff).forEach((item) => { // tokens.push(item); // }); // } @@ -270,7 +270,7 @@ class Decode { // * @param token // * @return {[]} array with tokens // */ -// const parseToken = (token) => { +// const _parseToken = (token) => { // let tokens = []; // if (token.indexOf(ZIP_START_DELIMITER) > -1) { // let [base, subString] = token.split(ZIP_START_DELIMITER); @@ -299,9 +299,9 @@ class Decode { // */ // const parseDelta = (string) => { // let tokens = []; -// const chunks = deltaChunks(string); +// const chunks = _deltaChunks(string); // -// chunks.forEach((chunk) => tokens = tokens.concat(parseDeltaChunks(chunk))); +// chunks.forEach((chunk) => tokens = tokens.concat(_parse_deltaChunks(chunk))); // // let last = 0; // tokens.forEach((token, i) => { @@ -319,7 +319,7 @@ class Decode { // * @param chunk // * @return {[]} array with tokens // */ -// const parseDeltaChunks = (chunk) => { +// const _parse_deltaChunks = (chunk) => { // let listBy; // let tokens = []; // if (chunk.startsWith(DELTA_LIST_BY_ONE)) listBy = 1; @@ -329,10 +329,10 @@ class Decode { // // if (listBy) { // if (blocks.length === 1) { -// tokens = wrap(chunk, listBy); +// tokens = _wrap(chunk, listBy); // } else { // let items = []; -// items = blocks.map((block, i) => (wrap(block, listBy))); +// items = blocks.map((block, i) => (_wrap(block, listBy))); // items.forEach((item, i) => { // if (i > 0) { // const c = tokens.pop(); @@ -359,7 +359,7 @@ class Decode { // * @param string for split into chunks // * @return [] of chunks // */ -// const deltaChunks = (string) => { +// const _deltaChunks = (string) => { // const chunks = []; // let buf = ''; // for (const ltr of string) { @@ -384,7 +384,7 @@ class Decode { // * @param count symbols // * @returns {[]} list of several strings // */ -// const wrap = (string, count) => { +// const _wrap = (string, count) => { // const list = []; // for (let i = 0; i < string.length; i += count) { // list.push(parseInt(string.slice(i, i + count), intBase)); From 6125e72eaa3716a00f449fa8ae9036dd870e35fb Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 11:59:38 +0500 Subject: [PATCH 13/44] fix decode --- scripts/decode.js | 197 ---------------------------------------------- 1 file changed, 197 deletions(-) diff --git a/scripts/decode.js b/scripts/decode.js index 5e6bd1d..0052f6c 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -196,203 +196,6 @@ class Decode { } } -// const NUM_DELIMITER = ','; -// const DELTA_LIST_BY_ONE = '.'; -// const DELTA_LIST_BY_TWO = ':'; -// const ZIP_START_DELIMITER = '('; -// const ZIP_END_DELIMITER = ')'; -// -// let intBase = 10; -// -// /** -// * Parse string to array of encoding numbers -// * -// * @param string -// * @returns {[]|*[]} -// */ -// const decode = (string) => { -// if (!string) { -// return []; -// } -// let items; -// -// // Parse base for int -// if (string.startsWith('x')) { -// let base; -// [base, string] = string.split('x'); -// intBase = base.slice(1); -// } -// -// // Parse empty string as empty list -// if (string.startsWith('~')) { -// items = parseDelta(string.slice(1)); -// } else { -// items = parseString(string); -// } -// -// return items; -// }; - -// /** -// * Parse string to tokens -// * -// * @param string -// * @return {[]} -// */ -// const parseString = (string) => { -// let buff = ''; const tokens = []; const -// zipBuff = []; -// -// for (const ltr of string) { -// if (ltr === ZIP_START_DELIMITER) zipBuff.push(1); -// if (ltr === ZIP_END_DELIMITER) zipBuff.pop(); -// if (zipBuff.length === 0 && ltr === NUM_DELIMITER) { -// _parseToken(buff).forEach((item) => { -// tokens.push(item); -// }); -// buff = ''; -// } else buff += ltr; -// } -// -// if (buff) { -// _parseToken(buff).forEach((item) => { -// tokens.push(item); -// }); -// } -// -// return tokens; -// }; -// -// -// /** -// * Parse token from string -// * -// * @param token -// * @return {[]} array with tokens -// */ -// const _parseToken = (token) => { -// let tokens = []; -// if (token.indexOf(ZIP_START_DELIMITER) > -1) { -// let [base, subString] = token.split(ZIP_START_DELIMITER); -// base = parseInt(base, 10); -// const items = parseString(subString.slice(0, subString.length - 1)); -// items.forEach((item) => tokens.push(item + base)); -// return tokens; -// } -// if (token.indexOf('-') > -1) { -// let [start, stop] = token.split('-'); -// start = parseInt(start, intBase); -// stop = parseInt(stop, intBase); -// -// for (let i = start; i <= stop; i += 1) { -// tokens.push(i); -// } -// } else tokens = [parseInt(token, intBase)]; -// return tokens; -// }; -// -// /** -// * Parse string by delta -// * -// * @param string -// * @return {[]} array with tokens -// */ -// const parseDelta = (string) => { -// let tokens = []; -// const chunks = _deltaChunks(string); -// -// chunks.forEach((chunk) => tokens = tokens.concat(_parse_deltaChunks(chunk))); -// -// let last = 0; -// tokens.forEach((token, i) => { -// tokens[i] = token + last; -// last = tokens[i]; -// }); -// -// return tokens; -// }; -// -// -// /** -// * Parse chunk of delta -// * -// * @param chunk -// * @return {[]} array with tokens -// */ -// const _parse_deltaChunks = (chunk) => { -// let listBy; -// let tokens = []; -// if (chunk.startsWith(DELTA_LIST_BY_ONE)) listBy = 1; -// if (chunk.startsWith(DELTA_LIST_BY_TWO)) listBy = 2; -// if (listBy) chunk = chunk.slice(1); -// const blocks = chunk.split('x'); -// -// if (listBy) { -// if (blocks.length === 1) { -// tokens = _wrap(chunk, listBy); -// } else { -// let items = []; -// items = blocks.map((block, i) => (_wrap(block, listBy))); -// items.forEach((item, i) => { -// if (i > 0) { -// const c = tokens.pop(); -// for (let j = 0; j < c; j++) tokens.push(item[0]); -// item = item.slice(1); -// } -// tokens.push(...item); -// }); -// return tokens; -// } -// } else if (blocks.length === 2) { -// const num = parseInt(blocks[1], intBase); -// for (let i = 0; i < blocks[0]; i++) { -// tokens.push(num); -// } -// } else tokens = [parseInt(chunk, intBase)]; -// -// return tokens; -// }; -// -// /** -// * Yield chunks for delta string -// * -// * @param string for split into chunks -// * @return [] of chunks -// */ -// const _deltaChunks = (string) => { -// const chunks = []; -// let buf = ''; -// for (const ltr of string) { -// if (ltr === NUM_DELIMITER) { -// (buf !== '') && chunks.push(buf); -// buf = ''; -// } else if (ltr === DELTA_LIST_BY_ONE || ltr === DELTA_LIST_BY_TWO) { -// (buf !== '') && chunks.push(buf); -// buf = ltr; -// } else { -// buf += ltr; -// } -// } -// if (buf !== '') chunks.push(buf); -// return chunks; -// }; -// -// /** -// * Convert string to several strings of length of count symbols -// * -// * @param string -// * @param count symbols -// * @returns {[]} list of several strings -// */ -// const _wrap = (string, count) => { -// const list = []; -// for (let i = 0; i < string.length; i += count) { -// list.push(parseInt(string.slice(i, i + count), intBase)); -// } -// return list; -// }; - - // Tests // Done // decode('123'); From 5dbf30156945a87dcee19aa836ddc83dce637e70 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 12:47:33 +0500 Subject: [PATCH 14/44] install dependencies: eslint, mocha --- package.json | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 3c1a76f..2d2ddd0 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,16 @@ "name": "zip-numbers", "version": "1.0.0", "description": "Compression writing numbers", - "dependencies": { - "mocha": "^6.2.2" + "dependencies": {}, + "repository": "git://github.com/jetstyle/js-zip-numbers.git", + "scripts": { + "eslint": "node_modules/.bin/eslint", + "test": "node_modules/.bin/mocha" }, - "repository": "git://github.com/jetstyle/js-zip-numbers.git" + "devDependencies": { + "eslint": "^6.7.2", + "eslint-config-airbnb-base": "^14.0.0", + "eslint-plugin-import": "^2.19.1", + "mocha": "^6.2.2" + } } From 6794ce1541e2da5838c927f3a8d09a2fca493069 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 12:48:49 +0500 Subject: [PATCH 15/44] module exports class --- scripts/decode.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/decode.js b/scripts/decode.js index 0052f6c..50b7736 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -228,6 +228,4 @@ class Decode { // decode('x16;3,f'); // decode('x2;11,101'); -let obj = new Decode(); -console.log(obj.parse('1(0,2,4,6)')); -console.log(obj.parse('~.12x22')); +module.exports = Decode; From 238721dd9150de124df4303a5fb19b5635dd08ef Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 12:49:14 +0500 Subject: [PATCH 16/44] module exports Encode --- scripts/encode.js | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/scripts/encode.js b/scripts/encode.js index c0afcec..b7019a1 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -18,7 +18,6 @@ class Encode { * @return {string} encoding string */ parse(tokens, mode = this.MODE_SIMPLE_STRING) { - if (tokens.length === 0) return ''; if (!tokens || !Array.isArray(tokens)) { console.error('tokens argument should be an array of integers'); return ''; @@ -44,6 +43,7 @@ class Encode { * @return {string} compressed string */ static encodeString(tokens) { + if (tokens.length === 0) return ''; if (tokens.length < 3) { return tokens.join(','); } @@ -79,6 +79,7 @@ class Encode { * @return {string} compressed string */ static encodeDelta(tokens) { + if (tokens.length === 0) return '~'; const sortedTokens = this._deltaCompression(tokens); const chunks = this._xBlocks(sortedTokens); return this._compressToString(chunks); @@ -153,19 +154,4 @@ class Encode { } } - -// Tests DONE -// encode([]); -// encode([1]); -// encode([1, 2]); -// encode([1, 2, 3]); -// console.log(encode([1, 2, 3, 4])); -// // encode([1, 3, 5, 7]); -// // encode([1, 2, 3, 5, 6, 7]); -// console.log(encode([1, 2, 3, 5, 6, 7, 9], 1)); -// console.log(encode([1, 2, 3, 5, 6, 7, 9], 2)); - - -const obj = new Encode(); -console.log(obj.parse([1, 3, 5, 7], 1)); -console.log(obj.parse([1, 3, 5, 7], 2)); +module.exports = Encode; From 87bea105a08d423f06b78c9531f03b0668a68fbe Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 12:49:50 +0500 Subject: [PATCH 17/44] add test for encode --- test/index.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 test/index.js diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..431ecde --- /dev/null +++ b/test/index.js @@ -0,0 +1,21 @@ +const assert = require('assert'); +const Encode = require('../scripts/encode'); + +const testObj = new Encode(); + +describe('encoding', () => { + it('For test making simple string', () => { + assert.equal(testObj.parse([]), ''); + assert.equal(testObj.parse([1]), '1'); + assert.equal(testObj.parse([1,2]), '1,2'); + assert.equal(testObj.parse([1,2,3]), '1(0-2)'); + assert.equal(testObj.parse([1,2,3,4]), '1(0-3)'); + assert.equal(testObj.parse([1,3,5,7]), '1(0,2,4,6)'); + assert.equal(testObj.parse([1, 2, 3, 5, 6, 7]), '1(0-2,4-6)'); + assert.equal(testObj.parse([1, 2, 3, 5, 6, 7, 9]), '1(0-2,4-6,8)'); + }); + it('For test making delta string', () => { + assert.equal(testObj.parse([], 2), '~'); + assert.equal(testObj.parse([1, 3, 6], 2), '~.123'); + }); +}); From b8b8abdb8b8c28920092a0dda8b7862c0d5504aa Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 12:57:24 +0500 Subject: [PATCH 18/44] fix index.js --- index.js | 227 ------------------------------------------------------- 1 file changed, 227 deletions(-) diff --git a/index.js b/index.js index 9e89856..8b13789 100644 --- a/index.js +++ b/index.js @@ -1,228 +1 @@ -const NUM_DELIMITER = ','; -const DELTA_LIST_BY_ONE = '.'; -const DELTA_LIST_BY_TWO = ':'; -const ZIP_START_DELIMITER = '('; -const ZIP_END_DELIMITER = ')'; - - -/** - * Parse string to array of encoding numbers - * - * @param string - * @returns {[]|*[]} - */ -const decode = string => { - if (!string) { - return []; - } - let items; - - // Parse base for int - if (string.startsWith('x')) { - // Дописать функционал - } - - // Parse empty string as empty list - if (string.startsWith('~')) { - items = parseDelta(string.slice(1)); - console.log(items); - } - else { - items = parseString(string); - console.log(items) - } - - return items; -}; - -/** - * Parse string to tokens - * - * @param string - * @return {[]} - */ -const parseString = string => { - let buff = '', tokens = [], zipBuff = []; - - for (const ltr of string) { - if (ltr === ZIP_START_DELIMITER) zipBuff.push(1); - if (ltr === ZIP_END_DELIMITER) zipBuff.pop(); - if (zipBuff.length === 0 && ltr === NUM_DELIMITER) { - parseToken(buff).forEach((item) => { - tokens.push(item); - }); - buff = ''; - } - else buff += ltr; - } - - if (buff) { - parseToken(buff).forEach((item) => { - tokens.push(item); - }); - } - - return tokens; -}; - - -/** - * Parse token from string - * - * @param token - * @return {[]} array with tokens - */ -const parseToken = token => { - let tokens = []; - if (token.indexOf(ZIP_START_DELIMITER) > -1) { - let [base, subString] = token.split(ZIP_START_DELIMITER); - base = parseInt(base, 10); - let items = parseString(subString.slice(0, subString.length-1)); - items.forEach((item) => tokens.push(item+base)); - return tokens; - } - if (token.indexOf('-') > -1) { - let [start, stop] = token.split('-'); - start = parseInt(start, 10); - stop = parseInt(stop, 10); - - for (let i = start; i <= stop; i += 1) { - tokens.push(i); - } - } - else tokens = [parseInt(token)]; - return tokens; -}; - -/** - * Parse string by delta - * - * @param string - * @return {[]} array with tokens - */ -const parseDelta = string => { - let tokens = [], - chunks = deltaChunks(string); - - chunks.forEach((chunk) => tokens = tokens.concat(parseDeltaChunks(chunk))); - - let last = 0; - tokens.forEach((token, i) => { - tokens[i]=token+last; - last=tokens[i]; - }); - - return tokens; -}; - - -/** - * Parse chunk of delta - * - * @param chunk - * @return {[]} array with tokens - */ -const parseDeltaChunks = chunk => { - let listBy, blocks, tokens = []; - if (chunk.startsWith(DELTA_LIST_BY_ONE)) listBy = 1; - if (chunk.startsWith(DELTA_LIST_BY_TWO)) listBy = 2; - if (listBy) chunk = chunk.slice(1); - blocks = chunk.split('x'); - - if (listBy) { - if (blocks.length === 1) { - tokens = wrap(chunk, listBy); - } - else { - // Дописать функционал - } - - } - else if (blocks.length === 2) { - let num = parseInt(blocks[1], 10); - for (let i = 0; i < blocks[0]; i++) { - tokens.push(num); - } - } - else tokens = [parseInt(chunk, 10)]; - - return tokens; - - }; - -/** - * Yield chunks for delta string - * - * @param string for split into chunks - * @return [] of chunks - */ -const deltaChunks = string => { - let chunks = [], - buf = ''; - for (let ltr of string) { - if (ltr === NUM_DELIMITER) { - (buf!=='') && chunks.push(buf); - buf = ''; - } - else if (ltr === DELTA_LIST_BY_ONE || ltr === DELTA_LIST_BY_TWO) { - (buf!=='') && chunks.push(buf); - buf = ltr; - } - else { - buf += ltr; - } - } - if (buf !== '') chunks.push(buf); - return chunks; -}; - -/** - * Convert string to several strings of length of count symbols - * - * @param string - * @param count symbols - * @returns {[]} list of several strings - */ -const wrap = (string, count) => { - let list = []; - for (let i = 0; i Date: Fri, 20 Dec 2019 14:37:05 +0500 Subject: [PATCH 19/44] rules for linter --- .eslintrc.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..780e535 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,21 @@ +module.exports = { + env: { + browser: true, + es6: true, + }, + extends: [ + 'airbnb-base', + ], + globals: { + Atomics: 'readonly', + SharedArrayBuffer: 'readonly', + }, + parserOptions: { + ecmaVersion: 2018, + sourceType: 'module', + }, + rules: { + "no-param-reassign": [0], + "no-underscore-dangle": [0] + }, +}; From aac5fd96448f35b79e0905c49c97f908b119a097 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 14:43:08 +0500 Subject: [PATCH 20/44] fix by eslint --- scripts/encode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/encode.js b/scripts/encode.js index b7019a1..fc82071 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -23,7 +23,7 @@ class Encode { return ''; } if (tokens.length > this.maxLength) { - console.error('array size is higher than allowed') + console.error('array size is higher than allowed'); return ''; } if (mode === this.MODE_SIMPLE_STRING) { From 75fa8d0105016c3c8347a7bcc9e5bd95d4f41bc4 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 14:43:32 +0500 Subject: [PATCH 21/44] rules by eslint --- .eslintrc.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index 780e535..0ae4550 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -16,6 +16,8 @@ module.exports = { }, rules: { "no-param-reassign": [0], - "no-underscore-dangle": [0] + "no-underscore-dangle": [0], + "no-unused-expressions": [0], + "no-nested-ternary": [0] }, }; From 2592262bcd5e3d5ac38d696455188c9a389f01f1 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 14:44:54 +0500 Subject: [PATCH 22/44] fix by eslint --- scripts/decode.js | 46 ++++++++++------------------------------------ 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/scripts/decode.js b/scripts/decode.js index 50b7736..e1e4109 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -49,6 +49,7 @@ class Decode { let buff = ''; const tokens = []; const zipBuff = []; + // eslint-disable-next-line no-restricted-syntax for (const ltr of string) { if (ltr === this.ZIP_START_DELIMITER) zipBuff.push(1); if (ltr === this.ZIP_END_DELIMITER) zipBuff.pop(); @@ -78,7 +79,10 @@ class Decode { let tokens = []; const chunks = this._deltaChunks(string); - chunks.forEach((chunk) => tokens = tokens.concat(this._parse_deltaChunks(chunk))); + chunks.forEach((chunk) => { + tokens = tokens.concat(this._parseDeltaChunks(chunk)); + return tokens; + }); let last = 0; tokens.forEach((token, i) => { @@ -98,6 +102,7 @@ class Decode { _parseToken(token) { let tokens = []; if (token.indexOf(this.ZIP_START_DELIMITER) > -1) { + // eslint-disable-next-line prefer-const let [base, subString] = token.split(this.ZIP_START_DELIMITER); base = parseInt(base, 10); const items = this.parseString(subString.slice(0, subString.length - 1)); @@ -122,7 +127,7 @@ class Decode { * @param chunk * @return {[]} array with tokens */ - _parse_deltaChunks(chunk) { + _parseDeltaChunks(chunk) { let listBy; let tokens = []; if (chunk.startsWith(this.DELTA_LIST_BY_ONE)) listBy = 1; @@ -139,7 +144,7 @@ class Decode { items.forEach((item, i) => { if (i > 0) { const c = tokens.pop(); - for (let j = 0; j < c; j++) tokens.push(item[0]); + for (let j = 0; j < c; j += 1) tokens.push(item[0]); item = item.slice(1); } tokens.push(...item); @@ -148,7 +153,7 @@ class Decode { } } else if (blocks.length === 2) { const num = parseInt(blocks[1], this.intBase); - for (let i = 0; i < blocks[0]; i++) { + for (let i = 0; i < blocks[0]; i += 1) { tokens.push(num); } } else tokens = [parseInt(chunk, this.intBase)]; @@ -165,6 +170,7 @@ class Decode { _deltaChunks(string) { const chunks = []; let buf = ''; + // eslint-disable-next-line no-restricted-syntax for (const ltr of string) { if (ltr === this.NUM_DELIMITER) { (buf !== '') && chunks.push(buf); @@ -196,36 +202,4 @@ class Decode { } } -// Tests -// Done -// decode('123'); -// decode('123,456'); -// decode('1-3'); -// decode('1-3,5-9'); -// decode('120(0,3,5,8,9)'); -// decode('12(1,4),140(0,2,5)'); -// decode('120(0,3,6),130-132'); -// decode('120(0-6)'); -// decode('~155'); -// decode('~1,2,3'); -// decode('~1'); -// decode('~.1'); -// decode('~.123'); -// decode('~.123:1012'); -// decode('~.12:10.45'); -// decode('~.12:10.45,146,234.14'); -// decode('~3x1'); -// decode('1-10'); -// decode('1,2,5,7-13'); -// decode('14(0-8,18)'); -// decode('~.13x3'); -// decode('~.2x12'); -// decode('~12,3x4,'); -// decode('~.54x13:1010x11'); - -// In process -// Strings with base of numbers -// decode('x16;3,f'); -// decode('x2;11,101'); - module.exports = Decode; From 6626a068cde12e29aee95da3d45886ac86d97920 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 15:17:08 +0500 Subject: [PATCH 23/44] tests passing (besides strings with base of numbers) --- test/index.js | 68 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/test/index.js b/test/index.js index 431ecde..f456060 100644 --- a/test/index.js +++ b/test/index.js @@ -1,21 +1,67 @@ const assert = require('assert'); const Encode = require('../scripts/encode'); +const Decode = require('../scripts/decode'); -const testObj = new Encode(); +const testEncode = new Encode(); +const testDecode = new Decode(); describe('encoding', () => { it('For test making simple string', () => { - assert.equal(testObj.parse([]), ''); - assert.equal(testObj.parse([1]), '1'); - assert.equal(testObj.parse([1,2]), '1,2'); - assert.equal(testObj.parse([1,2,3]), '1(0-2)'); - assert.equal(testObj.parse([1,2,3,4]), '1(0-3)'); - assert.equal(testObj.parse([1,3,5,7]), '1(0,2,4,6)'); - assert.equal(testObj.parse([1, 2, 3, 5, 6, 7]), '1(0-2,4-6)'); - assert.equal(testObj.parse([1, 2, 3, 5, 6, 7, 9]), '1(0-2,4-6,8)'); + assert.equal(testEncode.parse([]), ''); + assert.equal(testEncode.parse([1]), '1'); + assert.equal(testEncode.parse([1, 2]), '1,2'); + assert.equal(testEncode.parse([1, 2, 3]), '1(0-2)'); + assert.equal(testEncode.parse([1, 2, 3, 4]), '1(0-3)'); + assert.equal(testEncode.parse([1, 3, 5, 7]), '1(0,2,4,6)'); + assert.equal(testEncode.parse([1, 2, 3, 5, 6, 7]), '1(0-2,4-6)'); + assert.equal(testEncode.parse([1, 2, 3, 5, 6, 7, 9]), '1(0-2,4-6,8)'); }); it('For test making delta string', () => { - assert.equal(testObj.parse([], 2), '~'); - assert.equal(testObj.parse([1, 3, 6], 2), '~.123'); + assert.equal(testEncode.parse([], 2), '~'); + assert.equal(testEncode.parse([1, 3, 6], 2), '~.123'); }); }); + +describe('decoding', () => { + it('No-zipped strings', () => { + assert.deepEqual(testDecode.parse('123'), [123]); + assert.deepEqual(testDecode.parse('123, 456'), [123, 456]); + }); + it('Strings with ranges', () => { + assert.deepEqual(testDecode.parse('1-3'), [1, 2, 3]); + assert.deepEqual(testDecode.parse('1-3,5-9'), [1, 2, 3, 5, 6, 7, 8, 9]); + }); + it('Zipped strings', () => { + assert.deepEqual(testDecode.parse('120(0,3,5,8,9)'), [120, 123, 125, 128, 129]); + assert.deepEqual(testDecode.parse('12(1,4),140(0,2,5)'), [13, 16, 140, 142, 145]); + }); + it('Strings with zipped data and ranges', () => { + assert.deepEqual(testDecode.parse('120(0,3,6),130-132'), [120, 123, 126, 130, 131, 132]); + assert.deepEqual(testDecode.parse('120(0-6)'), [120, 121, 122, 123, 124, 125, 126]); + }); + it('Strings with base of numbers', () => { + assert.deepEqual(testDecode.parse('x16;3,f'), [3, 15]); + assert.deepEqual(testDecode.parse('x2;11,101'), [3, 5]); + }); + it('Base delta string', () => { + assert.deepEqual(testDecode.parse('~'), []); + assert.deepEqual(testDecode.parse('~1'), [1]); + assert.deepEqual(testDecode.parse('~155'), [155]); + assert.deepEqual(testDecode.parse('~1,2,3'), [1, 3, 6]); + }); + it('Delta string with ranges', () => { + assert.deepEqual(testDecode.parse('~.1'), [1]); + assert.deepEqual(testDecode.parse('~.123'), [1, 3, 6]); + assert.deepEqual(testDecode.parse('~.123:1012'), [1, 3, 6, 16, 28]); + assert.deepEqual(testDecode.parse('~.12:10.45'), [1, 3, 13, 17, 22]); + assert.deepEqual(testDecode.parse('~.12:10.45,146,234.14'), [1, 3, 13, 17, 22, 168, 402, 403, 407]); + }); + it('Delta strings with x-ranges', () => { + assert.deepEqual(testDecode.parse('~3x1'), [1, 2, 3]); + assert.deepEqual(testDecode.parse('~.2x12'), [1, 2, 4]); + assert.deepEqual(testDecode.parse('~.13x3'), [1, 4, 7, 10]); + assert.deepEqual(testDecode.parse('~12,3x4,'), [12, 16, 20, 24]); + assert.deepEqual(testDecode.parse('~.54x13:1010x11'), [5, 6, 7, 8, 9, 12, 22, 33, 44, 55, 66, 77, 88, 99, + 110, 121, 132]); + }); +}); \ No newline at end of file From 66b2d3407f3c4468b12fc78bffc3e21bb7a4c720 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 15:33:30 +0500 Subject: [PATCH 24/44] work with Strings with base of numbers --- scripts/decode.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/decode.js b/scripts/decode.js index e1e4109..dd446da 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -25,8 +25,10 @@ class Decode { // Parse base for int if (string.startsWith('x')) { let base; - [base, string] = string.split('x'); - this.intBase = base.slice(1); + [base, string] = string.split(';'); + this.intBase = parseInt(base.slice(1), 10); + } else { + this.intBase = 10; } // Parse empty string as empty list From d5d801ce7244145a0be37fce686cd800226d57e6 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 16:04:39 +0500 Subject: [PATCH 25/44] checking maxLength --- scripts/decode.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/scripts/decode.js b/scripts/decode.js index dd446da..d4cdbbd 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -20,6 +20,7 @@ class Decode { if (!string) { return []; } + this.countTokens = 0; let items; // Parse base for int @@ -115,11 +116,15 @@ class Decode { let [start, stop] = token.split('-'); start = parseInt(start, this.intBase); stop = parseInt(stop, this.intBase); + this._checkLength(Math.abs(stop - start)); for (let i = start; i <= stop; i += 1) { tokens.push(i); } } else tokens = [parseInt(token, this.intBase)]; + + this._checkLength(tokens.length); + this.countTokens += tokens.length; return tokens; } @@ -202,6 +207,16 @@ class Decode { } return list; } + + /** + * Check limit + * + * @param newCount + * @private + */ + _checkLength(newCount) { + if ((this.countTokens + newCount) > this.maxLength) throw new Error('Tokens count is greater than the limit.'); + } } module.exports = Decode; From 72076a037571badeb507586a061342bafd03d7d2 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 16:56:29 +0500 Subject: [PATCH 26/44] readme v1.0 --- README.md | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4f1eb6a..dfc882a 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,47 @@ Алгоритмы сжатия списков чисел для передачи в тестовом виде. В реализацию входят парсер строк и поле для django-rest-framework. -Поддерживаются 2 способа сжатия: диапазоны с выносом за скобку и дельта-строки. \ No newline at end of file +Поддерживаются 2 способа сжатия: диапазоны с выносом за скобку и дельта-строки. + +## Информация + +1. Сжимает строку по одному из двух способов сжатия, который можно выбрать: + 1. диапазоны с выносом за скобку + 2. дельта-строки + +2. Разжимает строку, сжатую по одному из двух алгоритмов. + + +## Примеры +#### Encode: +```js +var encodeObj = new Encode(); +encodeObj.parse([1, 3, 6], 1); +// return '1(0,2,5)' +encodeObj.parse([1, 3, 6], 2); +// return '~.123' +``` +#### Decode: +```js +var decodeObj = new Decode(); +decodeObj.parse('1(0,2,5)'); +// return [1, 3, 6] +decodeObj.parse('~.123'); +// return [1, 3, 6] +``` + +## API +### new Encode(maxLength) +Создает объект `Encode` с необязательным параметром `maxLength`. +### new Decode(maxLength) +Создает объект `Decode` с необязательным параметром `maxLength`. +### encode.parse(tokens, mode) +Возвращает из массива чисел `[tokens]` сжатую строку `string` по алгоритму: + +`mode=1` диапазоны с выносом за скобку, + +`mode=2` дельта-строки. + +### decode.parse(string) +Возвращает из сжатой строки `string` массив чисел `[tokens]`. + From fe2b70e5154825edc8a85573593203892761f66b Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 18:53:31 +0500 Subject: [PATCH 27/44] create functions encode, decode for interface --- index.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/index.js b/index.js index 8b13789..6244aba 100644 --- a/index.js +++ b/index.js @@ -1 +1,8 @@ +const Encode = require('./scripts/encode'); +const Decode = require('./scripts/decode'); +const encode = (tokens, mode) => new Encode().parse(tokens, mode); +const decode = (string) => new Decode().parse(string); + +exports.encode = encode; +exports.decode = decode; From 9bf5e874c5ea61c30d3422143af7d728a4fb2644 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 18:53:43 +0500 Subject: [PATCH 28/44] update version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2d2ddd0..b457f7d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "zip-numbers", - "version": "1.0.0", + "version": "1.0.1", "description": "Compression writing numbers", "dependencies": {}, "repository": "git://github.com/jetstyle/js-zip-numbers.git", From 85265064c4669f796565eeb099b7f15ca7d1827f Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 19:13:41 +0500 Subject: [PATCH 29/44] readme v.1.0.1 --- README.md | 65 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index dfc882a..9b9a1e9 100644 --- a/README.md +++ b/README.md @@ -12,37 +12,62 @@ 2. Разжимает строку, сжатую по одному из двух алгоритмов. +## Установка + +``` +$ npm install zip-numbers +``` + ## Примеры #### Encode: ```js -var encodeObj = new Encode(); -encodeObj.parse([1, 3, 6], 1); -// return '1(0,2,5)' -encodeObj.parse([1, 3, 6], 2); -// return '~.123' +const zip = require('zip-numbers'); + +zip.encode([1,3,6]); +//=> '1(0,2,5)' + +zip.encode([1,3,6], 1); +//=> '1(0,2,5)' + +zip.encode([1,3,6], 2); +//=> '~.123' ``` #### Decode: ```js -var decodeObj = new Decode(); -decodeObj.parse('1(0,2,5)'); -// return [1, 3, 6] -decodeObj.parse('~.123'); -// return [1, 3, 6] +zip.decode('1(0,2,5)'); +//=> [1, 3, 6] + +zip.decode('~.123'); +//=> [1, 3, 6] ``` ## API -### new Encode(maxLength) -Создает объект `Encode` с необязательным параметром `maxLength`. -### new Decode(maxLength) -Создает объект `Decode` с необязательным параметром `maxLength`. -### encode.parse(tokens, mode) -Возвращает из массива чисел `[tokens]` сжатую строку `string` по алгоритму: +### encode(tokens, [mode]) + +#### tokens + +Type: `Object` `Object[]` + +Array of tokens. + +#### mode + +Type: `number` + +Number 1 or 2 for description selecting of method (simple string or delta) + +##### return string `string` + + +### decode(string) + +#### string + +Type: `string` -`mode=1` диапазоны с выносом за скобку, +String of compressed tokens. -`mode=2` дельта-строки. +##### return tokens `Object` `Object[]` -### decode.parse(string) -Возвращает из сжатой строки `string` массив чисел `[tokens]`. From 45b4c06525181259079589a804dc08a3d0e6737e Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 20 Dec 2019 19:14:58 +0500 Subject: [PATCH 30/44] fix readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9b9a1e9..f7452fa 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,8 @@ zip.encode([1,3,6], 2); ``` #### Decode: ```js +const zip = require('zip-numbers'); + zip.decode('1(0,2,5)'); //=> [1, 3, 6] From 4a717bb27bfcfd53f1f8244254696fd956ad564a Mon Sep 17 00:00:00 2001 From: remort Date: Mon, 23 Dec 2019 16:15:10 +0300 Subject: [PATCH 31/44] fix readme.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit поправил ошибку --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f7452fa..b2f95de 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # zip-numbers -Алгоритмы сжатия списков чисел для передачи в тестовом виде. В реализацию входят парсер строк и поле для django-rest-framework. +Алгоритмы сжатия списков чисел для передачи в текстовом виде. В реализацию входят парсер строк и поле для django-rest-framework. Поддерживаются 2 способа сжатия: диапазоны с выносом за скобку и дельта-строки. From 742c27ccd2322ba22a98d61bd1a05ecb6aa70aac Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Tue, 24 Dec 2019 11:20:49 +0500 Subject: [PATCH 32/44] change eslint's environment --- .eslintrc.js | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc.js b/.eslintrc.js index 0ae4550..a05b06c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,6 +2,7 @@ module.exports = { env: { browser: true, es6: true, + mocha: true, }, extends: [ 'airbnb-base', From f67a73d584d69c280dc0026104024ae0a0c61ab7 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Tue, 24 Dec 2019 11:32:56 +0500 Subject: [PATCH 33/44] error processing --- scripts/encode.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/scripts/encode.js b/scripts/encode.js index fc82071..dff908c 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -19,12 +19,10 @@ class Encode { */ parse(tokens, mode = this.MODE_SIMPLE_STRING) { if (!tokens || !Array.isArray(tokens)) { - console.error('tokens argument should be an array of integers'); - return ''; + throw new TypeError('tokens argument should be an array of integers'); } if (tokens.length > this.maxLength) { - console.error('array size is higher than allowed'); - return ''; + throw new RangeError('array size is higher than allowed'); } if (mode === this.MODE_SIMPLE_STRING) { return (this.constructor.encodeString(tokens)); @@ -32,8 +30,7 @@ class Encode { if (mode === this.MODE_DELTA_STRING) { return (this.constructor.encodeDelta(tokens)); } - console.error('you must select 1 or 2 at second parameter (1 - simple string, 2 - delta string)'); - return ''; + throw new Error('you must select 1 or 2 at second parameter (1 - simple string, 2 - delta string)'); } /** From 675d09b8d8ee61d0837441b245991dc90f4267c8 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Tue, 24 Dec 2019 11:34:16 +0500 Subject: [PATCH 34/44] add keywords, license and fix scripts --- package.json | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b457f7d..8ce05e6 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,25 @@ { "name": "zip-numbers", - "version": "1.0.1", + "version": "1.0.3", "description": "Compression writing numbers", + "license": "MIT", "dependencies": {}, "repository": "git://github.com/jetstyle/js-zip-numbers.git", "scripts": { - "eslint": "node_modules/.bin/eslint", - "test": "node_modules/.bin/mocha" + "eslint": "eslint .", + "test": "mocha" }, "devDependencies": { "eslint": "^6.7.2", "eslint-config-airbnb-base": "^14.0.0", "eslint-plugin-import": "^2.19.1", "mocha": "^6.2.2" - } + }, + "keywords": [ + "numbers", + "encode", + "encodenumbers", + "decode", + "compression" + ] } From dfb596d3e64887dafb487966f3371fc64b3ae672 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Tue, 24 Dec 2019 11:36:14 +0500 Subject: [PATCH 35/44] change type error --- scripts/decode.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/decode.js b/scripts/decode.js index d4cdbbd..b5756fd 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -146,8 +146,7 @@ class Decode { if (blocks.length === 1) { tokens = this._wrap(chunk, listBy); } else { - let items = []; - items = blocks.map((block) => (this._wrap(block, listBy))); + const items = blocks.map((block) => (this._wrap(block, listBy))); items.forEach((item, i) => { if (i > 0) { const c = tokens.pop(); @@ -215,7 +214,7 @@ class Decode { * @private */ _checkLength(newCount) { - if ((this.countTokens + newCount) > this.maxLength) throw new Error('Tokens count is greater than the limit.'); + if ((this.countTokens + newCount) > this.maxLength) throw new RangeError('Tokens count is greater than the limit.'); } } From 71f950c8d862bd59292267d9cb30b7b8b7f83f3d Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Tue, 24 Dec 2019 11:42:59 +0500 Subject: [PATCH 36/44] fix work encoder --- scripts/encode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/encode.js b/scripts/encode.js index dff908c..d8433df 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -44,8 +44,8 @@ class Encode { if (tokens.length < 3) { return tokens.join(','); } + const sortedTokens = tokens.sort(); const min = tokens[0]; - const sortedTokens = tokens.sort((a, b) => a - b); let compressedString = `${min}`; let rangeStart = false; From 81265349ce3bca0cfc45d410cd909544155121b4 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Tue, 24 Dec 2019 11:43:30 +0500 Subject: [PATCH 37/44] fix index.js --- test/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.js b/test/index.js index f456060..c5b8995 100644 --- a/test/index.js +++ b/test/index.js @@ -64,4 +64,4 @@ describe('decoding', () => { assert.deepEqual(testDecode.parse('~.54x13:1010x11'), [5, 6, 7, 8, 9, 12, 22, 33, 44, 55, 66, 77, 88, 99, 110, 121, 132]); }); -}); \ No newline at end of file +}); From cf8feb4809e81d7f419443d165d09c2c7ec8aad5 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Tue, 24 Dec 2019 17:45:54 +0500 Subject: [PATCH 38/44] fix sorting --- scripts/encode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/encode.js b/scripts/encode.js index d8433df..a4cf3f4 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -90,7 +90,7 @@ class Encode { * @private */ static _deltaCompression(tokens) { - tokens.sort(); + tokens.sort((a, b) => a - b); const diffTokens = []; tokens.forEach((token, i) => { i !== 0 ? diffTokens.push(token - tokens[i - 1]) : diffTokens.push(token); From 925614aadd6ca60ed6484c011cf511b04ebd19e5 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Tue, 24 Dec 2019 18:17:47 +0500 Subject: [PATCH 39/44] fix jsdoc --- scripts/encode.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/encode.js b/scripts/encode.js index a4cf3f4..ad3b454 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -14,7 +14,8 @@ class Encode { * Encode array tokens to string * * @param tokens array of tokens - * @param mode where 1 - encode to simple string, 2 - encode to delta string + * @param mode where 1 - encode to simple string, 2 - encode to delta string. + * Default: MODE_SIMPLE_STRING * @return {string} encoding string */ parse(tokens, mode = this.MODE_SIMPLE_STRING) { @@ -102,7 +103,7 @@ class Encode { * Forming x-blocks from difference tokens * * @param tokens - * @return {[]} + * @return {string[]} * @private */ static _xBlocks(tokens) { From e8a5c6fbc095dfa4b43d2808cbfb85722a4c07f3 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Wed, 25 Dec 2019 11:10:59 +0500 Subject: [PATCH 40/44] fix sort --- scripts/encode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/encode.js b/scripts/encode.js index ad3b454..c55891b 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -45,7 +45,7 @@ class Encode { if (tokens.length < 3) { return tokens.join(','); } - const sortedTokens = tokens.sort(); + const sortedTokens = tokens.sort((a, b) => a - b); const min = tokens[0]; let compressedString = `${min}`; From 1120b913dc73575509d6b784fc64db68da68f650 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 27 Dec 2019 11:46:28 +0500 Subject: [PATCH 41/44] add constants in separate file constants/index.js --- constants/index.js | 21 +++++++++++++++++++++ scripts/decode.js | 32 +++++++++++++++----------------- scripts/encode.js | 32 +++++++++++++++++--------------- 3 files changed, 53 insertions(+), 32 deletions(-) create mode 100644 constants/index.js diff --git a/constants/index.js b/constants/index.js new file mode 100644 index 0000000..87178c8 --- /dev/null +++ b/constants/index.js @@ -0,0 +1,21 @@ +const DELTA = '~'; +const MULTIPLICATION = 'x'; +const NUM_DELIMITER = ','; +const DELTA_LIST_BY_ONE = '.'; +const DELTA_LIST_BY_TWO = ':'; +const ZIP_START_DELIMITER = '('; +const ZIP_END_DELIMITER = ')'; +const MODE_SIMPLE_STRING = 1; +const MODE_DELTA_STRING = 2; + +module.exports = { + DELTA, + MULTIPLICATION, + NUM_DELIMITER, + DELTA_LIST_BY_ONE, + DELTA_LIST_BY_TWO, + ZIP_START_DELIMITER, + ZIP_END_DELIMITER, + MODE_SIMPLE_STRING, + MODE_DELTA_STRING, +}; diff --git a/scripts/decode.js b/scripts/decode.js index b5756fd..ad73bb3 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -1,10 +1,7 @@ +const constants = require('../constants/index.js'); + class Decode { constructor(maxLength = 1000000) { - this.NUM_DELIMITER = ','; - this.DELTA_LIST_BY_ONE = '.'; - this.DELTA_LIST_BY_TWO = ':'; - this.ZIP_START_DELIMITER = '('; - this.ZIP_END_DELIMITER = ')'; this.intBase = 10; this.maxLength = maxLength; this.countTokens = 0; @@ -24,7 +21,7 @@ class Decode { let items; // Parse base for int - if (string.startsWith('x')) { + if (string.startsWith(constants.MULTIPLICATION)) { let base; [base, string] = string.split(';'); this.intBase = parseInt(base.slice(1), 10); @@ -33,7 +30,7 @@ class Decode { } // Parse empty string as empty list - if (string.startsWith('~')) { + if (string.startsWith(constants.DELTA)) { items = this.parseDelta(string.slice(1)); } else { items = this.parseString(string); @@ -54,9 +51,9 @@ class Decode { // eslint-disable-next-line no-restricted-syntax for (const ltr of string) { - if (ltr === this.ZIP_START_DELIMITER) zipBuff.push(1); - if (ltr === this.ZIP_END_DELIMITER) zipBuff.pop(); - if (zipBuff.length === 0 && ltr === this.NUM_DELIMITER) { + if (ltr === constants.ZIP_START_DELIMITER) zipBuff.push(1); + if (ltr === constants.ZIP_END_DELIMITER) zipBuff.pop(); + if (zipBuff.length === 0 && ltr === constants.NUM_DELIMITER) { this._parseToken(buff).forEach((item) => { tokens.push(item); }); @@ -104,9 +101,9 @@ class Decode { */ _parseToken(token) { let tokens = []; - if (token.indexOf(this.ZIP_START_DELIMITER) > -1) { + if (token.indexOf(constants.ZIP_START_DELIMITER) > -1) { // eslint-disable-next-line prefer-const - let [base, subString] = token.split(this.ZIP_START_DELIMITER); + let [base, subString] = token.split(constants.ZIP_START_DELIMITER); base = parseInt(base, 10); const items = this.parseString(subString.slice(0, subString.length - 1)); items.forEach((item) => tokens.push(item + base)); @@ -137,10 +134,10 @@ class Decode { _parseDeltaChunks(chunk) { let listBy; let tokens = []; - if (chunk.startsWith(this.DELTA_LIST_BY_ONE)) listBy = 1; - if (chunk.startsWith(this.DELTA_LIST_BY_TWO)) listBy = 2; + if (chunk.startsWith(constants.DELTA_LIST_BY_ONE)) listBy = 1; + if (chunk.startsWith(constants.DELTA_LIST_BY_TWO)) listBy = 2; if (listBy) chunk = chunk.slice(1); - const blocks = chunk.split('x'); + const blocks = chunk.split(constants.MULTIPLICATION); if (listBy) { if (blocks.length === 1) { @@ -173,15 +170,16 @@ class Decode { * @param string for split into chunks * @return [] of chunks */ + // eslint-disable-next-line class-methods-use-this _deltaChunks(string) { const chunks = []; let buf = ''; // eslint-disable-next-line no-restricted-syntax for (const ltr of string) { - if (ltr === this.NUM_DELIMITER) { + if (ltr === constants.NUM_DELIMITER) { (buf !== '') && chunks.push(buf); buf = ''; - } else if (ltr === this.DELTA_LIST_BY_ONE || ltr === this.DELTA_LIST_BY_TWO) { + } else if (ltr === constants.DELTA_LIST_BY_ONE || ltr === constants.DELTA_LIST_BY_TWO) { (buf !== '') && chunks.push(buf); buf = ltr; } else { diff --git a/scripts/encode.js b/scripts/encode.js index c55891b..6dd8d19 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -1,3 +1,5 @@ +const constants = require('../constants/index.js'); + class Encode { /** * @return {string} @@ -5,8 +7,6 @@ class Encode { constructor( maxLength = 1000000, ) { - this.MODE_SIMPLE_STRING = 1; - this.MODE_DELTA_STRING = 2; this.maxLength = maxLength; } @@ -18,17 +18,17 @@ class Encode { * Default: MODE_SIMPLE_STRING * @return {string} encoding string */ - parse(tokens, mode = this.MODE_SIMPLE_STRING) { + parse(tokens, mode = constants.MODE_SIMPLE_STRING) { if (!tokens || !Array.isArray(tokens)) { throw new TypeError('tokens argument should be an array of integers'); } if (tokens.length > this.maxLength) { throw new RangeError('array size is higher than allowed'); } - if (mode === this.MODE_SIMPLE_STRING) { + if (mode === constants.MODE_SIMPLE_STRING) { return (this.constructor.encodeString(tokens)); } - if (mode === this.MODE_DELTA_STRING) { + if (mode === constants.MODE_DELTA_STRING) { return (this.constructor.encodeDelta(tokens)); } throw new Error('you must select 1 or 2 at second parameter (1 - simple string, 2 - delta string)'); @@ -43,7 +43,7 @@ class Encode { static encodeString(tokens) { if (tokens.length === 0) return ''; if (tokens.length < 3) { - return tokens.join(','); + return tokens.join(constants.NUM_DELIMITER); } const sortedTokens = tokens.sort((a, b) => a - b); const min = tokens[0]; @@ -66,7 +66,7 @@ class Encode { }); values = values.map((item) => (typeof item === 'number' ? item : `${item[0]}-${item[1]}`)); - compressedString = `${compressedString}(${values.join(',')})`; + compressedString = `${compressedString}(${values.join(constants.NUM_DELIMITER)})`; return compressedString; } @@ -77,7 +77,7 @@ class Encode { * @return {string} compressed string */ static encodeDelta(tokens) { - if (tokens.length === 0) return '~'; + if (tokens.length === 0) return constants.DELTA; const sortedTokens = this._deltaCompression(tokens); const chunks = this._xBlocks(sortedTokens); return this._compressToString(chunks); @@ -127,22 +127,24 @@ class Encode { * @private */ static _compressToString(chunks) { - let del = ','; + let del = constants.NUM_DELIMITER; let newDel = null; let compressedString = ''; chunks.forEach((chunk) => { - if (chunk.indexOf('x') > -1) { - const [x, val] = chunk.split('x'); + if (chunk.indexOf(constants.MULTIPLICATION) > -1) { + const [x, val] = chunk.split(constants.MULTIPLICATION); if (x.length === val.length) { - newDel = (val.length === 1 ? '.' : (val.length === 2 ? ':' : ',')); + newDel = (val.length === 1 ? constants.DELTA_LIST_BY_ONE : (val.length === 2 + ? constants.DELTA_LIST_BY_TWO : constants.NUM_DELIMITER)); } else { - newDel = ','; + newDel = constants.NUM_DELIMITER; } } else { - newDel = (chunk.length === 1 ? '.' : (chunk.length === 2 ? ':' : ',')); + newDel = (chunk.length === 1 ? constants.DELTA_LIST_BY_ONE : (chunk.length === 2 + ? constants.DELTA_LIST_BY_TWO : constants.NUM_DELIMITER)); } - if (newDel === ',' || newDel !== del) { + if (newDel === constants.NUM_DELIMITER || newDel !== del) { compressedString += newDel; } compressedString += chunk; From f09f545f05cdfa4d7403fb519acda0a1a5a0655f Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 27 Dec 2019 12:15:50 +0500 Subject: [PATCH 42/44] exchange static methods to private methods --- .eslintrc.js | 3 ++- scripts/encode.js | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index a05b06c..ec3c615 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -19,6 +19,7 @@ module.exports = { "no-param-reassign": [0], "no-underscore-dangle": [0], "no-unused-expressions": [0], - "no-nested-ternary": [0] + "no-nested-ternary": [0], + "class-methods-use-this": [0] }, }; diff --git a/scripts/encode.js b/scripts/encode.js index 6dd8d19..dc36b12 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -26,10 +26,10 @@ class Encode { throw new RangeError('array size is higher than allowed'); } if (mode === constants.MODE_SIMPLE_STRING) { - return (this.constructor.encodeString(tokens)); + return (this._encodeString(tokens)); } if (mode === constants.MODE_DELTA_STRING) { - return (this.constructor.encodeDelta(tokens)); + return (this._encodeDelta(tokens)); } throw new Error('you must select 1 or 2 at second parameter (1 - simple string, 2 - delta string)'); } @@ -40,7 +40,7 @@ class Encode { * @param tokens * @return {string} compressed string */ - static encodeString(tokens) { + _encodeString(tokens) { if (tokens.length === 0) return ''; if (tokens.length < 3) { return tokens.join(constants.NUM_DELIMITER); @@ -76,7 +76,7 @@ class Encode { * @param tokens * @return {string} compressed string */ - static encodeDelta(tokens) { + _encodeDelta(tokens) { if (tokens.length === 0) return constants.DELTA; const sortedTokens = this._deltaCompression(tokens); const chunks = this._xBlocks(sortedTokens); @@ -90,7 +90,7 @@ class Encode { * @return {[]} sorted array of difference tokens * @private */ - static _deltaCompression(tokens) { + _deltaCompression(tokens) { tokens.sort((a, b) => a - b); const diffTokens = []; tokens.forEach((token, i) => { @@ -106,7 +106,7 @@ class Encode { * @return {string[]} * @private */ - static _xBlocks(tokens) { + _xBlocks(tokens) { let buf = []; const tokensCopy = []; tokens.forEach((token, i) => { @@ -126,7 +126,7 @@ class Encode { * @return {string} compressedString * @private */ - static _compressToString(chunks) { + _compressToString(chunks) { let del = constants.NUM_DELIMITER; let newDel = null; let compressedString = ''; From 9545c80d24a3e8f2cfe5e55199d059720b7ca504 Mon Sep 17 00:00:00 2001 From: "bukina.e" Date: Fri, 27 Dec 2019 12:54:26 +0500 Subject: [PATCH 43/44] docs in readme --- README.md | 59 ++++++++++++++++++++++++++++++++++++----------- scripts/decode.js | 34 +++++++++++++++++---------- scripts/encode.js | 5 +++- 3 files changed, 72 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index b2f95de..a924c1d 100644 --- a/README.md +++ b/README.md @@ -45,31 +45,64 @@ zip.decode('~.123'); ``` ## API -### encode(tokens, [mode]) + -#### tokens + -Type: `Object` `Object[]` +## Encode +**Kind**: global class -Array of tokens. +* [Encode](#Encode) + * [new Encode(maxLength)](#new_Encode_new) + * [.parse(tokens, mode)](#Encode+parse) ⇒ string -#### mode + -Type: `number` +### new Encode(maxLength) -Number 1 or 2 for description selecting of method (simple string or delta) +| Param | Default | +| --- | --- | +| maxLength | 1000000 | -##### return string `string` + +### encode.parse(tokens, mode) ⇒ string +Encode array tokens to string -### decode(string) +**Kind**: instance method of [Encode](#Encode) +**Returns**: string - encoding string -#### string +| Param | Description | +| --- | --- | +| tokens | array of tokens | +| mode | where 1 - encode to simple string, 2 - encode to delta string. Default: MODE_SIMPLE_STRING | -Type: `string` + -String of compressed tokens. +## Decode +**Kind**: global class -##### return tokens `Object` `Object[]` +* [Decode](#Decode) + * [new Decode(maxLength)](#new_Decode_new) + * [.parse(string)](#Decode+parse) ⇒ Array.<number> + +### new Decode(maxLength) + +| Param | Default | +| --- | --- | +| maxLength | 1000000 | + + + +### decode.parse(string) ⇒ Array.<number> +Parse string to array of encoding numbers + +**Kind**: instance method of [Decode](#Decode) + +| Param | +| --- | +| string | + + diff --git a/scripts/decode.js b/scripts/decode.js index ad73bb3..1c27dc9 100644 --- a/scripts/decode.js +++ b/scripts/decode.js @@ -1,6 +1,10 @@ const constants = require('../constants/index.js'); class Decode { + /** + * @param maxLength + * @return {number[]} + */ constructor(maxLength = 1000000) { this.intBase = 10; this.maxLength = maxLength; @@ -11,7 +15,7 @@ class Decode { * Parse string to array of encoding numbers * * @param string - * @returns {[]|*[]} + * @returns {number[]} */ parse(string) { if (!string) { @@ -31,9 +35,9 @@ class Decode { // Parse empty string as empty list if (string.startsWith(constants.DELTA)) { - items = this.parseDelta(string.slice(1)); + items = this._parseDelta(string.slice(1)); } else { - items = this.parseString(string); + items = this._parseString(string); } return items; @@ -43,9 +47,10 @@ class Decode { * Parse string to tokens * * @param string - * @return {[]} + * @return {number[]} + * @private */ - parseString(string) { + _parseString(string) { let buff = ''; const tokens = []; const zipBuff = []; @@ -73,9 +78,10 @@ class Decode { * Parse string by delta * * @param string - * @return {[]} array with tokens + * @return {number[]} array with tokens + * @private */ - parseDelta(string) { + _parseDelta(string) { let tokens = []; const chunks = this._deltaChunks(string); @@ -97,7 +103,8 @@ class Decode { * Parse token from string * * @param token - * @return {[]} array with tokens + * @return {number[]} array with tokens + * @private */ _parseToken(token) { let tokens = []; @@ -105,7 +112,7 @@ class Decode { // eslint-disable-next-line prefer-const let [base, subString] = token.split(constants.ZIP_START_DELIMITER); base = parseInt(base, 10); - const items = this.parseString(subString.slice(0, subString.length - 1)); + const items = this._parseString(subString.slice(0, subString.length - 1)); items.forEach((item) => tokens.push(item + base)); return tokens; } @@ -129,7 +136,8 @@ class Decode { * Parse chunk of delta * * @param chunk - * @return {[]} array with tokens + * @return {number[]} array with tokens + * @private */ _parseDeltaChunks(chunk) { let listBy; @@ -168,7 +176,8 @@ class Decode { * Yield chunks for delta string * * @param string for split into chunks - * @return [] of chunks + * @return {string[]} of chunks + * @private */ // eslint-disable-next-line class-methods-use-this _deltaChunks(string) { @@ -195,7 +204,8 @@ class Decode { * * @param string * @param count symbols - * @returns {[]} list of several strings + * @returns {string[]} list of several strings + * @private */ _wrap(string, count) { const list = []; diff --git a/scripts/encode.js b/scripts/encode.js index dc36b12..38e7cf5 100644 --- a/scripts/encode.js +++ b/scripts/encode.js @@ -2,6 +2,7 @@ const constants = require('../constants/index.js'); class Encode { /** + * @param maxLength * @return {string} */ constructor( @@ -39,6 +40,7 @@ class Encode { * * @param tokens * @return {string} compressed string + * @private */ _encodeString(tokens) { if (tokens.length === 0) return ''; @@ -75,6 +77,7 @@ class Encode { * * @param tokens * @return {string} compressed string + * @private */ _encodeDelta(tokens) { if (tokens.length === 0) return constants.DELTA; @@ -87,7 +90,7 @@ class Encode { * Converting array of tokens to sorted array of difference tokens * * @param tokens - * @return {[]} sorted array of difference tokens + * @return {number[]} sorted array of difference tokens * @private */ _deltaCompression(tokens) { From de8a082992612c061bad19f3b373469208d39135 Mon Sep 17 00:00:00 2001 From: Nikita Korshunov Date: Sat, 28 Dec 2019 16:43:45 +0500 Subject: [PATCH 44/44] Update module exports, JSDoc and README.md --- README.md | 81 +++++++++++++++++---------------------------------- index.js | 15 ++++++++++ test/index.js | 5 ++-- 3 files changed, 45 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index a924c1d..ba2cc32 100644 --- a/README.md +++ b/README.md @@ -27,10 +27,10 @@ const zip = require('zip-numbers'); zip.encode([1,3,6]); //=> '1(0,2,5)' -zip.encode([1,3,6], 1); +zip.encode([1,3,6], zip.constants.MODE_SIMPLE_STRING); //=> '1(0,2,5)' -zip.encode([1,3,6], 2); +zip.encode([1,3,6], zip.constants.MODE_DELTA_STRING); //=> '~.123' ``` #### Decode: @@ -44,65 +44,38 @@ zip.decode('~.123'); //=> [1, 3, 6] ``` -## API - +## Functions - +
+
encode(tokens, [mode])string
+

Encodes an array of tokens into a string.

+
+
decode(string)Array.<number>
+

Decodes a string into an array of tokens.

+
+
-## Encode -**Kind**: global class + -* [Encode](#Encode) - * [new Encode(maxLength)](#new_Encode_new) - * [.parse(tokens, mode)](#Encode+parse) ⇒ string +## encode(tokens, [mode]) ⇒ string +Encodes an array of tokens into a string. + +**Returns**: string - Encoded string. - +| Param | Type | Default | Description | +| ------ | --------------------------------- | ------------------------------- | ------------------------------------------------------------------- | +| tokens | Array.<number> | | Array of tokens. | +| [mode] | number | MODE_SIMPLE_STRING | Mode: MODE_SIMPLE_STRING or MODE_DELTA_STRING. See: `zip.constants` | -### new Encode(maxLength) + -| Param | Default | -| --- | --- | -| maxLength | 1000000 | +## decode(string) ⇒ Array.<number> +Decodes a string into an array of tokens. - +**Returns**: Array.<number> - Array of tokens. -### encode.parse(tokens, mode) ⇒ string -Encode array tokens to string +| Param | Type | Description | +| ------ | ------------------- | --------------- | +| string | string | Encoded string. | -**Kind**: instance method of [Encode](#Encode) -**Returns**: string - encoding string -| Param | Description | -| --- | --- | -| tokens | array of tokens | -| mode | where 1 - encode to simple string, 2 - encode to delta string. Default: MODE_SIMPLE_STRING | - - - -## Decode -**Kind**: global class - -* [Decode](#Decode) - * [new Decode(maxLength)](#new_Decode_new) - * [.parse(string)](#Decode+parse) ⇒ Array.<number> - - - -### new Decode(maxLength) - -| Param | Default | -| --- | --- | -| maxLength | 1000000 | - - - -### decode.parse(string) ⇒ Array.<number> -Parse string to array of encoding numbers - -**Kind**: instance method of [Decode](#Decode) - -| Param | -| --- | -| string | - - diff --git a/index.js b/index.js index 6244aba..11fb74e 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,23 @@ const Encode = require('./scripts/encode'); const Decode = require('./scripts/decode'); +const constants = require('./constants'); +/** + * Encodes an array of tokens into a string. + * @param {number[]} tokens Array of tokens. + * @param {number} [mode=MODE_SIMPLE_STRING] Mode: MODE_SIMPLE_STRING or MODE_DELTA_STRING. + * See: `zip.constants` + * @returns {string} Encoded string. + */ const encode = (tokens, mode) => new Encode().parse(tokens, mode); + +/** + * Decodes a string into an array of tokens. + * @param {string} string Encoded string. + * @returns {number[]} Array of tokens. + */ const decode = (string) => new Decode().parse(string); exports.encode = encode; exports.decode = decode; +exports.constants = constants; diff --git a/test/index.js b/test/index.js index c5b8995..29ec168 100644 --- a/test/index.js +++ b/test/index.js @@ -1,6 +1,7 @@ const assert = require('assert'); const Encode = require('../scripts/encode'); const Decode = require('../scripts/decode'); +const { MODE_DELTA_STRING } = require('../constants'); const testEncode = new Encode(); const testDecode = new Decode(); @@ -17,8 +18,8 @@ describe('encoding', () => { assert.equal(testEncode.parse([1, 2, 3, 5, 6, 7, 9]), '1(0-2,4-6,8)'); }); it('For test making delta string', () => { - assert.equal(testEncode.parse([], 2), '~'); - assert.equal(testEncode.parse([1, 3, 6], 2), '~.123'); + assert.equal(testEncode.parse([], MODE_DELTA_STRING), '~'); + assert.equal(testEncode.parse([1, 3, 6], MODE_DELTA_STRING), '~.123'); }); });