Assignment2: A calculator that implements front - and back-end interaction

-草甸- 2023-10-20 03:10:05

I. Introduction 

In this blog post, I will detail the implementation of the front - and back-end interactive Web calculator and show the final product.

I made this calculator can achieve addition, subtraction, multiplication, division, zero clearing, power and trigonometric function, exponential function, inverse trigonometric function and ans operations.

Link to the finished project code: Assignment2 codes in github

II. Basic information about the author

Course for This Assignment2301-MUSE社区-CSDN社区云
Assignment RequirementsSecond assignment-- Back-end separation calculator programming-CSDN社区
The Aim of This AssignmentImprove the function of calculator and realize front-end interaction
MU STU ID and FZU21126259_832101125

目录

I. Introduction 

II. Basic information about the author

III. PSP Table

IV. Finished product display

①Web developer model:

② Basic Function

③Trigonometric function

④Anti-trigonometric function

 ④ logarithmic function:

⑤ Find history records(the latest ten history records):

 V. Project design idea

①Front-end design ideas:

②Back-end design idea:

 VII. Code interpretation

①Front-end code interpretation

a. Java Script

b. HTML

c. Css

 ②Back-end Programming Implementation (Python)

VII. Project future outlook

VIII. reflections

IX. Reference material


III. PSP Table

PSP Table
PSPEstimated time (minutes)Actual time (minutes)
Planning  
• Estimate:4040
Development  
• Analysis3030
• Design Spec2020
• Design Review1010
• Coding Standard:2020
• Design3030
• Coding300500
• Code Review100100
• Test2030
Reporting  
• Test Report:55
• Size Measurement1010
• Postmortem & Process Improvement Plan1010
TOTAL TIME595805

IV. Finished Product Display

①Web developer model:

② Basic Function

 

③Trigonometric function

sin(x):

cos(x):

tan(x):

④ Anti-trigonometric function

 asin(x):

 

acos(x):

 

atan(x):

 

 ④ logarithmic function:

 

 

⑤ Find history records(the latest ten history records):

 


 V. Project design idea

①Front-end design ideas:

a. HTML Structure: Create an HTML file to define the structure of the web page. Add input fields, buttons, and other elements so that users can enter mathematical expressions and perform calculations.

b. CSS Styling: Use CSS to beautify your web pages and make them look attractive and easy to use. You can add styles such as backgrounds, fonts, colors, and layouts.

c. JavaScript interaction: Use JavaScript to write front-end logic that implements the following functions:

     Listen for button click events to capture user input.

     Dynamic display of user input mathematical expressions in the input box.

     Handles expression evaluation when the user clicks the equal button.

     Display the calculation results on the web page.

d. User Experience (UX) : Ensure that the user interface is friendly and easy to use. Error handling, such as division by zero error, inverse trigonometric function exceeding threshold error, etc. are added to improve user experience.

②Back-end design idea:

a. Python back end: Use Python to write back-end code, you can use PyCharm for development. The main role of the back end is to process requests from the front end, perform computation operations, and return the results to the front end.

b. API design: Design two apis, respectively for storage and reading.

c. Database connection: Store compute history or other data by using PyMySQL to connect to the database and perform the necessary database operations.

d. Result return: The stored expression and its corresponding calculation result are sent back to the front end, usually in JSON format. Be sure to handle any potential errors or exceptions to provide a friendly error message.

e. Deployment: Deploy the Python back-end to the local server to ensure that it can respond to front-end requests.


 VII. Code interpretation

①Front-end code interpretation

a. Java Script

// 这个函数用于将输入添加到显示框中
function display(input) {
  const str = document.getElementById("text");
  str.value += input;
}

