added punch-chart view of Level2 attendance

master
Tezza 2015-03-01 15:23:38 +01:00
parent 32af9ccf65
commit 30ddd6df82
11 changed files with 645 additions and 10 deletions

View File

@ -179,4 +179,38 @@
}
static public function getChartData( $app ) {
$dowMap = array( 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' );
$chartDataQuery = 'SELECT ROUND( AVG( people ) )
FROM state
WHERE datetime >= curdate() - INTERVAL 2 WEEK
AND WEEKDAY( datetime ) = ?
AND HOUR ( datetime ) = ?';
for( $dow = 0; $dow < 7; $dow++ ) {
$chartDataByDay[ 'name' ] = $dowMap[ $dow ];
for( $hod = 0; $hod < 24; $hod++ ) {
$chartDataByDay[ 'data' ][ $hod ] = $app[ 'db' ]->fetchColumn(
$chartDataQuery,
array(
$dow,
$hod
)
);
}
$chart[ $dow ] = $chartDataByDay;
}
return $chart;
}
}

View File

@ -41,8 +41,9 @@
return $app['twig']->render(
'openingTimes.twig',
array(
'page' => 'chart',
'level2' => Level2::getStatus( $app )
'page' => 'chart',
'level2' => Level2::getStatus( $app ),
'chart' => Helpers::JSON2Array( $app[ 'cache' ][ 'attendance' ][ 'json' ] )
)
);
@ -50,8 +51,9 @@
$ctr->get('/scrape', function() use ( $app ) {
Helpers::saveFile ( json_encode( Level2::getJSONCalendar( $app ) ), $app[ 'cache' ][ 'calendar' ][ 'json' ] );
Helpers::saveFile ( file_get_contents( $app[ 'google' ][ 'ical' ] ) , $app[ 'cache' ][ 'calendar' ][ 'ical' ] );
Helpers::saveFile ( json_encode( Level2::getJSONCalendar( $app ) ) , $app[ 'cache' ][ 'calendar' ][ 'json' ] );
Helpers::saveFile ( file_get_contents( $app[ 'google' ][ 'ical' ] ) , $app[ 'cache' ][ 'calendar' ][ 'ical' ] );
Helpers::saveFile ( json_encode( Level2::getChartData( $app ) ) , $app[ 'cache' ][ 'attendance' ][ 'json' ] );
return true;

View File

@ -15,6 +15,7 @@
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
<link href="/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/css/level2.css" rel="stylesheet">
<script src="/js/jquery.min.js"></script>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
@ -60,11 +61,8 @@
</div> <!-- /container -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="/js/d3.v3.min.js"></script>
<script src="/js/trianglify.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<script src="/js/level2.js"></script>
<script src="/bootstrap/js/bootstrap.min.js"></script>

View File

@ -35,7 +35,7 @@
<div class="google-map-container">
<a href="https://goo.gl/maps/OWqIf">
<img class="google-map no-margin" src="https://maps.googleapis.com/maps/api/staticmap?markers=color:blue%7Clabel:L%7C49.591597,6.140704&zoom=15&size=500x400" />
<img class="google-map no-margin" src="https://files.level2.lu/website/map.png" />
</a>
</div>

View File

@ -0,0 +1,37 @@
{% extends "base.twig" %}
{% block container %}
<div class="col-xs-12 well chart">
<table id="for-chart">
<tfoot>
<tr>
<td>&nbsp;</td>
{% for hour in 0..23 %}
<th>{{ hour }}</th>
{% endfor %}
</tr>
</tfoot>
<tbody>
{% for day in chart %}
<tr>
<th scope="row">{{ day.name }}</th>
{% for value in day.data %}
<td>{{ value }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<div id="chart"></div>
</div>
<script src="/js/raphael.js" type="text/javascript" charset="utf-8"></script>
<script src="/js/dots.js" type="text/javascript" charset="utf-8"></script>
{% endblock %}

View File

@ -2,7 +2,8 @@
"require": {
"silex/silex": "1.2.2",
"igorw/config-service-provider": "~1.2",
"twig/twig": ">=1.8,<2.0-dev"
"twig/twig": ">=1.8,<2.0-dev",
"doctrine/dbal" : "~2.4"
},
"autoload": {
"psr-0": {

478
src/composer.lock generated
View File

@ -4,8 +4,484 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "495bca3f44b9076d1110a6fe8e51814e",
"hash": "cb97ec1ecb0bc6c2f533cf823334f57a",
"packages": [
{
"name": "doctrine/annotations",
"version": "v1.2.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
"reference": "eeda578cbe24a170331a1cfdf78be723412df7a4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/eeda578cbe24a170331a1cfdf78be723412df7a4",
"reference": "eeda578cbe24a170331a1cfdf78be723412df7a4",
"shasum": ""
},
"require": {
"doctrine/lexer": "1.*",
"php": ">=5.3.2"
},
"require-dev": {
"doctrine/cache": "1.*",
"phpunit/phpunit": "4.*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\Annotations\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Docblock Annotations Parser",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"annotations",
"docblock",
"parser"
],
"time": "2014-12-20 20:49:38"
},
{
"name": "doctrine/cache",
"version": "v1.4.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/cache.git",
"reference": "2346085d2b027b233ae1d5de59b07440b9f288c8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/cache/zipball/2346085d2b027b233ae1d5de59b07440b9f288c8",
"reference": "2346085d2b027b233ae1d5de59b07440b9f288c8",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"conflict": {
"doctrine/common": ">2.2,<2.4"
},
"require-dev": {
"phpunit/phpunit": ">=3.7",
"predis/predis": "~0.8",
"satooshi/php-coveralls": "~0.6"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\Cache\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Caching library offering an object-oriented API for many cache backends",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"cache",
"caching"
],
"time": "2015-01-15 20:38:55"
},
{
"name": "doctrine/collections",
"version": "v1.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/collections.git",
"reference": "b99c5c46c87126201899afe88ec490a25eedd6a2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/collections/zipball/b99c5c46c87126201899afe88ec490a25eedd6a2",
"reference": "b99c5c46c87126201899afe88ec490a25eedd6a2",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\Collections\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com",
"homepage": "http://www.jwage.com/",
"role": "Creator"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com",
"homepage": "http://www.instaclick.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com",
"homepage": "https://github.com/schmittjoh",
"role": "Developer of wrapped JMSSerializerBundle"
}
],
"description": "Collections Abstraction library",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"array",
"collections",
"iterator"
],
"time": "2014-02-03 23:07:43"
},
{
"name": "doctrine/common",
"version": "v2.4.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/common.git",
"reference": "5db6ab40e4c531f14dad4ca96a394dfce5d4255b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/common/zipball/5db6ab40e4c531f14dad4ca96a394dfce5d4255b",
"reference": "5db6ab40e4c531f14dad4ca96a394dfce5d4255b",
"shasum": ""
},
"require": {
"doctrine/annotations": "1.*",
"doctrine/cache": "1.*",
"doctrine/collections": "1.*",
"doctrine/inflector": "1.*",
"doctrine/lexer": "1.*",
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "~3.7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.4.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com",
"homepage": "http://www.jwage.com/",
"role": "Creator"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com",
"homepage": "http://www.instaclick.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com",
"homepage": "https://github.com/schmittjoh",
"role": "Developer of wrapped JMSSerializerBundle"
}
],
"description": "Common Library for Doctrine projects",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"annotations",
"collections",
"eventmanager",
"persistence",
"spl"
],
"time": "2014-05-21 19:28:51"
},
{
"name": "doctrine/dbal",
"version": "v2.5.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
"reference": "628c2256b646ae2417d44e063bce8aec5199d48d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/628c2256b646ae2417d44e063bce8aec5199d48d",
"reference": "628c2256b646ae2417d44e063bce8aec5199d48d",
"shasum": ""
},
"require": {
"doctrine/common": ">=2.4,<2.6-dev",
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "4.*",
"symfony/console": "2.*"
},
"suggest": {
"symfony/console": "For helpful console commands such as SQL execution and import of files."
},
"bin": [
"bin/doctrine-dbal"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.5.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\DBAL\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
}
],
"description": "Database Abstraction Layer",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"database",
"dbal",
"persistence",
"queryobject"
],
"time": "2015-01-12 21:52:47"
},
{
"name": "doctrine/inflector",
"version": "v1.0.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "0bcb2e79d8571787f18b7eb036ed3d004908e604"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/0bcb2e79d8571787f18b7eb036ed3d004908e604",
"reference": "0bcb2e79d8571787f18b7eb036ed3d004908e604",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "4.*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\Inflector\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Common String Manipulations with regard to casing and singular/plural rules.",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"inflection",
"pluralize",
"singularize",
"string"
],
"time": "2014-12-20 21:24:13"
},
{
"name": "doctrine/lexer",
"version": "v1.0.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/lexer.git",
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\Lexer\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"lexer",
"parser"
],
"time": "2014-09-09 13:34:57"
},
{
"name": "igorw/config-service-provider",
"version": "v1.2.2",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

72
src/web/js/dots.js Normal file
View File

@ -0,0 +1,72 @@
$(function () {
// Grab the data
var data = [],
axisx = [],
axisy = [],
table = $("#for-chart");
$("tbody td", table).each(function (i) {
data.push(parseFloat($(this).text(), 10));
});
table.hide();
$("tbody th", table).each(function () {
axisy.push($(this).text());
});
$("tfoot th", table).each(function () {
axisx.push($(this).text());
});
// Draw
var width = $( '.chart' ).width(),
height = 300,
leftgutter = 30,
bottomgutter = 20,
r = Raphael("chart", width, height),
txt = {"font": '12px Open Sans, sans-serif', stroke: "none", fill: "#333333"},
X = (width - leftgutter) / axisx.length,
Y = (height - bottomgutter) / axisy.length,
color = $("#chart").css("color");
max = Math.round(X / 2) - 1;
// r.rect(0, 0, width, height, 5).attr({fill: "#000", stroke: "none"});
for (var i = 0, ii = axisx.length; i < ii; i++) {
r.text(leftgutter + X * (i + .5), 294, axisx[i]).attr(txt);
}
for (var i = 0, ii = axisy.length; i < ii; i++) {
r.text(10, Y * (i + .5), axisy[i]).attr(txt);
}
var o = 0;
for (var i = 0, ii = axisy.length; i < ii; i++) {
for (var j = 0, jj = axisx.length; j < jj; j++) {
var R = data[o] && Math.min(Math.round(Math.sqrt(data[o] / Math.PI) * 7), max);
if (R) {
(function (dx, dy, R, value) {
var color = "hsb(" + [(1 - R / max) * .5, 1, .75] + ")";
var dt = r.circle(dx + 60 + R, dy + 10, R).attr({stroke: "none", fill: color});
if (R < 6) {
var bg = r.circle(dx + 60 + R, dy + 10, 6).attr({stroke: "none", fill: "#000", opacity: .4}).hide();
}
var lbl = r.text(dx + 60 + R, dy + 10, data[o])
.attr({"font": '10px Fontin-Sans, Arial', stroke: "none", fill: "#fff"}).hide();
var dot = r.circle(dx + 60 + R, dy + 10, max).attr({stroke: "none", fill: "#000", opacity: 0});
dot[0].onmouseover = function () {
if (bg) {
bg.show();
} else {
var clr = Raphael.rgb2hsb(color);
clr.b = .5;
dt.attr("fill", Raphael.hsb2rgb(clr).hex);
}
lbl.show();
};
dot[0].onmouseout = function () {
if (bg) {
bg.hide();
} else {
dt.attr("fill", color);
}
lbl.hide();
};
})(leftgutter + X * (j + .5) - 60 - R, Y * (i + .5) - 10, R, data[o]);
}
o++;
}
}
});

4
src/web/js/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

11
src/web/js/raphael.js Normal file

File diff suppressed because one or more lines are too long