Private
Public Access
1
0

proof of concept /video

This commit is contained in:
Sander Roosendaal
2019-11-04 21:56:51 +01:00
parent 01ca362c87
commit f92d6405cf
3 changed files with 137 additions and 8 deletions

View File

@@ -0,0 +1,108 @@
{% extends "newbase.html" %}
{% load staticfiles %}
{% load rowerfilters %}
{% load i18n %}
{% block title %}Workout Video{% endblock %}
{% block main %}
<p>
{% if workout|previousworkout:rower.user %}
<a href="/rowers/workout/{{ workout|previousworkout:rower.user }}/stats"
title="Jump to preceding workout"><em>Previous</em></a>&nbsp;
{% endif %}
{% if workout|nextworkout:rower.user %}
<a href="/rowers/workout/{{ workout|nextworkout:rower.user }}/stats"
title="Jump to following workout"><em>Next</em></a>
{% endif %}
</p>
{% language 'en' %}
<h1>Workout Video for {{ workout.name }}</h1>
<ul class="main-content">
<li class="grid_4">
<p>
This page will contain an embedded video
</p>
</li>
<li>
Video Time
<span id="time">
</span> seconds
</li>
<li>
Boat Speed
<span id="speed">
</span> m/s
</li>
<li class="grid_4">
<div id="player"></div>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
var videotime = 0;
var boatspeed = [{% for s in boatspeed %}{{ s|floatformat:4 }},{% endfor %}];
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: '9dLFC2q9RWc',
events: {
'onReady': onPlayerReady
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
function updateTime() {
var oldTime = videotime;
if(player && player.getCurrentTime) {
videotime = player.getCurrentTime();
velo = boatspeed[Math.round(videotime)];
console.log(Math.round(videotime),velo);
document.getElementById("time").innerHTML = Math.round(videotime);
document.getElementById("speed").innerHTML = velo;
}
if(videotime !== oldTime) {
onProgress(videotime);
}
}
timeupdater = setInterval(updateTime, 1000);
}
// when the time changes, this will be called.
function onProgress(currentTime) {
if(currentTime > 20) {
console.log("the video reached 20 seconds!");
}
}
function stopVideo() {
player.stopVideo();
}
</script>
</li>
</ul>
{% endlanguage %}
{% endblock %}
{% block sidebar %}
{% include 'menu_workout.html' %}
{% endblock %}

View File

@@ -45,8 +45,8 @@ class WorkoutViewSet(viewsets.ModelViewSet):
except TypeError: except TypeError:
return [] return []
permission_classes = ( permission_classes = (
#DjangoModelPermissions, #DjangoModelPermissions,
IsOwnerOrNot, IsOwnerOrNot,
@@ -56,7 +56,7 @@ class RowerViewSet(viewsets.ModelViewSet):
model = Rower model = Rower
serializer_class = RowerSerializer serializer_class = RowerSerializer
#queryset = Rower.objects.all() #queryset = Rower.objects.all()
def get_queryset(self): def get_queryset(self):
try: try:
r = Rower.objects.filter(user=self.request.user) r = Rower.objects.filter(user=self.request.user)
@@ -70,7 +70,7 @@ class RowerViewSet(viewsets.ModelViewSet):
http_method_names = ['get','patch'] http_method_names = ['get','patch']
class FavoriteChartViewSet(viewsets.ModelViewSet): class FavoriteChartViewSet(viewsets.ModelViewSet):
model = FavoriteChart model = FavoriteChart
serializer_class = FavoriteChartSerializer serializer_class = FavoriteChartSerializer
@@ -88,10 +88,10 @@ class FavoriteChartViewSet(viewsets.ModelViewSet):
) )
http_method_names = ['get','put','patch','delete'] http_method_names = ['get','put','patch','delete']
class StrokeDataViewSet(viewsets.ModelViewSet): class StrokeDataViewSet(viewsets.ModelViewSet):
serializer_class = StrokeDataSerializer serializer_class = StrokeDataSerializer
# Routers provide an easy way of automatically determining the URL conf. # Routers provide an easy way of automatically determining the URL conf.
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register(r'api/workouts',WorkoutViewSet, 'workout') router.register(r'api/workouts',WorkoutViewSet, 'workout')
@@ -104,7 +104,6 @@ def permissiondenied_view(request):
def filenotfound_view(request): def filenotfound_view(request):
print('aapje')
return rowers.views.error403_view(request) return rowers.views.error403_view(request)
def response_error_handler(request, exception=None): def response_error_handler(request, exception=None):
@@ -344,6 +343,7 @@ urlpatterns = [
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/split/$',views.workout_split_view,name='workout_split_view'), re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/split/$',views.workout_split_view,name='workout_split_view'),
# re_path(r'^workout/(?P<id>\d+)/interactiveplot/$',views.workout_biginteractive_view), # re_path(r'^workout/(?P<id>\d+)/interactiveplot/$',views.workout_biginteractive_view),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/view/$',views.workout_view,name='workout_view'), re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/view/$',views.workout_view,name='workout_view'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/video/$',views.workout_video_view,name='workout_video_view'),
# re_path(r'^workout/(?P<id>\d+)/$',views.workout_view,name='workout_view'), # re_path(r'^workout/(?P<id>\d+)/$',views.workout_view,name='workout_view'),
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/$',views.workout_view,name='workout_view'), re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/$',views.workout_view,name='workout_view'),
re_path(r'^workout/fusion/(?P<id1>\b[0-9A-Fa-f]+\b)/(?P<id2>\b[0-9A-Fa-f]+\b)/$',views.workout_fusion_view,name='workout_fusion_view'), re_path(r'^workout/fusion/(?P<id1>\b[0-9A-Fa-f]+\b)/(?P<id2>\b[0-9A-Fa-f]+\b)/$',views.workout_fusion_view,name='workout_fusion_view'),
@@ -475,7 +475,7 @@ urlpatterns = [
re_path(r'^me/coachrequest/(?P<code>\w+.*)/accept/$',views.coach_accept_coachrequest_view, re_path(r'^me/coachrequest/(?P<code>\w+.*)/accept/$',views.coach_accept_coachrequest_view,
name='coach_accept_coachrequest_view'), name='coach_accept_coachrequest_view'),
re_path(r'^me/coachoffer/(?P<code>\w+.*)/accept/$',views.rower_accept_coachoffer_view, re_path(r'^me/coachoffer/(?P<code>\w+.*)/accept/$',views.rower_accept_coachoffer_view,
name='rower_accept_coachoffer_view'), name='rower_accept_coachoffer_view'),
re_path(r'^team/(?P<id>\d+)/delete/$',views.team_delete_view,name='team_delete_view'), re_path(r'^team/(?P<id>\d+)/delete/$',views.team_delete_view,name='team_delete_view'),
re_path(r'^team/create/$',views.team_create_view,name='team_create_view'), re_path(r'^team/create/$',views.team_create_view,name='team_create_view'),
re_path(r'^me/team/(?P<teamid>\d+)/drop/(?P<userid>\d+)/$',views.manager_member_drop_view,name='manager_member_drop_view'), re_path(r'^me/team/(?P<teamid>\d+)/drop/(?P<userid>\d+)/$',views.manager_member_drop_view,name='manager_member_drop_view'),

View File

@@ -6,6 +6,27 @@ from __future__ import unicode_literals
from rowers.views.statements import * from rowers.views.statements import *
import rowers.teams as teams import rowers.teams as teams
# Show 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):
w = get_workout_permitted(request.user,id)
df = getsmallrowdata_db(['time','velo'],ids=[w.id])
df2 = pd.DataFrame({'time':[0]})
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()
boatspeed = df2['velo']
return render(request,
'embedded_video.html',
{
'workout':w,
'rower':request.user.rower,
'boatspeed': boatspeed.values,
})
# Show the EMpower Oarlock generated Stroke Profile # Show the EMpower Oarlock generated Stroke Profile
@user_passes_test(ispromember,login_url="/rowers/paidplans/", @user_passes_test(ispromember,login_url="/rowers/paidplans/",
message="This functionality requires a Pro plan or higher", message="This functionality requires a Pro plan or higher",