Merge branch 'feature/admintouser' into develop
This commit is contained in:
@@ -1225,7 +1225,10 @@ def handle_nonpainsled(f2, fileformat, summary=''):
|
||||
try:
|
||||
os.remove(f_to_be_deleted)
|
||||
except:
|
||||
try:
|
||||
os.remove(f_to_be_deleted + '.gz')
|
||||
except:
|
||||
pass
|
||||
|
||||
return (f2, summary, oarlength, inboard, fileformat)
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ from django_mailbox.models import Message, MessageAttachment,Mailbox
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.conf import settings
|
||||
|
||||
from django.utils import timezone
|
||||
from rowers.models import Workout, Rower
|
||||
|
||||
from rowingdata import rower as rrower
|
||||
@@ -23,6 +24,8 @@ from rowers.mailprocessing import make_new_workout_from_email, send_confirm
|
||||
import rowers.polarstuff as polarstuff
|
||||
import rowers.c2stuff as c2stuff
|
||||
import rowers.stravastuff as stravastuff
|
||||
from rowers.models import User,VirtualRace,Workout
|
||||
from rowers.plannedsessions import email_submit_race
|
||||
|
||||
workoutmailbox = Mailbox.objects.get(name='workouts')
|
||||
failedmailbox = Mailbox.objects.get(name='Failed')
|
||||
@@ -66,16 +69,41 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False):
|
||||
if testing:
|
||||
print 'Creating workout from email'
|
||||
|
||||
# set user
|
||||
if rower.user.is_staff and 'username' in uploadoptions:
|
||||
users = User.objects.filter(username=uploadoptions['username'])
|
||||
if len(users)==1:
|
||||
therower = users[0].rower
|
||||
else:
|
||||
return 0
|
||||
else:
|
||||
therower = rower
|
||||
|
||||
|
||||
workoutid = [
|
||||
make_new_workout_from_email(rower, filename, title,testing=testing)
|
||||
make_new_workout_from_email(therower, filename, title,testing=testing)
|
||||
]
|
||||
|
||||
|
||||
if 'raceid' in uploadoptions and workoutid[0] and rower.user.is_staff:
|
||||
if testing and workoutid[0]:
|
||||
w = Workout.objects.get(id = workoutid[0])
|
||||
w.startdatetime = timezone.now()
|
||||
w.date = timezone.now().date()
|
||||
w.save()
|
||||
try:
|
||||
race = VirtualRace.objects.get(id=uploadoptions['raceid'])
|
||||
if race.manager == rower.user:
|
||||
result = email_submit_race(therower,race,workoutid[0])
|
||||
except VirtualRace.DoesNotExist:
|
||||
pass
|
||||
|
||||
if testing:
|
||||
print 'Workout id = {workoutid}'.format(workoutid=workoutid)
|
||||
|
||||
if workoutid[0]:
|
||||
link = settings.SITE_URL+reverse(
|
||||
rower.defaultlandingpage,
|
||||
therower.defaultlandingpage,
|
||||
kwargs = {
|
||||
'id':workoutid[0],
|
||||
}
|
||||
@@ -99,9 +127,9 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False):
|
||||
)
|
||||
try:
|
||||
if workoutid and not testing:
|
||||
if rower.getemailnotifications and not rower.emailbounced:
|
||||
if therower.getemailnotifications and not therower.emailbounced:
|
||||
email_sent = send_confirm(
|
||||
rower.user, title, link,
|
||||
therower.user, title, link,
|
||||
uploadoptions
|
||||
)
|
||||
time.sleep(10)
|
||||
@@ -109,9 +137,9 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False):
|
||||
try:
|
||||
time.sleep(10)
|
||||
if workoutid:
|
||||
if rower.getemailnotifications and not rower.emailbounced:
|
||||
if therower.getemailnotifications and not therower.emailbounced:
|
||||
email_sent = send_confirm(
|
||||
rower.user, title, link,
|
||||
therower.user, title, link,
|
||||
uploadoptions
|
||||
)
|
||||
except:
|
||||
|
||||
+128
-1
@@ -36,6 +36,10 @@ import courses
|
||||
import iso8601
|
||||
from iso8601 import ParseError
|
||||
from rowers.tasks import handle_check_race_course
|
||||
from rowers.tasks import (
|
||||
handle_sendemail_raceregistration,handle_sendemail_racesubmission
|
||||
)
|
||||
from rowers.utils import totaltime_sec_to_string
|
||||
|
||||
def get_indoorraces(workout):
|
||||
races1 = VirtualRace.objects.filter(
|
||||
@@ -777,7 +781,6 @@ def race_can_submit(r,race):
|
||||
else:
|
||||
return False
|
||||
|
||||
print 'pop'
|
||||
return False
|
||||
|
||||
def race_can_resubmit(r,race):
|
||||
@@ -877,6 +880,130 @@ def race_can_withdraw(r,race):
|
||||
|
||||
return True
|
||||
|
||||
def email_submit_race(r,race,workoutid):
|
||||
try:
|
||||
w = Workout.objects.get(id=workoutid)
|
||||
except Workout.DoesNotExist:
|
||||
return 0
|
||||
|
||||
if race.sessionmode == 'time':
|
||||
wduration = timefield_to_seconds_duration(w.duration)
|
||||
delta = wduration - (60.*race.sessionvalue)
|
||||
|
||||
if delta > -2 and delta < 2:
|
||||
w.duration = totaltime_sec_to_string(60.*race.sessionvalue)
|
||||
w.save()
|
||||
|
||||
|
||||
elif race.sessionmode == 'distance':
|
||||
delta = w.distance - race.sessionvalue
|
||||
|
||||
if delta > -5 and delta < 5:
|
||||
w.distance = race.sessionvalue
|
||||
w.save()
|
||||
|
||||
|
||||
if race_can_register(r,race):
|
||||
teamname = ''
|
||||
weightcategory = w.weightcategory
|
||||
sex = r.sex
|
||||
if sex == 'not specified':
|
||||
sex = 'male'
|
||||
|
||||
if not r.birthdate:
|
||||
return 0
|
||||
|
||||
age = calculate_age(r.birthdate)
|
||||
|
||||
adaptiveclass = r.adaptiveclass
|
||||
boatclass = w.workouttype
|
||||
|
||||
record = IndoorVirtualRaceResult(
|
||||
userid = r.id,
|
||||
teamname=teamname,
|
||||
race=race,
|
||||
username = u'{f} {l}'.format(
|
||||
f = r.user.first_name,
|
||||
l = r.user.last_name
|
||||
),
|
||||
weightcategory=weightcategory,
|
||||
adaptiveclass=adaptiveclass,
|
||||
duration=dt.time(0,0),
|
||||
boatclass=boatclass,
|
||||
coursecompleted=False,
|
||||
sex=sex,
|
||||
age=age
|
||||
)
|
||||
|
||||
record.save()
|
||||
|
||||
result = add_rower_race(r,race)
|
||||
|
||||
otherrecords = IndoorVirtualRaceResult.objects.filter(
|
||||
race = race)
|
||||
|
||||
|
||||
for otherrecord in otherrecords:
|
||||
otheruser = Rower.objects.get(id=otherrecord.userid)
|
||||
othername = otheruser.user.first_name+' '+otheruser.user.last_name
|
||||
registeredname = r.user.first_name+' '+r.user.last_name
|
||||
if otherrecord.emailnotifications:
|
||||
job = myqueue(
|
||||
queue,
|
||||
handle_sendemail_raceregistration,
|
||||
otheruser.user.email, othername,
|
||||
registeredname,
|
||||
race.name,
|
||||
race.id
|
||||
)
|
||||
|
||||
|
||||
if race_can_submit(r,race):
|
||||
records = IndoorVirtualRaceResult.objects.filter(
|
||||
userid = r.id,
|
||||
race=race
|
||||
)
|
||||
|
||||
if not records:
|
||||
return 0
|
||||
|
||||
record = records[0]
|
||||
|
||||
workouts = Workout.objects.filter(id=w.id)
|
||||
|
||||
result,comments,errors,jobid = add_workout_indoorrace(
|
||||
workouts,race,r,recordid=record.id
|
||||
)
|
||||
|
||||
|
||||
if result:
|
||||
otherrecords = IndoorVirtualRaceResult.objects.filter(
|
||||
race = race)
|
||||
|
||||
for otherrecord in otherrecords:
|
||||
otheruser = Rower.objects.get(id=otherrecord.userid)
|
||||
othername = otheruser.user.first_name+' '+otheruser.user.last_name
|
||||
registeredname = r.user.first_name+' '+r.user.last_name
|
||||
if otherrecord.emailnotifications:
|
||||
job = myqueue(
|
||||
queue,
|
||||
handle_sendemail_racesubmission,
|
||||
otheruser.user.email, othername,
|
||||
registeredname,
|
||||
race.name,
|
||||
race.id
|
||||
)
|
||||
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
else:
|
||||
|
||||
return 0
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def race_can_register(r,race):
|
||||
if race.sessiontype == 'race':
|
||||
recordobj = VirtualRaceResult
|
||||
|
||||
@@ -0,0 +1,503 @@
|
||||
{% extends "newbase.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load rowerfilters %}
|
||||
|
||||
{% block title %}Rowsandall Virtual Race{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
{% include "monitorjobs.html" %}
|
||||
<script>
|
||||
setTimeout("location.reload(true);",60000);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block og_title %}{{ race.name }}{% endblock %}
|
||||
{% block description %}Virtual Rowing Race {{ race.name }}{% endblock %}
|
||||
|
||||
{% if racelogo %}
|
||||
{% block og_image %}
|
||||
<meta property="og:image" content="http://rowsandall.com/{{ racelogo.filename|spacetohtml }}" />
|
||||
<meta property="og:image:secure_url" content="https://rowsandall.com/{{ racelogo.filename |spacetohtml }}" />
|
||||
<meta property="og:image:width" content="{{ racelogo.width }}" />
|
||||
<meta property="og:image:height" content="{{ racelogo.height }}" />
|
||||
{% endblock %}
|
||||
{% block image_src %}
|
||||
<link rel="image_src" href="/{{ racelogo.filename |spacetohtml }}" />
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
|
||||
<h1>{{ race.name }}</h1>
|
||||
|
||||
|
||||
<ul class="main-content">
|
||||
<li class="grid_2">
|
||||
<div id="results">
|
||||
<p>
|
||||
{% if race|is_final %}
|
||||
<h2>Final Results</h2>
|
||||
{% else %}
|
||||
<h2>Results</h2>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% if results or dns %}
|
||||
<p>
|
||||
<table class="listtable shortpadded" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th>Name</th>
|
||||
<th>Team Name</th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>Class</th>
|
||||
{% if race.sessiontype == 'race' %}
|
||||
<th>Boat</th>
|
||||
{% endif %}
|
||||
<th>Time</th>
|
||||
<th>Distance</th>
|
||||
<th>Details</th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for result in results %}
|
||||
<tr>
|
||||
<td>{{ forloop.counter }}</td>
|
||||
<td>
|
||||
<a href="/rowers/workout/{{ result.workoutid }}">
|
||||
{{ result.username }}</a></td>
|
||||
<td>{{ result.teamname }}</td>
|
||||
<td>{{ result.age }}</td>
|
||||
<td>{{ result.sex }}</td>
|
||||
<td>{{ result.weightcategory }}</td>
|
||||
<td>
|
||||
{% if result.adaptiveclass == 'None' %}
|
||||
|
||||
{% else %}
|
||||
{{ result.adaptiveclass }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ result.boatclass }}</td>
|
||||
{% if race.sessiontype == 'race' %}
|
||||
<td>{{ result.boattype }}</td>
|
||||
{% endif %}
|
||||
<td>{{ result.duration |durationprint:"%H:%M:%S.%f" }}</td>
|
||||
<td>{{ result.distance }} m</td>
|
||||
<td>
|
||||
<a href="/rowers/workout/{{ result.workoutid }}">
|
||||
Details</a></td>
|
||||
<td>
|
||||
{% if race.manager == request.user and not race|is_final %}
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/disqualify/{{ result.id }}/">
|
||||
Disqualify
|
||||
</a>
|
||||
{% else %}
|
||||
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% for result in dns %}
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>{{ result.username }}</td>
|
||||
<td>{{ result.teamname }}</td>
|
||||
<td>{{ result.age }}</td>
|
||||
<td>{{ result.sex }}</td>
|
||||
<td>{{ result.weightcategory }}</td>
|
||||
<td>
|
||||
{% if result.adaptiveclass == 'None' %}
|
||||
|
||||
{% else %}
|
||||
{{ result.adaptiveclass }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ result.boatclass }}</td>
|
||||
{% if race.sessiontype == 'race' %}
|
||||
<td>{{ result.boattype }}</td>
|
||||
{% endif %}
|
||||
<td>DNS</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</p>
|
||||
<p>
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/compare"
|
||||
title="Compare the workouts of all competitors">Compare Results</a>
|
||||
</p>
|
||||
{% else %}
|
||||
<p>
|
||||
No results yet
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
{% if form %}
|
||||
<li class="grid_2">
|
||||
|
||||
<p>
|
||||
<h2>Filter Results</h2>
|
||||
</p>
|
||||
<p>
|
||||
|
||||
<form id="result_filter_form", method="post">
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
</table>
|
||||
|
||||
{% csrf_token %}
|
||||
<input type="submit" value="Submit">
|
||||
</p>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if racelogo %}
|
||||
<li class="grid_2">
|
||||
<img src="/{{ racelogo.filename }}" alt="{{ racelogo.filename }}" height="100" width="120">
|
||||
{% if race.manager == request.user %}
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/image">Edit Image</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if race.sessiontype == 'race' %}
|
||||
<li class="grid_2">
|
||||
<p>
|
||||
<h2>Course</h2>
|
||||
</p>
|
||||
<div class="mapdiv">
|
||||
{{ coursediv|safe }}
|
||||
|
||||
{{ coursescript|safe }}
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="grid_2">
|
||||
<div id="raceinfo">
|
||||
<p>
|
||||
<h2>Race Information</h2>
|
||||
</p>
|
||||
<p>
|
||||
<table class="listtable shortpadded" width="100%">
|
||||
<tbody>
|
||||
{% if race.sessiontype == 'race' %}
|
||||
<tr>
|
||||
<th>Course</th><td>{{ race.course }}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<th>Indoor Race</th><td>To be rowed on a Concept2 ergometer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Time Zone</th><td>{{ race.timezone }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<th>
|
||||
{{ race.sessionmode }} challenge
|
||||
</th><td>{{ race.sessionvalue }} {{ race.sessionunit }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Registration closure</th>
|
||||
<td>{{ race.registration_closure }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Date</th><td>{{ race.startdate }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Race Window</th><td>{{ race.startdate }} {{ race.start_time }} to {{ race.enddate }} {{ race.end_time }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Results Submission Deadline</th><td>{{ race.evaluation_closure }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Organizer</th><td>{{ race.manager.first_name }} {{ race.manager.last_name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Contact Email</th><td>{{ race.contact_email }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Contact Phone</th><td>{{ race.contact_phone }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Comment</th><td>{{ race.comment|linebreaks }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="grid_2">
|
||||
<div id="registerbuttons">
|
||||
{% if request.user.is_anonymous %}
|
||||
<p>
|
||||
Registered users of rowsandall.com can participate in this event. Participation is free, unless specified differently in the race comment above.
|
||||
{% if race.sessiontype == 'race' %}
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/register"><h3>Register</h3></a>
|
||||
{% else %}
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/registerindoor"><h3>Register</h3></a>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% else %}
|
||||
<p>
|
||||
See race rules below. Participation to this race is free,
|
||||
unless specified differently in the race comment above.
|
||||
</p>
|
||||
<p>
|
||||
{% for button in buttons %}
|
||||
{% if button == 'registerbutton' %}
|
||||
<p>
|
||||
{% if race.sessiontype == 'race' %}
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/register"><h3>Register</h3></a>
|
||||
{% else %}
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/registerindoor"><h3>Register</h3></a>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if button == 'submitbutton' %}
|
||||
<table width=100% class="shortpadded">
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/submit">Submit Workout</a>
|
||||
</td>
|
||||
<td>
|
||||
Submit a workout that is already on the site as your race result
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/rowers/workout/upload">Upload your race result</a>
|
||||
</td>
|
||||
<td>
|
||||
Upload a new workout to the site and submit it as a result. You
|
||||
need a workout data file.
|
||||
</td>
|
||||
</tr>
|
||||
{% if race.sessiontype == 'indoorrace' %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/rowers/workout/addmanual">Enter your race result manually</a>
|
||||
</td>
|
||||
<td>
|
||||
If you don't have a data file, enter the results
|
||||
manually. If you have a photo of the monitor with the
|
||||
result, it is recommended to add this to the workout.
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% if button == 'resubmitbutton' %}
|
||||
<p>
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/submit">Submit New Result</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if button == 'withdrawbutton' %}
|
||||
<p>
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/withdraw">Withdraw</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if button == 'adddisciplinebutton' %}
|
||||
<p>
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/adddiscipline">
|
||||
Register New Boat
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if button == 'editbutton' %}
|
||||
<p>
|
||||
{% if race.sessiontype == 'race' %}
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/edit">Edit Race
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/editindoor">Edit Race
|
||||
</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
<li class="grid_2">
|
||||
<div id="registered">
|
||||
{% if records %}
|
||||
<h2>Registered Competitors</h2>
|
||||
<table class="listtable shortpadded" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Team Name</th>
|
||||
{% if race.sessiontype == 'race' %}
|
||||
<th>Class</th>
|
||||
<th>Boat</th>
|
||||
{% else %}
|
||||
<th>Class</th>
|
||||
{% endif %}
|
||||
<th>Age</th>
|
||||
<th>Gender</th>
|
||||
<th>Weight Category</th>
|
||||
<th>Adaptive</th>
|
||||
</tr>
|
||||
<tbody>
|
||||
{% for record in records %}
|
||||
<tr>
|
||||
<td>{{ record.username }}
|
||||
<td>{{ record.teamname }}</td>
|
||||
<td>{{ record.boatclass }}</td>
|
||||
{% if race.sessiontype == 'race' %}
|
||||
<td>{{ record.boattype }}</td>
|
||||
{% endif %}
|
||||
<td>{{ record.age }}</td>
|
||||
<td>{{ record.sex }}</td>
|
||||
<td>{{ record.weightcategory }}</td>
|
||||
<td>
|
||||
{% if record.adaptiveclass == 'None' %}
|
||||
|
||||
{% else %}
|
||||
{{ record.adaptiveclass }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% if record.userid == rower.id and 'withdrawbutton' in buttons %}
|
||||
<td>
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/withdraw/{{ record.id }}" >Withdraw</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% for record in records %}
|
||||
{% if record.userid == request.user.rower.id %}
|
||||
{% if race.sessiontype == 'race' %}
|
||||
{% if record.emailnotifications %}
|
||||
<a href="/rowers/raceregistration/togglenotification/{{ race.id }}">
|
||||
Unsubscribe from race notifications by email
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="/rowers/raceregistration/togglenotification/{{ race.id }}">
|
||||
Subscribe to race notifications by email
|
||||
</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if record.emailnotifications %}
|
||||
<a href="/rowers/indoorraceregistration/togglenotification/{{ race.id }}">
|
||||
Unsubscribe from race notifications by email
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="/rowers/indoorraceregistration/togglenotification/{{ race.id }}">
|
||||
Subscribe to race notifications by email
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</li>
|
||||
<li class="grid_4">
|
||||
<div id="rules">
|
||||
<p>
|
||||
<h2>Rules</h2>
|
||||
</p>
|
||||
<p>
|
||||
Virtual races are intended as an informal way to add a
|
||||
competitive element to training and as a quick way to set
|
||||
up and manage small regattas.
|
||||
</p>
|
||||
<p>
|
||||
On the water races are rowed on the course shown.
|
||||
You cannot submit results rowed
|
||||
on other bodies of water.
|
||||
</p>
|
||||
<p>
|
||||
Indoor races are open for all, wherever you live.
|
||||
However, be aware of the
|
||||
time zone for the race window.
|
||||
</p>
|
||||
<p>
|
||||
As a rowsandall.com user, you can
|
||||
register to take part in this event. Please note the registration
|
||||
deadline. You must register before this deadline.
|
||||
You can always withdraw from participating before the registration
|
||||
deadline or the start of the race window, whichever is earlier.
|
||||
</p>
|
||||
<p>
|
||||
After the start of the race window and before the submission deadline,
|
||||
you can submit results by linking the race to one of your uploaded
|
||||
workouts. The workout start time must be within the race window
|
||||
and your course must pass through the blue polygons on the course
|
||||
map (in the right order), for your result to be valid.
|
||||
</p>
|
||||
<p>
|
||||
The results table has a link to a page where details of your workout
|
||||
are shown.
|
||||
</p>
|
||||
<p>
|
||||
Race results are stored permanently and are not deleted when
|
||||
you delete the respective workout or remove your account.
|
||||
By registering, you agree with this and the race rules.
|
||||
</p>
|
||||
<p>
|
||||
If you use a manually added workout for your indoor race result,
|
||||
please attach a screenshot of the ergometer display for verification.
|
||||
</p>
|
||||
<p>
|
||||
Virtual Racing on rowsandall.com is honors based. Please be a good
|
||||
sport, submit real results rowed by you, and make sure you set the
|
||||
boat type correctly. For (future functionality) age and gender
|
||||
corrected times, please be sure your gender and birth date are set
|
||||
correctly in your user settings.
|
||||
</p>
|
||||
<p>
|
||||
Virtual races are intended as an informal way to add a
|
||||
competitive element to training. Virtual races are not
|
||||
refereed or staffed to provide for participants safety.
|
||||
Individual participants are entirely responsible for their
|
||||
safety while participating in a virtual race.
|
||||
</p>
|
||||
<p>
|
||||
Until the evaluation closure time, the race organizer can
|
||||
review and reject entries. If you are disqualified in this
|
||||
way, you will receive an email with the reason.
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<div class="fb-share-button"
|
||||
data-href="{{ request.build_absolute_uri }}"
|
||||
data-layout="button" data-size="small" data-mobile-iframe="false">
|
||||
<a class="fb-xfbml-parse-ignore" target="_blank"
|
||||
href="https://www.facebook.com/sharer/sharer.php?u={{ request.build_absolute_uri }}">Share</a>
|
||||
</div>
|
||||
</p><p>
|
||||
<a class="twitter-share-button"
|
||||
href="https://twitter.com/intent/tweet"
|
||||
data-url="{{ request.build_absolute_uri }}"
|
||||
{% if race.sessiontype == 'race' %}
|
||||
data-text="@rowsandall #rowingdata Participate in virtual race '{{ race.name }}'">Tweet</a>
|
||||
{% else %}
|
||||
data-text="@rowsandall #rowingdata Participate in Indoor Rowing virtual race '{{ race.name }}'">Tweet</a>
|
||||
{% endif %}
|
||||
</p><p>
|
||||
<a href="https://www.pinterest.com/pin/create/button/"
|
||||
data-pin-do="buttonBookmark">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
{% if not racelogo and race.manager == request.user %}
|
||||
<a href="/rowers/virtualevent/{{ race.id }}/image">Add Race Logo</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% include 'menu_racing.html' %}
|
||||
{% endblock %}
|
||||
@@ -128,6 +128,22 @@ class UserFactory(factory.DjangoModelFactory):
|
||||
first_name = faker.name().split(' ')[0]
|
||||
last_name = faker.name().split(' ')[0]
|
||||
|
||||
class RaceFactory(factory.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = VirtualRace
|
||||
|
||||
name = factory.LazyAttribute(lambda _: faker.word())
|
||||
registration_closure = timezone.now()+datetime.timedelta(days=1)
|
||||
evaluation_closure = timezone.now()+datetime.timedelta(days=2)
|
||||
startdate = timezone.now().date()
|
||||
start_time = datetime.time()
|
||||
enddate = (timezone.now()+datetime.timedelta(days=1)).date()
|
||||
end_time = datetime.time()
|
||||
preferreddate = timezone.now().date()
|
||||
sessiontype = 'indoorrace'
|
||||
sessionvalue = 1
|
||||
sessionmode = 'time'
|
||||
|
||||
class WorkoutFactory(factory.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = Workout
|
||||
@@ -150,3 +166,20 @@ class SessionFactory(factory.DjangoModelFactory):
|
||||
name = factory.LazyAttribute(lambda _: faker.word())
|
||||
comment = faker.text()
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def cleanup(request):
|
||||
def remove_test_files():
|
||||
|
||||
for filename in os.listdir('media/mailbox_attachments'):
|
||||
path = os.path.join('media/mailbox_attachments/',filename)
|
||||
if not os.path.isdir(path):
|
||||
os.remove(path)
|
||||
|
||||
for filename in os.listdir('rowers/tests/testdata/temp'):
|
||||
path = os.path.join('rowers/tests/testdata/temp/',filename)
|
||||
if not os.path.isdir(path):
|
||||
os.remove(path)
|
||||
|
||||
|
||||
request.addfinalizer(remove_test_files)
|
||||
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
#from __future__ import print_function
|
||||
from statements import *
|
||||
|
||||
class EmailUpload(TestCase):
|
||||
def setUp(self):
|
||||
redis_connection.publish('tasks','KILL')
|
||||
u = User.objects.create_user('john',
|
||||
'sander@ds.ds',
|
||||
'koeinsloot')
|
||||
r = Rower.objects.create(user=u,gdproptin=True,
|
||||
gdproptindate=timezone.now()
|
||||
)
|
||||
|
||||
self.theadmin = UserFactory(is_staff=True)
|
||||
self.rtheadmin = Rower.objects.create(user=self.theadmin,
|
||||
birthdate = faker.profile()['birthdate'],
|
||||
gdproptin=True,
|
||||
gdproptindate=timezone.now(),
|
||||
rowerplan='coach')
|
||||
|
||||
nu = datetime.datetime.now()
|
||||
workoutsbox = Mailbox.objects.create(name='workouts')
|
||||
workoutsbox.save()
|
||||
failbox = Mailbox.objects.create(name='Failed')
|
||||
failbox.save()
|
||||
|
||||
m = Message(mailbox=workoutsbox,
|
||||
from_header = u.email,
|
||||
subject = "run",
|
||||
body = """
|
||||
workout run
|
||||
""")
|
||||
m.save()
|
||||
a2 = 'media/mailbox_attachments/colin3.csv'
|
||||
copyfile('rowers/tests/testdata/emails/colin.csv',a2)
|
||||
a = MessageAttachment(message=m,document=a2[6:])
|
||||
a.save()
|
||||
|
||||
def tearDown(self):
|
||||
for filename in os.listdir('media/mailbox_attachments'):
|
||||
path = os.path.join('media/mailbox_attachments/',filename)
|
||||
if not os.path.isdir(path):
|
||||
try:
|
||||
os.remove(path)
|
||||
except (IOError,WindowsError):
|
||||
pass
|
||||
|
||||
@patch('rowers.dataprep.create_engine')
|
||||
@patch('rowers.polarstuff.get_polar_notifications')
|
||||
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
|
||||
@patch('rowers.c2stuff.requests.post', side_effect=mocked_requests)
|
||||
def test_emailupload(
|
||||
self, mocked_sqlalchemy,mocked_polar_notifications, mock_get, mock_post):
|
||||
out = StringIO()
|
||||
call_command('processemail', stdout=out,testing=True)
|
||||
self.assertIn('Successfully processed email attachments',out.getvalue())
|
||||
|
||||
ws = Workout.objects.filter(name="run")
|
||||
|
||||
self.assertEqual(len(ws),1)
|
||||
w = ws[0]
|
||||
self.assertEqual(w.workouttype,'Run')
|
||||
|
||||
|
||||
|
||||
#@pytest.mark.django_db
|
||||
class EmailTests(TestCase):
|
||||
def setUp(self):
|
||||
redis_connection.publish('tasks','KILL')
|
||||
u = User.objects.create_user('john',
|
||||
'sander@ds.ds',
|
||||
'koeinsloot')
|
||||
r = Rower.objects.create(user=u,gdproptin=True,
|
||||
gdproptindate=timezone.now()
|
||||
)
|
||||
|
||||
self.theadmin = UserFactory(is_staff=True)
|
||||
self.rtheadmin = Rower.objects.create(user=self.theadmin,
|
||||
birthdate = faker.profile()['birthdate'],
|
||||
gdproptin=True,
|
||||
gdproptindate=timezone.now(),
|
||||
rowerplan='coach')
|
||||
|
||||
nu = datetime.datetime.now()
|
||||
workoutsbox = Mailbox.objects.create(name='workouts')
|
||||
workoutsbox.save()
|
||||
failbox = Mailbox.objects.create(name='Failed')
|
||||
failbox.save()
|
||||
|
||||
|
||||
for filename in os.listdir(u'rowers/tests/testdata/emails'):
|
||||
m = Message(mailbox=workoutsbox,
|
||||
from_header = u.email,
|
||||
subject = filename,
|
||||
body="""
|
||||
---
|
||||
workouttype: water
|
||||
boattype: 4x
|
||||
...
|
||||
""")
|
||||
m.save()
|
||||
a2 = 'media/mailbox_attachments/'+filename
|
||||
copyfile(u'rowers/tests/testdata/emails/'+filename,a2)
|
||||
a = MessageAttachment(message=m,document=a2[6:])
|
||||
a.save()
|
||||
|
||||
m = Message(mailbox=workoutsbox,
|
||||
from_header = u.email,
|
||||
subject = "3x(5min/2min)/r2 \r2",
|
||||
body = """
|
||||
workout water
|
||||
""")
|
||||
m.save()
|
||||
a2 = 'media/mailbox_attachments/colin2.csv'
|
||||
copyfile('rowers/tests/testdata/emails/colin.csv',a2)
|
||||
a = MessageAttachment(message=m,document=a2[6:])
|
||||
a.save()
|
||||
|
||||
m = Message(mailbox=workoutsbox,
|
||||
from_header = self.theadmin.email,
|
||||
subject = "johnsworkout",
|
||||
body = """
|
||||
user john
|
||||
race 1
|
||||
""")
|
||||
m.save()
|
||||
|
||||
def tearDown(self):
|
||||
for filename in os.listdir('media/mailbox_attachments'):
|
||||
path = os.path.join('media/mailbox_attachments/',filename)
|
||||
if not os.path.isdir(path):
|
||||
try:
|
||||
os.remove(path)
|
||||
except (IOError,WindowsError):
|
||||
pass
|
||||
|
||||
@patch('rowers.dataprep.create_engine')
|
||||
@patch('rowers.polarstuff.get_polar_notifications')
|
||||
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
|
||||
@patch('rowers.c2stuff.requests.post', side_effect=mocked_requests)
|
||||
def test_emailprocessing(
|
||||
self, mocked_sqlalchemy,mocked_polar_notifications, mock_get, mock_post):
|
||||
out = StringIO()
|
||||
call_command('processemail', stdout=out,testing=True)
|
||||
self.assertIn('Successfully processed email attachments',out.getvalue())
|
||||
|
||||
|
||||
|
||||
class EmailAdminUpload(TestCase):
|
||||
def setUp(self):
|
||||
redis_connection.publish('tasks','KILL')
|
||||
u = User.objects.create_user('john',
|
||||
'sander@ds.ds',
|
||||
'koeinsloot')
|
||||
r = Rower.objects.create(user=u,gdproptin=True,
|
||||
gdproptindate=timezone.now(),
|
||||
birthdate = faker.profile()['birthdate']
|
||||
)
|
||||
|
||||
self.theadmin = UserFactory(is_staff=True)
|
||||
self.rtheadmin = Rower.objects.create(user=self.theadmin,
|
||||
birthdate = faker.profile()['birthdate'],
|
||||
gdproptin=True,
|
||||
gdproptindate=timezone.now(),
|
||||
rowerplan='coach')
|
||||
|
||||
self.race = RaceFactory(manager = self.theadmin)
|
||||
|
||||
nu = datetime.datetime.now()
|
||||
workoutsbox = Mailbox.objects.create(name='workouts')
|
||||
workoutsbox.save()
|
||||
failbox = Mailbox.objects.create(name='Failed')
|
||||
failbox.save()
|
||||
|
||||
m = Message(mailbox=workoutsbox,
|
||||
from_header = self.theadmin.email,
|
||||
subject = "johnsworkout",
|
||||
body = """
|
||||
user john
|
||||
race 1
|
||||
""")
|
||||
m.save()
|
||||
a2 = 'media/mailbox_attachments/minute.csv'
|
||||
copyfile('rowers/tests/testdata/minute.csv',a2)
|
||||
a = MessageAttachment(message=m,document=a2[6:])
|
||||
a.save()
|
||||
|
||||
def tearDown(self):
|
||||
for filename in os.listdir('media/mailbox_attachments'):
|
||||
path = os.path.join('media/mailbox_attachments/',filename)
|
||||
if not os.path.isdir(path):
|
||||
try:
|
||||
os.remove(path)
|
||||
except (IOError,WindowsError):
|
||||
pass
|
||||
|
||||
@patch('rowers.dataprep.create_engine')
|
||||
@patch('rowers.polarstuff.get_polar_notifications')
|
||||
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
|
||||
@patch('rowers.c2stuff.requests.post', side_effect=mocked_requests)
|
||||
def test_email_admin_upload(
|
||||
self, mocked_sqlalchemy,mocked_polar_notifications, mock_get, mock_post):
|
||||
out = StringIO()
|
||||
call_command('processemail', stdout=out,testing=True)
|
||||
self.assertIn('Successfully processed email attachments',out.getvalue())
|
||||
|
||||
ws = Workout.objects.filter(name="johnsworkout")
|
||||
if not len(ws):
|
||||
for w in Workout.objects.all():
|
||||
print w
|
||||
|
||||
self.assertEqual(len(ws),1)
|
||||
|
||||
w = ws[0]
|
||||
self.assertEqual(w.user.user.username,u'john')
|
||||
|
||||
results = IndoorVirtualRaceResult.objects.filter(
|
||||
race=self.race)
|
||||
|
||||
self.assertEqual(len(results),1)
|
||||
result = results[0]
|
||||
|
||||
self.assertTrue(result.coursecompleted)
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
#from __future__ import print_function
|
||||
import pytest
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
import re
|
||||
from nose_parameterized import parameterized
|
||||
from django.test import TestCase, Client,override_settings
|
||||
from django.core.management import call_command
|
||||
from django.utils.six import StringIO
|
||||
from django.test.client import RequestFactory
|
||||
from rowers.views import checkworkoutuser,c2_open
|
||||
from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage
|
||||
from rowers.forms import DocumentsForm,CNsummaryForm,RegistrationFormUniqueEmail
|
||||
import rowers.plots as plots
|
||||
import rowers.interactiveplots as iplots
|
||||
import datetime
|
||||
from rowingdata import rowingdata as rdata
|
||||
from rowingdata import rower as rrower
|
||||
from django.utils import timezone
|
||||
from rowers.rows import handle_uploaded_file
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from time import strftime,strptime,mktime,time,daylight
|
||||
import os
|
||||
from rowers.tasks import handle_makeplot
|
||||
from rowers.utils import serialize_list,deserialize_list
|
||||
from rowers.utils import NoTokenError
|
||||
from shutil import copyfile
|
||||
from nose.tools import assert_true
|
||||
from mock import Mock, patch
|
||||
from minimocktest import MockTestCase
|
||||
import pandas as pd
|
||||
import rowers.c2stuff as c2stuff
|
||||
|
||||
import json
|
||||
import numpy as np
|
||||
|
||||
from rowers import urls
|
||||
from rowers.views import error500_view,error404_view,error400_view,error403_view
|
||||
|
||||
from rowers.dataprep import delete_strokedata
|
||||
|
||||
from redis import StrictRedis
|
||||
redis_connection = StrictRedis()
|
||||
|
||||
from rowers.tests.test_imports import mocked_requests
|
||||
|
||||
|
||||
from django_mailbox.models import Mailbox,MessageAttachment,Message
|
||||
|
||||
from rowers.tests.mocks import mocked_sqlalchemy
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class UploadTests(TestCase):
|
||||
def setUp(self):
|
||||
redis_connection.publish('tasks','KILL')
|
||||
u = User.objects.create_user('john',
|
||||
'sander@ds.ds',
|
||||
'koeinsloot')
|
||||
r = Rower.objects.create(user=u,gdproptin=True,
|
||||
gdproptindate=timezone.now(),
|
||||
getemailnotifications = False,
|
||||
)
|
||||
|
||||
nu = datetime.datetime.now()
|
||||
workoutsbox = Mailbox.objects.create(name='workouts')
|
||||
workoutsbox.save()
|
||||
failbox = Mailbox.objects.create(name='Failed')
|
||||
failbox.save()
|
||||
m = Message(mailbox=workoutsbox,
|
||||
from_header = u.email,
|
||||
subject = "3x(5min/2min)/r2 \r2",
|
||||
body = """
|
||||
workout run
|
||||
""")
|
||||
m.save()
|
||||
a2 = 'media/mailbox_attachments/colin2.csv'
|
||||
copyfile('rowers/tests/testdata/emails/colin.csv',a2)
|
||||
a = MessageAttachment(message=m,document=a2[6:])
|
||||
a.save()
|
||||
|
||||
def tearDown(self):
|
||||
for filename in os.listdir('media/mailbox_attachments'):
|
||||
path = os.path.join('media/mailbox_attachments/',filename)
|
||||
if not os.path.isdir(path):
|
||||
try:
|
||||
os.remove(path)
|
||||
except (IOError,WindowsError):
|
||||
pass
|
||||
|
||||
@patch('requests.get', side_effect=mocked_requests)
|
||||
def test_email_workouttype(self, mock_get):
|
||||
out = StringIO()
|
||||
call_command('processemail', stdout=out, testing=True)
|
||||
w = Workout.objects.get(id=1)
|
||||
self.assertEqual(w.workouttype,'Run')
|
||||
|
||||
#@pytest.mark.django_db
|
||||
class EmailTests(TestCase):
|
||||
def setUp(self):
|
||||
redis_connection.publish('tasks','KILL')
|
||||
u = User.objects.create_user('john',
|
||||
'sander@ds.ds',
|
||||
'koeinsloot')
|
||||
r = Rower.objects.create(user=u,gdproptin=True,
|
||||
gdproptindate=timezone.now()
|
||||
)
|
||||
|
||||
nu = datetime.datetime.now()
|
||||
workoutsbox = Mailbox.objects.create(name='workouts')
|
||||
workoutsbox.save()
|
||||
failbox = Mailbox.objects.create(name='Failed')
|
||||
failbox.save()
|
||||
|
||||
for filename in os.listdir(u'rowers/tests/testdata/emails'):
|
||||
m = Message(mailbox=workoutsbox,
|
||||
from_header = u.email,
|
||||
subject = filename,
|
||||
body="""
|
||||
---
|
||||
workouttype: water
|
||||
boattype: 4x
|
||||
...
|
||||
""")
|
||||
m.save()
|
||||
a2 = 'media/mailbox_attachments/'+filename
|
||||
copyfile(u'rowers/tests/testdata/emails/'+filename,a2)
|
||||
a = MessageAttachment(message=m,document=a2[6:])
|
||||
a.save()
|
||||
|
||||
m = Message(mailbox=workoutsbox,
|
||||
from_header = u.email,
|
||||
subject = "3x(5min/2min)/r2 \r2",
|
||||
body = """
|
||||
workout water
|
||||
""")
|
||||
m.save()
|
||||
a2 = 'media/mailbox_attachments/colin2.csv'
|
||||
copyfile('rowers/tests/testdata/emails/colin.csv',a2)
|
||||
a = MessageAttachment(message=m,document=a2[6:])
|
||||
a.save()
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
for filename in os.listdir('media/mailbox_attachments'):
|
||||
path = os.path.join('media/mailbox_attachments/',filename)
|
||||
if not os.path.isdir(path):
|
||||
try:
|
||||
os.remove(path)
|
||||
except (IOError,WindowsError):
|
||||
pass
|
||||
|
||||
@patch('rowers.dataprep.create_engine')
|
||||
@patch('rowers.polarstuff.get_polar_notifications')
|
||||
@patch('rowers.c2stuff.requests.get', side_effect=mocked_requests)
|
||||
@patch('rowers.c2stuff.requests.post', side_effect=mocked_requests)
|
||||
def test_emailprocessing(
|
||||
self, mocked_sqlalchemy,mocked_polar_notifications, mock_get, mock_post):
|
||||
out = StringIO()
|
||||
call_command('processemail', stdout=out,testing=True)
|
||||
self.assertIn('Successfully processed email attachments',out.getvalue())
|
||||
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
index,TimeStamp (sec), activityIdx, lapIdx, pointIdx, ElapsedTime (sec), Horizontal (meters), Stroke500mPace (sec/500m), Cadence (strokes/min), HRCur (bpm), Power (watts), Calories (kCal), Speed (m/sec), StrokeCount, StrokeDistance (meters), DriveLength (meters), DriveTime (ms), StrokeRecoveryTime (ms), WorkPerStroke (joules), AverageDriveForce (lbs), PeakDriveForce (lbs), DragFactor, ElapsedTimeAtDrive (sec), HorizontalAtDrive (meters), WorkoutType, IntervalType, WorkoutState, RowingState, WorkoutDurationType, WorkoutIntervalCount, Cadence (stokes/min), AverageBoatSpeed (m/s), AverageDriveForce (N), PeakDriveForce (N), Stroke Number,cum_dist,originalvelo
|
||||
0,1548096824.0,0,0,0,4.18,20.3,93.3506356168139,48,86,436.5048883104004,1,5.3820000000000014,4,6.79,1.36,500,560,0,142.4,222.0,115,0.0,0.0,5,0,1,1,0,0,48.0,5.353892279687333,633.4265280000002,987.50484,2,20.3,5.353892279687333
|
||||
1,1548096826.7910905,0,0,1,6.94,35.9,89.62484388832563,45,87,496.4816892895996,2,5.6179999999999986,6,8.15,1.42,490,730,0,142.3,238.8,113,4.18,20.3,5,0,1,1,0,0,45.0,5.587840858292355,632.9817059999998,1062.2349359999996,4,35.9,5.587840858292355
|
||||
2,1548096837.108201,0,0,2,17.27,94.5,88.81577825856567,41,96,504.2099300644,8,5.647,13,8.19,1.36,480,770,0,144.0,242.9,112,6.94,35.9,5,0,1,1,0,0,41.0,5.616084465910367,640.54368,1080.4726380000004,11,94.5,5.616084465910367
|
||||
3,1548096839.086601,0,0,3,19.25,105.7,88.96490450858349,41,99,504.2099300644,8,5.647,14,8.19,1.39,480,750,0,142.0,244.6,112,17.27,94.5,5,0,1,1,0,0,41.0,5.616084465910367,631.64724,1088.034612,12,105.7,5.616084465910367
|
||||
4,1548096842.8994308,0,0,4,23.07,127.2,89.27586762584984,41,104,501.8029914016,11,5.638,17,8.12,1.36,470,760,0,143.6,251.4,112,19.25,105.7,5,0,1,1,0,0,41.0,5.607267018055401,638.7643919999998,1118.282508,15,127.2,5.607267018055401
|
||||
5,1548096847.161281,0,0,5,27.31,151.1,89.89298681607487,41,110,489.62041712640007,14,5.5920000000000005,20,8.11,1.36,490,760,0,133.6,231.0,111,23.07,127.2,5,0,1,1,0,0,41.0,5.561116672227786,594.282192,1027.53882,18,151.1,5.561116672227786
|
||||
6,1548096850.1555116,0,0,6,30.31,167.8,90.29743877919012,41,112,480.4843223404,15,5.557,22,8.47,1.39,490,820,0,143.9,234.4,111,27.31,151.1,5,0,1,1,0,0,41.0,5.526693931690064,640.0988580000002,1042.662768,20,167.8,5.526693931690064
|
||||
7,1548096853.1276512,0,0,7,33.28,184.3,90.39988760767656,40,113,484.1249963508004,17,5.5710000000000015,24,8.24,1.36,490,800,0,138.4,254.1,111,30.31,167.8,5,0,1,1,0,0,40.0,5.540780141843972,615.633648,1130.292702,22,184.3,5.540780141843972
|
||||
8,1548096856.0643613,0,0,8,36.21,200.5,90.61884542605642,41,115,477.8950465044004,18,5.5470000000000015,26,8.1,1.36,480,770,0,135.5,227.6,111,33.28,184.3,5,0,1,1,0,0,41.0,5.516936996579499,602.7338100000002,1012.4148720000001,24,200.5,5.516936996579499
|
||||
9,1548096859.0091813,0,0,9,39.17,216.8,91.12253138918642,41,116,468.9058576384001,20,5.5120000000000005,28,8.1,1.36,500,770,0,132.7,232.4,111,36.21,200.5,5,0,1,1,0,0,41.0,5.483057352779911,590.2787940000002,1033.766328,26,216.8,5.483057352779911
|
||||
10,1548096862.008181,0,0,10,42.16,233.2,91.7159092344983,40,117,462.8074479616,21,5.488,30,8.24,1.33,470,810,0,130.6,218.9,111,39.17,216.8,5,0,1,1,0,0,40.0,5.459111256687411,580.937532,973.715358,28,233.2,5.459111256687411
|
||||
11,1548096866.4157307,0,0,11,46.57,257.2,92.13100908526968,41,118,452.5120589444,24,5.447,33,7.89,1.33,470,760,0,133.0,227.5,111,42.16,233.2,5,0,1,1,0,0,41.0,5.417705060136527,591.61326,1011.97005,31,257.2,5.417705060136527
|
||||
12,1548096869.206501,0,0,12,49.36,272.4,92.30771272248859,43,118,452.7613310976001,25,5.448,35,7.6,1.3,460,710,0,131.0,208.0,111,46.57,257.2,5,0,1,1,0,0,43.0,5.418879375745096,582.71682,925.2297599999999,33,272.4,5.418879375745096
|
||||
13,1548096872.1160307,0,0,13,52.27,288.2,92.39395707918017,42,119,451.2670704864,26,5.442,37,7.96,1.33,480,770,0,132.8,222.3,111,49.36,272.4,5,0,1,1,0,0,42.0,5.413598960589,590.7236160000001,988.839306,35,288.2,5.413598960589
|
||||
14,1548096875.085701,0,0,14,55.24,304.2,92.99397114111812,41,119,442.6160316004,28,5.407,39,8.02,1.3,480,790,0,128.7,230.0,111,52.27,288.2,5,0,1,1,0,0,41.0,5.378657487091222,572.485914,1023.0906,37,304.2,5.378657487091222
|
||||
15,1548096878.0252109,0,0,15,58.2,319.9,94.06681282362852,41,119,426.8444927264001,29,5.3420000000000005,41,7.95,1.27,490,820,0,123.4,213.1,111,55.24,304.2,5,0,1,1,0,0,41.0,5.314061005420342,548.910348,947.9156820000001,39,319.9,5.314061005420342
|
||||
16,1548096880.0612912,0,0,16,60.0,329.3,95.37595742617708,40,120,409.81691239999986,30,5.27,42,8.03,1.27,490,840,0,110.4,193.6,111,58.2,319.9,5,0,10,0,0,0,40.0,5.242738806752646,491.08348800000016,861.175392,40,329.3,5.242738806752646
|
||||
|
BIN
Binary file not shown.
Vendored
+1
-1
@@ -2502,7 +2502,7 @@
|
||||
</Trackpoint>
|
||||
</Track>
|
||||
</Lap>
|
||||
<Notes><Element 'Notes' at 0x13f67128></Notes>
|
||||
<Notes><Element 'Notes' at 0x18ae8668></Notes>
|
||||
</Activity>
|
||||
</Activities>
|
||||
<Creator>
|
||||
|
||||
@@ -82,6 +82,27 @@ def matchchart(line):
|
||||
if tester3.match(line.lower()):
|
||||
return 'pieplot'
|
||||
|
||||
def matchuser(line):
|
||||
testert = '^(user)'
|
||||
tester = re.compile(testert)
|
||||
if tester.match(line.lower()):
|
||||
words = line.split()
|
||||
return words[1]
|
||||
|
||||
return None
|
||||
|
||||
def matchrace(line):
|
||||
testert = '^(race)'
|
||||
tester = re.compile(testert)
|
||||
if tester.match(line.lower()):
|
||||
words = line.split()
|
||||
try:
|
||||
return int(words[1])
|
||||
except:
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
def matchsync(line):
|
||||
results = []
|
||||
tester = '((sync)|(synchronization)|(export))'
|
||||
@@ -176,6 +197,22 @@ def getplotoptions_body2(uploadoptions,body):
|
||||
|
||||
return uploadoptions
|
||||
|
||||
def getuseroptions_body2(uploadoptions,body):
|
||||
for line in body.splitlines():
|
||||
user = matchuser(line)
|
||||
if user:
|
||||
uploadoptions['username'] = user
|
||||
|
||||
return uploadoptions
|
||||
|
||||
def getraceoptions_body2(uploadoptions,body):
|
||||
for line in body.splitlines():
|
||||
raceid = matchrace(line)
|
||||
if raceid:
|
||||
uploadoptions['raceid'] = raceid
|
||||
|
||||
return uploadoptions
|
||||
|
||||
def getsyncoptions_body2(uploadoptions,body):
|
||||
result = []
|
||||
for line in body.splitlines():
|
||||
@@ -261,6 +298,20 @@ def getboattype(uploadoptions,value,key):
|
||||
|
||||
return uploadoptions
|
||||
|
||||
def getuser(uploadoptions,value,key):
|
||||
uploadoptions['username'] = value
|
||||
|
||||
return uploadoptions
|
||||
|
||||
def getrace(uploadoptions,value,key):
|
||||
try:
|
||||
raceid = int(value)
|
||||
uploadoptions['raceid'] = raceid
|
||||
except:
|
||||
pass
|
||||
|
||||
return uploadoptions
|
||||
|
||||
def getsource(uploadoptions,value,key):
|
||||
workoutsource = 'unknown'
|
||||
for type,verb in workoutsources:
|
||||
@@ -306,6 +357,10 @@ def upload_options(body):
|
||||
uploadoptions = getboattype(uploadoptions,value,'boattype')
|
||||
if 'source' in lowkey:
|
||||
uploadoptions = getsource(uploadoptions,value,'workoutsource')
|
||||
if 'username' in lowkey:
|
||||
uploadoptions = getuser(uploadoptions,value,'username')
|
||||
if 'raceid' in lowkey:
|
||||
uploadoptions = getraceid(uploadoptions,value,'raceid')
|
||||
except AttributeError:
|
||||
#pass
|
||||
raise yaml.YAMLError
|
||||
@@ -317,6 +372,8 @@ def upload_options(body):
|
||||
uploadoptions = gettypeoptions_body2(uploadoptions,body)
|
||||
uploadoptions = getstravaid(uploadoptions,body)
|
||||
uploadoptions = getworkoutsources(uploadoptions,body)
|
||||
uploadoptions = getuseroptions_body2(uploadoptions,body)
|
||||
uploadoptions = getraceoptions_body2(uploadoptions,body)
|
||||
except IOError:
|
||||
pm = exc.problem_mark
|
||||
strpm = str(pm)
|
||||
|
||||
@@ -149,6 +149,7 @@ urlpatterns = [
|
||||
url(r'^indoorraceregistration/togglenotification/(?P<id>\d+)/$',
|
||||
views.indoorvirtualevent_toggle_email_view),
|
||||
url(r'^virtualevent/(?P<id>\d+)/$',views.virtualevent_view),
|
||||
url(r'^virtualevent/(?P<id>\d+)/ranking$',views.virtualevent_ranking_view),
|
||||
url(r'^virtualevent/(?P<id>\d+)/edit/$',views.virtualevent_edit_view),
|
||||
url(r'^virtualevent/(?P<id>\d+)/editindoor/$',views.indoorvirtualevent_edit_view),
|
||||
url(r'^virtualevent/(?P<id>\d+)/register/$',views.virtualevent_register_view),
|
||||
|
||||
+180
@@ -16128,6 +16128,186 @@ def virtualevent_view(request,id=0):
|
||||
'active':'nav-racing',
|
||||
})
|
||||
|
||||
def virtualevent_ranking_view(request,id=0):
|
||||
|
||||
results = []
|
||||
|
||||
if not request.user.is_anonymous():
|
||||
r = getrower(request.user)
|
||||
else:
|
||||
r = None
|
||||
|
||||
|
||||
try:
|
||||
race = VirtualRace.objects.get(id=id)
|
||||
except VirtualRace.DoesNotExist:
|
||||
raise Http404("Virtual Race does not exist")
|
||||
|
||||
if race.sessiontype == 'race':
|
||||
script,div = course_map(race.course)
|
||||
resultobj = VirtualRaceResult
|
||||
else:
|
||||
script = ''
|
||||
div = ''
|
||||
resultobj = IndoorVirtualRaceResult
|
||||
|
||||
records = resultobj.objects.filter(race=race)
|
||||
|
||||
|
||||
buttons = []
|
||||
|
||||
# to-do - add DNS
|
||||
dns = []
|
||||
if timezone.now() > race.evaluation_closure:
|
||||
dns = resultobj.objects.filter(
|
||||
race=race,
|
||||
workoutid__isnull=True,
|
||||
)
|
||||
|
||||
|
||||
if not request.user.is_anonymous():
|
||||
if race_can_register(r,race):
|
||||
buttons += ['registerbutton']
|
||||
|
||||
if race_can_adddiscipline(r,race):
|
||||
buttons += ['adddisciplinebutton']
|
||||
|
||||
if race_can_submit(r,race):
|
||||
buttons += ['submitbutton']
|
||||
|
||||
if race_can_resubmit(r,race):
|
||||
buttons += ['resubmitbutton']
|
||||
|
||||
if race_can_withdraw(r,race):
|
||||
buttons += ['withdrawbutton']
|
||||
|
||||
if race_can_edit(r,race):
|
||||
buttons += ['editbutton']
|
||||
|
||||
if request.method == 'POST':
|
||||
form = RaceResultFilterForm(request.POST,records=records)
|
||||
if form.is_valid():
|
||||
cd = form.cleaned_data
|
||||
try:
|
||||
sex = cd['sex']
|
||||
except KeyError:
|
||||
sex = ['female','male','mixed']
|
||||
|
||||
try:
|
||||
boattype = cd['boattype']
|
||||
except KeyError:
|
||||
boattype = mytypes.waterboattype
|
||||
|
||||
try:
|
||||
boatclass = cd['boatclass']
|
||||
except KeyError:
|
||||
if race.sessiontype == 'race':
|
||||
boatclass = [t for t in mytypes.otwtypes]
|
||||
else:
|
||||
boatclass = [t for t in mytypes.otetypes]
|
||||
|
||||
age_min = cd['age_min']
|
||||
age_max = cd['age_max']
|
||||
|
||||
try:
|
||||
weightcategory = cd['weightcategory']
|
||||
except KeyError:
|
||||
weightcategory = ['hwt','lwt']
|
||||
|
||||
try:
|
||||
adaptiveclass = cd['adaptiveclass']
|
||||
except KeyError:
|
||||
adaptiveclass = ['None','PR1','PR2','PR3','FES']
|
||||
|
||||
if race.sessiontype == 'race':
|
||||
results = resultobj.objects.filter(
|
||||
race=race,
|
||||
workoutid__isnull=False,
|
||||
boatclass__in=boatclass,
|
||||
boattype__in=boattype,
|
||||
sex__in=sex,
|
||||
weightcategory__in=weightcategory,
|
||||
adaptiveclass__in=adaptiveclass,
|
||||
age__gte=age_min,
|
||||
age__lte=age_max
|
||||
).order_by("duration")
|
||||
else:
|
||||
results = resultobj.objects.filter(
|
||||
race=race,
|
||||
workoutid__isnull=False,
|
||||
boatclass__in=boatclass,
|
||||
sex__in=sex,
|
||||
weightcategory__in=weightcategory,
|
||||
adaptiveclass__in=adaptiveclass,
|
||||
age__gte=age_min,
|
||||
age__lte=age_max
|
||||
).order_by("duration","-distance")
|
||||
|
||||
|
||||
# to-do - add DNS
|
||||
dns = []
|
||||
if timezone.now() > race.evaluation_closure:
|
||||
dns = resultobj.objects.filter(
|
||||
race=race,
|
||||
workoutid__isnull=True,
|
||||
boatclass__in=boatclass,
|
||||
sex__in=sex,
|
||||
weightcategory__in=weightcategory,
|
||||
adaptiveclass__in=adaptiveclass,
|
||||
age__gte=age_min,
|
||||
age__lte=age_max
|
||||
)
|
||||
else:
|
||||
results = resultobj.objects.filter(
|
||||
race=race,
|
||||
workoutid__isnull=False,
|
||||
coursecompleted=True,
|
||||
).order_by("duration","-distance")
|
||||
|
||||
if results:
|
||||
form = RaceResultFilterForm(records=records)
|
||||
else:
|
||||
form = None
|
||||
|
||||
|
||||
|
||||
breadcrumbs = [
|
||||
{
|
||||
'url':reverse(virtualevents_view),
|
||||
'name': 'Racing'
|
||||
},
|
||||
{
|
||||
'url':reverse(virtualevent_view,
|
||||
kwargs={'id':race.id}
|
||||
),
|
||||
'name': race.name
|
||||
}
|
||||
]
|
||||
|
||||
racelogos = race.logos.all()
|
||||
|
||||
if racelogos:
|
||||
racelogo = racelogos[0]
|
||||
else:
|
||||
racelogo = None
|
||||
|
||||
return render(request,'virtualeventranking.html',
|
||||
{
|
||||
'coursescript':script,
|
||||
'coursediv':div,
|
||||
'breadcrumbs':breadcrumbs,
|
||||
'race':race,
|
||||
'rower':r,
|
||||
'results':results,
|
||||
'buttons':buttons,
|
||||
'dns':dns,
|
||||
'records':records,
|
||||
'racelogo':racelogo,
|
||||
'form':form,
|
||||
'active':'nav-racing',
|
||||
})
|
||||
|
||||
|
||||
@login_required()
|
||||
def virtualevent_withdraw_view(request,id=0,recordid=None):
|
||||
r = getrower(request.user)
|
||||
|
||||
Reference in New Issue
Block a user