Changeset - 9c2e1b5c16e9
[Not reviewed]
default
0 1 0
drewp@bigasterisk.com - 3 years ago 2022-06-01 06:39:58
drewp@bigasterisk.com
speed: don't redo uri string replace all the time
1 file changed with 6 insertions and 11 deletions:
0 comments (0 inline, 0 general)
light9/web/live/Effect.ts
Show inline comments
 
@@ -5,66 +5,62 @@ import { Patch, patchContainsPreds, patc
 
import { SyncedGraph } from "../SyncedGraph";
 

	
 
type Color = string;
 
export type ControlValue = number | Color | NamedNode;
 

	
 
const log = debug("effect");
 

	
 
function isUri(x: Term | number | string): x is NamedNode {
 
  return typeof x == "object" && x.termType == "NamedNode";
 
}
 

	
 
function valuePred(graph: SyncedGraph, attr: NamedNode): NamedNode {
 
  const U = graph.U();
 
  const scaledAttributeTypes = [U(":color"), U(":brightness"), U(":uv")];
 
  if (some(scaledAttributeTypes, (x: NamedNode) => attr.equals(x))) {
 
    return U(":scaledValue");
 
  } else {
 
    return U(":value");
 
  }
 
}
 

	
 
// effect settings data; r/w sync with the graph
 
export class Effect {
 
  private settings: Array<{ device: NamedNode; deviceAttr: NamedNode; setting: NamedNode; value: ControlValue }> = [];
 

	
 
  private ctxForEffect: NamedNode
 
  constructor(
 
    public graph: SyncedGraph,
 
    public uri: NamedNode,
 
    // called if the graph changes our values and not when the caller uses edit()
 
    private onValuesChanged: (values: void) => void
 
  ) {
 
    this.ctxForEffect = this.graph.Uri(this.uri.value.replace("light9.bigasterisk.com/effect", "light9.bigasterisk.com/show/dance2019/effect"));
 
    graph.runHandler(this.rebuildSettingsFromGraph.bind(this), `effect sync ${uri.value}`);
 
  }
 

	
 
  private ctxForEffect(): NamedNode {
 
    return this.graph.Uri(this.uri.value.replace("light9.bigasterisk.com/effect", "light9.bigasterisk.com/show/dance2019/effect"));
 
  }
 

	
 
  addNewEffectToGraph() {
 
    const U = this.graph.U();
 
    const ctx = this.ctxForEffect();
 
    const quad = (s: Quad_Subject, p: Quad_Predicate, o: Quad_Object) => this.graph.Quad(s, p, o, ctx);
 
    const quad = (s: Quad_Subject, p: Quad_Predicate, o: Quad_Object) => this.graph.Quad(s, p, o, this.ctxForEffect);
 

	
 
    const addQuads = [
 
      quad(this.uri, U("rdf:type"), U(":Effect")),
 
      quad(this.uri, U("rdfs:label"), this.graph.Literal(this.uri.value.replace(/.*\//, ""))),
 
      quad(this.uri, U(":publishAttr"), U(":strength")),
 
    ];
 
    const patch = { adds: addQuads, dels: [] } as Patch;
 
    log("init new effect", patch);
 
    this.settings = [];
 
    this.graph.applyAndSendPatch(patch);
 
  }
 

	
 
  rebuildSettingsFromGraph(patch?: Patch) {
 
    const U = this.graph.U();
 
    if (patch && !patchContainsPreds(patch, [U(":setting"), U(":device"), U(":deviceAttr")])) {
 
      // that's an approx list of preds , but it just means we'll miss some pathological settings edits
 
      //   return;
 
    }
 

	
 
    // log("syncFromGraph", this.uri);
 

	
 
    // this repeats work- it gathers all settings when really some values changed (and we might even know about them). maybe push the value-fetching into a secnod phase of the run, and have the 1st phase drop out early
 
    const newSettings = [];
 

	
 
@@ -128,71 +124,70 @@ export class Effect {
 
      if (existingSetting === null) {
 
        patchUpdate(result, this._addEffectSetting(device, deviceAttr, newValue));
 
      } else {
 
        patchUpdate(result, this._patchExistingEffectSetting(existingSetting, deviceAttr, newValue));
 
      }
 
    } else {
 
      if (existingSetting !== null) {
 
        patchUpdate(result, this._removeEffectSetting(existingSetting));
 
      }
 
    }
 
    return result;
 
  }
 

	
 
  shouldBeStored(deviceAttr: NamedNode, value: ControlValue | null): boolean {
 
    // this is a bug for zoom=0, since collector will default it to
 
    // stick at the last setting if we don't explicitly send the
 
    // 0. rx/ry similar though not the exact same deal because of
 
    // their remap.
 
    return value != null && value !== 0 && value !== "#000000";
 
  }
 

	
 
  _addEffectSetting(device: NamedNode, deviceAttr: NamedNode, value: ControlValue): Patch {
 
    log("  _addEffectSetting", deviceAttr.value, value);
 
    const U = (x: string) => this.graph.Uri(x);
 
    const ctx = this.ctxForEffect();
 
    const quad = (s: Quad_Subject, p: Quad_Predicate, o: Quad_Object) => this.graph.Quad(s, p, o, ctx);
 
    const quad = (s: Quad_Subject, p: Quad_Predicate, o: Quad_Object) => this.graph.Quad(s, p, o, this.ctxForEffect);
 
    if (!this.uri) throw new Error("effect unset");
 
    const setting = this.graph.nextNumberedResource(this.uri.value + "_set");
 

	
 
    const addQuads = [
 
      quad(this.uri, U(":setting"), setting),
 
      quad(setting, U(":device"), device),
 
      quad(setting, U(":deviceAttr"), deviceAttr),
 
      quad(setting, valuePred(this.graph, deviceAttr), this._nodeForValue(value)),
 
    ];
 
    const patch = { adds: addQuads, dels: [] } as Patch;
 
    log("  save", patch);
 
    this.settings.push({ device, deviceAttr, setting, value });
 
    return patch;
 
  }
 

	
 
  _patchExistingEffectSetting(effectSetting: NamedNode, deviceAttr: NamedNode, value: ControlValue): Patch {
 
    log("  patch existing", effectSetting.value);
 
    return this.graph.getObjectPatch(
 
      effectSetting, //
 
      valuePred(this.graph, deviceAttr),
 
      this._nodeForValue(value),
 
      this.ctxForEffect()
 
      this.ctxForEffect
 
    );
 
  }
 

	
 
  _removeEffectSetting(effectSetting: NamedNode): Patch {
 
    const U = (x: string) => this.graph.Uri(x);
 
    log("  _removeEffectSetting", effectSetting.value);
 
    const toDel = [this.graph.Quad(this.uri, U(":setting"), effectSetting, this.ctxForEffect())];
 
    const toDel = [this.graph.Quad(this.uri, U(":setting"), effectSetting, this.ctxForEffect)];
 
    for (let q of this.graph.subjectStatements(effectSetting)) {
 
      toDel.push(q);
 
    }
 
    return { dels: toDel, adds: [] };
 
  }
 

	
 
  _nodeForValue(value: ControlValue): NamedNode | Literal {
 
    if (value === null) {
 
      throw new Error("no value");
 
    }
 
    if (isUri(value)) {
 
      return value;
 
    }
 
    return this.graph.prettyLiteral(value);
 
  }
 
}
0 comments (0 inline, 0 general)