Esempio n. 1
0
        public async Task <ActionResult <Scoreboard> > OnGet(int cid, bool @public,
                                                             [FromServices] ITeamStore store)
        {
            if (!Contest.StartTime.HasValue)
            {
                return(null);
            }
            var scb = await store.LoadScoreboardAsync(cid);

            var affs = await store.ListAffiliationAsync(cid);

            var orgs = await store.ListCategoryAsync(cid, false);

            var probs = Problems;

            var board = new FullBoardViewModel
            {
                RankCache    = scb.Data.Values,
                UpdateTime   = scb.RefreshTime,
                Problems     = probs,
                IsPublic     = @public,
                Categories   = orgs,
                Contest      = Contest,
                Affiliations = affs,
            };

            var opt = new int[probs.Length];

            for (int i = 0; i < probs.Length; i++)
            {
                opt[i] = i;
            }

            var go = board
                     .SelectMany(a => a)
                     .Select(t => new Scoreboard.Row
            {
                rank     = t.Rank.Value,
                team_id  = $"{t.TeamId}",
                score    = new Scoreboard.Score(t.Points, t.Penalty),
                problems = opt.Select(i => MakeProblem(t.Problems[i], probs[i]))
            });

            return(new Scoreboard
            {
                time = Contest.StartTime.Value,
                contest_time = DateTimeOffset.Now - Contest.StartTime.Value,
                event_id = $"{MaxEventId}",
                state = new State(Contest),
                rows = go,
            });
        }
Esempio n. 2
0
        public async Task <ActionResult <Scoreboard> > OnGet(
            [FromRoute] int cid,
            [FromQuery] bool @public)
        {
            bool isXcpc = Contest.RankingStrategy == CcsDefaults.RuleXCPC;
            bool isOi   = Contest.RankingStrategy == CcsDefaults.RuleIOI;

            if (!Contest.StartTime.HasValue ||
                Contest.Feature == CcsDefaults.KindProblemset ||
                (!isXcpc && !isOi))
            {
                return(null);
            }

            var scb = await Context.GetScoreboardAsync();

            var board = new FullBoardViewModel(scb, @public, !@public);
            var probs = board.Problems;

            var go = board
                     .SelectMany(a => a)
                     .Select(t => new Scoreboard.Row
            {
                Rank     = t.Rank.Value,
                TeamId   = $"{t.TeamId}",
                Score    = new Scoreboard.Score(isXcpc, t.Points, t.Penalty, t.LastAc),
                Problems = Enumerable.Range(0, probs.Count).Select(i => MakeProblem(t.Problems[i], probs[i], isXcpc)),
            });

            var maxEvent = await Context.GetMaxEventAsync();

            maxEvent ??= new Xylab.Contesting.Entities.Event {
                EventTime = DateTimeOffset.Now
            };
            return(new Scoreboard
            {
                Time = AbstractEvent.TrimToMilliseconds(maxEvent.EventTime),
                ContestTime = maxEvent.EventTime - Contest.StartTime.Value,
                EventId = $"{maxEvent.Id}",
                State = new State(Contest),
                Rows = go,
            });
        }
Esempio n. 3
0
        public async Task <IActionResult> ScoreboardXlsx(
            [FromQuery] int[] affiliations = null,
            [FromQuery] int[] categories   = null)
        {
            if (Contest.RankingStrategy == CcsDefaults.RuleCodeforces)
            {
                return(StatusCode(501));
            }
            if (affiliations != null && affiliations.Length == 0)
            {
                affiliations = null;
            }
            if (categories != null && categories.Length == 0)
            {
                categories = null;
            }

            if (!Contest.StartTime.HasValue)
            {
                return(BadRequest());
            }
            var scb = await Context.GetScoreboardAsync();

            var board = new FullBoardViewModel(scb, false)
            {
                FilteredAffiliations = affiliations?.ToHashSet(),
                FilteredCategories   = categories?.ToHashSet(),
            };

            using var workbook = OpenXmlScoreboard.Create(board, Contest.Name);

            var memoryStream = new MemoryStream();

            workbook.SaveAs(memoryStream);
            memoryStream.Position = 0;

            return(File(
                       fileStream: memoryStream,
                       contentType: OpenXmlScoreboard.MimeType,
                       fileDownloadName: $"c{Contest.Id}-scoreboard.xlsx"));
        }
