9 global $sch_unknown_fixfor;
12 function bug_person($user)
17 $query = "select ixPerson from Person where sEmail like '$user@%'";
18 $result = mysql_query($query, $bug_h);
19 $row = mysql_fetch_row($result);
26 function bug_duedate($fixfor)
31 $query = "select dt from FixFor where sFixFor='$fixfor'";
32 $result = mysql_query($query, $bug_h);
33 $row = mysql_fetch_row($result);
40 function bug_list($user, $fixfor, $startdate, $enddate)
49 if ($fixfor and $enddate)
50 $ffquery = " and (f.sFixFor = '$fixfor' or " .
51 "(f.dt is not null and f.dt <= '$enddate')) ";
53 $ffquery = " and f.sFixFor = '$fixfor' ";
55 # any bug opened before the end date counts toward that deadline, even
56 # if the deadline has passed and the bug isn't done.
58 $endquery = " and b.dtOpened < '$enddate' ";
60 # We want to get all bugs resolved by the user after the given start
61 # date, *and* all bugs currently assigned to the user.
64 $personid = bug_person($user);
65 $userquery = " and (" .
66 " (b.ixPersonAssignedTo=$personid and sStatus='ACTIVE') " .
67 " or (sStatus<>'ACTIVE' and e.ixPerson=$personid " .
68 " and e.sVerb like 'RESOLVED%' " .
69 " and e.dt >= '$startdate')" .
73 $query = "select distinct " .
74 "b.ixBug,sStatus,sTitle,hrsOrigEst,hrsCurrEst,hrsElapsed, " .
75 " ifnull(f.dt, '2099/9/9') as sortdate " .
76 "from Bug as b, BugEvent as e, FixFor as f, Status as s " .
77 "where e.ixBug=b.ixBug " .
78 " and f.ixFixFor=b.ixFixFor " .
79 " and s.ixStatus=b.ixStatus " .
83 " order by sortdate, sFixFor, ixPriority, ixBug ";
84 #print "(($query))<p>";
85 $result = mysql_query($query, $bug_h);
87 print mysql_error($bug_h);
90 while ($row = mysql_fetch_row($result))
92 $bug = array_shift($row);
93 $status = array_shift($row);
94 if ($status != "ACTIVE")
96 # the bug is done, so don't give it any more time remaining
98 $row[2] = 0.01; # nonzero so we know the 'remaining' is accurate
99 $row[3] = $row[2]; # elapsed = estimate; bug is done!
107 function bug_get($bugid)
112 $result = mysql_query("select sTitle,hrsOrigEst,hrsCurrEst,hrsElapsed, " .
113 " sStatus,sFixFor " .
114 "from Bug as b, Status as s, FixFor as f " .
115 "where s.ixStatus=b.ixStatus " .
116 " and f.ixFixFor=b.ixFixFor " .
117 " and ixBug=" . ($bugid+
0),
119 $row = mysql_fetch_row($result);
122 return array($bugid, 0, 0, 0);
127 function bug_link($bugid)
129 return "<a href='http://nits/FogBUGZ3/?$bugid'>$bugid</a>";
132 function bug_title($bugid)
134 $bug = bug_get($bugid);
138 function bug_set_release($fixfor, $dt)
143 $query = "delete from schedulator.Milestone " .
144 " where sMilestone='$fixfor' and nSub=0";
145 $result = mysql_query($query, $bug_h);
147 $query = "insert into schedulator.Milestone " .
148 " (sMilestone, nSub, dtDue) " .
149 " values ('$fixfor', 0, '$dt')";
150 $result = mysql_query($query, $bug_h);
153 function bug_set_milestones($fixfor, $dates)
158 $query = "delete from schedulator.Milestone " .
159 " where sMilestone='$fixfor' and nSub>0";
160 $result = mysql_query($query, $bug_h);
162 print mysql_error($bug_h);
165 foreach ($dates as $d)
167 $query = "insert into schedulator.Milestone " .
168 " (sMilestone, nSub, dtDue) " .
169 " values ('$fixfor', $n, '$d')";
170 $result = mysql_query($query, $bug_h);
172 print mysql_error($bug_h);
177 function bug_get_milestones($fixfor)
182 $query = "select distinct dtDue from schedulator.Milestone " .
183 " where sMilestone='$fixfor' and nSub>0 order by dtDue";
184 $result = mysql_query($query, $bug_h);
186 print mysql_error($bug_h);
189 while ($row = mysql_fetch_row($result))
190 array_push($a, $row[0]);
194 function bug_add_task($user, $fixfor, $t)
199 $task = mysql_escape_string($t[0]);
200 $subtask = mysql_escape_string($t[1]);
201 $query = "insert into schedulator.Task " .
202 " (sPerson, sFixFor, " .
203 " sTask, sSubTask, " .
204 " hrsOrigEst, hrsCurrEst, hrsElapsed, dtDue, fDone) " .
205 " values ('$user', '$fixfor', \"$task\", \"$subtask\", " .
206 " $t[2], $t[3], $t[4], '$t[5]', $t[6])";
207 $result = mysql_query($query, $bug_h);
209 print 'x-' . mysql_error($bug_h);
212 function bug_add_tasks($user, $fixfor, $tasks)
214 foreach ($tasks as $t)
215 bug_add_task($user, $fixfor, $t);
218 function bug_start_user($user)
223 $query = "update schedulator.Task set fValid=0 where sPerson='$user'";
224 $result = mysql_query($query, $bug_h);
227 function bug_finish_user($user)
232 $query = "delete from schedulator.Task where fValid=0";
233 $result = mysql_query($query, $bug_h);
239 # we mostly use GMT for our work, but if they want today, they want
241 $dat = strftime("%Y/%m/%d", time());
242 $today = sch_parse_day($dat);
243 #print("(today=$dat:$today/" . sch_format_day($today) . ")");
247 function sch_parse_day($day)
251 else if (preg_match(",(....)[/-](..)[/-](..),", $day, $a))
257 $stamp = mktime(0,0,12, $month, $day, $year);
258 $spl = localtime($stamp);
259 #print("(day-$year/$month/$day:$stamp:$spl[6])");
260 if ($spl[6] == 0) # sunday
262 else if ($spl[6] == 6) # saturday
263 $stamp +
= 2*24*60*60;
265 $stamp -= 4*24*60*60; # the epoch was a Thursday. Skip to Monday.
266 $days = floor($stamp/24/60/60);
267 $weeks = floor($days/7);
269 #printf("(days/weeks:$days/$weeks)");
270 return $weeks*5 +
$days;
274 print("(INVALID DATE:'$day')");
279 function sch_format_day($day)
284 # convert working days to "real" days
285 $weeks = floor($day/5);
286 $days = $day - $weeks*5;
287 $frac = $days - floor($days);
288 $stamp = ($weeks*7 +
$days) * 24*60*60;
289 $stamp +
= 4*24*60*60; # the epoch was a Thursday
290 $stamp +
= 12*60*60; # php timezone handling is insane
292 return strftime("%Y/%m/%d", $stamp);# . sprintf("+%.1f", $frac);
295 function sch_add_hours($day, $hours)
300 return $day; # never subtract hours from the date!
302 # FIXME: deal with "working days" vs. weekends
303 return $day +
($hours * $sch_load) / 8.0;
306 # returns a time in hours
307 function sch_parse_period($str)
310 if (preg_match('/([0-9.]+) *(h|hr|hrs|hour|hours)$/', $str, $out))
312 else if (preg_match('/([0-9.]+) *(d|day|days)$/', $str, $out))
313 return $out[1] * 8.0;
314 else if (preg_match('/([0-9.]+) *(min|minutes)$/', $str, $out))
315 return $out[1] / 60.0;
320 function _sch_period($hours)
326 return sprintf("%dh", $hours);
327 else if ($hours < 10*8.0)
328 return sprintf("%.1fd", $hours/8);
330 return sprintf("%dd", $hours/8);
333 function sch_period($hours)
336 return "<font color=red>-" . _sch_period(-$hours) . "</font>";
338 return _sch_period($hours);
341 function sch_fullline($text)
343 return "<tr><td colspan=7>$text</td></tr>";
346 function sch_genline($feat, $task, $orig, $curr, $elapsed, $left, $due)
350 $junk1 = $junk2 = '';
353 $junk1 = "<strike><font color=grey><i>";
354 $junk2 = "</i></font></strike>";
358 $ret .= "<td>$junk1$feat$junk2</td><td>$junk1$task$junk2</td>";
360 $ret .= "<td colspan=2>$junk1$feat$junk2</td>";
361 return $ret . "<td>$junk1" .
362 join("$junk2</td><td>$junk1",
363 array($orig, $curr, $elapsed, $left, $due)) .
367 function sch_line($feat, $task, $orig, $curr, $elapsed, $remain, $done)
369 global $sch_curday, $sch_bugs, $sch_got_bug;
376 $sremain = sch_period($remain);
378 $sch_curday = sch_add_hours($sch_curday, $curr);
379 $due = sch_format_day($sch_curday);
380 if ((!$curr ||
$remain) && !$done
381 && floor($sch_curday) < floor(sch_today()))
382 $due = "<font color=red>$due</font>";
384 return sch_genline($feat, $task,
385 sch_period($orig), sch_period($curr),
386 sch_period($elapsed), $sremain,
390 function sch_bug($feat, $task, $_orig, $_curr, $_elapsed, $done)
392 global $sch_user, $sch_curday, $sch_bugs, $sch_need_extraline;
393 global $sch_got_bug, $sch_unknown_fixfor;
395 if ($sch_need_extraline)
397 $ret .= sch_fullline(' ');
398 $sch_need_extraline = 0;
403 if (preg_match('/^[0-9]+$/', $feat))
405 $sch_got_bug[$feat] = 1;
406 $bug = bug_get($feat);
407 if (!$task) $task = $bug[0];
408 if (!$_orig) $_orig = $bug[1];
409 if (!$_curr) $_curr = $bug[2];
410 if (!$_elapsed) $_elapsed = $bug[3];
411 if (!$done && $bug[4] != 'ACTIVE') $done = 1;
413 $xfeat = bug_link($feat);
416 $orig = sch_parse_period($_orig);
417 $curr = sch_parse_period($_curr);
418 $elapsed = sch_parse_period($_elapsed);
420 $remain = $curr - $elapsed;
422 if (!$remain && $curr)
425 $ret .= sch_line($xfeat, $task, $orig, $curr, $elapsed, $remain, $done);
426 $buga = array($feat, $task, $orig, $curr, $elapsed,
427 sch_format_day($sch_curday), $done);
429 bug_add_task($sch_user, $fixfor, $buga);
431 array_push($sch_unknown_fixfor, $buga);
435 function sch_extrabugs($user, $fixfor, $enddate)
437 global $sch_got_bug, $sch_start;
439 $start = sch_format_day($sch_start);
441 $a = bug_list($user, $fixfor, $start, $enddate);
442 foreach ($a as $bugid => $bug)
444 if (!$sch_got_bug[$bugid])
445 $ret .= sch_bug($bugid, $bug[0], $bug[1], $bug[2], $bug[3], 0);
450 function sch_milestone($descr, $name, $due)
452 global $sch_user, $sch_load, $sch_curday, $sch_need_extraline;
454 # if no due date was given, assume it's the current date for purposes
455 # of collecting extra bugs.
457 $tmpdue = sch_format_day($sch_curday);
460 $ret .= sch_extrabugs($sch_user, $name, $tmpdue);
462 # if no due date was given, make it the day after the last bug finished.
464 $due = sch_format_day($sch_curday+
1);
466 $old_curday = $sch_curday;
468 $newday = sch_parse_day($due);
469 $xdue = sch_format_day($newday);
470 $slip = ($newday-$sch_curday)*8 / $sch_load;
471 #$ret .= sch_line("SLIPPAGE (to $xdue)", "", 0,$slip,0,$slip, 0);
472 $ret .= sch_line("<b>$descr: $name ($xdue)</b>", '', 0,$slip,0,$slip, 0);
473 $sch_need_extraline = 1;
475 $sch_curday = $old_curday; # slippage doesn't actually take time... right?
480 function view_macro_schedulator($text)
482 global $sch_start, $sch_curday, $sch_user, $sch_load, $sch_got_bug;
483 global $sch_unknown_fixfor;
487 if (!preg_match_all('/"[^"]*"|[^ ]+/', $text, $words))
488 return "regmatch failed!\n";
489 $words = $words[0]; # don't know why I have to do this, exactly...
491 foreach ($words as $key => $value)
493 if (preg_match('/^"(.*)"$/', $value, $result))
494 $words[$key] = $result[1];
500 foreach ($words as $word)
505 if ($words[0] == "START")
507 $ret .= "<table border=0 width='95%'>\n";
509 join("</th><th>", array("Task", "Subtask", "Orig", "Curr",
510 "Done", "Left", "Due")) .
512 $sch_user = $words[1];
513 $sch_start = $sch_curday = sch_parse_day($words[2]);
514 $sch_unknown_fixfor = array();
516 $ret .= sch_line("START", "", 0,0,0,0, 0);
517 bug_start_user($sch_user);
519 else if ($words[0] == "LOADFACTOR")
521 $loadtmp = $words[1] +
0.0;
523 $ret .= "(INVALID LOAD FACTOR:'$words[1]')";
525 $sch_load = $loadtmp;
527 $ret .= sch_fullline("(Load factor = $sch_load)");
529 else if ($words[0] == "FIXFOR")
531 $ret .= sch_extrabugs($sch_user, $words[1], '');
533 else if ($words[0] == "SETBOUNCE")
535 $cmd = array_shift($words);
536 $msname = array_shift($words);
537 bug_set_milestones($msname, $words);
539 else if ($words[0] == "MILESTONE" ||
$words[0] == "RELEASE"
540 ||
$words[0] == "BOUNCE")
545 $extra_due = bug_get_milestones($msname);
546 foreach ($extra_due as $xdue)
547 $ret .= sch_milestone("ZeroBugBounce", $msname, $xdue);
550 $msdue = bug_duedate($msname);
551 $ret .= sch_milestone($words[0], $msname, $msdue);
552 bug_set_release($msname, $msdue);
553 bug_add_tasks($sch_user, $msname, $sch_unknown_fixfor);
554 $sch_unknown_fixfor = array();
556 else if ($words[0] == "END")
558 $ret .= sch_extrabugs($sch_user, '', '');
559 bug_add_tasks($sch_user, 'UNKNOWN', $sch_unknown_fixfor);
560 bug_finish_user($sch_user);
561 $ret .= sch_line("END", "", 0,0,0,0, 0);
569 $elapsed = $words[3];
571 $ret .= sch_bug($bug, $task, $est, $est, $elapsed, 0);