软件工程实践第二次作业---个人实战

082000407傅铭锋 学生 2023-03-02 23:11:23

目录

  • Gitcode项目地址
  • PSP表格
  • 解题思路描述
  • 问题1 数据的获取
  • 问题2 json数据的解析
  • 接口设计和实现过程
  • 关键代码展示
  • 性能改进
  • 单元测试
  • 异常处理
  • 心得体会

这个作业属于哪个课程https://bbs.csdn.net/forums/weixin_53785144-01
这个作业要求在哪里https://bbs.csdn.net/topics/613505605
这个作业的目标完成对澳大利亚网球公开赛相关数据的收集,并实现一个能够对赛事数据进行统计的控制台程序
其他参考文献CSDN 、Github

Gitcode项目地址

https://gitcode.net/ajskx/hw2

PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划3020
Estimate估计这个任务需要多少时间100130
Development开发1030
Analysis需求分析4030
Design Spec生成设计文档3030
Design Review• 设计复审2020
Coding Standard• 代码规范2530
Design• 具体设计3040
Coding• 具体编码6070
Code Review• 代码复审2050
Test• 测试3030
Reporting报告3035
Test Repor• 测试报告2020
Size Measurement• 计算工作量3050
Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划3035
合计505620

解题思路描述

问题1 数据的获取

我们需要将澳洲网球公开赛的所有比赛信息包括选手和比赛结果信息当获得相应的信息时,输出给output.txt中。我们获得的数据主要来源于json数据,而有关json数据,一部分通过助教在群里分享,另一部分通过edge的F12中获得json数据

问题2 json数据的解析

一开始时通过jsoncpp进行数据解析,但是在性能优化的时候,jsoncpp性能过低,后面改用rapidjson进行解析json数据

接口设计和实现过程

代码主要是分为两部分,一部分工具代码(Lib.h,Lib.cpp),另一部分就是主程序(AOSearch.cpp),以下时Lib.h的展现。其中把基本功能里的:1、输出所有选手信息,2、输出每日比赛结果,都封装成方法进行调用。

img

关键代码展示

1、通过四重循环,获得result中获胜人员,比赛场次,以及开始时间的信息

void Lib::FindJson2(string filename) {
string path;
if (filename.find("result") != string::npos) {
    int pos = filename.find("result");
    filename.erase(pos, 6);
    filename.erase(remove(filename.begin(), filename.end(), ' '), filename.end());
  
//    cout << filename<<endl;

    path = "src/data/" + filename+".json";
    
    string dataFromJson;
    ifstream in(path, ifstream::in);
    if (in.is_open()) {
        string line;
        while (getline(in, line))
        {
            dataFromJson.append(line + "\n");
        }
    }
    else {
        datas.push_back("N/A");
        datas.push_back("-----");
    }
    rapidjson::Document d;
    d.Parse(dataFromJson.c_str());
    rapidjson::Value& courts = d["schedule"]["courts"];

    string team_id;//获胜队伍的id
    string player_id1 = "";//第一位获胜个人的id
    string player_id2 = "";//第二位获胜个人的id
    string winner_name = "";//获胜者信息

    for (auto &court : courts.GetArray()) {
        for (auto& session : court["sessions"].GetArray()) {
            for (auto& activity : session["activities"].GetArray()) {
               
                if (!activity.HasMember("teams")) break;
                string abbr = activity["match_status"]["abbr"].GetString();
                if ( abbr._Equal("W/O")) {
                       datas.push_back("W/O");
                       datas.push_back("-----");
                       break;
                }
                string start_time = activity["actual_start_time"].GetString();
                // cout << start_time << endl;
                datas.push_back("time:" + start_time);

                auto& teams = activity["teams"];   // root/schedule/courts/sessions/activities/teams

                //  cout << teams[0]["team_id"] << endl << teams[1]["team_id"] << endl;

                auto &team = teams[0];
                if (team.HasMember("status"))
                {
                    team_id = teams[0]["team_id"].GetString();
                }
                else { team_id = teams[1]["team_id"].GetString(); }

                for (auto &Team : d["teams"].GetArray()) {
                    if (Team["uuid"].GetString() == team_id)
                    {

                        if (Team["players"].GetArray().Size() == 1)
                        {
                            player_id1 = Team["players"][0].GetString();
                            break;
                        }
                        else {
                            player_id1 = Team["players"][0].GetString();
                            player_id2 = Team["players"][1].GetString();
                            break;
                        }
                    }
                }
                for (auto &player : d["players"].GetArray())
                {
                    if (player["uuid"].GetString() == player_id1 || player["uuid"].GetString() == player_id2) {
                        if (player_id2 == "")
                        {
                            //  cout << player["short_name"].asString() << endl;
                            string short_name = player["short_name"].GetString();
                            datas.push_back("winner:" + short_name);
                            winner_name = "";
                            break;
                        }
                        else {
                            if (winner_name == "")
                            {
                                string short_name = player["short_name"].GetString();
                                datas.push_back("winner:" + short_name);
                                winner_name += "winner:" + short_name + " & ";
                            }
                            else {
                                winner_name += player["short_name"].GetString();
                                // cout << winner_name << endl;
                                datas.push_back(winner_name);
                                winner_name = "";
                                break;
                            }
                        }
                    }
                }
                string scores = "score:";//分数
                int times = teams[0]["score"].GetArray().Size();
                for (int i = 0; i < times; i++) {
                    string score1 = teams[0]["score"][i]["game"].GetString();
                    string score2 = teams[1]["score"][i]["game"].GetString();

                    scores += " " + score1 + ":" + score2 + " ";
                    if (i < times - 1) {
                        scores += "|";
                    }
                }
                //   cout << scores << endl;
                datas.push_back(scores);
                datas.push_back("-----");
            }
        }
    }
    
}
else {
        datas.push_back("Error");
        datas.push_back("-----");
    }
  }

2、打开players的数据,直接读取所有成员的有关数据

void Lib::FindJson(string filename) {
string path = "src/data/" + filename + ".json";
string dataFromJson;
ifstream in(path,ifstream::in);
if (in.is_open()) {
    string line;
    while (getline(in,line))
    {
        dataFromJson.append(line + "\n");
    }
}
else {
    cout << "打开失败" << endl;
}
    rapidjson::Document d;
    d.Parse(dataFromJson.c_str());
    rapidjson::Value& players = d["players"];
    for (unsigned int i = 0; i < players.Size(); i++) {
    string name = players[i]["full_name"].GetString(); 
    datas.push_back("full_name:" + name);        
    rapidjson::Value::ConstMemberIterator gender = players[i].FindMember("gender");
    string G = gender->value.GetString();
    if (G._Equal("M")) {
        datas.push_back("gender: male");
    }
    else
    {
        datas.push_back("gender: female");
    }       
    rapidjson::Value& nationality = players[i]["nationality"];
    string nationality_name=nationality["name"].GetString();       
    datas.push_back("nationlity:"+nationality_name);
    datas.push_back("-----");
}

}

3、 将解析出来的数据存入目标文件,如output.txt中

//将解析出来的json的数据写入文件中
void Lib::writeFile(string file,list<string> datas) {
ofstream f(this->output,ios::out);
if (!f.is_open()) {
    cout << "文件查找不到" << endl;
    return;
}
for (list<string>::iterator it = datas.begin(); it != datas.end(); ++it) {
   f<< *it << "\n";
}

f.close();   
}

4、通过input.txt文件中的信息,将每行的内容读入list 中,随后一次解析每行文件的json数据

list <string> Lib::readFile(string file) {
list <string> data; //获得解析input内的数据
    ifstream f(file, ios::in);
    if (!f.is_open()) {
        cout << "文件打开失败" << endl;
        return data;
    }
    string strline;
    /*do
    {
        getline(f, strline);
        data.push_back(strline);           
    }while (getline(f, strline));*/

    while (getline(f, strline)) {
        data.push_back(strline);
    } 
    f.close();             //关闭文件输入流 
    return data;
}

5、通过从文件list获得的数据,一次分配到不同的FindJson中,进行json数据解析

void Lib::getData(list <string> data) { 
for (list<string>::iterator it = data.begin(); it != data.end(); ++it) {
    if (*it == "players")
    {   
        FindJson("players");
    }
    else {
        string s = *it;
        FindJson2(s);
    }
}
}   

性能改进

一开始使用jsoncpp的库进行数据解析,结果发现每次要调用解析json的方法的时候,都要进入文件夹,调用dll的相关方法,导致每次都要花大量的读取时间,

img

之后在对网络上进行查询有无更简单的优化方法时,找到了rapidjson的库,只需要将rapidjson中的include/rapidjson放入文件夹中,便能够调用有关的方法,之后便是修改FindJson方法(获得players的json数据)

img

发现性能有极大的优化以后,我们便修改了关于解析result的FindJson方法

img

极大的减少了时间的花费

单元测试

对于单元测试,我们需要使用vs2022自带的GoogleTest框架进行测试,虽然在这过程中,对于GoogleTest的使用我是一窍不通,但是通过查阅相关的文档和有关资料,我马马虎虎学习了对GoogleTest的使用,然后可能用的不够完美。

img

异常处理

对于异常的处理,主要情况都是文件无法找到从而难以打开,而处理方法是直接抛出
//json数据打不开
if (in.is_open()) {
    string line;
    while (getline(in,line))
    {
        dataFromJson.append(line + "\n");
    }
}
else {
    cout << "打开失败" << endl;
}

//文件input.txt打不开
list <string> data; //获得解析input内的数据
    ifstream f(file, ios::in);
    if (!f.is_open()) {
        cout << "文件打开失败" << endl;
        return data;
}

心得体会

1、通过这次的学习,了解了c++使用json的方法,复习了c++的相关知识。

2、在进行jsoncpp和GoogleTest时候的耗时是最久的,其中jsoncpp是使用cmake将从Github下载下来的zip解析并且生成解决方法,获得dll文件后添加到项目工程下,其次最令我头疼的就是就是关于GoogleTest的使用,我还特意重新建了一个SampleTest文件,进行测试,因此进行的有点困难

3、最后最大的收获,便是更加了解了git的使用方法,对于开发的流程有了更加熟悉的认知

...全文
193 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
郭渊伟 助教 2023-03-11
  • 打赏
  • 举报
回复

性能改进部分很有亮点,赞!

688

社区成员

发帖
与我相关
我的任务
社区描述
2023年福州大学软件工程实践课程W班的教学社区
软件工程团队开发软件构建 高校 福建省·福州市
社区管理员
  • FZU_SE_teacherW
  • 张书旖
  • 郭渊伟
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