Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#355 #477

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open

#355 #477

Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions naucse/data/stats.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
entries:

- label: active_runs
text:
- '%d právě probíhající kurz'
- '%d právě probíhající kurzy'
- '%d právě probíhajících kurzů'

- label: all_runs
text:
- '%d kurz celkem'
- '%d kurzy celkem'
- '%d kurzů celkem'

- label: sessions_delivered
text:
- '%d lekci odučeno'
- '%d lekce odučeno'
- '%d lekcí odučeno'

- label: sessions_available
text:
- 'materiály pro %d lekci'
- 'materiály pro %d různé lekce'
- 'materiály pro %d různých lekcí'

- label: cheatsheets
text:
- '%d tahák'
- '%d taháky'
- '%d taháků'

- label: contributors
text:
- '%d autor'
- '%d autoři'
- '%d autorů'

- label: price
text: '%d Kč'
11 changes: 11 additions & 0 deletions naucse/static/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,14 @@ nav.header * {
background-color: #296e62;
outline-color: #3fb0ac;
}

.statlabels {
text-align: center;
}

.statlabel {
font-size: 1.5rem;
margin: 0.3rem;
color: #FFF;
background-color: #3b4f5a;
}
8 changes: 8 additions & 0 deletions naucse/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ <h1 class="display-3">Nauč se Python!</h1>
</div>
</div>

<div class="row">
<div class="statlabels">
{% for stat_label in stat_labels.entries %}
<span class="badge statlabel statlabel-{{stat_label.label}}">{{ stat_label|fill_label }}</span>
{% endfor %}
</div>
</div>

</div>
</div>

Expand Down
24 changes: 24 additions & 0 deletions naucse/utils/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,3 +232,27 @@ def get_edit_info(edit_path):
"page_name": get_edit_page_name(),
"url": edit_link(edit_path)
}

def czech_plural(text, n):
"""
Chooses the Czech plural form based on n.
This either gets and immediately returns a string,
or it gets a list of 3 strings:
* for 1 item
* for 2-4 items
* for the rest
Picks the right one and returns it.
Uses the more modern option where e.g. 21 is NOT pluralized as 1
http://prirucka.ujc.cas.cz/?id=792
"""
if isinstance(text, str):
return text

# we don't expect negative numbers here, but just to be sure
n = abs(n)

if n == 1:
return text[0]
if 1 < n < 5:
return text[1]
return text[2]
110 changes: 99 additions & 11 deletions naucse/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@
from naucse.utils.views import does_course_return_info
from naucse.utils.views import raise_errors_from_forks
from naucse.utils.views import page_content_cache_key, get_edit_info
from naucse.utils.views import czech_plural
from naucse.validation import DisallowedStyle, DisallowedElement, InvalidHTML

import yaml

# so it can be mocked
import naucse.utils.views

Expand All @@ -44,7 +47,6 @@

_cached_model = None


@LocalProxy
def model():
"""Return the root of the naucse model
Expand Down Expand Up @@ -97,10 +99,19 @@ def session_url(course, session, coverpage='front'):
coverpage=coverpage)


def load_stat_labels():
datafile = os.path.join(os.path.dirname(__file__), 'data/stats.yml')
with open(datafile) as fstr:
stat_labels = yaml.load(fstr)

return stat_labels


@app.route('/')
def index():
return render_template("index.html",
edit_info=get_edit_info(Path(".")))
edit_info=get_edit_info(Path(".")),
stat_labels=load_stat_labels())


@app.route('/runs/')
Expand Down Expand Up @@ -172,23 +183,28 @@ def runs(year=None, all=None):
edit_info=get_edit_info(model.runs_edit_path))


def safe_courses():
courses = []

for course in model.courses.values():
if not course.is_link():
if not course.is_meta:
courses.append(course)
elif naucse.utils.views.forks_enabled() and does_course_return_info(course):
courses.append(course)

return courses

@app.route('/courses/')
def courses():
# since even the basic info about the forked courses can be broken,
# we need to make sure the required info is provided.
# If ``RAISE_FORK_ERRORS`` is set, exceptions are raised here,
# otherwise the course is ignored completely.
safe_courses = []

for course in model.courses.values():
if not course.is_link():
if not course.is_meta:
safe_courses.append(course)
elif naucse.utils.views.forks_enabled() and does_course_return_info(course):
safe_courses.append(course)
courses = safe_courses()

return render_template("course_list.html",
courses=safe_courses,
courses=courses,
title="Seznam online kurzů Pythonu",
edit_info=get_edit_info(model.courses_edit_path))

Expand Down Expand Up @@ -920,3 +936,75 @@ def course_calendar_ics(course):
abort(404)

return Response(str(calendar), mimetype="text/calendar")

def active_runs():
today = datetime.date.today()

runs = (model.runs_from_year(today.year) +
model.runs_from_year(today.year - 1) +
model.runs_from_year(today.year - 2))
ongoing = [run for run in runs if
run.start_date <= today and run.end_date >= today]

return len(ongoing)

def all_runs():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Myslím, že je název tento fuknce lehce matoucí, myslím že něco jako count_all_runs by bylo lepší, přeci jen to nevrací kurzy, ale jejich počet...

all_years = list(model.safe_run_years.keys())

return sum([len(model.runs_from_year(year)) for year in all_years])

def sessions_delivered():
today = datetime.date.today()
all_years = list(model.safe_run_years.keys())

all_runs = []
for year in all_years:
all_runs.extend(model.runs_from_year(year))

all_sessions = []
for run in all_runs:
all_sessions.extend(list(run.sessions.values()))

return len([session for session in all_sessions if session.date < today])

def sessions_available():
uniq_sessions = {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tady by podle mě bylo lepší použít set, nepotřebujeme si ukládat tu lekci samotnou, stačí ten slug.

for course in safe_courses():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tohle spíš na @hroncok nebo @encukou: má být v této statistice jen počet kanonických sessions nebo i sessions co byly jen na kurzech? A nebylo by možná indikativnější/hezčí mít počet materiálů než lekcí, případně také mít tento počet?

for session in course.sessions.values():
uniq_sessions[session.slug] = session

return len(uniq_sessions)

def cheatsheets():
sheets = 0
for course in safe_courses():
for session in course.sessions.values():
for material in session.materials:
if (material.url_type == 'cheatsheet'):
sheets += 1

return sheets


# This could use some caching, but for now it's the simplest way
def basic_stat(name):
if name == 'active_runs':
return active_runs()
elif name == 'all_runs':
return all_runs()
elif name == 'sessions_delivered':
return sessions_delivered()
elif name == 'sessions_available':
return sessions_available()
elif name == 'cheatsheets':
return cheatsheets()
else: # contributors, price
return 0

@app.template_filter('fill_label')
def fill_label(label):
stat_number = basic_stat(label['label'])

formatstr = czech_plural(label['text'], stat_number)

return formatstr % stat_number