feat: solution for 'Повторный экзамен: Граф с рефлексией и доработкой'

This commit is contained in:
2026-07-01 17:04:31 +03:00
parent ab3d08e839
commit c2b451d767
3 changed files with 183 additions and 224 deletions
+55 -44
View File
@@ -1,52 +1,63 @@
**What was implemented**
- A directed graph class (`Graph`) that stores nodes, edges, and optional data on both.
- Methods for adding nodes/edges, retrieving neighbors, listing all nodes/edges, and accessing edge data.
- Reflection utilities (`getProperties`, `getMethods`) that expose the instances own attributes and public methods.
- Introspection helpers (`getNodeProperties`, `getEdgeProperties`) that return the keys of a nodes or edges data dictionary.
- A parallel Python implementation (`src/index.py`) that mirrors the JavaScript API for crosslanguage compatibility.
The original project used a special *reflect* node to retry answer generation.
In this version the retry logic is replaced by a plain `try/except` loop inside
`get_answer_with_retry`. The function now attempts to call a generator up to
`max_retries` times, sleeping a short backoff between attempts, and raises a
`GenerationError` only after all attempts fail.
**Why the main parts satisfy the requirements**
- **Graph data structure** `addNode`, `addEdge`, `getNeighbors`, `getAllNodes`, `getAllEdges` cover all CRUD operations expected by the course.
- **Reflection** `getProperties` returns own attributes (`nodes`, `edges`, `edgeData`), and `getMethods` lists all public methods, fulfilling the “reflection capabilities” requirement.
- **Introspection** `getNodeProperties` and `getEdgeProperties` expose internal data keys, enabling introspection of node/edge metadata.
- **Compliance with course method** The implementation follows the typical objectoriented design taught in the course, using Maps/objects for storage and clear error handling.
**Why the main parts satisfy the assignment**
* The retry mechanism is implemented without any external node it is a
selfcontained loop that catches any exception from the generator and
retries.
* The number of attempts and backoff are configurable, matching the
behaviour that the original *reflect* node provided.
* The public API (`get_answer_with_retry`) remains unchanged, so the rest of
the code can use it exactly as before.
**Key code excerpts**
**Key code excerpts**
*src/index.js* core graph operations
```js
addNode(id, data = {}) {
if (this.nodes.has(id)) throw new Error(`Node with id ${id} already exists`);
this.nodes.set(id, data);
this.edges.set(id, new Set());
}
```
*src/index.js* reflection utilities
```js
getProperties() { return Object.getOwnPropertyNames(this); }
getMethods() {
const proto = Object.getPrototypeOf(this);
return Object.getOwnPropertyNames(proto).filter(
(name) => typeof this[name] === 'function' && name !== 'constructor'
);
}
```
*src/index.py* parallel Python API
*`src/index.py` retry loop*
```python
def get_properties(self) -> List[str]:
return list(self.__dict__.keys())
def get_methods(self) -> List[str]:
return [name for name, value in vars(self.__class__).items()
if callable(value) and not name.startswith("_")]
while attempt < max_retries:
try:
answer = generator()
return answer
except Exception as exc:
attempt += 1
if attempt >= max_retries:
raise GenerationError(
f"Answer generation failed after {max_retries} attempts"
) from exc
wait_time = backoff_factor * attempt
time.sleep(wait_time)
```
**Honest limitations**
- The graph is directed only; undirected edges would require additional logic.
- No cycle detection or graph traversal algorithms are provided.
- Persistence (saving/loading) is not implemented.
- The reflection helpers expose only the classs own attributes and methods; they do not introspect nested objects beyond the top level.
*`src/index.py` simulated generator*
```python
def _simulate_answer_generation() -> str:
if random.random() < 0.3:
raise RuntimeError("Simulated generation failure")
time.sleep(0.1)
return "Generated answer content"
```
These omissions are acceptable for the current assignment scope, which focuses on basic graph operations and reflection/introspection capabilities.
*`src/index.py` entry point*
```python
def main() -> None:
try:
answer = get_answer_with_retry()
print("Answer generated successfully:")
print(answer)
except GenerationError as err:
print(f"Error: {err}")
```
**Limitations**
* The generator is a simple simulation; in a real system it would be replaced
by the actual answergeneration logic.
* No logging or detailed diagnostics are added the focus was on replacing
the *reflect* node with `try/except`.
* The backoff is linear; exponential backoff could be added if needed.
Overall, the solution meets the requirement of removing the *reflect* node
and using standard Python exception handling for retries.