diff --git a/airtime_mvc/application/configs/navigation.php b/airtime_mvc/application/configs/navigation.php index e2df2e3f5..59ce874fe 100644 --- a/airtime_mvc/application/configs/navigation.php +++ b/airtime_mvc/application/configs/navigation.php @@ -87,7 +87,7 @@ $pages = array( 'resource' => 'playouthistory' ), array( - 'label' => 'Listener Stat', + 'label' => 'Listener Stats', 'module' => 'default', 'controller' => 'listenerstat', 'action' => 'index', diff --git a/airtime_mvc/application/controllers/ListenerstatController.php b/airtime_mvc/application/controllers/ListenerstatController.php index d80bcf871..648a88dfe 100644 --- a/airtime_mvc/application/controllers/ListenerstatController.php +++ b/airtime_mvc/application/controllers/ListenerstatController.php @@ -18,6 +18,7 @@ class ListenerstatController extends Zend_Controller_Action $baseUrl = $request->getBaseUrl(); $this->view->headScript()->appendFile($baseUrl.'/js/flot/jquery.flot.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); + $this->view->headScript()->appendFile($baseUrl.'/js/flot/jquery.flot.crosshair.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); $this->view->headScript()->appendFile($baseUrl.'/js/airtime/listenerstat/listenerstat.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); $offset = date("Z") * -1; diff --git a/airtime_mvc/application/models/ListenerStat.php b/airtime_mvc/application/models/ListenerStat.php index 8e9a9e4b6..f5567fed5 100644 --- a/airtime_mvc/application/models/ListenerStat.php +++ b/airtime_mvc/application/models/ListenerStat.php @@ -7,25 +7,44 @@ class Application_Model_ListenerStat public static function getDataPointsWithinRange($p_start, $p_end) { $sql = <<=:p1 AND ts.timestamp <= :p2) - ORDER BY mount_name, timestamp +WHERE (ts.timestamp >=:p1 AND ts.timestamp <=:p2) +group by mount_name SQL; $data = Application_Common_Database::prepareAndExecute($sql, - array('p1'=>$p_start, 'p2'=>$p_end)); + array('p1'=>$p_start, 'p2'=>$p_end)); $out = array(); foreach ($data as $d) { - $t = new DateTime($d['timestamp'], new DateTimeZone("UTC")); - $t->setTimezone(new DateTimeZone(date_default_timezone_get())); - // tricking javascript so it thinks the server timezone is in UTC - $dt = new DateTime($t->format("Y-m-d H:i:s"), new DateTimeZone("UTC")); + $jump = intval($d['count']/1000); + $jump = max(1, $jump); + $remainder = $jump == 1?0:1; - $d['timestamp'] = $dt->format("U"); - $out[$d['mount_name']][] = $d; + $sql = <<=:p1 AND ts.timestamp <= :p2) AND mount_name=:p3) as temp +WHERE (temp.rownum%:p4) = :p5; +SQL; + $result = Application_Common_Database::prepareAndExecute($sql, + array('p1'=>$p_start, 'p2'=>$p_end, 'p3'=>$d['mount_name'], 'p4'=>$jump, 'p5'=>$remainder)); + foreach ($result as $r) { + $t = new DateTime($r['timestamp'], new DateTimeZone("UTC")); + $t->setTimezone(new DateTimeZone(date_default_timezone_get())); + // tricking javascript so it thinks the server timezone is in UTC + $dt = new DateTime($t->format("Y-m-d H:i:s"), new DateTimeZone("UTC")); + + $r['timestamp'] = $dt->format("U"); + $out[$r['mount_name']][] = $r; + } } return $out; } diff --git a/airtime_mvc/application/views/scripts/listenerstat/index.phtml b/airtime_mvc/application/views/scripts/listenerstat/index.phtml index 3df9f08ca..9f3568869 100644 --- a/airtime_mvc/application/views/scripts/listenerstat/index.phtml +++ b/airtime_mvc/application/views/scripts/listenerstat/index.phtml @@ -1,5 +1,5 @@
- Timestamp vs Listener Count
+ Listener Count Over Time
date_form; ?> diff --git a/airtime_mvc/public/js/airtime/listenerstat/listenerstat.js b/airtime_mvc/public/js/airtime/listenerstat/listenerstat.js index 02ebefab8..a410acf62 100644 --- a/airtime_mvc/public/js/airtime/listenerstat/listenerstat.js +++ b/airtime_mvc/public/js/airtime/listenerstat/listenerstat.js @@ -35,6 +35,7 @@ function getDataAndPlot(startTimestamp, endTimestamp){ } function plot(datasets){ + var plot; data = null; function plotByChoice(doAll) { @@ -81,9 +82,20 @@ function plot(datasets){ numOfTicks = 10; tickSize = (lastTimestamp.getTime() - firstTimestamp.getTime())/1000/numOfTicks; - $.plot($("#flot_placeholder"), data, { + plot = $.plot($("#flot_placeholder"), data, { yaxis: { min: 0, tickDecimals: 0 }, xaxis: { mode: "time", timeformat:"%y/%m/%0d %H:%M", tickSize: [tickSize, "second"] }, + grid: { + hoverable: true, + backgroundColor: { colors: ["#888888", "#999999"] } + }, + series: { + lines: { + show: true, + fill: 0.3 + }, + points: { show: true } + }, legend: { container: $('#legend'), noColumns: 5, @@ -99,6 +111,45 @@ function plot(datasets){ } }); + function showTooltip(x, y, contents) { + $('
' + contents + '
').css( { + position: 'absolute', + display: 'none', + top: y + 5, + left: x + 5, + border: '1px solid #fdd', + padding: '2px', + 'background-color': '#fee', + opacity: 0.80 + }).appendTo("body").fadeIn(200); + } + + var previousPoint = null; + $("#flot_placeholder").bind("plothover", function (event, pos, item) { + if (item) { + if (previousPoint != item.dataIndex) { + previousPoint = item.dataIndex; + + $("#tooltip").remove(); + var y = item.datapoint[1].toFixed(2); + + showTooltip(item.pageX, item.pageY, + "Listener Count on '"+item.series.label + "': " + Math.floor(y)); + } + } + else { + $("#tooltip").remove(); + previousPoint = null; + } + }); + + $("#placeholder").bind("plotclick", function (event, pos, item) { + if (item) { + $("#clickdata").text("You clicked point " + item.dataIndex + " in " + item.series.label + "."); + plot.highlight(item.series, item.datapoint); + } + }); + $('#legend').find("input").click(function(){setTimeout(plotByChoice,100);}); }