annie.pages.event_task ====================== .. py:module:: annie.pages.event_task .. autoapi-nested-parse:: Event-annotation task UI — the video-editor timeline surface (UI). One queued video at a time: a large HTML5 player centred at the top, a transport bar (play/pause, ±5 s, frame-step, "Start/End here"), linked frame/second/timecode jump fields, then the SVG timeline (one lane per track) and an event editor. Events are authored from scratch and saved to the review DB **immediately** on every change — there is no Save button; export (JSON for code, CSV or XLSX for a spreadsheet) is a separate step. Which video is shown comes from the Browse annotator queue, like Curation. Frame accuracy is provided by :mod:`annie.pages.videoclock` (HTML5 ``currentTime`` stepping); the timeline is drawn by :mod:`annie.pages.timeline` (Python owns the model, JS reports gestures). The layout is fixed: the video and the editor sit side by side on top, with the full-width timeline in its own row beneath both. This module is heavy on browser interaction (video, JS bridge, SVG gestures) so its wiring is verified in the browser; the pure geometry/export/store pieces it calls are unit-tested in their own modules. Functions --------- .. autoapisummary:: annie.pages.event_task.next_default_category_name annie.pages.event_task.cleanup annie.pages.event_task.needs_metadata annie.pages.event_task.load_metadata annie.pages.event_task.event_annotation_task annie.pages.event_task.changed_fields Module Contents --------------- .. py:function:: next_default_category_name(existing: list[str], prefix: str = 'Participant') -> str Return the next free ``" N"`` name given the existing names. Used when a participant or event category is added without a typed name, so "just click Add" still yields a clean, consistent label (``Participant 2``, ``Event 3``, …) and never a collision. :param existing: The names already in use. :param prefix: The name's first word, ``"Participant"`` or ``"Event"``. :returns: ``" N"`` for the smallest ``N >= 1`` not already taken. .. py:function:: cleanup(client_id: str) -> None Drop a disconnected client's Event-annotation state and gesture handler flag. .. py:function:: needs_metadata(state_: _EventState, entry: annie.core.models.VideoEntry) -> bool Whether ``entry``'s metadata still has to be read before its work area can be built. .. py:function:: load_metadata(state_: _EventState, entry: annie.core.models.VideoEntry) -> bool :async: Read ``entry``'s frame rate and length off the event loop and apply them. A result that arrives after the reviewer moved on to another video is dropped, so stepping quickly always ends on the video asked for last. :param state_: The client's Event-annotation state. :param entry: The video whose metadata to read. :returns: ``True`` if ``state_`` now holds this video's metadata (or its read failed, which is reported once), ``False`` if the read was stale, duplicate or not needed. .. py:function:: event_annotation_task() -> None Build the Event-annotation work area for the current queued video. .. py:function:: changed_fields(event: annie.dataset.storage.EventRecord, fields: dict[str, object]) -> dict[str, object] The subset of ``fields`` whose value differs from what ``event`` stores.