Skip to content

Commit

Permalink
Chris/delays (#52)
Browse files Browse the repository at this point in the history
* Update xml files

* Add some non-null checks

* Add additional case check for ListViewAdapter

* Add delays to each List<Route> in RouteOptions

* Fix boardInMin for directions that were just a single bus

* Add some log statements to NetworkUtils.kt

* add V2 change

* Remove extra log statements from testing

* Add delay information to ListView cards

* Add style changes

* Add style changes
  • Loading branch information
ckdesir authored Dec 5, 2020
1 parent f0cacf3 commit 27834e6
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -87,7 +83,6 @@ class NetworkUtils {

val adapter: JsonAdapter<RouteOptions> = moshi.adapter(type)

Log.d("Route", ""+adapter.fromJson(arr.toString()));
return adapter.fromJson(arr.toString()) ?: RouteOptions(
emptyList(),
emptyList(),
Expand Down Expand Up @@ -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
Expand All @@ -129,7 +124,7 @@ class NetworkUtils {
val tripIds = ArrayList<String>()
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])
}
Expand All @@ -149,14 +144,14 @@ class NetworkUtils {
json.put("data", arr)

val requestBody = json.toString().toRequestBody(mediaType)

val request: Request = Request.Builder()
.url(url + "delays")
.post(requestBody)
.build()
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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ data class Direction(
@Json(name = "routeId")
val routeId: String?,
@Json(name = "tripIds")
val tripIds: List<String>,
//val delay: Int
val tripIds: List<String>?,
val delay: Int?,
val busNumber: Int?,
val distance: Double
)
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<RouteListAdapterObject>) :
Expand Down Expand Up @@ -150,7 +152,9 @@ class RouteListViewAdapter(context: Context, var userList: ArrayList<RouteListAd
grayDotParams.leftMargin = 10
grayDotParams.topMargin = 6

val grayDot1 = DirectionDot(routeCardContext, "gray", false, false, false, 6f, 0f, 0f)
val grayDot1 = DirectionDot(routeCardContext,
"gray", false, false,
false, 6f, 0f, 0f)
grayDot1.layoutParams = grayDotParams
dotsHolder.addView(grayDot1)

Expand Down Expand Up @@ -220,26 +224,63 @@ class RouteListViewAdapter(context: Context, var userList: ArrayList<RouteListAd
private fun drawRouteCard(p0: ViewHolder, p1: Int) {
p0.routeDynamicList.removeAllViews()
val routeObj: Route = userList[p1].data as Route
val sdf = SimpleDateFormat("h:mm a", Locale.US)

val boardHours = routeObj.boardInMin / 60
val boardMins = routeObj.boardInMin % 60
var firstBusDirection: Direction? = null
for (i in routeObj.directions.indices) {
val direction = routeObj.directions[i]
if (direction.type == DirectionType.BUS) {
firstBusDirection = direction
break
}
}
val firstBusDirectionDelay: Int? = if (firstBusDirection?.delay != null) {
firstBusDirection.delay
} else {
null
}
val boardInMin = if (firstBusDirectionDelay != null && abs(firstBusDirectionDelay) >= 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
Expand All @@ -248,21 +289,21 @@ class RouteListViewAdapter(context: Context, var userList: ArrayList<RouteListAd
val isOnlyWalking =
routeObj.directions.size == 1 && routeObj.directions[0].type == DirectionType.WALK
var isStopDestinationName = true
for(i in routeObj.directions.indices) {
for (i in routeObj.directions.indices) {
val direction = routeObj.directions[i]
if(direction.type == DirectionType.WALK) {
//Adds a walking component given whatever distance is in the direction object
if (direction.type == DirectionType.WALK) {
// Adds a walking component given whatever distance is in the direction object
var distance = "" + direction.distance.toInt() + " ft"
if(isOnlyWalking) {
if (isOnlyWalking) {
distance = "" + BigDecimal(routeObj.travelDistance).setScale(
2,
RoundingMode.HALF_EVEN
) + " mi"
}
val walkingImageView = createWalkingComponent(distance, true)
//Only considers drawing a direction linear layout from whatever starting location if
//the destination is at the start / is only walking
if(i == 0 || isOnlyWalking) {
// Only considers drawing a direction linear layout from whatever starting location if
// the destination is at the start / is only walking
if (i == 0 || isOnlyWalking) {
Repository.startLocation?.name?.let {
val directionLayout = createDirectionLinearLayout(
it,
Expand All @@ -283,19 +324,25 @@ class RouteListViewAdapter(context: Context, var userList: ArrayList<RouteListAd
stopName,
isBusStop = isBusRoute,
drawSegmentAbove =
i > 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,
Expand All @@ -305,10 +352,10 @@ class RouteListViewAdapter(context: Context, var userList: ArrayList<RouteListAd
isDestination = false
)
)
//This considers if the destination happens to be the last stop of the current
//direction
} else if(i == routeObj.directions.lastIndex) {
if(busStop.name != routeObj.endDestination) isStopDestinationName = false
// This considers if the destination happens to be the last stop of the current
// direction
} else if (i == routeObj.directions.lastIndex) {
if (busStop.name != routeObj.endDestination) isStopDestinationName = false
p0.routeDynamicList.addView(
createDirectionLinearLayout(
busStop.name,
Expand All @@ -324,8 +371,13 @@ class RouteListViewAdapter(context: Context, var userList: ArrayList<RouteListAd
}
// Creates end destination layout for route that's just walking, hides boarding text if so
// Also creates an empty walking component to the destination if last stop wasn't destination
if(isOnlyWalking || !isStopDestinationName) {
if(!isStopDestinationName) p0.routeDynamicList.addView(createWalkingComponent("", false))
if (isOnlyWalking || !isStopDestinationName) {
if (!isStopDestinationName) p0.routeDynamicList.addView(
createWalkingComponent(
"",
false
)
)
val directionLayout = createDirectionLinearLayout(
routeObj.endDestination,
isBusStop = false,
Expand All @@ -334,7 +386,7 @@ class RouteListViewAdapter(context: Context, var userList: ArrayList<RouteListAd
isDestination = true
)
p0.routeDynamicList.addView(directionLayout)
if(isOnlyWalking) {
if (isOnlyWalking) {
p0.description.visibility = View.GONE
p0.delay.visibility = View.GONE
}
Expand Down Expand Up @@ -372,4 +424,4 @@ class RouteListViewAdapter(context: Context, var userList: ArrayList<RouteListAd
this.userList = updatedInfo
notifyDataSetChanged()
}
}
}
1 change: 1 addition & 0 deletions app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<color name="primary">#3F51B5</color>
<color name="primaryDark">#303F9F</color>
<color name="red">#f2655d</color>
<color name="delay">#D82D4D</color>
<color name="routeBackground">#FAFAFA</color>
<color name="routeDetails">#212121</color>
<color name="routeDetailsHeader">#EEEEEE</color>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
<string name="app_name">Ithaca Transit</string>
<string name="board_in_mins">Board %1$s</string>
<string name="on_time">On Time</string>
<string name="late">Late - %1$s</string>
<string name="early">Early - %1$s</string>
</resources>
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 27834e6

Please sign in to comment.