@icarusmx/creta 1.3.4 → 1.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/bin/creta.js +8 -1576
  2. package/codex-refactor.txt +13 -0
  3. package/lib/builders/LessonBuilder.js +228 -0
  4. package/lib/builders/MenuBuilder.js +154 -0
  5. package/lib/builders/ProjectBuilder.js +56 -0
  6. package/lib/cli/index.js +81 -0
  7. package/lib/commands/help.js +5 -0
  8. package/lib/constants/paths.js +9 -0
  9. package/lib/data/enunciados.js +44 -0
  10. package/lib/data/lessons/index.js +25 -0
  11. package/lib/data/lessons/lesson1-system-decomposition.js +312 -0
  12. package/lib/data/lessons/lesson2-object-requests.js +318 -0
  13. package/lib/data/lessons/lesson3-only-way.js +349 -0
  14. package/lib/data/lessons/lesson4-operation-signatures.js +332 -0
  15. package/lib/data/lessons/lesson5-interface-set.js +341 -0
  16. package/lib/data/lessons/lesson6-interface-design.js +407 -0
  17. package/lib/data/lessons/lesson7-object-definition.js +375 -0
  18. package/lib/data/lessons/sintaxis/terminal-basico.js +46 -0
  19. package/lib/data/menus.js +43 -0
  20. package/lib/data/messages.js +28 -0
  21. package/lib/executors/enunciados-executor.js +63 -0
  22. package/lib/executors/portfolio-executor.js +167 -0
  23. package/lib/executors/proyectos-executor.js +23 -0
  24. package/lib/executors/sintaxis-executor.js +7 -0
  25. package/lib/templates/LevelModifier.js +287 -0
  26. package/lib/utils/file-utils.js +18 -0
  27. package/lib/utils/input.js +15 -0
  28. package/lib/utils/output.js +4 -0
  29. package/package.json +4 -1
  30. package/refactor.txt +581 -0
  31. package/test/enunciados.test.js +72 -0
  32. package/lessons/lesson1-system-decomposition.js +0 -313
  33. package/lessons/lesson2-object-requests.js +0 -309
  34. package/lessons/lesson3-only-way.js +0 -324
  35. package/lessons/lesson4-operation-signatures.js +0 -319
  36. package/lessons/lesson5-interface-set.js +0 -326
  37. package/lessons/lesson6-interface-design.js +0 -391
  38. package/lessons/lesson7-object-definition.js +0 -300
