软件工程第二次实践作业————个人实战
| 这个作业属于哪个课程 | 2023年福大-软件工程实践-W班 |
|---|---|
| 这个作业要求在哪里 | 软件工程实践第二次作业——个人实战 |
| 这个作业的目标 | 测试代码、GitHub管理项目、解析Json |
| 其他参考文献 | 单元测试、《码出高效_阿里巴巴Java开发手册》 |
目录
- 1.Gitcode项目地址
- 2.PSP表格
- 3.解题思路
- 3.1获取数据
- 4.接口设计和实现过程
- 4.1两个解析实体类
- 4.2命令判断函数
- 4.3解析核心代码
- 5.性能改进
- 6.单元测试展示
- 7.心路历程与收获
1.Gitcode项目地址
2.PSP表格
| PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 30 | 40 |
| • Estimate | • 估计这个任务需要多少时间 | 10 | 5 |
| Development | 开发 | 600 | 500 |
| • Analysis | • 需求分析 (包括学习新技术) | 30 | 60 |
| • Design Spec | • 生成设计文档 | 20 | 25 |
| • Design Review | • 设计复审 | 20 | 30 |
| • Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 20 | 15 |
| • Design | • 具体设计 | 50 | 60 |
| • Coding | • 具体编码 | 720 | 800 |
| • Code Review | • 代码复审 | 30 | 35 |
| • Test | • 测试(自我测试,修改代码,提交修改) | 30 | 30 |
| Reporting | 报告 | 50 | 70 |
| • Test Repor | • 测试报告 | 20 | 30 |
| • Size Measurement | • 计算工作量 | 10 | 20 |
| • Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 10 | 10 |
| 合计 | 1650 | 1730 |
3.解题思路
先在官网上爬到json数据,用fastjson解析json,最后编写代码实现输入输出。
3.1获取数据
找到json地址

