/**
   * This method is responsible for retrieving MM, list of RegistrantInfo and list of SubmissionInfo
   * given round id, pageSize, pageNumber, sortingOrder, sortingField
   *
   * @return a <code>String</code> that represent the state of execute result.
   * @throws Exception if any error occurred.
   */
  public String execute() throws Exception {
    final String signature = CLASS_NAME + "#execute()";
    try {
      if (projectId <= 0) {
        throw new DirectException("project less than 0 or not defined.");
      }

      TCSubject currentUser = DirectUtils.getTCSubjectFromSession();
      softwareCompetition =
          contestServiceFacade.getSoftwareContestByProjectId(
              DirectStrutsActionsHelper.getTCSubjectFromSession(), projectId);

      // Get the round id from the project info.
      String roundIdStr = softwareCompetition.getProjectHeader().getProperty("Marathon Match Id");

      hasRoundId = !(roundIdStr == null);

      viewData = new MMResultsInfoDTO();

      if (hasRoundId) {
        viewData.setRoundId(Long.valueOf(roundIdStr));
      }

      // If the contest don't have the round id or the contest is a active contest then throw an
      // exception.
      if (!hasRoundId
          || MarathonMatchHelper.isMarathonMatchActive(
              viewData.getRoundId(), marathonMatchAnalyticsService)) {
        throw new Exception("The contest is either don't have round id or is an active contest");
      }

      MarathonMatchHelper.getMarathonMatchDetails(
          viewData.getRoundId().toString(),
          marathonMatchAnalyticsService,
          timelineInterval,
          viewData);

      // Get the common data for contest page.
      MarathonMatchHelper.getCommonData(
          projectId,
          currentUser,
          softwareCompetition,
          viewData,
          contestServiceFacade,
          getSessionData());

      if (type == null) {
        // results page.
        viewResults();
      } else if (type.equals(RESULT_DETAIL)) {
        // result detail page.
        viewSystemTestResults();
      }

      return SUCCESS;
    } catch (Exception e) {
      LoggingWrapperUtility.logException(logger, signature, e);
      throw new Exception("Error when executing action : " + getAction() + " : " + e.getMessage());
    }
  }
  /**
   * Handle the view system test results request.
   *
   * @throws MarathonMatchAnalyticsServiceException if any error occurred.
   * @since 1.1
   */
  private void viewSystemTestResults() throws Exception {
    SystemTestResourceWrapper systemTestResourceWrapper =
        marathonMatchAnalyticsService.getSystemTests(
            viewData.getRoundId(),
            null,
            sr,
            stc,
            "score",
            "desc",
            MarathonMatchHelper.ACCESS_TOKEN);
    if (systemTestResourceWrapper.getItems() != null
        && systemTestResourceWrapper.getItems().size() != 0) {
      viewData.setCompetitorsTestCases(new ArrayList<TestCaseSubmissionInfo>());
      for (SystemTestResource systemTestResource : systemTestResourceWrapper.getItems()) {
        TestCaseSubmissionInfo competitorTestCases = new TestCaseSubmissionInfo();
        competitorTestCases.setTestCases(new ArrayList<TestCaseInfo>());

        for (TestCaseResource testCase : systemTestResource.getTestCases()) {
          TestCaseInfo testCaseInfo = new TestCaseInfo();
          testCaseInfo.setTestCaseId(testCase.getTestCaseId());
          testCaseInfo.setTestCaseScore(testCase.getScore());
          competitorTestCases.getTestCases().add(testCaseInfo);
        }
        competitorTestCases.setHandle(systemTestResource.getHandleName());
        competitorTestCases.setUserId(Long.valueOf(systemTestResource.getHandleId()));
        competitorTestCases.setFinalScore(systemTestResource.getScore());
        viewData.getCompetitorsTestCases().add(competitorTestCases);
      }
      viewData.setTestCasesStartNumber(systemTestResourceWrapper.getTestCasesStartNumber());
      // TODO: Due to the API bug, this test statement have to be added.
      viewData.setTestCasesEndNumber(
          systemTestResourceWrapper.getTestCasesEndNumber()
                      - systemTestResourceWrapper.getTestCasesStartNumber()
                  == 9
              ? systemTestResourceWrapper.getTestCasesEndNumber() - 1
              : systemTestResourceWrapper.getTestCasesEndNumber());
      viewData.setTestCasesCount(systemTestResourceWrapper.getTestCasesCount());
      viewData.setCodersStartNumber(systemTestResourceWrapper.getCodersStartNumber());
      // TODO: Due to the API bug, this test statement have to be added.
      viewData.setCodersEndNumber(
          systemTestResourceWrapper.getCodersEndNumber()
                      - systemTestResourceWrapper.getCodersStartNumber()
                  == 39
              ? systemTestResourceWrapper.getCodersEndNumber() - 1
              : systemTestResourceWrapper.getCodersEndNumber());
      viewData.setCodersCount(systemTestResourceWrapper.getCodersCount());
    } else {
      ServletActionContext.getRequest()
          .setAttribute("errorPageMessage", systemTestResourceWrapper.getMessage());
      throw new Exception("The system test cases result is empty");
    }
  }
  /**
   * Calculate the results graph data. The graph includes final rank graph and final vs provisional
   * score graph.
   *
   * @param resultInfos the results
   */
  private void calculateResultsGraphData(List<ResultInfo> resultInfos) {
    // Sort the results info by final score.
    Collections.sort(
        resultInfos,
        new Comparator<ResultInfo>() {
          public int compare(ResultInfo resultInfo, ResultInfo resultInfo2) {
            if (resultInfo.getFinalRank() < resultInfo2.getFinalRank()) {
              return 0;
            }
            if (resultInfo.getFinalRank() == resultInfo2.getFinalRank()) {
              return String.CASE_INSENSITIVE_ORDER.compare(
                  resultInfo.getHandle(), resultInfo2.getHandle());
            }
            return 1;
          }
        });
    ObjectMapper objectMapper = new ObjectMapper();
    ObjectNode finalScoreRankingData = objectMapper.createObjectNode();
    ObjectNode finalVsProvisionalScoreData = objectMapper.createObjectNode();
    ArrayNode rating = objectMapper.createArrayNode();
    ArrayNode score = objectMapper.createArrayNode();
    for (ResultInfo result : resultInfos) {
      ObjectNode finalScoreNode = objectMapper.createObjectNode();
      finalScoreNode.put("handle", result.getHandle());
      finalScoreNode.put("number", result.getFinalScore());
      finalScoreNode.put("rank", result.getFinalRank());
      rating.add(finalScoreNode);

      ObjectNode finalProvisionalScoreNode = objectMapper.createObjectNode();
      finalProvisionalScoreNode.put("handle", result.getHandle());
      finalProvisionalScoreNode.put("finalScore", result.getFinalScore());
      finalProvisionalScoreNode.put("provisionalScore", result.getProvisionalScore());
      score.add(finalProvisionalScoreNode);
    }
    finalScoreRankingData.put("rating", rating);
    finalVsProvisionalScoreData.put("score", score);

    viewData.setFinalScoreRankingData(finalScoreRankingData.toString());
    viewData.setFinalVsProvisionalScoreData(finalVsProvisionalScoreData.toString());
  }
  /**
   * This method will handle the request to results page.
   *
   * @throws MarathonMatchAnalyticsServiceException if any error occurred.
   */
  private void viewResults() throws MarathonMatchAnalyticsServiceException {
    SearchResult<MatchResultResource> matchResults =
        marathonMatchAnalyticsService.getMatchResults(
            viewData.getRoundId(),
            Integer.MAX_VALUE,
            1,
            "desc",
            "finalScore",
            MarathonMatchHelper.ACCESS_TOKEN);

    List<ResultInfo> resultInfos = convertResults(matchResults);

    // Sort the results info by provisional score and set the provisional rank.
    Collections.sort(
        resultInfos,
        new Comparator<ResultInfo>() {
          public int compare(ResultInfo resultInfo, ResultInfo resultInfo2) {
            if (resultInfo.getProvisionalScore() != null
                && resultInfo2.getProvisionalScore() != null) {
              if (resultInfo.getProvisionalScore() < resultInfo2.getProvisionalScore()) {
                return 1;
              }
              if (resultInfo.getProvisionalScore().equals(resultInfo2.getProvisionalScore())) {
                return String.CASE_INSENSITIVE_ORDER.compare(
                    resultInfo.getHandle(), resultInfo2.getHandle());
              }
            }
            return 0;
          }
        });
    for (ResultInfo r : resultInfos) {
      r.setProvisionalRank(resultInfos.indexOf(r) + 1);
    }
    viewData.setResults(resultInfos);

    // calculate the results graph data.
    calculateResultsGraphData(resultInfos);
  }