private void ExportInfo(RanklistResponse response, string outFile, List <Problem> orderedProblems)
        {
            Debug.Assert(response.Contest.ContestTimeSpan.Start != null,
                         "response.Contest.ContestTimeSpan.Start != null");
            Debug.Assert(response.Contest.ContestTimeSpan.End != null, "response.Contest.ContestTimeSpan.End != null");

            var beginTimeUtc   = DateTimeOffset.FromUnixTimeSeconds(response.Contest.ContestTimeSpan.Start.Value);
            var beginTimeLocal = beginTimeUtc.ToLocalTime();
            var length         = TimeSpan.FromSeconds(response.Contest.ContestTimeSpan.End.Value -
                                                      response.Contest.ContestTimeSpan.Start.Value);

            var contents = new List <string>
            {
                $"Title: CodeChef {response.Contest.DisplayName}",
                $"Begin Time: {beginTimeLocal:yyyy-MM-dd HH:mm:ss}",
                $"Length: {length:c}",
                "Rank rule: Customized",
                "Total penalty: Sum",
                $"Penalty(s): {_penaltyTime.TotalSeconds}",
                "Partial Score: Disable",
                $"Description: CodeChef contest {response.Contest.DisplayName} ({response.Contest.ContestCode}) as it " +
                "was originally held. Problems are in the order they are displayed in the CodeChef ranklist, not " +
                "necessarily in the order of difficulty. Only problems that were rated for this division are included. "
            };

            Debug.Assert(response.TotalItems != null, "response.TotalItems != null");
            if (response.Participants.Count > MaxParticipantCount)
            {
                switch (_overflowBehavior)
                {
                case VjudgeOverflowBehavior.Sample:
                    contents.Add(
                        "The ranklist is a RANDOM SAMPLE of all participants. The actual number of participants was " +
                        $"{response.TotalItems.Value}, some {MaxParticipantCount} are shown.");
                    break;

                case VjudgeOverflowBehavior.Truncate:
                    contents.Add("The ranklist is TRUNCATED. The actual number of participants was " +
                                 $"{response.TotalItems.Value}, top {MaxParticipantCount} are shown.");
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(_overflowBehavior));
                }
            }

            contents.Add(string.Empty);
            contents.Add("Enter problems in THIS order:");
            foreach (var problem in orderedProblems)
            {
                contents.Add($"{problem.Code} | {problem.DisplayName}");
            }

            File.WriteAllLines(outFile, contents, Encoding.UTF8);
        }
        public void Export(RanklistResponse response, string dirPath)
        {
            var unscoredProblems = new HashSet <string>(response.Contest.UnscoredProblems);
            var scoredProblems   = response.Problems
                                   .Where(problem => !unscoredProblems.Contains(problem.Code)).ToList();
            var problemColumns = new Dictionary <string, int>();

            for (var i = 0; i < scoredProblems.Count; i++)
            {
                problemColumns[scoredProblems[i].Code] = i + 2;
            }

            ExportInfo(response, Path.Combine(dirPath, "info.txt"), scoredProblems);
            ExportXls(response, Path.Combine(dirPath, "ranklist.xlsx"), problemColumns);
        }
        private void ExportXls(RanklistResponse response, string outFile, IDictionary <string, int> problemColumns)
        {
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
            using var excelPackage      = new ExcelPackage();
            var worksheet = excelPackage.Workbook.Worksheets.Add("ranklist");

            var maybeReducedList = ReduceParticipantList(response.Participants);

            for (var i = 0; i < maybeReducedList.Count; i++)
            {
                ExportParticipant(worksheet, i + 1, maybeReducedList[i], problemColumns);
            }

            excelPackage.SaveAs(new FileInfo(outFile));
        }