用得到的.json地址写Java代码把json写入本地文件
public static boolean saveJsonData(String jsonData, String fileName) {
boolean result = false;
BufferedWriter bufferedWriter = null;
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = jsonParser.parse(jsonData).getAsJsonObject();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String content = gson.toJson(jsonObject);
try {
String jsonFilePath = "data/schedule/" + fileName + ".json";
File file = new File(jsonFilePath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
}
bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8));
bufferedWriter.write(content);
result = true;
} catch (IOException e) {
System.out.println("保存数据到json文件异常!" + e);
} finally {
if (null != bufferedWriter) {
try {
bufferedWriter.close();
} catch (IOException exception) {
System.out.println("保存数据到json文件后,关闭流异常" + exception);
}
}
}
System.out.println("成功保存" + fileName +".json");
return result;
}
//将读取的json保存到本地
for (int i=1;i<=4;i++)
{
String url = "https://prod-scores-api.ausopen.com/year/2023/period/Q/day/" + String.valueOf(i) + "/results";
String json = loadJson(url);
HashMap map = new Gson().fromJson(json, HashMap.class);
saveJsonData(json,"Q"+String.valueOf(i));
}
然后编写代码达到题目需求,保证输出格式正确性
class Lib{
//读入函数
public static List<String> inPut(String path)
//写函数
public static void outPut(String content, String path)
//判断命令函数
public static String findCommand(String fname)
//根据json文件名得到当天/当季的胜者信息
public static String getMatch(String fname)
//得到所有选手的信息
public static String getPlayers()
}
4.接口设计和实现过程
4.1两个解析实体类
class MatchDay//单日、季度的实体类
{
private List<MatchesBean> matches;
private List<PlayersBean> players;
private List<TeamsBeanX> teams;
public static class MatchesBean {
private String actual_start_time;
private MatchStatusBean match_status;
private List<TeamsBean> teams;
public static class MatchStatusBean {
private String abbr;
}
public static class TeamsBean {
private String team_id;
private String status;
private List<ScoreBean> score;
public static class ScoreBean {
private int set;
private String game;
}
}
}
public static class PlayersBean {
private String uuid;
private String short_name;
}
public static class TeamsBeanX {
private String uuid;
private List<String> players;
}
}
class MatchPlayers//选手的实体类
{
private List<PlayersBean> players;
public static class PlayersBean {
private String full_name;
private String gender;
public static class NationalityBean {
private String name;
}
}
}
4.2命令判断函数
//输入命令字符串
//输出结果字符串(Error或者N/A或者字符串结果集)
public static String findCommand(String fname)
{
if (fname.length()<7)
{
return "Error\n-----\n";
}
else if (!fname.trim().equals("players")&&!fname.substring(0,7).equals("result "))
{
return "Error\n-----\n";
}
else if (fname.trim().equals("players"))
{
return getPlayers();
}
else
{
String name="01";
for (int i=16;i<30;i++)
{
if (fname.substring(7).trim().equals(name+i))
{
return getMatch(name+i);
}
}
for (int i=1;i<5;i++)
{
if (fname.substring(7).trim().equals("Q"+i))
{
return getMatch("Q"+i);
}
}
return "N/A\n-----\n";
}
}
4.3解析核心代码
//读写函数(略)
public static List<String> inPut(String path){}
public static void outPut(String content, String path){}
//核心,获得胜者信息
//遍历每场比赛
for (MatchDay.MatchesBean match:matchDay.getMatches())
{
if (match.getMatch_status().getAbbr().equals("W/O"))
{
winners+="W/O\n-----\n";
continue;
}
//胜利队号码
String teamNumber="";
//得到比赛时间
winners+="time:"+match.getActual_start_time()+"\n";
if (match.getTeams().get(0).getStatus()!=null)
{
teamNumber=match.getTeams().get(0).getTeam_id();
}
else
{
teamNumber=match.getTeams().get(1).getTeam_id();
}
//根据队号找选手名字,遍历队伍
winners+="winner:";
for (MatchDay.TeamsBeanX team: matchDay.getTeams())
{
if (team.getUuid().equals(teamNumber))
{
List<String> uuid=team.getPlayers();
for (int i=0;i<uuid.size();i++)
{
for (MatchDay.PlayersBean p: matchDay.getPlayers())
{
if (uuid.get(i).equals(p.getUuid()))
{
if (i != 0)
{
winners += " & ";
}
winners += p.getShort_name();
}
}
}
}
}
winners+="\n";
//得到比分
winners+="score:";
int i=0;
while (i<match.getTeams().get(0).getScore().size())
{
if (i==0)
{
winners+=match.getTeams().get(0).getScore().get(i).getGame()+":";
winners+=match.getTeams().get(1).getScore().get(i).getGame();
}
else
{
winners+=" | "+match.getTeams().get(0).getScore().get(i).getGame()+":";
winners+=match.getTeams().get(1).getScore().get(i).getGame();
}
i++;
}
winners+="\n-----\n";
}
//输出winners为胜者信息;
文件读写为常规读写,json解析使用fastjson.jar包的方法,将本地json封装到实体类中,然后使用普通的嵌套循环获得胜者信息,因为循环次数不大,代码的效率还算可以,选手信息的获取比较简单,就不放代码了。
5.性能改进
原来使用BufferedReader按行读文件,加到String
String line;
BufferedReader br =new BufferedReader(new InputStreamReader(new FileInputStream("data/schedule/"+fname+".json"),"utf-8"));
while ((line = br.readLine()) != null)
{
json+=line;
}
br.close();
改进:Read流按字符读取,append进StringBuffer流,速度更快。
File file = new File("data/schedule/"+fname+".json");
FileReader fileReader = new FileReader(file);
Reader reader = new InputStreamReader(new FileInputStream(file),"Utf-8");
int c = 0;
StringBuffer sb = new StringBuffer();
while ((c = reader.read()) != -1) {
sb.append((char) c);
}
fileReader.close();
reader.close();
json= sb.toString();
程序花费的时间从10872ms->898ms,时间是输出所有json的output花费的时间,使用fastjson包实体类解析速度不算慢,这里就不改进了,另外胜者信息的嵌套循环感觉速度还可以,这里页没有去改进(可能是实力不够,没时间改了)
6.单元测试展示
测试和覆盖率

