commit 7f4f8f475b6e917593397e80050ded61697fb33e Author: AndAlb Date: Tue Mar 31 14:34:08 2026 +0200 Initial commit: VS&NB diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9bcc548 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ + # Compiled Java output + bin/ + target/ + *.class + + # NetBeans private/generated files + nbproject/private/ + nbbuild/ + dist/ + nbdist/ + + # VS Code personal settings + .vscode/launch.json + .vscode/tasks.json + + # OS files + .DS_Store + Thumbs.db + + # PDF files + *.pdf EOF +cat > .gitignore << 'EOF' + # Compiled Java output + bin/ + target/ + *.class + + # NetBeans private/generated files + nbproject/private/ + nbbuild/ + dist/ + nbdist/ + + # VS Code personal settings + .vscode/launch.json + .vscode/tasks.json + + # OS files + .DS_Store + Thumbs.db + + # PDF files + *.pdf diff --git a/00824_IC2026.pdf b/00824_IC2026.pdf new file mode 100644 index 0000000..fe46612 Binary files /dev/null and b/00824_IC2026.pdf differ diff --git a/NetBeans_Proyecto_1_Parqueo/pom.xml b/NetBeans_Proyecto_1_Parqueo/pom.xml new file mode 100644 index 0000000..9d74671 --- /dev/null +++ b/NetBeans_Proyecto_1_Parqueo/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + cr.uned + parqueo + 1.0-SNAPSHOT + jar + + + UTF-8 + 21 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + ${maven.compiler.release} + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + Main + + + + + diff --git a/NetBeans_Proyecto_1_Parqueo/src/main/java/CalculoTarifa.java b/NetBeans_Proyecto_1_Parqueo/src/main/java/CalculoTarifa.java new file mode 100644 index 0000000..df07fbb --- /dev/null +++ b/NetBeans_Proyecto_1_Parqueo/src/main/java/CalculoTarifa.java @@ -0,0 +1,119 @@ +import java.time.LocalDateTime; +import java.time.Duration; + +public class CalculoTarifa { + + //originalmente calculaba el monto total aquí y en Main, pero codex sugirió mantener cálculos fuera de main. El prompt fué: "Remove the duplicate and adjust the text." + public static class DetalleCobro { + private long minutos; + private int tarifaAplicada; + private long unidCobro; + private int subtotal; + private int descuento; + private int total; + + public DetalleCobro(long minutos, int tarifaAplicada, long unidCobro, int subtotal, int descuento, int total) { + this.minutos = minutos; + this.tarifaAplicada = tarifaAplicada; + this.unidCobro = unidCobro; + this.subtotal = subtotal; + this.descuento = descuento; + this.total = total; + } + + public long getMinutos() { + return minutos; + } + + public int getTarifaAplicada() { + return tarifaAplicada; + } + + public long getUnidCobro() { + return unidCobro; + } + + public int getSubtotal() { + return subtotal; + } + + public int getDescuento() { + return descuento; + } + + public int getTotal() { + return total; + } + } + + public int calcularMonto(TiqueteParqueo t) { + DetalleCobro detalle = calcularDetalle(t); + t.setMontoTotal(detalle.getTotal()); + return detalle.getTotal(); + } + + public DetalleCobro calcularDetalle(TiqueteParqueo t) { + long minutos = calcularMinCobro(t); + int tarifa = obtenerTarifa(t); + long unidades = getUnidadCobro(minutos, t.getModalidad()); + int subtotal = (int) (unidades * tarifa); + int descuento = calcularDescuento(t.getModalidad(), unidades, subtotal); + int total = subtotal - descuento; + return new DetalleCobro(minutos, tarifa, unidades, subtotal, descuento, total); + } + + // Obtiene la tarifa segun tipo (1=Auto, 2=Moto, 3=Camion) + private int obtenerTarifa(TiqueteParqueo t) { + + TiqueteParqueo.TipoServicio modalidad = t.getModalidad(); + int tipo = t.getVehiculo().getTipo(); + + if (modalidad == TiqueteParqueo.TipoServicio.POR_HORA) { + if (tipo == 2) { + return 500; + } else if (tipo == 1 || tipo == 3) { + return 600; + } + } + + if (modalidad == TiqueteParqueo.TipoServicio.POR_DIA) { + if (tipo == 2) { + return 3000; + } else if (tipo == 1 || tipo == 3) { + return 5000; + } + } + + throw new IllegalArgumentException("Tipo de vehículo o modalidad inválidos."); + } + + private long calcularMinCobro(TiqueteParqueo t) { + LocalDateTime horaEntrada = t.getHoraEntrada(); + LocalDateTime horaSalida = t.getHoraSalida(); + + if (horaSalida.isBefore(horaEntrada)) { //excepción recomendada por codex + throw new IllegalArgumentException("La hora de salida no puede ser anterior a la hora de entrada."); + } + + long minutos = Duration.between(horaEntrada, horaSalida).toMinutes(); + if (minutos == 0) { + return 1; + } + return minutos; + } + + private long getUnidadCobro(long minutos, TiqueteParqueo.TipoServicio modalidad) { + if (modalidad == TiqueteParqueo.TipoServicio.POR_HORA) { + return (minutos + 59) / 60; + } + return (minutos + 1439) / 1440; + } + + private int calcularDescuento(TiqueteParqueo.TipoServicio modalidad, long unidades, int subtotal) { + if (modalidad == TiqueteParqueo.TipoServicio.POR_HORA && unidades > 8) { + return subtotal * 10 / 100; + } + return 0; + } + +} diff --git a/NetBeans_Proyecto_1_Parqueo/src/main/java/GestorParqueo.java b/NetBeans_Proyecto_1_Parqueo/src/main/java/GestorParqueo.java new file mode 100644 index 0000000..be68a0d --- /dev/null +++ b/NetBeans_Proyecto_1_Parqueo/src/main/java/GestorParqueo.java @@ -0,0 +1,94 @@ +import java.util.ArrayList; +import java.time.LocalDate; + +public class GestorParqueo { + + private static final int MAX_VEHICULOS = 10; + + private ArrayList vehiculosParqueados; + private ArrayList tiquetes; + + public GestorParqueo() { + + this.vehiculosParqueados = new ArrayList(); + this.tiquetes = new ArrayList(); + + } + + public boolean registrarIngreso(TiqueteParqueo nuevoTiquete) { + if (this.vehiculosParqueados.size() < MAX_VEHICULOS + && !existePlaca(nuevoTiquete.getVehiculo().getPlaca())) { + this.vehiculosParqueados.add(nuevoTiquete.getVehiculo()); + this.tiquetes.add(nuevoTiquete); + return true; + } + if (this.vehiculosParqueados.size() > 4){ + System.out.println("Aviso: quedan " + espaciosDisponibles() + "espacios disponibles."); + } + return false; + } + + public boolean existePlaca(String placa) { + for (Vehiculo vehiculo : this.vehiculosParqueados) { + if (vehiculo.getPlaca().equals(placa)) { + return true; + } + } + return false; + } + + public int espaciosDisponibles() { + return MAX_VEHICULOS - this.vehiculosParqueados.size(); + } + + public int getCapacidadMaxima() { + return MAX_VEHICULOS; + } + + public boolean estaVacio() { + return this.vehiculosParqueados.isEmpty(); + } + + public TiqueteParqueo buscarTiqueteAbierto(String placa) { + for (TiqueteParqueo tiquete : this.tiquetes) { + if (tiquete.getVehiculo().getPlaca().equals(placa) && tiquete.getHoraSalida() == null) { + return tiquete; + } + } + return null; + } + + public boolean registrarSalida(String placa) { + boolean vehiculoEliminado = false; + for (int i = 0; i < this.vehiculosParqueados.size(); i++) { + if (this.vehiculosParqueados.get(i).getPlaca().equals(placa)) { + this.vehiculosParqueados.remove(i); + vehiculoEliminado = true; + break; + } + } + + return vehiculoEliminado; + } + + public Vehiculo buscarPlaca(String placa) { + for (Vehiculo vehiculo : this.vehiculosParqueados) { + if (vehiculo.getPlaca().equals(placa)) { + return vehiculo; + } + } + return null; + } + + public ArrayList getTiquetesDia(LocalDate fecha) { + ArrayList resultado = new ArrayList(); + for (TiqueteParqueo tiquete : this.tiquetes) { + if (tiquete.getHoraEntrada() != null + && tiquete.getHoraEntrada().toLocalDate().equals(fecha)) { + resultado.add(tiquete); + } + } + return resultado; + } + +} diff --git a/NetBeans_Proyecto_1_Parqueo/src/main/java/Main.java b/NetBeans_Proyecto_1_Parqueo/src/main/java/Main.java new file mode 100644 index 0000000..ca1d64f --- /dev/null +++ b/NetBeans_Proyecto_1_Parqueo/src/main/java/Main.java @@ -0,0 +1,282 @@ +/* +UNIVERSIDAD ESTATAL A DISTANCIA +ESCUELAS DE CIENCIAS EXACTAS Y NATURALES +CATEDRA TECNOLOGÍA DE SISTEMAS + +ANDRES ALBERTO SANCHEZ TREJOS +GRUPO 09 +TUTOR: HERSANN FONSECA QUIRÓS +PROGRAMACION INTERMEDIA 00824 +Proyecto #1 +IC2026 + + +Bibliografía +Deitel, P.J.D. H. (2021). Cómo Programar En Java. Pearson HispanoAmerica Contenido. https://bookshelf.vitalsource.com/books/9786073255400 +https://www.w3schools.com/java/ +CODEX: se usó para generalmente para revisar la eficacia de las cláses y métodos. +El prompt generalmente utilizado fue "revisa esta método/función" o fué utilizado . + +*/ + +import java.util.Scanner; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class Main { + + private static final DateTimeFormatter fechaHora = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"); + + public static void main(String[] args) throws Exception { + GestorParqueo gestorParqueo = new GestorParqueo(); + + Scanner entrada = new Scanner(System.in); + int opcion = 0; + + System.out.println("================================="); + System.out.println("Bienvenido al sistema de parqueo"); + System.out.println("================================="); + LocalDate fechaAc = LocalDate.now(); + System.out.println("Fecha actual: " + fechaAc); + + while (opcion != 5) { + System.out.println("1. Registrar ingreso de vehículo"); + System.out.println("2. Registrar salida de vehículo"); + System.out.println("3. Consultar espacios disponibles"); + System.out.println("4. Ver reportes del día"); + System.out.println("5. Salir"); + System.out.println("Seleccione una opción:"); + opcion = intValida(entrada); + + switch (opcion) { + case 1: + TiqueteParqueo nuevoTiquete = registrarIngreso(entrada, gestorParqueo); + if (nuevoTiquete != null) { + if (gestorParqueo.registrarIngreso(nuevoTiquete)) { + System.out.println("Ingreso registrado correctamente."); + System.out.println("Espacios disponible: " + gestorParqueo.espaciosDisponibles() + "/10"); + if (gestorParqueo.espaciosDisponibles() <= 5) { + System.err.println("Advertencia: Se ha alcanzado el 50% de capacidad máxima"); + } + if (gestorParqueo.espaciosDisponibles() == 10) { + System.out.println("Advertencia: Se ha alcanzado la capacidad máxima 10/10."); + } + } else { + System.out.println("No hay espacios disponibles."); + } + } + regresarMenuPrincipal(entrada); + break; + case 2: + if (!gestorParqueo.estaVacio()) { + registrarSalida(entrada, gestorParqueo); + } else { + System.out.println("No hay vehiculos registrados."); + } + regresarMenuPrincipal(entrada); + break; + case 3: + System.out.println("Espacios disponibles: " + gestorParqueo.espaciosDisponibles()); + regresarMenuPrincipal(entrada); + break; + case 4: + mostrarMenuReportes(entrada, gestorParqueo); + regresarMenuPrincipal(entrada); + break; + case 5: + System.out.println("Saliendo del sistema de parqueo."); + break; + default: + System.out.println("Opción inválida. Por favor, seleccione una opción válida."); + regresarMenuPrincipal(entrada); + break; + } + + } + + entrada.close(); + } + + private static TiqueteParqueo registrarIngreso(Scanner entrada, GestorParqueo gestorParqueo) { + String placa = placaValida(entrada); + if (gestorParqueo.existePlaca(placa)) { + System.out.println("La placa ingresada ya está registrada."); + return null; + } + + int tipo = -1; + boolean tipoValido = false; + while (!tipoValido) { + System.out.println("Ingrese el tipo de vehículo (1 para Automóvil, 2 para Motocicleta, 3 para Camión):"); + tipo = intValida(entrada); + if (tipo >= 1 && tipo <= 3) { + tipoValido = true; + } else { + System.out.println("Opción inválida. Por favor, seleccione una opción válida."); + } + } + + TiqueteParqueo.TipoServicio modalidad = setModalidad(entrada); + + try { + Vehiculo vehiculo = new Vehiculo(placa, tipo); + return new TiqueteParqueo(vehiculo, LocalDateTime.now(), modalidad); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + return null; + } + } + + private static void registrarSalida(Scanner entrada, GestorParqueo gestorParqueo) { + + String placa = placaValida(entrada); + TiqueteParqueo tiquete = gestorParqueo.buscarTiqueteAbierto(placa); + + if (tiquete == null) { + System.out.println("Placa no se encuentra registrada en el sistema."); + } else { + tiquete.setHoraSalida(LocalDateTime.now()); + CalculoTarifa calculadora = new CalculoTarifa(); + CalculoTarifa.DetalleCobro detalle = calculadora.calcularDetalle(tiquete); + int monto = detalle.getTotal(); + tiquete.setMontoTotal(monto); + gestorParqueo.registrarSalida(placa); + + String horaEntrada = tiquete.getHoraEntrada().format(fechaHora); + String horaSalida = tiquete.getHoraSalida().format(fechaHora); + double tiempoHoras = detalle.getMinutos() / 60.0; + + System.out.println("****************************************"); + System.out.println("RECIBO DE PARQUEO"); + System.out.println("****************************************"); + System.out.println("Placa: " + tiquete.getVehiculo().getPlaca()); + System.out.println("Tipo: " + tipoVehiculoTexto(tiquete.getVehiculo().getTipo())); + System.out.println("Tipo de servicio: " + tipoServicioTexto(tiquete.getModalidad())); + System.out.println("Hora de entrada: " + horaEntrada); + System.out.println("Hora de salida: " + horaSalida); + System.out.println("Tiempo de permanencia (horas): " + String.format("%.2f", tiempoHoras)); + if (tiquete.getModalidad() == TiqueteParqueo.TipoServicio.POR_HORA) { + System.out.println("Costo por hora: CRC " + detalle.getTarifaAplicada()); + } else { + System.out.println("Costo por hora: No aplica (servicio por día)"); + } + System.out.println("Subtotal: CRC " + detalle.getSubtotal()); + if (detalle.getDescuento() > 0) { + System.out.println("Descuento: CRC " + detalle.getDescuento()); + } else { + System.out.println("Descuento: No aplica"); + } + System.out.println("========================================"); + System.out.println("TOTAL A PAGAR: CRC " + monto); + System.out.println("========================================"); + System.out.println("Gracias por usar nuestros servicios"); + } + + } + + private static void mostrarMenuReportes(Scanner entrada, GestorParqueo gestorParqueo) { + ReporteParqueo reporteParqueo = new ReporteParqueo(); + int opcionReporte = 0; + + while (opcionReporte != 4) { + System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + System.out.println("+ Menú de reportes del día +"); + System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + System.out.println("1. Listado de vehículos"); + System.out.println("2. Total recaudado por tipo de servicio"); + System.out.println("3. Estadísticas básicas de uso del parqueo"); + System.out.println("4. Volver al menú principal"); + System.out.println("Seleccione una opción:"); + opcionReporte = intValida(entrada); + + switch (opcionReporte) { + case 1: + reporteParqueo.vehiculosDia(gestorParqueo, LocalDate.now()); + break; + case 2: + reporteParqueo.totalUtilServicio(gestorParqueo, LocalDate.now()); + break; + case 3: + reporteParqueo.estadisticasBasicas(gestorParqueo, LocalDate.now()); + break; + case 4: + System.out.println("Regresando al menú principal."); + break; + default: + System.out.println("Opción inválida. Por favor, seleccione una opción válida."); + break; + } + } + } + + // define el tipo de servicio (modalida por dia o por hora) + private static TiqueteParqueo.TipoServicio setModalidad(Scanner entrada) { + int modalidad = -1; + while (modalidad != 1 && modalidad != 2) { + System.out.println("Seleccione modalidad de cobro (1 por hora, 2 por día):"); + modalidad = intValida(entrada); + if (modalidad != 1 && modalidad != 2) { + System.out.println("Opción inválida. Por favor, seleccione una opción válida."); + } + } + + if (modalidad == 1) { + return TiqueteParqueo.TipoServicio.POR_HORA; + } + return TiqueteParqueo.TipoServicio.POR_DIA; + } + + private static int intValida(Scanner entrada) { + int opcion = -1; + try { + opcion = Integer.parseInt(entrada.nextLine().trim()); + } catch (NumberFormatException e) { + System.out.println("Error: Entrada inválida. Por favor, ingrese un número entero."); + } + return opcion; + } + + private static void regresarMenuPrincipal(Scanner entrada) { + System.out.println("Presione Enter para volver al menú principal..."); + entrada.nextLine(); + } + + private static String placaValida(Scanner entrada) { + String placa = ""; + boolean placaValida = false; + while (!placaValida) { + System.out.println("Ingrese la placa del vehículo (en formato ABC123):"); + placa = entrada.nextLine().trim().toUpperCase(); + if (placa.isEmpty()) { + System.out.println("La placa no puede estar vacía."); + } else if (!Vehiculo.esPlacaValida(placa)) { + System.out.println("Formato inválido. Use 3 letras y 3 números (ejemplo: ABC123)."); + } else { + placaValida = true; + } + } + return placa; + } + + private static String tipoVehiculoTexto(int tipo) { + if (tipo == 1) { + return "Automóvil"; + } + if (tipo == 2) { + return "Motocicleta"; + } + if (tipo == 3) { + return "Camión"; + } + return "Desconocido"; + } + + private static String tipoServicioTexto(TiqueteParqueo.TipoServicio modalidad) { + if (modalidad == TiqueteParqueo.TipoServicio.POR_HORA) { + return "Por hora"; + } + return "Por día"; + } + +} diff --git a/NetBeans_Proyecto_1_Parqueo/src/main/java/ReporteParqueo.java b/NetBeans_Proyecto_1_Parqueo/src/main/java/ReporteParqueo.java new file mode 100644 index 0000000..4e635bf --- /dev/null +++ b/NetBeans_Proyecto_1_Parqueo/src/main/java/ReporteParqueo.java @@ -0,0 +1,96 @@ +import java.time.LocalDate; +import java.time.Duration; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; + +public class ReporteParqueo { + + private static final DateTimeFormatter soloFecha = DateTimeFormatter.ofPattern("dd/MM/yyyy"); + + public void vehiculosDia(GestorParqueo gestorParqueo, LocalDate fecha) { + + ArrayList tiquetes = gestorParqueo.getTiquetesDia(fecha); + + String fechaFormateada = fecha.format(soloFecha); + + if (tiquetes.isEmpty()) { + System.out.println("No hay vehículos registrados para la fecha: " + fechaFormateada); + return; + } + + System.out.println("Vehículos que usaron el parqueo el día " + fechaFormateada + ":"); + for (TiqueteParqueo tiquete : tiquetes) { + + String placa = tiquete.getVehiculo().getPlaca(); + String tipo = tipoVehiculoTexto(tiquete.getVehiculo().getTipo()); + String entrada = tiquete.getHoraEntrada().format(soloFecha); + String salida = "Aún parqueado"; + if (tiquete.getHoraSalida() != null) { + salida = tiquete.getHoraSalida().format(soloFecha); + } + + System.out.println( + "Placa: " + placa + " | Tipo: " + tipo + " | Entrada: " + entrada + " | Salida: " + salida); + } + } + + public void totalUtilServicio(GestorParqueo gestorParqueo, LocalDate fecha) { + + ArrayList tiquetes = gestorParqueo.getTiquetesDia(fecha); + int totalPorHora = 0; + int totalPorDia = 0; + + for (TiqueteParqueo tiquete : tiquetes) { + if (tiquete.getHoraSalida() == null) { + continue; + } + + if (tiquete.getModalidad() == TiqueteParqueo.TipoServicio.POR_HORA) { + totalPorHora += tiquete.getMontoTotal(); + } else { + totalPorDia += tiquete.getMontoTotal(); + } + } + + String fechaFormateada = fecha.format(soloFecha); + System.out.println("Total recaudado por servicio el día " + fechaFormateada + ":"); + System.out.println("Servicio por hora: CRC " + totalPorHora); + System.out.println("Servicio por día: CRC " + totalPorDia); + } + + public void estadisticasBasicas(GestorParqueo gestorParqueo, LocalDate fecha) { + ArrayList tiquetes = gestorParqueo.getTiquetesDia(fecha); + int vehiculosAtendidos = tiquetes.size(); + long minutosTotales = 0; + + for (TiqueteParqueo tiquete : tiquetes) { + if (tiquete.getHoraSalida() != null) { + minutosTotales += Duration.between(tiquete.getHoraEntrada(), tiquete.getHoraSalida()).toMinutes(); + } + } + + double horasTotales = minutosTotales / 60.0; + int capacidad = gestorParqueo.getCapacidadMaxima(); + int ocupadosActuales = capacidad - gestorParqueo.espaciosDisponibles(); + double ocupacionActual = (ocupadosActuales * 100.0) / capacidad; + + String fechaFormateada = fecha.format(soloFecha); + System.out.println("Estadísticas básicas del día " + fechaFormateada + ":"); + System.out.println("Sumatoria de horas de uso: " + String.format("%.2f", horasTotales)); + System.out.println("Cantidad de vehículos atendidos: " + vehiculosAtendidos); + System.out.println("Porcentaje de ocupación actual: " + String.format("%.2f", ocupacionActual) + "%"); + } + + private String tipoVehiculoTexto(int tipo) { + if (tipo == 1) { + return "Automóvil"; + } + if (tipo == 2) { + return "Motocicleta"; + } + if (tipo == 3) { + return "Camión"; + } + return "Desconocido"; + } +} diff --git a/NetBeans_Proyecto_1_Parqueo/src/main/java/TiqueteParqueo.java b/NetBeans_Proyecto_1_Parqueo/src/main/java/TiqueteParqueo.java new file mode 100644 index 0000000..63a83a8 --- /dev/null +++ b/NetBeans_Proyecto_1_Parqueo/src/main/java/TiqueteParqueo.java @@ -0,0 +1,64 @@ +import java.time.LocalDateTime; + +public class TiqueteParqueo { + + //orginalmente dos constantes, CODEX sugirió usar enum + public enum TipoServicio { + POR_HORA, + POR_DIA + } + + private Vehiculo vehiculo; + private LocalDateTime horaEntrada; + private LocalDateTime horaSalida; + private TipoServicio modalidad; + private int montoTotal; + + public TiqueteParqueo(Vehiculo vehiculo, LocalDateTime horaEntrada, TipoServicio modalidad) { + this.vehiculo = vehiculo; + this.horaEntrada = horaEntrada; + this.modalidad = modalidad; + this.horaSalida = null; + this.montoTotal = 0; + } + + public Vehiculo getVehiculo() { + return vehiculo; + } + + public void setVehiculo(Vehiculo vehiculo) { + this.vehiculo = vehiculo; + } + + public LocalDateTime getHoraEntrada() { + return horaEntrada; + } + + public void setHoraEntrada(LocalDateTime horaEntrada) { + this.horaEntrada = horaEntrada; + } + + public LocalDateTime getHoraSalida() { + return horaSalida; + } + + public void setHoraSalida(LocalDateTime horaSalida) { + this.horaSalida = horaSalida; + } + + public TipoServicio getModalidad() { + return modalidad; + } + + public void setModalidad(TipoServicio modalidad) { + this.modalidad = modalidad; + } + + public int getMontoTotal() { + return montoTotal; + } + + public void setMontoTotal(int montoTotal) { + this.montoTotal = montoTotal; + } +} diff --git a/NetBeans_Proyecto_1_Parqueo/src/main/java/Vehiculo.java b/NetBeans_Proyecto_1_Parqueo/src/main/java/Vehiculo.java new file mode 100644 index 0000000..22abed8 --- /dev/null +++ b/NetBeans_Proyecto_1_Parqueo/src/main/java/Vehiculo.java @@ -0,0 +1,49 @@ +import java.util.regex.Pattern; + +public class Vehiculo { + + private static final int AUTOMOVIL = 1; // constante de clase + private static final int MOTOCICLETA = 2; + private static final int CAMION = 3; + + private String placa; + private int tipo; + + // Constructor + public Vehiculo(String placa, int tipo) { + setPlaca(placa); + setTipo(tipo); + } + + public String getPlaca() { + return placa; + } + + public void setPlaca(String placa) { + if (esPlacaValida(placa)) { + this.placa = placa; + } else { + throw new IllegalArgumentException("La placa debe tener el formato ABC123."); + } + } + + public static boolean esPlacaValida(String placa) { + return Pattern.matches("[A-Z]{3}\\d{3}", placa); + } + + public int getTipo() { + return tipo; + } + + public void setTipo(int tipo) { + if (tipo == AUTOMOVIL || tipo == MOTOCICLETA || tipo == CAMION) { + this.tipo = tipo; + } else { + throw new IllegalArgumentException( + "Nümero inválido. Digite 1 para automóvil, 2 para motocicleta o 3 para camión."); + } + } + +} + + diff --git a/NetBeans_Proyecto_1_Parqueo/target/classes/CalculoTarifa$DetalleCobro.class b/NetBeans_Proyecto_1_Parqueo/target/classes/CalculoTarifa$DetalleCobro.class new file mode 100644 index 0000000..f426f61 Binary files /dev/null and b/NetBeans_Proyecto_1_Parqueo/target/classes/CalculoTarifa$DetalleCobro.class differ diff --git a/NetBeans_Proyecto_1_Parqueo/target/classes/CalculoTarifa.class b/NetBeans_Proyecto_1_Parqueo/target/classes/CalculoTarifa.class new file mode 100644 index 0000000..9820fd4 Binary files /dev/null and b/NetBeans_Proyecto_1_Parqueo/target/classes/CalculoTarifa.class differ diff --git a/NetBeans_Proyecto_1_Parqueo/target/classes/GestorParqueo.class b/NetBeans_Proyecto_1_Parqueo/target/classes/GestorParqueo.class new file mode 100644 index 0000000..8814e57 Binary files /dev/null and b/NetBeans_Proyecto_1_Parqueo/target/classes/GestorParqueo.class differ diff --git a/NetBeans_Proyecto_1_Parqueo/target/classes/Main.class b/NetBeans_Proyecto_1_Parqueo/target/classes/Main.class new file mode 100644 index 0000000..7f67bd6 Binary files /dev/null and b/NetBeans_Proyecto_1_Parqueo/target/classes/Main.class differ diff --git a/NetBeans_Proyecto_1_Parqueo/target/classes/ReporteParqueo.class b/NetBeans_Proyecto_1_Parqueo/target/classes/ReporteParqueo.class new file mode 100644 index 0000000..2672739 Binary files /dev/null and b/NetBeans_Proyecto_1_Parqueo/target/classes/ReporteParqueo.class differ diff --git a/NetBeans_Proyecto_1_Parqueo/target/classes/TiqueteParqueo$TipoServicio.class b/NetBeans_Proyecto_1_Parqueo/target/classes/TiqueteParqueo$TipoServicio.class new file mode 100644 index 0000000..368408f Binary files /dev/null and b/NetBeans_Proyecto_1_Parqueo/target/classes/TiqueteParqueo$TipoServicio.class differ diff --git a/NetBeans_Proyecto_1_Parqueo/target/classes/TiqueteParqueo.class b/NetBeans_Proyecto_1_Parqueo/target/classes/TiqueteParqueo.class new file mode 100644 index 0000000..ab963e8 Binary files /dev/null and b/NetBeans_Proyecto_1_Parqueo/target/classes/TiqueteParqueo.class differ diff --git a/NetBeans_Proyecto_1_Parqueo/target/classes/Vehiculo.class b/NetBeans_Proyecto_1_Parqueo/target/classes/Vehiculo.class new file mode 100644 index 0000000..3dfa40e Binary files /dev/null and b/NetBeans_Proyecto_1_Parqueo/target/classes/Vehiculo.class differ diff --git a/NetBeans_Proyecto_1_Parqueo/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/NetBeans_Proyecto_1_Parqueo/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..e69de29 diff --git a/NetBeans_Proyecto_1_Parqueo/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/NetBeans_Proyecto_1_Parqueo/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..8dfc6a0 --- /dev/null +++ b/NetBeans_Proyecto_1_Parqueo/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,6 @@ +/home/alberto/Documents/UNED/Prog. Intermedia/Proyecto 1/Proyecto_1_Parqueo/NetBeans_Proyecto_1_Parqueo/src/main/java/ReporteParqueo.java +/home/alberto/Documents/UNED/Prog. Intermedia/Proyecto 1/Proyecto_1_Parqueo/NetBeans_Proyecto_1_Parqueo/src/main/java/TiqueteParqueo.java +/home/alberto/Documents/UNED/Prog. Intermedia/Proyecto 1/Proyecto_1_Parqueo/NetBeans_Proyecto_1_Parqueo/src/main/java/Main.java +/home/alberto/Documents/UNED/Prog. Intermedia/Proyecto 1/Proyecto_1_Parqueo/NetBeans_Proyecto_1_Parqueo/src/main/java/GestorParqueo.java +/home/alberto/Documents/UNED/Prog. Intermedia/Proyecto 1/Proyecto_1_Parqueo/NetBeans_Proyecto_1_Parqueo/src/main/java/Vehiculo.java +/home/alberto/Documents/UNED/Prog. Intermedia/Proyecto 1/Proyecto_1_Parqueo/NetBeans_Proyecto_1_Parqueo/src/main/java/CalculoTarifa.java diff --git a/Proyecto_1_Parqueo/.gitignore b/Proyecto_1_Parqueo/.gitignore new file mode 100644 index 0000000..3aad8c5 --- /dev/null +++ b/Proyecto_1_Parqueo/.gitignore @@ -0,0 +1,10 @@ +# Compiled Java artifacts +bin/ +*.class + +# Editor settings +.vscode/ + +# OS-generated files +.DS_Store +Thumbs.db diff --git a/Proyecto_1_Parqueo/AGENTS.md b/Proyecto_1_Parqueo/AGENTS.md new file mode 100644 index 0000000..65c266a --- /dev/null +++ b/Proyecto_1_Parqueo/AGENTS.md @@ -0,0 +1,48 @@ +# Repository Guidelines + +## Project Structure & Module Organization +This repository is a small Java console application for parking management. + +- `src/`: Java source files (`Main.java`, `GestorParqueo.java`, `Vehiculo.java`). +- `bin/`: Compiled `.class` output (generated artifacts). +- `lib/`: External dependencies (currently unused, keep optional jars here). +- `.vscode/`: Local editor settings for VS Code Java workflows. + +Keep business logic in `GestorParqueo` and `Vehiculo`; keep CLI/menu flow in `Main`. + +## Build, Test, and Development Commands +Run commands from the repository root: + +- `javac -d bin src/*.java`: Compile all Java sources into `bin/`. +- `java -cp bin Main`: Run the console application. +- `rm -f bin/*.class`: Clean compiled artifacts for a fresh build. + +There is no Gradle/Maven wrapper configured yet, so use `javac`/`java` directly. + +## Coding Style & Naming Conventions +- Use 4-space indentation and UTF-8 encoding. +- Class names: `PascalCase` (for example, `GestorParqueo`). +- Methods/variables: `camelCase` (for example, `registrarVehiculo`). +- Constants: `UPPER_SNAKE_CASE` (for example, `MAX_VEHICULOS`). +- Keep methods focused; validate input close to where it is read. + +Prefer clear Spanish domain names consistent with current code (`placa`, `horaEntrada`, etc.). + +## Testing Guidelines +Automated tests are not present yet. Add tests before extending core behavior. + +- Suggested location: `test/` (mirror `src/` class names). +- Suggested framework: JUnit 5. +- Naming pattern: `ClassNameTest` and descriptive methods such as `registrarVehiculo_rechazaPlacaDuplicada`. +- Minimum expectation for changes: cover happy path plus at least one invalid-input case. + +Until tests are added, manually validate by compiling and running menu flows from `Main`. + +## Commit & Pull Request Guidelines +Git history is not available in this workspace, so use this convention: + +- Commit format: `type(scope): short imperative summary` + Example: `fix(main): validate integer menu option`. +- Keep commits small and single-purpose. +- PRs should include: objective, changed files, manual test steps, and console output/screenshots for UI/menu behavior. +- Link related issue/task IDs when available. diff --git a/Proyecto_1_Parqueo/README.md b/Proyecto_1_Parqueo/README.md new file mode 100644 index 0000000..7c03a53 --- /dev/null +++ b/Proyecto_1_Parqueo/README.md @@ -0,0 +1,18 @@ +## Getting Started + +Welcome to the VS Code Java world. Here is a guideline to help you get started to write Java code in Visual Studio Code. + +## Folder Structure + +The workspace contains two folders by default, where: + +- `src`: the folder to maintain sources +- `lib`: the folder to maintain dependencies + +Meanwhile, the compiled output files will be generated in the `bin` folder by default. + +> If you want to customize the folder structure, open `.vscode/settings.json` and update the related settings there. + +## Dependency Management + +The `JAVA PROJECTS` view allows you to manage your dependencies. More details can be found [here](https://github.com/microsoft/vscode-java-dependency#manage-dependencies). diff --git a/Proyecto_1_Parqueo/src/CalculoTarifa.java b/Proyecto_1_Parqueo/src/CalculoTarifa.java new file mode 100644 index 0000000..df07fbb --- /dev/null +++ b/Proyecto_1_Parqueo/src/CalculoTarifa.java @@ -0,0 +1,119 @@ +import java.time.LocalDateTime; +import java.time.Duration; + +public class CalculoTarifa { + + //originalmente calculaba el monto total aquí y en Main, pero codex sugirió mantener cálculos fuera de main. El prompt fué: "Remove the duplicate and adjust the text." + public static class DetalleCobro { + private long minutos; + private int tarifaAplicada; + private long unidCobro; + private int subtotal; + private int descuento; + private int total; + + public DetalleCobro(long minutos, int tarifaAplicada, long unidCobro, int subtotal, int descuento, int total) { + this.minutos = minutos; + this.tarifaAplicada = tarifaAplicada; + this.unidCobro = unidCobro; + this.subtotal = subtotal; + this.descuento = descuento; + this.total = total; + } + + public long getMinutos() { + return minutos; + } + + public int getTarifaAplicada() { + return tarifaAplicada; + } + + public long getUnidCobro() { + return unidCobro; + } + + public int getSubtotal() { + return subtotal; + } + + public int getDescuento() { + return descuento; + } + + public int getTotal() { + return total; + } + } + + public int calcularMonto(TiqueteParqueo t) { + DetalleCobro detalle = calcularDetalle(t); + t.setMontoTotal(detalle.getTotal()); + return detalle.getTotal(); + } + + public DetalleCobro calcularDetalle(TiqueteParqueo t) { + long minutos = calcularMinCobro(t); + int tarifa = obtenerTarifa(t); + long unidades = getUnidadCobro(minutos, t.getModalidad()); + int subtotal = (int) (unidades * tarifa); + int descuento = calcularDescuento(t.getModalidad(), unidades, subtotal); + int total = subtotal - descuento; + return new DetalleCobro(minutos, tarifa, unidades, subtotal, descuento, total); + } + + // Obtiene la tarifa segun tipo (1=Auto, 2=Moto, 3=Camion) + private int obtenerTarifa(TiqueteParqueo t) { + + TiqueteParqueo.TipoServicio modalidad = t.getModalidad(); + int tipo = t.getVehiculo().getTipo(); + + if (modalidad == TiqueteParqueo.TipoServicio.POR_HORA) { + if (tipo == 2) { + return 500; + } else if (tipo == 1 || tipo == 3) { + return 600; + } + } + + if (modalidad == TiqueteParqueo.TipoServicio.POR_DIA) { + if (tipo == 2) { + return 3000; + } else if (tipo == 1 || tipo == 3) { + return 5000; + } + } + + throw new IllegalArgumentException("Tipo de vehículo o modalidad inválidos."); + } + + private long calcularMinCobro(TiqueteParqueo t) { + LocalDateTime horaEntrada = t.getHoraEntrada(); + LocalDateTime horaSalida = t.getHoraSalida(); + + if (horaSalida.isBefore(horaEntrada)) { //excepción recomendada por codex + throw new IllegalArgumentException("La hora de salida no puede ser anterior a la hora de entrada."); + } + + long minutos = Duration.between(horaEntrada, horaSalida).toMinutes(); + if (minutos == 0) { + return 1; + } + return minutos; + } + + private long getUnidadCobro(long minutos, TiqueteParqueo.TipoServicio modalidad) { + if (modalidad == TiqueteParqueo.TipoServicio.POR_HORA) { + return (minutos + 59) / 60; + } + return (minutos + 1439) / 1440; + } + + private int calcularDescuento(TiqueteParqueo.TipoServicio modalidad, long unidades, int subtotal) { + if (modalidad == TiqueteParqueo.TipoServicio.POR_HORA && unidades > 8) { + return subtotal * 10 / 100; + } + return 0; + } + +} diff --git a/Proyecto_1_Parqueo/src/GestorParqueo.java b/Proyecto_1_Parqueo/src/GestorParqueo.java new file mode 100644 index 0000000..be68a0d --- /dev/null +++ b/Proyecto_1_Parqueo/src/GestorParqueo.java @@ -0,0 +1,94 @@ +import java.util.ArrayList; +import java.time.LocalDate; + +public class GestorParqueo { + + private static final int MAX_VEHICULOS = 10; + + private ArrayList vehiculosParqueados; + private ArrayList tiquetes; + + public GestorParqueo() { + + this.vehiculosParqueados = new ArrayList(); + this.tiquetes = new ArrayList(); + + } + + public boolean registrarIngreso(TiqueteParqueo nuevoTiquete) { + if (this.vehiculosParqueados.size() < MAX_VEHICULOS + && !existePlaca(nuevoTiquete.getVehiculo().getPlaca())) { + this.vehiculosParqueados.add(nuevoTiquete.getVehiculo()); + this.tiquetes.add(nuevoTiquete); + return true; + } + if (this.vehiculosParqueados.size() > 4){ + System.out.println("Aviso: quedan " + espaciosDisponibles() + "espacios disponibles."); + } + return false; + } + + public boolean existePlaca(String placa) { + for (Vehiculo vehiculo : this.vehiculosParqueados) { + if (vehiculo.getPlaca().equals(placa)) { + return true; + } + } + return false; + } + + public int espaciosDisponibles() { + return MAX_VEHICULOS - this.vehiculosParqueados.size(); + } + + public int getCapacidadMaxima() { + return MAX_VEHICULOS; + } + + public boolean estaVacio() { + return this.vehiculosParqueados.isEmpty(); + } + + public TiqueteParqueo buscarTiqueteAbierto(String placa) { + for (TiqueteParqueo tiquete : this.tiquetes) { + if (tiquete.getVehiculo().getPlaca().equals(placa) && tiquete.getHoraSalida() == null) { + return tiquete; + } + } + return null; + } + + public boolean registrarSalida(String placa) { + boolean vehiculoEliminado = false; + for (int i = 0; i < this.vehiculosParqueados.size(); i++) { + if (this.vehiculosParqueados.get(i).getPlaca().equals(placa)) { + this.vehiculosParqueados.remove(i); + vehiculoEliminado = true; + break; + } + } + + return vehiculoEliminado; + } + + public Vehiculo buscarPlaca(String placa) { + for (Vehiculo vehiculo : this.vehiculosParqueados) { + if (vehiculo.getPlaca().equals(placa)) { + return vehiculo; + } + } + return null; + } + + public ArrayList getTiquetesDia(LocalDate fecha) { + ArrayList resultado = new ArrayList(); + for (TiqueteParqueo tiquete : this.tiquetes) { + if (tiquete.getHoraEntrada() != null + && tiquete.getHoraEntrada().toLocalDate().equals(fecha)) { + resultado.add(tiquete); + } + } + return resultado; + } + +} diff --git a/Proyecto_1_Parqueo/src/Main.java b/Proyecto_1_Parqueo/src/Main.java new file mode 100644 index 0000000..ca1d64f --- /dev/null +++ b/Proyecto_1_Parqueo/src/Main.java @@ -0,0 +1,282 @@ +/* +UNIVERSIDAD ESTATAL A DISTANCIA +ESCUELAS DE CIENCIAS EXACTAS Y NATURALES +CATEDRA TECNOLOGÍA DE SISTEMAS + +ANDRES ALBERTO SANCHEZ TREJOS +GRUPO 09 +TUTOR: HERSANN FONSECA QUIRÓS +PROGRAMACION INTERMEDIA 00824 +Proyecto #1 +IC2026 + + +Bibliografía +Deitel, P.J.D. H. (2021). Cómo Programar En Java. Pearson HispanoAmerica Contenido. https://bookshelf.vitalsource.com/books/9786073255400 +https://www.w3schools.com/java/ +CODEX: se usó para generalmente para revisar la eficacia de las cláses y métodos. +El prompt generalmente utilizado fue "revisa esta método/función" o fué utilizado . + +*/ + +import java.util.Scanner; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class Main { + + private static final DateTimeFormatter fechaHora = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"); + + public static void main(String[] args) throws Exception { + GestorParqueo gestorParqueo = new GestorParqueo(); + + Scanner entrada = new Scanner(System.in); + int opcion = 0; + + System.out.println("================================="); + System.out.println("Bienvenido al sistema de parqueo"); + System.out.println("================================="); + LocalDate fechaAc = LocalDate.now(); + System.out.println("Fecha actual: " + fechaAc); + + while (opcion != 5) { + System.out.println("1. Registrar ingreso de vehículo"); + System.out.println("2. Registrar salida de vehículo"); + System.out.println("3. Consultar espacios disponibles"); + System.out.println("4. Ver reportes del día"); + System.out.println("5. Salir"); + System.out.println("Seleccione una opción:"); + opcion = intValida(entrada); + + switch (opcion) { + case 1: + TiqueteParqueo nuevoTiquete = registrarIngreso(entrada, gestorParqueo); + if (nuevoTiquete != null) { + if (gestorParqueo.registrarIngreso(nuevoTiquete)) { + System.out.println("Ingreso registrado correctamente."); + System.out.println("Espacios disponible: " + gestorParqueo.espaciosDisponibles() + "/10"); + if (gestorParqueo.espaciosDisponibles() <= 5) { + System.err.println("Advertencia: Se ha alcanzado el 50% de capacidad máxima"); + } + if (gestorParqueo.espaciosDisponibles() == 10) { + System.out.println("Advertencia: Se ha alcanzado la capacidad máxima 10/10."); + } + } else { + System.out.println("No hay espacios disponibles."); + } + } + regresarMenuPrincipal(entrada); + break; + case 2: + if (!gestorParqueo.estaVacio()) { + registrarSalida(entrada, gestorParqueo); + } else { + System.out.println("No hay vehiculos registrados."); + } + regresarMenuPrincipal(entrada); + break; + case 3: + System.out.println("Espacios disponibles: " + gestorParqueo.espaciosDisponibles()); + regresarMenuPrincipal(entrada); + break; + case 4: + mostrarMenuReportes(entrada, gestorParqueo); + regresarMenuPrincipal(entrada); + break; + case 5: + System.out.println("Saliendo del sistema de parqueo."); + break; + default: + System.out.println("Opción inválida. Por favor, seleccione una opción válida."); + regresarMenuPrincipal(entrada); + break; + } + + } + + entrada.close(); + } + + private static TiqueteParqueo registrarIngreso(Scanner entrada, GestorParqueo gestorParqueo) { + String placa = placaValida(entrada); + if (gestorParqueo.existePlaca(placa)) { + System.out.println("La placa ingresada ya está registrada."); + return null; + } + + int tipo = -1; + boolean tipoValido = false; + while (!tipoValido) { + System.out.println("Ingrese el tipo de vehículo (1 para Automóvil, 2 para Motocicleta, 3 para Camión):"); + tipo = intValida(entrada); + if (tipo >= 1 && tipo <= 3) { + tipoValido = true; + } else { + System.out.println("Opción inválida. Por favor, seleccione una opción válida."); + } + } + + TiqueteParqueo.TipoServicio modalidad = setModalidad(entrada); + + try { + Vehiculo vehiculo = new Vehiculo(placa, tipo); + return new TiqueteParqueo(vehiculo, LocalDateTime.now(), modalidad); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + return null; + } + } + + private static void registrarSalida(Scanner entrada, GestorParqueo gestorParqueo) { + + String placa = placaValida(entrada); + TiqueteParqueo tiquete = gestorParqueo.buscarTiqueteAbierto(placa); + + if (tiquete == null) { + System.out.println("Placa no se encuentra registrada en el sistema."); + } else { + tiquete.setHoraSalida(LocalDateTime.now()); + CalculoTarifa calculadora = new CalculoTarifa(); + CalculoTarifa.DetalleCobro detalle = calculadora.calcularDetalle(tiquete); + int monto = detalle.getTotal(); + tiquete.setMontoTotal(monto); + gestorParqueo.registrarSalida(placa); + + String horaEntrada = tiquete.getHoraEntrada().format(fechaHora); + String horaSalida = tiquete.getHoraSalida().format(fechaHora); + double tiempoHoras = detalle.getMinutos() / 60.0; + + System.out.println("****************************************"); + System.out.println("RECIBO DE PARQUEO"); + System.out.println("****************************************"); + System.out.println("Placa: " + tiquete.getVehiculo().getPlaca()); + System.out.println("Tipo: " + tipoVehiculoTexto(tiquete.getVehiculo().getTipo())); + System.out.println("Tipo de servicio: " + tipoServicioTexto(tiquete.getModalidad())); + System.out.println("Hora de entrada: " + horaEntrada); + System.out.println("Hora de salida: " + horaSalida); + System.out.println("Tiempo de permanencia (horas): " + String.format("%.2f", tiempoHoras)); + if (tiquete.getModalidad() == TiqueteParqueo.TipoServicio.POR_HORA) { + System.out.println("Costo por hora: CRC " + detalle.getTarifaAplicada()); + } else { + System.out.println("Costo por hora: No aplica (servicio por día)"); + } + System.out.println("Subtotal: CRC " + detalle.getSubtotal()); + if (detalle.getDescuento() > 0) { + System.out.println("Descuento: CRC " + detalle.getDescuento()); + } else { + System.out.println("Descuento: No aplica"); + } + System.out.println("========================================"); + System.out.println("TOTAL A PAGAR: CRC " + monto); + System.out.println("========================================"); + System.out.println("Gracias por usar nuestros servicios"); + } + + } + + private static void mostrarMenuReportes(Scanner entrada, GestorParqueo gestorParqueo) { + ReporteParqueo reporteParqueo = new ReporteParqueo(); + int opcionReporte = 0; + + while (opcionReporte != 4) { + System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + System.out.println("+ Menú de reportes del día +"); + System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + System.out.println("1. Listado de vehículos"); + System.out.println("2. Total recaudado por tipo de servicio"); + System.out.println("3. Estadísticas básicas de uso del parqueo"); + System.out.println("4. Volver al menú principal"); + System.out.println("Seleccione una opción:"); + opcionReporte = intValida(entrada); + + switch (opcionReporte) { + case 1: + reporteParqueo.vehiculosDia(gestorParqueo, LocalDate.now()); + break; + case 2: + reporteParqueo.totalUtilServicio(gestorParqueo, LocalDate.now()); + break; + case 3: + reporteParqueo.estadisticasBasicas(gestorParqueo, LocalDate.now()); + break; + case 4: + System.out.println("Regresando al menú principal."); + break; + default: + System.out.println("Opción inválida. Por favor, seleccione una opción válida."); + break; + } + } + } + + // define el tipo de servicio (modalida por dia o por hora) + private static TiqueteParqueo.TipoServicio setModalidad(Scanner entrada) { + int modalidad = -1; + while (modalidad != 1 && modalidad != 2) { + System.out.println("Seleccione modalidad de cobro (1 por hora, 2 por día):"); + modalidad = intValida(entrada); + if (modalidad != 1 && modalidad != 2) { + System.out.println("Opción inválida. Por favor, seleccione una opción válida."); + } + } + + if (modalidad == 1) { + return TiqueteParqueo.TipoServicio.POR_HORA; + } + return TiqueteParqueo.TipoServicio.POR_DIA; + } + + private static int intValida(Scanner entrada) { + int opcion = -1; + try { + opcion = Integer.parseInt(entrada.nextLine().trim()); + } catch (NumberFormatException e) { + System.out.println("Error: Entrada inválida. Por favor, ingrese un número entero."); + } + return opcion; + } + + private static void regresarMenuPrincipal(Scanner entrada) { + System.out.println("Presione Enter para volver al menú principal..."); + entrada.nextLine(); + } + + private static String placaValida(Scanner entrada) { + String placa = ""; + boolean placaValida = false; + while (!placaValida) { + System.out.println("Ingrese la placa del vehículo (en formato ABC123):"); + placa = entrada.nextLine().trim().toUpperCase(); + if (placa.isEmpty()) { + System.out.println("La placa no puede estar vacía."); + } else if (!Vehiculo.esPlacaValida(placa)) { + System.out.println("Formato inválido. Use 3 letras y 3 números (ejemplo: ABC123)."); + } else { + placaValida = true; + } + } + return placa; + } + + private static String tipoVehiculoTexto(int tipo) { + if (tipo == 1) { + return "Automóvil"; + } + if (tipo == 2) { + return "Motocicleta"; + } + if (tipo == 3) { + return "Camión"; + } + return "Desconocido"; + } + + private static String tipoServicioTexto(TiqueteParqueo.TipoServicio modalidad) { + if (modalidad == TiqueteParqueo.TipoServicio.POR_HORA) { + return "Por hora"; + } + return "Por día"; + } + +} diff --git a/Proyecto_1_Parqueo/src/ReporteParqueo.java b/Proyecto_1_Parqueo/src/ReporteParqueo.java new file mode 100644 index 0000000..4e635bf --- /dev/null +++ b/Proyecto_1_Parqueo/src/ReporteParqueo.java @@ -0,0 +1,96 @@ +import java.time.LocalDate; +import java.time.Duration; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; + +public class ReporteParqueo { + + private static final DateTimeFormatter soloFecha = DateTimeFormatter.ofPattern("dd/MM/yyyy"); + + public void vehiculosDia(GestorParqueo gestorParqueo, LocalDate fecha) { + + ArrayList tiquetes = gestorParqueo.getTiquetesDia(fecha); + + String fechaFormateada = fecha.format(soloFecha); + + if (tiquetes.isEmpty()) { + System.out.println("No hay vehículos registrados para la fecha: " + fechaFormateada); + return; + } + + System.out.println("Vehículos que usaron el parqueo el día " + fechaFormateada + ":"); + for (TiqueteParqueo tiquete : tiquetes) { + + String placa = tiquete.getVehiculo().getPlaca(); + String tipo = tipoVehiculoTexto(tiquete.getVehiculo().getTipo()); + String entrada = tiquete.getHoraEntrada().format(soloFecha); + String salida = "Aún parqueado"; + if (tiquete.getHoraSalida() != null) { + salida = tiquete.getHoraSalida().format(soloFecha); + } + + System.out.println( + "Placa: " + placa + " | Tipo: " + tipo + " | Entrada: " + entrada + " | Salida: " + salida); + } + } + + public void totalUtilServicio(GestorParqueo gestorParqueo, LocalDate fecha) { + + ArrayList tiquetes = gestorParqueo.getTiquetesDia(fecha); + int totalPorHora = 0; + int totalPorDia = 0; + + for (TiqueteParqueo tiquete : tiquetes) { + if (tiquete.getHoraSalida() == null) { + continue; + } + + if (tiquete.getModalidad() == TiqueteParqueo.TipoServicio.POR_HORA) { + totalPorHora += tiquete.getMontoTotal(); + } else { + totalPorDia += tiquete.getMontoTotal(); + } + } + + String fechaFormateada = fecha.format(soloFecha); + System.out.println("Total recaudado por servicio el día " + fechaFormateada + ":"); + System.out.println("Servicio por hora: CRC " + totalPorHora); + System.out.println("Servicio por día: CRC " + totalPorDia); + } + + public void estadisticasBasicas(GestorParqueo gestorParqueo, LocalDate fecha) { + ArrayList tiquetes = gestorParqueo.getTiquetesDia(fecha); + int vehiculosAtendidos = tiquetes.size(); + long minutosTotales = 0; + + for (TiqueteParqueo tiquete : tiquetes) { + if (tiquete.getHoraSalida() != null) { + minutosTotales += Duration.between(tiquete.getHoraEntrada(), tiquete.getHoraSalida()).toMinutes(); + } + } + + double horasTotales = minutosTotales / 60.0; + int capacidad = gestorParqueo.getCapacidadMaxima(); + int ocupadosActuales = capacidad - gestorParqueo.espaciosDisponibles(); + double ocupacionActual = (ocupadosActuales * 100.0) / capacidad; + + String fechaFormateada = fecha.format(soloFecha); + System.out.println("Estadísticas básicas del día " + fechaFormateada + ":"); + System.out.println("Sumatoria de horas de uso: " + String.format("%.2f", horasTotales)); + System.out.println("Cantidad de vehículos atendidos: " + vehiculosAtendidos); + System.out.println("Porcentaje de ocupación actual: " + String.format("%.2f", ocupacionActual) + "%"); + } + + private String tipoVehiculoTexto(int tipo) { + if (tipo == 1) { + return "Automóvil"; + } + if (tipo == 2) { + return "Motocicleta"; + } + if (tipo == 3) { + return "Camión"; + } + return "Desconocido"; + } +} diff --git a/Proyecto_1_Parqueo/src/TiqueteParqueo.java b/Proyecto_1_Parqueo/src/TiqueteParqueo.java new file mode 100644 index 0000000..63a83a8 --- /dev/null +++ b/Proyecto_1_Parqueo/src/TiqueteParqueo.java @@ -0,0 +1,64 @@ +import java.time.LocalDateTime; + +public class TiqueteParqueo { + + //orginalmente dos constantes, CODEX sugirió usar enum + public enum TipoServicio { + POR_HORA, + POR_DIA + } + + private Vehiculo vehiculo; + private LocalDateTime horaEntrada; + private LocalDateTime horaSalida; + private TipoServicio modalidad; + private int montoTotal; + + public TiqueteParqueo(Vehiculo vehiculo, LocalDateTime horaEntrada, TipoServicio modalidad) { + this.vehiculo = vehiculo; + this.horaEntrada = horaEntrada; + this.modalidad = modalidad; + this.horaSalida = null; + this.montoTotal = 0; + } + + public Vehiculo getVehiculo() { + return vehiculo; + } + + public void setVehiculo(Vehiculo vehiculo) { + this.vehiculo = vehiculo; + } + + public LocalDateTime getHoraEntrada() { + return horaEntrada; + } + + public void setHoraEntrada(LocalDateTime horaEntrada) { + this.horaEntrada = horaEntrada; + } + + public LocalDateTime getHoraSalida() { + return horaSalida; + } + + public void setHoraSalida(LocalDateTime horaSalida) { + this.horaSalida = horaSalida; + } + + public TipoServicio getModalidad() { + return modalidad; + } + + public void setModalidad(TipoServicio modalidad) { + this.modalidad = modalidad; + } + + public int getMontoTotal() { + return montoTotal; + } + + public void setMontoTotal(int montoTotal) { + this.montoTotal = montoTotal; + } +} diff --git a/Proyecto_1_Parqueo/src/Vehiculo.java b/Proyecto_1_Parqueo/src/Vehiculo.java new file mode 100644 index 0000000..22abed8 --- /dev/null +++ b/Proyecto_1_Parqueo/src/Vehiculo.java @@ -0,0 +1,49 @@ +import java.util.regex.Pattern; + +public class Vehiculo { + + private static final int AUTOMOVIL = 1; // constante de clase + private static final int MOTOCICLETA = 2; + private static final int CAMION = 3; + + private String placa; + private int tipo; + + // Constructor + public Vehiculo(String placa, int tipo) { + setPlaca(placa); + setTipo(tipo); + } + + public String getPlaca() { + return placa; + } + + public void setPlaca(String placa) { + if (esPlacaValida(placa)) { + this.placa = placa; + } else { + throw new IllegalArgumentException("La placa debe tener el formato ABC123."); + } + } + + public static boolean esPlacaValida(String placa) { + return Pattern.matches("[A-Z]{3}\\d{3}", placa); + } + + public int getTipo() { + return tipo; + } + + public void setTipo(int tipo) { + if (tipo == AUTOMOVIL || tipo == MOTOCICLETA || tipo == CAMION) { + this.tipo = tipo; + } else { + throw new IllegalArgumentException( + "Nümero inválido. Digite 1 para automóvil, 2 para motocicleta o 3 para camión."); + } + } + +} + +