diff --git a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_enemydrone_js.js b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_enemydrone_js.js new file mode 100644 index 0000000000000000000000000000000000000000..687f780a4bb65219a3f6c1e4a3b15d1f1069a831 --- /dev/null +++ b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_enemydrone_js.js @@ -0,0 +1,334 @@ +/*global BABYLON, console*/ +/*jslint nomen: true, indent: 2, maxlen: 80, todo: true */ + +/************************** ENEMY DRONE API ****************************/ +var EnemyDroneAPI = /** @class */ (function () { + "use strict"; + + var DEFAULT_ACCELERATION = 1, + VIEW_SCOPE = 50, + DEFAULT_SPEED = 16.5, + MIN_SPEED = 12, + MAX_SPEED = 26; + + //** CONSTRUCTOR + function EnemyDroneAPI(gameManager, drone_info, flight_parameters, id) { + this._gameManager = gameManager; + this._mapManager = this._gameManager._mapManager; + this._map_dict = this._mapManager.getMapInfo(); + this._flight_parameters = flight_parameters; + this._id = id; + this._drone_info = drone_info; + this._drone_dict_list = []; + this._acceleration = DEFAULT_ACCELERATION; + } + /* + ** Function called on start phase of the drone, just before onStart AI script + */ + EnemyDroneAPI.prototype.internal_start = function (drone) { + drone._targetCoordinates = drone.getCurrentPosition(); + drone._maxAcceleration = this.getMaxAcceleration(); + if (drone._maxAcceleration <= 0) { + throw new Error('max acceleration must be superior to 0'); + } + drone._minSpeed = this.getMinSpeed(); + if (drone._minSpeed <= 0) { + throw new Error('min speed must be superior to 0'); + } + drone._maxSpeed = this.getMaxSpeed(); + if (drone._minSpeed > drone._maxSpeed) { + throw new Error('min speed cannot be superior to max speed'); + } + drone._speed = drone._targetSpeed = this.getInitialSpeed(); + if (drone._speed < drone._minSpeed || drone._speed > drone._maxSpeed) { + throw new Error('Drone speed must be between min speed and max speed'); + } + if (drone._maxSinkRate > drone._maxSpeed) { + throw new Error('max sink rate cannot be superior to max speed'); + } + drone._maxOrientation = this.getMaxOrientation(); + return; + }; + /* + ** Function called on every drone update, right before onUpdate AI script + */ + EnemyDroneAPI.prototype.internal_update = function (context, delta_time) { + context._speed += context._acceleration * delta_time / 1000; + if (context._speed > context._maxSpeed) + context._speed = context._maxSpeed; + if (context._speed < -context._maxSpeed) + context._speed = -context._maxSpeed; + var updateSpeed = context._speed * delta_time / 1000; + if (context._direction.x !== 0 || + context._direction.y !== 0 || + context._direction.z !== 0) { + context._controlMesh.position.addInPlace( + new BABYLON.Vector3(context._direction.x * updateSpeed, + context._direction.y * updateSpeed, + context._direction.z * updateSpeed)); + } + var orientationValue = context._maxOrientation * + (context._speed / context._maxSpeed); + context._mesh.rotation = new BABYLON.Vector3( + orientationValue * context._direction.z, 0, + -orientationValue * context._direction.x); + context._controlMesh.computeWorldMatrix(true); + context._mesh.computeWorldMatrix(true); + return; + }; + /* + ** Function called on every drone update, right after onUpdate AI script + */ + EnemyDroneAPI.prototype.internal_post_update = function (drone) { + var _this = this, drone_position = drone.getCurrentPosition(), drone_info; + if (drone_position) { + drone_info = { + 'altitudeRel' : drone_position.z, + 'altitudeAbs' : _this._mapManager.getMapInfo().start_AMSL + + drone_position.z, + 'latitude' : drone_position.x, + 'longitude' : drone_position.y + }; + _this._drone_dict_list[_this._id] = drone_info; + //broadcast drone info using internal msg + _this._gameManager._droneList.forEach(function (drone) { + if (drone.id !== _this._id) { + drone.internal_getMsg(drone_info, _this._id); + } + }); + } + }; + + EnemyDroneAPI.prototype.setAltitude = function (drone, altitude) { + drone._targetCoordinates.z = altitude; + }; + + EnemyDroneAPI.prototype.setStartingPosition = function (drone, x, y, z) { + if (!drone._canPlay) { + if (z <= 0.05) { + z = 0.05; + } + drone._controlMesh.position = new BABYLON.Vector3(x, z, y); + } + drone._controlMesh.computeWorldMatrix(true); + drone._mesh.computeWorldMatrix(true); + }; + + EnemyDroneAPI.prototype.internal_getMsg = function (msg, id) { + this._drone_dict_list[id] = msg; + }; + + EnemyDroneAPI.prototype.internal_setTargetCoordinates = + function (drone, coordinates) { + if (!drone._canPlay) return; + var x = coordinates.x, y = coordinates.y, z = coordinates.z; + if (isNaN(x) || isNaN(y) || isNaN(z)) { + throw new Error('Target coordinates must be numbers'); + } + x -= drone._controlMesh.position.x; + y -= drone._controlMesh.position.z; + z -= drone._controlMesh.position.y; + drone.setDirection(x, y, z); + }; + EnemyDroneAPI.prototype.sendMsg = function (msg, to) { + var _this = this, + droneList = _this._gameManager._droneList; + _this._gameManager.delay(function () { + if (to < 0) { + // Send to all drones + droneList.forEach(function (drone) { + if (drone.infosMesh) { + try { + drone.onGetMsg(msg); + } catch (error) { + console.warn('Drone crashed on sendMsg due to error:', error); + drone._internal_crash(); + } + } + }); + } else { + // Send to specific drone + if (droneList[to].infosMesh) { + try { + droneList[to].onGetMsg(msg); + } catch (error) { + console.warn('Drone crashed on sendMsg due to error:', error); + droneList[to]._internal_crash(); + } + } + } + }, _this._flight_parameters.latency.communication); + }; + EnemyDroneAPI.prototype.log = function (msg) { + console.log("API say : " + msg); + }; + EnemyDroneAPI.prototype.getGameParameter = function (name) { + if (["gameTime", "map"].includes(name)) { + return this._gameManager.gameParameter[name]; + } + }; + /* + ** Enemy drone works with cartesian, no geo conversion + */ + EnemyDroneAPI.prototype.processCoordinates = function (x, y, z) { + if (isNaN(x) || isNaN(y) || isNaN(z)) { + throw new Error('Target coordinates must be numbers'); + } + if (z > this._map_dict.start_AMSL) { + z -= this._map_dict.start_AMSL; + } + return { + 'x': x, + 'y': y, + 'z': z + }; + }; + EnemyDroneAPI.prototype.getCurrentPosition = function (x, y, z) { + return this._mapManager.convertToGeoCoordinates(x, y, z); + }; + EnemyDroneAPI.prototype.getDroneViewInfo = function (drone) { + var context = this, result = [], distance, + drone_position = drone.position, other_position; + function calculateDistance(a, b) { + return Math.sqrt(Math.pow((a.x - b.x), 2) + Math.pow((a.y - b.y), 2) + + Math.pow((a.z - b.z), 2)); + } + context._gameManager._droneList_user.forEach(function (other) { + if (other.can_play) { + other_position = other.position; + distance = calculateDistance(drone_position, other_position); + if (distance <= VIEW_SCOPE) { + result.push({ + position: other_position, + direction: other.direction, + rotation: other.rotation, + speed: other.speed, + target: other._targetCoordinates, //check + team: other.team + }); + } + } + }); + return result; + }; + EnemyDroneAPI.prototype.getDroneAI = function () { + //interception math based on https://www.codeproject.com/Articles/990452/Interception-of-Two-Moving-Objects-in-D-Space + return 'var BASE_DISTANCE = 300;\n' + + 'function calculateInterception(hunter_position, prey_position, hunter_speed, prey_speed, prey_velocity_vector) {\n' + + ' var vector_from_drone, distance_to_prey, distance_to_prey_vector, a, b, c, t1, t2, interception_time, interception_point;\n' + + ' function dot(a, b) {\n' + + ' return a.map((x, i) => a[i] * b[i]).reduce((m, n) => m + n);\n' + + ' }\n' + + ' distance_to_prey_vector = [hunter_position.x - prey_position.x, hunter_position.y - prey_position.y, hunter_position.z - prey_position.z];\n' + + ' distance_to_prey = distance(hunter_position, prey_position);\n' + + ' a = hunter_speed * hunter_speed - prey_speed * prey_speed;\n' + + ' b = 2 * dot(distance_to_prey_vector, prey_velocity_vector);\n' + + ' c = - distance_to_prey * distance_to_prey;\n' + + ' t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a);\n' + + ' t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / (2 * a);\n' + + ' if (t1 > 0 && t2 > 0) {\n' + + ' interception_time = Math.min( t1, t2 );\n' + + ' } else {\n' + + ' interception_time = Math.max( t1, t2 );\n' + + ' }\n' + + ' interception_point = [prey_position.x + prey_velocity_vector[0] * interception_time, prey_position.y + prey_velocity_vector[1] * interception_time, prey_position.z + prey_velocity_vector[2] * interception_time];\n' + + ' if (isNaN(interception_point[0]) || isNaN(interception_point[1]) || isNaN(interception_point[2])) {\n' + + ' return;\n' + + ' }\n' + + ' return interception_point;\n' + + '}\n' + + 'function distance(a, b) {\n' + + ' return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2 + (a.z - b.z) ** 2);\n' + + '}\n' + + '\n' + + 'me.onStart = function () {\n' + + ' me.base = me.position;\n' + + ' me.setDirection(0,0,0);\n' + + ' return;\n' + + '\n' + + '};\n' + + '\n' + + 'me.onUpdate = function (timestamp) {\n' + + ' me.current_position = me.position;\n' + + ' var drone_position, drone_velocity_vector, interception_point, drone_view,\n' + + ' dist = distance(\n' + + ' me.current_position,\n' + + ' me.base\n' + + ' );\n' + + // return to base point if drone is too far + ' if (dist >= BASE_DISTANCE) {\n' + + ' me.chasing = false;\n' + + ' me.setTargetCoordinates(\n' + + ' me.base.x,\n' + + ' me.base.y,\n' + + ' me.base.z\n' + + ' );\n' + + ' return;\n' + + ' }\n' + + ' drone_view = me.getDroneViewInfo();\n' + + ' if (drone_view.length) {\n' + + ' drone_position = drone_view[0].position;\n' + + ' drone_velocity_vector = [drone_view[0].target.x - drone_position.x, drone_view[0].target.y - drone_position.y, drone_view[0].target.z - drone_position.z];\n' + + ' interception_point = calculateInterception(me.current_position, drone_position, me.speed, drone_view[0].speed, drone_velocity_vector);\n' + + ' if (!interception_point) {\n' + + ' return;\n' + + ' }\n' + + ' me.chasing = true;\n' + + ' me.setTargetCoordinates(interception_point[0], interception_point[1], interception_point[2]);\n' + + ' }\n' + + // return to base point if drone is too far + ' if (!me.chasing && dist <= 10) {\n' + + ' me.setDirection(0,0,0);\n' + + ' }\n' + + '};'; + }; + EnemyDroneAPI.prototype.getMinSpeed = function () { + return MIN_SPEED; + //return this._flight_parameters.drone.minSpeed; + }; + EnemyDroneAPI.prototype.getMaxSpeed = function () { + return MAX_SPEED; + //return this._flight_parameters.drone.maxSpeed; + }; + EnemyDroneAPI.prototype.getInitialSpeed = function () { + return DEFAULT_SPEED; + //return this._flight_parameters.drone.speed; + }; + EnemyDroneAPI.prototype.getMaxDeceleration = function () { + return this._flight_parameters.drone.maxDeceleration; + }; + EnemyDroneAPI.prototype.getMaxAcceleration = function () { + return this._flight_parameters.drone.maxAcceleration; + }; + EnemyDroneAPI.prototype.getMaxOrientation = function () { + //TODO should be a game parameter (but how to force value to PI quarters?) + return Math.PI / 4; + }; + EnemyDroneAPI.prototype.triggerParachute = function (drone) { + var drone_pos = drone.getCurrentPosition(); + drone.setTargetCoordinates(drone_pos.x, drone_pos.y, 5); + }; + EnemyDroneAPI.prototype.landed = function (drone) { + var drone_pos = drone.getCurrentPosition(); + return Math.floor(drone_pos.z) < 10; + }; + EnemyDroneAPI.prototype.exit = function () { + return; + }; + EnemyDroneAPI.prototype.getInitialAltitude = function () { + return 0; + }; + EnemyDroneAPI.prototype.getAltitudeAbs = function (altitude) { + return altitude; + }; + EnemyDroneAPI.prototype.getMinHeight = function () { + return 0; + }; + EnemyDroneAPI.prototype.getMaxHeight = function () { + return 800; + }; + EnemyDroneAPI.prototype.getFlightParameters = function () { + return this._flight_parameters; + }; + return EnemyDroneAPI; +}()); diff --git a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_enemydrone_js.xml b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_enemydrone_js.xml new file mode 100644 index 0000000000000000000000000000000000000000..1bcd5a1200ecd4903a88cfa29c62589fe6eedc33 --- /dev/null +++ b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_enemydrone_js.xml @@ -0,0 +1,346 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="Web Script" module="erp5.portal_type"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>_Access_contents_information_Permission</string> </key> + <value> + <tuple> + <string>Anonymous</string> + <string>Assignee</string> + <string>Assignor</string> + <string>Associate</string> + <string>Auditor</string> + <string>Manager</string> + </tuple> + </value> + </item> + <item> + <key> <string>_Add_portal_content_Permission</string> </key> + <value> + <tuple> + <string>Assignee</string> + <string>Assignor</string> + <string>Manager</string> + </tuple> + </value> + </item> + <item> + <key> <string>_Change_local_roles_Permission</string> </key> + <value> + <tuple> + <string>Assignor</string> + <string>Manager</string> + </tuple> + </value> + </item> + <item> + <key> <string>_Modify_portal_content_Permission</string> </key> + <value> + <tuple> + <string>Assignee</string> + <string>Assignor</string> + <string>Manager</string> + </tuple> + </value> + </item> + <item> + <key> <string>_View_Permission</string> </key> + <value> + <tuple> + <string>Anonymous</string> + <string>Assignee</string> + <string>Assignor</string> + <string>Associate</string> + <string>Auditor</string> + <string>Manager</string> + </tuple> + </value> + </item> + <item> + <key> <string>content_md5</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>content_type</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>default_reference</string> </key> + <value> <string>gadget_erp5_page_drone_capture_flag_enemydrone.js</string> </value> + </item> + <item> + <key> <string>description</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>drone_capture_flag_enemydrone_js</string> </value> + </item> + <item> + <key> <string>language</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>portal_type</string> </key> + <value> <string>Web Script</string> </value> + </item> + <item> + <key> <string>short_title</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>title</string> </key> + <value> <string>Enemy Drone (API)</string> </value> + </item> + <item> + <key> <string>version</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>workflow_history</string> </key> + <value> + <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent> + </value> + </item> + </dictionary> + </pickle> + </record> + <record id="2" aka="AAAAAAAAAAI="> + <pickle> + <global name="PersistentMapping" module="Persistence.mapping"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>data</string> </key> + <value> + <dictionary> + <item> + <key> <string>document_publication_workflow</string> </key> + <value> + <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent> + </value> + </item> + <item> + <key> <string>edit_workflow</string> </key> + <value> + <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent> + </value> + </item> + <item> + <key> <string>processing_status_workflow</string> </key> + <value> + <persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent> + </value> + </item> + </dictionary> + </value> + </item> + </dictionary> + </pickle> + </record> + <record id="3" aka="AAAAAAAAAAM="> + <pickle> + <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>_log</string> </key> + <value> + <list> + <dictionary> + <item> + <key> <string>action</string> </key> + <value> <string>publish_alive</string> </value> + </item> + <item> + <key> <string>actor</string> </key> + <value> <unicode>zope</unicode> </value> + </item> + <item> + <key> <string>comment</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>error_message</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>time</string> </key> + <value> + <object> + <klass> + <global name="_reconstructor" module="copy_reg"/> + </klass> + <tuple> + <global name="DateTime" module="DateTime.DateTime"/> + <global name="object" module="__builtin__"/> + <none/> + </tuple> + <state> + <tuple> + <float>1683915732.9</float> + <string>UTC</string> + </tuple> + </state> + </object> + </value> + </item> + <item> + <key> <string>validation_state</string> </key> + <value> <string>published_alive</string> </value> + </item> + </dictionary> + </list> + </value> + </item> + </dictionary> + </pickle> + </record> + <record id="4" aka="AAAAAAAAAAQ="> + <pickle> + <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>_log</string> </key> + <value> + <list> + <dictionary> + <item> + <key> <string>action</string> </key> + <value> <string>edit</string> </value> + </item> + <item> + <key> <string>actor</string> </key> + <value> <unicode>zope</unicode> </value> + </item> + <item> + <key> <string>comment</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>error_message</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>serial</string> </key> + <value> <string>1009.37360.49772.3874</string> </value> + </item> + <item> + <key> <string>state</string> </key> + <value> <string>current</string> </value> + </item> + <item> + <key> <string>time</string> </key> + <value> + <object> + <klass> + <global name="_reconstructor" module="copy_reg"/> + </klass> + <tuple> + <global name="DateTime" module="DateTime.DateTime"/> + <global name="object" module="__builtin__"/> + <none/> + </tuple> + <state> + <tuple> + <float>1688571911.82</float> + <string>UTC</string> + </tuple> + </state> + </object> + </value> + </item> + </dictionary> + </list> + </value> + </item> + </dictionary> + </pickle> + </record> + <record id="5" aka="AAAAAAAAAAU="> + <pickle> + <global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>_log</string> </key> + <value> + <list> + <dictionary> + <item> + <key> <string>action</string> </key> + <value> <string>detect_converted_file</string> </value> + </item> + <item> + <key> <string>actor</string> </key> + <value> <unicode>zope</unicode> </value> + </item> + <item> + <key> <string>comment</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>error_message</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>external_processing_state</string> </key> + <value> <string>converted</string> </value> + </item> + <item> + <key> <string>serial</string> </key> + <value> <string>0.0.0.0</string> </value> + </item> + <item> + <key> <string>time</string> </key> + <value> + <object> + <klass> + <global name="_reconstructor" module="copy_reg"/> + </klass> + <tuple> + <global name="DateTime" module="DateTime.DateTime"/> + <global name="object" module="__builtin__"/> + <none/> + </tuple> + <state> + <tuple> + <float>1683913977.2</float> + <string>UTC</string> + </tuple> + </state> + </object> + </value> + </item> + </dictionary> + </list> + </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_fixedwingdrone_js.js b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_fixedwingdrone_js.js index 8a374c6b762b78b54a6c59a3fd81f8d3198057e0..8739ee605b976fefdef88ddaa4efde13ad72278d 100644 --- a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_fixedwingdrone_js.js +++ b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_fixedwingdrone_js.js @@ -5,12 +5,9 @@ var FixedWingDroneAPI = /** @class */ (function () { "use strict"; - // var TAKEOFF_RADIUS = 60, var DEFAULT_SPEED = 16, EARTH_GRAVITY = 9.81, LOITER_LIMIT = 30, - LOITER_RADIUS_FACTOR = 0.60, - LOITER_SPEED_FACTOR = 1.5, MAX_ACCELERATION = 6, MAX_DECELERATION = 1, MIN_SPEED = 12, @@ -19,7 +16,8 @@ var FixedWingDroneAPI = /** @class */ (function () { MIN_PITCH = -20, MAX_PITCH = 25, MAX_CLIMB_RATE = 8, - MAX_SINK_RATE = 3; + MAX_SINK_RATE = 3, + VIEW_SCOPE = 100; //** CONSTRUCTOR function FixedWingDroneAPI(gameManager, drone_info, flight_parameters, id) { @@ -29,10 +27,8 @@ var FixedWingDroneAPI = /** @class */ (function () { this._flight_parameters = flight_parameters; this._id = id; this._drone_info = drone_info; - this._loiter_radius = 0; - this._last_loiter_point_reached = -1; + this._loiter_radius = 100; //this._start_altitude = 0; - //this._last_altitude_point_reached = -1; this._loiter_mode = false; this._drone_dict_list = []; } @@ -40,6 +36,7 @@ var FixedWingDroneAPI = /** @class */ (function () { ** Function called on start phase of the drone, just before onStart AI script */ FixedWingDroneAPI.prototype.internal_start = function (drone) { + drone._targetCoordinates = drone.getCurrentPosition(); drone._maxDeceleration = this.getMaxDeceleration(); if (drone._maxDeceleration <= 0) { throw new Error('max deceleration must be superior to 0'); @@ -146,9 +143,6 @@ var FixedWingDroneAPI = /** @class */ (function () { */ FixedWingDroneAPI.prototype.internal_post_update = function (drone) { var _this = this, drone_position = drone.getCurrentPosition(), drone_info; - if (_this._loiter_mode) { - _this.loiter(drone); - } /*if (_this._start_altitude > 0) { //TODO move start_altitude here _this.reachAltitude(drone); }*/ @@ -158,7 +152,10 @@ var FixedWingDroneAPI = /** @class */ (function () { 'altitudeAbs' : _this._mapManager.getMapInfo().start_AMSL + drone_position.z, 'latitude' : drone_position.x, - 'longitude' : drone_position.y + 'longitude' : drone_position.y, + 'yaw': drone.getYaw(), + 'speed': drone.getAirSpeed(), + 'climbRate': drone.getClimbRate() }; _this._drone_dict_list[_this._id] = drone_info; //broadcast drone info using internal msg @@ -171,7 +168,7 @@ var FixedWingDroneAPI = /** @class */ (function () { }; FixedWingDroneAPI.prototype._updateSpeed = function (drone, delta_time) { - var speed = drone.getSpeed(), speedDiff, speedUpdate; + var speed = drone.getAirSpeed(), speedDiff, speedUpdate; if (speed !== this._targetSpeed) { speedDiff = this._targetSpeed - speed; speedUpdate = drone._acceleration * delta_time / 1000; @@ -185,13 +182,30 @@ var FixedWingDroneAPI = /** @class */ (function () { }; FixedWingDroneAPI.prototype._updateDirection = function (drone, delta_time) { - var horizontalCoeff, newX, newY, newZ; - [newX, newZ] = this._getNewYaw(drone, delta_time); + var horizontalCoeff, newX, newY, newZ, tangentYaw; + + if (this._loiter_mode && Math.sqrt( + Math.pow(drone._targetCoordinates.x - drone.position.x, 2) + + Math.pow(drone._targetCoordinates.y - drone.position.y, 2) + ) <= this._loiter_radius) { + tangentYaw = this._computeBearing( + drone.position.x, + drone.position.y, + drone._targetCoordinates.x, + drone._targetCoordinates.y + ) - 90; + // trigonometric circle is east oriented, yaw angle is clockwise + tangentYaw = this._toRad(-tangentYaw + 90); + newX = Math.cos(tangentYaw); + newZ = Math.sin(tangentYaw); + } else { + [newX, newZ] = this._getNewYaw(drone, delta_time); + } newY = this._getNewAltitude(drone); horizontalCoeff = Math.sqrt( ( - Math.pow(drone.getSpeed(), 2) - Math.pow(newY, 2) + Math.pow(drone.getAirSpeed(), 2) - Math.pow(newY, 2) ) / ( Math.pow(newX, 2) + Math.pow(newZ, 2) ) @@ -235,14 +249,14 @@ var FixedWingDroneAPI = /** @class */ (function () { verticalSpeed = this._computeVerticalSpeed( altitudeDiff, this.getMaxClimbRate(), - drone.getSpeed(), + drone.getAirSpeed(), this.getMaxPitchAngle() ); } else { verticalSpeed = -this._computeVerticalSpeed( Math.abs(altitudeDiff), this.getMaxSinkRate(), - drone.getSpeed(), + drone.getAirSpeed(), -this.getMinPitchAngle() ); } @@ -261,18 +275,14 @@ var FixedWingDroneAPI = /** @class */ (function () { drone.rotation.z + y); }; - FixedWingDroneAPI.prototype.setAltitude = function (drone, altitude) { - drone._targetCoordinates.z = altitude; - }; - FixedWingDroneAPI.prototype.setSpeed = function (drone, speed) { this._targetSpeed = Math.max( Math.min(speed, this.getMaxSpeed()), this.getMinSpeed() ); - drone._acceleration = (this._targetSpeed > drone.getSpeed()) - ? this.getMaxAcceleration() : -this.getMaxDeceleration(); + drone._acceleration = (this._targetSpeed > drone.getAirSpeed()) ? + this.getMaxAcceleration() : -this.getMaxDeceleration(); }; FixedWingDroneAPI.prototype.setStartingPosition = function (drone, x, y, z) { @@ -290,34 +300,18 @@ var FixedWingDroneAPI = /** @class */ (function () { this._drone_dict_list[id] = msg; }; - FixedWingDroneAPI.prototype.set_loiter_mode = function (radius) { - this._loiter_mode = true; - if (radius && radius > LOITER_LIMIT) { - this._loiter_radius = radius * LOITER_RADIUS_FACTOR; - this._loiter_center = this._last_target; - this._loiter_coordinates = []; - this._last_loiter_point_reached = -1; - var x1, y1, angle; - //for (var angle = 0; angle <360; angle+=8){ //counter-clockwise - for (angle = 360; angle > 0; angle -= 8) { //clockwise - x1 = this._loiter_radius * - Math.cos(this._toRad(angle)) + this._loiter_center.x; - y1 = this._loiter_radius * - Math.sin(this._toRad(angle)) + this._loiter_center.y; - this._loiter_coordinates.push( - this.getCurrentPosition(x1, y1, this._loiter_center.z) - ); - } - } - }; FixedWingDroneAPI.prototype.internal_setTargetCoordinates = - function (drone, coordinates, loiter) { - if (!loiter) { + function (drone, coordinates, radius) { + if (radius) { + this._loiter_mode = true; + if (radius >= LOITER_LIMIT) { + this._loiter_radius = radius; + } + } else { this._loiter_mode = false; - //save last target point to use as next loiter center - this._last_target = coordinates; } }; + FixedWingDroneAPI.prototype.sendMsg = function (msg, to) { var _this = this, droneList = _this._gameManager._droneList; @@ -362,79 +356,59 @@ var FixedWingDroneAPI = /** @class */ (function () { if (isNaN(lat) || isNaN(lon) || isNaN(z)) { throw new Error('Target coordinates must be numbers'); } - var x = this._mapManager.longitudToX(lon, this._map_dict.width), - y = this._mapManager.latitudeToY(lat, this._map_dict.depth), - position = this._mapManager.normalize(x, y, this._map_dict), - processed_coordinates; + var point = this._mapManager.toLocalCoordinates(lat, lon, + this._map_dict.map_size), + position = this._mapManager.normalize(point.x, point.y, this._map_dict); if (z > this._map_dict.start_AMSL) { z -= this._map_dict.start_AMSL; } - processed_coordinates = { + return { x: position[0], y: position[1], z: z }; - //this._last_altitude_point_reached = -1; - //this.takeoff_path = []; - return processed_coordinates; }; FixedWingDroneAPI.prototype.getCurrentPosition = function (x, y, z) { return this._mapManager.convertToGeoCoordinates(x, y, z, this._map_dict); }; - FixedWingDroneAPI.prototype.loiter = function (drone) { - if (this._loiter_radius > LOITER_LIMIT) { - var drone_pos = drone.getCurrentPosition(), - min = 9999, - min_i, - i, - d, - next_point; - //shift loiter circle to nearest point - if (this._last_loiter_point_reached === -1) { - if (!this.shifted) { - drone._maxSpeed = drone._maxSpeed * LOITER_SPEED_FACTOR; - for (i = 0; i < this._loiter_coordinates.length; i += 1) { - d = this._mapManager.latLonDistance([drone_pos.x, drone_pos.y], - [this._loiter_coordinates[i].x, - this._loiter_coordinates[i].y]); - if (d < min) { - min = d; - min_i = i; - } - } - this._loiter_coordinates = this._loiter_coordinates.concat( - this._loiter_coordinates.splice(0, min_i) - ); - this.shifted = true; + FixedWingDroneAPI.prototype.getDroneViewInfo = function (drone) { + var context = this, result = { "obstacles": [], "drones": [] }, distance, + other_position, drone_position = drone.getCurrentPosition(); + function calculateDistance(a, b, _this) { + return _this._mapManager.latLonDistance([a.x, a.y], [b.x, b.y]); + } + context._gameManager._droneList.forEach(function (other) { + if (other.can_play && drone.id != other.id) { + other_position = other.getCurrentPosition(); + distance = calculateDistance(drone_position, other_position, context); + if (distance <= VIEW_SCOPE) { + result.drones.push({ + position: drone.getCurrentPosition(), + direction: drone.direction, + rotation: drone.rotation, + speed: drone.speed, + team: drone.team + }); } - } else { - this.shifted = false; } - //stop - if (this._last_loiter_point_reached === - this._loiter_coordinates.length - 1) { - if (drone._maxSpeed !== this.getMaxSpeed()) { - drone._maxSpeed = this.getMaxSpeed(); - } - drone.setDirection(0, 0, 0); - return; + }); + context._map_dict.geo_obstacle_list.forEach(function (obstacle) { + distance = calculateDistance(drone_position, obstacle.position, context); + if (distance <= VIEW_SCOPE) { + result.obstacles.push(obstacle); } - //loiter - next_point = - this._loiter_coordinates[this._last_loiter_point_reached + 1]; - this.internal_setTargetCoordinates(drone, next_point, true); - if (this._mapManager.latLonDistance([drone_pos.x, drone_pos.y], - [next_point.x, next_point.y]) < 1) { - this._last_loiter_point_reached += 1; - if (this._last_loiter_point_reached === - this._loiter_coordinates.length - 1) { - return; + }); + if (drone.__is_getting_drone_view !== true) { + drone.__is_getting_drone_view = true; + context._gameManager.delay(function () { + drone.__is_getting_drone_view = false; + try { + drone.onDroneViewInfo(result); + } catch (error) { + console.warn('Drone crashed on drone view due to error:', error); + drone._internal_crash(); } - next_point = this._loiter_coordinates[ - this._last_loiter_point_reached + 1 - ]; - this.internal_setTargetCoordinates(drone, next_point, true); - } + }, 1000); } }; FixedWingDroneAPI.prototype.getDroneAI = function () { @@ -475,9 +449,9 @@ var FixedWingDroneAPI = /** @class */ (function () { return Math.PI / 4; }; FixedWingDroneAPI.prototype.getYawVelocity = function (drone) { - return 360 * EARTH_GRAVITY - * Math.tan(this._toRad(this.getMaxRollAngle())) - / (2 * Math.PI * drone.getSpeed()); + return 360 * EARTH_GRAVITY * + Math.tan(this._toRad(this.getMaxRollAngle())) / + (2 * Math.PI * drone.getAirSpeed()); }; FixedWingDroneAPI.prototype.getYaw = function (drone) { var direction = drone.worldDirection; @@ -493,9 +467,10 @@ var FixedWingDroneAPI = /** @class */ (function () { }; FixedWingDroneAPI.prototype._computeVerticalSpeed = function (altitude_diff, max_climb_rate, speed, max_pitch) { - var maxVerticalSpeed = Math.min(altitude_diff, Math.min(max_climb_rate, speed)); - return (this._toDeg(Math.asin(maxVerticalSpeed / speed)) > max_pitch) - ? speed * Math.sin(this._toRad(max_pitch)) + var maxVerticalSpeed = + Math.min(altitude_diff, Math.min(max_climb_rate, speed)); + return (this._toDeg(Math.asin(maxVerticalSpeed / speed)) > max_pitch) ? + speed * Math.sin(this._toRad(max_pitch)) : maxVerticalSpeed; }; FixedWingDroneAPI.prototype._toRad = function (angle) { @@ -505,13 +480,13 @@ var FixedWingDroneAPI = /** @class */ (function () { return angle * 180 / Math.PI; }; FixedWingDroneAPI.prototype.getClimbRate = function (drone) { - return drone.worldDirection.y * drone.getSpeed(); + return drone.worldDirection.y * drone.getAirSpeed(); }; FixedWingDroneAPI.prototype.getGroundSpeed = function (drone) { var direction = drone.worldDirection; return Math.sqrt( - Math.pow(direction.x * drone.getSpeed(), 2) - + Math.pow(direction.z * drone.getSpeed(), 2) + Math.pow(direction.x * drone.getAirSpeed(), 2) + + Math.pow(direction.z * drone.getAirSpeed(), 2) ); }; FixedWingDroneAPI.prototype.triggerParachute = function (drone) { @@ -526,10 +501,10 @@ var FixedWingDroneAPI = /** @class */ (function () { return; }; FixedWingDroneAPI.prototype.getInitialAltitude = function () { - return 0; + return this._map_dict.start_AMSL; }; FixedWingDroneAPI.prototype.getAltitudeAbs = function (altitude) { - return altitude; + return altitude + this._map_dict.start_AMSL; }; FixedWingDroneAPI.prototype.getMinHeight = function () { return 0; diff --git a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_fixedwingdrone_js.xml b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_fixedwingdrone_js.xml index 0167003d5d84686f8fe18b96dec902e1fc6d47e9..c7c76f47bb945fc717faec379d8f1f8590d67024 100644 --- a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_fixedwingdrone_js.xml +++ b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_fixedwingdrone_js.xml @@ -246,7 +246,7 @@ </item> <item> <key> <string>serial</string> </key> - <value> <string>1007.63305.59225.51968</string> </value> + <value> <string>1010.5034.64121.33006</string> </value> </item> <item> <key> <string>state</string> </key> @@ -266,7 +266,7 @@ </tuple> <state> <tuple> - <float>1682437182.61</float> + <float>1690565260.64</float> <string>UTC</string> </tuple> </state> diff --git a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_logic_js.js b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_logic_js.js index 221e7d7b5654580d36b5311ec69cf4f40a574457..9b71aee56243361a7a73666c21bcbb93ae58349b 100644 --- a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_logic_js.js +++ b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_logic_js.js @@ -1,15 +1,17 @@ -/*global BABYLON, RSVP, console, FixedWingDroneAPI, document*/ +/*global BABYLON, RSVP, console, FixedWingDroneAPI, EnemyDroneAPI, document*/ /*jslint nomen: true, indent: 2, maxlen: 80, todo: true, unparam: true */ -var GAMEPARAMETERS = {}; +var GAMEPARAMETERS = {}, TEAM_USER = "user", TEAM_ENEMY = "enemy"; +//for DEBUG/TEST mode +var baseLogFunction = console.log, console_log = ""; /******************************* DRONE MANAGER ********************************/ var DroneManager = /** @class */ (function () { "use strict"; //** CONSTRUCTOR - function DroneManager(scene, id, API) { + function DroneManager(scene, id, API, team) { this._mesh = null; this._controlMesh = null; this._canPlay = false; @@ -31,8 +33,9 @@ var DroneManager = /** @class */ (function () { this._scene = scene; this._canUpdate = true; this._id = id; - this._leader_id = 0; + this._team = team; this._API = API; // var API created on AI evel + this._score = 0; // Create the control mesh this._controlMesh = BABYLON.Mesh.CreateBox( "droneControl_" + id, @@ -61,11 +64,6 @@ var DroneManager = /** @class */ (function () { // swap y and z axis so z axis represents altitude return new BABYLON.Vector3(vector.x, vector.z, vector.y); }; - Object.defineProperty(DroneManager.prototype, "leader_id", { - get: function () { return this._leader_id; }, - enumerable: true, - configurable: true - }); Object.defineProperty(DroneManager.prototype, "drone_dict", { get: function () { return this._API._drone_dict_list; }, enumerable: true, @@ -73,6 +71,7 @@ var DroneManager = /** @class */ (function () { }); Object.defineProperty(DroneManager.prototype, "can_play", { get: function () { return this._canPlay; }, + set: function (value) { this._canPlay = value; }, enumerable: true, configurable: true }); @@ -81,6 +80,17 @@ var DroneManager = /** @class */ (function () { enumerable: true, configurable: true }); + Object.defineProperty(DroneManager.prototype, "score", { + get: function () { return this._score; }, + set: function (value) { this._score = value; }, + enumerable: true, + configurable: true + }); + Object.defineProperty(DroneManager.prototype, "team", { + get: function () { return this._team; }, + enumerable: true, + configurable: true + }); Object.defineProperty(DroneManager.prototype, "colliderMesh", { get: function () { return this._mesh; }, enumerable: true, @@ -124,11 +134,10 @@ var DroneManager = /** @class */ (function () { enumerable: true, configurable: true }); - DroneManager.prototype.internal_start = function (initial_position) { + DroneManager.prototype.internal_start = function () { this._API.internal_start(this); this._canPlay = true; this._canCommunicate = true; - this._targetCoordinates = initial_position; try { return this.onStart(); } catch (error) { @@ -140,15 +149,30 @@ var DroneManager = /** @class */ (function () { * Set a target point to move */ DroneManager.prototype.setTargetCoordinates = function (x, y, z) { - if (!this._canPlay) { - return; + this._internal_setTargetCoordinates(x, y, z); + }; + DroneManager.prototype._internal_setTargetCoordinates = + function (x, y, z, radius) { + if (!this._canPlay) { + return; + } + //convert real geo-coordinates to virtual x-y coordinates + this._targetCoordinates = this._API.processCoordinates(x, y, z); + return this._API.internal_setTargetCoordinates( + this, + this._targetCoordinates, + radius + ); + }; + /** + * Returns the list of things a drone "sees" + */ + DroneManager.prototype.getDroneViewInfo = function () { + var context = this; + if (this._controlMesh) { + return context._API.getDroneViewInfo(context); } - //convert real geo-coordinates to virtual x-y coordinates - this._targetCoordinates = this._API.processCoordinates(x, y, z); - return this._API.internal_setTargetCoordinates( - this, - this._targetCoordinates - ); + return; }; DroneManager.prototype.internal_update = function (delta_time) { var context = this; @@ -194,7 +218,7 @@ var DroneManager = /** @class */ (function () { } return this._API.setStartingPosition(this, x, y, z); }; - DroneManager.prototype.setSpeed = function (speed) { + DroneManager.prototype.setAirSpeed = function (speed) { if (!this._canPlay) { return; } @@ -292,20 +316,11 @@ var DroneManager = /** @class */ (function () { } return null; }; - DroneManager.prototype.setAltitude = function (altitude) { - if (!this._canPlay) { - return; - } - return this._API.setAltitude(this, altitude); - }; /** * Make the drone loiter (circle with a set radius) */ - DroneManager.prototype.loiter = function (radius) { - if (!this._canPlay) { - return; - } - this._API.set_loiter_mode(radius); + DroneManager.prototype.loiter = function (x, y, z, radius) { + this._internal_setTargetCoordinates(x, y, z, radius); }; DroneManager.prototype.getFlightParameters = function () { if (this._API.getFlightParameters) { @@ -314,19 +329,31 @@ var DroneManager = /** @class */ (function () { return null; }; DroneManager.prototype.getYaw = function () { - return this._API.getYaw(this); + if (typeof this._API.getYaw !== "undefined") { + return this._API.getYaw(this); + } + return; }; - DroneManager.prototype.getSpeed = function () { + DroneManager.prototype.getAirSpeed = function () { return this._speed; }; DroneManager.prototype.getGroundSpeed = function () { - return this._API.getGroundSpeed(this); + if (typeof this._API.getGroundSpeed !== "undefined") { + return this._API.getGroundSpeed(this); + } + return; }; DroneManager.prototype.getClimbRate = function () { - return this._API.getClimbRate(this); + if (typeof this._API.getClimbRate !== "undefined") { + return this._API.getClimbRate(this); + } + return; }; DroneManager.prototype.getSinkRate = function () { - return this._API.getSinkRate(); + if (typeof this._API.getSinkRate !== "undefined") { + return this._API.getSinkRate(this); + } + return; }; DroneManager.prototype.triggerParachute = function () { return this._API.triggerParachute(this); @@ -364,6 +391,12 @@ var DroneManager = /** @class */ (function () { * @param msg The message */ DroneManager.prototype.onGetMsg = function () { return; }; + /** + * Function called when drone finished processing drone view + * (as result of getDroneViewInfo call) + */ + DroneManager.prototype.onDroneViewInfo = function (drone_view) { return; }; + return DroneManager; }()); @@ -375,41 +408,70 @@ var DroneManager = /** @class */ (function () { var MapManager = /** @class */ (function () { "use strict"; - function calculateMapInfo(map, map_dict, initial_position) { - var max_width = map.latLonDistance([map_dict.min_lat, map_dict.min_lon], - [map_dict.min_lat, map_dict.max_lon]), - max_height = map.latLonDistance([map_dict.min_lat, map_dict.min_lon], - [map_dict.max_lat, map_dict.min_lon]), - map_size = Math.ceil(Math.max(max_width, max_height)) * 0.6, - map_info = { - "depth": map_size, - "height": map_dict.height, - "width": map_size, - "map_size": map_size, - "min_x": map.longitudToX(map_dict.min_lon, map_size), - "min_y": map.latitudeToY(map_dict.min_lat, map_size), - "max_x": map.longitudToX(map_dict.max_lon, map_size), - "max_y": map.latitudeToY(map_dict.max_lat, map_size), - "start_AMSL": map_dict.start_AMSL - }, - position = map.normalize( - map.longitudToX(initial_position.longitude, map_size), - map.latitudeToY(initial_position.latitude, map_size), - map_info - ); - map_info.initial_position = { - "x": position[0], - "y": position[1], - "z": initial_position.z + //random geo-point: + var MIN_LAT = 45.64, + MIN_LON = 14.253, + EPSILON = 9.9, + START_Z = 15, + R = 6371e3; + function calculateMapInfo(map, map_dict) { + var min_lat = map_dict.min_lat || MIN_LAT, + min_lon = map_dict.min_lon || MIN_LON, + offset = map.latLonOffset(min_lat, min_lon, map_dict.map_size), + max_lat = offset[0], + max_lon = offset[1], + starting_point = map_dict.map_size / 2 * -0.75, + local_min = map.toLocalCoordinates(min_lat, min_lon, map_dict.map_size), + local_max = map.toLocalCoordinates(max_lat, max_lon, map_dict.map_size); + map.map_info = { + "depth": map_dict.map_size, + "width": map_dict.map_size, + "map_size": map_dict.map_size, + "min_lat": min_lat, + "min_lon": min_lon, + "max_lat": max_lat, + "max_lon": max_lon, + "min_x": local_min.x, + "min_y": local_min.y, + "max_x": local_max.x, + "max_y": local_max.y, + "height": map_dict.height, + "start_AMSL": map_dict.start_AMSL, + "flag_list": map_dict.flag_list, + "geo_flag_list": [], + "flag_distance_epsilon": map_dict.flag_distance_epsilon || EPSILON, + "obstacle_list": map_dict.obstacle_list, + "geo_obstacle_list": [], + "initial_position": { + "x": 0, + "y": starting_point, + "z": START_Z + } }; - return map_info; + map_dict.flag_list.forEach(function (flag_info, index) { + map.map_info.geo_flag_list.push(map.convertToGeoCoordinates( + flag_info.position.x, + flag_info.position.y, + flag_info.position.z + )); + }); + map_dict.obstacle_list.forEach(function (obstacle_info, index) { + var geo_obstacle = {}; + Object.assign(geo_obstacle, obstacle_info); + geo_obstacle.position = map.convertToGeoCoordinates( + obstacle_info.position.x, + obstacle_info.position.y, + obstacle_info.position.z + ); + map.map_info.geo_obstacle_list.push(geo_obstacle); + }); } //** CONSTRUCTOR function MapManager(scene) { - var _this = this, max_sky, skybox, skyboxMat, largeGroundMat, - largeGroundBottom, width, depth, terrain, max; - _this.map_info = calculateMapInfo(_this, GAMEPARAMETERS.map, - GAMEPARAMETERS.initialPosition); + var _this = this, max_sky, skybox, skyboxMat, largeGroundMat, flag_material, + largeGroundBottom, width, depth, terrain, max, flag_a, flag_b, mast, flag, + count = 0, new_obstacle; + calculateMapInfo(_this, GAMEPARAMETERS.map); max = _this.map_info.width; if (_this.map_info.depth > max) { max = _this.map_info.depth; @@ -419,30 +481,29 @@ var MapManager = /** @class */ (function () { } max = max < _this.map_info.depth ? _this.map_info.depth : max; // Skybox - max_sky = (max * 10 < 20000) ? max * 10 : 20000; - skybox = BABYLON.Mesh.CreateBox("skyBox", max_sky, scene); - skybox.infiniteDistance = true; - skybox.renderingGroupId = 0; + max_sky = (max * 15 < 20000) ? max * 15 : 20000; //skybox scene limit + skybox = BABYLON.MeshBuilder.CreateBox("skyBox", { size: max_sky }, scene); skyboxMat = new BABYLON.StandardMaterial("skybox", scene); skyboxMat.backFaceCulling = false; skyboxMat.disableLighting = true; + skybox.material = skyboxMat; + skybox.infiniteDistance = true; + skyboxMat.disableLighting = true; skyboxMat.reflectionTexture = new BABYLON.CubeTexture("./assets/skybox/sky", scene); skyboxMat.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE; - skyboxMat.infiniteDistance = true; - skybox.material = skyboxMat; + skybox.renderingGroupId = 0; // Plane from bottom largeGroundMat = new BABYLON.StandardMaterial("largeGroundMat", scene); largeGroundMat.specularColor = BABYLON.Color3.Black(); largeGroundMat.alpha = 0.4; largeGroundBottom = BABYLON.Mesh.CreatePlane("largeGroundBottom", - max * 11, scene); + max * 11, scene); largeGroundBottom.position.y = -0.01; largeGroundBottom.rotation.x = -Math.PI / 2; largeGroundBottom.rotation.y = Math.PI; largeGroundBottom.material = largeGroundMat; - // Camera - scene.activeCamera.upperRadiusLimit = max * 4; + largeGroundBottom.renderingGroupId = 1; // Terrain // Give map some margin from the flight limits width = _this.map_info.width * 1.10; @@ -453,19 +514,122 @@ var MapManager = /** @class */ (function () { terrain.position = BABYLON.Vector3.Zero(); terrain.scaling = new BABYLON.Vector3(depth / 50000, depth / 50000, width / 50000); + // Obstacles + _this._obstacle_list = []; + _this.map_info.obstacle_list.forEach(function (obstacle) { + switch (obstacle.type) { + case "box": + new_obstacle = BABYLON.MeshBuilder.CreateBox("obs_" + count, + { 'size': 1 }, scene); + break; + case "cylinder": + new_obstacle = BABYLON.MeshBuilder.CreateCylinder("obs_" + count, { + 'diameterBottom': obstacle.diameterBottom, + 'diameterTop': obstacle.diameterTop, + 'height': 1 + }, scene); + break; + case "sphere": + new_obstacle = BABYLON.MeshBuilder.CreateSphere("obs_" + count, { + 'diameterX': obstacle.scale.x, + 'diameterY': obstacle.scale.z, + 'diameterZ': obstacle.scale.y + }, scene); + break; + default: + return; + } + new_obstacle.type = obstacle.type; + var convertion = Math.PI / 180; + if ("position" in obstacle) + new_obstacle.position = new BABYLON.Vector3(obstacle.position.x, + obstacle.position.z, + obstacle.position.y); + if ("rotation" in obstacle) + new_obstacle.rotation = + new BABYLON.Vector3(obstacle.rotation.x * convertion, + obstacle.rotation.z * convertion, + obstacle.rotation.y * convertion); + if ("scale" in obstacle) + new_obstacle.scaling = new BABYLON.Vector3(obstacle.scale.x, + obstacle.scale.z, + obstacle.scale.y); + var obs_material = new BABYLON.StandardMaterial("obsmat_" + count, scene); + obs_material.alpha = 1; + obs_material.diffuseColor = new BABYLON.Color3(255, 153, 0); + new_obstacle.material = obs_material; + _this._obstacle_list.push(new_obstacle); + count++; + }); + // Flags + _this._flag_list = []; + var FLAG_SIZE = { + 'x': 1, + 'y': 1, + 'z': 6 + }; + _this.map_info.flag_list.forEach(function (flag_info, index) { + flag_material = new BABYLON.StandardMaterial("flag_mat_" + index, scene); + flag_material.alpha = 1; + flag_material.diffuseColor = BABYLON.Color3.Green(); + flag_a = BABYLON.MeshBuilder.CreateDisc("flag_a_" + index, + {radius: 7, tessellation: 3}, + scene); + flag_a.material = flag_material; + flag_a.position = new BABYLON.Vector3( + flag_info.position.x + 1, + FLAG_SIZE.z + 1, //swap + flag_info.position.y - 1 + ); + flag_a.rotation = new BABYLON.Vector3(0, 1, 0); + flag_b = BABYLON.MeshBuilder.CreateDisc("flag_b_" + index, + {radius: 3, tessellation: 3}, + scene); + flag_b.material = flag_material; + flag_b.position = new BABYLON.Vector3( + flag_info.position.x - 1, + FLAG_SIZE.z + 1, //swap + flag_info.position.y + 1 + ); + flag_b.rotation = new BABYLON.Vector3(0, 4, 0); + mast = BABYLON.MeshBuilder.CreateBox("mast_" + index, + { 'size': 1 }, scene); + mast.position = new BABYLON.Vector3( + flag_info.position.x, + FLAG_SIZE.z / 2, //swap + flag_info.position.y + ); + mast.scaling = new BABYLON.Vector3( + FLAG_SIZE.x, + FLAG_SIZE.z, //swap + FLAG_SIZE.y); + mast.material = flag_material; + flag = BABYLON.Mesh.MergeMeshes([flag_a, flag_b, mast]); + flag.id = index; + //flag.weight = _this.map_info.flag_weight; + flag.location = flag_info.position; + flag.drone_collider_list = []; + _this._flag_list.push(flag); + }); } MapManager.prototype.getMapInfo = function () { return this.map_info; }; - MapManager.prototype.longitudToX = function (lon, map_size) { - return (map_size / 360.0) * (180 + lon); + MapManager.prototype.latLonOffset = function (lat, lon, offset_in_mt) { + var R = 6371e3, //Earth radius + lat_offset = offset_in_mt / R, + lon_offset = offset_in_mt / (R * Math.cos(Math.PI * lat / 180)); + return [lat + lat_offset * 180 / Math.PI, + lon + lon_offset * 180 / Math.PI]; }; - MapManager.prototype.latitudeToY = function (lat, map_size) { - return (map_size / 180.0) * (90 - lat); + MapManager.prototype.toLocalCoordinates = function (lat, lon, map_size) { + return { + "x": (map_size / 360.0) * (180 + lon), + "y": (map_size / 180.0) * (90 - lat) + }; }; MapManager.prototype.latLonDistance = function (c1, c2) { - var R = 6371e3, - q1 = c1[0] * Math.PI / 180, + var q1 = c1[0] * Math.PI / 180, q2 = c2[0] * Math.PI / 180, dq = (c2[0] - c1[0]) * Math.PI / 180, dl = (c2[1] - c1[1]) * Math.PI / 180, @@ -481,8 +645,9 @@ var MapManager = /** @class */ (function () { return [n_x * 1000 - map_dict.width / 2, n_y * 1000 - map_dict.depth / 2]; }; - MapManager.prototype.convertToGeoCoordinates = function (x, y, z, map_dict) { - var lon = x + map_dict.width / 2, + MapManager.prototype.convertToGeoCoordinates = function (x, y, z) { + var map_dict = this.map_info, + lon = x + map_dict.width / 2, lat = y + map_dict.depth / 2; lon = lon / 1000; lon = lon * (map_dict.max_x - map_dict.min_x) + @@ -511,11 +676,15 @@ var GameManager = /** @class */ (function () { "use strict"; // *** CONSTRUCTOR *** function GameManager(canvas, game_parameters_json) { - var drone, header_list; + var drone, header_list, drone_count; this._canvas = canvas; + this._canvas_width = canvas.width; + this._canvas_height = canvas.height; this._scene = null; this._engine = null; this._droneList = []; + this._droneList_user = []; + this._droneList_enemy = []; this._canUpdate = false; this._max_step_animation_frame = game_parameters_json.simulation_speed; if (!this._max_step_animation_frame) { this._max_step_animation_frame = 5; } @@ -524,39 +693,55 @@ var GameManager = /** @class */ (function () { this._map_swapped = false; this._log_count = []; this._flight_log = []; - if (GAMEPARAMETERS.draw_flight_path) { - this._last_position_drawn = []; - this._trace_objects_per_drone = []; + this._result_message = ""; + if (GAMEPARAMETERS.log_drone_flight) { // ! Be aware that the following functions relies on this log format: // - getLogEntries at Drone Simulator Log Page - // - getLogEntries at Dron Log Follower API + // - getLogEntries at Drone Log Follower API header_list = ["timestamp (ms)", "latitude (°)", "longitude (°)", "AMSL (m)", "rel altitude (m)", "yaw (°)", "ground speed (m/s)", "climb rate (m/s)"]; - for (drone = 0; drone < GAMEPARAMETERS.droneList.length; drone += 1) { + drone_count = GAMEPARAMETERS.map.drones.user.length + + GAMEPARAMETERS.map.drones.enemy.length; + for (drone = 0; drone < drone_count; drone += 1) { this._flight_log[drone] = []; this._flight_log[drone].push(header_list); this._log_count[drone] = 0; - this._last_position_drawn[drone] = null; - this._trace_objects_per_drone[drone] = []; } - this._colors = [ - new BABYLON.Color3(255, 165, 0), - new BABYLON.Color3(0, 0, 255), - new BABYLON.Color3(255, 0, 0), - new BABYLON.Color3(0, 255, 0), - new BABYLON.Color3(0, 128, 128), - new BABYLON.Color3(0, 0, 0), - new BABYLON.Color3(255, 255, 255), - new BABYLON.Color3(128, 128, 0), - new BABYLON.Color3(128, 0, 128), - new BABYLON.Color3(0, 0, 128) - ]; + if (GAMEPARAMETERS.draw_flight_path) { + this._last_position_drawn = []; + this._trace_objects_per_drone = []; + for (drone = 0; drone < drone_count; drone += 1) { + this._last_position_drawn[drone] = null; + this._trace_objects_per_drone[drone] = []; + } + this._colors = [ + new BABYLON.Color3(255, 165, 0), + new BABYLON.Color3(0, 0, 255), + new BABYLON.Color3(255, 0, 0), + new BABYLON.Color3(0, 255, 0), + new BABYLON.Color3(0, 128, 128), + new BABYLON.Color3(0, 0, 0), + new BABYLON.Color3(255, 255, 255), + new BABYLON.Color3(128, 128, 0), + new BABYLON.Color3(128, 0, 128), + new BABYLON.Color3(0, 0, 128) + ]; + } } this.APIs_dict = { - FixedWingDroneAPI: FixedWingDroneAPI/*, - DroneLogAPI: DroneLogAPI*/ + FixedWingDroneAPI: FixedWingDroneAPI, + EnemyDroneAPI: EnemyDroneAPI }; + if (this._game_parameters_json.debug_test_mode) { + console.log = function () { + baseLogFunction.apply(console, arguments); + var args = Array.prototype.slice.call(arguments); + for (var i = 0;i < args.length;i++) { + console_log += args[i] + "\n"; + } + }; + } } Object.defineProperty(GameManager.prototype, "gameParameter", { @@ -571,11 +756,15 @@ var GameManager = /** @class */ (function () { var gadget = this; return gadget._init() .push(function () { - return gadget._flight_log; + return { + 'message': gadget._result_message, + 'content': gadget._flight_log, + 'console_log': console_log + }; }); }; - GameManager.prototype.update = function () { + GameManager.prototype.update = function (fullscreen) { // time delta means that drone are updated every virtual second // This is fixed and must not be modified // otherwise, it will lead to different scenario results @@ -587,10 +776,8 @@ var GameManager = /** @class */ (function () { function triggerUpdateIfPossible() { if ((_this._canUpdate) && (_this.ongoing_update_promise === null) && (0 < _this.waiting_update_count)) { - _this.ongoing_update_promise = _this._update( - TIME_DELTA, - (_this.waiting_update_count === 1) - ).push(function () { + _this.ongoing_update_promise = _this._update(TIME_DELTA, fullscreen) + .push(function () { _this.waiting_update_count -= 1; _this.ongoing_update_promise = null; triggerUpdateIfPossible(); @@ -617,16 +804,98 @@ var GameManager = /** @class */ (function () { this._flight_log[drone._id].push(error.stack); }; - GameManager.prototype._checkDroneRules = function (drone) { - //TODO move this to API methods. - //each type of drone should define its rules - if (drone.getCurrentPosition()) { - return drone.getCurrentPosition().z > 1; + GameManager.prototype._checkDroneOut = function (drone) { + if (drone.position) { + var map_limit = this._mapManager.getMapInfo().map_size / 2; + return (drone.position.z > this._mapManager.getMapInfo().height) || + (drone.position.x < -map_limit) || + (drone.position.x > map_limit) || + (drone.position.y < -map_limit) || + (drone.position.y > map_limit); } - return false; }; - GameManager.prototype._update = function (delta_time) { + GameManager.prototype._checkObstacleCollision = function (drone, obstacle) { + var closest = void 0, projected = BABYLON.Vector3.Zero(); + if (drone.colliderMesh && + drone.colliderMesh.intersectsMesh(obstacle, true)) { + drone._internal_crash(new Error('Drone ' + drone.id + + ' touched an obstacle.')); + //Following workaround seems not needed with new babylonjs versions + /** + * Closest facet check is needed for sphere and cylinder, + * but just seemed bugged with the box + * So only need to check intersectMesh for the box + */ + /*if (obstacle.type == "box") { + closest = true; + } else { + obstacle.updateFacetData(); + closest = obstacle.getClosestFacetAtCoordinates( + drone.infosMesh.position.x, + drone.infosMesh.position.y, + drone.infosMesh.position.z, projected); + } + if (closest !== null) { + drone._internal_crash(new Error('Drone ' + drone.id + + ' touched an obstacle.')); + }*/ + } + }; + + GameManager.prototype._checkFlagCollision = function (drone, flag) { + if (drone.team == TEAM_ENEMY) return; + function distance(a, b) { + return Math.sqrt(Math.pow((a.x - b.x), 2) + Math.pow((a.y - b.y), 2) + + Math.pow((a.z - b.z), 2)); + } + if (drone.position) { + //TODO epsilon distance is 15 because of fixed wing loiter flights + //there is not a proper collision + if (distance(drone.position, flag.location) <= + this._mapManager.getMapInfo().flag_distance_epsilon) { + if (!flag.drone_collider_list.includes(drone.id)) { + //TODO notify the drone somehow? Or the AI script is in charge? + //console.log("flag " + flag.id + " hit by drone " + drone.id); + drone._internal_crash(new Error('Drone ' + drone.id + + ' touched a flag.')); + if (flag.drone_collider_list.length === 0) { + drone.score++; + flag.drone_collider_list.push(drone.id); + } + } + } + } + }; + + GameManager.prototype._checkCollision = function (drone, other) { + if (drone.colliderMesh && other.colliderMesh && + drone.colliderMesh.intersectsMesh(other.colliderMesh, false)) { + var angle = Math.acos(BABYLON.Vector3.Dot(drone.worldDirection, + other.worldDirection) / + (drone.worldDirection.length() * + other.worldDirection.length())); + //TODO is this parameter set? keep it or make 2 drones die when intersect? + if (angle < GAMEPARAMETERS.drone.collisionSector) { + if (drone.speed > other.speed) { + other._internal_crash(new Error('Drone ' + drone.id + + ' bump drone ' + other.id + '.')); + } + else { + drone._internal_crash(new Error('Drone ' + other.id + + ' bumped drone ' + drone.id + '.')); + } + } + else { + drone._internal_crash(new Error('Drone ' + drone.id + + ' touched drone ' + other.id + '.')); + other._internal_crash(new Error('Drone ' + drone.id + + ' touched drone ' + other.id + '.')); + } + } + }; + + GameManager.prototype._update = function (delta_time, fullscreen) { var _this = this, queue = new RSVP.Queue(), i; @@ -642,14 +911,48 @@ var GameManager = /** @class */ (function () { } } + if (fullscreen) { + //Only resize if size changes + if (this._canvas.width !== GAMEPARAMETERS.fullscreen.width) { + this._canvas.width = GAMEPARAMETERS.fullscreen.width; + this._canvas.height = GAMEPARAMETERS.fullscreen.height; + } + } else { + if (this._canvas.width !== this._canvas_width) { + this._canvas.width = this._canvas_width; + this._canvas.height = this._canvas_height; + this._engine.resize(true); + } + } + this._droneList.forEach(function (drone) { queue.push(function () { + var msg = ''; drone._tick += 1; - if (_this._checkDroneRules(drone)) { - return drone.internal_update(delta_time); + if (drone.can_play) { + if (drone.getCurrentPosition().z <= 0) { + drone._internal_crash(new Error('Drone ' + drone.id + + ' touched the floor.')); + } + else if (_this._checkDroneOut(drone)) { + drone._internal_crash(new Error('Drone ' + drone.id + + ' out of limits.')); + } + else { + _this._droneList.forEach(function (other) { + if (other.can_play && drone.id != other.id) { + _this._checkCollision(drone, other); + } + }); + _this._mapManager._obstacle_list.forEach(function (obstacle) { + _this._checkObstacleCollision(drone, obstacle); + }); + _this._mapManager._flag_list.forEach(function (flag) { + _this._checkFlagCollision(drone, flag); + }); + } } - //TODO error must be defined by the api? - drone._internal_crash('Drone touched the floor'); + return drone.internal_update(delta_time); }); }); @@ -657,10 +960,17 @@ var GameManager = /** @class */ (function () { .push(function () { if (_this._timeOut()) { console.log("TIMEOUT!"); + _this._result_message += "TIMEOUT!"; return _this._finish(); } if (_this._allDronesFinished()) { - console.log("ALL DRONES EXITED"); + console.log("ALL DRONES DOWN"); + _this._result_message += "ALL DRONES DOWN!"; + return _this._finish(); + } + if (_this._allFlagsCaptured()) { + console.log("ALL FLAGS CAPTURED"); + _this._result_message += "ALL FLAGS CAPTURED!"; return _this._finish(); } }); @@ -674,7 +984,7 @@ var GameManager = /** @class */ (function () { seconds = Math.floor(this._game_duration / 1000), trace_objects; if (GAMEPARAMETERS.log_drone_flight || GAMEPARAMETERS.draw_flight_path) { - this._droneList.forEach(function (drone, index) { + this._droneList_user.forEach(function (drone, index) { if (drone.can_play) { drone_position = drone.position; if (GAMEPARAMETERS.log_drone_flight) { @@ -687,8 +997,7 @@ var GameManager = /** @class */ (function () { geo_coordinates = map_manager.convertToGeoCoordinates( drone_position.x, drone_position.y, - drone_position.z, - map_info + drone_position.z ); game_manager._flight_log[index].push([ game_manager._game_duration, geo_coordinates.x, @@ -711,12 +1020,14 @@ var GameManager = /** @class */ (function () { position_obj.position = new BABYLON.Vector3(drone_position.x, drone_position.z, drone_position.y); + //TODO base it on map_size position_obj.scaling = new BABYLON.Vector3(4, 4, 4); material = new BABYLON.StandardMaterial(game_manager._scene); material.alpha = 1; color = new BABYLON.Color3(255, 0, 0); - if (game_manager._colors[index]) { - color = game_manager._colors[index]; + var color_index = index % 10; + if (game_manager._colors[color_index]) { + color = game_manager._colors[color_index]; } material.diffuseColor = color; position_obj.material = material; @@ -742,7 +1053,7 @@ var GameManager = /** @class */ (function () { GameManager.prototype._allDronesFinished = function () { var finish = true; - this._droneList.forEach(function (drone) { + this._droneList_user.forEach(function (drone) { if (drone.can_play) { finish = false; } @@ -750,8 +1061,31 @@ var GameManager = /** @class */ (function () { return finish; }; + GameManager.prototype._allFlagsCaptured = function () { + var finish = true; + this._mapManager._flag_list.forEach(function (flag) { + //do not use flag weight for now, just 1 hit is enough + if (flag.drone_collider_list.length === 0) { + //if (flag.drone_collider_list.length < flag.weight) { + finish = false; + } + }); + return finish; + }; + + GameManager.prototype._calculateUserScore = function () { + var score = 0; + this._droneList_user.forEach(function (drone) { + //if (drone.can_play) { + score += drone.score; + //} + }); + return score; + }; + GameManager.prototype._finish = function () { console.log("Simulation finished"); + this._result_message += " User score: " + this._calculateUserScore(); this._canUpdate = false; return this.finish_deferred.resolve(); }; @@ -763,7 +1097,8 @@ var GameManager = /** @class */ (function () { }; GameManager.prototype._init = function () { - var _this = this, canvas, hemi_north, hemi_south, camera, on3DmodelsReady; + var _this = this, + canvas, hemi_north, hemi_south, camera, cam_radius, on3DmodelsReady; canvas = this._canvas; this._delayed_defer_list = []; this._dispose(); @@ -775,6 +1110,9 @@ var GameManager = /** @class */ (function () { audioEngine: false }); this._scene = new BABYLON.Scene(this._engine); + //for DEBUG - fondo negro + //this._scene.clearColor = BABYLON.Color3.Black(); + //deep ground color - light blue simile sky this._scene.clearColor = new BABYLON.Color4( 88 / 255, 171 / 255, @@ -797,13 +1135,18 @@ var GameManager = /** @class */ (function () { this._scene ); hemi_south.intensity = 0.75; - camera = new BABYLON.ArcRotateCamera("camera", 0, 1.25, 800, + cam_radius = (GAMEPARAMETERS.map.map_size * 1.10 < 6000) ? + GAMEPARAMETERS.map.map_size * 1.10 : 6000; //skybox scene limit + camera = new BABYLON.ArcRotateCamera("camera", 0, 1.25, cam_radius, BABYLON.Vector3.Zero(), this._scene); camera.wheelPrecision = 10; + //zoom out limit + camera.upperRadiusLimit = GAMEPARAMETERS.map.map_size * 10; + //scene.activeCamera.upperRadiusLimit = max * 4; //changed for event handling //camera.attachControl(this._scene.getEngine().getRenderingCanvas()); //orig camera.attachControl(canvas, true); - camera.maxz = 40000; + camera.maxz = 400000; this._camera = camera; // Render loop @@ -819,8 +1162,9 @@ var GameManager = /** @class */ (function () { } // Init the map _this._mapManager = new MapManager(ctx._scene); - ctx._spawnDrones(_this._mapManager.map_info.initial_position, - GAMEPARAMETERS.droneList, ctx); + ctx._spawnDrones(_this._mapManager.getMapInfo().initial_position, + GAMEPARAMETERS.map.drones.user, TEAM_USER, ctx); + ctx._spawnDrones(null, GAMEPARAMETERS.map.drones.enemy, TEAM_ENEMY, ctx); // Hide the drone prefab DroneManager.Prefab.isVisible = false; //Hack to make advanced texture work @@ -833,23 +1177,37 @@ var GameManager = /** @class */ (function () { ctx._scene ); document = documentTmp; - for (count = 0; count < GAMEPARAMETERS.droneList.length; count += 1) { - controlMesh = ctx._droneList[count].infosMesh; - rect = new BABYLON.GUI.Rectangle(); - rect.width = "10px"; - rect.height = "10px"; - rect.cornerRadius = 20; - rect.color = "white"; - rect.thickness = 0.5; - rect.background = "grey"; - advancedTexture.addControl(rect); - label = new BABYLON.GUI.TextBlock(); - label.text = count.toString(); - label.fontSize = 7; - rect.addControl(label); - rect.linkWithMesh(controlMesh); - rect.linkOffsetY = 0; + function colourDrones(drone_list, colour) { + for (count = 0; count < drone_list.length; count += 1) { + controlMesh = drone_list[count].infosMesh; + rect = new BABYLON.GUI.Rectangle(); + rect.width = "10px"; + rect.height = "10px"; + rect.cornerRadius = 20; + rect.color = "white"; + rect.thickness = 0.5; + rect.background = colour; + advancedTexture.addControl(rect); + rect.linkWithMesh(controlMesh); + } } + function colourFlags(flag_list) { + for (count = 0; count < flag_list.length; count += 1) { + controlMesh = flag_list[count].subMeshes[0]._mesh; + rect = new BABYLON.GUI.Rectangle(); + rect.width = "15px"; + rect.height = "10px"; + rect.cornerRadius = 1; + rect.color = "white"; + rect.thickness = 0.5; + rect.background = "green"; + advancedTexture.addControl(rect); + rect.linkWithMesh(controlMesh); + } + } + colourFlags(_this._mapManager._flag_list); + colourDrones(ctx._droneList_user, "blue"); + colourDrones(ctx._droneList_enemy, "red"); console.log("on3DmodelsReady - advaced textures added"); return ctx; }; @@ -862,6 +1220,8 @@ var GameManager = /** @class */ (function () { }) .push(function () { on3DmodelsReady(_this); + _this._droneList = + _this._droneList_user.concat(_this._droneList_enemy); var result = new RSVP.Queue(); result.push(function () { return RSVP.delay(1000); @@ -871,7 +1231,7 @@ var GameManager = /** @class */ (function () { }; GameManager.prototype._start = function () { - var _this = this, promise_list; + var _this = this, promise_list, start_msg; _this.waiting_update_count = 0; _this.ongoing_update_promise = null; _this.finish_deferred = RSVP.defer(); @@ -882,11 +1242,17 @@ var GameManager = /** @class */ (function () { return new RSVP.Queue() .push(function () { promise_list = []; - _this._droneList.forEach(function (drone) { + _this._droneList_user.forEach(function (drone) { + drone._tick = 0; + promise_list.push(drone.internal_start()); + }); + start_msg = { + 'flag_positions': _this._mapManager.getMapInfo().geo_flag_list + }; + promise_list.push(_this._droneList_user[0].sendMsg(start_msg)); + _this._droneList_enemy.forEach(function (drone) { drone._tick = 0; - promise_list.push(drone.internal_start( - _this._mapManager.getMapInfo().initial_position - )); + promise_list.push(drone.internal_start()); }); return RSVP.all(promise_list); }) @@ -941,9 +1307,10 @@ var GameManager = /** @class */ (function () { return parameter; }; - GameManager.prototype._spawnDrones = function (center, drone_list, ctx) { + GameManager.prototype._spawnDrones = function (init_position, drone_list, + team, ctx, drone_location) { var position, i, position_list = [], max_collision = 10 * drone_list.length, - collision_nb = 0, api; + collision_nb = 0, api, center; function checkCollision(position, list) { var el; for (el = 0; el < list.length; el += 1) { @@ -953,7 +1320,7 @@ var GameManager = /** @class */ (function () { } return false; } - function spawnDrone(x, y, z, index, drone_info, api) { + function spawnDrone(x, y, z, index, drone_info, api, team) { var default_drone_AI = api.getDroneAI(), code, base, code_eval; if (default_drone_AI) { code = default_drone_AI; @@ -961,9 +1328,9 @@ var GameManager = /** @class */ (function () { code = drone_info.script_content; } code_eval = "let drone = new DroneManager(ctx._scene, " + - index + ', api);' + + index + ', api, team);' + "let droneMe = function(NativeDate, me, Math, window, DroneManager," + - " GameManager, FixedWingDroneAPI, BABYLON, " + + " GameManager, FixedWingDroneAPI, EnemyDroneAPI, BABYLON, " + "GAMEPARAMETERS) {" + "var start_time = (new Date(2070, 0, 0, 0, 0, 0, 0)).getTime();" + "Date.now = function () {" + @@ -980,8 +1347,8 @@ var GameManager = /** @class */ (function () { } base = code_eval; code_eval += code + "}; droneMe(Date, drone, Math, {});"; - base += "};ctx._droneList.push(drone)"; - code_eval += "ctx._droneList.push(drone)"; + base += "};ctx._droneList_" + team + ".push(drone)"; + code_eval += "ctx._droneList_" + team + ".push(drone)"; /*jslint evil: true*/ try { eval(code_eval); @@ -1001,6 +1368,11 @@ var GameManager = /** @class */ (function () { return new BABYLON.Vector3(x, y, z); } for (i = 0; i < drone_list.length; i += 1) { + if (!init_position) { + center = drone_list[i].position; + } else { + center = init_position; + } position = randomSpherePoint(center.x + i, center.y + i, center.z + i, 0, 0, 0); if (checkCollision(position, position_list)) { @@ -1010,14 +1382,18 @@ var GameManager = /** @class */ (function () { } } else { position_list.push(position); + var id_offset = 0; + if (team == TEAM_ENEMY) { + id_offset = GAMEPARAMETERS.map.drones.user.length; + } api = new this.APIs_dict[drone_list[i].type]( this, drone_list[i], GAMEPARAMETERS, - i + i + id_offset ); - spawnDrone(position.x, position.y, position.z, i, - drone_list[i], api); + spawnDrone(position.x, position.y, position.z, i + id_offset, + drone_list[i], api, team); } } }; @@ -1043,15 +1419,15 @@ var runGame, updateGame; return game_manager_instance.run(); }; - updateGame = function () { + updateGame = function (fullscreen) { if (game_manager_instance) { - return game_manager_instance.update(); + return game_manager_instance.update(fullscreen); } }; /*// Resize canvas on window resize window.addEventListener('resize', function () { - engine.resize(); + game_manager_instance._engine.resize(); });*/ diff --git a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_logic_js.xml b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_logic_js.xml index 16a01b32e042c25599decf8db9d8dc087e4c8f9f..8badaa2df1a903c1ae7a6d8d7f813de647ca4a56 100644 --- a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_logic_js.xml +++ b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/drone_capture_flag_logic_js.xml @@ -246,7 +246,7 @@ </item> <item> <key> <string>serial</string> </key> - <value> <string>1007.63308.6371.35532</string> </value> + <value> <string>1010.5086.1058.34440</string> </value> </item> <item> <key> <string>state</string> </key> @@ -266,7 +266,7 @@ </tuple> <state> <tuple> - <float>1682437964.37</float> + <float>1690567567.2</float> <string>UTC</string> </tuple> </state> diff --git a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_html.html b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_html.html index a1735dc02102b321a11ef46a567a257989d8d857..261062f13a37f80653d1053a86197014fe175498 100644 --- a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_html.html +++ b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_html.html @@ -18,6 +18,7 @@ <script src="jiodev.js" type="text/javascript"></script> <script src="gadget_global.js" type="text/javascript"></script> <script src="domsugar.js" type="text/javascript"></script> + <script type="text/javascript" src="./libraries/seedrandom.min.js"></script> <script src="gadget_erp5_page_drone_capture_flag_script_page.js" type="text/javascript"></script> diff --git a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_html.xml b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_html.xml index f9fb06b19adeb4f66264f4c621c9f1959e7041b8..3b4c055041ba0b1f2367c0c1437fced367a1b0f4 100644 --- a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_html.xml +++ b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_html.xml @@ -244,7 +244,7 @@ </item> <item> <key> <string>serial</string> </key> - <value> <string>1007.63297.49586.20838</string> </value> + <value> <string>1008.22253.2281.60074</string> </value> </item> <item> <key> <string>state</string> </key> @@ -264,7 +264,7 @@ </tuple> <state> <tuple> - <float>1682436612.47</float> + <float>1683820259.6</float> <string>UTC</string> </tuple> </state> diff --git a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_js.js b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_js.js index 3d7298c3546088dc136211f0be4e8e9ddc5a638c..a09bf696a788125a308cf6a9d4d0d3c80ed03fd5 100644 --- a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_js.js +++ b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_js.js @@ -1,16 +1,13 @@ /*jslint indent: 2, maxlen: 100*/ -/*global window, rJS, domsugar, document, Blob*/ -(function (window, rJS, domsugar, document, Blob) { +/*global window, rJS, domsugar, document, URLSearchParams, Blob*/ +(function (window, rJS, domsugar, document, URLSearchParams, Blob) { "use strict"; - //Default values - TODO: get them from the drone API - var SIMULATION_SPEED = 200, - SIMULATION_TIME = 1500, - min_lat = 45.6364, - max_lat = 45.65, - min_lon = 14.2521, - max_lon = 14.2766, - map_height = 100, + //Drone default values - TODO: get them from the drone API + var SIMULATION_SPEED = 10, + SIMULATION_TIME = 270, + MAP_SIZE = 600, + map_height = 700, start_AMSL = 595, DEFAULT_SPEED = 16, MAX_ACCELERATION = 6, @@ -22,65 +19,20 @@ MAX_PITCH = 25, MAX_CLIMB_RATE = 8, MAX_SINK_RATE = 3, - INITIAL_POSITION = { - "latitude": 45.6412, - "longitude": 14.2658, - "z": 15 - }, - NUMBER_OF_DRONES = 2, + NUMBER_OF_DRONES = 10, + FLAG_WEIGHT = 5, + SEED = '6', // Non-inputs parameters DEFAULT_SCRIPT_CONTENT = - 'var ALTITUDE = 100,\n' + - ' EPSILON = 9,\n' + - ' CHECKPOINT_LIST = [\n' + - ' {\n' + - ' altitude: 585.1806861589965,\n' + - ' latitude: 45.64492790560583,\n' + - ' longitude: 14.25334942966329\n' + - ' },\n' + - ' {\n' + - ' altitude: 589.8802607573035,\n' + - ' latitude: 45.64316335436476,\n' + - ' longitude: 14.26332880184475\n' + - ' },\n' + - ' {\n' + - ' altitude: 608.6648153348965,\n' + - ' latitude: 45.64911917196595,\n' + - ' longitude: 14.26214792790128\n' + - ' },\n' + - ' {\n' + - ' altitude: 606.1448368129072,\n' + - ' latitude: 45.64122685351364,\n' + - ' longitude: 14.26590493128597\n' + - ' },\n' + - ' {\n' + - ' altitude: 630.0829598206344,\n' + - ' latitude: 45.64543355564817,\n' + - ' longitude: 14.27242391207985\n' + - ' },\n' + - ' {\n' + - ' altitude: 616.1839898415284,\n' + - ' latitude: 45.6372792927328,\n' + - ' longitude: 14.27533492411138\n' + - ' },\n' + - ' {\n' + - ' altitude: 598.0603137354178,\n' + - ' latitude: 45.64061299543953,\n' + - ' longitude: 14.26161958465814\n' + - ' },\n' + - ' {\n' + - ' altitude: 607.1243119862851,\n' + - ' latitude: 45.64032340702919,\n' + - ' longitude: 14.2682896662383\n' + - ' }\n' + - ' ];\n' + + 'var EPSILON = 15,\n' + + ' DODGE_DISTANCE = 100;\n' + '\n' + - 'function distance(lat1, lon1, lat2, lon2) {\n' + + 'function distance(a, b) {\n' + ' var R = 6371e3, // meters\n' + - ' la1 = lat1 * Math.PI / 180, // lat, lon in radians\n' + - ' la2 = lat2 * Math.PI / 180,\n' + - ' lo1 = lon1 * Math.PI / 180,\n' + - ' lo2 = lon2 * Math.PI / 180,\n' + + ' la1 = a.x * Math.PI / 180, // lat, lon in radians\n' + + ' la2 = b.x * Math.PI / 180,\n' + + ' lo1 = a.y * Math.PI / 180,\n' + + ' lo2 = b.y * Math.PI / 180,\n' + ' haversine_phi = Math.pow(Math.sin((la2 - la1) / 2), 2),\n' + ' sin_lon = Math.sin((lo2 - lo1) / 2),\n' + ' h = haversine_phi + Math.cos(la1) * Math.cos(la2) * sin_lon * sin_lon;\n' + @@ -89,49 +41,88 @@ '\n' + 'me.onStart = function () {\n' + ' me.direction_set = false;\n' + - ' me.next_checkpoint = 0;\n' + + ' me.dodging = false;\n' + + ' me.ongoing_detection = false;\n' + '};\n' + '\n' + - 'me.onUpdate = function (timestamp) {' + + 'me.onGetMsg = function (msg) {\n' + + ' if (msg && msg.flag_positions) {\n' + + ' me.flag_positions = msg.flag_positions\n' + + ' me.next_checkpoint = me.id % me.flag_positions.length;\n' + + ' }\n' + + '};\n' + + '\n' + + 'me.onUpdate = function (timestamp) {\n' + + ' if (!me.flag_positions) return;\n' + + ' if (me.dodging) {\n' + + ' me.current_position = me.getCurrentPosition();\n' + + ' var dist = distance(\n' + + ' me.current_position,\n' + + ' me.dodging.position\n' + + ' );\n' + + ' if (dist >= DODGE_DISTANCE) {\n' + + //' console.log("Good distance to obstacle. DODGED.");\n' + + ' me.dodging = false;\n' + + ' }\n' + + ' return;\n' + + ' }\n' + ' if (!me.direction_set) {\n' + - ' if (me.next_checkpoint < CHECKPOINT_LIST.length) {\n' + + ' if (me.next_checkpoint < me.flag_positions.length) {\n' + ' me.setTargetCoordinates(\n' + - ' CHECKPOINT_LIST[me.next_checkpoint].latitude,\n' + - ' CHECKPOINT_LIST[me.next_checkpoint].longitude,\n' + - ' CHECKPOINT_LIST[me.next_checkpoint].altitude + ALTITUDE + ALTITUDE * me.id\n' + + ' me.flag_positions[me.next_checkpoint].x,\n' + + ' me.flag_positions[me.next_checkpoint].y,\n' + + ' me.flag_positions[me.next_checkpoint].z + me.id\n' + ' );\n' + - ' console.log("[DEMO] Going to Checkpoint %d", me.next_checkpoint);\n' + + //' console.log("[DEMO] Going to Checkpoint %d", me.next_checkpoint);\n' + ' }\n' + ' me.direction_set = true;\n' + ' return;\n' + ' }\n' + - ' if (me.next_checkpoint < CHECKPOINT_LIST.length) {\n' + + ' if (me.next_checkpoint < me.flag_positions.length) {\n' + + ' if (!me.ongoing_detection) {\n' + + ' me.getDroneViewInfo();\n' + + ' me.ongoing_detection = true;\n' + + ' }\n' + + ' }\n' + + ' if (me.next_checkpoint < me.flag_positions.length) {\n' + ' me.current_position = me.getCurrentPosition();\n' + ' me.distance = distance(\n' + - ' me.current_position.x,\n' + - ' me.current_position.y,\n' + - ' CHECKPOINT_LIST[me.next_checkpoint].latitude,\n' + - ' CHECKPOINT_LIST[me.next_checkpoint].longitude\n' + + ' me.current_position,\n' + + ' me.flag_positions[me.next_checkpoint]\n' + ' );\n' + ' if (me.distance <= EPSILON) {\n' + - ' console.log("[DEMO] Reached Checkpoint %d", me.next_checkpoint);\n' + + //' console.log("[DEMO] Reached Checkpoint %d", me.next_checkpoint);\n' + ' me.next_checkpoint += 1;\n' + ' me.direction_set = false;\n' + ' }\n' + ' return;\n' + ' }\n' + - ' me.exit(0);\n' + + '};\n' + + '\n' + + 'me.onDroneViewInfo = function (drone_view) {\n' + + ' me.ongoing_detection = false;\n' + + ' if (drone_view && drone_view.obstacles && drone_view.obstacles.length) {\n' + + ' me.dodging = drone_view.obstacles[0];\n' + + ' me.direction_set = false;\n' + + ' var random = Math.random() < 0.5, dodge_point = {};\n' + + ' Object.assign(dodge_point, me.flag_positions[me.next_checkpoint]);\n' + + ' if (random) {\n' + + ' dodge_point.x = dodge_point.x * -1;\n' + + ' } else {\n' + + ' dodge_point.y = dodge_point.y * -1;\n' + + ' }\n' + + ' me.setTargetCoordinates(dodge_point.x, dodge_point.y, me.getCurrentPosition().z);\n' + + ' return;\n' + + ' }\n' + '};', DRAW = true, LOG = true, LOG_TIME = 1662.7915426540285, DRONE_LIST = [], - WIDTH = 680, - HEIGHT = 340, LOGIC_FILE_LIST = [ 'gadget_erp5_page_drone_capture_flag_logic.js', - 'gadget_erp5_page_drone_capture_flag_fixedwingdrone.js'/*, - 'gadget_erp5_page_drone_capture_flag_dronelogfollower.js'*/ + 'gadget_erp5_page_drone_capture_flag_fixedwingdrone.js', + 'gadget_erp5_page_drone_capture_flag_enemydrone.js' ]; rJS(window) @@ -161,7 +152,8 @@ }) .declareMethod('render', function render() { - var gadget = this; + var gadget = this, url_sp = new URLSearchParams(window.location.hash), + url_seed = url_sp.get("seed"); return gadget.getDeclaredGadget('form_view') .push(function (form_gadget) { return form_gadget.render({ @@ -299,60 +291,38 @@ "hidden": 0, "type": "FloatField" }, - "my_minimum_latitud": { + "my_map_size": { "description": "", - "title": "Minimum latitude", - "default": min_lat, + "title": "Map size", + "default": MAP_SIZE, "css_class": "", "required": 1, "editable": 1, - "key": "min_lat", + "key": "map_size", "hidden": 0, "type": "FloatField" }, - "my_maximum_latitud": { - "description": "", - "title": "Maximum latitude", - "default": max_lat, - "css_class": "", - "required": 1, - "editable": 1, - "key": "max_lat", - "hidden": 0, - "type": "FloatField" - }, - "my_minimum_longitud": { + "my_start_AMSL": { "description": "", - "title": "Minimum longitude", - "default": min_lon, + "title": "Start AMSL", + "default": start_AMSL, "css_class": "", "required": 1, "editable": 1, - "key": "min_lon", + "key": "start_AMSL", "hidden": 0, "type": "FloatField" }, - "my_maximum_longitud": { - "description": "", - "title": "Maximum longitude", - "default": max_lon, + "my_map_seed": { + "description": "Seed value to randomize the map", + "title": "Seed value", + "default": url_seed ? url_seed : SEED, "css_class": "", "required": 1, "editable": 1, - "key": "max_lon", + "key": "map_seed", "hidden": 0, - "type": "FloatField" - }, - "my_start_AMSL": { - "description": "", - "title": "Start AMSL", - "default": start_AMSL, - "css_class": "", - "required": 1, - "editable": 1, - "key": "start_AMSL", - "hidden": 0, - "type": "FloatField" + "type": "StringField" }, "my_map_height": { "description": "", @@ -365,39 +335,17 @@ "hidden": 0, "type": "IntegerField" }, - "my_init_pos_lon": { - "description": "", - "title": "Initial drone longitude", - "default": INITIAL_POSITION.longitude, - "css_class": "", - "required": 1, - "editable": 1, - "key": "init_pos_lon", - "hidden": 0, - "type": "FloatField" - }, - "my_init_pos_lat": { + /*"my_flag_weight": { "description": "", - "title": "Initial drone latitude", - "default": INITIAL_POSITION.latitude, + "title": "Flag Weight", + "default": FLAG_WEIGHT, "css_class": "", "required": 1, "editable": 1, - "key": "init_pos_lat", + "key": "flag_weight", "hidden": 0, - "type": "FloatField" - }, - "my_init_pos_z": { - "description": "", - "title": "Initial drone position Z", - "default": INITIAL_POSITION.z, - "css_class": "", - "required": 1, - "editable": 1, - "key": "init_pos_z", - "hidden": 0, - "type": "FloatField" - }, + "type": "IntegerField" + },*/ "my_number_of_drones": { "description": "", "title": "Number of drones", @@ -432,13 +380,11 @@ group_list: [[ "left", [["my_simulation_speed"], ["my_simulation_time"], ["my_number_of_drones"], - ["my_minimum_latitud"], ["my_maximum_latitud"], - ["my_minimum_longitud"], ["my_maximum_longitud"], - ["my_init_pos_lat"], ["my_init_pos_lon"], ["my_init_pos_z"], - ["my_map_height"]] + ["my_map_size"], ["my_map_height"],// ["my_flag_weight"], + ["my_start_AMSL"], ["my_map_seed"]] ], [ "right", - [["my_start_AMSL"], ["my_drone_min_speed"], ["my_drone_speed"], ["my_drone_max_speed"], + [["my_drone_min_speed"], ["my_drone_speed"], ["my_drone_max_speed"], ["my_drone_max_acceleration"], ["my_drone_max_deceleration"], ["my_drone_max_roll"], ["my_drone_min_pitch"], ["my_drone_max_pitch"], ["my_drone_max_sink_rate"], ["my_drone_max_climb_rate"]] @@ -460,14 +406,119 @@ .declareJob('runGame', function runGame(options) { var gadget = this, i, fragment = gadget.element.querySelector('.simulator_div'), - game_parameters_json; + game_parameters_json, map_json; + DRONE_LIST = []; fragment = domsugar(gadget.element.querySelector('.simulator_div'), [domsugar('div')]).firstElementChild; - DRONE_LIST = []; for (i = 0; i < options.number_of_drones; i += 1) { DRONE_LIST[i] = {"id": i, "type": "FixedWingDroneAPI", "script_content": options.script}; } + + function randomizeMap(json_map) { + function randomIntFromInterval(min, max, random_seed) { + return Math.floor(random_seed.quick() * (max - min + 1) + min); + } + function randomPosition(random_seed, map_size) { + var sign_x = random_seed.quick() < 0.5 ? -1 : 1, + sign_y = random_seed.quick() < 0.5 ? -1 : 1, + pos_x = sign_x * random_seed.quick() * map_size / 2, + pos_y = sign_y * random_seed.quick() * map_size / 2; + return [pos_x, pos_y]; + } + var seed_value = options.map_seed, + random_seed = new Math.seedrandom(seed_value), i, + n_enemies = randomIntFromInterval(5, 10, random_seed), + n_flags = randomIntFromInterval(Math.floor(DRONE_LIST.length / 2), + DRONE_LIST.length, random_seed), + n_obstacles = randomIntFromInterval(5, 15, random_seed), + flag_list = [], obstacle_list = [], enemy_list = [], random_position, + obstacles_types = ["box"/*, "sphere"*/, "cylinder"], type, + obstacle_limit = [options.map_size / 6, options.map_size / 100, + options.map_size / 6, 30]; + //enemies + for (i = 0; i < n_enemies; i += 1) { + random_position = randomPosition(random_seed, options.map_size); + enemy_list.push({ + "id": i + parseInt(options.number_of_drones), + "type": "EnemyDroneAPI", + "position": { + "x": random_position[0], + "y": random_position[1], + "z": 15 //TODO random z? + } + }); + } + //flags + for (i = 0; i < n_flags; i += 1) { + //avoid flags near the limits + random_position = randomPosition(random_seed, options.map_size * 0.75); + flag_list.push({ + "position": { + "x": random_position[0], + "y": random_position[1], + "z": 10 + } + }); + } + function checkDistance(position, position_list) { + function distance(a, b) { + return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2); + } + var el; + for (el = 0; el < position_list.length; el += 1) { + if (distance(position, position_list[el].position) < options.map_size / 6) { + return true; + } + } + return false; + } + //obstacles + for (i = 0; i < n_obstacles; i += 1) { + random_position = randomPosition(random_seed, options.map_size); + if (checkDistance({ 'x': random_position[0], + 'y': random_position[1]}, flag_list)) { + i -= 1; + } else { + type = randomIntFromInterval(0, 2, random_seed); + obstacle_list.push({ + "type": obstacles_types[type], + "position": { + "x": random_position[0], + "y": random_position[1], + "z": 15 //TODO random z? + }, + "scale": { + "x": randomIntFromInterval(20, obstacle_limit[type], random_seed), + "y": randomIntFromInterval(20, obstacle_limit[type], random_seed), + "z": randomIntFromInterval(5, obstacle_limit[3], random_seed) + }, + "rotation": { + "x": 0, + "y": 0, + "z": 0 + } + }); + } + } + json_map.obstacle_list = obstacle_list; + json_map.drones.enemy = enemy_list; + json_map.flag_list = flag_list; + return json_map; + } + + map_json = { + "map_size": parseFloat(options.map_size), + "height": parseInt(options.map_height, 10), + "start_AMSL": parseFloat(options.start_AMSL), + "flag_list": [], + "obstacle_list" : [], + "drones": { + "user": DRONE_LIST, + "enemy": [] + } + }; + game_parameters_json = { "drone": { "maxAcceleration": parseInt(options.drone_max_acceleration, 10), @@ -487,24 +538,11 @@ "information": 0, "communication": 0 }, - "map": { - "min_lat": parseFloat(options.min_lat), - "max_lat": parseFloat(options.max_lat), - "min_lon": parseFloat(options.min_lon), - "max_lon": parseFloat(options.max_lon), - "height": parseInt(options.map_height, 10), - "start_AMSL": parseFloat(options.start_AMSL) - }, - "initialPosition": { - "longitude": parseFloat(options.init_pos_lon), - "latitude": parseFloat(options.init_pos_lat), - "z": parseFloat(options.init_pos_z) - }, + "map": randomizeMap(map_json), "draw_flight_path": DRAW, "temp_flight_path": true, "log_drone_flight": LOG, - "log_interval_time": LOG_TIME, - "droneList": DRONE_LIST + "log_interval_time": LOG_TIME }; return gadget.declareGadget("babylonjs.gadget.html", {element: fragment, scope: 'simulator'}) @@ -525,8 +563,7 @@ "type": "GadgetField", "url": "babylonjs.gadget.html", "sandbox": "public", - "renderjs_extra": '{"autorun": false, "width": ' + WIDTH + ', ' + - '"height": ' + HEIGHT + ', ' + + "renderjs_extra": '{"autorun": false, ' + '"logic_file_list": ' + JSON.stringify(LOGIC_FILE_LIST) + ', ' + '"game_parameters": ' + JSON.stringify(game_parameters_json) + '}' @@ -553,35 +590,44 @@ return form_gadget.getContent(); }) .push(function (result) { - var a, blob, div, key, log, log_content; + var a, blob, div, key, log, log_content, aux; i = 0; - for (key in result) { - if (result.hasOwnProperty(key)) { - log_content = result[key].join('\n').replaceAll(",", ";"); + div = domsugar('div', { text: result.message }); + document.querySelector('.container').parentNode.appendChild(div); + for (key in result.content) { + if (result.content.hasOwnProperty(key)) { + log_content = result.content[key].join('\n').replaceAll(",", ";"); blob = new Blob([log_content], {type: 'text/plain'}); a = domsugar('a', { text: 'Download Simulation LOG ' + i, - download: 'simulation_log_' + i - + '_speed_' + game_parameters_json.drone.speed - + '_min-speed_' + game_parameters_json.drone.minSpeed - + '_max-speed_' + game_parameters_json.drone.maxSpeed - + '_max-accel_' + game_parameters_json.drone.maxAcceleration - + '_max-decel_' + game_parameters_json.drone.maxDeceleration - + '_max-roll_' + game_parameters_json.drone.maxRoll - + '_min-pitch_' + game_parameters_json.drone.minPitchAngle - + '_max-pitch_' + game_parameters_json.drone.maxPitchAngle - + '_max-sink_' + game_parameters_json.drone.maxSinkRate - + '_max-climb_' + game_parameters_json.drone.maxClimbRate - + '.txt', + download: 'simulation_log_' + i + + '_speed_' + game_parameters_json.drone.speed + + '_min-speed_' + game_parameters_json.drone.minSpeed + + '_max-speed_' + game_parameters_json.drone.maxSpeed + + '_max-accel_' + game_parameters_json.drone.maxAcceleration + + '_max-decel_' + game_parameters_json.drone.maxDeceleration + + '_max-roll_' + game_parameters_json.drone.maxRoll + + '_min-pitch_' + game_parameters_json.drone.minPitchAngle + + '_max-pitch_' + game_parameters_json.drone.maxPitchAngle + + '_max-sink_' + game_parameters_json.drone.maxSinkRate + + '_max-climb_' + game_parameters_json.drone.maxClimbRate + + '.txt', href: window.URL.createObjectURL(blob) }); - log = domsugar('textarea', { value: log_content, id: 'log_result_' + i }); + log = domsugar('textarea', + { value: log_content, id: 'log_result_' + i }); div = domsugar('div', [a]); a.dataset.downloadurl = ['text/plain', a.download, a.href].join(':'); - document.querySelector('.container').appendChild(div); - document.querySelector('.container').appendChild(log); + document.querySelector('.container').parentNode.appendChild(div); + document.querySelector('.container').parentNode.appendChild(log); i += 1; + if (i === DRONE_LIST.length) { + break; + //Do not show enemy drone logs for now + /*aux = domsugar('div', { text: "Enemy drones logs:" }); + document.querySelector('.container').parentNode.appendChild(aux);*/ + } } } }, function (error) { @@ -590,4 +636,4 @@ }); }); -}(window, rJS, domsugar, document, Blob)); \ No newline at end of file +}(window, rJS, domsugar, document, URLSearchParams, Blob)); \ No newline at end of file diff --git a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_js.xml b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_js.xml index f289d7c6eb7c768cb19a3a9b21d0df3b4c8968a5..e577a837a4405c956cc862fba0497fb06d2e3c99 100644 --- a/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_js.xml +++ b/bt5/erp5_officejs_drone_capture_flag/PathTemplateItem/web_page_module/ojs_drone_capture_flag_script_page_js.xml @@ -246,7 +246,7 @@ </item> <item> <key> <string>serial</string> </key> - <value> <string>1007.63299.40871.39799</string> </value> + <value> <string>1009.57725.14056.1911</string> </value> </item> <item> <key> <string>state</string> </key> @@ -266,7 +266,7 @@ </tuple> <state> <tuple> - <float>1682437874.39</float> + <float>1689793877.59</float> <string>UTC</string> </tuple> </state> diff --git a/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/assets/map/terrain.jpg.jpg b/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/assets/map/terrain.jpg.jpg index ded8ef17f20055d0fdc9ebd5eb23bc5b3547ac03..2620ca01daa08896d28e7f24bd1d8c639dbd58dc 100644 Binary files a/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/assets/map/terrain.jpg.jpg and b/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/assets/map/terrain.jpg.jpg differ diff --git a/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/assets/map/terrain.jpg.xml b/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/assets/map/terrain.jpg.xml index 4cc82e4c603ab402fb51d5d43a436ecfab2f5f37..88cde27e831d098e5c9edfd082157554d34f68ec 100644 --- a/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/assets/map/terrain.jpg.xml +++ b/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/assets/map/terrain.jpg.xml @@ -16,7 +16,7 @@ </item> <item> <key> <string>height</string> </key> - <value> <int>512</int> </value> + <value> <int>1024</int> </value> </item> <item> <key> <string>precondition</string> </key> @@ -28,7 +28,7 @@ </item> <item> <key> <string>width</string> </key> - <value> <int>512</int> </value> + <value> <int>1024</int> </value> </item> </dictionary> </pickle> diff --git a/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/libraries.xml b/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/libraries.xml new file mode 100644 index 0000000000000000000000000000000000000000..f3a8eab5f9153f8ba30df2cff5df497814514b2b --- /dev/null +++ b/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/libraries.xml @@ -0,0 +1,26 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="Folder" module="OFS.Folder"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>_objects</string> </key> + <value> + <tuple/> + </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>libraries</string> </value> + </item> + <item> + <key> <string>title</string> </key> + <value> <string></string> </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/libraries/seedrandom.min.js.js b/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/libraries/seedrandom.min.js.js new file mode 100644 index 0000000000000000000000000000000000000000..5cc872e11a572fb30aac0b49afe17cf133003c9e --- /dev/null +++ b/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/libraries/seedrandom.min.js.js @@ -0,0 +1 @@ +!function(f,a,c){var s,l=256,p="random",d=c.pow(l,6),g=c.pow(2,52),y=2*g,h=l-1;function n(n,t,r){function e(){for(var n=u.g(6),t=d,r=0;n<g;)n=(n+r)*l,t*=l,r=u.g(1);for(;y<=n;)n/=2,t/=2,r>>>=1;return(n+r)/t}var o=[],i=j(function n(t,r){var e,o=[],i=typeof t;if(r&&"object"==i)for(e in t)try{o.push(n(t[e],r-1))}catch(n){}return o.length?o:"string"==i?t:t+"\0"}((t=1==t?{entropy:!0}:t||{}).entropy?[n,S(a)]:null==n?function(){try{var n;return s&&(n=s.randomBytes)?n=n(l):(n=new Uint8Array(l),(f.crypto||f.msCrypto).getRandomValues(n)),S(n)}catch(n){var t=f.navigator,r=t&&t.plugins;return[+new Date,f,r,f.screen,S(a)]}}():n,3),o),u=new m(o);return e.int32=function(){return 0|u.g(4)},e.quick=function(){return u.g(4)/4294967296},e.double=e,j(S(u.S),a),(t.pass||r||function(n,t,r,e){return e&&(e.S&&v(e,u),n.state=function(){return v(u,{})}),r?(c[p]=n,t):n})(e,i,"global"in t?t.global:this==c,t.state)}function m(n){var t,r=n.length,u=this,e=0,o=u.i=u.j=0,i=u.S=[];for(r||(n=[r++]);e<l;)i[e]=e++;for(e=0;e<l;e++)i[e]=i[o=h&o+n[e%r]+(t=i[e])],i[o]=t;(u.g=function(n){for(var t,r=0,e=u.i,o=u.j,i=u.S;n--;)t=i[e=h&e+1],r=r*l+i[h&(i[e]=i[o=h&o+t])+(i[o]=t)];return u.i=e,u.j=o,r})(l)}function v(n,t){return t.i=n.i,t.j=n.j,t.S=n.S.slice(),t}function j(n,t){for(var r,e=n+"",o=0;o<e.length;)t[h&o]=h&(r^=19*t[h&o])+e.charCodeAt(o++);return S(t)}function S(n){return String.fromCharCode.apply(0,n)}if(j(c.random(),a),"object"==typeof module&&module.exports){module.exports=n;try{s=require("crypto")}catch(n){}}else"function"==typeof define&&define.amd?define(function(){return n}):c["seed"+p]=n}("undefined"!=typeof self?self:this,[],Math); diff --git a/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/libraries/seedrandom.min.js.xml b/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/libraries/seedrandom.min.js.xml new file mode 100644 index 0000000000000000000000000000000000000000..ae51021f95c5723bfedfc501c57f801931a8dad5 --- /dev/null +++ b/bt5/erp5_officejs_drone_capture_flag/SkinTemplateItem/portal_skins/erp5_drone_capture_flag/libraries/seedrandom.min.js.xml @@ -0,0 +1,28 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="File" module="OFS.Image"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>__name__</string> </key> + <value> <string>seedrandom.min.js</string> </value> + </item> + <item> + <key> <string>content_type</string> </key> + <value> <string>application/javascript</string> </value> + </item> + <item> + <key> <string>precondition</string> </key> + <value> <string></string> </value> + </item> + <item> + <key> <string>title</string> </key> + <value> <string></string> </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData>