class EventNlp
Attributes
params[RW]
Public Class Methods
new(now=Time.now, params: {}, debug: false)
click to toggle source
Calls superclass method
# File lib/event_nlp.rb, line 29 def initialize(now=Time.now, params: {}, debug: false) super() @now = now @params = params expressions(@params) @debug = debug end
Public Instance Methods
parse(s)
click to toggle source
# File lib/event_nlp.rb, line 40 def parse(s) @params[:input] = s r = run_route(s) return unless r.is_a? Hash OpenStruct.new({input: s}.merge r) end
Private Instance Methods
expressions(params)
click to toggle source
# File lib/event_nlp.rb, line 53 def expressions(params) starting = /(?:\(?\s*starting (\d+\w{2} \w+\s*\w*)(?: until (.*))?\s*\))?/ weekdays2 = (Date::DAYNAMES + Date::ABBR_DAYNAMES).join('|').downcase weekdays = "(%s)" % weekdays2 months = "(%s)" % (Date::MONTHNAMES[1..-1] + Date::ABBR_MONTHNAMES[1..-1])\ .join('|').downcase times = /(?: *(?:at |@ |from )?(\d+(?::\d+)?(?:[ap]m|\b)) *)/ times2 = /\d+(?::\d+)?[ap]m-\d+(?::\d+)?[ap]m|\d+(?::\d+)?-\d+(?::\d+)?/ times3 = /(\d+(?::\d+)?[ap]m-\d+(?::\d+)?[ap]m|\d+(?::\d+)?-\d+(?::\d+)?)/ days = /(\d+(?:st|nd|rd|th))/ periods = /day|week|month/ #weekdays = Date::DAYNAMES.join('|').downcase # #times = /(?: *at )?\d[ap]m/ # e.g. electricity bill on the 28th of every month get /(.*) on the (#{days}) of every (#{periods})/ do |title, day, recurring| raw_d = Chronic.parse(day) # if the date is less than now then increment it by a month d = raw_d < @now ? (raw_d.to_date >> 1).to_time : raw_d if @debug then puts [0.1, title, recurring, d].inspect.debug end {title: title, recurring: recurring, date: d} end get /^(.*)\s+(every \d\w+ \w+#{times})\s*#{starting}/ do \ |title, recurring, time, raw_date, end_date| input = params[:input].clone d = Chronic.parse(raw_date + ' ' + time.to_s) if recurring =~ /day|week/ then if d < @now then new_date = CronFormat.new(ChronicCron.new(recurring)\ .to_expression, d).to_time input.gsub!(raw_date, new_date\ .strftime("#{new_date.day.ordinal} %b %Y")) d = new_date end end if @debug then puts ["0.2".highlight, input, title, recurring, time, raw_date, end_date].inspect.debug end {input: input, title: title, recurring: recurring, date: d, end_date: end_date} end # e.g. some event 1st Monday of every month (starting 3rd Jul 2017) get /^(.*)\s+(\d(?:st|nd|rd|th) \w+ of every \w+(?: at (\d+[ap]m) )?)\s*#{starting}/ do \ |title, recurring, time, raw_date, end_date| input = params[:input].clone d = Chronic.parse(raw_date) if recurring =~ /day|week|month/ then if d < @now then new_date = CronFormat.new(ChronicCron.new(recurring)\ .to_expression, d).to_time input.gsub!(raw_date, new_date\ .strftime("#{new_date.day.ordinal} %b %Y")) d = new_date else d = ChronicCron.new(recurring, d.to_date.to_time).to_time end end puts ['0.3'.highlight, title, recurring, time, raw_date, end_date].inspect.debug if @debug {input: input, title: title, recurring: recurring, date: d, end_date: end_date} end # some event every 2 weeks # some event every 2 weeks at 6am starting from 14th Jan # some event every 2 weeks at 6am starting from 18th Feb until 28th Oct # some event every 2nd Monday (starting 7th Nov 2016) # some event every 2nd Monday (starting 7th Nov until 3rd Dec) # some event every 2 weeks (starting 02/11/17) # some event every Wednesday 1pm-4pm # get /^(.*)(every .*)/ do |title, recurring| input = params[:input].clone raw_start_date = recurring[/(?<=starting )[^\)]+/] d = if raw_start_date then start_date = Chronic.parse(raw_start_date, now: @now - 1, :endian_precedence => :little) puts ('recurring: ' + recurring.inspect).debug if @debug puts ('start_date: ' + start_date.inspect).debug if @debug if @now > start_date then exp = ChronicCron.new(recurring, start_date, debug: @debug).to_expression puts 'exp: ' + exp.inspect if @debug cf = CronFormat.new(exp, start_date, debug: @debug) puts ('cf.to_time: ' + cf.to_time.inspect).debug if @debug cf.next until cf.to_time > start_date new_date = cf.to_time input.gsub!(/(?<=starting )[^\)]+/, new_date\ .strftime("#{new_date.day.ordinal} %b %Y")) new_date else start_date end else exp = ChronicCron.new(recurring).to_expression cf = CronFormat.new(exp, @now) cf.to_time end if recurring =~ /-/ then end_date = Chronic.parse d.to_date.to_s + ' ' + recurring[/(?<=-)\d+(?::\d+)?(?:[ap]m)?/] end puts ['0.5'.highlight, title, recurring, d].join("\n").debug if @debug {input: input, title: title.rstrip, recurring: recurring, date: d, end_date: end_date } end # some meeting 3rd thursday of the month at 7:30pm # some meeting First thursday of the month at 7:30pm get /(.*)\s+(\w+ \w+day of (?:the|every) month at .*)/ do |title, recurring| puts ['1'.highlight, title, recurring].inspect.debug if @debug { title: title, recurring: recurring } end # 7th Oct Euston Station (meet at Timothy's house at 7pm) get /^(\d(?:st|nd|rd|th) \w+) *(.*)\s+at\s+(\w+)/i do \ |raw_day, title, time| d = Chronic.parse(raw_day + ' ' + time) puts ['1.5'.highlight, title, raw_day, time].inspect.debug if @debug { title: title, date: d } end # some event Wednesday # some event Wednesday 11am relative_day = '|today|tomorrow|tonight' get /^(.*)\s+(#{weekdays2+relative_day}\b)(?: \(([^\)]+)\)) (at \d{1,2}(?::\d{2})?(?:[ap]m)?)/i \ do |title, raw_date, date2, time2| puts ('time2: ' + time2.inspect).debug if @debug puts ('date2: ' + date2).debug if @debug puts ('raw_date: ' + raw_date).debug if @debug d = if date2 then Chronic.parse(date2 + ' '+ time2.to_s) else Chronic.parse(raw_date + ' '+ time2) end puts ['4'.highlight, title, raw_date, date2, time2].inspect.debug if @debug {title: title, date: d } end # Group meeting Red Hall 2pm-4pm on Monday (4th Dec 2017) get /^(.*)\s+(#{times2})(?: on) +#{weekdays}\b(?: \(([^\)]+)\))?/i \ do |title, xtimes, raw_day, actual_date| if @debug then puts ('actual_date: ' + actual_date.inspect).debug puts ('raw_day: ' + raw_day.inspect).debug puts ('xtimes: ' + xtimes.inspect).debug end input = params[:input].clone if actual_date then d = Chronic.parse actual_date else d = Chronic.parse(raw_day) input.sub!(/#{weekdays}\b/i, %Q(#{raw_day} (#{d.strftime("#{d.day.ordinal} %b %Y")}))) end t1, t2 = xtimes.split(/-/,2) puts ('d: ' + d.inspect).debug if @debug d1, d2 = [t1, t2].map {|t| Chronic.parse([d.to_date.to_s, t].join(' ')) } puts ['4.65'.highlight, input, title, raw_day, d1, d2].inspect.debug if @debug {input: input, title: title, date: d1, end_date: d2 } end # hall 2 friday at 11am get /^(.*)\s+#{weekdays}\b(?: \(([^\)]+)\))?(#{times})?/i \ do |title, raw_day, actual_date, time| if @debug then puts ('actual_date: ' + actual_date.inspect).debug puts ('raw_day: ' + raw_day.inspect).debug puts ('time: ' + time.inspect).debug end input = params[:input].clone if actual_date then d = Chronic.parse(raw_day + ' ' + time.to_s) else d = Chronic.parse(raw_day + ' ' + time.to_s) input.sub!(/#{weekdays}/i, %Q(#{raw_day} (#{d.strftime("#{d.day.ordinal} %b %Y")}))) end puts ('d: ' + d.inspect).debug if @debug puts [1.7, input, title, raw_day].inspect.debug if @debug {input: input, title: title, date: d } end # e.g. 21/05/2017 Forum meetup at Roundpeg from 2pm get /^(\d+\/\d+\/\d+)\s+(.*)(?: from|at)\s+(\d+[ap]m)/ do |raw_date, title, raw_time| d = Chronic.parse(raw_date + ' ' + raw_time, :endian_precedence => :little) recurring = nil puts [3, title, raw_date].inspect.debug if @debug { title: title, date: d } end # friday hall 2 11am until 12am get /^#{weekdays}\s+(.*)\s+#{times} until #{times}$/i do \ |raw_day, title, start_time, end_time| venue = title[/^at +(.*)/,1] d = Chronic.parse(raw_day + ' ' + start_time) d2 = Chronic.parse(raw_day + ' ' + end_time) puts ['1.44.3', title, raw_day].inspect.debug if @debug { title: title, date: d, end_date: d2, venue: venue } end # friday hall 2 11am get /^#{weekdays}\b\s+(.*)\s+(\d+(?::\d{2})?[ap]m)$/i do \ |raw_day, title, time| puts [raw_day, title, time].inspect if @debug venue = title[/^at +(.*)/,1] d = Chronic.parse(raw_day + ' ' + time) puts [1.44, title, raw_day].inspect.debug if @debug { title: title, date: d, venue: venue } end # Tuesday 10th July hall 2 at 11am get /#{weekdays}\b\s+#{days}\s+#{months}\s+(?:at )?(.*)\s+at\s+(#{times})/i \ do |wday, day, month, title, time| d = Chronic.parse([day, month, time].join(' ')) puts ['1.44.5', day, month, title].inspect.debug if @debug { title: title, date: d } end # 27-Mar@1436 some important day # 25/07/2017 11pm some important day # get /^(\d+\/\d+\/\d+)\s*(\d+(?:\:\d+)?[ap]m)?\s+([^\*]+)(\*)?/ \ do |raw_date, time, title, annualar| d = Chronic.parse(raw_date + ' ' + time.to_s, :endian_precedence => :little) recurring = nil if annualar then recurring = 'yearly' if d < @now then d = Chronic.parse(raw_date, now: Time.local(@now.year + 1, 1, 1)) end end puts [3, title, raw_date, time].inspect.debug if @debug { title: title, date: d, recurring: recurring } end # Some event (10 Woodhouse Lane) 30th Nov from 9:15-17:00 get /^(.*) #{days} #{months}(?: from)? (#{times2})/i do \ |title, day, month, xtimes| t1, t2 = xtimes.split(/-/,2) d1 = Chronic.parse([month, day, t1].join(' ')) d2 = Chronic.parse([month, day, t2].join(' ')) puts [4.5, title, d1, d2].inspect.debug if @debug { title: title, date: d1, end_date: d2 } end # Some event (10 Woodhouse Lane) 30th Nov from 9:15-17:00 get /^#{weekdays}\b #{months} #{days} #{times3} (.*)/i do \ |wday, month, day, xtimes, title| puts [month, day, xtimes, title].inspect if @debug t1, t2 = xtimes.split(/-/,2) d1 = Chronic.parse([month, day, t1 + ':00'].join(' ')) d2 = Chronic.parse([month, day, t2 + ':00'].join(' ')) puts [4.55, title, d1, d2].inspect.debug if @debug { title: title, date: d1, end_date: d2 } end # e.g. Wednesday 30th Nov at 9:15 10 Woodhouse Lane get /^(?:#{weekdays2}\b) #{days} #{months}(?: at)? #{times}(.*)/i do \ |day, month, t1, title| d1 = Chronic.parse([month, day, t1].join(' ')) puts [4.6, title, d1].inspect.debug if @debug { title: title, date: d1 } end # Some event (10 Woodhouse Lane) 30th Nov at 9:15- get /^(.*) #{days} #{months}(?: at)? (#{times})/i do \ |title, day, month, t1| d1 = Chronic.parse([month, day, t1].join(' ')) puts [4.7, title, d1].inspect.debug if @debug { title: title, date: d1 } end # hall 2 at 11am # get /(.*)\s+at\s+(#{times})/i do |title, time| d = Chronic.parse(time) puts [1.45, title].inspect.debug if @debug { title: title, date: d } end # Council Tax on the last day of the month # get /^(.*) (?:o[nf] the)\s*last day of the month/i do |title| td = @now.to_date d = Date.civil(td.year, td.month, -1).to_time puts [5, title].inspect.debug if @debug { title: title, date: d } end # Council Tax last day of the month # get /^(.*) +last day of the month/i do |title| td = @now.to_date d = Date.civil(td.year, td.month, -1).to_time puts [5.1, title].inspect.debug if @debug { title: title, date: d } end # some important day 11 Oct * # get /^(.*) +(\d+) +#{months} *(\*)?/i \ do |title, day, month, annualar| raw_date = day + ' ' + month d = Chronic.parse(raw_date, :endian_precedence => :little) recurring = nil if annualar then recurring = 'yearly' if d < @now then d = Chronic.parse(raw_date, now: Time.local(@now.year + 1, 1, 1)) end end puts [6, title, raw_date].inspect.debug if @debug { title: title, date: d, recurring: recurring } end # Tuesday 3rd October gas service at Barbara's house morning 9am-1pm # get '*' do s = params[:input] time1, time2, month, weekday, day, end_date, annualar = nil, nil, nil, nil, nil, nil, false s2 = s.sub(/#{times}/i) {|x| time1 = x; ''} puts 's2: ' + s2.inspect if @debug s3 = s2.sub(/-(?=\d)/,'').sub(/#{times}/i) {|x| time2 = x; ''} s4 = s3.sub(/ *#{weekdays} */i) {|x| weekday = x; ''} s5 = s4.sub(/ *#{months} */i) {|x| month = x; ''} s6 = s5.sub(/ *#{days} */i) {|x| day = x; ''} s7 = s6.sub(/\*$/) {|x| annualar = true; ''} title = s7.strip raw_date = [day, month].compact.join(' ') raw_date = weekday if raw_date.empty? d = Chronic.parse(raw_date + ' ' + time1.to_s, :endian_precedence => :little, now: @now) if time2 then end_date = Chronic.parse(raw_date + ' ' + time2.to_s, :endian_precedence => :little) end recurring = nil if annualar then recurring = 'yearly' if d < @now then d = Chronic.parse(raw_date, now: Time.local(@now.year + 1, 1, 1)) end end puts [10, title, raw_date, time1].inspect.debug if @debug { title: title, date: d, end_date: end_date, recurring: recurring } end end