Exemplo n.º 1
0
        private void ApplyMacros(ProblemContext context)
        {
            foreach (var macro in context.Macros)
            {
                if (context.Spec.Text.NotEmpty() && context.Spec.Text.Contains(macro.Key))
                {
                    context.Spec.Text = context.Spec.Text.Replace(macro.Key, macro.Value);
                }

                if (context.Flag.GradeInputData.NotEmpty() && context.Flag.GradeInputData.Contains(macro.Key))
                {
                    context.Flag.GradeInputData = context.Flag.GradeInputData.Replace(macro.Key, macro.Value);
                }
            }

            if (context.Flag.Workspace == null)
            {
                return;
            }

            foreach (var vm in context.Flag.Workspace.Vms)
            {
                if (vm.Replicas < 0)
                {
                    vm.Replicas = context.Problem.Team?.Players?.Count() ?? 1;
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Save submitted flag
        /// </summary>
        /// <param name="context"></param>
        /// <param name="flag"></param>
        private void SaveFlag(ProblemContext context, ProblemFlag flag)
        {
            string fn   = Path.Combine(context.ProblemFolder, flag.SubmissionId + ".json");
            string data = JsonConvert.SerializeObject(flag);

            File.WriteAllText(fn, data);
        }
Exemplo n.º 3
0
 private void FetchTemplates(ProblemContext context)
 {
     if (context.Flag.Workspace?.CustomizeTemplates ?? false)
     {
         string templates = Mojo.Templates(context.Flag.Workspace.Id).Result;
         File.WriteAllText(Path.Combine(context.ProblemFolder, "_templates.json"), templates);
     }
 }
Exemplo n.º 4
0
        private void Deploy(ProblemContext context)
        {
            // TODO: check max-concurrent-problems

            if (context.Flag.Workspace == null)
            {
                return;
            }

            if (context.Flag.Iso.NotEmpty())
            {
                context.Flag.Workspace.Iso = context.Flag.Iso;
            }

            string fn = Path.Combine(context.ProblemFolder, "_templates.json");

            if (File.Exists(fn))
            {
                context.Flag.Workspace.Templates = File.ReadAllText(fn);
            }

            // temp transition mapping
            var spec = JsonConvert.DeserializeObject <TopoMojo.Models.GamespaceSpec>(
                JsonConvert.SerializeObject(context.Flag.Workspace)
                );

            spec.WorkspaceId = context.Flag.Workspace.Id;
            spec.IsolationId = context.Problem.IsolationId;

            var state = Mojo.Start(spec).Result;

            string consoleMarkdown = "> Gamespace Resources: " + String.Join(
                " | ",
                state.Vms
                .Select(v => $"[{v.Name.Untagged()}](/console/{v.Id}/{v.Name.Untagged()}/{spec.IsolationId})")
                );

            context.ProblemState.GamespaceText = consoleMarkdown;

            string markdownMarker = "<!--tm doc-->";

            if (
                spec.AppendMarkdown &&
                state.Markdown.NotEmpty() &&
                !context.ProblemState.Text.Contains(markdownMarker))
            {
                context.ProblemState.Text += $"{state.Markdown}\n{markdownMarker}";
            }

            context.ProblemState.GamespaceReady = true;
            context.Flag.Workspace.Templates    = null;

            Data.SaveContext(context);
        }
Exemplo n.º 5
0
        public ProblemController(ProblemContext context)
        {
            _context = context;

            if (_context.ProblemItems.Count() == 0)
            {
                _context.ProblemItems.Add(new ProblemItem {
                    Name = "Проблема"
                });
                _context.SaveChanges();
            }
        }
Exemplo n.º 6
0
        private void HydrateFlagFiles(ProblemContext context)
        {
            if (context.Flag.Files.IsEmpty() || !Directory.Exists(context.ChallengeFolder))
            {
                return;
            }

            string[] files         = Directory.GetFiles(context.ChallengeFolder, "*", SearchOption.AllDirectories);
            var      selectedFiles = new List <string>();

            foreach (string target in context.Flag.Files)
            {
                if (files.Contains(target))
                {
                    selectedFiles.Add(target);
                    continue;
                }

                string match = files.FirstOrDefault(f => Path.GetFileName(f) == target);
                if (match.NotEmpty())
                {
                    selectedFiles.Add(match);
                    continue;
                }

                var rule = target.Split(":");
                if (int.TryParse(rule[0], out int count))
                {
                    for (int i = 0; i < count; i++)
                    {
                        string[] pool = files
                                        .Where(f => f.LikeGlob(rule[1]))
                                        .Except(selectedFiles)
                                        .ToArray();

                        if (pool.Length > 0)
                        {
                            selectedFiles.Add(pool[new Random().Next(pool.Length)]);
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
            context.Flag.Files = selectedFiles.ToArray();
            Array.Sort(context.Flag.Files);
        }
Exemplo n.º 7
0
        public Form1()
        {
            InitializeComponent();

            Bitmap data = (Bitmap)Bitmap.FromFile("map.jpg");

            ProblemContext.LoadFromImage((Bitmap)Bitmap.FromFile("map.jpg"));
            this.BackgroundImage = data;
            this.Width           = this.BackgroundImage.Width;
            this.Height          = this.BackgroundImage.Height;
            this.Paint          += new PaintEventHandler(Form1_Paint);
            this.MouseMove      += new MouseEventHandler(Form1_MouseMove);
            this.MouseClick     += new MouseEventHandler(Form1_MouseClick);

            this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
            this.UpdateStyles();
            this.button1.Text = "Compute EST path";
        }
Exemplo n.º 8
0
        private void BuildIso(ProblemContext context)
        {
            if (context.Flag.Iso.NotEmpty() || context.Flag.Files.IsEmpty())
            {
                return;
            }

            string path = Path.Combine(context.IsoFolder, context.Problem.Id + ".iso");

            try
            {
                var builder = new CDBuilder
                {
                    UseJoliet        = true,
                    VolumeIdentifier = "VOL" + new Random().Next().ToString("X")
                };

                foreach (string file in context.Flag.Files)
                {
                    builder.AddFile(Path.GetFileName(file), file);
                }

                if (context.Spec.Document.NotEmpty())
                {
                    string docpath = Path.Combine(context.ChallengeFolder, context.Spec.Document);
                    if (!File.Exists(docpath))
                    {
                        docpath = Path.Combine(context.IsoFolder, context.Spec.Document);
                    }
                    if (File.Exists(docpath))
                    {
                        builder.AddFile(Path.GetFileName(docpath), docpath);
                    }
                }

                builder.Build(path);

                context.Flag.Iso = Path.GetFileName(path);
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, $"Error building iso file for {context.Spec.Title}.");
            }
        }
Exemplo n.º 9
0
        private void ResolveText(ProblemContext context)
        {
            var links = new List <string>();

            if (context.Spec.Document.NotEmpty())
            {
                links.Add($"[PDF File]({Options.DownloadUrl}/{context.Spec.Document})");
            }

            if (context.Flag.Iso.NotEmpty() && !context.Flag.IsoRestricted)
            {
                // try get filesize
                string fsize = "";
                string path  = Path.Combine(Options.IsoPath, context.Flag.Iso);
                if (File.Exists(path))
                {
                    var info = new FileInfo(path);
                    fsize = info.Length.ToDisplayBytes();
                }
                links.Add($"[ISO File {fsize}]({Options.DownloadUrl}/{context.Flag.Iso})");
            }

            if (links.Count > 0)
            {
                var linkText = "> Download Resources: " + string.Join(" | ", links);
                context.Spec.Text = string.Join("\n\n", linkText, context.Spec.Text);
            }

            context.Spec.Text = string.IsNullOrWhiteSpace(context.Spec.Text)
                ? string.Empty
                : Regex.Replace(context.Spec.Text, "]\\(img/", $"]({Options.DownloadUrl}/img/");

            context.Flag.Text = string.IsNullOrWhiteSpace(context.Flag.Text)
                ? string.Empty
                : Regex.Replace(context.Flag.Text, "]\\(img/", $"]({Options.DownloadUrl}/img/");

            context.ProblemState.Text = string.Join("\n", context.Spec.Text, context.Flag.Text);
        }
Exemplo n.º 10
0
        private void Generate(ProblemContext context)
        {
            if (context.Flag != null)
            {
                return;
            }

            SelectFlag(context);

            ApplyMacros(context);

            FetchTemplates(context);

            HydrateFlagFiles(context);

            ExecuteScript(context);

            BuildIso(context);

            ResolveText(context);

            Data.SaveContext(context);
        }
Exemplo n.º 11
0
        private void SelectFlag(ProblemContext context)
        {
            if (context.Flag != null)
            {
                return;
            }

            if (!context.Problem.FlagIndex.HasValue)
            {
                context.Problem.FlagIndex = new Random().Next(context.Spec.Flags.Length);
            }

            context.FlagIndex = context.Problem.FlagIndex.Value;

            context.Flag = context.Spec.Flags[context.FlagIndex].Map <FlagSpec>();

            if (context.Flag.Workspace == null && context.Spec.Workspace != null)
            {
                context.Flag.Workspace = context.Spec.Workspace;
            }

            context.ProblemState.HasGamespace = context.Flag.Workspace != null;
            context.ProblemState.Tokens       = GetTokens(context.Flag);
        }
Exemplo n.º 12
0
 public ProblemsController(ProblemContext context)
 {
     _context = context;
 }
Exemplo n.º 13
0
 public MatchAlphaNumeric(Options options, ILogger logger, ProblemContext problemContext)
     : base(options, logger, problemContext)
 {
 }
Exemplo n.º 14
0
        /// <summary>
        /// Save a ProblemContext to a file
        /// </summary>
        /// <param name="context"></param>
        public void SaveContext(ProblemContext context)
        {
            string contextPath = Path.Combine(Data.RootPath, Options.ProblemPath, context.Problem.Id, "_context.json");

            File.WriteAllText(contextPath, JsonConvert.SerializeObject(context, Formatting.Indented));
        }
Exemplo n.º 15
0
        /// <summary>
        /// Grades a flag submitted for a problem
        /// </summary>
        /// <param name="flag"></param>
        /// <returns></returns>
        public GradedSubmission Grade(ProblemFlag flag)
        {
            ProblemContext context = null;
            GradingResult  result  = null;

            Logger.LogDebug($"grading {flag.Id}");
            var submissionStatus = SubmissionStatus.Submitted;

            try
            {
                context = Data.LoadContext(flag.Id);

                if (context == null || context.Flag == null)
                {
                    throw new NotFoundException();
                }

                if (context.ProblemState.Status == ProblemStatus.Complete)
                {
                    throw new ProblemCompleteException();
                }

                SaveFlag(context, flag);

                IGradingStrategy strategy = null;

                switch (context.Flag.Type)
                {
                case FlagType.MatchOutput:
                    strategy = new MatchOutput(Options, Logger, context);
                    break;

                case FlagType.MatchAll:
                    strategy = new MatchAll(Options, Logger, context);
                    break;

                case FlagType.MatchAny:
                    strategy = new MatchAny(Options, Logger, context);
                    break;

                case FlagType.Match:
                    strategy = new Match(Options, Logger, context);
                    break;

                case FlagType.MatchAlphaNumeric:
                default:
                    strategy = new MatchAlphaNumeric(Options, Logger, context);
                    break;
                }

                result = strategy.GradeTokens(flag);
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "Had a problem with grading");
            }
            finally
            {
                if (context != null && result != null)
                {
                    submissionStatus = result.Success ? SubmissionStatus.Passed : SubmissionStatus.Failed;

                    var check = false;

                    // if max submissions <= 0 then we accept
                    // unlimited submissions if unsuccessful
                    if (context.Problem.Settings.MaxSubmissions > 0)
                    {
                        if (context.Spec.IsMultiStage)
                        {
                            // if multi stage we only consider the
                            // last graded token incorrect count
                            check = result.GradedTokens.Last().Status != TokenStatusType.Correct &&
                                    flag.Count >= context.Problem.Settings.MaxSubmissions;
                        }
                        else
                        {
                            check = flag.Count >= context.Problem.Settings.MaxSubmissions;
                        }
                    }

                    var isFinal = result.Success || check;

                    if (isFinal)
                    {
                        //_ = Mojo.Stop(flag.Id);

                        context.ProblemState.End = DateTime.UtcNow;
                        //context.ProblemState.GamespaceReady = false;
                        context.ProblemState.Status = result.Success ? ProblemStatus.Success : ProblemStatus.Failure;
                    }

                    context.ProblemState.Percent = result.CorrectPercent;

                    // map TokenSpec detail along with correct answers
                    var problemStateTokens = new List <Token>();

                    int index = 0;
                    foreach (var tokenSpec in context.Flag.Tokens)
                    {
                        var correct = result.GradedTokens.SingleOrDefault(t => t.Index == index && t.Status == TokenStatusType.Correct);

                        problemStateTokens.Add(new Token
                        {
                            Index     = index,
                            Label     = tokenSpec.Label,
                            Percent   = context.Flag.Tokens.Length == 1 ? 100 : tokenSpec.Percent,
                            Status    = correct?.Status ?? TokenStatusType.Pending,
                            Timestamp = correct?.Timestamp,
                            Value     = correct?.Value
                        });

                        index++;
                    }

                    context.ProblemState.Tokens = problemStateTokens;

                    Data.SaveContext(context);
                }
            }

            Logger.LogDebug($"returning {flag.Id}");

            return(new GradedSubmission
            {
                ProblemId = flag.Id,
                SubmissionId = flag.SubmissionId,
                Status = submissionStatus,
                State = context?.ProblemState,
                Timestamp = DateTime.UtcNow,
                Tokens = result?.GradedTokens
            });
        }
Exemplo n.º 16
0
        /// <summary>
        /// Create a new instance of a problem for a team
        /// </summary>
        /// <param name="problem"></param>
        /// <returns></returns>
        public ProblemState Spawn(Problem problem)
        {
            var context = new ProblemContext {
                Problem      = problem,
                ProblemState = new ProblemState {
                    Id            = problem.Id,
                    ChallengeLink = problem.ChallengeLink
                }
            };

            try
            {
                Logger.LogDebug($"initializing {problem.Id}");
                context = Initialize(problem);

                if (!Stats.ClaimSession(context.ProblemState.TeamId, "adhoc", 0))
                {
                    throw new Exception($"All {Options.MaxSessions} sessions are in use. Please try again later.");
                }

                var start      = DateTime.UtcNow;
                var reportStat = context.Flag == null;

                Logger.LogDebug($"generating {problem.Id} [index: {problem.FlagIndex ?? -1}]");

                Generate(context);

                Logger.LogDebug($"deploying {problem.Id}");

                Deploy(context);

                if (reportStat)
                {
                    Stats.ReportStat(new ChallengeStat {
                        Id    = problem.ChallengeLink.Id,
                        Sum   = (int)DateTime.UtcNow.Subtract(start).TotalSeconds,
                        Count = 1
                    });
                }

                if (context.ProblemState.Start.IsEmpty())
                {
                    context.ProblemState.Start = DateTime.UtcNow;
                }

                if (context.ProblemState.Status != ProblemStatus.Failure &&
                    context.ProblemState.Status != ProblemStatus.Success &&
                    context.ProblemState.Status != ProblemStatus.Complete
                    )
                {
                    context.ProblemState.Status = ProblemStatus.Ready;
                }

                Data.SaveContext(context);
            }
            catch (Exception ex)
            {
                context.ProblemState.Status = ProblemStatus.Error;
                context.ProblemState.Text   = ex.Message;
                Logger.LogError(ex, $"Failed to spawn problem {problem.Id}");
            }
            finally
            {
            }

            return(context.ProblemState);
        }
Exemplo n.º 17
0
 public GradingResult(ProblemContext context)
 {
     ProblemContext = context;
 }
Exemplo n.º 18
0
 public MatchOutput(Options options, ILogger logger, ProblemContext problemContext)
     : base(options, logger, problemContext)
 {
 }
Exemplo n.º 19
0
 protected GradingStrategy(Options options, ILogger logger, ProblemContext problemContext)
 {
     Options        = options;
     Logger         = logger;
     ProblemContext = problemContext;
 }
Exemplo n.º 20
0
        private void ExecuteScript(ProblemContext context)
        {
            if (context.Flag.GenerateCommand.IsEmpty())
            {
                return;
            }

            var process = Process.Start(
                new ProcessStartInfo
            {
                FileName  = Options.Command,
                Arguments = string.Format(
                    Options.CommandArgs,
                    context.ChallengeFolder,
                    context.ProblemFolder,
                    context.Flag.GenerateImage,
                    context.Flag.GenerateCommand
                    )
            }
                );

            Logger.LogInformation(process.StartInfo.Arguments);
            process.WaitForExit(Options.MaxScriptSeconds * 1000);
            if (!process.HasExited)
            {
                process.Kill();
                throw new ProblemGenerationTimeoutException();
            }

            if (process.ExitCode > 0)
            {
                throw new ProblemGenerationException();
            }

            string fileName = Path.Combine(context.ProblemFolder, context.Flag.GenerateOutputFlag);

            if (File.Exists(fileName))
            {
                string data = File.ReadAllText(fileName);
                try
                {
                    context.Flag.Tokens = Deserializer.Deserialize <TokenSpec[]>(data);
                }
                catch
                {
                    context.Flag.Tokens = new TokenSpec[]
                    {
                        new TokenSpec
                        {
                            Value = data
                        }
                    };
                }
            }

            fileName = Path.Combine(context.ProblemFolder, context.Flag.GenerateOutputText);
            if (File.Exists(fileName))
            {
                context.Spec.Text = string.Join("\n\n", context.Spec.Text, File.ReadAllText(fileName));
            }

            fileName = Path.Combine(context.ProblemFolder, context.Flag.GenerateOutputFileList);
            if (File.Exists(fileName))
            {
                string[] files           = File.ReadAllLines(fileName);
                var      additionalFiles = new List <string>();
                foreach (string file in files)
                {
                    string target = file
                                    .Replace("/src", context.ChallengeFolder)
                                    .Replace("/dst", context.ProblemFolder);

                    if (File.Exists(target))
                    {
                        additionalFiles.Add(target);
                    }
                }

                if (additionalFiles.Count > 0)
                {
                    context.Flag.Files = context.Flag.Files
                                         .Union(additionalFiles)
                                         .ToArray();
                }
            }
        }