implemented hack to canvas quiz

This commit is contained in:
2023-08-18 17:18:23 -06:00
parent 6a76172231
commit f02ead7178
4 changed files with 76 additions and 31 deletions

View File

@@ -71,6 +71,9 @@ public record CanvasAssignment
[property: JsonPropertyName("allowed_attempts")] [property: JsonPropertyName("allowed_attempts")]
int AllowedAttempts, int AllowedAttempts,
[property: JsonPropertyName("is_quiz_assignment")]
bool IsQuizAssignment,
[property: JsonPropertyName("submission_types")] [property: JsonPropertyName("submission_types")]
IEnumerable<string> SubmissionTypes, IEnumerable<string> SubmissionTypes,

View File

@@ -19,7 +19,7 @@ public class CanvasAssignmentService
{ {
var url = $"courses/{courseId}/assignments"; var url = $"courses/{courseId}/assignments";
var request = new RestRequest(url); var request = new RestRequest(url);
request.AddParameter("include[]", "overrides"); // request.AddParameter("include[]", "overrides");
var assignmentResponse = await utils.PaginatedRequest<IEnumerable<CanvasAssignment>>(request); var assignmentResponse = await utils.PaginatedRequest<IEnumerable<CanvasAssignment>>(request);
return assignmentResponse.SelectMany( return assignmentResponse.SelectMany(
assignments => assignments =>

View File

@@ -1,3 +1,5 @@
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using CanvasModel.Quizzes; using CanvasModel.Quizzes;
using LocalModels; using LocalModels;
using RestSharp; using RestSharp;
@@ -8,11 +10,17 @@ public class CanvasQuizService
{ {
private readonly IWebRequestor webRequestor; private readonly IWebRequestor webRequestor;
private readonly CanvasServiceUtils utils; private readonly CanvasServiceUtils utils;
private readonly CanvasAssignmentService assignments;
public CanvasQuizService(IWebRequestor webRequestor, CanvasServiceUtils utils) public CanvasQuizService(
IWebRequestor webRequestor,
CanvasServiceUtils utils,
CanvasAssignmentService assignments
)
{ {
this.webRequestor = webRequestor; this.webRequestor = webRequestor;
this.utils = utils; this.utils = utils;
this.assignments = assignments;
} }
public async Task<IEnumerable<CanvasQuiz>> GetAll(ulong courseId) public async Task<IEnumerable<CanvasQuiz>> GetAll(ulong courseId)
@@ -56,7 +64,6 @@ public class CanvasQuizService
if (canvasQuiz == null) if (canvasQuiz == null)
throw new Exception("Created canvas quiz was null"); throw new Exception("Created canvas quiz was null");
var updatedQuiz = localQuiz with { CanvasId = canvasQuiz.Id }; var updatedQuiz = localQuiz with { CanvasId = canvasQuiz.Id };
var quizWithQuestions = await CreateQuizQuestions(canvasCourseId, updatedQuiz); var quizWithQuestions = await CreateQuizQuestions(canvasCourseId, updatedQuiz);
@@ -65,33 +72,67 @@ public class CanvasQuizService
public async Task<LocalQuiz> CreateQuizQuestions(ulong canvasCourseId, LocalQuiz localQuiz) public async Task<LocalQuiz> CreateQuizQuestions(ulong canvasCourseId, LocalQuiz localQuiz)
{ {
var tasks = localQuiz.Questions var tasks = localQuiz.Questions.Select(createQuestion(canvasCourseId, localQuiz)).ToArray();
.Select( var updatedQuestions = await Task.WhenAll(tasks);
async (question) =>
{
var newQuestion = await createQuestionOnly(canvasCourseId, localQuiz, question);
var answersWithIds = question.Answers await hackFixRedundantAssignments(canvasCourseId);
.Select(answer => return localQuiz with { Questions = updatedQuestions };
{ }
var canvasAnswer = newQuestion.Answers?.FirstOrDefault(ca => ca.Html == answer.Text);
if (canvasAnswer == null) private async Task hackFixRedundantAssignments(ulong canvasCourseId)
{ {
Console.WriteLine(JsonSerializer.Serialize(newQuestion)); var canvasAssignments = await assignments.GetAll(canvasCourseId);
Console.WriteLine(JsonSerializer.Serialize(question));
throw new NullReferenceException( var assignmentsToDelete = canvasAssignments
"Could not find canvas answer to update local answer id" .Where(
); assignment =>
} !assignment.IsQuizAssignment
return answer with { CanvasId = canvasAnswer.Id }; && assignment.SubmissionTypes.Contains(SubmissionType.ONLINE_QUIZ)
})
.ToArray();
return question with { CanvasId = newQuestion.Id, Answers = answersWithIds };
}
) )
.ToArray(); .ToArray();
var updatedQuestions = await Task.WhenAll(tasks); var tasks = assignmentsToDelete.Select(
return localQuiz with { Questions = updatedQuestions }; async (a) =>
{
await assignments.Delete(
canvasCourseId,
new LocalAssignment { Name = a.Name, CanvasId = a.Id }
);
}
);
await Task.WhenAll(tasks);
}
private Func<LocalQuizQuestion, Task<LocalQuizQuestion>> createQuestion(
ulong canvasCourseId,
LocalQuiz localQuiz
)
{
return async (question) =>
{
var newQuestion = await createQuestionOnly(canvasCourseId, localQuiz, question);
var answersWithIds = question.Answers
.Select(answer =>
{
var canvasAnswer = newQuestion.Answers?.FirstOrDefault(ca => ca.Html == answer.Text);
if (canvasAnswer == null)
{
Console.WriteLine(JsonSerializer.Serialize(newQuestion));
Console.WriteLine(JsonSerializer.Serialize(question));
throw new NullReferenceException(
"Could not find canvas answer to update local answer id"
);
}
return answer with { CanvasId = canvasAnswer.Id };
})
.ToArray();
return question with
{
CanvasId = newQuestion.Id,
Answers = answersWithIds
};
};
} }
private async Task<CanvasQuizQuestion> createQuestionOnly( private async Task<CanvasQuizQuestion> createQuestionOnly(
@@ -109,8 +150,8 @@ public class CanvasQuizService
question = new question = new
{ {
question_text = q.Text, question_text = q.Text,
question_type = q.QuestionType+"_question", question_type = q.QuestionType + "_question",
possible_points = q.Points, points_possible = q.Points,
// position // position
answers answers
} }
@@ -120,6 +161,7 @@ public class CanvasQuizService
var (newQuestion, response) = await webRequestor.PostAsync<CanvasQuizQuestion>(request); var (newQuestion, response) = await webRequestor.PostAsync<CanvasQuizQuestion>(request);
if (newQuestion == null) if (newQuestion == null)
throw new NullReferenceException("error creating new question, created question is null"); throw new NullReferenceException("error creating new question, created question is null");
return newQuestion; return newQuestion;
} }
} }

View File

@@ -7,13 +7,13 @@ GET https://snow.instructure.com/api/v1/courses/871954/assignments
Authorization: Bearer {{$dotenv CANVAS_TOKEN}} Authorization: Bearer {{$dotenv CANVAS_TOKEN}}
### ###
POST https://snow.instructure.com/api/v1/courses/871954/quizzes/3236013/questions POST https://snow.instructure.com/api/v1/courses/871954/quizzes/3243305/questions
Authorization: Bearer {{$dotenv CANVAS_TOKEN}} Authorization: Bearer {{$dotenv CANVAS_TOKEN}}
Content-Type: application/json Content-Type: application/json
{ {
"question":{ "question":{
"question_text": "Other clues to how things work come from their visible structure. Specifically from _____, _____, and _____", "question_text": "dummy question via the api",
"question_type": "multiple_answers_question", "question_type": "multiple_answers_question",
"points_possible": 3, "points_possible": 3,
"answers": [ "answers": [