Starsector API
Loading...
Searching...
No Matches
WeightedRandomPicker.java
Go to the documentation of this file.
1package com.fs.starfarer.api.util;
2
3import java.util.ArrayList;
4import java.util.Collection;
5import java.util.Collections;
6import java.util.Comparator;
7import java.util.HashMap;
8import java.util.List;
9import java.util.Map;
10import java.util.Random;
11
12import org.json.JSONArray;
13import org.json.JSONException;
14
15import com.fs.starfarer.api.campaign.econ.MarketAPI;
16
17public class WeightedRandomPicker<T> implements Cloneable {
18
21 try {
23 copy.items = new ArrayList<T>(items);
24 copy.weights = new ArrayList<Float>(weights);
25 return copy;
27 return null;
28 }
29 }
30
31 private List<T> items = new ArrayList<T>();
32 transient private List<Float> weights = new ArrayList<Float>();
33 private String w;
34
35 private float total = 0f;
36 private final boolean ignoreWeights;
37
38 private Random random = null;
39
41 this(false);
42 }
43
44 public WeightedRandomPicker(boolean ignoreWeights) {
45 this.ignoreWeights = ignoreWeights;
46 }
47
49 this(false);
50 this.random = random;
51 }
52
53 Object readResolve() {
54 try {
55 weights = new ArrayList<Float>();
56 if (w != null) {
57 JSONArray arr = new JSONArray(w);
58 for (int i = 0; i < arr.length(); i++) {
59 weights.add((float)arr.getDouble(i));
60 }
61 }
62 } catch (JSONException e) {
63 throw new RuntimeException(e);
64 }
65 return this;
66 }
67
68 Object writeReplace() {
69 JSONArray arr = new JSONArray();
70 for (Float f : weights) {
71 arr.put(f);
72 }
73 w = arr.toString();
74
75 return this;
76 }
77
78
79 public void clear() {
80 items.clear();
81 weights.clear();
82 total = 0;
83 }
84
85// public void addAll(List<T> items) {
86// for (T item : items) {
87// add(item);
88// }
89// }
90
91 public void addAll(Collection<T> items) {
92 for (T item : items) {
93 add(item);
94 }
95 }
96
97 public void addAll(WeightedRandomPicker<T> other) {
98 for (int i = 0; i < other.items.size(); i++) {
99 add(other.items.get(i), other.weights.get(i));
100 }
101 }
102
103 public void add(T item) {
104 add(item, 1f);
105 }
106 public void add(T item, float weight) {
107 //if (weight < 0) weight = 0;
108 if (weight <= 0) return;
109 items.add(item);
110 weights.add(weight); // + (weights.isEmpty() ? 0 : weights.get(weights.size() - 1)));
111 total += weight;
112 }
113
114 public void remove(T item) {
115 int index = items.indexOf(item);
116 if (index != -1) {
117 items.remove(index);
118 float weight = weights.remove(index);
119 total -= weight;
120 }
121 }
122
123 public boolean isEmpty() {
124 return items.isEmpty();
125 }
126
127 public List<T> getItems() {
128 return items;
129 }
130
131 public float getWeight(T item) {
132 int index = items.indexOf(item);
133 if (index < 0) return 0;
134 return getWeight(index);
135 }
136
137 public float getWeight(int index) {
138 return weights.get(index);
139 }
140 public void setWeight(int index, float weight) {
141 float w = getWeight(index);
142 weights.set(index, weight);
143 total += weight - w;
144 }
145
146 public T pickAndRemove() {
147 T pick = pick();
148 remove(pick);
149 return pick;
150 }
151
152 public T pick(Random random) {
153 Random orig = this.random;
154 this.random = random;
155 T pick = pick();
156 this.random = orig;
157 return pick;
158 }
159
160 public T pick() {
161 if (items.isEmpty()) return null;
162
163 if (ignoreWeights) {
164 int index;
165 if (random != null) {
166 index = (int) (random.nextDouble() * items.size());
167 } else {
168 index = (int) (Math.random() * items.size());
169 }
170 return items.get(index);
171 }
172
173 float random;
174 if (this.random != null) {
175 random = this.random.nextFloat() * total;
176 } else {
177 random = (float) (Math.random() * total);
178 }
179 if (random > total) random = total;
180 //random = 0.1f;
181 //random = total - 0.001f;
182 float weightSoFar = 0f;
183 int index = 0;
184 for (Float weight : weights) {
185 weightSoFar += weight;
186 if (random <= weightSoFar) break;
187 index++;
188 }
189 return items.get(Math.min(index, items.size() - 1));
190 }
191
192 public Random getRandom() {
193 return random;
194 }
195
196 public void setRandom(Random random) {
197 this.random = random;
198 }
199
200
201
202 public void print(String title) {
203 System.out.println(title);
204
206 for (int i = 0; i < items.size(); i++) {
207 T item = items.get(i);
208 indices.put(item, i);
209 }
210
211 List<T> sorted = new ArrayList<T>(items);
212 Collections.sort(sorted, new Comparator<T>() {
213 public int compare(T o1, T o2) {
214 return o1.toString().compareTo(o2.toString());
215 }
216 });
217
218 for (T item : sorted) {
219 int index = indices.get(item);
220 float weight = weights.get(index);
221 //String percent = Misc.getRoundedValueMaxOneAfterDecimal((weight / total) * 100f) + "%";
222 String percent = "" + (int)((weight / total) * 100f) + "%";
223
224 //System.out.println(" " + item.toString() + ": " + percent + " (" + Misc.getRoundedValue(weight) + ")");
225 String itemStr = "";
226 if (item instanceof MarketAPI) {
227 itemStr = ((MarketAPI)item).getName();
228 } else {
229 itemStr = item.toString();
230 }
231 System.out.println(String.format(" %-30s%10s%10s", itemStr, percent, Misc.getRoundedValue(weight)));
232 }
233 //System.out.println(" Total: " + (int) total);
234 //System.out.println();
235 }
236
237 public float getTotal() {
238 return total;
239 }
240
241}
242
243
244
245
246
247
static String getRoundedValue(float value)
Definition Misc.java:640
void addAll(WeightedRandomPicker< T > other)