PSP2.1 | 我的開發流程 | 預估耗費時間(分鐘) | 實際耗費時間(分鐘) |
---|---|---|---|
Planning | 計劃 | 5 | 3 |
· Estimate | 明確需求和其餘相關因素,估計每一個階段的時間成本 | 5 | 3 |
Development | 開發 | 274 | 308 |
· Analysis | 需求分析 (包括學習新技術) | 60 | 60 |
· Design Spec | 生成設計文檔 | 5 | 2 |
· Design Review | 設計複審 | 4 | 2 |
· Coding Standard | 代碼規範 | 5 | 5 |
· Design | 具體設計 | 10 | 20 |
· Coding | 具體編碼 | 120 | 180 |
· Code Review | 代碼複審 | 10 | 9 |
· Test | 測試(自我測試,修改代碼,提交修改) | 60 | 30 |
Reporting | 報告 | 40 | 65 |
· | 測試報告 | 30 | 60 |
· | 計算工做量 | 5 | 2 |
· | 並提出過程改進計劃 | 3 | 3 |
此次的項目是創建在上一次做業的項目的基礎上,在功能上,主要有兩個新增的地方:html
而後在設計上則是新增了GUI界面。java
詞組統計的話,是使用了多重循環,分層進行判斷,在存儲方面也是使用了Map進行存儲。git
自定義輸出的解題思路:戳這裏戳這裏戳這裏web
GUI界面使用了netbeans以及web來實現。編程
我對於GUI界面是使用了netBeans來實現,使用了文本框控件,菜單控件等來實現處理文件以及字符處理,經過給不一樣按鈕添加相應事件,以此來實現不一樣的功能。app
web界面的解題解題思路:戳這裏戳這裏戳這裏jsp
這個函數實現了統計指定長度的詞組的詞頻信息,經過傳入詞組長度,而後遍歷整個文件內容,先判斷單詞,再進行詞組的判斷。最後的存儲仍是使用Map來進行存儲,以便於統計輸出。ide
public Map getWordGroupFreq(int num) // 統計詞組詞頻(單詞:以4個英文字母開頭,跟上字母數字符號,單詞以分隔符分割,不區分大小寫。) { wordGroupFreq = new HashMap<String, Integer>(); String t = text; String[] spWord = t.split("\\s+"); // 對字符串進行分詞操做 for (int i = 0; i < spWord.length - num + 1; i++) { String wordG = ""; int isWG = 1; for (int j = i; j < i + num; j++) { if (spWord[j].length() < 4) { // 判斷是不是單詞,若不是,則直接不用考慮這個詞組 isWG = 0; break; } else { int flag = 1; // 判斷字符串的前四位是不是英文字母 char c; for (int k = 0; k < 4; k++) { c = spWord[j].charAt(k); if (!(c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')) { flag = 0; } } if (flag == 0) { isWG = 0; break; } else { wordG = wordG + spWord[j] + " "; } } } if (isWG == 1 && wordG.trim().length() != 0) { if (wordGroupFreq.get(wordG.trim()) == null) { // 判斷以前Map中是否出現過該詞組 wordGroupFreq.put(wordG.trim(), 1); } else { wordGroupFreq.put(wordG.trim(), wordGroupFreq.get(wordG.trim()) + 1); } } } return wordGroupFreq; }
打開文件函數
該函數用於實現菜單控件中打開文件的功能實現。經過選取文件,將文件內容顯示到相應的地方。佈局
private void openFileActionPerformed(java.awt.event.ActionEvent evt) { f = new Frame("my window");// 建立窗體對象 f.setBounds(300, 100, 650, 600);// 設置窗體位置和大小 open = new FileDialog(f, "打開", FileDialog.LOAD); open.setVisible(true);//顯示打開文件對話框 String dirpath = open.getDirectory();//獲取打開文件路徑並保存到字符串中。 String fileName = open.getFile();//獲取打開文件名稱並保存到字符串中 if (dirpath == null || fileName == null)//判斷路徑和文件是否爲空 { return; } else { text.setText(null);//文件不爲空,清空原來文件內容。 } File file = new File(dirpath, fileName);//建立新的路徑和名稱 try { //BufferedReader bufr = new BufferedReader(new FileReader(file));//嘗試從文件中讀東西 BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream(file), "gb2312")); String line = null;//變量字符串初始化爲空 while ((line = bufr.readLine()) != null) { text.append(line + "\r\n");//顯示每一行內容 } bufr.close();//關閉文件 } catch (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } }
保存文件
該函數用於將結果框中的內容保存爲文件。
private void saveFileActionPerformed(java.awt.event.ActionEvent evt) { save = new FileDialog(f, "保存", FileDialog.SAVE); save.setVisible(true);//顯示保存文件對話框 String dirpath = save.getDirectory();//獲取保存文件路徑並保存到字符串中。 String fileName = save.getFile();////獲取打保存文件名稱並保存到字符串中 if (dirpath == null || fileName == null)//判斷路徑和文件是否爲空 { return;//空操做 } else { file = new File(dirpath, fileName);//文件不爲空,新建一個路徑和名稱 } try { BufferedWriter bw = new BufferedWriter(new FileWriter(file)); String text = result.getText();//獲取文本內容 bw.write(text);//將獲取文本內容寫入到字符輸出流 bw.close();//關閉文件 } catch (IOException e1) { //拋出IO異常 e1.printStackTrace(); } }
功能函數的調用
這一類的方法是根據點擊的不一樣按鈕,對應實現不一樣的方法,並將結果進行展現。
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: String t = text.getText(); WordDeal wd = new WordDeal(t); // 調用類中的方法獲取相應的數值 int charNum = wd.getCharCount(); int wordCount = wd.getWordCount(); int ValidLine = wd.getLineCount(); Map<String, Integer> wordFreq = wd.getWordFreq(); List sortMap = wd.sortMap(wordFreq); String[] wFreq = wd.ListToArray(sortMap); String w = "字符總數:" + charNum + "\r\n" + "單詞總數" + wordCount + "\r\n" + "有效行數" + ValidLine + "\r\n詞頻統計:\r\n"; for (int i = 0; i < wFreq.length; i++) { w = w + wFreq[i] + "\r\n"; } result.setText(w); //寫入到相應的控件之中 }
對原有函數的迴歸測試
package junitTest; import static org.junit.Assert.*; import java.io.IOException; import java.util.*; import org.junit.Before; import org.junit.Test; import wCount.*; public class WordDealTest { @Before public void setUp() throws Exception { } @Test public void testGetCharCount() throws IOException {//統計字符數量測試 FileDeal fd = new FileDeal(); String text1 = fd.FileToString("text/text1.txt"); String text2 = fd.FileToString("text/text2.txt"); String text3 = fd.FileToString("text/text3.txt"); String text4 = fd.FileToString("text/text4.txt"); WordDeal wd1 = new WordDeal(text1); WordDeal wd2 = new WordDeal(text2); WordDeal wd3 = new WordDeal(text3); WordDeal wd4 = new WordDeal(text4); int cn1 = wd1.getCharCount(); int cn2 = wd2.getCharCount(); int cn3 = wd3.getCharCount(); int cn4 = wd4.getCharCount(); assertEquals(0, cn1); assertEquals(0, cn2); assertEquals(80, cn3); assertEquals(73, cn4); } @Test public void testGetWordCount() throws IOException {//統計單詞數量測試 FileDeal fd = new FileDeal(); String text1 = fd.FileToString("text/text1.txt"); String text2 = fd.FileToString("text/text4.txt"); WordDeal wd1 = new WordDeal(text1); WordDeal wd2 = new WordDeal(text2); int wn1 = wd1.getWordCount(); int wn2 = wd2.getWordCount(); assertEquals(0, wn1); assertEquals(3, wn2); } @Test public void testGetWordFreq() throws IOException {//統計詞頻測試 Map<String,Integer> ans1 = new HashMap<String,Integer>(); Map<String,Integer> ans2 = new HashMap<String,Integer>(); ans2.put("coverage", 1); ans2.put("yizhishuijiao", 2); FileDeal fd = new FileDeal(); String text1 = fd.FileToString("text/text1.txt"); String text2 = fd.FileToString("text/text4.txt"); WordDeal wd1 = new WordDeal(text1); WordDeal wd2 = new WordDeal(text2); Map<String,Integer> wf1 = wd1.getWordFreq(); Map<String,Integer> wf2 = wd2.getWordFreq(); assertEquals(ans1, wf1); assertEquals(ans2, wf2); } @Test public void testSortMap() throws IOException {//詞頻排序測試 FileDeal fd = new FileDeal(); String text1 = fd.FileToString("text/text1.txt"); String text2 = fd.FileToString("text/text4.txt"); WordDeal wd1 = new WordDeal(text1); WordDeal wd2 = new WordDeal(text2); Map<String,Integer> wf1 = wd1.getWordFreq(); Map<String,Integer> wf2 = wd2.getWordFreq(); List lis1 = wd1.sortMap(wf1); List lis2 = wd2.sortMap(wf2); //assertEquals(ans1, wf1); //assertEquals(ans2, wf2); } @Test public void testGetLineCount() throws IOException {//統計有效行數測試 FileDeal fd = new FileDeal(); String text1 = fd.FileToString("text/text1.txt"); String text2 = fd.FileToString("text/text4.txt"); WordDeal wd1 = new WordDeal(text1); WordDeal wd2 = new WordDeal(text2); int wn1 = wd1.getLineCount(); int wn2 = wd2.getLineCount(); assertEquals(0, wn1); assertEquals(4, wn2); } @Test public void testListToArray() throws IOException { FileDeal fd = new FileDeal(); String text1 = fd.FileToString("text/text1.txt"); String text2 = fd.FileToString("text/text4.txt"); String text3 = fd.FileToString("text/text5.txt"); WordDeal wd1 = new WordDeal(text1); WordDeal wd2 = new WordDeal(text2); WordDeal wd3 = new WordDeal(text3); Map<String,Integer> wf1 = wd1.getWordFreq(); Map<String,Integer> wf2 = wd2.getWordFreq(); Map<String,Integer> wf3 = wd3.getWordFreq(); List lis1 = wd1.sortMap(wf1); List lis2 = wd2.sortMap(wf2); List lis3 = wd3.sortMap(wf3); String[] s1 = wd1.ListToArray(lis1); String[] s2 = wd2.ListToArray(lis2); String[] s3 = wd3.ListToArray(lis3); } }
測試結果:
對新增函數的測試
測試用例:
測試代碼:
@Test public void testGetWordGroupFreq() throws IOException {//統計詞組測試 FileDeal fd = new FileDeal(); String text6 = fd.FileToString("text/text6.txt"); WordDeal wd6 = new WordDeal(text6); Map<String,Integer> wf6 = wd6.getWordGroupFreq(3); }
測試結果:
對命令行版本項目的單元測試
對web版本項目的單元測試
對命令行版本項目的效能測試
對web版本項目的效能測試
此次的結對編程是針對一個項目進行的改進,由於此次的要求,命令行輸入和GUI界面的實現是兩個相對獨立的版本,因此通過討論之後,咱們的分工基本仍是由我寫完新增函數之後,由每一個人來實現一個版本,相對來講除了在調用函數方面,其餘部分仍是比較獨立的,因此其實並無不少結對的感受,可是在最開始討論的時候,每一個人都尚未很清晰的認識這個過程,致使對這個項目各有各的見解,而後討論的效率仍是比較低,花了很長時間才獲得的統一。因此此次編程並無不少的感覺到1+1>2的效果