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'
|
||||
|
||||
// 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 {
|
||||
//establish payload db
|
||||
mutate: function (world) {
|
||||
@@ -11,25 +54,12 @@ export default {
|
||||
api: function (View) {
|
||||
/** return any data on our given matches */
|
||||
View.prototype.getPayloads = function () {
|
||||
let res = []
|
||||
const db = this.world.model.one.db || {}
|
||||
this.fullPointer.forEach(ptr => {
|
||||
const n = ptr[0]
|
||||
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 getPayloads(this).map(found => {
|
||||
return {
|
||||
match: found.match,
|
||||
val: found.obj.val,
|
||||
}
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
/** add data about our current matches */
|
||||
@@ -56,21 +86,15 @@ export default {
|
||||
View.prototype.clearPayloads = function () {
|
||||
const db = this.world.model.one.db || {}
|
||||
// get each payload
|
||||
const res = this.getPayloads()
|
||||
res.forEach(obj => {
|
||||
const ptr = obj.match.fullPointer[0] || []
|
||||
const [n, start, end] = ptr
|
||||
db[n] ||= []
|
||||
getPayloads(this).forEach(({ k, obj }) => {
|
||||
if (!Object.hasOwn(db, k)) {
|
||||
return
|
||||
}
|
||||
// remove it from our list of payloads
|
||||
db[n] = db[n].filter(r => {
|
||||
if (r.ptr[1] === start && r.ptr[2] === end) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
db[k] = db[k].filter(r => r !== obj)
|
||||
// clean-up any empty arrays
|
||||
if (db[n].length === 0) {
|
||||
delete db[n]
|
||||
if (db[k].length === 0) {
|
||||
delete db[k]
|
||||
}
|
||||
})
|
||||
return this
|
||||
|
||||
@@ -57,3 +57,26 @@ test('payload-fn', function (t) {
|
||||
t.equal(doc.getPayloads().length, 5, '5-now')
|
||||
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