Repository navigation
Give token and segment links ids and pick ties by rule (#430) - #461
Conversation
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
📝 Walkthrough
Merge Risk: 🔵 Low · up to
|
alex-rawlings-yyc
left a comment
There was a problem hiding this comment.
@alex-rawlings-yyc made 13 comments and resolved 13 discussions.
Reviewable status: 23 of 32 files reviewed, all discussions resolved (waiting on alex-rawlings-yyc).
src/__tests__/services/projectStorage.test.ts line 2566 at r2 (raw file):
Previously, imnasnainaec (D. Ror.) wrote…
⛏️ Fake GUIDS in other tests end with 1, 2, ... (instead of a, b)
Fixed.
src/__tests__/utils/pick-rules.test.ts line 14 at r2 (raw file):
Previously, imnasnainaec (D. Ror.) wrote…
⛏️ Spread
FIXTURE_STAMPS, aspayloaddoes;EARLIERis itscreatedAt.return { ...FIXTURE_STAMPS, id, analysisId: 'ta-1',
Done.
imnasnainaec
left a comment
There was a problem hiding this comment.
@imnasnainaec reviewed 6 files and all commit messages, and made 2 comments.
Reviewable status: 29 of 32 files reviewed, 2 unresolved discussions (waiting on alex-rawlings-yyc).
src/__tests__/store/analysisSlice.test.ts line 6990 at r3 (raw file):
} it('gives each link a gloss creates an id of its own, though the links share a payload', () => {
⛏️ The "gives ... creates ..." syntax of the it sentences in this describe are hard to parse.
How about (e.g.) "gives each link created by a gloss..." or "gives each gloss-created link ..."?
src/utils/concordance.ts line 203 at r3 (raw file):
* payload is missing from `analysesById` losing to one whose payload is present. */ export function approvedAnalysisByToken(
⛏️ Optional logic consolidation:
Same best-approved-link-per-key loop as selectApprovedIdByTokenRef (analysisSlice.ts:1988) and selectApprovedSegmentAnalysisBySegment (analysisSlice.ts:2479). All three keep winners plus a value map derived from it.
Suggest a helper beside preferredLink:
/** The link an approval tie picks for each key `keyOf` gives, skipping links it gives none. */
export function preferredLinkByKey<L extends AnalysisLink>(
links: readonly L[],
keyOf: (link: L) => string | undefined,
prefers: (link: L, rival: L) => boolean = prefersLink,
): Map<string, L> {
const winners = new Map<string, L>();
links.forEach((link) => {
const key = keyOf(link);
if (key === undefined) return;
const held = winners.get(key);
if (!held || prefers(link, held)) winners.set(key, link);
});
return winners;
}Here:
const hasPayload = (l: TokenAnalysisLink) => analysesById.has(l.analysisId);
const winners = preferredLinkByKey(
links,
(l) =>
l.status === 'approved'
? approvalKey(l.token.tokenRef, normalizeSurfaceForm(l.token.surfaceText))
: undefined,
(l, held) => (hasPayload(l) !== hasPayload(held) ? hasPayload(l) : prefersLink(l, held)),
);
return new Map([...winners].map(([key, l]) => [key, l.analysisId]));Orphan handling differs: this counts an approval to a missing record as approved (pinned by "reads an approval naming a missing record as unglossed"), while selectApprovedIdByTokenRef drops it. The concordance can show a token as analyzed that the editor shows as unanalyzed. Intended? If so, worth a line in the doc comment.
alex-rawlings-yyc
left a comment
There was a problem hiding this comment.
@alex-rawlings-yyc made 2 comments and resolved 2 discussions.
Reviewable status: 29 of 32 files reviewed, all discussions resolved (waiting on alex-rawlings-yyc).
src/__tests__/store/analysisSlice.test.ts line 6990 at r3 (raw file):
Previously, imnasnainaec (D. Ror.) wrote…
⛏️ The "gives ... creates ..." syntax of the
itsentences in thisdescribeare hard to parse.How about (e.g.) "gives each link created by a gloss..." or "gives each gloss-created link ..."?
Done: all five now use the "created by" form.
src/utils/concordance.ts line 203 at r3 (raw file):
Previously, imnasnainaec (D. Ror.) wrote…
⛏️ Optional logic consolidation:
Same best-approved-link-per-key loop as
selectApprovedIdByTokenRef(analysisSlice.ts:1988) andselectApprovedSegmentAnalysisBySegment(analysisSlice.ts:2479). All three keepwinnersplus a value map derived from it.Suggest a helper beside
preferredLink:/** The link an approval tie picks for each key `keyOf` gives, skipping links it gives none. */ export function preferredLinkByKey<L extends AnalysisLink>( links: readonly L[], keyOf: (link: L) => string | undefined, prefers: (link: L, rival: L) => boolean = prefersLink, ): Map<string, L> { const winners = new Map<string, L>(); links.forEach((link) => { const key = keyOf(link); if (key === undefined) return; const held = winners.get(key); if (!held || prefers(link, held)) winners.set(key, link); }); return winners; }Here:
const hasPayload = (l: TokenAnalysisLink) => analysesById.has(l.analysisId); const winners = preferredLinkByKey( links, (l) => l.status === 'approved' ? approvalKey(l.token.tokenRef, normalizeSurfaceForm(l.token.surfaceText)) : undefined, (l, held) => (hasPayload(l) !== hasPayload(held) ? hasPayload(l) : prefersLink(l, held)), ); return new Map([...winners].map(([key, l]) => [key, l.analysisId]));Orphan handling differs: this counts an approval to a missing record as approved (pinned by "reads an approval naming a missing record as unglossed"), while
selectApprovedIdByTokenRefdrops it. The concordance can show a token as analyzed that the editor shows as unanalyzed. Intended? If so, worth a line in the doc comment.
Done. preferredLinkByKey sits beside preferredLink, and all three loops now use it. I left out the prefers parameter because no caller needs a custom rule anymore. The difference in orphan handling wasn't intended: like the editor, the concordance now drops an approval that names a missing record. That removed the payload tie-break, and the pinned test now asserts the approval is left out.
imnasnainaec
left a comment
There was a problem hiding this comment.
@imnasnainaec reviewed 7 files and all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on alex-rawlings-yyc).
Part of #424; closes #430.
Link ids. Token and segment links now carry the
idphrase links already had; it moves ontoAnalysisLink. The reducers mint one for every new link, the PT9 converter writespt9:tl:<tokenRef>:<n>, and the perf generator draws them from a seeded stream of their own, so they never shift the draws a tier's records come from.validateTextAnalysisreports duplicate link ids on every layer.Old data. A saved project or inline draft holding a token or segment link with no id loads empty, with a log entry. A draft shard holding one is treated as unusable and loads empty, so books saved since keep their work.
Picks by rule.
src/utils/pick-rules.tsholds the rules. An approval tie goes to the latestupdatedAt, then the smallest id, for tokens and segments alike. A merge folds into the identical payload with the earliestcreatedAt, then the smallest id. The reducers apply them wherever they picked by list order: approval ties, held and stale links, find-or-create, and token and phrase merges. The read selectors and the concordance apply them too, so reads and writes agree. An approval naming a missing payload is dropped from a tie and the pick falls to the rest. A collapse that leaves a token two links keeps the approved one.Cached perf datasets lack link ids and load empty; regenerate them with
npm run perf:datasets.This change is
Summary by CodeRabbit