Current section

Files

Jump to
accept src accept_neg.erl
Raw

src/accept_neg.erl

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-module(accept_neg).
-moduledoc false.
-export([alt_tag/1, sort_scored/1, find_preferred_best/1, score_params/2]).
%% @doc Extracts the tag from an alternative.
-spec alt_tag(term()) -> {string(), binary()}.
alt_tag(Alt) ->
case Alt of
{_, _} -> Alt;
_ when is_binary(Alt) -> {accept_parser:ensure_string(Alt), Alt};
_ -> {Alt, Alt}
end.
%% @doc Sorts scored alternatives by score.
-spec sort_scored([{number(), term()}]) -> [{number(), term()}].
sort_scored(Scored) ->
lists:sort(fun scored_cmp/2, Scored).
%% @doc Find alternative with the best score
%%
%% keysort is stable so order of Alternatives preserved
%% after sorting Tail has the best score.
%% However if multiple alternatives have the same score as Tail
%% we should find first best alternative to respect user's priority.
-spec find_preferred_best([{number(), term()}]) -> {number(), term()}.
find_preferred_best(Alts) ->
Sorted = lists:keysort(1, Alts),
[B | R] = lists:reverse(Sorted),
find_preferred_best(B, R).
%% @doc Score parameters
-spec score_params([term()], [term()]) -> number().
score_params([], _) ->
1;
score_params(CCParams, AltParams) when length(CCParams) == length(AltParams) ->
case lists:sort(CCParams) == lists:sort(AltParams) of
true -> 2;
_ -> 0
end;
score_params(_, _) ->
0.
%%====================================================================
%% Private Parts
%%====================================================================
-spec scored_cmp({number(), term()}, {number(), term()}) -> boolean().
scored_cmp({S1, _}, {S2, _}) ->
S1 > S2.
-spec find_preferred_best({number(), term()}, [{number(), term()}]) -> {number(), term()}.
find_preferred_best({Q, _}, [{Q, _} = H | R]) ->
find_preferred_best(H, R);
find_preferred_best(B, []) ->
B;
find_preferred_best(B, _) ->
B.