/// <summary> /// Get information about all submissions made to the quiz /// </summary> private static List <Submission> GetSubmissions() { List <Submission> submissions = new List <Submission>(); using (HttpClient client = CanvasHttp.MakeClient()) { string url = String.Format("/api/v1/courses/{0}/quizzes/{1}/submissions?per_page=100", Auth.COURSE_ID, quizID); while (url != null) { HttpResponseMessage response = client.GetAsync(url).Result; if (response.IsSuccessStatusCode) { dynamic data = JObject.Parse(response.Content.ReadAsStringAsync().Result); data = data.quiz_submissions; foreach (dynamic submission in data) { submissions.Add(new Submission(submission)); } } else { Console.WriteLine("Error: " + response.StatusCode); Console.WriteLine(response.ReasonPhrase.ToString()); Console.WriteLine("Unable to read course"); throw new Exception(); } url = GetNextURL(response.Headers); } return(submissions); } }
/// <summary> /// Returns information about all short-answer questions that appear on the quiz /// </summary> /// <returns></returns> private static List <Question> GetQuestions() { List <Question> questions = new List <Question>(); using (HttpClient client = CanvasHttp.MakeClient()) { string url = String.Format("/api/v1/courses/{0}/quizzes/{1}/questions?per_page=100", Auth.COURSE_ID, quizID); while (url != null) { HttpResponseMessage response = client.GetAsync(url).Result; if (response.IsSuccessStatusCode) { dynamic qs = JArray.Parse(response.Content.ReadAsStringAsync().Result); foreach (dynamic question in qs) { if (question.question_type == "short_answer_question") { questions.Add(new Question(question)); } } } else { Console.WriteLine("Error: " + response.StatusCode); Console.WriteLine(response.ReasonPhrase.ToString()); Console.WriteLine("Unable to read question information"); throw new Exception(); } url = GetNextURL(response.Headers); } return(questions); } }
private static List <string> GetQuizIDs(string quizName) { List <string> quizIDs = new List <string>(); using (HttpClient client = CanvasHttp.MakeClient()) { string url = String.Format("/api/v1/courses/{0}/quizzes?search_term={1}&per_page=100", Auth.COURSE_ID, quizName); while (url != null) { HttpResponseMessage response = client.GetAsync(url).Result; if (response.IsSuccessStatusCode) { dynamic quizzes = JArray.Parse(response.Content.ReadAsStringAsync().Result); foreach (dynamic quiz in quizzes) { if (quiz.title == quizName) { quizIDs.Add(quiz.id.ToString()); } } } else { Console.WriteLine("Error: " + response.StatusCode); Console.WriteLine(response.ReasonPhrase.ToString()); Console.WriteLine("Unable to read quiz information"); throw new Exception(); } url = GetNextURL(response.Headers); } return(quizIDs); } }
private static List <KeyValuePair <string, string> > GetInputs(Submission submission, IList <Question> questions) { using (HttpClient client = CanvasHttp.MakeClient()) { string url = String.Format("/courses/{0}/quizzes/{1}/history?headless=1&hide_student_name=0&score_updated=1&user_id={2}&version={3}", Auth.COURSE_ID, quizID, submission.UserId, submission.Attempt); HttpResponseMessage response = client.GetAsync(url).Result; if (response.IsSuccessStatusCode) { string page = response.Content.ReadAsStringAsync().Result; //Console.WriteLine(page); List <KeyValuePair <string, string> > inputs = new List <KeyValuePair <string, string> >(); int inputIndex = page.IndexOf("<input "); while (inputIndex >= 0) { int nameIndex = page.IndexOf("name=\"", inputIndex) + 6; int valueIndex = page.IndexOf("value=\"", inputIndex) + 7; int nameQuote = page.IndexOf("\"", nameIndex); int valueQuote = page.IndexOf("\"", valueIndex); string name = page.Substring(nameIndex, nameQuote - nameIndex); string value = page.Substring(valueIndex, valueQuote - valueIndex); if (name != "answer_text") { inputs.Add(new KeyValuePair <string, string>(name, value)); } inputIndex = page.IndexOf("<input ", inputIndex + 1); } int textIndex = page.IndexOf("<textarea "); while (textIndex >= 0) { int nameIndex = page.IndexOf("name=\"", textIndex) + 6; int valueIndex = page.IndexOf(">", textIndex) + 1; int nameQuote = page.IndexOf("\"", nameIndex); int valueEnd = page.IndexOf("</textarea>", valueIndex); string name = page.Substring(nameIndex, nameQuote - nameIndex); string value = page.Substring(valueIndex, valueEnd - valueIndex); inputs.Add(new KeyValuePair <string, string>(name, value)); textIndex = page.IndexOf("<textarea ", textIndex + 1); } return(inputs); } else { Console.WriteLine("Error: " + (int)response.StatusCode); Console.WriteLine(response.ReasonPhrase.ToString()); Console.WriteLine("Unable to read page"); throw new Exception(); } } }
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(); } } } }
private static string GetCourseName() { using (HttpClient client = CanvasHttp.MakeClient()) { string url = String.Format("/api/v1/courses/{0}", Auth.COURSE_ID); HttpResponseMessage response = client.GetAsync(url).Result; if (response.IsSuccessStatusCode) { dynamic course = JObject.Parse(response.Content.ReadAsStringAsync().Result); return(course.name); } else { Console.WriteLine("Error: " + response.StatusCode); Console.WriteLine(response.ReasonPhrase.ToString()); Console.WriteLine("Unable to read course information"); throw new Exception(); } } }
/// <summary> /// Accumulate answers given to the questions in the submission /// </summary> /// <param name="questions"></param> /// <param name="answers"></param> private static void AddAnswers(Submission submission, IList <Question> questions, Dictionary <int, SortedSet <string> > answers) { using (HttpClient client = CanvasHttp.MakeClient()) { string url = String.Format("/courses/{0}/quizzes/{1}/history?headless=1&user_id={2}&version={3}", Auth.COURSE_ID, quizID, submission.UserId, submission.Attempt); HttpResponseMessage response = client.GetAsync(url).Result; if (response.IsSuccessStatusCode) { string page = response.Content.ReadAsStringAsync().Result; foreach (Question q in questions) { int start = page.IndexOf("<input type=\"text\" name=\"question_" + q.Id + "\""); start = page.IndexOf("value=\"", start) + 7; int stop = page.IndexOf("\"", start); String value = page.Substring(start, stop - start); SortedSet <string> set; if (answers.TryGetValue(q.Position, out set)) { set.Add(value.Trim()); } else { set = new SortedSet <string>(); answers[q.Position] = set; } } } else { Console.WriteLine("Error: " + (int)response.StatusCode); Console.WriteLine(response.ReasonPhrase.ToString()); Console.WriteLine("Unable to read course"); return; } } }
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; } } } } }
/// <summary> /// Adds a note to each student's grade /// </summary> public static void Main(string[] args) { // Get the course name String courseName = ""; using (HttpClient client = CanvasHttp.MakeClient()) { string url = String.Format("/api/v1/courses/{0}", Auth.COURSE_ID); HttpResponseMessage response = client.GetAsync(url).Result; if (response.IsSuccessStatusCode) { dynamic resp = JObject.Parse(response.Content.ReadAsStringAsync().Result); courseName = resp.name; Console.WriteLine("Labeler for " + courseName); } else { Console.WriteLine("Error: " + response.StatusCode); Console.WriteLine(response.ReasonPhrase.ToString()); Console.WriteLine("Unable to read course"); return; } } // Get the assignment ID string assignID; Console.Write("Enter assignment name: "); string assignName = Console.ReadLine(); List <string> assignmentIDs = CanvasHttp.GetAssignmentIDs(assignName); if (assignmentIDs.Count == 0) { Console.WriteLine("There is no assigment by that name"); return; } else if (assignmentIDs.Count > 1) { Console.WriteLine("There are " + assignmentIDs.Count + " assignments by that name"); return; } else { assignID = assignmentIDs[0]; } // Confirm with the user Console.WriteLine("You are about to label the submissions for " + courseName + " " + assignName + " with this message: "); Console.WriteLine(); Console.WriteLine(message); Console.WriteLine(); Console.WriteLine("Do you want to continue? [y/n]"); String yesno = Console.ReadLine(); if (yesno != "y") { return; } // Get the students Dictionary <string, string> allStudents = new Dictionary <string, string>(); using (HttpClient client = CanvasHttp.MakeClient()) { string url = String.Format("/api/v1/courses/{0}/search_users?enrollment_type[]=student&per_page=200", Auth.COURSE_ID); while (url != null) { HttpResponseMessage response = client.GetAsync(url).Result; if (response.IsSuccessStatusCode) { dynamic resp = JArray.Parse(response.Content.ReadAsStringAsync().Result); foreach (dynamic user in resp) { allStudents[user.id.ToString()] = user.name.ToString(); //allStudents[user.sis_user_id.ToString()] = user.name.ToString(); } url = CanvasHttp.GetNextURL(response.Headers); } else { Console.WriteLine("Error: " + response.StatusCode); Console.WriteLine(response.ReasonPhrase.ToString()); Console.WriteLine("Unable to read users"); return; } } Console.WriteLine("Student count: " + allStudents.Count); } // Do the labeling foreach (string id in allStudents.Keys) { using (HttpClient client = CanvasHttp.MakeClient()) { string data = "&comment[text_comment]=" + Uri.EscapeDataString(message); string url = String.Format("/api/v1/courses/{0}/assignments/{1}/submissions/{2}", Auth.COURSE_ID, assignID, id); //string url = String.Format("/api/v1/courses/{0}/assignments/{1}/submissions/sis_user_id:{2}", courseID, assignID, id); StringContent content = new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded"); HttpResponseMessage response = client.PutAsync(url, content).Result; if (response.IsSuccessStatusCode) { Console.WriteLine("Success: " + allStudents[id] + " " + id); } else { Console.WriteLine("Error: " + response.StatusCode); Console.WriteLine(response.ReasonPhrase.ToString()); Console.WriteLine(allStudents[id] + " " + id); Console.WriteLine(); } } } }