测试函数从函数入手,使得测试代码可以运行到大部分的函数代码,考虑函数的各种分支,测试尽量走过所有的分支和函数,提高覆盖率,保证代码的正确。
7.心路历程与收获
开学缓考没有时间写实践作业,只能天天熬夜(哭),实践收获还是有的,不止是黑眼圈。这次实践学到了爬json的过程,以前不怎么接触的,也复习了json解析,使用fastjson.jar和一些其他插件。 也学习许多程序测试、代码格式要求,感觉可以更加好得适应以后的工作。
相关推荐
三相四桥臂电压不对称跌落补偿动态电压恢复器DVR(Simulink仿真实现)
内容概要:本文介绍了一种基于三相四桥臂拓扑结构的动态电压恢复器(DVR),用于补偿电网中由电压不对称跌落引起的电能质量问题。通过Simulink平台构建仿真模型,重点研究了在不平衡负载和电网电压跌落工况下,DVR对负载侧电压的快速补偿能力。系统采用多准PR(Proportional Resonant)并联控制策略,实现对各相电压的独立精确控制,有效抑制负序分量,提升系统在复杂工况下的稳定性和响应性能。仿真结果验证了所提控制方法在电压幅值、相位补偿及波形质量改善方面的有效性,适用于对供电连续性和电能质量要求较高的工业场景。; 适合人群:电力电子、电气工程及其自动化等相关专业的研究生、科研人员及从事电能质量治理的工程技术人员。; 使用场景及目标:①研究动态电压恢复器在电压跌落、三相不平衡等典型电能质量问题中的补偿机制;②掌握三相四桥臂逆变器的建模与多准PR控制策略的设计与实现;③为高精度电能质量调节装置的研发提供理论依据和仿真验证手段。; 阅读建议:建议结合提供的参考文献和说明文档,深入理解控制算法的设计原理,并在Simulink环境中动手复现仿真模型,通过调整故障条件和控制器参数,观察系统动态响应,从而全面掌握DVR的工作特性与优化方法。
cp210x驱动与串口助手下载
usb转串口驱动
三相并网逆变器无功功率扰动+孤岛检测控制算法仿真【参考文献+仿真】
内容概要:本文档系统介绍了三相并网逆变器中基于无功功率扰动的孤岛检测控制算法仿真资源,结合Simulink仿真模型与权威参考文献,深入阐述了逆变器在并网运行中的核心控制策略。重点围绕通过主动调节无功功率实现孤岛效应的快速、可靠检测,避免非计划性孤岛运行对电网设备和人员造成安全隐患。资源内容涵盖完整的算法原理分析、控制逻辑架构设计、Simulink仿真模型搭建流程及关键参数整定方法,帮助使用者深刻理解无功扰动法在实际系统中的应用机制,掌握其在不同工况下的动态响应特性和检测盲区规避策略,确保电网的安全稳定运行。; 适合人群:电力电子、新能源发电、电气工程及其自动化等相关专业的高校硕士、博士研究生,从事光伏发电、风力发电等新能源并网系统研发的工程技术人员,以及致力于电力系统保护与控制领域研究的科研人员。; 使用场景及目标:①深入研究并掌握基于无功功率扰动的孤岛检测技术在三相并网逆变器中的具体实现方法与优化路径;②支撑高校课程设计、毕业课题、科研项目申报及工程实践中的仿真验证,深化对并网保护、电网阻抗变化影响及控制策略鲁棒性的理解;③服务于高水平学术论文(如SCI期刊)的算法复现、对比分析与创新性改进。; 阅读建议:建议学习者紧密结合所提供的参考文献与Simulink仿真模型进行同步研习,重点关注控制模块的搭建细节、无功扰动注入方式的选择与参数设计,通过反复仿真调试,探究不同负载条件下孤岛检测的触发阈值与响应时间,从而全面掌握该算法的核心要点与工程应用技巧。
Special-Comfy-part1.7z.011
ComfyUI专用模型资源分卷压缩包,Special-Comfy-part1系列第011卷。7z分卷格式,单卷900MB,需配合全部分卷解压使用。
OpenChiip数字员工开源.docx
OpenChiip数字员工开源


