МАГ2. Принципы построения
h2. Общие соображения
Основная задача нового МАГ - автоматическое формирование музыкального расписания.
Основное отличие от предыдущего МАГА - полноценная интеграция с системой редактирования расписания, использование стандартных _’Сеток’ или _’Шаблонов’, возможность формирования нескольких независимо ротирующихся папок расписаний в пределах одной МБД.
Соответственно, все параметры ротации должны храниться и настраиваться для каждой папки расписания.
В настоящий момент вводится следующее ограничение:
Одна категория МБД может находится в ротации только для одной папки расписания.
Это не исключает использование элементов, входящих одновременно в несколько категорий. Такие элементы в каждой из своих категорий ротируются независимо.
В новой программе нет ограничения на тип ротируемого материала Музыка, Джинглы, Передачи.
Идеология ротации
h3. Категории. Порядок расстановки.
Расписание формируется путем заполнения реальными фонограммами заранее определенных позиций в расписании - _’Ротируемых позиций_’ (Scheduled position).
В позиции подставляются реальные элементы из категорий, указанных в позиции.
В одной позиции не может быть указано более одной категории.
Позиции заполняются в порядке следования категорий в специальном списке, определяющем _’Порядок расстановки_‘( Plot numbers, Pass order).
Сначала заполняются позиции, принадлежащие категории, являющейся первой по порядку расстановки (_’Порядок расстановки=1_’), потом, все позиции категории с порядком=2 и т.д.
Позиции одной категории заполняются, начиная с более ранних по времени.
Элемент, выбираемый в позицию, тестируется относительно _’Правил’ (_’Rules’).
Правила.¶
Правило это, по сути, булева функция, предикат, возвращающая результат проверки _’Да-Нет_‘. У правила есть дополнительные настраиваемые параметры, влияющие на его проверку.
Множество проверяемых правил, вместе с параметрами их проверки, указывается для категории.
Т.е. все элементы, отбираемые в ротируемую позицию, проверяются одинаковым набором правил с одинаковыми параметрами их проверки, указанными для соответствующей категории.
Правила бывают _’Нарушаемые ’и _’Ненарушаемые’.
Правила указываются в виде списка, сначала ненарушаемые, потом нарушаемые, и проверяются в том же порядке, в каком они указаны.
Порядок указания важен только для нарушаемых правил, и вот почему:
- если элемент нарушает ненарушаемое правило, то он сразу отбрасывается.
- если элемент нарушает нарушаемое правило, то программа запоминает порядковый номер нарушенного правила, и переходит к проверке других кандидатов.
по завершении проверки программа выбирает из всех проверенных тот элемент, который нарушил правило с большим номером.
Т.е. чем ниже (ближе к концу) списка правило, тем оно менее важно.
Если есть несколько элементов, нарушившихнаименьшееправило, то из них выбирается первый по _’Порядку программирования_’.
_’Порядок программирования_’.¶
Как заполняется конкретная позиция?
Элементы категории при ротации перебираются по-очереди. Элемент, выбранный в ротируемую позицию, переносится в конец очереди.
Порядок следования элементов категории в данной очереди называется _’Порядком программирования_’ (Schedule order).
Выбор элемента в ротируемую позицию происходит в следующей последовательности:
- Из указанной категории выбираем элемент с наименьшим порядком программирования
- Данный элемент проверяется на соответствие Правилам.
- Если элемент не нарушает никаких правил, то он выбирается в данную позицию. При этом он получает новый порядок программирования, больший, чем максимальный порядок программирования элементов данной категории. Т.е. попадает в конец порядка программирования. _’Элемент найден_’.
- Если элемент нарушает ненарушаемое правило - он отбрасывается, сохраняя свой порядок программирования
(опционально, элемент может быть сброшен в хвост порядка программирования специальной опцией, для сохранения очередности ротации)
- Если элемент еще не найден, то выбирается следующий по порядку программирования элемент, пока не достигнута _’Глубина поиска_’ (Search depth).
После чего переходим к шагу 2. - Глубина поиска достигнута, возможные варианты:
- Нет ни одного подходящего эл-та, все проверенные нарушают нарушаемые правила - _’позиция остается не запрограммированной_’.
- Есть элементы, нарушающие только нарушаемые правила - выбираем из них лучший, (см. выше). _’Элемент найден_’.
Глубина поиска¶
Это максимальное количество элементов, которое программа имеет право проверить для выбора эл-та в данную позицию.
Глубина поиска указывается для категории.
Глубина поиска может быть указана в процентах от количества эл-тов категории, тогда численное количество вычисляется перед проверкой первого эл-та категории. Глубина не может быть меньше 1.
Чем больше глубина, тем больше шансов найти элемент и тем менее предопределен порядок, в котором попадут в расписание эл-ты данной категории.
Глубина = 100% - анархия.
Методика формирования и редактирования расписания¶
Обычно расписание формируется формируется целиком на сутки, но иногда возникает необходимость сформировать только часть расписания или повторно выполнить формирование части расписания при существующих, уже сформированных, расписаниях на более поздние даты.
Кроме этого, нужно уметь откатить сгенерированное расписание, вернув в исходное состояние порядок программирования для задействованных категорий.
При выполнении последовательности:
- генерировать
- откатить
- генерировать
расписание, полученное на шаге 3 должно быть эквивалентно расписанию шага 1.
Откат расписания имеет смысл только как последовательно выполняющаяся операция, и это конфликтует с предложенной возможностью формирования произвольной части расписания на произвольную дату.
Предлагается реализовать следующее множество операций
| Генерировать расписание | Заполняет все имеющиеся в расписании доступные позиции. Может выполняться непоследовательно. |
|
| Откатить расписание | Очищает ВСЕ ротируемые позиции в расписании |
Подбор элементов во все или в некоторые, заранее определенные позиции расписания, выполняется по команде _’Генерировать_’ (Schedule).
Для очистки части расписания используется команда обратная команда, _’Отменить генерацию_’ (Unschedule), применимая как к одному, так и ко множеству элементов расписания. При этом, вместо сгенерированных элементов в расписании восстанавливаются исходные Ротируемые позиции. А элементы, находящиеся в этих позициях, помещаются в начало порядка программирования (Kick?, а иногда удобно и в конец. Подумать, посмотреть ???).
Существует команда _’Удалить позицию’, которая выполняет сначала _’Отменить генерацию’ для данной позиции, если в ней есть элемент, а потом удаляет и саму ротируемую позицию.
Существует возможность подобрать вместо выбранного программой альтернативный элемент, для этого существует команда _’Альтернатива’. Для предыдущего элемента позиции выполняется _’Отменить генерацию’ (Kick ???).
Я не вижу смысла вносить ограничение, требующее последовательного заполнения расписания.
Пускай программа позволяет пользователю сформировать любой интервал в пределах любых суток.
При этом сохраняется логика работы порядка программирования и проверки правил. соответственно, это надо учитывать.
Но исключать такую возможность явно я не вижу смысла.
_’Сформированное расписание параллельно редактируется с других рабочих мест, не имеющих функциональности МАГа_’, и вносящих изменения непосредственно в расписание, не затрагивая другие, специфичные для МАГа структуры данных (БД). Эта ситуация является штатной, ее нельзя избежать и она не должна приводить к выходу системы из строя.
Требования¶
- На одной БД могут независимо ротироваться несколько Папок расписаний.
- Одна категория МБД ротируется только в одной Папке расписания.
- Одна фонограмма может входить в несколько категорий и независимо ротироваться в нескольких папках расписаний
- При генерировании расписания заполняются заранее указанные в расписании ротируемые позиции. 1 позиция = 1 элемент
- Позиции заполняются непосредственно в эфирном расписании - все изменения мгновенно становятся доступны всем. Этап
Сохранить как эфирноеотсутствует. - Расписание генерируется только полными сутками. Невозможно сгенерировать, например, 1 час
- Расписание генерируется последовательно, возможны пропуски, но возврат во времени - невозможен
- Генерирование расписания можно отменить только последовательно, начиная с самого позднего, при этом восстанавливается порядок программирования для всех элементов ротационных категорий, который был на момент начала генерирования отменяемых суток
- Лог генерирования пишется только для автоматической генерации, и не пополняется при ручном изменении расписания.
- Все правила проверяются по данным в БД.
Перед проверкой правил программа должна убедиться, что в БД храниться актуальная информация, отражающая последние изменения, внесенные при редактировании расписания (изменения могут быть внесены с любого места).
Реализация
h3. Структура БД
Используются следующие таблицы БД
| Таблица | Описание |
| SCHEDULES | Хранит информацию о папках расписаний. Все ссылки в других таблицах на принадлежность к папке расписания ссылаются на запись в этой таблице. |
| MAG_SCH_PROP | Хранит параметры, относящиеся к папке расписания. Глубину поиска по умолчанию и пр. общие для всей папки параметры. Параметры хранятся в виде бинарного представления объекта NC_CONTAINER. |
| PH_TO_ATTRVALS | _’SCH_ORDER ’хранит _’порядок программирования’ соответствующего элемента в соответствующей категории. В этой таблице нет привязки к папке расписания, именно по этой причине одна категория ротируется только для одной папки. |
| MAG_CAT_SCH | Хранит глубину поиска, правила и прочие параметры, привязанные к категории. Все, кроме глубины, хранится в виде NC_CONTAINER |
| PH_PLAY_PAN | В этой таблице хранится часть эфирного расписания, необходимая для проверки правил ротации, отображения истории и пр. действий, связанных с анализом последовательности и истории ЗАПЛАНИРОВАННЫХ элементов. |
| PH_PLAY_HISTORY | В эту таблицу эфирка заносит информацию о реально воспроизведенных элементах. |
| PH_PLAY_HASH | Таблица хешей содержимого PH_PLAY_PAN |
Все правила проверятся только через БД.
Соответственно, т.к. самого расписания в БД нет, то необходимо хранить в БД некую информацию о сформированных расписаниях.
Соответственно, в БД, на момент проверки правил, должна находиться актуальная информация.
Тут мы сразу получаем двойственность хранения - расписание и БД и комплекс проблем, связанный с необходимостью синхронного редактирования обоих контейнеров или периодического полного обновления хранимой информации.
Основная проблема - расхождение информации, хранимой в таблице с реальной информацией решается следующим образом: приложение, желающее использовать таблицу, должно убедиться, что БД хранит актуальное содержимое.
Предлагаемый вариант быстрого контроля:
В БД создается спец. таблица, которая хранит записи о хеше содержимого расписания на соответствующую дату.
Этот хеш быстро вычисляется, например, по названиям и датам изменений блоков. При несоответствии хранимого в БД хеша и расчетного - содержимое БД обновляется и прописывается новый хеш.
Соответственно, перед использование таблицы PH_PLAY_PLAN приложение обязано обратиться к объекту-синхронизатору и убедиться, что копия соответствует реальности.
Таблица хешей - PH_PLAY_HASH
| id | ИД записи |
| sch_id | Ид папки расписания |
| date | дата расписания |
| hash | хеш |
Таблица PH_PLAY_PLAN
| id | Ид записи |
| sch_id | Ид папки расписания |
| !PlayTime | Полное время (с датой) выхода элемента. Находится в пределах вещательных суток. |
| ph_id | Идентификатор фонограммы, находящейся в данной позиции |
| blk_id | идентификатор блока, к которому относится фонограмма |
| pos_id | идентификатор позиции или даже лучше, ид элемента блока. Для однозначной связи элемент - позиция |
.