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

222100123姚磊 2024-03-01 14:50:46
这个作业属于哪个课程软件工程实践-2023学年-W班
这个作业要求在哪里软件工程实践第二次作业——个人实战
这个作业的目标①完成对世界游泳锦标赛跳水项目相关数据的收集
②在收集相关数据后实现一个能够对赛事数据进行统计的控制台程序
其他参考文献《构建之法》

目录

  • 1.Gitcode项目地址
  • 2.PSP表格
  • 3.解题思路描述
  • 3.1 获取数据
  • 3.2 解析数据
  • 3.3 输入要求、输出结果
  • 4. 接口设计和实现过程
  • 4.1 接口设计
  • 4.2 实现过程
  • 5. 关键代码展示
  • 6. 性能改进
  • 7. 单元测试
  • 8. 异常处理
  • 9. 心得体会

1.Gitcode项目地址

仓库地址

2.PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划4030
• Estimate• 估计这个任务需要多少时间4030
Development开发12001300
• Analysis• 需求分析 (包括学习新技术)180200
• Design Spec• 生成设计文档2030
• Design Review• 设计复审2025
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)3035
• Design• 具体设计7080
• Coding• 具体编码700750
• Code Review• 代码复审6060
• Test• 测试(自我测试,修改代码,提交修改)120120
Reporting报告4055
• Test Repor• 测试报告2015
• Size Measurement• 计算工作量1010
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划2030
合计12801385

3.解题思路描述

3.1 获取数据

  • 通过作业要求的链接从网页上获取到相关数据,利用网页的开发者模式,获取到运动员和每场比赛结果数据的json文件。

3.2 解析数据

  • 先编写将json文件转换成字符串的函数,接着利用org.json库中的JSONArray和JSONObject来通过对应键值获取到的json字符串进行解析,对照json文件中的格式进行数据的不断获取并存在对应类中方便使用。如果是大括号对应的数据使用JSONObject解析,如果是[]对应的数据使用JSONArray解析。

3.3 输入要求、输出结果

  • 通过命令行输入input.txt文件,读入要求的字符串,接着通过分析字符串判断出对应的情况,编写输出不同信息的函数,包括对不符合条件,编写输出对应的错误信息的函数,无法识别的指令,则输出Error,result后的条件不符合以下要求,则输出N/A,输出均输出到output.txt的文件中。

4. 接口设计和实现过程

4.1 接口设计

  • DWASearch类:
      含有main函数,是程序的入口,其中包括判断输入对应的情况和调用相应功能函数。

  • Player类:
      含有输出运动员需要的信息和对应的方法

  • PlayerDetail类:
      含有输出比赛详细需要的运动员信息和对应的方法

  • PlayerMessage类:
      含有输出比赛决赛需要的运动员信息和对应的方法

  • Lib类:
      包含了所有的静态函数,实现输出比赛决赛信息,比赛详细信息和运动员信息

    /*功    能:输出比赛决赛信息*/
    public static void outputFinalGameResult(String gameName, String data, String outputPath){}
    /*功    能:输出比赛详细信息*/
    public static void outputDetailGameResult(String gameName, String data, String outputPath){}
    /*功    能:将运动员信息输出到output.txt文件中*/
    public static void outputPlayerMessage(String playersPath, String outputPath){}
    
  • LibTest类:
      测试和输出比赛决赛信息、比赛详细信息和运动员信息有关的函数,还包括对输出比赛详细信息函数前后优化对比的函数,具体函数如下:
>/*功    能:测试输出比赛决赛信息函数*/
>public void outputFinalGameResult(){}
>/*功    能:测试输出比赛详细信息函数*/
>public void outputDetailGameResult(){}
>/*功    能:测试输出比赛详细信息函数(优化前)*/
>public void outputDetailGameResultBeforeOptimization(){}
>/*功    能:测试输出运动员信息函数*/
>public void outputPlayerMessage(){}
  • 功能划分
    输出选手信息并加上文件输入输出
    输出决赛每个运动项目结果
    输出比赛详细信息
    input.txt出现多行情况
    处理当输入无法处理的指令中result后的条件不符合要求时输出N/A
    处理当输入无法处理的指令中无法识别的指令时输出Error
    优化代码结构
    添加单元测试代码
    性能改进
    增加博客代码

4.2 实现过程

在这里插入图片描述

5. 关键代码展示

public class Lib {
    static String[] correctGameName = {"women 1m springboard", "women 3m springboard", "women 10m platform", "women 3m synchronised"
            , "women 10m synchronised", "men 1m springboard", "men 3m springboard", "men 10m platform", "men 3m synchronised", "men 10m synchronised"};

    /*功    能:输出比赛决赛信息*/
    /*入口参数:比赛名字,对应比赛的json文件路径,output文件路径*/
    /*返    回:无*/
    public static void outputFinalGameResult(String gameName, String data, String outputPath) {
        if (Arrays.asList(correctGameName).contains(gameName)) {
            ArrayList<PlayerMessage> playerMessageArrayList = ParsePlayerMessage(ReadFile(data));

            try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputPath, true))) {      //向output.txt输出比赛决赛信息
                if (!hasContent(outputPath)) {
                    writer.write("\n");
                }

                for (int i = 0; i < playerMessageArrayList.size(); i++) {

                    if (i != 0) {
                        writer.write("\n" + playerMessageArrayList.get(i) + "\n-----");
                    } else {
                        writer.write(playerMessageArrayList.get(i) + "\n-----");
                    }
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            outputError(outputPath);
        }
    }

    /*功    能:输出比赛详细信息*/
    /*入口参数:比赛名字,对应比赛的json文件路径,output文件路径*/
    /*返    回:无*/
    public static void outputDetailGameResult(String gameName, String data, String outputPath) {
        if (Arrays.asList(correctGameName).contains(gameName)) {

            ArrayList<PlayerDetail> playerDetails = ParsePlayerDetail(ReadFile(data));

            try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputPath, true))) {      //向output.txt输出比赛详细信息
                if (!hasContent(outputPath)) {
                    writer.write("\n");
                }

                for (int i = 0; i < playerDetails.size(); i++) {

                    if (i != 0) {
                        writer.write("\n" + playerDetails.get(i) + "\n-----");
                    } else {
                        writer.write(playerDetails.get(i) + "\n-----");
                    }
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            outputError(outputPath);
        }
    }

    /*功    能:将Error错误信息输出到output.txt文件中*/
    /*入口参数:output文件路径*/
    /*返    回:无*/
    public static void outputError(String outputPath) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputPath, true))) {      //向output.txt输出N/A
            if (!hasContent(outputPath)) {
                writer.write("\n");
            }

            writer.write("N/A" + "\n-----");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*功    能:将运动员信息输出到output.txt文件中*/
    /*入口参数:运动员json文件路径,output文件路径*/
    /*返    回:无*/
    public static void outputPlayerMessage(String playersPath, String outputPath) {
        List<Player> players = ParsePlayer(ReadFile(playersPath));
        
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputPath, true))) {      //向output.txt输出运动员信息
            if (!hasContent(outputPath)) {
                writer.write("\n");
            }

            for (int i = 0; i < players.size(); i++) {

                if (i != 0) {
                    writer.write("\n" + players.get(i) + "\n-----");
                } else {
                    writer.write(players.get(i) + "\n-----");
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*功    能:读取文件*/
    /*入口参数:文件路径*/
    /*返    回:文件的字符串*/
    public static String ReadFile(String path) {
        String str = "";
        File file = new File(path);

        try {
            FileReader fileReader = new FileReader(file);
            Reader reader = new InputStreamReader(new FileInputStream(file), "utf-8");
            int ch = 0;
            StringBuffer stringBuffer = new StringBuffer();

            while ((ch = reader.read()) != -1) {
                stringBuffer.append((char) ch);                                                         //读出文件信息为字符串
            }

            fileReader.close();
            reader.close();
            str = stringBuffer.toString();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return str;
    }

    /*功    能:解析运动员信息的json*/
    /*入口参数:json字符串*/
    /*返    回:运动员列表*/
    public static ArrayList<Player> ParsePlayer(String str) {
        JSONObject jsonObject = new JSONObject(str);
        JSONArray objPlayer = jsonObject.getJSONArray("player");
        ArrayList<Player> players = new ArrayList<>();

        for (int i = 0; i < objPlayer.length(); i++) {

            JSONObject playerOne = objPlayer.getJSONObject(i);                                                            //取出同一个国家运动员信息
            String country = playerOne.getString("CountryName");
            JSONArray sameCountryPlayer = playerOne.getJSONArray("Participations");                                   //将运动员数组取出

            for (int j = 0; j < sameCountryPlayer.length(); j++) {

                JSONObject obj = sameCountryPlayer.getJSONObject(j);                                                       //从运动员数组中取出一个运动员信息
                Player player = new Player();
                String fullName = "";

                player.setCountry(country);
                fullName += obj.getString("PreferredLastName") + " " + obj.getString("PreferredFirstName");       //读出运动员名字
                player.setFullName(fullName);

                if (obj.getInt("Gender") == 0)                                                                         //读出运动员性别
                    player.setGender("Male");
                else
                    player.setGender("Female");

                players.add(player);
            }

        }

        return players;
    }

    /*功    能:解析决赛比赛信息的json*/
    /*入口参数:json字符串*/
    /*返    回:比赛中运动员信息列表*/
    public static ArrayList<PlayerMessage> ParsePlayerMessage(String str) {
        JSONObject jsonObject = new JSONObject(str);
        JSONArray messageArray = jsonObject.getJSONArray("Heats");
        ArrayList<PlayerMessage> playerMessageArrayList = new ArrayList<>();

        JSONObject gameObject = messageArray.getJSONObject(0);                                                //取出决赛比赛信息
        JSONArray gameArray = gameObject.getJSONArray("Results");

        for (int j = 0; j < gameArray.length(); j++) {
            JSONObject playerMessageObject = gameArray.getJSONObject(j);
            JSONArray div = playerMessageObject.getJSONArray("Dives");                                          //取出每次跳水得分数组
            String fullName = playerMessageObject.getString("FullName");                                        //取出运动员名字
            String[] name = fullName.split("/");

            ArrayList<Double> scores = new ArrayList<>();
            PlayerMessage playerMessage = new PlayerMessage();

            for (int n = 0; n < div.length(); n++) {
                scores.add(Double.parseDouble(div.getJSONObject(n).getString("DivePoints")));                   //取出每次跳水得分
            }

            playerMessage.setTotalScore(Double.parseDouble(playerMessageObject.getString("TotalPoints")));      //存入跳水总得分
            playerMessage.setRank(playerMessageObject.getInt("Rank"));                                          //存入跳水排名
            playerMessage.setScore(scores);                                                                          //存入每次跳水得分
            playerMessage.setGameType(gameObject.getString("Name"));                                            //存入final比赛

            if (name.length == 1) {                                                                                  //判断是否为单人项目
                playerMessage.setPlayerName(playerMessageObject.getString("FullName"));
            } else {                                                                                                 //是双人项目
                String player1LastName = name[0].trim();
                String player2LastName = name[1].trim();

                if (player1LastName.compareTo(player2LastName) <= 0) {                                               //名字排序
                    playerMessage.setPlayerName(player1LastName, player2LastName);
                } else {
                    playerMessage.setPlayerName(player2LastName, player1LastName);
                }
            }

            playerMessageArrayList.add(playerMessage);
        }

        return playerMessageArrayList;
    }

    /*功    能:解析比赛信息的json*/
    /*入口参数:json字符串*/
    /*返    回:比赛中运动员信息列表*/
    public static ArrayList<PlayerDetail> ParsePlayerDetail(String str) {
        JSONObject jsonObject = new JSONObject(str);
        JSONArray messageArray = jsonObject.getJSONArray("Heats");
        ArrayList<PlayerDetail> playerDetails = new ArrayList<>();

        for (int i = messageArray.length() - 1; i >= 0; i--) {
            JSONObject gameObject = messageArray.getJSONObject(i);
            JSONArray gameArray = gameObject.getJSONArray("Results");                                                           //每个运动员的得分
            String gameType = gameObject.getString("Name");                                                                     //取出比赛是final、Semifinal还是Preliminary
            int nowPlayerIndex = 0;

            for (int j = 0; j < gameArray.length(); j++) {                                                                          //从第一次比赛开始读
                JSONObject playerMessageObject = gameArray.getJSONObject(j);
                JSONArray div = playerMessageObject.getJSONArray("Dives");                                                     //取出每次跳水得分数组
                String fullName = playerMessageObject.getString("FullName");                                                   //取出运动员名字
                String[] name = fullName.split("/");

                ArrayList<Double> scores = new ArrayList<>();
                PlayerDetail playerDetail = new PlayerDetail();

                for (int n = 0; n < div.length(); n++) {
                    scores.add(Double.parseDouble(div.getJSONObject(n).getString("DivePoints")));                               //取出每次跳水得分
                }

                if (i == messageArray.length() - 1) {                                                                               //判断是否为第一次比赛,是的话存入名字
                    if (name.length == 1) {                                                                                         //判断是否为单人项目
                        playerDetail.setFullName(playerMessageObject.getString("FullName"));
                    } else {                                                                                                        //是双人项目
                        String player1LastName = name[0].trim();
                        String player2LastName = name[1].trim();

                        if (player1LastName.compareTo(player2LastName) <= 0)                                                        //名字排序
                            playerDetail.setFullName(player1LastName, player2LastName);
                        else
                            playerDetail.setFullName(player2LastName, player1LastName);
                    }
                    playerDetails.add(playerDetail);
                }

                for (PlayerDetail playerDetail1 : playerDetails) {                                                                  //找出当前取出的运动员在队列中的下标
                    if (name.length == 1) {
                        if (playerDetail1.getFullName().equals(playerMessageObject.getString("FullName")))
                            nowPlayerIndex = playerDetails.indexOf(playerDetail1);
                    } else {
                        String player1LastName = name[0].trim();
                        String player2LastName = name[1].trim();
                        String playerFullName = "";

                        if (player1LastName.compareTo(player2LastName) <= 0)
                            playerFullName = player1LastName + " & " + player2LastName;
                        else
                            playerFullName = player2LastName + " & " + player1LastName;

                        if (playerDetail1.getFullName().equals(playerFullName))
                            nowPlayerIndex = playerDetails.indexOf(playerDetail1);
                    }
                }

                playerDetail = playerDetails.get(nowPlayerIndex);

                if (gameType.equals("Preliminary")) {                                                                                 //判断是Preliminary比赛类型,存入相关信息
                    playerDetail.setPreliminaryTotalScore(Double.parseDouble(playerMessageObject.getString("TotalPoints")));
                    playerDetail.setPreliminaryRank(Integer.toString(playerMessageObject.getInt("Rank")));
                    playerDetail.setPreliminaryScores(scores);
                } else if (gameType.equals("Semifinal")) {                                                                             //判断是Semifinal比赛类型,存入相关信息
                    playerDetail.setSemifinalTotalScore(Double.parseDouble(playerMessageObject.getString("TotalPoints")));
                    playerDetail.setSemifinalRank(Integer.toString(playerMessageObject.getInt("Rank")));
                    playerDetail.setSemifinalScores(scores);
                } else {                                                                                                               //判断是final比赛类型,存入相关信息
                    playerDetail.setFinalTotalScore(Double.parseDouble(playerMessageObject.getString("TotalPoints")));
                    playerDetail.setFinalRank(Integer.toString(playerMessageObject.getInt("Rank")));
                    playerDetail.setFinalScores(scores);
                }

                playerDetails.set(nowPlayerIndex, playerDetail);
            }
        }


        return playerDetails;
    }

    }

6. 性能改进

  • 在实现对比赛详细信息展示的功能中,我刚开始使用了Map数据结构,以运动员名字为键值,运动员详细信息为值来存入信息,然后在返回时再变成ArrayList的数据结构。之后改用直接以ArrayList存入信息,然后遍历整个队列来获取当前正在存入的运动员对应索引,从而进行修改运动员比赛信息,发现直接用ArrayList的数据结构这个函数运行时间变短。

    在这里插入图片描述


    如图,outputDetailGameResultBeforeOptimization函数是使用了Map数据结构,而outputDetail
    GameResult是直接使用ArrayList数据结构,很明显的看出直接使用ArrayList数据结构会缩短代码运行时间。分析原因可能是因为分析的数据量较少,直接遍历的时间花费比使用按键存取再转换来的少。
  • 还有想到一个将String的字符串拼接改成先用StringBuffer来进行改进,发现两个所用时间没有很明显的区别,可能是因为拼接的次数很少,看不出区别,因此就没有改用StringBuffer来拼接。

7. 单元测试

  • 在单元测试中,我测试了输出比赛决赛信息的函数outputFinalGameResult,输出比赛详细信息的函数outputDetailGameResult和输出运动员信息的函数outputPlayerMessage,其中用到的测试用例有:
        result (result后加空格)
        result(result后没加空格)
        result women 3m springboard
        result detail
        result women 3m springboard detail
        players
@Test
    /*功    能:测试输出比赛决赛信息函数*/
    /*入口参数:无*/
    /*返    回:无*/
    public void outputFinalGameResult() {

        String outputPath=new File(System.getProperty("user.dir")) + File.separator + "src" + File.separator + "outputFinalGameResultTest.txt";

        Lib.createClearFile(outputPath);
        //在主函数中会判断出如果输入有result而没有detail的话是利用Lib中outputFinalGameResult函数来判断输出结果的,因此在这个函数中进行单元测试

        //输入是result 时,后面有空格,传入函数的gameName应该是空格,输出结果应该是N/A
        Lib.outputFinalGameResult(" ", new File(System.getProperty("user.dir")) + File.separator + "src" + File.separator + "data" + " .json",outputPath );

        //输入是result时,后面没有其他字符,传入函数的gameName应该是空,输出结果应该是N/A
        Lib.outputFinalGameResult("", new File(System.getProperty("user.dir")) + File.separator + "src" + File.separator + "data" + ".json", outputPath);

        //输入是result women 3m springboard,传入函数的gameName应该是women 3m springboard,输出结果应该是比赛结果
        Lib.outputFinalGameResult("women 3m springboard", new File(System.getProperty("user.dir")) + File.separator + "src" + File.separator + "data" + File.separator + "women 3m springboard.json", outputPath);

        //测试
        String result=Lib.ReadFile(outputPath);
        String expectation="N/A\n" +
                "-----\n" +
                "N/A\n" +
                "-----\n" +
                "Full Name:BENT-ASHMEIL Desharne\n" +
                "Rank:1\n" +
                "Score:61.50 + 63.55 + 66.00 + 55.50 + 45.00 = 291.55\n" +
                "-----\n" +
                "Full Name:MULLER Jette\n" +
                "Rank:2\n" +
                "Score:63.00 + 63.00 + 61.50 + 40.30 + 60.00 = 287.80\n" +
                "-----";

        Assert.assertTrue(result.startsWith(expectation));
    }
    
    @Test
    /*功    能:测试输出比赛详细信息函数*/
    /*入口参数:无*/
    /*返    回:无*/
    public void outputDetailGameResult() {
        String outputPath=new File(System.getProperty("user.dir")) + File.separator + "src" + File.separator + "outputDetailGameResultTest.txt";

        Lib.createClearFile(outputPath);
        //在主函数中会判断出如果输入有result且有detail的话是利用Lib中outputDetailGameResult函数来判断输出结果的,因此在这个函数中进行单元测试

        //输入是result detail时,result后有空格,传入函数的gameName应该是空格,输出结果应该是N/A
        Lib.outputDetailGameResult(" ", new File(System.getProperty("user.dir")) + File.separator + "src" + File.separator + "data" + " .json", outputPath);

        //输入是result women 3m springboard detail,传入函数的gameName应该是women 3m springboard,输出结果应该是比赛结果
        Lib.outputDetailGameResult("women 3m springboard", new File(System.getProperty("user.dir")) + File.separator + "src" + File.separator + "data" + File.separator + "women 3m springboard.json", outputPath);

        //测试
        String result=Lib.ReadFile(outputPath);
        String expectation="N/A\n" +
                "-----\n" +
                "Full Name:HENTSCHEL Lena\n" +
                "Rank:1 | 4 | 3\n" +
                "Preliminary Score:54.00 + 63.55 + 48.00 + 60.00 + 51.00 = 276.55\n" +
                "Semifinal Score:52.50 + 57.35 + 55.50 + 49.50 + 57.00 = 271.85\n" +
                "Final Score:58.50 + 57.35 + 60.00 + 45.00 + 63.00 = 283.85\n" +
                "-----\n" +
                "Full Name:MULLER Jette\n" +
                "Rank:2 | 8 | 2\n" +
                "Preliminary Score:57.00 + 51.00 + 55.50 + 51.15 + 52.50 = 267.15\n" +
                "Semifinal Score:57.00 + 51.00 + 55.50 + 31.00 + 54.00 = 248.50\n" +
                "Final Score:63.00 + 63.00 + 61.50 + 40.30 + 60.00 = 287.80\n" +
                "-----\n" +
                "Full Name:WILSON Aimee\n" +
                "Rank:3 | 2 | 4\n" +
                "Preliminary Score:54.00 + 52.70 + 54.00 + 49.50 + 55.50 = 265.70\n" +
                "Semifinal Score:52.50 + 55.80 + 57.00 + 52.50 + 58.50 = 276.30\n" +
                "Final Score:48.00 + 62.00 + 52.50 + 49.50 + 64.50 = 276.50\n" +
                "-----";

        Assert.assertTrue(result.startsWith(expectation));
    }
    
    @Test
    /*功    能:测试输出运动员信息函数*/
    /*入口参数:无*/
    /*返    回:无*/
    public void outputPlayerMessage() {

        String outputPath=new File(System.getProperty("user.dir")) + File.separator + "src" + File.separator + "outputPlayerMessageTest.txt";

        Lib.createClearFile(outputPath);

        //输出运动员信息
        Lib.outputPlayerMessage(new File(System.getProperty("user.dir")) + File.separator + "src" + File.separator + "data\\player.json",outputPath);

        //测试
        String result=Lib.ReadFile(outputPath);
        String expectation="Full Name:HART Alexander\n" +
                "Gender:Male\n" +
                "Country:Austria\n" +
                "-----\n" +
                "Full Name:LOTFI Dariush\n" +
                "Gender:Male\n" +
                "Country:Austria\n" +
                "-----\n" +
                "Full Name:SCHALLER Nikolaj\n" +
                "Gender:Male\n" +
                "Country:Austria\n" +
                "-----\n" +
                "Full Name:ABRAMOWICZ Tazman\n" +
                "Gender:Male\n" +
                "Country:Canada\n" +
                "-----";

        Assert.assertTrue(result.startsWith(expectation));
    }
  • 总的测试用例有
    result (result后加空格)
    result(result后没加空格)
    result detail
    result women 3m springboard
    result women 3m springboard detail
    result Women 3m springboard
    resultwomen 3m springboard
    player
    Players
    players
    result men 3m synchronised
    result men 3m synchronised detail
    input.txt文件中为空
  • 代码覆盖率

    在这里插入图片描述


    覆盖率优化方法:
        1.尽可能设计出边界的测试用例,完善测试用例。
        2.删除一些没有用的代码。
        3.减少判断分支。

8. 异常处理

  • 对于输出文件可能不存在或者是里面有内容需要清空的情况
>    /*功    能:文件不存在创建文件,文件存在将文件内容清空*/
    /*入口参数:文件路径*/
    /*返    回:无*/
    public static void createClearFile(String path) {
        File outputFile = new File(path);

        try {
            if (!outputFile.exists()) {
                outputFile.createNewFile();
            } else {
                FileWriter fileWriter = new FileWriter(path);
                fileWriter.write("");
                fileWriter.close();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
  • 读文件时处理异常
  if (inputIsEmpty) {                                                                                                                   //输入字符串为空的情况
         try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputPath, true))) {
             if (!Lib.hasContent(outputPath)) {
                 writer.write("\n");
             }
             writer.write("Error" + "\n-----");

         } catch (IOException e) {
             e.printStackTrace();
         }
     }
  • 对于输入的指令result后面不符合规则输出N/A
  /*功    能:将Error错误信息输出到output.txt文件中*/
 /*入口参数:output文件路径*/
 /*返    回:无*/
 public static void outputError(String outputPath) {
     try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputPath, true))) {      //向output.txt输出N/A
         if (!hasContent(outputPath)) {
             writer.write("\n");
         }

         writer.write("N/A" + "\n-----");

     } catch (IOException e) {
         e.printStackTrace();
     }
 }
  • 对于输入的指令无法识别的情况输出Error
