User:Dschwen/Works in progress/Timelineoptimizer

From Wikipedia, the free encyclopedia

A perl script to optimize bar positions in a Wikipedia timeline. The Script

  • reads all lines containing from,till pairs
  • estimates their text length and bar length
  • shifts text which passes the right margin back into the picture
  • shifts bar text for bars at the left edge of the picture as much left as possible, to make room on the right
  • recurses to find the combination of bars per line that uses the space best
  • is horrible perl :-)
#!/usr/bin/perl

$n=0;

$start=1900;
$end=2005;
$width=800;
$spacing=10;
$margin_right=50;

sub recurse_list
{
        my $i = shift ;
        my $m_end = shift ;
        my $len = shift ;
        my $growlist = shift ;

        my $added=0;
        my $min_len=$width;

        while($i<$n)
        {
                if( (($x1[$sorted[$i]]-$m_end) > $spacing) && ($status[$i]==0) && (($x1[$sorted[$i]]-$m_end)<$min_len) )
                {
                        $min_len=$x1[$sorted[$i]]-$m_end;
                        recurse_list($i,$x2[$sorted[$i]],$len+($x1[$sorted[$i]]-$m_end),$growlist.",$i");
                        $added++;
                }
                $i++;
        }

        if($added==0)
        {
                if($len<$min_len) { $min_len=$len; }
                push(@liste,$growlist);
                push(@laengen,$len);
        }
}

while(<STDIN>)
{
        if(/^\s\s(from|at):/)
        {
                s/\n//g;
                $line[$n]=$_;

                if(/^  from:([0-9start]+)\s+till:([0-9end]+)\s+text:\"([^\"]+)\"/)
                {
                        $text_raw=$3;
                        $from=$1; if($from eq "start") { $from=$start; }
                        $till=$2; if($till eq "end")   { $till=$end; }
                }
                elsif(/^  at:([0-9startend]+)\s+text:\"([^\"]+)\"/)
                {
                        $text_raw=$2;
                        $from=$1; if($from eq "start") { $from=$start; }
                        $till=$1; if($till eq "end")   { $till=$end; }
                }

                $text_raw =~ s/\[\[([^\|]+)\|([^\]]+)\]\]/$2/g;
                $text_raw =~ s/\[\[//g;
                $text_raw =~ s/\]\]//g;

                $text="";
                foreach(split(/~/,$text_raw))
                {
                        s/~//;
                        if(length($_)>length($text)) { $text=$_; }
                }

                $len_text=length($text)*7;
                $len_box=(($till-$from)*$width)/($end-$start);
                if($len_box>$len_text) { $len=$len_box;  $textover[$n]=0; }
                else { $len=$len_text; $textover[$n]=($len_text-$len_box); }

                $x1[$n]=(($from-$start)*$width)/($end-$start);
                $x2[$n]=$x1[$n]+$len;

                #randcheck
                $over=$x2[$n]-($width+$margin_right);
                if($over>0)
                {
                        $x1[$n]-=$over;
                        $x2[$n]-=$over;
                        $shifted[$n]=(5-$over);
                }

                $unsorted[$n]=$n;

                $n++;
        }
}

@sorted = sort {$x1[$a] <=> $x1[$b]} (@unsorted);

$i=0;
while($i<$n)
{
        undef @liste;
        undef @laengen;

        # Element noch nicht verarbeitet
        if($status[$i]==0)
        {
                if($shifted[$sorted[$i]]==0)
                {
                        if($textover[$sorted[$i]]>$x1[$sorted[$i]])
                        {
                                $x2[$sorted[$i]]-=$x1[$sorted[$i]];
                                $shifted[$sorted[$i]]=-$x1[$sorted[$i]];
                                $x1[$sorted[$i]]=0;
                        }
                        else
                        {
                                $x1[$sorted[$i]]-=$textover[$sorted[$i]];
                                $x2[$sorted[$i]]-=$textover[$sorted[$i]];
                                $shifted[$sorted[$i]]=-$textover[$sorted[$i]];
                        }
                }
                $min_len=$width;
                recurse_list($i,$x2[$sorted[$i]],0,"$i");

                # alle laengen durchsehen, kleinste nehmen und elemente aus liste  in status markieren
                $j=0;
                $minj=0;
                for( $j=1 ;$j<=$#laengen; $j++)
                {
                        if($laengen[$j]<$laengen[$minj]) { $minj=$j; }
                }

                print "\n  bar:wars$i\n\n";

                foreach(split(/,/,$liste[$minj]))
                {
                        $status[$_]=1;
                        print $line[$sorted[$_]];
                        if($shifted[$sorted[$_]]) { print " shift:(".int($shifted[$sorted[$_]]).",1)"; }
                        print "\n";
                }

        }

        $i++;
}