nearby stations and departures for Rhein-Ruhr

git-svn-id: https://public-transport-enabler.googlecode.com/svn/trunk@231 0924bc21-9374-b0fa-ee44-9ff1593b38f0
This commit is contained in:
andreas.schildbach 2010-10-03 15:18:25 +00:00
parent 1b8c97aa2d
commit 7cb981f289
3 changed files with 268 additions and 26 deletions

View file

@ -74,10 +74,7 @@ public abstract class AbstractEfaProvider implements NetworkProvider
return results; return results;
} }
private static final Pattern P_NEARBY = Pattern.compile("<itdOdvAssignedStop " // private static final Pattern P_NEARBY_MESSAGES = Pattern.compile("(unsere Server zur Zeit ausgelastet)");
+ "(?:stopID=\"(\\d+)\" x=\"(\\d+)\" y=\"(\\d+)\" mapName=\"WGS84\" [^>]*? nameWithPlace=\"([^\"]*)\" distance=\"(\\d+)\"" //
+ "|distance=\"(\\d+)\" [^>]*? nameWithPlace=\"([^\"]*)\" [^>]*? stopID=\"(\\d+)\" [^>]*? x=\"(\\d+)\" y=\"(\\d+)\"" //
+ ")");
protected abstract String nearbyLatLonUri(int lat, int lon); protected abstract String nearbyLatLonUri(int lat, int lon);
@ -87,29 +84,68 @@ public abstract class AbstractEfaProvider implements NetworkProvider
throws IOException throws IOException
{ {
String uri = null; String uri = null;
if (lat != 0 || lon != 0)
uri = nearbyLatLonUri(lat, lon);
if (uri == null && stationId != null) if (uri == null && stationId != null)
uri = nearbyStationUri(stationId); uri = nearbyStationUri(stationId);
if (uri == null && (lat != 0 || lon != 0))
uri = nearbyLatLonUri(lat, lon);
if (uri == null) if (uri == null)
throw new IllegalArgumentException("at least one of stationId or lat/lon must be given"); throw new IllegalArgumentException("at least one of stationId or lat/lon must be given");
try
{
final CharSequence page = ParserUtils.scrape(uri); final CharSequence page = ParserUtils.scrape(uri);
if (P_NEARBY_MESSAGES.matcher(page).find())
return null;
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
final XmlPullParser pp = factory.newPullParser();
pp.setInput(new StringReader(page.toString()));
XmlPullUtil.jumpToStartTag(pp, null, "itdOdvName");
final String nameState = pp.getAttributeValue(null, "state");
if (nameState.equals("identified"))
{
final List<Station> stations = new ArrayList<Station>(); final List<Station> stations = new ArrayList<Station>();
final Matcher mNearby = P_NEARBY.matcher(page); XmlPullUtil.jumpToStartTag(pp, null, "odvNameElem");
while (mNearby.find()) final String parsedOwnLocationIdStr = pp.getAttributeValue(null, "stopID");
if (parsedOwnLocationIdStr != null)
{ {
final boolean firstSyntax = mNearby.group(1) != null; final int parsedOwnLocationId = Integer.parseInt(parsedOwnLocationIdStr);
final int sId = Integer.parseInt(mNearby.group(firstSyntax ? 1 : 8)); final String parsedOwnMapName = pp.getAttributeValue(null, "mapName");
final int sLon = Integer.parseInt(mNearby.group(firstSyntax ? 2 : 9)); if (parsedOwnMapName != null)
final int sLat = Integer.parseInt(mNearby.group(firstSyntax ? 3 : 10)); {
final String sName = mNearby.group(firstSyntax ? 4 : 7).trim(); if (!"WGS84".equals(parsedOwnMapName))
final int sDist = Integer.parseInt(mNearby.group(firstSyntax ? 5 : 6)); throw new IllegalStateException("unknown mapName: " + parsedOwnMapName);
final int parsedOwnLon = Integer.parseInt(pp.getAttributeValue(null, "x"));
final int parsedOwnLat = Integer.parseInt(pp.getAttributeValue(null, "y"));
stations.add(new Station(parsedOwnLocationId, null, parsedOwnLat, parsedOwnLon, 0, null, null));
}
}
final Station station = new Station(sId, sName, sLat, sLon, sDist, null, null); if (XmlPullUtil.jumpToStartTag(pp, null, "itdOdvAssignedStops"))
stations.add(station); {
while (XmlPullUtil.nextStartTagInsideTree(pp, null, "itdOdvAssignedStop"))
{
final String parsedMapName = pp.getAttributeValue(null, "mapName");
if (parsedMapName != null)
{
if (!"WGS84".equals(parsedMapName))
throw new IllegalStateException("unknown mapName: " + parsedMapName);
final int parsedLocationId = Integer.parseInt(pp.getAttributeValue(null, "stopID"));
final String parsedName = normalizeLocationName(pp.getAttributeValue(null, "nameWithPlace"));
final int parsedLon = Integer.parseInt(pp.getAttributeValue(null, "x"));
final int parsedLat = Integer.parseInt(pp.getAttributeValue(null, "y"));
final String parsedDistStr = pp.getAttributeValue(null, "distance");
final int parsedDist = parsedDistStr != null ? Integer.parseInt(parsedDistStr) : 0;
stations.add(new Station(parsedLocationId, parsedName, parsedLat, parsedLon, parsedDist, null, null));
XmlPullUtil.skipRestOfTree(pp);
}
}
} }
if (maxStations == 0 || maxStations >= stations.size()) if (maxStations == 0 || maxStations >= stations.size())
@ -117,9 +153,26 @@ public abstract class AbstractEfaProvider implements NetworkProvider
else else
return stations.subList(0, maxStations); return stations.subList(0, maxStations);
} }
else if (nameState.equals("notidentified"))
{
return null;
}
else
{
throw new RuntimeException("unknown nameState '" + nameState + "' on " + uri);
}
}
catch (final XmlPullParserException x)
{
throw new RuntimeException(x);
}
}
private static final Pattern P_LINE_IRE = Pattern.compile("IRE\\d+");
private static final Pattern P_LINE_RE = Pattern.compile("RE\\d+"); private static final Pattern P_LINE_RE = Pattern.compile("RE\\d+");
private static final Pattern P_LINE_RB = Pattern.compile("RB\\d+"); private static final Pattern P_LINE_RB = Pattern.compile("RB\\d+");
private static final Pattern P_LINE_VB = Pattern.compile("VB\\d+");
private static final Pattern P_LINE_R = Pattern.compile("R\\d+(/R\\d+|\\(z\\))?");
private static final Pattern P_LINE_U = Pattern.compile("U\\d+"); private static final Pattern P_LINE_U = Pattern.compile("U\\d+");
protected String parseLine(final String number, final String symbol, final String mot) protected String parseLine(final String number, final String symbol, final String mot)
@ -157,6 +210,8 @@ public abstract class AbstractEfaProvider implements NetworkProvider
return 'R' + str; return 'R' + str;
if (type.equals("IRE")) // Interregio-Express if (type.equals("IRE")) // Interregio-Express
return 'R' + str; return 'R' + str;
if (P_LINE_IRE.matcher(type).matches())
return 'R' + str;
if (type.equals("RE")) // Regional-Express if (type.equals("RE")) // Regional-Express
return 'R' + str; return 'R' + str;
if (P_LINE_RE.matcher(type).matches()) if (P_LINE_RE.matcher(type).matches())
@ -167,6 +222,8 @@ public abstract class AbstractEfaProvider implements NetworkProvider
return 'R' + str; return 'R' + str;
if (type.equals("R")) // Regionalzug if (type.equals("R")) // Regionalzug
return 'R' + str; return 'R' + str;
if (P_LINE_R.matcher(type).matches())
return 'R' + str;
if (type.equals("D")) // Schnellzug if (type.equals("D")) // Schnellzug
return 'R' + str; return 'R' + str;
if (type.equals("WFB")) // Westfalenbahn if (type.equals("WFB")) // Westfalenbahn
@ -209,6 +266,10 @@ public abstract class AbstractEfaProvider implements NetworkProvider
return 'R' + str; return 'R' + str;
if (type.equals("VBG")) // Vogtlandbahn if (type.equals("VBG")) // Vogtlandbahn
return 'R' + str; return 'R' + str;
if (type.equals("VB")) // Vogtlandbahn
return 'R' + str;
if (P_LINE_VB.matcher(type).matches())
return 'R' + str;
if (type.equals("VX")) // Vogtland Express if (type.equals("VX")) // Vogtland Express
return 'R' + str; return 'R' + str;
if (type.equals("CB")) // City-Bahn Chemnitz if (type.equals("CB")) // City-Bahn Chemnitz
@ -279,6 +340,24 @@ public abstract class AbstractEfaProvider implements NetworkProvider
return 'R' + str; return 'R' + str;
if (type.equals("PRE")) // Pressnitztalbahn if (type.equals("PRE")) // Pressnitztalbahn
return 'R' + str; return 'R' + str;
if (type.equals("VEB")) // Vulkan-Eifel-Bahn
return 'R' + str;
if (type.equals("neg")) // Norddeutsche Eisenbahn Gesellschaft
return 'R' + str;
if (type.equals("AVG")) // Felsenland-Express
return 'R' + str;
if (type.equals("ABG")) // Anhaltische Bahngesellschaft
return 'R' + str;
if (type.equals("LGB")) // Lößnitzgrundbahn
return 'R' + str;
if (type.equals("LEO")) // Chiemgauer Lokalbahn
return 'R' + str;
if (type.equals("WTB")) // Weißeritztalbahn
return 'R' + str;
if (type.equals("P")) // Kasbachtalbahn, Wanderbahn im Regental, Rhön-Zügle
return 'R' + str;
if (type.equals("KBS")) // Kursbuchstrecke
return 'R' + str;
if (type.equals("BSB")) // Breisgau-S-Bahn if (type.equals("BSB")) // Breisgau-S-Bahn
return 'S' + str; return 'S' + str;
@ -414,7 +493,7 @@ public abstract class AbstractEfaProvider implements NetworkProvider
private static final Pattern P_STATION_NAME_WHITESPACE = Pattern.compile("\\s+"); private static final Pattern P_STATION_NAME_WHITESPACE = Pattern.compile("\\s+");
private static String normalizeLocationName(final String name) protected static String normalizeLocationName(final String name)
{ {
return P_STATION_NAME_WHITESPACE.matcher(name).replaceAll(" "); return P_STATION_NAME_WHITESPACE.matcher(name).replaceAll(" ");
} }

