Skip to content

Commit 5aa1f31

Browse files
author
Bytekeeper
committed
UnitFinder now allows additional criterias for searching.
1 parent 2e944e4 commit 5aa1f31

File tree

3 files changed

+136
-15
lines changed

3 files changed

+136
-15
lines changed

build.gradle.kts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ plugins {
22
java
33
id("maven")
44
id("me.champeau.gradle.jmh") version "0.4.8"
5-
id("org.sonarqube") version "2.7"
5+
id("org.sonarqube") version "2.7.1"
66
id("com.github.ben-manes.versions") version "0.21.0"
77
}
88

@@ -21,11 +21,11 @@ repositories {
2121

2222
dependencies {
2323
implementation(fileTree("lib").include("*.jar"))
24-
implementation("com.github.JasperGeurtz:JBWAPI:develop-SNAPSHOT")
24+
implementation("com.github.JasperGeurtz:JBWAPI:0.7")
2525

26-
testImplementation("org.junit.jupiter:junit-jupiter:5.4.2")
27-
testImplementation("org.assertj:assertj-core:3.12.2")
28-
testImplementation("io.jenetics:jenetics:4.4.0")
26+
testImplementation("org.junit.jupiter:junit-jupiter:5.5.1")
27+
testImplementation("org.assertj:assertj-core:3.13.2")
28+
testImplementation("io.jenetics:jenetics:5.0.1")
2929
}
3030

3131
configure<JavaPluginConvention> {

src/main/java/org/bk/ass/query/UnitFinder.java

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.*;
44
import java.util.Map.Entry;
55
import java.util.function.Function;
6+
import java.util.function.Predicate;
67
import java.util.stream.Collectors;
78
import java.util.stream.Stream;
89

@@ -109,12 +110,29 @@ public Collection<U> inArea(int ax, int ay, int bx, int by) {
109110
return subMapOfArea(ax, ay, bx, by).map(Entry::getValue).collect(Collectors.toList());
110111
}
111112

113+
/**
114+
* Returns a collection of all units in the area with top left (ax, ay) and bottom right (bx, by)
115+
* including those on the boundary. Only units passing the given criteria are returned.
116+
*/
117+
public Collection<U> inArea(int ax, int ay, int bx, int by, Predicate<U> criteria) {
118+
return subMapOfArea(ax, ay, bx, by, criteria).map(Entry::getValue).collect(Collectors.toList());
119+
}
120+
112121
private Stream<Entry<PositionAndId, U>> subMapOfArea(int ax, int ay, int bx, int by) {
113122
return map
114123
.subMap(
115124
new PositionAndId(-1, ax, ay), true, new PositionAndId(Integer.MAX_VALUE, bx, by), true)
116125
.entrySet().stream()
117-
.filter(u -> u.getKey().y <= by && u.getKey().y >= ay);
126+
.filter(u -> u.getKey().y <= by && u.getKey().y >= ay);
127+
}
128+
129+
private Stream<Entry<PositionAndId, U>> subMapOfArea(
130+
int ax, int ay, int bx, int by, Predicate<U> criteria) {
131+
return map
132+
.subMap(
133+
new PositionAndId(-1, ax, ay), true, new PositionAndId(Integer.MAX_VALUE, bx, by), true)
134+
.entrySet().stream()
135+
.filter(u -> u.getKey().y <= by && u.getKey().y >= ay && criteria.test(u.getValue()));
118136
}
119137

120138
/**
@@ -168,8 +186,42 @@ public Optional<U> closestTo(int x, int y) {
168186
return Optional.empty();
169187
}
170188
return subMapOfArea(x - squareHSize, y - squareHSize, x + squareHSize, y + squareHSize)
171-
.min(Comparator.comparing(e -> distanceProvider.distance(e.getKey().x, e.getKey().y, x, y)))
172-
.map(Entry::getValue);
189+
.min(Comparator.comparing(e -> distanceProvider.distance(e.getKey().x, e.getKey().y, x, y)))
190+
.map(Entry::getValue);
191+
}
192+
193+
/**
194+
* Returns the closest unit to the given position matching the given criteria or {@link
195+
* Optional#empty()} if no units are present.
196+
*/
197+
public Optional<U> closestTo(int x, int y, Predicate<U> criteria) {
198+
PositionAndId query = new PositionAndId(-1, x, y);
199+
int squareHSize = Integer.MAX_VALUE;
200+
Entry<PositionAndId, U> lowerBound = map.lowerEntry(query);
201+
while (lowerBound != null && !criteria.test(lowerBound.getValue())) {
202+
lowerBound = map.lowerEntry(lowerBound.getKey());
203+
}
204+
if (lowerBound != null) {
205+
int lx = lowerBound.getKey().x;
206+
int ly = lowerBound.getKey().y;
207+
squareHSize = max(abs(lx - x), abs(ly - y));
208+
}
209+
Entry<PositionAndId, U> higherBound = map.higherEntry(query);
210+
while (higherBound != null && !criteria.test(higherBound.getValue())) {
211+
higherBound = map.higherEntry(higherBound.getKey());
212+
}
213+
if (higherBound != null) {
214+
int hx = higherBound.getKey().x;
215+
int hy = higherBound.getKey().y;
216+
squareHSize = min(squareHSize, max(abs(hx - x), abs(hy - y)));
217+
}
218+
if (squareHSize == Integer.MAX_VALUE) {
219+
return Optional.empty();
220+
}
221+
return subMapOfArea(
222+
x - squareHSize, y - squareHSize, x + squareHSize, y + squareHSize, criteria)
223+
.min(Comparator.comparing(e -> distanceProvider.distance(e.getKey().x, e.getKey().y, x, y)))
224+
.map(Entry::getValue);
173225
}
174226

175227
@Override

src/test/java/org/bk/ass/query/UnitFinderTest.java

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
package org.bk.ass.query;
22

3-
import static org.assertj.core.api.Assertions.assertThat;
3+
import org.junit.jupiter.api.Test;
44

55
import java.util.Arrays;
66
import java.util.Collection;
77
import java.util.Collections;
8+
import java.util.Objects;
89
import java.util.function.Function;
9-
import org.junit.jupiter.api.Test;
10+
11+
import static org.assertj.core.api.Assertions.assertThat;
1012

1113
class UnitFinderTest {
1214

1315
@Test
14-
public void shouldNotDieIfEmpty() {
16+
void shouldNotDieIfEmpty() {
1517
// GIVEN
1618
UnitFinder<Object> finder =
1719
new UnitFinder<>(
@@ -30,7 +32,7 @@ public void shouldNotDieIfEmpty() {
3032
}
3133

3234
@Test
33-
public void shouldFindClosest() {
35+
void shouldFindClosest() {
3436
// GIVEN
3537
UnitFinder<PositionAndId> finder =
3638
new UnitFinder<>(
@@ -45,7 +47,43 @@ public void shouldFindClosest() {
4547
}
4648

4749
@Test
48-
public void shouldFindAllInArea() {
50+
void shouldFindClosestWithCriteria() {
51+
// GIVEN
52+
UnitFinder<Unit> finder =
53+
new UnitFinder<>(
54+
Arrays.asList(
55+
new Unit(-1, new PositionAndId(-1, -30, 0)),
56+
new Unit(0, new PositionAndId(0, 0, -30)),
57+
new Unit(1, new PositionAndId(1, 30, 0))),
58+
u -> u.positionAndId);
59+
60+
// WHEN
61+
Unit closest = finder.closestTo(0, 0, u -> u.id > 0).get();
62+
63+
// THEN
64+
assertThat(closest).isEqualTo(new Unit(1, new PositionAndId(1, 30, 0)));
65+
}
66+
67+
@Test
68+
void shouldFindDifferentItemIfCriteriaFails() {
69+
// GIVEN
70+
UnitFinder<Unit> finder =
71+
new UnitFinder<>(
72+
Arrays.asList(
73+
new Unit(-1, new PositionAndId(-1, -30, 0)),
74+
new Unit(0, new PositionAndId(0, 0, -30)),
75+
new Unit(1, new PositionAndId(1, 30, 0))),
76+
u -> u.positionAndId);
77+
78+
// WHEN
79+
Unit closest = finder.closestTo(30, 0, u -> u.id < 0).get();
80+
81+
// THEN
82+
assertThat(closest).isEqualTo(new Unit(-1, new PositionAndId(-1, -30, 0)));
83+
}
84+
85+
@Test
86+
void shouldFindAllInArea() {
4987
// GIVEN
5088
UnitFinder<PositionAndId> finder =
5189
new UnitFinder<>(
@@ -67,7 +105,7 @@ public void shouldFindAllInArea() {
67105
}
68106

69107
@Test
70-
public void shouldFindAllInRadius() {
108+
void shouldFindAllInRadius() {
71109
// GIVEN
72110
UnitFinder<PositionAndId> finder =
73111
new UnitFinder<>(
@@ -88,7 +126,7 @@ public void shouldFindAllInRadius() {
88126
}
89127

90128
@Test
91-
public void shouldFindAllInRadiusOfUnit() {
129+
void shouldFindAllInRadiusOfUnit() {
92130
// GIVEN
93131
PositionAndId unit = new PositionAndId(-1, 0, 0);
94132
UnitFinder<PositionAndId> finder =
@@ -108,4 +146,35 @@ public void shouldFindAllInRadiusOfUnit() {
108146
// THEN
109147
assertThat(result).hasSize(5);
110148
}
149+
150+
private static class Unit {
151+
public final int id;
152+
public final PositionAndId positionAndId;
153+
154+
private Unit(int id, PositionAndId positionAndId) {
155+
this.id = id;
156+
this.positionAndId = positionAndId;
157+
}
158+
159+
@Override
160+
public boolean equals(Object o) {
161+
if (this == o) return true;
162+
if (o == null || getClass() != o.getClass()) return false;
163+
Unit unit = (Unit) o;
164+
return id == unit.id && Objects.equals(positionAndId, unit.positionAndId);
165+
}
166+
167+
@Override
168+
public int hashCode() {
169+
return Objects.hash(id, positionAndId);
170+
}
171+
172+
@Override
173+
public String toString() {
174+
return "Unit{" +
175+
"id=" + id +
176+
", positionAndId=" + positionAndId +
177+
'}';
178+
}
179+
}
111180
}

0 commit comments

Comments
 (0)