/// <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();
                    }
                }
            }
        }
示例#2
0
        /// <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();
                        }
                    }
                }
            }
        }