Esempio n. 4
0
        public static XLWorkbook Create(FullBoardViewModel board, string contestName)
        {
            var workbook = new XLWorkbook(XLEventTracking.Disabled);

            foreach (var sortOrder in board)
            {
                var teams     = sortOrder.ToList();
                var cats      = string.Join(", ", teams.Select(t => t.Category).Distinct().Where(a => !string.IsNullOrWhiteSpace(a)));
                var worksheet = workbook.Worksheets.Add(cats);

                worksheet.Range(1, 1, 1, 4 + board.Problems.Count).Merge().Value(contestName).Bold().Align();
                worksheet.Range(2, 1, 2, 4 + board.Problems.Count).Merge().Value($"导出时间:{DateTimeOffset.Now}").Align(XLAlignmentHorizontalValues.Right);

                worksheet.Row(1).Height *= 3;
                worksheet.Row(1).Style.Font.FontSize *= 1.5;
                worksheet.Row(2).Height   *= 1.5;
                worksheet.Row(3).Height   *= 1.5;
                worksheet.Column(2).Width *= 2;

                worksheet.Cell(3, 1).Value("RANK").Bold().Align();
                worksheet.Cell(3, 2).Value("TEAM").Bold().Align();
                worksheet.Range(3, 3, 3, 4).Merge().Value("SCORE").Bold().Align();
                for (int i = 0; i < board.Problems.Count; i++)
                {
                    worksheet.Cell(3, 5 + i).Value(board.Problems[i].ShortName).Bold().Align();
                }

                int rowid = 4;
                foreach (var team in teams)
                {
                    var row = worksheet.Row(rowid++);
                    row.Height *= 1.5;

                    row.Cell(1).Value(team.Rank).Align();
                    row.Cell(2).Value(team.TeamName).Bold().Bgcolor(XLColor.FromHtml(team.CategoryColor)).Align(XLAlignmentHorizontalValues.Right);
                    row.Cell(3).Value(team.Points).Bold().Align();
                    row.Cell(4).Value(team.Penalty).Align();

                    for (int i = 0; i < team.Problems.Length; i++)
                    {
                        if (board.RankingStrategy.Id == CcsDefaults.RuleXCPC)
                        {
                            if (team.Problems[i] == null)
                            {
                                continue;
                            }
                            var prob = team.Problems[i];
                            if (!prob.Score.HasValue && prob.JudgedCount == 0)
                            {
                                continue;
                            }

                            row.Cell(5 + i).Align()
                            .Value(!prob.Score.HasValue
                                    ? $"(-{prob.JudgedCount})"
                                    : $"{prob.Score} (+{prob.JudgedCount})");
                        }
                        else if (board.RankingStrategy.Id == CcsDefaults.RuleIOI)
                        {
                            if (team.Problems[i]?.Score is not int sc)
                            {
                                continue;
                            }
                            row.Cell(5 + i).Align().Value(sc);
                        }
                    }
                }
            }

            // sentinel worksheet
            workbook.AddWorksheet("Sheet0");
            return(workbook);
        }
Esempio n. 5
0
            public async Task <JobStatus> ExecuteAsync(string arguments, Job job, ILogger logger)
            {
                var args    = arguments.AsJson <Models.ScoreboardArguments>();
                var context = await _factory.CreateAsync(args.ContestId, _serviceProvider, true);

                if (context == null)
                {
                    logger.LogError("Unknown contest ID specified.");
                    return(JobStatus.Failed);
                }

                var contest = context.Contest;

                if (!contest.StartTime.HasValue ||
                    contest.RankingStrategy == CcsDefaults.RuleCodeforces ||
                    contest.Feature == CcsDefaults.KindProblemset)
                {
                    logger.LogError("Export constraint failed.");
                    return(JobStatus.Failed);
                }

                logger.LogInformation("Calculating scoreboard...");

                DateTimeOffset?endTime = args.IncludeUpsolving
                    ? DateTimeOffset.Now
                    : (contest.StartTime + contest.EndTime);

                var raw = await RankingSolver.Select(contest)
                          .RefreshCache(
                    _scoreboard,
                    new Events.ScoreboardRefreshEvent(context, endTime));

                var rankCaches  = raw.RankCache.ToDictionary(r => r.TeamId);
                var scoreCaches = raw.ScoreCache.ToLookup(r => r.TeamId);
                var teams1      = await((ITeamContext)context).GetScoreboardRowsAsync();
                var teams       = teams1.ToDictionary(
                    k => k.TeamId,
                    v => v.With(rankCaches.GetValueOrDefault(v.TeamId), scoreCaches[v.TeamId]));

                logger.LogInformation("Loading other things from database...");

                var affs = await context.ListAffiliationsAsync();

                var orgs = await context.ListCategoriesAsync();

                var probs = await context.ListProblemsAsync();

                var scb = new ScoreboardModel(contest.Id, teams, orgs, affs, probs, contest, RankingSolver.Select(contest));

                var board = new FullBoardViewModel(scb, false)
                {
                    FilteredAffiliations = args.FilteredAffiliations?.ToHashSet(),
                    FilteredCategories   = args.FilteredCategories?.ToHashSet(),
                };

                logger.LogInformation("Data loaded.");

                using var workbook     = OpenXmlScoreboard.Create(board, contest.Name);
                using var memoryStream = new MemoryStream();
                workbook.SaveAs(memoryStream);
                memoryStream.Position = 0;

                await _files.SaveOutputAsync(job, memoryStream);

                logger.LogInformation("Export succeeded.");
                return(JobStatus.Finished);
            }
Esempio n. 6
0
        public static async Task <IActionResult> DomScoreboard <T>(
            this ContestControllerBase <T> that,
            bool isPublic, bool isJury, bool clear,
            int[] filtered_affiliations, int[] filtered_categories, int?page)
            where T : class, IContestContext
        {
            if (that.Contest.Feature != CcsDefaults.KindDom)
            {
                throw new NotSupportedException();
            }

            var pageVal = that.Contest.ShouldScoreboardPaging()
                ? page ?? 1
                : default(int?);

            that.ViewData["Paging"] = pageVal;
            if (pageVal.HasValue && pageVal < 1)
            {
                return(that.BadRequest());
            }

            if (clear)
            {
                filtered_categories = filtered_affiliations = Array.Empty <int>();
            }
            var scb = await that.Context.GetScoreboardAsync();

            var board = new FullBoardViewModel(scb, isPublic && !isJury, isJury);

            if (filtered_affiliations.Length > 0)
            {
                var aff2 = filtered_affiliations.ToHashSet();
                board.FilteredAffiliations           = aff2;
                that.ViewData["Filter_affiliations"] = aff2;
            }

            if (filtered_categories.Length > 0)
            {
                var cat2 = filtered_categories.ToHashSet();
                board.FilteredCategories           = cat2;
                that.ViewData["Filter_categories"] = cat2;
            }

            if (that.Request.Cookies.TryGetValue("domjudge_teamselection", out var teamselection))
            {
                try
                {
                    var vals = teamselection.AsJson <string[]>();
                    if (vals != null && vals.Length <= 20 && vals.Length > 0)
                    {
                        var teams = new HashSet <int>();
                        for (int i = 0; i < vals.Length; i++)
                        {
                            if (int.TryParse(vals[i], out int teamid))
                            {
                                teams.Add(teamid);
                            }
                        }
                        board.FavoriteTeams = teams;
                    }
                }
                catch
                {
                    // The field `domjudge_teamselection` is wrongly set.
                    that.Response.Cookies.Delete("domjudge_teamselection");
                }
            }

            return(that.View("Scoreboard", board));
        }