User:Dschwen/Works in progress/Timelineoptimizer
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++; }