/// <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(); } } } }
/// <summary> /// Obtains the logs /// </summary> public static void Main(string[] args) { // Get the course name and the Kattis problem String courseName; using (HttpClient client = CreateClient(REDIRECT)) { string url = String.Format("https://utah.instructure.com/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("Grading Kattis problem 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]; } } // Get the Kattis problem name string problemName; using (HttpClient client = CreateClient(REDIRECT)) { string url = String.Format("https://utah.instructure.com/api/v1/courses/{0}/assignments/{1}", Auth.COURSE_ID, assignID); HttpResponseMessage response = client.GetAsync(url).Result; if (response.IsSuccessStatusCode) { dynamic resp = JObject.Parse(response.Content.ReadAsStringAsync().Result); problemName = GetKattisProblemName(resp.description.ToString()); if (problemName == null) { Console.WriteLine("No Kattis problem referenced from the problem"); return; } else { Console.WriteLine("Grading Kattis problem " + problemName); problem = problems[problemName]; problem.StartDate = Convert.ToDateTime(Auth.START_TIME).ToLocalTime(); } } else { Console.WriteLine("Error: " + response.StatusCode); Console.WriteLine(response.ReasonPhrase.ToString()); Console.WriteLine("Unable to read assignment"); return; } } // Due date overrides Dictionary <int, Tuple <DateTime, DateTime> > overrides = new Dictionary <int, Tuple <DateTime, DateTime> >(); // Get the due dates and assignment name using (HttpClient client = CreateClient(AUTH)) { String url = String.Format("https://utah.instructure.com/api/v1/courses/{0}/assignments/{1}?include[]=overrides", Auth.COURSE_ID, assignID); HttpResponseMessage response = client.GetAsync(url).Result; if (response.IsSuccessStatusCode) { dynamic resp = JObject.Parse(response.Content.ReadAsStringAsync().Result); problem.DueDate = Convert.ToDateTime(resp.due_at.ToString()).ToLocalTime(); problem.LockDate = Convert.ToDateTime(resp.lock_at.ToString()).ToLocalTime(); problem.MaxGrade = Convert.ToInt32(resp.points_possible.ToString()); Console.WriteLine("Assignment: " + resp.name); Console.WriteLine("Start Date: " + problem.StartDate); Console.WriteLine("Default Due Date: " + problem.DueDate); Console.WriteLine("Default Lock Date: " + problem.LockDate); Console.WriteLine("Max Grade: " + problem.MaxGrade); foreach (dynamic oride in resp.overrides) { foreach (dynamic id in oride.student_ids) { overrides[(int)id] = new Tuple <DateTime, DateTime>(Convert.ToDateTime(oride.due_at).ToLocalTime(), Convert.ToDateTime(oride.lock_at).ToLocalTime()); } } } else { Console.WriteLine("Error obtaining due date: " + response.StatusCode); return; } } // Get the token string csrfToken; using (HttpClient client = CreateClient(REDIRECT)) { String url = "https://utah.kattis.com/login"; HttpResponseMessage response = client.GetAsync(url).Result; if (response.IsSuccessStatusCode) { string body = response.Content.ReadAsStringAsync().Result; string pattern = "name=\"csrf_token\" value=\""; int index1 = body.LastIndexOf(pattern); index1 = index1 + pattern.Length; int index2 = body.IndexOf("\"", index1); csrfToken = body.Substring(index1, index2 - index1); } else { Console.WriteLine("Error obtaining Kattis token: " + response.StatusCode); return; } } // Get the cookie using (HttpClient client = CreateClient(NONE)) { String url = "https://utah.kattis.com/login"; var values = new Dictionary <string, string> { { "user", Auth.KATTIS_LOGIN }, { "password", Auth.KATTIS_PASSWORD }, { "submit", "Submit" }, { "csrf_token", csrfToken } }; var content = new FormUrlEncodedContent(values); HttpResponseMessage response = client.PostAsync(url, content).Result; if (response.StatusCode != HttpStatusCode.Redirect) { Console.WriteLine("Error logging in to Kattis: " + response.StatusCode); return; } } // Get the data dynamic exported; using (HttpClient client = CreateClient(REDIRECT)) { String url = String.Format("https://utah.kattis.com/courses/{0}/{1}/export?type=results&submissions=all&include_testcases=true", Auth.KATTIS_COURSE, Auth.KATTIS_SEMESTER); //client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; …) Gecko/20100101 Firefox/57.0"); //client.DefaultRequestHeaders.Referrer = new Uri("https://utah.kattis.com/courses/CS4150/S18/export"); //client.DefaultRequestHeaders.Host = "utah.kattis.com"; Console.WriteLine(client.DefaultRequestHeaders.Accept); HttpResponseMessage response = client.GetAsync(url).Result; if (response.IsSuccessStatusCode) { String s = response.Content.ReadAsStringAsync().Result; exported = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result); } else { Console.WriteLine("Error obtaining Kattis data: " + response.StatusCode); return; } } // Get the number of test cases problem.PrivateTests = -1; List <Grade> grades = new List <Grade>(); foreach (dynamic student in exported.students) { foreach (dynamic submission in student.submissions) { if (submission.problem == problemName && submission.testcase_count != null) { int tests = Convert.ToInt32(submission.testcase_count.ToString()); Console.WriteLine("Total tests: " + tests); problem.PrivateTests = tests - problem.PublicTests; break; } } if (problem.PrivateTests >= 0) { break; } } if (problem.PrivateTests < 0) { Console.WriteLine("Unable to get count of tests"); return; } Dictionary <string, string> allStudents = new Dictionary <string, string>(); Dictionary <string, int> allIDs = new Dictionary <string, int>(); using (HttpClient client = CreateClient(REDIRECT | AUTH)) { string url = String.Format("https://utah.instructure.com/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.sis_user_id.ToString()] = user.name.ToString(); allIDs[user.sis_user_id.ToString()] = (int)user.id; } url = 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); } Console.WriteLine(); Console.WriteLine((compareGrades) ? "Using only students whose grades have changed" : "Using all students"); Console.WriteLine((recordGrades) ? "Recording grades" : "Not recording grades"); Console.Write("Do you want to continue? [y/n] "); String yesno = Console.ReadLine(); if (yesno != "y") { return; } Console.WriteLine(); Gradebook gradebook = new Gradebook(exported); foreach (string unid in allStudents.Keys) { // Get due and lock dates for this student. They can differ because of extensions. DateTime dueDate; DateTime lockDate; getDueAndLockDate(allIDs[unid], overrides, out dueDate, out lockDate); Grade g = gradebook.GetGrade(unid, problemName, problem, dueDate, lockDate); string compareResult = ""; if (compareGrades) { using (HttpClient client = CreateClient(REDIRECT | AUTH)) { String url = String.Format("https://utah.instructure.com/api/v1/courses/{0}/assignments/{1}/submissions/sis_user_id:{2}", Auth.COURSE_ID, assignID, unid); HttpResponseMessage response = client.GetAsync(url).Result; int oldGrade = -1; if (response.IsSuccessStatusCode) { dynamic resp = JObject.Parse(response.Content.ReadAsStringAsync().Result); string og = resp.score.ToString(); if (og == null || og == "") { oldGrade = -1; } else { oldGrade = Convert.ToInt32(resp.score.ToString()); } } if (oldGrade == -1) { compareResult = "No old grade"; } else if (g.Score != oldGrade) { compareResult = "Old grade " + oldGrade; } else { continue; } } } Console.WriteLine(); Console.WriteLine(allStudents[unid] + " " + unid); if (g.DueDate != problem.DueDate || g.LockDate != problem.LockDate) { Console.WriteLine(" " + "Due " + g.DueDate + " " + "Locked " + g.LockDate); Console.WriteLine(" " + "Due " + problem.DueDate + " " + "Locked " + problem.LockDate); } if (problem.SkipUsers.Contains(unid)) { Console.WriteLine(" Skipping"); continue; } Console.Write(" Passed: " + g.PublicTestsPassed + "/" + problem.PublicTests + " " + g.PrivateTestsPassed + "/" + problem.PrivateTests); Console.Write(" Grade: " + g.Score); if (compareGrades) { Console.Write(" (" + compareResult + ")"); } if (g.ExtraDaysUsed > 0) { Console.Write(" Extra: " + g.ExtraDaysUsed); } Console.WriteLine(); //Console.WriteLine(" " + g.Comment); if (recordGrades) { using (HttpClient client = CreateClient(REDIRECT | AUTH)) { string data = "submission[posted_grade]=" + g.Score; data += "&comment[text_comment]=" + Uri.EscapeDataString(g.Comment); string url = String.Format("https://utah.instructure.com/api/v1/courses/{0}/assignments/{1}/submissions/sis_user_id:{2}", Auth.COURSE_ID, assignID, unid); 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[unid] + " " + unid); } else { Console.WriteLine("Error: " + response.StatusCode); Console.WriteLine(response.ReasonPhrase.ToString()); Console.WriteLine(allStudents[unid] + " " + unid); Console.WriteLine(); } } } } }