]> www.fi.muni.cz Git - aoc.git/commitdiff
New fancy infrastructure: downloader, inotify watcher, submitter
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Fri, 16 Dec 2022 20:09:03 +0000 (21:09 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Fri, 16 Dec 2022 20:09:03 +0000 (21:09 +0100)
2022/get [new file with mode: 0755]
2022/run [new file with mode: 0755]
bashrc [new file with mode: 0644]
lib/Y/AoC.pm [new file with mode: 0644]
lib/Y/AoC/Task.pm [new file with mode: 0644]
lib/Y/AoC/UA.pm [new file with mode: 0644]

diff --git a/2022/get b/2022/get
new file mode 100755 (executable)
index 0000000..760e024
--- /dev/null
+++ b/2022/get
@@ -0,0 +1,63 @@
+#!/usr/bin/perl -w
+
+use v5.36;
+use strict;
+
+use Y::AoC qw(grey);
+use Y::AoC::UA;
+
+use Mojo::UserAgent -signatures;
+use Mojo::Util qw(getopt);
+use Time::ParseDate;
+
+my $start = '6:00:02';
+
+getopt
+       'd|day=i'  => \my $day,
+       'y|year=i' => \my $year;
+
+$year //= Y::AoC::year;
+my $sleep;
+
+if (!$day) {
+       my $now = time;
+       my @now = localtime($now);
+       if ($now[4] == 11 && $now[2] >= 5 && $now[2] < 7) {
+               $day = $now[3];
+               if ($now[2] == 5 && $now[1] >= 50) {
+                       my $then = parsedate($start);
+                       $sleep = $then - $now;
+               }
+       }
+}
+
+die "Use -d day command-line switch.\n"
+       if !$day;
+
+my $task = 2*$day-1;
+my $url = "https://adventofcode.com/$year/day/$day/input";
+my $dest = $task.'in.txt';
+
+if ($sleep) {
+       say "Sleeping for $sleep s till $start before downloading\n",
+               "$url to $dest";
+       sleep $sleep;
+}
+say "Downloading $url to $dest";
+
+my $data = Y::AoC::UA::request($url, { body => 1 });
+Mojo::File->new($dest)->spurt($data);
+say grey('==================================================');
+print $data;
+say grey('==================================================');
+
+say "lines words chars";
+system 'wc', $dest;
+
+$url =~ s/\/input\z//;
+$dest = $task.'test.txt';
+
+my $tst = Y::AoC::UA::request($url, { cache_to => "task-$year-$day.html" })
+       ->find('main > article > pre > code')->first->all_text;
+Mojo::File->new($dest)->spurt($tst);
+say "\n", grey("also downloaded $dest"), "\n";
diff --git a/2022/run b/2022/run
new file mode 100755 (executable)
index 0000000..40a45a6
--- /dev/null
+++ b/2022/run
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+
+use v5.36;
+use warnings;
+use strict;
+
+use Time::HiRes qw(sleep);
+use Linux::Inotify2;
+use POSIX qw(strftime);
+use Mojo::File;
+
+use Y::AoC qw(grey red);
+
+my $cmd = shift;
+my $backup = "backup/$cmd";
+$cmd = "./$cmd" if $cmd !~ /\//;
+
+my $last_backup;
+while (1) {
+       my $b = "$backup-".strftime("%H-%M-%S", localtime(time));
+       system 'cp', $cmd, $b;
+       say grey("\nrunning $cmd @ARGV... ============================");
+       system $cmd, @ARGV;
+       if ($?) {
+               say grey("FAILED: $?");
+       } else {
+               say grey("finished OK");
+       }
+
+       my $inotify = Linux::Inotify2->new;
+       $inotify->watch($cmd, IN_MODIFY);
+       say grey("\nWaiting for modification of $cmd ...");
+       $inotify->read;
+       sleep 0.1;
+}
diff --git a/bashrc b/bashrc
new file mode 100644 (file)
index 0000000..bca07d4
--- /dev/null
+++ b/bashrc
@@ -0,0 +1,3 @@
+export PERL5LIB="/home/kas/aoc/lib:$PERL5LIB"
+export PS1="AoC\$ "
+ulimit -v 35500000
diff --git a/lib/Y/AoC.pm b/lib/Y/AoC.pm
new file mode 100644 (file)
index 0000000..8fbb606
--- /dev/null
@@ -0,0 +1,26 @@
+package Y::AoC;
+
+use v5.36;
+
+use Exporter qw(import);
+our @EXPORT_OK = qw(red grey white yellow day year);
+
+use FindBin qw($Bin);
+use Term::ANSIColor;
+
+sub red    { colored(['bright_red    on_black'], @_); }
+sub white  { colored(['bright_white  on_black'], @_); }
+sub grey   { colored(['white         on_black'], @_); }
+sub yellow { colored(['bright_yellow on_black'], @_); }
+
+sub day {
+       my ($num) = $0 =~ /.*\D(\d+)/;
+       int ((1+$num)/2);
+}
+
+sub year {
+       my ($num) = $Bin =~ /.*(\d{4})/;
+       $num;
+}
+
+1;
diff --git a/lib/Y/AoC/Task.pm b/lib/Y/AoC/Task.pm
new file mode 100644 (file)
index 0000000..bab6d93
--- /dev/null
@@ -0,0 +1,102 @@
+package Y::AoC::Task;
+
+use v5.36;
+
+use Exporter ('import');
+our @EXPORT = qw(t asay bsay);
+use Y::AoC qw(red white grey yellow day year);
+
+our $printed_err;
+$SIG{__DIE__} = sub($msg) {
+       $msg =~ s/\A(.*?)( at \S+ )(line \d+)/red($1).$2.white($3)/e
+               if -t STDERR && !$printed_err++;
+       say STDERR $msg;
+       die "\n";
+};
+
+$SIG{__WARN__} = sub($msg) {
+       $msg =~ s/\A(.*?)( at \S+ )(line \d+)/red($1).$2.white($3)/e
+               if -t STDERR && !$printed_err++;
+       say STDERR $msg;
+};
+
+our $in_test;
+sub t($subtest = ()) {
+       $subtest //= '';
+       $ARGV[0] =~ s/in\.txt/test$subtest.txt/;
+       $in_test = 1;
+}
+
+sub asay(@msg) {
+       try_submit(1, @msg);
+}
+
+sub bsay(@msg) {
+       try_submit(2, @msg);
+}
+
+sub try_submit($part, @msg) {
+       my $msg = join($, // '', @msg);
+       my $ans;
+       $msg =~ s/(\w+)\z/white($ans = $1)/e;
+
+       say $msg;
+
+       return if $in_test;
+
+       my $day = day;
+       my $year = year;
+
+       my $url = "https://adventofcode.com/$year/day/$day/answer";
+       my $cachefile = "ans-$year-$day-$part-$ans.html";
+       local $| = 1;
+       print "\nSubmit $url\nlevel=", white($part), ' answer=',
+               white($ans), ' ? [Enter]/[Ctrl-C]: ';
+       
+       scalar <STDIN>;
+       eval '{
+               local $SIG{__DIE__};
+               require Y::AoC::UA;
+       }';
+       my $res = Y::AoC::UA::request($url, {
+               form => {
+                       answer => $ans,
+                       level  => $part,
+               },
+               cache_to => $cachefile,
+       });
+
+       my $art = $res->find('main > article > p')->join("\n");
+       if (!$art) {
+               say $res->to_string;
+               return;
+       }
+
+       $art =~ s/&#39;/'/g;
+       $art =~ s/(?<=That's )not(?= the right answer)/red($&)/e;
+       my $ok = $art =~ s/(?<=That's the )(right answer)/yellow($&)/e;
+       $art =~ s/(gold stars?)/yellow($&)/e;
+       $art =~ s/(silver star)/grey($&)/e;
+       Y::AoC::UA::cache_del($cachefile)
+               if $msg =~ s/(?<=Please wait ).*?(?= before trying again)/white($&)/e;
+       $art =~ s/(?<=your answer is )([^\.;]+)/red($&)/e;
+       $art =~ s/<code>([^<]+)<\/code>/white($1)/e;
+       $art =~ s/<[^>]+>//g;
+
+       if ($ok) {
+               system "cp $0 backup/$0-ok-$ans-$part";
+       }
+
+       say $art;
+}
+
+1;
+__END__
+package Y::AoC::UA;
+
+sub new($class, $year, $day) {
+       eval 'require
+}
+
+sub get($ua) {
+1;
diff --git a/lib/Y/AoC/UA.pm b/lib/Y/AoC/UA.pm
new file mode 100644 (file)
index 0000000..ecee1b0
--- /dev/null
@@ -0,0 +1,79 @@
+package Y::AoC::UA;
+
+use v5.36;
+
+use Mojo::Base -signatures;
+use Mojo::UserAgent;
+use Mojo::DOM;
+use Y::AoC qw(white);
+
+our $user_agent = 'kas@yenya.net https://www.fi.muni.cz/~kas/git/aoc.git';
+our $cache_dir = '/home/kas/aoc/cache';
+our $cookie;
+
+sub request($url, $args) {
+       chomp($cookie //= Mojo::File->new("$cache_dir/cookie")->slurp);
+
+       my ($cache, $cachefile);
+       if ($args->{cache_to}) {
+               $cachefile = $cache_dir . '/' . $args->{cache_to};
+               $cache = Mojo::File->new("$cachefile");
+
+               if ($args->{max_age}) { 
+                       $cache->remove
+                               if $cache->stat
+                               && time - $cache->stat->mtime
+                                       > $args->{max_age};
+               }
+
+               if ($cache->stat) {
+                       say "\n", white('cached'),
+                               " response from $cachefile";
+                       return Mojo::DOM->new($cache->slurp);
+               }
+       }
+
+       my $res;
+       my %hdrs = (
+               Cookie       => $cookie,
+               'User-Agent' => $user_agent,
+       );
+       my $ua = Mojo::UserAgent->new;
+       if ($args->{form}) {
+               $res = $ua->post($url => \%hdrs => form => $args->{form})
+                       ->result;
+       } else {
+               $res = $ua->get($url => \%hdrs)->result;
+       }
+
+       if (!$res->is_success) {
+               say $res->message;
+               say "body:\n",  $res->body;
+               die red("http request failed");
+       }
+
+       if ($cache) {
+               $cache->spurt($res->body);
+               # say "Stored response to $cachefile";
+       }
+       return $args->{body} ? $res->body : $res->dom;
+}
+
+sub cache_del($file) {
+       my $f = Mojo::File->new("$cache_dir/$file");
+       return if !$f->stat;
+       $f->move_to("$cache_dir/old-$file");
+}
+
+sub is_cached($file) { Mojo::File->new("$cache_dir/$file")->stat; }
+
+1;
+__END__
+package Y::AoC::UA;
+
+sub new($class, $year, $day) {
+       eval 'require
+}
+
+sub get($ua) {
+1;