let my={}
function init(){let version='0.82'
let w=520
let h=240
let s=''
s+=''
s+='
Drag the numerals to the blue boxes
'
s+=wrap({cls:'copyrt',pos:'abs',style:'left:5px; bottom:3px'},`© 2022 Rod Pierce v${version}`)
s=wrap({cls:'js',style:'width:'+w+'px; height:'+my.ht+'px;'},s)
docInsert(s)
my.can=new Can('canvasId',w,h,2)
my.drag={n:0,onq:false,holdX:0,holdY:0}
my.shapes=[]
my.startX=10
my.cellWidth=40
my.spacing=10
my.drag.onQ=false
this.numbers=[0,1,2,3,4,5,6,7,8,9]
my.dests=[[70,100,60,40,0],[210,100,60,40,0],]
my.eqs=['1','+','2','=','3']
this.ball={size:10,color:'white',lightColor:'yellow',darkColor:'blue',position:{x:160,y:120}}
newGame()
let el=my.can.el
el.addEventListener('mousedown',mouseDownListener,false)
el.addEventListener('touchstart',ontouchstart,false)
el.addEventListener('mousemove',dopointer,false)}
function newGame(){makeShapes()
drawShapes()}
function ontouchstart(ev){let touch=ev.targetTouches[0]
ev.clientX=touch.clientX
ev.clientY=touch.clientY
ev.touchQ=true
mouseDownListener(ev)}
function ontouchmove(ev){let touch=ev.targetTouches[0]
ev.clientX=touch.clientX
ev.clientY=touch.clientY
ev.touchQ=true
mouseMoveListener(ev)
ev.preventDefault()}
function ontouchend(ev){my.can.el.addEventListener('touchstart',ontouchstart,false)
window.removeEventListener('touchend',ontouchend,false)
let[mouseX,mouseY]=my.can.mousePos(ev)
drop(mouseX,mouseY)
if(my.drag.onQ){my.drag.onQ=false
window.removeEventListener('touchmove',ontouchmove,false)}}
function dopointer(ev){let[mouseX,mouseY]=my.can.mousePos(ev)
let inQ=false
for(let i=0;ihighestIndex){my.drag.holdX=mouseX-my.shapes[i].x
my.drag.holdY=mouseY-my.shapes[i].y
highestIndex=i
my.drag.n=i}}}
if(my.drag.onQ){if(ev.touchQ){window.addEventListener('touchmove',ontouchmove,false)}else{window.addEventListener('mousemove',mouseMoveListener,false)}}
if(ev.touchQ){my.can.el.removeEventListener('touchstart',ontouchstart,false)
window.addEventListener('touchend',ontouchend,false)}else{my.can.el.removeEventListener('mousedown',mouseDownListener,false)
window.addEventListener('mouseup',mouseUpListener,false)}
if(ev.preventDefault){ev.preventDefault()}
else if(ev.returnValue){ev.returnValue=false}
return false}
function mouseUpListener(ev){my.can.el.addEventListener('mousedown',mouseDownListener,false)
window.removeEventListener('mouseup',mouseUpListener,false)
let[mouseX,mouseY]=my.can.mousePos(ev)
drop(mouseX,mouseY)
if(my.drag.onQ){my.drag.onQ=false
window.removeEventListener('mousemove',mouseMoveListener,false)}}
function mouseMoveListener(ev){if(my.drag.n<0)return
let[mouseX,mouseY]=my.can.mousePos(ev)
let minX=0
let maxX=my.can.el.width-my.shapes[my.drag.n].wd
let posX=mouseX-my.drag.holdX
posX=posXmaxX?maxX:posX
let posY=mouseY-my.drag.holdY
my.shapes[my.drag.n].x=posX
my.shapes[my.drag.n].y=posY
for(let i=0;i>0)+(my.eqs[2]>>0)
makeShapes()
drawShapes()}
function isIn(x,y,lt,tp,wd,ht){if(xlt+wd)return false
if(ytp+ht)return false
return true}
function hitTest(shape,mx,my){if(mxshape.x+shape.wd)return false
if(my>shape.y+shape.ht)return false
return true}
function makeShapes(){my.shapes=[]
for(let i=0;i100){xp-=110
yp+=22}}}
CanvasRenderingContext2D.prototype.ball=function(ball,x,y){let size=ball.size
this.beginPath()
this.fillStyle=ball.color
this.arc(x,y,size,0,Math.PI*2,true)
let gradient=this.createRadialGradient(x-size/2,y-size/2,0,x,y,size)
gradient.addColorStop(0,ball.color)
gradient.addColorStop(1,ball.darkColor)
this.fillStyle=gradient
this.fill()
this.closePath()
this.beginPath()
this.arc(x,y,size*0.85,(Math.PI/180)*270,(Math.PI/180)*200,true)
gradient=this.createRadialGradient(x-size*0.5,y-size*0.5,0,x,y,size)
gradient.addColorStop(0,ball.lightColor)
gradient.addColorStop(0.5,'transparent')
this.fillStyle=gradient
this.fill()}
function docInsert(s){let div=document.createElement('div')
div.innerHTML=s
let script=document.currentScript
script.parentElement.insertBefore(div,script)}
class Can{constructor(id,wd,ht,ratio){this.id=id
this.wd=wd
this.ht=ht
this.ratio=ratio
let el=document.getElementById(id)
el.width=wd*ratio
el.style.width=wd+'px'
el.height=ht*ratio
el.style.height=ht+'px'
this.g=el.getContext('2d')
this.g.setTransform(ratio,0,0,ratio,0,0)
this.el=el
return this}
clear(){this.g.clearRect(0,0,this.wd,this.ht)}
mousePos(ev){let bRect=this.el.getBoundingClientRect()
let mouseX=(ev.clientX-bRect.left)*(this.el.width/this.ratio/bRect.width)
let mouseY=(ev.clientY-bRect.top)*(this.el.height/this.ratio/bRect.height)
return[mouseX,mouseY]}}
function wrap({id='',cls='',pos='rel',style='',txt='',tag='div',lbl='',fn='',opts=[]},...mores){let s=''
s+='\n'
txt+=mores.join('')
s+={btn:()=>{if(cls.length==0)cls='btn'
return '