FxCup: average fans. other minor fixes (e.g. css)

This commit is contained in:
abuchanan 2010-05-27 11:22:26 -07:00 коммит произвёл Alex Buchanan
Родитель 5b57bc88a2
Коммит f0c542be09
8 изменённых файлов: 102 добавлений и 13 удалений

Просмотреть файл

@ -131,7 +131,7 @@
"model": "addons.persona",
"fields": {
"display_username": "My Persona",
"popularity": 0,
"popularity": 10,
"license": null,
"footer": "BCBG_Persona_footer2.png",
"movers": null,

26
apps/firefoxcup/cron.py Normal file
Просмотреть файл

@ -0,0 +1,26 @@
from datetime import datetime
import commonware.log
import cronjobs
from addons.models import Persona
from .models import Stats
from . import teams as teams_config
log = commonware.log.getLogger('z.cron')
@cronjobs.register
def firefoxcup_stats(teams=teams_config):
try:
latest = Stats.objects.latest()
delta = datetime.today() - latest.created
if delta.days < 1:
return
except Stats.DoesNotExist:
pass
ids = [t['persona_id'] for t in teams]
for p in Persona.objects.filter(persona_id__in=ids):
Stats.objects.create(persona_id=p.persona_id, popularity=p.popularity)

Просмотреть файл

@ -1,15 +1,23 @@
from django.db import models
from django.db.models import Avg
import amo.models
from amo.models import ModelBase, ManagerBase
class StatsManager(ManagerBase):
def avg_fans(self):
return self.values('persona_id').annotate(average=Avg('popularity'))
class FirefoxcupStat(amo.models.ModelBase):
class Stats(ModelBase):
"""
Keeps record of daily ADU counts for Firefox Cup personas.
Used to calculate 'Average Fans' over time of Firefox Cup campaign
"""
persona = models.ForeignKey('addons.Persona')
adu = models.IntegerField()
persona_id = models.PositiveIntegerField(db_index=True)
popularity = models.PositiveIntegerField()
class Meta:
db_table = 'firefoxcup_stats'
objects = StatsManager()
class Meta(ModelBase.Meta):
db_table = 'stats_firefoxcup'

Просмотреть файл

@ -4,7 +4,7 @@
{% block site_header %}{% endblock %}
{% block site_css %}
{{ css('firefoxcup') }}
{{ css('firefoxcup/f') }}
{% endblock %}
{% block main_content %}
@ -117,7 +117,7 @@
<th>{{ _('Flag') }}</th>
<th>{{ _('Country') }}</th>
<th>{{ _('Average Fans') }}</th>
<th>{{ _('Total Fans') }}</th>
<th>{{ _('Fans Today') }}</th>
</tr>
<tr><td colspan="5"></td></tr>
</thead>
@ -126,8 +126,8 @@
<tr>
<td class="persona"><img class="persona-preview" src="{{ team.flag }}" alt="{{ _('Flag') }}" data-browsertheme="{{ team.persona.json_data if team.persona }}" /></td>
<td>{{ team.name }}</td>
<td>###,###</td>
<td>{{ team.persona.popularity|numberfmt if team.persona else '###,###' }}</td>
<td>{{ team.avg_fans|numberfmt if team.avg_fans else 0 }}</td>
<td>{{ team.persona.popularity|numberfmt if team.persona else 0 }}</td>
</tr>
{% endfor %}
</tbody>

Просмотреть файл

@ -1,3 +1,4 @@
from datetime import date, timedelta
import json
from StringIO import StringIO
from mock import patch
@ -5,9 +6,12 @@ from nose.tools import eq_
from pyquery import PyQuery as pq
import test_utils
from twitter import _process_tweet, search, _search_query, _prepare_lang
from .models import Stats
from .cron import firefoxcup_stats
class TestFirefoxCup(test_utils.TestCase):
fixtures = ['addons/persona']
def twitter_results(self):
return StringIO(json.dumps({'results': [{'text': 'text'}]}))
@ -43,3 +47,41 @@ class TestFirefoxCup(test_utils.TestCase):
a = search([])
eq_(a, ['text'])
def test_cron_popularity_history(self):
teams = [{
'name': 'test',
'persona_id': 813,
}]
"""If no records exist, one is created"""
eq_(Stats.objects.count(), 0)
# @patch('firefoxcup.cron.teams_config') didn't work :( why?
firefoxcup_stats(teams=teams)
eq_(Stats.objects.count(), 1)
"""If a recent record exists (< 1 day), don't create a new one"""
firefoxcup_stats(teams=teams)
eq_(Stats.objects.count(), 1)
"""If latest record is older than 1 day, create a new record"""
latest = Stats.objects.latest()
latest.created = date.today() - timedelta(days=1)
latest.save()
firefoxcup_stats(teams=teams)
eq_(Stats.objects.count(), 2)
def test_stats_avg(self):
"""Stats manager should pull average popularity grouped by persona"""
Stats.objects.create(persona_id=5, popularity=6)
Stats.objects.create(persona_id=5, popularity=2)
Stats.objects.create(persona_id=6, popularity=5)
Stats.objects.create(persona_id=6, popularity=15)
avgs = {}
for row in Stats.objects.avg_fans():
avgs[row['persona_id']] = row['average']
eq_(avgs[5], 4)
eq_(avgs[6], 10)

Просмотреть файл

@ -1,9 +1,10 @@
import jingo
from twitter import search
from addons.models import Persona
from . import tags, email_enabled
from . import teams as teams_config
from .models import Stats
from .twitter import search
# Create your views here.
@ -22,6 +23,9 @@ def index(request):
for persona in Persona.objects.filter(persona_id__in=teams.keys()):
teams[persona.persona_id]['persona'] = persona
for record in Stats.objects.avg_fans():
teams[record['persona_id']]['avg_fans'] = record['avg_fans']
return jingo.render(request, 'firefoxcup/index.html', {
'tweets': tweets,
'teams': teams.values(),

Просмотреть файл

@ -0,0 +1,9 @@
CREATE TABLE `stats_firefoxcup` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
`persona_id` int(10) unsigned NOT NULL,
`popularity` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `firefoxcup_popularityhistory_persona_id` (`persona_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Просмотреть файл

@ -309,7 +309,7 @@ MINIFY_BUNDLES = {
'css/zamboni/discovery-pane.css',
),
# CSS files specific to /firefoxcup/
'firefoxcup': (
'firefoxcup/f': (
'css/firefoxcup/reset-fonts-grids.css',
'css/main.css',
'css/zamboni/zamboni.css',