]> git.tdb.fi Git - poefilter.git/blob - source/rangecondition.h
Correctly merge icon and light beam appearances
[poefilter.git] / source / rangecondition.h
1 #ifndef RANGECONDITION_H_
2 #define RANGECONDITION_H_
3
4 #include "condition.h"
5 #include "filter.h"
6
7 template<typename T>
8 class RangeCondition: public Condition
9 {
10 public:
11         typedef T Traits;
12         typedef typename Traits::Type Type;
13
14 protected:
15         Type min;
16         Type max;
17
18 public:
19         RangeCondition(Type);
20         RangeCondition(Type, Type);
21
22         virtual RangeCondition<T> *clone() const;
23         virtual bool equals(const Condition &) const;
24         virtual bool can_merge(const Condition &, const CompoundCondition &) const;
25         virtual RangeCondition<T> *merge(const std::vector<const Condition *> &, const CompoundCondition &) const;
26         virtual bool is_viable() const { return min<=max; }
27         virtual void add_lines(std::list<FilterStatement> &) const;
28 };
29
30
31 struct RarityTraits
32 {
33         typedef Rarity Type;
34         static Rarity get_min() { return NORMAL; }
35         static Rarity get_max() { return UNIQUE; }
36         static const char *get_keyword() { return "Rarity"; }
37 };
38
39 typedef RangeCondition<RarityTraits> RarityCondition;
40
41
42 struct QualityTraits
43 {
44         typedef unsigned Type;
45         static unsigned get_min() { return 0; }
46         static unsigned get_max() { return 20; }
47         static const char *get_keyword() { return "Quality"; }
48 };
49
50 typedef RangeCondition<QualityTraits> QualityCondition;
51
52
53 struct ItemLevelTraits
54 {
55         typedef unsigned Type;
56         static unsigned get_min() { return 1; }
57         static unsigned get_max() { return 100; }
58         static const char *get_keyword() { return "ItemLevel"; }
59 };
60
61 typedef RangeCondition<ItemLevelTraits> ItemLevelCondition;
62
63
64 struct DropLevelTraits
65 {
66         typedef unsigned Type;
67         static unsigned get_min() { return 1; }
68         static unsigned get_max() { return 100; }
69         static const char *get_keyword() { return "DropLevel"; }
70 };
71
72 typedef RangeCondition<DropLevelTraits> DropLevelCondition;
73
74
75 struct MapTierTraits
76 {
77         typedef unsigned Type;
78         static unsigned get_min() { return 1; }
79         static unsigned get_max() { return 17; }
80         static const char *get_keyword() { return "MapTier"; }
81 };
82
83 typedef RangeCondition<MapTierTraits> MapTierCondition;
84
85
86 struct WidthTraits
87 {
88         typedef unsigned Type;
89         static unsigned get_min() { return 1; }
90         static unsigned get_max() { return 2; }
91         static const char *get_keyword() { return "Width"; }
92 };
93
94 typedef RangeCondition<WidthTraits> WidthCondition;
95
96
97 struct HeightTraits
98 {
99         typedef unsigned Type;
100         static unsigned get_min() { return 1; }
101         static unsigned get_max() { return 4; }
102         static const char *get_keyword() { return "Height"; }
103 };
104
105 typedef RangeCondition<HeightTraits> HeightCondition;
106
107
108 struct SocketsTraits
109 {
110         typedef unsigned Type;
111         static unsigned get_min() { return 1; }
112         static unsigned get_max() { return 6; }
113         static const char *get_keyword() { return "Sockets"; }
114 };
115
116 typedef RangeCondition<SocketsTraits> SocketsCondition;
117
118
119 struct LinkedSocketsTraits
120 {
121         typedef unsigned Type;
122         static unsigned get_min() { return 1; }
123         static unsigned get_max() { return 6; }
124         static const char *get_keyword() { return "LinkedSockets"; }
125 };
126
127 typedef RangeCondition<LinkedSocketsTraits> LinkedSocketsCondition;
128
129
130 template<typename T>
131 RangeCondition<T>::RangeCondition(Type v):
132         min(v),
133         max(v)
134 { }
135
136 template<typename T>
137 RangeCondition<T>::RangeCondition(Type n, Type x):
138         min(n),
139         max(x)
140 { }
141
142 template<typename T>
143 RangeCondition<T> *RangeCondition<T>::clone() const
144 {
145         return new RangeCondition<T>(min, max);
146 }
147
148 template<typename T>
149 bool RangeCondition<T>::equals(const Condition &other) const
150 {
151         const RangeCondition<T> *other_range = dynamic_cast<const RangeCondition<T> *>(&other);
152         if(!other_range)
153                 return false;
154
155         return (min==other_range->min && max==other_range->max);
156 }
157
158 template<typename T>
159 bool RangeCondition<T>::can_merge(const Condition &other, const CompoundCondition &parent) const
160 {
161         const RangeCondition<T> *other_range = dynamic_cast<const RangeCondition<T> *>(&other);
162         if(!other_range)
163                 return false;
164
165         if(dynamic_cast<const AndCondition *>(&parent))
166                 return true;
167         else if(dynamic_cast<const OrCondition *>(&parent))
168                 return min<=other_range->max+1 && max+1>=other_range->min;
169         else
170                 return false;
171 }
172
173 template<typename T>
174 RangeCondition<T> *RangeCondition<T>::merge(const std::vector<const Condition *> &conditions, const CompoundCondition &parent) const
175 {
176         if(conditions.empty())
177                 return 0;
178
179         bool intersect = dynamic_cast<const AndCondition *>(&parent);
180         RangeCondition<T> *result;
181         if(intersect)
182                 result = new RangeCondition<T>(Traits::get_min(), Traits::get_max());
183         else
184                 result = new RangeCondition<T>(Traits::get_max(), Traits::get_min());
185         for(std::vector<const Condition *>::const_iterator i=conditions.begin(); i!=conditions.end(); ++i)
186         {
187                 const RangeCondition<T> *c = static_cast<const RangeCondition<T> *>(*i);
188                 if(intersect)
189                 {
190                         result->min = std::max(result->min, c->min);
191                         result->max = std::min(result->max, c->max);
192                 }
193                 else
194                 {
195                         result->min = std::min(result->min, c->min);
196                         result->max = std::max(result->max, c->max);
197                 }
198         }
199         return result;
200 }
201
202 template<typename T>
203 void RangeCondition<T>::add_lines(std::list<FilterStatement> &st) const
204 {
205         const char *keyword = Traits::get_keyword();
206         if(min==max)
207                 FilterStatement::add_line(st, Msp::format("%s %s", keyword, min));
208         else
209         {
210                 if(min!=Traits::get_min())
211                         FilterStatement::add_line(st, Msp::format("%s >= %s", keyword, min));
212                 if(max!=Traits::get_max())
213                         FilterStatement::add_line(st, Msp::format("%s <= %s", keyword, max));
214         }
215 }
216
217 #endif