Перейти к содержанию
Баллы и голосования на мероприятиях с ODNFC Выбрать устройство

Баллы и голосования на мероприятиях с ODNFC

Два подхода к баллам, внутренним расчётам и голосованиям на мероприятиях: хранение состояния в MIFARE Ultralight EV1 или на сервере по UID любой поддерживаемой метки.

Браслет, бейдж, карта или брелок участника можно превратить во внутренний «кошелёк» мероприятия. За посещение стенда, выполненное задание или победу в игре участник получает баллы, а затем тратит их на призы, дополнительные попытки или доступ к активности. Тем же идентификатором можно голосовать за экспонаты, собирать отметки маршрута и участвовать в командном рейтинге.

Есть два основных способа построить такую систему:

  1. хранить баллы и прогресс прямо в памяти совместимой NFC-метки;
  2. хранить их на сервере, а UID метки использовать как номер участника.

Это разные архитектуры. Первая позволяет работать без сети, вторая упрощает общий баланс, голосования, рейтинги и защиту от повторных операций. На крупных площадках часто используют гибрид обоих подходов.

Здесь под внутренними расчётами понимаются игровые или бонусные единицы внутри мероприятия, а не банковский платёж. Если баллы продаются за деньги или обмениваются на товары и услуги, организатору отдельно нужно определить правила учёта, возврата, фискализации и защиты операций.

Коротко: чем отличаются два подхода

ВопросБаллы на карте Ultralight EV1Баллы на сервере по UID
Какая метка нужнаСовместимая перезаписываемая MIFARE Ultralight EV1Практически любая поддерживаемая метка со стабильным UID
Нужна ли сеть при касанииНетДа, хотя бы локальная сеть до сервера
Где находится актуальный балансНа карте или браслетеВ серверной базе
Несколько точек начисления и списанияРаботают с одной и той же картойРаботают с одной общей записью на сервере
Общий рейтинг в реальном времениНужна последующая выгрузка или отдельный серверФормируется сразу
Потеря браслетаВместе с ним обычно теряется локальный балансБаланс можно привязать к новой метке
Защита от копирования и измененияЗависит от типа метки и схемы контроля целостностиОсновные проверки выполняются на сервере
Типичный выборАвтономный квест и баллы небольшой ценностиГолосование, общий кошелёк, ценные призы и много точек

UID следует считать идентификатором, а не секретным ключом. Для серверной схемы лучше заранее выдавать участникам известные организатору метки со стабильным UID. Идентификаторы смартфонов, мобильных кошельков и некоторых банковских карт могут зависеть от устройства и режима работы, поэтому их проверяют до запуска проекта.

Подход 1. Баллы хранятся на MIFARE Ultralight EV1

Встроенные счётчики вместо одного изменяемого числа

MIFARE Ultralight EV1 содержит три независимых 24-битных счётчика. Они увеличиваются атомарно, но их нельзя уменьшить или сбросить. Поэтому текущий баланс удобно считать по двум счётчикам:

баланс = всего начислено − всего списано

Например:

  • счётчик 0 — все начисленные баллы;
  • счётчик 1 — все потраченные баллы;
  • счётчик 2 — число посещённых точек, отдельные бонусы или служебный счётчик.

При начислении 50 баллов считыватель увеличивает первый счётчик на 50. При покупке приза за 30 баллов он сначала вычисляет текущий баланс, проверяет, что баллов достаточно, а затем увеличивает второй счётчик на 30.

В прошивке ODNFC на Lua для этого предусмотрены функции чтения и увеличения счётчиков Ultralight EV1. Они описаны в справочнике модуля MFRC522.

MIFARE Ultralight без обозначения EV1 не имеет таких счётчиков. Для Ultralight C в ODNFC заявлено только чтение UID. Поэтому перед закупкой браслетов нужно проверить точную модель чипа и нужные операции на образцах, а не ориентироваться только на слово Ultralight в названии.

Баланс в пользовательских байтах

Другой вариант — записывать текущее число баллов в пользовательские страницы метки и изменять его при каждой операции. Рядом с балансом обычно хранят:

  • идентификатор или версию мероприятия;
  • номер последней операции;
  • тип баллов или флаги пройденных этапов;
  • контрольное значение для обнаружения повреждения или подмены данных.

Один беззнаковый байт хранит только значения от 0 до 255. На практике лучше заранее определить формат из нескольких байтов и порядок их записи. Также нужно продумать, что произойдёт, если участник уберёт браслет во время обновления: считыватель должен перечитать записанные данные и подтвердить операцию только после проверки.

Записываемые страницы удобнее аппаратных счётчиков, когда баланс нужно обнулять, переносить на следующее мероприятие или хранить сложный прогресс. Счётчики удобнее там, где важны атомарное начисление и сохранение истории начислено/списано без перезаписи прежнего значения.

Как проходит начисление или списание

  1. ODNFC считывает UID и определяет тип метки.
  2. Программа читает счётчики или пользовательские страницы.
  3. Проверяются версия мероприятия, доступный баланс, лимит повторов и роль точки.
  4. Считыватель выполняет запись или увеличение нужного счётчика.
  5. Данные читаются повторно, чтобы подтвердить успешную операцию.
  6. Подсветка и звук сообщают об успехе, недостатке баллов или ошибке записи.
  7. При наличии сети событие дополнительно отправляется в журнал сервера.

У точки может быть фиксированная роль: «начислить 10», «списать 50», «отметить этап 7». Другой вариант — загружать правила из локального файла и менять их через веб-интерфейс перед началом нового дня.

Когда подходит локальный баланс

Локальный баланс подходит, если:

  • сеть на площадке отсутствует или часто пропадает;
  • маршрут должен продолжать работать полностью автономно;
  • баллы имеют игровую, а не значительную материальную ценность;
  • число правил и типов операций невелико;
  • участник физически переносит состояние между точками на своём браслете;
  • итоговую статистику допустимо собрать после мероприятия.

Ограничения тоже нужно учитывать. Потерянную карту сложнее восстановить, операции нельзя мгновенно отозвать со всех точек, а простой UID или незащищённые пользовательские байты можно скопировать. Парольная защита Ultralight EV1 снижает риск случайной записи, но для дорогих призов или баланса, купленного за деньги, окончательный баланс лучше хранить на сервере.

Подход 2. Баллы хранятся на сервере, карта передаёт UID

В этой схеме на метку ничего записывать не требуется. Браслет или карта только предъявляет стабильный UID, а сервер находит по нему участника, баланс, историю операций, права и прогресс.

Так можно использовать не только Ultralight EV1, но и другую метку, поддерживаемую ODNFC. Важно, чтобы её UID стабильно читался выбранной моделью считывателя. Для меток, поддерживаемых только в режиме чтения UID, этого достаточно.

Как проходит серверная операция

  1. Считыватель получает UID.
  2. Локальная программа добавляет идентификаторы мероприятия и точки, тип операции, сумму, время и уникальный номер запроса.
  3. Запрос отправляется на сервер по локальной сети или через интернет.
  4. Сервер проверяет участника, лимиты, расписание, повторы и доступный баланс.
  5. Операция записывается в единый журнал транзакций.
  6. Сервер возвращает результат и новый баланс.
  7. ODNFC подтверждает успех или отказ светом и звуком.

Уникальный номер запроса нужен для идемпотентности: если ответ потерялся и считыватель повторил запрос, сервер должен вернуть прежний результат, а не начислить или списать баллы второй раз.

Сервер необязательно размещать в интернете. На временной площадке это может быть локальный компьютер в той же сети. Интернет тогда нужен только для удалённого наблюдения или публикации результатов, а касания продолжают обрабатываться внутри площадки.

Что даёт общий сервер

  • единый актуальный баланс на всех стойках и экспонатах;
  • атомарное списание без двойной выдачи приза;
  • журнал с причиной, временем и точкой каждой операции;
  • отмена ошибочной операции без перепрограммирования браслета;
  • перенос баланса на новую метку при утере старой;
  • сегменты участников, разные тарифы и дневные лимиты;
  • рейтинг команд и участников в реальном времени;
  • блокировка метки или конкретной точки сразу во всей системе.

Для защиты серверной схемы ODNFC и сервер должны аутентифицировать друг друга, запросы следует передавать по защищённому каналу, а каждой точке назначать собственный ключ или учётную запись. На сервере полезны лимиты частоты операций, журнал изменений и запрет отрицательного баланса на уровне одной транзакции базы данных.

Что делать при обрыве сети

Начисления небольшой ценности можно временно складывать в локальную очередь и передавать позже. Каждое событие получает уникальный номер, поэтому повторная синхронизация не создаёт дублей.

Со списанием сложнее: две автономные точки не знают, не потратил ли участник тот же баланс в другом месте. Для ценных операций выбирают один из вариантов:

  • запрещать списание до восстановления связи;
  • разрешать только небольшой офлайн-лимит;
  • хранить резерв доступных баллов на самой карте;
  • подключить точки к локальному серверу, не зависящему от интернета.

Нельзя одновременно обещать полностью автономную работу нескольких точек и строго единый баланс без конфликтов, если общее состояние нигде не синхронизируется.

Как выбрать подход для типовых сценариев

СценарийПредпочтительный подходПочему
Детский квест без сетиUltralight EV1 или пользовательские страницы меткиПрогресс путешествует с участником, точки автономны.
Баллы за посещение стендов и общий рейтингСервер или гибридНачисления сразу видны на табло, повторы проверяются между всеми точками.
Обмен баллов на сувениры небольшой ценностиСервер; локальная карта допустима при контролируемом рискеСервер предотвращает двойное списание и хранит журнал выдачи.
Напитки, товары или баллы, купленные за деньгиОсновной журнал на сервереНужны строгий баланс, отмены, аудит и отдельные правила расчётов.
Фиксированное число попыток на одном аттракционеКарта или локальная память считывателяОбщая сеть может быть не нужна.
Голосование за экспонаты с живым рейтингомСервер по UIDВсе голоса сразу попадают в общую статистику.
Командная игра на большой площадкеСервер или гибрид с локальной очередьюНесколько точек одновременно меняют общий результат.
Многоразовые бейджи на серии мероприятийСервер по UIDНовый сезон не требует очищать и заново размечать память каждой карты.

Голосование за экспонаты и проекты

Перед каждым экспонатом устанавливается ODNFC. Считывателю назначается идентификатор экспоната, проекта или номинации. Посетитель прикладывает браслет к понравившемуся объекту, после чего голос уходит на сервер, учитывается в статистике и может сразу повлиять на рейтинг.

Последовательность одного голоса

  1. ODNFC считывает UID браслета.
  2. Считыватель формирует событие: мероприятие, экспонат, UID, время и уникальный номер операции.
  3. Сервер проверяет, открыто ли голосование и имеет ли этот участник право голосовать.
  4. Применяется правило повторов: один голос за весь конкурс, один за номинацию, один за каждый экспонат или ограниченный бюджет голосов.
  5. Голос сохраняется в одной транзакции с защитой от дублей.
  6. Сервер отвечает принято, уже голосовали, лимит исчерпан или голосование закрыто.
  7. Считыватель показывает понятный результат цветом и звуком.
  8. Экран рейтинга получает обновлённую статистику и перерисовывает список.

Ограничение повторов лучше обеспечить не только программной проверкой, но и уникальным ограничением в базе. Например, для правила «один голос за номинацию» уникальной становится комбинация мероприятие + номинация + участник. Тогда два почти одновременных запроса не создадут два голоса.

Что можно показывать в рейтинге

  • число голосов и место каждого экспоната;
  • долю голосов внутри номинации;
  • число уникальных участников;
  • динамику по времени и активность зон;
  • рейтинг команд, городов, потоков или типов билетов;
  • выполнение минимального кворума;
  • отдельное служебное табло состояния считывателей.

Публичный рейтинг необязательно обновлять после каждого голоса. Чтобы текущие лидеры не влияли на выбор посетителей, его можно показывать с задержкой, только по завершении этапа или без точных чисел до закрытия голосования.

UID не следует выводить на публичный экран. Если персональные данные для сценария не нужны, сервер может работать с внутренним псевдонимом участника, а соответствие исходному UID хранить отдельно и ограничивать по сроку хранения.

Голосование без постоянной связи

Если сервер временно недоступен, локальная программа ODNFC может сохранять события в очередь и передавать их после восстановления сети. Рейтинг в этот момент отстаёт от фактических касаний.

Глобальное правило «только один голос на всём мероприятии» нельзя строго проверить на нескольких изолированных считывателях: каждый видит только свою локальную историю. После синхронизации сервер выявит и отклонит дубли по правилам, но посетитель мог получить подтверждение на нескольких точках. Если это недопустимо, нужна стабильная локальная сеть до общего сервера.

Для полностью автономного голосования часть состояния можно записывать на метку: например, битовую карту уже использованных номинаций или точек. Такой вариант ограничен объёмом памяти, требует контроля целостности и всё равно не даёт живой общий рейтинг без последующей выгрузки.

Другие сценарии на той же системе

Паспорт выставки

Каждый стенд добавляет отметку о посещении. После заданного числа разных точек участник получает подарок или право участвовать в розыгрыше. Серверный вариант показывает организатору поток посетителей и популярность зон; вариант с хранением данных на метке продолжает работать без сети.

Игровая валюта

Баллы выдаются за задания и тратятся на подсказки, повторные попытки, виртуальные предметы или сувениры. Для небольшого автономного квеста подходит Ultralight EV1. Для нескольких магазинов призов и общего остатка лучше сервер.

Лекции и мастер-классы

Касание отмечает вход, выход или выполнение практического задания. Начисление можно разрешить только после минимального времени участия, а повторное касание в той же аудитории не учитывать.

Командный зачёт

UID связывается с участником и командой. Личные баллы суммируются в командный результат, который выводится на экран. Отдельные точки могут иметь разные коэффициенты, лимиты и периоды доступности.

Персонализированный экспонат

После касания сервер или локальная программа возвращает язык, сложность, сохранённый прогресс или выбранный ранее сценарий. Экспонат реагирует на конкретного посетителя и продолжает прохождение с нужного шага.

Выдача призов и инвентаря

Касание подтверждает, кто, где и когда получил сувенир, оборудование или доступ к активности. Серверный журнал помогает разбирать спорные случаи и видеть остатки на разных стойках.

Гибридная схема

На крупном мероприятии можно использовать гибридную схему:

  • сервер хранит окончательный баланс, голоса и рейтинг;
  • ODNFC сразу обрабатывает карту, управляет индикацией и ставит события в очередь при кратком обрыве сети;
  • на Ultralight EV1 хранится резервный счётчик, прогресс квеста или небольшой офлайн-лимит;
  • после восстановления связи сервер принимает события по уникальным номерам и отмечает конфликты;
  • операции высокой ценности разрешаются только после ответа сервера.

ODNFC обрабатывает касание и индикацию локально, а общие правила, баланс и статистика остаются в центральной системе.

Что определить до разработки

  • какие именно метки и версии чипов будут выдаваться участникам;
  • должен ли UID оставаться стабильным на всех точках;
  • какая система хранит окончательный баланс при нормальной работе и при сбое;
  • можно ли начислять и списывать баллы без сети;
  • как обрабатываются повторное касание и повторная отправка запроса;
  • сколько голосов разрешено и в каком разрезе действует ограничение;
  • когда и с какой задержкой публикуется рейтинг;
  • как восстановить баланс при потере браслета;
  • какая операция считается достаточно ценной, чтобы требовать ответа сервера;
  • какие данные о посетителе действительно нужно хранить и когда их удалить;
  • каким светом и звуком обозначаются успех, отказ, ожидание и ошибка.

Для распределённых точек обычно выбирают ODNFC-LAN с Lua: устройство выполняет локальную логику, работает с Ultralight EV1 и передаёт события на сервер по сети.