private void _Grade(ChallengeSpec spec, SectionSubmission submission) { var section = spec.Challenge.Sections.ElementAtOrDefault(submission.SectionIndex); double lastScore = spec.Score; int i = 0; foreach (var question in section.Questions) { question.Grade(submission.Questions.ElementAtOrDefault(i++)?.Answer ?? ""); } section.Score = section.Questions .Where(q => q.IsCorrect) .Select(q => q.Weight - q.Penalty) .Sum() ; spec.Score = spec.Challenge.Sections .SelectMany(s => s.Questions) .Where(q => q.IsCorrect) .Select(q => q.Weight - q.Penalty) .Sum() ; if (spec.Score > lastScore) { spec.LastScoreTime = submission.Timestamp; } }
private ChallengeView MapChallenge(ChallengeSpec spec, int sectionIndex = 0) { var section = spec.Challenge.Sections.ElementAtOrDefault(sectionIndex); var challenge = new ChallengeView { Text = string.Join("\n\n", spec.Text, spec.Challenge.Text), LastScoreTime = spec.LastScoreTime, MaxPoints = spec.MaxPoints, MaxAttempts = spec.MaxAttempts, Attempts = spec.Submissions.Count, Score = Math.Round(spec.Score * spec.MaxPoints, 0, MidpointRounding.AwayFromZero), SectionIndex = sectionIndex, SectionCount = spec.Challenge.Sections.Count, SectionScore = Math.Round(section.Score * spec.MaxPoints, 0, MidpointRounding.AwayFromZero), SectionText = section.Text, Questions = Mapper.Map <QuestionView[]>(section.Questions.Where(q => !q.Hidden)) }; foreach (var q in challenge.Questions) { q.Weight = (float)Math.Round(q.Weight * spec.MaxPoints, 0, MidpointRounding.AwayFromZero); q.Penalty = (float)Math.Round(q.Penalty * spec.MaxPoints, 0, MidpointRounding.AwayFromZero); } return(challenge); }
public async Task UpdateChallenge(int id, ChallengeSpec spec) { var entity = await _workspaceStore.Load(id); if (entity == null || !entity.CanEdit(User)) { throw new InvalidOperationException(); } // spec.Randoms.Clear(); // hydrate question weights var unweighted = spec.Questions.Where(q => q.Weight == 0).ToArray(); float max = spec.Questions.Sum(q => q.Weight); if (unweighted.Any()) { float val = (1 - max) / unweighted.Length; foreach (var q in unweighted.Take(unweighted.Length - 1)) { q.Weight = val; max += val; } unweighted.Last().Weight = 1 - max; } entity.Challenge = JsonSerializer.Serialize(spec, jsonOptions); await _workspaceStore.Update(entity); }
public async Task UpdateChallenge(string id, ChallengeSpec spec) { var entity = await _store.Retrieve(id); entity.Challenge = JsonSerializer.Serialize <ChallengeSpec>(spec, jsonOptions); await _store.Update(entity); }
public ActionResult <ChallengeSpec> SaveChallengeSpec([FromRoute] string name, [FromBody] ChallengeSpec challengeSpec) { ChallengeSpec spec = _challengeService.SaveChallengeSpec(name, challengeSpec); if (spec == null) { throw new InvalidOperationException($"ChallengeSpec {name} was not saved. Please try again."); } return(Ok(spec)); }
public Task <List <ChallengeSpec> > ChallengeSpecs() { //TODO: it would be better if we could retrieve the items that were added by save method. //There is not a way to enumerate keys on IMemoryCache List <ChallengeSpec> challengeSpecs = new List <ChallengeSpec>(); ChallengeSpec challengeSpec = GetChallengeSpec(); challengeSpecs.Add(challengeSpec); return(Task.FromResult(challengeSpecs)); }
public async Task <ChallengeSpec> SaveChallengeSpec(string name, ChallengeSpec challengeSpec) { var result = await Http.PostAsync($"/api/challenge/savechallengespec/{name}", Json(challengeSpec)); if (!result.IsSuccessStatusCode) { throw new HttpRequestException(result.ReasonPhrase); } return(JsonConvert.DeserializeObject <ChallengeSpec>(await result.Content.ReadAsStringAsync())); }
public Task <ChallengeSpec> SaveChallengeSpec(string name, ChallengeSpec challengeSpec) { if (!string.IsNullOrEmpty(name) && challengeSpec != null) { challengeSpec.Slug = name; Cache.Set(name, challengeSpec); return(Task.FromResult(challengeSpec)); } else { throw new ArgumentException("The ChallengeSpec save operation failed."); } }
public async Task <IActionResult> UpdateChallengeSpec([FromRoute] string id, [FromBody] ChallengeSpec model) { await Validate(new Entity { Id = id }); await Validate(model); AuthorizeAny( () => Actor.IsAdmin, () => _svc.CanEdit(id, Actor.Id).Result ); await _svc.UpdateChallenge(id, model); // TODO: broadcast updated return(Ok()); }
private ChallengeSpec GetChallengeSpec() { ChallengeSpec challengeSpec = new ChallengeSpec(); challengeSpec.Title = "The Test Game"; challengeSpec.Tags = "Sift, Forensics"; challengeSpec.Document = "AI500 - T1.pdf"; challengeSpec.Description = " | Use Sift workstation to analyze evidence drives **Analysis using the virtual gamespace required **"; challengeSpec.Workspace = new WorkspaceSpec { Id = 104, CustomizeTemplates = true, Vms = new VmSpec[] { new VmSpec { Name = "Windows10", Replicas = 3 } } }; challengeSpec.Flags = new FlagSpec[] { new FlagSpec { Tokens = new TokenSpec[] { new TokenSpec { Value = "ncrypt10n_ch4ll3ng1ng" } } }, new FlagSpec { Tokens = new TokenSpec[] { new TokenSpec { Value = "ncrypt10n_h3lps" } }, GenerateCommand = "sed -i \"s/evidence1.vmdk/evidence2.vmdk/\" /dst/_templates.json", GenerateImage = "bash" }, new FlagSpec { Tokens = new TokenSpec[] { new TokenSpec { Value = "b1tl0ck3r" } }, GenerateCommand = "sed -i \"s/evidence1.vmdk/evidence3.vmdk/\" /dst/_templates.json", GenerateImage = "bash" } }; return(challengeSpec); }
/// <summary> /// Save a ChallengeSpec to a file /// </summary> /// <param name="name"></param> /// <param name="challengeSpec"></param> /// <returns></returns> public bool SaveChallengeSpec(string name, ChallengeSpec challengeSpec) { string folderPath = Path.Combine(Data.RootPath, Options.ChallengePath, name); if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } // TODO: how do we save all of the files that go into the ChallengeSpec? string filePath = Path.Combine(Data.RootPath, Options.ChallengePath, name + ".yaml"); string challengeSpecYaml = serializer.Serialize(challengeSpec); File.WriteAllText(filePath, challengeSpecYaml); return(true); }
public ChallengeSpec SaveChallengeSpec(string name, ChallengeSpec challengeSpec) { //bool isValid = ValidateChallengeSpec(name, challengeSpec); //if(!isValid) //{ // throw new ArgumentException("The ChallengeSpec was not saved. An Invalid ChallengeSpec was submitted."); //} var spec = Data.GetChallengeSpec(name); bool created = false; if (spec != null) { // this file already exists // archive existing spec and create a new one with this name if (ArchiveChallengeSpec(name)) { if (CreateNewChallengeSpec(name, challengeSpec)) { created = true; } } } else { if (CreateNewChallengeSpec(name, challengeSpec)) { created = true; } } if (created) { // TODO: force reload so we can get it from memory and return to caller. look into reloading just one item rather than all files. _dataContext.Reload(); return(Data.GetChallengeSpec(name)); } return(null); }
private void ResolveTransforms(ChallengeSpec spec, RegistrationContext ctx) { foreach (var kvp in spec.Transforms.ToArray()) { kvp.Value = ResolveRandom(kvp.Value, ctx); // insert `key_index: value` for any multi-token values (i.e. list-resolver) var tokens = kvp.Value.Split(" ", StringSplitOptions.RemoveEmptyEntries); if (tokens.Length > 1) { int i = 0; foreach (string token in tokens) { spec.Transforms.Add(new StringKeyValue { Key = $"{kvp.Key}_{++i}", Value = token }); } } } }
private bool CreateNewChallengeSpec(string name, ChallengeSpec challengeSpec) { return(Data.SaveChallengeSpec(name, challengeSpec)); }
public async Task <IActionResult> Challenge([FromRoute] int id, [FromBody] ChallengeSpec model) { await _workspaceService.UpdateChallenge(id, model); return(Ok()); }
private async Task _validate(ChallengeSpec model) { await Task.CompletedTask; }
private async Task <Data.Gamespace> Create( Data.Workspace workspace, string client, string isolationId ) { var gamespace = new Data.Gamespace { GlobalId = isolationId, Name = workspace.Name, Workspace = workspace, ShareCode = Guid.NewGuid().ToString("n"), Audience = client }; gamespace.Players.Add( new Data.Player { PersonId = User.Id, Permission = Data.Permission.Manager // LastSeen = DateTime.UtcNow } ); // glean randomize targets var regex = new Regex("##[^#]*##"); var map = new Dictionary <string, string>(); foreach (var t in gamespace.Workspace.Templates) { foreach (Match match in regex.Matches(t.Guestinfo ?? "")) { map.TryAdd(match.Value, ""); } foreach (Match match in regex.Matches(t.Detail ?? t.Parent?.Detail ?? "")) { map.TryAdd(match.Value, ""); } } // clone challenge var spec = new ChallengeSpec(); if (!string.IsNullOrEmpty(workspace.Challenge)) { spec = JsonSerializer.Deserialize <ChallengeSpec>(workspace.Challenge ?? "{}", jsonOptions); foreach (var question in spec.Questions) { foreach (Match match in regex.Matches(question.Answer)) { string key = match.Value; string val = ""; if (key.Contains(":list##")) { string[] list = question.Answer .Split(' ', StringSplitOptions.RemoveEmptyEntries) .Skip(1) .ToArray(); if (list.Length > 0) { val = list[_random.Next(list.Length)]; question.Answer = key; if (map.ContainsKey(key)) { map[key] = val; } } } map.TryAdd(key, val); } } } // resolve macros foreach (string key in map.Keys.ToArray()) { if (string.IsNullOrEmpty(map[key])) { map[key] = ResolveRandom(key); } } // apply macros to spec answers foreach (var q in spec.Questions) { foreach (string key in map.Keys) { q.Answer = q.Answer.Replace(key, map[key]); } } spec.Randoms = map; gamespace.Challenge = JsonSerializer.Serialize(spec, jsonOptions); await _gamespaceStore.Add(gamespace); return(gamespace); }