// JavaScript Document
            var shapeTypes;
            var cubesPerShape;
            var shapeSize = 16;
            var shapes;
            var showingGrid = true;
            var dragIndex;
            var dragging;
            var mouseX;
            var mouseY;
            var touchX, touchY;
            var dragHoldX;
            var dragHoldY;
            var theCanvas;
            var context;
            function init() {
                theCanvas = document.getElementById("counterCanvas");
                context = theCanvas.getContext("2d");
                context.canvas.width = 0.95 * window.innerWidth;
                context.canvas.height = 0.78 * window.innerHeight;
                shapes = [];
                makeShapes();
                theCanvas.addEventListener("mousedown", mouseDownListener, false);
                theCanvas.addEventListener('touchstart', touchDownListener, false);
                theCanvas.addEventListener('dblclick', doubleClickListener, false);
            }
            function makeShapes() {
                var colour = new Array("red", "green", "blue", "yellow");
                var type = new Array("f", "i", "l", "n", "p", "t", "u", "v", "w", "x", "y", "z");
                var perType = 11;
                shapeTypes = type.length;
                cubesPerShape = 5;
                var tempSize = shapeSize;
                var tempX;
                var tempY;
                for (var i = 0; i < shapeTypes; i++) {
                    for (var j = 0; j < cubesPerShape; j++) {
                        tempX = 0;
                        tempY = 0;
                        var tempShape = {x: tempX, y: tempY, type: type[i], state: 0, part: j, length: tempSize, height: tempSize, color: colour[i % colour.length], layer: shapes.length};
                        shapes.push(tempShape);
                    }
                }
                scatter();
                drawScreen();
            }
            function positionShapes() {
                var count = 0;
                for (var i = 0; i < shapeTypes; i++) {
                    for (var j = 0; j < cubesPerShape; j++) {
                        if (j > 0) {
                            shapes[i * cubesPerShape + j].x = shapes[i * cubesPerShape].x;
                            shapes[i * cubesPerShape + j].y = shapes[i * cubesPerShape].y;
                        }
                    }
                }
                var shift = shapeSize * 2;
                // f
                switch (shapes[0].state) {
                    case 0:
                        shapes[1].x -= shift;
                        shapes[2].y -= shift;
                        shapes[3].x += shift;
                        shapes[3].y -= shift;
                        shapes[4].y += shift;
                        break;
                    case 1:
                        shapes[1].x -= shift;
                        shapes[2].y -= shift;
                        shapes[3].x += shift;
                        shapes[4].x += shift;
                        shapes[4].y += shift;
                        break;
                    case 2:
                        shapes[1].y -= shift;
                        shapes[2].x += shift;
                        shapes[3].y += shift;
                        shapes[4].x -= shift;
                        shapes[4].y += shift;
                        break;
                    case 3:
                        shapes[1].x -= shift;
                        shapes[1].y -= shift;
                        shapes[2].x -= shift;
                        shapes[3].x += shift;
                        shapes[4].y += shift;
                        break;
                }
                // i
                switch (shapes[5].state) {
                    case 0:
                        shapes[6].y -= 2 * shift;
                        shapes[7].y -= shift;
                        shapes[8].y += shift;
                        shapes[9].y += 2 * shift;
                        break
                    case 1:
                        shapes[6].x -= 2 * shift;
                        shapes[7].x -= shift;
                        shapes[8].x += shift;
                        shapes[9].x += 2 * shift;
                        break;
                    case 2:
                        shapes[6].y -= 2 * shift;
                        shapes[7].y -= shift;
                        shapes[8].y += shift;
                        shapes[9].y += 2 * shift;
                        break
                    case 3:
                        shapes[6].x -= 2 * shift;
                        shapes[7].x -= shift;
                        shapes[8].x += shift;
                        shapes[9].x += 2 * shift;
                        break;
                }
                // l
                switch (shapes[10].state) {
                    case 0:
                        shapes[11].y -= 2 * shift;
                        shapes[12].y -= shift;
                        shapes[13].y += shift;
                        shapes[14].y += shift;
                        shapes[14].x -= shift;
                        break;
                    case 1:
                        shapes[11].x -= shift;
                        shapes[12].x -= shift;
                        shapes[12].y -= shift;
                        shapes[13].x += shift;
                        shapes[14].x += 2 * shift;
                        break;
                    case 2:
                        shapes[11].y += 2 * shift;
                        shapes[12].y += shift;
                        shapes[13].y -= shift;
                        shapes[14].y -= shift;
                        shapes[14].x += shift;
                        break;
                    case 3:
                        shapes[11].x -= 2 * shift;
                        shapes[12].x -= shift;
                        shapes[13].x += shift;
                        shapes[14].x += shift;
                        shapes[14].y += shift;
                        break;
                }
                // n
                switch (shapes[15].state) {
                    case 0:
                        shapes[16].x += shift;
                        shapes[16].y -= shift;
                        shapes[17].x += shift;
                        shapes[18].y += shift;
                        shapes[19].y += 2 * shift;
                        break;
                    case 1:
                        shapes[16].x -= 2 * shift;
                        shapes[17].x -= shift;
                        shapes[18].y += shift;
                        shapes[19].x += shift;
                        shapes[19].y += shift;
                        break;
                    case 2:
                        shapes[16].x -= shift;
                        shapes[16].y += shift;
                        shapes[17].x -= shift;
                        shapes[18].y -= shift;
                        shapes[19].y -= 2 * shift;
                        break;
                    case 3:
                        shapes[16].x += 2 * shift;
                        shapes[17].x += shift;
                        shapes[18].y -= shift;
                        shapes[19].x -= shift;
                        shapes[19].y -= shift;
                        break;
                }
                // p
                switch (shapes[20].state) {
                    case 0:
                        shapes[21].x += shift;
                        shapes[21].y -= shift;
                        shapes[22].x += shift;
                        shapes[23].x += shift;
                        shapes[23].y += shift;
                        shapes[24].y += shift;
                        break;
                    case 1:
                        shapes[21].y += shift;
                        shapes[21].x += 2 * shift;
                        shapes[22].y += shift;
                        shapes[23].y += shift;
                        shapes[23].x += shift;
                        shapes[24].x += shift;
                        break;
                    case 2:
                        shapes[21].x -= shift;
                        shapes[21].y += shift;
                        shapes[22].x -= shift;
                        shapes[23].x -= shift;
                        shapes[23].y -= shift;
                        shapes[24].y -= shift;
                        break;
                    case 3:
                        shapes[21].y -= shift;
                        shapes[21].x -= 2 * shift;
                        shapes[22].y -= shift;
                        shapes[23].y -= shift;
                        shapes[23].x -= shift;
                        shapes[24].x -= shift;
                        break;
                }
                // t
                switch (shapes[25].state) {
                    case 0:
                        shapes[26].x -= shift;
                        shapes[26].y -= shift;
                        shapes[27].y -= shift;
                        shapes[28].x += shift;
                        shapes[28].y -= shift;
                        shapes[29].y += shift;
                        break;
                    case 1:
                        shapes[26].y += shift;
                        shapes[26].x += shift;
                        shapes[27].x += shift;
                        shapes[28].y -= shift;
                        shapes[28].x += shift;
                        shapes[29].x -= shift;
                        break;
                    case 2:
                        shapes[26].x += shift;
                        shapes[26].y += shift;
                        shapes[27].y += shift;
                        shapes[28].x -= shift;
                        shapes[28].y += shift;
                        shapes[29].y -= shift;
                        break;
                    case 3:
                        shapes[26].y -= shift;
                        shapes[26].x -= shift;
                        shapes[27].x -= shift;
                        shapes[28].y += shift;
                        shapes[28].x -= shift;
                        shapes[29].x += shift;
                        break;
                }
                // u
                switch (shapes[30].state) {
                    case 0:
                        shapes[31].x -= shift;
                        shapes[32].x -= shift;
                        shapes[32].y -= shift;
                        shapes[33].x += shift;
                        shapes[33].y -= shift;
                        shapes[34].x += shift;
                        break;
                    case 1:
                        shapes[31].y += shift;
                        shapes[32].y += shift;
                        shapes[32].x += shift;
                        shapes[33].y -= shift;
                        shapes[33].x += shift;
                        shapes[34].y -= shift;
                        break;
                    case 2:
                        shapes[31].x += shift;
                        shapes[32].x += shift;
                        shapes[32].y += shift;
                        shapes[33].x -= shift;
                        shapes[33].y += shift;
                        shapes[34].x -= shift;
                        break;
                    case 3:
                        shapes[31].y -= shift;
                        shapes[32].y -= shift;
                        shapes[32].x -= shift;
                        shapes[33].y += shift;
                        shapes[33].x -= shift;
                        shapes[34].y += shift;
                        break;
                }
                // v
                switch (shapes[35].state) {
                    case 0:
                        shapes[36].y -= 2 * shift;
                        shapes[37].y -= shift;
                        shapes[38].x += shift;
                        shapes[39].x += 2 * shift;
                        break;
                    case 1:
                        shapes[36].y += 2 * shift;
                        shapes[37].y += shift;
                        shapes[38].x += shift;
                        shapes[39].x += 2 * shift;
                        break;
                    case 2:
                        shapes[36].y += 2 * shift;
                        shapes[37].y += shift;
                        shapes[38].x -= shift;
                        shapes[39].x -= 2 * shift;
                        break;
                    case 3:
                        shapes[36].x -= 2 * shift;
                        shapes[37].x -= shift;
                        shapes[38].y -= shift;
                        shapes[39].y -= 2 * shift;
                        break;
                }
                // w
                switch (shapes[40].state) {
                    case 0:
                        shapes[41].x -= shift;
                        shapes[41].y -= shift;
                        shapes[42].x -= shift;
                        shapes[43].y += shift;
                        shapes[44].x += shift;
                        shapes[44].y += shift;
                        break;
                    case 1:
                        shapes[41].y -= shift;
                        shapes[41].x += shift;
                        shapes[42].y -= shift;
                        shapes[43].x -= shift;
                        shapes[44].y += shift;
                        shapes[44].x -= shift;
                        break;
                    case 2:
                        shapes[41].x += shift;
                        shapes[41].y += shift;
                        shapes[42].x += shift;
                        shapes[43].y -= shift;
                        shapes[44].x -= shift;
                        shapes[44].y -= shift;
                        break;
                    case 3:
                        shapes[41].y += shift;
                        shapes[41].x -= shift;
                        shapes[42].y += shift;
                        shapes[43].x += shift;
                        shapes[44].y -= shift;
                        shapes[44].x += shift;
                        break;
                }
                // x
                shapes[46].x -= shift;
                shapes[47].y -= shift;
                shapes[48].x += shift;
                shapes[49].y += shift;
                // y
                // w
                switch (shapes[50].state) {
                    case 0:
                        shapes[51].x -= shift;
                        shapes[52].y -= shift;
                        shapes[53].y += shift;
                        shapes[54].y += 2 * shift;
                        break;
                    case 1:
                        shapes[51].y -= shift;
                        shapes[52].x += shift;
                        shapes[53].x -= shift;
                        shapes[54].x -= 2 * shift;
                        break;
                    case 2:
                        shapes[51].x += shift;
                        shapes[52].y += shift;
                        shapes[53].y -= shift;
                        shapes[54].y -= 2 * shift;
                        break;
                    case 3:
                        shapes[51].y += shift;
                        shapes[52].x -= shift;
                        shapes[53].x += shift;
                        shapes[54].x += 2 * shift;
                        break;
                }
                // z
                switch (shapes[55].state) {
                    case 0:
                        shapes[56].x -= shift;
                        shapes[56].y -= shift;
                        shapes[57].y -= shift;
                        shapes[58].y += shift;
                        shapes[59].x += shift;
                        shapes[59].y += shift;
                        break;
                    case 1:
                        shapes[56].x += shift;
                        shapes[56].y -= shift;
                        shapes[57].x += shift;
                        shapes[58].x -= shift;
                        shapes[59].x -= shift;
                        shapes[59].y += shift;
                        break;
                    case 2:
                        shapes[56].x -= shift;
                        shapes[56].y -= shift;
                        shapes[57].y -= shift;
                        shapes[58].y += shift;
                        shapes[59].x += shift;
                        shapes[59].y += shift;
                        break;
                    case 3:
                        shapes[56].x += shift;
                        shapes[56].y -= shift;
                        shapes[57].x += shift;
                        shapes[58].x -= shift;
                        shapes[59].x -= shift;
                        shapes[59].y += shift;
                        break;
                }
            }
            function rotate(i) {
                shapes[i].state++;
                if (shapes[i].state > 3) {
                    shapes[i].state = 0;
                }
            }
            function rotateLast() {
                var topShape = 0;
                var currentLayer = 0;

                for (var i = 0; i < shapes.length; i++) {
                    if (shapes[i].layer > currentLayer) {
                        topShape = i;
                        currentLayer = shapes[i].layer;
                    }
                }
                rotate(Math.floor(topShape / 5) * 5);
                drawScreen();
            }
            function doubleClickListener(e) {
                var i;
                var highestIndex = -1;
                getMousePos(e);
                for (i = 0; i < shapes.length; i++) {
                    if (hitTest(shapes[i], mouseX, mouseY)) {
                        if (i > highestIndex) {
                            rotate(i);
                            i = shapes.length;
                        }
                    }
                }
                drawScreen();
                e.preventDefault();
            }
            function touchDownListener(e) {
                var i;
                var hitShapes = [];
                var topShape = 0;
                var currentLayer = 0;
                getTouchPos(e);
                for (i = 0; i < shapes.length; i++) {
                    if (hitTest(shapes[i], touchX, touchY)) {
                        hitShapes.push(Math.floor(i / 5) * 5);
                        dragging = true;
                    }
                }
                for (i = 0; i < hitShapes.length; i++) {
                    if (shapes[hitShapes[i]].layer > currentLayer) {
                        topShape = hitShapes[i];
                        currentLayer = shapes[hitShapes[i]].layer;
                    }
                }
                if (dragging) {
                    dragHoldX = touchX;
                    dragHoldY = touchY;
                    changeLayers(topShape);
                    dragIndex = topShape;
                    window.addEventListener("touchmove", touchMoveListener, false);
                    drawScreen();
                }
                theCanvas.removeEventListener("touchdown", touchDownListener, false);
                window.addEventListener("touchend", touchUpListener, false);
                e.preventDefault();
            }
            function mouseDownListener(e) {
                var i;
                var hitShapes = [];
                var topShape = 0;
                var currentLayer = 0;
                getMousePos(e);
                for (i = 0; i < shapes.length; i++) {
                    if (hitTest(shapes[i], mouseX, mouseY)) {
                        hitShapes.push(Math.floor(i / 5) * 5);
                        dragging = true;
                    }
                }
                for (i = 0; i < hitShapes.length; i++) {
                    if (shapes[hitShapes[i]].layer > currentLayer) {
                        topShape = hitShapes[i];
                        currentLayer = shapes[hitShapes[i]].layer;
                    }
                }
                if (dragging) {
                    dragHoldX = mouseX;
                    dragHoldY = mouseY;
                    changeLayers(topShape);
                    dragIndex = topShape;
                    window.addEventListener("mousemove", mouseMoveListener, false);
                    drawScreen();
                }
                theCanvas.removeEventListener("mousedown", mouseDownListener, false);
                window.addEventListener("mouseup", mouseUpListener, false);
                e.preventDefault();
            }
            function changeLayers(i) {
                var max = 0;
                for (var j = 0; j < shapes.length; j++) {
                    if (max < shapes[j].layer && i != j) {
                        max = shapes[j].layer;
                    }
                }
                for (var k = 0; k < cubesPerShape; k++) {
                    shapes[i + k].layer = max + 1;
                }
            }
            function mouseUpListener(e) {
                theCanvas.addEventListener("mousedown", mouseDownListener, false);
                window.removeEventListener("mouseup", mouseUpListener, false);
                if (dragging) {
                    dragging = false;
                    window.removeEventListener("mousemove", mouseMoveListener, false);
                }
                shapes[dragIndex].x = Math.round(shapes[dragIndex].x / (shapeSize * 2)) * shapeSize * 2;
                shapes[dragIndex].y = Math.round(shapes[dragIndex].y / (shapeSize * 2)) * shapeSize * 2;
                drawScreen();
            }
            function touchUpListener(e) {
                theCanvas.addEventListener("touchdown", touchDownListener, false);
                window.removeEventListener("touchend", touchUpListener, false);
                if (dragging) {
                    dragging = false;
                    window.removeEventListener("touchmove", touchMoveListener, false);
                }
                shapes[dragIndex].x = Math.round(shapes[dragIndex].x / (shapeSize * 2)) * shapeSize * 2;
                shapes[dragIndex].y = Math.round(shapes[dragIndex].y / (shapeSize * 2)) * shapeSize * 2;
                drawScreen();
            }
            function getMousePos(e) {
                if (!e) {
                    var e = event;
                }
                if (e.offsetX) {
                    mouseX = e.offsetX;
                    mouseY = e.offsetY;
                } else if (e.layerX) {
                    mouseX = e.layerX;
                    mouseY = e.layerY;
                }
            }
            function getTouchPos(e) {
                if (!e)
                    var e = event;
                if (e.touches) {
                    if (e.touches.length == 1) { // Only deal with one finger
                        var touch = e.touches[0]; // Get the information for finger #1
                        touchX = touch.pageX - touch.target.offsetLeft;
                        touchY = touch.pageY - touch.target.offsetTop;
                    }
                }
            }
            function mouseMoveListener(e) {
                getMousePos(e);
                shapes[dragIndex].x = mouseX - shapes[dragIndex].length / 2;
                shapes[dragIndex].y = mouseY - shapes[dragIndex].height / 2;
                drawScreen();
            }
            function touchMoveListener(e) {
                getTouchPos(e);
                shapes[dragIndex].x = touchX - shapes[dragIndex].length / 2;
                shapes[dragIndex].y = touchY - shapes[dragIndex].height / 2;
                drawScreen();
            }
            function hitTest(shape, mx, my) {
                var hit = false;
                if (mx > shape.x - shape.length && mx < shape.x + shape.length && my > shape.y - shape.height && my < shape.y + shape.height) {
                    hit = true;
                }
                return hit;
            }

            function drawShapes() {
                positionShapes();
                context.strokeStyle = "black";
                context.lineWidth = 0.5;
                var totalShapes = 0;
                var currentLayer = 0;
                do {
                    for (var i = 0; i < shapes.length; i++) {
                        if (shapes[i].layer == currentLayer) {
                            totalShapes++;
                            context.fillStyle = shapes[i].color;
                            context.beginPath();
                            context.rect(shapes[i].x - shapes[i].length, shapes[i].y - shapes[i].length, 2 * shapes[i].length, 2 * shapes[i].length);
                            context.fill();
                            context.stroke();
                            context.closePath();
                        }
                    }
                    currentLayer++;
                } while (totalShapes < shapes.length);
            }
            function drawGrid() {
                context.strokeStyle = "black";
                context.lineWidth = 0.4;
                var gridSize = shapeSize * 2;
                for (var i = 0; i < Math.ceil(context.canvas.width / gridSize); i++) {
                    context.beginPath();
                    context.moveTo(i * gridSize - shapeSize, 0);
                    context.lineTo(i * gridSize - shapeSize, context.canvas.height);
                    context.closePath();
                    context.stroke();
                }
                for (var j = 0; j < Math.ceil(context.canvas.height / gridSize); j++) {
                    context.beginPath();
                    context.moveTo(0, j * gridSize - shapeSize);
                    context.lineTo(context.canvas.width, j * gridSize - shapeSize);
                    context.closePath();
                    context.stroke();
                }
            }
            function drawScreen() {
                context.fillStyle = "#fff";
                context.fillRect(0, 0, theCanvas.width, theCanvas.height);
                if (showingGrid) {
                    drawGrid();
                }
                drawShapes();
            }
            function scatter() {
                var maxHeight = context.canvas.height;
                var maxWidth = context.canvas.width;
                var maxSize = shapeSize;
                for (var i = 0; i < shapes.length; i++) {
                    shapes[i].x = getRandom(maxSize, maxWidth - 2 * maxSize);
                    shapes[i].y = getRandom(maxSize, maxHeight - 2 * maxSize);
                    shapes[i].x = Math.round(shapes[i].x / (shapeSize * 2)) * shapeSize * 2;
                    shapes[i].y = Math.round(shapes[i].y / (shapeSize * 2)) * shapeSize * 2;
                }
                drawScreen();
            }
            function tidy() {
                var startX = Math.round(context.canvas.width / 2 / (shapeSize * 2)) * shapeSize * 2;
                var startY = Math.round(context.canvas.height / 2 / (shapeSize * 2)) * shapeSize * 2;
                var shift = 2 * shapeSize;
                for (var i = 0; i < shapes.length; i++) {
                    shapes[i].x = startX;
                    shapes[i].y = startY;
                }
                for (var i = 0; i < shapes.length; i++) {
                    switch (shapes[i].type) {
                        case "f":
                            shapes[i].x += shift;
                            shapes[i].y += shift;
                            shapes[i].state = 1;
                            break;
                        case "i":
                            shapes[i].x -= 4 * shift;
                            break;
                        case "p":
                            shapes[i].x -= 2 * shift;
                            shapes[i].y -= shift;
                            shapes[i].state = 2;
                            break
                        case "t":
                            shapes[i].x -= 3 * shift;
                            shapes[i].y += 2 * shift;
                            shapes[i].state = 2;
                            break;
                        case "w":
                            shapes[i].x -= shift;
                            shapes[i].y += 2 * shift;
                            break;
                        case "x":
                            shapes[i].x -= shift;
                            break;
                        case "y":
                            shapes[i].y -= 2 * shift;
                            shapes[i].state = 3;
                            break;
                        case "n":
                            shapes[i].x += shift;
                            shapes[i].y += 3 * shift;
                            shapes[i].state = 3;
                            break;
                        case "v":
                            shapes[i].x += 5 * shift;
                            shapes[i].y -= 2 * shift;
                            shapes[i].state = 2;
                            break;
                        case "u":
                            shapes[i].x += 5 * shift;
                            shapes[i].y += 2 * shift;
                            shapes[i].state = 3;
                            break;
                        case "l":
                            shapes[i].x += 3 * shift;
                            shapes[i].y -= shift;
                            shapes[i].state = 3;
                            break;
                        case "z":
                            shapes[i].x += 3 * shift;
                            shapes[i].y += shift;
                            break;
                    }
                }
                drawScreen();
            }
            function toggleGrid() {
                if (showingGrid) {
                    document.getElementById('gridButton').value = "Εμφάνιση";
                    showingGrid = false;
                } else {
                    document.getElementById('gridButton').value = "Απόκρυψη";
                    showingGrid = true;
                }
                drawScreen();
            }
            function changeSize(x) {
                shapeSize += x;
                var inRange = true;
                if (shapeSize < 8) {
                    shapeSize = 8;
                    inRange = false;
                }
                if (shapeSize > 60) {
                    shapeSize = 60;
                    inRange = false;
                }
                if (inRange) {
                    for (var i = 0; i < shapes.length; i++) {
                        shapes[i].length += x * (shapes[i].length / shapes[i].height);
                        shapes[i].height += x;
                        shapes[i].x = Math.round(shapes[i].x / (shapeSize * 2)) * shapeSize * 2;
                        shapes[i].y = Math.round(shapes[i].y / (shapeSize * 2)) * shapeSize * 2;
                    }
                }
                drawScreen();
            }
