Fixes questions marked as incorrect, improves result view

This commit is contained in:
2025-10-02 18:15:04 +02:00
parent d2da811868
commit 5914e19ae1
5 changed files with 70 additions and 38 deletions

View File

@@ -1,13 +1,18 @@
package ch.gtache.fro.practice.gui.fx;
import ch.gtache.fro.BirdTranslator;
import ch.gtache.fro.practice.PracticeQuestion;
import ch.gtache.fro.practice.gui.PracticeResultController;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.util.Callback;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
/**
* FX implementation of {@link PracticeResultController}
@@ -16,28 +21,33 @@ import java.util.Objects;
public final class FXPracticeResultController implements PracticeResultController {
private final FXPracticeResultModel model;
private final BirdTranslator translator;
@FXML
private Label successNumberLabel;
@FXML
private Label failureNumberLabel;
@FXML
private Label successListLabel;
private ListView<PracticeQuestion> successList;
@FXML
private Label failureListLabel;
private ListView<PracticeQuestion> failureList;
@FXML
private Button confirmButton;
@Inject
FXPracticeResultController(final FXPracticeResultModel model) {
this.model = Objects.requireNonNull(model);
FXPracticeResultController(final FXPracticeResultModel model,
final BirdTranslator translator) {
this.model = requireNonNull(model);
this.translator = requireNonNull(translator);
}
@FXML
private void initialize() {
successNumberLabel.textProperty().bind(model.successLabelProperty());
failureNumberLabel.textProperty().bind(model.failureLabelProperty());
successListLabel.textProperty().bind(model.successListLabelProperty());
failureListLabel.textProperty().bind(model.failureListLabelProperty());
successList.setItems(model.successList());
failureList.setItems(model.failureList());
successList.setCellFactory(new QuestionListCellFactory());
failureList.setCellFactory(new QuestionListCellFactory());
}
@FXML
@@ -54,4 +64,23 @@ public final class FXPracticeResultController implements PracticeResultControlle
public FXPracticeResultModel model() {
return model;
}
private class QuestionListCellFactory implements Callback<ListView<PracticeQuestion>, ListCell<PracticeQuestion>> {
@Override
public ListCell<PracticeQuestion> call(final ListView<PracticeQuestion> param) {
return new PracticeQuestionListCell();
}
private class PracticeQuestionListCell extends ListCell<PracticeQuestion> {
@Override
protected void updateItem(final PracticeQuestion item, final boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
} else {
setText(translator.translateAsync(item.bird()).join());
}
}
}
}
}

View File

@@ -1,6 +1,6 @@
package ch.gtache.fro.practice.gui.fx;
import ch.gtache.fro.BirdTranslator;
import ch.gtache.fro.practice.PracticeQuestion;
import ch.gtache.fro.practice.PracticeResult;
import ch.gtache.fro.practice.gui.PracticeResultModel;
import jakarta.inject.Inject;
@@ -9,8 +9,8 @@ import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleObjectProperty;
import java.util.stream.Collectors;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
/**
* FX implementation of {@link PracticeResultModel}
@@ -21,20 +21,27 @@ public final class FXPracticeResultModel implements PracticeResultModel {
private final ObjectProperty<PracticeResult> practiceResult;
private final ReadOnlyStringWrapper successLabel;
private final ReadOnlyStringWrapper failureLabel;
private final ReadOnlyStringWrapper successListLabel;
private final ReadOnlyStringWrapper failureListLabel;
private final ObservableList<PracticeQuestion> successList;
private final ObservableList<PracticeQuestion> failureList;
@Inject
FXPracticeResultModel(final BirdTranslator translator) {
FXPracticeResultModel() {
this.practiceResult = new SimpleObjectProperty<>();
this.successLabel = new ReadOnlyStringWrapper();
this.failureLabel = new ReadOnlyStringWrapper();
this.successListLabel = new ReadOnlyStringWrapper();
this.failureListLabel = new ReadOnlyStringWrapper();
this.successList = FXCollections.observableArrayList();
this.failureList = FXCollections.observableArrayList();
successLabel.bind(resultProperty().map(r -> r.correctQuestionsCount() + "/" + r.totalQuestions()));
failureLabel.bind(resultProperty().map(r -> r.failedQuestionsCount() + "/" + r.totalQuestions()));
successListLabel.bind(resultProperty().map(r -> r.correctQuestions().stream().map(pq -> translator.translateAsync(pq.bird()).join()).collect(Collectors.joining(", "))));
failureListLabel.bind(resultProperty().map(r -> r.failedQuestions().stream().map(pq -> translator.translateAsync(pq.bird()).join()).collect(Collectors.joining(", "))));
practiceResult.addListener((_, _, newValue) -> {
if (newValue == null) {
successList.clear();
failureList.clear();
} else {
successList.setAll(newValue.correctQuestions());
failureList.setAll(newValue.failedQuestions());
}
});
}
@Override
@@ -70,20 +77,12 @@ public final class FXPracticeResultModel implements PracticeResultModel {
}
@Override
public String successListLabel() {
return successListLabel.get();
}
ReadOnlyStringProperty successListLabelProperty() {
return successListLabel.getReadOnlyProperty();
public ObservableList<PracticeQuestion> successList() {
return successList;
}
@Override
public String failureListLabel() {
return failureListLabel.get();
}
ReadOnlyStringProperty failureListLabelProperty() {
return failureListLabel.getReadOnlyProperty();
public ObservableList<PracticeQuestion> failureList() {
return failureList;
}
}

View File

@@ -3,6 +3,7 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.*?>
<GridPane hgap="10.0" vgap="10.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/24.0.1"
fx:controller="ch.gtache.fro.practice.gui.fx.FXPracticeResultController">
@@ -23,8 +24,8 @@
<Label text="%practice.result.failure.label" GridPane.rowIndex="2"/>
<Label fx:id="successNumberLabel" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<Label fx:id="failureNumberLabel" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
<Label fx:id="successListLabel" GridPane.columnIndex="2" GridPane.rowIndex="1"/>
<Label fx:id="failureListLabel" GridPane.columnIndex="2" GridPane.rowIndex="2"/>
<ListView fx:id="successList" GridPane.columnIndex="2" GridPane.rowIndex="1"/>
<ListView fx:id="failureList" GridPane.columnIndex="2" GridPane.rowIndex="2"/>
<Button fx:id="confirmButton" mnemonicParsing="false" onAction="#confirmPressed"
text="%practice.result.confirm.button.label" GridPane.columnSpan="2147483647"
GridPane.halignment="CENTER" GridPane.rowIndex="3"/>