Software Engineering Assignment 1: Calcura Full-Stack Calculator — Chen Linghan 832401201

832401201陈凌晗 832401201陈凌晗 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区

目录

  • Contents
  • 1. GitHub repositories and code standards
  • 2. Background and objectives
  • 3. Requirements
  • 3.1 Required functions
  • 3.2 Extensions
  • 4. Design and implementation
  • 5. Technology choices
  • 6. Interface and the service boundary
  • 7. Finished product
  • 7.1 Four operations
  • 7.2 Precedence, parentheses, signs, and decimals
  • 7.3 Invalid input and division by zero
  • 7.4 Scientific functions and explanation steps
  • 7.5 History, favorites, search, copy, CSV export, and refresh
  • 8. Code explanation
  • 8.1 Parsing rules
  • 8.2 API
  • 8.3 How one calculation runs
  • 8.4 Why the front end sends only the expression
  • 8.5 When the back end writes to the database
  • 8.6 Parsing, precedence, validation, and errors
  • 8.7 History operations and response format
  • 9. Database design
  • 10. Tests
  • 11. Deployment and access
  • 12. PSP table
  • 13. Personal summary
  • Appendix A. Assignment blog checklist
  • 14. References

Fuzhou University Software Engineering Assignment 1

Calcura: A Separated Front-End and Back-End Calculator

Chen Linghan Student ID 832401201 Completed 3 October 2026

Course: Software Engineering, Fuzhou University. Assignment: the first project, a calculator with a separated front end and back end. The goal is a calculator that anyone can open on the public internet, together with a report that covers the repositories, code standards, PSP table, finished product, design, code, and personal summary.

This report implements that calculator. The browser only collects input, shows results, and handles interaction. Parsing, arithmetic, error checks, and history storage all happen on the server. A successful result is written to PostgreSQL and can still be read back after the page is refreshed.

Contents

    1. GitHub repositories and code standards
    1. Background and objectives
    1. Requirements
  • 3.1 Required functions

  • 3.2 Extensions

    1. Design and implementation
    1. Technology choices
    1. Interface and the service boundary
    1. Finished product
  • 7.1 Four operations

  • 7.2 Precedence, parentheses, signs, and decimals

  • 7.3 Invalid input and division by zero

  • 7.4 Scientific functions and explanation steps

  • 7.5 History, favorites, search, copy, CSV export, and refresh

    1. Code explanation
  • 8.1 Parsing rules

  • 8.2 API

  • 8.3 How one calculation runs

  • 8.4 Why the front end sends only the expression

  • 8.5 When the back end writes to the database

  • 8.6 Parsing, precedence, validation, and errors

  • 8.7 History operations and response format

    1. Database design
    1. Tests
    1. Deployment and access
    1. PSP table
    1. Personal summary
  • Appendix A. Assignment blog checklist

    1. References

1. GitHub repositories and code standards

ItemLocation
Name / student IDChen Linghan / 832401201
Deadline7 October 2026, 23:59
Front-end websitehttps://calcura-frontend.vercel.app/
Back-end APIhttps://calcura-backend.vercel.app/
API documentationhttps://calcura-backend.vercel.app/docs
Front-end repositoryhttps://github.com/chenlinghan82-debug/calcura-frontend
Back-end repositoryhttps://github.com/chenlinghan82-debug/calcura-backend
Front-end code stylehttps://github.com/chenlinghan82-debug/calcura-frontend/blob/main/codestyle.md
Back-end code stylehttps://github.com/chenlinghan82-debug/calcura-backend/blob/main/codestyle.md

Both main branches contain codestyle.md. The standard follows Google style for names, formatting, comments, and commit messages. This report quotes only the pieces needed to explain a design choice. The complete source is the two GitHub repositories.

2. Background and objectives

The assignment asks for a calculator that other people can open, not a page that works only on one computer. The required behavior is addition, subtraction, multiplication, division, a separated front end and back end, operator precedence, parentheses, unary plus and minus, decimals, invalid input, division by zero, and history that is stored in a database, displayed, and deleted.

Calcura keeps that boundary strict. The browser does not call eval, and it does not calculate the answer before sending it. The front end submits the original expression. The back end returns the result, the explanation steps, and the database record. History is not stored in localStorage.

3. Requirements

3.1 Required functions

RequirementImplementationEvidence
Four operations+ - * / ; buttons show + - x and divisionFigures 3 to 6
Separated servicesThe React page calls the FastAPI JSON APIFigures 1, 2, and 28
PrecedenceRecursive descent does multiplication and division before additionFigure 8
ParenthesesParentheses change the order and may be nestedFigure 9
Unary signs-5 + 8, 3 x -2, and --5Figures 10 and 11
DecimalsDecimal parses and calculates decimal valuesFigure 7
ErrorsEmpty input, illegal characters, bad parentheses, and division by zero return 400Figures 12 to 14
Saved historyA successful calculation is written to calculation_historyFigures 22, 26, and 29
Display and deleteHistory can be read, one row can be deleted, or all rows can be clearedFigures 22 and 26

3.2 Extensions

  • Power, square root, factorial, percent, absolute value, and the constants pi and e. Power is right associative. The automated test expects 2^3^2 = 512.

  • sin, cos, and tan use degrees, so sin(30) = 0.5. ln is the natural logarithm and log is the common logarithm.

  • Ans reads the latest successful row in the database. It is not a number kept temporarily in the browser.

  • Every successful row stores its steps. History can be marked as a favorite and searched by expression.

  • Statistics show the count, average, minimum, and maximum. Search filters the list only. It does not change those four numbers.

  • The page can copy a result, switch between dark and light themes, accept keyboard input, and stack the panels on a phone-width screen.

  • CSV export, the health check, Swagger documentation, and the API connection panel are included.

4. Design and implementation

The system has three layers. The presentation layer collects the expression and renders the result. The application layer does lexical analysis, parsing, and the business rules. The data layer stores successful calculations only. A failed request does not add a row.

SYSTEM BOUNDARY browser, API, and database

Browser   React + TypeScript
|   HTTPS + JSON
v
FastAPI routes, validation, and error conversion
|
+-- Lexer
+-- Recursive-descent parser
|
v
SQLAlchemy  -->  Neon PostgreSQL
table calculation_history
ModuleResponsibility
frontend/src/App.tsxKeyboard, buttons, theme, history list, favorites, search, and copy
frontend/src/services/api.tsRequests for calculate, history, delete, statistics, export, and health
backend/app/api/routes.pyREST endpoints, status codes, and database transactions
backend/app/services/calculator.pySafe parsing and arithmetic. It does not run code from the input.
backend/app/models/history.pyColumns of the history table
backend/testsParser, API, errors, history, and PostgreSQL URL handling

5. Technology choices

LayerChoiceReason
Front endReact, TypeScript, ViteComponent interface with clear types
StylingPlain CSSResponsive layout without a large component library
Back endFastAPIExplicit routes and generated OpenAPI documentation
Data accessSQLAlchemy 2Keeps route handlers separate from database operations
Production dataNeon PostgreSQLHistory remains after the public deployment
Test dataSQLiteAutomated tests do not depend on the cloud database
Testspytest46 tests are collected and passing
HostingVercel and GitHubBoth services have public HTTPS addresses

6. Interface and the service boundary

After the home page opens, the top-right corner says Backend online, and the footer names FastAPI, PostgreSQL, and React. API connection is not a decoration. Clicking it expands the real service address, health check, preview endpoint, calculate endpoint, history endpoint, and database type, and it links to Swagger. Arithmetic still runs only on the back end. While the user is building an expression, Calcura keeps the complete expression visible and does not display an answer or create a history row. Only pressing = or Enter submits the finished expression. The page first obtains the result and explanation steps from POST /api/preview, then calls POST /api/calculate to save the successful record. Both operations use the same server-side parser. The browser neither parses nor evaluates the expression.

Figure 1

Figure 1. Public home page. The expression is entered on the left and database history is shown on the right. No rows exist yet, so the statistics are 0.

Figure 2

Figure 2. API connection panel. The status is Backend online, the address is https://calcura-backend.vercel.app/, and the database type is postgresql.

The keyboard accepts digits and operators directly. Users can continue building a long expression without an intermediate answer replacing their input. Enter or = calculates, Esc clears the current input, and Backspace deletes one character. After a successful copy, the button text changes to Copied. The light theme changes only the display. It does not change where the calculation or storage happens.

7. Finished product

The screenshots below come from the public website. In a few early screenshots, the status line still briefly says Calculating with the backend after the result and steps are already visible. That is the moment the screenshot was taken. It does not mean the browser calculated the result. The completed state is Result returned by the backend, together with the history row and the API response.

