@shaxpir/duiduidui-models 1.9.28 → 1.9.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/models/Collection.d.ts +20 -0
- package/dist/models/Collection.js +32 -0
- package/dist/models/Device.d.ts +4 -3
- package/dist/models/Device.js +34 -11
- package/package.json +1 -1
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Doc } from '@shaxpir/sharedb/lib/client';
|
|
2
2
|
import { CompactDateTime } from "@shaxpir/shaxpir-common";
|
|
3
3
|
import { ShareSync } from '../repo';
|
|
4
|
+
import { ArrayView } from './ArrayView';
|
|
4
5
|
import { Conditions } from './Condition';
|
|
5
6
|
import { Content, ContentBody, ContentId, ContentMeta } from "./Content";
|
|
7
|
+
import { AnnotatedPhrase } from './Phrase';
|
|
6
8
|
import { SkillLevel } from './SkillLevel';
|
|
7
9
|
/**
|
|
8
10
|
* Display metadata for a Collection, used in the UI.
|
|
@@ -13,6 +15,13 @@ export interface CollectionDisplay {
|
|
|
13
15
|
icon?: string;
|
|
14
16
|
sort_order: number;
|
|
15
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* A phrase explicitly included in a Collection, independent of condition matching.
|
|
20
|
+
*/
|
|
21
|
+
export interface CollectionPhrase {
|
|
22
|
+
text: string;
|
|
23
|
+
sense_rank: number;
|
|
24
|
+
}
|
|
16
25
|
/**
|
|
17
26
|
* The payload for a Collection document.
|
|
18
27
|
*
|
|
@@ -22,6 +31,7 @@ export interface CollectionDisplay {
|
|
|
22
31
|
export interface CollectionPayload {
|
|
23
32
|
collection_key: string;
|
|
24
33
|
conditions: Conditions;
|
|
34
|
+
phrases: CollectionPhrase[];
|
|
25
35
|
display: CollectionDisplay;
|
|
26
36
|
proficiency: SkillLevel;
|
|
27
37
|
term_scores: {
|
|
@@ -42,6 +52,7 @@ export interface CollectionBody extends ContentBody {
|
|
|
42
52
|
export interface CollectionCreateParams {
|
|
43
53
|
collectionKey: string;
|
|
44
54
|
conditions: Conditions;
|
|
55
|
+
phrases: CollectionPhrase[];
|
|
45
56
|
display: CollectionDisplay;
|
|
46
57
|
isBuiltin?: boolean;
|
|
47
58
|
isVisible?: boolean;
|
|
@@ -64,6 +75,7 @@ export declare class Collection extends Content {
|
|
|
64
75
|
text: string;
|
|
65
76
|
senseRank: number;
|
|
66
77
|
};
|
|
78
|
+
private _phrasesView;
|
|
67
79
|
constructor(doc: Doc, shouldAcquire: boolean, shareSync: ShareSync);
|
|
68
80
|
/**
|
|
69
81
|
* Create a new Collection for a user.
|
|
@@ -72,6 +84,7 @@ export declare class Collection extends Content {
|
|
|
72
84
|
get payload(): CollectionPayload;
|
|
73
85
|
get collectionKey(): string;
|
|
74
86
|
get conditions(): Conditions;
|
|
87
|
+
get phrases(): ArrayView<CollectionPhrase>;
|
|
75
88
|
get display(): CollectionDisplay;
|
|
76
89
|
get name(): string;
|
|
77
90
|
get description(): string;
|
|
@@ -123,6 +136,13 @@ export declare class Collection extends Content {
|
|
|
123
136
|
D: number;
|
|
124
137
|
F: number;
|
|
125
138
|
};
|
|
139
|
+
/**
|
|
140
|
+
* Check if a phrase belongs to this collection.
|
|
141
|
+
*
|
|
142
|
+
* First checks for an exact match in the explicit phrases list,
|
|
143
|
+
* then falls back to condition matching if no explicit match is found.
|
|
144
|
+
*/
|
|
145
|
+
matches(phrase: AnnotatedPhrase): boolean;
|
|
126
146
|
/**
|
|
127
147
|
* Update the IRT proficiency rating.
|
|
128
148
|
*/
|
|
@@ -3,7 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Collection = void 0;
|
|
4
4
|
const shaxpir_common_1 = require("@shaxpir/shaxpir-common");
|
|
5
5
|
const repo_1 = require("../repo");
|
|
6
|
+
const ConditionMatcher_1 = require("../util/ConditionMatcher");
|
|
6
7
|
const SenseRankEncoder_1 = require("../util/SenseRankEncoder");
|
|
8
|
+
const ArrayView_1 = require("./ArrayView");
|
|
7
9
|
const Content_1 = require("./Content");
|
|
8
10
|
const ContentKind_1 = require("./ContentKind");
|
|
9
11
|
const Operation_1 = require("./Operation");
|
|
@@ -31,6 +33,7 @@ class Collection extends Content_1.Content {
|
|
|
31
33
|
}
|
|
32
34
|
constructor(doc, shouldAcquire, shareSync) {
|
|
33
35
|
super(doc, shouldAcquire, shareSync);
|
|
36
|
+
this._phrasesView = new ArrayView_1.ArrayView(this, ['payload', 'phrases']);
|
|
34
37
|
}
|
|
35
38
|
/**
|
|
36
39
|
* Create a new Collection for a user.
|
|
@@ -50,6 +53,7 @@ class Collection extends Content_1.Content {
|
|
|
50
53
|
payload: {
|
|
51
54
|
collection_key: params.collectionKey,
|
|
52
55
|
conditions: params.conditions,
|
|
56
|
+
phrases: params.phrases,
|
|
53
57
|
display: params.display,
|
|
54
58
|
// Initial IRT proficiency - high uncertainty, no data yet
|
|
55
59
|
proficiency: SkillLevel_1.SkillLevelModel.createDefault(),
|
|
@@ -86,6 +90,13 @@ class Collection extends Content_1.Content {
|
|
|
86
90
|
return this.payload.conditions;
|
|
87
91
|
}
|
|
88
92
|
// ============================================================
|
|
93
|
+
// Explicit phrases getters
|
|
94
|
+
// ============================================================
|
|
95
|
+
get phrases() {
|
|
96
|
+
this.checkDisposed("Collection.phrases");
|
|
97
|
+
return this._phrasesView;
|
|
98
|
+
}
|
|
99
|
+
// ============================================================
|
|
89
100
|
// Display metadata getters
|
|
90
101
|
// ============================================================
|
|
91
102
|
get display() {
|
|
@@ -222,6 +233,27 @@ class Collection extends Content_1.Content {
|
|
|
222
233
|
};
|
|
223
234
|
}
|
|
224
235
|
// ============================================================
|
|
236
|
+
// Matching
|
|
237
|
+
// ============================================================
|
|
238
|
+
/**
|
|
239
|
+
* Check if a phrase belongs to this collection.
|
|
240
|
+
*
|
|
241
|
+
* First checks for an exact match in the explicit phrases list,
|
|
242
|
+
* then falls back to condition matching if no explicit match is found.
|
|
243
|
+
*/
|
|
244
|
+
matches(phrase) {
|
|
245
|
+
this.checkDisposed("Collection.matches");
|
|
246
|
+
// First, check for an exact match in the explicit phrases list
|
|
247
|
+
const phrases = this.payload.phrases;
|
|
248
|
+
for (const p of phrases) {
|
|
249
|
+
if (p.text === phrase.text && p.sense_rank === phrase.sense_rank) {
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// If no explicit match, fall back to condition matching
|
|
254
|
+
return ConditionMatcher_1.ConditionMatcher.matchesConditions(phrase, this.payload.conditions);
|
|
255
|
+
}
|
|
256
|
+
// ============================================================
|
|
225
257
|
// Mutators
|
|
226
258
|
// ============================================================
|
|
227
259
|
/**
|
package/dist/models/Device.d.ts
CHANGED
|
@@ -89,11 +89,12 @@ export declare class Device extends Content {
|
|
|
89
89
|
get currentSearchState(): SearchState | undefined;
|
|
90
90
|
/**
|
|
91
91
|
* Returns true if back navigation is possible.
|
|
92
|
-
*
|
|
92
|
+
* Skips over empty entries to find a non-empty one.
|
|
93
93
|
*/
|
|
94
94
|
get canGoBack(): boolean;
|
|
95
95
|
/**
|
|
96
96
|
* Returns true if forward navigation is possible.
|
|
97
|
+
* Skips over empty entries to find a non-empty one.
|
|
97
98
|
*/
|
|
98
99
|
get canGoForward(): boolean;
|
|
99
100
|
/**
|
|
@@ -106,12 +107,12 @@ export declare class Device extends Content {
|
|
|
106
107
|
*/
|
|
107
108
|
pushSearchState(state: SearchState): SearchState | undefined;
|
|
108
109
|
/**
|
|
109
|
-
* Navigates back in search history.
|
|
110
|
+
* Navigates back in search history, skipping over empty entries.
|
|
110
111
|
* @returns The search state at the new cursor position, or undefined if can't go back
|
|
111
112
|
*/
|
|
112
113
|
goBack(): SearchState | undefined;
|
|
113
114
|
/**
|
|
114
|
-
* Navigates forward in search history.
|
|
115
|
+
* Navigates forward in search history, skipping over empty entries.
|
|
115
116
|
* @returns The search state at the new cursor position, or undefined if can't go forward
|
|
116
117
|
*/
|
|
117
118
|
goForward(): SearchState | undefined;
|
package/dist/models/Device.js
CHANGED
|
@@ -267,24 +267,33 @@ class Device extends Content_1.Content {
|
|
|
267
267
|
}
|
|
268
268
|
/**
|
|
269
269
|
* Returns true if back navigation is possible.
|
|
270
|
-
*
|
|
270
|
+
* Skips over empty entries to find a non-empty one.
|
|
271
271
|
*/
|
|
272
272
|
get canGoBack() {
|
|
273
273
|
this.checkDisposed("Device.canGoBack");
|
|
274
274
|
const history = this.searchHistory;
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
275
|
+
// Look for any non-empty entry before the cursor
|
|
276
|
+
for (let i = history.cursor - 1; i >= 0; i--) {
|
|
277
|
+
if (!(0, SearchState_1.isEmptySearchState)(history.entries[i])) {
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return false;
|
|
280
282
|
}
|
|
281
283
|
/**
|
|
282
284
|
* Returns true if forward navigation is possible.
|
|
285
|
+
* Skips over empty entries to find a non-empty one.
|
|
283
286
|
*/
|
|
284
287
|
get canGoForward() {
|
|
285
288
|
this.checkDisposed("Device.canGoForward");
|
|
286
289
|
const history = this.searchHistory;
|
|
287
|
-
|
|
290
|
+
// Look for any non-empty entry after the cursor
|
|
291
|
+
for (let i = history.cursor + 1; i < history.entries.length; i++) {
|
|
292
|
+
if (!(0, SearchState_1.isEmptySearchState)(history.entries[i])) {
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return false;
|
|
288
297
|
}
|
|
289
298
|
/**
|
|
290
299
|
* Pushes a new search state onto the history stack.
|
|
@@ -328,7 +337,7 @@ class Device extends Content_1.Content {
|
|
|
328
337
|
return state;
|
|
329
338
|
}
|
|
330
339
|
/**
|
|
331
|
-
* Navigates back in search history.
|
|
340
|
+
* Navigates back in search history, skipping over empty entries.
|
|
332
341
|
* @returns The search state at the new cursor position, or undefined if can't go back
|
|
333
342
|
*/
|
|
334
343
|
goBack() {
|
|
@@ -337,14 +346,21 @@ class Device extends Content_1.Content {
|
|
|
337
346
|
return undefined;
|
|
338
347
|
}
|
|
339
348
|
const history = this.searchHistory;
|
|
340
|
-
|
|
349
|
+
// Find the first non-empty entry before the cursor
|
|
350
|
+
let newCursor = history.cursor - 1;
|
|
351
|
+
while (newCursor >= 0 && (0, SearchState_1.isEmptySearchState)(history.entries[newCursor])) {
|
|
352
|
+
newCursor--;
|
|
353
|
+
}
|
|
354
|
+
if (newCursor < 0) {
|
|
355
|
+
return undefined;
|
|
356
|
+
}
|
|
341
357
|
const batch = new Operation_1.BatchOperation(this);
|
|
342
358
|
batch.setPathValue(['payload', 'search_history', 'cursor'], newCursor);
|
|
343
359
|
batch.commit();
|
|
344
360
|
return history.entries[newCursor];
|
|
345
361
|
}
|
|
346
362
|
/**
|
|
347
|
-
* Navigates forward in search history.
|
|
363
|
+
* Navigates forward in search history, skipping over empty entries.
|
|
348
364
|
* @returns The search state at the new cursor position, or undefined if can't go forward
|
|
349
365
|
*/
|
|
350
366
|
goForward() {
|
|
@@ -353,7 +369,14 @@ class Device extends Content_1.Content {
|
|
|
353
369
|
return undefined;
|
|
354
370
|
}
|
|
355
371
|
const history = this.searchHistory;
|
|
356
|
-
|
|
372
|
+
// Find the first non-empty entry after the cursor
|
|
373
|
+
let newCursor = history.cursor + 1;
|
|
374
|
+
while (newCursor < history.entries.length && (0, SearchState_1.isEmptySearchState)(history.entries[newCursor])) {
|
|
375
|
+
newCursor++;
|
|
376
|
+
}
|
|
377
|
+
if (newCursor >= history.entries.length) {
|
|
378
|
+
return undefined;
|
|
379
|
+
}
|
|
357
380
|
const batch = new Operation_1.BatchOperation(this);
|
|
358
381
|
batch.setPathValue(['payload', 'search_history', 'cursor'], newCursor);
|
|
359
382
|
batch.commit();
|