#
222100309许君毓
这个作业属于哪个课程 | 软件工程实践-W班 |
---|---|
这个作业要求在哪里 | 软件工程实践寒假作业 |
这个作业的目标 | 完成对世界游泳锦标赛跳水项目相关数据的收集,并实现一个能够对赛事数据进行统计的控制台程序 |
目录
GitCode项目地址
https://gitcode.net/zlq22xjy/project-java
PSP表格
PSP | 预估耗时 | 实际耗时 |
---|---|---|
学习爬虫,爬取数据 | 2天 | 2天 |
复习Java | 1天 | 1天 |
需求分析 | 1天 | 1天 |
编写代码 | 3天 | 3天 |
测试 | 2天 | 2天 |
性能优化 | 2天 | 2天 |
解题思路描述
- 先将数据爬取下来,需要学习Python知识
- 将数据保存为CSV,后学习Java处理CSV文件的API
- 考虑对于women 1m springboard这样的比赛结构可以用字符串分割然后用作树状结构来处理数据
- 设计单例类来保存运动员和比赛的信息,其中比赛类需要知道参加的选手
- 设计一个工具类来对输入数据进行分流处理,提取信息输出到指定文件
接口设计和实现过程
Pyhthon代码:
import pandas
import requests
import pandas as pd
header={
'User-Agent':'https://api.worldaquatics.com/fina/events/108c795d-5e4f-4dc6-acea-0bc70bfd1928'
}
list=[]
response=requests.get(url,header)
result=response.json()
disciplineName=result['DisciplineName']
for competition in result['Heats']:
competitionName=competition['Name']
for athleteGoal in competition['Results']:
totalPoint=athleteGoal['TotalPoints']
athleteName=athleteGoal['FullName']
athlete_rank=athleteGoal['Rank']
athlete_detailGoal=''
i=0
for smallGoal in athleteGoal['Dives']:
athlete_detailGoal+=smallGoa>['DivePoints']
if(i!=len(athleteGoal['Dives'])-1):
athlete_detailGoal+='+'
i=i+1
athleteDetail={
'Name':athleteName.replace('/','&'),
'Rank':athlete_rank,
'DisciplineName':disciplineName,
'Session':competitionName,
'TotalPoints':totalPoint,
'DetailPoints':athlete_detailGoal
}
list.append((athleteDetail))
pdData=pandas.DataFrame(list)
pdData.to_csv(''+disciplineName+'.csv',index=False)
导出CSV文件:
2.用Java存贮静态数据
决定用单例模式来存贮Athlete和Event两个类
3.设计CSVReader工具类来进行读取数据
4.设计DivingInformSearch工具类来进行数据在input和output文件的读和写
##代码执行过程
首先,由CSVReader里的PrintAthleteInform方法和ReadCompetitionDetail将SingleInstance类中的HashMap<String,Athlete>athletes(运动员信息)和HashMap<String,Event>events(赛事信息)填充完整。接着,将命令行接收到的input和output文件地址传递给DivingInformSearch类的DistributeDivingPath,该静态方法逐行解析input文件中的信息,(若该行信息输入错误则抛出ErrorException(自定义异常类),若改行信息结构错误导致无法解析比赛项目则抛出NotFoundEventException(自定义异常类),接着由程序处理不同异常类的输出结果),若解析为‘players’,则调用WriteAthleteInform静态方法,
若解析为‘result …’则调用WriteCompetitionInform方法,将信息写入output文件
###排序
- 对Players进行按国际首字母升序排序
设计AthleteBaseInformComparator类继承自Comparator
在WriteAthleteInform调用前先将HashMap<String,Athlete>athletes里的每一个players取出构建一个ArrayList,调用ArrayList的Sort方法传入AthleteBaseInformComparator类
- 对每场比赛的排序
关键代码展示
- 非详细输出
if(!detail)
{
SingleInstance.GetInstance().events.get(eventName).sortAthlete();
ArrayList<Athlete>athletes=SingleInstance.GetInstance().events.get(eventName).getAthletes();
for(int i=0;i<athletes.size();i++)
{
Athlete a=athletes.get(i);
SessionResult finalResult=a.competitionDetail.get(eventName).get(sessionName[0]);
StringBuilder sb=new StringBuilder("");
sb.append("Full Name:").append(a.fullName).append("\r\n");
sb.append("Rank:").append(finalResult.rank).append("\r\n");
sb.append("Score:").append(finalResult.smallPoints).append("=").append(finalResult.totalPoints).append("\r\n");
sb.append("-----\r\n");
fw.write(sb.toString());
}fw.flush();
}
- 处理csv文件的每一行
public static void dataStore(List<String>lines)
{
for(int i=1;i<lines.size();i++)
{
String[]values=lines.get(i).split(",");
// System.out.println(values[0]+" "+values[1]+" "+values[2]+" "+values[3]+" "+values[4]+" "+values[5]+" ");
if(SingleInstance.GetInstance().isAthleteExsits(values[0]))
{
Athlete a=SingleInstance.GetInstance().getAthlete(values[0]);
a.addCompetition(values[2],values[3],new SessionResult(values[3],values[1],values[4],values[5]));
if(!SingleInstance.GetInstance().events.get(values[2]).athletes.contains(a))
SingleInstance.GetInstance().events.get(values[2]).addAthlete(a);
}
else{
Athlete a=new Athlete(values[0],"","");
a.addCompetition(values[2],values[3],new SessionResult(values[3],values[1],values[4],values[5]));
SingleInstance.GetInstance().addAthlete(values[0],a);
if(!SingleInstance.GetInstance().events.get(values[2]).athletes.contains(a))
SingleInstance.GetInstance().events.get(values[2]).addAthlete(a);
}
}
}
异常处理
DistributeDivingPath,该静态方法逐行解析input文件中的信息,(若该行信息输入错误则抛出ErrorException(自定义异常类),若改行信息结构错误导致无法解析比赛项目则抛出NotFoundEventException(自定义异常类),接着由程序处理不同异常类的输出结果
性能改进
1.对每名运动员的具体比赛场次信息用HashMap将Final,Semifinal,Preliminary作为键,映射SessionResult
测试
- 白盒测试
测试控制台代码:java -jar DWASearch.jar D://input.txt D://output.txt
-
D://input.txt:result women 1m springboard
result women 3m springboard detail
-
D://input.txt:result women 1m synchronised
result women 3m synchronised details -
D://input.txt:result women 3m synchronised
result women 3m synchronised detail -
D://input.txt:result men 1m springboard
result men 3m springboard detail -
D://input.txt:result men1m springboard
result men 3m springboard details
-
-
D://input.txt:result men 3m synchronised
result men 3m synchronised detail
-
D://input.txt:result women 3msynchronised
result men 3m synchronised detail
-
D://input.txt:result women 3msynchronised
result men 3m synchronised details
Player
心得体会
通过这次作业我学习了一点点Python,爬取数据让我觉得十分有趣,同时我也复习了Java,让我更加熟练地写单例类设计模式。但在性能方面的优化还存在不足,字符串的比较是否可以用树的结构进行快速分类还没有落实