Merge branch 'release/v12.39'
This commit is contained in:
@@ -267,9 +267,10 @@ def interactive_workouttype_piechart(workouts):
|
|||||||
|
|
||||||
for w in workouts:
|
for w in workouts:
|
||||||
try:
|
try:
|
||||||
label = mytypes.workouttypes_ordered[w.workouttype]
|
# label = mytypes.workouttypes_ordered[w.workouttype]
|
||||||
|
label = w.workouttype
|
||||||
except KeyError:
|
except KeyError:
|
||||||
labels = w.workouttype
|
label = w.workouttype
|
||||||
try:
|
try:
|
||||||
datadict[label] += 60*(60*w.duration.hour+w.duration.minute)+w.duration.second
|
datadict[label] += 60*(60*w.duration.hour+w.duration.minute)+w.duration.second
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@@ -277,13 +278,15 @@ def interactive_workouttype_piechart(workouts):
|
|||||||
|
|
||||||
data = pd.Series(datadict).reset_index(name='value').rename(columns={'index':'type'})
|
data = pd.Series(datadict).reset_index(name='value').rename(columns={'index':'type'})
|
||||||
data['angle'] = data['value']/data['value'].sum() * 2*pi
|
data['angle'] = data['value']/data['value'].sum() * 2*pi
|
||||||
if len(datadict)>2:
|
|
||||||
data['color'] = Category10[len(datadict)]
|
|
||||||
elif len(datadict)==2:
|
|
||||||
data['color'] = ['orange','lightblue']
|
|
||||||
else:
|
data = pd.DataFrame(data)
|
||||||
data['color'] = ['lightblue']
|
data['color'] = data['type'].apply(lambda x:mytypes.color_map[x])
|
||||||
data['totaltime'] = pd.Series([pretty_timedelta(v) for v in data['value']])
|
data['totaltime'] = data['value'].apply(lambda x:pretty_timedelta(x))
|
||||||
|
data['type'] = data['type'].apply(lambda x:mytypes.workouttypes_ordered[x])
|
||||||
|
|
||||||
|
|
||||||
p = figure(plot_height=350, title="Types", toolbar_location=None,
|
p = figure(plot_height=350, title="Types", toolbar_location=None,
|
||||||
tools="hover,save", tooltips="@type: @totaltime", x_range=(-0.5, 1.0))
|
tools="hover,save", tooltips="@type: @totaltime", x_range=(-0.5, 1.0))
|
||||||
@@ -410,6 +413,7 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type',toolbar_lo
|
|||||||
durations = []
|
durations = []
|
||||||
links = []
|
links = []
|
||||||
|
|
||||||
|
|
||||||
rowersinitials = {}
|
rowersinitials = {}
|
||||||
seen = ['seen']
|
seen = ['seen']
|
||||||
idseen = []
|
idseen = []
|
||||||
@@ -456,6 +460,7 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type',toolbar_lo
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
types.append(w.workouttype)
|
types.append(w.workouttype)
|
||||||
try:
|
try:
|
||||||
rowers.append(rowersinitials[w.user.id])
|
rowers.append(rowersinitials[w.user.id])
|
||||||
@@ -486,6 +491,7 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type',toolbar_lo
|
|||||||
durations.append(0)
|
durations.append(0)
|
||||||
links.append('')
|
links.append('')
|
||||||
types.append('rower')
|
types.append('rower')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
rowers.append(rowers[0])
|
rowers.append(rowers[0])
|
||||||
except IndexError:
|
except IndexError:
|
||||||
@@ -506,24 +512,24 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type',toolbar_lo
|
|||||||
'link':links,
|
'link':links,
|
||||||
}
|
}
|
||||||
|
|
||||||
types_ind = list(set(types))
|
dim_expr = hv.dim('type').categorize(mytypes.color_map)
|
||||||
|
|
||||||
|
|
||||||
df = pd.DataFrame(thedict)
|
df = pd.DataFrame(thedict)
|
||||||
|
|
||||||
source = ColumnDataSource(df)
|
source = ColumnDataSource(df)
|
||||||
|
|
||||||
df.sort_values('date_sorting',inplace=True)
|
df.sort_values('date_sorting',inplace=True)
|
||||||
|
#clrs = hv.Cycle(df['colors'].values)
|
||||||
|
|
||||||
hv.extension('bokeh')
|
hv.extension('bokeh')
|
||||||
|
|
||||||
if stack == 'type':
|
if stack == 'type':
|
||||||
table = hv.Table(df,[('date','Date'),('type','Workout Type')],[('duration','Minutes'),('link','link')])
|
table = hv.Table(df,[('date','Date'),('type','Workout Type')],[('duration','Minutes'),('link','link')])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
table = hv.Table(df,[('date','Date'),('rower','Rower')],[('duration','Minutes'),('link','link')])
|
table = hv.Table(df,[('date','Date'),('rower','Rower')],[('duration','Minutes'),('link','link')])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bars=table.to.bars(['date',stack],['duration'])
|
bars=table.to.bars(['date',stack],['duration'])
|
||||||
bars.opts(
|
bars.opts(
|
||||||
opts.Bars(color=hv.Cycle('Category10'), show_legend=True, stacked=True,
|
opts.Bars(color=hv.Cycle('Category10'), show_legend=True, stacked=True,
|
||||||
@@ -548,6 +554,168 @@ def interactive_activitychart(workouts,startdate,enddate,stack='type',toolbar_lo
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
callback = CustomJS(args={'links':df.link}, code="""
|
||||||
|
var index = cb_data.source.selected['1d'].indices[0];
|
||||||
|
console.log(links);
|
||||||
|
console.log(index);
|
||||||
|
console.log(links[index]);
|
||||||
|
window.location.href = links[index]
|
||||||
|
""")
|
||||||
|
|
||||||
|
taptool.callback = callback
|
||||||
|
|
||||||
|
|
||||||
|
script,div = components(p)
|
||||||
|
return script,div
|
||||||
|
|
||||||
|
def interactive_activitychart2(workouts,startdate,enddate,stack='type',toolbar_location=None):
|
||||||
|
|
||||||
|
dates = []
|
||||||
|
dates_sorting = []
|
||||||
|
types = []
|
||||||
|
rowers = []
|
||||||
|
durations = []
|
||||||
|
links = []
|
||||||
|
|
||||||
|
|
||||||
|
rowersinitials = {}
|
||||||
|
seen = ['seen']
|
||||||
|
idseen = []
|
||||||
|
|
||||||
|
startdate = datetime.datetime(year=startdate.year,month=startdate.month,day=startdate.day)
|
||||||
|
enddate = datetime.datetime(year=enddate.year,month=enddate.month,day=enddate.day)
|
||||||
|
|
||||||
|
duration = enddate-startdate
|
||||||
|
|
||||||
|
totaldays = duration.total_seconds()/(24*3600)
|
||||||
|
|
||||||
|
|
||||||
|
for w in workouts:
|
||||||
|
aantal=1
|
||||||
|
initials = w.user.user.first_name[0:aantal]+w.user.user.last_name[0:aantal]
|
||||||
|
if w.user.id not in idseen:
|
||||||
|
while initials in seen:
|
||||||
|
aantal += 1
|
||||||
|
initials = w.user.user.first_name[0:aantal]+w.user.user.last_name[0:aantal]
|
||||||
|
|
||||||
|
seen.append(initials)
|
||||||
|
idseen.append(w.user.id)
|
||||||
|
rowersinitials[w.user.id] = initials
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for w in workouts:
|
||||||
|
dd = w.date.strftime('%m/%d')
|
||||||
|
dd2 = w.date.strftime('%Y/%m/%d')
|
||||||
|
dd3 = w.date.strftime('%Y/%m')
|
||||||
|
du = w.duration.hour*60+w.duration.minute
|
||||||
|
|
||||||
|
if totaldays<30:
|
||||||
|
dates.append(dd)
|
||||||
|
dates_sorting.append(dd2)
|
||||||
|
else:
|
||||||
|
dates.append(dd3)
|
||||||
|
dates_sorting.append(dd3)
|
||||||
|
durations.append(du)
|
||||||
|
links.append(
|
||||||
|
"{siteurl}/rowers/workout/{code}/".format(
|
||||||
|
siteurl = settings.SITE_URL,
|
||||||
|
code = encoder.encode_hex(w.id)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
types.append(w.workouttype)
|
||||||
|
try:
|
||||||
|
rowers.append(rowersinitials[w.user.id])
|
||||||
|
except IndexError:
|
||||||
|
rowers.append(str(w.user))
|
||||||
|
|
||||||
|
try:
|
||||||
|
d = utc.localize(startdate)
|
||||||
|
except (ValueError,AttributeError):
|
||||||
|
d = startdate
|
||||||
|
|
||||||
|
try:
|
||||||
|
enddate = utc.localize(enddate)
|
||||||
|
except (ValueError,AttributeError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# add dates with no activity
|
||||||
|
while d<=enddate:
|
||||||
|
dd = d.strftime('%d')
|
||||||
|
|
||||||
|
|
||||||
|
if totaldays<30:
|
||||||
|
dates.append(d.strftime('%m/%d'))
|
||||||
|
dates_sorting.append(d.strftime('%Y/%m/%d'))
|
||||||
|
else:
|
||||||
|
dates.append(d.strftime('%Y/%m'))
|
||||||
|
dates_sorting.append(d.strftime('%Y/%m'))
|
||||||
|
durations.append(0)
|
||||||
|
links.append('')
|
||||||
|
types.append('rower')
|
||||||
|
|
||||||
|
try:
|
||||||
|
rowers.append(rowers[0])
|
||||||
|
except IndexError:
|
||||||
|
try:
|
||||||
|
rowers.append(str(workouts[0].user))
|
||||||
|
except IndexError:
|
||||||
|
rowers.append(' ')
|
||||||
|
|
||||||
|
d += datetime.timedelta(days=1)
|
||||||
|
|
||||||
|
|
||||||
|
thedict = {
|
||||||
|
'date':dates,
|
||||||
|
'date_sorting':dates_sorting,
|
||||||
|
'duration':durations,
|
||||||
|
'type':types,
|
||||||
|
'rower':rowers,
|
||||||
|
'link':links,
|
||||||
|
}
|
||||||
|
|
||||||
|
dim_expr = hv.dim('type').categorize(mytypes.color_map)
|
||||||
|
|
||||||
|
df = pd.DataFrame(thedict)
|
||||||
|
|
||||||
|
|
||||||
|
source = ColumnDataSource(df)
|
||||||
|
|
||||||
|
df.sort_values('date_sorting',inplace=True)
|
||||||
|
#clrs = hv.Cycle(df['colors'].values)
|
||||||
|
|
||||||
|
hv.extension('bokeh')
|
||||||
|
|
||||||
|
|
||||||
|
table = hv.Table(df,[('date','Date'),('type','Workout Type')],[('duration','Minutes'),('link','link')])
|
||||||
|
|
||||||
|
|
||||||
|
bars=table.to.bars(['date',stack],['duration'])
|
||||||
|
bars.opts(
|
||||||
|
opts.Bars(color=dim_expr, show_legend=True, stacked=True,
|
||||||
|
tools=['tap','hover'], width=550, xrotation=45,padding=(0,(0,.1)),
|
||||||
|
legend_position='bottom',show_frame=True))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
p = hv.render(bars)
|
||||||
|
|
||||||
|
p.title.text = 'Activity {d1} to {d2}'.format(
|
||||||
|
d1 = startdate.strftime("%Y-%m-%d"),
|
||||||
|
d2 = enddate.strftime("%Y-%m-%d"),
|
||||||
|
)
|
||||||
|
|
||||||
|
p.plot_width=550
|
||||||
|
p.plot_height=350
|
||||||
|
p.toolbar_location = toolbar_location
|
||||||
|
p.sizing_mode = 'scale_width'
|
||||||
|
url = "http://rowsandall.com/rowers/workout/@duration/"
|
||||||
|
taptool = p.select(type=TapTool)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
callback = CustomJS(args={'links':df.link}, code="""
|
callback = CustomJS(args={'links':df.link}, code="""
|
||||||
var index = cb_data.source.selected['1d'].indices[0];
|
var index = cb_data.source.selected['1d'].indices[0];
|
||||||
console.log(links);
|
console.log(links);
|
||||||
|
|||||||
@@ -270,6 +270,12 @@ rowtypes = (
|
|||||||
|
|
||||||
checktypes = [i[0] for i in workouttypes]
|
checktypes = [i[0] for i in workouttypes]
|
||||||
|
|
||||||
|
from bokeh.palettes import Category10
|
||||||
|
|
||||||
|
|
||||||
|
colors = Category10[9]+Category10[9]+Category10[9]+Category10[9]
|
||||||
|
color_map = {checktypes[i]:colors[i] for i in range(len(checktypes))}
|
||||||
|
|
||||||
workoutsources = (
|
workoutsources = (
|
||||||
('strava','strava'),
|
('strava','strava'),
|
||||||
('concept2','concept2'),
|
('concept2','concept2'),
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<h1>History for {{ rower.user.first_name }} {{ rower.user.last_name }} from {{ startdate|date:"c" }} to {{ enddate|date:"c"}}</h1>
|
<h1>History for {{ rower.user.first_name }} {{ rower.user.last_name }}</h1>
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<a href="/rowers/history/?enddate={{ today|date:"Y-m-d" }}&startdate={{ lastseven|date:"Y-m-d" }}&workouttype={{ workouttype }}">Past 7 days</a>
|
<a href="/rowers/history/?enddate={{ today|date:"Y-m-d" }}&startdate={{ lastseven|date:"Y-m-d" }}&workouttype={{ workouttype }}">Past 7 days</a>
|
||||||
|
|||||||
@@ -4783,7 +4783,6 @@ def history_view(request,userid=0):
|
|||||||
if firstmay>today:
|
if firstmay>today:
|
||||||
firstmay = datetime.datetime(year=today.year-1,month=5,day=1)
|
firstmay = datetime.datetime(year=today.year-1,month=5,day=1)
|
||||||
|
|
||||||
print(sstartdate,senddate,'history')
|
|
||||||
|
|
||||||
return render(request,'history.html',
|
return render(request,'history.html',
|
||||||
{
|
{
|
||||||
@@ -4923,7 +4922,7 @@ def history_view_data(request,userid=0):
|
|||||||
totalsdict['nrworkouts'] = g_workouts.count()
|
totalsdict['nrworkouts'] = g_workouts.count()
|
||||||
|
|
||||||
# activity chart
|
# activity chart
|
||||||
activity_script, activity_div = interactive_activitychart(g_workouts,startdate,enddate)
|
activity_script, activity_div = interactive_activitychart2(g_workouts,startdate,enddate)
|
||||||
|
|
||||||
# interactive hr pie chart
|
# interactive hr pie chart
|
||||||
if typeselect == 'All':
|
if typeselect == 'All':
|
||||||
|
|||||||
Reference in New Issue
Block a user