“本文转载自https://glama.ai/blog/2024-08-29-reverse-engineering-minified-code-using-openai”
在浏览互联网寻找灵感时,我发现了一个看起来很有趣的组件:
https://reactive.network/hackathon
我觉得带有运行 ASCII 艺术的区块看起来很酷,但我不太明白它是如何实现的,于是我开始查看源代码。
我找到了看起来可以完成这项工作的代码,但它被精简化了。
const { floor: ra, abs: KE, min: QE } = Math, O5 = ["reactive.network REACTIVE.NETWORK", "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,^`'. .:â–‘â–’â–“â–ˆ"], G7 = Date.now() % 3 ? O5[1] : O5[0], V5 = G7.length, JE = { fps: 60 };function eT(e, t, n, r) { const i = t.time * 8e-5, s = QE(t.cols, t.rows), o = t.metrics.aspect * 0.2, l = { x: ((4 * (e.x - t.cols / 6.25)) / s) * o, y: (5 * (e.y - t.rows / 4)) / s }, u = ra(KE(YE(l) - i) * V5 + (ra(e.x / 1) % 2) * 2) % V5; return G7[u];}const tT = () => { const e = j.useRef(null), [t, n] = j.useState({ height: null, width: null }); return ( j.useEffect(() => { function r() { n({ height: window.innerHeight, width: window.innerWidth }); } if (typeof window < "u") return n({ height: window.innerHeight, width: window.innerWidth }), window.addEventListener("resize", r), () => window.removeEventListener("resize", r); }, []), j.useEffect(() => { const r = e.current; if (!r) return; const i = 12, s = ra(t.width / i) * 1.6, o = ra(t.height / i), l = { aspect: s / o }, u = setInterval(() => { let c = ""; for (let d = 0; d < o; d++) { for (let f = 0; f < s; f++) c += eT({ x: f, y: d }, { cols: s, rows: o, metrics: l, time: Date.now() }); c += ``; } r.textContent = c; }, 1e3 / JE.fps); return () => clearInterval(u); }, [t]), a.jsx("p", { style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }, children: a.jsx("p", { ref: e, style: { width: "100%", height: "100%", whiteSpace: "pre", overflow: "hidden" } }) }) );};function nT(e) { return Math.cos(e.x * e.x - e.y * e.y);}const { floor: ia, abs: rT, min: iT } = Math, D5 = ["reactive.network REACTIVE.NETWORK", "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,^`'. .:â–‘â–’â–“â–ˆ"], X7 = Date.now() % 3 ? D5[1] : D5[0], F5 = X7.length, sT = { fps: 60 };function oT(e, t, n, r) { const i = t.time * 8e-5, s = iT(t.cols, t.rows), o = t.metrics.aspect * 0.2, l = { x: ((4 * (e.x - t.cols / 6.25)) / s) * o, y: (5 * (e.y - t.rows / 4)) / s }, u = ia(rT(nT(l) - i) * F5 + (ia(e.x / 1) % 2) * 2) % F5; return X7[u];}const aT = () => { const e = j.useRef(null), [t, n] = j.useState({ height: null, width: null }); return ( j.useEffect(() => { function r() { n({ height: window.innerHeight, width: window.innerWidth }); } if (typeof window < "u") return n({ height: window.innerHeight, width: window.innerWidth }), window.addEventListener("resize", r), () => window.removeEventListener("resize", r); }, []), j.useEffect(() => { const r = e.current; if (!r) return; const i = 12, s = ia(t.width / i) * 1.6, o = ia(t.height / i), l = { aspect: s / o }, u = setInterval(() => { let c = ""; for (let d = 0; d < o; d++) { for (let f = 0; f < s; f++) c += oT({ x: f, y: d }, { cols: s, rows: o, metrics: l, time: Date.now() }); c += ``; } r.textContent = c; }, 1e3 / sT.fps); return () => clearInterval(u); }, [t]), a.jsx("p", { style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }, children: a.jsx("p", { ref: e, style: { width: "100%", height: "100%", whiteSpace: "pre", overflow: "hidden" } }) }) );},通常情况下,我会通过阅读最小化的代码来理解其实现(或者查找 .map 文件来还原原始代码)。不过,我意识到我从未尝试过让 ChatGPT 帮我做这件事...... 于是,我复制了上述所有代码,并要求 ChatGPT “解释代码”。以下是回复:
提供的代码非常复杂,但我会将其分解为更易于理解的格式,解释其不同部分及其功能。 概述该代码使用 JavaScript 定义了几个函数和组件,特别是在 React 应用程序的上下文中。它处理使用预定义字符集中的字符生成一些动态文本内容,可能是 ASCII 艺术或某种视觉效果。此外,它还包括用于事件处理、性能计时和 HTML 内容转换的实用函数。 关键部件和功能字符集选择: const { floor: ra, abs: KE, min: QE } = Math;const O5 = ["reactive.network REACTIVE.NETWORK", "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,^`'. .:â–‘â–’â–“â–ˆ"];const G7 = Date.now() % 3 ? O5[1] : O5[0];const V5 = G7.length;这部分代码导入了一些常见的数学函数(floor、、abs和min),并定义了两组字符,存储在中O5。 根据当前时间(Date.now() % 3),它会选择其中一个集合(G7)以供稍后使用。 所选字符集的长度存储在中V5。 动态角色选择功能: function eT(e, t, n, r) { const i = t.time * 8e-5; const s = QE(t.cols, t.rows); const o = t.metrics.aspect * 0.2; const l = { x: ((4 * (e.x - t.cols / 6.25)) / s) * o, y: (5 * (e.y - t.rows / 4)) / s }; const u = ra(KE(YE(l) - i) * V5 + (ra(e.x / 1) % 2) * 2) % V5; return G7[u];}该eT函数根据输入位置(e.x,e.y)和当前时间(t.time)生成一个字符。 它使用一些纵横比计算来调整位置,并根据G7位置和时间的组合选择一个字符。 YE从代码中无法直接看出该函数的用途,但它似乎是此计算中使用的自定义函数。 tT用于显示动态内容的React 组件( ): const tT = () => { const e = j.useRef(null); const [t, n] = j.useState({ height: null, width: null }); j.useEffect(() => { function r() { n({ height: window.innerHeight, width: window.innerWidth }); } if (typeof window < "u") { n({ height: window.innerHeight, width: window.innerWidth }); window.addEventListener("resize", r); return () => window.removeEventListener("resize", r); } }, []); j.useEffect(() => { const r = e.current; if (!r) return; const i = 12; const s = ra(t.width / i) * 1.6; const o = ra(t.height / i); const l = { aspect: s / o }; const u = setInterval(() => { let c = ""; for (let d = 0; d < o; d++) { for (let f = 0; f < s; f++) c += eT({ x: f, y: d }, { cols: s, rows: o, metrics: l, time: Date.now() }); c += ``; } r.textContent = c; }, 1e3 / JE.fps); return () => clearInterval(u); }, [t]); return a.jsx("p", { style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }, children: a.jsx("p", { ref: e, style: { width: "100%", height: "100%", whiteSpace: "pre", overflow: "hidden" } }) });};这是一个 React 组件,它设置一个间隔,以使用动态生成的字符定期更新p元素的内容( )。e.current 它根据窗口大小计算列数(s)和行数( ),然后用函数生成的字符填充。opeT 该效果以每秒指定的帧数运行(JE.fps)。我继续询问“用 TypeScript 实现等效代码并使其易于阅读”,并得到了以下答复:
import React, { useEffect, useRef, useState } from 'react'; const selectedCharacterSet = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,^`'. .:â–‘â–’â–“â–ˆ";const characterSetLength = selectedCharacterSet.length; const calculateCharacter = ( x: number, y: number, cols: number, rows: number, aspect: number, time: number,): string => { const timeFactor = time * 0.000_08; const size = Math.min(cols, rows); const aspectRatio = aspect * 0.2; const position = { x: ((4 * (x - cols / 6.25)) / size) * aspectRatio, y: (5 * (y - rows / 4)) / size, }; const index = Math.floor( Math.abs( Math.cos(position.x * position.x - position.y * position.y) - timeFactor, ) * characterSetLength + (Math.floor(x) % 2) * 2, ) % characterSetLength; return selectedCharacterSet[index];}; type Size = { height: null | number; width: null | number;}; const AsciiArtGenerator: React.FC = () => { const textRef = useRef令我惊讶的是,响应不仅足够好,而且可读性也很强。(null); const [size, setSize] = useState ({ height: null, width: null }); useEffect(() => { const handleResize = () => { setSize({ height: window.innerHeight, width: window.innerWidth }); }; // Initial size setting handleResize(); window. addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; }, []); useEffect(() => { const element = textRef.current; if (!element || !size.width || !size.height) return undefined; const cols = Math.floor(size.width / 12) * 1.6; const rows = Math.floor(size.height / 12); const aspectRatio = cols / rows; const intervalId = setInterval(() => { let content = ''; for (let y = 0; y < rows; y++) { for (let x = 0; x < cols; x++) { content += calculateCharacter( x, y, cols, rows, aspectRatio, Date.now(), ); } content += 'n'; } element.textContent = content; }, 1_000 / 60); // 60 fps return () => { clearInterval(intervalId); }; }, [size]); return ( );}; export default () => { return ;};
上述组件的实际运行情况如下:
比较输出结果,LLM 响应似乎忽略了一些实现细节,但它仍然是一个值得学习的好实现。这绝对是一个我以前从未考虑过的巧妙用例!
注意:如果想第一时间收到 KiCad 内容推送,请点击下方的名片,按关注,再设为星标。
常用合集汇总:
和 Dr Peter 一起学 KiCad
KiCad 8 探秘合集
KiCad 使用经验分享
KiCad 设计项目(Made with KiCad)
常见问题与解决方法
KiCad 开发笔记
审核编辑 黄宇