Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Programme spreadsheet Java

0 views
Skip to first unread message

henryd

unread,
Jun 14, 2021, 5:26:17 AM6/14/21
to
Bonjour,

Dans le cadre du projet, je dois réaliser un petit tableur 10 lignes x 6
colonnes en Java avec un menu permettant de demander à l’utilisateur les actions
à réaliser : afficher le tableur, ajouter une valeur à une cellule, effacer la
valeur dans une cellule, importer un fichier et insérer ses valeurs dans les
cellules, enregistrer le tableur dans un fichier.

J’ai créé différentes classes : Programme (celle qui exécute le programme), Grid
(représente le tableur), Node (la cellule), Value (la valeur d’une cellule),
Tests (permet de tester le programme en fonction de différentes valeur de
cellule), UseCalcGUI et CalcGUI permettant de créer une interface graphique à
partie de JFrame pour afficher le tableur.

J’ai mis les différents fichiers de code, la consigne plus détaillée et autres
informations du projet sur mon repository Github :
https://github.com/henryd02/spreadsheet_java

J’ai actuellement plusieurs points bloquants :

- Le programme n’accepte pas que l’utilisateur rentre du texte, exemple des
références de cellules, ex : (1,1) et des formules du type Moy((1,1), (2,3)).
Pour le moment, mon programme n’accepte que des valeur numérique pour le moment,
c’est surement du à ma gestion de l’erreur mais je n’arrive pas à trouver
comment le résoudre et qu’il accepte du texte :
catch(NumberFormatException e){
System.out.println("e;e;Error: Not a number"e;e;);
}

- Écrire le code pour importer les valeurs d’un fichier dans le tableur. La
méthode loadFile permet d’importer un fichier table.txt dont Chaque valeur de
cellule est séparée par un & et chaque ligne du fichier correspond à une ligne
du tableur. Je pense que je vais parser le fichier ligne par ligne, faire un
slip sur le caractère & et enregistrer les valeurs dans un array list. Puis
insérer ces valeurs dans les cellules du tableur à la ligne correspondante. Je
pense créer une méthode assignCells( array list) dans la classe Grid afin de
réaliser ces opérations, est ce que cela vous semble correcte ?

- Calculer le résultat des formules dans les cellules. Exemple, si la valeur de
la cellule (2,2) est (1,1) + 2, il faut calculer le résultat en remplaçant (1,1)
avec sa valeur numérique. Idem pour les autres opérations arithmétiques : +, -,
*, /, Somme, Moy. Pour le déclenchement des opérations, je pense faire une loop
dans la classe Program qui va parcourir toutes les cellules du tableur et pour
chaque cellule, parser le contenu et détecter s’il y a s’agit d’un opération
avec un opérateur (+, -, *, /, Somme, Moy) et si c’est le cas, réaliser le
calcul. Pour le calcul, je pense créer les méthodes add, substract, multiply,
divide, Sum, Mean dans la classe Grid. Est ce que cela vous semble judicieux ?

- Représentation graphique de la table. Comment connecter le tableur avec
l’interface graphique UseCalcGUI et CalcGUI afin d’afficher les valeurs dans le
layout de la fenêtre. Je ne suis pas encore très à l’aise avec JFrame et donc
j’ai un peu de mal à comprendre comment avoir accès aux parties du Layout. Est
ce que vous auriez des idées ?

La suite du projet demande de gérer les dépendances entre cellules (point 4.2 de
la consigne) en créant un cycle dans les références de cellules lorsqu’une
cellule est modifiée et également de désigner les références de cellules de
manière relative (point 5 de la consigne, le point 3 n’est pas demandé). Je ne
suis pas encore à ces étapes.

