这个作业属于哪个课程 | 软件工程实践-2023 学年-W 班 |
---|---|
这个作业要求在哪里 | 软件工程实践第二次作业——个人实战 |
这个作业的目标 | 完成对世界游泳锦标赛跳水项目相关数据的收集,并实现一个能够对赛事数据进行统计的控制台程序 |
其他参考文献 | csdn,源代码管理 |
作业基本信息…
Gitcode项目地址
PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 40 | 30 |
• Estimate | • 估计这个任务需要多少时间 | 30 | 40 |
Development | 开发 | 1000 | 1200 |
• Analysis | • 需求分析 (包括学习新技术) | 300 | 350 |
• Design Spec | • 生成设计文档 | 20 | 30 |
• Design Review | • 设计复审 | 20 | 30 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 10 | 20 |
• Design | • 具体设计 | 60 | 70 |
• Coding | • 具体编码 | 500 | 600 |
• Code Review | • 代码复审 | 20 | 30 |
• Test | • 测试(自我测试,修改代码,提交修改) | 110 | 120 |
Reporting | 报告 | 30 | 40 |
• Test Repor | • 测试报告 | 20 | 20 |
• Size Measurement | • 计算工作量 | 10 | 10 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 20 | 20 |
合计 | 1190 | 1410 |
解题思路描述
仔细阅读题目不难发现是考网页数据的提取以及文件的输入输出两个部分
1.网页数据提取部分
先通过http连接获取所需JSON字符串并使用fastjson2对JSON数据进行解析,找到对应的JSONObject和JSONArray对象提取需要内容。
2.文件输入输出部分
通过FileReader、FileWriter流对命令函参数对应地址文件进行读写,从输入文件中读取指令,再通过MMap类方法映射出对应的URL地址,供listInformation()和listResult()功能函数使用。
接口设计和实现过程
Player、Gameresult类用于保存数据,MMap类用于从映射对应URL,Netparse类获取JSON字符串、ListInformation和ListResult类提供类方法对数据进行处理并输出、IOtxt类用于输入输出至txt文件,主类DWASearch调用类方法对输入指令进行处理并输出至对应文件。
关键代码展示
通过http连接获取JSON字符串
public static String getJSONstr (String str) {
URL url = null;
try {
url = new URL(str);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String s;
StringBuffer sb = new StringBuffer();
while ((s = br.readLine()) != null) {
sb.append(s);
}
return sb.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
对选手信息进行解析并输出
public class ListInformation {
public static void listInformation (String outputpath) {
ArrayList<Player> playerList = new ArrayList<>();
try
{
String jsonstr = Netparse.getJSONstr("https://api.worldaquatics.com/fina/competitions/3337/athletes?gender=&countryId=");
JSONArray objects = JSON.parseArray(jsonstr);
for (int i = 0; i < objects.size(); i++) {
JSONObject object = (JSONObject) objects.get(i);
JSONArray players = object.getJSONArray("Participations");
for (int j = 0; j < players.size(); j++) {
JSONObject player = (JSONObject) players.get(j);
Player p = new Player();
p.setCountry(object.getString("CountryName"));
if ((player.getString("Gender")).equals("0")) {
p.setGender("Male");
} else {
p.setGender("Female");
}
p.setName(player.getString("PreferredLastName") + " " + player.getString("PreferredFirstName"));
playerList.add(p);
}
}
}catch (Exception e){
System.out.println("获取选手信息失败");
throw new RuntimeException(e);
}
try {
BufferedWriter bw = IOtxt.outTotxt(outputpath);
for (int i = 0; i < playerList.size(); i++) {
Player p = playerList.get(i);
bw.append("Full Name:" + p.getName() + "\n");
bw.append("Gender:" + p.getGender() + "\n");
bw.append("Country:" + p.getCountry() + "\n");
bw.append("-----\n");
}
bw.flush();
bw.close();
}catch (Exception e){
System.out.println("输出失败");
throw new RuntimeException();
}
}
}
对比赛信息进行解析并输出
public class ListResult {
public static void listResult(Map<String,String> mMap, String gamename,String outputpath){
ArrayList<Gameresult> gameResults = new ArrayList<>();
try {
String jsonStr = Netparse.getJSONstr(mMap.get(gamename));
JSONObject object = JSON.parseObject(jsonStr);
JSONArray heats = JSON.parseArray(object.getString("Heats"));
JSONObject fin = (JSONObject) heats.get(0);
JSONArray results = JSON.parseArray(fin.getString("Results"));
for (int i = 0; i < results.size(); i++) {
JSONObject result = (JSONObject) results.get(i);
Gameresult g = new Gameresult();
g.setTotalScore(result.getString("TotalPoints"));
String name = result.getString("FullName");
name = name.replace('/', '&');
g.setPlayerName(name);
g.setRank(result.getString("Rank"));
JSONArray dives = JSON.parseArray(result.getString("Dives"));
for (int j = 0; j < dives.size(); j++) {
JSONObject score = (JSONObject) dives.get(j);
g.pushScore(score.getString("DivePoints"));
}
gameResults.add(g);
}
}catch (Exception e){
System.out.println("获取网络资源失败");
throw new RuntimeException();
}
try {
BufferedWriter bw = IOtxt.outTotxt(outputpath);
for (int i = 0; i < gameResults.size(); i++) {
Gameresult g = gameResults.get(i);
bw.append("Full Name:" + g.getPlayerName() + "\n");
bw.append("Rank:" + g.getRank() + "\n");
bw.append("Score:");
for (int j = 0; j < g.scores.size(); j++) {
bw.append(g.getScore(j));
if (j != g.scores.size() - 1) {
bw.append(" + ");
} else {
bw.append(" = " + g.getTotalScore() + "\n");
}
}
bw.append("-----" + "\n");
}
bw.flush();
bw.close();
}catch (Exception e){
System.out.println("输出失败");
throw new RuntimeException();
}
}
}
输入逻辑处理
public static void DWAsearch(String input, String output) {
try {
if(input==null||output==null){
System.out.println("输入输出不能为空");
}
else {
Map<String, String> mMap = MMap.getMap();
IOtxt.cleartxt(output);
BufferedReader reader = IOtxt.inTotxt(input);
String line = reader.readLine();
while (line != null) {
if (line.equals("players")) {
ListInformation.listInformation(output);
} else if (line.startsWith("result ")) {
if (mMap.containsKey(line)) {
ListResult.listResult(mMap, line, output);
} else {
BufferedWriter _bw = IOtxt.outTotxt(output);
_bw.append("N/A" + "\n");
_bw.append("-----" + "\n");
_bw.flush();
_bw.close();
}
} else {
BufferedWriter _bw = IOtxt.outTotxt(output);
_bw.append("Error" + "\n");
_bw.append("-----" + "\n");
_bw.flush();
_bw.close();
}
line = reader.readLine();
}
reader.close();
}
}catch(Exception e){
System.out.println("主程序运行失败");
throw new RuntimeException();
}
}
性能改进
将原本的字节流读取改为字符流BufferedReader/BufferedWriter,有缓冲读取的功能,提高数据读写效率,将映射表直接存在程序中,减少了输入时间。
单元测试
异常处理
通过try catch代码段防止文件路径不存在时程序的崩溃
心得体会
这次作业让我明白了此前学习中仍然存在诸如项目管理在内等不少问题和缺漏,绝大多数的时间都是在学习新技术新特性上了,还有就是在构建整个项目的过程中考虑不够周密,很多类都是后续想到才补充上的,代码整体的安全性、可读性较差,需要多多加油努力✊