one weekday matcher, and a stem list stops answering for sredstvo (V-581)
router.WeekdayIndex reads the lexicon and asks the dictionary about the case. Four private lists go away: the habit declension map, the weekday block of the day-plan refusal, the weekday and part-of-day entries of the weather guard, and the stem list in ruwords.go. The stem list was the real defect. mentionsUnknownDay matched sred, pyatnits and subbot with strings.Contains, so sredi, sredstvo and sredniy all read as Wednesday and a question carrying one was answered with onlyNearDaysReply instead of a date. It matches whole tokens now. The weather guard was a third copy of three closed sets that already exist. It kept the rooms of the house, which are its own, and asks the lexicon for the weekdays, the parts of the day and the words that follow v without naming a place. Questions phrased v srede, v utra and v obshchem reached the geocoder as cities before. Full suite green under -race.
This commit is contained in:
@@ -35,16 +35,14 @@ var dayPlanWords = []string{
|
||||
// answer today and stamp it with today's date, which is a wrong answer where
|
||||
// falling through is only a terse one.
|
||||
//
|
||||
// The weekday names are here as a refusal, not as a feature. "какие планы на
|
||||
// понедельник?" carries no other-day token in the сегодня family and does carry
|
||||
// "планы", so the plan used to claim it and recite today.
|
||||
// A weekday is a refusal too, and it is not in this list: IsDayPlanQuery asks
|
||||
// WeekdayIndex, so every case of every name refuses rather than the nine forms
|
||||
// that used to be written out here (V-581). "какие планы на понедельник?"
|
||||
// carries no other-day token in the сегодня family and does carry "планы", so
|
||||
// the plan used to claim it and recite today.
|
||||
var otherDayWords = []string{
|
||||
"завтра", "послезавтра", "вчера", "позавчера",
|
||||
"tomorrow", "yesterday",
|
||||
"понедельник", "вторник", "среду", "среда", "четверг", "пятницу", "пятница",
|
||||
"субботу", "суббота", "воскресенье",
|
||||
"понедельника", "вторника", "четверга", "пятницы", "субботы", "воскресенья",
|
||||
"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday",
|
||||
"неделю", "неделя", "недели", "неделе",
|
||||
"выходные", "выходных", "выходным",
|
||||
"месяц", "месяца", "месяце",
|
||||
@@ -69,6 +67,9 @@ func IsDayPlanQuery(text string) bool {
|
||||
}
|
||||
toks := planTokens(text)
|
||||
for _, t := range toks {
|
||||
if _, ok := WeekdayIndex(t); ok {
|
||||
return false
|
||||
}
|
||||
for _, w := range otherDayWords {
|
||||
if t == w {
|
||||
return false
|
||||
|
||||
@@ -27,26 +27,10 @@ var habitMarkers = []string{
|
||||
"typically", "normally",
|
||||
}
|
||||
|
||||
// weekdayWords — every form of a weekday name maven needs to recognise,
|
||||
// including the "по …ам" plural the question is usually phrased in.
|
||||
var weekdayWords = map[string]time.Weekday{
|
||||
"понедельник": time.Monday, "понедельникам": time.Monday,
|
||||
"вторник": time.Tuesday, "вторникам": time.Tuesday,
|
||||
"среда": time.Wednesday, "среду": time.Wednesday, "средам": time.Wednesday,
|
||||
"четверг": time.Thursday, "четвергам": time.Thursday,
|
||||
"пятница": time.Friday, "пятницу": time.Friday, "пятницам": time.Friday,
|
||||
"суббота": time.Saturday, "субботу": time.Saturday, "субботам": time.Saturday,
|
||||
"воскресенье": time.Sunday, "воскресеньям": time.Sunday,
|
||||
"воскресенья": time.Sunday, "воскресенью": time.Sunday,
|
||||
"воскресеньем": time.Sunday, "воскресеньях": time.Sunday,
|
||||
"monday": time.Monday, "mondays": time.Monday,
|
||||
"tuesday": time.Tuesday, "tuesdays": time.Tuesday,
|
||||
"wednesday": time.Wednesday, "wednesdays": time.Wednesday,
|
||||
"thursday": time.Thursday, "thursdays": time.Thursday,
|
||||
"friday": time.Friday, "fridays": time.Friday,
|
||||
"saturday": time.Saturday, "saturdays": time.Saturday,
|
||||
"sunday": time.Sunday, "sundays": time.Sunday,
|
||||
}
|
||||
// The weekday a habit question names comes from WeekdayIndex, not from a map
|
||||
// here. This file used to keep its own declension table, which had "воскресеньях"
|
||||
// and no "средах" — a list of forms is finished by whoever last thought of one,
|
||||
// and a dictionary is not (V-581).
|
||||
|
||||
// weekendWords — the weekend as one unit. "что я обычно делаю по выходным?"
|
||||
// has a habit marker and names days, but no weekday name is in it, so it used
|
||||
@@ -77,7 +61,7 @@ func ParseHabitQuery(text string) (HabitQuery, bool) {
|
||||
return HabitQuery{}, false
|
||||
}
|
||||
for _, t := range toks {
|
||||
if wd, ok := weekdayWords[t]; ok {
|
||||
if wd, ok := WeekdayIndex(t); ok {
|
||||
return HabitQuery{Weekday: wd, HasWeekday: true}, true
|
||||
}
|
||||
if weekendWords[t] {
|
||||
|
||||
@@ -3,6 +3,7 @@ package router
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/kami/maven/internal/lexicon"
|
||||
"github.com/kami/maven/internal/morph"
|
||||
@@ -234,16 +235,34 @@ func isMonth(tok string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// isWeekday reports whether the token is a day of the week in any case. The
|
||||
// lexicon lists the nominative, and "в пятницу" is what a reminder says, so the
|
||||
// match is by lemma — grammar is morph's job, not a second word list.
|
||||
func isWeekday(tok string) bool {
|
||||
for i := 0; i < 7; i++ {
|
||||
if morph.SameWord(tok, lexicon.Weekday(i)) {
|
||||
return true
|
||||
// WeekdayIndex reports which day of the week a token names, in any case and in
|
||||
// either language, or false when it names none.
|
||||
//
|
||||
// One matcher for the whole daemon (V-581). Four files used to keep a weekday
|
||||
// list of their own and each one was short in a different direction: the habit
|
||||
// map had "воскресеньях" but no "средах", the plan refusal had "среду" but not
|
||||
// "среде", and cmd/mavend matched the STEM "сред" with strings.Contains, so
|
||||
// "среди" and "средство" read as Wednesday. The lexicon lists the nominative,
|
||||
// every Russian case lemmatises to it, and only English needs its forms written
|
||||
// out — the vendored dictionary is Russian and leaves "mondays" alone.
|
||||
func WeekdayIndex(tok string) (time.Weekday, bool) {
|
||||
t := strings.ToLower(strings.TrimSpace(tok))
|
||||
if n, ok := lexicon.WeekdayEnglish(t); ok {
|
||||
return time.Weekday(n), true
|
||||
}
|
||||
for i, name := range lexicon.Weekdays() {
|
||||
if morph.SameWord(t, name) {
|
||||
return time.Weekday(i), true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// isWeekday reports whether the token is a day of the week, when the caller
|
||||
// does not need to know which one.
|
||||
func isWeekday(tok string) bool {
|
||||
_, ok := WeekdayIndex(tok)
|
||||
return ok
|
||||
}
|
||||
|
||||
// timeMarkers — the words that name a time on their own: the qualifiers that
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestWeekdayIndexReplacesFourLists — four files kept a weekday list of their
|
||||
// own and each was short in a different direction (V-581). The forms below are
|
||||
// the ones at least one of those lists missed, so they are the point of having
|
||||
// one matcher: the lexicon names the day and the dictionary answers the case.
|
||||
func TestWeekdayIndexReplacesFourLists(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
word string
|
||||
want time.Weekday
|
||||
}{
|
||||
{"понедельник", time.Monday},
|
||||
{"понедельникам", time.Monday},
|
||||
{"понедельником", time.Monday},
|
||||
{"вторник", time.Tuesday},
|
||||
{"среда", time.Wednesday},
|
||||
{"среду", time.Wednesday},
|
||||
{"среде", time.Wednesday},
|
||||
{"средам", time.Wednesday},
|
||||
{"четверга", time.Thursday},
|
||||
{"пятницу", time.Friday},
|
||||
{"субботам", time.Saturday},
|
||||
{"воскресеньях", time.Sunday},
|
||||
{"Воскресенье", time.Sunday},
|
||||
{"monday", time.Monday},
|
||||
{"Fridays", time.Friday},
|
||||
} {
|
||||
got, ok := WeekdayIndex(tc.word)
|
||||
if !ok || got != tc.want {
|
||||
t.Errorf("WeekdayIndex(%q) = %v, %v; want %v, true", tc.word, got, ok, tc.want)
|
||||
}
|
||||
}
|
||||
// A stem match said yes to all of these. A word match says no.
|
||||
for _, w := range []string{"среди", "средство", "средний", "среднем", "субботник", "", "через"} {
|
||||
if _, ok := WeekdayIndex(w); ok {
|
||||
t.Errorf("WeekdayIndex(%q) claimed a weekday", w)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user