/
vladlevin790
/
cpp-lab-2
Обзор
Документация
Войти
/
vladlevin790
/
cpp-lab-2
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
web/js/wasmAdapter.js
373 строки
14 KB
vladlevin790
init
05 май 2026, 21:32
05 май 2026, 21:32
3310cbd
Код
Авторство
О чём код?
import { parseJson } from "./utils.js"; function operation(action, message, success = true, steps = [], extra = {}) { return { success, action, message, elapsedMicroseconds: 0, steps, ...extra }; } function createFallbackModule() { const buckets = new Map(); let selectedStructure = "Vector"; let selectedType = "int"; let lastOperation = operation("init", "Приложение инициализировано."); const key = () => `${selectedType}:${selectedStructure}`; const currentItems = () => { if (!buckets.has(key())) { buckets.set(key(), []); } return buckets.get(key()); }; const parseValue = (raw) => { const value = String(raw ?? ""); if (selectedType === "int") { if (!/^-?\d+$/.test(value.trim())) { throw new Error("Введите целое число для типа int."); } const number = Number(value); if (!Number.isSafeInteger(number) || number < -2147483648 || number > 2147483647) { throw new Error("Число выходит за границы типа int."); } return String(number); } if (selectedType === "long") { if (!/^-?\d+$/.test(value.trim())) { throw new Error("Введите целое число для типа long."); } const parsed = BigInt(value.trim()); const min = -(1n << 63n); const max = (1n << 63n) - 1n; if (parsed < min || parsed > max) { throw new Error("Число выходит за границы типа long."); } return parsed.toString(); } if (selectedType === "double") { const number = Number(value.replace(",", ".")); if (!Number.isFinite(number)) { throw new Error("Введите число для типа double."); } return number.toFixed(2); } if (selectedType === "char") { if ([...value].length !== 1) { throw new Error("Для char нужен ровно один символ."); } return value; } return value; }; const supportsShift = () => selectedType === "int" || selectedType === "long"; const supportsMean = () => selectedType === "int" || selectedType === "long" || selectedType === "double"; const capacity = () => { const size = currentItems().length; if (selectedStructure === "Array") { return 100; } let cap = 4; while (cap < size) { cap *= 2; } return Math.max(cap, size); }; const roleFor = (index, size) => { if (selectedStructure === "Stack" && index === size - 1) { return "top"; } if (selectedStructure === "Queue" && index === 0) { return "front"; } if (selectedStructure === "Queue" && index === size - 1) { return "back"; } return ""; }; const binaryFor = (value) => { if (selectedType !== "int" && selectedType !== "long") { return ""; } try { let n = BigInt(value); if (n < 0n) { n = -n; } return n.toString(2); } catch { return ""; } }; const itemsWindow = (start = 0, limit = currentItems().length) => { const items = currentItems(); const safeStart = Math.max(0, Number(start) || 0); const safeLimit = Math.max(0, Number(limit) || 0); const end = Math.min(items.length, safeStart + safeLimit); const result = []; for (let index = safeStart; index < end; index += 1) { result.push({ index, position: index + 1, value: String(items[index]), binary: binaryFor(items[index]), isEvenPosition: (index + 1) % 2 === 0, role: roleFor(index, items.length) }); } return result; }; const state = () => { const items = currentItems(); const windowLimit = Math.min(items.length, 512); return { structure: selectedStructure, dataType: selectedType, dataTypeLabel: selectedType, supportsShift: supportsShift(), supportsMean: supportsMean(), size: items.length, capacity: capacity(), windowStart: 0, windowLimit, virtualized: items.length > windowLimit, items: itemsWindow(0, windowLimit) }; }; const demoValue = (index) => { if (selectedType === "int") return String((index + 1) * 10); if (selectedType === "long") return String(BigInt(index + 1) * 10000000000n); if (selectedType === "double") return ((index + 1) * 1.25).toFixed(2); if (selectedType === "char") return String.fromCharCode(65 + (index % 26)); return `item-${index + 1}`; }; return { __fallback: true, setStructure(structure) { if (!["Array", "Vector", "Stack", "Queue"].includes(structure)) { lastOperation = operation("set-structure", "Неизвестная структура данных.", false); return JSON.stringify(state()); } selectedStructure = structure; lastOperation = operation("set-structure", `Выбрана структура: ${structure}`); return JSON.stringify(state()); }, setDataType(type) { if (!["int", "long", "double", "char", "string"].includes(type)) { lastOperation = operation("set-data-type", "Неизвестный тип данных.", false); return JSON.stringify(state()); } selectedType = type; lastOperation = operation("set-data-type", `Выбран тип данных: ${type}`); return JSON.stringify(state()); }, insertValue(raw) { try { const parsed = parseValue(raw); const items = currentItems(); items.push(parsed); lastOperation = operation("insert", "Элемент добавлен в структуру.", true, [ { index: items.length - 1, before: "", after: parsed, formula: `insert(${parsed})` } ]); } catch (error) { lastOperation = operation("insert", error.message, false); } return JSON.stringify(state()); }, removeLast() { const items = currentItems(); if (items.length === 0) { lastOperation = operation("remove-last", "Структура пустая. Удаление невозможно.", false); return JSON.stringify(state()); } const index = selectedStructure === "Queue" ? 0 : items.length - 1; const [removed] = selectedStructure === "Queue" ? items.splice(0, 1) : items.splice(items.length - 1, 1); const message = selectedStructure === "Queue" ? "Удалён первый элемент очереди (dequeue)." : selectedStructure === "Stack" ? "Удалён верхний элемент стека (pop)." : "Последний элемент удалён."; lastOperation = operation("remove-last", message, true, [ { index, before: String(removed), after: "", formula: "remove()" } ]); return JSON.stringify(state()); }, replaceAt(index, raw) { const items = currentItems(); const safeIndex = Number(index); if (!Number.isInteger(safeIndex) || safeIndex < 0 || safeIndex >= items.length) { lastOperation = operation("replace-at", "Индекс находится вне границ структуры.", false); return JSON.stringify(state()); } try { const parsed = parseValue(raw); const oldValue = String(items[safeIndex]); items[safeIndex] = parsed; lastOperation = operation("replace-at", "Элемент по индексу заменён.", true, [ { index: safeIndex, before: oldValue, after: parsed, formula: `${oldValue} -> ${parsed}` } ]); } catch (error) { lastOperation = operation("replace-at", error.message, false); } return JSON.stringify(state()); }, clearCurrent() { currentItems().length = 0; lastOperation = operation("clear", "Текущая структура очищена."); return JSON.stringify(state()); }, applyShiftLeftEvenPositions() { const items = currentItems(); if (!supportsShift()) { lastOperation = operation("shift-left-even-positions", "Побитовый сдвиг доступен только для типа int или long.", false); return JSON.stringify(state()); } if (items.length === 0) { lastOperation = operation("shift-left-even-positions", "Структура пустая. Операция не выполнена."); return JSON.stringify(state()); } const steps = []; for (let index = 1; index < items.length; index += 2) { const before = String(items[index]); const after = selectedType === "long" ? (BigInt(before) << 1n).toString() : String(Number(before) << 1); items[index] = after; steps.push({ index, before, after, formula: `${before} << 1 = ${after}` }); } lastOperation = operation("shift-left-even-positions", steps.length ? "Для чётных позиций выполнен побитовый сдвиг влево." : "В структуре нет чётных позиций для изменения.", true, steps); return JSON.stringify(state()); }, calculateMeanJson() { const items = currentItems(); if (!supportsMean()) { lastOperation = operation("calculate-mean", "Математическое ожидание доступно только для int, long и double.", false, [], { result: 0 }); return JSON.stringify(lastOperation); } if (items.length === 0) { lastOperation = operation("calculate-mean", "Структура пустая. Математическое ожидание принято равным 0.", true, [], { result: 0 }); return JSON.stringify(lastOperation); } let sum = 0; const steps = items.map((value, index) => { sum += Number(value); return { index, before: String(value), after: String(sum), formula: `sum = sum + ${value}` }; }); const result = sum / items.length; lastOperation = operation("calculate-mean", "Вычислено математическое ожидание элементов структуры.", true, steps, { result }); return JSON.stringify(lastOperation); }, fillDemoData(count) { const size = Math.max(0, Number(count) || 0); const items = currentItems(); items.length = 0; for (let i = 0; i < size; i += 1) { items.push(demoValue(i)); } lastOperation = operation("fill-demo-data", "Структура заполнена демонстрационными данными."); return JSON.stringify(state()); }, getAsciiPreviewJson() { lastOperation = operation("ascii-preview", "Создан ASCII-preview текущей структуры."); return JSON.stringify({ items: itemsWindow(0, currentItems().length) }); }, getStateJson() { return JSON.stringify(state()); }, getLastOperationJson() { return JSON.stringify(lastOperation); }, getItemsWindowJson(start, count) { return JSON.stringify({ structure: selectedStructure, dataType: selectedType, size: currentItems().length, windowStart: Math.max(0, Number(start) || 0), windowLimit: Math.max(0, Number(count) || 0), items: itemsWindow(start, count) }); } }; } export async function loadWasmModule() { try { const moduleFactory = await import("../dist/lab_module.js"); const createLabModule = moduleFactory.default ?? moduleFactory; const module = await createLabModule({ locateFile(path) { if (path.endsWith(".wasm")) { return `./dist/${path}`; } return path; } }); return module; } catch (error) { console.warn("WASM module is not available. JS fallback is enabled.", error); return createFallbackModule(); } } export function getState(module) { return parseJson(module.getStateJson()); } export function getLastOperation(module) { return parseJson(module.getLastOperationJson()); } export function getItemsWindow(module, start, count) { if (!module?.getItemsWindowJson) { return { items: [], windowStart: start, windowLimit: count, size: 0 }; } return parseJson(module.getItemsWindowJson(start, count)); }