#!/usr/bin/perl -w
#
# this is pretty ugly code.  folks asked about it, so it's
# up, but it shouldn't be used as an example of good
# anything.  features don't work.

use strict;
use SWF::Shape;

my $m;
my $realmode = 1;
my $darkback = 1;
my $textcol = ($darkback) ? 0xff : 0;
my @textcol = ($textcol, $textcol, $textcol);
open(DUMP, ">text");

my $font = new SWF::Font("/usr/share/libming/fonts/Helmet.fdb"); # "serif.fdb");

SWF::setScale(1.0);
SWF::setVersion(5);


sub lbl {
  chr(65 + $_[0] / 10) . chr(65 + $_[0] % 10);
}

my $button;
sub rebutton { 
  my ($slidenum) = @_;
  $button = new SWF::Button();
  $button->setHit(&rect(0,0,300,200, 20, 20, 20, 20));
  $button->addAction(new SWF::Action('play();'));
  $button->addAction(new SWF::Action('play();'), 
                     SWF::Constants::SWFBUTTON_KEYPRESS(' '));
  if($slidenum > 2) {
    $button->addAction(new SWF::Action("gotoAndPlay(" . &lbl($slidenum-1) . ");"), 
                       SWF::Constants::SWFBUTTON_KEYPRESS('p'));
  }
  $button->addAction(new SWF::Action("gotoAndPlay(" . &lbl($slidenum+1) . ");"), 
                     SWF::Constants::SWFBUTTON_KEYPRESS('n'));
  $m->add($button);
}

my $slidenum = 0;
sub pause {
  my($mov) = @_;
  if($realmode) {
    $mov->add(new SWF::Action('stop();'));
  }
  $slidenum ++;
  &rebutton($slidenum);
  $mov->labelFrame(&lbl($slidenum));
  $mov->nextFrame();
  
  #print "slide $slidenum\n";
}

sub text {
  my($str, $r, $g, $b, $a) = @_;
  my $t = new SWF::Text();
  $t->setFont($font);
  $t->setHeight(20);
  $t->setColor($r, $g, $b, $a);
  $t->addString($str);
  print DUMP $str . "\n";
  #print $str . "\n";
  $t;
}

sub title {
  my ($m, $text) = @_;
  print DUMP "--\n";
  my $ret = $m->add(&textsprite($text, 0));
  $ret->moveTo(20, 25);
  $ret;
}


my $ping =       &text("ping",       0, 0, 0, 0xff);
my $traceroute = &text("traceroute", 0, 0, 0, 0xff);
my $sprobe =     &text("sprobe",     0, 0, 0, 0xff);

sub crossfade {
  my($m, $frames, $old, $new) = @_;
  my $i;
  $new->addColor(0, 0, 0, 0);
  for(my $i=0; $i < $frames; $i++) {
    $old->addColor(0, 0, 0, 255/$frames * ($frames-$i) );
    $new->addColor(0, 0, 0, 255/$frames * $i );
    $m->nextFrame();
  }
  $new->addColor(0, 0, 0, 0xff );
  $m->remove($old);
}

my $lastmsg;
sub statusmsg {
  my ($m, $txt) = @_;

  # my $msg = $m->add(&text($txt, @textcol, 0));
  my $msg = $m->add(&textsprite($txt, 0));
  my @linesa = split("\n", $txt);
  my $lines = $#linesa;
  # print $lines . "\n";
  $msg->moveTo(20, 180 - ($lines * 20));
  if(defined($lastmsg)) {
    &crossfade ($m, 4,  $lastmsg, $msg );
  } else {
    $msg->addColor(0, 0, 0, 0xff);
  }
  
  $lastmsg = $msg;
  $msg;
}
sub fadein {
  my ($frames, @txts) = @_;
  my $int = 255 % $frames;
  my $slp = int(255 / $frames);
  for (my $i=1; $i <= $frames; $i++) {
    my $t;
    foreach $t ( @txts ) {
      $t->addColor(0,0,0,$i * $slp + $int);
    }
    $m->nextFrame();
  }
}
sub fadeout {
  my ($frames, @txts) = @_;
  my $int = 255 % $frames;
  my $slp = int(255 / $frames);
  for (my $i=$frames; $i >= 0; $i--) {
    my $t;
    foreach $t ( @txts ) {
      $t->addColor(0,0,0,$i * $slp + $int);
    }
    $m->nextFrame();
  }
  my $t;
  foreach $t ( @txts ) {
    $m->remove($t);
  }
}

# Create a Movie to hold the Shape

$m = new SWF::Movie();
$m->setDimension(300,200);
$m->setBackground(0,0, 30);
# $m->setRate(60);
&rebutton(0);

# title slide

my $t = $m->add(&textsprite("Scriptroute: A Public Internet\nMeasurement Facility\n\nNeil Spring, David Wetherall,\n and Tom Anderson\n\nUSITS 2003", 1));
$t->moveTo(150, 40);
my $i;
for ($i=0;$i <=5; $i ++) {
  $t->addColor(0,0,0,$i * 50 + 5);
}

&pause($m);
&fadeout(5, $t);

# slide 1
my $ttl = &title($m, "The Problem");
#my $bm = new SWF::Bitmap("gnome-application-pdf.dbl");
my $bm = new SWF::Bitmap("gas_can2.trans.dbl");
my $tbm = $m->add($bm);
$tbm->scaleTo(0.003, 0.003);
$tbm->moveTo(15, 40 );

my $txt = $m->add(&textsprite("1. Measurement tools are\n   hard to deploy", 0));
my $txt2 = $m->add(&textsprite("2. Must be a sysadmin\n   to develop them", 0));
my $txt3 = $m->add(&textsprite("Tool quality suffers!", 0));
$txt->moveTo(62, 60);
$txt2->moveTo(62, 110);
$txt3->moveTo(22, 160);
&fadein(5, $ttl, $txt, $txt2, $txt3);
&pause($m);

&fadeout(5, $ttl, $txt, $txt2, $txt3);
$m->remove($tbm);

## solution
$ttl = &title($m, "Scriptroute");
$txt = $m->add(&textsprite("Open system for flexible,\ndistributed measurement\nof network paths.", 0));
$txt->moveTo(20, 60);
&fadein(5, $ttl, $txt);
&pause($m);
&fadeout(5, $ttl, $txt);
## outline-ish slide

$ttl = &title($m, "Scriptroute Tour");
$txt = $m->add(&textsprite("1. System components\n2. Providing protection\n3. Applications", 0));
$txt->moveTo(20, 60);
&fadein(5, $ttl, $txt);
&pause($m);
&fadeout(5, $ttl, $txt);


### begin arch illustration
$ttl = &title($m, "Server Architecture");
&fadein(5, $ttl);

my $midpoint = 82;
my $pingy = $m->add($ping);
$pingy->moveTo(20,$midpoint - 35);
my $tracey = $m->add($traceroute);
$tracey->moveTo(20,$midpoint - 5);
my $sprobey = $m->add($sprobe);
$sprobey->moveTo(20,$midpoint + 25);

&statusmsg($m, "Tools use different protocols");
$m->nextFrame();


## colorize
my $pingred = 200;
my @pingred = ( $pingred + 50, 50, 50 );
my $tracegreen = 150;
my @tracegreen = ( 80, $tracegreen + 80, 80 );
my $sprobeblue = 175;
my @sprobeblue = ( 80, 80, $sprobeblue + 80);
for(my $i=0; $i <= 5; $i++) {
  $pingy->addColor( map { $_ * $i / 5 } @pingred);   
  $tracey->addColor( map { $_ * $i / 5 } @tracegreen);
  $sprobey->addColor( map { $_ * $i / 5 } @sprobeblue);

  $m->nextFrame();
}

#for(my $i=0; $i < 10; $i++) {
  #$morphy->setRatio($i/10);
  #$m->nextFrame();
#}

&pause($m);
&statusmsg($m, "Split into two layers");
## splay
#for(my $i=0; $i <= 10; $i++) {
#  $pingy->move(0,  0);
#  $tracey->move(2, 0);
#  $sprobey->move(4, 0);
#  $m->nextFrame();
#}


## rotate
#for(my $i=1; $i <= 15; $i++) {
  #$pingy->rotateTo(6 * $i);
  #$tracey->rotateTo(6 * $i);
  #$sprobey->rotateTo(6 * $i);
#
  #$m->nextFrame();
#}

  $pingy->move(0,  0);
  $tracey->move(2, 0);
  $sprobey->move(4, 0);

## drop
for(my $i=0; $i < 10; $i++) {
  $pingy->move(0,  0);
  $tracey->move(2, 0);
  $sprobey->move(4, 0);
  $pingy->rotateTo(9 * ($i+1));
  $tracey->rotateTo(9 * ($i+1));
  $sprobey->rotateTo(9 * ($i+1));
  $pingy->scale(0.99, 1);
  $tracey->scale(0.9, 1);
  $sprobey->scale(0.94, 1);
  $pingy->move(0, 5);
  $tracey->move(0, 2);
  $sprobey->move(0, -1);
  $m->nextFrame();
}

## squash to uniform
#for(my $i=0; $i < 10; $i++) {
  #$m->nextFrame();
#}


my $s;
my %rects;
$s = &square(5, $midpoint, @pingred, 0);
$rects{"ra"} = $m->add($s);
$s = &square(26, $midpoint, @tracegreen, 0);
$rects{"ga"} = $m->add($s);
$s = &square(47, $midpoint, @sprobeblue, 0);
$rects{"ba"} = $m->add($s);

$s = &square(5, $midpoint+20, @pingred, 0);
$rects{"rb"} = $m->add($s);
$s = &square(26, $midpoint+20, @tracegreen, 0);
$rects{"gb"} = $m->add($s);
$s = &square(47, $midpoint+20, @sprobeblue, 0);
$rects{"bb"} = $m->add($s);


my $chopline = new SWF::Morph();
$s = $chopline->getShape1();
# $s->setLeftFill(0xff, 0, 0);
$s->setLine(2, $textcol, $textcol, $textcol);
$s->drawLine(1,0);

$s = $chopline->getShape2();
$s->setLine(2, $textcol, $textcol, $textcol);
$s->drawLine(300,0);

my $chopliney = $m->add($chopline);
$chopliney->moveTo(0,$midpoint);

#### chop 
##my $choppa = new SWF::Shape();
### $s->setLeftFill(0xff, 0, 0);
##$choppa->movePenTo(0,50);
##$choppa->setLine(3, 0, 0, 0);
##$choppa->drawLine(10,0);
##
##my $choppy = $m->add($choppa);
#for(my $i=1; $i <= 20; $i++) {
##  $choppy->scale(1.1, 1);
#  $chopliney->setRatio($i/20);
#  $m->nextFrame();
#}

my $klvly = $m->add(&text("packet exchange", $textcol, $textcol, $textcol, 0));
$klvly->moveTo(80, $midpoint + 17);

my $ulvly = $m->add(&text("measurement logic", $textcol, $textcol, $textcol, 0));
$ulvly->moveTo(80,$midpoint - 5);

## fade in 
for(my $i=1; $i <= 10; $i++) {
  $ulvly->addColor(0, 0, 0, 25*$i +5 );
  $klvly->addColor(0, 0, 0, 25*$i +5 );
  $chopliney->setRatio(($i)/10);
  $m->nextFrame();
}

## &pause($m);
## &statusmsg($m, "Split");

## 
sub rect { 
  my ($x, $y, $x2, $y2, $r, $g, $b, $a) = @_;
  my $ret = new SWF::Shape();
  my $fill = $ret->addFill($r, $g, $b, $a);
  $ret->setLine(1, $r, $g, $b, $a);
  $ret->setLeftFill($fill);
  $ret->movePenTo($x,$y);
  $ret->drawLineTo($x2, $y);
  $ret->drawLineTo($x2, $y2);
  $ret->drawLineTo($x, $y2);
  $ret->drawLineTo($x, $y);
  $ret;
}

sub square { 
  my ($x, $y, $r, $g, $b, $a) = @_;
  &rect( $x, $y, $x+20, $y-20, $r, $g, $b, $a);
}

&pause($m);
&statusmsg($m, "One privileged component");

&fadein(10, values %rects);
$m->remove($pingy);
$m->remove($tracey);
$m->remove($sprobey);

# split off
for(my $off=10; $off > 0; $off--) {
  $rects{"rb"}->move(2.5*(10-$off), $off/2);
  $rects{"gb"}->move(2.5*(10-$off), $off/2);
  $rects{"bb"}->move(2.5*(10-$off), $off/2);
  $m->nextFrame();
}
#my $hcenter = 110; # 60, 200, 100, 120
my $hcenter = 150; # 60, 200, 100, 120
my $ng = $m->add(&text("Network Guardian", $textcol, $textcol, $textcol, 0));
$ng->moveTo($hcenter - $ping->getWidth("Network Guardian")/2,$midpoint +19);
&crossfade($m, 10, $klvly, $ng);
$m->nextFrame();
&pause($m);
&statusmsg($m, "Implement logic in user scripts");

for(my $off=10; $off > 0; $off--) {
  $rects{"ra"}->move(2.5*(10-$off), -$off/2);
  $rects{"ga"}->move(2.5*(10-$off), -$off/2);
  $rects{"ba"}->move(2.5*(10-$off), -$off/2);
  $m->nextFrame();
}

my $int = $m->add(&text("Interpreter", $textcol, $textcol, $textcol, 0));
$int->moveTo($hcenter - $ping->getWidth("Interpreter")/2,$midpoint - 7);
## cross fade  
&crossfade($m, 8, $ulvly, $int);

$m->nextFrame();

#for(my $off=4; $off > 0; $off--) {
  #$rects{"rb"}->scaleTo(($off)/5, 1);
  #$rects{"rb"}->move(1, 0);
  #$rects{"gb"}->scaleTo(($off)/5, 1);
  #$rects{"bb"}->scaleTo(($off)/5, 1);
  #$rects{"bb"}->move(-1, 0);
  #$m->nextFrame();
#}

&pause($m);
&statusmsg($m, "Generic mechanism");

for(my $off=21; $off > 0; $off--) {
  $rects{"rb"}->addColor(0, 0, 0, $off * 5 + 120);
  $rects{"rb"}->move(1, 0);
  $rects{"gb"}->addColor(0, 0, 0, $off * 6 + 80);
  $rects{"bb"}->addColor(0, 0, 0, $off * 6 + 70);
  $rects{"bb"}->move(-1, 0);
  $m->nextFrame();
}
$rects{"rb"}->moveTo(131, 25);
$rects{"gb"}->moveTo(110, 25);
$rects{"bb"}->moveTo(89, 25);
$m->nextFrame();

&pause($m);
&statusmsg($m, "Enable diverse measurements\nHappy students!");

for(my $off=20; $off >= 0; $off--) {
  $rects{"ra"}->move(-3, 0);
  $rects{"ba"}->move( 3, 0);
  $m->nextFrame();
}

my %newrects;
my $xzero = 73;
$s = &square($xzero, $midpoint - 25, 
             0xf0, 0xa0, 0x10, 0);
$newrects{1} = $m->add($s);
$s = &square($xzero + 21, $midpoint - 25, 
             0xd0, 0xc0, 0x60, 0);
$newrects{5} = $m->add($s);
$s = &square($xzero + 42, $midpoint - 25, 
             0x40, 0xd0, 0x20, 0);
$newrects{2} = $m->add($s);
$s = &square(114+43, $midpoint - 25, 
             0, $tracegreen, 0xff, 0);
$newrects{4} = $m->add($s);
$s = &square(114+43 + 21, $midpoint - 25, 
             0xc0, 0x10, 0xf0, 0);
$newrects{6} = $m->add($s);
$s = &square(114+43 + 42, $midpoint - 25, 
             110, 0, 110, 0);
$newrects{3} = $m->add($s);

for(my $off=0; $off <= 25; $off++) {
  my $k;
  foreach $k (keys %newrects) {
    my $int =  ( $off - ( $k * 2 ) ) * 20;
    if( $int >= 0 && $int <=255 ) {
      $newrects{$k}->addColor(0, 0, 0, $int);
    }
  }
  $m->nextFrame();
}

