You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
4.2 KiB
173 lines
4.2 KiB
import { toEffectRaw, type Effect, type EffectRaw, fromEffectRaw } from "./assignment"
|
|
|
|
export default interface Script {
|
|
name: string
|
|
lines: ScriptLine[]
|
|
}
|
|
|
|
type ScriptLineEditableData = ScriptLineIf & ScriptLineAssign & ScriptLineSet & ScriptLineSelect
|
|
|
|
export interface ScriptLineEditable {
|
|
kind: "if" | "assign" | "set" | "select"
|
|
condition: Required<ScriptCondition>
|
|
effect: EffectRaw
|
|
matchKind: "all" | "name" | "role" | "raw"
|
|
matchValue: string
|
|
scope: string
|
|
key: string
|
|
value: string
|
|
then: ScriptLineEditable[]
|
|
else: ScriptLineEditable[]
|
|
}
|
|
|
|
export type ScriptLine =
|
|
| { if: ScriptLineIf }
|
|
| { assign: ScriptLineAssign }
|
|
| { set: ScriptLineSet }
|
|
| { select: ScriptLineSelect }
|
|
|
|
export interface ScriptLineIf {
|
|
condition: ScriptCondition
|
|
then: ScriptLine[]
|
|
else: ScriptLine[]
|
|
}
|
|
|
|
export interface ScriptCondition {
|
|
scope: string
|
|
key: string
|
|
op: string
|
|
value?: string
|
|
not?: boolean
|
|
}
|
|
|
|
export interface ScriptLineAssign {
|
|
match: string
|
|
effect: Effect
|
|
}
|
|
|
|
export interface ScriptLineSet {
|
|
scope: string
|
|
key: string
|
|
value: string
|
|
}
|
|
|
|
export interface ScriptLineAssign {
|
|
match: string
|
|
effect: Effect
|
|
}
|
|
|
|
export interface ScriptLineSelect {
|
|
match: string
|
|
then: ScriptLine[]
|
|
}
|
|
|
|
export function fromEditableScriptLine(line: ScriptLineEditable): ScriptLine {
|
|
switch (line.kind) {
|
|
case "if": return {
|
|
if: {
|
|
condition: line.condition,
|
|
then: line.then.map(fromEditableScriptLine),
|
|
else: line.else.map(fromEditableScriptLine),
|
|
}
|
|
};
|
|
case "assign": return {
|
|
assign: {
|
|
match: fromMatchKindValue(line),
|
|
effect: fromEffectRaw(line.effect),
|
|
}
|
|
}
|
|
case "select": return {
|
|
select: {
|
|
match: fromMatchKindValue(line),
|
|
then: line.then.map(fromEditableScriptLine),
|
|
}
|
|
}
|
|
case "set": return {
|
|
set: {
|
|
key: line.key,
|
|
scope: line.scope,
|
|
value: line.value,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export function toEditableScriptLine(line: ScriptLine): ScriptLineEditable {
|
|
const base = emptyEditable();
|
|
|
|
if ("assign" in line) {
|
|
base.kind = "assign";
|
|
base.effect = toEffectRaw(line.assign.effect);
|
|
Object.assign(base, toMatchKindValue(line.assign.match));
|
|
} else if ("if" in line) {
|
|
base.kind = "if";
|
|
base.condition = {
|
|
...line.if.condition,
|
|
not: line.if.condition.not || false,
|
|
value: line.if.condition.value || "",
|
|
};
|
|
base.then = line.if.then.map(toEditableScriptLine);
|
|
base.else = line.if.else.map(toEditableScriptLine);
|
|
} else if ("select" in line) {
|
|
base.kind = "select";
|
|
Object.assign(base, toMatchKindValue(line.select.match));
|
|
base.then = line.select.then.map(toEditableScriptLine);
|
|
} else if ("set" in line) {
|
|
base.kind = "set";
|
|
base.key = line.set.key
|
|
base.scope = line.set.scope
|
|
base.value = line.set.value
|
|
}
|
|
|
|
return base;
|
|
}
|
|
|
|
function toMatchKindValue(match: string): { matchKind: "all" | "name" | "role" | "raw", matchValue: string } {
|
|
if (match.startsWith("lucifer:name:")) {
|
|
return { matchKind: "name", matchValue: match.slice("lucifer:name:".length) };
|
|
} else if (match.startsWith("lucifer:role:")) {
|
|
return { matchKind: "role", matchValue: match.slice("lucifer:role:".length) };
|
|
} else if (match === "*") {
|
|
return { matchKind: "all", matchValue: "*" };
|
|
} else {
|
|
return { matchKind: "raw", matchValue: match }
|
|
}
|
|
}
|
|
|
|
function fromMatchKindValue({matchKind, matchValue }: { matchKind: "all" | "name" | "role" | "raw", matchValue: string }): string {
|
|
switch (matchKind) {
|
|
case "name": return `lucifer:name:${matchValue}`;
|
|
case "role": return `lucifer:role:${matchValue}`;
|
|
case "all": return "*";
|
|
case "raw": return matchValue;
|
|
}
|
|
}
|
|
|
|
function emptyEditable(): ScriptLineEditable {
|
|
return {
|
|
condition: {
|
|
key: "",
|
|
op: "add",
|
|
scope: "global",
|
|
not: false,
|
|
value: "",
|
|
},
|
|
effect: toEffectRaw({
|
|
solid: {
|
|
states: [
|
|
{color: null, intensity: null, power: null, temperature: null}
|
|
],
|
|
interleave: 0,
|
|
animationMs: 0,
|
|
}
|
|
}),
|
|
key: "",
|
|
kind: "assign",
|
|
matchKind: "name",
|
|
matchValue: "*",
|
|
scope: "match",
|
|
value: "",
|
|
then: [],
|
|
else: [],
|
|
}
|
|
}
|