Changeset - 9324fc8285ad
[Not reviewed]
default
0 3 0
drewp@bigasterisk.com - 3 years ago 2022-05-31 06:21:50
drewp@bigasterisk.com
Effect repairs duplicate :settings edges when it finds them
3 files changed with 24 insertions and 11 deletions:
0 comments (0 inline, 0 general)
light9/web/live/Effect.ts
Show inline comments
 
import debug from "debug";
 
import { Literal, NamedNode, Quad_Object, Quad_Predicate, Quad_Subject, Term } from "n3";
 
import { some } from "underscore";
 
import { Patch, patchContainsPreds } from "../patch";
 
import { Patch, patchContainsPreds, patchUpdate } from "../patch";
 
import { SyncedGraph } from "../SyncedGraph";
 

	
 
type Color = string;
 
@@ -60,13 +60,16 @@ export class Effect {
 
    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;
 
      //   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 = [];
 

	
 
    const seenDevAttrPairs: Set<string> = new Set();
 

	
 
    for (let setting of Array.from(this.graph.objects(this.uri, U(":setting")))) {
 
      //   log(`  setting ${setting.value}`);
 
      if (!isUri(setting)) throw new Error();
 
@@ -87,7 +90,7 @@ export class Effect {
 
          value = this.graph.stringValue(setting, pred); // this may find multi values and throw
 
        }
 
      }
 
    //   log(`change: graph contains ${deviceAttr.value} ${value}`);
 
      //   log(`change: graph contains ${deviceAttr.value} ${value}`);
 

	
 
      newSettings.push({ device, deviceAttr, setting, value });
 
    }
 
@@ -109,10 +112,13 @@ export class Effect {
 
  edit(device: NamedNode, deviceAttr: NamedNode, newValue: ControlValue | null): Patch {
 
    log(`edit: value=${newValue}`);
 
    let existingSetting: NamedNode | null = null;
 
    let result = { adds: [], dels: [] };
 
    for (let s of this.settings) {
 
      if (device.equals(s.device) && deviceAttr.equals(s.deviceAttr)) {
 
        if (existingSetting !== null) {
 
          throw new Error(`${this.uri.value} had two settings for ${device.value} - ${deviceAttr.value}`);
 
          // this is corrupt. There was only supposed to be one setting per (dev,attr) pair. But we can fix it because we're going to update existingSetting to the user's requested value.
 
          log(`${this.uri.value} had two settings for ${device.value} - ${deviceAttr.value} - deleting ${s.setting}`);
 
          patchUpdate(result,  this._removeEffectSetting(s.setting));
 
        }
 
        existingSetting = s.setting;
 
      }
 
@@ -120,16 +126,16 @@ export class Effect {
 

	
 
    if (newValue !== null && this.shouldBeStored(deviceAttr, newValue)) {
 
      if (existingSetting === null) {
 
        return this._addEffectSetting(device, deviceAttr, newValue);
 
        patchUpdate(result, this._addEffectSetting(device, deviceAttr, newValue));
 
      } else {
 
        return this._patchExistingEffectSetting(existingSetting, deviceAttr, newValue);
 
        patchUpdate(result, this._patchExistingEffectSetting(existingSetting, deviceAttr, newValue));
 
      }
 
    } else {
 
      if (existingSetting !== null) {
 
        return this._removeEffectSetting(existingSetting);
 
        patchUpdate(result, this._removeEffectSetting(existingSetting));
 
      }
 
    }
 
    return { adds: [], dels: [] };
 
    return result;
 
  }
 

	
 
  shouldBeStored(deviceAttr: NamedNode, value: ControlValue | null): boolean {
light9/web/live/Light9LiveControls.ts
Show inline comments
 
@@ -7,8 +7,8 @@ import { Patch, patchContainsPreds } fro
 
import { getTopGraph } from "../RdfdbSyncedGraph";
 
import { SyncedGraph } from "../SyncedGraph";
 
import { GraphToControls } from "./GraphToControls";
 
export { EditChoice } from "../EditChoice";
 
export { Light9DeviceControl as Light9LiveDeviceControl } from "./Light9DeviceControl";
 
export { EditChoice } from "../EditChoice";
 
const log = debug("controls");
 

	
 
@customElement("light9-live-controls")
light9/web/patch.ts
Show inline comments
 
import * as async from "async";
 
import debug from "debug";
 
import * as async from "async";
 
import { Writer, Parser, Quad, NamedNode } from "n3";
 
import { NamedNode, Parser, Quad, Writer } from "n3";
 
const log = debug("patch");
 

	
 
export interface Patch {
 
@@ -14,6 +14,12 @@ interface SyncgraphPatchMessage {
 
  patch: { adds: string; deletes: string };
 
}
 

	
 
export function patchUpdate(p1: Patch, p2: Patch): void {
 
  // this is approx, since it doesnt handle matching existing quads.
 
  p1.adds = p1.adds.concat(p2.adds);
 
  p1.dels = p1.dels.concat(p2.dels);
 
}
 

	
 
export function patchSizeSummary(patch: Patch) {
 
  return "-" + patch.dels.length + " +" + patch.adds.length;
 
}
 
@@ -43,6 +49,7 @@ export function parseJsonPatch(input: Sy
 
    });
 
  };
 

	
 
  // todo: is it faster to run them in series? might be
 
  return async.parallel([parseAdds, parseDels], (err: any) => cb(patch));
 
}
 

	
0 comments (0 inline, 0 general)