软工作业2-个人项目
这个作业属于哪个课程 | 计科34班 |
---|---|
这个作业要求在哪里 | 个人项目 |
这个作业的目标 | 完成个人项目,熟悉个人软件开发流程 |
项目要求
题目:论文查重
设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。
原文示例:今天是星期天,天气晴,今天晚上我要去看电影。
抄袭版示例:今天是周天,天气晴朗,我晚上要去看电影。
要求输入输出采用文件输入输出,规范如下:
从命令行参数给出:论文原文的文件的绝对路径。
从命令行参数给出:抄袭版论文的文件的绝对路径。
从命令行参数给出:输出的答案文件的绝对路径。
我们提供一份样例,课堂上下发,上传到班级群,使用方法是:orig.txt是原文,其他orig_add.txt等均为抄袭版论文。
注意:答案文件中输出的答案为浮点型,精确到小数点后两位
设计过程
一、算法、模块接口设计与实现
1、Jieba库
支持分词模式
- Search模式,用于对用户查询词分词
- Index模式,用于对索引文档分词
特性
- 支持多种分词模式
- 全角统一转成半角
- 用户词典功能
- conf 目录有整理的搜狗细胞词库
- 因为性能原因,最新的快照版本去除词性标注,也希望有更好的 Pull
Request 可以提供该功能。
代码如下
List<SegToken> tokens = segmenter.process(t, JiebaSegmenter.SegMode.INDEX);
StringBuilder strBuffer = new StringBuilder();
for (SegToken token : tokens) {
strBuffer.append(token.word);
}
2、Jaccard相似度算法
概述
- 是一种用于比较样本集之间相似性和差异性的方法。它使用杰卡德系数(Jaccard Index)来衡量相似度
算法原理
- J(A, B) = |A ∩ B| / |A ∪ B|
其中,A和B是两个样本集,|A ∩ B|表示A和B的交集的大小,|A ∪ B|表示A和B的并集的大小。杰卡德系数的值越大,表示样本集之间的相似度越高。
代码如下:
for (int i = 0; i < str1.length(); i++) {
s1.add(str1.charAt(i));//将string里面的元素一个一个按索引放进set集合
}
for (int j = 0; j < str2.length(); j++) {
s2.add(str2.charAt(j));
}
float mergeNum;//并集元素个数
float commonNum = 0;//相同元素个数(交集)
for (Character ch1 : s1) {
for (Character ch2 : s2) {
if (ch1.equals(ch2)) {
commonNum++;
}
}
}
mergeNum = s1.size() + s2.size() - commonNum;
float checkRate=commonNum / mergeNum;
3、流程图
4、具体实现
- 1.在给定的路径中读出文本内容
public static String readText(String path)
使用BufferedReader用于加快读取字符的速度。
- 2、对文本进行分词处理
public static String JiebaTest(String t
- 3、对指定的2个文本进行查重处理
public static float checkText(String str1,String str2)
- 4、将查重结果返回后,在指定的文件中写入论文原文的绝对路径、抄袭版论文的绝对路径、输出的答案的绝对路径、查重率
public static void fileWrite(String[] args,float checkRate)
使用了BufferedWrite类,提供了缓冲,加快IO。
5、运行结果
二、计算模块接口部分的性能改进
1、改进计算模块性能的耗时记录
60min
2、性能分析
性能分析图
方法调用情况
耗时最大的函数
public static String JiebaTest(String t)
点击查看具体代码
public static String JiebaTest(String t){
JiebaSegmenter segmenter = new JiebaSegmenter();
List<SegToken> tokens = segmenter.process(t, JiebaSegmenter.SegMode.INDEX);
StringBuilder strBuffer = new StringBuilder();
for (SegToken token : tokens) {
strBuffer.append(token.word);
}
t=strBuffer.toString();
return t;
}
}
三、计算模块部分单元测试展示
1、测试函数
点击查看代码
public class testText {
Text text= new Text();
@Test
public void Texttest() throws IOException {
String path ="E:\\Code\\IDEA\\Test_software\\src\\resource\\orig.txt";
text.setPath(path);
String t=null;
try {
t=readText(path);
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println(JiebaTest(t));
}
@Test
public void checktest() throws IOException {
String path1 ="E:\\Code\\IDEA\\Test_software\\src\\resource\\orig.txt";
String path2 ="E:\\Code\\IDEA\\Test_software\\src\\resource\\orig_0.8_add.txt";
String str1=readText(path1);
str1=JiebaTest(str1);
String str2=readText(path2);
str2=JiebaTest(str2);
checkText(str1,str2);
}
}
2、测试内容
将样例全部测试一遍,测试具体的功能函数的正确性。
3、测试结果
4、代码覆盖率
四、计算模块部分异常处理
1、输入路径有错误,提示错误
具体代码
点击查看代码
public void checkFile() throws IOException {
String path="E:\\Code\\IDEA\\Test_software\\src\\resource\\orig1.txt";
String str1=readText(path);
}
结果
PSP表
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 45 |
· Estimate | · 估计这个任务需要多少时间 | 60 | 45 |
Development | 开发 | 675 | 855 |
· Analysis | · 需求分析 (包括学习新技术) | 120 | 150 |
· Design Spec | · 生成设计文档 | 60 | 45 |
· Design Review | · 设计复审 | 45 | 45 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 45 | 75 |
· Design | · 具体设计 | 45 | 60 |
· Coding | · 具体编码 | 240 | 300 |
· Code Review | · 代码复审 | 60 | 90 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 90 |
Reporting | 报告 | 150 | 135 |
· Test Repor | · 测试报告 | 75 | 60 |
· Size Measurement | · 计算工作量 | 45 | 30 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 30 | 45 |
· 合计 | 885 | 1035 |
总结
完成这次项目过程中遇到了不少的问题,例如读文件时使用的BufferedReader,如果文件存放位置不是在src文件夹中,系统会报出文件查找失败。还有在提交在github上总是失败,只能在完成代码之后一次性提交。另外,完成此次项目作业让我学会了完成具体软件工程项目的步骤和注意事项,学会单元测试和性能分析。