uninav/lib/data/geo/parser.dart

170 lines
5.0 KiB
Dart
Raw Permalink Normal View History

2024-04-20 14:32:01 +00:00
import 'package:anyhow/anyhow.dart';
import 'package:geojson_vi/geojson_vi.dart';
2024-04-20 14:32:01 +00:00
import 'package:uninav/data/geo/model.dart';
import 'package:yaml/yaml.dart';
Result<Feature> parseFeature(
Map<String, dynamic> properties, GeoJSONGeometry geometry, String id) {
2024-04-20 14:32:01 +00:00
final name = properties['name'] as String?;
final description_yaml = properties['description'] as String? ?? '';
final layer = properties['layer'] as String?;
int? level;
// check if layer key contains a digit using \d+ regex
final layerNum = RegExp(r'\d+').firstMatch(layer ?? '');
if (layerNum != null) {
level = int.parse(layerNum.group(0)!);
}
// try parse yaml
if (description_yaml == null) {
2024-04-21 12:21:31 +00:00
print(
"warn: Description key is missing for feature $name\n\n$geometry\n\n$properties");
2024-04-20 14:32:01 +00:00
}
if (layer == null) {
2024-04-21 12:21:31 +00:00
return bail(
"Layer key \'layer\' is missing for feature $name\n\n$geometry\n\n$properties");
2024-04-20 14:32:01 +00:00
}
dynamic yaml;
try {
yaml = loadYaml(description_yaml);
} on YamlException catch (e) {
2024-04-21 12:21:31 +00:00
return bail(
"Couldn't parse YAML in description for feature $name\n\n$description_yaml\n\nError: $e");
2024-04-20 14:32:01 +00:00
}
yaml = yaml as YamlMap? ?? {};
2024-04-21 00:22:53 +00:00
final description = yaml['description'] as String?;
// if (description != null) print("================ $description");
2024-04-20 14:32:01 +00:00
2024-04-20 22:35:16 +00:00
final building = yaml['building'] as String?;
2024-04-21 06:24:50 +00:00
// print("yaml: $yaml");
2024-04-20 14:32:01 +00:00
var raw_type = yaml['type'] as String?;
if (raw_type == null && layer?.toLowerCase() == 'buildings') {
raw_type = 'building';
}
if (raw_type == null) {
return bail("Type key \'type\' is missing for feature $name");
}
FeatureType type;
try {
switch (raw_type) {
case 'building':
type = FeatureType.building();
case 'lift':
final list = getYamlList<int>(yaml, 'connects_levels')
.expect("Couldn't parse 'connects_levels' for feature $name");
type = FeatureType.lift(list);
break;
case 'stairs':
final list = getYamlList<int>(yaml, 'connects_levels')
.expect("Couldn't parse 'connects_levels' for feature $name");
type = FeatureType.stairs(list);
break;
case 'lecture_hall':
type = FeatureType.lectureHall();
break;
2024-04-21 12:21:31 +00:00
case 'seminar_room':
type = FeatureType.room(getYamlKeyStringify(yaml, 'number')
.expect("Couldn't parse 'number' for seminar_room feature $name"));
break;
case 'pc_pool':
type = FeatureType.pcPool(getYamlKeyStringify(yaml, 'number')
.expect("Couldn't parse 'number' for PcPool feature $name"));
break;
case 'food_drink':
type = FeatureType.foodDrink();
2024-04-20 14:32:01 +00:00
break;
case 'door':
final list = getYamlList<String>(yaml, 'connects')
.expect("Couldn't parse 'connects' for feature $name");
type = FeatureType.door(list);
break;
case 'toilet':
final toiletType = getYamlKey<String>(yaml, 'toilet_type')
.expect("Couldn't parse 'toilet_type' for feature $name");
type = FeatureType.toilet(toiletType);
break;
case 'public_transport':
2024-04-21 12:21:31 +00:00
final busLines = getYamlList<dynamic>(yaml, 'bus_lines').unwrapOr([]);
final tramLines = getYamlList<dynamic>(yaml, 'tram_lines').unwrapOr([]);
2024-04-20 14:32:01 +00:00
type = FeatureType.publicTransport(
stringifyList(busLines)
.expect('Couldn\'t stringify \'bus_lines\' for feature $name'),
stringifyList(tramLines)
.expect('Couldn\'t stringify \'tram_lines\' for feature $name'),
);
break;
default:
return bail("Unknown feature type $raw_type for feature $name");
}
} catch (e) {
return bail("Failed to parse feature type for feature $name: $e");
}
return Ok(Feature(
name: name ?? 'Unknown',
type: type,
description: description,
geometry: geometry,
level: level,
2024-04-20 22:35:16 +00:00
building: building,
id: id,
2024-04-20 14:32:01 +00:00
));
}
Result<List<String>> stringifyList(List<dynamic> tramLines) {
try {
return Ok(tramLines.map((e) => e.toString()).toList());
} catch (e) {
return bail("Couldn't stringify list: $e");
}
}
Result<List<T>> getYamlList<T>(YamlMap yaml, String key) {
try {
2024-04-21 06:24:50 +00:00
// print('yaml is ${yaml[key]}');
2024-04-20 14:32:01 +00:00
final val = (yaml[key] as YamlList?);
if (val == null) {
return bail("Key $key is missing in yaml");
}
return Ok(val.cast<T>());
} catch (e) {
return bail("Failed to parse yaml key $key as ${T.toString()}: $e");
}
}
Result<T> getYamlKey<T>(YamlMap yaml, String key) {
try {
final val = yaml[key] as T?;
if (val == null) {
return bail("Key $key is missing in yaml");
}
return Ok(val);
} catch (e) {
return bail("Failed to parse yaml key $key as ${T.toString()}: $e");
}
}
2024-04-21 12:21:31 +00:00
Result<String> getYamlKeyStringify<T>(YamlMap yaml, String key) {
try {
final val = yaml[key] as T?;
if (val == null) {
return bail("Key $key is missing in yaml");
}
return Ok(val.toString());
} catch (e) {
return bail("Failed to parse yaml key $key as ${T.toString()}: $e");
}
}