
eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
& eval 'exec perl -S $0 $argv:q'
if 0;

use LWP::Simple qw($ua get);

# If needed, uncomment this line and put the name and port of your
# proxy server here:
# $LWP::Simple::ua->proxy(http => 'http://webcache.ebay:8080');

&init;
mkdir("$SM/Personal",0755) unless (-d "$SM/Personal");
mkdir("$SM/Business",0755) unless (-d "$SM/Business");

### Memo files to generate:
$WEATHER = "$SM/Personal/weather.txt";
$OZONE = "$SM/Personal/airquality.txt";
$MOVIES = "$SM/Personal/movies.txt";
$AMC = "$SM/Personal/amc.txt";
$SUN_STOCK = "$SM/Business/stock_sun.txt";

#
# Weather report
#
if (&OutOfDate($WEATHER, 0.15) && !fork)
{
    my (@new_weather, $new_weather, $mode, $bit, @cols, @vals, $x, $i);
    @new_weather = split(/\n/,
	get 'http://www.wunderground.com/US/CA/Mountain_View.html');
    $mode = 0;

    foreach $line (@new_weather)
    {
	$new_weather .= "$1\n" if ($line =~ /<title>(.*)<\/title>/);
	next unless ($mode || $line =~ /Observed at/);
	unless ($mode) { $mode = 1; next }
	if ($mode <= 2)
	{
	    while ($line =~ s|<td>(.*?)</td>||)
	    {
		$bit = $1;
		$bit =~ s/<.*?>//g;
		$bit =~ s|&#176;||;
		if ($bit =~ /^Moon/) { $mode = 3; last }
		if ($mode==1)
		{
		    $new_weather .= "$bit: ";
		    $mode = 2;
		} else {
		    $new_weather .= "$bit\n";
		    $mode = 1;
		}
	    }
	    next;
	}
	next unless ($mode > 3 || $line =~ /Forecast as of/);
	if ($mode <= 3) { $mode=4; $new_weather .= "\nForecast as of "; next }
	if ($line =~ m|<table.*temperature|i)
	{
	    $mode = 5;
	    $new_weather .= "\n";
	    while ($line =~ s|<th.*?>(.*?)</th>||)
	    {
		($_ = $1) =~ s|<.*?>||g;
		$new_weather .= "  $_\n" if ($_);
	    }
	    next;
	}
	if ($mode == 5)
	{
	    if ($line =~ /<th>/)
	    {
		while ($line =~ s|<th>\s*(.*?)\s*</th>||)
		{
		    ($_ = $1) =~ s|<.*?>||g;
		    push(@cols, $_);
		}
		next;
	    }
	    if ($line =~ m|</table>|)
	    {
		foreach $x (@vals)
		{
		    foreach $i (0..$#$x)
		    {
			$new_weather .= "$cols[$i]: $x->[$i]\n";
		    }
		}
		last;
	    }
	    next unless ($line =~ /Mountain View/ || $line =~ /San Jose/);
	    $x = [];
	    unshift(@vals, $x);
	    while ($line =~ s|<td>\s*(.*?)\s*</td>||)
	    {
		($_ = $1) =~ s|<.*?>||g;
		push(@{$vals[0]}, $_);
	    }
	    next;
	}
	$line =~ tr/a-z/A-Z/ if ($line =~ /^<td align=left/i);
	$line =~ s/<[^>]*>//g;
	next unless ($line);
	if ($line =~ /Extended Forecast/)
	{
	    $line =~ tr/a-z/A-Z/;
	    $new_weather .= "\n";
	}
	$new_weather .= "$line\n";
    }

    &Update($WEATHER, $new_weather);
    exit;
}

#
# Bay Area Air Quality Forecast
#
if (&OutOfDate($OZONE) && !fork)
{
    my (@new_ozone, $new_ozone, @hdr, @dat, $sect, %day, $pf, @zon);
    %day = ('mon','Mon','tue','Tue','wed','Wed','thu','Thu','fri','Fri',
	    'sat','Sat','sun','Sun');
    @new_ozone = split(/\n/, get 'http://www.sparetheair.org/forecast/forecast.htm');

    $new_ozone = "Bay Area Air Quality Forecast\n" if (@new_ozone);
    $sect = 0;
    foreach $line (@new_ozone)
    {
	if ($sect == 0)		# sect 0 = read days
	{
	    push(@hdr, $day{$_})
	      if ($line =~ /\d(...)\.gif/i and $_="\L$1" and exists $day{$_});
	    $sect++ if $line =~ /fcst_map.gif/i;
	}
	else			# sect 1 = read data
	{
	    push(@dat, $1) if $line =~ /numbers\/(\d+)\.gif/i;
	}
    }
    @zon = ('Northern Counties   ', 'Coast & Central Bay ',
	    'Eastern District    ', 'South Central Bay   ',
	    'Santa Clara Valley  ');
    $pf = "%-5s" x scalar(@hdr) . "\n";
    $new_ozone .= "\n                    " . sprintf($pf,@hdr);
    while (@dat)
    {
	@_ = splice(@dat, 0, scalar(@hdr));
	$new_ozone .= shift(@zon) . sprintf($pf,@_);
    }
    $new_ozone .= "\n 0-50 = Good\n50-83 = Moderate\n84-100= Approaching\n" .
		  "   101+ = Unhealthful\n";

    &Update($OZONE, $new_ozone);
    exit;
}

#
# Century Theaters movie listings
#
if (&OutOfDate($MOVIES) && !fork)
{
    my (@new_movies, $new_movies, $go);
    @new_movies = split(/\015\n?/,
			get 'http://www.centurytheaters.com/schedule/nca.htm');

    $new_movies = "Century Theaters\n\n" if (@new_movies);
    foreach $line (@new_movies)
    {
	next if ($line =~ /^\s*$/);
	next unless ($go or $line =~ /A\s+NAME\s*="?anchor(17|03)/i);
	unless ($go) {
	    $line = $1 eq '17' ? 'CENTURY CINEMA' : 'CENTURY 21-25';
	    $go = 1;
	}
	$go=0, next if ($line =~ /A\s+NAME="?anchor/i);

	$line =~ s/<[^>]*>//g;
	$new_movies .= "$line\n";
    }

    &Update($MOVIES, $new_movies);
    exit;
}

#
# AMC Mercado 20 movie listings
#
if (&OutOfDate($AMC) && !fork)
{
    my (@new_amc, $new_amc, $bit);
    @new_amc = split(/<TD[^>]*>/i, get
'http://amctheaters.com/cgi-bin/showtimes.cgi?marketname=San+Jose&theatre=447');

    $new_amc = "AMC Mercado 20\n\n" if (@new_amc);
    $* = 1;
    foreach $line (@new_amc)
    {
	if ($line =~ m|^<A .*>(.*)</A>.*(Rated.*)$|i)
	{
	    $new_amc .= "$1 - ";
	    ($bit = $2) =~ s/<[^>]*>/ /g;  $bit =~ s/\s*$//;
	    $new_amc .= "$bit\n";
	}
	$new_amc .= "  $1 - $2\n"
	    if ($line =~ m|^([^<]*\d\d)<BR>([^<]*)<|i);
    }

    &Update($AMC, $new_amc);
    exit;
}

sub popCSV
{
    return $1 if $_[0] =~ s/^"(([^"]|"")*)"(,|\s*$)//;
    return $1 if $_[0] =~ s/^(.*?)(,|$)//;
    return $1 if $_[0] =~ s/^(.*)$//;
}

#
# Stock quotes
#
sub getQuote
{
    my ($symbol, $title, $stocks_owned, $purchase_price, $fee) = @_;
    my ($new_stock, $data, $price);

    $data = get
      "http://quote.yahoo.com/d/quotes.csv?e=.csv&f=l1nd1t1l1cmovrw&s=$symbol";
    $price = &popCSV($data);

    $new_stock = "$title (" . $price . ")\n\n";
    if ($purchase_price > 0 && $stocks_owned > 0)
    {
	$price = ($price - $purchase_price) * $stocks_owned - $fee;
	$new_stock .= 'Return: ';
	$new_stock .= '+' if ($price >= 0);
	$new_stock .= $price . ' on $' .
			  ($purchase_price * $stocks_owned) . "\n";
    }
    $new_stock .= sprintf "%-20s%s %s\n", &popCSV($data),
			  &popCSV($data), &popCSV($data);
    foreach ('Price', 'Change', 'Range', 'Open',
	     'Volume', 'P/E Ratio', '52wk Range')
    {
	$new_stock .= sprintf "%-20s%s\n", $_, &popCSV($data);
    }

    return $new_stock;
}

# Sun Stock Quote
#
if (&OutOfDate($SUN_STOCK) && !fork)
{
    $line = &getQuote("SUNW", "Sun Stock");
    &Update($SUN_STOCK, $line);
    exit;
}


#
# Does file need to be updated?
#
sub OutOfDate
{
    my ($FILE, $expire) = @_;
    $expire = 0.6 unless ($expire);
    return 1 if (! -f "$FILE" || (-M "$FILE" > $expire));
    return 0;
}

#
# General File update routine
#
sub Update
{
    my ($FILE, $new_text) = @_;
    my ($date, $time, $fname);

    if ($new_text)
    {
	open(FD, ">$FILE") ||
	    print STDERR "Unable to open $FILE for write\n";
	print FD $new_text;
	close(FD);
    } else {
	$date = `date "+%I:%M:%S %p   %a %D"`;
	$fname = $FILE;
	$fname =~ s|^.+(/[^/]+/[^/]+)$|...$1|;
	open(FD, ">>$FILE") ||
	    print STDERR "Unable to open $FILE for append\n";
	print FD "Unable to retrieve $fname at $date";
	close(FD);
	print STDERR "Unable to retrieve/process $fname at $date";
	$time = time - 365*24*60*60;	# set time back so another attempt
	utime($time, $time, $FILE);	# will be made on next update
    }
}

wait;
wait;
wait;
wait;
wait;
exit;

sub init
{
 # cwd should be pilotmgr rcdir (~/.pilotmgr)
 die "Error reading SyncMemo preferences file:\n\
SyncMemo/SyncMemo.prefs\n"
    if (! -f "SyncMemo/SyncMemo.prefs");
 
 eval `cat SyncMemo/SyncMemo.prefs`;
 $PREFS;
 die "No setting for Memo Directory found in SyncMemo preferences.\n"
    unless(defined($PREFS->{gHomeDirectory}));
 
 $SM = $PREFS->{gHomeDirectory};

 die "Memo directory from SyncMemo preferences doesn't exist:\n$SM\n"
    unless(-d $SM);
}

