proof of concept /video
This commit is contained in:
108
rowers/templates/embedded_video.html
Normal file
108
rowers/templates/embedded_video.html
Normal 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>
|
||||||
|
{% 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 %}
|
||||||
@@ -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'),
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user