@bettergi/utils 0.1.26 → 0.1.28
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/ocr.d.ts +6 -9
- package/dist/ocr.js +24 -37
- package/dist/store.js +10 -10
- package/package.json +1 -1
package/dist/ocr.d.ts
CHANGED
|
@@ -112,11 +112,10 @@ export type ListView = {
|
|
|
112
112
|
* @param condition 查找条件
|
|
113
113
|
* @param listView 列表视图参数
|
|
114
114
|
* @param retryOptions 重试选项
|
|
115
|
-
* @param
|
|
116
|
-
* @param threshold 采样区域匹配阈值(默认:0.9)
|
|
115
|
+
* @param threshold 列表视图变化匹配阈值(默认:0.9)
|
|
117
116
|
* @returns 如果找到匹配的区域,则返回该区域,否则返回 undefined
|
|
118
117
|
*/
|
|
119
|
-
export declare const findWithinListView: (condition: (listViewRegion: ImageRegion) => Region | undefined, listView: ListView, retryOptions?: RetryOptions,
|
|
118
|
+
export declare const findWithinListView: (condition: (listViewRegion: ImageRegion) => Region | undefined, listView: ListView, retryOptions?: RetryOptions, threshold?: number) => Promise<Region | undefined>;
|
|
120
119
|
/**
|
|
121
120
|
* 在列表视图中滚动搜索文本
|
|
122
121
|
* @param text 待搜索文本
|
|
@@ -124,19 +123,17 @@ export declare const findWithinListView: (condition: (listViewRegion: ImageRegio
|
|
|
124
123
|
* @param matchOptions 搜索选项
|
|
125
124
|
* @param retryOptions 重试选项
|
|
126
125
|
* @param config 识别对象配置
|
|
127
|
-
* @param
|
|
128
|
-
* @param threshold 采样区域匹配阈值(默认:0.9)
|
|
126
|
+
* @param threshold 列表视图变化匹配阈值(默认:0.9)
|
|
129
127
|
* @returns 如果找到匹配的文本区域,则返回该区域,否则返回 undefined
|
|
130
128
|
*/
|
|
131
|
-
export declare const findTextWithinListView: (text: string, listView: ListView, matchOptions?: TextMatchOptions, retryOptions?: RetryOptions, config?: ROConfig,
|
|
129
|
+
export declare const findTextWithinListView: (text: string, listView: ListView, matchOptions?: TextMatchOptions, retryOptions?: RetryOptions, config?: ROConfig, threshold?: number) => Promise<Region | undefined>;
|
|
132
130
|
/**
|
|
133
131
|
* 在列表视图中查找图像
|
|
134
132
|
* @param image 图片路径 或 图片Mat
|
|
135
133
|
* @param listView 列表视图参数
|
|
136
134
|
* @param retryOptions 重试选项
|
|
137
135
|
* @param config 识别对象配置
|
|
138
|
-
* @param
|
|
139
|
-
* @param threshold 采样区域匹配阈值(默认:0.9)
|
|
136
|
+
* @param threshold 列表视图变化匹配阈值(默认:0.9)
|
|
140
137
|
* @returns 如果找到匹配的区域,则返回该区域,否则返回 undefined
|
|
141
138
|
*/
|
|
142
|
-
export declare const findImageWithinListView: (image: string | ImageMat, listView: ListView, retryOptions?: RetryOptions, config?: ROConfig,
|
|
139
|
+
export declare const findImageWithinListView: (image: string | ImageMat, listView: ListView, retryOptions?: RetryOptions, config?: ROConfig, threshold?: number) => Promise<Region | undefined>;
|
package/dist/ocr.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import { mouseScrollDownLines } from "./mouse";
|
|
2
2
|
import { waitForAction } from "./workflow";
|
|
3
|
+
const scaleTo1080P = (n) => {
|
|
4
|
+
return genshin.scaleTo1080PRatio <= 1 ? n : n / Math.floor(genshin.scaleTo1080PRatio);
|
|
5
|
+
};
|
|
3
6
|
const directionToBounds = (direction) => {
|
|
4
7
|
const x = direction.includes("east") ? genshin.width / 2 : 0;
|
|
5
8
|
const y = direction.includes("south") ? genshin.height / 2 : 0;
|
|
6
9
|
const w = direction === "north" || direction === "south" ? genshin.width : genshin.width / 2;
|
|
7
10
|
const h = direction === "west" || direction === "east" ? genshin.height : genshin.height / 2;
|
|
8
|
-
|
|
9
|
-
if (scale <= 1) {
|
|
10
|
-
return { x, y, w, h };
|
|
11
|
-
}
|
|
12
|
-
else {
|
|
13
|
-
return { x: x / scale, y: y / scale, w: w / scale, h: h / scale };
|
|
14
|
-
}
|
|
11
|
+
return { x: scaleTo1080P(x), y: scaleTo1080P(y), w: scaleTo1080P(w), h: scaleTo1080P(h) };
|
|
15
12
|
};
|
|
16
13
|
/**
|
|
17
14
|
* 在整个画面内搜索图片
|
|
@@ -202,36 +199,34 @@ export const findTextInDirection = (text, direction, options, config = {}) => {
|
|
|
202
199
|
* @param condition 查找条件
|
|
203
200
|
* @param listView 列表视图参数
|
|
204
201
|
* @param retryOptions 重试选项
|
|
205
|
-
* @param
|
|
206
|
-
* @param threshold 采样区域匹配阈值(默认:0.9)
|
|
202
|
+
* @param threshold 列表视图变化匹配阈值(默认:0.9)
|
|
207
203
|
* @returns 如果找到匹配的区域,则返回该区域,否则返回 undefined
|
|
208
204
|
*/
|
|
209
|
-
export const findWithinListView = async (condition, listView, retryOptions,
|
|
205
|
+
export const findWithinListView = async (condition, listView, retryOptions, threshold = 0.9) => {
|
|
210
206
|
const { x, y, w, h, lineHeight, scrollLines = 1, paddingX = 10, paddingY = 10 } = listView;
|
|
211
207
|
const { maxAttempts = 99, retryInterval = 1200 } = retryOptions || {};
|
|
212
|
-
sampling ??= r => r.deriveCrop(1, r.height * 0.5, r.width - 1, r.height * 0.5);
|
|
213
208
|
const captureListViewRegion = () => captureGameRegion().deriveCrop(x, y, w, h);
|
|
214
209
|
const isReachedBottom = (() => {
|
|
210
|
+
let captured;
|
|
215
211
|
let lastCaptured;
|
|
216
212
|
return () => {
|
|
217
|
-
const newRegion = captureListViewRegion();
|
|
218
|
-
if (!newRegion?.isExist())
|
|
219
|
-
return true;
|
|
220
213
|
try {
|
|
214
|
+
captured = captureListViewRegion();
|
|
221
215
|
if (!lastCaptured)
|
|
222
216
|
return false;
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
// 根据采样区域画面是否变化,判断列表是否触底
|
|
227
|
-
const ro = RecognitionObject.templateMatch(oldRegion.srcMat);
|
|
217
|
+
// 根据列表视图区域画面是否变化,判断列表是否触底
|
|
218
|
+
const lc = lastCaptured.deriveCrop(1, 1, lastCaptured.width - 2, lastCaptured.height - 2);
|
|
219
|
+
const ro = RecognitionObject.templateMatch(lc.srcMat);
|
|
228
220
|
ro.threshold = threshold;
|
|
229
221
|
ro.use3Channels = true;
|
|
230
222
|
ro.initTemplate();
|
|
231
|
-
return
|
|
223
|
+
return captured.find(ro).isExist();
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
return true;
|
|
232
227
|
}
|
|
233
228
|
finally {
|
|
234
|
-
lastCaptured =
|
|
229
|
+
lastCaptured = captured;
|
|
235
230
|
}
|
|
236
231
|
};
|
|
237
232
|
})();
|
|
@@ -241,18 +236,12 @@ export const findWithinListView = async (condition, listView, retryOptions, samp
|
|
|
241
236
|
return targetRegion?.isExist() || isReachedBottom();
|
|
242
237
|
}, async () => {
|
|
243
238
|
moveMouseTo(x + w - paddingX, y + paddingY); // 移动到滚动条附近
|
|
244
|
-
await sleep(
|
|
239
|
+
await sleep(200); // 等待画面稳定
|
|
245
240
|
await mouseScrollDownLines(scrollLines, lineHeight); // 滚动指定行数
|
|
246
241
|
}, { maxAttempts, retryInterval });
|
|
247
242
|
if (targetRegion?.isExist()) {
|
|
248
243
|
const { item1, item2 } = targetRegion.convertPositionToGameCaptureRegion(0, 0);
|
|
249
|
-
|
|
250
|
-
if (scale <= 1) {
|
|
251
|
-
Object.assign(targetRegion, { x: item1, y: item2 });
|
|
252
|
-
}
|
|
253
|
-
else {
|
|
254
|
-
Object.assign(targetRegion, { x: item1 / scale, y: item2 / scale });
|
|
255
|
-
}
|
|
244
|
+
Object.assign(targetRegion, { x: scaleTo1080P(item1), y: scaleTo1080P(item2) });
|
|
256
245
|
return targetRegion;
|
|
257
246
|
}
|
|
258
247
|
};
|
|
@@ -263,11 +252,10 @@ export const findWithinListView = async (condition, listView, retryOptions, samp
|
|
|
263
252
|
* @param matchOptions 搜索选项
|
|
264
253
|
* @param retryOptions 重试选项
|
|
265
254
|
* @param config 识别对象配置
|
|
266
|
-
* @param
|
|
267
|
-
* @param threshold 采样区域匹配阈值(默认:0.9)
|
|
255
|
+
* @param threshold 列表视图变化匹配阈值(默认:0.9)
|
|
268
256
|
* @returns 如果找到匹配的文本区域,则返回该区域,否则返回 undefined
|
|
269
257
|
*/
|
|
270
|
-
export const findTextWithinListView = async (text, listView, matchOptions, retryOptions, config = {},
|
|
258
|
+
export const findTextWithinListView = async (text, listView, matchOptions, retryOptions, config = {}, threshold = 0.9) => {
|
|
271
259
|
const ro = RecognitionObject.ocrThis;
|
|
272
260
|
if (Object.keys(config).length > 0) {
|
|
273
261
|
Object.assign(ro, config) && ro.initTemplate();
|
|
@@ -276,7 +264,7 @@ export const findTextWithinListView = async (text, listView, matchOptions, retry
|
|
|
276
264
|
return findFirstRegion(lvr, ro, region => {
|
|
277
265
|
return region.isExist() && textMatch(region.text, text, matchOptions);
|
|
278
266
|
});
|
|
279
|
-
}, listView, retryOptions,
|
|
267
|
+
}, listView, retryOptions, threshold);
|
|
280
268
|
};
|
|
281
269
|
/**
|
|
282
270
|
* 在列表视图中查找图像
|
|
@@ -284,11 +272,10 @@ export const findTextWithinListView = async (text, listView, matchOptions, retry
|
|
|
284
272
|
* @param listView 列表视图参数
|
|
285
273
|
* @param retryOptions 重试选项
|
|
286
274
|
* @param config 识别对象配置
|
|
287
|
-
* @param
|
|
288
|
-
* @param threshold 采样区域匹配阈值(默认:0.9)
|
|
275
|
+
* @param threshold 列表视图变化匹配阈值(默认:0.9)
|
|
289
276
|
* @returns 如果找到匹配的区域,则返回该区域,否则返回 undefined
|
|
290
277
|
*/
|
|
291
|
-
export const findImageWithinListView = async (image, listView, retryOptions, config = {},
|
|
278
|
+
export const findImageWithinListView = async (image, listView, retryOptions, config = {}, threshold = 0.9) => {
|
|
292
279
|
const mat = typeof image === "string" ? file.readImageMatSync(image) : image;
|
|
293
280
|
const ro = RecognitionObject.templateMatch(mat);
|
|
294
281
|
if (Object.keys(config).length > 0) {
|
|
@@ -297,5 +284,5 @@ export const findImageWithinListView = async (image, listView, retryOptions, con
|
|
|
297
284
|
return findWithinListView(ir => {
|
|
298
285
|
const region = ir.find(ro);
|
|
299
286
|
return region.isExist() ? region : undefined;
|
|
300
|
-
}, listView, retryOptions,
|
|
287
|
+
}, listView, retryOptions, threshold);
|
|
301
288
|
};
|
package/dist/store.js
CHANGED
|
@@ -7,8 +7,8 @@ import { deepMerge } from "./misc";
|
|
|
7
7
|
*/
|
|
8
8
|
export const useStore = (name) => {
|
|
9
9
|
const filePath = `store/${name}.json`;
|
|
10
|
-
//
|
|
11
|
-
const
|
|
10
|
+
// 从文件读取数据
|
|
11
|
+
const storeData = (() => {
|
|
12
12
|
try {
|
|
13
13
|
const storeFiles = [...file.readPathSync("store")].map(path => path.replace(/\\/g, "/"));
|
|
14
14
|
if (!storeFiles.includes(filePath))
|
|
@@ -21,22 +21,22 @@ export const useStore = (name) => {
|
|
|
21
21
|
}
|
|
22
22
|
})();
|
|
23
23
|
// 创建代理函数
|
|
24
|
-
const createProxy = (
|
|
25
|
-
if (typeof
|
|
26
|
-
return
|
|
24
|
+
const createProxy = (targetObject, parentPath = []) => {
|
|
25
|
+
if (typeof targetObject !== "object" || targetObject === null) {
|
|
26
|
+
return targetObject;
|
|
27
27
|
}
|
|
28
|
-
return new Proxy(
|
|
28
|
+
return new Proxy(targetObject, {
|
|
29
29
|
get: (target, key) => {
|
|
30
30
|
const value = Reflect.get(target, key);
|
|
31
31
|
return typeof value === "object" && value !== null
|
|
32
|
-
? createProxy(value, [...parentPath, key])
|
|
32
|
+
? createProxy(value, [...parentPath, key])
|
|
33
33
|
: value;
|
|
34
34
|
},
|
|
35
35
|
set: (target, key, value) => {
|
|
36
36
|
const success = Reflect.set(target, key, value);
|
|
37
37
|
if (success) {
|
|
38
38
|
Promise.resolve().then(() => {
|
|
39
|
-
file.writeTextSync(filePath, JSON.stringify(
|
|
39
|
+
file.writeTextSync(filePath, JSON.stringify(storeData, null, 2));
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
return success;
|
|
@@ -45,14 +45,14 @@ export const useStore = (name) => {
|
|
|
45
45
|
const success = Reflect.deleteProperty(target, key);
|
|
46
46
|
if (success) {
|
|
47
47
|
Promise.resolve().then(() => {
|
|
48
|
-
file.writeTextSync(filePath, JSON.stringify(
|
|
48
|
+
file.writeTextSync(filePath, JSON.stringify(storeData, null, 2));
|
|
49
49
|
});
|
|
50
50
|
}
|
|
51
51
|
return success;
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
54
|
};
|
|
55
|
-
return createProxy(
|
|
55
|
+
return createProxy(storeData);
|
|
56
56
|
};
|
|
57
57
|
/**
|
|
58
58
|
* 创建一个带有默认值的持久化存储对象,用于管理应用状态数据
|