package router import "regexp" // IsAgendaQuestion answers whether an utterance asks about the owner's own // schedule, as opposed to merely naming a day. // // It exists because the calendar query source used to match on a day word and // nothing else (Vikunja #552). Every world question that happened to name a // day was claimed by the calendar and answered with an empty schedule: "какой // сегодня курс доллара" replied "на 05.08.2026 ничего нет", which reads as an // answer about a subject she never looked at. V-474 had already fixed one // instance of the class by teaching the calendar to step aside on weather // wording. Sunset, holidays, exchange rates and world news are the same class // and weather wording does not cover them. // // Three arms, and the order is only readability — any one of them is enough: // // - an agenda grammar already claims the phrasing. Reusing // AgendaQueryGrammars means the rule that ROUTES a question to the query // chain and the rule that lets the CALENDAR answer it cannot drift apart. // - the utterance names a scheduled thing. Wider than the grammars on // purpose: "какие встречи завтра" carries no possessive and no plan noun, // so no grammar claims it, and it is plainly a calendar question. // - the question names no subject of its own. "что сегодня?" is his agenda // by default, because there is nothing else for it to be about. This is // the same test the bare-imperative Praxis arm applies. // // Not a routing decision and not a fact, so a pattern is the right mechanism // here: it selects which source answers, and every source below still runs // when it returns false. func IsAgendaQuestion(u string) bool { for _, g := range AgendaQueryGrammars() { if g.Pattern.MatchString(u) { return true } } return scheduledThing.MatchString(u) || subjectlessDayQuestion.MatchString(u) } // scheduledThing — the nouns that name something on a calendar. Closed in the // sense that matters: these are the words for an appointment itself, not the // words for what an appointment is about. The stems are the union of the ones // AgendaQueryGrammars already carries, read here as a noun test rather than as // part of a phrasing. // // Stems and not whole words, because Russian declines them and "какие встречи" // and "на встречу" are one question. var scheduledThing = regexp.MustCompile(`(?i)(календар|расписани|повестк|планёрк|планерк|встреч|созвон|митинг|совещани|приём|прием|собеседовани|тренировк|занятие|занятия)`) // subjectlessDayQuestion — "что сегодня?", "что там на завтра", "что в среду". // An interrogative, an optional preposition, a day word, and nothing else. The // anchors at both ends are the whole point: the moment the sentence names what // it is asking about, it stops being his agenda and this must not match. var subjectlessDayQuestion = regexp.MustCompile( `(?i)^\s*(что|чего|какие|сколько|what)\s+(там\s+|ещё\s+|еще\s+)?(на\s+|в\s+|во\s+)?` + dayWordPattern + `\s*[?!.]*$`)