From 21d3b67237a8e1824bdcf130c84afca6f323c644 Mon Sep 17 00:00:00 2001
From: Andinus <andinus@nand.sh>
Date: Wed, 17 Nov 2021 18:49:36 +0530
Subject: Remove output option, rename frame-rate option to fps

---
 lib/Fornax/CLI.rakumod | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'lib')

diff --git a/lib/Fornax/CLI.rakumod b/lib/Fornax/CLI.rakumod
index 35109b7..32303fc 100644
--- a/lib/Fornax/CLI.rakumod
+++ b/lib/Fornax/CLI.rakumod
@@ -15,14 +15,14 @@ proto MAIN(|) is export { unless so @*ARGS { put $*USAGE; exit }; {*} }
 #| Collection of tools to visualize Path Finding Algorithms
 multi sub MAIN(
     File $input, #= fornax format file (solved)
-    IO() :$out = '/tmp', #= output directory (default: /tmp)
-    Int() :$batch = 4, #= batch size (generate frames in parallel)
-    Rat() :$frame-rate = 1, #= frame rate (default: 1)
+
+    Int() :$batch = 4, #= number of iterations to process at once (default: 4)
+    Int() :$fps = 1, #= frame rate for video solution (default: 1)
     Bool :$skip-video, #= skip video solution
-    Bool :$verbose = True, #= verbosity
+    Bool :$verbose = True, #= verbosity (default: True)
 ) is export {
     my IO() $output = "%s/fornax-%s".sprintf(
-        $out.absolute, ('a'...'z', 'A'...'Z', 0...9).roll(8).join
+        '/tmp', ('a'...'z', 'A'...'Z', 0...9).roll(8).join
     );
     mkdir $output;
     die "Output directory doesn't exist" unless $output.d;
@@ -166,7 +166,7 @@ multi sub MAIN(
         put "[fornax] Creating a slideshow." if $verbose;
 
         my Str $log-level = $verbose ?? "info" !! "error";
-        run «ffmpeg -loglevel "$log-level" -r "$frame-rate" -i "$output/\%08d.png"
+        run «ffmpeg -loglevel "$log-level" -r "$fps" -i "$output/\%08d.png"
                     -vf 'tpad=stop_mode=clone:stop_duration=4'
                     -vcodec libx264 -crf 28 -pix_fmt yuv420p "$output/solution.mp4"»;
     }
-- 
cgit 1.4.1-2-gfad0


From 22aa1c9b322c424724516d70b77d1d5b93155697 Mon Sep 17 00:00:00 2001
From: Andinus <andinus@nand.sh>
Date: Wed, 17 Nov 2021 18:50:25 +0530
Subject: Alias frame-rate to fps

Preserves backwards compatibility.
---
 lib/Fornax/CLI.rakumod | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'lib')

diff --git a/lib/Fornax/CLI.rakumod b/lib/Fornax/CLI.rakumod
index 32303fc..8b18215 100644
--- a/lib/Fornax/CLI.rakumod
+++ b/lib/Fornax/CLI.rakumod
@@ -17,7 +17,7 @@ multi sub MAIN(
     File $input, #= fornax format file (solved)
 
     Int() :$batch = 4, #= number of iterations to process at once (default: 4)
-    Int() :$fps = 1, #= frame rate for video solution (default: 1)
+    Int() :fps($frame-rate) = 1, #= frame rate for video solution (default: 1)
     Bool :$skip-video, #= skip video solution
     Bool :$verbose = True, #= verbosity (default: True)
 ) is export {
@@ -166,7 +166,7 @@ multi sub MAIN(
         put "[fornax] Creating a slideshow." if $verbose;
 
         my Str $log-level = $verbose ?? "info" !! "error";
-        run «ffmpeg -loglevel "$log-level" -r "$fps" -i "$output/\%08d.png"
+        run «ffmpeg -loglevel "$log-level" -r "$frame-rate" -i "$output/\%08d.png"
                     -vf 'tpad=stop_mode=clone:stop_duration=4'
                     -vcodec libx264 -crf 28 -pix_fmt yuv420p "$output/solution.mp4"»;
     }
-- 
cgit 1.4.1-2-gfad0


From eb96ab962545cf9b403f18422f1de698d9619499 Mon Sep 17 00:00:00 2001
From: Andinus <andinus@nand.sh>
Date: Thu, 18 Nov 2021 16:56:58 +0530
Subject: Move frame generation to a module, update progress reporting

---
 lib/Fornax/CLI.rakumod           | 123 ++++++++-------------------------------
 lib/Fornax/GenerateFrame.rakumod | 100 +++++++++++++++++++++++++++++++
 2 files changed, 123 insertions(+), 100 deletions(-)
 create mode 100644 lib/Fornax/GenerateFrame.rakumod

(limited to 'lib')

diff --git a/lib/Fornax/CLI.rakumod b/lib/Fornax/CLI.rakumod
index 8b18215..d066ebf 100644
--- a/lib/Fornax/CLI.rakumod
+++ b/lib/Fornax/CLI.rakumod
@@ -1,5 +1,4 @@
-use Cairo;
-use Fornax::Hex2RGB;
+use Fornax::GenerateFrame;
 
 subset File of Str where *.IO.f;
 
@@ -19,7 +18,7 @@ multi sub MAIN(
     Int() :$batch = 4, #= number of iterations to process at once (default: 4)
     Int() :fps($frame-rate) = 1, #= frame rate for video solution (default: 1)
     Bool :$skip-video, #= skip video solution
-    Bool :$verbose = True, #= verbosity (default: True)
+    Bool :$debug, #= debug logs
 ) is export {
     my IO() $output = "%s/fornax-%s".sprintf(
         '/tmp', ('a'...'z', 'A'...'Z', 0...9).roll(8).join
@@ -27,40 +26,14 @@ multi sub MAIN(
     mkdir $output;
     die "Output directory doesn't exist" unless $output.d;
 
-    put "[fornax] Output: '$output'" if $verbose;
+    put "[fornax] Output: '$output'";
 
     my Str @lines = $input.IO.lines;
     my Int() %meta{Str} = Metadata.parse(@lines.first).Hash
-                             or die "Cannot parse metadata";
-
-    # Cells as defined by fornax format.
-    constant $PATH = '.';
-    constant $BLOK = '#';
-    constant $DEST = '$';
-    constant $STRT = '^';
-    constant $VIS = '-';
-    constant $CUR = '@';
-    constant $CURPATH = '~';
+                                  or die "Cannot parse metadata";
 
     constant %CANVAS = :1920width, :1080height;
 
-    # Colors.
-    constant %C = (
-        bg-main => "#ffffff",
-
-        red-subtle-bg => "#f2b0a2",
-        blue-subtle-bg => "#b5d0ff",
-        cyan-subtle-bg => "#c0efff",
-        green-subtle-bg => "#aecf90",
-
-        fg-main => "#000000",
-
-        fg-special-cold => "#093060",
-        fg-special-warm => "#5d3026",
-        fg-special-mild => "#184034",
-        fg-special-calm => "#61284f",
-    ).map: {.key => hex2rgb(.value)};
-
     # Every cell must be square. Get the maximum width, height and use
     # that to decide which is to be used.
     my Int %cell = width => %CANVAS<width> div %meta<cols>,
@@ -79,7 +52,8 @@ multi sub MAIN(
         $side = %cell<height>;
     }
 
-    enum IterStatus <Walking Blocked Completed>;
+    my $render-start = now;
+    my Int $total-frames = @lines.elems - 1;
 
     my Promise @p;
     for @lines.skip.kv -> $idx, $iter is rw {
@@ -88,89 +62,38 @@ multi sub MAIN(
         if @p.elems == $batch {
             await @p;
             @p = [];
+
+            print "\r";
+            print "%s  Remaining: %.2fs  Elapsed: %.2fs %s".sprintf(
+                "[fornax $idx/$total-frames]",
+                ((now - $render-start) / $idx) * ($total-frames - $idx),
+                now - $render-start, "        ",
+            );
         }
 
         push @p, start {
-            my IterStatus $status;
-            given $iter.substr(0, 1) {
-                when '|' { $status = Completed }
-                when '!' { $status = Blocked }
-                default { $status = Walking }
-            };
-
-            # Remove marker.
-            $iter .= substr(1) if $status == Completed|Blocked;
-
-            put "[fornax] $idx $iter $status" if $verbose;
-
-            my @grid = $iter.comb.rotor: %meta<cols>;
-            warn "Invalid grid: $idx $iter $status" unless @grid.elems == %meta<rows>;
-
-            given Cairo::Image.create(
-                Cairo::FORMAT_ARGB32, %CANVAS<width>, %CANVAS<height>
-            ) {
-                given Cairo::Context.new($_) {
-                    # Paint the entire canvas white.
-                    .rgb: |%C<bg-main>;
-                    .rectangle(0, 0, %CANVAS<width>, %CANVAS<height>);
-                    .fill;
-
-                    for ^%meta<rows> -> $r {
-                        for ^%meta<cols> -> $c {
-                            my Int @target = %excess<width> div 2 + $c * $side,
-                                             %excess<height> div 2 + $r * $side,
-                                             $side, $side;
-
-                            .rectangle: |@target;
-
-                            given @grid[$r][$c] -> $cell {
-                                # According to the format, current
-                                # position may be prioritized over
-                                # Destination symbol so we colorize it
-                                # according to $status.
-                                when $cell eq $CUR {
-                                    .rgba: |%C<fg-special-cold>, 0.56;
-                                    .rgba: |%C<fg-special-mild>, 0.72 if $status == Completed;
-                                    .rgba: |%C<fg-special-warm>, 0.72 if $status == Blocked;
-                                }
-                                when $cell eq $CURPATH {
-                                    .rgba: |%C<blue-subtle-bg>, 0.84;
-                                    .rgba: |%C<green-subtle-bg>, 0.96 if $status == Completed;
-                                    .rgba: |%C<red-subtle-bg>, 0.96 if $status == Blocked;
-                                }
-                                when $cell eq $VIS {
-                                    .rgba: |%C<cyan-subtle-bg>, 0.72;
-                                }
-                                when $cell eq $BLOK { .rgba: |%C<fg-main>, 0.56 }
-                                when $cell eq $STRT|$DEST { .rgba: |%C<fg-special-mild>, 0.72 }
-                                default { .rgba: |%C<fg-main>, 0.08 }
-                            }
-                            .fill :preserve;
-
-                            .rgb: |%C<fg-main>;
-                            .stroke;
-                        }
-                    }
-                }
-                .write_png("%s/%08d.png".sprintf: $output, $idx);
-                .finish;
-            }
+            generate-frame(
+                :%CANVAS, :%excess, :$side, :%meta, :$iter, :$idx, :$debug,
+                :out("%s/%08d.png".sprintf: $output, $idx),
+            );
         }
     }
     # Wait for remaining jobs to finish.
     await @p;
 
-    put "[fornax] Generated images." if $verbose;
+    print "\r";
+    put "[fornax] Generated $total-frames frames in %.2fs. %s".sprintf(
+        now - $render-start, " " x 16,
+    );
 
     unless $skip-video {
-        put "[fornax] Creating a slideshow." if $verbose;
+        put "[fornax] Creating a slideshow.";
 
-        my Str $log-level = $verbose ?? "info" !! "error";
+        my Str $log-level = $debug ?? "info" !! "error";
         run «ffmpeg -loglevel "$log-level" -r "$frame-rate" -i "$output/\%08d.png"
                     -vf 'tpad=stop_mode=clone:stop_duration=4'
                     -vcodec libx264 -crf 28 -pix_fmt yuv420p "$output/solution.mp4"»;
     }
-    put "[fornax] Output: '$output'";
 }
 
 multi sub MAIN(
diff --git a/lib/Fornax/GenerateFrame.rakumod b/lib/Fornax/GenerateFrame.rakumod
new file mode 100644
index 0000000..e19d342
--- /dev/null
+++ b/lib/Fornax/GenerateFrame.rakumod
@@ -0,0 +1,100 @@
+use Cairo;
+use Fornax::Hex2RGB;
+
+# Cells as defined by fornax format.
+constant $PATH = '.';
+constant $BLOK = '#';
+constant $DEST = '$';
+constant $STRT = '^';
+constant $VIS = '-';
+constant $CUR = '@';
+constant $CURPATH = '~';
+
+# Colors.
+constant %C = (
+    bg-main => "#ffffff",
+
+    red-subtle-bg => "#f2b0a2",
+    blue-subtle-bg => "#b5d0ff",
+    cyan-subtle-bg => "#c0efff",
+    green-subtle-bg => "#aecf90",
+
+    fg-main => "#000000",
+
+    fg-special-cold => "#093060",
+    fg-special-warm => "#5d3026",
+    fg-special-mild => "#184034",
+    fg-special-calm => "#61284f",
+).map: {.key => hex2rgb(.value)};
+
+enum IterStatus <Walking Blocked Completed>;
+
+sub generate-frame(
+    :%CANVAS, :$out, :%excess, :$side, :%meta, :$iter is copy
+    , :$idx, :$debug,
+) is export {
+    my IterStatus $status;
+    given $iter.substr(0, 1) {
+        when '|' { $status = Completed }
+        when '!' { $status = Blocked }
+        default { $status = Walking }
+    };
+
+    # Remove marker.
+    $iter .= substr(1) if $status == Completed|Blocked;
+
+    put "\n[fornax] $idx $iter $status" if $debug;
+
+    my @grid = $iter.comb.rotor: %meta<cols>;
+    warn "Invalid grid: $idx $iter $status" unless @grid.elems == %meta<rows>;
+
+    given Cairo::Image.create(
+        Cairo::FORMAT_ARGB32, %CANVAS<width>, %CANVAS<height>
+    ) {
+        given Cairo::Context.new($_) {
+            # Paint the entire canvas white.
+            .rgb: |%C<bg-main>;
+            .rectangle(0, 0, %CANVAS<width>, %CANVAS<height>);
+            .fill;
+
+            # This seems to be slower than creating an intermediate
+            # variable and assigning from that. Difference is not much
+            # so we'll ignore it.
+            for ^%meta<rows> X ^%meta<cols>  -> ($r, $c) {
+                my Int @target = %excess<width> div 2 + $c * $side,
+                                 %excess<height> div 2 + $r * $side,
+                                 $side, $side;
+
+                .rectangle: |@target;
+
+                given @grid[$r][$c] -> $cell {
+                    # According to the format, current position may be
+                    # prioritized over Destination symbol so we
+                    # colorize it according to $status.
+                    when $cell eq $CUR {
+                        .rgba: |%C<fg-special-cold>, 0.56;
+                        .rgba: |%C<fg-special-mild>, 0.72 if $status == Completed;
+                        .rgba: |%C<fg-special-warm>, 0.72 if $status == Blocked;
+                    }
+                    when $cell eq $CURPATH {
+                        .rgba: |%C<blue-subtle-bg>, 0.84;
+                        .rgba: |%C<green-subtle-bg>, 0.96 if $status == Completed;
+                        .rgba: |%C<red-subtle-bg>, 0.96 if $status == Blocked;
+                    }
+                    when $cell eq $VIS {
+                        .rgba: |%C<cyan-subtle-bg>, 0.72;
+                    }
+                    when $cell eq $BLOK { .rgba: |%C<fg-main>, 0.56 }
+                    when $cell eq $STRT|$DEST { .rgba: |%C<fg-special-mild>, 0.72 }
+                    default { .rgba: |%C<fg-main>, 0.08 }
+                }
+                .fill :preserve;
+
+                .rgb: |%C<fg-main>;
+                .stroke;
+            }
+        }
+        .write_png($out);
+        .finish;
+    }
+}
-- 
cgit 1.4.1-2-gfad0


From 8af7ea1e0572870eb49e6a6784736a2ca803600e Mon Sep 17 00:00:00 2001
From: Andinus <andinus@nand.sh>
Date: Thu, 18 Nov 2021 17:00:08 +0530
Subject: Set stop duration to 2 seconds

---
 lib/Fornax/CLI.rakumod | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'lib')

diff --git a/lib/Fornax/CLI.rakumod b/lib/Fornax/CLI.rakumod
index d066ebf..bac08ff 100644
--- a/lib/Fornax/CLI.rakumod
+++ b/lib/Fornax/CLI.rakumod
@@ -91,7 +91,7 @@ multi sub MAIN(
 
         my Str $log-level = $debug ?? "info" !! "error";
         run «ffmpeg -loglevel "$log-level" -r "$frame-rate" -i "$output/\%08d.png"
-                    -vf 'tpad=stop_mode=clone:stop_duration=4'
+                    -vf 'tpad=stop_mode=clone:stop_duration=2'
                     -vcodec libx264 -crf 28 -pix_fmt yuv420p "$output/solution.mp4"»;
     }
 }
-- 
cgit 1.4.1-2-gfad0


From b1259dc7b9aba4831cd61bf3521708ec3089ed3c Mon Sep 17 00:00:00 2001
From: Andinus <andinus@nand.sh>
Date: Thu, 18 Nov 2021 17:09:51 +0530
Subject: Set default crf to 24

From https://trac.ffmpeg.org/wiki/Encode/H.265:

     The default is 28, and it should visually correspond to libx264
     video at CRF 23, but result in about half the file size.

This will result in larger videos. Maybe the default should be
libx265. I did try it, results in smaller videos but I wasn't able to
play the video on Firefox.
---
 lib/Fornax/CLI.rakumod | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'lib')

diff --git a/lib/Fornax/CLI.rakumod b/lib/Fornax/CLI.rakumod
index bac08ff..98f20a7 100644
--- a/lib/Fornax/CLI.rakumod
+++ b/lib/Fornax/CLI.rakumod
@@ -92,7 +92,7 @@ multi sub MAIN(
         my Str $log-level = $debug ?? "info" !! "error";
         run «ffmpeg -loglevel "$log-level" -r "$frame-rate" -i "$output/\%08d.png"
                     -vf 'tpad=stop_mode=clone:stop_duration=2'
-                    -vcodec libx264 -crf 28 -pix_fmt yuv420p "$output/solution.mp4"»;
+                    -vcodec libx264 -crf 24 -pix_fmt yuv420p "$output/solution.mp4"»;
     }
 }
 
-- 
cgit 1.4.1-2-gfad0