First Assignment: Front-End and Back-End Separation Calculator System

832402115钱施宇 2026-10-01 14:21:31

First Assignment: Front-End and Back-End Separation Calculator System

Course: 2601_FZU-MU_SE
Assignment: First Assignment — Front-End and Back-End Separation Calculator System
Student: Shiyu Qian (钱施宇)
MU ID: 24217213 / FZU ID: 832402115
Completion date: October 1, 2026

Table of Contents

  1. Course and Assignment Information
  2. Repository Links and Code Standards
  3. Assignment Requirements
  4. PSP Table
  5. Presentation of the Finished Product
  6. Requirement Analysis
  7. System Architecture
  8. Functional Structure
  9. API Design
  10. Database Design
  11. Code Explanation and Implementation Details
  12. Frontend Installation and Testing
  13. Backend Deployment
  14. Testing Results
  15. Personal Journey: Problems and Solutions
  16. Personal Learnings
  17. Future Improvements
  18. Third-Party Libraries
  19. Extra Features
  20. Conclusion

1. Course and Assignment Information

ItemDescription
Course2601_FZU-MU_SE / Software Engineering
AssignmentFirst Assignment: Front-End and Back-End Separation Calculator System
ObjectivesUnderstand front-end/back-end separation, implement a safe calculator API, persist calculation history, and deploy the system for public access
StudentShiyu Qian (钱施宇)
MU ID24217213
FZU ID832402115
Front endWeb application built with HTML, CSS, and native JavaScript
Back endNode.js 22+, Express, node:sqlite, decimal.js
DatabaseSQLite
DeploymentAlibaba Cloud ECS, Ubuntu 24.04, Nginx, PM2
Public frontendhttp://120.27.206.217/
Public APIhttp://120.27.206.217:8080/

The goal of this assignment was to build a calculator system with a separated front end and back end. The front end is responsible for user interaction and displaying results. The back end is responsible for validating and parsing expressions, performing calculations, handling exceptions, storing history, and returning JSON responses.

The most important architectural rule is that the final result must be calculated by the back end. The front end only sends an expression and displays the result returned by the API.

ItemLink
Frontend repositoryhttps://github.com/q1527700693-afk/832402115_calculator_frontend
Backend repositoryhttps://github.com/q1527700693-afk/832402115_calculator_backend
Frontend code standardhttps://github.com/q1527700693-afk/832402115_calculator_frontend/blob/main/codestyle.md
Backend code standardhttps://github.com/q1527700693-afk/832402115_calculator_backend/blob/main/codestyle.md

The frontend and backend are stored in two independent GitHub repositories, as required by the assignment.

3. Assignment Requirements

The assignment requires a calculator system with the following functions:

  • Addition, subtraction, multiplication, and division
  • Compound expressions with operator precedence
  • Parentheses
  • Decimal numbers
  • Unary positive and negative numbers
  • Invalid expression handling
  • Division-by-zero handling
  • Calculation history stored in a backend database
  • History query and deletion
  • Clear-all history as an optional function
  • Separation of front end and back end
  • Frontend/backend communication through HTTP and JSON
  • No use of eval, exec, or equivalent arbitrary-code execution
  • Deployment with a publicly accessible URL
  • Two GitHub repositories with README and codestyle.md
  • An English blog with screenshots, PSP data, design explanation, and testing instructions

4. PSP Table

The planned time was recorded before implementation. The actual time was updated after development, testing, and deployment.

PhaseTaskPlanned TimeActual Time
Requirement analysisRead the assignment and define the scope1 h1 h
System designArchitecture, API, and database design2 h2.5 h
Frontend developmentLayout, button interaction, history display4 h8 h
Backend developmentNode.js + Express project and APIs4 h6 h
Expression calculationTokenizer, infix-to-RPN conversion, RPN evaluation5 h7 h
DatabaseSQLite setup, table creation, node:sqlite operations3 h3 h
Frontend/backend integrationFetch API, CORS, joint debugging3 h4 h
TestingNormal, invalid, and boundary cases3 h5 h
DeploymentCloud deployment and public access3 h4 h
Blog writingScreenshots, documentation, PSP3 h3 h
Total31 h43.5 h

The actual time was higher than planned because additional features such as scientific calculation and base conversion were added, and several parser bugs were fixed during testing.

5. Presentation of the Finished Product

Figure 1: Main Interface

Main interface

The main interface contains three modes: standard calculation, base conversion, and scientific calculation. The calculation history is displayed on the right side.

Figure 2: Division Calculation

Division calculation

The expression 5÷2 is calculated on the backend and the result 2.5 is returned to the frontend.

Figure 3: Compound Expression

Compound expression

The compound expression 3+3×(5÷9)-5 is evaluated as -0.333333333333, which verifies operator precedence and negative results.

Figure 4: Scientific Calculation

Scientific calculation

The scientific expression 9×ln(2) is evaluated as 6.23832462504.

Figure 5: Base Conversion

Base conversion

The base conversion page supports conversions among binary, octal, decimal, and hexadecimal numbers.

Figure 6: History API

History API

The /api/history endpoint returns calculation history in JSON format.

Figure 7: Clear-All Confirmation

Clear-all confirmation

When the user clicks “Clear,” a confirmation dialog appears to prevent accidental deletion.

Figure 8: Backend Not Running

Backend not running

If the backend is stopped, the frontend displays the message “Unable to connect to the backend service.”

Figure 9: History and Scientific Calculations

History and scientific calculations

History records include scientific expressions such as log(8) and 9×ln(2), as well as invalid-expression messages.

Figure 10: Base Conversion Error

Base conversion error

When the backend is unavailable during base conversion, the frontend shows a connection error.

Figure 11: Adjacent Operand Bug

Adjacent operand bug

The invalid expression 0.888888888889tan(9)× was once treated as multiplication. This bug was fixed by adding syntax validation.

Figure 12: Input Sanitization

Input sanitization

The frontend filters unsupported characters, and the backend returns “Missing operator” for invalid input.

Figure 13: Backend Error Message

Backend error message

When the backend is stopped, historical records remain visible, but new calculations cannot be completed.

6. Requirement Analysis

6.1 Frontend Responsibilities

  • Display the calculator interface
  • Accept user input through buttons and keyboard
  • Send expressions to the backend API
  • Display calculation results
  • Display calculation history
  • Send delete and clear-history requests
  • Display error messages returned by the backend

6.2 Backend Responsibilities

  • Receive and validate expressions
  • Parse mathematical expressions safely
  • Perform calculations
  • Handle invalid expressions and division by zero
  • Store successful calculations in SQLite
  • Query and delete history
  • Return standardized JSON responses

7. System Architecture

Web Frontend
    |
    | HTTP / JSON
    v
Node.js + Express Backend
    |
    v
SQLite Database

The frontend does not calculate the final result. It sends the expression to the backend, and the backend performs validation, parsing, calculation, and history storage.

8. Functional Structure

Calculator System
├── Standard Calculation
│   ├── Addition, subtraction, multiplication, division
│   ├── Parentheses and operator precedence
│   ├── Decimal numbers
│   └── Unary positive/negative numbers
├── Scientific Calculation
│   ├── sin, cos, tan
│   ├── sqrt, log, ln, abs
│   ├── exponentiation (^)
│   └── constants pi and e
├── Base Conversion
│   └── Binary, octal, decimal, hexadecimal
├── Calculation History
│   ├── Save history
│   ├── Query history
│   ├── Delete one record
│   ├── Clear all history
│   └── Click a record to reuse its result
└── Error Handling
    ├── Invalid expression
    ├── Missing operator
    ├── Division by zero
    └── Backend connection failure

9. API Design

9.1 Calculate

POST /api/calculate
Content-Type: application/json

Request:

{
  "expression": "(1+2)*3"
}

Success response:

{
  "success": true,
  "expression": "(1+2)*3",
  "result": 9
}

Error response:

{
  "success": false,
  "message": "Division by zero is not allowed"
}

9.2 Base Conversion

POST /api/convert/base

Request:

{
  "value": "1010",
  "fromBase": 2,
  "toBase": 10
}

Success response:

{
  "success": true,
  "result": "10"
}

9.3 Query History

GET /api/history

Response:

{
  "success": true,
  "data": [
    {
      "id": 1,
      "expression": "6×6",
      "result": "36",
      "createdAt": "2026-10-01 13:15:54"
    }
  ]
}

9.4 Delete One History Record

DELETE /api/history/{id}

9.5 Clear All History

DELETE /api/history

10. Database Design

The backend uses SQLite to persist calculation history.

Table name: calculation_history

FieldTypeDescription
idINTEGERPrimary key, auto-increment
expressionTEXTCalculation expression
resultTEXTCalculation result
created_atTEXTCreation time

SQL:

CREATE TABLE IF NOT EXISTS calculation_history (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    expression TEXT NOT NULL,
    result TEXT NOT NULL,
    created_at TEXT NOT NULL
);

11. Code Explanation and Implementation Details

11.1 Frontend API Request

The frontend uses the Fetch API to send expressions to the backend.

