<!DOCTYPE html>
<html>
<head>

	<meta charset="UTF-8">
	<title>RetroPython</title>
<!--     // <script src="http://apps.bdimg.com/libs/jquery/2.0.0/jquery.min.js"></script>
    // <script type="text/javascript" src="http://cdn.bootcss.com/socket.io/1.4.8/socket.io.min.js"></script> -->
	<!-- // <script src="js/jquery.min.js"></script> -->
	<script src="./static/socket.io.min.js"></script>
	<script src="./static/jquery.min.js"></script>
	<style>

	</style>

	<script>
var isPi = 0

var prot = 80

function deepCopy(p, c) {
	var c = c || {};
	for (var i in p) {
		if (typeof p[i] === 'object') {
			c[i] = (p[i].constructor === Array) ? [] : {};
			deepCopy(p[i], c[i]);
		} else {
			c[i] = p[i];
		}
	}
	return c;
}


int = parseInt
float = parseFloat
log = console.log
debug = console.debug
info = console.info
table = console.table
len=(x)=>x.length
rn = (x)=> int(x*Math.random())
function range (f,n,max) {
	// 1.Python 用法 
	// 2.执行 f(n['property']) 并返回新的 [] 或 {}
	// range(10) =>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
	// range(x=>x*2,5,10) =>[10, 12, 14, 16, 18]
	// range(x=>x+x,['a', 'b', 'c']) 
	// =>["aa", "bb", "cc"]

	var flag = (typeof f == "number")

	if(flag){
		max =(typeof n == "number")?n:max
		n = f
		f = x=>x
	}
	var items = n
	var obj = (n.constructor === Array)?[]:{}
	if(typeof n == "number"){
		obj = []
		items = []
		var i=max?n:0
		max=max||n
		while(i!=max){items.push(i);i++}
	}
 	
 	for (var i in items) {
 		obj[i]=f(items[i])
 	}
 	return obj
 } 

sum = (arr)=>{
        var summ = 0
        for (var i in arr){
                summ += arr[i]
        }
        return summ
}
var cmp = (x,y)=>{
			return (x[0]==y[0])&&(x[1]==y[1])
}

function refresh (argument) {
	if(window.engineId == null&&p2[2]){
	    	window.history.go(0)
	    }
}



var ad ='http://' + document.domain + ':'+prot+'/game'
log(ad)
var socket = io.connect(ad);
socket.on('p2_to_p1', function(p2) {
    window.player2 = p2
    window.refresh()

})
socket.on('p1_to_pc', function(p1) {
    window.player1 = p1
    window.refresh()

})

socket.on('response', function(msg) {
    log('response:' + msg.data);

})
socket.on('testLine', function(msg) {
    log('testLine:' + msg.data);

})
socket.emit('testLine',{data:'p1 successed to pi!'})
	
</script>
</head>

<body>


	<canvas id="canvas" width="500" height="400" style="border: 1px solid gray;position:fixed;top:0px;left:0px;">

	</canvas>

</body>

<script>
$('#canvas').attr('width',document.documentElement.clientWidth)
$('#canvas').attr('height',document.documentElement.clientHeight)
var ctx = document.getElementById('canvas').getContext('2d');




var map = {
	// 游戏地图
	'width':20,
	'height':20,
	'defaultLen':8,
	'hardStone':[],
	'pythons':[],
	'playerNum':1,
	'apple':[],

	'isEatAppple':function  (head) {
		var tag = cmp(head,this.apple)
		if (tag==true){
			this.apple = [-1,-1]
		}
		return tag
	},
	'creatApple':function() {
		var x = rn(this.width)
		var y = rn(this.height)
		var count = 0
		var arr = [...this.pythons[0].body,...this.pythons[1].body]
		while(1){
			var summ = sum(arr.map(function(pos) {
				return cmp([x,y],pos)
			}))
			if(summ==0){
				break
			}

			if (count%this.width==0){
				y =(y+1)%this.height
			}
			x =(x+1)%this.width
			count += 1
		}
		this.apple=[x,y]

	},
	'render':()=>{canvas.render()},
	'init':function(n) {
		// 初始化 n 为 人数 但 1人模式已经废了
		if(n==1){
			var python = new creatPython()
			python.body=this.getPythonBody()
			this.pythons=[python]
		}
		if(n==2){
			this.playerNum = 2
			this.pythons[0] = new creatPython()
			this.pythons[0].body = this.getPythonBody()

			this.pythons[1] = new creatPython()
			this.pythons[1].body = this.getPythonBody()
			this.creatApple()
		}
	},
	
	'getPythonBody':()=>{
		// 初始化时的py
		return range(map.defaultLen).map(
			(pos) => {	
				var width = map.width
				var height=map.height

				var x,y
				x = int(width/2) 

				if(map.playerNum==2){
					x = (len(map.pythons)==1)?int(width/4):int(width*3/4)
				}
			
				y = height - pos-1

				return [x,y]
			}
		)},
	'getBuffer':function  () {
		// 返回 二维数组 包含每个像素点的值
		function fillBuffer (buffer,arr,vlue) {
			vlue=vlue?vlue:1
			arr.map((x)=>{
				buffer[x[1]][x[0]]=vlue
			})
		}

		buffer=range(this.height).map(()=>range(this.width).map(()=>0))

		fillBuffer(buffer,this.hardStone)
		var apple = this.apple
		buffer[apple[1]][apple[0]]=3
		if(typeof this.pythons[0] == 'object'){
			for (var i in this.pythons){
					fillBuffer(buffer,this.pythons[i].body,int(i)+1)
				}
		}
		return buffer

	},
	code:function() {
		// 对 buffer 转换为 max7219.device._buffer 以减少数据传输和处理
		var buffer = this.getBuffer()

		return range(map.width).map(function(w){
		    return sum(
		    	range(map.height).map(
		    		function(h){

		        	return (buffer[h][w]?1:0)*(2**h)
		    	})
		    	)
		})

	},
	win:function  (p) {
		// 游戏结束后的处理 p 为 0:和局, 1:player1赢, 2:player2赢,
		var r = [
		"<br><br><h1>Die together!,no winer! </h1><br><h2>平局,同归于尽!</h2>",
		"<br><br><h1>player "+p+" win!</h1><br><h2>恭喜恭喜 player "+p+"!</h2>",
		"<br><br><h1>player "+p+" win!</h1><br><h2>恭喜恭喜 player "+p+"!</h2>"]

		$('body').html(r[p]+'<br><br>点击屏幕或按空格键继续!')			
		

		socket.emit('end',p)
		clearInterval(window.engineId)
		window.engineId = null


	},
	isDie:function () {
		// 判断是否死亡
		var map = window.map
		var pys = map.pythons
		

		var arr = [...pys[0].body.slice(0,-1),...pys[1].body.slice(0,-1)]
		
		
		var head = [0,0] // 存储两条蛇的头
		var tag = [0,0] // 存放是否相撞
		for (var i in pys){
			head[i] = pys[i].body[pys[i].body.length-1]
			// 判断是否和非头的body相撞
			tag[i]=sum(arr.map(function(pos) {
				return cmp(head[i],pos)
			}))
		}

		// 若两头相等 则平局
		if(cmp(head[0],head[1])){map.win(0) ;return}

		if(tag[0]!=0||tag[1]!=0){
			// 判断输赢
			if(tag[0]!=0&&tag[1]!=0){map.win(0) ;return}
					
			if(tag[0]!=0){map.win(2) ;return}
			
			if(tag[1]!=0){map.win(1) ;return}
		}
		if(cmp(map.apple,[-1,-1])){
			// 若apple 被吃了 最后来创造新的
			map.creatApple()
		}	
	}
}