&pause($m);
&fadeout(5, $ttl);
$ttl = &title($m, "System Architecture");
&fadein(5, $ttl);
&statusmsg($m, "");

my $alpha;
for( $alpha = 220; $alpha >= 0; $alpha -= 22 ) {
  my $k;
  foreach $k ( keys %newrects ) {
    $newrects{$k}->addColor(0, 0, 0, $alpha);
  }
  foreach $k ( keys %rects ) {
    $rects{$k}->addColor(0, 0, 0, $alpha);
  }
  $m->nextFrame();
}

# &pause($m);
my $ln = new SWF::Shape();
$ln->setLine(3, $textcol, $textcol, $textcol);
$ln->movePenTo(-75, 0);
$ln->drawLineTo(75, 0);
my $lnn = $m->add($ln);
$lnn->moveTo(150, $midpoint);

my $txtwng = $ping->getWidth("Network Guardian");
my $txtwin = $ping->getWidth("Interpreter");
for($i=0; $i<0.3; $i+=0.02) {
  #$int->moveTo($hcenter - $txtwin*(1+$i)/2,$midpoint -7);
  #$int->scaleTo(1+$i, 1);
  #$ng->moveTo($hcenter - $txtwng*(1-$i)/2,$midpoint +19);
  #$ng->scaleTo(1-$i, 1);
  $chopliney->scaleTo(1-2.2*$i,1);
  $chopliney->moveTo($hcenter - 300*(1-1.8*$i)/2,$midpoint);
  $m->nextFrame();
}
$m->remove($chopliney);

sub server {
  my ($waitframes) = @_;
  my $ret = new SWF::MovieClip();
  my $int = $ret->add(&text("Interpreter", $textcol, $textcol, $textcol, 0x5f));
  $int->moveTo(0-$ping->getWidth("Interpreter")/2, -7);
  my $ng = $ret->add(&text("Network Guardian", $textcol, $textcol, $textcol, 0x5f));
  $ng->moveTo(0-$ping->getWidth("Network Guardian")/2, +19);
  my $ln = new SWF::Shape();
  $ln->setLine(3, $textcol, $textcol, $textcol);
  $ln->movePenTo(-75, 0);
  $ln->drawLineTo(70, 0);
  $ret->add($ln);
  
  $ret -> nextFrame();
  
  $ret->add(new SWF::Action('stop();'));
  $ret -> nextFrame();

  for($i = 1; $i <= $waitframes; $i++) {
    $int->addColor(0,0,0,$i/$waitframes * 0xaf + 0x5f);
    $ng->addColor(0,0,0,$i/$waitframes * (0xaf) + 0x5f);
    $ret -> nextFrame();
  }

#  $ret->add(new SWF::Action('stop();'));
#  $ret -> nextFrame();

  my $fe = $ret->add(&text("Front-End", $textcol-40, $textcol, $textcol-40, 0x0));
  $fe->moveTo(0-$ping->getWidth("Front-End")/2, -35);

  $ln = new SWF::Shape();
  $ln->setLine(3, $textcol-40, $textcol, $textcol-40);
  $ln->movePenTo(-75, -28);
  $ln->drawLineTo(70, -28);
  my $lny = $ret->add($ln);

  for($i=5;  $i <=255; $i+=25) {
    $lny->addColor(0,40,0,$i);
    $fe->addColor(0,40,0,$i);
    $ret->nextFrame();
  }
  $ret->add(new SWF::Action('stop();'));
  $ret->nextFrame();

  $ret;
}

my %servers;
my $k;
foreach $k ( 1, 2, 3, 4 ) {
  $servers{$k} = $m->add(&server(20));
  $servers{$k}->moveTo(150,$midpoint);
  $servers{$k}->setName("svr$k");
}

$m->remove($ng);
$m->remove($int);
$m->remove($lnn);

$m->nextFrame();
&pause($m);
&statusmsg($m, "1. Add a front-end web server");

foreach $k ( keys %servers ) {
  $m->add(new SWF::Action("_root.svr$k.play();"));
}

for ($i=0;$i < 20; $i ++) {
  foreach $k ( keys %servers ) {
    $servers{$k}->move(($k % 2) ? 3 : -3, ($k > 2) ? 3 : 0);
    $servers{$k}->scale(0.96,0.96);
  }
  $m->nextFrame();
}

&pause($m);
&statusmsg($m, "2. Periodically refresh directory");

sub refresher {
  my ($waitframes) = @_;
  my $ret = new SWF::MovieClip();
#  my $ln = new SWF::Shape();
#  $ln->setLine(2, 0, 50, 0);
#  $ln->drawLineTo(20, 0);
#  $ret->add($ln);
#  $ret -> nextFrame();
  
  for( $i = 1; $i < 24; $i++ ) {
    my $lna = new SWF::Shape();
    $lna->setLine(2, $textcol-120, $textcol, $textcol-120);
    $lna->movePenTo(0, 0);
    $lna->drawLineTo($i, 0);
    my $lnay =  $ret->add($lna);
    my $lnby;

    if($i<20) {
      my $lnb = new SWF::Shape();
      $lnb->setLine(2, $textcol-120, $textcol, $textcol-120);
      #$lnb->movePenTo($i * 2 + 4, 2);
      $lnb->movePenTo(24, 0);
      $lnb->drawLineTo(($i) + 4, 0);
      $lnby = $ret->add($lnb);
    }
    
    $ret->nextFrame();
    $ret->remove($lnay);
    if($i<20) {
      $ret->remove($lnby);
    }
  }
  
  $ret;
}

sub textsprite {
  my ($text, $center) = @_;
  my $ret = new SWF::MovieClip();
  my $l;
  my $y = 0;
  foreach $l ( split("\n", $text) ) { 
    my $tl = $ret->add(&text($l, $textcol, $textcol, $textcol, 0));
    if($center) {
      $tl->moveTo(0-$ping->getWidth($l)/2, $y);
    } else {
      $tl->moveTo(0, $y);
    }
    $y += 22;
  }
  
  print DUMP ".\n";
  $ret->nextFrame();
  $ret;
}

my $tsm = $m->add(&textsprite("Central\nDirectory", 1));
$tsm->moveTo(150, $midpoint + 25);

for ($i=0;$i <=10; $i ++) {
  foreach $k ( keys %servers ) {
    $servers{$k}->move(($k % 2) ? 3 : -3, 0);
  }
  $tsm->addColor(0,0,0,$i * 25 + 5);
  #$tl2->addColor(0,0,0,$i * 25 * 5);
  $m->nextFrame();
}

my %refreshers;
$refreshers{1} = $m->add(&refresher);
$refreshers{1}->moveTo(100,$midpoint + 65);
$refreshers{1}->rotate(35);

$refreshers{2} = $m->add(&refresher);
$refreshers{2}->moveTo(200,$midpoint + 65);
$refreshers{2}->rotate(145);

$refreshers{3} = $m->add(&refresher);
$refreshers{3}->moveTo(220,$midpoint + 16);
$refreshers{3}->rotate(200);

$refreshers{4} = $m->add(&refresher);
$refreshers{4}->moveTo(80,$midpoint + 16);
$refreshers{4}->rotate(-20);

&pause($m);
&statusmsg($m, "So clients can find servers");

my $tcl = $m->add(&textsprite("Client", 1));
$tcl->moveTo(150, $midpoint-25);

for ($i=0;$i <=10; $i ++) {
  $tsm->scale(0.96,0.96);
  $tsm->move(0,1);
  $tcl->addColor(0,0,0,$i * 25 + 5);
  $m->nextFrame();
}

sub arrowsprite {
  my ($waitframes) = @_;
  my $ret = new SWF::MovieClip();
  my $i;
  
  for( $i = 1; $i < 8; $i++ ) {
    my $lna = new SWF::Shape();
    $lna->setLine(2, 0, 0, 120);
    $lna->setLine(2, $textcol-120, $textcol-120, $textcol);
    $lna->movePenTo(0, 0);
    $lna->drawLineTo($i*3, 0);
    my $xxx = $ret -> add($lna);
    $ret -> nextFrame();
    $ret -> remove($xxx);
  }
  my $lna = new SWF::Shape();
  $lna->setLine(2, $textcol-120, $textcol-120, $textcol);
  $lna->movePenTo(0, 0);
  $lna->drawLineTo($i*3, 0);
  $lna->drawLine(-2, -2);
  $lna->drawLine(2, 2);
  $lna->drawLine(-2, 2);
  $ret -> add($lna);
  $ret->add(new SWF::Action('stop();'));
  $ret -> nextFrame();
  
  $ret;

}

my $tarcl = $m->add(&arrowsprite);
$tarcl->moveTo(150, $midpoint + 20);
$tarcl->scale(1.6,1);
$tarcl->rotate(90);

for($i=0; $i<12; $i++) {
  $m->nextFrame();
}

my $tarlf = $m->add(&arrowsprite);
$tarlf->moveTo(120, $midpoint -32);
$tarlf->scale(1.4,1);
$tarlf->rotate(200);

my $tarrt = $m->add(&arrowsprite);
$tarrt->moveTo(180, $midpoint-32);
$tarrt->scale(1.4,1);
$tarrt->rotate(-20);

&pause($m);

&statusmsg($m, "Happy researchers!");
#my $tarve = $m->add(&arrowsprite);
#$tarve->moveTo(180, $midpoint+16);
#$tarve->scale(1.4,1);
#$tarve->rotate(20);
#
#&statusmsg($m, "End-to-end verification");

&pause($m);

&fadeout(5, $tarrt, $tarlf, $tarcl, $tcl, values %refreshers, 
         $servers{4}, $servers{3}, $servers{1}, $tsm, $lastmsg);

for ($i=0;$i < 10; $i ++) {
  $servers{2}->move(0, -1);
  $servers{2}->scale(1.03,1.03);
  $m->nextFrame();
}

sub tab {
  my $ret = new SWF::Shape();
  my ($idx) = @_;
  my $fill = $ret->addFill(0, 0, 60, 0xff);
  $ret->setLeftFill($fill);
  $ret->setLine(2, $textcol-120, $textcol-120, $textcol);
  $ret->movePenTo(5,40 + $idx * 16 );
  $ret->drawLineTo(108,40 + $idx * 16 );
  $ret->drawLineTo(108, 40 );
  $ret->drawLineTo(290, 40 );
  $ret->drawLineTo(290, 185);
  $ret->drawLineTo(108, 185);
  $ret->drawLineTo(108, 55 + $idx * 16);
  $ret->drawLineTo(5, 55 + $idx * 16);
  $ret->drawLineTo(5, 40 + $idx * 16);
  
  print DUMP "-\n";

  $ret;
}

&fadeout(5, $ttl);
$ttl = &title($m, "Security Architecture");
my $fedesc = $m->add(&textsprite("Protect:\n". 
                                 "1. Host resources\n" .
                                 "2. Host integrity\n" .
                                 "3. The network\n", 0));
$fedesc->moveTo(115, 60);
# $fedesc->scaleTo(0.9, 0.9);
&fadein(5, $ttl, $fedesc);

&pause($m);
&fadeout(5, $fedesc);

my $lasttab = $m->add(&tab(0));
$lasttab->setDepth(0);
$fedesc = $m->add(&textsprite("Accepts scripts\n" .
                              "  (thttpd)\n" .
                              "Verifies client address\n" .
                              "Limits script length\n" .
                              "Limits duration\n" .
                              "Limits output length", 0));
$fedesc->moveTo(115, 60);
$fedesc->scaleTo(0.9, 0.9);
&fadein(5, $fedesc);

&pause($m);
&fadeout(5, $fedesc);
$m->remove($lasttab);
$lasttab = $m->add(&tab(1));
$lasttab->setDepth(0);
$fedesc = $m->add(&textsprite("Executes scripts\n\n" .
                              "Safe-mode\n" .
                              "Resource limits:\n" .
                              " Memory, CPU time\n" .
                              " Processes, files\n" .
                              "Nobody in chroot\n", 0));
$fedesc->moveTo(115, 60);
$fedesc->scaleTo(0.9, 0.9);
&fadein(5, $fedesc);

&pause($m);
&fadeout(5, $fedesc);
$m->remove($lasttab);
$lasttab = $m->add(&tab(2));
$lasttab->setDepth(0);
$fedesc = $m->add(&textsprite("Raw net access\n\n" .
                              "Protect network\n" .
                              "Rate-limits:\n" .
                              " Source, Destination\n" .
                              "Filter bad packets\n" .
                              "Log packets\n", 0));
$fedesc->moveTo(115, 60);
$fedesc->scaleTo(0.9, 0.9);
&fadein(5, $fedesc);
&pause($m);
&fadeout(5, $ttl, $fedesc, $lasttab, $servers{2});

$ttl = &title($m, "Evaluating Scriptroute");
$fedesc = $m->add(&textsprite("Is it easy?\n" .
                              "Can we build\n  something useful?", 0));
$fedesc->moveTo(20, 60);
&fadein(5, $ttl, $fedesc);
&pause($m);
&fadeout(5, $ttl, $fedesc);

$ttl = &title($m, "Building tools");
$fedesc = $m->add(&textsprite(&traceroute_text, 0));
$fedesc->moveTo(20, 40);
$fedesc->scaleTo(0.33, 0.33);
# $fedesc->scaleTo(0.9, 0.9);
&fadein(3, $ttl, $fedesc);

&pause($m);
&fadeout(3, $ttl, $fedesc);
#######

$ttl = &title($m, "Distributed tools");
my $fedescy = $m->add(&textsprite("Reverse Path Tree", 0));
$fedesc = $m->add(&textsprite("G.N.P. eval dataset collector\n" .
                              "Planet-Lab topology discovery\n" . 
                              "Network mapping\n" , 0));
$fedescy->moveTo(20, 60);
$fedesc->moveTo(20, 80);
$fedesc->scaleTo(0.9, 0.9);
# $fedesc->scaleTo(0.9, 0.9);
&fadein(5, $ttl, $fedesc, $fedescy);

&pause($m);
&fadeout(5, $ttl, $fedesc);
for($i=0; $i <=5; $i++) {
  $fedescy->move(0, -6);
  $m->nextFrame();
}

sub circle {
  my ($r, $red, $g, $blue, $alpha) = @_;
  my $x = 0;
  my $y = 0;
  my $a = $r * 0.414213562; # = tan(22.5 deg)
  my $b = $r * 0.707106781; # = sqrt(2)/2 = sin(45 deg)

  $s = new SWF::Shape();
  my $fill = $s->addFill($red, $g, $blue, $alpha);
  $s->setLine(1, $red, $g, $blue, $alpha);
  $s->setLeftFill($fill);

  $s->movePenTo($x+$r, $y);

  $s->drawCurveTo($x+$r, $y-$a, $x+$b, $y-$b);
  $s->drawCurveTo($x+$a, $y-$r, $x, $y-$r);
  $s->drawCurveTo($x-$a, $y-$r, $x-$b, $y-$b);
  $s->drawCurveTo($x-$r, $y-$a, $x-$r, $y);
  $s->drawCurveTo($x-$r, $y+$a, $x-$b, $y+$b);
  $s->drawCurveTo($x-$a, $y+$r, $x, $y+$r);
  $s->drawCurveTo($x+$a, $y+$r, $x+$b, $y+$b);
  $s->drawCurveTo($x+$r, $y+$a, $x+$r, $y);
  $s;
}

my %svrcircle;
my @colors = ( "150 255 255" , "205 100 205" , "220 100 100", "90 240 90" , "110 110 255" );
for($i = 0; $i < 5; $i++) {
  $svrcircle{$i} = $m->add(&circle(20, split(' ', $colors[$i]), 0xff));
  $svrcircle{$i}->moveTo(30, 50);
  $svrcircle{$i}->scaleTo(0.5, 0.5);
}
$m->nextFrame;
# 15 too small.
# 18 too small.
for(my $i = 1; $i <=10; $i++) {
  my $k;
  foreach $k ( keys %svrcircle ) {
    $svrcircle{$k}->move( $k * 6, 0);
  }
  $m->nextFrame;
}

sub make_target {
  my $s = new SWF::MovieClip();
  my $target0 = $s->add(&circle(20, split(' ', "255 0 0"), 0xff));
  my $target1 = $s->add(&circle(20, split(' ', "255 255 255"), 0xff));
  my $target2 = $s->add(&circle(20, split(' ', "255 0 0"), 0xff));
  $target0->scaleTo(0.5, 0.5);
  $target1->scaleTo(0.35, 0.35);
  $target2->scaleTo(0.15, 0.15);
  $s->nextFrame();
  $s;
}
  
my $target = $m->add(&make_target);
$target->moveTo(150,170);


# 20 to 280, 70 to 150 
my @rtrcircleloc  = ( "20 100", "30 140", "50 80", "60 120", "70 150", "80 75", "90 100",
                      "120 100", "130 140", "150 80", "160 120", "170 150", "180 75", "190 100", 
                      "220 100", "230 140", "250 80", "260 120", "270 150", "280 75", 
                      );
my %rtrcircle;
$i = 0;
foreach my $loc ( @rtrcircleloc ) {
  $rtrcircle{$i} = $m->add(&circle(20, split(' ', "200 200 200"), 0xff));
  $rtrcircle{$i}->moveTo(split(' ', $loc));
  $rtrcircle{$i}->scaleTo(0.3, 0.3);
  #$s = $m->add(&textsprite("$i",1));
  #$s->moveTo(split(' ', $loc));
  #$s->addColor(0,0,0,0xff);
#
  $i ++;
}

sub first {
  my $path = new SWF::MovieClip();
  my $s = new SWF::Shape();
  my ($color, @hops) = @_;

  $s->setLine(2, split(' ', $color), 0xff);
  $s->movePenTo(split(' ', shift(@hops)));
  foreach my $h ( @hops ) {
    $s->drawLineTo(split(' ', $h));
  }
  $path->add($s);

  $path->add(new SWF::Action('stop();'));
  $path->nextFrame();
  $path;
}

sub righttwo {
  my ($x, $y) = split(' ', $_[0]);
  "" . ($x+2) . " " . ($y-1);
}

&pause($m);
my @lines;
sub drawlines {
  my ($wantpause) = @_;
  $lines[0] = $m->add(&first($colors[0], "30 50", ( map { $rtrcircleloc[$_]; } ( 2, 6, 7, 8 ) ) , "150 170"));
  $lines[0]->setDepth(0);
  &pause($m) if($wantpause);
  $lines[1] = $m->add(&first($colors[1], "90 50",  ( map { &righttwo($rtrcircleloc[$_]); } ( 5, 6 )) ));
  $lines[1]->setDepth(0);
  &pause($m) if($wantpause);
  $lines[2] = $m->add(&first($colors[2], "150 50", 
                             ( map { &righttwo($rtrcircleloc[$_]); } ( 9, 12, 13, 10, 11 )) , 
                             &righttwo("150 170") ));
  $lines[2]->setDepth(0);
  &pause($m) if($wantpause);
  $lines[3] = $m->add(&first($colors[3], "210 50", ( map { $rtrcircleloc[$_]; } ( 16, 17, 15, 11 )) ));
  $lines[3]->setDepth(0);
  &pause($m) if($wantpause);
  $lines[4] = $m->add(&first($colors[4], "270 50", 
                             ( map { &righttwo($rtrcircleloc[$_]); } ( 19, 17 )) ));
  $lines[4]->setDepth(0);
  &pause($m) if($wantpause);
}
&drawlines(1);
&fadeout(5, $fedescy);
$ttl = &title($m, "R P T: Alias resolution");
&fadein(5, $ttl);

sub recolor {
  my ($i, @col) = @_;
  $m->remove( $rtrcircle{$i} );
  $rtrcircle{$i} = $m->add(&circle(20, @col, 0xff));
  $rtrcircle{$i}->moveTo(split(' ', $rtrcircleloc[$i]));
  $rtrcircle{$i}->scaleTo(0.3, 0.3);
}

&recolor(11, 180, 40, 180);
&recolor(8, 180, 40, 180);
&recolor(5, 50, 255, 50);
&recolor(2, 50, 255, 50);
&recolor(16, 50, 50, 255);
&recolor(19, 50, 50, 255);
&recolor(10, 255, 255, 100);
&recolor(15, 255, 255, 100);
&pause($m);

sub meld {
  my ($stepleft, $a, $b) = @_;
  my ($x1, $y1) = split(' ', $rtrcircleloc[$a]);
  my ($x2, $y2) = split(' ', $rtrcircleloc[$b]);
  $x1 = int($x1 + ( $x2 - $x1 ) / $stepleft);
  $x2 = int($x2 + ( $x1 - $x2 ) / $stepleft);
  $y1 = int($y1 + ( $y2 - $y1 ) / $stepleft);
  $y2 = int($y2 + ( $y1 - $y2 ) / $stepleft);
  
  $rtrcircleloc[$a] = "$x1 $y1";
  $rtrcircleloc[$b] = "$x2 $y2";
}
for($i=15; $i > 0; $i--) {
  &meld($i, 11,8);
  &meld($i, 5,2);
  &meld($i, 16,19);
  foreach my $l (@lines) {
    $m->remove($l);
  }
  &drawlines(0);
  # have to redraw the dots
  &recolor(11, 180, 40, 180);
  &recolor(8, 180, 40, 180);
  &recolor(5, 50, 255, 50);
  &recolor(2, 50, 255, 50);
  &recolor(16, 50, 50, 255);
  &recolor(19, 50, 50, 255);
  $m->nextFrame();
}

&pause($m);

&fadeout(5, $ttl, values %rtrcircle, @lines, $target, values %svrcircle);

$ttl = &title($m, "R P T  Summary");
$fedesc = $m->add(&textsprite("Network friendly\n" .
                              "Server friendly\n" .
                              "Traceroute +\n" .
                              "Composition of scripts\n" .
                              "Foundation for annotation\n" .
                              "Live demo at scriptroute.org\n", 0));
$fedesc->moveTo(20, 60);
#$fedesc->scaleTo(0.9, 0.9);
# $fedesc->scaleTo(0.9, 0.9);
&fadein(5, $ttl, $fedesc);

&pause($m);
&fadeout(5, $ttl, $fedesc);
########

$ttl = &title($m, "Things worth doing");
$fedesc = $m->add(&textsprite("Portable (adaptive) resource limits\n". 
                              "Precise probe scheduling\n",
                              0));
$fedesc->moveTo(20, 60);
$fedesc->scaleTo(0.9, 0.9);
# $fedesc->scaleTo(0.9, 0.9);
&fadein(5, $ttl, $fedesc);

&pause($m);
&fadeout(5, $ttl, $fedesc);
###
$ttl = &title($m, "Related");
&fadein(5, $ttl);
my $originx = 40;
my $originy = $midpoint + 25;
my $yaxis = $m->add(&arrowsprite);
$yaxis->moveTo($originx, $originy);
$yaxis->scale(3,1);
$yaxis->rotate(90);
my $yaxislab = $m->add(&textsprite("Flexibility", 0));
$yaxislab->moveTo($originx-10, $originy);
$yaxislab->scaleTo(0.9, 0.9);
$yaxislab->rotate(90);
&fadein(5, $yaxislab);

  my $flexc = $m->add(&circle(20, 255, 50, 50, 0xff));
  $flexc->moveTo($originx + 10, $originy-50);
  $flexc->scaleTo(0.3, 0.3);
  my $flex = $m->add(&text("Platforms and Testbeds", 255, 50, 50, 0xff));
  $flex->moveTo($originx + 10, $originy-60);

&pause($m);
my $xaxis = $m->add(&arrowsprite);
$xaxis->moveTo($originx, $originy);
$xaxis->scale(3,1);
my $xaxislab = $m->add(&textsprite("Deployment", 0));
$xaxislab->moveTo($originx, $originy + 20);
$xaxislab->scaleTo(0.9, 0.9);
&fadein(5, $xaxislab);

  my $trac = $m->add(&circle(20, 220, 50, 220, 0xff));
  $trac->moveTo($originx + 50, $originy-5);
  $trac->scaleTo(0.3, 0.3);
  my $tray = $m->add(&text("Traceroute Servers", 220, 50, 220, 0xff));
  $tray->moveTo($originx + 60, $originy-5);

&pause($m);

  my $scrpc = $m->add(&circle(20, 150, 255, 150, 0xff));
  $scrpc->moveTo($originx + 30, $originy-30);
  $scrpc->scaleTo(0.3, 0.3);
  my $scrp = $m->add(&text("Scriptroute", 150, 255, 150, 0xff));
  $scrp->moveTo($originx + 40, $originy-30);

#$fedesc = $m->add(&textsprite("Testbeds and Platforms:\n" .
#                              "  NIMI, RON, AMP, Surveyor\n" .
#                              "  RIPE-NCC, Emulab\n". 
#                              "  Traceroute servers\n" .
#                              "FLAME, PeriScope\n",
#                              0));
#$fedesc->moveTo(20, 60);
#$fedesc->scaleTo(0.9, 0.9);
# $fedesc->scaleTo(0.9, 0.9);

&pause($m);
&fadeout(5, $ttl, $yaxislab, $xaxislab, $xaxis, $yaxis, 
         $trac, $flexc, $flex, $tray, $scrpc, $scrp);
###
$ttl = &title($m, "Conclusion");
$fedesc = $m->add(&textsprite("Scriptroute is an open system\n" .
                              "  for flexible, distributed\n" .
                              "  network measurement.\n" .
                              "Deployed on Planet-lab\n\n" .
                              "www.scriptroute.org\n" .
                              "nspring\@cs.washington.edu\n", 0));
$fedesc->moveTo(20, 60);
$fedesc->scaleTo(0.9, 0.9);

&fadein(5, $ttl, $fedesc);
&pause($m);

$m->add(new SWF::Action('stop();'));
$m->nextFrame();
$m->save("usits-scriptroute.swf");
print "saved.\n";

exit();
print "out?.\n";
close(DUMP);

sub traceroute_text {
  my $ret =<<EOF;
#! ../srinterpreter
probe = Scriptroute::Udp.new(12) 
probe.ip_dst = ARGV[0]
unreach = false
catch (:unreachable) do 
      ( 1..64 ).each { |probe.ip_ttl|
          ( 1..3 ).each { |rep|
            packets = Scriptroute::send_train([ Struct::DelayedPacket.new(0,probe) ])
            response = (packets[0].response) ?  packets[0].response.packet : nil
            if(response) then
                puts '%d %s %5.3f ms' % [ ttl, response.ip_src, packets[0].rtt * 1000.0 ]
                if(response.is_a?(Scriptroute::Icmp)) then
                    unreach = true if(response.icmp_type == Scriptroute::Icmp::ICMP_UNREACH)
                end
            else
                puts ttl.to_s + ' *' 
            end
        }
        throw :unreachable if(unreach)
    }
end
}
EOF
}