try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputPath, true))) {
                        //输入无法识别的指令
                        if (!Lib.hasContent(outputPath)) {
                            writer.write("\n");
                        }
                        writer.write("Error" + "\n-----");

                    } catch (IOException e) {
                        e.printStackTrace();
                    }

9. 心得体会

  • 在编写过程中,首先对于应该获取怎么样的数据让我不知所措,在查阅相关资料和同学的帮助下,发现可以使用网页上的json数据并利用相关方法对数据进行解析。
  • 在编写代码前应该做好大概的设计框架,想到哪写到哪容易出现大规模修改代码的情况。
  • 在面对自己不是很熟悉的知识时,不要出现排斥心理,要主动投入的进行学习。
...全文
373 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
助教杨蕊蘭 助教 2024-03-13
  • 打赏
  • 举报
回复

做的不错~继续努力!

内容概要:本文系统研究了基于Wilcoxon Rank-Sum检验的多算法性能统计分析方法,重点对比Bonferroni与Benjamini–Hochberg(BH)两种多重检验校正策略在多目标优化算法性能评估中的表现。实验采用超体积(HV)指标衡量算法性能,先通过3种算法的小样本(5次重复)实验进行初步分析,再扩展至8种算法的大样本(100次重复)实验,全面比较原始p值、Bonferroni校正和BH校正下的显著性差异结果。结果显示,在小样本场景中两种校正方法结论一致,均表明算法A显著优于B和C;而在大规模两两对比(28组)场景中,BH校正因采用动态阈值策略,具有更高的统计功效,能有效识别被Bonferroni校正漏检的真实性能差异,更适合多算法性能对比的探索性研究。; 适合人群:从事智能优化算法、进化计算、机器学习等领域的科研人员及具备一定统计学基础的研究生或工程师。; 使用场景及目标:①解决多算法两两比较中的多重假设检验问题;②选择合适的统计校正方法以平衡假阳性控制与检验功效;③提升算法性能比较结果的可靠性与可复现性; 阅读建议:建议结合文中提供的具体计算过程与大样本实验数据表深入理解Wilcoxon检验及两类校正机制的差异,尤其关注BH校正在高维多重检验中的优势,实际应用中优先选用BH校正以获得更稳健、敏感的统计结论。
内容概要:本文针对含多微电网租赁共享储能的配电网系统,提出了一种基于博弈论的优化调度模型,并提供了完整的Matlab代码实现。研究聚焦于多个微电网主体在共享储能租赁机制下的竞争与协作关系,通过构建非合作博弈模型,刻画各微电网在能量调度、储能租用决策等方面的策略互动。模型充分考虑了分布式能源出力不确定性、负荷需求波动、储能运行约束及电网交互功率限制等多重因素,旨在实现各微电网个体运行成本最小化的同时,保障配电网整体运行的经济性与稳定性。通过算例仿真验证了所提博弈模型的良好收敛性与有效性,结果表明该方法能够有效激励微电网合理参与储能共享,提升系统整体资源利用效率与运行灵活性。; 适合人群:具备一定电力系统基础知识和Matlab编程能力,从事微电网、分布式能源、共享储能或博弈论应用研究的研究生、科研人员及工程技术人员。; 使用场景及目标:① 学习和复现多微电网与共享储能协同优化调度的博弈模型;② 理解非合作博弈在电力系统分布式优化中的建模与求解方法;③ 获取可用于二次开发的Matlab代码框架,应用于相关领域的科研或项目开发。; 阅读建议:在学习过程中应结合博弈论基本概念理解模型构建逻辑,重点关注目标函数与约束条件的物理意义,并利用提供的Matlab代码进行仿真调试,通过修改参数观察博弈均衡过程,以深入掌握模型特性。
内容概要:本文围绕有限控制集模型预测控制(FCS-MPC)下三相并网逆变器的运行特性与并网性能展开深入研究,重点通过Simulink仿真实现对系统动态响应、稳态精度及抗扰能力的全面评估。研究构建了完整的并网逆变器数学模型与仿真系统,涵盖主电路拓扑、控制算法设计及电网交互模块,并在电网电压对称、不平衡及动态波动等多种典型工况下进行仿真验证。文中系统分析了FCS-MPC在电流跟踪精度、功率响应速度和系统稳定性方面的优异表现,阐明其通过滚动优化与有限候选电压矢量选择实现高性能控制的内在机制。相比传统PI控制等方法,FCS-MPC展现出无需调参、响应迅速、多目标灵活优化等优势,尤其在复杂电网环境下具有更强的适应性与鲁棒性,为高比例新能源接入背景下的高性能并网控制提供了有效的技术路径。; 适合人群:具备电力电子、自动控制或新能源并网等相关专业知识背景,从事科研工作、工程仿真开发或处于研究生及以上学习阶段的技术人员与研究人员。; 使用场景及目标:①掌握有限控制集模型预测控制在三相并网逆变器中的建模与实现方法;②理解FCS-MPC在电网扰动下的动态响应机制与性能优势;③应用于新能源发电系统仿真、逆变器先进控制策略设计与优化等科研或工程项目中。; 阅读建议:建议结合Simulink仿真平台动手复现模型,重点关注控制算法与主电路的接口逻辑,配合不同工况设置进行仿真测试,深入理解FCS-MPC的预测机制与性能表现。

315

社区成员

发帖
与我相关
我的任务
社区描述
福州大学的软件工程实践-2023学年-W班
软件工程需求分析结对编程 高校 福建省·福州市
社区管理员
  • FZU_SE_teacherW
  • Pity·Monster
  • 助教张富源
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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