diff --git a/rowers/datautils.py b/rowers/datautils.py index bff11450..7f8c1af4 100644 --- a/rowers/datautils.py +++ b/rowers/datautils.py @@ -452,7 +452,7 @@ def getfastest(df,thevalue,mode='distance'): starttime = griddata(restime,starttimes,[thevalue*60*1000],method='linear',rescale=True) duration = griddata(restime,restime,[thevalue*60*1000],method='linear',rescale=True) endtime = starttime+duration - #print(distance,starttime,endtime ) + print(distance,starttime,endtime ) return distance[0],starttime[0]/1000.,endtime[0]/1000. return 0 diff --git a/rowers/forms.py b/rowers/forms.py index dba009c4..eff14e8a 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -15,7 +15,7 @@ from rowers.rows import validate_file_extension,must_be_csv,validate_image_exten from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from django.contrib.admin.widgets import AdminDateWidget -from django.forms.widgets import SelectDateWidget +from django.forms.widgets import SelectDateWidget,HiddenInput #from django.forms.extras.widgets import SelectDateWidget from django.utils import timezone,translation from django.forms import ModelForm, Select @@ -410,6 +410,8 @@ class UploadOptionsForm(forms.Form): initial='workout_edit_view', label='After Upload, go to') + raceid = forms.IntegerField(initial=0,widget=HiddenInput()) + class Meta: fields = ['make_plot','plottype','upload_toc2','makeprivate'] @@ -448,6 +450,7 @@ class UploadOptionsForm(forms.Form): if int(raceid) in [r.id for r in races]: therace = VirtualRace.objects.get(id=raceid) + self.fields['raceid'].initial = therace.id if therace.sessiontype == 'race': registrations = VirtualRaceResult.objects.filter(race=therace,userid=r.id) else: diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index b0ac380b..77cf6117 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -371,7 +371,7 @@ def add_workouts_plannedsession(ws,ps,r): ids = [w.id for w in wold] + [w.id for w in ws] ids = list(set(ids)) - if len(ids)>1 and ps.sessiontype in ['test','coursetest','race','fastest_distance','fastest_time']: + if len(ids)>1 and ps.sessiontype in ['test','coursetest','race']: errors.append('For tests, you can only attach one workout') return result,comments,errors @@ -1496,23 +1496,33 @@ def default_class(r,w,race): boatclass=boatclass, adaptiveclass=adaptiveclass, boattype=boattype, + sex=sex, ).order_by( "agemax","-agemin","boattype","sex","weightclass", "referencespeed" ) if standards.count()==0: + # omit adaptive class standards = CourseStandard.objects.filter( agemin__lt=age,agemax__gt=age, - boattype=boattype + boattype=boattype,sex=sex, ).order_by( "agemax","-agemin","boattype","sex", "weightclass","referencespeed") if standards.count()==0: + # omit boattype standards = CourseStandard.objects.filter( - agemin__lt=age,agemax__gt=age + agemin__lt=age,agemax__gt=age,sex=sex, ).order_by( "agemax","-agemin","boattype","sex", "weightclass","referencespeed") + if standards.count()==0: + # omit boattype + standards = CourseStandard.objects.filter( + agemin__lt=age,agemax__gt=age,sex='male', + ).order_by( + "agemax","-agemin","boattype","sex", + "weightclass","referencespeed") if standards.count()==0: # boolean, boattype, boatclass, adaptiveclass, weightclass, sex, coursestandard, @@ -1526,6 +1536,153 @@ def default_class(r,w,race): # No Course Standard return True,boattype,boatclass,adaptiveclass,weightclass,sex,5.0,None +def add_workout_fastestrace(ws, race, r, recordid=0, doregister=False): + result = 0 + comments = [] + errors = [] + + start_time = race.start_time + start_date = race.startdate + startdatetime = datetime.combine(start_date,start_time) + startdatetime = pytz.timezone(race.timezone).localize( + startdatetime + ) + + end_time = race.end_time + end_date = race.enddate + enddatetime = datetime.combine(end_date,end_time) + enddatetime = pytz.timezone(race.timezone).localize( + enddatetime + ) + + ids = [w.id for w in ws] + ids = list(set(ids)) + + if len(ids)>1 and race.sessiontype in ['test','coursetest','race','indoorrace','fastest_time','fastest_distance']: + errors.append('For tests, you can only attach one workout') + return result,comments,errors,0 + + username = r.user.first_name+' '+r.user.last_name + if r.birthdate: + age = calculate_age(r.birthdate) + else: + age = None + + try: + record = IndoorVirtualRaceResult.objects.get( + userid=r.id, + race=race, + id=recordid + ) + except IndoorVirtualRaceResult.DoesNotExist: + if doregister: + hasinitial,boattype,boatclass,adaptiveclass,weightclass,sex,referencespeed,initialcategory = default_class(r,ws[0],race) + if hasinitial: + record = IndoorVirtualRaceResult( + userid = r.id, + username = r.user.first_name+' '+r.user.last_name, + weightcategory=weightclass, + adaptiveclass=adaptiveclass, + race=race, + boatclass=boatclass, + sex=sex, + age = age, + referencespeed=referencespeed, + entrycategory=initialcategory, + ) + record.save() + else: + errors.append("Unable to find a suitable start category") + return result,comments,errors,0 + else: + errors.append("Couldn't find this entry") + return result,comments,errors,0 + + records = IndoorVirtualRaceResult.objects.filter( + userid=r.id, + race=race, + workoutid = ws[0].id + ) + + if ws[0].workouttype != record.boatclass: + errors.append('Your workout boat class is different than on your race registration') + return 0,comments,errors,0 + + if ws[0].workouttype not in mytypes.otwtypes: + errors.append('You must submit a on-the-water rowing workout') + return 0,comments, errors, 0 + + if record.weightcategory == 'lwt' and ws[0].weightcategory != record.weightcategory: + errors.append('Your workout weight category did not match the weight category you registered') + return 0,comments, errors,0 + + if ws[0].adaptiveclass != record.adaptiveclass: + errors.append('Your adaptive classification did not match the registration') + return 0,comments, errors, 0 + + # start adding sessions + if ws[0].startdatetime>=startdatetime and ws[0].startdatetime<=enddatetime: + ws[0].plannedsession = race + ws[0].save() + result += 1 + + else: + errors.append('Workout %i did not match the race window' % ws[0].id) + return result,comments,errors,0 + + if result>0: + for otherrecord in records: + otherrecord.workoutid = None + otherrecord.coursecompleted = False + otherrecord.save() + + result, comment, errors = add_workouts_plannedsession(ws,race,r) + if result: + record.coursecompleted = True + record.workoutid = ws[0].id + if race.sessiontype == 'fastest_distance': + df = dataprep.getsmallrowdata_db(['time','cumdist'],ids=[ws[0].id]) + fastest_milliseconds,startsecond,endsecond = datautils.getfastest(df,race.sessionvalue,mode='distance') + velo = race.sessionvalue/fastest_milliseconds + points = 100.*velo/record.referencespeed + + if fastest_milliseconds > 0: + duration = to_time(1000.*fastest_milliseconds) + record.coursecompleted = True + record.duration = duration + record.distance = race.sessionvalue + record.points = points + record.startsecond = startsecond + record.endsecond = endsecond + record.save() + if race.sessiontype == 'fastest_time': + df = dataprep.getsmallrowdata_db(['time','cumdist'],ids=[ws[0].id]) + fastest_meters, startsecond, endsecond = datautils.getfastest(df,race.sessionvalue,mode='time') + velo = fastest_meters/(60.*race.sessionvalue) + points = 100.*velo/record.referencespeed + + if fastest_meters > 0: + duration = dt.time(0,race.sessionvalue) + record.duration = duration + record.distance = fastest_meters + record.coursecompleted = True + record.points = points + record.startsecond = startsecond + record.endsecond = endsecond + record.save() + + + + if ws[0].privacy == 'private': + ws[0].privacy = 'visible' + ws[0].save() + comments.append('Workouts submitted to virtual events have to be public. We have changed the workout to a public workout.') + + record.save() + else: + errors.append('Could not find a valid interval in this workout') + + return result, comments, errors, 0 # Low Level functions - to be called by higher level methods diff --git a/rowers/templates/fastestvirtualeventcreate.html b/rowers/templates/fastestvirtualeventcreate.html index 7034c3f3..d577973e 100644 --- a/rowers/templates/fastestvirtualeventcreate.html +++ b/rowers/templates/fastestvirtualeventcreate.html @@ -55,7 +55,11 @@ The participants can row this challenge on any course, and their fastest time over the challenge distance (respectively the largest distance achieved over the challenge duration) is automatically extracted from the workout. No +<<<<<<< HEAD + need to program a set piece. +======= need to program a set piece. +>>>>>>> develop
Standard Times are a way to compare results in a race category with diff --git a/rowers/templates/menu_racing.html b/rowers/templates/menu_racing.html index 4ebd5e26..2c04ced0 100644 --- a/rowers/templates/menu_racing.html +++ b/rowers/templates/menu_racing.html @@ -6,15 +6,10 @@
+ On-the-water challenge with a course. You have to row through + all the gates on the course to create a valid entry. Ideal for + local challenges. +
+
+ On-the-water challenge over a set time or distance. This can be rowed + on any body of water in the world. Ideal to create a global on-the-water + challenge. +
+
+ Indoor rowing challenge over a set time or distance. This can be rowed + on any indoor rowing machine. Dial up the given distance or time and row! + Ideal to create a global indoor rowing + challenge. +
++ This on-the-water challenge asks you to try to get + as far as you can over the + race duration. It automatically finds the fastest interval + of the given duration + in your entire workout. +
+ {% elif race.sessiontype == 'fastest_distance' %} ++ This on-the-water challenge asks you to try row as hard + as you can over a set distance. + It automatically finds the fastest interval of the given length + in your entire workout. +
{% else %}
Indoor challenges are open for all, wherever you live.
diff --git a/rowers/urls.py b/rowers/urls.py
index f67379d8..b2d003a4 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -260,8 +260,11 @@ urlpatterns = [
# re_path(r'^list-workouts/(?P