App-Basis-ConvertText2

 view release on metacpan or  search on metacpan

lib/App/Basis/ConvertText2/Plugin/Venn.pm  view on Meta::CPAN


=head1 NAME

App::Basis::ConvertText2::Plugin::Venn

=head1 SYNOPSIS

    my $content = "abel edward momo albert jack julien chris
    edward isabel antonio delta albert kevin jake
    gerald jake kevin lucia john edward" ;
    my $params = { 
        title   => "sample venn diagram",
        legends => "team1 team2 team3",
        scheme  => "rgb", 
        explain => '1'
    } ;
    my $obj = App::Basis::ConvertText2::Plugin::Venn->new() ;
    my $out = $obj->process( 'venn', $content, $params) ;

=head1 DESCRIPTION

Convert a text string of comma separated numbers into a Venn diagran image PNG

=cut

# ----------------------------------------------------------------------------

package App::Basis::ConvertText2::Plugin::Venn;
$App::Basis::ConvertText2::Plugin::Venn::VERSION = '0.4';
use 5.10.0;
use strict;
use warnings;
use GD;

# we need to do this to ensure that venn::chart uses the right level of color
GD::Image->trueColor(0);
use Venn::Chart;
use Path::Tiny;
use Moo;
use App::Basis;
use App::Basis::ConvertText2::Support;
use namespace::autoclean;

has handles => (
    is       => 'ro',
    init_arg => undef,
    default  => sub {[qw{venn}]}
);

# -----------------------------------------------------------------------------

my %_colour_schemes = (
    default => [ [ 189,  66, 238, 0 ],   [ 255,  133,  0,    0 ],   [ 0,   107,  44,  0 ] ],
    rgb     => [ [ 0x99, 00, 00,  40 ],  [ 0x33, 0x99, 0xcc, 40 ],  [ 0,   0x66, 0,   40 ] ],
    rgb1    => [ [ 0x99, 00, 00,  240 ], [ 0x33, 0x99, 0xcc, 240 ], [ 0,   0x66, 0,   240 ] ],
    rgb2    => [ [ 0x99, 00, 00,  0 ],   [ 0x33, 0x99, 0xcc, 0 ],   [ 0,   0x66, 0,   0 ] ],
    blue    => [ [ 98,   66, 238, 0 ],   [ 98,   211,  124,  0 ],   [ 110, 205,  225, 0 ] ],
);

# -----------------------------------------------------------------------------

=item venn

create a simple venn diagram image, with some nice defaults, returns some 
markdown explaining the diagram, undex/empty if errors

 parameters
    text   - 2 or 3 space separated lines of items for the venn
    filename - filename to save the created image as 

    hashref params of
        title   - title for the image
        legends - legends to match the lines
        size    - size of image, default 400x400, widthxheight - optional
        scheme - color scheme

=cut

sub process {
    my $self = shift;
    my ( $tag, $content, $params, $cachedir ) = @_;
    $params->{size}    ||= "";
    $params->{title}   ||= "";
    $params->{legends} ||= "";
    $params->{size}    ||= "400x400";
    $params->{scheme}  ||= 'default';
    $params->{scheme} = lc( $params->{scheme} );
    my ( $w, $h ) = ( $params->{size} =~ /^\s*(\d+)\s*x\s*(\d+)\s*$/ );

    if ( !$h ) {
        $w = 400;
        $h = 400;
    }
    return "" if ( !$content );

    # we can use the cache or process everything ourselves
    my $sig = create_sig( $content, $params );
    my $filename = cachefile( $cachedir, "$sig.png" );

    # we will not check for the cachefile as we need to create the venn object
    # each time to get the explaination text, besides not many people will
    # use this plugin, so lets not go to the extra effort
    my $venn_chart = Venn::Chart->new( $w, $h ) or die("error : $!");

    # lose any leading spaces
    $content =~ s/^\s+//s;

    # Set a title, colors and a legend for our chart
    my $colors = $_colour_schemes{ $params->{scheme} } ? $_colour_schemes{ $params->{scheme} } : $_colour_schemes{default};

    $venn_chart->set_options( -title => $params->{title}, -colors => $colors );

    my @legends;

    # decide how to split the legends
    if ( $params->{legends} =~ /,/ ) {
        @legends = map { my $n = $_; $n =~ s/^\s+//; $n } split( /,/, $params->{legends} );
    }
    else {
        @legends = split( /\s/, $params->{legends} );
    }

    # get the venn data, max 3 lines of it
    my $lines = 0;
    my @data;
    my @newlegends;
    foreach my $line ( split( /\n/, $content ) ) {
        $line =~ s/^s+//;    # remove leading spaces
        next if ( !$line );

        # update legends with members
        my $l = $legends[$lines];
        if ( !$l ) {
            $l = 'missing';
            push @legends, $l;
        }
        push @newlegends, "$l : $line";
        last if ( ++$lines > 3 );
        my @a = split( /[,\s+]/, $line );
        push @data, \@a;
    }
    $venn_chart->set_legends(@newlegends);

    # Create a diagram with gd object
    my $gd_venn = $venn_chart->plot(@data);

    # Create a Venn diagram image in png format
    path($filename)->spew_raw( $gd_venn->png() );

    my $out;
    if ( -f $filename ) {

        # now explain what is in each region
        my @ref_lists = $venn_chart->get_list_regions();

        # create something suitable for the HTML
        $out = create_img_src( $filename, $params->{title} );
        $out .= "\n\n" . "* only in $legends[0] : " . join( ' ', @{ $ref_lists[0] } ) . "  
    * only in $legends[1] : " . join( ' ', @{ $ref_lists[1] } ) . "
    * $legends[0] and $legends[1] share : " . join( ' ', @{ $ref_lists[2] } ) . "\n";

        if ( scalar(@newlegends) > 2 ) {
            $out .= "* only in $legends[2] : " . join( ' ', @{ $ref_lists[3] } ) . "
    * $legends[0] and $legends[2] share : " . join( ' ', @{ $ref_lists[4] } ) . "
    * $legends[1] and $legends[2] share : " . join( ' ', @{ $ref_lists[5] } ) . "
    * $legends[0], $legends[1] and $legends[2] share : " . join( ' ', @{ $ref_lists[6] } ) . "\n";
        }
        $out .= "\n";
    }
    return $out;

}

# ----------------------------------------------------------------------------

1;

__END__



( run in 1.027 second using v1.01-cache-2.11-cpan-39bf76dae61 )