Repository navigation
Expand file tree
/
Copy pathfunc-test.mjs
More file actions
108 lines (91 loc) · 4.04 KB
/
Copy pathfunc-test.mjs
File metadata and controls
108 lines (91 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// func-test.mjs — 用 CDP 真实触控在小游戏里落子,验证「触控→落子」功能链路
import http from "http";
import WebSocket from "ws";
import fs from "fs";
import { PNG } from "pngjs";
const PORT = 9222;
const BEFORE = "/Users/cuijiawei/Developer/wechat-dev-mcp/func-before.png";
const AFTER = "/Users/cuijiawei/Developer/wechat-dev-mcp/func-after.png";
// 逻辑坐标(来自 game.js 几何:SCREEN 390x844, BOARD_X=30, BOARD_Y=257, CELL=23.57)
const BOARD_X = 30, BOARD_Y = 257, CELL = 23.571;
const gridToPoint = (r, c) => ({ x: Math.round(BOARD_X + c * CELL), y: Math.round(BOARD_Y + r * CELL) });
function httpGet(path) {
return new Promise((resolve, reject) => {
const req = http.get(`http://127.0.0.1:${PORT}${path}`, res => {
let d = ""; res.on("data", c => d += c);
res.on("end", () => { try { resolve(JSON.parse(d)); } catch(e){ reject(e); } });
});
req.on("error", reject);
req.setTimeout(3000, () => { req.destroy(); reject(new Error("timeout")); });
});
}
function cdpSend(ws, id, method, params = {}) {
return new Promise((resolve) => {
const h = msg => { const m = JSON.parse(msg.toString()); if (m.id === id) { ws.off("message", h); resolve(m); } };
ws.on("message", h);
ws.send(JSON.stringify({ id, method, params }));
});
}
async function findGameWs() {
const list = await httpGet("/json/list");
const g = list.find(t => (t.url || "").includes("gamePage.html"));
return g ? g.webSocketDebuggerUrl : null;
}
async function screenshot(ws, out) {
await cdpSend(ws, 1, "Page.enable");
const r = await cdpSend(ws, 2, "Page.captureScreenshot", { format: "png", fromSurface: true });
if (r.result && r.result.data) { fs.writeFileSync(out, Buffer.from(r.result.data, "base64")); return r.result.data.length; }
return 0;
}
// 数「很暗」像素(黑棋 #1a1a1a),排除顶部状态栏区域(y<120 截图像素)
function countDarkStones(path) {
const png = PNG.sync.read(fs.readFileSync(path));
const { width, height, data } = png;
let count = 0;
for (let y = 120; y < height; y++) {
for (let x = 0; x < width; x++) {
const i = (width * y + x) << 2;
const r = data[i], g = data[i+1], b = data[i+2];
if (r < 45 && g < 45 && b < 45) count++;
}
}
return count;
}
async function dispatchTap(ws, x, y) {
// touchStart
await cdpSend(ws, 10, "Input.dispatchTouchEvent", {
type: "touchStart",
touchPoints: [{ x, y, id: 0, radiusX: 1, radiusY: 1, force: 1 }],
});
await new Promise(r => setTimeout(r, 60));
// touchEnd
await cdpSend(ws, 11, "Input.dispatchTouchEvent", { type: "touchEnd", touchPoints: [] });
await new Promise(r => setTimeout(r, 300));
}
async function main() {
const wsUrl = await findGameWs();
if (!wsUrl) { console.error("NO_GAME_WEBVIEW"); process.exit(1); }
console.log("[func-test] game webview:", wsUrl);
const ws = new WebSocket(wsUrl);
await new Promise(r => ws.once("open", r));
// 落子前截图
const bLen = await screenshot(ws, BEFORE);
console.log("[func-test] before screenshot:", bLen, "bytes, darkPx=", countDarkStones(BEFORE));
// 落两子:grid(7,7) 黑 + grid(3,3) 白(交替)
const p1 = gridToPoint(7, 7);
console.log("[func-test] tap black at grid(7,7) ->", p1);
await dispatchTap(ws, p1.x, p1.y);
const p2 = gridToPoint(3, 3);
console.log("[func-test] tap white at grid(3,3) ->", p2);
await dispatchTap(ws, p2.x, p2.y);
// 落子后截图
const aLen = await screenshot(ws, AFTER);
console.log("[func-test] after screenshot:", aLen, "bytes, darkPx=", countDarkStones(AFTER));
ws.close();
const beforeDark = countDarkStones(BEFORE);
const afterDark = countDarkStones(AFTER);
console.log("[func-test] dark stone pixels:", beforeDark, "->", afterDark, "(delta", afterDark - beforeDark, ")");
if (afterDark - beforeDark > 300) console.log("[func-test] ✅ FUNCTIONAL: 落子生效,黑/白棋已渲染");
else console.log("[func-test] ⚠️ 未检测到明显落子(delta 偏小)");
}
main().catch(e => { console.error("FATAL:", e.message); process.exit(1); });