VideoAnalysis object urls
This commit is contained in:
@@ -96,7 +96,8 @@ from rowers.models import (
|
||||
TrainingMesoCycleForm, TrainingMicroCycleForm,
|
||||
RaceLogo,RowerBillingAddressForm,PaidPlan,
|
||||
AlertEditForm, ConditionEditForm,
|
||||
PlannedSessionComment,CoachRequest,CoachOffer,checkaccessplanuser
|
||||
PlannedSessionComment,CoachRequest,CoachOffer,checkaccessplanuser,
|
||||
VideoAnalysis
|
||||
)
|
||||
from rowers.models import (
|
||||
RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm,
|
||||
|
||||
@@ -47,10 +47,125 @@ def get_video_id(url):
|
||||
raise ValueError
|
||||
|
||||
# Show a video compared with data
|
||||
def workout_video_view(request,id=''):
|
||||
try:
|
||||
id = encoder.decode_hex(id)
|
||||
analysis = VideoAnalysis.objects.get(id=id)
|
||||
except VideoAnalysis.DoesNotExist:
|
||||
raise Http404("Video Analysis does not exist")
|
||||
|
||||
w = analysis.workout
|
||||
delay = analysis.delay
|
||||
|
||||
if request.user.is_authenticated:
|
||||
mayedit = checkworkoutuser(request.user,w) and isprorower(request.user.rower)
|
||||
rower = request.user.rower
|
||||
else:
|
||||
mayedit = False
|
||||
rower = None
|
||||
|
||||
# get video ID and offset
|
||||
if mayedit and request.method == 'POST':
|
||||
form = VideoAnalysisCreateForm(request.POST)
|
||||
if form.is_valid():
|
||||
video_id = form.cleaned_data['url']
|
||||
delay = form.cleaned_data['delay']
|
||||
if 'save_button' in request.POST:
|
||||
analysis.name = form.cleaned_data['name']
|
||||
analysis.video_id = video_id
|
||||
analysis.delay = delay
|
||||
analysis.save()
|
||||
else:
|
||||
video_id = id
|
||||
delay = 0
|
||||
elif mayedit:
|
||||
form = VideoAnalysisCreateForm(
|
||||
initial = {
|
||||
'name':analysis.name,
|
||||
'delay': analysis.delay,
|
||||
'url': analysis.video_id,
|
||||
}
|
||||
)
|
||||
video_id = analysis.video_id
|
||||
else:
|
||||
form = None
|
||||
|
||||
# get data
|
||||
df = getsmallrowdata_db(['time','velo','spm'],ids=[w.id],
|
||||
workstrokesonly=False,doclean=False,compute=False)
|
||||
df['time'] = (df['time']-df['time'].min())/1000.
|
||||
df.sort_values(by='time',inplace=True)
|
||||
|
||||
|
||||
df.set_index(pd.to_timedelta(df['time'],unit='s'),inplace=True)
|
||||
df2 = df.resample('1s').mean().interpolate()
|
||||
|
||||
|
||||
mask = df2['time'] < delay
|
||||
df2 = df2.mask(mask).dropna()
|
||||
df2['time'] = (df2['time']-df2['time'].min())
|
||||
|
||||
boatspeed = (100*df2['velo']).astype(int)/100.
|
||||
spm = (10*df2['spm']).astype(int)/10.
|
||||
|
||||
coordinates = dataprep.get_latlon_time(w.id)
|
||||
|
||||
coordinates.set_index(pd.to_timedelta(coordinates['time'],unit='s'),inplace=True)
|
||||
coordinates = coordinates.resample('1s').mean().interpolate()
|
||||
mask = coordinates['time'] < delay
|
||||
coordinates = coordinates.mask(mask).dropna()
|
||||
coordinates['time'] = coordinates['time']-coordinates['time'].min()
|
||||
latitude = coordinates['latitude']
|
||||
longitude = coordinates['longitude']
|
||||
|
||||
# create map
|
||||
mapscript, mapdiv = leaflet_chart_video(latitude,longitude,
|
||||
w.name)
|
||||
|
||||
# bundle data
|
||||
data = {
|
||||
'boatspeed':[ v for v in boatspeed.values],
|
||||
'latitude':[ l for l in latitude.values],
|
||||
'longitude':[ l for l in longitude.values],
|
||||
'spm':[ s for s in spm.values ]
|
||||
}
|
||||
|
||||
breadcrumbs = [
|
||||
{
|
||||
'url':'/rowers/list-workouts/',
|
||||
'name':'Workouts'
|
||||
},
|
||||
{
|
||||
'url':get_workout_default_page(request,encoder.encode_hex(w.id)),
|
||||
'name': w.name
|
||||
},
|
||||
{
|
||||
'url':reverse('workout_video_view',kwargs={'id':encoder.encode_hex(analysis.id)}),
|
||||
'name': 'Video Analysis'
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
return render(request,
|
||||
'embedded_video.html',
|
||||
{
|
||||
'workout':w,
|
||||
'rower':rower,
|
||||
'data': json.dumps(data,default=default),
|
||||
'mapscript': mapscript,
|
||||
'mapdiv': mapdiv,
|
||||
'video_id': analysis.video_id,
|
||||
'form':form,
|
||||
'breadcrumbs':breadcrumbs,
|
||||
'analysis':analysis,
|
||||
})
|
||||
|
||||
|
||||
# Create a video compared with data
|
||||
@user_passes_test(ispromember,login_url="/rowers/paidplans/",
|
||||
message="This functionality requires a Pro plan or higher",
|
||||
redirect_field_name=None)
|
||||
def workout_video_view(request,id=0):
|
||||
def workout_video_create_view(request,id=0):
|
||||
# get workout
|
||||
w = get_workout_permitted(request.user,id)
|
||||
|
||||
@@ -61,6 +176,17 @@ def workout_video_view(request,id=0):
|
||||
url = form.cleaned_data['url']
|
||||
delay = form.cleaned_data['delay']
|
||||
video_id = get_video_id(url)
|
||||
if 'save_button' in request.POST:
|
||||
analysis = VideoAnalysis(
|
||||
workout=w,
|
||||
name=form.cleaned_data['name'],
|
||||
video_id = video_id,
|
||||
delay=delay,
|
||||
)
|
||||
analysis.save()
|
||||
url = reverse('workout_video_view',
|
||||
kwargs={'id':encoder.encode_hex(analysis.id)})
|
||||
return HttpResponseRedirect(url)
|
||||
else:
|
||||
video_id = None
|
||||
delay = 0
|
||||
@@ -109,6 +235,22 @@ def workout_video_view(request,id=0):
|
||||
'spm':[ s for s in spm.values ]
|
||||
}
|
||||
|
||||
breadcrumbs = [
|
||||
{
|
||||
'url':'/rowers/list-workouts/',
|
||||
'name':'Workouts'
|
||||
},
|
||||
{
|
||||
'url':get_workout_default_page(request,encoder.encode_hex(w.id)),
|
||||
'name': w.name
|
||||
},
|
||||
{
|
||||
'url':reverse('workout_video_create_view',kwargs={'id':encoder.encode_hex(w.id)}),
|
||||
'name': 'Video Analysis'
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
return render(request,
|
||||
'embedded_video.html',
|
||||
{
|
||||
@@ -119,6 +261,7 @@ def workout_video_view(request,id=0):
|
||||
'mapdiv': mapdiv,
|
||||
'video_id': video_id,
|
||||
'form':form,
|
||||
'breadcrumbs':breadcrumbs,
|
||||
})
|
||||
|
||||
# Show the EMpower Oarlock generated Stroke Profile
|
||||
@@ -3633,6 +3776,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
|
||||
except:
|
||||
pass
|
||||
|
||||
videos = VideoAnalysis.objects.filter(workout=row)
|
||||
|
||||
# create interactive plot
|
||||
f1 = row.csvfilename
|
||||
@@ -3696,6 +3840,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
|
||||
'workout':row,
|
||||
'teams':get_my_teams(request.user),
|
||||
'graphs':g,
|
||||
'videos':videos,
|
||||
'breadcrumbs':breadcrumbs,
|
||||
'rower':r,
|
||||
'indoorraces':indoorraces,
|
||||
@@ -5357,6 +5502,58 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
|
||||
'formvalues':formvalues,
|
||||
})
|
||||
|
||||
class VideoDelete(DeleteView):
|
||||
login_required = True
|
||||
model = VideoAnalysis
|
||||
template_name = 'video_delete_confirm.html'
|
||||
|
||||
# extra parameters
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(VideoDelete, self).get_context_data(**kwargs)
|
||||
|
||||
breadcrumbs = [
|
||||
{
|
||||
'url':'/rowers/list-workouts/',
|
||||
'name':'Workouts'
|
||||
},
|
||||
{
|
||||
'url':get_workout_default_page(
|
||||
self.request,
|
||||
encoder.encode_hex(self.object.workout.id)),
|
||||
'name': self.object.workout.name
|
||||
},
|
||||
{
|
||||
'url':reverse('workout_video_view',kwargs={'id':encoder.encode_hex(self.object.id)}),
|
||||
'name': 'Video Analysis'
|
||||
},
|
||||
{ 'url':reverse('video_delete',kwargs={'pk':str(self.object.pk)}),
|
||||
'name': 'Delete'
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
context['active'] = 'nav-workouts'
|
||||
context['rower'] = getrower(self.request.user)
|
||||
context['breadcrumbs'] = breadcrumbs
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_success_url(self):
|
||||
w = self.object.workout
|
||||
try:
|
||||
w = Workout.objects.get(id=w.id)
|
||||
except Workout.DoesNotExist:
|
||||
return reverse('workouts_view')
|
||||
|
||||
return reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(w.id)})
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
obj = super(VideoDelete, self).get_object(*args, **kwargs)
|
||||
if not checkaccessuser(self.request.user,obj.workout.user):
|
||||
raise PermissionDenied('You are not allowed to delete this analysis')
|
||||
|
||||
return obj
|
||||
|
||||
class GraphDelete(DeleteView):
|
||||
login_required = True
|
||||
|
||||
Reference in New Issue
Block a user