From e7f72ea4052bba61cde60c464339eefb11a149f5 Mon Sep 17 00:00:00 2001 From: Bianca Steffes Date: Tue, 28 Sep 2021 11:48:15 +0200 Subject: [PATCH] Code concluded and tested as far as possible --- export/src/export/Main.java | 180 ++++++++++++----------- export/src/export/MainTest.java | 246 +++++++++++++++++++++++++++++--- 2 files changed, 317 insertions(+), 109 deletions(-) diff --git a/export/src/export/Main.java b/export/src/export/Main.java index a46f970..9953ef8 100644 --- a/export/src/export/Main.java +++ b/export/src/export/Main.java @@ -7,7 +7,6 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; -import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.net.HttpURLConnection; @@ -33,57 +32,75 @@ public class Main public static final String baseUrl = "https://www.strava.com/api/v3/"; private static int athleteId = 0; private static JSONParser parser = new JSONParser(); - + private static String testRequest; + private static File errorFile; + + private static void writeError(String text) + { + if(errorFile==null) + { + errorFile = new File("error_"+System.currentTimeMillis()+".txt"); + } + + try(BufferedWriter bout = new BufferedWriter(new FileWriter(errorFile, true))) + { + bout.write(text); + bout.newLine(); + } + catch (IOException e) + { + } + } + + /** + * For testing: ensures the test requests are used + * @param testrequest Request to be used + */ + static void setTest(String testrequest) + { + testRequest=testrequest; + } + /** - * - * @param token + * Saves the data of one athlete into a temp file and returns it. + * @param token Identifier / authorization token of the athlete + * @return created temp file */ @SuppressWarnings("unchecked") - static void oneAthlete(String token) + static File oneAthlete(String token) { - Map athletesTempFiles = new HashMap(); - // get general information - athletesTempFiles.put("general_information.json", saveGeneralInformation(token)); - // get Activities Map activities = getActivities(token); // for each activity: save streams + JSONArray allActivities = new JSONArray(); int simpleActivityId=0; for (String id: activities.keySet()) { JSONObject data = addStreams(id, activities.get(id), token); data.put("activity_id", simpleActivityId); - - try - { - File temp = File.createTempFile("activity_" +simpleActivityId , ".json"); - temp.deleteOnExit(); - BufferedWriter bw = new BufferedWriter(new FileWriter(temp)); - bw.write(data.toString()); - bw.close(); - athletesTempFiles.put(""+simpleActivityId, temp); - } - catch (IOException e) - { - //Temp File coldnt be created - // TODO Auto-generated catch block - e.printStackTrace(); - } - + allActivities.add(data); simpleActivityId++; } + // get general information + JSONObject athleteInfo = saveGeneralInformation(token); + athleteInfo.put("activities", allActivities); + try { - zipAllFiles(athletesTempFiles); + File temp = File.createTempFile("Athlete_" +athleteId , ".json"); + temp.deleteOnExit(); + BufferedWriter bw = new BufferedWriter(new FileWriter(temp)); + bw.write(athleteInfo.toString()); + bw.close(); + return temp; } catch (IOException e) { - //Problem zipping - // TODO Auto-generated catch block - e.printStackTrace(); + writeError("Athlete "+athleteId+": Error writing temp file: "+e.toString()); } + return null; } /** @@ -96,7 +113,7 @@ public class Main @SuppressWarnings("unchecked") static JSONObject addStreams(String id, JSONObject data, String token) { - //TODO: das könnte mit dem Array Probleme geben.... + //TODO: Array representation is not tested String requestUrlExtension = "activities/"+id+"/streams?keys=[time, distance, latlng, altitude, " + "velocity_smooth, heartrate, cadence, watts, temp, moving, grade_smooth]&key_by_type="; String json = makeOneRequest(requestUrlExtension, token); @@ -110,18 +127,13 @@ public class Main for (int i=0; i files) throws IOException { - //TODO: checken, ob hier an den richtigen Ort gespeichert wird. - //TODO: evtl. alles nochmal zippen - FileOutputStream fos = new FileOutputStream("athlete_"+athleteId+".zip"); + FileOutputStream fos = new FileOutputStream("data.zip"); ZipOutputStream zipOut = new ZipOutputStream(fos); for (String key : files.keySet()) { @@ -281,6 +271,13 @@ public class Main */ static String makeOneRequest(String requestUrlExtension, String token) { + //TODO: http requests are not tested + if(testRequest!= null) + { + String varTestRequest = testRequest.replaceAll("\\:\\s*([0-9]{15,})\\,", ":\"$1\","); + testRequest=null; + return varTestRequest; + } HttpURLConnection connection = null; StringBuilder result = new StringBuilder(); try @@ -295,14 +292,11 @@ public class Main if (responseCode != HttpURLConnection.HTTP_OK) { - //TODO: mehr auf response codes achten + writeError("Wrong response code: "+responseCode); return ""; } - - InputStream inputStream = connection.getInputStream(); - try (Reader reader = new BufferedReader( - new InputStreamReader(inputStream, Charset.forName(StandardCharsets.UTF_8.name())))) + new InputStreamReader(connection.getInputStream(), Charset.forName(StandardCharsets.UTF_8.name())))) { int c = reader.read(); while (c != -1) @@ -311,27 +305,39 @@ public class Main c = reader.read(); } } - } catch(IOException e) { - //TODO: was tun bei error + writeError("Error while handling request: "+e.toString()); return ""; } - return result.toString(); + //Numbers too long for int or long are turned into Strings + return result.toString().replaceAll("\\:\\s*([0-9]{15,})\\,", ":\"$1\","); } public static void main(String[] args) { + //TODO: tokens need to be added by Enduco List tokens = new ArrayList<>(); - //TODO: tokens befüllen + //TODO: Should we expect problems with memory?? + Map allFiles = new HashMap<>(); for (String token : tokens) { - oneAthlete(token); + File athlete = oneAthlete(token); + if(athlete != null) + { + allFiles.put("Athlete_"+athleteId+".json", athlete); + } athleteId++; } - //TODO: alles nochmal zippen + try + { + zipAllFiles(allFiles); + } + catch (IOException e) + { + writeError("Files coulnd't be zipped"); + } } - -} +} \ No newline at end of file diff --git a/export/src/export/MainTest.java b/export/src/export/MainTest.java index ca1fd81..86d712e 100644 --- a/export/src/export/MainTest.java +++ b/export/src/export/MainTest.java @@ -1,52 +1,254 @@ package export; -import static org.junit.Assert.*; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.junit.Assert; import org.junit.Test; public class MainTest { - - @Test - public void testOneAthlete() - { - fail("Not yet implemented"); - } + //Test data from: + //https://developers.strava.com/playground/#/ + //https://developers.strava.com/docs/reference/ @Test public void testAddStreams() { - fail("Not yet implemented"); + String requestDistance = "[ { \"type\" : \"distance\", " + + "\"data\" : [ 2.9, 5.8, 8.5, 11.7, 15, 19, 23.2, 28, 32.8, 38.1, 43.8, 49.5 ], " + + "\"series_type\" : \"distance\", \"original_size\" : 12, \"resolution\" : \"high\"}]"; + //Time data is the same as distance only with different type and series_type + String requestDistanceAndTime = "[{\"type\" : \"distance\", " + + "\"data\" : [ 2.9, 5.8, 8.5, 11.7, 15, 19, 23.2, 28, 32.8, 38.1, 43.8, 49.5 ], " + + "\"series_type\" : \"distance\", \"original_size\" : 12, \"resolution\" : \"high\"}," + + "{\"type\" : \"time\", " + + "\"data\" : [ 2.9, 5.8, 8.5, 11.7, 15, 19, 23.2, 28, 32.8, 38.1, 43.8, 49.5 ], " + + "\"series_type\" : \"time\", \"original_size\" : 12, \"resolution\" : \"high\"}]"; + + + Main.setTest(requestDistance); + JSONObject res = Main.addStreams("id", new JSONObject(), "token"); + Assert.assertNull(res.get("stream_time")); + Assert.assertNotNull(res.get("stream_distance")); + Assert.assertNull(res.get("stream_altitude")); + + Main.setTest(requestDistanceAndTime); + res = Main.addStreams("id", new JSONObject(), "token"); + Assert.assertNotNull(res.get("stream_time")); + Assert.assertNotNull(res.get("stream_distance")); + Assert.assertNull(res.get("stream_altitude")); + + } @Test public void testGetActivities() { - fail("Not yet implemented"); + String request_full = "[{\"resource_state\": 2, " + + "\"athlete\": {\"id\": 134815, \"resource_state\": 1}, " + + "\"name\": \"Happy Friday\", \"distance\": 24931.4, \"moving_time\": 4500, " + + "\"elapsed_time\": 4500, \"total_elevation_gain\": 0, \"type\": \"Ride\", " + + "\"workout_type\": null, \"id\": 154504250376823, " + + "\"external_id\": \"garmin_push_12345678987654321\", " + + "\"upload_id\": 987654321234567900000, \"start_date\": \"2018-05-02T12:15:09Z\", " + + "\"start_date_local\": \"2018-05-02T05:15:09Z\", " + + "\"timezone\": \"(GMT-08:00) America/Los_Angeles\", \"utc_offset\": -25200, " + + "\"start_latlng\": null, \"end_latlng\": null, \"location_city\": null, " + + "\"location_state\": null, \"location_country\": \"United States\", " + + "\"achievement_count\": 0, \"kudos_count\": 3, \"comment_count\": 1, " + + "\"athlete_count\": 1, \"photo_count\": 0, " + + "\"map\": {\"id\": \"a12345678987654321\", \"summary_polyline\": null, \"resource_state\": 2 }," + + "\"trainer\": true, \"commute\": false, \"manual\": false, \"private\": false, " + + "\"flagged\": false, \"gear_id\": \"b12345678987654321\", \"from_accepted_tag\": false, " + + "\"average_speed\": 5.54, \"max_speed\": 11, \"average_cadence\": 67.1, " + + "\"average_watts\": 175.3, \"weighted_average_watts\": 210, \"kilojoules\": 788.7, " + + "\"device_watts\": true, \"has_heartrate\": true, \"average_heartrate\": 140.3, " + + "\"max_heartrate\": 178, \"max_watts\": 406, \"pr_count\": 0, \"total_photo_count\": 1," + + "\"has_kudoed\": false,\"suffer_score\": 82}," + + "{\"resource_state\": 2, \"athlete\": {\"id\": 167560, \"resource_state\": 1}," + + "\"name\": \"Bondcliff\", \"distance\": 23676.5, \"moving_time\": 5400," + + "\"elapsed_time\": 5400, \"total_elevation_gain\": 0, \"type\": \"Ride\", " + + "\"workout_type\": null, \"id\": 1234567809, " + + "\"external_id\": \"garmin_push_12345678987654321\", \"upload_id\": 1234567819," + + "\"start_date\": \"2018-04-30T12:35:51Z\", \"start_date_local\": \"2018-04-30T05:35:51Z\"," + + "\"timezone\": \"(GMT-08:00) America/Los_Angeles\", \"utc_offset\": -25200, " + + "\"start_latlng\": null, \"end_latlng\": null, \"location_city\": null, \"location_state\": null," + + "\"location_country\": \"United States\", \"achievement_count\": 0, \"kudos_count\": 4, " + + "\"comment_count\": 0, \"athlete_count\": 1, \"photo_count\": 0, " + + "\"map\": {\"id\": \"a12345689\", \"summary_polyline\": null, \"resource_state\": 2}," + + "\"trainer\": true, \"commute\": false, \"manual\": false, \"private\": false, " + + "\"flagged\": false, \"gear_id\": \"b12345678912343\", \"from_accepted_tag\": false," + + "\"average_speed\": 4.385, \"max_speed\": 8.8, \"average_cadence\": 69.8, " + + "\"average_watts\": 200, \"weighted_average_watts\": 214, \"kilojoules\": 1080, " + + "\"device_watts\": true, \"has_heartrate\": true, \"average_heartrate\": 152.4," + + "\"max_heartrate\": 183, \"max_watts\": 403, \"pr_count\": 0, \"total_photo_count\": 1, " + + "\"has_kudoed\": false, \"suffer_score\": 162}]"; + + String request_shortened = "[{\"type\": \"Ride\", \"id\": 154504250376823, " + + "\"start_date_local\": \"2018-05-02T05:15:09Z\", " + + "\"timezone\": \"(GMT-08:00) America/Los_Angeles\"}," + + "{\"type\": \"Ride\", \"id\": 1234567809, " + + "\"start_date_local\": \"2018-04-30T05:35:51Z\"," + + "\"timezone\": \"(GMT-08:00) America/Los_Angeles\"}]"; + + String request_shortened_one = "[{\"type\": \"Ride\", \"id\": 1234567809, " + + "\"start_date_local\": \"2018-04-30T05:35:51Z\"," + + "\"timezone\": \"(GMT-08:00) America/Los_Angeles\"}]"; + + String request_missing_type = "[{\"id\": 1234567809, " + + "\"start_date_local\": \"2018-04-30T05:35:51Z\"," + + "\"timezone\": \"(GMT-08:00) America/Los_Angeles\"}]"; + + String request_missing_id = "[{\"type\": \"Ride\", " + + "\"start_date_local\": \"2018-04-30T05:35:51Z\"," + + "\"timezone\": \"(GMT-08:00) America/Los_Angeles\"}]"; + + String request_missing_start = "[{\"type\": \"Ride\", \"id\": 1234567809, " + + "\"timezone\": \"(GMT-08:00) America/Los_Angeles\"}]"; + + String request_missing_timezone = "[{\"type\": \"Ride\", \"id\": 1234567809, " + + "\"start_date_local\": \"2018-04-30T05:35:51Z\"}]"; + + String[] requestsOneActivity = {request_shortened_one, request_missing_start, + request_missing_timezone, request_missing_type}; + + String[] requestsTwoActivities = {request_full, request_shortened}; + + for (String request: requestsTwoActivities) + { + Main.setTest(request); + Map res = Main.getActivities("token"); + Assert.assertEquals(res.size(), 2); + } + + for (String request: requestsOneActivity) + { + Main.setTest(request); + Map res = Main.getActivities("token"); + Assert.assertEquals(res.size(), 1); + } + + Main.setTest(request_missing_id); + Map res = Main.getActivities("token"); + Assert.assertEquals(res.size(), 0); + } @Test public void testSaveGeneralInformation() { - fail("Not yet implemented"); - } + String request_full ="{ \"id\" : 1234567890987654321, \"username\" : \"marianne_t\", \"resource_state\" : 3," + + "\"firstname\" : \"Marianne\", \"lastname\" : \"Teutenberg\", \"city\" : \"San Francisco\", " + + "\"state\" : \"CA\", \"country\" : \"US\", \"sex\" : \"F\", \"premium\" : true, " + + "\"created_at\" : \"2017-11-14T02:30:05Z\", \"updated_at\" : \"2018-02-06T19:32:20Z\", " + + "\"badge_type_id\" : 4, " + + "\"profile_medium\" : \"https://xxxxxx.cloudfront.net/pictures/athletes/123456789/123456789/2/medium.jpg\", " + + "\"profile\" : \"https://xxxxx.cloudfront.net/pictures/athletes/123456789/123456789/2/large.jpg\", " + + "\"friend\" : null, \"follower\" : null, \"follower_count\" : 5, \"friend_count\" : 5, " + + "\"mutual_friend_count\" : 0, \"athlete_type\" : 1, \"date_preference\" : \"%m/%d/%Y\", " + + "\"measurement_preference\" : \"feet\", \"clubs\" : [ ], \"ftp\" : null, \"weight\" : 0, " + + "\"bikes\" : [ { \"id\" : \"b12345678987655\"," + + "\"primary\" : true, \"name\" : \"EMC\", \"resource_state\" : 2, " + + "\"distance\" : 0 } ], " + + "\"shoes\" : [ { \"id\" : \"g12345678987655\", \"primary\" : true, \"name\" : \"adidas\", " + + "\"resource_state\" : 2, \"distance\" : 4904 } ]}"; + + String request_shortened ="{\"country\" : \"US\", \"sex\" : \"F\", \"date_preference\" : \"%m/%d/%Y\", " + + "\"measurement_preference\" : \"feet\", \"weight\" : 0}"; - @Test - public void testZipAllFiles() - { - fail("Not yet implemented"); - } + String request_missing_country ="{\"sex\" : \"F\", \"date_preference\" : \"%m/%d/%Y\", " + + "\"measurement_preference\" : \"feet\", \"weight\" : 0}"; + + String request_missing_gender ="{\"country\" : \"US\", \"date_preference\" : \"%m/%d/%Y\", " + + "\"measurement_preference\" : \"feet\", \"weight\" : 0}"; + + String request_missing_date_pref ="{\"country\" : \"US\", \"sex\" : \"F\", " + + "\"measurement_preference\" : \"feet\", \"weight\" : 0}"; + + String request_missing_meas_pref ="{\"country\" : \"US\", \"sex\" : \"F\", " + + " \"date_preference\" : \"%m/%d/%Y\", \"weight\" : 0}"; + + String request_missing_weight ="{\"country\" : \"US\", \"sex\" : \"F\", " + + " \"date_preference\" : \"%m/%d/%Y\", \"measurement_preference\" : \"feet\"}"; + + String request_bad_format ="{\"c: \"%m/%d/%Y\", \"measurement_preference\" : \"feet\"}"; + + String[] allRequests = {request_full, request_shortened, request_missing_country, + request_missing_date_pref, request_missing_gender, request_missing_meas_pref, + request_missing_weight}; + + for (String request: allRequests) + { + Main.setTest(request); + JSONObject o = Main.saveGeneralInformation("token"); + Assert.assertNotNull(o); + } + + Main.setTest(request_bad_format); + JSONObject o = Main.saveGeneralInformation("token"); + Assert.assertNull(o); - @Test - public void testMakeOneRequest() - { - fail("Not yet implemented"); } + @SuppressWarnings("unchecked") @Test - public void testMain() + public void testStructure() { - fail("Not yet implemented"); + String request_shortened = "[{\"type\": \"Ride\", \"id\": 154504250376823, " + + "\"start_date_local\": \"2018-05-02T05:15:09Z\", " + + "\"timezone\": \"(GMT-08:00) America/Los_Angeles\"}]"; + + Main.setTest(request_shortened); + Map res = Main.getActivities("token"); + + String requestDistanceAndTime = "[{\"type\" : \"distance\", " + + "\"data\" : [ 2.9, 5.8, 8.5, 11.7, 15, 19, 23.2, 28, 32.8, 38.1, 43.8, 49.5 ], " + + "\"series_type\" : \"distance\", \"original_size\" : 12, \"resolution\" : \"high\"}," + + "{\"type\" : \"time\", " + + "\"data\" : [ 2.9, 5.8, 8.5, 11.7, 15, 19, 23.2, 28, 32.8, 38.1, 43.8, 49.5 ], " + + "\"series_type\" : \"time\", \"original_size\" : 12, \"resolution\" : \"high\"}]"; + + JSONArray allActivities = new JSONArray(); + for(String activity : res.keySet()) + { + Main.setTest(requestDistanceAndTime); + JSONObject toSave = Main.addStreams("id", res.get(activity), "token"); + allActivities.add(toSave); + } + Assert.assertEquals(allActivities.size(), res.keySet().size()); + + String request_missing_country ="{\"sex\" : \"F\", \"date_preference\" : \"%m/%d/%Y\", " + + "\"measurement_preference\" : \"feet\", \"weight\" : 0}"; + + Main.setTest(request_missing_country); + JSONObject a = Main.saveGeneralInformation("token"); + a.put("activities", allActivities); + + try + { + File temp = File.createTempFile("Athlete_0" , ".json"); + temp.deleteOnExit(); + BufferedWriter bw = new BufferedWriter(new FileWriter(temp)); + bw.write(a.toString()); + bw.close(); + + Map map = new HashMap<>(); + map.put("athlete_0.json", temp); + Main.zipAllFiles(map); + + } + catch (IOException e) + { + Assert.fail(); + } + } }