Merged branch history_model.

This commit is contained in:
A. Svensson 2015-03-08 13:28:02 +01:00
commit 50b4bcc36e
6 changed files with 58 additions and 61 deletions

View File

@ -3,6 +3,5 @@ django
django-debug-toolbar
requests
beautifulsoup4
redis
gunicorn
fabric

View File

@ -1,12 +1,10 @@
#!/usr/bin/env python
import re
import time
from django.core.management.base import BaseCommand
from django.utils import timezone
from gameservers.models import Server, PlayerHistory
from gameservers.models import Server, ServerHistory
import requests
from bs4 import BeautifulSoup
@ -88,15 +86,14 @@ class ServerParser(object):
class Command(BaseCommand):
help = 'Update population stats for all ss13 servers.'
help = 'Update history stats for all ss13 servers.'
def handle(self, *args, **kwargs):
parser = ServerParser()
#parser.url = './dump.html' # Use a local file instead when testing
servers = parser.run()
history = PlayerHistory()
now = time.mktime(timezone.now().timetuple())
servers_handled = []
new_items = []
for data in servers:
# Prevent empty servers with identical names to other, active servers
@ -106,10 +103,6 @@ class Command(BaseCommand):
else:
servers_handled.append(data['title'])
# Keep the amount of data down in redis
history.trim_points(data['title'])
# TODO: do bulk insert instead!
server, created = Server.objects.update_or_create(
title=data['title'],
defaults= dict(
@ -119,8 +112,9 @@ class Command(BaseCommand):
)
)
# Update the player history
history.add_point(server, now, data['player_count'])
history = ServerHistory(server=server, players=data['player_count'])
new_items.append(history)
ServerHistory.objects.bulk_create(new_items)
Server.remove_old_servers()

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('gameservers', '0010_auto_20150223_1927'),
]
operations = [
migrations.CreateModel(
name='ServerHistory',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('created', models.DateTimeField(default=django.utils.timezone.now)),
('players', models.PositiveIntegerField(default=0)),
('server', models.ForeignKey(to='gameservers.Server')),
],
options={
'ordering': ['-created', 'server'],
},
bases=(models.Model,),
),
]

View File

@ -2,8 +2,6 @@
from django.db import models
from django.utils import timezone
import redis
class Server(models.Model):
title = models.CharField(max_length=255)
@ -28,32 +26,14 @@ class Server(models.Model):
server.delete()
class PlayerHistory(object):
def __init__(self, redis_settings=dict(host='localhost', port=6379, db=0)):
self.redis = redis.StrictRedis(**redis_settings)
class ServerHistory(models.Model):
server = models.ForeignKey(Server)
created = models.DateTimeField(default=timezone.now)
players = models.PositiveIntegerField(default=0)
# 32256 = 4 times per hour * 24 hours * 7 days * 4 weeks * 12 months
self.max_items = 32256
class Meta:
ordering = ['-created', 'server']
def add_point(self, server, time, players):
'''Add a new point in the player history.'''
self.redis.lpush(server, '{},{}'.format(time, players))
def trim_points(self, server):
'''Trim away too old points and servers in the player history.'''
self.redis.ltrim(server, 0, self.max_items)
# let the list expire after a week without updates
self.redis.expire(server, 604800)
def get_history(self, server, days=7):
'''Get a range of days in a server's player history.'''
# 96 = 4 times per hour * 24 hours
max_items = days * 96
items = []
for tmp in self.redis.lrange(server, 0, max_items):
time, players = tmp.split(',')
time, players = float(time), int(players)
items.append((time, players))
return items
def __str__(self):
return 'History for {} at {}.'.format(self.server, self.created)

View File

@ -1,8 +1,11 @@
from datetime import timedelta
from django.shortcuts import render
from django.views import generic
from django.utils import timezone
from .models import Server, PlayerHistory
from .models import Server, ServerHistory
class ServerListView(generic.ListView):
model = Server
@ -13,25 +16,24 @@ class ServerDetailView(generic.DetailView):
def get_context_data(self, **kwargs):
context = super(ServerDetailView, self).get_context_data(**kwargs)
server = context['server']
history = PlayerHistory()
items = history.get_history(server)
context['player_history'] = items
weekly_history = ServerHistory.objects.filter(
server=server,
created__gte=timezone.now() - timedelta(days=7),
)
context['weekly_history'] = weekly_history
# Moving average for the last day
# TODO: remove the hardcoded value
tmp = [players for time, players in items[-96:]]
tmp = [tmp.players for tmp in ServerHistory.objects.filter(
server=server,
created__gte=timezone.now() - timedelta(days=1))]
context['daily_average'] = sum(tmp) / float(len(tmp))
context['daily_min'] = min(tmp)
context['daily_max'] = max(tmp)
tmp = [players for time, players in items[-96*7:]]
tmp = [tmp.players for tmp in weekly_history]
context['weekly_average'] = sum(tmp) / float(len(tmp))
context['weekly_min'] = min(tmp)
context['weekly_max'] = max(tmp)
tmp = [players for time, players in items]
context['total_average'] = sum(tmp) / float(len(tmp))
context['total_min'] = min(tmp)
context['total_max'] = max(tmp)
return context

View File

@ -45,12 +45,6 @@
<th>{{weekly_min}}</th>
<th>{{weekly_max}}</th>
</tr>
<tr>
<th>Total</th>
<th>{{total_average|floatformat}}</th>
<th>{{total_min}}</th>
<th>{{total_max}}</th>
</tr>
</table>
<div id="chart"></div>
@ -62,8 +56,8 @@
$(function() {
var series = [
{# convert timestamp to ms, because javascript... #}
{% for timestamp, players in player_history %}
[{{timestamp}} * 1000, {{players}}],
{% for item in weekly_history %}
[{{item.created|date:'U'}} * 1000, {{item.players}}],
{% endfor %}
];