View file

@ -0,0 +1,114 @@
/*
* Copyright 2010 the original author or authors.
*
* 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 de.schildbach.pte;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author Andreas Schildbach
*/
public class VrrProvider extends AbstractEfaProvider
{
public static final String NETWORK_ID = "efa3.vrr.de";
private static final String API_BASE = "http://efa3.vrr.de/vrr_mobile/";
public boolean hasCapabilities(final Capability... capabilities)
{
for (final Capability capability : capabilities)
if (capability == Capability.DEPARTURES)
return true;
return false;
}
@Override
protected String autocompleteUri(CharSequence constraint)
{
throw new UnsupportedOperationException();
}
@Override
protected String nearbyLatLonUri(final int lat, final int lon)
{
return null;
}
private static final String NEARBY_STATION_URI = API_BASE
+ "XSLT_DM_REQUEST"
+ "?outputFormat=XML&coordOutputFormat=WGS84&name_dm=%s&type_dm=stop&itOptionsActive=1&ptOptionsActive=1&useProxFootSearch=1&mergeDep=1&useAllStops=1&mode=direct&deleteAssignedStop=0";
@Override
protected String nearbyStationUri(final String stationId)
{
return String.format(NEARBY_STATION_URI, stationId);
}
public StationLocationResult stationLocation(String stationId) throws IOException
{
throw new UnsupportedOperationException();
}
public String departuresQueryUri(final String stationId, final int maxDepartures)
{
final StringBuilder uri = new StringBuilder();
uri.append(API_BASE).append("XSLT_DM_REQUEST");
uri.append("?outputFormat=XML");
uri.append("&coordOutputFormat=WGS84");
uri.append("&type_dm=stop");
uri.append("&name_dm=").append(stationId);
uri.append("&mode=direct");
return uri.toString();
}
public QueryConnectionsResult queryConnections(LocationType fromType, String from, LocationType viaType, String via, LocationType toType,
String to, Date date, boolean dep, WalkSpeed walkSpeed) throws IOException
{
throw new UnsupportedOperationException();
}
public QueryConnectionsResult queryMoreConnections(String uri) throws IOException
{
throw new UnsupportedOperationException();
}
public GetConnectionDetailsResult getConnectionDetails(String connectionUri) throws IOException
{
throw new UnsupportedOperationException();
}
private static final Map<Character, int[]> LINES = new HashMap<Character, int[]>();
static
{
LINES.put('I', new int[] { Color.WHITE, Color.RED, Color.RED });
LINES.put('R', new int[] { Color.GRAY, Color.WHITE });
LINES.put('S', new int[] { Color.parseColor("#006e34"), Color.WHITE });
LINES.put('U', new int[] { Color.parseColor("#003090"), Color.WHITE });
LINES.put('T', new int[] { Color.parseColor("#cc0000"), Color.WHITE });
LINES.put('B', new int[] { Color.parseColor("#993399"), Color.WHITE });
LINES.put('F', new int[] { Color.BLUE, Color.WHITE });
LINES.put('?', new int[] { Color.DKGRAY, Color.WHITE });
}
public int[] lineColors(final String line)
{
return LINES.get(line.charAt(0));
}
}

View file

@ -0,0 +1,49 @@
/*
* Copyright 2010 the original author or authors.
*
* 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 de.schildbach.pte.live;
import java.util.List;
import org.junit.Test;
import de.schildbach.pte.QueryDeparturesResult;
import de.schildbach.pte.Station;
import de.schildbach.pte.VrrProvider;
/**
* @author Andreas Schildbach
*/
public class VrrProviderLiveTest
{
private final VrrProvider provider = new VrrProvider();
@Test
public void nearbyStation() throws Exception
{
final List<Station> results = provider.nearbyStations("20019904", 0, 0, 0, 0);
System.out.println(results.size() + " " + results);
}
@Test
public void departures() throws Exception
{
final QueryDeparturesResult result = provider.queryDepartures(provider.departuresQueryUri("1007258", 0));
System.out.println(result.departures.size() + " " + result.departures);
}
}