diff --git a/mysteries/barricelli-scene-7/fixtures/national-library-patent-ocr.txt b/mysteries/barricelli-scene-7/fixtures/national-library-patent-ocr.txt new file mode 100644 index 0000000..4c3d167 --- /dev/null +++ b/mysteries/barricelli-scene-7/fixtures/national-library-patent-ocr.txt @@ -0,0 +1,21 @@ +Nr. 75 348. + +Kl. 33 b-9 — Fra 31 mai 1948 — 93585. + +Koffert-kommode. + +Niels Aall Baricélli; Oslo. Fullmektig: O.r.- +sakfører Johan Storm Bull, Oslo. + +Utf. 4de juni 1951. + +Patentpåstand: + +1. Kommode, som er satt sammen av +flere enkeltdeler, som hver er utført som +koffert av et hensiktsmessig materiale, ka- +rakterisert ved at hver av de nevnte en- +keltdeler består av en ytre kasse som be- +rende stativ for kommoden, og en i denne +kasse uttrekkbart anbrakt, låsbar skuff, +forsynt med kofferthåndtak. diff --git a/mysteries/barricelli-scene-7/mystery.json b/mysteries/barricelli-scene-7/mystery.json index 4c95cf0..8130cc0 100644 --- a/mysteries/barricelli-scene-7/mystery.json +++ b/mysteries/barricelli-scene-7/mystery.json @@ -53,6 +53,27 @@ "minimumSimilarity": 0.68 } ] + }, + { + "name": "Nasjonalbiblioteket · Patent 93585", + "sourceLabel": "Nasjonalbiblioteket · Patent 93585 · Koffert-kommode", + "sourceUri": "https://www.nb.no/items/921545b51acef0b05054cfc1f4666975?page=9&searchText=baricelli", + "flagKey": "scene7.nils_inventor_proved", + "minimumAnchorMatches": 2, + "anchors": [ + { + "phrase": "Nr 75 348 Kl 33 b-9 Fra 31 mai 1948 93585 Koffert-kommode", + "minimumSimilarity": 0.68 + }, + { + "phrase": "Niels Aall Baricelli Oslo", + "minimumSimilarity": 0.72 + }, + { + "phrase": "Patentpaastand Kommode som er satt sammen av flere enkeltdeler som hver er utfort som koffert", + "minimumSimilarity": 0.62 + } + ] } ], "evidenceSemanticRules": [ diff --git a/server/api.integration.test.ts b/server/api.integration.test.ts index b860afd..b1a265b 100644 --- a/server/api.integration.test.ts +++ b/server/api.integration.test.ts @@ -257,10 +257,15 @@ suite('normalized level persistence API', () => { }),goals:[expect.objectContaining({ key:'barricelli.inventor-proof',status:'pending',newlyCompleted:false, })] }) - expect(await (await adminFetch(`${baseUrl}/api/levels/${imported.playableLevel.id}/evidence-match-rules`)).json()).toEqual([ + const sceneSevenRules=await (await adminFetch(`${baseUrl}/api/levels/${imported.playableLevel.id}/evidence-match-rules`)).json() + expect(sceneSevenRules).toHaveLength(2) + expect(sceneSevenRules).toEqual(expect.arrayContaining([ expect.objectContaining({ name:'Google Patents · GB695913A',sourceUri:'https://patents.google.com/patent/GB695913A/en', flagKey:'scene7.nils_inventor_proved',minimumAnchorMatches:2 }), - ]) + expect.objectContaining({ name:'Nasjonalbiblioteket · Patent 93585', + sourceUri:'https://www.nb.no/items/921545b51acef0b05054cfc1f4666975?page=9&searchText=baricelli', + flagKey:'scene7.nils_inventor_proved',minimumAnchorMatches:2 }), + ])) expect(await (await adminFetch(`${baseUrl}/api/levels/${imported.playableLevel.id}/evidence-semantic-rules`)).json()).toEqual([ expect.objectContaining({ goalKey:'barricelli.inventor-proof',targetSubject:'Nils Aall Barricelli', relatedFlagKey:'scene7.father_inventor_discovered' }), diff --git a/server/evidenceMatching.test.ts b/server/evidenceMatching.test.ts index 7775122..598cfad 100644 --- a/server/evidenceMatching.test.ts +++ b/server/evidenceMatching.test.ts @@ -30,9 +30,12 @@ const sceneSevenManifest = JSON.parse(readFileSync( goals: { key:string;requiredFlags:string[] }[] evidenceMatchRules: { name:string;flagKey:string;minimumAnchorMatches:number;anchors:{ phrase:string;minimumSimilarity:number }[] }[] } -const authoredPatentRule = sceneSevenManifest.evidenceMatchRules[0] -const patentRule = { id:'rule-patent',...authoredPatentRule, - anchors:authoredPatentRule.anchors.map((anchor,index) => ({ id:`anchor-${index}`,...anchor })) } +const authoredPatentRule = sceneSevenManifest.evidenceMatchRules.find(rule => rule.name.startsWith('Google Patents'))! +const authoredNationalLibraryRule = sceneSevenManifest.evidenceMatchRules.find(rule => rule.name.startsWith('Nasjonalbiblioteket'))! +const materializeRule = (id:string, rule:typeof authoredPatentRule) => ({ id,...rule, + anchors:rule.anchors.map((anchor,index) => ({ id:`${id}-anchor-${index}`,...anchor })) }) +const patentRule = materializeRule('rule-patent',authoredPatentRule) +const nationalLibraryRule = materializeRule('rule-national-library',authoredNationalLibraryRule) describe('evidence text matching', () => { it('normalizes historical Norwegian characters and page layout noise', () => { @@ -69,6 +72,12 @@ describe('evidence text matching', () => { expect(evaluation.matchedAnchorCount).toBeGreaterThanOrEqual(2) }) + it('accepts the Norwegian National Library patent notice found during playtesting', () => { + const evaluation = evaluateEvidenceRules(sceneSevenFixture('national-library-patent-ocr.txt'), [nationalLibraryRule])[0] + expect(evaluation).toMatchObject({ matched:true,flagKey:'scene7.nils_inventor_proved' }) + expect(evaluation.matchedAnchorCount).toBeGreaterThanOrEqual(2) + }) + it('keeps the Scene 7 assignment empty and ties its goal to the source flag', () => { expect(sceneSevenManifest.documents).toEqual([]) expect(sceneSevenManifest.goals).toEqual([ @@ -78,8 +87,8 @@ describe('evidence text matching', () => { }) it('does not confuse the father-only source with proof about Nils', () => { - expect(evaluateEvidenceRules(sceneSevenFixture('father-only-negative-ocr.txt'), [patentRule])[0]) - .toMatchObject({ matched: false }) + expect(evaluateEvidenceRules(sceneSevenFixture('father-only-negative-ocr.txt'), [patentRule,nationalLibraryRule])) + .toEqual([expect.objectContaining({ matched:false }),expect.objectContaining({ matched:false })]) }) it('tolerates a cropped, line-broken patent result without accepting unrelated patents or empty OCR', () => {