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

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: [],
}
}