Exemplo n.º 1
0
        public async Task <Challenge> Grade(SectionSubmission model, string actorId)
        {
            var entity = await Store.Retrieve(model.Id);

            // TODO: don't log auto-grader events
            // if (model.Id != actorId)
            entity.Events.Add(new Data.ChallengeEvent
            {
                Id        = Guid.NewGuid().ToString("n"),
                UserId    = actorId,
                TeamId    = entity.TeamId,
                Timestamp = DateTimeOffset.UtcNow,
                Type      = ChallengeEventType.Submission
            });

            double currentScore = entity.Score;

            var result = await Sync(
                entity,
                Mojo.GradeChallengeAsync(model)
                );

            if (result.Score > currentScore)
            {
                await Store.UpdateTeam(entity.TeamId);
            }

            return(Mapper.Map <Challenge>(entity));
        }
Exemplo n.º 2
0
        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;
            }
        }
Exemplo n.º 3
0
        public async Task <ActionResult <GameState> > GradeChallenge([FromBody] SectionSubmission model)
        {
            await Validate(new Entity { Id = model.Id });

            AuthorizeAny(
                () => Actor.IsAdmin,
                () => model.Id == Actor.Id,  // from valid grader_apikey
                () => _svc.CanInteract(model.Id, Actor.Id).Result
                );

            return(Ok(
                       await _svc.Grade(model)
                       ));
        }
Exemplo n.º 4
0
        public async Task <Challenge> Grade([FromBody] SectionSubmission model)
        {
            AuthorizeAny(
                () => Actor.IsDirector,
                () => Actor.Id == model.Id, // auto-grader
                () => ChallengeService.UserIsTeamPlayer(model.Id, Actor.Id).Result
                );

            await Validate(new Entity { Id = model.Id });

            var result = await ChallengeService.Grade(model, Actor.Id);

            await Hub.Clients.Group(result.TeamId).ChallengeEvent(
                new HubEvent <Challenge>(result, EventAction.Updated)
                );

            return(result);
        }
Exemplo n.º 5
0
        private bool IsDuplicateSubmission(ICollection <SectionSubmission> history, SectionSubmission submission)
        {
            bool dupe = false;

            string incoming = string.Join('|',
                                          submission.Questions.Select(q => q.Answer ?? "")
                                          );

            foreach (var s in history)
            {
                string target = string.Join('|',
                                            s.Questions.Select(q => q.Answer ?? "")
                                            );

                dupe |= target.Equals(incoming);

                if (dupe)
                {
                    break;
                }
            }

            return(dupe || incoming.Replace("|", "") == string.Empty);
        }
Exemplo n.º 6
0
        public async Task <GameState> Grade(SectionSubmission submission)
        {
            DateTimeOffset ts = DateTimeOffset.UtcNow;

            string id = submission.Id;

            if (!await _locker.Lock(id))
            {
                throw new ResourceIsLocked();
            }

            var ctx = await LoadContext(id);

            var spec = JsonSerializer.Deserialize <ChallengeSpec>(ctx.Gamespace.Challenge, jsonOptions);

            var section = spec.Challenge.Sections.ElementAtOrDefault(submission.SectionIndex);

            if (IsDuplicateSubmission(spec.Submissions, submission))
            {
                _locker.Unlock(id).Wait();
                return(await LoadState(ctx.Gamespace));
            }

            if (section == null)
            {
                _locker.Unlock(id, new InvalidOperationException()).Wait();
            }

            if (!ctx.Gamespace.IsActive)
            {
                _locker.Unlock(id, new GamespaceIsExpired()).Wait();
            }

            if (spec.MaxAttempts > 0 && spec.Submissions.Where(s => s.SectionIndex == submission.SectionIndex).Count() >= spec.MaxAttempts)
            {
                _locker.Unlock(id, new AttemptLimitReached()).Wait();
            }

            submission.Timestamp = ts;
            spec.Submissions.Add(submission);

            _Grade(spec, submission);

            ctx.Gamespace.Challenge = JsonSerializer.Serialize(spec, jsonOptions);

            // handle completion if max attempts reached or full score
            if (
                spec.Score == 1 ||
                (
                    spec.MaxAttempts > 0 &&
                    spec.Submissions.Count == spec.MaxAttempts
                )
                )
            {
                ctx.Gamespace.EndTime = ts;
            }

            await _store.Update(ctx.Gamespace);

            // map return model
            var result = await LoadState(ctx.Gamespace);

            // merge submission into return model
            int i = 0;

            foreach (var question in result.Challenge.Questions)
            {
                question.Answer = submission.Questions.ElementAtOrDefault(i++)?.Answer ?? "";
            }

            await _locker.Unlock(id);

            return(result);
        }