@shaxpir/duiduidui-models 1.2.1 → 1.3.0

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.
@@ -23,4 +23,8 @@ export declare class Progress extends Content {
23
23
  static create(userId: ContentId): Progress;
24
24
  constructor(doc: Doc, shouldAcquire: boolean, shareSync: ShareSync);
25
25
  get payload(): ProgressPayload;
26
+ setUserRank(value: number): void;
27
+ setCognitiveLoad(value: number): void;
28
+ updatePhraseProgress(phraseId: string, progress: PhraseProgress): void;
29
+ updateMultiplePhrases(updates: Record<string, PhraseProgress>): void;
26
30
  }
@@ -5,6 +5,7 @@ const shaxpir_common_1 = require("@shaxpir/shaxpir-common");
5
5
  const repo_1 = require("../repo");
6
6
  const Content_1 = require("./Content");
7
7
  const ContentKind_1 = require("./ContentKind");
8
+ const Operation_1 = require("./Operation");
8
9
  class Progress extends Content_1.Content {
9
10
  static makeProgressId(userId) {
10
11
  return shaxpir_common_1.CachingHasher.makeMd5Base62Hash(userId + "-" + ContentKind_1.ContentKind.PROGRESS);
@@ -35,5 +36,35 @@ class Progress extends Content_1.Content {
35
36
  this.checkDisposed("Progress.payload");
36
37
  return this.doc.data.payload;
37
38
  }
39
+ setUserRank(value) {
40
+ this.checkDisposed("Progress.setUserRank");
41
+ if (this.payload.user_rank !== value) {
42
+ const batch = new Operation_1.BatchOperation(this);
43
+ batch.setPathValue(['payload', 'user_rank'], value);
44
+ batch.commit();
45
+ }
46
+ }
47
+ setCognitiveLoad(value) {
48
+ this.checkDisposed("Progress.setCognitiveLoad");
49
+ if (this.payload.cognitive_load !== value) {
50
+ const batch = new Operation_1.BatchOperation(this);
51
+ batch.setPathValue(['payload', 'cognitive_load'], value);
52
+ batch.commit();
53
+ }
54
+ }
55
+ updatePhraseProgress(phraseId, progress) {
56
+ this.checkDisposed("Progress.updatePhraseProgress");
57
+ const batch = new Operation_1.BatchOperation(this);
58
+ batch.setPathValue(['payload', 'phrases', phraseId], progress);
59
+ batch.commit();
60
+ }
61
+ updateMultiplePhrases(updates) {
62
+ this.checkDisposed("Progress.updateMultiplePhrases");
63
+ const batch = new Operation_1.BatchOperation(this);
64
+ for (const [phraseId, progress] of Object.entries(updates)) {
65
+ batch.setPathValue(['payload', 'phrases', phraseId], progress);
66
+ }
67
+ batch.commit();
68
+ }
38
69
  }
39
70
  exports.Progress = Progress;
@@ -16,10 +16,11 @@ export interface SessionBody extends ContentBody {
16
16
  payload: SessionPayload;
17
17
  }
18
18
  export declare class Session extends Content {
19
+ private _reviewsView;
20
+ constructor(doc: Doc, shouldAcquire: boolean, shareSync: ShareSync);
19
21
  static makeSessionId(userId: ContentId): ContentId;
20
22
  static makeSessionRef(userId: ContentId, at: MultiTime): ContentRef;
21
23
  static create(userId: ContentId, deviceId: ContentId): Session;
22
- constructor(doc: Doc, shouldAcquire: boolean, shareSync: ShareSync);
23
24
  get payload(): SessionPayload;
24
25
  touch(): void;
25
26
  get start(): MultiTime;
@@ -28,4 +29,5 @@ export declare class Session extends Content {
28
29
  get durationMinutes(): number;
29
30
  get deviceId(): ContentId;
30
31
  modelUpdated(): Promise<void>;
32
+ addReview(review: Review): void;
31
33
  }
@@ -8,7 +8,12 @@ const ContentKind_1 = require("./ContentKind");
8
8
  const Metric_1 = require("./Metric");
9
9
  const Operation_1 = require("./Operation");
10
10
  const Workspace_1 = require("./Workspace");
11
+ const ArrayView_1 = require("./ArrayView");
11
12
  class Session extends Content_1.Content {
13
+ constructor(doc, shouldAcquire, shareSync) {
14
+ super(doc, shouldAcquire, shareSync);
15
+ this._reviewsView = new ArrayView_1.ArrayView(this, ['payload', 'reviews']);
16
+ }
12
17
  static makeSessionId(userId) {
13
18
  return shaxpir_common_1.CachingHasher.makeMd5Base62Hash(userId + "-" + ContentKind_1.ContentKind.SESSION);
14
19
  }
@@ -39,9 +44,6 @@ class Session extends Content_1.Content {
39
44
  }
40
45
  });
41
46
  }
42
- constructor(doc, shouldAcquire, shareSync) {
43
- super(doc, shouldAcquire, shareSync);
44
- }
45
47
  get payload() {
46
48
  this.checkDisposed("Session.payload");
47
49
  return this.doc.data.payload;
@@ -99,5 +101,9 @@ class Session extends Content_1.Content {
99
101
  minutesWritingMetric.setDateAmount(date, minutesWritingOnDate);
100
102
  minutesWritingMetric.release();
101
103
  }
104
+ addReview(review) {
105
+ this.checkDisposed("Session.addReview");
106
+ this._reviewsView.push(review);
107
+ }
102
108
  }
103
109
  exports.Session = Session;
@@ -29,8 +29,13 @@ export interface TermBody extends ContentBody {
29
29
  }
30
30
  export declare class Term extends Content {
31
31
  static makeTermId(userId: ContentId, text: string, senseRank: number): ContentId;
32
+ private _reviewsView;
33
+ constructor(doc: Doc, shouldAcquire: boolean, shareSync: ShareSync);
34
+ static forUserPhrase(userId: ContentId, text: string, senseRank: number, learnRank: number, phraseId?: number): Term;
32
35
  static forUserPhrase(userId: ContentId, phrase: Phrase): Term;
33
36
  static forBuiltinPhrase(userId: ContentId, phrase: BuiltInPhrase): Term;
34
- constructor(doc: Doc, shouldAcquire: boolean, shareSync: ShareSync);
35
37
  get payload(): TermPayload;
38
+ setStarredAt(value: CompactDateTime | null): void;
39
+ updateBayesianScore(alpha: number, beta: number, theta: number): void;
40
+ addReview(review: ReviewLike): void;
36
41
  }
@@ -5,15 +5,41 @@ const shaxpir_common_1 = require("@shaxpir/shaxpir-common");
5
5
  const Content_1 = require("./Content");
6
6
  const ContentKind_1 = require("./ContentKind");
7
7
  const repo_1 = require("../repo");
