//Make sure canvasses are in the correct positionG var maincanvas= document.querySelector("MainCanvas"); var MainCanvas = document.getElementById("MainCanvas"); var MainCanvas_ctx = MainCanvas.getContext("2d"); var maincanvasBackground="lightgrey"; var mouseIsDown=false; var mouseDownLocation; var mouseDidMovement=false; var imageSize=40; var small_button_size = 20; var uiDeviceInfoLevel = 1; //What do we display when we look at the network //The user interface mode. 0=network, 1=network information, 2=puzzle-selection menu var uiMode=1; const imageCollection = loadImages( ["ArrowUp", "ArrowDown", "animations", "burnmark", "cellphone", "circle", "copier", "firewall", "fluorescent", "hub", "ip_phone", "laptop", "link", "microwave", "pc", "printer", "router", "select", "server", "shapes", "square", "switch", "tablet", "tree", "vidimage", "wap", "wbridge", "wrepeater", "wrouter", "x", "info", "menu"], ["img/ArrowUp.png", "img/ArrowDown.png", "img/Animations.png", "img/BurnMark.png", "img/cellphone.png", "img/Circle.png", "img/Copier.png", "img/firewall.png", "img/fluorescent.png", "img/Hub.png", "img/ip_phone.png", "img/Laptop.png", "img/link.png", "img/microwave.png", "img/PC.png", "img/Printer.png", "img/Router.png", "img/select.png", "img/Server.png", "img/Shapes.png", "img/Square.png", "img/Switch.png", "img/tablet.png", "img/tree.png", "img/VidImage.png", "img/WAP.png", "img/WBridge.png", "img/WRepeater.png", "img/WRouter.png", "img/X.png", "img/info.png", "img/menu.png"], InitializeGameMenu // this is called when all images have loaded. ); var menuItemSize=50; function loadImages(names, files, onAllLoaded) { var i = 0, numLoading = names.length; const onload = () => --numLoading === 0 && onAllLoaded(); const images = {}; while (i < names.length) { const img = images[names[i]] = new Image; img.src = files[i++]; img.onload = onload; } return images; } function imageFromName(name) { return imageCollection[name]; } function InitializeGameMenu() { console.log("Initializing"); MainCanvas.addEventListener("touchstart", handleTouchStart); MainCanvas.addEventListener("touchend", handleTouchEnd); MainCanvas.addEventListener("touchcancel", handleTouchCancel); MainCanvas.addEventListener("touchmove", handleTouchMove); MainCanvas.addEventListener('mousedown',handleMouseDown); MainCanvas.addEventListener('mouseup',handleMouseUp); MainCanvas.addEventListener('mousemove',handleMouseMove); //MainCanvas_ctx.drawImage(imageCollection['router'],100,100,50,50); //MainCanvas_ctx.drawImage(imageCollection['firewall'],150,150,50,50); InitializeSelectMenu(); //It should be printed PrintScreen(); } //Print the screen. Figure out what needs to be printed based on the mode function PrintScreen(WhatPassedIn=-1) { //allow us to override what is printed var what=uiMode; if(WhatPassedIn >=0) what=WhatPassedIn; console.log("PrintingScreen for mode: " + what); if(what == 0) { //The network drawing mode. Print the network //Clear the old screen MainCanvas_ctx.fillStyle = maincanvasBackground; MainCanvas_ctx.fillRect(0,0, MainCanvas.width, MainCanvas.height); //Draw the puzzle-select button //Put the X there so we can click on it MainCanvas_ctx.drawImage(imageFromName("menu"),MainCanvas.width - small_button_size,0,small_button_size,small_button_size); //Draw the info button MainCanvas_ctx.drawImage(imageFromName("info"),MainCanvas.width - small_button_size,small_button_size,small_button_size,small_button_size); drawSelectMenu(); PrintAllNetworkLinks(); PrintAllNetworkDevices(); } else if(what == 1) //PuzzleDescription/Info { //Display the text about the puzzle textMenuPrint(puzzle.en_message); } else if(what == 2) //PuzzleSelect { //TextMenuSelection PrintPuzzleSelectMenu(0); } } function handleTouchStart(evt) { handleMouseDown(copyLocation(evt)); } function handleTouchEnd(evt) { handleMouseUp(copyLocation(evt)); } function handleTouchCancel(evt) { evt.preventDefault(); console.log("canceling touch"); } function handleTouchMove(evt) { //evt.preventDefault(); if(evt.touches.length > 0) { handleMouseMove(copyLocation(evt.touches[0])); } else{ //console.log("not enough touches"); } //console.log("moving touch"); } function handleMouseDown(evt) { mouseDownLocation = copyLocation(evt); mouseIsDown=true; //console.log("mousedown"); if(uiMode==0) SelectMenu_handleMouseDown(mouseDownLocation); } function handleMouseUp(evt) { //evt.preventDefault(); mouseIsDown=false; //See if we have a mouse click let deltaX = Math.abs(evt.pageX - mouseDownLocation.pageX); let deltaY = Math.abs(evt.pageY - mouseDownLocation.pageY); //console.log("delta " + deltaX + "," + deltaY); if(deltaY < 3 && deltaX <3) { //We did not move much. Assume click if(evt.pageX <= menuItemSize && !mouseDidMovement) { if(uiMode==0) SelectMenu_handleMouseUp(evt); //We are in the item select menu. } if(!mouseDidMovement) { //If we are not dragging, it is a click if(uiMode==1) TextWindow_handleMouseUp(evt); else if(uiMode==2) TextWindow_handleMouseUp(evt); else if(uiMode==0 && evt.pageX >= MainCanvas.width - small_button_size) { console.log("clicked far enough x wise"); //We may be clicking on one of the small buttons if(evt.pageY < small_button_size) { //We clicked on the puzzle-select menu console.log("PuzzleSelect pressed"); uiMode=2; PrintScreen(); } else if(evt.pageY < small_button_size *2) { console.log("Selected info button"); //It is the info button uiMode=1; PrintScreen(); } } } } mouseDidMovement=false; //reset it after we raise the button } function handleMouseMove(evt) { //evt.preventDefault(); if(mouseIsDown) { let deltaX = evt.pageX - mouseDownLocation.pageX; let deltaY = evt.pageY - mouseDownLocation.pageY; if(isNaN(deltaY)) deltaY=0; if(isNaN(deltaX)) deltaX=0; //we are dragging //console.log('mousemove ' + evt.pageX + " " + evt.pageY + " delta " + deltaY ); if(uiMode == 0) { SelectMenu_handleMouseMove(evt); } mouseDidMovement=true; } else //Mouse is not down. Not dragging { if(uiMode==2) { textMenu_HandleMouseMove(evt); } } } function copyLocation({ pageX, pageY }) { return { pageX, pageY }; } function PrintNetworkLink(linkToPrint) { //We should have passed in a working link, make sure it exists if(linkToPrint !== null) { if(linkToPrint.SrcNic !== null && linkToPrint.DestNic !== null) { //console.log("printing link from " + linkToPrint.SrcNic.hostname); sdevice = deviceFromID(linkToPrint.SrcNic.hostid); ddevice = deviceFromID(linkToPrint.DstNic.hostid); if(sdevice !== null && ddevice !== null) { //We have an existing link with two devices. Find the device locations and print var spoint = convertXYPointToActual(newPointFromString(sdevice.location)); var dpoint = convertXYPointToActual(newPointFromString(ddevice.location)); //Now we draw a line between them MainCanvas_ctx.beginPath(); MainCanvas_ctx.moveTo(spoint.x,spoint.y); MainCanvas_ctx.lineTo(dpoint.x,dpoint.y); MainCanvas_ctx.stroke(); } } } } function PrintAllNetworkLinks() { if (puzzle == null) return; //If the puzzle has not been set, exit let index=0; if(puzzle.link !== null && typeof(puzzle.link) === "object") { while (index < puzzle.link.length) { PrintNetworkLink(puzzle.link[index]); index++; } } } function PrintNetworkDevice(ToPrint) { //We should have passed in a working device, make sure it exists if(ToPrint !== null) { var rect = deviceRectangle(ToPrint); var dname = ToPrint.mytype; if(dname=="net_switch") dname="switch"; if(dname=="net_hub") dname="hub"; //console.log("printing device " + dname); MainCanvas_ctx.drawImage(imageFromName(dname), rect.spoint.x, rect.spoint.y, rect.width, rect.height); //Now, we see if we need to print the name, or a list of IPs.. var xpoint = rect.center.x; var ystart = rect.epoint.y; //the bottom-most Y point var gap = 3; switch (uiDeviceInfoLevel) { case 0: //Do not print anything break; case 1: //Print the name printCenteredText(MainCanvas_ctx, ToPrint.hostname, xpoint, ystart); break; case 2: //Print both the name and the IP addresses break; case 3: //print just the ip addresses break; } } } function PrintAllNetworkDevices() { if (puzzle == null) return; //If the puzzle has not been set, exit let index=0; while (index < puzzle.device.length) { PrintNetworkDevice(puzzle.device[index]); index++; } } //print centered text. We use y as the top-most y position. But we center around the x position function printCenteredText(canvas_context, text, centerx, top_y, font = "15px serif", textcolor="black") { var metrics = canvas_context.measureText(text); var yHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent + tmTextYGap; var xWidth = metrics.width; var oldfill = canvas_context.fillStyle; var oldstroke = canvas_context.strokeStyle; canvas_context.font = font; canvas_context.fillStyle = textcolor; canvas_context.strokeStyle = textcolor; canvas_context.fillText(text, centerx - (xWidth / 2), top_y + (yHeight / 3)); //reset stuff when done canvas_context.fillStyle = oldfill; canvas_context.strokeStyle = oldstroke; return yHeight; //report back how much space we used. Just in case they want it. } function convertXYPointToActual(point) { //We have an x and y coordinate which needs to be converted to the canvas size var deltax = (MainCanvas.width - menuItemSize) / puzzle.width; var deltay = MainCanvas.height / puzzle.height; return newPointFromPair((point.x * deltax) + menuItemSize, point.y * deltay); } function convertXYpairToActual(x,y) { return convertXYPointToActual(newPointFromPair(x,y)); } function newPointFromPair(x,y) { var point = { 'x' : Math.floor(x), 'y' : Math.floor(y) } return point; } function newPointFromString(pointasstring) { if(typeof(pointasstring) == "string") { var tarray=pointasstring.split(","); return newPointFromPair(Number(tarray[0]),Number(tarray[1])); } } //return a rectangle for the device function deviceRectangle(theDevice) { var centerpoint = convertXYPointToActual(newPointFromString(theDevice.location)); var delta = imageSize / 2; var rect = { spoint : newPointFromPair(centerpoint.x-delta, centerpoint.y-delta), height : imageSize, width : imageSize, epoint : newPointFromPair(centerpoint.x + delta, centerpoint.y + delta), center: centerpoint, } return rect; }