use strict; use warnings; use DateTime; use constant PI => 2 * atan2(1, 0); my %cycles = ( 'Physical' => 23, 'Emotional' => 28, 'Mental' => 33 ); my @Q = ( ['up and rising', 'peak'], ['up but falling', 'transition'], ['down and falling', 'valley'], ['down but rising', 'transition'] ); my $target = DateTime->new(year=>1863, month=>11, day=>19); my $bday = DateTime->new(year=>1809, month=> 2, day=>12); my $days = $bday->delta_days( $target )->in_units('days'); print "Day $days:\n"; for my $label (sort keys %cycles) { my($length) = $cycles{$label}; my $position = $days % $length; my $quadrant = int $position / $length * 4; my $percentage = int(sin($position / $length * 2 * PI )*1000)/10; my $description; if ( $percentage > 95) { $description = 'peak' } elsif ( $percentage < -95) { $description = 'valley' } elsif (abs($percentage) < 5) { $description = 'critical transition' } else { my $transition = $target->clone->add( days => (int(($quadrant + 1)/4 * $length) - $position))->ymd; my ($trend, $next) = @{$Q[$quadrant]}; $description = sprintf "%5.1f%% ($trend, next $next $transition)", $percentage; } printf "%-13s %2d: %s", "$label day\n", $position, $description; }