From f447a59e88500802d05b5c205882d499c3a9b4c4 Mon Sep 17 00:00:00 2001 From: sanderd17 Date: Wed, 8 Aug 2012 14:30:37 +0300 Subject: [PATCH 1/9] Update interface openinghours an update to the new interface, no features changed --- .../src/net/osmand/plus/osmedit/EditingPOIActivity.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/osmedit/EditingPOIActivity.java b/OsmAnd/src/net/osmand/plus/osmedit/EditingPOIActivity.java index c6310f75f6..18995d8049 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/EditingPOIActivity.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/EditingPOIActivity.java @@ -17,6 +17,7 @@ import net.osmand.osm.Node; import net.osmand.osm.OSMSettings.OSMTagKey; import net.osmand.osm.OpeningHoursParser; import net.osmand.osm.OpeningHoursParser.BasicDayOpeningHourRule; +import net.osmand.osm.OpeningHoursParser.OpeningHours; import net.osmand.osm.OpeningHoursParser.OpeningHoursRule; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; @@ -323,7 +324,7 @@ public class EditingPOIActivity implements DialogProvider { private Dialog createOpenHoursDlg(){ - List time = OpeningHoursParser.parseOpenedHours(openingHours.getText().toString()); + OpeningHours time = OpeningHoursParser.parseOpenedHours(openingHours.getText().toString()); if(time == null){ AccessibleToast.makeText(ctx, ctx.getString(R.string.opening_hours_not_supported), Toast.LENGTH_LONG).show(); return null; @@ -332,7 +333,7 @@ public class EditingPOIActivity implements DialogProvider { List simple = null; if(time != null){ simple = new ArrayList(); - for(OpeningHoursRule r : time){ + for(OpeningHoursRule r : time.getRules()){ if(r instanceof BasicDayOpeningHourRule){ simple.add((BasicDayOpeningHourRule) r); } else { @@ -348,7 +349,8 @@ public class EditingPOIActivity implements DialogProvider { builder.setPositiveButton(ctx.getString(R.string.default_buttons_apply), new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which) { - openingHours.setText(OpeningHoursParser.toStringOpenedHours(v.getTime())); + OpeningHours oh = new OpeningHours((ArrayList) v.getTime()); + openingHours.setText(oh.toString()); ctx.removeDialog(DIALOG_OPENING_HOURS); } }); From 344344150f3ee4312eed00842c699c7d9359cfb6 Mon Sep 17 00:00:00 2001 From: sanderd17 Date: Wed, 8 Aug 2012 14:36:41 +0300 Subject: [PATCH 2/9] Better parsing, all logic gathered in one class --- .../net/osmand/osm/OpeningHoursParser.java | 445 ++++++++++++++---- 1 file changed, 343 insertions(+), 102 deletions(-) diff --git a/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java b/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java index 619344567a..825fab16c7 100644 --- a/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java +++ b/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java @@ -1,48 +1,260 @@ package net.osmand.osm; + + + import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; -import java.util.List; + +/** + * Class used to parse opening hours + * + * the method "parseOpenedHours" will parse an OSM opening_hours string and return + * an object of the type OpeningHours. That object can be used to check if the OSM feature + * is open at a certain time. + */ public class OpeningHoursParser { private static final String[] daysStr = new String[] {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ + /** + * This class contains the entire OpeningHours schema and + * offers methods to check directly weather something is open + * + * @author sander + */ + public static class OpeningHours { + + /** + * list of the different rules + */ + private ArrayList rules; + + /** + * Constructor + * + * @param rules List of OpeningHoursRule to be given + */ + public OpeningHours(ArrayList rules) { + this.rules = rules; + } + + /** + * Empty constructor + */ + public OpeningHours(){ + rules = new ArrayList(); + } + + /** + * add a rule to the opening hours + * @param r rule to add + */ + public void addRule(OpeningHoursRule r){ + rules.add(r); + } + + /** + * return the list of rules + * + * @return the rules + */ + public ArrayList getRules(){ + return rules; + } + + /** + * check if the feature is opened at time "cal" + * @param cal the time to check + * @return true if feature is open + */ + public boolean isOpenedForTime(Calendar cal){ + /* + * first check for rules that contain the current day + * afterwards check for rules that contain the previous + * day with overlapping times (times after midnight) + */ + boolean isOpenDay = false; + for (OpeningHoursRule r : rules){ + if(r.containsDay(cal)){ + isOpenDay = r.isOpenedForTime(cal, false); + } + } + boolean isOpenPrevious = false; + for (OpeningHoursRule r : rules){ + if(r.containsPreviousDay(cal)){ + isOpenPrevious = r.isOpenedForTime(cal, true); + } + } + return isOpenDay || isOpenPrevious; + } + + @Override + public String toString(){ + StringBuilder s = new StringBuilder(); + + for (OpeningHoursRule r : rules) { + s.append(r.toString()).append("; "); + } + + return s.toString(); + } + + } + + /** + * Interface to represent a single rule + * + * A rule consist out of + * - a collection of days/dates + * - a time range + */ public static interface OpeningHoursRule { - public boolean isOpenedForTime(Calendar cal); + /** + * Check if, for this rule, the feature is opened for time "cal" + * @param cal the time to check + * @param checkPrevious only check for overflowing times (after midnight) or don't check for it + * @return true if the feature is open + */ + public boolean isOpenedForTime(Calendar cal, boolean checkPrevious); + + /** + * Check if the previous day before "cal" is part of this rule + * @param cal; the time to check + * @return true if the previous day is part of the rule + */ + public boolean containsPreviousDay(Calendar cal); + + /** + * Check if the day of "cal" is part of this rule + * @param cal; the time to check + * @return true if the day is part of the rule + */ + public boolean containsDay(Calendar cal); public String toRuleString(); } + /** + * implementation of the basic OpeningHoursRule + * + * This implementation only supports day of weeks and numeral times, or the value "off" + * + */ public static class BasicDayOpeningHourRule implements OpeningHoursRule { + /** + * represents the list on which days it is open. + * Day number 0 is ???? TODO + */ private boolean[] days = new boolean[7]; - private int startTime = -1; - private int endTime = -1; + /** + * lists of equal size representing the start and end times + */ + private int[] startTimes, endTimes; + /** + * return an array representing the days of the rule + * @return the days of the rule + */ public boolean[] getDays() { return days; } - public void setStartEndTime(int startTime, int endTime) { - this.startTime = startTime; - this.endTime = endTime; + @Deprecated + /** + * set a single start time, erase all previously added start times + * @param s startTime to set + */ + public void setStartTime(int s) { + startTimes = new int[]{s}; + if(endTimes.length != 1) { + endTimes = new int[]{0}; + } } + @Deprecated + /** + * set a single end time, erase all previously added end times + * @param e endTime to set + */ + public void setEndTime(int e) { + endTimes = new int[]{e}; + if(startTimes.length != 1) { + startTimes = new int[]{0}; + } + } + + /** + * get a single start time + * @return a single start time + */ public int getStartTime() { - return startTime; + try { + return startTimes[0]; + } catch (Exception e){ + return 0; + } } + /** + * get a single end time + * @return a single end time + */ public int getEndTime() { - return endTime; + try { + return endTimes[0]; + } catch (Exception e){ + return 0; + } + } + + @Override + /** + * Check if the weekday of time "cal" is part of this rule + * @param cal the time to check + * @return true if this day is part of the rule + */ + public boolean containsDay(Calendar cal){ + int i = cal.get(Calendar.DAY_OF_WEEK); + int d = (i + 5) % 7; + if (days[d]) { + return true; + } + return false; + + } + + @Override + /** + * Check if the previous weekday of time "cal" is part of this rule + * @param cal the time to check + * @return true if the previous day is part of the rule + */ + public boolean containsPreviousDay(Calendar cal){ + int i = cal.get(Calendar.DAY_OF_WEEK); + int p = (i + 4) % 7; + if (days[p]) { + return true; + } + return false; + } @Override - public boolean isOpenedForTime(Calendar cal) { - if (startTime == -1) { + /** + * Check if this rule says the feature is open at time "cal" + * @param cal the time to check + * @return true if this rule contains the day to check and the start and end times denote it's open + * @return true if this rule contains the previous day and an endTime>startTime such that the time to check falls before the endtime + * @return false in all other cases, also if only day is wrong + */ + public boolean isOpenedForTime(Calendar cal, boolean checkPrevious) { + if (startTimes == null) { return false; } int i = cal.get(Calendar.DAY_OF_WEEK); @@ -52,26 +264,29 @@ public class OpeningHoursParser { p += 7; } int time = cal.get(Calendar.HOUR_OF_DAY) * 60 + cal.get(Calendar.MINUTE); - int startTime = this.startTime; - int endTime = this.endTime; - // one day working 10 - 20 (not 20 - 04) - if (startTime < endTime || endTime == -1) { - if (days[d]) { - if (time >= startTime && (endTime == -1 || time <= endTime)) { + for (i = 0; i= startTime && (endTime == -1 || time <= endTime)) { + return true; + } + } + } else { + if (time >= startTime && days[p] && checkPrevious) { + // check in previous day + return true; + } else if (time <= endTime && days[d] && !checkPrevious) { return true; } } - } else { - if (time >= startTime && days[p]) { - // check in previous day - return true; - } else if (time <= endTime && days[d]) { - // check in previous day - return true; - } } return false; } + + @Override public String toRuleString() { StringBuilder b = new StringBuilder(25); @@ -98,17 +313,26 @@ public class OpeningHoursParser { open24_7 = false; } } - if (open24_7 && startTime == 0 && endTime / 60 == 24) { - return "24/7"; + if (startTimes == null || startTimes.length == 0){ + b.append(" off "); + } else { + for (int i = 0; i rs){ + /** + * Parse an opening_hours string from OSM to an OpeningHours object which can be used to check + * @param r the string to parse + * @param rs the resulting object representing the opening hours of the feature + * @return true if the String is successfully parsed + */ + public static boolean parseRule(String r, OpeningHours rs){ int startDay = -1; int previousDay = -1; int k = 0; @@ -136,9 +383,9 @@ public class OpeningHoursParser { boolean[] days = basic.getDays(); if("24/7".equals(r)){ Arrays.fill(days, true); - basic.setStartEndTime(0, 24*60); - rs.add(basic); - return basic; + basic.addTimeRange(0, 24*60); + rs.addRule(basic); + return true; } for (; k < r.length(); k++) { @@ -147,13 +394,17 @@ public class OpeningHoursParser { // time starts break; } + if (ch == 'o' && r.charAt(k+1) == 'f' && r.charAt(k+1) == 'f'){ + // value "off" is found + break; + } if(Character.isWhitespace(ch) || ch == ','){ continue; } else if(ch == '-'){ if(previousDay != -1){ startDay = previousDay; } else { - return null; + return false; } } else if(k < r.length() - 1){ int i = 0; @@ -175,11 +426,11 @@ public class OpeningHoursParser { previousDay = i; } } else { - return null; + return false; } } if(previousDay == -1){ - return null; + return false; } String timeSubstr = r.substring(k); String[] times = timeSubstr.split(","); @@ -189,6 +440,9 @@ public class OpeningHoursParser { if(time.length() == 0){ continue; } + if(time.equals("off")){ + break; // add no time values + } String[] stEnd = time.split("-"); //$NON-NLS-1$ if (stEnd.length != 2) { continue; @@ -200,60 +454,47 @@ public class OpeningHoursParser { int i1 = stEnd[0].indexOf(':'); int i2 = stEnd[1].indexOf(':'); if (i1 == -1 || i2 == -1) { - return null; + return false; } st = Integer.parseInt(stEnd[0].substring(0, i1).trim()) * 60 + Integer.parseInt(stEnd[0].substring(i1 + 1).trim()); end = Integer.parseInt(stEnd[1].substring(0, i2).trim()) * 60 + Integer.parseInt(stEnd[1].substring(i2 + 1).trim()); } catch (NumberFormatException e) { - return null; + return false; } - basic.setStartEndTime(st, end); - rs.add(basic); - BasicDayOpeningHourRule nbasic = new BasicDayOpeningHourRule(); - nbasic.days = basic.days; - basic = nbasic; + basic.addTimeRange(st, end); } + rs.addRule(basic); if(!timesExist){ - return null; + return false; } - return basic; + return true; } - - public static List parseOpenedHours(String format){ + /** + * parse OSM opening_hours string to an OpeningHours object + * @param format the string to parse + * @return the OpeningHours object when parsing was successful + * @return null when parsing was unsuccessful + */ + public static OpeningHours parseOpenedHours(String format){ + // split the OSM string in multiple rules String[] rules = format.split(";"); //$NON-NLS-1$ - List rs = new ArrayList(); + OpeningHours rs = new OpeningHours(); for(String r : rules){ r = r.trim(); if(r.length() == 0){ continue; } // check if valid - OpeningHoursRule rule = parseRule(r, rs); - if(rule == null){ + boolean rule = parseRule(r, rs); + if(!rule){ return null; } } return rs; } - public static String toStringOpenedHours(List rules){ - StringBuilder b = new StringBuilder(100); - // check 24/7 - boolean first = true; - for (OpeningHoursRule p : rules) { - if(p == null){ - continue; - } - if (first) { - first = false; - } else { - b.append("; "); //$NON-NLS-1$ - } - b.append(p.toRuleString()); - } - - return b.toString(); - } + + private static void formatTime(int h, int t, StringBuilder b){ if(h < 10){ b.append("0"); //$NON-NLS-1$ @@ -265,39 +506,39 @@ public class OpeningHoursParser { b.append(t); } - private static void testOpened(String time, List hours, boolean expected) throws ParseException { - boolean opened = false; + + private static void testOpened(String time, OpeningHours hours, boolean expected) throws ParseException { Calendar cal = Calendar.getInstance(); cal.setTime(new SimpleDateFormat("dd.MM.yyyy hh:mm").parse(time)); - for(OpeningHoursRule r : hours) { - if(r.isOpenedForTime(cal)){ - opened = true; - break; - } - } - System.out.println("Expected " + expected +" = " + opened); + System.out.println("Expected " + time+": " + expected +" = " + hours.isOpenedForTime(cal)); } public static void main(String[] args) throws ParseException { - - List hours = parseOpenedHours("Mo-Fr 08:30-14:40; Sa 08:00 - 14:00"); //$NON-NLS-1$ + //Test basic case + OpeningHours hours = parseOpenedHours("Mo-Fr 08:30-14:40" ); //$NON-NLS-1$ System.out.println(hours); - System.out.println(toStringOpenedHours(hours)); - hours = parseOpenedHours("Mo-Fr 08:30-14:40,15:00-19:00"); //$NON-NLS-1$ - testOpened("20.04.2012 14:00", hours, true); - testOpened("20.04.2012 15:00", hours, true); - testOpened("20.04.2012 14:50", hours, false); + testOpened("09.08.2012 12:00", hours, true); + testOpened("09.08.2012 16:00", hours, false); + // two time and date ranges + hours = parseOpenedHours("Mo-We, Fr 08:30-14:40,15:00-19:00"); //$NON-NLS-1$ System.out.println(hours); - System.out.println(toStringOpenedHours(hours)); - hours = parseOpenedHours("Mo, We-Fr, Th, Sa 08:30-14:40; Sa 08:00 - 14:00"); //$NON-NLS-1$ + testOpened("08.08.2012 14:00", hours, true); + testOpened("10.08.2012 15:00", hours, true); + testOpened("08.08.2012 14:50", hours, false); + // test exception on general schema + hours = parseOpenedHours("Mo-Sa 08:30-14:40; Tu 08:00 - 14:00"); //$NON-NLS-1$ System.out.println(hours); - System.out.println(toStringOpenedHours(hours)); - hours = parseOpenedHours("Mo-Su 00:00-24:00"); //$NON-NLS-1$ + testOpened("07.08.2012 14:20", hours, false); + // test off value + hours = parseOpenedHours("Mo-Sa 00:00-24:00; Th off"); //$NON-NLS-1$ System.out.println(hours); - System.out.println(toStringOpenedHours(hours)); + testOpened("08.08.2012 23:59", hours, true); + testOpened("09.08.2012 00:15", hours, false); + //test 24/7 hours = parseOpenedHours("24/7"); //$NON-NLS-1$ System.out.println(hours); - System.out.println(toStringOpenedHours(hours)); + testOpened("08.08.2012 23:59", hours, true); } } + From 1864074f1b078c9e5104145a118c4c57792a5712 Mon Sep 17 00:00:00 2001 From: sanderd17 Date: Wed, 8 Aug 2012 14:37:19 +0300 Subject: [PATCH 3/9] Update interface openinghours --- .../src/net/osmand/osm/util/AHSupermarketResolver.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DataExtractionOSM/src/net/osmand/osm/util/AHSupermarketResolver.java b/DataExtractionOSM/src/net/osmand/osm/util/AHSupermarketResolver.java index 928ca77814..5152d82443 100644 --- a/DataExtractionOSM/src/net/osmand/osm/util/AHSupermarketResolver.java +++ b/DataExtractionOSM/src/net/osmand/osm/util/AHSupermarketResolver.java @@ -191,7 +191,7 @@ public class AHSupermarketResolver { newTags.put("addr:postcode", props.get("zip")+""); JSONArray o = (JSONArray) props.get("hours"); - List rules = new ArrayList(); + OpeningHoursParser.OpeningHours rules = new OpeningHoursParser.OpeningHours(); BasicDayOpeningHourRule prev = null; for(int i=0; i<7; i++){ JSONObject obj = o.getJSONObject(i); @@ -207,14 +207,14 @@ public class AHSupermarketResolver { } else { BasicDayOpeningHourRule rule = new OpeningHoursParser.BasicDayOpeningHourRule(); rule.getDays()[i] = true; - rule.setStartEndTime(start, end); + rule.addTimeRange(start, end); prev = rule; - rules.add(rule); + rules.addRule(rule); } } } - newTags.put("opening_hours", OpeningHoursParser.toStringOpenedHours(rules)); + newTags.put("opening_hours", rules.toString()); // Check distance to info LatLon real = new LatLon((Double)props.get("lat"), (Double) props.get("lng")); From 21c46e88dd7517eb36e002817d5407b32c539b9e Mon Sep 17 00:00:00 2001 From: sanderd17 Date: Wed, 8 Aug 2012 14:40:52 +0300 Subject: [PATCH 4/9] update to new interface --- .../plus/activities/search/SearchPOIActivity.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/activities/search/SearchPOIActivity.java b/OsmAnd/src/net/osmand/plus/activities/search/SearchPOIActivity.java index 39b9c8ab83..d3d0bfd6ac 100644 --- a/OsmAnd/src/net/osmand/plus/activities/search/SearchPOIActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/search/SearchPOIActivity.java @@ -25,6 +25,7 @@ import net.osmand.data.Amenity; import net.osmand.data.AmenityType; import net.osmand.osm.LatLon; import net.osmand.osm.OpeningHoursParser; +import net.osmand.osm.OpeningHoursParser.OpeningHours; import net.osmand.osm.OpeningHoursParser.OpeningHoursRule; import net.osmand.plus.NameFinderPoiFilter; import net.osmand.plus.OsmandApplication; @@ -727,17 +728,12 @@ public class SearchPOIActivity extends OsmandListActivity implements SensorEvent label.setText(str); int opened = -1; if (amenity.getOpeningHours() != null) { - List rs = OpeningHoursParser.parseOpenedHours(amenity.getOpeningHours()); + OpeningHours rs = OpeningHoursParser.parseOpenedHours(amenity.getOpeningHours()); if (rs != null) { Calendar inst = Calendar.getInstance(); inst.setTimeInMillis(System.currentTimeMillis()); boolean work = false; - for (OpeningHoursRule p : rs) { - if (p.isOpenedForTime(inst)) { - work = true; - break; - } - } + work = rs.isOpenedForTime(inst); if (work) { opened = 0; } else { From d6955d50f785c71d765e12a87936716e7afa61ea Mon Sep 17 00:00:00 2001 From: Sander Deryckere Date: Wed, 8 Aug 2012 17:44:48 +0200 Subject: [PATCH 5/9] Better parsing of opening hours. First two pages of taginfo are parsed correctly. --- .../net/osmand/osm/OpeningHoursParser.java | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java b/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java index 825fab16c7..3baf5a097d 100644 --- a/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java +++ b/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java @@ -101,7 +101,7 @@ public class OpeningHoursParser { s.append(r.toString()).append("; "); } - return s.toString(); + return s.substring(0, s.length()-2); } } @@ -333,7 +333,7 @@ public class OpeningHoursParser { b.append(", "); } } - return b.toString(); + return b.substring(0, b.length()-2); } @Override @@ -443,6 +443,11 @@ public class OpeningHoursParser { if(time.equals("off")){ break; // add no time values } + if(time.equals("24/7")){ + // for some reason, this is used. See tagwatch. + basic.addTimeRange(0, 24*60); + break; + } String[] stEnd = time.split("-"); //$NON-NLS-1$ if (stEnd.length != 2) { continue; @@ -453,11 +458,25 @@ public class OpeningHoursParser { try { int i1 = stEnd[0].indexOf(':'); int i2 = stEnd[1].indexOf(':'); - if (i1 == -1 || i2 == -1) { - return false; + int startHour, startMin, endHour, endMin; + if(i1 == -1) { + // if no minutes are given, try complete value as hour + startHour = Integer.parseInt(stEnd[0].trim()); + startMin = 0; + } else { + startHour = Integer.parseInt(stEnd[0].substring(0, i1).trim()); + startMin = Integer.parseInt(stEnd[0].substring(i1 + 1).trim()); } - st = Integer.parseInt(stEnd[0].substring(0, i1).trim()) * 60 + Integer.parseInt(stEnd[0].substring(i1 + 1).trim()); - end = Integer.parseInt(stEnd[1].substring(0, i2).trim()) * 60 + Integer.parseInt(stEnd[1].substring(i2 + 1).trim()); + if(i2 == -1) { + // if no minutes are given, try complete value as hour + endHour = Integer.parseInt(stEnd[0].trim()); + endMin = 0; + } else { + endHour = Integer.parseInt(stEnd[0].substring(0, i1).trim()); + endMin = Integer.parseInt(stEnd[0].substring(i1 + 1).trim()); + } + st = startHour * 60 + startMin; + end = endHour * 60 + endMin; } catch (NumberFormatException e) { return false; } @@ -530,7 +549,7 @@ public class OpeningHoursParser { System.out.println(hours); testOpened("07.08.2012 14:20", hours, false); // test off value - hours = parseOpenedHours("Mo-Sa 00:00-24:00; Th off"); //$NON-NLS-1$ + hours = parseOpenedHours("Mo-Th 09:00-18:25; Fr 09:00-18:55; Sa 09:00-17:55"); //$NON-NLS-1$ System.out.println(hours); testOpened("08.08.2012 23:59", hours, true); testOpened("09.08.2012 00:15", hours, false); @@ -538,7 +557,11 @@ public class OpeningHoursParser { hours = parseOpenedHours("24/7"); //$NON-NLS-1$ System.out.println(hours); testOpened("08.08.2012 23:59", hours, true); + // some people seem to use the following syntax: + hours = parseOpenedHours("Sa-Su 24/7"); + System.out.println(hours); + hours = parseOpenedHours("Mo-Fr 9-19"); + System.out.println(hours); } } - From bb4864eefe6c51f707874003aeb350f15e00b8f3 Mon Sep 17 00:00:00 2001 From: Sander Deryckere Date: Wed, 8 Aug 2012 17:51:05 +0200 Subject: [PATCH 6/9] Opening hours, better parsing --- .../net/osmand/osm/OpeningHoursParser.java | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java b/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java index 3baf5a097d..d54d30cad1 100644 --- a/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java +++ b/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java @@ -2,8 +2,6 @@ package net.osmand.osm; - - import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -20,6 +18,17 @@ import java.util.Calendar; */ public class OpeningHoursParser { private static final String[] daysStr = new String[] {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ + /** + * default values for sunrise and sunset. Might be computed afterwards, not final + */ + private static String sunrise = "07:00", sunset = "21:00"; + /** + * hour of when you would expect a day to be ended. + * This is to be used when no end hour is known (like pubs that open at a certain time, + * but close at a variable time, depending on the number of clients). + * OsmAnd needs to show a value, so there is some arbitrary default value chosen. + */ + private static String endOfDay = "24:00"; /** * This class contains the entire OpeningHours schema and @@ -189,6 +198,7 @@ public class OpeningHoursParser { } } + @Deprecated /** * get a single start time * @return a single start time @@ -201,6 +211,7 @@ public class OpeningHoursParser { } } + @Deprecated /** * get a single end time * @return a single end time @@ -330,10 +341,10 @@ public class OpeningHoursParser { formatTime(stHour, stTime, b); b.append("-"); //$NON-NLS-1$ formatTime(enHour, enTime, b); - b.append(", "); + b.append(","); } } - return b.substring(0, b.length()-2); + return b.substring(0, b.length()-1); } @Override @@ -375,6 +386,11 @@ public class OpeningHoursParser { * @return true if the String is successfully parsed */ public static boolean parseRule(String r, OpeningHours rs){ + // replace words "sunrise" and "sunset" by real hours + r = r.replaceAll("sunset", sunset); + r = r.replaceAll("sunrise", sunrise); + // replace the '+' by an arbitrary value + r = r.replaceAll("\\+", "-" + endOfDay); int startDay = -1; int previousDay = -1; int k = 0; @@ -419,6 +435,14 @@ public class OpeningHoursParser { for (int j = startDay; j <= i; j++) { days[j] = true; } + if(startDay > i){// overflow handling, e.g. Su-We + for (int j = startDay; j <= 6; j++) { + days[j] = true; + } + for (int j = 0; j <= i; j++){ + days[j] = true; + } + } startDay = -1; } else { days[i] = true; @@ -430,7 +454,10 @@ public class OpeningHoursParser { } } if(previousDay == -1){ - return false; + // no days given => take all days. + for (int i = 0; i<7; i++){ + days[i] = true; + } } String timeSubstr = r.substring(k); String[] times = timeSubstr.split(","); @@ -469,11 +496,11 @@ public class OpeningHoursParser { } if(i2 == -1) { // if no minutes are given, try complete value as hour - endHour = Integer.parseInt(stEnd[0].trim()); + endHour = Integer.parseInt(stEnd[1].trim()); endMin = 0; } else { - endHour = Integer.parseInt(stEnd[0].substring(0, i1).trim()); - endMin = Integer.parseInt(stEnd[0].substring(i1 + 1).trim()); + endHour = Integer.parseInt(stEnd[1].substring(0, i2).trim()); + endMin = Integer.parseInt(stEnd[1].substring(i2 + 1).trim()); } st = startHour * 60 + startMin; end = endHour * 60 + endMin; @@ -528,15 +555,17 @@ public class OpeningHoursParser { private static void testOpened(String time, OpeningHours hours, boolean expected) throws ParseException { Calendar cal = Calendar.getInstance(); - cal.setTime(new SimpleDateFormat("dd.MM.yyyy hh:mm").parse(time)); + cal.setTime(new SimpleDateFormat("dd.MM.yyyy HH:mm").parse(time)); System.out.println("Expected " + time+": " + expected +" = " + hours.isOpenedForTime(cal)); } public static void main(String[] args) throws ParseException { + + //Test basic case OpeningHours hours = parseOpenedHours("Mo-Fr 08:30-14:40" ); //$NON-NLS-1$ System.out.println(hours); - testOpened("09.08.2012 12:00", hours, true); + testOpened("09.08.2012 11:00", hours, true); testOpened("09.08.2012 16:00", hours, false); // two time and date ranges hours = parseOpenedHours("Mo-We, Fr 08:30-14:40,15:00-19:00"); //$NON-NLS-1$ @@ -549,10 +578,10 @@ public class OpeningHoursParser { System.out.println(hours); testOpened("07.08.2012 14:20", hours, false); // test off value - hours = parseOpenedHours("Mo-Th 09:00-18:25; Fr 09:00-18:55; Sa 09:00-17:55"); //$NON-NLS-1$ + hours = parseOpenedHours("Mo-Sa 09:00-18:25; Th off"); //$NON-NLS-1$ System.out.println(hours); - testOpened("08.08.2012 23:59", hours, true); - testOpened("09.08.2012 00:15", hours, false); + testOpened("08.08.2012 12:00", hours, true); + testOpened("09.08.2012 12:00", hours, false); //test 24/7 hours = parseOpenedHours("24/7"); //$NON-NLS-1$ System.out.println(hours); @@ -562,6 +591,18 @@ public class OpeningHoursParser { System.out.println(hours); hours = parseOpenedHours("Mo-Fr 9-19"); System.out.println(hours); + hours = parseOpenedHours("09:00-17:00"); + System.out.println(hours); + hours = parseOpenedHours("sunrise-sunset"); + System.out.println(hours); + hours = parseOpenedHours("10:00+"); + System.out.println(hours); + hours = parseOpenedHours("Su-Th sunset-24:00, 04:00-sunrise; Fr-Sa sunset-sunrise"); + System.out.println(hours); + testOpened("12.08.2012 04:00", hours, true); + testOpened("12.08.2012 23:00", hours, true); + testOpened("08.08.2012 12:00", hours, false); + testOpened("08.08.2012 05:00", hours, true); } } From 46bca3b1bb694f281c061181e2ecd9d1af88da51 Mon Sep 17 00:00:00 2001 From: Sander Deryckere Date: Thu, 9 Aug 2012 10:10:24 +0200 Subject: [PATCH 7/9] Fix nullpointer exception --- DataExtractionOSM/src/net/osmand/data/Amenity.java | 2 +- DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java | 4 ++++ OsmAnd/src/net/osmand/plus/osmedit/EditingPOIActivity.java | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/DataExtractionOSM/src/net/osmand/data/Amenity.java b/DataExtractionOSM/src/net/osmand/data/Amenity.java index a5bcea37b7..cb6e40c73b 100644 --- a/DataExtractionOSM/src/net/osmand/data/Amenity.java +++ b/DataExtractionOSM/src/net/osmand/data/Amenity.java @@ -47,7 +47,7 @@ public class Amenity extends MapObject { this.site = entity.getTag(OSMTagKey.CONTACT_WEBSITE); } } - if (this.site.indexOf("://") == -1){ + if (this.site != null && !this.site.startsWith("http://")){ this.site = "http://"+this.site; } } diff --git a/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java b/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java index d54d30cad1..7d8ace0d8f 100644 --- a/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java +++ b/DataExtractionOSM/src/net/osmand/osm/OpeningHoursParser.java @@ -106,6 +106,10 @@ public class OpeningHoursParser { public String toString(){ StringBuilder s = new StringBuilder(); + if (rules.isEmpty()) { + return ""; + } + for (OpeningHoursRule r : rules) { s.append(r.toString()).append("; "); } diff --git a/OsmAnd/src/net/osmand/plus/osmedit/EditingPOIActivity.java b/OsmAnd/src/net/osmand/plus/osmedit/EditingPOIActivity.java index 18995d8049..d294cf33a3 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/EditingPOIActivity.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/EditingPOIActivity.java @@ -100,6 +100,7 @@ public class EditingPOIActivity implements DialogProvider { } private void showPOIDialog(int dialogID, Node n, AmenityType type, String subType) { + System.out.println("showing dialog: "+n.toString()); Amenity a = new Amenity(n, type, subType); dialogBundle.putSerializable(KEY_AMENITY, a); dialogBundle.putSerializable(KEY_AMENITY_NODE, n); From acec83df92d300f205ed3ae5e1c51916a3d464df Mon Sep 17 00:00:00 2001 From: Sander Deryckere Date: Thu, 9 Aug 2012 11:03:35 +0200 Subject: [PATCH 8/9] Adding phone and website options to edit POI --- OsmAnd/res/layout/editing_poi.xml | 59 ++++++++++++++++++- OsmAnd/res/values/strings.xml | 3 +- .../plus/osmedit/EditingPOIActivity.java | 17 ++++++ 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/OsmAnd/res/layout/editing_poi.xml b/OsmAnd/res/layout/editing_poi.xml index 6b20cd6143..e116e980dd 100644 --- a/OsmAnd/res/layout/editing_poi.xml +++ b/OsmAnd/res/layout/editing_poi.xml @@ -4,24 +4,79 @@ android:layout_width="fill_parent" android:layout_height="fill_parent"> + android:layout_height="wrap_content" android:orientation="vertical"> + + + + + -