(It's stickytape, just under a different name - lost my password for stickytape and I haven't got that e-mail account any more! DOH)
Anyway....
I don't know if any of you lot remember but some time ago I wanted to write a script which allows people to rate certain items. Well, I've managed to write it....almost.
What I've got at the moment is a script which takes a rating (out of 10) from a form then creates a filename.dat file (if one doesn't exist already), then writes to that file, writing the number of hits that page has received, the number of votes that have been cast, the average vote so far and the IP of the person casting the vote.
It all works just like I want it to so far. However, the final stage of what I want is to create a dynamic top 5(or 10) list of the top voted pages. i.e. somehow take the average from all the filename.dat files and then work out which 5 (or 10) are the highest values, then print these in a table.
So how do I go about this bit then? I'm quite proud of my little self for getting this far, but I'm a bit stumped. I'm guessing I'm going to need sessions (which I'm not particularly hot on!) but any method which works is fine by me!
All help appreciated!
Rich
Generally, if you already have the averages calculated, you'd read the average from each file and put it in an array / hash (depending on which language you're using), then sort the array and print out just the top 5 or 10 entries.
You were doing this in PHP, weren't you?
How do I go about reading the files? All the files are in different directories i.e:
folderA/filename.dat
folderB/filename.dat
folderC/filename.dat
etc
and like I said, each file contains other information too (such as the IP address) - that info is ¦ separated.
Once again, any help is ALWAYS appreciated!
Rich
$array=file('filename.dat');
If the file is a single line, that line will be in $array[0]
As to reading all the files in turn, prolly the best way (if you know the filenames beforehand) is to put the filenames into an array and use a for{} loop to read them in turn - eg
$dirs=("dir1/filename.dat", "dir2/filename.dat");
for ($i=0; $i < count($dirs); $i++) {
$foo=file("$i");
# do stuff with $foo[0] here
}
To deal with the ¦ delimiting, use the split() function - eg
$array=split("¦", $foo[0]);
Currently, all the filename.dat files contain (in this order) the following information:
So from this info, I want to read the 3rd bit of data in that. How do I do this? Is it using the
$array=split("¦", $foo[2]);
thingy? Am I right in putting [2] in there? - because it's the 3rd part of data, or is the [0] for something else?
What does the above give me? i.e. what is the split function doing? Does it read ALL the info in the file, then put it into an array, then extract the bit you tell it to?
So, once I have done this, I will have a list of all the averages right? How do I then read this file and extract, say the top 5?
If I haven't got the first bit right - i.e. about reading all the averages, then don't worry about explaining the getting the top 5 bit - I want to actually understand what's going on here, because I will prolly be using this sort of stuff in the future! (Of course, if you're feeling in a particularly helpful mood today then you could go on to explain about the Top 5 bit :) )
As always, ANY help is seriously appreciated. Thanks for the info and help so far sugarkane,
Rich
Any chance you can explain it Sugar? Or anyone else for that matter. I also don't seem to be able to find a reference for it anywhere.
I've also tried looking for scripts which do this kind of thing at every script resource I know: hotscripts, WMB, cgi-resources, scriptworld, freescripts, the lot but none.
Anyone??
You then want to pass the line through split:
$split_array=split("¦", $foo[0]);
$split_array will now contain the various sections of data, one per array element - if you want the 3rd part, it'll be in $split_array[2]
Does that make sense?
If anyone finds any pre-made script for this sort of thing, let me know, I've looked EVERYWHERE....if no one can find one, when I get this done, I'll give everyone credit for it and publish it, cos I reckon it could be quite useful!
Rich
use strict;
#change 'pathtofolders' to directory holding folderA
my $mainfolder = "/pathtofolders";
my ($avevote,$temp,$top1,$top2,$top3,$top4,$top5);
opendir(LIST,"$mainfolder");
foreach (readdir(LIST)) {
if ($_ eq "." ¦¦ $_ eq "..") { next }
opendir(LIST2,"$mainfolder/$_");
foreach (readdir(LIST2)) {
if ($_ eq "." ¦¦ $_ eq "..") { next }
open(FILE,"$_");
while(<FILE>) {
($avevote,$avevote,$avevote) = split("¦",$_);
if ($avevote > $top1) { $temp = $top1; $top1 = $avevote; $avevote = $temp; };
if ($avevote > $top2) { $temp = $top2; $top2 = $avevote; $avevote = $temp; };
if ($avevote > $top3) { $temp = $top3; $top3 = $avevote; $avevote = $temp; };
if ($avevote > $top4) { $temp = $top4; $top4 = $avevote; $avevote = $temp; };
if ($avevote > $top5) { $top5 = $avevote };
}
close(FILE);
}
closedir(LIST2);
}
closedir(LIST);
print "Content-type: text/html\n\n";
print "<html><body><h2>Top Rated Sites by Voter Averages</h2>";
print "Top Site 1: $top1<br>";
print "Top Site 2: $top2<br>";
print "Top Site 3: $top3<br>";
print "Top Site 4: $top4<br>";
print "Top Site 5: $top5<br>";
print "</body></html>";
exit;
----------------------------------------
may have errors, let me know if it crashes. didn't test it and just out of memory so might be something wrong.
opps, had to disable smileys
(edited by: netcommr at 2:24 pm (gmt) on Oct. 12, 2001
Sugarkane, I've just read your explanation and it seems very straight forward. I will give that a go tonight and report back with how I'm doing and any problems ( :) ) I'm having
Cheers again both of you
Rich
#change 'pathtofolders' to directory holding folderA
my $mainfolder = "/pathtofolders";
# just declaring variables you will be using
my ($avevote,$temp,$top1,$top2,$top3,$top4,$top5);
# this line just opens the directory (for reading)
# you have entered into the variable $mainfolder
opendir(LIST,"$mainfolder");
# scans through each of the contents of the directory
foreach (readdir(LIST)) {
# gets the next entry in the directory if it is
# looking at the parent directory link(..) or
# current directory link(.)
if ($_ eq "." ¦¦ $_ eq "..") { next }
# new line I added here which skips the entry
# if it is not a directory
next unless -d "$_";
# if the current selection passes the above 2 tests
# then it opens the directory, scans over each
# entry and performs the first test
opendir(LIST2,"$mainfolder/$_");
foreach (readdir(LIST2)) {
if ($_ eq "." ¦¦ $_ eq "..") { next }
# if you will have any files or folders in these
# subdirectories holding your data files that you
# don't want to read or open, test for them here
# --I added to skip other directories
next if -d "$_";
# open the current file for reading
open(FILE,"$_");
# scan the file one line at a time
while(<FILE>) {
# split line of data on the '¦' and put contents
# of the third column in the $avevote variable
# --a non-standard trick to do it with 1 variable
($avevote,$avevote,$avevote) = split("¦",$_);
# next 5 lines test to see if the data in $avevote
# is greater then the current values in the $top variables
# if not, then skips to next line
# if true, then takes the value of the $top and
# stores it in a $temp variable just to hold it
# while the $avevote is copied to the $top variable
# then the old value of the $top is copied to $avevote
# --this just swaps the value basically to put
# the highest values at the top and lowest fall
# off the bottom
if ($avevote > $top1) { $temp = $top1; $top1 = $avevote; $avevote = $temp; };
if ($avevote > $top2) { $temp = $top2; $top2 = $avevote; $avevote = $temp; };
if ($avevote > $top3) { $temp = $top3; $top3 = $avevote; $avevote = $temp; };
if ($avevote > $top4) { $temp = $top4; $top4 = $avevote; $avevote = $temp; };
if ($avevote > $top5) { $top5 = $avevote };
}
# this closes the current open file
close(FILE);
# this point the script loops to get the next file
}
# when all the files have been read, the
# subdirectory is closed
closedir(LIST2);
# loops to get the next subdirectory (IE folderB)
}
# all subdirectories have been scanned and no
# more data to read, close $mainfolder
closedir(LIST);
# this is a required header so the browser can
# read your output, without it your script crashes
print "Content-type: text/html\n\n";
# this line just print a header, add what
# ever you need to print here
print "<html><body><h2>Top Rated Sites by Voter Averages</h2>";
# these lines print your top listings,
# variable $top1 is 1st, $top5 is 5th
print "Top Site 1: $top1<br>";
print "Top Site 2: $top2<br>";
print "Top Site 3: $top3<br>";
print "Top Site 4: $top4<br>";
print "Top Site 5: $top5<br>";
# this is just for continuity of the above header
print "</body></html>";
# this just tell the server, "I'm Done"
exit;
---------------------
basically, all it does is open ALL of the folders, (folderA,B,C,etc), which are in the $mainfolder. Then it opens all the files in each folder and reads each line of the file. By the end it will have the highest value found for average votes stored in the $top1 variable, next highest in $top2, etc.
If you want to display more than the top 5, say top 10, then add $top6 - $top10 in 3 places. The first place is in the variable declaration line. Second is in the jumble of lines which do the swapping of values, just make sure the last line (currently $top5) is formatted like it is and all above it are in the same format as they are now. You can't just add more lines without changing line 5. Then, last of all, you need to print the values.
Just remember it will open ALL folders in $mainfolder and scan ALL files contained in them. That means any folders, or files in those folders, you don't want opened, you need to put in tests to skip them.
#TIP - the 'use strict;' line is for developement stage only, remove from script once you are finished with it, it will run faster. The "strict" is use to help you manage all your variables so you don't make mistakes, such as typos. This will force the script to crash if you have an undefined variable name, such as you try to use '$avvote' by mistake. It has more meaning than this, but for short scripts like this, thats the best benefit. Also, it is a good idea to use the -w flag after the #!/usr/bin/perl line during testing, this is for warnings output.
such as #!/usr/bin/perl -w
A great tool for testing scripts is testmy.cgi available here [perlarchive.com], this link is posted because the Craig Richards [craigrichards.com] site is down. If his site does not come back up and you can't find it, I will make it available.
This will probably really annoy you, but I think I'm starting to make progress with the PHP script now, so it looks like I am going to be able to use that. However, I will keep a copy of that script (which I now (almost) fully understand thanks to your descriptions) in my spare scripts folder, just in case.
This is why I love WebmasterWorld so much, 'cos there's always someone available to help, and usually it's someone with years of experience that can explain something better than most of my University lecturers could!
If you 2 guys (and anyone else) could keep your eyes peeled on this thread for the next couple of days I would really appreciate it, cos I've nearly finished the PHP version of this. I will probably need some last minute help etc!
Thanks again both of you,
Rich
(P.S. - what's with the smiley in the last script, is it meant to be a smiley or is it meant to be ;) and you forgot to turn smileys off? hehe lol)
Just noticed something quite neat. When you shorten WebmasterWorld with the letters "W M W" but without the spaces, it automatically replaces it. Nice little function!
Currently, I have a file called index2.dat which is as follows:
[center]4¦3¦7.6666666666667¦127.0.0.1¦127.0.0.1[/center] Then, I'm trying to do this simplest part and split this file into it's constituents using the split function as you suggested. The php script looks as follows:
<?PHP$myfile=file("index2.dat");
print ($myfile[0]);
$split_myfile=split("¦",$myfile);
print ($split_myfile[2]);
?>
I've put that first print function in there to test that the file is actually opening correctly, which it is, because when I run the script, I get a printout like I should.
However, when it comes to the 2nd print function, the one after the file has been split, NOTHING is printed. Nothing what-so-ever.
I think that once I have this problem solved, I'll be able to do the rest (touch wood). I'll probably be using the sort() function, but I may write my own, depends.
Can someone, ANYONE, please, PLEASE help me solve this, it's 02:36 and I need to go to bed. It's been frustrating me for the best part of 4 hours, and I have NO idea where I'm going wrong.....anyone?
I've fixed it. I don't know why it requires this, maybe someone could tell me. Frankly, I couldn't care, because it's 03:11 now and I am very tired and I have lectures tomorrow. Bummer! Anyway, here's the fix:
I had to implode the index2.dat file first like so:
[center]$implode_myfile = implode($myfile, "¦");[/center] Then I had to resplit it, like so:
[center]$split_implode_myfile = split("¦",$implode_myfile);[/center] Then I could print it like so:
[center]print ($split_implode_myfile[2]);[/center] I don't know why I had to employ this method, like I said, if someone know's why, I wouldn't mind them telling me..... I'll read up on it tomorrow! :)
Anyway, Just two stages left now for this script I feel:
1) Work out how to grab ALL the filename.dat files into 1 array (i.e. just the average vote from each)
2) Sort the Top 5 out and print
Anyone got any helpful hinters along these lines?
Rich
It's chosen NOT to work now. I don't understand why.
At the moment my script separates the data by using ¦ and not ¦ - when I try and use split to separate them by using split
("¦",$myfile); where
$myfile is a variable which has the file in it. When I do that and run the script is gives an error:
Unexpected Regex Error (14)
Any ideas anyone? This is really bugging me now.
I've tried swapping the ¦ for ¦ with ereg_replace, but it comes up with a blank - i.e. it's saying there aren't any ¦ in the file. I'm really confused about this too??
Ideas....anyone?
Hmm, just noticed something.... in the text above I'm trying to have a solid vertical bar (i.e. like an "l") and a split vertical bar ("¦") It appears that they come out the same charcter
Anyway, right, now that know how to extract 1 average from 1 file.....I now need to extract several averages from several files.... lets see if Richard can do that this afternoon.
Cheers again,
Rich
When I try and do this, is seems to get the filename's incorrect. What I mean is, if I put 2 filenames into the array, it tries to locate a file which has both of the filenames together....i.e.
If I have filenameA.txt and filenameB.txt in the array, it tries to find "filenameAfilenameB.txt"
Me is confused....