Skip to content

Instantly share code, notes, and snippets.

@amiika
Created August 16, 2023 12:10
Show Gist options
  • Save amiika/44f6450f7bc42d5d60f306c4c5ada604 to your computer and use it in GitHub Desktop.
Save amiika/44f6450f7bc42d5d60f306c4c5ada604 to your computer and use it in GitHub Desktop.
Typescript linked list with number references for live coding method chaining
// Simple pattern class creating pattern from list of values
export class Pattern {
events: Event[];
_current : number | undefined = undefined;
constructor(values: number[]) {
this.events = values.map((value, index) => new Event(value));
this.buildLinks();
}
// Create links cyclic links between events
buildLinks(): void {
this.events.forEach((event, index) => {
event._next = index + 1 < this.events.length ? index + 1 : 0;
});
}
// Get the current event for this pattern
next(): Event {
if(this._current !== undefined) {
// Get current event
const currentEvent = this.events[this._current % this.events.length];
// Set currentEvent undefined (If you dont want to mofify modified events)
if(currentEvent.modifiedEvent) currentEvent.modifiedEvent = undefined;
// Set next event index
this._current = this._current + 1 < this.events.length ? this._current + 1 : 0;
} else {
// Set current event index when starting
this._current = 0;
}
// Get next event
const nextEvent = this.events[this._current % this.events.length];
return nextEvent;
}
peek(): Event {
return this.events[this._current || 0];
}
hasStarted(): boolean {
return this._current !== undefined;
}
}
// Simple event class with simple numerical value and link to next event
export class Event {
_next!: number;
_value: number;
// Used to store a modified version of the event
modifiedEvent: Event | undefined = undefined;
constructor(value: number) {
this._value = value;
}
get value(): number {
if(this.modifiedEvent) return this.modifiedEvent._value;
return this._value;
}
add(value: number): Event {
if(!this.modifiedEvent) {
this.modifiedEvent = this.clone();
}
this.modifiedEvent._value += value;
return this;
}
clone(): Event {
const event = new Event(this._value);
event._next = this._next;
return event;
}
}
// Simple cache for patterns
let cache = new Map<string, Pattern>();
// Create a cache key from the values of a pattern somehow
const createCacheKey = (values: number[]) => values.join('-');
// Get a cached pattern or create a new one
const getCachedPattern = (values: number[]) => {
const key = createCacheKey(values);
const cachedPattern = cache.get(key);
if(cachedPattern) return cachedPattern;
const newPattern = new Pattern(values);
cache.set(key, newPattern);
return newPattern;
}
// Cached event function that includes the main logic
const cachedEvent = (values: number[]): Event => {
const pattern = getCachedPattern(values);
if(pattern.hasStarted()) { console.log("Play: ", pattern.peek().value) }
else { console.log("Current is undefined so just starting!") }
return pattern.next();
}
// Test it out
let i = 0;
while(true) {
cachedEvent([1, 2, 3]).add(1).add(2);
if(i++>10) break;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment