Commit e743561c authored by Sharp Hall's avatar Sharp Hall

Encapsulate app logic in react

parent 5a497ca7
......@@ -6,6 +6,6 @@
<script src="bundle.js"></script>
</head>
<body>
<div id="routelist"></div>
<div id="app"></div>
</body>
</html>
......@@ -15,12 +15,6 @@ var STOP_DISTANCE_THRESHOLD = 0.2;
var septaRoutes = {};
var septaStops = {routes: {}, stops: []};
var nearbyStops = [];
var selectedRoutes = [];
var flatDistanceSorted = [];
var currentLocation = null;
function milesFromObj(ref, septaObj) {
return haversine(ref, {latitude: parseFloat(septaObj.lat),
......@@ -29,99 +23,116 @@ function milesFromObj(ref, septaObj) {
}
function markRoutes(routes) {
_.forEach(routes, function(value, key) {
_.forEach(value, function(route) {
route.route = key;
});
_.forEach(routes, (value, key) => {
_.forEach(value, (route) => { route.route = key; });
});
return routes;
}
$(function () {
ReactDOM.render(<WhereSepta />,
document.getElementById('app'));
});
var refreshDisplay = _.debounce(function () {
if (currentLocation === null) {
ReactDOM.render(<LocationSharingNotice />,
document.getElementById('routelist'));
return;
class WhereSepta extends React.Component {
constructor(props) {
super(props);
this.state = {
routeInfo: {},
stops: [],
vehicles: {},
location: null
};
}
var here = point([currentLocation.longitude, currentLocation.latitude]);
// find close stops
nearbyStops = _.filter(
_.map(septaStops.stops, function (stop) {
stop.distance = haversine(currentLocation, {latitude: stop.y,
longitude: stop.x});
return stop;
}), function (stop) {
return stop.distance < STOP_DISTANCE_THRESHOLD;
}
);
selectedRoutes = _.uniq(_.flatten(_.map(nearbyStops, stops => { return stops.r; })));
pullNewData() {
if (document.visibilityState == "visible") {
$.ajax({
url: "https://www3.septa.org/hackathon/TransitViewAll/",
jsonp: "callback",
dataType: "jsonp",
success: (newData) => {
this.setState({
vehicles: markRoutes(newData.routes[0])
});
}
});
}
}
// update distance in septa route objects according to currentLocation
_.forEach(septaRoutes, function(route) {
_.forEach(route, function(vehicle) {
vehicle.distance = milesFromObj(currentLocation, vehicle);
var p = point([parseFloat(vehicle.lng), parseFloat(vehicle.lat)]);
vehicle.bearing = bearing(p, here, {final: true});
vehicle.alignment = (vehicle.heading - vehicle.bearing + 360) % 360;
if (vehicle.distance < NEAR_THRESHOLD) {
vehicle.coming = vehicle.alignment < COMING_ANGLE || vehicle.alignment > 360 - COMING_ANGLE;
vehicle.going = vehicle.alignment > 180 - COMING_ANGLE && vehicle.alignment < 180 + COMING_ANGLE;
} else {
vehicle.coming = vehicle.alignment < 90 || vehicle.alignment > 270;
vehicle.going = !vehicle.coming;
componentDidMount() {
$.ajax({
url: "stops.json",
success: (stopData) => {
this.setState({
routeInfo: stopData.routes,
stops: stopData.stops
});
}
});
});
flatDistanceSorted = _.sortBy(_.filter(_.flatten(_.values(septaRoutes)), v => { return selectedRoutes.includes(v.route) || selectedRoutes === []; }),
function (vehicle) {
return vehicle.distance;
});
flatDistanceSorted = _.filter(flatDistanceSorted, (vehicle) => {
if (vehicle.distance > DISTANCE_THRESHOLD) {
return false;
}
if (vehicle.distance < NEAR_THRESHOLD) {
return true;
this.pullNewData();
this.updateTimer = setInterval(() => this.pullNewData(), 15 * 1000);
this.geolocationWatch = navigator.geolocation.watchPosition((position) => this.setState({
location: {latitude: position.coords.latitude, longitude: position.coords.longitude}
})
);
}
componentWillUnmount() {
clearInterval(this.updateTimer);
navigator.geolocation.clearWatch(this.geolocationWatch);
}
render() {
var location = this.state.location;
if (location === null) {
return(<LocationSharingNotice />);
}
return vehicle.coming;
});
ReactDOM.render(<VehicleList vehicleList={flatDistanceSorted} routeList={selectedRoutes} />,
document.getElementById('routelist'));
}, 500);
var here = point([location.longitude, location.latitude]);
// find close stops
var nearbyStops = _.filter(
_.map(this.state.stops, (stop) => {
stop.distance = haversine(location, {latitude: stop.y,
longitude: stop.x});
return stop;
}), (stop) => {
return stop.distance < STOP_DISTANCE_THRESHOLD;
}
);
function getSeptaTransitView() {
if (document.visibilityState == "visible") {
$.ajax({
url: "https://www3.septa.org/hackathon/TransitViewAll/",
jsonp: "callback",
dataType: "jsonp",
success: function (newData) {
septaRoutes = markRoutes(newData.routes[0]);
refreshDisplay();
var selectedRoutes = _.uniq(_.flatten(_.map(nearbyStops, stops => { return stops.r; })));
// update distance in septa route objects according to location
_.forEach(this.state.vehicles, (route) => {
_.forEach(route, (vehicle) => {
vehicle.distance = milesFromObj(location, vehicle);
var p = point([parseFloat(vehicle.lng), parseFloat(vehicle.lat)]);
vehicle.bearing = bearing(p, here, {final: true});
vehicle.alignment = (vehicle.heading - vehicle.bearing + 360) % 360;
if (vehicle.distance < NEAR_THRESHOLD) {
vehicle.coming = vehicle.alignment < COMING_ANGLE || vehicle.alignment > 360 - COMING_ANGLE;
vehicle.going = vehicle.alignment > 180 - COMING_ANGLE && vehicle.alignment < 180 + COMING_ANGLE;
} else {
vehicle.coming = vehicle.alignment < 90 || vehicle.alignment > 270;
vehicle.going = !vehicle.coming;
}
});
});
var flatDistanceSorted = _.sortBy(_.filter(_.flatten(_.values(this.state.vehicles)), v => { return selectedRoutes.includes(v.route) || selectedRoutes === []; }),
(vehicle) => { return vehicle.distance; });
flatDistanceSorted = _.filter(flatDistanceSorted, (vehicle) => {
if (vehicle.distance > DISTANCE_THRESHOLD) {
return false;
}
if (vehicle.distance < NEAR_THRESHOLD) {
return true;
}
return vehicle.coming;
});
return(<VehicleList vehicleList={flatDistanceSorted} routeList={selectedRoutes} />);
}
}
$(function () {
getSeptaTransitView();
setInterval(getSeptaTransitView, 15 * 1000);
$.ajax({
url: "stops.json",
success: function (stopData) {
septaStops = stopData;
refreshDisplay();
}
});
navigator.geolocation.watchPosition(function(position) {
currentLocation = {latitude: position.coords.latitude, longitude: position.coords.longitude};
refreshDisplay();
});
refreshDisplay();
});
class Vehicle extends React.Component {
static NICE_DIRECTIONS = {
'NorthBound': 'going north',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment