Bimba.git

commit 05022e4df566a76d22d41307fcb0871544a6f37c

Author: Adam Pioterek <adam.pioterek@protonmail.ch>

faster iterating over trips & dynamic tabs in StopActivity

%!v(PANIC=String method: strings: negative Repeat count)


diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt
index 27baedc722898d0b2ae894c661346fb75c100ee8..fb942717e129f320c45b662e851bbfff1dabf6cc 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt
@@ -178,13 +178,9 @@         Snackbar.make(findViewById(R.id.drawer_layout), message, Snackbar.LENGTH_LONG).show()
         //todo refresh
     }
 
-    private fun selectTodayPage() { //todo Services
-        val today = Calendar.getInstance()
-        when (today.get(Calendar.DAY_OF_WEEK)) {
-            Calendar.SATURDAY -> tabLayout.getTabAt(1)?.select()
-            Calendar.SUNDAY -> tabLayout.getTabAt(2)?.select()
-            else -> tabLayout.getTabAt(0)?.select()
-        }
+    private fun selectTodayPage() {
+        val today = (Calendar.getInstance().get(Calendar.DAY_OF_WEEK) - 1) % 7
+        tabLayout.getTabAt(sectionsPagerAdapter!!.todayTab(today))
     }
 
     override fun onCreateOptionsMenu(menu: Menu): Boolean {
@@ -272,13 +268,47 @@             }
         }
     }
 
-    inner class SectionsPagerAdapter(fm: FragmentManager, var departures: Map<AgencyAndId, List<Departure>>) : FragmentStatePagerAdapter(fm) {
+    inner class SectionsPagerAdapter(fm: FragmentManager, departures: Map<AgencyAndId, List<Departure>>) : FragmentStatePagerAdapter(fm) {
 
-        private val modes = departures.keys.sortedBy {
-            timetable.calendarToMode(AgencyAndId(it.id)).sorted()[0]
+        var departures: Map<AgencyAndId, List<Departure>> = departures
+            set(value) {
+                refreshTabs()
+            }
+
+        private var modes = ArrayList<AgencyAndId>()
+
+        init {
+            refreshTabs()
         }
 
         var relativeTime = true
+
+        fun todayTab(today: Int): Int {
+            if (modes.isEmpty())
+                return 0
+            return modes.indexOf(modes.filter {
+                timetable.calendarToMode(it).contains(today)
+            }[0])
+        }
+
+
+        private fun refreshTabs() {
+            tabLayout.removeAllTabs()
+            departures.keys.sortedBy {
+                timetable.calendarToMode(AgencyAndId(it.id)).sorted()[0]
+            }.mapTo(modes) { it }
+            modes.forEach {
+                val tab = tabLayout.newTab()
+                tab.text = timetable.calendarToMode(it)
+                        .joinToString { resources.getStringArray(R.array.daysOfWeekShort)[it] }
+                tabLayout.addTab(tab)
+            }
+            if (modes.isEmpty()) {
+                val tab = tabLayout.newTab()
+                tab.text = getString(R.string.today)
+                tabLayout.addTab(tab)
+            }
+        }
 
         override fun getItemPosition(obj: Any): Int {
             return PagerAdapter.POSITION_NONE




diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/StopSpecifyActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/StopSpecifyActivity.kt
index d8cf258e3ae5b3ff20508948a1601ebf6f843770..ae47d0daee70f338262a9699d121ec57fe1411a0 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/activities/StopSpecifyActivity.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/activities/StopSpecifyActivity.kt
@@ -65,7 +65,7 @@                 context.startActivity(intent)
             }
             holder?.stopCode?.text = values.values.sortedBy { it.first }[position].first
             holder?.stopHeadlines?.text = values.values.sortedBy { it.first }[position].second
-                    .sortedBy { it }
+                    .sortedBy { it } // fixme natural sort
                     .joinToString()
         }
 




diff --git a/app/src/main/java/ml/adamsprogs/bimba/datasources/VmClient.kt b/app/src/main/java/ml/adamsprogs/bimba/datasources/VmClient.kt
index e5b0a6357e3d5cb9d5065d89bcf81cd94ef5ebe7..3e0201d46f297094460f835d3a3c68b052f21320 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/datasources/VmClient.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/datasources/VmClient.kt
@@ -126,7 +126,9 @@
     private fun isAlreadyRequested(stopSegment: StopSegment): Boolean {
         val platesIn = requests[stopSegment.stop]?.map { it.plate }?.toSet()
         val platesOut = stopSegment.plates
-        return (platesOut == platesIn || platesIn!!.containsAll(platesOut!!))
+        if (platesIn == null || platesIn.isEmpty())
+            return false
+        return (platesOut == platesIn || platesIn.containsAll(platesOut!!))
     }
 
 
@@ -229,7 +231,8 @@     private fun sendResult(plateId: Plate.ID, departures: HashSet?) {
         val broadcastIntent = Intent()
         broadcastIntent.action = ACTION_READY
         broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT)
-        broadcastIntent.putStringArrayListExtra(EXTRA_DEPARTURES, departures?.map { it.toString() } as java.util.ArrayList<String>)
+        if (departures != null)
+            broadcastIntent.putStringArrayListExtra(EXTRA_DEPARTURES, departures.map { it.toString() } as ArrayList)
         broadcastIntent.putExtra(EXTRA_PLATE_ID, plateId)
         sendBroadcast(broadcastIntent)
     }




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 8eaeca2bed5e0f54c6e8eaac1d7d70e2ea692020..2a661964d69a99829a85721de236790646fb761e 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt
@@ -59,6 +59,7 @@
     data class ID(val line: AgencyAndId, val stop: AgencyAndId, val headsign: String) : Serializable {
         companion object {
             fun fromString(string: String): ID {
+                println(string)
                 val (line, stop, headsign) = string.split("|")
                 return ID(AgencyAndId.convertFromString(line),
                         AgencyAndId.convertFromString(stop), headsign)
@@ -72,7 +73,7 @@             return line == other.line && stop == other.stop && headsign.toLowerCase() == other.headsign.toLowerCase()
         }
 
         override fun toString(): String {
-            return "$line|$stop$headsign"
+            return "$line|$stop|$headsign"
         }
 
         override fun hashCode(): Int {




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/StopSegment.kt b/app/src/main/java/ml/adamsprogs/bimba/models/StopSegment.kt
index dfd3cbf72ad518ab0eedc9b4d241bec7400026fe..39d6ebd24628bd690314b6159ac0b46d8f580bb1 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/models/StopSegment.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/models/StopSegment.kt
@@ -7,7 +7,7 @@
 data class StopSegment(val stop: AgencyAndId, var plates: Set<Plate.ID>?) : Parcelable {
     constructor(parcel: Parcel) : this(
             parcel.readSerializable() as AgencyAndId,
-            parcel.readString().split("|").map { Plate.ID.fromString(it) }.toSet()
+            parcel.readString().split(";").map { Plate.ID.fromString(it) }.toSet()
     )
 
     companion object CREATOR : Parcelable.Creator<StopSegment> {
@@ -27,7 +27,7 @@
     override fun writeToParcel(dest: Parcel?, flags: Int) {
         dest?.writeSerializable(stop)
         if (plates != null)
-            dest?.writeString(plates!!.joinToString("|") { it.toString() })
+            dest?.writeString(plates!!.joinToString(";") { it.toString() })
     }
 
     override fun describeContents(): Int {




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 d1351d8d56a399e1ef17aa0959a036024fde5196..0ef3fc05099e29112c9444407c4dcc9b2e84abb2 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt
@@ -72,14 +72,12 @@         return _stops!!
     }
 
     fun getHeadlinesForStop(stops: Set<AgencyAndId>): Map<AgencyAndId, Pair<String, Set<String>>> {
-        println(JCalendar.getInstance().timeInMillis)
         val trips = HashMap<String, HashSet<String>>()
         val routes = HashMap<String, Pair<String, String>>()
         val headsigns = HashMap<AgencyAndId, Pair<String, HashSet<String>>>()
         val settings = CsvParserSettings()
         settings.format.setLineSeparator("\r\n")
-        settings.format.quote='"'
-        println(JCalendar.getInstance().timeInMillis)
+        settings.format.quote = '"'
         val parser = CsvParser(settings)
         stops.forEach {
             trips[it.id] = HashSet()
@@ -91,18 +89,11 @@                     trips[stop]!!.add(it[0])
                 }
             }
         }
-        println(JCalendar.getInstance().timeInMillis)
-
-        //val allTrips = trips.flatMap { it.value }
-        println(JCalendar.getInstance().timeInMillis)
 
         val stopsFile = File(filesDir, "gtfs_files/trips.txt")
         parser.parseAll(stopsFile).forEach {
-            //if (it[2] in allTrips)
             routes[it[2]] = Pair(it[0], it[3])
         }
-        println(JCalendar.getInstance().timeInMillis)
-
 
         trips.forEach {
             val headsign = HashSet<String>()
@@ -111,7 +102,6 @@                 headsign.add("${routes[it]!!.first} → ${routes[it]!!.second}")
             }
             headsigns[AgencyAndId(it.key)] = Pair(getStopCode(AgencyAndId(it.key)), headsign)
         }
-        println(JCalendar.getInstance().timeInMillis)
 
         return headsigns
         /*
@@ -222,18 +212,16 @@     }
 
     private fun getStopDeparturesByPlate(plate: Plate): Plate {
         val resultPlate = Plate(Plate.ID(plate.id), HashMap())
-        val trips = HashMap<String, Map<String, Any>>()
-        val stopTimesFile = File(filesDir, "gtfs_files/stop_times.txt") //todo stop_times_$stopId
+        val stopTimes = HashMap<String, Map<String, Any>>()
+        val stopTimesFile = File(filesDir, "gtfs_files/stop_times_${plate.id.stop.id}.txt")
         var mapReader = CsvMapReader(FileReader(stopTimesFile), CsvPreference.STANDARD_PREFERENCE)
         var header = mapReader.getHeader(true)
 
         var stopTimesRow: Map<String, Any>? = null
         var processors = Array<CellProcessor?>(header.size, { null })
         while ({ stopTimesRow = mapReader.read(header, processors); stopTimesRow }() != null) {
-            if ((stopTimesRow!!["stop_id"] as String) == plate.id.stop.id) {
-                val tripId = stopTimesRow!!["trip_id"] as String
-                trips[tripId] = stopTimesRow!!
-            }
+            val tripId = stopTimesRow!!["trip_id"] as String
+            stopTimes[tripId] = stopTimesRow!!
         }
         mapReader.close()
 
@@ -243,31 +231,37 @@         header = mapReader.getHeader(true)
 
         var tripsRow: Map<String, Any>? = null
         processors = Array(header.size, { null })
+
+        val trips = HashMap<String, Map<String, Any>>()
         while ({ tripsRow = mapReader.read(header, processors); tripsRow }() != null) {
             val tripId = tripsRow!!["trip_id"] as String
-            if (tripId in trips && tripsRow!!["route_id"] as String == plate.id.line.id
+            if (tripsRow!!["route_id"] as String == plate.id.line.id
                     && tripsRow!!["trip_headsign"] as String == plate.id.headsign) { //check if toLower is needed
-                val cal = JCalendar.getInstance()
-                val (h, m, s) = (trips[tripId]!!["departure_time"] as String).split(":")
-                cal.set(JCalendar.HOUR_OF_DAY, h.toInt())
-                cal.set(JCalendar.MINUTE, m.toInt())
-                cal.set(JCalendar.SECOND, s.toInt())
-                val time = cal.secondsAfterMidnight()
-                val serviceId = AgencyAndId(tripsRow!!["service_id"] as String)
-                val mode = calendarToMode(serviceId)
-                val lowFloor = trips[tripId]!!["wheelchair_accessible"] as String == "1"
-                val mod = explainModification(Trip(AgencyAndId(tripsRow!!["route_id"] as String),
-                        serviceId, createTripId(tripsRow!!["trip_id"] as String),
-                        tripsRow!!["trip_headsign"] as String, Integer.parseInt(tripsRow!!["direction_id"] as String),
-                        AgencyAndId(tripsRow!!["shape_id"] as String)), Integer.parseInt(trips[tripId]!!["stop_sequence"] as String))
-
-                val dep = Departure(plate.id.line, mode, time, lowFloor, mod, plate.id.headsign)
-                if (resultPlate.departures!![serviceId] == null)
-                    resultPlate.departures[serviceId] = HashSet()
-                resultPlate.departures[serviceId]!!.add(dep)
+                trips[tripId] = tripsRow!!
             }
         }
         mapReader.close()
+
+        trips.forEach {
+            val cal = JCalendar.getInstance()
+            val (h, m, s) = (stopTimes[it.key]!!["departure_time"] as String).split(":")
+            cal.set(JCalendar.HOUR_OF_DAY, h.toInt())
+            cal.set(JCalendar.MINUTE, m.toInt())
+            cal.set(JCalendar.SECOND, s.toInt())
+            val time = cal.secondsAfterMidnight()
+            val serviceId = AgencyAndId(it.value["service_id"] as String)
+            val mode = calendarToMode(serviceId)
+            val lowFloor = it.value["wheelchair_accessible"] as String == "1"
+            val mod = explainModification(Trip(AgencyAndId(it.value["route_id"] as String),
+                    serviceId, createTripId(it.value["trip_id"] as String),
+                    it.value["trip_headsign"] as String, Integer.parseInt(it.value["direction_id"] as String),
+                    AgencyAndId(it.value["shape_id"] as String)), Integer.parseInt(stopTimes[it.key]!!["stop_sequence"] as String))
+
+            val dep = Departure(plate.id.line, mode, time, lowFloor, mod, plate.id.headsign)
+            if (resultPlate.departures!![serviceId] == null)
+                resultPlate.departures[serviceId] = HashSet()
+            resultPlate.departures[serviceId]!!.add(dep)
+        }
         return resultPlate
     }
 
@@ -309,7 +303,7 @@             if (it.stopRange != null) {
                 if (stopSequence in it.stopRange)
                     explanations.add(definitions[it.id.id]!!)
             } else {
-                explanations.add(definitions[it.id.id]!!)
+                explanations.add(definitions[it.id.id]!!) //fixme null
             }
         }
 
@@ -317,7 +311,7 @@         return explanations
     }
 
     private fun getRouteForTrip(trip: Trip): Route {
-        val routesFile = File(filesDir, "gtfs_files/routes.txt")
+        val routesFile = File(filesDir, "gtfs_files/trips.txt")
         var mapReader = CsvMapReader(FileReader(routesFile), CsvPreference.STANDARD_PREFERENCE)
         var header = mapReader.getHeader(true)
 
@@ -336,7 +330,7 @@             mapReader.close()
             throw IllegalArgumentException("Trip ${trip.rawId} not in store")
         }
 
-        val tripsFile = File(filesDir, "gtfs_files/trips.txt")
+        val tripsFile = File(filesDir, "gtfs_files/routes.txt")
         mapReader = CsvMapReader(FileReader(tripsFile), CsvPreference.STANDARD_PREFERENCE)
         header = mapReader.getHeader(true)
 
@@ -378,22 +372,20 @@ //    }
 
     fun getTripsForStop(stopId: AgencyAndId): Set<Trip> {
         val tripIds = HashSet<String>()
-        val stopTimesFile = File(filesDir, "gtfs_files/stop_times.txt")
+        val stopTimesFile = File(filesDir, "gtfs_files/stop_times_${stopId.id}.txt")
         var mapReader = CsvMapReader(FileReader(stopTimesFile), CsvPreference.STANDARD_PREFERENCE)
         var header = mapReader.getHeader(true)
 
         var stopTimesRow: Map<String, Any>? = null
         var processors = Array<CellProcessor?>(header.size, { null })
         while ({ stopTimesRow = mapReader.read(header, processors); stopTimesRow }() != null) {
-            if ((stopTimesRow!!["stop_id"] as String) == stopId.id) {
-                val tripId = stopTimesRow!!["trip_id"] as String
-                tripIds.add(tripId)
-            }
+            val tripId = stopTimesRow!!["trip_id"] as String
+            tripIds.add(tripId)
         }
         mapReader.close()
 
 
-        val trips = HashSet<Trip>()
+        val trips = HashMap<String, Trip>()
         val tripsFile = File(filesDir, "gtfs_files/trips.txt")
         mapReader = CsvMapReader(FileReader(tripsFile), CsvPreference.STANDARD_PREFERENCE)
         header = mapReader.getHeader(true)
@@ -402,17 +394,21 @@         var tripsRow: Map? = null
         processors = Array(header.size, { null })
         while ({ tripsRow = mapReader.read(header, processors); tripsRow }() != null) {
             val tripId = tripsRow!!["trip_id"] as String
-            if (tripId in tripIds) {
-                trips.add(Trip(AgencyAndId(tripsRow!!["route_id"] as String),
-                        AgencyAndId(tripsRow!!["service_id"] as String),
-                        createTripId(tripId),
-                        tripsRow!!["trip_headsign"] as String,
-                        Integer.parseInt(tripsRow!!["direction_id"] as String),
-                        AgencyAndId(tripsRow!!["shape_id"] as String)))
-            }
+            trips[tripId] = Trip(AgencyAndId(tripsRow!!["route_id"] as String),
+                    AgencyAndId(tripsRow!!["service_id"] as String),
+                    createTripId(tripId),
+                    tripsRow!!["trip_headsign"] as String,
+                    Integer.parseInt(tripsRow!!["direction_id"] as String),
+                    AgencyAndId(tripsRow!!["shape_id"] as String))
         }
         mapReader.close()
-        return trips
+
+        val filteredTrips = HashSet<Trip>()
+
+        tripIds.forEach {
+            filteredTrips.add(trips[it]!!)
+        }
+        return filteredTrips
     }
 
     private fun createTripId(rawId: String): Trip.ID {
@@ -523,19 +519,17 @@         throw IllegalArgumentException("Route $number not in store")
     }
 
     fun getPlatesForStop(stop: AgencyAndId): Set<Plate.ID> {
-        val plates = HashSet<Plate.ID>()
+        val plates = HashMap<String, Plate.ID>()
         val tripIds = HashSet<String>()
-        val stopTimesFile = File(filesDir, "gtfs_files/stop_times.txt")
+        val stopTimesFile = File(filesDir, "gtfs_files/stop_times_${stop.id}.txt")
         var mapReader = CsvMapReader(FileReader(stopTimesFile), CsvPreference.STANDARD_PREFERENCE)
         var header = mapReader.getHeader(true)
 
         var stopTimesRow: Map<String, Any>? = null
         var processors = Array<CellProcessor?>(header.size, { null })
         while ({ stopTimesRow = mapReader.read(header, processors); stopTimesRow }() != null) {
-            if ((stopTimesRow!!["stop_id"] as String) == stop.id) {
-                val tripId = stopTimesRow!!["trip_id"] as String
-                tripIds.add(tripId)
-            }
+            val tripId = stopTimesRow!!["trip_id"] as String
+            tripIds.add(tripId)
         }
         mapReader.close()
 
@@ -547,13 +541,18 @@
         var tripsRow: Map<String, Any>? = null
         processors = Array(header.size, { null })
         while ({ tripsRow = mapReader.read(header, processors); tripsRow }() != null) {
-            if (tripsRow!!["trip_id"] as String in tripIds) {
-                plates.add(Plate.ID(AgencyAndId(tripsRow!!["route_id"] as String), stop, tripsRow!!["trip_headsign"] as String))
-            }
+            val tripId = tripsRow!!["trip_id"] as String
+            plates[tripId] = Plate.ID(AgencyAndId(tripsRow!!["route_id"] as String), stop, tripsRow!!["trip_headsign"] as String)
+
         }
         mapReader.close()
 
-        return plates
+        val filteredPlates = HashSet<Plate.ID>()
+        tripIds.forEach {
+            filteredPlates.add(plates[it]!!)
+        }
+
+        return filteredPlates
     }
 }
 




diff --git a/app/src/main/res/layout/activity_stop.xml b/app/src/main/res/layout/activity_stop.xml
index a56ab1e2d284b956c2fb13106f8d74bd7d2eabcc..6de28177cef9c063f6323d9a2e1dd99572646e63 100644
--- a/app/src/main/res/layout/activity_stop.xml
+++ b/app/src/main/res/layout/activity_stop.xml
@@ -5,8 +5,8 @@     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/main_content"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:fitsSystemWindows="true"
     android:animateLayoutChanges="true"
+    android:fitsSystemWindows="true"
     tools:context="ml.adamsprogs.bimba.activities.StopActivity">
 
     <android.support.design.widget.AppBarLayout
@@ -30,27 +30,7 @@
         <android.support.design.widget.TabLayout
             android:id="@+id/tabs"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <android.support.design.widget.TabItem
-                android:id="@+id/tabItem"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/tab_workday_text" />
-
-            <android.support.design.widget.TabItem
-                android:id="@+id/tabItem2"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/tab_saturday_text" />
-
-            <android.support.design.widget.TabItem
-                android:id="@+id/tabItem3"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/tab_sunday_text" />
-
-        </android.support.design.widget.TabLayout>
+            android:layout_height="wrap_content" />
     </android.support.design.widget.AppBarLayout>
 
     <android.support.v4.view.ViewPager




diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f32ba834964104a849d4039d163c2bffae2c0ea1..cc3dac1c13fa07f11275b532af588802f03da62b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -83,7 +83,18 @@         Saturday
         <item>Sunday</item>
     </string-array>
 
+    <string-array name="daysOfWeekShort">
+        <item>Mon</item>
+        <item>Tue</item>
+        <item>Wed</item>
+        <item>Thu</item>
+        <item>Fri</item>
+        <item>Sat</item>
+        <item>Sun</item>
+    </string-array>
+
     <string name="zone_a_colour" translatable="false">#00a650</string>
     <string name="zone_b_colour" translatable="false">#ed1c24</string>
     <string name="zone_c_colour" translatable="false">#ffc107</string>
+    <string name="today">Today</string>
 </resources>




diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 9519974ec391690efa8cab3744f5951f0ba5019f..0ac6eb65d8ffdca102eac78605f52d186780b659 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -68,5 +68,15 @@         Freitag
         <item>Samstag</item>
         <item>Sontag</item>
     </string-array>
+    <string-array name="daysOfWeekShort">
+        <item>Mon</item>
+        <item>Die</item>
+        <item>Mit</item>
+        <item>Don</item>
+        <item>Fre</item>
+        <item>Sam</item>
+        <item>Son</item>
+    </string-array>
     <string name="timetable_converting">Fahrplan wird umgewandelt…</string>
+    <string name="today">Heute</string>
 </resources>




diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 37743291599fe9d5d4b0a64fab051653776a0088..fd5f16720a42519165056818678b1c28c809b79b 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -66,5 +66,15 @@         Venerdi
         <item>Sabato</item>
         <item>Domenica</item>
     </string-array>
+    <string-array name="daysOfWeekShort">
+        <item>Lu</item>
+        <item>Ma</item>
+        <item>Me</item>
+        <item>Gi</item>
+        <item>Ve</item>
+        <item>Sa</item>
+        <item>Do</item>
+    </string-array>
     <string name="timetable_converting">L’orario e stando convertito</string>
+    <string name="today">Oggi</string>
 </resources>




diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 7d0841a718752fca9fb3cdc3a2cb4f6f1095844e..6f77515832fe84b73f3c13be4b6486b09a819a54 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -68,5 +68,15 @@         Piątek
         <item>Sobota</item>
         <item>Niedziela</item>
     </string-array>
+    <string-array name="daysOfWeekShort">
+        <item>Pn</item>
+        <item>Wt</item>
+        <item>Śr</item>
+        <item>Czw</item>
+        <item>Pt</item>
+        <item>S</item>
+        <item>N</item>
+    </string-array>
     <string name="timetable_converting">Konwertowanie rozkładu</string>
+    <string name="today">Dzisiaj</string>
 </resources>
\ No newline at end of file