201671010409 达选奇 《英文文本统计分析》结对项目报告
实验四 软件工程界对项目
博文简要信息:
项目 | 内容 |
---|---|
软件工程 | 教师博客主页链接 |
作业要求 | 作业链接地址 |
课程目标 | 熟悉软件开发整体流程,提升自身能力 |
实现目标 | 第一次体验一个完整的工程 |
实验内容:
任务 | 内容 |
---|---|
任务一 | 两两自由结对,对结对方的《实验二 软件工程个人项目》的项目成果进行评价 |
任务二 | 采用两人合作方式,设计开发一个英文文本统计分析软件 |
任务三 | 完成博文作业 |
任务一 组队互评
项目 | 内容 |
---|---|
作业博客 | 丁家辉201671010406 |
点评内容 | 博文脉络清晰,博文结构中有需求分析、功能设计、环境需求、测试运行、部分代码、psp、运行截图、设计实现等功能模块,结构符合规范。博文内容每一模块 都联系该程序的相应功能模块来说,内容以程序实际运行状况为依据进行总结,内容紧凑。博文排版结构与psp中任务内容列的关系大致上保持同步,在对psp 中的“计划完成需要的时间”和“实际完成需要的时间”的两列数据进行比较发现,很多完成时间和预估时间存在差异,一方面是因为理论上的估算时间和现实的工 程进行时的时间是有区别的,另一方面在实际操作中因为对C语言编程的掌握程度不同,从而影响程序的一系列相关的进程的开发。软件结构设计比较合理,代码规范有待进一步加强,其中高频词、柱状图功能没有实现,人机交互只有两项,略显少。 |
点评心得 | 总的来说实现功能较少,还用加强java编程学习 |
Github仓库主页 | https://github.com/Hero-ding/Hero/tree/master/词频统计 |
任务二 合作设计
结对项目源码在Github的仓库主页链接地址:https://github.com/Daxuanqi/ptdm/tree/master/实验四
1.需求分析
-
实验2要求的功能;
-
单词频数可视化柱状图要求是以下样式:
-
统计该文本行数及字符数;
-
各种统计功能均提供计时功能,显示程序统计所消耗时间(单位:ms);
-
可处理任意用户导入的任意英文文本;
-
人机交互界面要求GUI界面(WEB页面、APP页面都可);
-
附加分功能:统计文本中除冠词、代词、介词之外的高频词;
-
附加分功能:统计前10个两个单词组成的词组频率。
2.软件设计:类关键信息
-
BufferedReader(Reader in,int sz)类
创建一个使用指定大小输入缓冲区的缓冲字符输入流
-
JFreeChart类
字符串中的字母被转换为小写字母,开放的图表绘制类库,用于生成柱形图,可以产生PNG文件
-
CategoryPlot类
实现对数组的排序,给输出的单词频率高低进行排序
-
SimpleDateFormat类
以与语言环境相关的方式来格式化和分析日期的具体类
-
Map<String ,Integer>map接口
以键值对方存储单词词频
-
File类
File对象用来获取或处理与磁盘文件相关的信息,例如权限,时间,日期和目录路径
-
ServletInputStream类
一个 Servlet 通过使用ServletRequest 接口获得了对一ServletInputStream 对象的说明。这个类的子类必须提供一InputStream接口读取有关信息的方法
-
Collection集合接口
集合接口
uml图
![](https://img2018.cnblogs.com/blog/1614530/201904/1614530-20190403081819923-616491803.png)
3.核心功能代码展示
/**
* 柱状图设置文字样式
* @param chart
*/
private static void getChartByFont(JFreeChart chart,Integer end) {
// 图形设置标题文字
TextTitle textTitle = chart.getTitle();
textTitle.setFont(new Font("宋体", Font.BOLD, 32));
//设置X轴内容竖直
// XYPlot xyplot = chart.getXYPlot();
// DateAxis dateaxis = (DateAxis)xyplot.getDomainAxis();
// dateaxis.setTickUnit(new DateTickUnit(1, 1, new SimpleDateFormat("MMM-yyyy")));
// dateaxis.setVerticalTickLabels(true);
// 设置图形X轴坐标文字
CategoryPlot plot = (CategoryPlot) chart.getPlot();
CategoryAxis axis = plot.getDomainAxis();
axis.setLabelFont(new Font("宋体", Font.BOLD, 8)); // 设置X轴坐标上标题的文字
axis.setTickLabelFont(new Font("宋体", Font.BOLD, 16)); // 设置X轴坐标上的文字
axis.setCategoryLabelPositions(CategoryLabelPositions.DOWN_45);
axis.setUpperMargin(0.01);//设置距离图片左端距离
axis.setLowerMargin(0.01); //设置距离图片右端距离
// 设置图形Y轴坐标文字
NumberAxis na= (NumberAxis)plot.getRangeAxis();
na.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
ValueAxis valueAxis = plot.getRangeAxis();
valueAxis.setLabelFont(new Font("宋体", Font.BOLD, 20)); // 设置Y轴坐标上标题的文字
valueAxis.setTickLabelFont(new Font("sans-serif", Font.BOLD, 16));// 设置Y轴坐标上的文字
valueAxis.setRange(0,end);
// valueAxis.setLowerBound(0); //Y轴以开始的最小值
// valueAxis.setUpperBound(15); //Y轴的最大值
// 设置提示内容的文字
chart.getLegend().setItemFont(new Font("宋体", Font.BOLD, 24));
}
}
public class InputFile {
/**
* 文件名生成
* @return
*/
public static String getRandomFileName() {
SimpleDateFormat simpleDateFormat;
simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
Date date = new Date();
String str = simpleDateFormat.format(date);
Random random = new Random();
int rannum = (int) (random.nextDouble() * (99999 - 10000 + 1)) + 10000;// 获取5位随机数
return rannum + str;// 当前时间
}
/**
* 单词:词频
* @param file
* @return
*/
public class FileServlet extends HttpServlet{
private static final long serialVersionUID = 1L;
public FileServlet() {
super();
}
/**
* 存入文件
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
/**
* 读取文件
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("utf-8");
//String contentType = request.getContentType();
//System.out.println("表单类型:"+contentType);
//String boundary = contentType.substring(contentType.indexOf("boundary=")+9);
//System.out.println("boundary:"+boundary);
String root = getServletContext().getRealPath("/tempFile/temp.txt");
File file = new File(root);
if(!file.exists()){
//先得到文件的上级目录,并创建上级目录,在创建文件
file.getParentFile().mkdir();
try {
//创建文件
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
public class JfreeChartServlet extends HttpServlet{
/**
* 柱状图生成
* @return
*/
private static final long serialVersionUID = 1L;
public JfreeChartServlet() {
super();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
@SuppressWarnings("null")
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "textml;charset=UTF-8");
String root = getServletContext().getRealPath("/tempFile/temp.txt");
File readfile = new File(root);
//System.out.println(readfile.exists());
if(readfile.exists()){
InputFile in = new InputFile();
Map<String,Integer> readmap = in.readFile(readfile);
//System.out.println(readmap);
//取出单词词频最大数值
Collection<Integer> c = readmap.values();
Object[] obj = c.toArray();
Arrays.sort(obj);
// System.out.println("单词词频数:"+Arrays.toString(obj));
// System.out.println("最大词频:"+obj[obj.length-1]);
Integer maxnumber = (Integer) obj[obj.length-1];
System.out.println("单词数:"+obj.length);
//遍历
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
for (String key : readmap.keySet()) {
Integer value = readmap.get(key); //得到每个key所对应的value值
dataset.addValue(value, "单词", key);
}
// 获取柱状图工具类创建的柱状图,(将数据集传入)
JFreeChart chart = ColumnarTools.createCoColumnar(dataset,maxnumber+1);
new InputFile();
//以当前时间生成图片名称(防止图片重复被覆盖)
String time = InputFile.getRandomFileName();
String uploadUrl = request.getServletContext().getRealPath("/")+"images\\"+time+".png";
System.out.println("图片物理路径所在位置:"+uploadUrl);
File file = new File(uploadUrl);
//System.out.println(file);
if(!file.exists()){
//先得到文件的上级目录,并创建上级目录,在创建文件
file.getParentFile().mkdir();
try {
//创建文件
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
ChartUtilities.saveChartAsJPEG(file, chart, 800, 600);
Map<String, String> map = new HashMap<String, String>();
map.put("name", time+".png");
JSONObject jsonObject = JSONObject.fromObject(map);
System.out.println("json图片名称:"+jsonObject);
response.getWriter().write(jsonObject.toString());
}
4.程序运行
选择txt文本:
读取txt,分离单词:
查询单词频率:
显示统计柱状图:
5.过程及照片
6.PSP
PSP2.1 | 任务内容 | 计划共完成需要的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
Planning | 计划 | 10 | 15 |
Estimate | 估计这个任务需要多少 时间,并规划大致工作步骤 | 10 | |
Development | 开发 | 300 | 400 |
Analysis | 需求分析 (包括学习新技术) | 15 | 20 |
Design Spec | 生成设计文档 | 15 | 30 |
Design Review | 设计复审 (和同学审核设计文档) | 16 | 23 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 5 | 9 |
Design | 具体设计 | 20 | 30 |
Coding | 具体编码 | 180 | 240 |
Code Review | 代码复审 | 20 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 50 | 50 |
Reporting | 报告 | 25 | 30 |
Test Report | 测试报告 | 6 | 8 |
Size Measurement | 计算工作量 | 5 | 5 |
Postmortem & Process Improvement Plan | 事后总结 ,并提出过程改进计划 | 9 | 12 |
实验小结
通过这次结对编程项目,我对多人结对的工作模式有了更深刻的理解,对软件工程的复杂性有了清楚的认识,同时对这次编程中暴露的问题有了充分的思想准备,希望在以后学习中加强编程的功底。