个人项目
| 这个作业属于哪个课程 | https://edu.cnblogs.com/campus/gdgy/SoftwareEngineeringClassof2023/ |
|---|---|
| 这个作业要求在哪里 | https://edu.cnblogs.com/campus/gdgy/SoftwareEngineeringClassof2023/homework/13324 |
GitHub链接:https://github.com/lzw0312/lzw0312/tree/master
一.PSP表格
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟 | 实际耗时(分钟 |
|---|---|---|---|
| Planning | 计划 | ---- | |
| Estimate | 估计这个任务需要多少时间 | 650 | 590 |
| Development | 开发 | ||
| Analysis | 需求分析 (包括学习新技术) | 60 | 40 |
| Design Spec | 生成设计文档 | 30 | 30 |
| Design Review | 设计复审 | 120 | 140 |
| Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
| Design | 具体设计 | 30 | 30 |
| Coding | 具体编码 | 120 | 100 |
| Code Review | 代码复审 | 100 | 50 |
| Test | 测试(自我测试,修改代码,提交修改) | 120 | 100 |
| Reporting | 报告 | ||
| Test Repor | 测试报告 | 30 | 30 |
| Size Measurement | 计算工作量 | 10 | 10 |
| Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 20 | 50 |
| 合计 | 650 | 590 |
二.计算模块接口的设计与实现
1.项目结构

2.主函数流程图

3.PlagiarismChecker流程图

4.算法关键:文本预处理、分词、余弦相似度
5.独到之处:通过文本预处理方法,能够去除标点符号、特殊字符和多余空格的影响,确保分词和相似度计算的准确性。利用LanLP工具将文本分割成单词或词组,最后通过计算余弦相似度得出重复率
三.性能分析图


由性能分析图可知public static Set
四.计算模块部分单元测试展示
1.测试代码
点击查看代码
private static final String ANSWER_TEST_FILE = "C:\\Users\\Aurora\\Desktop\\answer.txt";
/**
* 测试完全相同的文本
* 预期结果:相似度应为1.0
*/
@Test
public void testIdenticalText() {
String result = PlagiarismChecker.plagiarismChecker("今天是星期天,天气晴,今天晚上我要去看电影。", "今天是星期天,天气晴,今天晚上我要去看电影。", ANSWER_TEST_FILE);
assertTrue("测试完全相同文本,结果因为1.00", Double.parseDouble(result) == 1.00);
}
/**
* 测试未抄袭文本
* 预期结果:结果应小于0.3
*/
@Test
public void testWithoutPlagiarizingText() {
String result = PlagiarismChecker.plagiarismChecker("今天是星期天,天气晴,今天晚上我要去看电影。", "我明天要和你一起吃饭", ANSWER_TEST_FILE);
assertTrue("测试未抄袭文本,结果应小于0.3", Double.parseDouble(result) < 0.5);
}
/**
* 测试原文本为空
* 预期结果:返回“”
*/
@Test
public void testEmptyOrignalText() {
String result = PlagiarismChecker.plagiarismChecker("", "我明天要和你一起吃饭", ANSWER_TEST_FILE);
assertTrue("测试原文本为空,结果应为空字符", result.equals(""));
}
/**
* 测试抄袭文本为空
* 预期结果:返回“”
*/
@Test
public void testEmptyCopiedText() {
String result = PlagiarismChecker.plagiarismChecker("今天是星期天,天气晴,今天晚上我要去看电影。", "", ANSWER_TEST_FILE);
assertTrue("测试抄袭文本为空,结果应为空字符", result.equals(""));
}
/**
* 测试原文本和抄袭文本都为空
* 预期结果:返回“”
*/
@Test
public void testTextBothEmpty() {
String result = PlagiarismChecker.plagiarismChecker("", "", ANSWER_TEST_FILE);
assertTrue("测试原文本和抄袭文本都为空,结果应为空字符", result.equals(""));
}
/**
* 测试特殊符号
* 预期结果:特殊符号不影响结果,结果应为0.00
*/
@Test
public void testSpecialSymbol() {
String result = PlagiarismChecker.plagiarismChecker(",.!英语", ",.!语文", ANSWER_TEST_FILE);
assertTrue("测试原文本和抄袭文本都为空,结果应为空字符", Double.parseDouble(result) == 0.00);
}
/**
* 测试包含数字的文本
* 预期结果:数字不影响结果
*/
@Test
public void testNumbers() {
String result = PlagiarismChecker.plagiarismChecker("今天是2023年10月1日", "今天是 2023 年 10 月 1 日", ANSWER_TEST_FILE);
Assert.assertTrue("测试数字,结果应为1.0", Double.parseDouble(result) == 1.0);
}
/**
* 测试短抄袭文本
* 预期结果:结果应大于0.8
*/
@Test
public void testPlagiarizingText() {
String result = PlagiarismChecker.plagiarismChecker("今天是星期天,天气晴,今天晚上我要去看电影。", "今天是周天,天气晴朗,我晚上要去看电影。", ANSWER_TEST_FILE);
assertTrue("测试未抄袭文本,结果应大于0.8", Double.parseDouble(result) > 0.80);
}
/**
* 测试长抄袭文本
* 预期结果:结果应大于0.5
*/
@Test
public void testLongPlagiarizingText() throws InterruptedException {
String result = PlagiarismChecker.plagiarismChecker("今天是星期天,天气晴朗,我和家人一起去了公园。公园里有很多人,有的在跑步,有的在打羽毛球,还有的在放风筝。我们找了一个安静的地方坐下,享受着阳光和微风。孩子们在草地上嬉戏玩耍,笑声不断。中午我们在公园里的餐厅吃了午饭,饭后继续散步,直到傍晚才回家。这一天过得非常愉快,希望下次还能来",
"今天是周日,天气非常好,我和家人一起去逛公园。公园里聚集了不少人,有人在慢跑,有人在打羽毛球,还有人在放风筝。我们选择了一处宁静的地方休息,尽情享受阳光与轻柔的微风。孩子们在草坪上欢快地奔跑,充满了欢声笑语。中午时分,我们在公园内的餐馆享用了午餐,之后又漫步了一会儿,直到傍晚才离开。这真是美好的一天,期待下次再来",
ANSWER_TEST_FILE);
assertTrue("测试未抄袭文本,结果应大于0.8", Double.parseDouble(result) >= 0.50);
}
/**
* 测试文本长度差异较大
* 预期结果:算法应能正确处理长度差异较大的文本
*/
@Test
public void testLengthDifference() {
String result = PlagiarismChecker.plagiarismChecker("今天是星期天,天气晴,今天晚上我要去看电影。",
"今天是周日,天气非常好,我和家人一起去逛公园。公园里聚集了不少人,有人在慢跑,有人在打羽毛球,还有人在放风筝。我们选择了一处宁静的地方休息,尽情享受阳光与轻柔的微风。孩子们在草坪上欢快地奔跑,充满了欢声笑语。中午时分,我们在公园内的餐馆享用了午餐,之后又漫步了一会儿,直到傍晚才离开。这真是美好的一天,期待下次再来",
ANSWER_TEST_FILE);
assertTrue("测试未抄袭文本,结果应小于于0.5", Double.parseDouble(result) <= 0.50);
}
2.测试覆盖率截图

五.计算模块部分异常处理说明
1.异常代码
点击查看代码
public class ExceptionTest {
/**
* 测试输入文件数目的异常情况
*/
@Test
public void main_InvalidNumberOfArguments_ShouldPrintErrorMessage() {
String[] args = {"file1.txt", "file2.txt"};
System.setOut(new java.io.PrintStream(new java.io.ByteArrayOutputStream()));
assertThrows(IllegalArgumentException.class, () -> {
Main.main(args);
});
}
/**
* 测试读入文件的异常情况
*/
@Test
public void FileUtil_readFile_ShouldPrintErrorMessage() {
System.setOut(new java.io.PrintStream(new java.io.ByteArrayOutputStream()));
assertThrows(FileNotFoundException.class, () -> {
FileUtil.readFile("file1.txt");
});
}
/**
* 测试写入文件的异常情况
*/
@Test
public void FileUtil_writeFile_ShouldPrintErrorMessage() {
String[] args = {"C:\\Users\\Aurora\\Desktop\\orig.txt",
"C:\\Users\\Aurora\\Desktop\\orig_0.8_add.txt" ,
"file2.txt"};
System.setOut(new java.io.PrintStream(new java.io.ByteArrayOutputStream()));
assertThrows(FileNotFoundException.class, () -> {
Main.main(args);
});
}
}
2.设计目标
2.1 IllegalArgumentException:输入参数个数不正确时抛出
2.2 FileNotFoundException:当文件不存在时抛出
2.3 RuntimeException:IO操作出错时抛出
浙公网安备 33010602011771号