Je vous invite à aller faire un tour sur mon repository Github
(https://github.com/henryd02/spreadsheet_java) afin de comprendre plus en détail
le projet, regarder la structure du code et me dire ce qui pourrait être
amélioré,

Je reste à disposition si vous avez besoin d’information complémentaire,

Bien cordialement,

Henry

Yliur

unread,
Jun 15, 2021, 5:49:59 AM6/15/21
to
Le Mon, 14 Jun 2021 04:26:15 -0500, henryd a écrit :

Bonjour

Pour commencer, je dirais que ce projet est sensiblement plus complexe
que le précédent, d'un point de vue algorithmique, modélisation ou
utilisation de bibliothèques (swing, pour l'interface graphique). Mieux
vaut sans doute être à l'aise avec le précédent avant de se lancer dedans.

Es-tu plutôt débutant en programmation ? Est-ce un projet qu'on t'a donné
ou bien un projet que tu as choisi de réaliser pour apprendre ?


> J’ai créé différentes classes : Programme (celle qui exécute le
> programme), Grid (représente le tableur), Node (la cellule), Value (la
> valeur d’une cellule),

Pourquoi ne stockes-tu pas le tableau gridArray dans un attribut de Grid,
au lieu de construire une structure complexe permettant de lier les
cellules les unes aux autres ? Il est plus simple d'accéder aux cellules
par leurs coordonnées.


> J’ai actuellement plusieurs points bloquants :
>
> - Le programme n’accepte pas que l’utilisateur rentre du texte, exemple
> des références de cellules, ex : (1,1) et des formules du type
> Moy((1,1), (2,3)).
> Pour le moment, mon programme n’accepte que des valeur numérique pour le
> moment, c’est surement du à ma gestion de l’erreur mais je n’arrive pas
> à trouver comment le résoudre et qu’il accepte du texte :
> catch(NumberFormatException e){
> System.out.println("e;e;Error: Not a number"e;e;);
> }

Comme je l'ai indiqué dans mon message dans l'autre fil de discussion,
laisse courir les exceptions : ne les capture pas comme ça. Le mieux est
de les laisser planter le programme, tu obtiendras une pile d'appels qui
t'indiquera (et nous indiquera, si tu ne sais pas quoi en faire) à quel
endroit précis le programme a planté.


> - Écrire le code pour importer les valeurs d’un fichier dans le tableur.
> La méthode loadFile permet d’importer un fichier table.txt dont Chaque
> valeur de cellule est séparée par un & et chaque ligne du fichier
> correspond à une ligne du tableur. Je pense que je vais parser le
> fichier ligne par ligne, faire un slip sur le caractère & et enregistrer
> les valeurs dans un array list. Puis insérer ces valeurs dans les
> cellules du tableur à la ligne correspondante. Je pense créer une
> méthode assignCells( array list) dans la classe Grid afin de réaliser
> ces opérations, est ce que cela vous semble correcte ?

Suivant comment ton code est agencé, tu n'as pas forcément besoin du
tableau (ArrayList) intermédiaire. Sinon oui, ça me paraît correct.


> - Calculer le résultat des formules dans les cellules. Exemple, si la
> valeur de la cellule (2,2) est (1,1) + 2, il faut calculer le résultat
> en remplaçant (1,1) avec sa valeur numérique. Idem pour les autres
> opérations arithmétiques : +, -,
> *, /, Somme, Moy. Pour le déclenchement des opérations, je pense faire
> une loop dans la classe Program qui va parcourir toutes les cellules du
> tableur et pour chaque cellule, parser le contenu et détecter s’il y a
> s’agit d’un opération avec un opérateur (+, -, *, /, Somme, Moy) et si
> c’est le cas, réaliser le calcul. Pour le calcul, je pense créer les
> méthodes add, substract, multiply, divide, Sum, Mean dans la classe
> Grid. Est ce que cela vous semble judicieux ?

Non, a priori.

Mais surtout : si tu débutes en programmation, l'analyse syntaxique des
formules, l'exécution de formules et la modélisation des liens entre
cellules pour détecter les cycles et les mises à jour à réaliser, ça me
paraît un peu tendu : il y a pas mal de travail d'algorithmique et de
modélisation. Et dans tous les cas c'est à réaliser (l'analyse syntaxique
et la modélisation des formules au moins) avant de se demander comment
les calculer. Tu n'as jamais eu aucun cours sur ces sujets ?


> - Représentation graphique de la table. Comment connecter le tableur
> avec l’interface graphique UseCalcGUI et CalcGUI afin d’afficher les
> valeurs dans le layout de la fenêtre. Je ne suis pas encore très à
> l’aise avec JFrame et donc j’ai un peu de mal à comprendre comment avoir
> accès aux parties du Layout. Est ce que vous auriez des idées ?

Tu devrais avoir un tableau à deux dimensions représentant les valeurs de
la grille, et tu as un tableau à deux dimensions dans ta fenêtre (nommé
"tft") : quand tu veux mettre à jour la cellule (2,1), tu attrapes le
champ de saisie correspondant dans tft et tu modifies sa valeur. Tu n'as
pas besoin d'accéder aux autres éléments de la fenêtre pour cette mise à
jour.

Yliur

henryd

unread,
Jun 15, 2021, 2:25:39 PM6/15/21
to
Le mardi 15 Juin 2021 à 11:49 par Yliur :
> Le Mon, 14 Jun 2021 04:26:15 -0500, henryd a écrit :
>
> Bonjour
>
> Pour commencer, je dirais que ce projet est sensiblement plus complexe
> que le précédent, d'un point de vue algorithmique,
> modélisation ou
> utilisation de bibliothèques (swing, pour l'interface graphique). Mieux
> vaut sans doute être Í  l'aise avec le
> précédent avant de se lancer dedans.
>
> Es-tu plutÍ´t débutant en programmation ? Est-ce un projet
> qu'on t'a donné
> ou bien un projet que tu as choisi de réaliser pour apprendre ?
>
>
>> J’ai créé différentes classes : Programme (celle
>> qui exécute le
>> programme), Grid (représente le tableur), Node (la cellule), Value (la
>> valeur d’une cellule),
>>
>>
> Pourquoi ne stockes-tu pas le tableau gridArray dans un attribut de Grid,
> au lieu de construire une structure complexe permettant de lier les
> cellules les unes aux autres ? Il est plus simple d'accéder aux cellules
> par leurs coordonnées.
>
>
>> J’ai actuellement plusieurs points bloquants :
>>
>> - Le programme n’accepte pas que l’utilisateur rentre du texte,
>> exemple
>> des références de cellules, ex : (1,1) et des formules du type
>> Moy((1,1), (2,3)).
>> Pour le moment, mon programme n’accepte que des valeur numérique
>> pour le
>> moment, c’est surement du Í  ma gestion de l’erreur
>> mais je n’arrive pas
>> Í  trouver comment le résoudre et qu’il accepte du
>> texte :
>> catch(NumberFormatException e){
>> System.out.println("e;e;Error: Not a number"e;e;);
>> }
>>
>>
> Comme je l'ai indiqué dans mon message dans l'autre fil de discussion,
> laisse courir les exceptions : ne les capture pas comme ça. Le mieux est
> de les laisser planter le programme, tu obtiendras une pile d'appels qui
> t'indiquera (et nous indiquera, si tu ne sais pas quoi en faire) Í 
> quel
> endroit précis le programme a planté.
>
>
>> - Écrire le code pour importer les valeurs d’un fichier dans le
>> tableur.
>> La méthode loadFile permet d’importer un fichier table.txt dont
>> Chaque
>> valeur de cellule est séparée par un & et chaque ligne du
>> fichier
>> correspond Í  une ligne du tableur. Je pense que je vais parser le
>> fichier ligne par ligne, faire un slip sur le caractère & et
>> enregistrer
>> les valeurs dans un array list. Puis insérer ces valeurs dans les
>> cellules du tableur Í  la ligne correspondante. Je pense
>> créer une
>> méthode assignCells( array list) dans la classe Grid afin de
>> réaliser
>> ces opérations, est ce que cela vous semble correcte ?
>>
>>
> Suivant comment ton code est agencé, tu n'as pas forcément besoin
> du
> tableau (ArrayList) intermédiaire. Sinon oui, ça me
> paraͮt correct.
>
>
>> - Calculer le résultat des formules dans les cellules. Exemple, si la
>> valeur de la cellule (2,2) est (1,1) + 2, il faut calculer le résultat
>> en remplaçant (1,1) avec sa valeur numérique. Idem pour les
>> autres
>> opérations arithmétiques : +, -,
>> *, /, Somme, Moy. Pour le déclenchement des opérations, je pense
>> faire
>> une loop dans la classe Program qui va parcourir toutes les cellules du
>> tableur et pour chaque cellule, parser le contenu et détecter
>> s’il y a
>> s’agit d’un opération avec un opérateur (+, -, *, /,
>> Somme, Moy) et si
>> c’est le cas, réaliser le calcul. Pour le calcul, je pense
>> créer les
>> méthodes add, substract, multiply, divide, Sum, Mean dans la classe
>> Grid. Est ce que cela vous semble judicieux ?
>>
>>
> Non, a priori.
>
> Mais surtout : si tu débutes en programmation, l'analyse syntaxique des
> formules, l'exécution de formules et la modélisation des liens
> entre
> cellules pour détecter les cycles et les mises Í  jour
> Í  réaliser, ça me
> paraͮt un peu tendu : il y a pas mal de travail d'algorithmique et
> de
> modélisation. Et dans tous les cas c'est Í  réaliser
> (l'analyse syntaxique
> et la modélisation des formules au moins) avant de se demander comment
> les calculer. Tu n'as jamais eu aucun cours sur ces sujets ?
>
>
>> - Représentation graphique de la table. Comment connecter le tableur
>> avec l’interface graphique UseCalcGUI et CalcGUI afin d’afficher
>> les
>> valeurs dans le layout de la fenêtre. Je ne suis pas encore très
>> Í 
>> l’aise avec JFrame et donc j’ai un peu de mal Í 
>> comprendre comment avoir
>> accès aux parties du Layout. Est ce que vous auriez des idées ?
>>
>>
> Tu devrais avoir un tableau Í  deux dimensions représentant
> les valeurs de
> la grille, et tu as un tableau Í  deux dimensions dans ta
> fenêtre (nommé
> "tft") : quand tu veux mettre Í  jour la cellule (2,1),
> tu attrapes le
> champ de saisie correspondant dans tft et tu modifies sa valeur. Tu n'as
> pas besoin d'accéder aux autres éléments de la
> fenêtre pour cette mise Í 
> jour.
>
> Yliur
Hello Yliur,

Merci beaucoup pour ton retour :)

Me concernant, je suis chef de projet technique en système d’information donc
pas développeur de formation. L’année dernière j’ai commencé à développer en
Python et cette année je me suis mis à Java. Effectivement l’autre projet est
plus simple mais j’ai une échéance plus courte pour celui là donc je dois
avancer dessus :)

Pour répondre aux différents points dans ton message précédent :

- Pour le tableau gridArray en tant qu’attribut de Grid tu as raison ça m’a
l’air beaucoup plus simple. J’étais partie sur une classe Node afin de pratiquer
les classes mais bon pas forcément judicieux. Je vais essayer de voir pour faire
une modification.
Pour les exceptions, effectivement, je les ai laissé courir (finally {}) et ça
m’a permis de voir d’où venait l’erreur et de la corriger, les expressions sont
acceptées maintenant !

- Pour l’importation du fichier dans le tableur, j’ai parsé le contenu du
fichier et importé les différentes valeurs dans un ArrayList puis je l’ai envoyé
à la méthode importFile afin de les transférer dans l’objet Node. Effectivement,
comme tu l’as suggéré, peut-être qu’on pourrait juste enregistrer cet ArrayList
comme attribut de la classe Grid et aussi remplacer les valeurs de l’ArrayList
par l’objet Valeur ayant les attributs : tag, dval, sval utiles par la suite ?

- Pour l’analyse syntaxique des formules dans les cellules, je pensais faire une
Regex Pattern.compile("\\+", Pattern.CASE_INSENSITIVE); afin de détecter les
opérations à faire dans les cellules. Une fois l’opération détectée, faire le
calcul et stocker le résultat dans l’attribut dval de la classe Value. Est ce
que ça te semble une bonne solution ?

