個人項目


個人項目

軟件工程 網工1934鏈接
作業要求:
1.在Github倉庫中新建一個學號為名的文件夾
2.在開始實現程序之前,在PSP表格記錄下在程序開發各個步驟耗費時間,實現程序后,在PSP表格記錄各個模塊上實際花費時間
3.語言不限,實現程序后將代碼發布到Github倉庫的realease中

4.提交的代碼要求經過Code Quality Analysis工具分析並消除所有警告
5.完成項目首個版本之后,使用性能分析工具Studio Profiling Tools找出代碼性能瓶頸
6.使用Github來管理源代碼和測試用例,代碼有進展即簽入Github
7.使用單元測試對項目進行測試,並使用插件查看測試分支覆蓋率等指標
作業要求鏈接
作業目標:
完成論文查重項目的實現后進行測試並按以上要求使用Github進行版本發布及源碼和測試用例管理

個人作業github鏈接

一.PSP表格

PSP2.1 Personal Software Process Stages 預估耗時(分鍾) 實際耗時(分鍾)
Planning 計划
· Estimate · 估計這個任務需要多少時間 405 340
Development 開發
· Analysis · 需求分析 (包括學習新技術) 100 120
· Design Spec · 生成設計文檔 30 30
· Design Review · 設計復審 10 10
· Coding Standard · 代碼規范 (為目前的開發制定合適的規范) 10 10
· Design · 具體設計 40 40
· Coding · 具體編碼 80 40
· Code Review · 代碼復審 60 20
· Test · 測試(自我測試,修改代碼,提交修改) 20 15
Reporting 報告
· Test Repor · 測試報告 30 30
· Size Measurement · 計算工作量 10 10
· Postmortem & Process Improvement Plan · 事后總結, 並提出過程改進計划 15 15
· 合計 405 340

二. 模塊接口的設計與實現過程

1. 主要實現類

工具類:

FileUtils:文件工具類,具有讀寫文件,獲取文件名等靜態方法

QueryReapeat :查重工具類,具有對兩段字符串進行查重等靜態方法

ResultEditor類:結果處理工具類,具有對查重結果進行處理並返回的靜態方法

主類:

Application 類 :程序的入口類,其中的main方法可以接收多個參數用來作為輸入輸出文件的絕對路徑,main方法中調用工具類中的靜態方法實現整個查重功能。

各類之間的關系:

項目結構:

2. 關鍵函數的分析與實現

關鍵函數在於如何實現查重函數queryRepeat()?

通過上網查閱資料,參考了TF-IDF與余弦相似性的應用(二):找出相似文章 這篇博文。

假設有兩個句子A,B

  句子A:我喜歡吃蘋果,不喜歡吃榴蓮。

  句子B:我不喜歡吃蘋果,也不喜歡吃榴蓮。

第一步,分詞。

  句子A:我/喜歡/吃/蘋果,不/喜歡/吃/榴蓮。

  句子B:我/不/喜歡/吃/蘋果,也/不/喜歡/吃/榴蓮。

實現:通過IKAnalyzer中文分詞器實現,即通過查詢內置的詞典進行分詞

第二步,列出所有的詞。

  我,喜歡,吃,蘋果,榴蓮,不,也。

第三步,計算詞頻。

  句子A:我 1,喜歡 2,吃 2,蘋果 1,榴蓮 1,不 1,也 0。

  句子B:我 1,喜歡 2,吃 2,蘋果 1,榴蓮 1,不 2,也 1。

第四步,寫出詞頻向量。

  句子A:[1, 2, 2, 1, 1, 1, 0]

  句子B:[1, 2, 2, 1, 1, 2, 1]

實現:詞與詞頻是鍵值對的形式,因此可以用哈希表來存儲

到這里,問題就變成了如何計算這兩個向量的相似程度。

我們可以把它們想象成空間中的兩條線段,都是從原點([0, 0, ...])出發,指向不同的方向。兩條線段之間形成一個夾角,如果夾角為0度,意味着方向相同、線段重合;如果夾角為90度,意味着形成直角,方向完全不相似;如果夾角為180度,意味着方向正好相反。因此,我們可以通過夾角的大小,來判斷向量的相似程度。夾角越小,就代表越相似。

則計算A, B向量間的夾角的余弦值

假定a向量是[x1, y1],b向量是[x2, y2],那么可以將余弦定理改寫成下面的形式:

img

推廣至n維

img

余弦值越接近1,說明兩向量間夾角越接近0,即兩個句子越相似,因此余弦值即為兩句子的相似度

三.模塊接口部分的性能改進

可以看出程序中消耗最大的函數是中文分詞器查詢字典調用的相關函數

四.模塊部分單元測試展示

1.測試工具

使用JUnit4進行單元測試,創建一個TestCoverage類,在其中測試各模塊方法。

2.WordsUtil工具類方法測試

@Test
public void testWordUtil() {
    // 測試正常情況下分詞
    List<String> strings1 = WordsUtil.splitWords("今天是周天,天氣晴朗,我晚上要去看電影。");
    // 測試空串情況下分詞
    List<String> strings2 = WordsUtil.splitWords("");
    // 測試字符串中插入不同符號情況下分詞
    List<String> strings3 = WordsUtil.splitWords("@*()-+今天是**周天,天氣晴朗");
    // 測試字符串中存在空格情況下分詞
    List<String> strings4 = WordsUtil.splitWords("   今天是周天,天氣晴  朗,我晚上要去看電影。    ");
    System.out.println("strings1:");
    for (String string : strings1) {
        System.out.print(string + "/");
    }
    System.out.println();
    System.out.println("strings2:");
    for (String string : strings2) {
        System.out.print(string + "/");
    }
    System.out.println();
    System.out.println("strings3:");
    for (String string : strings3) {
        System.out.print(string + "/");
    }
    System.out.println();
    System.out.println("strings4:");
    for (String string : strings4) {
        System.out.print(string + "/");
    }
    System.out.println();
}

測試結果:

3. QueryRepeat工具類測試

@Test
    public void testQueryRepeat() {
        // 完全倒序情況
        double repeatRadius1 = QueryRepeat.getRepeatRadius("今天是星期天,天氣晴,今天晚上我要去看電影。",
                "影電看去要我上晚天今,晴氣天,天期星是天今。");
        // 空字符串情況
        double repeatRadius2 = QueryRepeat.getRepeatRadius("", "");
        // 完全相同情況
        double repeatRadius3 = QueryRepeat.getRepeatRadius("今天是星期天,天氣晴,今天晚上我要去看電影。",
                "今天是星期天,天氣晴,今天晚上我要去看電影。");
        // 部分抄襲情況
        double repeatRadius4 = QueryRepeat.getRepeatRadius("今天是星期天,天氣晴,今天晚上我要去看電影。",
                "今天是周天,天氣晴朗,我晚上要去看電影。");
        // 插入符號情況
        double repeatRadius5 = QueryRepeat.getRepeatRadius("今天是星期天,天氣晴,今天晚上我要去看電影。",
                "今天是*&星期*(天,天氣+-晴,今天晚&&上我要去看電影。");
		// 包含空格情況
        double repeatRadius6 = QueryRepeat.getRepeatRadius("今天是星期天,天氣晴,今天晚上我要去看電影。",
                "今天是  星期  天,天氣  晴,今天晚  上我要去看電影。");

        System.out.println("repeatRadius1:" + repeatRadius1);
        System.out.println("repeatRadius2:" + repeatRadius2);
        System.out.println("repeatRadius3:" + repeatRadius3);
        System.out.println("repeatRadius4:" + repeatRadius4);
        System.out.println("repeatRadius5:" + repeatRadius5);
        System.out.println("repeatRadius6:" + repeatRadius6);
    }

空串情況下:

剩余情況:

4.代碼覆蓋率截圖

五.模塊部分異常處理說明

通過上面單元測試發現了QueryRepeat.getRepeatRadius("", "")方法會報空指針異常並對其進行了捕獲處理,在控制台輸出了相應報錯信息。
也可以在Application類加入判斷,當有空串時就退出程序並打印信息到控制台

if(originText.equals("") || copyText.equals("")) {
    System.out.println("文件內無內容!");
    System.exit(0);
}

六. 項目程序功能測試



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM