Last active
July 31, 2023 00:16
-
-
Save xpando/2629df53d4da0421d772aa96098f6746 to your computer and use it in GitHub Desktop.
Kotlin CSV serializer example
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
{ | |
"Seattle": [ | |
{ | |
"inverter": { | |
"manufacturer": "Inverter Corp", | |
"model": "Model 1" | |
}, | |
"arrays": [ | |
{ | |
"count": 10, | |
"manufacturer": "Module Corp", | |
"model": "Model A", | |
"orientation": { | |
"tilt": 15.0, | |
"azimuth": 180.0 | |
}, | |
"monthlySolarAccess": { | |
"JANUARY": 70.0, | |
"FEBRUARY": 75.0, | |
"MARCH": 80.0, | |
"APRIL": 85.0, | |
"MAY": 90.0, | |
"JUNE": 95.0, | |
"JULY": 100.0, | |
"AUGUST": 95.0, | |
"SEPTEMBER": 90.5, | |
"OCTOBER": 85.0, | |
"NOVEMBER": 80.0, | |
"DECEMBER": 75.0 | |
} | |
}, | |
{ | |
"count": 15, | |
"manufacturer": "Module Corp", | |
"model": "Model A", | |
"orientation": { | |
"tilt": 12.4, | |
"azimuth": 90.0 | |
}, | |
"monthlySolarAccess": { | |
"JANUARY": 60.0, | |
"FEBRUARY": 65.0, | |
"MARCH": 60.0, | |
"APRIL": 65.0, | |
"MAY": 60.0, | |
"JUNE": 65.0, | |
"JULY": 60.0, | |
"AUGUST": 65.0, | |
"SEPTEMBER": 60.5, | |
"OCTOBER": 65.0, | |
"NOVEMBER": 60.0, | |
"DECEMBER": 65.0 | |
} | |
} | |
] | |
}, | |
{ | |
"inverter": { | |
"manufacturer": "Inverter Corp", | |
"model": "Model 2" | |
}, | |
"arrays": [ | |
{ | |
"count": 25, | |
"manufacturer": "Module Corp", | |
"model": "Model B", | |
"orientation": { | |
"tilt": 9.25, | |
"azimuth": 270.0 | |
}, | |
"monthlySolarAccess": { | |
"JANUARY": 100.0, | |
"FEBRUARY": 100.0, | |
"MARCH": 100.0, | |
"APRIL": 100.0, | |
"MAY": 100.0, | |
"JUNE": 100.0, | |
"JULY": 100.0, | |
"AUGUST": 100.0, | |
"SEPTEMBER": 100.5, | |
"OCTOBER": 100.0, | |
"NOVEMBER": 100.0, | |
"DECEMBER": 100.0 | |
} | |
} | |
] | |
} | |
], | |
"Boston": [ | |
{ | |
"inverter": { | |
"manufacturer": "Inverter Corp", | |
"model": "Model 3" | |
}, | |
"arrays": [ | |
{ | |
"count": 13, | |
"manufacturer": "Module Corp", | |
"model": "Model B", | |
"orientation": { | |
"tilt": 9.25, | |
"azimuth": 270.0 | |
}, | |
"monthlySolarAccess": { | |
"JANUARY": 100.0, | |
"FEBRUARY": 100.0, | |
"MARCH": 100.0, | |
"APRIL": 100.0, | |
"MAY": 100.0, | |
"JUNE": 100.0, | |
"JULY": 100.0, | |
"AUGUST": 100.0, | |
"SEPTEMBER": 100.5, | |
"OCTOBER": 100.0, | |
"NOVEMBER": 100.0, | |
"DECEMBER": 100.0 | |
} | |
} | |
] | |
} | |
] | |
} |
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
import com.google.gson.GsonBuilder | |
import java.time.Month | |
val csvData = arrayOf( | |
arrayOf( | |
"Site_id", | |
"inverter_id", | |
"inverter_manufacturer", | |
"inverter_model", | |
"module_manufacturer", | |
"module_model", | |
"module_count", | |
"tilt", | |
"azimuth", | |
"jan", | |
"feb", | |
"mar", | |
"apr", | |
"may", | |
"jun", | |
"jul", | |
"aug", | |
"sep", | |
"oct", | |
"nov", | |
"dec" | |
), | |
arrayOf( | |
"Seattle", | |
"1", | |
"Inverter Corp", | |
"Model 1", | |
"Module Corp", | |
"Model A", | |
"10", | |
"15.0", | |
"180.0", | |
"70.0", | |
"75.0", | |
"80.0", | |
"85", | |
"90", | |
"95", | |
"100", | |
"95", | |
"90.5", | |
"85", | |
"80", | |
"75" | |
), | |
arrayOf( | |
"Seattle", | |
"1", | |
"Inverter Corp", | |
"Model 1", | |
"Module Corp", | |
"Model A", | |
"15", | |
"12.4", | |
"90.0", | |
"60.0", | |
"65.0", | |
"60.0", | |
"65", | |
"60", | |
"65", | |
"60", | |
"65", | |
"60.5", | |
"65", | |
"60", | |
"65" | |
), | |
arrayOf( | |
"Seattle", | |
"2", | |
"Inverter Corp", | |
"Model 2", | |
"Module Corp", | |
"Model B", | |
"25", | |
"9.25", | |
"270.0", | |
"100.0", | |
"100.0", | |
"100.0", | |
"100", | |
"100", | |
"100", | |
"100", | |
"100", | |
"100.5", | |
"100", | |
"100", | |
"100" | |
), | |
arrayOf( | |
"Boston", | |
"1", | |
"Inverter Corp", | |
"Model 3", | |
"Module Corp", | |
"Model B", | |
"13", | |
"9.25", | |
"270.0", | |
"100.0", | |
"100.0", | |
"100.0", | |
"100", | |
"100", | |
"100", | |
"100", | |
"100", | |
"100.5", | |
"100", | |
"100", | |
"100" | |
), | |
) | |
data class SolarSystem(val inverter: Inverter, val arrays: MutableList<ModuleArray>) | |
data class Inverter(val manufacturer: String, val model: String) | |
data class ModuleArray( | |
val count: Int, | |
val manufacturer: String, | |
val model: String, | |
val orientation: Orientation, | |
val monthlySolarAccess: Map<Month, Double> | |
) | |
data class Orientation(val tilt: Double, val azimuth: Double) | |
const val SITE_ID = 0 | |
const val INVERTER_ID = 1 | |
const val INVERTER_MANUFACTURER = 2 | |
const val INVERTER_MODEL = 3 | |
const val MODULE_MANUFACTURER = 4 | |
const val MODULE_MODEL = 5 | |
const val MODULE_COUNT = 6 | |
const val TILT = 7 | |
const val AZIMUTH = 8 | |
fun parseOrientation(line: Array<String>) = | |
Orientation( | |
tilt = line[TILT].toDouble(), | |
azimuth = line[AZIMUTH].toDouble(), | |
) | |
fun parseMonthlySolarAccess(line: Array<String>) = | |
(1..12).associate { | |
Month.of(it) to line[AZIMUTH + it].toDouble() | |
} | |
fun parseModuleArray(line: Array<String>) = | |
ModuleArray( | |
count = line[MODULE_COUNT].toInt(), | |
manufacturer = line[MODULE_MANUFACTURER], | |
model = line[MODULE_MODEL], | |
orientation = parseOrientation(line), | |
monthlySolarAccess = parseMonthlySolarAccess(line) | |
) | |
fun parseInverter(line: Array<String>) = | |
Inverter( | |
manufacturer = line[INVERTER_MANUFACTURER], | |
model = line[INVERTER_MODEL], | |
) | |
fun parseSolarSystem(lines: List<Array<String>>) = | |
SolarSystem( | |
inverter = parseInverter(lines.first()), | |
arrays = lines.map { parseModuleArray(it) }.toMutableList() | |
) | |
fun parseSite(lines: List<Array<String>>) = | |
lines | |
.groupBy { it[INVERTER_ID] } | |
.map { (_, inverterLines) -> parseSolarSystem(inverterLines) } | |
fun usingFold(): MutableMap<String, MutableList<SolarSystem>> = | |
csvData.asSequence() | |
.drop(1) | |
.fold(mutableMapOf()) { sites, line -> | |
val systems = sites.getOrPut(line[SITE_ID]) { mutableListOf() } | |
var system = | |
systems.firstOrNull() { it.inverter.manufacturer == line[INVERTER_MANUFACTURER] && it.inverter.model == line[INVERTER_MODEL] } | |
if (system == null) { | |
system = SolarSystem( | |
inverter = parseInverter(line), | |
arrays = mutableListOf(), | |
) | |
systems.add(system) | |
} | |
system.arrays.add(parseModuleArray(line)) | |
sites | |
} | |
fun main() { | |
val gson = GsonBuilder().setPrettyPrinting().create() | |
val sites1 = csvData.asSequence().drop(1) | |
.groupBy { it[SITE_ID] } | |
.map { (siteId, siteLines) -> siteId to parseSite(siteLines) } | |
.toMap() | |
println(gson.toJson(sites1)) | |
val sites2 = usingFold() | |
println(gson.toJson(sites2)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment