stats report alert
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{% extends "newbase.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load rowerfilters %}
|
||||
|
||||
{% block title %}Metric Alert{% endblock %}
|
||||
|
||||
@@ -13,19 +14,33 @@
|
||||
</p>
|
||||
|
||||
<ul class="main-content">
|
||||
|
||||
<li>
|
||||
{{ stats|lookuplong:'startdate' }} - {{ stats|lookuplong:'enddate' }}
|
||||
</li>
|
||||
|
||||
<li class="grid_4">
|
||||
<h2>Alert</h2>
|
||||
<h2>{{ alert.name }}</h2>
|
||||
<p>{{ alert }}</p>
|
||||
<p>{{ alert.description }}</p>
|
||||
<p>This is a page under construction. Currently with minimal information</p>
|
||||
</li>
|
||||
{% for key, value in stats.items %}
|
||||
<li>
|
||||
<h2>{{ key }}</h2>
|
||||
<p>{{ value }}</p>
|
||||
<li class="rounder">
|
||||
<h2>Score</h2>
|
||||
<hr>
|
||||
<h2>{{ stats|lookup:'percentage' }}%</h2>
|
||||
</li>
|
||||
<li class="rounder">
|
||||
<h2>Data set</h2>
|
||||
<hr>
|
||||
<p>{{ stats|lookup:'workouts' }} workouts</p>
|
||||
<p>{{ stats|lookup:'nr_strokes_qualifying' }} strokes out of {{ stats|lookup:'nr_strokes' }}</p>
|
||||
</li>
|
||||
<li class="rounder">
|
||||
<h2>Statistics</h2>
|
||||
<hr>
|
||||
<p>Median {{ alert.metricname }}: {{ stats|lookup:'median'|sigdig }}</p>
|
||||
<p>Median {{ alert.metricname }}: {{ stats|lookup:'median_q'|sigdig }} ({{ alert.shortdescription }})</p>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
BIN
rowers/tests/testdata/testdata.csv.gz
vendored
BIN
rowers/tests/testdata/testdata.csv.gz
vendored
Binary file not shown.
@@ -4328,7 +4328,8 @@ def alerts_view(request,userid=0):
|
||||
|
||||
for alert in alerts:
|
||||
stats.append(alert_get_stats(alert))
|
||||
|
||||
|
||||
|
||||
breadcrumbs = [
|
||||
{
|
||||
'url':'/rowers/analysis',
|
||||
|
||||
Reference in New Issue
Block a user