From 25d59bedbfd84dcbadd00cfbca9c49cd1c55b73e Mon Sep 17 00:00:00 2001
From: Daniel <59575049+lumijiez@users.noreply.github.com>
Date: Tue, 15 Oct 2024 02:11:01 +0300
Subject: [PATCH] better styling, fixed some logic
---
pom.xml | 1 +
.../lumijiez/monoalpha/MainController.java | 117 ++------
.../org/lumijiez/monoalpha/MonoAlpha.java | 10 +-
.../monoalpha/util/CharacterSwitcher.java | 33 ++-
.../lumijiez/monoalpha/util/GlobalVars.java | 5 +
.../monoalpha/util/InputAnalyzer.java | 97 +++++--
.../monoalpha/util/PatternGenerator.java | 82 ++++++
.../org/lumijiez/monoalpha/monoalpha.fxml | 271 +++++++++---------
8 files changed, 363 insertions(+), 253 deletions(-)
create mode 100644 src/main/java/org/lumijiez/monoalpha/util/GlobalVars.java
create mode 100644 src/main/java/org/lumijiez/monoalpha/util/PatternGenerator.java
diff --git a/pom.xml b/pom.xml
index b5af8ca..b1e0477 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,6 +30,7 @@
atlantafx-base
2.0.1
+
org.junit.jupiter
junit-jupiter-api
diff --git a/src/main/java/org/lumijiez/monoalpha/MainController.java b/src/main/java/org/lumijiez/monoalpha/MainController.java
index 745a938..3e48d6b 100644
--- a/src/main/java/org/lumijiez/monoalpha/MainController.java
+++ b/src/main/java/org/lumijiez/monoalpha/MainController.java
@@ -2,26 +2,27 @@ package org.lumijiez.monoalpha;
import javafx.fxml.FXML;
import javafx.scene.chart.BarChart;
-import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
+import javafx.scene.control.CheckBox;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
+import javafx.scene.text.Text;
+import javafx.scene.text.TextFlow;
import org.lumijiez.monoalpha.util.CharacterSwitcher;
import org.lumijiez.monoalpha.util.InputAnalyzer;
+import org.lumijiez.monoalpha.util.PatternGenerator;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import static org.lumijiez.monoalpha.util.GlobalVars.RAINBOW;
+import static org.lumijiez.monoalpha.util.PatternGenerator.matchPattern;
+
public class MainController {
@FXML
- private BarChart barChart;
+ private BarChart barChart;
@FXML
private TextArea inputArea;
@@ -30,7 +31,7 @@ public class MainController {
private TextArea ruleArea;
@FXML
- private TextArea outputArea;
+ private TextFlow outputArea;
@FXML
private TextField patternInput;
@@ -41,98 +42,38 @@ public class MainController {
@FXML
private TextArea patternOutput;
- private Map> dictionaryMap;
+ @FXML
+ private CheckBox rainbowCheckbox;
+
+ private final Map> dictionaryMap = new HashMap<>();
@FXML
private void initialize() {
analyzeText();
- loadDictionary();
- barChart.setStyle("-fx-font-size: 18px;");
+ PatternGenerator.loadDictionary(dictionaryMap, patternOutput);
+ //barChart.setStyle("-fx-font-size: 18px;");
inputArea.textProperty().addListener((observable, oldValue, newValue) -> {
analyzeText();
- applyChanges();
+ applyChanges(ruleArea.getText());
+ });
+ ruleArea.textProperty().addListener((observable, oldValue, newValue) -> applyChanges(newValue));
+ patternButton.setOnAction(e -> matchPattern(patternInput.getText().trim(), patternOutput, dictionaryMap));
+ rainbowCheckbox.selectedProperty().addListener((observable, oldValue, newValue) -> {
+ RAINBOW = newValue;
+ analyzeText();
});
- ruleArea.textProperty().addListener((observable, oldValue, newValue) -> applyChanges());
- patternButton.setOnAction(e -> matchPattern());
}
@FXML
private void analyzeText() {
- String inputText = inputArea.getText();
- Map frequencyMap = InputAnalyzer.analyzeFrequency(inputText);
- List> barChartData = InputAnalyzer.getBarChartData(frequencyMap);
- InputAnalyzer.updateBarChart(barChart, barChartData);
+ String input = inputArea.getText();
+ Map frequencyMap = InputAnalyzer.analyzeFrequency(input);
+ InputAnalyzer.updateBarChart(barChart, frequencyMap);
}
- private void applyChanges() {
- String rules = ruleArea.getText();
- String changedText = CharacterSwitcher.applyRules(rules, inputArea.getText());
- outputArea.setText(changedText);
- }
-
- private void loadDictionary() {
- dictionaryMap = new HashMap<>();
-
- try (InputStream is = getClass().getResourceAsStream("/org/lumijiez/monoalpha/dictionary.txt")) {
- assert is != null;
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
-
- String line;
- while ((line = reader.readLine()) != null) {
- String[] parts = line.split(" ");
- if (parts.length == 2) {
- String pattern = parts[0];
- String word = parts[1];
- dictionaryMap.computeIfAbsent(pattern, k -> new ArrayList<>()).add(word);
- }
- }
-
- }
- } catch (IOException e) {
- e.printStackTrace();
- patternOutput.setText("Error loading dictionary");
- }
- }
-
- private void matchPattern() {
- String inputWord = patternInput.getText().trim();
- if (inputWord.isEmpty()) {
- patternOutput.setText("Please enter a word.");
- return;
- }
-
- String inputPattern = generatePattern(inputWord);
-
- List matchingWords = dictionaryMap.getOrDefault(inputPattern, new ArrayList<>());
-
- if (matchingWords.isEmpty()) {
- patternOutput.setText("No matching words found.");
- } else {
- patternOutput.setText(String.join("\n", matchingWords));
- }
- }
-
- private String generatePattern(String word) {
- StringBuilder pattern = new StringBuilder();
- char nextLower = 'a';
- char nextUpper = 'A';
- Map charMap = new HashMap<>();
-
- for (char c : word.toCharArray()) {
- if (Character.isLowerCase(c)) {
- if (!charMap.containsKey(c)) {
- charMap.put(c, nextLower++);
- }
- pattern.append(charMap.get(c));
- } else if (Character.isUpperCase(c)) {
- if (!charMap.containsKey(c)) {
- charMap.put(c, nextUpper++);
- }
- pattern.append(charMap.get(c));
- } else {
- pattern.append(c);
- }
- }
- return pattern.toString();
+ private void applyChanges(String input) {
+ List textNodes = CharacterSwitcher.applyRules(input, inputArea.getText());
+ outputArea.getChildren().clear();
+ outputArea.getChildren().addAll(textNodes);
}
}
\ No newline at end of file
diff --git a/src/main/java/org/lumijiez/monoalpha/MonoAlpha.java b/src/main/java/org/lumijiez/monoalpha/MonoAlpha.java
index ea989c6..41fd15a 100644
--- a/src/main/java/org/lumijiez/monoalpha/MonoAlpha.java
+++ b/src/main/java/org/lumijiez/monoalpha/MonoAlpha.java
@@ -1,24 +1,18 @@
package org.lumijiez.monoalpha;
-import atlantafx.base.theme.Dracula;
+import atlantafx.base.theme.PrimerLight;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
-import javafx.scene.image.Image;
-import javafx.scene.layout.BackgroundImage;
-import javafx.scene.layout.BackgroundPosition;
-import javafx.scene.layout.BackgroundRepeat;
-import javafx.scene.layout.BackgroundSize;
import javafx.stage.Stage;
import java.io.IOException;
-import java.util.Objects;
public class MonoAlpha extends Application {
@Override
public void start(Stage stage) throws IOException {
- Application.setUserAgentStylesheet(new Dracula().getUserAgentStylesheet());
+ Application.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet());
FXMLLoader fxmlLoader = new FXMLLoader(MonoAlpha.class.getResource("monoalpha.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 1280, 720);
diff --git a/src/main/java/org/lumijiez/monoalpha/util/CharacterSwitcher.java b/src/main/java/org/lumijiez/monoalpha/util/CharacterSwitcher.java
index 6b53ec9..6f66b4c 100644
--- a/src/main/java/org/lumijiez/monoalpha/util/CharacterSwitcher.java
+++ b/src/main/java/org/lumijiez/monoalpha/util/CharacterSwitcher.java
@@ -1,30 +1,53 @@
package org.lumijiez.monoalpha.util;
+import javafx.scene.paint.Color;
+import javafx.scene.text.Text;
+
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
public class CharacterSwitcher {
- public static String applyRules(String rulesInput, String text) {
+
+ public static List applyRules(String rulesInput, String text) {
Map ruleMap = new HashMap<>();
String[] rules = rulesInput.split(";");
+
for (String rule : rules) {
String[] parts = rule.split(">");
if (parts.length != 2 || parts[0].trim().length() != 1 || parts[1].trim().length() != 1) {
- return "BAD RULE";
+ List errorText = new ArrayList<>();
+ errorText.add(createErrorText());
+ return errorText;
}
char from = parts[0].trim().charAt(0);
char to = parts[1].trim().charAt(0);
ruleMap.put(from, to);
}
- StringBuilder result = new StringBuilder();
+ text = text.replaceAll("\\r?\\n", "");
+
+ List textNodes = new ArrayList<>();
for (char c : text.toCharArray()) {
char newChar = ruleMap.getOrDefault(c, c);
- result.append(newChar);
+ Text textNode = new Text(newChar + "");
+
+ if (c != newChar) {
+ textNode.setFill(Color.RED);
+ }
+
+ textNodes.add(textNode);
}
- return result.toString();
+ return textNodes;
+ }
+
+ private static Text createErrorText() {
+ Text errorText = new Text("BAD RULE");
+ errorText.setFill(Color.RED);
+ return errorText;
}
}
diff --git a/src/main/java/org/lumijiez/monoalpha/util/GlobalVars.java b/src/main/java/org/lumijiez/monoalpha/util/GlobalVars.java
new file mode 100644
index 0000000..ff5b4f7
--- /dev/null
+++ b/src/main/java/org/lumijiez/monoalpha/util/GlobalVars.java
@@ -0,0 +1,5 @@
+package org.lumijiez.monoalpha.util;
+
+public class GlobalVars {
+ public static boolean RAINBOW = false;
+}
diff --git a/src/main/java/org/lumijiez/monoalpha/util/InputAnalyzer.java b/src/main/java/org/lumijiez/monoalpha/util/InputAnalyzer.java
index efda703..c3e3961 100644
--- a/src/main/java/org/lumijiez/monoalpha/util/InputAnalyzer.java
+++ b/src/main/java/org/lumijiez/monoalpha/util/InputAnalyzer.java
@@ -8,45 +8,102 @@ import javafx.util.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Random;
import java.util.stream.Collectors;
+import static org.lumijiez.monoalpha.util.GlobalVars.RAINBOW;
+
public class InputAnalyzer {
+ private static final Map ENGLISH_FREQUENCIES = createEnglishFrequencies();
+ private static final Random RANDOM = new Random();
+
+ private static Map createEnglishFrequencies() {
+ Map frequencies = new HashMap<>();
+ String[] letters = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
+ "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
+ "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d",
+ "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
+ "o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
+ "y", "z"};
+ double[] frequenciesValues = {8.17, 1.49, 2.78, 4.25, 12.70, 2.23, 2.01, 6.09, 6.97, 0.15,
+ 0.77, 4.03, 2.41, 6.75, 7.51, 1.93, 0.09, 5.99, 6.33, 9.06,
+ 2.76, 0.98, 2.36, 0.15, 1.97, 0.07, 8.17, 1.49, 2.78, 4.25,
+ 12.70, 2.23, 2.01, 6.09, 6.97, 0.15, 0.77, 4.03, 2.41, 6.75,
+ 7.51, 1.93, 0.09, 5.99, 6.33, 9.06, 2.76, 0.98, 2.36, 0.15,
+ 1.97, 0.07};
+
+ for (int i = 0; i < letters.length; i++) {
+ frequencies.put(letters[i], frequenciesValues[i]);
+ }
+ return frequencies;
+ }
+
public static Map analyzeFrequency(String text) {
Map frequencyMap = new HashMap<>();
- for (char ch : text.toCharArray()) {
- if (Character.isLetter(ch)) {
- frequencyMap.put(ch, frequencyMap.getOrDefault(ch, 0) + 1);
- }
- }
+ text.chars()
+ .filter(Character::isLetter)
+ .forEach(ch -> frequencyMap.merge((char) ch, 1, Integer::sum));
return frequencyMap;
}
- public static List> getBarChartData(Map frequencyMap) {
+ public static List> getBarChartData(Map frequencyMap) {
+ int totalCount = frequencyMap.values().stream().mapToInt(Integer::intValue).sum();
return frequencyMap.entrySet().stream()
- .map(entry -> new XYChart.Data<>(entry.getKey().toString(), entry.getValue()))
+ .map(entry -> new XYChart.Data<>(entry.getKey().toString(), (entry.getValue() / (double) totalCount) * 100))
.collect(Collectors.toList());
}
- public static void updateBarChart(BarChart barChart, List> data) {
+ public static List> getStaticEnglishFrequencies() {
+ return ENGLISH_FREQUENCIES.entrySet().stream()
+ .map(entry -> new XYChart.Data<>(entry.getKey(), entry.getValue()))
+ .collect(Collectors.toList());
+ }
+
+ public static void updateBarChart(BarChart barChart, Map frequencyMap) {
barChart.getData().clear();
- XYChart.Series series = new XYChart.Series<>();
- for (XYChart.Data datum : data) {
- series.getData().add(new XYChart.Data<>(datum.getXValue(), datum.getYValue()));
+ List> actualData = getBarChartData(frequencyMap);
+ List> englishData = getStaticEnglishFrequencies();
+
+ barChart.getData().add(createSeries("Actual Frequency", actualData, true)); // Random colors
+ barChart.getData().add(createSeries("English Frequency", englishData, false)); // Constant color
+
+ setTooltips(barChart.getData().get(0));
+ setTooltips(barChart.getData().get(1));
+ }
+
+ private static XYChart.Series createSeries(String name, List> data, boolean randomizeColor) {
+ XYChart.Series series = new XYChart.Series<>();
+ series.setName(name);
+ for (XYChart.Data datum : data) {
+ XYChart.Data barData = new XYChart.Data<>(datum.getXValue(), datum.getYValue());
+ barData.nodeProperty().addListener((obs, oldNode, newNode) -> {
+ if (RAINBOW && randomizeColor && newNode != null) {
+ String color = randomColor();
+ newNode.setStyle("-fx-bar-fill: " + color + ";");
+ }
+ });
+ series.getData().add(barData);
}
+ setTooltips(series);
+ return series;
+ }
- barChart.getXAxis().setAnimated(false);
- barChart.getData().add(series);
-
- for (XYChart.Data datum : series.getData()) {
- Tooltip tooltip = new Tooltip("Frequency: " + datum.getYValue());
-
- tooltip.setShowDelay(new Duration(0));
- tooltip.setHideDelay(new Duration(0));
+ private static String randomColor() {
+ int r = RANDOM.nextInt(256);
+ int g = RANDOM.nextInt(256);
+ int b = RANDOM.nextInt(256);
+ return String.format("rgb(%d,%d,%d)", r, g, b);
+ }
+ private static void setTooltips(XYChart.Series series) {
+ for (XYChart.Data datum : series.getData()) {
+ String tooltipText = String.format("%s: %.2f%%", series.getName(), (Double) datum.getYValue());
+ Tooltip tooltip = new Tooltip(tooltipText);
+ tooltip.setShowDelay(Duration.ZERO);
+ tooltip.setHideDelay(Duration.ZERO);
Tooltip.install(datum.getNode(), tooltip);
}
}
}
-
diff --git a/src/main/java/org/lumijiez/monoalpha/util/PatternGenerator.java b/src/main/java/org/lumijiez/monoalpha/util/PatternGenerator.java
new file mode 100644
index 0000000..380e238
--- /dev/null
+++ b/src/main/java/org/lumijiez/monoalpha/util/PatternGenerator.java
@@ -0,0 +1,82 @@
+package org.lumijiez.monoalpha.util;
+
+import javafx.scene.control.TextArea;
+import org.lumijiez.monoalpha.MainController;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class PatternGenerator {
+
+ public static String generatePattern(String word) {
+ StringBuilder pattern = new StringBuilder();
+ char nextLower = 'a';
+ char nextUpper = 'A';
+ Map charMap = new HashMap<>();
+
+ for (char c : word.toCharArray()) {
+ if (Character.isLowerCase(c)) {
+ if (!charMap.containsKey(c)) {
+ charMap.put(c, nextLower++);
+ }
+ pattern.append(charMap.get(c));
+ } else if (Character.isUpperCase(c)) {
+ if (!charMap.containsKey(c)) {
+ charMap.put(c, nextUpper++);
+ }
+ pattern.append(charMap.get(c));
+ } else {
+ pattern.append(c);
+ }
+ }
+ return pattern.toString();
+ }
+
+ public static void loadDictionary(Map> dictionaryMap, TextArea textArea) {
+
+ try (InputStream is = MainController.class.getResourceAsStream("/org/lumijiez/monoalpha/dictionary.txt")) {
+ assert is != null;
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
+
+ String line;
+ while ((line = reader.readLine()) != null) {
+ String[] parts = line.split(" ");
+ if (parts.length == 2) {
+ String pattern = parts[0];
+ String word = parts[1];
+ dictionaryMap.computeIfAbsent(pattern, k -> new ArrayList<>()).add(word);
+ }
+ }
+
+ }
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ textArea.setText("Error loading dictionary");
+ }
+ }
+
+ public static void matchPattern(String inputWord, TextArea patternOutput, Map> dictionaryMap) {
+
+ if (inputWord.isEmpty()) {
+ patternOutput.setText("Please enter a word.");
+ return;
+ }
+
+ String inputPattern = generatePattern(inputWord);
+
+ List matchingWords = dictionaryMap.getOrDefault(inputPattern, new ArrayList<>());
+
+ if (matchingWords.isEmpty()) {
+ patternOutput.setText("No matching words found.");
+ } else {
+ patternOutput.setText(String.join("\n", matchingWords));
+ }
+ }
+
+}
diff --git a/src/main/resources/org/lumijiez/monoalpha/monoalpha.fxml b/src/main/resources/org/lumijiez/monoalpha/monoalpha.fxml
index 3ab276d..9ebefdf 100644
--- a/src/main/resources/org/lumijiez/monoalpha/monoalpha.fxml
+++ b/src/main/resources/org/lumijiez/monoalpha/monoalpha.fxml
@@ -4,161 +4,168 @@
+
+
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
-
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
-
+
-
-
+
+
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+