Skip to content

Commit

Permalink
fix colorOn (#122)
Browse files Browse the repository at this point in the history
* fix colorOn
  • Loading branch information
twonirwana authored Sep 2, 2024
1 parent 42d90d4 commit 0b8c61e
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 45 deletions.
2 changes: 1 addition & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ All functions are case insensitiv.
|sort desc |`desc(<expression1>, <expression2> ...)` |`desc(4d6)` |sorts all elements descending of one or more inner expressions. Text is compared alphabetically
|cancel |`cancel(<expression>, <listA>, <listB>)` |`cancel(8d10, 10, 1)` |the elements of listA and listB (can also be single elements) cancel each other and remove each other from the result.
|replace |`replace(<expression>, <find>, <replace> ...)` |`replace(8d10, [9/10], 'bonus')` | each element in `<expression>` that matches on of the elements in `<find>` will be replaced with the elements in `<replace>`. `<replace>` can be an empty list `[]` or literal `''` and thereby removing the found elements. It is possible to add multiple <find>/<replace> pairs to replace different elements in one replace. If the <replace> expression contains dice then they will only be rolled on a matching find element and for each matching element again.
|color on |`colorOn(<expression>, <in>, <color> ...)` |`replace(8d10, [9/10], 'red')` | each element in `<expression>` that is in the elements in `in` will be get the color `<color>`. `<color>` can be an empty list `[]` or literal `''` and thereby removing the current color. It is possible to add multiple <in>/<color> pairs to set different color for different values. If the <color> expression contains dice then they will only be rolled on a matching in element and for each matching in again.
|color on |`colorOn(<expression>, <in>, <color> ...)` |`replace(8d10, [9/10], 'red')` | each element in `<expression>` that is in the elements in `in` will be get the color `<color>`. `<color>` can be an empty list `[]` or literal `''` and thereby removing the current color. It is possible to add multiple <in>/<color> pairs to set different color for different values. If the <color> expression contains dice then they will be rolled once and used for all elements.
|explode |`exp(<roll>,<rerollOnList>,<numberOfRerolls>` |`exp(d[1/2/3],[2/3])` or `exp(d[1/2/3],[2/3], 2)` | Rerolls the `<roll>` expression if any of its result elements are in the elements of `<rerollOnList>` and returns the original result and all reroll results. If `<roll>` contain more then one die then all are rerolled, even if only on result of one die matches the reroll list. `<numberOfRerolls>` define the maximum number of rerolls bevor the function stops with rerolls and returns the current result. `<numberOfRerolls>` must be a number between 0 and 100. If `<numberOfRerolls>` is not provided as argument then 100 will be used.
|if |`if(<boolean>,<true>,<false>)` |`if(1d6=?6,'six','not six')` or `if(1d6=?6,'six')` or `val('$r',1d6), if('$r'=?1,'one','$r'=?2,'two','else')` |if `<boolean>` equal true then return the `<true>` expression or else the `<false>` expression. The `<false>` expression is optional, if it is missing and `<boolean>` is `false` then the result empty. It is possible to add more than `<boolean>,<true>` pair in the function, the result will be the `<true>` of the first true `<boolean>`, coming from left. All <boolean> must be non-empty and contain only on element (therefor can't contain only `val`). `val` are will only set in the first <true>. Use the following structure to use `if` to set different value in a `val`: `if(1d6>?4, val('$a',10), val('$a',-10))`, this will set '$a' to 10 if the 1d6 roll is bigger than 4 and to -10 otherwise.
|group count |`groupC(<expression1>, <expression2> ...)` |`groupC(20d6)` | counts all elements of with the same value and provides the results as list in the format of `<count>x<value>`
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/de/janno/evaluator/dice/RandomElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ public RandomElement copyWithTagAndColor(@NonNull String color) {

public String toString() {
if (randomSelectedFrom != null) {
return "%s=%s∈%s".formatted(dieId, rollElement.toString(), randomSelectedFrom);
return "%s=%s∈%s".formatted(dieId, rollElement.toStringWithColorAndTag(), randomSelectedFrom);
} else {
return "%s=%s∈[%d...%d]".formatted(dieId, rollElement.toString(), minInc, maxInc);
return "%s=%s∈[%d...%d]".formatted(dieId, rollElement.toStringWithColorAndTag(), minInc, maxInc);
}
}

Expand Down
29 changes: 21 additions & 8 deletions src/main/java/de/janno/evaluator/dice/function/ColorOn.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,33 +29,46 @@ public ColorOn(int maxNumberOfElements, boolean keepChildrenRolls) {
}
ImmutableList.Builder<Roll> allRolls = ImmutableList.<Roll>builder().addAll(input.get());
ImmutableList<RollElement> inputRollElements = input.get().stream().flatMap(r -> r.getElements().stream()).collect(ImmutableList.toImmutableList());
for (int i = 1; i < arguments.size() - 1; i = i + 2) {
ImmutableList<RandomElement> inputRandomElements = input.get().stream().flatMap(r -> r.getRandomElementsInRoll().stream()).collect(ImmutableList.toImmutableList());

for (int i = 1; i < arguments.size() - 1; i = i + 2) {
Optional<List<Roll>> inRolls = arguments.get(i).extendRoll(rollContext);
checkContainsSingleRoll(expressionPosition, inRolls, i + 1);
final Roll inRoll = inRolls.orElseThrow().getFirst();
allRolls.add(inRoll);
Optional<List<Roll>> colorRolls = arguments.get(i + 1).extendRoll(rollContext);
checkContainsSingleRoll(expressionPosition, colorRolls, i + 2);
Roll colorRoll = colorRolls.orElseThrow().getFirst();
checkContainsNoOrSingleElement(expressionPosition, colorRoll, "%d argument".formatted(i + 2));
final String color = colorRoll.asSingleValue().orElse(RollElement.NO_COLOR);

ImmutableList.Builder<RollElement> currentIterationElements = ImmutableList.builder();
for (RollElement rollElement : inputRollElements) {
if (inRoll.isElementsContainsElementWithValueAndTag(rollElement)) {
Optional<List<Roll>> colorRolls = arguments.get(i + 1).extendRoll(rollContext);
checkContainsSingleRoll(expressionPosition, colorRolls, i + 2);
Roll colorRoll = colorRolls.orElseThrow().getFirst();
checkContainsNoOrSingleElement(expressionPosition, colorRoll, "%d argument".formatted(i + 2));
final String color = colorRoll.asSingleValue().orElse(RollElement.NO_COLOR);
allRolls.add(colorRoll);
currentIterationElements.add(new RollElement(rollElement.getValue(), rollElement.getTag(), color));
} else {
currentIterationElements.add(rollElement);
}
}
inputRollElements = currentIterationElements.build();
ImmutableList.Builder<RandomElement> currentIterationRandomElements = ImmutableList.builder();

for (RandomElement randomElement : inputRandomElements) {
if (inRoll.isElementsContainsElementWithValueAndTag(randomElement.getRollElement())) {
currentIterationRandomElements.add(randomElement.copyWithTagAndColor(color));
} else {
currentIterationRandomElements.add(randomElement);
}
}
inputRandomElements = currentIterationRandomElements.build();
}

RandomElementsBuilder builder = RandomElementsBuilder.empty(rollContext);
builder.addRandomElements(inputRandomElements);

return Optional.of(ImmutableList.of(new Roll(toExpression(),
inputRollElements,
RandomElementsBuilder.fromRolls(allRolls.build(), rollContext),
builder.build(),
allRolls.build(),
expressionPosition,
maxNumberOfElements, keepChildrenRolls)));
Expand Down
32 changes: 15 additions & 17 deletions src/test/java/de/janno/evaluator/dice/DiceEvaluatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -701,11 +701,11 @@ private static Stream<Arguments> generateStringDiceDataWithRandomElements() {
Arguments.of("(d4)d!(d6)", List.of(2, 6, 6, 4, 3), "6, 4, 3", "[1de0i0r0=2∈[1...4], 4d!e0i0r0=6∈[1...6], 4d!e0i0r1=4∈[1...6], 4d!e0i1r0=3∈[1...6], 7de0i0r0=6∈[1...6]]"),
Arguments.of("(d4)d!!(d6)", List.of(2, 6, 6, 4, 3), "10, 3", "[1de0i0r0=2∈[1...4], 4d!!e0i0r0=6∈[1...6], 4d!!e0i0r1=4∈[1...6], 4d!!e0i1r0=3∈[1...6], 8de0i0r0=6∈[1...6]]"),

Arguments.of("d6 col 'red' ", List.of(), "6-c:red", "[0de0i0r0=6∈[1...6]]"),
Arguments.of("d6 col d6 ", List.of(), "6-c:6", "[0de0i0r0=6∈[1...6], 7de0i0r0=6∈[1...6]]"),
Arguments.of("d[a,b,c,d,e,f] col 'red'", List.of(), "f-c:red", "[0de0i0r0=f∈[a, b, c, d, e, f]]"),
Arguments.of("d!6 col 'red'", List.of(6, 3), "6-c:red, 3-c:red", "[0d!e0i0r0=6∈[1...6], 0d!e0i0r1=3∈[1...6]]"),
Arguments.of("d!!6 col 'red'", List.of(6, 3), "9-c:red", "[0d!!e0i0r0=6∈[1...6], 0d!!e0i0r1=3∈[1...6]]"),
Arguments.of("d6 col 'red' ", List.of(), "6-c:red", "[0de0i0r0=6-c:red∈[1...6]]"),
Arguments.of("d6 col d6 ", List.of(), "6-c:6", "[0de0i0r0=6-c:6∈[1...6], 7de0i0r0=6-c:6∈[1...6]]"),
Arguments.of("d[a,b,c,d,e,f] col 'red'", List.of(), "f-c:red", "[0de0i0r0=f-c:red∈[a, b, c, d, e, f]]"),
Arguments.of("d!6 col 'red'", List.of(6, 3), "6-c:red, 3-c:red", "[0d!e0i0r0=6-c:red∈[1...6], 0d!e0i0r1=3-c:red∈[1...6]]"),
Arguments.of("d!!6 col 'red'", List.of(6, 3), "9-c:red", "[0d!!e0i0r0=6-c:red∈[1...6], 0d!!e0i0r1=3-c:red∈[1...6]]"),

Arguments.of("d6 tag 'red' ", List.of(), "6-t:red", "[0de0i0r0=6∈[1...6]]"),
Arguments.of("d6 tag d6 ", List.of(), "6-t:6", "[0de0i0r0=6∈[1...6], 7de0i0r0=6∈[1...6]]"),
Expand Down Expand Up @@ -770,12 +770,12 @@ private static Stream<Arguments> generateStringDiceDataWithRandomElements() {
Arguments.of("val('$s',1), if(0=?1, '') + '$s'", List.of(), "1", "[]"),
Arguments.of("val('$s',1) if(0=?1, '') '$s'", List.of(), "1", "[]"),

Arguments.of("colorOn(3d6,[1/2],'white')", List.of(6, 2, 1), "6, 2-c:white, 1-c:white", "[9de0i0r0=6∈[1...6], 9de0i1r0=2∈[1...6], 9de0i2r0=1∈[1...6]]"),
Arguments.of("colorOn(3d6 col 'red', [1/2],'')", List.of(6, 2, 1), "6-c:red, 2, 1", "[9de0i0r0=6∈[1...6], 9de0i1r0=2∈[1...6], 9de0i2r0=1∈[1...6]]"),
Arguments.of("colorOn(3d6,[1/2],'white')", List.of(6, 2, 1), "6, 2-c:white, 1-c:white", "[9de0i0r0=6∈[1...6], 9de0i1r0=2-c:white∈[1...6], 9de0i2r0=1-c:white∈[1...6]]"),
Arguments.of("colorOn(3d6 col 'red', [1/2],'')", List.of(6, 2, 1), "6-c:red, 2, 1", "[9de0i0r0=6-c:red∈[1...6], 9de0i1r0=2∈[1...6], 9de0i2r0=1∈[1...6]]"),
Arguments.of("colorOn('',[1/2],'white')", List.of(), "", "[]"),
Arguments.of("colorOn(val('a',1),1,'white')", List.of(), "", "[]"),
Arguments.of("colorOn(3d6,[1/2],'white')", List.of(6, 5, 5), "6, 5, 5", "[9de0i0r0=6∈[1...6], 9de0i1r0=5∈[1...6], 9de0i2r0=5∈[1...6]]"),
Arguments.of("colorOn(4d6 col 'red',[1/2],'white', 3, 'black', 1, 'green')", List.of(4, 3, 2, 1), "4-c:red, 3-c:black, 2-c:white, 1-c:green", "[9de0i0r0=4∈[1...6], 9de0i1r0=3∈[1...6], 9de0i2r0=2∈[1...6], 9de0i3r0=1∈[1...6]]"),
Arguments.of("colorOn(4d6 col 'red',[1/2],'white', 3, 'black', 1, 'green')", List.of(4, 3, 2, 1), "4-c:red, 3-c:black, 2-c:white, 1-c:green", "[9de0i0r0=4-c:red∈[1...6], 9de0i1r0=3-c:black∈[1...6], 9de0i2r0=2-c:white∈[1...6], 9de0i3r0=1-c:green∈[1...6]]"),

//systems
Arguments.of(THE_ONE_RING, List.of(), " ⬟= ᚠ", "[34de0i0r0=12∈[1...12]]"),
Expand Down Expand Up @@ -834,19 +834,17 @@ void rollDiceExpressionWithRandomElements(String diceExpression, List<Integer> d

@Test
void debug() throws ExpressionException {
GivenNumberSupplier numberSupplier = new GivenNumberSupplier(3);
GivenNumberSupplier numberSupplier = new GivenNumberSupplier(3, 1, 2);
DiceEvaluator underTest = new DiceEvaluator(numberSupplier, 1000, 10_000, true);

// List<Roll> res = underTest.evaluate("3d!6+(2r(2d8))");
RollResult res = underTest.evaluate("if(d6>?3,d8) + 1");
RollResult res = underTest.evaluate("colorOn(3d6,[1/2],'white')");
System.out.println(res.getRolls().size());
res.getRolls().forEach(System.out::println);
res.getRolls().forEach(r -> System.out.println(r.getResultString()));
System.out.println(res);
System.out.println(res.getExpression());
System.out.println(res.getAllRandomElements().stream()
.map(re -> re.getDieId() + "=" + re.getRollElement().getValue())
.collect(Collectors.joining(", ")));
System.out.println(res.getAllRandomElements());
res.getRolls().forEach(r -> System.out.println(r.getRandomElementsInRoll()));
res.getRolls().forEach(r -> System.out.println(getRandomElementsString(r)));
System.out.println(res.getRolls().stream().flatMap(r -> r.getElements().stream()).map(RollElement::getValue).toList());
Expand Down Expand Up @@ -941,7 +939,7 @@ void valRandomElementsInCorrectOrder() throws ExpressionException {

assertThat(values(res.getRolls())).containsExactly("successes: 0, blue:1, purple_dark:1");
assertThat(res.getRolls().size()).isEqualTo(1);
assertThat(res.getGroupedRandomElements().toString()).isEqualTo("[[16de0i0r0=1∈[1...9]], [44de0i0r0=2∈[1...10]]]");
assertThat(res.getGroupedRandomElements().toString()).isEqualTo("[[16de0i0r0=1-c:blue∈[1...9]], [44de0i0r0=2-c:purple_dark∈[1...10]]]");
assertThat(getRandomElementsString(res.getRolls().getFirst())).isEqualTo("[1] [2]");
}

Expand Down Expand Up @@ -1525,7 +1523,7 @@ void toStringColorTest() throws ExpressionException {
RollResult res = underTest.evaluate("color(1d6,'red') + color(3d20,'blue')");

assertThat(res.getRolls()).hasSize(1);
assertThat(res.getGroupedRandomElements().toString()).isEqualTo("[[7de0i0r0=3∈[1...6]], [26de0i0r0=2∈[1...20], 26de0i1r0=1∈[1...20], 26de0i2r0=4∈[1...20]]]");
assertThat(res.getGroupedRandomElements().toString()).isEqualTo("[[7de0i0r0=3-c:red∈[1...6]], [26de0i0r0=2-c:blue∈[1...20], 26de0i1r0=1-c:blue∈[1...20], 26de0i2r0=4-c:blue∈[1...20]]]");
assertThat(getRandomElementsString(res.getRolls().getFirst())).isEqualTo("[3] [2, 1, 4]");
assertThat(res.getRolls().getFirst().getResultString()).isEqualTo("red:3, blue:2, blue:1, blue:4");
assertThat(res.getRolls().getFirst().getExpression()).isEqualTo("color(1d6,'red')+color(3d20,'blue')");
Expand Down Expand Up @@ -1553,7 +1551,7 @@ void colTest() throws ExpressionException {
RollResult res = underTest.evaluate("1d6 col 'red' + 3d20 col 'blue'");

assertThat(res.getRolls()).hasSize(1);
assertThat(res.getGroupedRandomElements().toString()).isEqualTo("[[1de0i0r0=3∈[1...6]], [18de0i0r0=2∈[1...20], 18de0i1r0=1∈[1...20], 18de0i2r0=4∈[1...20]]]");
assertThat(res.getGroupedRandomElements().toString()).isEqualTo("[[1de0i0r0=3-c:red∈[1...6]], [18de0i0r0=2-c:blue∈[1...20], 18de0i1r0=1-c:blue∈[1...20], 18de0i2r0=4-c:blue∈[1...20]]]");
assertThat(res.getRolls().getFirst().getRandomElementsInRoll().stream()
.map(RandomElement::getRollElement)
.map(RollElement::getColor)).containsExactly("red", "blue", "blue", "blue");
Expand Down Expand Up @@ -1590,7 +1588,7 @@ void toStringValColorTest() throws ExpressionException {

assertThat(res).hasSize(1);
assertThat(res.getFirst().getResultString()).isEqualTo("red:3, blue:3");
assertThat(res.getFirst().getRandomElementsInRoll().toString()).isEqualTo("[11de0i0r0=3∈[1...6]]");
assertThat(res.getFirst().getRandomElementsInRoll().toString()).isEqualTo("[11de0i0r0=3-c:blue∈[1...6]]");
assertThat(getRandomElementsString(res.getFirst())).isEqualTo("[3]");
assertThat(res.getFirst().getExpression()).isEqualTo("val('$r',1d6), color('$r','red')+color('$r','blue')");
}
Expand Down
Loading

0 comments on commit 0b8c61e

Please sign in to comment.