main
Raw Download raw file
  1package manifest
  2
  3import (
  4	"encoding/json"
  5	"fmt"
  6	"os"
  7	"sort"
  8	"time"
  9)
 10
 11// NewClipIndex creates a new ClipIndex.
 12func NewClipIndex(cameraID, cameraName, date string) *ClipIndex {
 13	now := time.Now()
 14	return &ClipIndex{
 15		CameraID:   cameraID,
 16		CameraName: cameraName,
 17		Date:       date,
 18		CreatedAt:  now,
 19		UpdatedAt:  now,
 20		Clips:      make([]*ClipEntry, 0),
 21	}
 22}
 23
 24// AddClip adds a clip entry to the index.
 25func (ci *ClipIndex) AddClip(entry *ClipEntry) {
 26	ci.Clips = append(ci.Clips, entry)
 27	ci.UpdatedAt = time.Now()
 28}
 29
 30// Sort orders clips by (start_ms, end_ms, event_id) for deterministic ordering.
 31func (ci *ClipIndex) Sort() {
 32	sort.Slice(ci.Clips, func(i, j int) bool {
 33		a, b := ci.Clips[i], ci.Clips[j]
 34		if a.StartMs != b.StartMs {
 35			return a.StartMs < b.StartMs
 36		}
 37		if a.EndMs != b.EndMs {
 38			return a.EndMs < b.EndMs
 39		}
 40		return a.EventID < b.EventID
 41	})
 42}
 43
 44// FindByEventID returns the clip entry with the given event ID, or nil.
 45func (ci *ClipIndex) FindByEventID(eventID string) *ClipEntry {
 46	for _, c := range ci.Clips {
 47		if c.EventID == eventID {
 48			return c
 49		}
 50	}
 51	return nil
 52}
 53
 54// Write saves the clip index to a JSON file.
 55func (ci *ClipIndex) Write(path string) error {
 56	ci.UpdatedAt = time.Now()
 57	ci.Sort()
 58
 59	data, err := json.MarshalIndent(ci, "", "  ")
 60	if err != nil {
 61		return fmt.Errorf("marshaling clip index: %w", err)
 62	}
 63
 64	err = os.WriteFile(path, data, 0644)
 65	if err != nil {
 66		return fmt.Errorf("writing clip index: %w", err)
 67	}
 68
 69	return nil
 70}
 71
 72// ReadClipIndex loads a clip index from a JSON file.
 73func ReadClipIndex(path string) (*ClipIndex, error) {
 74	data, err := os.ReadFile(path)
 75	if err != nil {
 76		return nil, fmt.Errorf("reading clip index: %w", err)
 77	}
 78
 79	var ci ClipIndex
 80	err = json.Unmarshal(data, &ci)
 81	if err != nil {
 82		return nil, fmt.Errorf("parsing clip index: %w", err)
 83	}
 84
 85	return &ci, nil
 86}
 87
 88// WriteDayMetadata saves day metadata to a JSON file.
 89func WriteDayMetadata(path string, meta *DayMetadata) error {
 90	data, err := json.MarshalIndent(meta, "", "  ")
 91	if err != nil {
 92		return fmt.Errorf("marshaling day metadata: %w", err)
 93	}
 94
 95	err = os.WriteFile(path, data, 0644)
 96	if err != nil {
 97		return fmt.Errorf("writing day metadata: %w", err)
 98	}
 99
100	return nil
101}