/* * Copyright (c) 2016 Washington State Department of Transportation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> * */ package gov.wa.wsdot.mobile.client.activities.amtrakcascades.schedules; import com.google.gwt.event.shared.EventBus; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.user.client.ui.AcceptsOneWidget; import com.googlecode.gwtphonegap.client.PhoneGap; import com.googlecode.gwtphonegap.client.geolocation.GeolocationCallback; import com.googlecode.gwtphonegap.client.geolocation.Position; import com.googlecode.gwtphonegap.client.geolocation.PositionError; import com.googlecode.gwtphonegap.client.notification.AlertCallback; import com.googlecode.mgwt.mvp.client.MGWTAbstractActivity; import gov.wa.wsdot.mobile.client.ClientFactory; import gov.wa.wsdot.mobile.client.activities.amtrakcascades.schedules.details.AmtrakCascadesSchedulesDetailsPlace; import gov.wa.wsdot.mobile.client.event.ActionEvent; import gov.wa.wsdot.mobile.client.event.ActionNames; import gov.wa.wsdot.mobile.client.plugins.accessibility.Accessibility; import gov.wa.wsdot.mobile.client.plugins.analytics.Analytics; import gov.wa.wsdot.mobile.client.util.Consts; import gov.wa.wsdot.mobile.shared.AmtrakCascadesStationItem; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; public class AmtrakCascadesSchedulesActivity extends MGWTAbstractActivity implements AmtrakCascadesSchedulesView.Presenter { private ClientFactory clientFactory; private AmtrakCascadesSchedulesView view; private EventBus eventBus; private PhoneGap phoneGap; private Analytics analytics; private List<AmtrakCascadesStationItem> amtrakStationItems = new ArrayList<AmtrakCascadesStationItem>(); private DateTimeFormat dateFormat = DateTimeFormat.getFormat("MMMM d, yyyy h:mm a"); private Accessibility accessibility; public AmtrakCascadesSchedulesActivity(ClientFactory clientFactory) { this.clientFactory = clientFactory; } @Override public void start(AcceptsOneWidget panel, final EventBus eventBus) { view = clientFactory.getAmtrakCascadesSchedulesView(); this.eventBus = eventBus; phoneGap = clientFactory.getPhoneGap(); analytics = clientFactory.getAnalytics(); accessibility = clientFactory.getAccessibility(); view.setPresenter(this); view.showProgressIndicator(); getDaysOfWeek(); getAmtrakStations(); getCurrentLocation(); if (Consts.ANALYTICS_ENABLED) { analytics.trackScreen("/Amtrak Cascades/Schedules"); } panel.setWidget(view); accessibility.postScreenChangeNotification(); } private void getDaysOfWeek() { List<String> daysOfWeek = new ArrayList<String>(); Date startDate = new Date(); for (int i = 0; i < 7; i++) { Date nextDay = new Date(startDate.getTime() + i * 24 * 3600 * 1000); daysOfWeek.add(dateFormat.format(nextDay)); } view.renderDaysOfWeek(daysOfWeek); } private void getAmtrakStations() { amtrakStationItems.add(new AmtrakCascadesStationItem("VAC", "Vancouver, BC", 1, 49.2737293, -123.0979175)); amtrakStationItems.add(new AmtrakCascadesStationItem("BEL", "Bellingham, WA", 2, 48.720423, -122.5109386)); amtrakStationItems.add(new AmtrakCascadesStationItem("MVW", "Mount Vernon, WA", 3, 48.4185923, -122.334973)); amtrakStationItems.add(new AmtrakCascadesStationItem("STW", "Stanwood, WA", 4, 48.2417732, -122.3495322)); amtrakStationItems.add(new AmtrakCascadesStationItem("EVR", "Everett, WA", 5, 47.975512, -122.197854)); amtrakStationItems.add(new AmtrakCascadesStationItem("EDM", "Edmonds, WA", 6, 47.8111305, -122.3841639)); amtrakStationItems.add(new AmtrakCascadesStationItem("SEA", "Seattle, WA", 7, 47.6001899, -122.3314322)); amtrakStationItems.add(new AmtrakCascadesStationItem("TUK", "Tukwila, WA", 8, 47.461079, -122.242693)); amtrakStationItems.add(new AmtrakCascadesStationItem("TAC", "Tacoma, WA", 9, 47.2419939, -122.4205623)); amtrakStationItems.add(new AmtrakCascadesStationItem("OLW", "Olympia/Lacey, WA", 10, 46.9913576, -122.793982)); amtrakStationItems.add(new AmtrakCascadesStationItem("CTL", "Centralia, WA", 11, 46.7177596, -122.9528291)); amtrakStationItems.add(new AmtrakCascadesStationItem("KEL", "Kelso/Longview, WA", 12, 46.1422504, -122.9132438)); amtrakStationItems.add(new AmtrakCascadesStationItem("VAN", "Vancouver, WA", 13, 45.6294472, -122.685568)); amtrakStationItems.add(new AmtrakCascadesStationItem("PDX", "Portland, OR", 14, 45.528639, -122.676284)); amtrakStationItems.add(new AmtrakCascadesStationItem("ORC", "Oregon City, OR", 15, 45.3659422, -122.5960671)); amtrakStationItems.add(new AmtrakCascadesStationItem("SLM", "Salem, OR", 16, 44.9323665, -123.0281591)); amtrakStationItems.add(new AmtrakCascadesStationItem("ALY", "Albany, OR", 17, 44.6300975, -123.1041787)); amtrakStationItems.add(new AmtrakCascadesStationItem("EUG", "Eugene, OR", 18, 44.055506, -123.094523)); Collections.sort(amtrakStationItems, AmtrakCascadesStationItem.stationNameComparator); } private void getCurrentLocation() { phoneGap.getGeolocation().getCurrentPosition(new GeolocationCallback() { @Override public void onSuccess(Position position) { double latitude = position.getCoordinates().getLatitude(); double longitude = position.getCoordinates().getLongitude(); getDistanceFromStation(latitude, longitude); view.hideProgressIndicator(); accessibility.postScreenChangeNotification(); } @Override public void onFailure(PositionError error) { switch (error.getCode()) { case PositionError.PERMISSION_DENIED: phoneGap.getNotification() .alert("You can turn Location Services on at Settings > Privacy > Location Services.", new AlertCallback() { @Override public void onOkButtonClicked() { // TODO Auto-generated method stub } }, "Location Services Off"); view.renderFromLocation(amtrakStationItems); view.renderToLocation(amtrakStationItems); view.hideProgressIndicator(); break; default: view.renderFromLocation(amtrakStationItems); view.renderToLocation(amtrakStationItems); view.hideProgressIndicator(); break; } } }); } /** * Haversine formula * * Provides great-circle distances between two points on a sphere from their longitudes and latitudes * * http://en.wikipedia.org/wiki/Haversine_formula * * @param latitude * @param longitude */ protected void getDistanceFromStation(double latitude, double longitude) { for (AmtrakCascadesStationItem station: amtrakStationItems) { double earthRadius = 3958.75; // miles double dLat = Math.toRadians(station.getLatitude() - latitude); double dLng = Math.toRadians(station.getLongitude() - longitude); double sindLat = Math.sin(dLat / 2); double sindLng = Math.sin(dLng / 2); double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2) * Math.cos(Math.toRadians(latitude)) * Math.cos(Math.toRadians(station.getLatitude())); double c = 2 * Math.asin(Math.sqrt(a)); int distance = (int) Math.round(earthRadius * c); station.setDistance(distance); } view.setLocationEnabled(true); view.renderFromLocation(amtrakStationItems); view.renderToLocation(amtrakStationItems); } @Override public void onStop() { view.setPresenter(null); } @Override public void onBackButtonPressed() { ActionEvent.fire(eventBus, ActionNames.BACK); } @Override public void onSubmitButtonPressed() { String statusDate = view.getDayOfWeekSelected(); String fromLocation = view.getFromLocationSelected(); String toLocation = view.getToLocationSelected(); if (fromLocation.equalsIgnoreCase("NA")) { phoneGap.getNotification().alert( "Please select a point of origin from the selection box.", new AlertCallback() { @Override public void onOkButtonClicked() { // TODO Auto-generated method stub } }, "Point of origin needed"); } else if (toLocation.equalsIgnoreCase("NA") || fromLocation.equalsIgnoreCase(toLocation)) { // User selected no destination or user picked the same destination as the origin. Just ignore it. toLocation = "NA"; if (Consts.ANALYTICS_ENABLED) { analytics.trackEvent("Amtrak", "Schedules", fromLocation); } clientFactory.getPlaceController().goTo( new AmtrakCascadesSchedulesDetailsPlace(statusDate, fromLocation, toLocation)); } else { if (Consts.ANALYTICS_ENABLED) { analytics.trackEvent("Amtrak", "Schedules", fromLocation + " - " + toLocation); } clientFactory.getPlaceController().goTo( new AmtrakCascadesSchedulesDetailsPlace(statusDate, fromLocation, toLocation)); } } }