Часто перед разработчиком стоит задача установить определенный элемент на сайте, который случайным образом выводит информацию.Будь то коллаж в шапке, изречения философов и т.д. Задача тривиальная, но для обычных языков программирования, а если возможности использовать их нет?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;