# ALIGN2HTML # Author: Jerome Ajot # # This software was developed at the National Institute of Standards and Technology by # employees of the Federal Government in the course of their official duties. Pursuant # to title 17 Section 105 of the United States Code this software is not subject to # copyright protection and is in the public domain. ALIGN2HTML is an experimental system. # NIST assumes no responsibility whatsoever for its use by other parties, and makes no # guarantees, expressed or implied, about its quality, reliability, or any other # characteristic. We would appreciate acknowledgement if the software is used. # # THIS SOFTWARE IS PROVIDED "AS IS." With regard to this software, NIST MAKES NO EXPRESS # OR IMPLIED WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING MERCHANTABILITY, # OR FITNESS FOR A PARTICULAR PURPOSE. package Segment; use strict; use Data::Dumper; use Token; sub new { my $class = shift; my $self = {}; $self->{ID} = shift; $self->{SPKRID} = shift; $self->{TOKENS} = {}; $self->{MINX} = 10000000; $self->{MAXX} = 0; $self->{HEIGHT} = 0; $self->{HASFAKETIME} = 0; bless $self; return $self; } sub AddToken { my ($self, $tkn) = @_; $self->{TOKENS}{$tkn->{ID}} = $tkn; } sub SetY { my ($self, $ypos) = @_; foreach my $tknid(sort keys %{ $self->{TOKENS} }) { $self->{TOKENS}{$tknid}->SetYPos($ypos); } } sub isTokenInSegment { my ($self, $tokenid) = @_; foreach my $tknid(sort keys %{ $self->{TOKENS} }) { return 1 if($tknid == $tokenid); } return 0; } sub CalculateMinMaxX { my ($self) = @_; foreach my $tknid(sort keys %{ $self->{TOKENS} }) { next if( ($self->{TOKENS}{$tknid}->{XSTARTPOS} == 0) && ($self->{TOKENS}{$tknid}->{XENDPOS} == 0) && ($self->{TOKENS}{$tknid}->{TEXT} eq "") ); $self->{MINX} = $self->{TOKENS}{$tknid}->{XSTARTPOS} if($self->{MINX} > $self->{TOKENS}{$tknid}->{XSTARTPOS}); $self->{MAXX} = $self->{TOKENS}{$tknid}->{XENDPOS} if($self->{MAXX} < $self->{TOKENS}{$tknid}->{XENDPOS}); } } sub HasOnlyOneFakeToken { my ($self) = @_; foreach my $tknid(sort keys %{ $self->{TOKENS} }) { return 0 if( !( ($self->{TOKENS}{$tknid}->{XSTARTPOS} == 0) && ($self->{TOKENS}{$tknid}->{XENDPOS} == 0) && ($self->{TOKENS}{$tknid}->{TEXT} eq "") ) ); } return 1; } sub CleanSegmentPrevNext { my ($self) = @_; foreach my $tknid(sort keys %{ $self->{TOKENS} }) { my $myToken = $self->{TOKENS}{$tknid}; for(my $i=0; $i< @{ $myToken->{PREVTKNID} }; $i++) { delete $myToken->{PREVTKNID}[$i] if(!$self->isTokenInSegment($myToken->{PREVTKNID}[$i])); } for(my $i=0; $i< @{ $myToken->{NEXTTKNID} }; $i++) { delete $myToken->{NEXTTKNID}[$i] if(!$self->isTokenInSegment($myToken->{NEXTTKNID}[$i])); } $myToken->{NUMPREV} = scalar( @{ $myToken->{PREVTKNID} } ); $myToken->{NUMNEXT} = scalar( @{ $myToken->{NEXTTKNID} } ); } } sub MultiGraphXY { my ($self) = @_; my $maxheigh = 0; if(scalar(keys %{ $self->{TOKENS} }) != 0) { my %tokenPositions; my @listTokenID; my $currentlevel = 0; my $maxlengh = 0; foreach my $tknid(sort {$a <=> $b} keys %{ $self->{TOKENS} }) { $tokenPositions{$tknid}{XB} = 0; $tokenPositions{$tknid}{XE} = 1; $tokenPositions{$tknid}{Y} = 0; $tokenPositions{$tknid}{TEXT} = $self->{TOKENS}{$tknid}->{TEXT}; push(@listTokenID, $tknid); if( scalar(@{ $self->{TOKENS}{$tknid}->{PREVTKNID} }) == 0 ) { $tokenPositions{$tknid}{Y} = $currentlevel; $currentlevel++; } } for(my $i=0; $i<@listTokenID; $i++) { my $tokenid = $listTokenID[$i]; my $token = $self->{TOKENS}{$tokenid}; my @prevtkn = @{ $token->{PREVTKNID} }; my @nexttkn = @{ $token->{NEXTTKNID} }; my $tokenBegin = $tokenPositions{$tokenid}{XB}; my $tokenEnd = $tokenPositions{$tokenid}{XE}; my $tokenY = $tokenPositions{$tokenid}{Y}; for(my $j=0; $j<@nexttkn; $j++) { my $nexttokenid = $nexttkn[$j]; my $nexttokenBegin = $tokenPositions{$nexttokenid}{XB}; my $nexttokenEnd = $tokenPositions{$nexttokenid}{XE}; my $nextTokenY = $tokenPositions{$nexttokenid}{Y}; if( $nexttokenBegin < $tokenEnd) { $tokenPositions{$nexttokenid}{XB} = $tokenEnd; $tokenPositions{$nexttokenid}{XE} = $tokenPositions{$nexttokenid}{XB} + 1; $i = -1; } my $nbrprev = scalar( @{ $self->{TOKENS}{$nexttokenid}->{PREVTKNID} } ) - 1; if($nextTokenY < ($tokenY + $j - $nbrprev)) { $tokenPositions{$nexttokenid}{Y} = $tokenY + $j - $nbrprev; $i = -1; } } for(my $j=0; $j<@prevtkn; $j++) { my $prevtokenid = $prevtkn[$j]; my $prevtokenBegin = $tokenPositions{$prevtokenid}{XB}; my $prevtokenEnd = $tokenPositions{$prevtokenid}{XE}; if( $prevtokenEnd != $tokenBegin) { $tokenPositions{$prevtokenid}{XE} = $tokenBegin; $i = -1; } } } foreach my $tken (sort {$a <=> $b} keys %tokenPositions) { $maxheigh = $tokenPositions{$tken}{Y} if($tokenPositions{$tken}{Y} > $maxheigh); $maxlengh = $tokenPositions{$tken}{XE} if($tokenPositions{$tken}{XE} > $maxlengh); } foreach my $tknid(sort keys %{ $self->{TOKENS} }) { my $updown = 1; my $base = 0; if($self->{TOKENS}{$tknid}->{REFORSYS} eq "REF") { $updown = -1; $base = $maxheigh; } if($self->{TOKENS}{$tknid}->{REALTIME} == 0) { $self->{TOKENS}{$tknid}->MakeFakeTime($tokenPositions{$tknid}{XB}, $tokenPositions{$tknid}{XE}, $maxlengh); $self->{HASFAKETIME} = 1; } $self->{TOKENS}{$tknid}->{YPOS} += $base*30 + $updown*30*$tokenPositions{$tknid}{Y}; } } $self->{HEIGHT} = ($maxheigh+1)*30; } sub Compute { my ($self) = @_; # Calculate Min and Max X $self->CalculateMinMaxX(); # Clean up the previous and Next of Tokens $self->CleanSegmentPrevNext(); # Assign X and Y for graph $self->MultiGraphXY(); } sub GetDraw { my ($self, $minx) = @_; my $output2 = ""; my @listfirsts; my @listlasts; foreach my $tknid(sort keys %{ $self->{TOKENS} }) { my @prevtkn = @{ $self->{TOKENS}{$tknid}->{PREVTKNID} }; my @nexttkn = @{ $self->{TOKENS}{$tknid}->{NEXTTKNID} }; if(scalar(@prevtkn) > 1) { for(my $i=1; $i<@prevtkn; $i++) { my $end1x = $self->{TOKENS}{$prevtkn[$i-1]}->{XENDPOS} - $minx; my $end1y = $self->{TOKENS}{$prevtkn[$i-1]}->{YPOS}; my $end2x = $self->{TOKENS}{$prevtkn[$i]}->{XENDPOS} - $minx; my $end2y = $self->{TOKENS}{$prevtkn[$i]}->{YPOS}; $output2 .= sprintf("jg.drawLine(scale*%.0f, %.0f, scale*%.0f, %.0f);\n", $end1x, $end1y, $end2x, $end2y); } } push(@listfirsts, $tknid) if(scalar(@prevtkn) == 0); if(scalar(@nexttkn) > 1) { for(my $i=1; $i<@nexttkn; $i++) { my $begin1x = $self->{TOKENS}{$nexttkn[$i-1]}->{XSTARTPOS} - $minx; my $begin1y = $self->{TOKENS}{$nexttkn[$i-1]}->{YPOS}; my $begin2x = $self->{TOKENS}{$nexttkn[$i]}->{XSTARTPOS} - $minx; my $begin2y = $self->{TOKENS}{$nexttkn[$i]}->{YPOS}; $output2 .= sprintf("jg.drawLine(scale*%.0f, %.0f, scale*%.0f, %.0f);\n", $begin1x, $begin1y, $begin2x, $begin2y); } } push(@listlasts, $tknid) if(scalar(@nexttkn) == 0); } if(scalar(@listfirsts) > 1) { for(my $i=1; $i<@listfirsts; $i++) { my $begin1x = $self->{TOKENS}{$listfirsts[$i-1]}->{XSTARTPOS} - $minx; my $begin1y = $self->{TOKENS}{$listfirsts[$i-1]}->{YPOS}; my $begin2x = $self->{TOKENS}{$listfirsts[$i]}->{XSTARTPOS} - $minx; my $begin2y = $self->{TOKENS}{$listfirsts[$i]}->{YPOS}; $output2 .= sprintf("jg.drawLine(scale*%.0f, %.0f, scale*%.0f, %.0f);\n", $begin1x, $begin1y, $begin2x, $begin2y); } } if(scalar(@listlasts) > 1) { for(my $i=1; $i<@listlasts; $i++) { my $end1x = $self->{TOKENS}{$listlasts[$i-1]}->{XENDPOS} - $minx; my $end1y = $self->{TOKENS}{$listlasts[$i-1]}->{YPOS}; my $end2x = $self->{TOKENS}{$listlasts[$i]}->{XENDPOS} - $minx; my $end2y = $self->{TOKENS}{$listlasts[$i]}->{YPOS}; $output2 .= sprintf("jg.drawLine(scale*%.0f, %.0f, scale*%.0f, %.0f);\n", $end1x, $end1y, $end2x, $end2y); } } my $output = ""; if($output2 ne "") { $output .= sprintf("jg.setColor(\"grey\");\n"); $output .= sprintf("jg.setStroke(Stroke.DOTTED);\n"); $output .= $output2; } foreach my $tknid(sort keys %{ $self->{TOKENS} }) { $output .= $self->{TOKENS}{$tknid}->GetDraw($minx); } return $output; } 1;