结对作业

结对编程
| 这个作业属于哪个课程 | 班级的链接 | 
|---|---|
| 这个作业要求在哪里 | 作业要求的链接 | 
| 这个作业的目标 | 实现一个自动生成小学四则运算题目的命令行程序(也可以用图像界面,具有相似功能) | 
| github | 代码仓库 | 
|---|---|
| 结对成员 | 3118005424谭宗麟,3118005419彭凯金 | 
PSP表格
| PSP2.1 | Personal Software Process Stages | 预估耗时(小时) | 实际耗时(小时) | 
|---|---|---|---|
| Planning | 计划 | -- | -- | 
| · Estimate | 估计这个任务需要多少时间 | 1 | 1.5 | 
| ·Development | 开发 | -- | -- | 
| · Analysis | 需求分析 (包括学习新技术) | 48 | 50 | 
| · Design Spec | 生成设计文档 | 1 | 1.5 | 
| · Design Review | 设计复审 | 1 | 1 | 
| · Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 0.5 | 0.5 | 
| · Design | 具体设计 | 4 | 4.5 | 
| · Coding | 具体编码 | 8 | 8 | 
| · Code Review | 代码复审 | 1 | 2 | 
| · Test | 测试(自我测试,修改代码,提交修改) | 2 | 4 | 
| ·Reporting | 报告 | 2 | 3 | 
| · Test Repor | 测试报告 | 1 | 1 | 
| · Size Measurement | 计算工作量 | 0.5 | 1 | 
| · Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 1 | 1.5 | 
| 合计 | 71 | 79.5 | 
效能分析
题目生成
CPU性能

内存性能

时间性能

实测结果

设计实现过程
设计流程图

类的关系
| 类名 | 说明 | 
|---|---|
| JarMain | 主类 | 
| yuefen | 约分静态工具类 | 
| daifenshu | 带分数静态工具类(化为带分数) | 
| application | 启动类 | 
| baifenshu | 静态工具类(计算两数相除百分比) | 
| Configure | 配置swagger2 | 

根据输入参数生成题目文件与参考答案文件
输入范围和题目数量,生成包含题目和答案(txt文件)的zip压缩文件。注意txt是序号和.开头的,其后才是内容。
由于本项目是部署到服务器上的,所以将上述题目和答案文件输出到HTTP请求的响应流response里,这里不再赘述。
设计思路
- 借助讨论的排列组合的思想,我建立了两个数组,存放内容如下:
 
int number01 = Integer.parseInt(number);//题目数量
int fanwei01  = Integer.parseInt(fanwei);//生成题目数值范围
List<Integer> num1lsit = new ArrayList<>();
List<Integer> num2lsit = new ArrayList<>();
List<String> resultlist = new ArrayList<>();
Random random = new Random();
//生成运算数的时候可以顺序生成,等要显示的时候再根据序号随机抽取相同序号的组.
for(int i = 1;i < fanwei01;i++){//直接不要0计算,甚至不要重复
    for(int j = 1;j < i;j++){
        num1lsit.add(new Integer(i));
        num2lsit.add(new Integer(j));
    }
}
经过如上代码,同一个序号的元素,数组num2list始终比num1list小(不会相等),这就保证了不会出现项目要求的需求6中提到
任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目
的情况(两个运算符始终是前面大后面小你告诉我怎么重复?是吧~)。
举个例子就是,给范围10,那么数组1和2内内容依次是:
(10,1),(10,2),(10,3),(10,4),(10,5),(10,6),(10,7),(10,8),(10,9)。
然后对这两个数组之间加上+ - x /四个运算符号,这就组成了题目,最后题目装入字符串类型的题目数组,对应答案装入答案数组:
//以下是部分for()循环内容
Exercises.add(num1lsit.get(i)+" + "+num2lsit.get(i));
resultlist.add(String.valueOf(num1lsit.get(i)+num2lsit.get(i)));
以上循环次数起初是按照本算法尽力生成的最多题目数量和给的题目数量参数中的较小值作为循环装入次数的,但是后面测试时发现如果输入的要我生成的题目数量过大(比如一百万),会造成服务器一直计算而出不了结果(15分钟以上),所以在生成的时候就加入逻辑,时刻检测生成的题目数量是否已经达到了输入要求的题目数量,一旦达到就停止生成。
- 
仅仅生成范围内正整数之间的题目还不足以支持生成一万道题目,所以得加上分数,项目要求分数要么以带分数形式出现,要么以真分数形式出现,所以为了便于展示,写了个将假分数化成带分数的方法public static String jiahuadai(String jiafenshu),具体作用是假分数化成带分数,如20/3化成6'2/3 (英文单引号'),自带判断分数是否是假分数,真分数原样输出。
分数的分子和分母也是借助上述两个初始数组生成的,生成分数题目的部分代码如下:
 
Exercises.add(daifenshu.jiahuadai(yuefen.reduce(num1lsit.get(i),num2lsit.get(i)))+" x "+ daifenshu.jiahuadai( yuefen.reduce (num1lsit.get(j),num2lsit.get(j))));  
resultlist.add(daifenshu.jiahuadai(yuefen.reduce(num1lsit.get(i)*num1lsit.get(j),num2lsit.get(i)*num2lsit.get(j))));//分子与分子、分母与分母相乘后约分
加上分数可以支持范围10的时候生成1万多道题目,如果比10更大的范围,可以生成超过1万道多得多的题目。
代码说明
本算法核心代码就是JarMain类,类如其名,也是一个接口类。
剩余的类如public static String reduce(Integer fenzi,Integer fenmu)、public static String jiahuadai(String jiafenshu)等都是静态工具类,用于将分数化成带分数和约分所用。
代码段的解释在代码的注释都有所解释,大体流程是生成数组并组成题目并计算出相应答案,然后将内容写入文本新建的txt文件中,最后输出。
单元测试
这里简单模拟了下JarMain的运行,只要:
public class test {
    JarMain  a = new JarMain();
    @Test
    public void testsizeyunsuan() throws Exception {
        String b = a.sizeyunsuan(null,"10","100");
        if(b != null){
            return;
        }
        else{
            throw new Exception();
        }
    }
}
测试经测试是没有抛出异常的,说明正常输出了文件流。
异常处理
<script type="text/javascript">
        function check() {
            var number = document.getElementById("number").value;
            var resultLimit = document.getElementById("fanwei").value;
            if (number == null || number == "" || resultLimit == null || resultLimit == "") {
                alert("禁止输入空值");
                return false;
            }
            if (number == '0' || resultLimit == '0') {
                alert("禁止输入0")
                return false;
            }
            if (isNaN(number) || isNaN(resultLimit)) {
                alert("请输入数字");
                return false;
            }
            return true;
        }
    </script>
<form action="http://47.115.185.6:81/size/yunsuan" method="post" class="formself" onsubmit="return check()">
            <h1>GERENATOR</h1>
            <input type="text" id="fanwei" name="fanwei" placeholder="范围" class="inp">
            <input type="text" id="number" name="number" placeholder="题目数量" class="inp">
            <input type="submit" name="" value="bingo" class="bingo">
            <div class="wave1"></div>
            <div class="wave2"></div>
            <div class="wave3"></div>
        </form>
输入为空异常提示
输入0时异常提示
作业地址
操作演示
操作过程

下载文件目录

项目小结
3118005419彭凯金:
测试很重要!测试很重要!测试很重要!没测试前我还没仔细看项目要求,想到要测试我才跑去看项目要求的,于是发现并修改了许多bug。
结对感受:
分工相比个人全栈开发的好处是前后端分离,后台完全不用管前端的事情,这对于我这个前端完全小白的菜鸡而言非常友好,我个人更加喜欢前后端分离的开发方式了。但是对于后台的需求,我的结对伙伴也非常努力学习并帮助我实现,因此也能够在规定时间内完成作业。
3118005424谭宗麟:
前端页面实现得不够好,改进方向应该使用Ajax来提交表单数据与后台交互,不必在提交表单后再次加载页面。同时做了输入的异常判断处理,向用户进行反馈异常错误信息。
结对感受:
分工我主要负责前端页面编写与后端的交互,彭凯金主要实现后台的题目生成算法。同时易于沟通,在我不清楚后台核心算法原理同时耐心举例解答。在遇到问题时能够很快达成共识,解决问题。
                    
                
                
            
        
浙公网安备 33010602011771号