8
+ const Operation_1 = require("./Operation");
9
+ const ArrayView_1 = require("./ArrayView");
8
10
  class Term extends Content_1.Content {
9
11
  static makeTermId(userId, text, senseRank) {
10
12
  return shaxpir_common_1.CachingHasher.makeMd5Base62Hash(`${ContentKind_1.ContentKind.TERM}-${userId}-${text}-${senseRank}`);
11
13
  }
12
- static forUserPhrase(userId, phrase) {
14
+ constructor(doc, shouldAcquire, shareSync) {
15
+ super(doc, shouldAcquire, shareSync);
16
+ this._reviewsView = new ArrayView_1.ArrayView(this, ['payload', 'reviews']);
17
+ }
18
+ static forUserPhrase(userId, textOrPhrase, senseRank, learnRank, phraseId) {
13
19
  const now = shaxpir_common_1.MultiClock.now();
20
+ // Handle overloaded parameters
21
+ let phrase;
22
+ if (typeof textOrPhrase === 'string') {
23
+ // Create a minimal Phrase object from individual parameters
24
+ phrase = {
25
+ text: textOrPhrase,
26
+ sense_rank: senseRank,
27
+ learn_rank: learnRank,
28
+ hanzi_count: textOrPhrase.length,
29
+ pinyin: '',
30
+ pinyin_tokenized: '',
31
+ transliteration: '',
32
+ translation: '',
33
+ notes: '',
34
+ examples: [],
35
+ keywords: [],
36
+ tags: []
37
+ };
38
+ }
39
+ else {
40
+ phrase = textOrPhrase;
41
+ }
14
42
  const termId = shaxpir_common_1.CachingHasher.makeMd5Base62Hash(`${userId}-${phrase.text}-${phrase.sense_rank}`);
15
- const initalAlpha = phrase.learn_rank < 100 ? 1 : 2;
16
- const initalBeta = phrase.learn_rank < 100 ? 1 : 2;
17
43
  return repo_1.ShareSyncFactory.get().createContent({
18
44
  meta: {
19
45
  ref: termId,
@@ -24,7 +50,7 @@ class Term extends Content_1.Content {
24
50
  updated_at: now
25
51
  },
26
52
  payload: {
27
- phrase_id: null,
53
+ phrase_id: (typeof textOrPhrase === 'string' && phraseId) ? phraseId : null,
28
54
  text: phrase.text,
29
55
  sense_rank: phrase.sense_rank,
30
56
  hanzi_count: phrase.hanzi_count,
@@ -71,12 +97,29 @@ class Term extends Content_1.Content {
71
97
  }
72
98
  });
73
99
  }
74
- constructor(doc, shouldAcquire, shareSync) {
75
- super(doc, shouldAcquire, shareSync);
76
- }
77
100
  get payload() {
78
101
  this.checkDisposed("Term.payload");
79
102
  return this.doc.data.payload;
80
103
  }
104
+ setStarredAt(value) {
105
+ this.checkDisposed("Term.setStarredAt");
106
+ if (this.payload.starred_at !== value) {
107
+ const batch = new Operation_1.BatchOperation(this);
108
+ batch.setPathValue(['payload', 'starred_at'], value);
109
+ batch.commit();
110
+ }
111
+ }
112
+ updateBayesianScore(alpha, beta, theta) {
113
+ this.checkDisposed("Term.updateBayesianScore");
114
+ const batch = new Operation_1.BatchOperation(this);
115
+ batch.setPathValue(['payload', 'alpha'], alpha);
116
+ batch.setPathValue(['payload', 'beta'], beta);
117
+ batch.setPathValue(['payload', 'theta'], theta);
118
+ batch.commit();
119
+ }
120
+ addReview(review) {
121
+ this.checkDisposed("Term.addReview");
122
+ this._reviewsView.push(review);
123
+ }
81
124
  }
82
125
  exports.Term = Term;
@@ -48,12 +48,9 @@ const Manifest_1 = require("../models/Manifest");
48
48
  const User_1 = require("../models/User");
49
49
  // Register the ShareDB types
50
50
  const Json1 = __importStar(require("./PermissiveJson1"));
51
- const RichText = require('@shaxpir/rich-text');
52
51
  const UnicodeText = require('ot-text-unicode');
53
52
  client_1.default.types.register(Json1.type);
54
- client_1.default.types.register(RichText.type);
55
53
  client_1.default.types.register(UnicodeText.type);
56
- Json1.type.registerSubtype(RichText.type);
57
54
  Json1.type.registerSubtype(UnicodeText.type);
58
55
  var ShareSyncDisposalStrategy;
59
56
  (function (ShareSyncDisposalStrategy) {
@@ -4,6 +4,7 @@ import { ShareSync, ShareSyncFactory } from '../repo';
4
4
  import { BayesianScore } from './BayesianScore';
5
5
  import { Content, ContentBody, ContentId, ContentMeta } from "./Content";
6
6
  import { ContentKind } from './ContentKind';
7
+ import { BatchOperation } from './Operation';
7
8
 
8
9
  export interface PhraseProgress extends BayesianScore {
9
10
  text:string;
@@ -63,4 +64,38 @@ export class Progress extends Content {
63
64
  this.checkDisposed("Progress.payload");
64
65
  return this.doc.data.payload as ProgressPayload;
65
66
  }
67
+
68
+ public setUserRank(value: number): void {
69
+ this.checkDisposed("Progress.setUserRank");
70
+ if (this.payload.user_rank !== value) {
71
+ const batch = new BatchOperation(this);
72
+ batch.setPathValue(['payload', 'user_rank'], value);
73
+ batch.commit();
74
+ }
75
+ }
76
+
77
+ public setCognitiveLoad(value: number): void {
78
+ this.checkDisposed("Progress.setCognitiveLoad");
79
+ if (this.payload.cognitive_load !== value) {
80
+ const batch = new BatchOperation(this);
81
+ batch.setPathValue(['payload', 'cognitive_load'], value);
82
+ batch.commit();
83
+ }
84
+ }
85
+
86
+ public updatePhraseProgress(phraseId: string, progress: PhraseProgress): void {
87
+ this.checkDisposed("Progress.updatePhraseProgress");
88
+ const batch = new BatchOperation(this);
89
+ batch.setPathValue(['payload', 'phrases', phraseId], progress);
90
+ batch.commit();
91
+ }
92
+
93
+ public updateMultiplePhrases(updates: Record<string, PhraseProgress>): void {
94
+ this.checkDisposed("Progress.updateMultiplePhrases");
95
+ const batch = new BatchOperation(this);
96
+ for (const [phraseId, progress] of Object.entries(updates)) {
97
+ batch.setPathValue(['payload', 'phrases', phraseId], progress);
98
+ }
99
+ batch.commit();
100
+ }
66
101
  }
@@ -7,6 +7,7 @@ import { Metric, MetricName } from './Metric';
7
7
  import { BatchOperation } from './Operation';
8
8
  import { Review } from './Review';
9
9
  import { Workspace } from './Workspace';
10
+ import { ArrayView } from './ArrayView';
10
11
 
11
12
 
12
13
  export interface SessionPayload {
@@ -25,6 +26,13 @@ export interface SessionBody extends ContentBody {
25
26
 
26
27
  export class Session extends Content {
27
28
 
29
+ private _reviewsView:ArrayView<Review>;
30
+
31
+ constructor(doc:Doc, shouldAcquire:boolean, shareSync:ShareSync) {
32
+ super(doc, shouldAcquire, shareSync);
33
+ this._reviewsView = new ArrayView(this, [ 'payload', 'reviews' ]);
34
+ }
35
+
28
36
  public static makeSessionId(userId:ContentId):ContentId {
29
37
  return CachingHasher.makeMd5Base62Hash(userId + "-" + ContentKind.SESSION) as ContentId;
30
38
  }
@@ -65,10 +73,6 @@ export class Session extends Content {
65
73
  ) as Session;
66
74
  }
67
75
 
68
- constructor(doc:Doc, shouldAcquire:boolean, shareSync:ShareSync) {
69
- super(doc, shouldAcquire, shareSync);
70
- }
71
-
72
76
  public get payload():SessionPayload {
73
77
  this.checkDisposed("Session.payload");
74
78
  return this.doc.data.payload;
@@ -137,4 +141,9 @@ export class Session extends Content {
137
141
  minutesWritingMetric.setDateAmount(date, minutesWritingOnDate);
138
142
  minutesWritingMetric.release();
139
143
  }
144
+
145
+ public addReview(review: Review): void {
146
+ this.checkDisposed("Session.addReview");
147
+ this._reviewsView.push(review);
148
+ }
140
149
  }
@@ -6,6 +6,8 @@ import { BuiltInPhrase, Phrase, PhraseExample } from './Phrase';
6
6
  import { ReviewLike } from "./Review";
7
7
  import { ContentKind } from './ContentKind';
8
8
  import { ShareSync, ShareSyncFactory } from '../repo';
9
+ import { BatchOperation } from './Operation';
10
+ import { ArrayView } from './ArrayView';
9
11
 
10
12
  export interface TermPayload extends BayesianScore {
11
13
 
@@ -46,14 +48,56 @@ export class Term extends Content {
46
48
  return CachingHasher.makeMd5Base62Hash(`${ContentKind.TERM}-${userId}-${text}-${senseRank}`) as ContentId;
47
49
  }
48
50
 
51
+ private _reviewsView:ArrayView<ReviewLike>;
52
+
53
+ constructor(doc:Doc, shouldAcquire:boolean, shareSync:ShareSync) {
54
+ super(doc, shouldAcquire, shareSync);
55
+ this._reviewsView = new ArrayView(this, [ 'payload', 'reviews' ]);
56
+ }
57
+
58
+ public static forUserPhrase(
59
+ userId:ContentId,
60
+ text:string,
61
+ senseRank:number,
62
+ learnRank:number,
63
+ phraseId?:number
64
+ ):Term;
49
65
  public static forUserPhrase(
50
66
  userId:ContentId,
51
67
  phrase:Phrase
68
+ ):Term;
69
+ public static forUserPhrase(
70
+ userId:ContentId,
71
+ textOrPhrase:string | Phrase,
72
+ senseRank?:number,
73
+ learnRank?:number,
74
+ phraseId?:number
52
75
  ):Term {
53
76
  const now = MultiClock.now();
77
+
78
+ // Handle overloaded parameters
79
+ let phrase: Phrase;
80
+ if (typeof textOrPhrase === 'string') {
81
+ // Create a minimal Phrase object from individual parameters
82
+ phrase = {
83
+ text: textOrPhrase,
84
+ sense_rank: senseRank!,
85
+ learn_rank: learnRank!,
86
+ hanzi_count: textOrPhrase.length,
87
+ pinyin: '',
88
+ pinyin_tokenized: '',
89
+ transliteration: '',
90
+ translation: '',
91
+ notes: '',
92
+ examples: [],
93
+ keywords: [],
94
+ tags: []
95
+ } as Phrase;
96
+ } else {
97
+ phrase = textOrPhrase;
98
+ }
99
+
54
100
  const termId = CachingHasher.makeMd5Base62Hash(`${userId}-${phrase.text}-${phrase.sense_rank}`) as ContentId;
55
- const initalAlpha = phrase.learn_rank < 100 ? 1 : 2;
56
- const initalBeta = phrase.learn_rank < 100 ? 1 : 2;
57
101
  return ShareSyncFactory.get().createContent(
58
102
  {
59
103
  meta : {
@@ -66,7 +110,7 @@ export class Term extends Content {
66
110
  },
67
111
  payload : {
68
112
 
69
- phrase_id : null,
113
+ phrase_id : (typeof textOrPhrase === 'string' && phraseId) ? phraseId : null,
70
114
  text : phrase.text,
71
115
  sense_rank : phrase.sense_rank,
72
116
  hanzi_count : phrase.hanzi_count,
@@ -128,12 +172,31 @@ export class Term extends Content {
128
172
  ) as Term;
129
173
  }
130
174
 
131
- constructor(doc:Doc, shouldAcquire:boolean, shareSync:ShareSync) {
132
- super(doc, shouldAcquire, shareSync);
133
- }
134
-
135
175
  public get payload():TermPayload {
136
176
  this.checkDisposed("Term.payload");
137
177
  return this.doc.data.payload as TermPayload;
138
178
  }
179
+
180
+ public setStarredAt(value: CompactDateTime | null): void {
181
+ this.checkDisposed("Term.setStarredAt");
182
+ if (this.payload.starred_at !== value) {
183
+ const batch = new BatchOperation(this);
184
+ batch.setPathValue(['payload', 'starred_at'], value);
185
+ batch.commit();
186
+ }
187
+ }
188
+
189
+ public updateBayesianScore(alpha: number, beta: number, theta: number): void {
190
+ this.checkDisposed("Term.updateBayesianScore");
191
+ const batch = new BatchOperation(this);
192
+ batch.setPathValue(['payload', 'alpha'], alpha);
193
+ batch.setPathValue(['payload', 'beta'], beta);
194
+ batch.setPathValue(['payload', 'theta'], theta);
195
+ batch.commit();
196
+ }
197
+
198
+ public addReview(review: ReviewLike): void {
199
+ this.checkDisposed("Term.addReview");
200
+ this._reviewsView.push(review);
201
+ }
139
202
  }
@@ -13,14 +13,11 @@ import { ConnectionListener } from './ConnectionListener';
13
13
  // Register the ShareDB types
14
14
  import * as Json1 from './PermissiveJson1';
15
15
 
16
- const RichText = require('@shaxpir/rich-text');
17
16
  const UnicodeText = require('ot-text-unicode');
18
17
 
19
18
  ShareDB.types.register(Json1.type);
20
- ShareDB.types.register(RichText.type);
21
19
  ShareDB.types.register(UnicodeText.type);
22
20
 
23
- Json1.type.registerSubtype(RichText.type);
24
21
  Json1.type.registerSubtype(UnicodeText.type);
25
22
 
26
23
  export enum ShareSyncDisposalStrategy {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shaxpir/duiduidui-models",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/shaxpir/duiduidui-models"