- Concernant la modélisation des liens entre les cellules, pour gérer les
dépendances, d’après ce qui était conseillé dans le projet, il faudrait créer en
attribut de chaque cellule (ou de la classe Value), une liste avec les
coordonnées des cellules qui dépendent de C. Pour détecter un cycle, il faut
vérifier, à chaque fois que l’utilisateur rentre une valeur, s’il y une
référence déjà présente dans la liste des cellules qui dépendent de C. Si c’est
le cas, ne pas autoriser à la renseigner. Idem, pour la mise à jour automatique
d’une cellule. A chaque fois qu’une cellule est modifier, il faut mettre à jour
les cellules qui sont renseignées dans la liste des cellules qui dépendent
d’elle et ainsi de suite (la valeur du calcul est stockée dans l’attribut dval
de l’objet Value et la valeur texte (formule) dans l’attribut sval ce qui permet
de pouvoir recalculer la formule). Est ce que cette algorithme te semble
judicieux pour modéliser les liaisons entre les cellules ?

- Merci pour l’information concernant le tableau à 2 dimensions tft afin de
mettre à jour les cellules dans la fenêtre. Je vais regarder afin de mettre les
valeurs contenues dans la liste ArrayList dans le tableau tft pour qu’elles
soient affichées dans l’interface graphique

- Dans le point 5 du projet, il est demandé que le programme prenne en charge
les références de cellules relatives avec le signe $. Pour calculer, la position
d'une cellule ayant une référence relative $(1,2) dans la cellule (2,3) par
exemple est la position absolue : (1,1) (1 ligne plus haute et 2 colonnes vers
la gauche), est bien cela ? Car je n’arrive pas à comprendre l’exemple qu’ils
donnent dans l’explication. Idem que dans l'affichage du contenu de la cellule
référencée de manière absolue, il faut afficher sa valeur dans la cellule de
destination pour pouvoir faire le calcul, je ferai donc la même technique que
celle utilisée pour les références absolues c’est à dire avec le tableau des
références qui dépendent de la cellules

- Je t’invite à me dire s’il y a d’autres points importants que je pourrais
améliorer dans mon code ou qu'il pourrait être intéressant d'approfondir dans le
projet :)

Merci beaucoup pour ton aide :)

Bien cordialement,

Henry

Yliur

unread,
Jun 15, 2021, 4:55:38 PM6/15/21
to
Le Tue, 15 Jun 2021 13:25:37 -0500, henryd a écrit :

