function countUp(a,b,c,d,e,f){for(var g=0,h=["webkit","moz","ms"],i=0;i<h.length&&!window.requestAnimationFrame;++i)window.requestAnimationFrame=window[h[i]+"RequestAnimationFrame"],window.cancelAnimationFrame=window[h[i]+"CancelAnimationFrame"]||window[h[i]+"CancelRequestAnimationFrame"];window.requestAnimationFrame||(window.requestAnimationFrame=function(a){var c=(new Date).getTime(),d=Math.max(0,16-(c-g)),e=window.setTimeout(function(){a(c+d)},d);return g=c+d,e}),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(a){clearTimeout(a)}),this.options=f||{useEasing:!0,useGrouping:!0,separator:",",decimal:"."},""==this.options.separator&&(this.options.useGrouping=!1),null==this.options.prefix&&(this.options.prefix=""),null==this.options.suffix&&(this.options.suffix="");var j=this;this.d="string"==typeof a?document.getElementById(a):a,this.startVal=Number(b),this.endVal=Number(c),this.countDown=this.startVal>this.endVal?!0:!1,this.startTime=null,this.timestamp=null,this.remaining=null,this.frameVal=this.startVal,this.rAF=null,this.decimals=Math.max(0,d||0),this.dec=Math.pow(10,this.decimals),this.duration=1e3*e||2e3,this.version=function(){return"1.2.0"},this.easeOutExpo=function(a,b,c,d){return 1024*c*(-Math.pow(2,-10*a/d)+1)/1023+b},this.count=function(a){null===j.startTime&&(j.startTime=a),j.timestamp=a;var b=a-j.startTime;if(j.remaining=j.duration-b,j.options.useEasing)if(j.countDown){var c=j.easeOutExpo(b,0,j.startVal-j.endVal,j.duration);j.frameVal=j.startVal-c}else j.frameVal=j.easeOutExpo(b,j.startVal,j.endVal-j.startVal,j.duration);else if(j.countDown){var c=(j.startVal-j.endVal)*(b/j.duration);j.frameVal=j.startVal-c}else j.frameVal=j.startVal+(j.endVal-j.startVal)*(b/j.duration);j.frameVal=Math.round(j.frameVal*j.dec)/j.dec,j.frameVal=j.countDown?j.frameVal<j.endVal?j.endVal:j.frameVal:j.frameVal>j.endVal?j.endVal:j.frameVal,j.d.innerHTML=j.formatNumber(j.frameVal.toFixed(j.decimals)),b<j.duration?j.rAF=requestAnimationFrame(j.count):null!=j.callback&&j.callback()},this.start=function(a){return j.callback=a,isNaN(j.endVal)||isNaN(j.startVal)?(console.log("countUp error: startVal or endVal is not a number"),j.d.innerHTML="--"):j.rAF=requestAnimationFrame(j.count),!1},this.stop=function(){cancelAnimationFrame(j.rAF)},this.reset=function(){j.startTime=null,j.startVal=b,cancelAnimationFrame(j.rAF),j.d.innerHTML=j.formatNumber(j.startVal.toFixed(j.decimals))},this.resume=function(){j.startTime=null,j.duration=j.remaining,j.startVal=j.frameVal,requestAnimationFrame(j.count)},this.formatNumber=function(a){a+="";var b,c,d,e;if(b=a.split("."),c=b[0],d=b.length>1?j.options.decimal+b[1]:"",e=/(\d+)(\d{3})/,j.options.useGrouping)for(;e.test(c);)c=c.replace(e,"$1"+j.options.separator+"$2");return j.options.prefix+c+d+j.options.suffix},j.d.innerHTML=j.formatNumber(j.startVal.toFixed(j.decimals))}

jQuery.extend( jQuery.easing,
{
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeOutBounce: function (x, t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	}
});

