Skip to content
Snippets Groups Projects
Commit 7b7f4395 authored by LABOUREL Arnaud's avatar LABOUREL Arnaud
Browse files

First version of the template

parent dc6d9566
Branches
No related tags found
No related merge requests found
Showing
with 277 additions and 515 deletions
# Représentation de formules # Agence de voyage
## Description du projet ## Description du projet
Dans cette planche de TP, vous allez implémenter des classes pour générer des formules mathématiques. Chaque classe Ce projet consistera à coder des classes permettant à une agence de location (*rental agency* en anglais) de vehicle
correspondra à un type de formule (constantes, variable, addition, multiplication, ... ). (*vehicles*) d'offrir à ses clients la possibilité de choisir la voiture qui souhaite louer en fonction de différents
critères.
Chaque classe devra implémenter l'interface Formula suivante :
```java
public interface Formula {
/**
* Compute the value of the formula
*
* @param xValue the value of the variable x
* @return the value of the function when the variable x has value {@code xValue}
*/
double eval(double xValue);
/**
* Compute a {@code String} representation of the formula.
* @return the formula as a {@code String}
*/
String toString();
/**
* Compute the derivative of the formula.
* @return the derivative of the formula
*/
Formula derivative();
}
```
Une classe implémentant `Formula` devra donc avoir trois fonctionnalités :
- le calcul de sa valeur étant donnée une valeur pour la variable $x$ : méthode `eval`,
- la représentation en chaîne de caractères de la formule : méthode `toString`,
- le calcul de sa dérivée sous la forme d'une autre formule : méthode `derivative`.
## Membres du projet ## Membres du projet
- NOM, prénom, numéro de groupe, du premier participant - NOM prénom du premier participant
- NOM, prénom, numéro de groupe, du deuxième participant - NOM prénom du deuxième participant
\ No newline at end of file
...@@ -13,9 +13,9 @@ repositories { ...@@ -13,9 +13,9 @@ repositories {
} }
dependencies { dependencies {
testImplementation('org.junit.jupiter:junit-jupiter-api:5.7.2', testImplementation('org.junit.jupiter:junit-jupiter-api:5.8.1',
'org.assertj:assertj-core:3.11.1') 'org.assertj:assertj-core:3.21.0')
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
} }
test { test {
...@@ -23,5 +23,5 @@ test { ...@@ -23,5 +23,5 @@ test {
} }
application { application {
mainClassName = "viewer.MainAppLauncher" mainClassName = "App"
} }
\ No newline at end of file
public class App {
public static void main(String[] args){
}
}
package formula;
import java.util.HashMap;
public class Constant implements Formula {
private double value;
public Constant(double value) {
// TODO : change the code.
}
/**
* Compute the value of the formula
*
* @param xValue the value of the variable x
* @return the value of the function when the variable x has value {@code xValue}
*/
@Override
public double eval(double xValue) {
// TODO : change the code.
return 0;
}
/**
* Compute the derivative of the formula.
*
* @return the derivative of the formula
*/
@Override
public Formula derivative() {
// TODO : change the code.
return this;
}
/**
* Return a {@code String} representation of the formula.
*
* @return the formula as a {@code String}
*/
@Override
public String toString() {
// TODO : change the code.
return "toto";
}
/**
* Indicates whether some other object is "equal to" this one.
*
* @param obj the reference object with which to compare.
* @return {@code true} if this object is the same as the obj
* argument; {@code false} otherwise.
* @see #hashCode()
* @see HashMap
*/
@Override
public boolean equals(Object obj) {
if(obj == null) return false;
if(!(obj instanceof Constant constant)) return false;
return this.value == constant.value;
}
}
package formula;
public interface Formula {
/**
* Compute the value of the formula
*
* @param xValue the value of the variable x
* @return the value of the function when the variable x has value {@code xValue}
*/
double eval(double xValue);
/**
* Compute a {@code String} representation of the formula.
* @return the formula as a {@code String}
*/
String toString();
/**
* Compute the derivative of the formula.
* @return the derivative of the formula
*/
Formula derivative();
}
package util;
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.ZoneId;
public class TimeProvider {
private static Clock clock = Clock.systemDefaultZone();
private static ZoneId zoneId = ZoneId.systemDefault();
public static int currentYearValue(){
return now().getYear();
}
private static LocalDateTime now() {
return LocalDateTime.now(clock);
}
public static void useFixedClockAt(LocalDateTime date) {
clock = Clock.fixed(date.atZone(zoneId).toInstant(), zoneId);
}
}
\ No newline at end of file
package viewer;
import javafx.geometry.Side;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
class FunctionChart extends LineChart<Number, Number> {
private static final int TICK_UNIT = 1;
private static final int LOWER_BOUND = -10;
private static final int UPPER_BOUND = 10;
int getLowerBound() {
return LOWER_BOUND;
}
int getUpperBound() {
return UPPER_BOUND;
}
FunctionChart(){
super(new NumberAxis(LOWER_BOUND, UPPER_BOUND, TICK_UNIT), new NumberAxis(LOWER_BOUND, UPPER_BOUND, TICK_UNIT));
getXAxis().setSide(Side.BOTTOM);
getYAxis().setSide(Side.LEFT);
setPrefWidth(900);
setPrefHeight(900);
setCreateSymbols(false);
}
private Series<Number, Number> getSeries(String name){
for (Series<Number, Number> series : getData())
if(series.getName().equals(name)){
return series;
}
return null;
}
void removeSeries(String name){
Series<Number, Number> series = getSeries(name);
if(series != null){
getData().remove(series);
}
}
}
package viewer;
import formula.Constant;
import javafx.scene.chart.XYChart;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
class FunctionList {
private final List<PlottableFunction> functions = new ArrayList<>();
private final FunctionChart functionChart;
private final double lowerBound;
private final double upperBound;
FunctionList(FunctionChart functionChart) {
this.functionChart = functionChart;
this.lowerBound = functionChart.getLowerBound();
this.upperBound = functionChart.getUpperBound();
PlottableFunction function = new PlottableFunction(new Constant(1), "f");
addFunctionAndItsDerivative(function);
}
void toggleFunction(PlottableFunction function) {
if (function.isPlotted()){
unplot(function);
}
else{
plot(function);
}
}
private void unplot(PlottableFunction function) {
functionChart.removeSeries(function.toString());
function.setPlotted(false);
}
List<PlottableFunction> getFunctions(){
return functions;
}
private void plot(PlottableFunction function){
XYChart.Series<Number, Number> series = function.getData(lowerBound, upperBound);
series.setName(function.toString());
functionChart.getData().add(series);
function.setPlotted(true);
}
private void addFunctionsAndTheirDerivative(Collection<PlottableFunction> functions){
for(PlottableFunction function: functions){
addFunctionAndItsDerivative(function);
}
}
private void addFunctionAndItsDerivative(PlottableFunction function){
add(function);
add(function.derivative());
}
private void add(PlottableFunction function) {
functions.add(function);
}
void clear() {
functionChart.getData().clear();
for(PlottableFunction function: functions){
function.setPlotted(false);
}
}
}
package viewer;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import java.net.URL;
import java.util.ResourceBundle;
public class MainAppController implements Initializable {
private static final int BUTTON_WIDTH = 500;
@FXML
private AnchorPane anchorPane;
@FXML
private VBox vBox;
private FunctionList functionList;
@Override
public void initialize(final URL url, final ResourceBundle rb) {
FunctionChart functionChart = new FunctionChart();
functionList = new FunctionList(functionChart);
anchorPane.getChildren().add(functionChart);
addFunctionButtons();
addClearButton();
}
private void addClearButton() {
Button clearButton = new Button("Clear");
clearButton.setOnAction(event -> functionList.clear());
addButton(clearButton);
}
private void addFunctionButtons() {
for(PlottableFunction function : functionList.getFunctions()){
addFunctionButton(function);
}
}
private void addFunctionButton(PlottableFunction function) {
Button button = new Button(function.toString());
addButton(button);
button.setOnAction(event -> toggleFunction(function));
}
private void toggleFunction(PlottableFunction function){
functionList.toggleFunction(function);
}
private void addButton(Button button) {
button.setPrefWidth(BUTTON_WIDTH);
vBox.getChildren().add(button);
}
}
package viewer;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.util.Objects;
public class MainAppLauncher extends Application {
public static void main(String[] args) {
Application.launch(MainAppLauncher.class, args);
}
@Override
public void start(Stage stage) {
try {
Parent root = FXMLLoader.load(Objects.requireNonNull(getClass().getClassLoader()
.getResource("MainApp.fxml")));
stage.setScene(new Scene(root));
stage.setTitle("Formulas");
stage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
package viewer;
import formula.Formula;
import javafx.scene.chart.XYChart;
public class PlottableFunction {
private final Formula formula;
private final String name;
private static final double PRECISION = 0.01;
private boolean isPlotted = false;
PlottableFunction(Formula formula, String name) {
this.formula = formula;
this.name = name;
}
@Override
public String toString() {
return name + "(x) = " + formula;
}
public PlottableFunction derivative(){
return new PlottableFunction(formula.derivative(), name + "'");
}
XYChart.Series<Number, Number> getData(double lowerBound, double upperBound) {
final XYChart.Series<Number, Number> series = new XYChart.Series<>();
for (int index = 0; index <= 2 * (upperBound-lowerBound) / PRECISION; index++) {
double x = lowerBound + index * PRECISION;
series.getData().add(new XYChart.Data<>(x, formula.eval(x)));
}
return series;
}
boolean isPlotted() {
return isPlotted;
}
void setPlotted(boolean plotted) {
isPlotted = plotted;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<AnchorPane maxHeight="900.0" maxWidth="1200.0" minHeight="900.0" minWidth="1400.0"
prefHeight="900.0" prefWidth="1000.0"
styleClass="root" stylesheets="stylesheet.css"
xmlns:fx="http://javafx.com/fxml"
fx:controller="viewer.MainAppController">
<AnchorPane layoutX="900.0" minHeight="0.0" minWidth="0.0" prefHeight="900.0" prefWidth="300.0">
<VBox fx:id="vBox" prefHeight="800.0" prefWidth="500.0"/>
</AnchorPane>
<AnchorPane fx:id="anchorPane" layoutX="-7.0" prefHeight="900.0" prefWidth="900.0"/>
</AnchorPane>
\ No newline at end of file
#pane, .root, .split-pane{
-fx-background-color: #353434;
-fx-foreground-color: #353434;
}
.chart-vertical-zero-line {
-fx-stroke: white;
}
.chart-horizontal-zero-line {
-fx-stroke: white;
}
.chart-plot-background {
-fx-background-color: #575758;
-fx-foreground-color: white;
-fx-stroke: white;
}
.chart-vertical-grid-lines {
-fx-stroke: #898887;
}
.chart-horizontal-grid-lines {
-fx-stroke: #898887;
}
.chart-alternative-row-fill {
-fx-fill: transparent;
-fx-stroke: transparent;
-fx-stroke-width: 1;
}
.axis {
-fx-stroke: white;
-fx-fill: white;
-fx-font-size: 1.4em;
-fx-tick-label-fill: white;
-fx-font-family: Tahoma;
-fx-tick-length: 0;
-fx-minor-tick-length: 0;
}
.background {
-fx-background-color: #674A44;
-fx-foreground-color: #353434;
}
.button {
-fx-padding: 5 22 5 22;
-fx-border-color: #353434;
-fx-border-width: 0;
-fx-background-radius: 0;
-fx-background-color: derive(#353434,20%);
-fx-font-family: "Segoe UI", Helvetica, Arial, sans-serif;
-fx-font-size: 11pt;
-fx-text-fill: #d8d8d8;
-fx-background-insets: 0 0 0 0, 0, 1, 2;
}
.button:hover {
-fx-background-color: #3a3a3a;
}
.button:pressed, .button:default:hover:pressed {
-fx-background-color: #bdbcbc;
-fx-text-fill: black;
}
.button:disabled, .button:default:disabled {
-fx-opacity: 0.4;
-fx-background-color: #353434;
-fx-text-fill: white;
}
.button:default {
-fx-background-color: -fx-focus-color;
-fx-text-fill: #ffffff;
}
.button:default:hover {
-fx-background-color: derive(-fx-focus-color,30%);
}
.text-area .content {
-fx-background-color: #575758;
}
\ No newline at end of file
import formula.Constant;
import formula.Formula;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.within;
public class ConstantTest {
@Test
public void testEval(){
Constant constantTen = new Constant(10);
assertThat(constantTen.eval(0.)).isCloseTo(10., within(.001));
Constant constantOne = new Constant(1);
assertThat(constantOne.eval(10.)).isCloseTo(1., within(.001));
}
@Test
public void testToString(){
Constant constantTen = new Constant(10);
assertThat(constantTen.toString()).isEqualTo("10.0");
Constant constantOne = new Constant(1);
assertThat(constantOne.toString()).isEqualTo("1.0");
}
@Test
public void testEquals() {
Constant constantTen = new Constant(10);
Constant constantTen2 = new Constant(10);
Constant constantOne = new Constant(0);
assertThat(constantTen).isEqualTo(constantTen);
assertThat(constantTen).isEqualTo(constantTen2);
assertThat(constantTen).isNotEqualTo(constantOne);
}
@Test
public void testDerivative() {
Constant constantTen = new Constant(10);
Formula derivedConstant = constantTen.derivative();
assertThat(derivedConstant.eval(10.)).isCloseTo(0., within(.001));
Constant constantZero = new Constant(0);
assertThat(derivedConstant).isEqualTo(constantZero);
}
}
package agency;
class TestCar {
// TODO : décommenter le code ci-dessous pour tester la tâche 2.
/*
Car catalinaCar = new Car(apple, catalina, catalinaYear, catalinaNumberOfSeats);
Car windows95Car = new Car(microsoft, windows95, windows95Year, windows95NumberOfSeats);
static final String apple = "Apple";
static final String catalina = "Catalina";
static final String microsoft = "Microsoft";
static final String windows95 = "Windows95";
static final int catalinaYear = 2019;
static final int windows95Year = 1995;
static final int catalinaNumberOfSeats = 3;
private static final int windows95NumberOfSeats = 1;
private static final LocalDateTime YEAR2000 = LocalDateTime.of(2000, 1, 1, 0, 0);
private static final LocalDateTime YEAR2019 = LocalDateTime.of(2019, 1, 1, 0, 0);
@BeforeEach
void fixClock(){
TimeProvider.useFixedClockAt(YEAR2019);
}
@Test
void testConstructionOfTooOldVehicle(){
assertThatIllegalArgumentException()
.isThrownBy(()->new Car("Linux", "ubuntu",1899, 3))
.withMessageContaining("1899");
}
@Test
void testConstructionOfFutureVehicle() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new Car("Linux", "ubuntu", 2020, 3))
.withMessageContaining("2020");
}
@Test
void testConstructionOfVehicleWithNoSeats() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new Car("Linux", "ubuntu", 2000, 0))
.withMessageContaining("0");
}
@Test
void testGetters() {
assertThat(catalinaCar).hasFieldOrPropertyWithValue("brand", apple)
.hasFieldOrPropertyWithValue("model", catalina)
.hasFieldOrPropertyWithValue("productionYear", catalinaYear)
.hasFieldOrPropertyWithValue("numberOfSeats", catalinaNumberOfSeats);
}
@Test
void testConstructionOfFutureCar(){
assertThatIllegalArgumentException().
isThrownBy(() -> new Car("Linux", "ubuntu",
2020, 2));
}
@Test
void testConstructionOfTooOldCar(){
assertThatIllegalArgumentException().
isThrownBy(() -> new Car("Linux", "ubuntu",
1899, 1));
}
@Test
void testThatCarImplementsVehicle(){
assertThat(catalinaCar).withFailMessage("%s must implement %s",
Car.class, Vehicle.class)
.isInstanceOf(Vehicle.class);
}
@Test
void testIsNew(){
assertThat(windows95Car).withFailMessage("A car with production year %s should have been old",
windows95Year)
.returns(false, Car::isNew);
assertThat(catalinaCar).withFailMessage("A car with production year %s should have been new",
catalinaYear)
.returns(true, Car::isNew);
TimeProvider.useFixedClockAt(YEAR2000);
assertThat(windows95Car).withFailMessage("A car with production year %s should have been new in %s",
windows95Year, YEAR2000)
.returns(true, Car::isNew);
TimeProvider.useFixedClockAt(YEAR2019);
}
@Test
void testDailyRentalPrice(){
double expectedPriceCatalinaCar = 40.*catalinaNumberOfSeats;
double expectedPriceWindowsCar = 20.*windows95NumberOfSeats;
assertThat(catalinaCar).as("Car DailyRentalPrice")
.withFailMessage("A new car with %s seats must have price %s",
catalinaNumberOfSeats, expectedPriceCatalinaCar )
.returns(expectedPriceCatalinaCar, Car::dailyRentalPrice);
assertThat(windows95Car).as("Car DailyRentalPrice")
.withFailMessage("An old car with %s seat must have price %s",
windows95NumberOfSeats, expectedPriceCatalinaCar )
.returns(expectedPriceWindowsCar, Car::dailyRentalPrice);
}
@Test
void testToString(){
String expectedStringMacOs = "Car Apple Catalina 2019 (3 seats) : 120.0€";
assertThat(catalinaCar).returns(expectedStringMacOs, Objects::toString);
String expectedStringWin = "Car Microsoft Windows95 1995 (1 seat) : 20.0€";
assertThat(windows95Car).returns(expectedStringWin, Objects::toString);
}
*/
}
package agency;
class TestClient {
// TODO : décommenter le code ci-dessous pour tester la classe Client.
/*
private Client arnaud;
@BeforeEach
void initializeClient() {
arnaud = new Client("Arnaud", "Labourel", 1981);
}
@Test
void testGetFirstName(){
assertThat(arnaud.getFirstName()).isEqualTo("Arnaud");
}
@Test
void testGetLastName(){
assertThat(arnaud.getLastName()).isEqualTo("Labourel");
}
@Test
void testGetYearOfBirth(){
assertThat(arnaud.getYearOfBirth()).isEqualTo(1981);
}
*/
}
package agency;
class TestRentalAgency extends agency.TestCar {
// TODO : décommenter le code ci-dessous pour tester la tâche 2.
/*
private RentalAgency rentalAgency;
@BeforeEach
void initializeRentalAgency(){
rentalAgency = new RentalAgency();
}
@Test
void testAddingCars(){
rentalAgency.add(catalinaCar);
assertThat(rentalAgency.getVehicles())
.containsExactly(catalinaCar);
rentalAgency.add(windows95Car);
assertThat(rentalAgency.getVehicles())
.containsExactly(catalinaCar, windows95Car);
}
@Test
void testAddingSameCar() {
assertThat(rentalAgency.add(catalinaCar)).isTrue();
assertThat(rentalAgency.add(catalinaCar)).isFalse();
}
@Test
void testRemovingExistingVehicle(){
rentalAgency.add(catalinaCar);
rentalAgency.remove(catalinaCar);
assertThat(rentalAgency.getVehicles()).doesNotContain(catalinaCar);
}
*/
// TODO : décommenter le code ci-dessous pour tester la méthode select.
/*
@Test
void testRemovingNonExistingVehicle(){
assertThatThrownBy(() -> rentalAgency.remove(catalinaCar))
.isInstanceOf(UnknownVehicleException.class)
.hasMessageContaining(catalinaCar.toString());
}
*/
// TODO : décommenter le code ci-dessous pour tester la tâche 6.
/*
@Test
void testSelect(){
rentalAgency.add(catalinaCar);
rentalAgency.add(windows95Car);
assertThat(rentalAgency.select(vehicle -> vehicle.getBrand().equals(apple)))
.containsExactly(catalinaCar);
assertThat(rentalAgency.select(vehicle -> vehicle.getModel().equals(windows95)))
.containsExactly(windows95Car);
}
private Client arnaud = new Client("Arnaud", "Labourel", 1981);
private Client paul = new Client("Paul", "Calcul", 2018);
@Test
void testRentingVehicles(){
rentalAgency.add(catalinaCar);
rentalAgency.add(windows95Car);
rentalAgency.rentVehicle(arnaud, catalinaCar);
rentalAgency.rentVehicle(paul, windows95Car);
assertThat(rentalAgency.allRentedVehicles()).containsExactly(catalinaCar, windows95Car);
}
@Test
void testSameClientRentingSeveralVehicles(){
rentalAgency.add(catalinaCar);
rentalAgency.add(windows95Car);
assertThat(rentalAgency.rentVehicle(arnaud, catalinaCar)).isEqualTo(120.);
assertThatIllegalStateException().isThrownBy(() -> rentalAgency.rentVehicle(arnaud, windows95Car));
}
@Test
void testSameVehicleRentedTwice(){
rentalAgency.add(catalinaCar);
rentalAgency.rentVehicle(arnaud, catalinaCar);
assertThatIllegalStateException().isThrownBy(() -> rentalAgency.rentVehicle(paul, catalinaCar));
}
@Test
void testRentingAVehicleNotInTheAgency(){
assertThatThrownBy(() -> rentalAgency.rentVehicle(paul, catalinaCar))
.isInstanceOf(UnknownVehicleException.class)
.hasMessageContaining(catalinaCar.toString());
}
*/
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment