package hae // assignLayers проставляет слой каждой группе точек. // // Правило проверено на всей истории (находка 33) и дважды ломалось на живых // данных при более простых формулировках: классификация доставки целиком // сложила минутные точки с посекундными и удвоила сумму за час, а // классификация каждой метрики по отдельности растащила редкие метрики по трём // слоям. // // Работающая формулировка в три шага: // // 1. плотная метрика (не меньше denseThreshold точек) классифицируется по // собственному выравниванию; // 2. редкая наследует самый мелкий слой среди плотных метрик этой доставки — // её собственное выравнивание ничего не значит, одна метка на часе бывает // и у минутного ряда; // 3. доставка без плотных метрик вовсе наследует последний надёжно выведенный // слой той же автоматизации, а если и его нет — берёт слой из НАДЁЖНОГО // заголовка. // // Третий шаг не роскошь: измерено 2 такие доставки из 89, обе с заголовком // `Default`. Заменить его заголовком нельзя — `Default` не означает режима. func assignLayers(groups []group, meta Meta, res *Result) error { delivery := deliveryLayer(groups) if delivery == "" { // Плотных метрик нет: наследуем от прошлых доставок этой автоматизации, // иначе — от надёжного заголовка. delivery = meta.FallbackLayer if delivery == "" { delivery = res.HeaderLayer } if delivery == "" { return ErrLayerUnknown } } res.Layer = delivery // Расхождение сверяется только с надёжным заголовком: `Default` не // означает режима, и сравнение с ним давало бы WARN на каждой доставке // потока в пять минут — сигнал утонул бы в собственном шуме. res.LayerMismatch = res.HeaderLayer != "" && delivery != res.HeaderLayer for i := range groups { g := &groups[i] switch { case g.fixed: // Слой назначен схемой, выводить нечего. case g.dense: g.layer = g.alignment default: g.layer = delivery } } return nil } // deliveryLayer — самый мелкий слой среди плотных метрик доставки. Пустой, // если плотных метрик нет. // // Группы с назначенным слоем в голосовании не участвуют: суточных сводок сна // бывает больше порога плотности, и их полуночные метки иначе назначили бы // всей доставке слой hour. func deliveryLayer(groups []group) Layer { var out Layer for _, g := range groups { if g.fixed || !g.dense { continue } if out == "" { out = g.alignment continue } out = finer(out, g.alignment) } return out }