content: /**
   * OWASP Benchmark Project
   *
   * <p>This file is part of the Open Web Application Security Project (OWASP) Benchmark Project For
   * details, please see <a
   * href="https://owasp.org/www-project-benchmark/">https://owasp.org/www-project-benchmark/</a>.
   *
   * <p>The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms
   * of the GNU General Public License as published by the Free Software Foundation, version 2.
   *
   * <p>The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY
   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
   * PURPOSE. See the GNU General Public License for more details.
   *
   * @author Sascha Knoop
   * @created 2024
   */
  package com.alipay.xast.score.report.html;
  
  import com.alipay.xast.score.CategoryResults;
  import com.alipay.xast.score.Configuration;
  import com.alipay.xast.score.TP_FN_TN_FP_Counts;
  import com.alipay.xast.score.Tool;
  import com.alipay.xast.score.ToolResults;
  
  import java.util.Map;
  import java.util.Set;
  
  import static com.alipay.xast.score.report.Formats.fourDecimalPlacesNumber;
  import static com.alipay.xast.score.report.Formats.twoDecimalPlacesPercentage;
  
  /** Vulnerability stats table that goes at the bottom of each vulnerability category page. */
  public class VulnerabilityStatsTable {
  
      private final Configuration config;
      private final String testSuite;
      private final Set<Tool> tools;
  
      public VulnerabilityStatsTable(Configuration config, String testSuite, Set<Tool> tools) {
          this.config = config;
          this.testSuite = testSuite;
          this.tools = tools;
      }
  
      public String generateFor(String category) {
          HtmlStringBuilder htmlBuilder = new HtmlStringBuilder();
  
          htmlBuilder.beginTable("table");
  
          addHeaderTo(htmlBuilder);
  
          tools.stream()
                  .filter(tool -> !(config.showAveOnlyMode && tool.isCommercial()))
                  .forEach(tool -> appendRowTo(htmlBuilder, tool, category));
  
          htmlBuilder.endTable();
  
          return htmlBuilder.toString();
      }
  
      private void addHeaderTo(HtmlStringBuilder htmlBuilder) {
          htmlBuilder.beginTr();
          htmlBuilder.th("Tool");
          htmlBuilder.th("Type");
  
          if (config.mixedMode) {
              htmlBuilder.th(testSuite + " Version");
          }
  
          htmlBuilder.th("TP");
          htmlBuilder.th("FN");
          htmlBuilder.th("TN");
          htmlBuilder.th("FP");
          htmlBuilder.th("Total");
  
          if (config.includePrecision) {
              htmlBuilder.th("Precision");
              htmlBuilder.th("F-score");
          }
  
          htmlBuilder.th("${tprlabel}");
          htmlBuilder.th("FPR");
          htmlBuilder.th("Score");
          htmlBuilder.endTr();
      }
  
      private void appendRowTo(HtmlStringBuilder htmlBuilder, Tool tool, String category) {
          ToolResults toolResults = tool.getOverallResults();
          Map<String, TP_FN_TN_FP_Counts> scores = tool.getScores();
          TP_FN_TN_FP_Counts c = scores.get(category);
          CategoryResults categoryResults = toolResults.getCategoryResults(category);
  
          htmlBuilder.beginTr(cssClassFor(categoryResults));
          htmlBuilder.td(tool.getToolNameAndVersion());
          htmlBuilder.td(tool.getToolType().name());
  
          if (config.mixedMode) {
              htmlBuilder.td(tool.getTestSuiteVersion());
          }
  
          htmlBuilder.td(c.tp);
          htmlBuilder.td(c.fn);
          htmlBuilder.td(c.tn);
          htmlBuilder.td(c.fp);
          htmlBuilder.td(categoryResults.totalTestCases);
  
          if (config.includePrecision) {
              htmlBuilder.td(twoDecimalPlacesPercentage.format(categoryResults.precision));
              htmlBuilder.td(fourDecimalPlacesNumber.format(categoryResults.fscore));
          }
  
          htmlBuilder.td(twoDecimalPlacesPercentage.format(categoryResults.truePositiveRate));
          htmlBuilder.td(twoDecimalPlacesPercentage.format(categoryResults.falsePositiveRate));
          htmlBuilder.td(twoDecimalPlacesPercentage.format(categoryResults.score));
          htmlBuilder.endTr();
      }
  
      private String cssClassFor(CategoryResults categoryResults) {
          String cssClass = null;
  
          if (isDanger(categoryResults)) {
              cssClass = "danger";
          } else if (isSuccess(categoryResults)) {
              cssClass = "success";
          }
  
          return cssClass;
      }
  
      private boolean isSuccess(CategoryResults categoryResults) {
          return categoryResults.truePositiveRate > .7 && categoryResults.falsePositiveRate < .3;
      }
  
      private boolean isDanger(CategoryResults categoryResults) {
          return Math.abs(categoryResults.truePositiveRate - categoryResults.falsePositiveRate) < .1;
      }
  }
  