import { MinHeap } from './MinHeap' ; import { MagnetManager } from './magnetManager' ; import { UserManager } from './UserManager' ; import { Share } from './share' ; /**
 * the graph where the nodes are the pixels that are not drawn
 */ export class PixelGraph { * getNeighbors ( node ) { const up = { x : node . x , y : node . y - 1 } ; const down = { x : node . x , y : node . y + 1 } ; const left = { x : node . x - 1 , y : node . y } ; const right = { x : node . x + 1 , y : node . y } ; function * possibleYield ( node ) { if ( ! S . isPixel ( node ) ) yield node ; } yield * possibleYield ( down ) ; yield * possibleYield ( up ) ; yield * possibleYield ( left ) ; yield * possibleYield ( right ) ; yield * possibleYield ( { x : node . x - 1 , y : node . y - 1 } ) ; yield * possibleYield ( { x : node . x - 1 , y : node . y + 1 } ) ; yield * possibleYield ( { x : node . x + 1 , y : node . y + 1 } ) ; yield * possibleYield ( { x : node . x + 1 , y : node . y - 1 } ) ; } * getEdgesToNeighbors ( node ) { const up = { x : node . x , y : node . y - 1 } ; const down = { x : node . x , y : node . y + 1 } ; const left = { x : node . x - 1 , y : node . y } ; const right = { x : node . x + 1 , y : node . y } ; const dist = ( a , b ) => Math . sqrt ( ( a . x - b . x ) ** 2 + ( a . y - b . y ) ** 2 ) ; function * possibleYield ( n ) { if ( ! S . isPixel ( n ) ) yield { node : n , weight : dist ( node , n ) } ; } yield * possibleYield ( down ) ; yield * possibleYield ( up ) ; yield * possibleYield ( left ) ; yield * possibleYield ( right ) ; yield * possibleYield ( { x : node . x - 1 , y : node . y - 1 } ) ; yield * possibleYield ( { x : node . x - 1 , y : node . y + 1 } ) ; yield * possibleYield ( { x : node . x + 1 , y : node . y + 1 } ) ; yield * possibleYield ( { x : node . x + 1 , y : node . y - 1 } ) ; } } window [ "MinHeap" ] = MinHeap ; window [ "PixelGraph" ] = PixelGraph ; /** this class contains the method that can be used in scripts of Tableaunoir */ export class S { private static audioCtx : AudioContext ; static boardReset ( ) { Share . execute ( "boardReset" , [ ] ) ; } static newOscillator ( ) { if ( ! S . audioCtx ) S . audioCtx = new ( window . AudioContext ) ; const oscillator = S . audioCtx . createOscillator ( ) ; oscillator . type = 'sawtooth' ; oscillator . frequency . value = 440 ; oscillator . connect ( S . audioCtx . destination ) ; return oscillator ; } static setFrequency ( oscillator , frequency ) { oscillator . frequency . value = frequency ; } /**
     * shake a magnet during 500ms
     */ static shake ( magnet ) { magnet . classList . add ( "shake" ) ; setTimeout ( ( ) => { magnet . classList . remove ( "shake" ) ; } , 500 ) ; } static playNote ( frequency , duration ) { if ( ! S . audioCtx ) S . audioCtx = new ( window . AudioContext ) ; const oscillator = S . audioCtx . createOscillator ( ) ; oscillator . type = 'triangle' ; oscillator . frequency . value = frequency ; oscillator . connect ( S . audioCtx . destination ) ; oscillator . start ( ) ; setTimeout ( ( ) => { oscillator . stop ( ) ; } , duration ) ; } /** assign S.mousemove to execute sth when you move the chalk on the board */ static onmagnetmousedown : ( evt ) => void = ( ) => { } ; static onmousemove : ( { x , y } : { x : number ; y : number ; } ) => void = ( ) => { } ; static onkey : ( keyname : string ) => void = ( ) => { } ; static onupdate : ( ) => void = ( ) => { } ; static onmagnetmove : ( evt ) => void = ( ) => { } ; param a param text description static magnetSetText ( magnet , text ) { magnet . innerHTML = text ; } param x return static round1 ( x ) { return Math . round ( 10 * x ) / 10 ; } param c description static setColor ( c ) { Share . execute ( "setCurrentColor" , [ UserManager . me . userID , c ] ) ; } param magnet param cx param cy description static magnetMove ( magnet , cx , cy ) { Share . execute ( "magnetMove" , [ magnet . id , cx - magnet . offsetWidth / 2 , cy - magnet . offsetHeight / 2 ] ) ; } param magnet return static magnetCenter ( magnet ) { return MagnetManager . getMagnetCenter ( magnet ) ; } param magnet return static magnetMiddleBottom ( magnet ) { return MagnetManager . getMagnetMiddleButton ( magnet ) ; } return static getMagnets ( ) { const magnets = MagnetManager . getMagnets ( ) ; const result = [ ] ; for ( let i = 0 ; i < magnets . length ; i ++ ) result . push ( magnets [ i ] ) ; return result ; } param point param rectangle return static inRectangle ( { x , y } , { x1 , y1 , x2 , y2 } ) { return ( x1 <= x ) && ( x <= x2 ) && ( y1 <= y ) && ( y <= y2 ) ; } static magnetDrawingUnder ( magnet , x , y ) { const data = ( < HTMLCanvasElement > document . getElementById ( "canvas" ) ) . getContext ( "2d" ) . getImageData ( x - 16 , y - 16 , 32 , 32 ) ; for ( let i = 0 ; i <= data . data . length - 1 ; i ++ ) if ( data . data [ i ] > 8 ) return true ; return false ; } param param0 returns static getPixel ( { x , y } ) { const data = ( < HTMLCanvasElement > document . getElementById ( "canvas" ) ) . getContext ( "2d" ) . getImageData ( x , y , 1 , 1 ) ; const r = data . data [ 0 ] ; const g = data . data [ 1 ] ; const b = data . data [ 2 ] ; const a = data . data [ 3 ] ; return "rgba(" + [ r , g , b , a ] . join ( "," ) + ")" ; } param point returns static setPixel ( { x , y } , color ) { const ctx = ( < HTMLCanvasElement > document . getElementById ( "canvas" ) ) . getContext ( "2d" ) ; ctx . fillStyle = color ; ctx . globalCompositeOperation = "source-over" ; ctx . globalAlpha = 1.0 ; ctx . fillRect ( x , y , 1 , 1 ) ; } param point description static clearPixel ( { x , y } ) { const ctx = ( < HTMLCanvasElement > document . getElementById ( "canvas" ) ) . getContext ( "2d" ) ; ctx . globalCompositeOperation = "destination-out" ; ctx . fillStyle = `rgba(${ 255 },${ 255 },${ 255 },${ 1 })` ; ctx . fillRect ( x , y , 1 , 1 ) ; } param a returns static isPixel ( { x , y } ) { const data = ( < HTMLCanvasElement > document . getElementById ( "canvas" ) ) . getContext ( "2d" ) . getImageData ( x , y , 1 , 1 ) ; const a = data . data [ 3 ] ; return a > 128 ; } static set nbUpdatePerCycle ( v ) { if ( 1 <= v && v <= 1000 ) Script . nbUpdatePerCycle = v ; else throw "the number of update per cycle should be between 1 and 1000" ; } description static stop ( ) { Script . stop ( ) ; } } description window [ 'S' ] = S ; export class Script { static nbUpdatePerCycle = 1 ; static isRun = false ; static init ( ) { document . getElementById ( "script" ) . onkeydown = ( ) => { } ; document . getElementById ( "buttonScriptRun" ) . onclick = Script . toggle ; } static toggle ( ) { if ( Script . isRun ) { document . getElementById ( "buttonScriptRun" ) . innerHTML = "▷" ; Script . stop ( ) ; } else { document . getElementById ( "buttonScriptRun" ) . innerHTML = "□" ; Script . run ( ) ; } } static run ( ) { Script . isRun = true ; const step = ( ) => { for ( let i = 0 ; i < Script . nbUpdatePerCycle ; i ++ ) S . onupdate ( ) ; if ( Script . isRun ) requestAnimationFrame ( step ) ; } ; eval ( ( < HTMLTextAreaElement > document . getElementById ( "script" ) ) . value ) ; step ( ) ; } static stop ( ) { Script . isRun = false ; S . onkey = ( ) => { } ; S . onmousemove = ( ) => { } ; S . onupdate = ( ) => { } ; S . onmagnetmousedown = ( ) => { } ; S . onmagnetmove = ( ) => { } ; } } window [ 'Script' ] = Script ;