Dynamische Merkmale

Motivation

Merkmale dienen dazu Komponenten zu charakterisieren. Im Allgemeinen werden Merkmale durch konkrete Werte ausgeprägt, die durch externe Quellen, meinst manuelle Eingaben, gespeist werden. Die Werte von Merkmalen können zeitlich variieren, wobei diese Information ebenfalls explizit durch Eingaben eingebracht werden.

Dynamische Merkmale sind eine Weiterentwicklung, bei der sich der konkrete Wert eines Merkmals in Abhängigkeit mehreren anderen Umgebungsfaktoren ergibt, bzw. von diesen abgeleitet wird.

Dies kann beispielsweise dann zur Anwendung kommen, wenn mehr als eine Ausgangsbedingung erfüllt sein muss, um eine bestimmte Einstufung zu erreichen. Wenn für die Einordnung einer Messstelle in einen steuerlichen Paragraphen neben den Vorliegen einer Genehmigung auch eine Mindestleistung gegeben sein muss, damit die steuerliche Bewertung erfolgen kann. Entfällt einer der Rahmenbedinungen, muss die steuerliche Bewertung automatisch angepasst werden.

Signale als Grundlage

Dynamische Merkmale werden wie generell alle Merkmale als Signal abgebildet.

debug("HELLO DYNAMIC TYPE TEST #{meterlocation}");
// der Eigentümer der Messstelle wird ermittelt
var user = meterlocation.user();
// der Verwendungszweck der Messstelle wird ermittelt
var purps = DB.getMarketPartnerPurposes({user});

// Hilfsfunktion zum Abfragen des benötigten Verwendungszwecks
function fetchStatus(name) {
	var purp = purps.filter(x => x.name()==name)[0];	
	// Wenn Verwednungszweck nicht vorhanden dann null
	if(purp == null) return null;
	// Wenn vorhanden, dann Rückgabe des Objektes
	var functionStatus = meterlocation.functionStatus(purp);
	return functionStatus;
}

// "Map String (Sig v) -> Sig (Map String v)"
// Zusammenführen (joinen) meherer Signale
function zip(sigs) {
    var result = StepSignalStart({startValue:{}, samples:[]});
    for(var {key,value} in sigs) {
		if(value == null) continue; 
        result = result.pointwise(value, (x,y) => {
            var r = {...x};
            r[key] = y;
            return r;
        });
    }
    return result;
}

var preEnv = {};

// Zunächst mal nur für Strom
// Aufstellung der benötigten Verwendungszwecke
var used = ["STBG-STROM-STATUS", "PV-STROM-ERLAUBNIS", "KWK-STROM-ERLAUBNIS"];

for(var name in used) {
	// Abfrage des benötigten Status (siehe Funktion weiter oben)
	var here = fetchStatus(name);	
	if(here != null) {
		// Einfügen des Verwendungszweckes in ein Dictionary `preEnv`
		preEnv[name] = here;
	} else {
		debug("Status für #{name} nicht gefunden.");
	}
}

// Für das eindeutige Setzen des dynamischen Merkmals ist die
// zusätzliche Kennzeichnungen über weiteres Merkmal "USECASE"
// erforderlich.
// Dieses Merkmal kennzeichnet über den Verwendungszweck hinaus
// die Nutzungsart der Messstelle.
// Nutzungsarten:
//  - OWN - Eigenverbrauch
//  - GENERATION - erzeugte Menge
//  - GRID - Abgabe an das Netz
// Es gibt derzeit: "OWN", "GENERATION", "GRID"
var nutzungsart = DB.flexibleProperty({
	meteringCode: meterlocation.meteringCode(),
	keyName: "USECASE"
});

// Ermittlung der Nutzungsart Messstelle 
if(nutzungsart != null) {
	preEnv.nutzungsart = nutzungsart.createStringSignal();
} else {
	// default?
	debug("Nutzungsart nicht gefunden. Nehme OWN an");
	preEnv.nutzungsart = StepSignalStart({startValue:"OWN", samples:[]});
}

// Es wird die Nennleistung der Messstelle ermittelt
// (felxibles Merkmal)
var nennLeistung = DB.flexibleProperty({
	meteringCode: meterlocation.meteringCode() ?? meterlocation.marketLocation(),
	keyName: "KWK_M_LEISTUNG"
});

if(nennLeistung != null) {
	var tmp = nennLeistung.createNumericSignal();
	// Kopie anfertigen, da createNumericSignal ein StepSignalStartOfDoubleObject ergibt.
	var startValue = tmp.startValue();
	var samples = [];
	for(var i in range(tmp.size())) {
		samples.push(tmp[i]);
	}
	preEnv.nennLeistung = StepSignalStart({startValue, samples});
} else {
	// default?
	debug("Nennleistung nicht gefunden, nehme 0 an");
	preEnv.nennLeistung = StepSignalStart({startValue:0, samples: []});
}

debug({preEnv});

var env = zip(preEnv);

debug({env});


var result = env.pointwise(vals => {
	if (vals["STBG-STROM-STATUS"]) {
		return switch(vals.nutzungsart) {
			string "OWN" => "VALUE1";
			string "GENERATION" => "VALUE2";
			string "GRID" => "VALUE3";
			_ => "VALUE0";
		};
	} else if (vals["PV-STROM-ERLAUBNIS"]) {
		// ...
	} else if (vals["KWK-STROM-ERLAUBNIS"]) {
		return switch(vals.nutzungsart) {			
			// ??:
			string "OWN" => "VALUE1";
			// Einspeisung:
			string "GENERATION" => vals.nennLeistung <= 2000 ? "VALUE1" : "VALUE2";
			// Ausspeisung:
			string "GRID" => vals.nennLeistung > 2000 ? "VALUE3" : "VALUE4";

			_ => "VALUE0";
		};
	}
	return "??";
});

return result;
/* vereinfachter Test für ein funktional generiertes Markmal
return StepSignalStart(
	{
    	startValue: "VALUE1",
    	samples: [
        	{
				date: Date.of(70,0,1),
				value: "VALUE2"
			},
        	{
				date: Date.of(124,6,2),
				value: "VALUE3"
			}
    	]
	}
);
*/