1:- module(bc_tag_stat, [
    2    bc_tag_stat/1,     % -Tags
    3    bc_tag_stat/2,     % +Type, -Tags
    4    bc_tag_stat_all/2  % +Type, -Tags
    5]).

Tag statistics */

    9:- use_module(library(assoc)).   10:- use_module(library(docstore)).   11:- use_module(library(sort_dict)).
 bc_tag_stat(+Type, -Tags) is det
Finds tags that are used by published posts. Gives list of dicts _{ tag: Tag, count: Count }
   19bc_tag_stat(Type, Tags):-
   20    must_be(atom, Type),
   21    ds_find(entry,
   22        (published=true, type=Type),
   23        [tags], Posts),
   24    tag_statistics(Posts, _{}, Tags).
 bc_tag_stat_all(+Type, -Tags) is det
Finds tags that are used by all posts. Otherwise same as bc_tag_stat/2.
   31bc_tag_stat_all(Type, Tags):-
   32    must_be(atom, Type),
   33    ds_find(entry, type=Type, [tags], Posts),
   34    tag_statistics(Posts, _{}, Tags).
 bc_tag_stat(-Tags) is det
Same as bc_tag_stat/2 but uses post as the entry type.
   41bc_tag_stat(Tags):-
   42    bc_tag_stat(post, Tags).
   43
   44tag_statistics([Post|Posts], Acc, Tags):-
   45    PostTags = Post.tags,
   46    update_tagstat(PostTags, Acc, Tmp),
   47    tag_statistics(Posts, Tmp, Tags).
   48
   49tag_statistics([], Acc, Sorted):-
   50    tag_stat_dicts(Acc, Tags),
   51    sort_dict(count, desc, Tags, Sorted).
   52
   53update_tagstat([Tag|Tags], In, Out):-
   54    (   get_dict(Tag, In, Old)
   55    ->  New is Old + 1,
   56        put_dict(Tag, In, New, Tmp)
   57    ;   put_dict(Tag, In, 1, Tmp)),
   58    update_tagstat(Tags, Tmp, Out).
   59
   60update_tagstat([], Acc, Acc).
   61
   62% Turns stat dict into list of
   63% smaller dicts _{ tag: Tag, count: Count }.
   64
   65tag_stat_dicts(Stats, List):-
   66    dict_pairs(Stats, _, Pairs),
   67    tag_stat_dicts_list(Pairs, List).
   68
   69tag_stat_dicts_list([Tag-Count|Pairs], [Dict|List]):-
   70    Dict = _{ tag: Tag, count: Count },
   71    tag_stat_dicts_list(Pairs, List).
   72
   73tag_stat_dicts_list([], [])