Historial de Cambios en el Motor

4/5

Aportes 21

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

¡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);
      }
    };
  }
}
```js export class Motor { constructor(propulsionTo, historyInstance) { let status = "off"; let history = historyInstance; this.getPropulsionTo = () => propulsionTo; this.getStatus = () => status; let setStatus = (newStatus) => { status = newStatus; }; this.turnOn = () => { setStatus("on") history.setFullState({ propulsionTo: this.getPropulsionTo(), status: this.getStatus() }) }; this.turnOff = () => { setStatus("off"); history.setFullState({ propulsionTo: this.getPropulsionTo(), status: this.getStatus() }) } ; this.getHistory = () => history.getFullState(); } } export class History { constructor() { let history = []; this.getFullState = () => history; this.setFullState = ({ propulsionTo, status }) => { if (history.length===0||history[history.length-1].propulsionTo!=propulsionTo|| history[history.length-1].status!=status) history.push({ propulsionTo, status }) } } } ```aca mi solucion.

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;
  }
}

Ufff este se me lio mucho mas pero lo consegui, ahora a desenmascarar a ese impostor!!!

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.

undefined