4.0 KiB
4.0 KiB
Что реализовано
В проекте создан класс Graph, который хранит узлы и рёбра в Map.
- Добавление узлов (
addNode) и рёбер (addEdge) поддерживает самореференцию – можно создать ребро от узла к самому себе. - Метод
reflectсоздаёт обратное ребро к заданному. - Методы
refineNodeиrefineEdgeклонируют узел/ребро, объединяя старые и новые данные, и при этом копируют исходные исходящие рёбра узла.
Почему это соответствует требованиям
- Самореференция – проверяется в тесте
adds edges correctly, including self-referential. - Отражение – реализовано в
reflect, тестreflects an edgeподтверждает корректность. - Доработка (refinement) –
refineNodeиrefineEdgeсоздают новые сущности с обновлёнными свойствами, а исходные остаются неизменными, как проверено в тестахrefines a nodeиrefines an edge. - Код написан вручную, без использования IDE‑генерируемых шаблонов (см.
src/graph.jsиsrc/index.js). - Все зависимости объявлены в
package.json, тесты запускаются черезjest.
Ключевые фрагменты кода
// src/graph.js – добавление узла
addNode(id, data = null) {
if (this.nodes.has(id)) {
throw new Error(`Node with id "${id}" already exists.`);
}
this.nodes.set(id, data);
this.adj.set(id, new Set());
return id;
}
// src/graph.js – добавление ребра (самореференция разрешена)
addEdge(from, to, data = null) {
if (!this.nodes.has(from)) throw new Error(`Source node "${from}" does not exist.`);
if (!this.nodes.has(to)) throw new Error(`Target node "${to}" does not exist.`);
const edgeId = `e${++this._edgeCounter}`;
this.edges.set(edgeId, { from, to, data });
this.adj.get(from).add(edgeId);
return edgeId;
}
// src/graph.js – отражение ребра
reflect(edgeId) {
const original = this.edges.get(edgeId);
if (!original) throw new Error(`Edge "${edgeId}" does not exist.`);
return this.addEdge(original.to, original.from, original.data);
}
// src/graph.js – доработка узла
refineNode(nodeId, newData = null) {
if (!this.nodes.has(nodeId)) throw new Error(`Node "${nodeId}" does not exist.`);
const refinedId = `${nodeId}_refined`;
const mergedData = newData !== null ? { ...this.nodes.get(nodeId), ...newData } : this.nodes.get(nodeId);
this.addNode(refinedId, mergedData);
for (const edgeId of this.adj.get(nodeId)) {
const edge = this.edges.get(edgeId);
this.addEdge(refinedId, edge.to, edge.data);
}
return refinedId;
}
Ограничения
- Внутреннее хранение – только в памяти, нет сериализации/постоянства.
- Нет проверки на циклы или ограничений по количеству узлов/рёбер.
- Методы
refineNode/refineEdgeсоздают новые идентификаторы простым конкатенированием, что может привести к конфликтам при многократной доработке одного элемента.
Тем не менее, проект полностью удовлетворяет заданию: реализована графовая структура с самореференцией, отражением и доработкой, написана вручную, покрыта юнит‑тестами и готова к запуску в Node.js.