Skip to content

Commit

Permalink
Geocoding error handling, modify new trips
Browse files Browse the repository at this point in the history
  • Loading branch information
tanykim committed May 23, 2016
1 parent 39e6658 commit e4a8e49
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 90 deletions.
89 changes: 53 additions & 36 deletions client/scripts/controllers/trips.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ angular.module('365daysApp').controller('TripsCtrl', [
}

//find traveled places
//$scope.error = null;
$scope.loaded = false;
var tracedTrips = analyzer.getTracedTrips();
$scope.selected = _.map(_.range(tracedTrips.length), function (i) {
Expand All @@ -30,28 +31,38 @@ angular.module('365daysApp').controller('TripsCtrl', [
//transform TracedTrip with the location name (city, country) acquired from the API on the server side
//then process with Analyzer to merge trips and get round trips
var locations = [];
var singleTrips = _.map(angular.copy(tracedTrips), function (d) {
$scope.tripList = [];
var tripsWithName = _.map(angular.copy(tracedTrips), function (d) {
return {
date: moment(d.date, 'YYYYMMDD'),
timestamp: { from: d.from.timestamp, to: d.to.timestamp },
name: {},
offset: { from: null, to: null }
};
});
socket.emit('trips', tracedTrips);
socket.on('location', function (location) {
locations.push(location);
if (locations.length === tracedTrips.length * 2) {
_.each(locations, function (d) {
singleTrips[d.id].name[d.type] = d.name;
if (d.timezone.status === 'OK') {
singleTrips[d.id].offset[d.type] = d.timezone.rawOffset;
}
});
$scope.tripList = analyzer.getRoundTrips(singleTrips);
$scope.loaded = true;
}
});
if (!_.isEmpty(tracedTrips)) {
socket.emit('trips', tracedTrips);
socket.on('location', function (location) {
locations.push(location);
if (location.error) {
$scope.error = location.error;
$scope.loaded = true;
}
else if (locations.length === tracedTrips.length * 2) {
_.each(locations, function (d) {
tripsWithName[d.id].name[d.type] = d.name;
if (d.timezone.status === 'OK') {
tripsWithName[d.id].offset[d.type] = d.timezone.rawOffset;
}
});
$scope.tripList = analyzer.getRoundTrips(tripsWithName);
$scope.loaded = true;
}
});
} else {
$scope.error = "No trips are found";
$scope.loaded = true;
}

//remove trip
$scope.removeTrip = function (index) {
Expand All @@ -75,57 +86,63 @@ angular.module('365daysApp').controller('TripsCtrl', [
var dateRange = analyzer.getDateRanges();
$scope.minDate = dateRange.startDate;
$scope.maxDate = dateRange.endDate;
$scope.datePicker = {
opened: false
};
$scope.open = function() {
$scope.datePicker.opened = true;
$scope.datePicker = [{ opened: false }, { opened: false }];
$scope.open = function(index) {
$scope.datePicker[index].opened = true;
};
$scope.addedTripDates = [$scope.minDate, $scope.minDate.clone().add(7, 'days')];
$scope.setTripDate = function (e, index) {
console.log(index);
$scope.addedTripDates[index] = moment(new Date(e.dt));
};

//add trip
var newLocation = { destination: null, startDate: null, endDate: null };
$scope.searchTripGeocoding = function() {
console.log($scope.newTrip.typed);
//valid input
if ($scope.newTrip.typed) {
newLocation = { destination: null };
socket.emit('newTrip', $scope.newTrip.typed);
//no sever error previously
if (!$scope.error) {
newLocation = { destination: null };
socket.emit('newTrip', $scope.newTrip.typed);
} else {
$scope.addTrip(false);
}
}
};
$scope.newTrip = { searched: false, newName: {} };
$scope.newTrip = { searched: false, newName: null };
socket.on('newTripLocation', function (loc) {

newLocation.destination = loc.name;
//change to new suggested name
if (newLocation.name) {
console.log(newLocation);
if (!loc.error) {
//change to new suggested name
newLocation.destination = loc.name;
$scope.newTrip.searched = true;
$scope.newTrip.newName = newLocation.destination;
} else {
$scope.addTrip(false);
}
});
//add the new location to trip list
$scope.addTrip = function (useNewName) {
console.log(useNewName);
newLocation.startDate = addedTripDates[0];
newLocation.endDate = addedTripDates[1];
newLocation.startDate = $scope.addedTripDates[0];
newLocation.endDate = $scope.addedTripDates[1];
//TODO: add offsetDiff in the new trip
newLocation.offsetDiff = '';
var newTripIndex = 0;
for (var i = 0; i < $scope.tripList.length; i++ ) {
if ($scope.tripList[i].startDate.diff(anewLocation.endDate, 'days') >= 0) {
newTripIndex = i;
break;
for (var i = 0; i < $scope.tripList.length; i++) {
if ($scope.tripList[i].startDate.diff(newLocation.endDate, 'days') <= 0) {
newTripIndex = i + 1;
}
}

//use typed name
if (!useNewName) {
newLocation.destination = $scope.newTrip.typed;
}
$scope.tripList.splice(newTripIndex, 0, newLocation);
$scope.selected.splice(newTripIndex, 0, true);

//TODO: disable dates on and before the start date

//reset
$scope.newTrip = { searched: false, newName: null };
newLocation = { destination: null };
Expand Down
20 changes: 12 additions & 8 deletions client/scripts/services/analyzer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ angular.module('365daysApp').factory('analyzer', [
var originalDuplicates = [];

//trip
var tracedTrips;
var userSetTrips;
var tracedTrips = [];
var userSetTrips = [];

function getDuration(st, et, currentDate) {

Expand Down Expand Up @@ -336,12 +336,16 @@ angular.module('365daysApp').factory('analyzer', [
return roundTrips;
};
this.setUserSelectedTrips = function (tripList) {
userSetTrips = _.map(angular.copy(tripList), function (trip) {
return {
dateIndex: toDayIndex(trip.date.format('YYYYMMDD')),
itinerary: trip.name
};
});
if (!_.isEmpty(tripList)) {
userSetTrips = _.map(angular.copy(tripList), function (trip) {
return {
startDateId: toDayIndex(trip.startDate.format('YYYYMMDD')),
endDateId: toDayIndex(trip.endDate.format('YYYYMMDD')),
destination: trip.destination,
offsetDiff: trip.offsetDiff
};
});
}
};

/***
Expand Down
53 changes: 35 additions & 18 deletions client/scripts/services/visualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,31 +122,48 @@ angular.module('365daysApp').factory('visualizer', [

function drawTrips(g, trip, startDate, dayUnit) {

var x1, x2, y1, y2;
var x1s, x2s, x1e, x2e, y1s, y2s, y1e, y2e, tx, ty;
if (options.orientation === 'landscape') {
x1 = dayUnit * trip.dateIndex;
x2 = dayUnit * trip.dateIndex;
y1 = dim.h;
y2 = dim.h + margin.gap;
x1s = dayUnit * trip.startDateId;
x2s = dayUnit * trip.startDateId;
x1e = dayUnit * trip.endDateId;
x2e = dayUnit * trip.endDateId;
y1s = dim.h;
y2s = dim.h + margin.gap;
y1e = dim.h;
y2e = dim.h + margin.gap;
tx = (x1s + x1e) / 2;
ty = dim.h + margin.gap;
} else {
x1 = dim.w;
x2 = dim.w + margin.gap;
y1 = dayUnit * trip.dateIndex;
y2 = dayUnit * trip.dateIndex;
x1s = dim.w;
x2s = dim.w + margin.gap;
x1e = dim.w;
x2e = dim.w + margin.gap;
y1s = dayUnit * trip.startDateId;
y2s = dayUnit * trip.startDateId;
y1e = dayUnit * trip.endDateId;
y2e = dayUnit * trip.endDateId;
tx = dim.w;
ty = (y1s + y1e) / 2
}
var currentDate = startDate.clone().add(trip.dateIndex, 'days');

//TODO: tailor the poisition depending on departure/arrival
//TODO: CSS for position
g.append('line')
.attr('x1', x1s)
.attr('x2', x2s)
.attr('y1', y1s)
.attr('y2', y2s)
.attr('class', 'stroke-1 stroke-black');
g.append('line')
.attr('x1', x1)
.attr('x2', x2)
.attr('y1', y1)
.attr('y2', y2)
.attr('x1', x1e)
.attr('x2', x2e)
.attr('y1', y1e)
.attr('y2', y2e)
.attr('class', 'stroke-1 stroke-black');
g.append('text')
.attr('x', x1)
.attr('y', y1)
.text(trip.itinerary.from + ' >> ' + trip.itinerary.to)
.attr('x', tx)
.attr('y', ty)
.text(trip.destination)
.attr('class', 'size-small fill-black');
}

Expand Down
24 changes: 8 additions & 16 deletions client/views/trips.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
<h2> Add Trips </h2>
Let us know if you had any trips with time-zone change. Here are our suggestions.
<div ng-if="!loaded">
Analyzing your trips
<h3>Analyzing your trips...</h3>
</div>
<div ng-if="loaded">
<div ng-if="loaded && error">
<h3>{{ error }} <br/> Please enter your trips manually.</h3>
<div ng-if="loaded && tripList.length > 0">
<table>
<tr class="trip-list">
<th> Select </th>
Expand Down Expand Up @@ -42,29 +44,19 @@ <h2> Add Trips </h2>
</div>

<!-- Add a trip -->
<div><a ng-click="isAddOpen = !isAddOpen">Add a trip</a></div>
<div><a ng-click="isAddOpen = !isAddOpen"><h3>Add a trip</h3></a></div>
<div ng-show="isAddOpen">
<p class="input-group" ng-repeat="date in ['Depatrue', 'Return'] track by $index">
<span>{{ date }} :</span>
<input type="text" class="form-control" uib-datepicker-popup="MMMM dd, yyyy" ng-model="dt" show-weeks="false" placeholder="{{ addedTripDates[$index] | amDateFormat: 'MMMM DD, YYYY' }}" is-open="datePicker.opened" min-date="minDate" max-date="maxDate" init-date="addedTripDates[$index]" ng-required="true" show-button-bar="false" ng-change="setTripDate(this, $index)">
<input type="text" class="form-control" uib-datepicker-popup="MMMM dd, yyyy" ng-model="dt" show-weeks="false" placeholder="{{ addedTripDates[$index] | amDateFormat: 'MMMM DD, YYYY' }}" is-open="datePicker[$index].opened" min-date="minDate" max-date="maxDate" init-date="addedTripDates[$index]" ng-required="true" show-button-bar="false" ng-change="setTripDate(this, $index)">
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open()"><i class="glyphicon glyphicon-calendar"></i></button>
<button type="button" class="btn btn-default" ng-click="open($index)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
<!-- <p class="input-group">
Return:
<input type="text" class="form-control" uib-datepicker-popup="MMMM dd, yyyy" ng-model="dt" show-weeks="false" placeholder="{{ minDate | amDateFormat: 'MMMM DD, YYYY' }}" is-open="datePicker.opened" min-date="minDate" max-date="maxDate" init-date="addedTripDate[1]" ng-required="true" show-button-bar="false" ng-change="setTripDate(this, 1)">
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open()"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p> -->

<!-- <input type="text" ng-model="newTrip.typed.from" placeholder="San Francisco"> -->
<input type="text" ng-model="newTrip.typed" placeholder="Enter a destination (e.g., Paris)">
<button type="button" class="btn btn-primary" ng-click="searchTripGeocoding(); isAddOpen = true">Add</button>
<button type="button" class="btn btn-primary" ng-click="searchTripGeocoding()">Add</button>
<div ng-if="newTrip.searched">
We found <br/>
<!-- <strong>{{ newTrip.newName.from }}</strong> for {{ newTrip.typed.from }} and <br/> -->
<strong>{{ newTrip.newName }}</strong> for {{ newTrip.typed }}.<br/>
Want to add with this name?
<div><a ng-click="addTrip(true)">YES</a></div>
Expand Down
21 changes: 9 additions & 12 deletions server/socketComm.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,35 +59,32 @@ module.exports = function(app, server) {
}

function reverseGeocoding(id, type, lat, lng, timestamp) {

//TODO: handle daily limit error
// [Error: Status is OVER_QUERY_LIMIT. You have exceeded your daily request quota for this API.] { raw:
// { error_message: 'You have exceeded your daily request quota for this API.',
// results: [],
// status: 'OVER_QUERY_LIMIT' } }
geocoder.reverse({ lat:lat, lon:lng }, function (err, res) {
console.log(err, res);
var name = lat + ', ' + lng;
if (_.isArray(res)) {
name = (res[0].city ? (res[0].city + ', ') : '') + res[0].country;
getTimezone(lat, lng, timestamp, name, id, type);
} else {
io.emit('location', {
error: res.raw.error_message
});
}
});
}

function getGeocoding(address) {
console.log(address);
// { raw:
// { error_message: 'You have exceeded your daily request quota for this API.',
// results: [],
// status: 'OVER_QUERY_LIMIT' } }
geocoder.geocode({ address: address }, function (err, res) {
console.log(res);
var name = address;
var error = false;
if (_.isArray(res) && !_.isEmpty(res)) {
name = (res[0].city ? (res[0].city + ', ') : '') + res[0].country;
name = (res[0].city ? (res[0].city + ', ') : '') + res[0].country;
} else {
error = true;
}
io.emit('newTripLocation', { name: name });
io.emit('newTripLocation', { name: name, error: true });
});
}

Expand Down

0 comments on commit e4a8e49

Please sign in to comment.