{"id":15958971,"url":"https://github.com/mokira3d48/suko","last_synced_at":"2026-04-30T03:32:11.449Z","repository":{"id":216218423,"uuid":"737190508","full_name":"mokira3d48/suko","owner":"mokira3d48","description":"Super Kalculator implemented in Java with JFX.","archived":false,"fork":false,"pushed_at":"2024-01-18T15:54:03.000Z","size":812,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-04T10:51:24.090Z","etag":null,"topics":["calculator","interpreter-pattern","javafx","javafx-fxml","pipeline-pattern"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mokira3d48.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-30T05:54:11.000Z","updated_at":"2024-03-17T15:53:14.000Z","dependencies_parsed_at":"2024-01-15T23:01:04.164Z","dependency_job_id":"b8f99db1-c082-48e3-9298-73c15ad83915","html_url":"https://github.com/mokira3d48/suko","commit_stats":{"total_commits":69,"total_committers":2,"mean_commits":34.5,"dds":0.02898550724637683,"last_synced_commit":"6fdbdcaca15c805ff26b116e50a31c53abbd9875"},"previous_names":["mokira3d48/suko"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mokira3d48/suko","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mokira3d48%2Fsuko","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mokira3d48%2Fsuko/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mokira3d48%2Fsuko/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mokira3d48%2Fsuko/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mokira3d48","download_url":"https://codeload.github.com/mokira3d48/suko/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mokira3d48%2Fsuko/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263244729,"owners_count":23436478,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["calculator","interpreter-pattern","javafx","javafx-fxml","pipeline-pattern"],"created_at":"2024-10-07T14:21:43.964Z","updated_at":"2026-04-30T03:32:01.431Z","avatar_url":"https://github.com/mokira3d48.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\u003cimg src=\"./images/suko.png\" /\u003e\u003c/div\u003e\n\n-------------------------------------------------------------------------------\n\u003cdiv align=\"center\"\u003e\n\n![](https://img.shields.io/badge/pattern-MVC-blue)\n![](https://img.shields.io/badge/build-success-success)\n![](https://img.shields.io/badge/IDE-Netbeans-green)\n![](https://img.shields.io/badge/contact-dr.mokira%40gmail.com-blueviolet)\n\n\u003c/div\u003e\n\u003cbr/\u003e\n\nUne calculatrice simple avec interface graphique développée en **JavaFX** et **FXML + CSS**.\nComme spécifié ci-dessous, elle ne gère pas les nombres à virgule, ni les parenthèses ni\nautres fonctions mathématiques complexes à part l'addition, la soustration, la multiplication\net la division.\n\nVous pouvez utiliser les boutons présents sur l'interface utilisateur\nou utiliser le pavé numérique de votre clavier pour interagir avec le logiciel.\n\n- Le projet de l'application avec interface graphique se trouve dans le dossier `Suko`.\n- Le projet de l'application avec interface console se trouve dans le dossier `SukoConsole`.\n\n\u003cbr/\u003e\n\u003cbr/\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n![](./images/suko_screenshot.png)\n\n\u003c/div\u003e\n\n- Appuyez sur `[ENTER]` de votre clavier ou *=* de la calculatrice pour avoir le résultat;\n- Appuyez sur `[C]` de votre clavier ou le bouton **C** de la calculatrice\npour reinitialiser la calculatrice;\n- Appuyez sur `[DELETE]` de votre clavier ou le bouton **CE** de la calculatrice pour effacer\nle champs de saisi inférieur.\n- Appuyez sur `[BACK SPACE]` de votre clavier ou le bouton **DEL** de la calculatrice pour\neffacer chiffre par chiffre le nombre saisi sur la champs de saisi inférieur.\n- Vous avez la possibilité de changer l'opérateur précédement saisi en appuyant sur une des\ntouche des opérateurs ( + - * /), ceci même si vous aviez déjà saisi un nombre dans champs\nde saisi inférieur.\n\n\n## Spécifications\nDéveloppez une calculatrice dotée d’une interface qui reçoit les informations entrées par l’utilisateur. Ces informations permettront de calculer le résultat des opérations.\n\n- **Etape 0** : La calculatrice attend la saisie du premier terme.\n- **Etape 1** : D’abord le premier terme est entré par la fourniture successive du (ou des) chiffre(s) le composant.\n- **Etape 2** : Ensuite, un symbole est fourni par l’entrée d’un des signes des opérations acceptés par la calculatrice (+ -  DIV *).\n- **Etape 3** : Et enfin le deuxième terme qui sera composé de 1 ou plusieurs chiffres aussi sera entré.\n- **Etape 4** : Apres cette étape, l’utilisateur devra taper le signe = et le résultat définitif de l’opération lui sera affiché et la calculatrice reviendra à l’**étape 1**.\nA l’entrée de « C », l’opération est remise à zéro, et on revient à l’**étape 0**.\n\n\u003e **NOTE** : l’application pourra ne gérer que les nombres entiers dans un premier temps. Ensuite, elle ne devra gérer que les cas normaux de fonctionnement. Ainsi, les cas exceptionnels d’erreur (cas anormaux) ne seront pas pris en compte (Exemple : appui sur = après saisie de la première opérande)\n\n## Conception\nDans une expression, nous avons des opérations et des termes. Les différentes opérations possibles\nque nous pouvons avoir sont des additions, multiplications, soustrations et divisions. Les termes\nne sont uniquement que des nombres entiers. Donc, il n'y aura aucune implémentation pour gérer\ndes nombres réels. Vooici un exemple d'expression :\n\n$$\n97 \\times 985 + 109 - 229\n$$\n\n### Interpreteur\nL'expression à calculer sera représentée sous forme arborescente, dans un premier temps. C'est ce\narbre de calcul qui sera évalué pour obtenir le résultat final. Dans l'exemple\nsuivant, les noeuds en forme de carré représentent les termes et les noeuds en forme circulaire\nreprésentent les opérations ($+, -, \\times \\div$).\n\n\u003cdiv align=\"center\"\u003e\n\t\u003cimg src=\"./images/tree_calculus.png\" width=\"80%\" height=\"80%\"/\u003e\n\u003cp\u003e\n\n*Figure 01* : Exemple d'un arbre de calcul.\n\n\u003c/p\u003e\n\u003cbr/\u003e\n\n\u003c/div\u003e\n\n- Les noeuds en forme de carré représentent les noeuds terminaux.\n- Les noeuds en forme circulaire représentent les noeuds non-terminaux.\n\nPour parvenir à obtenir ce modèle d'arbre, nous allons utiliser le design pattern **interpreter**.\nVoici donc le diagramme des classes modélisant cet arbre :\n\n\u003cdiv align=\"center\"\u003e\n\t\u003cimg src=\"./images/interpreter.png\" width=\"90%\" height=\"90%\"/\u003e\n\u003cp\u003e\n\n*Figure 02* : Diagramme des classes du modèle interpreter.\n\n\u003c/p\u003e\n\u003cbr/\u003e\n\n\u003c/div\u003e\n\n- Les noeuds terminaux seront représentés par les instances de la classe `TerminalNode`;\n- Les noeuds non-terminaux sont représentés par les instances de la classe `NonTerminalNode`;\n- Le contexte `Context` encapsule la liste des variables de l'équation mappées leurs valeurs\nrespectives;\n\nLe modèle interpreter permet de définir une équation en fonction des variables qu'on peut\nrenseigner avec leurs valeurs respectives. Ces variables sont représentées par des noeuds\nterminaux.\n\nPar contre, ce modèle ne permet pas d'implémenter l'analyseur qui permettra de construire\nl'arbre de calcul. Ce qui fera l'objet de la sous-section suivante.\n\n\n### Analyseur\nDans cette étape de conception, nous allons mettre en place l'analyseur qui va nous permettre\nde construire l'arbre du modèle interpreter à partir de l'équation reçue sous forme chaine de\ncaractères.\n\nL'équation reçue étant sous forme de chaine de caractères, on aura besoin de faire une chaine\nde traitement à effectuer sur ce dernier celle-ci afin d'obtenir l'arbre de calcul résultant.\nC'est cette chaine de traitement qui constitue l'analyseur. Voici la chaine de traitement\nproposée :\n\n\u003cdiv align=\"center\"\u003e\n\t\u003cimg src=\"./images/pipeline.png\" width=\"90%\" height=\"90%\"/\u003e\n\u003cp\u003e\n\n*Figure 03* : Pipeline de l'analyse et construction de l'arbre de calcul.\n\n\u003c/p\u003e\n\u003cbr/\u003e\n\n\u003c/div\u003e\n\nIl y a juste deux étapes de traitement.\n\nPour élaborer cette chaine de traitement, nous allons utiliser le design pattern **Pipeline**.\nCe modèle de conception permet de définir une chaine de responsabilité (processus)\ndestinée à s'exécuter de façon séquentielle : l'une après l'autre. Voici donc le diagramme\ndes classes modélisant cette chaine de traitement :\n\n\n\u003cdiv align=\"center\"\u003e\n\t\u003cimg src=\"./images/analyser.png\" width=\"90%\" height=\"90%\"/\u003e\n\u003cp\u003e\n\n*Figure 04* : Diagramme des classes de l'analyseur.\n\n\u003c/p\u003e\n\u003cbr/\u003e\n\n\u003c/div\u003e\n\nAprès l'implémentation, on pourra écrire le code suivant pour initialiser l'analyseur.\n\n```java\nPipeline\u003cString, Expression\u003e analyser = null;\nanalyser = new Pipeline\u003c\u003e(new Preprocess(...)).addHandler(new TreeBuilder(...));\n\n```\n\n- `Preprocess` a besoin de la liste de tous les opérateurs mappés avec leur niveau de\nriorité (de 1 à $+\\infty$).\n\n```\n{\"+\": 1};\n{\"-\": 1};\n{\"/\": 2};\n{\"*\": 2};\n\n```\n\nPlus ce nombre augment pour un opérateur plus ce opérateur a plus de priorié.\n\n- `TreeBuilder` a besoin de la liste des opérateurs mappés avec leur instance de noeud\nnon-terminal respectives.\n\n```\n{\"+\": (l, r) -\u003e new AddNode(l, r)}\n{\"-\": (l, r) -\u003e new SubtractNode(l, r)};\n{\"*\": (l, r) -\u003e new MultiplyNode(l, r)};\n{\"/\": (l, r) -\u003e new DivisionNode(l, r)};\n```\n\nEt pour une équation bien définit sous forme chaine de caractères, on pourra faire comme suit :\n\n```java\nNode treeRoot = analyser.execute(\"a * b + c - d\");\n\n```\n\n`treeRoot` sera donc le noeud racine de l'arbre de calcul résultant de l'équation `a * b + c - d`\n.\n\n### Instance de calculatrice\nIci, il s'agira de \"builder\" une instance de la calculatrice (`Calculator`) muni de son analyseur.\nPour cela nous allons utiliser le pattern **Builder** pour élaboler le programme qui va nous\npermettre de construire une instance de notre calculatrice. Voici le diagramme des classes\nde l'analyseur :\n\n\n\u003cdiv align=\"center\"\u003e\n\t\u003cimg src=\"./images/builder.png\" width=\"90%\" height=\"90%\"/\u003e\n\u003cp\u003e\n\n*Figure 04* : Diagramme des classes du buildeur d'un objet `Calculator`.\n\n\u003c/p\u003e\n\u003cbr/\u003e\n\n\u003c/div\u003e\n\n\n## Implémentation\nJe ne vais pas détailler l'implémentation de toutes les classes énoncées dans la partie,\nmais je peux vous montrer le résultat d'implémentation sur un exemple d'équation. Je ferai\nla démonstraction sur exemple suivant :\n\n$$\n\\alpha + x_2 \\times x_3 - x_4 \\times x_4 + x_4 \\times (x_1 + \\alpha) + \\frac{x_5}{x_3 \\times x_2}\n$$\n\n### Construction d'une calculatrice\nDans une première étape, on doit construire une instance de la calculatrice `Calculator`.\n\n```java\nBuilder\u003cCalculator\u003e b = new CalculatorBuilder();\nDirector director = new Director(b);\ndirector.makeBuild();\nCalculator calc = b.getResult();\n```\n\n### Définition du contexte\nOn définit une instance d'un context qui encapsulera toutes les variables de l'équation\nassociées à leur valeur.\n\n```java\n// instantiate the context\nContext ctx = new Context();\n\nctx.assign(\"alpha\", 8);\nctx.assign(\"x1\", 0);\nctx.assign(\"x2\", 12);\nctx.assign(\"x3\", 10);\nctx.assign(\"x4\", 65);\nctx.assign(\"x5\", 32);\nctx.assign(\"x6\", 10);\n\n```\n\n### Équation à évaluer\nOn définit ensuite l'équation en fonction de ces variables définies précédement.\n\n```java\ncalc.setEquation(\"alpha + x2 * x3 - x4 * x4 + x4 * (x1 + alpha) + x5 / (x3 * x2)\");\ncalc.setContext(ctx);\n\nSystem.out.println(ctx);\nSystem.out.println(\"Equation = \" + calc.getEquation());\n```\n\n![](./images/output01.png)\n\n\n### Evaluation de l'équation\nMaintenant, on peut évaluer l'équation en appelant la fonction `evaluate()` de l'objet `calc`.\n\n```java\n\ntry {\n\tDouble result = calc.evaluate();\n\t// On convertie le resultat en entier avant de l'afficher.\n\tSystem.out.println(\"Result = \" + result.intValue());\n} catch (SemanticError e) {\n\tSystem.out.println(\"SemanticError: \\t\" + e);\n} catch (Exception e) {\n\te.printStackTrace();\n}\n\n```\n\n![](./images/output02.png)\n\nLe programme a tout simplement remplacé les valeurs du contexte par leur variable dans l'équation\navant d'éffectuer le calcul.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmokira3d48%2Fsuko","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmokira3d48%2Fsuko","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmokira3d48%2Fsuko/lists"}