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

hi guys, i'm a newbie in PERL and trying to figure out how to rotate images in HTML. the code below is supposed to rotate the images read from a flat database file. the flat db format is:
1|/pics/boy.gif|http://www.b.com|internal 2|/pics/gal.gif|http://www.g.com|partner 3|/pics/gol.gif|http://www.f.com|payed
the code will open the flat db file and prints the image depending on the type of the image (internal,partner,or payed). the problem is the code does not rotate the images it only prints out the last image found. here's the piece of my code and see if you can fix it.... i know this is a very lame code so no flames pls.
if(!open DAT, "ads.dat") { print "Error: cannot open data file!\n"; exit 1; } else { @imgdata=<DAT>; foreach $c (@imgdata) { ($id,$image,$url,$type)=split(/\|/,$c); if ($type=~/^internal|partner$/) { srand(time() ^ ($$ + ($$ << 15)) ); @imgs = ($image); $img = $imgs[int(rand($#imgs+1))]; print "Location: $img\n\n"; } } } }
thanks in advance.

Replies are listed 'Best First'.
Re: Printing Random Image in HTML
by merlyn (Sage) on Sep 13, 2000 at 13:14 UTC
Re: Printing Random Image in HTML
by kilinrax (Deacon) on Sep 13, 2000 at 14:49 UTC
    Basically, the problem is simply that your random image selection and 'Location: ...' printing statements are inside the foreach loop.
    Also, you want to push $image to @imgs, not assign it.
    if(!open DAT, "ads.dat") { print "Error: cannot open data file!\n"; exit 1; } else { @imgdata=<DAT>; foreach $c (@imgdata) { ($id,$image,$url,$type)=split(/\|/,$c); if ($type=~/^(internal|partner)$/) { push (@imgs, $image); } } $img = $imgs[int(rand($#imgs+1))]; print "Location: $img\n\n"; }
      kilinrax: nice code, but we can get rid of your foreach loop:
      open DAT, "ads.dat" or die "Error: cannot open data file: $!\n"; @imgdata=<DAT>; @imgs = grep { s/^[^|]+\|([^|]+)\|[^|]+\|(?:internal|partner)$/$1/ } @ +imgdata; $img = $imgs[int(rand($#imgs+1))]; print "Location: $img\n\n";

      Cheers,
      Ovid

      I noticed everyone else had better, shorter answers than mine, sniff, sniff, so I just HAD to do something. Here's the regex broken out, for those who have asked for it:

      s/^ # Beginning of string [^|]+ # Everything up to the next bar \| # The bar ( # Capture to $1 [^|]+ # Everything up to the next bar ) # End capture \| # The bar [^|]+ # Everything up to the next bar \| # The bar (?: # Non-capturing parens internal # the string "internal" | # or partner # the string "partner" )$ # End of string /$1/x # Substitute $1 for string
      Join the Perlmonks Setiathome Group or just go the the link and check out our stats.
      hi kilinrax, u'r suggestion is the most effective, thanks allot.... oh btw. the image does rotates fine, but how will i be able to save the correct URL ($url) for the correct image? i will be saving the correct url to the cookie. the script should be able to rotate the image with corresponding url. thanks again.
Re: Printing Random Image in HTML
by btrott (Parson) on Sep 13, 2000 at 11:00 UTC
    Your code will print out multiple Location headers, because you don't stop after printing the first one. Also, you don't need to call srand.

    Here's some code that will do the same job (hopefully):

    open DAT, "ads.dat" or die "Can't open data file: $!"; my @valid = grep $_->[3] =~ /^internal|partner$/, map [ split /\|/ ], <DAT>; close DAT or die "Can't close data file: $!"; my $which = $valid[ rand @valid ]; print "Location: ", $which->[2], "\n\n";
      hi btrott, i think the code u've just suggested does not prints any images. thanks again.
Re: Printing Random Image in HTML
by little (Curate) on Sep 13, 2000 at 12:33 UTC
    #!usr/local/bin/perl use strict; $|++; my ($c, $id, $image, $url, $type, @imgs, $img); open DAT, "ads.dat" or die "Error: cannot open data file!\n"; my @imgdata=<DAT>; close DAT; $id = int(rand(scalar @imgdata)); $c = @imgdata[$id]; { chop $c; ($id,$image,$url,$type)=split(/\|/,$c); } print "Location: $type\n\n";
    if u use flat files always remove the newline at the end of each row of your dataset when reading those :-), but make sure that the last row has a newline too so far this works :-) regards
(Ovid) RE: Printing Random Image in HTML
by Ovid (Cardinal) on Sep 13, 2000 at 20:11 UTC
    One thing that I noticed is that you are printing out a Location: header. I haven't tried this as a method of providing an image in an HTML document, so I can't say for sure that it will work. However, take the following code and customize it and it should work fine.
    #!/usr/bin/perl -w use strict; use LWP::Simple; use vars qw($in_file @imgdata @imgs $num $id $image $url $type $format $out_file); $in_file = 'ads.dat'; @imgdata = <DATA>; @imgs = grep {/\|(?:internal|partner)$/} @imgdata; $num = int(rand($#imgs) +1); ($id, $image, $url, $type) = split /\|/, $imgs[$num]; $url = $url . $image; $format = $1 if $image =~ /\.(\w+)$/; $format = 'jpeg' if $format =~ /^jpe?g$/; $out_file = get($url); print "Content-type: image/$format\n\n"; print $out_file; __DATA__ 1|/images/dibona_sm.gif|http://perlmonks.org|internal 2|/images/usermonkpics/ovidmonk.gif|http://perlmonks.org|partner 3|/pics/gol.gif|http://www.f.com|payed
    The way to call it from an HTML document would be something like the following:
    <img src="http://www.somedomain.com/cgi-bin/myscriptname.cgi" alt="Ran +dom image">
    The only problem that I see with it is that you can't specify the height and width tags, but being able to embed it in HTML instead of just serving an image by itself should give you greater flexibility. (This code can probably be simplified further. I just threw it together).

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just go the the link and check out our stats.

      Thanks for this example, ovid.

      I had a little better luck with a version of this script I reworked the parens in the random image chooser like this:

      my $num = int(rand($#imgs +1));

      I had a list of just two images, and I kept getting the same image routine. I didn't think too hard about why my change worked any better, though. :)

      -mark