diff --git a/html/logic.js b/html/logic.js
new file mode 100644
index 0000000..f078b4d
--- /dev/null
+++ b/html/logic.js
@@ -0,0 +1,267 @@
+const socket = new WebSocket("ws://localhost:7865");
+var canvas = document.getElementById("board");
+var colorInput = document.getElementById("color");
+var canvasHidden = document.getElementById("hidden");
+var ctx = canvas.getContext("2d");
+var ctx2 = canvasHidden.getContext("2d");
+var currentColor = "#000000"
+canvas.width = 1920;
+canvas.height = 1080;
+canvasHidden.width = 1920;
+canvasHidden.height = 1080;
+var imgData = ctx2.createImageData(canvasHidden.width, canvasHidden.height)
+
+function drawPixel(x, y, color) {
+ let pixelNumber;
+ if (y > 0)
+ pixelNumber = (y) * canvas.width + x
+ if (y == 0)
+ pixelNumber = x
+ if (color == undefined) rgbColor = hexToRgb(currentColor);
+ for (let l = 0; l < 4; l ++)
+ for (let l = 0; l < 5; l ++){
+ imgData.data[pixelNumber + 0] = color == undefined? rgbColor.r : color.r;
+ imgData.data[pixelNumber + 1] = color == undefined? rgbColor.g : color.g;
+ imgData.data[pixelNumber + 2] = color == undefined? rgbColor.b : color.b;
+ imgData.data[pixelNumber + 3] = 255;
+ }
+
+ redraw();
+ }
+
+function redraw() {
+ ctx.save();
+ ctx.setTransform(1,0,0,1,0,0);
+ ctx.clearRect(0,0,canvas.width,canvas.height);
+ ctx.restore();
+
+ ctx2.putImageData(imgData, 0, 0);
+ ctx.drawImage(canvasHidden, 0, 0)
+ ctx.imageSmoothingEnabled = false
+ }
+
+socket.addEventListener("open", (event) => {
+ socket.send("{\"code\":0}");
+});
+
+socket.addEventListener("message", (event) => {
+ // console.log("Message from server ", JSON.stringify(event.data.toString()));
+ event.data.text().then(function(packet){
+ packet = JSON.parse(packet)
+ let code = packet.code
+ let content = packet.content
+ switch (code){
+ case 0:
+ //Ineffective way to do that, fix that later ;)
+ let converted = Uint8ClampedArray.from(content)
+
+ for (let i = 0; i < converted.length; i ++)
+ imgData.data[i] = converted[i]
+ redraw();
+ break;
+ case 1:
+ contentJson = JSON.parse(content);
+ let color = {
+ r: contentJson.r,
+ g: contentJson.g,
+ b: contentJson.b
+ }
+
+ drawPixel(contentJson.x * 4, contentJson.y * 4, color)
+ redraw();
+ break;
+ }
+ });
+});
+
+// All the code that is making zooms and moving around cavnas is made with big help of http://phrogz.net/tmp/canvas_zoom_to_cursor.html. Thanks alot!
+window.onload = function() {
+ var ctx = canvas.getContext("2d");
+ trackTransforms(ctx);
+
+ var lastX=canvas.width/2, lastY=canvas.height/2;
+ var dragStart,dragged;
+ canvas.addEventListener('mousedown',function(evt){
+ if (evt.button == 1 || 1 == evt.button&2){
+ document.body.style.mozUserSelect = document.body.style.webkitUserSelect = document.body.style.userSelect = 'none';
+ lastX = evt.offsetX || (evt.pageX - canvas.offsetLeft);
+ lastY = evt.offsetY || (evt.pageY - canvas.offsetTop);
+ dragStart = ctx.transformedPoint(lastX,lastY);
+ dragged = false;
+ }
+ },false);
+ canvas.addEventListener('mousemove',function(evt){
+ lastX = evt.offsetX || (evt.pageX - canvas.offsetLeft);
+ lastY = evt.offsetY || (evt.pageY - canvas.offsetTop);
+ dragged = true;
+ if (dragStart){
+ var pt = ctx.transformedPoint(lastX,lastY);
+ ctx.translate(pt.x-dragStart.x,pt.y-dragStart.y);
+ redraw();
+ }
+ },false);
+ canvas.addEventListener('mouseup',function(evt){
+ if (evt.button == 1 || 1 == evt.button&2){
+ dragStart = null;
+ if (dragged) {
+
+ let point = ctx.transformedPoint(
+ evt.clientX - canvas.offsetLeft,
+ evt.clientY - canvas.offsetTop
+ );
+ } else {
+ let point = {
+ x: Math.floor(ctx.transformedPoint(lastX,lastY).x) * 4,
+ y: Math.floor(ctx.transformedPoint(lastX,lastY).y) * 4,
+ };
+ x = point.x; y = point.y;
+ let pixelNumber;
+ if (y > 0)
+ pixelNumber = (y) * canvas.width + x
+ if (y == 0)
+ pixelNumber = x
+
+ let color = {
+ r: imgData.data[pixelNumber + 0],
+ g: imgData.data[pixelNumber + 1],
+ b: imgData.data[pixelNumber + 2]
+ };
+
+ changeColor(rgbToHex(color.r, color.g, color.b));
+ }
+ } else if (evt.button == 0) {
+ let point = {
+ x: Math.floor(ctx.transformedPoint(lastX,lastY).x) * 4,
+ y: Math.floor(ctx.transformedPoint(lastX,lastY).y) * 4,
+ };
+ let rgbColor = hexToRgb(currentColor);
+ let pixel = JSON.stringify({
+ "x": `${point.x/4}`,
+ "y": `${point.y/4}`,
+ "r": `${rgbColor.r}`,
+ "g": `${rgbColor.g}`,
+ "b": `${rgbColor.b}`
+ });
+ let packet = {
+ "code": 1,
+ "content": pixel
+ }
+ socket.send(JSON.stringify(packet));
+ // console.log(`{\"code\":1, \"content\":${pixel}}`)
+
+ drawPixel(point.x, point.y, undefined);
+ }
+ },false);
+
+ var scaleFactor = 1.1;
+ var zoom = function(clicks){
+ var pt = ctx.transformedPoint(lastX,lastY);
+ ctx.translate(pt.x,pt.y);
+ var factor = Math.pow(scaleFactor,clicks);
+ ctx.scale(factor,factor);
+ ctx.translate(-pt.x,-pt.y);
+ redraw();
+ }
+
+ var handleScroll = function(evt){
+ var delta = evt.wheelDelta ? evt.wheelDelta/40 : evt.detail ? -evt.detail : 0;
+ if (delta) zoom(delta);
+ return evt.preventDefault() && false;
+ };
+ canvas.addEventListener('DOMMouseScroll',handleScroll,false);
+ canvas.addEventListener('mousewheel',handleScroll,false);
+};
+
+function evaulatePixelNumber(x, y) {
+ let pixelNumber;
+ if (y > 0)
+ pixelNumber = (y) * canvas.width + x
+ if (y == 0)
+ pixelNumber = x
+ return pixelNumber
+}
+function changeColor(color) {
+ if (color == undefined) currentColor = colorInput.value;
+ else {
+ currentColor = color
+ colorInput.value = color
+ }
+}
+
+
+//Code from https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb#5624139
+function hexToRgb(hex) {
+ // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
+ var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
+ hex = hex.replace(shorthandRegex, function(m, r, g, b) {
+ return r + r + g + g + b + b;
+ });
+
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ return result ? {
+ r: parseInt(result[1], 16),
+ g: parseInt(result[2], 16),
+ b: parseInt(result[3], 16)
+ } : null;
+}
+
+const rgbToHex = (r, g, b) => '#' + [r, g, b].map(x => {
+ const hex = x.toString(16)
+ return hex.length === 1 ? '0' + hex : hex
+}).join('')
+
+function trackTransforms(ctx){
+ var svg = document.createElementNS("http://www.w3.org/2000/svg",'svg');
+ var xform = svg.createSVGMatrix();
+ ctx.getTransform = function(){ return xform; };
+
+ var savedTransforms = [];
+ var save = ctx.save;
+ ctx.save = function(){
+ savedTransforms.push(xform.translate(0,0));
+ return save.call(ctx);
+ };
+ var restore = ctx.restore;
+ ctx.restore = function(){
+ xform = savedTransforms.pop();
+ return restore.call(ctx);
+ };
+
+ var scale = ctx.scale;
+ ctx.scale = function(sx,sy){
+ xform = xform.scaleNonUniform(sx,sy);
+ return scale.call(ctx,sx,sy);
+ };
+ var rotate = ctx.rotate;
+ ctx.rotate = function(radians){
+ xform = xform.rotate(radians*180/Math.PI);
+ return rotate.call(ctx,radians);
+ };
+ var translate = ctx.translate;
+ ctx.translate = function(dx,dy){
+ xform = xform.translate(dx,dy);
+ return translate.call(ctx,dx,dy);
+ };
+ var transform = ctx.transform;
+ ctx.transform = function(a,b,c,d,e,f){
+ var m2 = svg.createSVGMatrix();
+ m2.a=a; m2.b=b; m2.c=c; m2.d=d; m2.e=e; m2.f=f;
+ xform = xform.multiply(m2);
+ return transform.call(ctx,a,b,c,d,e,f);
+ };
+ var setTransform = ctx.setTransform;
+ ctx.setTransform = function(a,b,c,d,e,f){
+ xform.a = a;
+ xform.b = b;
+ xform.c = c;
+ xform.d = d;
+ xform.e = e;
+ xform.f = f;
+ return setTransform.call(ctx,a,b,c,d,e,f);
+ };
+ var pt = svg.createSVGPoint();
+ ctx.transformedPoint = function(x,y){
+ pt.x=x; pt.y=y;
+ return pt.matrixTransform(xform.inverse());
+ }
+}
\ No newline at end of file