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 cmap;
33cmap =
34{
35    chain			= "255+0+0";
36    internal_bug		= "255+255+0";
37    internal_enhancement	= "0+255+0";
38    internal_improvement	= "0+255+255";
39    external_bug		= "192+192+0";
40    external_enhancement	= "0+192+0";
41    external_improvement	= "0+192+192";
42};
43
44columns({width = 1000; });
45print("Content-Type: text/html");
46print("");
47print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\""
48	## "\"http://www.w3.org/TR/REC-html40/loose.dtd\">");
49print("<html><head>");
50print("<meta name=\"ROBOTS\" content=\"NOINDEX, NOFOLLOW\">");
51print("<meta name=\"GENERATOR\" content=\"" ## script_name ## "\">");
52print("<meta http-equiv=\"Content-Type\" "
53	## "content=\"text/html; charset=ISO-8859-1\">");
54print("<style type=\"text/css\"> "
55	## "tr.even-group { background-color: #CCCCCC; } "
56	## "body { background-color: white; } "
57	## "</style>");
58/*
59 * Netscape 4.x has numerous CSS bugs, two of which need mentioning.
60 * 1. If a style sheet is not present Netscape says 404 Not found, when
61 * it should silently ignore it.  2. Style sheets who's media is not
62 * "screen" will be ignored.  Fortunately we can use (2) to get around (1).
63 */
64print("<link rel=\"stylesheet\" type=\"text/css\" href=\"/aedefault.css\" "
65	## "media=\"all\">");
66auto stack, depth, bn;
67depth=0;
68stack[depth] = project[pn].state.name;
69while ("" != ( bn = project[stack[depth]].state.parent_name )) {
70  stack[++depth] = bn;
71}
72while ( depth >= 0) {
73    print("<link rel=\"stylesheet\" type=\"text/css\" href=\"/" ##
74       stack[depth--] ## ".css\" " ## "media=\"all\">");
75}
76print("<title>");
77print("Project " ## quote_html(pn) ## ", Change Cause Histogram");
78print("</title><head><body><h1 align=center>");
79
80print("<a href=\"" ## script_name ## "\">Project</a>");
81auto long_project_name;
82auto prj_name_parts;
83prj_name_parts = split(pn, '.');
84href = script_name ## "?file@proj_menu+project@"
85	## quote_url(prj_name_parts[0]);
86long_project_name = "<a href=\"" ## href ## "\" >"
87	## quote_html(prj_name_parts[0]) ## "</a>";
88auto j;
89for (j = 1; j < count(prj_name_parts); j++)
90{
91    href ##= '.' ## prj_name_parts[j];
92    long_project_name ##= ".<a href=\"" ## href ## "\" >"
93    	## quote_html(prj_name_parts[j]) ## "</a>";
94};
95long_project_name = "&ldquo;" ## long_project_name ## "&rdquo;,<br>";
96/* HTTP limits lines to 510 characters */
97for (j in wrap(long_project_name, 510))
98    print(j);
99
100print("Change Cause Histogram");
101print("</h1>");
102print("<div class=\"information\">");
103
104auto earliest_year, latest_year;
105earliest_year = 0;
106latest_year = 0;
107auto bucket, year;
108bucket = {};
109for (ph in ps.branch.history)
110{
111    cs = ps.branch.change[ph.change_number];
112    when = cs.history[count(cs.history) - 1].when;
113    year = 0 + strftime("%Y", when);
114    if (typeof(bucket[year]) == "nul")
115       	bucket[year] = {};
116    bucket[year][cs.cause]++;
117    bucket[year].Total++;
118    if (earliest_year == 0 || earliest_year > year)
119       	earliest_year = year;
120    if (latest_year < year)
121       	latest_year = year;
122}
123
124max = 1;
125for (year in keys(bucket))
126{
127    n = 0 + bucket[year].Total;
128    if (n > max)
129       	max = n;
130}
131max = 400. / max;
132
133auto clr;
134print("<table align=center>");
135print("<tr><th>Year</th><th>Count</th></tr>");
136for (year = earliest_year; year <= latest_year; ++year)
137{
138    n = 0 + bucket[year].Total;
139    print("<tr><td valign=top align=right>");
140    if (n > 0)
141    {
142       	href = script_name ## "?file@proj_cch2";
143       	href ##= "+project@" ## quote_url(project_name());
144       	href ##=  "+" ## year;
145       	print("<a href=\"" ## href ## "\">");
146    }
147    print(year);
148    if (n > 0)
149       	print("</a>");
150    print("</td><td valign=top align=right>");
151    print(n);
152    print("</td><td valign=top>");
153    auto cause;
154    for (cause in [chain,
155       	internal_bug, internal_enhancement, internal_improvement,
156       	external_bug, external_enhancement, external_improvement])
157    {
158       	n = 0 + bucket[year][cause];
159       	if (n > 0)
160	{
161	    clr = cmap[cause];
162	    if (clr == "")
163	     	clr = "255+0+255";
164	    n = round(n * max);
165	    if (n < 3)
166	     	n = 3;
167	    href = script_name ## "?file@rect+" ## n ## "+12";
168	    href ##= "+color+" ## clr;
169	    print("<img src=\"" ## href ## "\" width="##n##" height=12>");
170       	}
171    }
172    print("</td></tr>");
173}
174print("</table>");
175print("</div>");
176print("<hr>");
177
178print("<div class=\"legend\">");
179print("<h2 align=center>Legend</h2>");
180print("This table associates each color in the above graph with");
181print("a change cause.  A brief description of each cause is");
182print("also given.");
183print("<table align=center>");
184print("<tr><th>Color</th><th>Cause</th><th>Description</th></tr>");
185
186clr = cmap[chain];
187href = script_name ## "?file@rect+50+12+color+" ## clr;
188print("<tr><td valign=top>");
189print("<img src=\""##href##"\" width=50 height=12>");
190print("</td><td valign=top align=center>");
191print("chain");
192print("</td><td valign=top>");
193print("This cause is used for bugs introduced by previous changes.");
194print("This is a special case of the <dfn>internal_bug</dfn> cause.");
195print("</td></tr>");
196
197clr = cmap[internal_bug];
198href = script_name ## "?file@rect+50+12+color+" ## clr;
199print("<tr><td valign=top>");
200print("<img src=\""##href##"\" width=50 height=12>");
201print("</td><td valign=top align=center>");
202print("internal_bug");
203print("</td><td valign=top>");
204print("This cause is used for bugs found by the development team, or by");
205print("the development organization.");
206print("</td></tr>");
207
208clr = cmap[internal_enhancement];
209href = script_name ## "?file@rect+50+12+color+" ## clr;
210print("<tr><td valign=top>");
211print("<img src=\""##href##"\" width=50 height=12>");
212print("</td><td valign=top align=center>");
213print("internal_enhancement");
214print("</td><td valign=top>");
215print("This cause is used for new functionality requested by the");
216print("development team, or by the development organization.");
217print("</td></tr>");
218
219clr = cmap[internal_improvement];
220href = script_name ## "?file@rect+50+12+color+" ## clr;
221print("<tr><td valign=top>");
222print("<img src=\""##href##"\" width=50 height=12>");
223print("</td><td valign=top align=center>");
224print("internal_improvement");
225print("</td><td valign=top>");
226print("This cause is used for improvement to existing functionality");
227print("(e.g. performance) requested by the development team, or by the");
228print("development organization.");
229print("</td></tr>");
230
231clr = cmap[external_bug];
232href = script_name ## "?file@rect+50+12+color+" ## clr;
233print("<tr><td valign=top>");
234print("<img src=\""##href##"\" width=50 height=12>");
235print("</td><td valign=top align=center>");
236print("external_bug");
237print("</td><td valign=top>");
238print("This cause is used for bugs found by the customer, or by a source");
239print("outside the development organization.");
240print("</td></tr>");
241
242clr = cmap[external_enhancement];
243href = script_name ## "?file@rect+50+12+color+" ## clr;
244print("<tr><td valign=top>");
245print("<img src=\""##href##"\" width=50 height=12>");
246print("</td><td valign=top align=center>");
247print("external_enhancement");
248print("</td><td valign=top>");
249print("This cause is used for new functionality requested by the customer,");
250print("or by a source outside the development organization.");
251print("</td></tr>");
252
253clr = cmap[external_improvement];
254href = script_name ## "?file@rect+50+12+color+" ## clr;
255print("<tr><td valign=top>");
256print("<img src=\""##href##"\" width=50 height=12>");
257print("</td><td valign=top align=center>");
258print("external_improvement");
259print("</td><td valign=top>");
260print("This cause is used for improvement to existing functionality");
261print("(e.g. performance) requested by the customer, or a source outside");
262print("the development development organization.");
263print("</td></tr>");
264
265print("</table>");
266print("</div>");
267
268print("<hr>");
269print("<p align=center class=\"navbar\">[");
270print("<a href=\"" ## script_name ## "\">Project List</a> |");
271href = script_name ## "?file@proj_menu+project@" ## quote_url(pn);
272print("<a href=\"" ## href ## "\">Project Menu</a> |");
273href = script_name ## "?file@changes+project@" ## quote_url(pn);
274print("<a href=\"" ## href ## "\">Change List</a>");
275print("]</p>");
276
277print("<hr>");
278print("This page was generated " ## now() ## ".");
279print("</body></html>");
280