Скоро некоторые из нас пойдут отдавать свои голоса за очередных кандидатов в депутаты. Депутаты являются нашими представителями и им мы предоставляем право принимать некоторые законодательные решения за нас. В данных условиях логично выбирать тех кто делает свой выбор также как и мы.
Голоса депутатов находятся на 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)
Все имена и события вымышлены. Совпадения случайны.
Заключение
Надеюсь этот скрипт поможет делать более осознанный выбор своего представителя в законодательной власти. А заодно и покажет пример написания расширения для анализа данных на государственных сайтах .
Об ошибках прошу писать в личные сообщения.

