summaryrefslogtreecommitdiff
blob: feac276a6fcd6a4eaca306052be06035ce4ded80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
-module(blc_damage_type).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-type entry() :: {shr_damage_type:type(), non_neg_integer()}.
-type coefficient() :: {shr_damage_type:type(), 0..100}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-export_type([entry/0, coefficient/0]).

-export
(
   [
      sort_entries/1,
      compute_score/1,
      apply_score_modifier/3,
      generate_entries_from_score/2
   ]
).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec sort_entries (list(entry())) -> list(entry()).
sort_entries (Entries) ->
   lists:sort
   (
      fun ({_NameA, ValueA}, {_NameB, ValueB}) -> (ValueA >= ValueB) end,
      Entries
   ).

-spec compute_score (list(entry())) -> non_neg_integer().
compute_score (SortedEntries) ->
   {_LastIndex, Result} =
      lists:foldl
      (
         fun ({_Name, Value}, {Index, Current}) ->
            {(Index + 1), (Current + (Index * Value))}
         end,
         {1, 0},
         SortedEntries
      ),

   Result.

-spec apply_score_modifier
   (
      non_neg_integer(),
      (-1 | 1),
      list(entry())
   )
   -> list(entry()).
apply_score_modifier (AbsModifier, Mod, S0SortedEntries) ->
   {S1SortedEntries, {_EndIndex, EndModifier}} =
      lists:mapfoldl
      (
         fun ({Name, S0Value}, {Index, RemainingModifier}) ->
            case ((RemainingModifier >= Index) and (S0Value > 0)) of
               true ->
                  {
                     {Name, (S0Value + Mod)},
                     {(Index + 1), (RemainingModifier - Index)}
                  };

               false -> {{Name, S0Value}, {(Index + 1), RemainingModifier}}
            end
         end,
         {1, AbsModifier},
         S0SortedEntries
      ),

   case (EndModifier > 0) of
      false -> S1SortedEntries;
      true -> apply_score_modifier(EndModifier, Mod, S1SortedEntries)
   end.

-spec generate_entries_from_score
   (
      non_neg_integer(),
      list(coefficient())
   )
   -> list(entry()).
generate_entries_from_score (TargetScore, SortedRatios) ->
   {Distribution, _LastIndex} =
      lists:foldl
      (
         fun ({_Name, Value}, {Cumul, Index}) ->
            {(Cumul + (Value * Index)), (Index + 1)}
         end,
         {0, 1},
         SortedRatios
      ),

   Base =
      case Distribution of
         0 -> 0;
         _ -> (TargetScore / (Distribution / 100))
      end,

   UnderperformingEntries =
      lists:map
      (
         fun ({Name, Value}) -> {Name, trunc(Base * (Value / 100))} end,
         SortedRatios
      ),

   MissingScore = (TargetScore - compute_score(UnderperformingEntries)),

   case Base of
      0 -> [];
      _ ->
         case (MissingScore >= 0) of
            true ->
               apply_score_modifier(MissingScore, 1, UnderperformingEntries);

            false ->
               apply_score_modifier
               (
                  (-1 * MissingScore),
                  -1,
                  UnderperformingEntries
               )
         end
   end.