dnd-travel-calculator
Version:
D&D 5e travel calculator
146 lines (124 loc) • 16.4 kB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.TravelCalculator = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
module.exports = require("./travel-calculator");
},{"./travel-calculator":2}],2:[function(require,module,exports){
var config = (function (props) {
var self = {};
var _getByPropPath = function (o, s) {
// http://stackoverflow.com/a/6491621
s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
s = s.replace(/^\./, ''); // strip a leading dot
var a = s.split('.');
for (var i = 0, n = a.length; i < n; ++i) {
var k = a[i];
if (k in o) {
o = o[k];
} else {
return;
}
}
return o;
};
self.get = function (a) {
return _getByPropPath(props, a);
};
return self;
})({"Client":{"5e":{"land":{"fast":{"milesPerDay":30,"hoursPerDay":8},"normal":{"milesPerDay":24,"hoursPerDay":8},"slow":{"milesPerDay":18,"hoursPerDay":8}},"sea":{"galley":{"milesPerDay":96,"hoursPerDay":24},"keelboat":{"milesPerDay":72,"hoursPerDay":24},"longship":{"milesPerDay":120,"hoursPerDay":24},"rowboat":{"milesPerDay":24,"hoursPerDay":8},"sailingShip":{"milesPerDay":120,"hoursPerDay":24},"warship":{"milesPerDay":96,"hoursPerDay":24}}}}});;
var TravelCalculator = (function () {
/**
* @param normalTerrainMiles [int] The total miles in normal terrain
* @param difficultTerrainMiles [int] The total miles in difficult terrain
* @param travelPace [string] The travel pace used (normal|slow|fast)
* @return [map] An associative array that represents a time object:
{ days: <int>, hours: <int>, minutes: <int>}
*/
var calculateTravelTimeByLand = function(normalTerrainMiles, difficultTerrainMiles, travelPace) {
//0. Check the pace
if (!(travelPace == 'fast' || travelPace == 'slow' || travelPace == 'normal')) {
travelPace = "normal";
}
//1. Independently get the travel times for normal and diff terrains
var normalResult = calculate(normalTerrainMiles, false, "land", travelPace);
var difficultResult = calculate(difficultTerrainMiles, true, "land", travelPace);
//2. Add the results together
var mergedResult = {
days : normalResult.days + difficultResult.days,
hours : normalResult.hours + difficultResult.hours,
minutes : normalResult.minutes + difficultResult.minutes
};
//3. Make human readable
upConvertTime(mergedResult, "land", travelPace);
return mergedResult;
};
var calculateTravelTimeBySea = function(totalMiles, boatType) {
//0. Check the boat type
//1. Get the travel time
var result = calculate(totalMiles, false, "sea", boatType);
//2. Upconvert
upConvertTime(result, "sea", boatType);
return result;
};
/**
* @param totalMiles [int] The total miles to travel
* @param isDifficult [boolean] Whether the travel is over difficult terrain
* @param travelType [String] Possible values: "land", "sea"
* @para travelPace [string] Possible values: (fast|normal|slow|galley|keelboat|longship|rowboat|sailingShip|warship)
*/
var calculate = function(totalMiles, isDifficult, travelType, travelPace) {
var configPrefix = "Client.5e." + travelType + "." + travelPace;
var time = {
days: 0,
hours: 0,
minutes: 0
};
if (!isInt(totalMiles) || totalMiles <= 0) {
return time;
}
var milesPerDay = config.get(configPrefix + ".milesPerDay");
if (isDifficult) {
milesPerDay /= 2;
}
var maxHoursTraveledPerDay = config.get(configPrefix + ".hoursPerDay");
var milesPerHour = milesPerDay / maxHoursTraveledPerDay;
var minsPerMile = 60 / milesPerHour;
var remainingMiles = totalMiles % milesPerDay;
//Get the total days the trip takes (rounded down)
time.days = Math.floor(totalMiles / milesPerDay);
//Get the remaining miles needed to complete the journey on the last day
time.hours = Math.floor(remainingMiles / milesPerHour);
time.minutes = (remainingMiles % milesPerHour) * minsPerMile;
return time;
};
/**
* Upconverts time from something like
* days: 1, hours: 7, minutes: 60
* to
* days: 2, hours: 0, minutes: 0
*/
var upConvertTime = function(time, travelType, travelPace) {
//1. Upconvert minutes to hours by mod-ing the value by 60 since there are 60 minutes in an hour
var modMinutes = time.minutes % 60;
//Then, add the quotient back to the hours since that represents
//how many hours were made from the minutes
time.hours += Math.floor(time.minutes / 60);
time.minutes = modMinutes;
//2. Upconvert hours to days by mod-ing the total hours by the hours traveled in a day
var maxHoursTraveledPerDay = config.get("Client.5e." + travelType + "." + travelPace + ".hoursPerDay");
var modHours = time.hours % maxHoursTraveledPerDay;
//Then, add the quotient back to the days since that represents
//how many days were made from the hours
time.days += Math.floor(time.hours / maxHoursTraveledPerDay);
time.hours = modHours;
//3. The days should be a merged result of extra day made from hours/minutes
};
var isInt = function(value) {
return !isNaN(value) && parseInt(Number(value)) == value && !isNaN(parseInt(value, 10));
};
return {
calculateTravelTimeByLand : calculateTravelTimeByLand,
calculateTravelTimeBySea : calculateTravelTimeBySea
};
})();
module.exports = TravelCalculator;
},{}]},{},[1])(1)
});
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJzcmMvaW5kZXguanMiLCJzcmMvdHJhdmVsLWNhbGN1bGF0b3IuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCIuL3RyYXZlbC1jYWxjdWxhdG9yXCIpOyIsInZhciBjb25maWcgPSAoZnVuY3Rpb24gKHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgc2VsZiA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9nZXRCeVByb3BQYXRoID0gZnVuY3Rpb24gKG8sIHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS82NDkxNjIxXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcyA9IHMucmVwbGFjZSgvXFxbKFxcdyspXFxdL2csICcuJDEnKTsgLy8gY29udmVydCBpbmRleGVzIHRvIHByb3BlcnRpZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzID0gcy5yZXBsYWNlKC9eXFwuLywgJycpOyAgICAgICAgICAgLy8gc3RyaXAgYSBsZWFkaW5nIGRvdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhID0gcy5zcGxpdCgnLicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBuID0gYS5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGsgPSBhW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoayBpbiBvKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvID0gb1trXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbztcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuZ2V0ID0gZnVuY3Rpb24gKGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2dldEJ5UHJvcFBhdGgocHJvcHMsIGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICAgICAgICAgIH0pKHtcIkNsaWVudFwiOntcIjVlXCI6e1wibGFuZFwiOntcImZhc3RcIjp7XCJtaWxlc1BlckRheVwiOjMwLFwiaG91cnNQZXJEYXlcIjo4fSxcIm5vcm1hbFwiOntcIm1pbGVzUGVyRGF5XCI6MjQsXCJob3Vyc1BlckRheVwiOjh9LFwic2xvd1wiOntcIm1pbGVzUGVyRGF5XCI6MTgsXCJob3Vyc1BlckRheVwiOjh9fSxcInNlYVwiOntcImdhbGxleVwiOntcIm1pbGVzUGVyRGF5XCI6OTYsXCJob3Vyc1BlckRheVwiOjI0fSxcImtlZWxib2F0XCI6e1wibWlsZXNQZXJEYXlcIjo3MixcImhvdXJzUGVyRGF5XCI6MjR9LFwibG9uZ3NoaXBcIjp7XCJtaWxlc1BlckRheVwiOjEyMCxcImhvdXJzUGVyRGF5XCI6MjR9LFwicm93Ym9hdFwiOntcIm1pbGVzUGVyRGF5XCI6MjQsXCJob3Vyc1BlckRheVwiOjh9LFwic2FpbGluZ1NoaXBcIjp7XCJtaWxlc1BlckRheVwiOjEyMCxcImhvdXJzUGVyRGF5XCI6MjR9LFwid2Fyc2hpcFwiOntcIm1pbGVzUGVyRGF5XCI6OTYsXCJob3Vyc1BlckRheVwiOjI0fX19fX0pOztcblxudmFyIFRyYXZlbENhbGN1bGF0b3IgPSAoZnVuY3Rpb24gKCkge1xuXHQvKipcblx0KiBAcGFyYW0gbm9ybWFsVGVycmFpbk1pbGVzIFtpbnRdIFRoZSB0b3RhbCBtaWxlcyBpbiBub3JtYWwgdGVycmFpblxuXHQqIEBwYXJhbSBkaWZmaWN1bHRUZXJyYWluTWlsZXMgW2ludF0gVGhlIHRvdGFsIG1pbGVzIGluIGRpZmZpY3VsdCB0ZXJyYWluXG5cdCogQHBhcmFtIHRyYXZlbFBhY2UgW3N0cmluZ10gVGhlIHRyYXZlbCBwYWNlIHVzZWQgKG5vcm1hbHxzbG93fGZhc3QpXG5cdCogQHJldHVybiBbbWFwXSBBbiBhc3NvY2lhdGl2ZSBhcnJheSB0aGF0IHJlcHJlc2VudHMgYSB0aW1lIG9iamVjdDpcblx0eyBkYXlzOiA8aW50PiwgaG91cnM6IDxpbnQ+LCBtaW51dGVzOiA8aW50Pn1cblx0Ki9cblx0dmFyIGNhbGN1bGF0ZVRyYXZlbFRpbWVCeUxhbmQgPSBmdW5jdGlvbihub3JtYWxUZXJyYWluTWlsZXMsIGRpZmZpY3VsdFRlcnJhaW5NaWxlcywgdHJhdmVsUGFjZSkge1xuXHRcdC8vMC4gQ2hlY2sgdGhlIHBhY2Vcblx0XHRpZiAoISh0cmF2ZWxQYWNlID09ICdmYXN0JyB8fCB0cmF2ZWxQYWNlID09ICdzbG93JyB8fCB0cmF2ZWxQYWNlID09ICdub3JtYWwnKSkge1xuXHRcdFx0dHJhdmVsUGFjZSA9IFwibm9ybWFsXCI7XG5cdFx0fVxuXG5cdFx0Ly8xLiBJbmRlcGVuZGVudGx5IGdldCB0aGUgdHJhdmVsIHRpbWVzIGZvciBub3JtYWwgYW5kIGRpZmYgdGVycmFpbnNcblx0XHR2YXIgbm9ybWFsUmVzdWx0ID0gY2FsY3VsYXRlKG5vcm1hbFRlcnJhaW5NaWxlcywgZmFsc2UsIFwibGFuZFwiLCB0cmF2ZWxQYWNlKTtcblx0XHR2YXIgZGlmZmljdWx0UmVzdWx0ID0gY2FsY3VsYXRlKGRpZmZpY3VsdFRlcnJhaW5NaWxlcywgdHJ1ZSwgXCJsYW5kXCIsIHRyYXZlbFBhY2UpO1xuXHRcdFxuXHRcdC8vMi4gQWRkIHRoZSByZXN1bHRzIHRvZ2V0aGVyXG5cdFx0dmFyIG1lcmdlZFJlc3VsdCA9IHtcblx0XHRcdGRheXMgOiBub3JtYWxSZXN1bHQuZGF5cyArIGRpZmZpY3VsdFJlc3VsdC5kYXlzLFxuXHRcdFx0aG91cnMgOiBub3JtYWxSZXN1bHQuaG91cnMgKyBkaWZmaWN1bHRSZXN1bHQuaG91cnMsXG5cdFx0XHRtaW51dGVzIDogbm9ybWFsUmVzdWx0Lm1pbnV0ZXMgKyBkaWZmaWN1bHRSZXN1bHQubWludXRlc1xuXHRcdH07XG5cblx0XHQvLzMuIE1ha2UgaHVtYW4gcmVhZGFibGVcblx0XHR1cENvbnZlcnRUaW1lKG1lcmdlZFJlc3VsdCwgXCJsYW5kXCIsIHRyYXZlbFBhY2UpOyBcblx0XHRyZXR1cm4gbWVyZ2VkUmVzdWx0O1xuXHR9O1xuXG5cdHZhciBjYWxjdWxhdGVUcmF2ZWxUaW1lQnlTZWEgPSBmdW5jdGlvbih0b3RhbE1pbGVzLCBib2F0VHlwZSkge1xuXHRcdC8vMC4gQ2hlY2sgdGhlIGJvYXQgdHlwZVxuXG5cdFx0Ly8xLiBHZXQgdGhlIHRyYXZlbCB0aW1lXG5cdFx0dmFyIHJlc3VsdCA9IGNhbGN1bGF0ZSh0b3RhbE1pbGVzLCBmYWxzZSwgXCJzZWFcIiwgYm9hdFR5cGUpO1xuXG5cdFx0Ly8yLiBVcGNvbnZlcnRcblx0XHR1cENvbnZlcnRUaW1lKHJlc3VsdCwgXCJzZWFcIiwgYm9hdFR5cGUpO1xuXHRcdHJldHVybiByZXN1bHQ7XG5cdH07XG5cblx0LyoqXG5cdCogQHBhcmFtIHRvdGFsTWlsZXMgW2ludF0gVGhlIHRvdGFsIG1pbGVzIHRvIHRyYXZlbFxuXHQqIEBwYXJhbSBpc0RpZmZpY3VsdCBbYm9vbGVhbl0gV2hldGhlciB0aGUgdHJhdmVsIGlzIG92ZXIgZGlmZmljdWx0IHRlcnJhaW5cblx0KiBAcGFyYW0gdHJhdmVsVHlwZSBbU3RyaW5nXSBQb3NzaWJsZSB2YWx1ZXM6IFwibGFuZFwiLCBcInNlYVwiXG5cdCogQHBhcmEgdHJhdmVsUGFjZSBbc3RyaW5nXSBQb3NzaWJsZSB2YWx1ZXM6IChmYXN0fG5vcm1hbHxzbG93fGdhbGxleXxrZWVsYm9hdHxsb25nc2hpcHxyb3dib2F0fHNhaWxpbmdTaGlwfHdhcnNoaXApXG5cdCovXG5cdHZhciBjYWxjdWxhdGUgPSBmdW5jdGlvbih0b3RhbE1pbGVzLCBpc0RpZmZpY3VsdCwgdHJhdmVsVHlwZSwgdHJhdmVsUGFjZSkge1xuXHRcdHZhciBjb25maWdQcmVmaXggPSBcIkNsaWVudC41ZS5cIiArIHRyYXZlbFR5cGUgKyBcIi5cIiArIHRyYXZlbFBhY2U7XG5cdFx0dmFyIHRpbWUgPSB7XG5cdFx0XHRkYXlzOiAwLFxuXHRcdFx0aG91cnM6IDAsXG5cdFx0XHRtaW51dGVzOiAwXG5cdFx0fTtcblxuXHRcdGlmICghaXNJbnQodG90YWxNaWxlcykgfHwgdG90YWxNaWxlcyA8PSAwKSB7XG5cdFx0XHRyZXR1cm4gdGltZTtcblx0XHR9XG5cblx0XHR2YXIgbWlsZXNQZXJEYXkgPSBjb25maWcuZ2V0KGNvbmZpZ1ByZWZpeCArIFwiLm1pbGVzUGVyRGF5XCIpO1xuXHRcdGlmIChpc0RpZmZpY3VsdCkge1xuXHRcdFx0bWlsZXNQZXJEYXkgLz0gMjtcblx0XHR9XG5cdFx0dmFyIG1heEhvdXJzVHJhdmVsZWRQZXJEYXkgPSBjb25maWcuZ2V0KGNvbmZpZ1ByZWZpeCArIFwiLmhvdXJzUGVyRGF5XCIpO1xuXHRcdHZhciBtaWxlc1BlckhvdXIgPSBtaWxlc1BlckRheSAvIG1heEhvdXJzVHJhdmVsZWRQZXJEYXk7XG5cdFx0dmFyIG1pbnNQZXJNaWxlID0gNjAgLyBtaWxlc1BlckhvdXI7XG5cdFx0dmFyIHJlbWFpbmluZ01pbGVzID0gdG90YWxNaWxlcyAlIG1pbGVzUGVyRGF5OyBcblxuXHRcdC8vR2V0IHRoZSB0b3RhbCBkYXlzIHRoZSB0cmlwIHRha2VzIChyb3VuZGVkIGRvd24pXG5cdFx0dGltZS5kYXlzID0gTWF0aC5mbG9vcih0b3RhbE1pbGVzIC8gbWlsZXNQZXJEYXkpO1xuXHRcdC8vR2V0IHRoZSByZW1haW5pbmcgbWlsZXMgbmVlZGVkIHRvIGNvbXBsZXRlIHRoZSBqb3VybmV5IG9uIHRoZSBsYXN0IGRheVxuXHRcdHRpbWUuaG91cnMgPSBNYXRoLmZsb29yKHJlbWFpbmluZ01pbGVzIC8gbWlsZXNQZXJIb3VyKTtcblx0XHR0aW1lLm1pbnV0ZXMgPSAocmVtYWluaW5nTWlsZXMgJSBtaWxlc1BlckhvdXIpICogbWluc1Blck1pbGU7XG5cdFx0cmV0dXJuIHRpbWU7XG5cdH07XG5cblx0LyoqXG5cdCogVXBjb252ZXJ0cyB0aW1lIGZyb20gc29tZXRoaW5nIGxpa2UgXG5cdCogZGF5czogMSwgaG91cnM6IDcsIG1pbnV0ZXM6IDYwXG5cdCogdG9cblx0KiBkYXlzOiAyLCBob3VyczogMCwgbWludXRlczogMFxuXHQqLyBcblx0dmFyIHVwQ29udmVydFRpbWUgPSBmdW5jdGlvbih0aW1lLCB0cmF2ZWxUeXBlLCB0cmF2ZWxQYWNlKSB7XG5cdFx0Ly8xLiBVcGNvbnZlcnQgbWludXRlcyB0byBob3VycyBieSBtb2QtaW5nIHRoZSB2YWx1ZSBieSA2MCBzaW5jZSB0aGVyZSBhcmUgNjAgbWludXRlcyBpbiBhbiBob3VyXG5cdFx0dmFyIG1vZE1pbnV0ZXMgPSB0aW1lLm1pbnV0ZXMgJSA2MDtcblx0XHQvL1RoZW4sIGFkZCB0aGUgcXVvdGllbnQgYmFjayB0byB0aGUgaG91cnMgc2luY2UgdGhhdCByZXByZXNlbnRzIFxuXHRcdC8vaG93IG1hbnkgaG91cnMgd2VyZSBtYWRlIGZyb20gdGhlIG1pbnV0ZXNcblx0XHR0aW1lLmhvdXJzICs9IE1hdGguZmxvb3IodGltZS5taW51dGVzIC8gNjApO1xuXHRcdHRpbWUubWludXRlcyA9IG1vZE1pbnV0ZXM7XG5cblx0XHQvLzIuIFVwY29udmVydCBob3VycyB0byBkYXlzIGJ5IG1vZC1pbmcgdGhlIHRvdGFsIGhvdXJzIGJ5IHRoZSBob3VycyB0cmF2ZWxlZCBpbiBhIGRheVxuXHRcdHZhciBtYXhIb3Vyc1RyYXZlbGVkUGVyRGF5ID0gY29uZmlnLmdldChcIkNsaWVudC41ZS5cIiArIHRyYXZlbFR5cGUgKyBcIi5cIiArIHRyYXZlbFBhY2UgKyBcIi5ob3Vyc1BlckRheVwiKTtcblx0XHR2YXIgbW9kSG91cnMgPSB0aW1lLmhvdXJzICUgbWF4SG91cnNUcmF2ZWxlZFBlckRheTtcblx0XHQvL1RoZW4sIGFkZCB0aGUgcXVvdGllbnQgYmFjayB0byB0aGUgZGF5cyBzaW5jZSB0aGF0IHJlcHJlc2VudHNcblx0XHQvL2hvdyBtYW55IGRheXMgd2VyZSBtYWRlIGZyb20gdGhlIGhvdXJzXG5cdFx0dGltZS5kYXlzICs9IE1hdGguZmxvb3IodGltZS5ob3VycyAvIG1heEhvdXJzVHJhdmVsZWRQZXJEYXkpO1xuXHRcdHRpbWUuaG91cnMgPSBtb2RIb3VycztcblxuXHRcdC8vMy4gVGhlIGRheXMgc2hvdWxkIGJlIGEgbWVyZ2VkIHJlc3VsdCBvZiBleHRyYSBkYXkgbWFkZSBmcm9tIGhvdXJzL21pbnV0ZXNcblx0fTtcblxuXHR2YXIgaXNJbnQgPSBmdW5jdGlvbih2YWx1ZSkge1xuICBcdFx0cmV0dXJuICFpc05hTih2YWx1ZSkgJiYgcGFyc2VJbnQoTnVtYmVyKHZhbHVlKSkgPT0gdmFsdWUgJiYgIWlzTmFOKHBhcnNlSW50KHZhbHVlLCAxMCkpO1xuXHR9O1xuICBcblx0cmV0dXJuIHtcbiAgXHRcdGNhbGN1bGF0ZVRyYXZlbFRpbWVCeUxhbmQgOiBjYWxjdWxhdGVUcmF2ZWxUaW1lQnlMYW5kLFxuICBcdFx0Y2FsY3VsYXRlVHJhdmVsVGltZUJ5U2VhIDogY2FsY3VsYXRlVHJhdmVsVGltZUJ5U2VhXG5cdH07XG5cbn0pKCk7XG5cbm1vZHVsZS5leHBvcnRzID0gVHJhdmVsQ2FsY3VsYXRvcjsiXX0=