• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16class PrefetchCount {
17  private readonly itemsOnScreen: IItemsOnScreenProvider;
18  private readonly MAX_SCREENS = 4;
19  private readonly MIN_SCREENS = 0.6;
20  private min = 0;
21  private max = 0;
22
23  constructor(itemsOnScreen: IItemsOnScreenProvider) {
24    this.itemsOnScreen = itemsOnScreen;
25    this.itemsOnScreen.register(() => {
26      this.updateLimits();
27    });
28  }
29
30  private _prefetchCountValue = 0;
31
32  get prefetchCountValue(): number {
33    return this._prefetchCountValue;
34  }
35
36  set prefetchCountValue(v: number) {
37    this._prefetchCountValue = v;
38    Logger.log(`{"tm":${Date.now()},"prefetch_count":${v}}`);
39  }
40
41  private _currentLimit = 0;
42
43  get currentLimit(): number {
44    return this._currentLimit;
45  }
46
47  private _maxRatio = 0.5;
48
49  get maxRatio(): number {
50    return this._maxRatio;
51  }
52
53  set maxRatio(value: number) {
54    this._maxRatio = value;
55    this.updateCurrentLimit();
56  }
57
58  getPrefetchCountByRatio(ratio: number): number {
59    return this.min + Math.ceil(ratio * (this.currentLimit - this.min));
60  }
61
62  getRangeToPrefetch(totalCount: number): IndexRange {
63    const visibleRange = this.itemsOnScreen.visibleRange;
64    let start = 0;
65    let end = 0;
66    switch (this.itemsOnScreen.direction) {
67      case 'UNKNOWN':
68        start = Math.max(0, visibleRange.start - Math.round(this.prefetchCountValue));
69        end = Math.min(totalCount, visibleRange.end + Math.round(this.prefetchCountValue));
70        break;
71      case 'UP':
72        start = Math.max(0, visibleRange.start - Math.round(this.prefetchCountValue));
73        end = Math.min(totalCount, visibleRange.end + Math.round(this.prefetchCountValue * 0.5));
74        break;
75      case 'DOWN':
76        start = Math.max(0, visibleRange.start - Math.round(this.prefetchCountValue * 0.5));
77        end = Math.min(totalCount, visibleRange.end + Math.round(this.prefetchCountValue));
78        break;
79    }
80    return new IndexRange(start, end);
81  }
82
83  private updateLimits(): void {
84    this.min = Math.ceil(this.itemsOnScreen.meanValue * this.MIN_SCREENS);
85    this.max = Math.max(this.min, Math.ceil(this.MAX_SCREENS * this.itemsOnScreen.meanValue));
86    this.updateCurrentLimit();
87  }
88
89  private updateCurrentLimit(): void {
90    this._currentLimit = Math.max(this.min, Math.ceil(this.max * this._maxRatio));
91  }
92}
93