Fixes questions marked as incorrect, improves result view
This commit is contained in:
@@ -41,7 +41,7 @@ public class PracticeRunnerImpl implements PracticeRunner {
|
|||||||
if (run.currentQuestionIndex() < run.parameters().questionsNumber()) {
|
if (run.currentQuestionIndex() < run.parameters().questionsNumber()) {
|
||||||
final var question = questionGenerator.generate(run.parameters());
|
final var question = questionGenerator.generate(run.parameters());
|
||||||
final var currentQuestion = run.currentQuestion();
|
final var currentQuestion = run.currentQuestion();
|
||||||
if (currentQuestion.bird() == answer) {
|
if (currentQuestion.bird().equals(answer)) {
|
||||||
final var newCorrectQuestions = new ArrayList<>(run.correctQuestions());
|
final var newCorrectQuestions = new ArrayList<>(run.correctQuestions());
|
||||||
newCorrectQuestions.add(currentQuestion);
|
newCorrectQuestions.add(currentQuestion);
|
||||||
return new PracticeRunImpl(run.parameters(), run.currentQuestionIndex() + 1, question, newCorrectQuestions, run.failedQuestions());
|
return new PracticeRunImpl(run.parameters(), run.currentQuestionIndex() + 1, question, newCorrectQuestions, run.failedQuestions());
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package ch.gtache.fro.practice.gui;
|
package ch.gtache.fro.practice.gui;
|
||||||
|
|
||||||
import ch.gtache.fro.gui.Model;
|
import ch.gtache.fro.gui.Model;
|
||||||
|
import ch.gtache.fro.practice.PracticeQuestion;
|
||||||
import ch.gtache.fro.practice.PracticeResult;
|
import ch.gtache.fro.practice.PracticeResult;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model for the practice result view
|
* Model for the practice result view
|
||||||
*/
|
*/
|
||||||
@@ -37,16 +40,16 @@ public interface PracticeResultModel extends Model {
|
|||||||
String failureLabel();
|
String failureLabel();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The text for the label of successful guesses
|
* The list of successful questions
|
||||||
*
|
*
|
||||||
* @return The text
|
* @return The list of questions
|
||||||
*/
|
*/
|
||||||
String successListLabel();
|
List<PracticeQuestion> successList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The text for the label of failed guesses
|
* The list of failed questions
|
||||||
*
|
*
|
||||||
* @return The text
|
* @return The list of questions
|
||||||
*/
|
*/
|
||||||
String failureListLabel();
|
List<PracticeQuestion> failureList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
package ch.gtache.fro.practice.gui.fx;
|
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 ch.gtache.fro.practice.gui.PracticeResultController;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.inject.Singleton;
|
import jakarta.inject.Singleton;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.Label;
|
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}
|
* FX implementation of {@link PracticeResultController}
|
||||||
@@ -16,28 +21,33 @@ import java.util.Objects;
|
|||||||
public final class FXPracticeResultController implements PracticeResultController {
|
public final class FXPracticeResultController implements PracticeResultController {
|
||||||
|
|
||||||
private final FXPracticeResultModel model;
|
private final FXPracticeResultModel model;
|
||||||
|
private final BirdTranslator translator;
|
||||||
@FXML
|
@FXML
|
||||||
private Label successNumberLabel;
|
private Label successNumberLabel;
|
||||||
@FXML
|
@FXML
|
||||||
private Label failureNumberLabel;
|
private Label failureNumberLabel;
|
||||||
@FXML
|
@FXML
|
||||||
private Label successListLabel;
|
private ListView<PracticeQuestion> successList;
|
||||||
@FXML
|
@FXML
|
||||||
private Label failureListLabel;
|
private ListView<PracticeQuestion> failureList;
|
||||||
@FXML
|
@FXML
|
||||||
private Button confirmButton;
|
private Button confirmButton;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
FXPracticeResultController(final FXPracticeResultModel model) {
|
FXPracticeResultController(final FXPracticeResultModel model,
|
||||||
this.model = Objects.requireNonNull(model);
|
final BirdTranslator translator) {
|
||||||
|
this.model = requireNonNull(model);
|
||||||
|
this.translator = requireNonNull(translator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void initialize() {
|
private void initialize() {
|
||||||
successNumberLabel.textProperty().bind(model.successLabelProperty());
|
successNumberLabel.textProperty().bind(model.successLabelProperty());
|
||||||
failureNumberLabel.textProperty().bind(model.failureLabelProperty());
|
failureNumberLabel.textProperty().bind(model.failureLabelProperty());
|
||||||
successListLabel.textProperty().bind(model.successListLabelProperty());
|
successList.setItems(model.successList());
|
||||||
failureListLabel.textProperty().bind(model.failureListLabelProperty());
|
failureList.setItems(model.failureList());
|
||||||
|
successList.setCellFactory(new QuestionListCellFactory());
|
||||||
|
failureList.setCellFactory(new QuestionListCellFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@@ -54,4 +64,23 @@ public final class FXPracticeResultController implements PracticeResultControlle
|
|||||||
public FXPracticeResultModel model() {
|
public FXPracticeResultModel model() {
|
||||||
return 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package ch.gtache.fro.practice.gui.fx;
|
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.PracticeResult;
|
||||||
import ch.gtache.fro.practice.gui.PracticeResultModel;
|
import ch.gtache.fro.practice.gui.PracticeResultModel;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
@@ -9,8 +9,8 @@ import javafx.beans.property.ObjectProperty;
|
|||||||
import javafx.beans.property.ReadOnlyStringProperty;
|
import javafx.beans.property.ReadOnlyStringProperty;
|
||||||
import javafx.beans.property.ReadOnlyStringWrapper;
|
import javafx.beans.property.ReadOnlyStringWrapper;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
import java.util.stream.Collectors;
|
import javafx.collections.ObservableList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FX implementation of {@link PracticeResultModel}
|
* FX implementation of {@link PracticeResultModel}
|
||||||
@@ -21,20 +21,27 @@ public final class FXPracticeResultModel implements PracticeResultModel {
|
|||||||
private final ObjectProperty<PracticeResult> practiceResult;
|
private final ObjectProperty<PracticeResult> practiceResult;
|
||||||
private final ReadOnlyStringWrapper successLabel;
|
private final ReadOnlyStringWrapper successLabel;
|
||||||
private final ReadOnlyStringWrapper failureLabel;
|
private final ReadOnlyStringWrapper failureLabel;
|
||||||
private final ReadOnlyStringWrapper successListLabel;
|
private final ObservableList<PracticeQuestion> successList;
|
||||||
private final ReadOnlyStringWrapper failureListLabel;
|
private final ObservableList<PracticeQuestion> failureList;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
FXPracticeResultModel(final BirdTranslator translator) {
|
FXPracticeResultModel() {
|
||||||
this.practiceResult = new SimpleObjectProperty<>();
|
this.practiceResult = new SimpleObjectProperty<>();
|
||||||
this.successLabel = new ReadOnlyStringWrapper();
|
this.successLabel = new ReadOnlyStringWrapper();
|
||||||
this.failureLabel = new ReadOnlyStringWrapper();
|
this.failureLabel = new ReadOnlyStringWrapper();
|
||||||
this.successListLabel = new ReadOnlyStringWrapper();
|
this.successList = FXCollections.observableArrayList();
|
||||||
this.failureListLabel = new ReadOnlyStringWrapper();
|
this.failureList = FXCollections.observableArrayList();
|
||||||
successLabel.bind(resultProperty().map(r -> r.correctQuestionsCount() + "/" + r.totalQuestions()));
|
successLabel.bind(resultProperty().map(r -> r.correctQuestionsCount() + "/" + r.totalQuestions()));
|
||||||
failureLabel.bind(resultProperty().map(r -> r.failedQuestionsCount() + "/" + 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(", "))));
|
practiceResult.addListener((_, _, newValue) -> {
|
||||||
failureListLabel.bind(resultProperty().map(r -> r.failedQuestions().stream().map(pq -> translator.translateAsync(pq.bird()).join()).collect(Collectors.joining(", "))));
|
if (newValue == null) {
|
||||||
|
successList.clear();
|
||||||
|
failureList.clear();
|
||||||
|
} else {
|
||||||
|
successList.setAll(newValue.correctQuestions());
|
||||||
|
failureList.setAll(newValue.failedQuestions());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -70,20 +77,12 @@ public final class FXPracticeResultModel implements PracticeResultModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String successListLabel() {
|
public ObservableList<PracticeQuestion> successList() {
|
||||||
return successListLabel.get();
|
return successList;
|
||||||
}
|
|
||||||
|
|
||||||
ReadOnlyStringProperty successListLabelProperty() {
|
|
||||||
return successListLabel.getReadOnlyProperty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String failureListLabel() {
|
public ObservableList<PracticeQuestion> failureList() {
|
||||||
return failureListLabel.get();
|
return failureList;
|
||||||
}
|
|
||||||
|
|
||||||
ReadOnlyStringProperty failureListLabelProperty() {
|
|
||||||
return failureListLabel.getReadOnlyProperty();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.Button?>
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.control.ListView?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?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"
|
<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">
|
fx:controller="ch.gtache.fro.practice.gui.fx.FXPracticeResultController">
|
||||||
@@ -23,8 +24,8 @@
|
|||||||
<Label text="%practice.result.failure.label" GridPane.rowIndex="2"/>
|
<Label text="%practice.result.failure.label" GridPane.rowIndex="2"/>
|
||||||
<Label fx:id="successNumberLabel" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
|
<Label fx:id="successNumberLabel" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
|
||||||
<Label fx:id="failureNumberLabel" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
|
<Label fx:id="failureNumberLabel" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
|
||||||
<Label fx:id="successListLabel" GridPane.columnIndex="2" GridPane.rowIndex="1"/>
|
<ListView fx:id="successList" GridPane.columnIndex="2" GridPane.rowIndex="1"/>
|
||||||
<Label fx:id="failureListLabel" GridPane.columnIndex="2" GridPane.rowIndex="2"/>
|
<ListView fx:id="failureList" GridPane.columnIndex="2" GridPane.rowIndex="2"/>
|
||||||
<Button fx:id="confirmButton" mnemonicParsing="false" onAction="#confirmPressed"
|
<Button fx:id="confirmButton" mnemonicParsing="false" onAction="#confirmPressed"
|
||||||
text="%practice.result.confirm.button.label" GridPane.columnSpan="2147483647"
|
text="%practice.result.confirm.button.label" GridPane.columnSpan="2147483647"
|
||||||
GridPane.halignment="CENTER" GridPane.rowIndex="3"/>
|
GridPane.halignment="CENTER" GridPane.rowIndex="3"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user