2 * Copyright (c) 2016-2019 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.
26 #include <curl/curl.h>
27 #include <yajl_parse.h>
37 FN_AG_DROP_LOWEST
= 4,
38 FN_AG_DROP_HIGHEST
= 5,
53 cmp_entry_by_pos(const void *a
, const void *b
)
55 const entry
*ea
= (const entry
*) a
;
56 const entry
*eb
= (const entry
*) b
;
57 const char *sa
= ea
->vs
[FN_A_POSITION
- 1];
58 const char *sb
= eb
->vs
[FN_A_POSITION
- 1];
59 long long la
= strtoll(sa
, 0, 0);
60 long long lb
= strtoll(sb
, 0, 0);
62 return (la
< lb
) ? -1 : ((la
> lb
) ? 1 : 0);
66 write_out_everything(map
*assigns
, map
*agroups
)
71 char **agroups_positions
= 0;
72 size_t agroups_num
= 0;
75 char **unprinted_a_ids
= 0;
80 uint_fast8_t some_categorized
= 0;
81 uint_fast8_t printed_uncategorized
= 0;
83 map_get_keys(agroups
, &agroups_positions
, &agroups_num
);
84 map_get_keys(assigns
, &a_ids
, &as_num
);
86 if (!(unprinted_a_ids
= calloc(as_num
, sizeof *unprinted_a_ids
))) {
92 if (!(ca
= calloc(as_num
, sizeof *ca
))) {
98 memcpy(unprinted_a_ids
, a_ids
, as_num
* sizeof unprinted_a_ids
);
100 for (j
= 0; j
< agroups_num
; ++j
) {
101 ag
= map_get(agroups
, agroups_positions
[j
]);
107 printf("%s %s", UBSAFES(ag
[FN_AG_ID
- 1]), UBSAFES(
108 ag
[FN_AG_NAME
- 1]));
110 if (ag
[FN_AG_WEIGHT
- 1]) {
111 printf(" (%s%%)", ag
[FN_AG_WEIGHT
- 1]);
114 if (ag
[FN_AG_DROP_LOWEST
- 1] &&
115 strcmp(ag
[FN_AG_DROP_LOWEST
- 1], "0")) {
116 printf(" (Drop %s lowest)", ag
[FN_AG_DROP_LOWEST
- 1]);
119 if (ag
[FN_AG_DROP_HIGHEST
- 1] &&
120 strcmp(ag
[FN_AG_DROP_HIGHEST
- 1], "0")) {
121 printf(" (Drop %s highest)\n", ag
[FN_AG_DROP_HIGHEST
-
129 for (k
= 0; k
< as_num
; ++k
) {
130 a
= map_get(assigns
, a_ids
[k
]);
132 if (!strcmp(ag
[FN_AG_ID
- 1], a
[FN_A_GROUP_ID
- 1])) {
133 unprinted_a_ids
[k
] = 0;
134 ca
[ca_num
] = (entry
) { .k
= a_ids
[k
], .vs
= a
};
139 qsort(ca
, ca_num
, sizeof *ca
, cmp_entry_by_pos
);
141 for (k
= 0; k
< ca_num
; ++k
) {
142 some_categorized
= 1;
143 printf(" %s %s", UBSAFES(ca
[k
].k
), UBSAFES(
144 ca
[k
].vs
[FN_A_NAME
- 1]));
146 if (ca
[k
].vs
[FN_A_MAX_POINTS
- 1]) {
147 printf(" (%s)", ca
[k
].vs
[FN_A_MAX_POINTS
- 1]);
150 if (ca
[k
].vs
[FN_A_DUE_AT
- 1]) {
151 printf(" due at %s\n", ca
[k
].vs
[FN_A_DUE_AT
-
159 for (k
= 0; k
< as_num
; ++k
) {
160 if (!unprinted_a_ids
[k
]) {
164 if (some_categorized
&&
165 !printed_uncategorized
) {
166 printf("UNCATEGORIZED\n");
167 printed_uncategorized
= 1;
170 if (some_categorized
) {
174 a
= map_get(assigns
, unprinted_a_ids
[k
]);
175 printf("%s %s", unprinted_a_ids
[k
], a
[FN_A_NAME
- 1]);
177 if (a
[FN_A_MAX_POINTS
- 1]) {
178 printf(" (%s)\n", a
[FN_A_MAX_POINTS
- 1]);
186 free(agroups_positions
);
188 free(unprinted_a_ids
);
195 main(int argc
, char **argv
)
199 char *auth_token
= 0;
201 const char *fn_agroups
[] = {
203 [FN_AG_POSITION
] = "position", /* */
204 [FN_AG_NAME
] = "name", /* */
205 [FN_AG_ID
] = "id", /* */
206 [FN_AG_WEIGHT
] = "group_weight", /* */
207 [FN_AG_DROP_LOWEST
] = "drop_lowest", /* */
208 [FN_AG_DROP_HIGHEST
] = "drop_highest", /* */
209 [FN_AG_END
] = 0 /* */
211 const char *fn_assigns
[] = {
213 [FN_A_ID
] = "id", /* */
214 [FN_A_GROUP_ID
] = "assignment_group_id", /* */
215 [FN_A_POSITION
] = "position", /* */
216 [FN_A_NAME
] = "name", /* */
217 [FN_A_MAX_POINTS
] = "points_possible", /* */
218 [FN_A_DUE_AT
] = "due_at", /* */
227 setlocale(LC_ALL
, "");
229 while ((opt
= getopt(argc
, argv
, "c:")) != -1) {
241 fprintf(stderr
, "course-id is mandatory\n");
245 curl_global_init(CURL_GLOBAL_DEFAULT
);
247 if (!(url_base
= get_url_base())) {
250 /* Error should have already been printed */
254 if (!(auth_token
= get_auth_token())) {
257 /* Error should have already been printed */
262 "%s/api/v1/courses/%s/assignment_groups?per_page=9999",
267 ret
= errno
= EOVERFLOW
;
272 if (!(built_uri
= malloc(len
+ 1))) {
279 "%s/api/v1/courses/%s/assignment_groups?per_page=9999",
283 if ((ret
= key_value_extract(built_uri
, auth_token
, fn_agroups
, 0,
290 len
= snprintf(0, 0, "%s/api/v1/courses/%s/assignments?per_page=9999",
291 url_base
, course_id
);
294 ret
= errno
= EOVERFLOW
;
299 if (!(built_uri
= malloc(len
+ 1))) {
305 sprintf(built_uri
, "%s/api/v1/courses/%s/assignments?per_page=9999",
306 url_base
, course_id
);
308 if ((ret
= key_value_extract(built_uri
, auth_token
, fn_assigns
, 0,
313 if ((ret
= write_out_everything(&assigns
, &agroups
))) {
324 curl_global_cleanup();