Сервис референдумов и опросов: запуск + изменения

28 дней назад
79 в golos

Здравствуйте. В этом посте я описывал алгоритм работы такого сервиса, но, как часто бывает, после начала разработки было найдено много недочётов и придумано несколько улучшений.
Давайте рассмотрим это всё.

Удобный интерфейс

Чтобы пользователи, которые не умеют в код, могли пользоваться, сделал интерфейс для системы опросов и референдумов:

Кроме того, есть лента опросов и референдумов в аккаунте @golos-votes https://golos.id/dpos-post/@golos-votes/votes-list (комментарии к посту, можете отсортировать).

Итоговые коды:

Создание опроса:

Делается это путём сжигания GBG к null. При этом принимается, только если сумма >= прописанной минимальной в конфиге.
Пример в блоке №32003579
{"contractName":"golos-votes","contractAction":"createVote","contractPayload":{"question":"Есть ли у вас планы по развитию Голоса?","answers":["Да: опишу их","Да, но описывать не буду","Пока нет","Нет"],"end_date":1575857880,"consider":0}}

  • contractName (используется везде) - golos-votes. Это название софт-смарта;
  • contractAction - createVote, т.е. создание голосования;
  • contractPayload - данные действия.
    • "question - вопрос;
    • answers - массив вариантов ответа;
    • end_date - дата и время окончания опроса в формате Unix time (int);
    • consider - тип учёта СГ: 0 - только личная, 1 - личная + прокси, 2 - как при апвотинге.

Голосование

  • id golos-votes;
  • Указывается только required_posting_auths с логином голосующего (означает, что участвовать в опросах можно с постинг ключом);

Пример кода в блоке №32004108
{"contractName":"golos-votes\","contractAction":"voteing\","contractPayload":{"votePermlink":"survey-1573255083\","answerId":"0"}}.

  • contractAction voteing означает, что действие - голосование;
  • votePermlink - пермлинк опроса (с его помощью происходит идентификация опроса);
  • answerId - id варианта ответа (соответствует ключу массива ответов).

Как работает:

  1. Парсит блоки в поисках переводов GBG к null или custom_json операций;
  2. В первом случае проверяется, что memo - json, что действие - createVote, а также что формат соответствует стандарту,
    Во втором проверяется id, что действие voteing, а также что формат соответствует коду голосования;

Создание опроса:

  1. После проверки формата производится добавление пермлинка: survey-unixTime.
    где "survey-" - это первая часть пермлинка, а unixTime - дата и время перевода (timestamp) в Unix time формате;
  2. Добавление в базу данных. В функцию передаются вопрос, ответы, пермлинк опроса/референдума, тип учёта Силы Голоса и Unix time завершения опроса;
  3. Создаётся переменная title со значением "вопрос " + переменная, выводящая его.
  4. Формируется строка, в которую добавляется список вариантов ответа (формат markdown маркированного списка).
    В body выводится заголовок "варианты ответа" и переменная с их списком.
    В функцию публикации отправляется тайтл, пермлинк, текст, ответы и завершение опроса.
    В json_metadata добавляется массив с вариантами ответа, что позволяет при желании работать с get_content, а не с базами данных;
  5. В самой функции поста в начале и конце добавляется текст с информацией о том, при помощи чего создан опрос, а также ссылки на голосование и просмотр предварительных или окончательных результатов.

Голосование

  • После проверки формата и действия получаем опрос по пермлинку из БД., а затем проверяем, что Unix time текущего времени <= unix time окончания опроса.
  • Также проверяется, что answerId такой есть в массиве вариантов ответа. Для этого берётся length-1 массива вариантов и проверяется, что он >= answerId.
  • Далее получаем информацию об аккаунте, после чего, в зависимости от consider считаем СГ: если 0, только личную в parseFloat; если 1, прибавляем к parseFloat личной parseFloat прокси; Если 2, прибавляем к личной parseFloat полученного делегирования и вычитаем отданное делегирование (как при апах).
    Также в зависимости от consider выводим строку с соответствующим текстом, например, для первого варианта она будет 'Учитывается только личная СГ';
  • После того обновляем вариант ответа. Идентификация по пермлинку опроса и логину голосующего, но в функцию передаётся всё в следующем порядке: пермлинк, id варианта ответа, логин (берётся из required_posting_auths) и GESTS;
  • Если статус равен одному (всё ок), производятся дальнейшие действия;
  • Создаётся тайтл с вопросом, берётся пермлинк опроса;
  • Далее получаем список всех голосов по пермлинку опроса;
  • Суммируем все GESTS, находя общую сумму, создаём массивы вариантов и голосовавших пользователей;
  • Суммируем ГЕСТЫ для каждого варианта ответа благодаря variants, где ключ - это id варианта;
  • Также производим формирование массива users, куда добавляем объекты с логином и GESTS пользователя;
  • Вычисляем процент для каждого варианта ответа при помощи деления суммы GESTS варианта каждого на общую сумму и умножения на 100 с фиксацией до двух знаков после запятой;
  • Далее выводим в текст поста строку с уведомлением о методе учёта СГ, после чего формируем markdown таблицу с вариантами ответов и процентами;
  • В конце выводим топ 100 пользователей (от большей СГ к меньшей) по каждому варианту. Для этого проходим циклом по массиву users и, взяв название варианта из базы с опросом, выводим заголовок, сортируем логины по GESTS и выводим при помощи ещё одного цикла markdown списком.
    В функции публикации поста отправляются такие-же данные, что и при создании опроса, но в отличие от того варианта здесь массив вариантов ответа и дата окончания опроса берутся из данных опроса / референдума.

Страницы:

  1. Список опросов - берётся список из БД.;
  2. Предварительные или конечные результаты: код такой-же, как описанный выше, но данные выводятся не в markdown формате, а в html. Кроме того, на уровне сервера выводится всё в виде объекта, т.е. так:
    {"question":"Тест?","type":"При расчёте результатов учитывается личная + прокси СГ","variants":[{"answer":"Да","percent":"6.20","voters":"<a href=\"https://dpos.space/profiles/denis-skripnik/golos\" target=\"_blank\">denis-skripnik</a>, <a href=\"https://dpos.space/profiles/golos-votes/golos\" target=\"_blank\">golos-votes</a>, <a href=\"https://dpos.space/profiles/prazdnik/golos\" target=\"_blank\">prazdnik</a>"},{"answer":"нет","percent":"81.34","voters":"<a href=\"https://dpos.space/profiles/lex/golos\" target=\"_blank\">lex</a>"},{"answer":"не знаю","percent":"12.46","voters":"<a href=\"https://dpos.space/profiles/golos50-50/golos\" target=\"_blank\">golos50-50</a>, <a href=\"https://dpos.space/profiles/upromo/golos\" target=\"_blank\">upromo</a>"}],"voters":[]}
    После чего выводится на странице в нужном формате.

В заключение

Напомню ссылку на интерфейс: https://dpos.space/golos-polls.

Всё

Благодарю за внимание.

С уважением, незрячий программист, делегат и Кит @denis-skripnik. Буду рад голосам за меня, как делегата, тут: https://golos.id/~witnesses.

Порядок сортировки:  Популярное
74
  ·  28 дней назад

Hello, @denis-skripnik. You received 90% upvote from Flotilia.


Здравствуйте, @denis-skripnik. Вы получили 90% апвот от Флотилии.

Hello, @denis-skripnik. You received 100% upvote from UPRomo for burned GBG in 1,177 MLN Golos Power. Promoted this post in the queue: @denis-skripnik.

The instruction for burning, for promotion or a drop of posts, Invest in UPRomo, Agreement on the use of service.


Здравствуйте, @denis-skripnik. Вы получили 100% апвот от UPRomo за сожженные GBG примерно на 1,177 МЛН СГ. Продвигали этот пост в очереди: @denis-skripnik.

Инструкция по сжиганию GBG для продвижения или задвигания постов, Для инвесторов, Соглашение об использовании.

46
  ·  27 дней назад

👍 by @rentmyvote service

63
  ·  27 дней назад

Здравствуйте, @denis-skripnik.
Вы получили 100.00% апвот от @goloslove.
Оплатил(a) ап поста: @denis-skripnik.

Инструкция по использованию сервиса.

69
  ·  27 дней назад

@denis-skripnik, поздравляю! Вы добились некоторого прогресса на Голосе и были награждены следующими новыми бейджами:

Ваш пост получил наибольшее количество комментариев за день

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

Вы можете проголосовать за это уведомление для того, чтобы помочь всем пользователям Голос. Как? Читайте здесь.