@ -34,6 +34,8 @@ public class Main 
		
	
		
			
				{ {  
		
	
		
			
					public  static  final  String  baseUrl  =  "https://www.strava.com/api/v3/" ; 	public  static  final  String  baseUrl  =  "https://www.strava.com/api/v3/" ;  
		
	
		
			
					public  static  final  String  tokenUrl  =  "https://www.strava.com/api/v3/oauth/token" ; 	public  static  final  String  tokenUrl  =  "https://www.strava.com/api/v3/oauth/token" ;  
		
	
		
			
					private  static  final  int  retryTimes  =  20 ;  
		
	
		
			
					private  static  final  int  httpCodeLimitReached  =  429 ;  
		
	
		
			
					private  static  int  athleteId  =  0 ; 	private  static  int  athleteId  =  0 ;  
		
	
		
			
					private  static  JSONParser  parser  =  new  JSONParser ( ) ; 	private  static  JSONParser  parser  =  new  JSONParser ( ) ;  
		
	
		
			
					private  static  String  testRequest ; 	private  static  String  testRequest ;  
		
	
	
		
			
				
					
						
							 
					
					
						
							 
					
					
				 
				@ -95,6 +97,10 @@ public class Main 
		
	
		
			
				
 
		
	
		
			
						/ /  get  general  information 		/ /  get  general  information  
		
	
		
			
						JSONObject  athleteInfo  =  saveGeneralInformation ( token ) ; 		JSONObject  athleteInfo  =  saveGeneralInformation ( token ) ;  
		
	
		
			
						if ( athleteInfo = = null ) 	/ / error  getting  General  Information  
		
	
		
			
						{  
		
	
		
			
							athleteInfo  =  new  JSONObject ( ) ;  
		
	
		
			
						}  
		
	
		
			
						athleteInfo . put ( "activities" ,  allActivities ) ; 		athleteInfo . put ( "activities" ,  allActivities ) ;  
		
	
		
			
				
 
		
	
		
			
						try 		try  
		
	
	
		
			
				
					
						
							 
					
					
						
							 
					
					
				 
				@ -127,9 +133,10 @@ public class Main 
		
	
		
			
						String  requestUrlExtension  =  "activities/"  +  id  +  "/streams?" 		String  requestUrlExtension  =  "activities/"  +  id  +  "/streams?"  
		
	
		
			
								+  "keys=[time,distance,latlng,altitude,velocity_smooth,heartrate," 				+  "keys=[time,distance,latlng,altitude,velocity_smooth,heartrate,"  
		
	
		
			
								+  "cadence,watts,temp,moving,grade_smooth]&key_by_type=true" ; 				+  "cadence,watts,temp,moving,grade_smooth]&key_by_type=true" ;  
		
	
		
			
						String  json  =  makeOneGetRequest ( requestUrlExtension ,  token ) ;  
		
	
		
			
								 
		
	
		
			
						if  ( json . isEmpty ( ) | | json . isBlank ( ) | | json . equals ( "" ) )  
		
	
		
			
						String  json  =  makeGetRequestWithRetry ( requestUrlExtension ,  token ) ; ;  
		
	
		
			
				
 
		
	
		
			
						if  ( json = = null  | | json . isEmpty ( ) | | json . isBlank ( ) | | json . equals ( "" ) )  
		
	
		
			
						{ 		{  
		
	
		
			
							return  data ; 			return  data ;  
		
	
		
			
						} 		}  
		
	
	
		
			
				
					
						
							 
					
					
						
							 
					
					
				 
				@ -179,9 +186,9 @@ public class Main 
		
	
		
			
						int  pageIndex  =  1 ; 		int  pageIndex  =  1 ;  
		
	
		
			
						while  ( true ) 		while  ( true )  
		
	
		
			
						{ 							 		{ 							  
		
	
		
			
							String  requestExtension  =  "athlete/activities?page="  +  pageIndex ;  
		
	
		
			
							String  json  =  makeOne GetRequest ( requestExtension ,  token ) ;  
		
	
		
			
							if  ( json . isEmpty ( )  | |  json . isBlank ( )  | |  json . equals ( "" )  | |  json . equals ( "[]" ) )  / /  don ' t  know  where  the  last  page  is . . .  
		
	
		
			
							String  requestExtension  =  "athlete/activities?per_page=500&p age="  +  pageIndex ;  
		
	
		
			
							String  json  =  makeGetRequestWithRetry  ( requestExtension ,  token ) ;  
		
	
		
			
							if  ( json = = null  | |  json . isEmpty ( )  | |  json . isBlank ( )  | |  json . equals ( "" )  | |  json . equals ( "[]" ) )  / /  don ' t  know  where  the  last  page  is . . .  
		
	
		
			
							{ 			{  
		
	
		
			
								break ; 				break ;  
		
	
		
			
							} 			}  
		
	
	
		
			
				
					
						
							 
					
					
						
							 
					
					
				 
				@ -217,6 +224,53 @@ public class Main 
		
	
		
			
						return  result ; 		return  result ;  
		
	
		
			
					} 	}  
		
	
		
			
				
 
		
	
		
			
					/ * *  
		
	
		
			
					 *  Method  is  used  to  find  the  next  request  window :  It  tries  the  same  request  again  after  5  minutes .  
		
	
		
			
					 *  After  a  set  number  of  times  ( retryTimes )  it  stops  if  it  still  wasn ' t  successful .  
		
	
		
			
					 *  @param  urlExtension  UrlExtension  for  the  request  
		
	
		
			
					 *  @param  token  Token  for  the  request  
		
	
		
			
					 *  @return  Data  as  a  String  or   { @code  null }  if  there  is  no  data  
		
	
		
			
					 * /  
		
	
		
			
					static  String  makeGetRequestWithRetry ( String  urlExtension ,  String  token )  
		
	
		
			
					{  
		
	
		
			
						String  json = null ;  
		
	
		
			
						int  count = 0 ;  
		
	
		
			
						do  
		
	
		
			
						{  
		
	
		
			
							try  
		
	
		
			
							{  
		
	
		
			
								json  =  makeOneGetRequest ( urlExtension ,  token ) ;  
		
	
		
			
							}  
		
	
		
			
							catch  ( ResponseCodeWrongException  e )  
		
	
		
			
							{  
		
	
		
			
								/ / tried  enough  times ,  so  stop  now  
		
	
		
			
								if ( count  > =  retryTimes )  
		
	
		
			
								{  
		
	
		
			
									return  null ;  
		
	
		
			
								}  
		
	
		
			
								/ / request  limit  is  reached ,  try  again  later  
		
	
		
			
								if  ( e . getResponseCode ( ) = = httpCodeLimitReached )  
		
	
		
			
								{  
		
	
		
			
									count + + ; 					 
		
	
		
			
								}  
		
	
		
			
								else  / / some  other  error :  try  only  one  other  time !  
		
	
		
			
								{  
		
	
		
			
									count = retryTimes ;  
		
	
		
			
								}  
		
	
		
			
								/ / Sleep  for  5  minutes  and  try  to  get  the  next  15  min  request  window  
		
	
		
			
								try  
		
	
		
			
								{  
		
	
		
			
									TimeUnit . MINUTES . sleep ( 5 ) ;  
		
	
		
			
								}  
		
	
		
			
								catch  ( InterruptedException  e1 )  
		
	
		
			
								{  
		
	
		
			
								}  
		
	
		
			
							}  
		
	
		
			
							 
		
	
		
			
						} while ( json = = null ) ;  
		
	
		
			
						return  json ;  
		
	
		
			
					}  
		
	
		
			
					 
		
	
		
			
					/ * * 	/ * *  
		
	
		
			
					 *  Extracts  an  athletes  general  information . 	 *  Extracts  an  athletes  general  information .  
		
	
		
			
					 *  	 *   
		
	
	
		
			
				
					
					
					
						
							 
					
				 
				@ -232,7 +286,8 @@ public class Main 
		
	
		
			
						String  meas_pref  =  "measurement_preference" ;  / /  Possible  values  =  feet ,  meters 		String  meas_pref  =  "measurement_preference" ;  / /  Possible  values  =  feet ,  meters  
		
	
		
			
						String  weight  =  "weight" ; 		String  weight  =  "weight" ;  
		
	
		
			
				
 
		
	
		
			
						String  json  =  makeOneGetRequest ( "athlete" ,  token ) ;  
		
	
		
			
						 
		
	
		
			
						String  json  =  makeGetRequestWithRetry ( "athlete" ,  token ) ;  
		
	
		
			
				
 
		
	
		
			
						JSONObject  toSave  =  new  JSONObject ( ) ; 		JSONObject  toSave  =  new  JSONObject ( ) ;  
		
	
		
			
						try 		try  
		
	
	
		
			
				
					
						
							 
					
					
						
							 
					
					
				 
				@ -291,8 +346,9 @@ public class Main 
		
	
		
			
					 *  @param  token                Identification  /  authorization  token  of  the 	 *  @param  token                Identification  /  authorization  token  of  the  
		
	
		
			
					 *                             athlete 	 *                             athlete  
		
	
		
			
					 *  @return  The  response  as  a  String ,  an  empty  String  in  case  of  error . 	 *  @return  The  response  as  a  String ,  an  empty  String  in  case  of  error .  
		
	
		
			
					 *  @throws  ResponseCodeWrongException  If  there  was  an  http  error  
		
	
		
			
					 * / 	 * /  
		
	
		
			
					static  String  makeOneGetRequest ( String  requestUrlExtension ,  String  token )  
		
	
		
			
					static  String  makeOneGetRequest ( String  requestUrlExtension ,  String  token )  throws  ResponseCodeWrongException   
		
	
		
			
					{ 	{  
		
	
		
			
						if  ( testRequest  ! =  null ) 		if  ( testRequest  ! =  null )  
		
	
		
			
						{ 		{  
		
	
	
		
			
				
					
						
							 
					
					
						
							 
					
					
				 
				@ -335,20 +391,21 @@ public class Main 
		
	
		
			
					 *  	 *   
		
	
		
			
					 *  @param  connection  Connection  to  the  site 	 *  @param  connection  Connection  to  the  site  
		
	
		
			
					 *  @return  Response  as  a  String 	 *  @return  Response  as  a  String  
		
	
		
			
					 *  @throws  IOException  in  case  of  error  
		
	
		
			
					 *  @throws  IOException  in  case  of  error  with  the  stream  
		
	
		
			
					 *  @throws  ResponseCodeWrongException  if  no  data  was  read  because  of  http  problems  
		
	
		
			
					 * / 	 * /  
		
	
		
			
					static  String  getResponse ( HttpsURLConnection  connection )  throws  IOException  
		
	
		
			
					static  String  getResponse ( HttpsURLConnection  connection )  throws  IOException ,  ResponseCodeWrongException  
		
	
		
			
					{ 	{  
		
	
		
			
						StringBuilder  result  =  new  StringBuilder ( ) ; 		StringBuilder  result  =  new  StringBuilder ( ) ;  
		
	
		
			
						int  responseCode  =  connection . getResponseCode ( ) ; 		int  responseCode  =  connection . getResponseCode ( ) ;  
		
	
		
			
						if  ( responseCode  ! =  HttpURLConnection . HTTP_OK ) 		if  ( responseCode  ! =  HttpURLConnection . HTTP_OK )  
		
	
		
			
						{ 		{  
		
	
		
			
							/ / excluded  error  messages  appearing  on  missing  streams  
		
	
		
			
							if ( responseCode  ! =  HttpURLConnection . HTTP_NOT_FOUND )  
		
	
		
			
							/ / excluded  error  messages  appearing  on  missing  streams  and  reached  rate  limit   
		
	
		
			
							if ( responseCode  ! =  HttpURLConnection . HTTP_NOT_FOUND  & &  responseCode ! =  httpCodeLimitReached  )  
		
	
		
			
							{ 			{  
		
	
		
			
								writeError ( "Wrong response code: "  +  responseCode ) ; 								writeError ( "Wrong response code: "  +  responseCode ) ; 				 
		
	
		
			
							} 			}  
		
	
		
			
							return  "" ;  
		
	
		
			
							throw  new  ResponseCodeWrongException ( responseCode ) ;  
		
	
		
			
						} 		}  
		
	
		
			
				
 
		
	
		
			
						try  ( Reader  reader  =  new  BufferedReader ( 		try  ( Reader  reader  =  new  BufferedReader (  
		
	
	
		
			
				
					
					
					
						
							 
					
				 
				@ -372,8 +429,9 @@ public class Main 
		
	
		
			
					 *  @param  data  Triplet  containing :  a  the  client_id ,  b  the  client_secret ,  c  the 	 *  @param  data  Triplet  containing :  a  the  client_id ,  b  the  client_secret ,  c  the  
		
	
		
			
					 *              refresh_token 	 *              refresh_token  
		
	
		
			
					 *  @return  The  response  as  a  String ,  an  empty  String  in  case  of  error . 	 *  @return  The  response  as  a  String ,  an  empty  String  in  case  of  error .  
		
	
		
			
					 *  @throws  ResponseCodeWrongException  If  there  was  an  http  error  
		
	
		
			
					 * / 	 * /  
		
	
		
			
					static  String  makeOnePostRequest ( Triplet  data )  
		
	
		
			
					static  String  makeOnePostRequest ( Triplet  data )  throws  ResponseCodeWrongException   
		
	
		
			
					{ 	{  
		
	
		
			
						HttpsURLConnection  connection  =  null ; 		HttpsURLConnection  connection  =  null ;  
		
	
		
			
						try 		try  
		
	
	
		
			
				
					
						
							 
					
					
						
							 
					
					
				 
				@ -423,7 +481,41 @@ public class Main 
		
	
		
			
					 * / 	 * /  
		
	
		
			
					static  Tuple  getAccessToken ( Triplet  refreshInfo ) 	static  Tuple  getAccessToken ( Triplet  refreshInfo )  
		
	
		
			
					{ 	{  
		
	
		
			
						String  json  =  makeOnePostRequest ( refreshInfo ) ;  
		
	
		
			
						String  json = null ;  
		
	
		
			
						int  count  = 0 ;  
		
	
		
			
						do  
		
	
		
			
						{  
		
	
		
			
							try  
		
	
		
			
							{  
		
	
		
			
								json  =  makeOnePostRequest ( refreshInfo ) ;  
		
	
		
			
							}  
		
	
		
			
							catch  ( ResponseCodeWrongException  e )  
		
	
		
			
							{  
		
	
		
			
								/ / tried  enough  times ,  so  stop  now  
		
	
		
			
								if ( count  > =  retryTimes )  
		
	
		
			
								{  
		
	
		
			
									return  null ;  
		
	
		
			
								}  
		
	
		
			
								/ / request  limit  is  reached ,  try  again  later  
		
	
		
			
								if  ( e . getResponseCode ( ) = = httpCodeLimitReached )  
		
	
		
			
								{  
		
	
		
			
									count + + ; 					 
		
	
		
			
								}  
		
	
		
			
								else  / / some  other  error :  try  only  one  other  time !  
		
	
		
			
								{  
		
	
		
			
									count = retryTimes ;  
		
	
		
			
								}  
		
	
		
			
								/ / Sleep  for  5  minutes  and  try  to  get  the  next  15  min  request  window  
		
	
		
			
								try  
		
	
		
			
								{  
		
	
		
			
									TimeUnit . MINUTES . sleep ( 5 ) ;  
		
	
		
			
								}  
		
	
		
			
								catch  ( InterruptedException  e1 )  
		
	
		
			
								{  
		
	
		
			
								}  
		
	
		
			
							}  
		
	
		
			
							 
		
	
		
			
						} while ( json = = null ) ;  
		
	
		
			
						try 		try  
		
	
		
			
						{ 		{  
		
	
		
			
							Object  obj  =  parser . parse ( json ) ; 			Object  obj  =  parser . parse ( json ) ;  
		
	
	
		
			
				
					
						
							 
					
					
						
							 
					
					
				 
				@ -476,41 +568,3 @@ public class Main 
		
	
		
			
						} 		}  
		
	
		
			
					} 	}  
		
	
		
			
				} }  
		
	
		
			
				
 
		
	
		
			
				class  Tuple  
		
	
		
			
				{  
		
	
		
			
					private  String  a ;  
		
	
		
			
					private  String  b ;  
		
	
		
			
				
 
		
	
		
			
					public  Tuple ( String  a ,  String  b )  
		
	
		
			
					{  
		
	
		
			
						this . a  =  a ;  
		
	
		
			
						this . b  =  b ;  
		
	
		
			
					}  
		
	
		
			
				
 
		
	
		
			
					public  String  getA ( )  
		
	
		
			
					{  
		
	
		
			
						return  a ;  
		
	
		
			
					}  
		
	
		
			
				
 
		
	
		
			
					public  String  getB ( )  
		
	
		
			
					{  
		
	
		
			
						return  b ;  
		
	
		
			
					}  
		
	
		
			
				}  
		
	
		
			
				
 
		
	
		
			
				class  Triplet  extends  Tuple  
		
	
		
			
				{  
		
	
		
			
					private  String  c ;  
		
	
		
			
				
 
		
	
		
			
					public  Triplet ( String  a ,  String  b ,  String  c )  
		
	
		
			
					{  
		
	
		
			
						super ( a ,  b ) ;  
		
	
		
			
						this . c  =  c ;  
		
	
		
			
					}  
		
	
		
			
				
 
		
	
		
			
					public  String  getC ( )  
		
	
		
			
					{  
		
	
		
			
						return  c ;  
		
	
		
			
					}  
		
	
		
			
				}