Annotation of ConnorCalendar/calendar.pl, revision 1.14

1.10      nick        1: #!/usr/bin/perl -w
1.1       nick        2: 
                      3: =begin comment info
                      4: +------------------------------------------------------------------------------
                      5: |
                      6: | See end of script for comments and 'pod2man $NAME | nroff -man' to
                      7: | view man page or pod2text $NAME for plain text.
                      8: |
                      9: |   Nicholas DeClario <nick@demandred.dyndns.org>
                     10: |   March 2009
1.14    ! nick       11: |      $Id: calendar.pl,v 1.13 2018/10/30 13:53:00 nick Exp $
1.1       nick       12: |
                     13: +------------------------------------------------------------------------------
                     14: =end comment
                     15: =cut
                     16: BEGIN {
                     17:         delete @ENV{ qw(IFS CDPATH ENV BASH_ENV PATH) };
                     18:         $ENV{'PATH'} = "/bin:/usr/bin";
                     19:       }
                     20: 
                     21: use strict;
                     22: use Getopt::Long;
                     23: use Pod::Usage;
                     24: use Data::Dumper;
                     25: use Calendar::Simple;
1.10      nick       26: use Date::Pcalendar::Year qw( :all );
                     27: use Date::Pcalendar::Profiles qw( $Profiles );
1.1       nick       28: 
1.14    ! nick       29: my $VERSION  = '$Id: calendar.pl,v 1.13 2018/10/30 13:53:00 nick Exp $';
1.1       nick       30: my $DEBUG    = "";
1.2       nick       31: my $URL             = "http://demandred.dyndns.org/cgi-bin/ConnorCalendar/index.cgi";
1.1       nick       32: my %post_in  = ( );
                     33: my %opts     = &fetchOptions( );
1.3       nick       34: my @list     = ( );
1.1       nick       35: my @months   = qw/ January February March April May June July 
1.12      nick       36:                    August September October November December /;
1.1       nick       37: my %holidays = ( 
1.7       nick       38:                 "Easter Sunday"        => 'even',
1.1       nick       39:                 "Christmas Day"        => 'even',
                     40:                 "Christmas Eve"        => 'odd',
                     41:                 "Father's Day"         => 'all',
                     42:                 "Independence Day"     => 'even',
                     43:                 "Labor Day"            => 'even',
                     44:                 "Memorial Day"         => 'odd',
1.8       nick       45:                 "New Year's Day"       => 'odd',
                     46:                 "New Year's Eve"       => 'odd',
1.1       nick       47:                 "Thanksgiving Day"     => 'odd', 
1.14    ! nick       48:         );
1.1       nick       49: 
                     50: my %specials = (
                     51:                "11/28"                 => "even",
                     52:                "5/6"                   => "odd",
                     53:                );
1.12      nick       54: 
1.14    ! nick       55: my @school_days = (
        !            56:         "2020/11/27",
        !            57:         "2020/12/24",
        !            58:         "2020/12/25",
        !            59:         "2020/12/28",
        !            60:         "2020/12/29",
        !            61:         "2020/12/30",
        !            62:         "2020/12/31",
        !            63:         "2021/01/01",
        !            64:         "2021/01/18",
        !            65:         "2021/02/15",
        !            66:         "2021/03/29",
        !            67:         "2021/03/30",
        !            68:         "2021/03/31",
        !            69:         "2021/04/01",
        !            70:         "2021/04/02",
        !            71:         "2021/04/05",
        !            72:         "2021/05/31",
        !            73:         "2021/06/01"
        !            74:     );
        !            75: 
1.12      nick       76: print "Content-type: text/html\n\n";
                     77: print &header( );
                     78: 
                     79: 
1.10      nick       80: ## Change this @weekend to 'qw/ 2011 8 12 /' for original schedule
                     81: my @weekend  = qw/ 2011 8 19 /;
1.3       nick       82: my %weekends = &calcWeekends( @weekend );
1.1       nick       83: 
                     84: &ReadParse( );
                     85: 
1.12      nick       86: my $yr =  sprintf( "%d", $post_in{'cy'} || ( localtime )[5] + 1900 );
1.1       nick       87: my $YEAR = sprintf( "%d", $yr );
1.9       nick       88: push @list, 'Easter Sunday' if ( $YEAR % 2 == 0 );
1.1       nick       89: 
1.5       nick       90: print &css( );
1.10      nick       91: my $year_us = Date::Pcalendar::Year->new( $YEAR, $Profiles->{'US-FL'} );
1.1       nick       92: my @hdays = $year_us->labels( );
                     93: 
1.7       nick       94: print "<h1><center><a href=\"$URL?cy=" . ( $YEAR - 1 ) .
                     95:       "\">&lt;--</a> " .
                     96:       "Calendar Days Connor Visits for $YEAR" .
1.10      nick       97:        "<a href=\"$URL?cy=" . ( $YEAR + 1 ) . "\"> --&gt;</a></h1>";
1.1       nick       98: my $row = 0;
1.5       nick       99: print "<table align=center border=0><tr>";
1.1       nick      100: for( my $month = 1; $month <= 12; $month++ )
                    101: {
                    102:        if ( $row >= 3 ) 
                    103:        {
                    104:                $row = 0;
                    105:                print "</tr><tr>";
                    106:        }
                    107:        print "<td align=center valign=top>";
                    108:        print "<b>$months[($month - 1)]</b>\n";
                    109:        print "<pre>Su Mo Tu We Th Fr Sa\n";
                    110:        my @CALS = calendar( $month, $YEAR );
                    111:        foreach my $cal ( @CALS ) 
                    112:        {
                    113:                foreach my $day ( @$cal ) 
                    114:                {
                    115:                        if( defined $day ) 
                    116:                        {
                    117:                                my $h_day = ( $year_us->labels( $YEAR, $month, $day ) )[1];
                    118:                                if( &IHaveConnor( $h_day ) ) {
1.3       nick      119:                                        push @list, $h_day;
1.1       nick      120:                                        print sprintf "<font color=red><b>%2d</b> </font>", $day;
                    121:                                } elsif ( &isSpecial( $YEAR, $month, $day ) || 
                    122:                                          &isWeekend( $YEAR, $month, $day ) ) {
                    123:                                        print sprintf "<font color=green><b>%2d</b> </font>", $day;
                    124:                                } elsif ( &isToday( $YEAR, $month, $day ) ) {
                    125:                                        print sprintf "<font color=blue><b>%2d</b> </font>", $day;
1.14    ! nick      126:                 } elsif ( &isSchoolClosed( $YEAR, $month, $day ) ) {
        !           127:                                        print sprintf "<font color=orange><b>%2d</b> </font>", $day;
1.1       nick      128:                                } else {
                    129:                                        print sprintf "%2d ", $day;
                    130:                                }
                    131:                        } else {
                    132:                                print '   ';
                    133:                        }       
                    134:                }
                    135:                print "\n";
                    136:        }
                    137:        print "</pre></td>";
                    138:        $row++;
                    139: }
                    140: print "</tr></table>";
1.13      nick      141: print "<p class=\"Legend\">Holidays Connor visits are in <font color=red>Red</font>\n</br>";
1.6       nick      142: print "Today is <font color=blue>Blue</font>\n</br>";
1.14    ! nick      143: print "Days off from school are <font color=orange>Orange</font>\n<br><b> Last Day of School 06/23/2021</b>\n</br>\n";
1.13      nick      144: print "Weekends and special days Connor visits are in <font color=green>Green</font>\n</p>";
1.6       nick      145: 
                    146: 
1.7       nick      147: print "<table width=35% align=center border=0><tr><td>List of Special/Holidays " .
1.13      nick      148:       "Connor Visits:<br /><p class=Legend>";
1.7       nick      149: print map { $_ . "<br />\n" } sort @list;
                    150: print "</p></td></tr></table>\n";
1.6       nick      151: print "</pre><p class=\"footer\">Version: <font color=green>$VERSION</font><br />";
                    152: print "CVS: <a target=\"_new\" href=\"http://demandred.dyndns.org/cgi-bin/cvsweb/ConnorCalendar/\">http://demandred.dyndns.org/cgi-bin/cvsweb/ConnorCalendar/</a>";
                    153: print "</center></p>";
1.3       nick      154: 
1.1       nick      155: 
                    156: ###############################################################################
                    157: ###############################################################################
                    158: sub IHaveConnor 
                    159: {
                    160:        my $holiday = shift || return 0;
                    161:        my $y = ( $YEAR % 2 ) ? "odd" : "even";
                    162: 
                    163:        if ( defined $holidays{$holiday} )
                    164:        {
                    165:                return 1 if ( $holidays{$holiday} eq "all" );
                    166:                return 1 if ( $holidays{$holiday} eq $y );
                    167:        }
                    168: 
                    169:        return 0;
                    170: }
                    171: 
                    172: sub isSpecial
                    173: {
1.14    ! nick      174:     my $y = shift || return 0;
        !           175:     my $m = shift || return 0;
        !           176:     my $d = shift || return 0;
1.1       nick      177:        my $yr = ( $YEAR % 2 ) ? "odd" : "even";
                    178: 
                    179:        my $ref = "$m/$d";
                    180:        
                    181:        if ( defined $specials{$ref} )
                    182:        {
1.3       nick      183:                if ( $specials{$ref} eq "all" ||
                    184:                     $specials{$ref} eq $yr ) {
                    185:                        push @list, $ref;
                    186:                        return 1;
                    187:                }
1.1       nick      188:        }
                    189: 
                    190:        return 0;
                    191: }
                    192: 
1.14    ! nick      193: sub isSchoolClosed
        !           194: {
        !           195:     my $y = shift || return 0;
        !           196:     my $m = shift || return 0;
        !           197:     my $d = shift || return 0;
        !           198: 
        !           199:     my $date_str = sprintf( "$y/%02d/%02d", $m, $d );
        !           200: 
        !           201:     foreach my $sd ( @school_days ) {
        !           202:       return 1 if $date_str =~ m/$sd/;
        !           203:     }
        !           204: 
        !           205:     return 0;
        !           206: }
        !           207: 
1.1       nick      208: sub isWeekend
                    209: {
1.3       nick      210:        my $y = shift || return 0;
1.10      nick      211:     my $m = shift || return 0;
                    212:     my $d = shift || return 0;
1.1       nick      213: 
1.3       nick      214:        $m--;
                    215:        my $ds = sprintf( "$y/$months[$m]/%02d", $d );
                    216: 
                    217:        return 1 if ( defined $weekends{$ds} );
                    218: 
1.1       nick      219:        return 0;
                    220: }
                    221: 
                    222: sub isToday
                    223: {
                    224:        my $y = shift || return 0;
                    225:        my $m = shift || return 0;
                    226:        my $d = shift || return 0;
                    227: 
                    228:        return 1 if ( $y eq ( ( localtime )[5] + 1900 ) &&
                    229:             $m eq ( ( localtime )[4] + 1 ) &&
                    230:             $d eq ( ( localtime )[3] ) );
                    231:        return 0;
                    232: }
                    233: 
1.3       nick      234: sub calcWeekends 
                    235: {
                    236:        my $y = shift;
                    237:        my $m = shift;
                    238:        my $d = shift;
                    239:        my %weekends = ( );
                    240: 
1.13      nick      241:        print "Weekends Connor Visits:\n";
1.3       nick      242: 
                    243:        use Calendar;
                    244:        my $date = Calendar->new_from_Gregorian( $m, $d, $y );
                    245:                
                    246:        $weekends{$date->date_string( "%Y/%M/%d" )} = 1;
                    247:        &twoMore( $date );
                    248:        while ( $date->date_string( "%Y" ) <= 2026 ) 
                    249:        {
                    250:                $date += 14;
                    251:                $weekends{$date->date_string( "%Y/%M/%d" )} = 1;
                    252:                &twoMore( $date );
                    253:        }
                    254: 
                    255:        return %weekends;
                    256: 
                    257:        sub twoMore 
                    258:        {
                    259:                my $td = shift;
                    260:                
                    261:                $td++;
                    262:                $weekends{$td->date_string( "%Y/%M/%d" )} = 1;
                    263:                $td++;
                    264:                $weekends{$td->date_string( "%Y/%M/%d" )} = 1;
                    265:        }
                    266: }
                    267: 
1.1       nick      268: ###############################################################################
                    269: ###############################################################################
                    270: sub ReadParse
                    271: {
                    272:         my $a = $_[0] ? $_[0] : \%post_in;
                    273:         my ( $i, $in );
                    274:         my @in = ( );
                    275: 
                    276:         if ( defined $ENV{'SERVER_NAME'} ) {
                    277:                 my $SERVER = $ENV{'SERVER_NAME'};
                    278:         }
                    279: 
                    280:         if ( ( defined $ENV{'REQUEST_METHOD'} ) &&
                    281:              ($ENV{'REQUEST_METHOD'} eq 'POST') )
                    282:         {
                    283:                 read(STDIN, $in, $ENV{'CONTENT_LENGTH'});
                    284:         }
                    285:         else
                    286:         {
                    287:                 $in = $ENV{'QUERY_STRING'} || "";
                    288:         }
                    289: 
                    290:         @in = split(/\&/, $in);
                    291: 
                    292:         foreach $i (@in)
                    293:         {
                    294:                 my ($k, $v) = split(/=/, $i, 2);
                    295:                 $k =~ s/\+/ /g; $k =~ s/%(..)/pack("c",hex($1))/ge;
                    296:                 $v =~ s/\+/ /g; $v =~ s/%(..)/pack("c",hex($1))/ge;
                    297:                 $a->{$k} = defined($a->{$k}) ? $a->{$k}."\0".$v : $v;
                    298:         }
                    299: 
                    300: }
                    301: 
                    302: ###############################################################################
                    303: ##
                    304: ## &fetchOptions( );
                    305: ##
                    306: ##      Grab our command line arguments and toss them in to a hash
                    307: ##
                    308: ###############################################################################
                    309: sub fetchOptions {
                    310:         my %opts;
                    311: 
                    312:         &GetOptions(
                    313:                         "help|?"        => \$opts{'help'},
                    314:                         "man"           => \$opts{'man'},
                    315:                    ) || &pod2usage( );
                    316:         &pod2usage( ) if defined $opts{'help'};
                    317:         &pod2usage( { -verbose => 2, -input => \*DATA } ) if defined $opts{'man'};
                    318: 
                    319:         return %opts;
                    320: }
                    321: 
1.5       nick      322: sub header {
                    323:        return <<EOF;
                    324: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                    325: 
                    326: <html xmlns="http://www.w3.org/1999/xhtml">
                    327: <head>
                    328: <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
                    329:     <title>Calendar Days Connor Visits</title>
                    330:   </head>
                    331: <body bgcolor="#FFFFFF">
                    332: EOF
                    333: }
                    334: 
                    335: sub css {
                    336:        return <<EOF;
                    337: <style type="text/css">
                    338: body {
                    339: 
                    340: padding-top: 0px;
                    341: padding-left: 0px;
                    342: padding-right: 0px;
                    343: padding-bottom: 0px;
                    344: 
                    345:  text-align:left;
                    346:  margin:0;
                    347:  font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, sans-serif;
                    348:  #font-family: Geneva, Arial, Helvetica, sans-serif;
                    349:  font-size: 12pt;
1.7       nick      350:  background: #eeeeee;
1.5       nick      351:  color:#000000;
                    352: 
                    353: 
                    354: }
                    355: 
                    356: .name { 
                    357:  color: #191970; 
                    358:  font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, sans-serif;
                    359:  #font-family: Verdana, Arial, sans-serif;
                    360:  font-size: 18pt; font-weight: bold; line-height: 38pt;
                    361:  text-align: center;
                    362: }
                    363: 
1.6       nick      364: p.Legend {
                    365:  color: #000000;
                    366:  font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, sans-serif;
                    367:  font-size: 8pt;
                    368:  margin: auto;
1.7       nick      369:  width: 300px;
1.6       nick      370:  background-color : transparent;
                    371:  border-top: 1px solid #888888;
                    372:  border-left: 1px solid #888888;
                    373:  border-right: 1px solid #888888;
                    374:  border-bottom: 1px solid #888888;
                    375:  padding-top: 3px;
                    376:  padding-bottom: 3px;
                    377:  padding-left: 3px;
                    378:  padding-right: 3px;
                    379: }
                    380: 
1.5       nick      381: h1 { 
                    382:  color: #191970; 
                    383:  font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, sans-serif;
                    384:  #font-family: Verdana, Arial, sans-serif;
                    385:  font-size: 12pt; font-weight: bold; line-height: 15pt;
1.6       nick      386:  background-color : transparent;
                    387:  margin-left: 20px;
                    388:  margin-right: 20px;
                    389:  border-top: 1px solid black;
                    390:  border-bottom: 1px solid black;
1.5       nick      391: }
                    392: 
                    393: 
                    394: h2 {
                    395:  color: #191970; 
                    396:  font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, sans-serif;
                    397:         font-weight: bold;
                    398:         font-size: 18px;
                    399: }
                    400:         
                    401: h3 {
                    402:  color: #191970; 
                    403:  font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, sans-serif;
                    404:         font-weight: bold;
                    405:         font-size: 14px;
                    406: }
                    407: 
                    408: 
                    409: textarea { width:100%; }
                    410: 
                    411: .gallery {
                    412: padding-top: 80px;
                    413: padding-left: 60px;
                    414: padding-right: 50px;
                    415: line-height: 120%;
                    416: background:url('topleft.jpg') no-repeat top left;
                    417: }
                    418: .browse {
                    419: padding-top: 80px;
                    420: padding-left: 60px;
                    421: padding-right: 50px;
                    422: line-height: 120%;
                    423: background:url(topleft.jpg) no-repeat top left;
                    424: }
                    425: .content, .rc {
                    426: padding-top: 100px;
                    427: padding-left: 80px;
                    428: padding-right: 50px;
                    429: line-height: 120%;
                    430: }
                    431: 
                    432: 
1.6       nick      433: p.footer {
                    434:  color: #000000;
                    435:  font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, sans-serif;
                    436:  font-size: 8pt;
                    437:  margin: auto;
1.7       nick      438:  width: 500px;
1.6       nick      439:  background-color : transparent;
                    440:  border-top: 1px solid #888888;
                    441:  padding-top: 3px;
                    442:  padding-bottom: 3px;
                    443:  padding-left: 3px;
                    444:  padding-right: 3px;
                    445:  text-align: center;
1.5       nick      446: }
                    447: 
                    448: 
                    449: .header {
                    450: float: right;
                    451: margin-top: 30px;
                    452: margin-right: 50px;
                    453: padding: 10px;
                    454: padding-top: 10px,10px,10px,10px;
                    455: 
                    456: }
                    457: pre {
                    458:     border: #777777 1px dashed;
                    459:     padding: 0.5em;
                    460:     margin-left: 1em;
                    461:     margin-right: 2em;
                    462:     white-space: pre;
                    463:     background-color: #fbfdff;
                    464:     color: black;
                    465:     font-size:12px;
                    466: }
                    467: 
                    468: .refer {
                    469:        padding-left: 60px;
                    470:        padding-right: 50px;
                    471:        margin-right: 50px;
                    472:        margin-left: 50px;
                    473:        font-size:80%;
                    474: }
                    475: 
                    476: .gotobar {
                    477:        color: #191970; 
                    478:        font-size:10px;
                    479: }
                    480: 
                    481: .edit bar {
                    482:        color: #949ce5; 
                    483: }
                    484: 
                    485: .contactInfo {
                    486:        font-size:12px;
                    487:        text-align:center;
                    488: }
                    489: 
                    490: .workHeader {
                    491:        text-align:left;
                    492:        font-size:13px;
                    493:        text-decoration:none;
                    494:        font-weight:normal;
                    495: }
                    496: 
                    497: .workHeaderDate {
                    498:        float: right;
                    499: }
                    500: 
                    501: .workHeaderStrong {
                    502:        font-size:15px;
                    503:        text-decoration:none;
                    504:        font-weight:bolder;
                    505: }
                    506: 
                    507: .jobDescription {
                    508:        padding-top:15px;
                    509:        font-size:13px;
                    510: }
                    511: 
                    512: .bulletContent {
                    513:        font-size:13px;
                    514: }
                    515: 
                    516: .leftCol {
                    517:        width:10.2em;
                    518:        position:absolute;
                    519:        top:0;
                    520:        font-size:13px;
                    521:        padding-left:1%;
                    522:        padding-right:1%;
                    523: }
                    524: 
                    525: .rightCol {
                    526:        width:10.2em;
                    527:        position:absolute;
                    528:        top:0;
                    529:        font-size:13px;
                    530:        padding-left:1%;
                    531:        padding-right:1%;
                    532: }
                    533: 
                    534: a:link {color:#082e58;  text-decoration: none; font-weight:bolder;}
                    535: a:visited {color:#7795b7; font-weight:normal; text-decoration:none;}
                    536: a:hover {color:#949ce5;}
                    537: 
                    538: 
                    539: a.definition:before { content:"[::"; }
                    540: a.definition:after { content:"]"; }
                    541: a.alias { text-decoration:none; border-bottom: thin dashed; }
                    542: a.near:link { color:#093; }
                    543: a.near:visited { color:#550; }
                    544: a.upload:before { content:"<"; }
                    545: a.upload:after { content:">"; }
                    546: a.outside:before { content:"["; }
                    547: a.outside:after { content:"]"; }
                    548: img.logo { float: right; clear: right; border-style:none; }
                    549: div.diff { padding-left:5%; padding-right:5%; }
                    550: div.old { background-color:#FFFFAF; }
                    551: div.new { background-color:#CFFFCF; }
                    552: div.message { background-color:#FEE; }
                    553: div.journal h1 { font-size:large; }
                    554: table.history { border-style:none; }
                    555: td.history { border-style:none; }
                    556: span.result { font-size:larger; }
                    557: span.info { font-size:smaller; font-style:italic; }
                    558: div.rss { background-color:#EEF; }
                    559: div.sister { float:left; margin-right:1ex; background-color:#FFF; }
                    560: div.sister p { margin-top:0; }
                    561: div.sister img { border:none; }
                    562: div.near { background-color:#EFE; }
                    563: div.near p { margin-top:0; }
                    564: </style>
                    565: EOF
                    566: 
                    567: }
                    568: 
1.1       nick      569: __END__
                    570: 
                    571: =head1 NAME
                    572: 
                    573: masterbuild.pl - blurb
                    574: 
                    575: =head1 SYNOPSIS
                    576: 
                    577: masterbuild.pl [options]
                    578: 
                    579:  Options:
                    580:         --help,?        Display the basic help menu
                    581:         --man,m         Display the detailed man page
                    582: 
                    583: =head1 DESCRIPTION
                    584: 
                    585: =head1 HISTORY
                    586: 
                    587: =head1 AUTHOR
                    588: 
                    589: Nicholas DeClario <nick@declario.com>
                    590: 
                    591: =head1 BUGS
                    592: 
                    593: This is a work in progress.  Please report all bugs to the author.
                    594: 
                    595: =head1 SEE ALSO
                    596: 
                    597: =head1 COPYRIGHT
                    598: 
                    599: =cut

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>