content/hifi-content/brosche/DomainContent/Rust/DJ-Tools/DJ_Dispatch_Zone_Server.js
2022-02-13 21:50:01 +01:00

460 lines
16 KiB
JavaScript

// DJ_Dispatch_Zone_Server.js
//
// Created by Milad Nazeri on 2018-06-19
//
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// Dispatcher that manages Generators(things that create data), Sensors(things that take that data and normalize it),
// Endpoints(Where the disptach will send to Sensors input)
(function () {
// Polyfill
Script.require("https://hifi-content.s3.amazonaws.com/milad/ROLC/Organize/O_Projects/Hifi/Scripts/hifi-content/Utilities/Polyfills.js")();
// "../../../Utilities/Polyfills.js"
// Helper Functions
var Util = Script.require("https://hifi-content.s3.amazonaws.com/milad/ROLC/Organize/O_Projects/Hifi/Scripts/hifi-content/Utilities/Helper.js");
// "../../../Utilities/Helper.js"
var getProps = Util.Entity.getProps,
getUserData = Util.Entity.getUserData,
searchForChildren = Util.Entity.searchForChildren;
// Log Setup
var LOG_CONFIG = {},
LOG_ENTER = Util.Debug.LOG_ENTER,
LOG_UPDATE = Util.Debug.LOG_UPDATE,
LOG_ERROR = Util.Debug.LOG_ERROR,
LOG_VALUE = Util.Debug.LOG_VALUE,
LOG_ARCHIVE = Util.Debug.LOG_ARCHIVE;
LOG_CONFIG[LOG_ENTER] = false;
LOG_CONFIG[LOG_UPDATE] = false;
LOG_CONFIG[LOG_ERROR] = false;
LOG_CONFIG[LOG_VALUE] = false;
LOG_CONFIG[LOG_ARCHIVE] = false;
var log = Util.Debug.log(LOG_CONFIG);
// Init
var entityID,
debugCubeID = null,
isOn = false,
name = null,
lastHeartBeat = null,
loadedChildren = false,
HEARTBEAT_CHECK_INTERVAL = 1500,
HEARTBEAT_TIMEOUT = 2000,
heartbeatCheck = null,
lastEdit = 0,
LAST_EDIT_TIMEOUT = 2500,
SEARCH_FOR_CHILDREN_TIMEOUT = 5000,
SEARCH_FOR_CHILDNAME_TIMEOUT = 1000,
TURN_ON = "turnOn",
TURN_OFF = "turnOff",
EDIT = "edit",
IN_BOX = "inBox",
IN_MARGIN = "inMargin",
GENERATOR = "generator",
SENSOR = "sensor",
ENDPOINT = "endPoint",
DEBUG = false,
wantsCube = false,
self;
// Collections
var currentProperties = {},
userData = {},
userdataProperties = {},
childrenIDS = {},
avatarsInZone = {},
childNames = [],
sensors = [],
endPoints = [],
generators = [];
// Constructor Functions
function EndPoint(id, endPointGroupID) {
this.id = id;
this.endPointGroupID = endPointGroupID;
}
EndPoint.prototype = {
updateDebugCubeID: function (id) {
Entities.callEntityMethod(this.id, "updateDebugCubeID", [id]);
},
turnOn: function () {
Entities.callEntityMethod(this.id, "turnOn");
},
turnOff: function () {
Entities.callEntityMethod(this.id, "turnOff");
}
};
function Generator(id) {
this.id = id;
}
Generator.prototype = {
clearDebugEndpointInfo: function () {
for (var id in avatarsInZone) {
Entities.callEntityClientMethod(id, this.id, "clearDebugEndpointInfo");
}
},
storeDebugSensorInfo: function (event) {
for (var id in avatarsInZone) {
Entities.callEntityClientMethod(id, this.id, "storeDebugSensorInfo", [event]);
}
},
storeDebugEndpointInfo: function (event, name) {
for (var id in avatarsInZone) {
Entities.callEntityClientMethod(id, this.id, "storeDebugEndpointInfo", [event, name]);
}
},
turnOn: function () {
for (var id in avatarsInZone) {
Entities.callEntityClientMethod(id, this.id, "turnOn");
}
},
turnOff: function () {
for (var id in avatarsInZone) {
Entities.callEntityClientMethod(id, this.id, "turnOff");
}
}
};
function Sensor(id, endPointGroups) {
this.id = id;
this.endPointGroups = endPointGroups;
this.endPoints = [];
this.currentGenerators = {};
this.canEdit = false;
this.activeGenerator = null;
this.activeUUID = null;
this.lastEdit = 0;
}
Sensor.prototype = {
grabEndPointIDsFromGroup: function (groupID) {
return endPoints.filter(function (endPoint) {
return endPoint.endPointGroupID === groupID;
});
},
getEndPoints: function () {
var allEndpoints = [];
this.endPointGroups.forEach(function (endPointGroup) {
allEndpoints = allEndpoints.concat(this.grabEndPointIDsFromGroup(endPointGroup));
}, this);
this.endPoints = allEndpoints;
},
updateDebugCubeID: function (debugCubeID) {
for (var id in avatarsInZone) {
Entities.callEntityClientMethod(id, this.id, "updateDebugCubeID");
}
},
turnOn: function () {
for (var id in avatarsInZone) {
Entities.callEntityClientMethod(id, this.id, "turnOn");
}
},
turnOff: function () {
for (var id in avatarsInZone) {
Entities.callEntityClientMethod(id, this.id, "turnOff");
}
}
};
// Procedural Functions
// Entity Definition
function DJ_Dispatch_Zone_Server() {
self = this;
}
DJ_Dispatch_Zone_Server.prototype = {
remotelyCallable: [
"clearDebugEndpointInfo",
"receiveHeartBeat",
"requestTurnOff",
"scan",
"sendEdit",
"sendOff",
"sendOn",
"storeDebugEndpointInfo",
"storeDebugSensorInfo",
"submitEvent",
"turnOff",
"turnOn",
"updateComponents"
],
clearDebugEndpointInfo: function (id) {
generators[0].clearDebugEndpointInfo();
},
heartBeatHelper: function () {
var shouldKeepActive = false,
now = Date.now(),
avatars = Object.keys(avatarsInZone);
avatars.forEach(function(avatar) {
var timeToCheck = now - avatarsInZone[avatar];
if (timeToCheck > HEARTBEAT_TIMEOUT) {
delete avatarsInZone[avatar];
} else {
shouldKeepActive = true;
}
});
if (!shouldKeepActive) {
self.turnOff();
}
},
preload: function (id) {
entityID = id;
currentProperties = Entities.getEntityProperties(entityID, ["name", "userData"]);
name = currentProperties.name;
userData = currentProperties.userData;
try {
userdataProperties = JSON.parse(userData);
DEBUG = userdataProperties.performance.DEBUG;
wantsCube = userdataProperties.performance.wantsCube;
if (DEBUG) {
LOG_CONFIG[LOG_ENTER] = true;
LOG_CONFIG[LOG_UPDATE] = true;
LOG_CONFIG[LOG_ERROR] = true;
LOG_CONFIG[LOG_VALUE] = true;
log = Util.Debug.log(LOG_CONFIG);
}
var childNameTimeOutFunction = function () {
userdataProperties = getUserData(entityID);
if (!userdataProperties.performance.childNamesUpdated) {
Script.setTimeout(childNameTimeOutFunction, SEARCH_FOR_CHILDNAME_TIMEOUT);
} else {
childNames = userdataProperties.performance.childNames;
var childNamesToSearch = Array.prototype.slice.call(childNames);
childNames.forEach(function (name) {
childrenIDS[name] = null;
});
var searchCallback = function (children, foundAllEntities, names) {
if (foundAllEntities) {
loadedChildren = true;
Object.keys(children).forEach(function (name) {
childrenIDS[name] = children[name];
});
self.updateComponents();
} else {
searchForChildren(entityID, names, searchCallback, SEARCH_FOR_CHILDREN_TIMEOUT, true);
}
};
searchForChildren(entityID, childNamesToSearch, searchCallback, SEARCH_FOR_CHILDREN_TIMEOUT, true);
}
};
Script.setTimeout(childNameTimeOutFunction, SEARCH_FOR_CHILDNAME_TIMEOUT);
} catch (e) {
log(LOG_ERROR, "ERROR READING USERDATA", e);
}
},
receiveHeartBeat: function (id, param) {
var avatarID = param[0];
avatarsInZone[avatarID] = Date.now();
sensors.forEach(function(sensor) {
if (sensor.canEdit && Date.now() - sensor.lastEdit > LAST_EDIT_TIMEOUT) {
var sensorEndpoints = sensor.endPoints;
sensor.activeUUID = null;
sensor.activeGenerator = null;
self.sendOff(sensorEndpoints);
sensor.canEdit = false;
}
});
log(LOG_VALUE, "AVATRS IN ZONE ON RECEIVE HEART BEAT", avatarsInZone);
},
requestTurnOff: function() {
this.heartBeatHelper();
},
returnSensorIndex: function (id) {
var foundIndex;
sensors.forEach(function(sensor, index) {
if (sensor.id === id) {
foundIndex = index;
}
});
return foundIndex;
},
scan: function () {
var foundSensors = [];
var foundEndPoints = [];
var foundGenerators = [];
childNames.forEach(function (name) {
var idToCheck = childrenIDS[name];
var properties = getProps(idToCheck);
try {
var userData = JSON.parse(properties.userData);
var id = properties.id;
if (userData.performance.type === SENSOR) {
var endPointGroups = userData.performance.endPointGroups;
foundSensors.push(new Sensor(id, endPointGroups));
}
if (userData.performance.type === ENDPOINT) {
var endPointGroupID = userData.performance.endPointGroupID;
foundEndPoints.push(new EndPoint(id, endPointGroupID));
}
if (userData.performance.type === GENERATOR) {
foundGenerators.push(new Generator(id));
if (properties.name.indexOf("Debug-Cube") > -1) {
debugCubeID = id;
}
}
} catch (e) {
log(LOG_ERROR, "PARSE ERROR LOOKING FOR USERDATA", e);
}
});
sensors = foundSensors;
endPoints = foundEndPoints;
generators = foundGenerators;
},
sendEdit: function (groupEndPoints, range, direction) {
groupEndPoints.forEach(function(endPoint) {
Entities.callEntityMethod(
endPoint.id,
'edit',
[range, direction]
);
});
if (DEBUG && wantsCube) {
this.storeDebugSensorInfo(range);
}
},
sendOff: function (groupEndPoints) {
groupEndPoints.forEach(function(endPoint) {
Entities.callEntityMethod(endPoint.id, 'turnOff');
});
if (DEBUG && wantsCube) {
this.clearDebugEndpointInfo();
}
},
sendOn: function (groupEndPoints) {
groupEndPoints.forEach(function(endPoint) {
Entities.callEntityMethod(endPoint.id, 'turnOn');
});
if (DEBUG && wantsCube) {
this.clearDebugEndpointInfo();
}
},
storeDebugEndpointInfo: function (id, parm) {
generators[0].storeDebugEndpointInfo(parm[0], parm[1]);
},
storeDebugSensorInfo: function (range) {
generators[0].storeDebugSensorInfo(range);
},
submitEvent: function (id, param) {
var range = param[0],
direction = param[1],
generator = param[2],
box = param[3],
sensorID = param[4],
uuid = param[5];
var sensorIndex = this.returnSensorIndex(sensorID);
var sensor = sensors[sensorIndex];
var sensorEndpoints = sensors[sensorIndex].endPoints;
if (box === IN_BOX) {
if (!sensor.activeUUID && !sensor.activeGenerator) {
sensor.activeUUID = uuid;
sensor.activeGenerator = generator;
this.sendOn(sensorEndpoints);
sensors[sensorIndex].canEdit = true;
return;
}
if (sensor.activeGenerator === generator &&
sensor.activeUUID === uuid &&
sensor.canEdit) {
sensor.lastEdit = Date.now();
this.sendEdit(sensorEndpoints, range, direction);
return;
}
}
if (box === IN_MARGIN) {
if (sensor.activeUUID === uuid &&
sensor.activeGenerator === generator) {
sensor.activeUUID = null;
sensor.activeGenerator = null;
this.sendOff(sensorEndpoints);
sensor.canEdit = false;
}
}
},
turnOff: function () {
isOn = false;
if (heartbeatCheck) {
Script.clearInterval(heartbeatCheck);
heartbeatCheck = null;
}
sensors.forEach(function (sensor) {
sensor.turnOff();
});
generators.forEach(function (generator) {
generator.turnOff();
});
endPoints.forEach(function (endPoint) {
endPoint.turnOff();
});
},
turnOn: function (id, param) {
var avatarID = param[0];
avatarsInZone[avatarID] = Date.now();
log(LOG_ENTER, "Turn on activated", avatarsInZone);
if (isOn) {
return;
} else {
isOn = true;
sensors.forEach(function (sensor) {
sensor.turnOn();
});
generators.forEach(function (generator) {
generator.turnOn();
});
heartbeatCheck = Script.setInterval( function() {
self.heartBeatHelper();
}, HEARTBEAT_CHECK_INTERVAL);
}
},
unload: function () {
if (heartbeatCheck) {
Script.clearInterval(heartbeatCheck);
}
this.turnOff();
},
updateComponents: function () {
this.scan();
this.updateDispatch();
if (DEBUG && wantsCube) {
this.updateDebugCubeID(debugCubeID);
}
},
updateDebugCubeID: function (debugCubeID) {
sensors.forEach(function (sensor) {
sensor.updateDebugCubeID(debugCubeID);
});
},
updateDispatch: function () {
sensors.forEach(function (sensor) {
sensor.getEndPoints();
});
}
};
return new DJ_Dispatch_Zone_Server();
});