'use strict';
(function($){
	
if (!Object.keys) {
  Object.keys = function(obj) {
    var keys = [];

    for (var i in obj) {
      if (obj.hasOwnProperty(i)) {
        keys.push(i);
      }
    }
    return keys;
  };
}

var dot2dotUI = function(wrap, options){
	this.options = options;

	this.focusZoom = options.focusZoom;
	this.dotWidth = options.dotWidth;
	this.dotHeight = options.dotHeight;
	this.lineWeight = options.lineWeight;
	this.cursorWeight = options.cursorWeight;
	this.width = options.width;
	this.height = options.height;


	this.$wrap = wrap;
	this.$wrap.css({
		'width': this.width+options.margin*2,
		'height': this.height+options.margin*2
	});
	this.$wrap.closest('.dot2dot').width(this.width+options.margin*2);
	this.$wrapLines = this.$wrap.find('.oio_wrap_lines');
	this.$wrapDots = this.$wrap.find('.oio_wrap_dots');
	this.$cursor = this.$wrap.find('.oio_sel_cursor');
	this.$modal = this.$wrap.closest('.dot2dot').find('.oio_wrap_modal');

	$.fx.interval = 26;

	this.selMode = false;

	this.prepareCursor();


}

dot2dotUI.prototype.renderGrid = function(grid){
	this.$wrapLines.empty();
	this.$wrapDots.empty();

	for (var i = 1; i <= this.sizeY; i++){
		for (var j = 1; j <= this.sizeX; j++){
			

			if(grid[j+'_'+i]){
				this.renderDot(j, i, grid[j+'_'+i]);
			}

		};
	};
};

dot2dotUI.prototype.renderDot = function(x, y, color){
	var $inDot = $('<div/>');
	var self = this;
	$inDot
		.addClass('dot')
		.css({
			'background-color': color,
			'width': this.dotWidth,
			'height': this.dotHeight
		})
	;

	var $dot = $('<div/>');
	$dot
		.addClass('oio_dot dotpos_'+x+'_'+y)
		.height(this.height/this.sizeY)
		.width(this.width/this.sizeX)
		.append($inDot)
		.data({
			'posX': x,
			'posY': y,
			'color': color
		})
		.css({
			'top': (this.height/this.sizeY)*(y-1-this.sizeY),
			'left': (this.width/this.sizeX)*(x-1)+self.options.margin,
			'user-select': 'none'
		})
		.attr('unselectable', 'on')
		.animate({
			'top': (this.height/this.sizeY)*(y-1)+self.options.margin
		}, 900, 'easeOutBounce')
	;

	this.$wrapDots.append($dot);
};

dot2dotUI.prototype.removeDot = function(x, y, noEvent){
	var $dot = this.$wrapDots.find('.dotpos_'+x+'_'+y);
	if($dot.size()){
		$dot.stop().find('.dot').animate({
			'opacity': 0,
			'width': 0,
			'height': 0
		}, 500, 'easeOutQuint', function(){
			$(this).closest('.oio_dot').remove();
		});

		if(!noEvent){
			this.$wrap.trigger('removeDot.oioEvent', [+x, +y, $dot.data('color')]);
		}
	}

};

dot2dotUI.prototype.removeAllDots = function(){
	this.$wrapDots.find('.oio_dot').remove();
};

dot2dotUI.prototype.setCount = function(color, count, maxCount){
	var $dot = this.$wrap.closest('.dot2dot').find('.oio_panel .complete [rel="'+color+'"]');

	if($dot.size() && count <= maxCount){
		
		if('undefined' !== typeof(countUp)){
			if($dot.counter){
				$dot.counter.stop();
			}
		
			$dot.counter = new countUp($dot[0], $dot.text(), (count > 0 ? count : 0), 0, 0.4, {});

			$dot.counter.start(function(){
				if(count == maxCount){
					$dot.closest('.dot_color').find('.dot').html('&#10003;');
				}
			});
			
		}else{
			if(count == maxCount){
				$dot.text(count);
			}else{
				$dot.closest('.dot_color').find('.dot').html('&#10003;');
			}
		}
	}
};

dot2dotUI.prototype.focusSimilarDots = function(x, y){
	var dotColor = this.getColor(x, y);

	for(var i = 1; i <= this.sizeY; i++){
		for (var j = 1; j <= this.sizeX; j++){
			if(this.getColor(i, j) == dotColor){
				this.focusDot(i, j);
			}
		};
	};
};

dot2dotUI.prototype.removeSimilarDots = function(x, y){
	var dotColor = this.getColor(x, y);

	for(var i = 1; i <= this.sizeY; i++){
		for (var j = 1; j <= this.sizeX; j++){
			if(this.getColor(i, j) == dotColor){
				this.removeDot(i, j);
			}
		};
	};
};

dot2dotUI.prototype.moveDot = function(x, y, xNew, yNew){
	var $dot = this.$wrapDots.find('.dotpos_'+x+'_'+y);
	var self = this;
	if($dot.size()){
		$dot
			.addClass('dotpos_'+xNew+'_'+yNew)
			.removeClass('dotpos_'+x+'_'+y)
			.data({
				'posX': xNew,
				'posY': yNew
			})
		;
		$dot.stop().animate({
			'top': (this.height/this.sizeY)*(yNew-1)+self.options.margin,
			'left': (this.width/this.sizeX)*(xNew-1)+self.options.margin
		}, 800, 'easeOutBounce');

		this.$wrap.trigger('moveDot.oioEvent', [+x, +y, +xNew, +yNew]);
	}
};

dot2dotUI.prototype.focusDot = function(x, y){
	var $dot = this.$wrapDots.find('.dotpos_'+x+'_'+y);
	if($dot.size()){
		var focusW = this.dotWidth*this.focusZoom;
		var focusH = this.dotHeight*this.focusZoom;

		$dot.clone().css({
			'width': focusW,
			'height': focusH,
			'top': '-='+(focusH-$dot.height())/2,
			'left': '-='+(focusW-$dot.width())/2
		}).appendTo(this.$wrapLines).stop().find('.dot').css('opacity', 0.8).animate({
			'opacity': 0,
			'width': focusW,
			'height': focusH
		}, 1500, 'easeOutQuint', function(){
			$(this).closest('.oio_dot').remove();
		});
	}
};

dot2dotUI.prototype.getColor = function(x, y){
	var $dot = this.$wrapDots.find('.dotpos_'+x+'_'+y);
	if($dot.size()){
		return $dot.data('color');
	}else{
		return false;
	}
};

dot2dotUI.prototype.renderLine = function(x1, y1, x2, y2){
	x1 = parseInt(x1);
	y1 = parseInt(y1);
	x2 = parseInt(x2);
	y2 = parseInt(y2);

	if(x1 > x2 || y1 > y2){
		var tmpx = x1; x1 = x2; x2 = tmpx;
		var tmpy = y1; y1 = y2; y2 = tmpy;
	}


	if(x1 == x2 && Math.abs(y1 - y2) == 1){
		var posTop = this.$wrapDots.find('.dotpos_'+x2+'_'+y2).position().top;
		var posLeft = this.$wrapDots.find('.dotpos_'+x1+'_'+y1).position().left + (this.$wrapDots.find('.dotpos_'+x1+'_'+y1).width()/2);

	}else if(y1 == y2  && Math.abs(x1 - x2) == 1){
		var posTop = this.$wrapDots.find('.dotpos_'+x1+'_'+y1).position().top + (this.$wrapDots.find('.dotpos_'+x1+'_'+y1).height()/2);
		var posLeft = this.$wrapDots.find('.dotpos_'+x2+'_'+y2).position().left;

	}else{
		return false;
	}

	
	var $line = $('<div/>');
	$line
		.addClass('oio_line')
		.addClass('line_'+x1+'_'+y1+'_'+x2+'_'+y2)
		.css({
			'background-color': this.getColor(x1, y1),
			'top': posTop,
			'left': posLeft
		})
	;

	if(x1 == x2){
		$line
			.css({
				'height': this.$wrapDots.height()/this.sizeY,
				'width': this.lineWeight,
				'margin-top': -(this.$wrapDots.height()/this.sizeY/2),
				'margin-left': -(this.lineWeight/2)
			})
		;
	}else{
		$line
			.css({
				'height': this.lineWeight,
				'width': this.$wrapDots.width()/this.sizeX,
				'margin-top': -(this.lineWeight/2),
				'margin-left': -(this.$wrapDots.width()/this.sizeX/2)
			})
		;
	}

	this.$wrapLines.append($line);
};

dot2dotUI.prototype.removeLine = function(x1, y1, x2, y2){
	x1 = parseInt(x1);
	y1 = parseInt(y1);
	x2 = parseInt(x2);
	y2 = parseInt(y2);

	if(x1 > x2 || y1 > y2){
		var tmpx = x1; x1 = x2; x2 = tmpx;
		var tmpy = y1; y1 = y2; y2 = tmpy;
	}

	var $line = this.$wrapLines.find('.line_'+x1+'_'+y1+'_'+x2+'_'+y2);

	if($line.size()){
		$line.remove();
	}
};

dot2dotUI.prototype.removeAllLines = function(){
	//
	this.$wrapLines.find('.oio_line').remove();
};

dot2dotUI.prototype.prepareCursor = function(){
	this.$cursor[0].width = this.width+this.options.margin*2;
	this.$cursor[0].height = this.height+this.options.margin*2;
	this.ctx = this.$cursor[0].getContext ? this.$cursor[0].getContext('2d') : null;
	if(this.ctx){
		this.ctx.lineWidth = this.cursorWeight;
	}
};

dot2dotUI.prototype.setCursor = function(x, y){
	var $dot = this.$wrapDots.find('.dotpos_'+x+'_'+y);
	if(this.ctx && $dot.size()){
		this.cursorPosLeft = $dot.position().left + ($dot.width()/2);
		this.cursorPosTop = $dot.position().top + ($dot.height()/2);
		this.ctx.strokeStyle = $dot.find('.dot').css('background-color');
		this.clearCursor();
	}
};

dot2dotUI.prototype.drawCursor = function(x, y){
	if(this.ctx){
		this.clearCursor();
		
		this.ctx.beginPath();  
		this.ctx.moveTo(this.cursorPosLeft, this.cursorPosTop);
		this.ctx.lineTo(x, y);
		this.ctx.stroke();
	}
};

dot2dotUI.prototype.clearCursor = function(){
	if(this.ctx){
		this.ctx.clearRect(0, 0, this.width+this.options.margin*2, this.height+this.options.margin*2);
	}
};

dot2dotUI.prototype.setLevel = function(i){
	var self = this;
	this.level = i;
	this.sizeX = this.options.levels[i].cols;
	this.sizeY = this.options.levels[i].rows;
	this.$wrap.closest('.dot2dot').find('.oio_panel .complete').empty();
	$.each(this.options.levels[i].complete, function(color, count){
		self.$wrap.closest('.dot2dot').find('.oio_panel .complete').append('<div class="dot_color"><div style="background:'+color+';" class="dot"></div><div class="dot_count"><span rel="'+color+'">0</span> / '+count+'</div></div>');
	});

	this.$wrap.trigger('changeLevel.oioEvent', i);
};

dot2dotUI.prototype.showDefeatMessage = function(callBack){
	var self = this;
	setTimeout(function(){

		var tpl = [];
		tpl.push('<div class="remodal">');
			tpl.push('<h2>'+self.options.defeatMessage+'</h2>');
			tpl.push('<div class="complete">');
				tpl.push(self.$wrap.closest('.dot2dot').find('.oio_panel .complete').html());
			tpl.push('</div>');
			tpl.push('<a class="remodal-cancel remodal-restart" href="#">Restart</a>');
		tpl.push('</div>');
		self.$modal.html(tpl.join('')).show();

		setTimeout(function(){
			self.$wrap.closest('.dot2dot').addClass('blur');
			self.$modal.css({'opacity': 1});
		}, 10);

		self.$modal.find('.remodal-cancel').click(callBack);

	}, 400);
};

dot2dotUI.prototype.showDoneMessage = function(callBack){
	var self = this;
	
		var tpl = [];
		tpl.push('<div class="remodal">');
			tpl.push('<h2>'+this.options.doneMessage+'</h2>');
			tpl.push('<div class="complete">');
				$.each(self.options.levels[self.level].complete, function(color, count){
					tpl.push('<div class="dot_color"><div style="background:'+color+';" class="dot">&#10003;</div><div class="dot_count">'+count+'</div></div>');
				});
			tpl.push('</div>');
			tpl.push('<a class="remodal-confirm remodal-next" href="#">Następny poziom</a>');
		tpl.push('</div>');
		self.$modal.html(tpl.join('')).show();

		self.$modal.find('.remodal-confirm').click(callBack);

		setTimeout(function(){
			self.$wrap.closest('.dot2dot').addClass('blur');
			self.$modal.css({'opacity': 1});
		}, 10);
	
};

dot2dotUI.prototype.showStartMessage = function(callBack){
	var self = this;

	

		var tpl = [];
		tpl.push('<div class="remodal">');
			tpl.push('<h2>Poziom '+self.level+'</h2>');
			tpl.push('<div class="complete">');
				$.each(self.options.levels[self.level].complete, function(color, count){
					tpl.push('<div class="dot_color"><div style="background:'+color+';" class="dot"></div><div class="dot_count">'+count+'</div></div>');
				});
			tpl.push('</div>');
			tpl.push('<a class="remodal-confirm remodal-close" href="#">Graj</a>');
		tpl.push('</div>');
		self.$modal.html(tpl.join('')).show();

		self.$modal.find('.remodal-close').click(callBack);

		setTimeout(function(){
			self.$wrap.closest('.dot2dot').addClass('blur');
			self.$modal.css({'opacity': 1});
		}, 10);


};



var dot2dotMath = function(options){
	this.opts = options;
};

dot2dotMath.prototype.isValidWay = function(x1, y1, color1, x2, y2, color2){
	x1 = parseInt(x1);
	y1 = parseInt(y1);
	x2 = parseInt(x2);
	y2 = parseInt(y2);

	var valid = true;

	if(
		//тільки сусідні точки
		Math.abs(x1 - x2) > 1
		|| Math.abs(y1 - y2) > 1
		//не по діагоналі
		|| (x1 != x2 && y1 != y2)
		//не та сама точка
		|| (x1 == x2 && y1 == y2)
		//одного кольору
		|| color1 != color2
	){
		valid = false;
	}

	return valid;
};

dot2dotMath.prototype.isQuadrate = function(way){
	var f=0;
	for(var i=0; i<way.length; i++){
		for(var j=0; j<way.length; j++){
			if(way[i]===way[j] && j!=i){
				f++;
			}   
		}
	}

	if(f > 1 && way.length >= 4 && this.opts.magicQuadrate){
		return true;
	}else{
		return false;
	}
};




var methods = {
	init: function(options){
		options = $.extend({
			'width': 400,
			'height': 400,
			'dotWidth': 24,
			'dotHeight': 24,
			'focusZoom': 3,
			'lineWeight': 6,
			'cursorWeight': 6,

			'magicQuadrate': true,

			'margin': 10,

			'levels': {
				'1': {
					'cols': 10,
					'rows': 10,
					'steps': 99,
					'dotsVariats': ['#77c298', '#fecd6c', '#da344d', '#718dbf', '#a4547d'],
					'complete': {}
				}
			},

			'doneMessage': 'Very good :-)',
			'defeatMessage': 'Defeat :-('
		}, options);
		
		return this.each(function(){
			var $this = $(this);
			var data = $this.data('dot2dot');
			
			if(!data){

				$this.addClass('dot2dot').empty();

				var $wrp = $('<div>')
					.addClass('oio_wrap')
					.append('<div class="oio_wrap_lines"></div>')
					.append('<div class="oio_wrap_dots"></div>')
					.append('<canvas class="oio_sel_cursor"></canvas>')
				;

				$this.append('<div class="oio_panel"><div class="steps"></div><div class="complete"></div></div>').append($wrp);
				$this.append('<div class="oio_wrap_modal"></div>');


				var oioUI = new dot2dotUI($wrp, options);
				var oioMath = new dot2dotMath(options);
				
				var dotsRoote = [];
				var steps = 99;
				var statistic = {'all': 0};
				

				$this
					.on('changeLevel.oioEvent', function(newLevel){
						oioUI.removeAllDots();
						
						oioUI.showStartMessage(function(e){
							e.preventDefault();
							
							oioUI.$wrap.removeClass('loading');
							steps = options.levels[oioUI.level].steps;
							$this.find('.steps').html(steps+'<span>kroki</span>');

							statistic = {'all': 0};
							$.each(options.levels[oioUI.level].dotsVariats, function(i, color){
								statistic[color] = 0;
							});
							oioUI.renderGrid(function(){
								var randGrid = {};
								for (var i = 1; i <= oioUI.sizeY; i++){
									for (var j = 1; j <= oioUI.sizeX; j++){
										//randGrid[j+'_'+i] = options.levels[oioUI.level].dotsVariats[Math.floor(Math.random() * options.levels[oioUI.level].dotsVariats.length)];
										if('undefined' != typeof(options.levels[oioUI.level].map[j+'_'+i])){
											randGrid[j+'_'+i] = options.levels[oioUI.level].map[j+'_'+i];
										}else{
											randGrid[j+'_'+i] = options.levels[oioUI.level].dotsVariats[Math.floor(Math.random() * options.levels[oioUI.level].dotsVariats.length)];
										}
									};
								};
								return randGrid;
							}());
						});
					})
					.on('removeDot.oioEvent moveDot.oioEvent', function(e, x, y){
						oioUI.moveDot(x, y-1, x, y);
						if(y == 1){
							oioUI.renderDot(x, y, options.levels[oioUI.level].dotsVariats[Math.floor(Math.random() * options.levels[oioUI.level].dotsVariats.length)]);
						}
					})
					.on('removeDot.oioEvent', function(e, x, y, color){
						statistic[color]++;
						statistic['all']++;

						oioUI.setCount(color, statistic[color], options.levels[oioUI.level].complete[color]);
					})
				;


				$this
					.on('click', '.remodal-close, .remodal-next', function(e){
						e.preventDefault();

						oioUI.$wrap.closest('.dot2dot').removeClass('blur');
						oioUI.$modal.css({'opacity': 0});
						setTimeout(function(){
							oioUI.$modal.hide();
						}, 300);
					})

					.on('selectstart', '.oio_dot', false)
					.on('selectstart', false)
					.on('mousemove.oioEvent touchmove', function(e){
						if(oioUI.selMode){

							var px = e.pageX-oioUI.$cursor.offset().left;
							var py = e.pageY-oioUI.$cursor.offset().top;

							oioUI.drawCursor(px, py);
						}
					})

					.on('touchmove.oioEvent', function(e){
						e.preventDefault();
						if(oioUI.selMode){
							if(e.originalEvent.targetTouches.length == 1){
							    var touch = e.originalEvent.targetTouches[0];

							    var px = touch.pageX-oioUI.$cursor.offset().left;
								var py = touch.pageY-oioUI.$cursor.offset().top;
								oioUI.drawCursor(px, py);

								var fdotx = Math.ceil((px-oioUI.options.margin)/oioUI.$wrapDots.find('.dotpos_1_1').width());
								var fdoty = Math.ceil((py-oioUI.options.margin)/oioUI.$wrapDots.find('.dotpos_1_1').height());

								if($this.lastDot != fdotx+'_'+fdoty){
									$this.lastDot = fdotx+'_'+fdoty;
									oioUI.$wrapDots.find('.dotpos_'+fdotx+'_'+fdoty).trigger('mouseenter.oioEvent');
								}
							}
						}
					})

					.on('mousedown.oioEvent touchstart.oioEvent', '.oio_dot', function(e){
						oioUI.selMode = true;
						$(this).trigger('mouseenter.oioEvent');
					})
					.on('mouseup.oioEvent mouseleave.oioEvent touchend.oioEvent', function(){
						oioUI.selMode = false;
						oioUI.clearCursor();
						oioUI.removeAllLines();

						if(dotsRoote.length > 1){
							if(oioMath.isQuadrate(dotsRoote)){
								oioUI.removeSimilarDots(dotsRoote[0].split('_')[0], dotsRoote[0].split('_')[1]);
							}else{
								$.each(dotsRoote, function(i, pos){
									oioUI.removeDot(pos.split('_')[0], pos.split('_')[1]);
								});
							}

							steps--;
							$this.find('.steps').html(steps+'<span>kroki</span>');



							if(function(stat, step){
								var truecount = 0;

								$.each(options.levels[oioUI.level].complete, function(color, count){
									if(stat[color] >= count){
										truecount++;
									}
								});

								return (Object.keys(options.levels[oioUI.level].complete).length == truecount);
							}(statistic, steps)){
								
								oioUI.showDoneMessage(function(e){
									e.preventDefault();
									if('undefined' != typeof(oioUI.options.levels[oioUI.level+1])){
										oioUI.setLevel(oioUI.level+1);
									}else{
										oioUI.setLevel(1);
									}
								});
								$this.trigger('victory', [statistic, steps]);
							}else if(steps <= 0){
								
								oioUI.showDefeatMessage(function(e){
									e.preventDefault();
									oioUI.setLevel(oioUI.level);
								});
								$this.trigger('defeat', [statistic, steps]);
							}
						}

						dotsRoote.splice(0, dotsRoote.length);
					})
					.on('mouseenter.oioEvent', '.oio_dot', function(){
						if(oioUI.selMode){
							if(0 == dotsRoote.length){
								
								dotsRoote.push($(this).data('posX') + '_' + $(this).data('posY'));

								var curr = dotsRoote[dotsRoote.length-1].split('_');

								oioUI.setCursor(curr[0], curr[1]);
								oioUI.focusDot(curr[0], curr[1]);
							}else if(1 == dotsRoote.length){
								
								dotsRoote.push($(this).data('posX') + '_' + $(this).data('posY'));

								var prev = dotsRoote[dotsRoote.length-2].split('_');
								var curr = dotsRoote[dotsRoote.length-1].split('_');

								if(!oioMath.isValidWay(curr[0], curr[1], oioUI.getColor(curr[0], curr[1]), prev[0], prev[1], oioUI.getColor(prev[0], prev[1]))){
									dotsRoote.pop();
									return false;
								}

								oioUI.setCursor(curr[0], curr[1]);
								oioUI.focusDot(curr[0], curr[1]);
								
								oioUI.renderLine(curr[0], curr[1], prev[0], prev[1]);
							}else if(dotsRoote.length > 1){
								
								dotsRoote.push($(this).data('posX') + '_' + $(this).data('posY'));
								
								var prev = dotsRoote[dotsRoote.length-2].split('_');
								var curr = dotsRoote[dotsRoote.length-1].split('_');

								if(!oioMath.isValidWay(curr[0], curr[1], oioUI.getColor(curr[0], curr[1]), prev[0], prev[1], oioUI.getColor(prev[0], prev[1]))){
									dotsRoote.pop();
									return false;
								}

								var beforePrev = dotsRoote[dotsRoote.length-3].split('_');

								if(dotsRoote[dotsRoote.length-1] == dotsRoote[dotsRoote.length-3]){
									oioUI.removeLine(curr[0], curr[1], prev[0], prev[1]);
									oioUI.setCursor(beforePrev[0], beforePrev[1]);

									dotsRoote.pop();
									dotsRoote.pop();
									
								}else{
									oioUI.renderLine(curr[0], curr[1], prev[0], prev[1]);
									oioUI.setCursor(curr[0], curr[1]);

									if(oioMath.isQuadrate(dotsRoote)){
										oioUI.focusSimilarDots(curr[0], curr[1]);
									}else{
										oioUI.focusDot(curr[0], curr[1]);
									}

								}
							}
						}
					})
				;

				oioUI.setLevel(1);

				$this.data('dot2dot', {
					d2dUI: oioUI,
					d2dMath: oioMath
				});
			}
		});
	},
	destroy: function(){
		return this.each(function(){
			$(this)
				.empty()
				.removeData('dot2dot')
				.off('.oioEvent')
			;
		});
	}
};

$.fn.dot2dot = function(method){
	if(methods[method]){
		return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
	}else if(typeof method === 'object' || ! method){
		return methods.init.apply(this, arguments);
	}else{
		$.error('Method “'+ method+'” not found in dot2dot game.');
	}    
};

})(jQuery);