ngb-calendar.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /**
  2. * @fileoverview added by tsickle
  3. * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  4. */
  5. import { NgbDate } from './ngb-date';
  6. import { Injectable } from '@angular/core';
  7. import { isInteger } from '../util/util';
  8. import * as i0 from "@angular/core";
  9. /**
  10. * @param {?} jsDate
  11. * @return {?}
  12. */
  13. export function fromJSDate(jsDate) {
  14. return new NgbDate(jsDate.getFullYear(), jsDate.getMonth() + 1, jsDate.getDate());
  15. }
  16. /**
  17. * @param {?} date
  18. * @return {?}
  19. */
  20. export function toJSDate(date) {
  21. /** @type {?} */
  22. const jsDate = new Date(date.year, date.month - 1, date.day, 12);
  23. // this is done avoid 30 -> 1930 conversion
  24. if (!isNaN(jsDate.getTime())) {
  25. jsDate.setFullYear(date.year);
  26. }
  27. return jsDate;
  28. }
  29. /**
  30. * @return {?}
  31. */
  32. export function NGB_DATEPICKER_CALENDAR_FACTORY() {
  33. return new NgbCalendarGregorian();
  34. }
  35. /**
  36. * A service that represents the calendar used by the datepicker.
  37. *
  38. * The default implementation uses the Gregorian calendar. You can inject it in your own
  39. * implementations if necessary to simplify `NgbDate` calculations.
  40. * @abstract
  41. */
  42. export class NgbCalendar {
  43. }
  44. NgbCalendar.decorators = [
  45. { type: Injectable, args: [{ providedIn: 'root', useFactory: NGB_DATEPICKER_CALENDAR_FACTORY },] }
  46. ];
  47. /** @nocollapse */ NgbCalendar.ngInjectableDef = i0.ɵɵdefineInjectable({ factory: NGB_DATEPICKER_CALENDAR_FACTORY, token: NgbCalendar, providedIn: "root" });
  48. if (false) {
  49. /**
  50. * Returns the number of days per week.
  51. * @abstract
  52. * @return {?}
  53. */
  54. NgbCalendar.prototype.getDaysPerWeek = function () { };
  55. /**
  56. * Returns an array of months per year.
  57. *
  58. * With default calendar we use ISO 8601 and return [1, 2, ..., 12];
  59. * @abstract
  60. * @param {?=} year
  61. * @return {?}
  62. */
  63. NgbCalendar.prototype.getMonths = function (year) { };
  64. /**
  65. * Returns the number of weeks per month.
  66. * @abstract
  67. * @return {?}
  68. */
  69. NgbCalendar.prototype.getWeeksPerMonth = function () { };
  70. /**
  71. * Returns the weekday number for a given day.
  72. *
  73. * With the default calendar we use ISO 8601: 'weekday' is 1=Mon ... 7=Sun
  74. * @abstract
  75. * @param {?} date
  76. * @return {?}
  77. */
  78. NgbCalendar.prototype.getWeekday = function (date) { };
  79. /**
  80. * Adds a number of years, months or days to a given date.
  81. *
  82. * * `period` can be `y`, `m` or `d` and defaults to day.
  83. * * `number` defaults to 1.
  84. *
  85. * Always returns a new date.
  86. * @abstract
  87. * @param {?} date
  88. * @param {?=} period
  89. * @param {?=} number
  90. * @return {?}
  91. */
  92. NgbCalendar.prototype.getNext = function (date, period, number) { };
  93. /**
  94. * Subtracts a number of years, months or days from a given date.
  95. *
  96. * * `period` can be `y`, `m` or `d` and defaults to day.
  97. * * `number` defaults to 1.
  98. *
  99. * Always returns a new date.
  100. * @abstract
  101. * @param {?} date
  102. * @param {?=} period
  103. * @param {?=} number
  104. * @return {?}
  105. */
  106. NgbCalendar.prototype.getPrev = function (date, period, number) { };
  107. /**
  108. * Returns the week number for a given week.
  109. * @abstract
  110. * @param {?} week
  111. * @param {?} firstDayOfWeek
  112. * @return {?}
  113. */
  114. NgbCalendar.prototype.getWeekNumber = function (week, firstDayOfWeek) { };
  115. /**
  116. * Returns the today's date.
  117. * @abstract
  118. * @return {?}
  119. */
  120. NgbCalendar.prototype.getToday = function () { };
  121. /**
  122. * Checks if a date is valid in the current calendar.
  123. * @abstract
  124. * @param {?} date
  125. * @return {?}
  126. */
  127. NgbCalendar.prototype.isValid = function (date) { };
  128. }
  129. export class NgbCalendarGregorian extends NgbCalendar {
  130. /**
  131. * @return {?}
  132. */
  133. getDaysPerWeek() { return 7; }
  134. /**
  135. * @return {?}
  136. */
  137. getMonths() { return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; }
  138. /**
  139. * @return {?}
  140. */
  141. getWeeksPerMonth() { return 6; }
  142. /**
  143. * @param {?} date
  144. * @param {?=} period
  145. * @param {?=} number
  146. * @return {?}
  147. */
  148. getNext(date, period = 'd', number = 1) {
  149. /** @type {?} */
  150. let jsDate = toJSDate(date);
  151. /** @type {?} */
  152. let checkMonth = true;
  153. /** @type {?} */
  154. let expectedMonth = jsDate.getMonth();
  155. switch (period) {
  156. case 'y':
  157. jsDate.setFullYear(jsDate.getFullYear() + number);
  158. break;
  159. case 'm':
  160. expectedMonth += number;
  161. jsDate.setMonth(expectedMonth);
  162. expectedMonth = expectedMonth % 12;
  163. if (expectedMonth < 0) {
  164. expectedMonth = expectedMonth + 12;
  165. }
  166. break;
  167. case 'd':
  168. jsDate.setDate(jsDate.getDate() + number);
  169. checkMonth = false;
  170. break;
  171. default:
  172. return date;
  173. }
  174. if (checkMonth && jsDate.getMonth() !== expectedMonth) {
  175. // this means the destination month has less days than the initial month
  176. // let's go back to the end of the previous month:
  177. jsDate.setDate(0);
  178. }
  179. return fromJSDate(jsDate);
  180. }
  181. /**
  182. * @param {?} date
  183. * @param {?=} period
  184. * @param {?=} number
  185. * @return {?}
  186. */
  187. getPrev(date, period = 'd', number = 1) { return this.getNext(date, period, -number); }
  188. /**
  189. * @param {?} date
  190. * @return {?}
  191. */
  192. getWeekday(date) {
  193. /** @type {?} */
  194. let jsDate = toJSDate(date);
  195. /** @type {?} */
  196. let day = jsDate.getDay();
  197. // in JS Date Sun=0, in ISO 8601 Sun=7
  198. return day === 0 ? 7 : day;
  199. }
  200. /**
  201. * @param {?} week
  202. * @param {?} firstDayOfWeek
  203. * @return {?}
  204. */
  205. getWeekNumber(week, firstDayOfWeek) {
  206. // in JS Date Sun=0, in ISO 8601 Sun=7
  207. if (firstDayOfWeek === 7) {
  208. firstDayOfWeek = 0;
  209. }
  210. /** @type {?} */
  211. const thursdayIndex = (4 + 7 - firstDayOfWeek) % 7;
  212. /** @type {?} */
  213. let date = week[thursdayIndex];
  214. /** @type {?} */
  215. const jsDate = toJSDate(date);
  216. jsDate.setDate(jsDate.getDate() + 4 - (jsDate.getDay() || 7)); // Thursday
  217. // Thursday
  218. /** @type {?} */
  219. const time = jsDate.getTime();
  220. jsDate.setMonth(0); // Compare with Jan 1
  221. jsDate.setDate(1);
  222. return Math.floor(Math.round((time - jsDate.getTime()) / 86400000) / 7) + 1;
  223. }
  224. /**
  225. * @return {?}
  226. */
  227. getToday() { return fromJSDate(new Date()); }
  228. /**
  229. * @param {?} date
  230. * @return {?}
  231. */
  232. isValid(date) {
  233. if (!date || !isInteger(date.year) || !isInteger(date.month) || !isInteger(date.day)) {
  234. return false;
  235. }
  236. // year 0 doesn't exist in Gregorian calendar
  237. if (date.year === 0) {
  238. return false;
  239. }
  240. /** @type {?} */
  241. const jsDate = toJSDate(date);
  242. return !isNaN(jsDate.getTime()) && jsDate.getFullYear() === date.year && jsDate.getMonth() + 1 === date.month &&
  243. jsDate.getDate() === date.day;
  244. }
  245. }
  246. NgbCalendarGregorian.decorators = [
  247. { type: Injectable }
  248. ];
  249. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmdiLWNhbGVuZGFyLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG5nLWJvb3RzdHJhcC9uZy1ib290c3RyYXAvIiwic291cmNlcyI6WyJkYXRlcGlja2VyL25nYi1jYWxlbmRhci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLFlBQVksQ0FBQztBQUNuQyxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxjQUFjLENBQUM7Ozs7OztBQUV2QyxNQUFNLFVBQVUsVUFBVSxDQUFDLE1BQVk7SUFDckMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLEVBQUUsTUFBTSxDQUFDLFFBQVEsRUFBRSxHQUFHLENBQUMsRUFBRSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztBQUNwRixDQUFDOzs7OztBQUNELE1BQU0sVUFBVSxRQUFRLENBQUMsSUFBYTs7VUFDOUIsTUFBTSxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUM7SUFDaEUsMkNBQTJDO0lBQzNDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUU7UUFDNUIsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDL0I7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDOzs7O0FBSUQsTUFBTSxVQUFVLCtCQUErQjtJQUM3QyxPQUFPLElBQUksb0JBQW9CLEVBQUUsQ0FBQztBQUNwQyxDQUFDOzs7Ozs7OztBQVNELE1BQU0sT0FBZ0IsV0FBVzs7O1lBRGhDLFVBQVUsU0FBQyxFQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLCtCQUErQixF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QyxJQUFJLE1BQU0sQ0FBQyxXQUFXLEVBQUUsS0FBSyxJQUFJLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDLEtBQUssSUFBSSxDQUFDLEtBQUs7WUFDekcsTUFBTSxDQUFDLE9BQU8sRUFBRSxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUM7SUFDcEMsQ0FBQzs7O1lBcEZGLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge05nYkRhdGV9IGZyb20gJy4vbmdiLWRhdGUnO1xuaW1wb3J0IHtJbmplY3RhYmxlfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7aXNJbnRlZ2VyfSBmcm9tICcuLi91dGlsL3V0aWwnO1xuXG5leHBvcnQgZnVuY3Rpb24gZnJvbUpTRGF0ZShqc0RhdGU6IERhdGUpIHtcbiAgcmV0dXJuIG5ldyBOZ2JEYXRlKGpzRGF0ZS5nZXRGdWxsWWVhcigpLCBqc0RhdGUuZ2V0TW9udGgoKSArIDEsIGpzRGF0ZS5nZXREYXRlKCkpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHRvSlNEYXRlKGRhdGU6IE5nYkRhdGUpIHtcbiAgY29uc3QganNEYXRlID0gbmV3IERhdGUoZGF0ZS55ZWFyLCBkYXRlLm1vbnRoIC0gMSwgZGF0ZS5kYXksIDEyKTtcbiAgLy8gdGhpcyBpcyBkb25lIGF2b2lkIDMwIC0+IDE5MzAgY29udmVyc2lvblxuICBpZiAoIWlzTmFOKGpzRGF0ZS5nZXRUaW1lKCkpKSB7XG4gICAganNEYXRlLnNldEZ1bGxZZWFyKGRhdGUueWVhcik7XG4gIH1cbiAgcmV0dXJuIGpzRGF0ZTtcbn1cblxuZXhwb3J0IHR5cGUgTmdiUGVyaW9kID0gJ3knIHwgJ20nIHwgJ2QnO1xuXG5leHBvcnQgZnVuY3Rpb24gTkdCX0RBVEVQSUNLRVJfQ0FMRU5EQVJfRkFDVE9SWSgpIHtcbiAgcmV0dXJuIG5ldyBOZ2JDYWxlbmRhckdyZWdvcmlhbigpO1xufVxuXG4vKipcbiAqIEEgc2VydmljZSB0aGF0IHJlcHJlc2VudHMgdGhlIGNhbGVuZGFyIHVzZWQgYnkgdGhlIGRhdGVwaWNrZXIuXG4gKlxuICogVGhlIGRlZmF1bHQgaW1wbGVtZW50YXRpb24gdXNlcyB0aGUgR3JlZ29yaWFuIGNhbGVuZGFyLiBZb3UgY2FuIGluamVjdCBpdCBpbiB5b3VyIG93blxuICogaW1wbGVtZW50YXRpb25zIGlmIG5lY2Vzc2FyeSB0byBzaW1wbGlmeSBgTmdiRGF0ZWAgY2FsY3VsYXRpb25zLlxuICovXG5ASW5qZWN0YWJsZSh7cHJvdmlkZWRJbjogJ3Jvb3QnLCB1c2VGYWN0b3J5OiBOR0JfREFURVBJQ0tFUl9DQUxFTkRBUl9GQUNUT1JZfSlcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBOZ2JDYWxlbmRhciB7XG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgZGF5cyBwZXIgd2Vlay5cbiAgICovXG4gIGFic3RyYWN0IGdldERheXNQZXJXZWVrKCk6IG51bWJlcjtcblxuICAvKipcbiAgICogUmV0dXJucyBhbiBhcnJheSBvZiBtb250aHMgcGVyIHllYXIuXG4gICAqXG4gICAqIFdpdGggZGVmYXVsdCBjYWxlbmRhciB3ZSB1c2UgSVNPIDg2MDEgYW5kIHJldHVybiBbMSwgMiwgLi4uLCAxMl07XG4gICAqL1xuICBhYnN0cmFjdCBnZXRNb250aHMoeWVhcj86IG51bWJlcik6IG51bWJlcltdO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBudW1iZXIgb2Ygd2Vla3MgcGVyIG1vbnRoLlxuICAgKi9cbiAgYWJzdHJhY3QgZ2V0V2Vla3NQZXJNb250aCgpOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHdlZWtkYXkgbnVtYmVyIGZvciBhIGdpdmVuIGRheS5cbiAgICpcbiAgICogV2l0aCB0aGUgZGVmYXVsdCBjYWxlbmRhciB3ZSB1c2UgSVNPIDg2MDE6ICd3ZWVrZGF5JyBpcyAxPU1vbiAuLi4gNz1TdW5cbiAgICovXG4gIGFic3RyYWN0IGdldFdlZWtkYXkoZGF0ZTogTmdiRGF0ZSk6IG51bWJlcjtcblxuICAvKipcbiAgICogQWRkcyBhIG51bWJlciBvZiB5ZWFycywgbW9udGhzIG9yIGRheXMgdG8gYSBnaXZlbiBkYXRlLlxuICAgKlxuICAgKiAqIGBwZXJpb2RgIGNhbiBiZSBgeWAsIGBtYCBvciBgZGAgYW5kIGRlZmF1bHRzIHRvIGRheS5cbiAgICogKiBgbnVtYmVyYCBkZWZhdWx0cyB0byAxLlxuICAgKlxuICAgKiBBbHdheXMgcmV0dXJucyBhIG5ldyBkYXRlLlxuICAgKi9cbiAgYWJzdHJhY3QgZ2V0TmV4dChkYXRlOiBOZ2JEYXRlLCBwZXJpb2Q/OiBOZ2JQZXJpb2QsIG51bWJlcj86IG51bWJlcik6IE5nYkRhdGU7XG5cbiAgLyoqXG4gICAqIFN1YnRyYWN0cyBhIG51bWJlciBvZiB5ZWFycywgbW9udGhzIG9yIGRheXMgZnJvbSBhIGdpdmVuIGRhdGUuXG4gICAqXG4gICAqICogYHBlcmlvZGAgY2FuIGJlIGB5YCwgYG1gIG9yIGBkYCBhbmQgZGVmYXVsdHMgdG8gZGF5LlxuICAgKiAqIGBudW1iZXJgIGRlZmF1bHRzIHRvIDEuXG4gICAqXG4gICAqIEFsd2F5cyByZXR1cm5zIGEgbmV3IGRhdGUuXG4gICAqL1xuICBhYnN0cmFjdCBnZXRQcmV2KGRhdGU6IE5nYkRhdGUsIHBlcmlvZD86IE5nYlBlcmlvZCwgbnVtYmVyPzogbnVtYmVyKTogTmdiRGF0ZTtcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgd2VlayBudW1iZXIgZm9yIGEgZ2l2ZW4gd2Vlay5cbiAgICovXG4gIGFic3RyYWN0IGdldFdlZWtOdW1iZXIod2VlazogcmVhZG9ubHkgTmdiRGF0ZVtdLCBmaXJzdERheU9mV2VlazogbnVtYmVyKTogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB0b2RheSdzIGRhdGUuXG4gICAqL1xuICBhYnN0cmFjdCBnZXRUb2RheSgpOiBOZ2JEYXRlO1xuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYSBkYXRlIGlzIHZhbGlkIGluIHRoZSBjdXJyZW50IGNhbGVuZGFyLlxuICAgKi9cbiAgYWJzdHJhY3QgaXNWYWxpZChkYXRlOiBOZ2JEYXRlKTogYm9vbGVhbjtcbn1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE5nYkNhbGVuZGFyR3JlZ29yaWFuIGV4dGVuZHMgTmdiQ2FsZW5kYXIge1xuICBnZXREYXlzUGVyV2VlaygpIHsgcmV0dXJuIDc7IH1cblxuICBnZXRNb250aHMoKSB7IHJldHVybiBbMSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOSwgMTAsIDExLCAxMl07IH1cblxuICBnZXRXZWVrc1Blck1vbnRoKCkgeyByZXR1cm4gNjsgfVxuXG4gIGdldE5leHQoZGF0ZTogTmdiRGF0ZSwgcGVyaW9kOiBOZ2JQZXJpb2QgPSAnZCcsIG51bWJlciA9IDEpIHtcbiAgICBsZXQganNEYXRlID0gdG9KU0RhdGUoZGF0ZSk7XG4gICAgbGV0IGNoZWNrTW9udGggPSB0cnVlO1xuICAgIGxldCBleHBlY3RlZE1vbnRoID0ganNEYXRlLmdldE1vbnRoKCk7XG5cbiAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgY2FzZSAneSc6XG4gICAgICAgIGpzRGF0ZS5zZXRGdWxsWWVhcihqc0RhdGUuZ2V0RnVsbFllYXIoKSArIG51bWJlcik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbSc6XG4gICAgICAgIGV4cGVjdGVkTW9udGggKz0gbnVtYmVyO1xuICAgICAgICBqc0RhdGUuc2V0TW9udGgoZXhwZWN0ZWRNb250aCk7XG4gICAgICAgIGV4cGVjdGVkTW9udGggPSBleHBlY3RlZE1vbnRoICUgMTI7XG4gICAgICAgIGlmIChleHBlY3RlZE1vbnRoIDwgMCkge1xuICAgICAgICAgIGV4cGVjdGVkTW9udGggPSBleHBlY3RlZE1vbnRoICsgMTI7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdkJzpcbiAgICAgICAganNEYXRlLnNldERhdGUoanNEYXRlLmdldERhdGUoKSArIG51bWJlcik7XG4gICAgICAgIGNoZWNrTW9udGggPSBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gZGF0ZTtcbiAgICB9XG5cbiAgICBpZiAoY2hlY2tNb250aCAmJiBqc0RhdGUuZ2V0TW9udGgoKSAhPT0gZXhwZWN0ZWRNb250aCkge1xuICAgICAgLy8gdGhpcyBtZWFucyB0aGUgZGVzdGluYXRpb24gbW9udGggaGFzIGxlc3MgZGF5cyB0aGFuIHRoZSBpbml0aWFsIG1vbnRoXG4gICAgICAvLyBsZXQncyBnbyBiYWNrIHRvIHRoZSBlbmQgb2YgdGhlIHByZXZpb3VzIG1vbnRoOlxuICAgICAganNEYXRlLnNldERhdGUoMCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZyb21KU0RhdGUoanNEYXRlKTtcbiAgfVxuXG4gIGdldFByZXYoZGF0ZTogTmdiRGF0ZSwgcGVyaW9kOiBOZ2JQZXJpb2QgPSAnZCcsIG51bWJlciA9IDEpIHsgcmV0dXJuIHRoaXMuZ2V0TmV4dChkYXRlLCBwZXJpb2QsIC1udW1iZXIpOyB9XG5cbiAgZ2V0V2Vla2RheShkYXRlOiBOZ2JEYXRlKSB7XG4gICAgbGV0IGpzRGF0ZSA9IHRvSlNEYXRlKGRhdGUpO1xuICAgIGxldCBkYXkgPSBqc0RhdGUuZ2V0RGF5KCk7XG4gICAgLy8gaW4gSlMgRGF0ZSBTdW49MCwgaW4gSVNPIDg2MDEgU3VuPTdcbiAgICByZXR1cm4gZGF5ID09PSAwID8gNyA6IGRheTtcbiAgfVxuXG4gIGdldFdlZWtOdW1iZXIod2VlazogcmVhZG9ubHkgTmdiRGF0ZVtdLCBmaXJzdERheU9mV2VlazogbnVtYmVyKSB7XG4gICAgLy8gaW4gSlMgRGF0ZSBTdW49MCwgaW4gSVNPIDg2MDEgU3VuPTdcbiAgICBpZiAoZmlyc3REYXlPZldlZWsgPT09IDcpIHtcbiAgICAgIGZpcnN0RGF5T2ZXZWVrID0gMDtcbiAgICB9XG5cbiAgICBjb25zdCB0aHVyc2RheUluZGV4ID0gKDQgKyA3IC0gZmlyc3REYXlPZldlZWspICUgNztcbiAgICBsZXQgZGF0ZSA9IHdlZWtbdGh1cnNkYXlJbmRleF07XG5cbiAgICBjb25zdCBqc0RhdGUgPSB0b0pTRGF0ZShkYXRlKTtcbiAgICBqc0RhdGUuc2V0RGF0ZShqc0RhdGUuZ2V0RGF0ZSgpICsgNCAtIChqc0RhdGUuZ2V0RGF5KCkgfHwgNykpOyAgLy8gVGh1cnNkYXlcbiAgICBjb25zdCB0aW1lID0ganNEYXRlLmdldFRpbWUoKTtcbiAgICBqc0RhdGUuc2V0TW9udGgoMCk7ICAvLyBDb21wYXJlIHdpdGggSmFuIDFcbiAgICBqc0RhdGUuc2V0RGF0ZSgxKTtcbiAgICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLnJvdW5kKCh0aW1lIC0ganNEYXRlLmdldFRpbWUoKSkgLyA4NjQwMDAwMCkgLyA3KSArIDE7XG4gIH1cblxuICBnZXRUb2RheSgpOiBOZ2JEYXRlIHsgcmV0dXJuIGZyb21KU0RhdGUobmV3IERhdGUoKSk7IH1cblxuICBpc1ZhbGlkKGRhdGU6IE5nYkRhdGUpOiBib29sZWFuIHtcbiAgICBpZiAoIWRhdGUgfHwgIWlzSW50ZWdlcihkYXRlLnllYXIpIHx8ICFpc0ludGVnZXIoZGF0ZS5tb250aCkgfHwgIWlzSW50ZWdlcihkYXRlLmRheSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyB5ZWFyIDAgZG9lc24ndCBleGlzdCBpbiBHcmVnb3JpYW4gY2FsZW5kYXJcbiAgICBpZiAoZGF0ZS55ZWFyID09PSAwKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QganNEYXRlID0gdG9KU0RhdGUoZGF0ZSk7XG5cbiAgICByZXR1cm4gIWlzTmFOKGpzRGF0ZS5nZXRUaW1lKCkpICYmIGpzRGF0ZS5nZXRGdWxsWWVhcigpID09PSBkYXRlLnllYXIgJiYganNEYXRlLmdldE1vbnRoKCkgKyAxID09PSBkYXRlLm1vbnRoICYmXG4gICAgICAgIGpzRGF0ZS5nZXREYXRlKCkgPT09IGRhdGUuZGF5O1xuICB9XG59XG4iXX0=