173
社区成员
发帖
与我相关
我的任务
分享| Course for This Assignment | Software Engineering Practice |
|---|---|
| Assignment Requirements | Front-end / back-end separated calculator system |
| Objectives | Master front-end/back-end separation, API development, database persistence, system design, and technical blog writing |
| Name / Student ID | WU Zhengyang / 24127167 |
| PSP2.1 | Stages | Estimated (min) | Actual (min) |
|---|---|---|---|
| Planning | Planning | 30 | 25 |
| Development | Development | 320 | 360 |
| · Analysis | · Requirements analysis | 30 | 25 |
| · Design | · System/API/DB design | 40 | 45 |
| · Coding | · Backend (RPN + DB) | 90 | 110 |
| · Coding | · Frontend page | 60 | 70 |
| · Test | · Test all features | 30 | 35 |
| Reporting | Reporting | 150 | 160 |
| Total | Total | 500 | 545 |
This assignment requires a strictly separated front-end / back-end calculator. All computation must run on the backend; the frontend only collects the expression and sends it via HTTP POST. History must persist in a backend database (no localStorage). Must support operator precedence, parentheses, decimals, unary minus. No eval/exec. Two independent GitHub repos, each with README.md and codestyle.md. Support deleting history by id.
Tech stack: Python + FastAPI, SQLite, plain HTML/CSS/JS, hand-written Reverse Polish Notation.
Browser (index.html)
│ HTTP/JSON
▼
FastAPI (main.py)
├── Expression parser (tokenize → infix-to-postfix → evaluate)
├── History module (SQLAlchemy ORM)
▼
SQLite (calculator.db)
| Endpoint | Method | Purpose |
|---|---|---|
| /api/calculate | POST | Calculate expression and save to history |
| /api/history | GET | Get all history (descending) |
| /api/history/{id} | DELETE | Delete a record by id |










async function submitCalc(){
const resp = await fetch(BACKEND_URL + "/api/calculate", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({expression: inputDom.value.trim()})
});
const data = await resp.json();
resultDom.innerText = data.success ? "Result = " + data.result : "Error: " + data.message;
loadHistory();
}
@app.post("/api/calculate")
def calc(req: CalcRequest):
db = SessionLocal()
try:
res = calculate_expression(req.expression)
record = CalcHistory(expression=req.expression, result=res)
db.add(record); db.commit()
return {"success": True, "expression": req.expression, "result": res}
except ZeroDivisionError:
return {"success": False, "message": "Division by zero"}
except Exception as e:
return {"success": False, "message": "Invalid expression: " + str(e)}
finally:
db.close()
if c == "-":
if i == 0 or expr[i-1] in "(+-*/":
tokens.append("u-") # unary minus
else:
tokens.append(c) # binary subtraction
3*-2 and leading -5 needed a separate u- token with highest precedence.