¡Un reto más, Platzinauta! 💪
El manejo de la memoria y la copia o comparación de objetos en JavaScript es un tema con varios niveles de complejidad.
Si es tu primera vez enfrentándote a este tipo de problemas, te recomiendo estos materiales:
Juan David Castro Gallego
Aportes 21
Preguntas 1
¡Un reto más, Platzinauta! 💪
El manejo de la memoria y la copia o comparación de objetos en JavaScript es un tema con varios niveles de complejidad.
Si es tu primera vez enfrentándote a este tipo de problemas, te recomiendo estos materiales:
Excelente! Apoyo para que se sigan haciendo este tipo de clases: son entretenidas, pones en practica tus conocimientos y si te falta algo lo repasas o vas y lo aprendes de verdad excelente!
listo mi solucion
export class Motor {
constructor(propulsionTo, historyInstance) {
let status = "off"
let history = historyInstance;
this.getStatus = () => status;
let setStatus = (newStatus) => {
if (status != newStatus) {
history.agragarEvento(propulsionTo, newStatus)
status = newStatus;
}
};
this.turnOn = () => setStatus("on");
this.turnOff = () => setStatus("off");
this.getHistory = () => history.getFullState();
}
}
export class History {
constructor() {
let history = [];
this.getFullState = () => history;
this.agragarEvento = (direccion, estado) => history.push({"propulsionTo": direccion, "status": estado})
}
}
esto es muy divertido
// Clase Motor
export class Motor {
// Constructor de la clase `Motor`.
constructor(propulsionTo, history) {
// Establece una propiedad llamada `propulsionTo` para el objeto `Motor`.
this.propulsionTo = propulsionTo;
// Establece una propiedad llamada `history` para el objeto `Motor`.
this.history = history;
// Establece una propiedad llamada `status` para el objeto `Motor`.
this.status = "off";
}
// Método que cambia el valor de la propiedad `status` del objeto `Motor` a "on" y agrega un objeto de cambio al historial.
turnOn() {
this.status = "on";
this.history.addChange(this.propulsionTo, this.status);
}
// Método que cambia el valor de la propiedad `status` del objeto `Motor` a "off" y agrega un objeto de cambio al historial.
turnOff() {
this.status = "off";
this.history.addChange(this.propulsionTo, this.status);
}
}
// Clase History
export class History {
constructor() {
// Si la instancia de la clase `History` no existe, crea una nueva y establece una propiedad llamada `history` como un array vacío.
if (!History.instance) {
History.instance = this;
this.history = [];
}
// Devuelve la instancia existente de la clase `History`.
return History.instance;
}
// Método que agrega un objeto de cambio al historial si el último objeto agregado tiene una propiedad diferente de `propulsionTo` o `status`.
addChange(propulsionTo, status) {
const lastChange = this.history[this.history.length - 1];
if (!lastChange || lastChange.propulsionTo !== propulsionTo || lastChange.status !== status) {
this.history.push({ propulsionTo, status });
}
}
// Método que devuelve una copia del historial.
getFullState() {
return this.history.slice();
}
}
Spoler
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Lo hice sencillo, sin ningún tipo de shallow copy o utilizando stringify y parse
export class Motor {
constructor(propulsionTo, historyInstance) {
let status = "off"
let dir = propulsionTo
let history = historyInstance;
this.getStatus = () => status;
let setStatus = (newStatus) => {
status = newStatus;
history.addRecord({propulsionTo:dir, status:status})
};
this.turnOn = () => setStatus("on");
this.turnOff = () => setStatus("off");
this.getHistory = () => history.getFullState();
}
}
export class History {
constructor() {
let history = [];
this.getFullState = () => history;
this.addRecord = (record) => {
const lastRecord = history[history.length - 1]
if (!lastRecord) {
history.push(record)
console.log("First added")
return
}
const isSamePropulsion = lastRecord.propulsionTo == record.propulsionTo
const isSameStatus = lastRecord.status == record.status
if (isSamePropulsion && isSameStatus)
{
console.log("Not added")
return
}
history.push(record)
console.log("Added")
}
}
}
Comparto mi solucion, es realmente satisfactorio lograrlo con tus propios conocimientos.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
class Motor {
constructor(propulsionTo, historyInstance) {
let status = ""
let history = historyInstance;
this.getStatus = () => status;
let setStatus = (newStatus) => {
if(status !== newStatus){
status = newStatus;
mensajeEstadoMotor(propulsionTo, newStatus);
}
};
this.turnOn = () => setStatus("on");
this.turnOff = () => setStatus("off");
this.getHistory = () => history.getFullState();
let setHistory = (mensaje) => {
history.setFullState(mensaje);
};
let mensajeEstadoMotor = (motorName, MotorStatus) => {
const mensaje = {
"propulsionTo": motorName,
"status": MotorStatus,
}
setHistory(mensaje);
};
}
}
class History {
constructor() {
let history = [];
this.getFullState = () => history;
this.setFullState = (mensaje) => {
history.push(mensaje)
}
}
}
’
“
”"
"
"
"
""
"
"
"
"
"
"
export class Motor {
constructor(propulsionTo, historyInstance) {
let status = "off"
let history = historyInstance;
this.getStatus = () => status;
let setStatus = (newStatus) => {
status = newStatus
history.addRecord(newStatus, propulsionTo)
};
this.turnOn = () => setStatus("on");
this.turnOff = () => setStatus("off");
this.getHistory = () => history.getFullState();
}
}
export class History {
constructor() {
let history = [];
this.getFullState = () => {
return history
};
this.addRecord = (newStatus, propulsionTo) => {
let lastObj = history[history.length - 1]
if (lastObj?.propulsionTo === propulsionTo && lastObj?.status === newStatus ) {
return false
}
history.push({
"propulsionTo": propulsionTo,
"status": newStatus
})
}
}
}
Spoiler
mi Solucion
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
export class Motor {
constructor(propulsionTo, historyInstance) {
let status = "off"
let history = historyInstance;
this.getStatus = () => status;
let setStatus = (newStatus) => {
status = newStatus;
};
this.turnOn = () => {
setStatus("on")
this.setHistory()
};
this.turnOff = () => {
setStatus("off")
this.setHistory()
};
this.setHistory = () => {
const lastHistory = history.getFullState()
const payload = { propulsionTo: propulsionTo, status: this.getStatus() }
const isEqual = JSON.stringify((lastHistory[lastHistory.length - 1])) === JSON.stringify(payload)
if (!isEqual) {
history.setHistory(payload)
}
}
this.getHistory = () => history.getFullState();
}
}
export class History {
constructor() {
let history = [];
this.getFullState = () => history;
this.setHistory = (payload) => {
history.push(payload)
}
}
}
Mi solución 👇
.
.
.
.
.
.
.
.
.
.
.
.
.
.
export class Motor {
constructor(propulsionTo, historyInstance) {
let status = "off";
let history = historyInstance;
this.getStatus = () => status;
let setStatus = (newStatus) => {
status = newStatus;
historyInstance.historyEvent = {
propulsionTo,
status
}
};
this.turnOn = () => setStatus("on");
this.turnOff = () => setStatus("off");
this.getHistory = () => history.getFullState();
}
}
export class History {
constructor() {
this.history = [];
this.getFullState = () => this.history;
}
set historyEvent(event) {
if (JSON.stringify(this.history.at(-1)) !== JSON.stringify(event)) {
this.history.push(event);
}
}
}
Debo decir que tuve problemas con este ejercicio 😕, pero gracias a los aportes logre superarlo 😅.
Solución 😄…
.
.
.
.
export class Motor {
constructor(propulsionTo, historyInstance) {
let status = "off"
let history = historyInstance;
this.getStatus = () => status;
let setStatus = (newStatus) => {
status = newStatus;
};
this.turnOn = () => {
setStatus("on");
history.addToHistory(propulsionTo, status);
};
this.turnOff = () => {
setStatus("off");
history.addToHistory(propulsionTo, status);
};
this.getHistory = () => history.getFullState();
}
}
export class History {
constructor() {
let history = [];
this.getFullState = () => history;
this.addToHistory = (propulsionTo, status) => {
let lastRecord = history[history.length - 1];
let record = {
"propulsionTo": propulsionTo,
"status": status
};
if (
JSON.stringify(record) !== JSON.stringify(lastRecord)
) {
history.push(record);
}
};
}
}
Uff muy buenos pero me hace falta aprender mucho!
😃
😃
😃
😃
😃
😃
😃
😃
😃
😃
😃
😃
😃
😃
Lo realize con mi propia logica 😅, aunque despues de ver las demas resoluciones, la mia quedo muy grande y engorrosa.
export class Motor {
constructor(propulsionTo, historyInstance) {
let status = "off";
let fullHistory = [];
//validacion de history
if (historyInstance instanceof History) {
//obteniendo el historial completo
fullHistory = historyInstance.getFullState();
}
this.getStatus = () => status;
function setStatus(newStatus) {
//evaluando si el ultimo status es igual al nuevo
if (
fullHistory[fullHistory.length - 1]?.propulsionTo !== propulsionTo ||
fullHistory[fullHistory.length - 1]?.status !== newStatus
) {
historyInstance.setHistory({
propulsionTo: propulsionTo,
status: newStatus,
});
}
status = newStatus;
}
this.turnOn = () => setStatus("on");
this.turnOff = () => setStatus("off");
this.getHistory = () => history.getFullState();
}
}
export class History {
//trabaje con private fields
#_history;
constructor() {
this.#_history = [];
this.setHistory = (history) => {
this.#_history.push(history);
};
this.getFullState = () => this.#_history;
}
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
export class Motor {
constructor(propulsionTo, historyInstance) {
let status = "off"
let history = historyInstance;
this.getStatus = () => status;
let setStatus = (newStatus) => {
status = newStatus;
historyInstance.add(propulsionTo, status)
};
this.turnOn = () => setStatus("on");
this.turnOff = () => setStatus("off");
this.getHistory = () => history.getFullState();
}
}
export class History {
constructor() {
let history = [];
this.getFullState = () => history;
this.add = (propulsionTo, status) => {
const lastElement = history[history.length - 1]
if (lastElement && lastElement.propulsionTo === propulsionTo && lastElement.status === status) return
history.push({
propulsionTo,
status,
})
}
}
}
Mi solución agregando métodos y validaciones en ambas clases:
.
.
.
.
.
.
.
.
.
export class Motor {
constructor(propulsionTo, historyInstance) {
let propulsion = propulsionTo;
let status = "off";
let history = historyInstance;
this.getPropulsion = () => propulsion;
this.getStatus = () => status;
let setStatus = newStatus => {
status = newStatus;
};
this.turnOn = () => {
if (this.getStatus() !== "on") {
setStatus("on");
history.addRecord(this);
}
};
this.turnOff = () => {
if (this.getStatus() !== "off") {
setStatus("off");
history.addRecord(this);
}
};
this.getHistory = () => history.getFullState();
}
}
export class History {
constructor() {
let history = [];
this.addRecord = motor => {
history.push({
propulsionTo: motor.getPropulsion(),
status: motor.getStatus(),
});
};
this.getFullState = () => history;
}
}
export class Motor {
constructor(propulsionTo, historyInstance) {
let status = "off"
let history = historyInstance
this.getStatus = () => status;
let setStatus = (newStatus) => {
if (newStatus !== status) {
status = newStatus;
history.addStatus({propulsionTo,status})
}
};
this.turnOn = () => setStatus("on");
this.turnOff = () => setStatus("off");
this.getHistory = () => history.getFullState();
}
}
export class History {
constructor() {
let history = [];
this.getFullState = () => history;
this.addStatus = (obj) => history.push(obj)
}
}
Esta es mi solución usando el método structuredClone()
en vez de JSON.stringify/parse
También modifique las propiedades y métodos para usarlos como privados o públicos según corresponda.
export class Motor {
#STATUS_ON = "on";
#STATUS_OFF = "off";
#id;
#status;
#history;
constructor(id, historyInstance) {
this.#id = id;
this.#status = this.#STATUS_OFF;
this.#history = historyInstance;
}
getStatus() {
return this.#status;
}
turnOn() {
this.#setStatus({ status: this.#STATUS_ON });
this.#saveNewState();
}
turnOff() {
this.#setStatus({ status: this.#STATUS_OFF });
this.#saveNewState();
}
#setStatus({ status }) {
this.#status = status;
}
#saveNewState() {
const status = this.getStatus();
const lastState = this.#history.getLastState({
propulsionTo: this.#id,
});
if (lastState === undefined || lastState?.status !== status) {
this.#history.recordLog({ status, propulsionTo: this.#id });
}
// probamos modificar el último state por ser un objeto
// if (lastState !== undefined) lastState.status = "ON_FAKE";
}
}
export class History {
#history;
constructor() {
this.#history = [];
}
getFullState() {
return structuredClone(this.#history);
}
recordLog({ status, propulsionTo }) {
this.#history.push({ status, propulsionTo });
}
getLastState({ propulsionTo }) {
// structuredClone reeplazaría el JSON.stringify/parse
return structuredClone(
this.#history.findLast(
(state) => state.propulsionTo === propulsionTo
)
);
}
}
Bueno les dejo mi solución creo que es algo corta aunque no comparo directamento los objetos más bien las propiedades. Además de agregar otra propiedad a History para agregar el objeto que tiene la dirección y el estado.
.
.
.
.
.
.
.
.
.
.
.
export class Motor {
constructor(propulsionTo, historyInstance) {
let status = "off"
let history = historyInstance;
this.getStatus = () => status;
let setStatus = (newStatus) => {
status = newStatus;
};
this.turnOn = () => {
const currentStates = history.getFullState()
if (status === 'on' && currentStates.at(-1)?.propulsionTo === propulsionTo) return
setStatus("on")
history.setDirection({
"propulsionTo": propulsionTo,
"status": this.getStatus(),
})
}
this.turnOff = () => {
const currentStates = history.getFullState()
if (status === 'off' && currentStates.at(-1)?.propulsionTo === propulsionTo) return
setStatus("off")
history.setDirection({
"propulsionTo": propulsionTo,
"status": this.getStatus(),
})
}
this.getHistory = () => history.getFullState();
}
}
export class History {
constructor() {
let history = [];
this.getFullState = () => history;
this.setDirection = (direction) => history.push(direction)
}
}
Aquí tienes una implementación actualizada de las clases Motor
e History
que cumplen con los requerimientos especificados:
export class Motor {
constructor(propulsionTo, historyInstance) {
let status = "off";
let lastStatus = null;
let history = historyInstance;
this.getStatus = () => status;
let setStatus = (newStatus) => {
if (newStatus !== lastStatus) {
status = newStatus;
history.addChange(propulsionTo, status);
lastStatus = newStatus;
}
};
this.turnOn = () => setStatus("on");
this.turnOff = () => setStatus("off");
this.getHistory = () => history.getFullState();
}
}
export class History {
constructor() {
let changes = [];
this.addChange = (propulsionTo, status) => {
changes.push({ propulsionTo, status });
};
this.getFullState = () => changes;
}
}
En esta implementación, se agregó una variable lastStatus
para realizar un seguimiento del último estado registrado en el historial. Cuando se intenta cambiar el estado de un motor, se verifica si es diferente al último estado registrado. Si es diferente, se actualiza el estado del motor, se agrega el cambio al historial y se actualiza lastStatus
. Esto garantiza que no se guarden cambios repetidos consecutivos.
.
Ahora, puedes utilizar las clases actualizadas de la siguiente manera:
const history = new History();
const motorUp = new Motor("up", history);
const motorDown = new Motor("down", history);
motorUp.turnOn();
motorDown.turnOn();
motorUp.turnOff();
motorUp.turnOff(); // Repetido
motorUp.turnOn();
motorUp.turnOn(); // Repetido
motorDown.turnOff();
console.log(history.getFullState());
El resultado será el siguiente:
[
{
"propulsionTo": "up",
"status": "on"
},
{
"propulsionTo": "down",
"status": "on"
},
{
"propulsionTo": "up",
"status": "off"
},
{
"propulsionTo": "up",
"status": "on"
},
{
"propulsionTo": "down",
"status": "off"
}
]
El historial refleja los cambios de estado de los motores según los requerimientos especificados.
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?