Search code examples
htmlperlcgissi

How to display random data from text file when reload page in perl?


I have a text data file called "poduct_data.txt"

id  |  name  | top
------------------
id01--  name01--    top

id02--  name02--    
id03--  name03--    
id04--  name04--    top

id05--  name05--    top

id06--  name06--    
id07--  name07--    top

id08--  name08--    
id09--  name09--    
id10--  name10--    top

Here is 3 columns called id,name&top. "my task is :

  1. to find top column data from this text file and
  2. display them randomly by three top data when reload page." like: name01 name04 name 05

if reload page then show randomly another 3 data may be : name07 name05 name10

Every time reload page show different 3 data from top data

1 is done and displaying like: name01 name10 name04 name07 name 05

but having problem in 2.

My work files are in below:

library file : ProductLib.pm

    package ProductLib;
    use strict;
    use File::Basename;
    use FileHandle;
    use Encode;
    use CGI;
    use POSIX;
    use Date::Parse;
    
    sub new {
        my $class   = shift;
        my ($ProgramName, $ProgramPath, undef)  = fileparse($0);
        my $self    = {
                    'program_name'      => $ProgramName,        
                    'program_path'      => $ProgramPath,        
                    'data_dir'          => 'data',
                    'product_data_file' => 'product_data.txt',
                    'template_dir'      => 'templates',
                    'template'          => {},
                    'cgi'               => new CGI(),
                    @_,
                };
    
        $Data::Dumper::Sortkeys = 1;
        $Data::Dumper::Indent = 1;
        $Data::Dumper::Terse = 1;
    
        return bless $self, $class;
    }
    sub SearchRandomProduct{
        my $self        = shift;
        my $TargetTop       = shift;
        my $ProductHash = $self->GetProductData();
    
        my $TargetProduct   = {};
        foreach my $ProductId (sort {$a cmp $b} (keys %{$ProductHash})){
    
            my $ProductData     = $ProductHash->{$ProductId};
            my $ProductTop      = $ProductData->{'top'};
    
            next if(defined $TargetTop && $ProductTop ne $TargetTop);
    
            $TargetProduct->{$ProductId}    = $ProductData;
        }
        return $TargetProduct;
    }
    sub GetProductData{
        my $self        = shift;
        my $FilePath    = sprintf('%s/%s',
                                $self->{'data_dir'},
                                $self->{'product_data_file'}
                            );
        my $FileData    = ${$self->GetFileData($FilePath)};
    
        my $ProductHash = {};
        my @LineData    = split("\n", $FileData);
    
        foreach my $LineData (@LineData){
            next if($LineData eq '' || $LineData =~ /^#/);
    
            my @DataArray       = split("\t", $LineData, 3);
            my $ProductId       = $DataArray[0];
            my $ProductName     = $DataArray[1];
            my $ProductTop      = $DataArray[2];
    
            $ProductHash->{$ProductId}  = {
                    'id'        => $ProductId,
                    'name'      => $ProductName,
                    'top'       => $ProductTop,
                };
        }
        return $ProductHash;
    }
    sub SetTemplateParameter{
        my $self    = shift;
        my $TemplateData    = shift; 
        my $ProductData     = shift;
        $TemplateData   = ${$TemplateData} if(ref($TemplateData) eq 'SCALAR');
        $TemplateData =~ s/\$\{(.*?)\}/$ProductData->{$1}/ges;
        return \$TemplateData;
    }
sub GetFileData{

    my $self        = shift;

    my $FilePath    = shift;

    my $FileData    = '';
    if(-e "${FilePath}"){

        my $FileHandle  = new FileHandle;
        sysopen($FileHandle, "${FilePath}", O_RDONLY);
            $FileData = join'',<$FileHandle>;
        close($FileHandle);
    }
    return \$FileData;
}
    1;

cgi file: product_random_list.cgi

#!/usr/bin/perl

use FindBin;
use lib "$FindBin::Bin/lib";
use strict;
use CGI;
use ProductLib;
use Data::Dumper;

 my $ProductFormat  = ' <a class="card">
                            <div class="card-body">
                                    <strong>${name}</strong>
                            </div>
                        </a>';
my $q           = new CGI;
my $ProductLib  = new ProductLib();

my $TargetMode      = $q->param('mode') || 'init';
my $TargetTop       = $q->param('top');

my $ProductList = {};

if($TargetMode eq 'init'){
    $ProductList    = $ProductLib->SearchRandomProduct($TargetTop);
}

my $ProductHtml = '';
foreach my $ProductId ( 
    sort {
        $ProductList->{$a}->{'id'} cmp $ProductList->{$b}->{'id'}
    }
(keys %{$ProductList})){
    my $ProductData = $ProductList->{$ProductId};
    $ProductHtml    .= ${$ProductLib->SetTemplateParameter(\$ProductFormat, $ProductData)};
}

print "Content-Type: text/plain; charset=utf8\n\n";
print $ProductHtml;
exit;

index file : index.html

<!DOCTYPE html>
<html>
<body>

<section>
    <div class="container-fluid">
        <div class="card-deck sMb">
                <!--#include virtual="/ssi/product_random_list.cgi?top=top" -->
        </div>
    </div>
</section>

</body>
</html>

please help me to display them randomly by three top data when reload page in above index page...


Solution

  • display them randomly by three top data when reload page.

    You can select three random items from the product list by using for example List::Util::shuffle(). Example:

    use strict;
    use warnings;
    use List::Util qw(shuffle);
    my $ProductList = {
        id01 => {id => 'id01', name => 'name01', top => 'top'},
        id10 => {id => 'id10', name => 'name10', top => 'top'},
        id04 => {id => 'id04', name => 'name04', top => 'top'},
        id07 => {id => 'id07', name => 'name07', top => 'top'},
        id05 => {id => 'id05', name => 'name05', top => 'top'},
    };
    my @ids = keys %$ProductList;
    my @idx = shuffle 0..$#ids;
    my @randidx = @ids[@idx[0..2]];
    

    Every time reload page show different 3 data from top data

    In order to recognize if the page is reloaded or not, you could use a session variable. See CGI::Session for more information.