Ⅰ. Introduction
In this blog, I’d like to introduce a web calculator. It can implement a variety of complex calculation functions, while storing the calculated strings and results. So I will show the design and codes of this calculator and display its functions.
The github link: github link
Ⅱ. Author Information Table
Course for This Assignment | https://bbs.csdn.net/forums/ssynkqtd-04 |
---|---|
The Link of Requirement of This Assignment | https://bbs.csdn.net/topics/617378696 |
The Aim of This Assignment | Implement both front end and back end functions of the calculator |
MU STU ID and FZU STU ID | <21125953_832101113> |
Ⅲ. PSP Form
Personal Software Process Stages | Estimated Time(minutes) | Actual Time(minutes) |
---|---|---|
Planning | ||
• Estimate | 40 | 40 |
Development | ||
• Analysis | 40 | 40 |
• Design Spec | 25 | 30 |
• Design Review | 20 | 20 |
• Coding Standard | 10 | 10 |
• Design | 30 | 40 |
• Coding | 500 | 550 |
• Code Review | 120 | 100 |
• Test | 60 | 60 |
Reporting | ||
• Test Repor | 60 | 80 |
• Size Measurement | 10 | 10 |
• Postmortem & Process Improvement Plan | 15 | 15 |
Sum | 930 | 995 |
Ⅳ. Product Display
Arithmetic operation functions display:
The calculator can implement not only basic but also complex arithmetic functions, including radical sign, trigonometric function, log, scientific notation, bracket computation and so on.
The storing function display:
Ⅴ. Design and Implementation Process
- HTML is used for creating a web page and set corresponding buttons and interfaces.
- CSS is mainly for controlling sizes and colors to beautifying the calculator.
- JAVASCRIPT implements calculated functions and interaction between front-end and back-end.
- MySQL records operations into database.
functional structure diagram
Ⅵ. Code
(1) Front end
HTML:
Set all required buttons and a history interface.
<!DOCTYPE html>
<html>
<head>
<title>web calculator</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="calculator">
<input type="text" id="display" readonly>
<div id="buttons">
<button>(</button>
<button>)</button>
<button>C</button>
<button>DEL</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button>+</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>-</button>
<button>7</button>
<button>8</button>
<button>9</button>
<button>*</button>
<button>.</button>
<button>0</button>
<button>=</button>
<button>/</button>
</div>
<div id="advanced-buttons">
<button>e^x</button>
<button>ln</button>
<button>x^y</button>
<button>sin</button>
<button>cos</button>
<button>tan</button>
<button>%</button>
<button>sqrt</button>
<button>sci</button>
<button>pi</button>
<button>ans</button>
<button>his</button>
</div>
<div id="history"></div>
</div>
<script src="calculator.js"></script>
</body>
</html>
CSS:
Set the sizes and colors of the items, including the calculator background, displays and storing interface.
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #fff;
font-family: Arial, sans-serif;
}
#calculator {
width: 530px;
}
#display {
width: 100%;
height: 80px;
text-align: right;
margin: 0;
padding-right: 10px;
box-sizing: border-box;
border: none;
background-color: #303030;
color: #fff;
font-size: 50px
}
#buttons, #advanced-buttons {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
#buttons button, #advanced-buttons button {
height: 80px;
border: none;
border-top: 1px solid #303030;
background-color: #505050;
color: #00ff90;
font-size: 30px;
outline: none;
}
#buttons button:active, #advanced-buttons button:active {
background-color: #505050;
}
#history {
height: 100px;
margin-top: 20px;
padding: 10px;
overflow: auto;
background-color: #404040;
color: #fff;
}
JAVASCRIPT:
var display = document.getElementById('display');
function appendToScreen(btnVal) {
display.value += btnVal;
}
function clearScreen() {
display.value = '';
}
function deleteCharacter() {
if (display.value) {
display.value = display.value.slice(0, -1);
}
}
// send results to back end
function sendCalculationToBackend(expression, result) {
const xhr = new XMLHttpRequest();
xhr.open('POST', '/getCalculation', true);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
const data = {
expression: expression,
result: result
};
xhr.send(JSON.stringify(data));
}
// Symbol button click event
document.getElementById("buttons").addEventListener("click", function (e) {
if (e.target.matches("button")) {
var btnVal = e.target.innerText;
switch (btnVal) {
case '=':
try {
var result = new Function('return ' + display.value)();
display.value = result.toString();
sendCalculationToBackend(display.value, result);
} catch (err) {
display.value = "error";
}
break;
case 'C':
clearScreen();
break;
case 'DEL':
deleteCharacter();
break;
default:
appendToScreen(btnVal);
}
}
});
// Advanced computing button click event
document.getElementById("advanced-buttons").addEventListener("click", function (e) {
if (e.target.matches("button")) {
var op = e.target.innerText;
var curVal = eval(display.value);
switch (op) {
case 'e^x':
display.value = Math.exp(curVal).toString();
break;
case 'ln':
display.value = Math.log(curVal).toString();
break;
case 'x^y':
display.value = 'Math.pow(' + display.value + ',y'; // y is the desired variable
break;
case 'sin':
var rad = curVal * (Math.PI / 180); // Convert angles to radians
display.value = Math.sin(rad).toString();
break;
case 'cos':
var rad = curVal * (Math.PI / 180); // Convert angles to radians
display.value = Math.cos(rad).toString();
break;
case 'tan':
var rad = curVal * (Math.PI / 180); // Convert angles to radians
display.value = Math.tan(rad).toString();
break;
case 'sqrt':
display.value = Math.sqrt(curVal).toString();
break;
case '%':
var divisor = parseFloat(prompt("Enter divisor:"));
if (!isNaN(divisor) && divisor !== 0) {
var result = curVal % divisor;
display.value = result.toString();
} else {
display.value = "Invalid divisor";
}
break;
case 'sci':
display.value = curVal.toExponential();
break;
case 'pi': // add π button
display.value += Math.PI;
break;
default:
appendToScreen(btnVal);
}
}
});
(2) Back end
Import the necessary libraries and modules. Creating a MySQL database connection: To create a connection to a MySQL database using the pymysql library, you need to provide connection parameters such as host name, port, user name, password, and database name. Then create Flask application and database table.
from flask import Flask, request, render_template, jsonify
import sqlite3
conn = pymysql.connect(
host='cheng',
port=3306,
user='root',
password='446537',
database='calculator'
)
app = Flask(__name)
cursor = conn.cursor()
# 创建计算历史表
cursor.execute('''
CREATE TABLE IF NOT EXISTS calculation_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
expression TEXT,
result REAL
)
''')
conn.commit()
@app.route('/')
def index():
return render_template('calculator.html')
@app.route('/saveCalculation', methods=['POST'])
def save_calculation():
data = request.get_json()
expression = data.get('expression')
result = data.get('result')
try:
# 在后端执行计算
calculation_result = eval(expression)
# 保存计算历史到数据库
cursor.execute('INSERT INTO calculation_history (expression, result) VALUES (?, ?)', (expression, calculation_result))
conn.commit()
return jsonify({'message': 'Calculation successful', 'result': calculation_result})
except Exception as e:
return jsonify({'message': 'Calculation error', 'error': str(e)})
@app.route('/getCalculationHistory', methods=['GET'])
def get_calculation_history():
# 获取计算历史记录
cursor.execute('SELECT expression, result FROM calculation_history')
history = cursor.fetchall()
return jsonify({'data': history})
if __name__ == '__main__':
app.run(debug=True)
Ⅶ. Summary
In this assignment, I have a deeper understanding of front-end tools (HTML, CSS, JAVASCRIPT). Also, I learned back-end technologies like the flask framework and the database of MySQL. In the future, I tend to improve my both front-end and back-end skills and continue optimizing designs and codes of projects.