> Pour répondre aux différents points dans ton message précédent :
>
> - Pour le tableau gridArray en tant qu’attribut de Grid tu as raison ça
> m’a l’air beaucoup plus simple. J’étais partie sur une classe Node afin
> de pratiquer les classes mais bon pas forcément judicieux. Je vais
> essayer de voir pour faire une modification.

Tu peux tout à fait garder cette classe, simplement il est plus pratique
d'accéder aux cellules par leurs coordonnées que de suivre des liens
entre elles. Au lieu d'une méthode traverse qui parcourt les cellules, tu
aurais une méthode plus simple qui contiendrait
return gridArray[i][j] ;

Par contre tu pourrais peut-être fusionner Node et Value, pour
simplifier. Ce sont bien deux concepts distincts, mais pour chaque
cellule il y a une valeur et réciproquement, donc il est possible de les
fusionner si c'est plus simple.


> - Pour l’importation du fichier dans le tableur, j’ai parsé le contenu
> du fichier et importé les différentes valeurs dans un ArrayList puis je
> l’ai envoyé à la méthode importFile afin de les transférer dans l’objet
> Node. Effectivement, comme tu l’as suggéré, peut-être qu’on pourrait
> juste enregistrer cet ArrayList comme attribut de la classe Grid et
> aussi remplacer les valeurs de l’ArrayList par l’objet Valeur ayant les
> attributs : tag, dval, sval utiles par la suite ?

Je pensais plutôt à mettre tout le code de lecture du fichier dans
importFile et à remplir directement gridArray avec des objets Node/
Value : tu fais déjà les deux boucles sur les lignes et sur les éléments
de la ligne quand tu lis le fichier, il te suffirait de remplir les cases
au fur et à mesure, au lieu de passer par des structures intermédiaires.


> - Pour l’analyse syntaxique des formules dans les cellules, je pensais
> faire une Regex Pattern.compile("\\+", Pattern.CASE_INSENSITIVE); afin
> de détecter les opérations à faire dans les cellules. Une fois
> l’opération détectée, faire le calcul et stocker le résultat dans
> l’attribut dval de la classe Value. Est ce que ça te semble une bonne
> solution ?

En relisant la consigne, je m'aperçois que les calculs en question ne
consistent qu'en une seule opération, ça ne peut pas être complexe. Ça
rend le projet plus abordable que ce que je pensais.

Je ne sais pas très calé en expressions rationnelles. Si tu sais t'en
servir, c'est bien. Sinon les opérations simples de manipulation des
chaînes suffiront.

Il te faut effectivement détecter l'opérateur (opérateur arithmétique ou
fonction Somme/Moy), extraire les opérandes et réaliser l'opération
correspondante.


> - Concernant la modélisation des liens entre les cellules, pour gérer
> les dépendances, d’après ce qui était conseillé dans le projet, il
> faudrait créer en attribut de chaque cellule (ou de la classe Value),
> une liste avec les coordonnées des cellules qui dépendent de C. Pour
> détecter un cycle, il faut vérifier, à chaque fois que l’utilisateur
> rentre une valeur, s’il y une référence déjà présente dans la liste des
> cellules qui dépendent de C. Si c’est le cas, ne pas autoriser à la
> renseigner. Idem, pour la mise à jour automatique d’une cellule. A
> chaque fois qu’une cellule est modifier, il faut mettre à jour les
> cellules qui sont renseignées dans la liste des cellules qui dépendent
> d’elle et ainsi de suite (la valeur du calcul est stockée dans
> l’attribut dval de l’objet Value et la valeur texte (formule) dans
> l’attribut sval ce qui permet de pouvoir recalculer la formule). Est ce
> que cette algorithme te semble judicieux pour modéliser les liaisons
> entre les cellules ?

Vois-tu comment fonctionne la récursion ? Parce que le cycle peut
impliquer un paquet de cellules, il faut remonter les cellules pour
vérifier qu'il n'y a aucun cycle d'aucune longueur. Sais-tu comment faire
ça ?


> - Dans le point 5 du projet, il est demandé que le programme prenne en
> charge les références de cellules relatives avec le signe $. Pour
> calculer, la position d'une cellule ayant une référence relative $(1,2)
> dans la cellule (2,3) par exemple est la position absolue : (1,1) (1
> ligne plus haute et 2 colonnes vers la gauche), est bien cela ? Car je
> n’arrive pas à comprendre l’exemple qu’ils donnent dans l’explication.

C'est ce que je comprends. C'est bizarre de compter comme ça par contre,
j'aurais plutôt considéré les valeurs positives de décalage vers le bas
et la droite.

> Idem que dans l'affichage du contenu de la cellule référencée de manière
> absolue, il faut afficher sa valeur dans la cellule de destination pour
> pouvoir faire le calcul, je ferai donc la même technique que celle
> utilisée pour les références absolues c’est à dire avec le tableau des
> références qui dépendent de la cellules

