diff --git a/DevEfficace/rapport.md b/DevEfficace/rapport.md index 57e2c8bb503e8153ea05fd21d650bed7563c12c6..6af361b323664e928794357eca5f03dc1231b736 100644 --- a/DevEfficace/rapport.md +++ b/DevEfficace/rapport.md @@ -1,4 +1,4 @@ -# Algorithme K-NN - Rapport R3.02 (EN COURS - NON RELU) +# Algorithme K-NN - Rapport R3.02 ### Groupe H-4 @@ -8,7 +8,6 @@ - [DEKEISER Matisse](mailto:matisse.dekeiser.etu@univ-lille.fr) - [DESMONS Hugo](mailto:hugo.desmons.etu@univ-lille.fr) - --- ## Implémentation de K-NN @@ -17,55 +16,50 @@ pas à mettre en avant l’efficacité de ces méthodes (approprié pour un grand volume de données, normalisation efficace des distances).* -Nous avons implémenté l'algorithme K-NN dans une classe MethodKNN. Nous avons choisis d'utiliser des methodes statiques pour faciliter l'utilisation de cette algorithme. -Cette classe contient 5 methodes permettant d'implementer l'algorithme K-NN et ses differentes fonctionnalités. +Nous avons implémenté l'algorithme K-NN dans une classe `MethodKNN`. Nous avons choisi d'utiliser des méthodes statiques pour faciliter l'utilisation de cet algorithme. +Cette classe contient 5 méthodes permettant d'implémenter l'algorithme K-NN et ses différentes fonctionnalités. > public static void updateModel(List<LoadableData> datas) -Cette premiere methode permet de mettre a jour les données de l'algorithme. Ainsi il faut passer en parametre les données sur lesquelles ont souhaite travailler. -Cette methode va calculer les valeurs max et min ainsi que l'amplitude de chaque attribue des données passé en parametre. -Cette methode necessite 2 parcours, 1 sur les données, puis un sur les min et les max de chaque attribue pour calculer l'amplitude. Il est donc conseillé de n'utiliser cette methode qu'une fois par jeu de données (toute facon le resultat serait le meme) -C'est pour cela que cette methode n'est pas directement appelé dans les methodes ci-dessous mais qu'elle doit explicitement être appelé aupparavant. +Cette première méthode permet de mettre à jour les données de l'algorithme. Ainsi, il faut passer en paramètre les données sur lesquelles on souhaite travailler. +Cette méthode va calculer les valeurs max et min ainsi que l'amplitude de chaque attribut des données passé en paramètre. +Cette méthode nécessite 2 parcours : 1 sur les données, puis un sur les valeurs min et max de chaque attribut pour calculer l'amplitude. Il est donc conseillé de n'utiliser cette méthode qu'une fois par jeu de données (le résultat serait le même). +C'est pour cela que cette méthode n'est pas directement appelée dans les méthodes ci-dessous, mais qu'elle doit explicitement être appelée auparavant. -> public static List<LoadableData> kVoisins(List<LoadableData> datas, LoadableData data, int k, Distance distance) +> public static List<LoadableData> kVoisins(List<LoadableData> datas, LoadableData data, int k, Distance distance) -Cette methode a pour objectif de recupéré les k voisins les plus proches d'un donnée parmis un jeu de données et selon une distance. -Elle prends donc en parametre le jeu de données, la données pour laquelle on souhaite obtenir les voisins, le nombre de voisins souhaités ainsi que la distance avec laquelle les calculs doivent etres effectués. -Cette methode n'effectue qu'un seul parcours de boucle et calcul pour chacune des données sa distance avec la donnée passée en parametre. Les calculs de distance sont definis dans l'objet implémentant l'interface Distance passé en parametre. -Si il s'agit d'une distance normalisée la normalisation s'effectue au moment de la recherche des voisins. - ->public static double robustesse(List<LoadableData> datas, int k, Distance distance, double testPart) - +Cette méthode a pour objectif de récupérer les **k** voisins les plus proches d'une donnée parmi un jeu de données et selon une distance. +Elle prend donc en paramètres le jeu de données, la donnée pour laquelle on souhaite obtenir les voisins, le nombre de voisins souhaités ainsi que la distance avec laquelle les calculs doivent être effectués. +Cette méthode n'effectue qu'un seul parcours de boucle, et calcule pour chacune des données sa distance avec la donnée passée en paramètre. Les calculs de distance sont définis dans l'objet implémentant l'interface Distance passé en paramètre. +S'il s'agit d'une distance normalisée, la normalisation s'effectue au moment de la recherche des voisins. -Cette methode a pour objectif d'évaluer la robustesse de l'algorithme sur un jeu de donné avec un K donné et une distance donnée. Elle prends en parametre le jeu de données sur lequel effectué l'evalutation, -le k a tester, la distance a utiliser ainsi que un pourcentage correspondant a la partie des données qui sera utilisé afin de tester les données. Ex avec testPart=0.2, 80% des données serviront de données de reférence et 20% seront utilisé pour tester la -validité de l'algorithme. Cette effectue une validation croisée (Voir #Validation Croisée) +> public static double robustesse(List<LoadableData> datas, int k, Distance distance, double testPart) +Cette méthode a pour objectif d'évaluer la robustesse de l'algorithme sur un jeu de données avec un **k** et une distance donnés. Elle prend en paramètres le jeu de données sur lequel effectuer l'évaluation, +le **k** à tester, la distance à utiliser ainsi qu'un pourcentage correspondant à la partie des données qui sera utilisée afin de tester les données. Exemple avec testPart=0.2, 80% des données serviront de données de reférence et 20% seront utilisées pour tester la +validité de l'algorithme. Cette méthode effectue une validation croisée. (voir `Validation croisée`) > public static int bestK(List<LoadableData> datas, Distance distance) -Cette methode a pour objectif de rechercher le meilleur K possible pour un jeu de données et une distance données. -Elle va tester la totalité des K impair compris entre 1 et racine caré du nombre de données. Cette valeur max permet d'eviter que le K choisit soit trop grand et -fausse les résultats. Elle test donc la robustesse de chaque K et renvoie le K ayant la meilleure robustesse. Cette methode parcours le jeu de donnée Kmax*(1/testPart) fois, ou testPart correspond au pourcentage des données utilisé comme valeurs de test. - +Cette méthode a pour objectif de rechercher le meilleur **K** possible pour un jeu de données et une distance donnée. +Elle va tester la totalité des **K** impairs compris entre 1 et racine carrée du nombre de données. Cette valeur max permet d'éviter que le **K** choisi soit trop grand et +fausse les résultats. Elle teste donc la robustesse de chaque **K** et renvoie le **K** ayant la meilleure robustesse. Cette méthode parcourt le jeu de donnée `Kmax * (1/testPart)` fois, où testPart correspond au pourcentage des données utilisées comme valeurs de test. --- ## Validation croisée - -#### Rappel de la methode de validation croisée +#### Rappel de la méthode de validation croisée La validation croisée est une méthode d'évaluation utilisée pour mesurer la performance d'un modèle en le testant sur des données qu'il n'a pas utilisées pour l'entraînement. Dans ce cas précis : -Les données sont divisées en plusieurs parties égales (appelées folds ou partitions). +Les données sont divisées en plusieurs parties égales (appelées _folds_ ou _partitions_). À chaque itération, une des partitions est utilisée comme jeu de test, tandis que les autres servent pour l'entraînement. Les résultats des tests sont cumulés pour calculer un score global. Cette méthode permet de minimiser le biais d'évaluation en utilisant toutes les données tour à tour pour l'entraînement et le test. #### Implémentation de la validation croisée - La méthode effectue une validation croisée en divisant les données en plusieurs partitions. À chaque itération : Une partie des données sert de jeu de test. @@ -75,55 +69,68 @@ Voici les étapes principales : - Calcul du nombre d'itérations : Le nombre d'itérations est déterminé par -1/testPart. Par exemple, si testPart = 0.1, la méthode effectue 10 itérations, si testPart = 0.2, la méthode effectue 5 iterations, etc. +`1/testPart`. Par exemple, si testPart = 0.1, la méthode effectue 10 itérations, si testPart = 0.2, la méthode effectue 5 itérations, etc. - Division des données : -Pour chaque itération i, une sous-liste correspondant au pourcentage testPart (par exemple, 10 % des données) est extraite et utilisée comme jeu de test (testData). -Le reste des données sert de jeu d'entraînement (trainingData). +Pour chaque itération **i**, une sous-liste correspondant au pourcentage testPart (par exemple, 10% des données) est extraite et utilisée comme jeu de test (testData). +Le reste des données sert de jeu d'entraînement (`trainingData`). - Estimation des classes : -Chaque élément du jeu de test est classé à l’aide de la fonction MethodKNN.estimateClass(trainingData, l, k, distance) où trainingData correspond au reste des données. -Si la classe prédite correspond à la classe réelle (retournée par l.getClassification()), un compteur (totalFind) est incrémenté. +Chaque élément du jeu de test est classé à l’aide de la fonction `MethodKNN.estimateClass(trainingData, l, k, distance)`, où trainingData correspond au reste des données. +Si la classe prédite correspond à la classe réelle (retournée par `l.getClassification()`), un compteur (`totalFind`) est incrémenté. - Calcul du taux de réussite : -Après chaque itération, le taux de réussite est calculé totalFind/totalTry et ajouté à la variable taux. -- Renvoie du taux total moyen de reussite: Enfin, on divise la variable taux par le nombre d'itération afin d'obtenir un taux de reussite moyen. +Après chaque itération, le taux de réussite est calculé (`totalFind/totalTry`) et ajouté à la variable taux. +- Renvoi du taux total moyen de réussite : enfin, on divise la variable taux par le nombre d'itérations afin d'obtenir un taux de réussite moyen. --- ## Choix du meilleur K +Pour obtenir le meilleur **K**, on appelle la méthode `bestK(List<LoadableData> datas, Distance distance)` décrite plus haut. On obtient un **K** optimal, puis on appelle la méthode `robustesse(...)` avec le k trouvé plus tôt comme paramètre. -Pour obtenir le meilleur K, on appel la methode bestK(List<LoadableData> datas, Distance distance) decrite plus haut. On obtient un K optimal, puis on appel la methode robustesse(...) avec le k trouvé plutot comme parametre. +En appliquant cette méthode, voici les résultats que nous avons obtenus avec : -En appliquant cette methode voici les resultats que nous avons obtenue avec: +### Iris -##### Iris +| Distance \ k | 1 | 3 | 5 | 7 | 9 | 11 | k choisi | +|-----------------------------------|-------|-------|-------|-------|-------|-------|----------| +| Distance euclidienne | 0.96 | 0.966 | 0.96 | 0.98 | 0.98 | 0.98 | 5 | +| Distance euclidienne (normalisée) | 0.946 | 0.946 | 0.96 | 0.96 | 0.96 | 0.96 | 7 | +| Distance Manhattan | 0.953 | 0.946 | 0.946 | 0.96 | 0.96 | 0.953 | 7 | +| Distance Manhattan (normalisée) | 0.946 | 0.96 | 0.946 | 0.953 | 0.953 | 0.953 | 3 | +On obtient donc un taux de réussite plutôt élevé. À chaque fois, l'algorithme choisit le K avec le plus haut taux de réussite. En cas d'égalité, il choisit le plus petit K parmi les égalités. +### Pokémon -| Distance \ K | 1 | 3 | 5 | 7 | 9 | 11 | K choisit | -|---------------------------------|-------|-------|-------|-------|-------|-------|----| -| Distance Euclidienne | 0.96 | 0.966 | 0.96 | 0.98 | 0.98 | 0.98 | 5 | -| Distance Euclidienne Normalisée | 0.946 | 0.946 | 0.96 | 0.96 | 0.96 | 0.96 | 7 | -| Distance Manhattan | 0.953 | 0.946 | 0.946 | 0.96 | 0.96 | 0.953 | 7 | -| Distance Manhattan Normalisée | 0.946 | 0.96 | 0.946 | 0.953 | 0.953 | 0.953 | 3 | +**Classification selon le type** -On obtient donc un taux de reussiste plutôt élevé. A chaque fois l'algorithme choisit le K avec le plus haut taux de reussite. En cas d'égalité, il choisit le plus petit K parmis les égalités. +| Distance \ k | 1 | 3 | 5 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 21 | k choisi | +|-----------------------------------|-------|-------|-------|-------|-------|-------|----|----|----|----|----|----------| +| Distance euclidienne | 0.243 | 0.229 | 0.239 | 0.235 | 0.247 | 0.251 | 0.237 | 0.225 | 0.215 | 0.205 | 0.2 | 11 | +| Distance euclidienne (normalisée) | 0.211 | 0.229 | 0.251 | 0.245 | 0.245 | 0.239 | 0.245 | 0.243 | 0.237 | 0.239 | 0.225 | 5 | +| Distance Manhattan | 0.231 | 0.235 | 0.239 | 0.239 | 0.241 | 0.239 | 0.237 | 0.235 | 0.233 | 0.207 | 0.201 | 9 | +| Distance Manhattan (normalisée) | 0.178 | 0.188 | 0.2 | 0.215 | 0.205 | 0.203 | 0.194 | 0.190 | 0.184 | 0.180 | 0.190 | 7 | +--- -##### Pokemon +Le taux de réussite est ici plus bas, cela s'explique notamment par le nombre d'attributs différents et la complexité à identifier le type d'un Pokémon. +Cependant, le taux de réussite reste satisfaisant et stable. -| Distance \ K | 1 | 3 | 5 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 21 | K choisit | -|---------------------------------|-------|-------|-------|-------|-------|-------|----|----|----|----|----|----| -| Distance Euclidienne | 0.243 | 0.229 | 0.239 | 0.235 | 0.247 | 0.251 | 0.237 | 0.225 | 0.215 | 0.205 | 0.2 | 11 | -| Distance Euclidienne Normalisée | 0.211 | 0.229 | 0.251 | 0.245 | 0.245 | 0.239 | 0.245 | 0.243 | 0.237 | 0.239 | 0.225 | 5 | -| Distance Manhattan | 0.231 | 0.235 | 0.239 | 0.239 | 0.241 | 0.239 | 0.237 | 0.235 | 0.233 | 0.207 | 0.201 | 9 | -| Distance Manhattan Normalisée | 0.178 | 0.188 | 0.2 | 0.215 | 0.205 | 0.203 | 0.194 | 0.190 | 0.184 | 0.180 | 0.190 | 7 | ---- +**Classification (légendaire ou non légendaire)** + +| Distance \ K | 1 | 3 | 5 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 21 | K choisit | +|-----------------------------------|-------|-------|-------|-------|-------|-------|----|----|----|----|----|----| +| Distance euclidienne | 0.986 | 0.978 | 0.984 | 0.980 | 0.984 | 0.984 | 0.984 | 0.984 | 0.984 | 0.984 | 0.984 | 1 | +| Distance euclidienne (normalisée) | 1.0 | 0.998 | 0.998 | 0.996 | 0.996 | 0.998 | 0.998 | 0.998 | 0.998 | 0.998 | 0.998 | 1 | +| Distance Manhattan | 0.978 | 0.972 | 0.984 | 0.980 | 0.984 | 0.984 | 0.984 | 0.984 | 0.984 | 0.984 | 0.984 | 5 | +| Distance Manhattan (normalisée) | 0.980 | 0.984 | 0.988 | 0.984 | 0.984 | 0.986 | 0.986 | 0.986 | 0.986 | 0.986 | 0.984 | 5 | -ajoyter un commentaire sur les resultats +On a ici des résultats bien meilleurs. En effet, estimer si un Pokémon est légendaire ou non est bien plus simple qu'estimer son type, les attributs des Pokémons légendaires sont bien différents de ceux non-légendaires, contrairement aux types, où, selon les types, les valeurs ne fluctuent pas autant. + +--- ## Efficacité -Comme expliqué pour chaque methode dans la partie Implementation de l'algorithme, nous avons chercher a minimiser le nombre de parcours du fichier de données et plus generalement le nombre de boucle. -L'algorithme necessite une List qui sera donnée en parametre, il est donc libre a la personne qui l'utilise de fournir l'implementation de List qu'il souhaite. De plus, pour le calcul des parametres du jeu de données ( -amplitude,valeur minimale, valeur maximal) nous avons utiliser un tableau de double afin de limiter les performances \ No newline at end of file +Comme expliqué pour chaque méthode dans la partie `Implémentation` de l'algorithme, nous avons cherché à minimiser le nombre de parcours du fichier de données, et plus généralement le nombre de boucles. +L'algorithme nécessite une `List` qui sera donnée en paramètre, il est donc libre à la personne qui l'utilise de fournir l'implémentation de `List` qu'il souhaite. De plus, pour le calcul des paramètres du jeu de données +`(amplitude, valeur minimale, valeur maximale)`, nous avons utilisé un tableau de `double` afin de limiter les performances. \ No newline at end of file diff --git a/TutoImportation.md b/TutoImportation.md new file mode 100644 index 0000000000000000000000000000000000000000..d9d265925512ae680dec9284d36b8e90884d68fb --- /dev/null +++ b/TutoImportation.md @@ -0,0 +1,176 @@ +## Importation d'un fichier CSV + +#### Préambule + +Avant de commencer, sachez que cette importation nécessite certaines connaissances en Java ou en programmation orientée objet. Cependant, si vous n'êtes pas familier avec ces concepts, ce tutoriel vous guidera à travers toutes les étapes nécessaires pour importer de nouvelles données. + +Assurez-vous que votre base de données est sous forme de fichier CSV, avec les noms des colonnes sur la première ligne. Il est également essentiel de savoir quelles données vous souhaitez analyser. Cette étape est indépendante du logiciel que vous utilisez et dépend plutôt de la manière dont vous allez importer vos données. + +--- + +### Procédure + +Ce modèle de classification permet d’importer une base de données. Pour ce faire, il vous suffit d'ajouter au modèle, dans le dossier `src/main/java/fr.univlille.sae.classification/model`, une nouvelle classe portant le nom de votre choix, correspondant à votre jeu de données. + +Une fois cela fait, vous devrez implémenter les différentes méthodes présentes dans l'interface `LoadableData`. Dans votre nouvelle classe, commencez par définir les attributs correspondant aux colonnes de votre fichier CSV. Par exemple : + +```java +@CsvBindByName(column = "column1") +private String column1; +@CsvBindByName(column = "column2") +private int column2; +@CsvBindByName(column = "column3") +private boolean column3; +@CsvBindByName(column = "column4") +private double column4; +``` + +Réitérez cette opération pour toutes les colonnes de votre CSV. Vous remarquerez qu’il est nécessaire d’attribuer un type à chaque attribut. Assurez-vous de bien distinguer les types numériques (entiers, réels) des chaînes de caractères. + +Ensuite, créez les différents constructeurs pour votre classe. Commencez par un constructeur vide, indispensable au bon fonctionnement de l’importation. N'oubliez pas d'initialiser la donnée à classifier par défaut. Par exemple, la première donnée correspond à l'indice 0 : + +```java +public [NomDeLaClasse]() { + classificationType = [numéro de la donnée à classifier]; +} +``` + +Puis, créez un constructeur prenant en paramètre tous les attributs définis précédemment, ainsi que le numéro de la donnée à classifier, la première donnée correspondant à l'indice 0 : + +```java +public [NomDeLaClasse](String column1, int column2, boolean column3, double column4) { + super(); + classificationType = [numéro de la donnée à classifier]; + this.column1 = column1; + this.column2 = column2; + this.column3 = column3; + this.column4 = column4; +} +``` + +Enfin, créez un autre constructeur qui accepte une liste d'objets. Chaque élément de cette liste doit être converti au type correspondant à chaque attribut, en commençant par l'élément à l'indice 0 : + +```java +public [NomDeLaClasse](Object[] list) { + this((String) list[0], (int) list[1], (boolean) list[2], (double) list[3]); +} +``` + +Ensuite, modifiez les méthodes `getClassification()` et `setClassification()` pour leur attribuer la valeur que vous souhaitez étudier. C’est à vous de définir cette valeur : + +```java +@Override +public String getClassification() throws IllegalAccessException { + return (String) this.getClass().getDeclaredFields()[classificationType].get(this).toString(); +} + +@Override +public void setClassification(String classification) throws IllegalAccessException { + this.getClass().getDeclaredFields()[classificationType].set(this, classification); +} +``` + +Il vous suffit ensuite de copier-coller cette méthode pour pouvoir définir le type de classification actuel : + +```java +public void setClassificationType(int classificationType) throws IllegalArgumentException, IllegalAccessException { + if (classificationType < 0 || classificationType >= getAttributesNames().size()) { + throw new IllegalArgumentException("Cet attribut n'existe pas."); + } + String keyToVerify = getAttributesNames().keySet().toArray(new String[0])[classificationType]; + if (!getClassifiedAttributes().containsKey(keyToVerify)) { + throw new IllegalArgumentException("Cet attribut ne peut pas être utilisé pour la classification."); + } + LoadableData.classificationType = classificationType; + LoadableData.setClassificationTypes(ClassificationModel.getClassificationModel().getDatas()); +} +``` + +Vous devez ensuite inscrire les différentes classifications que vous souhaitez étudier : + +```java +public Map<String, Object> getClassifiedAttributes() { + Map<String, Object> attributes = new LinkedHashMap<>(); + attributes.put("column1", column1); + attributes.put("column2", column2); + attributes.put("column3", column3); + attributes.put("column4", column4); + return attributes; +} +``` + +Puis ajoutez cette méthode pour pouvoir définir le type de classification : + +```java +@Override +public int getClassificationType() { + return classificationType; +} +``` + +La méthode `getAttributesNames()` renvoie les différents attributs étudiés dans le graphe, c'est-à-dire tous les attributs sauf celui que vous souhaitez classifier. Vous pouvez rendre les noms des attributs plus lisibles que leur nom de variable, comme dans l’exemple ci-dessous : + +```java +@Override +public Map<String, Object> getAttributesNames() { + Map<String, Object> attrNames = new LinkedHashMap<>(); + attrNames.put("Column 1", column1); + attrNames.put("Column 2", column2); + attrNames.put("Column 3", column3); + attrNames.put("Column 4", column4); + return attrNames; +} +``` + +La méthode `getAttributes()` permet de renvoyer les différents attributs numériques sous forme de tableau de doubles. Cela correspond aux données qui pourront être affichées dans le graphe : + +```java +@Override +public double[] getAttributes() { + return new double[]{column1, column2, column3 ? 1.0 : 0.0, column4}; // Assurez-vous de convertir les booléens +} +``` + +La méthode `getStringAttributes()` renvoie un tableau d'attributs de type chaîne de caractères, y compris les valeurs booléennes : + +```java +@Override +public String[] getStringAttributes() { + return new String[]{column1, String.valueOf(column2), String.valueOf(column3)}; +} +``` + +Il ne vous reste plus qu'à personnaliser la méthode `toString()`, qui permet d’afficher les informations d’un point. Vous pouvez entièrement personnaliser l’affichage, mais il est recommandé de respecter cette structure pour une présentation claire : + +```java +@Override +public String toString() { + return "Column 1: " + this.column1 + "\n" + + "Column 2: " + this.column2 + "\n" + + "Column 3: " + this.column3 + "\n" + + "Column 4: " + this.column4 + "\n"; +} +``` + +Votre classe pour le nouveau jeu de données est maintenant prête. + +--- + +Ensuite, vous devez ajouter ce nouveau type à l'énumération `DataType`, en spécifiant le nombre d'arguments à exploiter, soit le nombre de colonnes dans le fichier CSV, moins un (puisque vous avez une colonne pour la classification). + +--- + +Rendez-vous ensuite dans la classe `PointFactory` et ajoutez le code suivant dans le `switch case` de la méthode `createPoint()` : + +```java +case [Nom des données]: + if (size != DataType.[Nom des données].getArgumentSize()) { + throw new IllegalArgumentException("Le nombre de coordonnées doit être de " + DataType.[Nom des données].getArgumentSize() + " pour le type [Nom des données]."); + } + data = new [Nom des données](coords); + break; +``` + +--- + +Ces explications devraient vous permettre d’ajouter des données à la classification. Si vous rencontrez des difficultés lors de votre implémentation, n'hésitez pas à relire ce tutoriel ou à consulter les implémentations existantes. Veillez à vous assurer que toutes les méthodes ont bien été implémentées, sinon l'implémentation ne fonctionnera pas correctement. diff --git a/res/data/pokemon_train_corrige.csv b/res/data/pokemon_train_corrige.csv new file mode 100644 index 0000000000000000000000000000000000000000..01ea9294b691b0236386c7177ca94db8610d594d --- /dev/null +++ b/res/data/pokemon_train_corrige.csv @@ -0,0 +1,508 @@ +name,attack,base_egg_steps,capture_rate,defense,experience_growth,hp,sp_attack,sp_defense,type1,type2,speed,is_legendary +Swablu,40,5120,255.0,60,600000,45,40,75,normal,flying,50,False +Budew,30,5120,255.0,35,1059860,40,50,70,grass,poison,55,False +Minun,40,5120,200.0,50,1000000,60,75,85,electric,,95,False +Metapod,20,3840,120.0,55,1000000,50,25,25,bug,,30,False +Chikorita,49,5120,45.0,65,1059860,45,49,65,grass,,45,False +Pinsir,155,6400,45.0,120,1250000,65,65,90,bug,,105,False +Cinccino,95,3840,60.0,60,800000,75,65,60,normal,,115,False +Elgyem,55,5120,255.0,55,1000000,55,85,55,psychic,,30,False +Foongus,55,5120,190.0,45,1000000,69,55,55,grass,poison,15,False +Ariados,90,3840,90.0,70,800000,70,60,70,bug,poison,40,False +Aipom,70,5120,45.0,55,800000,55,40,55,normal,,85,False +Accelgor,70,3840,75.0,40,1000000,80,100,60,bug,,145,False +Dialga,120,30720,3.0,120,1250000,100,150,100,steel,dragon,90,True +Starly,55,3840,255.0,30,1059860,40,30,30,normal,flying,60,False +Ledyba,20,3840,255.0,30,800000,40,40,80,bug,flying,55,False +Politoed,75,5120,45.0,75,1059860,90,90,100,water,,70,False +Dodrio,110,5120,45.0,70,1000000,60,60,60,normal,flying,110,False +Aggron,140,8960,45.0,230,1250000,70,60,80,steel,rock,50,False +Mankey,80,5120,190.0,35,1000000,40,35,45,fighting,,70,False +Hitmonlee,120,6400,45.0,53,1000000,50,35,110,fighting,,87,False +Oshawott,55,5120,45.0,45,1059860,55,63,45,water,,45,False +Cyndaquil,52,5120,45.0,43,1059860,39,60,50,fire,,65,False +Goldeen,67,5120,225.0,60,1000000,45,35,50,water,,63,False +Swinub,50,5120,225.0,40,1250000,50,30,30,ice,ground,50,False +Nihilego,53,30720,45.0,47,1250000,109,127,131,rock,poison,103,True +Mudkip,70,5120,45.0,50,1059860,50,50,50,water,,40,False +Sewaddle,53,3840,255.0,70,1059860,45,40,60,bug,grass,42,False +Weezing,90,5120,60.0,120,1000000,65,85,70,poison,,60,False +Grumpig,45,5120,60.0,65,800000,80,90,110,psychic,,80,False +Lopunny,136,5120,60.0,94,1000000,65,54,96,normal,,135,False +Togepi,20,2560,190.0,65,800000,35,40,65,fairy,,20,False +Teddiursa,80,5120,120.0,50,1000000,60,50,50,normal,,40,False +Lampent,40,5120,90.0,60,1059860,60,95,60,ghost,fire,55,False +Palkia,120,30720,3.0,100,1250000,90,150,120,water,dragon,100,True +Shroomish,40,3840,255.0,60,1640000,60,40,60,grass,,35,False +Porygon-Z,80,5120,30.0,70,1000000,85,135,75,normal,,90,False +Flygon,100,5120,45.0,80,1059860,80,80,80,ground,dragon,100,False +Tynamo,55,5120,190.0,40,1250000,35,45,40,electric,,60,False +Machop,80,5120,180.0,50,1059860,70,35,35,fighting,,35,False +Zekrom,150,30720,3.0,120,1250000,100,120,100,dragon,electric,90,True +Wigglytuff,70,2560,50.0,45,800000,140,85,50,normal,fairy,45,False +Heracross,185,6400,45.0,115,1250000,80,40,105,bug,fighting,75,False +Archeops,140,7680,45.0,65,1000000,75,112,65,rock,flying,110,False +Gyarados,155,1280,45.0,109,1250000,95,70,130,water,flying,81,False +Gliscor,95,5120,30.0,125,1059860,75,45,75,ground,flying,95,False +Tranquill,77,3840,120.0,62,1059860,62,50,42,normal,flying,65,False +Gardevoir,85,5120,45.0,65,1250000,68,165,135,psychic,fairy,100,False +Azelf,125,20480,3.0,70,1250000,75,125,70,psychic,,115,True +Regice,50,20480,3.0,100,1250000,80,100,200,ice,,50,True +Roselia,60,5120,150.0,45,1059860,50,100,80,grass,poison,65,False +Chimecho,50,6400,45.0,80,800000,75,95,90,psychic,,65,False +Bounsweet,30,5120,235.0,38,1059860,42,30,38,grass,,32,False +Pikachu,55,2560,190.0,40,1000000,35,50,50,electric,,90,False +Articuno,85,20480,3.0,100,1250000,90,95,125,ice,flying,85,True +Machoke,100,5120,90.0,70,1059860,80,50,60,fighting,,45,False +Gumshoos,110,3840,127.0,60,1000000,88,55,60,normal,,45,False +Pikipek,75,3840,255.0,30,1000000,35,30,30,normal,flying,65,False +Cloyster,95,5120,60.0,180,1250000,50,85,45,water,ice,70,False +Crawdaunt,120,3840,155.0,85,1640000,63,90,55,water,dark,55,False +Whismur,51,5120,190.0,23,1059860,64,51,23,normal,,28,False +Silcoon,35,3840,120.0,55,1000000,50,25,25,bug,,15,False +Chandelure,55,5120,45.0,90,1059860,60,145,90,ghost,fire,80,False +Jumpluff,55,5120,45.0,70,1059860,75,55,95,grass,flying,110,False +Amoonguss,85,5120,75.0,70,1000000,114,85,80,grass,poison,30,False +Victreebel,105,5120,45.0,65,1059860,80,100,70,grass,poison,70,False +Metagross,145,10240,3.0,150,1250000,80,105,110,steel,psychic,110,False +Braixen,59,5120,45.0,58,1059860,59,90,70,fire,,73,False +Tapu Bulu,130,3840,3.0,115,1250000,70,85,95,grass,fairy,75,True +Magikarp,10,1280,255.0,55,1250000,20,15,20,water,,80,False +Simisear,98,5120,75.0,63,1000000,75,98,63,fire,,101,False +Charjabug,82,3840,120.0,95,1000000,57,55,75,bug,electric,36,False +Ducklett,44,5120,190.0,50,1000000,62,44,50,water,flying,55,False +Eelektrik,85,5120,60.0,70,1250000,65,75,70,electric,,40,False +Gallade,165,5120,45.0,95,1250000,68,65,115,psychic,fighting,110,False +Fletchling,50,3840,255.0,43,1059860,45,40,38,normal,flying,62,False +Murkrow,85,5120,30.0,42,1059860,60,85,42,dark,flying,91,False +Noctowl,50,3840,90.0,50,1000000,100,86,96,normal,flying,70,False +Anorith,95,7680,45.0,50,600000,45,40,50,rock,bug,75,False +Forretress,90,5120,75.0,140,1000000,75,60,60,bug,steel,40,False +Nidorino,72,5120,120.0,57,1059860,61,55,55,poison,,65,False +Ferroseed,50,5120,255.0,91,1000000,44,24,86,grass,steel,10,False +Chingling,30,6400,120.0,50,800000,45,65,50,psychic,,45,False +Duskull,40,6400,190.0,90,800000,20,30,90,ghost,,25,False +Mimikyu,90,5120,45.0,80,1000000,55,50,105,ghost,fairy,96,False +Fearow,90,3840,90.0,65,1000000,65,61,61,normal,flying,100,False +Reshiram,120,30720,3.0,100,1250000,100,150,120,dragon,fire,90,True +Magnemite,35,5120,190.0,70,1000000,25,95,55,electric,steel,45,False +Huntail,104,5120,60.0,105,600000,55,94,75,water,,52,False +Ambipom,100,5120,45.0,66,800000,75,60,66,normal,,115,False +Snivy,45,5120,45.0,55,1059860,45,45,55,grass,,63,False +Spinda,60,3840,255.0,60,800000,60,60,60,normal,,60,False +Croagunk,61,2560,140.0,40,1000000,48,61,40,poison,fighting,50,False +Mesprit,105,20480,3.0,105,1250000,80,105,105,psychic,,80,True +Poliwag,50,5120,255.0,40,1059860,40,40,40,water,,90,False +Oricorio,70,5120,45.0,70,1000000,75,98,70,fire,flying,93,False +Golurk,124,6400,90.0,80,1000000,89,55,80,ground,ghost,55,False +Armaldo,125,7680,45.0,100,600000,75,70,80,rock,bug,45,False +Electabuzz,83,6400,45.0,57,1000000,65,95,85,electric,,105,False +Ursaring,130,5120,60.0,75,1000000,90,75,75,normal,,55,False +Bewear,125,3840,70.0,80,1000000,120,55,60,normal,fighting,60,False +Charizard,104,5120,45.0,78,1059860,78,159,115,fire,flying,100,False +Vanillite,50,5120,255.0,50,1250000,36,65,60,ice,,44,False +Floette,65,5120,120.0,67,1000000,74,125,128,fairy,,92,False +Happiny,5,10240,130.0,5,800000,100,15,65,normal,,30,False +Deino,65,10240,45.0,50,1250000,52,45,50,dark,dragon,38,False +Hoothoot,30,3840,255.0,30,1000000,60,36,56,normal,flying,50,False +Volcarona,60,10240,15.0,65,1250000,85,135,105,bug,fire,100,False +Sylveon,65,8960,45.0,65,1000000,95,110,130,fairy,,60,False +Finneon,49,5120,190.0,56,600000,49,49,61,water,,66,False +Rufflet,83,5120,190.0,50,1250000,70,37,50,normal,flying,60,False +Karrablast,75,3840,200.0,45,1000000,50,40,45,bug,,60,False +Lotad,30,3840,255.0,30,1059860,40,40,50,water,grass,30,False +Lapras,85,10240,45.0,80,1250000,130,85,95,water,ice,60,False +Poliwhirl,65,5120,120.0,65,1059860,65,50,50,water,,90,False +Sawsbuck,100,5120,75.0,70,1000000,80,60,70,normal,grass,95,False +Piloswine,100,5120,75.0,80,1250000,100,60,60,ice,ground,50,False +Litten,65,3840,45.0,40,1059860,45,60,40,fire,,70,False +Clauncher,53,3840,225.0,62,1250000,50,58,63,water,,44,False +Zoroark,105,5120,45.0,60,1059860,60,120,60,dark,,105,False +Garbodor,95,5120,60.0,82,1000000,80,60,82,poison,,75,False +Deerling,60,5120,190.0,50,1000000,60,40,50,normal,grass,75,False +Illumise,47,3840,150.0,75,1640000,65,73,85,bug,,85,False +Unfezant,115,3840,45.0,80,1059860,80,65,55,normal,flying,93,False +Manaphy,100,2560,3.0,100,1250000,100,100,100,water,,100,True +Glaceon,60,8960,45.0,110,1000000,65,130,95,ice,,65,False +Vikavolt,70,3840,45.0,90,1000000,77,145,75,bug,electric,43,False +Xatu,75,5120,75.0,70,1000000,65,95,70,psychic,flying,95,False +Galvantula,77,5120,75.0,60,1000000,70,97,60,bug,electric,108,False +Fraxure,117,10240,60.0,70,1250000,66,40,50,dragon,,67,False +Exeggcute,40,5120,90.0,80,1250000,60,60,45,grass,psychic,40,False +Baltoy,40,5120,255.0,55,1000000,40,40,70,ground,psychic,55,False +Zebstrika,100,5120,75.0,63,1000000,75,80,63,electric,,116,False +Loudred,71,5120,120.0,43,1059860,84,71,43,normal,,48,False +Cofagrigus,50,6400,90.0,145,1000000,58,95,105,ghost,,30,False +Cubone,50,5120,190.0,95,1000000,50,40,50,ground,,35,False +Virizion,90,20480,3.0,72,1250000,91,90,129,grass,fighting,108,True +Groudon,180,30720,3.0,160,1250000,100,150,90,ground,,90,True +Sunkern,30,5120,235.0,30,1059860,30,30,30,grass,,30,False +Lurantis,105,5120,75.0,90,1000000,70,80,90,grass,,45,False +Quilladin,78,5120,45.0,95,1059860,61,56,58,grass,,57,False +Lunala,113,30720,45.0,89,1250000,137,137,107,psychic,ghost,97,True +Infernape,104,5120,45.0,71,1059860,76,104,71,fire,fighting,108,False +Exploud,91,5120,45.0,63,1059860,104,91,73,normal,,68,False +Zubat,45,3840,255.0,35,1000000,40,30,40,poison,flying,55,False +Tapu Lele,85,3840,3.0,75,1250000,70,130,115,psychic,fairy,95,True +Hakamo-o,75,10240,45.0,90,1250000,55,65,70,dragon,fighting,65,False +Floatzel,105,5120,75.0,55,1000000,85,85,50,water,,115,False +Gurdurr,105,5120,90.0,85,1059860,85,40,50,fighting,,40,False +Kricketot,25,3840,255.0,41,1059860,37,25,41,bug,,25,False +Terrakion,129,20480,3.0,90,1250000,91,72,90,rock,fighting,108,True +Roggenrola,75,3840,255.0,85,1059860,55,25,25,rock,,15,False +Masquerain,60,3840,75.0,62,1000000,70,100,82,bug,flying,80,False +Crabominable,132,5120,60.0,77,1000000,97,62,67,fighting,ice,43,False +Dusknoir,100,6400,45.0,135,800000,45,65,135,ghost,,45,False +Gastrodon,83,5120,75.0,68,1000000,111,92,82,water,ground,39,False +Riolu,70,6400,75.0,40,1059860,40,35,40,fighting,,60,False +Kangaskhan,125,5120,45.0,100,1000000,105,60,100,normal,,100,False +Treecko,45,5120,45.0,35,1059860,40,65,55,grass,,70,False +Darumaka,90,5120,120.0,45,1059860,70,15,45,fire,,50,False +Wartortle,63,5120,45.0,80,1059860,59,65,80,water,,58,False +Azumarill,50,2560,75.0,80,800000,100,60,80,water,fairy,50,False +Swirlix,48,5120,200.0,66,1000000,62,59,57,fairy,,49,False +Shiinotic,45,5120,75.0,80,1000000,60,90,100,grass,fairy,30,False +Spoink,25,5120,255.0,35,800000,60,70,80,psychic,,60,False +Pyukumuku,60,3840,60.0,130,800000,55,30,130,water,,5,False +Rhydon,130,5120,60.0,120,1250000,105,45,45,ground,rock,40,False +Lileep,41,7680,45.0,77,600000,66,61,87,rock,grass,23,False +Steelix,125,6400,25.0,230,1000000,75,55,95,steel,ground,30,False +Palossand,75,3840,60.0,110,1000000,85,100,75,ghost,ground,35,False +Ralts,25,5120,235.0,25,1250000,28,45,35,psychic,fairy,40,False +Buzzwole,139,30720,25.0,139,1250000,107,53,53,bug,fighting,79,True +Wailmer,70,10240,125.0,35,1640000,130,70,35,water,,60,False +Jellicent,60,5120,60.0,70,1000000,100,85,105,water,ghost,60,False +Stunky,63,5120,225.0,47,1000000,63,41,41,poison,dark,74,False +Yungoos,70,3840,255.0,30,1000000,48,30,30,normal,,45,False +Morelull,35,5120,190.0,55,1000000,40,65,75,grass,fairy,15,False +Buizel,65,5120,190.0,35,1000000,55,60,30,water,,85,False +Hippowdon,112,7680,60.0,118,1250000,108,68,72,ground,,47,False +Nidoran♀,47,5120,235.0,52,1059860,55,40,40,poison,,41,False +Samurott,100,5120,45.0,85,1059860,95,108,70,water,,70,False +Omanyte,40,7680,45.0,100,1000000,35,90,55,rock,water,35,False +Blaziken,160,5120,45.0,80,1059860,80,130,80,fire,fighting,100,False +Golbat,80,3840,90.0,70,1000000,75,65,75,poison,flying,90,False +Dratini,64,10240,45.0,45,1250000,41,50,50,dragon,,50,False +Meganium,82,5120,45.0,100,1059860,80,83,100,grass,,80,False +Delphox,69,5120,45.0,72,1059860,75,114,100,fire,psychic,104,False +Corphish,80,3840,205.0,65,1640000,43,50,35,water,,35,False +Araquanid,70,3840,100.0,92,1000000,68,50,132,water,bug,42,False +Cleffa,25,2560,150.0,28,800000,50,45,55,fairy,,15,False +Xurkitree,89,30720,30.0,71,1250000,83,173,71,electric,,83,True +Doduo,85,5120,190.0,45,1000000,35,35,35,normal,flying,75,False +Basculin,92,10240,25.0,65,1000000,70,80,55,water,,98,False +Bidoof,45,3840,255.0,40,1000000,59,35,40,normal,,31,False +Krookodile,117,5120,45.0,80,1059860,95,65,70,ground,dark,92,False +Spinarak,60,3840,255.0,40,800000,40,40,40,bug,poison,30,False +Girafarig,80,5120,60.0,65,1000000,70,90,65,normal,psychic,85,False +Pangoro,124,6400,65.0,78,1000000,95,69,71,fighting,dark,58,False +Butterfree,45,3840,45.0,50,1000000,60,90,80,bug,flying,70,False +Altaria,110,5120,45.0,110,600000,75,110,105,dragon,flying,80,False +Electrode,50,5120,60.0,70,1000000,60,80,80,electric,,150,False +Phanpy,60,5120,120.0,60,1000000,90,40,40,ground,,40,False +Vileplume,80,5120,45.0,85,1059860,75,110,90,grass,poison,50,False +Kyurem,120,30720,3.0,90,1250000,125,170,100,dragon,ice,95,True +Beautifly,70,3840,45.0,50,1000000,60,100,50,bug,flying,65,False +Kommo-o,110,10240,45.0,125,1250000,75,100,105,dragon,fighting,85,False +Zorua,65,6400,75.0,40,1059860,40,80,40,dark,,65,False +Wormadam,69,3840,45.0,95,1000000,60,69,95,bug,grass,36,False +Boldore,105,3840,120.0,105,1059860,70,50,40,rock,,20,False +Meloetta,128,30720,3.0,90,1250000,100,77,77,normal,psychic,128,True +Sandile,72,5120,180.0,35,1059860,50,35,35,ground,dark,65,False +Farfetch'd,90,5120,45.0,55,1000000,52,58,62,normal,flying,60,False +Nosepass,45,5120,255.0,135,1000000,30,45,90,rock,,30,False +Shelgon,95,10240,45.0,100,1250000,65,60,50,dragon,,50,False +Yanmega,76,5120,30.0,86,1000000,86,116,56,bug,flying,95,False +Granbull,120,5120,75.0,75,800000,90,60,60,fairy,,45,False +Grovyle,65,5120,45.0,45,1059860,50,85,65,grass,,95,False +Swoobat,57,3840,45.0,55,1000000,67,77,55,psychic,flying,114,False +Grubbin,62,3840,255.0,45,1000000,47,55,45,bug,,46,False +Lairon,90,8960,90.0,140,1250000,60,50,50,steel,rock,40,False +Kecleon,90,5120,200.0,70,1059860,60,60,120,normal,,40,False +Psyduck,52,5120,190.0,48,1000000,50,65,50,water,,55,False +Gulpin,43,5120,225.0,53,1640000,70,43,53,poison,,40,False +Wobbuffet,33,5120,45.0,58,1000000,190,33,58,psychic,,33,False +Lickilicky,85,5120,30.0,95,1000000,110,80,95,normal,,50,False +Chespin,61,5120,45.0,65,1059860,56,48,45,grass,,38,False +Giratina,120,30720,3.0,100,1250000,150,120,100,ghost,dragon,90,True +Suicune,75,20480,3.0,115,1250000,100,90,115,water,,85,True +Inkay,54,5120,190.0,53,1000000,53,37,46,dark,psychic,45,False +Alakazam,50,5120,50.0,65,1059860,55,175,105,psychic,,150,False +Latias,100,30720,3.0,120,1250000,80,140,150,dragon,psychic,110,True +Popplio,54,3840,45.0,54,1059860,50,66,56,water,,40,False +Magby,75,6400,45.0,37,1000000,45,70,55,fire,,83,False +Aerodactyl,135,8960,45.0,85,1250000,80,70,95,rock,flying,150,False +Drifblim,80,7680,60.0,44,1640000,150,90,54,ghost,flying,80,False +Clawitzer,73,3840,55.0,88,1250000,71,120,89,water,,59,False +Slowbro,75,5120,75.0,180,1000000,95,130,80,water,psychic,30,False +Komala,115,5120,45.0,65,1250000,65,75,95,normal,,65,False +Feebas,15,5120,255.0,20,600000,20,10,55,water,,80,False +Vanilluxe,95,5120,45.0,85,1250000,71,110,95,ice,,79,False +Probopass,55,5120,60.0,145,1000000,60,75,150,rock,steel,40,False +Heliolisk,55,5120,75.0,52,1000000,62,109,94,electric,normal,109,False +Frillish,40,5120,190.0,50,1000000,55,65,85,water,ghost,40,False +Hitmontop,95,6400,45.0,95,1000000,50,35,110,fighting,,70,False +Goodra,100,10240,45.0,70,1250000,90,110,150,dragon,,80,False +Nidorina,62,5120,120.0,67,1059860,70,55,55,poison,,56,False +Umbreon,65,8960,45.0,110,1000000,95,60,130,dark,,65,False +Munna,25,2560,190.0,45,800000,76,67,55,psychic,,24,False +Froslass,80,5120,75.0,70,1000000,70,80,70,ice,ghost,110,False +Abra,20,5120,200.0,15,1059860,25,105,55,psychic,,90,False +Pineco,65,5120,190.0,90,1000000,50,35,35,bug,,15,False +Weepinbell,90,5120,120.0,50,1059860,65,85,45,grass,poison,55,False +Wooper,45,5120,255.0,45,1000000,55,25,25,water,ground,15,False +Arcanine,110,5120,75.0,80,1250000,90,100,80,fire,,95,False +Magcargo,50,5120,75.0,120,1000000,60,90,80,fire,rock,30,False +Feraligatr,105,5120,45.0,100,1059860,85,79,83,water,,78,False +Conkeldurr,140,5120,45.0,95,1059860,105,55,65,fighting,,45,False +Greninja,145,5120,45.0,67,1059860,72,153,71,water,dark,132,False +Toucannon,120,3840,45.0,75,1000000,80,75,75,normal,flying,60,False +Munchlax,85,10240,50.0,40,1250000,135,40,85,normal,,5,False +Oddish,50,5120,255.0,55,1059860,45,75,65,grass,poison,30,False +Chinchou,38,5120,190.0,38,1250000,75,56,56,water,electric,67,False +Rayquaza,180,30720,45.0,100,1250000,105,180,100,dragon,flying,115,True +Scrafty,90,3840,90.0,115,1000000,65,45,115,dark,fighting,58,False +Gourgeist,100,5120,60.0,122,1000000,85,58,75,ghost,grass,54,False +Type: Null,95,30720,3.0,95,1250000,95,95,95,normal,,59,False +Onix,45,6400,45.0,160,1000000,35,30,45,rock,ground,70,False +Remoraid,65,5120,190.0,35,1000000,35,65,35,water,,65,False +Voltorb,30,5120,190.0,50,1000000,40,55,55,electric,,100,False +Glalie,120,5120,75.0,80,1000000,80,120,80,ice,,100,False +Trevenant,110,5120,60.0,76,1000000,85,65,82,ghost,grass,56,False +Dustox,50,3840,45.0,70,1000000,60,50,90,bug,poison,65,False +Drilbur,85,5120,120.0,40,1000000,60,30,45,ground,,68,False +Skiddo,65,5120,200.0,48,1000000,66,62,57,grass,,52,False +Scraggy,75,3840,180.0,70,1000000,50,35,70,dark,fighting,48,False +Venipede,45,3840,255.0,59,1059860,30,30,39,bug,poison,57,False +Kabuto,80,7680,45.0,90,1000000,30,55,45,rock,water,55,False +Latios,130,30720,3.0,100,1250000,80,160,120,dragon,psychic,110,True +Gengar,65,5120,45.0,80,1059860,60,170,95,ghost,poison,130,False +Typhlosion,84,5120,45.0,78,1059860,78,109,85,fire,,100,False +Seaking,92,5120,60.0,65,1000000,80,65,80,water,,68,False +Poochyena,55,3840,255.0,35,1000000,35,30,30,dark,,35,False +Sentret,46,3840,255.0,34,1000000,35,35,45,normal,,20,False +Cottonee,27,5120,190.0,60,1000000,40,37,50,grass,fairy,66,False +Miltank,80,5120,45.0,105,1250000,95,40,70,normal,,100,False +Pachirisu,45,2560,200.0,70,1000000,60,45,90,electric,,95,False +Honchkrow,125,5120,30.0,52,1059860,100,105,52,dark,flying,71,False +Regigigas,160,30720,3.0,110,1250000,110,80,110,normal,,100,True +Combusken,85,5120,45.0,60,1059860,60,85,60,fire,fighting,55,False +Walrein,80,5120,45.0,90,1059860,110,95,90,ice,water,65,False +Monferno,78,5120,45.0,52,1059860,64,78,52,fire,fighting,81,False +Taillow,55,3840,200.0,30,1059860,40,30,30,normal,flying,85,False +Gogoat,100,5120,45.0,62,1000000,123,97,81,grass,,68,False +Comfey,52,5120,60.0,90,800000,51,82,110,fairy,,100,False +Jynx,50,6400,45.0,35,1000000,65,115,95,ice,psychic,95,False +Amaura,59,7680,45.0,50,1000000,77,67,63,rock,ice,46,False +Koffing,65,5120,190.0,95,1000000,40,60,45,poison,,35,False +Swellow,85,3840,45.0,60,1059860,60,75,50,normal,flying,125,False +Vibrava,70,5120,120.0,50,1059860,50,50,50,ground,dragon,70,False +Shiftry,100,3840,45.0,60,1059860,90,90,60,grass,dark,80,False +Crabrawler,82,5120,225.0,57,1000000,47,42,47,fighting,,63,False +Horsea,40,5120,225.0,70,1000000,30,70,25,water,,60,False +Unown,72,10240,225.0,48,1000000,48,72,48,psychic,,48,False +Hitmonchan,105,6400,45.0,79,1000000,50,35,110,fighting,,76,False +Snubbull,80,5120,190.0,50,800000,60,40,40,fairy,,30,False +Kartana,181,30720,255.0,131,1250000,59,59,31,grass,steel,109,True +Slakoth,60,3840,255.0,60,1250000,60,35,35,normal,,30,False +Pansear,53,5120,190.0,48,1000000,50,53,48,fire,,64,False +Maractus,86,5120,255.0,67,1000000,75,106,67,grass,,60,False +Espurr,48,5120,190.0,54,1000000,62,63,60,psychic,,68,False +Cherrim,60,5120,75.0,70,1000000,70,87,78,grass,,85,False +Doublade,110,5120,90.0,150,1000000,59,45,49,steel,ghost,35,False +Tsareena,120,5120,45.0,98,1059860,72,50,98,grass,,72,False +Wimpod,35,5120,90.0,40,1000000,25,20,30,bug,water,80,False +Tyrantrum,121,7680,45.0,119,1000000,82,69,59,rock,dragon,71,False +Bagon,75,10240,45.0,60,1250000,45,40,30,dragon,,50,False +Moltres,100,20480,3.0,90,1250000,90,125,85,fire,flying,90,True +Quagsire,85,5120,90.0,85,1000000,95,65,65,water,ground,35,False +Carvanha,90,5120,225.0,20,1250000,45,65,20,water,dark,65,False +Beldum,55,10240,3.0,80,1250000,40,35,60,steel,psychic,30,False +Mew,100,30720,45.0,100,1059860,100,100,100,psychic,,100,True +Gorebyss,84,5120,60.0,105,600000,55,114,75,water,,52,False +Excadrill,135,5120,60.0,60,1000000,110,50,65,ground,steel,88,False +Mienfoo,85,6400,180.0,50,1059860,45,55,50,fighting,,65,False +Patrat,55,3840,255.0,39,1000000,45,35,39,normal,,42,False +Houndoom,90,5120,45.0,90,1250000,75,140,90,dark,fire,115,False +Uxie,75,20480,3.0,130,1250000,75,75,130,psychic,,95,True +Passimian,120,5120,45.0,90,1250000,100,40,60,fighting,,80,False +Luxio,85,5120,120.0,49,1059860,60,60,49,electric,,60,False +Electrike,45,5120,120.0,40,1250000,40,65,40,electric,,65,False +Jolteon,65,8960,45.0,60,1000000,65,110,95,electric,,130,False +Clefable,70,2560,25.0,73,800000,95,95,90,fairy,,60,False +Goomy,50,10240,45.0,35,1250000,45,55,75,dragon,,40,False +Ampharos,95,5120,45.0,105,1059860,90,165,110,electric,,45,False +Hippopotas,72,7680,140.0,78,1250000,68,38,42,ground,,32,False +Genesect,120,30720,3.0,95,1250000,71,120,95,bug,steel,99,True +Misdreavus,60,6400,45.0,60,800000,60,85,85,ghost,,85,False +Absol,150,6400,30.0,60,1059860,65,115,60,dark,,115,False +Noibat,30,5120,190.0,35,1000000,40,45,40,flying,dragon,55,False +Talonflame,81,3840,45.0,71,1059860,78,74,69,fire,flying,126,False +Stufful,75,3840,140.0,50,1000000,70,45,50,normal,fighting,50,False +Swanna,87,5120,45.0,63,1000000,75,87,63,water,flying,98,False +Dusclops,70,6400,90.0,130,800000,40,60,130,ghost,,25,False +Torkoal,85,5120,90.0,140,1000000,70,85,70,fire,,20,False +Chesnaught,107,5120,45.0,122,1059860,88,74,75,grass,fighting,64,False +Vanillish,65,5120,120.0,65,1250000,51,80,75,ice,,59,False +Spheal,40,5120,255.0,50,1059860,70,55,50,ice,water,25,False +Clefairy,45,2560,150.0,48,800000,70,60,65,fairy,,35,False +Donphan,120,5120,60.0,120,1000000,90,60,60,ground,,50,False +Barbaracle,105,5120,45.0,115,1000000,72,54,86,rock,water,68,False +Aron,70,8960,180.0,100,1250000,50,40,40,steel,rock,30,False +Purrloin,50,5120,255.0,37,1000000,41,50,37,dark,,66,False +Cranidos,125,7680,45.0,40,600000,67,30,30,rock,,58,False +Torchic,60,5120,45.0,40,1059860,45,70,50,fire,,45,False +Growlithe,70,5120,190.0,45,1250000,55,70,50,fire,,60,False +Pancham,82,6400,220.0,62,1000000,67,46,48,fighting,,43,False +Flaaffy,55,5120,120.0,55,1059860,70,80,60,electric,,45,False +Electivire,123,6400,30.0,67,1000000,75,95,85,electric,,95,False +Phantump,70,5120,120.0,48,1000000,43,50,60,ghost,grass,38,False +Steenee,40,5120,120.0,48,1059860,52,40,48,grass,,62,False +Staraptor,120,3840,45.0,70,1059860,85,50,60,normal,flying,100,False +Grotle,89,5120,45.0,85,1059860,75,55,65,grass,,36,False +Emboar,123,5120,45.0,65,1059860,110,100,65,fire,fighting,65,False +Solosis,30,5120,200.0,40,1059860,45,105,50,psychic,,20,False +Hawlucha,92,5120,100.0,75,1000000,78,74,63,fighting,flying,118,False +Servine,60,5120,45.0,75,1059860,60,60,75,grass,,83,False +Tentacool,40,5120,190.0,35,1250000,40,50,100,water,poison,70,False +Shuckle,10,5120,190.0,230,1059860,20,10,230,bug,rock,5,False +Marill,20,2560,190.0,50,800000,70,20,50,water,fairy,40,False +Furfrou,80,5120,160.0,60,1000000,75,65,90,normal,,102,False +Zangoose,115,5120,90.0,60,600000,73,60,60,normal,,90,False +Skitty,45,3840,255.0,45,800000,50,35,35,normal,,50,False +Porygon2,80,5120,45.0,90,1000000,85,105,95,normal,,60,False +Bouffalant,110,5120,45.0,95,1000000,95,40,95,normal,,55,False +Mantine,40,6400,25.0,70,1250000,85,80,140,water,flying,70,False +Avalugg,117,5120,55.0,184,1000000,95,44,46,ice,,28,False +Smoochum,30,6400,45.0,15,1000000,45,85,65,ice,psychic,65,False +Milotic,60,5120,60.0,79,600000,95,100,125,water,,81,False +Frogadier,63,5120,45.0,52,1059860,54,83,56,water,,97,False +Pansage,53,5120,190.0,48,1000000,50,53,48,grass,,64,False +Mr. Mime,45,6400,45.0,65,1000000,40,100,120,psychic,fairy,90,False +Skuntank,93,5120,60.0,67,1000000,103,71,61,poison,dark,84,False +Kyogre,150,30720,3.0,90,1250000,100,180,160,water,,90,True +Kabutops,115,7680,45.0,105,1000000,60,65,70,rock,water,80,False +Minccino,50,3840,255.0,40,800000,55,40,40,normal,,75,False +Croconaw,80,5120,45.0,80,1059860,65,59,63,water,,58,False +Rotom,65,5120,45.0,107,1000000,50,105,107,electric,ghost,86,False +Bayleef,62,5120,45.0,80,1059860,60,63,80,grass,,60,False +Gligar,75,5120,60.0,105,1059860,65,35,65,ground,flying,85,False +Makuhita,60,5120,180.0,30,1640000,72,20,30,fighting,,25,False +Squirtle,48,5120,45.0,65,1059860,44,50,64,water,,43,False +Nidoqueen,92,5120,45.0,87,1059860,90,75,85,poison,ground,76,False +Crustle,105,5120,75.0,125,1000000,70,65,75,bug,rock,45,False +Carnivine,100,6400,200.0,72,1250000,74,90,72,grass,,46,False +Ditto,48,5120,35.0,48,1000000,48,48,48,normal,,48,False +Snorunt,50,5120,190.0,50,1000000,50,50,50,ice,,50,False +Purugly,82,5120,75.0,64,800000,71,64,59,normal,,112,False +Magmortar,95,6400,30.0,67,1000000,75,125,95,fire,,83,False +Magneton,60,5120,60.0,95,1000000,50,120,70,electric,steel,70,False +Bronzong,89,5120,90.0,116,1000000,67,79,116,steel,psychic,33,False +Golett,74,6400,190.0,50,1000000,59,35,50,ground,ghost,35,False +Slaking,160,3840,45.0,100,1250000,150,95,65,normal,,100,False +Burmy,29,3840,120.0,45,1000000,40,29,45,bug,,36,False +Dewgong,70,5120,75.0,80,1000000,90,70,95,water,ice,70,False +Stunfisk,66,5120,75.0,84,1000000,109,81,99,ground,electric,32,False +Gastly,35,5120,190.0,30,1059860,30,100,35,ghost,poison,80,False +Blastoise,103,5120,45.0,120,1059860,79,135,115,water,,78,False +Turtonator,78,5120,70.0,135,1000000,60,91,85,fire,dragon,36,False +Spewpa,22,3840,120.0,60,1000000,45,27,30,bug,,29,False +Pelipper,50,5120,45.0,100,1000000,60,95,70,water,flying,65,False +Stantler,95,5120,45.0,62,1250000,73,85,65,normal,,85,False +Barboach,48,5120,190.0,43,1000000,50,46,41,water,ground,60,False +Phione,80,10240,30.0,80,1250000,80,80,80,water,,80,False +Trumbeak,85,3840,120.0,50,1000000,55,40,50,normal,flying,75,False +Chimchar,58,5120,45.0,44,1059860,44,58,44,fire,,61,False +Luxray,120,5120,45.0,79,1059860,80,95,79,electric,,70,False +Quilava,64,5120,45.0,58,1059860,58,80,65,fire,,80,False +Cosmog,29,30720,45.0,31,1250000,43,29,31,psychic,,37,True +Drampa,60,5120,70.0,85,1000000,78,135,91,normal,dragon,36,False +Camerupt,120,5120,150.0,100,1000000,70,145,105,fire,ground,20,False +Cherubi,35,5120,190.0,45,1000000,45,62,53,grass,,35,False +Breloom,130,3840,90.0,80,1640000,60,60,60,grass,fighting,70,False +Litwick,30,5120,190.0,55,1059860,50,65,55,ghost,fire,20,False +Elekid,63,6400,45.0,37,1000000,45,65,55,electric,,95,False +Roserade,70,5120,75.0,65,1059860,60,125,105,grass,poison,90,False +Joltik,47,5120,190.0,50,1000000,50,57,50,bug,electric,65,False +Lillipup,60,3840,255.0,45,1059860,45,25,45,normal,,55,False +Toxicroak,106,5120,75.0,65,1000000,83,86,65,poison,fighting,85,False +Beheeyem,75,5120,90.0,75,1000000,75,125,95,psychic,,40,False +Incineroar,115,3840,45.0,90,1059860,95,80,90,fire,dark,60,False +Bisharp,125,5120,45.0,100,1000000,65,60,70,dark,steel,70,False +Golisopod,125,5120,45.0,140,1000000,75,60,90,bug,water,40,False +Marshtomp,85,5120,45.0,70,1059860,70,60,70,water,ground,50,False +Mandibuzz,65,5120,60.0,105,1250000,110,55,95,dark,flying,80,False +Togetic,40,2560,75.0,85,800000,55,80,105,fairy,flying,40,False +Wynaut,23,5120,125.0,48,1000000,95,23,48,psychic,,23,False +Klink,55,5120,130.0,70,1059860,40,45,60,steel,,30,False +Blitzle,60,5120,190.0,32,1000000,45,50,32,electric,,76,False +Tyrunt,89,7680,45.0,77,1000000,58,45,45,rock,dragon,48,False +Dunsparce,70,5120,190.0,70,1000000,100,65,65,normal,,45,False +Nidoran♂,57,5120,235.0,40,1059860,46,40,40,poison,,50,False +Vullaby,55,5120,190.0,75,1250000,70,45,65,dark,flying,60,False +Meditite,40,5120,180.0,55,1000000,30,40,55,fighting,psychic,60,False +Alomomola,75,10240,75.0,80,800000,165,40,45,water,,65,False +Parasect,95,5120,75.0,80,1000000,60,60,80,bug,grass,30,False +Spearow,60,3840,255.0,30,1000000,40,31,31,normal,flying,70,False +Tauros,100,5120,45.0,95,1250000,75,40,70,normal,,110,False +Eevee,55,8960,45.0,50,1000000,55,45,65,normal,,55,False +Slugma,40,5120,190.0,40,1000000,40,70,40,fire,,20,False +Beartic,130,5120,60.0,80,1000000,95,70,80,ice,,50,False +Scyther,110,6400,45.0,80,1000000,70,55,80,bug,flying,105,False +Garchomp,170,10240,45.0,115,1250000,108,120,95,dragon,ground,92,False +Kadabra,35,5120,100.0,30,1059860,40,120,70,psychic,,105,False +Combee,30,3840,120.0,42,1059860,30,30,42,bug,flying,70,False +Espeon,65,8960,45.0,60,1000000,65,130,95,psychic,,110,False +Gabite,90,10240,45.0,65,1250000,68,50,55,dragon,ground,82,False +Starmie,75,5120,60.0,85,1250000,60,100,85,water,psychic,115,False +Crobat,90,3840,90.0,80,1000000,85,70,80,poison,flying,130,False +Banette,165,6400,45.0,75,800000,64,93,83,ghost,,75,False +Mudsdale,125,5120,60.0,100,1000000,100,55,85,ground,,35,False +Spritzee,52,5120,200.0,60,1000000,78,63,65,fairy,,23,False +Venomoth,65,5120,75.0,60,1000000,70,90,75,bug,poison,90,False +Shaymin,103,30720,45.0,75,1059860,100,120,75,grass,grass,127,True +Binacle,52,5120,120.0,67,1000000,42,39,56,rock,water,50,False +Skarmory,80,6400,25.0,140,1250000,65,40,70,steel,flying,70,False +Durant,109,5120,90.0,112,1000000,58,48,48,bug,steel,109,False +Ponyta,85,5120,190.0,55,1000000,50,65,65,fire,,90,False +Archen,112,7680,45.0,45,1000000,55,74,45,rock,flying,70,False +Tangrowth,100,5120,30.0,125,1000000,100,110,50,grass,,50,False +Omastar,60,7680,45.0,125,1000000,70,115,70,rock,water,55,False +Druddigon,120,7680,45.0,90,1000000,77,60,90,dragon,,48,False +Ribombee,55,5120,75.0,60,1000000,60,95,70,bug,fairy,124,False +Spiritomb,92,7680,100.0,108,1000000,50,92,108,ghost,dark,35,False +Larvesta,85,10240,45.0,55,1250000,55,50,55,bug,fire,60,False +Ledian,35,3840,90.0,50,800000,55,55,110,bug,flying,85,False +Medicham,100,5120,90.0,85,1000000,60,80,85,fighting,psychic,100,False +Staravia,75,3840,120.0,50,1059860,55,40,40,normal,flying,80,False +Fennekin,45,5120,45.0,40,1059860,40,62,60,fire,,60,False +Tangela,55,5120,45.0,115,1000000,65,100,40,grass,,60,False +Heatran,90,2560,3.0,106,1250000,91,130,106,fire,steel,77,True +Numel,60,5120,255.0,40,1000000,60,65,45,fire,ground,35,False +Deoxys,95,30720,3.0,90,1250000,50,95,90,psychic,,180,True +Venonat,55,5120,190.0,50,1000000,60,40,55,bug,poison,45,False +Mismagius,60,6400,45.0,60,800000,60,105,105,ghost,,105,False +Rowlet,55,3840,45.0,55,1059860,68,50,50,grass,flying,42,False +Dragonite,134,10240,45.0,95,1250000,91,100,100,dragon,flying,80,False +Florges,65,5120,45.0,68,1000000,78,112,154,fairy,,75,False +Musharna,55,2560,75.0,85,800000,116,107,95,psychic,,29,False +Helioptile,38,5120,190.0,33,1000000,44,61,43,electric,normal,70,False +Caterpie,30,3840,255.0,35,1000000,45,20,20,bug,,45,False +Kirlia,35,5120,120.0,35,1250000,38,65,55,psychic,fairy,50,False +Silvally,95,30720,3.0,95,1250000,95,95,95,normal,,95,False +Lickitung,55,5120,45.0,75,1000000,90,60,75,normal,,30,False +Brionne,69,3840,45.0,69,1059860,60,91,81,water,,50,False +Shelmet,40,3840,200.0,85,1000000,50,40,65,bug,,25,False +Cutiefly,45,5120,190.0,40,1000000,40,55,40,bug,fairy,84,False +Togedemaru,98,2560,180.0,63,1000000,65,40,73,electric,steel,96,False +Tentacruel,70,5120,60.0,65,1250000,80,80,120,water,poison,100,False +Shuppet,75,6400,225.0,35,800000,44,63,33,ghost,,45,False +Aurorus,77,7680,45.0,72,1000000,123,99,92,rock,ice,58,False +Slowpoke,65,5120,190.0,65,1000000,90,40,40,water,psychic,15,False +Jirachi,100,30720,3.0,100,1250000,100,100,100,steel,psychic,100,True +Shedinja,90,3840,45.0,45,600000,1,30,30,bug,ghost,40,False +Necrozma,107,30720,3.0,101,1250000,97,127,89,psychic,,79,True +Zweilous,85,10240,45.0,70,1250000,72,65,70,dark,dragon,58,False +Flabébé,38,5120,225.0,39,1000000,44,61,79,fairy,,42,False +Mantyke,20,6400,25.0,50,1250000,45,60,120,water,flying,50,False +Seismitoad,95,5120,45.0,75,1059860,105,85,75,water,ground,74,False diff --git a/res/stages/add-data-stage.fxml b/res/stages/add-data-stage.fxml index 9b58157236839645fcb24b3b5a8a5422cdc7a7dc..2cf27241564c1caee29b07b65773d70f5b52cbc0 100644 --- a/res/stages/add-data-stage.fxml +++ b/res/stages/add-data-stage.fxml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> +<?import javafx.geometry.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> @@ -9,16 +10,19 @@ <Stage fx:id="stage" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.univlille.sae.classification.controller.AddDataController"> <scene> <Scene> - <AnchorPane prefHeight="406.0" prefWidth="385.0"> + <AnchorPane prefHeight="458.0" prefWidth="389.0"> <children> - <VBox alignment="CENTER" layoutY="385.0" prefHeight="38.0" prefWidth="384.0" spacing="20.0"> + <VBox alignment="CENTER" layoutX="1.0" layoutY="420.0" prefHeight="38.0" prefWidth="384.0" spacing="20.0"> <children> <Button fx:id="confirmAdd" mnemonicParsing="false" onAction="#validate" stylesheets="@../css/style.css" text="Valider" textFill="WHITE"> <font> <Font name="System Bold" size="13.0" /> </font></Button> </children></VBox> - <VBox fx:id="entries" layoutY="16.0" prefHeight="366.0" prefWidth="385.0" spacing="10.0" /> + <VBox fx:id="entries" layoutY="-4.0" prefHeight="424.0" prefWidth="390.0" spacing="10.0"> + <opaqueInsets> + <Insets top="1.0" /> + </opaqueInsets></VBox> </children></AnchorPane> </Scene> </scene> diff --git a/res/stages/axes-settings-stage.fxml b/res/stages/axes-settings-stage.fxml index e19aa3020780237261a7602394e6b241b1913e23..f5bcb1d57a7fb0017b0b0086b7f40d2405cde7c3 100644 --- a/res/stages/axes-settings-stage.fxml +++ b/res/stages/axes-settings-stage.fxml @@ -84,11 +84,6 @@ </children></AnchorPane> </content> </Tab> - <Tab text="Couleurs des données"> - <content> - <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" /> - </content> - </Tab> </tabs> </TabPane> </children></AnchorPane> diff --git a/res/stages/choose-attributes.fxml b/res/stages/choose-attributes.fxml new file mode 100644 index 0000000000000000000000000000000000000000..b046d8b6bc710a876fb1681854c3cdb24c1431ef --- /dev/null +++ b/res/stages/choose-attributes.fxml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.*?> +<?import javafx.scene.control.*?> +<?import javafx.scene.layout.*?> +<?import javafx.scene.text.*?> +<?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.ChooseAttributesController"> + <scene> + <Scene> + <AnchorPane prefHeight="175.0" prefWidth="317.0"> + <children> + <VBox alignment="CENTER" prefHeight="200.0" prefWidth="315.0" spacing="30.0" stylesheets="@../css/style.css"> + <children> + <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Veuillez selectionner l'attribut sur lequel vous souhaitez classifier les données" textAlignment="CENTER" wrappingWidth="254.06924438476562" /> + <ChoiceBox fx:id="choice" prefWidth="150.0" stylesheets="@../css/style.css" /> + <Button mnemonicParsing="false" onAction="#validate" stylesheets="@../css/style.css" text="Valider" textFill="WHITE"> + <font> + <Font name="System Bold" size="13.0" /> + </font></Button> + </children> + </VBox> + </children></AnchorPane> + </Scene> + </scene> +</Stage> diff --git a/res/stages/data-view-stage.fxml b/res/stages/data-view-stage.fxml index 9f17a8fd5c75ee133bb950bbb475f88f00c6548f..d2658c4ebee924b06feb5eac100b804aa366305b 100644 --- a/res/stages/data-view-stage.fxml +++ b/res/stages/data-view-stage.fxml @@ -68,14 +68,14 @@ </HBox> <VBox prefHeight="65.0" prefWidth="801.0"> <children> - <HBox fx:id="legend" alignment="CENTER" prefHeight="58.0" prefWidth="762.0" spacing="10.0"> + <VBox fx:id="legend" alignment="CENTER" prefHeight="58.0" prefWidth="762.0" spacing="10.0"> <opaqueInsets> <Insets /> </opaqueInsets> <padding> <Insets left="2.0" right="2.0" /> </padding> - </HBox> + </VBox> </children> </VBox> </children> diff --git a/res/stages/k-NN-stage.fxml b/res/stages/k-NN-stage.fxml index d85e37816d2a07190893f8454bbc57f4dc5c0871..0098c9719114f20d296fe1ef34c6d6b8666f3301 100644 --- a/res/stages/k-NN-stage.fxml +++ b/res/stages/k-NN-stage.fxml @@ -36,7 +36,7 @@ </HBox> <HBox alignment="CENTER" prefHeight="36.0" prefWidth="364.0" spacing="20.0"> <children> - <Spinner fx:id="kEntry" /> + <Spinner fx:id="kEntry" stylesheets="@../css/style.css" /> <Button fx:id="autoK" mnemonicParsing="false" onAction="#bestK" stylesheets="@../css/style.css" text="Attribution auto" textFill="WHITE"> <font> <Font name="System Bold" size="13.0" /> @@ -46,7 +46,7 @@ </HBox> <HBox alignment="CENTER" prefHeight="59.0" prefWidth="364.0"> <children> - <Button fx:id="confirmK" onAction="#validate" mnemonicParsing="false" stylesheets="@../css/style.css" text="Valider" textFill="WHITE"> + <Button fx:id="confirmK" mnemonicParsing="false" onAction="#validate" stylesheets="@../css/style.css" text="Valider" textFill="WHITE"> <font> <Font name="System Bold" size="14.0" /> </font></Button> diff --git a/res/stages/load-data-stage.fxml b/res/stages/load-data-stage.fxml index 6c6f3fc9506adec0621557c674947a76c68e0ef8..026abc2aa9d7e6991c65b0d8924e9a4b797d6c48 100644 --- a/res/stages/load-data-stage.fxml +++ b/res/stages/load-data-stage.fxml @@ -29,7 +29,10 @@ </HBox> <HBox alignment="CENTER" prefHeight="76.0" prefWidth="310.0"> <children> - <Button fx:id="confirmDataSelection" mnemonicParsing="false" onAction="#validate" stylesheets="@../css/style.css" text="Valider" textFill="WHITE" /> + <Button fx:id="confirmDataSelection" mnemonicParsing="false" onAction="#validate" stylesheets="@../css/style.css" text="Valider" textFill="WHITE"> + <font> + <Font name="System Bold" size="13.0" /> + </font></Button> </children> </HBox> </children> diff --git a/src/main/java/fr/univlille/sae/classification/ClassificationApp.java b/src/main/java/fr/univlille/sae/classification/ClassificationApp.java index c3c9cd7cab7f88c31ab2a550418d84daef27a770..1cdf30c244f9c1535bd97ac0af8672e493bb3574 100644 --- a/src/main/java/fr/univlille/sae/classification/ClassificationApp.java +++ b/src/main/java/fr/univlille/sae/classification/ClassificationApp.java @@ -18,7 +18,7 @@ public class ClassificationApp extends Application { * Point d'entrée principal pour l'initialisation de l'interface utilisateur. * Cette méthode configure la vue principale en utilisant une instance du modèle * de classification, puis affiche la fenêtre principale. - * @param stage la fenêtre principale de l'application. + * @param stage La fenêtre principale de l'application. */ public void start(Stage stage) throws IOException { ClassificationModel model = ClassificationModel.getClassificationModel(); @@ -30,7 +30,7 @@ public class ClassificationApp extends Application { /** * Point d'entrée principal de l'application. * Cette méthode lance l'application JavaFX. - * @param args les arguments de ligne de commande. + * @param args Les arguments de ligne de commande. */ public static void main(String[] args) { Application.launch(args); diff --git a/src/main/java/fr/univlille/sae/classification/Main.java b/src/main/java/fr/univlille/sae/classification/Main.java index 84adac9c52050badc03a6fd071244f7d2e781d39..d30364df55c3c17853485353d6c2138b1d13e1e9 100644 --- a/src/main/java/fr/univlille/sae/classification/Main.java +++ b/src/main/java/fr/univlille/sae/classification/Main.java @@ -12,7 +12,7 @@ import java.io.IOException; public class Main { /** * Point d'entrée principal de l'application. - * @param args les arguments de ligne de commande. + * @param args Les arguments de ligne de commande. */ public static void main(String[] args) { ClassificationApp.main(args); diff --git a/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java b/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java index 9a220bdf4e1c24f8db37dad2a63785c1c25873de..9d019f52d8d5aed788bf8c34a139850f79c98c7f 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/AddDataController.java @@ -13,31 +13,39 @@ import javafx.stage.Stage; import java.io.IOException; import java.lang.reflect.Array; import java.time.temporal.Temporal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; /** - * Controlleur pour le FXML add-data-stage, pour ajouter une nouvelle donnée + * Contrôleur pour le fichier FXML "add-data-stage", permettant à l'utilisateur + * d'ajouter une nouvelle donnée dans le modèle de classification. */ public class AddDataController { + /** + * Fenêtre associée à cette vue. + */ @FXML private Stage stage; + /** + * Conteneur contenant les champs d'entrée de données. + */ @FXML private VBox entries; /** - * MainStageView associé au controlleur + * MainStageView associée au contrôleur. */ MainStageView mainStageView; + /** + * Liste des composants d'entrée gérés dynamiquement (Spinner, TextField, + * ChoiceBox) selon le type des données. + */ private List<Object> components; /** - * Méthode d'intitialisation du controlleur + * Méthode d'initialisation du contrôleur. */ @FXML public void initialize() { @@ -45,69 +53,74 @@ public class AddDataController { ClassificationModel model = ClassificationModel.getClassificationModel(); if (!model.getDatas().isEmpty()) { Map<String, Object> attrMap = model.getDatas().get(0).getAttributesNames(); + int classificationType = model.getDatas().get(0).getClassificationType(); for (Map.Entry<String, Object> entry : attrMap.entrySet()) { String attrName = entry.getKey(); Object attrValue = entry.getValue(); - Label label = new Label(attrName); - HBox hbox = new HBox(10, label); - hbox.setAlignment(Pos.CENTER); - hbox.setSpacing(10); + if(!attrMap.keySet().toArray()[classificationType].equals(attrName)) { + Label label = new Label(attrName); + HBox hbox = new HBox(10, label); + hbox.setAlignment(Pos.CENTER); + hbox.setSpacing(10); - if (attrValue instanceof Double) { - Spinner<Double> doubleSpinner = new Spinner<>(); - doubleSpinner.setEditable(true); - SpinnerValueFactory<Double> valueFactory = - new SpinnerValueFactory.DoubleSpinnerValueFactory( - 0.0, - 9999, - 0.0, - 0.5 - ); - doubleSpinner.setValueFactory(valueFactory); - hbox.getChildren().add(doubleSpinner); - components.add(doubleSpinner); + if (attrValue instanceof Double) { + Spinner<Double> doubleSpinner = new Spinner<>(); + doubleSpinner.setEditable(true); + SpinnerValueFactory<Double> valueFactory = + new SpinnerValueFactory.DoubleSpinnerValueFactory( + 0.0, + 9999, + 0.0, + 0.5 + ); + doubleSpinner.setValueFactory(valueFactory); + hbox.getChildren().add(doubleSpinner); + components.add(doubleSpinner); + } + else if (attrValue instanceof Integer) { + Spinner<Integer> integerSpinner = new Spinner<>(); + integerSpinner.setEditable(true); + SpinnerValueFactory<Integer> valueFactory = + new SpinnerValueFactory.IntegerSpinnerValueFactory( + 0, + Integer.MAX_VALUE, + 0, + 1 + ); + integerSpinner.setValueFactory(valueFactory); + hbox.getChildren().add(integerSpinner); + components.add(integerSpinner); + } + else if (attrValue instanceof String) { + TextField textField = new TextField(); + hbox.getChildren().add(textField); + components.add(textField); + } + else if (attrValue instanceof Boolean) { + ChoiceBox<String> choiceBox = new ChoiceBox<>(); + choiceBox.getItems().addAll("VRAI", "FAUX"); + choiceBox.setValue("VRAI"); + hbox.getChildren().add(choiceBox); + components.add(choiceBox); + } + entries.getChildren().add(hbox); } - else if (attrValue instanceof Integer) { - Spinner<Integer> integerSpinner = new Spinner<>(); - integerSpinner.setEditable(true); - SpinnerValueFactory<Integer> valueFactory = - new SpinnerValueFactory.IntegerSpinnerValueFactory( - 0, - Integer.MAX_VALUE, - 0, - 1 - ); - integerSpinner.setValueFactory(valueFactory); - hbox.getChildren().add(integerSpinner); - components.add(integerSpinner); - } - else if (attrValue instanceof String) { - TextField textField = new TextField(); - hbox.getChildren().add(textField); - components.add(textField); - } - else if (attrValue instanceof Boolean) { - ChoiceBox<String> choiceBox = new ChoiceBox<>(); - choiceBox.getItems().addAll("VRAI", "FAUX"); - choiceBox.setValue("VRAI"); - hbox.getChildren().add(choiceBox); - components.add(choiceBox); - } - entries.getChildren().add(hbox); + + } } } /** - * Méthode permettante d'attribuer la mainStageView associer à la classe + * Méthode permettant d'attribuer la mainStageView associée à la classe. * @param mainStageView mainStageView à attribuer */ public void setMainStageView(MainStageView mainStageView) { this.mainStageView = mainStageView; } /** - * Validation des données à ajouter + * Validation des données à ajouter. */ public void validate() { System.out.println("validé"); @@ -136,5 +149,4 @@ public class AddDataController { } stage.close(); } - } diff --git a/src/main/java/fr/univlille/sae/classification/controller/AxesSettingsController.java b/src/main/java/fr/univlille/sae/classification/controller/AxesSettingsController.java index b355ba3bb9c6528d2475e76edadb5ee4fd29bc08..508057c91f7ae07310ecee04773a594fc30ef1d5 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/AxesSettingsController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/AxesSettingsController.java @@ -10,18 +10,27 @@ import javafx.scene.control.SpinnerValueFactory; import javafx.stage.Stage; /** - * Controlleur pour le FXML axes-settings-stage, pour gérer les axes de la vue + * Contrôleur pour le fichier FXML "axes-settings-stage", pour gérer les axes de la vue. */ public class AxesSettingsController{ + /** + * Fenêtre associée à cette vue. + */ @FXML Stage stage; + /** + * Choix des données en axes (abscisse et ordonnée). + */ @FXML ChoiceBox selectOrd; @FXML ChoiceBox selectAbs; + /** + * Choix des limites inférieures et supérieures des axes. + */ @FXML Spinner OrdSizeLower; @@ -36,12 +45,12 @@ public class AxesSettingsController{ /** - * DataVisualizationView associé au controlleur + * DataVisualizationView associé au contrôleur. */ DataVisualizationView dataVisualizationView; /** - * Ajout des éléments à sélectionner pour les ordonnées de la grille + * Ajout des éléments à sélectionner pour les ordonnées de la grille. * @param fields Éléments à ajouter */ public void setSelectOrd(String[] fields){ @@ -51,7 +60,7 @@ public class AxesSettingsController{ } /** - * Ajout des éléments à sélectionner pout les abscisses de la grille + * Ajout des éléments à sélectionner pour les abscisses de la grille. * @param fields Éléments à ajouter */ public void setSelectAbs(String[] fields){ @@ -60,18 +69,34 @@ public class AxesSettingsController{ selectAbs.setValue(dataVisualizationView.getActualX()); } + /** + * Configure la limite supérieure de l'axe des ordonnées. + * @param value Valeur initiale à définir pour la limite supérieure. + */ public void setOrdSizeUpper(double value){ OrdSizeUpper.setValueFactory(new SpinnerValueFactory.DoubleSpinnerValueFactory(0.0, 9999, value,1)); } + /** + * Configure la limite inférieure de l'axe des ordonnées. + * @param value Valeur initiale à définir pour la limite inférieure. + */ public void setOrdSizeLower(double value){ OrdSizeLower.setValueFactory(new SpinnerValueFactory.DoubleSpinnerValueFactory(0.0, 9999, value,1)); } + /** + * Configure la limite supérieure de l'axe des abscisses. + * @param value Valeur initiale à définir pour la limite supérieure. + */ public void setAbsSizeUpper(double value){ AbsSizeUpper.setValueFactory(new SpinnerValueFactory.DoubleSpinnerValueFactory(0.0, 9999, value,1)); } + /** + * Configure la limite inférieure de l'axe des abscisses. + * @param value Valeur initiale à définir pour la limite inférieure. + */ public void setAbsSizeLower(double value){ AbsSizeLower.setValueFactory(new SpinnerValueFactory.DoubleSpinnerValueFactory(0.0, 9999, value,1)); } @@ -85,7 +110,7 @@ public class AxesSettingsController{ } /** - * Validation des paramètres des axes + * Validation des paramètres des axes. */ public void validate(){ if(dataVisualizationView.getActualX() != null || dataVisualizationView.getActualY() != null){ @@ -128,6 +153,10 @@ public class AxesSettingsController{ stage.close(); } + /** + * Réinitialise les paramètres des axes en activant l'ajustement + * automatique et recharge la visualisation des données. + */ public void reset(){ ((NumberAxis) dataVisualizationView.getScatterChart().getXAxis()).setAutoRanging(true); ((NumberAxis) dataVisualizationView.getScatterChart().getYAxis()).setAutoRanging(true); diff --git a/src/main/java/fr/univlille/sae/classification/controller/ChooseAttributesController.java b/src/main/java/fr/univlille/sae/classification/controller/ChooseAttributesController.java new file mode 100644 index 0000000000000000000000000000000000000000..e2105ebd204cf13402dfde477a0559eaf75338e6 --- /dev/null +++ b/src/main/java/fr/univlille/sae/classification/controller/ChooseAttributesController.java @@ -0,0 +1,58 @@ +package fr.univlille.sae.classification.controller; + +import fr.univlille.sae.classification.model.ClassificationModel; +import fr.univlille.sae.classification.model.LoadableData; +import javafx.fxml.FXML; +import javafx.scene.control.ChoiceBox; +import javafx.stage.Stage; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ChooseAttributesController { + + + @FXML + Stage stage; + + + @FXML + ChoiceBox<String> choice; + + + @FXML + public void initialize() { + LoadableData rdmData = ClassificationModel.getClassificationModel().getDatas().get(0); + choice.getItems().addAll(rdmData.getClassifiedAttributes().keySet()); + String value = rdmData.getAttributesNames().keySet().toArray(new String[0])[rdmData.getClassificationType()]; + if(!rdmData.getClassifiedAttributes().containsKey(value)) { + value = (String) rdmData.getClassifiedAttributes().keySet().toArray()[0]; + } + choice.setValue(value); + } + + + + + public void validate() { + String selected = choice.getValue(); + LoadableData rdmData = ClassificationModel.getClassificationModel().getDatas().get(0); + + System.out.println(LoadableData.getClassifications()); + List<String> temp = new ArrayList<>(rdmData.getAttributesNames().keySet()); + + System.out.println(selected); + + System.out.println("Index: " + temp.indexOf(selected)); + try { + rdmData.setClassificationType(temp.indexOf(selected)); + } catch (IllegalAccessException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + stage.close(); + } + +} diff --git a/src/main/java/fr/univlille/sae/classification/controller/DataStageController.java b/src/main/java/fr/univlille/sae/classification/controller/DataStageController.java index edc1926630b2d6e48ec257ef103af2249d61d715..49f0c708a3165b3d42287461c4e94f84f96bf2c7 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/DataStageController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/DataStageController.java @@ -13,45 +13,43 @@ import javafx.stage.Stage; import java.io.IOException; /** - * Controlleur pour le FXML data-view-stage, pour gérer la vue supplémentaire + * Contrôleur pour le fichier FXML "data-view-stage", pour gérer la vue supplémentaire. */ public class DataStageController extends DataVisualizationController{ + /** + * Fenêtre associée à cette vue. + */ @FXML Stage stage; - - - + /** + * Composant ListView pour l'affichage des informations des données d'un point. + */ @FXML ListView PointInfo; - - - + /** + * Initialise le contrôleur en configurant le zoom et le déplacement de la vue. + */ public void initialize() { setupZoom(); setupDrag(); } - - /** - * Associe la dataStageView associer à la classe - * @param dataStageView + * Associe la dataStageView associée à la classe. + * @param dataStageView Instance de dataStageView à associer. */ public void setDataStageView (DataStageView dataStageView) { this.view = dataStageView; } - - - - - + /** + * Retourne l'instance de PointInfo. + * @return Instance de PointInfo. + */ public ListView getPointInfo(){ return this.PointInfo; }; - - } diff --git a/src/main/java/fr/univlille/sae/classification/controller/DataVisualizationController.java b/src/main/java/fr/univlille/sae/classification/controller/DataVisualizationController.java index 5ef74cc7e39ae4b8cb3dd04ad4ae9900740f78e6..471b4f145c3358ae2e32dddefdf5b2abf7e28671 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/DataVisualizationController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/DataVisualizationController.java @@ -11,33 +11,57 @@ import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.stage.Stage; +/** + * Classe abstraite de contrôleur pour les fenêtres de visualisation de données. + */ public abstract class DataVisualizationController { - + /** + * Fenêtre associée à cette vue. + */ @FXML Stage stage; + /** + * Label affichant les axes. + */ @FXML Label AxesSelected; + /** + * Légende de la visualisation. + */ @FXML VBox legend; - + /** + * ScatterChart pour l'affichage des données. + */ @FXML ScatterChart scatterChart; + /** + * Positions x et y du curseur de la souris. + */ protected double initialX; protected double initialY; + + /** + * Limites initiales des axes. + */ protected double initialLowerBoundX; protected double initialUpperBoundX; protected double initialLowerBoundY; protected double initialUpperBoundY; - + /** + * Vue de visualisation des données associé à ce contrôleur. + */ protected DataVisualizationView view; - + /** + * Configure les fonctionnalités de zoom à l'aide de la molette de la souris. + */ protected void setupZoom() { NumberAxis xAxis = (NumberAxis) scatterChart.getXAxis(); NumberAxis yAxis = (NumberAxis) scatterChart.getYAxis(); @@ -82,7 +106,9 @@ public abstract class DataVisualizationController { yAxis.setAutoRanging(true); } - + /** + * Configure les fonctionnalités de déplacement à l'aide de la souris. + */ protected void setupDrag() { scatterChart.setOnMousePressed(event -> { initialX = event.getSceneX(); @@ -117,17 +143,16 @@ public abstract class DataVisualizationController { } /** - * Ouvrir les paramètres des axes de la vue + * Ouvrir les paramètres des axes de la vue. */ public void openAxesSetting(){ AxesSettingsView axesSettingsView = new AxesSettingsView(ClassificationModel.getClassificationModel(), stage, view); axesSettingsView.show(); } - /** - * Renvoie la grille associé à la classe - * @return grille de la classe + * Renvoie la grille associée à la classe. + * @return Grille de la classe */ public ScatterChart getScatterChart() { return this.scatterChart; @@ -135,25 +160,26 @@ public abstract class DataVisualizationController { /** - * Attribut une valeur à l'axe de la grille + * Attribue une valeur à l'axe de la grille. * @param texte Valeur de l'axe */ public void setAxesSelected(String texte) { this.AxesSelected.setText(texte); } - public void setAxesSelectedDisable(){ - this.AxesSelected.setDisable(true); + /** + * Désactive ou active la zone de texte des axes sélectionnés. + */ + public void setAxesSelectedDisability(boolean disability){ + this.AxesSelected.setDisable(disability); } - - + /** + * Charge une légende dans le conteneur dédié. + * @param vBox Conteneur contenant les éléments de la légende + */ public void loadLegend(VBox vBox) { this.legend.getChildren().clear(); this.legend.getChildren().addAll(vBox.getChildren()); } - - - - } diff --git a/src/main/java/fr/univlille/sae/classification/controller/KNNController.java b/src/main/java/fr/univlille/sae/classification/controller/KNNController.java index aed754ea35b2858b197d619a6436712911466db6..41ca88999f1a7ef6ed6950828c5d94c10da77a91 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/KNNController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/KNNController.java @@ -19,24 +19,44 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +/** + * Contrôleur pour la fenêtre de l'algorithme KNN. + */ public class KNNController { + /** + * Fenêtre associée à cette vue. + */ @FXML private Stage stage; + /** + * Menu déroulant pour sélectionner l'algorithme de calcul de distances. + */ @FXML ChoiceBox<String> algoSelector; + /** + * Spinner pour définir le nombre de k (voisins). + */ @FXML Spinner<Integer> kEntry; + /** + * Bouton pour calculer automatiquement le k optimal. + */ @FXML Button autoK; + /** + * Bouton pour valider la classification du point. + */ @FXML Button confirmK; - + /** + * Initialisation du contrôleur. + */ @FXML public void initialize() { int max = (int) Math.sqrt(ClassificationModel.getClassificationModel().getDatas().size()); @@ -51,8 +71,9 @@ public class KNNController { algoSelector.setValue(Distance.getDistanceName(ClassificationModel.getClassificationModel().getDistance())); } - - + /** + * Calcul du k optimal en fonction des données actuelles. + */ public void bestK() { ClassificationModel model = ClassificationModel.getClassificationModel(); @@ -61,8 +82,6 @@ public class KNNController { kEntry.getValueFactory().setValue(model.getkOptimal()); }else { // Calcul du K Optimal: - - Task<Scene> knnTask = new Task<>() { @Override protected Scene call() throws Exception { @@ -130,15 +149,13 @@ public class KNNController { }); new Thread(knnTask).start(); - - - - } } - + /** + * Validation des paramètres de l'algorithme KNN. + */ public void validate() { ClassificationModel model = ClassificationModel.getClassificationModel(); diff --git a/src/main/java/fr/univlille/sae/classification/controller/LoadDataController.java b/src/main/java/fr/univlille/sae/classification/controller/LoadDataController.java index 4baf15fcc240ad98712f30d4d42a49855513be51..78ebe5078f84237ad315f4adb45649393a71c07c 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/LoadDataController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/LoadDataController.java @@ -4,6 +4,9 @@ import com.opencsv.exceptions.CsvException; import com.opencsv.exceptions.CsvRequiredFieldEmptyException; import fr.univlille.sae.classification.model.ClassificationModel; import fr.univlille.sae.classification.model.DataType; +import fr.univlille.sae.classification.model.LoadableData; +import fr.univlille.sae.classification.view.ChooseAttributesView; +import fr.univlille.sae.classification.view.DataVisualizationView; import javafx.fxml.FXML; import javafx.scene.control.Alert; import javafx.scene.control.Button; @@ -15,24 +18,37 @@ import javafx.stage.Stage; import java.io.File; import java.io.IOException; +/** + * Contrôleur pour la fenêtre de chargement des données. + */ public class LoadDataController { - + /** + * Fenêtre associée à cette vue. + */ @FXML Stage stage; - + /** + * Champ de texte affichant le chemin du fichier sélectionné. + */ @FXML TextField filePath; + /** + * Menu déroulant permettant de sélectionner une classification pré-fabriquée des données du fichier. + */ @FXML ChoiceBox<DataType> fileType = new ChoiceBox<>(); /** - * Fichier sélectionné + * Fichier sélectionné. */ File file; + /** + * Initialisation du contrôleur. + */ @FXML public void initialize() { fileType.getItems().addAll(DataType.values()); @@ -40,7 +56,7 @@ public class LoadDataController { } /** - * Ouvre un explorateur de fichiers pour sélectionner le fichier à étudier + * Ouvre un explorateur de fichiers pour sélectionner le fichier à étudier. */ public void openFileChooser() { FileChooser fileChooser = new FileChooser(); @@ -54,9 +70,8 @@ public class LoadDataController { } - /** - * Valide le fichier sélectionné au préalable + * Valide le fichier sélectionné au préalable. */ public void validate(){ @@ -76,13 +91,20 @@ public class LoadDataController { ClassificationModel.getClassificationModel().setType(typeChoisi); try { + DataVisualizationView.resetEachAxis(); + LoadableData.setClassificationTypeGlobal(-1); ClassificationModel.getClassificationModel().loadData(file); + ChooseAttributesView chooseAttributesView = new ChooseAttributesView(ClassificationModel.getClassificationModel(), (Stage) stage.getOwner()); + chooseAttributesView.show(); }catch (RuntimeException | CsvRequiredFieldEmptyException e) { Alert alert = new Alert(Alert.AlertType.ERROR); alert.initOwner(stage); alert.setHeaderText(e.toString()); alert.setContentText("Le chargement du fichier à echoué, veuillez reessayer !"); alert.showAndWait(); + e.printStackTrace(); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); } stage.close(); } diff --git a/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java b/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java index bed2fe9ea1cbc0a630a8026a45faea8404b04698..4fb823c046bf6991387ede7988f73d5ccf3b3a3d 100644 --- a/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java +++ b/src/main/java/fr/univlille/sae/classification/controller/MainStageController.java @@ -12,23 +12,32 @@ import javafx.stage.Stage; import java.io.IOException; +/** + * Contrôleur de la fenêtre principale du programme. + */ public class MainStageController extends DataVisualizationController{ - - + /** + * Bouton pour classifier les points ajoutés par l'utilisateur à l'aide de + * l'algorithme KNN. + */ @FXML Button classifyData; - - - + /** + * Affichage des informations du point sélectionné par l'utilisateur. + */ @FXML ListView PointInfo; - + /** + * Vue principale associée à ce contrôleur. + */ private MainStageView mainStageView; - + /** + * Initialisation du contrôleur. + */ public void initialize() { setupZoom(); setupDrag(); @@ -43,6 +52,10 @@ public class MainStageController extends DataVisualizationController{ loadDataView.show(); } + /** + * Ouvre l'interface de classification des données entrées par l'utilisateur à + * l'aide de l'algorithme KNN. + */ public void openClassification(){ KNNView knnView = new KNNView(ClassificationModel.getClassificationModel(), stage); knnView.show(); @@ -111,10 +124,12 @@ public class MainStageController extends DataVisualizationController{ return this.classifyData; } + /** + * Retourne l'instance de PointInfo. + * @return Instance de PointInfo. + */ public ListView getPointInfo(){ return this.PointInfo; }; - - } diff --git a/src/main/java/fr/univlille/sae/classification/knn/MethodKNN.java b/src/main/java/fr/univlille/sae/classification/knn/MethodKNN.java index 686303ccf2d4e88c048c40d37c40ebe7719370b4..19c4a13f7fc78e7bb6147f553a21362b7a3d9cd3 100644 --- a/src/main/java/fr/univlille/sae/classification/knn/MethodKNN.java +++ b/src/main/java/fr/univlille/sae/classification/knn/MethodKNN.java @@ -12,9 +12,9 @@ import java.util.*; public class MethodKNN { - - - + /** + * Chemin du fichier de données. + */ public static String path = System.getProperty("user.dir") + File.separator + "res" + File.separator; public static double[] amplitude; public static double[] minData; @@ -24,10 +24,9 @@ public class MethodKNN { } - /** - * Permet de mettre a jour les données de l'algorithme. Recalcul les amplitudes et les min/max des données - * @param datas Les données sur lequel l'algorithme doit travailler + * Permet de mettre à jour les données de l'algorithme. Recalcule les amplitudes et les min/max des données. + * @param datas Les données sur lesquelles l'algorithme doit travailler */ public static void updateModel(List<LoadableData> datas) { if(datas.isEmpty()) return; @@ -37,7 +36,6 @@ public class MethodKNN { maxData = new double[numAttributes]; amplitude = new double[numAttributes]; - for(LoadableData l :datas) { double[] attributes = l.getAttributes(); for(int i = 0; i<numAttributes; i++) { @@ -52,86 +50,96 @@ public class MethodKNN { } /** - * Permet de recuperer les K-voisins les plus proches d'une données dans un jeu de données - * en fonction d'une Distance. - * @param datas Le jeu de données - * @param data La donnée avec laquelle calculer la distance - * @param k Le nombre de voisins a recupérer - * @param distance - * @return + * Renvoie une liste des voisins. + * @param datas Liste des données + * @param data Donnée cible + * @param k Nombre de voisins + * @param distance Algorithme de distance utilisée pour calculer la proximité entre les points + * @return Liste des voisins */ public static List<LoadableData> kVoisins(List<LoadableData> datas, LoadableData data, int k, Distance distance) { - // On recupere toutes les données + // On récupère toutes les données. List<LoadableData> voisins = new ArrayList<>(datas); - // on retire la valeur dont on cherche les voisins + // On retire la valeur dont on cherche les voisins. voisins.remove(data); - // On tri la liste en fonction de la distance entre chaque point et data + // On trie la liste en fonction de la distance entre chaque point et data. voisins.sort(new DataComparator(distance, data)); - - // On renvoie les k premier qui sont les k avec la plus petite distance a data + // On renvoie les k premiers qui sont les k avec la plus petite distance à data. return voisins.subList(0, k); - } + /** + * Estime la classe d'une donnée cible en se basant sur ses k plus proches voisins. + * @param datas Liste de données + * @param data Donnée cible + * @param k Nombre de voisins + * @param distance Algorithme de distance utilisée pour calculer la proximité entre les points + * @return Classe estimée pour la donnée cible + * @throws IllegalAccessException + */ + public static String estimateClass(List<LoadableData> datas, LoadableData data, int k, Distance distance) throws IllegalAccessException { - - public static String estimateClass(List<LoadableData> datas, LoadableData data, int k, Distance distance) { - - // On recupere les K voisions de data. + // On récupère les K voisins de data. List<LoadableData> kVoisins = MethodKNN.kVoisins(datas, data, k, distance); - // On compte le nombre de représentation de chaque class parmis les voisins - // Et on récupere la plus présente + // On compte le nombre de représentations de chaque classe parmi les voisins + // Et on récupère la plus présente. Map<String, Integer> classOfNeighbours = new HashMap<>(); String currentClass = kVoisins.get(0).getClassification(); - - for(LoadableData voisin : kVoisins) { int newValue = ((classOfNeighbours.get(voisin.getClassification()) == null) ? 0 : classOfNeighbours.get(voisin.getClassification()) )+ 1; classOfNeighbours.put(voisin.getClassification(), newValue); - // si la classe est plus presente que la classe acutelemnt majoritaire, on change la classe majoritaire. - // Si il y'a egalité alors on garde la premiere trouvé + // Si la classe est plus présente que la classe actuellement majoritaire, on change la classe majoritaire. + // S'il y a égalité, alors on garde la première trouvée. if(classOfNeighbours.get(voisin.getClassification()) > classOfNeighbours.get(currentClass)) { currentClass = voisin.getClassification(); } - } - return currentClass; } - - public static int bestK(List<LoadableData> datas, Distance distance) { - // On borne le K pour eviter de trouver un K trop grand + /** + * Estimation du meilleur K. + * @param datas Liste des données + * @param distance Algorithme de distance utilisée pour calculer la proximité entre les points + * @return Meilleur k déterminé + * @throws IllegalAccessException + */ + public static int bestK(List<LoadableData> datas, Distance distance) throws IllegalAccessException { + // On borne le K pour éviter de trouver un K trop grand int maxK = (int) (Math.sqrt(datas.size())); System.out.println("Max k: " + maxK); int betK = 1; Map<Integer, Double> results = new LinkedHashMap<>(); - // Pour chaque valeur impaire possible de K, on calcul la robustesse (le taux de reussite) de l'algorithme. + // Pour chaque valeur impaire possible de K, on calcule la robustesse (le taux de réussite) de l'algorithme. for(int i =1; i<maxK; i = i +2) { results.put(i, robustesse(datas, i, distance, 0.2)); - // On modifie le meilleur k si le taux est superieur au K precedent - // Si egalité, on garde le premier trouvé + // On modifie le meilleur k si le taux est supérieur au K precedent + // Si égalité, on garde le premier trouvé if(results.get(i) > results.get(betK)) betK = i; } System.out.println("Results: " + results); return betK; - } - - public static double robustesse(List<LoadableData> datas, int k, Distance distance, double testPart) { - - - + /** + * Évaluation de la robustesse de l'algorithme KNN. + * @param datas Liste des données + * @param k Nombre de voisins + * @param distance Algorithme de distance utilisée pour calculer la proximité entre les points + * @param testPart Fraction des données utilisée pour le test + * @return Taux de réussite de l'algorithme pour un k spécifié + * @throws IllegalAccessException + */ + public static double robustesse(List<LoadableData> datas, int k, Distance distance, double testPart) throws IllegalAccessException { double taux = 0; for(int i = 0; i<1/testPart; i++) { @@ -154,20 +162,21 @@ public class MethodKNN { String baseClass = l.getClassification(); if(baseClass.equals(MethodKNN.estimateClass(trainingData,l, k, distance))) totalFind++; } - - // On affiche le taux de reussite a chaque tour System.out.println("total find: " +totalFind + " total try: " + totalTry); taux += (totalFind/(double) totalTry); } - - - return taux/(1/testPart); } - public static void main(String[] args) throws CsvRequiredFieldEmptyException { + /** + * Fonction principale. + * @param args Arguments donnés + * @throws CsvRequiredFieldEmptyException + * @throws IllegalAccessException + */ + public static void main(String[] args) throws CsvRequiredFieldEmptyException, IllegalAccessException { //Test de la robustesse et du meillleur K @@ -178,29 +187,23 @@ public class MethodKNN { MethodKNN.updateModel(model.getDatas()); System.out.println(); + // Permet de définir l'attribut sur lequel l'on souhaite classifier : + LoadableData.setClassificationTypeGlobal(12); + List<LoadableData> datas = ClassificationModel.getClassificationModel().getDatas(); - // On mélange les données pour tester sur differentes variétes car le fichier de base est trié. + // On mélange les données pour tester sur différentes variétés car le fichier de base est trié. Collections.shuffle(datas); for(int i = 0; i<1; i++) { System.out.println("Search best k"); - // On cherche le meilleure K + // On cherche le meilleur K int bestK = MethodKNN.bestK(datas, new DistanceManhattanNormalisee()); System.out.println(bestK); - // Puis on clacul la robustesse avec le K trouvé + // Puis on calcule la robustesse avec le K trouvé System.out.println(MethodKNN.robustesse( datas, bestK, new DistanceManhattanNormalisee(), 0.2)); } - - - } - - - - - - } diff --git a/src/main/java/fr/univlille/sae/classification/knn/distance/Distance.java b/src/main/java/fr/univlille/sae/classification/knn/distance/Distance.java index 24fd3796dd99cc4eb343b15cc679a407b90eac05..fce56cd6a321436e872210e33ecea845b103ca65 100644 --- a/src/main/java/fr/univlille/sae/classification/knn/distance/Distance.java +++ b/src/main/java/fr/univlille/sae/classification/knn/distance/Distance.java @@ -4,9 +4,19 @@ import fr.univlille.sae.classification.model.LoadableData; public interface Distance { - + /** + * Calcul de la distance. + * @param l1 Point 1 + * @param l2 Point 2 + * @return Distance calculée entre les 2 points + */ double distance(LoadableData l1, LoadableData l2); + /** + * Renvoie l'algorithme de distance selon le nom. + * @param name Nom de l'algorithme + * @return Classe liée à l'algorithme de distance + */ static Distance getByName(String name){ switch (name) { case "Euclidienne Normalisée": @@ -21,6 +31,11 @@ public interface Distance { } + /** + * Renvoie le nom de l'algorithme utilisé. + * @param distance Algorithme de distance + * @return Chaîne de caractères correspondante + */ static String getDistanceName(Distance distance){ if (distance instanceof DistanceEuclidienneNormalisee) { return "Euclidienne Normalisee"; diff --git a/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceEuclidienne.java b/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceEuclidienne.java index 954bd42e74f0d548a30bddf29e5fd702fee41734..56611ff42215bcb4d7a3c5e48566dd3f54bff625 100644 --- a/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceEuclidienne.java +++ b/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceEuclidienne.java @@ -4,7 +4,12 @@ import fr.univlille.sae.classification.model.LoadableData; public class DistanceEuclidienne implements Distance { - + /** + * Calcul de la distance. + * @param l1 Point 1 + * @param l2 Point 2 + * @return Distance calculée entre les 2 points + */ @Override public double distance(LoadableData l1, LoadableData l2) { if(l1.getAttributes().length != l2.getAttributes().length) throw new IllegalArgumentException("Error while trying to get Distance : Attributes do not match"); diff --git a/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceEuclidienneNormalisee.java b/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceEuclidienneNormalisee.java index 9be1180ffd7a53d7b2b2d785596fdbfcea7dbefc..812a9afff6b0dff4b6405fd44a800868eef06087 100644 --- a/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceEuclidienneNormalisee.java +++ b/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceEuclidienneNormalisee.java @@ -4,6 +4,13 @@ import fr.univlille.sae.classification.knn.MethodKNN; import fr.univlille.sae.classification.model.LoadableData; public class DistanceEuclidienneNormalisee implements Distance{ + + /** + * Calcul de la distance. + * @param l1 Point 1 + * @param l2 Point 2 + * @return Distance calculée entre les 2 points + */ @Override public double distance(LoadableData l1, LoadableData l2) { if(l1.getAttributes().length != l2.getAttributes().length) throw new IllegalArgumentException("Error while trying to get Distance : Attributes do not match"); @@ -25,6 +32,11 @@ public class DistanceEuclidienneNormalisee implements Distance{ return Math.sqrt(total); } + /** + * Renvoie les valeurs normalisées. + * @param l Liste des valeurs + * @return Tableau des valeurs normalisées + */ private double[] normalise(LoadableData l) { double[] dataNormalise = new double[l.getAttributes().length]; for(int i = 0;i<dataNormalise.length;i++) { diff --git a/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceManhattan.java b/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceManhattan.java index c5ea628f74b3686f8445c32f6519a95a316e7133..799e2818fd2731490864acf6cc1a43a94c533979 100644 --- a/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceManhattan.java +++ b/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceManhattan.java @@ -4,10 +4,14 @@ import fr.univlille.sae.classification.model.LoadableData; public class DistanceManhattan implements Distance{ + /** + * Calcul de la distance. + * @param l1 Point 1 + * @param l2 Point 2 + * @return Distance calculée entre les 2 points + */ public double distance(LoadableData l1, LoadableData l2){ double distance = 0; - - for(int i = 0 ;i<l1.getAttributes().length; i++){ distance = distance + Math.abs(l1.getAttributes()[i]- l2.getAttributes()[i]); } diff --git a/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceManhattanNormalisee.java b/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceManhattanNormalisee.java index 50a678bf52e356b3388b9145b072340f61b72d17..1e30ace45fca9c9d1876a71de163d52a5b75b8a3 100644 --- a/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceManhattanNormalisee.java +++ b/src/main/java/fr/univlille/sae/classification/knn/distance/DistanceManhattanNormalisee.java @@ -6,6 +6,12 @@ import fr.univlille.sae.classification.model.LoadableData; public class DistanceManhattanNormalisee implements Distance{ + /** + * Calcul de la distance. + * @param l1 Point 1 + * @param l2 Point 2 + * @return Distance calculée entre les 2 points + */ @Override public double distance(LoadableData l1, LoadableData l2) { double distance = 0; diff --git a/src/main/java/fr/univlille/sae/classification/model/ClassificationModel.java b/src/main/java/fr/univlille/sae/classification/model/ClassificationModel.java index 403e01cbbfdc0b1b94d65de4ec9196c80d43878a..cfa396d6d507695ad2f8002846d55482002fb129 100644 --- a/src/main/java/fr/univlille/sae/classification/model/ClassificationModel.java +++ b/src/main/java/fr/univlille/sae/classification/model/ClassificationModel.java @@ -20,15 +20,21 @@ import java.util.concurrent.ConcurrentHashMap; * Gère le chargement, l'ajout et la classification des données. */ public class ClassificationModel extends Observable { - + /** + * Données du modèle. + */ private List<LoadableData> datas; private final Map<LoadableData, Boolean> dataToClass; + /** + * Type de données. + */ private DataType type; - private static ClassificationModel model; - private Distance distance; + /** + * Valeurs de k liées à l'algorithme KNN. + */ private int kOptimal; private int k; @@ -90,17 +96,16 @@ public class ClassificationModel extends Observable { .withType(type.getClazz()) .build().parse(); - Set<String> types = new HashSet<>(); - for (LoadableData d : datas) { - types.add(d.getClassification()); - } Collections.shuffle(datas); - LoadableData.setClassificationTypes(types); + + LoadableData.setClassificationTypes(getDatas()); notifyObservers(); } catch (IOException e) { System.err.println("Erreur lors du chargement des données : " + e.getMessage()); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); } } @@ -121,7 +126,11 @@ public class ClassificationModel extends Observable { public void classifierDonnee(LoadableData data) { if(dataToClass.get(data) != null && dataToClass.get(data)) return; this.dataToClass.remove(data); - data.setClassification(MethodKNN.estimateClass(datas, data, k, distance)); + try { + data.setClassification(MethodKNN.estimateClass(datas, data, k, distance)); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } notifyObservers(data); dataToClass.put(data, true); } diff --git a/src/main/java/fr/univlille/sae/classification/model/DataType.java b/src/main/java/fr/univlille/sae/classification/model/DataType.java index 0881c8866aee02eeaf5db1b27dc328bdaad5fc14..a819898819ee389edcbcfc8a5fc0d58bb5bb1cc3 100644 --- a/src/main/java/fr/univlille/sae/classification/model/DataType.java +++ b/src/main/java/fr/univlille/sae/classification/model/DataType.java @@ -1,22 +1,41 @@ package fr.univlille.sae.classification.model; public enum DataType { - IRIS(4, Iris.class), - POKEMON(11, Pokemon.class); + POKEMON(12, Pokemon.class); + /** + * Nombre d'arguments nécessaires. + */ private final int argumentSize; + + /** + * Classe liée à l'élément. + */ private final Class<? extends LoadableData> clazz; + /** + * Constructeur de l'enum. + * @param argumentSize Nombre d'arguments nécessaires + * @param clazz Classe liée + */ DataType(int argumentSize, Class<? extends LoadableData> clazz) { this.argumentSize = argumentSize; this.clazz = clazz; } + /** + * Renvoie le nombre d'arguments. + * @return Nombre d'arguments + */ public int getArgumentSize() { return argumentSize; } + /** + * Renvoie la classe liée à l'élément de l'enum. + * @return Classe liée + */ public Class<? extends LoadableData> getClazz() { return clazz; } diff --git a/src/main/java/fr/univlille/sae/classification/model/Iris.java b/src/main/java/fr/univlille/sae/classification/model/Iris.java index fbf1734713ae37b123b20e4f9f1f06cbfce9fe32..68a6f668ad726eb861774b6220c340689b22b2d3 100644 --- a/src/main/java/fr/univlille/sae/classification/model/Iris.java +++ b/src/main/java/fr/univlille/sae/classification/model/Iris.java @@ -25,7 +25,7 @@ public class Iris extends LoadableData { private String variety; /** - * Constructeur pour créer une instance de Iris avec tous les attributs. + * Constructeur pour créer une instance d'Iris avec tous les attributs. * @param sepalLength longueur du sépale. * @param sepalWidth largeur du sépale. * @param petalLength longueur du pétale. @@ -34,6 +34,7 @@ public class Iris extends LoadableData { */ public Iris(double sepalLength, double sepalWidth, double petalLength, double petalWidth, String variety) { super(); + classificationType = 4; this.sepalWidth = sepalWidth; this.sepalLength = sepalLength; this.petalWidth = petalWidth; @@ -56,25 +57,62 @@ public class Iris extends LoadableData { * Constructeur par défaut. */ public Iris() { - // + classificationType = 4; } /** - * Renvoie la classification (variété) de l'Iris. - * @return variété de l'Iris. + * Renvoie la classification de l'objet. + * + * @return classification sous forme de chaîne. */ @Override - public String getClassification() { - return variety; + public String getClassification() throws IllegalAccessException { + return (String) this.getClass().getDeclaredFields()[classificationType].get(this).toString(); + } + + /** + * Permet de modifier l'attribut sur lequelle ont souhaite classifier + * Ne sont valable que les attributs present dans getClassificationAttributes() + * + * Le numéro de l'attribut correspond a sa place dans la liste de tous le attributs. + * @param classificationType + */ + @Override + public void setClassificationType(int classificationType) throws IllegalArgumentException, IllegalAccessException { + if(classificationType < 0 || classificationType > getAttributesNames().size()) throw new IllegalArgumentException("Cette attribut n'existe pas"); + String keyToVerify = getAttributesNames().keySet().toArray(new String[0])[classificationType]; + if(!getClassifiedAttributes().containsKey(keyToVerify)) throw new IllegalArgumentException("Cette attribut ne peut pas être utiliser pour la classification"); + LoadableData.classificationType = classificationType; + System.out.println("Set type to : " + classificationType); + + LoadableData.setClassificationTypes(ClassificationModel.getClassificationModel().getDatas()); } /** * Définit la classification (variété) de l'Iris. - * @param classification variété à définir. */ @Override - public void setClassification(String classification) { - this.variety = classification; + public Map<String, Object> getClassifiedAttributes() { + Map<String, Object> attributes = new LinkedHashMap<>(); + + attributes.put("Variété", variety); + + return attributes; + } + + @Override + public int getClassificationType() { + return classificationType; + } + + /** + * Définit la classification de l'objet. + * + * @param classification classification à définir. + */ + @Override + public void setClassification(String classification) throws IllegalAccessException { + this.getClass().getDeclaredFields()[classificationType].set(this, classification); } /** @@ -120,10 +158,6 @@ public class Iris extends LoadableData { return new String[0]; } - - - - /** * Renvoie les noms des attributs de l'Iris. * @return tableau de chaînes contenant les noms des attributs. @@ -136,6 +170,7 @@ public class Iris extends LoadableData { attrNames.put("Largeur des sépales", sepalWidth); attrNames.put("Longueur des pétales", petalLength); attrNames.put("Largeur des pétales", petalWidth); + attrNames.put("Variété", variety); return attrNames; } @@ -145,12 +180,16 @@ public class Iris extends LoadableData { */ @Override public String toString() { - return ( - "Sepal length: " + sepalLength + "\n" + - "Sepal width: " + sepalWidth + "\n" + - "Petal length: " + petalLength + "\n" + - "Petal width: " + petalWidth + "\n" + - "Variety: " + getClassification() - ); + try { + return ( + "Sepal length: " + sepalLength + "\n" + + "Sepal width: " + sepalWidth + "\n" + + "Petal length: " + petalLength + "\n" + + "Petal width: " + petalWidth + "\n" + + "Variety: " + getClassification() + ); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } } } diff --git a/src/main/java/fr/univlille/sae/classification/model/LoadableData.java b/src/main/java/fr/univlille/sae/classification/model/LoadableData.java index d1b6696c9a3b53870870913fb953e819b3f1a413..28dc4bb1b39db4a9734b2efa681e418fcd6dc384 100644 --- a/src/main/java/fr/univlille/sae/classification/model/LoadableData.java +++ b/src/main/java/fr/univlille/sae/classification/model/LoadableData.java @@ -1,23 +1,28 @@ package fr.univlille.sae.classification.model; +import javafx.scene.control.Label; import javafx.scene.paint.Color; -import java.util.Map; -import java.util.HashMap; +import java.util.*; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; /** * Classe abstraite représentant des données pouvant être chargées. */ public abstract class LoadableData { - + /** + * Ensemble des types de classification actuellement définis. + */ private static Set<String> classificationTypes; + /** + * Map contenant les classifications associées à leur couleur représentative. + */ private static Map<String, Color> classification = new HashMap<>() ; + protected static int classificationType = 1; + /** * Constructeur par défaut. */ @@ -29,7 +34,7 @@ public abstract class LoadableData { * Renvoie la classification de l'objet. * @return classification sous forme de chaîne. */ - public abstract String getClassification(); + public abstract String getClassification() throws IllegalAccessException; /** * Renvoie les types de classification définis. @@ -39,16 +44,47 @@ public abstract class LoadableData { return classificationTypes; } + /** + * Renvoie une Map des classifications avec leur couleur réprésentative. + * @return Map des classifications avec leur couleur + */ public static Map<String, Color> getClassifications() { return classification; } + /** + * Définit le type de classification global à utiliser. + * @param classificationType Index du type de classification + * @throws IllegalArgumentException + * @throws IllegalAccessException + */ + public static void setClassificationTypeGlobal(int classificationType) throws IllegalArgumentException, IllegalAccessException { + LoadableData.classificationType = classificationType; + } + + /** + * Définit le type de classification pour un objet spécifique. + * @param classificationType Index du type de classification + * @throws IllegalArgumentException + * @throws IllegalAccessException + */ + public abstract void setClassificationType(int classificationType) throws IllegalArgumentException, IllegalAccessException; + /** * Définit les types de classification disponibles. - * @param classificationTypes ensemble de types de classification à définir. + * @param datas Liste des objets + * @throws IllegalAccessException */ - public static void setClassificationTypes(Set<String> classificationTypes) { - LoadableData.classificationTypes = classificationTypes; + public static void setClassificationTypes(List<LoadableData> datas) throws IllegalAccessException { + + Set<String> types = new HashSet<>(); + for (LoadableData d : datas) { + types.add(d.getClassification()); + } + + + classificationTypes = types; + LoadableData.classification.clear(); int nbOfColors = classificationTypes.size() + 1; int nb = 0; @@ -61,7 +97,12 @@ public abstract class LoadableData { LoadableData.classification.put("undefined", getColor(nb,nbOfColors)); } - + /** + * Génère une couleur unique pour chaque type de classification. + * @param nb Numéro de la couleur + * @param totalColors Nombre total de couleurs nécessaires + * @return La couleur générée + */ private static Color getColor(int nb, int totalColors) { // Ratio pour répartir les couleurs uniformément double ratio = (double) nb / (double) totalColors; @@ -83,32 +124,40 @@ public abstract class LoadableData { return Color.color(red, green, blue); } - /* private static Color getColor(int i) { - double ratio = (double) i / classificationTypes.size(); - - // Réduire les composantes pour éviter les tons clairs - double red = 0.2 + 0.6 * ratio; // Entre 0.2 et 0.8 - double green = 0.8 - 0.6 * ratio; // Entre 0.8 et 0.2 - double blue = 0.5 + 0.3 * Math.sin(ratio * Math.PI); // Entre 0.5 et 0.8 - - return Color.color(red, green, blue); - } - + /** + * Renvoie une Map des attributs valides pour la classification. + * @return Map des attributs avec leur nom et valeur + */ + public abstract Map<String, Object> getClassifiedAttributes(); - */ + /** + * + * @return Renvoie l'index du type de la classification. + */ + public abstract int getClassificationType() ; /** * Définit la classification de l'objet. * @param classification classification à définir. */ - public abstract void setClassification(String classification); + public abstract void setClassification(String classification) throws IllegalAccessException; + /** + * Renvoie les noms des attributs de l'objet. + * @return Tableau de chaînes contenant les noms des attributs ainsi que leur variable + */ public abstract Map<String, Object> getAttributesNames(); - - + /** + * Renvoie les attributs numériques. + * @return Tableau des attributs numériques + */ public abstract double[] getAttributes(); + /** + * Renvoie les attributs de type chaînes de caractères. + * @return Tableau des attributs String + */ public abstract String[] getStringAttributes(); } diff --git a/src/main/java/fr/univlille/sae/classification/model/PointFactory.java b/src/main/java/fr/univlille/sae/classification/model/PointFactory.java index 27eba5e9a8c138c2bf0ef639b73bfeada563ed68..2b21cc730329abbe877b630d0dee78bf3a6dc056 100644 --- a/src/main/java/fr/univlille/sae/classification/model/PointFactory.java +++ b/src/main/java/fr/univlille/sae/classification/model/PointFactory.java @@ -1,5 +1,7 @@ package fr.univlille.sae.classification.model; +import java.util.Arrays; + /** * Usine pour créer des objets LoadableData en fonction du type de données. */ @@ -7,15 +9,15 @@ public class PointFactory { /** * Crée un point de données en fonction du type spécifié et des coordonnées fournies. - * @param type type de données - * @param coords coordonnées du point à créer. - * @return instance de LoadableData correspondant aux coordonnées, ou null en cas d'erreur. + * @param type Type de données + * @param coords Coordonnées du point à créer + * @return Instance de LoadableData correspondant aux coordonnées, ou null en cas d'erreur * @throws IllegalArgumentException si le nombre de coordonnées ne correspond pas au type spécifié. */ public static LoadableData createPoint(DataType type, Object[] coords) throws IllegalArgumentException { int size = coords.length; LoadableData data; - + System.out.println("Arrays : " + Arrays.toString(coords) + " " + size); switch (type) { case IRIS: if (size != DataType.IRIS.getArgumentSize()) { @@ -25,14 +27,22 @@ public class PointFactory { break; case POKEMON: if(size != DataType.POKEMON.getArgumentSize()) { - throw new IllegalArgumentException("Le nombre de coordonnées doit être de 11 pour le type POKEMON."); + throw new IllegalArgumentException("Le nombre de coordonnées doit être de 12 pour le type POKEMON."); } data = null; if (coords.length == 13) { - data = new Pokemon(coords); + try { + data = new Pokemon(coords); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Erreur lors de la création du Pokemon"); + } } - else if (coords.length == 11) { - data = new Pokemon((String) coords[0], (Integer) coords[1], (Integer) coords[2], (Double) coords[3], (Integer) coords[4], (Integer) coords[5], (Integer) coords[6], (Integer) coords[7], (Integer) coords[8], "undefined", "", (Double) coords[9], (Boolean) coords[10]); + else if (coords.length == 12) { + try { + data = new Pokemon(coords); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Une erreur est survenue lors de la création du point"); + } } break; default: diff --git a/src/main/java/fr/univlille/sae/classification/model/Pokemon.java b/src/main/java/fr/univlille/sae/classification/model/Pokemon.java index 7ac5fad96ac847d5199b969014b9c3f852fa4e79..7f7e35e32ff6e8a77aba199216197fcb7eed80b7 100644 --- a/src/main/java/fr/univlille/sae/classification/model/Pokemon.java +++ b/src/main/java/fr/univlille/sae/classification/model/Pokemon.java @@ -1,14 +1,15 @@ package fr.univlille.sae.classification.model; import com.opencsv.bean.CsvBindByName; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -public class Pokemon extends LoadableData{ +import java.lang.reflect.Field; +import java.util.*; - // name,attack,base_egg_steps,capture_rate,defense,experience_growth,hp,sp_attack,sp_defense,type1,type2,speed,is_legendary - // Swablu,40,5120,255.0,60,600000,45,75,50,normal,flying,1.2,False +/** + * Représente un point Pokémon. + * Contient des informations sur les statistiques (attaque, défense, PV...) ainsi que les types du monstre. + */ +public class Pokemon extends LoadableData{ @CsvBindByName(column = "name") private String name; @@ -35,11 +36,27 @@ public class Pokemon extends LoadableData{ @CsvBindByName(column = "speed") private double speed; @CsvBindByName(column = "is_legendary") - private boolean isLegendary; - + private Boolean isLegendary = null ; + /** + * Constructeur pour créer une instance de Pokémon avec tous les attributs. + * @param name Nom du monstre + * @param attack Statistique d'attaque + * @param baseEggSteps Pas nécessaires à l'éclosion de son œuf + * @param captureRate Taux de capture + * @param defense Statistique de défense + * @param experienceGrowth Taux de croissance de l'expérience + * @param hp Points de vie + * @param spAttack Statistique d'attaque spéciale + * @param spDefense Statistique de défense spéciale + * @param type1 Type principal + * @param type2 Type secondaire (non obligatoire) + * @param speed Statistique de vitesse + * @param isLegendary Est-il un Pokémon légendaire + */ public Pokemon(String name, int attack, int baseEggSteps, double captureRate, int defense, int experienceGrowth, int hp, int spAttack, int spDefense, String type1, String type2, double speed, boolean isLegendary) { super(); + classificationType = 9; this.name = name; this.attack = attack; this.baseEggSteps = baseEggSteps; @@ -59,44 +76,102 @@ public class Pokemon extends LoadableData{ this.isLegendary = isLegendary; } - public Pokemon(Object[] list) { - this((String) list[0], (Integer) list[1], (Integer) list[2], (Double) list[3], (Integer) list[4], (Integer) list[5], (Integer) list[6], (Integer) list[7], (Integer) list[8], (String) list[9], (String) list[10], (Double) list[11], (Boolean) list[12]); + /** + * Constructeur avec un tableau. + * @param list Tableau d'élements + * @throws IllegalAccessException + */ + public Pokemon(Object[] list) throws IllegalAccessException { + + Field[] fields = getClass().getDeclaredFields(); + for(int i = 0; i<fields.length; i++) { + if(i != LoadableData.classificationType) { + fields[i].set(this, list[i]); + }else if(fields[i].getType().equals(String.class)) { + fields[i].set(this, "undefinied"); + } + } + } /** * Constructeur par défaut. */ public Pokemon() { - // + classificationType = 9; } /** * Renvoie la classification de l'objet. * - * @return classification sous forme de chaîne. + * @return Classification sous forme de chaîne */ @Override - public String getClassification() { - return type1; + public String getClassification() throws IllegalAccessException { + return (String) this.getClass().getDeclaredFields()[classificationType].get(this).toString(); } /** * Définit la classification de l'objet. * - * @param classification classification à définir. + * @param classification Classification à définir */ @Override - public void setClassification(String classification) { - this.type1 = classification; + public void setClassification(String classification) throws IllegalAccessException { + Field field = this.getClass().getDeclaredFields()[classificationType]; + if(field.getClass().equals(String.class)) { + field.set(this, classification); + }else if(field.getType().equals(Boolean.class)) { + field.set(this, Boolean.valueOf(classification)); + } + } /** - * Renvoie les noms des attributs de l'objet. + * Permet de modifier l'attribut sur laquelle l'on souhaite classifier + * Ne sont valables que les attributs présents dans getClassificationAttributes() + * Le numéro de l'attribut correspond à sa place dans la liste de tous les attributs. + * @param classificationType + */ + public void setClassificationType(int classificationType) throws IllegalArgumentException, IllegalAccessException { + if(classificationType < 0 || classificationType > getAttributesNames().size()) throw new IllegalArgumentException("Cette attribut n'existe pas"); + String keyToVerify = getAttributesNames().keySet().toArray(new String[0])[classificationType]; + if(!getClassifiedAttributes().containsKey(keyToVerify)) throw new IllegalArgumentException("Cette attribut ne peut pas être utiliser pour la classification"); + LoadableData.classificationType = classificationType; + System.out.println("Set type to : " + classificationType); + + LoadableData.setClassificationTypes(ClassificationModel.getClassificationModel().getDatas()); + } + + /** + * Renvoie une Map des attributs valides pour la classification. + * @return Map des attributs avec leur nom et valeur + */ + public Map<String, Object> getClassifiedAttributes() { + Map<String, Object> attributes = new LinkedHashMap<>(); + + attributes.put("Experience growth", experienceGrowth); + attributes.put("Type 1", type1); + attributes.put("Type 2", type2); + attributes.put("Is legendary", isLegendary); + + return attributes; + } + + /** * - * @return tableau de chaînes contenant les noms des attributs. + * @return */ + @Override + public int getClassificationType() { + return classificationType; + } + /** + * Renvoie les noms des attributs de l'objet. + * @return Tableau de chaînes contenant les noms des attributs ainsi que leur variable + */ @Override public Map<String, Object> getAttributesNames() { Map<String, Object> attrNames = new LinkedHashMap<>(); @@ -109,27 +184,36 @@ public class Pokemon extends LoadableData{ attrNames.put("HP", hp); attrNames.put("Special attack", spAttack); attrNames.put("Special defense", spDefense); + attrNames.put("Type 1", type1); + attrNames.put("Type 2", type2); attrNames.put("Speed", speed); attrNames.put("Is legendary", isLegendary); return attrNames; } - - - - - + /** + * Renvoie les attributs numériques sous forme de tableau. + * @return Tableau des attributs numériques + */ @Override public double[] getAttributes() { return new double[]{attack, baseEggSteps, captureRate, defense, experienceGrowth, hp, spAttack, spDefense, speed}; } + /** + * Renvoie les attributs de type chaînes de caractères. + * @return Tableau des attributs String + */ @Override public String[] getStringAttributes() { return new String[]{type2, String.valueOf(isLegendary)}; } + /** + * Représentation sous forme de chaîne de l'objet Pokémon. + * @return Chaîne contenant les informations du Pokémon + */ @Override public String toString(){ return( diff --git a/src/main/java/fr/univlille/sae/classification/utils/Observable.java b/src/main/java/fr/univlille/sae/classification/utils/Observable.java index 00a0d47c6bd6daaece5cb36a2738d483320b6bbd..8dd8c8f5d93154585f4241bc975bebd76b3e2814 100644 --- a/src/main/java/fr/univlille/sae/classification/utils/Observable.java +++ b/src/main/java/fr/univlille/sae/classification/utils/Observable.java @@ -8,12 +8,19 @@ import java.util.HashSet; */ public abstract class Observable { + /** + * Liste des observateurs attachés. + */ protected Collection<Observer> attached = new HashSet<>(); + + /** + * Liste des observateurs à détacher. + */ protected Collection<Observer> toDetach = new HashSet<>(); /** * Attache un observateur à l'objet observable. - * @param obs observateur à attacher. + * @param obs Observateur à attacher */ public void attach(Observer obs) { attached.add(obs); @@ -21,7 +28,7 @@ public abstract class Observable { /** * Détache un observateur de l'objet observable. - * @param obs observateur à détacher. + * @param obs Observateur à détacher */ public void detach(Observer obs) { this.toDetach.add(obs); @@ -39,7 +46,7 @@ public abstract class Observable { /** * Notifie tous les observateurs attachés avec des données supplémentaires. - * @param data données à transmettre aux observateurs. + * @param data Données à transmettre aux observateurs */ protected void notifyObservers(Object data) { this.updateList(); diff --git a/src/main/java/fr/univlille/sae/classification/utils/Observer.java b/src/main/java/fr/univlille/sae/classification/utils/Observer.java index 0f7f2081b45365e98f517f4ec7fc366582e3c6cf..fcedd98dfa7b58b7d610c5353f0c726031514880 100644 --- a/src/main/java/fr/univlille/sae/classification/utils/Observer.java +++ b/src/main/java/fr/univlille/sae/classification/utils/Observer.java @@ -13,15 +13,15 @@ public interface Observer { /** * Méthode appelée pour notifier l'observateur qu'un changement s'est produit * dans l'objet observé. - * @param observable l'objet observé qui a subi un changement. + * @param observable L'objet observé qui a subi un changement */ void update(Observable observable); /** * Méthode appelée pour notifier l'observateur qu'un changement s'est produit * dans l'objet observé, avec des données supplémentaires. - * @param observable l'objet observé qui a subi un changement. - * @param data des informations supplémentaires concernant le changement. + * @param observable L'objet observé qui a subi un changement + * @param data Informations supplémentaires concernant le changement */ void update(Observable observable, Object data); diff --git a/src/main/java/fr/univlille/sae/classification/utils/ViewUtil.java b/src/main/java/fr/univlille/sae/classification/utils/ViewUtil.java index 2ae6f8ef46d06a72f0da156f1c350c180a2f7b57..29f9009fd8d2c3b04ad298b19e9e5e78c9d87930 100644 --- a/src/main/java/fr/univlille/sae/classification/utils/ViewUtil.java +++ b/src/main/java/fr/univlille/sae/classification/utils/ViewUtil.java @@ -26,11 +26,13 @@ import java.util.Map; */ public class ViewUtil { + private static Shape clickedForm; + /** - * Définit la couleur de la forme - * @param form forme à configurer. - * @param controller contrôleur principale pour le menu contextuel. - * @return forme configurée. + * Définit la couleur de la forme. + * @param form Forme à configurer + * @param controller Contrôleur principal pour le menu contextuel + * @return Forme configurée */ public static Shape getForm(LoadableData dataLoaded, Shape form, Object controller) { try { @@ -39,14 +41,20 @@ public class ViewUtil { form.setFill(color); form.setOnMouseClicked(e -> { + if(clickedForm!=null) { + clickedForm.setStyle("-fx-stroke-width: 0;"); + } if (controller instanceof DataStageController) { DataStageController dataController = (DataStageController) controller; dataController.getPointInfo().getItems().clear(); dataController.getPointInfo().getItems().add(dataLoaded.toString()); + form.setStyle("-fx-stroke-width: 2;"); } else if (controller instanceof MainStageController) { MainStageController mainController = (MainStageController) controller; mainController.getPointInfo().getItems().clear(); mainController.getPointInfo().getItems().add(dataLoaded.toString()); + form.setStyle("-fx-stroke: #60ffc6; -fx-stroke-width: 3;"); + clickedForm = form; } else { System.err.println("Contrôleur inconnu"); } @@ -57,7 +65,10 @@ public class ViewUtil { return form; } - + /** + * Configuration de la légende. + * @return Le conteneur contenant la légende + */ public static VBox loadLegend() { //Color @@ -76,7 +87,7 @@ public class ViewUtil { line.getChildren().add(tempHBox); String[] colorsString = colors.keySet().toArray(new String[0]); - for(int i = 0 ; i < colorsString.length ; i+= 7) { + for (int i = 0; i < colorsString.length; i += 7) { for (int j = 0; i + j < colorsString.length && j < i + 7; j++) { if (j % 7 == 0 && i != 0) { legend.getChildren().add(line); @@ -87,27 +98,26 @@ public class ViewUtil { tempHBox = new HBox(); label = new Label(colorsString[i + j]); - rectangle = new Rectangle(10, 10); - rectangle.setFill(colors.get(colorsString[i + j])); - tempHBox.getChildren().addAll(rectangle, label); + Circle circle = new Circle(5); + circle.setFill(colors.get(colorsString[i + j])); + tempHBox.getChildren().addAll(circle, label); line.getChildren().add(tempHBox); - - }} + } + } if (colorsString.length < 7) legend.getChildren().add(line); -/** - for(String s : colors.keySet()) { - Circle c = new Circle(5); - c.setFill(colors.get(s)); - label = new Label(s); - tempHBox = new HBox(); - tempHBox.getChildren().addAll(c, label); + /** + for(String s : colors.keySet()) { + Circle c = new Circle(5); + c.setFill(colors.get(s)); + label = new Label(s); + tempHBox = new HBox(); + tempHBox.getChildren().addAll(c, label); - hbox.getChildren().add(tempHBox); - } - */ + hbox.getChildren().add(tempHBox); + } + */ return legend; } - - } + } diff --git a/src/main/java/fr/univlille/sae/classification/view/AddDataView.java b/src/main/java/fr/univlille/sae/classification/view/AddDataView.java index 5acf7069c2bf493f0e82ed9d5c85b8bbe9a589e7..aa924f749b5894b29d2ea4a421a60819fec3785b 100644 --- a/src/main/java/fr/univlille/sae/classification/view/AddDataView.java +++ b/src/main/java/fr/univlille/sae/classification/view/AddDataView.java @@ -16,15 +16,26 @@ import java.net.URL; */ public class AddDataView { + /** + * Modèle de classification utilisé pour gérer les données. + */ private ClassificationModel model; + + /** + * Fenêtre parente de la vue. + */ private Stage owner; + + /** + * La vue principale. + */ private MainStageView mainStageView; /** * Constructeur pour initialiser la vue d'ajout de données. - * @param model le modèle de classification utilisé pour gérer les données. - * @param owner la fenêtre parente de cette vue. - * @param mainStageView la vue principale associée. + * @param model Le modèle de classification utilisé pour gérer les données + * @param owner La fenêtre parente de cette vue + * @param mainStageView La vue principale associée */ public AddDataView(ClassificationModel model, Stage owner, MainStageView mainStageView) { this.model = model; diff --git a/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java b/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java index 041cafc01de1f11ccd76de9a4578c943ea2a06fe..6cfc16851fd38636887fce2dc070f4765a7f4e3e 100644 --- a/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java +++ b/src/main/java/fr/univlille/sae/classification/view/AxesSettingsView.java @@ -19,15 +19,26 @@ import java.util.ArrayList; */ public class AxesSettingsView { + /** + * Modèle de classification utilisé pour gérer les données. + */ private ClassificationModel model; + + /** + * Fenêtre parente de la vue. + */ private Stage owner; + + /** + * Vue de visualisation des données. + */ private DataVisualizationView dataVisualizationView; /** * Constructeur pour initialiser la vue de configuration des axes. - * @param model modèle de classification utilisé pour gérer les données. - * @param owner fenêtre parente de cette vue. - * @param dataVisualizationView vue de visualisation des données associée. + * @param model Modèle de classification utilisé pour gérer les données + * @param owner Fenêtre parente de cette vue + * @param dataVisualizationView Vue de visualisation des données associée */ public AxesSettingsView(ClassificationModel model, Stage owner, DataVisualizationView dataVisualizationView) { this.model = model; diff --git a/src/main/java/fr/univlille/sae/classification/view/ChooseAttributesView.java b/src/main/java/fr/univlille/sae/classification/view/ChooseAttributesView.java new file mode 100644 index 0000000000000000000000000000000000000000..0262ac36210c8131a388aa385e58725db72add0f --- /dev/null +++ b/src/main/java/fr/univlille/sae/classification/view/ChooseAttributesView.java @@ -0,0 +1,79 @@ +package fr.univlille.sae.classification.view; + +import fr.univlille.sae.classification.controller.AddDataController; +import fr.univlille.sae.classification.controller.ChooseAttributesController; +import fr.univlille.sae.classification.model.ClassificationModel; +import javafx.fxml.FXMLLoader; +import javafx.scene.control.Alert; +import javafx.stage.Modality; +import javafx.stage.Stage; + +import java.io.File; +import java.io.IOException; +import java.net.URL; + +/** + * Classe responsable du choix des attributs. + */ +public class ChooseAttributesView { + + /** + * Modèle de classification utilisé pour gérer les données. + */ + private ClassificationModel model; + + /** + * Fenêtre parente de la vue. + */ + private Stage owner; + + /** + * Constructeur pour initialiser la vue de choix des attributs. + * @param model Le modèle de classification + * @param owner La fenêtre parente de cette vue + */ + public ChooseAttributesView(ClassificationModel model, Stage owner) { + this.model = model; + this.owner = owner; + } + + /** + * Affiche la vue du choix des attributs. + */ + public void show() { + FXMLLoader loader = new FXMLLoader(); + URL fxmlFileUrl = getClass().getClassLoader().getResource("stages"+ File.separator+"choose-attributes.fxml"); + + if (fxmlFileUrl == null) { + System.out.println("Impossible de charger le fichier fxml"); + System.exit(-1); + } + + loader.setLocation(fxmlFileUrl); + + try { + Stage root = loader.load(); + // ChooseAttributesController controller = loader.getController(); + + if (model.getDatas().isEmpty()) { + Alert alert = new Alert(Alert.AlertType.WARNING); + alert.setTitle("Erreur"); + alert.setHeaderText(null); + alert.setContentText("Veuillez d'abord charger les données avant de pouvoir choisir l'attribut a classifier"); + alert.showAndWait(); + return; + } + + root.setResizable(false); + root.initOwner(owner); + root.initModality(Modality.APPLICATION_MODAL); + root.setTitle("Choix d'attribut"); + + root.showAndWait(); + } catch (IOException e) { + System.out.println("Erreur lors du chargement de la scène : " + e.getMessage()); + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/fr/univlille/sae/classification/view/DataStageView.java b/src/main/java/fr/univlille/sae/classification/view/DataStageView.java index 68d70c468c480b1ac178c38e901cfddf6f8ee524..95a8fe8fa2a777b2a2c36005aaae7fc85bc09635 100644 --- a/src/main/java/fr/univlille/sae/classification/view/DataStageView.java +++ b/src/main/java/fr/univlille/sae/classification/view/DataStageView.java @@ -3,8 +3,6 @@ package fr.univlille.sae.classification.view; import fr.univlille.sae.classification.controller.DataStageController; import fr.univlille.sae.classification.controller.MainStageController; import fr.univlille.sae.classification.model.ClassificationModel; -import fr.univlille.sae.classification.model.DataType; -import fr.univlille.sae.classification.model.Iris; import fr.univlille.sae.classification.model.LoadableData; import fr.univlille.sae.classification.utils.Observable; import fr.univlille.sae.classification.utils.Observer; @@ -32,17 +30,17 @@ import java.util.Map; * Implémente l'interface Observer pour recevoir des notifications de mise à jour. */ public class DataStageView extends DataVisualizationView implements Observer { - - - - - - + /** + * Regroupements de points. + */ private XYChart.Series series1; private XYChart.Series series2; private XYChart.Series series3; private XYChart.Series series4; + /** + * Fenêtre de la vue secondaire. + */ private Stage root; /** @@ -51,8 +49,6 @@ public class DataStageView extends DataVisualizationView implements Observer { */ public DataStageView(ClassificationModel model) { super(model); - - this.series1 = new XYChart.Series(); this.series2 = new XYChart.Series(); this.series3 = new XYChart.Series(); diff --git a/src/main/java/fr/univlille/sae/classification/view/DataVisualizationView.java b/src/main/java/fr/univlille/sae/classification/view/DataVisualizationView.java index 0ee1a0140fd6e25ea2dba391e677ffcafbe6679a..862a8d1f6b89dca3c476588cf5341df187749ce1 100644 --- a/src/main/java/fr/univlille/sae/classification/view/DataVisualizationView.java +++ b/src/main/java/fr/univlille/sae/classification/view/DataVisualizationView.java @@ -8,23 +8,21 @@ import fr.univlille.sae.classification.model.LoadableData; import fr.univlille.sae.classification.utils.Observable; import fr.univlille.sae.classification.utils.ViewUtil; import javafx.scene.Node; +import javafx.scene.chart.NumberAxis; import javafx.scene.chart.ScatterChart; import javafx.scene.chart.XYChart; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.shape.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Classe abstraite représentant une vue de visualisation des données. * Elle gère les axes actuels et le graphique de dispersion. */ public abstract class DataVisualizationView { - + private static Set<DataVisualizationView> views = new HashSet<>(); public DataVisualizationController controller; private ScatterChart.Series series1; private ScatterChart.Series series2; @@ -45,6 +43,27 @@ public abstract class DataVisualizationView { this.serieList = new HashMap<String, ScatterChart.Series<Double, Double>>(); this.model = model; this.series4 = new XYChart.Series(); + views.add(this); + } + + /** + * Réinitialisation des axes. + */ + public static void resetEachAxis() { + // call method resetAxis for each instance of DataVisualizationView (views) + for(DataVisualizationView view : views) { + view.resetAxis(); + } + } + + /** + * Réinitialisation des axes. + */ + public void resetAxis(){ + setActualY(""); + setActualX(""); + ((NumberAxis) scatterChart.getXAxis()).setLabel(""); + ((NumberAxis) scatterChart.getYAxis()).setLabel(""); } /** @@ -107,11 +126,12 @@ public abstract class DataVisualizationView { scatterChart.getData().clear(); serieList.clear(); - if (actualX == null && actualY == null) { + if (actualX == null && actualY == null || actualY.isEmpty() || actualX.isEmpty()) { controller.setAxesSelected("Aucuns axes sélectionnés"); + controller.setAxesSelectedDisability(false); } else { controller.setAxesSelected(""); - controller.setAxesSelectedDisable(); + controller.setAxesSelectedDisability(true); List<LoadableData> points = new ArrayList<>(model.getDatas()); points.addAll(model.getDataToClass().keySet()); @@ -152,7 +172,7 @@ public abstract class DataVisualizationView { if(editSerie == null){ editSerie = new ScatterChart.Series<Double, Double>(); } - if(data.getClassification().equals("undefined") || model.getDataToClass().containsKey(data)) { + if(data.getClassification().equals("undefined") || data.getClassification().equals("null") || model.getDataToClass().containsKey(data)) { nodePoint = ViewUtil.getForm(data, new Rectangle(10,10), controller); } @@ -189,11 +209,10 @@ public abstract class DataVisualizationView { return; } - - LoadableData newData = (LoadableData) data; - if (actualX == null || actualY == null) { + if (actualX == null || actualY == null || actualY.isEmpty() || actualX.isEmpty()) { controller.setAxesSelected("Aucuns axes sélectionnés"); + controller.setAxesSelectedDisability(false); return; } Object attrX = newData.getAttributesNames().get(actualX); diff --git a/src/main/java/fr/univlille/sae/classification/view/KNNView.java b/src/main/java/fr/univlille/sae/classification/view/KNNView.java index 5df40577e89bfd2bda585d59c9f94ab00fe2e2cb..6e3272cc5ef3d5b0a11fa0413f3fd5ca156ed223 100644 --- a/src/main/java/fr/univlille/sae/classification/view/KNNView.java +++ b/src/main/java/fr/univlille/sae/classification/view/KNNView.java @@ -11,15 +11,24 @@ import java.io.File; import java.io.IOException; import java.net.URL; +/** + * Classe représentant la vue de classification des données avec KNN. + */ public class KNNView { - + /** + * Modèle de classification utilisé pour gérer les données. + */ private ClassificationModel model; + + /** + * Fenêtre parente de la vue. + */ private Stage owner; /** * Constructeur de la vue de chargement des données. - * @param model modèle de classification à utiliser. - * @param owner fenêtre parente. + * @param model Modèle de classification à utiliser + * @param owner Fenêtre parente */ public KNNView(ClassificationModel model, Stage owner) { this.model = model; @@ -27,7 +36,7 @@ public class KNNView { } /** - * + * Charge le fichier FXML et initialise la scène. */ public void show() { FXMLLoader loader = new FXMLLoader(); diff --git a/src/main/java/fr/univlille/sae/classification/view/LoadDataView.java b/src/main/java/fr/univlille/sae/classification/view/LoadDataView.java index e7961d593ab7099dbfcf41f7bcf8cd5861e5e7e6..f1693fed1058515aaf3932f254853754425b1dca 100644 --- a/src/main/java/fr/univlille/sae/classification/view/LoadDataView.java +++ b/src/main/java/fr/univlille/sae/classification/view/LoadDataView.java @@ -15,14 +15,20 @@ import java.net.URL; * Classe responsable de l'affichage de la vue de chargement des données. */ public class LoadDataView { - + /** + * Modèle de classification utilisé pour gérer les données. + */ private ClassificationModel model; + + /** + * Fenêtre parente de la vue. + */ private Stage owner; /** * Constructeur de la vue de chargement des données. - * @param model modèle de classification à utiliser. - * @param owner fenêtre parente. + * @param model Modèle de classification à utiliser + * @param owner Fenêtre parente */ public LoadDataView(ClassificationModel model, Stage owner) { this.model = model; @@ -30,7 +36,7 @@ public class LoadDataView { } /** - * Affiche la fenêtre de chargement des données. + * Charge le fichier FXML et initialise la scène. */ public void show() { FXMLLoader loader = new FXMLLoader(); diff --git a/src/main/java/fr/univlille/sae/classification/view/MainStageView.java b/src/main/java/fr/univlille/sae/classification/view/MainStageView.java index 36661733bc711b9951119c79df26b58938cdbedb..e451f23a71b0481b8142818e34e7fc59efc14286 100644 --- a/src/main/java/fr/univlille/sae/classification/view/MainStageView.java +++ b/src/main/java/fr/univlille/sae/classification/view/MainStageView.java @@ -27,10 +27,14 @@ import java.util.*; */ public class MainStageView extends DataVisualizationView implements Observer { - + /** + * Fenêtre de la vue principale. + */ private Stage root; - + /** + * Regroupements de points. + */ private ScatterChart.Series series1; private ScatterChart.Series series2; private ScatterChart.Series series3;