Index: trunk/www/dch/obs_summary.php
===================================================================
--- trunk/www/dch/obs_summary.php	(revision 18884)
+++ trunk/www/dch/obs_summary.php	(revision 18884)
@@ -0,0 +1,497 @@
+<?php
+
+    include("db.php");
+    require_once("class.Diff.php");
+
+ //   ini_set("display_errors", "On");
+ //   ini_set("mysql.trace_mode", "On");
+
+
+$db_id = mysql_connect($host, $user, $pw);
+if ($db_id==FALSE)
+{
+    printf("mysql_connect returned the following error: %s\n", mysql_error());
+    die("");
+}
+mysql_select_db($db);
+
+date_default_timezone_set('UTC');
+
+$date  = isset($_GET["d"]) ? $_GET["d"] : date("Y-m-d");//'2016-02-16';
+$night = str_replace("-", "", $date);
+
+// ====================================================================
+
+function fmt($date)
+{
+    $d = date_create_from_format("Y-m-d G:i:s", $date);
+    return "new Date(".$d->format("Y,n-1,j,G,i,s,0").")";
+    //return "new Date(".($d->getTimestamp()*1000).")";//format("Y,n-1,j,G,i,s,0").")";
+}
+
+// ====================================================================
+
+function QuerySchedule(&$data, &$html1, &$html2, &$query, $db_id, $table, $date)
+{
+$query = <<<EOT
+
+SELECT
+   fStart, fSourceName, fUser, fMeasurementTypeName
+FROM $table
+LEFT JOIN Source USING (fSourceKey)
+LEFT JOIN MeasurementType USING (fMeasurementTypeKey)
+WHERE fStart
+   BETWEEN ADDDATE('$date', INTERVAL +12 HOUR)
+   AND ADDDATE('$date', INTERVAL +36 HOUR)
+ORDER BY fStart
+
+EOT;
+
+$html1 = "";
+$array = array();
+
+$result = mysql_query($query, $db_id);
+if ($result)
+{
+    $html1 .= "<table>\n";
+
+    $n = 0;
+    while ($row = mysql_fetch_assoc($result))
+    {
+	$html1 .= " <tr>\n";
+        $html1 .= "  <td>".$row["fStart"]."|</td>\n";
+        $html1 .= "  <td>".$row["fMeasurementTypeName"]."</td>\n";
+        $html1 .= "  <td>|".$row["fSourceName"]."</td>\n";
+        $html1 .= "  <td>[".$row["fUser"]."]</td>\n";
+        $html1 .= " </tr>\n";
+
+        $array[$n++] = $row;
+    }
+    $html1 .= "</table>\n";
+
+    mysql_free_result($result);
+}
+else
+    $html1 = "[empty:".mysql_error()."]\n";
+
+// --------------------------------------------------------------------
+
+$html2 = "<table>\n";
+
+$suspend = false;
+$prev_data = array();
+
+for ($i=0; $i<$n-1; $i++)
+{
+    // Switch to "suspend-mode"
+    if ($array[$i]['fMeasurementTypeName']=='Suspend')
+    	$suspend = true;
+
+    // If a resume is found, the data is replaced with the
+    // last data run with the resume-time as start time.
+    if ($array[$i]['fMeasurementTypeName']=='Resume')
+    {
+        // Sanity check: There is not much we can do
+        if (empty($prev_data) || !$suspend)
+           continue;
+
+        $prev_data['fStart'] = $array[$i]['fStart'];
+        $array[$i] = $prev_data;
+        $suspend = false;
+    }
+
+    // None data runs are not displayed
+    if ($array[$i]['fMeasurementTypeName']!='Data')
+        continue;
+
+    // If this is a data run keep that for use after a suspend/resume
+    $prev_data = $array[$i];
+
+    // If the system is suspended, don't display the runs
+    if ($suspend)
+       continue;
+
+    $data .= "[";
+    $data .= "'".$table."',";
+    $data .= "'".$array[$i]['fSourceName']."',";
+    $data .= fmt($array[$i]['fStart']).",";
+    $data .= fmt($array[$i+1]['fStart']).",";
+    $data .= "],\n";
+
+    $html2 .= " <tr>";
+    $html2 .= "  <td>".$array[$i]['fStart']."|</td>\n";
+    $html2 .= "  <td>".$array[$i]["fSourceName"]."</td>\n";
+    $html2 .= "  <td>|".$array[$i+1]["fStart"]."|</td>\n";
+    $html2 .= " </tr>\n";
+}
+
+$html2 .= "</table>\n";
+}
+
+// --------------------------------------------------------------------
+
+function QueryRunInfo(&$data, &$diff, &$html2, &$query2, $night, $db_id, $where)
+{
+$query2 = <<< EOT
+
+SELECT
+   fRunID,
+   fSourceName,
+   fRunStart,
+   fRunStop
+FROM RunInfo
+LEFT JOIN Source USING(fSourceKey)
+LEFT JOIN AnalysisResultsRunLP USING (fNight, fRunID)
+WHERE fNight=$night
+   AND NOT fRunStart='0000-00-00 00:00:00'
+   AND NOT fRunStop='0000-00-00 00:00:00'
+   AND fRunTypeKEY=1
+   $where
+ORDER BY fRunID
+
+EOT;
+
+// --------------------------------------------------------------------
+
+$array2 = array();
+
+$result2 = mysql_query($query2, $db_id);
+if ($result2)
+{
+    $html2 .= "<table>\n";
+
+    $n = 0;
+    while ($row = mysql_fetch_assoc($result2))
+    {
+        if (empty($row['fSourceName']))
+            continue;
+
+        $data .= "[";
+        $data .= "'RunInfo',";
+        $data .= "'".$row['fSourceName']."',";
+        $data .= fmt($row['fRunStart']).",";
+        $data .= fmt($row['fRunStop']).",";
+        $data .= "],\n";
+
+
+        $html2 .= " <tr>\n";
+        $html2 .= "  <td>".$row["fRunStart"]." | </td>\n";
+        $html2 .= "  <td>".$row["fSourceName"]."</td>\n";
+        $html2 .= "  <td> | ".$row["fRunStop"]."</td>\n";
+        $html2 .= " </tr>\n";
+
+        $diff .= $row["fRunStart"]." | ";
+        $diff .= $row["fSourceName"]." | ";
+        $diff .= $row["fRunStop"]."\n";
+
+        $n++;
+    }
+    $html2 .= "</table>\n";
+
+    mysql_free_result($result2);
+}
+else
+    $html2 = "[empty:".mysql_error()."]\n";
+}
+
+// --------------------------------------------------------------------
+
+QuerySchedule($data, $html0a, $html0b, $query0, $db_id, "AutoSchedule", $date);
+QuerySchedule($data, $html1a, $html1b, $query1, $db_id, "Schedule",     $date);
+
+// --------------------------------------------------------------------
+
+QueryRunInfo($dataA, $diffA, $html2, $query2, $night, $db_id, "");
+QueryRunInfo($dataB, $diffB, $html3, $query3, $night, $db_id, "AND NOT ISNULL(fNumExcEvts)");
+
+$data .= $dataA;
+
+$diff = "";
+if ($dataA!=$dataB)
+{
+   $diff = Diff::toTable(Diff::compare($diffA, $diffB));
+   $data .= str_replace("RunInfo", "QLA", $dataB);
+}
+
+// --------------------------------------------------------------------
+
+mysql_close($db_id);
+
+// --------------------------------------------------------------------
+
+$color = "false";
+if (empty($data))
+{
+   $data = "['No Schedule','',new Date(1970,1,1,19,0,0),new Date(1970,1,2,7,0,0)]";
+   $color = "'#eee'";
+}
+
+$querycol0 = colorize($query0);
+$querycol1 = colorize($query1);
+$querycol2 = colorize($query2);
+$querycol3 = colorize($query3);
+
+// --------------------------------------------------------------------
+
+echo <<<EOT
+
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="//code.jquery.com/jquery-2.2.1.min.js"        integrity="sha256-gvQgAFzTH6trSrAWoH1iPo9Xc96QxSZ3feW6kem+O00=" crossorigin="anonymous"></script>
+<script src="//code.jquery.com/ui/1.11.4/jquery-ui.min.js" integrity="sha256-xNjb53/rY+WmG+4L6tTl9m6PpqknWZvRt0rO1SRnJzw=" crossorigin="anonymous"></script>
+
+<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
+
+<script type="text/javascript" src="//www.gstatic.com/charts/loader.js"></script>
+<script type="text/javascript">
+
+    google.charts.load('current', {packages: ['timeline']});
+    google.charts.setOnLoadCallback(draw);
+
+    function draw()
+    {
+	$(document).keydown(function(e)
+        {
+            var offset = 0;
+            if (e.which == 38) offset =  7*24*3600*1000;
+            if (e.which == 40) offset = -7*24*3600*1000;
+            if (e.which == 39) offset =  1*24*3600*1000;
+            if (e.which == 37) offset = -1*24*3600*1000;
+            if (!offset)
+                return;
+
+            var d = $("#datepicker").datepicker("getDate");//.getTime();
+
+            var c = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate())+offset);
+
+            window.location = "?d="+c.toISOString().split("T")[0];
+
+            //$("#datepicker").datepicker("setDate", date);
+            //$("#datepicker").trigger("select");
+
+            return false;
+        });
+
+      var dp = $("#datepicker").datepicker({
+  autoSize: true,
+  dateFormat: "yy-mm-dd",
+  selectOtherMonths: true,
+  /*showButtonPanel: true,*/
+  showWeek: true,
+  defaultDate: "$date",
+  inline: true,
+  changeMonth: true,
+  changeYear: true,
+  minDate: new Date(2011, 10, 15),
+  onSelect: function(date) { window.location = "?d="+date; }
+
+});
+
+      var data = new google.visualization.DataTable();
+      data.addColumn({ type: 'string', id: 'Role' });
+      data.addColumn({ type: 'string', id: 'Name' });
+      data.addColumn({ type: 'date', id: 'Start' });
+      data.addColumn({ type: 'date', id: 'End' });
+      data.addRows([$data]);
+
+      //var dateFormatter = new google.visualization.DateFormat({pattern: 'dd/MM/yyyy HH:mm'});
+      //dateFormatter.format(data, 2);
+      //dateFormatter.format(data, 3);
+
+      var options = {
+        hAxis: {format:'HH:mm', minorGridlines: {count:1}},
+        avoidOverlappingGridLines: false,
+        timeline: { singleColor: $color },
+      };
+
+      var chart = new google.visualization.Timeline(document.getElementById('chart_div'));
+      chart.draw(data, options);
+      //document.getElementById('print_chart').innerHTML = '<a href="' + chart.getImageURI() + '">Print</a>';
+      console.log("Google.chart.ready");
+    }
+</script>
+<style>
+dl {
+    //border: 3px double #ccc;
+    padding: 0.5em;
+  }
+  dt {
+    float: left;
+    clear: left;
+    width: 130px;
+    text-align: right;
+    font-weight: bold;
+    color: green;
+  }
+  dt:after {
+    content: ":";
+  }
+  dd {
+    margin: 0 0 0 140px;
+    padding: 0 0 1em 0;
+  }
+  code {
+	padding: 0 3px;
+	background-color: #eee; /* support: IE8 */;
+	background-color: rgba( 0, 0, 0, .1 );
+	border-radius: 3px;
+}
+.diff td{
+  vertical-align : top;
+  /*white-space    : pre;
+  white-space    : pre-wrap;*/
+  font-family    : monospace;
+}
+.diff span{
+  margin-right: 2em;
+}
+
+/*      .diff span:first-child{
+        margin-top:0;
+      }*/
+
+      .diffDeleted span{
+        border:1px solid rgb(255,192,192);
+        background:rgb(255,224,224);
+      }                                                        <
+
+      .diffInserted span{
+        border:1px solid rgb(192,255,192);
+        background:rgb(224,255,224);
+      }
+
+
+</style>
+
+<body>
+
+<p style="font-weight: bold;font-size:130%;">Date: <input type="text" id="datepicker" style="font-weight:normal;font-size:100%;" value="$date"></p>
+
+<div style='position:relative'>
+<!--<H3>$date</H3>-->
+<div id='chart_div' style="height:220px;width:99%;margin-left:0.5%;">Preparing chart... please stand by.</div>
+<div id='print_chart' style='position:absolute;top:10px;right:40px;'></div>
+</div>
+
+<hr>
+
+<input type="button" onclick="$('#spoiler0').toggle(300);" value="Legend"/>
+<div id="spoiler0" style="display:none">
+ <dl>
+  <dt>AutoSchedule</dt>
+  <dd>(if available) The schedule from the AutoSchedule table as planned by the autoscheduler (<i>makeschedule</I>).</dd>
+  <dt>Schedule</dt>
+  <dd>The schedule as available in the Schedule table after the night.</dd>
+  <dt>RunInfo</dt>
+  <dd>The schedule as executed, taken from the RunInfo table. Only data runs are counted.</dd>
+  <dt>QLA</dt>
+  <dd>This row is only displayed if different from RunInfo. It shows all runs
+      which have been processed by the QLA already.
+ </dl>
+Note that the two schedules will never perfectly coincide with the runs taken
+because finite Measurements scheduled together with a source in one observation
+are counted to be part of the source. Also automatic calibration
+runs are obviously not accounted for in the schedule.
+
+<hr>
+
+<h3>Keyboard interaction</h3>
+
+<li><code>LEFT</code>: Move to the previous day.</li>
+<li><code>RIGHT</code>: Move to the next day.</li>
+<li><code>UP</code>: Move to the previous week.</li>
+<li><code>DOWN</code>: Move the next week.</li>
+
+<p>While the datepicker is open, the following key commands are available:</p>
+<ul>
+<li><code>PAGE UP</code>: Move to the previous month.</li>
+<li><code>PAGE DOWN</code>: Move to the next month.</li>
+<li><code>CTRL</code> + <code>PAGE UP</code>: Move to the previous year.</li>
+<li><code>CTRL</code> + <code>PAGE DOWN</code>: Move to the next year.</li>
+<li><code>CTRL</code> + <code>HOME</code>: Open the datepicker if closed.</li>
+<li><code>CTRL</code>/<code>COMMAND</code> + <code>HOME</code>: Move to the current month.</li>
+<li><code>CTRL</code>/<code>COMMAND</code> + <code>LEFT</code>: Move to the previous day.</li>
+<li><code>CTRL</code>/<code>COMMAND</code> + <code>RIGHT</code>: Move to the next day.</li>
+<li><code>CTRL</code>/<code>COMMAND</code> + <code>UP</code>: Move to the previous week.</li>
+<li><code>CTRL</code>/<code>COMMAND</code> + <code>DOWN</code>: Move the next week.</li>
+<li><code>ENTER</code>: Select the focused date.</li>
+<li><code>CTRL</code>/<code>COMMAND</code> + <code>END</code>: Close the datepicker and erase the date.</li>
+<li><code>ESCAPE</code>: Close the datepicker without selection.</li>
+</ul>
+
+</div>
+
+<hr>
+
+<input type="button" onclick="$('#spoiler1').show(300);$('#spoiler2').show(300);$('#spoiler3').show(300);$('#spoiler4').show(300);" value="Show all tables"/>
+<input type="button" onclick="$('#spoiler1').hide(300);$('#spoiler2').hide(300);$('#spoiler3').hide(300);$('#spoiler4').hide(300);" value="Hide all tables"/>
+
+<hr>
+
+<input type="button" onclick="$('#spoiler1').toggle(300);" value="Planned Schedule"/>
+<div id="spoiler1" style="display:none">
+$html0a
+<hr style='width:95%'>
+$html0b
+</div>
+
+<hr>
+
+<input type="button" onclick="$('#spoiler2').toggle(300);" value="Scheduled observations"/>
+<div id="spoiler2" style="display:none">
+$html1a
+<hr style='width:95%'>
+$html1b
+</div>
+
+<hr>
+
+<input type="button" onclick="$('#spoiler3').toggle(300);" value="Runs taken"/>
+<div id="spoiler3" style="display:none">
+$html2
+</div>
+
+<hr>
+
+<input type="button" onclick="$('#spoiler4').toggle(300);" value="Runs analysed"/>
+<div id="spoiler4" style="display:none">
+$html2
+</div>
+
+<hr>
+
+<input type="button" onclick="$('#spoiler5').toggle(300);" value="Diff taken/analysed"/>
+<div id="spoiler5" style="display:none">
+$diff
+</div>
+
+<hr>
+
+<input type="button" onclick="$('#spoiler6').toggle(300);" value="SQL query (Auto)Schedule"/>
+<div id="spoiler6" style="display:none">
+<pre>
+$querycol0
+<hr style='width:95%'>
+$querycol1
+</pre>
+</div>
+
+<hr>
+
+<input type="button" onclick="$('#spoiler7').toggle(300);" value="SQL query RunInfo"/>
+<div id="spoiler7" style="display:none">
+<pre>
+$querycol2
+<hr style='width:95%'>
+$querycol3
+</pre>
+</div>
+
+<hr>
+
+</body>
+</html>
+EOT;
+
+?>
