From bf6b52e92a4db8861419b9c18be80dadcaf45955 Mon Sep 17 00:00:00 2001 From: jvgruber Date: Thu, 21 Nov 2024 10:32:26 +0100 Subject: [PATCH] Issue #1712: implement scoring --- .../simulationLogic/simulation.scene.js | 2 +- OpenRobertaWeb/package-lock.json | 10 +- OpenRobertaWeb/package.json | 3 +- .../simulationLogic/simulation.scene.ts | 132 +++++++++++++++++- 4 files changed, 133 insertions(+), 14 deletions(-) diff --git a/OpenRobertaServer/staticResources/js/app/simulation/simulationLogic/simulation.scene.js b/OpenRobertaServer/staticResources/js/app/simulation/simulationLogic/simulation.scene.js index 5dc903b9c4..7d2e31269a 100644 --- a/OpenRobertaServer/staticResources/js/app/simulation/simulationLogic/simulation.scene.js +++ b/OpenRobertaServer/staticResources/js/app/simulation/simulationLogic/simulation.scene.js @@ -1,3 +1,3 @@ -var __spreadArray=this&&this.__spreadArray||function(t,e,i){if(i||2===arguments.length)for(var s,r=0,o=e.length;r=0?(s(this).html("Stop
Scoring Run"),i.init(),s("#rcjStartStop").addClass("running"),!1):(s(this).html("Start
Scoring Run"),clearInterval(i.stopWatch),s("#rcjStartStop").removeClass("running"),s("#rcjLoP").addClass("disabled"),s("#rcjNextCP").addClass("disabled"),i.robot.interpreter.terminate(),i.programPaused=!0,!1)})),s("#rcjLoP").off().on("click",(function(t){i.robot.interpreter.terminate(),i.programPaused=!0,s("#rcjLoP").addClass("disabled"),s("#rcjNextCP").addClass("disabled");var r=o.default.getTilePose(i.lastCheckPoint,e.tiles[i.lastCheckPoint.next],i.prevCheckPointTile);return i.robot.pose=new n.Pose(r.x,r.y,r.theta),i.robot.initialPose=new n.Pose(r.x,r.y,r.theta),i.path=i.lastCheckPoint.index[0],i.lastPath=i.path,i.loPCounter+=1,i.loPSum+=1,i.nextCheckPoint&&i.loPCounter>=3&&s("#rcjNextCP").removeClass("disabled"),!1})),s("#rcjNextCP").off().on("click",(function(t){if(i.robot.interpreter.terminate(),i.programPaused=!0,s("#rcjLoP").addClass("disabled"),s("#rcjNextCP").addClass("disabled"),i.nextCheckPoint){var r=o.default.getTilePose(i.nextCheckPoint,e.tiles[i.nextCheckPoint.next],i.prevNextCheckPoint);i.robot.pose=new n.Pose(r.x,r.y,r.theta),i.robot.initialPose=new n.Pose(r.x,r.y,r.theta),i.path=i.nextCheckPoint.index[0],i.lastPath=i.path,i.loPCounter=0,i.section+=1,i.lastCheckPoint=i.nextCheckPoint,i.setNextCheckPoint()}})),s("#rcjName").text(e.name),s("#rcjTeam").text(t.interpreter.name),s("#rcjTime").text("00:00:0")}return t.prototype.init=function(){this.path=0,this.lastPath=0,this.line=!0,clearInterval(this.stopWatch),this.mins=0,this.secs=0,this.csecs=0,this.running=!0,this.stopWatch=setInterval(this.timer.bind(this),100),this.robot&&this.initialPose&&(this.robot.initialPose=this.initialPose,this.robot.resetPose()),this.loPCounter=0,this.loPSum=0,this.section=0,this.victimsLocated=0},t.prototype.timer=function(){this.running&&(this.csecs++,10===this.csecs&&(this.secs++,this.csecs=0),60===this.secs&&(this.mins++,this.secs=0),s("#rcjTime").text(("00"+this.mins).slice(-2)+":"+("00"+this.secs).slice(-2)+":"+this.csecs),s("#rcjPath").text(-1===this.path?"wrong":"correct"),s("#rcjLastPath").text(this.lastPath),s("#rcjSection").text(this.section),s("#rcjLoPpS").text(this.loPCounter),s("#rcjLoPCount").text(this.loPSum),s("#rcjLine").text(this.line?"yes":"no"),this.mins>=this.MAX_TIME&&s("#rcjStartStop").trigger("click"),s("#rcjRescueMulti").text(this.victimsLocated))},t.prototype.update=function(t){if(this.running)if(t instanceof n.RobotBaseMobile){var e=t;this.robot!=e&&(this.robot=e,this.initialPose=this.robot.initialPose),this.programPaused&&(this.programPaused=!1,s("#rcjLoP").removeClass("disabled"),s("#rcjNextCP").addClass("disabled")),this.pose=e.pose;var i=Math.floor((this.pose.x-10)/90),o=Math.floor((this.pose.y-10)/90),a=this.configData.tiles[i+","+o+",0"],c=a&&a.index[0];c==this.lastPath||c==this.lastPath+1?(this.path=c,this.lastPath=c,a&&a.checkPoint||0==c?this.lastCheckPoint!=a&&(this.loPCounter=0,this.section+=1,this.lastCheckPoint=a,this.setNextCheckPoint()):this.prevCheckPointTile=a):this.path=-1,this.line=this.path>=0&&e.F.lightValue<100}else if(t instanceof r.CircleSimulationObject){var h=t;h.inEvacuationZone&&"#33B8CA"===h.color&&(h.selected=!0,s("#simDeleteObject").trigger("click"),this.victimsLocated+=1)}},t.prototype.setNextCheckPoint=function(){for(var t=this.configData.tiles[this.lastCheckPoint.next];t&&this.configData.tiles[t.next]&&(this.prevNextCheckPoint=t,!(t=this.configData.tiles[t.next]).checkPoint););t&&t.checkPoint?this.nextCheckPoint=t:(this.nextCheckPoint=null,this.prevNextCheckPoint=null)},t.prototype.openClose=function(){var t=s("#simDiv").position();t.left=12,s("#rcjScoringWindow").toggleSimPopup(t)},t.prototype.destroy=function(){s("#rcjStartStop").html("Start
Scoring Run"),s("#rcjStartStop").removeClass("running"),s("#rcjLoP").addClass("disabled"),s("#rcjNextCP").addClass("disabled"),clearInterval(this.stopWatch),this.stopWatch=null,s("#rcjPath").text(""),s("#rcjLastPath").text(""),s("#rcjSection").text(""),s("#rcjLoPpS").text(""),s("#rcjLoPCount").text(""),s("#rcjLine").text(""),s("#rcjName").text(""),s("#rcjTeam").text(""),s("#rcjTime").text("00:00:0"),s("#rcjRescueMulti").text("")},t}();e.RcjScoringTool=c;var h=function(){function t(t){this.DEFAULT_TRAIL_WIDTH=10,this.DEFAULT_TRAIL_COLOR="#000000",this.customBackgroundLoaded=!1,this.ground=new r.Ground(0,0,0,0),this.imgBackgroundList=[],this.imgPath="/css/img/simBackgrounds/",this.playground={x:0,y:0,w:0,h:0},this._colorAreaList=[],this._obstacleList=[],this._rcjList=[],this._markerList=[],this._redrawColorAreas=!1,this._redrawObstacles=!1,this._redrawMarkers=!1,this._robots=[],this._uniqueObjectId=0,this._scoring=!1,this.sim=t,this.uCanvas=document.createElement("canvas"),this.uCtx=this.uCanvas.getContext("2d",{willReadFrequently:!0}),this.udCanvas=document.createElement("canvas"),this.udCtx=this.udCanvas.getContext("2d",{willReadFrequently:!0}),this.bCtx=s("#backgroundLayer")[0].getContext("2d"),this.dCtx=s("#drawLayer")[0].getContext("2d"),this.aCtx=s("#arucoMarkerLayer")[0].getContext("2d"),this.oCtx=s("#objectLayer")[0].getContext("2d"),this.rCtx=s("#robotLayer")[0].getContext("2d"),this.rcjCtx=s("#rcjLayer")[0].getContext("2d")}return Object.defineProperty(t.prototype,"scoring",{get:function(){return this._scoring},set:function(t){this._scoring=t},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"uniqueObjectId",{get:function(){return++this._uniqueObjectId},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"robots",{get:function(){return this._robots},set:function(t){this.clearList(this._robots),this._robots=t},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"obstacleList",{get:function(){return this._obstacleList},set:function(t){this.clearList(this._obstacleList),this._obstacleList=t,this.redrawObstacles=!0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"rcjList",{get:function(){return this._rcjList},set:function(t){this.clearList(this._rcjList),this._rcjList=t,this.redrawObstacles=!0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"colorAreaList",{get:function(){return this._colorAreaList},set:function(t){this.clearList(this._colorAreaList),this._colorAreaList=t,this.redrawColorAreas=!0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"markerList",{get:function(){return this._markerList},set:function(t){this.clearList(this._markerList),this._markerList=t,this.redrawMarkers=!0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"redrawObstacles",{get:function(){return this._redrawObstacles},set:function(t){this._redrawObstacles=t},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"redrawColorAreas",{get:function(){return this._redrawColorAreas},set:function(t){this._redrawColorAreas=t},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"redrawMarkers",{get:function(){return this._redrawMarkers},set:function(t){this._redrawMarkers=t},enumerable:!1,configurable:!0}),t.prototype.addColorArea=function(t){this.addSimulationObject(this.colorAreaList,t,r.SimObjectType.ColorArea),this.redrawColorAreas=!0},t.prototype.addImportColorAreaList=function(t){var e=this,i=[];t.forEach((function(t){var s=r.SimObjectFactory.getSimObject.apply(r.SimObjectFactory,__spreadArray([t.id,e,e.sim.selectionListener,t.shape,r.SimObjectType.ColorArea,t.p,null,t.color],t.params,!1));i.push(s)})),this.colorAreaList=i},t.prototype.addImportObstacle=function(t){var e=this,i=[];t.forEach((function(t){var s=r.SimObjectFactory.getSimObject.apply(r.SimObjectFactory,__spreadArray([t.id,e,e.sim.selectionListener,t.shape,r.SimObjectType.Obstacle,t.p,null,t.color],t.params,!1));i.push(s)})),this.obstacleList=i},t.prototype.addImportRcjLabel=function(t){var e=this,i=[];t.forEach((function(t){var s=new r.RcjSimulationLabel(e.uniqueObjectId,e,e.sim.selectionListener,r.SimObjectType.ColorArea,t.x,t.y,t.checkPoint?"checkPoint":t.start?"start":null,t.index[0]);i.push(s)})),this.rcjList=i},t.prototype.addImportMarkerList=function(t){var e=this,i=[];t.forEach((function(t){var s=r.SimObjectFactory.getSimObject.apply(r.SimObjectFactory,__spreadArray([t.id,e,e.sim.selectionListener,t.shape,r.SimObjectType.Marker,t.p,null,t.color],t.params,!1));s.markerId=t.markerId,i.push(s)})),this.markerList=i},t.prototype.addObstacle=function(t){this.addSimulationObject(this.obstacleList,t,r.SimObjectType.Obstacle),this.redrawObstacles=!0},t.prototype.addSimulationObject=function(t,e,i,o){var a=s("#robotLayer");a.attr("tabindex",0),a.trigger("focus");var n=Math.random()*(this.ground.w-300)+100,c=Math.random()*(this.ground.h-200)+100,h=r.SimObjectFactory.getSimObject(this.uniqueObjectId,this,this.sim.selectionListener,e,i,{x:n,y:c},this.backgroundImg.width);e==r.SimObjectShape.Marker&&o&&(h.markerId=o),t.push(h),h.selected=!0},t.prototype.changeColorWithColorPicker=function(t){var e=this.obstacleList.concat(this.colorAreaList).filter((function(t){return t.selected}));1==e.length&&(e[0].color=t,e[0].type===r.SimObjectType.Obstacle?this.redrawObstacles=!0:this.redrawColorAreas=!0)},t.prototype.clearList=function(t){t.forEach((function(t){t.destroy()})),t.length=0},t.prototype.deleteSelectedObject=function(){var t=this;function e(e){for(var i=0;i.pace").show(),this.robots=[],a.RobotFactory.createRobots(o,n,c,this.sim.selectionListener,this.robotType).then((function(t){if(l.robots=t.robots,l.robotClass=t.robotClass,l.setRobotPoses(h),l.initViews(),u){l.removeRcjScoringTool(),g.imgBackgroundList=[],g.currentBackground=0,g.obstacleList.length>0&&(g.obstacleList=[]),g.colorAreaList.length>0&&(g.colorAreaList=[]);var e=".svg";i.isIE()&&(e=".png"),g.loadBackgroundImages((function(){g.robots[0].mobile?(s(".simMobile").show(),g.images=g.loadImages(["roadWorks","pattern"],["roadWorks"+e,"wallPattern.png"],(function(){g.ground=new r.Ground(10,10,g.imgBackgroundList[g.currentBackground].width,g.imgBackgroundList[g.currentBackground].height),g.backgroundImg=g.imgBackgroundList[0];var t=new r.RectangleSimulationObject(0,g,g.sim.selectionListener,r.SimObjectType.Obstacle,{x:7*g.backgroundImg.width/9,y:g.backgroundImg.height-2*g.backgroundImg.width/9},g.backgroundImg.width);g.obstacleList.push(t),g.centerBackground(!0),g.initEvents(),g.sim.initColorPicker(a.RobotBase.colorRange),g.showFullyLoadedSim(d),g.sim.start()}))):(s(".simMobile").hide(),g.images={},g.ground=new r.Ground(10,10,g.imgBackgroundList[g.currentBackground].width,g.imgBackgroundList[g.currentBackground].height),g.backgroundImg=g.imgBackgroundList[0],g.centerBackground(!0),g.initEvents(),g.showFullyLoadedSim(d),g.sim.start())}))}l.showFullyLoadedSim(d),l.sim.start()}))):(this.robots.forEach((function(t,e){g.rcjScoringTool&&t.addObserver(g.rcjScoringTool),t.replaceState(o[e]),t.reset()})),this.showFullyLoadedSim(d)),this.robots.forEach((function(t,e){t.time=0}))},t.prototype.showFullyLoadedSim=function(t){this.obstacleList.forEach((function(t){t.removeMouseEvents(),t.addMouseEvents()})),this.markerList.forEach((function(t){t.removeMouseEvents(),t.addMouseEvents()})),this.colorAreaList.forEach((function(t){t.removeMouseEvents(),t.addMouseEvents()})),s("#canvasDiv").fadeIn("slow"),s("#simDiv>.pace").fadeOut("fast"),"function"==typeof t&&t()},t.prototype.initViews=function(){var t=s("#systemValuesView"),e=s("#robotIndex");t.html("");var i="",r=this.robots[0]instanceof n.RobotBaseMobile?this.robots[0].chassis.geom.color:"#ffffff";if(i+='",t.append('
'+i+"
"),e.off("change.sim"),this.robots.length>1){var o=this;e.on("change.sim",(function(){var t=Number(s(this).val());o.robots[t].selected=!0,o.sim.selectionListener.fire(null)}))}},t.prototype.initEvents=function(){var t=this,e=0;s(window).off("resize.sim").on("resize.sim",(function(i,s){e>3||"loaded"==s?(t.centerBackground(!1),e=0):e++})),s("#robotLayer").off("keydown.sim").on("keydown.sim",this.handleKeyEvent.bind(this))},t.prototype.loadBackgroundImages=function(t){var e,s;s=i.isIE()?".png":".svg";for(var r=(e=this.robots[0].mobile?this.robots[0].imgList.map((function(t){return t.endsWith("jpg")?t:"".concat(t).concat(s)})):[this.robotType+"Background"+s]).length,o=this,a=function(){if(0==--r&&(t(),i.isLocalStorageAvailable()&&o.robots[0].mobile)){var e=localStorage.getItem("customBackground");if(e){try{JSON.parse(e)}catch(t){localStorage.setItem("customBackground",JSON.stringify({image:e,timestamp:(new Date).getTime()})),e=localStorage.getItem("customBackground")}var s=JSON.parse(e);if((new Date).getTime()-s.timestamp>54432e5)localStorage.removeItem("customBackground");else{var a=s.image,n=new Image;n.src="data:image/png;base64,"+a,o.imgBackgroundList.push(n),o.customBackgroundLoaded=!0}}}},n=0;n0;){a[0].updateSensor(i.uCtx,o,a),a.shift()}})),this.draw(t,e)},t.prototype.toggleTrail=function(){this.robots.forEach((function(t){t.hasTrail=!t.hasTrail,t.pose.xOld=t.pose.x,t.pose.yOld=t.pose.y}))},t.prototype.resetPoseAndDrawings=function(){this.robots.forEach((function(t){return t.resetPose()})),this.dCtx.canvas.width=this.dCtx.canvas.width,this.udCtx.canvas.width=this.udCtx.canvas.width,this.rcjCtx.canvas.width=this.rcjCtx.canvas.width},t.prototype.addMarker=function(t){this.addSimulationObject(this.markerList,r.SimObjectShape.Marker,r.SimObjectType.Marker,t),this._redrawMarkers=!0},t.prototype.setRcjScoringTool=function(t,e){this.rcjScoringTool=new c(t,e),this.scoring=!0;var i=this;s("#simCompetition").show(),s("#simCompetition").off(),s("#simCompetition").onWrap("click",(function(){i.rcjScoringTool.openClose()})),this.obstacleList.forEach((function(t){t.addObserver&&"function"==typeof t.addObserver&&t.addObserver(i.rcjScoringTool)}))},t.prototype.removeRcjScoringTool=function(){this.rcjScoringTool&&this.rcjScoringTool.destroy(),this.rcjScoringTool=null,this.scoring=!1,s("#simCompetition").hide(),s("#simCompetition").off()},t}();e.SimulationScene=h})); +var __spreadArray=this&&this.__spreadArray||function(t,i,e){if(e||2===arguments.length)for(var s,o=0,r=i.length;o=0?(s(this).html("Stop
Scoring Run"),e.init(),s("#rcjStartStop").addClass("running"),!1):(s(this).html("Start
Scoring Run"),clearInterval(e.stopWatch),s("#rcjStartStop").removeClass("running"),s("#rcjLoP").addClass("disabled"),s("#rcjNextCP").addClass("disabled"),e.robot&&e.robot.interpreter.terminate(),e.programPaused=!0,!1)})),s("#rcjLoP").off().on("click",(function(t){e.robot.interpreter.terminate(),e.programPaused=!0,s("#rcjLoP").addClass("disabled"),s("#rcjNextCP").addClass("disabled");var o=r.default.getTilePose(e.lastCheckPoint,i.tiles[e.lastCheckPoint.next],e.prevCheckPointTile);return e.robot.pose=new n.Pose(o.x,o.y,o.theta),e.robot.initialPose=new n.Pose(o.x,o.y,o.theta),e.path=e.lastCheckPoint.index[0],e.lastPath=e.path,e.loPCounter+=1,e.loPSum+=1,e.nextCheckPoint&&e.loPCounter>=3&&s("#rcjNextCP").removeClass("disabled"),!1})),s("#rcjNextCP").off().on("click",(function(t){if(e.robot.interpreter.terminate(),e.programPaused=!0,s("#rcjLoP").addClass("disabled"),s("#rcjNextCP").addClass("disabled"),e.nextCheckPoint){var o=r.default.getTilePose(e.nextCheckPoint,i.tiles[e.nextCheckPoint.next],e.prevNextCheckPoint);e.robot.pose=new n.Pose(o.x,o.y,o.theta),e.robot.initialPose=new n.Pose(o.x,o.y,o.theta),e.path=e.nextCheckPoint.index[0],e.lastPath=e.path,e.loPCounter=0,e.section+=1,e.lastCheckPoint=e.nextCheckPoint,e.setNextCheckPoint()}})),s("#rcjName").text(i.name),s("#rcjTeam").text(t.interpreter.name),s("#rcjTime").text("00:00:0")}return t.prototype.init=function(){this.path=0,this.lastPath=0,this.line=!0,clearInterval(this.stopWatch),this.mins=0,this.secs=0,this.csecs=0,this.running=!0,this.stopWatch=setInterval(this.timer.bind(this),100);var t=this.configData.tiles[this.configData.startTile.x+","+this.configData.startTile.y+",0"];this.initialPose=r.default.getTilePose(t,this.configData.tiles[t.next],null),this.lastTile=t,this.lastCheckPoint=t,this.robot&&(this.robot.initialPose=this.initialPose,this.robot.resetPose()),this.loPCounter=0,this.loPSum=0,this.section=0,this.victimsLocated=0,this.linePoints=0,this.obstaclePoints=0,this.totalScore=0,this.inAvoidanceMode=!1,this.countedTileIndices=[0],this.lastCheckPointIndex=0,this.rescueMulti=1},t.prototype.timer=function(){this.running&&(this.csecs++,10===this.csecs&&(this.secs++,this.csecs=0),60===this.secs&&(this.mins++,this.secs=0),s("#rcjTime").text(("00"+this.mins).slice(-2)+":"+("00"+this.secs).slice(-2)+":"+this.csecs),s("#rcjPath").text(-1===this.path?"wrong":"correct"),s("#rcjLastPath").text(this.lastPath),s("#rcjSection").text(this.section),s("#rcjLoPpS").text(this.loPCounter),s("#rcjLoPCount").text(this.loPSum),s("#rcjLine").text(this.line?"yes":"no"),this.mins>=this.MAX_TIME&&s("#rcjStartStop").trigger("click"),s("#rcjRescueMulti").text(Math.round(100*this.rescueMulti)/100),s("#rcjLinePoints").text(this.linePoints),s("#rcjObstaclePoints").text(this.obstaclePoints),s("#rcjTotalScore").text(this.totalScore))},t.prototype.countObstaclePoints=function(t){t&&!this.countedTileIndices.includes(t.index[0])&&(t.tileType.gaps>0&&(this.obstaclePoints+=this.POINTS_GAP),t.tileType.intersections>0&&(this.obstaclePoints+=this.POINTS_INTERSECTION),this.countedTileIndices.push(t.index[0]))},t.prototype.callAutoLoP=function(){s("#rcjLoP").trigger("click")},t.prototype.update=function(t){if(this.running)if(t instanceof n.RobotBaseMobile){var i=t;this.robot!=i&&(this.robot=i,this.initialPose=this.robot.initialPose),this.programPaused&&(this.programPaused=!1,s("#rcjLoP").removeClass("disabled"),s("#rcjNextCP").addClass("disabled")),this.pose=i.pose;var r=Math.floor((this.pose.x-10)/90),a=Math.floor((this.pose.y-10)/90),c=this.configData.tiles[r+","+a+",0"],h=c&&c.index[0];if(h==this.lastPath||h==this.lastPath+1){if(this.path=h,this.lastPath=h,this.line=i.F.lightValue<70,this.line&&(this.wasOnLineOnce=!0),c&&c.checkPoint||0==h){if(this.lastCheckPoint!=c){var l=this.loPCounter0&&1===this.configData.tiles[this.lastTile.next].items.obstacles?(this.inAvoidanceMode=!0,this.path+=1,this.lastPath=this.path,this.avoidanceGoalIndex=this.lastTile.index[0]+2):this.lastTile.items.obstacles>0?(this.inAvoidanceMode=!0,this.avoidanceGoalIndex=this.lastTile.index[0]+1):(-1!=this.path&&h&&this.callAutoLoP(),this.path=-1)),this.line=!1;this.totalScore=(this.linePoints+this.obstaclePoints)*this.rescueMulti,this.totalScore=e.round(this.totalScore,2)}else if(t instanceof o.CircleSimulationObject){var d=t;d.inEvacuationZone&&"#33B8CA"===d.color&&(d.selected=!0,s("#simDeleteObject").trigger("click"),this.rescueMulti*=this.POINTS_VICTIM_MULTI,this.victimsLocated+=1),d.inEvacuationZone&&"#000000"===d.color&&(d.selected=!0,s("#simDeleteObject").trigger("click"),this.victimsLocated>1?this.rescueMulti*=this.POINTS_VICTIM_MULTI:this.rescueMulti*=this.POINTS_DEADONLY_VICTIM_MULTI,this.victimsLocated+=1),this.victimsLocated>=3&&s("#rcjStartStop").trigger("click")}},t.prototype.setNextCheckPoint=function(){for(var t=this.configData.tiles[this.lastCheckPoint.next];t&&this.configData.tiles[t.next]&&(this.prevNextCheckPoint=t,!(t=this.configData.tiles[t.next]).checkPoint););t&&t.checkPoint?this.nextCheckPoint=t:(this.nextCheckPoint=null,this.prevNextCheckPoint=null)},t.prototype.openClose=function(){var t=s("#simDiv").position();t.left=12,s("#rcjScoringWindow").toggleSimPopup(t)},t.prototype.destroy=function(){s("#rcjStartStop").html("Start
Scoring Run"),s("#rcjStartStop").removeClass("running"),s("#rcjLoP").addClass("disabled"),s("#rcjNextCP").addClass("disabled"),clearInterval(this.stopWatch),this.stopWatch=null,s("#rcjPath").text(""),s("#rcjLastPath").text(""),s("#rcjSection").text(""),s("#rcjLoPpS").text(""),s("#rcjLoPCount").text(""),s("#rcjLine").text(""),s("#rcjName").text(""),s("#rcjTeam").text(""),s("#rcjTime").text("00:00:0"),s("#rcjRescueMulti").text("")},t}();i.RcjScoringTool=c;var h=function(){function t(t){this.DEFAULT_TRAIL_WIDTH=10,this.DEFAULT_TRAIL_COLOR="#000000",this.customBackgroundLoaded=!1,this.ground=new o.Ground(0,0,0,0),this.imgBackgroundList=[],this.imgPath="/css/img/simBackgrounds/",this.playground={x:0,y:0,w:0,h:0},this._colorAreaList=[],this._obstacleList=[],this._rcjList=[],this._markerList=[],this._redrawColorAreas=!1,this._redrawObstacles=!1,this._redrawMarkers=!1,this._robots=[],this._uniqueObjectId=0,this._scoring=!1,this.sim=t,this.uCanvas=document.createElement("canvas"),this.uCtx=this.uCanvas.getContext("2d",{willReadFrequently:!0}),this.udCanvas=document.createElement("canvas"),this.udCtx=this.udCanvas.getContext("2d",{willReadFrequently:!0}),this.bCtx=s("#backgroundLayer")[0].getContext("2d"),this.dCtx=s("#drawLayer")[0].getContext("2d"),this.aCtx=s("#arucoMarkerLayer")[0].getContext("2d"),this.oCtx=s("#objectLayer")[0].getContext("2d"),this.rCtx=s("#robotLayer")[0].getContext("2d"),this.rcjCtx=s("#rcjLayer")[0].getContext("2d")}return Object.defineProperty(t.prototype,"scoring",{get:function(){return this._scoring},set:function(t){this._scoring=t},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"uniqueObjectId",{get:function(){return++this._uniqueObjectId},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"robots",{get:function(){return this._robots},set:function(t){this.clearList(this._robots),this._robots=t},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"obstacleList",{get:function(){return this._obstacleList},set:function(t){this.clearList(this._obstacleList),this._obstacleList=t,this.redrawObstacles=!0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"rcjList",{get:function(){return this._rcjList},set:function(t){this.clearList(this._rcjList),this._rcjList=t,this.redrawObstacles=!0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"colorAreaList",{get:function(){return this._colorAreaList},set:function(t){this.clearList(this._colorAreaList),this._colorAreaList=t,this.redrawColorAreas=!0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"markerList",{get:function(){return this._markerList},set:function(t){this.clearList(this._markerList),this._markerList=t,this.redrawMarkers=!0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"redrawObstacles",{get:function(){return this._redrawObstacles},set:function(t){this._redrawObstacles=t},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"redrawColorAreas",{get:function(){return this._redrawColorAreas},set:function(t){this._redrawColorAreas=t},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"redrawMarkers",{get:function(){return this._redrawMarkers},set:function(t){this._redrawMarkers=t},enumerable:!1,configurable:!0}),t.prototype.addColorArea=function(t){this.addSimulationObject(this.colorAreaList,t,o.SimObjectType.ColorArea),this.redrawColorAreas=!0},t.prototype.addImportColorAreaList=function(t){var i=this,e=[];t.forEach((function(t){var s=o.SimObjectFactory.getSimObject.apply(o.SimObjectFactory,__spreadArray([t.id,i,i.sim.selectionListener,t.shape,o.SimObjectType.ColorArea,t.p,null,t.color],t.params,!1));e.push(s)})),this.colorAreaList=e},t.prototype.addImportObstacle=function(t){var i=this,e=[];t.forEach((function(t){var s=o.SimObjectFactory.getSimObject.apply(o.SimObjectFactory,__spreadArray([t.id,i,i.sim.selectionListener,t.shape,o.SimObjectType.Obstacle,t.p,null,t.color],t.params,!1));e.push(s)})),this.obstacleList=e},t.prototype.addImportRcjLabel=function(t){var i=this,e=[];t.forEach((function(t){var s=new o.RcjSimulationLabel(i.uniqueObjectId,i,i.sim.selectionListener,o.SimObjectType.ColorArea,t.x,t.y,t.checkPoint?"checkPoint":t.start?"start":null,t.index[0]);e.push(s)})),this.rcjList=e},t.prototype.addImportMarkerList=function(t){var i=this,e=[];t.forEach((function(t){var s=o.SimObjectFactory.getSimObject.apply(o.SimObjectFactory,__spreadArray([t.id,i,i.sim.selectionListener,t.shape,o.SimObjectType.Marker,t.p,null,t.color],t.params,!1));s.markerId=t.markerId,e.push(s)})),this.markerList=e},t.prototype.addObstacle=function(t){this.addSimulationObject(this.obstacleList,t,o.SimObjectType.Obstacle),this.redrawObstacles=!0},t.prototype.addSimulationObject=function(t,i,e,r){var a=s("#robotLayer");a.attr("tabindex",0),a.trigger("focus");var n=Math.random()*(this.ground.w-300)+100,c=Math.random()*(this.ground.h-200)+100,h=o.SimObjectFactory.getSimObject(this.uniqueObjectId,this,this.sim.selectionListener,i,e,{x:n,y:c},this.backgroundImg.width);i==o.SimObjectShape.Marker&&r&&(h.markerId=r),t.push(h),h.selected=!0},t.prototype.changeColorWithColorPicker=function(t){var i=this.obstacleList.concat(this.colorAreaList).filter((function(t){return t.selected}));1==i.length&&(i[0].color=t,i[0].type===o.SimObjectType.Obstacle?this.redrawObstacles=!0:this.redrawColorAreas=!0)},t.prototype.clearList=function(t){t.forEach((function(t){t.destroy()})),t.length=0},t.prototype.deleteSelectedObject=function(){var t=this;function i(i){for(var e=0;e.pace").show(),this.robots=[],a.RobotFactory.createRobots(r,n,c,this.sim.selectionListener,this.robotType).then((function(t){if(d.robots=t.robots,d.robotClass=t.robotClass,d.setRobotPoses(h),d.initViews(),u){d.removeRcjScoringTool(),g.imgBackgroundList=[],g.currentBackground=0,g.obstacleList.length>0&&(g.obstacleList=[]),g.colorAreaList.length>0&&(g.colorAreaList=[]);var i=".svg";e.isIE()&&(i=".png"),g.loadBackgroundImages((function(){g.robots[0].mobile?(s(".simMobile").show(),g.images=g.loadImages(["roadWorks","pattern"],["roadWorks"+i,"wallPattern.png"],(function(){g.ground=new o.Ground(10,10,g.imgBackgroundList[g.currentBackground].width,g.imgBackgroundList[g.currentBackground].height),g.backgroundImg=g.imgBackgroundList[0];var t=new o.RectangleSimulationObject(0,g,g.sim.selectionListener,o.SimObjectType.Obstacle,{x:7*g.backgroundImg.width/9,y:g.backgroundImg.height-2*g.backgroundImg.width/9},g.backgroundImg.width);g.obstacleList.push(t),g.centerBackground(!0),g.initEvents(),g.sim.initColorPicker(a.RobotBase.colorRange),g.showFullyLoadedSim(l),g.sim.start()}))):(s(".simMobile").hide(),g.images={},g.ground=new o.Ground(10,10,g.imgBackgroundList[g.currentBackground].width,g.imgBackgroundList[g.currentBackground].height),g.backgroundImg=g.imgBackgroundList[0],g.centerBackground(!0),g.initEvents(),g.showFullyLoadedSim(l),g.sim.start())}))}d.showFullyLoadedSim(l),d.sim.start()}))):(this.robots.forEach((function(t,i){g.rcjScoringTool&&t.addObserver(g.rcjScoringTool),t.replaceState(r[i]),t.reset()})),this.showFullyLoadedSim(l)),this.robots.forEach((function(t,i){t.time=0}))},t.prototype.showFullyLoadedSim=function(t){this.obstacleList.forEach((function(t){t.removeMouseEvents(),t.addMouseEvents()})),this.markerList.forEach((function(t){t.removeMouseEvents(),t.addMouseEvents()})),this.colorAreaList.forEach((function(t){t.removeMouseEvents(),t.addMouseEvents()})),s("#canvasDiv").fadeIn("slow"),s("#simDiv>.pace").fadeOut("fast"),"function"==typeof t&&t()},t.prototype.initViews=function(){var t=s("#systemValuesView"),i=s("#robotIndex");t.html("");var e="",o=this.robots[0]instanceof n.RobotBaseMobile?this.robots[0].chassis.geom.color:"#ffffff";if(e+='",t.append('
'+e+"
"),i.off("change.sim"),this.robots.length>1){var r=this;i.on("change.sim",(function(){var t=Number(s(this).val());r.robots[t].selected=!0,r.sim.selectionListener.fire(null)}))}},t.prototype.initEvents=function(){var t=this,i=0;s(window).off("resize.sim").on("resize.sim",(function(e,s){i>3||"loaded"==s?(t.centerBackground(!1),i=0):i++})),s("#robotLayer").off("keydown.sim").on("keydown.sim",this.handleKeyEvent.bind(this))},t.prototype.loadBackgroundImages=function(t){var i,s;s=e.isIE()?".png":".svg";for(var o=(i=this.robots[0].mobile?this.robots[0].imgList.map((function(t){return t.endsWith("jpg")?t:"".concat(t).concat(s)})):[this.robotType+"Background"+s]).length,r=this,a=function(){if(0==--o&&(t(),e.isLocalStorageAvailable()&&r.robots[0].mobile)){var i=localStorage.getItem("customBackground");if(i){try{JSON.parse(i)}catch(t){localStorage.setItem("customBackground",JSON.stringify({image:i,timestamp:(new Date).getTime()})),i=localStorage.getItem("customBackground")}var s=JSON.parse(i);if((new Date).getTime()-s.timestamp>54432e5)localStorage.removeItem("customBackground");else{var a=s.image,n=new Image;n.src="data:image/png;base64,"+a,r.imgBackgroundList.push(n),r.customBackgroundLoaded=!0}}}},n=0;n0;){a[0].updateSensor(e.uCtx,r,a),a.shift()}})),this.draw(t,i)},t.prototype.toggleTrail=function(){this.robots.forEach((function(t){t.hasTrail=!t.hasTrail,t.pose.xOld=t.pose.x,t.pose.yOld=t.pose.y}))},t.prototype.resetPoseAndDrawings=function(){this.robots.forEach((function(t){return t.resetPose()})),this.dCtx.canvas.width=this.dCtx.canvas.width,this.udCtx.canvas.width=this.udCtx.canvas.width,this.rcjCtx.canvas.width=this.rcjCtx.canvas.width},t.prototype.addMarker=function(t){this.addSimulationObject(this.markerList,o.SimObjectShape.Marker,o.SimObjectType.Marker,t),this._redrawMarkers=!0},t.prototype.setRcjScoringTool=function(t,i){this.rcjScoringTool=new c(t,i),this.scoring=!0;var e=this;s("#simCompetition").show(),s("#simCompetition").off(),s("#simCompetition").onWrap("click",(function(){e.rcjScoringTool.openClose()})),this.obstacleList.forEach((function(t){t.addObserver&&"function"==typeof t.addObserver&&t.addObserver(e.rcjScoringTool)}))},t.prototype.removeRcjScoringTool=function(){this.rcjScoringTool&&this.rcjScoringTool.destroy(),this.rcjScoringTool=null,this.scoring=!1,s("#simCompetition").hide(),s("#simCompetition").off()},t}();i.SimulationScene=h})); //# sourceMappingURL=simulation.scene.js.map //# sourceMappingURL=simulation.scene.js.map diff --git a/OpenRobertaWeb/package-lock.json b/OpenRobertaWeb/package-lock.json index 1a6db27ebe..ce8707c8a5 100644 --- a/OpenRobertaWeb/package-lock.json +++ b/OpenRobertaWeb/package-lock.json @@ -19,7 +19,8 @@ "isomorphic-ws": "^5.0.0", "jquery": "^3.7.1", "lodash.isequal": "^4.5.0", - "web-bluetooth": "^0.1.2" + "web-bluetooth": "^0.1.2", + "ws": "^8.18.0" }, "devDependencies": { "@cor3ntin/flexbuffers-wasm": "^0.0.18", @@ -4473,10 +4474,9 @@ "dev": true }, "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "peer": true, + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "engines": { "node": ">=10.0.0" }, diff --git a/OpenRobertaWeb/package.json b/OpenRobertaWeb/package.json index bd2e52c234..bba1561def 100644 --- a/OpenRobertaWeb/package.json +++ b/OpenRobertaWeb/package.json @@ -25,7 +25,8 @@ "isomorphic-ws": "^5.0.0", "jquery": "^3.7.1", "lodash.isequal": "^4.5.0", - "web-bluetooth": "^0.1.2" + "web-bluetooth": "^0.1.2", + "ws": "^8.18.0" }, "devDependencies": { "@cor3ntin/flexbuffers-wasm": "^0.0.18", diff --git a/OpenRobertaWeb/src/app/simulation/simulationLogic/simulation.scene.ts b/OpenRobertaWeb/src/app/simulation/simulationLogic/simulation.scene.ts index 6f2b31b92b..b64450be0a 100644 --- a/OpenRobertaWeb/src/app/simulation/simulationLogic/simulation.scene.ts +++ b/OpenRobertaWeb/src/app/simulation/simulationLogic/simulation.scene.ts @@ -4,7 +4,19 @@ */ import * as UTIL from 'util.roberta'; import * as $ from 'jquery'; -import { BaseSimulationObject, CircleSimulationObject, Ground, IMovable, ISimulationObstacle, MarkerSimulationObject, RcjSimulationLabel, RectangleSimulationObject, SimObjectFactory, SimObjectShape, SimObjectType } from 'simulation.objects'; +import { + BaseSimulationObject, + CircleSimulationObject, + Ground, + IMovable, + ISimulationObstacle, + MarkerSimulationObject, + RcjSimulationLabel, + RectangleSimulationObject, + SimObjectFactory, + SimObjectShape, + SimObjectType, +} from 'simulation.objects'; import simulationRoberta, { SimulationRoberta } from 'simulation.roberta'; import { IDestroyable, RobotBase, RobotFactory } from 'robot.base'; import { Interpreter } from 'interpreter.interpreter'; @@ -27,6 +39,12 @@ export interface IObservableSimulationObject { export class RcjScoringTool implements IObserver { private MAX_TIME = 8; + private POINTS_OBSTACLE = 15; + private POINTS_GAP = 10; + private POINTS_INTERSECTION = 10; + private POINTS_VICTIM_MULTI = 1.4; + private POINTS_DEADONLY_VICTIM_MULTI = 1.2; + private POINTS_LINE: number[] = [5, 3, 1, 0]; private configData: any; private running: boolean = false; private mins: number = 0; @@ -48,9 +66,21 @@ export class RcjScoringTool implements IObserver { private prevNextCheckPoint: {}; private programPaused: boolean = true; private victimsLocated: number = 0; + private linePoints: number = 1; + private obstaclePoints: number = 0; + private totalScore: number = 0; + private inAvoidanceMode: boolean; + private lastTile: any; + private countedTileIndices: number[]; + private avoidanceGoalIndex: number = null; + private rescueMulti: number; + private lastCheckPointIndex: number; + private wasOnLineOnce: boolean = false; constructor(robot: RobotBase, configData: any) { this.configData = configData; + this.robot = robot as RobotBaseMobile; + this.init(); let rcj = this; $('#rcjStartStop') .off() @@ -66,7 +96,7 @@ export class RcjScoringTool implements IObserver { $('#rcjStartStop').removeClass('running'); $('#rcjLoP').addClass('disabled'); $('#rcjNextCP').addClass('disabled'); - rcj.robot.interpreter.terminate(); + rcj.robot && rcj.robot.interpreter.terminate(); rcj.programPaused = true; return false; } @@ -132,7 +162,11 @@ export class RcjScoringTool implements IObserver { this.csecs = 0; this.running = true; this.stopWatch = setInterval(this.timer.bind(this), 100); - if (this.robot && this.initialPose) { + let startTile = this.configData.tiles['' + this.configData.startTile.x + ',' + this.configData.startTile.y + ',0']; + this.initialPose = simulationRoberta.getTilePose(startTile, this.configData['tiles'][startTile['next']], null); + this.lastTile = startTile; + this.lastCheckPoint = startTile; + if (this.robot) { this.robot.initialPose = this.initialPose; this.robot.resetPose(); } @@ -140,6 +174,13 @@ export class RcjScoringTool implements IObserver { this.loPSum = 0; this.section = 0; this.victimsLocated = 0; + this.linePoints = 0; + this.obstaclePoints = 0; + this.totalScore = 0; + this.inAvoidanceMode = false; + this.countedTileIndices = [0]; + this.lastCheckPointIndex = 0; + this.rescueMulti = 1; } timer() { @@ -163,10 +204,29 @@ export class RcjScoringTool implements IObserver { if (this.mins >= this.MAX_TIME) { $('#rcjStartStop').trigger('click'); } - $('#rcjRescueMulti').text(this.victimsLocated); + $('#rcjRescueMulti').text(Math.round(this.rescueMulti * 100) / 100); + $('#rcjLinePoints').text(this.linePoints); + $('#rcjObstaclePoints').text(this.obstaclePoints); + $('#rcjTotalScore').text(this.totalScore); } } + countObstaclePoints(tile: any) { + if (tile && !this.countedTileIndices.includes(tile.index[0])) { + if (tile.tileType.gaps > 0) { + this.obstaclePoints += this.POINTS_GAP; + } + if (tile.tileType.intersections > 0) { + this.obstaclePoints += this.POINTS_INTERSECTION; + } + this.countedTileIndices.push(tile.index[0]); + } + } + + callAutoLoP() { + $('#rcjLoP').trigger('click'); + } + update(simObject: RobotBaseMobile | CircleSimulationObject) { if (!this.running) { return; @@ -190,28 +250,85 @@ export class RcjScoringTool implements IObserver { if (path == this.lastPath || path == this.lastPath + 1) { this.path = path; this.lastPath = path; + this.line = (robot as RobotRcj)['F'].lightValue < 70 ? true : false; + if (this.line) { + this.wasOnLineOnce = true; + } if ((tile && tile.checkPoint) || path == 0) { if (this.lastCheckPoint != tile) { - // TODO calculate passed section's scoring + // calculate passed section's scoring + let pointsIndex: number = this.loPCounter < this.POINTS_LINE.length ? this.loPCounter : this.POINTS_LINE.length - 1; + this.linePoints += (tile.index[0] - this.lastCheckPointIndex) * this.POINTS_LINE[pointsIndex]; + + // reset section variables this.loPCounter = 0; this.section += 1; this.lastCheckPoint = tile; + this.lastCheckPointIndex = tile.index[0]; this.setNextCheckPoint(); } } else { this.prevCheckPointTile = tile; } + if (this.inAvoidanceMode && this.line && tile.index[0] == this.avoidanceGoalIndex) { + if (!this.countedTileIndices.includes(tile.index[0])) { + this.obstaclePoints += this.POINTS_OBSTACLE; + this.countedTileIndices.push(this.avoidanceGoalIndex - 1); + } + this.avoidanceGoalIndex = null; + this.inAvoidanceMode = false; + } + if (tile && tile !== this.lastTile) { + if (!this.wasOnLineOnce && !this.inAvoidanceMode) { + this.callAutoLoP(); + } else { + this.countObstaclePoints(this.lastTile); + } + this.lastTile = tile; + this.wasOnLineOnce = false; + } } else { - this.path = -1; + if (!this.inAvoidanceMode) { + if (this.lastTile['next'].length > 0 && this.configData['tiles'][this.lastTile['next']]['items']['obstacles'] === 1) { + this.inAvoidanceMode = true; + this.path += 1; + this.lastPath = this.path; + this.avoidanceGoalIndex = this.lastTile.index[0] + 2; + } else if (this.lastTile.items.obstacles > 0) { + this.inAvoidanceMode = true; + this.avoidanceGoalIndex = this.lastTile.index[0] + 1; + } else { + if (this.path != -1 && path) { + this.callAutoLoP(); + } + this.path = -1; + } + } + this.line = false; } - this.line = this.path >= 0 ? ((robot as RobotRcj)['F'].lightValue < 100 ? true : false) : false; + this.totalScore = (this.linePoints + this.obstaclePoints) * this.rescueMulti; + this.totalScore = UTIL.round(this.totalScore, 2); } else if (simObject instanceof CircleSimulationObject) { let circle: CircleSimulationObject = simObject; if (circle.inEvacuationZone && circle.color === '#33B8CA') { circle.selected = true; $('#simDeleteObject').trigger('click'); + this.rescueMulti *= this.POINTS_VICTIM_MULTI; + this.victimsLocated += 1; + } + if (circle.inEvacuationZone && circle.color === '#000000') { + circle.selected = true; + $('#simDeleteObject').trigger('click'); + if (this.victimsLocated > 1) { + this.rescueMulti *= this.POINTS_VICTIM_MULTI; + } else { + this.rescueMulti *= this.POINTS_DEADONLY_VICTIM_MULTI; + } this.victimsLocated += 1; } + if (this.victimsLocated >= 3) { + $('#rcjStartStop').trigger('click'); + } } } @@ -1123,6 +1240,7 @@ export class SimulationScene { } }); } + removeRcjScoringTool() { if (this.rcjScoringTool) { this.rcjScoringTool.destroy();