Private
Public Access
1
0

Merge branch 'release/v3.48'

This commit is contained in:
Sander Roosendaal
2017-07-29 12:49:55 +02:00
7 changed files with 117 additions and 5 deletions
+1 -1
View File
@@ -411,7 +411,7 @@ def save_workout_database(f2,r,dosmooth=True,workouttype='rower',
summary='', summary='',
makeprivate=False, makeprivate=False,
oarlength=2.89,inboard=0.88, oarlength=2.89,inboard=0.88,
consistencychecks=True): consistencychecks=False):
message = None message = None
powerperc = 100*np.array([r.pw_ut2, powerperc = 100*np.array([r.pw_ut2,
r.pw_ut1, r.pw_ut1,
+58 -1
View File
@@ -12,7 +12,7 @@ from bokeh.palettes import Dark2_8 as palette
import itertools import itertools
from bokeh.plotting import figure, ColumnDataSource, Figure,curdoc from bokeh.plotting import figure, ColumnDataSource, Figure,curdoc
from bokeh.models import CustomJS,Slider, TextInput,BoxAnnotation from bokeh.models import CustomJS,Slider, TextInput,BoxAnnotation
from bokeh.charts import Histogram,HeatMap,Area,BoxPlot from bokeh.charts import Histogram,HeatMap,Area,BoxPlot,Bar
from bokeh.resources import CDN,INLINE from bokeh.resources import CDN,INLINE
from bokeh.embed import components from bokeh.embed import components
from bokeh.layouts import layout,widgetbox from bokeh.layouts import layout,widgetbox
@@ -219,6 +219,63 @@ def interactive_boxchart(datadf,fieldname,extratitle=''):
return script,div return script,div
def interactive_activitychart(workouts,startdate,enddate):
if len(workouts) == 0:
return "",""
dates = []
types = []
durations = []
for w in workouts:
if w.privacy == 'visible':
dd = w.date.strftime('%m/%d')
du = w.duration.hour*60+w.duration.minute
dates.append(dd)
durations.append(du)
types.append(w.workouttype)
d = startdate
while d<=enddate:
dates.append(d.strftime('%m/%d'))
durations.append(0)
types.append('rower')
d += datetime.timedelta(days=1)
df = pd.DataFrame({
'date':dates,
'duration':durations,
'type':types,
})
p = Bar(df,'date',values='duration',title='Activity',
stack='type',
plot_width=350,
plot_height=250,
toolbar_location = None,
)
for legend in p.legend:
new_items = []
for legend_item in legend.items:
it = legend_item.label['value']
tot = df[df['type']==it].duration.sum()
if tot != 0:
new_items.append(legend_item)
legend.items = new_items
p.legend.location = "top_left"
p.legend.background_fill_alpha = 0.7
p.yaxis.axis_label = 'Minutes'
script, div = components(p)
return script,div
def interactive_forcecurve(theworkouts,workstrokesonly=False): def interactive_forcecurve(theworkouts,workstrokesonly=False):
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair' TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
+29
View File
@@ -135,6 +135,35 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
<div class="grid_4" id="interactiveplot">
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
<script async="true" type="text/javascript">
Bokeh.set_log_level("info");
</script>
{{ interactiveplot |safe }}
<script>
// Set things up to resize the plot on a window resize. You can play with
// the arguments of resize_width_height() to change the plot's behavior.
var plot_resize_setup = function () {
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
var plot = Bokeh.index[plotid];
var plotresizer = function() {
// arguments: use width, use height, maintain aspect ratio
plot.resize_width_height(true, true, true);
};
window.addEventListener('resize', plotresizer);
plotresizer();
};
window.addEventListener('load', plot_resize_setup);
</script>
<style>
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
html, body {height: 100%; margin:5px;}
</style>
{{ the_div |safe }}
</div>
<div class="grid_4" id="announcements"> <div class="grid_4" id="announcements">
{% if announcements %} {% if announcements %}
<h3>What's New?</h3> <h3>What's New?</h3>
+3 -1
View File
@@ -11,7 +11,7 @@
<p> <p>
Links to the cumulative statistics pages for your team's members Links to the cumulative statistics pages for your team's members
</p> </p>
<table width="70%" class="listtable shortpadded"> <table width="90%" class="listtable shortpadded">
<tbody> <tbody>
{% for u in theusers %} {% for u in theusers %}
<tr> <tr>
@@ -21,6 +21,8 @@
<td><a href="/rowers/histo/u/{{ u.id }}">Power Histogram</a></td> <td><a href="/rowers/histo/u/{{ u.id }}">Power Histogram</a></td>
<td><a href="/rowers/cumstats/u/{{ u.id }}">Stats</a></td> <td><a href="/rowers/cumstats/u/{{ u.id }}">Stats</a></td>
<td><a href="/rowers/user-boxplot-select/user/{{ u.id }}/">Box Chart</a></td> <td><a href="/rowers/user-boxplot-select/user/{{ u.id }}/">Box Chart</a></td>
<td><a href="/rowers/{{ u.id }}/otw-bests">OTW Ranking Pieces</a></td>
<td><a href="/rowers/user-multiflex-select/user/{{ u.id }}/">Trend Flex</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
+24
View File
@@ -4014,6 +4014,9 @@ def workouts_view(request,message='',successmessage='',
enddate = startdate enddate = startdate
startdate = s startdate = s
# start date for the small graph
activity_startdate = enddate-datetime.timedelta(days=15)
if teamid: if teamid:
try: try:
theteam = Team.objects.get(id=teamid) theteam = Team.objects.get(id=teamid)
@@ -4024,10 +4027,16 @@ def workouts_view(request,message='',successmessage='',
workouts = Workout.objects.filter(team=theteam, workouts = Workout.objects.filter(team=theteam,
startdatetime__gte=startdate, startdatetime__gte=startdate,
startdatetime__lte=enddate).order_by("-date", "-starttime") startdatetime__lte=enddate).order_by("-date", "-starttime")
g_workouts = Workout.objects.filter(team=theteam,
startdatetime__gte=activity_startdate,
startdatetime__lte=enddate).order_by("-date", "-starttime")
elif theteam.viewing == 'coachonly': elif theteam.viewing == 'coachonly':
workouts = Workout.objects.filter(team=theteam,user=r, workouts = Workout.objects.filter(team=theteam,user=r,
startdatetime__gte=startdate, startdatetime__gte=startdate,
startdatetime__lte=enddate).order_by("-date","-starttime") startdatetime__lte=enddate).order_by("-date","-starttime")
g_workouts = Workout.objects.filter(team=theteam,user=r,
startdatetime__gte=activity_startdate,
enddatetime__lte=enddate).order_by("-date","-starttime")
else: else:
@@ -4035,6 +4044,9 @@ def workouts_view(request,message='',successmessage='',
workouts = Workout.objects.filter(user=r, workouts = Workout.objects.filter(user=r,
startdatetime__gte=startdate, startdatetime__gte=startdate,
startdatetime__lte=enddate).order_by("-date", "-starttime") startdatetime__lte=enddate).order_by("-date", "-starttime")
g_workouts = Workout.objects.filter(user=r,
startdatetime__gte=activity_startdate,
startdatetime__lte=enddate).order_by("-date","-starttime")
query = request.GET.get('q') query = request.GET.get('q')
if query: if query:
@@ -4064,6 +4076,10 @@ def workouts_view(request,message='',successmessage='',
"-id" "-id"
) )
script,div = interactive_activitychart(g_workouts,
activity_startdate,
enddate)
messages.info(request,successmessage) messages.info(request,successmessage)
messages.error(request,message) messages.error(request,message)
@@ -4075,6 +4091,8 @@ def workouts_view(request,message='',successmessage='',
'announcements':announcements[0:4], 'announcements':announcements[0:4],
'team':theteam, 'team':theteam,
'teams':get_my_teams(request.user), 'teams':get_my_teams(request.user),
'interactiveplot':script,
'the_div':div,
}) })
@@ -7421,6 +7439,12 @@ def team_workout_upload_view(request,message="",
url = reverse(team_workout_upload_view) url = reverse(team_workout_upload_view)
response = HttpResponseRedirect(url) response = HttpResponseRedirect(url)
return response return response
elif id == -1:
message = 'The zip archive will be processed in the background. The files in the archive will only be uploaded without the extra actions. You will receive email when the workouts are ready.'
messages.info(request,message)
url = reverse(team_workout_upload_view)
response = HttpResponseRedirect(url)
return response
else: else:
successmessage = "The workout was added to the user's account" successmessage = "The workout was added to the user's account"
+1 -1
View File
@@ -139,7 +139,7 @@ DATABASES = {
'PASSWORD': CFG['db_password'], 'PASSWORD': CFG['db_password'],
'HOST': CFG['db_host'], 'HOST': CFG['db_host'],
'PORT': CFG['db_port'], 'PORT': CFG['db_port'],
}, },
'slave': { 'slave': {
'ENGINE': 'django.db.backends.sqlite3', 'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+1 -1
View File
@@ -15,7 +15,7 @@ DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.sqlite3', 'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
'HOST': 'localhost' 'HOST': 'localhost',
}, },
# 'TEST': { # 'TEST': {
# 'CHARSET': 'utf8', # 'CHARSET': 'utf8',