Здравствуйте. В этом посте я описывал алгоритм работы такого сервиса, но, как часто бывает, после начала разработки было найдено много недочётов и придумано несколько улучшений.
Давайте рассмотрим это всё.
Удобный интерфейс
Чтобы пользователи, которые не умеют в код, могли пользоваться, сделал интерфейс для системы опросов и референдумов:
- список опросов https://dpos.space/golos-polls/list
- Создание опроса : https://dpos.space/golos-polls/create
- голосование имеет вид
https://dpos.space/golos-polls/voteing/permlink
, а результатыhttps://dpos.space/golos-polls/results/permlink
(эти две ссылки нерабочие).
Кроме того, есть лента опросов и референдумов в аккаунте @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 варианта ответа (соответствует ключу массива ответов).
Как работает:
- Парсит блоки в поисках переводов GBG к null или custom_json операций;
- В первом случае проверяется, что memo - json, что действие - createVote, а также что формат соответствует стандарту,
Во втором проверяется id, что действие voteing, а также что формат соответствует коду голосования;
Создание опроса:
- После проверки формата производится добавление пермлинка: survey-unixTime.
где "survey-" - это первая часть пермлинка, а unixTime - дата и время перевода (timestamp) в Unix time формате; - Добавление в базу данных. В функцию передаются вопрос, ответы, пермлинк опроса/референдума, тип учёта Силы Голоса и Unix time завершения опроса;
- Создаётся переменная title со значением "вопрос " + переменная, выводящая его.
- Формируется строка, в которую добавляется список вариантов ответа (формат markdown маркированного списка).
В body выводится заголовок "варианты ответа" и переменная с их списком.
В функцию публикации отправляется тайтл, пермлинк, текст, ответы и завершение опроса.
В json_metadata добавляется массив с вариантами ответа, что позволяет при желании работать с get_content, а не с базами данных; - В самой функции поста в начале и конце добавляется текст с информацией о том, при помощи чего создан опрос, а также ссылки на голосование и просмотр предварительных или окончательных результатов.
Голосование
- После проверки формата и действия получаем опрос по пермлинку из БД., а затем проверяем, что 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 списком.
В функции публикации поста отправляются такие-же данные, что и при создании опроса, но в отличие от того варианта здесь массив вариантов ответа и дата окончания опроса берутся из данных опроса / референдума.
Страницы:
- Список опросов - берётся список из БД.;
- Предварительные или конечные результаты: код такой-же, как описанный выше, но данные выводятся не в 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.
@denis-skripnik, поздравляю! Вы добились некоторого прогресса на Голосе и были награждены следующими новыми бейджами:
Вы можете нажать на бейдж, чтобы увидеть свою страницу на Доске Почета.
Если вы больше не хотите получать уведомления, ответьте на этот комментарий словом
стоп
Здравствуйте, @denis-skripnik.
Вы получили 100.00% апвот от @goloslove.
Оплатил(a) ап поста: @denis-skripnik.
Инструкция по использованию сервиса.
👍 by @rentmyvote service
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 для продвижения или задвигания постов, Для инвесторов, Соглашение об использовании.
Hello, @denis-skripnik. You received 90% upvote from Flotilia.
Здравствуйте, @denis-skripnik. Вы получили 90% апвот от Флотилии.