From a91e454eaa58ee312a707adbfc74de2ad979d5fe Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Thu, 29 Aug 2019 14:46:34 +0200
Subject: [PATCH] stats report alert
---
rowers/alerts.py | 9 ++++++-
rowers/models.py | 32 ++++++++++++++++++++---
rowers/templates/alert_stats.html | 29 ++++++++++++++++-----
rowers/templatetags/rowerfilters.py | 36 +++++++++++++++++++++++---
rowers/tests/testdata/testdata.csv.gz | Bin 12683 -> 12683 bytes
rowers/views/analysisviews.py | 3 ++-
6 files changed, 93 insertions(+), 16 deletions(-)
diff --git a/rowers/alerts.py b/rowers/alerts.py
index f33bd3f9..6e9fcd12 100644
--- a/rowers/alerts.py
+++ b/rowers/alerts.py
@@ -169,6 +169,10 @@ def alert_get_stats(alert,nperiod=0):
percentage = int(100.*nr_strokes_qualifying/nr_strokes)
else:
percentage = 0
+
+ median_q = df2[alert.measured.metric].median()
+ median = df[alert.measured.metric].median()
+ std = df[alert.measured.metric].std()
return {
'workouts':len(workouts),
@@ -177,7 +181,10 @@ def alert_get_stats(alert,nperiod=0):
'nr_strokes':nr_strokes,
'nr_strokes_qualifying':nr_strokes_qualifying,
'percentage': percentage,
- 'nperiod':nperiod,
+ 'nperiod':nperiod,
+ 'median':median,
+ 'median_q':median_q,
+ 'standard_dev':std,
}
# run alert report
diff --git a/rowers/models.py b/rowers/models.py
index f9d2ae9f..3028d064 100644
--- a/rowers/models.py
+++ b/rowers/models.py
@@ -881,9 +881,12 @@ class Rower(models.Model):
def save(self, *args, **kwargs):
try:
for group in self.coachinggroups.all():
- coach = Rower.objects.get(mycoachgroup=group)
- if coach.rowerplan == 'freecoach':
- self.coachinggroups.remove(group)
+ try:
+ coach = Rower.objects.get(mycoachgroup=group)
+ if coach.rowerplan == 'freecoach':
+ self.coachinggroups.remove(group)
+ except Rower.DoesNotExist:
+ pass
except ValueError:
pass
@@ -1093,6 +1096,11 @@ class Alert(models.Model):
return stri
+ def metricname(self):
+ metricdict = {key:value for (key,value) in parchoicesy1}
+
+ return metricdict[self.measured.metric]
+
def description(self):
metricdict = {key:value for (key,value) in parchoicesy1}
@@ -1115,6 +1123,24 @@ class Alert(models.Model):
return description
+ def shortdescription(self):
+ metricdict = {key:value for (key,value) in parchoicesy1}
+
+ if self.measured.condition == 'between':
+ description = '{value1} < {metric} < {value2}'.format(
+ metric = self.measured.metric,
+ value1 = self.measured.value1,
+ value2 = self.measured.value2,
+ )
+ else:
+ description = '{metric} {condition} {value1}'.format(
+ metric = self.measured.metric,
+ value1 = self.measured.value1,
+ condition = self.measured.condition
+ )
+
+ return description
+
class AlertEditForm(ModelForm):
class Meta:
diff --git a/rowers/templates/alert_stats.html b/rowers/templates/alert_stats.html
index fb950332..400a8dd3 100644
--- a/rowers/templates/alert_stats.html
+++ b/rowers/templates/alert_stats.html
@@ -1,5 +1,6 @@
{% extends "newbase.html" %}
{% load staticfiles %}
+{% load rowerfilters %}
{% block title %}Metric Alert{% endblock %}
@@ -13,19 +14,33 @@
-
+ -
+ {{ stats|lookuplong:'startdate' }} - {{ stats|lookuplong:'enddate' }}
+
+
-
-
Alert
+ {{ alert.name }}
{{ alert }}
{{ alert.description }}
This is a page under construction. Currently with minimal information
- {% for key, value in stats.items %}
- -
-
{{ key }}
- {{ value }}
+ -
+
Score
+
+ {{ stats|lookup:'percentage' }}%
+
+ -
+
Data set
+
+ {{ stats|lookup:'workouts' }} workouts
+ {{ stats|lookup:'nr_strokes_qualifying' }} strokes out of {{ stats|lookup:'nr_strokes' }}
+
+ -
+
Statistics
+
+ Median {{ alert.metricname }}: {{ stats|lookup:'median'|sigdig }}
+ Median {{ alert.metricname }}: {{ stats|lookup:'median_q'|sigdig }} ({{ alert.shortdescription }})
- {% endfor %}
diff --git a/rowers/templatetags/rowerfilters.py b/rowers/templatetags/rowerfilters.py
index e3ee8050..d7f9dd4a 100644
--- a/rowers/templatetags/rowerfilters.py
+++ b/rowers/templatetags/rowerfilters.py
@@ -4,6 +4,7 @@ from time import strftime
from django.utils import timezone
import dateutil.parser
import json
+import math
import datetime
import re
register = template.Library()
@@ -37,6 +38,25 @@ from django.template.defaultfilters import stringfilter
from six import string_types
+@register.filter
+def sigdig(value, digits = 3):
+ try:
+ order = int(math.floor(math.log10(math.fabs(value))))
+ except (ValueError,TypeError):
+ return value
+
+ # return integers as is
+ if value % 1 == 0:
+ return value
+
+ places = digits - order - 1
+ if places > 0:
+ fmtstr = "%%.%df" % (places)
+ else:
+ fmtstr = "%.0f"
+ return fmtstr % (round(value, places))
+
+
@register.filter(is_safe=True, needs_autoescape=True)
@stringfilter
def urlshorten(value, limit,autoescape=None):
@@ -278,18 +298,26 @@ def jsdict(dict,key):
s = dict.get(key)
return mark_safe(json.dumps(s))
+
+
@register.filter
def lookup(dict, key):
- s = dict.get(key)
-
+ try:
+ s = dict.get(key)
+ except KeyError:
+ return None
+
if isinstance(s,string_types) and len(s) > 22:
s = s[:22]
return s
@register.filter
def lookuplong(dict, key):
- s = dict.get(key)
-
+ try:
+ s = dict.get(key)
+ except KeyError:
+ return None
+
return s
@register.filter
diff --git a/rowers/tests/testdata/testdata.csv.gz b/rowers/tests/testdata/testdata.csv.gz
index 9941ccb444e906701f738010a5e1dc1051028b01..784c98feafe9f936f665b0d739d2e9d913540969 100644
GIT binary patch
delta 16
XcmeB9?oMWx@8;mxz9)Sndy63eGD`*J
delta 16
XcmeB9?oMWx@8;lWzmT?(y~Pj!F>VFO
diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py
index c8d68209..6bb2801c 100644
--- a/rowers/views/analysisviews.py
+++ b/rowers/views/analysisviews.py
@@ -4328,7 +4328,8 @@ def alerts_view(request,userid=0):
for alert in alerts:
stats.append(alert_get_stats(alert))
-
+
+
breadcrumbs = [
{
'url':'/rowers/analysis',