Skip to content
This repository was archived by the owner on Sep 19, 2018. It is now read-only.

Commit ebf7ee8

Browse files
committed
Merge pull request #343 from ialja/scoreboard
Added scoreboard that ranks countries based on number of events
2 parents a7112dd + e3f6013 commit ebf7ee8

File tree

10 files changed

+153
-2
lines changed

10 files changed

+153
-2
lines changed

codeweekeu/settings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@
209209
'social.apps.django_app.default',
210210
# django-countries country listing
211211
'django_countries',
212+
# additional info about countries
213+
'countries_plus',
212214
# avatar handling
213215
'avatar',
214216
# support for tags

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ django-appconf==0.6
1111
django-avatar==2.0
1212
django-compressor==1.4
1313
django-countries==2.0c1
14+
django-countries-plus==0.3
1415
django-debug-toolbar==1.0.1
1516
django-endless-pagination==2.0
1617
django-geoposition==0.1.5

server-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ django-appconf==0.6
1111
django-avatar==2.0
1212
django-compressor==1.4
1313
django-countries==2.0c1
14+
django-countries-plus==0.3
1415
django-debug-toolbar==1.0.1
1516
django-endless-pagination==2.0
1617
django-geoposition==0.1.5

static/scss/_768up.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@
1717
background-color: $whitesmoke;
1818
color: $black;
1919
padding-left: 25px;
20-
}
20+
}
21+

static/scss/_base.scss

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,3 +534,25 @@ LIST EVENTS STYLES
534534
}
535535
}
536536

537+
/*********************
538+
SCOREBOARD STYLES
539+
*********************/
540+
541+
.country {
542+
border-bottom:1px solid #ccc;
543+
border:1px solid #ccc;
544+
.country-name {
545+
font-weight: 800;
546+
font-size: 1.2em;
547+
}
548+
.event-number {
549+
font-weight: 800;
550+
font-size: 1.5em;
551+
}
552+
background-color: #F5F5F5;
553+
}
554+
555+
.highlighted {
556+
background-color: #F0F8FF;
557+
}
558+

web/processors/event.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from django.contrib.gis.geoip import GeoIP
66
from api.models import Event
77
from django_countries import countries
8+
from countries_plus.models import Country
89

910
from web.processors import media
1011
from mailer.event_report_mailer import send_email_to_country_ambassadors
@@ -120,6 +121,34 @@ def get_country(country_code, user_ip):
120121
return country
121122

122123

124+
def count_approved_events_for_country(past=True):
125+
"""
126+
Count the number of approved events and score for each country
127+
"""
128+
129+
all_events = Event.objects.filter(status='APPROVED')
130+
131+
country_count = []
132+
133+
# not including the first two fake countries in the list
134+
for country in list(countries)[2:]:
135+
country_code = country[0]
136+
country_name = country[1]
137+
number_of_events = all_events.filter(country=country_code).count()
138+
population = Country.objects.get(iso=country_code).population
139+
country_score = 0
140+
if number_of_events > 0 and population > 0 and population != "":
141+
country_score = 1. * number_of_events / population
142+
country_entry = {'country_code': country_code,
143+
'country_name': country_name,
144+
'events': number_of_events,
145+
'score': country_score}
146+
country_count.append(country_entry)
147+
148+
sorted_count = sorted(country_count, key=lambda k: k['score'], reverse=True)
149+
return sorted_count
150+
151+
123152
def change_event_status(event_id):
124153
event = Event.objects.get(pk=event_id)
125154

web/templates/pages/scoreboard.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{% extends 'base.html' %}
2+
3+
{% block title %}- Events Scoreboard{% endblock title %}
4+
5+
{% block content %}
6+
<div class="container">
7+
<h1>#codeEU Events Scoreboard</h1>
8+
<p>Which countries in Europe are buzzing with coding activity? The scoreboard is sorted by the number of listed coding events per population, so don't be surprised to see some of the smaller countries higher up on the list!</p>
9+
{% for country in counts %}
10+
<div class="col-md-6 country{% if forloop.counter < 11 %} highlighted{% endif %}">
11+
<img src="/static/flags/{{ country.country_code|lower }}.png" alt="{{ country.country_name }}" />
12+
<span class="icon-flag">
13+
<span class="country-name">{{ country.country_name }}</span> is participating with
14+
<span class="event-number"><a href="{% url 'web.search_events' %}?country_code={{ country.country_code }}&amp;past=yes">{{ country.events }}</span> event{% if country.events != 1 %}s{% endif %}</a>
15+
</span>
16+
</div>
17+
{% endfor %}
18+
</div>
19+
{% endblock content %}

