<commit_before>#!/usr/bin/env swipl -t halt -g main -q -s
infer( [tech,team],    entry( 'tech team',    [gsg, meeting] ) ).
infer( [time,tracker], entry( 'time tracker', [gsg         ] ) ).
infer( [gitc,support], entry( 'user support', [gsg, gitc   ] ) ).
infer( [Changeset], entry( '', [gsg,Project,Name] ) ) :-
    changeset( Changeset, Project, Name ).
infer( [review,Changeset], entry( 'code review', [gsg,Project,Name] ) ) :-
    changeset( Changeset, Project, Name ).
infer( Words, entry( Subject, Tags ) ) :-
    infer_tags( Words, Tags ),
    subtract( Words, Tags, SubjectWords ),
    concat_atom( SubjectWords, ' ', Subject ).

infer_tags( Words, Tags ) :-
    findall( Ts, ( member( W, Words ), tags(W, Ts) ), NestedTags ),
    flatten( NestedTags, TagList ),
    list_to_set( TagList, Tags ).
    
tags( jjg, jjgames ).
tags( W, [W]) :- member( W, [ jjgames, gsg, scs, conserve ] ).
tags( Project, [ Client, Project ] ) :- project( Client, Project ).
tags( Changeset, [ gsg, Project, Name ] ) :-
    changeset( Changeset, Project, Name ).
tags( Bug, [Bug] ) :- bugzilla(Bug).

% projects for each client
project( gsg, P ) :- member( P, [ 'gsg-arc', zions, gitc ] ).
project( scs, P ) :- member( P, [ wcit, qa ] ).

% GSG's changeset designation (like project#e1234b)
changeset( C, Project, Name ) :- concat_atom( [ Project, Name ], '#', C ).

% Bugzilla bug number
bugzilla(Bug) :-
    concat_atom( [b, X], Bug ),
    atom_number( X, N ),
    N > 0.

% find structure for the command line arguments
main( Words ) :-
    infer( Words, entry( Subject, Tags ) ),
    format('-m "~w" -t ~w~n', [Subject, Tags] ).

% boilerplate for extracting command-line arguments
main :-
    current_prolog_flag( argv, Argv ),
    append( _, [--|Args], Argv ),
    !,
    main( Args ).

% tests
ok(Goal) :- Goal, format('ok - ~w~n', [Goal]), !.
ok(Goal) :- format('not ok - ~w~n', [Goal]), !.
test :-
    format('1..~w~n', [6]),
    ok( infer([tech,team],entry('tech team', [gsg,meeting]))),
    ok( infer([gsg,email],entry('email', [gsg]))),
    ok( infer(['zions#e1234'],entry('', [gsg,zions,e1234]))),
    ok( infer([review, 'zions#e1234'],entry('code review', [gsg,zions,e1234]))),
    ok( infer([scs,wcit,fixing,errors],entry('fixing errors', [scs,wcit]))),
    ok( infer([jjg,b690],entry('', [jjgames,b690]))),
    true.
<commit_msg>Complete rewrite of inference script<commit_after>#!/usr/bin/env swipl -t halt -g main -q -s

infer( [tech,team],        'tech team',    [gsg, meeting] ).
infer( [time,tracker],     'time tracker', [gsg         ] ).
infer( [gitc,support],     'user support', [gitc,gsg    ] ).
infer( [svkc,support],     'user support', [gsg,svkc    ] ).
infer( [review,Changeset], 'code review',  Tags ) :-
    changeset( Changeset, Project, Name ),
    sort([gsg,Project,Name], Tags).
infer( Words, Subject, Tags ) :-
    infer_(Words, [], [], Subject, Tags).

% accumulating helper for infer/3
infer_( [H|Tail], S0, T0, Subject, Tags ) :-
    expand( H, S, T ),
    !,
    append( S0, S, S1 ),
    append( T0, T, T1 ),
    infer_( Tail, S1, T1, Subject, Tags ).
infer_( [], S0, T0, Subject, Tags ) :-
    concat_atom( S0, ' ', Subject ),
    sort( T0, Tags ).

% expand single words into subject words and tags
expand( jjg, [], [jjgames] ).
expand( Changeset, [], [gsg,Project,Name] ) :-
    changeset( Changeset, Project, Name ).
expand( Client, [], [Client] ) :-
    member( Client, [ jjgames, gsg, scs, conserve ] ).
expand( Project, [], [Client,Project] ) :-
    project( Client, Project ).
expand( Bug, [], [Bug] ) :-
    concat_atom( [b, X], Bug ),
    catch( atom_number( X, N ), _, fail ),
    N > 0.
expand( W, [W], [] ).

% each client's projects
project( gsg, P ) :-
    member( P, [ arc,tla,cd,pma,zions,'tax-lien','tax-cbs','tva-note','fmac-ebb',eventum,'yield-auction',foreclosures,'fmac-debt','gsg-catalyst','gsg-shared','gsg-db-schema','mellon-gsl','time-tracker','gsg-homepage',gitc,'zions-sso','zions-new-account','gsg-catalyst-base' ] ).
project( scs, P ) :-
    member( P, [ wcit, qa ] ).

% GSG's changeset format (e.g. tax-cbs#e12345)
changeset( Changeset, Project, Name ) :-
    concat_atom( [ Project, Name ], '#', Changeset ).

% find structure for the command line arguments
main( Words ) :-
    infer( Words, Subject, Tags ),
    format('-m "~w" -t ~w~n', [Subject, Tags] ).

% boilerplate for extracting command-line arguments
main :-
    current_prolog_flag( argv, Argv ),
    append( _, [--|Args], Argv ),
    !,
    main( Args ).

% tests
ok(Goal) :- Goal, format('ok - ~w~n', [Goal]), !.
ok(Goal) :- format('not ok - ~w~n', [Goal]), !.
test :-
    format('1..~w~n', [7]),
    ok( infer([tech,team],             'tech team',     [gsg,meeting    ])),
    ok( infer([gsg,email],             'email',         [gsg            ])),
    ok( infer(['zions#e1234'],         '',              [e1234,gsg,zions])),
    ok( infer([review, 'zions#e1234'], 'code review',   [e1234,gsg,zions])),
    ok( infer([scs,wcit,fixing,errors],'fixing errors', [scs,wcit       ])),
    ok( infer([jjg,b690],              '',              [b690,jjgames   ])),
    % atom_number might throw an exception, be sure it's caught
    ok( infer([boo],                   'boo',           [               ])),
    true.

{'fraction_non_alphanumeric': 0.20626432391138275, 'fraction_numerical': 0.013750954927425516, 'mean_word_length': 3.107450980392157, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3118775', 'n_tokens_mistral': 2057, 'n_tokens_neox': 1906, 'n_words': 480}