Commit d5a9d3ed authored by Myriam Begel's avatar Myriam Begel

Save routes' time into DB

parent 48060ab6
......@@ -17,6 +17,7 @@ class AppRepository(val context : Context) {
private val mEventsAndDaysDAO = db.eventsAndDaysDao()
private val mExpenseDAO = db.expenseDao()
private val mTripDayDAO = db.tripDayDao()
private val mRouteBtwEventsDAO = db.routeBtwEventsDao()
private val allTrips = mTripDAO.getAllTrips()
// TRIPDAYS
......@@ -199,4 +200,29 @@ class AppRepository(val context : Context) {
return null
}
}
// ROUTES
fun getRoutesByTripId(tripId: String) = mRouteBtwEventsDAO.getRoutesByTripId(tripId)
fun insertRoute(element: RouteBtwEvents) {
insertRouteAsyncTask(mRouteBtwEventsDAO).execute(element)
}
fun insertAllRoutes(elements: List<RouteBtwEvents>) {
insertAllRoutesAsyncTask(mRouteBtwEventsDAO).execute(elements)
}
private class insertRouteAsyncTask (private val mAsyncRouteBtwEventsDAO: RouteBtwEventsDAO) :
AsyncTask<RouteBtwEvents, Void, Void>() {
override fun doInBackground(vararg params: RouteBtwEvents): Void? {
mAsyncRouteBtwEventsDAO.insertRoute(params[0])
return null
}
}
private class insertAllRoutesAsyncTask (private val mAsyncRouteBtwEventsDAO: RouteBtwEventsDAO) :
AsyncTask<List<RouteBtwEvents>, Void, Void>() {
override fun doInBackground(vararg params: List<RouteBtwEvents>): Void? {
mAsyncRouteBtwEventsDAO.insertAllRoutes(params[0])
return null
}
}
}
\ No newline at end of file
......@@ -12,7 +12,7 @@ const val DATABASE_NAME = "bonvoyage.db"
*/
@Database(entities = arrayOf(
Trip::class, Event::class, Expense::class,
TripDay::class, EventsAndDays::class),
TripDay::class, EventsAndDays::class, RouteBtwEvents::class),
version = 2)
abstract class AppRoomDatabase : RoomDatabase() {
......@@ -21,6 +21,7 @@ abstract class AppRoomDatabase : RoomDatabase() {
abstract fun expenseDao(): ExpenseDAO
abstract fun tripDayDao(): TripDayDAO
abstract fun eventsAndDaysDao(): EventsAndDaysDAO
abstract fun routeBtwEventsDao(): RouteBtwEventsDAO
companion object {
......
......@@ -2,20 +2,20 @@ package fr.begel.apps.bonvoyage.persistence
import android.arch.persistence.room.*
import android.arch.persistence.room.ForeignKey.CASCADE
import com.here.android.mpa.routing.Route
import com.here.android.mpa.common.GeoCoordinate
import java.util.*
@Entity(tableName = "routes",
foreignKeys = [
(ForeignKey(parentColumns = ["id"], childColumns = ["event_id_start"],
onDelete = CASCADE, entity = Event::class)),
ForeignKey(parentColumns = ["id"], childColumns = ["event_id_destination"],
onDelete = CASCADE, entity = Event::class)],
indices = [Index("event_id_start"), Index("event_id_destination")])
ForeignKey(parentColumns = ["tripid"], childColumns = ["trip_id"],
onDelete = CASCADE, entity = Trip::class)],
indices = [Index("trip_id")])
@TypeConverters(Converters::class)
data class RouteBtwEvents(
@ColumnInfo(name = "event_id_start") val eventIdStart: String,
@ColumnInfo(name = "event_id_destination") val eventIdDest: String,
@ColumnInfo(name = "route") var route: Route? = null,
@ColumnInfo(name = "trip_id") val tripId: String,
@ColumnInfo(name = "coordinate_start") val coordinateStart: GeoCoordinate,
@ColumnInfo(name = "coordinate_end") val coordinateEnd: GeoCoordinate,
@ColumnInfo(name = "mode") var mode: String,
@ColumnInfo(name = "tta") var tta: Int? = null,
@PrimaryKey@ColumnInfo(name = "route_id") val routeId: String = UUID.randomUUID().toString()
)
\ No newline at end of file
package fr.begel.apps.bonvoyage.persistence
import android.arch.lifecycle.LiveData
import android.arch.persistence.room.*
/**
* Data Access Object for the trip table.
*/
@Dao
interface RouteBtwEventsDAO {
@Query("SELECT * FROM routes WHERE trip_id = :tripId")
fun getRoutesByTripId(tripId: String): LiveData<List<RouteBtwEvents>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertRoute(element: RouteBtwEvents)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAllRoutes(elements: List<RouteBtwEvents>)
}
\ No newline at end of file
......@@ -138,15 +138,15 @@ class EventAdapter :
holder.cardDay.background = holder.view.context.getDrawable(R.color.colors13)
holder.item_day_name.text = orEmpty(element.name)
holder.item_day_date.text = calToShortText(element.date)
holder.item_day_nb.text = ""
holder.item_day_nb.text = "Jour ${element.number + 1}"
holder.cardEvent.visibility = View.GONE
}
private fun fillRoute(element: RouteBtwEvents, holder: ViewHolder){
holder.cardDay.visibility = View.VISIBLE
holder.cardDay.background = holder.view.context.getDrawable(R.color.colors50)
holder.item_day_name.text = element.route?.getTta(Route.TrafficPenaltyMode.DISABLED, Route.WHOLE_ROUTE)?.duration.toString()
holder.item_day_date.text = element.route?.routePlan?.routeOptions?.transportMode.toString()
holder.item_day_name.text = fromSecondToTime(element.tta)
holder.item_day_date.text = element.mode
holder.item_day_nb.text = ""
holder.cardEvent.visibility = View.GONE
}
......
......@@ -2,10 +2,7 @@ package fr.begel.apps.bonvoyage.ui
import android.arch.lifecycle.ViewModel
import android.content.Context
import fr.begel.apps.bonvoyage.persistence.AppRepository
import fr.begel.apps.bonvoyage.persistence.Event
import fr.begel.apps.bonvoyage.persistence.Expense
import fr.begel.apps.bonvoyage.persistence.TripDay
import fr.begel.apps.bonvoyage.persistence.*
class EventViewModel(val context: Context) : ViewModel() {
......@@ -36,4 +33,9 @@ class EventViewModel(val context: Context) : ViewModel() {
fun getTripWithDays(tripId: String) = mRepository.getTripWithDays(tripId)
fun getRoutesByTripId(tripId: String) = mRepository.getRoutesByTripId(tripId)
fun insertRoute(element: RouteBtwEvents) = mRepository.insertRoute(element)
fun insertAllRoutes(elements: List<RouteBtwEvents>) = mRepository.insertAllRoutes(elements)
}
......@@ -45,7 +45,9 @@ class EventsOfTrip : Fragment(),
private var mLayoutManager = LinearLayoutManager(context)
private var mapEngine: MapEngine = MapEngine.getInstance()
private val routeManager: RouteManager = RouteManager()
private val routesBtwEvents = ArrayList<RouteBtwEvents>()
private val routesBtwEventsToCalculate = ArrayList<RouteBtwEvents>()
private var existingRoutesBtwEvents : ArrayList<RouteBtwEvents>? = null
private var toInsertRoutesBtwEvents : ArrayList<RouteBtwEvents> = ArrayList()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
......@@ -87,6 +89,13 @@ class EventsOfTrip : Fragment(),
}
}
)
viewModel.getRoutesByTripId(tripId!!).observe({this.lifecycle}) {
routes ->
Log.d("Help", "viewModel observe routes, size=${routes?.size}")
existingRoutesBtwEvents = routes as ArrayList<RouteBtwEvents>
updateDataSet()
}
mapEngine.init(context){}
}
......@@ -98,7 +107,7 @@ class EventsOfTrip : Fragment(),
Log.d("Help", "Position to Scroll: $position, dayId: $toScroll")
mLayoutManager.scrollToPositionWithOffset(position, 0)
Log.d("Help", "HashMap size : ${allEventsMap.size} - Days size : ${daysWithEventsId.size}")
if (daysWithEventsId.isNotEmpty() and allEventsMap.isNotEmpty()){
if (daysWithEventsId.isNotEmpty() and allEventsMap.isNotEmpty() and (existingRoutesBtwEvents != null)){
Log.d("Help", "UpdateDataSet not empty")
days = OrderTripDaysWithEvents(allEventsMap, daysWithEventsId).days
//mDataSet = flattenTripDays(days)
......@@ -187,16 +196,36 @@ class EventsOfTrip : Fragment(),
}
}
private fun isRouteOf(event1: Event, event2: Event, routeBtwEvents: RouteBtwEvents): Boolean{
return ((coordinateEnd(event1) == routeBtwEvents.coordinateStart)
and (event2.coordinate == routeBtwEvents.coordinateEnd))
}
private fun coordinateEnd(event: Event): GeoCoordinate? {
return event.coordinate_end ?: event.coordinate
}
private fun extractElements(trip_days: List<TripDayWithEvents>): ArrayList<Any>{
val allItems = ArrayList<Any>()
val routes = ArrayList<Pair<GeoCoordinate, GeoCoordinate>>()
for (day in trip_days){
allItems.add(day.tripDay)
for (j in 0..day.events.size - 2){
allItems.add(day.events[j])
val routeBtwEvent = RouteBtwEvents(day.events[j].id, day.events[j+1].id)
allItems.add(routeBtwEvent)
routesBtwEvents.add(routeBtwEvent)
val event1 = day.events[j]
val event2 = day.events[j+1]
allItems.add(event1)
if ((coordinateEnd(event1) != null) and (event2.coordinate != null)){
var routeBtwEvent = existingRoutesBtwEvents!!.find{ r ->
isRouteOf(day.events[j], day.events[j+1], r)}
if (routeBtwEvent == null) {
routeBtwEvent = RouteBtwEvents(
day.tripDay.tripId, coordinateEnd(event1)!!,
event2.coordinate!!, "CAR"
)
routesBtwEventsToCalculate.add(routeBtwEvent)
}
allItems.add(routeBtwEvent)
}
}
if (day.events.size > 0)
allItems.add(day.events.last())
......@@ -209,34 +238,30 @@ class EventsOfTrip : Fragment(),
override fun afterCalculateRoute(route: Route?) {
Log.d("Help", "Start After calculate route")
if (route != null) {
val routeBtwEvent = routesBtwEvents.removeAt(0)
routeBtwEvent.route = route
val routeBtwEvent = routesBtwEventsToCalculate.removeAt(0)
routeBtwEvent.tta = route.getTta(Route.TrafficPenaltyMode.DISABLED, Route.WHOLE_ROUTE).duration
toInsertRoutesBtwEvents.add(routeBtwEvent)
viewAdapter.setEvents(mDataSet)
Log.d("Help", "Assigned a route for ${route.start}-${route.destination}")
}
if (routesBtwEvents.isNotEmpty()){
val first = routesBtwEvents.first()
val cooStart = allEventsMap[first.eventIdStart]!!.coordinate_end
?: allEventsMap[first.eventIdStart]!!.coordinate
val cooDest = allEventsMap[first.eventIdDest]!!.coordinate
if ((cooStart != null) and (cooDest != null)){
val routeOptions = RouteOptions().apply {
transportMode = RouteOptions.TransportMode.CAR
routeType = RouteOptions.Type.FASTEST
}
val routePlan = RoutePlan()
routePlan.routeOptions = routeOptions
routePlan.addWaypoint(cooStart)
routePlan.addWaypoint(cooDest)
val rl = RouteListener()
rl.setListener(this)
Log.d("Help", "Launch calculate route ${cooStart}-${cooDest}")
routeManager.calculateRoute(routePlan, rl)
} else {
Log.d("Help", "One point null - next")
routesBtwEvents.removeAt(0)
afterCalculateRoute(null)
if (routesBtwEventsToCalculate.isNotEmpty()){
val routeBtwEvents = routesBtwEventsToCalculate.first()
val routeOptions = RouteOptions().apply {
transportMode = RouteOptions.TransportMode.valueOf(routeBtwEvents.mode)
routeType = RouteOptions.Type.FASTEST
}
val routePlan = RoutePlan()
routePlan.routeOptions = routeOptions
routePlan.addWaypoint(routeBtwEvents.coordinateStart)
routePlan.addWaypoint(routeBtwEvents.coordinateEnd)
val rl = RouteListener()
rl.setListener(this)
Log.d("Help", "Launch calculate route " +
"${routeBtwEvents.coordinateStart} - ${routeBtwEvents.coordinateEnd}")
routeManager.calculateRoute(routePlan, rl)
} else {
viewModel.insertAllRoutes(toInsertRoutesBtwEvents)
toInsertRoutesBtwEvents = ArrayList()
}
}
}
......@@ -251,9 +276,7 @@ class RouteListener: RouteManager.Listener {
Log.d("Help", "onCalculateRouteFinished had an error ${error.toString()}")
}
}
override fun onProgress(p0: Int) {
Log.d("Help", "onProgress routeListener $p0")
}
override fun onProgress(p0: Int) {}
private var mListener: AfterCalculateRouteListener? = null
fun setListener(listener: AfterCalculateRouteListener) {mListener = listener}
......
......@@ -18,6 +18,8 @@ import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.util.concurrent.locks.Lock
import kotlin.concurrent.withLock
val local: Locale = Locale.FRANCE
......@@ -228,4 +230,22 @@ fun restoreAppDbFromDownloadFolder(context: Context): Boolean {
} else
Toast.makeText(context, "Storage not readable, restore not possible", Toast.LENGTH_LONG).show()
return false
}
//REF: https://jonnyzzz.com/blog/2017/03/01/guarded-by-lock/
class GuardedByLock<out L: Lock, out T>(
val lock: L,
val state: T
) {
inline fun <Y> runWithLock(action: T.() -> Y) = lock.withLock { state.action() }
}
fun fromSecondToTime(seconds: Int?): String{
if (seconds == null) return "Temps inconnu"
if (seconds < 60) return "$seconds s"
var minutes = seconds / 60
if (minutes < 60) return "$minutes min"
val hours = minutes / 60
minutes = minutes.rem(60)
return "$hours h $minutes min"
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment