Skip to content

Commit 2d037b7

Browse files
committed
add click tester
1 parent c508899 commit 2d037b7

File tree

1 file changed

+200
-47
lines changed

1 file changed

+200
-47
lines changed

tasks/clickTest.ts

Lines changed: 200 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,118 @@
11
import adb, { DeviceClient, Utils, MotionEventMap, Scrcpy } from "../src/index.js";
22
import Parser from "../src/adb/parser.js";
3+
import readline from "node:readline";
34

4-
const NB_CLICK = 1000000;
5+
const NB_CLICK = 100000000;
56

67
const Y_OFFSET = 0.02;//25;
78

8-
async function* getCenterTaps(width: number, height: number, count: number, asPercent = false) {
9+
interface TapOptions {
10+
xRadius?: number;
11+
yRadius?: number;
12+
asPercent?: boolean;
13+
fromX?: number;
14+
fromY?: number;
15+
toX?: number;
16+
toY?: number;
17+
stepX?: number;
18+
stepY?: number;
19+
}
20+
21+
const MODES = ["NONE", "CENTER", "MIX", "ALL", ] as const;
22+
let MODE: (typeof MODES)[number] = "NONE";
23+
let currentModeIndex = 0;
24+
MODE = MODES[currentModeIndex];
25+
26+
async function* getCenterTaps(width: number, height: number, options: TapOptions = {}) {
27+
const { xRadius, yRadius, asPercent = false } = options;
928
const centerX = asPercent ? width / 2 : Math.floor(width / 2);
1029
const centerY = asPercent ? height / 2 - height * Y_OFFSET : Math.floor(height / 2 - height * Y_OFFSET); // Move up by 20%
11-
const radius = Math.min(width, height) * 0.15; // 40% diameter = 20% radius
30+
const defaultRadius = Math.min(width, height) * 0.22; // 40% diameter = 20% radius
31+
const radiusX = xRadius ?? defaultRadius;
32+
const radiusY = yRadius ?? defaultRadius;
1233

13-
console.log(`Screen: ${width}x${height}, Center: ${centerX},${centerY}, Circle radius: ${radius}`);
34+
console.log(`Screen: ${width}x${height}, Center: ${centerX},${centerY}, Radius: ${radiusX}x${radiusY}`);
1435
const STEPS = 16;
15-
for (let i = 0; i < count; i++) {
16-
const angle = (2 * Math.PI * (i % STEPS)) / STEPS;
17-
const x = asPercent ? centerX + radius * Math.cos(angle) : Math.floor(centerX + radius * Math.cos(angle));
18-
const y = asPercent ? centerY + radius * Math.sin(angle) : Math.floor(centerY + radius * Math.sin(angle));
19-
yield { x, y };
20-
// await Utils.delay(100);
36+
37+
const fromX = options.fromX ?? 0.1;
38+
const fromY = options.fromY ?? 0.1;
39+
40+
const toX = options.toX ?? 0.9;
41+
const toY = options.toY ?? 0.9;
42+
43+
const selctionsCenter: Array<{ x: number, y: number }> = [];
44+
const selctionsMix: Array<{ x: number, y: number }> = [];
45+
const selctionsAll: Array<{ x: number, y: number }> = [];
46+
47+
const shuffle = (array: Array<{ x: number, y: number }>) => {
48+
for (let i = array.length - 1; i > 0; i--) {
49+
const j = Math.floor(Math.random() * (i + 1));
50+
[array[i], array[j]] = [array[j], array[i]];
51+
}
52+
};
53+
54+
// while (true)
55+
{
56+
for (let i = 0; i < (STEPS * 1); i++) {
57+
const angle = (2 * Math.PI * (i % STEPS)) / STEPS;
58+
const x = asPercent ? centerX + radiusX * Math.cos(angle) : Math.floor(centerX + radiusX * Math.cos(angle));
59+
const y = asPercent ? centerY + radiusY * Math.sin(angle) : Math.floor(centerY + radiusY * Math.sin(angle));
60+
selctionsCenter.push({ x, y });
61+
// yield { x, y };
62+
// await Utils.delay(100);
63+
}
64+
for (let x = fromX; x <= toX; x += (options.stepX ?? 0.1)) {
65+
for (let y = fromY; y <= toY; y += (options.stepY ?? 0.1)) {
66+
const posX = asPercent ? x : Math.floor(x * width);
67+
const posY = asPercent ? y : Math.floor(y * height);
68+
if (posX < 0.4 && posY < 0.4) continue;
69+
selctionsAll.push({ x: posX, y: posY });
70+
// yield { x: posX, y: posY };
71+
// await Utils.delay(100);
72+
}
73+
}
74+
selctionsMix.push(...selctionsCenter);
75+
selctionsMix.push(...selctionsCenter);
76+
selctionsMix.push(...selctionsCenter);
77+
selctionsMix.push(...selctionsCenter);
78+
selctionsMix.push(...selctionsAll);
79+
shuffle(selctionsCenter);
80+
shuffle(selctionsAll);
81+
shuffle(selctionsMix);
82+
while (true) {
83+
// console.log("Mode: ", MODE);
84+
await Utils.delay(100);
85+
if (MODE === "CENTER") {
86+
for (const selection of selctionsCenter) {
87+
await Utils.delay(1);
88+
yield selection;
89+
if (MODE !== "CENTER") {
90+
break;
91+
}
92+
}
93+
} else if (MODE === "MIX") {
94+
for (const selection of selctionsMix) {
95+
await Utils.delay(1);
96+
yield selection;
97+
if (MODE !== "MIX") {
98+
break;
99+
}
100+
}
101+
} else if (MODE === "ALL") {
102+
for (const selection of selctionsAll) {
103+
await Utils.delay(1);
104+
yield selection;
105+
if (MODE !== "ALL") {
106+
break;
107+
}
108+
}
109+
} else {
110+
await Utils.delay(100);
111+
}
112+
}
21113
}
22114
}
23115

24-
25116
async function* getGridPercent(count: number) {
26117
const XGap = 0.02;
27118
const YGap = 0.35;
@@ -45,10 +136,11 @@ async function* getGridPercent(count: number) {
45136

46137

47138

48-
async function* getCenterTapsForDevice(deviceClient: DeviceClient, count: number, asPercent = false) {
139+
async function* getCenterTapsForDevice(deviceClient: DeviceClient, options: TapOptions = {}) {
140+
const { asPercent = false } = options;
49141
if (asPercent) {
50142
// Use normalized coordinates (0-1) without retrieving actual screen size
51-
for await (const pos of getCenterTaps(1, 1, count, true)) {
143+
for await (const pos of getCenterTaps(1, 1, options)) {
52144
yield pos;
53145
}
54146
} else {
@@ -59,34 +151,15 @@ async function* getCenterTapsForDevice(deviceClient: DeviceClient, count: number
59151
}
60152
const width = parseInt(match[1]);
61153
const height = parseInt(match[2]);
62-
for await (const pos of getCenterTaps(width, height, count, false)) {
154+
for await (const pos of getCenterTaps(width, height, options)) {
63155
yield pos;
64156
}
65157
}
66158
}
67159

68-
// async function* getFixedCenterForDevice(deviceClient: DeviceClient, count: number) {
69-
// const screenInfo = await deviceClient.execOut("wm size", "utf8");
70-
// const match = screenInfo.match(/Physical size: (\d+)x(\d+)/);
71-
// if (!match) {
72-
// throw new Error("Could not parse screen dimensions");
73-
// }
74-
// const width = parseInt(match[1]);
75-
// const height = parseInt(match[2]);
76-
// const centerX = Math.floor(width / 2);
77-
// const centerY = Math.floor(height / 2 - height * Y_OFFSET); // Move up by 20%
78-
// // const centerY = Math.floor(height / 2);
79-
//
80-
// console.log(`Screen: ${width}x${height}, Fixed center: ${centerX},${centerY}`);
81-
//
82-
// for (let i = 0; i < count; i++) {
83-
// yield { x: centerX, y: centerY };
84-
// }
85-
// }
86-
87160
const testClickExec = async (deviceClient: DeviceClient) => {
88161
try {
89-
for await (const pos of getCenterTapsForDevice(deviceClient, NB_CLICK)) {
162+
for await (const pos of getCenterTapsForDevice(deviceClient)) {
90163
await deviceClient.execOut(`input tap ${pos.x} ${pos.y}`, "utf8");
91164
}
92165
} catch (e) {
@@ -122,7 +195,7 @@ const testClickScrcpy = async (deviceClient: DeviceClient, coordinateGenerator:
122195
while (!scrcpy) {
123196
try {
124197
scrcpy = deviceClient.scrcpy({});
125-
await Utils.delay(1);
198+
await Utils.delay(2);
126199
await scrcpy.start();
127200
await scrcpy.width;
128201
} catch (e) {
@@ -131,10 +204,6 @@ const testClickScrcpy = async (deviceClient: DeviceClient, coordinateGenerator:
131204
scrcpy = undefined;
132205
}
133206
}
134-
// const scrcpy
135-
// = deviceClient.scrcpy({});
136-
// await Utils.delay(1);
137-
// await scrcpy.start();
138207
await Utils.delay(1);
139208
const width = await scrcpy.width;
140209
const height = await scrcpy.height;
@@ -158,9 +227,18 @@ const testClickScrcpy = async (deviceClient: DeviceClient, coordinateGenerator:
158227
// Send ACTION_DOWN followed by ACTION_UP for each tap
159228
// MotionEvent.ACTION_DOWN
160229
await scrcpy.injectTouchEvent(MotionEventMap.ACTION_DOWN, 0n, position, screenSize, undefined, 0, MotionEventMap.BUTTON_PRIMARY);
161-
await Utils.delay(8);
162-
//await scrcpy.injectTouchEvent(MotionEventMap.ACTION_UP, 0n, position, screenSize, undefined, 0, 0);
163-
//await Utils.delay(1);
230+
// const c2 = await coordinateGenerator.next();
231+
// if (!c2.done) {
232+
// const tap2 = c2.value;
233+
// const position2 = {
234+
// x: tap2.x <= 1 ? Math.floor(tap2.x * width) : tap2.x,
235+
// y: tap2.y <= 1 ? Math.floor(tap2.y * height) : tap2.y
236+
// };
237+
// await scrcpy.injectTouchEvent(MotionEventMap.ACTION_DOWN, 0n, position, screenSize, undefined, 0, MotionEventMap.BUTTON_SECONDARY);
238+
// await scrcpy.injectTouchEvent(MotionEventMap.ACTION_UP, 0n, position, screenSize, undefined, 0, MotionEventMap.BUTTON_SECONDARY);
239+
// }
240+
await scrcpy.injectTouchEvent(MotionEventMap.ACTION_UP, 0n, position, screenSize, undefined, 0, 0);
241+
// await Utils.delay(1);
164242
}
165243
console.log('All scrcpy taps completed');
166244
} catch (e) {
@@ -171,6 +249,64 @@ const testClickScrcpy = async (deviceClient: DeviceClient, coordinateGenerator:
171249
scrcpy.stop();
172250
};
173251

252+
const setupKeyboardInterface = () => {
253+
console.log('\n=== MODE CONTROL ===');
254+
console.log('Use ARROW KEYS (←/→) or SPACE to change mode');
255+
console.log('Press ESC or Ctrl+C to continue');
256+
console.log(`Current mode: ${MODE}`);
257+
258+
readline.emitKeypressEvents(process.stdin);
259+
if (process.stdin.isTTY) {
260+
process.stdin.setRawMode(true);
261+
}
262+
263+
const keyListener = (_chunk: any, key: any) => {
264+
if (key) {
265+
if (key.name === 'escape' || (key.ctrl && key.name === 'c')) {
266+
process.stdin.setRawMode(false);
267+
process.stdin.removeListener('keypress', keyListener);
268+
console.log('\nContinuing with execution...\n');
269+
return;
270+
}
271+
272+
if (key.name === 'left' || key.name === 'right' || key.name === 'space') {
273+
if (key.name === 'left') {
274+
currentModeIndex = (currentModeIndex - 1 + MODES.length) % MODES.length;
275+
} else {
276+
currentModeIndex = (currentModeIndex + 1) % MODES.length;
277+
}
278+
MODE = MODES[currentModeIndex];
279+
let line = `\rCurrent mode`;
280+
for (const m of MODES) {
281+
if (m === MODE) {
282+
line += ` [${m}]`;
283+
} else {
284+
line += ` ${m} `;
285+
}
286+
}
287+
process.stdout.write(line + ' ');
288+
//
289+
//process.stdout.write(`\rCurrent mode: ${MODE} `);
290+
}
291+
}
292+
};
293+
294+
process.stdin.on('keypress', keyListener);
295+
296+
return new Promise<void>((resolve) => {
297+
const originalListener = process.stdin.listeners('keypress').find(l => l === keyListener);
298+
if (originalListener) {
299+
const wrappedListener = (_chunk: any, key: any) => {
300+
keyListener(_chunk, key);
301+
if (key && (key.name === 'escape' || (key.ctrl && key.name === 'c'))) {
302+
resolve();
303+
}
304+
};
305+
process.stdin.removeListener('keypress', keyListener);
306+
process.stdin.on('keypress', wrappedListener);
307+
}
308+
});
309+
};
174310

175311
const main = async () => {
176312
// process.env.DEBUG = '*';
@@ -181,7 +317,8 @@ const main = async () => {
181317
return;
182318
}
183319
const deviceClient = devices[0].getClient();
184-
320+
// await
321+
setupKeyboardInterface();
185322
// {
186323
// let t1 = Date.now();
187324
// await testClickExec(deviceClient);
@@ -192,7 +329,7 @@ const main = async () => {
192329
if (false) {
193330
const promises: Promise<unknown>[] = [];
194331
let t2 = Date.now();
195-
promises.push(testClickShell(deviceClient, getCenterTapsForDevice(deviceClient, NB_CLICK)));
332+
promises.push(testClickShell(deviceClient, getCenterTapsForDevice(deviceClient)));
196333
//promises.push(testClickShell(deviceClient, getFixedCenterForDevice(deviceClient, NB_CLICK));
197334
await Promise.all(promises);
198335
t2 = Date.now() - t2;
@@ -201,8 +338,21 @@ const main = async () => {
201338

202339
if (true) {
203340
let t3 = Date.now();
204-
// await testClickScrcpy(deviceClient, getCenterTapsForDevice(deviceClient, NB_CLICK, true));
205-
await testClickScrcpy(deviceClient, getGridPercent(NB_CLICK));
341+
const opts = {
342+
asPercent: true,
343+
xRadius: 0.30,
344+
yRadius: 0.14,
345+
fromX: 0.08,
346+
fromY: 0.2,
347+
toX: 0.92,
348+
toY: 0.75,// 0.75,
349+
stepX: 0.05,
350+
stepY: 0.025,
351+
} satisfies TapOptions;
352+
opts.xRadius *= 0.8;
353+
opts.yRadius *= 0.8;
354+
await testClickScrcpy(deviceClient, getCenterTapsForDevice(deviceClient, opts));
355+
// await testClickScrcpy(deviceClient, getGridPercent(NB_CLICK));
206356
t3 = Date.now() - t3;
207357
console.log(`scrcpy = ${t3 / NB_CLICK}`);
208358
}
@@ -219,7 +369,10 @@ process.on(
219369
"exit",
220370
(code) => console.log("Processus is closing, exit code:", code),
221371
);
222-
process.on("SIGINT", () => console.log("SIGINT reçu"));
372+
process.on("SIGINT", () => {
373+
console.log("SIGINT reçu");
374+
process.exit();
375+
});
223376
process.on("SIGTERM", () => console.log("SIGTERM reçu"));
224377

225378
main().catch((e) => console.error("ERROR", e)).finally(() => {

0 commit comments

Comments
 (0)