2 * Copyright (c) 2016, S. Gilles <sgilles@math.umd.edu>
4 * Permission to use, copy, modify, and/or distribute this software
5 * for any purpose with or without fee is hereby granted, provided
6 * that the above copyright notice and this permission notice appear
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
13 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
14 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 #include <curl/curl.h>
28 #include <yajl_parse.h>
33 /* Write output to stdout */
34 static void write_out_everything(char *course_id
, map
*students
, map
**grades
,
35 map
*totals
, size_t assignments_num
,
36 char **assignment_ids
, map
*assignments
)
40 char **student_names
= 0;
47 map_get_keys(students
, &student_names
, &students_num
);
48 printf("\"Name\",\"ID\"");
50 for (j
= 0; j
< assignments_num
; ++j
) {
51 printf(",\"%s:%s (", course_id
, assignment_ids
[j
]);
52 res
= map_get(assignments
, assignment_ids
[j
]);
56 print_esc_0x22(res
[0]);
63 printf(",\"Total\",\"Letter Grade\"");
68 for (j
= 0; j
< students_num
; ++j
) {
69 name
= student_names
[j
];
70 id
= map_get(students
, name
);
79 printf("\",\"%s\"", id
[0]);
81 for (k
= 0; k
< assignments_num
; ++k
) {
82 score
= map_get(&((*grades
)[k
]), id
[0]);
87 !strcasecmp(score
[1], "true")) {
91 print_esc_0x22(score
[0]);
98 score
= map_get(totals
, id
[0]);
103 print_esc_0x22(score
[0]);
110 print_esc_0x22(score
[1]);
122 int main(int argc
, char **argv
)
126 char *auth_token
= 0;
128 const char *fn_students
[] = { "sortable_name", "id", 0 };
129 const char *fn_scores
[] = { "user_id", "score", "excused", 0 };
130 const char *fn_totals
[] = { "user_id", "final_score", "final_grade",
132 const char *fn_assignments
[] = { "id", "name", 0 };
133 uint_fast8_t fetch_all_arg
= 0;
134 uint_fast8_t totals_arg
= 0;
135 char **assignment_ids
= 0;
136 map students
= { 0 };
139 map assignments
= { 0 };
141 size_t assignments_num
= 0;
146 setlocale(LC_ALL
, "");
148 if (!(assignment_ids
= calloc((argc
/ 2), sizeof *assignment_ids
))) {
154 while ((opt
= getopt(argc
, argv
, "c:a:At")) != -1) {
160 assignment_ids
[assignments_num
++] = optarg
;
175 fprintf(stderr
, "both -A and -a provided, ignoring -a\n");
180 fprintf(stderr
, "course-id is mandatory\n");
184 if (!fetch_all_arg
&&
188 fprintf(stderr
, "one of -a, -A, -t is mandatory\n");
192 if (!(grades
= calloc(assignments_num
, sizeof *grades
))) {
198 curl_global_init(CURL_GLOBAL_DEFAULT
);
200 if (!(url_base
= get_url_base())) {
201 /* Error should have already been printed */
206 if (!(auth_token
= get_auth_token())) {
207 /* Error should have already been printed */
212 /* Get a list of all students, so we can find out their names */
213 len
= snprintf(0, 0, "%s/api/v1/courses/%s/students?per_page=9999",
214 url_base
, course_id
);
217 ret
= errno
= EOVERFLOW
;
222 if (!(built_uri
= malloc(len
+ 1))) {
228 sprintf(built_uri
, "%s/api/v1/courses/%s/students?per_page=9999",
229 url_base
, course_id
);
231 if ((ret
= key_value_extract(built_uri
, auth_token
, fn_students
, 0,
236 /* Get a list of all assignments, so we can find out their names */
238 len
= snprintf(0, 0, "%s/api/v1/courses/%s/assignments?per_page=9999",
239 url_base
, course_id
);
242 ret
= errno
= EOVERFLOW
;
247 if (!(built_uri
= malloc(len
+ 1))) {
253 sprintf(built_uri
, "%s/api/v1/courses/%s/assignments?per_page=9999",
254 url_base
, course_id
);
256 if ((ret
= key_value_extract(built_uri
, auth_token
, fn_assignments
, 0,
263 free(assignment_ids
);
267 map_get_keys(&assignments
, &assignment_ids
, &assignments_num
);
269 if (!assignments_num
) {
271 perror(L("map_get_keys"));
275 if (!(grades
= calloc(assignments_num
, sizeof *grades
))) {
282 for (j
= 0; j
< assignments_num
; ++j
) {
284 len
= snprintf(0, 0, "%s/api/v1/courses/%s/assignments/%s/"
285 "submissions?per_page=9999", url_base
,
290 ret
= errno
= EOVERFLOW
;
295 if (!(built_uri
= malloc(len
+ 1))) {
301 sprintf(built_uri
, "%s/api/v1/courses/%s/assignments/%s/"
302 "submissions?per_page=9999", url_base
,
306 if ((ret
= key_value_extract(built_uri
, auth_token
, fn_scores
,
315 "%s/api/v1/courses/%s/enrollments?per_page=9999",
320 ret
= errno
= EOVERFLOW
;
325 if (!(built_uri
= malloc(len
+ 1))) {
332 "%s/api/v1/courses/%s/enrollments?per_page=9999",
336 if ((ret
= key_value_extract(built_uri
, auth_token
, fn_totals
,
342 write_out_everything(course_id
, &students
, &grades
, (totals_arg
?
344 assignments_num
, assignment_ids
, &assignments
);
350 curl_global_cleanup();
351 free(assignment_ids
);
352 map_clean(&students
);
353 map_clean(&assignments
);
356 if (assignments_num
) {
358 map_clean(&grades
[--assignments_num
]);
359 } while (assignments_num
);