Skip to content

Instantly share code, notes, and snippets.

@Pe8er
Last active April 20, 2018 18:28
Show Gist options
  • Save Pe8er/592d820836b20a3e2864b3b09c448f53 to your computer and use it in GitHub Desktop.
Save Pe8er/592d820836b20a3e2864b3b09c448f53 to your computer and use it in GitHub Desktop.
global jsonWeek, jsonYear, jsonAthlete, athleteID
property token : "????" -- your Strava API access token. Get it here: https://www.strava.com/settings/api
property yearRideGoal : 2000 -- in kilometers
property enableLogging : "off" --- options: on | off
on run theArgument
-- Set up the JSON files
tell application "Finder"
set jsonWeek to POSIX path of (container of (path to me) as alias) & "StravaWeek.json"
set jsonYear to POSIX path of (container of (path to me) as alias) & "StravaYear.json"
set jsonAthlete to POSIX path of (container of (path to me) as alias) & "StravaAthlete.json"
end tell
set athleteID to my getAthleteID()
-- Debugger
if class of theArgument is script then set theArgument to {"Run-Week"} --Possible parameters: Run-Week | Ride-Week | Run-Year | Ride-Year | Refresh
-- Refresh JSONs
if theArgument is {"Refresh"} then
downloadJson()
error number -128
end if
-- Always make sure JSONs are up to date
updateJson("all")
-- Main calculations
set yearRideDistance to numberToString(distanceCalc("Ride-Year") / 1000)
set yearRunDistance to numberToString(distanceCalc("Run-Year") / 1000)
if theArgument is {"Ride-Week"} then
set weekRideDistance to numberToString(distanceCalc(theArgument) / 1000)
-- How many weeks are remaining until the deadline?
set weeksRemaining to round (((date ("12/31/" & (year of (current date)) as string)) - (current date)) div days / 7)
if weeksRemaining ≤ 0 then set weeksRemaining to 1
-- Distance I need to ride weekly to meet my yearly goal
set weekRideGoal to numberToString((yearRideGoal - yearRideDistance) / weeksRemaining)
-- Let's make the progress bar
set weekProgressBar to makeProgressBar((weekRideDistance / weekRideGoal) * 100, 7)
-- Render output
return weekProgressBar & space & formatNumber(weekRideDistance, true) & "/" & formatNumber(weekRideGoal, true) & space & "KM"
else if theArgument is {"Ride-Year"} then
-- Let's make the progress bar
set yearProgressBar to makeProgressBar((yearRideDistance / yearRideGoal) * 100, 5)
-- render output
return yearProgressBar & space & formatNumber(yearRideDistance, true) & "/" & yearRideGoal & space & "KM"
else if theArgument is {"Run-Week"} then
return formatNumber(numberToString(distanceCalc(theArgument) / 1000), true) & space & "KM"
else if theArgument is {"Run-Year"} then
return formatNumber(numberToString(distanceCalc(theArgument) / 1000), true) & space & "KM"
else
log {"Rides: " & formatNumber(yearRideDistance, true), "Runs: " & formatNumber(yearRunDistance, true)}
end if
end run
-----------------------------------------------------------
------------------------SUBROUTINES------------------------
-----------------------------------------------------------
on distanceCalc(theArgument)
set theArgument to theArgument as string
set {TID, text item delimiters} to {text item delimiters, "-"}
set {activityType, period, text item delimiters} to {text item 1 of theArgument, text item 2 of theArgument, TID}
set distance to 0
if period is "Week" then
set startWeek to getWeekdayDate(current date, Monday, 0)
set endWeek to getWeekdayDate(current date, Monday, 1)
try
set myJSON to my getJson(jsonWeek)
repeat with anItem in items of myJSON
if type of anItem is activityType then
set activityDate to my convertStravaDate(start_date_local of anItem)
if activityDate ≥ startWeek and activityDate ≤ endWeek then set distance to (distance of anItem) + distance
end if
end repeat
on error e
my logEvent(e)
return e
end try
else if period is "Year" then
set myJSON to my getJson(jsonYear)
if activityType is "Ride" then
return distance of ytd_ride_totals of myJSON
else
return distance of ytd_run_totals of myJSON
end if
end if
return distance
end distanceCalc
on downloadJson()
set firstDayOfYear to numberToString((date ("1-1-" & year of (current date))) - (date "Thursday, January 1, 1970 at 12:00:00 AM"))
set firstDayOfWeek to numberToString(getWeekdayDate(current date, Monday, 0) - (date "Thursday, January 1, 1970 at 12:00:00 AM"))
try
do shell script "curl -X GET 'https://www.strava.com/api/v3/athlete/activities?access_token=" & token & "&after=" & firstDayOfWeek & "&per_page=200' -H 'accept: application/json' --output " & jsonWeek
on error e
my logEvent(e)
end try
try
do shell script "curl -X GET 'https://www.strava.com/api/v3/athletes/" & athleteID & "/stats?access_token=" & token & "&after=" & firstDayOfYear & "&per_page=200' -H 'accept: application/json' --output " & jsonYear
on error e
my logEvent(e)
end try
end downloadJson
on getAthleteID()
tell application "Finder" to if not (exists (jsonAthlete as POSIX file)) then do shell script "curl -X GET 'https://www.strava.com/api/v3/athlete?access_token=" & token & "' -H 'accept: application/json' --output " & jsonAthlete
set athleteID to |id| of my getJson(jsonAthlete)
end getAthleteID
on updateJson(jsonFile)
if jsonFile is "all" then set jsonFile to {jsonWeek, jsonYear}
repeat with aFile in jsonFile
try
if getModificationDate(aFile) < ((current date) - 8 * hours) then downloadJson(aFile)
on error e
log e
downloadJson()
end try
end repeat
end updateJson
on getJson(jsonFile)
try
tell application "JSON Helper" to read JSON from (read jsonFile)
on error e
my logEvent(e)
return "Can't read JSON"
end try
end getJson
on getModificationDate(theFile)
tell application "System Events" to modification date of file theFile
end getModificationDate
on makeProgressBar(Percent, Dots)
set e to "○"
set f to "●"
set o to "★"
set progressBar to ""
set progressNum to formatNumber(Percent / (100 / Dots), false) as integer
if progressNum < Dots then
repeat progressNum times
set progressBar to f & progressBar
end repeat
repeat Dots - progressNum times
set progressBar to progressBar & e
end repeat
else
set progressBar to o
end if
progressBar
end makeProgressBar
on numberToString(this_number)
set this_number to this_number as string
if this_number contains "E+" then
set x to the offset of "." in this_number
set y to the offset of "+" in this_number
set z to the offset of "E" in this_number
set the decimal_adjust to characters (y - (length of this_number)) thru ¬
-1 of this_number as string as number
if x is not 0 then
set the first_part to characters 1 thru (x - 1) of this_number as string
else
set the first_part to ""
end if
set the second_part to characters (x + 1) thru (z - 1) of this_number as string
set the converted_number to the first_part
repeat with i from 1 to the decimal_adjust
try
set the converted_number to ¬
the converted_number & character i of the second_part
on error
set the converted_number to the converted_number & "0"
end try
end repeat
return converted_number
else
return this_number
end if
end numberToString
on formatNumber(x, returnFraction)
set x to x as string
set text item delimiters to "."
try
set numA to text item 1 of x
set numB to "." & text item 2 of x
on error
set numA to x
set numB to ""
end try
set text item delimiters to ""
if length of numA > 3 then
set numA to items 1 thru ((length of numA) - 3) of numA & "," & items ((length of numA) - 2) thru -1 of numA as string
end if
if returnFraction is true then
if numB starts with ".0" then set numB to ""
if length of numB > 2 then set numB to items 1 thru 2 of numB
else
set numB to ""
end if
return numA & numB as string
end formatNumber
on getWeekdayDate(d, w, i) -- returns a date
-- Keep an note of whether the instance value *starts* as zero
set instanceIsZero to (i is 0)
-- Increment negative instances to compensate for the following subtraction loop
if i < 0 and d's weekday is not w then set i to i + 1
-- Subtract a day at a time until the required weekday is reached
repeat until d's weekday is w
set d to d - days
-- Increment an original zero instance to 1 if subtracting from Sunday into Saturday
if instanceIsZero and d's weekday is Sunday then set i to 1
end repeat
-- Add (adjusted instance) * weeks to the date just obtained and zero the time
d + i * weeks - (d's time)
end getWeekdayDate
on convertStravaDate(aDate)
set {TID, text item delimiters} to {text item delimiters, "T"}
set aDate to text item 1 of aDate
set text item delimiters to "-"
set {yy, mm, dd, text item delimiters} to every text item in aDate & TID
return date (mm & space & dd & space & yy)
end convertStravaDate
on logEvent(e)
if enableLogging is true then
set e to e as string
tell application "Finder" to set myName to (name of file (path to me))
do shell script "echo '" & (current date) & space & quoted form of e & "' >> ~/Library/Logs/" & quoted form of myName & ".log" & return
else
return
end if
end logEvent
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment