From afa6457f88a208a30f8d1114e63f199c7ea27aad Mon Sep 17 00:00:00 2001 From: Miika Alonen Date: Thu, 14 Dec 2023 21:48:46 +0200 Subject: [PATCH] Added cache method for generators and new logging method for chains --- package.json | 2 +- src/API.ts | 74 +++++++++++++++++++++++++++++++++-- src/KeyActions.ts | 9 +++++ src/Utils/Generic.ts | 4 +- src/classes/AbstractEvents.ts | 19 +++++++++ src/classes/ZPlayer.ts | 4 +- yarn.lock | 7 ++-- 7 files changed, 107 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index f9f5c0a..c14e657 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "tone": "^14.8.49", "unique-names-generator": "^4.7.1", "vite-plugin-markdown": "^2.1.0", - "zifferjs": "^0.0.54", + "zifferjs": "link:../zifferjs", "zyklus": "^0.1.4", "zzfx": "^1.2.0" } diff --git a/src/API.ts b/src/API.ts index c33509b..3e36155 100644 --- a/src/API.ts +++ b/src/API.ts @@ -13,6 +13,7 @@ import { SoundEvent } from "./classes/SoundEvent"; import { MidiEvent, MidiParams } from "./classes/MidiEvent"; import { LRUCache } from "lru-cache"; import { InputOptions, Player } from "./classes/ZPlayer"; +import { isGenerator, isGeneratorFunction } from "./Utils/Generic"; import { loadUniverse, openUniverseModal, @@ -87,6 +88,7 @@ export class UserAPI { public currentSeed: string | undefined = undefined; public localSeeds = new Map(); public patternCache = new LRUCache({ max: 1000, ttl: 1000 * 60 * 5 }); + public tempCache = new LRUCache({ max: 1000, ttl: 1000 * 60 * 5 }); public invalidPatterns: {[key: string]: boolean} = {}; public cueTimes: { [key: string]: number } = {}; private errorTimeoutID: number = 0; @@ -701,7 +703,7 @@ export class UserAPI { }; // ============================================================= - // Ziffers related functions + // Cache functions // ============================================================= public generateCacheKey = (...args: any[]): string => { @@ -712,10 +714,74 @@ export class UserAPI { this.patternCache.forEach((player) => (player as Player).reset()); }; + public clearPatternCache = (): void => { + this.patternCache.clear(); + } + public removePatternFromCache = (id: string): void => { this.patternCache.delete(id); }; + maybeToNumber = (something: any): number|any => { + // If something is BigInt + if(something && typeof something === "bigint") { + return Number(something); + } else { + return something; + } + } + + cache = (key: string, value: any) => { + /** + * Gets or sets a value in the cache. + * + * @param key - The key of the value to get or set + * @param value - The value to set + * @returns The value of the key + */ + if(value !== undefined) { + if(isGenerator(value)) { + if(this.patternCache.has(key)) { + const cachedValue = (this.patternCache.get(key) as Generator).next().value + if(!cachedValue) { + const generator = value as unknown as Generator + this.patternCache.set(key, generator); + return this.maybeToNumber(generator.next().value); + } + return this.maybeToNumber(cachedValue); + } else { + const generator = value as unknown as Generator + this.patternCache.set(key, generator); + return this.maybeToNumber(generator.next().value); + } + } else if(isGeneratorFunction(value)) { + if(this.patternCache.has(key)) { + const cachedValue = (this.patternCache.get(key) as Generator).next().value; + if(cachedValue) { + return this.maybeToNumber(cachedValue); + } else { + const generator = value(); + this.patternCache.set(key, generator); + return this.maybeToNumber(generator.next().value); + } + } else { + const generator = value(); + this.patternCache.set(key, generator); + return this.maybeToNumber(generator.next().value); + } + } else { + this.patternCache.set(key, value); + return this.maybeToNumber(value); + } + } else { + return this.maybeToNumber(this.patternCache.get(key)); + } + } + + // ============================================================= + // Ziffers related functions + // ============================================================= + public z = ( input: string | Generator, options: InputOptions = {}, @@ -739,11 +805,11 @@ export class UserAPI { } } - if (validSyntax && (!player || replace)) { + if ((typeof input !== "string" || validSyntax) && (!player || replace)) { const newPlayer = new Player(input, options, this.app, zid); if(newPlayer.isValid()) { player = newPlayer - this.app.api.patternCache.set(key, player); + this.patternCache.set(key, player); } else if(typeof input === "string") { this.invalidPatterns[input] = true; } @@ -752,7 +818,7 @@ export class UserAPI { if(player) { if(player.atTheBeginning()) { - if(!validSyntax) this.app.api.log(`Invalid syntax: ${input}`); + if(typeof input === "string" && !validSyntax) this.app.api.log(`Invalid syntax: ${input}`); } if (player.ziffers.generator && player.ziffers.generatorDone) { diff --git a/src/KeyActions.ts b/src/KeyActions.ts index 76e38cc..5b68a56 100644 --- a/src/KeyActions.ts +++ b/src/KeyActions.ts @@ -109,6 +109,15 @@ export const registerOnKeyDown = (app: Editor) => { app.flashBackground("#404040", 200); } + // Force eval with clearing cache + if (event.ctrlKey && event.shiftKey && (event.key === "Backspace" || event.key === "Delete")) { + event.preventDefault(); + app.api.clearPatternCache(); + app.currentFile().candidate = app.view.state.doc.toString(); + tryEvaluate(app, app.currentFile()); + app.flashBackground("#404040", 200); + } + // app is the modal to switch between universes if (event.ctrlKey && event.key === "b") { event.preventDefault(); diff --git a/src/Utils/Generic.ts b/src/Utils/Generic.ts index fd1cfe7..ee69e4c 100644 --- a/src/Utils/Generic.ts +++ b/src/Utils/Generic.ts @@ -87,4 +87,6 @@ export function filterObject( } export const GeneratorType = (function*(){yield undefined;}).constructor; -export const GeneratorIteratorType = (function*(){yield undefined;}).prototype.constructor; \ No newline at end of file +export const GeneratorIteratorType = (function*(){yield undefined;}).prototype.constructor; +export const isGenerator = (v:any) => Object.prototype.toString.call(v) === '[object Generator]'; +export const isGeneratorFunction = (v:any) => Object.prototype.toString.call(v) === '[object GeneratorFunction]'; \ No newline at end of file diff --git a/src/classes/AbstractEvents.ts b/src/classes/AbstractEvents.ts index 057cbf2..efbe666 100644 --- a/src/classes/AbstractEvents.ts +++ b/src/classes/AbstractEvents.ts @@ -444,6 +444,25 @@ export abstract class AudibleEvent extends AbstractEvent { } }; + public log = (key: string|string[], ...args: string[]) => { + /* + * Log values from values using log() + * + * @param key - The key(s) to log + * @returns this and logs the values + */ + if (typeof key === "string") { + if(args && args.length > 0) { + this.app.api.log([key, ...args].map((k) => this.values[k])); + } else { + this.app.api.log(this.values[key]); + } + } else { + this.app.api.log([...key, ...args].map((k) => this.values[k])); + } + return this; + } + freq = (value: number | number[], ...kwargs: number[]): this => { /* * This function is used to set the frequency of the Event. diff --git a/src/classes/ZPlayer.ts b/src/classes/ZPlayer.ts index efdb6d2..7dab35a 100644 --- a/src/classes/ZPlayer.ts +++ b/src/classes/ZPlayer.ts @@ -5,7 +5,7 @@ import { SkipEvent } from "./SkipEvent"; import { SoundEvent, SoundParams } from "./SoundEvent"; import { MidiEvent, MidiParams } from "./MidiEvent"; import { RestEvent } from "./RestEvent"; -import { GeneratorIteratorType, GeneratorType, arrayOfObjectsToObjectWithArrays } from "../Utils/Generic"; +import { arrayOfObjectsToObjectWithArrays, isGenerator } from "../Utils/Generic"; import { TonnetzSpaces } from "zifferjs/src/tonnetz"; export type InputOptions = { [key: string]: string | number }; @@ -40,7 +40,7 @@ export class Player extends AbstractEvent { } else if (typeof input === "number") { this.input = input; this.ziffers = Ziffers.fromNumber(input, options); - } else if (input.constructor === GeneratorType || input.constructor === GeneratorIteratorType){ + } else if (isGenerator(input)) { this.ziffers = Ziffers.fromGenerator(input, options); this.input = this.ziffers.input; } else { diff --git a/yarn.lock b/yarn.lock index e7de0e7..18b82c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4028,10 +4028,9 @@ yaml@^2.1.1: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== -zifferjs@^0.0.54: - version "0.0.54" - resolved "https://registry.yarnpkg.com/zifferjs/-/zifferjs-0.0.54.tgz#2dd4b43820f85d797c13dd35d933476ecacdb146" - integrity sha512-vo1I12VvW4yFdVJTVnrfOxeOpWq7tIMZ67BfXxcK0t9GveLi+3GrF1zjowq8WCDssVgw+lQHEjdGVhO5FbK3RA== +"zifferjs@link:../zifferjs": + version "0.0.0" + uid "" zyklus@^0.1.4: version "0.1.4"