LifeHacker & Elyssa
Elyssa Elyssa
Привет, Лайфхакерша, я тут ковырялась с голосовым календарем, который сам назначает встречи, планирует перекусы и даже медитации — представь себе личного лайфхакера, но на максималках. Хочешь заглянуть в код и посмотрим, как сделать его круче, чем твои нынешние инструменты продуктивности?
LifeHacker LifeHacker
Звучит как мечта. Давай посмотрим на репозиторий и начнем чистить лишние триггеры. Я сначала задокументирую текущий процесс, а потом добавим более продвинутое распознавание контекста, чтобы оно понимало, когда ты на совещании, а когда просто разговариваешь с коллегой. Покажи мне код, и мы сделаем его безупречным.
Elyssa Elyssa
Вот небольшой фрагмент секции триггеров из `triggers.py` – пока что там полный хаос. # triggers.py from events import * def register_triggers(): triggers = [] # Триггеры устарели, многие из них пересекаются triggers.append(When('meeting_start').do(schedule_meeting)) triggers.append(When('meeting_end').do(clean_up_meeting)) triggers.append(When('email_sent').do(archive_email)) triggers.append(When('message_received').do(process_message)) triggers.append(When('task_created').do(create_task)) # Повторяющиеся и редко используемые triggers.append(When('calendar_view').do(update_ui)) triggers.append(When('calendar_view').do(log_view)) triggers.append(When('calendar_view').do(cache_view)) return triggers ``` Мы можем избавиться от `calendar_view`, объединить `schedule_meeting` и `clean_up_meeting` в один обработчик с учетом контекста, и заменить простые проверки `When` на датчик контекста, который будет помечать события как "встреча", "вне экрана" и т.д. Давай набросаем простой `ContextSensor`, который будет отмечать события на основе текущего статуса календаря, а затем подключим его к циклу. Хочешь увидеть код датчика дальше?
LifeHacker LifeHacker
Конечно, вот минимальный датчик, чтобы помечать события до срабатывания триггеров. # context_sensor.py class ContextSensor: def __init__(self, calendar): self.calendar = calendar # простой интерфейс с is_meeting() и т.д. def tag(self, event): if self.calendar.is_meeting(): event.context = 'in_meeting' elif self.calendar.is_offscreen(): event.context = 'off_screen' else: event.context = 'idle' return event ``` Затем в основном цикле: ``` sensor = ContextSensor(calendar) for event in event_stream: event = sensor.tag(event) handle(event) # твой универсальный обработчик ``` Так ты можешь избавиться от старых проверок `When` и просто смотреть на `event.context`. Это даёт чистый и расширяемый хук для будущих меток. Скажи, если захочешь добавить более тонкие состояния или обработку неизвестных событий.
Elyssa Elyssa
Замечательно, этот датчик поддерживает структуру цикла в порядке. Один небольшой штрих: сделай так, чтобы функция `tag` возвращала копию, а не изменяла исходное событие, чтобы избежать случайных побочных эффектов. И добавь контекст `unknown` для событий, которые не соответствуют ни одному правилу – так будет проще ловить ошибки на раннем этапе. Хочешь небольшую тестовую систему, чтобы проверить теги на основе фиктивного календаря?
LifeHacker LifeHacker
Вот небольшая доработка и крошечная проверка, чтобы убедиться, что всё работает.
Elyssa Elyssa
Выглядит здорово! Только одна маленькая поправка – давай выделим состояние "idle" в отдельную подпись, вместо того, чтобы относить его к "неизвестному". Так потом будет проще добавить специальную обработку для реального состояния простоя. В остальном, плетение должно выводить три контекста, как и ожидалось. Готова запускать его в основной цикл?
LifeHacker LifeHacker
Поняла, просто переставь проверку бездействия до значения по умолчанию. Вот финальная настройка датчика: ```class ContextSensor: def __init__(self, calendar): self.calendar = calendar def tag(self, event): ev = copy.deepcopy(event) if self.calendar.is_meeting(): ev.context = 'in_meeting' elif self.calendar.is_offscreen(): ev.context = 'off_screen' elif self.calendar.is_idle(): # add this in your calendar class ev.context = 'idle' else: ev.context = 'unknown' return ev ``` Обнови свой mock календаря: ```class FakeCalendar: def __init__(self, state): self.state = state def is_meeting(self): return self.state == 'meeting' def is_offscreen(self): return self.state == 'off_screen' def is_idle(self): return self.state == 'idle' ``` Запусти тест снова, увидишь `in_meeting`, `off_screen`, `idle` и `unknown` как отдельные метки. Теперь можно напрямую подключить это к основному циклу и добавить отдельные обработчики для каждого контекста. Готова вставлять.
Elyssa Elyssa
Поняла — твой финальный датчик — чистый switch-case. Сейчас запускаю работу с подключением: state=meeting → context=in_meeting state=off_screen → context=off_screen state=idle → context=idle state=unknown → context=unknown Отлично. Подключи это в основной цикл событий, сопоставь каждый контекст с соответствующим обработчиком, и у тебя получится очень чёткий, контекстно-зависимый поток. Что дальше будем добавлять?
LifeHacker LifeHacker
Отлично, теперь когда с датчиком всё в порядке, переходим к следующей крутой штуке: уведомления о простоях с прогнозированием. В общем, если ты находишься в состоянии "ожидания" дольше минуты, предлагай короткий перерыв или напоминание о растяжке. Чтобы работа не превращалась в скуку смертную. Добавь таймер в обработчике бездействия, который будет выдавать вежливое уведомление. Готова набросать это?