|
#!/usr/bin/perl -w # # tcams --crb3 16Feb07/19feb07 # # collect and graph camera-time values for the chapters of a # multichapter fic assembled using tpp. 'cameras' are # designators for character appearance and viewpoint (assigned # cameras); the idea is to graph character appearances in such a # way as to help the writer manage them for dramatic flow. # numbers are first generated in bytecounts, then converted to # percentage of chapter, and graphed that way in LinePoint # format. # # for starts, tuned to the specific tpp decorations I use. then # to be generalized, maybe, but count on using tpp's tagged output # (-t -u). # # multicamera options allowed (#cam=hp,nt). # # works with Chart-0.99, which uses older GD producing GIFs. There are # hints throughout as to how to adapt to newer versions which produce # PNGs. # # the -g option causes the script to print image sizes to stdout # in a raw format suitable for insertion into an <IMG> tag, in, # say, a tindexer-generated index. # use Data::Dumper; use Chart::LinesPoints; $cwd=`pwd`; chomp $cwd; our($val,$yval,$arb4cam,$xmin,$ymin,$xfudge,$yfudge); $xval=400; $yval=180; $arb4cam=17; $xmin=400; $ymin=225; $xfudge=0; $yfudge=225; $do_absolutes=0; $select='*'; # string of CSV cameras to display, unless '*' $subtitle=""; $title="Cameras"; $ftyp='*'; $issub=$istit=$isx=$isy=$chatty=$showit=$debug=0; while(defined($ARGV[0]) and index($ARGV[0],'-')==0){ $arg=shift(@ARGV); # get any the switches $key=substr($arg,1,1); # get no-arg switches first substr($arg,0,2)=""; if($key eq 'v'){ # verbose? $chatty ^= 1; next; }elsif($key eq 'S'){ # show gif once made? $showit^=1; next; }elsif($key eq 'D'){ # debug $debug^=1; next; }elsif($key eq 'a'){ # emit byct as well as % graphs? $do_absolutes^=1; next; }elsif($key eq 'g'){ # print gif sizes to stdout $xandy^=1; next; }elsif($key eq 'h' or $key eq '?'){ # show helps and leave. print <<EOT; tcams GIF-graphs char vp as % of chapter size --crb3 16Feb07/19feb07 tcams [options] tpp-tagged-text-infile Options: -a toggle: emit absolute-byct graphs as well as % (default: off) -c <regex> filename filter for chapters (def: .*) -C aa,bb,cc,dd CSV, what cameras to show -d /subdir relative path to subdir where chapter txt files are -f txt filetype of chapter files (def: txt) -g toggle: emit gif sizes to stdout (off) -m <mountpoint> where chosen floppy mounts -o <outfname> output filename -s <subtitle> subtitle to put at top of graph (if not deprecated) -t <title> title to put at top of graph -x override graph width in pixels -y override graph height in pixels -v toggle: script gets chatty -D toggle: turn on ad-hoc debug tracers -h,-? show helps, then leave EOT exit(0); } $arg =~ s/^\=//; # handles switch=arg $arg=shift(@ARGV) if($arg eq "" and ($ARGV[0] !~ /^\-\w/) ); # # handles space-separated switch/arg if($key eq 'o'){ # output filename $ofile=$arg; }elsif($key eq 'f'){ # filetype $ftyp=$arg; # 'txt' }elsif($key eq 'x'){ # override x dimension $xval=$arg; $isx=1; }elsif($key eq 'y'){ # override y dimension $yval=$arg; $isy=1; }elsif($key eq 'd'){ # what subdir are text chapters in $chapdir=$arg; # 'ch' }elsif($key eq 't'){ # title to put at top of graph $title=$arg; # 'Name of Story' $istit=1; }elsif($key eq 's'){ # subtitle to put at top of graph $subtitle=$arg; # (might be deprecated out in your pkgs) $issub=1; }elsif($key eq 'c'){ $chapfiles=$arg; # 'sottc\.\d{6}\.txt' --regex }elsif($key eq 'C'){ $select=$arg; # CSV, what cameras to show }else{ warn "$0: unrecognized option -$key $arg\n"; } } die "no tpp-tagged-format infile specified\n" unless defined $ARGV[0]; $inf=shift(@ARGV); unless($select eq '*'){ foreach $cm (split(',',$select)){ $camsels{$cm}=1; # build a quick-check hash } } $|=1 if $debug; $camera='none'; $chapnum='0'; $d={}; $firstchap=$chapcount=-1; open(T,"<$inf") or die "can't open infile $inf\n"; while(defined($ln=<T>)){ if(index($ln,'#cam=')==0){ chomp $ln; $camera=(split('=',$ln))[1]; $camera =~ s/\s+$//; push(@cfiles,$cfile); # for checking for dual-cam instances if($ftyp ne '*'){ next unless $cfile =~ /\.$ftyp$/; } if(index($camera,',')>-1){ foreach $cam (split(',',$camera)){ unless($select eq '*'){ next unless exists $camsels{$cam}; } $cams{$cam}=1; $d->{$chapnum}->{$cam}=0 unless exists $d->{$chapnum}->{$cam}; $d->{$chapnum}->{$cam} += (-s $cfile); } }else{ unless($select eq '*'){ next unless exists $camsels{$camera}; } $cams{$camera}=1; $d->{$chapnum}->{$camera}=0 unless exists $d->{$chapnum}->{$camera}; $d->{$chapnum}->{$camera} += (-s $cfile); } $firstchap=$chapnum if $firstchap==-1; $chapcount=0+$chapnum; # max }elsif(index($ln,'===[')==0){ # switch to new chunk filename chomp $ln; substr($ln,0,4)=""; # whack off ===[ ($cfile,$chapnum)=split(/\]\[/,$ln,2); $chapnum =~ s/\].*$//; } } close(T); for($cx=0;$cx<$#cfiles;$cx++){ if($cfiles[$cx] eq $cfiles[$cx+1]){ warn "midfile camera switch: $cfiles[$cx]\n"; } } if($debug){ $dumped=Dumper($d); if(defined($ofile)){ open(O,">$ofile.DUMP") or die "can't make output dumpfile.\n"; print O $dumped; close(O); }else{ print $dumped,"\n"; } } $e->{_chapters_}=$chapcount; $e->{_firstchapter_}=$firstchap; foreach $cam (keys %cams){ foreach $ch ($firstchap .. $chapcount){ push( @{$e->{$cam}}, ( exists($d->{$ch}->{$cam}) ? $d->{$ch}->{$cam} : 0 ) ); } } if($debug){ $dumped=Dumper($e); if(defined($ofile)){ open(O,">$ofile") or die "can't make output dumpfile.\n"; print O $dumped; close(O); }else{ print $dumped,"\n"; } } foreach $ch ($firstchap .. $chapcount){ push(@chlbls,sprintf("%2.02d",$ch)); } push(@gifdata,\@chlbls); foreach $cam (sort keys %cams){ my @dataset; next if index($cam,',')>-1; next if $cam eq 'none'; push(@labels,$cam); # for graphing foreach $ch ($firstchap .. $chapcount){ push( @dataset, $e->{$cam}->[$ch-1] ); } push(@gifdata,\@dataset); } # # graphing camera-time in kilobytes per chapter # isn't all that useful, but here's the code; # see for yourself. # if($do_absolutes){ %gv=( 'title' => 'Cameras by chapter bytecounts', 'grid_lines' => 'true', 'stagger_x_labels' => 'true', # 'skip_x_ticks' => 5, 'legend' => 'bottom', 'legend_labels' => \@labels, # 'max_val' => 110, # 'y_ticks' => 11, 'grey_background' => 'false', 'x_label' => "chapter", 'y_label' => "Kbytes", ); $gifname="$ofile.gif"; $gif = Chart::LinesPoints->new($xval,$yval); $gif->set( %gv ); $gif->gif($gifname,\@gifdata); undef $gif; undef %gv; system("gifview $gifname &") if $showit; } # # datasets are more useful as % of chapter than as bycts... # to derive that, we need chapter sizes. in a tpp build, the # text chapters are probably in a separate subdir, split out for # generating HTML chapters. # # if no regex given, assume all *.txt are involved # $chapfiles='.txt$' unless defined $chapfiles; $chapdir='.' unless defined $chapdir; opendir(DIR,$chapdir) or die "can't open chapters dir $chapdir\n"; (@files)=sort grep(/$chapfiles/,(readdir(DIR))); closedir(DIR); foreach $fl (@files){ $fl =~ /(\d+)/; # grab just contiguous numbers. chaps MUST be enumerated. $chnum = $&; $chsizes[$chnum-1]= -s "$chapdir/$fl"; } # # now we can convert all those previously-collected bytecounts to percentages. # (portion / whole) * 100 # $first=1; foreach $gd (@gifdata){ if($first){ $first=0; next; } for($cx=0;$cx<$chapcount;$cx++){ $gd->[$cx] = ( $gd->[$cx] / $chsizes[$cx] ) * 100; } } %gv=( 'title' => "$title by chapter %", 'grid_lines' => 'true', 'stagger_x_labels' => 'false', # 'skip_x_ticks' => 5, 'legend' => 'bottom', 'legend_labels' => \@labels, 'max_val' => 100, 'y_ticks' => 6, 'min_val' => 0, 'gif_border' => 5, # 'text_space' => 1, ...buggy, causes right-aligned titles 'dashed_lines' => undef, 'grey_background' => 'false', 'x_label' => "chapter", 'y_label' => "percent", ); $gv{'sub_title'} = $subtitle if length($subtitle); $gifname="$ofile.percent.gif"; # newer: png, not gif $gif = Chart::LinesPoints->new($xval,$yval); $gif->set( %gv ); $gif->gif($gifname,\@gifdata); # newer: ->png undef $gif; system("gifview $gifname &") if $showit; # use ImageMagick's 'display" for png? if($xandy){ print "width=\"$xval\" height=\"$yval\"\n"; } |
Grab a gzipped copy here |
| Syntax highlighting using Syntax::Highlight::Engine::Kate |