Add utils.js with Excel reading, validation and normalization functions

This commit is contained in:
2026-07-30 16:50:44 +03:00
parent 5b5a0e68ee
commit f9fd5a7b8a
+78
View File
@@ -0,0 +1,78 @@
// utils.js
// Вспомогательные функции для работы с Excel, валидации и нормализации данных
/**
* Читает файл Excel и возвращает массив листов.
* @param {File} file
* @returns {Promise<Array<{name:string, data:Array<Array<any>>}>>}
*/
export async function readExcel(file) {
const data = await file.arrayBuffer();
const wb = XLSX.read(data, { type: 'array' });
return wb.SheetNames.map(name => ({
name,
data: XLSX.utils.sheet_to_json(wb.Sheets[name], { header: 1, defval: '' })
}));
}
/**
* Проверка типа и размера файла.
* @param {File} file
* @returns {boolean}
*/
export function validateFile(file) {
const ext = file.name.slice(file.name.lastIndexOf('.')).toLowerCase();
if (!['.xlsx', '.xls'].includes(ext)) {
alert(`Недопустимый тип файла: ${ext}`);
return false;
}
if (file.size === 0) {
alert('Файл пустой');
return false;
}
return true;
}
/**
* Нормализация номера ТС (замена латинских букв их русскими аналогами).
* @param {string} plate
* @returns {string}
*/
export function normalizePlate(plate) {
const map = {A:'\u0410',B:'\u0412',C:'\u0421',E:'\u0415',H:'\u041D',K:'\u041A',M:'\u041C',O:'\u041E',P:'\u0420',T:'\u0422',X:'\u0425',Y:'\u0423'};
return plate.toUpperCase().replace(/[ABCEHKMOPTXY]/g, ch => map[ch] || ch);
}
/**
* Приведение ФИО к единому регистру, замена Ё на Е.
* @param {string} name
* @returns {string}
*/
export function normalizeName(name) {
return name.toUpperCase().replace(/\u0401/g, '\u0415').trim();
}
/**
* Вычисление схожести строк (Levenshtein).
* @param {string} a
* @param {string} b
* @returns {number} коэффициент от 0 до 1
*/
export function similarity(a, b) {
if (!a || !b) return 0;
const editDist = (s1, s2) => {
const dp = Array(s1.length + 1).fill().map(() => Array(s2.length + 1).fill(0));
for (let i = 0; i <= s1.length; i++) dp[i][0] = i;
for (let j = 0; j <= s2.length; j++) dp[0][j] = j;
for (let i = 1; i <= s1.length; i++) {
for (let j = 1; j <= s2.length; j++) {
dp[i][j] = s1[i - 1] === s2[j - 1]
? dp[i - 1][j - 1]
: Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1;
}
}
return dp[s1.length][s2.length];
};
const dist = editDist(a, b);
return 1 - dist / Math.max(a.length, b.length);
}