/**
* Command classes for QubecTalk UI translator.
*
* Provides command class definitions for substance operations
* including basic commands, lifecycle commands (retire, recharge),
* policy commands (recycle, replace, assume, limit), and
* compatibility markers.
*
* @license BSD, see LICENSE.md
*/
import {formatEngineNumber} from "ui_translator_util";
/**
* Command with type, target, value and duration.
*
* Command such as a set command with a specified type, target, value and
* duration.
*/
class Command {
/**
* Create a new Command.
*
* @param {string} typeName - Type of the command.
* @param {string} target - Target of the command (e.g., "domestic", "import", "export",
* "equipment", "priorEquipment", "bank", "priorBank", "sales").
* Note: "bank" and "priorBank" are synonyms for "equipment" and
* "priorEquipment" respectively.
* @param {EngineNumber} value - Value for the command.
* @param {YearMatcher} duration - Duration for the command.
*/
constructor(typeName, target, value, duration) {
const self = this;
self._typeName = typeName;
self._target = target;
self._value = value;
self._duration = duration;
}
/**
* Get the type name of this command.
*
* @returns {string} The command type name (e.g. "change", "retire", "setVal", etc).
*/
getTypeName() {
const self = this;
return self._typeName;
}
/**
* Get the target of this command.
*
* @returns {string} The target name (e.g., "domestic", "import", "equipment", "bank", etc).
* Note: "bank" and "priorBank" are accepted as synonyms for "equipment"
* and "priorEquipment".
*/
getTarget() {
const self = this;
return self._target;
}
/**
* Get the value associated with this command.
*
* @returns {EngineNumber} The command's value with units.
*/
getValue() {
const self = this;
return self._value;
}
/**
* Get the duration for which this command applies.
*
* @returns {YearMatcher} The duration specification, or null for all years.
*/
getDuration() {
const self = this;
return self._duration;
}
/**
* Check if this command is compatible with UI editing.
*
* @returns {boolean} Always returns true as basic commands are UI-compatible.
*/
getIsCompatible() {
const self = this;
return true;
}
}
/**
* Retire command with optional replacement capability.
*
* Retire command with value, duration, and withReplacement flag indicating
* whether retired equipment should be replaced to maintain population.
*/
class RetireCommand {
/**
* Create a new RetireCommand.
*
* @param {EngineNumber} value - Retirement rate/amount.
* @param {YearMatcher|null} duration - Duration specification or null for all years.
* @param {boolean} withReplacement - Whether to maintain equipment via replacement.
*/
constructor(value, duration, withReplacement) {
const self = this;
self._value = value;
self._duration = duration;
self._withReplacement = withReplacement;
}
/**
* Get the type name of this command.
*
* @returns {string} Always returns "retire".
*/
getTypeName() {
const self = this;
return "retire";
}
/**
* Get the value associated with this command.
*
* @returns {EngineNumber} The retirement rate/amount with units.
*/
getValue() {
const self = this;
return self._value;
}
/**
* Get the duration for which this command applies.
*
* @returns {YearMatcher|null} The duration specification, or null for all years.
*/
getDuration() {
const self = this;
return self._duration;
}
/**
* Get whether this retire command uses replacement.
*
* @returns {boolean} True if retire should maintain equipment via replacement.
*/
getWithReplacement() {
const self = this;
return self._withReplacement;
}
/**
* Check if this command is compatible with UI editing.
*
* @returns {boolean} Always returns true as retire commands are UI-compatible.
*/
getIsCompatible() {
const self = this;
return true;
}
}
/**
* Assume command with mode for sales assumptions.
*
* Assume command with target stream, mode, and duration for specifying
* sales behavior assumptions.
*/
class AssumeCommand {
/**
* Create a new AssumeCommand.
*
* @param {string} mode - The assumption mode: "no", "only recharge", or "continued".
* @param {string} stream - The target stream (e.g., "sales").
* @param {YearMatcher|null} duration - Duration specification or null for all years.
*/
constructor(mode, stream, duration) {
const self = this;
self._mode = mode;
self._stream = stream;
self._duration = duration;
}
/**
* Get the type name of this command.
*
* @returns {string} Always returns "assume".
*/
getTypeName() {
const self = this;
return "assume";
}
/**
* Get the assumption mode.
*
* @returns {string} The mode: "no", "only recharge", or "continued".
*/
getMode() {
const self = this;
return self._mode;
}
/**
* Get the target stream.
*
* @returns {string} The target stream name (e.g., "sales").
*/
getStream() {
const self = this;
return self._stream;
}
/**
* Get the duration for which this command applies.
*
* @returns {YearMatcher|null} The duration specification, or null for all years.
*/
getDuration() {
const self = this;
return self._duration;
}
/**
* Check if this command is compatible with UI editing.
*
* @returns {boolean} Always returns true as assume commands are UI-compatible.
*/
getIsCompatible() {
const self = this;
return true;
}
}
/**
* Limit command with displacement capability.
*/
class LimitCommand {
/**
* Create a new LimitCommand.
*
* @param {string} typeName - Type of limit (cap/floor).
* @param {string} target - Target of the limit.
* @param {EngineNumber} value - Limit value.
* @param {YearMatcher} duration - Duration of limit.
* @param {string} displacing - Substance/stream being displaced.
* @param {string} displacingType - Type of displacement ("", "by volume", "by units").
*/
constructor(typeName, target, value, duration, displacing, displacingType) {
const self = this;
self._typeName = typeName;
self._target = target;
self._value = value;
self._duration = duration;
self._displacing = displacing;
self._displacingType = displacingType;
}
/**
* Get the type name of this limit command.
*
* @returns {string} The command type ("cap" or "floor").
*/
getTypeName() {
const self = this;
return self._typeName;
}
/**
* Get the target of this limit command.
*
* @returns {string} The target name (e.g. "domestic", "import", etc).
*/
getTarget() {
const self = this;
return self._target;
}
/**
* Get the value associated with this limit.
*
* @returns {EngineNumber} The limit value with units.
*/
getValue() {
const self = this;
return self._value;
}
/**
* Get the duration for which this limit applies.
*
* @returns {YearMatcher} The duration specification, or null for all years.
*/
getDuration() {
const self = this;
return self._duration;
}
/**
* Get the substance being displaced by this limit.
*
* @returns {string|null} Name of substance being displaced, or null if none.
*/
getDisplacing() {
const self = this;
return self._displacing;
}
/**
* Get the type of displacement.
*
* @returns {string} The displacement type ("", "by volume", "by units").
*/
getDisplacingType() {
const self = this;
return self._displacingType;
}
/**
* Check if this limit command is compatible with UI editing.
*
* @returns {boolean} Always returns true as limit commands are UI-compatible.
*/
getIsCompatible() {
const self = this;
return true;
}
}
/**
* Recharge command with duration capability.
*/
class RechargeCommand {
/**
* Create a new RechargeCommand.
*
* @param {EngineNumber} populationEngineNumber - Population amount and units to recharge.
* @param {EngineNumber} volumeEngineNumber - Volume per unit amount and units.
* @param {YearMatcher|null} duration - Duration specification or null for all years.
*/
constructor(populationEngineNumber, volumeEngineNumber, duration) {
const self = this;
self._populationEngineNumber = populationEngineNumber;
self._volumeEngineNumber = volumeEngineNumber;
self._duration = duration;
}
/**
* Get the population EngineNumber.
*
* @returns {EngineNumber} The population amount and units.
*/
getPopulationEngineNumber() {
const self = this;
return self._populationEngineNumber;
}
/**
* Get the volume EngineNumber.
*
* @returns {EngineNumber} The volume per unit amount and units.
*/
getVolumeEngineNumber() {
const self = this;
return self._volumeEngineNumber;
}
/**
* Get the target for this recharge command (population - Command interface compatibility).
*
* @returns {EngineNumber} The population EngineNumber.
*/
getTarget() {
const self = this;
return self._populationEngineNumber;
}
/**
* Get the value for this recharge command (volume - Command interface compatibility).
*
* @returns {EngineNumber} The volume EngineNumber.
*/
getValue() {
const self = this;
return self._volumeEngineNumber;
}
/**
* Get the duration for which this recharge command applies.
*
* @returns {YearMatcher|null} The duration specification, or null for all years.
*/
getDuration() {
const self = this;
return self._duration;
}
/**
* Build the command string for this recharge with original number formatting preserved.
*
* @param {string} substance - The substance name (unused but kept for consistency).
* @returns {string} The generated recharge command.
*/
buildCommand(substance) {
const self = this;
const populationStr = formatEngineNumber(self._populationEngineNumber);
const volumeStr = formatEngineNumber(self._volumeEngineNumber);
const baseCommand = `recharge ${populationStr} with ${volumeStr}`;
let command = baseCommand;
if (self._duration) {
const start = self._duration.getStart();
const end = self._duration.getEnd();
if (start !== null && end !== null) {
if (start.equals(end)) {
command += ` during year ${start.getYearStr()}`;
} else {
command += ` during years ${start.getYearStr()} to ${end.getYearStr()}`;
}
} else if (start !== null) {
command += ` during years ${start.getYearStr()} to onwards`;
} else if (end !== null) {
command += ` during years beginning to ${end.getYearStr()}`;
}
}
return command;
}
/**
* Get the type name of this command.
*
* @returns {string} The command type name.
*/
getTypeName() {
const self = this;
return "recharge";
}
/**
* Check if this recharge command is compatible with UI editing.
*
* @returns {boolean} Always returns true as recharge commands are UI-compatible.
*/
getIsCompatible() {
const self = this;
return true;
}
}
/**
* Recycle command for substance recovery.
*/
class RecycleCommand {
/**
* Create a new RecycleCommand.
*
* @param {EngineNumber} target - Recovery amount and units.
* @param {EngineNumber} value - Reuse amount and units.
* @param {YearMatcher} duration - Duration of recovery.
* @param {string} stage - Recycling stage ("eol" or "recharge").
* @param {EngineNumber|string|null} induction - Induction amount, "default", or null for
* backward compatibility.
*/
constructor(target, value, duration, stage, induction = null) {
const self = this;
self._target = target;
self._value = value;
self._duration = duration;
self._stage = stage;
self._induction = induction;
}
/**
* Get the type name of this recycle command.
*
* @returns {string} Always returns "recycle".
*/
getTypeName() {
const self = this;
return "recycle";
}
/**
* Get the target (recovery amount) of this recycle command.
*
* @returns {EngineNumber} The recovery amount with units.
*/
getTarget() {
const self = this;
return self._target;
}
/**
* Get the value (reuse amount) associated with this recycle.
*
* @returns {EngineNumber} The reuse amount with units.
*/
getValue() {
const self = this;
return self._value;
}
/**
* Get the duration for which this recycle applies.
*
* @returns {YearMatcher} The duration specification, or null for all years.
*/
getDuration() {
const self = this;
return self._duration;
}
/**
* Get the recycling stage for this recycle command.
*
* @returns {string} The recycling stage ("eol" or "recharge").
*/
getStage() {
const self = this;
return self._stage;
}
/**
* Get the induction rate for this recycle command.
*
* @returns {EngineNumber|string|null} The induction amount, "default", or null if not specified.
*/
getInduction() {
const self = this;
return self._induction;
}
/**
* Check if this recycle command is compatible with UI editing.
*
* @returns {boolean} Always returns true as recycle commands are UI-compatible.
*/
getIsCompatible() {
const self = this;
return true;
}
}
/**
* Represent a command to replace one substance with another.
*/
class ReplaceCommand {
/**
* Create a new ReplaceCommand.
*
* @param {EngineNumber} volume - Volume to replace.
* @param {string} source - Source substance.
* @param {string} destination - Destination substance.
* @param {YearMatcher} duration - Duration of replacement.
*/
constructor(volume, source, destination, duration) {
const self = this;
self._volume = volume;
self._source = source;
self._destination = destination;
self._duration = duration;
}
/**
* Get the type name of this replace command.
*
* @returns {string} Always returns "replace".
*/
getTypeName() {
const self = this;
return "replace";
}
/**
* Get the volume to be replaced.
*
* @returns {EngineNumber} The volume with units.
*/
getVolume() {
const self = this;
return self._volume;
}
/**
* Get the source substance to replace from.
*
* @returns {string} Name of source substance.
*/
getSource() {
const self = this;
return self._source;
}
/**
* Get the destination substance to replace with.
*
* @returns {string} Name of destination substance.
*/
getDestination() {
const self = this;
return self._destination;
}
/**
* Get the duration for which this replacement applies.
*
* @returns {YearMatcher} The duration specification, or null for all years.
*/
getDuration() {
const self = this;
return self._duration;
}
/**
* Check if this replace command is compatible with UI editing.
*
* @returns {boolean} Always returns true as replace commands are UI-compatible.
*/
getIsCompatible() {
const self = this;
return true;
}
}
/**
* Command that is not compatible with the UI editor.
*/
class IncompatibleCommand {
/**
* Create a new incompatible command marker.
*
* @param {string} typeName - Type of incompatible command for reporting.
*/
constructor(typeName) {
const self = this;
self._typeName = typeName;
}
/**
* Get the type name of this incompatible command.
*
* @returns {string} Type name of the incompatible command.
*/
getTypeName() {
const self = this;
return self._typeName;
}
/**
* Check if this command is compatible with UI editing.
*
* @returns {boolean} Always returns false as this marks incompatibility.
*/
getIsCompatible() {
const self = this;
return false;
}
}
export {
AssumeCommand,
Command,
IncompatibleCommand,
LimitCommand,
RechargeCommand,
RecycleCommand,
ReplaceCommand,
RetireCommand,
};