feat: basic navigation with bugs
This commit is contained in:
		@ -19,7 +19,7 @@ Future<void> showFeatureBottomSheet(
 | 
				
			|||||||
      data: ThemeData.light(),
 | 
					      data: ThemeData.light(),
 | 
				
			||||||
      child: Container(
 | 
					      child: Container(
 | 
				
			||||||
        constraints: const BoxConstraints(
 | 
					        constraints: const BoxConstraints(
 | 
				
			||||||
          minHeight: 300,
 | 
					            // minHeight: 300,
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        width: Get.mediaQuery.size.width,
 | 
					        width: Get.mediaQuery.size.width,
 | 
				
			||||||
        decoration: const BoxDecoration(
 | 
					        decoration: const BoxDecoration(
 | 
				
			||||||
@ -72,6 +72,28 @@ Future<void> showFeatureBottomSheet(
 | 
				
			|||||||
            const SizedBox(height: 10),
 | 
					            const SizedBox(height: 10),
 | 
				
			||||||
          ],
 | 
					          ],
 | 
				
			||||||
          ..._buildFeatureContent(feature),
 | 
					          ..._buildFeatureContent(feature),
 | 
				
			||||||
 | 
					          const SizedBox(height: 20),
 | 
				
			||||||
 | 
					          Row(
 | 
				
			||||||
 | 
					            mainAxisAlignment: MainAxisAlignment.end,
 | 
				
			||||||
 | 
					            children: [
 | 
				
			||||||
 | 
					              ElevatedButton(
 | 
				
			||||||
 | 
					                child: const Row(
 | 
				
			||||||
 | 
					                  children: [
 | 
				
			||||||
 | 
					                    Icon(
 | 
				
			||||||
 | 
					                      Icons.share_location,
 | 
				
			||||||
 | 
					                      color: Colors.black,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    SizedBox(width: 4),
 | 
				
			||||||
 | 
					                    Text(
 | 
				
			||||||
 | 
					                      "Start Navigation",
 | 
				
			||||||
 | 
					                      style: TextStyle(color: Colors.black),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ],
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                onPressed: () => {},
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
        ]),
 | 
					        ]),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
@ -114,7 +136,35 @@ List<Widget> _buildRoomContent(Feature feature) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Builds the content for the Door feature type.
 | 
					/// Builds the content for the Door feature type.
 | 
				
			||||||
List<Widget> _buildDoorContent(Feature feature, List<String> connects) {
 | 
					List<Widget> _buildDoorContent(Feature feature, List<String> connects) {
 | 
				
			||||||
  return [Text('Door: ${feature.name}\nConnects: $connects')];
 | 
					  return [
 | 
				
			||||||
 | 
					    Text(
 | 
				
			||||||
 | 
					      feature.name,
 | 
				
			||||||
 | 
					      style: const TextStyle(fontSize: 18),
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    const SizedBox(height: 10),
 | 
				
			||||||
 | 
					    if (connects.isNotEmpty) ...[
 | 
				
			||||||
 | 
					      const Align(
 | 
				
			||||||
 | 
					        alignment: Alignment.centerLeft,
 | 
				
			||||||
 | 
					        child: Padding(
 | 
				
			||||||
 | 
					          padding: EdgeInsets.only(right: 4),
 | 
				
			||||||
 | 
					          child: Text(
 | 
				
			||||||
 | 
					            'Connects:',
 | 
				
			||||||
 | 
					            style: TextStyle(fontWeight: FontWeight.bold),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      Align(
 | 
				
			||||||
 | 
					        alignment: Alignment.centerLeft,
 | 
				
			||||||
 | 
					        child: Wrap(
 | 
				
			||||||
 | 
					          spacing: 8,
 | 
				
			||||||
 | 
					          runSpacing: 4,
 | 
				
			||||||
 | 
					          children: connects.map((place) {
 | 
				
			||||||
 | 
					            return ColorfulChip(label: place.toString());
 | 
				
			||||||
 | 
					          }).toList(),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Builds the content for the Toilet feature type.
 | 
					/// Builds the content for the Toilet feature type.
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,9 @@ import 'package:uninav/map.dart';
 | 
				
			|||||||
import 'package:uninav/util/geomath.dart';
 | 
					import 'package:uninav/util/geomath.dart';
 | 
				
			||||||
import 'package:uninav/util/util.dart';
 | 
					import 'package:uninav/util/util.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
List<Widget> renderLevel(int level, {LayerHitNotifier? hitNotifier}) {
 | 
					List<Widget> renderLevel(
 | 
				
			||||||
 | 
					  int level,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
  return <Widget>[
 | 
					  return <Widget>[
 | 
				
			||||||
    LevelLayer(
 | 
					    LevelLayer(
 | 
				
			||||||
      filter: (feature) =>
 | 
					      filter: (feature) =>
 | 
				
			||||||
@ -22,7 +24,6 @@ List<Widget> renderLevel(int level, {LayerHitNotifier? hitNotifier}) {
 | 
				
			|||||||
              color: Colors.orange.withOpacity(0.2),
 | 
					              color: Colors.orange.withOpacity(0.2),
 | 
				
			||||||
              borderColor: Colors.orange,
 | 
					              borderColor: Colors.orange,
 | 
				
			||||||
              borderStrokeWidth: 2,
 | 
					              borderStrokeWidth: 2,
 | 
				
			||||||
                hitValue: feature,
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
          .unwrap(),
 | 
					          .unwrap(),
 | 
				
			||||||
@ -41,7 +42,7 @@ List<Widget> renderLevel(int level, {LayerHitNotifier? hitNotifier}) {
 | 
				
			|||||||
        ),
 | 
					        ),
 | 
				
			||||||
        alignment: Alignment.center,
 | 
					        alignment: Alignment.center,
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
        notifier: hitNotifier),
 | 
					    ),
 | 
				
			||||||
    LevelLayer(
 | 
					    LevelLayer(
 | 
				
			||||||
      filter: (feature) => feature.level == level && feature.type is Room,
 | 
					      filter: (feature) => feature.level == level && feature.type is Room,
 | 
				
			||||||
      polyConstructor: (feature) => feature
 | 
					      polyConstructor: (feature) => feature
 | 
				
			||||||
@ -51,11 +52,9 @@ List<Widget> renderLevel(int level, {LayerHitNotifier? hitNotifier}) {
 | 
				
			|||||||
              color: Colors.green.withOpacity(1.2),
 | 
					              color: Colors.green.withOpacity(1.2),
 | 
				
			||||||
              borderColor: Colors.green,
 | 
					              borderColor: Colors.green,
 | 
				
			||||||
              borderStrokeWidth: 2,
 | 
					              borderStrokeWidth: 2,
 | 
				
			||||||
              hitValue: feature,
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
          .unwrap(),
 | 
					          .unwrap(),
 | 
				
			||||||
      notifier: hitNotifier,
 | 
					 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
    LevelLayer(
 | 
					    LevelLayer(
 | 
				
			||||||
      filter: (feature) => feature.level == level && feature.type is Door,
 | 
					      filter: (feature) => feature.level == level && feature.type is Door,
 | 
				
			||||||
@ -72,7 +71,6 @@ List<Widget> renderLevel(int level, {LayerHitNotifier? hitNotifier}) {
 | 
				
			|||||||
          alignment: Alignment.center,
 | 
					          alignment: Alignment.center,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      notifier: hitNotifier,
 | 
					 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
    LevelLayer(
 | 
					    LevelLayer(
 | 
				
			||||||
      filter: (feature) => feature.level == level && feature.type is Toilet,
 | 
					      filter: (feature) => feature.level == level && feature.type is Toilet,
 | 
				
			||||||
@ -91,7 +89,6 @@ List<Widget> renderLevel(int level, {LayerHitNotifier? hitNotifier}) {
 | 
				
			|||||||
          alignment: Alignment.center,
 | 
					          alignment: Alignment.center,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      notifier: hitNotifier,
 | 
					 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
    LevelLayer(
 | 
					    LevelLayer(
 | 
				
			||||||
      filter: (feature) =>
 | 
					      filter: (feature) =>
 | 
				
			||||||
@ -110,7 +107,6 @@ List<Widget> renderLevel(int level, {LayerHitNotifier? hitNotifier}) {
 | 
				
			|||||||
          alignment: Alignment.center,
 | 
					          alignment: Alignment.center,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      notifier: hitNotifier,
 | 
					 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
    LevelLayer(
 | 
					    LevelLayer(
 | 
				
			||||||
      filter: (feature) =>
 | 
					      filter: (feature) =>
 | 
				
			||||||
@ -129,7 +125,6 @@ List<Widget> renderLevel(int level, {LayerHitNotifier? hitNotifier}) {
 | 
				
			|||||||
          alignment: Alignment.center,
 | 
					          alignment: Alignment.center,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      notifier: hitNotifier,
 | 
					 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -140,7 +135,6 @@ class LevelLayer extends StatelessWidget {
 | 
				
			|||||||
  final Marker Function(LatLng, String)? polyCenterMarkerConstructor;
 | 
					  final Marker Function(LatLng, String)? polyCenterMarkerConstructor;
 | 
				
			||||||
  final Marker Function(Feature)? markerConstructor;
 | 
					  final Marker Function(Feature)? markerConstructor;
 | 
				
			||||||
  final int? level;
 | 
					  final int? level;
 | 
				
			||||||
  final LayerHitNotifier? notifier;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const LevelLayer({
 | 
					  const LevelLayer({
 | 
				
			||||||
    this.level,
 | 
					    this.level,
 | 
				
			||||||
@ -148,7 +142,6 @@ class LevelLayer extends StatelessWidget {
 | 
				
			|||||||
    this.polyConstructor,
 | 
					    this.polyConstructor,
 | 
				
			||||||
    this.polyCenterMarkerConstructor,
 | 
					    this.polyCenterMarkerConstructor,
 | 
				
			||||||
    this.markerConstructor,
 | 
					    this.markerConstructor,
 | 
				
			||||||
    this.notifier,
 | 
					 | 
				
			||||||
    super.key,
 | 
					    super.key,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -173,7 +166,6 @@ class LevelLayer extends StatelessWidget {
 | 
				
			|||||||
                            points: points,
 | 
					                            points: points,
 | 
				
			||||||
                            borderColor: Colors.black26,
 | 
					                            borderColor: Colors.black26,
 | 
				
			||||||
                            borderStrokeWidth: 2.0,
 | 
					                            borderStrokeWidth: 2.0,
 | 
				
			||||||
                            hitValue: feature,
 | 
					 | 
				
			||||||
                          ))
 | 
					                          ))
 | 
				
			||||||
                  .unwrap());
 | 
					                  .unwrap());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -241,14 +233,12 @@ class LevelLayer extends StatelessWidget {
 | 
				
			|||||||
          widgets.add(TranslucentPointer(
 | 
					          widgets.add(TranslucentPointer(
 | 
				
			||||||
            child: PolygonLayer(
 | 
					            child: PolygonLayer(
 | 
				
			||||||
              polygons: filteredPolygons,
 | 
					              polygons: filteredPolygons,
 | 
				
			||||||
              hitNotifier: notifier,
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ));
 | 
					          ));
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          widgets.add(TranslucentPointer(
 | 
					          widgets.add(TranslucentPointer(
 | 
				
			||||||
            child: PolygonLayer(
 | 
					            child: PolygonLayer(
 | 
				
			||||||
              polygons: filteredPolygons,
 | 
					              polygons: filteredPolygons,
 | 
				
			||||||
              hitNotifier: notifier,
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ));
 | 
					          ));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -86,15 +86,15 @@ class MyMapController extends GetxController {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      final featuresList = <Feature>[];
 | 
					      final featuresList = <Feature>[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      print('doing');
 | 
					      // print('doing');
 | 
				
			||||||
      final geojson = GeoJSONFeatureCollection.fromJSON(geoJsonString);
 | 
					      final geojson = GeoJSONFeatureCollection.fromJSON(geoJsonString);
 | 
				
			||||||
      print('done');
 | 
					      // print('done');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      for (final feature in geojson.features) {
 | 
					      for (final feature in geojson.features) {
 | 
				
			||||||
        print(feature);
 | 
					        // print(feature);
 | 
				
			||||||
        print(feature?.properties);
 | 
					        // print(feature?.properties);
 | 
				
			||||||
        if (feature == null) continue;
 | 
					        if (feature == null) continue;
 | 
				
			||||||
        print(feature.properties);
 | 
					        // print(feature.properties);
 | 
				
			||||||
        final parsed = parseFeature(
 | 
					        final parsed = parseFeature(
 | 
				
			||||||
            feature.properties ?? <String, dynamic>{}, feature.geometry);
 | 
					            feature.properties ?? <String, dynamic>{}, feature.geometry);
 | 
				
			||||||
        if (parsed case Ok(:final ok)) {
 | 
					        if (parsed case Ok(:final ok)) {
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,6 @@ class Feature with _$Feature {
 | 
				
			|||||||
            points: pts,
 | 
					            points: pts,
 | 
				
			||||||
            borderColor: Colors.black26,
 | 
					            borderColor: Colors.black26,
 | 
				
			||||||
            borderStrokeWidth: 2.0,
 | 
					            borderStrokeWidth: 2.0,
 | 
				
			||||||
            hitValue: 'test${pts.length}',
 | 
					 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
      final polygon = geometry as GeoJSONPolygon;
 | 
					      final polygon = geometry as GeoJSONPolygon;
 | 
				
			||||||
      // print(polygon.geometry!.geoSeries[0].geoPoints);
 | 
					      // print(polygon.geometry!.geoSeries[0].geoPoints);
 | 
				
			||||||
 | 
				
			|||||||
@ -40,7 +40,7 @@ Result<Feature> parseFeature(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  final building = yaml['building'] as String?;
 | 
					  final building = yaml['building'] as String?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  print("yaml: $yaml");
 | 
					  // print("yaml: $yaml");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  var raw_type = yaml['type'] as String?;
 | 
					  var raw_type = yaml['type'] as String?;
 | 
				
			||||||
  if (raw_type == null && layer?.toLowerCase() == 'buildings') {
 | 
					  if (raw_type == null && layer?.toLowerCase() == 'buildings') {
 | 
				
			||||||
@ -123,7 +123,7 @@ Result<List<String>> stringifyList(List<dynamic> tramLines) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Result<List<T>> getYamlList<T>(YamlMap yaml, String key) {
 | 
					Result<List<T>> getYamlList<T>(YamlMap yaml, String key) {
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    print('yaml is ${yaml[key]}');
 | 
					    // print('yaml is ${yaml[key]}');
 | 
				
			||||||
    final val = (yaml[key] as YamlList?);
 | 
					    final val = (yaml[key] as YamlList?);
 | 
				
			||||||
    if (val == null) {
 | 
					    if (val == null) {
 | 
				
			||||||
      return bail("Key $key is missing in yaml");
 | 
					      return bail("Key $key is missing in yaml");
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/services.dart';
 | 
				
			||||||
import 'package:get/get.dart';
 | 
					import 'package:get/get.dart';
 | 
				
			||||||
import 'package:uninav/controllers/isar_controller.dart';
 | 
					import 'package:uninav/controllers/isar_controller.dart';
 | 
				
			||||||
import 'package:uninav/controllers/map_controller.dart';
 | 
					import 'package:uninav/controllers/map_controller.dart';
 | 
				
			||||||
@ -8,6 +9,9 @@ import 'package:uninav/settings.dart';
 | 
				
			|||||||
// TODO: maybe make not async?
 | 
					// TODO: maybe make not async?
 | 
				
			||||||
void main() async {
 | 
					void main() async {
 | 
				
			||||||
  Get.put(MyMapController());
 | 
					  Get.put(MyMapController());
 | 
				
			||||||
 | 
					  await Get.find<MyMapController>()
 | 
				
			||||||
 | 
					      .loadGeoJson(await rootBundle.loadString('assets/geo/uulm_beta.geojson'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  await Get.putAsync(() async {
 | 
					  await Get.putAsync(() async {
 | 
				
			||||||
    final controller = IsarController();
 | 
					    final controller = IsarController();
 | 
				
			||||||
    await controller.initializeIsar();
 | 
					    await controller.initializeIsar();
 | 
				
			||||||
 | 
				
			|||||||
@ -19,7 +19,6 @@ class MapPage extends StatelessWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    final LayerHitNotifier hitNotifier = ValueNotifier(null);
 | 
					 | 
				
			||||||
    return Scaffold(
 | 
					    return Scaffold(
 | 
				
			||||||
        drawer: MyDrawer(),
 | 
					        drawer: MyDrawer(),
 | 
				
			||||||
        appBar: AppBar(
 | 
					        appBar: AppBar(
 | 
				
			||||||
@ -43,8 +42,6 @@ class MapPage extends StatelessWidget {
 | 
				
			|||||||
        floatingActionButton: FloatingActionButton(
 | 
					        floatingActionButton: FloatingActionButton(
 | 
				
			||||||
          onPressed: () async {
 | 
					          onPressed: () async {
 | 
				
			||||||
            // Add onPressed logic here
 | 
					            // Add onPressed logic here
 | 
				
			||||||
            await Get.find<MyMapController>().loadGeoJson(
 | 
					 | 
				
			||||||
                await rootBundle.loadString('assets/geo/uulm_beta.geojson'));
 | 
					 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          child: const Icon(Icons.add),
 | 
					          child: const Icon(Icons.add),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
@ -70,7 +67,6 @@ class MapPage extends StatelessWidget {
 | 
				
			|||||||
                TranslucentPointer(
 | 
					                TranslucentPointer(
 | 
				
			||||||
                  child: LevelLayer(
 | 
					                  child: LevelLayer(
 | 
				
			||||||
                    filter: (feature) => feature.type is Building,
 | 
					                    filter: (feature) => feature.type is Building,
 | 
				
			||||||
                    notifier: hitNotifier,
 | 
					 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -97,10 +93,8 @@ class MapPage extends StatelessWidget {
 | 
				
			|||||||
                                  color: Colors.green.withOpacity(0.2),
 | 
					                                  color: Colors.green.withOpacity(0.2),
 | 
				
			||||||
                                  borderColor: Colors.green,
 | 
					                                  borderColor: Colors.green,
 | 
				
			||||||
                                  borderStrokeWidth: 1,
 | 
					                                  borderStrokeWidth: 1,
 | 
				
			||||||
                                  hitValue: feature,
 | 
					 | 
				
			||||||
                                ))
 | 
					                                ))
 | 
				
			||||||
                        .unwrap(),
 | 
					                        .unwrap(),
 | 
				
			||||||
                    notifier: hitNotifier,
 | 
					 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -109,7 +103,7 @@ class MapPage extends StatelessWidget {
 | 
				
			|||||||
                  () => Stack(
 | 
					                  () => Stack(
 | 
				
			||||||
                      children: renderLevel(
 | 
					                      children: renderLevel(
 | 
				
			||||||
                    Get.find<MyMapController>().currentLevel.value,
 | 
					                    Get.find<MyMapController>().currentLevel.value,
 | 
				
			||||||
                          hitNotifier: hitNotifier)),
 | 
					                  )),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              ],
 | 
					              ],
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										425
									
								
								lib/nav/graph.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										425
									
								
								lib/nav/graph.dart
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,425 @@
 | 
				
			|||||||
 | 
					import 'package:anyhow/anyhow.dart';
 | 
				
			||||||
 | 
					import 'package:collection/collection.dart';
 | 
				
			||||||
 | 
					import 'package:directed_graph/directed_graph.dart';
 | 
				
			||||||
 | 
					import 'package:fast_immutable_collections/fast_immutable_collections.dart';
 | 
				
			||||||
 | 
					import 'package:freezed_annotation/freezed_annotation.dart';
 | 
				
			||||||
 | 
					import 'package:geojson_vi/geojson_vi.dart';
 | 
				
			||||||
 | 
					import 'package:get/get.dart';
 | 
				
			||||||
 | 
					import 'package:latlong2/latlong.dart';
 | 
				
			||||||
 | 
					import 'package:uninav/data/geo/model.dart';
 | 
				
			||||||
 | 
					import 'package:uninav/util/geojson_util.dart';
 | 
				
			||||||
 | 
					import 'package:uninav/util/util.dart';
 | 
				
			||||||
 | 
					import 'dart:collection';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					part 'graph.freezed.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@freezed
 | 
				
			||||||
 | 
					class GraphFeature with _$GraphFeature {
 | 
				
			||||||
 | 
					  const factory GraphFeature.buildingFloor(int floor, Feature building) =
 | 
				
			||||||
 | 
					      BuildingFloor;
 | 
				
			||||||
 | 
					  const factory GraphFeature.portal(int fromFloor, String from, int toFloor,
 | 
				
			||||||
 | 
					      String to, Feature baseFeature) = Portal;
 | 
				
			||||||
 | 
					  const factory GraphFeature.basicFeature(
 | 
				
			||||||
 | 
					      int floor, String building, Feature feature) = BasicFeature;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const GraphFeature._();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Result<LatLng> getCenter() {
 | 
				
			||||||
 | 
					    return when(
 | 
				
			||||||
 | 
					      buildingFloor: (floor, building) => building.getCenterPoint(),
 | 
				
			||||||
 | 
					      portal: (fromFloor, from, toFloor, to, baseFeature) =>
 | 
				
			||||||
 | 
					          baseFeature.getCenterPoint(),
 | 
				
			||||||
 | 
					      basicFeature: (floor, building, feature) => feature.getCenterPoint(),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  double distanceTo(GraphFeature other, String unit) => distanceBetweenLatLng(
 | 
				
			||||||
 | 
					      getCenter().unwrap(), other.getCenter().unwrap(), unit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  double metersTo(GraphFeature other) => distanceTo(other, "meters");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    return when(
 | 
				
			||||||
 | 
					      buildingFloor: (floor, building) => 'Floor (${building.name}:$floor)',
 | 
				
			||||||
 | 
					      portal: (fromFloor, from, toFloor, to, _) =>
 | 
				
			||||||
 | 
					          'Portal ($from:$fromFloor -> $to:$toFloor)',
 | 
				
			||||||
 | 
					      basicFeature: (floor, building, feature) =>
 | 
				
			||||||
 | 
					          'Feature (${formatFeatureTitle(feature)} ($building:$floor))',
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool eq(String? a, String? b) => a?.toLowerCase() == b?.toLowerCase();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IList<GraphFeature> wrap(Feature feature, int floor, String buildingFrom) {
 | 
				
			||||||
 | 
					  return feature.type
 | 
				
			||||||
 | 
					      .maybeWhen(
 | 
				
			||||||
 | 
					        building: () => [GraphFeature.buildingFloor(floor, feature)],
 | 
				
			||||||
 | 
					        stairs: (floors) => stairPortalGenerator(floors, floor, feature),
 | 
				
			||||||
 | 
					        lift: (floors) => stairPortalGenerator(floors, floor, feature, 99),
 | 
				
			||||||
 | 
					        door: (connections) =>
 | 
				
			||||||
 | 
					            doorPortalGenerator(connections, floor, buildingFrom, feature),
 | 
				
			||||||
 | 
					        orElse: () => [GraphFeature.basicFeature(floor, buildingFrom, feature)],
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					      .lock;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					List<GraphFeature> doorPortalGenerator(
 | 
				
			||||||
 | 
					    List<String> connections, int floor, String from, Feature feature) {
 | 
				
			||||||
 | 
					  final portals = <GraphFeature>[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (final connection in connections.where((c) => !eq(c, from))) {
 | 
				
			||||||
 | 
					    portals.add(GraphFeature.portal(
 | 
				
			||||||
 | 
					        floor, from, floor, connection.toLowerCase(), feature));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return portals;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					List<GraphFeature> stairPortalGenerator(
 | 
				
			||||||
 | 
					    List<int> floors, int floor, Feature feature,
 | 
				
			||||||
 | 
					    [int maxDist = 1]) {
 | 
				
			||||||
 | 
					  final portals = <GraphFeature>[];
 | 
				
			||||||
 | 
					  for (int i = 1; i <= maxDist; i++) {
 | 
				
			||||||
 | 
					    if (floors.contains(floor - i)) {
 | 
				
			||||||
 | 
					      portals.add(GraphFeature.portal(floor, feature.building!.toLowerCase(),
 | 
				
			||||||
 | 
					          floor - i, feature.building!.toLowerCase(), feature));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (floors.contains(floor + i)) {
 | 
				
			||||||
 | 
					      portals.add(GraphFeature.portal(floor, feature.building!.toLowerCase(),
 | 
				
			||||||
 | 
					          floor + i, feature.building!.toLowerCase(), feature));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return portals;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Feature unwrap(GraphFeature feature) {
 | 
				
			||||||
 | 
					  return feature.when(
 | 
				
			||||||
 | 
					    buildingFloor: (floor, building) => building,
 | 
				
			||||||
 | 
					    portal: (fromFloor, from, toFloor, to, baseFeature) => baseFeature,
 | 
				
			||||||
 | 
					    basicFeature: (floor, building, f) => f,
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double sum(double left, double right) => left + right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// WeightedDirectedGraph createGraph(Feature origin, List<Feature> allFeatures) {
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					List<GraphFeature> findAdjacent(
 | 
				
			||||||
 | 
					    GraphFeature feature, Iterable<Feature> allFeatures) {
 | 
				
			||||||
 | 
					  List<GraphFeature> adjacentFeatures = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (feature is BuildingFloor) {
 | 
				
			||||||
 | 
					    // find all features in the building on the right floor
 | 
				
			||||||
 | 
					    adjacentFeatures = allFeatures
 | 
				
			||||||
 | 
					        .where((f) => eq(f.building, feature.building.name) || f.type is Door)
 | 
				
			||||||
 | 
					        .where((f) => f.type.maybeWhen(
 | 
				
			||||||
 | 
					            lift: (levels) => levels.contains(feature.floor),
 | 
				
			||||||
 | 
					            stairs: (levels) => levels.contains(feature.floor),
 | 
				
			||||||
 | 
					            door: (connections) =>
 | 
				
			||||||
 | 
					                f.level == feature.floor &&
 | 
				
			||||||
 | 
					                connections
 | 
				
			||||||
 | 
					                    .map((e) => e.toLowerCase())
 | 
				
			||||||
 | 
					                    .contains(feature.building.name.toLowerCase()),
 | 
				
			||||||
 | 
					            orElse: () => f.level == feature.floor))
 | 
				
			||||||
 | 
					        .mapMany((f) => wrap(f, feature.floor, feature.building.name))
 | 
				
			||||||
 | 
					        .toList();
 | 
				
			||||||
 | 
					  } else if (feature is Portal) {
 | 
				
			||||||
 | 
					    adjacentFeatures = allFeatures
 | 
				
			||||||
 | 
					        .where((f) => eq(f.name, feature.to) && f.type is Building)
 | 
				
			||||||
 | 
					        .mapMany((f) => wrap(f, feature.toFloor, feature.to))
 | 
				
			||||||
 | 
					        .toList();
 | 
				
			||||||
 | 
					  } else if (feature is BasicFeature) {
 | 
				
			||||||
 | 
					    adjacentFeatures = allFeatures
 | 
				
			||||||
 | 
					        .where(
 | 
				
			||||||
 | 
					            (f) => eq(f.name, feature.feature.building) && f.type is Building)
 | 
				
			||||||
 | 
					        .mapMany((f) => wrap(f, feature.feature.level!, f.name))
 | 
				
			||||||
 | 
					        .toList();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return adjacentFeatures;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					List<GraphFeature> createGraphList(
 | 
				
			||||||
 | 
					    GraphFeature origin, List<Feature> allFeatures,
 | 
				
			||||||
 | 
					    [Set<GraphFeature>? visited]) {
 | 
				
			||||||
 | 
					  // final usedFeatures = <GraphFeature>[origin];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  visited ??= <GraphFeature>{origin};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final adjacent = findAdjacent(origin, allFeatures);
 | 
				
			||||||
 | 
					  for (final feature in adjacent.asSet()..removeAll(visited)) {
 | 
				
			||||||
 | 
					    visited.add(feature);
 | 
				
			||||||
 | 
					    final deeper = createGraphList(feature, allFeatures, visited);
 | 
				
			||||||
 | 
					    visited.addAll(deeper);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return visited.toList();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Map<GraphFeature, Map<GraphFeature, double>> createGraphMap(
 | 
				
			||||||
 | 
					    GraphFeature origin, List<Feature> allFeatures) {
 | 
				
			||||||
 | 
					  final graphList = createGraphList(origin, allFeatures);
 | 
				
			||||||
 | 
					  final graphMap = <GraphFeature, Map<GraphFeature, double>>{};
 | 
				
			||||||
 | 
					  for (final node in graphList) {
 | 
				
			||||||
 | 
					    final adjacents = node.when(
 | 
				
			||||||
 | 
					      buildingFloor: (floor, building) {
 | 
				
			||||||
 | 
					        return graphList
 | 
				
			||||||
 | 
					            .where((f) =>
 | 
				
			||||||
 | 
					                f is Portal &&
 | 
				
			||||||
 | 
					                    eq(f.from, building.name) &&
 | 
				
			||||||
 | 
					                    f.fromFloor == floor ||
 | 
				
			||||||
 | 
					                f is BasicFeature &&
 | 
				
			||||||
 | 
					                    eq(f.building, building.name) &&
 | 
				
			||||||
 | 
					                    f.floor == floor)
 | 
				
			||||||
 | 
					            .map((f) => f.when(
 | 
				
			||||||
 | 
					                  portal: (fromFloor, from, toFloor, to, baseFeature) => (
 | 
				
			||||||
 | 
					                    f,
 | 
				
			||||||
 | 
					                    f.metersTo(node),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  basicFeature: (floor, building, feature) =>
 | 
				
			||||||
 | 
					                      (f, f.metersTo(node)),
 | 
				
			||||||
 | 
					                  buildingFloor: (floor, building) => throw StateError(
 | 
				
			||||||
 | 
					                      "BUG: createGraphMap(): BuildingFloors shouldn't "
 | 
				
			||||||
 | 
					                      "be matched by BuildingFloors"),
 | 
				
			||||||
 | 
					                ));
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      portal: (fromFloor, from, toFloor, to, baseFeature) {
 | 
				
			||||||
 | 
					        return graphList
 | 
				
			||||||
 | 
					            .where((f) =>
 | 
				
			||||||
 | 
					                f is BuildingFloor &&
 | 
				
			||||||
 | 
					                eq(f.building.name, to) &&
 | 
				
			||||||
 | 
					                f.floor == toFloor)
 | 
				
			||||||
 | 
					            .map((f) => f.when(
 | 
				
			||||||
 | 
					                  portal: (fromFloor, from, toFloor, to, baseFeature) =>
 | 
				
			||||||
 | 
					                      throw StateError(
 | 
				
			||||||
 | 
					                          "BUG: createGraphMap(): Portals shouldn't "
 | 
				
			||||||
 | 
					                          "be matched by Portals"),
 | 
				
			||||||
 | 
					                  basicFeature: (floor, building, feature) => throw StateError(
 | 
				
			||||||
 | 
					                      "BUG: createGraphMap(): BasicFeatures shouldn't "
 | 
				
			||||||
 | 
					                      "be matched by BasicFeatures"),
 | 
				
			||||||
 | 
					                  buildingFloor: (floor, building) => (
 | 
				
			||||||
 | 
					                    f,
 | 
				
			||||||
 | 
					                    f.metersTo(node) +
 | 
				
			||||||
 | 
					                        5 /* 5 extra meters for all portals. TODO: smarter!*/
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ));
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      basicFeature: (floor, building, feature) {
 | 
				
			||||||
 | 
					        return graphList
 | 
				
			||||||
 | 
					            .where((f) =>
 | 
				
			||||||
 | 
					                f is BuildingFloor &&
 | 
				
			||||||
 | 
					                eq(f.building.name, building) &&
 | 
				
			||||||
 | 
					                f.floor == floor)
 | 
				
			||||||
 | 
					            .map((f) => f.when(
 | 
				
			||||||
 | 
					                  portal: (fromFloor, from, toFloor, to, baseFeature) =>
 | 
				
			||||||
 | 
					                      throw StateError(
 | 
				
			||||||
 | 
					                          "BUG: createGraphMap(): Portal shouldn't be matched "
 | 
				
			||||||
 | 
					                          "by BasicFeature"),
 | 
				
			||||||
 | 
					                  basicFeature: (floor, building, feature) => throw StateError(
 | 
				
			||||||
 | 
					                      "BUG: createGraphMap(): BasicFeatures shouldn't "
 | 
				
			||||||
 | 
					                      "be matched by BasicFeatures"),
 | 
				
			||||||
 | 
					                  buildingFloor: (floor, building) => (f, f.metersTo(node)),
 | 
				
			||||||
 | 
					                ));
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    graphMap[node] =
 | 
				
			||||||
 | 
					        Map.fromEntries(adjacents.map((tup) => MapEntry(tup.$1, tup.$2)));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return graphMap;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WeightedDirectedGraph<GraphFeature, double> createGraph(
 | 
				
			||||||
 | 
					    GraphFeature origin, List<Feature> allFeatures) {
 | 
				
			||||||
 | 
					  final map = createGraphMap(origin, allFeatures);
 | 
				
			||||||
 | 
					  final graph = WeightedDirectedGraph<GraphFeature, double>(
 | 
				
			||||||
 | 
					    map,
 | 
				
			||||||
 | 
					    summation: sum,
 | 
				
			||||||
 | 
					    zero: 0.0,
 | 
				
			||||||
 | 
					    comparator: (a, b) => compareGraphFeatures(a, b),
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					  return graph;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Result<List<(GraphFeature, double)>> findShortestPath(
 | 
				
			||||||
 | 
					    GraphFeature origin, GraphFeature destination, List<Feature> allFeatures,
 | 
				
			||||||
 | 
					    [heuristicVariant = "zero", heuristicMultiplier = 0.2]) {
 | 
				
			||||||
 | 
					  var graph = createGraphMap(origin, allFeatures);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!(graph.keys.contains(origin) &&
 | 
				
			||||||
 | 
					      graph.values.firstWhereOrNull((vals) => vals.containsKey(destination)) !=
 | 
				
			||||||
 | 
					          null)) {
 | 
				
			||||||
 | 
					    return bail("Origin or destination not in graph");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // euclidean distance heuristic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  double Function(GraphFeature) heuristic =
 | 
				
			||||||
 | 
					      (GraphFeature node) => 0.0; // standard zero
 | 
				
			||||||
 | 
					  if (heuristicVariant == "zero") {
 | 
				
			||||||
 | 
					    heuristic = (GraphFeature node) => 0.0;
 | 
				
			||||||
 | 
					  } else if (heuristicVariant == "euclidean") {
 | 
				
			||||||
 | 
					    heuristic =
 | 
				
			||||||
 | 
					        (GraphFeature node) => node.metersTo(destination) * heuristicMultiplier;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  //heuristic(GraphFeature node) => 0.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // openlist
 | 
				
			||||||
 | 
					  // format: (heuristic, g-val, parent?, node)
 | 
				
			||||||
 | 
					  PriorityQueue<(double, double, GraphFeature?, GraphFeature)> openlist =
 | 
				
			||||||
 | 
					      HeapPriorityQueue(
 | 
				
			||||||
 | 
					    // reverse order (cmp b to a) because lower f-val (shorter distance) is better
 | 
				
			||||||
 | 
					    (a, b) => (b.$1 + b.$2).compareTo((a.$1 + a.$2)),
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final Map<GraphFeature, (GraphFeature?, double)> bestPathMap = {
 | 
				
			||||||
 | 
					    origin: (null, 0.0)
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  openlist.add((heuristic(origin), 0.0, null, origin));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // closed list
 | 
				
			||||||
 | 
					  Set<GraphFeature> closedlist = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var cost = 0.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (openlist.isNotEmpty) {
 | 
				
			||||||
 | 
					    final (f, g, parent, node) = openlist.removeFirst();
 | 
				
			||||||
 | 
					    closedlist.add(node);
 | 
				
			||||||
 | 
					    bestPathMap[node] = (parent, g);
 | 
				
			||||||
 | 
					    if (node == destination) {
 | 
				
			||||||
 | 
					      cost = g;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					      // TODO: restore path
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // expand node
 | 
				
			||||||
 | 
					    final adjacents = graph[node]!;
 | 
				
			||||||
 | 
					    for (final entry in adjacents.entries) {
 | 
				
			||||||
 | 
					      final adjNode = entry.key;
 | 
				
			||||||
 | 
					      final adjCost = entry.value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (closedlist.contains(adjNode)) {
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      bool found = false;
 | 
				
			||||||
 | 
					      for (final open in openlist.unorderedElements) {
 | 
				
			||||||
 | 
					        if (open.$4 == adjNode) {
 | 
				
			||||||
 | 
					          found = true;
 | 
				
			||||||
 | 
					          if (g + adjCost < open.$2) {
 | 
				
			||||||
 | 
					            openlist.remove(open);
 | 
				
			||||||
 | 
					            openlist.add((
 | 
				
			||||||
 | 
					              open.$1 /* heuristic stays the same */,
 | 
				
			||||||
 | 
					              g + adjCost,
 | 
				
			||||||
 | 
					              adjNode,
 | 
				
			||||||
 | 
					              open.$4
 | 
				
			||||||
 | 
					            ));
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (!found) {
 | 
				
			||||||
 | 
					        openlist.add((
 | 
				
			||||||
 | 
					          f + heuristic(adjNode),
 | 
				
			||||||
 | 
					          g + adjCost,
 | 
				
			||||||
 | 
					          node,
 | 
				
			||||||
 | 
					          adjNode,
 | 
				
			||||||
 | 
					        ));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (bestPathMap.isNotEmpty) {
 | 
				
			||||||
 | 
					    final path = <(GraphFeature, double)>[];
 | 
				
			||||||
 | 
					    (GraphFeature?, double)? currentNode = (destination, cost);
 | 
				
			||||||
 | 
					    while (currentNode?.$1 != null) {
 | 
				
			||||||
 | 
					      final nextNode = bestPathMap[currentNode!.$1];
 | 
				
			||||||
 | 
					      path.insert(
 | 
				
			||||||
 | 
					          0, (currentNode!.$1!, currentNode.$2 - (nextNode?.$2 ?? 0.0)));
 | 
				
			||||||
 | 
					      currentNode = nextNode;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return Ok(path);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return bail("No path found");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Compares two [GraphFeature] instances and determines their relative order.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// The comparison is based on the specific subtypes and properties of the
 | 
				
			||||||
 | 
					/// [GraphFeature] instances. The comparison logic is as follows:
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// 1. If both instances are [BuildingFloor], they are compared first by the
 | 
				
			||||||
 | 
					///    building name and then by the floor number.
 | 
				
			||||||
 | 
					/// 2. If one instance is a [Portal] and the other is a [BuildingFloor] or
 | 
				
			||||||
 | 
					///    [BasicFeature], the [Portal] is considered greater.
 | 
				
			||||||
 | 
					/// 3. If both instances are [Portal], they are compared first by the `from`
 | 
				
			||||||
 | 
					///    property, then by the `to` property, and finally by the `baseFeature` name.
 | 
				
			||||||
 | 
					/// 4. If one instance is a [BasicFeature] and the other is a [BuildingFloor] or
 | 
				
			||||||
 | 
					///    [Portal], the [BasicFeature] is considered greater.
 | 
				
			||||||
 | 
					/// 5. If both instances are [BasicFeature], they are compared first by the
 | 
				
			||||||
 | 
					///    building name, then by the floor number, and finally by the feature name.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Returns a negative value if [a] is considered "less than" [b], a positive
 | 
				
			||||||
 | 
					/// value if [a] is considered "greater than" [b], and zero if they are considered
 | 
				
			||||||
 | 
					/// equal.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// This function can be used as a comparator for sorting or ordering
 | 
				
			||||||
 | 
					/// [GraphFeature] instances.
 | 
				
			||||||
 | 
					int compareGraphFeatures(GraphFeature a, GraphFeature b) {
 | 
				
			||||||
 | 
					  return a.when(
 | 
				
			||||||
 | 
					    buildingFloor: (floorA, buildingA) {
 | 
				
			||||||
 | 
					      return b.when(
 | 
				
			||||||
 | 
					        buildingFloor: (floorB, buildingB) {
 | 
				
			||||||
 | 
					          final buildingComparison = buildingA.name.compareTo(buildingB.name);
 | 
				
			||||||
 | 
					          if (buildingComparison != 0) {
 | 
				
			||||||
 | 
					            return buildingComparison;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          return floorA.compareTo(floorB);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        portal: (fromFloorB, fromB, toFloorB, toB, baseFeatureB) => -1,
 | 
				
			||||||
 | 
					        basicFeature: (floorB, buildingB, featureB) => -1,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    portal: (fromFloorA, fromA, toFloorA, toA, baseFeatureA) {
 | 
				
			||||||
 | 
					      return b.when(
 | 
				
			||||||
 | 
					        buildingFloor: (floorB, buildingB) => 1,
 | 
				
			||||||
 | 
					        portal: (fromFloorB, fromB, toFloorB, toB, baseFeatureB) {
 | 
				
			||||||
 | 
					          final fromComparison = fromA.compareTo(fromB);
 | 
				
			||||||
 | 
					          if (fromComparison != 0) {
 | 
				
			||||||
 | 
					            return fromComparison;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          final toComparison = toA.compareTo(toB);
 | 
				
			||||||
 | 
					          if (toComparison != 0) {
 | 
				
			||||||
 | 
					            return toComparison;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          return baseFeatureA.name.compareTo(baseFeatureB.name);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        basicFeature: (floorB, buildingB, featureB) => -1,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    basicFeature: (floorA, buildingA, featureA) {
 | 
				
			||||||
 | 
					      return b.when(
 | 
				
			||||||
 | 
					        buildingFloor: (floorB, buildingB) => 1,
 | 
				
			||||||
 | 
					        portal: (fromFloorB, fromB, toFloorB, toB, baseFeatureB) => 1,
 | 
				
			||||||
 | 
					        basicFeature: (floorB, buildingB, featureB) {
 | 
				
			||||||
 | 
					          final buildingComparison = buildingA.compareTo(buildingB);
 | 
				
			||||||
 | 
					          if (buildingComparison != 0) {
 | 
				
			||||||
 | 
					            return buildingComparison;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          final floorComparison = floorA.compareTo(floorB);
 | 
				
			||||||
 | 
					          if (floorComparison != 0) {
 | 
				
			||||||
 | 
					            return floorComparison;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          return featureA.name.compareTo(featureB.name);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										646
									
								
								lib/nav/graph.freezed.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										646
									
								
								lib/nav/graph.freezed.dart
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,646 @@
 | 
				
			|||||||
 | 
					// coverage:ignore-file
 | 
				
			||||||
 | 
					// GENERATED CODE - DO NOT MODIFY BY HAND
 | 
				
			||||||
 | 
					// ignore_for_file: type=lint
 | 
				
			||||||
 | 
					// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					part of 'graph.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// **************************************************************************
 | 
				
			||||||
 | 
					// FreezedGenerator
 | 
				
			||||||
 | 
					// **************************************************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					T _$identity<T>(T value) => value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					final _privateConstructorUsedError = UnsupportedError(
 | 
				
			||||||
 | 
					    'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// @nodoc
 | 
				
			||||||
 | 
					mixin _$GraphFeature {
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult when<TResult extends Object?>({
 | 
				
			||||||
 | 
					    required TResult Function(int floor, Feature building) buildingFloor,
 | 
				
			||||||
 | 
					    required TResult Function(int fromFloor, String from, int toFloor,
 | 
				
			||||||
 | 
					            String to, Feature baseFeature)
 | 
				
			||||||
 | 
					        portal,
 | 
				
			||||||
 | 
					    required TResult Function(int floor, String building, Feature feature)
 | 
				
			||||||
 | 
					        basicFeature,
 | 
				
			||||||
 | 
					  }) =>
 | 
				
			||||||
 | 
					      throw _privateConstructorUsedError;
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult? whenOrNull<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult? Function(int floor, Feature building)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult? Function(int fromFloor, String from, int toFloor, String to,
 | 
				
			||||||
 | 
					            Feature baseFeature)?
 | 
				
			||||||
 | 
					        portal,
 | 
				
			||||||
 | 
					    TResult? Function(int floor, String building, Feature feature)?
 | 
				
			||||||
 | 
					        basicFeature,
 | 
				
			||||||
 | 
					  }) =>
 | 
				
			||||||
 | 
					      throw _privateConstructorUsedError;
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult maybeWhen<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult Function(int floor, Feature building)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult Function(int fromFloor, String from, int toFloor, String to,
 | 
				
			||||||
 | 
					            Feature baseFeature)?
 | 
				
			||||||
 | 
					        portal,
 | 
				
			||||||
 | 
					    TResult Function(int floor, String building, Feature feature)? basicFeature,
 | 
				
			||||||
 | 
					    required TResult orElse(),
 | 
				
			||||||
 | 
					  }) =>
 | 
				
			||||||
 | 
					      throw _privateConstructorUsedError;
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult map<TResult extends Object?>({
 | 
				
			||||||
 | 
					    required TResult Function(BuildingFloor value) buildingFloor,
 | 
				
			||||||
 | 
					    required TResult Function(Portal value) portal,
 | 
				
			||||||
 | 
					    required TResult Function(BasicFeature value) basicFeature,
 | 
				
			||||||
 | 
					  }) =>
 | 
				
			||||||
 | 
					      throw _privateConstructorUsedError;
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult? mapOrNull<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult? Function(BuildingFloor value)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult? Function(Portal value)? portal,
 | 
				
			||||||
 | 
					    TResult? Function(BasicFeature value)? basicFeature,
 | 
				
			||||||
 | 
					  }) =>
 | 
				
			||||||
 | 
					      throw _privateConstructorUsedError;
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult maybeMap<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult Function(BuildingFloor value)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult Function(Portal value)? portal,
 | 
				
			||||||
 | 
					    TResult Function(BasicFeature value)? basicFeature,
 | 
				
			||||||
 | 
					    required TResult orElse(),
 | 
				
			||||||
 | 
					  }) =>
 | 
				
			||||||
 | 
					      throw _privateConstructorUsedError;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// @nodoc
 | 
				
			||||||
 | 
					abstract class $GraphFeatureCopyWith<$Res> {
 | 
				
			||||||
 | 
					  factory $GraphFeatureCopyWith(
 | 
				
			||||||
 | 
					          GraphFeature value, $Res Function(GraphFeature) then) =
 | 
				
			||||||
 | 
					      _$GraphFeatureCopyWithImpl<$Res, GraphFeature>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// @nodoc
 | 
				
			||||||
 | 
					class _$GraphFeatureCopyWithImpl<$Res, $Val extends GraphFeature>
 | 
				
			||||||
 | 
					    implements $GraphFeatureCopyWith<$Res> {
 | 
				
			||||||
 | 
					  _$GraphFeatureCopyWithImpl(this._value, this._then);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // ignore: unused_field
 | 
				
			||||||
 | 
					  final $Val _value;
 | 
				
			||||||
 | 
					  // ignore: unused_field
 | 
				
			||||||
 | 
					  final $Res Function($Val) _then;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// @nodoc
 | 
				
			||||||
 | 
					abstract class _$$BuildingFloorImplCopyWith<$Res> {
 | 
				
			||||||
 | 
					  factory _$$BuildingFloorImplCopyWith(
 | 
				
			||||||
 | 
					          _$BuildingFloorImpl value, $Res Function(_$BuildingFloorImpl) then) =
 | 
				
			||||||
 | 
					      __$$BuildingFloorImplCopyWithImpl<$Res>;
 | 
				
			||||||
 | 
					  @useResult
 | 
				
			||||||
 | 
					  $Res call({int floor, Feature building});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $FeatureCopyWith<$Res> get building;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// @nodoc
 | 
				
			||||||
 | 
					class __$$BuildingFloorImplCopyWithImpl<$Res>
 | 
				
			||||||
 | 
					    extends _$GraphFeatureCopyWithImpl<$Res, _$BuildingFloorImpl>
 | 
				
			||||||
 | 
					    implements _$$BuildingFloorImplCopyWith<$Res> {
 | 
				
			||||||
 | 
					  __$$BuildingFloorImplCopyWithImpl(
 | 
				
			||||||
 | 
					      _$BuildingFloorImpl _value, $Res Function(_$BuildingFloorImpl) _then)
 | 
				
			||||||
 | 
					      : super(_value, _then);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @pragma('vm:prefer-inline')
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  $Res call({
 | 
				
			||||||
 | 
					    Object? floor = null,
 | 
				
			||||||
 | 
					    Object? building = null,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return _then(_$BuildingFloorImpl(
 | 
				
			||||||
 | 
					      null == floor
 | 
				
			||||||
 | 
					          ? _value.floor
 | 
				
			||||||
 | 
					          : floor // ignore: cast_nullable_to_non_nullable
 | 
				
			||||||
 | 
					              as int,
 | 
				
			||||||
 | 
					      null == building
 | 
				
			||||||
 | 
					          ? _value.building
 | 
				
			||||||
 | 
					          : building // ignore: cast_nullable_to_non_nullable
 | 
				
			||||||
 | 
					              as Feature,
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @pragma('vm:prefer-inline')
 | 
				
			||||||
 | 
					  $FeatureCopyWith<$Res> get building {
 | 
				
			||||||
 | 
					    return $FeatureCopyWith<$Res>(_value.building, (value) {
 | 
				
			||||||
 | 
					      return _then(_value.copyWith(building: value));
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// @nodoc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _$BuildingFloorImpl extends BuildingFloor {
 | 
				
			||||||
 | 
					  const _$BuildingFloorImpl(this.floor, this.building) : super._();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  final int floor;
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  final Feature building;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    return 'GraphFeature.buildingFloor(floor: $floor, building: $building)';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  bool operator ==(Object other) {
 | 
				
			||||||
 | 
					    return identical(this, other) ||
 | 
				
			||||||
 | 
					        (other.runtimeType == runtimeType &&
 | 
				
			||||||
 | 
					            other is _$BuildingFloorImpl &&
 | 
				
			||||||
 | 
					            (identical(other.floor, floor) || other.floor == floor) &&
 | 
				
			||||||
 | 
					            (identical(other.building, building) ||
 | 
				
			||||||
 | 
					                other.building == building));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  int get hashCode => Object.hash(runtimeType, floor, building);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @JsonKey(ignore: true)
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @pragma('vm:prefer-inline')
 | 
				
			||||||
 | 
					  _$$BuildingFloorImplCopyWith<_$BuildingFloorImpl> get copyWith =>
 | 
				
			||||||
 | 
					      __$$BuildingFloorImplCopyWithImpl<_$BuildingFloorImpl>(this, _$identity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult when<TResult extends Object?>({
 | 
				
			||||||
 | 
					    required TResult Function(int floor, Feature building) buildingFloor,
 | 
				
			||||||
 | 
					    required TResult Function(int fromFloor, String from, int toFloor,
 | 
				
			||||||
 | 
					            String to, Feature baseFeature)
 | 
				
			||||||
 | 
					        portal,
 | 
				
			||||||
 | 
					    required TResult Function(int floor, String building, Feature feature)
 | 
				
			||||||
 | 
					        basicFeature,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return buildingFloor(floor, building);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult? whenOrNull<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult? Function(int floor, Feature building)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult? Function(int fromFloor, String from, int toFloor, String to,
 | 
				
			||||||
 | 
					            Feature baseFeature)?
 | 
				
			||||||
 | 
					        portal,
 | 
				
			||||||
 | 
					    TResult? Function(int floor, String building, Feature feature)?
 | 
				
			||||||
 | 
					        basicFeature,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return buildingFloor?.call(floor, building);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult maybeWhen<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult Function(int floor, Feature building)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult Function(int fromFloor, String from, int toFloor, String to,
 | 
				
			||||||
 | 
					            Feature baseFeature)?
 | 
				
			||||||
 | 
					        portal,
 | 
				
			||||||
 | 
					    TResult Function(int floor, String building, Feature feature)? basicFeature,
 | 
				
			||||||
 | 
					    required TResult orElse(),
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    if (buildingFloor != null) {
 | 
				
			||||||
 | 
					      return buildingFloor(floor, building);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return orElse();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult map<TResult extends Object?>({
 | 
				
			||||||
 | 
					    required TResult Function(BuildingFloor value) buildingFloor,
 | 
				
			||||||
 | 
					    required TResult Function(Portal value) portal,
 | 
				
			||||||
 | 
					    required TResult Function(BasicFeature value) basicFeature,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return buildingFloor(this);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult? mapOrNull<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult? Function(BuildingFloor value)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult? Function(Portal value)? portal,
 | 
				
			||||||
 | 
					    TResult? Function(BasicFeature value)? basicFeature,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return buildingFloor?.call(this);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult maybeMap<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult Function(BuildingFloor value)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult Function(Portal value)? portal,
 | 
				
			||||||
 | 
					    TResult Function(BasicFeature value)? basicFeature,
 | 
				
			||||||
 | 
					    required TResult orElse(),
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    if (buildingFloor != null) {
 | 
				
			||||||
 | 
					      return buildingFloor(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return orElse();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class BuildingFloor extends GraphFeature {
 | 
				
			||||||
 | 
					  const factory BuildingFloor(final int floor, final Feature building) =
 | 
				
			||||||
 | 
					      _$BuildingFloorImpl;
 | 
				
			||||||
 | 
					  const BuildingFloor._() : super._();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int get floor;
 | 
				
			||||||
 | 
					  Feature get building;
 | 
				
			||||||
 | 
					  @JsonKey(ignore: true)
 | 
				
			||||||
 | 
					  _$$BuildingFloorImplCopyWith<_$BuildingFloorImpl> get copyWith =>
 | 
				
			||||||
 | 
					      throw _privateConstructorUsedError;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// @nodoc
 | 
				
			||||||
 | 
					abstract class _$$PortalImplCopyWith<$Res> {
 | 
				
			||||||
 | 
					  factory _$$PortalImplCopyWith(
 | 
				
			||||||
 | 
					          _$PortalImpl value, $Res Function(_$PortalImpl) then) =
 | 
				
			||||||
 | 
					      __$$PortalImplCopyWithImpl<$Res>;
 | 
				
			||||||
 | 
					  @useResult
 | 
				
			||||||
 | 
					  $Res call(
 | 
				
			||||||
 | 
					      {int fromFloor,
 | 
				
			||||||
 | 
					      String from,
 | 
				
			||||||
 | 
					      int toFloor,
 | 
				
			||||||
 | 
					      String to,
 | 
				
			||||||
 | 
					      Feature baseFeature});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $FeatureCopyWith<$Res> get baseFeature;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// @nodoc
 | 
				
			||||||
 | 
					class __$$PortalImplCopyWithImpl<$Res>
 | 
				
			||||||
 | 
					    extends _$GraphFeatureCopyWithImpl<$Res, _$PortalImpl>
 | 
				
			||||||
 | 
					    implements _$$PortalImplCopyWith<$Res> {
 | 
				
			||||||
 | 
					  __$$PortalImplCopyWithImpl(
 | 
				
			||||||
 | 
					      _$PortalImpl _value, $Res Function(_$PortalImpl) _then)
 | 
				
			||||||
 | 
					      : super(_value, _then);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @pragma('vm:prefer-inline')
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  $Res call({
 | 
				
			||||||
 | 
					    Object? fromFloor = null,
 | 
				
			||||||
 | 
					    Object? from = null,
 | 
				
			||||||
 | 
					    Object? toFloor = null,
 | 
				
			||||||
 | 
					    Object? to = null,
 | 
				
			||||||
 | 
					    Object? baseFeature = null,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return _then(_$PortalImpl(
 | 
				
			||||||
 | 
					      null == fromFloor
 | 
				
			||||||
 | 
					          ? _value.fromFloor
 | 
				
			||||||
 | 
					          : fromFloor // ignore: cast_nullable_to_non_nullable
 | 
				
			||||||
 | 
					              as int,
 | 
				
			||||||
 | 
					      null == from
 | 
				
			||||||
 | 
					          ? _value.from
 | 
				
			||||||
 | 
					          : from // ignore: cast_nullable_to_non_nullable
 | 
				
			||||||
 | 
					              as String,
 | 
				
			||||||
 | 
					      null == toFloor
 | 
				
			||||||
 | 
					          ? _value.toFloor
 | 
				
			||||||
 | 
					          : toFloor // ignore: cast_nullable_to_non_nullable
 | 
				
			||||||
 | 
					              as int,
 | 
				
			||||||
 | 
					      null == to
 | 
				
			||||||
 | 
					          ? _value.to
 | 
				
			||||||
 | 
					          : to // ignore: cast_nullable_to_non_nullable
 | 
				
			||||||
 | 
					              as String,
 | 
				
			||||||
 | 
					      null == baseFeature
 | 
				
			||||||
 | 
					          ? _value.baseFeature
 | 
				
			||||||
 | 
					          : baseFeature // ignore: cast_nullable_to_non_nullable
 | 
				
			||||||
 | 
					              as Feature,
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @pragma('vm:prefer-inline')
 | 
				
			||||||
 | 
					  $FeatureCopyWith<$Res> get baseFeature {
 | 
				
			||||||
 | 
					    return $FeatureCopyWith<$Res>(_value.baseFeature, (value) {
 | 
				
			||||||
 | 
					      return _then(_value.copyWith(baseFeature: value));
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// @nodoc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _$PortalImpl extends Portal {
 | 
				
			||||||
 | 
					  const _$PortalImpl(
 | 
				
			||||||
 | 
					      this.fromFloor, this.from, this.toFloor, this.to, this.baseFeature)
 | 
				
			||||||
 | 
					      : super._();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  final int fromFloor;
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  final String from;
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  final int toFloor;
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  final String to;
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  final Feature baseFeature;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    return 'GraphFeature.portal(fromFloor: $fromFloor, from: $from, toFloor: $toFloor, to: $to, baseFeature: $baseFeature)';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  bool operator ==(Object other) {
 | 
				
			||||||
 | 
					    return identical(this, other) ||
 | 
				
			||||||
 | 
					        (other.runtimeType == runtimeType &&
 | 
				
			||||||
 | 
					            other is _$PortalImpl &&
 | 
				
			||||||
 | 
					            (identical(other.fromFloor, fromFloor) ||
 | 
				
			||||||
 | 
					                other.fromFloor == fromFloor) &&
 | 
				
			||||||
 | 
					            (identical(other.from, from) || other.from == from) &&
 | 
				
			||||||
 | 
					            (identical(other.toFloor, toFloor) || other.toFloor == toFloor) &&
 | 
				
			||||||
 | 
					            (identical(other.to, to) || other.to == to) &&
 | 
				
			||||||
 | 
					            (identical(other.baseFeature, baseFeature) ||
 | 
				
			||||||
 | 
					                other.baseFeature == baseFeature));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  int get hashCode =>
 | 
				
			||||||
 | 
					      Object.hash(runtimeType, fromFloor, from, toFloor, to, baseFeature);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @JsonKey(ignore: true)
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @pragma('vm:prefer-inline')
 | 
				
			||||||
 | 
					  _$$PortalImplCopyWith<_$PortalImpl> get copyWith =>
 | 
				
			||||||
 | 
					      __$$PortalImplCopyWithImpl<_$PortalImpl>(this, _$identity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult when<TResult extends Object?>({
 | 
				
			||||||
 | 
					    required TResult Function(int floor, Feature building) buildingFloor,
 | 
				
			||||||
 | 
					    required TResult Function(int fromFloor, String from, int toFloor,
 | 
				
			||||||
 | 
					            String to, Feature baseFeature)
 | 
				
			||||||
 | 
					        portal,
 | 
				
			||||||
 | 
					    required TResult Function(int floor, String building, Feature feature)
 | 
				
			||||||
 | 
					        basicFeature,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return portal(fromFloor, from, toFloor, to, baseFeature);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult? whenOrNull<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult? Function(int floor, Feature building)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult? Function(int fromFloor, String from, int toFloor, String to,
 | 
				
			||||||
 | 
					            Feature baseFeature)?
 | 
				
			||||||
 | 
					        portal,
 | 
				
			||||||
 | 
					    TResult? Function(int floor, String building, Feature feature)?
 | 
				
			||||||
 | 
					        basicFeature,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return portal?.call(fromFloor, from, toFloor, to, baseFeature);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult maybeWhen<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult Function(int floor, Feature building)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult Function(int fromFloor, String from, int toFloor, String to,
 | 
				
			||||||
 | 
					            Feature baseFeature)?
 | 
				
			||||||
 | 
					        portal,
 | 
				
			||||||
 | 
					    TResult Function(int floor, String building, Feature feature)? basicFeature,
 | 
				
			||||||
 | 
					    required TResult orElse(),
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    if (portal != null) {
 | 
				
			||||||
 | 
					      return portal(fromFloor, from, toFloor, to, baseFeature);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return orElse();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult map<TResult extends Object?>({
 | 
				
			||||||
 | 
					    required TResult Function(BuildingFloor value) buildingFloor,
 | 
				
			||||||
 | 
					    required TResult Function(Portal value) portal,
 | 
				
			||||||
 | 
					    required TResult Function(BasicFeature value) basicFeature,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return portal(this);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult? mapOrNull<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult? Function(BuildingFloor value)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult? Function(Portal value)? portal,
 | 
				
			||||||
 | 
					    TResult? Function(BasicFeature value)? basicFeature,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return portal?.call(this);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult maybeMap<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult Function(BuildingFloor value)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult Function(Portal value)? portal,
 | 
				
			||||||
 | 
					    TResult Function(BasicFeature value)? basicFeature,
 | 
				
			||||||
 | 
					    required TResult orElse(),
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    if (portal != null) {
 | 
				
			||||||
 | 
					      return portal(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return orElse();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class Portal extends GraphFeature {
 | 
				
			||||||
 | 
					  const factory Portal(
 | 
				
			||||||
 | 
					      final int fromFloor,
 | 
				
			||||||
 | 
					      final String from,
 | 
				
			||||||
 | 
					      final int toFloor,
 | 
				
			||||||
 | 
					      final String to,
 | 
				
			||||||
 | 
					      final Feature baseFeature) = _$PortalImpl;
 | 
				
			||||||
 | 
					  const Portal._() : super._();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int get fromFloor;
 | 
				
			||||||
 | 
					  String get from;
 | 
				
			||||||
 | 
					  int get toFloor;
 | 
				
			||||||
 | 
					  String get to;
 | 
				
			||||||
 | 
					  Feature get baseFeature;
 | 
				
			||||||
 | 
					  @JsonKey(ignore: true)
 | 
				
			||||||
 | 
					  _$$PortalImplCopyWith<_$PortalImpl> get copyWith =>
 | 
				
			||||||
 | 
					      throw _privateConstructorUsedError;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// @nodoc
 | 
				
			||||||
 | 
					abstract class _$$BasicFeatureImplCopyWith<$Res> {
 | 
				
			||||||
 | 
					  factory _$$BasicFeatureImplCopyWith(
 | 
				
			||||||
 | 
					          _$BasicFeatureImpl value, $Res Function(_$BasicFeatureImpl) then) =
 | 
				
			||||||
 | 
					      __$$BasicFeatureImplCopyWithImpl<$Res>;
 | 
				
			||||||
 | 
					  @useResult
 | 
				
			||||||
 | 
					  $Res call({int floor, String building, Feature feature});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $FeatureCopyWith<$Res> get feature;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// @nodoc
 | 
				
			||||||
 | 
					class __$$BasicFeatureImplCopyWithImpl<$Res>
 | 
				
			||||||
 | 
					    extends _$GraphFeatureCopyWithImpl<$Res, _$BasicFeatureImpl>
 | 
				
			||||||
 | 
					    implements _$$BasicFeatureImplCopyWith<$Res> {
 | 
				
			||||||
 | 
					  __$$BasicFeatureImplCopyWithImpl(
 | 
				
			||||||
 | 
					      _$BasicFeatureImpl _value, $Res Function(_$BasicFeatureImpl) _then)
 | 
				
			||||||
 | 
					      : super(_value, _then);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @pragma('vm:prefer-inline')
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  $Res call({
 | 
				
			||||||
 | 
					    Object? floor = null,
 | 
				
			||||||
 | 
					    Object? building = null,
 | 
				
			||||||
 | 
					    Object? feature = null,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return _then(_$BasicFeatureImpl(
 | 
				
			||||||
 | 
					      null == floor
 | 
				
			||||||
 | 
					          ? _value.floor
 | 
				
			||||||
 | 
					          : floor // ignore: cast_nullable_to_non_nullable
 | 
				
			||||||
 | 
					              as int,
 | 
				
			||||||
 | 
					      null == building
 | 
				
			||||||
 | 
					          ? _value.building
 | 
				
			||||||
 | 
					          : building // ignore: cast_nullable_to_non_nullable
 | 
				
			||||||
 | 
					              as String,
 | 
				
			||||||
 | 
					      null == feature
 | 
				
			||||||
 | 
					          ? _value.feature
 | 
				
			||||||
 | 
					          : feature // ignore: cast_nullable_to_non_nullable
 | 
				
			||||||
 | 
					              as Feature,
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @pragma('vm:prefer-inline')
 | 
				
			||||||
 | 
					  $FeatureCopyWith<$Res> get feature {
 | 
				
			||||||
 | 
					    return $FeatureCopyWith<$Res>(_value.feature, (value) {
 | 
				
			||||||
 | 
					      return _then(_value.copyWith(feature: value));
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// @nodoc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _$BasicFeatureImpl extends BasicFeature {
 | 
				
			||||||
 | 
					  const _$BasicFeatureImpl(this.floor, this.building, this.feature) : super._();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  final int floor;
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  final String building;
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  final Feature feature;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    return 'GraphFeature.basicFeature(floor: $floor, building: $building, feature: $feature)';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  bool operator ==(Object other) {
 | 
				
			||||||
 | 
					    return identical(this, other) ||
 | 
				
			||||||
 | 
					        (other.runtimeType == runtimeType &&
 | 
				
			||||||
 | 
					            other is _$BasicFeatureImpl &&
 | 
				
			||||||
 | 
					            (identical(other.floor, floor) || other.floor == floor) &&
 | 
				
			||||||
 | 
					            (identical(other.building, building) ||
 | 
				
			||||||
 | 
					                other.building == building) &&
 | 
				
			||||||
 | 
					            (identical(other.feature, feature) || other.feature == feature));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  int get hashCode => Object.hash(runtimeType, floor, building, feature);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @JsonKey(ignore: true)
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @pragma('vm:prefer-inline')
 | 
				
			||||||
 | 
					  _$$BasicFeatureImplCopyWith<_$BasicFeatureImpl> get copyWith =>
 | 
				
			||||||
 | 
					      __$$BasicFeatureImplCopyWithImpl<_$BasicFeatureImpl>(this, _$identity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult when<TResult extends Object?>({
 | 
				
			||||||
 | 
					    required TResult Function(int floor, Feature building) buildingFloor,
 | 
				
			||||||
 | 
					    required TResult Function(int fromFloor, String from, int toFloor,
 | 
				
			||||||
 | 
					            String to, Feature baseFeature)
 | 
				
			||||||
 | 
					        portal,
 | 
				
			||||||
 | 
					    required TResult Function(int floor, String building, Feature feature)
 | 
				
			||||||
 | 
					        basicFeature,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return basicFeature(floor, building, feature);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult? whenOrNull<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult? Function(int floor, Feature building)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult? Function(int fromFloor, String from, int toFloor, String to,
 | 
				
			||||||
 | 
					            Feature baseFeature)?
 | 
				
			||||||
 | 
					        portal,
 | 
				
			||||||
 | 
					    TResult? Function(int floor, String building, Feature feature)?
 | 
				
			||||||
 | 
					        basicFeature,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return basicFeature?.call(floor, building, feature);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult maybeWhen<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult Function(int floor, Feature building)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult Function(int fromFloor, String from, int toFloor, String to,
 | 
				
			||||||
 | 
					            Feature baseFeature)?
 | 
				
			||||||
 | 
					        portal,
 | 
				
			||||||
 | 
					    TResult Function(int floor, String building, Feature feature)? basicFeature,
 | 
				
			||||||
 | 
					    required TResult orElse(),
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    if (basicFeature != null) {
 | 
				
			||||||
 | 
					      return basicFeature(floor, building, feature);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return orElse();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult map<TResult extends Object?>({
 | 
				
			||||||
 | 
					    required TResult Function(BuildingFloor value) buildingFloor,
 | 
				
			||||||
 | 
					    required TResult Function(Portal value) portal,
 | 
				
			||||||
 | 
					    required TResult Function(BasicFeature value) basicFeature,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return basicFeature(this);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult? mapOrNull<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult? Function(BuildingFloor value)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult? Function(Portal value)? portal,
 | 
				
			||||||
 | 
					    TResult? Function(BasicFeature value)? basicFeature,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    return basicFeature?.call(this);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  @optionalTypeArgs
 | 
				
			||||||
 | 
					  TResult maybeMap<TResult extends Object?>({
 | 
				
			||||||
 | 
					    TResult Function(BuildingFloor value)? buildingFloor,
 | 
				
			||||||
 | 
					    TResult Function(Portal value)? portal,
 | 
				
			||||||
 | 
					    TResult Function(BasicFeature value)? basicFeature,
 | 
				
			||||||
 | 
					    required TResult orElse(),
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    if (basicFeature != null) {
 | 
				
			||||||
 | 
					      return basicFeature(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return orElse();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class BasicFeature extends GraphFeature {
 | 
				
			||||||
 | 
					  const factory BasicFeature(
 | 
				
			||||||
 | 
					          final int floor, final String building, final Feature feature) =
 | 
				
			||||||
 | 
					      _$BasicFeatureImpl;
 | 
				
			||||||
 | 
					  const BasicFeature._() : super._();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int get floor;
 | 
				
			||||||
 | 
					  String get building;
 | 
				
			||||||
 | 
					  Feature get feature;
 | 
				
			||||||
 | 
					  @JsonKey(ignore: true)
 | 
				
			||||||
 | 
					  _$$BasicFeatureImplCopyWith<_$BasicFeatureImpl> get copyWith =>
 | 
				
			||||||
 | 
					      throw _privateConstructorUsedError;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,21 +0,0 @@
 | 
				
			|||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:uninav/components/drawer.dart';
 | 
					 | 
				
			||||||
import 'package:uninav/components/hamburger_menu.dart';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class SettingsPage extends StatelessWidget {
 | 
					 | 
				
			||||||
  const SettingsPage({super.key});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override
 | 
					 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					 | 
				
			||||||
    return Scaffold(
 | 
					 | 
				
			||||||
      appBar: AppBar(
 | 
					 | 
				
			||||||
        title: const Text('Settings'),
 | 
					 | 
				
			||||||
        leading: HamburgerMenu(),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      drawer: MyDrawer(),
 | 
					 | 
				
			||||||
      body: const Center(
 | 
					 | 
				
			||||||
        child: Text('TODO'),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										54
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								pubspec.lock
									
									
									
									
									
								
							@ -154,7 +154,7 @@ packages:
 | 
				
			|||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "4.10.0"
 | 
					    version: "4.10.0"
 | 
				
			||||||
  collection:
 | 
					  collection:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: "direct main"
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: collection
 | 
					      name: collection
 | 
				
			||||||
      sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
 | 
					      sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
 | 
				
			||||||
@ -185,14 +185,6 @@ packages:
 | 
				
			|||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "1.0.8"
 | 
					    version: "1.0.8"
 | 
				
			||||||
  dart_earcut:
 | 
					 | 
				
			||||||
    dependency: transitive
 | 
					 | 
				
			||||||
    description:
 | 
					 | 
				
			||||||
      name: dart_earcut
 | 
					 | 
				
			||||||
      sha256: "41b493147e30a051efb2da1e3acb7f38fe0db60afba24ac1ea5684cee272721e"
 | 
					 | 
				
			||||||
      url: "https://pub.dev"
 | 
					 | 
				
			||||||
    source: hosted
 | 
					 | 
				
			||||||
    version: "1.1.0"
 | 
					 | 
				
			||||||
  dart_style:
 | 
					  dart_style:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
@ -209,6 +201,22 @@ packages:
 | 
				
			|||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "1.2.0"
 | 
					    version: "1.2.0"
 | 
				
			||||||
 | 
					  directed_graph:
 | 
				
			||||||
 | 
					    dependency: "direct main"
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: directed_graph
 | 
				
			||||||
 | 
					      sha256: fcb45029b4a5089d383b79056b6716d6bf5af79b8e7dbac4b61d26af46410548
 | 
				
			||||||
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "0.4.3"
 | 
				
			||||||
 | 
					  exception_templates:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: exception_templates
 | 
				
			||||||
 | 
					      sha256: "517f7c770da690073663f867ee2057ae2f4ffb28edae9da9faa624aa29ac76eb"
 | 
				
			||||||
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "0.3.1"
 | 
				
			||||||
  fake_async:
 | 
					  fake_async:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
@ -217,6 +225,14 @@ packages:
 | 
				
			|||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "1.3.1"
 | 
					    version: "1.3.1"
 | 
				
			||||||
 | 
					  fast_immutable_collections:
 | 
				
			||||||
 | 
					    dependency: "direct main"
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: fast_immutable_collections
 | 
				
			||||||
 | 
					      sha256: "38fbc50df5b219dcfb83ebbc3275ec09872530ca1153858fc56fceadb310d037"
 | 
				
			||||||
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "10.2.2"
 | 
				
			||||||
  ffi:
 | 
					  ffi:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
@ -258,10 +274,10 @@ packages:
 | 
				
			|||||||
    dependency: "direct main"
 | 
					    dependency: "direct main"
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: flutter_map
 | 
					      name: flutter_map
 | 
				
			||||||
      sha256: bee8c5bacb49a68aabcf6009c050a8b3b07ac75403f29f741d8c00d4a725e086
 | 
					      sha256: cda8d72135b697f519287258b5294a57ce2f2a5ebf234f0e406aad4dc14c9399
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "7.0.0-dev.1"
 | 
					    version: "6.1.0"
 | 
				
			||||||
  flutter_test:
 | 
					  flutter_test:
 | 
				
			||||||
    dependency: "direct dev"
 | 
					    dependency: "direct dev"
 | 
				
			||||||
    description: flutter
 | 
					    description: flutter
 | 
				
			||||||
@ -424,6 +440,14 @@ packages:
 | 
				
			|||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "0.9.1"
 | 
					    version: "0.9.1"
 | 
				
			||||||
 | 
					  lazy_memo:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: lazy_memo
 | 
				
			||||||
 | 
					      sha256: dcb30b4184a6d767e1d779d74ce784d752d38313b8fb4bad6b659ae7af4bb34d
 | 
				
			||||||
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "0.2.3"
 | 
				
			||||||
  leak_tracker:
 | 
					  leak_tracker:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
@ -640,6 +664,14 @@ packages:
 | 
				
			|||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "1.2.3"
 | 
					    version: "1.2.3"
 | 
				
			||||||
 | 
					  quote_buffer:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: quote_buffer
 | 
				
			||||||
 | 
					      sha256: c4cd07e55ed1b1645a1cc74278a03b2a642c9f6ea3c0528d51827fdd320acf87
 | 
				
			||||||
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "0.2.6"
 | 
				
			||||||
  rust_core:
 | 
					  rust_core:
 | 
				
			||||||
    dependency: "direct main"
 | 
					    dependency: "direct main"
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
 | 
				
			|||||||
@ -39,7 +39,8 @@ dependencies:
 | 
				
			|||||||
  yaml: ^3.1.2
 | 
					  yaml: ^3.1.2
 | 
				
			||||||
  surrealdb: ^0.8.0
 | 
					  surrealdb: ^0.8.0
 | 
				
			||||||
  # geojson: ^1.0.0
 | 
					  # geojson: ^1.0.0
 | 
				
			||||||
  flutter_map: 7.0.0-dev.1
 | 
					  # flutter_map: 7.0.0-dev.1
 | 
				
			||||||
 | 
					  flutter_map: ^6.0.0
 | 
				
			||||||
  # flutter_map: ^4.0.0
 | 
					  # flutter_map: ^4.0.0
 | 
				
			||||||
  latlong2: ^0.9.0
 | 
					  latlong2: ^0.9.0
 | 
				
			||||||
  # latlong2: ^0.8.0
 | 
					  # latlong2: ^0.8.0
 | 
				
			||||||
@ -53,6 +54,9 @@ dependencies:
 | 
				
			|||||||
  isar: ^3.1.0+1
 | 
					  isar: ^3.1.0+1
 | 
				
			||||||
  isar_flutter_libs: ^3.1.0+1
 | 
					  isar_flutter_libs: ^3.1.0+1
 | 
				
			||||||
  path_provider: ^2.1.3
 | 
					  path_provider: ^2.1.3
 | 
				
			||||||
 | 
					  directed_graph: ^0.4.3
 | 
				
			||||||
 | 
					  fast_immutable_collections: ^10.2.2
 | 
				
			||||||
 | 
					  collection: ^1.18.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dev_dependencies:
 | 
					dev_dependencies:
 | 
				
			||||||
  flutter_test:
 | 
					  flutter_test:
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										176
									
								
								test/graph_tests.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								test/graph_tests.dart
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,176 @@
 | 
				
			|||||||
 | 
					import 'dart:async';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/services.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_test/flutter_test.dart';
 | 
				
			||||||
 | 
					import 'package:get/get.dart';
 | 
				
			||||||
 | 
					import 'package:uninav/controllers/map_controller.dart';
 | 
				
			||||||
 | 
					import 'package:uninav/data/geo/model.dart';
 | 
				
			||||||
 | 
					import 'package:uninav/nav/graph.dart';
 | 
				
			||||||
 | 
					import 'package:uninav/util/util.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String formatGraphFeature(GraphFeature feature) {
 | 
				
			||||||
 | 
					  return feature.when(
 | 
				
			||||||
 | 
					    buildingFloor: (floor, building) => "(bfl ${building.name}:$floor)",
 | 
				
			||||||
 | 
					    portal: (fromFloor, from, toFloor, to, baseFeat) {
 | 
				
			||||||
 | 
					      return "(p ${formatFeatureTitle(baseFeat)} $from:$fromFloor -> $to:$toFloor)";
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    basicFeature: (lv, building, bf) =>
 | 
				
			||||||
 | 
					        "(bf ${formatFeatureTitle(bf)} $building:$lv)",
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
					  TestWidgetsFlutterBinding.ensureInitialized();
 | 
				
			||||||
 | 
					  group('findAdjacent', () {
 | 
				
			||||||
 | 
					    late MyMapController mapController;
 | 
				
			||||||
 | 
					    late List<Feature> allFeatures;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setUp(() async {
 | 
				
			||||||
 | 
					      // Initialize the MyMapController and load the GeoJSON data
 | 
				
			||||||
 | 
					      mapController = MyMapController();
 | 
				
			||||||
 | 
					      await mapController.loadGeoJson(
 | 
				
			||||||
 | 
					          await rootBundle.loadString('assets/geo/uulm_beta.geojson'));
 | 
				
			||||||
 | 
					      allFeatures = mapController.features;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test('generates a graph', () {
 | 
				
			||||||
 | 
					      // Find a building feature
 | 
				
			||||||
 | 
					      // final buildingFeature = allFeatures.firstWhere((f) => f.type is Building);
 | 
				
			||||||
 | 
					      final buildingFeature = allFeatures
 | 
				
			||||||
 | 
					          .firstWhere((f) => f.type is Building && eq(f.name, 'o28'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final graph = createGraph(
 | 
				
			||||||
 | 
					          wrap(buildingFeature, 2, buildingFeature.name).first, allFeatures);
 | 
				
			||||||
 | 
					      // print(graph);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test('generates a graph map', () {
 | 
				
			||||||
 | 
					      // Find a building feature
 | 
				
			||||||
 | 
					      // final buildingFeature = allFeatures.firstWhere((f) => f.type is Building);
 | 
				
			||||||
 | 
					      final buildingFeature = allFeatures
 | 
				
			||||||
 | 
					          .firstWhere((f) => f.type is Building && eq(f.name, 'o28'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final graph = createGraphMap(
 | 
				
			||||||
 | 
					          wrap(buildingFeature, 2, buildingFeature.name).first, allFeatures);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      print(graph.entries
 | 
				
			||||||
 | 
					          .map((entry) => "${formatGraphFeature(entry.key)}: "
 | 
				
			||||||
 | 
					              "{${entry.value.entries.map((e) => "${formatGraphFeature(entry.key)}: ${entry.value.map((key, value) => MapEntry(formatGraphFeature(key), value))}").join(', ')}")
 | 
				
			||||||
 | 
					          .join('\n'));
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test('generates a graph list', () {
 | 
				
			||||||
 | 
					      // Find a building feature
 | 
				
			||||||
 | 
					      // final buildingFeature = allFeatures.firstWhere((f) => f.type is Building);
 | 
				
			||||||
 | 
					      final buildingFeature = allFeatures
 | 
				
			||||||
 | 
					          .firstWhere((f) => f.type is Building && eq(f.name, 'o28'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final graph = createGraphList(
 | 
				
			||||||
 | 
					          wrap(buildingFeature, 2, buildingFeature.name).first, allFeatures);
 | 
				
			||||||
 | 
					      var text = graph.map(formatGraphFeature).join(' ');
 | 
				
			||||||
 | 
					      print(text);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test('finds adjacent features for a building', () {
 | 
				
			||||||
 | 
					      // Find a building feature
 | 
				
			||||||
 | 
					      // final buildingFeature = allFeatures.firstWhere((f) => f.type is Building);
 | 
				
			||||||
 | 
					      final buildingFeature = allFeatures
 | 
				
			||||||
 | 
					          .firstWhere((f) => f.type is Building && eq(f.name, 'o28'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Find adjacent features for the building
 | 
				
			||||||
 | 
					      final adjacentFeatures = findAdjacent(
 | 
				
			||||||
 | 
					          wrap(buildingFeature, 2, buildingFeature.name).first, allFeatures);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final doorPortal = adjacentFeatures
 | 
				
			||||||
 | 
					          .firstWhere((f) => f is Portal && f.baseFeature.type is Door);
 | 
				
			||||||
 | 
					      print(
 | 
				
			||||||
 | 
					          "adjacent for building ${buildingFeature.name}: \n${adjacentFeatures.map((e) => "${e.toString()}\n")}");
 | 
				
			||||||
 | 
					      print(adjacentFeatures.map(unwrap).map(formatFeatureTitle));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final doorAdjacentFeatures = findAdjacent(doorPortal, allFeatures);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      print("\n\ndoor $doorPortal : ");
 | 
				
			||||||
 | 
					      print(doorAdjacentFeatures.map((e) => "${e.toString()}\n"));
 | 
				
			||||||
 | 
					      print(doorAdjacentFeatures.map(unwrap).map(formatFeatureTitle));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final stairsPortal = adjacentFeatures
 | 
				
			||||||
 | 
					          .firstWhere((f) => f is Portal && f.baseFeature.type is Stairs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final stairsAdjacentFeatures = findAdjacent(stairsPortal, allFeatures);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      print("\n\nstairs $stairsPortal : ");
 | 
				
			||||||
 | 
					      print(stairsAdjacentFeatures.map((e) => "${e.toString()}\n"));
 | 
				
			||||||
 | 
					      print(stairsAdjacentFeatures.map(unwrap).map(formatFeatureTitle));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final baseFeature = adjacentFeatures.firstWhere((f) => f is BasicFeature);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final baseAdjacentFeatures = findAdjacent(baseFeature, allFeatures);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      print("\n\nbase $baseFeature : ");
 | 
				
			||||||
 | 
					      print(baseAdjacentFeatures.map((e) => "${e.toString()}\n"));
 | 
				
			||||||
 | 
					      print(baseAdjacentFeatures.map(unwrap).map(formatFeatureTitle));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Check if all adjacent features are in the same building
 | 
				
			||||||
 | 
					      expect(
 | 
				
			||||||
 | 
					          true, // TODO
 | 
				
			||||||
 | 
					          true);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test('tries to find a path through the graph using own method', () async {
 | 
				
			||||||
 | 
					      // Find a building feature
 | 
				
			||||||
 | 
					      // final buildingFeature = allFeatures.firstWhere((f) => f.type is Building);
 | 
				
			||||||
 | 
					      final startFeature = allFeatures
 | 
				
			||||||
 | 
					          .firstWhere((f) => f.type is Building && eq(f.name, 'o28'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // final endFeature = allFeatures
 | 
				
			||||||
 | 
					      //     .firstWhere((f) => f.type is Building && eq(f.name, 'o25'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final endFeature = allFeatures
 | 
				
			||||||
 | 
					          .firstWhere((f) => f.type is LectureHall && eq(f.name, 'H1'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      print(endFeature);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final path = findShortestPath(
 | 
				
			||||||
 | 
					        wrap(startFeature, 2, startFeature.name).first,
 | 
				
			||||||
 | 
					        // wrap(endFeature, 2, endFeature.name).first,
 | 
				
			||||||
 | 
					        wrap(endFeature, endFeature.level!, endFeature.building!).first,
 | 
				
			||||||
 | 
					        allFeatures,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      print(path
 | 
				
			||||||
 | 
					          .unwrap()
 | 
				
			||||||
 | 
					          .map((e) => "${formatGraphFeature(e.$1)} (${e.$2}m)")
 | 
				
			||||||
 | 
					          .join(' -> '));
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					    test('tries to find a path through the graph', () async {
 | 
				
			||||||
 | 
					      // Find a building feature
 | 
				
			||||||
 | 
					      // final buildingFeature = allFeatures.firstWhere((f) => f.type is Building);
 | 
				
			||||||
 | 
					      final startFeature = allFeatures
 | 
				
			||||||
 | 
					          .firstWhere((f) => f.type is Building && eq(f.name, 'o28'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final endFeature = allFeatures
 | 
				
			||||||
 | 
					          .firstWhere((f) => f.type is Building && eq(f.name, 'o25'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // final endFeature = allFeatures
 | 
				
			||||||
 | 
					      //     .firstWhere((f) => f.type is LectureHall && eq(f.name, 'H1'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final graph = createGraph(
 | 
				
			||||||
 | 
					          wrap(startFeature, 2, startFeature.name).first, allFeatures);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      final path = await Future.any([
 | 
				
			||||||
 | 
					        Future.delayed(const Duration(seconds: 5),
 | 
				
			||||||
 | 
					            () => throw TimeoutException('Test timed out after 5 seconds')),
 | 
				
			||||||
 | 
					        Future(() => graph.shortestPath(
 | 
				
			||||||
 | 
					              wrap(startFeature, 1, startFeature.name).first,
 | 
				
			||||||
 | 
					              wrap(endFeature, 2, endFeature.name).first,
 | 
				
			||||||
 | 
					              //wrap(endFeature, endFeature.level!, endFeature.building!).first,
 | 
				
			||||||
 | 
					            )),
 | 
				
			||||||
 | 
					      ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      print(path.map(formatGraphFeature).join('\n'));
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user