Oui.


> - Je t’invite à me dire s’il y a d’autres points importants que je
> pourrais améliorer dans mon code ou qu'il pourrait être intéressant
> d'approfondir dans le projet :)

Ça me paraît déjà beaucoup de travail... :)

Il reste pas mal d'endroits où tu ne laisses pas filer les exceptions,
c'est dommage en cas de bug.

Note que si tu laisses filer les exceptions le try/catch ou try-finally
n'est pas nécessaire (sauf dans le cas où tu utilises la try pour gérer
automatiquement la fermeture de flux, comme InputStream).

henryd

unread,
Jun 17, 2021, 2:33:26 AM6/17/21
to
Le mardi 15 Juin 2021 à 22:55 par Yliur :
> Le Tue, 15 Jun 2021 13:25:37 -0500, henryd a écrit :
>
>> Pour répondre aux différents points dans ton message
>> précédent :
>>
>> - Pour le tableau gridArray en tant qu’attribut de Grid tu as raison
>> ça
>> m’a l’air beaucoup plus simple. J’étais partie sur
>> une classe Node afin
>> de pratiquer les classes mais bon pas forcément judicieux. Je vais
>> essayer de voir pour faire une modification.
>>
>>
> Tu peux tout Í  fait garder cette classe, simplement il est plus
> pratique
> d'accéder aux cellules par leurs coordonnées que de suivre des
> liens
> entre elles. Au lieu d'une méthode traverse qui parcourt les cellules,
> tu
> aurais une méthode plus simple qui contiendrait
> return gridArray[i][j] ;
>
> Par contre tu pourrais peut-être fusionner Node et Value, pour
> simplifier. Ce sont bien deux concepts distincts, mais pour chaque
> cellule il y a une valeur et réciproquement, donc il est possible de les
> fusionner si c'est plus simple.
>
>
>> - Pour l’importation du fichier dans le tableur, j’ai parsé
>> le contenu
>> du fichier et importé les différentes valeurs dans un ArrayList
>> puis je
>> l’ai envoyé Í  la méthode importFile afin de
>> les transférer dans l’objet
>> Node. Effectivement, comme tu l’as suggéré,
>> peut-être qu’on pourrait
>> juste enregistrer cet ArrayList comme attribut de la classe Grid et
>> aussi remplacer les valeurs de l’ArrayList par l’objet Valeur
>> ayant les
>> attributs : tag, dval, sval utiles par la suite ?
>>
>>
> Je pensais plutÍ´t Í  mettre tout le code de lecture
> du fichier dans
> importFile et Í  remplir directement gridArray avec des objets
> Node/
> Value : tu fais déjÍ  les deux boucles sur les lignes et sur
> les éléments
> de la ligne quand tu lis le fichier, il te suffirait de remplir les cases
> au fur et Í  mesure, au lieu de passer par des structures
> intermédiaires.
>
>
>> - Pour l’analyse syntaxique des formules dans les cellules, je pensais
>> faire une Regex Pattern.compile("\\+", Pattern.CASE_INSENSITIVE);
>> afin
>> de détecter les opérations Í  faire dans les
>> cellules. Une fois
>> l’opération détectée, faire le calcul et stocker le
>> résultat dans
>> l’attribut dval de la classe Value. Est ce que ça te semble une
>> bonne
>> solution ?
>>
>>
> En relisant la consigne, je m'aperçois que les calculs en question ne
> consistent qu'en une seule opération, ça ne peut pas être
> complexe. Ça
> rend le projet plus abordable que ce que je pensais.
>
> Je ne sais pas très calé en expressions rationnelles. Si tu sais
> t'en
> servir, c'est bien. Sinon les opérations simples de manipulation des
> chaͮnes suffiront.
>
> Il te faut effectivement détecter l'opérateur (opérateur
> arithmétique ou
> fonction Somme/Moy), extraire les opérandes et réaliser
> l'opération
> correspondante.
>
>
>> - Concernant la modélisation des liens entre les cellules, pour
>> gérer
>> les dépendances, d’après ce qui était
>> conseillé dans le projet, il
>> faudrait créer en attribut de chaque cellule (ou de la classe Value),
>> une liste avec les coordonnées des cellules qui dépendent de C.
>> Pour
>> détecter un cycle, il faut vérifier, Í  chaque fois
>> que l’utilisateur
>> rentre une valeur, s’il y une référence
>> déjÍ  présente dans la liste des
>> cellules qui dépendent de C. Si c’est le cas, ne pas autoriser
>> Í  la
>> renseigner. Idem, pour la mise Í  jour automatique d’une
>> cellule. A
>> chaque fois qu’une cellule est modifier, il faut mettre Í 
>> jour les
>> cellules qui sont renseignées dans la liste des cellules qui
>> dépendent
>> d’elle et ainsi de suite (la valeur du calcul est stockée dans
>> l’attribut dval de l’objet Value et la valeur texte (formule) dans
>> l’attribut sval ce qui permet de pouvoir recalculer la formule). Est ce
>> que cette algorithme te semble judicieux pour modéliser les liaisons
>> entre les cellules ?
>>
>>
> Vois-tu comment fonctionne la récursion ? Parce que le cycle peut
> impliquer un paquet de cellules, il faut remonter les cellules pour
> vérifier qu'il n'y a aucun cycle d'aucune longueur. Sais-tu comment
> faire
> ça ?
>
>
>> - Dans le point 5 du projet, il est demandé que le programme prenne en
>> charge les références de cellules relatives avec le signe $.
>> Pour
>> calculer, la position d'une cellule ayant une référence relative
>> $(1,2)
>> dans la cellule (2,3) par exemple est la position absolue : (1,1) (1
>> ligne plus haute et 2 colonnes vers la gauche), est bien cela ? Car je
>> n’arrive pas Í  comprendre l’exemple qu’ils
>> donnent dans l’explication.
>>
>>
> C'est ce que je comprends. C'est bizarre de compter comme ça par contre,
> j'aurais plutÍ´t considéré les valeurs positives de
> décalage vers le bas
> et la droite.
>
>> Idem que dans l'affichage du contenu de la cellule
>> référencée de manière
>> absolue, il faut afficher sa valeur dans la cellule de destination pour
>> pouvoir faire le calcul, je ferai donc la même technique que celle
>> utilisée pour les références absolues c’est
>> Í  dire avec le tableau des
>> références qui dépendent de la cellules
>>
>>
> Oui.
>
>
>> - Je t’invite Í  me dire s’il y a d’autres
>> points importants que je
>> pourrais améliorer dans mon code ou qu'il pourrait être
>> intéressant
>> d'approfondir dans le projet :)
>>
>>
> Ça me paraÍ®t déjÍ  beaucoup de travail...
> :)
>
> Il reste pas mal d'endroits o͹ tu ne laisses pas filer les
> exceptions,
> c'est dommage en cas de bug.
>
> Note que si tu laisses filer les exceptions le try/catch ou try-finally
> n'est pas nécessaire (sauf dans le cas o͹ tu utilises la
> try pour gérer
> automatiquement la fermeture de flux, comme InputStream).
Hello Yliur,

