Skip to content

Instantly share code, notes, and snippets.

@mathieuancelin
Created March 23, 2012 14:32
Show Gist options
  • Save mathieuancelin/2171195 to your computer and use it in GitHub Desktop.
Save mathieuancelin/2171195 to your computer and use it in GitHub Desktop.
package controllers
import play.api._
import play.api.mvc._
import play.api.libs._
import play.api.libs.iteratee._
import play.api.libs.concurrent.Promise
import java.util.concurrent.TimeUnit
import scala.concurrent.stm._
object Application extends Controller {
def index() = Action {
Ok( views.html.index() )
}
def monitoringSource() = Action {
SimpleResult(
header = ResponseHeader(
OK,
Map(
CONTENT_LENGTH -> "-1",
CONTENT_TYPE -> "text/event-stream"
)
),
monitoring &> toEventSource
)
}
val toEventSource = Enumeratee.map[String] { msg => "data: " + msg + "\n\n" }
val monitoring = Enumerator.fromCallback{ () =>
Promise.timeout(
Some( ((Math.random * 200) + 1).toInt +
":" + ((Math.random * 200) + 1).toInt +
":" + ((Math.random * 200) + 1).toInt +
":" + ((Math.random * 200) + 1).toInt), 1000, TimeUnit.MILLISECONDS )
}
}
@()
@main("SSE Monitoring") {
<h1>Monitoring</h1>
<div id="text"></div>
<div id="zone">
<canvas id="drawing" style="border: 1px solid; background: #303030;"></canvas>
</div>
<script type="text/javascript">
var charts = new Array( {
fromX: 10, fromY: 10, val: 0,
current: 0, doMove: 0, previous: -1
}, {
fromX: 70, fromY: 10, val: 0,
current: 0, doMove: 0, previous: -1
}, {
fromX: 130, fromY: 10, val: 0,
current: 0, doMove: 0, previous: -1
}, {
fromX: 190, fromY: 10, val: 0,
current: 0, doMove: 0, previous: -1
} )
var canvas
var context
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback, element){
window.setTimeout(callback, 1000 / 60);
};
})();
function openSSEConnection() {
var pushSource = new EventSource( '@routes.Application.monitoringSource()' )
pushSource.onopen = function(e) {
console.log("[INFO] Monitoring event source opened !")
}
pushSource.onerror = function(e) {
if (pushSource.readyState == EventSource.CLOSED) {
console.log("[INFO] Monitoring event source closed !")
} else {
console.log("[ERROR] Monitoring event source error : %s", e)
}
charts.forEach(function(element, index, array) {
element.val = 0
})
context.fillStyle = "rgb(255,0,0)"
context.fillRect(245, 10, 10, 10)
$( '#text' ).html( "Error !!!" )
}
pushSource.onmessage = function ( event ) {
var vals = event.data.split(":")
vals.forEach(function(element, index, array) {
charts[index].val = element * 1
})
//$( '#text' ).html( charts[0].val + " : " + charts[1].val + ":" + charts[2].val + ":" + charts[3].val )
}
}
$( document ).ready( function () {
var canvas = document.getElementById('drawing');
init(canvas, charts);
context.lineWidth = 1
context.lineCap = 'square'
context.font = "7pt Calibri";
charts.forEach(function(element, index, array) {
drawGrads(array, index)
})
animate()
setTimeout(openSSEConnection, 200)
})
/**
* Draw animation
**/
function draw() {
charts.forEach(function(element, index, array) {
drawBar(array, index)
})
}
function drawGrads(arr, index) {
var fromX = arr[index].fromX
var fromY = arr[index].fromY
// legend
context.fillStyle = "rgb(96,96,96)"
context.fillText("200", fromX + 34, fromY + 3)
context.fillText("150", fromX + 34, fromY + 53)
context.fillText("100", fromX + 34, fromY + 103)
context.fillText("50", fromX + 34, fromY + 153)
context.fillText("0", fromX + 34, fromY + 193)
}
function drawBar(arr, index) {
// if value didn't move then do nothing
if (arr[index].previous == arr[index].val) {
return
}
var fromX = arr[index].fromX
var fromY = arr[index].fromY
context.clearRect(fromX - 3, fromY - 3, 35, 210)
// bar background
context.fillStyle = "rgb(64,64,64)";
context.fillRect (fromX - 2, fromY - 2, 34, 202);
// around bar
context.strokeStyle = "rgb(96,96,96)"
context.beginPath();
context.moveTo(fromX,fromY);
context.lineTo(fromX + 30,fromY);
context.lineTo(fromX +30,fromY + 200);
context.lineTo(fromX,fromY + 200);
context.lineTo(fromX,fromY);
// legend bars
context.moveTo(fromX,fromY +50);
context.lineTo(fromX +30,fromY+50);
context.moveTo(fromX,fromY + 100);
context.lineTo(fromX +30,fromY + 100);
context.moveTo(fromX,fromY+150);
context.lineTo(fromX +30,fromY+150);
context.closePath();
context.stroke();
// bar
context.fillStyle = "00CCFF";
arr[index].current = arr[index].current + arr[index].doMove
context.fillRect (fromX, fromY + (200 - arr[index].current), 30, 198 - (200 - arr[index].current))
// compute next move
if (arr[index].current > arr[index].val) {
arr[index].doMove = calcInc( arr[index].current, arr[index].val )
}
if (arr[index].current < arr[index].val) {
arr[index].doMove = calcInc( arr[index].current, arr[index].val )
}
if (arr[index].current == arr[index].val) {
arr[index].doMove = 0
arr[index].previous = arr[index].val
}
}
/** Speed for bars to get a natural movement **/
var SPEEDY = 3
var SLOWY = 1
/**
* Return the right increment for bar so they accelerate
* and decelerate at start and stop between 2 values
**/
function calcInc(current, val) {
if (current < val) {
if (val - current < 20) {
return SLOWY
} else {
return SPEEDY
}
}
if (current > val) {
if (current - val < 20) {
return -SLOWY
} else {
return -SPEEDY
}
}
}
/**
* Init the canvas size
**/
function init(canvas, chart) {
canvas.width = (chart.length * 60) + 20;
canvas.height = 220;
context = canvas.getContext( '2d' )
}
/**
* Callback function for animation drawing
**/
function animate() {
requestAnimFrame( animate )
draw()
}
</script>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment