Compare commits

...

2 Commits

@ -97,6 +97,10 @@ const ProfiledUnitsComponent = (props: ProfiledUnitsProps) => {
props.onError(err.message);
return;
}
for (const gen in newGenerators) {
newGenerators[gen]["Type"] = "Profiled";
}
const newScenario = {
...props.scenario,
Generators: newGenerators,

@ -11,6 +11,7 @@ import {
} from "../../CaseBuilder/Buses/Buses";
import { generateCsv, parseCsv } from "./DataTable";
import { TEST_DATA_1 } from "../../../core/fixtures.test";
import { ProfiledUnitsColumnSpec } from "../../CaseBuilder/ProfiledUnits/ProfiledUnits";
test("generate CSV", () => {
const [data, columns] = generateBusesData(TEST_DATA_1);
@ -23,7 +24,7 @@ test("generate CSV", () => {
assert.strictEqual(actualCsv, expectedCsv);
});
test("parse CSV", () => {
test("parse CSV (Buses)", () => {
const csvContents =
"Name,Load (MW) 00:00,Load (MW) 01:00,Load (MW) 02:00,Load (MW) 03:00,Load (MW) 04:00\n" +
"b1,0,1,2,3,4\n" +
@ -39,3 +40,64 @@ test("parse CSV", () => {
},
});
});
test("parse CSV with duplicated names", () => {
const csvContents =
"Name,Load (MW) 00:00,Load (MW) 01:00,Load (MW) 02:00,Load (MW) 03:00,Load (MW) 04:00\n" +
"b1,0,0,0,0,0\n" +
"b1,0,0,0,0,0";
const [, err] = parseCsv(csvContents, BusesColumnSpec, TEST_DATA_1);
assert(err !== null);
assert.equal(err.message, `Name "b1" is duplicated (row 2)`);
});
test("parse CSV (Profiled Units)", () => {
const csvContents =
"Name,Bus,Cost ($/MW),Maximum power (MW) 00:00,Maximum power (MW) 01:00," +
"Maximum power (MW) 02:00,Maximum power (MW) 03:00," +
"Maximum power (MW) 04:00,Minimum power (MW) 00:00," +
"Minimum power (MW) 01:00,Minimum power (MW) 02:00," +
"Minimum power (MW) 03:00,Minimum power (MW) 04:00\n" +
"pu1,b1,50,260.25384545,72.89148068,377.17886108,336.66732361," +
"376.82781758,52.05076909,14.57829614,75.43577222,67.33346472,75.36556352\n" +
"pu2,b1,0,0,0,0,0,0,0,0,0,0,0";
const [newGenerators, err] = parseCsv(
csvContents,
ProfiledUnitsColumnSpec,
TEST_DATA_1,
);
assert(err === null);
assert.deepEqual(newGenerators, {
pu1: {
Bus: "b1",
"Minimum power (MW)": [
52.05076909, 14.57829614, 75.43577222, 67.33346472, 75.36556352,
],
"Maximum power (MW)": [
260.25384545, 72.89148068, 377.17886108, 336.66732361, 376.82781758,
],
"Cost ($/MW)": 50.0,
},
pu2: {
Bus: "b1",
"Minimum power (MW)": [0, 0, 0, 0, 0],
"Maximum power (MW)": [0, 0, 0, 0, 0],
"Cost ($/MW)": 0.0,
},
});
});
test("parse CSV with invalid bus", () => {
const csvContents =
"Name,Bus,Cost ($/MW),Maximum power (MW) 00:00,Maximum power (MW) 01:00," +
"Maximum power (MW) 02:00,Maximum power (MW) 03:00," +
"Maximum power (MW) 04:00,Minimum power (MW) 00:00," +
"Minimum power (MW) 01:00,Minimum power (MW) 02:00," +
"Minimum power (MW) 03:00,Minimum power (MW) 04:00\n" +
"pu1,b99,50,260.25384545,72.89148068,377.17886108,336.66732361," +
"376.82781758,52.05076909,14.57829614,75.43577222,67.33346472,75.36556352\n" +
"pu2,b1,0,0,0,0,0,0,0,0,0,0,0";
const [, err] = parseCsv(csvContents, ProfiledUnitsColumnSpec, TEST_DATA_1);
assert(err !== null);
assert.equal(err.message, 'Bus "b99" does not exist (row 1)');
});

@ -13,6 +13,7 @@ import {
import { ValidationError } from "../../../core/Validation/validate";
import { UnitCommitmentScenario } from "../../../core/fixtures";
import Papa from "papaparse";
import { parseNumber } from "../../../core/Operations/commonOps";
export interface ColumnSpec {
title: string;
@ -178,14 +179,32 @@ export const parseCsv = (
const data: { [key: string]: any } = {};
for (let i = 0; i < csv.data.length; i++) {
const row = csv.data[i] as { [key: string]: any };
const rowRef = ` (row ${i + 1})`;
const name = row["Name"] as string;
if (name in data) {
return [null, { message: `Name "${name}" is duplicated` + rowRef }];
}
data[name] = {};
for (const spec of colSpecs) {
if (spec.title === "Name") continue;
switch (spec.type) {
case "string":
data[name][spec.title] = row[spec.title];
break;
case "number":
const [val, err] = parseNumber(row[spec.title]);
if (err) return [null, { message: err.message + rowRef }];
data[name][spec.title] = val;
break;
case "busRef":
const busName = row[spec.title];
if (!(busName in scenario.Buses)) {
return [
null,
{ message: `Bus "${busName}" does not exist` + rowRef },
];
}
data[name][spec.title] = row[spec.title];
break;
case "number[]":
@ -198,7 +217,7 @@ export const parseCsv = (
}
break;
default:
console.error(`Unknown type: ${spec.type}`);
throw Error(`Unknown type: ${spec.type}`);
}
}
}

@ -48,13 +48,20 @@ test("deleteBus", () => {
});
test("renameBus", () => {
let [scenario, err] = renameBus("b2", "b99", TEST_DATA_1);
let [scenario, err] = renameBus("b1", "b99", TEST_DATA_1);
assert(err === null);
assert.deepEqual(scenario.Buses, {
b1: { "Load (MW)": [35.79534, 34.38835, 33.45083, 32.89729, 33.25044] },
b99: { "Load (MW)": [14.03739, 13.48563, 13.11797, 12.9009, 13.03939] },
b99: { "Load (MW)": [35.79534, 34.38835, 33.45083, 32.89729, 33.25044] },
b2: { "Load (MW)": [14.03739, 13.48563, 13.11797, 12.9009, 13.03939] },
b3: { "Load (MW)": [27.3729, 26.29698, 25.58005, 25.15675, 25.4268] },
});
assert.deepEqual(scenario.Generators["pu1"], {
Bus: "b99",
Type: "Profiled",
"Cost ($/MW)": 12.5,
"Maximum power (MW)": [10, 12, 13, 15, 20],
"Minimum power (MW)": [0, 0, 0, 0, 0],
});
});
test("renameBus with duplicated name", () => {

@ -56,7 +56,14 @@ export const changeBusData = (
export const deleteBus = (bus: string, scenario: UnitCommitmentScenario) => {
const { [bus]: _, ...newBuses } = scenario.Buses;
return { ...scenario, Buses: newBuses };
const newGenerators = { ...scenario.Generators };
// Update generators
for (const genName in scenario.Generators) {
let gen = scenario.Generators[genName]!;
if (gen["Bus"] === bus) delete newGenerators[genName];
}
return { ...scenario, Buses: newBuses, Generators: newGenerators };
};
export const renameBus = (
@ -66,5 +73,14 @@ export const renameBus = (
): [UnitCommitmentScenario, ValidationError | null] => {
const [newBuses, err] = renameItemInObject(oldName, newName, scenario.Buses);
if (err) return [scenario, err];
return [{ ...scenario, Buses: newBuses }, null];
// Update generators
const newGenerators = { ...scenario.Generators };
for (const genName in scenario.Generators) {
let gen = newGenerators[genName]!;
if (gen["Bus"] === oldName) {
newGenerators[genName] = { ...gen, Bus: newName };
}
}
return [{ ...scenario, Buses: newBuses, Generators: newGenerators }, null];
};

@ -40,7 +40,9 @@ export const generateUniqueName = (container: any, prefix: string): string => {
return name;
};
const parseNumber = (valueStr: string): [number, ValidationError | null] => {
export const parseNumber = (
valueStr: string,
): [number, ValidationError | null] => {
const valueFloat = parseFloat(valueStr);
if (isNaN(valueFloat)) {
return [0, { message: `"${valueStr}" is not a valid number` }];

Loading…
Cancel
Save