function calculate(expression) {
    return request(API_BASE + "/api/calculate", {
        method: "POST",
        headers: {
            "Content-Type": "application/json"
        },
        body: JSON.stringify({
            expression: expression
        })
    });
}

The frontend selects the API base address dynamically:

var isLocal = window.location.protocol === "file:"
    || window.location.hostname === "localhost"
    || window.location.hostname === "127.0.0.1";

var API_BASE = isLocal
    ? "http://localhost:8080"
    : "http://120.27.206.217:8080";

11.2 Backend Calculation Route

router.post("/calculate", (request, response) => {
    try {
        const expression = request.body.expression;

        if (typeof expression !== "string" || expression.trim() === "") {
            throw new Error("Expression cannot be empty");
        }

        const result = evaluate(expression);
        historyService.save(expression, result);

        response.json({
            success: true,
            expression,
            result: toJsonResult(result)
        });
    } catch (error) {
        response.status(400).json({
            success: false,
            message: error.message
        });
    }
});

11.3 Expression Parser

The parser uses a safe mathematical expression pipeline:

  1. Tokenize the expression into numbers, functions, constants, operators, and parentheses.
  2. Validate token syntax to prevent adjacent operands and invalid function calls.
  3. Convert infix notation to Reverse Polish Notation with the shunting-yard algorithm.
  4. Evaluate the RPN expression with a stack.

The parser supports +, -, *, /, ^, parentheses, unary signs, sin, cos, tan, sqrt, log, ln, abs, pi, and e.

11.4 Database Operations

Insert:

const insertStatement = db.prepare(
    "INSERT INTO calculation_history (expression, result, created_at) VALUES (?, ?, ?)"
);

insertStatement.run(expression, result.toString(), createdAt);

Query:

const listStatement = db.prepare(
    "SELECT id, expression, result, created_at AS createdAt " +
    "FROM calculation_history ORDER BY id DESC"
);

listStatement.all();

Delete:

const deleteStatement = db.prepare(
    "DELETE FROM calculation_history WHERE id = ?"
);

deleteStatement.run(id);

12. Frontend Installation and Testing

12.1 Local Frontend

Open frontend/index.html directly in a browser, or use a local static server:

cd frontend
python -m http.server 5500

Then visit:

http://localhost:5500

When running locally, the frontend uses http://localhost:8080 as the API base address.

12.2 Test Cases

TestExpressionExpected Result
Addition12+820
Subtraction8-3*22
Multiplication7*642
Division10/2+712
Decimal0.1+0.20.3
Parentheses(1+2)*39
Unary negative-5+83
Division by zero1/0Error message
Invalid expression(1+2Error message
Scientificsin(30)0.5
Base conversion1010 from binary to decimal10

13. Backend Deployment

The backend is deployed on an Alibaba Cloud ECS instance.

Server information:

Deployment steps:

  1. Install Node.js 22+.
  2. Install Git and Nginx.
  3. Clone the frontend and backend repositories from GitHub.
  4. Run npm install in the backend directory.
  5. Start the backend with PM2 and configure auto-start on reboot.
  6. Configure the frontend API base address.
  7. Deploy the frontend with Nginx.
  8. Open the required ports in the Alibaba Cloud security group and system firewall.
  9. Test the public frontend and API.

14. Testing Results

The following tests were performed:

  • Basic arithmetic operations
  • Operator precedence
  • Parentheses
  • Decimal calculation
  • Unary positive and negative numbers
  • Division by zero
  • Invalid expressions
  • Scientific functions
  • Base conversion
  • History insertion, query, deletion, and clear-all
  • History persistence after page refresh
  • Frontend behavior when the backend is stopped
  • Public access from the internet

All required functions worked correctly after the fixes described in Section 15.

15. Personal Journey: Problems and Solutions

Problem 1: Adjacent Operands Were Misparsed

Input:

0.888888888889tan(9)×

The parser treated the expression as 0.888888888889 × tan(9) instead of reporting an error.

Cause: the parser did not check whether two operands were separated by a valid operator.

Solution: I added a validateTokens step. The validator checks:

  • Two operands must have an operator between them.
  • A function must be followed by parentheses.
  • Parentheses cannot be empty.
  • A binary operator cannot be followed directly by ).
  • Illegal consecutive operators are rejected.

After the fix, the expression above returns “Missing operator.”

Problem 2: Frontend Accepted Too Many Invalid Symbols

The input box allowed users to enter long sequences of unsupported characters.

Solution: I added frontend input sanitization and operator replacement:

  • Unsupported characters are filtered.
  • Maximum input length is limited.
  • Consecutive operator buttons replace the previous operator instead of appending endlessly.
  • The backend still performs final syntax validation.

