Skip to content
Snippets Groups Projects
Commit c21e2b04 authored by Hugo Desmons's avatar Hugo Desmons
Browse files

Merge branch 'master' into hugo-desmons

parents 4ba56197 3d8a9acf
No related branches found
No related tags found
No related merge requests found
Showing
with 431 additions and 138 deletions
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
### Équipe H4 ### Équipe H4
- [ANTOINE Maxence](maxence.antoine.etu@univ-lille.fr) - [ANTOINE Maxence](mailto:maxence.antoine.etu@univ-lille.fr)
- [DEBUYSER Hugo](hugo.debuyser.etu@univ-lille.fr) - [DEBUYSER Hugo](mailto:hugo.debuyser.etu@univ-lille.fr)
- [DEKEISER Matisse](matisse.dekeiser.etu@univ-lille.fr) - [DEKEISER Matisse](mailto:matisse.dekeiser.etu@univ-lille.fr)
- [DESMONS Hugo](hugo.desmons.etu@univ-lille.fr) - [DESMONS Hugo](mailto:hugo.desmons.etu@univ-lille.fr)
- [MENNECART Matias](matias.mennecart.etu@univ-lille.fr) - [MENNECART Matias](mailto:matias.mennecart.etu@univ-lille.fr)
___ ___
...@@ -32,6 +32,8 @@ ___ ...@@ -32,6 +32,8 @@ ___
## Diagramme de cas d'utilisation ## Diagramme de cas d'utilisation
Systeme: Application de classification de données
![Diagramme de cas d'utilisation](./ressources/DiagrammeUtilisation.png) ![Diagramme de cas d'utilisation](./ressources/DiagrammeUtilisation.png)
### Fiches descriptives ### Fiches descriptives
...@@ -116,17 +118,25 @@ ___ ...@@ -116,17 +118,25 @@ ___
1) L'utilisateur actionne le bouton "classifier les données". 1) L'utilisateur actionne le bouton "classifier les données".
2) Le système classifie les points de façon aléatoire et modifie leurs couleurs en fonction de la classe choisis. 2) Le système classifie les points de façon aléatoire et modifie leurs couleurs en fonction de la classe choisis.
*Inclure les fiches descriptives pour ces fonctionnalités:*
- *Charger l'ensemble de données*
- *Ajouter une donnée*
- *Classifier la donnée non classifiée*
### Prototypes pour l'interface ### Prototypes pour l'interface
[Prototype figma](https://www.figma.com/design/J7CNIyIPHg0QBvoMKEAZ2L/Untitled?node-id=0-1&t=rzTi4oB0jeOOZTxv-1) Vous pouvez retrouver le [Prototype figma](https://www.figma.com/design/J7CNIyIPHg0QBvoMKEAZ2L/Untitled?node-id=0-1&t=rzTi4oB0jeOOZTxv-1) afin de tester une démonstration de la maquette de l'application.
#### Interface principale
La première page de l’interface se compose des éléments suivants :
- **Nuage de points** : Pour l'instant vide, permettra d'afficher le nuage de points..
<img src="./ressources/MaquetteFigma.png" width="60%" height="60%" alt="Maquette Figma"> - **Icône d'engrenage** :Située en haut à droite de la zone d’affichage permet d'accéder à un menu de paramètres pour configurer l'affichage.
- **Bouton charger des données** : Ce bouton ouvre une fenêtre qui permet à l’utilisateur d'importer un fichier contenant les données avec lesquelles il souhaite travailler.
- **Bouton ajouter une donnée** : Cette option permet à l’utilisateur d’ajouter une donnée au nuage de point.
- **Bouton classifier les données** : Ce bouton permet la classification des données non classifiées grâce a un algorithme (Pour le jalon 1, cette classification est aléatoire).
---
#### Interface principale #### Interface principale
...@@ -144,30 +154,27 @@ La première page de l’interface se compose des éléments suivants : ...@@ -144,30 +154,27 @@ La première page de l’interface se compose des éléments suivants :
<img src="./ressources/ChargerDonnées.png" width="60%" height="60%" alt="Charger les données"> <img src="./ressources/ChargerDonnées.png" width="60%" height="60%" alt="Charger les données">
*Inclure des prototypes de l'interface utilisateur pour ces fonctionnalités:*
#### Fenêtre de chargement de fichier #### Fenêtre de chargement de fichier
- **Nom fichier** : une zone texte où s’affichera le nom du fichier sélectionné après avoir utilisé le bouton "PARCOURIR".
- **Bouton "PARCOURIR"** : Ce bouton permet à l’utilisateur d'ouvrir une fenêtre de navigation dans ses fichiers locaux afin de sélectionner le fichier de données à importer dans l’application. - **Bouton "PARCOURIR"** : Ce bouton permet à l’utilisateur d'ouvrir une fenêtre de navigation dans ses fichiers locaux afin de sélectionner le fichier de données à importer dans l’application.
- **Bouton "Valider"** : Une fois le fichier sélectionné, ce bouton permet de confirmer le choix et de lancer le chargement du fichier dans le graphe. - **Nom fichier** : une zone texte où s’affichera le chemin vers le fichier sélectionné après avoir utilisé le bouton "PARCOURIR".
- **Bouton "Valider"** : Une fois le fichier sélectionné, ce bouton permet de confirmer le choix et de lancer le chargement du fichier dans le nuage de points.
--- ---
- *Ajouter une donnée*
<img src="./ressources/AjouterDonnées.png" width="60%" height="60%" alt="Ajouter une donnée"> <img src="./ressources/AjouterDonnées.png" width="60%" height="60%" alt="Ajouter une donnée">
<img src="./ressources/AjoutDonnéesVisible.png" width="60%" height="60%" alt="Classifier une donnée"> <img src="./ressources/AjoutDonnéesVisible.png" width="60%" height="60%" alt="Classifier une donnée">
#### Formulaire d'ajout de données #### Ajouter une donnée
Cette page présente une interface permettant à l’utilisateur d'ajouter manuellement de nouvelles données dans l’application. Cette page présente une interface permettant à l’utilisateur d'ajouter manuellement de nouvelles données pour lesquelles il souhaite déterminer une classification.
- **Champs de saisie pour les valeurs** : Quatre champs de texte sont affichés dans une boîte. - **Champs de saisie pour les valeurs** : Quatre champs de texte sont affichés permettant d'inscrire les 4 valeurs necessaires pour ajouter une donnée (Uniquement des Iris pour le jalon 1).
- **Zone texte Valeur**: Ces champs permettent à l’utilisateur de saisir manuellement quatre valeurs différentes. - **Bouton "Valider"** : Après avoir rempli les champs de saisie, l’utilisateur peut cliquer sur ce bouton pour valider l'entrée. Cela ajoutera la donnée dans le nuage de points.
- **Bouton "Valider"** : Après avoir rempli les champs de saisie, l’utilisateur peut cliquer sur ce bouton pour valider l'entrée. Cela ajoutera la donnée sur le graphe. - **Ajout d'une donnée** : On remarque qu'après avoir cliqué sur le bouton "Valider", une valeur a été ajouté sous une forme et une couleur diférenciées des autres.
- **Ajout d'une donnée** : On remarque qu'après avoir cliqué sur le bouton "Valider", une valeur a été ajouté sous la forme d'une étoile de couleur verte.
--- ---
<img src="./ressources/AjoutDonnéesVisible.png" width="60%" height="60%" alt="Afficher les données"> <img src="./ressources/AjoutDonnéesVisible.png" width="60%" height="60%" alt="Afficher les données">
...@@ -175,18 +182,15 @@ Cette page présente une interface permettant à l’utilisateur d'ajouter manue ...@@ -175,18 +182,15 @@ Cette page présente une interface permettant à l’utilisateur d'ajouter manue
#### Visualisation des données classifiées #### Visualisation des données classifiées
Cette page représente la visualisation graphique des données après l’étape de classification. Cette page représente la visualisation graphique des données après l’étape de classification (réalisé par l'action sur le bouton `classifier les données`, ainsi tous les points non classifiés le sont).
- **Graphique** : La zone est désormais utilisée pour afficher un graphique. On y voit plusieurs points de deux couleurs différentes, représentant deux classes distinctes de données :
- **Bouton "Classifier les données"** : En appuyant sur ce bouton, la donnée ajoutée se classifie selon ses valeurs renseignés. - **Bouton "Classifier les données"** : En appuyant sur ce bouton, la donnée ajoutée se classifie selon ses valeurs renseignés.
- **Points rouges** : Ces points représentent une première catégorie de données classifiées.
- **Points bleus** : Ils représentent une deuxième catégorie de données classifiées. La donnée qui avait été ajoutée par l'utilisateur garde un symbole différenciateur mais adopte la couleur de la classification qui lui a été déterminer.
- **Étoile bleue** : Ce symbole représente la nouvelle donnée que l’utilisateur a ajoutée manuellement. L’étoile montre la position de cette donnée sur le graphique, suggérant qu'elle a été classée dans la même catégorie que les points bleus.
--- ---
- *Modifier les attributs pour l'affichage*
<img src="./ressources/ModifierAttributs.png" width="60%" height="60%" alt="Modifier les attibuts"> <img src="./ressources/ModifierAttributs.png" width="60%" height="60%" alt="Modifier les attibuts">
...@@ -198,27 +202,19 @@ Cette page permet à l’utilisateur de modifier les attributs utilisés pour re ...@@ -198,27 +202,19 @@ Cette page permet à l’utilisateur de modifier les attributs utilisés pour re
- **Champ "Valeur Abscisse"** : L'utilisateur peut selectioner ici la valeur qu'il souhaite voir représentée sur l'axe des abscisses (X) du graphique. - **Champ "Valeur Abscisse"** : L'utilisateur peut selectioner ici la valeur qu'il souhaite voir représentée sur l'axe des abscisses (X) du graphique.
- **Bouton "Valider"** : Une fois les valeurs des axes définies, l’utilisateur peut cliquer sur ce bouton pour appliquer ces paramètres et afficher les données selon les nouveaux attributs choisis. - **Bouton "Valider"** : Une fois les valeurs des axes définies, l’utilisateur peut cliquer sur ce bouton pour appliquer ces paramètres et afficher les données selon les nouveaux attributs choisis.
Cette page permet à l’utilisateur de modifier les attributs utilisés pour représenter les données sur le graphique, en particulier les valeurs des axes X (abscisses) et Y (ordonnées).
--- - **Champ "Valeur Ordonnée"** : L'utilisateur peut selectioner ici la valeur qu'il souhaite voir représentée sur l'axe des ordonnées (Y) du graphique.
- **Champ "Valeur Abscisse"** : L'utilisateur peut selectioner ici la valeur qu'il souhaite voir représentée sur l'axe des abscisses (X) du graphique.
*Chaque prototype est constitué d'une suite d'écrans, ou d'une arborescence d'écrans si plusieurs chemins d'interaction sont possibles.* - **Bouton "Valider"** : Une fois les valeurs des axes définies, l’utilisateur peut cliquer sur ce bouton pour appliquer ces paramètres et afficher les données selon les nouveaux attributs choisis.
*Pour les deux fonctionnalités dont on demande le prototype et la fiche descriptive, vous ferez le lien entre le prototype et la fiche descriptive. Plus précisément, pour chaque étape de la fiche descriptive, vous indiquerez à quel écran elle correspond. Vous pouvez par exemple mettre une légende sous l'écran, par ex. "Écran pour l'étape 3 de la fiche descriptive du UC Ajouter une donnée."*
*Les prototypes peuvent être en faible fidélité.* ---
*Les prototypes peuvent être dessinés à la main ou générés en utilisant un logiciel. Dans les deux cas, veillez à ce que les images soient lisibles et avec une bonne résolution (possibilité de zoomer pour lire le texte qui s'y trouve).* ---
## Diagramme de classes ## Diagramme de classes
<img src="./ressources/DiagrammeClasse.png" width="60%" height="60%" alt="Diagramme de classe"> <img src="./ressources/DiagrammeClasse.png" width="60%" height="60%" alt="Diagramme de classe">
*Inclure un diagramme de classes qui permet d'**implémenter toutes les fonctionnalités**.* Nous avons fais le choix d'implémenter la classe `ClassificationModel`comme un singleton afin d'éviter que plusieurs model se retrouve au sein de la même application et créé des incohérences.
\ No newline at end of file
*Le diagramme de classes doit suivre le design pattern MVC, mais vous ne ferez pas figurer les classes de la vue. Il doit être clair quelles classes font partie du contrôleur (par exemple grâce à un nom de classe qui contient 'Controleur'); les classes restantes seront considérées faisant partie du modèle.*
*L'image du diagramme doit être de résolution suffisante permettant de zoomer et lire le texte qui y figure.*
Analyse/ressources/DiagrammeClasse.png

396 KiB | W: | H:

Analyse/ressources/DiagrammeClasse.png

811 KiB | W: | H:

Analyse/ressources/DiagrammeClasse.png
Analyse/ressources/DiagrammeClasse.png
Analyse/ressources/DiagrammeClasse.png
Analyse/ressources/DiagrammeClasse.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
<artifactId>javafx-maven-plugin</artifactId> <artifactId>javafx-maven-plugin</artifactId>
<version>0.0.4</version> <version>0.0.4</version>
<configuration> <configuration>
<mainClass>fr.univlille.sae.classification.view.MainStage</mainClass> <mainClass>fr.univlille.sae.classification.Main</mainClass>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
...@@ -67,5 +67,10 @@ ...@@ -67,5 +67,10 @@
<artifactId>javafx-fxml</artifactId> <artifactId>javafx-fxml</artifactId>
<version>11.0.1</version> <version>11.0.1</version>
</dependency> </dependency>
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.9</version>
</dependency>
</dependencies> </dependencies>
</project> </project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.stage.*?>
<Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.AddDataController">
<scene>
<Scene>
<AnchorPane prefHeight="200" prefWidth="200">
<children>
<VBox alignment="CENTER" prefHeight="224.0" prefWidth="384.0" spacing="20.0">
<children>
<HBox alignment="CENTER" prefHeight="18.0" prefWidth="335.0" spacing="20.0">
<children>
<Label text="Valeur 1" />
<TextField />
</children>
</HBox>
<HBox alignment="CENTER" layoutX="10.0" layoutY="47.0" prefHeight="17.0" prefWidth="335.0" spacing="20.0">
<children>
<Label text="Valeur 2" />
<ChoiceBox prefHeight="26.0" prefWidth="163.0" />
</children>
</HBox>
<HBox alignment="CENTER" layoutX="10.0" layoutY="109.0" prefHeight="17.0" prefWidth="335.0" spacing="20.0">
<children>
<Label text="Valeur 3" />
<Spinner />
</children>
</HBox>
<Button fx:id="confirmAdd" mnemonicParsing="false" text="Valider" />
</children></VBox>
</children></AnchorPane>
</Scene>
</scene>
</Stage>
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.stage.*?>
<Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.AxesSettingsController">
<scene>
<Scene>
<AnchorPane prefHeight="200" prefWidth="200">
<children>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="406.0" spacing="15.0">
<children>
<HBox alignment="CENTER" prefHeight="46.0" prefWidth="406.0" spacing="20.0">
<children>
<Label text="Valeur des ordonnées" />
<ChoiceBox fx:id="selectOrd" prefWidth="150.0" />
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="44.0" prefWidth="406.0" spacing="20.0">
<children>
<Label text="Valeur des abscisses" />
<ChoiceBox fx:id="selectAbs" prefWidth="150.0" />
</children>
</HBox>
<Button fx:id="confirmAxes" mnemonicParsing="false" text="Valider" />
</children>
</VBox>
</children></AnchorPane>
</Scene>
</scene>
</Stage>
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.stage.*?>
<Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.DisplaySettingsController">
<scene>
<Scene>
<AnchorPane prefHeight="200" prefWidth="200">
<children>
<VBox alignment="CENTER" layoutY="1.0" prefHeight="292.0" prefWidth="438.0" spacing="30.0">
<children>
<HBox alignment="CENTER" prefHeight="58.0" prefWidth="294.0" spacing="20.0">
<children>
<Label text="Nouvel ajout" />
<ColorPicker fx:id="addColor" editable="true" />
</children></HBox>
<Button fx:id="confirmSettings" mnemonicParsing="false" text="Valider" />
</children></VBox>
</children></AnchorPane>
</Scene>
</scene>
</Stage>
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.Scene?> <?import javafx.scene.*?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.*?>
<?import javafx.scene.control.Label?> <?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?> <?import javafx.stage.*?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.stage.Stage?>
<Stage fx:id="stage" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.LoadDataController"> <Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.LoadDataController">
<scene> <scene>
<Scene> <Scene>
<AnchorPane prefHeight="143.0" prefWidth="363.0"> <AnchorPane prefHeight="143.0" prefWidth="363.0">
...@@ -17,13 +14,13 @@ ...@@ -17,13 +14,13 @@
<children> <children>
<HBox alignment="CENTER" prefHeight="91.0" prefWidth="272.0"> <HBox alignment="CENTER" prefHeight="91.0" prefWidth="272.0">
<children> <children>
<Label fx:id="filenamelab" prefHeight="83.0" prefWidth="157.0" text="file name" /> <Button fx:id="browseFile" mnemonicParsing="false" onAction="#openFileChooser" text="Parcourir" />
<Button mnemonicParsing="false" onAction="#openFileChooser" text="Parcourir" /> <TextField fx:id="filePath" prefHeight="26.0" prefWidth="207.0" />
</children> </children>
</HBox> </HBox>
<HBox alignment="CENTER" prefHeight="76.0" prefWidth="310.0"> <HBox alignment="CENTER" prefHeight="76.0" prefWidth="310.0">
<children> <children>
<Button mnemonicParsing="false" onAction="#validate" text="Valider" /> <Button fx:id="confirmDataSelection" mnemonicParsing="false" onAction="#validate" text="Valider" />
</children> </children>
</HBox> </HBox>
</children> </children>
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.Scene?> <?import javafx.scene.*?>
<?import javafx.scene.chart.CategoryAxis?> <?import javafx.scene.chart.*?>
<?import javafx.scene.chart.NumberAxis?> <?import javafx.scene.control.*?>
<?import javafx.scene.chart.ScatterChart?> <?import javafx.scene.layout.*?>
<?import javafx.scene.control.Button?> <?import javafx.stage.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?>
<?import javafx.stage.Stage?>
<Stage fx:id="stage" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.MainStageController"> <Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.12" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.MainStageController">
<scene> <scene>
<Scene> <Scene>
<AnchorPane prefHeight="487.0" prefWidth="692.0"> <AnchorPane prefHeight="487.0" prefWidth="692.0">
<children> <children>
<VBox prefHeight="488.0" prefWidth="691.0"> <VBox prefHeight="488.0" prefWidth="691.0">
<children> <children>
<HBox prefHeight="305.0" prefWidth="691.0"> <HBox prefHeight="356.0" prefWidth="691.0">
<children> <children>
<Region prefHeight="200.0" prefWidth="200.0" /> <Region prefHeight="338.0" prefWidth="65.0" />
<ScatterChart prefHeight="213.0" prefWidth="557.0"> <ScatterChart fx:id="scatterChart" prefHeight="342.0" prefWidth="609.0">
<xAxis> <xAxis>
<CategoryAxis side="BOTTOM" /> <NumberAxis fx:id="absAxe" prefHeight="21.0" prefWidth="498.0" side="BOTTOM" />
</xAxis> </xAxis>
<yAxis> <yAxis>
<NumberAxis side="LEFT" /> <NumberAxis fx:id="ordAxe" side="LEFT" />
</yAxis> </yAxis>
</ScatterChart> </ScatterChart>
<Region prefHeight="200.0" prefWidth="200.0" /> <Button fx:id="settings" mnemonicParsing="false" text="Réglage" />
</children> </children>
</HBox> </HBox>
<Region prefHeight="77.0" prefWidth="691.0" /> <HBox alignment="CENTER" prefHeight="169.0" prefWidth="691.0" spacing="50.0">
<HBox prefHeight="100.0" prefWidth="200.0">
<children> <children>
<Region prefHeight="101.0" prefWidth="131.0" /> <Button fx:id="loadData" mnemonicParsing="false" onAction="#openLoadData" prefHeight="27.0" prefWidth="185.0" text="Charger un jeu de données" />
<Button mnemonicParsing="false" onAction="#openLoadData" prefHeight="27.0" prefWidth="122.0" text="Charger" /> <Button fx:id="addData" mnemonicParsing="false" prefHeight="26.0" prefWidth="141.0" text="Ajouter une donnée" />
<Region prefHeight="101.0" prefWidth="75.0" /> <Button fx:id="classifyData" disable="true" mnemonicParsing="false" prefHeight="26.0" prefWidth="157.0" text="Classifier une donnée" />
<Button mnemonicParsing="false" prefHeight="25.0" prefWidth="129.0" text="Classifier" />
<Region prefHeight="101.0" prefWidth="70.0" />
<Button mnemonicParsing="false" prefHeight="26.0" prefWidth="133.0" text="Reglages" />
<Region prefHeight="101.0" prefWidth="111.0" />
</children> </children>
</HBox> </HBox>
</children> </children>
......
...@@ -3,18 +3,15 @@ package fr.univlille.sae.classification; ...@@ -3,18 +3,15 @@ package fr.univlille.sae.classification;
import fr.univlille.sae.classification.model.ClassificationModel; import fr.univlille.sae.classification.model.ClassificationModel;
import fr.univlille.sae.classification.view.MainStageView; import fr.univlille.sae.classification.view.MainStageView;
import javafx.application.Application; import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URL;
public class Main extends Application { public class Main extends Application {
public void start(Stage stage) throws IOException { public void start(Stage stage) throws IOException {
ClassificationModel model = new ClassificationModel(); ClassificationModel model = ClassificationModel.getClassificationModel();
MainStageView view = new MainStageView(model); MainStageView view = new MainStageView(model);
view.show(); view.show();
......
package fr.univlille.sae.classification.controller;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.stage.Stage;
public class AddDataController {
@FXML
Stage stage;
@FXML
Button confirmAdd;
}
package fr.univlille.sae.classification.controller;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
public class AxesSettingsController {
@FXML
ChoiceBox selectOrd;
@FXML
ChoiceBox selectAbs;
@FXML
Button confirmAxes;
}
package fr.univlille.sae.classification.controller;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ColorPicker;
import javafx.stage.Stage;
public class DisplaySettingsController {
@FXML
Stage stage;
@FXML
Button confirmSettings;
@FXML
ColorPicker addColor;
}
package fr.univlille.sae.classification.controller; package fr.univlille.sae.classification.controller;
import fr.univlille.sae.classification.model.ClassificationModel;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.io.File; import java.io.File;
import java.io.IOException;
public class LoadDataController { public class LoadDataController {
...@@ -14,7 +18,13 @@ public class LoadDataController { ...@@ -14,7 +18,13 @@ public class LoadDataController {
Stage stage; Stage stage;
@FXML @FXML
Label filenamelab; Button browseFile;
@FXML
Button confirmDataSelection;
@FXML
TextField filePath;
File file; File file;
...@@ -34,19 +44,21 @@ public class LoadDataController { ...@@ -34,19 +44,21 @@ public class LoadDataController {
this.file = fileChooser.showOpenDialog(stage); this.file = fileChooser.showOpenDialog(stage);
if(file != null) { if(file != null) {
filenamelab.setText(file.getName()); filePath.setText(file.getPath());
} }
} }
public void validate() { public void validate() throws IOException {
if (file == null) { if (file == null) {
stage.close(); stage.close();
//throw exception //throw exception
} }
ClassificationModel.getClassificationModel().loadData(file);
loadData(); stage.close();
} }
......
package fr.univlille.sae.classification.controller; package fr.univlille.sae.classification.controller;
import fr.univlille.sae.classification.model.ClassificationModel;
import fr.univlille.sae.classification.view.LoadDataView;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.scene.Scene; import javafx.scene.chart.*;
import javafx.scene.layout.VBox; import javafx.scene.control.Button;
import javafx.stage.Modality; import javafx.stage.*;
import javafx.stage.Stage;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
...@@ -17,6 +18,27 @@ public class MainStageController { ...@@ -17,6 +18,27 @@ public class MainStageController {
@FXML @FXML
Stage stage; Stage stage;
@FXML
NumberAxis absAxe;
@FXML
NumberAxis ordAxe;
@FXML
Button settings;
@FXML
Button loadData;
@FXML
Button addData;
@FXML
Button classifyData;
@FXML
ScatterChart scatterChart;
Stage loadStage; Stage loadStage;
...@@ -26,26 +48,14 @@ public class MainStageController { ...@@ -26,26 +48,14 @@ public class MainStageController {
*/ */
public void openLoadData() throws IOException { public void openLoadData() throws IOException {
LoadDataView loadDataView = new LoadDataView(ClassificationModel.getClassificationModel(), stage);
loadDataView.show();
FXMLLoader loader = new FXMLLoader();
URL fxmlFileUrl = new File(System.getProperty("user.dir") + File.separator + "res" + File.separator + "stages" + File.separator + "load-data-stage.fxml").toURI().toURL();
if (fxmlFileUrl == null) {
System.out.println("Impossible de charger le fichier fxml");
System.exit(-1);
} }
loader.setLocation(fxmlFileUrl);
loadStage = loader.load();
loadStage.setResizable(false);
loadStage.initOwner(stage);
loadStage.initModality(Modality.APPLICATION_MODAL);
loadStage.setTitle("Chargement des donées");
loadStage.showAndWait();
public ScatterChart getScatterChart() {
return this.scatterChart;
} }
} }
package fr.univlille.sae.classification.model; package fr.univlille.sae.classification.model;
import com.opencsv.bean.CsvToBeanBuilder;
import fr.univlille.sae.classification.utils.Observable; import fr.univlille.sae.classification.utils.Observable;
import javax.xml.crypto.Data;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.io.IOException;
import java.util.List; import java.nio.file.Files;
import java.util.Random; import java.nio.file.Paths;
import java.util.Set; import java.util.*;
public class ClassificationModel extends Observable { public class ClassificationModel extends Observable {
...@@ -14,18 +17,42 @@ public class ClassificationModel extends Observable { ...@@ -14,18 +17,42 @@ public class ClassificationModel extends Observable {
private List<LoadableData> datas; private List<LoadableData> datas;
private List<LoadableData> dataToClass; private List<LoadableData> dataToClass;
public ClassificationModel() { private DataType type;
this.datas = new ArrayList<>();
}
private static ClassificationModel model;
/** /**
* TODO * Renvoie une instance unique du model. Par default le type de ce modele est Iris.
* @param x * Modifier en .setType(DataType).
* @param y * @return l'instance du model
*/ */
private void ajouterDonnee(double x, double y) { public static ClassificationModel getClassificationModel() {
if(model == null) model = new ClassificationModel();
return model;
}
private ClassificationModel() {
this(DataType.IRIS);
}
private ClassificationModel(DataType type) {
this.datas = new ArrayList<>();
this.dataToClass = new ArrayList<>();
this.type = type;
}
/**
* Ajoute un point au nuage de points avec toutes les données de ce point
* @param coords toutes les données du points
* @throws IllegalArgumentException Exception levée si le nombre de parametres est insuffisant pour creer un point du type du model
*/
public void ajouterDonnee(double... coords) {
LoadableData newData = PointFactory.createPoint(type, coords);
this.dataToClass.add(newData);
notifyObservers(newData);
} }
...@@ -33,21 +60,50 @@ public class ClassificationModel extends Observable { ...@@ -33,21 +60,50 @@ public class ClassificationModel extends Observable {
* TODO * TODO
* @param file * @param file
*/ */
private void loadData(File file) { public void loadData(File file) throws IOException {
this.datas = new CsvToBeanBuilder<LoadableData>(Files.newBufferedReader(file.toPath()))
.withSeparator(',')
.withType(Iris.class)
.build().parse();
Set<String> types = new HashSet<>();
for (LoadableData d : datas) {
types.add(d.getClassification());
}
LoadableData.setClassificationTypes(types);
notifyObservers();
} }
/** /**
* TODO * TODO
* @param data * @param data
*/ */
private void classifierDonnee(LoadableData data) { public void classifierDonnee(LoadableData data) {
List<String> classes = new ArrayList<>(data.getClassificationTypes()); List<String> classes = new ArrayList<>(data.getClassificationTypes());
Random rdm = new Random(); Random rdm = new Random();
data.setClassification(classes.get(rdm.nextInt(classes.size()))); data.setClassification(classes.get(rdm.nextInt(classes.size())));
notifyObservers(data);
}
public void setType(DataType type) {
this.type = type;
} }
public List<LoadableData> getDatas() {
return datas;
}
public List<LoadableData> getDataToClass() {
return dataToClass;
}
public DataType getType() {
return type;
}
} }
package fr.univlille.sae.classification.model;
public enum DataType {
IRIS;
}
package fr.univlille.sae.classification.model; package fr.univlille.sae.classification.model;
import java.util.Set; import java.util.Set;
import com.opencsv.bean.*;
public class Iris extends LoadableData{ public class Iris extends LoadableData{
@CsvBindByName(column = "sepal.width")
private double sepalWidth; private double sepalWidth;
@CsvBindByName(column = "sepal.length")
private double sepalLength; private double sepalLength;
@CsvBindByName(column = "petal.width")
private double petalWidth; private double petalWidth;
@CsvBindByName(column = "petal.length")
private double petalLength; private double petalLength;
public Iris(double sepalWidth, double sepalLength, double petalWidth, double petalLength) { public Iris(double sepalWidth, double sepalLength, double petalWidth, double petalLength) {
this(sepalWidth, sepalLength, petalWidth, petalLength, "undefined"); this(sepalWidth, sepalLength, petalWidth, petalLength, "undefined");
} }
public Iris() {
//
}
public Iris(double sepalWidth, double sepalLength, double petalWidth, double petalLength, String classification) { public Iris(double sepalWidth, double sepalLength, double petalWidth, double petalLength, String classification) {
super(); super();
this.sepalWidth = sepalWidth; this.sepalWidth = sepalWidth;
...@@ -25,9 +30,6 @@ public class Iris extends LoadableData{ ...@@ -25,9 +30,6 @@ public class Iris extends LoadableData{
this.petalLength = petalLength; this.petalLength = petalLength;
} }
public double getSepalWidth() { public double getSepalWidth() {
return sepalWidth; return sepalWidth;
} }
...@@ -43,4 +45,14 @@ public class Iris extends LoadableData{ ...@@ -43,4 +45,14 @@ public class Iris extends LoadableData{
public double getPetalLength() { public double getPetalLength() {
return petalLength; return petalLength;
} }
@Override
public String toString() {
return "Iris{" +
"sepalWidth=" + sepalWidth +
", sepalLength=" + sepalLength +
", petalWidth=" + petalWidth +
", petalLength=" + petalLength +
'}';
}
} }
...@@ -2,23 +2,28 @@ package fr.univlille.sae.classification.model; ...@@ -2,23 +2,28 @@ package fr.univlille.sae.classification.model;
import java.util.Set; import java.util.Set;
public class LoadableData { public abstract class LoadableData {
private static Set<String> classificationTypes; private static Set<String> classificationTypes;
private String classification; private String classification;
public LoadableData() { protected LoadableData() {
} }
public String getClassification() { public String getClassification() {
return this.classification; return this.classification;
} }
Set<String> getClassificationTypes() { public static Set<String> getClassificationTypes() {
return classificationTypes; return classificationTypes;
} }
void setClassification(String classification) {
public static void setClassificationTypes(Set<String> classificationTypes) {
LoadableData.classificationTypes = classificationTypes;
}
public void setClassification(String classification) {
this.classification = classification; this.classification = classification;
} }
......
package fr.univlille.sae.classification.model;
public class PointFactory {
public static LoadableData createPoint(DataType type, double[] coords) {
int size = coords.length;
LoadableData data;
switch (type) {
case IRIS:
if(size != 4) throw new IllegalArgumentException();
data = new Iris(coords[0],coords[1],coords[2],coords[3]);
break;
default:
throw new IllegalArgumentException();
}
return data;
}
}
package fr.univlille.sae.classification.view; package fr.univlille.sae.classification.view;
import fr.univlille.sae.classification.model.ClassificationModel;
import javafx.fxml.FXMLLoader;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
public class LoadDataView { public class LoadDataView {
private ClassificationModel model;
private Stage owner;
public LoadDataView(ClassificationModel model, Stage owner) {
this.model = model;
this.owner = owner;
}
public void show() throws IOException {
FXMLLoader loader = new FXMLLoader();
URL fxmlFileUrl = new File(System.getProperty("user.dir") + File.separator + "res" + File.separator + "stages" + File.separator + "load-data-stage.fxml").toURI().toURL();
if (fxmlFileUrl == null) {
System.out.println("Impossible de charger le fichier fxml");
System.exit(-1);
}
loader.setLocation(fxmlFileUrl);
Stage root = loader.load();
root.setResizable(false);
root.initOwner(owner);
root.initModality(Modality.APPLICATION_MODAL);
root.setTitle("Chargement des donées");
root.showAndWait();
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment