实验四 软件工程界对项目
博文简要信息:
项目 |
内容 |
这个作业属于哪个课程 |
教师博客主页链接 |
这个作业的要求在哪里 |
作业链接地址 |
课程学习目标 |
熟悉软件开发整体流程,提升自身能力 |
本次作业在哪个具体方面帮助我们实现目标 |
第一次体验一个完整的工程 |
实验内容:
任务 |
内容 |
任务一 |
两两自由结对,对结对方的《实验二 软件工程个人项目》的项目成果进行评价 |
任务二 |
采用两人合作方式,设计开发一个英文文本统计分析软件 |
任务三 |
完成博文作业 |
任务一 组队互评
项目 |
内容 |
作业博客 |
达选奇201671010409 |
点评内容 |
博文脉络清晰,博文结构中有需求分析、功能设计、环境需求、测试运行、部分代码、psp、运行截图、设计实现等功能模块,结构符合规范。从博文排版可看出,对于mackbook编辑器排版功能使用不是很熟练,基本符合规范。在对psp 中的“计划完成需要的时间”和“实际完成需要的时间”的两列数据进行比较发现,很多完成时间和预估时间存在差异,一方面是因为理论上的估算时间和现实的工 程进行时的时间是有区别的,另一方面在实际操作中因为对C语言编程的掌握程度不同,从而影响程序的一系列相关的进程的开发。软件结构设计比较合理,代码规范有待进一步加强,其中高频词、柱状图功能没有实现,人机交互只有两项,略显少,主要还是对于编程语言使用不熟练,知识比较缺乏,还需要加强编程能力的训练 |
点评心得 |
对于我们初次使用mackbook,各种排版不是很完美。在对与缺少Java编程语言的相关技能,编程过程中出现的代码问题较多。没有很好的实现所有功能。 |
任务二 合作设计
1.需求分析
- 实验2要求的功能;
- 单词频数可视化柱状图要求是以下样式:
![](https://img2018.cnblogs.com/blog/1223402/201903/1223402-20190321093513885-1488132485.png)
- 统计该文本行数及字符数;
- 各种统计功能均提供计时功能,显示程序统计所消耗时间(单位:ms);
- 可处理任意用户导入的任意英文文本;
- 人机交互界面要求GUI界面(WEB页面、APP页面都可);
- 附加分功能:统计文本中除冠词、代词、介词之外的高频词;
- 附加分功能:统计前10个两个单词组成的词组频率。
2.软件设计:类关键信息
-
BufferedReader(Reader in,int sz)类
创建一个使用指定大小输入缓冲区的缓冲字符输入流
-
JFreeChart类
开放的图表绘制类库,用于生成柱形图,可以产生PNG文件。
-
CategoryPlot类
组合图形
-
以与语言环境相关的方式来格式化和分析日期的具体类
-
Date
类 Date 表示特定的瞬间,精确到毫秒
-
Map<String ,Integer>map接口
以键值对方存储单词词频
-
File类
File对象用来获取或处理与磁盘文件相关的信息,例如权限,时间,日期和目录路径
-
一个 Servlet 通过使用ServletRequest 接口获得了对一个 ServletInputStream 对象的说明。这个类的子类必须提供一InputStream 接口读取有关信息的方法
-
Collection
集合接口
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.程序运行
![](https://img2018.cnblogs.com/blog/1614544/201904/1614544-20190403091244013-675199141.png)
![](https://img2018.cnblogs.com/blog/1614544/201904/1614544-20190403091947328-1738852808.png)
![](https://img2018.cnblogs.com/blog/1614544/201904/1614544-20190403092002738-400640189.png)
![](https://img2018.cnblogs.com/blog/1614544/201904/1614544-20190403080009294-2002486315.png)
5.过程及照片
6.PSP
PSP2.1 |
任务内容 |
计划共完成需要的时间(min) |
实际完成需要的时间(min) |
Planning |
计划 |
10 |
15 |
Estimate |
估计这个任务需要多少 时间,并规划大致工作步骤 |
10 |
20 |
Development |
开发 |
300 |
600 |
Analysis |
需求分析 (包括学习新技术) |
30 |
60 |
Design Spec |
生成设计文档 |
15 |
30 |
Design Review |
设计复审 (和同学审核设计文档) |
30 |
45 |
Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
10 |
10 |
Design |
具体设计 |
30 |
50 |
Coding |
具体编码 |
200 |
500 |
Code Review |
代码复审 |
20 |
30 |
Test |
测试(自我测试,修改代码,提交修改) |
40 |
60 |
Reporting |
报告 |
30 |
30 |
Test Report |
测试报告 |
6 |
8 |
Size Measurement |
计算工作量 |
5 |
5 |
Postmortem & Process Improvement Plan |
事后总结 ,并提出过程改进计划 |
9 |
12 |
GitHub代码地址
实验小结
从此次实验项目,我们小组都努力的去完成这个工作,但在这个过程中,深刻认识到了团队的重要性。从中体现了各种问题,也让我们很苦恼,但最后我们都一一解决。还有我们每个人缺乏的编程能力,这是一大硬伤,我们在之后还需加大对编程能力的提高。