Merged branch history_model.
This commit is contained in:
commit
50b4bcc36e
@ -3,6 +3,5 @@ django
|
||||
django-debug-toolbar
|
||||
requests
|
||||
beautifulsoup4
|
||||
redis
|
||||
gunicorn
|
||||
fabric
|
||||
|
||||
@ -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()
|
||||
|
||||
28
src/gameservers/migrations/0011_serverhistory.py
Normal file
28
src/gameservers/migrations/0011_serverhistory.py
Normal 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,),
|
||||
),
|
||||
]
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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 %}
|
||||
];
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user