diff --git a/astrid/.classpath b/astrid/.classpath index 40651759a..9900acf07 100644 --- a/astrid/.classpath +++ b/astrid/.classpath @@ -28,5 +28,7 @@ + + diff --git a/astrid/astrid.launch b/astrid/astrid.launch index 7b969a0ea..cb174a74d 100644 --- a/astrid/astrid.launch +++ b/astrid/astrid.launch @@ -6,7 +6,7 @@ - + diff --git a/astrid/libs/jchronic-0.2.3.jar b/astrid/libs/jchronic-0.2.3.jar new file mode 100644 index 000000000..c0f15a32a Binary files /dev/null and b/astrid/libs/jchronic-0.2.3.jar differ diff --git a/astrid/src/com/todoroo/astrid/service/TaskService.java b/astrid/src/com/todoroo/astrid/service/TaskService.java index 41cb563c4..2bf937ec4 100644 --- a/astrid/src/com/todoroo/astrid/service/TaskService.java +++ b/astrid/src/com/todoroo/astrid/service/TaskService.java @@ -1,8 +1,6 @@ package com.todoroo.astrid.service; import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.weloveastrid.rmilk.data.MilkTaskFields; @@ -27,9 +25,10 @@ import com.todoroo.astrid.data.Task; import com.todoroo.astrid.gcal.GCalHelper; import com.todoroo.astrid.gtasks.GtasksMetadata; import com.todoroo.astrid.opencrx.OpencrxCoreUtils; -import com.todoroo.astrid.producteev.ProducteevUtilities; import com.todoroo.astrid.producteev.sync.ProducteevTask; import com.todoroo.astrid.tags.TagService; +import com.todoroo.astrid.utility.TitleParser; + /** * Service layer for {@link Task}-centered activities. @@ -350,37 +349,11 @@ public class TaskService { @SuppressWarnings("nls") public static void parseQuickAddMarkup(Task task, ArrayList tags) { String title = task.getValue(Task.TITLE); + TitleParser parse = new TitleParser(task, tags); - Pattern tagPattern = Pattern.compile("(\\s|^)#([^\\s]+)"); - Pattern contextPattern = Pattern.compile("(\\s|^)(@[^\\s]+)"); - Pattern importancePattern = Pattern.compile("(\\s|^)!(\\d)(\\s|$)"); - while(true) { - Matcher m = tagPattern.matcher(title); - if(m.find()) { - tags.add(m.group(2)); - } else { - m = contextPattern.matcher(title); - if(m.find()) { - tags.add(m.group(2)); - } else { - m = importancePattern.matcher(title); - if(m.find()) { - int value = Integer.parseInt(m.group(2)); - // not in producteev world: !1 to !4 => importance 3 to 0 - int importance = Math.max(Task.IMPORTANCE_MOST, Task.IMPORTANCE_LEAST + 1 - value); - // in the producteev world, !1 to !4 => importance 4 to 1 - if(ProducteevUtilities.INSTANCE.isLoggedIn() || OpencrxCoreUtils.INSTANCE.isLoggedIn()) - importance++; - - task.setValue(Task.IMPORTANCE, importance); - } else - break; - } - } - title = title.substring(0, m.start()) + title.substring(m.end()); - } - task.setValue(Task.TITLE, title.trim()); } + + } diff --git a/astrid/src/com/todoroo/astrid/utility/TitleParser.java b/astrid/src/com/todoroo/astrid/utility/TitleParser.java new file mode 100644 index 000000000..29fa8ddea --- /dev/null +++ b/astrid/src/com/todoroo/astrid/utility/TitleParser.java @@ -0,0 +1,257 @@ +package com.todoroo.astrid.utility; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.mdimension.jchronic.Chronic; +import com.todoroo.astrid.data.Task; + + +public class TitleParser { + + HashMap results; + Task task; + ArrayList tags; + + public TitleParser(Task task, ArrayList tags){ + this.task = task; + this.tags = tags; + runAllHelpers(); + } + + public Task getTask(){ + return task; + } + + private void runAllHelpers(){ + priorityListHelper(task, results, tags); + dayHelper(task, results, tags); + dateHelper(task, results, tags); + timeHelper(task, results, tags); + repeatHelper(task, results, tags); + } + + private static int str_to_priority(String priority_str) { + int priority = Task.IMPORTANCE_DO_OR_DIE; + if (priority_str.equals ("0") || priority_str.equals ("!0")) + priority = Task.IMPORTANCE_NONE; + if (priority_str.equals ("!") || priority_str.equals ("!1")) + priority = Task.IMPORTANCE_SHOULD_DO; + if (priority_str.equals("!!") || priority_str.equals ("!2")) + priority = Task.IMPORTANCE_MUST_DO; + return priority; + } + + private static void priorityListHelper(Task task, HashMap map, ArrayList tags) { + String inputText = task.getValue(Task.TITLE); + + Pattern importancePattern = Pattern.compile("(.*)(^|[^\\w!])(!+|0|!\\d)($|[^\\w!])(.*)"); + Pattern tagPattern = Pattern.compile("(\\s|^)#([^\\s]+)"); + Pattern contextPattern = Pattern.compile("(\\s|^)(@[^\\s]+)"); + + while(true) { + Matcher m = tagPattern.matcher(inputText); + if(m.find()) { + tags.add(m.group(2)); + } else { + m = contextPattern.matcher(inputText); + if(m.find()) { + tags.add(m.group(2)); + }else{ + m = importancePattern.matcher(inputText); + if(m.find()) { + map.put("title", m.group(1)); //make task list without !! + + map.put("priority", str_to_priority(m.group(3))); + task.setValue(Task.IMPORTANCE, str_to_priority(m.group(3))); + + } else + break; + } + } + inputText = inputText.substring(0, m.start()) + inputText.substring(m.end()); + } + task.setValue(Task.TITLE, inputText.trim()); + } + + private static void dayHelper(Task task, HashMap map, ArrayList tags) { + String inputText = task.getValue(Task.TITLE); + String[] dates = { + "(?i)\\b(today)\\b", + "(?i)\\b(tomorrow)\\b", + "(?i)\\b(mon(day\\b|\\.))", + "(?i)\\b(tues(day\\b|\\.))", + "(?i)\\b(wed(nesday\\b|\\.))", + "(?i)\\b(thurs(day\\b|\\.))", + "(?i)\\b(fri(day\\b|\\.))", + "(?i)\\b(sat(urday\\b|\\.))", + "(?i)\\b(sun(day\\b|\\.))", + "(?i)\\b(next (month|week|year))\\b" }; + + for (String date : dates){ + Pattern pattern = Pattern.compile(date); + Matcher m = pattern.matcher(inputText); + + if (m.find()) { + Calendar cal = Chronic.parse(m.group(0)).getBeginCalendar(); + map.put("date", cal); + long time = cal.getTime().getTime(); + task.setValue(Task.DUE_DATE, time); + + } + } + } + + private static void dateHelper(Task task, HashMap map, ArrayList tags) { + String inputText = task.getValue(Task.TITLE); + String ds = "3[0-1]|[0-2]?[0-9]"; + String[] dates = { + "\\b(1?[1-9](\\/|-)(3[0-1]|[0-2]?[0-9])($|\\s|\\/|-))", + "\\b(jan(uary)?)(\\s(3[0-1]|[0-2]?[0-9]))?", + "\\b(feb(ruary)?)(\\s(3[0-1]|[0-2]?[0-9]))?", + "\\b(mar(ch)?)(\\s(3[0-1]|[0-2]?[0-9]))?", + "\\b(apr(il)?)(\\s(3[0-1]|[0-2]?[0-9]))?", + "\\b(may)(\\s(3[0-1]|[0-2]?[0-9]))?", + "\\b(june?)(\\s(3[0-1]|[0-2]?[0-9]))?", + "\\b(july?)(\\s(3[0-1]|[0-2]?[0-9]))?", + "\\b(aug(ust)?)(\\s(3[0-1]|[0-2]?[0-9]))?", + "\\b(sep(tember)?)(\\s(3[0-1]|[0-2]?[0-9]))?", + "\\b(oct(ober)?)(\\s(3[0-1]|[0-2]?[0-9]))?", + "\\b(nov(ember)?)(\\s(3[0-1]|[0-2]?[0-9]))?", + "\\b(dec(ember)?)(\\s(3[0-1]|[0-2]?[0-9]))?" + }; + for (String date:dates) { + Pattern pattern = Pattern.compile(date); + Matcher m = pattern.matcher(inputText); + //if (m.find()) { + if (m.find() && map.get("day")== null){ + Calendar cal = Chronic.parse(m.group(0)).getBeginCalendar(); + Calendar today = Calendar.getInstance(); + if (today.get(Calendar.MONTH) - cal.get(Calendar.MONTH) > 1){ //if more than a month in the past + cal.set(cal.get(Calendar.YEAR)+1, cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)); + } + map.put("day", cal); + } + } + } + private static void timeHelper(Task task, HashMap map, ArrayList tags) { + String inputText = task.getValue(Task.TITLE); + String[] times = { + //[time] am/pm + "(?i)\\b((i?)\\d.* ?[ap]\\.?m\\.?)\\b", + //army time + "(?i)\\b([0-2]?[0-9]:[0-5][0-9])\\b", + //at [int] + "(?i)\\bat ([01]?\\d)($|\\D($|\\D))", + //[int] o'clock + "(?i)\\b([01]?\\d ?o'? ?clock)\\b" + }; + for (String time:times){ + Pattern pattern = Pattern.compile(time); + Matcher m = pattern.matcher(inputText); + if (m.find()){ + map.put("time", Chronic.parse(m.group(1)).getBeginCalendar()); + } + } + HashMap dayTimes = new HashMap(); + dayTimes.put("(?i)\\bafternoon\\b", "15:00"); + dayTimes.put("(?i)\\bevening\b" , "19:00"); + dayTimes.put("(?i)\\bnight\\b" , "19:00"); + dayTimes.put("(?i)\\bmidnight\\b" , "0:00"); + dayTimes.put("(?i)\\bnoon\\b" , "12:00"); + + for (String dayTime: dayTimes.keySet()){ + Pattern pattern = Pattern.compile(dayTime); + Matcher m = pattern.matcher(inputText); + if (m.find() && map.get("time")==null){ + String dtime = dayTimes.get(dayTime); + map.put("time", Chronic.parse(dtime).getBeginCalendar()); + + } + } + + HashMap mealTimes = new HashMap(); + mealTimes.put("(?i)\\bbreakfast\\b", "8:00"); + mealTimes.put("(?i)\\blunch\\b", "12:00"); + mealTimes.put("(?i)\\bsupper\\b" ,"18:00"); + mealTimes.put("(?i)\\bdinner\b","18:00"); + mealTimes.put("(?i)\\bbrunch\b", "10:00"); + + for (String mealTime:mealTimes.keySet()){ + Pattern pattern = Pattern.compile(mealTime); + Matcher m = pattern.matcher(inputText); + if (m.find() && map.get("time")==null){ + String mtime = mealTimes.get(mealTime); + map.put("time", Chronic.parse(mtime).getBeginCalendar()); + } + } + } + + + private static void repeatHelper(Task task, HashMap map, ArrayList tags) { + String inputText = task.getValue(Task.TITLE); + HashMap repeatTimes = new HashMap(); + repeatTimes.put("(?i)\\bevery \\w{0,6} ?days?\\b" , "day"); + repeatTimes.put("(?i)\\bevery \\w{0,6} ?weeks?\\b", "week"); + repeatTimes.put("(?i)\\bevery \\w{0,6} ?(mon|tues|wednes|thurs|fri|satur|sun)days?\b/i","week"); + repeatTimes.put("(?i)\\bevery \\w{0,6} ?months?\\b", "month"); + repeatTimes.put("(?i)\\bevery \\w{0,6} ?years?\\b", "year"); + + HashMap repeatTimesIntervalOne = new HashMap(); + //pre-determined intervals of 1 + repeatTimesIntervalOne.put( "(?i)\\bdaily\\b" , "day"); + repeatTimesIntervalOne.put( "(?i)\\bweekly\\b" , "week"); + repeatTimesIntervalOne.put( "(?i)\\bmonthly\\b" ,"month"); + repeatTimesIntervalOne.put( "(?i)\\byearly\\b" , "year"); + + for (String repeatTime:repeatTimes.keySet()){ + Pattern pattern = Pattern.compile(repeatTime); + Matcher m = pattern.matcher(inputText); + if (m.find() && map.get("time")==null){ + String rtime = repeatTimes.get(repeatTime); + map.put("freq", rtime); + map.put("interval",findInterval(inputText)); + map.put("repeats", true); + } + } + + for (String repeatTimeIntervalOne:repeatTimesIntervalOne.keySet()){ + Pattern pattern = Pattern.compile(repeatTimeIntervalOne); + Matcher m = pattern.matcher(inputText); + if (m.find() && map.get("time")==null){ + String rtime = repeatTimesIntervalOne.get(repeatTimeIntervalOne); + map.put("freq", rtime); + map.put("interval", 1); + map.put("repeats", true); + } + } + } + + private static int findInterval(String inputText) { + HashMap words_to_num = new HashMap(); + String[] words = new String[] { + "one", "two", "three", "four", "five", "six", + "seven", "eight", "nine", "ten", "eleven", "twelve" + }; + for(int i = 0; i < words.length; i++) { + words_to_num.put(words[i], i+1); + words_to_num.put(Integer.toString(i + 1), i + 1); + } + words_to_num.put("other" , 2); + + Pattern pattern = Pattern.compile("\\bevery (\\w*)\\b"); + int interval = 1; + Matcher m = pattern.matcher(inputText); + if (m.find() && m.group(1)!=null){ + String interval_str = m.group(1); + if (words_to_num.containsKey(interval_str)) + interval = words_to_num.get(interval_str); + } + return interval; + } + +} + diff --git a/tests/.settings/org.eclipse.jdt.ui.prefs b/tests/.settings/org.eclipse.jdt.ui.prefs index 29fddf385..662739807 100644 --- a/tests/.settings/org.eclipse.jdt.ui.prefs +++ b/tests/.settings/org.eclipse.jdt.ui.prefs @@ -1,4 +1,4 @@ -#Tue Mar 08 14:08:11 PST 2011 +#Tue Jan 10 16:28:27 PST 2012 cleanup.add_default_serial_version_id=true cleanup.add_generated_serial_version_id=false cleanup.add_missing_annotations=true