Add Pet Scheduler assignment
This commit is contained in:
0
PetCareScheduler/build.gradle
Normal file
0
PetCareScheduler/build.gradle
Normal file
67
PetCareScheduler/src/main/java/Appointment.java
Normal file
67
PetCareScheduler/src/main/java/Appointment.java
Normal file
@@ -0,0 +1,67 @@
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public final class Appointment {
|
||||
|
||||
private Type type;
|
||||
private LocalDate date;
|
||||
private LocalTime time;
|
||||
private String notes;
|
||||
|
||||
public Appointment(Type type, LocalDate date, LocalTime time, String notes) {
|
||||
this.type = requireNonNull(type, "Type must not be null");
|
||||
this.date = requireNonNull(date, "date must not be null");
|
||||
this.time = requireNonNull(time, "time must not be null");
|
||||
this.notes = requireNonNull(notes, "note must not be null");
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public LocalDate getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public LocalTime getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public String getNotes() {
|
||||
return notes;
|
||||
}
|
||||
|
||||
public void setType(Type type) {
|
||||
this.type = requireNonNull(type, "Type must not be null");
|
||||
}
|
||||
|
||||
public void setDate(LocalDate date) {
|
||||
this.date = requireNonNull(date, "date must not be null");
|
||||
}
|
||||
|
||||
public void setTime(LocalTime time) {
|
||||
this.time = requireNonNull(time, "time must not be null");
|
||||
}
|
||||
|
||||
public void setNotes(String notes) {
|
||||
this.notes = requireNonNull(notes, "note must not be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Appointment{" +
|
||||
"type=" + type +
|
||||
", date=" + date +
|
||||
", time=" + time +
|
||||
", notes='" + notes + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
VET_VISIT,
|
||||
VACCINATION,
|
||||
GROOMING
|
||||
}
|
||||
}
|
||||
110
PetCareScheduler/src/main/java/Pet.java
Normal file
110
PetCareScheduler/src/main/java/Pet.java
Normal file
@@ -0,0 +1,110 @@
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public final class Pet {
|
||||
|
||||
private String id;
|
||||
private String name;
|
||||
private String owner;
|
||||
private String contactInformation;
|
||||
private String breed;
|
||||
private int age;
|
||||
private LocalDate registrationDate;
|
||||
private final List<Appointment> appointments = new ArrayList<>();
|
||||
|
||||
public Pet(String id, String name, String owner, String contactInformation, String breed, int age, LocalDate registrationDate) {
|
||||
|
||||
if (age < 0) throw new IllegalArgumentException("Age must be over 0");
|
||||
|
||||
this.age = age;
|
||||
this.id = requireNonNull(id, "id must not be null");
|
||||
this.name = requireNonNull(name, "Name must not be null");
|
||||
this.owner = requireNonNull(owner, "Owner must not be null");
|
||||
this.contactInformation = requireNonNull(contactInformation, "Contact information must not be null");
|
||||
this.breed = requireNonNull(breed, "Breed must not be null");
|
||||
this.registrationDate = requireNonNull(registrationDate, "Registration date must not be null");
|
||||
}
|
||||
|
||||
public void addAppointment(Appointment appointment) {
|
||||
this.appointments.add(requireNonNull(appointment, "Appointment must not be null"));
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public String getContactInformation() {
|
||||
return contactInformation;
|
||||
}
|
||||
|
||||
public String getBreed() {
|
||||
return breed;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public LocalDate getRegistrationDate() {
|
||||
return registrationDate;
|
||||
}
|
||||
|
||||
public List<Appointment> getAppointments() {
|
||||
return Collections.unmodifiableList(appointments);
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = requireNonNull(id, "id must not be null");
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = requireNonNull(name, "Name must not be null");
|
||||
}
|
||||
|
||||
public void setOwner(String owner) {
|
||||
this.owner = requireNonNull(owner, "Owner must not be null");
|
||||
}
|
||||
|
||||
public void setContactInformation(String contactInformation) {
|
||||
this.contactInformation =requireNonNull(contactInformation, "Contact information must not be null");
|
||||
}
|
||||
|
||||
public void setBreed(String breed) {
|
||||
this.breed = requireNonNull(breed, "Breed must not be null");
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
if (age < 0) throw new IllegalArgumentException("Age must be over 0");
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public void setRegistrationDate(LocalDate registrationDate) {
|
||||
this.registrationDate = requireNonNull(registrationDate, "Registration date must not be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Pet{" +
|
||||
"id='" + id + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", owner='" + owner + '\'' +
|
||||
", contactInformation='" + contactInformation + '\'' +
|
||||
", breed='" + breed + '\'' +
|
||||
", age=" + age +
|
||||
", registrationDate=" + registrationDate +
|
||||
", appointments=" + appointments +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
379
PetCareScheduler/src/main/java/PetCareScheduler.java
Normal file
379
PetCareScheduler/src/main/java/PetCareScheduler.java
Normal file
@@ -0,0 +1,379 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user