forked from Ares-Developers/YRpp
-
Notifications
You must be signed in to change notification settings - Fork 25
/
DiscreteSelectionClass.h
93 lines (73 loc) · 1.99 KB
/
DiscreteSelectionClass.h
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
/*
A helper to randomly select from many equally good items with the best
rating.
Add one or more items you want to select from, giving each a rating value.
The instance is able to select values if there is at least one item with
a rating that compares equal to or better to the initial value. Items with
a worse rating than the best are discarded.
You can select multiple items using the same instance of this class, the
probabilities of items to be selected will not change. Valid values for
selection are 0..GetCount()-1. The select function will return true if and
only if the instance is set up correctly and an item could be selected. The
out parameter is written to if and only if an item could be selected.
*/
#pragma once
#include <ArrayClasses.h>
#include <Randomizer.h>
#include <utility>
template <typename T>
class DiscreteSelectionClass
{
public:
DiscreteSelectionClass() = default;
explicit DiscreteSelectionClass(int initial) : Rating(initial) {}
void Add(T value, int rating) {
if(this->Rating > rating) {
return;
}
if(rating > this->Rating) {
this->Clear();
this->Rating = rating;
}
this->Items.AddItem(std::move(value));
}
void Clear() {
this->Items.Clear();
}
int GetRating() const {
return this->Rating;
}
int GetCount() const {
return this->Items.Count;
}
bool IsValid() const {
return this->GetCount() > 0;
}
bool Select(int index, T* pOut) const {
if(this->Items.ValidIndex(index)) {
if(pOut) {
*pOut = this->Items[index];
}
return true;
}
return false;
}
bool Select(Randomizer &random, T* pOut) const {
if(!this->IsValid()) {
return false;
}
int value = random.RandomRanged(0, this->GetCount() - 1);
return this->Select(value, pOut);
}
T Select(int index, T default = T()) const {
this->Select(index, &default);
return default;
}
T Select(Randomizer &random, T default = T()) const {
this->Select(random, &default);
return default;
}
private:
DynamicVectorClass<T> Items{};
int Rating{ 0 };
};