Spaces:
Sleeping
Sleeping
Viktoria435 commited on
Commit ·
916df2b
1
Parent(s): 22df730
Refactor serialization logic in BookService, VisitorService, and WorkerService
Browse files- Simplified the serialization of book, visitor, and worker objects by removing unnecessary asynchronous calls to serializeTxtRow.
- Updated the writeLines method to directly use the synchronous map function for improved performance.
- Removed unused key-manager, crypto, lzss, and offset-encryption utility files to clean up the codebase.
- src/book/book.service.ts +5 -13
- src/common/key-manager.ts +0 -51
- src/utils/crypto.utils.ts +0 -23
- src/utils/file.utils.ts +2 -14
- src/utils/lzss.util.ts +0 -165
- src/utils/offset-encryption.util.ts +0 -55
- src/visitor/visitor.service.ts +5 -13
- src/worker/worker.service.ts +4 -12
src/book/book.service.ts
CHANGED
|
@@ -34,7 +34,7 @@ export class BookService {
|
|
| 34 |
status: BookStatus.AVAILABLE,
|
| 35 |
};
|
| 36 |
const lines = await this.file.readLines();
|
| 37 |
-
lines.push(
|
| 38 |
await this.file.writeLines(lines);
|
| 39 |
return newBook;
|
| 40 |
}
|
|
@@ -44,9 +44,7 @@ export class BookService {
|
|
| 44 |
const index = books.findIndex((b) => b.id === id);
|
| 45 |
if (index === -1) return null;
|
| 46 |
books[index] = { ...books[index], ...dto };
|
| 47 |
-
await this.file.writeLines(
|
| 48 |
-
await Promise.all(books.map((book) => serializeTxtRow(book))),
|
| 49 |
-
);
|
| 50 |
return books[index];
|
| 51 |
}
|
| 52 |
|
|
@@ -55,9 +53,7 @@ export class BookService {
|
|
| 55 |
const index = books.findIndex((b) => b.id === id);
|
| 56 |
if (index === -1) return false;
|
| 57 |
books.splice(index, 1);
|
| 58 |
-
await this.file.writeLines(
|
| 59 |
-
await Promise.all(books.map((book) => serializeTxtRow(book))),
|
| 60 |
-
);
|
| 61 |
return true;
|
| 62 |
}
|
| 63 |
|
|
@@ -81,9 +77,7 @@ export class BookService {
|
|
| 81 |
borrowed.push(book);
|
| 82 |
}
|
| 83 |
|
| 84 |
-
await this.file.writeLines(
|
| 85 |
-
await Promise.all(books.map((book) => serializeTxtRow(book))),
|
| 86 |
-
);
|
| 87 |
return borrowed;
|
| 88 |
}
|
| 89 |
|
|
@@ -115,9 +109,7 @@ export class BookService {
|
|
| 115 |
returned.push(book);
|
| 116 |
}
|
| 117 |
|
| 118 |
-
await this.file.writeLines(
|
| 119 |
-
await Promise.all(books.map((book) => serializeTxtRow(book))),
|
| 120 |
-
);
|
| 121 |
return returned;
|
| 122 |
}
|
| 123 |
}
|
|
|
|
| 34 |
status: BookStatus.AVAILABLE,
|
| 35 |
};
|
| 36 |
const lines = await this.file.readLines();
|
| 37 |
+
lines.push(serializeTxtRow(newBook));
|
| 38 |
await this.file.writeLines(lines);
|
| 39 |
return newBook;
|
| 40 |
}
|
|
|
|
| 44 |
const index = books.findIndex((b) => b.id === id);
|
| 45 |
if (index === -1) return null;
|
| 46 |
books[index] = { ...books[index], ...dto };
|
| 47 |
+
await this.file.writeLines(books.map(serializeTxtRow));
|
|
|
|
|
|
|
| 48 |
return books[index];
|
| 49 |
}
|
| 50 |
|
|
|
|
| 53 |
const index = books.findIndex((b) => b.id === id);
|
| 54 |
if (index === -1) return false;
|
| 55 |
books.splice(index, 1);
|
| 56 |
+
await this.file.writeLines(books.map(serializeTxtRow));
|
|
|
|
|
|
|
| 57 |
return true;
|
| 58 |
}
|
| 59 |
|
|
|
|
| 77 |
borrowed.push(book);
|
| 78 |
}
|
| 79 |
|
| 80 |
+
await this.file.writeLines(books.map(serializeTxtRow));
|
|
|
|
|
|
|
| 81 |
return borrowed;
|
| 82 |
}
|
| 83 |
|
|
|
|
| 109 |
returned.push(book);
|
| 110 |
}
|
| 111 |
|
| 112 |
+
await this.file.writeLines(books.map(serializeTxtRow));
|
|
|
|
|
|
|
| 113 |
return returned;
|
| 114 |
}
|
| 115 |
}
|
src/common/key-manager.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
| 1 |
-
import { promises as fs } from 'fs';
|
| 2 |
-
import path from 'path';
|
| 3 |
-
import {
|
| 4 |
-
decryptWithAlphabet,
|
| 5 |
-
encryptWithAlphabet,
|
| 6 |
-
} from 'src/utils/offset-encryption.util';
|
| 7 |
-
|
| 8 |
-
const dataDir = path.join(process.cwd(), 'src/data/encrypted/');
|
| 9 |
-
const keyFile = path.join(dataDir, '.encryption_key');
|
| 10 |
-
|
| 11 |
-
const MASTER_KEY = process.env.MASTER_KEY || 'RSIOT_SECRET_KEY_VARIAHT1';
|
| 12 |
-
|
| 13 |
-
export async function ensureDataDir(): Promise<void> {
|
| 14 |
-
try {
|
| 15 |
-
await fs.access(dataDir);
|
| 16 |
-
} catch {
|
| 17 |
-
await fs.mkdir(dataDir, { recursive: true });
|
| 18 |
-
}
|
| 19 |
-
}
|
| 20 |
-
|
| 21 |
-
export async function getOrCreateKey(): Promise<string> {
|
| 22 |
-
await ensureDataDir();
|
| 23 |
-
|
| 24 |
-
try {
|
| 25 |
-
const encryptedKey = await fs.readFile(keyFile, 'utf-8');
|
| 26 |
-
return decryptWithAlphabet(encryptedKey, MASTER_KEY);
|
| 27 |
-
} catch (err: unknown) {
|
| 28 |
-
if (err instanceof Error && err.message.includes('ENOENT')) {
|
| 29 |
-
const newKey = generateRandomKey(16);
|
| 30 |
-
await saveKey(newKey);
|
| 31 |
-
return newKey;
|
| 32 |
-
}
|
| 33 |
-
throw err;
|
| 34 |
-
}
|
| 35 |
-
}
|
| 36 |
-
|
| 37 |
-
export async function saveKey(key: string): Promise<void> {
|
| 38 |
-
await ensureDataDir();
|
| 39 |
-
const encryptedKey = encryptWithAlphabet(key, MASTER_KEY);
|
| 40 |
-
await fs.writeFile(keyFile, encryptedKey, 'utf-8');
|
| 41 |
-
}
|
| 42 |
-
|
| 43 |
-
export function generateRandomKey(length: number): string {
|
| 44 |
-
const chars =
|
| 45 |
-
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*';
|
| 46 |
-
let key = '';
|
| 47 |
-
for (let i = 0; i < length; i++) {
|
| 48 |
-
key += chars.charAt(Math.floor(Math.random() * chars.length));
|
| 49 |
-
}
|
| 50 |
-
return key;
|
| 51 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/utils/crypto.utils.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
| 1 |
-
import { lzssEncode, lzssDecode } from './lzss.util';
|
| 2 |
-
import {
|
| 3 |
-
encryptWithAlphabet,
|
| 4 |
-
decryptWithAlphabet,
|
| 5 |
-
} from './offset-encryption.util';
|
| 6 |
-
import { getOrCreateKey } from 'src/common/key-manager';
|
| 7 |
-
|
| 8 |
-
export async function encryptData(data: string): Promise<string> {
|
| 9 |
-
const compressed = lzssEncode(data);
|
| 10 |
-
const key = await getOrCreateKey();
|
| 11 |
-
const encrypted = encryptWithAlphabet(compressed, key);
|
| 12 |
-
|
| 13 |
-
return encrypted;
|
| 14 |
-
}
|
| 15 |
-
|
| 16 |
-
export async function decryptData(encrypted: string): Promise<string> {
|
| 17 |
-
const key = await getOrCreateKey();
|
| 18 |
-
const decrypted = decryptWithAlphabet(encrypted, key);
|
| 19 |
-
const decompressed = lzssDecode(decrypted);
|
| 20 |
-
console.log('decompressed', decompressed);
|
| 21 |
-
|
| 22 |
-
return decompressed;
|
| 23 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/utils/file.utils.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
| 1 |
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
| 2 |
import { Link } from '../common/Link';
|
| 3 |
-
import { decryptData, encryptData } from './crypto.utils';
|
| 4 |
-
|
| 5 |
function isLinkString(value: string | undefined) {
|
| 6 |
if (!value) return false;
|
| 7 |
return /^[a-zA-Z]+:[^:]+$/.test(value);
|
| 8 |
}
|
| 9 |
|
| 10 |
-
function
|
| 11 |
if (typeof row !== 'string') {
|
| 12 |
throw new Error('parseTxtRow: row is not string: ' + JSON.stringify(row));
|
| 13 |
}
|
|
@@ -53,7 +51,7 @@ function parseTxtRowInternal(row: string): any {
|
|
| 53 |
return obj;
|
| 54 |
}
|
| 55 |
|
| 56 |
-
function
|
| 57 |
return Object.entries(obj)
|
| 58 |
.map(([key, value]) => {
|
| 59 |
if (value instanceof Link) {
|
|
@@ -76,13 +74,3 @@ function serializeTxtRowInternal(obj: any): string {
|
|
| 76 |
})
|
| 77 |
.join(';');
|
| 78 |
}
|
| 79 |
-
|
| 80 |
-
export async function parseTxtRow(encryptedRow: string): Promise<any> {
|
| 81 |
-
const decrypted = await decryptData(encryptedRow);
|
| 82 |
-
return parseTxtRowInternal(decrypted);
|
| 83 |
-
}
|
| 84 |
-
|
| 85 |
-
export async function serializeTxtRow(obj: any): Promise<string> {
|
| 86 |
-
const serialized = serializeTxtRowInternal(obj);
|
| 87 |
-
return await encryptData(serialized);
|
| 88 |
-
}
|
|
|
|
| 1 |
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
| 2 |
import { Link } from '../common/Link';
|
|
|
|
|
|
|
| 3 |
function isLinkString(value: string | undefined) {
|
| 4 |
if (!value) return false;
|
| 5 |
return /^[a-zA-Z]+:[^:]+$/.test(value);
|
| 6 |
}
|
| 7 |
|
| 8 |
+
export function parseTxtRow(row: string): any {
|
| 9 |
if (typeof row !== 'string') {
|
| 10 |
throw new Error('parseTxtRow: row is not string: ' + JSON.stringify(row));
|
| 11 |
}
|
|
|
|
| 51 |
return obj;
|
| 52 |
}
|
| 53 |
|
| 54 |
+
export function serializeTxtRow(obj: any): string {
|
| 55 |
return Object.entries(obj)
|
| 56 |
.map(([key, value]) => {
|
| 57 |
if (value instanceof Link) {
|
|
|
|
| 74 |
})
|
| 75 |
.join(';');
|
| 76 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/utils/lzss.util.ts
DELETED
|
@@ -1,165 +0,0 @@
|
|
| 1 |
-
export interface LZSSMatch {
|
| 2 |
-
offset: number;
|
| 3 |
-
length: number;
|
| 4 |
-
}
|
| 5 |
-
|
| 6 |
-
export interface LZSSToken {
|
| 7 |
-
type: 'literal' | 'match';
|
| 8 |
-
value: string | LZSSMatch;
|
| 9 |
-
}
|
| 10 |
-
|
| 11 |
-
// Параметры LZSS
|
| 12 |
-
const WINDOW_SIZE = 4096; // Размер окна поиска (12 бит)
|
| 13 |
-
const LOOKAHEAD_SIZE = 18; // Размер буфера упреждения
|
| 14 |
-
const MIN_MATCH_LENGTH = 3; // Минимальная длина совпадения
|
| 15 |
-
|
| 16 |
-
export function lzssEncode(text: string): string {
|
| 17 |
-
if (!text) return '';
|
| 18 |
-
|
| 19 |
-
const tokens: LZSSToken[] = [];
|
| 20 |
-
let pos = 0;
|
| 21 |
-
|
| 22 |
-
while (pos < text.length) {
|
| 23 |
-
let bestMatch: LZSSMatch | null = null;
|
| 24 |
-
let bestLength = 0;
|
| 25 |
-
|
| 26 |
-
// Определяем начало окна поиска
|
| 27 |
-
const windowStart = Math.max(0, pos - WINDOW_SIZE);
|
| 28 |
-
const lookaheadEnd = Math.min(text.length, pos + LOOKAHEAD_SIZE);
|
| 29 |
-
|
| 30 |
-
// Ищем самое длинное совпадение в окне
|
| 31 |
-
for (let i = windowStart; i < pos; i++) {
|
| 32 |
-
let matchLength = 0;
|
| 33 |
-
|
| 34 |
-
// Считаем длину совпадения
|
| 35 |
-
while (
|
| 36 |
-
pos + matchLength < lookaheadEnd &&
|
| 37 |
-
text[i + matchLength] === text[pos + matchLength]
|
| 38 |
-
) {
|
| 39 |
-
matchLength++;
|
| 40 |
-
}
|
| 41 |
-
|
| 42 |
-
// Если найдено лучшее совпадение
|
| 43 |
-
if (matchLength >= MIN_MATCH_LENGTH && matchLength > bestLength) {
|
| 44 |
-
bestLength = matchLength;
|
| 45 |
-
bestMatch = {
|
| 46 |
-
offset: pos - i,
|
| 47 |
-
length: matchLength,
|
| 48 |
-
};
|
| 49 |
-
}
|
| 50 |
-
}
|
| 51 |
-
|
| 52 |
-
if (bestMatch) {
|
| 53 |
-
tokens.push({
|
| 54 |
-
type: 'match',
|
| 55 |
-
value: bestMatch,
|
| 56 |
-
});
|
| 57 |
-
pos += bestMatch.length;
|
| 58 |
-
} else {
|
| 59 |
-
tokens.push({
|
| 60 |
-
type: 'literal',
|
| 61 |
-
value: text[pos],
|
| 62 |
-
});
|
| 63 |
-
pos++;
|
| 64 |
-
}
|
| 65 |
-
}
|
| 66 |
-
|
| 67 |
-
// Кодируем токены в бинарную строку
|
| 68 |
-
return encodeTokens(tokens);
|
| 69 |
-
}
|
| 70 |
-
|
| 71 |
-
function encodeTokens(tokens: LZSSToken[]): string {
|
| 72 |
-
let result = '';
|
| 73 |
-
|
| 74 |
-
for (const token of tokens) {
|
| 75 |
-
if (token.type === 'literal') {
|
| 76 |
-
// Флаг 1 означает литерал, затем 8 бит символа
|
| 77 |
-
result += '1';
|
| 78 |
-
const char = token.value as string;
|
| 79 |
-
const charCode = char.charCodeAt(0);
|
| 80 |
-
result += charCode.toString(2).padStart(16, '0'); // 16 бит для Unicode
|
| 81 |
-
} else {
|
| 82 |
-
// Флаг 0 означает совпадение
|
| 83 |
-
result += '0';
|
| 84 |
-
const match = token.value as LZSSMatch;
|
| 85 |
-
// 12 бит для смещения, 6 бит для длины (максимум 18+3=21)
|
| 86 |
-
result += match.offset.toString(2).padStart(12, '0');
|
| 87 |
-
result += (match.length - MIN_MATCH_LENGTH).toString(2).padStart(6, '0');
|
| 88 |
-
}
|
| 89 |
-
}
|
| 90 |
-
|
| 91 |
-
return result;
|
| 92 |
-
}
|
| 93 |
-
|
| 94 |
-
export function lzssDecode(encoded: string): string {
|
| 95 |
-
if (!encoded) return '';
|
| 96 |
-
|
| 97 |
-
let result = '';
|
| 98 |
-
let pos = 0;
|
| 99 |
-
|
| 100 |
-
while (pos < encoded.length) {
|
| 101 |
-
const flag = encoded[pos];
|
| 102 |
-
pos++;
|
| 103 |
-
|
| 104 |
-
if (flag === '1') {
|
| 105 |
-
// Литерал: читаем 16 бит
|
| 106 |
-
if (pos + 16 > encoded.length) {
|
| 107 |
-
console.error('Неполный литерал на позиции', pos);
|
| 108 |
-
break;
|
| 109 |
-
}
|
| 110 |
-
const charCode = parseInt(encoded.substring(pos, pos + 16), 2);
|
| 111 |
-
result += String.fromCharCode(charCode);
|
| 112 |
-
pos += 16;
|
| 113 |
-
} else if (flag === '0') {
|
| 114 |
-
// Совпадение: читаем 12 бит смещения и 6 бит длины
|
| 115 |
-
if (pos + 18 > encoded.length) {
|
| 116 |
-
console.error('Неполное совпадение на позиции', pos);
|
| 117 |
-
break;
|
| 118 |
-
}
|
| 119 |
-
|
| 120 |
-
const offset = parseInt(encoded.substring(pos, pos + 12), 2);
|
| 121 |
-
pos += 12;
|
| 122 |
-
const length =
|
| 123 |
-
parseInt(encoded.substring(pos, pos + 6), 2) + MIN_MATCH_LENGTH;
|
| 124 |
-
pos += 6;
|
| 125 |
-
|
| 126 |
-
// Копируем из уже декодированной части
|
| 127 |
-
const startPos = result.length - offset;
|
| 128 |
-
|
| 129 |
-
if (startPos < 0) {
|
| 130 |
-
console.error(
|
| 131 |
-
`Некорректное смещение: ${offset} на позиции результата ${result.length}`,
|
| 132 |
-
);
|
| 133 |
-
break;
|
| 134 |
-
}
|
| 135 |
-
|
| 136 |
-
for (let i = 0; i < length; i++) {
|
| 137 |
-
result += result[startPos + i];
|
| 138 |
-
}
|
| 139 |
-
} else {
|
| 140 |
-
console.error('Неизвестный флаг:', flag);
|
| 141 |
-
break;
|
| 142 |
-
}
|
| 143 |
-
}
|
| 144 |
-
|
| 145 |
-
return result;
|
| 146 |
-
}
|
| 147 |
-
|
| 148 |
-
// Функция для статистики сжатия
|
| 149 |
-
export function getLZSSStats(
|
| 150 |
-
original: string,
|
| 151 |
-
encoded: string,
|
| 152 |
-
): {
|
| 153 |
-
originalSize: number;
|
| 154 |
-
compressedSize: number;
|
| 155 |
-
compressionRatio: number;
|
| 156 |
-
} {
|
| 157 |
-
const originalSize = original.length * 16; // 16 бит на символ (UTF-16)
|
| 158 |
-
const compressedSize = encoded.length;
|
| 159 |
-
|
| 160 |
-
return {
|
| 161 |
-
originalSize,
|
| 162 |
-
compressedSize,
|
| 163 |
-
compressionRatio: compressedSize / originalSize,
|
| 164 |
-
};
|
| 165 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/utils/offset-encryption.util.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
| 1 |
-
export const CUSTOM_ALPHABET =
|
| 2 |
-
'abcdefghijklmnopqrstuvwxyz' +
|
| 3 |
-
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
|
| 4 |
-
'0123456789' +
|
| 5 |
-
'.,;:=|!?()[]{}"\'-_/\\@#$%^&* ';
|
| 6 |
-
|
| 7 |
-
const alphabetMap = new Map<string, number>();
|
| 8 |
-
|
| 9 |
-
for (let i = 0; i < CUSTOM_ALPHABET.length; i++) {
|
| 10 |
-
alphabetMap.set(CUSTOM_ALPHABET[i], i + 1);
|
| 11 |
-
}
|
| 12 |
-
|
| 13 |
-
function getPos(char: string): number {
|
| 14 |
-
const pos = alphabetMap.get(char);
|
| 15 |
-
if (!pos) throw new Error(`Character "${char}" is missing in the alphabet`);
|
| 16 |
-
return pos;
|
| 17 |
-
}
|
| 18 |
-
|
| 19 |
-
function getChar(pos: number): string {
|
| 20 |
-
return CUSTOM_ALPHABET[pos - 1];
|
| 21 |
-
}
|
| 22 |
-
|
| 23 |
-
export function encryptWithAlphabet(text: string, key: string): string {
|
| 24 |
-
let result = '';
|
| 25 |
-
const N = CUSTOM_ALPHABET.length;
|
| 26 |
-
|
| 27 |
-
for (let i = 0; i < text.length; i++) {
|
| 28 |
-
const tPos = getPos(text[i]);
|
| 29 |
-
const kPos = getPos(key[i % key.length]);
|
| 30 |
-
|
| 31 |
-
let encPos = tPos + kPos;
|
| 32 |
-
if (encPos > N) encPos -= N;
|
| 33 |
-
|
| 34 |
-
result += getChar(encPos);
|
| 35 |
-
}
|
| 36 |
-
|
| 37 |
-
return result;
|
| 38 |
-
}
|
| 39 |
-
|
| 40 |
-
export function decryptWithAlphabet(encrypted: string, key: string): string {
|
| 41 |
-
let result = '';
|
| 42 |
-
const N = CUSTOM_ALPHABET.length;
|
| 43 |
-
|
| 44 |
-
for (let i = 0; i < encrypted.length; i++) {
|
| 45 |
-
const ePos = getPos(encrypted[i]);
|
| 46 |
-
const kPos = getPos(key[i % key.length]);
|
| 47 |
-
|
| 48 |
-
let decPos = ePos - kPos;
|
| 49 |
-
if (decPos <= 0) decPos += N;
|
| 50 |
-
|
| 51 |
-
result += getChar(decPos);
|
| 52 |
-
}
|
| 53 |
-
|
| 54 |
-
return result;
|
| 55 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/visitor/visitor.service.ts
CHANGED
|
@@ -46,7 +46,7 @@ export class VisitorService {
|
|
| 46 |
};
|
| 47 |
|
| 48 |
const lines = await this.file.readLines();
|
| 49 |
-
lines.push(
|
| 50 |
await this.file.writeLines(lines);
|
| 51 |
|
| 52 |
return newVisitor;
|
|
@@ -59,9 +59,7 @@ export class VisitorService {
|
|
| 59 |
throw new NotFoundException(`Visitor with id ${id} not found`);
|
| 60 |
|
| 61 |
visitors[index] = { ...visitors[index], ...dto };
|
| 62 |
-
await this.file.writeLines(
|
| 63 |
-
await Promise.all(visitors.map((visitor) => serializeTxtRow(visitor))),
|
| 64 |
-
);
|
| 65 |
return visitors[index];
|
| 66 |
}
|
| 67 |
|
|
@@ -78,9 +76,7 @@ export class VisitorService {
|
|
| 78 |
}
|
| 79 |
|
| 80 |
visitors.splice(index, 1);
|
| 81 |
-
await this.file.writeLines(
|
| 82 |
-
await Promise.all(visitors.map((visitor) => serializeTxtRow(visitor))),
|
| 83 |
-
);
|
| 84 |
}
|
| 85 |
|
| 86 |
async addCurrentBooks(visitorId: string, books: Book[]): Promise<void> {
|
|
@@ -94,9 +90,7 @@ export class VisitorService {
|
|
| 94 |
visitors[visitorIndex].currentBooks.push(
|
| 95 |
...books.map((b) => bookLinkManager.toLink(b.id)),
|
| 96 |
);
|
| 97 |
-
await this.file.writeLines(
|
| 98 |
-
await Promise.all(visitors.map((visitor) => serializeTxtRow(visitor))),
|
| 99 |
-
);
|
| 100 |
}
|
| 101 |
|
| 102 |
async moveToHistory(visitorId: string, books: Book[]): Promise<void> {
|
|
@@ -124,9 +118,7 @@ export class VisitorService {
|
|
| 124 |
visitor.history.push(removedBook);
|
| 125 |
}
|
| 126 |
|
| 127 |
-
await this.file.writeLines(
|
| 128 |
-
await Promise.all(visitors.map((visitor) => serializeTxtRow(visitor))),
|
| 129 |
-
);
|
| 130 |
}
|
| 131 |
|
| 132 |
async hasBook(visitorId: string, bookId: string): Promise<boolean> {
|
|
|
|
| 46 |
};
|
| 47 |
|
| 48 |
const lines = await this.file.readLines();
|
| 49 |
+
lines.push(serializeTxtRow(newVisitor));
|
| 50 |
await this.file.writeLines(lines);
|
| 51 |
|
| 52 |
return newVisitor;
|
|
|
|
| 59 |
throw new NotFoundException(`Visitor with id ${id} not found`);
|
| 60 |
|
| 61 |
visitors[index] = { ...visitors[index], ...dto };
|
| 62 |
+
await this.file.writeLines(visitors.map(serializeTxtRow));
|
|
|
|
|
|
|
| 63 |
return visitors[index];
|
| 64 |
}
|
| 65 |
|
|
|
|
| 76 |
}
|
| 77 |
|
| 78 |
visitors.splice(index, 1);
|
| 79 |
+
await this.file.writeLines(visitors.map(serializeTxtRow));
|
|
|
|
|
|
|
| 80 |
}
|
| 81 |
|
| 82 |
async addCurrentBooks(visitorId: string, books: Book[]): Promise<void> {
|
|
|
|
| 90 |
visitors[visitorIndex].currentBooks.push(
|
| 91 |
...books.map((b) => bookLinkManager.toLink(b.id)),
|
| 92 |
);
|
| 93 |
+
await this.file.writeLines(visitors.map(serializeTxtRow));
|
|
|
|
|
|
|
| 94 |
}
|
| 95 |
|
| 96 |
async moveToHistory(visitorId: string, books: Book[]): Promise<void> {
|
|
|
|
| 118 |
visitor.history.push(removedBook);
|
| 119 |
}
|
| 120 |
|
| 121 |
+
await this.file.writeLines(visitors.map(serializeTxtRow));
|
|
|
|
|
|
|
| 122 |
}
|
| 123 |
|
| 124 |
async hasBook(visitorId: string, bookId: string): Promise<boolean> {
|
src/worker/worker.service.ts
CHANGED
|
@@ -74,9 +74,7 @@ export class WorkerService {
|
|
| 74 |
};
|
| 75 |
|
| 76 |
workers.push(newWorker);
|
| 77 |
-
await this.file.writeLines(
|
| 78 |
-
await Promise.all(workers.map((worker) => serializeTxtRow(worker))),
|
| 79 |
-
);
|
| 80 |
|
| 81 |
return newWorker;
|
| 82 |
}
|
|
@@ -94,9 +92,7 @@ export class WorkerService {
|
|
| 94 |
...workers[index],
|
| 95 |
...dto,
|
| 96 |
};
|
| 97 |
-
await this.file.writeLines(
|
| 98 |
-
await Promise.all(workers.map((worker) => serializeTxtRow(worker))),
|
| 99 |
-
);
|
| 100 |
return workers[index];
|
| 101 |
}
|
| 102 |
|
|
@@ -107,9 +103,7 @@ export class WorkerService {
|
|
| 107 |
if (index === -1) return false;
|
| 108 |
|
| 109 |
workers.splice(index, 1);
|
| 110 |
-
await this.file.writeLines(
|
| 111 |
-
await Promise.all(workers.map((worker) => serializeTxtRow(worker))),
|
| 112 |
-
);
|
| 113 |
|
| 114 |
return true;
|
| 115 |
}
|
|
@@ -135,8 +129,6 @@ export class WorkerService {
|
|
| 135 |
|
| 136 |
workers[index] = target;
|
| 137 |
|
| 138 |
-
await this.file.writeLines(
|
| 139 |
-
await Promise.all(workers.map((worker) => serializeTxtRow(worker))),
|
| 140 |
-
);
|
| 141 |
}
|
| 142 |
}
|
|
|
|
| 74 |
};
|
| 75 |
|
| 76 |
workers.push(newWorker);
|
| 77 |
+
await this.file.writeLines(workers.map(serializeTxtRow));
|
|
|
|
|
|
|
| 78 |
|
| 79 |
return newWorker;
|
| 80 |
}
|
|
|
|
| 92 |
...workers[index],
|
| 93 |
...dto,
|
| 94 |
};
|
| 95 |
+
await this.file.writeLines(workers.map(serializeTxtRow));
|
|
|
|
|
|
|
| 96 |
return workers[index];
|
| 97 |
}
|
| 98 |
|
|
|
|
| 103 |
if (index === -1) return false;
|
| 104 |
|
| 105 |
workers.splice(index, 1);
|
| 106 |
+
await this.file.writeLines(workers.map(serializeTxtRow));
|
|
|
|
|
|
|
| 107 |
|
| 108 |
return true;
|
| 109 |
}
|
|
|
|
| 129 |
|
| 130 |
workers[index] = target;
|
| 131 |
|
| 132 |
+
await this.file.writeLines(workers.map(serializeTxtRow));
|
|
|
|
|
|
|
| 133 |
}
|
| 134 |
}
|