Merci beaucoup pour toutes tes explications très claires :)

- Concernant la mise en place d’une méthode return gridArray[i][j] au lieu de la
méthode traverse dans la classe Grid effectivement cela simplifierait. Est ce
qu’il faut aussi que je mette gridArray[i][j] en tant qu’attribut de la classe
Grid car je ne pense pas que ce soit le cas ? Pour la fusion de Node et Value,
je pourrais mettre les attributs de Value (dval, sval, tag) dans Node afin
d’utiliser uniquement Node. Effectivement pour l’import du fichier, je pourrais
remplir la liste gridArray avec les Node/ Value directement dans la fonction
loadFile lorsque je parcours la liste. Est ce que ces points te semblent
corrects ?

- J’ai implémenté le code avec les expressions rationnelles pour détecter les
références, opérandes et les opérations à faire dans une cellule et réaliser les
calculs. Je sais que ça ne doit pas être très optimisé ou lisible mais ça m’a
l’air de fonctionner. Peut être faire une boucle et une fonction pour éviter de
répéter à chaque fois Pattern, Matcher ?

- Pour réaliser le cycle grâce aux fonctions récursives : remonter les cellules
pour vérifier qu’il n’y a aucun cycle d’aucune longueur, je ne suis pas encore
très à l’aise avec les fonctions récursives, est ce que tu aurais une idée de
comment faire s’il te plait ?
f([c]) {
f([c])
}

- Pour les coordonnées relatives, je penses qu’il n’y aura pas beaucoup de
difficultés, une fois que la méthode gridArray[i][j] sera implémenté, il faudra
retrouver la position relative grâce à la position de cellule d’origine donc
peut être créer une méthode convertRelativeToAbsolue.

Yliur

unread,
Jun 17, 2021, 4:35:07 AM6/17/21
to

Bonjour

> - Concernant la mise en place d’une méthode return gridArray[i][j] au
> lieu de la méthode traverse dans la classe Grid effectivement cela
> simplifierait. Est ce qu’il faut aussi que je mette gridArray[i][j] en
> tant qu’attribut de la classe Grid car je ne pense pas que ce soit le
> cas ?

