shenanigans

This commit is contained in:
alex 2022-01-25 17:03:22 +00:00
parent d15ac42969
commit f696cd554f
3 changed files with 108 additions and 55 deletions

View File

@ -5,6 +5,10 @@ var removeUndefineds = function(xs) {
return xs.filter(x => x != undefined) return xs.filter(x => x != undefined)
} }
function flatten(arr) {
return [].concat(...arr)
}
// Returns the start of the cycle. // Returns the start of the cycle.
Fraction.prototype.sam = function() { Fraction.prototype.sam = function() {
return Fraction(Math.floor(this)) return Fraction(Math.floor(this))
@ -36,6 +40,18 @@ Fraction.prototype.gte = function(other) {
return this.compare(other) >= 0 return this.compare(other) >= 0
} }
Fraction.prototype.max = function(other) {
return this.gt(other) ? this : other
}
Fraction.prototype.min = function(other) {
return this.lt(other) ? this : other
}
Fraction.prototype.show = function () {
return this.n + "/" + this.d
}
class TimeSpan { class TimeSpan {
constructor(begin, end) { constructor(begin, end) {
this.begin = Fraction(begin) this.begin = Fraction(begin)
@ -71,8 +87,8 @@ class TimeSpan {
intersection(other) { intersection(other) {
// Intersection of two timespans, returns None if they don't intersect. // Intersection of two timespans, returns None if they don't intersect.
intersect_begin = Math.max(this.begin, other.begin) var intersect_begin = this.begin.max(other.begin)
intersect_end = Math.min(this.end, other.end) var intersect_end = this.end.min(other.end)
if (intersect_begin.gt(intersect_end)) { if (intersect_begin.gt(intersect_end)) {
return(undefined) return(undefined)
@ -92,12 +108,12 @@ class TimeSpan {
intersection_e(other) { intersection_e(other) {
// Like 'sect', but raises an exception if the timespans don't intersect. // Like 'sect', but raises an exception if the timespans don't intersect.
result = this.intersection(other) var result = this.intersection(other)
if (result.equals(None)) { if (result == undefined) {
// TODO - raise exception // TODO - raise exception
// raise ValueError(f'TimeSpan {self} and TimeSpan {other} do not intersect') // raise ValueError(f'TimeSpan {self} and TimeSpan {other} do not intersect')
} }
return(result) return result
} }
get midpoint() { get midpoint() {
@ -107,6 +123,10 @@ class TimeSpan {
equals(other) { equals(other) {
return this.begin.equals(other.begin) && this.end.equals(other.end) return this.begin.equals(other.begin) && this.end.equals(other.end)
} }
show() {
return this.begin.show() + " -> " + this.end.show()
}
} }
class Hap { class Hap {
@ -158,6 +178,10 @@ class Hap {
&& this.value === other.value && this.value === other.value
) )
} }
show() {
return "(" + (this.whole == undefined ? "~" : this.whole.show()) + ", " + this.part.show() + ", " + this.value + ")"
}
} }
class Pattern { class Pattern {
@ -170,7 +194,7 @@ class Pattern {
// easier to express, as all events are then constrained to happen within // easier to express, as all events are then constrained to happen within
// a cycle. // a cycle.
var query = function(span) { var query = function(span) {
return span.spanCycles.map(subspan => this.query(subspan)).concat return flatten(span.spanCycles.map(subspan => this.query(subspan)))
} }
return new Pattern(query) return new Pattern(query)
} }
@ -200,16 +224,16 @@ class Pattern {
withValue(func) { withValue(func) {
// Returns a new pattern, with the function applied to the value of // Returns a new pattern, with the function applied to the value of
// each event. It has the alias 'fmap'. // each event. It has the alias 'fmap'.
return new Pattern(this.query(span).map(hap => hap.withValue(func))) return new Pattern(span => this.query(span).map(hap => hap.withValue(func)))
} }
// alias // alias
fmap(func) { fmap(func) {
this.withValue(func) return this.withValue(func)
} }
_filterEvents(event_test) { _filterEvents(event_test) {
return new Pattern(span => this.query(span).filter(event_test)) return new Pattern(span => this.query(span).filter(event_tespanCyclesst))
} }
_filterValues(self, value_test) { _filterValues(self, value_test) {
@ -227,18 +251,18 @@ class Pattern {
// Assumes 'this' is a pattern of functions, and given a function to // Assumes 'this' is a pattern of functions, and given a function to
// resolve wholes, applies a given pattern of values to that // resolve wholes, applies a given pattern of values to that
// pattern of functions. // pattern of functions.
pat_func = this var pat_func = this
query = function(span) { query = function(span) {
event_funcs = pat_func.query(span) var event_funcs = pat_func.query(span)
event_vals = pat_val.query(span) var event_vals = pat_val.query(span)
apply = function(event_func, event_val) { apply = function(event_func, event_val) {
s = event_func.part.intersection(event_val.part) var s = event_func.part.intersection(event_val.part)
if (s === undefined) { if (s === undefined) {
return undefined return undefined
} }
return new Hap(whole_func(event_func.whole, event_val.whole), s, event_func.value(event_val.value)) return new Hap(whole_func(event_func.whole, event_val.whole), s, event_func.value(event_val.value))
} }
return event_funcs.map(event_func => removeUndefineds(event_vals.map(event_val => apply(event_func, event_val)))).concat return flatten(event_funcs.map(event_func => removeUndefineds(event_vals.map(event_val => apply(event_func, event_val)))))
} }
return new Pattern(query) return new Pattern(query)
} }
@ -255,43 +279,53 @@ class Pattern {
} }
appLeft(pat_val) { appLeft(pat_val) {
pat_func = this var pat_func = this
var query = function(span) {
events = []
for (event_func in pat_func.query(span)) {
event_vals = pat_val.query(event_func.part)
for (event_val in event_vals) {
new_whole = event_func.whole
new_part = event_func.part.intersection_e(event_val.part)
new_value = event_func.value(event_val.value)
events.push(new Event(new_whole, new_part, new_value))
}
}
return events
}
return Pattern(query)
}
appRight(pat_val) {
pat_func = this
var query = function(span) { var query = function(span) {
events = [] var haps = []
for (event_val in pat_val.query(span)) { for (var hap_func of pat_func.query(span)) {
event_funcs = pat_func.query(event_val.part) var event_vals = pat_val.query(hap_func.part)
for (event_func in event_funcs) { for (var hap_val of event_vals) {
new_whole = event_val.whole var new_whole = hap_func.whole
new_part = event_func.part.intersection_e(event_val.part) var new_part = hap_func.part.intersection_e(hap_val.part)
new_value = event_func.value(event_val.value) var new_value = hap_func.value(hap_val.value)
events.push(new Event(new_whole, new_part, new_value)) var hap = new Hap(new_whole, new_part, new_value)
haps.push(hap)
} }
} }
return events return haps
} }
return new Pattern(query) return new Pattern(query)
} }
// def __add__(self, other): appRight(pat_val) {
// return self.fmap(lambda x: lambda y: x + y).app_left(reify(other)) var pat_func = this
var query = function(span) {
var haps = []
for (var hap_val of pat_val.query(span)) {
var hap_funcs = pat_func.query(hap_val.part)
for (var hap_func of hap_funcs) {
var new_whole = hap_val.whole
var new_part = hap_func.part.intersection_e(hap_val.part)
var new_value = hap_func.value(hap_val.value)
var hap = new Hap(new_whole, new_part, new_value)
haps.push(hap)
}
}
return haps
}
return new Pattern(query)
}
add(other) {
// TODO - reify other
return this.fmap(x => y => x + y).appLeft(other)
}
get firstCycle() {
return this.query(new TimeSpan(Fraction(0), Fraction(1)))
}
// def __radd__(self, other): // def __radd__(self, other):
// return self.__add__(other) // return self.__add__(other)

24
package-lock.json generated
View File

@ -379,9 +379,9 @@
"integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg=="
}, },
"node_modules/@sindresorhus/is": { "node_modules/@sindresorhus/is": {
"version": "4.3.0", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.3.0.tgz", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz",
"integrity": "sha512-wwOvh0eO3PiTEivGJWiZ+b946SlMSb4pe+y+Ur/4S87cwo09pYi+FWHHnbrM3W9W7cBYKDqQXcrFYjYUCOJUEQ==", "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==",
"engines": { "engines": {
"node": ">=10" "node": ">=10"
}, },
@ -438,9 +438,9 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "17.0.10", "version": "17.0.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.10.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.12.tgz",
"integrity": "sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog==" "integrity": "sha512-4YpbAsnJXWYK/fpTVFlMIcUIho2AYCi4wg5aNPrG1ng7fn/1/RZfCIpRCiBX+12RVa34RluilnvCqD+g3KiSiA=="
}, },
"node_modules/@types/parse-json": { "node_modules/@types/parse-json": {
"version": "4.0.0", "version": "4.0.0",
@ -4800,9 +4800,9 @@
} }
}, },
"@sindresorhus/is": { "@sindresorhus/is": {
"version": "4.3.0", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.3.0.tgz", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz",
"integrity": "sha512-wwOvh0eO3PiTEivGJWiZ+b946SlMSb4pe+y+Ur/4S87cwo09pYi+FWHHnbrM3W9W7cBYKDqQXcrFYjYUCOJUEQ==" "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ=="
}, },
"@szmarczak/http-timer": { "@szmarczak/http-timer": {
"version": "4.0.6", "version": "4.0.6",
@ -4847,9 +4847,9 @@
} }
}, },
"@types/node": { "@types/node": {
"version": "17.0.10", "version": "17.0.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.10.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.12.tgz",
"integrity": "sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog==" "integrity": "sha512-4YpbAsnJXWYK/fpTVFlMIcUIho2AYCi4wg5aNPrG1ng7fn/1/RZfCIpRCiBX+12RVa34RluilnvCqD+g3KiSiA=="
}, },
"@types/parse-json": { "@types/parse-json": {
"version": "4.0.0", "version": "4.0.0",

View File

@ -15,6 +15,15 @@ describe('TimeSpan', function() {
assert.equal(new TimeSpan(Fraction(0),Fraction(2)).spanCycles.length, 2) assert.equal(new TimeSpan(Fraction(0),Fraction(2)).spanCycles.length, 2)
}) })
}) })
describe('intersection_e', function () {
var a = new TimeSpan(Fraction(0), Fraction(2))
var b = new TimeSpan(Fraction(1), Fraction(3))
var c = new TimeSpan(Fraction(1), Fraction(2))
var d = new TimeSpan(Fraction(1), Fraction(2))
it('Should create an intersection', function () {
assert.equal(a.intersection_e(b).equals(c), true)
})
})
}); });
describe('Hap', function() { describe('Hap', function() {
@ -47,4 +56,14 @@ describe('Pattern', function() {
assert.equal(pure("hello").query(new TimeSpan(Fraction(0.5), Fraction(2.5))).length, 3) assert.equal(pure("hello").query(new TimeSpan(Fraction(0.5), Fraction(2.5))).length, 3)
}) })
}) })
describe('fmap()', function () {
it('Can add things', function () {
assert.equal(pure(3).fmap(x => x + 4).firstCycle[0].value, 7)
})
})
describe('add()', function () {
it('Can add things', function() {
assert.equal(pure(3).add(pure(4)).query(new TimeSpan(Fraction(0), Fraction(1)))[0].value, 7)
})
})
}) })