前后端分离计算器系统 | Front-End/Back-End Separation Calculator (832401126)
**
前后端分离计算器系统 | Front-End/Back-End Separation Calculator (832401126)
Front-End / Back-End Separation Calculator System — Assignment Blog
目录
- 前后端分离计算器系统 | Front-End/Back-End Separation Calculator (832401126)
- Front-End / Back-End Separation Calculator System — Assignment Blog
- 1. Git Repository Link and Code Standards Link
- 2. PSP Table
- 3. Assignment Description
- 4. Presentation of the Finished Product
- 4.1 Main calculator interface
- 4.2 Addition
- 4.3 Subtraction
- 4.4 Multiplication
- 4.5 Division
- 4.6 Decimal calculation
- 4.7 Compound expression & operator precedence
- 4.8 Parentheses
- 4.9 Unary positive / negative numbers
- 4.10 Invalid expression handling
- 4.11 Division by zero handling
- 4.12 Calculation history
- 4.13 History persistence after refresh
- 4.14 Delete a specified history record
- 4.15 History search (extension)
- 4.16 Scientific functions (extension)
- 4.17 Theme switching (extension)
- 4.18 Keyboard input (extension)
- 4.19 Back-end offline behavior (separation verification)
- 5. Design and Implementation Process
- 5.1 Requirement analysis
- 5.2 Overall system architecture
- 5.3 Functional structure diagram
- 5.4 Front-end design
- 5.5 Back-end design
- 5.6 API design
- 5.7 Database design
- 5.8 Calculation module design (the core)
- 5.9 Calculation history module design
- 5.10 Exception handling
- 5.11 Front-end / back-end interaction process
- 5.12 Deployment process
- 6. Code Explanation
- 6.1 Front-end API request (js/api.js)
- 6.2 Back-end calculation endpoint (controller)
- 6.3 Expression parsing (parser.py — precedence)
- 6.4 Input validation & security (lexer.py)
- 6.5 Division by zero & overflow (evaluator.py)
- 6.6 Database insert (database.py + service)
- 6.7 Database query & delete (history_service.py)
- 7. Personal Journey and Learnings
- 7.1 Problems encountered and solutions
- 7.2 New knowledge learned
- 7.3 Possible future improvements
- 8. Deployment & Access Guide (for teaching assistants)
- How to access the running project
- How to test
- Notes
1. Git Repository Link and Code Standards Link
| Item | Link |
|---|---|
| Frontend Repository | https://github.com/**Tribulati0n**/832401126_calculator_frontend |
| Backend Repository | https://github.com/**Tribulati0n**/832401126_calculator_backend |
| Frontend Code Standard | https://github.com/**Tribulati0n**/832401126_calculator_frontend/blob/main/codestyle.md |
| Backend Code Standard | https://github.com/**Tribulati0n**/832401126_calculator_backend/blob/main/codestyle.md |
2. PSP Table
Time recorded before implementation (estimated) and after implementation (actual).
| Module | Planned (min) | Actual (min) |
|---|---|---|
| Requirement analysis | 30 | 35 |
| System design (architecture, API, database) | 40 | 45 |
| Expression calculation module (lexer / parser / evaluator) | 90 | 100 |
| Back-end development (API + services) | 60 | 70 |
| Database design & history module | 50 | 45 |
| Front-end development (UI + interaction) | 120 | 130 |
| Front-end / back-end integration | 40 | 35 |
| Testing (unit tests + API tests + manual) | 50 | 45 |
| Deployment & configuration | 30 | 25 |
| Screenshots / demo recording | 30 | 40 |
| Blog writing | 90 | 85 |
| Total | 630 | 655 |
3. Assignment Description
The task is to build a calculator system based on a front-end / back-end separation architecture. The client only takes care of user interaction and information display, while the server is responsible for calculation, expression processing, data validation, exception handling and database operations. The two parts communicate through HTTP/JSON APIs.
Core requirements:
- Basic calculation — at least
+ − × ÷; the front end sends{"expression": "12+8"}and displays the result the back end returns. The front end must not compute the result itself. - Compound expression calculation — operator precedence, parentheses, unary
+/-, decimals, invalid-expression handling, division-by-zero handling. The calculation must happen on the back end. - Calculation history — every successful calculation is stored in a back-end database (
expression,result,created_at); history is fetched from the database and survives refresh/restart. - Delete history — delete one record by id (and optionally clear all) through a back-end API; the database row must actually be removed.
- Security —
eval/exec/ equivalent arbitrary-code execution is prohibited. I implemented a hand-written lexer → recursive-descent parser → AST evaluator pipeline.
Technology choices: Flask + SQLite (back end), vanilla HTML/CSS/JS (front end), deployed as two independent services. The full stack is documented in each repository's README.
4. Presentation of the Finished Product
4.1 Main calculator interface

The main page is split into two panels: the calculator (display + keypad + collapsible scientific panel) on the left, and the calculation history panel on the right. The status chip in the header shows whether the back end is reachable.
4.2 Addition

12 + 8 — the front end sends the expression, the back end computes 20 and stores it, the front end displays 12+8 = 20.
4.3 Subtraction

12 − 8 = 4.
4.4 Multiplication

5 × 8 = 40. The UI shows ×, the API payload uses * (5*8), and the back end normalizes both.
4.5 Division

10 ÷ 2 = 5.
4.6 Decimal calculation

0.1 + 0.2 = 0.3 — floating-point noise is rounded away by the result formatter on the back end.
4.7 Compound expression & operator precedence

1 + 2 × 3 = 7 — multiplication binds tighter than addition.
4.8 Parentheses

(1 + 2) × 3 = 9 — parentheses override precedence.
4.9 Unary positive / negative numbers

−5 + 8 = 3. The parser treats a leading − as a unary negation node.
4.10 Invalid expression handling

An incomplete expression such as 1+ is rejected by the back end with a clear message and HTTP 400; the front end shows the error banner.
4.11 Division by zero handling

1 ÷ 0 returns Division by zero instead of crashing the server.
4.12 Calculation history

Every successful calculation is appended to the history panel with expression, result and time — read from the back-end database.
4.13 History persistence after refresh

The page was fully reloaded; all records are still there because they live in the back-end SQLite database, not in browser storage.
4.14 Delete a specified history record

Clicking ✕ sends DELETE /api/history/{id}; the record count drops from 8 to 7 and the list is re-fetched from the database.
4.15 History search (extension)

Typing 2 in the search box queries the back end (GET /api/history?q=2) and shows only the 6 records whose expression contains 2.
4.16 Scientific functions (extension)

Scientific panel with sin(30) = 0.5 (degrees).

sqrt(16) = 4 and 5! = 120 (postfix factorial) also run through the same back-end engine.
4.17 Theme switching (extension)

One click switches between light and dark themes (CSS custom properties, preference persisted in localStorage).
4.18 Keyboard input (extension)

The whole keypad is usable from the keyboard: digits, operators, Enter/= to evaluate, Backspace, Esc to clear. The demo GIF below shows 12+8= typed entirely with the keyboard.

4.19 Back-end offline behavior (separation verification)