function creatPython () {
	return {
		// 生成 Python 实例
		'body':[], // 蛇本身 body[-1] 为头的坐标
		'button':'u', // 玩家按钮 ['u','r','d','l']
		'direct':'u', //现在的朝向 ['u','r','d','l']
		'turn':'f', // ['f','r','b','l']
		'speed':1,
		directArr:['u','r','d','l'],
		turnDic:{'f':0,'r':1,'b':2,'l':3},
		getNewHead:function(head,d,tag) {
			// 获得下一步 当前头 direct 
			// tag 判断是否可以夸边界(未用)
			var newHead
			if(d=='u'){newHead = [head[0],head[1]-1]}
			if(d=='r'){newHead = [head[0]+1,head[1]]}
			if(d=='d'){newHead = [head[0],head[1]+1]}
			if(d=='l'){newHead = [head[0]-1,head[1]]}
			if(tag){
				return newHead
			}
			return [(newHead[0]+map.width)%map.width,(newHead[1]+map.height)%map.height]
		},
		time:3, // 记录未加速状态下的循环次数
		move:function () {
			if (this.speed == 0){
			// 判断并处理未加速状态下的 记录
				if (this.time<3){
					this.time+=1
					return
				}else{
					this.time=0
				}
			}else{
				this.time=0
			}
			
			var arr = this.directArr
			var d = this.direct
			// 若方向与与当前方向相反 方向不变
			if (this.button==arr[(arr.indexOf(d)+2)%4]){
				this.button = d
			}
			
			var s = this.speed
			var body = this.body
			var head = body[len(body)-1]
			this.direct = this.button

			var newHead = this.getNewHead(head,this.button)
			// 若没吃到apple 削去 尾巴
			if(map.isEatAppple(newHead)==0){
				this.body=this.body.slice(1)
			}
			
			this.body.push(newHead)
			// info(newDirect,head,newHead)

			// log(this.body,newHead)
			

		},
		moveByTurn:function () {
			// 已经不用了 采用左转右转方式移动

			var d = this.direct
			var t = this.turn

			var body = this.body
			var head = body[len(body)-1]
			var newDirect = this.directArr[(this.directArr.indexOf(d)+this.turnDic[t])%4]
			this.direct = newDirect
			var newHead = this.getNewHead(head,newDirect)
			// 各种判断
			this.body=this.body.slice(1)
			this.body.push(newHead)
			// info(newDirect,head,newHead)

			// log(this.body,newHead)
			canvas.render()

		},
	}
}


canvasDiv = 'canvas'
var canvas = {
	// 用于canvas 渲染
	buffer:[],
	width:document.getElementById(canvasDiv).width,
	height:document.getElementById(canvasDiv).height,
	mapW:map.width,
	mapH:map.height,
	lineColor:'rgba(0,0,0,0.1)',
	blockColor:'rgba(0,0,0,0.4)', // 可以不用了
	bgColor:'rgba(0,0,0,0.1)',
	py1Color:'blue',
	py2Color:'gray',
	appleColor:'red',
	size:function(){
		// 返回单个方块的最佳大小
		var w=this.width/this.mapW
		var h=this.height/this.mapH
		return (w<h)?w:h
	},
	drewSquare:function(x,y,size,color) {
		// 画方块
		color=color||this.bgColor
		ctx.save()
		ctx.fillStyle=color
		ctx.strokeStyle=this.lineColor
		ctx.translate(x,y)
		ctx.beginPath()
		ctx.moveTo(0,0)
		ctx.lineTo(size,0)
		ctx.lineTo(size,size)
		ctx.lineTo(0,size)
		ctx.lineTo(0,0)
		ctx.fill()
		ctx.stroke()
		ctx.restore()
		// log(x,y)
	},
	render:function() {
		ctx.clearRect(0,0,this.width,this.height);
		var size = this.size()
		// x, y 为偏移量
		var x=(this.width - this.mapW*size)/2
		var y=(this.height - this.mapH*size)/2

		var color
		var buffer = map.getBuffer()
		// 画Squares
		for(var i in range(this.mapH)){

			for(var j in range(this.mapW)){
				
				color=[
					this.bgColor,
					this.py1Color,
					this.py2Color,
					this.appleColor
				][
					buffer[i][j]
				]
				this.drewSquare(j*size+x,i*size+y,size,color)
				
			}
		}

	},

}


// 控制数据存放 接口变量
var player1 = [0,0,0]
var player2 = [0,0,0]



function showXY () {
	// 在屏幕上显示控制数据
	if (window.isPi != 1){return}
	$('#x').html(window.player1[1])
	$('#y').html(window.player1[0])
	$('#z').html(window.player1[2]?true:false)
}

window.addEventListener('touchstart',function(e){
	window.player1[2] = 1
	window.showXY()
})
window.addEventListener('touchend',function(e){

	window.player1[2] = 0
	window.showXY()
    window.refresh()

})

$(document).keydown(function(event){
   
	if([38,39,40,37,32].indexOf(event.keyCode)!=-1){
		
		event.preventDefault()
		if(event.keyCode==38){window.player1[1]= 1}
		if(event.keyCode==39){window.player1[0]= 1}
		if(event.keyCode==40){window.player1[1]=-1}
		if(event.keyCode==37){window.player1[0]=-1}
		if(event.keyCode==32){window.player1[2]= 1}
		window.showXY()
	}
});
$(document).keyup(function(event){

	if([38,39,40,37,32].indexOf(event.keyCode)!=-1){
		
		event.preventDefault()
		if(event.keyCode==38){window.player1[1]= 0}
		if(event.keyCode==39){window.player1[0]= 0}
		if(event.keyCode==40){window.player1[1]= 0}
		if(event.keyCode==37){window.player1[0]= 0}
		if(event.keyCode==32){window.player1[2]= 0;
		    window.refresh()
		}
		window.showXY()
	}
});

var dealControl=(x)=>{
	// 转换原始角度数据
		if(x>20){return 1}
		if(x<-20){return -1}
		return 0
	}


function orientationHandler(event) {

	var control=[
		dealControl(event.beta),
		dealControl(event.gamma),
	]


	var changeTag = 0
	if(control[0]!=window.player1[0]){
		window.player1[0]=control[0]
		changeTag = 1
	}
	if(control[1]!=window.player1[1]){
		window.player1[1]=control[1]
		changeTag = 1
	}
	if(changeTag==1){
		window.showXY()
	}
}


if (window.DeviceOrientationEvent) {
    window.addEventListener("deviceorientation", orientationHandler, true);
} else {
    document.body.innerHTML = "Can't found window.DeviceOrientationEvent, Maybe need one of them: \n1) using 127.0.0.1 url  \n2)using fire fox \n3) hosted over https.";
}




function controlToButton(control,py){
	// 将控制接口用于 python.button
	py=py||0
	if(control[2]== 1){py.speed=1}
	if(control[2]== 0){py.speed=0}	
	if(control[0]== 1){py.button='r';return}
	if(control[0]==-1){py.button='l';return}
	if(control[1]== 1){py.button='u';return}
	if(control[1]==-1){py.button='d';return}
}

map.init(2)
// table(map.getBuffer() )
// py = map.pythons[0]
canvas.render()

var engine = ()=>{
	// 每一帧的处理
	// 1. 将控制接口应用于python.button
	controlToButton(window.player1,map.pythons[0])
	// 2. 处理运行后的
	map.pythons[0].move()
	if(map.playerNum==2){
		controlToButton(window.player2,map.pythons[1])
		map.pythons[1].move()
	}

	// socket.emit('buffer', map.code())
	window.map.isDie()
	canvas.render()
}

var enginePi = ()=>{
	controlToButton(window.player1,map.pythons[0])
	map.pythons[0].move()
	if(map.playerNum==2){
		controlToButton(window.player2,map.pythons[1])
		map.pythons[1].move()
	}	
	window.map.isDie()
	socket.emit('buffer', map.code())
}

if(isPi==1){
	engine=enginePi
	var body ='\
	<p>前后倾角:<span id="x">0</span></p>\
	<p>左右倾角:<span id="y">0</span></p>\
	<p>是否加速:<span id="z">0</span></p>\
<div id="show"></div>\
<div id="null" style="width:100%;position:fixed;top:0px;left:0px;height:100%;z-index=2" ></div>'
	$('body').html(body)
	}
var engineId = setInterval(engine,100)




</script>

</html>