#!/usr/bin/perl # Filename: simmer_theme # Author: David Ljung Madison # See License: http://MarginalHacks.com/License my $VERSION= '3.12'; # Description: Builds a theme based on: # 1) A group of icons following the same names of Dave Simmer's basic themes # 2) Optional files: Font, CREDIT, Style.css # 3) Optional album minimum version file: requires # # For using Overlay borders, create images: # Over_TL.png Over_T.png Over_TR.png # Over_L.png Over_R.png # Over_BL.png Over_B.png Over_BR.png # # Then figure out how many pixels of the borders are padding (outside photo) # Then put those values in: Over_T.pad Over_R.pad Over_B.pad Over_L.pad # See "Themes/FunLand" for a simple example # # Documentation: Ha! I wish I had time.. See the album "Writing Themes" docs. # # Basically, simmer_theme is perl code that writes themes which are part # perl code that write HTML. So it's code that writes code that writes code. # Yikes! # # CHANGELOG # --------- # # Version 3.12, 2013/05/22 # ------------------------ # + Added support for local album.css stylesheet # + Added span/classes of dirname, dircap, thumbname, thumbcap # # Version 3.11, 2012/01/24 # ------------------------ # + Support for RSS image if found (and using one of the RSS plugins) # + Support for -just_medium (click through) # # Version 3.10, 2008/03/13 # ------------------------ # * Wasn't "undef" the variables for batch runs! Oops! # * Number of images/directories are now translated in all cases # # Version 3.09, 2007/05/01 # ------------------------ # + Converted to XHTML 1.0 Transitional to match album # * Fixed slideshow extra colon bug (:>10 seconds) # # Version 3.08, 2007/01/29 # ------------------------ # * Fixed a slideshow problem # + Better wrapping around prev/next buttons (using float) # # Version 3.07, 2006/12/26 # ------------------------ # + Language support! Ex: Themes/Blues/More.gif vs. Themes/Blue/lang/nl/More.gif # + Nicer alignment of Prev/Next buttons # # Version 3.06, 2006/06/10 # ------------------------ # + Overlay borders! Borders are now easy and can overhang thumbnails! # + Slideshow support! (Using code by Frank Celler, http://www.celler.de/) # + charset support. # # Version 3.05, 2005/12/27 # ------------------------ # + Border gif/jpg/png support # # Version 3.04, 2005/10/24 # ------------------------ # + Better Style.css support # + NotLocked image support # + Better -no_dir_thumbs support # # Version 3.03, 2005/01/20 # ------------------------ # + Started to keep a changelog # + Initial Overlay support # ......Overlay($img,'thumb', 'full', $Overlay) if Get($img,'thumb', 'x') # * Fixed tag HTML problem # # Version 3.02, 2004/??/?? # ------------------------ # + Allow for IBord_* image borders (different from thumbnail borders) # # Version 3.01, 2004/??/?? # ------------------------ # + Added Pretty(), New_Row() code - new API support functions # + New stretchable bar code # # Version 3.00, 2004/07/27 # ------------------------ # + Converted to album v3.0 API, big cleanup # + Added Locked.gif support # # Version 2.01, 2004/05/28? # ------------------------ # + Initial use of album Border API function # + Cleanup with get_img, Image_Array functions # + Renamed Bord_* to ThBord_* # # Version 2.00, 2003/11/17 # ------------------------ # + Made HTML valid (removed , fixed tags, etc..) # # Version 1.16, 2002/10/29 # ------------------------ # + Converted to Theme_URL() (allowing for -theme_url option) # + img_src allows for alt tags now # + Some code cleaning # # Version 1.15, 200?/??/?? # ------------------------ # + First revision control release use strict; use Cwd 'abs_path'; my $PROGNAME = $0; my $THEME_DIRECTORY = "/Themes"; my $CONVERT = "convert"; my ($HEADER,$ALBUM,$IMAGE); # Image size sub get_size { my ($img) = @_; return (0,0) unless (-f $img); print STDERR "get_size() run: $CONVERT -verbose $img /dev/null\n" if ($MAIN::DEBUG); open(SIZE,"$CONVERT -verbose \Q$img\E /dev/null 2>&1 |") || die("[$PROGNAME] Couldn't run convert! [$CONVERT]\n"); while() { print STDERR "get_size(): $_" if ($MAIN::DEBUG); if(/\s(\d+)x(\d+)(\s|\+)/) { close(SIZE); return ($1,$2); } } print STDERR "[$PROGNAME] Can't get [$img] size from 'convert -verbose' output\n"; die("\n"); } my @SET; my $OVER_BORD; # Overlay borders, 8 pieces my @BORD; # Regular borders, 4, 8 or 12 pieces my @IBORD; # Image borders my @OPTIONS; sub find_img { my ($path,$img) = @_; return $img if -f $img; foreach my $post ( qw(gif jpg png) ) { return "$img.$post" if -f "$path/$img.$post"; } $img; } sub img_info { my ($path,$img) = @_; $img = find_img($path,$img); return 0 unless -f "$path/$img"; my ($x,$y) = get_size("$path/$img"); return 0 unless $x && $y; # Use \$PATH instead of $path! ($img, $x, $y); } # Find an image and create an Image_Array of the same name sub get_img { my ($path,$img,$use_x,$use_y) = @_; my ($found,$x,$y) = img_info($path,$img); return (0,0) unless $found; $use_x = $use_x || $x; $use_y = $use_y || $y; my $name = $img; $name =~ s|\.[^\.]+$||; # Use \$PATH instead of $path! push(@SET, " \@$name = (\"\$PATH/$found\", $use_x, $use_y);\n"); return wantarray ? ($x,$y) : (($x&&$y) ? 1 : 0); } # Find an image (and all translation images) and create an Image_Ref sub get_imgs { my ($path,$img) = @_; my @imgs; my ($found,$x,$y) = img_info($path,$img); # Use \$PATH instead of $path! push(@imgs, "\t\t'_' => [\"\$PATH/$found\",$x,$y],\n") if $found; if (opendir(LANG,"$path/lang")) { my @langs = grep(!/^\.{1,2}$/, readdir(LANG)); foreach my $lang ( @langs ) { my ($found,$x,$y) = img_info("$path/lang/$lang",$img); push(@imgs, "\t\t'$lang' => [\"\$PATH/lang/$lang/$found\",$x,$y],\n") if $found; } closedir(LANG); } return unless @imgs; my $name = $img; $name =~ s|\.[^\.]+$||; push(@SET, " \$$name =\t{\n", @imgs, "\t\t};\n") } sub fix_names { my ($path) = @_; sub my_rename { my ($path,$old,$new) = @_; rename("$path/$old","$path/$new") if (-f "$path/$old" && !-f "$path/$new"); } # Icons my_rename($path,"alb_bak.gif","Back.gif"); my_rename($path,"nav.gif", "Back.gif"); my_rename($path,"alb_mor.gif","More.gif"); my_rename($path,"alb_nam.gif","Icon.gif"); my_rename($path,"ico.gif", "Icon.gif"); my_rename($path,"alb_nex.gif","Next.gif"); my_rename($path,"alb_prv.gif","Prev.gif"); # Bar my_rename($path,"bar_lef.gif","Bar_L.gif"); my_rename($path,"bar_mid.gif","Bar_M.gif"); my_rename($path,"bar_rig.gif","Bar_R.gif"); # Thumbnail borders my_rename($path,"th_top.gif","Bord_T.gif"); my_rename($path,"th_tlf.gif","Bord_TL.gif"); my_rename($path,"th_trt.gif","Bord_TR.gif"); my_rename($path,"th_bot.gif","Bord_B.gif"); my_rename($path,"th_blf.gif","Bord_BL.gif"); my_rename($path,"th_brt.gif","Bord_BR.gif"); my_rename($path,"th_lef.gif","Bord_L.gif"); my_rename($path,"th_ltp.gif","Bord_LT.gif"); my_rename($path,"th_lbt.gif","Bord_LB.gif"); my_rename($path,"th_rig.gif","Bord_R.gif"); my_rename($path,"th_rtp.gif","Bord_RT.gif"); my_rename($path,"th_rbt.gif","Bord_RB.gif"); my_rename($path,"ThBord_T.gif", "Bord_T.gif"); my_rename($path,"ThBord_TL.gif","Bord_TL.gif"); my_rename($path,"ThBord_TR.gif","Bord_TR.gif"); my_rename($path,"ThBord_B.gif", "Bord_B.gif"); my_rename($path,"ThBord_BL.gif","Bord_BL.gif"); my_rename($path,"ThBord_BR.gif","Bord_BR.gif"); my_rename($path,"ThBord_L.gif", "Bord_L.gif"); my_rename($path,"ThBord_LT.gif","Bord_LT.gif"); my_rename($path,"ThBord_LB.gif","Bord_LB.gif"); my_rename($path,"ThBord_R.gif", "Bord_R.gif"); my_rename($path,"ThBord_RT.gif","Bord_RT.gif"); my_rename($path,"ThBord_RB.gif","Bord_RB.gif"); my_rename($path,"nul.gif","Null.gif"); my_rename($path,"spacer.gif","Null.gif"); print "Warning: Missing Null.gif\n" unless (-f "$path/Null.gif"); } sub get_file_val { my ($file) = @_; open(F,"<$file") || return 0; while() { if (/([\d\.]+)/) { close F; return $1; } } close F; return 0; } sub get_settings { my ($path) = @_; my $name = abs_path($path); $name =~ s|.*/||; my $req = get_file_val("$path/requires"); if ($req) { push(@SET,<\";\n"); } push(@SET, " \$CSS .= \"\\n\t\t\";\n"); push(@SET, "\n"); if (-f "$path/Style.css") { push(@SET, <<'END_CSS'); $BODY=""; $START_TITLE = ""; $START_MAIN = ""; $START_CREDIT = ""; $END_FONT = ""; END_CSS } elsif (open(FONT,"<$path/Font")) { while () { (/^\s*(#c)?\s*(\/\/)?\s*options?:\s*(\S.*)/i) ? push(@OPTIONS, $_) : push(@SET, $_); } close FONT; push(@SET, "\n"); push(@SET, <<'NOT_CSS'); $START_TITLE = ""; $START_MAIN = ""; $START_CREDIT = ""; $END_FONT = ""; NOT_CSS } else { print "Warning: Missing $path/Font\n"; } push(@SET, "\n \$SLIDESHOW = Option('slideshow');\n"); push(@SET, " # Icons/graphics\n"); my (undef,$bar_H) = get_img($path,"Bar_L"); my ($bar_ML,undef) = get_img($path,"Bar_ML","'100%'"); get_img($path,"Bar_MR","'100%'"); get_img($path,"Bar_M",$bar_ML ? undef : "'100%'"); get_img($path,"Bar_R"); get_img($path,"Locked"); get_img($path,"NotLocked"); get_img($path,"RSS"); #get_img($path,"Null"); # Null is used as a spacer # Currently these are the only graphics that are "translated" get_imgs($path,"Icon"); get_imgs($path,"Back"); get_imgs($path,"Next"); get_imgs($path,"Prev"); get_imgs($path,"More"); push(@SET, <<'END_SET'); sub Bar { my ($colspan) = @_; return unless @Bar_M; :> <: foreach my $bar ( \@Bar_L, \@Bar_ML, \@Bar_M, \@Bar_MR, \@Bar_R ) { next unless @$bar; my $width = $bar->[1] =~ /100%/ ? "" : " width='$bar->[1]'"; print "\t\t\t\t\t\t\t\n"; } :>
"; print Image_Array(@$bar); print "
<: } END_SET # Overlays? if (opendir(D,$path)) { my @over = grep(/^Overlay/, readdir(D)); closedir D; if (@over) { push(@SET,"\n# Overlays\n"); @over = sort @over; foreach my $over ( @over ) { my ($x,$y) = get_size("$path/$over"); next unless $x && $y; push(@SET," push(\@Overlays, [\"\$PATH/$over\", $x, $y]);\n"); } # Random matching overlay code push(@SET,<<'OVERLAY'); # Come up with a 'distance' of ratio/size closeness sub OverlayErr { my ($x,$y,$overlay) = @_; my $ox = $overlay->[1]; my $oy = $overlay->[2]; my $err = abs($x-$ox)/$x; $err += abs($y-$oy)/$y; $err += abs(($x/$y)-($ox/$oy))/($x/$y); $err; } srand(time^$$); sub PickOverlay { my ($img, $type) = @_; my $x = Get($img,$type,'x'); return unless $x; my $y = Get($img,$type,'y'); # Find the lowest error my $besterr = undef; foreach my $overlay ( @Overlays ) { my $err = OverlayErr($x,$y,$overlay); next if defined $besterr && $besterr<$err; $besterr = $err; } # Now find a list of overlays that are close to that error $besterr *= 1.05; # Err or within 5% <- HEURISTIC! my @best = grep { OverlayErr($x,$y,$_) <= $besterr; } @Overlays; # Pick one randomly and apply it Overlay($img,$type,'full', $best[int(rand($#best+1))]); } OVERLAY push(@SET,"\n"); } } # Borders push(@SET, "\n"); push(@SET, " # Thumbnail border\n"); get_img($path,"Bord_LT"); get_img($path,"Bord_RT"); get_img($path,"Bord_LB"); get_img($path,"Bord_RB"); get_img($path,"Bord_L"); get_img($path,"Bord_R"); get_img($path,"Bord_TL"); get_img($path,"Bord_TR"); get_img($path,"Bord_BL"); get_img($path,"Bord_BR"); get_img($path,"Bord_T"); my $bords = get_img($path,"Bord_B"); push(@BORD, "\n".' @Border = (\@Bord_TL,\@Bord_T,\@Bord_TR,\@Bord_RT,\@Bord_R,\@Bord_RB,\@Bord_BR,\@Bord_B,\@Bord_BL,\@Bord_LB,\@Bord_L,\@Bord_LT) unless @Border;'."\n") if $bords; # A better option: Overlay Borders get_img($path,"Over_TL"); $OVER_BORD = get_img($path,"Over_T"); get_img($path,"Over_TR"); get_img($path,"Over_R"); get_img($path,"Over_BR"); get_img($path,"Over_B"); get_img($path,"Over_BL"); get_img($path,"Over_L"); push(@BORD, "\n".' @Border = (\@Over_TL,\@Over_T,\@Over_TR,\@Over_R,\@Over_BR,\@Over_B,\@Over_BL,\@Over_L) unless @Border;'."\n") if $OVER_BORD; # Get pad values if the files exist if ($OVER_BORD) { push(@BORD, "\n # Overlay padding\n"); foreach my $o (qw(T B L R)) { my $pad = "Over_$o"; my $v = get_file_val("$path/$pad.pad"); push(@BORD, " push(\@$pad, $v);\n"); } push(@BORD, "\n"); } # Are image page borders different than thumbnail borders? # (Doesn't work for overlays - generally unnecessary) unless (-f "$path/IBord_T") { @IBORD = @BORD; return; } get_img($path,"IBord_LT"); get_img($path,"IBord_RT"); get_img($path,"IBord_LB"); get_img($path,"IBord_RB"); get_img($path,"IBord_L"); get_img($path,"IBord_R"); get_img($path,"IBord_TL"); get_img($path,"IBord_TR"); get_img($path,"IBord_BL"); get_img($path,"IBord_BR"); get_img($path,"IBord_T"); get_img($path,"IBord_B"); push(@IBORD, "\n".' @Border = (\@IBord_TL,\@IBord_T,\@IBord_TR,\@IBord_RT,\@IBord_R,\@IBord_RB,\@IBord_BR,\@IBord_B,\@IBord_BL,\@IBord_LB,\@IBord_L,\@IBord_LT) unless @Border;'."\n"); } sub can_simmer { #c// -- Auto generated by simmer_theme v$VERSION my ($path) = @_; unless (-f "$path/album.th") { return 1 if -f "$path/Over_T.png"; return 1 if -f "$path/Bord_T.gif"; return 1 if -f "$path/Bord_T.jpg"; return 1 if -f "$path/Bord_T.png"; return 1 if -f "$path/th_top.gif"; return 1 if -f "$path/ThBord_T.gif"; return 0; } open(CHECK,"<$path/album.th") || return 0; my $simmered = grep(/Auto generated by .*simmer_theme/, ) ? 1 : 0; close(CHECK); $simmered; } sub album { my ($path) = @_; open(OUT,">$path/album.th") || die("Couldn't write $path/album.th"); print OUT @OPTIONS; print OUT $HEADER; print OUT @SET; print OUT @BORD; print OUT $ALBUM; close OUT; } sub image { my ($path) = @_; open(OUT,">$path/image.th") || die("Couldn't write $path/image.th"); #print OUT "#c// options: -image_sizes\n" if ($CORNERS); print OUT $HEADER; print OUT @SET; print OUT @IBORD; print OUT $IMAGE; close OUT; } sub main { my @themes = grep(-d $_, @ARGV); die("No theme args?") unless @themes; foreach my $path ( @themes ) { print "Theme: $path"; unless (can_simmer($path)) { print " [album.th is not a simmer_theme - skipping]\n"; next; } print "\n"; fix_names($path); get_settings($path); album($path); image($path); undef @SET; undef $OVER_BORD; undef @BORD; undef @IBORD; undef @OPTIONS; } } $HEADER = < #c// ################################################################### #c// Album Theme by David Ljung Madison #c// Design by Dave Simmer of DaveWeb.com, modified by Dave Madison #c// -- Auto generated by simmer_theme v$VERSION #c// -- From: http://MarginalHacks.com/Hacks/album/ #c// ################################################################### #c// <: END_OF_HEADER $ALBUM = <<'END_OF_ALBUM'; :>// #c// #c// ################################################################### #c// Everything beyond here is the same for every DaveWeb theme.. #c// ################################################################### <: # Shorthand for column info specified by -columns $Dir_Thumbs = Option('dir_thumbs'); $Cols = Option('columns'); $Col_Perc = int(100/$Cols)."%"; :>// <: Meta() :> <:= Trans('Album:') :> <:= Path('album_name') :> <:= $CSS :> <:Body_Tag():>> <: if ($Dir_Thumbs && isHeader()) { _:> <: } _:> <: Bar($Cols) :> #c// Are there more albums below this one? <: my $alb = First('dirs'); if ($alb) { _:> #c// Bar after child albums <: Bar($Cols) :> #c// #c// End if albums <: } :> #c// #c// The images <: my $img = First('pics'); if ($img) { _:>// <: my @save; while ($img) { _:> <: if (New_Row($img,$Cols) || !Next($img)) { _:> <: foreach my $save ( @save ) { _:> <: } undef @save; if (New_Row($img,$Cols)) { _:> <: } } $img = Next($img); } # End child album loop _:> <: Bar($Cols) :> <:}:>// <: if (isFooter()) { _:> <: Bar($Cols) :> <: } _:>
<:=Image_Array("$PATH/Null.gif",11,10):>
<:=$START_TITLE:> <: if ($Icon) { print Image_Ref($Icon,"align='middle'"); print "\n
    \n"; } else { print "".Trans('Album:')."\n"; } _:> <:= Parent_Albums(':'); :> <:=$END_FONT:>
<: $back=Back(); if ($back && $back ne "''" && $back ne "'0'") { print "$START_TITLE"; print ""; print $Back ? Image_Ref($Back,"align='middle'") : Trans('Up'); print "\n"; print "$END_FONT"; } my $rss = Option('extra/rss2.alp:feedFilename') || Option('extra/rss.alp:feedFilename'); print "".Image_Array(@RSS)."\n" if $rss && $RSS[0]; :>

<:=$START_MAIN:> <:pHeader():> <:=$END_FONT:>
<:=Image_Array("$PATH/Null.gif",20,10):>
<: if (!$Dir_Thumbs) { :> <: } :> #c// #c// Loop on all the albums <: my @save; while ($alb) { if ($Dir_Thumbs) { _:> <: if (New_Row($alb,$Cols,$More?1:0) || !Next($alb)) { _:> <: foreach my $save ( @save ) { _:> <:= "\n" unless !$More || Get($save,'num') :> <: } # end foreach $save undef @save; if (New_Row($alb,$Cols,$More?1:0)) { _:> <: } # end new row } # end printing of $save # end if $Dir_Thumbs } else { print Image_Array( (-e Get($alb,'path').'/.htaccess') ? @Locked : @NotLocked); print "\n"; print Get($alb,'href','dir'); print Pretty(Name($alb),1,1), ""; print "\n"; my $cap = Caption($alb); my $num_pics = Get($alb,'num_pics_str'); my $num_dirs = Get($alb,'num_dirs_str'); if ($cap || $num_pics || $num_dirs) { _:>   <:=$cap if $cap:> <:=": " if $cap && ($num_pics || $num_dirs):> <:=$num_dirs:> <:=", " if $num_pics && $num_dirs:> <:=$num_pics:> <: } print "
\n"; } # end not $Dir_Thumbs $alb = Next($alb); } # End child album loop _:> <: if (!$Dir_Thumbs) { :> <:=$END_FONT:> <: } :>//
<:=$START_TITLE:> <:= $More ? Image_Ref($More) : "".Trans('More albums:')."" :>
<:=$END_FONT:> <:=$START_MAIN:> <: } elsif ($More) { :>
<:=Image_Ref($More):> <: PickOverlay($alb, 'thumb') if @Overlays :> <: Border($alb, 'thumb','dir', @Border) if Get($alb,'thumb','x') :> <: push(@save,$alb); :>
<:=$START_MAIN:> <:= Image_Array( (-e Get($save,'path').'/.htaccess') ? @Locked : @NotLocked) :> <:=Get($save,'href','dir'):> <:=Pretty(Name($save),1,1):> <: my $cap = Caption($save); my $num_pics = Get($save,'num_pics_str'); my $num_dirs = Get($save,'num_dirs_str'); if ($cap || $num_pics || $num_dirs) { _:>
<:=$cap if $cap:> <:="
" if $cap && ($num_pics || $num_dirs):> <:=$num_dirs:> <:=", " if $num_pics && $num_dirs:> <:=$num_pics:>
<: } :> <:=$END_FONT:>
<:=$START_MAIN:> <:pHeader():> <:=$END_FONT:>
<: PickOverlay($img, 'thumb') if @Overlays :> <: Border($img,'thumb','image', @Border) if Get($img,'thumb','x') :> <: push(@save,$img); :>
<:=$START_MAIN:> <:=Get($save,'href','image'):> <:=Pretty(Name($save),1,1):> <: if (my $cap = Caption($save)) { _:>
<:=$cap:>
<: } :> <:=$END_FONT:>
<:=Image_Array("$PATH/Null.gif",20,20):>
<:=Image_Array("$PATH/Null.gif",20,20):>

<:pFooter():>
<:=$START_CREDIT:><: Credit() :> on <:=scalar localtime:><:=$END_FONT:>

END_OF_ALBUM $IMAGE = <<'END_OF_IMAGE'; :>// #c// #c// ################################################################### #c// Everything beyond here is the same for every DaveWeb theme.. #c// ################################################################### <: Meta() :> <:=Trans('Image:') :> <:=Name(This_Image) :> <:= $CSS :> <: if ($SLIDESHOW) { :> <: unless ($CSS) { :> <: } :> <: } :> <:Body_Tag():> > <:=Image_Array("$PATH/Null.gif",1,10):> <: if ($SLIDESHOW) { :> <: } :> <: Bar($SLIDESHOW ? 3 : 2) :>
<: if ($Icon) { print Image_Ref($Icon,"align='middle'"); print "\n
\n"; } _:> <:=$START_TITLE:>     <:= Parent_Albums(':'); :> <:=$END_FONT:>

#c// #c// Prev/caption/next #c//
<: if (my $prev = Prev(This_Image, $opt->{image_loop})) { _:>
<:=$START_MAIN:> <:=Get($prev,'href','image_page','image_page'):> <:= $Prev ? "".Image_Ref($Prev)."" : "(".Trans('Prev').") "; :> <:=Pretty(Name($prev),1):> <:=$END_FONT:>
<: } _:>
<:=$START_TITLE:> <:=Get(This_Image,'href','image'):> <:=Pretty(Name(This_Image),1,1):><:=$END_FONT:>
<:=$START_MAIN:> <:=Caption(This_Image):><:=$END_FONT:>
<: if (my $next = Next(This_Image, $opt->{image_loop})) { _:>
<:=$START_MAIN:> <:=Get($next,'href','image_page','image_page'):> <:= "".Image_Ref($Next)."" if $Next :> <:=Pretty(Name($next),1):> <:= " (".Trans('Next').")" unless $Next; :> <:=$END_FONT:>
<: } _:>
#c// #c// The image #c// <: Bar(1) :>

<: PickOverlay(This_Image, 'full') if @Overlays; my $click = Option('just_medium') ? 'next' : 'image'; Border(This_Image,'full',$click, @Border); :>
<:=Image_Array("$PATH/Null.gif",20,20):>
<:=$START_CREDIT:><: Credit() :> on <:=scalar localtime:><:=$END_FONT:>

END_OF_IMAGE main();