2 * Copyright (c) 2016-2017 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,
52 static int cmp_entry_by_pos(const void *a
, const void *b
)
54 const entry
*ea
= (const entry
*) a
;
55 const entry
*eb
= (const entry
*) b
;
56 const char *sa
= ea
->vs
[FN_A_POSITION
- 1];
57 const char *sb
= eb
->vs
[FN_A_POSITION
- 1];
58 long long la
= strtoll(sa
, 0, 0);
59 long long lb
= strtoll(sb
, 0, 0);
61 return (la
< lb
) ? -1 : ((la
> lb
) ? 1 : 0);
64 static int write_out_everything(map
*assigns
, map
*agroups
)
69 char **agroups_positions
= 0;
70 size_t agroups_num
= 0;
73 char **unprinted_a_ids
= 0;
78 uint_fast8_t some_categorized
= 0;
79 uint_fast8_t printed_uncategorized
= 0;
81 map_get_keys(agroups
, &agroups_positions
, &agroups_num
);
82 map_get_keys(assigns
, &a_ids
, &as_num
);
84 if (!(unprinted_a_ids
= calloc(as_num
, sizeof *unprinted_a_ids
))) {
90 if (!(ca
= calloc(as_num
, sizeof *ca
))) {
96 memcpy(unprinted_a_ids
, a_ids
, as_num
* sizeof unprinted_a_ids
);
98 for (j
= 0; j
< agroups_num
; ++j
) {
99 ag
= map_get(agroups
, agroups_positions
[j
]);
105 printf("%s %s", UBSAFES(ag
[FN_AG_ID
- 1]), UBSAFES(
106 ag
[FN_AG_NAME
- 1]));
108 if (ag
[FN_AG_WEIGHT
- 1]) {
109 printf(" (%s%%)", ag
[FN_AG_WEIGHT
- 1]);
112 if (ag
[FN_AG_DROP_LOWEST
- 1] &&
113 strcmp(ag
[FN_AG_DROP_LOWEST
- 1], "0")) {
114 printf(" (Drop %s lowest)", ag
[FN_AG_DROP_LOWEST
- 1]);
117 if (ag
[FN_AG_DROP_HIGHEST
- 1] &&
118 strcmp(ag
[FN_AG_DROP_HIGHEST
- 1], "0")) {
119 printf(" (Drop %s highest)\n", ag
[FN_AG_DROP_HIGHEST
-
127 for (k
= 0; k
< as_num
; ++k
) {
128 a
= map_get(assigns
, a_ids
[k
]);
130 if (!strcmp(ag
[FN_AG_ID
- 1], a
[FN_A_GROUP_ID
- 1])) {
131 unprinted_a_ids
[k
] = 0;
132 ca
[ca_num
] = (entry
) { .k
= a_ids
[k
], .vs
= a
};
137 qsort(ca
, ca_num
, sizeof *ca
, cmp_entry_by_pos
);
139 for (k
= 0; k
< ca_num
; ++k
) {
140 some_categorized
= 1;
141 printf(" %s %s", UBSAFES(ca
[k
].k
), UBSAFES(
142 ca
[k
].vs
[FN_A_NAME
- 1]));
144 if (ca
[k
].vs
[FN_A_MAX_POINTS
- 1]) {
145 printf(" (%s)", ca
[k
].vs
[FN_A_MAX_POINTS
- 1]);
148 if (ca
[k
].vs
[FN_A_DUE_AT
- 1]) {
149 printf(" due at %s\n", ca
[k
].vs
[FN_A_DUE_AT
-
157 for (k
= 0; k
< as_num
; ++k
) {
158 if (!unprinted_a_ids
[k
]) {
162 if (some_categorized
&&
163 !printed_uncategorized
) {
164 printf("UNCATEGORIZED\n");
165 printed_uncategorized
= 1;
168 if (some_categorized
) {
172 a
= map_get(assigns
, unprinted_a_ids
[k
]);
173 printf("%s %s", unprinted_a_ids
[k
], a
[FN_A_NAME
- 1]);
175 if (a
[FN_A_MAX_POINTS
- 1]) {
176 printf(" (%s)\n", a
[FN_A_MAX_POINTS
- 1]);
184 free(agroups_positions
);
186 free(unprinted_a_ids
);
192 int main(int argc
, char **argv
)
196 char *auth_token
= 0;
198 const char *fn_agroups
[] = {
200 [FN_AG_POSITION
] = "position", /* */
201 [FN_AG_NAME
] = "name", /* */
202 [FN_AG_ID
] = "id", /* */
203 [FN_AG_WEIGHT
] = "group_weight", /* */
204 [FN_AG_DROP_LOWEST
] = "drop_lowest", /* */
205 [FN_AG_DROP_HIGHEST
] = "drop_highest", /* */
206 [FN_AG_END
] = 0 /* */
208 const char *fn_assigns
[] = {
210 [FN_A_ID
] = "id", /* */
211 [FN_A_GROUP_ID
] = "assignment_group_id", /* */
212 [FN_A_POSITION
] = "position", /* */
213 [FN_A_NAME
] = "name", /* */
214 [FN_A_MAX_POINTS
] = "points_possible", /* */
215 [FN_A_DUE_AT
] = "due_at", /* */
224 setlocale(LC_ALL
, "");
226 while ((opt
= getopt(argc
, argv
, "c:")) != -1) {
238 fprintf(stderr
, "course-id is mandatory\n");
242 curl_global_init(CURL_GLOBAL_DEFAULT
);
244 if (!(url_base
= get_url_base())) {
247 /* Error should have already been printed */
251 if (!(auth_token
= get_auth_token())) {
254 /* Error should have already been printed */
259 "%s/api/v1/courses/%s/assignment_groups?per_page=9999",
264 ret
= errno
= EOVERFLOW
;
269 if (!(built_uri
= malloc(len
+ 1))) {
276 "%s/api/v1/courses/%s/assignment_groups?per_page=9999",
280 if ((ret
= key_value_extract(built_uri
, auth_token
, fn_agroups
, 0,
287 len
= snprintf(0, 0, "%s/api/v1/courses/%s/assignments?per_page=9999",
288 url_base
, course_id
);
291 ret
= errno
= EOVERFLOW
;
296 if (!(built_uri
= malloc(len
+ 1))) {
302 sprintf(built_uri
, "%s/api/v1/courses/%s/assignments?per_page=9999",
303 url_base
, course_id
);
305 if ((ret
= key_value_extract(built_uri
, auth_token
, fn_assigns
, 0,
310 if ((ret
= write_out_everything(&assigns
, &agroups
))) {
321 curl_global_cleanup();