With the back-end service stopped, the UI stays fully interactive, the status chip turns red, and any attempt to calculate shows “Cannot reach the back end…” — the front end cannot obtain a new valid result on its own, which proves the calculation really lives on the back end.
5. Design and Implementation Process
5.1 Requirement analysis
- Functional requirements: basic arithmetic, compound expressions with correct mathematical rules, history persistence, history deletion (single + clear-all), plus usable extras (scientific functions, keyboard, theme, search, connectivity indicator).
- Architectural requirement (the core of this assignment): front-end and back-end separation over HTTP/JSON; the back end must perform validation, parsing, calculation, exception handling and database operations; the front end must not compute results.
- Non-functional requirements: no
eval/exec; data survives refresh and restart; the project must be deployable so teaching assistants can check it.
5.2 Overall system architecture
┌─────────────────────┐ HTTP/JSON ┌──────────────────────┐ ┌──────────┐
│ Front End │ POST /api/calculate │ Back End (Flask) │ SQL │ Database │
│ HTML/CSS/JS │ ──────────────────────► │ │ ─────► │ SQLite │
│ │ GET /api/history │ controller → service│ │ │
│ • buttons/keyboard │ ◄────────────────────── │ → engine → model │ ◄───── │ history │
│ • display │ DELETE /api/history/id │ │ rows │ table │
│ • history UI │ │ │ │ │
│ • error banner │ JSON responses │ │ │ │
└─────────────────────┘ ◄──────────────────────┘ └────────┘ └
The back end is layered (controller → service → calculator engine / model), which keeps HTTP concerns, business flow and pure calculation logic separate and independently testable.
5.3 Functional structure diagram
Calculator System
┌──────────────────────┼──────────────────────┐
Calculator History Front/Back End
│ │ │
┌─────┼────────┐ ┌──────┼──────┐ ┌─────────┼─────────┐
Basic Compound Error Save Query Delete Front End Back End Database
Calc Expr Handle List Search Delete (HTML/CSS/JS) (Flask) (SQLite)
│ │ │ │ │ │
+ − × ÷ precedence invalid insert list+search one/clear
parens ÷0 on OK + paginate by id
unary domain
decimals overflow
5.4 Front-end design
- No framework — plain HTML/CSS/ES Modules so the code is easy to read and needs no build step.
js/api.jsis the only module that talks to the network: afetchwrapper with an 8-second timeout and a typedApiErrorthat carries the back end's error message.js/calculator.jsowns the input buffer and renders the display. It converts display symbols (× ÷ −) to API symbols (* / -) only when building the request body.js/history.jsrenders the list fromGET /api/history, with per-item delete, clear-all, debounced search and a “Load more” button for pagination.- Light input conveniences exist (no two consecutive operators, one decimal point per number, balanced parentheses), but all real validation happens on the back end.
5.5 Back-end design
controller/— Flask blueprint that maps HTTP requests to services and translates engine exceptions into400responses.service/—CalculatorService.calculate()implements exactly the required flow: validate → parse → calculate → store → return.calculator/— the pure expression engine (no Flask dependency):lexer → parser → evaluator.model/— SQLite connection handling and the history record model.
5.6 API design
| Method | Endpoint | Request / params | Response |
|---|---|---|---|
| POST | /api/calculate | {"expression": "(1+2)*3"} | 200 {success,id,expression,result,created_at} |
| GET | /api/history | ?q=&limit=&offset= | 200 {success,data,total,limit,offset} |
| DELETE | /api/history/{id} | — | 200 {success,deleted,id} / 404 |
| DELETE | /api/history | — | 200 {success,deleted} |
| GET | /api/health | — | 200 {status:"ok",...} |
Failures always use HTTP 4xx with {"success": false, "message": "..."}, so the front end has a single error path.
5.7 Database design
CREATE TABLE calculation_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
expression TEXT NOT NULL, -- normalized expression, e.g. "(1+2)*3"
result TEXT NOT NULL, -- display-ready result, e.g. "9"
created_at TEXT NOT NULL -- "YYYY-MM-DD HH:MM:SS"
);
Design notes: the result is stored as text so the display value is never mangled by float serialization; the created_at index keeps list queries fast; SQLite needs no external server, which makes local and hosted deployment trivial; the file path is configurable via DATABASE_PATH.
5.8 Calculation module design (the core)
The pipeline is: whitelist check → tokenize → parse (AST) → evaluate. Full grammar (recursive descent):
expression := term (('+' | '-') term)*
term := factor (('*' | '/' | '%') factor)*
factor := ('+' | '-') factor | power
power := primary ('^' factor)? # right associative
primary := NUMBER | CONSTANT | FUNC '(' args ')' | '(' expression ')' ['!' ...]
- Precedence is encoded in the grammar levels:
+ −<* / %< unary±<^< primary. - Unary minus creates a
("neg", node)AST node;-2^2 = -(2^2) = -4follows mathematical convention. - Division/modulo by zero raises
DivisionByZeroError;sqrt(-1),ln(0)etc. raiseMathDomainError; values beyond1e308raiseNumberOverflowError. - Security: the lexer only accepts a strict character whitelist (
0-9 + - * / ^ % ( ) . , whitespace letters _ !), quotes and semicolons are rejected before parsing, and noeval/execexists anywhere.
5.9 Calculation history module design
- Save: inside
CalculatorService.calculate()— after a successful evaluation, an INSERT stores(expression, result, created_at)in the same request cycle. - Query:
GET /api/historywith optionalq(SQLLIKEsearch) andlimit/offsetpagination. - Delete:
DELETE /api/history/{id}deletes the actual row (rowcount > 0decides 200 vs 404);DELETE /api/historyclears everything. - Front end: after every delete/clear, the list is re-fetched so the UI always mirrors the database.
5.10 Exception handling
CalculatorError (base)
├── InvalidExpressionError -> 400 "Expression ended unexpectedly…"
├── DivisionByZeroError -> 400 "Division by zero"
├── MathDomainError -> 400 "sqrt of a negative number is undefined"
└── NumberOverflowError -> 400 "Result is too large to represent"
The controller catches only CalculatorError; unknown errors fall through to a JSON 500 handler, so the client always gets a structured response.
5.11 Front-end / back-end interaction process
User presses "=" → front end builds expression string
→ fetch POST /api/calculate {"expression": "12+8"}
→ back end: validate → tokenize → parse → evaluate → INSERT history
→ back end returns 200 {"success":true, "result":"20", ...}
→ front end renders "12+8 = 20" and refreshes the history list
On error: back end returns 400 {"success":false, "message": "..."}
→ front end shows the message in the error banner
5.12 Deployment process
- Local: start the back end (
python app.py), serve the front end (python -m http.server 5500), setjs/config.js→apiBaseUrl. - Hosted (Render): push the backend repo to GitHub, create a Render web service (blueprint
render.yamlincluded), DB stored on a persistent disk at/data. - Hosted (Vercel/Netlify): import the frontend repo as a static site (no build command), then point
apiBaseUrlat the Render URL. - Docker (optional):
Dockerfileincluded for the back end.
6. Code Explanation
Key implementation logic with brief explanations (full source in the repositories).
6.1 Front-end API request (js/api.js)
async function request(path, options = {}) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
let response;
try {
response = await fetch(`${CONFIG.apiBaseUrl}${path}`, { ...options, signal: controller.signal });
} catch {
throw new ApiError("Cannot reach the back end. Please check that the server is running.", null);
} finally {
clearTimeout(timer);
}
const body = await response.json().catch(() => null);
if (!response.ok || (body && body.success === false)) {
throw new ApiError((body && body.message) || `Request failed with status ${response.status}`, response.status);
}
return body;
}
Why: one place owns timeouts, network failures and the error envelope, so the UI never guesses at backend messages. This is what produces the friendly “Cannot reach the back end…” banner.
6.2 Back-end calculation endpoint (controller)
@calculator_bp.post("/calculate")
def calculate():
payload = request.get_json(silent=True)
if payload is None:
return _error("Request body must be valid JSON"), 400
if "expression" not in payload or not isinstance(payload["expression"], str):
return _error("Missing or invalid field 'expression'"), 400
try:
record = calculator_service.calculate(payload["expression"])
except CalculatorError as exc:
return _error(str(exc)), 400
return jsonify({"success": True, **record}), 200
Why: the controller is a thin translation layer — request parsing and error translation only; all business logic lives in the service.
6.3 Expression parsing (parser.py — precedence)
def _term(self):
node = self._factor()
while self._peek().type == TokenType.OPERATOR and self._peek().value in ("*", "/", "%"):
self._advance()
node = ("binop", token.value, node, self._factor())
return node
Why: precedence comes from the grammar structure, not from a list of rules. 1+2*3 parses as 1 + (2*3) because _expression only loops over + - while _term consumes * / % first.
6.4 Input validation & security (lexer.py)
_ALLOWED_CHARS = re.compile(r"^[0-9+\-*/^%().,\sA-Za-z_!]+$")
def tokenize(text):
if not _ALLOWED_CHARS.match(text):
raise InvalidExpressionError("Expression contains illegal characters")
...
Why: rejecting programming characters (quotes, ;, =, #…) at the door makes __import__("os")-style attacks fail before parsing even starts. Combined with hand-written evaluation, arbitrary code execution is impossible by construction.
6.5 Division by zero & overflow (evaluator.py)
def _binary(op, left, right):
if op == "/":
if right == 0:
raise DivisionByZeroError("Division by zero")
return _check_overflow(left / right)
if op == "^":
try:
return _check_overflow(math.pow(left, right))
except OverflowError:
raise NumberOverflowError("Result is too large to represent")
def _check_overflow(value):
if not math.isfinite(value) or abs(value) > 1e308:
raise NumberOverflowError("Result is too large to represent")
return value
Why: every operator and function funnels through _check_overflow, so overflow can never silently become inf.
6.6 Database insert (database.py + service)
cursor = self._database.execute_write(
"INSERT INTO calculation_history (expression, result, created_at) VALUES (?, ?, ?)",
(normalized, result_text, created_at),
)
record = HistoryRecord(id=cursor.lastrowid, expression=normalized, ...)
return record.to_dict()
Why: parameterized SQL prevents injection; the insert happens inside the calculate request, so a successful calculation and its history record are always consistent.
6.7 Database query & delete (history_service.py)
rows = self._database.query(
f"SELECT id, expression, result, created_at FROM calculation_history "
f"{where} ORDER BY id DESC LIMIT ? OFFSET ?",
tuple(params + [limit, offset]),
)
...
cursor = self._database.execute_write(
"DELETE FROM calculation_history WHERE id = ?", (history_id,))
return cursor.rowcount > 0 # False -> controller returns 404
Why: newest-first ordering matches what users expect; rowcount makes the delete idempotent and tells the API whether the id existed.
7. Personal Journey and Learnings
7.1 Problems encountered and solutions
- “Which side computes what?” — I first sketched a version where the front end computed and only stored results. Re-reading the assignment made the rule clear: the front end sends the expression, the back end returns the result. I then designed the API and the UI around that flow and verified it by stopping the back end (see 4.19).
- Expression parsing — the first prototype used Python's
eval, which the assignment forbids. I replaced it with a hand-written tokenizer + recursive-descent parser. The hardest part was unary minus vs. exponent precedence (-2^2should be-4); the fix was putting unary operators one grammar level abovepower. - Floating-point display —
0.1+0.2returned0.30000000000000004. I added a result formatter that rounds to 12 significant digits before storing. - Front-end / back-end communication — CORS blocked browser calls during early testing; I added
flask-corswith a configurable origin list. The timeout + typedApiErrorwrapper then gave consistent UX for network failures. - SQLite in a threaded server — concurrent requests occasionally hit “database is locked”. Writes are now serialized with a lock and each request opens a short-lived connection; WAL mode allows concurrent readers.
- History disappearing on reload — early debugging showed history only in the front end; after moving persistence into the back-end
calculateflow, records survived refresh (verified in 4.13). - Deployment planning — SQLite is not a remote database, so for Render I mount a persistent disk at
/data; the DB path is env-configurable.
7.2 New knowledge learned
- Front-end/back-end separation is a responsibility boundary, not just two folders: what the client can and cannot do changes the API design.
- A safe expression engine is a miniature compiler: lexer → parser → AST → evaluator, with each stage doing one job.
- HTTP status codes + a consistent JSON envelope make client error handling dramatically simpler.
- CORS, timeouts, pagination and search are “small” things that decide whether a demo feels like a real product.
7.3 Possible future improvements
- User accounts and per-user history (the current table is global).
- RAD/DEG mode toggle, more scientific functions (hyperbolic, random, constants).
- Expression auto-completion and syntax highlighting in the display.
- Export history to CSV, calculation statistics dashboard.
- Replace SQLite with PostgreSQL/MySQL for multi-instance hosting.
8. Deployment & Access Guide (for teaching assistants)
How to access the running project
- Public URLs (during evaluation):
- Front end:https://elegant-elf-173fd2.netlify.app/
- Back end:https://tribulation.pythonanywhere.com/
- (fill in the actual deployed URLs here once deployed) - Local run: follow each repository's README (install →
python app.py→python -m http.server 5500→ openhttp://localhost:5500).
How to test
- Click buttons or use the keyboard to enter expressions (
12+8,(1+2)*3,-5+8,0.1+0.2,1/0,1+…) and press=. - Verify every calculation shows in the History panel; refresh the page and verify the history persists.
- Click ✕ on a record to delete it; use Clear all; use the search box.
- Toggle the scientific panel (
ƒx) and trysin(30),sqrt(16),5!. - Stop the back-end service and press
=— the front end must not produce a result (separation check). - API smoke test:
curl -X POST https://<your-backend-domain>/api/calculate -H "Content-Type: application/json" -d '{"expression":"(1+2)*3"}'
# => {"success":true,"expression":"(1+2)*3","result":"9",...}
Notes
- Screenshots are also stored in the backend repo under
docs/screenshots/(20 PNGs + 1 GIF). - Both repositories contain
README.md(run instructions) andcodestyle.md(code standards with sources). - If any link above is still a placeholder, it means the corresponding repository or deployment was not yet pushed/published — please replace with the final URLs.
— Assignment blog by student 832401126 · First Assignment · Front-End / Back-End Separation Calculator System
相关推荐
基于改进虚拟同步发电机的构网型并联储能逆变器控制研究(Simulink仿真实现)
内容概要:本文系统解读了一套完整的多机器人路径规划(MAPF)MATLAB代码库,重点剖析了基于优先级规划算法的实现机制与工程架构设计。该框架采用几何、拓扑、调度与呈现四层解耦结构,实现了从地图解析、四邻域拓扑与Petri网构建、基于启发式的路径规划,到时间同步冲突消解及动画可视化的全流程处理。核心技术亮点包括动态边权膨胀机制以缓解硬封锁引发的虚假不可解问题、基于哈希结构的节点预留历史实现高效冲突查询、以及通过规划阶段信息前移驱动的几何惩罚型局部同步策略,显著提升了大规模场景下的求解效率与可行性。文章还深入比较了三种时间同步策略的设计取舍,并介绍了Petri网双阶段优化路径与端到端的可视化链路,旨在为MAPF领域的研究与教学提供一个可复现、可扩展、可批判的高质量参考实现。; 适合人群:具备一定MATLAB编程基础,从事路径规划、机器人调度、智能交通、自动化仓储等相关领域研究的科研人员、高校研究生及工程技术人员。; 使用场景及目标:①学习和复现多机器人路径规划中的优先级规划算法及其工程实现;②掌握动态边权膨胀、节点预留历史、局部同步等关键技术以提升算法效率与鲁棒性;③构建从算法建模、冲突消解到结果可视化的完整科研流程,支撑论文复现与系统开发。; 阅读建议:建议读者结合提供的代码逐模块调试,重点关注四层架构之间的接口设计与信息传递机制,通过修改地图复杂度与智能体数量验证算法性能,并尝试优化文中指出的重复代码以提升运行效率。
模拟、机会约束、敏感性分析和蒙特卡洛验证的电池储能系统辅助数据中心容量规划的学术研究项目.rar
模拟、机会约束、敏感性分析和蒙特卡洛验证的电池储能系统辅助数据中心容量规划的学术研究项目.rar
新一代NetCore Net10 代码生成器 SmartSoftHelp DeepCore XSuite Pro Global Eco AIAgent 20206.V29国际专业版
这不仅仅是一个代码生成器 SmartSoftHelp DeepCore XSuite Pro Global Eco AIAgent 20206.V29国际专业版 致力于打造世界一流的.NET C# 辅助开发工具。 以「最专业、最智能、最简单、最实用」为核心目标,极简,极速,极致的巅峰之作! 面向世界专业生态版! C#软件开发,代码生成,工具集成,最前沿的科技之作! 数据库安全解决方案,高并发解决方案 软件极速开发解决方案,UI,后端,API,优化方案 微软最新技术栈,最佳架构方案,数据库操作,控制器,UI全程异步操作 程序开发工具集成,版权保护方案 SmartSoftHelp魔法精灵工作室
04_开发环境.rar
04_开发环境
基于PID控制的永磁同步直线电机位置环控制matlab仿真(三闭环)(Simulink仿真实现)
内容概要:本文系统解读了一套完整的多机器人路径规划(MAPF)MATLAB代码库,聚焦于优先级规划算法的工程实现。文章将求解过程划分为几何、拓扑、调度与呈现四个解耦层次,详细阐述了地图解析、Petri网构建、基于动态边权膨胀的路径规划、时间同步与冲突消解机制,以及可视化链路设计。框架核心思想是分离空间规划与时间消解:先通过惩罚机制引导路径避让,再以节点预留历史等技术高效处理时间冲突,并提出几何惩罚前移等优化策略提升同步效率。全文还分析了不同同步策略的取舍与框架的可扩展性,旨在为MAPF的研究与教学提供一份可复现、可批判的参考文本。; 适合人群:具备一定编程基础,熟悉MATLAB环境,从事机器人路径规划、智能调度或相关领域研究的研发人员及研究生。; 使用场景及目标:① 学习并实现大规模多机器人系统的路径规划与冲突消解;② 理解优先级规划中动态边权膨胀、节点预留历史、几何惩罚前移等关键技术的设计原理与工程取舍;③ 为仓储物流、无人机编队等应用场景提供可复现的算法框架和技术参考。; 阅读建议:此资源不仅提供算法代码,更注重系统架构设计与工程实践。建议读者结合全文的数据流组织,逐步实现各模块功能,并通过提供的可视化工具调试和验证算法行为,重点关注各模块间的接口契约与性能优化点。


