11package Colmena ;
2+
23import java .io .*;
34import java .util .List ;
45import java .util .Map ;
78import java .util .concurrent .locks .*;
89
910public class Utilidades {
11+ // Usamos un lock para evitar condiciones de carrera en las operaciones de entrada/salida
1012 private static final Lock inputLock = new ReentrantLock ();
13+
14+ // Método para imprimir texto con un retraso, simulando una escritura progresiva
1115 public static void printWithDelay (String text , int delayMs ) {
12- inputLock .lock ();
16+ inputLock .lock (); // Bloqueamos para garantizar que no haya acceso concurrente
1317 try {
18+ // Iteramos sobre cada carácter en el texto y lo imprimimos con un retraso
1419 for (char c : text .toCharArray ()) {
15- System .out .print (c );
20+ System .out .print (c ); // Imprimimos el carácter
1621 try {
17- Thread .sleep (delayMs );
22+ Thread .sleep (delayMs ); // Retraso entre caracteres
1823 } catch (InterruptedException ignored ) {
24+ // Si ocurre una interrupción, simplemente la ignoramos
1925 }
2026 }
21- System .out .println ();
27+ System .out .println (); // Nueva línea después de imprimir el texto
2228 } finally {
23- inputLock .unlock ();
29+ inputLock .unlock (); // Liberamos el lock
2430 }
2531 }
2632
33+ // Método que muestra una animación de abejas con un retraso dinámico basado en una función trigonométrica
2734 public static void animacionAbejas () {
28- inputLock .lock ();
35+ inputLock .lock (); // Lock para evitar acceso concurrente
2936 try {
3037 String [] frames = {
3138 " 🌺 " ,
@@ -34,23 +41,27 @@ public static void animacionAbejas() {
3441 " 🍯 " ,
3542 };
3643
44+ // Usamos una función matemática (seno) para alterar la velocidad de la animación
3745 for (int i = 0 ; i < 5 ; i ++) {
3846 for (String frame : frames ) {
39- System .out .print ("\r " + frame );
47+ // Calculamos un factor de tiempo basado en la función seno para crear una animación más dinámica
48+ double timeFactor = Math .sin (i + frame .length ()) * 150 + 150 ; // Ajuste dinámico del tiempo
49+ System .out .print ("\r " + frame ); // Sobrescribimos la línea para crear el efecto de animación
4050 try {
41- Thread .sleep (300 );
51+ Thread .sleep (( long ) timeFactor ); // Usamos el tiempo calculado para la espera
4252 } catch (InterruptedException ignored ) {
4353 }
4454 }
4555 }
4656 System .out .println ("\r 🐝 Las abejas están listas para trabajar.\n " );
4757 } finally {
48- inputLock .unlock ();
58+ inputLock .unlock (); // Liberamos el lock
4959 }
5060 }
5161
62+ // Método que muestra una animación de búsqueda con un retraso constante
5263 public static void animacionBusqueda () {
53- inputLock .lock ();
64+ inputLock .lock (); // Bloqueo para evitar acceso concurrente
5465 try {
5566 String [] frames = {
5667 " 🔍 " ,
@@ -59,123 +70,145 @@ public static void animacionBusqueda() {
5970 " 🔎 " ,
6071 };
6172
73+ // Animación simple de búsqueda con un tiempo constante entre cuadros
6274 for (int i = 0 ; i < 5 ; i ++) {
6375 for (String frame : frames ) {
64- System .out .print ("\r " + frame );
76+ System .out .print ("\r " + frame ); // Imprimimos el cuadro de animación
6577 try {
66- TimeUnit .MILLISECONDS .sleep (300 );
78+ TimeUnit .MILLISECONDS .sleep (300 ); // Espera constante de 300 ms
6779 } catch (InterruptedException ignored ) {}
6880 }
6981 }
7082 } finally {
71- inputLock .unlock ();
83+ inputLock .unlock (); // Liberamos el lock
7284 }
7385 }
7486
87+ // Método que obtiene una entrada válida del usuario, asegurándose de que coincida con un patrón regex
7588 public static String getValidInput (String prompt , String regex ) {
76- inputLock .lock ();
89+ inputLock .lock (); // Lock para asegurar que no haya condiciones de carrera en la entrada del usuario
7790 try {
78- Scanner scanner = new Scanner (System .in );
91+ Scanner scanner = new Scanner (System .in ); // Scanner para leer la entrada del usuario
7992 String input ;
8093 while (true ) {
81- System .out .print (prompt );
82- input = scanner .nextLine ().trim ();
94+ System .out .print (prompt ); // Pedimos la entrada
95+ input = scanner .nextLine ().trim (); // Limpiamos espacios al inicio y al final
8396
97+ // Normalizamos la entrada (capitalizamos la primera letra y convertimos el resto a minúsculas)
8498 if (!input .isEmpty ()) {
8599 input = input .substring (0 , 1 ).toUpperCase () + input .substring (1 ).toLowerCase ();
86100 }
87101
102+ // Verificamos si la entrada coincide con el patrón proporcionado
88103 if (input .matches (regex )) {
89- return input ;
104+ return input ; // Si es válida, la devolvemos
90105 }
91- System .out .println ("⚠️ Entrada inválida. Inténtalo de nuevo.\n " );
106+ System .out .println ("⚠️ Entrada inválida. Inténtalo de nuevo.\n " ); // Mensaje de error si la entrada es inválida
92107 }
93108 } finally {
94- inputLock .unlock ();
109+ inputLock .unlock (); // Liberamos el lock
95110 }
96111 }
97112
113+ // Método que ejecuta una tarea en un hilo separado y espera su finalización
98114 public static void runWithBlock (Runnable task ) {
99- Thread thread = new Thread (task );
100- thread .start ();
115+ Thread thread = new Thread (task ); // Creamos un nuevo hilo
116+ thread .start (); // Iniciamos el hilo
101117 try {
102- thread .join ();
118+ thread .join (); // Esperamos a que termine la ejecución del hilo
103119 } catch (InterruptedException ignored ) {
120+ // Si el hilo es interrumpido, simplemente lo ignoramos
104121 }
105122 }
106123
124+ // Método que verifica la integridad de los datos de las colmenas y apicultores
107125 public static void verificarDatos (List <Colmena > colmenas , List <Apicultor > apicultores , Map <String , Apicultor > asignaciones ) {
108126 Scanner scanner = new Scanner (System .in );
109127
110- runWithBlock (() -> printWithDelay ("🗃️ Verificando integridad de datos..." , 50 ));
111- animacionBusqueda ();
128+ runWithBlock (() -> printWithDelay ("🗃️ Verificando integridad de datos..." , 50 )); // Mensaje de verificación
129+ animacionBusqueda (); // Animación de búsqueda
130+
131+ // Validamos cada colmena
112132 for (Colmena colmena : colmenas ) {
133+ // Comprobamos que cada colmena tenga un ID válido
113134 if (colmena .id == null || !colmena .id .matches ("C\\ d{3}" )) {
114135 printWithDelay ("\r ⚠️ Falta el ID de una colmena. Proporcione un nuevo ID (formato CXXX): " , 50 );
115136 colmena .id = getValidInput ("ID: " , "C\\ d{3}" );
116137 }
138+ // Validamos la ubicación de la colmena
117139 if (colmena .ubicacion == null || colmena .ubicacion .isEmpty ()) {
118140 printWithDelay ("\r ⚠️ Falta la ubicación de la colmena con ID " + colmena .id + ". Proporcione una ubicación: " , 50 );
119141 colmena .ubicacion = scanner .nextLine ();
120142 }
143+ // Validamos el estado de salud de la colmena
121144 if (colmena .estadoSalud == null || !colmena .estadoSalud .matches ("Buena|Regular|Mala" )) {
122145 printWithDelay ("\r ⚠️ Falta el estado de salud de la colmena con ID " + colmena .id + ". Proporcione un estado (Buena/Regular/Mala): " , 50 );
123146 colmena .estadoSalud = getValidInput ("Estado de Salud: " , "Buena|Regular|Mala" );
124147 }
148+ // Si no hay apicultor asignado, asignamos uno
125149 if (!asignaciones .containsKey (colmena .id )) {
126150 printWithDelay ("\r ⚠️ No hay un apicultor asignado para la colmena con ID " + colmena .id + "." , 50 );
127151 printWithDelay ("\n 🧑🌾 Asignando un apicultor existente:\n " , 50 );
128152
153+ // Listamos apicultores disponibles para asignar
129154 for (int i = 0 ; i < apicultores .size (); i ++) {
130155 System .out .printf ("[%d] %s (Tel: %s)\n " , i + 1 , apicultores .get (i ).nombre , apicultores .get (i ).telefono );
131156 }
132157
133158 int opcion = Integer .parseInt (getValidInput ("\n Selecciona un apicultor por número: " , "\\ d+" )) - 1 ;
134159 if (opcion >= 0 && opcion < apicultores .size ()) {
135- asignaciones .put (colmena .id , apicultores .get (opcion ));
160+ asignaciones .put (colmena .id , apicultores .get (opcion )); // Asignamos el apicultor seleccionado
136161 printWithDelay ("\n ✅ Apicultor asignado correctamente.\n " , 50 );
137162 } else {
138163 printWithDelay ("⚠️ Opción no válida. Se omitió la asignación.\n " , 50 );
139164 }
140165 }
141166 }
142167
168+ // Validamos los datos de los apicultores
143169 for (Apicultor apicultor : apicultores ) {
170+ // Validamos el nombre del apicultor
144171 if (apicultor .nombre == null || apicultor .nombre .isEmpty ()) {
145172 printWithDelay ("\r ⚠️ Falta el nombre de un apicultor. Proporcione un nombre: " , 50 );
146173 apicultor .nombre = scanner .nextLine ();
147174 }
175+ // Validamos el teléfono del apicultor
148176 if (apicultor .telefono == null || !apicultor .telefono .matches ("\\ d{10}" )) {
149177 printWithDelay ("\r ⚠️ Falta el teléfono del apicultor " + apicultor .nombre + ". Proporcione un teléfono (10 dígitos): " , 50 );
150178
151179 String telefono = getValidInput ("Teléfono: " , "\\ d{10}" );
152180 boolean telefonoExistente = apicultores .stream ().anyMatch (a -> a .telefono != null && a .telefono .equals (telefono ));
153181
182+ // Verificamos si el teléfono ya está registrado por otro apicultor
154183 if (telefonoExistente ) {
155184 printWithDelay ("\n ⚠️ El teléfono " + telefono + " ya está registrado por otro apicultor. Intenta con otro número." , 50 );
156185 } else {
157- apicultor .telefono = telefono ;
186+ apicultor .telefono = telefono ; // Asignamos el teléfono
158187 }
159188 }
160189 }
161190
162- printWithDelay ("\r ✅ Verificación completa.\n " , 50 );
191+ printWithDelay ("\r ✅ Verificación completa.\n " , 50 ); // Mensaje de verificación completada
163192 }
164193
194+ // Método para cargar los datos desde un archivo serializado
165195 public static void cargarDatos (List <Colmena > colmenas , List <Apicultor > apicultores , Map <String , Apicultor > asignaciones , String dataFile ) throws IOException , ClassNotFoundException {
166196 try (ObjectInputStream ois = new ObjectInputStream (new FileInputStream (dataFile ))) {
197+ // Leemos el archivo serializado y extraemos los datos
167198 DatosApicola datos = (DatosApicola ) ois .readObject ();
168199 colmenas .addAll (datos .colmenas );
169200 apicultores .addAll (datos .apicultores );
170201 asignaciones .putAll (datos .asignaciones );
171- verificarDatos (colmenas , apicultores , asignaciones );
202+ verificarDatos (colmenas , apicultores , asignaciones ); // Verificamos los datos cargados
172203 }
173204 }
174205
206+ // Método para guardar los datos a un archivo serializado
175207 public static void guardarDatos (List <Colmena > colmenas , List <Apicultor > apicultores , Map <String , Apicultor > asignaciones , String dataFile ) throws IOException {
176208 try (ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream (dataFile ))) {
209+ // Guardamos los datos serializados en el archivo
177210 oos .writeObject (new DatosApicola (colmenas , apicultores , asignaciones ));
178- printWithDelay ("✅ Datos guardados correctamente.\n " , 50 );
211+ printWithDelay ("✅ Datos guardados correctamente.\n " , 50 ); // Confirmación de guardado
179212 }
180213 }
181214}
0 commit comments