Compare commits

..

No commits in common. "1bbb36c85a620bce75b7e0a4dbec4d782fe17516" and "036fb1733318d93046b57a73acb80322176f923f" have entirely different histories.

7 changed files with 62 additions and 246 deletions

View File

@ -3,10 +3,7 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"babel-loader": "8.0.6",
"moment": "^2.24.0",
"react": "^16.10.2", "react": "^16.10.2",
"react-bulma-components": "3.1.3",
"react-dom": "^16.10.2", "react-dom": "^16.10.2",
"react-scripts": "3.2.0" "react-scripts": "3.2.0"
}, },

View File

@ -24,7 +24,7 @@
work correctly both with client-side routing and a non-root public URL. work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title>Tracer Debug App</title> <title>React App</title>
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>

View File

@ -1,3 +1,9 @@
html, body, #root {
background-color: #000;
color: #fff;
height: 100%;
}
.App { .App {
text-align: center; text-align: center;
} }
@ -6,26 +12,4 @@
display: inline-block; display: inline-block;
color: #fff; color: #fff;
text-shadow: 0 0 4px #000, 0 0 8px #000 ; text-shadow: 0 0 4px #000, 0 0 8px #000 ;
cursor: crosshair;
}
.frame .name {
text-align: center;
}
.title {
color: #fff;
}
.subtitle {
color: #aaa;
}
.value {
text-align: center;
border: 1px solid #888;
}
.menu {
margin: .5em;
} }

View File

@ -1,92 +1,18 @@
import React from 'react'; import React from 'react';
import moment from 'moment';
import './App.css'; import './App.css';
import {
Columns,
Heading,
} from 'react-bulma-components';
const ROOT = process.env.PUBLIC_URL + '/tracer/'; const ROOT = process.env.PUBLIC_URL + '/tracer/';
const DATA_URL = ROOT + 'data.json'; const DATA_URL = ROOT + 'data.json';
const MAX_ZOOM_FACTOR = 32;
const Sidebar = (props) => {
let {
binary, binaryMax, imageMetadata, zoomFactor, x, y,
onZoom,
} = props;
let samples = imageMetadata.map((md) => {
let pix = binary[md.name];
if (pix === undefined) { return <p key={md.name}>Loading...</p>; }
let max = binaryMax[md.name];
let [w, h] = md.size;
let xOff = Math.min(w, Math.max(0, Math.round(x*w)));
let yOff = Math.min(h, Math.max(0, Math.round(y*h)));
let v = pix[xOff+yOff*w];
if (v === undefined) {
console.log(`${x} ${y} ${w} ${h} ${xOff} ${yOff} ${v} ${pix.length}`);
return <p key={md.name}>Loading...</p>;
}
let color = "#fff";
let rgb = "";
let value = "";
if (md.format === "RGB01") {
let r = Math.round(v[0]*255);
let g = Math.round(v[1]*255);
let b = Math.round(v[2]*255);
rgb = `rgb(${r}, ${g}, ${b})`;
color = `rgb(${255^r}, ${255^g}, ${255^b})`;
value = rgb;
} else {
let c = 255*v/max;
rgb = `rgb(${c}, ${c}, ${c})`;
color = `rgb(${255^c}, ${255^c}, ${255^c})`;
value = v;
}
return <div className="sample" key={md.name}>
<p>{md.name}</p>
<p className="value" style={{
color,
backgroundColor: rgb,
}}>{value}</p>
</div>
});
return <aside className="menu">
<p className="menu-label">
Controls
</p>
<ul className="menu-list">
<li>
<p>Zoom:</p>
<input
id="zoom"
type="range"
min="1" max={MAX_ZOOM_FACTOR}
value={zoomFactor}
onChange={onZoom}
step="0.1"/>
<p className="value">{Math.round(zoomFactor*100)/100}x</p>
</li>
</ul>
<p className="menu-label">
Samples
</p>
{samples}
</aside>;
}
class App extends React.Component { class App extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
data: null, data: null,
binary: {},
binaryMax: {},
isFetching: false, isFetching: false,
isFrozen: false, isFrozen: false,
isZoomed: false, isZoomed: false,
zoomFactor: 4, zoomFactor: 16,
x: 0, x: 0,
y: 0, y: 0,
}; };
@ -100,48 +26,14 @@ class App extends React.Component {
} }
fetchTracerData() { fetchTracerData() {
this.setState({...this.state, isFetching: true}) this.setState({...this.state, isFetching: true})
const max = (acc, cur) => Math.max(acc, cur);
// console.log(array1.reduce(max));
fetch(DATA_URL) fetch(DATA_URL)
.then(response => response.json()) .then(response => response.json())
.then(result => { .then(result => this.setState({data: result, isFetching: false}))
let {data} = this.state;
if ((data === null) ||
(data.timestamp !== result.timestamp)) {
this.setState({data: result, isFetching: false});
result.imageMetadata.forEach((md) => {
let binaryUrl = ROOT + md.binary;
fetch(binaryUrl)
.then(response => response.json())
.then(result => {
let curBinary = this.state.binary;
let curBinaryMax = this.state.binaryMax;
let binaryMax = result.reduce(max);
console.log(`${md.name} ${binaryMax}`);
this.setState({
binary: {
[md.name]: result,
...curBinary
},
binaryMax: {
[md.name]: binaryMax,
...curBinaryMax
}
});
})
.catch(e => console.log(e));
});
} else {
this.setState({isFetching: false});
}
})
.catch(e => console.log(e)); .catch(e => console.log(e));
} }
render() { render() {
let images = []; let imgs = [];
let { let {
binary,
binaryMax,
data, data,
isFrozen, isFrozen,
isZoomed, isZoomed,
@ -149,10 +41,10 @@ class App extends React.Component {
y, y,
zoomFactor, zoomFactor,
} = this.state; } = this.state;
let mainContent = <h1>Loading</h1>;
let sidebarContent = <h1>Loading</h1>;
if (data !== null) { if (data !== null) {
let {timestamp, imageMetadata} = data; let {ratio, timestamp, images, size} = data;
let width = 512;
let height = (ratio * width).toFixed();
const mouseClick = (e) => { const mouseClick = (e) => {
console.log('isFrozen', isFrozen, 'this.state.isFrozen', this.state.isFrozen); console.log('isFrozen', isFrozen, 'this.state.isFrozen', this.state.isFrozen);
this.setState({isFrozen: !this.state.isFrozen}); this.setState({isFrozen: !this.state.isFrozen});
@ -163,89 +55,63 @@ class App extends React.Component {
} }
this.setState({isZoomed: true}); this.setState({isZoomed: true});
}; };
const mouseScroll = (e) => {
let delta = parseFloat(-e.deltaY/100.0);
let zoomFactor = delta + this.state.zoomFactor;
if (zoomFactor < 1) { zoomFactor = 1; }
if (zoomFactor > MAX_ZOOM_FACTOR) {
zoomFactor = MAX_ZOOM_FACTOR;
}
this.setState({
zoomFactor: zoomFactor,
isZoomed: true
});
};
const mouseLeave = (e) => { const mouseLeave = (e) => {
if (isFrozen) { if (isFrozen) {
return; return;
} }
this.setState({isZoomed: false}); this.setState({isZoomed: false});
}; };
const onZoom = (e) => this.setState({ const mouseMove = (e) => {
zoomFactor: Number(e.target.value) if (isFrozen) {
}); return;
}
images = imageMetadata.map((metadata) => { let rect = e.currentTarget.getBoundingClientRect();
let {name, ratio, image} = metadata; let x = e.clientX - rect.left;
let width = 384; let y = e.clientY - rect.top;
let height = (ratio * width).toFixed(); this.setState({x: x/width, y: y/height});
let url = ROOT + image + '?t=' + timestamp; };
const mouseMove = (e) => { let style = {
if (isFrozen) { width: width + 'px',
return; height: height + 'px',
} imageRendering: isZoomed ? 'pixelated' : 'auto',
let rect = e.currentTarget.getBoundingClientRect(); backgroundSize: isZoomed ? zoomFactor * size[0] + 'px ' + zoomFactor * size[1] + 'px' : 'contain',
let x = e.clientX - rect.left; backgroundPosition: isZoomed ? 100*x + '% ' + 100*y + '%' : 'center center',
let y = e.clientY - rect.top; };
this.setState({x: x/width, y: y/height}); imgs = images.map((name) => {
}; let url = ROOT + name + '?t=' + timestamp;
let style = {
width: width + 'px',
height: height + 'px',
imageRendering: isZoomed ? 'pixelated' : 'auto',
backgroundSize: isZoomed ? zoomFactor * width + 'px ' + zoomFactor * height + 'px' : 'contain',
backgroundPosition: isZoomed ? 100*x + '% ' + 100*y + '%' : 'center center',
};
return ( return (
<div key={name} <div key={name}
onClick={mouseClick} onClick={mouseClick}
onMouseMove={mouseMove} onMouseMove={mouseMove}
onMouseEnter={mouseEnter} onMouseEnter={mouseEnter}
onMouseLeave={mouseLeave} onMouseLeave={mouseLeave}
onWheel={mouseScroll}
className="frame" className="frame"
style={{backgroundImage: 'url("' + url + '")', ...style}}> style={{backgroundImage: 'url("' + url + '")', ...style}}>
<p className="name">{name}</p> <p>{name}</p>
</div>) </div>)
}); });
let time = moment.unix(timestamp);
mainContent = <div>
<Heading>
Run @ {time.format("llll")}
</Heading>
<Heading subtitle>
{time.fromNow()}
</Heading>
{images}
</div>;
sidebarContent = <Sidebar
imageMetadata={imageMetadata}
zoomFactor={zoomFactor}
x={x} y={y}
binary={binary}
binaryMax={binaryMax}
onZoom={onZoom} />;
} }
return ( return (
<Columns> <div>
<Columns.Column size="one-fifth"> <div className="controls">
{sidebarContent} <label>
</Columns.Column> Zoom:
<Columns.Column> <input
{mainContent} id="zoom"
</Columns.Column> type="range"
</Columns> min="1" max="64"
value={zoomFactor}
onChange={(e) => this.setState({
zoomFactor: e.target.value
})}
step="1"/>
</label>
{zoomFactor}
</div>
<div className="App">
{imgs}
</div>
</div>
); );
} }
} }

View File

@ -11,14 +11,3 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace; monospace;
} }
html {
background-color: #000;
}
html, body, #root {
background-color: #000;
color: #fff;
height: 100%;
}

View File

@ -1,6 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import 'react-bulma-components/dist/react-bulma-components.min.css';
import './index.css'; import './index.css';
import App from './App'; import App from './App';
import * as serviceWorker from './serviceWorker'; import * as serviceWorker from './serviceWorker';

View File

@ -1974,10 +1974,6 @@ builtin-status-codes@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
bulma@0.7.5:
version "0.7.5"
resolved "https://registry.yarnpkg.com/bulma/-/bulma-0.7.5.tgz#35066c37f82c088b68f94450be758fc00a967208"
bytes@3.0.0: bytes@3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
@ -2174,10 +2170,6 @@ class-utils@^0.3.5:
isobject "^3.0.0" isobject "^3.0.0"
static-extend "^0.1.1" static-extend "^0.1.1"
classnames@2.2.6:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
clean-css@4.2.x: clean-css@4.2.x:
version "4.2.1" version "4.2.1"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17"
@ -5522,10 +5514,6 @@ mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
dependencies: dependencies:
minimist "0.0.8" minimist "0.0.8"
moment@^2.24.0:
version "2.24.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
move-concurrently@^1.0.1: move-concurrently@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
@ -7024,13 +7012,6 @@ react-app-polyfill@^1.0.4:
regenerator-runtime "0.13.3" regenerator-runtime "0.13.3"
whatwg-fetch "3.0.0" whatwg-fetch "3.0.0"
react-bulma-components@3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/react-bulma-components/-/react-bulma-components-3.1.3.tgz#8dee9697d66f5ead92244fac6ef6b2fe3d1c8b71"
dependencies:
bulma "0.7.5"
classnames "2.2.6"
react-dev-utils@^9.1.0: react-dev-utils@^9.1.0:
version "9.1.0" version "9.1.0"
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-9.1.0.tgz#3ad2bb8848a32319d760d0a84c56c14bdaae5e81" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-9.1.0.tgz#3ad2bb8848a32319d760d0a84c56c14bdaae5e81"
@ -7061,14 +7042,14 @@ react-dev-utils@^9.1.0:
strip-ansi "5.2.0" strip-ansi "5.2.0"
text-table "0.2.0" text-table "0.2.0"
react-dom@^16.10.2: react-dom@16.10.2:
version "16.11.0" version "16.10.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.11.0.tgz#7e7c4a5a85a569d565c2462f5d345da2dd849af5" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.10.2.tgz#4840bce5409176bc3a1f2bd8cb10b92db452fda6"
dependencies: dependencies:
loose-envify "^1.1.0" loose-envify "^1.1.0"
object-assign "^4.1.1" object-assign "^4.1.1"
prop-types "^15.6.2" prop-types "^15.6.2"
scheduler "^0.17.0" scheduler "^0.16.2"
react-error-overlay@^6.0.3: react-error-overlay@^6.0.3:
version "6.0.3" version "6.0.3"
@ -7138,9 +7119,9 @@ react-scripts@3.2.0:
optionalDependencies: optionalDependencies:
fsevents "2.0.7" fsevents "2.0.7"
react@^16.10.2: react@16.10.2:
version "16.11.0" version "16.10.2"
resolved "https://registry.yarnpkg.com/react/-/react-16.11.0.tgz#d294545fe62299ccee83363599bf904e4a07fdbb" resolved "https://registry.yarnpkg.com/react/-/react-16.10.2.tgz#a5ede5cdd5c536f745173c8da47bda64797a4cf0"
dependencies: dependencies:
loose-envify "^1.1.0" loose-envify "^1.1.0"
object-assign "^4.1.1" object-assign "^4.1.1"
@ -7535,9 +7516,9 @@ saxes@^3.1.9:
dependencies: dependencies:
xmlchars "^2.1.1" xmlchars "^2.1.1"
scheduler@^0.17.0: scheduler@^0.16.2:
version "0.17.0" version "0.16.2"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.17.0.tgz#7c9c673e4ec781fac853927916d1c426b6f3ddfe" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.16.2.tgz#f74cd9d33eff6fc554edfb79864868e4819132c1"
dependencies: dependencies:
loose-envify "^1.1.0" loose-envify "^1.1.0"
object-assign "^4.1.1" object-assign "^4.1.1"