public override bool ValidateInput(LabConfigurationExerciseEntry exercise, object input)
    {
        if (!(exercise is LabConfigurationMultipleChoiceExerciseEntry multipleChoiceExercise))
        {
            throw new ArgumentException("Invalid exercise type", nameof(exercise));
        }
        if (!(input is IEnumerable <int> selectedOptions))
        {
            throw new ArgumentException("Invalid input type", nameof(input));
        }
        var selectedIds = selectedOptions
                          .OrderBy(id => id)
                          .ToArray();

        // Extract correct options
        var correctIds = multipleChoiceExercise.Options
                         .Select((option, index) => (option, index))
                         .Where(opt => opt !.option.Correct) // IDE says this may be null, which is wrong
                         .Select(opt => opt.index)
                         .OrderBy(id => id)
                         .ToArray();

        // Compare
        if (multipleChoiceExercise.RequireAll)
        {
            return(selectedIds.SequenceEqual(correctIds));
        }
        return(selectedIds.Any() && selectedIds.All(id => correctIds.Contains(id)));
    }
示例#2
0
    public override bool Update(LabConfigurationExerciseEntry exercise)
    {
        if (!(exercise is LabConfigurationStringExerciseEntry stringExercise))
        {
            throw new ArgumentException("Invalid exercise type", nameof(exercise));
        }

        // Is the expected solution still valid?
        if (stringExercise.AllowAnySolution)
        {
            // We allow any solution, so no need to store a name
            if (SolutionName != null)
            {
                // Drop previous solution name
                SolutionName = null;
                return(true);
            }
        }
        else
        {
            // Check whether the exercise requires a specific, existing solution
            if (SolutionName == null || stringExercise.ValidSolutions.All(s => s.Name != SolutionName))
            {
                // Pick a random solution
                var random = stringExercise.ValidSolutions[RandomNumberGenerator.GetInt32(stringExercise.ValidSolutions.Length)];
                SolutionName = random.Name;
                return(true);
            }
        }

        return(false);
    }
示例#3
0
 public override string FormatDescriptionString(LabConfigurationExerciseEntry exercise)
 {
     if (exercise.DescriptionFormat == null)
     {
         return("");
     }
     return(string.Format(exercise.DescriptionFormat, SolutionName));
 }
        public override bool Update(LabConfigurationExerciseEntry exercise)
        {
            if (!(exercise is LabConfigurationScriptExerciseEntry))
            {
                throw new ArgumentException("Invalid exercise type", nameof(exercise));
            }

            // No changes required
            return(false);
        }
示例#5
0
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jsonObject   = JObject.Load(reader);
        var     exerciseType = jsonObject[nameof(LabConfigurationExerciseEntry.Type)]?.ToObject <LabConfigurationExerciseEntryType>();

        LabConfigurationExerciseEntry exercise = exerciseType switch
        {
            LabConfigurationExerciseEntryType.String => new LabConfigurationStringExerciseEntry(),
            LabConfigurationExerciseEntryType.MultipleChoice => new LabConfigurationMultipleChoiceExerciseEntry(),
            LabConfigurationExerciseEntryType.Script => new LabConfigurationScriptExerciseEntry(),
            _ => throw new JsonSerializationException("Unknown exercise type")
        };

        serializer.Populate(jsonObject.CreateReader(), exercise);

        return(exercise);
    }
示例#6
0
    public override bool ValidateInput(LabConfigurationExerciseEntry exercise, object input)
    {
        if (!(exercise is LabConfigurationStringExerciseEntry stringExercise))
        {
            throw new ArgumentException("Invalid exercise type", nameof(exercise));
        }
        if (!(input is string inputStr))
        {
            throw new ArgumentException("Invalid input type", nameof(input));
        }

        if (stringExercise.UseRegex)
        {
            // Match any solution
            if (stringExercise.AllowAnySolution)
            {
                return(stringExercise.ValidSolutions.Any(s => Regex.IsMatch(inputStr, s.Value)));
            }

            // Match specific solution
            var pattern = stringExercise.ValidSolutions.FirstOrDefault(s => s.Name == SolutionName)?.Value;
            if (pattern == null)
            {
                return(false);
            }
            return(Regex.IsMatch(inputStr, pattern));
        }

        // Compare against any solution
        if (stringExercise.AllowAnySolution)
        {
            return(stringExercise.ValidSolutions.Any(s => s.Value == inputStr));
        }

        // Compare against specific solutions
        return(stringExercise.ValidSolutions.FirstOrDefault(s => s.Name == SolutionName)?.Value == inputStr);
    }
示例#7
0
 /// <summary>
 /// Returns a description string for the given exercise, with placeholders replaced by values from this state.
 /// </summary>
 /// <param name="exercise">Exercise data.</param>
 /// <returns></returns>
 public abstract string FormatDescriptionString(LabConfigurationExerciseEntry exercise);
示例#8
0
 /// <summary>
 /// Returns whether the given input is a valid solution.
 /// </summary>
 /// <param name="exercise">Exercise data.</param>
 /// <param name="input">Input.</param>
 /// <returns></returns>
 public abstract bool ValidateInput(LabConfigurationExerciseEntry exercise, object input);
示例#9
0
 /// <summary>
 /// Checks whether the internal state is still consistent with the given exercise data, and updates it if necessary.
 /// The return value indicates whether the state has been updated.
 /// </summary>
 /// <param name="exercise">Exercise data.</param>
 public abstract bool Update(LabConfigurationExerciseEntry exercise);
 public override string FormatDescriptionString(LabConfigurationExerciseEntry exercise)
 {
     return(exercise.DescriptionFormat ?? "");
 }
 public override bool Update(LabConfigurationExerciseEntry exercise)
 {
     return(true);
 }
 public override bool ValidateInput(LabConfigurationExerciseEntry exercise, object input)
 {
     // Input validation is left to state service
     throw new NotSupportedException("Script exercises must be checked using the Docker service.");
 }