Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Igor Urisman authored and Igor Urisman committed May 23, 2024
1 parent 1acd25d commit 6f93638
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 2 deletions.
2 changes: 1 addition & 1 deletion bin/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Build server SPI standard library.
#

version=1.3.0
version=1.3.1
root_dir=$(cd $(dirname $0)/..; pwd)

cd $root_dir
Expand Down
Binary file removed lib/variant-spi-1.0.1-RC1.jar
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<variant.version>1.3.0</variant.version>
<variant.version>1.3.1</variant.version>

</properties>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.variant.spi.stdlib.lifecycle;

import com.variant.server.boot.ServerExceptionInternal;
import com.variant.server.spi.TargetingLifecycleEvent;
import com.variant.server.spi.TargetingLifecycleHook;
import com.variant.share.schema.State;
import com.variant.share.schema.Variation;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;

import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.stream.Collectors;

/**
* Targets randomly, honoring weights, which must be supplied in experience properties like so:
* <pre>
* ...
* experiences:
* - name: foo
* properties:
* weight: 1
* - name: bar
* weight: 1.5
* - name: baz
* weight: 0.75
* * </pre>
* By default, looks for the <code>weight</code> experience property, unless overridden in the
* <code>init</code> key, like so (variation and state params are cas-sensitive):
* <pre>
* hooks:
* - class: com.variant.spi.stdlib.lifecycle.WeightedRandomTargetingHook
* init:
* key: Weight
* </pre>
*/
public class WeightedRandomTargetingHook implements TargetingLifecycleHook {

final private String propName;

public WeightedRandomTargetingHook() {
propName = "weight";
}
public WeightedRandomTargetingHook(Node node) {
this.propName = ((MappingNode)node).getValue().stream()
.filter(nt -> ((ScalarNode)nt.getKeyNode()).getValue().equals("key"))
.map(nt -> ((ScalarNode)nt.getValueNode()).getValue())
.findAny()
.orElseThrow(() -> new RuntimeException("Unable to parse init " + node));
}
private static Random rand = new Random();

@Override
public Optional<Variation.Experience> post(TargetingLifecycleEvent event) {

Variation var = event.getVariation();
State state = event.getState();
List<Variation.Experience> definedExperiences = var.getExperiences().stream()
.filter(e -> e.isDefinedOn(state))
.toList();
if (definedExperiences.isEmpty()) {
throw new RuntimeException(
String.format("No experiences in variation [%s] are defined on state [%s]", var.getName(), state.getName()));
}
double weightSum = definedExperiences.stream()
.map(e -> Double.parseDouble(e.getParameters().get(propName)))
.reduce(0D, Double::sum);

double randVal = rand.nextDouble() * weightSum;
weightSum = 0;
for (Variation.Experience e: definedExperiences) {
weightSum += Double.parseDouble(e.getParameters().get(propName));
if (randVal < weightSum) {
return Optional.of(e);
}
}
// Should never get here.
throw new RuntimeException("Unexpected state");
}

}

0 comments on commit 6f93638

Please sign in to comment.