diff --git a/package.json b/package.json index c13cfa4..6fb3679 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "test:pyunit": "npm run extractcode && ./unittest_python.sh", "test": "npm run jest && npm run test:pyunit && npm run test:pystress", "build:ssr": "./ssr-all.sh", - "update:html": "mkdir -p build && (for i in {chapter1,chapter2,chapter3,chapter4}; do mustache src/mustache/$i.json src/page.html.template > src/autogenerated/$i.html; done)", + "update:html": "mkdir -p build && (for i in {chapter1,chapter2,chapter3,chapter4,new_demos}; do mustache src/mustache/$i.json src/page.html.template > src/autogenerated/$i.html; done)", "start": "webpack-dev-server --config webpack.dev.js --host 0.0.0.0", "serve": "http-server -p 9090 dist/", "build": "npm run build:ssr && webpack --config webpack.prod.js", diff --git a/src/autogenerated/new_demos.html b/src/autogenerated/new_demos.html new file mode 100644 index 0000000..1241b14 --- /dev/null +++ b/src/autogenerated/new_demos.html @@ -0,0 +1,18 @@ + + +
+${bp.newListIdx} == ${bp.number} % ${
- bp.newList.size
- }`;
+ return `Compute the slot index: ${bp.newListIdx} == ${bp.number} % ${bp.newList.size}`;
case 'check-collision':
return chapter1_2_FormatCheckCollision(bp.newList, bp.newListIdx, bp.fmtCollisionCount);
case 'next-idx':
- return `Keep probing, the next slot will be ${bp.newListIdx} == (${
- prevBp.newListIdx
- } + 1) % ${bp.newList.size}`;
+ return `Keep probing, the next slot will be ${bp.newListIdx} == (${prevBp.newListIdx} + 1) % ${bp.newList.size}`;
case 'assign-elem': {
const prevNumber = prevBp.newList.get(bp.newListIdx);
if (prevNumber != null) {
- return `Collision of ${bp.number} with ${prevNumber} in slot ${
- bp.newListIdx
- } - the number is overwritten`;
+ return `Collision of ${bp.number} with ${prevNumber} in slot ${bp.newListIdx} - the number is overwritten`;
} else {
return `Put ${bp.number} in slot ${bp.newListIdx}`;
}
@@ -351,9 +351,7 @@ class SimplifiedSearch extends BreakpointFunction {
let formatSimplifiedSearchDescription = function(bp) {
switch (bp.point) {
case 'compute-idx':
- return `Compute the slot index: ${bp.newListIdx} == ${bp.number} % ${
- bp.newList.size
- }`;
+ return `Compute the slot index: ${bp.newListIdx} == ${bp.number} % ${bp.newList.size}`;
case 'check-not-found':
return commonFormatCheckNotFound(bp.newList, bp.newListIdx, bp.fmtCollisionCount);
case 'check-found':
@@ -618,8 +616,8 @@ export class Chapter1_SimplifiedHash extends ChapterComponent {
Accessing a single element by index is very fast. Accessing only a few elements would be fast - too. We don't want to be doing a linear scan over the whole list every time we look up a number, so - we need to organize our data in a clever way. + too. We don't want to be doing a linear scan over the whole list every time we look up a number, + so we need to organize our data in a clever way.
Here's how.
diff --git a/src/code_blocks.js b/src/code_blocks.js index 5e7e539..af3e851 100644 --- a/src/code_blocks.js +++ b/src/code_blocks.js @@ -1310,6 +1310,55 @@ export class Tetris extends React.PureComponent { } } +export function formatBp(bp, prevBp, formatBpDesc) { + let desc = null; + if (typeof formatBpDesc === 'function') { + desc = formatBpDesc(bp, prevBp); + } else { + for (const formatFunc of formatBpDesc) { + desc = formatFunc(bp, prevBp); + if (desc != null) break; + } + } + return desc; +} + +export function getVisibleBreakpoints(code, breakpoints, time) { + let visibleBreakpoints = {}; + let pointToLevel = {}; + for (let [line, bpPoint, level] of code) { + if (line === '' || bpPoint === '') { + continue; + } + if (level === undefined) { + pointToLevel = null; + break; + } + pointToLevel[bpPoint] = level; + } + + let prevBp = null; + for (let [t, bp] of breakpoints.entries()) { + if (t > time) { + break; + } + + if (bp.point in visibleBreakpoints) { + let level = pointToLevel[bp.point]; + for (let visibleBpPoint in visibleBreakpoints) { + if (pointToLevel[visibleBpPoint] >= level) { + delete visibleBreakpoints[visibleBpPoint]; + } + } + } + + visibleBreakpoints[bp.point] = {bp, prevBp}; + prevBp = bp; + } + + return visibleBreakpoints; +} + class CodeBlockWithActiveLineAndAnnotations extends React.Component { constructor() { super(); @@ -1330,7 +1379,6 @@ class CodeBlockWithActiveLineAndAnnotations extends React.Component { }); getCodeWithExplanationHtmlLines(visibleBreakpoints, activeBp) { - const t1 = performance.now(); const code = this.props.code; const hlLines = this._highlightLines(code); let lines = []; @@ -1345,15 +1393,7 @@ class CodeBlockWithActiveLineAndAnnotations extends React.Component { if (bpPoint in visibleBreakpoints) { const {bp, prevBp} = visibleBreakpoints[bpPoint]; - let desc = null; - if (typeof this.props.formatBpDesc === 'function') { - desc = this.props.formatBpDesc(bp, prevBp); - } else { - for (const formatBpDesc of this.props.formatBpDesc) { - desc = formatBpDesc(bp, prevBp); - if (desc != null) break; - } - } + const desc = formatBp(bp, prevBp, this.props.formatBpDesc); if (desc == null) { throw new Error('Unknown bp type: ' + bpPoint); @@ -1399,47 +1439,10 @@ class CodeBlockWithActiveLineAndAnnotations extends React.Component { return lines; } - getVisibleBreakpoints(activeBp) { - const t1 = performance.now(); - let visibleBreakpoints = {}; - let pointToLevel = {}; - for (let [line, bpPoint, level] of this.props.code) { - if (line === '' || bpPoint === '') { - continue; - } - if (level === undefined) { - pointToLevel = null; - break; - } - pointToLevel[bpPoint] = level; - } - - let prevBp = null; - for (let [time, bp] of this.props.breakpoints.entries()) { - if (time > this.props.time) { - break; - } - - if (bp.point in visibleBreakpoints) { - let level = pointToLevel[bp.point]; - for (let visibleBpPoint in visibleBreakpoints) { - if (pointToLevel[visibleBpPoint] >= level) { - delete visibleBreakpoints[visibleBpPoint]; - } - } - } - - visibleBreakpoints[bp.point] = {bp, prevBp}; - prevBp = bp; - } - - return visibleBreakpoints; - } - render() { let activeBp = this.props.breakpoints[this.props.time]; - const visibleBreakpoints = this.getVisibleBreakpoints(activeBp); + const visibleBreakpoints = getVisibleBreakpoints(this.props.code, this.props.breakpoints, this.props.time); const lines = this.getCodeWithExplanationHtmlLines(visibleBreakpoints, activeBp); return ( @@ -1792,6 +1795,18 @@ export class VisualizedCode extends React.Component { } } + getLastDesc() { + const currentBp = this.props.breakpoints[this.state.time]; + // Pretty hacky as an experiment + const visibleBreakpoints = getVisibleBreakpoints(this.props.code, this.props.breakpoints, this.state.time); + if (visibleBreakpoints.length === 0) { + return null; + } + console.log('VB', visibleBreakpoints, currentBp.point); + const {bp, prevBp} = visibleBreakpoints[currentBp.point]; + return formatBp(bp, prevBp, this.props.formatBpDesc); + } + render() { const windowWidth = this.props.windowWidth; const windowHeight = this.props.windowHeight; @@ -1801,6 +1816,9 @@ export class VisualizedCode extends React.Component { const smallerFont = tallScreen || serverSide; let bp = this.props.breakpoints[this.state.time]; + + const lastDesc = this.getLastDesc(); + const StateVisualization = this.props.stateVisualization; let codeHeight; @@ -1835,6 +1853,14 @@ export class VisualizedCode extends React.Component { maxTime={this.props.breakpoints.length - 1} autoplayByDefault={this.props.autoplayByDefault} /> +
Hello, world!
+Hello, world!
+