Problem 3: Node.js Version Compatibility

The backend uses the built-in node:sqlite module, which requires Node.js 22 or later.

Solution: I installed Node.js 22+ on the server and used PM2 to keep the process running.

Problem 4: Frontend/Backend Connection

When the backend was not running, the frontend showed a connection error. This was expected, but the message was initially misleading because it mentioned Spring Boot.

Solution: I changed the message to “Unable to connect to the backend service. Please make sure the Node backend is running.”

16. Personal Learnings

Through this assignment, I learned how to design and implement a front-end/back-end separated system. I practised:

  • Building a calculator UI with HTML, CSS, and JavaScript
  • Using the Fetch API to call a backend service
  • Designing RESTful APIs with Express
  • Parsing mathematical expressions safely without eval
  • Using the shunting-yard algorithm and RPN evaluation
  • Persisting data with SQLite and node:sqlite
  • Using decimal.js for accurate decimal calculations
  • Deploying a Node.js application with PM2 and Nginx
  • Debugging frontend/backend integration and parser bugs

I also learned that testing invalid and boundary inputs is as important as testing normal cases.

17. Future Improvements

Possible future improvements include:

  • Unit conversion
  • User accounts with independent history
  • History search and pagination
  • Theme switching
  • More scientific functions and angle-unit switching
  • Keyboard shortcuts
  • Calculation statistics
  • Cloud database support such as PostgreSQL
  • HTTPS support with a custom domain

18. Third-Party Libraries

LibraryPurposeReason
ExpressWeb frameworkProvides REST API routing and request handling
decimal.jsHigh-precision decimal arithmeticAvoids floating-point issues such as 0.1 + 0.2
node:sqliteSQLite driverBuilt-in Node.js module for persistent history
corsCross-origin supportAllows the frontend to call the backend API during development

The backend does not use eval, exec, or script engines to execute user input. It uses a custom parser with syntax validation, shunting-yard conversion, and stack-based evaluation.

19. Extra Features

19.1 Base Conversion

Supports binary, octal, decimal, and hexadecimal conversions through:

POST /api/convert/base

19.2 Scientific Calculation

Supports:

sin, cos, tan, sqrt, log, ln, abs, ^, pi, e

Trigonometric functions use degrees by default.

19.3 Enhanced History

  • Delete one record
  • Clear all records
  • Click a history record to reuse its result
  • Persist history after page refresh

19.4 Frontend Input Protection

  • Filter unsupported characters
  • Limit input length
  • Replace the previous operator when operators are clicked consecutively

20. Conclusion

This assignment helped me understand the complete workflow of a front-end/back-end separated application. The frontend provides a usable calculator interface, while the backend performs all calculations, handles errors, stores history, and returns JSON responses. The project has been deployed to a public server and can be accessed through the URLs above. The bugs found during testing were analysed and fixed, which improved both the reliability of the parser and the user experience.

...全文
48 回复 打赏 收藏 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
内容概要:本文介绍了“Java+大数据+AI架构师实战营”这一系统性人才培养方案,旨在帮助具备Java基础的开发者在26周内完成向融合Java、大数据与人工智能技术的复合型架构师跃迁。课程围绕五大核心模块展开:架构基本功(微服务演进、分布式锁与ID设计)、数据引擎(亿级数据存储与Flink CDC实时同步)、网关与可观测性(Gateway源码改造、限流与日志采样)、AI融入架构(推荐系统、大模型应用开发)以及架构思维培养。通过“小绿书”项目贯穿始终,强调整合三域技术的系统设计能力而非孤立技能堆叠。; 适合人群:具备1-5年Java开发经验,希望突破技术瓶颈、拓展大数据与AI领域能力的中高级研发人员;适合有志于成长为全栈架构师的技术从业者。; 使用场景及目标:①掌握高并发、分布式系统下的架构设计方法;②理解海量数据的存储分层与实时计算架构;③学会将AI能力如大模型、RAG、向量检索等深度集成到业务系统中;④构建完整的系统可观测性与网关控制能力;⑤形成跨技术域的系统性架构思维。; 阅读建议:此资源以实战项目驱动学习,强调动手实践与架构思维并重。建议学习者结合课程代码与实际调试,深入理解每一环节的技术选型与设计权衡,尤其关注真实生产环境中难以复现的复杂约束,从而建立可迁移的架构“手感”。

173

社区成员

发帖
与我相关
我的任务
社区描述
梅努斯-软件工程
软件工程 高校 福建省·福州市
社区管理员
  • FZU_SE_LQF
  • zjcTander
  • 木村修
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