FxCup: average fans. other minor fixes (e.g. css)
This commit is contained in:
Родитель
5b57bc88a2
Коммит
f0c542be09
|
@ -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,
|
||||
|
|
|
@ -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',
|
||||
|
|
Загрузка…
Ссылка в новой задаче