#! /usr/bin/perl use warnings; use strict; use 5.010; use WWW::Mechanize::GZip; use HTML::TableExtract; use HTML::TableExtract qw(tree); use open ':std', OUT => ':utf8'; use Prompt::Timeout; use constant TIMEOUT => 3; use constant MAXTRIES => 16; my $site = 'http://www.fourmilab.ch/yoursky/cities.html'; my $mech = 'WWW::Mechanize::GZip'->new; $mech->get($site); $mech->follow_link( text => 'Portland OR' ); my $lub = 2457204.63659; #least upper bound my $glb = 2457207.63659; #greatest lower bound my @right; my @left; my @julian; $mech->set_fields(qw'date 2'); my ( $vstr, $jstr ) = ( 5, 3 ); my $upper = $lub; my $lower = $glb; my $equal; my $equal_sec; my $now_string = localtime; my $filename = 'planet5.txt'; open( my $jh, '>>', $filename ) or die "Could not open file '$filename' $!"; say $jh "Script executed at $now_string"; say $jh join "\t", "venus", "jupiter", "julian date"; my $attempts = 1; while ( ( $jstr != $vstr ) ) { my $default = ( ( $attempts >= MAXTRIES ) ) ? 'N' : 'Y'; my $answer = prompt( "Make query number $attempts?", $default, TIMEOUT ); exit if $answer =~ /^N/i; my $guess = median( $upper, $lower ); say "guess is $guess"; push @julian, $guess; $mech->set_fields( jd => $guess ); $mech->click_button( value => "Update" ); my $te = 'HTML::TableExtract'->new; $te->parse( $mech->content ); my $table = ( $te->tables )[3]; my $table_tree = $table->tree; my $venus = $table_tree->cell( 4, 1 )->as_text; my $jupiter = $table_tree->cell( 7, 1 )->as_text; $vstr = string_to_second($venus); say "vstr is $vstr"; push @right, $vstr; $jstr = string_to_second($jupiter); say "jstr is $jstr"; push @left, $jstr; say $jh join "\t", $vstr, $jstr, $guess; if ( $jstr > $vstr ) { $upper = $guess; } elsif ( $vstr > $jstr ) { $lower = $guess; } else { $equal = $guess; say "equal, while condition should fail $equal"; $equal_sec = $vstr; } $te->delete; $attempts++; } my $equal_ra = second_to_string($equal_sec); say "equal_ra is $equal_ra"; say $jh "equal seconds is $equal_sec and equal ra is $equal_ra"; say "right is @right"; say "left is @left"; say "julian is @julian"; ## Determine last best guess that was unequal my $ind1 = get_index( \@right ); say "ind is $ind1"; say "v is $right[$ind1] and jul is $julian[$ind1]"; if ( $ind1 >= 0 ) { $upper = $julian[$ind1]; } else { $upper = $lub; } say "upper is $upper"; $lower = $julian[-1]; say "lower is $lower"; ## find upper bound of convergence range $attempts = 1; while ( ( abs( $upper - $lower ) > .000005 ) ) { my $default = ( ( $attempts >= MAXTRIES ) ) ? 'N' : 'Y'; my $answer = prompt( "Make query number $attempts?", $default, TIMEOUT ); exit if $answer =~ /^N/i; my $guess = median( $upper, $lower ); say "guess is $guess"; $mech->set_fields( jd => $guess ); $mech->click_button( value => "Update" ); my $te = 'HTML::TableExtract'->new; $te->parse( $mech->content ); my $table = ( $te->tables )[3]; my $table_tree = $table->tree; my $venus = $table_tree->cell( 4, 1 )->as_text; my $jupiter = $table_tree->cell( 7, 1 )->as_text; $vstr = string_to_second($venus); say "vstr is $vstr"; $jstr = string_to_second($jupiter); say "jstr is $jstr"; say $jh join "\t", $vstr, $jstr, $guess; if ( $vstr > $jstr ) { $upper = $guess; } elsif ( $vstr == $jstr ) { $lower = $guess; } else { die "retrograde motion or bad data"; } $te->delete; $attempts++; } say "after upper contraction, upper is $upper"; say "after upper contraction, lower is $lower"; my $end_time = $lower; say $jh join "\t", $upper, $end_time; ## Determine last best guess that was unequal $ind1 = low_index( \@left ); say "ind is $ind1"; say "v is $left[$ind1] and jul is $julian[$ind1]"; if ( $ind1 >= 0 ) { $upper = $julian[$ind1]; } else { $upper = $glb; } $lower = $julian[-1]; say "lower is $lower"; ## find beginning bound of convergence range $attempts = 1; while ( ( abs( $upper - $lower ) > .000005 ) ) { my $default = ( ( $attempts >= MAXTRIES ) ) ? 'N' : 'Y'; my $answer = prompt( "Make query number $attempts?", $default, TIMEOUT ); exit if $answer =~ /^N/i; my $guess = median( $upper, $lower ); say "guess is $guess"; $mech->set_fields( jd => $guess ); $mech->click_button( value => "Update" ); my $te = 'HTML::TableExtract'->new; $te->parse( $mech->content ); my $table = ( $te->tables )[3]; my $table_tree = $table->tree; my $venus = $table_tree->cell( 4, 1 )->as_text; my $jupiter = $table_tree->cell( 7, 1 )->as_text; $vstr = string_to_second($venus); say "vstr is $vstr"; $jstr = string_to_second($jupiter); say "jstr is $jstr"; say $jh join "\t", $vstr, $jstr, $guess; if ( $vstr < $jstr ) { $upper = $guess; } elsif ( $vstr == $jstr ) { $lower = $guess; } else { die "retrograde motion or bad data"; } $te->delete; $attempts++; } say "after begin contraction, upper is $upper"; say "after begin contraction, lower is $lower"; my $begin_time = $upper; say $jh join "\t", $lower, $begin_time; my $middle = median( $begin_time, $end_time ); say "middle is $middle"; my $duration = $end_time - $begin_time; say "duration is $duration"; say $jh "middle: $middle\t duration: $duration"; # get final disposition $mech->set_fields( jd => $middle ); $mech->set_fields(qw'lat 35 ns North'); $mech->set_fields(qw'lon 80 ew East'); my $te = 'HTML::TableExtract'->new; $te->parse( $mech->content ); my $table = ( $te->tables )[3]; my $table_tree = $table->tree; my $vdistance = $table_tree->cell( 4, 3 )->as_text; my $jdistance = $table_tree->cell( 7, 3 )->as_text; say $jh "vdistance is $vdistance"; say $jh "jdistance is $jdistance"; my $table2 = ( $te->tables )[1]; my $table_tree2 = $table2->tree; my $table_text2 = $table_tree2->as_text; say "table text2 is $table_text2"; my $utc1 = $table_tree->cell( 1, 1 )->as_text; say $jh "utc1 is $utc1"; my $utc2 = $table_tree->cell( 1, 0 )->as_text; say $jh "utc2 is $utc2"; #my $utc = $mech->value(utc); #say "utc is $utc"; sub median { my ( $up, $low ) = @_; my $return = ( $up + $low ) / 2.0; return $return; } sub string_to_second { my $string = shift; my $return = 9000; if ( my $success = $string =~ /^(\d*)h\s+(\d*)m\s+(\d*)s$/ ) { $return = 3600 * $1 + 60 * $2 + $3; } else { say "string was misformed"; } return $return; } sub second_to_string { my $seconds = shift; my $hours = int( $seconds / 3600 ); my $remainder = $seconds % 3600; my $minutes = int( $remainder / 60 ); my $sec = $remainder % 60; my $return = join '', $hours, 'h ', $minutes, 'm ', $sec, 's'; return $return; } sub get_index { my ($ref_right) = shift; my @right = @$ref_right; my $return = -1; my $eq = $right[-1]; say "right is @right"; say "eq is $eq"; for my $i ( 0 .. $#right ) { if ( $right[$i] <= $eq ) { next; } else { $return = $i; say "i is $i"; } } say "right is @right"; return $return; } sub low_index { my ($ref_right) = shift; my @right = @$ref_right; my $return = -1; my $eq = $right[-1]; say "right is @right"; say "eq is $eq"; for my $i ( 0 .. $#right ) { if ( $right[$i] >= $eq ) { next; } else { $return = $i; say "i is $i"; } } say "right is @right"; return $return; } #### Script executed at Mon Jun 29 02:10:13 2015 venus jupiter julian date 34790 34686 2457206.13659 34682 34653 2457205.38659 34628 34636 2457205.01159 34655 34644 2457205.19909 34641 34640 2457205.10534 34634 34638 2457205.058465 34638 34639 2457205.0819025 34640 34640 2457205.09362125 equal seconds is 34640 and equal ra is 9h 37m 20s 34640 34640 2457205.09948062 34641 34640 2457205.10241031 34641 34640 2457205.10094547 34641 34640 2457205.10021305 34641 34640 2457205.09984684 34641 34640 2457205.09966373 34641 34640 2457205.09957218 34640 34640 2457205.0995264 34641 34640 2457205.09954929 34640 34640 2457205.09953785 34640 34640 2457205.09954357 34640 34640 2457205.09954643 2457205.09954929 2457205.09954643 34639 34640 2457205.08776187 34639 34640 2457205.09069156 34639 34640 2457205.09215641 34640 34640 2457205.09288883 34639 34640 2457205.09252262 34639 34640 2457205.09270572 34640 34640 2457205.09279728 34640 34640 2457205.0927515 34640 34640 2457205.09272861 34639 34640 2457205.09271717 34639 34640 2457205.09272289 34639 34640 2457205.09272575 2457205.09272861 2457205.09272575 middle: 2457205.09613609 duration: 0.0068206787109375 vdistance is 0.512 jdistance is 6.083 utc1 is utc2 is