Private
Public Access
1
0
Files
rowsandall/rowers/tasks.py
Sander Roosendaal 4063b88d53 some bug fixes
2019-09-22 08:56:15 +02:00

2304 lines
61 KiB
Python

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
""" Background tasks done by Celery (develop) or QR (production) """
import os
import time
import gc
import gzip
import shutil
import numpy as np
import re
from scipy import optimize
from scipy.signal import savgol_filter
import rowingdata
from rowingdata import rowingdata as rdata
from datetime import timedelta
from sqlalchemy import create_engine
#from celery import app
from rowers.celery import app
from celery import shared_task
import datetime
import pytz
import iso8601
from matplotlib.backends.backend_agg import FigureCanvas
#from matplotlib.backends.backend_cairo import FigureCanvasCairo as FigureCanvas
import matplotlib.pyplot as plt
from matplotlib import path
from rowsandall_app.settings import SITE_URL
from rowsandall_app.settings_dev import SITE_URL as SITE_URL_DEV
from rowsandall_app.settings import PROGRESS_CACHE_SECRET
from rowsandall_app.settings import SETTINGS_NAME
from rowsandall_app.settings import workoutemailbox
import pandas as pd
from django_rq import job
from django.utils import timezone
from django.utils.html import strip_tags
from rowers.utils import deserialize_list,ewmovingaverage,wavg
from rowers.emails import htmlstrip
#from HTMLParser import HTMLParser
from html.parser import HTMLParser
class MLStripper(HTMLParser):
def __init__(self):
self.reset()
self.fed = []
def handle_data(self, d):
self.fed.append(d)
def get_data(self):
return ''.join(self.fed)
def strip_tags(html):
s = MLStripper()
s.feed(html)
return s.get_data()
from rowers.dataprepnodjango import (
update_strokedata, new_workout_from_file,
getsmallrowdata_db, updatecpdata_sql,
update_agegroup_db,fitnessmetric_to_sql,
add_c2_stroke_data_db,totaltime_sec_to_string,
create_c2_stroke_data_db,update_empower,
database_url_debug,database_url,dataprep,
# create_strava_stroke_data_db
)
from rowers.opaque import encoder
from django.core.mail import (
send_mail,
EmailMessage,EmailMultiAlternatives,
)
from django.template import Context
from django.db.utils import OperationalError
from jinja2 import Template,Environment,FileSystemLoader
env = Environment(loader = FileSystemLoader(["rowers/templates"]))
import rowers.datautils as datautils
import rowers.utils as utils
import requests
import rowers.longtask as longtask
import arrow
from rowers.utils import get_strava_stream
def safetimedelta(x):
try:
return timedelta(seconds=x)
except ValueError:
return timedelta(seconds=0)
siteurl = SITE_URL
# testing task
from rowers.emails import send_template_email
from rowers.courseutils import coursetime_paths, coursetime_first, time_in_path
@app.task
def add(x, y):
return x + y
@app.task
def handle_c2_import_stroke_data(c2token,
c2id,workoutid,
starttimeunix,
csvfilename,debug=True,**kwargs):
if 'workouttype' in kwargs:
workouttype = kwargs['workouttype']
else:
workouttype = 'rower'
authorizationstring = str('Bearer ' + c2token)
headers = {'Authorization': authorizationstring,
'user-agent': 'sanderroosendaal',
'Content-Type': 'application/json'}
url = "https://log.concept2.com/api/users/me/results/"+str(c2id)+"/strokes"
s = requests.get(url,headers=headers)
if s.status_code == 200:
strokedata = pd.DataFrame.from_dict(s.json()['data'])
result = add_c2_stroke_data_db(
strokedata,workoutid,starttimeunix,
csvfilename,debug=debug,workouttype=workouttype
)
return 1
else:
url = "https://log.concept2.com/api/users/me/results/{id}".format(id=c2id)
s = requests.get(url,headers=headers)
if s.status_code == 200:
workoutdata = s.json()['data']
distance = workoutdata['distance']
c2id = workoutdata['id']
workouttype = workoutdata['type']
verified = workoutdata['verified']
startdatetime = iso8601.parse_date(workoutdata['date'])
weightclass = workoutdata['weight_class']
weightcategory = 'hwt'
if weightclass == "L":
weightcategory = 'lwt'
totaltime = workoutdata['time']/10.
duration = totaltime_sec_to_string(totaltime)
duration = datetime.datetime.strptime(duration,'%H:%M:%S.%f').time()
try:
timezone_str = tz(workoutdata['timezone'])
except:
timezone_str = 'UTC'
workoutdate = startdatetime.astimezone(
pytz.timezone(timezone_str)
).strftime('%Y-%m-%d')
starttime = startdatetime.astimezone(
pytz.timezone(timezone_str)
).strftime('%H:%M:%S')
result = create_c2_stroke_data_db(
distance,duration,workouttype,
workoutid,starttimeunix,
csvfilename,debug=debug,
)
return 1
return 0
return 0
def getagegrouprecord(age,sex='male',weightcategory='hwt',
distance=2000,duration=None,indf=pd.DataFrame()):
if not duration:
df = indf[indf['distance'] == distance]
else:
duration = 60*int(duration)
df = indf[indf['duration'] == duration]
if not df.empty:
ages = df['age']
powers = df['power']
#poly_coefficients = np.polyfit(ages,powers,6)
fitfunc = lambda pars, x: np.abs(pars[0])*(1-x/max(120,pars[1]))-np.abs(pars[2])*np.exp(-x/np.abs(pars[3]))+np.abs(pars[4])*(np.sin(np.pi*x/max(50,pars[5])))
errfunc = lambda pars, x,y: fitfunc(pars,x)-y
p0 = [700,120,700,10,100,100]
p1, success = optimize.leastsq(errfunc,p0[:],
args = (ages,powers))
if success:
power = fitfunc(p1, float(age))
#power = np.polyval(poly_coefficients,age)
power = 0.5*(np.abs(power)+power)
else:
power = 0
else:
power = 0
return power
def polygon_to_path(polygon,debug=True):
pid = polygon[0]
query = "SELECT id, latitude, longitude FROM rowers_geopoint WHERE polygon_id = {pid} ORDER BY order_in_poly ASC".format(
pid=pid
)
if debug:
engine = create_engine(database_url_debug, echo=False)
else:
engine = create_engine(database_url, echo=False)
with engine.connect() as conn, conn.begin():
result = conn.execute(query)
points = result.fetchall()
conn.close()
engine.dispose()
s = []
for point in points:
s.append([point[1],point[2]])
p = path.Path(s[:-1])
return p
@app.task(bind=True)
def handle_check_race_course(self,
f1,workoutid,courseid,
recordid,**kwargs):
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = False
if 'splitsecond' in kwargs:
splitsecond = kwargs['splitsecond']
else:
splitsecond = 0
mode = 'race'
if 'mode' in kwargs:
mode = kwargs['mode']
columns = ['time',' latitude',' longitude','cum_dist']
try:
row = rdata(csvfile=f1)
except IOError:
try:
row = rdata(csvfile=f1 + '.csv')
except IOError:
try:
row = rdata(csvfile=f1 + '.gz')
except IOError:
return 0
rowdata = row.df
try:
s = rowdata[' latitude']
except KeyError:
return 0
rowdata.rename(columns = {
' latitude':'latitude',
' longitude':'longitude',
'TimeStamp (sec)': 'time',
}, inplace=True)
rowdata.fillna(method='backfill',inplace=True)
rowdata['time'] = rowdata['time']-rowdata.ix[0,'time']
rowdata = rowdata[rowdata['time']>splitsecond]
# we may want to expand the time (interpolate)
rowdata['dt'] = rowdata['time'].apply(
lambda x: safetimedelta(x)
)
rowdata = rowdata.resample('100ms',on='dt').mean()
rowdata = rowdata.interpolate()
# initiate database engine
if debug:
engine = create_engine(database_url_debug, echo=False)
else:
engine = create_engine(database_url, echo=False)
# get polygons
query = "SELECT id FROM rowers_geopolygon WHERE course_id = {courseid} ORDER BY order_in_course ASC".format(
courseid=courseid
)
with engine.connect() as conn, conn.begin():
result = conn.execute(query)
polygons = result.fetchall()
conn.close()
engine.dispose()
paths = []
for polygon in polygons:
path = polygon_to_path(polygon,debug=debug)
paths.append(path)
# check how many times went through start polygon
entrytimes,entrydistances = time_in_path(rowdata,paths[0],maxmin='max',getall=True)
cseconds = []
cmeters = []
ccomplete = []
for startt in entrytimes:
rowdata2 = rowdata[rowdata['time']>(startt-10.)]
(
coursetimeseconds,
coursemeters,
coursecompleted,
) = coursetime_paths(rowdata2,paths)
(
coursetimefirst,
coursemetersfirst,
firstcompleted
) = coursetime_first(
rowdata2,paths)
coursetimeseconds = coursetimeseconds-coursetimefirst
coursemeters = coursemeters-coursemetersfirst
cseconds.append(coursetimeseconds)
cmeters.append(coursemeters)
ccomplete.append(coursecompleted)
records = pd.DataFrame({
'coursetimeseconds':cseconds,
'coursecompleted': ccomplete,
'coursemeters': cmeters
})
records = records[records['coursecompleted'] == True]
if len(records):
coursecompleted = True
mintime = records['coursetimeseconds'].min()
coursetimeseconds = records[records['coursetimeseconds'] == mintime]['coursetimeseconds'].min()
coursemeters = records[records['coursetimeseconds'] == mintime]['coursemeters'].min()
else:
coursecompleted = False
if coursecompleted:
query = 'UPDATE rowers_virtualraceresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid} WHERE id={recordid}'.format(
recordid=recordid,
duration=totaltime_sec_to_string(coursetimeseconds),
distance=int(coursemeters),
workoutid=workoutid,
)
if mode == 'coursetest':
query = 'UPDATE rowers_coursetestresult SET coursecompleted = 1, duration = "{duration}", distance = {distance}, workoutid = {workoutid} WHERE id={recordid}'.format(
recordid=recordid,
duration=totaltime_sec_to_string(coursetimeseconds),
distance=int(coursemeters),
workoutid=workoutid,
)
with engine.connect() as conn, conn.begin():
result = conn.execute(query)
conn.close()
engine.dispose()
return 1
else:
return 2
return 0
@app.task(bind=True)
def handle_getagegrouprecords(self,
df,
distances,durations,
age,sex,weightcategory,
**kwargs):
wcdurations = []
wcpower = []
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = False
df = pd.read_json(df)
if sex == 'not specified':
return 0
for distance in distances:
worldclasspower = getagegrouprecord(
age,
sex=sex,
distance=distance,
weightcategory=weightcategory,indf=df,
)
velo = (worldclasspower/2.8)**(1./3.)
if not np.isinf(worldclasspower) and not np.isnan(worldclasspower):
try:
duration = distance/velo
wcdurations.append(duration)
wcpower.append(worldclasspower)
except ZeroDivisionError:
pass
for duration in durations:
worldclasspower = getagegrouprecord(
age,
sex=sex,
duration=duration,
weightcategory=weightcategory,indf=df
)
if not np.isinf(worldclasspower) and not np.isnan(worldclasspower):
try:
velo = (worldclasspower/2.8)**(1./3.)
distance = int(60*duration*velo)
wcdurations.append(60.*duration)
wcpower.append(worldclasspower)
except ValueError:
pass
update_agegroup_db(age,sex,weightcategory,wcdurations,wcpower,
debug=debug)
return 1
@app.task(bind=True)
def long_test_task(self,aantal,debug=False,job=None,session_key=None):
job = self.request
return longtask.longtask(aantal,jobid=job.id,debug=debug,
session_key=session_key)
@app.task(bind=True)
def long_test_task2(self,aantal,**kwargs):
#debug=False,job=None,jobid='aap'):
job = self.request
job_id = job.id
if 'jobkey' in kwargs:
job_id = kwargs.pop('jobkey')
kwargs['jobid'] = job_id
return longtask.longtask2(aantal,**kwargs)
# create workout
@app.task
def handle_new_workout_from_file(r, f2,
workouttype='rower',
boattype='1x',
makeprivate=False,
notes='',debug=False):
return new_workout_from_file(r, f2, workouttype,
title, makeprivate, notes)
# process and update workouts
@app.task(bind=True)
def handle_update_empower(self,
useremail,
workoutdicts,
debug=False, **kwargs):
job = self.request
job_id = job.id
if 'jobkey' in kwargs:
job_id = kwargs.pop('jobkey')
aantal = len(workoutdicts)
counter = 0
for workoutdict in workoutdicts:
wid = workoutdict['id']
inboard = workoutdict['inboard']
oarlength = workoutdict['oarlength']
boattype = workoutdict['boattype']
f1 = workoutdict['filename']
# oarlength consistency checks will be done in view
havedata = 1
try:
rowdata = rdata(csvfile=f1)
except IOError:
try:
rowdata = rdata(csvfile=f1 + '.csv')
except IOError:
try:
rowdata = rdata(csvfile=f1 + '.gz')
except IOError:
havedata = 0
progressurl = SITE_URL
siteurl = SITE_URL
if debug:
progressurl = SITE_URL_DEV
siteurl = SITE_URL_DEV
secret = PROGRESS_CACHE_SECRET
kwargs['job_id'] = job_id
progressurl += "/rowers/record-progress/"
progressurl += job_id
if havedata:
success = update_empower(wid, inboard, oarlength, boattype,
rowdata.df, f1, debug=debug)
counter += 1
progress = 100.*float(counter)/float(aantal)
post_data = {
"secret":secret,
"value":progress,
}
s = requests.post(progressurl, data=post_data)
status_code = s.status_code
subject = "Rowsandall.com Your Old Empower Oarlock data have been corrected"
message = """
We have updated Power and Work per Stroke data according to the instructions by Nielsen-Kellerman.
"""
email = EmailMessage(subject, message,
'Rowsandall <info@rowsandall.com>',
[useremail])
if 'emailbounced' in kwargs:
emailbounced = kwargs['emailbounced']
else:
emailbounced = False
if not emailbounced:
res = email.send()
return 1
@app.task
def handle_calctrimp(id,
csvfilename,
ftp,
sex,
hrftp,
hrmax,
hrmin,
debug=False, **kwargs):
if debug:
engine = create_engine(database_url_debug, echo=False)
else:
engine = create_engine(database_url, echo=False)
try:
rowdata = rdata(csvfile=csvfilename)
except IOError:
try:
rowdata = rdata(csvfile=csvfilename + '.csv')
except IOError:
try:
rowdata = rdata(csvfile=csvfilename + '.gz')
except IOError:
return 0
df = rowdata.df
try:
df['deltat'] = df[' ElapsedTime (sec)'].diff().abs()
except KeyError:
return 0
df2 = df.copy()
df2['time'] = df2[' ElapsedTime (sec)']
df2['time'] = df2['time'].apply(
lambda x:safetimedelta(x)
)
duration = df['TimeStamp (sec)'].max()-df['TimeStamp (sec)'].min()
df2 = df2.resample('1s',on='time').mean()
df2.fillna(method='ffill',inplace=True)
df2 = df2.rolling(30).mean()
df2[' Power (watts)'] = df2[' Power (watts)'].abs()
df2['pwr4'] = df2[' Power (watts)']**(4.0)
# pwr4mean = wavg(df,'pwr4','deltat')
pwr4mean = df2['pwr4'].mean()
pwrmean = df2[' Power (watts)'].mean()
# pwrmean = wavg(df,' Power (watts)','deltat')
if pwr4mean > 0:
normp = (pwr4mean)**(0.25)
else:
normp = pwrmean
intensityfactor = normp/float(ftp)
tss = 100.*((duration*normp*intensityfactor)/(3600.*ftp))
if sex == 'male':
f = 1.92
else:
f = 1.67
dt = df['TimeStamp (sec)'].diff()/60.
hrr = (df[' HRCur (bpm)']-hrmin)/(hrmax-hrmin)
hrrftp = (hrftp-hrmin)/float(hrmax-hrmin)
trimp1hr = 60.*hrrftp*0.64*np.exp(f*hrrftp)
trimpdata = dt*hrr*0.64*np.exp(f*hrr)
trimp = trimpdata.sum()
hrtss = 100.*trimp/trimp1hr
pp = 8.0
df['v4'] = df[' AverageBoatSpeed (m/s)']**(pp)
v4mean = wavg(df,'v4','deltat')
normv = v4mean**(1./pp)
try:
df['w4'] = df['driveenergy']**(pp)
w4mean = wavg(df,'w4','deltat')
normw = w4mean**(1./pp)
except KeyError:
normw = 0
if not np.isfinite(normv):
normv = 500./120.
if not np.isfinite(normw):
normw = 0
try:
dum = int(tss)
except ValueError:
tss = 0
try:
dum = int(normp)
except ValueError:
normp = 0
try:
dump = int(trimp)
except ValueError:
trimp = 0
try:
dump = int(hrtss)
except ValueError:
hrtss = 0
query = 'UPDATE rowers_workout SET rscore = {tss}, normp = {normp}, trimp={trimp}, hrtss={hrtss}, normv={normv}, normw={normw} WHERE id={id}'.format(
tss = int(tss),
normp = int(normp),
trimp = int(trimp),
hrtss = int(hrtss),
normv=normv,
normw=normw,
id = id,
)
with engine.connect() as conn, conn.begin():
result = conn.execute(query)
conn.close()
engine.dispose()
return 1
@app.task
def handle_updatedps(useremail, workoutids, debug=False,**kwargs):
for wid, f1 in workoutids:
havedata = 1
try:
rowdata = rdata(csvfile=f1)
except IOError:
try:
rowdata = rdata(csvfile=f1 + '.csv')
except IOError:
try:
rowdata = rdata(csvfile=f1 + '.gz')
except IOError:
havedata = 0
if havedata:
update_strokedata(wid, rowdata.df, debug=debug)
subject = "Rowsandall.com Your Distance per Stroke metric has been updated"
message = "All your workouts now have Distance per Stroke"
email = EmailMessage(subject, message,
'Rowsandall <info@rowsandall.com>',
[useremail])
if 'emailbounced' in kwargs:
emailbounced = kwargs['emailbounced']
else:
emailbounced = False
if not emailbounced:
res = email.send()
return 1
import math
def sigdig(value, digits = 3):
try:
order = int(math.floor(math.log10(math.fabs(value))))
except (ValueError,TypeError):
return value
# return integers as is
if value % 1 == 0:
return value
places = digits - order - 1
if places > 0:
fmtstr = "%%.%df" % (places)
else:
fmtstr = "%.0f"
return fmtstr % (round(value, places))
@app.task
def handle_send_email_alert(
useremail, userfirstname, userlastname, rowerfirstname, alertname, stats, **kwargs):
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = False
if 'othertexts' in kwargs:
othertexts = kwargs['othertexts']
else:
othertexts = None
report = {}
try:
report['Percentage'] = int(stats['percentage'])
except KeyError:
pass
try:
report['Number of workouts'] = int(stats['workouts'])
except KeyError:
pass
try:
report['Data set'] = "{a} strokes out of {b}".format(
a = stats['nr_strokes_qualifying'],
b = stats['nr_strokes']
)
except KeyError:
pass
try:
report['Median'] = sigdig(stats['median'])
except KeyError:
pass
try:
report['Median of qualifying strokes'] = sigdig(stats['median_q'])
except KeyError:
pass
subject = "Rowsandall.com: {alertname} ({startdate} to {enddate})".format(
startdate = stats['startdate'],
enddate = stats['enddate'],
alertname=alertname,
)
from_email = 'Rowsandall <info@rowsandall.com>'
d = {
'report':report,
'first_name':userfirstname,
'last_name':userlastname,
'siteurl':siteurl,
'rowerfirstname':rowerfirstname,
'alertname':alertname,
'othertexts':othertexts,
}
res = send_template_email(from_email,[useremail],subject,
'alertemail.html',
d,**kwargs)
return 1
@app.task
def handle_send_email_transaction(
username, useremail, amount, **kwargs):
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = True
subject = "Rowsandall Payment Confirmation"
from_email = 'Rowsandall <admin@rowsandall.com>'
d = {
'name': username,
'siteurl': siteurl,
'amount': amount
}
res = send_template_email(from_email,[useremail],
subject,
'paymentconfirmationemail.html',
d, **kwargs)
return 1
@app.task
def handle_send_email_failed_cancel(
name, email, username, id, **kwargs):
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = True
subject = "Rowsandall Subscription Cancellation Error"
from_email = 'Rowsandall <admin@rowsandall.com>'
d = {
'name': name,
'siteurl': siteurl,
'email': email,
'username': username,
'id': id,
}
res = send_template_email(from_email,["support@rowsandall.com"],
subject,
'cancel_subscription_fail_email.html',
d, **kwargs)
return 1
@app.task
def handle_send_email_subscription_update(
username, useremail, planname, recurring, price, amount,
end_of_billing_period, method, **kwargs):
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = True
from_email = 'Rowsandall <admin@rowsandall.com>'
d = {
'name': username,
'siteurl': siteurl,
'amount': amount,
'price':price,
'planname': planname,
'recurring': recurring,
'end_of_billing_period': end_of_billing_period,
}
if method == 'down':
template_name = 'subscription_downgrade_email.html'
notification_template_name = 'subscription_downgrade_notification.html'
subject = "Rowsandall Change Confirmation"
else:
template_name = 'subscription_update_email.html'
notification_template_name = 'subscription_update_notification.html'
subject = "Rowsandall Payment Confirmation"
res = send_template_email(from_email,[useremail],
subject,
template_name,
d, **kwargs)
res = send_template_email(from_email,['info@rowsandall.com'],
'Subscription Update Notification',
notification_template_name,
d, **kwargs)
return 1
@app.task
def handle_send_email_subscription_create(
username, useremail, planname, recurring, price, amount,
end_of_billing_period, **kwargs):
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = True
subject = "Rowsandall Payment Confirmation"
from_email = 'Rowsandall <admin@rowsandall.com>'
d = {
'name': username,
'siteurl': siteurl,
'amount': amount,
'price':price,
'planname': planname,
'end_of_billing_period': end_of_billing_period,
'recurring': recurring,
}
res = send_template_email(from_email,[useremail],
subject,
'subscription_create_email.html',
d, **kwargs)
res = send_template_email(from_email,['info@rowsandall.com'],
'Subscription Update Notification',
'subscription_create_notification.html',
d, **kwargs)
return 1
@app.task
def handle_sendemail_raceregistration(
useremail, username, registeredname, racename, raceid, **kwargs):
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = True
subject = "A new competitor has registered for virtual race {n}".format(
n = racename
)
from_email = 'Rowsandall <info@rowsandall.com>'
d = {
'username':username,
'registeredname':registeredname,
'siteurl':siteurl,
'racename':racename,
'raceid':raceid,
}
res = send_template_email(from_email,[useremail],
subject,
'raceregisteredemail.html',
d,**kwargs)
return 1
@app.task
def handle_sendemail_racesubmission(
useremail, username, registeredname, racename, raceid, **kwargs):
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = True
subject = "A new result has been submitted for virtual race {n}".format(
n = racename
)
from_email = 'Rowsandall <info@rowsandall.com>'
d = {
'username':username,
'siteurl':siteurl,
'registeredname':registeredname,
'racename':racename,
'raceid':raceid,
}
res = send_template_email(from_email,[useremail],
subject,
'racesubmissionemail.html',
d,**kwargs)
return 1
@app.task
def handle_send_disqualification_email(
useremail,username,reason,message, racename, **kwargs):
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = True
subject = "Your result for {n} has been disqualified on rowsandall.com".format(
n = racename
)
from_email = 'Rowsandall <support@rowsandall.com>'
d = {
'username':username,
'reason':reason,
'siteurl':siteurl,
'message': htmlstrip(message),
'racename':racename,
}
res = send_template_email(from_email,[useremail],
subject,
'disqualificationemail.html',
d,**kwargs)
return 1
@app.task
def handle_sendemail_expired(useremail,userfirstname,userlastname,expireddate,
**kwargs):
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = False
subject = "Your rowsandall.com paid account has expired"
from_email = 'Rowsandall <info@rowsandall.com>'
d = {
'first_name':userfirstname,
'last_name':userlastname,
'siteurl':siteurl,
'expireddate':expireddate,
}
res = send_template_email(from_email,[useremail],
subject,'accountexpiredemail.html',
d,cc=['support@rowsandall.com'],**kwargs)
return 1
@app.task
def handle_sendemail_breakthrough(workoutid, useremail,
userfirstname, userlastname,
btvalues=pd.DataFrame().to_json(),
**kwargs):
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = False
btvalues = pd.read_json(btvalues)
btvalues.sort_values('delta', axis=0, inplace=True)
tablevalues = [
{'delta': t.delta,
'cpvalue': t.cpvalues,
'pwr': t.pwr
} for t in btvalues.itertuples()
]
# send email with attachment
subject = "A breakthrough workout on rowsandall.com"
from_email = 'Rowsandall <info@rowsandall.com>'
d = {
'first_name':userfirstname,
'siteurl':siteurl,
'workoutid':encoder.encode_hex(workoutid),
'btvalues':tablevalues,
}
res = send_template_email(from_email,[useremail],
subject,'breakthroughemail.html',
d,**kwargs)
return 1
# send email when a breakthrough workout is uploaded
@app.task
def handle_sendemail_hard(workoutid, useremail,
userfirstname, userlastname,
btvalues=pd.DataFrame().to_json(),
debug=False,**kwargs):
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = False
btvalues = pd.read_json(btvalues)
btvalues.sort_values('delta', axis=0, inplace=True)
tablevalues = [
{'delta': t.delta,
'cpvalue': t.cpvalues,
'pwr': t.pwr
} for t in btvalues.itertuples()
]
# send email with attachment
subject = "That was a pretty hard workout on rowsandall.com"
from_email = 'Rowsandall <info@rowsandall.com>'
d = {
'first_name':userfirstname,
'siteurl':siteurl,
'workoutid':encoder.encode_hex(workoutid),
'btvalues':tablevalues,
}
res = send_template_email(from_email,[useremail],
subject,'hardemail.html',d,**kwargs)
return 1
# send email when user deletes account
@app.task
def handle_sendemail_userdeleted(name, email, debug=False, **kwargs):
fullemail = 'roosendaalsander@gmail.com'
subject = 'User account deleted'
message = 'Sander,\n\n'
message += 'The user {name} ({email}) has just deleted his account'.format(
name=name,
email=email
)
email = EmailMessage(subject,message,
'Rowsandall <info@rowsandall.com>',
[fullemail])
if 'emailbounced' in kwargs:
emailbounced = kwargs['emailbounced']
else:
emailbounced = False
if not emailbounced:
res = email.send()
return 1
# send email to me when an unrecognized file is uploaded
@app.task
def handle_sendemail_unrecognized(unrecognizedfile, useremail,
debug=False,**kwargs):
# send email with attachment
fullemail = 'roosendaalsander@gmail.com'
subject = "Unrecognized file from Rowsandall.com"
message = "Dear Sander,\n\n"
message += "Please find attached a file that someone tried to upload to rowsandall.com. The file was not recognized as a valid file type.\n\n"
message += "User Email " + useremail + "\n\n"
message += "Best Regards, the Rowsandall Team"
email = EmailMessage(subject, message,
'Rowsandall <info@rowsandall.com>',
[fullemail])
try:
email.attach_file(unrecognizedfile)
except IOError:
pass
if 'emailbounced' in kwargs:
emailbounced = kwargs['emailbounced']
else:
emailbounced = False
if not emailbounced:
res = email.send()
# remove tcx file
try:
os.remove(unrecognizedfile)
except:
pass
return 1
# send email to owner when an unrecognized file is uploaded
@app.task
def handle_sendemail_unrecognizedowner(useremail, userfirstname,
debug=False,**kwargs):
# send email with attachment
fullemail = useremail
subject = "Unrecognized file from Rowsandall.com"
d = {
'first_name':userfirstname,
'siteurl':siteurl,
}
from_email = 'Rowsandall <info@rowsandall.com>'
res = send_template_email(from_email,[fullemail],
subject,'unrecognizedemail.html',d,
**kwargs)
return 1
@app.task
def handle_sendemailics(first_name, last_name, email, icsfile, **kwargs):
# send email with attachment
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
subject = "Calendar File from Rowsandall.com"
d = {'first_name':first_name,
'siteurl':siteurl,
}
from_email = 'Rowsandall <info@rowsandall.com>'
res = send_template_email(from_email,[fullemail],
subject,'icsemail.html',d,
attach_file=icsfile,**kwargs)
os.remove(icsfile)
return 1
@app.task
def handle_sendemailkml(first_name, last_name, email, kmlfile,**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 <info@rowsandall.com>'
res = send_template_email(from_email,[fullemail],
subject,'kmlemail.html',d,
attach_file=kmlfile,**kwargs)
os.remove(kmlfile)
return 1
# Send email with TCX attachment
@app.task
def handle_sendemailtcx(first_name, last_name, email, tcxfile,**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 <info@rowsandall.com>'
res = send_template_email(from_email,[fullemail],
subject,'tcxemail.html',d,
attach_file=tcxfile,**kwargs)
os.remove(tcxfile)
return 1
@app.task
def handle_zip_file(emailfrom, subject, file,**kwargs):
message = "... zip processing ... "
try:
debug = kwargs['debug']
except KeyError:
debug = False
if debug:
print(message)
email = EmailMessage(subject, message,
emailfrom,
['workouts@rowsandall.com'])
email.attach_file(file)
if debug:
print("attaching")
res = email.send()
if debug:
print("sent")
time.sleep(60)
return 1
# Send email with CSV attachment
@app.task
def handle_sendemailsummary(first_name, last_name, email, csvfile, **kwargs):
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
subject = "File from Rowsandall.com"
d = {'first_name':first_name,
'siteurl':siteurl,
}
from_email = 'Rowsandall <info@rowsandall.com>'
res = send_template_email(from_email,[fullemail],
subject,'summarymail.html',d,
attach_file=csvfile,
**kwargs)
try:
os.remove(csvfile)
except:
pass
return 1
#from rowers.emails import sendemail
@app.task
def handle_sendemailcsv(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 <info@rowsandall.com>'
res = send_template_email(from_email,[fullemail],
subject,'csvemail.html',d,
attach_file=csvfile,**kwargs)
return 1
@app.task
def handle_sendemail_ical(first_name, last_name, email, url, icsfile, **kwargs):
# send email with attachment
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
subject = "Calendar File for your sessions from Rowsandall.com"
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = False
siteurl = SITE_URL
if debug:
progressurl = SITE_URL_DEV
siteurl = SITE_URL_DEV
d = {'first_name':first_name,
'siteurl':siteurl,
'url':url,
}
from_email = 'Rowsandall <info@rowsandall.com>'
res = send_template_email(from_email,[fullemail],
subject,'icsemail.html',d,
attach_file=icsfile,**kwargs)
try:
os.remove(csvfile)
except:
pass
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 <info@rowsandall.com>'
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
@app.task(bind=True)
def handle_otwsetpower(self,f1, boattype, weightvalue,
first_name, last_name, email, workoutid,
**kwargs):
job = self.request
job_id = job.id
if 'jobkey' in kwargs:
job_id = kwargs.pop('jobkey')
if 'ps' in kwargs:
ps = kwargs['ps']
else:
ps = [1,1,1,1]
if 'ratio' in kwargs:
ratio = kwargs['ratio']
else:
ratio = 1.0
if 'debug' in kwargs:
debug = kwargs['debug']
else:
debug = False
if 'quick_calc' in kwargs:
usetable = kwargs['quick_calc']
else:
usetable = False
kwargs['jobid'] = job_id
try:
rowdata = rdata(csvfile=f1)
except IOError:
try:
rowdata = rdata(csvfile=f1 + '.csv')
except IOError:
rowdata = rdata(csvfile=f1 + '.gz')
weightvalue = float(weightvalue)
# do something with boat type
boatfile = {
'1x': 'static/rigging/1x.txt',
'2x': 'static/rigging/2x.txt',
'2-': 'static/rigging/2-.txt',
'4x': 'static/rigging/4x.txt',
'4-': 'static/rigging/4-.txt',
'8+': 'static/rigging/8+.txt',
}
try:
rg = rowingdata.getrigging(boatfile[boattype])
except KeyError:
rg = rowingdata.getrigging('static/rigging/1x.txt')
# do calculation, but do not overwrite NK Empower Power data
powermeasured = False
try:
w = rowdata.df['wash']
if w.mean() != 0:
powermeasured = True
except KeyError:
pass
progressurl = SITE_URL
siteurl = SITE_URL
if debug:
progressurl = SITE_URL_DEV
siteurl = SITE_URL_DEV
secret = PROGRESS_CACHE_SECRET
progressurl += "/rowers/record-progress/"
progressurl += job_id+'/'
# determine cache file name
physics_cache = 'media/'+str(boattype)+'_'+str(int(weightvalue))
rowdata.otw_setpower(skiprows=5, mc=weightvalue, rg=rg,
powermeasured=powermeasured,
progressurl=progressurl,
secret=secret,
silent=True,
usetable=usetable,storetable=physics_cache,
)
# save data
rowdata.write_csv(f1, gzip=True)
update_strokedata(workoutid, rowdata.df, debug=debug)
totaltime = rowdata.df['TimeStamp (sec)'].max(
) - rowdata.df['TimeStamp (sec)'].min()
try:
totaltime = totaltime + rowdata.df.ix[0, ' ElapsedTime (sec)']
except KeyError:
pass
df = getsmallrowdata_db(
['power', 'workoutid', 'time'], ids=[workoutid],
debug=debug)
thesecs = totaltime
maxt = 1.05 * thesecs
logarr = datautils.getlogarr(maxt)
dfgrouped = df.groupby(['workoutid'])
delta, cpvalues, avgpower = datautils.getcp(dfgrouped, logarr)
#delta,cpvalues,avgpower = datautils.getsinglecp(rowdata.df)
res, btvalues, res2 = utils.isbreakthrough(
delta, cpvalues, ps[0], ps[1], ps[2], ps[3], ratio)
if res:
handle_sendemail_breakthrough(
workoutid, email,
first_name,
last_name, btvalues=btvalues.to_json())
subject = "Your OTW Physics Calculations are ready"
from_email = 'Rowsandall <info@rowsandall.com>'
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
d = {
'first_name':first_name,
'siteurl':siteurl,
'workoutid':encoder.encode_hex(workoutid),
}
res = send_template_email(from_email,[fullemail],
subject,'otwpoweremail.html',d,
**kwargs)
return 1
@app.task
def handle_updateergcp(rower_id,workoutfilenames,debug=False,**kwargs):
therows = []
for f1 in workoutfilenames:
try:
rowdata = rdata(csvfile=f1)
except IOError:
try:
rowdata = rdata(csvfile=f1 + '.csv')
except IOError:
try:
rowdata = rdata(csvfile=f1 + '.gz')
except IOError:
rowdata = 0
if rowdata != 0:
therows.append(rowdata)
cpdata = rowingdata.cumcpdata(therows)
cpdata.columns = cpdata.columns.str.lower()
updatecpdata_sql(rower_id,cpdata['delta'],cpdata['cp'],
table='ergcpdata',distance=cpdata['distance'],
debug=debug)
return 1
def cp_from_workoutids(workoutids,debug=False):
columns = ['power','workoutid','time']
df = getsmallrowdata_db(columns,ids=workoutids,debug=debug)
df.dropna(inplace=True,axis=0)
if df.empty:
# change this
return 0,0,0
# df is not empty. We continue
dfgrouped = df.groupby(['workoutid'])
maxt = 1.05*df['time'].max()/1000.
logarr = datautils.getlogarr(maxt)
delta,cpvalue,avgpower = datautils.getcp(dfgrouped,logarr)
powerdf = pd.DataFrame({
'Delta':delta,
'CP':cpvalue,
})
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)
p1,fitt,fitpower,ratio = datautils.cpfit(powerdf)
# This is code duplication from datautils -- correct asap
fitfunc = lambda pars,x: abs(pars[0])/(1+(x/abs(pars[2]))) + abs(pars[1])/(1+(x/abs(pars[3])))
powerfourmin = fitfunc(p1,240.)
powerhour = fitfunc(p1,3600.)
# 2k power
velofourmin = (powerfourmin/2.8)**(1./3.)
dfourmin = 240.*velofourmin
dratio = 2000./dfourmin
pacefourmin = 500./velofourmin
# assume 5 sec per doubling drop
pace2k = pacefourmin + 5.*np.log10(dratio)/np.log10(2.)
velo2k = 500./pace2k
t2k = 2000./velo2k
pwr2k = fitfunc(p1,t2k)
velo2 = (pwr2k/2.8)**(1./3.)
if np.isnan(velo2) or velo2 <= 0:
velo2 = 1.0
t2 = 2000./velo2
pwr2k = fitfunc(p1,t2)
velo3 = (pwr2k/2.8)**(1./3.)
t3 = 2000./velo3
power2k = fitfunc(p1,t3)
return powerfourmin,power2k,powerhour
@app.task
def handle_updatefitnessmetric(user_id,mode,workoutids,debug=False,
**kwargs):
powerfourmin = -1
power2k = -1
powerhour = -1
mdict = {
'user_id': user_id,
'PowerFourMin': powerfourmin,
'PowerTwoK': power2k,
'PowerOneHour': powerhour,
'workoutmode': mode,
'last_workout': max(workoutids),
'date': timezone.now().strftime('%Y-%m-%d'),
}
result = fitnessmetric_to_sql(mdict,debug=debug,doclean=False)
powerfourmin,power2k,powerhour = cp_from_workoutids(workoutids,debug=debug)
if powerfourmin > 0 and power2k > 0 and powerhour > 0:
mdict = {
'user_id': user_id,
'PowerFourMin': powerfourmin,
'PowerTwoK': power2k,
'PowerOneHour': powerhour,
'workoutmode': mode,
'last_workout': max(workoutids),
'date': timezone.now().strftime('%Y-%m-%d'),
}
result = fitnessmetric_to_sql(mdict,debug=debug,doclean=True)
else:
result = 0
return result
@app.task
def handle_updatecp(rower_id,workoutids,debug=False,table='cpdata',**kwargs):
columns = ['power','workoutid','time']
df = getsmallrowdata_db(columns,ids=workoutids,debug=debug)
dfgrouped = df.groupby(['workoutid'])
if not df.empty:
maxt = 1.05*df['time'].max()/1000.
else:
maxt = 1000.
logarr = datautils.getlogarr(maxt)
delta,cpvalue,avgpower = datautils.getcp(dfgrouped,logarr)
updatecpdata_sql(rower_id,delta,cpvalue,debug=debug,table=table)
return 1
@app.task
def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename,
debug=False,**kwargs):
hrmax = hrdata['hrmax']
hrut2 = hrdata['hrut2']
hrut1 = hrdata['hrut1']
hrat = hrdata['hrat']
hrtr = hrdata['hrtr']
hran = hrdata['hran']
ftp = hrdata['ftp']
powerzones = deserialize_list(hrdata['powerzones'])
powerperc = np.array(deserialize_list(hrdata['powerperc'])).astype(float)
rr = rowingdata.rower(hrmax=hrmax, hrut2=hrut2,
hrut1=hrut1, hrat=hrat,
hrtr=hrtr, hran=hran,
ftp=ftp, powerperc=powerperc,
powerzones=powerzones)
try:
row = rdata(csvfile=f2, rower=rr)
except IOError:
row = rdata(csvfile=f2 + '.gz', rower=rr)
try:
haspower = row.df[' Power (watts)'].mean() > 50
except (TypeError, KeyError):
haspower = False
nr_rows = len(row.df)
if (plotnr in [1, 2, 4, 5, 8, 11, 9, 12]) and (nr_rows > 1200):
bin = int(nr_rows / 1200.)
df = row.df.groupby(lambda x: x / bin).mean()
row.df = df
nr_rows = len(row.df)
if (plotnr == 1):
fig1 = row.get_timeplot_erg(t)
elif (plotnr == 2):
fig1 = row.get_metersplot_erg(t)
elif (plotnr == 3):
t += ' - Heart Rate Distribution'
fig1 = row.get_piechart(t)
elif (plotnr == 4):
if haspower:
fig1 = row.get_timeplot_otwempower(t)
else:
fig1 = row.get_timeplot_otw(t)
elif (plotnr == 5):
if haspower:
fig1 = row.get_metersplot_otwempower(t)
else:
fig1 = row.get_metersplot_otw(t)
elif (plotnr == 6):
t += ' - Heart Rate Distribution'
fig1 = row.get_piechart(t)
elif (plotnr == 7) or (plotnr == 10):
fig1 = row.get_metersplot_erg2(t)
elif (plotnr == 8) or (plotnr == 11):
fig1 = row.get_timeplot_erg2(t)
elif (plotnr == 9) or (plotnr == 12):
fig1 = row.get_time_otwpower(t)
elif (plotnr == 13) or (plotnr == 16):
t += ' - Power Distribution'
fig1 = row.get_power_piechart(t)
if fig1:
canvas = FigureCanvas(fig1)
canvas.print_figure('static/plots/' + imagename)
plt.close(fig1)
fig1.clf()
gc.collect()
return imagename
# Team related remote tasks
@app.task
def handle_sendemail_coachrequest(email,name,code,coachname,
debug=False,**kwargs):
fullemail = email
subject = 'Invitation to add {n} to your athletes'.format(n=name)
from_email = 'Rowsandall <info@rowsandall.com>'
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'name':name,
'coach':coachname,
'code':code,
'siteurl':siteurl
}
form_email = 'Rowsandall <info@rowsandall.com>'
res = send_template_email(from_email,[fullemail],
subject,'coachrequestemail.html',d,
**kwargs)
return 1
@app.task
def handle_sendemail_coachoffer_rejected(coachemail,coachname,name,
debug=False,**kwargs):
fullemail = coachemail
subject = '{n} has rejected your offer to be his coach on rowsandall.com'.format(n=name)
from_email = 'Rowsandall <info@rowsandall.com>'
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'name':name,
'coach':coachname,
'siteurl':siteurl,
}
res = send_template_email(from_email,[fullemail],
subject,'coachofferrejectedemail.html',
d,
**kwargs)
return 1
@app.task
def handle_sendemail_coachrequest_rejected(email,coachname,name,
debug=False,**kwargs):
fullemail = email
subject = '{n} has rejected your coaching request on rowsandall.com'.format(n=coachname)
from_email = 'Rowsandall <info@rowsandall.com>'
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'name':name,
'coach':coachname,
'siteurl':siteurl,
}
res = send_template_email(from_email,[fullemail],
subject,'coachrequestrejectedemail.html',
d,
**kwargs)
return 1
@app.task
def handle_sendemail_coachrequest_accepted(email,coachname,name,
debug=False,**kwargs):
fullemail = email
subject = '{n} has accepted your coaching request on rowsandall.com'.format(n=coachname)
from_email = 'Rowsandall <info@rowsandall.com>'
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'name':name,
'coach':coachname,
'siteurl':siteurl,
}
res = send_template_email(from_email,[fullemail],
subject,'coachrequestacceptedemail.html',
d,
**kwargs)
return 1
@app.task
def handle_sendemail_coachoffer_accepted(coachemail,coachname,name,
debug=False,**kwargs):
fullemail = coachemail
subject = '{n} has accepted your coaching offer on rowsandall.com'.format(n=name)
from_email = 'Rowsandall <info@rowsandall.com>'
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'name':name,
'coach':coachname,
'siteurl':siteurl,
}
res = send_template_email(from_email,[fullemail],
subject,'coachofferacceptedemail.html',
d,
**kwargs)
return 1
@app.task
def handle_sendemail_coacheerequest(email,name,code,coachname,
debug=False,**kwargs):
fullemail = email
subject = '{n} requests coach access to your data on rowsandall.com'.format(n=coachname)
from_email = 'Rowsandall <info@rowsandall.com>'
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'name':name,
'coach':coachname,
'code':code,
'siteurl':siteurl
}
res = send_template_email(from_email,[fullemail],
subject,'coacheerequestemail.html',d,
**kwargs)
return 1
@app.task
def handle_sendemail_invite(email, name, code, teamname, manager,
debug=False,**kwargs):
fullemail = email
subject = 'Invitation to join team ' + teamname
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'name':name,
'manager':manager,
'code':code,
'teamname':teamname,
'siteurl':siteurl
}
from_email = 'Rowsandall <info@rowsandall.com>'
res = send_template_email(from_email,[fullemail],
subject,'teaminviteemail.html',d,
**kwargs)
return 1
@app.task
def handle_sendemailnewresponse(first_name, last_name,
email,
commenter_first_name,
commenter_last_name,
comment,
workoutname, workoutid, commentid,
debug=False,**kwargs):
fullemail = email
from_email = 'Rowsandall <info@rowsandall.com>'
subject = 'New comment on session ' + workoutname
comment = u''+comment
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
sessiontype = 'workout'
if 'sessiontype' in kwargs:
sessiontype=kwargs.pop('sessiontype')
commentlink = '/rowers/workout/{workoutid}/comment/'.format(
workoutid=encoder.encode_hex(workoutid))
if 'commentlink' in kwargs:
commentlink = kwargs.pop('commentlink')
d = {
'first_name':first_name,
'commenter_first_name':commenter_first_name,
'commenter_last_name':commenter_last_name,
'comment':comment,
'workoutname':workoutname,
'siteurl':siteurl,
'workoutid':workoutid,
'commentid':commentid,
'sessiontype':sessiontype,
'commentlink':commentlink,
}
res = send_template_email(from_email,
[fullemail],
subject,'teamresponseemail.html',d,**kwargs)
return 1
@app.task
def handle_sendemailnewcomment(first_name,
last_name,
email,
commenter_first_name,
commenter_last_name,
comment, workoutname,
workoutid,
debug=False,**kwargs):
fullemail = email
from_email = 'Rowsandall <info@rowsandall.com>'
subject = 'New comment on session ' + workoutname
comment = u''+comment
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
sessiontype = 'workout'
if 'sessiontype' in kwargs:
sessiontype=kwargs.pop('sessiontype')
commentlink = '/rowers/workout/{workoutid}/comment/'.format(
workoutid=encoder.encode_hex(workoutid))
if 'commentlink' in kwargs:
commentlink = kwargs.pop('commentlink')
d = {
'first_name':first_name,
'commenter_first_name':commenter_first_name,
'commenter_last_name':commenter_last_name,
'comment':comment,
'workoutname':workoutname,
'siteurl':siteurl,
'workoutid':encoder.encode_hex(workoutid),
'sessiontype':sessiontype,
'commentlink':commentlink,
}
res = send_template_email(from_email,[fullemail],subject,
'teamresponseemail.html',d,**kwargs)
return 1
@app.task
def handle_sendemail_message(email,fromemail,rowername,message,teamname,managername,
debug=False,**kwargs):
fullemail = email
subject = 'New message from team ' + teamname
from_email = fromemail
d = {
'rowername':rowername,
'teamname':teamname,
'managername':managername,
'message':message,
}
res = send_template_email(from_email,[fullemail],subject,
'teammessage.html',d,**kwargs)
return 1
@app.task
def handle_sendemail_request(email, name, code, teamname, requestor, id,
debug=False,**kwargs):
fullemail = email
subject = 'Request to join team ' + teamname
from_email = 'Rowsandall <info@rowsandall.com>'
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'requestor':requestor,
'teamname':teamname,
'siteurl':siteurl,
'id':id,
'first_name':name,
}
res = send_template_email(from_email,[fullemail],subject,
'teamrequestemail.html',d,**kwargs)
return 1
@app.task
def handle_sendemail_request_accept(email, name, teamname, managername,
debug=False,**kwargs):
fullemail = email
subject = 'Welcome to ' + teamname
from_email = 'Rowsandall <info@rowsandall.com>'
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'first_name':name,
'managername':managername,
'teamname':teamname,
'siteurl':siteurl,
}
res = send_template_email(from_email,[fullemail],subject,
'teamwelcomeemail.html',d,**kwargs)
return 1
@app.task
def handle_sendemail_request_reject(email, name, teamname, managername,
debug=False,**kwargs):
fullemail = email
subject = 'Your application to ' + teamname + ' was rejected'
from_email = 'Rowsandall <info@rowsandall.com>'
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'first_name':name,
'managername':managername,
'teamname':teamname,
'siteurl':siteurl,
}
res = send_template_email(from_email,[fullemail],subject,
'teamrejectemail.html',d,**kwargs)
return 1
@app.task
def handle_sendemail_member_dropped(email, name, teamname, managername,
debug=False,**kwargs):
fullemail = email
subject = 'You were removed from ' + teamname
from_email = 'Rowsandall <info@rowsandall.com>'
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'first_name':name,
'managername':managername,
'teamname':teamname,
'siteurl':siteurl,
}
res = send_template_email(from_email,[fullemail],subject,
'teamdropemail.html',d,**kwargs)
return 1
@app.task
def handle_sendemail_team_removed(email, name, teamname, managername,
debug=False,**kwargs):
fullemail = email
subject = 'You were removed from ' + teamname
from_email = 'Rowsandall <info@rowsandall.com>'
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'first_name':name,
'managername':managername,
'teamname':teamname,
'siteurl':siteurl,
}
res = send_template_email(from_email,[fullemail],subject,
'teamremoveemail.html',d,**kwargs)
return 1
@app.task
def handle_sendemail_invite_reject(email, name, teamname, managername,
debug=False,**kwargs):
fullemail = email
subject = 'Your invitation to ' + name + ' was rejected'
from_email = 'Rowsandall <info@rowsandall.com>'
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'first_name':name,
'managername':managername,
'teamname':teamname,
'siteurl':siteurl,
}
res = send_template_email(from_email,[fullemail],subject,
'teaminviterejectemail.html',d,**kwargs)
return 1
@app.task
def handle_sendemail_invite_accept(email, name, teamname, managername,
debug=False,**kwargs):
fullemail = email
subject = 'Your invitation to ' + name + ' was accepted'
from_email = 'Rowsandall <info@rowsandall.com>'
siteurl = SITE_URL
if debug:
siteurl = SITE_URL_DEV
d = {
'first_name':name,
'managername':managername,
'teamname':teamname,
'siteurl':siteurl,
}
res = send_template_email(from_email,[fullemail],subject,
'teaminviteacceptemail.html',d,**kwargs)
return 1
# Another simple task for debugging purposes
def add2(x, y,debug=False,**kwargs):
return x + y