added package status option
[ppastats.git] / src / html.c
1 /*
2     Copyright (C) 2011 jeanfi@gmail.com
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17     02110-1301 USA
18 */
19
20 #include <string.h>
21
22 #include "html.h"
23 #include "list.h"
24 #include "lp_ws.h"
25
26 #include <json/json.h>
27
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 #define HTML_TEMPLATE \
32 "<html>\n\
33   <head>\n\
34     <script type='text/javascript'\
35             src='https://www.google.com/jsapi'></script>\n\
36     <script type='text/javascript'>\n\
37       google.load('visualization', '1', {packages:['corechart']});\
38       google.setOnLoadCallback(drawChart);\n\
39       function drawChart() {\n\
40         var data = new google.visualization.DataTable();\n\
41         data.addColumn('string', 'Date');\n\
42 %s\
43         data.addRows(%s);\n\
44         data.sort(0);\n\
45         var chart = new google.visualization.LineChart\
46                 (document.getElementById('chart_div'));\n\
47         chart.draw(data, {width: 1024, height: 768,\
48                           title: 'PPA Statistics'});\n\
49       }\n\
50     </script>\n\
51   </head>\n\
52 \n\
53   <body>\n\
54     <div id='chart_div'></div>\n\
55   </body>\n\
56 </html>\n"
57
58 static json_object *
59 get_count_array(json_object *data, const char *date)
60 {
61         int n, i;
62         json_object *o, *o_date;
63         const char *date2;
64
65         n = json_object_array_length(data);
66         for (i = 0; i < n; i++) {
67                 o = json_object_array_get_idx(data, i);
68                 o_date = json_object_array_get_idx(o, 0);
69                 date2 = json_object_get_string(o_date);
70
71                 if (!strcmp(date2, date))
72                         return o;
73         }
74
75         return NULL;
76 }
77
78 static json_object *count_array_new(json_object *data, const char *d, int n)
79 {
80         json_object *result = json_object_new_array();
81         int i;
82
83         json_object_array_add(result, json_object_new_string(d));
84
85         for (i = 0; i < n; i++)
86                 json_object_array_add(result, json_object_new_int(0));
87
88         json_object_array_add(data, result);
89
90         return result;
91 }
92
93 static char *
94 build_package_display_name(struct binary_package_publishing_history *b)
95 {
96         char *str = malloc(strlen(b->binary_package_name)+
97                            1+
98                            strlen(b->binary_package_version)+
99                            1);
100
101         sprintf(str, "%s-%s",
102                 b->binary_package_name, b->binary_package_version);
103
104         return str;
105 }
106
107 static char *
108 build_addcolums_str(struct binary_package_publishing_history **list)
109 {
110         struct binary_package_publishing_history **cur = list;
111         struct binary_package_publishing_history *b;
112         char *str, *tmpstr;
113         char *dname;
114
115         str = malloc(1);
116         *str = '\0';
117         const char *pattern = "%s        data.addColumn('number', '%s');\n";
118
119         while (*cur) {
120                 b = *cur;
121                 dname = build_package_display_name(b);
122
123                 tmpstr = malloc(strlen(str)+strlen(pattern)+strlen(dname)+1);
124                 sprintf(tmpstr, pattern, str, dname);
125
126                 free(str);
127                 free(dname);
128
129                 str = tmpstr;
130
131                 cur++;
132         }
133
134         return str;
135 }
136
137 static char *
138 build_data_str(struct binary_package_publishing_history **list)
139 {
140         int n, i;
141         json_object *data;
142         char *str;
143
144         n = list_length((void **)list);
145
146         data = json_object_new_array();
147         for (i = 0; i < n; i++) {
148                 struct binary_package_publishing_history *binary;
149                 const struct distro_arch_series *dist;
150                 struct daily_download_total **totals;
151                 struct daily_download_total **t_cur;
152
153                 binary = list[i];
154                 dist = get_distro_arch_series(binary->distro_arch_series_link);
155
156                 totals = get_daily_download_totals(binary->self_link);
157
158                 t_cur = totals;
159                 while (*t_cur) {
160                         char *d = malloc(10+1);
161                         json_object *data2;
162
163                         sprintf(d, "%d-%02d-%02d",
164                                 (*t_cur)->date.tm_year+1900,
165                                 (*t_cur)->date.tm_mon+1,
166                                 (*t_cur)->date.tm_mday);
167
168                         data2 = get_count_array(data, d);
169
170                         if (!data2)
171                                 data2 = count_array_new(data, d, n);
172
173                         json_object_array_put_idx
174                                 (data2,
175                                  i+1, json_object_new_int((*t_cur)->count));
176
177                         free(d);
178                         t_cur++;
179                 }
180
181                 daily_download_total_list_free(totals);
182         }
183
184         str = strdup(json_object_to_json_string(data));
185
186         json_object_put(data);
187
188         return str;
189 }
190
191 void ppa_to_html(const char *owner, const char *ppa, const char *package_status)
192 {
193         struct binary_package_publishing_history **list;
194         char *archive_url = get_archive_url(owner, ppa);
195         char *addcolumns_str;
196         char *data_str;
197
198         list = get_binary_package_publishing_history_list(archive_url,
199                                                           package_status);
200         free(archive_url);
201
202         if (!list) {
203                 fprintf(stderr, "Failed to retrieve PPA information\n");
204                 exit(EXIT_FAILURE);
205         }
206
207         addcolumns_str = build_addcolums_str(list);
208         data_str = build_data_str(list);
209
210         printf(HTML_TEMPLATE, addcolumns_str, data_str);
211
212         free(addcolumns_str);
213         free(data_str);
214         binary_package_publishing_history_list_free(list);
215 }