Gossamer Forum
Home : Products : DBMan : Customization :

Updated MOD: Top 10/Record Hit Counter (More Accurate)

Quote Reply
Updated MOD: Top 10/Record Hit Counter (More Accurate)
##################################################################
### (More Accurate) Record Hit Counter and Top Ten Hits List ###
### originally by leisurelee and JPDeni ###
### redesigned by TheFew (AJ) ###
### arusso@thefew.com ###
### see in action: http://www.thefew.com/cgi-bin/db/db.cgi ###
### ###
### Modified: 21 Apr 2000 - by leisurelee and JPDeni ###
### Modified: 05 Apr 2000 - by TheFew (AJ) ###
##################################################################

Well, it took me a few hours, but I got all the bugs worked out. This is partly a continuation of thread www.gossamer-threads.com/scripts/forum/resources/Forum12/HTML/002847.html .

The difference in the 05 Apr 2000 version from the original is an
iplog.txt file is created in the "temp" directory and when a record is hit DBMan writes the line:
IP Address|UNIX Date|$db_key
to iplog.txt. If within a specified time the same record is hit by the same IP Address it will NOT record a hit. After the specified time, the line will be deleted, and that IP Address can hit the record and count another hit. This keeps cheaters from pushing a record to the top.

How to set up this MOD:

Create a directory within your DBMan directory. Name the new directory "temp". Set the permissions on the directory to 777 (-rwxrwxrwx)

###############################################################
# default.cfg #
#-------------------------------------------------------------#
# Add the following to your .cfg file: #
###############################################################

### In the # File and URL's section add:
Code:
# Full Path and File name of the record view count directory.
$counter_dir = $db_script_path . "/temp";

### After $auth_logoff = "http://www.yourdomain.com"; add:
Code:
# How many seconds to remove the old ip addresses for record view count?
# 3600 - One Hour (Recomended)
$ipupdate = "3600"; ### Added for time interval
###############################################################
# html.pl #
#-------------------------------------------------------------#
# In 'sub html_record' (or 'sub html_record_long', if you're #
# using the short/long display mod): #
###############################################################

### MOVE the following line
Code:
($db_auto_generate and print &build_html_record(%rec) and return);
### below this line
Code:
my (%rec) = @_;
### AND add the following after the moved line
Code:
&top10($rec{$db_key});

###--- What you will end up with at the top of sub html_record(_long) ---####
Code:
my (%rec) = @_;
($db_auto_generate and print &build_html_record(%rec) and return);
&top10;

### Reference $countup wherever you want to show the # of hits made to the record


### To include link to a top ten list of the most visited records, add the following subroutine:

Code:
sub html_topten {
#-------------------------------------------------------------
opendir (TEMPDIR, "$counter_dir");
@files = readdir(TEMPDIR); # Read in list of files in directory..
closedir (TEMPDIR);

FILE: foreach $file (@files) {
next if ($file =~ /^\./); # Skip "." and ".." entries..
next if ($file =~ /^index/); # Skip index.htm type files..
next if ($file =~ /^iplog/); # Skip iplog.txt file..
open (COUNTER, "<$counter_dir/$file");
$count{$file} = int(<COUNTER> );
close COUNTER;
}

foreach $key (sort {$count{$b} <=> $count{$a} } keys %count) { push (@top_ten,$key); }

&html_print_headers;
print qq|
<html>
<head><title>$html_title: Top Ten Records.</title></head>
<BODY>
header html code goes here
|;

for ($i=0;$i<10 ;$i++) {
$toparray .= "$top_ten[$i],";
}
chop $toparray;
foreach my $toplist (split(/,/,$toparray)) {
&html_record(&get_record($toplist)); ## See below if you're using short/long display mod
}
print qq|footer html code goes here|;
&html_footer;
print qq|</body></html>|;
}
###############################################################
# If you're using the short/long display mod, look above #
# at the commented line and change as appropriate #
###############################################################

### Instead of:
Code:
&html_record(&get_record($toplist));
#### Use the following, and change $rec{'FieldName'} to match your database.
Code:
%rec = (&get_record($toplist));
print qq|
<a href="$db_script_link_url&$db_key=$rec{$db_key}&view_records=1&ww=1">$rec{'FieldName'}</a>
|;

### In 'sub html_footer', add
Code:
print qq!|<A HREF="$db_script_link_url&topten=1">Top Ten</A> ! if ($per_view);

###############################################################
# db.cgi #
#-------------------------------------------------------------#
# Delete (or comment out) this line in sub get_record: #
###############################################################
Code:
($restricted = 1) if ($auth_modify_own and !$per_admin);

### In 'sub main', after
Code:
if ($in{'add_form'}) { if ($per_add) { &html_add_form; } else { &html_unauth; } }
### add
Code:
elsif ($in{'topten'}) { if ($per_view) { &html_topten; } else { &html_unauth; } }

### Also, add new subroutine:
Code:
sub top10 {
#-----------------------------------------------------------
my ($db_key) = $_[0];

$count_up= "$counter_dir/$db_key";
$iptime = time();
$remote = $ENV{'REMOTE_ADDR'};
$cheat = 0;

if (-e "$counter_dir/iplog.txt") {
open (iplog, "+<$counter_dir/iplog.txt");
if ($db_use_flock) { flock(iplog, 2); }
@ipdata = <iplog>;
seek (iplog, 0, 0);
truncate (iplog,0);
foreach $log (@ipdata) {
@ips = split(/\|/, $log);
$iptotal = $iptime - $ips[1];
if (($ips[0] == $remote) && ($ips[2] == $db_key) && ($iptotal < $ipupdate)) { $cheat = 1; }
if ($iptotal < $ipupdate) { print iplog "$ips[0]|$ips[1]|$ips[2]\n"; }
}
unless ($cheat) { print iplog "$remote|$iptime|$db_key\n"; }
close (iplog);
} else {
open(newip, ">$counter_dir/iplog.txt");
print newip "$remote|$iptime|$db_key\n";
close (newip);
}
if (!$cheat) {
open (COUNT, "$count_up");
if ($db_use_flock) { flock(COUNT, 2); }
$countup = <COUNT>;
$countup++;
close COUNT;
open (COUNT, ">$count_up");
if ($db_use_flock) { flock(COUNT, 2); }
print COUNT $countup;
close COUNT;
} else {
open (COUNT, "<$count_up");
if ($db_use_flock) { flock(COUNT, 2); }
$countup = <COUNT>;
close COUNT;
}
}

That's it! To see it in action, go to:

www.thefew.com/cgi-bin/db/db.cgi

You will automatically be logged in as 'default'. From the menu, choose search and do a search. You'll get the short list. Click on a last name to get the long form. You have just recorded a hit and you will see how many hits there have been on that record. Go back to the short list and click on the record again. It should not record a hit. I have the '$ipupdate' time set to 60 seconds. If you go back to the short list, wait 60 seconds, then click on the record again, you'll see the # hits go up. On that page, go to the Jump To: box and choose 'Top 10' to see the Top 10 list with view counts and alternating colors (did not include these 2 things in this MOD - will be happy to provide to code for it on request).

Any questions please reply to this thread.

Semper Fi,
AJ

[This message has been edited by TheFew (edited May 06, 2000).]

[This message has been edited by TheFew (edited May 06, 2000).]
Quote Reply
Re: Updated MOD: Top 10/Record Hit Counter (More Accurate) In reply to
Cool...Its a wonderful mod.
I will try it and see how it works. Smile

I would like to ask the other question for this mod. Is it possible to use it to count the hits of record for top ten hits of "male" and top ten hits of "female" ??

Thanks a lot

Quote Reply
Re: Updated MOD: Top 10/Record Hit Counter (More Accurate) In reply to
Oops, forgot to add something to the script above! The $rec('db_key') needs to be passed to the top10 subroutine. Here is the change that you need to make:

In html.pl, Instead of:

&top10;

It should be:

&top10($rec{$db_key});

I have already made the change in the first message above.

Sorry to those that may have tried it already! I thought about it on the way to work today whether I included the correct subroutine call!

Have a day!
AJ
Quote Reply
Re: Updated MOD: Top 10/Record Hit Counter (More Accurate) In reply to
I put all the code in the files and all shows up, but when i go to Top Ten link, nothing shows up, only Header and footer.

The iplog.txt is not changed and no new file is created. My temp dir is in mode 777, but nothing happend.

Ideas? Could someone help?

Thanks.


Quote Reply
Re: Updated MOD: Top 10/Record Hit Counter (More Accurate) In reply to
Did you by any chance forget to add to your db.cgi file:

elsif ($in{'topten'}) { if ($per_view) { &html_topten; } else { &html_unauth; } }

Also check the source code of your page to see if there is an error message which will help provide a clue as to why it's not displaying.

I had to fiddle with the code a little to get it to display. Here is what I'm using with my short/long mod where I only want it to display validated records.

sub html_topten { ### top 10 hits w\counter
#-------------------------------------------------------
opendir (TEMPDIR, "$counter_dir");
@files = readdir(TEMPDIR); # Read in list of files in directory..
closedir (TEMPDIR);
FILE: foreach $file (@files) {
next if ($file =~ /^\./); # Skip "." and ".." entries..
next if ($file =~ /^index/); # Skip index.htm type files..
next if ($file =~ /^iplog/); # Skip iplog.txt file..
open (COUNTER, "<$counter_dir/$file");
$count{$file} = int(<COUNTER> );
close COUNTER;
}
foreach $key (sort {$count{$b} <=> $count{$a} } keys %count) { push (@top_ten,$key); }

$page_title = "Top Ten Ads in $class_subtitle";
&html_page_top;

print qq|
<CENTER><TABLE width=350><TR><TH><$font_title>Top Ten Ads</font><P></TH></TR>
<TR><TD><$font>|;

for ($i=0;$i<10 ;$i++) {
$toparray .= "$top_ten[$i],";
}
chop $toparray;
foreach my $toplist (split(/,/,$toparray)) {
%rec = (&get_record($toplist));
#### to display the count add these lines ###########
$count_up= "$counter_dir/$rec{$db_key}";
open (COUNT, "<$count_up");
$countup = <COUNT>;
close COUNT;
######## end display counts ######

if ($rec{'Validated'} eq 'Yes') {
print qq|
<a href="$db_script_link_url&$db_key=$rec{$db_key}&view_records=1&ww=1">$rec{'Title'}</a> ($countup)<BR> |;
}
}
print qq| </font></TD></TR></TABLE></CENTER><P> |;

&html_footer;
&html_page_bottom;
}

Hope this helps :)

Quote Reply
Re: Updated MOD: Top 10/Record Hit Counter (More Accurate) In reply to
I've currently got leisurelee and JPD's Hit Counter and Top Ten list working, but trying to encorporate yr updated mod. I thought I had all the syntax right, but closest I get is the open|save prompt when I execute db.cgi. Below is what I've got ... anything you see glaringly wrong?

in default.cfg
Code:
...
# Full path and file name of the html routines.
require $db_script_path . "/html.pl";
# Full path and file name of the hit counter.
$counter_dir = $db_script_path . "/temp";
# Full path to sendmail on your system
$mailprog = "|/usr/lib/sendmail -t -oeq";
...
# URL to send user if they chose log off. Leave blank and the script will return to
# the logon prompt (although this only makes sense if you are using authentication).
$auth_logoff = "http://www.izmirhigh.com/cgi-local/Database/db.cgi";

# How many seconds to remove the old ip addresses for record view count?
# 3600 - One Hour (Recomended)
$ipupdate = "3600"; ### Added for time interval
...
in html.pl
Code:
...
sub html_record_long {
#----------------------------------------------------------------
my (%rec) = @_;
($db_auto_generate and print &build_html_record(%rec) and return);
&top10;

$rec{$db_key} =~ s/<.?B>//g;
...
<TR><TD COLSPAN="50%">This record has been hit:</TD>
<td COLSPAN="50%"><b>$countup</b> times.</td></tr>|;
...
sub html_topten {
#-------------------------------------------------------------
opendir (TEMPDIR, "$counter_dir");
@files = readdir(TEMPDIR); # Read in list of files in directory..
closedir (TEMPDIR);
FILE: foreach $file (@files) {
next if ($file =~ /^\./); # Skip "." and ".." entries..
next if ($file =~ /^index/); # Skip index.htm type files..
next if ($file =~ /^iplog/); # Skip iplog.txt file..
open (COUNTER, "<$counter_dir/$file");
$count{$file} = int(<COUNTER> );
close COUNTER;
}
foreach $key (sort {$count{$b} <=> $count{$a} } keys %count) { push (@top_ten,$key);
}

&html_print_headers;
print qq|
<html>
<head>
<title>$html_title: Top 10 Records</title>
</head>
<body background="http://www.izmirhigh.com/AB/texture3.gif">
<table border=1 bgcolor="#ffffff" cellpadding=5 cellspacing=3 width=550 align=center valign=top>
|;
for ($i=0;$i<10 ;$i++) {
$toparray .= "$top_ten[$i],";
}
chop $toparray;
foreach my $toplist (split(/,/,$toparray)) {
%rec = (&get_record($toplist));
print qq|
<a href="$db_script_link_url&$db_key=$rec{$db_key}&view_records=1&ww=1">$rec{'LastNameinSchool'}</a>
|;
}

print qq|
<td><$font_title><b><A HREF="$db_script_link_url">$html_title</a> :
Top 10 Records</b></font>
<p><$font>Listing of the Top 10 visited records in the database.
</td>|;

print qq|
<tr bgcolor="$row_color[$color]"
</tr>|;
$color = !$color;

print qq|
<td><a href="$db_script_link_url&$db_key=$rec{$db_key}&view_records=1&ww=1">
$rec{'LastNameinSchool'}</a>
$rec{'Married Name'}
$rec{'First Name (Nickname) & Spouses Name'}
$rec{'YearGrad'}

</td></tr>|;
}
print "</table>";

&html_footer;
print qq|
</td>
</tr>
</table>|;
print qq|
</body>
</html>|;
...
print qq!| <a href="$db_script_link_url&Year_Grad=1&sb=2&so=descend">Top 5 Classes</a> ! if ($per_view);
print qq!| <A HREF="$db_script_link_url&topten=1">Top Ten</A> ! if ($per_view);
...
in db.cgi
Code:
...
if ($in{'add_form'}) { if ($per_add) { &html_add_form; } else { &html_unauth; } }
elsif ($in{'topten'}) { if ($per_view) { &html_topten; } else { &html_unauth; } }
elsif ($in{'add_record'}) { if ($per_add) { &add_record; } else { &html_unauth; } }
...
sub top10 {
#-----------------------------------------------------------
my ($db_key) = $_[0];
$count_up= "$counter_dir/$db_key";
$iptime = time();
$remote = $ENV{'REMOTE_ADDR'};
$cheat = 0;
if (-e "$counter_dir/iplog.txt") {
open (iplog, "+<$counter_dir/iplog.txt");
if ($db_use_flock) { flock(iplog, 2); }
@ipdata = <iplog>;
seek (iplog, 0, 0);
truncate (iplog,0);
foreach $log (@ipdata) {
@ips = split(/\|/, $log);
$iptotal = $iptime - $ips[1];
if (($ips[0] == $remote) && ($ips[2] == $db_key) && ($iptotal < $ipupdate)) { $cheat = 1; }
if ($iptotal < $ipupdate) { print iplog "$ips[0]|$ips[1]|$ips[2]\n"; }
}
unless ($cheat) { print iplog "$remote|$iptime|$db_key\n"; }
close (iplog);
} else {
open(newip, ">$counter_dir/iplog.txt");
print newip "$remote|$iptime|$db_key\n";
close (newip);
}
if (!$cheat) {
open (COUNT, "$count_up");
if ($db_use_flock) { flock(COUNT, 2); }
$countup = <COUNT>;
$countup++;
close COUNT;
open (COUNT, ">$count_up");
if ($db_use_flock) { flock(COUNT, 2); }
print COUNT $countup;
close COUNT;
} else {
open (COUNT, "<$count_up");
if ($db_use_flock) { flock(COUNT, 2); }
$countup = <COUNT>;
close COUNT;
}
}
...
Quote Reply
Re: Updated MOD: Top 10/Record Hit Counter (More Accurate) In reply to
Well, I can't find anything wrong from what you have. Can you give me the url of the db.cgi so I can test it. Also, if you want me to look deeper, e-mail me your html.pl and db.cgi files along with a few records in your database and I'll set it up on my server and check it out. That's about all I can do because from the looks of what you have, it looks fine.


AJ
Webmaster, TheFew.com
http://www.thefew.com
Semper Fi, Do or Die!
Quote Reply
Fixed joebagodonuts' problem... In reply to
Just in case anyone reads this, here was the problem with joebagodonuts script:

He sent me his db.cgi and html.pl files and I looked through them thouroughly. db.cgi was fine, but I came across a subroutine with no close bracket "}". I found the } before the end of the subroutine. After fixing this } I tested it and still had a problem. I found 2 more subs with the } in the wrong place. I fixed it up and tested it and it all worked fine, including the Top10 (More Accurate) MOD.


AJ
Webmaster, TheFew.com
http://www.thefew.com
Semper Fi, Do or Die!