Skip to content

Commit 85f0edd

Browse files
authored
Merge pull request #9 from seanbonner/feat/perfect-and-priceless-collection
Add Perfect & Priceless collection
2 parents 3be9268 + 5253171 commit 85f0edd

5 files changed

Lines changed: 83 additions & 9 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
'@networked-art/punks-sdk': minor
3+
---
4+
5+
Add the `perfect-and-priceless` curated collection: the 24 Punks printed and
6+
shown in Kate Vass Galerie's 2018-2019 "Perfect & Priceless" exhibition, each
7+
framed print backed by its seed phrase sealed in an envelope.
8+
9+
- Resolves under every name the set is known by — `perfect & priceless`,
10+
`perfect and priceless`, `kate vass`, `kate vass galerie`, `paper punks`,
11+
`paper`.
12+
- The collection alias matcher now skips punctuation-only tokens, so the `&`
13+
spelling of a name matches the same set as the spelled-out form.

sdk/README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,18 @@ skin tone.
110110

111111
### Curated collections
112112

113-
Curated collections are named, sourced sets of Punk ids — `burned` and `museum`
114-
today, more to come. A collection alias resolves to its id set through the
115-
existing `includeIds` path, so it composes with the rest of a query:
113+
Curated collections are named, sourced sets of Punk ids — `burned`, `museum`,
114+
and `perfect-and-priceless` today, more to come. A collection alias resolves to
115+
its id set through the existing `includeIds` path, so it composes with the rest
116+
of a query, and a set can carry several aliases:
116117

117118
```ts
118119
punks.search({ text: 'burned punks' }) // the burned set
119120
punks.search({ text: 'burned alien' }) // burned ∩ alien
120121
punks.count({ text: 'burned OR alien' })
122+
123+
punks.search({ text: 'paper' }) // the Perfect & Priceless set
124+
punks.search({ text: 'kate vass' }) // same set, by its gallery
121125
```
122126

123127
Collections can nest independently resolvable institutions, so `museum` matches

sdk/src/search-collections.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,23 @@
5353
"ids": [9833]
5454
}
5555
}
56+
},
57+
"perfect-and-priceless": {
58+
"title": "Perfect & Priceless Punks",
59+
"description": "Punks printed and shown in Kate Vass Galerie's 2018-2019 'Perfect & Priceless' exhibition, each framed print backed by its seed phrase sealed in an envelope.",
60+
"aliases": [
61+
"perfect and priceless",
62+
"perfect & priceless",
63+
"kate vass",
64+
"kate vass galerie",
65+
"paper punks",
66+
"paper"
67+
],
68+
"source": "https://www.katevassgalerie.com/perfect-and-priceless",
69+
"standard": "v2",
70+
"ids": [
71+
207, 269, 636, 652, 672, 722, 726, 728, 770, 795, 872, 910, 934, 1819,
72+
2134, 2830, 3036, 3122, 4530, 4946, 5127, 6347, 6675, 8773
73+
]
5674
}
5775
}

sdk/src/text-parse.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -498,12 +498,16 @@ function matchSearchCollectionEntry(
498498
entry: SearchCollectionEntry,
499499
): number | undefined {
500500
let phrase = ''
501-
const maxTerms = Math.min(entry.tokens.length, terms.length - start)
502-
for (let consumed = 1; consumed <= maxTerms; consumed++) {
503-
const term = terms[start + consumed - 1]
501+
let consumed = 0
502+
while (start + consumed < terms.length) {
503+
const term = terms[start + consumed]
504504
if (term.exact) return undefined
505+
consumed++
506+
// Punctuation-only tokens (e.g. the `&` in `perfect & priceless`) normalize
507+
// to nothing; consume them but skip them in the phrase so the surrounding
508+
// words still match the `&`-free alias key.
505509
const normalized = normalizeSynonymText(term.text)
506-
if (!normalized) return undefined
510+
if (!normalized) continue
507511
phrase = phrase ? `${phrase} ${normalized}` : normalized
508512
if (phrase === entry.key) return consumed
509513
if (!entry.key.startsWith(`${phrase} `)) return undefined

sdk/test/collections.test.mjs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,16 @@ const MUSEUM = [
2020
const MOMA = [74, 2786, 3407, 4018, 5160, 5616, 7178, 7899]
2121
const ZKM = [1286, 2554, 2838, 5449]
2222

23+
const PERFECT_AND_PRICELESS = [
24+
207, 269, 636, 652, 672, 722, 726, 728, 770, 795, 872, 910, 934, 1819, 2134,
25+
2830, 3036, 3122, 4530, 4946, 5127, 6347, 6675, 8773,
26+
]
27+
2328
describe('curated collections', () => {
2429
it('bundles the burned set as validated, normalized data', () => {
2530
assert.deepEqual(
2631
searchCollections.map((collection) => collection.slug),
27-
['burned', 'museum'],
32+
['burned', 'museum', 'perfect-and-priceless'],
2833
)
2934

3035
const burned = getSearchCollection('burned')
@@ -90,10 +95,11 @@ describe('curated collections', () => {
9095

9196
assert.deepEqual(
9297
punks.collections.list().map((collection) => collection.slug),
93-
['burned', 'museum'],
98+
['burned', 'museum', 'perfect-and-priceless'],
9499
)
95100
assert.equal(punks.collections.has('burned'), true)
96101
assert.equal(punks.collections.has('museum'), true)
102+
assert.equal(punks.collections.has('perfect-and-priceless'), true)
97103
assert.equal(punks.collections.has('missing'), false)
98104
assert.equal(punks.collections.get('burned').ids.length, 12)
99105
assert.equal(punks.collections.get('missing'), undefined)
@@ -164,4 +170,33 @@ describe('curated collections', () => {
164170
[2838, 5449],
165171
)
166172
})
173+
174+
it('resolves the Perfect & Priceless set under all its names', () => {
175+
const collection = getSearchCollection('perfect-and-priceless')
176+
assert.equal(collection.title, 'Perfect & Priceless Punks')
177+
assert.equal(
178+
collection.source,
179+
'https://www.katevassgalerie.com/perfect-and-priceless',
180+
)
181+
assert.equal(collection.standard, 0)
182+
assert.deepEqual(collection.ids, PERFECT_AND_PRICELESS)
183+
184+
const sdk = createOfflinePunksDataClient()
185+
// The gallery name (with `&` and spelled-out `and`), the gallery, and the
186+
// informal "paper" name all resolve to the same set.
187+
for (const phrase of [
188+
'perfect & priceless',
189+
'perfect and priceless',
190+
'kate vass',
191+
'kate vass galerie',
192+
'paper punks',
193+
'paper',
194+
]) {
195+
assert.deepEqual(
196+
sdk.searchSync({ text: phrase }),
197+
PERFECT_AND_PRICELESS,
198+
`"${phrase}" should resolve to the Perfect & Priceless set`,
199+
)
200+
}
201+
})
167202
})

0 commit comments

Comments
 (0)