diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..4da3dc3b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "tslint.enable": true, + "tslint.rulesDirectory": "node_modules/tslint-microsoft-contrib" +} \ No newline at end of file diff --git a/libs/i2c-fram/fram.ts b/libs/i2c-fram/fram.ts index 21366aee..2bf372ab 100644 --- a/libs/i2c-fram/fram.ts +++ b/libs/i2c-fram/fram.ts @@ -36,7 +36,7 @@ namespace i2c_fram { pins.i2cWriteBuffer(devaddr, buf) } - + export function readBuffer(addr: number, length: number) { if (addr < 0 || length < 0 || (addr + length) > memend) die(); @@ -45,8 +45,8 @@ namespace i2c_fram { buf[i] = readByte(addr + i) return buf } - - export function writeBuffer(addr:number, buf: Buffer) { + + export function writeBuffer(addr: number, buf: Buffer) { if (addr < 0 || (addr + buf.length) > memend) die(); for (let i = 0; i < buf.length; ++i) diff --git a/sim/libmbit.ts b/sim/libmbit.ts index 2d3979be..045c8935 100644 --- a/sim/libmbit.ts +++ b/sim/libmbit.ts @@ -4,12 +4,12 @@ namespace pxsim { pxsim.initCurrentRuntime = () => { - U.assert(!runtime.board) - runtime.board = new Board() + U.assert(!runtime.board); + runtime.board = new Board(); } export function board() { - return runtime.board as Board + return runtime.board as Board; } export interface AnimationOptions { @@ -77,7 +77,7 @@ namespace pxsim { }) } } - + /** * Error codes used in the micro:bit runtime. */ @@ -115,7 +115,7 @@ namespace pxsim { img.set(3, 1, 255); img.set(4, 1, 255); runtime.updateDisplay(); - + throw new Error("PANIC " + code) } @@ -125,9 +125,9 @@ namespace pxsim { export namespace AudioContextManager { - var _context: any; // AudioContext - var _vco: any; //OscillatorNode; - var _vca: any; // GainNode; + let _context: any; // AudioContext + let _vco: any; // OscillatorNode; + let _vca: any; // GainNode; function context(): any { if (!_context) _context = freshContext(); @@ -152,7 +152,7 @@ namespace pxsim { export function tone(frequency: number, gain: number) { if (frequency <= 0) return; - var ctx = context(); + let ctx = context(); if (!ctx) return; gain = Math.max(0, Math.min(1, gain)); @@ -198,10 +198,10 @@ namespace pxsim.basic { pause(interval * 5); } else { if (s.length == 1) showLeds(createImageFromString(s), interval * 5) - else ImageMethods.scrollImage(createImageFromString(s + ' '), interval, 1); + else ImageMethods.scrollImage(createImageFromString(s + " "), interval, 1); } } - + export function showLeds(leds: Image, delay: number): void { showAnimation(leds, delay); } @@ -226,19 +226,19 @@ namespace pxsim.control { export function reset() { U.userError("reset not implemented in simulator yet") } - - export function deviceName() : string { + + export function deviceName(): string { let b = board(); - return b && b.id - ? b.id.slice(0, 4) - : 'abcd'; + return b && b.id + ? b.id.slice(0, 4) + : "abcd"; } - + export function deviceSerialNumber(): number { let b = board(); - return parseInt(b && b.id - ? b.id.slice(1) - : '42'); + return parseInt(b && b.id + ? b.id.slice(1) + : "42"); } export function onEvent(id: number, evid: number, handler: RefAction) { @@ -306,7 +306,7 @@ namespace pxsim.input { export function compassHeading(): number { - var b = board(); + let b = board(); if (!b.usesHeading) { b.usesHeading = true; runtime.queueDisplayUpdate(); @@ -315,7 +315,7 @@ namespace pxsim.input { } export function temperature(): number { - var b = board(); + let b = board(); if (!b.usesTemperature) { b.usesTemperature = true; runtime.queueDisplayUpdate(); @@ -565,29 +565,29 @@ namespace pxsim.images { namespace pxsim.ImageMethods { export function showImage(leds: Image, offset: number) { - if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); - + if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); + leds.copyTo(offset, 5, board().image, 0) runtime.queueDisplayUpdate() } export function plotImage(leds: Image, offset: number): void { if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); - + leds.copyTo(offset, 5, board().image, 0) runtime.queueDisplayUpdate() } - export function height(leds: Image) : number { - if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); + export function height(leds: Image): number { + if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); return Image.height; } - export function width(leds: Image) : number { - if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); + export function width(leds: Image): number { + if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); return leds.width; } - + export function plotFrame(leds: Image, frame: number) { ImageMethods.plotImage(leds, frame * Image.height); } @@ -595,38 +595,38 @@ namespace pxsim.ImageMethods { export function showFrame(leds: Image, frame: number) { ImageMethods.showImage(leds, frame * Image.height); } - - export function pixel(leds: Image, x: number, y: number) : number { - if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); - return leds.get(x,y); + + export function pixel(leds: Image, x: number, y: number): number { + if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); + return leds.get(x, y); } - - export function setPixel(leds: Image, x: number, y: number, v:number) { - if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); - leds.set(x,y,v); + + export function setPixel(leds: Image, x: number, y: number, v: number) { + if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); + leds.set(x, y, v); } export function clear(leds: Image) { - if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); - + if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); + leds.clear(); } export function setPixelBrightness(i: Image, x: number, y: number, b: number) { - if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); + if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); i.set(x, y, b); } export function pixelBrightness(i: Image, x: number, y: number): number { - if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); + if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); return i.get(x, y); } export function scrollImage(leds: Image, interval: number, stride: number): void { - if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); - + if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE); + let cb = getResume() let off = stride > 0 ? 0 : leds.width - 1; let display = board().image; diff --git a/sim/simsvg.ts b/sim/simsvg.ts index 9b01b16a..5497bee6 100644 --- a/sim/simsvg.ts +++ b/sim/simsvg.ts @@ -15,7 +15,7 @@ namespace pxsim.micro_bit { virtualButtonOuter?: string; virtualButtonUp?: string; virtualButtonDown?: string; - lightLevelOn?:string; + lightLevelOn?: string; lightLevelOff?: string; } @@ -25,7 +25,7 @@ namespace pxsim.micro_bit { display: "#000", pin: "#D4AF37", pinTouched: "#FFA500", - pinActive:"#FF5500", + pinActive: "#FF5500", ledOn: "#ff7f7f", ledOff: "#202020", buttonOuter: "#979797", @@ -35,44 +35,44 @@ namespace pxsim.micro_bit { virtualButtonUp: "#fff", lightLevelOn: "yellow", lightLevelOff: "#555" - }}); + } + }); - export function randomTheme() : IBoardTheme { + export function randomTheme(): IBoardTheme { return themes[Math.floor(Math.random() * themes.length)]; } export interface IBoardProps { runtime: pxsim.Runtime; theme?: IBoardTheme; - disableTilt?:boolean; + disableTilt?: boolean; } - + const pointerEvents = !!(window as any).PointerEvent ? { up: "pointerup", down: "pointerdown", move: "pointermove", leave: "pointerleave" } : { - up: "mouseup", - down: "mousedown", - move: "mousemove", - leave: "mouseleave" - }; + up: "mouseup", + down: "mousedown", + move: "mousemove", + leave: "mouseleave" + }; - export class MicrobitBoardSvg - { - public element : SVGSVGElement; + export class MicrobitBoardSvg { + public element: SVGSVGElement; private style: SVGStyleElement; - private defs : SVGDefsElement; + private defs: SVGDefsElement; private g: SVGElement; - + private logos: SVGElement[]; private head: SVGGElement; private headInitialized = false; private headText: SVGTextElement; private display: SVGElement; private buttons: SVGElement[]; private buttonsOuter: SVGElement[]; - private buttonABText:SVGTextElement; + private buttonABText: SVGTextElement; private pins: SVGElement[]; private pinGradients: SVGLinearGradientElement[]; private pinTexts: SVGTextElement[]; @@ -81,27 +81,27 @@ namespace pxsim.micro_bit { private systemLed: SVGCircleElement; private antenna: SVGPolylineElement; private lightLevelButton: SVGCircleElement; - private lightLevelGradient : SVGLinearGradientElement; + private lightLevelGradient: SVGLinearGradientElement; private lightLevelText: SVGTextElement; - private thermometerGradient : SVGLinearGradientElement; + private thermometerGradient: SVGLinearGradientElement; private thermometer: SVGRectElement; private thermometerText: SVGTextElement; private shakeButton: SVGCircleElement; private shakeText: SVGTextElement; - public board: pxsim.Board; - + public board: pxsim.Board; + constructor(public props: IBoardProps) { this.board = this.props.runtime.board as pxsim.Board; this.board.updateView = () => this.updateState(); - this.buildDom(); + this.buildDom(); this.updateTheme(); this.updateState(); this.attachEvents(); } - + private updateTheme() { let theme = this.props.theme; - + Svg.fill(this.display, theme.display); Svg.fills(this.leds, theme.ledOn); Svg.fills(this.ledsOuter, theme.ledOff); @@ -111,81 +111,81 @@ namespace pxsim.micro_bit { Svg.fill(this.buttons[2], theme.virtualButtonUp); Svg.fills(this.logos, theme.accent); if (this.shakeButton) Svg.fill(this.shakeButton, theme.virtualButtonUp); - - this.pinGradients.forEach(lg => Svg.setGradientColors(lg, theme.pin, theme.pinActive)); + + this.pinGradients.forEach(lg => Svg.setGradientColors(lg, theme.pin, theme.pinActive)); Svg.setGradientColors(this.lightLevelGradient, theme.lightLevelOn, theme.lightLevelOff); - + Svg.setGradientColors(this.thermometerGradient, theme.ledOff, theme.ledOn); } - + public updateState() { let state = this.board; if (!state) return; let theme = this.props.theme; - + state.buttons.forEach((btn, index) => { - Svg.fill(this.buttons[index], btn.pressed ? theme.buttonDown : theme.buttonUp); + Svg.fill(this.buttons[index], btn.pressed ? theme.buttonDown : theme.buttonUp); }); - - var bw = state.displayMode == pxsim.DisplayMode.bw - var img = state.image; - this.leds.forEach((led,i) => { - var sel = (led) + + let bw = state.displayMode == pxsim.DisplayMode.bw + let img = state.image; + this.leds.forEach((led, i) => { + let sel = (led) sel.style.opacity = ((bw ? img.data[i] > 0 ? 255 : 0 : img.data[i]) / 255.0) + ""; }) this.updatePins(); this.updateTilt(); - this.updateHeading(); + this.updateHeading(); this.updateLightLevel(); - this.updateTemperature(); - this.updateButtonAB(); - this.updateGestures(); - + this.updateTemperature(); + this.updateButtonAB(); + this.updateGestures(); + if (!runtime || runtime.dead) Svg.addClass(this.element, "grayscale"); else Svg.removeClass(this.element, "grayscale"); } - + private updateGestures() { let state = this.board; if (state.useShake && !this.shakeButton) { - this.shakeButton = Svg.child(this.g, "circle", {cx:380, cy:100, r:16.5}) as SVGCircleElement; + this.shakeButton = Svg.child(this.g, "circle", { cx: 380, cy: 100, r: 16.5 }) as SVGCircleElement; Svg.fill(this.shakeButton, this.props.theme.virtualButtonUp) this.shakeButton.addEventListener(pointerEvents.down, ev => { let state = this.board; - Svg.fill(this.shakeButton, this.props.theme.buttonDown); + Svg.fill(this.shakeButton, this.props.theme.buttonDown); }) this.shakeButton.addEventListener(pointerEvents.leave, ev => { let state = this.board; - Svg.fill(this.shakeButton, this.props.theme.virtualButtonUp); + Svg.fill(this.shakeButton, this.props.theme.virtualButtonUp); }) this.shakeButton.addEventListener(pointerEvents.up, ev => { let state = this.board; - Svg.fill(this.shakeButton, this.props.theme.virtualButtonUp); + Svg.fill(this.shakeButton, this.props.theme.virtualButtonUp); this.board.bus.queue(DAL.MICROBIT_ID_GESTURE, 11); // GESTURE_SHAKE - }) - this.shakeText = Svg.child(this.g, "text", {x:400, y:110, class:'sim-text'}) as SVGTextElement; - this.shakeText.textContent = "SHAKE" - } + }) + this.shakeText = Svg.child(this.g, "text", { x: 400, y: 110, class: "sim-text" }) as SVGTextElement; + this.shakeText.textContent = "SHAKE" + } } - + private updateButtonAB() { let state = this.board; if (state.usesButtonAB && !this.buttonABText) { - (this.buttonsOuter[2]).style.visibility = 'visible'; - (this.buttons[2]).style.visibility = 'visible'; - this.buttonABText = Svg.child(this.g, "text", {class: 'sim-text', x:370, y:272 }) as SVGTextElement; + (this.buttonsOuter[2]).style.visibility = "visible"; + (this.buttons[2]).style.visibility = "visible"; + this.buttonABText = Svg.child(this.g, "text", { class: "sim-text", x: 370, y: 272 }) as SVGTextElement; this.buttonABText.textContent = "A+B"; this.updateTheme(); - } + } } - - private updatePin(pin : Pin, index: number) { + + private updatePin(pin: Pin, index: number) { if (!pin) return; let text = this.pinTexts[index]; - let v = ''; + let v = ""; if (pin.mode & PinMode.Analog) { - v = Math.floor(100 - (pin.value || 0) / 1023 * 100) + '%'; - if(text) text.textContent = (pin.period ? "~" : "") + (pin.value || 0) + ""; + v = Math.floor(100 - (pin.value || 0) / 1023 * 100) + "%"; + if (text) text.textContent = (pin.period ? "~" : "") + (pin.value || 0) + ""; } else if (pin.mode & PinMode.Digital) { v = pin.value > 0 ? '0%' : '100%'; @@ -196,48 +196,48 @@ namespace pxsim.micro_bit { if (text) text.textContent = ""; } else { v = '100%'; - if(text) text.textContent = ''; + if (text) text.textContent = ''; } if (v) Svg.setGradientValue(this.pinGradients[index], v); } - + private updateTemperature() { let state = this.board; if (!state || !state.usesTemperature) return; - + let tmin = -5; let tmax = 50; - if (!this.thermometer) { + if (!this.thermometer) { let gid = "gradient-thermometer"; this.thermometerGradient = Svg.linearGradient(this.defs, gid); - this.thermometer = Svg.child(this.g, "rect", { - class: "sim-thermometer", - x:120, - y:110, - width:20, - height:160, - rx:5, ry:5, - fill:`url(#${gid})` + this.thermometer = Svg.child(this.g, "rect", { + class: "sim-thermometer", + x: 120, + y: 110, + width: 20, + height: 160, + rx: 5, ry: 5, + fill: `url(#${gid})` }); - this.thermometerText = Svg.child(this.g, "text", { class:'sim-text', x:58, y:130}) as SVGTextElement; + this.thermometerText = Svg.child(this.g, "text", { class: 'sim-text', x: 58, y: 130 }) as SVGTextElement; this.updateTheme(); - + let pt = this.element.createSVGPoint(); Svg.buttonEvents(this.thermometer, (ev) => { let cur = Svg.cursorPoint(pt, this.element, ev); let t = Math.max(0, Math.min(1, (260 - cur.y) / 140)) - state.temperature = Math.floor(tmin + t * (tmax-tmin)); + state.temperature = Math.floor(tmin + t * (tmax - tmin)); this.updateTemperature(); - }, ev => {}, ev => {}) + }, ev => { }, ev => { }) } - + let t = Math.max(tmin, Math.min(tmax, state.temperature)) - let per = Math.floor((state.temperature - tmin) / (tmax-tmin)*100) + let per = Math.floor((state.temperature - tmin) / (tmax - tmin) * 100) Svg.setGradientValue(this.thermometerGradient, 100 - per + '%'); this.thermometerText.textContent = t + '°C'; } - + private updateHeading() { let xc = 258; let yc = 75; @@ -249,42 +249,42 @@ namespace pxsim.micro_bit { let pt = this.element.createSVGPoint(); Svg.buttonEvents( this.head, - (ev : MouseEvent) => { - let cur = Svg.cursorPoint(pt, this.element, ev); - state.heading = Math.floor(Math.atan2(cur.y - yc, cur.x - xc) * 180 / Math.PI+90); - if (state.heading < 0) state.heading += 360; - console.log('heading: ' + state.heading) - this.updateHeading(); + (ev: MouseEvent) => { + let cur = Svg.cursorPoint(pt, this.element, ev); + state.heading = Math.floor(Math.atan2(cur.y - yc, cur.x - xc) * 180 / Math.PI + 90); + if (state.heading < 0) state.heading += 360; + console.log('heading: ' + state.heading) + this.updateHeading(); }); this.headInitialized = true; } - + let txt = state.heading.toString() + '°'; - if (txt != this.headText.textContent) { - Svg.rotateElement(this.head, xc, yc, state.heading+180); + if (txt != this.headText.textContent) { + Svg.rotateElement(this.head, xc, yc, state.heading + 180); this.headText.textContent = txt; - } + } } - - private lastFlashTime : number = 0; + + private lastFlashTime: number = 0; public flashSystemLed() { if (!this.systemLed) - this.systemLed = Svg.child(this.g, "circle", {class:"sim-systemled", cx:300, cy:20, r:5}) + this.systemLed = Svg.child(this.g, "circle", { class: "sim-systemled", cx: 300, cy: 20, r: 5 }) let now = Date.now(); if (now - this.lastFlashTime > 150) { this.lastFlashTime = now; Svg.animate(this.systemLed, 'sim-flash') } } - - private lastAntennaFlash : number = 0; + + private lastAntennaFlash: number = 0; public flashAntenna() { - if (!this.antenna) { + if (!this.antenna) { let ax = 380; let dax = 18; let ayt = 10; let ayb = 40; - this.antenna = Svg.child(this.g, "polyline", { class:"sim-antenna", points: `${ax},${ayb} ${ax},${ayt} ${ax+=dax},${ayt} ${ax},${ayb} ${ax+=dax},${ayb} ${ax},${ayt} ${ax+=dax},${ayt} ${ax},${ayb} ${ax+=dax},${ayb} ${ax},${ayt} ${ax+=dax},${ayt}`}) + this.antenna = Svg.child(this.g, "polyline", { class: "sim-antenna", points: `${ax},${ayb} ${ax},${ayt} ${ax += dax},${ayt} ${ax},${ayb} ${ax += dax},${ayb} ${ax},${ayt} ${ax += dax},${ayt} ${ax},${ayb} ${ax += dax},${ayb} ${ax},${ayt} ${ax += dax},${ayt}` }) } let now = Date.now(); if (now - this.lastAntennaFlash > 200) { @@ -292,53 +292,54 @@ namespace pxsim.micro_bit { Svg.animate(this.antenna, 'sim-flash-stroke') } } - + private updatePins() { let state = this.board; if (!state) return; - - state.pins.forEach((pin,i) => this.updatePin(pin,i)); - } - + + state.pins.forEach((pin, i) => this.updatePin(pin, i)); + } + private updateLightLevel() { let state = this.board; if (!state || !state.usesLightLevel) return; - + if (!this.lightLevelButton) { - let gid= "gradient-light-level"; - this.lightLevelGradient = Svg.linearGradient(this.defs, gid) + let gid = "gradient-light-level"; + this.lightLevelGradient = Svg.linearGradient(this.defs, gid) let cy = 50; let r = 35; - this.lightLevelButton = Svg.child(this.g, "circle", { - cx: `50px`, cy: `${cy}px`, r: `${r}px`, - class:'sim-light-level-button', - fill: `url(#${gid})` }) as SVGCircleElement; + this.lightLevelButton = Svg.child(this.g, "circle", { + cx: `50px`, cy: `${cy}px`, r: `${r}px`, + class: 'sim-light-level-button', + fill: `url(#${gid})` + }) as SVGCircleElement; let pt = this.element.createSVGPoint(); Svg.buttonEvents(this.lightLevelButton, (ev) => { let pos = Svg.cursorPoint(pt, this.element, ev); - let rs = r/2; - let level = Math.max(0, Math.min(255, Math.floor((pos.y - (cy-rs)) / (2*rs) * 255))); + let rs = r / 2; + let level = Math.max(0, Math.min(255, Math.floor((pos.y - (cy - rs)) / (2 * rs) * 255))); if (level != this.board.lightLevel) { this.board.lightLevel = level; this.applyLightLevel(); } - }, ev => {}, - ev => {}) - this.lightLevelText = Svg.child(this.g, "text", { x:85, y:cy+r-5, text:'', class:'sim-text'}) as SVGTextElement; + }, ev => { }, + ev => { }) + this.lightLevelText = Svg.child(this.g, "text", { x: 85, y: cy + r - 5, text: '', class: 'sim-text' }) as SVGTextElement; this.updateTheme(); - } - - Svg.setGradientValue(this.lightLevelGradient, Math.min(100, Math.max(0, Math.floor(state.lightLevel * 100 / 255))) + '%') + } + + Svg.setGradientValue(this.lightLevelGradient, Math.min(100, Math.max(0, Math.floor(state.lightLevel * 100 / 255))) + '%') this.lightLevelText.textContent = state.lightLevel.toString(); - } - + } + private applyLightLevel() { let lv = this.board.lightLevel; - Svg.setGradientValue(this.lightLevelGradient, Math.min(100, Math.max(0, Math.floor(lv * 100 / 255))) + '%') - this.lightLevelText.textContent = lv.toString(); + Svg.setGradientValue(this.lightLevelGradient, Math.min(100, Math.max(0, Math.floor(lv * 100 / 255))) + '%') + this.lightLevelText.textContent = lv.toString(); } - + private updateTilt() { if (this.props.disableTilt) return; let state = this.board; @@ -348,20 +349,21 @@ namespace pxsim.micro_bit { let y = state.accelerometer.getY(); let af = 8 / 1023; - this.element.style.transform = "perspective(30em) rotateX(" + y*af + "deg) rotateY(" + x*af +"deg)" + this.element.style.transform = "perspective(30em) rotateX(" + y * af + "deg) rotateY(" + x * af + "deg)" this.element.style.perspectiveOrigin = "50% 50% 50%"; - this.element.style.perspective = "30em"; + this.element.style.perspective = "30em"; } - + private buildDom() { this.element = Svg.elt("svg") Svg.hydrate(this.element, { - "version": "1.0", + "version": "1.0", "viewBox": "0 0 498 406", "enable-background": "new 0 0 498 406", - "class":"sim", + "class": "sim", "x": "0px", - "y": "0px"}); + "y": "0px" + }); this.style = Svg.child(this.element, "style", {}); this.style.textContent = ` svg.sim { @@ -457,66 +459,66 @@ svg.sim.grayscale { } `; - - + + this.defs = Svg.child(this.element, "defs", {}); this.g = Svg.elt("g"); this.element.appendChild(this.g); - + // filters - let glow = Svg.child(this.defs, "filter", {id:"filterglow", x:"-5%", y:"-5%", width:"120%", height:"120%"}); - Svg.child(glow, "feGaussianBlur", {stdDeviation:"5", result: "glow" }); + let glow = Svg.child(this.defs, "filter", { id: "filterglow", x: "-5%", y: "-5%", width: "120%", height: "120%" }); + Svg.child(glow, "feGaussianBlur", { stdDeviation: "5", result: "glow" }); let merge = Svg.child(glow, "feMerge", {}); - for(let i=0;i<3;++i) Svg.child(merge, "feMergeNode", {in:"glow"}) - + for (let i = 0; i < 3; ++i) Svg.child(merge, "feMergeNode", { in: "glow" }) + // outline - Svg.path(this.g, "sim-board", "M498,31.9C498,14.3,483.7,0,466.1,0H31.9C14.3,0,0,14.3,0,31.9v342.2C0,391.7,14.3,406,31.9,406h434.2c17.6,0,31.9-14.3,31.9-31.9V31.9z M14.3,206.7c-2.7,0-4.8-2.2-4.8-4.8c0-2.7,2.2-4.8,4.8-4.8c2.7,0,4.8,2.2,4.8,4.8C19.2,204.6,17,206.7,14.3,206.7z M486.2,206.7c-2.7,0-4.8-2.2-4.8-4.8c0-2.72.2-4.8,4.8-4.8c2.7,0,4.8,2.2,4.8,4.8C491,204.6,488.8,206.7,486.2,206.7z"); + Svg.path(this.g, "sim-board", "M498,31.9C498,14.3,483.7,0,466.1,0H31.9C14.3,0,0,14.3,0,31.9v342.2C0,391.7,14.3,406,31.9,406h434.2c17.6,0,31.9-14.3,31.9-31.9V31.9z M14.3,206.7c-2.7,0-4.8-2.2-4.8-4.8c0-2.7,2.2-4.8,4.8-4.8c2.7,0,4.8,2.2,4.8,4.8C19.2,204.6,17,206.7,14.3,206.7z M486.2,206.7c-2.7,0-4.8-2.2-4.8-4.8c0-2.72.2-4.8,4.8-4.8c2.7,0,4.8,2.2,4.8,4.8C491,204.6,488.8,206.7,486.2,206.7z"); // script background this.display = Svg.path(this.g, "sim-display", "M333.8,310.3H165.9c-8.3,0-15-6.7-15-15V127.5c0-8.3,6.7-15,15-15h167.8c8.3,0,15,6.7,15,15v167.8C348.8,303.6,342.1,310.3,333.8,310.3z"); this.logos = []; - this.logos.push(Svg.child(this.g, "polygon", {class:"sim-theme", points:"115,56.7 173.1,0 115,0"})); + this.logos.push(Svg.child(this.g, "polygon", { class: "sim-theme", points: "115,56.7 173.1,0 115,0" })); this.logos.push(Svg.path(this.g, "sim-theme", "M114.2,0H25.9C12.1,2.1,0,13.3,0,27.7v83.9L114.2,0z")); - this.logos.push(Svg.child(this.g, "polygon", {class:"sim-theme", points:"173,27.9 202.5,0 173,0"})); - this.logos.push(Svg.child(this.g, "polygon", {class:"sim-theme", points:"54.1,242.4 54.1,274.1 22.4,274.1"})); - this.logos.push(Svg.child(this.g, "polygon", {class:"sim-theme", points:"446.2,164.6 446.2,132.8 477.9,132.8"})); - + this.logos.push(Svg.child(this.g, "polygon", { class: "sim-theme", points: "173,27.9 202.5,0 173,0" })); + this.logos.push(Svg.child(this.g, "polygon", { class: "sim-theme", points: "54.1,242.4 54.1,274.1 22.4,274.1" })); + this.logos.push(Svg.child(this.g, "polygon", { class: "sim-theme", points: "446.2,164.6 446.2,132.8 477.9,132.8" })); + // leds this.leds = []; this.ledsOuter = []; - var left = 154, top = 113, ledoffw = 46, ledoffh = 44; - for (var i = 0; i < 5; ++i) { - var ledtop = i * ledoffh + top; - for (var j = 0; j < 5; ++j) { - var ledleft = j * ledoffw + left; - var k = i * 5 + j; - this.ledsOuter.push(Svg.child(this.g, "rect", { class:"sim-led-back", x:ledleft, y:ledtop, width:10, height:20, rx:2, ry:2 })); - this.leds.push(Svg.child(this.g, "rect", { class:"sim-led", x:ledleft-2, y:ledtop-2, width:14, height:24, rx:3, ry:3, title:`(${j},${i})`})); + let left = 154, top = 113, ledoffw = 46, ledoffh = 44; + for (let i = 0; i < 5; ++i) { + let ledtop = i * ledoffh + top; + for (let j = 0; j < 5; ++j) { + let ledleft = j * ledoffw + left; + let k = i * 5 + j; + this.ledsOuter.push(Svg.child(this.g, "rect", { class: "sim-led-back", x: ledleft, y: ledtop, width: 10, height: 20, rx: 2, ry: 2 })); + this.leds.push(Svg.child(this.g, "rect", { class: "sim-led", x: ledleft - 2, y: ledtop - 2, width: 14, height: 24, rx: 3, ry: 3, title: `(${j},${i})` })); } } - + // head this.head = Svg.child(this.g, "g", {}); - Svg.child(this.head, "circle", { cx: 258, cy: 75, r: 100, fill:'transparent'}) - this.logos.push(Svg.path(this.head, "sim-theme","M269.9,50.2L269.9,50.2l-39.5,0v0c-14.1,0.1-24.6,10.7-24.6,24.8c0,13.9,10.4,24.4,24.3,24.7v0h39.6c14.2,0,24.8-10.6,24.8-24.7C294.5,61,284,50.3,269.9,50.2 M269.7,89.2L269.7,89.2l-39.3,0c-7.7-0.1-14-6.4-14-14.2c0-7.8,6.4-14.2,14.2-14.2h39.1c7.8,0,14.2,6.4,14.2,14.2C283.9,82.9,277.5,89.2,269.7,89.2")); - this.logos.push(Svg.path(this.head, "sim-theme","M230.6,69.7c-2.9,0-5.3,2.4-5.3,5.3c0,2.9,2.4,5.3,5.3,5.3c2.9,0,5.3-2.4,5.3-5.3C235.9,72.1,233.5,69.7,230.6,69.7")); - this.logos.push(Svg.path(this.head, "sim-theme","M269.7,80.3c2.9,0,5.3-2.4,5.3-5.3c0-2.9-2.4-5.3-5.3-5.3c-2.9,0-5.3,2.4-5.3,5.3C264.4,77.9,266.8,80.3,269.7,80.3")); - this.headText = Svg.child(this.g, "text", { x: 310, y: 100, class:'sim-text' }) - + Svg.child(this.head, "circle", { cx: 258, cy: 75, r: 100, fill: "transparent" }) + this.logos.push(Svg.path(this.head, "sim-theme", "M269.9,50.2L269.9,50.2l-39.5,0v0c-14.1,0.1-24.6,10.7-24.6,24.8c0,13.9,10.4,24.4,24.3,24.7v0h39.6c14.2,0,24.8-10.6,24.8-24.7C294.5,61,284,50.3,269.9,50.2 M269.7,89.2L269.7,89.2l-39.3,0c-7.7-0.1-14-6.4-14-14.2c0-7.8,6.4-14.2,14.2-14.2h39.1c7.8,0,14.2,6.4,14.2,14.2C283.9,82.9,277.5,89.2,269.7,89.2")); + this.logos.push(Svg.path(this.head, "sim-theme", "M230.6,69.7c-2.9,0-5.3,2.4-5.3,5.3c0,2.9,2.4,5.3,5.3,5.3c2.9,0,5.3-2.4,5.3-5.3C235.9,72.1,233.5,69.7,230.6,69.7")); + this.logos.push(Svg.path(this.head, "sim-theme", "M269.7,80.3c2.9,0,5.3-2.4,5.3-5.3c0-2.9-2.4-5.3-5.3-5.3c-2.9,0-5.3,2.4-5.3,5.3C264.4,77.9,266.8,80.3,269.7,80.3")); + this.headText = Svg.child(this.g, "text", { x: 310, y: 100, class: "sim-text" }) + // https://www.microbit.co.uk/device/pins // P0, P1, P2 this.pins = [ "M16.5,341.2c0,0.4-0.1,0.9-0.1,1.3v60.7c4.1,1.7,8.6,2.7,12.9,2.7h34.4v-64.7h0.3c0,0,0-0.1,0-0.1c0-13-10.6-23.6-23.7-23.6C27.2,317.6,16.5,328.1,16.5,341.2z M21.2,341.6c0-10.7,8.7-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3c0,10.7-8.6,19.3-19.3,19.3C29.9,360.9,21.2,352.2,21.2,341.6z", "M139.1,317.3c-12.8,0-22.1,10.3-23.1,23.1V406h46.2v-65.6C162.2,327.7,151.9,317.3,139.1,317.3zM139.3,360.1c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C158.6,351.5,150,360.1,139.3,360.1z", "M249,317.3c-12.8,0-22.1,10.3-23.1,23.1V406h46.2v-65.6C272.1,327.7,261.8,317.3,249,317.3z M249.4,360.1c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C268.7,351.5,260.1,360.1,249.4,360.1z" - ].map((p,pi) => Svg.path(this.g, "sim-pin sim-pin-touch", p, `P${pi}, ANALOG IN`)); + ].map((p, pi) => Svg.path(this.g, "sim-pin sim-pin-touch", p, `P${pi}, ANALOG IN`)); // P3 this.pins.push(Svg.path(this.g, "sim-pin", "M0,357.7v19.2c0,10.8,6.2,20.2,14.4,25.2v-44.4H0z", "P3, ANALOG IN, LED Col 1")); - [66.7,79.1,91.4,103.7,164.3,176.6,188.9,201.3,213.6,275.2,287.5,299.8,312.1,324.5,385.1,397.4,409.7,422].forEach(x => { - this.pins.push(Svg.child(this.g, "rect", {x:x, y:356.7, width:10, height:50, class:"sim-pin"})); + [66.7, 79.1, 91.4, 103.7, 164.3, 176.6, 188.9, 201.3, 213.6, 275.2, 287.5, 299.8, 312.1, 324.5, 385.1, 397.4, 409.7, 422].forEach(x => { + this.pins.push(Svg.child(this.g, "rect", { x: x, y: 356.7, width: 10, height: 50, class: "sim-pin" })); }) Svg.title(this.pins[4], "P4, ANALOG IN, LED Col 2") Svg.title(this.pins[5], "P5, BUTTON A") @@ -536,32 +538,32 @@ svg.sim.grayscale { Svg.title(this.pins[19], "P19, I2C - SCL") Svg.title(this.pins[20], "P20, I2C - SDA") Svg.title(this.pins[21], "GND") - - this.pins.push(Svg.path(this.g, "sim-pin", "M483.6,402c8.2-5,14.4-14.4,14.4-25.1v-19.2h-14.4V402z", "GND")); - + + this.pins.push(Svg.path(this.g, "sim-pin", "M483.6,402c8.2-5,14.4-14.4,14.4-25.1v-19.2h-14.4V402z", "GND")); + this.pins.push(Svg.path(this.g, "sim-pin", "M359.9,317.3c-12.8,0-22.1,10.3-23.1,23.1V406H383v-65.6C383,327.7,372.7,317.3,359.9,317.3z M360,360.1c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C379.3,351.5,370.7,360.1,360,360.1z", "+3v3")); this.pins.push(Svg.path(this.g, "sim-pin", "M458,317.6c-13,0-23.6,10.6-23.6,23.6c0,0,0,0.1,0,0.1h0V406H469c4.3,0,8.4-1,12.6-2.7v-60.7c0-0.4,0-0.9,0-1.3C481.6,328.1,471,317.6,458,317.6z M457.8,360.9c-10.7,0-19.3-8.6-19.3-19.3c0-10.7,8.6-19.3,19.3-19.3c10.7,0,19.3,8.7,19.3,19.3C477.1,352.2,468.4,360.9,457.8,360.9z", "GND")); - - - this.pinGradients = this.pins.map((pin,i) => { - let gid= "gradient-pin-" + i - let lg = Svg.linearGradient(this.defs, gid) + + + this.pinGradients = this.pins.map((pin, i) => { + let gid = "gradient-pin-" + i + let lg = Svg.linearGradient(this.defs, gid) pin.setAttribute("fill", `url(#${gid})`); return lg; }) - - this.pinTexts = [67,165,275].map(x => Svg.child(this.g, "text", { class:'sim-text-pin', x:x, y:345})); + + this.pinTexts = [67, 165, 275].map(x => Svg.child(this.g, "text", { class: 'sim-text-pin', x: x, y: 345 })); this.buttonsOuter = []; this.buttons = []; this.buttonsOuter.push(Svg.path(this.g, "sim-button-outer", "M82.1,232.6H25.9c-0.5,0-1-0.4-1-1v-56.2c0-0.5,0.4-1,1-1h56.2c0.5,0,1,0.4,1,1v56.2C83,232.2,82.6,232.6,82.1,232.6", "A")); this.buttons.push(Svg.path(this.g, "sim-button", "M69.7,203.5c0,8.7-7,15.7-15.7,15.7s-15.7-7-15.7-15.7c0-8.7,7-15.7,15.7-15.7S69.7,194.9,69.7,203.5")); this.buttonsOuter.push(Svg.path(this.g, "sim-button-outer", "M474.3,232.6h-56.2c-0.5,0-1-0.4-1-1v-56.2c0-0.5,0.4-1,1-1h56.2c0.5,0,1,0.4,1,1v56.2C475.3,232.2,474.8,232.6,474.3,232.6", "B")); - this.buttons.push(Svg.path(this.g, "sim-button", "M461.9,203.5c0,8.7-7,15.7-15.7,15.7c-8.7,0-15.7-7-15.7-15.7c0-8.7,7-15.7,15.7-15.7C454.9,187.8,461.9,194.9,461.9,203.5")); - this.buttonsOuter.push(Svg.child(this.g, "rect", {class:"sim-button-outer", x:417, y:250, width:58, height:58, rx:1, ry:1, title:"A+B"})); - this.buttons.push(Svg.child(this.g, "circle", {class:"sim-button", cx:446, cy:278, r:16.5})); + this.buttons.push(Svg.path(this.g, "sim-button", "M461.9,203.5c0,8.7-7,15.7-15.7,15.7c-8.7,0-15.7-7-15.7-15.7c0-8.7,7-15.7,15.7-15.7C454.9,187.8,461.9,194.9,461.9,203.5")); + this.buttonsOuter.push(Svg.child(this.g, "rect", { class: "sim-button-outer", x: 417, y: 250, width: 58, height: 58, rx: 1, ry: 1, title: "A+B" })); + this.buttons.push(Svg.child(this.g, "circle", { class: "sim-button", cx: 446, cy: 278, r: 16.5 })); (this.buttonsOuter[2]).style.visibility = 'hidden'; (this.buttons[2]).style.visibility = 'hidden'; - + Svg.path(this.g, "sim-label", "M35.7,376.4c0-2.8,2.1-5.1,5.5-5.1c3.3,0,5.5,2.4,5.5,5.1v4.7c0,2.8-2.2,5.1-5.5,5.1c-3.3,0-5.5-2.4-5.5-5.1V376.4zM43.3,376.4c0-1.3-0.8-2.3-2.2-2.3c-1.3,0-2.1,1.1-2.1,2.3v4.7c0,1.2,0.8,2.3,2.1,2.3c1.3,0,2.2-1.1,2.2-2.3V376.4z"); Svg.path(this.g, "sim-label", "M136.2,374.1c2.8,0,3.4-0.8,3.4-2.5h2.9v14.3h-3.4v-9.5h-3V374.1z"); Svg.path(this.g, "sim-label", "M248.6,378.5c1.7-1,3-1.7,3-3.1c0-1.1-0.7-1.6-1.6-1.6c-1,0-1.8,0.6-1.8,2.1h-3.3c0-2.6,1.8-4.6,5.1-4.6c2.6,0,4.9,1.3,4.9,4.3c0,2.4-2.3,3.9-3.8,4.7c-2,1.3-2.5,1.8-2.5,2.9h6.1v2.7h-10C244.8,381.2,246.4,379.9,248.6,378.5z"); @@ -572,12 +574,12 @@ svg.sim.grayscale { Svg.path(this.g, "sim-label", "M368.5,385.9h-3.1l-5.1-14.3h3.5l3.1,10.1l3.1-10.1h3.6L368.5,385.9z") Svg.path(this.g, "sim-label", "M444.4,378.3h7.4v2.5h-1.5c-0.6,3.3-3,5.5-7.1,5.5c-4.8,0-7.5-3.5-7.5-7.5c0-3.9,2.8-7.5,7.5-7.5c3.8,0,6.4,2.3,6.6,5h-3.5c-0.2-1.1-1.4-2.2-3.1-2.2c-2.7,0-4.1,2.3-4.1,4.7c0,2.5,1.4,4.7,4.4,4.7c2,0,3.2-1.2,3.4-2.7h-2.5V378.3z") Svg.path(this.g, "sim-label", "M461.4,380.9v-9.3h3.3v14.3h-3.5l-5.2-9.2v9.2h-3.3v-14.3h3.5L461.4,380.9z") - Svg.path(this.g, "sim-label", "M472.7,371.6c4.8,0,7.5,3.5,7.5,7.2s-2.7,7.2-7.5,7.2h-5.3v-14.3H472.7z M470.8,374.4v8.6h1.8c2.7,0,4.2-2.1,4.2-4.3s-1.6-4.3-4.2-4.3H470.8z") + Svg.path(this.g, "sim-label", "M472.7,371.6c4.8,0,7.5,3.5,7.5,7.2s-2.7,7.2-7.5,7.2h-5.3v-14.3H472.7z M470.8,374.4v8.6h1.8c2.7,0,4.2-2.1,4.2-4.3s-1.6-4.3-4.2-4.3H470.8z") } - + private attachEvents() { Runtime.messagePosted = (msg) => { - switch(msg.type || '') { + switch (msg.type || '') { case 'serial': this.flashSystemLed(); break; case 'radiopacket': this.flashAntenna(); break; } @@ -585,8 +587,8 @@ svg.sim.grayscale { let tiltDecayer = 0; this.element.addEventListener(pointerEvents.move, (ev: MouseEvent) => { let state = this.board; - if (!state.accelerometer.isActive) return; - + if (!state.accelerometer.isActive) return; + if (tiltDecayer) { clearInterval(tiltDecayer); tiltDecayer = 0; @@ -594,39 +596,39 @@ svg.sim.grayscale { let ax = (ev.clientX - this.element.clientWidth / 2) / (this.element.clientWidth / 3); let ay = (ev.clientY - this.element.clientHeight / 2) / (this.element.clientHeight / 3); - + let x = - Math.max(- 1023, Math.min(1023, Math.floor(ax * 1023))); let y = Math.max(- 1023, Math.min(1023, Math.floor(ay * 1023))); - let z2 = 1023*1023 - x * x - y * y; - let z = Math.floor((z2 > 0 ? -1 : 1)* Math.sqrt(Math.abs(z2))); - - state.accelerometer.update(x,y,z); + let z2 = 1023 * 1023 - x * x - y * y; + let z = Math.floor((z2 > 0 ? -1 : 1) * Math.sqrt(Math.abs(z2))); + + state.accelerometer.update(x, y, z); this.updateTilt(); }, false); this.element.addEventListener(pointerEvents.leave, (ev: MouseEvent) => { let state = this.board; if (!state.accelerometer.isActive) return; - + if (!tiltDecayer) { tiltDecayer = setInterval(() => { let accx = state.accelerometer.getX(MicroBitCoordinateSystem.RAW); accx = Math.floor(Math.abs(accx) * 0.85) * (accx > 0 ? 1 : -1); let accy = state.accelerometer.getY(MicroBitCoordinateSystem.RAW); accy = Math.floor(Math.abs(accy) * 0.85) * (accy > 0 ? 1 : -1); - let accz = -Math.sqrt(Math.max(0, 1023*1023 - accx*accx - accy*accy)); + let accz = -Math.sqrt(Math.max(0, 1023 * 1023 - accx * accx - accy * accy)); if (Math.abs(accx) <= 24 && Math.abs(accy) <= 24) { - clearInterval(tiltDecayer); - tiltDecayer = 0; + clearInterval(tiltDecayer); + tiltDecayer = 0; accx = 0; accy = 0; - accz = -1023; - } + accz = -1023; + } state.accelerometer.update(accx, accy, accz); - this.updateTilt(); - }, 50) + this.updateTilt(); + }, 50) } }, false); - + this.pins.forEach((pin, index) => { if (!this.board.pins[index]) return; let pt = this.element.createSVGPoint(); @@ -641,32 +643,32 @@ svg.sim.grayscale { let v = (400 - cursor.y) / 40 * 1023 pin.value = Math.max(0, Math.min(1023, Math.floor(v))); } - this.updatePin(pin,index); + this.updatePin(pin, index); }, // start ev => { let state = this.board; let pin = state.pins[index]; let svgpin = this.pins[index]; - Svg.addClass(svgpin, 'touched'); + Svg.addClass(svgpin, "touched"); if (pin.mode & PinMode.Input) { let cursor = Svg.cursorPoint(pt, this.element, ev); let v = (400 - cursor.y) / 40 * 1023 pin.value = Math.max(0, Math.min(1023, Math.floor(v))); } - this.updatePin(pin,index); + this.updatePin(pin, index); }, // stop (ev: MouseEvent) => { let state = this.board; let pin = state.pins[index]; let svgpin = this.pins[index]; - Svg.removeClass(svgpin, 'touched'); + Svg.removeClass(svgpin, "touched"); this.updatePin(pin, index); return false; - }); + }); }) - this.pins.slice(0,3).forEach((btn, index) => { + this.pins.slice(0, 3).forEach((btn, index) => { btn.addEventListener(pointerEvents.down, ev => { let state = this.board; state.pins[index].touched = true; @@ -682,13 +684,13 @@ svg.sim.grayscale { state.pins[index].touched = false; this.updatePin(state.pins[index], index); this.board.bus.queue(state.pins[index].id, DAL.MICROBIT_BUTTON_EVT_CLICK); - }) + }) }) - this.buttonsOuter.slice(0,2).forEach((btn, index) => { + this.buttonsOuter.slice(0, 2).forEach((btn, index) => { btn.addEventListener(pointerEvents.down, ev => { let state = this.board; state.buttons[index].pressed = true; - Svg.fill(this.buttons[index], this.props.theme.buttonDown); + Svg.fill(this.buttons[index], this.props.theme.buttonDown); }) btn.addEventListener(pointerEvents.leave, ev => { let state = this.board; @@ -699,39 +701,39 @@ svg.sim.grayscale { let state = this.board; state.buttons[index].pressed = false; Svg.fill(this.buttons[index], this.props.theme.buttonUp); - + this.board.bus.queue(state.buttons[index].id, DAL.MICROBIT_BUTTON_EVT_CLICK); }) }) this.buttonsOuter[2].addEventListener(pointerEvents.down, ev => { - let state = this.board; - state.buttons[0].pressed = true; - state.buttons[1].pressed = true; - state.buttons[2].pressed = true; - Svg.fill(this.buttons[0], this.props.theme.buttonDown); - Svg.fill(this.buttons[1], this.props.theme.buttonDown); - Svg.fill(this.buttons[2], this.props.theme.buttonDown); - }) + let state = this.board; + state.buttons[0].pressed = true; + state.buttons[1].pressed = true; + state.buttons[2].pressed = true; + Svg.fill(this.buttons[0], this.props.theme.buttonDown); + Svg.fill(this.buttons[1], this.props.theme.buttonDown); + Svg.fill(this.buttons[2], this.props.theme.buttonDown); + }) this.buttonsOuter[2].addEventListener(pointerEvents.leave, ev => { - let state = this.board; - state.buttons[0].pressed = false; - state.buttons[1].pressed = false; - state.buttons[2].pressed = false; - Svg.fill(this.buttons[0], this.props.theme.buttonUp); - Svg.fill(this.buttons[1], this.props.theme.buttonUp); - Svg.fill(this.buttons[2], this.props.theme.virtualButtonUp); + let state = this.board; + state.buttons[0].pressed = false; + state.buttons[1].pressed = false; + state.buttons[2].pressed = false; + Svg.fill(this.buttons[0], this.props.theme.buttonUp); + Svg.fill(this.buttons[1], this.props.theme.buttonUp); + Svg.fill(this.buttons[2], this.props.theme.virtualButtonUp); }) this.buttonsOuter[2].addEventListener(pointerEvents.up, ev => { - let state = this.board; - state.buttons[0].pressed = false; - state.buttons[1].pressed = false; - state.buttons[2].pressed = false; - Svg.fill(this.buttons[0], this.props.theme.buttonUp); - Svg.fill(this.buttons[1], this.props.theme.buttonUp); - Svg.fill(this.buttons[2], this.props.theme.virtualButtonUp); - - this.board.bus.queue(state.buttons[2].id, DAL.MICROBIT_BUTTON_EVT_CLICK); - }) + let state = this.board; + state.buttons[0].pressed = false; + state.buttons[1].pressed = false; + state.buttons[2].pressed = false; + Svg.fill(this.buttons[0], this.props.theme.buttonUp); + Svg.fill(this.buttons[1], this.props.theme.buttonUp); + Svg.fill(this.buttons[2], this.props.theme.virtualButtonUp); + + this.board.bus.queue(state.buttons[2].id, DAL.MICROBIT_BUTTON_EVT_CLICK); + }) } } } \ No newline at end of file diff --git a/tslint.json b/tslint.json new file mode 100644 index 00000000..6d9bd5e2 --- /dev/null +++ b/tslint.json @@ -0,0 +1,56 @@ +{ + "rules": { + "class-name": true, + "comment-format": [ + true + ], + "indent": [ + true, + "spaces" + ], + "no-duplicate-variable": true, + "no-eval": true, + "no-internal-module": true, + "no-trailing-whitespace": true, + "no-var-keyword": true, + "one-line": [ + true, + "check-open-brace", + "check-whitespace" + ], + "quotemark": [ + true, + "double" + ], + "semicolon": [ + false, + "always" + ], + "triple-equals": [ + false, + "allow-null-check" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "variable-name": [ + true, + "ban-keywords" + ], + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ] + } +} \ No newline at end of file