Created
October 19, 2020 18:04
-
-
Save alwarren/5faf55dd3456ab631e3bc95a7cf720dd to your computer and use it in GitHub Desktop.
Parsing Metar data in CSV format from NOAA's Text Data Server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object CsvMapper { | |
fun decode(rawText: String): Metar { | |
val values = rawText.split(",") | |
return buildMetar(values, skyConditions(values), qualityControlFlags(values)) | |
} | |
private fun buildMetar(values: List<String>, skyCondition: List<SkyCondition>, qualityControlFlags: QualityControlFlags): Metar { | |
// 0:raw_text 1:station_id 2:observation_time 3:latitude 4:longitude 5:temp_c 6:dewpoint_c 7:wind_dir_degrees | |
// 8:wind_speed_kt 9:wind_gust_kt 10:visibility_statute_mi 11:altim_in_hg 12:sea_level_pressure_mb | |
// 13:quality_control_flags | |
// 14:wx_string | |
// 15:sky_condition | |
// 16:flight_category 17:three_hr_pressure_tendency_mb 18:maxT_c 19:minT_c 20:maxT24hr_c 21:minT24hr_c | |
// 22:precip_in 23:pcp3hr_in 24:pcp6hr_in 25:pcp24hr_in 26:snow_in 27:vert_vis_ft 28:metar_type 29:elevation_m | |
val metar = Metar( | |
values[0], values[1], values[2], values[3].toFloatOrNull(), values[4].toFloatOrNull(), values[5].toFloatOrNull(), | |
values[6].toFloatOrNull(), values[7].toIntOrNull(), values[8].toIntOrNull(), values[9].toIntOrNull(), | |
values[10].toFloatOrNull(), values[11].toFloatOrNull(), values[12].toFloatOrNull(), | |
qualityControlFlags, values[14], | |
skyCondition, values[16], values[17].toFloatOrNull(), values[18].toFloatOrNull(), values[19].toFloatOrNull(), | |
values[20].toFloatOrNull(), values[21].toFloatOrNull(), values[22].toFloatOrNull(), values[23].toFloatOrNull(), | |
values[24].toFloatOrNull(), values[25].toFloatOrNull(), values[26].toFloatOrNull(), values[27].toFloatOrNull(), | |
values[28], values[29].toFloatOrNull() | |
) | |
return metar | |
} | |
private fun skyConditions(values: List<String>): List<SkyCondition> { | |
val skies = mutableListOf<SkyCondition>() | |
val skyConditionIndices = (22..29).toList() | |
for(index in 0 until skyConditionIndices.size-1 step 2) { | |
val condition = values[skyConditionIndices[index]] | |
val altitude = values[skyConditionIndices[index + 1]] | |
if (condition.isNotEmpty()) | |
skies.add( | |
SkyCondition( | |
condition, | |
if(altitude.isNotEmpty()) | |
Integer.parseInt(altitude) else null | |
) | |
) | |
} | |
return skies | |
} | |
private fun qualityControlFlags(values: List<String>): QualityControlFlags { | |
// 13..20 | |
return QualityControlFlags( | |
values[13], values[14], values[15], values[16], values[17], values[18], | |
values[19], values[20]) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CsvResponse(responseText: String) { | |
val errors: String | |
val warnings: String | |
val timeTaken: String | |
val dataSource: String | |
val numResults: String | |
val data: List<Metar> | |
private val lines = responseText.trim().split("\n") | |
init { | |
validateResponseText() | |
errors = lines[0] | |
warnings = lines[1] | |
timeTaken = lines[2] | |
dataSource = lines[3] | |
numResults = lines[4] | |
data = getMetars() | |
} | |
private fun getMetars(): List<Metar> { | |
val indices = 6 until lines.size | |
val airports = mutableListOf<Metar>() | |
for (i in indices) | |
airports.add(CsvMapper.decode(lines[i])) | |
return airports | |
} | |
private fun validateResponseText() { | |
when { | |
lines.isEmpty() -> throw FileParseException("Empty server response") | |
lines.size < 5 -> throw FileParseException("Invalid server response") | |
lines.size == 6 -> throw FileParseException("Missing server data") | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FileParseException(message:String): Exception(message) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ntxdroid.metar.domain.entity | |
data class Metar( | |
val rawText: String?, | |
val stationId: String?, | |
val observationTime: String?, | |
val latitude: Float?, // float | |
val longitude: Float?, // float | |
val tempC: Float?, // float | |
val dewpointC: Float?, // float | |
val windDirDegrees: Int?, // int | |
val windSpeedKt: Int?, // int | |
val windGustKt: Int?, // int | |
val visibilityStatuteMi: Float?, // float | |
val altimInHg: Float?, // float | |
val seaLevelPressureMb: Float?, // float | |
val qualityControlFlags: QualityControlFlags?, | |
val wxString: String?, | |
val skyCondition: List<SkyCondition>?, | |
val flightCategory: String?, | |
val threeHrPressureTendencyMb: Float?, // float | |
val maxTC: Float?, // float | |
val minTC: Float?, // float | |
val maxT24hrC: Float?, // float | |
val minT24hrC: Float?, // float | |
val precipIn: Float?, // float | |
val pcp3hrIn: Float?, // float | |
val pcp6hrIn: Float?, // float | |
val pcp24hrIn: Float?, // float | |
val snowIn: Float?, // float | |
val vertVisFt: Float?, // float | |
val metarType: String?, | |
val elevationM: Float? // float | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data class QualityControlFlags ( | |
val autoStation: String?, | |
val auto: String?, | |
val presentWeatherSensorOff: String?, | |
val noSignal: String?, | |
val maintenanceIndicatorOn: String?, | |
val lightningSensorOff: String?, | |
val freezingRainSensorOff: String?, | |
val corrected: String? | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data class SkyCondition ( | |
val skyCover: String, | |
val cloudBaseFtAgl: Int? = null | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment