Passed
Branch master (27e47c)
by Vincent
03:32
created

reverseBool(int)   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
dl 0
loc 2
ccs 1
cts 1
cp 1
crap 1
rs 10
1
/*
2
 * This file is part of ArakneUtils.
3
 *
4
 * ArakneUtils 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
 * ArakneUtils 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 ArakneUtils.  If not, see <https://www.gnu.org/licenses/>.
16
 *
17
 * Copyright (c) 2017-2020 Vincent Quatrevieux
18
 */
19
20
package fr.arakne.utils.value.helper;
21
22
import fr.arakne.utils.value.Interval;
23
24
import java.util.*;
25
26
/**
27
 * Utility for random numbers
28
 *
29
 * This utility class must be used instead of the native {@link Random} class,
30
 * for create predictable random values on testing environment
31
 *
32
 * It's not recommended to share the RandomUtil instance between objects instances (i.e. store into a static field)
33
 * Each objects instance should have its own RandomUtil instance
34
 * But in case of short-life objects static instance of RandomUtil can be used when created using {@link RandomUtil#createShared()}
35
 */
36
final public class RandomUtil extends Random {
37
    /**
38
     * Testing mode ?
39
     * If set to true, the seed value will be fixed and random will be predictable
40
     */
41 1
    static private boolean testing = false;
42
43
    /**
44
     * List of instance which are shared between instances
45
     * This list is used for reset random seeds when enable testing mode
46
     *
47
     * @see RandomUtil#createShared()
48
     */
49 1
    final static private Collection<RandomUtil> sharedInstances = new ArrayList<>();
50
51 1
    public RandomUtil() {
52 1
        if (testing) {
53 1
            setSeed(0);
54
        }
55 1
    }
56
57
    /**
58
     * Get random number into [min, max] interval
59
     * The interval is inclusive
60
     *
61
     * If max if lower than min, min is returned
62
     */
63
    public int rand(int min, int max) {
64 1
        if (max <= min) {
65 1
            return min;
66
        }
67
68 1
        if (min == 0) {
69 1
            return nextInt(max + 1);
70
        }
71
72 1
        return nextInt((max - min) + 1) + min;
73
    }
74
75
    /**
76
     * Get random number into given interval
77
     * The interval is inclusive
78
     */
79
    public int rand(Interval interval) {
80 1
        return rand(interval.min(), interval.max());
81
    }
82
83
    /**
84
     * Get a random double between interval [0, max[
85
     *
86
     * @param max The maximum value (exclusive)
87
     */
88
    public double decimal(double max) {
89 1
        return nextDouble() * max;
90
    }
91
92
    /**
93
     * Get a random number from an interval
94
     */
95
    public int rand(int[] interval) {
96 1
        if (interval.length == 1 || interval[0] > interval[1]) {
97 1
            return interval[0];
98
        }
99
100 1
        return rand(interval[0], interval[1]);
101
    }
102
103
    /**
104
     * Get a random boolean value
105
     *
106
     * @param percent Percent of chance that the returned value is true.
107
     *                If the value is 100, this method will always returns true
108
     *                If the value is 0, the method will always returns false
109
     */
110
    public boolean bool(int percent) {
111 1
        return nextInt(100) < percent;
112
    }
113
114
    /**
115
     * Get a random boolean value
116
     * The returned value has same chance to be true or false
117
     *
118
     * This method is equivalent to `bool(50)`
119
     *
120
     * @see RandomUtil#bool(int)
121
     */
122
    public boolean bool() {
123 1
        return nextBoolean();
124
    }
125
126
    /**
127
     * Get a random boolean value following reverse chance
128
     * The return value if true with the probability of 1 / rate
129
     * Higher the rate value is, lower the probability is
130
     *
131
     * For rate = 2, the probability is 50% and its equivalent to call bool(50) or bool()
132
     * For rate = 100, the probability is 1% and its equivalent to call bool(1)
133
     *
134
     * @param rate The rate
135
     *
136
     * @return The random boolean value
137
     */
138
    public boolean reverseBool(int rate) {
139 1
        return nextInt(rate) == 0;
140
    }
141
142
    /**
143
     * Get a random value from an array of values
144
     * All elements has the same selection probability
145
     *
146
     * @param values The provided values
147
     *
148
     * @return One of the element of the array
149
     */
150
    public<T> T of(T[] values) {
151 1
        return values[nextInt(values.length)];
152
    }
153
154
    /**
155
     * Get a random value from an array of characters
156
     *
157
     * @see RandomUtil#of(Object[])
158
     */
159
    public char of(char[] values) {
160 1
        return values[nextInt(values.length)];
161
    }
162
163
    /**
164
     * Get a random value from a list of values
165
     * All elements has the same selection probability
166
     *
167
     * @param values The provided values
168
     *
169
     * @return One of the element of the list
170
     */
171
    public<T> T of(List<T> values) {
172 1
        return values.get(nextInt(values.size()));
173
    }
174
175
    /**
176
     * Randomize list element positions
177
     * This method will create a copy of the list, without modify the input parameter (unlike {@link Collections#shuffle(List)})
178
     *
179
     * @param list The list to randomize
180
     * @param <T> The element type
181
     *
182
     * @return The randomized list
183
     */
184
    public<T> List<T> shuffle(List<T> list) {
185 1
        List<T> shuffled = new ArrayList<>(list);
186
187 1
        Collections.shuffle(shuffled, this);
188
189 1
        return shuffled;
190
    }
191
192
    /**
193
     * Create a new RandomUtil instance which is shared between instances (store in a static field)
194
     * This method allows the system to reset the random seed value when enable testing mode, for predictable random
195
     */
196
    static public RandomUtil createShared() {
197 1
        RandomUtil random = new RandomUtil();
198
199 1
        sharedInstances.add(random);
200
201 1
        return random;
202
    }
203
204
    /**
205
     * Enable the testing mode for get predictable random values
206
     * This method MUST NOT be used outside tests
207
     */
208
    static public void enableTestingMode() {
209 1
        testing = true;
210
211
        // Reset the random state
212 1
        sharedInstances.forEach(randomUtil -> randomUtil.setSeed(0));
213 1
    }
214
}
215