Si : il te faut créer un attribut de type Node[][] dans la classe et le
remplir dans le constructeur. Sinon tu ne pourras pas y accéder dans les
autres méthodes. C'est en remplacement de l'attribut head, un moyen plus
simple d'accéder aux cellules.

Et une méthode qui aurait par exemple cette signature :
public Node cellule (int ligne, int colonne)
et qui se contenterait d'aller voir dans le tableau ; à la place de
traverse.


> Pour la fusion de Node et Value,
> je pourrais mettre les attributs de Value (dval, sval, tag) dans Node
> afin d’utiliser uniquement Node. Effectivement pour l’import du fichier,
> je pourrais remplir la liste gridArray avec les Node/ Value directement
> dans la fonction loadFile lorsque je parcours la liste. Est ce que ces
> points te semblent corrects ?

Oui. Il te faudra sans doute un autre constructeur pour Grid, qui prend
en paramètre un le tableau de type Node[][] au lieu d'en créer un lui-
même comme dans ton constructeur actuel. Les deux constructeurs peuvent
cohabiter. Ou bien tu remplis les cases d'une grille existante, au choix.


> - J’ai implémenté le code avec les expressions rationnelles pour
> détecter les références, opérandes et les opérations à faire dans une
> cellule et réaliser les calculs. Je sais que ça ne doit pas être très
> optimisé ou lisible mais ça m’a l’air de fonctionner. Peut être faire
> une boucle et une fonction pour éviter de répéter à chaque fois Pattern,
> Matcher ?

Tu pourrais effectivement avoir une fonction pour éviter de répéter le
code de test de l'expression rationnelle, par contre je ne pense pas
qu'une boucle t'aide tellement.

Une note sur les performances : ce n'est pas important pour ton projet,
mais Pattern.compile ça peut coûter quelque chose. Donc dans un vrai
projet tu préféreras peut-être stocker le résultat quelque part une fois
au chargement de la classe, avant toutes tes fonctions :
private static Pattern ... = Pattern.compile (...) ;
Avec des noms précis, pour éviter d'exécuter ce traitement à chaque appel
de la fonction.


> - Pour réaliser le cycle grâce aux fonctions récursives : remonter les
> cellules pour vérifier qu’il n’y a aucun cycle d’aucune longueur, je ne
> suis pas encore très à l’aise avec les fonctions récursives, est ce que
> tu aurais une idée de comment faire s’il te plait ?
> f([c]) {
> f([c])
> }

En y repensant, je pense qu'on peut faire sans récursion. Tu vas avoir
besoin des classes de type Set (des ensembles de données, sans ordre
particulier et sans doublons en général). Tu peux par exemple utiliser
HashSet.

Tu as besoin de remonter les cellules dépendant de la cellule, et ainsi
de suite, en notant toutes celles qui sont passées et en vérifiant que tu
ne retombes jamais sur celle de départ.

Ça devrait marcher approximativement comme ça :
- Tu initialises l'ensemble des cellules déjà passées, il est vide.
- Tu initialises l'ensemble des cellules à traiter en plaçant dedans
la cellule de départ.
- Tu commences une boucle qui se termine quand il n'y a plus aucun
élément dans l'ensemble de cellules à traiter.
- Dans la boucle, tu prend un élément de l'ensemble des cellules à
traiter (par exemple avec ensemble.iterator().next(), sans
parcourir toutes les valeurs de l'ensemble à la suite : tu te
contentes d'en piocher un).
- Si cette cellule se trouve dans les cellules déjà passées, tu
l'ignores.
- Sinon tu considères les cellules qui dépendent de celle que tu
viens de piocher, si l'une d'elle est ta cellule de départ
c'est qu'il y a un cycle, tu peux arrêter tout le processus.
Sinon tu places ces cellules dans les cellules à traiter.
- Si à un moment il n'y a plus de cellules dans l'ensemble de celles
à traiter, c'est qu'il n'y a pas de cycle.

L'idée est de remonter les cellules en vérifiant qu'on ne retombe jamais
sur celle de départ.

C'est une forme d'algorithme assez classique, ça te resservira sans doute.

Dans ton cas il est même possible de le simplifier un peu : en
considérant qu'il n'y a pas de cycle dans le reste des cellules
(puisqu'on vérifie au fur et à mesure), on pourrait se dispenser de noter
les cellules déjà passées. Un cas conduirait à examiner plus de
cellules : celui où une cellule est, directement ou indirectement, dans
les dépendances de deux cellules : si C0 dépend de C1 et C2, C1 et C2
dépendent chacune de C3 et que C3 dépend de C4, on examinerait deux fois
le cas de C3 et C4. Ce n'est pas forcément très grave dans ton cas, donc
tu peux te dispenser de l'ensemble de cellules déjà examinées si tu veux.

Yliur
0 new messages