/**
* Clase gestora del flujo de ejecución del algoritmo
*/
class __FlowManager {
#steps;
#actualStep;
#stepCount;
#stepIndex;
#lineaActual;
#stepInitialized;
#canBack;
#canNext;
#playing;
#player;
/**
* Constructor por defecto
* @constructor
*/
constructor() {
this.steps = new Array(0);
this.actualStep = {
backward: new Array(0),
execution: new Array(0),
exit: new Array(0),
};
this.stepCount = 0;
this.stepIndex = 0;
this.lineaActual = -1;
this.stepInitialized = false;
this.canBack = false;
this.canNext = false;
this.playing = false;
}
/**
* Inicializa el gestor
*/
startFlow() {
this.steps = new Array(0);
this.stepCount = 0;
this.stepIndex = 0;
this.stepInitialized = false;
}
/**
* Finaliza el gestor
*/
finishFlow() {
this.stepCount = this.steps.length;
this.stepIndex = 0;
this.canBack = false;
this.canNext = true;
this.steps[this.stepIndex].execution.forEach((el) =>
this.executeAction(el)
);
}
/**
* Crea un nuevo paso en el gestor
*/
startStep() {
if (this.stepInitialized) return;
this.actualStep = {
backward: new Array(0),
execution: new Array(0),
exit: new Array(0),
};
this.stepInitialized = true;
}
/**
* Finaliza el paso creado
*/
finishStep() {
if (!this.stepInitialized) return;
this.steps.push(this.actualStep);
this.stepInitialized = false;
}
/**
* Vuelve al primer paso del algoritmo
*/
reset() {
for (var i = this.stepIndex; i > 0; i--) {
this.steps[i].backward.forEach((el) => this.executeAction(el));
this.steps[i].exit.forEach((el) => this.executeAction(el));
}
this.stepIndex = 0;
this.steps[this.stepIndex].execution.forEach((el) =>
this.executeAction(el)
);
}
/**
* Retrocede un paso en el algotimo
*/
back() {
if (this.stepIndex <= 0) return;
this.steps[this.stepIndex].backward.forEach((el) => this.executeAction(el));
this.steps[this.stepIndex].exit.forEach((el) => this.executeAction(el));
this.stepIndex--;
this.steps[this.stepIndex].execution.forEach((el) =>
this.executeAction(el)
);
}
/**
* Avanza un paso en el algoritmo
*/
next() {
if (this.stepIndex >= this.stepCount - 1) return;
this.steps[this.stepIndex].exit.forEach((el) => this.executeAction(el));
this.stepIndex++;
this.steps[this.stepIndex].execution.forEach((el) =>
this.executeAction(el)
);
}
/**
* Va al último paso en el algoritmo
*/
last() {
for (var i = this.stepIndex; i < this.stepCount - 1; i++) {
this.steps[i].execution.forEach((el) => this.executeAction(el));
this.steps[i].exit.forEach((el) => this.executeAction(el));
}
this.stepIndex = this.stepCount - 1;
this.steps[this.stepIndex].execution.forEach((el) =>
this.executeAction(el)
);
}
/**
* Alterna el avance automático de pasos
*/
trogglePlay() {
if (!this.playing) {
this.playing = true;
this.player = setInterval(() => {
if (this.stepIndex >= this.stepCount - 1) {
$("#player").attr("src", "/images/iconos/play.svg");
clearTimeout(this.player);
return;
}
this.next();
}, 1000);
$("#player").attr("src", "/images/iconos/pause.svg");
} else {
this.playing = false;
if (this.player != undefined) {
clearInterval(this.player);
}
$("#player").attr("src", "/images/iconos/play.svg");
}
}
/**
* Acción de seleccionar una línea de código
* @param {number} line Línea a seleccionar
*/
static selectLine(line) {
var id = "#lineaCodigo" + line;
$(id).removeClass("codigo").addClass("codigoSeleccionado");
}
/**
* Acción de deseleccionar una línea de código
* @param {number} line
*/
static unselectLine(line) {
var id = "#lineaCodigo" + line;
$(id).removeClass("codigoSeleccionado").addClass("codigo");
}
/**
* Añade una nueva acción que se ejecutará al entrar al paso
* @param {action} action Acción a añadir
*/
includeAction(action) {
this.actualStep.execution.push(action);
}
/**
* Añade una nueva acción que se ejecutará al entrar volver al paso anterior
* @param {action} action Acción a añadir
*/
includeBackAction(action) {
this.actualStep.backward.push(action);
}
/**
* Añade una nueva acción que se ejecutará al salir del paso hacia adelante
* @param {action} action Acción a añadir
*/
includeExitAction(action) {
this.actualStep.exit.push(action);
}
/**
* Valor que se setará en la entrada del paso para la celda de la tabla indicada
* @param {string} table Nombre de la tabla
* @param {number} row Número de la fila
* @param {number} column Número de la columna
* @param {object} value Nuevo valor
*/
newCellValue(table, row, column, value) {
this.includeAction({
action: "cellValue",
values: [table, row, column, value],
});
}
/**
* Valor que se seteará cuando se vuelva para el paso anterior del paso actual para la celda de la tabla indicada
* @param {string} table Nombre de la tabla
* @param {number} row Número de la fila
* @param {number} column Número de la columna
* @param {object} value Valor viejo
*/
oldCellValue(table, row, column, value) {
this.includeBackAction({
action: "cellValue",
values: [table, row, column, value],
});
}
/**
* Selecciona la línea de código en la entrada del paso
* @param {number} line Número de línea
*/
selectSourceLine(line) {
this.includeExitAction({ action: "unselectSourceLine", values: [line] });
this.includeAction({ action: "selectSourceLine", values: [line] });
}
/**
* Selecciona para ese paso la celda de la tabla indicada
* @param {string} table Nombre de la tabla
* @param {number} row Número de la fila
* @param {number} column Número de la columna
*/
selectCell(table, row, column) {
this.includeExitAction({
action: "unselectCell",
values: [table, row, column],
});
this.includeAction({ action: "selectCell", values: [table, row, column] });
}
/**
* Selecciona una celda permanentemente de la tabla indicada
* @param {string} table Nombre de la tabla
* @param {number} row Número de la fila
* @param {number} column Número de la columna
*/
selectCellPermanent(table, row, column) {
this.includeBackAction({
action: "unselectCell",
values: [table, row, column],
});
this.includeAction({ action: "selectCell", values: [table, row, column] });
}
/**
* Valor que se seteará cuando se entre en el paso para la variable indicada
* @param {string} name Nombre de la variable
* @param {object} value Valor nuevo
*/
newResultValue(name, value) {
this.includeAction({ action: "resultValue", values: [name, value] });
}
/**
* Valor que se seteará cuando se vuelva para el paso anterior para una variable dada
* @param {string} name Nombre de la variable
* @param {object} value Valor antiguo
*/
oldResultValue(name, value) {
this.includeBackAction({ action: "resultValue", values: [name, value] });
}
/**
* Aplica el estilo al elemento del grafo indicado al entrar en el paso
* @param {string} graph Nombre del grafo
* @param {string} elementId Identificador de elemento o grupo
* @param {object} style Estilo a aplicar
*/
setGraphStyle(graph, elementId, style) {
this.includeAction({
action: "setGraphStyle",
values: [graph, elementId, style],
});
this.includeBackAction({
action: "unsetGraphStyle",
values: [graph, elementId, style],
});
}
/**
* Quita el estilo al elemento del grafo indicado al entrar en el paso
* @param {string} graph Nombre del grafo
* @param {string} elementId Identificador de elemento o grupo
* @param {object} style Esilo a quitar
*/
unsetGraphStyle(graph, elementId, style) {
this.includeAction({
action: "unsetGraphStyle",
values: [graph, elementId, style],
});
this.includeBackAction({
action: "setGraphStyle",
values: [graph, elementId, style],
});
}
/**
* Valor que se setará en la entrada del paso para la barra del gráfico indicado
* @param {string} chart Nombre de la gráfico
* @param {number} id Número de barra
* @param {object} value Nuevo valor
*/
newBarValue(chart, id, value) {
this.includeAction({ action: "barValue", values: [chart, id, value] });
}
/**
* Valor que se seteará cuando se vuelva para el paso anterior del paso actualpara la barra del gráfico indicado
* @param {string} chart Nombre de la gráfico
* @param {number} id Número de barra
* @param {object} value Valor viejo
*/
oldBarValue(chart, id, value) {
this.includeBackAction({ action: "barValue", values: [chart, id, value] });
}
/**
* Selecciona para ese paso la barra del gráfico indicado
* @param {string} chart Nombre de la gráfico
* @param {number} id Número de barra
*/
selectBar(chart, id, color = "red") {
this.includeExitAction({
action: "unselectBar",
values: [chart, id],
});
this.includeAction({ action: "selectBar", values: [chart, id] });
}
/**
* Selecciona una barra permanentemente del gráfico indicado
* @param {string} chart Nombre de la gráfico
* @param {number} id Número de barra
*/
selectBarPermanent(chart, id, color = "red") {
this.includeBackAction({
action: "unselectBar",
values: [chart, id],
});
this.includeAction({ action: "selectBar", values: [chart, id, color] });
}
/**
* Deselecciona para ese paso la barra del gráfico indicado
* @param {string} chart Nombre de la gráfico
* @param {number} id Número de barra
*/
unselectBar(chart, id) {
if (OutputData.get(chart).getBarStyle(id) !== undefined) {
this.includeBackAction({
action: "setBarStyle",
values: [chart, id, OutputData.get(chart).getBarStyle(id)],
});
}
this.includeAction({ action: "unselectBar", values: [chart, id] });
}
action = {
selectCellAction: function (table, row, column) {
OutputData.get(table).selectCell(row, column);
},
unselectCellAction: function (table, row, column) {
OutputData.get(table).unselectCell(row, column);
},
unselectSourceLineAction: function (line) {
__FlowManager.unselectLine(line);
},
selectSourceLineAction: function (line) {
__FlowManager.selectLine(line);
},
cellValueAction: function (table, row, column, value) {
OutputData.get(table).setValue(row, column, value);
},
resultValueAction: function (name, value) {
OutputData.get(name).setData(value);
},
setGraphStyleAction: function (graph, id, style) {
OutputData.get(graph).setStyleToElement(id, style);
},
unsetGraphStyleAction: function (graph, id, style) {
OutputData.get(graph).unsetStyleToElement(id, style);
},
barValueAction: function (chart, id, value) {
OutputData.get(chart).setBarValue(id, value);
},
selectBarAction: function (chart, id, color) {
OutputData.get(chart).selectBar(id, color);
},
unselectBarAction: function (chart, id) {
OutputData.get(chart).unselectBar(id);
},
setBarStyleAction: function (chart, id, style) {
OutputData.get(chart).setBarStyle(id, style);
},
};
/**
* Ejecuta la acción dada
* @param {action} actualAction Acción a ejecutar
*/
executeAction = function (actualAction) {
switch (actualAction.action) {
case "selectCell":
this.action.selectCellAction.apply(actualAction, actualAction.values);
break;
case "unselectCell":
this.action.unselectCellAction.apply(actualAction, actualAction.values);
break;
case "unselectSourceLine":
this.action.unselectSourceLineAction.apply(
actualAction,
actualAction.values
);
break;
case "selectSourceLine":
this.action.selectSourceLineAction.apply(
actualAction,
actualAction.values
);
break;
case "cellValue":
this.action.cellValueAction.apply(actualAction, actualAction.values);
break;
case "resultValue":
this.action.resultValueAction.apply(actualAction, actualAction.values);
break;
case "setGraphStyle":
this.action.setGraphStyleAction.apply(
actualAction,
actualAction.values
);
break;
case "unsetGraphStyle":
this.action.unsetGraphStyleAction.apply(
actualAction,
actualAction.values
);
break;
case "barValue":
this.action.barValueAction.apply(actualAction, actualAction.values);
break;
case "selectBar":
this.action.selectBarAction.apply(actualAction, actualAction.values);
break;
case "unselectBar":
this.action.unselectBarAction.apply(actualAction, actualAction.values);
break;
case "setBarStyle":
this.action.setBarStyleAction.apply(actualAction, actualAction.values);
break;
default:
break;
}
};
}
/**
* Instancia del gestor del flujo del algoritmo
* @constant
* @type {__FlowManager}
*/
const FlowManager = new __FlowManager();