7.1 Four operations

Figure 3

Figure 3. Addition: 12 + 8 = 20. The step is 12 + 8 = 20.

Figure 4

Figure 4. Subtraction: 20 - 8 = 12. The step is 20 - 8 = 12.

Figure 5

Figure 5. Multiplication: 6 x 7 = 42. The step is 6 x 7 = 42.

Figure 6

Figure 6. Division: 20 / 4 = 5. The step is 20 / 4 = 5.

7.2 Precedence, parentheses, signs, and decimals

The four captions below keep only the result, so an expression is not split across lines. The automated tests also cover 0.1 + 0.2 = 0.3. For 1 + 2 x 3, the steps first calculate 2 x 3 = 6 and then 1 + 6 = 7. For (1 + 2) x 3, the steps first calculate 1 + 2 = 3 and then 3 x 3 = 9. The tests also cover --5 = 5.

Figure 7

Figure 7. Decimals: 1.5 + 2.25 = 3.75.

Figure 8

Figure 8. Precedence: 1 + 2 x 3 = 7.

Figure 9

Figure 9. Parentheses: (1 + 2) x 3 = 9.

Figure 10

Figure 10. Unary minus: -5 + 8 = 3.

Figure 11

Figure 11. Negative multiplication: 3 x -2 = -6. A unary minus may follow the multiplication sign.

7.3 Invalid input and division by zero

An incomplete expression, an unknown name, a bad decimal, unmatched parentheses, and division by zero are all rejected by the back end. The API returns HTTP 400. The page shows the reason in red, and the failed attempt is not written to the database.

Figure 12

Figure 12. After 12 +, the back end returns an invalid-expression message.

Figure 13

Figure 13. For 8 / 0, the page shows Division by zero is not allowed.

Figure 14

Figure 14. A direct POST /api/calculate with {"expression":"8/0"}. The response is HTTP 400 and the message is Division by zero is not allowed.

7.4 Scientific functions and explanation steps

Scientific functions are also sent to the back end. The arguments of sin, cos, and tan are degrees, not radians, so sin(30) = 0.5, cos(60) = 0.5, and tan(45) = 1. tan(90), ln(0), log(-2), and the square root of a negative number are rejected. log(100) = 2, which is the common logarithm.

Figure 15

Figure 15. Power and sign: -2 ^ 2 = -4. Power binds before the unary minus, so the first step is 2 ^ 2 = 4.

Figure 16

Figure 16. Square root: sqrt(9) = 3.

Figure 17

Figure 17. Factorial: 5! = 120. Factorial accepts only integers from 0 to 170.

Figure 18

Figure 18. Percent: 50% = 0.5. The percent sign divides by 100.

Figure 19

Figure 19. The constant pi is 3.1415926536. pi and e are constants, not functions.

Figure 20

Figure 20. Sine: sin(30) = 0.5. Here 30 means 30 degrees.

Figure 21

Figure 21. Natural logarithm: ln(1) = 0. Absolute value is also covered by the history in Figure 26: abs(-12) = 12.

Right-associative power is covered by tests. 2^3^2 first calculates 3^2 and then 2^9, so the result is 512, not 64. The result of -2^2 is -4 because the unary minus does not become part of the power base.

7.5 History, favorites, search, copy, CSV export, and refresh

Each history row contains the expression, result, steps, favorite flag, and creation time. The page converts the UTC time returned by the back end into the browser's local time. The 2026-10-02 16:02 shown in a screenshot corresponds to 2026-10-02T08:02Z in the API. The eight-hour difference is the time zone, not a wrong record.

The Export button downloads the stored calculation history as calcura-history.csv through GET /api/history/export. The file is generated by the back end from the database rather than copied from the currently visible rows. It contains id, expression, result, created_at, is_favorite, and steps, so the calculation data can be opened in Excel or another spreadsheet program for checking and analysis. The front end does not send the search keyword to the export route, so a search filters only the on-screen list; the CSV still contains up to the latest 1,000 stored records.

Figure 22

Figure 22. History, steps, and favorites. The step for 5 + 1 is 5 + 1 = 6. The stars on 12 + 8 and 20 - 8 are lit. At that moment there were 19 records, the average was 12.731136, and the range was -6 to 120.

Figure 23

Figure 23. After searching for sqrt, the list contains only sqrt(9) = 3 and says 1 result. The statistics above still cover all 19 records: average about 11.046926, range -6 to 120. Search does not recalculate the statistics.

The averages in Figures 22 and 23 differ because rows were added and deleted between the two screenshots, while both totals are 19. Statistics always describe every successful record in the database at that moment.

Figure 24

Figure 24. Copy succeeded in the dark theme. The button says Copied.

Figure 25

Figure 25. Light theme. 5 + 1 = 6, and the status is Result returned by the backend.

Figure 26

Figure 26. After a refresh, the current input returns to its initial state, but the history remains. The light page still shows 19 records, so the data comes from the database rather than page memory. The cross on each row deletes that record.

Deleting one record calls DELETE /api/history/{id}. Clearing everything calls DELETE /api/history. A favorite calls POST /api/history/{id}/favorite. The automated tests check all three operations.

8. Code explanation

This section explains the important implementation, as the assignment requires, without pasting the whole source. Sections 8.1 and 8.2 give the grammar and the API list. Sections 8.3 through 8.7 explain the front-end request, the back-end calculation, precedence, validation, errors, creating and deleting history, the response format, and why the code is written this way. The files are frontend/src/services/api.ts, backend/app/api/routes.py, backend/app/services/calculator.py, and backend/app/models/history.py. The colored boxes below are the code being explained.

8.1 Parsing rules

The parser first splits the input into numbers, names, operators, and parentheses, then evaluates it by grammar level. It does not hand the string to Python for execution. The test input import('os') is recognized as an illegal name.

CODE 1 parsing grammar backend/app/services/calculator.py

expression = term     ((+|-) term)*
term       = unary    ((*|/) unary)*
unary      = (+|-) unary | power
power      = postfix  (^ unary)*          right associative
postfix    = primary  (! | %)*
primary    = number | constant | Ans | function(expression) | (expression)

Multiplication and division sit in an inner level, so they finish before addition and subtraction. The exponent of a power goes back into unary, so 2^3^2 is evaluated from right to left and the result is 512, not 64. The unary minus wraps the power. -2^2 first calculates 2^2 and then negates it, so the result is -4.

  • An expression may be at most 200 characters, and the absolute value of an exponent cannot exceed 1000.

  • Factorial accepts only integers from 0 to 170. Percent divides the current value by 100.

  • sqrt rejects a negative number. sin, cos, and tan convert degrees to radians before calculating.

  • Ans reads the latest successful record. Using Ans when there is no history returns a clear error.

8.2 API

MethodPathPurpose
GET/api/healthCheck the service and the database type
POST/api/previewReturn the back-end result without writing history. The page uses it to show an answer quickly.
POST/api/calculateCalculate the expression. Success returns 201 and saves the row.
GET/api/historyReturn history, newest first. keyword searches the expressions.
DELETE/api/history/{id}Delete one record
DELETE/api/historyClear all history
POST/api/history/{id}/favoriteToggle the favorite flag
GET/api/statsReturn the count, average, minimum, and maximum
GET/api/history/exportExport CSV

Figure 27

Figure 27. Back-end Swagger at https://calcura-backend.vercel.app/docs. It lists the endpoints above and their request and response models.

Figure 28

Figure 28. GET /api/health returns HTTP 200. database is postgresql, so the live service is not using SQLite.

Figure 29

Figure 29. GET /api/history?limit=3 returns the latest 3 rows, while total is still 19. Each row includes steps and a UTC time.

Figure 30

Figure 30. In the same check, GET /api/stats returns total = 19, average = 11.046925929136304, minimum = -6, and maximum = 120.

Figure 31

Figure 31. The CSV export contains id, expression, result, created_at, is_favorite, and steps. The stored result of abs(-12) is 12, and two early rows have favorite set to True.

8.3 How one calculation runs

The work is split into four layers. Neither the calculation nor the save happens in the browser.

CODE 2 four layers of one calculation

Interface    buttons, keyboard, theme, copy, and error text
Requests     preview, calculate, history, delete, favorite, stats, export, health
Calculation  lexer, recursive descent, Decimal, scientific functions, steps
Data         save successful calculations only; query, delete, favorite, statistics, export

After the user presses = or Enter, the front end sends the original complete expression to /api/preview. The back end parses and calculates it without writing history, allowing the result and steps to be displayed. The front end then calls /api/calculate; only a successful official calculation creates a calculation_history row. Finally, the page requests /api/history to refresh the list. Merely typing or refreshing the page never calculates an expression or creates a record.

8.4 Why the front end sends only the expression

The body of calculate contains only the expression. There is no result field. The browser cannot calculate the answer first and then upload it.

CODE 3 front end frontend/src/services/api.ts calculate sends the expression only

export function calculate(expression: string) {
  return request<CalculateResponse>('/api/calculate', {
    method: 'POST',
    body: JSON.stringify({ expression }),
  })
}

POST uses text/plain so the browser can skip one CORS preflight and the public site waits for one fewer round trip. This is not local calculation. The content type is set in the shared request function, before calculate sends the body.

CODE 4 front end frontend/src/services/api.ts POST is text/plain

if (method === 'POST' && init?.body && !headers.has('Content-Type')) {
  headers.set('Content-Type', 'text/plain;charset=UTF-8')
}

On failure, the page reads the message from the back end and shows it in red. The preview request starts only after = or Enter is pressed. If the same completed expression is submitted again within a short time, the request layer may reuse that exact result only after the back end has already calculated it; typing alone never enters the preview cache. If the back end is stopped, the page can still accept input, but it cannot produce a new correct result.

8.5 When the back end writes to the database

/api/calculate adds a row only after parsing succeeds. The success status is 201. Division by zero, an empty expression, and illegal characters become HTTP 400 before any insert, so a failure leaves no history.

CODE 5 back end backend/app/api/routes.py write the row only after success

def calculate(
        request: CalculateRequest,
        db: Session = Depends(get_db),
) -> CalculateResponse:
    needs_ans = expression_needs_ans(request.expression)
    ans = latest_answer(db) if needs_ans else None
    try:
        result, steps = explain_expression(request.expression, ans)
    except CalculationError as exc:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail={"success": False, "message": str(exc)},
        ) from exc
 
    record = CalculationHistory(
        expression=request.expression,
        result=result,
        is_favorite=False,
        steps_json=dump_steps(steps),
    )
    db.add(record)
    db.commit()

Preview of an ordinary expression does not query the database. Only when the expression contains Ans does it read the latest successful record, and preview still does not insert a row. Typing can therefore show a back-end result quickly, while pressing equals is what saves it.

8.6 Parsing, precedence, validation, and errors

The parser is handwritten recursive descent. It does not use eval or exec, and it does not give the user input to a third-party expression library. The lexer accepts only numbers, names, the four arithmetic operators, power, parentheses, percent, and factorial. An unrecognized character raises Unsupported character. Empty input raises Expression cannot be empty. import('os') is treated as a name and is then rejected because it is not pi, e, Ans, or an allowed function. User input therefore cannot become Python code.

Precedence comes from which function calls which, not from temporarily rewriting multiplication before addition. _expression calls _term first, and only _term does multiplication and division, so 1+2*3 first becomes 6 and then 1+6. Parentheses recursively call the whole expression at the innermost level, so they can change the order and can be nested. Decimals use Decimal, which avoids the binary floating-point error in 0.1+0.2. Scientific functions are rounded to a limited number of decimal places only at the end. sin, cos, and tan convert degrees to radians first, so sin(30) equals 0.5.

Validation has three layers. The lexical layer rejects an empty string, an illegal character, and a bad decimal such as 2..3. The syntax layer rejects a missing parenthesis, an operator with no following number, and an unknown name. The semantic layer rejects division by zero, the square root of a negative number, ln(0), log(-2), tan(90), an exponent that is too large, and a non-integer factorial. Division by zero is raised where the division happens:

CODE 6 back end backend/app/services/calculator.py reject division by zero

if operator == "*":
    result = left * right
else:
    if right == 0:
        raise CalculationError("Division by zero is not allowed")
    result = left / right

The route catches CalculationError and returns HTTP 400. The body has success set to false and a message. The front end shows that sentence and does not show a stack trace. If a record does not exist, delete and favorite return 404. Bad input is not a 500, because the problem is the user's expression, not a server crash.

8.7 History operations and response format

A successful calculation creates a row. Queries are ordered by creation time, newest first. keyword filters expressions only and does not change the statistics. Deleting one record first loads it by id. A missing id returns 404; an existing id is deleted and committed. Clearing all history is an extension and returns the number of rows actually deleted. A favorite only toggles the flag and does not change the result. Ans uses the latest successful record. Using Ans when no history exists returns a clear error instead of silently treating it as 0.

The official calculation returns the expression, result, steps, and the complete record. Preview returns the same result and steps, but saved is false. The history response returns both items and total, so the page can show only the newest few rows while still saying how many rows the database contains. The statistics endpoint returns the count, average, minimum, and maximum separately, so a search cannot make the average look like the average of the visible list.

9. Database design

The live service has one business table, calculation_history. Local pytest uses SQLite with the same columns. The Vercel back end connects to Neon PostgreSQL through an environment variable. The database type returned by the health check distinguishes these two environments.

ColumnTypeMeaning
idinteger, primary keyRecord number
expressionstring, at most 200The original expression submitted by the user
resultfloating pointResult calculated by the back end
is_favoritebooleanFavorite flag, default false
steps_jsonstring, at most 2000JSON array of explanation steps
created_attimezone-aware datetimeStored in UTC

10. Tests

pytest in the back-end test directory reports 46 passed. The local tests use a temporary SQLite database and do not change the live PostgreSQL database.

GroupCountWhat it covers
Valid expressions23Four operations, precedence, parentheses, signs, decimals, power, percent, factorial, and scientific functions
Invalid expressions14Empty input, division by zero, incomplete expressions, parentheses, bad decimals, unknown names, huge exponents, and illegal function arguments
Code injection1Rejects treating Python code as an expression
Ans and steps1Steps for (2+3)4, and Ans3
API7Health, save, search, error codes, delete, clear, statistics, favorites, export, and database URL normalization
  • Valid samples include 1+2*3=7, (1+2)*3=9, 0.1+0.2=0.3, 2^3^2=512, -2^2=-4, sin(30)=0.5, and log(100)=2.

  • Invalid samples include 1/0, 1+, (1+2, 2..3, 2**3, sqrt(-1), 1.5!, ln(0), log(-2), and tan(90).

11. Deployment and access

The front end and the back end are two GitHub repositories, deployed separately on Vercel. The database address is a Vercel environment variable. The repository does not contain the database password. Pushing code to main redeploys the matching Vercel project. Changing only this report or its screenshots does not require a new deployment. The calculation service is in San Francisco. The current access path arrives there first, so keeping the function in the same region avoids an extra trip through Hong Kong and returns the answer sooner.

  • On a computer, open https://calcura-frontend.vercel.app/. The top-right corner should say Backend online.

  • For the API, open https://calcura-backend.vercel.app/api/health. database should be postgresql.

  • If a phone on mobile data cannot open the site, the phone network usually cannot reach Vercel. A proxy running on the computer is not applied to the phone automatically. Connect the phone to Wi-Fi that can reach the site, or turn on the same proxy on the phone and then open it.

The statistics card in Figure 33 still describes every record: 19 rows, an average of about 11.046926, and a range from -6 to 120. Only the newest 6 rows are shown so the card fits the page. The footer still says 19 results.

Figure 32

Figure 32. Phone width. Function keys are above the numeric keypad.

Figure 33

Figure 33. Phone-width history. The total is still 19; the newest 6 rows are shown.

12. PSP table

The table below is my own time estimate for this assignment, in hours. It records planned and actual effort. It is not an audit by someone else.

StagePlannedActualMain work
Reading and planning1.52.0Confirm the front-end and back-end duties and the deliverables
Requirements and design2.53.0Function list, API, and table structure
Back-end implementation6.08.0Parser, API, errors, and database
Front-end implementation5.07.0Interface, history, theme, search, and mobile layout
Testing2.53.546 automated tests and public manual checks
Deployment2.03.0GitHub, Vercel, and PostgreSQL
Report2.53.0Screenshots, captions, and writing
Total22.029.5Extra time went mainly to deployment and checking screenshots

The rows follow the stages suggested by the course. Reading and planning is requirements confirmation. Requirements and design includes the system design, the API, and the database table. Back-end implementation includes expression calculation, error handling, and writing history. Front-end implementation includes showing history, deleting it, and interaction. Testing includes the joint check. Deployment and the report correspond to going online and writing the blog. Planned hours were estimated before development. Actual hours were filled in after the work was finished.

13. Personal summary

The point of this assignment was not to draw a calculator. It was to keep the calculation and the data on the server. Calcura uses its own recursive-descent parser instead of eval, and PostgreSQL stores the history. The health check, Swagger, steps, favorites, search, statistics, and CSV export are there to show the front-end and back-end process.

While debugging, I mainly watched three things: the 46 pytest tests, the status code of a direct API request, and whether the request body sent by the browser was the original expression. After the back end is stopped, the page still opens, but it cannot produce a new answer. That shows the calculation was not left in the browser.

On the public network, a cross-origin preflight can delay the first request, so POST was changed to text/plain to avoid an unnecessary round trip. The interface now keeps a long expression visible while it is being entered and does not show a result until = or Enter is pressed. The health check keeps the service connection active without evaluating an expression or creating history. Preview and the official calculation both remain on the back end, and only the successful official calculation is saved. A phone on mobile data could not open the site because that network could not reach Vercel, not because the page was built only for a computer.

The easy expression mistakes are power and the minus sign. 2^3^2 must be read from right to left, and the result is 512. The result of -2^2 is -4. Trigonometric functions use degrees rather than radians, so sin(30) is 0.5. The database stores UTC, and the page converts it to local time, so a screenshot and the API differ by 8 hours. The record is not wrong. Search filters the list only. Statistics still cover every successful record.

For deployment, local tests use temporary SQLite and the live site uses Neon PostgreSQL. The database address is a Vercel environment variable, and the repository has no password. /api/health returns postgresql, which shows that the live site is not SQLite. What I learned most clearly is how recursive descent expresses precedence, why decimals need Decimal, and what 201, 400, and 404 should each mean.

A later version could add login, so each person sees only their own history. The public database currently holds the demonstration data for this assignment, so the scope was not expanded into an unfinished account system.

Appendix A. Assignment blog checklist

The Chinese CSDN post keeps a table-of-contents marker at the top. This Word report uses the Contents list in the opening section instead. The table below maps the course requirements to this report.

Course requirementWhere it is in this report
Assignment backgroundSection 2
Requirements analysisSection 3
System architectureSections 4, 5, and 6
API designSection 8.2
Database designSection 9
Code explanationSection 8, especially Sections 8.3 to 8.7
Front-end and back-end flowSections 8.3 and 8.4
Expression parsingSections 8.1 and 8.6
Exception handlingSections 7.3 and 8.6
Calculation and history modulesSections 8.5 to 8.7
Deployment addressSections 1 and 11
GitHub addressesSection 1
PSP tableSection 12
At least 10 screenshotsFigures 1 through 33
Personal summarySection 13

CSV export, the health check, Swagger, and API connection are in Sections 3.2, 6, and 8.2, and in Figures 2 and 27 through 31. These extensions do not move the calculation into the browser.

14. References

...全文

相关推荐

从注意力到行动 pdf Agent

从注意力到行动 pdf

言之。

同步电机与构网型变流器的频率稳定特性及多时间尺度交互机理研究(Simulink仿真实现)

内容概要:本文系统解读了一套完整的多机器人路径规划(MAPF)MATLAB代码库,重点围绕优先级规划算法展开,涵盖从地图解析、拓扑构建、路径规划、冲突消解到可视化呈现的全流程。文章提出四层架构设计:几何层负责地图解析与栅格化;拓扑层构建四邻域图与Petri网模型;调度层实现基于动态边权膨胀的优先级路径规划与时间同步冲突消解;呈现层完成动画与视频输出。核心创新包括动态边权膨胀机制避免硬封锁导致的虚假不可解、节点预留历史实现高效冲突查询、几何惩罚驱动的局部同步提升效率,以及Petri网双阶段优化支持解的存在性与最优性分离判断。框架兼顾实用性与可扩展性,适用于大规模智能体场景。; 适合人群:具备MATLAB编程基础,从事机器人、自动化、智能交通或路径规划相关研究的科研人员与研究生。; 使用场景及目标:① 学习并复现多机器人无冲突路径规划的经典与先进算法;② 掌握动态边权膨胀、时间同步、冲突消解等关键技术的工程实现;③ 借助模块化框架进行算法改进与性能优化,支撑仓储物流、无人机编队等应用场景的仿真研究。; 阅读建议:建议按文中所述的数据流顺序逐步阅读,重点关注各模块接口设计与算法取舍逻辑,结合提供的完整资源进行代码调试与实验验证,深入理解“空间规划-时间消解”分离的设计思想。

程序猿鑫

huashu-motion 让编码 Agent 直出商业宣传片-一个专门给 Claude Code、Codex 等工具使用的 Skill

huashu-motion 一个专门给 Claude Code、Codex 等工具使用的 Skill。它不跑黑盒视频生成模型,而是让 Agent 直接用代码绘制动画,成片就是一个网页。 项目最大的特色是“先写谱再拍片”,Agent 能写纯文本乐谱配合乐器采样在本地配乐,并精准对齐每帧音效。在浏览器里按 C 键点击画面就能直接留批注,Agent 会定位源码只改动那一处,也可以在右侧表单手动调参。 它还内置了从顶级发布片提炼的 20 种运动语言、自动化质检与并行渲染机制,小模型同样能做出高级感。

一叶知秋yyds

YOLO26算法校园作业场景锚目标检测+训练好的模型+103张数据集+pyqt可视化界面.zip

附训练好的 YOLO 权重与 PyQt 可视化检测界面,页面底部含可视化效果预览,毕设/课设开箱即用。 【数据集概况】 · 检测类别(中文):[锚(anchor)] · 训练集:90 张 · 验证集:9 张 · 测试集:4 张 · 总计:103 张 该数据集聚焦校园作业场景,通过精准标注手写文字中的锚元素,为教育场景下的文本识别与作业分析提供高质量数据支撑,助力教学评估与学生书写质量研究。该数据集训练集占比90%,验证集与测试集分别占9%和4%,符合目标检测任务数据划分的常规比例,训练集规模充足以保障模型学习能力,验证集与测试集合理分配用于模型性能评估,确保数据分布科学合理。该数据集标注工作严格遵循规范,所有锚元素的边界框标注精准,标注内容与... 【训练曲线与评估图】 【模型训练配置】 参数 | 值 模型 | yolo26n 训练轮数 | 100 epochs 输入尺寸 | 640x640 批次大小 | 24 优化器 | auto 初始学习率 | 0.01 训练设备 【关键指标汇总】 训练了 100 个 epoch,最终轮指标: 指标 | 数值 mAP50 | **0.6351** mAP50-95 | 0.1958 Precision | 0.6436 Recall | 0.5714 train/box_loss | 1.6649 train/cls_loss | 1.3181 val/box_loss | 2.3156 val/cls_loss | 2.5145 【训练过程分析】 100 轮训练后 mAP50 仅 0.6351,模型收敛不充分。Loss 曲线前期下降后进入平台期,mAP 提升缓慢。mAP50-95 为 0.1958,定位精度同样偏低。 【模型性能评估】 Precision 0.643... 使用场景:毕业设计、课程设计、深度学习入门、工业场景落地验证。

guo_xiao_xiao_

基于扩展卡尔曼滤波(EKF)的激光雷达与雷达异构传感器融合算法研究(Matlab代码实现)

内容概要:本文系统解读了一套完整的多机器人路径规划(MAPF)MATLAB代码库,聚焦于优先级规划算法的工程实现。该框架将求解过程划分为几何、拓扑、调度与呈现四个解耦层次,实现了从地图解析、四邻域拓扑与Petri网建模,到基于优先级启发式的路径规划、时间同步冲突消解,再到动画可视化的全流程闭环。其核心创新在于“空间规划-时间消解”分离的设计思想:通过动态边权膨胀策略取代传统硬封锁,允许后续智能体在必要时穿越先前路径,提升狭窄环境下的规划成功率;利用节点预留历史机制实现高效的冲突查询,并结合几何惩罚机制在规划阶段预测潜在冲突,显著提高时间同步效率。框架还支持Petri网整数规划求解路径,增强了算法的完备性与优化潜力,整体具备良好的可复现性、可扩展性与教学价值。; 适合人群:具备一定编程基础和机器人路径规划基础知识,从事相关科研或工程应用的研发人员,尤其是高校研究生及自动化、人工智能方向的技术人员。; 使用场景及目标:①应用于仓储物流、无人机编队、自动驾驶等多智能体协同场景中的路径规划问题;②为MAPF算法的教学、实验与性能评估提供可复现的MATLAB实现参考;③支持对优先级规划、冲突消解机制、Petri网建模等关键技术进行二次开发与优化验证。; 阅读建议:建议读者按照文中所述的数据流顺序逐步学习,重点关注各模块之间的接口设计与信息传递机制,结合提供的可视化工具调试与观察算法行为,深入理解“空间规划-时间消解”分离的设计思想,并可在实际应用中尝试调整惩罚权重、同步策略等参数以优化性能。

李锦科研
评论
收藏 已收藏
分享
返回顶部