Compare commits
3 Commits
3f0342b6cb
...
main
Author | SHA1 | Date | |
---|---|---|---|
54cfe936c3 | |||
2a780f13c7 | |||
7b6a276c21 |
@@ -14,8 +14,9 @@ PODS:
|
|||||||
- geolocator_apple (1.2.0):
|
- geolocator_apple (1.2.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- OrderedSet (5.0.0)
|
- OrderedSet (5.0.0)
|
||||||
- path_provider_ios (0.0.1):
|
- path_provider_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
- url_launcher_ios (0.0.1):
|
- url_launcher_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ DEPENDENCIES:
|
|||||||
- flutter_compass (from `.symlinks/plugins/flutter_compass/ios`)
|
- flutter_compass (from `.symlinks/plugins/flutter_compass/ios`)
|
||||||
- flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`)
|
- flutter_inappwebview (from `.symlinks/plugins/flutter_inappwebview/ios`)
|
||||||
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/ios`)
|
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/ios`)
|
||||||
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
@@ -43,8 +44,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/flutter_inappwebview/ios"
|
:path: ".symlinks/plugins/flutter_inappwebview/ios"
|
||||||
geolocator_apple:
|
geolocator_apple:
|
||||||
:path: ".symlinks/plugins/geolocator_apple/ios"
|
:path: ".symlinks/plugins/geolocator_apple/ios"
|
||||||
path_provider_ios:
|
path_provider_foundation:
|
||||||
:path: ".symlinks/plugins/path_provider_ios/ios"
|
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
|
|
||||||
@@ -55,9 +56,9 @@ SPEC CHECKSUMS:
|
|||||||
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
|
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
|
||||||
geolocator_apple: cc556e6844d508c95df1e87e3ea6fa4e58c50401
|
geolocator_apple: cc556e6844d508c95df1e87e3ea6fa4e58c50401
|
||||||
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
||||||
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
|
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||||
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
|
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
||||||
|
|
||||||
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
|
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
|
||||||
|
|
||||||
COCOAPODS: 1.11.3
|
COCOAPODS: 1.12.1
|
||||||
|
@@ -156,7 +156,7 @@
|
|||||||
97C146E61CF9000F007C117D /* Project object */ = {
|
97C146E61CF9000F007C117D /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 1300;
|
LastUpgradeCheck = 1430;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
97C146ED1CF9000F007C117D = {
|
97C146ED1CF9000F007C117D = {
|
||||||
@@ -205,6 +205,7 @@
|
|||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
|
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||||
);
|
);
|
||||||
name = "Thin Binary";
|
name = "Thin Binary";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1300"
|
LastUpgradeVersion = "1430"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
@@ -122,7 +122,10 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
alignment: Alignment.bottomCenter,
|
alignment: Alignment.bottomCenter,
|
||||||
child: Container(
|
child: Container(
|
||||||
height: overscrollBottomAmount + 30,
|
height: overscrollBottomAmount + 30,
|
||||||
color: Colors.grey.shade50,
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey.shade50,
|
||||||
|
border: Border.all(width: 0, color: Colors.white),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Consumer<HomePageState>(
|
Consumer<HomePageState>(
|
||||||
|
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;
|
||||||
|
}
|
472
pubspec.lock
472
pubspec.lock
File diff suppressed because it is too large
Load Diff
@@ -35,7 +35,7 @@ dependencies:
|
|||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
english_words: ^4.0.0
|
english_words: ^4.0.0
|
||||||
intl: ^0.17.0
|
intl: ^0.17.0
|
||||||
google_fonts: ^3.0.1
|
google_fonts: ^4.0.4
|
||||||
http: ^0.13.5
|
http: ^0.13.5
|
||||||
convert: ^3.0.2
|
convert: ^3.0.2
|
||||||
crypto: ^3.0.2
|
crypto: ^3.0.2
|
||||||
|
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