teamsLevelsRate(EndFightResults)   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 7
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 6
c 0
b 0
f 0
dl 0
loc 7
ccs 3
cts 3
cp 1
crap 1
rs 10
1
/*
2
 * This file is part of Araknemu.
3
 *
4
 * Araknemu is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * Araknemu is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with Araknemu.  If not, see <https://www.gnu.org/licenses/>.
16
 *
17
 * Copyright (c) 2017-2019 Vincent Quatrevieux
18
 */
19
20
package fr.quatrevieux.araknemu.game.fight.ending.reward.drop.pvm.provider;
21
22
import fr.quatrevieux.araknemu.data.constant.Characteristic;
23
import fr.quatrevieux.araknemu.game.fight.ending.EndFightResults;
24
import fr.quatrevieux.araknemu.game.fight.ending.reward.drop.DropReward;
25
import fr.quatrevieux.araknemu.game.fight.fighter.Fighter;
26
import fr.quatrevieux.araknemu.game.fight.fighter.monster.MonsterFighter;
27
import fr.quatrevieux.araknemu.game.fight.fighter.operation.FighterOperation;
28
import org.checkerframework.checker.index.qual.NonNegative;
29
30
/**
31
 * Base formula for compute the Pvm experience
32
 */
33
public final class PvmXpProvider implements DropRewardProvider {
34
    private final double rate;
35
36
    public PvmXpProvider() {
37 1
        this(1.0);
38 1
    }
39
40 1
    public PvmXpProvider(double rate) {
41 1
        this.rate = rate;
42 1
    }
43
44
    @Override
45
    public DropRewardProvider.Scope initialize(EndFightResults results) {
46 1
        return new Scope(
47 1
            totalXp(results),
48 1
            teamsLevelsRate(results),
49 1
            teamLevelDeviationBonus(results),
50 1
            results.winners().stream().mapToInt(Fighter::level).sum()
51
        );
52
    }
53
54
    private long totalXp(EndFightResults results) {
55 1
        return (long) (results.applyToLoosers(new ExtractXp()).get() * rate);
56
    }
57
58
    private double teamLevelDeviationBonus(EndFightResults results) {
59 1
        final int level = results.winners().stream().mapToInt(Fighter::level).max().orElse(0) / 3;
60
61 1
        int number = 0;
62
63 1
        for (Fighter winner : results.winners()) {
64 1
            if (winner.level() > level) {
65 1
                ++number;
66
            }
67 1
        }
68
69 1
        switch (number) {
70
            case 1:
71 1
                return 1.0;
72
73
            case 2:
74 1
                return 1.1;
75
76
            case 3:
77 1
                return 1.3;
78
79
            case 4:
80 1
                return 2.2;
81
82
            case 5:
83 1
                return 2.5;
84
85
            case 6:
86 1
                return 2.8;
87
88
            case 7:
89 1
                return 3.1;
90
91
            default:
92 1
                return 3.5;
93
        }
94
    }
95
96
    private double teamsLevelsRate(EndFightResults results) {
97 1
        final double winnersLevel = results.winners().stream().mapToInt(Fighter::level).sum();
98 1
        final double loosersLevel = results.loosers().stream().mapToInt(Fighter::level).sum();
99
100 1
        return Math.min(
101
            1.3,
102
            1 + loosersLevel / winnersLevel
103
        );
104
    }
105
106
    private static class Scope implements DropRewardProvider.Scope {
0 ignored issues
show
Comprehensibility introduced by
Class or interface names should not shadow other classes or interfaces. In general, shadowing is a bad practice as it makes code harder to understand. Consider renaming this class.
Loading history...
107
        private final long totalXp;
108
        private final double teamsLevelsRate;
109
        private final double teamLevelDeviationBonus;
110
        private final double winnersLevel;
111
112 1
        public Scope(long totalXp, double teamsLevelsRate, double teamLevelDeviationBonus, double winnersLevel) {
113 1
            this.totalXp = totalXp;
114 1
            this.teamsLevelsRate = teamsLevelsRate;
115 1
            this.teamLevelDeviationBonus = teamLevelDeviationBonus;
116 1
            this.winnersLevel = winnersLevel;
117 1
        }
118
119
        @Override
120
        public void provide(DropReward reward) {
121 1
            final long winXp = (long) (
122
                totalXp
123
                    * teamsLevelsRate
124
                    * teamLevelDeviationBonus
125 1
                    * (1 + ((double) reward.fighter().level() / winnersLevel))
126 1
                    * (1 + (double) reward.fighter().characteristics().get(Characteristic.WISDOM) / 100)
127
            );
128
129 1
            reward.setXp(Math.max(winXp, 0));
130 1
        }
131
    }
132
133
    private static class ExtractXp implements FighterOperation {
134
        private @NonNegative long xp;
135
136
        @Override
137
        public void onMonster(MonsterFighter fighter) {
138 1
            xp += fighter.reward().experience();
139 1
        }
140
141
        public @NonNegative long get() {
142 1
            return xp;
143
        }
144
    }
145
}
146