Яндекс цитирования
 

CGI/PERL : практика программирования

 

[ В начало раздела ]

Голосование и опросы на сайте

У многих вебмастеров после некоторого времени раскрутки, накрутки функциональности сайта, возникает желание поводить на сайте виртуальные социологические опросы с различной тематической, аудиторной, целевой направленностью. Конечно, существует множество серверов в Сети, предоставляющих бесплатный (а может где-то и платный) аналогичный сервис. Но, согласитесь, что написать и адоптировать такого рода скрипт к задачам Вашего сайта – дело благородное, трудное и, вместе с тем, интересное.

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

Итак, если Вас заинтересовала моя прелюдия, приглашаю Вас вместе со мною рассмотреть создание CGI-скрипта для проведения виртуального голосования на сайте. А вдруг, кто-то из Вас будет его использовать в кампании по выборам мэра города или района! :))))!

В любой из реализаций скрипта опроса имеются 3 основные функции: Формирование формы голосования (вопрос, варианты ответов, ссылка на текущие результаты) Получение ответа на вопрос от посетителя сайта, его обработка и сохранение информации Вывод текущих результатов голосования по вопросу

Помимо этого я прелагаю добавить еще одну функцию – функцию проверки «на вшивость» голосующего, запрещающую учитывать его ответ, если он недавно уже голосовал. Тем самым мы запретим накрутку результатов голосования.

Теперь же рассмотрим, как можно реализовать масштабируемость нашего решения. Все выглядит прозрачно, если Вы используете только одну форму опроса на сайте. Вам достаточно иметь лишь один файл базы вопросов, жестко зашитым в скрипте. Но что делать, если на сайте существует несколько разделов, страниц, где хотелось бы проводить опрос посетителей? Значит, нам следует при разработке учитывать различие вариантов голосования. Информацию о голосовании будем хранить в двух файлах:

<префикс_файла>_base.txt – база вопросов и результатов голосования
<префикс_файла>_who.txt  - база о голосовавших по вопросу.

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

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

!20000712 20000719
QКакой из языков программирования наиболее хорош для WEB-программирования?
0>>Delphi
0>>Perl, CGI
0>>PHP
0>>ASP
0>>С/С++

, где 1-ая строка содержит информацию о диапазоне календарных дат, когда по вопросу проводится голосование; 2-ая строка, начинающаяся с латинской буквы Q (question – вопрос), содержит собственно вопрос; 3-я и последующие строчки – варианты ответов на вопрос. Начинаются с числа (количество раз, когда выбирали данный ответ), затем разделитель, после сам ответ.

Календарную дату представляем в формате YYYYMMDD. Это поможет нам без проблем следить за сменой календарных дат.

Теперь поговорим о том, как представлять посетителям сайта текущий вопрос и генерировать соответствующую форму. Я здесь для решения этой проблемы выбрал использование протокола SSI (Server Side Include). Таким образом, в HTML-страничке, где мы желаем включить форму опроса по разделу anytopic (файлы anytopic_base.txt и anytopic_who.txt), включаем инструкцию:

для WEB-серверов под Unix:
<!--#include virtual="/cgi-bin/vote.pl?file=anytopic" -->
для Internet Information Server (Windows):
<!--#exec cgi="/cgi-bin/vote.pl?file=anytopic" -->

В ответ на эти инструкции, скрипт должен сгенерировать актуальную форму опроса, выбрав в соответствии текущей дате вопрос и предложив варианты ответа.

Пример формы опроса

1. Пример формы опроса

Вот соответствующий фрагмент кода.

