@icarusmx/creta 1.0.22 → 1.1.0
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.
- package/.claude/settings.local.json +2 -1
- package/bin/creta.js +55 -10
- package/lessons/lesson7-object-definition.js +393 -0
- package/package.json +11 -3
package/bin/creta.js
CHANGED
|
@@ -12,6 +12,7 @@ import { Lesson3OnlyWay } from '../lessons/lesson3-only-way.js'
|
|
|
12
12
|
import { Lesson4OperationSignatures } from '../lessons/lesson4-operation-signatures.js'
|
|
13
13
|
import { Lesson5InterfaceSet } from '../lessons/lesson5-interface-set.js'
|
|
14
14
|
import { Lesson6InterfaceDesign } from '../lessons/lesson6-interface-design.js'
|
|
15
|
+
import { Lesson7ObjectDefinition } from '../lessons/lesson7-object-definition.js'
|
|
15
16
|
|
|
16
17
|
const ENUNCIADOS = [
|
|
17
18
|
{
|
|
@@ -49,6 +50,12 @@ const ENUNCIADOS = [
|
|
|
49
50
|
texto: "El énfasis al diseñar los objetos debe estar en la definición de sus solicitudes e interfaces.",
|
|
50
51
|
nivel: "Diseño",
|
|
51
52
|
enfoque: "Metodología de desarrollo"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 7,
|
|
56
|
+
texto: "Un objeto es un conjunto de datos y procedimientos que operan sobre esos datos.",
|
|
57
|
+
nivel: "Definición",
|
|
58
|
+
enfoque: "Naturaleza del objeto"
|
|
52
59
|
}
|
|
53
60
|
]
|
|
54
61
|
|
|
@@ -579,8 +586,8 @@ async function unstuckProject(level) {
|
|
|
579
586
|
|
|
580
587
|
function showHelp() {
|
|
581
588
|
console.log("\n📚 Comandos disponibles:")
|
|
582
|
-
console.log(" creta - Explora los
|
|
583
|
-
console.log(" creta enunciados - Explora los
|
|
589
|
+
console.log(" creta - Explora los 7 enunciados fundamentales (comando principal) 🧠")
|
|
590
|
+
console.log(" creta enunciados - Explora los 7 enunciados fundamentales 🧠")
|
|
584
591
|
console.log(" creta portafolio - Crea tu portafolio personal (reto completo)")
|
|
585
592
|
console.log(" creta portafolio-1 - Desbloquea nivel 1 (navbar) 🔓")
|
|
586
593
|
console.log(" creta portafolio-2 - Desbloquea nivel 2 (navbar + hero) 🔓")
|
|
@@ -767,7 +774,9 @@ async function startEnunciadosSelectorInteractive() {
|
|
|
767
774
|
throw new Error('setRawMode not available')
|
|
768
775
|
}
|
|
769
776
|
|
|
770
|
-
console.log("Los enunciados fundamentales son un conjunto de afirmaciones que tienen el propósito de ejercitar el pensamiento orientado a objetos de los estudiantes de Creta.
|
|
777
|
+
console.log("Los enunciados fundamentales son un conjunto de afirmaciones que tienen el propósito de ejercitar el pensamiento orientado a objetos de los estudiantes de Creta.")
|
|
778
|
+
console.log("")
|
|
779
|
+
console.log("Escogimos estos enunciados porque creemos que exhaustan los conceptos mínimos necesarios para entender el paradigma de la programación orientada a objetos.")
|
|
771
780
|
|
|
772
781
|
// Wait for user to press Enter before showing the list
|
|
773
782
|
const rl = createInterface({
|
|
@@ -803,7 +812,9 @@ async function startEnunciadosSelectorInteractive() {
|
|
|
803
812
|
process.stdout.write('\x1b[2J')
|
|
804
813
|
process.stdout.write('\x1b[H')
|
|
805
814
|
|
|
806
|
-
console.log("Los enunciados fundamentales son un conjunto de afirmaciones que tienen el propósito de ejercitar el pensamiento orientado a objetos de los estudiantes de Creta.
|
|
815
|
+
console.log("Los enunciados fundamentales son un conjunto de afirmaciones que tienen el propósito de ejercitar el pensamiento orientado a objetos de los estudiantes de Creta.")
|
|
816
|
+
console.log("")
|
|
817
|
+
console.log("Escogimos estos enunciados porque creemos que exhaustan los conceptos mínimos necesarios para entender el paradigma de la programación orientada a objetos.")
|
|
807
818
|
console.log("")
|
|
808
819
|
console.log("Elige qué enunciado te gustaría explorar:")
|
|
809
820
|
console.log("")
|
|
@@ -818,8 +829,8 @@ async function startEnunciadosSelectorInteractive() {
|
|
|
818
829
|
let formattedText = enunciado.texto
|
|
819
830
|
if (enunciado.id === 4) {
|
|
820
831
|
// Special formatting for enunciado 4 with list items
|
|
821
|
-
formattedText = formattedText.replace(/\n([abc])\)/g, '\n
|
|
822
|
-
formattedText = formattedText.replace(/\n\nEstos tres elementos/g, '\n\n
|
|
832
|
+
formattedText = formattedText.replace(/\n([abc])\)/g, '\n $1)')
|
|
833
|
+
formattedText = formattedText.replace(/\n\nEstos tres elementos/g, '\n\n Estos tres elementos')
|
|
823
834
|
}
|
|
824
835
|
console.log(`${highlight}${prefix}${index + 1}. ${formattedText}${reset}`)
|
|
825
836
|
console.log("")
|
|
@@ -961,6 +972,22 @@ async function startEnunciadosSelectorInteractive() {
|
|
|
961
972
|
console.log("- Proyectos específicos para internalizar la idea")
|
|
962
973
|
await returnToMainMenu()
|
|
963
974
|
}
|
|
975
|
+
} else if (enunciadoSeleccionado.id === 7) {
|
|
976
|
+
console.log(`${enunciadoSeleccionado.texto}`)
|
|
977
|
+
await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
|
|
978
|
+
|
|
979
|
+
try {
|
|
980
|
+
const lesson7 = new Lesson7ObjectDefinition()
|
|
981
|
+
await lesson7.start()
|
|
982
|
+
await returnToMainMenu()
|
|
983
|
+
} catch (error) {
|
|
984
|
+
console.error("\n❌ Error al ejecutar la lección:", error.message)
|
|
985
|
+
console.log("\n🚀 Próximamente:")
|
|
986
|
+
console.log("- Sesiones de estudio dirigidas basadas en este enunciado")
|
|
987
|
+
console.log("- Ejercicios prácticos que ilustren el concepto")
|
|
988
|
+
console.log("- Proyectos específicos para internalizar la idea")
|
|
989
|
+
await returnToMainMenu()
|
|
990
|
+
}
|
|
964
991
|
} else {
|
|
965
992
|
console.log("\n🚀 Próximamente:")
|
|
966
993
|
console.log("- Sesiones de estudio dirigidas basadas en este enunciado")
|
|
@@ -1002,7 +1029,9 @@ async function startEnunciadosSelectorFallback() {
|
|
|
1002
1029
|
}
|
|
1003
1030
|
|
|
1004
1031
|
try {
|
|
1005
|
-
console.log("Los enunciados fundamentales son un conjunto de afirmaciones que tienen el propósito de ejercitar el pensamiento orientado a objetos de los estudiantes de Creta.
|
|
1032
|
+
console.log("Los enunciados fundamentales son un conjunto de afirmaciones que tienen el propósito de ejercitar el pensamiento orientado a objetos de los estudiantes de Creta.")
|
|
1033
|
+
console.log("")
|
|
1034
|
+
console.log("Escogimos estos enunciados porque creemos que exhaustan los conceptos mínimos necesarios para entender el paradigma de la programación orientada a objetos.")
|
|
1006
1035
|
|
|
1007
1036
|
await askQuestion("\nPresiona Enter para comenzar...")
|
|
1008
1037
|
|
|
@@ -1022,7 +1051,7 @@ async function startEnunciadosSelectorFallback() {
|
|
|
1022
1051
|
console.log("")
|
|
1023
1052
|
})
|
|
1024
1053
|
|
|
1025
|
-
const respuesta = await askQuestion("Elige un número (1-
|
|
1054
|
+
const respuesta = await askQuestion("Elige un número (1-7) o 'q' para salir: ")
|
|
1026
1055
|
|
|
1027
1056
|
if (respuesta.toLowerCase() === 'q') {
|
|
1028
1057
|
console.log("¡Hasta la vista! 👋")
|
|
@@ -1032,7 +1061,7 @@ async function startEnunciadosSelectorFallback() {
|
|
|
1032
1061
|
|
|
1033
1062
|
const numeroSeleccionado = parseInt(respuesta)
|
|
1034
1063
|
|
|
1035
|
-
if (numeroSeleccionado >= 1 && numeroSeleccionado <=
|
|
1064
|
+
if (numeroSeleccionado >= 1 && numeroSeleccionado <= 7) {
|
|
1036
1065
|
const enunciadoSeleccionado = ENUNCIADOS[numeroSeleccionado - 1]
|
|
1037
1066
|
|
|
1038
1067
|
// Check if we have a lesson implementation for this enunciado
|
|
@@ -1148,6 +1177,22 @@ async function startEnunciadosSelectorFallback() {
|
|
|
1148
1177
|
console.log("- Proyectos específicos para internalizar la idea")
|
|
1149
1178
|
}
|
|
1150
1179
|
return
|
|
1180
|
+
} else if (enunciadoSeleccionado.id === 7) {
|
|
1181
|
+
console.log(`${enunciadoSeleccionado.texto}`)
|
|
1182
|
+
rl.close()
|
|
1183
|
+
await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
|
|
1184
|
+
|
|
1185
|
+
try {
|
|
1186
|
+
const lesson7 = new Lesson7ObjectDefinition()
|
|
1187
|
+
await lesson7.start()
|
|
1188
|
+
} catch (error) {
|
|
1189
|
+
console.error("\n❌ Error al ejecutar la lección:", error.message)
|
|
1190
|
+
console.log("\n🚀 Próximamente:")
|
|
1191
|
+
console.log("- Sesiones de estudio dirigidas basadas en este enunciado")
|
|
1192
|
+
console.log("- Ejercicios prácticos que ilustren el concepto")
|
|
1193
|
+
console.log("- Proyectos específicos para internalizar la idea")
|
|
1194
|
+
}
|
|
1195
|
+
return
|
|
1151
1196
|
} else {
|
|
1152
1197
|
console.log("\n🚀 Próximamente:")
|
|
1153
1198
|
console.log("- Sesiones de estudio dirigidas basadas en este enunciado")
|
|
@@ -1159,7 +1204,7 @@ async function startEnunciadosSelectorFallback() {
|
|
|
1159
1204
|
}
|
|
1160
1205
|
|
|
1161
1206
|
} else {
|
|
1162
|
-
console.log("❌ Opción no válida. Elige un número entre 1 y
|
|
1207
|
+
console.log("❌ Opción no válida. Elige un número entre 1 y 7.")
|
|
1163
1208
|
}
|
|
1164
1209
|
|
|
1165
1210
|
rl.close()
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// LECCIÓN 7: Un objeto es un conjunto de datos y procedimientos que operan sobre esos datos
|
|
4
|
+
// Enfoque práctico: Comparación entre código procedural vs orientado a objetos
|
|
5
|
+
|
|
6
|
+
import { createInterface } from 'readline'
|
|
7
|
+
|
|
8
|
+
export class Lesson7ObjectDefinition {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.rl = createInterface({
|
|
11
|
+
input: process.stdin,
|
|
12
|
+
output: process.stdout
|
|
13
|
+
})
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async start() {
|
|
17
|
+
await this.waitForEnter("\nPresiona Enter para comenzar...")
|
|
18
|
+
|
|
19
|
+
await this.practicalExercise()
|
|
20
|
+
await this.conclusion()
|
|
21
|
+
|
|
22
|
+
this.rl.close()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async practicalExercise() {
|
|
26
|
+
console.clear()
|
|
27
|
+
console.log("Exploraremos qué ES un objeto comparando dos enfoques:")
|
|
28
|
+
console.log("1. Datos separados + funciones sueltas")
|
|
29
|
+
console.log("2. Objeto = datos + procedimientos unidos")
|
|
30
|
+
|
|
31
|
+
await this.waitForEnter("\nPresiona Enter para continuar...")
|
|
32
|
+
|
|
33
|
+
await this.step1_ProceduralApproach()
|
|
34
|
+
await this.step2_ObjectOrientedApproach()
|
|
35
|
+
await this.step3_ComparisonAndBenefits()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async step1_ProceduralApproach() {
|
|
39
|
+
console.clear()
|
|
40
|
+
console.log("🔧 Enfoque Procedural: Datos Separados")
|
|
41
|
+
console.log("=" .repeat(50))
|
|
42
|
+
|
|
43
|
+
console.log("\n💳 Ejemplo: Sistema de Cuenta Bancaria")
|
|
44
|
+
console.log("\n📊 Datos sueltos:")
|
|
45
|
+
|
|
46
|
+
const dataCode = `// Datos de la cuenta
|
|
47
|
+
let accountNumber = "001-234567"
|
|
48
|
+
let ownerName = "María González"
|
|
49
|
+
let balance = 5000
|
|
50
|
+
let isActive = true`
|
|
51
|
+
|
|
52
|
+
this.printCodeWithColors("Variables globales", dataCode)
|
|
53
|
+
|
|
54
|
+
await this.waitForEnter("\nPresiona Enter para ver las funciones...")
|
|
55
|
+
|
|
56
|
+
console.log("\n⚙️ Funciones separadas que operan sobre esos datos:")
|
|
57
|
+
|
|
58
|
+
const functionsCode = `function deposit(amount) {
|
|
59
|
+
if (!isActive) {
|
|
60
|
+
console.log("Cuenta inactiva")
|
|
61
|
+
return false
|
|
62
|
+
}
|
|
63
|
+
if (amount <= 0) {
|
|
64
|
+
console.log("Cantidad inválida")
|
|
65
|
+
return false
|
|
66
|
+
}
|
|
67
|
+
balance += amount
|
|
68
|
+
return true
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function withdraw(amount) {
|
|
72
|
+
if (!isActive) return false
|
|
73
|
+
if (amount <= 0) return false
|
|
74
|
+
if (amount > balance) {
|
|
75
|
+
console.log("Fondos insuficientes")
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
balance -= amount
|
|
79
|
+
return true
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function getBalance() {
|
|
83
|
+
return isActive ? balance : 0
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function deactivate() {
|
|
87
|
+
isActive = false
|
|
88
|
+
}`
|
|
89
|
+
|
|
90
|
+
this.printCodeWithColors("Funciones sueltas", functionsCode)
|
|
91
|
+
|
|
92
|
+
await this.waitForEnter("\nPresiona Enter para ver el problema...")
|
|
93
|
+
|
|
94
|
+
console.clear()
|
|
95
|
+
console.log("❌ Problemas del enfoque procedural:")
|
|
96
|
+
console.log("=" .repeat(50))
|
|
97
|
+
|
|
98
|
+
console.log("\n1️⃣ Datos expuestos globalmente:")
|
|
99
|
+
console.log(" • Cualquier código puede modificar 'balance' directamente")
|
|
100
|
+
console.log(" • No hay protección de los datos")
|
|
101
|
+
|
|
102
|
+
console.log("\n2️⃣ Funciones no están vinculadas a datos:")
|
|
103
|
+
console.log(" • deposit() asume que 'balance' existe")
|
|
104
|
+
console.log(" • ¿Qué pasa si necesitamos múltiples cuentas?")
|
|
105
|
+
|
|
106
|
+
console.log("\n3️⃣ Difícil de escalar:")
|
|
107
|
+
|
|
108
|
+
const problemCode = `// ¿Cómo manejamos dos cuentas?
|
|
109
|
+
let balance1 = 5000
|
|
110
|
+
let balance2 = 3000
|
|
111
|
+
let accountNumber1 = "001"
|
|
112
|
+
let accountNumber2 = "002"
|
|
113
|
+
|
|
114
|
+
// Las funciones solo trabajan con una cuenta
|
|
115
|
+
deposit(100) // ¿A cuál cuenta?`
|
|
116
|
+
|
|
117
|
+
this.printCodeWithColors("Escalabilidad problemática", problemCode)
|
|
118
|
+
|
|
119
|
+
await this.waitForEnter("\nPresiona Enter para ver la solución...")
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async step2_ObjectOrientedApproach() {
|
|
123
|
+
console.clear()
|
|
124
|
+
console.log("✨ Enfoque Orientado a Objetos: Datos + Procedimientos")
|
|
125
|
+
console.log("=" .repeat(50))
|
|
126
|
+
|
|
127
|
+
console.log("\n💡 Un objeto AGRUPA datos y procedimientos")
|
|
128
|
+
console.log("Los datos se convierten en PROPIEDADES")
|
|
129
|
+
console.log("Los procedimientos se convierten en MÉTODOS")
|
|
130
|
+
|
|
131
|
+
await this.waitForEnter("\nPresiona Enter para ver el código...")
|
|
132
|
+
|
|
133
|
+
const objectCode = `class BankAccount {
|
|
134
|
+
// Constructor: inicializa los DATOS del objeto
|
|
135
|
+
constructor(accountNumber, ownerName, initialBalance) {
|
|
136
|
+
this.accountNumber = accountNumber
|
|
137
|
+
this.ownerName = ownerName
|
|
138
|
+
this.balance = initialBalance
|
|
139
|
+
this.isActive = true
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// PROCEDIMIENTOS que operan sobre ESTOS datos específicos
|
|
143
|
+
deposit(amount) {
|
|
144
|
+
if (!this.isActive) {
|
|
145
|
+
console.log("Cuenta inactiva")
|
|
146
|
+
return false
|
|
147
|
+
}
|
|
148
|
+
if (amount <= 0) {
|
|
149
|
+
console.log("Cantidad inválida")
|
|
150
|
+
return false
|
|
151
|
+
}
|
|
152
|
+
this.balance += amount
|
|
153
|
+
return true
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
withdraw(amount) {
|
|
157
|
+
if (!this.isActive) return false
|
|
158
|
+
if (amount <= 0) return false
|
|
159
|
+
if (amount > this.balance) {
|
|
160
|
+
console.log("Fondos insuficientes")
|
|
161
|
+
return false
|
|
162
|
+
}
|
|
163
|
+
this.balance -= amount
|
|
164
|
+
return true
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
getBalance() {
|
|
168
|
+
return this.isActive ? this.balance : 0
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
deactivate() {
|
|
172
|
+
this.isActive = false
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
getAccountInfo() {
|
|
176
|
+
return {
|
|
177
|
+
number: this.accountNumber,
|
|
178
|
+
owner: this.ownerName,
|
|
179
|
+
balance: this.getBalance(),
|
|
180
|
+
status: this.isActive ? 'Activa' : 'Inactiva'
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}`
|
|
184
|
+
|
|
185
|
+
this.printCodeWithColors("Clase BankAccount", objectCode)
|
|
186
|
+
|
|
187
|
+
await this.waitForEnter("\nPresiona Enter para ver múltiples instancias...")
|
|
188
|
+
|
|
189
|
+
console.clear()
|
|
190
|
+
console.log("🎯 Múltiples objetos = Múltiples conjuntos de datos")
|
|
191
|
+
console.log("=" .repeat(50))
|
|
192
|
+
|
|
193
|
+
const usageCode = `// Crear múltiples cuentas es simple
|
|
194
|
+
const account1 = new BankAccount("001-234567", "María González", 5000)
|
|
195
|
+
const account2 = new BankAccount("001-789012", "Juan Pérez", 3000)
|
|
196
|
+
|
|
197
|
+
// Cada objeto tiene SUS PROPIOS datos
|
|
198
|
+
account1.deposit(500)
|
|
199
|
+
account2.withdraw(200)
|
|
200
|
+
|
|
201
|
+
console.log(account1.getBalance()) // 5500
|
|
202
|
+
console.log(account2.getBalance()) // 2800
|
|
203
|
+
|
|
204
|
+
// Los procedimientos operan sobre los datos del objeto específico
|
|
205
|
+
account1.deactivate()
|
|
206
|
+
console.log(account1.isActive) // false
|
|
207
|
+
console.log(account2.isActive) // true ← No afectado`
|
|
208
|
+
|
|
209
|
+
this.printCodeWithColors("Uso del objeto", usageCode)
|
|
210
|
+
|
|
211
|
+
await this.waitForEnter("\nPresiona Enter para ver las ventajas...")
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async step3_ComparisonAndBenefits() {
|
|
215
|
+
console.clear()
|
|
216
|
+
console.log("📊 Comparación Directa")
|
|
217
|
+
console.log("=" .repeat(50))
|
|
218
|
+
|
|
219
|
+
console.log("\n🔴 Enfoque Procedural:")
|
|
220
|
+
console.log(" Datos: let balance = 5000")
|
|
221
|
+
console.log(" Procedimiento: function deposit(amount) { balance += amount }")
|
|
222
|
+
console.log(" ❌ Separados, sin relación formal")
|
|
223
|
+
|
|
224
|
+
console.log("\n🟢 Enfoque Orientado a Objetos:")
|
|
225
|
+
console.log(" Datos: this.balance = 5000")
|
|
226
|
+
console.log(" Procedimiento: deposit(amount) { this.balance += amount }")
|
|
227
|
+
console.log(" ✅ Unidos en el MISMO objeto")
|
|
228
|
+
|
|
229
|
+
await this.waitForEnter("\nPresiona Enter para ver ejemplo visual...")
|
|
230
|
+
|
|
231
|
+
console.clear()
|
|
232
|
+
console.log("🎨 Visualización del Concepto")
|
|
233
|
+
console.log("=" .repeat(50))
|
|
234
|
+
|
|
235
|
+
console.log("\n┌─────────────────────────────────────┐")
|
|
236
|
+
console.log("│ OBJETO: account1 │")
|
|
237
|
+
console.log("├─────────────────────────────────────┤")
|
|
238
|
+
console.log("│ DATOS: │")
|
|
239
|
+
console.log("│ • accountNumber = \"001-234567\" │")
|
|
240
|
+
console.log("│ • ownerName = \"María González\" │")
|
|
241
|
+
console.log("│ • balance = 5000 │")
|
|
242
|
+
console.log("│ • isActive = true │")
|
|
243
|
+
console.log("├─────────────────────────────────────┤")
|
|
244
|
+
console.log("│ PROCEDIMIENTOS: │")
|
|
245
|
+
console.log("│ • deposit(amount) │")
|
|
246
|
+
console.log("│ • withdraw(amount) │")
|
|
247
|
+
console.log("│ • getBalance() │")
|
|
248
|
+
console.log("│ • deactivate() │")
|
|
249
|
+
console.log("└─────────────────────────────────────┘")
|
|
250
|
+
|
|
251
|
+
console.log("\n📌 Nota clave:")
|
|
252
|
+
console.log("Los procedimientos SOLO operan sobre los datos de ESTE objeto")
|
|
253
|
+
console.log("account1.deposit() modifica account1.balance")
|
|
254
|
+
console.log("account2.deposit() modifica account2.balance")
|
|
255
|
+
|
|
256
|
+
await this.waitForEnter("\nPresiona Enter para ver otro ejemplo...")
|
|
257
|
+
|
|
258
|
+
console.clear()
|
|
259
|
+
console.log("🎮 Ejemplo 2: Sistema de Carrito de Compras")
|
|
260
|
+
console.log("=" .repeat(50))
|
|
261
|
+
|
|
262
|
+
const cartCode = `class ShoppingCart {
|
|
263
|
+
// DATOS del carrito
|
|
264
|
+
constructor(userId) {
|
|
265
|
+
this.userId = userId
|
|
266
|
+
this.items = []
|
|
267
|
+
this.totalAmount = 0
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// PROCEDIMIENTOS que operan sobre estos datos
|
|
271
|
+
addItem(product, quantity) {
|
|
272
|
+
const item = { product, quantity, price: product.price * quantity }
|
|
273
|
+
this.items.push(item)
|
|
274
|
+
this.totalAmount += item.price
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
removeItem(productId) {
|
|
278
|
+
const itemIndex = this.items.findIndex(i => i.product.id === productId)
|
|
279
|
+
if (itemIndex > -1) {
|
|
280
|
+
this.totalAmount -= this.items[itemIndex].price
|
|
281
|
+
this.items.splice(itemIndex, 1)
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
getTotal() {
|
|
286
|
+
return this.totalAmount
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
getItemCount() {
|
|
290
|
+
return this.items.reduce((sum, item) => sum + item.quantity, 0)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
clear() {
|
|
294
|
+
this.items = []
|
|
295
|
+
this.totalAmount = 0
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Uso
|
|
300
|
+
const cart = new ShoppingCart("user123")
|
|
301
|
+
cart.addItem({ id: 1, name: "Libro", price: 299 }, 2)
|
|
302
|
+
cart.addItem({ id: 2, name: "Café", price: 85 }, 1)
|
|
303
|
+
|
|
304
|
+
console.log(cart.getTotal()) // 683
|
|
305
|
+
console.log(cart.getItemCount()) // 3`
|
|
306
|
+
|
|
307
|
+
this.printCodeWithColors("Clase ShoppingCart", cartCode)
|
|
308
|
+
|
|
309
|
+
await this.waitForEnter("\nPresiona Enter para la conclusión...")
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
async conclusion() {
|
|
313
|
+
console.clear()
|
|
314
|
+
console.log("🎓 Conclusión: Definición del Objeto")
|
|
315
|
+
console.log("=" .repeat(50))
|
|
316
|
+
|
|
317
|
+
console.log("\n💎 Enunciado fundamental:")
|
|
318
|
+
console.log("'Un objeto es un conjunto de datos y procedimientos")
|
|
319
|
+
console.log(" que operan sobre esos datos'")
|
|
320
|
+
|
|
321
|
+
console.log("\n🔍 Desglose:")
|
|
322
|
+
console.log("1️⃣ CONJUNTO → agrupación unificada")
|
|
323
|
+
console.log("2️⃣ DATOS → propiedades del objeto (this.property)")
|
|
324
|
+
console.log("3️⃣ PROCEDIMIENTOS → métodos del objeto")
|
|
325
|
+
console.log("4️⃣ OPERAN SOBRE → los métodos modifican/leen las propiedades")
|
|
326
|
+
|
|
327
|
+
console.log("\n✅ Ventajas demostradas:")
|
|
328
|
+
console.log("• Encapsulación: datos y operaciones juntos")
|
|
329
|
+
console.log("• Modularidad: cada objeto es independiente")
|
|
330
|
+
console.log("• Escalabilidad: múltiples instancias fácilmente")
|
|
331
|
+
console.log("• Organización: responsabilidades claras")
|
|
332
|
+
|
|
333
|
+
console.log("\n📚 Ejemplos vistos:")
|
|
334
|
+
console.log("• BankAccount: balance + deposit/withdraw")
|
|
335
|
+
console.log("• ShoppingCart: items + addItem/removeItem")
|
|
336
|
+
|
|
337
|
+
console.log("\n🔗 Conexión con otros enunciados:")
|
|
338
|
+
console.log("• Enunciado 1: Estos objetos son los que descomponemos del sistema")
|
|
339
|
+
console.log("• Enunciado 2: Estos objetos interactúan mediante solicitudes")
|
|
340
|
+
console.log("• Enunciado 5: La interfaz expone los procedimientos disponibles")
|
|
341
|
+
|
|
342
|
+
console.log("\n💭 Reflexión:")
|
|
343
|
+
console.log("Antes de diseñar cómo los objetos interactúan,")
|
|
344
|
+
console.log("debemos entender QUÉ ES un objeto:")
|
|
345
|
+
console.log("datos + procedimientos, unidos e inseparables.")
|
|
346
|
+
|
|
347
|
+
await this.waitForEnter("\n✨ ¡Lección 7 completada! Presiona Enter para continuar...")
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
formatCode(code) {
|
|
351
|
+
const colors = {
|
|
352
|
+
keyword: '\x1b[35m',
|
|
353
|
+
property: '\x1b[32m',
|
|
354
|
+
string: '\x1b[33m',
|
|
355
|
+
comment: '\x1b[90m',
|
|
356
|
+
reset: '\x1b[0m'
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return code
|
|
360
|
+
.replace(/\b(class|constructor|return|if|const|let|new|function)\b/g, `${colors.keyword}$1${colors.reset}`)
|
|
361
|
+
.replace(/\bthis\./g, `${colors.property}this.${colors.reset}`)
|
|
362
|
+
.replace(/'([^']*)'/g, `${colors.string}'$1'${colors.reset}`)
|
|
363
|
+
.replace(/"([^"]*)"/g, `${colors.string}"$1"${colors.reset}`)
|
|
364
|
+
.replace(/\/\/.*$/gm, `${colors.comment}$&${colors.reset}`)
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
printCodeWithColors(title, code) {
|
|
368
|
+
console.log(`\n${title}`)
|
|
369
|
+
console.log("━".repeat(50))
|
|
370
|
+
|
|
371
|
+
code.split('\n').forEach(line => {
|
|
372
|
+
const formattedLine = this.formatCode(line)
|
|
373
|
+
console.log(formattedLine)
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
console.log("━".repeat(50))
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
async waitForEnter(message) {
|
|
380
|
+
return new Promise((resolve) => {
|
|
381
|
+
this.rl.question(message, () => {
|
|
382
|
+
console.log("\n\n")
|
|
383
|
+
resolve()
|
|
384
|
+
})
|
|
385
|
+
})
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Para usar la lección independientemente
|
|
390
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
391
|
+
const lesson = new Lesson7ObjectDefinition()
|
|
392
|
+
await lesson.start()
|
|
393
|
+
}
|
package/package.json
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@icarusmx/creta",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Salgamos de este laberinto.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"creta": "./bin/creta.js"
|
|
8
8
|
},
|
|
9
|
-
"keywords": [
|
|
9
|
+
"keywords": [
|
|
10
|
+
"cli",
|
|
11
|
+
"icarus",
|
|
12
|
+
"creta",
|
|
13
|
+
"scythe",
|
|
14
|
+
"software school"
|
|
15
|
+
],
|
|
10
16
|
"author": "Guillermo Rodríguez López",
|
|
11
|
-
"publishConfig": {
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
12
20
|
"license": "MIT",
|
|
13
21
|
"dependencies": {
|
|
14
22
|
"chalk": "^5.3.0",
|