Like every other monday, we started with a meeting. I would continue my work on the check-in application. Because the application was getting bigger and harder to maintain, I was free to choose a template engine and/or framework.
I did a school project in Symfony2 and I really liked working with Doctrine, Twig, the dependency injection, the routing, ... But Symfony2 as a full-stack framework was overkill in my opinion, so I started digging into the Silex documentation.
Switching to Silex
Thanks to some excellent course material made by Bramus Vandamme, I started rewriting my code to a fully working Silex webapp. To do so, I first created my basic Silex project structure (a web folder with the public files, and an app & src folder with the logic). I've first set up my bootstrap and application code and then I configured my routing to the appropriate controllers.
Each section of the checkin application has it's own controller and implements the
ControllerProviderInterface, which also defines subroutes for that "section". Working with data happens in each repository class, which can be accessed thanks to the dependency injection, e.g.
I used a lot of Service Providers, like:
- Twig, the preferred template engine. Very intuitively and easy to use.
- Doctrine, for Doctrine DBAL integration in Silex.
- Knp Doctrine Repository service provider
- URLGenerator service provider
- Session service provider
- Security service provider
- Webprofiler service provider
I used the Security service provider with a custom User Provider to keep the webapplication secure, but I also defined the user roles (e.g. admins, users, ...) to keep the admin pages only accessible for the admins.
Once the application was back up and running – faster, cleaner, more secure and better then ever – I begon to create some interesting dashboard widgets. Once you gather a lot of check-in data, you can do so much with it on the dashboard.
One of the idea's was to create a weekly overview of your check-ins. The other idea was to calculate a score for each user, where 0 means that the user is working exactly the hours he's supposed to do. A negative score, like -1.5 means that the employee worked 1h30 less than he's supposed to be working. The aim is to keep this value as close to zero (or higher) as possible.
Calculating the score
To implement the user score I realised I couldn't calculate the user score of every check-in on the fly, because this wouldn't be efficiënt when the user has already made hundreds of check in the past. So I created my functions to calculate the user score from a specified start & end date. This function would calculate how much hours the user is supposed to work in that specified period, and the calculate the sum of all the check-ins in that period and finally calculate the difference. The score is then added to the score column of that user in the database.
Looks like I've been doing 21 minutes of overtime :-)
I've set up a cron job to run this function each morning (or better: at night). I created a CronController class with different functions to run every month, week, daily or after each check-in. I then configured the cron jobs with Lingon on my mac, but the crontab on linux will take care of the cronjobs when the app goes into production.
The cronjob function will calculate the score during the period of time since the last calculation was done, and adds this score to the userscore in the database. By doing that, the hundreds of check-ins previously done by the user during the past months, years, .. don't have to be iterated which benefits the workload of the server.
Weekly check-ins graph
The idea was to display each check-in on to each day of the week like a bar, sort of like the iCal week view. I was fascinated by the possibilities of HighCharts.js and I thought it would get the job done.
I started experimenting with highcharts in jsfiddle and after a couple of hours I already could show a working example.
Arrival of the Raspberry Pi
The raspberry pi got delivered this week, so I immediately started configuring it. It's amazing how easy this was! You insert the usb power adapter, the SD card with the OS, a hdmi cable, and a usb keyboard & mouse. The raspberry pi will boot and the first thing you'll see is the raspi-config window.
Here you can expand the disk space to use the full capacity of the SD card, instead of the necessary 2GB. I also set the keyboard layout, my locale and timezone, and enabled SSH access. Then started the update and finally I finished and went to the terminal where I started the GUI by entering the
I followed this tutorial to setup my Edimax wifi usb adapter and then I connected to the Thinline wifi network. I didn't need the keyboard and mouse at this stage, so I disconnected it and logged into the raspberry pi from my mac with SSH. I finally installed TightVNCServer to login with VNC when I need to.
I bought myself a book called "Programming the Raspberry Pi: Getting started with Python" by Simon Monk, as I'm getting fascinated by the raspberry pi and I'm planning to use it to create some small projects at home. I'll also be learning Python, and there are many reasons to do this:
- It's a very high-level language, so it's easy to learn and a lot of the more complex concepts of other programming languages are made easy in python. It also has an easy-to-read syntax, while being very powerful and letting you get a lot done very quickly.
- It's multi-purpose. If you learn a language such as PHP, your aim is to build websites, but with Python you can script almost anything, websites included.
- It got a very large standard library, so most of the things have already been included in Python. No need to browse the internet looking for libraries or algorithms.
- Excellent for beginners, yet superb for experts.
I tried making a simple api request, and this was only a few lines of code:
import requests url = 'http://checkin.localhost/api/users/4/checkins' r = requests.post(url) print(r)
The NFC/RFID break-out board, the cobbler kit and the LCD display were out of stock last week in the adafruit shop, so we'll have to wait a few more days until I can work on the hardware part of this project.