Thanks, AM, I've got results, and having a stochastic means of taking guesses has been a key in making it as robust as it is.
#! /usr/bin/perl use warnings; use strict; use 5.010; use WWW::Mechanize::GZip; use HTML::TableExtract qw(tree); use open ':std', OUT => ':utf8'; use Prompt::Timeout; use constant TIMEOUT => 3; use constant MAXTRIES => 30; 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 $before_bound = 2457496.65; #before conjunction my $after_bound = 2457496.75; #after conjunction $mech->set_fields(qw'date 2'); my $moonstring = 5; my $jstr = 3; my $upper = $before_bound; my $lower = $after_bound; my $equal; my $equal_sec; my $now_string = localtime; my $filename = 'planet7.txt'; open( my $jh, '>>', $filename ) or die "Could not open file '$filename +' $!"; say $jh "Script executed at $now_string"; my $attempts = 1; while ( ( $jstr != $moonstring ) ) { my $default = ( ( $attempts >= MAXTRIES ) ) ? 'N' : 'Y'; my $answer = prompt( "Make query number $attempts?", $default, TIME +OUT ); exit if $answer =~ /^N/i; say "upper is $upper"; say "lower is $lower"; my $guess = closetohalf( $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( 5, 1 )->as_text; my $jupiter = $table_tree->cell( 7, 1 )->as_text; $moonstring = string_to_second($venus); say "moon seconds is $moonstring"; $jstr = string_to_second($jupiter); say "jupiter seconds is $jstr"; if ( $jstr > $moonstring ) { $upper = $guess; } elsif ( $moonstring > $jstr ) { $lower = $guess; } else { $equal = $guess; say "equal, while condition should fail $equal"; $equal_sec = $moonstring; } $te->delete; $attempts++; } say $jh "equal seconds is $equal_sec"; ###redesign 4/20/16 ## determining beginning my $outer = $before_bound; my $inner = $equal; say $jh join "\t", 'moonstring', 'jstr', 'outer', 'inner', 'guess'; $attempts = 1; while ( ( abs( $outer - $inner ) > .00001 ) ) { my $default = ( ( $attempts >= MAXTRIES ) ) ? 'N' : 'Y'; my $answer = prompt( "Make query number $attempts?", $default, TIME +OUT ); exit if $answer =~ /^N/i; say "outer is $outer"; say "inner is $inner"; my $guess = closetohalf( $outer, $inner ); 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( 5, 1 )->as_text; my $jupiter = $table_tree->cell( 7, 1 )->as_text; $moonstring = string_to_second($venus); $jstr = string_to_second($jupiter); say $jh join "\t", $moonstring, $jstr, $outer, $inner, $guess; if ( $moonstring < $jstr ) { $outer = $guess; } elsif ( $moonstring == $jstr ) { $inner = $guess; } else { die "retrograde motion or bad data"; } $te->delete; $attempts++; } say $jh "after beginning contraction, upper is $outer"; say $jh "after beginning contraction, lower is $inner"; my $begin_time = $inner; ## determine end time $outer = $after_bound; $inner = $equal; say $jh join "\t", 'moonstring', 'jstr', 'outer', 'inner', 'guess'; $attempts = 1; while ( ( abs( $outer - $inner ) > .00001 ) ) { my $default = ( ( $attempts >= MAXTRIES ) ) ? 'N' : 'Y'; my $answer = prompt( "Make query number $attempts?", $default, TIME +OUT ); exit if $answer =~ /^N/i; say "outer is $outer"; say "inner is $inner"; my $guess = closetohalf( $outer, $inner ); 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( 5, 1 )->as_text; my $jupiter = $table_tree->cell( 7, 1 )->as_text; $moonstring = string_to_second($venus); $jstr = string_to_second($jupiter); say $jh join "\t", $moonstring, $jstr, $outer, $inner, $guess; if ( $moonstring > $jstr ) { $outer = $guess; } elsif ( $moonstring == $jstr ) { $inner = $guess; } else { die "retrograde motion or bad data"; } $te->delete; $attempts++; } say $jh "after ending contraction, outer is $outer"; say $jh "after ending contraction, inner is $inner"; my $end_time = $inner; my $jul_length = $end_time - $begin_time; my $second_length = $jul_length * 86400; say "duration in seconds is $second_length"; say $jh "duration in seconds is $second_length"; 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 closetohalf { my ( $up, $low ) = @_; $low + ( $up - $low ) * ( 0.4 + rand 0.2 ); }
Output:
Script executed at Sun Apr 24 16:40:08 2016 equal seconds is 39783 moonstring jstr outer inner guess 39726 39783 2457496.65 2457496.69915925 2457496.67869833 39753 39783 2457496.67869833 2457496.69915925 2457496.6885 +3017 39769 39783 2457496.68853017 2457496.69915925 2457496.6942 +0768 39777 39783 2457496.69420768 2457496.69915925 2457496.6971 +6155 39780 39783 2457496.69716155 2457496.69915925 2457496.6981 +1072 39781 39783 2457496.69811072 2457496.69915925 2457496.6986 +7181 39782 39783 2457496.69867181 2457496.69915925 2457496.6989 +1007 39782 39783 2457496.69891007 2457496.69915925 2457496.6990 +2581 39783 39783 2457496.69902581 2457496.69915925 2457496.6990 +8113 39782 39783 2457496.69902581 2457496.69908113 2457496.6990 +5188 39783 39783 2457496.69905188 2457496.69908113 2457496.6990 +6548 39782 39783 2457496.69905188 2457496.69906548 2457496.6990 +5783 after beginning contraction, upper is 2457496.69905783 after beginning contraction, lower is 2457496.69906548 moonstring jstr outer inner guess 39864 39783 2457496.75 2457496.69915925 2457496.72857204 39818 39783 2457496.72857204 2457496.69915925 2457496.7117 +5627 39800 39783 2457496.71175627 2457496.69915925 2457496.7055 +5956 39792 39783 2457496.70555956 2457496.69915925 2457496.7023 +8023 39788 39783 2457496.70238023 2457496.69915925 2457496.7009 +2664 39785 39783 2457496.70092664 2457496.69915925 2457496.6998 +935 39784 39783 2457496.6998935 2457496.69915925 2457496.69946 +611 39783 39783 2457496.69946611 2457496.69915925 2457496.6993 +0239 39783 39783 2457496.69946611 2457496.69930239 2457496.6993 +7787 39783 39783 2457496.69946611 2457496.69937787 2457496.6994 +1601 39784 39783 2457496.69946611 2457496.69941601 2457496.6994 +3739 39784 39783 2457496.69943739 2457496.69941601 2457496.6994 +2669 39783 39783 2457496.69942669 2457496.69941601 2457496.6994 +21 after ending contraction, outer is 2457496.69942669 after ending contraction, inner is 2457496.699421 duration in seconds is 30.7171538472176
Does the ultimate result seem plausible? I think I have a geometric justification for why this should be close to the number of days in a month. (Jupiter's position in seconds remains unchanged during the event.)
Beyond whether this makes any sense physically is how it looks and works as perl, and I'm accepting any criticisms along those lines. Thank you, and happy skywatching....
In reply to Re^2: subroutines for close to half
by Aldebaran
in thread subroutines for close to half
by Aldebaran
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |