Gossamer Forum
Home : General : Perl Programming :

Perl and 'Averaging?' HELP!

Quote Reply
Perl and 'Averaging?' HELP!
I'm creating a script which will allow my visitors to imput number values as ratings, have them added (or weighted) and emitted into a file which takes the name of the thing rated. (out of 100)
I used
open (LOG, ">>../smee/$name.txt") || &ErrorMessage;
print LOG "+$smeerating\n";
close (LOG);
to create the file, which will also create any file should it not exist.

Well, I want to be able to add all the ratings of that file together and divide by the AMOUNT OF RATINGS (effectively giving an average rating).

I've tried everything I could, and nothing has worked. Please provide some insight into how I can do this!

Quote Reply
Re: Perl and 'Averaging?' HELP! In reply to
Are the ratings on multiple lines or in a single line with delimiters?

If it's in a single line, you could do...
Code:
open (LOG, "../smee/$name.txt") || &ErrorMessage;
$ratings = <LOG>;
close (LOG);
@rates = split(/\|/, $ratings);
$num = $#rates + 1;
$total = 0;
foreach $vote (@rates) {
$total += $vote;
}
$average = $total / $num;
That assumes that your delimter is a |. Just change the '\|' depending on why your using.

As for multiple lines... I don't know.

--Drew
Quote Reply
Re: Perl and 'Averaging?' HELP! In reply to
Actually, I got it to work, BUT it does not average. When I find the average rating, it takes the rating the person gave, not average. (I used the ratings 100, 90, and 23 to figure this out).

Also, unless the file is created already, perl will not create it and give an error.

I have decided to display the whole script. The scalars are all correponding to form data, and the name scalar is part of a hidden, archived field. This is my first real attempt at a useful script, so it is VERY simplistic.
#!/usr/bin/perl

require "subparseform.lib";
&Parse_Form;

$wait = $formdata{'wait'};
$theme = $formdata{'theme'};
$pacing = $formdata{'pacing'};
$comparison = $formdata{'comparison'};
$overall = $formdata{'overall'};
$name = $formdata{'name'};

$smeepace = $pacing*2;
$smeecomp = $comparison*2;
$smeeover = $overall*4;
$smeerating = $wait+$theme+$smeepace+$smeecomp+$smeeover;

open (LOG, "../smee/$name.txt") || &ErrorMessage;
$smeeratings = <LOG>;
close (LOG);
@rates = split(/\|/, $smeerating);
$num = $#rates + 1;
$total = 0;
foreach $vote (@rates) {
$total += $vote;
}
$average = $total / $num;

print "Content-type: text/html\n\n";
print "<P>You rated $name. Thank you.";
print "<P>The Smee scale rating for $name is $smeerating.";
print "<P>This data has been added to the $name LOG for saving.";
print "<P>Current $name average is $average.";

sub ErrorMessage {
print "Content-type: text/html\n\n";
print "The server can't open the file. It either doesn't exist or the permissions are wrong. \n";
exit;
}

Also, Perl is not writing the values to the log txt using the print LOG tag. It says it does, but really, it doesn't.

One more thing, I am not sure about the | thing you were telling me about. Do I need those for some reason?

Quote Reply
Re: Perl and 'Averaging?' HELP! In reply to
More information about dillemma:

I have MULTIPLE files to rate, hence the $name.txt tag. There are about 100 to rate, so it's hard to get the script to take from each one...

Quote Reply
Re: Perl and 'Averaging?' HELP! In reply to
In Reply To:
Also, Perl is not writing the values to the log txt using the print LOG tag. It says it does, but really, it doesn't.
I know. The codes I gave you read the data from a file into a variable, splits each rating by a specified delimeter into an array, counts the total number of rates, adds them together, and then finds the average.

You will need to add codes back into your script for writing to the files.

Also, the reason why you aren't getting any results with the averaging is because of a typo:
Code:
open (LOG, "../smee/$name.txt") || &ErrorMessage;
$smeeratings = <LOG>;
close (LOG);
@rates = split(/\|/, $smeerating);
The first red variable is the data retrieved from the file. The second red variable is the most recent rating, as defined earlier:
Code:
$smeerating = $wait+$theme+$smeepace+$smeecomp+$smeeover;
To get the average rating, the second red variable must be $smeeratings. Note the trailing 's'.

In Reply To:
One more thing, I am not sure about the | thing you were telling me about. Do I need those for some reason?
You were printing rates to a file at one point, weren't you? And didn't you use someting to distinguish one rating from another? Whatever you were using must be what is used to split the ratings into an array.

I don't know what else to say... maybe someone with a degree in programming can help you.

--Drew
Quote Reply
Re: Perl and 'Averaging?' HELP! In reply to
Thanks very, very much! I am really learning this now. I have one last dillema. The script isn't counting votes! It's always 100/1 or 23/1 no matter how many times I've done it.

Quote Reply
Re: Perl and 'Averaging?' HELP! In reply to
Well, did you ever add codes to have the script write to the file?

Please re-post your entire script and post a sample log file, and the URL where you are running the script.

--Drew
Quote Reply
Re: Perl and 'Averaging?' HELP! In reply to
Hey, I figured it out! THANKS! My problem was that when I wrote the ratings to the script, I didn't do $smeerating | (with the dilamiter). That's what splits it all into arrays and stuff. Thanks very much for all the help.

Also, lets say I want to include the average rating file (something I've done successfully) into a page using SSI. Let's say that file doesn't exist. Is there a way to replace [An error occured...] with something like "No rating"?

One last thing? Say I get a rating of 86.666666666666667. How do I crop it to just 86 or 87?

Quote Reply
Re: Perl and 'Averaging?' HELP! In reply to
To get whole numbers, change:
Code:
$average = $total / $num;
To:
Code:
$average = int $total / $num;
To get the average up to two decimal places, change:
Code:
$average = $total / $num;
To:
Code:
$average = sprintf("%.2f", $total / $num);
Also, you should be careful about printing delimeters. If the file didn't previously exists, print only the value. If the file does exists, print the delimeter and then the value. The reason to do it this way is so you don't end up with ratings, for example, of '90' and ''. The script thinks there is one rating more then exists because of the trailing delimeter, so for example, you'd get an average rating of '45', instead of '90'.

--Drew
Quote Reply
Re: Perl and 'Averaging?' HELP! In reply to
One thing I forgot...

What would I use to like, log IPs and prohibit voting more than once. I want to make sure that you can vote for each file, and that voting on one file will not disable the voting options on ALL files.

THANKS for the help with everything, Drew. I really, really appriciate it.