web/tests/test_events_processors.py

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from api.processors import get_approved_events
1919
from api.processors import get_next_or_previous
2020
from api.processors import get_nearby_events
21-
21+
from web.processors.event import count_approved_events_for_country
2222

2323
class EventTestCase(TestCase):
2424
def get_user(self):
@@ -345,3 +345,66 @@ def test_create_event_in_moldova(admin_user, db):
345345

346346
assert "MD" == test_event.country.code
347347

348+
@pytest.mark.django_db
349+
def test_scoreboard_counter(admin_user, db):
350+
351+
initial_counter = count_approved_events_for_country()
352+
353+
counted_events_before = 0
354+
355+
for country in initial_counter:
356+
if country['country_code'] == 'SI':
357+
counted_events_before = country['events']
358+
359+
# Adding one approved and one pending event in same country
360+
# the count for events for the country should increase by 1
361+
event_data = {
362+
'audience': [3],
363+
'theme': [1,2],
364+
'country': u'SI',
365+
'description': u'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\r\ntempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\r\nquis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\r\nconsequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\r\ncillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non\r\nproident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
366+
'location': u'Ljubljana, Slovenia',
367+
'organizer': u'testko',
368+
"creator": admin_user,
369+
'start_date': datetime.datetime.now(),
370+
'end_date': datetime.datetime.now() + datetime.timedelta(days=3, hours=3),
371+
'title': u'Test Approved Event',
372+
'status':"APPROVED",
373+
}
374+
375+
test_approved_event = create_or_update_event(event_id=None, **event_data)
376+
377+
event_data = {
378+
'audience': [3],
379+
'theme': [1,2],
380+
'country': u'SI',
381+
'description': u'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\r\ntempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\r\nquis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\r\nconsequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\r\ncillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non\r\nproident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
382+
'location': u'Ljubljana, Slovenia',
383+
'organizer': u'testko',
384+
"creator": admin_user,
385+
'start_date': datetime.datetime.now(),
386+
'end_date': datetime.datetime.now() + datetime.timedelta(days=3, hours=3),
387+
'title': u'Test Pending Event',
388+
'status':"PENDING",
389+
}
390+
391+
test_pending_event = create_or_update_event(event_id=None, **event_data)
392+
393+
new_counter = count_approved_events_for_country()
394+
395+
counted_events_after = 0
396+
397+
for country in new_counter:
398+
if country['country_code'] == 'SI':
399+
counted_events_after = country['events']
400+
401+
# An extra check with a direct DB query
402+
counted_events_query = Event.objects.filter(status='APPROVED').filter(country='SI').count()
403+
404+
assert counted_events_after == counted_events_before + 1
405+
assert counted_events_after == counted_events_query
406+
407+
test_approved_event.delete()
408+
test_pending_event.delete()
409+
410+

web/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
url(r'^about/$', TemplateView.as_view(template_name="pages/about.html"), name='web.about'),
2121
url(r'^login/$', 'users.login', name='web.login'),
2222
url(r'^ambassadors/$', 'users.ambassadors', name='web.ambassadors'),
23+
url(r'^scoreboard/$', 'events.scoreboard', name='web.scoreboard'),
2324
url(r'^change_status/(?P<event_id>\d+)/$', 'events.change_status', name='web.change_status'),
2425
url(r'^reject_status/(?P<event_id>\d+)/$', 'events.reject_status', name='web.reject_status'),
2526
# Note: do not place any url after this one of it will not work

web/views/events.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from web.processors.event import list_countries
3131
from web.processors.event import get_country
3232
from web.processors.event import get_country_from_user_ip
33+
from web.processors.event import count_approved_events_for_country
3334
from web.processors.media import process_image
3435
from web.processors.media import ImageSizeTooLargeException
3536
from web.processors.media import UploadImageError
@@ -309,6 +310,17 @@ def search_events(request):
309310
},
310311
context_instance=RequestContext(request))
311312

313+
def scoreboard(request):
314+
template = 'pages/scoreboard.html'
315+
316+
counts = count_approved_events_for_country()
317+
318+
return render_to_response(
319+
template, {
320+
'counts': counts,
321+
},
322+
context_instance=RequestContext(request))
323+
312324

313325
@login_required
314326
@can_moderate_event

0 commit comments

Comments
 (0)