web: ThermalUnits: onDataChanged

web
Alinson S. Xavier 3 months ago
parent 3bf028577e
commit eb3d39b1ab

@ -30,6 +30,7 @@ import {
import { ColumnDefinition } from "tabulator-tables";
import { offerDownload } from "../Common/io";
import {
changeThermalUnitData,
createThermalUnit,
deleteGenerator,
renameGenerator,
@ -194,17 +195,17 @@ const ThermalUnitsComponent = (props: CaseBuilderSectionProps) => {
field: string,
newValue: string,
): ValidationError | null => {
// const [newScenario, err] = changeThermalUnitData(
// name,
// field,
// newValue,
// props.scenario,
// );
// if (err) {
// props.onError(err.message);
// return err;
// }
// props.onDataChanged(newScenario);
const [newScenario, err] = changeThermalUnitData(
name,
field,
newValue,
props.scenario,
);
if (err) {
props.onError(err.message);
return err;
}
props.onDataChanged(newScenario);
return null;
};

@ -350,10 +350,9 @@ const DataTable = (props: DataTableProps) => {
useEffect(() => {
const onCellEdited = (cell: CellComponent) => {
let newValue = cell.getValue();
let oldValue = cell.getOldValue();
// eslint-disable-next-line eqeqeq
if (newValue == oldValue) return;
let newValue = `${cell.getValue()}`;
let oldValue = `${cell.getOldValue()}`;
if (newValue === oldValue) return;
if (cell.getField() === "Name") {
if (newValue === "") {
const err = props.onRowDeleted(oldValue);

@ -108,7 +108,26 @@ export const changeNumberData = (
];
};
export const changeNumberVecData = (
export const changeBooleanData = (
field: string,
newValueStr: string,
container: { [key: string]: any },
): [{ [key: string]: any }, ValidationError | null] => {
// Parse value
const [newValueBool, err] = parseBool(newValueStr);
if (err) return [container, err];
// Build the new object
return [
{
...container,
[field]: newValueBool,
},
null,
];
};
export const changeNumberVecTData = (
field: string,
time: string,
newValueStr: string,
@ -136,6 +155,43 @@ export const changeNumberVecData = (
];
};
export const changeNumberVecNData = (
field: string,
offset: string,
newValueStr: string,
container: { [key: string]: any },
): [{ [key: string]: any }, ValidationError | null] => {
const oldVec = container[field];
const newVec = [...container[field]];
const idx = parseInt(offset) - 1;
if (newValueStr === "") {
// Trim the vector
newVec.splice(idx, oldVec.length - idx);
} else {
// Parse new value
const [newValueFloat, err] = parseNumber(newValueStr);
if (err) return [container, err];
// Increase the length of the vector
if (idx >= oldVec.length) {
for (let i = oldVec.length; i < idx; i++) {
newVec[i] = 0;
}
}
// Assign new value
newVec[idx] = newValueFloat;
}
return [
{
...container,
[field]: newVec,
},
null,
];
};
export const changeData = (
field: string,
newValueStr: string,
@ -143,9 +199,9 @@ export const changeData = (
colSpecs: ColumnSpec[],
scenario: UnitCommitmentScenario,
): [{ [key: string]: any }, ValidationError | null] => {
const match = field.match(/^([^0-9]+)(\d+:\d+)?$/);
const match = field.match(/^([^0-9]+)([0-9:]+)?$/);
const fieldName = match![1]!.trim();
const fieldTime = match![2];
const fieldOffset = match![2];
for (const spec of colSpecs) {
if (spec.title !== fieldName) continue;
switch (spec.type) {
@ -156,13 +212,22 @@ export const changeData = (
case "number":
return changeNumberData(fieldName, newValueStr, container);
case "number[T]":
return changeNumberVecData(
return changeNumberVecTData(
fieldName,
fieldTime!,
fieldOffset!,
newValueStr,
container,
scenario,
);
case "number[N]":
return changeNumberVecNData(
fieldName,
fieldOffset!,
newValueStr,
container,
);
case "boolean":
return changeBooleanData(fieldName, newValueStr, container);
default:
throw Error(`Unknown type: ${spec.type}`);
}

@ -8,6 +8,7 @@ import { TEST_DATA_1, TEST_DATA_BLANK } from "../fixtures.test";
import assert from "node:assert";
import {
changeProfiledUnitData,
changeThermalUnitData,
createProfiledUnit,
createThermalUnit,
deleteGenerator,
@ -63,6 +64,58 @@ test("changeProfiledUnitData", () => {
});
});
test("changeThermalUnitData", () => {
let scenario = TEST_DATA_1;
let err: ValidationError | null;
[scenario, err] = changeThermalUnitData(
"g1",
"Ramp up limit (MW)",
"99",
scenario,
);
assert(!err);
[scenario, err] = changeThermalUnitData(
"g1",
"Startup costs ($) 2",
"99",
scenario,
);
assert(!err);
[scenario, err] = changeThermalUnitData(
"g1",
"Production cost curve ($) 7",
"99",
scenario,
);
assert(!err);
[scenario, err] = changeThermalUnitData(
"g1",
"Production cost curve (MW) 3",
"",
scenario,
);
assert(!err);
[scenario, err] = changeThermalUnitData("g1", "Must run?", "true", scenario);
assert(!err);
assert.deepEqual(scenario.Generators["g1"], {
Bus: "b1",
Type: "Thermal",
"Production cost curve (MW)": [100.0, 110],
"Production cost curve ($)": [1400.0, 1600.0, 2200.0, 2400.0, 0, 0, 99],
"Startup costs ($)": [300.0, 99.0],
"Startup delays (h)": [1, 4],
"Ramp up limit (MW)": 99,
"Ramp down limit (MW)": 232.68,
"Startup limit (MW)": 232.68,
"Shutdown limit (MW)": 232.68,
"Minimum downtime (h)": 4,
"Minimum uptime (h)": 4,
"Initial status (h)": 12,
"Initial power (MW)": 115,
"Must run?": true,
});
});
test("changeProfiledUnitData with invalid bus", () => {
let scenario = TEST_DATA_1;
let err = null;

@ -13,6 +13,7 @@ import {
renameItemInObject,
} from "./commonOps";
import { ProfiledUnitsColumnSpec } from "../../components/CaseBuilder/ProfiledUnits";
import { ThermalUnitsColumnSpec } from "../../components/CaseBuilder/ThermalUnits";
const assertBusesNotEmpty = (
scenario: UnitCommitmentScenario,
@ -109,6 +110,32 @@ export const changeProfiledUnitData = (
];
};
export const changeThermalUnitData = (
generator: string,
field: string,
newValueStr: string,
scenario: UnitCommitmentScenario,
): [UnitCommitmentScenario, ValidationError | null] => {
const [newGen, err] = changeData(
field,
newValueStr,
scenario.Generators[generator]!,
ThermalUnitsColumnSpec,
scenario,
);
if (err) return [scenario, err];
return [
{
...scenario,
Generators: {
...scenario.Generators,
[generator]: newGen,
} as Generators,
},
null,
];
};
export const deleteGenerator = (
name: string,
scenario: UnitCommitmentScenario,

Loading…
Cancel
Save