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