基于Python和Java混合编程实现的小学生数学口算题卡定制练习题
1. 总体要求
- 综合运用软件工程的思想,协同完成一个软件项目的开发,掌软件工程相关的技术和方法;
- 组成小组进行选题,通过调研完成项目的需求分析,并详细说明小组成员的分工、项目的时间管理等方面。
- 根据需求分析进行总体设计、详细设计、编码与测试等。
2. 基本内容
根据给出的题目任选一题,自行组队,设计与开发中软件过程必须包括:
- 问题概述、需求分析:正确使用相关工具和方法说明所开发软件的问题定义和需求分析,比如 NABCD 模型,Microsoft Visio,StarUML 等工具 (20%);
- 原型系统设计、概要设计、详细设计:主要说明所开发软件的架构、数据结构及主要算法设计,比如墨刀等工具(35%);
- 编码与测试:编码规范,运用码云等平台进行版本管理,设计测试计划和测试用例(30%);
- 功能创新:与众不同、特别吸引用户的创新(10%);
- 用户反馈:包括用户的使用记录,照片,视频等(5%)。
3. 问题定义
3.1 项目背景与意义
3.1.1 项目需求(Need)
家长在辅导上小学的孩子学习数学时,通常需要很大的题量来熟悉和掌握四则运算。但是作业册的题量不一定能够满足需求,而且题目的难度、侧重点会随年级提升有所改变,所以会导致用户出题的效率变得很低。用户希望通过一个可靠且方便的平台能够为儿童定制练习题;
3.1.2 实现方法(Approach)
平台通过难度地每次随机生成 10 道四则运算题目帮助各个年级的孩子练习和掌握数学运算;平台通过计时测试的功能帮助家长发布测验,检测孩子学习进度;平台通过对测验结果进行数据分析,产生反馈信息,让用户实时发现对应的不足之处;平台还有用户数据的排名情况,可以和小伙伴比一比谁做的题更多,准确率更大,为做数学题增加一丝乐趣。
3.1.3 好处(Benefit)
用户每次做题时都会有计时器功能,可以模拟真实场景下的情况;用户可以通过平台快速地为孩子定制数学运算练习题,也可以通过每次的反馈信息找到短板进行针对性训练;用户可以通过测验功能为孩子布置作业,测验成绩优秀的奖励机制也可以激励孩子努力学习;
3.1.4 功能创新(亮点)
平台提供用户更加精准的的注册方式——手机号注册。因此,用户注册时需要逐步输入用户名、图片验证码、短信验证码等来保证账号的安全。当注册完成后,用户输入自己的账号/手机号加上密码即可登录。
每次测试会有得分统计与错题统计,用户/家长可以根据自己的做题情况得到反馈,从而接下来可以根据该板块进行强化练习。
测试结束后,家长可以根据需要将错题下载到客户端,进而可以打印成纸质版的习题方便孩子提升自己。现在已经有了许多四则运算生成的网站,但是功能都比较局限:
3.2 项目基本目标
我们设计的项目的基础目标是满足所有小学生不同程度的日常口算学习的需求,该项目主要包含了两个重要模块。
第一是用户注册模块。在注册模块内,用户注册时需要逐步输入用户名、图片验证码、短信验证码等来保证账号的安全。当注册完成后,用户输入自己的账号/手机号加上密码即可登录。
第二个是测试模块。在主页面内,用户点击口算题卡即可进入测试模块。用户选择好年级后系统会一次性的相应出 10 道题目,并同时开始计时。用户作答完毕后可以提交页面,然后系统给出此次习题的得分情况。
在分年级选择题目类型中,我们定义如下的环境:
- 一二年级:两个 100 以内操作数的加减法:a+b
- 三四年级:两个 100 以内操作数的加减乘除法:a*b
- 五六年级:三个 100 以内操作数的加减乘除法:a+b/c
- 三个 30 以内操作数的带括号的加减乘除法:(a-b)*c,a/(b-c)
4. 需求分析
4.1 E-R 图、数据流图等
4.1.1 E-R 图
我们有“商店”和“顾客”两个实体。“商店”即我们的答题网站——爱 Math 在线答题网站;“顾客”即为网站的用户,主要群体为一年级到六年级的小学生。
“商店”的属性有:店名(网站名)、地址(网址)、店面装修(前端)、仓库与物流(数据库及相应的数据交互);“顾客”的属性有:用户名(身份标识)、用户密码、手机号、年龄和年级。
网站可以有多个用户访问。用户每次登录网站、选择年级后进行线上数学口算题练习,每次练习都会更新“分数”和“排名”两个属性。同时,用户可以取走练习结果,即通过我们的“打印”功能。
综合以上分析,可作出 ER 图如图 2.1 所示:
图 2.1 ER 图
4.1.2 数据流图
从数据的角度分析该系统,可作出数据流图如图 2.2 所示:
图 2-2 数据流图
4.2 用例图
图 2-3 用例图
4.3 原型系统设计
4.3.1 设计工具
整个系统的设计是在前端和后端的相互配合下完成的。前端设计所用的核心“工具”为 HTML 和 CSS,其中 HTML 用于控制网页的结构,CSS 用于控制网页的外观,我们也在不断对网页外观的求简求美的过程学习了新的知识;后端设计所用的核心“工具”为 Java,外加一些 JavaScript,用于实现与服务器的交互并控制网页的行为实现一些特定功能。
4.3.2 设计思路
基于 Web 开发,设计相应的页面,主要有:登录页面——注册页面——个人主页——个人信息页面——年级选择页面——做题页面——查看排名。
4.3.3 设计成果
基于 Web 开发,实现效果如下:
登录页面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jJZ1CCr3-1642768096151)(./photo/image-20220121184252844.png)]
注册页面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jsMlEMrx-1642768096152)(./photo/image-20220121184302980.png)]
个人主页
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gOiKPPo8-1642768096152)(./photo/image-20220121184310025.png)]
个人信息界面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mtaLapfX-1642768096152)(./photo/image-20220121184320270.png)]
做题界面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZKznXpFw-1642768096153)(./photo/image-20220121184327423.png)]
查看排名
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EO6E21Hp-1642768096153)(./photo/image-20220121184334295.png)]
5. 概要设计和详细设计
5.1 系统结构
整个系统结构如下图所示:
图 3-1:系统结构
1)登录:
登录流程为输入用户名,输入密码,点击登录按钮这几个步骤,若没有帐号可以选择点击注册按钮立即进入注册界面;后台负责在用户名和密码输入之后进行数据库查询校验,并将相应信息返回给网页。
2)注册:
注册流程为输入相应的用户信息,设置密码,确认密码,点击注册这几个步骤;后台负责在用户名输入之后查询数据库看用户名是否重复以及检查两次密码输入是否一致,并将相应信息返回给网页。
3)题目:
题目流程为选择年级后进入做题界面,在此可以选择在线做题,也可以选择打印题目和答案(爱护视力);若选择在线做题,将页面上的 10 个题目做完并提交后,会显示耗时以及得分情况,如果想要继续做题可以点击换卷按钮,不想继续做题就可以点击回到主页按钮。
4)排名:
排名模块主要就是根据注册用户的累计得分来计算排名;后台负责数据库查询并将信息传给网页展示。
5)个人信息:
个人信息模块主要就是展示个人信息以及提供退出登陆的功能,如果想要退出登录,点击相应按钮即可;后台负责数据库查询并将信息传给页面展示以及提供退出当前账号并返回登陆页面的功能。
5.2 类图&MVC 设计模式
该系统基于 JavaWeb 编程,采用的是 MVC 设计模式。
- JavaWeb 基础:
servlet:Java 类,是一种用来扩展 Web 服务器功能的组件规范,属于服务端程序,主要功能在于交互式地浏览和修改数据,生成动态 Web 内容。
在具体实现时,一般与网页交互时需要继承 HttpServlet 类,它是一个抽象类,在继承后对其的一些方法如 doPost,doGet 等按需重写即可,下面以 LoginServlet 类为例来看类图关系,如下图所示:
图 3-2:类图举例 LoginServlet
由上图可知:GenericServlet 类实现了三个接口 ServletConfig,Servlet 和 Serializable,HttpServlet 类是对 GenericServlet 类的继承,LoginServlet 类(自己实现)继承了 HttpServlet 类并且重写了 doPost 方法,其余类均大同小异。
JSP:Java 类,是一种服务器端动态页面技术的组件规范。
-
MVC 设计模式:
MVC 模式是基于代码分层的思想,将代码按照功能分成三层,即模型层(Model),显示层(View),控制层(Controller)。
-
Model:代表业务数据;
-
View:对 Model 进行可视化;
-
Controller:作用于 Model 和 View 上,控制数据流向 Model 对象,在数据变化时更新 View,使 Model 与 View 分离;
-
具体关系如下图所示:
图 3-3:MVC 设计模式
在该项目中,MVC 模式的具体实现如下图所示:
图 3-4:MVC 设计模式具体实现
Model:
- service 包中包含了几个后台功能的接口以及一个 Impl 包,这个包里是这几个接口的具体实现类,该包中主要实现具体的业务逻辑,如登录,登出,注册等等;
- repository 包中包含了一个与用户数据库交互有关的接口以及它的具体实现类,该包中主要实现的是与数据库交互的逻辑;
- entity 包中是两个实体类 User 和 Questions,是业务操作的两个核心数据对象;
- utils 包中包含了数据库操作要用到的工具,JDBC 数据库线程池的实现逻辑。
View:
这里是多个 JSP 文件,JSP 文件是 HTML,CSS,JavaScript 以及 Java 代码综合的文件,用于网页展示,实质上是一个 servlet 的高级封装,是前后端交互的枢纽,用于网页的信息展示以及后台操作的连接。
Controller:
controller 包中是几个 HttpServlet 类的子类,处理的是与页面交互的业户逻辑,即 B/S 开发模式中的 request 与 response,用来处理网页发来的 URL 请求,然后做相应的 response 处理,具体处理时会调用一些 Model 里的对象,这正是 MVC 设计模式的体现。
总而言之,在项目当中,具体的处理流程如下图所示:
图 3-5:Web 具体处理流程
5.3 关键数据结构定义
该项目中需要处理的关键数据被封装为两个类,User 类和 Question 类。User 类用来做用户信息处理,Question 类用来做题目相关的业务逻辑。以下为两个类的具体设计:
User 类:
成员变量:
private String userName; //用户姓名
private String userPwd; //用户密码
private Integer userAge; //用户年龄
private Integer userScores; //用户得分
方法:
public User(String username, String userPwd, Integer userAge, Integer userScores);//构造函数
public String getUserName();//得到用户名
public String getUserScores();//得到用户得分
Question 类:
成员变量:
private double operand_1;
private double operand_2;
private double operand_3; //三个操作数
private String operator_1;
private String operator_2;
private String operator_3;
private String operator_4; //四个操作符
private int grade; //年级
private int type; //题目类型
private double ans; //题目答案
private String str; //题目的字符串
方法:
public Question(double operand_1, double operand_2, double operand_3,String operator_1, String operator_2, String operator_3, String operator_4, int type);//构造器
public double getAnswer();//得到答案
public String getStr();//得到题目的字符串
5.4 关键算法设计
系统总体设计如下图所示:
图 3-6:系统总体流程
解释出题算法:
Question 类:
首先定义一个 Question 类用于存储一道题目的相关信息:
根据年级划分出题难度。一二年级为低难度,三四年级为中等难度,五六年级为高难度。低难度的题目涉及两个整数的加减法,中等难度的题目涉及两个整数的加减乘除法,高难度的题目涉及三个整数的加减乘除运算,可能带括号。
所以按题目的表达式划分一共有五种类型,分别是:
- 低年级的:a +/- b
- 中年级的:a +/-/×/÷b
- 高年级的:a×b÷c
- 高年级的:(a+/-b)×/÷c
- 高年级的:a×/÷(b+/-c)
由上可知最长的题目的字符串一共包含 3 个操作数、4 个操作符,且根据难度不同操作数和操作符的位置也不一样。所以要定义一个 Question 类存储一个题目的所有信息,这个类中有一个实例字段 type 标识题目的难度,有一个字符串字段存储题目的字符串(根据 type 的值和 3 个操作数以及 4 个操作符得到规范格式)。该类提供了 public double getAnswer()方法获取该题目的答案。如图是 Question 类的成员变量:
图 3-7:Question 类的成员变量
Question 类的构造器声明如图所示:
图 3-8:Question 类的构造器
由 Question 类中的一些成员变量可以得到题目的字符串 str:
图 3-9:Question 类的 str 变量的生成
Question 类中提供了 getAnswer 方法,可以根据 type 以及操作数和操作符得到该算数题目的答案。
生成题目的算法:
设计根据年级随机生成题目的算法,返回值是一个 Question 类的 List。定义一个类实现 QuestionsService 接口。
对于一个用户,每次随机生成 10 道题目,所以循环 10 次,每次循环得到得到一个 Question 类的对象,加到 Question 对象的 List 中,所以一次循环就要得到上图中的三个操作数 oprand、四个操作运算符 operator 和题目类型 type 这几个确定的值,并调用 Question 的构造器进行实例化,构造器的声明如上上图所示。
循环体中根据年级 grade 生成题目,自定义三个操作数分别为 a、b、c,四个操作符为:ch1、ch2、ch3、ch4,类型为 type:
如果 grade 为 1 或 2,得到诸如 a+b 形式的题目,具体到实对象。操作数 a 和 b 都是通过:rand.nextInt(100) + 1 得到的,操作符 ch1 也是通过 rand.nextInt(4)得到的,如果生成的随机数为 0 或 1,则 ch1 为‘+’。如果生成的随机数为 2 或 3,ch1 为‘-’,type=1。创建对象为 new Question(operand_1 : a, operand_2 : b, operand_3 : 0, operator_1 : ch1, operator_2 : null,operator_3 : null,operator_4 : null, type : 1)
如果 grade 为 3 或 4,得到形如 a×b 形式的题目,具体到实对象。操作数 a 和 b 都是通过:rand.nextInt(100) + 1 得到的,操作符 ch1 也是通过 rand.nextInt(4)得到的,如果生成的随机数为 0,则 ch1 为‘+’。如果生成的随机数为 2,ch1 为‘-’,如果为 3,ch1 为‘×’,如果为 4,ch1 为‘÷’,type=1。创建对象为 new Question(operand_1 : a, operand_2 : b, operand_3 : 0, operator_1 : ch1, operator_2 : null,operator_3 : null,operator_4 : null, type : 2)
如图所示为中和低年级的题目生成的流程图:
图 3-10:低年级和中年级的题目生成流程
对于高年级,分为三种情况:
type3:形如 a + b / c;生成各操作数和操作符后调用 Question 类的构造器:new Question(operand_1 : a, operand_2 : b, operand_3 : c, operator_1 : ch1, operator_2 : ch2,operator_3 : null,operator_4 : null, type : 3)
type4:形如(a+b)/c;生成各操作数和操作符后调用 Question 类的构造器:new Question(operand_1 : a, operand_2 : b, operand_3 : c, operator_1 : “(”, operator_2 : ch2,operator_3 : “)”,operator_4 : ch4, type : 4)
type5:形如 a/(b+c);生成各操作数和操作符后调用 Question 类的构造器:new Question(operand_1 : a, operand_2 : b, operand_3 : c, operator_1 : ch1, operator_2 : “(”,operator_3 : ch3,operator_4 : “)”, type : 5)
如图所示为高年级的题目生成流程:
图 3-11:高年级的题目生成流程
这样通过每个用户的年级,就可以得到一个 Question 对象的 List,每个 List 有 10 个 Question 对象。通过 Question 对象的 str 成员可以得到题目的字符串。
5.5 数据管理说明
管理数据库用到的是 MySQL 数据库,维护了一张表,用来记录用户信息,如图所示:
图 3-12:MySQL 数据库 tb_user 表
在项目里用来与数据库交互的工具为 JDBC,数据库连接池;
1)JDBC:
JDBC 全称为 Java DataBase Connectivity,是一个独立于特定数据库的管理系统。它的接口包括两个层面,一是面向应用的 API,供程序员调用;二是面向数据库的 API,供厂商开发数据库的驱动程序。而在项目中 Java 应用只需用到第一个层面即可。
在项目的具体实现中,JDBC 的使用流程如下图所示:
图 3-13:JDBC 使用流程
2)数据库连接池:
由上可知,每一次与数据库的交互都需要获取连接,在执行完 SQL 语句之后断开连接,这种方式会造成资源的浪费,由此就有了数据库连接池的技术。
基本思想就是为数据库建立一个缓冲池,预先向缓冲池中放入一定数量的连接对象,当需要获取数据库连接的时候,只需要从缓冲池中取出一个对象,用完之后再放回到缓冲池中,供下次请求使用,做到了资源的重复利用,允许程序重复使用多个现有的数据库连接对象,而不需要重新创建。当数据库连接池中没有空闲的连接时,新的请求就会进入等待队列,等待其他线程释放连接。
具体在项目使用中引用第三方工具 C3P0,该工具实现了 javax.sql.DataSource 这一 Java 官方提供的用于 JDBC 数据库连接池的接口。
6. 实现与测试
6.1 实现环境
硬件配置:
-
处理器: Intel® Core™ i7-8550U CPU @ 1.80GHz 1.99GHz
-
RAM: 8.00GB
-
系统类型: 64 位操作系统,基于 x64 的处理器
编程开发环境:
- IntelliJ IDEA 2017.3.5 x64
- pycharm community 版本
- Visual Studio Code
- HBulider
6.2 关键函数说明
- controller package 中的类均为 HttpServlet 类的继承,均按需重写了 doPost 或 doGet 方法;
- repository package 中为与数据库交互有关的函数:
public User login(String username, String password);//登录
public User registCheck(String username);//注册检查
public void insertUser(String username, String password, Integer age);//插入用户
public List<User> rank();//排名
public void updateScores(String username, Integer addScores);//更新用户得分
- service package 中为具体的业务逻辑实现:
public User login(String username, String password);//登录
public List<Question> getQuestions(int grade);//得到题目列表
public void buildFile(String path, List<Question> questions) throws IOException;//构造题目文件
public void updateScores(String userName, Integer addScores);//更新用户得分
public List<User> rank();//排名
public User registCheck(String username);//注册检查
public void insertUser(String username, String password, Integer age);//插入用户
- utils package 中存放的是数据库交互要用的工具类:
public static Connection getConnection();//获取连接
public static void release(Connection connection, Statement statement, ResultSet resultSet);//释放连接
大致函数调用关系如下图所示:
图 4-2:函数调用关系
6.3 测试计划和测试用例
测试分为白盒测试和黑盒测试。白盒测试的常见方法包括:逻辑覆盖法、路径测试法。黑盒测试的内容包括 Alpha/Beta 测试、菜单、帮助测试、发行测试、回归测试、效能测试、负载/压力测试。黑盒测试法是根据被测程序功能来进行测试,也称为功能测试,有 4 种常用技术:等价分类法、边界值分析法、错误猜测法、因果图法。测试计划分为对流程的测试和对功能的测试。
注册:用户依次输入手机号,如果输入的是有效手机号,则输入图片验证码,
图 4-3 注册流程
如果图片验证码输入正确,则点击获取验证码操作后会向手机号发送短信验证码,输入验证码后输入密码,即注册完成。
图 4-4 给注册的手机号发短信
1)登录
故意输入错误密码:
图 4-5:登陆时故意输入错误密码
登陆成功进入主页:
图 4-6:登陆成功进入主页
2)注册
用户名重复:
图 4-7:注册用户名重复
确认密码与密码不一致:
图 4-8:注册确认密码与密码不一致
3)查看排名
图 4-9:排名
4)查看个人信息
图 4-10:个人信息
5)做题
选择年级
图 4-11:选择年级
下载题目
图 4-12:题目下载
在线做题
图 4-13:做题后显示耗时和得分
图 4-14:点击换卷后更新的页面
6.4 结果分析
由 4.3 可知,对于操作流程而言,网站基本实现主页、选择题目、生成题目等界面的转换。在功能实现方面,对于不同难度可以生成相应题目,还可以选择生成题目的数量。实现了特色功能方面上,用户手机号注册、打印功能、计时功能均基本实现,题目被下载到本地,可以修改格式。或者直接在线打印,预览打印效果。此外,新增换卷功能,随机生成一套新的题目。
综上,产品很好的实现了各模块的功能。