// Оракул экрана «до» свода 2 (Svod2Page на коммите 399234a + material-react-table). Копии дословные. // matchesSearch: Svod2Page.jsx:283-294; equals: material-react-table/dist/index.esm.js:663-667. import { mkdirSync, writeFileSync } from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const matchesSearch = (row, query) => { const searchableData = { ...row.data?.header, ...row.data?.contract_summary, ...row.data?.contract_detail, }; return Object.values(searchableData).some((value) => String(value ?? '') .toLowerCase() .includes(query), ); }; const equals = (row, id, filterValue) => { var _a; return ((_a = row.getValue(id)) === null || _a === void 0 ? void 0 : _a.toString().toLowerCase().trim()) === filterValue.toString().toLowerCase().trim(); }; equals.autoRemove = (val) => !val; export { matchesSearch, equals }; export const FILTER_COLUMNS = ['smeta_type', 'smeta_direction', 'org_name']; // accessorFn колонок: valueAt(row, ['header', id]) const asTableRow = (row, id) => ({ getValue: () => row.data?.header?.[id] }); const cellValue = (row, id) => row.data?.header?.[id]; const activeFilters = (filters, skipId) => FILTER_COLUMNS.filter((id) => id !== skipId && filters[id] && !equals.autoRemove(filters[id])); const bySearch = (rows, search) => { const normalizedSearch = String(search ?? '').trim().toLowerCase(); return normalizedSearch ? rows.filter((row) => matchesSearch(row, normalizedSearch)) : rows; }; const byFilters = (rows, filters, skipId) => { const ids = activeFilters(filters, skipId); return rows.filter((row) => ids.every((id) => equals({ getValue: () => cellValue(row, id) }, id, filters[id]))); }; export function screenRows(rows, { search = '', filters = {} } = {}) { return byFilters(bySearch(rows, search), filters, null); } export function screenFound(rows, search) { return { found: bySearch(rows, search).length, total: rows.length }; } export function screenFacets(rows, { search = '', filters = {} } = {}) { const searched = bySearch(rows, search); const result = { total: rows.length, search_total: searched.length }; for (const id of FILTER_COLUMNS) { const counts = new Map(); for (const row of byFilters(searched, filters, id)) { const value = asTableRow(row, id).getValue(id); counts.set(value, (counts.get(value) ?? 0) + 1); } result[id] = Array.from(counts.keys()) .filter((value) => value !== null && value !== undefined) .sort((a, b) => a.localeCompare(b)) .map((value) => [value, counts.get(value)]); } return result; } export const NUMBER_VECTOR_INPUTS = [ '0', '-0', '1', '-1', '100', '100.00', '1234.50', '12.34', '0.5', '0.30000000000000004', '0.000001', '1e-7', '-1.5e-10', '123e-20', '1e15', '1e20', '1e21', '123456789012345680000', '9007199254740993', '5e-324', '1.7976931348623157e308', ]; // Числа в строках берём через JSON.parse, чтобы запись была как у JSON-ответа API. const J = (text) => JSON.parse(text); export const SYNTHETIC_ROWS = [ { data: { line_id: 1, header: { name: 'Аренда помещения', smeta_type: 'КВ', smeta_direction: 'Развитие', org_name: 'Филиал Ёлки' }, contract_summary: { counterparty: 'ООО Ромашка' }, contract_detail: { counterparty: null, ceiling_amount: J('1234.50') } } }, { data: { line_id: 2, header: { name: 'АРЕНДА склада', smeta_type: 'АХР', smeta_direction: 'Поддержка', org_name: 'Филиал Ёлки' }, contract_summary: {}, contract_detail: { counterparty: 'ООО Ромашка Плюс', ceiling_amount: J('100') } } }, { data: { line_id: 3, header: { name: 'Ёлка новогодняя', smeta_type: 'КВ', smeta_direction: null, org_name: 'филиал ёлки ' }, contract_summary: { counterparty: 'ИП Ёж' }, contract_detail: { ceiling_amount: J('0') } } }, { data: { line_id: 4, header: { name: 'ёжик', smeta_type: 'кв ', smeta_direction: 'Развитие', org_name: 'Центр' }, contract_summary: {}, contract_detail: { ceiling_amount: J('1e-7') } } }, { data: { line_id: 5, header: { name: 'Услуги связи', smeta_type: 'КВ', smeta_direction: 'Поддержка', org_name: 'Центр' }, contract_summary: {}, contract_detail: { note: 'a b' } } }, { data: { line_id: 6, header: { name: 'Без маркера', smeta_type: 'АХР', smeta_direction: 'Развитие', org_name: 'Север' }, contract_summary: {}, contract_detail: { note: 'xy' } } }, { data: { line_id: 7, header: { name: 'Флаг', smeta_type: 'КВ', smeta_direction: 'Развитие', org_name: 'Север', is_active: true }, contract_summary: { flag: true }, contract_detail: { note: null } } }, { data: { line_id: 8, header: { name: null, smeta_type: null, smeta_direction: null, org_name: null }, contract_summary: {}, contract_detail: {} } }, { data: { line_id: 9, header: { name: 'Итого 1', smeta_type: 'АХР', smeta_direction: 'Поддержка', org_name: 'Центр' }, contract_summary: { counterparty: 'ООО Ромашка' }, contract_detail: { counterparty: 'ООО Ромашка', ceiling_amount: J('1234.5') } } }, { data: { line_id: 10, header: { name: 'Прочее', smeta_type: 'ПР', smeta_direction: 'Развитие', org_name: 'Филиал Ёлки' }, contract_summary: {}, contract_detail: { ceiling_amount: J('1e-7'), note: 'Договор №1' } } }, { data: { line_id: 11, header: { name: 'Лицензии', smeta_type: 'КВ', smeta_direction: 'Поддержка', org_name: 'Юг' }, contract_summary: {}, contract_detail: { ceiling_amount: J('100.00') } } }, ]; export const SCREEN_CASES = [ { search: '', filters: {} }, { search: 'аРЕНДА', filters: {} }, { search: 'ё', filters: {} }, { search: 'ромаш', filters: {} }, { search: '1234.5', filters: {} }, { search: '1234.50', filters: {} }, { search: ' аренда ', filters: {} }, { search: ' ', filters: {} }, { search: '1', filters: {} }, { search: '', filters: { smeta_type: 'кв ' } }, { search: '', filters: { org_name: 'Филиал Ёлки' } }, { search: '', filters: { smeta_type: 'КВ', smeta_direction: 'Развитие' } }, { search: 'ё', filters: { smeta_type: 'КВ' } }, { search: '', filters: { org_name: 'филиал ёлки' } }, ]; export function emitNumberVectors() { return NUMBER_VECTOR_INPUTS.map((input) => ({ input, js: String(JSON.parse(input)) })); } export function emitScreenVectors() { return { rows: SYNTHETIC_ROWS, cases: SCREEN_CASES.map(({ search, filters }) => ({ search, filters, line_ids: screenRows(SYNTHETIC_ROWS, { search, filters }).map((r) => r.data.line_id), found: screenFound(SYNTHETIC_ROWS, search), facets: screenFacets(SYNTHETIC_ROWS, { search, filters }), })), }; } if (process.argv[1] === fileURLToPath(import.meta.url)) { const i = process.argv.indexOf('--emit-vectors'); if (i > 0 && process.argv[i + 1]) { const dir = process.argv[i + 1]; mkdirSync(dir, { recursive: true }); writeFileSync(path.join(dir, 'js_number_text_vectors.json'), `${JSON.stringify(emitNumberVectors(), null, 2)}\n`); writeFileSync(path.join(dir, 'svod2_screen_vectors.json'), `${JSON.stringify(emitScreenVectors(), null, 2)}\n`); } }