/*
* 2016 Maciej Wiecierzewski
*/
/**
* @constructor
* @classdesc Widget for displaying expression and manipulating the order of symbols
*/
function ExpressionWidget(images)
{
this.images = images;
this.symbolsImg = [];
this.tiles = [];
this.checkedTile = 0;
this.maxX = 0;
this.drawn = false;
this.tileColor = "#fff";
this.correctAnsColor = "#6f0";
this.wrongAnsColor = "#e20";
this.container = new createjs.Container();
var backgroundMousedown = function(event)
{
this.xPos = event.stageX;
this.prevX = this.container.x;
}.bind(this);
var backgroundPressmove = function(event)
{
var x = event.stageX-this.xPos;
this.container.x = this.prevX+x;
}.bind(this);
var backgroundPressup = function(event)
{
if(this.container.x > 0) this.container.x = 0
if(this.container.x < this.maxX) this.container.x = this.maxX;
}.bind(this);
this.background = new createjs.Shape();
this.background.addEventListener("mousedown", backgroundMousedown);
this.background.addEventListener("pressmove", backgroundPressmove);
this.background.addEventListener("pressup", backgroundPressup);
this.container.addChild(this.background);
}
/**
* Creates tile's 'Shape' object
* @param {type} img
* @param {type} color
* @returns {ExpressionWidget.createTileShape.shape|createjs.Shape}
*/
ExpressionWidget.createTileShape = function(img, color)
{
var graphics = new createjs.Graphics();
graphics.beginFill(color);
graphics.drawRect(0, 0, 100, 100);
graphics.endFill();
graphics.beginBitmapFill(img, undefined, new createjs.Matrix2D(0.6, 0, 0, 0.6));
graphics.drawRect(0, 0, 100, 100);
var shape = new createjs.Shape(graphics);
shape.setBounds(0, 0, 60, 60);
return shape;
}
/**
* Returns current state of order of symbols
* @returns {Array|ExpressionWidget.prototype.getSolution.array}
*/
ExpressionWidget.prototype.getSolution = function()
{
var array = [];
for(var i = 0; i < this.tiles.length; i++)
{
array.push(this.tiles[i].order);
}
return array;
}
/**
* Sets new expression
* @param {Array} expression Expression to be drawn
* @returns {undefined}
*/
ExpressionWidget.prototype.draw = function(expression)
{
this.container.removeAllChildren();
this.container.addChild(this.background);
this.checkedTile = 0;
this.tiles = [];
// Creating tiles
for(var i = 0; i < expression.string.length; i++)
{
// Building the spriteSheet
var symbol = expression.string.charAt(i);
var builder = new createjs.SpriteSheetBuilder();
var tileFrame = ExpressionWidget.createTileShape(this.symbolsImg[symbol], this.tileColor);
var correctAnsFrame = ExpressionWidget.createTileShape(this.symbolsImg[symbol], this.correctAnsColor);
var wrongAnsFrame = ExpressionWidget.createTileShape(this.symbolsImg[symbol], this.wrongAnsColor);
builder.addFrame(tileFrame);
builder.addFrame(correctAnsFrame);
builder.addFrame(wrongAnsFrame);
var spriteSheet = builder.build();
// tile's sprite
var tile = new createjs.Sprite(spriteSheet);
tile.id = 's'+i;
this.container.addChild(tile);
var tileMousedown = function(event)
{
this.yPos = event.stageY
this.timeStamp = event.timeStamp;
var id = parseInt(event.target.id.substring(1));
this.checkTile(id);
Dialog.actions['showDescription'](id);
}.bind(this);
// Tile's event listeners
var tilePressmove = function(event)
{
var y = event.stageY-this.yPos;
this.moveTile(y);
}.bind(this);
var tilePressup = function(event)
{
var y = event.stageY-this.yPos;
var hold = (event.timeStamp - this.timeStamp) > 300;
if(y > 30)
this.tileDown(hold);
else if(y < -30)
this.tileUp(hold);
this.putBackTile();
}.bind(this);
tile.addEventListener("mousedown", tileMousedown);
tile.addEventListener("pressmove", tilePressmove);
tile.addEventListener("pressup", tilePressup);
// Tile's text
var text = new createjs.Text("0", "26px Arial", "#000");
this.container.addChild(text);
// The tile object
this.tiles[i] = { tileObj: tile, text: text, symbol: symbol, order: 0, correctOrder: null };
}
// Creates up arrow
{
// Event listeners
var arrowMousedown = function(event)
{
this.timeStamp = event.timeStamp;
}.bind(this);
var arrowPressup = function(event)
{
var hold = (event.timeStamp - this.timeStamp) > 400;
this.tileUp(hold);
}.bind(this);
// 'Graphics' object
var graphics = new createjs.Graphics();
graphics.beginBitmapFill(this.images['uparrow']);
graphics.drawRect(0, 0, 100, 60);
// Creating the object
this.uparrow = new createjs.Shape(graphics);
var hitArea = new createjs.Shape();
hitArea.graphics.beginFill("#000").drawRect(0, 0, 100, 60);
this.uparrow.hitArea = hitArea;
this.uparrow.scaleX = 0.6;
this.uparrow.scaleY = 0.6;
this.uparrow.addEventListener('mousedown', arrowMousedown);
this.uparrow.addEventListener('pressup', arrowPressup);
// Appending to the container
this.container.addChild(this.uparrow);
}
// Creates down arrow
{
// Event listeners
var arrowMousedown = function(event)
{
this.timeStamp = event.timeStamp;
}.bind(this);
var arrowPressup = function(event)
{
var hold = (event.timeStamp - this.timeStamp) > 400;
this.tileDown(hold);
}.bind(this);
// 'Graphics' object
var graphics = new createjs.Graphics();
graphics.beginBitmapFill(this.images['downarrow']);
graphics.drawRect(0, 0, 100, 60);
// Creating the object
this.downarrow = new createjs.Shape(graphics);
var hitArea = new createjs.Shape();
hitArea.graphics.beginFill("#000").drawRect(0, 0, 100, 60);
this.downarrow.hitArea = hitArea;
this.downarrow.scaleX = 0.6;
this.downarrow.scaleY = 0.6;
this.downarrow.addEventListener('mousedown', arrowMousedown);
this.downarrow.addEventListener('pressup', arrowPressup);
// Appending to the container
this.container.addChild(this.downarrow);
}
this.drawn = true;
}
ExpressionWidget.prototype.setCheckResult = function(result)
{
for(var i = 0; i < result.length; i++)
{
if(result[i] === 1)
{
this.tiles[i].correctOrder = this.tiles[i].order;
this.tiles[i].wrongOrder = null;
}
else if(result[i] === 2)
{
this.tiles[i].correctOrder = null;
this.tiles[i].wrongOrder = this.tiles[i].order;
}
else
{
this.tiles[i].correctOrder = null;
this.tiles[i].wrongOrder = null
}
}
this.updateTilesState();
}
/**
* Resizes the widget
* @param {number} x
* @param {number} y
* @param {number} w
* @param {number} h
*/
ExpressionWidget.prototype.resize = function(x, y, w, h)
{
this.container.x = x;
this.container.y = y;
this.maxX = Math.min(w-(this.tiles.length*65+50), 0);
this.background.graphics.clear();
this.background.graphics.beginFill('#eee').drawRect(0, 0, this.tiles.length*65+50, h);
if(!this.drawn)
return;
this.shapeY = 0.5*h;
for(var i = 0; i < this.tiles.length; i++)
{
var tile = this.tiles[i].tileObj;
var text = this.tiles[i].text;
tile.x = 10+65*i;
tile.y = this.shapeY;
text.x = 35+65*i;
text.y = this.shapeY-80;
}
this.uparrow.y = this.shapeY-40;
this.downarrow.y = this.shapeY+65;
this.showArrows();
}
/**
* Sets tile to be checked
* @param {Number} tile number
*/
ExpressionWidget.prototype.checkTile = function(i)
{
this.putBackTile();
this.checkedTile = i;
this.showArrows();
}
/** Sets arrows' position */
ExpressionWidget.prototype.showArrows = function()
{
var i = this.checkedTile;
this.uparrow.x = 10+65*i;
this.downarrow.x = 10+65*i;
}
/*
* Changes operators' order
* @param {type} hold
* @returns {undefined}
*/
ExpressionWidget.prototype.tileUp = function(hold)
{
var i = this.checkedTile;
if(hold === true)
{
var max = 0;
for(var j = 0; j < this.tiles.length; j++)
{
if(this.tiles[j].order > this.tiles[max].order)
{
max = j;
}
}
if(this.tiles[max].order < this.tiles.length)
{
this.tiles[i].order = this.tiles[max].order+1;
}
this.updateTilesState();
return;
}
else if(this.tiles[i].order === 0)
{
var minValue = this.tiles[i].order;
var maxValue = this.tiles[i].order;
var end = false;
while(!end)
{
end = true;
for(var j = 0; j < this.tiles.length; j++)
{
if(this.tiles[j].order === maxValue)
{
maxValue++;
end = false;
break;
}
}
}
for(var j = 0; j < this.tiles.length; j++)
{
if(this.tiles[j].order > minValue && this.tiles[j].order < maxValue)
this.tiles[j].order++;
}
}
if(this.tiles[i].order === this.tiles.length)
{
this.tiles[i].order = 0;
}
else
{
var newValue = this.tiles[i].order+1;
for(var j = 0; j < this.tiles.length; j++)
{
if(this.tiles[j].order === newValue)
{
this.tiles[j].order = this.tiles[i].order;
break;
}
}
this.tiles[i].order++;
}
this.updateTilesState();
}
/*
* Changes operators' order
* @param {type} hold
* @returns {undefined}
*/
ExpressionWidget.prototype.tileDown = function(hold)
{
var i = this.checkedTile;
if(hold === true)
{
this.tiles[i].order = 0;
}
else if(this.tiles[i].order === 0)
{
var newValue = this.tiles.length;
var end = false;
while(!end && newValue > 0)
{
end = true;
for(var j = 0; j < this.tiles.length; j++)
{
if(this.tiles[j].order === newValue)
{
end = false;
newValue--;
break;
}
}
}
this.tiles[i].order = newValue;
}
else if(this.tiles[i].order === 1)
{
this.tiles[i].order--;
}
else
{
var newValue = this.tiles[i].order-1;
for(var j = 0; j < this.tiles.length; j++)
{
if(this.tiles[j].order === newValue)
{
this.tiles[j].order = this.tiles[i].order;
break;
}
}
this.tiles[i].order--;
}
this.updateTilesState();
}
/** Updates tile's color and displayed number */
ExpressionWidget.prototype.updateTilesState = function()
{
for(var i = 0; i < this.tiles.length; i++)
{
this.tiles[i].text.text = this.tiles[i].order;
if(this.tiles[i].order === this.tiles[i].correctOrder)
this.tiles[i].tileObj.gotoAndStop(1);
else if(this.tiles[i].order === this.tiles[i].wrongOrder)
this.tiles[i].tileObj.gotoAndStop(2);
else
this.tiles[i].tileObj.gotoAndStop(0);
}
}
/**
* Tilts the checked tile in y axes
* @param {type} y
*/
ExpressionWidget.prototype.moveTile = function(y)
{
var shape = this.tiles[this.checkedTile].tileObj;
shape.y = this.shapeY+y*0.2;
}
/** Puts the checked tile's y axes in its original position */
ExpressionWidget.prototype.putBackTile = function()
{
var shape = this.tiles[this.checkedTile].tileObj;
shape.y = this.shapeY;
}