Last active
April 20, 2018 18:28
-
-
Save Pe8er/592d820836b20a3e2864b3b09c448f53 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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