Find payloads by term id so they survive a .remove()
This commit is contained in:
1 parent
21ceba9e20
commit
2bef4a0319
2 files changed
+77
-30
No files matched your search
@@ -1,5 +1,48 @@
|
|||||||
import debug from './debug.js'
|
import debug from './debug.js'
|
||||||
|
|
||||||
|
// payloads are stored by sentence index, which goes stale after a .remove()
|
||||||
|
// so find each one again by the ids of its first and last terms
|
||||||
|
const findPayloads = function (view) {
|
||||||
|
const db = view.world.model.one.db || {}
|
||||||
|
const where = new Map()
|
||||||
|
view.document.forEach((terms, n) => {
|
||||||
|
terms.forEach((term, i) => where.set(term.id, [n, i]))
|
||||||
|
})
|
||||||
|
const found = []
|
||||||
|
Object.keys(db).forEach(k => {
|
||||||
|
db[k].forEach(obj => {
|
||||||
|
const [, , , startId, endId] = obj.ptr
|
||||||
|
const start = where.get(startId)
|
||||||
|
const end = where.get(endId)
|
||||||
|
// its words were removed
|
||||||
|
if (!start || !end || start[0] !== end[0]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
found.push({ k, obj, ptr: [start[0], start[1], end[1] + 1, startId, endId] })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
|
// all payloads inside our current matches
|
||||||
|
const getPayloads = function (view) {
|
||||||
|
const payloads = findPayloads(view)
|
||||||
|
const res = []
|
||||||
|
view.fullPointer.forEach(ptr => {
|
||||||
|
const seeking = view.update([ptr])
|
||||||
|
payloads.forEach(found => {
|
||||||
|
if (found.ptr[0] !== ptr[0]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const m = view.update([found.ptr])
|
||||||
|
if (seeking.has(m)) {
|
||||||
|
res.push({ ...found, match: m })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
//establish payload db
|
//establish payload db
|
||||||
mutate: function (world) {
|
mutate: function (world) {
|
||||||
@@ -11,25 +54,12 @@ export default {
|
|||||||
api: function (View) {
|
api: function (View) {
|
||||||
/** return any data on our given matches */
|
/** return any data on our given matches */
|
||||||
View.prototype.getPayloads = function () {
|
View.prototype.getPayloads = function () {
|
||||||
let res = []
|
return getPayloads(this).map(found => {
|
||||||
const db = this.world.model.one.db || {}
|
return {
|
||||||
this.fullPointer.forEach(ptr => {
|
match: found.match,
|
||||||
const n = ptr[0]
|
val: found.obj.val,
|
||||||
if (Object.hasOwn(db, n)) {
|
|
||||||
// look at all vals for this sentence
|
|
||||||
const seeking = this.update([ptr])
|
|
||||||
db[n].forEach(obj => {
|
|
||||||
const m = this.update([obj.ptr])
|
|
||||||
if (seeking.has(m)) {
|
|
||||||
res = res.concat({
|
|
||||||
match: m,
|
|
||||||
val: obj.val,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** add data about our current matches */
|
/** add data about our current matches */
|
||||||
@@ -56,21 +86,15 @@ export default {
|
|||||||
View.prototype.clearPayloads = function () {
|
View.prototype.clearPayloads = function () {
|
||||||
const db = this.world.model.one.db || {}
|
const db = this.world.model.one.db || {}
|
||||||
// get each payload
|
// get each payload
|
||||||
const res = this.getPayloads()
|
getPayloads(this).forEach(({ k, obj }) => {
|
||||||
res.forEach(obj => {
|
if (!Object.hasOwn(db, k)) {
|
||||||
const ptr = obj.match.fullPointer[0] || []
|
return
|
||||||
const [n, start, end] = ptr
|
}
|
||||||
db[n] ||= []
|
|
||||||
// remove it from our list of payloads
|
// remove it from our list of payloads
|
||||||
db[n] = db[n].filter(r => {
|
db[k] = db[k].filter(r => r !== obj)
|
||||||
if (r.ptr[1] === start && r.ptr[2] === end) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
// clean-up any empty arrays
|
// clean-up any empty arrays
|
||||||
if (db[n].length === 0) {
|
if (db[k].length === 0) {
|
||||||
delete db[n]
|
delete db[k]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return this
|
return this
|
||||||
|
|||||||
@@ -57,3 +57,26 @@ test('payload-fn', function (t) {
|
|||||||
t.equal(doc.getPayloads().length, 5, '5-now')
|
t.equal(doc.getPayloads().length, 5, '5-now')
|
||||||
t.end()
|
t.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('payload-after-remove', function (t) {
|
||||||
|
let doc = nlp('one apple. two pears. three plums.')
|
||||||
|
doc.match('(apple|plums)').addPayload(m => ({ fruit: m.text('normal') }))
|
||||||
|
t.equal(doc.getPayloads().length, 2, 'before-remove')
|
||||||
|
|
||||||
|
doc.remove('two pears')
|
||||||
|
let fruit = doc.getPayloads().map(p => p.val.fruit)
|
||||||
|
t.deepEqual(fruit, ['apple', 'plums'], 'after-remove')
|
||||||
|
t.equal(doc.match('plums').getPayloads().length, 1, 'plums-still-found')
|
||||||
|
|
||||||
|
doc.match('plums').clearPayloads()
|
||||||
|
fruit = doc.getPayloads().map(p => p.val.fruit)
|
||||||
|
t.deepEqual(fruit, ['apple'], 'clear-after-remove')
|
||||||
|
|
||||||
|
// removing the payload's own words drops it
|
||||||
|
doc = nlp('one apple. two pears. three plums.')
|
||||||
|
doc.match('(apple|pears|plums)').addPayload(m => ({ fruit: m.text('normal') }))
|
||||||
|
doc.remove('two pears')
|
||||||
|
fruit = doc.getPayloads().map(p => p.val.fruit)
|
||||||
|
t.deepEqual(fruit, ['apple', 'plums'], 'removed-payload-is-gone')
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
Reference in new issue
Block a user