@@ -0,0 +1,312 @@
1
+ export const LESSON_1_SYSTEM_DECOMPOSITION = {
2
+ id: 1,
3
+ title: 'LECCIÓN 1: La parte difícil del diseño orientado a objetos es descomponer un sistema como un conjunto de objetos que interactúan entre sí',
4
+ subtitle: 'Enfoque práctico: Dos definiciones de sistema y su descomposición en objetos',
5
+ flow: [
6
+ {
7
+ message: '\nPresiona Enter para comenzar...',
8
+ type: 'pause'
9
+ },
10
+ {
11
+ type: 'clear'
12
+ },
13
+ {
14
+ lines: [
15
+ 'Comenzaremos con dos definiciones de sistema y posteriormente',
16
+ 'ejemplificaremos la descomposición en objetos.'
17
+ ],
18
+ type: 'text'
19
+ },
20
+ {
21
+ message: '\nPresiona Enter para continuar...',
22
+ type: 'pause'
23
+ },
24
+ {
25
+ type: 'clear'
26
+ },
27
+ {
28
+ lines: [
29
+ 'Definición 1:',
30
+ 'El sistema es una totalidad deductiva de discurso',
31
+ '\nDefinición 2:',
32
+ 'El sistema es un conjunto de cosas que relacionadas',
33
+ 'entre sí ordenadamente contribuyen a un determinado propósito'
34
+ ],
35
+ type: 'text'
36
+ },
37
+ {
38
+ message: '\nPresiona Enter para ver un ejemplo de sistema...',
39
+ type: 'pause'
40
+ },
41
+ {
42
+ type: 'clear'
43
+ },
44
+ {
45
+ lines: [
46
+ '🏛️ Ejemplo: Biblioteca Digital',
47
+ '========================================',
48
+ '\n📚 Definición 1 - Totalidad deductiva de discurso:',
49
+ "Partiendo de 'Biblioteca Digital', ¿qué se deduce naturalmente?"
50
+ ],
51
+ type: 'text'
52
+ },
53
+ {
54
+ message: '\nPresiona Enter para ver la primera deducción...',
55
+ type: 'pause'
56
+ },
57
+ {
58
+ lines: [
59
+ '\n🔍 Primera deducción:',
60
+ "• De 'Biblioteca' → contiene LIBROS",
61
+ "• De 'Digital' → acceso remoto por USUARIOS"
62
+ ],
63
+ type: 'text'
64
+ },
65
+ {
66
+ message: '\nPresiona Enter para ver la deducción clave...',
67
+ type: 'pause'
68
+ },
69
+ {
70
+ lines: [
71
+ '\n⚡ Deducción clave:',
72
+ '• Libros + Usuarios → deben interactuar',
73
+ '• ¿Cómo? → préstamos, búsquedas, devoluciones',
74
+ "\n💡 Conclusión: De 'biblioteca digital' se deduce naturalmente",
75
+ ' un conjunto de libros y usuarios interactuando'
76
+ ],
77
+ type: 'text'
78
+ },
79
+ {
80
+ message: '\nPresiona Enter para la segunda definición...',
81
+ type: 'pause'
82
+ },
83
+ {
84
+ type: 'clear'
85
+ },
86
+ {
87
+ lines: [
88
+ '🎯 Definición 2 - Conjunto de cosas con propósito:',
89
+ '¿Qué elementos relacionados contribuyen al propósito?',
90
+ '\n📖 Elementos del sistema:',
91
+ '• Libros - recursos que se prestan',
92
+ '• Usuarios - quienes solicitan préstamos',
93
+ '• Préstamos - relación temporal entre libro y usuario',
94
+ '• Biblioteca - coordina todo el proceso',
95
+ '\n🎯 Propósito determinado:',
96
+ 'Facilitar el acceso organizado a recursos bibliográficos',
97
+ '\n🔗 Relaciones ordenadas:',
98
+ '• Usuario solicita → Biblioteca evalúa → Préstamo se crea',
99
+ '• Libro cambia estado → Usuario recibe acceso → Plazo se establece',
100
+ '• Vencimiento llega → Usuario devuelve → Libro se libera'
101
+ ],
102
+ type: 'text'
103
+ },
104
+ {
105
+ message: '\nPresiona Enter para ver la descomposición en objetos...',
106
+ type: 'pause'
107
+ },
108
+ {
109
+ type: 'clear'
110
+ },
111
+ {
112
+ lines: [
113
+ 'Descomposición en objetos:'
114
+ ],
115
+ type: 'text'
116
+ },
117
+ {
118
+ code: 'class Book {\n' +
119
+ ' constructor(title, author, isbn) {\n' +
120
+ ' this.title = title\n' +
121
+ ' this.author = author\n' +
122
+ ' this.isbn = isbn\n' +
123
+ ' this.isLoaned = false\n' +
124
+ ' }\n' +
125
+ '\n' +
126
+ ' isAvailable() {\n' +
127
+ ' return !this.isLoaned\n' +
128
+ ' }\n' +
129
+ '\n' +
130
+ ' markAsLoaned() {\n' +
131
+ ' this.isLoaned = true\n' +
132
+ ' }\n' +
133
+ '\n' +
134
+ ' markAsReturned() {\n' +
135
+ ' this.isLoaned = false\n' +
136
+ ' }\n' +
137
+ '}',
138
+ title: '📄 Clase Book',
139
+ type: 'code'
140
+ },
141
+ {
142
+ message: '\nPresiona Enter para ver User...',
143
+ type: 'pause'
144
+ },
145
+ {
146
+ code: 'class User {\n' +
147
+ ' constructor(name, email, maxLoans = 3) {\n' +
148
+ ' this.name = name\n' +
149
+ ' this.email = email\n' +
150
+ ' this.maxLoans = maxLoans\n' +
151
+ ' this.currentLoans = []\n' +
152
+ ' }\n' +
153
+ '\n' +
154
+ ' canBorrow() {\n' +
155
+ ' return this.currentLoans.length < this.maxLoans\n' +
156
+ ' }\n' +
157
+ '\n' +
158
+ ' addLoan(loan) {\n' +
159
+ ' this.currentLoans.push(loan)\n' +
160
+ ' }\n' +
161
+ '\n' +
162
+ ' removeLoan(loan) {\n' +
163
+ ' const index = this.currentLoans.indexOf(loan)\n' +
164
+ ' if (index > -1) this.currentLoans.splice(index, 1)\n' +
165
+ ' }\n' +
166
+ '}',
167
+ title: '📄 Clase User',
168
+ type: 'code'
169
+ },
170
+ {
171
+ message: '\nPresiona Enter para ver Loan...',
172
+ type: 'pause'
173
+ },
174
+ {
175
+ code: 'class Loan {\n' +
176
+ ' constructor(user, book, durationDays = 14) {\n' +
177
+ ' this.user = user\n' +
178
+ ' this.book = book\n' +
179
+ ' this.startDate = new Date()\n' +
180
+ ' this.dueDate = new Date(Date.now() + durationDays * 24 * 60 * 60 * 1000)\n' +
181
+ ' this.returned = false\n' +
182
+ ' }\n' +
183
+ '\n' +
184
+ ' isOverdue() {\n' +
185
+ ' return !this.returned && new Date() > this.dueDate\n' +
186
+ ' }\n' +
187
+ '\n' +
188
+ ' calculateFine() {\n' +
189
+ ' if (!this.isOverdue()) return 0\n' +
190
+ ' const daysLate = Math.ceil((new Date() - this.dueDate) / (24 * 60 * 60 * 1000))\n' +
191
+ ' return daysLate * 5 // $5 por día\n' +
192
+ ' }\n' +
193
+ '\n' +
194
+ ' returnBook() {\n' +
195
+ ' this.returned = true\n' +
196
+ ' this.book.markAsReturned()\n' +
197
+ ' this.user.removeLoan(this)\n' +
198
+ ' }\n' +
199
+ '}',
200
+ title: '📄 Clase Loan',
201
+ type: 'code'
202
+ },
203
+ {
204
+ message: '\nPresiona Enter para ver Library...',
205
+ type: 'pause'
206
+ },
207
+ {
208
+ lines: [
209
+ '\nclass Library {',
210
+ ' constructor() {',
211
+ ' this.books = []',
212
+ ' this.users = []',
213
+ ' this.loans = []',
214
+ ' }',
215
+ '',
216
+ ' lendBook(user, book) {',
217
+ ' if (!user.canBorrow()) return null',
218
+ ' if (!book.isAvailable()) return null',
219
+ '',
220
+ ' const loan = new Loan(user, book)',
221
+ ' book.markAsLoaned()',
222
+ ' user.addLoan(loan)',
223
+ ' this.loans.push(loan)',
224
+ ' return loan',
225
+ ' }',
226
+ '',
227
+ ' returnBook(loan) {',
228
+ ' loan.returnBook()',
229
+ ' return loan.calculateFine()',
230
+ ' }',
231
+ '',
232
+ ' getOverdueLoans() {',
233
+ ' return this.loans.filter(loan => loan.isOverdue())',
234
+ ' }',
235
+ '}'
236
+ ],
237
+ type: 'text'
238
+ },
239
+ {
240
+ message: '\nPresiona Enter para ver la interacción...',
241
+ type: 'pause'
242
+ },
243
+ {
244
+ type: 'clear'
245
+ },
246
+ {
247
+ lines: [
248
+ 'Ejemplo de uso:',
249
+ '',
250
+ 'const library = new Library()',
251
+ "const book = new Book('1984', 'George Orwell', '978-0451524935')",
252
+ "const user = new User('Ana García', 'ana@email.com')",
253
+ '',
254
+ '// Los objetos interactúan entre sí',
255
+ 'const loan = library.lendBook(user, book)',
256
+ 'console.log(book.isAvailable()) // false',
257
+ 'console.log(user.canBorrow()) // true (2 préstamos disponibles)',
258
+ '',
259
+ '// Simular libro vencido',
260
+ 'loan.dueDate = new Date(Date.now() - 24 * 60 * 60 * 1000)',
261
+ 'console.log(loan.isOverdue()) // true',
262
+ 'console.log(loan.calculateFine()) // 5',
263
+ '',
264
+ '// Devolver libro',
265
+ 'const fine = library.returnBook(loan)',
266
+ 'console.log(book.isAvailable()) // true'
267
+ ],
268
+ type: 'text'
269
+ },
270
+ {
271
+ message: '\nPresiona Enter para la conclusión...',
272
+ type: 'pause'
273
+ },
274
+ {
275
+ type: 'clear'
276
+ },
277
+ {
278
+ lines: [
279
+ '🎓 Conclusión: La Descomposición de Sistemas',
280
+ '==================================================',
281
+ '🎯 Hemos demostrado que:',
282
+ '\n1️⃣ Sistema como totalidad deductiva:',
283
+ " • De 'biblioteca digital' se deduce naturalmente: libros + usuarios",
284
+ ' • Esta deducción revela la interacción fundamental del sistema',
285
+ '\n2️⃣ Sistema como conjunto con propósito:',
286
+ ' • Elementos identificados: Book, User, Loan, Library',
287
+ ' • Relaciones ordenadas: solicitud → evaluación → préstamo → devolución',
288
+ ' • Propósito determinado: acceso organizado a recursos',
289
+ '\n⚡ La parte difícil:',
290
+ '¿Cómo decidimos que necesitábamos exactamente estos 4 objetos?',
291
+ '¿Por qué no 3? ¿Por qué no 10? ¿Cuál es el criterio?',
292
+ '\n🔍 Criterio de descomposición:',
293
+ '• Book - responsabilidad de estado propio',
294
+ '• User - responsabilidad de sus límites',
295
+ '• Loan - responsabilidad de la relación temporal',
296
+ '• Library - responsabilidad de coordinación',
297
+ '\n📚 Conexión con lecciones siguientes:',
298
+ '• Lección 2: Los objetos interactúan a través de solicitudes',
299
+ '• Lección 3: Las solicitudes son la única forma de ejecutar operaciones',
300
+ '• Lección 4-6: Cómo definir esas interacciones correctamente',
301
+ '\n💭 Reflexión:',
302
+ 'La descomposición en objetos es difícil porque requiere identificar',
303
+ 'las responsabilidades naturales que se deducen del sistema.'
304
+ ],
305
+ type: 'text'
306
+ },
307
+ {
308
+ message: '\n✨ ¡Lección 1 completada! Presiona Enter para continuar...',
309
+ type: 'pause'
310
+ }
311
+ ]
312
+ }
@@ -0,0 +1,318 @@
1
+ export const LESSON_2_OBJECT_REQUESTS = {
2
+ id: 2,
3
+ title: 'LECCIÓN 2: Los objetos interactúan entre sí a través de solicitudes',
4
+ subtitle: 'Enfoque práctico: Demostrar cómo los objetos se comunican sin acceder directamente a datos internos',
5
+ flow: [
6
+ {
7
+ lines: [
8
+ '\n💡 ¿Qué significa esto exactamente?',
9
+ '- Los objetos NO acceden directamente a los datos de otros objetos',
10
+ '- En lugar de eso, hacen SOLICITUDES específicas',
11
+ '- Cada solicitud tiene un propósito claro y definido'
12
+ ],
13
+ type: 'text'
14
+ },
15
+ {
16
+ message: '\nPresiona Enter para comenzar el ejercicio práctico...',
17
+ type: 'pause'
18
+ },
19
+ {
20
+ type: 'clear'
21
+ },
22
+ {
23
+ lines: [
24
+ '🛠️ EJERCICIO PRÁCTICO: Sistema de Mensajería',
25
+ '==================================================',
26
+ '🎯 Vamos a ver cómo los objetos se solicitan información sin acceso directo',
27
+ '\nSistema: Chat entre usuarios',
28
+ 'Objetos: User, Message, ChatRoom'
29
+ ],
30
+ type: 'text'
31
+ },
32
+ {
33
+ message: '\nPresiona Enter para ver el ANTI-PATRÓN...',
34
+ type: 'pause'
35
+ },
36
+ {
37
+ type: 'clear'
38
+ },
39
+ {
40
+ lines: [
41
+ '❌ ANTI-PATRÓN: Acceso Directo (INCORRECTO)',
42
+ '=============================================',
43
+ 'Veamos qué NO debemos hacer:',
44
+ '\n// ❌ MALO: Acceso directo a datos internos',
45
+ 'class ChatRoom {\n' +
46
+ ' addMessage(user, text) {\n' +
47
+ ' // ❌ Accediendo directamente a user.name\n' +
48
+ ' if (user.name && user.name.length > 0) {\n' +
49
+ ' // ❌ Accediendo directamente a user.isActive\n' +
50
+ ' if (user.isActive === true) {\n' +
51
+ ' const message = new Message(user.name, text)\n' +
52
+ ' this.messages.push(message)\n' +
53
+ ' }\n' +
54
+ ' }\n' +
55
+ ' }\n' +
56
+ '}',
57
+ '\n🚨 Problemas del acceso directo:',
58
+ '• ChatRoom conoce la estructura interna de User',
59
+ '• Si User cambia, ChatRoom se rompe',
60
+ '• No hay control sobre qué se accede',
61
+ '• Violación de encapsulación'
62
+ ],
63
+ type: 'text'
64
+ },
65
+ {
66
+ message: '\nPresiona Enter para ver la forma CORRECTA...',
67
+ type: 'pause'
68
+ },
69
+ {
70
+ type: 'clear'
71
+ },
72
+ {
73
+ lines: [
74
+ '✅ PATRÓN CORRECTO: Solicitudes (CORRECTO)',
75
+ '=============================================',
76
+ 'Ahora veamos cómo debe ser:',
77
+ '\n// ✅ BUENO: Comunicación a través de solicitudes',
78
+ 'class User {\n' +
79
+ ' constructor(name) {\n' +
80
+ ' this.#name = name\n' +
81
+ ' this.#isActive = true\n' +
82
+ ' }\n' +
83
+ '\n' +
84
+ ' // 🔑 SOLICITUD: getName()\n' +
85
+ ' getName() {\n' +
86
+ ' return this.#name\n' +
87
+ ' }\n' +
88
+ '\n' +
89
+ ' // 🔑 SOLICITUD: isCurrentlyActive()\n' +
90
+ ' isCurrentlyActive() {\n' +
91
+ ' return this.#isActive\n' +
92
+ ' }\n' +
93
+ '\n' +
94
+ ' // 🔑 SOLICITUD: canSendMessage()\n' +
95
+ ' canSendMessage() {\n' +
96
+ ' return this.#isActive && this.#name.length > 0\n' +
97
+ ' }\n' +
98
+ '}'
99
+ ],
100
+ type: 'text'
101
+ },
102
+ {
103
+ message: '\nPresiona Enter para ver cómo ChatRoom usa las solicitudes...',
104
+ type: 'pause'
105
+ },
106
+ {
107
+ lines: [
108
+ '\n// ✅ ChatRoom usa SOLICITUDES, no acceso directo',
109
+ 'class ChatRoom {\n' +
110
+ ' addMessage(user, text) {\n' +
111
+ ' // ✅ SOLICITUD: ¿puede enviar mensajes?\n' +
112
+ ' if (user.canSendMessage()) {\n' +
113
+ ' // ✅ SOLICITUD: dame tu nombre\n' +
114
+ ' const userName = user.getName()\n' +
115
+ ' const message = new Message(userName, text)\n' +
116
+ ' this.messages.push(message)\n' +
117
+ ' }\n' +
118
+ ' }\n' +
119
+ '\n' +
120
+ ' getActiveUsers() {\n' +
121
+ ' return this.users.filter(user =>\n' +
122
+ ' // ✅ SOLICITUD: ¿estás activo?\n' +
123
+ ' user.isCurrentlyActive()\n' +
124
+ ' )\n' +
125
+ ' }\n' +
126
+ '}',
127
+ '\n🌟 Beneficios de las solicitudes:',
128
+ '• ChatRoom no conoce la estructura interna de User',
129
+ '• User controla qué información expone',
130
+ '• Cambios internos en User no afectan ChatRoom',
131
+ '• Cada solicitud tiene un propósito específico'
132
+ ],
133
+ type: 'text'
134
+ },
135
+ {
136
+ message: '\nPresiona Enter para ver tipos de solicitudes...',
137
+ type: 'pause'
138
+ },
139
+ {
140
+ type: 'clear'
141
+ },
142
+ {
143
+ lines: [
144
+ '🔍 TIPOS DE SOLICITUDES',
145
+ '==============================',
146
+ 'Las solicitudes pueden ser de diferentes tipos:',
147
+ '\n1️⃣ SOLICITUDES DE CONSULTA (Query)',
148
+ ' • user.getName() → devuelve información',
149
+ ' • user.isCurrentlyActive() → devuelve estado',
150
+ ' • message.getTimestamp() → devuelve dato',
151
+ '\n2️⃣ SOLICITUDES DE ACCIÓN (Command)',
152
+ ' • user.setActive(false) → cambia estado',
153
+ ' • message.markAsRead() → ejecuta acción',
154
+ ' • chatRoom.addUser(user) → modifica colección',
155
+ '\n3️⃣ SOLICITUDES DE VALIDACIÓN (Validation)',
156
+ ' • user.canSendMessage() → verifica capacidad',
157
+ ' • message.isValid() → verifica integridad',
158
+ ' • chatRoom.hasPermission(user) → verifica acceso'
159
+ ],
160
+ type: 'text'
161
+ },
162
+ {
163
+ message: '\nPresiona Enter para ver una interacción compleja...',
164
+ type: 'pause'
165
+ },
166
+ {
167
+ type: 'clear'
168
+ },
169
+ {
170
+ lines: [
171
+ '💬 EJEMPLO: Enviar mensaje con validaciones',
172
+ '=============================================',
173
+ '\n// Los objetos colaboran solo a través de solicitudes',
174
+ 'function sendMessage(chatRoom, user, text) {\n' +
175
+ ' // 🔍 SOLICITUD: ¿el usuario puede enviar?\n' +
176
+ ' if (!user.canSendMessage()) {\n' +
177
+ ' console.log("Usuario no puede enviar mensajes")\n' +
178
+ ' return false\n' +
179
+ ' }\n' +
180
+ '\n' +
181
+ ' // 🔍 SOLICITUD: ¿el usuario tiene permisos en este chat?\n' +
182
+ ' if (!chatRoom.hasPermission(user)) {\n' +
183
+ ' console.log("Sin permisos en este chat")\n' +
184
+ ' return false\n' +
185
+ ' }\n' +
186
+ '\n' +
187
+ ' // 🔍 SOLICITUD: ¿el texto es válido?\n' +
188
+ ' const message = new Message(user.getName(), text)\n' +
189
+ ' if (!message.isValid()) {\n' +
190
+ ' console.log("Mensaje inválido")\n' +
191
+ ' return false\n' +
192
+ ' }\n' +
193
+ '\n' +
194
+ ' // ⚡ SOLICITUD: agregar el mensaje\n' +
195
+ ' chatRoom.addMessage(user, text)\n' +
196
+ '\n' +
197
+ ' // 🔍 SOLICITUD: notificar a usuarios activos\n' +
198
+ ' const activeUsers = chatRoom.getActiveUsers()\n' +
199
+ ' activeUsers.forEach(activeUser => {\n' +
200
+ ' // 🔍 SOLICITUD: notificar\n' +
201
+ ' activeUser.notifyNewMessage(message)\n' +
202
+ ' })\n' +
203
+ '\n' +
204
+ ' return true\n' +
205
+ '}',
206
+ '\n🎯 Observa: En ningún momento accedemos directamente a',
207
+ ' user.#name, user.#isActive, chatRoom.#messages, etc.',
208
+ ' Todo pasa por SOLICITUDES específicas.'
209
+ ],
210
+ type: 'text'
211
+ },
212
+ {
213
+ message: '\nPresiona Enter para la demostración final...',
214
+ type: 'pause'
215
+ },
216
+ {
217
+ type: 'clear'
218
+ },
219
+ {
220
+ lines: [
221
+ '🎭 DEMOSTRACIÓN: Interacción Completa',
222
+ '========================================',
223
+ 'Veamos todos los objetos interactuando:',
224
+ '\n// Crear objetos',
225
+ "const chatRoom = new ChatRoom('Desarrollo')",
226
+ "const ana = new User('Ana')",
227
+ "const carlos = new User('Carlos')",
228
+ '',
229
+ '// Agregar usuarios al chat',
230
+ 'chatRoom.addUser(ana) // SOLICITUD',
231
+ 'chatRoom.addUser(carlos) // SOLICITUD',
232
+ '',
233
+ '// Ana envía mensaje',
234
+ "sendMessage(chatRoom, ana, 'Hola a todos!')",
235
+ '',
236
+ '// Secuencia de SOLICITUDES que se ejecutan:',
237
+ '// 1. ana.canSendMessage() → true',
238
+ '// 2. chatRoom.hasPermission(ana) → true',
239
+ "// 3. ana.getName() → 'Ana'",
240
+ '// 4. message.isValid() → true',
241
+ '// 5. chatRoom.addMessage(ana, text)',
242
+ '// 6. chatRoom.getActiveUsers() → [ana, carlos]',
243
+ '// 7. carlos.notifyNewMessage(message)',
244
+ '\n💡 Resultado:',
245
+ '✅ Ana: Mensaje enviado',
246
+ '📬 Carlos: Notificación recibida'
247
+ ],
248
+ type: 'text'
249
+ },
250
+ {
251
+ message: '\nPresiona Enter para ver qué pasa si Carlos se desconecta...',
252
+ type: 'pause'
253
+ },
254
+ {
255
+ lines: [
256
+ '\n// Carlos se desconecta',
257
+ 'carlos.setActive(false) // SOLICITUD',
258
+ '',
259
+ '// Ana envía otro mensaje',
260
+ "sendMessage(chatRoom, ana, 'Carlos, ¿estás ahí?')",
261
+ '',
262
+ '// Secuencia de SOLICITUDES:',
263
+ '// 1-5. Igual que antes...',
264
+ '// 6. chatRoom.getActiveUsers() → [ana] // ¡Carlos ya no aparece!',
265
+ '// 7. Solo ana.notifyNewMessage() se ejecuta',
266
+ '\n💡 Resultado:',
267
+ '✅ Ana: Mensaje enviado',
268
+ '😴 Carlos: No recibe notificación (está inactivo)',
269
+ '\n🎯 Observación clave:',
270
+ 'Los objetos cambian su comportamiento interno, pero las',
271
+ 'SOLICITUDES siguen siendo las mismas. La interacción es estable.'
272
+ ],
273
+ type: 'text'
274
+ },
275
+ {
276
+ message: '\nPresiona Enter para la conclusión...',
277
+ type: 'pause'
278
+ },
279
+ {
280
+ type: 'clear'
281
+ },
282
+ {
283
+ lines: [
284
+ '🎓 CONCLUSIÓN: Interacción a través de Solicitudes',
285
+ '==================================================',
286
+ '🎯 Hemos demostrado que:',
287
+ '\n1️⃣ Los objetos NUNCA acceden directamente a datos internos',
288
+ '2️⃣ Toda comunicación ocurre a través de SOLICITUDES específicas',
289
+ '3️⃣ Cada solicitud tiene un propósito claro y definido',
290
+ '4️⃣ Los objetos controlan qué información exponen',
291
+ '\n🔑 Tipos de solicitudes vistas:',
292
+ '• CONSULTA: getName(), isCurrentlyActive()',
293
+ '• ACCIÓN: setActive(), addMessage()',
294
+ '• VALIDACIÓN: canSendMessage(), hasPermission()',
295
+ '\n🌟 Beneficios fundamentales:',
296
+ '• Encapsulación preservada',
297
+ '• Flexibilidad para cambios internos',
298
+ '• Interacciones estables y predecibles',
299
+ '• Control total sobre el acceso a datos',
300
+ '\n📚 Conexión con otras lecciones:',
301
+ '• Lección 1: Los objetos que identificamos ahora interactúan',
302
+ '• Lección 3: Las solicitudes son la ÚNICA forma de ejecutar operaciones',
303
+ '• Lecciones 4-6: Cómo definir formalmente estas solicitudes',
304
+ '\n💭 Reflexión:',
305
+ '¿Te imaginas un mundo donde pudieras acceder directamente',
306
+ 'a la cuenta bancaria de cualquier persona? ¡Sería un caos!',
307
+ 'Los objetos funcionan igual: solicitudes controladas, acceso seguro.',
308
+ '\n🏆 Ahora entiendes por qué los objetos interactúan a través',
309
+ 'de solicitudes: es la base de la comunicación segura y ordenada.'
310
+ ],
311
+ type: 'text'
312
+ },
313
+ {
314
+ message: '\n✨ ¡Lección 2 completada! Presiona Enter para salir...',
315
+ type: 'pause'
316
+ }
317
+ ]
318
+ }