// 这个异步函数执行计算,处理数学表达式
async function equals() {
  const str = document.getElementById("text");
  let input = str.value;
  let lastExpression = input;

  // 如果输入包含 'Ans',尝试获取答案并替换 'Ans' 为答案的值
  if (input.includes('Ans')) {
    try {
      const ansValue = await getAns();
      input = input.replace(/Ans/g, ansValue);
    } catch (error) {
      console.error('获取答案出错: ' + error);
    }
  }

  // 处理三角函数和反三角函数
  if (input.includes('asin') || input.includes('acos')) {
    const asinMatch = input.match(/asin\(([^)]+)\)/);
    const acosMatch = input.match(/acos\(([^)]+)\)/);

    if (asinMatch) {
      const x = parseFloat(asinMatch[1]);
      if (x < -1 || x > 1) {
        str.value = "Error: Invalid input for asin(x). x must be in the range [-1, 1].";
        return;
      }
    }

    if (acosMatch) {
      const x = parseFloat(acosMatch[1]);
      if (x < -1 || x > 1) {
        str.value = "Error: Invalid input for acos(x). x must be in the range [-1, 1].";
        return;
      }
    }
  }

  // 替换 '^' 运算符为 '**'
  if (input.includes('^')) {
    input = input.replace(/\^/g, '**');
  }

  // 替换三角函数和反三角函数为 Math 对象的方法
  if (input.includes('asin') || input.includes('acos') || input.includes('atan')) {
    input = input.replace(/(\b(asin|acos|atan))\(/g, 'Math.$2(');
  }

  // 替换 sin, cos, tan 为 Math.sin, Math.cos, Math.tan
  if (input.includes('sin') || input.includes('cos') || input.includes('tan')) {
    input = input.replace(/(\b(sin|cos|tan))\(/g, 'Math.$2(');
  }

  // 替换 'e' 为 Math.E,'π' 为 Math.PI
  if (input.includes('e')) {
    input = input.replace(/e/g, 'Math.E');
  }
  if (input.includes('π')) {
    input = input.replace(/π/g, 'Math.PI');
  }

  // 处理对数函数
  if (input.includes('log')) {
    input = input.replace(/log\(([^)]+)\)\(([^)]+)\)/g, 'Math.log($2) / Math.log($1)');
  }

  // 替换 'ln' 为 Math.log
  if (input.includes('ln')) {
    input = input.replace(/ln/g, 'Math.log');
  }

  // 替换 'Ans' 为上次计算的结果
  if (input.includes('Ans')) {
    let ansValue = getAns();
    input = input.replace(/Ans/g, ansValue);
  }

  // 处理除以 0 的情况
  if (input.includes('/0')) {
    str.value = "Error: Division by zero is not allowed";
    return;
  }

  try {
    // 使用 eval 函数计算表达式
    const result = eval(input);
    str.value = result;

    // 创建一个 XMLHttpRequest 对象并发送 POST 请求
    const xhr = new XMLHttpRequest();
    xhr.open('POST', 'http://localhost:5000/post', true);
    xhr.setRequestHeader('Content-type', 'application/json');
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          const response = xhr.responseText;
          console.log(response);
        } else {
          console.error('请求失败,状态码:' + xhr.status);
        }
      }
    };
    const data = {
      expression: lastExpression,
      result: result
    };
    xhr.send(JSON.stringify(data));
  } catch (error) {
    str.value = "Error";
  }
}

// 删除最后一个字符
function back() {
  const str = document.getElementById("text");
  str.value = str.value.substring(0, str.value.length - 1);
}

// 重置显示框
function reset() {
  const str = document.getElementById("text");
  str.value = "";
}

// 将常数 Math.E 插入到显示框
function insertE() {
  const str = document.getElementById("text");
  str.value += Math.E;
}

// 在 getAns 函数中返回 Promise,用于获取答案
function getAns() {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://localhost:5000/get', true);
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          const Data = JSON.parse(xhr.responseText);
          const array = Data["data"];
          console.log(array);
          resolve(array[0][1]);
        } else {
          console.error('获取数据出错: ' + xhr.status);
          reject(xhr.status);
        }
      }
    };
    xhr.send();
  });
}

// 获取历史记录
function getHistory() {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', 'http://localhost:5000/get', true);
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if (xhr.status === 200) {
        Data = JSON.parse(xhr.responseText);
        array = Data["data"];
        console.log(array);
        let string = "";
        for (let i = 0; i < array.length; i++) {
          string += array[i][0] + " = " + array[i][1];
          string += '\n';
        }
      } else {
        console.error('获取数据出错: ' + xhr.status);
      }
    }
  };
  xhr.send();
}

b. HTML

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>Simple Calculator in Web</title>
		<link href="css/PageSetting.css" rel="stylesheet" type="text/css" />
		<script type="text/javascript" src="js/CalculatorFunction.js"></script>
		<!-- <script type="text/javascript" src="js/history.js"></script>  -->
		<!-- <script type="text/javascript" src="js/localServer.js"></script> -->
	</head>
	
	<body>
		<div id="calculator">
			<div id="head"><h3>Simple Calculator in Web</h3></div>
			<div id="show" align="center"><input type="text" id="text" ></div>
			<div id="cuttom">
				<table align="center">
					<tr>
						<td><input type="button" value="e" onclick="display('e')"></td>
						<td><input type="button" value="π" onclick="display('π')"></td>
						
						<td><input type="button" value="(" onclick="display('(')"></td>
						<td><input type="button" value=")" onclick="display(')')"></td>
						
						<td><input type="button" value="^" onclick="display('^')"></td>
						<td><input type="button" value="history" onclick="getHistory()"></td>
					</tr>
					<tr>
						<td><input type="button" value="log" onclick="display('log(')"></td>
						<td><input type="button" value="ln" onclick="display('ln(')"></td>
						<td><input type="button" value="ans" onclick="display('Ans')"></td>
						<td><input type="button" value="asin" onclick="display('asin(')"></td>
						<td colspan="2"><input type="button" value="←" onclick="back()"></td>
					</tr>
					<tr>
						<td><input type="button" value="." onclick="display('.')"></td>
						<td><input type="button" value="0" onclick="display(0)"></td>
						<td><input type="button" value="acos" onclick="display('acos(')"></td>
						<td><input type="button" value="atan" onclick="display('atan(')"></td>
						<td colspan="2"><input type="button" value="c" onclick="reset()"></td>
					</tr>
					<tr>
						<td><input type="button" value="7" onclick="display(7)"></td>
						<td><input type="button" value="8" onclick="display(8)"></td>
						<td><input type="button" value="9" onclick="display(9)"></td>
						<td><input type="button" value="+" onclick="display('+')"></td>
						<td><input type="button" value="-" onclick="display('-')"></td>
						<td><input type="button" value="tan" onclick="display('tan(')"></td>
					</tr>
					<tr>
						<td><input type="button" value="4" onclick="display(4)"></td>
						<td><input type="button" value="5" onclick="display(5)"></td>
						<td><input type="button" value="6" onclick="display(6)"></td>
						<td><input type="button" value="*" onclick="display('*')"></td>
						<td><input type="button" value="/" onclick="display('/')"></td>
						<td><input type="button" value="sin" onclick="display('sin(')"></td>
					</tr>
					<tr>
						<td><input type="button" value="1" onclick="display(1)"></td>
						<td><input type="button" value="2" onclick="display(2)"></td>
						<td><input type="button" value="3" onclick="display(3)"></td>
						<td colspan="2"><input type="button" value="=" onclick="equals()"></td>
						<td><input type="button" value="cos" onclick="display('cos(')"></td>
					</tr>
				</table>
				
			</div>
		</div>
	</body>
</html>

c. Css

body {
    background: #f0f0f0;
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
}

#calculator {
    width: 600px;
    margin: 50px auto;
    border: 1px solid #ccc;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    background-color: #fff;
    border-radius: 10px; /* 添加圆角 */
    padding: 20px; /* 增加内边距 */
}

#head {
    background-color: #333;
    color: #fff;
    text-align: center;
    padding: 10px 0;
    border-radius: 10px; /* 添加圆角 */
}

#head h3 {
    margin: 0;
    font-size: 24px;
}

#show input {
    width: 100%;
    height: 60px;
    font-size: 30px;
    text-align: right;
    border: 2px solid black;
    padding: 10px;
    outline: none;
    box-sizing: border-box;
    border-radius: 10px; /* 添加圆角边框 */
}

#custom {
    padding: 20px;
}

table {
    width: 100%;
    table-layout: fixed;
    margin-top: 15px; /* 上方间隔 */
    margin-bottom: 15px; /* 下方间隔 */
}

table td {
    width: 25%;
    margin: 10px; /* 左右间隔 */
}

table input {
    width: 100%;
    height: 50px;
    font-size: 20px;
    text-align: center;
    border: none;
    outline: none;
    cursor: pointer;
    background: #f0f0f0;
    border-radius: 10px;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2); /* 添加阴影效果 */
    transition: transform 0.2s, box-shadow 0.2s; /* 添加过渡效果 */
}



/* 鼠标悬停时应用立体效果和放大效果 */
table input:hover {
    background: #ccc;
    transform: scale(1.1); /* 放大效果 */
    box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2), 0 0 0 2px #000; /* 增加阴影深度和黑色边框 */
}

 ②Back-end Programming Implementation (Python)

/post API

  • Used to store operation expressions and values.
  • The client can send a POST request to this interface, passing a JSON data including the expression and the result of the calculation.
  • The interface inserts the received data into the database and ensures that the latest 10 records are kept and the excess records are deleted.
  • Return a JSON response, including the message "ok" indicating that the operation was successful, or an error message and status code 500 indicating that the operation failed.
@app.route('/post', methods=['POST'])
def post_history():  # 存储运算表达式和值
    try:
        data = request.get_json()  # 获取POST请求的JSON数据
        expression = data.get('expression')
        result = data.get('result')

        time = datetime.datetime.now()

        # 插入新数据
        data = (time, expression, result)
        insert = "INSERT INTO history (time, expression, result) VALUES (%s, %s, %s)"
        cursor.execute(insert, data)

        # 获取当前记录数量
        cursor.execute("SELECT COUNT(*) FROM history")
        record_count = cursor.fetchone()[0]

        # 如果记录数量超过十条,删除最旧的记录
        if record_count > 10:
            delete_old_records = "DELETE FROM history ORDER BY time LIMIT %s"
            cursor.execute(delete_old_records, (record_count - 10,))

        conn.commit()

        response_message = "ok"
        return jsonify({"message": response_message})

    except Exception as e:
        error_message = str(e)
        return jsonify({"error": error_message}), 500
#用于存储运算表达式和值。
#客户端可以向此接口发送 POST 请求,传递一个 JSON 数据包括表达式和计算结果。
#该接口会将接收到的数据插入数据库中,并确保保留最新的 10 条记录,删除多余的记录。
#返回一个 JSON 响应,包括消息 "ok" 表示操作成功,或者包括错误消息和状态码 500 表示操作失败。

/get API

  • Used to obtain historical operation expressions and results.
  • A client can send a GET request to this interface to get the latest 10 history records.
  • The interface queries the history in the database and returns a JSON response with the expression and result data.
  • If the query fails, an error message and status code 500 are returned.
@app.route('/get', methods=['GET'])
def get_calculation_data():  # 得到历史值
    try:
        cursor.execute("SELECT expression, result FROM history ORDER BY time DESC LIMIT 10")
        data = cursor.fetchall()
        return jsonify({"data": data})

    except Exception as e:
        error_message = str(e)
        return jsonify({"error": error_message}), 500
#用于获取历史运算表达式和结果。
#客户端可以向此接口发送 GET 请求,以获取最新的 10 条历史记录。
#该接口会查询数据库中的历史记录,并返回一个 JSON 响应,其中包括表达式和结果的数据。
#如果查询失败,将返回错误消息和状态码 500。

VII. Project future outlook

Classify users by setting new interactive bars and new calculation logic, so that specific users can directly use the calculation keys related to the intended purpose, such as tax calculation, game equipment damage calculation and other functions.


VIII. Reflections

In this assignment, I successfully completed the development of web from front end to back end, which further improved my understanding of the connection between front and back end, and made the connection process and details clearer. As an EE student, after completing this project, I have also preliminarily mastered the code writing of java script, css and html, and become more familiar with the development framework of web pages, which will be of great help to my further study.


IX. Reference material

...全文
1147 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
promisekoloer 2023-11-04
  • 打赏
  • 举报
回复

项目设计理念部分,用pycharm写java代码?

-草甸- 2023-11-05
  • 举报
回复
@promisekoloer 在网上学的Python flask 里的jsonify,由于是零基础可能有理解不当的地方,不好意思
内容概要:本文提出一种基于灰狼优化算法(GWO)优化改进互补集合经验模态分解(CEEMDAN)的混合储能风电功率平抑策略。通过GWO算法对CEEMDAN的关键参数(如白噪声幅值、最大本征模态函数数量等)进行全局寻优,显著提高了信号分解的精度与自适应性,有效克服模态混叠与残余噪声问题。在此基础上,将分解后的风电功率序列按频域特征分配给电池与超级电容构成的混合储能系统,充分发挥电池长时储能与超级电容快速响应的优势,实现高频分量由超级电容平抑、低频分量由电池承担的协调控制。结合Matlab平台完成算法仿真与系统建模,验证了该方法在平抑风电功率波动、降低储能系统综合损耗、延长设备寿命及提升电网电能质量与运行稳定性方面的优越性能。; 适合人群:具备一定电力系统分析、可再生能源并网技术、现代信号处理(如EMD类方法)及智能优化算法基础的研究生、科研人员及从事新能源发电控制、储能系统设计与智能电网调度的工程技术人员。; 使用场景及目标:①应用于风电场配套混合储能系统的实时功率协调控制,提升并网友好性;②优化非平稳、非线性风电功率信号的自适应分解精度,服务于后续预测与调度;③结合GWO等群智能优化算法,提升储能系统在平抑可再生能源波动中的动态响应能力、运行经济性与工程实用性。; 阅读建议:建议读者结合提供的Matlab代码深入理解GWO优化CEEMDAN参数选择机制与混合储能功率分配逻辑,重点关注信号分解效果评价指标(如相关系数、均方根误差)与储能系统性能指标(如SOC变化、功率应力)的关联分析,可进一步拓展至多目标优化、在线滚动优化及其他智能算法(如鲸鱼优化、麻雀搜索)的对比研究。
代码下载链接: https://pan.quark.cn/s/ce7b749cac89 家政上门预约服务小程序源码是一款用于构建专业家政门到门预约服务应用的小程序软件,能够帮助用户创建一个独立的品牌中心,不仅有助于构建一种身临其境的客户体验,而且能够以「美图秀秀」风格的方式展示专业的维修项目以及维修人员,使得服务信息一目了然。该源码主要适用于单一区域(或无需设置城市),不支持企业直接入驻(企业可以选择以个人身份进行入驻),其后台系统功能完备,订单分配方式丰富多样。维修人员能够参与订单的竞争获取,管理员则有权进行订单的指派,同时系统支持客户自主选择维修师傅,并配备了分销与促销、会员优惠、积分兑换、子卡使用等多种营销手段。源码所含功能:城市定位:允许设置多个城市,一旦启用城市功能,客户在进入首页时将自动进行位置识别,同时在首页和下单页面对客户是否位于运营城市进行提示。注意:每个城市提供的服务的种类相同,此功能并非城市加盟或代理功能,城市设置的主要目的是提醒客户当前所在城市非运营区域。下单途径:提供多种下单方式,包括选择服务下单(可选择配件/可直接选择师傅/仅显示后台设定的距离范围内的师傅)、次卡下单(需先购买次卡/次卡可设定使用次数和有效期)、管理员派单(客户需扫描绑定至个人微信)。抢单/派单:后台可设定距离范围,维修人员仅能参与范围内订单的竞争(抢单功能可根据需求关闭),管理员在派单页面会按照师傅与客户的距离进行排序,同时展示师傅的联系电话,以便在派单前与师傅进行电话确认订单:
内容概要:本文围绕“考虑光伏-储能-数据中心多能互补的园区容量优化配置”展开研究,提出了一种基于Matlab代码实现的综合优化模型,旨在通过深度融合光伏发电、储能系统与数据中心的算力负荷特性,实现园区内能源供给与信息负载的协同优化。研究构建了一个兼顾可再生能源出力波动性、储能系统动态响应能力以及数据中心弹性算力需求的多目标优化框架,采用先进的优化算法求解光伏装机容量与储能配置容量的最优组合,以实现能源利用率最大化、运行成本最小化及碳排放最低化的多重目标。文中提供了完整的Matlab实现代码,涵盖数据预处理、模型构建、求解流程与结果可视化,便于读者复现、验证与拓展研究。; 适合人群:具备一定电力系统、能源工程、运筹学或自动化背景的科研人员、研究生及工程技术人员,尤其适用于从事综合能源系统规划、可再生能源集成、数据中心节能优化、低碳园区建设等相关领域的专业人士。; 使用场景及目标:①用于高校与科研机构开展多能互补系统容量配置的理论研究与教学示范;②为工业园区、数字经济园区、绿色数据中心等提供科学的能源系统规划与设计依据;③支撑智能微电网、虚拟电厂、碳中和园区等新型能源形态的仿真验证与决策支持。; 阅读建议:建议读者结合Matlab代码与技术文档同步研读,重点关注优化模型的数学建模逻辑、目标函数设计、约束条件设定及求解器调用过程,推荐在实际案例数据基础上调整参数进行仿真实验,以深入理解多能互补系统的协同运行机制与优化配置规律。

176

社区成员

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

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