Skip to content

Commit

Permalink
Closes #2992 Game, map, mod reviews average score filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
bukajsytlos committed Jul 18, 2023
1 parent 6a1596c commit d4d2f15
Show file tree
Hide file tree
Showing 11 changed files with 86 additions and 20 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ dependencies {

implementation("io.projectreactor.addons:reactor-extra")

def commonsVersion = "f5a7832399"
def commonsVersion = "4a3facc824"

implementation("com.github.FAForever.faf-java-commons:faf-commons-data:${commonsVersion}") {
exclude module: 'guava'
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/com/faforever/client/domain/ReviewsSummaryBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public abstract class ReviewsSummaryBean {
FloatProperty positive = new SimpleFloatProperty();
FloatProperty negative = new SimpleFloatProperty();
FloatProperty score = new SimpleFloatProperty();
FloatProperty averageScore = new SimpleFloatProperty();
IntegerProperty numReviews = new SimpleIntegerProperty();
FloatProperty lowerBound = new SimpleFloatProperty();

Expand Down Expand Up @@ -64,6 +65,18 @@ public void setScore(float score) {
this.score.set(score);
}

public FloatProperty averageScoreProperty() {
return averageScore;
}

public float getAverageScore() {
return averageScore.get();
}

public void setAverageScore(float averageScore) {
this.averageScore.set(averageScore);
}

public FloatProperty scoreProperty() {
return score;
}
Expand Down
26 changes: 21 additions & 5 deletions src/main/java/com/faforever/client/fx/JavaFxUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,13 @@

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.math.RoundingMode;
import java.nio.file.Path;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

Expand Down Expand Up @@ -444,6 +449,13 @@ public static void bindManagedToVisible(Node... nodes) {

public static void bindTextFieldAndRangeSlider(TextField lowValueTextField, TextField highValueTextField,
RangeSlider rangeSlider) {
DecimalFormat numberFormat = (DecimalFormat) DecimalFormat.getInstance();
numberFormat.setMaximumFractionDigits(0);
bindTextFieldAndRangeSlider(lowValueTextField, highValueTextField, rangeSlider, numberFormat);
}

public static void bindTextFieldAndRangeSlider(TextField lowValueTextField, TextField highValueTextField,
RangeSlider rangeSlider, DecimalFormat format) {
Map.of(
lowValueTextField, Pair.of(rangeSlider.lowValueProperty(), rangeSlider.getMin()),
highValueTextField, Pair.of(rangeSlider.highValueProperty(), rangeSlider.getMax())
Expand All @@ -454,18 +466,22 @@ public static void bindTextFieldAndRangeSlider(TextField lowValueTextField, Text
@Override
public String toString(Number number) {
if (!number.equals(value)) {
return String.valueOf(number.intValue());
return format.format(number);
} else {
return "";
}
}

@Override
public Number fromString(String string) {
if (NumberUtils.isParsable(string)) {
return Double.parseDouble(string);
} else {
if (!string.equals("-") && !string.equals(".")) {
String decimalSeparator = Character.toString(format.getDecimalFormatSymbols().getDecimalSeparator());
try {
Number number = format.parse(string);
String decimalSeparatorSuffix = string.endsWith(decimalSeparator) && format.getMaximumFractionDigits() > 0 ? decimalSeparator : "";
textField.setText(format.format(number) + decimalSeparatorSuffix);
return number;
} catch (ParseException e) {
if (!string.equals("-") && !string.equals(decimalSeparator)) {
textField.setText("");
}
return value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Random;
import java.util.function.Function;

@Slf4j
@Component
Expand Down Expand Up @@ -96,7 +97,8 @@ protected void initSearchController() {

searchController.addCategoryFilter("latestVersion.width", i18n.get("map.width"), mapSizeMap);
searchController.addCategoryFilter("latestVersion.height", i18n.get("map.height"), mapSizeMap);
searchController.addRangeFilter("latestVersion.maxPlayers", i18n.get("map.maxPlayers"), 0, 16, 1, Double::intValue);
searchController.addRangeFilter("latestVersion.maxPlayers", i18n.get("map.maxPlayers"), 0, 16, 1, 0);
searchController.addRangeFilter("reviewsSummary.averageScore", i18n.get("reviews.averageScore"), 0, 5, 0.5, 1);
searchController.addToggleFilter("latestVersion.ranked", i18n.get("map.onlyRanked"), "true");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ protected void initSearchController() {
searchController.addTextFilter("author", i18n.get("mod.author"), false);
searchController.addDateRangeFilter("latestVersion.updateTime", i18n.get("mod.uploadedDateTime"), 0);

searchController.addRangeFilter("reviewsSummary.averageScore", i18n.get("reviews.averageScore"), 0, 5, 0.5, 1);

searchController.addBinaryFilter("latestVersion.type", i18n.get("mod.type"),
ModType.UI.toString(), ModType.SIM.toString(), i18n.get("modType.ui"), i18n.get("modType.sim"));
searchController.addToggleFilter("latestVersion.ranked", i18n.get("mod.onlyRanked"), "true");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@
import javafx.scene.control.MenuButton;
import javafx.scene.control.TextField;
import lombok.Data;
import lombok.SneakyThrows;
import org.controlsfx.control.RangeSlider;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
Expand All @@ -35,26 +40,31 @@ public class RangeFilterController implements FilterNodeController {

private String propertyName;
private Function<Double, ? extends Number> valueTransform;
private int numberOfFractionDigits;
private DecimalFormat numberFormat;

public void initialize() {
JavaFxUtil.bindManagedToVisible(menu);
rangeSlider.setShowTickMarks(true);
rangeSlider.setShowTickLabels(true);
rangeSlider.setMinorTickCount(0);
valueTransform = (value) -> value;
valueTransform = Function.identity();
}

@SneakyThrows
public Optional<List<Condition>> getCondition() {
List<Condition> conditions = new ArrayList<>();
if (!lowValue.getText().isBlank() && rangeSlider.getLowValue() > rangeSlider.getMin()) {
double lowValueValue = numberFormat.parse(numberFormat.format(rangeSlider.getLowValue())).doubleValue();
if (!lowValue.getText().isBlank() && lowValueValue > rangeSlider.getMin()) {
QBuilder qBuilderLow = new QBuilder<>();
DoubleProperty propertyLow = qBuilderLow.doubleNum(propertyName);
conditions.add(propertyLow.gte(valueTransform.apply(rangeSlider.getLowValue())));
conditions.add(propertyLow.gte(valueTransform.apply(lowValueValue)));
}
if (!highValue.getText().isBlank() && rangeSlider.getHighValue() < rangeSlider.getMax()) {
double highValueValue = numberFormat.parse(numberFormat.format(rangeSlider.getHighValue())).doubleValue();
if (!highValue.getText().isBlank() && highValueValue < rangeSlider.getMax()) {
QBuilder qBuilderHigh = new QBuilder<>();
DoubleProperty propertyHigh = qBuilderHigh.doubleNum(propertyName);
conditions.add(propertyHigh.lte(valueTransform.apply(rangeSlider.getHighValue())));
conditions.add(propertyHigh.lte(valueTransform.apply(highValueValue)));
}
if (!conditions.isEmpty()) {
if (!menu.getStyleClass().contains("query-filter-selected")) {
Expand Down Expand Up @@ -92,8 +102,6 @@ public void setMinMax(double min, double max) {
rangeSlider.setMax(max);
rangeSlider.setHighValue(max);
highValue.setText("");

JavaFxUtil.bindTextFieldAndRangeSlider(lowValue, highValue, rangeSlider);
}

public void setIncrement(double increment) {
Expand All @@ -112,6 +120,18 @@ public void setValueTransform(Function<Double, ? extends Number> valueTransform)
this.valueTransform = valueTransform;
}

public void setNumberOfFractionDigits(int numberOfFractionDigits) {
this.numberOfFractionDigits = numberOfFractionDigits;
}

public void bind() {
numberFormat = (DecimalFormat) DecimalFormat.getInstance();
numberFormat.setRoundingMode(RoundingMode.HALF_UP);
numberFormat.setMinimumFractionDigits(0);
numberFormat.setMaximumFractionDigits(numberOfFractionDigits);
JavaFxUtil.bindTextFieldAndRangeSlider(lowValue, highValue, rangeSlider, numberFormat);
}

@Override
public Node getRoot() {
return menu;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class SearchablePropertyMappings {
.put("mapVersion.height", new Property("map.heightPixels", false))
.put("mapVersion.folderName", new Property("game.map.folderName", false))
.put("mapVersion.map.author.login", new Property("game.map.author", false))
.put("reviewsSummary.averageScore", new Property("reviews.averageScore", true))

.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,12 @@ protected void initSearchController() {

//TODO: Use rating rather than estimated mean with an assumed deviation of 300 when that is available
searchController.addRangeFilter("playerStats.ratingChanges.meanBefore", i18n.get("game.rating"),
MIN_RATING, MAX_RATING, 100, (value) -> value + 300);
MIN_RATING, MAX_RATING, 100, 0, value -> value + 300);

searchController.addRangeFilter("reviewsSummary.averageScore", i18n.get("reviews.averageScore"),0, 5, 0.5, 1);

searchController.addDateRangeFilter("endTime", i18n.get("game.date"), 1);
searchController.addRangeFilter("replayTicks", i18n.get("game.duration"), 0, 60, 1, value -> (int) (value*60*10));
searchController.addRangeFilter("replayTicks", i18n.get("game.duration"), 0, 60, 6, 0, value -> (int) (value*60*10));
searchController.addToggleFilter("validity", i18n.get("game.onlyRanked"), "VALID");

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.text.NumberFormat;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -303,18 +304,25 @@ public CategoryFilterController addCategoryFilter(String propertyName, String ti
return categoryFilterController;
}

public RangeFilterController addRangeFilter(String propertyName, String title, double min, double max,
double tickUnit, Function<Double, ? extends Number> valueTransform) {
public void addRangeFilter(String propertyName, String title, double min, double max,
double tickUnit, int numberOfFractionDigits) {
addRangeFilter(propertyName, title, min, max, tickUnit, numberOfFractionDigits, Function.identity());
}

public void addRangeFilter(String propertyName, String title, double min, double max,
double tickUnit, int numberOfFractionDigits,
Function<Double, ? extends Number> valueTransform) {
RangeFilterController rangeFilterController = uiService.loadFxml("theme/vault/search/rangeFilter.fxml");
rangeFilterController.setTitle(title);
rangeFilterController.setPropertyName(propertyName);
rangeFilterController.setMinMax(min, max);
rangeFilterController.setIncrement(tickUnit);
rangeFilterController.setTickUnit(tickUnit);
rangeFilterController.setSnapToTicks(true);
rangeFilterController.setNumberOfFractionDigits(numberOfFractionDigits);
rangeFilterController.setValueTransform(valueTransform);
rangeFilterController.bind();
addFilterNode(rangeFilterController);
return rangeFilterController;
}

public DateRangeFilterController addDateRangeFilter(String propertyName, String title, int initialYearsBefore) {
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,7 @@ game.create.generatedMap2 = Generate the map
settings.fa.allowIpv6 = Allow the ICE adapter to use IPv6
settings.fa.allowIpv6.description = Ipv6 causes connection issues for some players. Turn this on if you do not have any IPv6 issues with connections
home.directory.warning.cyrillic = Warning\: Cyrillic characters in the home directory path may cause problems. Please, avoid using them.
reviews.averageScore = Average reviews score
ignoreWarning = Ignore warning
replay.replayRunning = Replay could not be started because another replay is already running.
teammatchmaking.queue.tmm3v3 = 3v3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public void setUp() throws Exception {
instance.setSnapToTicks(true);
instance.setTickUnit(increment);
instance.setValueTransform((value) -> value);
instance.bind();
}

@Test
Expand Down Expand Up @@ -88,7 +89,7 @@ public void testAddListener() throws Exception {
instance.rangeSlider.setHighValue(90.0);
instance.lowValue.setText("20");
instance.highValue.setText("80");
verify(queryListener, times(12)).invalidated(any());
verify(queryListener, times(20)).invalidated(any());
}

@Test
Expand Down

0 comments on commit d4d2f15

Please sign in to comment.