package de.schildbach.pte; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import de.schildbach.pte.QueryDeparturesResult.Status; public class OebbProvider implements NetworkProvider { public static final String NETWORK_ID = "fahrplan.oebb.at"; public boolean hasCapabilities(final Capability... capabilities) { for (final Capability capability : capabilities) if (capability == Capability.DEPARTURES || capability == Capability.LOCATION_STATION_ID) return true; return false; } private static final String NAME_URL = "http://fahrplan.oebb.at/bin/stboard.exe/dn?input="; private static final Pattern P_SINGLE_NAME = Pattern .compile(".*?.*", Pattern.DOTALL); private static final Pattern P_MULTI_NAME = Pattern.compile("", Pattern.DOTALL); public List autocompleteStations(final CharSequence constraint) throws IOException { final CharSequence page = ParserUtils.scrape(NAME_URL + ParserUtils.urlEncode(constraint.toString())); final List results = new ArrayList(); final Matcher mSingle = P_SINGLE_NAME.matcher(page); if (mSingle.matches()) { results.add(new Autocomplete(Integer.parseInt(mSingle.group(2)), ParserUtils.resolveEntities(mSingle.group(1)))); } else { final Matcher mMulti = P_MULTI_NAME.matcher(page); while (mMulti.find()) results.add(new Autocomplete(Integer.parseInt(mMulti.group(1)), ParserUtils.resolveEntities(mMulti.group(2)))); } return results; } private final String NEARBY_URI = "http://fahrplan.oebb.at/bin/stboard.exe/dn?distance=50&near=Suchen&input=%d"; private final static Pattern P_NEARBY_COARSE = Pattern.compile("(.*?)", Pattern.DOTALL); private final static Pattern P_NEARBY_FINE = Pattern.compile(".*?stboard\\.exe/.*?&input=.*?%23(\\d+)&.*?>(.*?).*?", Pattern.DOTALL); public List nearbyStations(final String stationId, final double lat, final double lon, final int maxDistance, final int maxStations) throws IOException { if (stationId == null) throw new IllegalArgumentException("stationId must be given"); final List stations = new ArrayList(); final String uri = String.format(NEARBY_URI, stationId); final CharSequence page = ParserUtils.scrape(uri); final Matcher mCoarse = P_NEARBY_COARSE.matcher(page); while (mCoarse.find()) { final Matcher mFine = P_NEARBY_FINE.matcher(mCoarse.group(1)); if (mFine.matches()) { final int parsedId = Integer.parseInt(mFine.group(1)); final String parsedName = ParserUtils.resolveEntities(mFine.group(2)); final Station station = new Station(parsedId, parsedName, 0, 0, 0, null, null); stations.add(station); } else { throw new IllegalArgumentException("cannot parse '" + mCoarse.group(1) + "' on " + uri); } } if (maxStations == 0 || maxStations >= stations.size()) return stations; else return stations.subList(0, maxStations); } public StationLocationResult stationLocation(final String stationId) throws IOException { throw new UnsupportedOperationException(); } private static final Map WALKSPEED_MAP = new HashMap(); static { WALKSPEED_MAP.put(WalkSpeed.SLOW, "115"); WALKSPEED_MAP.put(WalkSpeed.NORMAL, "100"); WALKSPEED_MAP.put(WalkSpeed.FAST, "85"); } private String connectionsQuery(final LocationType fromType, final String from, final LocationType viaType, final String via, final LocationType toType, final String to, final Date date, final boolean dep, final WalkSpeed walkSpeed) throws IOException { final DateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yy"); final DateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm"); final StringBuilder uri = new StringBuilder(); uri.append("queryPageDisplayed=yes"); uri.append("&start.x=0"); uri.append("&start.y=0"); uri.append("&start=Suchen"); uri.append("&REQ0JourneyStopsS0A=").append(locationType(fromType)); uri.append("&REQ0JourneyStopsS0G=").append(ParserUtils.urlEncode(from)); uri.append("&REQ0JourneyStopsS0ID="); // "tupel"? if (via != null) { uri.append("&REQ0JourneyStops1.0A=").append(locationType(viaType)); uri.append("&REQ0JourneyStops1.0G=").append(ParserUtils.urlEncode(via)); uri.append("&REQ0JourneyStops1.0ID="); } uri.append("&REQ0JourneyStopsZ0A=").append(locationType(toType)); uri.append("&REQ0JourneyStopsZ0G=").append(ParserUtils.urlEncode(to)); uri.append("&REQ0JourneyStopsZ0ID="); uri.append("&REQ0JourneyDate=").append(ParserUtils.urlEncode(DATE_FORMAT.format(date))); uri.append("&wDayExt0=").append(ParserUtils.urlEncode("Mo|Di|Mi|Do|Fr|Sa|So")); uri.append("&REQ0JourneyTime=").append(ParserUtils.urlEncode(TIME_FORMAT.format(date))); uri.append("&REQ0HafasSearchForw=").append(dep ? "1" : "0"); uri.append("&existHafasDemo3=yes"); uri.append("&REQ0JourneyProduct_list=").append(ParserUtils.urlEncode("0:1111111111010000-000000")); uri.append("&REQ0JourneyDep_Foot_speed=").append(WALKSPEED_MAP.get(walkSpeed)); uri.append("&existBikeEverywhere=yes"); uri.append("&existHafasAttrInc=yes"); return uri.toString(); } private static int locationType(final LocationType locationType) { if (locationType == LocationType.STATION) return 1; if (locationType == LocationType.ADDRESS) return 2; if (locationType == LocationType.ANY) return 255; throw new IllegalArgumentException(locationType.toString()); } private static final String QUERY_CONNECTIONS_FORM_URL = "http://fahrplan.oebb.at/bin/query.exe/dn?"; private static final Pattern P_QUERY_CONNECTIONS_FORM_ACTION = Pattern .compile("
]*>(.*?)", Pattern.DOTALL); private static final Pattern P_ADDRESSES = Pattern.compile("]*>\\s*(.*?)\\s*", Pattern.DOTALL); public QueryConnectionsResult queryConnections(final LocationType fromType, final String from, final LocationType viaType, final String via, final LocationType toType, final String to, final Date date, final boolean dep, final WalkSpeed walkSpeed) throws IOException { // get base url and cookies from form final CharSequence form = ParserUtils.scrape(QUERY_CONNECTIONS_FORM_URL, false, null, null, true); final Matcher m = P_QUERY_CONNECTIONS_FORM_ACTION.matcher(form); if (!m.find()) throw new IllegalStateException("cannot find form: '" + form + "' on " + QUERY_CONNECTIONS_FORM_URL); final String baseUri = m.group(1); // query final String query = connectionsQuery(fromType, from, viaType, via, toType, to, date, dep, walkSpeed); final CharSequence page = ParserUtils.scrape(baseUri, true, query, null, true); final Matcher mError = P_QUERY_CONNECTIONS_ERROR.matcher(page); if (mError.find()) { if (mError.group(1) != null) return QueryConnectionsResult.NO_CONNECTIONS; if (mError.group(2) != null) return QueryConnectionsResult.INVALID_DATE; if (mError.group(3) != null) return QueryConnectionsResult.SESSION_TIMEOUT; } List fromAddresses = null; List viaAddresses = null; List toAddresses = null; final Matcher mPreAddress = P_PRE_ADDRESS.matcher(page); while (mPreAddress.find()) { final String type = mPreAddress.group(1); final String options = mPreAddress.group(2); final Matcher mAddresses = P_ADDRESSES.matcher(options); final List addresses = new ArrayList(); while (mAddresses.find()) { final String address = ParserUtils.resolveEntities(mAddresses.group(1)).trim(); if (!addresses.contains(address)) addresses.add(address); } if (type.equals("REQ0JourneyStopsS0K")) fromAddresses = addresses; else if (type.equals("REQ0JourneyStopsZ0K")) toAddresses = addresses; else if (type.equals("REQ0JourneyStops1.0K")) viaAddresses = addresses; else throw new IOException(type); } if (fromAddresses != null || viaAddresses != null || toAddresses != null) return new QueryConnectionsResult(QueryConnectionsResult.Status.AMBIGUOUS, fromAddresses, viaAddresses, toAddresses); else return queryConnections(baseUri, page); } public QueryConnectionsResult queryMoreConnections(final String uri) throws IOException { final CharSequence page = ParserUtils.scrape(uri, false, null, null, true); final Matcher mError = P_QUERY_CONNECTIONS_ERROR.matcher(page); if (mError.find()) { if (mError.group(1) != null) return QueryConnectionsResult.NO_CONNECTIONS; if (mError.group(2) != null) return QueryConnectionsResult.INVALID_DATE; if (mError.group(3) != null) return QueryConnectionsResult.SESSION_TIMEOUT; } return queryConnections(uri, page); } private static final Pattern P_CONNECTIONS_FORM_ACTION = Pattern .compile("]*>.*?" // action + "\n(.*?)\n
.*?" // header + "\n" // + "(.*?
(.*?)
.*?)\n" // connections overview + ".*?" // + "\n" // + "(.*?)\n" // connection details + "
\n]*>\\s*(.*?)\\s*.*?" // from + "Datum:.*?]*>.., (\\d{2}\\.\\d{2}\\.\\d{2}).*?" // date + "nach:.*?]*>\\s*(.*?)\\s*.*?" // to + "(?:\"(REQ0HafasScrollDir=2&guiVCtrl_connection_detailsOut_add_selection&)\".*?)?" // linkEarlier + "(?:\"(REQ0HafasScrollDir=1&guiVCtrl_connection_detailsOut_add_selection&)\".*?)?" // linkLater , Pattern.DOTALL); private static final Pattern P_CONNECTIONS_COARSE = Pattern.compile("\n(.*?)", Pattern.DOTALL); private static final Pattern P_CONNECTIONS_FINE = Pattern.compile(".*?" // + "name=\"guiVCtrl_connection_detailsOut_select_([\\w-]+)\".*?" // id + "]*>(\\d{2}\\.\\d{2}\\.\\d{2})" // departureDate + "(?:
(\\d{2}\\.\\d{2}\\.\\d{2}))?.*?" // arrivalDate + "(\\d{1,2}:\\d{2})" // departureTime + "
(\\d{1,2}:\\d{2}).*?" // arrivalTime , Pattern.DOTALL); private static final Pattern P_CONNECTIONS_DETAILS_COARSE = Pattern.compile("Detailansicht" // id + "(.*?)" // + "\nDauer:", Pattern.DOTALL); private static final Pattern P_CONNECTION_DETAILS_COARSE = Pattern.compile("\n(.*?)\n\n" // + "\n(.*?)\n\n\n(.*?)\n", Pattern.DOTALL); private static final Pattern P_CONNECTION_DETAILS_FINE = Pattern.compile(".*?" // + "]*>\n" // + "(?:]*>)?" // departureId + "([^\n<]*).*?" // departure + "]*>\n(?:(\\d{2}\\.\\d{2}\\.\\d{2})| )\n.*?" // departureDate + "]*>(?:(\\d{2}:\\d{2})| ).*?" // departureTime + "]*>\\s*(?: |(.*?))\\s*.*?" // departurePosition + "]*>(.*?).*?)?" // line + "]*>\n" // + "(?:]*>)?" // arrivalId + "([^\n<]*).*?" // arrival + "]*>\n(?:(\\d{2}\\.\\d{2}\\.\\d{2})| )\n.*?" // arrivalDate + "]*>(?:(\\d{2}:\\d{2})| ).*?" // arrivalTime + "]*>\\s*(?: |(.*?))\\s*.*?" // arrivalPosition + "(?:ca\\. (\\d+) Min\\.\n.*?)?" // min , Pattern.DOTALL); private QueryConnectionsResult queryConnections(final String firstUri, final CharSequence firstPage) throws IOException { // ugly workaround to fetch all details final Matcher mFormAction = P_CONNECTIONS_FORM_ACTION.matcher(firstPage); if (!mFormAction.find()) throw new IOException("cannot find form action in '" + firstPage + "' on " + firstUri); final String baseUri = mFormAction.group(1); final String query = "sortConnections=minDeparture&guiVCtrl_connection_detailsOut_add_group_overviewOut=yes"; final CharSequence page = ParserUtils.scrape(baseUri, true, query, null, true); final Matcher mError = P_QUERY_CONNECTIONS_ERROR.matcher(page); if (mError.find()) { if (mError.group(1) != null) return QueryConnectionsResult.NO_CONNECTIONS; if (mError.group(2) != null) return QueryConnectionsResult.INVALID_DATE; if (mError.group(3) != null) return QueryConnectionsResult.SESSION_TIMEOUT; } // parse page final Matcher mPage = P_CONNECTIONS_PAGE.matcher(page); if (mPage.matches()) { final String action = mPage.group(1); final String headSet = mPage.group(2) + mPage.group(4); final Matcher mHead = P_CONNECTIONS_HEAD.matcher(headSet); if (mHead.matches()) { final String from = ParserUtils.resolveEntities(mHead.group(1)); final Date currentDate = ParserUtils.parseDate(mHead.group(2)); final String to = ParserUtils.resolveEntities(mHead.group(3)); final String linkEarlier = mHead.group(4) != null ? action + "&REQ0HafasScrollDir=2" + ParserUtils.resolveEntities(mHead.group(4)) : null; final String linkLater = mHead.group(5) != null ? action + "&REQ0HafasScrollDir=1" + ParserUtils.resolveEntities(mHead.group(5)) : null; final List connections = new ArrayList(); final Matcher mConCoarse = P_CONNECTIONS_COARSE.matcher(mPage.group(3)); while (mConCoarse.find()) { final Matcher mConFine = P_CONNECTIONS_FINE.matcher(mConCoarse.group(1)); if (mConFine.matches()) { final String id = mConFine.group(1); final Date departureDate = ParserUtils.parseDate(mConFine.group(2)); final Date arrivalDate = mConFine.group(3) != null ? ParserUtils.parseDate(mConFine.group(3)) : null; final Date departureTime = ParserUtils.joinDateTime(departureDate, ParserUtils.parseTime(mConFine.group(4))); final Date arrivalTime = ParserUtils.joinDateTime(arrivalDate != null ? arrivalDate : departureDate, ParserUtils .parseTime(mConFine.group(5))); final String link = firstUri + "#" + id; // TODO use print link? final Connection connection = new Connection(id, link, departureTime, arrivalTime, null, null, 0, from, 0, to, new ArrayList(1)); connections.add(connection); } else { throw new IllegalArgumentException("cannot parse '" + mConCoarse.group(1) + "' on " + baseUri + " (POST)"); } } final Matcher mConDetCoarse = P_CONNECTIONS_DETAILS_COARSE.matcher(mPage.group(5)); while (mConDetCoarse.find()) { final String id = mConDetCoarse.group(1); final Connection connection = findConnection(connections, id); Date lastDate = null; final Matcher mDetCoarse = P_CONNECTION_DETAILS_COARSE.matcher(mConDetCoarse.group(2)); while (mDetCoarse.find()) { final String set = mDetCoarse.group(1) + mDetCoarse.group(2) + mDetCoarse.group(3); final Matcher mDetFine = P_CONNECTION_DETAILS_FINE.matcher(set); if (mDetFine.matches()) { final int departureId = mDetFine.group(1) != null ? Integer.parseInt(mDetFine.group(1)) : 0; final String departure = ParserUtils.resolveEntities(mDetFine.group(2)); Date departureDate = mDetFine.group(3) != null ? ParserUtils.parseDate(mDetFine.group(3)) : null; if (departureDate != null) lastDate = departureDate; else departureDate = lastDate; final String lineType = mDetFine.group(6); final int arrivalId = mDetFine.group(8) != null ? Integer.parseInt(mDetFine.group(8)) : 0; final String arrival = ParserUtils.resolveEntities(mDetFine.group(9)); Date arrivalDate = mDetFine.group(10) != null ? ParserUtils.parseDate(mDetFine.group(10)) : null; if (arrivalDate != null) lastDate = arrivalDate; else arrivalDate = lastDate; if (!lineType.equals("fuss")) { if (departureId == 0) throw new IllegalStateException("departureId"); final Date departureTime = ParserUtils.parseTime(mDetFine.group(4)); final Date departureDateTime = ParserUtils.joinDateTime(departureDate, departureTime); final String departurePosition = mDetFine.group(5) != null ? ParserUtils.resolveEntities(mDetFine.group(5)) : null; final String line = normalizeLine(lineType, ParserUtils.resolveEntities(mDetFine.group(7))); if (arrivalId == 0) throw new IllegalStateException("arrivalId"); final Date arrivalTime = ParserUtils.parseTime(mDetFine.group(11)); final Date arrivalDateTime = ParserUtils.joinDateTime(arrivalDate, arrivalTime); final String arrivalPosition = mDetFine.group(12) != null ? ParserUtils.resolveEntities(mDetFine.group(12)) : null; final Connection.Trip trip = new Connection.Trip(line, LINES.get(line.charAt(0)), null, departureDateTime, departurePosition, departureId, departure, arrivalDateTime, arrivalPosition, arrivalId, arrival); connection.parts.add(trip); } else { final int min = Integer.parseInt(mDetFine.group(13)); final Connection.Footway footway = new Connection.Footway(min, departureId, departure, arrivalId, arrival); connection.parts.add(footway); } } else { throw new IllegalArgumentException("cannot parse '" + set + "' on " + baseUri + " (POST)"); } } } return new QueryConnectionsResult(baseUri, from, to, currentDate, linkEarlier, linkLater, connections); } else { throw new IllegalArgumentException("cannot parse '" + headSet + "' on " + baseUri + " (POST)"); } } else { throw new IOException(page.toString()); } } private Connection findConnection(final List connections, final String id) { for (final Connection connection : connections) if (connection.id.equals(id)) return connection; return null; } public GetConnectionDetailsResult getConnectionDetails(final String connectionUri) throws IOException { throw new UnsupportedOperationException(); } public String departuresQueryUri(final String stationId, final int maxDepartures) { final DateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm"); final Date now = new Date(); final StringBuilder uri = new StringBuilder(); uri.append("http://fahrplan.oebb.at/bin/stboard.exe/dn?L=vs_scotty.vs_stb"); uri.append("&input=").append(stationId); uri.append("&boardType=dep"); uri.append("&time=").append(TIME_FORMAT.format(now)); uri.append("&productsFilter=111111111111"); uri.append("&additionalTime=0"); uri.append("&maxJourneys=20"); uri.append("&start=yes"); uri.append("&selectDate=today"); uri.append("&monitor=1"); uri.append("&requestType=0"); uri.append("&view=preview"); uri.append("&disableEquivs=yes"); // don't use nearby stations return uri.toString(); } public QueryDeparturesResult queryDepartures(final String uri) throws IOException { // scrape page final String page = ParserUtils.scrape(uri).toString().substring(14); try { final JSONObject head = new JSONObject(page); final String location = ParserUtils.resolveEntities(head.getString("stationName")); final int locationId = head.optInt("stationEvaId", -1); // final boolean rt = head.optBoolean("rtInfo"); if (locationId == -1) return new QueryDeparturesResult(uri, Status.INVALID_STATION); final List departures = new ArrayList(8); final JSONArray aDeparture = head.optJSONArray("journey"); if (aDeparture != null) { for (int i = 0; i < aDeparture.length(); i++) { final JSONObject departure = aDeparture.optJSONObject(i); if (departure != null) { final Date time = ParserUtils.joinDateTime(ParserUtils.parseDate(departure.getString("da")), ParserUtils.parseTime(departure .getString("ti"))); final String line = normalizeLine(departure.getString("pr")); final String destination = ParserUtils.resolveEntities(departure.getString("st")); String position = departure.optString("tr"); if (position != null) position = "Gl. " + position; final boolean rt = head.optBoolean("rt", false); if (rt == true) System.out.println("Realtime!!"); final String lineLink = departure.optString("tinfoline"); departures.add(new Departure(!rt ? time : null, rt ? time : null, line, line != null ? LINES.get(line.charAt(0)) : null, lineLink, position, 0, destination, null)); } } } return new QueryDeparturesResult(uri, locationId, location, null, departures); } catch (final JSONException x) { throw new RuntimeException("cannot parse: '" + page + "' on " + uri, x); } } private static final Pattern P_NORMALIZE_LINE = Pattern.compile("([A-Za-zÄÖÜäöüßáàâéèêíìîóòôúùû-]+)[\\s]*(.*)"); private static String normalizeLine(final String line) { final Matcher m = P_NORMALIZE_LINE.matcher(line); if (m.matches()) { final String type = m.group(1); final String number = m.group(2); final char normalizedType = normalizeType(type); if (normalizedType != 0) return normalizedType + type + number; throw new IllegalStateException("cannot normalize type " + type + " line " + line); } else { throw new IllegalStateException("cannot normalize line " + line); } } private static String normalizeLine(final String type, final String line) { final Matcher m = P_NORMALIZE_LINE.matcher(line); final String strippedLine = m.matches() ? m.group(1) + m.group(2) : line; final char normalizedType = normalizeType(type); if (normalizedType != 0) return normalizedType + strippedLine; return '?' + strippedLine; // throw new IllegalStateException("cannot normalize type " + type + " line " + line); } private static char normalizeType(final String type) { final String ucType = type.toUpperCase(); if (ucType.equals("OEC")) // ÖBB-EuroCity return 'I'; if (ucType.equals("OIC")) // ÖBB-InterCity return 'I'; if (ucType.equals("EC")) // EuroCity return 'I'; if (ucType.equals("IC")) // InterCity return 'I'; if (ucType.equals("ICE")) // InterCityExpress return 'I'; // if (ucType.equals("X")) // Interconnex // return 'I'; // if (ucType.equals("EN")) // EuroNight // return 'I'; // if (ucType.equals("CNL")) // CityNightLine // return 'I'; // if (ucType.equals("DNZ")) // Berlin-Saratov, Berlin-Moskva // return 'I'; // if (ucType.equals("INT")) // Rußland // return 'I'; // if (ucType.equals("D")) // Rußland // return 'I'; // if (ucType.equals("RR")) // Finnland // return 'I'; // if (ucType.equals("TLK")) // Tanie Linie Kolejowe, Polen // return 'I'; // if (ucType.equals("EE")) // Rumänien // return 'I'; // if (ucType.equals("SC")) // SuperCity, Tschechien // return 'I'; // if (ucType.equals("RJ")) // RailJet, Österreichische Bundesbahnen // return 'I'; // if (ucType.equals("EST")) // Eurostar Frankreich // return 'I'; // if (ucType.equals("ALS")) // Spanien // return 'I'; // if (ucType.equals("ARC")) // Spanien // return 'I'; // if (ucType.equals("TLG")) // Spanien, Madrid // return 'I'; // if (ucType.equals("HOT")) // Spanien, Nacht // return 'I'; // if (ucType.equals("AVE")) // Alta Velocidad Española, Spanien // return 'I'; // if (ucType.equals("INZ")) // Schweden, Nacht // return 'I'; // if (ucType.equals("OZ")) // Schweden, Oeresundzug // return 'I'; // if (ucType.equals("X2")) // Schweden // return 'I'; // if (ucType.equals("THA")) // Thalys // return 'I'; // if (ucType.equals("TGV")) // Train à Grande Vitesse // return 'I'; // if (ucType.equals("LYN")) // Dänemark // return 'I'; if (ucType.equals("ARZ")) // Frankreich, Nacht return 'I'; // if (ucType.equals("ES")) // Eurostar Italia // return 'I'; // if (ucType.equals("ICN")) // Italien, Nacht // return 'I'; // if (ucType.equals("UUU")) // Italien, Nacht // return 'I'; // if (ucType.equals("RHI")) // ICE // return 'I'; // if (ucType.equals("RHT")) // TGV // return 'I'; // if (ucType.equals("TGD")) // TGV // return 'I'; // if (ucType.equals("ECB")) // EC // return 'I'; // if (ucType.equals("IRX")) // IC // return 'I'; // if (ucType.equals("AIR")) // return 'I'; // if (ucType.equals("R")) return 'R'; if (ucType.equals("REX")) // RegionalExpress return 'R'; // if (ucType.equals("ZUG")) // return 'R'; // if (ucType.equals("EZ")) // Erlebniszug // return 'R'; // if (ucType.equals("S2")) // Helsinki-Turku // return 'R'; if (ucType.equals("RB")) // RegionalBahn Deutschland return 'R'; if (ucType.equals("RE")) // RegionalExpress Deutschland return 'R'; // if (ucType.equals("DPN")) // TODO nicht evtl. doch eher ne S-Bahn? // return 'R'; // if (ucType.equals("VIA")) // return 'R'; // if (ucType.equals("PCC")) // Polen // return 'R'; // if (ucType.equals("KM")) // Polen // return 'R'; // if (ucType.equals("SKM")) // Polen // return 'R'; // if (ucType.equals("SKW")) // Polen // return 'R'; // if (ucType.equals("WKD")) // Warszawska Kolej Dojazdowa, Polen // return 'R'; // if (ucType.equals("IR")) // Polen // return 'R'; // if (ucType.equals("OS")) // Chop-Cierna nas Tisou // return 'R'; // if (ucType.equals("SP")) // Polen // return 'R'; // if (ucType.equals("EX")) // Polen // return 'R'; // if (ucType.equals("E")) // Budapest, Ungarn // return 'R'; // if (ucType.equals("IP")) // Ozd, Ungarn // return 'R'; // if (ucType.equals("ZR")) // Bratislava, Slovakai // return 'R'; // if (ucType.equals("CAT")) // Stockholm-Arlanda, Arlanda Express // return 'R'; // if (ucType.equals("RT")) // Deutschland // return 'R'; // if (ucType.equals("IRE")) // Interregio Express // return 'R'; // if (ucType.equals("N")) // Frankreich, Tours // return 'R'; // if (ucType.equals("DPF")) // VX=Vogtland Express // return 'R'; if (ucType.equals("S")) return 'S'; if (ucType.equals("RSB")) // Schnellbahn Wien return 'S'; // if (ucType.equals("RER")) // Réseau Express Régional, Frankreich // return 'S'; if (ucType.equals("U")) return 'U'; if (ucType.equals("STR")) return 'T'; // if (ucType.equals("LKB")) // return 'T'; if (ucType.equals("WLB")) // via JSON API return 'T'; if (ucType.equals("BUS")) return 'B'; // if (ucType.equals("RFB")) // return 'B'; // if (ucType.equals("OBU")) // return 'B'; if (ucType.equals("AST")) return 'B'; if (ucType.equals("ASTSV")) // via JSON API return 'B'; if (ucType.equals("ICB")) // ÖBB ICBus return 'B'; // if (ucType.equals("FB")) // Polen // return 'B'; // if (ucType.equals("BSV")) // Deutschland // return 'B'; // if (ucType.equals("LT")) // Linien-Taxi // return 'B'; if (ucType.equals("BUSSV")) // via JSON API return 'B'; if (ucType.equals("O-B")) // Stadtbus, via JSON API return 'B'; // if (ucType.equals("SCH")) // return 'F'; // if (ucType.equals("AS")) // SyltShuttle // return 'F'; // // if (ucType.equals("SB")) // return 'C'; // if (ucType.equals("LIF")) // return 'C'; // // if (ucType.equals("U70")) // U.K. // return '?'; // if (ucType.equals("R84")) // return '?'; // if (ucType.equals("S84")) // return '?'; // if (ucType.equals("T84")) // return '?'; return 0; } private static final Map LINES = new HashMap(); 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)); } }