Author: Adam Pioterek <adam.pioterek@protonmail.ch>
splitting stop_times on download
%!v(PANIC=String method: strings: negative Repeat count)
diff --git a/.idea/dictionaries/adam.xml b/.idea/dictionaries/adam.xml index 97ec6acaf972c3064bc9ec97c5fbf5d9c8dcb7c3..9d09bd12aa6a772411430c5662305f5dda08a2df 100644 --- a/.idea/dictionaries/adam.xml +++ b/.idea/dictionaries/adam.xml @@ -2,6 +2,7 @@<dictionary name="adam"> <words> <w>headsign</w> + <w>headsigns</w> </words> </dictionary> </component> \ No newline at end of file diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt index ef52f870857a4c47430fcaefaddf004188946012..2632da43868d731ed9015939e0b71f027cea0408 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt @@ -40,14 +40,11 @@ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_dash) - println("view set") AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO) setSupportActionBar(toolbar) supportActionBar?.title = getString(R.string.merge_favourites) - println("getting stops") getStops() - println("stops got") prepareFavourites() @@ -129,7 +126,6 @@ "B" -> context.getString(R.string.zone_b_colour) "C" -> context.getString(R.string.zone_c_colour) else -> "#000000" } - println("${text[0]} $colour") val t = "<small><font color=\"$colour\">" + text[1] + "</font></small>" if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { textView.text = Html.fromHtml("${text[0]} $t", Html.FROM_HTML_MODE_LEGACY) 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 01bae71d5ba1be49469bb1f76fc5f96afbc30d7f..14b2eb1488f25760892592baef1aa81f563ccc5b 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/activities/StopSpecifyActivity.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/activities/StopSpecifyActivity.kt @@ -20,13 +20,17 @@ val ids = intent.getStringExtra(EXTRA_STOP_IDS).split(",").map {AgencyAndId(it)}.toSet() val headlines = Timetable.getTimetable().getHeadlinesForStop(ids) + headlines.forEach { + println(it) + } + //todo select shed val shed = AgencyAndId("1") - intent = Intent(this, StopActivity::class.java) + /*intent = Intent(this, StopActivity::class.java) intent.putExtra(StopActivity.SOURCE_TYPE, StopActivity.SOURCE_TYPE_STOP) intent.putExtra(StopActivity.EXTRA_STOP_ID, shed) - startActivity(intent) + startActivity(intent)*/ } } diff --git a/app/src/main/java/ml/adamsprogs/bimba/datasources/TimetableDownloader.kt b/app/src/main/java/ml/adamsprogs/bimba/datasources/TimetableDownloader.kt index 06fc8fed24f7c6f5e687e5611c8619882a3b683e..c198ae033db3d6db29b58e64950787c232debe42 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/datasources/TimetableDownloader.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/datasources/TimetableDownloader.kt @@ -6,17 +6,19 @@ import android.app.Notification import android.content.Context import android.content.Intent import android.support.v4.app.NotificationCompat -import java.net.HttpURLConnection -import java.net.URL import java.io.* -import java.security.MessageDigest import android.app.NotificationManager import android.os.Build +import com.univocity.parsers.csv.CsvWriter +import com.univocity.parsers.csv.CsvWriterSettings import ir.mahdi.mzip.zip.ZipArchive import ml.adamsprogs.bimba.NetworkStateReceiver import ml.adamsprogs.bimba.NotificationChannels import ml.adamsprogs.bimba.R import ml.adamsprogs.bimba.models.Timetable +import org.supercsv.io.CsvListReader +import org.supercsv.prefs.CsvPreference +import java.net.* import java.util.* class TimetableDownloader : IntentService("TimetableDownloader") { @@ -58,7 +60,7 @@ sendResult(RESULT_UP_TO_DATE) return } - notifyDownloading(0) + notify(0, getString(R.string.timetable_downloading), size) val gtfs = File(this.filesDir, "timetable.zip") copyInputStreamToFile(httpCon.inputStream, gtfs) @@ -67,15 +69,50 @@ prefsEditor.putString("timetableLastModified", lastModified) prefsEditor.apply() sendResult(RESULT_DOWNLOADED) - //notifyConverting() //fixme + notify(getString(R.string.timetable_converting)) val target = File(this.filesDir, "gtfs_files") target.deleteRecursively() target.mkdir() ZipArchive.unzip(gtfs.path, target.path, "") - //todo divide stop_times by stop_id + + val stopTimesFile = File(filesDir, "gtfs_files/stop_times.txt") + + val reader = CsvListReader(FileReader(stopTimesFile), CsvPreference.STANDARD_PREFERENCE) + val header = reader.getHeader(true) + + val headers = HashMap<String, Boolean>() + val mapReader = CsvListReader(FileReader(stopTimesFile), CsvPreference.STANDARD_PREFERENCE) + + val string = getString(R.string.timetable_converting) + + notify(0, string, 1_030_000) + + println(Calendar.getInstance().timeInMillis) + + var row: List<Any>? = null + while ({ row = mapReader.read(); row }() != null) { + val stopId = row!![3] as String + val outFile = File(filesDir, "gtfs_files/stop_times_$stopId.txt") + val writer = CsvWriter(CsvWriterSettings()) + if (headers[stopId] == null) { + val h = writer.writeHeadersToString(header.asList()) + outFile.appendText("$h\r\n") + headers[stopId] = true + } + if (mapReader.rowNumber % 10_300 == 0) + notify(mapReader.rowNumber, string, 1_030_000) + val line = writer.writeRowToString(row!!) + outFile.appendText("$line\r\n") + } + mapReader.close() + gtfs.delete() - Timetable.getTimetable().refresh() + + stopTimesFile.delete() + Timetable.getTimetable(this).refresh() + + println(Calendar.getInstance().timeInMillis) cancelNotification() @@ -100,51 +137,51 @@ broadcastIntent.putExtra(EXTRA_RESULT, result) sendBroadcast(broadcastIntent) } - private fun notifyDownloading(progress: Int) { + private fun notify(progress: Int, message: String, max: Int) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) - notifyCompat(progress) + notifyCompat(progress, message, max) else - notifyStandard(progress) + notifyStandard(progress, message, max) } @Suppress("DEPRECATION") - private fun notifyCompat(progress: Int) { + private fun notifyCompat(progress: Int, message: String, max: Int) { val builder = NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_download) - .setContentTitle(getString(R.string.timetable_downloading)) - .setContentText("$progress KiB/$size KiB") + .setContentTitle(message) + .setContentText("${(progress.toDouble() / max.toDouble() * 100).toInt()} %") .setCategory(NotificationCompat.CATEGORY_PROGRESS) .setOngoing(true) - .setProgress(size, progress, false) + .setProgress(max, progress, false) notificationManager.notify(42, builder.build()) } @TargetApi(Build.VERSION_CODES.O) - private fun notifyStandard(progress: Int) { + private fun notifyStandard(progress: Int, message: String, max: Int) { NotificationChannels.makeChannel(NotificationChannels.CHANNEL_UPDATES, "Updates", notificationManager) val builder = Notification.Builder(this, NotificationChannels.CHANNEL_UPDATES) .setSmallIcon(R.drawable.ic_download) - .setContentTitle(getString(R.string.timetable_downloading)) - .setContentText("$progress KiB/$size KiB") + .setContentTitle(message) + .setContentText("${(progress.toDouble() / max.toDouble() * 100).toInt()} %") .setCategory(Notification.CATEGORY_PROGRESS) .setOngoing(true) - .setProgress(size, progress, false) + .setProgress(max, progress, false) notificationManager.notify(42, builder.build()) } - private fun notifyConverting() { + private fun notify(message: String) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) - notifyCompatConverting() + notifyCompat(message) else - notifyStandardConverting() + notifyStandard(message) } @Suppress("DEPRECATION") - private fun notifyCompatConverting() { + private fun notifyCompat(message: String) { val builder = NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_download) - .setContentTitle(getString(R.string.timetable_converting)) + .setContentTitle(message) .setContentText("") .setCategory(NotificationCompat.CATEGORY_PROGRESS) .setOngoing(true) @@ -153,11 +190,11 @@ notificationManager.notify(42, builder.build()) } @TargetApi(Build.VERSION_CODES.O) - private fun notifyStandardConverting() { + private fun notifyStandard(message: String) { NotificationChannels.makeChannel(NotificationChannels.CHANNEL_UPDATES, "Updates", notificationManager) val builder = Notification.Builder(this, NotificationChannels.CHANNEL_UPDATES) .setSmallIcon(R.drawable.ic_download) - .setContentTitle(getString(R.string.timetable_converting)) + .setContentTitle(message) .setContentText("") .setCategory(Notification.CATEGORY_PROGRESS) .setOngoing(true) @@ -170,7 +207,6 @@ notificationManager.cancel(42) } private fun copyInputStreamToFile(ins: InputStream, file: File) { - val md = MessageDigest.getInstance("SHA-512") try { val out = FileOutputStream(file) val buf = ByteArray(5 * 1024) @@ -180,10 +216,9 @@ while (len > 0) { len = ins.read(buf) if (len <= 0) break - md.update(buf, 0, len) out.write(buf, 0, len) lenSum += len.toFloat() / 1024.0f - notifyDownloading(lenSum.toInt()) + notify(lenSum.toInt(), getString(R.string.timetable_downloading), size) } out.close() } catch (e: Exception) { 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 fe52772baa69c84eb089af806c8ceff6019823ae..bfa0eade27e6f02a16ba5814a10059df59919063 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt @@ -73,7 +73,43 @@ return _stops!! } fun getHeadlinesForStop(stops: Set<AgencyAndId>): Map<AgencyAndId, Pair<String, Set<String>>> { - TODO("Not Implemented") + 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='"' + val parser = CsvParser(settings) + stops.forEach { + trips[it.id] = HashSet() + val stop = it.id + val stopsFile = File(filesDir, "gtfs_files/stop_times_${it.id}.txt") + parser.parseAll(stopsFile).forEach { + if (it[6] in arrayOf("0", "3")) { + trips[stop]!!.add(it[0]) + } + } + } + + val allTrips = trips.flatMap { it.value } + + 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]) + } + + + trips.forEach { + val headsign = HashSet<String>() + it.value.forEach { + println("adding: ${routes[it]}") + headsign.add("${routes[it]!!.first} → ${routes[it]!!.second}") + } + headsigns[AgencyAndId(it.key)] = Pair(getStopCode(AgencyAndId(it.key)), headsign) + } + + return headsigns /* 1435 -> (AWF03, {232 → Os. Rusa}) 1436 -> (AWF04, {232 → Rondo Kaponiera})