Author: Adam Pioterek <adam.pioterek@protonmail.ch>
all models fixed
.idea/kotlinc.xml | 6 .idea/misc.xml | 2 app/src/main/java/ml/adamsprogs/bimba/extensions.kt | 13 app/src/main/java/ml/adamsprogs/bimba/models/Departure.kt | 28 app/src/main/java/ml/adamsprogs/bimba/models/DeparturesAdapter.kt | 11 app/src/main/java/ml/adamsprogs/bimba/models/Favourite.kt | 14 app/src/main/java/ml/adamsprogs/bimba/models/FavouriteStorage.kt | 12 app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt | 24 app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt | 35
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000000000000000000000000000000000000..0dd4b354636ab01a5a9aee4a507c42898cb5b291 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="Kotlin2JvmCompilerArguments"> + <option name="jvmTarget" value="1.8" /> + </component> +</project> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index ba7052b8197ddf8ba8756022d905d03055c7ad60..635999df1e86791ad3787e455b4524e4d8879b93 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -24,7 +24,7 @@ </value> </option> </component> - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <output url="file://$PROJECT_DIR$/build/classes" /> </component> <component name="ProjectType"> diff --git a/app/src/main/java/ml/adamsprogs/bimba/extensions.kt b/app/src/main/java/ml/adamsprogs/bimba/extensions.kt index 573413e9eb80eb743d273913ad8c1cee9361c056..245856cb99111d38675fc1780a5dd7047b9e9095 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/extensions.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/extensions.kt @@ -15,11 +15,22 @@ internal fun String.toPascalCase(): String { //check val builder = StringBuilder(this) var isLastCharSeparator = true builder.forEach { - isLastCharSeparator = if ((it in 'a'..'z' || it in 'A'..'Z') && isLastCharSeparator){ + isLastCharSeparator = if ((it in 'a'..'z' || it in 'A'..'Z') && isLastCharSeparator) { it.toUpperCase() false } else true } return builder.toString() +} + +internal fun Calendar.rollTime(seconds: Int): Calendar { + val hour = seconds / 3600 + val minute = (seconds % 3600) / 60 + val second = (seconds % 60) + this.set(Calendar.HOUR_OF_DAY, hour) + this.set(Calendar.MINUTE, minute) + this.set(Calendar.SECOND, second) + this.set(Calendar.MILLISECOND, 0) + return this } \ No newline at end of file diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/Departure.kt b/app/src/main/java/ml/adamsprogs/bimba/models/Departure.kt index 66f433fa96b1afa00711e5024935f7535f1b8933..fe15418697ab681c70a7a5958c0277768286d6c4 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/models/Departure.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/models/Departure.kt @@ -1,5 +1,6 @@ package ml.adamsprogs.bimba.models +import ml.adamsprogs.bimba.rollTime import org.onebusaway.gtfs.model.AgencyAndId import java.util.* import kotlin.collections.ArrayList @@ -15,7 +16,7 @@ return modification.isNotEmpty() } override fun toString(): String { - return "$line|$mode|$time|$lowFloor|$modification|$direction|$vm|$tomorrow|$onStop" + return "$line|${mode.joinToString(";")}|$time|$lowFloor|${modification.joinToString(";")}|$direction|$vm|$tomorrow|$onStop" } fun copy(): Departure { @@ -25,7 +26,7 @@ companion object { private fun filterDepartures(departures: List<Departure>): ArrayList<Departure> { val filtered = ArrayList<Departure>() - val lines = HashMap<String, Int>() + val lines = HashMap<AgencyAndId, Int>() val sortedDepartures = departures.sortedBy { it.timeTill() } for (departure in sortedDepartures) { var lineExistedTimes = lines[departure.line] @@ -38,20 +39,20 @@ } return filtered } - fun createDepartures(stopId: String): Map<String, List<Departure>> { + fun createDepartures(stopId: AgencyAndId): Map<AgencyAndId, List<Departure>> { val timetable = Timetable.getTimetable() val departures = timetable.getStopDepartures(stopId) return createDepartures(departures) } - fun createDepartures(departures: Map<String, List<Departure>>): Map<String, List<Departure>> { //todo if departure.timeTill < 0 -> show ‘just departed’ - val moreDepartures = HashMap<String, ArrayList<Departure>>() + fun createDepartures(departures: Map<AgencyAndId, List<Departure>>): Map<AgencyAndId, List<Departure>> { //todo if departure.timeTill < 0 -> show ‘just departed’ + val moreDepartures = HashMap<AgencyAndId, ArrayList<Departure>>() for ((k, v) in departures) { moreDepartures[k] = ArrayList() for (departure in v) moreDepartures[k]!!.add(departure.copy()) } - val rolledDepartures = HashMap<String, ArrayList<Departure>>() + val rolledDepartures = HashMap<AgencyAndId, ArrayList<Departure>>() for ((_, tomorrowDepartures) in moreDepartures) { tomorrowDepartures.forEach { it.tomorrow = true } @@ -70,20 +71,21 @@ fun fromString(string: String): Departure { val array = string.split("|") if (array.size != 9) throw IllegalArgumentException() - return Departure(array[0], array[1], array[2], array[3] == "true", array[4], array[5], - array[6] == "true", array[7] == "true", array[8] == "true") + return Departure(AgencyAndId.convertFromString(array[0]), + array[1].split(";").map { Integer.parseInt(it) }, + Integer.parseInt(array[2]), array[3] == "true", + array[4].split(";"), array[5], array[6] == "true", + array[7] == "true", array[8] == "true") } } fun timeTill(): Long { - val time = Calendar.getInstance() - time.set(Calendar.HOUR_OF_DAY, Integer.parseInt(this.time.split(":")[0])) - time.set(Calendar.MINUTE, Integer.parseInt(this.time.split(":")[1])) - time.set(Calendar.SECOND, 0) - time.set(Calendar.MILLISECOND, 0) + val time = Calendar.getInstance().rollTime(this.time) val now = Calendar.getInstance() if (this.tomorrow) time.add(Calendar.DAY_OF_MONTH, 1) return (time.timeInMillis - now.timeInMillis) / (1000 * 60) } + + val lineText: String = Timetable.getTimetable().getLineNumber(line) } \ No newline at end of file diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/DeparturesAdapter.kt b/app/src/main/java/ml/adamsprogs/bimba/models/DeparturesAdapter.kt index 57a1d726719af4607ec42df4cdfa59809fb43d8b..a105bdc9c8d135042e98fa9011b37be48ac7ab0e 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/models/DeparturesAdapter.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/models/DeparturesAdapter.kt @@ -12,6 +12,7 @@ import android.widget.TextView import ml.adamsprogs.bimba.R import android.view.LayoutInflater import ml.adamsprogs.bimba.Declinator +import ml.adamsprogs.bimba.rollTime import java.util.* class DeparturesAdapter(val context: Context, private val departures: List<Departure>?, private val relativeTime: Boolean) : @@ -42,9 +43,7 @@ return } val departure = departures[position] val now = Calendar.getInstance() - val departureTime = Calendar.getInstance() - departureTime.set(Calendar.HOUR_OF_DAY, Integer.parseInt(departure.time.split(":")[0])) - departureTime.set(Calendar.MINUTE, Integer.parseInt(departure.time.split(":")[1])) + val departureTime = Calendar.getInstance().rollTime(departure.time) if (departure.tomorrow) departureTime.add(Calendar.DAY_OF_MONTH, 1) @@ -52,14 +51,14 @@ val departureIn = (departureTime.timeInMillis - now.timeInMillis) / (1000 * 60) val timeString: String timeString = if (departureIn > 60 || departureIn < 0 || !relativeTime) - context.getString(R.string.departure_at, departure.time) + context.getString(R.string.departure_at, "${departureTime.get(Calendar.HOUR_OF_DAY)}:${departureTime.get(Calendar.MINUTE)}") else if (departureIn > 0 && !departure.onStop) context.getString(Declinator.decline(departureIn), departureIn.toString()) else context.getString(R.string.now) val line = holder?.lineTextView - line?.text = departure.line + line?.text = departure.lineText val time = holder?.timeTextView time?.text = timeString val direction = holder?.directionTextView @@ -79,7 +78,7 @@ AlertDialog.Builder(context) .setPositiveButton(context.getText(android.R.string.ok), { dialog: DialogInterface, _: Int -> dialog.cancel() }) .setCancelable(true) - .setMessage(departure.modification) + .setMessage(departure.modification.joinToString("; ")) .create().show() } } diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/Favourite.kt b/app/src/main/java/ml/adamsprogs/bimba/models/Favourite.kt index 91817eaa814f7d1bf9206b783fc5c7d11d887820..b341c64d7097628561e3d62935bfbd7fd32f8626 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/models/Favourite.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/models/Favourite.kt @@ -4,7 +4,7 @@ import android.os.Parcel import android.os.Parcelable import android.util.Log import ml.adamsprogs.bimba.MessageReceiver -import ml.adamsprogs.bimba.getMode +import org.onebusaway.gtfs.model.AgencyAndId import java.util.* import kotlin.collections.ArrayList import kotlin.collections.HashMap @@ -111,10 +111,10 @@ .minBy { it.timeTill() } } private fun nowDepartures(): ArrayList<Departure> { - val today = Calendar.getInstance().getMode() + val today = timetable.getServiceForToday() val tomorrowCal = Calendar.getInstance() tomorrowCal.add(Calendar.DAY_OF_MONTH, 1) - val tomorrow = tomorrowCal.getMode() + val tomorrow = timetable.getServiceForTomorrow() val departures = timetable.getStopDepartures(timetables) val todayDepartures = departures[today]!! @@ -128,18 +128,18 @@ tomorrowDepartures.forEach { twoDayDepartures.add(it) } return twoDayDepartures } - fun allDepartures(): Map<String, List<Departure>> { - val departures = timetable.getStopDepartures(timetables) as HashMap<String, ArrayList<Departure>> + fun allDepartures(): Map<AgencyAndId, List<Departure>> { + val departures = timetable.getStopDepartures(timetables) as HashMap<AgencyAndId, ArrayList<Departure>> if (vmDepartures.isNotEmpty()) { - val today = Calendar.getInstance().getMode() + val today = timetable.getServiceForToday() departures[today] = vmDepartures } return Departure.createDepartures(departures) } - fun fullTimetable(): Map<String, List<Departure>>? { + fun fullTimetable(): Map<AgencyAndId, List<Departure>>? { return timetable.getStopDepartures(timetables) } diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/FavouriteStorage.kt b/app/src/main/java/ml/adamsprogs/bimba/models/FavouriteStorage.kt index c385320d575062e8d3f85134702ad6f786df06e6..b79f0eb8a15d27ddf173e8c091c4944b04b67191 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/models/FavouriteStorage.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/models/FavouriteStorage.kt @@ -5,6 +5,7 @@ import android.content.SharedPreferences import com.google.gson.Gson import com.google.gson.JsonArray import com.google.gson.JsonObject +import org.onebusaway.gtfs.model.AgencyAndId class FavouriteStorage private constructor(context: Context) : Iterable<Favourite> { @@ -35,7 +36,11 @@ val favouritesString = preferences.getString("favourites", "{}") val favouritesMap = Gson().fromJson(favouritesString, JsonObject::class.java) for ((name, jsonTimetables) in favouritesMap.entrySet()) { val timetables = HashSet<Plate>() - jsonTimetables.asJsonArray.mapTo(timetables) { Plate(it.asJsonObject["line"].asString, it.asJsonObject["stop"].asString, null) } + jsonTimetables.asJsonArray.mapTo(timetables) { + Plate(AgencyAndId.convertFromString(it.asJsonObject["line"].asString), + AgencyAndId.convertFromString(it.asJsonObject["stop"].asString), + it.asJsonObject["headsign"].asString, null) + } favourites[name] = Favourite(name, timetables) } } @@ -74,8 +79,9 @@ for ((name, favourite) in favourites) { val timetables = JsonArray() for (timetable in favourite.timetables) { val element = JsonObject() - element.addProperty("stop", timetable.stop) - element.addProperty("line", timetable.line) + element.addProperty("stop", timetable.stop.toString()) + element.addProperty("line", timetable.line.toString()) + element.addProperty("headsign", timetable.headsign) timetables.add(element) } rootObject.add(name, timetables) diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt b/app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt index 89476d0e4c136b34ca6a61b0a427cbe227d2aded..ff23a07df5c8c03399fc13e61ee3b682497db18d 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt @@ -6,10 +6,12 @@ data class Plate(val line: AgencyAndId, val stop: AgencyAndId, val headsign: String, val departures: HashMap>?) { override fun toString(): String { var result = "$line=$stop=$headsign={" if (departures != null) { - for ((_, column) in departures) + for ((service, column) in departures) { + result += service.toString() + ":" for (departure in column) { result += departure.toString() + ";" } + } } result += "}" return result @@ -17,24 +19,28 @@ } companion object { fun fromString(string: String): Plate { - val (line, stop, headsign, departuresString) = string.split("=") - val departures = HashMap<String, HashSet<Departure>>() + val (lineStr, stopStr, headsign, departuresString) = string.split("=") + val line = AgencyAndId.convertFromString(lineStr) + val stop = AgencyAndId.convertFromString(stopStr) + val departures = HashMap<AgencyAndId, HashSet<Departure>>() departuresString.replace("{", "").replace("}", "").split(";") .filter { it != "" } .forEach { try { - val dep = Departure.fromString(it) - if (departures[dep.mode] == null) - departures[dep.mode] = HashSet() - departures[dep.mode]!!.add(dep) + val (serviceStr, depStr) = it.split(":") + val dep = Departure.fromString(depStr) + val service = AgencyAndId.convertFromString(serviceStr) + if (departures[service] == null) + departures[service] = HashSet() + departures[service]!!.add(dep) } catch (e: IllegalArgumentException) { } } return Plate(line, stop, headsign, departures) } - fun join(set: Set<Plate>): HashMap<String, ArrayList<Departure>> { - val departures = HashMap<String, ArrayList<Departure>>() + fun join(set: Set<Plate>): HashMap<AgencyAndId, ArrayList<Departure>> { + val departures = HashMap<AgencyAndId, ArrayList<Departure>>() for (plate in set) { for ((mode, d) in plate.departures!!) { if (departures[mode] == null) diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt b/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt index b2648495b1e06aae110ce0b24914aa3519437058..934fcdf08d2affbcc102072fd35a2a90aa2601ab 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt @@ -21,7 +21,7 @@ fun getTimetable(context: Context? = null, force: Boolean = false): Timetable { return if (timetable == null || force) if (context != null) { timetable = Timetable() - timetable!!.store = read(context) + timetable!!.store = read(context) as GtfsDaoImpl timetable!!.cacheManager = CacheManager.getCacheManager(context) timetable as Timetable } else @@ -40,12 +40,12 @@ return store } } - lateinit var store: GtfsDao + lateinit var store: GtfsDaoImpl private lateinit var cacheManager: CacheManager private var _stops: ArrayList<StopSuggestion>? = null //todo stops to cache fun refresh(context: Context) { - this.store = read(context) + this.store = read(context) as GtfsDaoImpl cacheManager.recreate(getStopDeparturesByPlates(cacheManager.keys().toSet())) @@ -102,7 +102,7 @@ fun getStopSymbol(stopId: AgencyAndId) = store.getStopForId(stopId).code!! fun getLineNumber(lineId: AgencyAndId) = store.getRouteForId(lineId).shortName!! - fun getStopDepartures(stopId: AgencyAndId): Map<String, List<Departure>> { + fun getStopDepartures(stopId: AgencyAndId): Map<AgencyAndId, List<Departure>> { val plates = HashSet<Plate>() val toGet = HashSet<Plate>() @@ -124,7 +124,7 @@ return Plate.join(plates) } - fun getStopDepartures(plates: Set<Plate>): Map<String, ArrayList<Departure>> { + fun getStopDepartures(plates: Set<Plate>): Map<AgencyAndId, ArrayList<Departure>> { val result = HashSet<Plate>() val toGet = HashSet<Plate>() @@ -225,5 +225,30 @@ fun getValidSince() = store.allFeedInfos.toTypedArray()[0].startDate.asString!! fun getValidTill() = store.allFeedInfos.toTypedArray()[0].endDate.asString!! + + fun getServiceForToday(): AgencyAndId { + val today = Calendar.getInstance().get(Calendar.DAY_OF_WEEK) + return getServiceFor(today) + } + + fun getServiceForTomorrow(): AgencyAndId { + val tomorrow = Calendar.getInstance() + tomorrow.add(Calendar.DAY_OF_MONTH, 1) + val tomorrowDoW = tomorrow.get(Calendar.DAY_OF_WEEK) + return getServiceFor(tomorrowDoW) + } + + private fun getServiceFor(day: Int): AgencyAndId { + store.allCalendars.forEach { + if (it.monday == 1 && day == Calendar.MONDAY) return it.serviceId + if (it.tuesday == 1 && day == Calendar.TUESDAY) return it.serviceId + if (it.wednesday == 1 && day == Calendar.WEDNESDAY) return it.serviceId + if (it.thursday == 1 && day == Calendar.THURSDAY) return it.serviceId + if (it.friday == 1 && day == Calendar.FRIDAY) return it.serviceId + if (it.saturday == 1 && day == Calendar.SATURDAY) return it.serviceId + if (it.sunday == 1 && day == Calendar.SUNDAY) return it.serviceId + } + throw IllegalArgumentException() + } }