package de.tum.in.tumcampusapp.managers; import android.content.Context; import android.database.Cursor; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; import de.tum.in.tumcampusapp.R; import de.tum.in.tumcampusapp.auxiliary.DateUtils; import de.tum.in.tumcampusapp.models.cafeteria.Location; /** * Location manager, handles database stuff */ public class OpenHoursManager extends AbstractManager { /** * Constructor, open/create database, create table if necessary * * @param context Context */ public OpenHoursManager(Context context) { super(context); // create table if needed db.execSQL("CREATE TABLE IF NOT EXISTS locations (id INTEGER PRIMARY KEY, category VARCHAR, " + "name VARCHAR, address VARCHAR, room VARCHAR, transport VARCHAR, " + "hours VARCHAR, remark VARCHAR, url VARCHAR)"); } /** * Checks if the locations table is empty * * @return true if no locations are available, else false */ public boolean empty() { boolean result = true; Cursor c = db.rawQuery("SELECT id FROM locations LIMIT 1", null); if (c.moveToNext()) { result = false; } c.close(); return result; } /** * Get all locations by category from the database * * @param category String Location category, e.g. library, cafeteria * @return Database cursor (name, address, room, transport, hours, remark, * url, _id) */ public Cursor getAllHoursFromDb(String category) { return db.rawQuery( "SELECT name, address, room, transport, hours, remark, url, id as _id " + "FROM locations WHERE category=? ORDER BY name", new String[]{category}); } /** * Get opening hours for a specific location * * @param id Location ID, e.g. 100 * @return hours */ String getHoursById(int id) { String result = ""; Cursor c = db.rawQuery("SELECT hours FROM locations WHERE id=?", new String[]{String.valueOf(id)}); if (c.moveToNext()) { result = c.getString(0); } c.close(); return result; } /** * Converts the opening hours into more readable format. * e.g. Opening in 2 hours. * HINT: Currently only works for cafeterias, and institutions * that have Mo-Do xx-yy.yy, Fr aa-bb and Mo-Fr xx-yy format * * @param context Context * @param id Location ID, e.g. 100 * @param date Relative date * @return Readable opening string */ public String getHoursByIdAsString(Context context, int id, Date date) { String result = this.getHoursById(id); //Check which week day we have Calendar cal = new GregorianCalendar(); cal.setTime(date); int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); //Split up the data string from the database with regex which has the format: "Mo-Do 11-14, Fr 11-13.45" or "Mo-Fr 9-20" Matcher m = Pattern.compile("([a-z]{2}?)[-]?([a-z]{2}?)? ([0-9]{1,2}(?:[\\.][0-9]{2}?)?)-([0-9]{1,2}(?:[\\.][0-9]{2}?)?)", Pattern.CASE_INSENSITIVE).matcher(result); //Capture groups for: Mo-Do 9-21.30 //#0 Mo-Do 9-21.30 //#1 Mo //#2 Do //#3 9 //#4 21.30 //Find the first part String[] time = new String[2]; if (m.find()) { //We are currently in Mo-Do/Fr, when this weekday is in that range we have our result or we check if the current range is valid for fridays also if (dayOfWeek <= Calendar.THURSDAY || m.group(2).equalsIgnoreCase("fr")) { time[0] = m.group(3); time[1] = m.group(4); } else { //Otherwise we need to move to the next match if (m.find()) { //Got a match, data should be in capture groups 3/4 time[0] = m.group(3); time[1] = m.group(4); } else { //No match found, return return ""; } } } else { //No match found, return return ""; } //Convert time to workable calender objects Calendar now = Calendar.getInstance(); Calendar opens = strToCal(date, time[0]); Calendar closes = strToCal(date, time[1]); //Check the relativity Calendar relativeTo; int relation; if (opens.after(now)) { relation = R.string.opens; relativeTo = opens; } else if (closes.after(now)) { relation = R.string.closes; relativeTo = closes; } else { relation = R.string.closed; relativeTo = closes; } //Get the relative string String relStr = DateUtils.getFutureTime(relativeTo.getTime(), context); //Return an assembly return context.getString(relation) + " " + relStr.substring(0, 1).toLowerCase(Locale.getDefault()) + relStr.substring(1); } private static Calendar strToCal(Date date, String time) { Calendar opens = Calendar.getInstance(); opens.setTime(date); if (time.contains(".")) { int hour = Integer.parseInt(time.substring(0, time.indexOf('.'))); int min = Integer.parseInt(time.substring(time.indexOf('.') + 1)); opens.set(Calendar.HOUR_OF_DAY, hour); opens.set(Calendar.MINUTE, min); } else { opens.set(Calendar.HOUR_OF_DAY, Integer.parseInt(time)); opens.set(Calendar.MINUTE, 0); } return opens; } /** * Replaces a location in the database * * @param l Location object */ public void replaceIntoDb(Location l) { if (l.id <= 0) { throw new IllegalArgumentException("Invalid id."); } if (l.name.isEmpty()) { throw new IllegalArgumentException("Invalid name."); } db.execSQL("REPLACE INTO locations (id, category, name, address, room, " + "transport, hours, remark, url) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", new String[]{String.valueOf(l.id), l.category, l.name, l.address, l.room, l.transport, l.hours, l.remark, l.url}); } }