Skip to content

Commit

Permalink
Initial work on #9.
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Conway committed Aug 21, 2012
1 parent 66adff2 commit adef575
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 2 deletions.
163 changes: 163 additions & 0 deletions app/updaters/DeploymentPlan.java
@@ -0,0 +1,163 @@
package updaters;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TimeZone;

import com.google.gson.Gson;

import play.Play;

import models.GtfsFeed;
import models.MetroArea;
import models.NtdAgency;

/**
* A deployment plan contains all the information needed to build a graph for a given metro area at a
* given time.
*
* @author mattwigway
*/

public class DeploymentPlan {
private Date startDate;
private Date endDate;
private static TimeZone gmt = TimeZone.getTimeZone("GMT");
private Calendar calendar = Calendar.getInstance(gmt);
private FeedDescriptor[] feeds;

/**
* Create a plan for the given metro at the current time and for the default window.
* @param area
*/
public DeploymentPlan(MetroArea area) {
this(area, new Date());
}

/**
* Create a plan for the given metro at the given date and for the default window.
* @param area
* @param date
*/
public DeploymentPlan(MetroArea area, Date date) {
this(area, date,
Integer.parseInt(Play.configuration.getProperty("dashboard.planwindow", "14")));
}

/**
* Create a new deployment plan.
* @param area The Metro Area to create a plan for.
* @param date The date this plan should go into effect
* @param window The number of days this plan should attempt to find valid trip plans.
*/
public DeploymentPlan(MetroArea area, Date date, int window) {
this.startDate = date;
calendar.setTime(date);
calendar.add(Calendar.DAY_OF_YEAR, window);
this.endDate = calendar.getTime();

List<GtfsFeed> feeds;
Set<FeedDescriptor> toInclude = new HashSet<FeedDescriptor>();

for (NtdAgency agency : area.getAgencies()) {
// all the unsuperseded feeds for this agency

for (GtfsFeed feed : agency.feeds) {
if (feed.supersededBy != null) {
continue;
}

addFeeds(feed, toInclude);
}

this.feeds = new FeedDescriptor[toInclude.size()];
this.feeds = toInclude.toArray(this.feeds);
}
}

/**
* Follows the chain of supersession back until it adds enough feeds to cover the window.
* @param feed
* @param toInclude
*/
private void addFeeds(GtfsFeed feed, Set<FeedDescriptor> toInclude) {
addFeeds(feed, toInclude, 0);
}

private void addFeeds(GtfsFeed feed, Set<FeedDescriptor> toInclude, int i) {
FeedDescriptor fd;
GtfsFeed olderFeed;

if (this.startDate.compareTo(feed.startDate) < 0) {
// Feed starts after today

if (this.endDate.compareTo(feed.startDate) > 0) {
// Feed starts before the end of the window, include it
fd = new FeedDescriptor();
fd.feedId = feed.storedId;

// force expire before the next one starts, if it's not already
if (feed.supersededBy != null &&
feed.expirationDate.compareTo(feed.supersededBy.startDate) >= 0) {
calendar.setTime(feed.supersededBy.startDate);
// Go back one day to get the end date for this feed
calendar.add(Calendar.DAY_OF_YEAR, -1);
fd.expireOn = calendar.getTime();
}
// otherwise, let it expire normally
else {
fd.expireOn = feed.expirationDate;
}

fd.defaultAgencyId = feed.dataExchangeId + "_" + i;
}

olderFeed = GtfsFeed.find("bySupersededBy", feed).first();
if (olderFeed == null) {
// Data doesn't go back far enough
return;
}

addFeeds(olderFeed, toInclude, i + 1);
return;
}
else {
// Feed does not start after today. Presumably we'll be following feeds
// through supersession in roughly chronological order, so we don't need
// to continue searching for older feeds.
fd = new FeedDescriptor();
fd.feedId = feed.storedId;
fd.expireOn = feed.expirationDate;
fd.defaultAgencyId = feed.dataExchangeId + "_" + i;
toInclude.add(fd);
return;
}
}

/**
* Convert this plan to JSON for Deployer.
* @return JSON for Deployer.
*/
public String toJson () {
DeploymentPlanProxy plan = new DeploymentPlanProxy();
plan.feeds = this.feeds;

Gson gson = new Gson();
return gson.toJson(plan);
}

// This is serialized to JSON and sent to deployer.
private class DeploymentPlanProxy {
private FeedDescriptor[] feeds;
}

private class FeedDescriptor {
private String feedId;
private Date expireOn;
private String defaultAgencyId;
}
}
32 changes: 32 additions & 0 deletions app/updaters/DeploymentPlanGeneratorHook.java
@@ -0,0 +1,32 @@
package updaters;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Set;

import models.MetroArea;

/**
* Generates a deployment plan and dispatches to Deployer for each changed metro area.
* @author mattwigway
*
*/
public class DeploymentPlanGeneratorHook implements UpdaterHook {

@Override
public void update(Set<MetroArea> areas) {
for (MetroArea area : areas) {
// generate the plan
DeploymentPlan plan = new DeploymentPlan(area);

// and dispatch the JSON
try {
FileWriter writer = new FileWriter("/tmp/" + area.name + ".json");
writer.write(plan.toJson());
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
10 changes: 8 additions & 2 deletions app/updaters/GtfsDataExchangeUpdater.java
Expand Up @@ -52,9 +52,15 @@ public Set<MetroArea> update () {

// FIXME remove
if (dataExchangeId.equals("mts")) continue;

if (dataExchangeId.equals("amtrak-sunset-limited-unofficial-feed")) continue;
if (dataExchangeId.equals("tac-transportation")) continue;

// find the feed
GtfsFeed originalFeed = GtfsFeed.find("byDataExchangeId", dataExchangeId).first();
// make sure we get the latest one so that date comparisons work
// TODO: This shouldn't depend on how JPA lays out relationships
GtfsFeed originalFeed = GtfsFeed.find("dataExchangeId = ? and supersededBy_id IS NULL",
dataExchangeId)
.first();

String url = XPath.selectText("@href", link);

Expand Down
1 change: 1 addition & 0 deletions conf/application-context.xml
Expand Up @@ -17,6 +17,7 @@
<property name="hooks">
<list>
<bean class="updaters.LoggingUpdaterHook" />
<bean class="updaters.DeploymentPlanGeneratorHook" />
</list>
</property>
</bean>
Expand Down
3 changes: 3 additions & 0 deletions conf/application.conf
Expand Up @@ -227,3 +227,6 @@ mail.smtp=mock
%test.jpa.ddl=create
%test.mail.smtp=mock

# Window in days for deployer requests
dashboard.planwindow=28

0 comments on commit adef575

Please sign in to comment.