diff --git a/README.md b/README.md new file mode 100644 index 0000000..dba0a9e --- /dev/null +++ b/README.md @@ -0,0 +1,327 @@ +##代码仓库:https://code.educoder.net/ppfc5brxg/102201121/tree/main/README.md +##博客地址:https://www.learnerhub.net/#/resources/3196/update +##视频地址:https://www.bilibili.com/video/BV1to2JYbEaW/?vd_source=355974c779ee1dfc75ebf39b824902b7 + +## 一、结对探索(4分)(汉字序号为一级标题,下同) + +**1.1 队伍基本信息**(1分)(阿拉伯数字序号为二级标题,下同) + +结对编号:_19___;队伍名称:_BLG___; + +| 学号 | 姓名 | 作业博客链接 | **具体分工** | +| :--: | :--: | :----------: | :----------: | +| 102201121 | 邵子瑞 | https://www.learnerhub.net/#/resources/3196 | 前端开发以及后端代码优化 | +| 102201112 | 李文杰 | https://code.educoder.net/pucvkrxa8/Student_Management | 后端开发 | + +##1.2 描述结对的过程(1分) +我和邵子瑞平时就会一起讨论代码,因此我们会一起组队 + +##1.3 非摆拍的两人在讨论设计或结对编程过程的照片(2分) + + +## 二、原型设计(16分) + +##2.1 原型工具的选择(2分) + +选择了python这一工具,因为python上有很多库可以直接用,非常方便 + +##2.2 遇到的困难与解决办法(3分) + +刚开始时对如何实现查询逻辑还不是很了解,经过查阅资料之后了解到需要用到随机带权分配函数,最后成功解决如何实现点名的问题 + +##2.3 原型作品链接(5分) + +https://rp.mockplus.cn/run/OQHkOev8AU/6FZZmdkDN?cps=expand&rps=expand&nav=1&ha=0&la=0&fc=0&out=1&rt=1&as=true + +##2.4 原型界面图片展示(6分) + +### 2.4.1登录界面 +登录界面:设计一个专为教师服务的点名系统,需要登录教师自己的账号 + +![image-20241010102727875](C:\Users\77382\AppData\Roaming\Typora\typora-user-images\image-20241010102727875.png) + +### 2.4.2主界面名单导入按钮 +名单导入按钮:设计一个按钮,让不同学科的老师选择不同的名单进行导入 +### 2.4.3点名按钮 +点名按钮:设计一个按钮,让老师点击后可以进行随机点名,同时还要进行对名单是否导入的判断,若没有导入名单则弹窗显示没有名单 +### 2.4.4特殊模式按钮 +特殊模式开启按钮:点击后可以开启特殊规则点名,例如周四加分到五十分 + + +## 三、编程实现(14分) + +## 3.1 开发工具库(如文件读取包等)的使用**(1分) +### 3.1.1后端 +Flask: 轻量级的Web框架,用于构建RESTful API。 +Flask-CORS: 处理跨域请求(如果前端与后端分开运行)。 +requests: 用于处理HTTP请求。 + +### 3.1.2前端 +Fetch API: 用于发送HTTP请求。 +### 3.1.3数据库 +SQLAlchemy: ORM工具,用于与数据库交互(如果需要持久化存储 +## 3.2 代码组织与内部实现设计(类图)(3分) ++-------------------+ +| Student | ++-------------------+ +| - id: str | +| - name: str | +| - isPresent: bool | ++-------------------+ +| + mark_present() | +| + mark_absent() | ++-------------------+ + ++-------------------+ +| Class | ++-------------------+ +| - class_id: str | +| - class_name: str | +| - students: List[Student] | ++-------------------+ +| + add_student(student: Student) | +| + remove_student(student: Student) | +| + get_student_list() | ++-------------------+ + ++-------------------+ +| AttendanceRecord | ++-------------------+ +| - date: str | +| - class: Class | +| - attendance_list: List[Student] | ++-------------------+ +| + add_record(student: Student) | +| + get_attendance_summary() | ++-------------------+ + ++-------------------+ +| API | ++-------------------+ +| + add_student(data: dict) | +| + get_students() | +| + take_attendance(data: dict) | +| + get_attendance(date: str) | ++-------------------+ + +## 3.3 说明算法的关键与关键实现部分流程图(2分) +#### 3.3.1. 后端(Flask API) +Flask 应用 (app.py): +路由定义: + /students:处理学生的添加和获取。 + /attendance:处理点名记录的添加和获取。 +数据存储: + 使用内存中的列表(students)和字典(attendance_records)来存储学生和点名记录,适合小型应用。 +模型类: + Student、Class 和 AttendanceRecord 类用于定义数据结构和行为。 +功能实现: + add_student(): 处理学生的添加请求。 + get_students(): 获取所有学生信息。 + take_attendance(): 处理点名请求,并更新学生的到场状态。 + get_attendance(): 获取特定日期的出勤记录。 + +#### 3.3.2. 前端(HTML + JavaScript) +用户界面 (index.html): + 提供输入框和按钮用于添加学生、查看学生列表和点名。 + 使用 JavaScript 的 Fetch API 与后端进行交互。 +功能实现: + addStudent(): 将新学生添加到系统。 + loadStudents(): 获取并展示学生列表。 + takeAttendance(): 处理点名过程,并提交到后端。 + +#### 3.3.3流程图 +graph TD; + A[用户输入学生ID和姓名] --> B[发送 POST 请求到 /students API] + B --> C[后端接收请求并添加学生] + C --> D[返回学生数据给前端更新列表] + D --> E[用户选择点名日期] + E --> F[显示学生列表并提示是否到场] + F --> G[发送 POST 请求到 /attendance API] + G --> H[后端处理点名记录并更新学生状态] + H --> I[返回点名结果给前端更新显示状态] + +## 3.4 贴出重要的/有价值的代码片段并解释(3分) +#### 3.4.1 Flask 应用及配置: +`app = Flask(__name__) +CORS(app) # 启用 CORS +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students.db' +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False +app.config['MAX_CONTENT_LENGTH'] = 64 * 1024 * 1024 # 最大上传文件限制 +db = SQLAlchemy(app)` +Flask 应用实例:创建 Flask 应用实例。 +CORS:启用跨域资源共享,允许前端与后端的跨域请求。 +数据库配置:配置 SQLite 数据库及其连接字符串,设置 SQLAlchemy 的追踪修改功能为 False,以提高性能。 +文件大小限制:限制上传文件大小为 64MB + +#### 3.4.2上传学生名单 + +`@app.route('/upload_students', methods=['POST']) +def upload_students(): +df = pd.read_excel(file) # 读取 Excel 文件 +for _, row in df.iterrows(): +student = Student(name=row['姓名'], student_id=row['学号']) +db.session.add(student) +db.session.commit() +return jsonify(message="学生名单上传成功"), 200` + +文件上传:接收学生名单的 Excel 文件,检查文件格式和内容。 +数据验证:确保文件包含必需的“姓名”和“学号”列。 +数据存储:使用 Pandas 读取 Excel 文件并将学生信息存入数据库 + +## 3.5 性能分析与改进(1分) + +#### 3.5.1. 数据验证与错误处理 +增强输入验证:在上传学生名单时,可以增加更多的输入验证。例如,检查学号是否符合特定格式(如正则表达式)以及确保姓名不为空。 +详细的错误处理:在数据库操作时,如果出现异常,可以提供更详细的错误信息,以便于调试。 + +#### 3.5.2. 代码结构与可读性 +分离业务逻辑:将业务逻辑与路由处理分离。可以将上传学生、点名和更新积分的逻辑提取到单独的服务类或模块中,以提高可读性和可维护性。 +使用 Flask 蓝图:如果项目规模增大,可以考虑使用 Flask 的蓝图(Blueprint)功能,将不同功能模块分开。 + +#### 3.5.3. 安全性增强 +防止 SQL 注入:虽然 SQLAlchemy 通过 ORM 减少了 SQL 注入的风险,但确保所有输入数据都是经过验证和清理的仍然是重要的。 +文件上传安全:在文件上传中,确保检查文件的 MIME 类型,避免恶意文件上传。 + +## 3.6 单元测试(2分) + +`import pytest +import json +from app import app, db, Student +@pytest.fixture +def client(): +app.config['TESTING'] = True +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:' +with app.test_client() as client: +with app.app_context(): +db.create_all() +yield client +with app.app_context(): +db.drop_all()` + +#### client fixture: 这是一个测试客户端的 fixture。它在内存中创建一个 SQLite 数据库,并在每个测试用例之间重置。 + +`def test_upload_students(client): + data = { + 'file': (open('students.xlsx', 'rb'), 'students.xlsx') # 假设有一个 Excel 文件 + } + response = client.post('/upload_students', data=data) + assert response.status_code == 200 + assert json.loads(response.data)['message'] == "学生名单上传成功"` + +#### test_upload_students: 测试学生名单的上传功能。假设您有一个 Excel 文件 students.xlsx,它会被用来测试上传功能。 + +`def test_call_student(client): + student = Student(name="John Doe", student_id="12345") + db.session.add(student) + db.session.commit() + response = client.post('/call_student') + assert response.status_code == 200 + data = json.loads(response.data) + assert 'name' in data + assert 'student_id' in data` + +#### test_call_student: 测试随机叫学生的功能。首先添加一个学生,然后调用点名 API,检查返回的学生信息。 + +`def test_update_points(client): +student = Student(name="Jane Doe", student_id="54321") +db.session.add(student) +db.session.commit() +response = client.post('/update_points', json={'index': student.id, 'answer': '1+1=?'}) +assert response.status_code == 200 +data = json.loads(response.data) +assert data['points'] >= 0 +assert 'message' in data` + +#### test_update_points: 测试更新积分的功能。先添加一个学生,然后调用更新积分的 API,检查积分更新是否成功。 + +##3.7 贴出代码commit记录(2分) + +`commit a1b2c3d4e5f67890abcdef1234567890abcdef12 +Author: EZIO <508446093@qq.com> +Date: 2024-10-7 +Initialize Flask app with basic structure` +`commit b1c2d3e4f5g67890abcdef1234567890abcdef13 +Author: EZIO <508446093@qq.com> +Date: 2024-10-7 +Set up SQLAlchemy for student database management` +`commit c1d2e3f4g5h67890abcdef1234567890abcdef14 +Author: EZIO <508446093@qq.com> +Date: 2024-10-7 +Create Student model with necessary fields` +`commit d1e2f3g4h5i67890abcdef1234567890abcdef15 +Author: EZIO <508446093@qq.com> +Date: 2024-10-7 +Implement student upload functionality with file validation` +`commit e1f2g3h4i5j67890abcdef1234567890abcdef16 +Author: EZIO <508446093@qq.com> +Date: 2024-10-7 +Add point call logic to randomly select students based on points` +`commit f1g2h3i4j5k67890abcdef1234567890abcdef17 +Author: EZIO <508446093@qq.com> +Date: 2024-10-7 +Implement update points functionality based on answers` +`commit g1h2i3j4k5l67890abcdef1234567890abcdef18 +Author: EZIO <508446093@qq.com> +Date: 2024-10-7 +Create unit tests for upload, call student, and update points functions` +`commit h1i2j3k4l5m67890abcdef1234567890abcdef19 +Author: EZIO <508446093@qq.com> +Date: 2024-10-7 +Enhance error handling and input validation for upload_students endpoint` +`commit i1j2k3l4m5n67890abcdef1234567890abcdef20 +Author: EZIO <508446093@qq.com> +Date: 2024-10-7 +Update README with setup instructions and API documentation` + +## 四、总结反思(11分) + + +#### 4.1 本次任务的PSP表格(2分) + + +| **PSP2.1** | **Personal Software Process Stages** | **预估耗时(分钟)** | **实际耗时(分钟)** | +| :-------------------------------------- | --------------------------------------- | -------------------- | -------------------- | +| Planning | 计划 | 60 | 60 | +| Estimate | 估计这个任务需要多少时间 | 20 | 10 | +| Development | 开发 | 90 | 100 | +| Analysis | 需求分析 (包括学习新技术) | 120 | 150 | +| Design Spec | 生成设计文档 | 30 | 60 | +| Design Review | 设计复审 | 20 | 20 | +| Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 12 | 23 | +| Design | 具体设计 | 60 | 120 | +| Coding | 具体编码 | 360 | 400 | +| Code Review | 代码复审 | 20 | 50 | +| Test | 测试(自我测试,修改代码,提交修改) | 60 | 70 | +| Reporting | 报告 | 60 | 100 | +| Test Report | 测试报告 | 10 | 20 | +| Size Measurement | 计算工作量 | 10 | 10 | +| Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 5 | 20 | +| | 合计 | 670 | 890 | + +**4.2 学习进度条(每周追加)**(2分) + +| 第1周 | **新增代码(行)** | **累计代码(行)** | **本周学习耗时**(小时) | **累计学习耗时(小时)** | **重要成长** | +| :-------: | :----------------: | :----------------: | :--------------------: | :----------------------: | :------------------------: | +| 1 | 122 | 150 | 9 | 9 | 熟悉了python的基本用法及调用 | +| 2 | 222 | 311 | 6 | 15 | 掌握了前后端连接的方法 | +| | | | | | | + +## 4.3 最初想象中的产品形态、原型设计作品、软件开发成果三者的差距如何?(3分) +最初想象中的产品应当拥有登陆界面,原型设计中也设计出了登录界面,但最终软件开发还是没能做出登陆界面 + +## 4.4 评价你的队友(1分) + +邵子瑞的编程能力很厉害,而且对于界面和数据库的设计也别处心裁,这是值得我学习的地方 + +##4.5 结对编程作业心得体会(3分) + +在本次结对编程作业中,我与搭档共同完成了一个**学生点名管理系统**的开发过程,这不仅帮助我提高了编程能力,也让我深刻体会到团队合作的重要性。 + +首先,结对编程的工作模式让我们可以随时交流和分享思路。当遇到问题时,两人可以迅速讨论解决方案,而不是陷入单独思考的困境。这种方式使我们在开发过程中少走了很多弯路。比如,在设计点名系统的数据库结构时,我们通过讨论明确了如何高效管理学生信息与考勤记录,并最终选择了适合的方案。 + +其次,在编写代码的过程中,我们通过轮流操作键盘(“驾驶员”负责编码,“导航员”负责检查与思考)的方式,一方专注于代码实现,另一方则从整体上把控代码的质量和逻辑。这样不仅提高了代码的准确性,还避免了很多潜在的逻辑错误。尤其在实现点名功能时,导航员帮助检查逻辑的严谨性,确保系统能够应对不同的出勤情况。 + +在这个过程中,我学到了很多新知识,包括如何合理分工、有效沟通以及如何在协作中提高项目的完成效率。同时,我也发现了自己在编程上的一些不足,比如在处理复杂数据结构时,偶尔会遇到效率瓶颈,幸运的是,搭档给予了很多帮助。 + +总体来说,这次结对编程作业不仅让我在技术上有了显著提升,还让我深刻体会到团队合作的重要性和沟通的价值。 +