Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: mndrix/clk
base: a20ab57c12
...
head fork: mndrix/clk
compare: a7bb398c31
  • 2 commits
  • 2 files changed
  • 0 commit comments
  • 1 contributor
Commits on Feb 21, 2012
@mndrix Build a pie chart summarizing work by category
This graphic should help me control how much time I spend on overhead
and email.  It also helps me restrain my 20% time to only 20% of my
work hours.

classify/3 (11 lines long) is the only part that's really suited to
Mercury.  It probably would have been much more succinct to write this
report in Perl.  String munging, hash table maintenance and IO
dominate.
3a3ad1f
@mndrix Clean up pie report
Using a more functional style makes the code easier to read and also
made determinism easier to deal with.  The trick was slurping all
input lines into memory and then operating over them purely.
Separating IO from computation seems to help a lot.
a7bb398
Showing with 82 additions and 0 deletions.
  1. +3 −0  .gitignore
  2. +79 −0 clk-report-pie.m
View
3  .gitignore
@@ -1,4 +1,7 @@
+Mercury/
*.hi
*.o
*.exe
*.swp
+*.err
+*.mh
View
79 clk-report-pie.m
@@ -0,0 +1,79 @@
+:- module 'clk-report-pie'.
+
+:- interface.
+:- import_module io.
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module assoc_list.
+:- import_module exception, float, int, list, map, math, parser, string, term.
+
+:- type summary == map(string,float).
+
+main(!IO) :-
+ command_line_arguments(Args,!IO),
+ ( [File]=Args -> see(File,_,!IO) ; true ),
+ slurp(Lines, !IO),
+ filter_map(parse_line, Lines, Entries),
+ foldl( group_by, Entries, init, Summary ),
+ display_graph(Summary, !IO).
+
+:- pred slurp(list(string)::out, io::di, io::uo) is det.
+slurp(Lines, !IO) :-
+ slurp_([],Backwards,!IO),
+ reverse(Backwards,Lines).
+slurp_(Accum,Out,!IO) :-
+ read_line_as_string(Result,!IO),
+ ( eof = Result, Out = Accum
+ ; error(X) = Result, throw(X)
+ ; ok(L) = Result, slurp_([chomp(L)|Accum],Out,!IO)
+ ).
+
+:- pred parse_line(string::in,{string,float}::out) is semidet.
+parse_line(Line,{Group,Duration}) :-
+ [_,_,Seconds,TagsString,Message] = split_at_char('\t', Line),
+ remove_suffix(Seconds,"s",DurationString),
+ to_float(DurationString,Duration),
+ Tags = (TagsString = "" -> [] ; split_at_char(',',TagsString)),
+ Group = (if classify(Tags,Message,G) then G else "other: "++Message),
+ \+ Group = "out".
+
+:- pred display_graph(summary::in,io::di,io::uo) is det.
+display_graph(Summary, !IO) :-
+ foldl_values(max_p, Summary, 0.0, Max),
+ foldl_values(sum_p, Summary, 0.0, Sum),
+ keys_and_values( to_assoc_list(Summary), Ks, Vs),
+ Values = map(float_to_string, Vs),
+ Keys = map_corresponding(
+ (func(K,V)=C:-format("%s (%.0f%%)",[s(K),f(100.0*V/Sum)],C)),
+ Ks, Vs),
+ format(
+ "open 'https://chart.googleapis.com/chart?chds=0,%.0f&cht=p&chs=700x300&chd=t:%s&chl=%s'",
+ [
+ f(Max),
+ s(join_list(",",Values)),
+ s(join_list("|",Keys))
+ ],
+ Cmd
+ ),
+ call_system(Cmd, _, !IO).
+:- pred max_p(float::in,float::in,float::out) is det.
+max_p(X,Y,Z) :- Z = max(X,Y).
+:- pred sum_p(float::in,float::in,float::out) is det.
+sum_p(X,Y,Z) :- Z = X+Y.
+
+:- pred group_by({string,float}::in,summary::in,summary::out) is det.
+group_by({Group,Duration},!Summary) :-
+ OldDuration = (if search(!.Summary,Group,D) then D else 0.0),
+ set(Group,OldDuration+Duration,!Summary).
+
+:- pred classify(list(string)::in,string::in,string::out) is semidet.
+classify([],"out","out").
+classify(["ndrix"],"email","email").
+classify(["ndrix","research"],_,"twenty").
+classify(["ndrix","20"],_,"twenty").
+classify(["ndrix","coincard"],_,"twenty").
+classify(["jjgames"|_],_,"jjgames").
+classify(["scs"|_],_,"scs").
+classify(["vgpc"|_],_,"vgpc").

No commit comments for this range

Something went wrong with that request. Please try again.