Допустим, вам поставили задачу разработать веб-приложение для проведения интерактивного розыгрыша счастливых номеров участников конференции. Таблица участников формируется на основе регистрации посетителей этого мероприятия. Счастливчиков необходимо выбирать случайным образом и не повторяться. Такую задачу достаточно быстро удалось решить с помощью Power Apps + MS SharePoint List через коллекции.

Код не оптимизирован (это было мое первое приложение в Power Apps), но задача решалась так:

1) Размещаем компоненты: 2 таймера, контейнеры для картинок, таблицу для визуального просмотра всех участников (все в зале должны видеть кто участвует в розыгрыше).

2) Начало работы ведущего мероприятия состоит в том, чтобы инициализировать 1 раз все необходимые переменные и массивы. Программно на OnSelect кнопки СТАРТ пишем такой код (Power Apps):

Clear(cLotto); //Создаем коллекцию
Collect(cLotto,M_LOTTO_ITS); // собираем данные участников из SharePoint List
Set(vMin, Min(cLotto.NN,NN)); // определяем минимальное значение кода участника
Set(vMax, Max(cLotto.NN,NN)); // определяем максимальное значение кода участника
UpdateContext({TimerGo:false}); // для булевой переменной работы с 1-ым таймером выставляем дефолтное значение
UpdateContext({Reset: false}); Reset(tTimer); UpdateContext({Reset: true}); // сбрасываем значения других переменных до дефолтных
UpdateContext({vWin:0}); // обнуляем код победителя
UpdateContext({vMan:"?"}); // а ФИО нам тоже неизвестно вначале розыгрыша, поэтому ?
UpdateContext({vFStyle:"font-size:2em; color:#FFF;"}); // стиль шрифта в табло по умолчанию

3) В нашем приложении 2 таймера: tGTimer - таймер контролирует общее время случайного выбора, длительность работы 2 сек. и tTimer - длительность работы 25 мс, повторяющийся, отвечает за переборку случайных участников. Такая реализация позволяет представить анимированный процесс выбора. Для tTimer: OnTimerStart

UpdateContext({vWin:RandBetween(vMin,vMax)}); // определяем случайно номер ID победителя из базы

В течение 2 секунд с длительностью 25 мс (80 итераций) осуществляется выбор победителя. Для tGTimer: OnTimerEnd

UpdateContext({TimerGo:false}); // Останавливаем работу таймера и выбор участника
UpdateContext({Reset: false}); 
Reset(tGTimer); 
UpdateContext({Reset: true});
UpdateContext({vFStyle:"font-size:4em; color:#bee2dd;"}); // Меняем стиль для отображения победителя
UpdateContext({vMan:Concatenate(Last(FirstN(cLotto,vWin)).NAME," ",Last(FirstN(cLotto,vWin)).SURNAME)}); // Выводим ФИО по ID из коллекции
Remove(cLotto, First(Filter(cLotto, SURNAME=Last(FirstN(cLotto,vWin)).SURNAME)), {isWIN:true }); // Удаляем победителя из участия в следующем круге розыгрыша приза
ForAll(Sequence(CountRows(cLotto)),{NN: Last(FirstN(cLotto)).NN}); // Обновляем общее итоговое количество участников, каждый СТАРТ будет N-1 участников

4) Пока не истекли 2 секунды отображается анимация слева. Победитель удаляется по ID из коллекции cLotto. Можно дальше продолжать розыгрыш.

Управление запуском и остановкой таймеров осуществляется сменой значения булевых переменных для Property: OnTimerStart и OnTimerEnd.

Преимущества такого способа - это возможность визуализации в WEBе достаточно привлекательного интерфейса для участников розыгрыша. На JavaScript+HTML пришлось бы написать гораздо больше кода.

ПРИМЕЧАНИЕ: Все имена в таблице розыгрыша вымышленные.