Android Open Source - grtransit Service Calendar






From Project

Back to project page grtransit.

License

The source code is released under:

GNU General Public License

If you think the Android project grtransit listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright 2011 Giles Malet./*  w  ww.  j  ava2  s.  c om*/
 *
 * This file is part of GRTransit.
 * 
 * GRTransit 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.
 * 
 * GRTransit 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 GRTransit.  If not, see <http://www.gnu.org/licenses/>.
 */

package net.kw.shrdlu.grtgtfs;

import android.database.Cursor;
import android.text.format.Time;
import android.util.Log;
import android.util.TimeFormatException;

import java.util.ArrayList;
import java.util.HashMap;

public class ServiceCalendar {
  private static final String TAG = "ServiceCalendar";
  private static final String mDBQuery = "select * from calendar where service_id = ?";
  private static final String mDBQueryDate = "select * from calendar_dates where service_id = ? and date = ?";

  // Cache some results, to save db lookups
  private static final HashMap<String, String> truemap = new HashMap<>(32);
  private static final HashMap<String, String> falsemap = new HashMap<>(32);
  private static final HashMap<String, String> trip2servicemap = new HashMap<>(64);

  // Match day number to a string and an abbreviation
  private static final String[] mWeekDays = { "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" };
  private static final String[] mWeekDaysAbbrev = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

  public ServiceCalendar() {
    // Log.v(TAG, "ServiceCalendar()");
  }

  // Return string showing days this bus runs.
  // Cursor points to a row in the calendar table for this service_id.
  private static String getDays(Cursor csr) {
    String days = "";

    for (int i = 0; i < 7; i++) {
      if (csr.getInt(csr.getColumnIndex(mWeekDays[i])) == 1) {
        days += mWeekDaysAbbrev[i] + " ";
      }
    }

    return days;
  }

  // Do the actual work of the getDays() call, but it makes
  // sure we close the cursor on exit.
  private static String process_db(String service_id, String date, boolean limit, Cursor csr) {

    if (!csr.moveToFirst()) {
      return null;
    }

    // Make sure it's in a current schedule period
    final String start = csr.getString(csr.getColumnIndex("start_date"));
    final String end = csr.getString(csr.getColumnIndex("end_date"));
    if (date.compareTo(start) < 0 || date.compareTo(end) > 0) {
      // return "Schedule data has expired!";
      return null;
    }

    // If we're not limiting the display, return what we have
    if (!limit) {
      return getDays(csr);
    }

    // Check for exceptions
    final String[] selectargs = { service_id, date };
    final Cursor exp = DatabaseHelper.ReadableDB().rawQuery(mDBQueryDate, selectargs);
    if (exp.moveToFirst()) {
      final int exception = exp.getInt(exp.getColumnIndex("exception_type"));
      exp.close();
      if (exception == 2) {
        return null;
      }
      if (exception == 1) {
        return getDays(csr); // service added for this day
      }
      Log.e(TAG, "bogus exception type " + exception + " for service " + service_id + "!");
      return null;
    } else {
      exp.close();
    }

    // Check if the bus runs on the given day of the week.
    final Time t = new Time();
    try {
      t.parse(date);
      t.normalize(false);
    } catch (final TimeFormatException e) {
      Log.e(TAG, "got bogus date \"" + date + "\"");
      return null;
    }
    final int weekday = t.weekDay; // 0--6
    if (csr.getInt(csr.getColumnIndex(mWeekDays[weekday])) == 1) {
      return getDays(csr);
    }

    return null; // doesn't run on given date.
  }

  // Return a string showing the days a bus runs, or null if it doesn't
  // run on the given date. Limit to correct days of week, or not.
  private static String getTripDaysofWeek(String trip_id, String date, boolean limit) {

    String retstr;

    // Get and translate the service id
    String service_id;
    if (trip2servicemap.containsKey(trip_id)) {
      service_id = trip2servicemap.get(trip_id);
    } else {
      final String svsq = "select service_id from trips where trip_id = ?";
      final String[] svsargs = { trip_id };
      final Cursor svs = DatabaseHelper.ReadableDB().rawQuery(svsq, svsargs);
      svs.moveToFirst();
      service_id = svs.getString(0);
      svs.close();
      if (service_id != null && !service_id.equals("")) {
        trip2servicemap.put(trip_id, service_id);
      }
    }
    if (service_id == null) {
      return null;
    }

    // First check the cache
    if (limit) {
      if (truemap.containsKey(service_id + date)) {
        retstr = truemap.get(service_id + date);
        // Log.v(TAG, "Retrieved " + service_id+":"+date + " -> " + retstr + " from truecache");
        return retstr;
      }
    } else {
      if (falsemap.containsKey(service_id + date)) {
        retstr = falsemap.get(service_id + date);
        // Log.v(TAG, "Retrieved " + service_id+":"+date + " -> " + retstr + " from falsecache");
        return retstr;
      }
    }

    final String[] selectargs = { service_id };
    final Cursor csr = DatabaseHelper.ReadableDB().rawQuery(mDBQuery, selectargs);
    retstr = process_db(service_id, date, limit, csr);
    csr.close();

    // Save in cache
    if (limit) {
      truemap.put(service_id + date, retstr);
    } else {
      falsemap.put(service_id + date, retstr);
    }

    return retstr;
  }

  /* Return a list of times that all busses for all routes depart a given stop, sorted by time. List is departure_time,
   * route_id, trip_headsign. */
  public static ArrayList<String[]> getRouteDepartureTimes(String stopid, String date, boolean limittotoday,
      NotificationCallback task) {

    final String q = "select distinct departure_time as _id, trips.trip_id, routes.route_short_name, trip_headsign from stop_times "
        + "join trips on stop_times.trip_id = trips.trip_id " + "join routes on routes.route_id = trips.route_id  "
        + "where stop_id = ? order by departure_time";
    final String[] selectargs = new String[] { stopid };
    final Cursor csr = DatabaseHelper.ReadableDB().rawQuery(q, selectargs);

    // Load the array for the list
    final int maxcount = csr.getCount();
    int progresscount = 0;
    final ArrayList<String[]> listdetails = new ArrayList<>(maxcount);

    boolean more = csr.moveToFirst();
    while (more) {

      final String trip_id = csr.getString(1);
      final String daysstr = ServiceCalendar.getTripDaysofWeek(trip_id, date, limittotoday);

      // Only add if the bus runs on this day.
      if (daysstr != null) {
        listdetails.add(new String[] { csr.getString(0), daysstr, csr.getString(2), csr.getString(3) });
      }

      if (task != null) {
        task.notificationCallback((int) ((++progresscount / (float) maxcount) * 10000));
      }

      more = csr.moveToNext();
    }
    csr.close();

    return listdetails;
  }

  /* Return a list of times that all busses for a given route depart a given stop, sorted by time. List is departure_times,
   * days of week the bus runs, and trip_id. */
  public static ArrayList<String[]> getRouteDepartureTimes(String stopid, String routeid, String headsign, String date,
      boolean limittotoday, NotificationCallback task) {

    final String q = "select distinct departure_time as _id, trip_id from stop_times where stop_id = ? and trip_id in "
        + "(select trip_id from trips where route_id = ? and trip_headsign = ?) order by departure_time";
    final String[] selectargs = new String[] { stopid, routeid, headsign };
    final Cursor csr = DatabaseHelper.ReadableDB().rawQuery(q, selectargs);

    // Load the array for the list
    final int maxcount = csr.getCount();
    int progresscount = 0;
    final ArrayList<String[]> listdetails = new ArrayList<>(maxcount);

    boolean more = csr.moveToFirst();
    while (more) {

      final String trip_id = csr.getString(1);
      final String daysstr = ServiceCalendar.getTripDaysofWeek(trip_id, date, limittotoday);

      // Only add if the bus runs on this day.
      if (daysstr != null) {
        listdetails.add(new String[] { csr.getString(0), daysstr, csr.getString(1) });
      }

      if (task != null) {
        task.notificationCallback((int) ((++progresscount / (float) maxcount) * 10000));
      }

      more = csr.moveToNext();
    }
    csr.close();

    return listdetails;
  }

  /* Return the time and route details of the next bus for any route, or null if there isn't one today. */
  public static String[] getNextDepartureTime(String stopid, String date) {

    final ArrayList<String[]> listdetails = getRouteDepartureTimes(stopid, date, true, null);

    if (listdetails == null) {
      return null;
    }

    final Time t = new Time();
    t.setToNow();
    final String timenow = String.format("%02d:%02d:%02d", t.hour, t.minute, t.second);

    // Find when the next bus leaves
    for (int i = 0; i < listdetails.size(); i++) {
      final String departure_time = listdetails.get(i)[0];
      if (departure_time.compareTo(timenow) >= 0) {
        return new String[] { departure_time, listdetails.get(i)[2], listdetails.get(i)[3] };
      }
    }

    // No more busses today.
    return null;
  }

  /* Return the time of the next bus for a given route, or null if there isn't one today. */
  public static String getNextDepartureTime(String stopid, String routeid, String headsign, String date) {

    final ArrayList<String[]> listdetails = getRouteDepartureTimes(stopid, routeid, headsign, date, true, null);

    if (listdetails == null) {
      return null;
    }

    final Time t = new Time();
    t.setToNow();
    final String timenow = String.format("%02d:%02d:%02d", t.hour, t.minute, t.second);

    // Find when the next bus leaves
    for (int i = 0; i < listdetails.size(); i++) {
      final String departure_time = listdetails.get(i)[0];
      if (departure_time.compareTo(timenow) >= 0) {
        return departure_time;
      }
    }

    // No more busses today.
    return null;
  }

  /* Return a properly formatted time. Assumes nn:nn[:nn] input somewhere in the string, may return just that, or convert and
   * add annoying American `am/pm' suffix. */
  public static String formattedTime(String time) {
    final int i = time.indexOf(':'); // Take note of where first colon is
    final int j = time.lastIndexOf(':'); // and the last.

    if (i < 0) {
      return time; // strange?
    }

    String newtime;

    // If the string contains seconds, which are always zero, truncate them.
    if (j == i + 3 && time.substring(j, j + 3).contentEquals(":00")) {
      newtime = time.substring(0, j) + time.substring(j + 3);
    } else {
      newtime = time;
    }

    if (!GRTApplication.mPreferences.showAMPMTimes()) {
      return newtime.replaceFirst(":", "h");
    }

    final String AM = "am", PM = "pm";

    // Hopefully we actually have a time
    if (i > 0) {
      int hours;
      try {
        hours = Integer.parseInt(newtime.substring(i - 2, i));
      } catch (final NumberFormatException e) {
        Log.d(TAG, "NumberFormatException: " + e.getMessage() + ", for time `" + newtime + "'");
        return newtime;
      }
      String prefix = AM;

      if (hours >= 12 && hours < 24) {
        prefix = PM;
        if (hours > 12) {
          hours -= 12;
        }
      }
      if (hours >= 24) {
        if (hours == 24) {
          hours = 12;
        } else {
          hours -= 24;
        }
      }

      // Reformat to drop leading zero, add prefix
      final int where = newtime.indexOf(" ", i); // to put the suffix
      if (where > 0) {
        newtime = String.format("%s%d%s%s%s", newtime.subSequence(0, i - 2), hours, newtime.substring(i, where),
            prefix, newtime.substring(where));
      } else { // stick it on the end
        newtime = String.format("%s%d%s%s", newtime.subSequence(0, i - 2), hours, newtime.substring(i), prefix);
      }
    }

    return newtime;
  }
}




Java Source Code List

net.kw.shrdlu.grtgtfs.DatabaseHelper.java
net.kw.shrdlu.grtgtfs.GRTApplication.java
net.kw.shrdlu.grtgtfs.NavOptions.java
net.kw.shrdlu.grtgtfs.NotificationCallback.java
net.kw.shrdlu.grtgtfs.Preferences.java
net.kw.shrdlu.grtgtfs.RouteOverlay.java
net.kw.shrdlu.grtgtfs.ServiceCalendar.java
net.kw.shrdlu.grtgtfs.StopsOverlay.java
net.kw.shrdlu.grtgtfs.Activities.ClosestStopsActivity.java
net.kw.shrdlu.grtgtfs.Activities.FavstopsActivity.java
net.kw.shrdlu.grtgtfs.Activities.MenuListActivity.java
net.kw.shrdlu.grtgtfs.Activities.MenuMapActivity.java
net.kw.shrdlu.grtgtfs.Activities.PrefsActivity.java
net.kw.shrdlu.grtgtfs.Activities.RiderAlertsActivity.java
net.kw.shrdlu.grtgtfs.Activities.RouteActivity.java
net.kw.shrdlu.grtgtfs.Activities.RouteselectActivity.java
net.kw.shrdlu.grtgtfs.Activities.SearchActivity.java
net.kw.shrdlu.grtgtfs.Activities.StartupActivity.java
net.kw.shrdlu.grtgtfs.Activities.StopsActivity.java
net.kw.shrdlu.grtgtfs.Activities.TimesActivity.java
net.kw.shrdlu.grtgtfs.Activities.TripStopsActivity.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.FavstopsArrayAdapter.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.ListArrayAdapter.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.ListCursorAdapter.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.NavDrawerItem.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.NavDrawerListAdapter.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.TimeStopdescArrayAdapter.java
net.kw.shrdlu.grtgtfs.LayoutAdapters.TimesArrayAdapter.java