4 Commits

3 changed files with 103 additions and 7 deletions

View File

@@ -7,7 +7,7 @@
<groupId>com.calendar</groupId>
<artifactId>vaccalc</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
<packaging>jar</packaging>
<name>VacCalc</name>

View File

@@ -3,18 +3,22 @@ package net.themusicinnoise.vaccalc;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PointEngine {
private double defaultPoints;
private static final Pattern DEFAULT_PATTERN = Pattern.compile("^default\\s+(\\d+\\.\\d+)", Pattern.CASE_INSENSITIVE);
static private class PointRule {
private enum RuleType {
@@ -23,9 +27,9 @@ public class PointEngine {
DATE,
}
static final Pattern DOW_PATTERN = Pattern.compile("dow=(sun|mon|tue|wed|thu|fri|sat) (\\d+\\.\\d+)", Pattern.CASE_INSENSITIVE);
static final Pattern MONTH_PATTERN = Pattern.compile("m=(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec) (\\d+\\.\\d+)", Pattern.CASE_INSENSITIVE);
static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4}-\\d{2}-\\d{2}) (\\d+\\.\\d+)", Pattern.CASE_INSENSITIVE);
private static final Pattern DOW_PATTERN = Pattern.compile("^dow=(sun|mon|tue|wed|thu|fri|sat)\\s+(\\d+\\.\\d+)", Pattern.CASE_INSENSITIVE);
private static final Pattern MONTH_PATTERN = Pattern.compile("^m=(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\\s+(\\d+\\.\\d+)", Pattern.CASE_INSENSITIVE);
private static final Pattern DATE_PATTERN = Pattern.compile("^(\\d{4}-\\d{2}-\\d{2})\\s+(\\d+\\.\\d+)", Pattern.CASE_INSENSITIVE);
private RuleType type;
private DayOfWeek dow;
@@ -77,15 +81,13 @@ public class PointEngine {
}
public void importPointsFile(File pointsFile) {
Pattern defaultPattern = Pattern.compile("default (\\d+\\.\\d+)");
try (BufferedReader br = new BufferedReader(new FileReader(pointsFile))) {
String line;
while ((line = br.readLine()) != null) {
if (line.isEmpty() || line.charAt(0) == '#')
continue;
Matcher defaultMatcher = defaultPattern.matcher(line);
Matcher defaultMatcher = DEFAULT_PATTERN.matcher(line);
if (defaultMatcher.find()) {
defaultPoints = Double.parseDouble(defaultMatcher.group(1));
} else {
@@ -107,4 +109,41 @@ public class PointEngine {
}
return defaultPoints;
}
public void exportSelectedDates(File exportFile, Set<LocalDate> selectedDates) throws IOException {
try (FileWriter writer = new FileWriter(exportFile)) {
selectedDates.stream()
.sorted()
.forEach(date -> {
try {
writer.write(String.format("%s%n", date));
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
}
public Set<LocalDate> importSelectedDates(File importFile) throws IOException {
Set<LocalDate> dates = new HashSet<>();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
try (BufferedReader br = new BufferedReader(new FileReader(importFile))) {
String line;
while ((line = br.readLine()) != null) {
line = line.trim();
if (line.isEmpty() || line.charAt(0) == '#')
continue;
try {
LocalDate date = LocalDate.parse(line, formatter);
dates.add(date);
} catch (Exception e) {
throw new IllegalArgumentException("Invalid date format in line: '" + line + "'");
}
}
}
return dates;
}
}

View File

@@ -4,8 +4,10 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
public class VacCalc extends JFrame {
@@ -42,6 +44,61 @@ public class VacCalc extends JFrame {
}
});
appMenu.add(importItem);
appMenu.addSeparator();
JMenuItem exportItem = new JMenuItem("Export selected dates");
exportItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ev) {
if (calendarPanel.getSelectedDates().isEmpty()) {
JOptionPane.showMessageDialog(VacCalc.this, "No dates selected.", "Export Error",
JOptionPane.WARNING_MESSAGE);
return;
}
JFileChooser fileChooser = new JFileChooser();
fileChooser.setSelectedFile(new File("vacation_dates.txt"));
int ret = fileChooser.showSaveDialog(VacCalc.this);
if(ret == JFileChooser.APPROVE_OPTION) {
try {
pointEngine.exportSelectedDates(fileChooser.getSelectedFile(), calendarPanel.getSelectedDates());
JOptionPane.showMessageDialog(VacCalc.this, "Dates exported successfully.", "Export Complete",
JOptionPane.INFORMATION_MESSAGE);
} catch(Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(VacCalc.this, ex.getMessage(), "Export Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
});
appMenu.add(exportItem);
JMenuItem importDatesItem = new JMenuItem("Import dates");
importDatesItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ev) {
JFileChooser fileChooser = new JFileChooser();
int ret = fileChooser.showOpenDialog(VacCalc.this);
if(ret == JFileChooser.APPROVE_OPTION) {
try {
calendarPanel.clearSelection();
Set<LocalDate> importedDates = pointEngine.importSelectedDates(fileChooser.getSelectedFile());
if (importedDates.isEmpty()) {
JOptionPane.showMessageDialog(VacCalc.this, "No valid dates found in file.", "Import Warning",
JOptionPane.WARNING_MESSAGE);
return;
}
calendarPanel.setSelectedDates(importedDates);
JOptionPane.showMessageDialog(VacCalc.this, "Imported " + importedDates.size() + " dates.", "Import Complete",
JOptionPane.INFORMATION_MESSAGE);
} catch(Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(VacCalc.this, ex.getMessage(), "Import Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
});
appMenu.add(importDatesItem);
appMenu.addSeparator();
JMenuItem exitItem = new JMenuItem("Exit");
exitItem.addActionListener(new ActionListener() {
@Override