sub create_form {
  local($out,$answers,$qnom);

# поиск фрагмента, удовлетворяющего текущей дате $truequest = 0; $id=0; $qnom = 0; foreach $s (@base) { if ($s =~ /^!(.*)/) { $qnom++; if ($truequest eq 1) {last;} # прекращаем обработку ($date1,$date2) = split(/ /, $1); if(($date1 <= $curdate)and($date2 >= $curdate)) { $truequest = 1; } } elsif ($truequest eq 1) { # обрабатываем текущий вопрос if ($s =~ /^Q(.*)/) {$question = $1;} else { $id++; ($rat,$a) = split(/>>/, $s); $a =~ s/\n//; $answers .= "<tr><td valign=\"top\"><font size=\"1\"><input type=radio name=\"votes\" value=\"$qnom\_$id\"> $a</font></td></tr>\n"; } } }

# создание формы с вопросами print "Content-type: text/html\n\n"; print <<EOF; <!-- Форма виртуального опроса отДСВ - начало фрагмента --> <center><FORM name="myform" action="$ENV{'PATH_INFO'}" method="POST"> <table border=1 width="100%" cellspacing=0> <tr align=center><td><font size="1">$question</font></td></tr> $answers <tr><td align="center"><input type="button" value="Голосовать" onClick="validateform()"> </td></tr></table><input type="hidden" name="file" value="$fileprefix"></FORM> <p><a href="javascript:showresults()">Результаты</a></center> <!-- Форма виртуального опроса отДСВ - конец фрагмента --> EOF ; }

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

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

  ($voteqnom,$voteid) = split(/_/, $FORM{'votes'});

# поиск фрагмента, удовлетворяющего текущей дате $truequest = 0; $id=0; $records = 0; $qnom = 0; foreach $s (@base) { if ($s =~ /^!(.*)/) { $qnom++; if ($truequest eq 1) {last;} # прекращаем обработку if($qnom eq $voteqnom) { $truequest = 1; } } elsif ($truequest eq 1) { # обрабатываем текущий вопрос if ($s =~ /^Q(.*)/) {} else { $id++; ($rat,$a) = split(/>>/, $s); if ($id eq $voteid) { $rat++; $base[$records] = join(">>",$rat,$a); } } } $records++; } # запись результатов в базу open(BASE, ">$VOTE_BASE"); print BASE @base; close (BASE); }

Последней функцией будет отображение результатов голосования по текущему вопросу. На рисунке ниже представлен вариант предоставления результатов голосования.

Пример предоставления результатов

2. Пример предоставления результатов

Предоставление результатов работает на основе технологии использования html-шаблонов.

sub show_results {

local($out); my %hash = ();

# поиск фрагмента, удовлетворяющего текущей дате $truequest = 0; $id=0; $total = 0; foreach $s (@base) { if ($s =~ /^!(.*)/) { if ($truequest eq 1) {last;} # прекращаем обработку ($date1,$date2) = split(/ /, $1); if(($date1 <= $curdate)and($date2 >= $curdate)) { $truequest = 1; } } elsif ($truequest eq 1) { # обрабатываем текущий вопрос if ($s =~ /^Q(.*)/) {$question = $1;} else { $id++; ($rat,$a) = split(/>>/, $s); $total += $rat; %hash = (%hash, "$id", $s); } } } # формируем таблицу $out = ""; $out .= "<table border=0 width=\"100%\">\n"; $out .= "<tr><td colspan=\"3\"><b>Вопрос недели:</b> <br>$question<br> </td></tr>\n";

while(($key,$value)=each(%hash)) { #$value = $hash{$key}; ($rat,$a) = split(/>>/, $value); $len=0; if($total ne 0) { $len = sprintf("%2.0f",($rat/$total)*100); } $tw = $len * 3; $out .= "<tr><td width=\"50%\">$a ($len%)</td><td width=\"50%\">\n". "<table><tr><td width=\"$tw%\" height=\"10\"><img src=\"/images/bar1.gif\" height=10 width=$tw border=0></td></tr></table>\n". "</td></tr>\n"; }

$out .= "<tr><td colspan=\"3\"><br>Всего проголосовало человек: $total</td></tr></table>\n"; return($out); }

Полный исходник скрипта с подробными комментариями Вы можете скачать здесь!

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

Исходник скрипта

© Долгов Сергей, 02.06.2001

 

[ В начало раздела ]


 

 

Все для web-дизана!!! Бард-Путеводитель Много Всего CGI-Гид. Лучшие скрипты... WDH - WebDesignHelp - CGI, JAVA, APPLETS, TOP100! Раскрутка, увеличение посещаемости и индекса цитируемости в поисковых системах.

© 2000-2002 Долгов Сергей

dolgov_sergei@mail.ru

X