Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating scripts encode, decode + tests #1

Open
wants to merge 45 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
7bbf061
functions for delta-strings (compressing delta-string)
Dec 19, 2019
c4cff19
function deltaCompression (sorting array and return array of differen…
Dec 19, 2019
4f65c1c
selecting modes (simple_string=1, delta_string=2)
Dec 19, 2019
c4fdc6a
add parameter baseInt ( works "Strings with base of numbers"
Dec 19, 2019
c1eebf3
add function for Delta strings with x-ranges
Dec 19, 2019
481acd3
fix parameter intBase in decode.js
Dec 19, 2019
1987410
fix files with eslint
Dec 19, 2019
504ce26
encode to class
Dec 20, 2019
db3fb19
fix encode to class
Dec 20, 2019
77cf8c3
decode to class
Dec 20, 2019
91f6ac4
add methods with underscore (private methods)
Dec 20, 2019
8b39ce1
add methods with underscore (private methods)
Dec 20, 2019
6125e72
fix decode
Dec 20, 2019
5dbf301
install dependencies: eslint, mocha
Dec 20, 2019
6794ce1
module exports class
Dec 20, 2019
238721d
module exports Encode
Dec 20, 2019
87bea10
add test for encode
Dec 20, 2019
b8b8abd
fix index.js
Dec 20, 2019
423bc08
rules for linter
Dec 20, 2019
aac5fd9
fix by eslint
Dec 20, 2019
75fa8d0
rules by eslint
Dec 20, 2019
2592262
fix by eslint
Dec 20, 2019
6626a06
tests passing (besides strings with base of numbers)
Dec 20, 2019
66b2d34
work with Strings with base of numbers
Dec 20, 2019
d5d801c
checking maxLength
Dec 20, 2019
72076a0
readme v1.0
Dec 20, 2019
fe2b70e
create functions encode, decode for interface
Dec 20, 2019
9bf5e87
update version
Dec 20, 2019
8526506
readme v.1.0.1
Dec 20, 2019
45b4c06
fix readme
Dec 20, 2019
4a717bb
fix readme.md
remort Dec 23, 2019
742c27c
change eslint's environment
Dec 24, 2019
f67a73d
error processing
Dec 24, 2019
675d09b
add keywords, license and fix scripts
Dec 24, 2019
dfb596d
change type error
Dec 24, 2019
71f950c
fix work encoder
Dec 24, 2019
8126534
fix index.js
Dec 24, 2019
a4ee130
Merge remote-tracking branch 'origin/develop' into develop
Dec 24, 2019
cf8feb4
fix sorting
Dec 24, 2019
925614a
fix jsdoc
Dec 24, 2019
e8a5c6f
fix sort
Dec 25, 2019
1120b91
add constants in separate file constants/index.js
Dec 27, 2019
f09f545
exchange static methods to private methods
Dec 27, 2019
9545c80
docs in readme
Dec 27, 2019
de8a082
Update module exports, JSDoc and README.md
Dec 28, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module.exports = {
env: {
browser: true,
es6: true,
mocha: true,
},
extends: [
'airbnb-base',
],
globals: {
Atomics: 'readonly',
SharedArrayBuffer: 'readonly',
},
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
},
rules: {
"no-param-reassign": [0],
"no-underscore-dangle": [0],
"no-unused-expressions": [0],
"no-nested-ternary": [0],
"class-methods-use-this": [0]
},
};
80 changes: 78 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,81 @@
# zip-numbers

Алгоритмы сжатия списков чисел для передачи в тестовом виде. В реализацию входят парсер строк и поле для django-rest-framework.
Алгоритмы сжатия списков чисел для передачи в текстовом виде. В реализацию входят парсер строк и поле для django-rest-framework.

Поддерживаются 2 способа сжатия: диапазоны с выносом за скобку и дельта-строки.

## Информация

1. Сжимает строку по одному из двух способов сжатия, который можно выбрать:
1. диапазоны с выносом за скобку
2. дельта-строки

2. Разжимает строку, сжатую по одному из двух алгоритмов.

## Установка

```
$ npm install zip-numbers
```


## Примеры
#### Encode:
```js
const zip = require('zip-numbers');

zip.encode([1,3,6]);
//=> '1(0,2,5)'

zip.encode([1,3,6], zip.constants.MODE_SIMPLE_STRING);
//=> '1(0,2,5)'

zip.encode([1,3,6], zip.constants.MODE_DELTA_STRING);
//=> '~.123'
```
#### Decode:
```js
const zip = require('zip-numbers');

zip.decode('1(0,2,5)');
//=> [1, 3, 6]

zip.decode('~.123');
//=> [1, 3, 6]
```

## Functions

<dl>
<dt><a href="#encode">encode(tokens, [mode])</a> ⇒ <code>string</code></dt>
<dd><p>Encodes an array of tokens into a string.</p>
</dd>
<dt><a href="#decode">decode(string)</a> ⇒ <code>Array.&lt;number&gt;</code></dt>
<dd><p>Decodes a string into an array of tokens.</p>
</dd>
</dl>

<a name="encode"></a>

## encode(tokens, [mode]) ⇒ <code>string</code>
Encodes an array of tokens into a string.

**Returns**: <code>string</code> - Encoded string.

| Param | Type | Default | Description |
| ------ | --------------------------------- | ------------------------------- | ------------------------------------------------------------------- |
| tokens | <code>Array.&lt;number&gt;</code> | | Array of tokens. |
| [mode] | <code>number</code> | <code>MODE_SIMPLE_STRING</code> | Mode: MODE_SIMPLE_STRING or MODE_DELTA_STRING. See: `zip.constants` |

<a name="decode"></a>

## decode(string) ⇒ <code>Array.&lt;number&gt;</code>
Decodes a string into an array of tokens.

**Returns**: <code>Array.&lt;number&gt;</code> - Array of tokens.

| Param | Type | Description |
| ------ | ------------------- | --------------- |
| string | <code>string</code> | Encoded string. |


Поддерживаются 2 способа сжатия: диапазоны с выносом за скобку и дельта-строки.
21 changes: 21 additions & 0 deletions constants/index.js
Original file line number Diff line number Diff line change
@@ -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,
};
237 changes: 16 additions & 221 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,228 +1,23 @@

const NUM_DELIMITER = ',';
const DELTA_LIST_BY_ONE = '.';
const DELTA_LIST_BY_TWO = ':';
const ZIP_START_DELIMITER = '(';
const ZIP_END_DELIMITER = ')';

const Encode = require('./scripts/encode');
const Decode = require('./scripts/decode');
const constants = require('./constants');

/**
* Parse string to array of encoding numbers
*
* @param string
* @returns {[]|*[]}
* 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 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;
};
const encode = (tokens, mode) => new Encode().parse(tokens, mode);

/**
* Parse string to tokens
*
* @param string
* @return {[]}
* Decodes a string into an array of tokens.
* @param {string} string Encoded string.
* @returns {number[]} Array of tokens.
*/
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<string.length; i+=count) {
list.push(parseInt(string.slice(i, i+count), 10));
}
return list;
};


// 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)');
// 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,');


const decode = (string) => new Decode().parse(string);

exports.encode = encode;
exports.decode = decode;
exports.constants = constants;
Loading