Скоро некоторые из нас пойдут отдавать свои голоса за очередных кандидатов в депутаты. Депутаты являются нашими представителями и им мы предоставляем право принимать некоторые законодательные решения за нас. В данных условиях логично выбирать тех кто делает свой выбор также как и мы.
Голоса депутатов находятся на vote.duma.gov.ru. Нам остаётся проголосовать за важные для нас законопроекты в соответствии со своим видением и получить рейтинг на основе которого и делать выбор на выборах.
Я выбрал наименее затратный путь и написал JavaScript расширение для Chrome. Работа с ним организованна через консоль браузера (Ctrl + Shift + J). Бонусом я протестировал поддержку русского языка в JavaScript без препроцессоров.
Под катом вас ждёт код с комментариями и комментарии к статье.
В папке "vote" три файла "manifest.json", "insert.js", "script.js" в кодировке UTF-8 (без BOM).
Код:
Файл "manifest.json":
{
"manifest_version": 2,
"name": "Твой кандидат",
"description": "Расширение для подсчёта персонального рейтинга депутатов на vote.duma.gov.ru",
"version": "1.0",
"content_scripts": [
{
"matches": [ "http://vote.duma.gov.ru/*" ],
"js": [ "insert.js" ],
"run_at": "document_end"
}
],
"web_accessible_resources": [
"script.user.js"
]
}
Часть манифеста "web_accessible_resources" даёт доступ странице загружать и использовать перечисленные в ней файлы плагина. "script.js" это основной скрипт в котором вся логика.
Хром не даёт прямого доступа расширениям к переменным страницы. Мы внедряем свой скрипт("script.js") в саму страницу при помощи "insert.js".
Файл "insert.js":
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = chrome.extension.getURL("script.user.js");
script.async = 1;
document.head.appendChild(script);
Файл "script.user.js":
// ==UserScript==
// @name Твой кандидат
// @description Расширение для подсчёта персонального рейтинга депутатов на vote.duma.gov.ru
// @author ivan386
// @license MIT
// @version 1.0
// @run-at document-end
// @include http://vote.duma.gov.ru/*
// ==/UserScript==
javascript:
(function() {
'use strict';
var вывести = function( текст ){
console.log( текст );
document.querySelector( "#текст" ).innerText = текст;
};
var голосовать = function( ваш_голос )
{
if ( typeof deputiesData !== 'undefined' )
{
/* Для хранения рейтинга и остальных данных депутатов используется localStorage */
var депутаты = JSON.parse( localStorage.getItem( "депутаты" ) || "{}" );
/* В переменной deputiesData храняться голоса депутатов за текущий закнопроект и другие данные. */
deputiesData.forEach( function( депутат )
{
var ls_депутат = депутаты[ депутат.url ];
/* Восстанавливаем сохранённый рейтинг или устанавливаем 0 */
депутат.рейтинг = ( !ls_депутат ) ? 0 : ls_депутат.рейтинг;
/* Восстанавливаем статистику */
депутат.статистика = ( !ls_депутат ) ? {} : ( ls_депутат.статистика || {} );
/* Копируем имя */
депутат.имя = депутат.sortName;
/* Сохраняем статистику голосов депутатов на будущее. */
if ( typeof( депутат.статистика[ депутат.result ] ) === 'undefined' )
депутат.статистика[ депутат.result ] = 1;
else
депутат.статистика[ депутат.result ] ++;
депутат.количество = 0;
for ( var голоса in депутат.статистика )
депутат.количество += депутат.статистика[голоса];
/* У каждого депутата есть ссылка с его ID на результаты его голосования. */
/* Используем её как уникальный идентификатор. */
депутаты[ депутат.url ] = депутат;
/* Результат голосования каждого депутата лежит в переменной result */
/* Соответствия взяты из функции renderer скрипта на странице с результатами голосования на vote.duma.gov.ru. */
/* Значение -1 соответствует голосу "За" */
/* Значение 0 соответствует голосу "Воздержался" */
/* Значение 1 соответствует голосу "Против" */
/* Значение 2 соответствует голосу "Не голосовал" */
/* Меняем рейтинг депутата в соответствии с нашим выбором. */
депутат.рейтинг += ( депутат.result == ваш_голос ) ? 1 : -1;
} );
/*Сохраняем рейтинг и другие данные в localStorage */
localStorage.setItem( "депутаты" , JSON.stringify( депутаты ) );
вывести( "голос " + ( ваш_голос == -1 ? "За" : "Против" ) + " принят" );
}
else
вывести( "на странице не найдено результатов голосования депутатов за законопроект" );
};
var за = function()
{
/* Значение -1 соответствует голосу "За" */
return голосовать( -1 );
};
var против = function()
{
/* Значение 1 соответствует голосу "Против" */
return голосовать( 1 );
};
var по_рейтингу = function( список )
{
var список_по_рейтингу = [];
var вывод = [];
for ( var ключ in список )
список_по_рейтингу.push( список[ ключ ] );
список_по_рейтингу.sort( function( первый, второй )
{
/* Сортируем в порядке убывания рейтинга */
return второй.рейтинг - первый.рейтинг;
} );
список_по_рейтингу.forEach( function( элемент )
{
/* Выводим результаты в консоль */
вывод.push( элемент.имя + ": " + элемент.рейтинг + ( элемент.количество ? " (" + элемент.количество + ")" : "" ) );
} );
return вывод.join( "\n" );
};
var рейтинг_депутатов = function()
{
var депутаты = JSON.parse( localStorage.getItem( "депутаты" ) || "{}" );
вывести( по_рейтингу( депутаты ) );
};
var рейтинг_партий = function()
{
var депутаты = JSON.parse( localStorage.getItem( "депутаты" ) || "{}" );
var партии = {};
for ( var идентификатор in депутаты )
{
var депутат = депутаты[ идентификатор ];
var партия = партии[ депутат.factionCode ];
if ( партия )
{
/* Рейтинг партии складывается из рейтинга депутатов. */
партия.рейтинг += депутат.рейтинг;
партия.количество ++;
}
else
партии[ депутат.factionCode ] = { имя: депутат.faction , рейтинг: депутат.рейтинг , количество: 1 };
}
вывести( по_рейтингу( партии ) );
};
var окно = (typeof unsafeWindow === 'undefined') ? window : unsafeWindow;
document.body.insertBefore( document.createElement( "div" ) , document.body.firstChild ).innerHTML = 'Твой кандидат:\n\
<button onclick="за()">За</button>\n\
<button onclick="против()">Против</button>\n\
<button onclick="рейтинг_партий()">Рейтинг партий</button>\n\
<button onclick="рейтинг_депутатов()">Рейтинг депутатов</button>\n\
<div id="текст"></div>';
окно.за = за;
окно.против = против;
окно.рейтинг_депутатов = рейтинг_депутатов;
окно.рейтинг_партий = рейтинг_партий;
if ( typeof( окно.deputiesData ) !== 'undefined' )
deputiesData = окно.deputiesData;
вывести( "за() - проголосовать за\n\
против() - проголосовать против\n\
рейтинг_депутатов() - выводит текущий рейтинг депутатов в соответствии с вашими голосами\n\
рейтинг_партий() - выводит текущий рейтинг партий в соответствии с вашими голосами\n\
" );
})();
void(0);
Установка
- Копируем папку "vote" с содержимым на локальный диск.
- В браузере Chrome открываем "chrome://extensions/" или "Главное Меню > Дополнительные инструменты > Расширения"
- Ставим галочку "Режим разработчика"
- Нажимаем "Загрузить распакованное расширение..."
- Находим и выбираем папку "vote" со скриптами.
- Нажимаем ОК.
Использование
Голосуем
- Заходим на страницы с голосами депутатов на vote.duma.gov.ru.
Например: http://vote.duma.gov.ru/vote/95967 (ссылка взята здесь) Открываем консоль браузера (Ctrl + Shift + J).
3.1. Если против пишем:
против()
3.2. Если за пишем:
за()
- Нажимаем Enter
Получаем рейтинг
- Заходим на любую страницу vote.duma.gov.ru.
Открываем консоль браузера (Ctrl + Shift + J) ещё не открыта.
3.1. Для вывода рейтинга депутатов:
рейтинг_депутатов()
3.2. Для вывода рейтинга партий:
рейтинг_партий()
- Нажимаем Enter
Либо можно воспользоваться кнопками вверху страницы.
Результат
В результате каждый пользователь этого скрипта получает свой рейтинг депутатов и партий в соответствии со своим выбором и выбором депутатов.
Пример рейтинга депутатов:
Иванов Иван Иванович: 5
Петров Пётр Петрович: 0
Сидоров Владимир Владимирович: -5
Пример рейтинга партий (в скобках количество депутатов):
Пиастрская: 100 (10)
Фарианская: 0 (1)
АнтиПиастрская: -100 (1)
Все имена и события вымышлены. Совпадения случайны.
Заключение
Надеюсь этот скрипт поможет делать более осознанный выбор своего представителя в законодательной власти. А заодно и покажет пример написания расширения для анализа данных на государственных сайтах .
Об ошибках прошу писать в личные сообщения.