diff --git a/rowers/courses.py b/rowers/courses.py index 4d204100..25e87620 100644 --- a/rowers/courses.py +++ b/rowers/courses.py @@ -142,7 +142,6 @@ def kmltocourse(f): if not courses: courses = doc.findall('.//opengis:Placemark',ns) - if courses: return crewnerdcourse(courses) @@ -156,7 +155,7 @@ def kmltocourse(f): def createcourse( manager,name,polygons,notes=''): - + c = GeoCourse(manager=manager,name=name,notes=notes) c.save() @@ -192,7 +191,7 @@ def createcourse( c.distance = int(course_length(c)) c.save() - + return c diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 1f23f6ec..23294e2b 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -871,6 +871,8 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', # auto smoothing pace = row.df[' Stroke500mPace (sec/500m)'].values velo = 500. / pace + if workouttype == 'bikeerg': + velo = 1000. / pace f = row.df['TimeStamp (sec)'].diff().mean() if f != 0 and not np.isnan(f): diff --git a/rowers/dataprepnodjango.py b/rowers/dataprepnodjango.py index 229f6289..57f13d2f 100644 --- a/rowers/dataprepnodjango.py +++ b/rowers/dataprepnodjango.py @@ -1236,7 +1236,12 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True, engine = create_engine(database_url, echo=False) with engine.connect() as conn, conn.begin(): - data.to_sql('strokedata',engine,if_exists='append',index=False) + try: + data.to_sql('strokedata',engine,if_exists='append',index=False) + except OperationalError: + data.drop(columns=['rhythm'],inplace=True) + data.to_sql('strokedata',engine,if_exists='append',index=False) + conn.close() engine.dispose() return data diff --git a/rowers/tasks.py b/rowers/tasks.py index 420594bd..67910935 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -977,6 +977,39 @@ def handle_sendemailcsv(first_name, last_name, email, csvfile,**kwargs): return 1 +@app.task +def handle_sendemailfile(first_name, last_name, email, csvfile,**kwargs): + + + # send email with attachment + fullemail = first_name + " " + last_name + " " + "<" + email + ">" + subject = "File from Rowsandall.com" + + d = {'first_name':first_name, + 'siteurl':siteurl, + } + + from_email = 'Rowsandall ' + + + res = send_template_email(from_email,[fullemail], + subject,'fileemail.html',d, + attach_file=csvfile,**kwargs) + + + if 'delete' in kwargs: + dodelete = kwargs['delete'] + else: + dodelete = False + + if dodelete: + try: + os.remove(csvfile) + except: + pass + + return 1 + # Calculate wind and stream corrections for OTW rowing diff --git a/rowers/templates/fileemail.html b/rowers/templates/fileemail.html new file mode 100644 index 00000000..3094204b --- /dev/null +++ b/rowers/templates/fileemail.html @@ -0,0 +1,13 @@ +{% extends "emailbase.html" %} + +{% block body %} +

Dear {{ first_name }},

+ +

+ Please find attached the requested file from rowsandall.com +

+ +

+ Best Regards, the Rowsandall Team +

+{% endblock %} diff --git a/rowers/types.py b/rowers/types.py index a1781393..c6a2165c 100644 --- a/rowers/types.py +++ b/rowers/types.py @@ -2,6 +2,7 @@ workouttypes = ( ('water','Standard Racing Shell'), ('rower','Indoor Rower'), ('skierg','Ski Erg'), + ('bike','Bike Erg'), ('dynamic','Dynamic Indoor Rower'), ('slides','Indoor Rower on Slides'), ('paddle','Paddle Adapter'), diff --git a/rowers/uploads.py b/rowers/uploads.py index cf726ae2..2304e37d 100644 --- a/rowers/uploads.py +++ b/rowers/uploads.py @@ -394,60 +394,80 @@ def do_sync(w,options): w.save() except KeyError: pass - + if ('upload_to_C2' in options and options['upload_to_C2']) or (w.user.c2_auto_export and isprorower(w.user)): - try: - message,id = c2stuff.workout_c2_upload(w.user.user,w) - except NoTokenError: - id = 0 - message = "Something went wrong with the Concept2 sync" + if ('upload_to_C2' in options and not options['upload_to_C2']): + pass + else: + try: + message,id = c2stuff.workout_c2_upload(w.user.user,w) + except NoTokenError: + id = 0 + message = "Something went wrong with the Concept2 sync" if ('upload_to_Strava' in options and options['upload_to_Strava']) or (w.user.strava_auto_export and isprorower(w.user)): - try: - message,id = stravastuff.workout_strava_upload( - w.user.user,w - ) - except NoTokenError: - id = 0 - message = "Please connect to Strava first" + if ('upload_to_Strava' in options and not options['upload_to_Strava']): + pass + else: + try: + message,id = stravastuff.workout_strava_upload( + w.user.user,w + ) + except NoTokenError: + id = 0 + message = "Please connect to Strava first" if ('upload_to_SportTracks' in options and options['upload_to_SportTracks']) or (w.user.sporttracks_auto_export and isprorower(w.user)): - try: - message,id = sporttracksstuff.workout_sporttracks_upload( - w.user.user,w - ) - except NoTokenError: - message = "Please connect to SportTracks first" - id = 0 + if ('upload_to_SportTracks' in options and not options['upload_to_SportTracks']): + pass + else: + + try: + message,id = sporttracksstuff.workout_sporttracks_upload( + w.user.user,w + ) + except NoTokenError: + message = "Please connect to SportTracks first" + id = 0 if ('upload_to_RunKeeper' in options and options['upload_to_RunKeeper']) or (w.user.runkeeper_auto_export and isprorower(w.user)): - try: - message,id = runkeeperstuff.workout_runkeeper_upload( - w.user.user,w - ) - except NoTokenError: - message = "Please connect to Runkeeper first" - id = 0 + if ('upload_to_RunKeeper' in options and not options['upload_to_RunKeeper']): + pass + else: + + try: + message,id = runkeeperstuff.workout_runkeeper_upload( + w.user.user,w + ) + except NoTokenError: + message = "Please connect to Runkeeper first" + id = 0 if ('upload_to_MapMyFitness' in options and options['upload_to_MapMyFitness']) or (w.user.mapmyfitness_auto_export and isprorower(w.user)): - try: - message,id = underarmourstuff.workout_ua_upload( - w.user.user,w - ) - except NoTokenError: - message = "Please connect to MapMyFitness first" - id = 0 + if ('upload_to_MapMyFitness' in options and not options['upload_to_MapMyFitness']): + pass + else: + try: + message,id = underarmourstuff.workout_ua_upload( + w.user.user,w + ) + except NoTokenError: + message = "Please connect to MapMyFitness first" + id = 0 if ('upload_to_TrainingPeaks' in options and options['upload_to_TrainingPeaks']) or (w.user.trainingpeaks_auto_export and isprorower(w.user)): - try: - message,id = tpstuff.workout_tp_upload( - w.user.user,w - ) - except NoTokenError: - message = "Please connect to TrainingPeaks first" - id = 0 + if ('upload_to_TrainingPeaks' in options and not options['upload_to_TrainingPeaks']): + pass + else: + try: + message,id = tpstuff.workout_tp_upload( + w.user.user,w + ) + except NoTokenError: + message = "Please connect to TrainingPeaks first" + id = 0 return 1 diff --git a/rowers/urls.py b/rowers/urls.py index 12561aaa..9d294f9a 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -249,6 +249,7 @@ urlpatterns = [ url(r'^workout/(?P\d+)/emailgpx$',views.workout_gpxemail_view), url(r'^workout/(?P\d+)/emailcsv$',views.workout_csvemail_view), url(r'^workout/(?P\d+)/csvtoadmin$',views.workout_csvtoadmin_view), + url(r'^ergcpdatatoadmin/(?P\d+)/(?P\d+-\d+-\d+)/(?P\w+.*)$',views.otecp_toadmin_view), url(r'^workout/compare/(?P\d+)/$',views.workout_comparison_list), url(r'^workout/compare2/(?P\d+)/(?P\d+)/(?P\w+.*)/(?P\w+.*)/$',views.workout_comparison_view), url(r'^workout/compare/(?P\d+)/(?P\d+-\d+-\d+)/(?P\w+.*)$',views.workout_comparison_list), diff --git a/rowers/views.py b/rowers/views.py index 1d88d01f..a2a7bd28 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -132,6 +132,7 @@ from rowers.tasks import handle_makeplot,handle_otwsetpower,handle_sendemailtcx, from rowers.tasks import ( handle_sendemail_unrecognized,handle_sendemailnewcomment, handle_sendemailsummary, + handle_sendemailfile, handle_sendemailkml, handle_sendemailnewresponse, handle_updatedps, handle_updatecp,long_test_task,long_test_task2, @@ -4276,6 +4277,79 @@ def otwrankings_view(request,theuser=0, 'workouttype':'water', }) +@login_required() +def otecp_toadmin_view(request,theuser=0, + startdate=timezone.now()-datetime.timedelta(days=365), + enddate=timezone.now(), + startdatestring="", + enddatestring="", + ): + + if startdatestring != "": + try: + startdate = iso8601.parse_date(startdatestring) + except ParseError: + pass + + if enddatestring != "": + try: + enddate = iso8601.parse_date(enddatestring) + except ParseError: + pass + + if theuser == 0: + theuser = request.user.id + + r = Rower.objects.get(user=request.user) + + startdate = datetime.datetime.combine(startdate,datetime.time()) + enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59)) + + theworkouts = Workout.objects.filter( + user=r,rankingpiece=True, + workouttype__in=[ + 'rower', + 'dynamic', + 'slides' + ], + startdatetime__gte=startdate, + startdatetime__lte=enddate + ).order_by("-startdatetime") + + + delta,cpvalue,avgpower = dataprep.fetchcp( + r,theworkouts,table='cpergdata' + ) + + powerdf = pd.DataFrame({ + 'Delta':delta, + 'CP':cpvalue, + }) + + csvfilename = 'CP_data_user_{id}.csv'.format( + id = theuser + ) + + powerdf = powerdf[powerdf['CP']>0] + powerdf.dropna(axis=0,inplace=True) + powerdf.sort_values(['Delta','CP'],ascending=[1,0],inplace=True) + powerdf.drop_duplicates(subset='Delta',keep='first',inplace=True) + powerdf.to_csv(csvfilename) + + res = myqueue(queuehigh, + handle_sendemailfile, + 'Sander', + 'Roosendaal', + 'roosendaalsander@gmail.com', + csvfilename, + delete=True) + + successmessage = "The CSV file was sent to the site admin per email" + messages.info(request,successmessage) + response = HttpResponseRedirect('/rowers/list-workouts/') + + return response + # Show ranking distances including predicted paces @user_passes_test(ispromember,login_url="/",redirect_field_name=None) def oterankings_view(request,theuser=0, @@ -9893,6 +9967,9 @@ def workout_upload_view(request, except KeyError: upload_to_tp = False + + + response = {} if request.method == 'POST': form = DocumentsForm(request.POST,request.FILES) @@ -10040,7 +10117,7 @@ def workout_upload_view(request, request.session['async_tasks'] = [(jobid,'make_plot')] # upload to C2 - if (upload_to_c2) or (w.user.c2_auto_export and isprorower(w.user)): + if (upload_to_c2): try: message,id = c2stuff.workout_c2_upload(request.user,w) except NoTokenError: @@ -10051,7 +10128,7 @@ def workout_upload_view(request, else: messages.error(request,message) - if (upload_to_strava) or (w.user.strava_auto_export and isprorower(w.user)): + if (upload_to_strava): try: message,id = stravastuff.workout_strava_upload( request.user,w @@ -10064,7 +10141,7 @@ def workout_upload_view(request, else: messages.error(request,message) - if (upload_to_st) or (w.user.sporttracks_auto_export and isprorower(w.user)): + if (upload_to_st): try: message,id = sporttracksstuff.workout_sporttracks_upload( request.user,w @@ -10077,7 +10154,7 @@ def workout_upload_view(request, else: messages.error(request,message) - if (upload_to_rk) or (w.user.runkeeper_auto_export and isprorower(w.user)): + if (upload_to_rk): try: message,id = runkeeperstuff.workout_runkeeper_upload( request.user,w @@ -10092,7 +10169,7 @@ def workout_upload_view(request, messages.error(request,message) - if (upload_to_ua) or (w.user.mapmyfitness_auto_export and isprorower(w.user)): + if (upload_to_ua): try: message,id = underarmourstuff.workout_ua_upload( request.user,w @@ -10107,7 +10184,7 @@ def workout_upload_view(request, messages.error(request,message) - if (upload_to_tp) or (w.user.trainingpeaks_auto_export and isprorower(w.user)): + if (upload_to_tp): try: message,id = tpstuff.workout_tp_upload( request.user,w @@ -10150,6 +10227,24 @@ def workout_upload_view(request, return response else: if not is_ajax: + if r.c2_auto_export and isprorower(r): + uploadoptions['upload_to_C2'] = True + + if r.strava_auto_export and isprorower(r): + uploadoptions['upload_to_Strava'] = True + + if r.sporttracks_auto_export and isprorower(r): + uploadoptions['upload_to_SportTracks'] = True + + if r.runkeeper_auto_export and isprorower(r): + uploadoptions['upload_to_RunKeeper'] = True + + if r.trainingpeaks_auto_export and isprorower(r): + uploadoptions['upload_to_TrainingPeaks'] = True + + if r.mapmyfitness_auto_export and isprorower(r): + uploadoptions['upload_to_MapMyFitness'] = True + form = DocumentsForm(initial=docformoptions) optionsform = UploadOptionsForm(initial=uploadoptions) return render(request, 'document_form.html',