Skip to content

Commit d834b32

Browse files
Add historical comparison charts to stats page (#289)
* Add historical comparison charts to stats page (implements #287) * Add 2025 proposals count as constant
1 parent f156637 commit d834b32

File tree

4 files changed

+236
-0
lines changed

4 files changed

+236
-0
lines changed

portal/common.py

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
CACHE_KEY_DONATION_TOWARDS_GOAL_PERCENT,
99
CACHE_KEY_DONATIONS_TOTAL_AMOUNT,
1010
CACHE_KEY_DONORS_COUNT,
11+
CACHE_KEY_HISTORICAL_COMPARISON,
1112
CACHE_KEY_SPONSORSHIP_BREAKDOWN,
1213
CACHE_KEY_SPONSORSHIP_COMMITTED,
1314
CACHE_KEY_SPONSORSHIP_COMMITTED_COUNT,
@@ -27,6 +28,8 @@
2728
CACHE_KEY_VOLUNTEER_SIGNUPS_COUNT,
2829
DONATION_GOAL_AMOUNT,
2930
DONATIONS_GOAL,
31+
HISTORICAL_STATS,
32+
PROPOSALS_2025_COUNT,
3033
SPONSORSHIP_GOAL,
3134
SPONSORSHIP_GOAL_AMOUNT,
3235
STATS_CACHE_TIMEOUT,
@@ -49,6 +52,7 @@ def get_stats_cached_values():
4952
stats_dict.update(get_sponsorships_stats_dict())
5053
stats_dict.update(get_donations_stats_dict())
5154
stats_dict.update(get_attendee_stats_dict())
55+
stats_dict[CACHE_KEY_HISTORICAL_COMPARISON] = get_historical_comparison_data()
5256
return stats_dict
5357

5458

@@ -610,3 +614,142 @@ def get_attendee_stats_dict():
610614
stats_dict = {}
611615
stats_dict[CACHE_KEY_ATTENDEE_COUNT] = get_attendee_count_cache()
612616
return stats_dict
617+
618+
619+
def get_historical_comparison_data():
620+
"""
621+
Returns historical comparison data for charts showing progress over the years.
622+
Combines hardcoded historical data with current year's data.
623+
"""
624+
historical_comparison = cache.get(CACHE_KEY_HISTORICAL_COMPARISON)
625+
if not historical_comparison:
626+
# Get current year data
627+
current_registrations = get_attendee_count_cache()
628+
current_sponsors = get_sponsorship_total_count_stats_cache()
629+
current_sponsorship_amount = get_sponsorship_committed_amount_stats_cache()
630+
current_donors = get_donors_count_cache()
631+
current_donation_amount = get_total_donations_amount_cache()
632+
633+
# Build comparison data structure
634+
historical_comparison = []
635+
636+
# Registrations comparison
637+
historical_comparison.append(
638+
{
639+
"title": "Registrations Over the Years",
640+
"columns": [["string", "Year"], ["number", "Registrations"]],
641+
"data": [
642+
["2023", HISTORICAL_STATS["2023"]["registrations"]],
643+
["2024", HISTORICAL_STATS["2024"]["registrations"]],
644+
["2025", current_registrations],
645+
],
646+
"chart_id": "registrations_comparison",
647+
"chart_type": "bar",
648+
}
649+
)
650+
651+
# Proposals comparison
652+
historical_comparison.append(
653+
{
654+
"title": "Proposals Over the Years",
655+
"columns": [["string", "Year"], ["number", "Proposals"]],
656+
"data": [
657+
["2023", HISTORICAL_STATS["2023"]["proposals"]],
658+
["2024", HISTORICAL_STATS["2024"]["proposals"]],
659+
["2025", PROPOSALS_2025_COUNT],
660+
],
661+
"chart_id": "proposals_comparison",
662+
"chart_type": "bar",
663+
}
664+
)
665+
666+
# Sponsors comparison
667+
historical_comparison.append(
668+
{
669+
"title": "Number of Sponsors Over the Years",
670+
"columns": [["string", "Year"], ["number", "Sponsors"]],
671+
"data": [
672+
["2023", HISTORICAL_STATS["2023"]["sponsors"]],
673+
["2024", HISTORICAL_STATS["2024"]["sponsors"]],
674+
["2025", current_sponsors],
675+
],
676+
"chart_id": "sponsors_comparison",
677+
"chart_type": "bar",
678+
}
679+
)
680+
681+
# Sponsorship amount comparison
682+
historical_comparison.append(
683+
{
684+
"title": "Sponsorship Amount Over the Years",
685+
"columns": [["string", "Year"], ["number", "Amount (USD)"]],
686+
"data": [
687+
["2023", HISTORICAL_STATS["2023"]["sponsorship_amount"]],
688+
["2024", HISTORICAL_STATS["2024"]["sponsorship_amount"]],
689+
["2025", current_sponsorship_amount],
690+
],
691+
"chart_id": "sponsorship_amount_comparison",
692+
"chart_type": "bar",
693+
}
694+
)
695+
696+
# Individual donations comparison
697+
historical_comparison.append(
698+
{
699+
"title": "Number of Individual Donors Over the Years",
700+
"columns": [["string", "Year"], ["number", "Donors"]],
701+
"data": [
702+
["2023", HISTORICAL_STATS["2023"]["donors"]],
703+
["2024", HISTORICAL_STATS["2024"]["donors"]],
704+
["2025", current_donors],
705+
],
706+
"chart_id": "donors_comparison",
707+
"chart_type": "bar",
708+
}
709+
)
710+
711+
# Donation amount comparison
712+
historical_comparison.append(
713+
{
714+
"title": "Donation Amount Over the Years",
715+
"columns": [["string", "Year"], ["number", "Amount (USD)"]],
716+
"data": [
717+
["2023", HISTORICAL_STATS["2023"]["donation_amount"]],
718+
["2024", HISTORICAL_STATS["2024"]["donation_amount"]],
719+
["2025", current_donation_amount],
720+
],
721+
"chart_id": "donation_amount_comparison",
722+
"chart_type": "bar",
723+
}
724+
)
725+
726+
# Total proceeds comparison
727+
historical_comparison.append(
728+
{
729+
"title": "Total Proceeds Over the Years",
730+
"columns": [["string", "Year"], ["number", "Amount (USD)"]],
731+
"data": [
732+
[
733+
"2023",
734+
HISTORICAL_STATS["2023"]["sponsorship_amount"]
735+
+ HISTORICAL_STATS["2023"]["donation_amount"],
736+
],
737+
[
738+
"2024",
739+
HISTORICAL_STATS["2024"]["sponsorship_amount"]
740+
+ HISTORICAL_STATS["2024"]["donation_amount"],
741+
],
742+
["2025", current_sponsorship_amount + current_donation_amount],
743+
],
744+
"chart_id": "proceeds_comparison",
745+
"chart_type": "bar",
746+
}
747+
)
748+
749+
cache.set(
750+
CACHE_KEY_HISTORICAL_COMPARISON,
751+
historical_comparison,
752+
STATS_CACHE_TIMEOUT,
753+
)
754+
755+
return historical_comparison

portal/constants.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,31 @@
3434

3535
CACHE_KEY_ATTENDEE_COUNT = "attendee_count"
3636

37+
# Historical data for comparison charts
38+
CACHE_KEY_HISTORICAL_COMPARISON = "historical_comparison"
39+
40+
# Historical data from past PyLadiesCon events
41+
# Data source: https://conference.pyladies.com/2024-pyladiescon-ends/
42+
HISTORICAL_STATS = {
43+
"2023": {
44+
"registrations": 600,
45+
"proposals": 164,
46+
"sponsors": 8,
47+
"sponsorship_amount": 10500,
48+
"donors": 58,
49+
"donation_amount": 650,
50+
},
51+
"2024": {
52+
"registrations": 732,
53+
"proposals": 192,
54+
"sponsors": 11,
55+
"sponsorship_amount": 10000,
56+
"donors": 105,
57+
"donation_amount": 1520,
58+
},
59+
}
60+
61+
# Current year proposals count (not stored in database)
62+
PROPOSALS_2025_COUNT = 194
63+
3764
BASE_PRETIX_URL = "https://pretix.eu/api/v1/"
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{% comment %}
2+
Historical comparison charts for PyLadiesCon stats across years
3+
Uses Google Charts to display bar charts comparing metrics from 2023, 2024, and 2025
4+
{% endcomment %}
5+
{% for comparison in stats.historical_comparison %}
6+
var data_{{ comparison.chart_id }} = new google.visualization.DataTable();
7+
{% for column in comparison.columns %}
8+
data_{{ comparison.chart_id }}.addColumn('{{ column.0 }}', '{{ column.1 }}');
9+
{% endfor %}
10+
data_{{ comparison.chart_id }}.addRows([
11+
{% for row in comparison.data %}
12+
['{{ row.0 }}', {{ row.1 }}]
13+
{% if not forloop.last %}
14+
,
15+
{% endif %}
16+
{% endfor %}
17+
]);
18+
var options_{{ comparison.chart_id }} = {
19+
title: '{{ comparison.title }}',
20+
chartArea: { width: '70%' },
21+
hAxis: {
22+
title: 'Year',
23+
minValue: 0
24+
},
25+
vAxis: {
26+
title: '{{ comparison.columns.1.1 }}'
27+
},
28+
colors: ['#7C5BC8'],
29+
legend: { position: 'none' },
30+
animation: {
31+
startup: true,
32+
duration: 1000,
33+
easing: 'out'
34+
}
35+
};
36+
var chart_{{ comparison.chart_id }} = new google.visualization.ColumnChart(
37+
document.getElementById('{{ comparison.chart_id }}')
38+
);
39+
chart_{{ comparison.chart_id }}.draw(data_{{ comparison.chart_id }}, options_{{ comparison.chart_id }});
40+
{% endfor %}

templates/portal/stats.html

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,14 @@
1111
function drawChart() {
1212
{% include "sponsorship/sponsorship_charts.html" %}
1313
{% include "volunteer/volunteer_charts.html" %}
14+
{% include "portal/historical_comparison_charts.html" %}
1415
}
1516
</script>
17+
<style>
18+
.chart-container {
19+
height: 300px;
20+
}
21+
</style>
1622
{% endblock extra_head %}
1723
{% block body %}
1824
{% endblock body %}
@@ -53,5 +59,25 @@ <h3 class="mb-2">
5359
</div>
5460
</div>
5561
{% include "volunteer/volunteer_stats.html" %}
62+
<!-- Historical Comparison Section -->
63+
<div class="row mt-5">
64+
<div class="col-12">
65+
<h3 class="pb-2 border-bottom">
66+
<i class="bi bi-graph-up"></i> Historical Comparison
67+
</h3>
68+
</div>
69+
</div>
70+
<div class="row g-4 mt-2">
71+
{% for comparison in stats.historical_comparison %}
72+
<div class="col-md-6">
73+
<div class="card h-100">
74+
<div class="card-body">
75+
<div id="{{ comparison.chart_id }}" class="chart-container">
76+
</div>
77+
</div>
78+
</div>
79+
</div>
80+
{% endfor %}
81+
</div>
5682
</div>
5783
{% endblock content %}

0 commit comments

Comments
 (0)