/* This program is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser 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 org.opentripplanner.updater.stoptime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.onebusaway.gtfs.model.AgencyAndId;
import org.opentripplanner.common.CTX;
import org.opentripplanner.routing.trippattern.Update;
public class KV8Update extends Update {
public KV8Update(AgencyAndId tripId, String stopId, int stopSeq, int arrive, int depart,
Status status, long timestamp) {
super(tripId, stopId, stopSeq, arrive, depart, status, timestamp);
}
public static List<Update> fromCTX(String ctxString) {
CTX ctx = new CTX(ctxString);
return fromCTX(ctx);
}
public static List<Update> fromCTX(CTX ctx) {
//LOG.trace(ctxString);
// at this point, updates may have mixed trip IDs, dates, etc.
List<Update> ret = new ArrayList<Update>();
for (int i = 0; i < ctx.rows.size(); i++) {
HashMap<String, String> row = ctx.rows.get(i);
// there was a field in the CTX all along that indicated the extra non-passenger stops...
if (row.get("JourneyStopType").equals("INFOPOINT"))
continue;
int arrival = secondsSinceMidnight(row.get("ExpectedArrivalTime"));
int departure = secondsSinceMidnight(row.get("ExpectedDepartureTime"));
KV8Update u = new KV8Update(
kv8TripId(row),
kv8StopId(row),
Integer.parseInt(row.get("UserStopOrderNumber")),
arrival, departure,
kv8Status(row),
kv8Timestamp(row)) ;
ret.add(u);
}
return ret;
}
/**
* no good for DST
*/
private static int secondsSinceMidnight(String hhmmss) {
String[] time = hhmmss.split(":");
int hours = Integer.parseInt(time[0]);
int minutes = Integer.parseInt(time[1]);
int seconds = Integer.parseInt(time[2]);
return (hours * 60 + minutes) * 60 + seconds;
}
/**
* convert KV7 fields into a GTFS trip_id
* trip_ids must be data set unique in GTFS, which is why we use the DataOwnerCode (~=agency_id)
* twice, in the trip_id itself and the enclosing AgencyAndId.
* https://github.com/skywave/kv7tools/blob/master/kv7_gtfs.sql#L42
*/
private static AgencyAndId kv8TripId (HashMap<String, String> row) {
String tripId = String.format("%s|%s|%s|%s|%s",
row.get("DataOwnerCode"),
row.get("LinePlanningNumber"),
row.get("LocalServiceLevelCode"),
row.get("JourneyNumber"),
row.get("FortifyOrderNumber"));
return new AgencyAndId(row.get("DataOwnerCode"), tripId);
}
/**
* Convert KV7 fields into a GTFS stop_id. DataOwnerCode and UserStopCode are the agency's
* internal identifiers for a stop, so should not be used. TimingPointCode is a unique
* nationwide (feed-wide) identifier which includes those UserStopCodes.
*/
private static String kv8StopId (HashMap<String, String> row) {
return row.get("TimingPointCode");
}
private static long kv8Timestamp (HashMap<String, String> row) {
String timestamp = row.get("LastUpdateTimeStamp");
DateTimeFormatter parser = ISODateTimeFormat.dateTimeNoMillis();
DateTime dt = parser.parseDateTime(timestamp);
return dt.getMillis();
}
private static Update.Status kv8Status(HashMap<String, String> row) {
String s = row.get("TripStopStatus");
if (s.equals("DRIVING"))
return Update.Status.PREDICTION;
else
return Update.Status.valueOf(s);
}
}