Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Writing a perl based web poll.

by DigitalKitty (Parson)
on Jul 15, 2003 at 06:59 UTC ( [id://274290]=perlquestion: print w/replies, xml ) Need Help??

DigitalKitty has asked for the wisdom of the Perl Monks concerning the following question:

Hi.

I need a little help with this particular project. The goal is to create a perl based web poll ( the poll questions I asked are merely examples) that retains a 'running total' of each potential response ( virtually identical to the polls created on http://www.perlmonks.org ). If an option has never been selected, there shouldn't be a red line to its immediate right. If an option has been selected by 15 separate individuals, the bar should reflect that fact (longer).

I've been at work for far too long today so please forgive the verbosity of the code sample. *grin*

#!c:\perl\bin\perl.exe -w use strict; use CGI qw( :standard ); my %data = (); my $item = ''; my $value = 0; my $key; my $total; print header; $data{total}++; if( !param('age') ) { $data{'age_none'}++; } elsif ( param('age') eq 'under18' ) { $data{'under18'}++; } elsif ( param('age') eq '18to30' ) { $data{'18to30'}++; } elsif ( param('age') eq '30to45' ) { $data{'30to45'}++; } elsif ( param('age') eq '45to65' ) { $data{'45to65'}++; } elsif ( param('age') eq 'over65' ) { $data{'over65'}++; } if( !param('gender') ) { $data{'gender_none'}++; } elsif ( param('male') ) { $data{'male'}++; } elsif ( param('female') ) { $data{'female'}++; } if( !param('diabetic') ) { $data{'diabetic_none'}++; } elsif ( param('diabetic') ) { $data{'Not_diabetic'}++; } elsif ( param('diabetic') ) { $data{'Diabetic'}++; } if( !param('heart') ) { $data{'heart_none'}++; } elsif ( param('heart') ) { $data{'No_heart_attack'}++; } elsif ( param('heart') ) { $data{'Heart_attack'}++; } if( !param('exercise') ) { $data{'exercise_none'}++; } elsif ( param('exercise') ) { $data{'No_regular_exercise'}++; } elsif ( param('exercise') ) { $data{'Regular_exercise'}++; } if( !param('group') ) { $data{'group_none'}++; } elsif ( param('group') ) { $data{'No_support_group'}++; } elsif ( param('group') ) { $data{'Support_group'}++; } open( RESULTS, ">survey.txt" ) or die "Error : $!\n"; foreach $item ( keys %data ) { print RESULTS "$item $data{$item}\n"; } close RESULTS; print start_html; open( RESULTS, "<survey.txt" ) or die "Error : $!\n"; foreach( keys ( %data ) ) { while(<RESULTS>) { ($item, $value) = split( ' ' ); print table(Tr(td( $item ), td( { -width => "$value%", -bgcolor = +> "red" }, br) ) ); } } close RESULTS;

Thanks,
-Katie.

Replies are listed 'Best First'.
Re: Writing a perl based web poll.
by Skeeve (Parson) on Jul 15, 2003 at 07:40 UTC
    I don't see, where you get your old data from.
    You do a $data{total}++ but this will give you 1 always.
    Maybe you should use dbmopen? This could store your values and give you back a hash immediately. But you should take care that no two running scripts access them at the same time.
    I'd write your if - elsif blocks like this:
    if (param('age') =~ /^(under18|18to30|30to45|45to65|over65)$/) { ++$data{$1}; } else { ++$data{'age_none'}; }

      Hi there,

      As Skeeves comments, every time the cgi is run you star afresh with empty data. You should first of all open your results file and retrieve the data stored there, then add the appropriate values and write them back to the file. While you are at it, you can store the contents on a variable so you don't need to open it again just to display it's results (which right now is overwritten with your last run, instead of accumulated). Something in the line of:

      ### reading open FILE, "+<results.txt" or print CGI::STDERR 'Cannot open results file: $!' and die $!; my %results = map { split / /, $_ } <FILE>; ### working # this ++'s where appropriate my %new_results = process( %results ); ### writing back while ( my ($key, $val) = each %new_result ) { print FILE "$key $val\n"; } close FILE or die "Cannot close results file!!! $!";

      If this takes too long to process and you don't want to lock the results file for other instances that may be running, just use a temporary file, or inmediately close the FILE handler and reopen it after the processing is done. Have a look at modules such as IO::File and similar for blocking and nonblocking I/O... There's probably a clever tie out there in CPAN to makes this much easier, tie is your friend...

      Good luck,

      --
      our $Perl6 is Fantastic;

Re: Writing a perl based web poll.
by Tanalis (Curate) on Jul 15, 2003 at 09:46 UTC
    As has already been pointed out by Skeeve, you're not reading in the data there before you start incrementing the results.

    It's also a very good idea to lock the results file before you write to it - especially with web applications - otherwise you could find that the file gets clobbered and you lose the data in it.

    I've always done this using Fcntl's flock method, which can be set to only allow one process read/write access to a file at a time.

    It seems most effective (from experience) if you use flock on a lock file, and lock that, rather than the results file directly before you write any data. For example:

    use Fcntl qw/:flock/; open LOCK, ">", "results.dat.lck" or die; flock LOCK, LOCK_EX; open OUT, ">", "results.dat" or die; # print data close OUT; close LOCK; # releases the lockfile, lets other processes write
    I'm sure this is documented somewhere in a much better way than I can explain it, and with the reasons behind the use of the external lock file rather than direct locking, but I can't find it at the minute. I'll keep looking .. *grin*

    Hope that helps.

    -- Foxcub
    #include www.liquidfusion.org.uk

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://274290]
Approved by allolex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (7)
As of 2024-04-25 08:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found