379 lines
15 KiB
Java
379 lines
15 KiB
Java
import java.io.BufferedReader;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.PrintWriter;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.OpenOption;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.StandardOpenOption;
|
|
import java.time.DayOfWeek;
|
|
import java.time.LocalDate;
|
|
import java.time.LocalDateTime;
|
|
import java.time.LocalTime;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.time.format.DateTimeParseException;
|
|
import java.time.temporal.TemporalAdjusters;
|
|
import java.util.*;
|
|
import java.util.stream.Collectors;
|
|
|
|
/**
|
|
* Pet Care Scheduler
|
|
*
|
|
* @author John Ahlroos / 2025
|
|
*
|
|
* Allows the user to manage Pet care appointments
|
|
*/
|
|
public class PetCareScheduler {
|
|
|
|
private final List<Pet> pets;
|
|
private final String dataFileName;
|
|
private final Scanner scanner;
|
|
|
|
public PetCareScheduler(Scanner scanner, String dataFileName) {
|
|
this.dataFileName = dataFileName;
|
|
this.scanner = scanner;
|
|
this.pets = new ArrayList<>();
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
|
|
System.out.println("PET CARE SCHEDULER v1.0");
|
|
System.out.println("=================================================================");
|
|
System.out.println();
|
|
|
|
try (Scanner scanner = new Scanner(System.in)) {
|
|
|
|
PetCareScheduler scheduler = new PetCareScheduler(scanner, "data.txt");
|
|
|
|
boolean loaded = scheduler.loadPetsFromFile();
|
|
if (!loaded) {
|
|
System.err.println("Failed to load data file.");
|
|
return;
|
|
}
|
|
|
|
System.out.println();
|
|
|
|
|
|
boolean exited = false;
|
|
while (!exited) {
|
|
System.out.println("Actions:");
|
|
System.out.println("\t1: Register Pet");
|
|
System.out.println("\t2: Schedule Appointment");
|
|
System.out.println("\t3: List Pets");
|
|
System.out.println("\t4: Print Report");
|
|
System.out.println("\t5: Save & Exit");
|
|
System.out.println();
|
|
System.out.print("Action: ");
|
|
|
|
try {
|
|
int action = Integer.parseInt(scanner.nextLine());
|
|
switch (action) {
|
|
case 1:
|
|
scheduler.registerPet();
|
|
break;
|
|
case 2:
|
|
scheduler.addAppointment();
|
|
break;
|
|
case 3:
|
|
scheduler.list();
|
|
break;
|
|
case 4:
|
|
scheduler.report();
|
|
break;
|
|
case 5:
|
|
boolean saved = scheduler.savePetsToFile();
|
|
if (!saved) {
|
|
System.err.println("Failed to save data file! Latest changes were lost.");
|
|
System.out.print("Exit anyway (yes/no)?");
|
|
String option = scanner.nextLine();
|
|
exited = option.equals("yes");
|
|
} else {
|
|
exited = true;
|
|
}
|
|
break;
|
|
default:
|
|
System.out.println("Not a valid option!");
|
|
}
|
|
} catch (NumberFormatException nfe) {
|
|
System.err.println("Action must be a number!");
|
|
}
|
|
}
|
|
} catch (RuntimeException re) {
|
|
System.err.println(re.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register a new pet with the system
|
|
*/
|
|
public void registerPet() {
|
|
System.out.println("=================================================================");
|
|
|
|
String id = UUID.randomUUID().toString();
|
|
LocalDate registration = LocalDate.now();
|
|
System.out.print("Name: ");
|
|
String name = scanner.nextLine();
|
|
if (name.isBlank()) {
|
|
System.err.println("Name must not be blank!");
|
|
return;
|
|
}
|
|
|
|
System.out.print("Owner: ");
|
|
String owner = scanner.nextLine();
|
|
if (owner.isBlank()) {
|
|
System.err.println("Owner must not be blank!");
|
|
return;
|
|
}
|
|
|
|
System.out.print("Contact Information: ");
|
|
String contact = scanner.nextLine();
|
|
System.out.print("Breed: ");
|
|
String breed = scanner.nextLine();
|
|
System.out.print("Age: ");
|
|
int age;
|
|
try{
|
|
age = Integer.parseInt(scanner.nextLine());
|
|
} catch (NumberFormatException nfe) {
|
|
System.err.println("Not a valid number!");
|
|
return;
|
|
}
|
|
|
|
Pet pet = new Pet(id,name,owner,contact,breed,age,registration);
|
|
pets.add(pet);
|
|
|
|
System.out.printf("New pet %s registered with id %s%n", pet.getName(), pet.getId());
|
|
System.out.println("=================================================================");
|
|
System.out.println();
|
|
}
|
|
|
|
/**
|
|
* Add a new appointment for a pet
|
|
*/
|
|
public void addAppointment() {
|
|
System.out.println("=================================================================");
|
|
System.out.print("Pet ID: ");
|
|
String petId = scanner.nextLine();
|
|
|
|
Optional<Pet> pet = pets.stream().filter(p -> p.getId().equals(petId)).findFirst();
|
|
if (pet.isEmpty()) {
|
|
System.err.printf("No Pet with id %s%n", petId);
|
|
return;
|
|
}
|
|
|
|
System.out.printf("Type (%s): ", Arrays.stream(Appointment.Type.values()).map(Enum::name).collect(Collectors.joining("|")));
|
|
String typeStr = scanner.nextLine().toUpperCase();
|
|
if (Arrays.stream(Appointment.Type.values()).map(Enum::name).noneMatch(t -> t.equals(typeStr))) {
|
|
System.err.printf("%s is not a valid appointment type%n", typeStr);
|
|
return;
|
|
}
|
|
|
|
System.out.print("Date (dd/mm/yyyy): ");
|
|
String dateStr = scanner.nextLine();
|
|
LocalDate date;
|
|
try {
|
|
date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("dd/MM/yyyy"));
|
|
} catch (DateTimeParseException dtpe) {
|
|
System.err.printf("%s is not a valid date%n", dateStr);
|
|
return;
|
|
}
|
|
|
|
System.out.print("Time (hh:mm): ");
|
|
String timeStr = scanner.nextLine();
|
|
LocalTime time;
|
|
try {
|
|
time = LocalTime.parse(timeStr, DateTimeFormatter.ofPattern("HH:mm"));
|
|
} catch (DateTimeParseException dtpe) {
|
|
System.err.printf("%s is not a valid time%n", timeStr);
|
|
return;
|
|
}
|
|
|
|
System.out.print("Notes: ");
|
|
String notes = scanner.nextLine();
|
|
|
|
Appointment appointment = new Appointment(Appointment.Type.valueOf(typeStr), date, time, notes);
|
|
pet.get().addAppointment(appointment);
|
|
|
|
System.out.printf("Appointment added for pet %s at %s%n", pet.get().getName(), appointment.getDate().atTime(appointment.getTime()));
|
|
System.out.println("=================================================================");
|
|
System.out.println();
|
|
}
|
|
|
|
/**
|
|
* List all pets in the system
|
|
*/
|
|
public void list() {
|
|
System.out.println("=================================================================");
|
|
System.out.println();
|
|
|
|
for (Pet pet: pets) {
|
|
System.out.printf("Id:\t\t\t%s%n", pet.getId());
|
|
System.out.printf("Name:\t\t%s%n", pet.getName());
|
|
System.out.printf("Owner:\t\t%s%n", pet.getOwner());
|
|
System.out.printf("Contact:\t%s%n", pet.getContactInformation());
|
|
System.out.printf("Breed:\t\t%s%n", pet.getBreed());
|
|
System.out.printf("Age:\t\t%d%n", pet.getAge());
|
|
System.out.printf("Registered:\t%s%n", pet.getRegistrationDate());
|
|
|
|
System.out.println("Upcoming Appointments:");
|
|
for (Appointment appointment : pet.getAppointments()) {
|
|
if (appointment.getDate().atTime(appointment.getTime()).isAfter(LocalDateTime.now())) {
|
|
System.out.printf("\t- %s %s %s%n",
|
|
appointment.getDate().atTime(appointment.getTime()),
|
|
appointment.getType(),
|
|
appointment.getNotes());
|
|
}
|
|
}
|
|
|
|
System.out.println("Past Appointments:");
|
|
for (Appointment appointment : pet.getAppointments()) {
|
|
if (appointment.getDate().atTime(appointment.getTime()).isBefore(LocalDateTime.now())) {
|
|
System.out.printf("\t- %s %s %s%n",
|
|
appointment.getDate().atTime(appointment.getTime()),
|
|
appointment.getType(),
|
|
appointment.getNotes());
|
|
}
|
|
}
|
|
|
|
System.out.println();
|
|
}
|
|
|
|
System.out.println("=================================================================");
|
|
System.out.println();
|
|
}
|
|
|
|
/**
|
|
* Generate a report of future and past appointments
|
|
*/
|
|
public void report() {
|
|
System.out.println("=================================================================");
|
|
System.out.println("Next Week: ");
|
|
LocalDateTime nextMonday = LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.MONDAY)).atTime(LocalTime.MIDNIGHT);
|
|
LocalDateTime nextSunday = nextMonday.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
|
|
for (Pet pet : pets) {
|
|
for (Appointment appointment : pet.getAppointments()) {
|
|
LocalDateTime dt = appointment.getDate().atTime(appointment.getTime());
|
|
if (dt.isAfter(nextMonday) && dt.isBefore(nextSunday)) {
|
|
System.out.printf("%s: %s %s %s%n", pet.getId(), dt, pet.getName(), pet.getOwner());
|
|
}
|
|
}
|
|
}
|
|
|
|
System.out.println();
|
|
|
|
System.out.println("Due Visits: ");
|
|
LocalDateTime dueDate = LocalDate.now().minusMonths(6).atTime(LocalTime.MIDNIGHT);
|
|
for (Pet pet : pets) {
|
|
for (Appointment appointment : pet.getAppointments()) {
|
|
LocalDateTime dt = appointment.getDate().atTime(appointment.getTime());
|
|
if (dt.isBefore(dueDate)) {
|
|
System.out.printf("%s: %s %s %s%n", pet.getId(), dt, pet.getName(), pet.getOwner());
|
|
}
|
|
}
|
|
}
|
|
|
|
System.out.println("=================================================================");
|
|
System.out.println();
|
|
}
|
|
|
|
/**
|
|
* Load pets from file
|
|
*/
|
|
private boolean loadPetsFromFile() {
|
|
File dataFile = new File(".", dataFileName);
|
|
if (!dataFile.exists()) {
|
|
System.out.println("No data file exists, loading empty pet database");
|
|
return true;
|
|
}
|
|
|
|
try (BufferedReader reader = Files.newBufferedReader(dataFile.toPath())) {
|
|
String line;
|
|
while((line = reader.readLine()) != null) {
|
|
StringTokenizer petDeserializer = new StringTokenizer(line, "|");
|
|
Pet pet = new Pet(
|
|
petDeserializer.nextToken(), // id
|
|
petDeserializer.nextToken(), // name
|
|
petDeserializer.nextToken(), // owner
|
|
petDeserializer.nextToken(), // contactInformation
|
|
petDeserializer.nextToken(), // breed
|
|
Integer.parseInt(petDeserializer.nextToken()), //age
|
|
LocalDate.parse(petDeserializer.nextToken(), DateTimeFormatter.ISO_DATE) // registrationDate
|
|
);
|
|
|
|
while((line = reader.readLine()) != null) {
|
|
if (line.isEmpty()) {
|
|
break;
|
|
}
|
|
|
|
StringTokenizer appointmentDeserializer = new StringTokenizer(line, "|");
|
|
Appointment appointment = new Appointment(
|
|
Appointment.Type.valueOf(appointmentDeserializer.nextToken()), // type
|
|
LocalDate.parse(appointmentDeserializer.nextToken(), DateTimeFormatter.ISO_DATE), // date
|
|
LocalTime.parse(appointmentDeserializer.nextToken(), DateTimeFormatter.ISO_TIME), // time
|
|
appointmentDeserializer.hasMoreTokens() ? appointmentDeserializer.nextToken() : "" // notes
|
|
);
|
|
pet.addAppointment(appointment);
|
|
}
|
|
|
|
pets.add(pet);
|
|
}
|
|
System.out.printf("%d pets loaded successfully from data file %s.%n", pets.size(), dataFileName);
|
|
return true;
|
|
} catch (IOException | RuntimeException e) {
|
|
System.err.printf("Failed to read data file. %s%n", e.getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save pets to file
|
|
*/
|
|
private boolean savePetsToFile() {
|
|
if (pets == null || pets.isEmpty()) {
|
|
System.out.println("No pets to save");
|
|
return true;
|
|
}
|
|
|
|
File dataFile = new File(".", dataFileName);
|
|
|
|
try {
|
|
Path parent = dataFile.toPath().getParent();
|
|
if (parent != null) {
|
|
Files.createDirectories(parent);
|
|
}
|
|
} catch (IOException e) {
|
|
System.err.println("Failed to create data directory");
|
|
return false;
|
|
}
|
|
|
|
OpenOption[] fileOptions = new OpenOption[]{ StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING };
|
|
try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(dataFile.toPath(), fileOptions))) {
|
|
for (Pet pet : pets) {
|
|
StringJoiner petSerializer = new StringJoiner("|");
|
|
petSerializer.add(Objects.toString(pet.getId(), UUID.randomUUID().toString()));
|
|
petSerializer.add(Objects.toString(pet.getName()," "));
|
|
petSerializer.add(Objects.toString(pet.getOwner(), " "));
|
|
petSerializer.add(Objects.toString(pet.getContactInformation(), "None"));
|
|
petSerializer.add(Objects.toString(pet.getBreed(), "Unknown"));
|
|
petSerializer.add(String.valueOf(pet.getAge()));
|
|
petSerializer.add(Optional.ofNullable(pet.getRegistrationDate()).orElse(LocalDate.now()).format(DateTimeFormatter.ISO_DATE));
|
|
writer.println(petSerializer);
|
|
|
|
for (Appointment appointment : pet.getAppointments()) {
|
|
StringJoiner appointmentSerializer = new StringJoiner("|");
|
|
appointmentSerializer.add(appointment.getType().name());
|
|
appointmentSerializer.add(appointment.getDate().format(DateTimeFormatter.ISO_DATE));
|
|
appointmentSerializer.add(appointment.getTime().format(DateTimeFormatter.ISO_TIME));
|
|
appointmentSerializer.add(appointment.getNotes());
|
|
writer.println(appointmentSerializer);
|
|
}
|
|
|
|
writer.println();
|
|
}
|
|
System.out.printf("%d pets saved successfully to fata file %s.%n", pets.size(), dataFileName);
|
|
return true;
|
|
} catch (IOException | RuntimeException e) {
|
|
System.err.printf("Failed to write to file. %s%n", e.getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
} |