1/*
2 *	aegis - project change supervisor
3 *	Copyright (C) 1998, 2002, 2003, 2005-2008 Peter Miller
4 *
5 *	This program is free software; you can redistribute it and/or modify
6 *	it under the terms of the GNU General Public License as published by
7 *	the Free Software Foundation; either version 3 of the License, or
8 *	(at your option) any later version.
9 *
10 *	This program is distributed in the hope that it will be useful,
11 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *	GNU General Public License for more details.
14 *
15 *	You should have received a copy of the GNU General Public License
16 *	along with this program. If not, see
17 *	<http://www.gnu.org/licenses/>.
18 */
19
20auto pn, p;
21pn = project_name();
22p = project[pn];
23auto ps, cs;
24ps = p.state;
25auto ph, when, n, max, href;
26
27auto script_name;
28script_name = getenv("SCRIPT_NAME");
29if (script_name == "")
30	script_name = "http://localhost/cgi-bin/aegis.cgi";
31
32auto t, month, year;
33if (count(arg) > 0)
34    t = mktime(arg[0]);
35else
36    t = now();
37month = 0 + strftime("%m", t);
38year = 0 + strftime("%Y", t);
39
40auto cmap;
41cmap =
42{
43    chain			= "255+0+0";
44    internal_bug		= "255+255+0";
45    internal_enhancement	= "0+255+0";
46    internal_improvement	= "0+255+255";
47    external_bug		= "192+192+0";
48    external_enhancement	= "0+192+0";
49    external_improvement	= "0+192+192";
50};
51
52columns({width = 1000; });
53print("Content-Type: text/html");
54print("");
55print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\""
56	## "\"http://www.w3.org/TR/REC-html40/loose.dtd\">");
57print("<html><head>");
58print("<meta name=\"ROBOTS\" content=\"NOINDEX, NOFOLLOW\">");
59print("<meta name=\"GENERATOR\" content=\"" ## script_name ## "\">");
60print("<meta http-equiv=\"Content-Type\" "
61	## "content=\"text/html; charset=ISO-8859-1\">");
62print("<style type=\"text/css\"> "
63	## "tr.even-group { background-color: #CCCCCC; } "
64	## "body { background-color: white; } "
65	## "</style>");
66/*
67 * Netscape 4.x has numerous CSS bugs, two of which need mentioning.
68 * 1. If a style sheet is not present Netscape says 404 Not found, when
69 * it should silently ignore it.  2. Style sheets who's media is not
70 * "screen" will be ignored.  Fortunately we can use (2) to get around (1).
71 */
72print("<link rel=\"stylesheet\" type=\"text/css\" href=\"/aedefault.css\" "
73	## "media=\"all\">");
74auto stack, depth, bn;
75depth=0;
76stack[depth] = project[pn].state.name;
77while ("" != ( bn = project[stack[depth]].state.parent_name )) {
78  stack[++depth] = bn;
79}
80while ( depth >= 0) {
81    print("<link rel=\"stylesheet\" type=\"text/css\" href=\"/" ##
82      stack[depth--] ## ".css\" " ## "media=\"all\">");
83}
84print("<title>");
85print("Project " ## quote_html(pn) ## ", Change Cause Histogram");
86print("</title><head><body><h1 align=center>");
87
88print("<a href=\"" ## script_name ## "\">Project</a>");
89auto long_project_name;
90auto prj_name_parts;
91prj_name_parts = split(pn, '.');
92href = script_name ## "?file@proj_menu+project@"
93	## quote_url(prj_name_parts[0]);
94long_project_name = "<a href=\"" ## href ## "\" >"
95	## quote_html(prj_name_parts[0]) ## "</a>";
96auto j;
97for (j = 1; j < count(prj_name_parts); j++)
98{
99    href ##= '.' ## prj_name_parts[j];
100    long_project_name ##= ".<a href=\"" ## href ## "\" >"
101    	## quote_html(prj_name_parts[j]) ## "</a>";
102};
103long_project_name = "&ldquo;" ## long_project_name ## "&rdquo;,<br>";
104/* HTTP limits lines to 510 characters */
105for (j in wrap(long_project_name, 510))
106    print(j);
107
108href = script_name ## "?file@proj_cch1+project@" ## quote_url(pn);
109print("Change Cause <a href=\"" ## href ## "\">Histogram</a><br>");
110print(strftime("%B", t));
111href = script_name ## "?file@proj_cch2+project@" ## quote_url(pn)
112        ## "+" ## year;
113print("<a href=\"" ## href ## "\">" ## strftime("%Y", t) ## "</a>");
114print("</h1>");
115print("<div class=\"information\">");
116
117auto earliest_mday, latest_mday;
118
119auto bucket, mday, last_mday;
120bucket = {};
121for (ph in ps.branch.history)
122{
123    cs = ps.branch.change[ph.change_number];
124    when = cs.history[count(cs.history) - 1].when;
125    if (year != 0 + strftime("%Y", when))
126       	continue;
127    if (month != 0 + strftime("%m", when))
128       	continue;
129    mday = 0 + strftime("%d", when);
130    if (typeof(bucket[mday]) == "nul")
131       	bucket[mday] = {};
132    bucket[mday][cs.cause]++;
133    bucket[mday].Total++;
134}
135
136max = 1;
137for (mday in keys(bucket))
138{
139    n = 0 + bucket[mday].Total;
140    if (n > max)
141       	max = n;
142}
143max = 400. / max;
144
145last_mday = 28;
146for (n = 28; n < 32; ++n)
147{
148    when = mktime(strftime("1-%b-%Y 00:00:00", t));
149    when += (n - 1) * (24 * 60 * 60);
150    if (strftime("%m", when) + 0 != month)
151       	break;
152    last_mday = n;
153}
154
155auto clr;
156print("<table align=center>");
157print("<tr><th>Day</th><th>Count</th></tr>");
158for (mday = 1; mday <= last_mday; ++mday)
159{
160    if (typeof(bucket[mday]) == "nul")
161       	bucket[mday] = {};
162    n = 0 + bucket[mday].Total;
163    print("<tr><td valign=top align=right>");
164    print(mday);
165    print("</td><td valign=top align=right>");
166    print(n);
167    print("</td><td valign=top>");
168    auto cause;
169    for (cause in [chain,
170       	internal_bug, internal_enhancement, internal_improvement,
171       	external_bug, external_enhancement, external_improvement])
172    {
173       	n = 0 + bucket[mday][cause];
174       	if (n > 0)
175       	{
176	    clr = cmap[cause];
177	    n = round(n * max);
178	    if (n < 3)
179		n = 3;
180	    href = script_name ## "?file@rect+" ## n ## "+12";
181	    href ##= "+color+" ## clr;
182	    print("<img src=\"" ## href ## "\" width="##n## " height=12>");
183       	}
184    }
185    print("</td></tr>");
186}
187print("</table>");
188print("</div>");
189print("<hr>");
190
191print("<div class=\"legend\">");
192print("<h2 align=center>Legend</h2>");
193print("This table associates each color in the above graph with");
194print("a change cause.  A brief description of each cause is");
195print("also given.");
196print("<table align=center>");
197print("<tr><th>Color</th><th>Cause</th><th>Description</th></tr>");
198
199clr = cmap[chain];
200href = script_name ## "?file@rect+50+12+color+" ## clr;
201print("<tr><td valign=top>");
202print("<img src=\""##href##"\" width=50 height=12>");
203print("</td><td valign=top align=center>");
204print("chain");
205print("</td><td valign=top>");
206print("This cause is used for bugs introduced by previous changes.");
207print("This is a special case of the <dfn>internal_bug</dfn> cause.");
208print("</td></tr>");
209
210clr = cmap[internal_bug];
211href = script_name ## "?file@rect+50+12+color+" ## clr;
212print("<tr><td valign=top>");
213print("<img src=\""##href##"\" width=50 height=12>");
214print("</td><td valign=top align=center>");
215print("internal_bug");
216print("</td><td valign=top>");
217print("This cause is used for bugs found by the development team, or by");
218print("the development organization.");
219print("</td></tr>");
220
221clr = cmap[internal_enhancement];
222href = script_name ## "?file@rect+50+12+color+" ## clr;
223print("<tr><td valign=top>");
224print("<img src=\""##href##"\" width=50 height=12>");
225print("</td><td valign=top align=center>");
226print("internal_enhancement");
227print("</td><td valign=top>");
228print("This cause is used for new functionality requested by the");
229print("development team, or by the development organization.");
230print("</td></tr>");
231
232clr = cmap[internal_improvement];
233href = script_name ## "?file@rect+50+12+color+" ## clr;
234print("<tr><td valign=top>");
235print("<img src=\""##href##"\" width=50 height=12>");
236print("</td><td valign=top align=center>");
237print("internal_improvement");
238print("</td><td valign=top>");
239print("This cause is used for improvement to existing functionality");
240print("(e.g. performance) requested by the development team, or by the");
241print("development organization.");
242print("</td></tr>");
243
244clr = cmap[external_bug];
245href = script_name ## "?file@rect+50+12+color+" ## clr;
246print("<tr><td valign=top>");
247print("<img src=\""##href##"\" width=50 height=12>");
248print("</td><td valign=top align=center>");
249print("external_bug");
250print("</td><td valign=top>");
251print("This cause is used for bugs found by the customer, or by a source");
252print("outside the development organization.");
253print("</td></tr>");
254
255clr = cmap[external_enhancement];
256href = script_name ## "?file@rect+50+12+color+" ## clr;
257print("<tr><td valign=top>");
258print("<img src=\""##href##"\" width=50 height=12>");
259print("</td><td valign=top align=center>");
260print("external_enhancement");
261print("</td><td valign=top>");
262print("This cause is used for new functionality requested by the customer,");
263print("or by a source outside the development organization.");
264print("</td></tr>");
265
266clr = cmap[external_improvement];
267href = script_name ## "?file@rect+50+12+color+" ## clr;
268print("<tr><td valign=top>");
269print("<img src=\""##href##"\" width=50 height=12>");
270print("</td><td valign=top align=center>");
271print("external_improvement");
272print("</td><td valign=top>");
273print("This cause is used for improvement to existing functionality");
274print("(e.g. performance) requested by the customer, or a source outside");
275print("the development development organization.");
276print("</td></tr>");
277
278print("</table>");
279print("</div>");
280
281print("<hr>");
282print("<p align=center class=\"navbar\">[");
283print("<a href=\"" ## script_name ## "\">Project List</a> |");
284href = script_name ## "?file@proj_menu+project@" ## quote_url(pn);
285print("<a href=\"" ## href ## "\">Project Menu</a> |");
286href = script_name ## "?file@changes+project@" ## quote_url(pn);
287print("<a href=\"" ## href ## "\">Change List</a> |");
288href = script_name ## "?file@proj_cch1+project@" ## quote_url(pn);
289print("<a href=\"" ## href ## "\">Project Histogram</a> |");
290href = script_name ## "?file@proj_cch2+project@" ## quote_url(pn) ## "+"
291	## year;
292print("<a href=\"" ## href ## "\">Year Histogram</a>");
293print("]</p>");
294
295print("<hr>");
296print("This page was generated " ## now() ## ".");
297print("</body></html>");
298