Gossamer Forum
Home : Products : DBMan : Customization :

calling random mod from within a sub routine

Quote Reply
calling random mod from within a sub routine
How can I use the random mod inside another sub routine.
What I would like to do display random text or html from a seperate db, on a page. I don't need to call it from a link.
I've put sub get_random in the cgi, and I've got the database set up, but I carn't figure out how to call it from within another sub routine, as the mod uses a seperate sub routine to call &html_record_long.
This is the random mod as is:
Code:
sub get_random {
# --------------------------------------------------------
my ($random) = $_[0];
my (@hits,$line,@lines,@rlines,$random_number,@values,$tmp,$j);
open (DB, "<$db_file_name") or &cgierr("error in get_random.
unable to open db file: $db_file_name.\nReason: $!");
if ($db_use_flock) { flock(DB, 1); }
@lines = <DB>;
close DB;

foreach $line (@lines) {
if ($line =~ /^$/) { next; }
if ($line =~ /^#/) { next; }
push (@rlines,$line);
}
srand( time() ^ ($$ + ($$ << 15)) );
$rvalue = scalar(@rlines);
$random_number = int(rand $rvalue);
@values = &split_decode($rlines[$random_number]);
push (@hits, @values);

return (@hits);
}
sub html_random_record {
# --------------------------------------------------------
# This page displays the results of a successful search.
# You can use the following variables when displaying your
# results:
#
# $numhits - the number of hits in this batch of results.
# $maxhits - the max number of hits displayed.
# $db_total_hits - the total number of hits.
# $db_next_hits - html for displaying the next set of results.
#

my (@hits) = &get_random;
$db_total_hits = 1;

$page_title = "Random Record";
&html_page_top;

&html_record_long(&array_to_hash(0, @hits));

&html_footer;
&html_page_bottom;

}
I've tried using
Code:
my (@hits) = &get_random;
for (0 .. 4) {
&html_adisplay (&array_to_hash($_, @hits));
}
from withinside a subroutine, but it turns up blank.
I've also added another display subroutine.
Code:
sub html_adisplay {
my (%rec) = @_;
print qq|
<TABLE WIDTH="270" CELLPADDING=0 CELLSPACING=0 BORDER=0>
<TR><TD >$rec{'Adhtml'}</TD>
</TR>

</TABLE>
|;
}

thanks
Bob




Quote Reply
Re: calling random mod from within a sub routine In reply to
What page are you trying to insert your random record into? Or, to put it another way, where is the code

Code:
my (@hits) = &get_random;
for (0 .. 4) {
&html_adisplay (&array_to_hash($_, @hits));
}

located?

Also, be aware that the get_random subroutine only returns one record. You will have to change it to return more than one record.


------------------
JPD






Quote Reply
Re: calling random mod from within a sub routine In reply to
What I would like to do with this is to display a number of random ads on a page called from a seperate database.
They may go on several pages, and the number of ads will vary per page.
So i need a way of printing x number of random ads or text or whatever, from a seperate db, from within the sub routine that displayes the page.
The main place would be within the list categories mod, but I would like to be able to use it else where as well.
Thanks
Bob


Quote Reply
Re: calling random mod from within a sub routine In reply to
Would this sorta be like what I did for Frank (fharris) recently with the random banner between records? I was trying to find it, but I couldn't remember the title of the thread and UBB doesn't do searches on recent threads.

Let me see if I can locate it, so I don't have to start from scratch.


------------------
JPD






Quote Reply
Re: calling random mod from within a sub routine In reply to
I had a look at the mod you did for fharris.
Kinda sorta what I need, except I need to take my ads from a seperate database, and I don't need any records just a random list of ads. I do need some way of defining the amount of ads displayed with a variable.

thanks
Bob
Quote Reply
Re: calling random mod from within a sub routine In reply to
What thread was that? I still couldn't find it. Smile

Let me see if I understand you correctly. You want to display a (random?) number of records (interspersed? randomly?) with the search results and the records are in another .db file. Yes?


------------------
JPD






Quote Reply
Re: calling random mod from within a sub routine In reply to
The mod for fharris is at
www.gossamer-threads.com/scripts/forum/resources/Forum12/HTML/002544.html
If you take a quick look at my site at
totallyfreeads.com
you will see on the category and sub category pages, a lot of blank space. This is where I need to print the random ads.
The ads will be in the same format as the ones on the front page.
I also would like to use it on other pages around the site, where I may need to display 1 or 2 random ads on a page, so I need to be able to tell the mod how many random ads to display.

thanks
Bob
Quote Reply
Re: calling random mod from within a sub routine In reply to
I didn't see the spaces, but I guess that doesn't matter.

Use sub get_random, except you want to change the name of the .db file.

Code:
sub get_random_from_other_db {
# --------------------------------------------------------
my (@hits,$line,@lines,@rlines,$random_number,@values,$tmp,$j);

# Change the name of the file to match the name of the .db file you're pulling from.
$other_db_file_name = "$db_script_path" . "/other.db";
open (DB, "<$other_db_file_name") or &cgierr("error in get_random.
unable to open db file: $other_db_file_name.\nReason: $!");
if ($db_use_flock) { flock(DB, 1); }
@lines = <DB>;
close DB;
foreach $line (@lines) {
if ($line =~ /^$/) { next; }
if ($line =~ /^#/) { next; }
push (@rlines,$line);
}
srand( time() ^ ($$ + ($$ << 15)) );
$rvalue = scalar(@rlines);
$random_number = int(rand $rvalue);
@values = &split_decode($rlines[$random_number]);
push (@hits, @values);
return (@hits);
}

Wherever you want to print a random ad, use

Code:
&html_random_record(&array_to_hash(0,&get_random_from_other_db));

Then create a subroutine

Code:
sub html_random_record {
my (%rec) = @_;
print qq|
Here you will define the display of your
random record

|;
}

We can then work out where you want to display the random ad. But for now, I'd like you to be sure that this works right.


------------------
JPD






Quote Reply
Re: calling random mod from within a sub routine In reply to
JPD,
I realy can not get this to work the way it is. This is my sub _html_random_record
Code:
sub html_random_record {
# --------------------------------------------------------
my (%rec) = @_;
print qq|
<TABLE WIDTH="270" CELLPADDING=0 CELLSPACING=0 BORDER=0>
<TR><TD >$rec{'Description'}</TD>
</TR>

</TABLE>
|;
}
Description is the field I,m using to store the code which is field 1.
I have been able to get it to work using the code from sub get_random_from_other_db straight into the sub routine I'm printing it from, like this
Code:
my (@hits,$line,@lines,@rlines,$random_number,@values,$tmp,$j);
open (DB, "<$db_file_name4") or &cgierr("error in get_random.
unable to open db file: $db_file_name.\nReason: $!");
if ($db_use_flock) { flock(DB, 1); }
@lines = <DB>;
close DB;

foreach $line (@lines) {
if ($line =~ /^$/) { next; }
if ($line =~ /^#/) { next; }
push (@rlines,$line);
}
srand( time() ^ ($$ + ($$ << 15)) );
$rvalue = scalar(@rlines);
$random_number = int(rand $rvalue);
@values = &split_decode($rlines[$random_number]);
push (@hits, @values);

print qq| $hits[1] |;
which will print 1 random record, but it won't work the other way.

thanks
Bob


[This message has been edited by lanerj (edited April 19, 2000).]
Quote Reply
Re: calling random mod from within a sub routine In reply to
I don't know what you have in what place.

Can you copy just the subroutine where you want to place the random record and let me see what you're doing? I'm really confused.

(Of course, it could have something to do with the headache pill I took last night. Smile )


------------------
JPD






Quote Reply
Re: calling random mod from within a sub routine In reply to
JPD,
This is the list categories mod of yours I,m using, where I would like to list the random ads. I've taken out all the excess html, to make things easier. I would like to put the random ads in the category listing, and the sub category, where it is marked in the mod.
But I would also like to use it in other sub routines, if we can get it to work.
Code:
sub html_list_categories {
# --------------------------------------------------------
for ($i = 0; $i <= $#db_cols; $i++) {
if ($db_cols[$i] eq "Category" ) {
$fieldnum = $i; $found = 1; $t = 1;
last;
}
}
if (!$found) {
&cgierr("No Category field defined");
}
if ($in{'Category'}) {
$page_title = "$in{'Category'} sub-category listing";
&html_page_top;
print qq|
<table width=459 border=0 cellspacing="0" cellpadding="0" bgcolor=#ffffff>
<tr>
<td>
*************************************************************
This is where I need to print x number of random ads from the random ads db
*************************************************************
</td>
<td bgcolor=#2c0059 align=center valign=top>
|;

$found = 0;
for ($i = 0; $i <= $#db_cols; $i++) {
if ($db_cols[$i] eq "Subcategory" ) {
$fieldnum2 = $i; $found = 1; $t = 1;

last;
}
}
if (!$found) {
&cgierr("No Subcategory field defined");
}
open (DB, "<$db_file_name3") or &cgierr("unable to open $db_file_name3. Reason: $!");
if ($db_use_flock) { flock(DB, 1); }
LINE: while (<DB> ) {
next if /^#/;
next if /^\s*$/;
$line = $_;
chomp ($line);
@fields = &split_decode ($line);
if ($fields[1] eq $in{'Category'}) {
if (!(grep $_ eq $fields[2], @selectfields)) {
push (@selectfields, $fields[2]);
}
}
++$count{$fields[2]};
}
close DB;
foreach $field (sort @selectfields) {
$sfield = &urlencode($field);
print qq| <font face="verdana,arial, helvetica,sans serif" size="-2" color=#ffefef><a
href="$db_script_link_url&Country=$in{'Country'}&Category=$in{'Category'}&Subcategory=$sfield&view_records=1&search_flag=1"
style="color:#ffefef">$field</a></font> <br>|;
}
}

else {
$page_title = "Category Listing";
&html_page_top;
print qq|
<table width=459 border=0 cellspacing="0" cellpadding="0" bgcolor=#ffffff border=0>
<tr>
<td>
*************************************************************
This is where I need to print x number of random ads from the random ads db
*************************************************************
</td>
</tr>
<tr>
<td bgcolor=#2c0059 align=center valign=top>
<IMG SRC="$graphic_dir/selectcat.gif" WIDTH=113 HEIGHT=50 align=center hspace=15 vspace=0>
|;

open (DB, "<$db_file_name3") or &cgierr("unable to open $db_file_name3. Reason: $!");
if ($db_use_flock) { flock(DB, 1); }
LINE: while (<DB> ) {
next if /^#/;
next if /^\s*$/;
$line = $_;
chomp ($line);
@fields = &split_decode ($line);
if (!(grep $_ eq $fields[1], @selectfields)) {
push (@selectfields, $fields[1]);
}
++$count{$fields[1]};
}
close DB;

foreach $field (sort @selectfields) {
$sfield = &urlencode($field);
print qq| <font face="verdana,arial, helvetica,sans serif" size="-2" color=#ffefef><a href="$db_script_link_url&Country=$in{'Country'}&Category=$sfield&list_categories=1&search_flag=1" style="color:#ffefef">$field</a></font> <br>|;
}
print qq|
</td></tr></table>
|;
&html_page_bottom;

}

thanks
Bob

[This message has been edited by lanerj (edited April 20, 2000).]
Quote Reply
Re: calling random mod from within a sub routine In reply to
Is the structure of the database that holds the random ads the same as the structure of the database you're trying to get them to display in?


------------------
JPD






Quote Reply
Re: calling random mod from within a sub routine In reply to
JPD,
I don't realy understand what you mean.
The database used to hold the ad info is called rotads.db, and it has It's own cfg file,
Code:
%db_def = (
ID => [0, 'numer', 5, 8, 1, '', ''],
Description => [1, 'alpha', 225, 255, 1, '', ''],
Userid => [2, 'alpha', -2, 15, 0, '', '']
);
I do have 2 other external dbs, one of which holdes the category and sub category info for the above mod, which I just open and read when needed, I thought this would work the same.
I'm now confused.
can we try this another way.
how can I get
Code:
my (@hits,$line,@lines,@rlines,$random_number,@values,$tmp,$j);
open (DB, "<$db_file_name4") or &cgierr("error in get_random.
unable to open db file: $db_file_name.\nReason: $!");
if ($db_use_flock) { flock(DB, 1); }
@lines = <DB>;
close DB;

foreach $line (@lines) {
if ($line =~ /^$/) { next; }
if ($line =~ /^#/) { next; }
push (@rlines,$line);
}
srand( time() ^ ($$ + ($$ << 15)) );
$rvalue = scalar(@rlines);
$random_number = int(rand $rvalue);
@values = &split_decode($rlines[$random_number]);
push (@hits, @values);

print qq| $hits[1] |;
to print more than 1 random record.
If I can do that, I can then use it in the places that I want to print the random ads out.

Thanks
Bob


[This message has been edited by lanerj (edited April 20, 2000).]
Quote Reply
Re: calling random mod from within a sub routine In reply to
You can do it one of two ways.

You can put the code into a subroutine like I showed you before -- sub get_random_from_other_db

And, where you want x number of ads to appear, use

Code:
srand( time() ^ ($$ + ($$ << 15)) );
for ($i=1; $i<=x; $i++) {
@hits = &get_random_from_other_db;
print qq| $hits[1] |;
}

Or you can add the code within the "for" loop:

Code:
srand( time() ^ ($$ + ($$ << 15)) );
for ($i=1; $i<=x; $i++) {
open (DB, "<$db_file_name4") or &cgierr("error in get_random.
unable to open db file: $db_file_name.\nReason: $!");
if ($db_use_flock) { flock(DB, 1); }
@lines = <DB>;
close DB;
foreach $line (@lines) {
if ($line =~ /^$/) { next; }
if ($line =~ /^#/) { next; }
push (@rlines,$line);
}
$rvalue = scalar(@rlines);
$random_number = int(rand $rvalue);
@values = &split_decode($rlines[$random_number]);
push (@hits, @values);
print qq| $hits[1] |;
}

(The reason I moved the "srand" line is that it's best to just seed the random number once.)

Both sets of code I gave you will do the same thing, assuming you have added sub get_random_from_other_db. But you may want to keep it all together.

Be sure to change the x to the number of ads you want to display.

Be aware, though, that, unless you have a large number of ads, there is a possiblity that the same ad will appear twice. The larger the number of ads that you have, the less likely you are to have duplications.

Does this help? I feel like we've been going around in random circles. Smile


------------------
JPD






Quote Reply
Re: calling random mod from within a sub routine In reply to
PD,
Ihave tryed both versions of this, but for the life of me I can not get either verson to print out any more than 1 random record.
I set x to 3, but it still only prints out 1 random record.
You would think that because it is in a for loop that it should work.
I realy don,t know why it dosn't.

thanks
Bob
Quote Reply
Re: calling random mod from within a sub routine In reply to
Well, then, let's try it another way.

Instead of

Code:
for ($i=1; $i<=x; $i++) {
@hits = &get_random_from_other_db;
print qq| $hits[1] |;
}

try

Code:
@hits = &get_random_from_other_db;
print qq| $hits[1] <BR>|;
@hits = &get_random_from_other_db;
print qq| $hits[1] <BR>|;
@hits = &get_random_from_other_db;
print qq| $hits[1] <BR>|;

(I added line breaks in there so it wouldn't all be on one line.)


------------------
JPD






Quote Reply
Re: calling random mod from within a sub routine In reply to
JPD,
I,m sorry but that dosn't work either.
It is printing 3 records, but they are all the same.
Every time the page is loades It is a different set, so it is randomising, but only once.
I have an idea, very rare but it does happen.
Is the contents of a hash random. If so would it be possible to put the fields into a hash and print that. Would that work.

thanks
Bob



[This message has been edited by lanerj (edited April 23, 2000).]
Quote Reply
Re: calling random mod from within a sub routine In reply to
I'm not sure what you mean. I would need an example.

You could try adding the srand line before each of the "get_random" lines.



------------------
JPD






Quote Reply
Re: calling random mod from within a sub routine In reply to
JPD,
I tried the hash idea, It wouldn’t work either, it just printed out the db in sequence, so I got it to work using this.
Code:
srand( time() ^ ($$ + ($$ << 15)) );
open (DB, "<$db_file_name4") or &cgierr("unable to open $db_file_name4. Reason: $!");
if ($db_use_flock) { flock(DB, 1); }
LINE: while (<DB> ) {
next if /^#/;
next if /^\s*$/;
$line = $_;
chomp ($line);
@fields = &split_decode ($line);
if (!(grep $_ eq $fields[1], @selectfields)) {
push (@results, $fields[1]);
}
}
close DB;
for ($i=1; $i<=6; $i++) {
$number = int(rand(@results));
print qq| $results[$number]<br>|;
}
I need your help with the next bit because I don’t know how to write the code.
Because this db will only have about 30 records, I need a way to checking used $numbers, so there won’t be multiple records printed on the page.
The way I thought of doing this is:
push $number into an array, say @control.
check the existence of $number in @control, with gerp.
If exists, loop back and randomise again, until we find an $number which isn’t in control, and push that $number into @control, and use that $number to print.
I was thinking of doing the randomising within a while loop:
Code:
while (grep(------)) {
$number = int(rand(@results));
}
push (@control, $number);
but I can’t get the grep code right.
HELP!
Quote Reply
Re: calling random mod from within a sub routine In reply to
I'll get back to you on this. These things are the hardest for my brain to wrap itself around and I'm still a little groggy. I'll have something for you later today.


------------------
JPD






Quote Reply
Re: calling random mod from within a sub routine In reply to
I got another idea. Maybe this will work better. This is from my days years ago with BASIC when I was working on a card game. The routine shuffled cards and then dealt them out. I figured that you could just "shuffle" the records.

Code:
open (DB, "<$db_file_name4") or &cgierr("unable to open $db_file_name4. Reason: $!");
if ($db_use_flock) { flock(DB, 1); }
LINE: while (<DB> ) {
next if /^#/;
next if /^\s*$/;
$line = $_;
chomp ($line);
push(@sort,$line);
}
close DB;
srand( time() ^ ($$ + ($$ << 15)) );
$k = $#sort;
for ($j=0;$j<=$#sort;++$j) {
$l = int(rand($k));
$temp = $sort[$k];
$sort[$k] = $sort[$l];
$sort[$l] = $temp;
--$k;
}
for ($m=0;$m<=6 ;++$m) {
@fields=&split_decode(sort[$m]);
print qq|$fields[1]|;
}

I should have thought of this before.

------------------
JPD






Quote Reply
Re: calling random mod from within a sub routine In reply to
OK, I bow to the master, your the lady. I would have never thought of doing it that way.
With a few modifications, this is it.
Code:
$times = 6;
open (DB, "<$db_file_name4") or &cgierr("unable to open $db_file_name4. Reason: $!");
if ($db_use_flock) { flock(DB, 1); }
LINE: while (<DB> ) {
next if /^#/;
next if /^\s*$/;
$line = $_;
chomp ($line);
@fields = &split_decode ($line);
push (@sort, $fields[1]);
}
close DB;
srand( time() ^ ($$ + ($$ << 15)) );
$k = $#sort;
for ($j=0;$j<=$#sort;++$j) {
$l = int(rand($k));
$temp = $sort[$k];
$sort[$k] = $sort[$l];
$sort[$l] = $temp;
--$k;
}
for ($m=1;$m<=$times;++$m) {
print qq|$sort[$m]<br>|;
}
Thanks JPD for your help.
A question - What does the # do?

thanks
Bob

[This message has been edited by lanerj (edited April 26, 2000).]
Quote Reply
Re: calling random mod from within a sub routine In reply to
With your modification, you're splitting every record. With my code, you're only splitting the ones you need. But if you only have a small number of records, it won't make much difference.

The structure $#sort means "the highest number in the array called 'sort'." So if you have defined from $sort[0] through $sort[29], $#sort will be equal to 29. (Notice that, even if there is nothing in, say, $sort[15], $#sort will still be equal to 29.)

I just can't believe that I didn't think of this before. I need to remember to call on all those previous years of programming as I'm working here. Smile


------------------
JPD






Quote Reply
Re: calling random mod from within a sub routine In reply to
Thanks for the info, I'll use that in the future.
The way you had it with: print qq|$fields[1]|;, I wouldn't print.
Using print qq|$sort[1]|;, would print ARRAY(2c009xy), or somthing like that.
Using qq|$sort[$m]|;, and @fields=&split_decode(sort[$m]);, in the for loop, would print each line.
Anyway, with this I should be able to search by category as well, so this is an excellent random mod.
One more question, and I hope you don,t mind me asking you these.
In the documentation is says to avoid using grep(), and to use map() instead. What would be the reason for this.
I am using grep()in a number of mods, and it works fine. Would it be because it,s a DOS command, and therefore may not work on different operating systems.

thanks
Bob

Quote Reply
Re: calling random mod from within a sub routine In reply to
I have no idea why grep shouldn't be used.

I'm just glad we finally got this to work for you.

Smile


------------------
JPD