private static dynamic GetCorrection(Submission s, AllAttempts attempts, IList <Question> questions, GradingRules rules, out string name) { Attempt attempt = attempts.GetAttempt(s.UserId, s.Attempt); name = attempt.UserName; JObject questionsObj = null; foreach (Question q in questions) { Answer realAnswer = attempt.GetAnswer(q.Id); Answer ruleAnswer = rules.GetAnswer(q.Id, realAnswer.Text); if (realAnswer.Points != ruleAnswer.Points || ruleAnswer.Comment.Length > 0) { if (questionsObj == null) { questionsObj = new JObject(); } JObject change = new JObject(); if (realAnswer.Points != ruleAnswer.Points) { change["score"] = ruleAnswer.Points; } if (ruleAnswer.Comment.Length > 0) { change["comment"] = ruleAnswer.Comment; } questionsObj[q.Id.ToString()] = change; } } if (questionsObj != null) { JObject correction = new JObject(); JArray items = new JArray(); correction["quiz_submissions"] = items; JObject attemptObj = new JObject(); items.Add(attemptObj); attemptObj["attempt"] = s.Attempt; attemptObj["questions"] = questionsObj; return(correction); } else { return(null); } }
private static AllAttempts GetAllAttempts(List <Question> questions) { using (HttpClient client = CanvasHttp.MakeClient()) { string url = String.Format("/api/v1/courses/{0}/quizzes/{1}/reports", Auth.COURSE_ID, quizID); var inputs = new Dictionary <string, string>(); inputs["quiz_report[report_type]"] = "student_analysis"; inputs["quiz_report[includes_all_versions]"] = "true"; while (true) { var content = new FormUrlEncodedContent(inputs); HttpResponseMessage response = client.PostAsync(url, content).Result; if (response.IsSuccessStatusCode) { dynamic qs = JObject.Parse(response.Content.ReadAsStringAsync().Result); if (qs.file != null) { using (StreamReader reader = new StreamReader(WebRequest.Create(qs.file.url.ToString()).GetResponse().GetResponseStream())) { using (CsvReader parser = new CsvReader(reader)) { AllAttempts attempts = new AllAttempts(parser, questions); return(attempts); } } } else { Console.WriteLine("Waiting for quiz report to be generated by Canvas..."); Thread.Sleep(1000); } } else if (response.StatusCode == HttpStatusCode.Conflict) { Console.WriteLine("Waiting for quiz report to be generated by Canvas..."); Thread.Sleep(1000); } else { Console.WriteLine("Error: " + response.StatusCode); Console.WriteLine(response.ReasonPhrase.ToString()); Console.WriteLine("Unable to obtain quiz analysis"); throw new Exception(); } } } }
public GradingRules(List <Question> questions, AllAttempts allAttempts) { answerMap = new Dictionary <int, SortedSet <Answer> >(); foreach (Question question in questions) { answerMap[question.Id] = new SortedSet <Answer>(); } foreach (Attempt attempt in allAttempts.GetAttempts()) { Count++; foreach (Question question in questions) { Answer answer = attempt.GetAnswer(question.Id); if (answer.Text.Length > 0) { answerMap[question.Id].Add(answer); } } } }
public static void GetAnswers() { // Get the short-answer questions that appear on the quiz List <Question> questions = GetQuestions(); Console.WriteLine(questions.Count + " short answer questions found"); // Get information about all submissions to the quiz AllAttempts allAttempts = GetAllAttempts(questions); Console.WriteLine(allAttempts.Count + " attempts found"); // Organize into grading rules GradingRules rules = new GradingRules(questions, allAttempts); // Write the information to a CSV Console.Write("Write results to " + GetQuizFilename() + "? [y/n] "); if (Console.ReadLine().Trim().ToLower() == "y") { WriteAnalysis(questions, rules); } }
public static void SetScores() { // Get information about all of the short answer questions that appear on the quiz List <Question> questions = GetQuestions(); Console.WriteLine(questions.Count + " short answer questions found"); // Get information about all submissions to the quiz List <Submission> submissions = GetSubmissions(); Console.WriteLine(submissions.Count + " submissions found"); // Get information about attempts AllAttempts attempts = GetAllAttempts(questions); Console.WriteLine(attempts.Count + " attempts found"); // Read the grading rules for this quiz GradingRules rules; using (var input = new CsvReader(new StreamReader(@"..\..\" + GetQuizFilename()))) { rules = new GradingRules(input); } Console.WriteLine(GetQuizFilename() + " is based on " + rules.Count + " attempts"); // Warn the user int delta = attempts.Count - rules.Count; if (delta != 0) { Console.WriteLine("There have " + delta + " attempts since " + GetQuizFilename() + " was created"); Console.WriteLine("You should recreate that file"); } // Make sure we proceed Console.Write("Update grades in Canvas? [y/n] "); if (Console.ReadLine().Trim().ToLower() != "y") { return; } // Change the grade of attempt if necessary foreach (Attempt attempt in attempts.GetAttempts()) { Submission submission = GetSubmission(submissions, attempt.UserID, attempt.Number); dynamic correction = GetCorrection(attempt, questions, rules, out string name); if (correction == null) { Console.WriteLine("unchanged (v" + attempt.Number + ") " + name); } else if (submission == null) { Console.WriteLine("*MISSING* (v" + attempt.Number + ") " + name); } else { using (HttpClient client = CanvasHttp.MakeClient()) { String url = String.Format("/api/v1/courses/{0}/quizzes/{1}/submissions/{2} ", Auth.COURSE_ID, quizID, submission.Id); var content = new StringContent(correction.ToString(), Encoding.UTF8, "application/json"); HttpResponseMessage response = client.PutAsync(url, content).Result; //HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); if (response.IsSuccessStatusCode) { Console.WriteLine("updated (v" + attempt.Number + ") " + name); } else { Console.WriteLine("*FAILED* (v" + attempt.Number + ") " + name + " " + response.StatusCode); return; } } } } }