about summary refs log tree commit diff stats
path: root/lib/Taurus
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Taurus')
-rw-r--r--lib/Taurus/CLI.rakumod141
1 files changed, 117 insertions, 24 deletions
diff --git a/lib/Taurus/CLI.rakumod b/lib/Taurus/CLI.rakumod
index db6be9e..4647c1c 100644
--- a/lib/Taurus/CLI.rakumod
+++ b/lib/Taurus/CLI.rakumod
@@ -1,29 +1,122 @@
 use CSV::Parser;
-use Terminal::UI;
-use Terminal::Spinners;
-use Text::Table::Simple;
+use Terminal::UI 'ui';
+use Terminal::ANSI::OO 't';
+
+# If no arguments are passed then run USAGE & exit.
+proto MAIN(|) is export {unless so @*ARGS {put $*USAGE; exit}; {*}}
 
 #| parses Call Logs
-unit sub MAIN (
+multi sub MAIN (
     Str $log where *.IO.f, #= input log file to parse
     UInt :$digits = 10, #= number of significant digits
-);
-
-my @logs;
-my Str %contacts{Str};
-Spinner.new(:type<bounce2>).await: Promise.start: {
-    my $p = CSV::Parser.new();
-    # 0: Name, 1: Phone number, 2: Call Type, 3: Timestamp,
-    # 4: Duration, 5: Sim used.
-
-    # Turn the Hash to an Array.
-    @logs = @($log.IO.lines.skip.hyper.map({$p.parse($_)})>>.{0..4}
-              # Discard invalid phone numbers.
-              .grep(*.[1].chars >= $digits));
-
-    # Discard non-significant digits from phone numbers.
-    .[1] = .[1].substr(*-10) for @logs;
-
-    # Build contact list.
-    %contacts{.[1]} = .[0] for @logs.grep(*.[0].chars > 0);
-};
+) is export {
+    my @logs;
+    my Str %contacts{Str};
+
+    my Instant $timed = now;
+    my Promise $initial = start {
+        my $p = CSV::Parser.new();
+        # 0: Name, 1: Phone number, 2: Call Type,
+        # 3: Timestamp, 4: Duration, 5: Sim used.
+
+        # Turn the Hash to an Array.
+        @logs = @($log.IO.lines.skip[^200].hyper.map({$p.parse($_)})>>.{0..4}
+                  # Discard invalid phone numbers.
+                  .grep(*.[1].chars >= $digits));
+
+        for @logs {
+            # Discard non-significant digits from phone numbers.
+            .[1] .= substr(*-10);
+
+            # Removing leading/trailing whitespaces from names.
+            .[0] .= trim;
+
+            # Build contact list.
+            %contacts{.[1]} = .[0] if .[0].chars > 0;
+
+            # Store Duration in seconds.
+            .[4] = (.[4].split(":")[0] * 60) + .[4].split(":")[1];
+        }
+    };
+
+    ui.setup: :2panes;
+    my $p0 = ui.panes[0];
+    my $p1 = ui.panes[1];
+
+    $p0.put: t.bold ~ t.bg-cyan ~ t.black ~t.underline~ "Taurus v" ~ $?DISTRIBUTION.meta<version>;
+    $p0.put: "";
+
+    with ui.screen.add-frame(:4height, :40width, :center) -> $f {
+        with $f.add-pane -> $p {
+            $f.draw;
+            until $initial.status {
+                $p.splash: "Parsing logs" ~ (".  ", ".. ", "...")[$++ % 3];
+                sleep 0.8;
+            }
+            $p.splash: "Parsed {@logs.elems} entries in {now - $timed}s.";
+            $p.put: " " x 18 ~ "Ok";
+            $p.select-last;
+            ui.focus($f);
+        }
+        ui.get-key;
+        ui.screen.remove-frame($f);
+        ui.focus($f);
+    }
+    ui.refresh;
+
+    $p0.put: "- Show Records", :meta(:all);
+    $p0.put: "";
+    # First list Contacts, then sorted phone numbers.
+    for @logs.race.map(*.[1]).unique.sort({%contacts{$_} // "Z", $_}) {
+        $p0.put: "- " ~ $_ ~ " {%contacts{$_} // ''}", :meta(:number($_));
+    }
+
+    $p1.clear;
+    $p0.select-first;
+    $p0.select(2);
+    $p0.on: select => -> :%meta {
+        if %meta<all> {
+            $p1.clear;
+            with @logs {
+                my Int $fmt = 16;
+
+                my $outgoing = .grep(*.[2] eqv "Outgoing Call").map(*.[4]).sum;
+                my $incoming = .grep(*.[2] eqv "Incoming Call").map(*.[4]).sum;
+
+                $p1.put: sprintf("%-*s", $fmt, "Outgoing:") ~ $outgoing / 3600 ~ " hours" ;
+                $p1.put: sprintf("%-*s", $fmt, "Incoming:") ~ $incoming / 3600 ~ " hours";
+                $p1.put: sprintf("%-*s", $fmt, "Total:") ~ ($incoming + $outgoing) / 3600 ~ " hours";
+                $p1.put: "";
+            }
+        } elsif %meta<number> -> $num {
+            my Int $fmt = 18;
+
+            $p1.clear;
+            $p1.put: "Name:   " ~ $_ with %contacts{$num};
+            $p1.put: "Number: " ~ $num;
+            $p1.put: "";
+            with @logs.grep(*.[1] eqv $num).cache {
+                my $outgoing = .grep(*.[2] eqv "Outgoing Call").map(*.[4]).sum;
+                my $incoming = .grep(*.[2] eqv "Incoming Call").map(*.[4]).sum;
+
+                $p1.put: sprintf("%-*s", $fmt, "Outgoing:") ~ $outgoing / 3600 ~ " hours";
+                $p1.put: sprintf("%-*s", $fmt, "Incoming:") ~ $incoming / 3600 ~ " hours";
+                $p1.put: sprintf("%-*s", $fmt, "Total:") ~ ($incoming + $outgoing) / 3600 ~ " hours";
+                $p1.put: "";
+
+                $p1.put: sprintf("%-*s", $fmt, "Declined:") ~ .grep(
+                    {$_.[2] eqv "Incoming Call" and $_.[4] == 0}).elems;
+                $p1.put: sprintf("%-*s", $fmt, "Declined (they):") ~ .grep(
+                    {$_.[2] eqv "Outgoing Call" and $_.[4] == 0}).elems;
+                $p1.put: sprintf("%-*s", $fmt, "Missed Calls:") ~ .grep(*.[2] eqv "Missed Call").elems;
+            }
+        }
+    }
+
+    ui.interact;
+    ui.shutdown;
+}
+
+multi sub MAIN(
+    Bool :$version #= print version
+) is export { put "Lacerta v" ~ $?DISTRIBUTION.meta<version>; }