/**
* Module which implements the class Measurement which includes the four
* parameters that are measured in Q4S.
* @module measure
*/
/** Measurement Class*/
class Measure {
/**
* Constructor for the Measurement.
* @param {Number} latency - Latency in ms
* @param {Number} jitter - Jitter in ms
* @param {Number} bandwidth - bandwidth in ms
* @param {Number} packetLoss - packetLoss
*/
constructor(latency, jitter, bandwidth, packetLoss) {
/**
* Latency in ms
* @member {Number}
*/
this.latency = latency;
/**
* Jitter in ms
* @member {Number}
*/
this.jitter = jitter;
/**
* Bandwidth in kbps kilo bits per second
* @member {Number}
*/
this.bandwidth = bandwidth;
/**
* Packet Loss in probability 0 to 1
* @member {Number}
*/
this.packetLoss = packetLoss;
}
/**
* Extract the text view of this object to be included in headers.
* @return {String} The header representation of tose measurements.
*/
toHeader() {
let header = 'l=';
if (typeof this.latency !== 'undefined') {
header = header + this.latency;
}
header = header + ', j=';
if (typeof this.jitter !== 'undefined') {
header = header + this.jitter;
}
header = header + ', pl=';
if (typeof this.packetLoss !== 'undefined') {
header = header + this.packetLoss;
}
header = header + ', bw=';
if (typeof this.bandwidth !== 'undefined') {
header = header + this.bandwidth;
}
return header;
}
/**
* Fill this object with contents from a text header.
* @param {String} hdr - Header line to extract the text from.
*/
fromHeader(hdr) {
const latencyReg = /^l=\d+(\.\d+)?/;
const jitterReg = /^j=\d+(\.\d+)?/;
const packetLossReg = /^pl=[0-1]+(\.\d+)?/;
const bandwidthReg = /^bw=\d+(\.\d+)?/;
const parts = hdr.split(', ');
parts.forEach((element) => {
if (latencyReg.test(element)) {
this.latency = parseFloat(element.substring(2));
} else if (jitterReg.test(element)) {
this.jitter = parseFloat(element.substring(2));
} else if (packetLossReg.test(element)) {
this.packetLoss = parseFloat(element.substring(3));
} else if (bandwidthReg.test(element)) {
this.bandwidth = parseFloat(element.substring(3));
}
});
}
/**
* Fill the jitter attribute with an Array of dates. Those dates are the
* arrival dates of packets. The array is expected to be filled with zeroes
* in the empty spaces thata re not used. The lenght considered is up to the
* last not zero value.
* @param {Object[]} reqTime
* @param {Number} reqTime.seq
* @param {Date} reqTime.time
*/
extractJitter(reqTime) {
reqTime.sort((a, b) => {
return a.seq - b.seq;
});
let acum = 0;
let size = 0;
let diff = 0;
for (let i = 1; i < reqTime.length; i++) {
if (reqTime[i].seq == reqTime[i - 1].seq + 1) {
acum = acum + reqTime[i].time.getTime() - reqTime[i - 1].time.getTime();
size++;
}
}
const averageTime = acum / size;
acum = 0;
for (let i = 1; i < reqTime.length; i++) {
if (reqTime[i].seq == reqTime[i - 1].seq + 1) {
diff = reqTime[i].time.getTime() - reqTime[i - 1].time.getTime();
acum = acum + Math.abs(diff - averageTime);
}
}
if (size !== 0) {
this.jitter = acum / size;
}
}
/**
* Fill the packet loss and latency attribute with an Array of dates. Those
* dates are thedeparture of the packet and the time of ariva of the
* corresponding response. The array is expected to be filled with zeroes
* in the empty spaces thata re not used. The lenght considered is up to the
* last not zero value.
* @param {Object[]} departureTime
* @param {Number} departureTime.seq
* @param {Date} departureTime.time
* @param {Object[]} arrivalTime
* @param {Number} arrivalTime.seq
* @param {Date} arrivalTime.time
*/
extractLatency(departureTime, arrivalTime) {
arrivalTime.sort((a, b) => {
return a.seq - b.seq;
});
let acum = 0;
let lost = 0;
for (let i = 0; i < departureTime.length; i++) {
let isFound = false;
for (let j = i - lost; j < arrivalTime.length; j++) {
if (departureTime[i].seq == arrivalTime[j].seq) {
acum = acum +
arrivalTime[j].time.getTime() -
departureTime[i].time.getTime();
isFound = true;
break;
}
}
if (!isFound) {
lost++;
}
}
this.latency = acum / arrivalTime.length;
this.packetLoss = lost / departureTime.length;
}
/**
* From recieved in bandwidth measurement.
* @param {Number[]} arrivedMessages - The sending times
* @param {Number} expectedBandwidth - The targeted bandwidth
*/
extractBandwidth(arrivedMessages, expectedBandwidth) {
const size = arrivedMessages.length;
if (size > 0) {
const maxSeq = arrivedMessages.reduce((prev, curr) => {
return prev > curr ? prev : curr;
});
const recievedPercentage = size / (maxSeq + 1);
this.packetLoss = 1 - recievedPercentage;
this.bandwidth = expectedBandwidth * recievedPercentage;
}
}
}
module.exports = Measure;