wip: support saferide shuttle
This commit is contained in:
		
							
								
								
									
										61
									
								
								lib/src/services/transportation/route.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								lib/src/services/transportation/route.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					import 'dart:ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_map/flutter_map.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/widgets/map/route_marker.dart';
 | 
				
			||||||
 | 
					import 'package:latlong2/latlong.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TransportationRoute {
 | 
				
			||||||
 | 
					  final Polyline route;
 | 
				
			||||||
 | 
					  final List<Stop> stops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  TransportationRoute({
 | 
				
			||||||
 | 
					    required this.route,
 | 
				
			||||||
 | 
					    required this.stops,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  factory TransportationRoute.fromPoints({
 | 
				
			||||||
 | 
					    required List<LatLng> points,
 | 
				
			||||||
 | 
					    required Color color,
 | 
				
			||||||
 | 
					    required List<Stop> stops,
 | 
				
			||||||
 | 
					  }) {
 | 
				
			||||||
 | 
					    var route = Polyline(
 | 
				
			||||||
 | 
					      points: points,
 | 
				
			||||||
 | 
					      color: color,
 | 
				
			||||||
 | 
					      strokeWidth: 4,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    return TransportationRoute(
 | 
				
			||||||
 | 
					      route: route,
 | 
				
			||||||
 | 
					      stops: stops,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Stop {
 | 
				
			||||||
 | 
					  int id;
 | 
				
			||||||
 | 
					  String name;
 | 
				
			||||||
 | 
					  LatLng location;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Stop({
 | 
				
			||||||
 | 
					    required this.id,
 | 
				
			||||||
 | 
					    required this.name,
 | 
				
			||||||
 | 
					    required this.location,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  factory Stop.fromLiveSafeJson(Map<String, dynamic> json) {
 | 
				
			||||||
 | 
					    return Stop(
 | 
				
			||||||
 | 
					      id: json["AddressID"],
 | 
				
			||||||
 | 
					      name: json["Description"],
 | 
				
			||||||
 | 
					      location: LatLng(json["Latitude"], json["Longitude"]),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Marker toMarker({required Color color}) {
 | 
				
			||||||
 | 
					    return Marker(
 | 
				
			||||||
 | 
					      point: location,
 | 
				
			||||||
 | 
					      height: 100,
 | 
				
			||||||
 | 
					      width: 100,
 | 
				
			||||||
 | 
					      builder: (context) => RouteMarker(color: color),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,3 +1,48 @@
 | 
				
			|||||||
class TransportationSafeRideShuttleService {
 | 
					import 'dart:convert';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/utils/decode_polyline.dart';
 | 
				
			||||||
 | 
					import 'package:http/http.dart' as http;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'route.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TransportationSafeRideShuttleService {
 | 
				
			||||||
 | 
					  static const service =
 | 
				
			||||||
 | 
					      "https://furmansaferide.ridesystems.net/Services/JSONPRelay.svc";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static const apiKey = "8882812681";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static Future<http.Response> _serviceRequest(
 | 
				
			||||||
 | 
					      String endpoint, Map<String, dynamic>? queryParameters) async {
 | 
				
			||||||
 | 
					    Uri serviceUri = Uri.https(
 | 
				
			||||||
 | 
					        'furmansaferide.ridesystems.net',
 | 
				
			||||||
 | 
					        "/Services/JSONPRelay.svc/$endpoint",
 | 
				
			||||||
 | 
					        {...?queryParameters, 'apiKey': apiKey});
 | 
				
			||||||
 | 
					    return http.get(serviceUri);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static Future<TransportationRoute> fetchShuttleRoute() async {
 | 
				
			||||||
 | 
					    final response = await _serviceRequest(
 | 
				
			||||||
 | 
					        'GetRoutesForMapWithScheduleWithEncodedLine', {'isDispatch': 'false'});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (response.statusCode == 200) {
 | 
				
			||||||
 | 
					      // If the server did return a 200 OK response,
 | 
				
			||||||
 | 
					      // then parse the JSON.
 | 
				
			||||||
 | 
					      final json = jsonDecode(response.body);
 | 
				
			||||||
 | 
					      String encodedPolyline = json[0]["EncodedPolyline"];
 | 
				
			||||||
 | 
					      final points = decodeEncodedPolyline(encodedPolyline);
 | 
				
			||||||
 | 
					      var stops = (json[0]["Stops"] as List<dynamic>)
 | 
				
			||||||
 | 
					          .map((e) => Stop.fromLiveSafeJson(e))
 | 
				
			||||||
 | 
					          .toList();
 | 
				
			||||||
 | 
					      return TransportationRoute.fromPoints(
 | 
				
			||||||
 | 
					        points: points,
 | 
				
			||||||
 | 
					        color: Colors.red.shade300,
 | 
				
			||||||
 | 
					        stops: stops,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      // If the server did not return a 200 OK response,
 | 
				
			||||||
 | 
					      // then throw an exception.
 | 
				
			||||||
 | 
					      throw Exception('Failed to load SafeRide shuttle route.');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								lib/src/services/transportation/vehicle.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								lib/src/services/transportation/vehicle.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class TransportationVehicle {
 | 
				
			||||||
 | 
					  // name of the vehicle
 | 
				
			||||||
 | 
					  String get name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // is the vehicle currently running?
 | 
				
			||||||
 | 
					  VehicleStatus get status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // name of vehicle's next stop
 | 
				
			||||||
 | 
					  String get nextStop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // vehicle icon
 | 
				
			||||||
 | 
					  IconData get icon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // vehicle route
 | 
				
			||||||
 | 
					  TransitionRoute get route;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum VehicleStatus { running, stopped }
 | 
				
			||||||
							
								
								
									
										34
									
								
								lib/src/utils/decode_polyline.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								lib/src/utils/decode_polyline.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					import 'package:latlong2/latlong.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Decodes the an encoded polyline using the Encoded Polyline Algorithm Format
 | 
				
			||||||
 | 
					/// for more info about the algorithm check
 | 
				
			||||||
 | 
					/// https://developers.google.com/maps/documentation/utilities/polylinealgorithm
 | 
				
			||||||
 | 
					List<LatLng> decodeEncodedPolyline(String encoded) {
 | 
				
			||||||
 | 
					  List<LatLng> poly = [];
 | 
				
			||||||
 | 
					  int index = 0, len = encoded.length;
 | 
				
			||||||
 | 
					  int lat = 0, lng = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (index < len) {
 | 
				
			||||||
 | 
					    int b, shift = 0, result = 0;
 | 
				
			||||||
 | 
					    do {
 | 
				
			||||||
 | 
					      b = encoded.codeUnitAt(index++) - 63;
 | 
				
			||||||
 | 
					      result |= (b & 0x1f) << shift;
 | 
				
			||||||
 | 
					      shift += 5;
 | 
				
			||||||
 | 
					    } while (b >= 0x20);
 | 
				
			||||||
 | 
					    int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
 | 
				
			||||||
 | 
					    lat += dlat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    shift = 0;
 | 
				
			||||||
 | 
					    result = 0;
 | 
				
			||||||
 | 
					    do {
 | 
				
			||||||
 | 
					      b = encoded.codeUnitAt(index++) - 63;
 | 
				
			||||||
 | 
					      result |= (b & 0x1f) << shift;
 | 
				
			||||||
 | 
					      shift += 5;
 | 
				
			||||||
 | 
					    } while (b >= 0x20);
 | 
				
			||||||
 | 
					    int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
 | 
				
			||||||
 | 
					    lng += dlng;
 | 
				
			||||||
 | 
					    LatLng p = LatLng((lat / 1E5).toDouble(), (lng / 1E5).toDouble());
 | 
				
			||||||
 | 
					    poly.add(p);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return poly;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										22
									
								
								test/service_tests/transportation/saferide_shuttle_test.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								test/service_tests/transportation/saferide_shuttle_test.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					import "package:furman_now/src/services/transportation/saferide_shuttle.dart";
 | 
				
			||||||
 | 
					import "package:test/test.dart";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
					  test("shuttle status is fetched successfully", () async {
 | 
				
			||||||
 | 
					    var route = await TransportationSafeRideShuttleService.fetchShuttleRoute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ensure polyline has points
 | 
				
			||||||
 | 
					    expect(route.route.points.length, isNonZero);
 | 
				
			||||||
 | 
					    // ensure stops are listed
 | 
				
			||||||
 | 
					    expect(route.stops.length, isNonZero);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  test("shuttle route is fetched successfully", () async {
 | 
				
			||||||
 | 
					    var route = await TransportationSafeRideShuttleService.fetchShuttleRoute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ensure polyline has points
 | 
				
			||||||
 | 
					    expect(route.route.points.length, isNonZero);
 | 
				
			||||||
 | 
					    // ensure stops are listed
 | 
				
			||||||
 | 
					    expect(route.stops.length, isNonZero);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user