diff --git a/app/src/main/java/com/example/ithaca_transit_android_v2/NetworkUtils.kt b/app/src/main/java/com/example/ithaca_transit_android_v2/NetworkUtils.kt index 6486fa4..9ead021 100644 --- a/app/src/main/java/com/example/ithaca_transit_android_v2/NetworkUtils.kt +++ b/app/src/main/java/com/example/ithaca_transit_android_v2/NetworkUtils.kt @@ -2,11 +2,7 @@ package com.example.ithaca_transit_android_v2 import android.util.Log import com.example.ithaca_transit_android_v2.models.* import com.example.ithaca_transit_android_v2.models.tracking.BusInformation -import com.example.ithaca_transit_android_v2.models.Coordinate -import com.example.ithaca_transit_android_v2.models.Location -import com.example.ithaca_transit_android_v2.models.RouteOptions import com.squareup.moshi.JsonAdapter -import com.squareup.moshi.JsonReader import com.squareup.moshi.Moshi import com.squareup.moshi.Types.newParameterizedType import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory @@ -87,7 +83,6 @@ class NetworkUtils { val adapter: JsonAdapter = moshi.adapter(type) - Log.d("Route", ""+adapter.fromJson(arr.toString())); return adapter.fromJson(arr.toString()) ?: RouteOptions( emptyList(), emptyList(), @@ -119,7 +114,7 @@ class NetworkUtils { val body = client.newCall(request).execute().body?.string() val response = JSONObject(body!!) val arr = response.get("data") - Log.i("qwerty", "The server returns: "+response.toString()) + Log.i("qwerty", "The server returns: " + response.toString()) } // Returns an updated list of routes containing delays @@ -129,7 +124,7 @@ class NetworkUtils { val tripIds = ArrayList() for(route in routes) { for (i in route.directions) { - if (i.type != DirectionType.WALK) { + if (i.type != DirectionType.WALK && i.tripIds != null && i.tripIds.isNotEmpty()) { stopIds.add(i.busStops[0].stopId) tripIds.add(i.tripIds[0]) } @@ -149,6 +144,7 @@ class NetworkUtils { json.put("data", arr) val requestBody = json.toString().toRequestBody(mediaType) + val request: Request = Request.Builder() .url(url + "delays") .post(requestBody) @@ -156,7 +152,6 @@ class NetworkUtils { val body = client.newCall(request).execute().body?.string() val response = JSONObject(body!!) val data:JSONArray = response.getJSONArray("data") - Log.i("delays_from_server", data.toString()) return routes.mapIndexed { index, route -> val delay = data.getJSONObject(index).getString("delay") diff --git a/app/src/main/java/com/example/ithaca_transit_android_v2/NetworkingAdapters.kt b/app/src/main/java/com/example/ithaca_transit_android_v2/NetworkingAdapters.kt index eb542ee..e7bcf94 100644 --- a/app/src/main/java/com/example/ithaca_transit_android_v2/NetworkingAdapters.kt +++ b/app/src/main/java/com/example/ithaca_transit_android_v2/NetworkingAdapters.kt @@ -89,16 +89,17 @@ class RouteAdapter { @FromJson private fun fromJson(json: JsonRoute): Route { - val firstBus = if (json.directions[0].type == DirectionType.BUS) 0 else 1 - val boardInMins: Int = - if (json.directions.size != 1) Route.computeBoardInMin(json.directions[firstBus]) else 0 + val boardInMinIndex = if (json.directions[0].type == DirectionType.BUS || + (json.directions.size == 1 && json.directions[0].type == DirectionType.WALK)) { + 0 + } else 1 return Route( json.directions, json.startCoords, json.endCoords, json.arrival, json.depart, - boardInMins, + Route.computeBoardInMin(json.directions[boardInMinIndex]), null, json.travelDistance, json.endDestination diff --git a/app/src/main/java/com/example/ithaca_transit_android_v2/models/Direction.kt b/app/src/main/java/com/example/ithaca_transit_android_v2/models/Direction.kt index 62ac261..f6aa556 100644 --- a/app/src/main/java/com/example/ithaca_transit_android_v2/models/Direction.kt +++ b/app/src/main/java/com/example/ithaca_transit_android_v2/models/Direction.kt @@ -20,8 +20,8 @@ data class Direction( @Json(name = "routeId") val routeId: String?, @Json(name = "tripIds") - val tripIds: List, - //val delay: Int + val tripIds: List?, + val delay: Int?, val busNumber: Int?, val distance: Double ) \ No newline at end of file diff --git a/app/src/main/java/com/example/ithaca_transit_android_v2/presenters/MapPresenter.kt b/app/src/main/java/com/example/ithaca_transit_android_v2/presenters/MapPresenter.kt index 2bb634b..7371f82 100644 --- a/app/src/main/java/com/example/ithaca_transit_android_v2/presenters/MapPresenter.kt +++ b/app/src/main/java/com/example/ithaca_transit_android_v2/presenters/MapPresenter.kt @@ -64,7 +64,7 @@ class MapPresenter() { fun liveTrackingTEST(route: Route) { Thread(Runnable { for(direction in route.directions) { - if (direction.tripIds.isNotEmpty()) { + if (direction.tripIds != null && direction.tripIds.isNotEmpty()) { val busInfo = BusInformation( direction.tripIds.first(), direction.routeId diff --git a/app/src/main/java/com/example/ithaca_transit_android_v2/presenters/RouteOptionsPresenter.kt b/app/src/main/java/com/example/ithaca_transit_android_v2/presenters/RouteOptionsPresenter.kt index 96c92a6..c007ea7 100644 --- a/app/src/main/java/com/example/ithaca_transit_android_v2/presenters/RouteOptionsPresenter.kt +++ b/app/src/main/java/com/example/ithaca_transit_android_v2/presenters/RouteOptionsPresenter.kt @@ -103,6 +103,12 @@ class RouteOptionsPresenter( false, state.destLocation.name ) + if(routeOptions.boardingSoon != null && routeOptions.boardingSoon.isNotEmpty()) { + NetworkUtils().applyDelayRoutes(routeOptions.boardingSoon) + } + if(routeOptions.fromStop != null && routeOptions.fromStop.isNotEmpty()) { + NetworkUtils().applyDelayRoutes(routeOptions.fromStop) + } RouteListState(state.startLocation, state.destLocation, routeOptions) } else { state diff --git a/app/src/main/java/com/example/ithaca_transit_android_v2/ui_adapters/RouteListViewAdapter.kt b/app/src/main/java/com/example/ithaca_transit_android_v2/ui_adapters/RouteListViewAdapter.kt index af65592..b282550 100644 --- a/app/src/main/java/com/example/ithaca_transit_android_v2/ui_adapters/RouteListViewAdapter.kt +++ b/app/src/main/java/com/example/ithaca_transit_android_v2/ui_adapters/RouteListViewAdapter.kt @@ -11,6 +11,7 @@ import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import com.example.ithaca_transit_android_v2.R import com.example.ithaca_transit_android_v2.Repository +import com.example.ithaca_transit_android_v2.models.Direction import com.example.ithaca_transit_android_v2.models.DirectionType import com.example.ithaca_transit_android_v2.models.Route import com.example.ithaca_transit_android_v2.views.BusNumberComponent @@ -21,6 +22,7 @@ import java.math.RoundingMode import java.text.SimpleDateFormat import java.util.* import kotlin.collections.ArrayList +import kotlin.math.abs // Recycler view adapter that fills each route card with the list of Route objects that is returned by our RouteOptions networking call. class RouteListViewAdapter(context: Context, var userList: ArrayList) : @@ -150,7 +152,9 @@ class RouteListViewAdapter(context: Context, var userList: ArrayList= 60) { + routeObj.boardInMin + firstBusDirectionDelay / 60 + } else { + routeObj.boardInMin + } + val boardHours = boardInMin / 60 + val boardMins = boardInMin % 60 var timeString = "in " - if(boardHours >= 1) { + if (boardHours >= 1) { timeString += "$boardHours hr" - if(boardMins >= 0) { + if (boardMins >= 0) { timeString += " " } } - if(boardMins >= 0) { + if (boardMins >= 0) { timeString += "$boardMins min" } - if(boardMins == 0 && boardHours == 0) { + if (boardMins == 0 && boardHours == 0) { timeString = "now" } p0.description?.text = routeCardContext.getString(R.string.board_in_mins, timeString) + p0.delay.text = routeCardContext.getString(R.string.on_time) + p0.delay.setTypeface(null, Typeface.BOLD) + if (firstBusDirectionDelay != null && abs(firstBusDirectionDelay) >= 60) { + // This requires some further investigation. If a route is early, it's probably already + // passed. Maybe don't draw onto ListView? In this case boardMins is most likely negative I + // believe. + if (firstBusDirectionDelay <= -60) { + p0.delay.text = routeCardContext.getString( + R.string.early, + sdf.format(Date(firstBusDirection!!.startTime.time + firstBusDirectionDelay * 1000)) + ) + } else { + p0.delay.text = routeCardContext.getString( + R.string.late, + sdf.format(Date(firstBusDirection!!.startTime.time + firstBusDirectionDelay * 1000)) + ) + p0.delay.setTextColor(routeCardContext.getColor(R.color.delay)) + } + } - val sdf = SimpleDateFormat("h:mm a", Locale.US) val routeInterval: String = sdf.format(routeObj.depart) + " - " + sdf.format(routeObj.arrival) p0.routeDuration.text = routeInterval @@ -248,21 +289,21 @@ class RouteListViewAdapter(context: Context, var userList: ArrayList 0 && routeObj.directions[i - 1].type == DirectionType.BUS && stopName != routeObj.endDestination, + i > 0 && routeObj.directions[i - 1].type == DirectionType.BUS && stopName != routeObj.endDestination, drawSegmentBelow = isBusRoute, - isDestination = stopName == routeObj.endDestination) + isDestination = stopName == routeObj.endDestination + ) p0.routeDynamicList.addView(directionLayout) - if(isBusRoute && direction.routeId != null) { + if (isBusRoute && direction.routeId != null) { val busImageView = createBusIconComponent(direction.routeId) p0.routeDynamicList.addView(busImageView) } - if(direction.busStops.isNotEmpty()) { + if (direction.busStops.isNotEmpty()) { val busStop = direction.busStops.last() - //Only considers adding the last bus stop to the view if it isn't the name - //of the next direction / isn't the end destination - if(i < routeObj.directions.lastIndex && busStop.name != routeObj.directions[i+1].name) { + // Only considers adding the last bus stop to the view if it isn't the name + // of the next direction / isn't the end destination. Prevents extra direction layout + // drawn for the same stop. Still considers drawing direction layout if last bus stop has same + // name as end direction, but end direction is some walking direction + if (i < routeObj.directions.lastIndex && + (busStop.name != routeObj.directions[i + 1].name || + routeObj.directions[i + 1].type == DirectionType.WALK) + ) { p0.routeDynamicList.addView( createDirectionLinearLayout( busStop.name, @@ -305,10 +352,10 @@ class RouteListViewAdapter(context: Context, var userList: ArrayList#3F51B5 #303F9F #f2655d + #D82D4D #FAFAFA #212121 #EEEEEE diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9169f86..d97fb47 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2,4 +2,6 @@ Ithaca Transit Board %1$s On Time + Late - %1$s + Early - %1$s diff --git a/build.gradle b/build.gradle index 90dff3d..50f355b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,13 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.72' + ext.kotlin_version = '1.4.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.2' + classpath 'com.android.tools.build:gradle:4.1.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 04785e9..3fd1932 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Oct 03 19:01:14 EDT 2020 +#Thu Dec 03 22:29:52 EST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip