Часто перед разработчиком стоит задача установить определенный элемент на сайте, который случайным образом выводит информацию.Будь то коллаж в шапке, изречения философов и т.д. Задача тривиальная, но для обычных языков программирования, а если возможности использовать их нет?Java Script не в счет, зависеть от настроек пользователя в таких задачах — не кошерно. На помощь приходит SSI, хотя, положа руку на сердце, это не те задачи, которые должен выполнять.Итак, что у нас есть, и что можно сделать:
- SSI не может получить список файлов (элементов) из папки, поэтому будем список указывать в коде не динамично;
- В SSI нет массивов, значит будем делать псевдо массив из переменных;
- В SSI нет математических функций, зато есть конкатенация и регулярные выражения;
- Нет математики, но есть время, случайное число можно выбирать из секунд (кстати функция rand во многих языках программирования работает именно от времени);
- Так как в SSI мы не можем указать диапазон случайной выборки, диапазонами может быть секунды в пределах десятка (10 элементов), в пределах минуты (60 элементов), в пределах сотни (100 элементов), и т.д.;
- Ввиду того, что в SSI нет циклов, скрипт должен быть линейным в один проход, будет куча copy/past;
- Проверяем какие есть элементы, а каких нет;
- Заполняем недостающие элементы последовательностью из существующих;
- В SSI нет математических функций, зато есть конкатенация и регулярные выражения;
- Выбираем соответствующий элемент относительно секунд;
<!-- Объявляем переменные списка --> <!--#set var="RND_0" value="Значение 0" --> <!--#set var="RND_1" value="Значение 1" --> <!--#set var="RND_2" value="Значение 2" --> <!-- Вызываем компоненту --> <!--#include virtual="/rnd.shtml"--> <!-- Вот наше случайное значение --> [ <!--#echo var="RND_X"--> ]Компоненту рекомендую делать на 10 элементов, она объемом 14 Кб, а на 60 элементов уже больше 500 Кб, вот так-то (хотя надо подумать над оптимизацией еще).Компонента: Код (2)
<!-- Объявляем дополнительные переменные для псевдо списков существующих и использованных элементов --> <!--#set var="RND_LIST_INDEX" value="x" --> <!--#set var="RND_LIST_INDEX_TMP" value="x" --> <!-- Заполняем переменную существующих элементов и объявляем дополнительные переменные "флаги" существования переменных. Ввиду того, что циклов нет, приходится делать такой длинный копипаст. --> <!--#if expr="$RND_0" --> <!--#set var="RND_LIST_INDEX" value="${RND_LIST_INDEX}0" --> <!--#set var="RND_0_EX" value="1" --> <!--#else --> <!--#set var="RND_0_EX" value="0" --> <!--#endif --> <!--#if expr="$RND_1" --> <!--#set var="RND_LIST_INDEX" value="${RND_LIST_INDEX}1" --> <!--#set var="RND_1_EX" value="1" --> <!--#else --> <!--#set var="RND_1_EX" value="0" --> <!--#endif --> <!--#if expr="$RND_2" --> <!--#set var="RND_LIST_INDEX" value="${RND_LIST_INDEX}2" --> <!--#set var="RND_2_EX" value="1" --> <!--#else --> <!--#set var="RND_2_EX" value="0" --> <!--#endif --> <!--#if expr="$RND_3" --> <!--#set var="RND_LIST_INDEX" value="${RND_LIST_INDEX}3" --> <!--#set var="RND_3_EX" value="1" --> <!--#else --> <!--#set var="RND_3_EX" value="0" --> <!--#endif --> <!--#if expr="$RND_4" --> <!--#set var="RND_LIST_INDEX" value="${RND_LIST_INDEX}4" --> <!--#set var="RND_4_EX" value="1" --> <!--#else --> <!--#set var="RND_4_EX" value="0" --> <!--#endif --> <!--#if expr="$RND_5" --> <!--#set var="RND_LIST_INDEX" value="${RND_LIST_INDEX}5" --> <!--#set var="RND_5_EX" value="1" --> <!--#else --> <!--#set var="RND_5_EX" value="0" --> <!--#endif --> <!--#if expr="$RND_6" --> <!--#set var="RND_LIST_INDEX" value="${RND_LIST_INDEX}6" --> <!--#set var="RND_6_EX" value="1" --> <!--#else --> <!--#set var="RND_6_EX" value="0" --> <!--#endif --> <!--#if expr="$RND_7" --> <!--#set var="RND_LIST_INDEX" value="${RND_LIST_INDEX}7" --> <!--#set var="RND_7_EX" value="1" --> <!--#else --> <!--#set var="RND_7_EX" value="0" --> <!--#endif --> <!--#if expr="$RND_8" --> <!--#set var="RND_LIST_INDEX" value="${RND_LIST_INDEX}8" --> <!--#set var="RND_8_EX" value="1" --> <!--#else --> <!--#set var="RND_8_EX" value="0" --> <!--#endif --> <!--#if expr="$RND_9" --> <!--#set var="RND_LIST_INDEX" value="${RND_LIST_INDEX}9" --> <!--#set var="RND_9_EX" value="1" --> <!--#else --> <!--#set var="RND_9_EX" value="0" --> <!--#endif --> <!-- Теперь по порядку устанавливаем значение переменных списка, если у переменной значения нет. Значение устанавливаем при условии, что мы не устанавливали его до этого, ввиду того, что у нас жестко определена последовательность от 0 до 9. --> <!--#if expr="$RND_0_EX = 0 && $RND_0_EX = 1 && $RND_LIST_INDEX_TMP != /0/" --> <!--#set var="RND_0" value="$RND_0" --> <!--#set var="RND_LIST_INDEX_TMP" value="${RND_LIST_INDEX_TMP}0" --> <!--#elif expr="$RND_0_EX = 0 && $RND_1_EX = 1 && $RND_LIST_INDEX_TMP != /1/" --> <!--#set var="RND_0" value="$RND_1" --> <!--#set var="RND_LIST_INDEX_TMP" value="${RND_LIST_INDEX_TMP}1" --> <!--#elif expr="$RND_0_EX = 0 && $RND_2_EX = 1 && $RND_LIST_INDEX_TMP != /2/" --> <!--#set var="RND_0" value="$RND_2" --> <!--#set var="RND_LIST_INDEX_TMP" value="${RND_LIST_INDEX_TMP}2" --> <!--#elif expr="$RND_0_EX = 0 && $RND_3_EX = 1 && $RND_LIST_INDEX_TMP != /3/" --> <!--#set var="RND_0" value="$RND_3" --> <!--#set var="RND_LIST_INDEX_TMP" value="${RND_LIST_INDEX_TMP}3" --> <!--#elif expr="$RND_0_EX = 0 && $RND_4_EX = 1 && $RND_LIST_INDEX_TMP != /4/" --> <!--#set var="RND_0" value="$RND_4" --> <!--#set var="RND_LIST_INDEX_TMP" value="${RND_LIST_INDEX_TMP}4" --> <!--#elif expr="$RND_0_EX = 0 && $RND_5_EX = 1 && $RND_LIST_INDEX_TMP != /5/" --> <!--#set var="RND_0" value="$RND_5" --> <!--#set var="RND_LIST_INDEX_TMP" value="${RND_LIST_INDEX_TMP}5" --> <!--#elif expr="$RND_0_EX = 0 && $RND_6_EX = 1 && $RND_LIST_INDEX_TMP != /6/" --> <!--#set var="RND_0" value="$RND_6" --> <!--#set var="RND_LIST_INDEX_TMP" value="${RND_LIST_INDEX_TMP}6" --> <!--#elif expr="$RND_0_EX = 0 && $RND_7_EX = 1 && $RND_LIST_INDEX_TMP != /7/" --> <!--#set var="RND_0" value="$RND_7" --> <!--#set var="RND_LIST_INDEX_TMP" value="${RND_LIST_INDEX_TMP}7" --> <!--#elif expr="$RND_0_EX = 0 && $RND_8_EX = 1 && $RND_LIST_INDEX_TMP != /8/" --> <!--#set var="RND_0" value="$RND_8" --> <!--#set var="RND_LIST_INDEX_TMP" value="${RND_LIST_INDEX_TMP}8" --> <!--#elif expr="$RND_0_EX = 0 && $RND_9_EX = 1 && $RND_LIST_INDEX_TMP != /9/" --> <!--#set var="RND_0" value="$RND_9" --> <!--#set var="RND_LIST_INDEX_TMP" value="${RND_LIST_INDEX_TMP}9" --> <!--#endif --> <!-- Теперь проверяем, не заполнен ли уже список и не надо ли последовательность устанавливать сначала --> <!--#if expr="$RND_LIST_INDEX_TMP = $RND_LIST_INDEX" --> <!--#set var="RND_LIST_INDEX_TMP" value="x" --> <!--#endif --> <!-- Дальше точно такие же блоки для каждой их переменных по порядку для всего диапазона от 0 до 9. Не забываем после каждого блока проверять заполненность последовательности. --> <!--#if expr="$RND_1_EX = 0 && $RND_0_EX = 1 && $RND_LIST_INDEX_TMP != /0/" --> <!--#set var="RND_1" value="$RND_0" --> <!--#set var="RND_LIST_INDEX_TMP" value="${RND_LIST_INDEX_TMP}0" --> <!--#elif expr="$RND_1_EX = 0 && $RND_1_EX = 1 && $RND_LIST_INDEX_TMP != /1/" --> <!--#set var="RND_1" value="$RND_1" --> <!--#set var="RND_LIST_INDEX_TMP" value="${RND_LIST_INDEX_TMP}1" --> <!--#elif expr="$RND_1_EX = 0 && $RND_2_EX = 1 && $RND_LIST_INDEX_TMP != /2/" --> ... <!-- Весь список элементов заполнен, можно выбрать нужный относительно секунд. --> <!--#config timefmt="%S" --> <!--#set var="NUM_SEC" value="$DATE_LOCAL" --> <!--#if expr="$NUM_SEC = /0$/" --> <!--#set var="RND_X" value="$RND_0" --> <!--#elif expr="$NUM_SEC = /1$/" --> <!--#set var="RND_X" value="$RND_1" --> <!--#elif expr="$NUM_SEC = /2$/" --> <!--#set var="RND_X" value="$RND_2" --> <!--#elif expr="$NUM_SEC = /3$/" --> <!--#set var="RND_X" value="$RND_3" --> <!--#elif expr="$NUM_SEC = /4$/" --> <!--#set var="RND_X" value="$RND_4" --> <!--#elif expr="$NUM_SEC = /5$/" --> <!--#set var="RND_X" value="$RND_5" --> <!--#elif expr="$NUM_SEC = /6$/" --> <!--#set var="RND_X" value="$RND_6" --> <!--#elif expr="$NUM_SEC = /7$/" --> <!--#set var="RND_X" value="$RND_7" --> <!--#elif expr="$NUM_SEC = /8$/" --> <!--#set var="RND_X" value="$RND_8" --> <!--#elif expr="$NUM_SEC = /9$/" --> <!--#set var="RND_X" value="$RND_9" --> <!--#else --> <!--#set var="RND_X" value="$RND_0" --> <!--#endif --> <!-- ВАЖНО!!! Теперь желательно обнулить список, т.к. переменные все глобальные, и если мы будем использовать компоненту несколько раз на одной странице для разных списков, то может произойти смешение списков. Хотя оставим возможность не обнулять его. --> <!--#if expr="$RND_DO_NOT_CLEAN_LIST"--> <!--#set var="RND_DO_NOT_CLEAN_LIST" value="" --> <!--#else --> <!--#set var="RND_0" value="" --> <!--#set var="RND_1" value="" --> <!--#set var="RND_2" value="" --> <!--#set var="RND_3" value="" --> <!--#set var="RND_4" value="" --> <!--#set var="RND_5" value="" --> <!--#set var="RND_6" value="" --> <!--#set var="RND_7" value="" --> <!--#set var="RND_8" value="" --> <!--#set var="RND_9" value="" --> <!--#endif --> <!-- Собственно все, случайное значение находится в переменной RND_X -->Конечно, вероятность получения элементов сильно зависит от общего количества элементов, так для списка из трех 9 элементов мы получим последовательность
- RND_0 => Значение 0;
- RND_1 => Значение 1;
- RND_2 => Значение 2;
- RND_3 => Значение 3;
- RND_4 => Значение 4;
- RND_5 => Значение 5;
- RND_6 => Значение 6;
- RND_7 => Значение 7;
- RND_8 => Значение 8;
- RND_9 => Значение 0;