Subversion Repository Public Repository

Nextrek

Diff Revisions 1085 vs 1086 for /s2s/data/118CE96FK8F58A440CSAA11E22CCAF101A06.json

Diff revisions: vs.
  @@ -6,10 +6,10 @@
6 6 "name": "Component_MessageTextRenderer",
7 7 "type": "game_script",
8 8 "order": 11,
9 - "content": "# ===================================================================\n#\n# Script: Component_MessageTextRenderer\n#\n# $$COPYRIGHT$$\n#\n# ===================================================================\nclass Component_MessageTextRenderer extends gs.Component_TextRenderer\n @objectCodecBlackList = [\"onLinkClick\", \"onBatchDisappear\"]\n ###*\n * Called if this object instance is restored from a data-bundle. It can be used\n * re-assign event-handler, anonymous functions, etc.\n * \n * @method onDataBundleRestore.\n * @param Object data - The data-bundle\n * @param gs.ObjectCodecContext context - The codec-context.\n ###\n onDataBundleRestore: (data, context) ->\n @setupEventHandlers()\n l = 0\n \n for message in @object.messages\n if @object.settings.useCharacterColor\n @object.font.color = new gs.Color(message.character.textColor)\n @lines = @calculateLines(lcsm(message.text), yes, 0)\n for line in @lines\n bitmap = @createBitmap(line)\n if line == @line\n @drawLineContent(line, bitmap, @charIndex+1)\n else\n @drawLineContent(line, bitmap, -1)\n @allSprites[l].bitmap = bitmap\n l++\n \n \n for customObject in @customObjects\n SceneManager.scene.addObject(customObject)\n \n return null\n \n ###*\n * A text-renderer component to render an animated and interactive message text using\n * dimensions of the game object's destination-rectangle. The message is displayed\n * using a sprite for each line instead of drawing to the game object's bitmap object.\n *\n * @module gs\n * @class Component_MessageTextRenderer\n * @extends gs.Component_TextRenderer\n * @memberof gs\n * @constructor\n ###\n constructor: ->\n super\n \n ###*\n * An array containing all sprites of the current message.\n * @property sprites\n * @type gs.Sprite[]\n * @protected\n ###\n @sprites = []\n \n ###*\n * An array containing all sprites of all messages. In NVL mode\n * a page can contain multiple messages.\n * @property allSprites\n * @type gs.Sprite[]\n * @protected\n ###\n @allSprites = []\n ###*\n * An array containing all line-objects of the current message.\n * @property lines\n * @type gs.TextRendererLine[]\n * @readOnly\n ###\n @lines = null\n \n ###*\n * The line currently rendered.\n * @property line\n * @type number\n * @readOnly\n ###\n @line = 0\n \n ###*\n * The left and right padding per line.\n * @property padding\n * @type number\n ###\n @padding = 6\n \n ###*\n * The minimum height of the line currently rendered. If 0, the measured\n * height of the line will be used.\n * @property minLineHeight\n * @type number\n ###\n @minLineHeight = 0\n \n ###*\n * The spacing between text lines in pixels.\n * @property lineSpacing\n * @type number\n ###\n @lineSpacing = 2\n \n ###*\n * The line currently rendered.\n * @property currentLine\n * @type number\n * @protected\n ###\n @currentLine = 0\n \n ###*\n * The height of the line currently rendered.\n * @property currentLineHeight\n * @type number\n * @protected\n ###\n @currentLineHeight = 0\n \n ###*\n * Index of the current character to draw.\n * @property charIndex\n * @type number\n * @readOnly\n ###\n @charIndex = 0\n \n ###*\n * Position of the message caret. The caret is like an invisible\n * cursor pointing to the x/y coordinates of the last rendered character of\n * the message. That position can be used to display a waiting- or processing-animation for example.\n * @property caretPosition\n * @type gs.Point\n * @readOnly\n ###\n @caretPosition = new gs.Point()\n \n ###*\n * Indicates that the a message is currently in progress.\n * @property isRunning\n * @type boolean\n * @readOnly\n ###\n @isRunning = no\n \n ###*\n * The current x-coordinate of the caret/cursor.\n * @property currentX\n * @type number\n * @readOnly\n ###\n @currentX = 0\n \n ###*\n * The current y-coordinate of the caret/cursor.\n * @property currentY\n * @type number\n * @readOnly\n ###\n @currentY = 0\n \n ###*\n * The current sprites used to display the current text-line/part.\n * @property currentSprite\n * @type gs.Sprite\n * @readOnly\n ###\n @currentSprite = null\n \n ###*\n * Indicates if the message-renderer is currently waiting like for a user-action.\n * @property isWaiting\n * @type boolean\n * @readOnly\n ###\n @isWaiting = no\n \n ###*\n * Indicates if the message-renderer is currently waiting for a key-press or mouse/touch action.\n * @property waitForKey\n * @type boolean\n * @readOnly\n ###\n @waitForKey = no\n \n ###*\n * Number of frames the message-renderer should wait before continue.\n * @property waitCounter\n * @type number\n ###\n @waitCounter = 0\n \n ###*\n * Speed of the message-drawing. The smaller the value, the faster the message is displayed.\n * @property speed\n * @type number\n ###\n @speed = 1\n \n ###*\n * Indicates if the message should be rendered immedialtely without any animation or delay.\n * @property drawImmediately\n * @type boolean\n ###\n @drawImmediately = no\n \n ###*\n * Indicates if the message should wait for a user-action or a certain amount of time\n * before finishing.\n * @property waitAtEnd\n * @type boolean\n ###\n @waitAtEnd = yes\n \n ###*\n * The number of frames to wait before finishing a message.\n * before finishing.\n * @property waitAtEndTime\n * @type number\n ###\n @waitAtEndTime = 0\n \n ###*\n * Indicates if auto word-wrap should be used. Default is <b>true</b>\n * @property wordWrap\n * @type boolean\n ###\n @wordWrap = yes\n \n ###*\n * Custom game objects which are alive until the current message is erased. Can be used to display\n * animated icons, etc.\n * @property customObjects\n * @type gs.Object_Base[]\n ###\n @customObjects = []\n \n ###*\n * A hashtable/dictionary object to store custom-data useful like for token-processing. The data must be\n * serializable.\n * @property customObjects\n * @type Object\n ###\n @customData = {}\n \n ###*\n * A callback function called if the player clicks on a non-stylable link (LK text-code) to trigger\n * the specified common event.\n * @property onLinkClick\n * @type Function\n ###\n @onLinkClick = (e) ->\n eventId = e.data.linkData.commonEventId\n event = RecordManager.commonEvents[eventId]\n if !event\n event = RecordManager.commonEvents.first (x) => x.name == eventId\n eventId = event.index if event\n SceneManager.scene.interpreter.callCommonEvent(eventId, null, yes)\n \n ###*\n * A callback function called if a batched messsage has been faded out. It triggers the execution of\n * the next message.\n * @property onBatchDisappear\n * @type Function\n ### \n @onBatchDisappear = (e) => \n @drawImmediately = no\n @isWaiting = no\n @object.opacity = 255\n @executeBatch()\n \n ###*\n * Serializes the message text-renderer into a data-bundle.\n * @method toDataBundle\n * @return {Object} A data-bundle.\n ###\n toDataBundle: ->\n ignore = [\"object\", \"font\", \"sprites\", \"allSprites\", \"currentSprite\", \"currentX\"]\n bundle = { currentSpriteIndex: @sprites.indexOf(@currentSprite) }\n \n for k of this\n if ignore.indexOf(k) == -1\n bundle[k] = this[k]\n \n return bundle\n \n \n \n ###*\n * Disposes the message text-renderer and all sprites used to display\n * the message.\n * @method dispose\n ###\n dispose: ->\n super\n \n gs.GlobalEventManager.offByOwner(\"mouseUp\", @object)\n gs.GlobalEventManager.offByOwner(\"keyUp\", @object)\n \n for sprite in @allSprites\n sprite.bitmap?.dispose()\n sprite.dispose()\n \n ###*\n * Adds event-handlers for mouse/touch events\n *\n * @method setupEventHandlers\n ### \n setupEventHandlers: ->\n gs.GlobalEventManager.offByOwner(\"mouseUp\", @object)\n gs.GlobalEventManager.offByOwner(\"keyUp\", @object)\n \n gs.GlobalEventManager.on \"mouseUp\", ((e) =>\n return if (GameManager.settings.autoMessage.enabled and !GameManager.settings.autoMessage.stopOnAction)\n \n #if @object.dstRect.contains(Input.Mouse.x - @object.origin.x, Input.Mouse.y - @object.origin.y)\n if @isWaiting and not (@waitCounter > 0 or @waitForKey)\n e.breakChain = yes\n @continue()\n else\n e.breakChain = @isRunning\n @drawImmediately = !@waitForKey\n @waitCounter = 0\n @waitForKey = no\n @isWaiting = no\n \n if @waitForKey\n if Input.Mouse.buttons[Input.Mouse.LEFT] == 2\n e.breakChain = yes\n Input.clear()\n @waitForKey = no\n @isWaiting = no\n \n \n \n \n ), null, @object\n \n gs.GlobalEventManager.on \"keyUp\", ((e) =>\n if Input.keys[Input.C] and (!@isWaiting or (@waitCounter > 0 or @waitForKey))\n @drawImmediately = !@waitForKey\n @waitCounter = 0\n @waitForKey = no\n @isWaiting = no\n \n if @isWaiting and !@waitForKey and !@waitCounter and Input.keys[Input.C]\n @continue()\n \n if @waitForKey\n if Input.keys[Input.C]\n Input.clear()\n @waitForKey = no\n @isWaiting = no\n \n ), null, @object\n \n ###*\n * Sets up the renderer. Registers necessary event handlers.\n * @method setup\n ### \n setup: ->\n @setupEventHandlers()\n \n ###*\n * Restores the message text-renderer's state from a data-bundle.\n * @method restore\n * @param {Object} bundle - A data-bundle containing message text-renderer state.\n ###\n restore: (bundle) ->\n for k of bundle\n if k == \"currentSpriteIndex\"\n @currentSprite = @sprites[bundle.currentSpriteIndex]\n else\n this[k] = bundle[k]\n \n if @sprites.length > 0\n @currentY = @sprites.last().y - @object.origin.y - @object.dstRect.y\n @line = @maxLines\n @isWaiting = @isWaiting || @isRunning\n \n return null \n \n \n ###*\n * Continues message-processing if currently waiting.\n * @method continue\n ###\n continue: -> \n #Input.clear()\n @isWaiting = no\n \n if @line >= @lines.length\n @isRunning = no\n @object.events?.emit(\"messageFinish\", this)\n else\n @object.events?.emit(\"messageBatch\", this)\n fading = GameManager.tempSettings.messageFading\n duration = if GameManager.tempSettings.skip then 0 else fading.duration\n @object.animator.disappear(fading.animation, fading.easing, duration, gs.CallBack(\"onBatchDisappear\", this))\n #@executeBatch()\n \n ###*\n * Updates the text-renderer.\n * @method update\n ###\n update: ->\n for sprite in @allSprites\n sprite.opacity = @object.opacity\n sprite.visible = @object.visible\n sprite.ox = -@object.offset.x\n sprite.oy = -@object.offset.y\n sprite.mask.value = @object.mask.value\n sprite.mask.vague = @object.mask.vague\n sprite.mask.source = @object.mask.source\n sprite.mask.type = @object.mask.type\n \n for object in @customObjects\n object.opacity = @object.opacity\n object.visible = @object.visible\n \n if not @isRunning and @waitCounter > 0\n @waitCounter--\n if @waitCounter == 0\n @continue()\n return\n \n if @object.visible and @lines?.length > 0\n @updateLineWriting()\n @updateWaitForKey()\n @updateWaitCounter()\n @updateCaretPosition()\n \n \n ###*\n * Indicates if its a batched messages.\n *\n * @method isBatched\n * @return If <b>true</b> it is a batched message. Otherwise <b>false</b>.\n ###\n isBatched: -> @lines.length > @maxLines\n \n ###*\n * Indicates if the batch is still in progress and not done.\n *\n * @method isBatchInProgress\n * @return If <b>true</b> the batched message is still not done. Otherwise <b>false</b>\n ###\n isBatchInProgress: -> @lines.length - @line > @maxLines\n \n ###*\n * Starts displaying the next page of text if a message is too long to fit\n * into one message box.\n *\n * @method executeBatch\n ### \n executeBatch: ->\n @clearAllSprites()\n @lines = @lines.slice(@line)\n @line = 0\n @currentX = 0\n @currentY = 0 \n @currentLineHeight = 0\n @tokenIndex = 0\n @charIndex = 0\n @token = @lines[@line].content[@tokenIndex] || new gs.RendererToken(null, \"\");\n @maxLines = @calculateMaxLines(@lines)\n @lineAnimationCount = @speed\n @sprites = @createSprites(@lines)\n @allSprites = @allSprites.concat(@sprites)\n @currentSprite = @sprites[@line]\n @currentSprite.x = @currentX + @object.origin.x + @object.dstRect.x\n @drawNext()\n \n ###*\n * Calculates the duration(in frames) the message-renderer needs to display\n * the message.\n *\n * @method calculateDuration\n * @return {number} The duration in frames.\n ### \n calculateDuration: ->\n duration = 0\n \n if @lines?\n for line in @lines\n for token in line.content\n if token?\n duration += @calculateDurationForToken(token)\n return duration\n \n ###*\n * Calculates the duration(in frames) the message-renderer needs to display\n * the specified line.\n *\n * @method calculateDurationForLine\n * @param {gs.RendererTextLine} line The line to calculate the duration for.\n * @return {number} The duration in frames.\n ### \n calculateDurationForLine: (line) ->\n duration = 0\n \n if line\n for token in line.content\n if token?\n duration += @calculateDurationForToken(token)\n \n return duration\n \n ###*\n * Calculates the duration(in frames) the message-renderer needs to process\n * the specified token.\n *\n * @method calculateDurationForToken\n * @param {string|Object} token - The token.\n * @return {number} The duration in frames.\n ### \n calculateDurationForToken: (token) ->\n duration = 0\n \n if token.code?\n switch token.code\n when \"W\"\n if token.value != \"A\"\n duration = token.value / 1000 * Graphics.frameRate\n else\n duration = token.value.length * @speed\n \n return duration\n \n ###*\n * Calculates the maximum of lines which can be displayed in one message.\n *\n * @method calculateMaxLines\n * @param {Array} lines - An array of line-objects.\n * @return {number} The number of displayable lines.\n ###\n calculateMaxLines: (lines) ->\n height = 0\n result = 0\n \n for line in lines\n height += line.height + @lineSpacing\n if @currentY+height > (@object.dstRect.height)\n break\n result++\n \n return Math.min(lines.length, result || 1)\n \n ###*\n * Displays the character or processes the next control-token.\n *\n * @method drawNext\n ###\n drawNext: ->\n token = @processToken()\n \n if token?.value.length > 0\n @char = @token.value.charAt(@charIndex)\n \n size = @font.measureTextPlain(@char) \n s = Graphics.scale \n lineSpacing = @lineSpacing\n \n if @currentLine != @line\n @currentLine = @line\n # @currentY += @currentLineHeight + lineSpacing * Graphics.scale\n @currentLineHeight = 0\n\n @currentSprite.y = @object.origin.y + @object.dstRect.y + @currentY\n @currentSprite.visible = yes\n @drawLineContent(@lines[@line], @currentSprite.bitmap, @charIndex+1)\n @currentSprite.srcRect.width = @currentSprite.bitmap.width #Math.min(@currentSprite.srcRect.width + size.width, @currentSprite.bitmap.width)\n \n @currentLineHeight = @lines[@line].height\n @currentX = Math.min(@lines[@line].width, @currentX + size.width)\n \n ###*\n * Processes the next character/token of the message.\n * @method nextChar\n * @private\n ###\n nextChar: ->\n loop\n @charIndex++\n @lineAnimationCount = @speed\n \n if @token.code? or @charIndex >= @token.value.length\n @token.onEnd?()\n @tokenIndex++\n if @tokenIndex >= @lines[@line].content.length\n @tokenIndex = 0\n @line++\n @currentSprite.srcRect.width = @currentSprite.bitmap.width\n @currentSprite = @sprites[@line]\n if @currentSprite?\n @currentSprite.x = @object.origin.x + @object.dstRect.x\n if @line < @maxLines\n @currentY += (@currentLineHeight || @font.lineHeight) + @lineSpacing * Graphics.scale\n @charIndex = 0\n @currentX = 0\n @token = @lines[@line].content[@tokenIndex] || new gs.RendererToken(null, \"\")\n else\n @charIndex = 0\n @token = @lines[@line].content[@tokenIndex] || new gs.RendererToken(null, \"\")\n @token.onStart?()\n\n \n if !@token or @token.value != \"\\n\" or !@lines[@line]\n break\n ###*\n * Finishes the message. Depending on the message configuration, the\n * message text-renderer will now wait for a user-action or a certain amount\n * of time.\n *\n * @method finish\n ###\n finish: ->\n if @waitAtEnd\n @isWaiting = yes\n @object.events?.emit(\"messageWaiting\", this)\n else if @waitAtEndTime > 0\n @waitCounter = @waitAtEndTime\n @isWaiting = no\n \n @object.events?.emit(\"messageWaiting\", this)\n else\n @object.events?.emit(\"messageWaiting\", this)\n @continue()\n \n ###*\n * Returns the position of the caret in pixels. The caret is like an invisible\n * cursor pointing to the x/y coordinates of the last rendered character of\n * the message. That position can be used to display a waiting- or processing-animation for example.\n *\n * @method updateCaretPosition\n ###\n updateCaretPosition: -> \n @caretPosition.x = @currentX + @padding \n @caretPosition.y = @currentY + @currentLineHeight/2\n \n ###*\n * Updates the line writing.\n *\n * @method updateLineWriting\n * @private\n ###\n updateLineWriting: ->\n if @isRunning and !@isWaiting and !@waitForKey and @waitCounter <= 0\n if @lineAnimationCount <= 0\n loop\n if @line < @maxLines\n @nextChar()\n \n if @line >= @maxLines\n @finish()\n else\n @drawNext()\n \n break unless (@token.code or @lineAnimationCount <= 0 or @drawImmediately) and !@waitForKey and @waitCounter <= 0 and @isRunning and @line < @maxLines\n \n if GameManager.tempSettings.skip\n @lineAnimationCount = 0\n else\n @lineAnimationCount--\n \n ###*\n * Updates wait-for-key state. If skipping is enabled, the text renderer will\n * not wait for key press.\n *\n * @method updateWaitForKey\n * @private\n ###\n updateWaitForKey: ->\n if @waitForKey\n @isWaiting = !GameManager.tempSettings.skip\n @waitForKey = @isWaiting\n \n ###*\n * Updates wait counter if the text renderer is waiting for a certain amount of time to pass. If skipping is enabled, the text renderer will\n * not wait for the actual amount of time and sets the wait-counter to 1 frame instead.\n *\n * @method updateWaitForKey\n * @private\n ### \n updateWaitCounter: ->\n if @waitCounter > 0\n if GameManager.tempSettings.skip\n @waitCounter = 1\n @isWaiting = yes\n @waitCounter--\n if @waitCounter <= 0\n @isWaiting = no\n @continue() if @line >= @maxLines\n \n ###*\n * Creates a token-object for a specified text-code.\n * \n * @method createToken\n * @param {string} code - The code/type of the text-code.\n * @param {string} value - The value of the text-code.\n * @return {Object} The token-object.\n ###\n createToken: (code, value) ->\n tokenObject = null\n \n switch code\n when \"CE\"\n data = value.split(\"/\")\n value = data.shift()\n value = if isNaN(value) then value else parseInt(value)\n for i in [0...data]\n if data[i].startsWith('\"') and data[i].endsWith('\"')\n data[i] = data[i].substring(1, data[i].length-1)\n else\n data[i] = if isNaN(data[i]) then data[i] else parseFloat(data[i])\n tokenObject = { code: code, value: value, values: data }\n else\n tokenObject = super(code, value)\n \n \n return tokenObject \n ###*\n * <p>Measures a control-token. If a token produces a visual result like displaying an icon then it must return the size taken by\n * the visual result. If the token has no visual result, <b>null</b> must be returned. This method is called for every token when the message is initialized.</p> \n *\n * <p>This method is not called while the message is running. For that case, see <i>processControlToken</i> method which is called\n * for every token while the message is running.</p>\n *\n * @param {Object} token - A control-token.\n * @return {gs.Size} The size of the area taken by the visual result of the token or <b>null</b> if the token has no visual result.\n * @method analyzeControlToken\n * @protected\n ###\n measureControlToken: (token) -> return super(token)\n \n ###*\n * <p>Draws the visual result of a token, like an icon for example, to the specified bitmap. This method is called for every token when the message is initialized and the sprites for each\n * text-line are created.</p> \n *\n * <p>This method is not called while the message is running. For that case, see <i>processControlToken</i> method which is called\n * for every token while the message is running.</p>\n *\n * @param {Object} token - A control-token.\n * @param {gs.Bitmap} bitmap - The bitmap used for the current text-line. Can be used to draw something on it like an icon, etc.\n * @param {number} offset - An x-offset for the draw-routine.\n * @param {number} length - Determines how many characters of the token should be drawn. Can be ignored for tokens\n * not drawing any characters.\n * @method drawControlToken\n * @protected\n ###\n drawControlToken: (token, bitmap, offset, length) ->\n switch token.code\n when \"RT\" # Ruby Text\n super(token, bitmap, offset, length)\n \n \n ###*\n * Processes a control-token. A control-token is a token which influences\n * the text-rendering like changing the fonts color, size or style. Changes \n * will be automatically applied to the game object's font.\n *\n * For message text-renderer, a few additional control-tokens like\n * speed-change, waiting, etc. needs to be processed here.\n *\n * This method is called for each token while the message is initialized and\n * also while the message is running. See <i>formattingOnly</i> parameter.\n *\n * @param {Object} token - A control-token.\n * @param {boolean} formattingOnly - If <b>true</b> the message is initializing right now and only \n * format-tokens should be processed which is necessary for the message to calculated sizes correctly.\n * @return {Object} A new token which is processed next or <b>null</b>.\n * @method processControlToken\n * @protected\n ###\n processControlToken: (token, formattingOnly) ->\n return super(token) if formattingOnly\n result = null\n \n switch token.code\n when \"CR\" # Change Current Character\n character = RecordManager.charactersArray.first (c) -> (c.name.defaultText ? c.name) == token.value\n if character\n SceneManager.scene.currentCharacter = character\n when \"CE\" # Call Common Event\n params = { \"values\": token.values }\n @object.events?.emit(\"callCommonEvent\", @object, { commonEventId: token.value, params: params, finish: no, waiting: yes })\n when \"X\" # Script\n token.value?(@object)\n when \"A\" # Play Animation\n animation = RecordManager.animations[Math.max(token.value-1, 0)]\n if animation?.graphic.name?\n bitmap = ResourceManager.getBitmap(\"Graphics/Pictures/#{animation.graphic.name}\")\n object = new gs.Object_Animation(animation)\n \n @addCustomObject(object)\n @currentX += Math.round(bitmap.width / animation.framesX)\n @currentSprite.srcRect.width += Math.round(bitmap.width / animation.framesX)\n \n when \"RT\" # Ruby Text\n if token.rtSize.width > token.rbSize.width\n @currentX += token.rtSize.width\n @font.set(@getRubyTextFont(token))\n else\n @currentX += token.rbSize.width\n \n when \"LK\" # Link \n if token.value == 'E' # End Link\n object = new ui.Object_Hotspot()\n object.enabled = yes\n object.setup()\n \n @addCustomObject(object)\n \n object.dstRect.x = @object.dstRect.x + @object.origin.x + @customData.linkData.cx\n object.dstRect.y = @object.dstRect.y + @object.origin.y + @customData.linkData.cy\n object.dstRect.width = @currentX - @customData.linkData.cx\n object.dstRect.height = @currentLineHeight\n\n object.events.on(\"click\", gs.CallBack(\"onLinkClick\", this), linkData: @customData.linkData, this)\n else # Begin Link\n @customData.linkData = { cx: @currentX, cy: @currentY, commonEventId: token.value, tokenIndex: @tokenIndex }\n when \"SLK\" # Styleable Link\n if token.value == 'E' # End Link\n @currentSprite.bitmap.clearRect(@customData.linkData.cx,\n @customData.linkData.cy,\n @currentX - @customData.linkData.cx + @object.font.borderSize*2,\n @currentLineHeight)\n line = @lines[@line].content\n linkStart = @findToken(@tokenIndex-1, \"SLK\", -1, line)\n textTokens = @findTokensBetween(@customData.linkData.tokenIndex, @tokenIndex, null, line)\n \n object = new ui.Object_Text()\n object.text = textTokens.select((x) => x.value).join(\"\")\n object.sizeToFit = yes\n object.formatting = yes\n object.wordWrap = no\n object.ui = new ui.Component_UIBehavior()\n object.enabled = yes\n object.addComponent(object.ui)\n object.addComponent(new gs.Component_HotspotBehavior())\n \n if @customData.linkData.styleIndex == -1\n ui.UIManager.addControlStyles(object, [\"hyperlink\"])\n else \n ui.UIManager.addControlStyles(object, [\"hyperlink-\"+@customData.linkData.styleIndex])\n \n object.setup()\n \n @addCustomObject(object)\n \n object.dstRect.x = @object.dstRect.x + @object.origin.x + @customData.linkData.cx\n object.dstRect.y = @object.dstRect.y + @object.origin.y + @customData.linkData.cy\n\n object.events.on(\"click\", gs.CallBack(\"onLinkClick\", this), linkData: @customData.linkData, this)\n else # Begin Link\n if token.value?.contains(\",\")\n values = token.value.split(\",\")\n @customData.linkData = { cx: @currentX, cy: @currentY, commonEventId: values[0], styleIndex: parseInt(values[1]), tokenIndex: @tokenIndex }\n else\n @customData.linkData = { cx: @currentX, cy: @currentY, commonEventId: token.value, tokenIndex: @tokenIndex, styleIndex: -1 }\n \n when \"E\" # Change Expression\n expression = RecordManager.characterExpressions[Math.max(token.value-1, 0)]\n character = SceneManager.scene.currentCharacter\n if expression? and character?.index?\n duration = GameManager.defaults.character.expressionDuration\n easing = gs.Easings.fromObject(GameManager.defaults.character.changeEasing)\n animation = GameManager.defaults.character.changeAnimation\n object = SceneManager.scene.characters.first (c) -> c.rid == character.index\n object?.behavior.changeExpression(expression, animation, easing, duration)\n \n when \"SP\" # Play Sound\n sound = RecordManager.system.sounds[token.value-1]\n AudioManager.playSound(sound)\n when \"S\" # Change Speed\n GameManager.settings.messageSpeed = token.value\n when \"W\" # Wait\n @drawImmediately = no\n if !GameManager.tempSettings.skip\n if token.value == \"A\"\n @waitForKey = yes\n else\n @waitCounter = Math.round(token.value / 1000 * Graphics.frameRate)\n when \"WE\" # Wait at End\n @waitAtEnd = token.value == \"Y\"\n when \"DI\" # Draw Immedialty\n @drawImmediately = token.value == 1 or token.value == \"Y\" # Draw immediately\n else\n result = super(token)\n \n return result \n ###*\n * Clears/Resets the text-renderer.\n *\n * @method clear\n ###\n clear: ->\n @charIndex = 0\n @currentX = 0\n @currentY = 0\n @line = 0\n @lines = []\n @clearCustomObjects()\n @object.bitmap?.clear()\n \n for sprite in @allSprites\n sprite.dispose()\n sprite.bitmap?.dispose()\n @allSprites = []\n return null\n \n ###*\n * Clears/Disposes all sprites used to display the text-lines/parts.\n *\n * @method clearAllSprites\n ###\n clearAllSprites: ->\n for sprite in @allSprites\n sprite.dispose()\n sprite.bitmap?.dispose()\n \n return null\n \n ###*\n * Clears/Disposes the sprites used to display the text-lines/parts of the current/last message.\n *\n * @method clearSprites\n ### \n clearSprites: ->\n for sprite in @sprites\n sprite.dispose()\n sprite.bitmap?.dispose()\n \n return null\n \n \n ###*\n * Removes a game object from the message.\n *\n * @method removeCustomObject\n * @param object {gs.Object_Base} The game object to remove.\n ###\n removeCustomObject: (object) ->\n SceneManager.scene.removeObject(object)\n object.dispose()\n @customObjects.remove(object)\n \n ###*\n * Adds a game object to the message which is alive until the message is\n * erased. Can be used to display animationed-icons, etc. in a message.\n *\n * @method addCustomObject\n * @param object {gs.Object_Base} The game object to add.\n ###\n addCustomObject: (object) ->\n object.dstRect.x = @object.dstRect.x + @object.origin.x + @currentX\n object.dstRect.y = @object.dstRect.y + @object.origin.y + @currentY\n object.zIndex = @object.zIndex + 1\n object.update()\n \n SceneManager.scene.addObject(object)\n @customObjects.push(object)\n \n ###*\n * Clears the list of custom game objects. All game objects are disposed and removed\n * from the scene.\n *\n * @method clearCustomObjects\n * @param object {Object} The game object to add.\n ### \n clearCustomObjects: ->\n for object in @customObjects\n object.dispose()\n SceneManager.scene.removeObject(object)\n \n @customObjects = []\n \n ###*\n * Creates the bitmap for a specified line-object.\n *\n * @method createBitmap\n * @private\n * @param {Object} line - A line-object.\n * @return {Bitmap} A newly created bitmap containing the line-text.\n ###\n createBitmap: (line) ->\n @font = @object.font\n bitmap = new Bitmap(@object.dstRect.width, Math.max(@minLineHeight, line.height))\n bitmap.font = @font\n \n return bitmap\n \n ###*\n * Draws the line's content on the specified bitmap.\n *\n * @method drawLineContent\n * @protected\n * @param {Object} line - A line-object which should be drawn on the bitmap.\n * @param {gs.Bitmap} bitmap - The bitmap to draw the line's content on.\n * @param {number} length - Determines how many characters of the specified line should be drawn. You can \n * specify -1 to draw all characters.\n ###\n drawLineContent: (line, bitmap, length) ->\n bitmap.clear()\n currentX = @padding\n drawAll = length == -1\n \n for token, i in line.content\n break if i > @tokenIndex and !drawAll\n if token.code?\n size = @measureControlToken(token, bitmap)\n @drawControlToken(token, bitmap, currentX)\n if size then currentX += size.width\n @processControlToken(token, yes, line)\n else if token.value.length > 0\n token.applyFormat(@font)\n value = token.value\n if !drawAll and @tokenIndex == i and value.length > length\n value = value.substring(0, length)\n if value != \"\\n\"\n size = @font.measureTextPlain(value) \n bitmap.drawText(currentX, line.height - (size.height - @font.descent) - line.descent, size.width, bitmap.height, value, 0, 0)\n currentX += size.width\n \n line.contentWidth = currentX + @font.measureTextPlain(\" \").width \n \n ###*\n * Creates the sprite for a specified line-object.\n *\n * @method createSprite\n * @private\n * @param {Object} line - A line-object.\n * @return {Sprite} A newly created sprite object containing the line-text as bitmap.\n ###\n createSprite: (line) ->\n bitmap = @createBitmap(line)\n \n @currentX = 0\n @waitCounter = 0\n @waitForKey = no\n \n sprite = new Sprite(Graphics.viewport)\n sprite.bitmap = bitmap\n sprite.visible = yes\n sprite.z = @object.zIndex + 1\n \n sprite.srcRect = new Rect(0, 0, 0, bitmap.height)\n \n return sprite\n \n ###*\n * Creates the sprites for a specified array of line-objects.\n *\n * @method createSprites\n * @private\n * @see gs.Component_MessageTextRenderer.createSprite.\n * @param {Array} lines - An array of line-objects.\n * @return {Array} An array of sprites.\n ###\n createSprites: (lines) ->\n @fontSize = @object.font.size\n result = []\n for line, i in lines\n sprite = @createSprite(line)\n result.push(sprite)\n return result\n \n ###*\n * Starts a new line.\n *\n * @method newLine\n ###\n newLine: ->\n @currentX = 0\n @currentY += @currentLineHeight + @lineSpacing\n \n ###*\n * Displays a formatted text immediately without any delays or animations. The\n * Component_TextRenderer.drawFormattedText method from the base-class cannot\n * be used here because it would render to the game object's bitmap object while\n * this method is rendering to the sprites.\n *\n * @method drawFormattedTextImmediately\n * @param {number} x - The x-coordinate of the text's position.\n * @param {number} y - The y-coordinate of the text's position.\n * @param {number} width - Deprecated. Can be null.\n * @param {number} height - Deprecated. Can be null.\n * @param {string} text - The text to draw.\n * @param {boolean} wordWrap - If wordWrap is set to true, line-breaks are automatically created.\n ###\n drawFormattedTextImmediately: (x, y, width, height, text, wordWrap) ->\n @drawFormattedText(x, y, width, height, text, wordWrap)\n \n loop\n @nextChar()\n \n if @line >= @maxLines\n @isRunning = no\n else\n @drawNext()\n \n break unless @isRunning\n \n @currentY += @currentLineHeight + @lineSpacing\n \n return null\n \n \n ###*\n * Starts the rendering-process for the message.\n *\n * @method drawFormattedText\n * @param {number} x - The x-coordinate of the text's position.\n * @param {number} y - The y-coordinate of the text's position.\n * @param {number} width - Deprecated. Can be null.\n * @param {number} height - Deprecated. Can be null.\n * @param {string} text - The text to draw.\n * @param {boolean} wordWrap - If wordWrap is set to true, line-breaks are automatically created.\n ###\n drawFormattedText: (x, y, width, height, text, wordWrap) ->\n text = text || \" \" # Use a space character if no text is specified.\n @font.set(@object.font)\n @speed = 11 - Math.round(GameManager.settings.messageSpeed * 2.5)\n @isRunning = yes\n @drawImmediately = no\n @lineAnimationCount = @speed\n @currentLineHeight = 0\n @isWaiting = no\n @waitForKey = no\n @charIndex = 0\n @token = null\n @tokenIndex = 0\n @message = text\n @line = 0\n @currentLine = @line\n currentX = @currentX\n @lines = @calculateLines(lcsm(@message), wordWrap, @currentX)\n @sprites = @createSprites(@lines)\n @allSprites = @allSprites.concat(@sprites)\n @currentX = currentX\n @currentSprite = @sprites[@line]\n @currentSprite.x = @currentX + @object.origin.x + @object.dstRect.x\n @maxLines = @calculateMaxLines(@lines)\n @token = @lines[@line]?.content[@tokenIndex] || new gs.RendererToken(null, \"\")\n \n \n @start()\n \n ###*\n * Starts the message-rendering process.\n *\n * @method start\n * @protected\n ### \n start: ->\n if GameManager.tempSettings.skip and GameManager.tempSettings.skipTime == 0\n @instantSkip()\n else if @maxLines == 0\n # If first line is empty then it doesn't fit into current line, so finish.\n if @lines[0]?.content == \"\"\n @finish()\n else\n @maxLines = 1\n @drawNext()\n else\n @drawNext()\n \n ###*\n * Skips the current message and finishes the message-processing immediately. The message\n * tokens are processed but not rendered.\n *\n * @method instantSkip\n ### \n instantSkip: ->\n loop\n if @line < @maxLines\n @nextChar()\n \n if @line >= @maxLines\n break\n else\n @processToken()\n \n break unless @isRunning and @line < @maxLines\n \n @object.events?.emit(\"messageWaiting\", this)\n @continue()\n \n ###*\n * Processes the current token.\n *\n * @method processToken\n ### \n processToken: ->\n token = null\n \n if @token.code?\n token = @processControlToken(@token, no)\n if token?\n @token = token\n @token.onStart?()\n else\n token = @token\n \n return token\n \n \n \ngs.Component_MessageTextRenderer = Component_MessageTextRenderer",
9 + "content": "# ===================================================================\n#\n# Script: Component_MessageTextRenderer\n#\n# $$COPYRIGHT$$\n#\n# ===================================================================\nclass Component_MessageTextRenderer extends gs.Component_TextRenderer\n @objectCodecBlackList = [\"onLinkClick\", \"onBatchDisappear\"]\n ###*\n * Called if this object instance is restored from a data-bundle. It can be used\n * re-assign event-handler, anonymous functions, etc.\n * x\n * @method onDataBundleRestore.\n * @param Object data - The data-bundle\n * @param gs.ObjectCodecContext context - The codec-context.\n ###\n onDataBundleRestore: (data, context) ->\n @setupEventHandlers()\n l = 0\n \n for message in @object.messages\n if @object.settings.useCharacterColor\n @object.font.color = new gs.Color(message.character.textColor)\n @lines = @calculateLines(lcsm(message.text), yes, 0)\n for line in @lines\n bitmap = @createBitmap(line)\n if line == @line\n @drawLineContent(line, bitmap, @charIndex+1)\n else\n @drawLineContent(line, bitmap, -1)\n @allSprites[l].bitmap = bitmap\n l++\n \n \n for customObject in @customObjects\n SceneManager.scene.addObject(customObject)\n \n return null\n \n ###*\n * A text-renderer component to render an animated and interactive message text using\n * dimensions of the game object's destination-rectangle. The message is displayed\n * using a sprite for each line instead of drawing to the game object's bitmap object.\n *\n * @module gs\n * @class Component_MessageTextRenderer\n * @extends gs.Component_TextRenderer\n * @memberof gs\n * @constructor\n ###\n constructor: ->\n super\n \n ###*\n * An array containing all sprites of the current message.\n * @property sprites\n * @type gs.Sprite[]\n * @protected\n ###\n @sprites = []\n \n ###*\n * An array containing all sprites of all messages. In NVL mode\n * a page can contain multiple messages.\n * @property allSprites\n * @type gs.Sprite[]\n * @protected\n ###\n @allSprites = []\n ###*\n * An array containing all line-objects of the current message.\n * @property lines\n * @type gs.TextRendererLine[]\n * @readOnly\n ###\n @lines = null\n \n ###*\n * The line currently rendered.\n * @property line\n * @type number\n * @readOnly\n ###\n @line = 0\n \n ###*\n * The left and right padding per line.\n * @property padding\n * @type number\n ###\n @padding = 6\n \n ###*\n * The minimum height of the line currently rendered. If 0, the measured\n * height of the line will be used.\n * @property minLineHeight\n * @type number\n ###\n @minLineHeight = 0\n \n ###*\n * The spacing between text lines in pixels.\n * @property lineSpacing\n * @type number\n ###\n @lineSpacing = 2\n \n ###*\n * The line currently rendered.\n * @property currentLine\n * @type number\n * @protected\n ###\n @currentLine = 0\n \n ###*\n * The height of the line currently rendered.\n * @property currentLineHeight\n * @type number\n * @protected\n ###\n @currentLineHeight = 0\n \n ###*\n * Index of the current character to draw.\n * @property charIndex\n * @type number\n * @readOnly\n ###\n @charIndex = 0\n \n ###*\n * Position of the message caret. The caret is like an invisible\n * cursor pointing to the x/y coordinates of the last rendered character of\n * the message. That position can be used to display a waiting- or processing-animation for example.\n * @property caretPosition\n * @type gs.Point\n * @readOnly\n ###\n @caretPosition = new gs.Point()\n \n ###*\n * Indicates that the a message is currently in progress.\n * @property isRunning\n * @type boolean\n * @readOnly\n ###\n @isRunning = no\n \n ###*\n * The current x-coordinate of the caret/cursor.\n * @property currentX\n * @type number\n * @readOnly\n ###\n @currentX = 0\n \n ###*\n * The current y-coordinate of the caret/cursor.\n * @property currentY\n * @type number\n * @readOnly\n ###\n @currentY = 0\n \n ###*\n * The current sprites used to display the current text-line/part.\n * @property currentSprite\n * @type gs.Sprite\n * @readOnly\n ###\n @currentSprite = null\n \n ###*\n * Indicates if the message-renderer is currently waiting like for a user-action.\n * @property isWaiting\n * @type boolean\n * @readOnly\n ###\n @isWaiting = no\n \n ###*\n * Indicates if the message-renderer is currently waiting for a key-press or mouse/touch action.\n * @property waitForKey\n * @type boolean\n * @readOnly\n ###\n @waitForKey = no\n \n ###*\n * Number of frames the message-renderer should wait before continue.\n * @property waitCounter\n * @type number\n ###\n @waitCounter = 0\n \n ###*\n * Speed of the message-drawing. The smaller the value, the faster the message is displayed.\n * @property speed\n * @type number\n ###\n @speed = 1\n \n ###*\n * Indicates if the message should be rendered immedialtely without any animation or delay.\n * @property drawImmediately\n * @type boolean\n ###\n @drawImmediately = no\n \n ###*\n * Indicates if the message should wait for a user-action or a certain amount of time\n * before finishing.\n * @property waitAtEnd\n * @type boolean\n ###\n @waitAtEnd = yes\n \n ###*\n * The number of frames to wait before finishing a message.\n * before finishing.\n * @property waitAtEndTime\n * @type number\n ###\n @waitAtEndTime = 0\n \n ###*\n * Indicates if auto word-wrap should be used. Default is <b>true</b>\n * @property wordWrap\n * @type boolean\n ###\n @wordWrap = yes\n \n ###*\n * Custom game objects which are alive until the current message is erased. Can be used to display\n * animated icons, etc.\n * @property customObjects\n * @type gs.Object_Base[]\n ###\n @customObjects = []\n \n ###*\n * A hashtable/dictionary object to store custom-data useful like for token-processing. The data must be\n * serializable.\n * @property customObjects\n * @type Object\n ###\n @customData = {}\n \n ###*\n * A callback function called if the player clicks on a non-stylable link (LK text-code) to trigger\n * the specified common event.\n * @property onLinkClick\n * @type Function\n ###\n @onLinkClick = (e) ->\n eventId = e.data.linkData.commonEventId\n event = RecordManager.commonEvents[eventId]\n if !event\n event = RecordManager.commonEvents.first (x) => x.name == eventId\n eventId = event.index if event\n if !event\n SceneManager.scene.interpreter.jumpToLabel(eventId)\n else\n SceneManager.scene.interpreter.callCommonEvent(eventId, null, yes)\n \n ###*\n * A callback function called if a batched messsage has been faded out. It triggers the execution of\n * the next message.\n * @property onBatchDisappear\n * @type Function\n ### \n @onBatchDisappear = (e) => \n @drawImmediately = no\n @isWaiting = no\n @object.opacity = 255\n @executeBatch() \n \n \n ###*\n * Serializes the message text-renderer into a data-bundle.\n * @method toDataBundle\n * @return {Object} A data-bundle.\n ###\n toDataBundle: ->\n ignore = [\"object\", \"font\", \"sprites\", \"allSprites\", \"currentSprite\", \"currentX\"]\n bundle = { currentSpriteIndex: @sprites.indexOf(@currentSprite) }\n \n for k of this\n if ignore.indexOf(k) == -1\n bundle[k] = this[k]\n \n return bundle\n \n \n \n ###*\n * Disposes the message text-renderer and all sprites used to display\n * the message.\n * @method dispose\n ###\n dispose: ->\n super\n \n @disposeEventHandlers()\n \n for sprite in @allSprites\n sprite.bitmap?.dispose()\n sprite.dispose()\n \n ###*\n * Removes all attached event handlers \n * the message.\n * @method disposeEventHandlers\n ### \n disposeEventHandlers: ->\n gs.GlobalEventManager.offByOwner(\"mouseUp\", @object)\n gs.GlobalEventManager.offByOwner(\"keyUp\", @object)\n \n ###*\n * Adds event-handlers for mouse/touch events\n *\n * @method setupEventHandlers\n ### \n setupEventHandlers: ->\n gs.GlobalEventManager.offByOwner(\"mouseUp\", @object)\n gs.GlobalEventManager.offByOwner(\"keyUp\", @object)\n \n gs.GlobalEventManager.on \"mouseUp\", ((e) =>\n return if @object.findComponentByName(\"animation\") or (GameManager.settings.autoMessage.enabled and !GameManager.settings.autoMessage.stopOnAction)\n \n #if @object.dstRect.contains(Input.Mouse.x - @object.origin.x, Input.Mouse.y - @object.origin.y)\n if @isWaiting and not (@waitCounter > 0 or @waitForKey)\n e.breakChain = yes\n @continue()\n else\n e.breakChain = @isRunning\n @drawImmediately = !@waitForKey\n @waitCounter = 0\n @waitForKey = no\n @isWaiting = no\n \n if @waitForKey\n if Input.Mouse.buttons[Input.Mouse.LEFT] == 2\n e.breakChain = yes\n Input.clear()\n @waitForKey = no\n @isWaiting = no\n \n \n \n \n ), null, @object\n \n gs.GlobalEventManager.on \"keyUp\", ((e) =>\n if Input.keys[Input.C] and (!@isWaiting or (@waitCounter > 0 or @waitForKey))\n @drawImmediately = !@waitForKey\n @waitCounter = 0\n @waitForKey = no\n @isWaiting = no\n \n if @isWaiting and !@waitForKey and !@waitCounter and Input.keys[Input.C]\n @continue()\n \n if @waitForKey\n if Input.keys[Input.C]\n Input.clear()\n @waitForKey = no\n @isWaiting = no\n \n ), null, @object\n \n ###*\n * Sets up the renderer. Registers necessary event handlers.\n * @method setup\n ### \n setup: ->\n @setupEventHandlers()\n \n ###*\n * Restores the message text-renderer's state from a data-bundle.\n * @method restore\n * @param {Object} bundle - A data-bundle containing message text-renderer state.\n ###\n restore: (bundle) ->\n for k of bundle\n if k == \"currentSpriteIndex\"\n @currentSprite = @sprites[bundle.currentSpriteIndex]\n else\n this[k] = bundle[k]\n \n if @sprites.length > 0\n @currentY = @sprites.last().y - @object.origin.y - @object.dstRect.y\n @line = @maxLines\n @isWaiting = @isWaiting || @isRunning\n \n return null \n \n \n ###*\n * Continues message-processing if currently waiting.\n * @method continue\n ###\n continue: -> \n @isWaiting = no\n \n if @line >= @lines.length\n @isRunning = no\n @object.events?.emit(\"messageFinish\", this)\n else\n @object.events?.emit(\"messageBatch\", this)\n fading = GameManager.tempSettings.messageFading\n duration = if GameManager.tempSettings.skip then 0 else fading.duration\n @object.animator.disappear(fading.animation, fading.easing, duration, gs.CallBack(\"onBatchDisappear\", this))\n \n ###*\n * Updates the text-renderer.\n * @method update\n ###\n update: ->\n for sprite in @allSprites\n sprite.opacity = @object.opacity\n sprite.visible = @object.visible\n sprite.ox = -@object.offset.x\n sprite.oy = -@object.offset.y\n sprite.mask.value = @object.mask.value\n sprite.mask.vague = @object.mask.vague\n sprite.mask.source = @object.mask.source\n sprite.mask.type = @object.mask.type\n \n for object in @customObjects\n object.opacity = @object.opacity\n object.visible = @object.visible\n \n if not @isRunning and @waitCounter > 0\n @waitCounter--\n if @waitCounter == 0\n @continue()\n return\n \n if @object.visible and @lines?.length > 0\n @updateLineWriting()\n @updateWaitForKey()\n @updateWaitCounter()\n @updateCaretPosition()\n \n \n ###*\n * Indicates if its a batched messages.\n *\n * @method isBatched\n * @return If <b>true</b> it is a batched message. Otherwise <b>false</b>.\n ###\n isBatched: -> @lines.length > @maxLines\n \n ###*\n * Indicates if the batch is still in progress and not done.\n *\n * @method isBatchInProgress\n * @return If <b>true</b> the batched message is still not done. Otherwise <b>false</b>\n ###\n isBatchInProgress: -> @lines.length - @line > @maxLines\n \n ###*\n * Starts displaying the next page of text if a message is too long to fit\n * into one message box.\n *\n * @method executeBatch\n ### \n executeBatch: ->\n @clearAllSprites()\n @lines = @lines.slice(@line)\n @line = 0\n @currentX = 0\n @currentY = 0 \n @currentLineHeight = 0\n @tokenIndex = 0\n @charIndex = 0\n @token = @lines[@line].content[@tokenIndex] || new gs.RendererToken(null, \"\");\n @maxLines = @calculateMaxLines(@lines)\n @lineAnimationCount = @speed\n @sprites = @createSprites(@lines)\n @allSprites = @allSprites.concat(@sprites)\n @currentSprite = @sprites[@line]\n @currentSprite.x = @currentX + @object.origin.x + @object.dstRect.x\n @drawNext()\n \n ###*\n * Calculates the duration(in frames) the message-renderer needs to display\n * the message.\n *\n * @method calculateDuration\n * @return {number} The duration in frames.\n ### \n calculateDuration: ->\n duration = 0\n \n if @lines?\n for line in @lines\n for token in line.content\n if token?\n duration += @calculateDurationForToken(token)\n return duration\n \n ###*\n * Calculates the duration(in frames) the message-renderer needs to display\n * the specified line.\n *\n * @method calculateDurationForLine\n * @param {gs.RendererTextLine} line The line to calculate the duration for.\n * @return {number} The duration in frames.\n ### \n calculateDurationForLine: (line) ->\n duration = 0\n \n if line\n for token in line.content\n if token?\n duration += @calculateDurationForToken(token)\n \n return duration\n \n ###*\n * Calculates the duration(in frames) the message-renderer needs to process\n * the specified token.\n *\n * @method calculateDurationForToken\n * @param {string|Object} token - The token.\n * @return {number} The duration in frames.\n ### \n calculateDurationForToken: (token) ->\n duration = 0\n \n if token.code?\n switch token.code\n when \"W\"\n if token.value != \"A\"\n duration = token.value / 1000 * Graphics.frameRate\n else\n duration = token.value.length * @speed\n \n return duration\n \n ###*\n * Calculates the maximum of lines which can be displayed in one message.\n *\n * @method calculateMaxLines\n * @param {Array} lines - An array of line-objects.\n * @return {number} The number of displayable lines.\n ###\n calculateMaxLines: (lines) ->\n height = 0\n result = 0\n \n for line in lines\n height += line.height + @lineSpacing\n if @currentY+height > (@object.dstRect.height)\n break\n result++\n \n return Math.min(lines.length, result || 1)\n \n ###*\n * Displays the character or processes the next control-token.\n *\n * @method drawNext\n ###\n drawNext: ->\n token = @processToken()\n \n if token?.value.length > 0\n @char = @token.value.charAt(@charIndex)\n \n size = @font.measureTextPlain(@char) \n lineSpacing = @lineSpacing\n \n if @currentLine != @line\n @currentLine = @line\n # @currentY += @currentLineHeight + lineSpacing * Graphics.scale\n @currentLineHeight = 0\n\n @currentSprite.y = @object.origin.y + @object.dstRect.y + @currentY\n @currentSprite.visible = yes\n @drawLineContent(@lines[@line], @currentSprite.bitmap, @charIndex+1)\n @currentSprite.srcRect.width = @currentSprite.bitmap.width #Math.min(@currentSprite.srcRect.width + size.width, @currentSprite.bitmap.width)\n \n @currentLineHeight = @lines[@line].height\n @currentX = Math.min(@lines[@line].width, @currentX + size.width)\n \n ###*\n * Processes the next character/token of the message.\n * @method nextChar\n * @private\n ###\n nextChar: ->\n loop\n @charIndex++\n @lineAnimationCount = @speed\n \n if @token.code? or @charIndex >= @token.value.length\n @token.onEnd?()\n @tokenIndex++\n if @tokenIndex >= @lines[@line].content.length\n @tokenIndex = 0\n @line++\n @currentSprite.srcRect.width = @currentSprite.bitmap.width\n @currentSprite = @sprites[@line]\n if @currentSprite?\n @currentSprite.x = @object.origin.x + @object.dstRect.x\n if @line < @maxLines\n @currentY += (@currentLineHeight || @font.lineHeight) + @lineSpacing * Graphics.scale\n @charIndex = 0\n @currentX = 0\n @token = @lines[@line].content[@tokenIndex] || new gs.RendererToken(null, \"\")\n else\n @charIndex = 0\n @token = @lines[@line].content[@tokenIndex] || new gs.RendererToken(null, \"\")\n @token.onStart?()\n\n \n if !@token or @token.value != \"\\n\" or !@lines[@line]\n break\n ###*\n * Finishes the message. Depending on the message configuration, the\n * message text-renderer will now wait for a user-action or a certain amount\n * of time.\n *\n * @method finish\n ###\n finish: ->\n if @waitAtEnd\n @isWaiting = yes\n @object.events?.emit(\"messageWaiting\", this)\n else if @waitAtEndTime > 0\n @waitCounter = @waitAtEndTime\n @isWaiting = no\n \n @object.events?.emit(\"messageWaiting\", this)\n else\n @object.events?.emit(\"messageWaiting\", this)\n @continue()\n \n ###*\n * Returns the position of the caret in pixels. The caret is like an invisible\n * cursor pointing to the x/y coordinates of the last rendered character of\n * the message. That position can be used to display a waiting- or processing-animation for example.\n *\n * @method updateCaretPosition\n ###\n updateCaretPosition: -> \n @caretPosition.x = @currentX + @padding \n @caretPosition.y = @currentY + @currentLineHeight/2\n \n ###*\n * Updates the line writing.\n *\n * @method updateLineWriting\n * @private\n ###\n updateLineWriting: ->\n if @isRunning and !@isWaiting and !@waitForKey and @waitCounter <= 0\n if @lineAnimationCount <= 0\n loop\n if @line < @maxLines\n @nextChar()\n \n if @line >= @maxLines\n @finish()\n else\n @drawNext()\n \n break unless (@token.code or @lineAnimationCount <= 0 or @drawImmediately) and !@waitForKey and @waitCounter <= 0 and @isRunning and @line < @maxLines\n \n if GameManager.tempSettings.skip\n @lineAnimationCount = 0\n else\n @lineAnimationCount--\n \n ###*\n * Updates wait-for-key state. If skipping is enabled, the text renderer will\n * not wait for key press.\n *\n * @method updateWaitForKey\n * @private\n ###\n updateWaitForKey: ->\n if @waitForKey\n @isWaiting = !GameManager.tempSettings.skip\n @waitForKey = @isWaiting\n \n ###*\n * Updates wait counter if the text renderer is waiting for a certain amount of time to pass. If skipping is enabled, the text renderer will\n * not wait for the actual amount of time and sets the wait-counter to 1 frame instead.\n *\n * @method updateWaitForKey\n * @private\n ### \n updateWaitCounter: ->\n if @waitCounter > 0\n if GameManager.tempSettings.skip\n @waitCounter = 1\n @isWaiting = yes\n @waitCounter--\n if @waitCounter <= 0\n @isWaiting = no\n @continue() if @line >= @maxLines\n \n ###*\n * Creates a token-object for a specified text-code.\n * \n * @method createToken\n * @param {string} code - The code/type of the text-code.\n * @param {string} value - The value of the text-code.\n * @return {Object} The token-object.\n ###\n createToken: (code, value) ->\n tokenObject = null\n \n switch code\n when \"CE\"\n data = value.split(\"/\")\n value = data.shift()\n value = if isNaN(value) then value else parseInt(value)\n for i in [0...data]\n if data[i].startsWith('\"') and data[i].endsWith('\"')\n data[i] = data[i].substring(1, data[i].length-1)\n else\n data[i] = if isNaN(data[i]) then data[i] else parseFloat(data[i])\n tokenObject = { code: code, value: value, values: data }\n else\n tokenObject = super(code, value)\n \n \n return tokenObject \n ###*\n * <p>Measures a control-token. If a token produces a visual result like displaying an icon then it must return the size taken by\n * the visual result. If the token has no visual result, <b>null</b> must be returned. This method is called for every token when the message is initialized.</p> \n *\n * <p>This method is not called while the message is running. For that case, see <i>processControlToken</i> method which is called\n * for every token while the message is running.</p>\n *\n * @param {Object} token - A control-token.\n * @return {gs.Size} The size of the area taken by the visual result of the token or <b>null</b> if the token has no visual result.\n * @method analyzeControlToken\n * @protected\n ###\n measureControlToken: (token) -> return super(token)\n \n ###*\n * <p>Draws the visual result of a token, like an icon for example, to the specified bitmap. This method is called for every token when the message is initialized and the sprites for each\n * text-line are created.</p> \n *\n * <p>This method is not called while the message is running. For that case, see <i>processControlToken</i> method which is called\n * for every token while the message is running.</p>\n *\n * @param {Object} token - A control-token.\n * @param {gs.Bitmap} bitmap - The bitmap used for the current text-line. Can be used to draw something on it like an icon, etc.\n * @param {number} offset - An x-offset for the draw-routine.\n * @param {number} length - Determines how many characters of the token should be drawn. Can be ignored for tokens\n * not drawing any characters.\n * @method drawControlToken\n * @protected\n ###\n drawControlToken: (token, bitmap, offset, length) ->\n switch token.code\n when \"RT\" # Ruby Text\n super(token, bitmap, offset, length)\n when \"SLK\" # Stylable Link\n if !token.customData.offsetX?\n token.customData.offsetX = offset\n if @customData.linkData\n linkData = @customData.linkData[@line]\n if linkData then for data in linkData\n @sprites[@line].bitmap.clearRect(data.cx,\n 0,\n data.width,\n data.height)\n \n \n ###*\n * Processes a control-token. A control-token is a token which influences\n * the text-rendering like changing the fonts color, size or style. Changes \n * will be automatically applied to the game object's font.\n *\n * For message text-renderer, a few additional control-tokens like\n * speed-change, waiting, etc. needs to be processed here.\n *\n * This method is called for each token while the message is initialized and\n * also while the message is running. See <i>formattingOnly</i> parameter.\n *\n * @param {Object} token - A control-token.\n * @param {boolean} formattingOnly - If <b>true</b> the message is initializing right now and only \n * format-tokens should be processed which is necessary for the message to calculated sizes correctly.\n * @return {Object} A new token which is processed next or <b>null</b>.\n * @method processControlToken\n * @protected\n ###\n processControlToken: (token, formattingOnly) ->\n return super(token) if formattingOnly\n result = null\n \n switch token.code\n when \"CR\" # Change Current Character\n character = RecordManager.charactersArray.first (c) -> (c.name.defaultText ? c.name) == token.value\n if character\n SceneManager.scene.currentCharacter = character\n when \"CE\" # Call Common Event\n params = { \"values\": token.values }\n @object.events?.emit(\"callCommonEvent\", @object, { commonEventId: token.value, params: params, finish: no, waiting: yes })\n when \"X\" # Script\n token.value?(@object)\n when \"A\" # Play Animation\n animation = RecordManager.animationsArray.first (a) -> a.name == token.value\n if !animation\n animation = RecordManager.animations[token.value]\n if animation?.graphic.name?\n bitmap = ResourceManager.getBitmap(\"Graphics/Pictures/#{animation.graphic.name}\")\n object = new gs.Object_Animation(animation)\n \n @addCustomObject(object)\n @currentX += Math.round(bitmap.width / animation.framesX)\n @currentSprite.srcRect.width += Math.round(bitmap.width / animation.framesX)\n \n when \"RT\" # Ruby Text\n if token.rtSize.width > token.rbSize.width\n @currentX += token.rtSize.width\n @font.set(@getRubyTextFont(token))\n else\n @currentX += token.rbSize.width\n \n when \"LK\" # Link \n if token.value == 'E' # End Link\n object = new ui.Object_Hotspot()\n object.enabled = yes\n object.setup()\n \n @addCustomObject(object)\n \n object.dstRect.x = @object.dstRect.x + @object.origin.x + @customData.linkData.cx\n object.dstRect.y = @object.dstRect.y + @object.origin.y + @customData.linkData.cy\n object.dstRect.width = @currentX - @customData.linkData.cx\n object.dstRect.height = @currentLineHeight\n\n object.events.on(\"click\", gs.CallBack(\"onLinkClick\", this), linkData: @customData.linkData, this)\n else # Begin Link\n @customData.linkData = { cx: @currentX, cy: @currentY, commonEventId: token.value, tokenIndex: @tokenIndex }\n when \"SLK\" # Styleable Link\n if token.value == 'E' # End Link\n linkData = @customData.linkData[@line].last()\n line = @lines[@line].content\n linkStart = @findToken(@tokenIndex-1, \"SLK\", -1, line)\n textTokens = @findTokensBetween(linkData.tokenIndex, @tokenIndex, null, line)\n \n linkData.cx = linkStart.customData.offsetX\n linkData.width = @currentX - linkData.cx + @padding\n linkData.height = @currentSprite.bitmap.height\n \n object = new ui.Object_Text()\n object.text = textTokens.select((x) => x.value).join(\"\")\n #object.sizeToFit = yes\n object.formatting = no\n object.wordWrap = no\n object.ui = new ui.Component_UIBehavior()\n object.enabled = yes\n object.addComponent(object.ui)\n object.addComponent(new gs.Component_HotspotBehavior())\n object.behavior.padding.left = 0\n object.behavior.padding.right = 0\n object.dstRect.width = linkData.width\n object.dstRect.height = linkData.height\n \n if linkData.styleIndex == -1\n ui.UIManager.addControlStyles(object, [\"hyperlink\"])\n else \n ui.UIManager.addControlStyles(object, [\"hyperlink-\"+linkData.styleIndex])\n \n object.setup()\n \n @addCustomObject(object)\n \n object.dstRect.x = @currentSprite.x + linkData.cx\n object.dstRect.y = @object.dstRect.y + @object.origin.y + linkData.cy\n\n object.events.on(\"click\", gs.CallBack(\"onLinkClick\", this), linkData: linkData, this)\n else # Begin Link\n if !@customData.linkData\n @customData.linkData = []\n if !@customData.linkData[@line]\n @customData.linkData[@line] = []\n if token.value?.contains(\",\")\n values = token.value.split(\",\")\n @customData.linkData[@line].push({ cx: @currentX, cy: @currentY, commonEventId: values[0], styleIndex: parseInt(values[1]), tokenIndex: @tokenIndex })\n else\n @customData.linkData[@line].push({ cx: @currentY, cy: @currentY, commonEventId: token.value, tokenIndex: @tokenIndex, styleIndex: -1 })\n \n when \"E\" # Change Expression\n expression = RecordManager.characterExpressionsArray.first (c) -> (c.name.defaultText ? c.name) == token.value\n if !expression\n expression = RecordManager.characterExpressions[token.value]\n \n character = SceneManager.scene.currentCharacter\n if expression? and character?.index?\n duration = GameManager.defaults.character.expressionDuration\n easing = gs.Easings.fromObject(GameManager.defaults.character.changeEasing)\n animation = GameManager.defaults.character.changeAnimation\n object = SceneManager.scene.characters.first (c) -> c.rid == character.index\n object?.behavior.changeExpression(expression, animation, easing, duration)\n \n when \"SP\" # Play Sound\n sound = RecordManager.system.sounds[token.value-1]\n AudioManager.playSound(sound)\n when \"S\" # Change Speed\n GameManager.settings.messageSpeed = token.value\n when \"W\" # Wait\n @drawImmediately = no\n if !GameManager.tempSettings.skip\n if token.value == \"A\"\n @waitForKey = yes\n else\n @waitCounter = Math.round(token.value / 1000 * Graphics.frameRate)\n when \"WE\" # Wait at End\n @waitAtEnd = token.value == \"Y\"\n when \"DI\" # Draw Immedialty\n @drawImmediately = token.value == 1 or token.value == \"Y\" # Draw immediately\n else\n result = super(token)\n \n return result \n ###*\n * Clears/Resets the text-renderer.\n *\n * @method clear\n ###\n clear: ->\n @charIndex = 0\n @currentX = 0\n @currentY = 0\n @line = 0\n @lines = []\n @clearCustomObjects()\n @object.bitmap?.clear()\n \n for sprite in @allSprites\n sprite.dispose()\n sprite.bitmap?.dispose()\n @allSprites = []\n return null\n \n ###*\n * Clears/Disposes all sprites used to display the text-lines/parts.\n *\n * @method clearAllSprites\n ###\n clearAllSprites: ->\n for sprite in @allSprites\n sprite.dispose()\n sprite.bitmap?.dispose()\n \n return null\n \n ###*\n * Clears/Disposes the sprites used to display the text-lines/parts of the current/last message.\n *\n * @method clearSprites\n ### \n clearSprites: ->\n for sprite in @sprites\n sprite.dispose()\n sprite.bitmap?.dispose()\n \n return null\n \n \n ###*\n * Removes a game object from the message.\n *\n * @method removeCustomObject\n * @param object {gs.Object_Base} The game object to remove.\n ###\n removeCustomObject: (object) ->\n SceneManager.scene.removeObject(object)\n object.dispose()\n @customObjects.remove(object)\n \n ###*\n * Adds a game object to the message which is alive until the message is\n * erased. Can be used to display animationed-icons, etc. in a message.\n *\n * @method addCustomObject\n * @param object {gs.Object_Base} The game object to add.\n ###\n addCustomObject: (object) ->\n object.dstRect.x = @object.dstRect.x + @object.origin.x + @currentX\n object.dstRect.y = @object.dstRect.y + @object.origin.y + @currentY\n object.zIndex = @object.zIndex + 1\n object.update()\n \n SceneManager.scene.addObject(object)\n @customObjects.push(object)\n \n ###*\n * Clears the list of custom game objects. All game objects are disposed and removed\n * from the scene.\n *\n * @method clearCustomObjects\n * @param object {Object} The game object to add.\n ### \n clearCustomObjects: ->\n for object in @customObjects\n object.dispose()\n SceneManager.scene.removeObject(object)\n \n @customObjects = []\n \n ###*\n * Creates the bitmap for a specified line-object.\n *\n * @method createBitmap\n * @private\n * @param {Object} line - A line-object.\n * @return {Bitmap} A newly created bitmap containing the line-text.\n ###\n createBitmap: (line) ->\n @font = @object.font\n bitmap = new Bitmap(@object.dstRect.width, Math.max(@minLineHeight, line.height))\n bitmap.font = @font\n \n return bitmap\n \n ###*\n * Draws the line's content on the specified bitmap.\n *\n * @method drawLineContent\n * @protected\n * @param {Object} line - A line-object which should be drawn on the bitmap.\n * @param {gs.Bitmap} bitmap - The bitmap to draw the line's content on.\n * @param {number} length - Determines how many characters of the specified line should be drawn. You can \n * specify -1 to draw all characters.\n ###\n drawLineContent: (line, bitmap, length) ->\n bitmap.clear()\n currentX = @padding\n drawAll = length == -1\n \n for token, i in line.content\n break if i > @tokenIndex and !drawAll\n if token.code?\n size = @measureControlToken(token, bitmap)\n @drawControlToken(token, bitmap, currentX)\n if size then currentX += size.width\n @processControlToken(token, yes, line)\n else if token.value.length > 0\n token.applyFormat(@font)\n value = token.value\n if !drawAll and @tokenIndex == i and value.length > length\n value = value.substring(0, length)\n if value != \"\\n\"\n size = @font.measureTextPlain(value) \n bitmap.drawText(currentX, line.height - (size.height - @font.descent) - line.descent, size.width, bitmap.height, value, 0, 0)\n currentX += size.width\n \n line.contentWidth = currentX + @font.measureTextPlain(\" \").width \n \n ###*\n * Creates the sprite for a specified line-object.\n *\n * @method createSprite\n * @private\n * @param {Object} line - A line-object.\n * @return {Sprite} A newly created sprite object containing the line-text as bitmap.\n ###\n createSprite: (line) ->\n bitmap = @createBitmap(line)\n \n @currentX = 0\n @waitCounter = 0\n @waitForKey = no\n \n sprite = new Sprite(Graphics.viewport)\n sprite.bitmap = bitmap\n sprite.visible = yes\n sprite.z = @object.zIndex + 1\n \n sprite.srcRect = new Rect(0, 0, 0, bitmap.height)\n \n return sprite\n \n ###*\n * Creates the sprites for a specified array of line-objects.\n *\n * @method createSprites\n * @private\n * @see gs.Component_MessageTextRenderer.createSprite.\n * @param {Array} lines - An array of line-objects.\n * @return {Array} An array of sprites.\n ###\n createSprites: (lines) ->\n @fontSize = @object.font.size\n result = []\n for line, i in lines\n sprite = @createSprite(line)\n result.push(sprite)\n return result\n \n ###*\n * Starts a new line.\n *\n * @method newLine\n ###\n newLine: ->\n @currentX = 0\n @currentY += @currentLineHeight + @lineSpacing\n \n ###*\n * Displays a formatted text immediately without any delays or animations. The\n * Component_TextRenderer.drawFormattedText method from the base-class cannot\n * be used here because it would render to the game object's bitmap object while\n * this method is rendering to the sprites.\n *\n * @method drawFormattedTextImmediately\n * @param {number} x - The x-coordinate of the text's position.\n * @param {number} y - The y-coordinate of the text's position.\n * @param {number} width - Deprecated. Can be null.\n * @param {number} height - Deprecated. Can be null.\n * @param {string} text - The text to draw.\n * @param {boolean} wordWrap - If wordWrap is set to true, line-breaks are automatically created.\n ###\n drawFormattedTextImmediately: (x, y, width, height, text, wordWrap) ->\n @drawFormattedText(x, y, width, height, text, wordWrap)\n \n loop\n @nextChar()\n \n if @line >= @maxLines\n @isRunning = no\n else\n @drawNext()\n \n break unless @isRunning\n \n @currentY += @currentLineHeight + @lineSpacing\n \n return null\n \n \n ###*\n * Starts the rendering-process for the message.\n *\n * @method drawFormattedText\n * @param {number} x - The x-coordinate of the text's position.\n * @param {number} y - The y-coordinate of the text's position.\n * @param {number} width - Deprecated. Can be null.\n * @param {number} height - Deprecated. Can be null.\n * @param {string} text - The text to draw.\n * @param {boolean} wordWrap - If wordWrap is set to true, line-breaks are automatically created.\n ###\n drawFormattedText: (x, y, width, height, text, wordWrap) ->\n text = text || \" \" # Use a space character if no text is specified.\n @font.set(@object.font)\n @speed = 11 - Math.round(GameManager.settings.messageSpeed * 2.5)\n @isRunning = yes\n @drawImmediately = no\n @lineAnimationCount = @speed\n @currentLineHeight = 0\n @isWaiting = no\n @waitForKey = no\n @charIndex = 0\n @token = null\n @tokenIndex = 0\n @message = text\n @line = 0\n @currentLine = @line\n currentX = @currentX #Math.max(@currentX, @padding)\n @lines = @calculateLines(lcsm(@message), wordWrap, @currentX)\n @sprites = @createSprites(@lines)\n @allSprites = @allSprites.concat(@sprites)\n @currentX = currentX\n @currentSprite = @sprites[@line]\n @currentSprite.x = @currentX + @object.origin.x + @object.dstRect.x\n @maxLines = @calculateMaxLines(@lines)\n @token = @lines[@line]?.content[@tokenIndex] || new gs.RendererToken(null, \"\")\n \n \n @start()\n \n ###*\n * Starts the message-rendering process.\n *\n * @method start\n * @protected\n ### \n start: ->\n if GameManager.tempSettings.skip and GameManager.tempSettings.skipTime == 0\n @instantSkip()\n else if @maxLines == 0\n # If first line is empty then it doesn't fit into current line, so finish.\n if @lines[0]?.content == \"\"\n @finish()\n else\n @maxLines = 1\n @drawNext()\n else\n @drawNext()\n \n ###*\n * Skips the current message and finishes the message-processing immediately. The message\n * tokens are processed but not rendered.\n *\n * @method instantSkip\n ### \n instantSkip: ->\n loop\n if @line < @maxLines\n @nextChar()\n \n if @line >= @maxLines\n break\n else\n @processToken()\n \n break unless @isRunning and @line < @maxLines\n \n @object.events?.emit(\"messageWaiting\", this)\n @continue()\n \n ###*\n * Processes the current token.\n *\n * @method processToken\n ### \n processToken: ->\n token = null\n \n if @token.code?\n token = @processControlToken(@token, no)\n if token?\n @token = token\n @token.onStart?()\n else\n token = @token\n \n return token\n \n \n \ngs.Component_MessageTextRenderer = Component_MessageTextRenderer",
10 10 "parentId": "D3325122KACDEA4515SB731E37A42B9D779F",
11 11 "folder": false,
12 - "compiledContent": "var Component_MessageTextRenderer,\n extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n hasProp = {}.hasOwnProperty;\n\nComponent_MessageTextRenderer = (function(superClass) {\n extend(Component_MessageTextRenderer, superClass);\n\n Component_MessageTextRenderer.objectCodecBlackList = [\"onLinkClick\", \"onBatchDisappear\"];\n\n\n /**\n * Called if this object instance is restored from a data-bundle. It can be used\n * re-assign event-handler, anonymous functions, etc.\n * \n * @method onDataBundleRestore.\n * @param Object data - The data-bundle\n * @param gs.ObjectCodecContext context - The codec-context.\n */\n\n Component_MessageTextRenderer.prototype.onDataBundleRestore = function(data, context) {\n var bitmap, customObject, j, l, len, len1, len2, line, m, message, n, ref, ref1, ref2;\n this.setupEventHandlers();\n l = 0;\n ref = this.object.messages;\n for (j = 0, len = ref.length; j < len; j++) {\n message = ref[j];\n if (this.object.settings.useCharacterColor) {\n this.object.font.color = new gs.Color(message.character.textColor);\n }\n this.lines = this.calculateLines(lcsm(message.text), true, 0);\n ref1 = this.lines;\n for (m = 0, len1 = ref1.length; m < len1; m++) {\n line = ref1[m];\n bitmap = this.createBitmap(line);\n if (line === this.line) {\n this.drawLineContent(line, bitmap, this.charIndex + 1);\n } else {\n this.drawLineContent(line, bitmap, -1);\n }\n this.allSprites[l].bitmap = bitmap;\n l++;\n }\n }\n ref2 = this.customObjects;\n for (n = 0, len2 = ref2.length; n < len2; n++) {\n customObject = ref2[n];\n SceneManager.scene.addObject(customObject);\n }\n return null;\n };\n\n\n /**\n * A text-renderer component to render an animated and interactive message text using\n * dimensions of the game object's destination-rectangle. The message is displayed\n * using a sprite for each line instead of drawing to the game object's bitmap object.\n *\n * @module gs\n * @class Component_MessageTextRenderer\n * @extends gs.Component_TextRenderer\n * @memberof gs\n * @constructor\n */\n\n function Component_MessageTextRenderer() {\n Component_MessageTextRenderer.__super__.constructor.apply(this, arguments);\n\n /**\n * An array containing all sprites of the current message.\n * @property sprites\n * @type gs.Sprite[]\n * @protected\n */\n this.sprites = [];\n\n /**\n * An array containing all sprites of all messages. In NVL mode\n * a page can contain multiple messages.\n * @property allSprites\n * @type gs.Sprite[]\n * @protected\n */\n this.allSprites = [];\n\n /**\n * An array containing all line-objects of the current message.\n * @property lines\n * @type gs.TextRendererLine[]\n * @readOnly\n */\n this.lines = null;\n\n /**\n * The line currently rendered.\n * @property line\n * @type number\n * @readOnly\n */\n this.line = 0;\n\n /**\n * The left and right padding per line.\n * @property padding\n * @type number\n */\n this.padding = 6;\n\n /**\n * The minimum height of the line currently rendered. If 0, the measured\n * height of the line will be used.\n * @property minLineHeight\n * @type number\n */\n this.minLineHeight = 0;\n\n /**\n * The spacing between text lines in pixels.\n * @property lineSpacing\n * @type number\n */\n this.lineSpacing = 2;\n\n /**\n * The line currently rendered.\n * @property currentLine\n * @type number\n * @protected\n */\n this.currentLine = 0;\n\n /**\n * The height of the line currently rendered.\n * @property currentLineHeight\n * @type number\n * @protected\n */\n this.currentLineHeight = 0;\n\n /**\n * Index of the current character to draw.\n * @property charIndex\n * @type number\n * @readOnly\n */\n this.charIndex = 0;\n\n /**\n * Position of the message caret. The caret is like an invisible\n * cursor pointing to the x/y coordinates of the last rendered character of\n * the message. That position can be used to display a waiting- or processing-animation for example.\n * @property caretPosition\n * @type gs.Point\n * @readOnly\n */\n this.caretPosition = new gs.Point();\n\n /**\n * Indicates that the a message is currently in progress.\n * @property isRunning\n * @type boolean\n * @readOnly\n */\n this.isRunning = false;\n\n /**\n * The current x-coordinate of the caret/cursor.\n * @property currentX\n * @type number\n * @readOnly\n */\n this.currentX = 0;\n\n /**\n * The current y-coordinate of the caret/cursor.\n * @property currentY\n * @type number\n * @readOnly\n */\n this.currentY = 0;\n\n /**\n * The current sprites used to display the current text-line/part.\n * @property currentSprite\n * @type gs.Sprite\n * @readOnly\n */\n this.currentSprite = null;\n\n /**\n * Indicates if the message-renderer is currently waiting like for a user-action.\n * @property isWaiting\n * @type boolean\n * @readOnly\n */\n this.isWaiting = false;\n\n /**\n * Indicates if the message-renderer is currently waiting for a key-press or mouse/touch action.\n * @property waitForKey\n * @type boolean\n * @readOnly\n */\n this.waitForKey = false;\n\n /**\n * Number of frames the message-renderer should wait before continue.\n * @property waitCounter\n * @type number\n */\n this.waitCounter = 0;\n\n /**\n * Speed of the message-drawing. The smaller the value, the faster the message is displayed.\n * @property speed\n * @type number\n */\n this.speed = 1;\n\n /**\n * Indicates if the message should be rendered immedialtely without any animation or delay.\n * @property drawImmediately\n * @type boolean\n */\n this.drawImmediately = false;\n\n /**\n * Indicates if the message should wait for a user-action or a certain amount of time\n * before finishing.\n * @property waitAtEnd\n * @type boolean\n */\n this.waitAtEnd = true;\n\n /**\n * The number of frames to wait before finishing a message.\n * before finishing.\n * @property waitAtEndTime\n * @type number\n */\n this.waitAtEndTime = 0;\n\n /**\n * Indicates if auto word-wrap should be used. Default is <b>true</b>\n * @property wordWrap\n * @type boolean\n */\n this.wordWrap = true;\n\n /**\n * Custom game objects which are alive until the current message is erased. Can be used to display\n * animated icons, etc.\n * @property customObjects\n * @type gs.Object_Base[]\n */\n this.customObjects = [];\n\n /**\n * A hashtable/dictionary object to store custom-data useful like for token-processing. The data must be\n * serializable.\n * @property customObjects\n * @type Object\n */\n this.customData = {};\n\n /**\n * A callback function called if the player clicks on a non-stylable link (LK text-code) to trigger\n * the specified common event.\n * @property onLinkClick\n * @type Function\n */\n this.onLinkClick = function(e) {\n var event, eventId;\n eventId = e.data.linkData.commonEventId;\n event = RecordManager.commonEvents[eventId];\n if (!event) {\n event = RecordManager.commonEvents.first((function(_this) {\n return function(x) {\n return x.name === eventId;\n };\n })(this));\n if (event) {\n eventId = event.index;\n }\n }\n return SceneManager.scene.interpreter.callCommonEvent(eventId, null, true);\n };\n\n /**\n * A callback function called if a batched messsage has been faded out. It triggers the execution of\n * the next message.\n * @property onBatchDisappear\n * @type Function\n */\n this.onBatchDisappear = (function(_this) {\n return function(e) {\n _this.drawImmediately = false;\n _this.isWaiting = false;\n _this.object.opacity = 255;\n return _this.executeBatch();\n };\n })(this);\n }\n\n\n /**\n * Serializes the message text-renderer into a data-bundle.\n * @method toDataBundle\n * @return {Object} A data-bundle.\n */\n\n Component_MessageTextRenderer.prototype.toDataBundle = function() {\n var bundle, ignore, k;\n ignore = [\"object\", \"font\", \"sprites\", \"allSprites\", \"currentSprite\", \"currentX\"];\n bundle = {\n currentSpriteIndex: this.sprites.indexOf(this.currentSprite)\n };\n for (k in this) {\n if (ignore.indexOf(k) === -1) {\n bundle[k] = this[k];\n }\n }\n return bundle;\n };\n\n\n /**\n * Disposes the message text-renderer and all sprites used to display\n * the message.\n * @method dispose\n */\n\n Component_MessageTextRenderer.prototype.dispose = function() {\n var j, len, ref, ref1, results, sprite;\n Component_MessageTextRenderer.__super__.dispose.apply(this, arguments);\n gs.GlobalEventManager.offByOwner(\"mouseUp\", this.object);\n gs.GlobalEventManager.offByOwner(\"keyUp\", this.object);\n ref = this.allSprites;\n results = [];\n for (j = 0, len = ref.length; j < len; j++) {\n sprite = ref[j];\n if ((ref1 = sprite.bitmap) != null) {\n ref1.dispose();\n }\n results.push(sprite.dispose());\n }\n return results;\n };\n\n\n /**\n * Adds event-handlers for mouse/touch events\n *\n * @method setupEventHandlers\n */\n\n Component_MessageTextRenderer.prototype.setupEventHandlers = function() {\n gs.GlobalEventManager.offByOwner(\"mouseUp\", this.object);\n gs.GlobalEventManager.offByOwner(\"keyUp\", this.object);\n gs.GlobalEventManager.on(\"mouseUp\", ((function(_this) {\n return function(e) {\n if (GameManager.settings.autoMessage.enabled && !GameManager.settings.autoMessage.stopOnAction) {\n return;\n }\n if (_this.isWaiting && !(_this.waitCounter > 0 || _this.waitForKey)) {\n e.breakChain = true;\n _this[\"continue\"]();\n } else {\n e.breakChain = _this.isRunning;\n _this.drawImmediately = !_this.waitForKey;\n _this.waitCounter = 0;\n _this.waitForKey = false;\n _this.isWaiting = false;\n }\n if (_this.waitForKey) {\n if (Input.Mouse.buttons[Input.Mouse.LEFT] === 2) {\n e.breakChain = true;\n Input.clear();\n _this.waitForKey = false;\n return _this.isWaiting = false;\n }\n }\n };\n })(this)), null, this.object);\n return gs.GlobalEventManager.on(\"keyUp\", ((function(_this) {\n return function(e) {\n if (Input.keys[Input.C] && (!_this.isWaiting || (_this.waitCounter > 0 || _this.waitForKey))) {\n _this.drawImmediately = !_this.waitForKey;\n _this.waitCounter = 0;\n _this.waitForKey = false;\n _this.isWaiting = false;\n }\n if (_this.isWaiting && !_this.waitForKey && !_this.waitCounter && Input.keys[Input.C]) {\n _this[\"continue\"]();\n }\n if (_this.waitForKey) {\n if (Input.keys[Input.C]) {\n Input.clear();\n _this.waitForKey = false;\n return _this.isWaiting = false;\n }\n }\n };\n })(this)), null, this.object);\n };\n\n\n /**\n * Sets up the renderer. Registers necessary event handlers.\n * @method setup\n */\n\n Component_MessageTextRenderer.prototype.setup = function() {\n return this.setupEventHandlers();\n };\n\n\n /**\n * Restores the message text-renderer's state from a data-bundle.\n * @method restore\n * @param {Object} bundle - A data-bundle containing message text-renderer state.\n */\n\n Component_MessageTextRenderer.prototype.restore = function(bundle) {\n var k;\n for (k in bundle) {\n if (k === \"currentSpriteIndex\") {\n this.currentSprite = this.sprites[bundle.currentSpriteIndex];\n } else {\n this[k] = bundle[k];\n }\n }\n if (this.sprites.length > 0) {\n this.currentY = this.sprites.last().y - this.object.origin.y - this.object.dstRect.y;\n this.line = this.maxLines;\n this.isWaiting = this.isWaiting || this.isRunning;\n }\n return null;\n };\n\n\n /**\n * Continues message-processing if currently waiting.\n * @method continue\n */\n\n Component_MessageTextRenderer.prototype[\"continue\"] = function() {\n var duration, fading, ref, ref1;\n this.isWaiting = false;\n if (this.line >= this.lines.length) {\n this.isRunning = false;\n return (ref = this.object.events) != null ? ref.emit(\"messageFinish\", this) : void 0;\n } else {\n if ((ref1 = this.object.events) != null) {\n ref1.emit(\"messageBatch\", this);\n }\n fading = GameManager.tempSettings.messageFading;\n duration = GameManager.tempSettings.skip ? 0 : fading.duration;\n return this.object.animator.disappear(fading.animation, fading.easing, duration, gs.CallBack(\"onBatchDisappear\", this));\n }\n };\n\n\n /**\n * Updates the text-renderer.\n * @method update\n */\n\n Component_MessageTextRenderer.prototype.update = function() {\n var j, len, len1, m, object, ref, ref1, ref2, sprite;\n ref = this.allSprites;\n for (j = 0, len = ref.length; j < len; j++) {\n sprite = ref[j];\n sprite.opacity = this.object.opacity;\n sprite.visible = this.object.visible;\n sprite.ox = -this.object.offset.x;\n sprite.oy = -this.object.offset.y;\n sprite.mask.value = this.object.mask.value;\n sprite.mask.vague = this.object.mask.vague;\n sprite.mask.source = this.object.mask.source;\n sprite.mask.type = this.object.mask.type;\n }\n ref1 = this.customObjects;\n for (m = 0, len1 = ref1.length; m < len1; m++) {\n object = ref1[m];\n object.opacity = this.object.opacity;\n object.visible = this.object.visible;\n }\n if (!this.isRunning && this.waitCounter > 0) {\n this.waitCounter--;\n if (this.waitCounter === 0) {\n this[\"continue\"]();\n }\n return;\n }\n if (this.object.visible && ((ref2 = this.lines) != null ? ref2.length : void 0) > 0) {\n this.updateLineWriting();\n this.updateWaitForKey();\n this.updateWaitCounter();\n return this.updateCaretPosition();\n }\n };\n\n\n /**\n * Indicates if its a batched messages.\n *\n * @method isBatched\n * @return If <b>true</b> it is a batched message. Otherwise <b>false</b>.\n */\n\n Component_MessageTextRenderer.prototype.isBatched = function() {\n return this.lines.length > this.maxLines;\n };\n\n\n /**\n * Indicates if the batch is still in progress and not done.\n *\n * @method isBatchInProgress\n * @return If <b>true</b> the batched message is still not done. Otherwise <b>false</b>\n */\n\n Component_MessageTextRenderer.prototype.isBatchInProgress = function() {\n return this.lines.length - this.line > this.maxLines;\n };\n\n\n /**\n * Starts displaying the next page of text if a message is too long to fit\n * into one message box.\n *\n * @method executeBatch\n */\n\n Component_MessageTextRenderer.prototype.executeBatch = function() {\n this.clearAllSprites();\n this.lines = this.lines.slice(this.line);\n this.line = 0;\n this.currentX = 0;\n this.currentY = 0;\n this.currentLineHeight = 0;\n this.tokenIndex = 0;\n this.charIndex = 0;\n this.token = this.lines[this.line].content[this.tokenIndex] || new gs.RendererToken(null, \"\");\n this.maxLines = this.calculateMaxLines(this.lines);\n this.lineAnimationCount = this.speed;\n this.sprites = this.createSprites(this.lines);\n this.allSprites = this.allSprites.concat(this.sprites);\n this.currentSprite = this.sprites[this.line];\n this.currentSprite.x = this.currentX + this.object.origin.x + this.object.dstRect.x;\n return this.drawNext();\n };\n\n\n /**\n * Calculates the duration(in frames) the message-renderer needs to display\n * the message.\n *\n * @method calculateDuration\n * @return {number} The duration in frames.\n */\n\n Component_MessageTextRenderer.prototype.calculateDuration = function() {\n var duration, j, len, len1, line, m, ref, ref1, token;\n duration = 0;\n if (this.lines != null) {\n ref = this.lines;\n for (j = 0, len = ref.length; j < len; j++) {\n line = ref[j];\n ref1 = line.content;\n for (m = 0, len1 = ref1.length; m < len1; m++) {\n token = ref1[m];\n if (token != null) {\n duration += this.calculateDurationForToken(token);\n }\n }\n }\n }\n return duration;\n };\n\n\n /**\n * Calculates the duration(in frames) the message-renderer needs to display\n * the specified line.\n *\n * @method calculateDurationForLine\n * @param {gs.RendererTextLine} line The line to calculate the duration for.\n * @return {number} The duration in frames.\n */\n\n Component_MessageTextRenderer.prototype.calculateDurationForLine = function(line) {\n var duration, j, len, ref, token;\n duration = 0;\n if (line) {\n ref = line.content;\n for (j = 0, len = ref.length; j < len; j++) {\n token = ref[j];\n if (token != null) {\n duration += this.calculateDurationForToken(token);\n }\n }\n }\n return duration;\n };\n\n\n /**\n * Calculates the duration(in frames) the message-renderer needs to process\n * the specified token.\n *\n * @method calculateDurationForToken\n * @param {string|Object} token - The token.\n * @return {number} The duration in frames.\n */\n\n Component_MessageTextRenderer.prototype.calculateDurationForToken = function(token) {\n var duration;\n duration = 0;\n if (token.code != null) {\n switch (token.code) {\n case \"W\":\n if (token.value !== \"A\") {\n duration = token.value / 1000 * Graphics.frameRate;\n }\n }\n } else {\n duration = token.value.length * this.speed;\n }\n return duration;\n };\n\n\n /**\n * Calculates the maximum of lines which can be displayed in one message.\n *\n * @method calculateMaxLines\n * @param {Array} lines - An array of line-objects.\n * @return {number} The number of displayable lines.\n */\n\n Component_MessageTextRenderer.prototype.calculateMaxLines = function(lines) {\n var height, j, len, line, result;\n height = 0;\n result = 0;\n for (j = 0, len = lines.length; j < len; j++) {\n line = lines[j];\n height += line.height + this.lineSpacing;\n if (this.currentY + height > this.object.dstRect.height) {\n break;\n }\n result++;\n }\n return Math.min(lines.length, result || 1);\n };\n\n\n /**\n * Displays the character or processes the next control-token.\n *\n * @method drawNext\n */\n\n Component_MessageTextRenderer.prototype.drawNext = function() {\n var lineSpacing, s, size, token;\n token = this.processToken();\n if ((token != null ? token.value.length : void 0) > 0) {\n this.char = this.token.value.charAt(this.charIndex);\n size = this.font.measureTextPlain(this.char);\n s = Graphics.scale;\n lineSpacing = this.lineSpacing;\n if (this.currentLine !== this.line) {\n this.currentLine = this.line;\n this.currentLineHeight = 0;\n }\n this.currentSprite.y = this.object.origin.y + this.object.dstRect.y + this.currentY;\n this.currentSprite.visible = true;\n this.drawLineContent(this.lines[this.line], this.currentSprite.bitmap, this.charIndex + 1);\n this.currentSprite.srcRect.width = this.currentSprite.bitmap.width;\n this.currentLineHeight = this.lines[this.line].height;\n return this.currentX = Math.min(this.lines[this.line].width, this.currentX + size.width);\n }\n };\n\n\n /**\n * Processes the next character/token of the message.\n * @method nextChar\n * @private\n */\n\n Component_MessageTextRenderer.prototype.nextChar = function() {\n var base, base1, results;\n results = [];\n while (true) {\n this.charIndex++;\n this.lineAnimationCount = this.speed;\n if ((this.token.code != null) || this.charIndex >= this.token.value.length) {\n if (typeof (base = this.token).onEnd === \"function\") {\n base.onEnd();\n }\n this.tokenIndex++;\n if (this.tokenIndex >= this.lines[this.line].content.length) {\n this.tokenIndex = 0;\n this.line++;\n this.currentSprite.srcRect.width = this.currentSprite.bitmap.width;\n this.currentSprite = this.sprites[this.line];\n if (this.currentSprite != null) {\n this.currentSprite.x = this.object.origin.x + this.object.dstRect.x;\n }\n if (this.line < this.maxLines) {\n this.currentY += (this.currentLineHeight || this.font.lineHeight) + this.lineSpacing * Graphics.scale;\n this.charIndex = 0;\n this.currentX = 0;\n this.token = this.lines[this.line].content[this.tokenIndex] || new gs.RendererToken(null, \"\");\n }\n } else {\n this.charIndex = 0;\n this.token = this.lines[this.line].content[this.tokenIndex] || new gs.RendererToken(null, \"\");\n }\n if (typeof (base1 = this.token).onStart === \"function\") {\n base1.onStart();\n }\n }\n if (!this.token || this.token.value !== \"\\n\" || !this.lines[this.line]) {\n break;\n } else {\n results.push(void 0);\n }\n }\n return results;\n };\n\n\n /**\n * Finishes the message. Depending on the message configuration, the\n * message text-renderer will now wait for a user-action or a certain amount\n * of time.\n *\n * @method finish\n */\n\n Component_MessageTextRenderer.prototype.finish = function() {\n var ref, ref1, ref2;\n if (this.waitAtEnd) {\n this.isWaiting = true;\n return (ref = this.object.events) != null ? ref.emit(\"messageWaiting\", this) : void 0;\n } else if (this.waitAtEndTime > 0) {\n this.waitCounter = this.waitAtEndTime;\n this.isWaiting = false;\n return (ref1 = this.object.events) != null ? ref1.emit(\"messageWaiting\", this) : void 0;\n } else {\n if ((ref2 = this.object.events) != null) {\n ref2.emit(\"messageWaiting\", this);\n }\n return this[\"continue\"]();\n }\n };\n\n\n /**\n * Returns the position of the caret in pixels. The caret is like an invisible\n * cursor pointing to the x/y coordinates of the last rendered character of\n * the message. That position can be used to display a waiting- or processing-animation for example.\n *\n * @method updateCaretPosition\n */\n\n Component_MessageTextRenderer.prototype.updateCaretPosition = function() {\n this.caretPosition.x = this.currentX + this.padding;\n return this.caretPosition.y = this.currentY + this.currentLineHeight / 2;\n };\n\n\n /**\n * Updates the line writing.\n *\n * @method updateLineWriting\n * @private\n */\n\n Component_MessageTextRenderer.prototype.updateLineWriting = function() {\n if (this.isRunning && !this.isWaiting && !this.waitForKey && this.waitCounter <= 0) {\n if (this.lineAnimationCount <= 0) {\n while (true) {\n if (this.line < this.maxLines) {\n this.nextChar();\n }\n if (this.line >= this.maxLines) {\n this.finish();\n } else {\n this.drawNext();\n }\n if (!((this.token.code || this.lineAnimationCount <= 0 || this.drawImmediately) && !this.waitForKey && this.waitCounter <= 0 && this.isRunning && this.line < this.maxLines)) {\n break;\n }\n }\n }\n if (GameManager.tempSettings.skip) {\n return this.lineAnimationCount = 0;\n } else {\n return this.lineAnimationCount--;\n }\n }\n };\n\n\n /**\n * Updates wait-for-key state. If skipping is enabled, the text renderer will\n * not wait for key press.\n *\n * @method updateWaitForKey\n * @private\n */\n\n Component_MessageTextRenderer.prototype.updateWaitForKey = function() {\n if (this.waitForKey) {\n this.isWaiting = !GameManager.tempSettings.skip;\n return this.waitForKey = this.isWaiting;\n }\n };\n\n\n /**\n * Updates wait counter if the text renderer is waiting for a certain amount of time to pass. If skipping is enabled, the text renderer will\n * not wait for the actual amount of time and sets the wait-counter to 1 frame instead.\n *\n * @method updateWaitForKey\n * @private\n */\n\n Component_MessageTextRenderer.prototype.updateWaitCounter = function() {\n if (this.waitCounter > 0) {\n if (GameManager.tempSettings.skip) {\n this.waitCounter = 1;\n }\n this.isWaiting = true;\n this.waitCounter--;\n if (this.waitCounter <= 0) {\n this.isWaiting = false;\n if (this.line >= this.maxLines) {\n return this[\"continue\"]();\n }\n }\n }\n };\n\n\n /**\n * Creates a token-object for a specified text-code.\n * \n * @method createToken\n * @param {string} code - The code/type of the text-code.\n * @param {string} value - The value of the text-code.\n * @return {Object} The token-object.\n */\n\n Component_MessageTextRenderer.prototype.createToken = function(code, value) {\n var data, i, j, ref, tokenObject;\n tokenObject = null;\n switch (code) {\n case \"CE\":\n data = value.split(\"/\");\n value = data.shift();\n value = isNaN(value) ? value : parseInt(value);\n for (i = j = 0, ref = data; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {\n if (data[i].startsWith('\"') && data[i].endsWith('\"')) {\n data[i] = data[i].substring(1, data[i].length - 1);\n } else {\n data[i] = isNaN(data[i]) ? data[i] : parseFloat(data[i]);\n }\n }\n tokenObject = {\n code: code,\n value: value,\n values: data\n };\n break;\n default:\n tokenObject = Component_MessageTextRenderer.__super__.createToken.call(this, code, value);\n }\n return tokenObject;\n };\n\n\n /**\n * <p>Measures a control-token. If a token produces a visual result like displaying an icon then it must return the size taken by\n * the visual result. If the token has no visual result, <b>null</b> must be returned. This method is called for every token when the message is initialized.</p> \n *\n * <p>This method is not called while the message is running. For that case, see <i>processControlToken</i> method which is called\n * for every token while the message is running.</p>\n *\n * @param {Object} token - A control-token.\n * @return {gs.Size} The size of the area taken by the visual result of the token or <b>null</b> if the token has no visual result.\n * @method analyzeControlToken\n * @protected\n */\n\n Component_MessageTextRenderer.prototype.measureControlToken = function(token) {\n return Component_MessageTextRenderer.__super__.measureControlToken.call(this, token);\n };\n\n\n /**\n * <p>Draws the visual result of a token, like an icon for example, to the specified bitmap. This method is called for every token when the message is initialized and the sprites for each\n * text-line are created.</p> \n *\n * <p>This method is not called while the message is running. For that case, see <i>processControlToken</i> method which is called\n * for every token while the message is running.</p>\n *\n * @param {Object} token - A control-token.\n * @param {gs.Bitmap} bitmap - The bitmap used for the current text-line. Can be used to draw something on it like an icon, etc.\n * @param {number} offset - An x-offset for the draw-routine.\n * @param {number} length - Determines how many characters of the token should be drawn. Can be ignored for tokens\n * not drawing any characters.\n * @method drawControlToken\n * @protected\n */\n\n Component_MessageTextRenderer.prototype.drawControlToken = function(token, bitmap, offset, length) {\n switch (token.code) {\n case \"RT\":\n return Component_MessageTextRenderer.__super__.drawControlToken.call(this, token, bitmap, offset, length);\n }\n };\n\n\n /**\n * Processes a control-token. A control-token is a token which influences\n * the text-rendering like changing the fonts color, size or style. Changes \n * will be automatically applied to the game object's font.\n *\n * For message text-renderer, a few additional control-tokens like\n * speed-change, waiting, etc. needs to be processed here.\n *\n * This method is called for each token while the message is initialized and\n * also while the message is running. See <i>formattingOnly</i> parameter.\n *\n * @param {Object} token - A control-token.\n * @param {boolean} formattingOnly - If <b>true</b> the message is initializing right now and only \n * format-tokens should be processed which is necessary for the message to calculated sizes correctly.\n * @return {Object} A new token which is processed next or <b>null</b>.\n * @method processControlToken\n * @protected\n */\n\n Component_MessageTextRenderer.prototype.processControlToken = function(token, formattingOnly) {\n var animation, bitmap, character, duration, easing, expression, line, linkStart, object, params, ref, ref1, result, sound, textTokens, values;\n if (formattingOnly) {\n return Component_MessageTextRenderer.__super__.processControlToken.call(this, token);\n }\n result = null;\n switch (token.code) {\n case \"CR\":\n character = RecordManager.charactersArray.first(function(c) {\n var ref;\n return ((ref = c.name.defaultText) != null ? ref : c.name) === token.value;\n });\n if (character) {\n SceneManager.scene.currentCharacter = character;\n }\n break;\n case \"CE\":\n params = {\n \"values\": token.values\n };\n if ((ref = this.object.events) != null) {\n ref.emit(\"callCommonEvent\", this.object, {\n commonEventId: token.value,\n params: params,\n finish: false,\n waiting: true\n });\n }\n break;\n case \"X\":\n if (typeof token.value === \"function\") {\n token.value(this.object);\n }\n break;\n case \"A\":\n animation = RecordManager.animations[Math.max(token.value - 1, 0)];\n if ((animation != null ? animation.graphic.name : void 0) != null) {\n bitmap = ResourceManager.getBitmap(\"Graphics/Pictures/\" + animation.graphic.name);\n object = new gs.Object_Animation(animation);\n this.addCustomObject(object);\n this.currentX += Math.round(bitmap.width / animation.framesX);\n this.currentSprite.srcRect.width += Math.round(bitmap.width / animation.framesX);\n }\n break;\n case \"RT\":\n if (token.rtSize.width > token.rbSize.width) {\n this.currentX += token.rtSize.width;\n this.font.set(this.getRubyTextFont(token));\n } else {\n this.currentX += token.rbSize.width;\n }\n break;\n case \"LK\":\n if (token.value === 'E') {\n object = new ui.Object_Hotspot();\n object.enabled = true;\n object.setup();\n this.addCustomObject(object);\n object.dstRect.x = this.object.dstRect.x + this.object.origin.x + this.customData.linkData.cx;\n object.dstRect.y = this.object.dstRect.y + this.object.origin.y + this.customData.linkData.cy;\n object.dstRect.width = this.currentX - this.customData.linkData.cx;\n object.dstRect.height = this.currentLineHeight;\n object.events.on(\"click\", gs.CallBack(\"onLinkClick\", this), {\n linkData: this.customData.linkData\n }, this);\n } else {\n this.customData.linkData = {\n cx: this.currentX,\n cy: this.currentY,\n commonEventId: token.value,\n tokenIndex: this.tokenIndex\n };\n }\n break;\n case \"SLK\":\n if (token.value === 'E') {\n this.currentSprite.bitmap.clearRect(this.customData.linkData.cx, this.customData.linkData.cy, this.currentX - this.customData.linkData.cx + this.object.font.borderSize * 2, this.currentLineHeight);\n line = this.lines[this.line].content;\n linkStart = this.findToken(this.tokenIndex - 1, \"SLK\", -1, line);\n textTokens = this.findTokensBetween(this.customData.linkData.tokenIndex, this.tokenIndex, null, line);\n object = new ui.Object_Text();\n object.text = textTokens.select((function(_this) {\n return function(x) {\n return x.value;\n };\n })(this)).join(\"\");\n object.sizeToFit = true;\n object.formatting = true;\n object.wordWrap = false;\n object.ui = new ui.Component_UIBehavior();\n object.enabled = true;\n object.addComponent(object.ui);\n object.addComponent(new gs.Component_HotspotBehavior());\n if (this.customData.linkData.styleIndex === -1) {\n ui.UIManager.addControlStyles(object, [\"hyperlink\"]);\n } else {\n ui.UIManager.addControlStyles(object, [\"hyperlink-\" + this.customData.linkData.styleIndex]);\n }\n object.setup();\n this.addCustomObject(object);\n object.dstRect.x = this.object.dstRect.x + this.object.origin.x + this.customData.linkData.cx;\n object.dstRect.y = this.object.dstRect.y + this.object.origin.y + this.customData.linkData.cy;\n object.events.on(\"click\", gs.CallBack(\"onLinkClick\", this), {\n linkData: this.customData.linkData\n }, this);\n } else {\n if ((ref1 = token.value) != null ? ref1.contains(\",\") : void 0) {\n values = token.value.split(\",\");\n this.customData.linkData = {\n cx: this.currentX,\n cy: this.currentY,\n commonEventId: values[0],\n styleIndex: parseInt(values[1]),\n tokenIndex: this.tokenIndex\n };\n } else {\n this.customData.linkData = {\n cx: this.currentX,\n cy: this.currentY,\n commonEventId: token.value,\n tokenIndex: this.tokenIndex,\n styleIndex: -1\n };\n }\n }\n break;\n case \"E\":\n expression = RecordManager.characterExpressions[Math.max(token.value - 1, 0)];\n character = SceneManager.scene.currentCharacter;\n if ((expression != null) && ((character != null ? character.index : void 0) != null)) {\n duration = GameManager.defaults.character.expressionDuration;\n easing = gs.Easings.fromObject(GameManager.defaults.character.changeEasing);\n animation = GameManager.defaults.character.changeAnimation;\n object = SceneManager.scene.characters.first(function(c) {\n return c.rid === character.index;\n });\n if (object != null) {\n object.behavior.changeExpression(expression, animation, easing, duration);\n }\n }\n break;\n case \"SP\":\n sound = RecordManager.system.sounds[token.value - 1];\n AudioManager.playSound(sound);\n break;\n case \"S\":\n GameManager.settings.messageSpeed = token.value;\n break;\n case \"W\":\n this.drawImmediately = false;\n if (!GameManager.tempSettings.skip) {\n if (token.value === \"A\") {\n this.waitForKey = true;\n } else {\n this.waitCounter = Math.round(token.value / 1000 * Graphics.frameRate);\n }\n }\n break;\n case \"WE\":\n this.waitAtEnd = token.value === \"Y\";\n break;\n case \"DI\":\n this.drawImmediately = token.value === 1 || token.value === \"Y\";\n break;\n default:\n result = Component_MessageTextRenderer.__super__.processControlToken.call(this, token);\n }\n return result;\n };\n\n\n /**\n * Clears/Resets the text-renderer.\n *\n * @method clear\n */\n\n Component_MessageTextRenderer.prototype.clear = function() {\n var j, len, ref, ref1, ref2, sprite;\n this.charIndex = 0;\n this.currentX = 0;\n this.currentY = 0;\n this.line = 0;\n this.lines = [];\n this.clearCustomObjects();\n if ((ref = this.object.bitmap) != null) {\n ref.clear();\n }\n ref1 = this.allSprites;\n for (j = 0, len = ref1.length; j < len; j++) {\n sprite = ref1[j];\n sprite.dispose();\n if ((ref2 = sprite.bitmap) != null) {\n ref2.dispose();\n }\n }\n this.allSprites = [];\n return null;\n };\n\n\n /**\n * Clears/Disposes all sprites used to display the text-lines/parts.\n *\n * @method clearAllSprites\n */\n\n Component_MessageTextRenderer.prototype.clearAllSprites = function() {\n var j, len, ref, ref1, sprite;\n ref = this.allSprites;\n for (j = 0, len = ref.length; j < len; j++) {\n sprite = ref[j];\n sprite.dispose();\n if ((ref1 = sprite.bitmap) != null) {\n ref1.dispose();\n }\n }\n return null;\n };\n\n\n /**\n * Clears/Disposes the sprites used to display the text-lines/parts of the current/last message.\n *\n * @method clearSprites\n */\n\n Component_MessageTextRenderer.prototype.clearSprites = function() {\n var j, len, ref, ref1, sprite;\n ref = this.sprites;\n for (j = 0, len = ref.length; j < len; j++) {\n sprite = ref[j];\n sprite.dispose();\n if ((ref1 = sprite.bitmap) != null) {\n ref1.dispose();\n }\n }\n return null;\n };\n\n\n /**\n * Removes a game object from the message.\n *\n * @method removeCustomObject\n * @param object {gs.Object_Base} The game object to remove.\n */\n\n Component_MessageTextRenderer.prototype.removeCustomObject = function(object) {\n SceneManager.scene.removeObject(object);\n object.dispose();\n return this.customObjects.remove(object);\n };\n\n\n /**\n * Adds a game object to the message which is alive until the message is\n * erased. Can be used to display animationed-icons, etc. in a message.\n *\n * @method addCustomObject\n * @param object {gs.Object_Base} The game object to add.\n */\n\n Component_MessageTextRenderer.prototype.addCustomObject = function(object) {\n object.dstRect.x = this.object.dstRect.x + this.object.origin.x + this.currentX;\n object.dstRect.y = this.object.dstRect.y + this.object.origin.y + this.currentY;\n object.zIndex = this.object.zIndex + 1;\n object.update();\n SceneManager.scene.addObject(object);\n return this.customObjects.push(object);\n };\n\n\n /**\n * Clears the list of custom game objects. All game objects are disposed and removed\n * from the scene.\n *\n * @method clearCustomObjects\n * @param object {Object} The game object to add.\n */\n\n Component_MessageTextRenderer.prototype.clearCustomObjects = function() {\n var j, len, object, ref;\n ref = this.customObjects;\n for (j = 0, len = ref.length; j < len; j++) {\n object = ref[j];\n object.dispose();\n SceneManager.scene.removeObject(object);\n }\n return this.customObjects = [];\n };\n\n\n /**\n * Creates the bitmap for a specified line-object.\n *\n * @method createBitmap\n * @private\n * @param {Object} line - A line-object.\n * @return {Bitmap} A newly created bitmap containing the line-text.\n */\n\n Component_MessageTextRenderer.prototype.createBitmap = function(line) {\n var bitmap;\n this.font = this.object.font;\n bitmap = new Bitmap(this.object.dstRect.width, Math.max(this.minLineHeight, line.height));\n bitmap.font = this.font;\n return bitmap;\n };\n\n\n /**\n * Draws the line's content on the specified bitmap.\n *\n * @method drawLineContent\n * @protected\n * @param {Object} line - A line-object which should be drawn on the bitmap.\n * @param {gs.Bitmap} bitmap - The bitmap to draw the line's content on.\n * @param {number} length - Determines how many characters of the specified line should be drawn. You can \n * specify -1 to draw all characters.\n */\n\n Component_MessageTextRenderer.prototype.drawLineContent = function(line, bitmap, length) {\n var currentX, drawAll, i, j, len, ref, size, token, value;\n bitmap.clear();\n currentX = this.padding;\n drawAll = length === -1;\n ref = line.content;\n for (i = j = 0, len = ref.length; j < len; i = ++j) {\n token = ref[i];\n if (i > this.tokenIndex && !drawAll) {\n break;\n }\n if (token.code != null) {\n size = this.measureControlToken(token, bitmap);\n this.drawControlToken(token, bitmap, currentX);\n if (size) {\n currentX += size.width;\n }\n this.processControlToken(token, true, line);\n } else if (token.value.length > 0) {\n token.applyFormat(this.font);\n value = token.value;\n if (!drawAll && this.tokenIndex === i && value.length > length) {\n value = value.substring(0, length);\n }\n if (value !== \"\\n\") {\n size = this.font.measureTextPlain(value);\n bitmap.drawText(currentX, line.height - (size.height - this.font.descent) - line.descent, size.width, bitmap.height, value, 0, 0);\n currentX += size.width;\n }\n }\n }\n return line.contentWidth = currentX + this.font.measureTextPlain(\" \").width;\n };\n\n\n /**\n * Creates the sprite for a specified line-object.\n *\n * @method createSprite\n * @private\n * @param {Object} line - A line-object.\n * @return {Sprite} A newly created sprite object containing the line-text as bitmap.\n */\n\n Component_MessageTextRenderer.prototype.createSprite = function(line) {\n var bitmap, sprite;\n bitmap = this.createBitmap(line);\n this.currentX = 0;\n this.waitCounter = 0;\n this.waitForKey = false;\n sprite = new Sprite(Graphics.viewport);\n sprite.bitmap = bitmap;\n sprite.visible = true;\n sprite.z = this.object.zIndex + 1;\n sprite.srcRect = new Rect(0, 0, 0, bitmap.height);\n return sprite;\n };\n\n\n /**\n * Creates the sprites for a specified array of line-objects.\n *\n * @method createSprites\n * @private\n * @see gs.Component_MessageTextRenderer.createSprite.\n * @param {Array} lines - An array of line-objects.\n * @return {Array} An array of sprites.\n */\n\n Component_MessageTextRenderer.prototype.createSprites = function(lines) {\n var i, j, len, line, result, sprite;\n this.fontSize = this.object.font.size;\n result = [];\n for (i = j = 0, len = lines.length; j < len; i = ++j) {\n line = lines[i];\n sprite = this.createSprite(line);\n result.push(sprite);\n }\n return result;\n };\n\n\n /**\n * Starts a new line.\n *\n * @method newLine\n */\n\n Component_MessageTextRenderer.prototype.newLine = function() {\n this.currentX = 0;\n return this.currentY += this.currentLineHeight + this.lineSpacing;\n };\n\n\n /**\n * Displays a formatted text immediately without any delays or animations. The\n * Component_TextRenderer.drawFormattedText method from the base-class cannot\n * be used here because it would render to the game object's bitmap object while\n * this method is rendering to the sprites.\n *\n * @method drawFormattedTextImmediately\n * @param {number} x - The x-coordinate of the text's position.\n * @param {number} y - The y-coordinate of the text's position.\n * @param {number} width - Deprecated. Can be null.\n * @param {number} height - Deprecated. Can be null.\n * @param {string} text - The text to draw.\n * @param {boolean} wordWrap - If wordWrap is set to true, line-breaks are automatically created.\n */\n\n Component_MessageTextRenderer.prototype.drawFormattedTextImmediately = function(x, y, width, height, text, wordWrap) {\n this.drawFormattedText(x, y, width, height, text, wordWrap);\n while (true) {\n this.nextChar();\n if (this.line >= this.maxLines) {\n this.isRunning = false;\n } else {\n this.drawNext();\n }\n if (!this.isRunning) {\n break;\n }\n }\n this.currentY += this.currentLineHeight + this.lineSpacing;\n return null;\n };\n\n\n /**\n * Starts the rendering-process for the message.\n *\n * @method drawFormattedText\n * @param {number} x - The x-coordinate of the text's position.\n * @param {number} y - The y-coordinate of the text's position.\n * @param {number} width - Deprecated. Can be null.\n * @param {number} height - Deprecated. Can be null.\n * @param {string} text - The text to draw.\n * @param {boolean} wordWrap - If wordWrap is set to true, line-breaks are automatically created.\n */\n\n Component_MessageTextRenderer.prototype.drawFormattedText = function(x, y, width, height, text, wordWrap) {\n var currentX, ref;\n text = text || \" \";\n this.font.set(this.object.font);\n this.speed = 11 - Math.round(GameManager.settings.messageSpeed * 2.5);\n this.isRunning = true;\n this.drawImmediately = false;\n this.lineAnimationCount = this.speed;\n this.currentLineHeight = 0;\n this.isWaiting = false;\n this.waitForKey = false;\n this.charIndex = 0;\n this.token = null;\n this.tokenIndex = 0;\n this.message = text;\n this.line = 0;\n this.currentLine = this.line;\n currentX = this.currentX;\n this.lines = this.calculateLines(lcsm(this.message), wordWrap, this.currentX);\n this.sprites = this.createSprites(this.lines);\n this.allSprites = this.allSprites.concat(this.sprites);\n this.currentX = currentX;\n this.currentSprite = this.sprites[this.line];\n this.currentSprite.x = this.currentX + this.object.origin.x + this.object.dstRect.x;\n this.maxLines = this.calculateMaxLines(this.lines);\n this.token = ((ref = this.lines[this.line]) != null ? ref.content[this.tokenIndex] : void 0) || new gs.RendererToken(null, \"\");\n return this.start();\n };\n\n\n /**\n * Starts the message-rendering process.\n *\n * @method start\n * @protected\n */\n\n Component_MessageTextRenderer.prototype.start = function() {\n var ref;\n if (GameManager.tempSettings.skip && GameManager.tempSettings.skipTime === 0) {\n return this.instantSkip();\n } else if (this.maxLines === 0) {\n if (((ref = this.lines[0]) != null ? ref.content : void 0) === \"\") {\n return this.finish();\n } else {\n this.maxLines = 1;\n return this.drawNext();\n }\n } else {\n return this.drawNext();\n }\n };\n\n\n /**\n * Skips the current message and finishes the message-processing immediately. The message\n * tokens are processed but not rendered.\n *\n * @method instantSkip\n */\n\n Component_MessageTextRenderer.prototype.instantSkip = function() {\n var ref;\n while (true) {\n if (this.line < this.maxLines) {\n this.nextChar();\n }\n if (this.line >= this.maxLines) {\n break;\n } else {\n this.processToken();\n }\n if (!(this.isRunning && this.line < this.maxLines)) {\n break;\n }\n }\n if ((ref = this.object.events) != null) {\n ref.emit(\"messageWaiting\", this);\n }\n return this[\"continue\"]();\n };\n\n\n /**\n * Processes the current token.\n *\n * @method processToken\n */\n\n Component_MessageTextRenderer.prototype.processToken = function() {\n var base, token;\n token = null;\n if (this.token.code != null) {\n token = this.processControlToken(this.token, false);\n if (token != null) {\n this.token = token;\n if (typeof (base = this.token).onStart === \"function\") {\n base.onStart();\n }\n }\n } else {\n token = this.token;\n }\n return token;\n };\n\n return Component_MessageTextRenderer;\n\n})(gs.Component_TextRenderer);\n\ngs.Component_MessageTextRenderer = Component_MessageTextRenderer;\n\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU9BLElBQUEsNkJBQUE7RUFBQTs7O0FBQU07OztFQUNGLDZCQUFDLENBQUEsb0JBQUQsR0FBd0IsQ0FBQyxhQUFELEVBQWdCLGtCQUFoQjs7O0FBQ3hCOzs7Ozs7Ozs7MENBUUEsbUJBQUEsR0FBcUIsU0FBQyxJQUFELEVBQU8sT0FBUDtBQUNqQixRQUFBO0lBQUEsSUFBQyxDQUFBLGtCQUFELENBQUE7SUFDQSxDQUFBLEdBQUk7QUFFSjtBQUFBLFNBQUEscUNBQUE7O01BQ0ksSUFBRyxJQUFDLENBQUEsTUFBTSxDQUFDLFFBQVEsQ0FBQyxpQkFBcEI7UUFDSSxJQUFDLENBQUEsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFiLEdBQXlCLElBQUEsRUFBRSxDQUFDLEtBQUgsQ0FBUyxPQUFPLENBQUMsU0FBUyxDQUFDLFNBQTNCLEVBRDdCOztNQUVBLElBQUMsQ0FBQSxLQUFELEdBQVMsSUFBQyxDQUFBLGNBQUQsQ0FBZ0IsSUFBQSxDQUFLLE9BQU8sQ0FBQyxJQUFiLENBQWhCLEVBQW9DLElBQXBDLEVBQXlDLENBQXpDO0FBQ1Q7QUFBQSxXQUFBLHdDQUFBOztRQUNJLE1BQUEsR0FBUyxJQUFDLENBQUEsWUFBRCxDQUFjLElBQWQ7UUFDVCxJQUFHLElBQUEsS0FBUSxJQUFDLENBQUEsSUFBWjtVQUNJLElBQUMsQ0FBQSxlQUFELENBQWlCLElBQWpCLEVBQXVCLE1BQXZCLEVBQStCLElBQUMsQ0FBQSxTQUFELEdBQVcsQ0FBMUMsRUFESjtTQUFBLE1BQUE7VUFHSSxJQUFDLENBQUEsZUFBRCxDQUFpQixJQUFqQixFQUF1QixNQUF2QixFQUErQixDQUFDLENBQWhDLEVBSEo7O1FBSUEsSUFBQyxDQUFBLFVBQVcsQ0FBQSxDQUFBLENBQUUsQ0FBQyxNQUFmLEdBQXdCO1FBQ3hCLENBQUE7QUFQSjtBQUpKO0FBY0E7QUFBQSxTQUFBLHdDQUFBOztNQUNJLFlBQVksQ0FB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O2NBQ0gsQ0FBQztTQUZYO09BRko7S0FBQSxNQUFBO01BTUksS0FBQSxHQUFRLElBQUMsQ0FBQSxNQU5iOztBQVFBLFdBQU87RUFYRzs7OztHQXZxQzBCLEVBQUUsQ0FBQzs7QUFzckMvQyxFQUFFLENBQUMsNkJBQUgsR0FBbUMiLCJzb3VyY2VzQ29udGVudCI6WyIjID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiNcbiMgICBTY3JpcHQ6IENvbXBvbmVudF9NZXNzYWdlVGV4dFJlbmRlcmVyXG4jXG4jICAgJCRDT1BZUklHSFQkJFxuI1xuIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5jbGFzcyBDb21wb25lbnRfTWVzc2FnZVRleHRSZW5kZXJlciBleHRlbmRzIGdzLkNvbXBvbmVudF9UZXh0UmVuZGVyZXJcbiAgICBAb2JqZWN0Q29kZWNCbGFja0xpc3QgPSBbXCJvbkxpbmtDbGlja1wiLCBcIm9uQmF0Y2hEaXNhcHBlYXJcIl1cbiAgICAjIyMqXG4gICAgKiBDYWxsZWQgaWYgdGhpcyBvYmplY3QgaW5zdGFuY2UgaXMgcmVzdG9yZWQgZnJvbSBhIGRhdGEtYnVuZGxlLiBJdCBjYW4gYmUgdXNlZFxuICAgICogcmUtYXNzaWduIGV2ZW50LWhhbmRsZXIsIGFub255bW91cyBmdW5jdGlvbnMsIGV0Yy5cbiAgICAqIFxuICAgICogQG1ldGhvZCBvbkRhdGFCdW5kbGVSZXN0b3JlLlxuICAgICogQHBhcmFtIE9iamVjdCBkYXRhIC0gVGhlIGRhdGEtYnVuZGxlXG4gICAgKiBAcGFyYW0gZ3MuT2JqZWN0Q29kZWNDb250ZXh0IGNvbnRleHQgLSBUaGUgY29kZWMtY29udGV4dC5cbiAgICAjIyNcbiAgICBvbkRhdGFCdW5kbGVSZXN0b3JlOiAoZGF0YSwgY29udGV4dCkgLT5cbiAgICAgICAgQHNldHVwRXZlbnRIYW5kbGVycygpXG4gICAgICAgIGwgPSAwXG4gICAgICAgIFxuICAgICAgICBmb3IgbWVzc2FnZSBpbiBAb2JqZWN0Lm1lc3NhZ2VzXG4gICAgICAgICAgICBpZiBAb2JqZWN0LnNldHRpbmdzLnVzZUNoYXJhY3RlckNvbG9yXG4gICAgICAgICAgICAgICAgQG9iamVjdC5mb250LmNvbG9yID0gbmV3IGdzLkNvbG9yKG1lc3NhZ2UuY2hhcmFjdGVyLnRleHRDb2xvcilcbiAgICAgICAgICAgIEBsaW5lcyA9IEBjYWxjdWxhdGVMaW5lcyhsY3NtKG1lc3NhZ2UudGV4dCksIHllcywgMClcbiAgICAgICAgICAgIGZvciBsaW5lIGluIEBsaW5lc1xuICAgICAgICAgICAgICAgIGJpdG1hcCA9IEBjcmVhdGVCaXRtYXAobGluZSlcbiAgICAgICAgICAgICAgICBpZiBsaW5lID09IEBsaW5lXG4gICAgICAgICAgICAgICAgICAgIEBkcmF3TGluZUNvbnRlbnQobGluZSwgYml0bWFwLCBAY2hhckluZGV4KzEpXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICBAZHJhd0xpbmVDb250ZW50KGxpbmUsIGJpdG1hcCwgLTEpXG4gICAgICAgICAgICAgICAgQGFsbFNwcml0ZXNbbF0uYml0bWFwID0gYml0bWFwXG4gICAgICAgICAgICAgICAgbCsrXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgXG4gICAgICAgIGZvciBjdXN0b21PYmplY3QgaW4gQGN1c3RvbU9iamVjdHNcbiAgICAgICAgICAgIFNjZW5lTWFuYWdlci5zY2VuZS5hZGRPYmplY3QoY3VzdG9tT2JqZWN0KVxuICAgICAgICAgICAgICAgIFxuICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICBcbiAgICAjIyMqXG4gICAgKiAgQSB0ZXh0LXJlbmRlcmVyIGNvbXBvbmVudCB0byByZW5kZXIgYW4gYW5pbWF0ZWQgYW5kIGludGVyYWN0aXZlIG1lc3NhZ2UgdGV4dCB1c2luZ1xuICAgICogIGRpbWVuc2lvbnMgb2YgdGhlIGdhbWUgb2JqZWN0J3MgZGVzdGluYXRpb24tcmVjdGFuZ2xlLiBUaGUgbWVzc2FnZSBpcyBkaXNwbGF5ZWRcbiAgICAqICB1c2luZyBhIHNwcml0ZSBmb3IgZWFjaCBsaW5lIGluc3RlYWQgb2YgZHJhd2luZyB0byB0aGUgZ2FtZSBvYmplY3QncyBiaXRtYXAgb2JqZWN0LlxuICAgICpcbiAgICAqICBAbW9kdWxlIGdzXG4gICAgKiAgQGNsYXNzIENvbXBvbmVudF9NZXNzYWdlVGV4dFJlbmRlcmVyXG4gICAgKiAgQGV4dGVuZHMgZ3MuQ29tcG9uZW50X1RleHRSZW5kZXJlclxuICAgICogIEBtZW1iZXJvZiBnc1xuICAgICogIEBjb25zdHJ1Y3RvclxuICAgICMjI1xuICAgIGNvbnN0cnVjdG9yOiAtPlxuICAgICAgICBzdXBlclxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIEFuIGFycmF5IGNvbnRhaW5pbmcgYWxsIHNwcml0ZXMgb2YgdGhlIGN1cnJlbnQgbWVzc2FnZS5cbiAgICAgICAgKiBAcHJvcGVydHkgc3ByaXRlc1xuICAgICAgICAqIEB0eXBlIGdzLlNwcml0ZVtdXG4gICAgICAgICogQHByb3RlY3RlZFxuICAgICAgICAjIyNcbiAgICAgICAgQHNwcml0ZXMgPSBbXVxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIEFuIGFycmF5IGNvbnRhaW5pbmcgYWxsIHNwcml0ZXMgb2YgYWxsIG1lc3NhZ2VzLiBJbiBOVkwgbW9kZVxuICAgICAgICAqIGEgcGFnZSBjYW4gY29udGFpbiBtdWx0aXBsZSBtZXNzYWdlcy5cbiAgICAgICAgKiBAcHJvcGVydHkgYWxsU3ByaXRlc1xuICAgICAgICAqIEB0eXBlIGdzLlNwcml0ZVtdXG4gICAgICAgICogQHByb3RlY3RlZFxuICAgICAgICAjIyNcbiAgICAgICAgQGFsbFNwcml0ZXMgPSBbXVxuICAgICAgICAjIyMqXG4gICAgICAgICogQW4gYXJyYXkgY29udGFpbmluZyBhbGwgbGluZS1vYmplY3RzIG9mIHRoZSBjdXJyZW50IG1lc3NhZ2UuXG4gICAgICAgICogQHByb3BlcnR5IGxpbmVzXG4gICAgICAgICogQHR5cGUgZ3MuVGV4dFJlbmRlcmVyTGluZVtdXG4gICAgICAgICogQHJlYWRPbmx5XG4gICAgICAgICMjI1xuICAgICAgICBAbGluZXMgPSBudWxsXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogVGhlIGxpbmUgY3VycmVudGx5IHJlbmRlcmVkLlxuICAgICAgICAqIEBwcm9wZXJ0eSBsaW5lXG4gICAgICAgICogQHR5cGUgbnVtYmVyXG4gICAgICAgICogQHJlYWRPbmx5XG4gICAgICAgICMjI1xuICAgICAgICBAbGluZSA9IDBcbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBUaGUgbGVmdCBhbmQgcmlnaHQgcGFkZGluZyBwZXIgbGluZS5cbiAgICAgICAgKiBAcHJvcGVydHkgcGFkZGluZ1xuICAgICAgICAqIEB0eXBlIG51bWJlclxuICAgICAgICAjIyNcbiAgICAgICAgQHBhZGRpbmcgPSA2XG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogVGhlIG1pbmltdW0gaGVpZ2h0IG9mIHRoZSBsaW5lIGN1cnJlbnRseSByZW5kZXJlZC4gSWYgMCwgdGhlIG1lYXN1cmVkXG4gICAgICAgICogaGVpZ2h0IG9mIHRoZSBsaW5lIHdpbGwgYmUgdXNlZC5cbiAgICAgICAgKiBAcHJvcGVydHkgbWluTGluZUhlaWdodFxuICAgICAgICAqIEB0eXBlIG51bWJlclxuICAgICAgICAjIyNcbiAgICAgICAgQG1pbkxpbmVIZWlnaHQgPSAwXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogVGhlIHNwYWNpbmcgYmV0d2VlbiB0ZXh0IGxpbmVzIGluIHBpeGVscy5cbiAgICAgICAgKiBAcHJvcGVydHkgbGluZVNwYWNpbmdcbiAgICAgICAgKiBAdHlwZSBudW1iZXJcbiAgICAgICAgIyMjXG4gICAgICAgIEBsaW5lU3BhY2luZyA9IDJcbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBUaGUgbGluZSBjdXJyZW50bHkgcmVuZGVyZWQuXG4gICAgICAgICogQHByb3BlcnR5IGN1cnJlbnRMaW5lXG4gICAgICAgICogQHR5cGUgbnVtYmVyXG4gICAgICAgICogQHByb3RlY3RlZFxuICAgICAgICAjIyNcbiAgICAgICAgQGN1cnJlbnRMaW5lID0gMFxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIFRoZSBoZWlnaHQgb2YgdGhlIGxpbmUgY3VycmVudGx5IHJlbmRlcmVkLlxuICAgICAgICAqIEBwcm9wZXJ0eSBjdXJyZW50TGluZUhlaWdodFxuICAgICAgICAqIEB0eXBlIG51bWJlclxuICAgICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgICAgIyMjXG4gICAgICAgIEBjdXJyZW50TGluZUhlaWdodCA9IDBcbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBJbmRleCBvZiB0aGUgY3VycmVudCBjaGFyYWN0ZXIgdG8gZHJhdy5cbiAgICAgICAgKiBAcHJvcGVydHkgY2hhckluZGV4XG4gICAgICAgICogQHR5cGUgbnVtYmVyXG4gICAgICAgICogQHJlYWRPbmx5XG4gICAgICAgICMjI1xuICAgICAgICBAY2hhckluZGV4ID0gMFxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIFBvc2l0aW9uIG9mIHRoZSBtZXNzYWdlIGNhcmV0LiBUaGUgY2FyZXQgaXMgbGlrZSBhbiBpbnZpc2libGVcbiAgICAgICAgKiBjdXJzb3IgcG9pbnRpbmcgdG8gdGhlIHgveSBjb29yZGluYXRlcyBvZiB0aGUgbGFzdCByZW5kZXJlZCBjaGFyYWN0ZXIgb2ZcbiAgICAgICAgKiB0aGUgbWVzc2FnZS4gVGhhdCBwb3NpdGlvbiBjYW4gYmUgdXNlZCB0byBkaXNwbGF5IGEgd2FpdGluZy0gb3IgcHJvY2Vzc2luZy1hbmltYXRpb24gZm9yIGV4YW1wbGUuXG4gICAgICAgICogQHByb3BlcnR5IGNhcmV0UG9zaXRpb25cbiAgICAgICAgKiBAdHlwZSBncy5Qb2ludFxuICAgICAgICAqIEByZWFkT25seVxuICAgICAgICAjIyNcbiAgICAgICAgQGNhcmV0UG9zaXRpb24gPSBuZXcgZ3MuUG9pbnQoKVxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIEluZGljYXRlcyB0aGF0IHRoZSBhIG1lc3NhZ2UgaXMgY3VycmVudGx5IGluIHByb2dyZXNzLlxuICAgICAgICAqIEBwcm9wZXJ0eSBpc1J1bm5pbmdcbiAgICAgICAgKiBAdHlwZSBib29sZWFuXG4gICAgICAgICogQHJlYWRPbmx5XG4gICAgICAgICMjI1xuICAgICAgICBAaXNSdW5uaW5nID0gbm9cbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBUaGUgY3VycmVudCB4LWNvb3JkaW5hdGUgb2YgdGhlIGNhcmV0L2N1cnNvci5cbiAgICAgICAgKiBAcHJvcGVydHkgY3VycmVudFhcbiAgICAgICAgKiBAdHlwZSBudW1iZXJcbiAgICAgICAgKiBAcmVhZE9ubHlcbiAgICAgICAgIyMjXG4gICAgICAgIEBjdXJyZW50WCA9IDBcbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBUaGUgY3VycmVudCB5LWNvb3JkaW5hdGUgb2YgdGhlIGNhcmV0L2N1cnNvci5cbiAgICAgICAgKiBAcHJvcGVydHkgY3VycmVudFlcbiAgICAgICAgKiBAdHlwZSBudW1iZXJcbiAgICAgICAgKiBAcmVhZE9ubHlcbiAgICAgICAgIyMjXG4gICAgICAgIEBjdXJyZW50WSA9IDBcbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBUaGUgY3VycmVudCBzcHJpdGVzIHVzZWQgdG8gZGlzcGxheSB0aGUgY3VycmVudCB0ZXh0LWxpbmUvcGFydC5cbiAgICAgICAgKiBAcHJvcGVydHkgY3VycmVudFNwcml0ZVxuICAgICAgICAqIEB0eXBlIGdzLlNwcml0ZVxuICAgICAgICAqIEByZWFkT25seVxuICAgICAgICAjIyNcbiAgICAgICAgQGN1cnJlbnRTcHJpdGUgPSBudWxsXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogSW5kaWNhdGVzIGlmIHRoZSBtZXNzYWdlLXJlbmRlcmVyIGlzIGN1cnJlbnRseSB3YWl0aW5nIGxpa2UgZm9yIGEgdXNlci1hY3Rpb24uXG4gICAgICAgICogQHByb3BlcnR5IGlzV2FpdGluZ1xuICAgICAgICAqIEB0eXBlIGJvb2xlYW5cbiAgICAgICAgKiBAcmVhZE9ubHlcbiAgICAgICAgIyMjXG4gICAgICAgIEBpc1dhaXRpbmcgPSBub1xuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIEluZGljYXRlcyBpZiB0aGUgbWVzc2FnZS1yZW5kZXJlciBpcyBjdXJyZW50bHkgd2FpdGluZyBmb3IgYSBrZXktcHJlc3Mgb3IgbW91c2UvdG91Y2ggYWN0aW9uLlxuICAgICAgICAqIEBwcm9wZXJ0eSB3YWl0Rm9yS2V5XG4gICAgICAgICogQHR5cGUgYm9vbGVhblxuICAgICAgICAqIEByZWFkT25seVxuICAgICAgICAjIyNcbiAgICAgICAgQHdhaXRGb3JLZXkgPSBub1xuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIE51bWJlciBvZiBmcmFtZXMgdGhlIG1lc3NhZ2UtcmVuZGVyZXIgc2hvdWxkIHdhaXQgYmVmb3JlIGNvbnRpbnVlLlxuICAgICAgICAqIEBwcm9wZXJ0eSB3YWl0Q291bnRlclxuICAgICAgICAqIEB0eXBlIG51bWJlclxuICAgICAgICAjIyNcbiAgICAgICAgQHdhaXRDb3VudGVyID0gMFxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIFNwZWVkIG9mIHRoZSBtZXNzYWdlLWRyYXdpbmcuIFRoZSBzbWFsbGVyIHRoZSB2YWx1ZSwgdGhlIGZhc3RlciB0aGUgbWVzc2FnZSBpcyBkaXNwbGF5ZWQuXG4gICAgICAgICogQHByb3BlcnR5IHNwZWVkXG4gICAgICAgICogQHR5cGUgbnVtYmVyXG4gICAgICAgICMjI1xuICAgICAgICBAc3BlZWQgPSAxXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogSW5kaWNhdGVzIGlmIHRoZSBtZXNzYWdlIHNob3VsZCBiZSByZW5kZXJlZCBpbW1lZGlhbHRlbHkgd2l0aG91dCBhbnkgYW5pbWF0aW9uIG9yIGRlbGF5LlxuICAgICAgICAqIEBwcm9wZXJ0eSBkcmF3SW1tZWRpYXRlbHlcbiAgICAgICAgKiBAdHlwZSBib29sZWFuXG4gICAgICAgICMjI1xuICAgICAgICBAZHJhd0ltbWVkaWF0ZWx5ID0gbm9cbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBJbmRpY2F0ZXMgaWYgdGhlIG1lc3NhZ2Ugc2hvdWxkIHdhaXQgZm9yIGEgdXNlci1hY3Rpb24gb3IgYSBjZXJ0YWluIGFtb3VudCBvZiB0aW1lXG4gICAgICAgICogYmVmb3JlIGZpbmlzaGluZy5cbiAgICAgICAgKiBAcHJvcGVydHkgd2FpdEF0RW5kXG4gICAgICAgICogQHR5cGUgYm9vbGVhblxuICAgICAgICAjIyNcbiAgICAgICAgQHdhaXRBdEVuZCA9IHllc1xuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIFRoZSBudW1iZXIgb2YgZnJhbWVzIHRvIHdhaXQgYmVmb3JlIGZpbmlzaGluZyBhIG1lc3NhZ2UuXG4gICAgICAgICogYmVmb3JlIGZpbmlzaGluZy5cbiAgICAgICAgKiBAcHJvcGVydHkgd2FpdEF0RW5kVGltZVxuICAgICAgICAqIEB0eXBlIG51bWJlclxuICAgICAgICAjIyNcbiAgICAgICAgQHdhaXRBdEVuZFRpbWUgPSAwXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogSW5kaWNhdGVzIGlmIGF1dG8gd29yZC13cmFwIHNob3VsZCBiZSB1c2VkLiBEZWZhdWx0IGlzIDxiPnRydWU8L2I+XG4gICAgICAgICogQHByb3BlcnR5IHdvcmRXcmFwXG4gICAgICAgICogQHR5cGUgYm9vbGVhblxuICAgICAgICAjIyNcbiAgICAgICAgQHdvcmRXcmFwID0geWVzXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogQ3VzdG9tIGdhbWUgb2JqZWN0cyB3aGljaCBhcmUgYWxpdmUgdW50aWwgdGhlIGN1cnJlbnQgbWVzc2FnZSBpcyBlcmFzZWQuIENhbiBiZSB1c2VkIHRvIGRpc3BsYXlcbiAgICAgICAgKiBhbmltYXRlZCBpY29ucywgZXRjLlxuICAgICAgICAqIEBwcm9wZXJ0eSBjdXN0b21PYmplY3RzXG4gICAgICAgICogQHR5cGUgZ3MuT2JqZWN0X0Jhc2VbXVxuICAgICAgICAjIyNcbiAgICAgICAgQGN1c3RvbU9iamVjdHMgPSBbXVxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIEEgaGFzaHRhYmxlL2RpY3Rpb25hcnkgb2JqZWN0IHRvIHN0b3JlIGN1c3RvbS1kYXRhIHVzZWZ1bCBsaWtlIGZvciB0b2tlbi1wcm9jZXNzaW5nLiBUaGUgZGF0YSBtdXN0IGJlXG4gICAgICAgICogc2VyaWFsaXphYmxlLlxuICAgICAgICAqIEBwcm9wZXJ0eSBjdXN0b21PYmplY3RzXG4gICAgICAgICogQHR5cGUgT2JqZWN0XG4gICAgICAgICMjI1xuICAgICAgICBAY3VzdG9tRGF0YSA9IHt9XG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogQSBjYWxsYmFjayBmdW5jdGlvbiBjYWxsZWQgaWYgdGhlIHBsYXllciBjbGlja3Mgb24gYSBub24tc3R5bGFibGUgbGluayAoTEsgdGV4dC1jb2RlKSB0byB0cmlnZ2VyXG4gICAgICAgICogdGhlIHNwZWNpZmllZCBjb21tb24gZXZlbnQuXG4gICAgICAgICogQHByb3BlcnR5IG9uTGlua0NsaWNrXG4gICAgICAgICogQHR5cGUgRnVuY3Rpb25cbiAgICAgICAgIyMjXG4gICAgICAgIEBvbkxpbmtDbGljayA9IChlKSAtPlxuICAgICAgICAgICAgZXZlbnRJZCA9IGUuZGF0YS5saW5rRGF0YS5jb21tb25FdmVudElkXG4gICAgICAgICAgICBldmVudCA9IFJlY29yZE1hbmFnZXIuY29tbW9uRXZlbnRzW2V2ZW50SWRdXG4gICAgICAgICAgICBpZiAhZXZlbnRcbiAgICAgICAgICAgICAgICBldmVudCA9IFJlY29yZE1hbmFnZXIuY29tbW9uRXZlbnRzLmZpcnN0ICh4KSA9PiB4Lm5hbWUgPT0gZXZlbnRJZFxuICAgICAgICAgICAgICAgIGV2ZW50SWQgPSBldmVudC5pbmRleCBpZiBldmVudFxuICAgICAgICAgICAgU2NlbmVNYW5hZ2VyLnNjZW5lLmludGVycHJldGVyLmNhbGxDb21tb25FdmVudChldmVudElkLCBudWxsLCB5ZXMpXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogQSBjYWxsYmFjayBmdW5jdGlvbiBjYWxsZWQgaWYgYSBiYXRjaGVkIG1lc3NzYWdlIGhhcyBiZWVuIGZhZGVkIG91dC4gSXQgdHJpZ2dlcnMgdGhlIGV4ZWN1dGlvbiBvZlxuICAgICAgICAqIHRoZSBuZXh0IG1lc3NhZ2UuXG4gICAgICAgICogQHByb3BlcnR5IG9uQmF0Y2hEaXNhcHBlYXJcbiAgICAgICAgKiBAdHlwZSBGdW5jdGlvblxuICAgICAgICAjIyMgICAgXG4gICAgICAgIEBvbkJhdGNoRGlzYXBwZWFyID0gKGUpID0+IFxuICAgICAgICAgICAgQGRyYXdJbW1lZGlhdGVseSA9IG5vXG4gICAgICAgICAgICBAaXNXYWl0aW5nID0gbm9cbiAgICAgICAgICAgIEBvYmplY3Qub3BhY2l0eSA9IDI1NVxuICAgICAgICAgICAgQGV4ZWN1dGVCYXRjaCgpXG4gICAgICAgICAgICBcbiAgICAjIyMqXG4gICAgKiBTZXJpYWxpemVzIHRoZSBtZXNzYWdlIHRleHQtcmVuZGVyZXIgaW50byBhIGRhdGEtYnVuZGxlLlxuICAgICogQG1ldGhvZCB0b0RhdGFCdW5kbGVcbiAgICAqIEByZXR1cm4ge09iamVjdH0gQSBkYXRhLWJ1bmRsZS5cbiAgICAjIyNcbiAgICB0b0RhdGFCdW5kbGU6IC0+XG4gICAgICAgIGlnbm9yZSA9IFtcIm9iamVjdFwiLCBcImZvbnRcIiwgXCJzcHJpdGVzXCIsIFwiYWxsU3ByaXRlc1wiLCBcImN1cnJlbnRTcHJpdGVcIiwgXCJjdXJyZW50WFwiXVxuICAgICAgICBidW5kbGUgPSB7IGN1cnJlbnRTcHJpdGVJbmRleDogQHNwcml0ZXMuaW5kZXhPZihAY3VycmVudFNwcml0ZSkgfVxuICAgICAgICBcbiAgICAgICAgZm9yIGsgb2YgdGhpc1xuICAgICAgICAgICAgaWYgaWdub3JlLmluZGV4T2YoaykgPT0gLTFcbiAgICAgICAgICAgICAgICBidW5kbGVba10gPSB0aGlzW2tdXG4gICAgICAgICAgICAgICAgXG4gICAgICAgIHJldHVybiBidW5kbGVcbiAgICAgXG4gICAgXG4gICAgICAgICAgICBcbiAgICAjIyMqXG4gICAgKiBEaXNwb3NlcyB0aGUgbWVzc2FnZSB0ZXh0LXJlbmRlcmVyIGFuZCBhbGwgc3ByaXRlcyB1c2VkIHRvIGRpc3BsYXlcbiAgICAqIHRoZSBtZXNzYWdlLlxuICAgICogQG1ldGhvZCBkaXNwb3NlXG4gICAgIyMjXG4gICAgZGlzcG9zZTogLT5cbiAgICAgICAgc3VwZXJcbiAgICAgICAgXG4gICAgICAgIGdzLkdsb2JhbEV2ZW50TWFuYWdlci5vZmZCeU93bmVyKFwibW91c2VVcFwiLCBAb2JqZWN0KVxuICAgICAgICBncy5HbG9iYWxFdmVudE1hbmFnZXIub2ZmQnlPd25lcihcImtleVVwXCIsIEBvYmplY3QpXG4gICAgICAgIFxuICAgICAgICBmb3Igc3ByaXRlIGluIEBhbGxTcHJpdGVzXG4gICAgICAgICAgICBzcHJpdGUuYml0bWFwPy5kaXNwb3NlKClcbiAgICAgICAgICAgIHNwcml0ZS5kaXNwb3NlKClcbiAgICBcbiAgICAjIyMqXG4gICAgKiBBZGRzIGV2ZW50LWhhbmRsZXJzIGZvciBtb3VzZS90b3VjaCBldmVudHNcbiAgICAqXG4gICAgKiBAbWV0aG9kIHNldHVwRXZlbnRIYW5kbGVyc1xuICAgICMjIyBcbiAgICBzZXR1cEV2ZW50SGFuZGxlcnM6IC0+XG4gICAgICAgIGdzLkdsb2JhbEV2ZW50TWFuYWdlci5vZmZCeU93bmVyKFwibW91c2VVcFwiLCBAb2JqZWN0KVxuICAgICAgICBncy5HbG9iYWxFdmVudE1hbmFnZXIub2ZmQnlPd25lcihcImtleVVwXCIsIEBvYmplY3QpXG4gICAgICAgIFxuICAgICAgICBncy5HbG9iYWxFdmVudE1hbmFnZXIub24gXCJtb3VzZVVwXCIsICgoZSkgPT5cbiAgICAgICAgICAgIHJldHVybiBpZiAoR2FtZU1hbmFnZXIuc2V0dGluZ3MuYXV0b01lc3NhZ2UuZW5hYmxlZCBhbmQgIUdhbWVNYW5hZ2VyLnNldHRpbmdzLmF1dG9NZXNzYWdlLnN0b3BPbkFjdGlvbilcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICNpZiBAb2JqZWN0LmRzdFJlY3QuY29udGFpbnMoSW5wdXQuTW91c2UueCAtIEBvYmplY3Qub3JpZ2luLngsIElucHV0Lk1vdXNlLnkgLSBAb2JqZWN0Lm9yaWdpbi55KVxuICAgICAgICAgICAgaWYgQGlzV2FpdGluZyBhbmQgbm90IChAd2FpdENvdW50ZXIgPiAwIG9yIEB3YWl0Rm9yS2V5KVxuICAgICAgICAgICAgICAgIGUuYnJlYWtDaGFpbiA9IHllc1xuICAgICAgICAgICAgICAgIEBjb250aW51ZSgpXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgZS5icmVha0NoYWluID0gQGlzUnVubmluZ1xuICAgICAgICAgICAgICAgIEBkcmF3SW1tZWRpYXRlbHkgPSAhQHdhaXRGb3JLZXlcbiAgICAgICAgICAgICAgICBAd2FpdENvdW50ZXIgPSAwXG4gICAgICAgICAgICAgICAgQHdhaXRGb3JLZXkgPSBub1xuICAgICAgICAgICAgICAgIEBpc1dhaXRpbmcgPSBub1xuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYgQHdhaXRGb3JLZXlcbiAgICAgICAgICAgICAgICBpZiBJbnB1dC5Nb3VzZS5idXR0b25zW0lucHV0Lk1vdXNlLkxFRlRdID09IDJcbiAgICAgICAgICAgICAgICAgICAgZS5icmVha0NoYWluID0geWVzXG4gICAgICAgICAgICAgICAgICAgIElucHV0LmNsZWFyKClcbiAgICAgICAgICAgICAgICAgICAgQHdhaXRGb3JLZXkgPSBub1xuICAgICAgICAgICAgICAgICAgICBAaXNXYWl0aW5nID0gbm9cbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICksIG51bGwsIEBvYmplY3RcbiAgICAgICAgXG4gICAgICAgIGdzLkdsb2JhbEV2ZW50TWFuYWdlci5vbiBcImtleVVwXCIsICgoZSkgPT5cbiAgICAgICAgICAgIGlmIElucHV0LmtleXNbSW5wdXQuQ10gYW5kICghQGlzV2FpdGluZyBvciAoQHdhaXRDb3VudGVyID4gMCBvciBAd2FpdEZvcktleSkpXG4gICAgICAgICAgICAgICAgQGRyYXdJbW1lZGlhdGVseSA9ICFAd2FpdEZvcktleVxuICAgICAgICAgICAgICAgIEB3YWl0Q291bnRlciA9IDBcbiAgICAgICAgICAgICAgICBAd2FpdEZvcktleSA9IG5vXG4gICAgICAgICAgICAgICAgQGlzV2FpdGluZyA9IG5vXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiBAaXNXYWl0aW5nIGFuZCAhQHdhaXRGb3JLZXkgYW5kICFAd2FpdENvdW50ZXIgYW5kIElucHV0LmtleXNbSW5wdXQuQ11cbiAgICAgICAgICAgICAgICBAY29udGludWUoKVxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYgQHdhaXRGb3JLZXlcbiAgICAgICAgICAgICAgICBpZiBJbnB1dC5rZXlzW0lucHV0LkNdXG4gICAgICAgICAgICAgICAgICAgIElucHV0LmNsZWFyKClcbiAgICAgICAgICAgICAgICAgICAgQHdhaXRGb3JLZXkgPSBub1xuICAgICAgICAgICAgICAgICAgICBAaXNXYWl0aW5nID0gbm9cbiAgICAgICAgICAgICAgICBcbiAgICAgICAgKSwgbnVsbCwgQG9iamVjdFxuICAgICAgICBcbiAgICAjIyMqXG4gICAgKiBTZXRzIHVwIHRoZSByZW5kZXJlci4gUmVnaXN0ZXJzIG5lY2Vzc2FyeSBldmVudCBoYW5kbGVycy5cbiAgICAqIEBtZXRob2Qgc2V0dXBcbiAgICAjIyMgXG4gICAgc2V0dXA6IC0+XG4gICAgICAgIEBzZXR1cEV2ZW50SGFuZGxlcnMoKVxuICAgICAgICBcbiAgICAjIyMqXG4gICAgKiBSZXN0b3JlcyB0aGUgbWVzc2FnZSB0ZXh0LXJlbmRlcmVyJ3Mgc3RhdGUgZnJvbSBhIGRhdGEtYnVuZGxlLlxuICAgICogQG1ldGhvZCByZXN0b3JlXG4gICAgKiBAcGFyYW0ge09iamVjdH0gYnVuZGxlIC0gQSBkYXRhLWJ1bmRsZSBjb250YWluaW5nIG1lc3NhZ2UgdGV4dC1yZW5kZXJlciBzdGF0ZS5cbiAgICAjIyNcbiAgICByZXN0b3JlOiAoYnVuZGxlKSAtPlxuICAgICAgICBmb3IgayBvZiBidW5kbGVcbiAgICAgICAgICAgIGlmIGsgPT0gXCJjdXJyZW50U3ByaXRlSW5kZXhcIlxuICAgICAgICAgICAgICAgIEBjdXJyZW50U3ByaXRlID0gQHNwcml0ZXNbYnVuZGxlLmN1cnJlbnRTcHJpdGVJbmRleF1cbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0aGlzW2tdID0gYnVuZGxlW2tdXG4gICAgICAgIFxuICAgICAgICBpZiBAc3ByaXRlcy5sZW5ndGggPiAwXG4gICAgICAgICAgICBAY3VycmVudFkgPSBAc3ByaXRlcy5sYXN0KCkueSAtIEBvYmplY3Qub3JpZ2luLnkgLSBAb2JqZWN0LmRzdFJlY3QueVxuICAgICAgICAgICAgQGxpbmUgPSBAbWF4TGluZXNcbiAgICAgICAgICAgIEBpc1dhaXRpbmcgPSBAaXNXYWl0aW5nIHx8IEBpc1J1bm5pbmdcbiAgICAgICAgICAgIFxuICAgICAgICByZXR1cm4gbnVsbCAgICBcbiAgICBcbiAgICBcbiAgICAjIyMqXG4gICAgKiBDb250aW51ZXMgbWVzc2FnZS1wcm9jZXNzaW5nIGlmIGN1cnJlbnRseSB3YWl0aW5nLlxuICAgICogQG1ldGhvZCBjb250aW51ZVxuICAgICMjI1xuICAgIGNvbnRpbnVlOiAtPiBcbiAgICAgICAgI0lucHV0LmNsZWFyKClcbiAgICAgICAgQGlzV2FpdGluZyA9IG5vXG4gICBcbiAgICAgICAgaWYgQGxpbmUgPj0gQGxpbmVzLmxlbmd0aFxuICAgICAgICAgICAgQGlzUnVubmluZyA9IG5vXG4gICAgICAgICAgICBAb2JqZWN0LmV2ZW50cz8uZW1pdChcIm1lc3NhZ2VGaW5pc2hcIiwgdGhpcylcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgQG9iamVjdC5ldmVudHM/LmVtaXQoXCJtZXNzYWdlQmF0Y2hcIiwgdGhpcylcbiAgICAgICAgICAgIGZhZGluZyA9IEdhbWVNYW5hZ2VyLnRlbXBTZXR0aW5ncy5tZXNzYWdlRmFkaW5nXG4gICAgICAgICAgICBkdXJhdGlvbiA9IGlmIEdhbWVNYW5hZ2VyLnRlbXBTZXR0aW5ncy5za2lwIHRoZW4gMCBlbHNlIGZhZGluZy5kdXJhdGlvblxuICAgICAgICAgICAgQG9iamVjdC5hbmltYXRvci5kaXNhcHBlYXIoZmFkaW5nLmFuaW1hdGlvbiwgZmFkaW5nLmVhc2luZywgZHVyYXRpb24sIGdzLkNhbGxCYWNrKFwib25CYXRjaERpc2FwcGVhclwiLCB0aGlzKSlcbiAgICAgICAgICAgICNAZXhlY3V0ZUJhdGNoKClcbiAgICAgICAgICAgIFxuICAgICMjIypcbiAgICAqIFVwZGF0ZXMgdGhlIHRleHQtcmVuZGVyZXIuXG4gICAgKiBAbWV0aG9kIHVwZGF0ZVxuICAgICMjI1xuICAgIHVwZGF0ZTogLT5cbiAgICAgICAgZm9yIHNwcml0ZSBpbiBAYWxsU3ByaXRlc1xuICAgICAgICAgICAgc3ByaXRlLm9wYWNpdHkgPSBAb2JqZWN0Lm9wYWNpdHlcbiAgICAgICAgICAgIHNwcml0ZS52aXNpYmxlID0gQG9iamVjdC52aXNpYmxlXG4gICAgICAgICAgICBzcHJpdGUub3ggPSAtQG9iamVjdC5vZmZzZXQueFxuICAgICAgICAgICAgc3ByaXRlLm95ID0gLUBvYmplY3Qub2Zmc2V0LnlcbiAgICAgICAgICAgIHNwcml0ZS5tYXNrLnZhbHVlID0gQG9iamVjdC5tYXNrLnZhbHVlXG4gICAgICAgICAgICBzcHJpdGUubWFzay52YWd1ZSA9IEBvYmplY3QubWFzay52YWd1ZVxuICAgICAgICAgICAgc3ByaXRlLm1hc2suc291cmNlID0gQG9iamVjdC5tYXNrLnNvdXJjZVxuICAgICAgICAgICAgc3ByaXRlLm1hc2sudHlwZSA9IEBvYmplY3QubWFzay50eXBlXG4gICAgXG4gICAgICAgIGZvciBvYmplY3QgaW4gQGN1c3RvbU9iamVjdHNcbiAgICAgICAgICAgIG9iamVjdC5vcGFjaXR5ID0gQG9iamVjdC5vcGFjaXR5XG4gICAgICAgICAgICBvYmplY3QudmlzaWJsZSA9IEBvYmplY3QudmlzaWJsZVxuICAgICAgICAgICAgXG4gICAgICAgIGlmIG5vdCBAaXNSdW5uaW5nIGFuZCBAd2FpdENvdW50ZXIgPiAwXG4gICAgICAgICAgICBAd2FpdENvdW50ZXItLVxuICAgICAgICAgICAgaWYgQHdhaXRDb3VudGVyID09IDBcbiAgICAgICAgICAgICAgICBAY29udGludWUoKVxuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgICAgXG4gICAgICAgIGlmIEBvYmplY3QudmlzaWJsZSBhbmQgQGxpbmVzPy5sZW5ndGggPiAwXG4gICAgICAgICAgICBAdXBkYXRlTGluZVdyaXRpbmcoKVxuICAgICAgICAgICAgQHVwZGF0ZVdhaXRGb3JLZXkoKVxuICAgICAgICAgICAgQHVwZGF0ZVdhaXRDb3VudGVyKClcbiAgICAgICAgICAgIEB1cGRhdGVDYXJldFBvc2l0aW9uKClcbiAgICAgICAgXG4gICAgIFxuICAgICMjIypcbiAgICAqIEluZGljYXRlcyBpZiBpdHMgYSBiYXRjaGVkIG1lc3NhZ2VzLlxuICAgICpcbiAgICAqIEBtZXRob2QgaXNCYXRjaGVkXG4gICAgKiBAcmV0dXJuIElmIDxiPnRydWU8L2I+IGl0IGlzIGEgYmF0Y2hlZCBtZXNzYWdlLiBPdGhlcndpc2UgPGI+ZmFsc2U8L2I+LlxuICAgICMjI1xuICAgIGlzQmF0Y2hlZDogLT4gQGxpbmVzLmxlbmd0aCA+IEBtYXhMaW5lc1xuICAgIFxuICAgICMjIypcbiAgICAqIEluZGljYXRlcyBpZiB0aGUgYmF0Y2ggaXMgc3RpbGwgaW4gcHJvZ3Jlc3MgYW5kIG5vdCBkb25lLlxuICAgICpcbiAgICAqIEBtZXRob2QgaXNCYXRjaEluUHJvZ3Jlc3NcbiAgICAqIEByZXR1cm4gSWYgPGI+dHJ1ZTwvYj4gdGhlIGJhdGNoZWQgbWVzc2FnZSBpcyBzdGlsbCBub3QgZG9uZS4gT3RoZXJ3aXNlIDxiPmZhbHNlPC9iPlxuICAgICMjI1xuICAgIGlzQmF0Y2hJblByb2dyZXNzOiAtPiBAbGluZXMubGVuZ3RoIC0gQGxpbmUgPiBAbWF4TGluZXNcbiAgICBcbiAgICAjIyMqXG4gICAgKiBTdGFydHMgZGlzcGxheWluZyB0aGUgbmV4dCBwYWdlIG9mIHRleHQgaWYgYSBtZXNzYWdlIGlzIHRvbyBsb25nIHRvIGZpdFxuICAgICogaW50byBvbmUgbWVzc2FnZSBib3guXG4gICAgKlxuICAgICogQG1ldGhvZCBleGVjdXRlQmF0Y2hcbiAgICAjIyMgXG4gICAgZXhlY3V0ZUJhdGNoOiAtPlxuICAgICAgICBAY2xlYXJBbGxTcHJpdGVzKClcbiAgICAgICAgQGxpbmVzID0gQGxpbmVzLnNsaWNlKEBsaW5lKVxuICAgICAgICBAbGluZSA9IDBcbiAgICAgICAgQGN1cnJlbnRYID0gMFxuICAgICAgICBAY3VycmVudFkgPSAwICBcbiAgICAgICAgQGN1cnJlbnRMaW5lSGVpZ2h0ID0gMFxuICAgICAgICBAdG9rZW5JbmRleCA9IDBcbiAgICAgICAgQGNoYXJJbmRleCA9IDBcbiAgICAgICAgQHRva2VuID0gQGxpbmVzW0BsaW5lXS5jb250ZW50W0B0b2tlbkluZGV4XSB8fCBuZXcgZ3MuUmVuZGVyZXJUb2tlbihudWxsLCBcIlwiKTtcbiAgICAgICAgQG1heExpbmVzID0gQGNhbGN1bGF0ZU1heExpbmVzKEBsaW5lcylcbiAgICAgICAgQGxpbmVBbmltYXRpb25Db3VudCA9IEBzcGVlZFxuICAgICAgICBAc3ByaXRlcyA9IEBjcmVhdGVTcHJpdGVzKEBsaW5lcylcbiAgICAgICAgQGFsbFNwcml0ZXMgPSBAYWxsU3ByaXRlcy5jb25jYXQoQHNwcml0ZXMpXG4gICAgICAgIEBjdXJyZW50U3ByaXRlID0gQHNwcml0ZXNbQGxpbmVdXG4gICAgICAgIEBjdXJyZW50U3ByaXRlLnggPSBAY3VycmVudFggKyBAb2JqZWN0Lm9yaWdpbi54ICsgQG9iamVjdC5kc3RSZWN0LnhcbiAgICAgICAgQGRyYXdOZXh0KClcbiAgICBcbiAgICAjIyMqXG4gICAgKiBDYWxjdWxhdGVzIHRoZSBkdXJhdGlvbihpbiBmcmFtZXMpIHRoZSBtZXNzYWdlLXJlbmRlcmVyIG5lZWRzIHRvIGRpc3BsYXlcbiAgICAqIHRoZSBtZXNzYWdlLlxuICAgICpcbiAgICAqIEBtZXRob2QgY2FsY3VsYXRlRHVyYXRpb25cbiAgICAqIEByZXR1cm4ge251bWJlcn0gVGhlIGR1cmF0aW9uIGluIGZyYW1lcy5cbiAgICAjIyMgICAgXG4gICAgY2FsY3VsYXRlRHVyYXRpb246IC0+XG4gICAgICAgIGR1cmF0aW9uID0gMFxuICAgICAgICBcbiAgICAgICAgaWYgQGxpbmVzP1xuICAgICAgICAgICAgZm9yIGxpbmUgaW4gQGxpbmVzXG4gICAgICAgICAgICAgICAgZm9yIHRva2VuIGluIGxpbmUuY29udGVudFxuICAgICAgICAgICAgICAgICAgICBpZiB0b2tlbj9cbiAgICAgICAgICAgICAgICAgICAgICAgIGR1cmF0aW9uICs9IEBjYWxjdWxhdGVEdXJhdGlvbkZvclRva2VuKHRva2VuKVxuICAgICAgICByZXR1cm4gZHVyYXRpb25cbiAgICBcbiAgICAjIyMqXG4gICAgKiBDYWxjdWxhdGVzIHRoZSBkdXJhdGlvbihpbiBmcmFtZXMpIHRoZSBtZXNzYWdlLXJlbmRlcmVyIG5lZWRzIHRvIGRpc3BsYXlcbiAgICAqIHRoZSBzcGVjaWZpZWQgbGluZS5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGNhbGN1bGF0ZUR1cmF0aW9uRm9yTGluZVxuICAgICogQHBhcmFtIHtncy5SZW5kZXJlclRleHRMaW5lfSBsaW5lIFRoZSBsaW5lIHRvIGNhbGN1bGF0ZSB0aGUgZHVyYXRpb24gZm9yLlxuICAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgZHVyYXRpb24gaW4gZnJhbWVzLlxuICAgICMjIyAgICAgIFxuICAgIGNhbGN1bGF0ZUR1cmF0aW9uRm9yTGluZTogKGxpbmUpIC0+XG4gICAgICAgIGR1cmF0aW9uID0gMFxuICAgICAgICBcbiAgICAgICAgaWYgbGluZVxuICAgICAgICAgICAgZm9yIHRva2VuIGluIGxpbmUuY29udGVudFxuICAgICAgICAgICAgICAgIGlmIHRva2VuP1xuICAgICAgICAgICAgICAgICAgICBkdXJhdGlvbiArPSBAY2FsY3VsYXRlRHVyYXRpb25Gb3JUb2tlbih0b2tlbilcbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICByZXR1cm4gZHVyYXRpb25cbiAgICAgXG4gICAgIyMjKlxuICAgICogQ2FsY3VsYXRlcyB0aGUgZHVyYXRpb24oaW4gZnJhbWVzKSB0aGUgbWVzc2FnZS1yZW5kZXJlciBuZWVkcyB0byBwcm9jZXNzXG4gICAgKiB0aGUgc3BlY2lmaWVkIHRva2VuLlxuICAgICpcbiAgICAqIEBtZXRob2QgY2FsY3VsYXRlRHVyYXRpb25Gb3JUb2tlblxuICAgICogQHBhcmFtIHtzdHJpbmd8T2JqZWN0fSB0b2tlbiAtIFRoZSB0b2tlbi5cbiAgICAqIEByZXR1cm4ge251bWJlcn0gVGhlIGR1cmF0aW9uIGluIGZyYW1lcy5cbiAgICAjIyMgICAgICAgICAgICAgICAgICAgIFxuICAgIGNhbGN1bGF0ZUR1cmF0aW9uRm9yVG9rZW46ICh0b2tlbikgLT5cbiAgICAgICAgZHVyYXRpb24gPSAwXG4gICAgICAgIFxuICAgICAgICBpZiB0b2tlbi5jb2RlP1xuICAgICAgICAgICAgc3dpdGNoIHRva2VuLmNvZGVcbiAgICAgICAgICAgICAgICB3aGVuIFwiV1wiXG4gICAgICAgICAgICAgICAgICAgIGlmIHRva2VuLnZhbHVlICE9IFwiQVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBkdXJhdGlvbiA9IHRva2VuLnZhbHVlIC8gMTAwMCAqIEdyYXBoaWNzLmZyYW1lUmF0ZVxuICAgICAgICBlbHNlXG4gICAgICAgICAgICBkdXJhdGlvbiA9IHRva2VuLnZhbHVlLmxlbmd0aCAqIEBzcGVlZFxuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgcmV0dXJuIGR1cmF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAjIyMqXG4gICAgKiBDYWxjdWxhdGVzIHRoZSBtYXhpbXVtIG9mIGxpbmVzIHdoaWNoIGNhbiBiZSBkaXNwbGF5ZWQgaW4gb25lIG1lc3NhZ2UuXG4gICAgKlxuICAgICogQG1ldGhvZCBjYWxjdWxhdGVNYXhMaW5lc1xuICAgICogQHBhcmFtIHtBcnJheX0gbGluZXMgLSBBbiBhcnJheSBvZiBsaW5lLW9iamVjdHMuXG4gICAgKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgZGlzcGxheWFibGUgbGluZXMuXG4gICAgIyMjXG4gICAgY2FsY3VsYXRlTWF4TGluZXM6IChsaW5lcykgLT5cbiAgICAgICAgaGVpZ2h0ID0gMFxuICAgICAgICByZXN1bHQgPSAwXG4gICAgICAgIFxuICAgICAgICBmb3IgbGluZSBpbiBsaW5lc1xuICAgICAgICAgICAgICAgIGhlaWdodCArPSBsaW5lLmhlaWdodCArIEBsaW5lU3BhY2luZ1xuICAgICAgICAgICAgICAgIGlmIEBjdXJyZW50WStoZWlnaHQgPiAoQG9iamVjdC5kc3RSZWN0LmhlaWdodClcbiAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICByZXN1bHQrK1xuICAgICBcbiAgICAgICAgcmV0dXJuIE1hdGgubWluKGxpbmVzLmxlbmd0aCwgcmVzdWx0IHx8IDEpXG4gICAgXG4gICAgIyMjKlxuICAgICogRGlzcGxheXMgdGhlIGNoYXJhY3RlciBvciBwcm9jZXNzZXMgdGhlIG5leHQgY29udHJvbC10b2tlbi5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGRyYXdOZXh0XG4gICAgIyMjXG4gICAgZHJhd05leHQ6IC0+XG4gICAgICAgIHRva2VuID0gQHByb2Nlc3NUb2tlbigpXG4gICAgICAgICAgICBcbiAgICAgICAgaWYgdG9rZW4/LnZhbHVlLmxlbmd0aCA+IDBcbiAgICAgICAgICAgIEBjaGFyID0gQHRva2VuLnZhbHVlLmNoYXJBdChAY2hhckluZGV4KVxuICAgICAgICAgICAgXG4gICAgICAgICAgICBzaXplID0gQGZvbnQubWVhc3VyZVRleHRQbGFpbihAY2hhcikgIFxuICAgICAgICAgICAgcyA9IEdyYXBoaWNzLnNjYWxlICAgXG4gICAgICAgICAgICBsaW5lU3BhY2luZyA9IEBsaW5lU3BhY2luZ1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiBAY3VycmVudExpbmUgIT0gQGxpbmVcbiAgICAgICAgICAgICAgICBAY3VycmVudExpbmUgPSBAbGluZVxuICAgICAgICAgICAgICAgIyBAY3VycmVudFkgKz0gQGN1cnJlbnRMaW5lSGVpZ2h0ICsgbGluZVNwYWNpbmcgKiBHcmFwaGljcy5zY2FsZVxuICAgICAgICAgICAgICAgIEBjdXJyZW50TGluZUhlaWdodCA9IDBcblxuICAgICAgICAgICAgQGN1cnJlbnRTcHJpdGUueSA9IEBvYmplY3Qub3JpZ2luLnkgKyBAb2JqZWN0LmRzdFJlY3QueSArIEBjdXJyZW50WVxuICAgICAgICAgICAgQGN1cnJlbnRTcHJpdGUudmlzaWJsZSA9IHllc1xuICAgICAgICAgICAgQGRyYXdMaW5lQ29udGVudChAbGluZXNbQGxpbmVdLCBAY3VycmVudFNwcml0ZS5iaXRtYXAsIEBjaGFySW5kZXgrMSlcbiAgICAgICAgICAgIEBjdXJyZW50U3ByaXRlLnNyY1JlY3Qud2lkdGggPSBAY3VycmVudFNwcml0ZS5iaXRtYXAud2lkdGggI01hdGgubWluKEBjdXJyZW50U3ByaXRlLnNyY1JlY3Qud2lkdGggKyBzaXplLndpZHRoLCBAY3VycmVudFNwcml0ZS5iaXRtYXAud2lkdGgpXG4gICAgICAgIFxuICAgICAgICAgICAgQGN1cnJlbnRMaW5lSGVpZ2h0ID0gQGxpbmVzW0BsaW5lXS5oZWlnaHRcbiAgICAgICAgICAgIEBjdXJyZW50WCA9IE1hdGgubWluKEBsaW5lc1tAbGluZV0ud2lkdGgsIEBjdXJyZW50WCArIHNpemUud2lkdGgpXG4gICAgICAgICAgICBcbiAgICAjIyMqXG4gICAgKiBQcm9jZXNzZXMgdGhlIG5leHQgY2hhcmFjdGVyL3Rva2VuIG9mIHRoZSBtZXNzYWdlLlxuICAgICogQG1ldGhvZCBuZXh0Q2hhclxuICAgICogQHByaXZhdGVcbiAgICAjIyNcbiAgICBuZXh0Q2hhcjogLT5cbiAgICAgICAgbG9vcFxuICAgICAgICAgICAgQGNoYXJJbmRleCsrXG4gICAgICAgICAgICBAbGluZUFuaW1hdGlvbkNvdW50ID0gQHNwZWVkXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmIEB0b2tlbi5jb2RlPyBvciBAY2hhckluZGV4ID49IEB0b2tlbi52YWx1ZS5sZW5ndGhcbiAgICAgICAgICAgICAgICBAdG9rZW4ub25FbmQ/KClcbiAgICAgICAgICAgICAgICBAdG9rZW5JbmRleCsrXG4gICAgICAgICAgICAgICAgaWYgQHRva2VuSW5kZXggPj0gQGxpbmVzW0BsaW5lXS5jb250ZW50Lmxlbmd0aFxuICAgICAgICAgICAgICAgICAgICBAdG9rZW5JbmRleCA9IDBcbiAgICAgICAgICAgICAgICAgICAgQGxpbmUrK1xuICAgICAgICAgICAgICAgICAgICBAY3VycmVudFNwcml0ZS5zcmNSZWN0LndpZHRoID0gQGN1cnJlbnRTcHJpdGUuYml0bWFwLndpZHRoXG4gICAgICAgICAgICAgICAgICAgIEBjdXJyZW50U3ByaXRlID0gQHNwcml0ZXNbQGxpbmVdXG4gICAgICAgICAgICAgICAgICAgIGlmIEBjdXJyZW50U3ByaXRlP1xuICAgICAgICAgICAgICAgICAgICAgICAgQGN1cnJlbnRTcHJpdGUueCA9IEBvYmplY3Qub3JpZ2luLnggKyBAb2JqZWN0LmRzdFJlY3QueFxuICAgICAgICAgICAgICAgICAgICBpZiBAbGluZSA8IEBtYXhMaW5lc1xuICAgICAgICAgICAgICAgICAgICAgICAgQGN1cnJlbnRZICs9IChAY3VycmVudExpbmVIZWlnaHQgfHwgQGZvbnQubGluZUhlaWdodCkgKyBAbGluZVNwYWNpbmcgKiBHcmFwaGljcy5zY2FsZVxuICAgICAgICAgICAgICAgICAgICAgICAgQGNoYXJJbmRleCA9IDBcbiAgICAgICAgICAgICAgICAgICAgICAgIEBjdXJyZW50WCA9IDBcbiAgICAgICAgICAgICAgICAgICAgICAgIEB0b2tlbiA9IEBsaW5lc1tAbGluZV0uY29udGVudFtAdG9rZW5JbmRleF0gfHwgbmV3IGdzLlJlbmRlcmVyVG9rZW4obnVsbCwgXCJcIilcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIEBjaGFySW5kZXggPSAwXG4gICAgICAgICAgICAgICAgICAgIEB0b2tlbiA9IEBsaW5lc1tAbGluZV0uY29udGVudFtAdG9rZW5JbmRleF0gfHwgbmV3IGdzLlJlbmRlcmVyVG9rZW4obnVsbCwgXCJcIilcbiAgICAgICAgICAgICAgICBAdG9rZW4ub25TdGFydD8oKVxuXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmICFAdG9rZW4gb3IgQHRva2VuLnZhbHVlICE9IFwiXFxuXCIgb3IgIUBsaW5lc1tAbGluZV1cbiAgICAgICAgICAgICAgICBicmVha1xuICAgICMjIypcbiAgICAqIEZpbmlzaGVzIHRoZSBtZXNzYWdlLiBEZXBlbmRpbmcgb24gdGhlIG1lc3NhZ2UgY29uZmlndXJhdGlvbiwgdGhlXG4gICAgKiBtZXNzYWdlIHRleHQtcmVuZGVyZXIgd2lsbCBub3cgd2FpdCBmb3IgYSB1c2VyLWFjdGlvbiBvciBhIGNlcnRhaW4gYW1vdW50XG4gICAgKiBvZiB0aW1lLlxuICAgICpcbiAgICAqIEBtZXRob2QgZmluaXNoXG4gICAgIyMjXG4gICAgZmluaXNoOiAtPlxuICAgICAgICBpZiBAd2FpdEF0RW5kXG4gICAgICAgICAgICBAaXNXYWl0aW5nID0geWVzXG4gICAgICAgICAgICBAb2JqZWN0LmV2ZW50cz8uZW1pdChcIm1lc3NhZ2VXYWl0aW5nXCIsIHRoaXMpXG4gICAgICAgIGVsc2UgaWYgQHdhaXRBdEVuZFRpbWUgPiAwXG4gICAgICAgICAgICBAd2FpdENvdW50ZXIgPSBAd2FpdEF0RW5kVGltZVxuICAgICAgICAgICAgQGlzV2FpdGluZyA9IG5vXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIEBvYmplY3QuZXZlbnRzPy5lbWl0KFwibWVzc2FnZVdhaXRpbmdcIiwgdGhpcylcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgQG9iamVjdC5ldmVudHM/LmVtaXQoXCJtZXNzYWdlV2FpdGluZ1wiLCB0aGlzKVxuICAgICAgICAgICAgQGNvbnRpbnVlKClcbiAgICBcbiAgICAjIyMqXG4gICAgKiBSZXR1cm5zIHRoZSBwb3NpdGlvbiBvZiB0aGUgY2FyZXQgaW4gcGl4ZWxzLiBUaGUgY2FyZXQgaXMgbGlrZSBhbiBpbnZpc2libGVcbiAgICAqIGN1cnNvciBwb2ludGluZyB0byB0aGUgeC95IGNvb3JkaW5hdGVzIG9mIHRoZSBsYXN0IHJlbmRlcmVkIGNoYXJhY3RlciBvZlxuICAgICogdGhlIG1lc3NhZ2UuIFRoYXQgcG9zaXRpb24gY2FuIGJlIHVzZWQgdG8gZGlzcGxheSBhIHdhaXRpbmctIG9yIHByb2Nlc3NpbmctYW5pbWF0aW9uIGZvciBleGFtcGxlLlxuICAgICpcbiAgICAqIEBtZXRob2QgdXBkYXRlQ2FyZXRQb3NpdGlvblxuICAgICMjI1xuICAgIHVwZGF0ZUNhcmV0UG9zaXRpb246IC0+IFxuICAgICAgICBAY2FyZXRQb3NpdGlvbi54ID0gQGN1cnJlbnRYICsgQHBhZGRpbmcgICBcbiAgICAgICAgQGNhcmV0UG9zaXRpb24ueSA9IEBjdXJyZW50WSArIEBjdXJyZW50TGluZUhlaWdodC8yXG4gICAgICAgIFxuICAgICMjIypcbiAgICAqIFVwZGF0ZXMgdGhlIGxpbmUgd3JpdGluZy5cbiAgICAqXG4gICAgKiBAbWV0aG9kIHVwZGF0ZUxpbmVXcml0aW5nXG4gICAgKiBAcHJpdmF0ZVxuICAgICMjI1xuICAgIHVwZGF0ZUxpbmVXcml0aW5nOiAtPlxuICAgICAgICBpZiBAaXNSdW5uaW5nIGFuZCAhQGlzV2FpdGluZyBhbmQgIUB3YWl0Rm9yS2V5IGFuZCBAd2FpdENvdW50ZXIgPD0gMFxuICAgICAgICAgICAgaWYgQGxpbmVBbmltYXRpb25Db3VudCA8PSAwXG4gICAgICAgICAgICAgICAgbG9vcFxuICAgICAgICAgICAgICAgICAgICBpZiBAbGluZSA8IEBtYXhMaW5lc1xuICAgICAgICAgICAgICAgICAgICAgICAgQG5leHRDaGFyKClcbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBpZiBAbGluZSA+PSBAbWF4TGluZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIEBmaW5pc2goKVxuICAgICAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBAZHJhd05leHQoKVxuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrIHVubGVzcyAoQHRva2VuLmNvZGUgb3IgQGxpbmVBbmltYXRpb25Db3VudCA8PSAwIG9yIEBkcmF3SW1tZWRpYXRlbHkpIGFuZCAhQHdhaXRGb3JLZXkgYW5kIEB3YWl0Q291bnRlciA8PSAwIGFuZCBAaXNSdW5uaW5nIGFuZCBAbGluZSA8IEBtYXhMaW5lc1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiBHYW1lTWFuYWdlci50ZW1wU2V0dGluZ3Muc2tpcFxuICAgICAgICAgICAgICAgIEBsaW5lQW5pbWF0aW9uQ291bnQgPSAwXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgQGxpbmVBbmltYXRpb25Db3VudC0tXG4gICAgXG4gICAgIyMjKlxuICAgICogVXBkYXRlcyB3YWl0LWZvci1rZXkgc3RhdGUuIElmIHNraXBwaW5nIGlzIGVuYWJsZWQsIHRoZSB0ZXh0IHJlbmRlcmVyIHdpbGxcbiAgICAqIG5vdCB3YWl0IGZvciBrZXkgcHJlc3MuXG4gICAgKlxuICAgICogQG1ldGhvZCB1cGRhdGVXYWl0Rm9yS2V5XG4gICAgKiBAcHJpdmF0ZVxuICAgICMjI1xuICAgIHVwZGF0ZVdhaXRGb3JLZXk6IC0+XG4gICAgICAgIGlmIEB3YWl0Rm9yS2V5XG4gICAgICAgICAgICBAaXNXYWl0aW5nID0gIUdhbWVNYW5hZ2VyLnRlbXBTZXR0aW5ncy5za2lwXG4gICAgICAgICAgICBAd2FpdEZvcktleSA9IEBpc1dhaXRpbmdcbiAgICAgXG4gICAgIyMjKlxuICAgICogVXBkYXRlcyB3YWl0IGNvdW50ZXIgaWYgdGhlIHRleHQgcmVuZGVyZXIgaXMgd2FpdGluZyBmb3IgYSBjZXJ0YWluIGFtb3VudCBvZiB0aW1lIHRvIHBhc3MuIElmIHNraXBwaW5nIGlzIGVuYWJsZWQsIHRoZSB0ZXh0IHJlbmRlcmVyIHdpbGxcbiAgICAqIG5vdCB3YWl0IGZvciB0aGUgYWN0dWFsIGFtb3VudCBvZiB0aW1lIGFuZCBzZXRzIHRoZSB3YWl0LWNvdW50ZXIgdG8gMSBmcmFtZSBpbnN0ZWFkLlxuICAgICpcbiAgICAqIEBtZXRob2QgdXBkYXRlV2FpdEZvcktleVxuICAgICogQHByaXZhdGVcbiAgICAjIyMgICAgICAgXG4gICAgdXBkYXRlV2FpdENvdW50ZXI6IC0+XG4gICAgICAgIGlmIEB3YWl0Q291bnRlciA+IDBcbiAgICAgICAgICAgIGlmIEdhbWVNYW5hZ2VyLnRlbXBTZXR0aW5ncy5za2lwXG4gICAgICAgICAgICAgICAgQHdhaXRDb3VudGVyID0gMVxuICAgICAgICAgICAgQGlzV2FpdGluZyA9IHllc1xuICAgICAgICAgICAgQHdhaXRDb3VudGVyLS1cbiAgICAgICAgICAgIGlmIEB3YWl0Q291bnRlciA8PSAwXG4gICAgICAgICAgICAgICAgQGlzV2FpdGluZyA9IG5vXG4gICAgICAgICAgICAgICAgQGNvbnRpbnVlKCkgaWYgQGxpbmUgPj0gQG1heExpbmVzXG4gICAgICAgICAgICAgICAgXG4gICAgIyMjKlxuICAgICogQ3JlYXRlcyBhIHRva2VuLW9iamVjdCBmb3IgYSBzcGVjaWZpZWQgdGV4dC1jb2RlLlxuICAgICogXG4gICAgKiBAbWV0aG9kIGNyZWF0ZVRva2VuXG4gICAgKiBAcGFyYW0ge3N0cmluZ30gY29kZSAtIFRoZSBjb2RlL3R5cGUgb2YgdGhlIHRleHQtY29kZS5cbiAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgdGV4dC1jb2RlLlxuICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgdG9rZW4tb2JqZWN0LlxuICAgICMjI1xuICAgIGNyZWF0ZVRva2VuOiAoY29kZSwgdmFsdWUpIC0+XG4gICAgICAgIHRva2VuT2JqZWN0ID0gbnVsbFxuICAgICAgICBcbiAgICAgICAgc3dpdGNoIGNvZGVcbiAgICAgICAgICAgIHdoZW4gXCJDRVwiXG4gICAgICAgICAgICAgICAgZGF0YSA9IHZhbHVlLnNwbGl0KFwiL1wiKVxuICAgICAgICAgICAgICAgIHZhbHVlID0gZGF0YS5zaGlmdCgpXG4gICAgICAgICAgICAgICAgdmFsdWUgPSBpZiBpc05hTih2YWx1ZSkgdGhlbiB2YWx1ZSBlbHNlIHBhcnNlSW50KHZhbHVlKVxuICAgICAgICAgICAgICAgIGZvciBpIGluIFswLi4uZGF0YV1cbiAgICAgICAgICAgICAgICAgICAgaWYgZGF0YVtpXS5zdGFydHNXaXRoKCdcIicpIGFuZCBkYXRhW2ldLmVuZHNXaXRoKCdcIicpXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhW2ldID0gZGF0YVtpXS5zdWJzdHJpbmcoMSwgZGF0YVtpXS5sZW5ndGgtMSlcbiAgICAgICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVtpXSA9IGlmIGlzTmFOKGRhdGFbaV0pIHRoZW4gZGF0YVtpXSBlbHNlIHBhcnNlRmxvYXQoZGF0YVtpXSlcbiAgICAgICAgICAgICAgICB0b2tlbk9iamVjdCA9IHsgY29kZTogY29kZSwgdmFsdWU6IHZhbHVlLCB2YWx1ZXM6IGRhdGEgIH1cbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0b2tlbk9iamVjdCA9IHN1cGVyKGNvZGUsIHZhbHVlKVxuICAgICAgIFxuICAgICAgICAgICAgICAgIFxuICAgICAgICByZXR1cm4gdG9rZW5PYmplY3QgXG4gICAgIyMjKlxuICAgICogPHA+TWVhc3VyZXMgYSBjb250cm9sLXRva2VuLiBJZiBhIHRva2VuIHByb2R1Y2VzIGEgdmlzdWFsIHJlc3VsdCBsaWtlIGRpc3BsYXlpbmcgYW4gaWNvbiB0aGVuIGl0IG11c3QgcmV0dXJuIHRoZSBzaXplIHRha2VuIGJ5XG4gICAgKiB0aGUgdmlzdWFsIHJlc3VsdC4gSWYgdGhlIHRva2VuIGhhcyBubyB2aXN1YWwgcmVzdWx0LCA8Yj5udWxsPC9iPiBtdXN0IGJlIHJldHVybmVkLiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgZm9yIGV2ZXJ5IHRva2VuIHdoZW4gdGhlIG1lc3NhZ2UgaXMgaW5pdGlhbGl6ZWQuPC9wPiBcbiAgICAqXG4gICAgKiA8cD5UaGlzIG1ldGhvZCBpcyBub3QgY2FsbGVkIHdoaWxlIHRoZSBtZXNzYWdlIGlzIHJ1bm5pbmcuIEZvciB0aGF0IGNhc2UsIHNlZSA8aT5wcm9jZXNzQ29udHJvbFRva2VuPC9pPiBtZXRob2Qgd2hpY2ggaXMgY2FsbGVkXG4gICAgKiBmb3IgZXZlcnkgdG9rZW4gd2hpbGUgdGhlIG1lc3NhZ2UgaXMgcnVubmluZy48L3A+XG4gICAgKlxuICAgICogQHBhcmFtIHtPYmplY3R9IHRva2VuIC0gQSBjb250cm9sLXRva2VuLlxuICAgICogQHJldHVybiB7Z3MuU2l6ZX0gVGhlIHNpemUgb2YgdGhlIGFyZWEgdGFrZW4gYnkgdGhlIHZpc3VhbCByZXN1bHQgb2YgdGhlIHRva2VuIG9yIDxiPm51bGw8L2I+IGlmIHRoZSB0b2tlbiBoYXMgbm8gdmlzdWFsIHJlc3VsdC5cbiAgICAqIEBtZXRob2QgYW5hbHl6ZUNvbnRyb2xUb2tlblxuICAgICogQHByb3RlY3RlZFxuICAgICMjI1xuICAgIG1lYXN1cmVDb250cm9sVG9rZW46ICh0b2tlbikgLT4gcmV0dXJuIHN1cGVyKHRva2VuKVxuICAgICAgICBcbiAgICAjIyMqXG4gICAgKiA8cD5EcmF3cyB0aGUgdmlzdWFsIHJlc3VsdCBvZiBhIHRva2VuLCBsaWtlIGFuIGljb24gZm9yIGV4YW1wbGUsIHRvIHRoZSBzcGVjaWZpZWQgYml0bWFwLiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgZm9yIGV2ZXJ5IHRva2VuIHdoZW4gdGhlIG1lc3NhZ2UgaXMgaW5pdGlhbGl6ZWQgYW5kIHRoZSBzcHJpdGVzIGZvciBlYWNoXG4gICAgKiB0ZXh0LWxpbmUgYXJlIGNyZWF0ZWQuPC9wPiBcbiAgICAqXG4gICAgKiA8cD5UaGlzIG1ldGhvZCBpcyBub3QgY2FsbGVkIHdoaWxlIHRoZSBtZXNzYWdlIGlzIHJ1bm5pbmcuIEZvciB0aGF0IGNhc2UsIHNlZSA8aT5wcm9jZXNzQ29udHJvbFRva2VuPC9pPiBtZXRob2Qgd2hpY2ggaXMgY2FsbGVkXG4gICAgKiBmb3IgZXZlcnkgdG9rZW4gd2hpbGUgdGhlIG1lc3NhZ2UgaXMgcnVubmluZy48L3A+XG4gICAgKlxuICAgICogQHBhcmFtIHtPYmplY3R9IHRva2VuIC0gQSBjb250cm9sLXRva2VuLlxuICAgICogQHBhcmFtIHtncy5CaXRtYXB9IGJpdG1hcCAtIFRoZSBiaXRtYXAgdXNlZCBmb3IgdGhlIGN1cnJlbnQgdGV4dC1saW5lLiBDYW4gYmUgdXNlZCB0byBkcmF3IHNvbWV0aGluZyBvbiBpdCBsaWtlIGFuIGljb24sIGV0Yy5cbiAgICAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgLSBBbiB4LW9mZnNldCBmb3IgdGhlIGRyYXctcm91dGluZS5cbiAgICAqIEBwYXJhbSB7bnVtYmVyfSBsZW5ndGggLSBEZXRlcm1pbmVzIGhvdyBtYW55IGNoYXJhY3RlcnMgb2YgdGhlIHRva2VuIHNob3VsZCBiZSBkcmF3bi4gQ2FuIGJlIGlnbm9yZWQgZm9yIHRva2Vuc1xuICAgICogbm90IGRyYXdpbmcgYW55IGNoYXJhY3RlcnMuXG4gICAgKiBAbWV0aG9kIGRyYXdDb250cm9sVG9rZW5cbiAgICAqIEBwcm90ZWN0ZWRcbiAgICAjIyNcbiAgICBkcmF3Q29udHJvbFRva2VuOiAodG9rZW4sIGJpdG1hcCwgb2Zmc2V0LCBsZW5ndGgpIC0+XG4gICAgICAgIHN3aXRjaCB0b2tlbi5jb2RlXG4gICAgICAgICAgICB3aGVuIFwiUlRcIiAjIFJ1YnkgVGV4dFxuICAgICAgICAgICAgICAgIHN1cGVyKHRva2VuLCBiaXRtYXAsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgICAgICAgICAgIFxuICAgICBcbiAgICAjIyMqXG4gICAgKiBQcm9jZXNzZXMgYSBjb250cm9sLXRva2VuLiBBIGNvbnRyb2wtdG9rZW4gaXMgYSB0b2tlbiB3aGljaCBpbmZsdWVuY2VzXG4gICAgKiB0aGUgdGV4dC1yZW5kZXJpbmcgbGlrZSBjaGFuZ2luZyB0aGUgZm9udHMgY29sb3IsIHNpemUgb3Igc3R5bGUuIENoYW5nZXMgXG4gICAgKiB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgYXBwbGllZCB0byB0aGUgZ2FtZSBvYmplY3QncyBmb250LlxuICAgICpcbiAgICAqIEZvciBtZXNzYWdlIHRleHQtcmVuZGVyZXIsIGEgZmV3IGFkZGl0aW9uYWwgY29udHJvbC10b2tlbnMgbGlrZVxuICAgICogc3BlZWQtY2hhbmdlLCB3YWl0aW5nLCBldGMuIG5lZWRzIHRvIGJlIHByb2Nlc3NlZCBoZXJlLlxuICAgICpcbiAgICAqIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBmb3IgZWFjaCB0b2tlbiB3aGlsZSB0aGUgbWVzc2FnZSBpcyBpbml0aWFsaXplZCBhbmRcbiAgICAqIGFsc28gd2hpbGUgdGhlIG1lc3NhZ2UgaXMgcnVubmluZy4gU2VlIDxpPmZvcm1hdHRpbmdPbmx5PC9pPiBwYXJhbWV0ZXIuXG4gICAgKlxuICAgICogQHBhcmFtIHtPYmplY3R9IHRva2VuIC0gQSBjb250cm9sLXRva2VuLlxuICAgICogQHBhcmFtIHtib29sZWFufSBmb3JtYXR0aW5nT25seSAtIElmIDxiPnRydWU8L2I+IHRoZSBtZXNzYWdlIGlzIGluaXRpYWxpemluZyByaWdodCBub3cgYW5kIG9ubHkgXG4gICAgKiBmb3JtYXQtdG9rZW5zIHNob3VsZCBiZSBwcm9jZXNzZWQgd2hpY2ggaXMgbmVjZXNzYXJ5IGZvciB0aGUgbWVzc2FnZSB0byBjYWxjdWxhdGVkIHNpemVzIGNvcnJlY3RseS5cbiAgICAqIEByZXR1cm4ge09iamVjdH0gQSBuZXcgdG9rZW4gd2hpY2ggaXMgcHJvY2Vzc2VkIG5leHQgb3IgPGI+bnVsbDwvYj4uXG4gICAgKiBAbWV0aG9kIHByb2Nlc3NDb250cm9sVG9rZW5cbiAgICAqIEBwcm90ZWN0ZWRcbiAgICAjIyNcbiAgICBwcm9jZXNzQ29udHJvbFRva2VuOiAodG9rZW4sIGZvcm1hdHRpbmdPbmx5KSAtPlxuICAgICAgICByZXR1cm4gc3VwZXIodG9rZW4pIGlmIGZvcm1hdHRpbmdPbmx5XG4gICAgICAgIHJlc3VsdCA9IG51bGxcbiAgICAgICAgXG4gICAgICAgIHN3aXRjaCB0b2tlbi5jb2RlXG4gICAgICAgICAgICB3aGVuIFwiQ1JcIiAjIENoYW5nZSBDdXJyZW50IENoYXJhY3RlclxuICAgICAgICAgICAgICAgIGNoYXJhY3RlciA9IFJlY29yZE1hbmFnZXIuY2hhcmFjdGVyc0FycmF5LmZpcnN0IChjKSAtPiAoYy5uYW1lLmRlZmF1bHRUZXh0ID8gYy5uYW1lKSA9PSB0b2tlbi52YWx1ZVxuICAgICAgICAgICAgICAgIGlmIGNoYXJhY3RlclxuICAgICAgICAgICAgICAgICAgICBTY2VuZU1hbmFnZXIuc2NlbmUuY3VycmVudENoYXJhY3RlciA9IGNoYXJhY3RlclxuICAgICAgICAgICAgd2hlbiBcIkNFXCIgIyBDYWxsIENvbW1vbiBFdmVudFxuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHsgXCJ2YWx1ZXNcIjogdG9rZW4udmFsdWVzIH1cbiAgICAgICAgICAgICAgICBAb2JqZWN0LmV2ZW50cz8uZW1pdChcImNhbGxDb21tb25FdmVudFwiLCBAb2JqZWN0LCB7IGNvbW1vbkV2ZW50SWQ6IHRva2VuLnZhbHVlLCBwYXJhbXM6IHBhcmFtcywgZmluaXNoOiBubywgd2FpdGluZzogeWVzIH0pXG4gICAgICAgICAgICB3aGVuIFwiWFwiICMgU2NyaXB0XG4gICAgICAgICAgICAgICAgdG9rZW4udmFsdWU/KEBvYmplY3QpXG4gICAgICAgICAgICB3aGVuIFwiQVwiICMgUGxheSBBbmltYXRpb25cbiAgICAgICAgICAgICAgICBhbmltYXRpb24gPSBSZWNvcmRNYW5hZ2VyLmFuaW1hdGlvbnNbTWF0aC5tYXgodG9rZW4udmFsdWUtMSwgMCldXG4gICAgICAgICAgICAgICAgaWYgYW5pbWF0aW9uPy5ncmFwaGljLm5hbWU/XG4gICAgICAgICAgICAgICAgICAgIGJpdG1hcCA9IFJlc291cmNlTWFuYWdlci5nZXRCaXRtYXAoXCJHcmFwaGljcy9QaWN0dXJlcy8je2FuaW1hdGlvbi5ncmFwaGljLm5hbWV9XCIpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdCA9IG5ldyBncy5PYmplY3RfQW5pbWF0aW9uKGFuaW1hdGlvbilcbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgIEBhZGRDdXN0b21PYmplY3Qob2JqZWN0KVxuICAgICAgICAgICAgICAgICAgICBAY3VycmVudFggKz0gTWF0aC5yb3VuZChiaXRtYXAud2lkdGggLyBhbmltYXRpb24uZnJhbWVzWClcbiAgICAgICAgICAgICAgICAgICAgQGN1cnJlbnRTcHJpdGUuc3JjUmVjdC53aWR0aCArPSBNYXRoLnJvdW5kKGJpdG1hcC53aWR0aCAvIGFuaW1hdGlvbi5mcmFtZXNYKVxuICAgICAgICAgICAgXG4gICAgICAgICAgICB3aGVuIFwiUlRcIiAjIFJ1YnkgVGV4dFxuICAgICAgICAgICAgICAgIGlmIHRva2VuLnJ0U2l6ZS53aWR0aCA+IHRva2VuLnJiU2l6ZS53aWR0aFxuICAgICAgICAgICAgICAgICAgICBAY3VycmVudFggKz0gdG9rZW4ucnRTaXplLndpZHRoXG4gICAgICAgICAgICAgICAgICAgIEBmb250LnNldChAZ2V0UnVieVRleHRGb250KHRva2VuKSlcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIEBjdXJyZW50WCArPSB0b2tlbi5yYlNpemUud2lkdGhcbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB3aGVuIFwiTEtcIiAjIExpbmsgICAgICBcbiAgICAgICAgICAgICAgICBpZiB0b2tlbi52YWx1ZSA9PSAnRScgIyBFbmQgTGlua1xuICAgICAgICAgICAgICAgICAgICBvYmplY3QgPSBuZXcgdWkuT2JqZWN0X0hvdHNwb3QoKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuZW5hYmxlZCA9IHllc1xuICAgICAgICAgICAgICAgICAgICBvYmplY3Quc2V0dXAoKVxuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgQGFkZEN1c3RvbU9iamVjdChvYmplY3QpXG4gICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuZHN0UmVjdC54ID0gQG9iamVjdC5kc3RSZWN0LnggKyBAb2JqZWN0Lm9yaWdpbi54ICsgQGN1c3RvbURhdGEubGlua0RhdGEuY3hcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmRzdFJlY3QueSA9IEBvYmplY3QuZHN0UmVjdC55ICsgQG9iamVjdC5vcmlnaW4ueSArIEBjdXN0b21EYXRhLmxpbmtEYXRhLmN5XG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5kc3RSZWN0LndpZHRoID0gQGN1cnJlbnRYIC0gQGN1c3RvbURhdGEubGlua0RhdGEuY3hcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmRzdFJlY3QuaGVpZ2h0ID0gQGN1cnJlbnRMaW5lSGVpZ2h0XG5cbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmV2ZW50cy5vbihcImNsaWNrXCIsIGdzLkNhbGxCYWNrKFwib25MaW5rQ2xpY2tcIiwgdGhpcyksIGxpbmtEYXRhOiBAY3VzdG9tRGF0YS5saW5rRGF0YSwgdGhpcylcbiAgICAgICAgICAgICAgICBlbHNlICMgQmVnaW4gTGlua1xuICAgICAgICAgICAgICAgICAgICBAY3VzdG9tRGF0YS5saW5rRGF0YSA9IHsgY3g6IEBjdXJyZW50WCwgY3k6IEBjdXJyZW50WSwgY29tbW9uRXZlbnRJZDogdG9rZW4udmFsdWUsIHRva2VuSW5kZXg6IEB0b2tlbkluZGV4IH1cbiAgICAgICAgICAgIHdoZW4gXCJTTEtcIiAjIFN0eWxlYWJsZSBMaW5rXG4gICAgICAgICAgICAgICAgaWYgdG9rZW4udmFsdWUgPT0gJ0UnICMgRW5kIExpbmtcbiAgICAgICAgICAgICAgICAgICAgQGN1cnJlbnRTcHJpdGUuYml0bWFwLmNsZWFyUmVjdChAY3VzdG9tRGF0YS5saW5rRGF0YS5jeCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAY3VzdG9tRGF0YS5saW5rRGF0YS5jeSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAY3VycmVudFggLSBAY3VzdG9tRGF0YS5saW5rRGF0YS5jeCArIEBvYmplY3QuZm9udC5ib3JkZXJTaXplKjIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQGN1cnJlbnRMaW5lSGVpZ2h0KVxuICAgICAgICAgICAgICAgICAgICBsaW5lID0gQGxpbmVzW0BsaW5lXS5jb250ZW50XG4gICAgICAgICAgICAgICAgICAgIGxpbmtTdGFydCA9IEBmaW5kVG9rZW4oQHRva2VuSW5kZXgtMSwgXCJTTEtcIiwgLTEsIGxpbmUpXG4gICAgICAgICAgICAgICAgICAgIHRleHRUb2tlbnMgPSBAZmluZFRva2Vuc0JldHdlZW4oQGN1c3RvbURhdGEubGlua0RhdGEudG9rZW5JbmRleCwgQHRva2VuSW5kZXgsIG51bGwsIGxpbmUpXG4gICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBvYmplY3QgPSBuZXcgdWkuT2JqZWN0X1RleHQoKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QudGV4dCA9IHRleHRUb2tlbnMuc2VsZWN0KCh4KSA9PiB4LnZhbHVlKS5qb2luKFwiXCIpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5zaXplVG9GaXQgPSB5ZXNcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmZvcm1hdHRpbmcgPSB5ZXNcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LndvcmRXcmFwID0gbm9cbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnVpID0gbmV3IHVpLkNvbXBvbmVudF9VSUJlaGF2aW9yKClcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmVuYWJsZWQgPSB5ZXNcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmFkZENvbXBvbmVudChvYmplY3QudWkpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5hZGRDb21wb25lbnQobmV3IGdzLkNvbXBvbmVudF9Ib3RzcG90QmVoYXZpb3IoKSlcbiAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBpZiBAY3VzdG9tRGF0YS5saW5rRGF0YS5zdHlsZUluZGV4ID09IC0xXG4gICAgICAgICAgICAgICAgICAgICAgICB1aS5VSU1hbmFnZXIuYWRkQ29udHJvbFN0eWxlcyhvYmplY3QsIFtcImh5cGVybGlua1wiXSlcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBcbiAgICAgICAgICAgICAgICAgICAgICAgIHVpLlVJTWFuYWdlci5hZGRDb250cm9sU3R5bGVzKG9iamVjdCwgW1wiaHlwZXJsaW5rLVwiK0BjdXN0b21EYXRhLmxpbmtEYXRhLnN0eWxlSW5kZXhdKVxuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnNldHVwKClcbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgIEBhZGRDdXN0b21PYmplY3Qob2JqZWN0KVxuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmRzdFJlY3QueCA9IEBvYmplY3QuZHN0UmVjdC54ICsgQG9iamVjdC5vcmlnaW4ueCArIEBjdXN0b21EYXRhLmxpbmtEYXRhLmN4XG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5kc3RSZWN0LnkgPSBAb2JqZWN0LmRzdFJlY3QueSArIEBvYmplY3Qub3JpZ2luLnkgKyBAY3VzdG9tRGF0YS5saW5rRGF0YS5jeVxuXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5ldmVudHMub24oXCJjbGlja1wiLCBncy5DYWxsQmFjayhcIm9uTGlua0NsaWNrXCIsIHRoaXMpLCBsaW5rRGF0YTogQGN1c3RvbURhdGEubGlua0RhdGEsIHRoaXMpXG4gICAgICAgICAgICAgICAgZWxzZSAjIEJlZ2luIExpbmtcbiAgICAgICAgICAgICAgICAgICAgaWYgdG9rZW4udmFsdWU/LmNvbnRhaW5zKFwiLFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gdG9rZW4udmFsdWUuc3BsaXQoXCIsXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBAY3VzdG9tRGF0YS5saW5rRGF0YSA9IHsgY3g6IEBjdXJyZW50WCwgY3k6IEBjdXJyZW50WSwgY29tbW9uRXZlbnRJZDogdmFsdWVzWzBdLCBzdHlsZUluZGV4OiBwYXJzZUludCh2YWx1ZXNbMV0pLCB0b2tlbkluZGV4OiBAdG9rZW5JbmRleCB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIEBjdXN0b21EYXRhLmxpbmtEYXRhID0geyBjeDogQGN1cnJlbnRYLCBjeTogQGN1cnJlbnRZLCBjb21tb25FdmVudElkOiB0b2tlbi52YWx1ZSwgdG9rZW5JbmRleDogQHRva2VuSW5kZXgsIHN0eWxlSW5kZXg6IC0xIH1cbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB3aGVuIFwiRVwiICMgQ2hhbmdlIEV4cHJlc3Npb25cbiAgICAgICAgICAgICAgICBleHByZXNzaW9uID0gUmVjb3JkTWFuYWdlci5jaGFyYWN0ZXJFeHByZXNzaW9uc1tNYXRoLm1heCh0b2tlbi52YWx1ZS0xLCAwKV1cbiAgICAgICAgICAgICAgICBjaGFyYWN0ZXIgPSBTY2VuZU1hbmFnZXIuc2NlbmUuY3VycmVudENoYXJhY3RlclxuICAgICAgICAgICAgICAgIGlmIGV4cHJlc3Npb24/IGFuZCBjaGFyYWN0ZXI/LmluZGV4P1xuICAgICAgICAgICAgICAgICAgICBkdXJhdGlvbiA9IEdhbWVNYW5hZ2VyLmRlZmF1bHRzLmNoYXJhY3Rlci5leHByZXNzaW9uRHVyYXRpb25cbiAgICAgICAgICAgICAgICAgICAgZWFzaW5nID0gZ3MuRWFzaW5ncy5mcm9tT2JqZWN0KEdhbWVNYW5hZ2VyLmRlZmF1bHRzLmNoYXJhY3Rlci5jaGFuZ2VFYXNpbmcpXG4gICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbiA9IEdhbWVNYW5hZ2VyLmRlZmF1bHRzLmNoYXJhY3Rlci5jaGFuZ2VBbmltYXRpb25cbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0ID0gU2NlbmVNYW5hZ2VyLnNjZW5lLmNoYXJhY3RlcnMuZmlyc3QgKGMpIC0+IGMucmlkID09IGNoYXJhY3Rlci5pbmRleFxuICAgICAgICAgICAgICAgICAgICBvYmplY3Q/LmJlaGF2aW9yLmNoYW5nZUV4cHJlc3Npb24oZXhwcmVzc2lvbiwgYW5pbWF0aW9uLCBlYXNpbmcsIGR1cmF0aW9uKVxuICBcbiAgICAgICAgICAgIHdoZW4gXCJTUFwiICMgUGxheSBTb3VuZFxuICAgICAgICAgICAgICAgIHNvdW5kID0gUmVjb3JkTWFuYWdlci5zeXN0ZW0uc291bmRzW3Rva2VuLnZhbHVlLTFdXG4gICAgICAgICAgICAgICAgQXVkaW9NYW5hZ2VyLnBsYXlTb3VuZChzb3VuZClcbiAgICAgICAgICAgIHdoZW4gXCJTXCIgIyBDaGFuZ2UgU3BlZWRcbiAgICAgICAgICAgICAgICBHYW1lTWFuYWdlci5zZXR0aW5ncy5tZXNzYWdlU3BlZWQgPSB0b2tlbi52YWx1ZVxuICAgICAgICAgICAgd2hlbiBcIldcIiAjIFdhaXRcbiAgICAgICAgICAgICAgICBAZHJhd0ltbWVkaWF0ZWx5ID0gbm9cbiAgICAgICAgICAgICAgICBpZiAhR2FtZU1hbmFnZXIudGVtcFNldHRpbmdzLnNraXBcbiAgICAgICAgICAgICAgICAgICAgaWYgdG9rZW4udmFsdWUgPT0gXCJBXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIEB3YWl0Rm9yS2V5ID0geWVzXG4gICAgICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIEB3YWl0Q291bnRlciA9IE1hdGgucm91bmQodG9rZW4udmFsdWUgLyAxMDAwICogR3JhcGhpY3MuZnJhbWVSYXRlKVxuICAgICAgICAgICAgd2hlbiBcIldFXCIgIyBXYWl0IGF0IEVuZFxuICAgICAgICAgICAgICAgIEB3YWl0QXRFbmQgPSB0b2tlbi52YWx1ZSA9PSBcIllcIlxuICAgICAgICAgICAgd2hlbiBcIkRJXCIgIyBEcmF3IEltbWVkaWFsdHlcbiAgICAgICAgICAgICAgICBAZHJhd0ltbWVkaWF0ZWx5ID0gdG9rZW4udmFsdWUgPT0gMSBvciB0b2tlbi52YWx1ZSA9PSBcIllcIiAjIERyYXcgaW1tZWRpYXRlbHlcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBzdXBlcih0b2tlbilcbiAgICAgICAgXG4gICAgICAgIHJldHVybiByZXN1bHQgICAgICAgIFxuICAgICMjIypcbiAgICAqIENsZWFycy9SZXNldHMgdGhlIHRleHQtcmVuZGVyZXIuXG4gICAgKlxuICAgICogQG1ldGhvZCBjbGVhclxuICAgICMjI1xuICAgIGNsZWFyOiAtPlxuICAgICAgICBAY2hhckluZGV4ID0gMFxuICAgICAgICBAY3VycmVudFggPSAwXG4gICAgICAgIEBjdXJyZW50WSA9IDBcbiAgICAgICAgQGxpbmUgPSAwXG4gICAgICAgIEBsaW5lcyA9IFtdXG4gICAgICAgIEBjbGVhckN1c3RvbU9iamVjdHMoKVxuICAgICAgICBAb2JqZWN0LmJpdG1hcD8uY2xlYXIoKVxuICAgICAgICBcbiAgICAgICAgZm9yIHNwcml0ZSBpbiBAYWxsU3ByaXRlc1xuICAgICAgICAgICAgc3ByaXRlLmRpc3Bvc2UoKVxuICAgICAgICAgICAgc3ByaXRlLmJpdG1hcD8uZGlzcG9zZSgpXG4gICAgICAgIEBhbGxTcHJpdGVzID0gW11cbiAgICAgICAgcmV0dXJuIG51bGxcbiAgICBcbiAgICAjIyMqXG4gICAgKiBDbGVhcnMvRGlzcG9zZXMgYWxsIHNwcml0ZXMgdXNlZCB0byBkaXNwbGF5IHRoZSB0ZXh0LWxpbmVzL3BhcnRzLlxuICAgICpcbiAgICAqIEBtZXRob2QgY2xlYXJBbGxTcHJpdGVzXG4gICAgIyMjXG4gICAgY2xlYXJBbGxTcHJpdGVzOiAtPlxuICAgICAgICBmb3Igc3ByaXRlIGluIEBhbGxTcHJpdGVzXG4gICAgICAgICAgICBzcHJpdGUuZGlzcG9zZSgpXG4gICAgICAgICAgICBzcHJpdGUuYml0bWFwPy5kaXNwb3NlKClcbiAgICAgICAgICAgIFxuICAgICAgICByZXR1cm4gbnVsbFxuICAgIFxuICAgICMjIypcbiAgICAqIENsZWFycy9EaXNwb3NlcyB0aGUgc3ByaXRlcyB1c2VkIHRvIGRpc3BsYXkgdGhlIHRleHQtbGluZXMvcGFydHMgb2YgdGhlIGN1cnJlbnQvbGFzdCBtZXNzYWdlLlxuICAgICpcbiAgICAqIEBtZXRob2QgY2xlYXJTcHJpdGVzXG4gICAgIyMjICAgICAgICBcbiAgICBjbGVhclNwcml0ZXM6IC0+XG4gICAgICAgIGZvciBzcHJpdGUgaW4gQHNwcml0ZXNcbiAgICAgICAgICAgIHNwcml0ZS5kaXNwb3NlKClcbiAgICAgICAgICAgIHNwcml0ZS5iaXRtYXA/LmRpc3Bvc2UoKVxuICAgICAgICAgICAgXG4gICAgICAgIHJldHVybiBudWxsXG4gICAgXG4gICAgXG4gICAgIyMjKlxuICAgICogUmVtb3ZlcyBhIGdhbWUgb2JqZWN0IGZyb20gdGhlIG1lc3NhZ2UuXG4gICAgKlxuICAgICogQG1ldGhvZCByZW1vdmVDdXN0b21PYmplY3RcbiAgICAqIEBwYXJhbSBvYmplY3Qge2dzLk9iamVjdF9CYXNlfSBUaGUgZ2FtZSBvYmplY3QgdG8gcmVtb3ZlLlxuICAgICMjI1xuICAgIHJlbW92ZUN1c3RvbU9iamVjdDogKG9iamVjdCkgLT5cbiAgICAgICAgU2NlbmVNYW5hZ2VyLnNjZW5lLnJlbW92ZU9iamVjdChvYmplY3QpXG4gICAgICAgIG9iamVjdC5kaXNwb3NlKClcbiAgICAgICAgQGN1c3RvbU9iamVjdHMucmVtb3ZlKG9iamVjdClcbiAgICAgICAgXG4gICAgIyMjKlxuICAgICogQWRkcyBhIGdhbWUgb2JqZWN0IHRvIHRoZSBtZXNzYWdlIHdoaWNoIGlzIGFsaXZlIHVudGlsIHRoZSBtZXNzYWdlIGlzXG4gICAgKiBlcmFzZWQuIENhbiBiZSB1c2VkIHRvIGRpc3BsYXkgYW5pbWF0aW9uZWQtaWNvbnMsIGV0Yy4gaW4gYSBtZXNzYWdlLlxuICAgICpcbiAgICAqIEBtZXRob2QgYWRkQ3VzdG9tT2JqZWN0XG4gICAgKiBAcGFyYW0gb2JqZWN0IHtncy5PYmplY3RfQmFzZX0gVGhlIGdhbWUgb2JqZWN0IHRvIGFkZC5cbiAgICAjIyNcbiAgICBhZGRDdXN0b21PYmplY3Q6IChvYmplY3QpIC0+XG4gICAgICAgIG9iamVjdC5kc3RSZWN0LnggPSBAb2JqZWN0LmRzdFJlY3QueCArIEBvYmplY3Qub3JpZ2luLnggKyBAY3VycmVudFhcbiAgICAgICAgb2JqZWN0LmRzdFJlY3QueSA9IEBvYmplY3QuZHN0UmVjdC55ICsgQG9iamVjdC5vcmlnaW4ueSArIEBjdXJyZW50WVxuICAgICAgICBvYmplY3QuekluZGV4ID0gQG9iamVjdC56SW5kZXggKyAxXG4gICAgICAgIG9iamVjdC51cGRhdGUoKVxuICAgICAgICBcbiAgICAgICAgU2NlbmVNYW5hZ2VyLnNjZW5lLmFkZE9iamVjdChvYmplY3QpXG4gICAgICAgIEBjdXN0b21PYmplY3RzLnB1c2gob2JqZWN0KVxuICAgICBcbiAgICAjIyMqXG4gICAgKiBDbGVhcnMgdGhlIGxpc3Qgb2YgY3VzdG9tIGdhbWUgb2JqZWN0cy4gQWxsIGdhbWUgb2JqZWN0cyBhcmUgZGlzcG9zZWQgYW5kIHJlbW92ZWRcbiAgICAqIGZyb20gdGhlIHNjZW5lLlxuICAgICpcbiAgICAqIEBtZXRob2QgY2xlYXJDdXN0b21PYmplY3RzXG4gICAgKiBAcGFyYW0gb2JqZWN0IHtPYmplY3R9IFRoZSBnYW1lIG9iamVjdCB0byBhZGQuXG4gICAgIyMjICAgXG4gICAgY2xlYXJDdXN0b21PYmplY3RzOiAtPlxuICAgICAgICBmb3Igb2JqZWN0IGluIEBjdXN0b21PYmplY3RzXG4gICAgICAgICAgICBvYmplY3QuZGlzcG9zZSgpXG4gICAgICAgICAgICBTY2VuZU1hbmFnZXIuc2NlbmUucmVtb3ZlT2JqZWN0KG9iamVjdClcbiAgICAgICAgICAgIFxuICAgICAgICBAY3VzdG9tT2JqZWN0cyA9IFtdXG4gICAgXG4gICAgIyMjKlxuICAgICogQ3JlYXRlcyB0aGUgYml0bWFwIGZvciBhIHNwZWNpZmllZCBsaW5lLW9iamVjdC5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGNyZWF0ZUJpdG1hcFxuICAgICogQHByaXZhdGVcbiAgICAqIEBwYXJhbSB7T2JqZWN0fSBsaW5lIC0gQSBsaW5lLW9iamVjdC5cbiAgICAqIEByZXR1cm4ge0JpdG1hcH0gQSBuZXdseSBjcmVhdGVkIGJpdG1hcCBjb250YWluaW5nIHRoZSBsaW5lLXRleHQuXG4gICAgIyMjXG4gICAgY3JlYXRlQml0bWFwOiAobGluZSkgLT5cbiAgICAgICAgQGZvbnQgPSBAb2JqZWN0LmZvbnRcbiAgICAgICAgYml0bWFwID0gbmV3IEJpdG1hcChAb2JqZWN0LmRzdFJlY3Qud2lkdGgsIE1hdGgubWF4KEBtaW5MaW5lSGVpZ2h0LCBsaW5lLmhlaWdodCkpXG4gICAgICAgIGJpdG1hcC5mb250ID0gQGZvbnRcbiAgICAgICBcbiAgICAgICAgcmV0dXJuIGJpdG1hcFxuICAgIFxuICAgICMjIypcbiAgICAqIERyYXdzIHRoZSBsaW5lJ3MgY29udGVudCBvbiB0aGUgc3BlY2lmaWVkIGJpdG1hcC5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGRyYXdMaW5lQ29udGVudFxuICAgICogQHByb3RlY3RlZFxuICAgICogQHBhcmFtIHtPYmplY3R9IGxpbmUgLSBBIGxpbmUtb2JqZWN0IHdoaWNoIHNob3VsZCBiZSBkcmF3biBvbiB0aGUgYml0bWFwLlxuICAgICogQHBhcmFtIHtncy5CaXRtYXB9IGJpdG1hcCAtIFRoZSBiaXRtYXAgdG8gZHJhdyB0aGUgbGluZSdzIGNvbnRlbnQgb24uXG4gICAgKiBAcGFyYW0ge251bWJlcn0gbGVuZ3RoIC0gRGV0ZXJtaW5lcyBob3cgbWFueSBjaGFyYWN0ZXJzIG9mIHRoZSBzcGVjaWZpZWQgbGluZSBzaG91bGQgYmUgZHJhd24uIFlvdSBjYW4gXG4gICAgKiBzcGVjaWZ5IC0xIHRvIGRyYXcgYWxsIGNoYXJhY3RlcnMuXG4gICAgIyMjXG4gICAgZHJhd0xpbmVDb250ZW50OiAobGluZSwgYml0bWFwLCBsZW5ndGgpIC0+XG4gICAgICAgIGJpdG1hcC5jbGVhcigpXG4gICAgICAgIGN1cnJlbnRYID0gQHBhZGRpbmdcbiAgICAgICAgZHJhd0FsbCA9IGxlbmd0aCA9PSAtMVxuICAgICAgICBcbiAgICAgICAgZm9yIHRva2VuLCBpIGluIGxpbmUuY29udGVudFxuICAgICAgICAgICAgYnJlYWsgaWYgaSA+IEB0b2tlbkluZGV4IGFuZCAhZHJhd0FsbFxuICAgICAgICAgICAgaWYgdG9rZW4uY29kZT9cbiAgICAgICAgICAgICAgICBzaXplID0gQG1lYXN1cmVDb250cm9sVG9rZW4odG9rZW4sIGJpdG1hcClcbiAgICAgICAgICAgICAgICBAZHJhd0NvbnRyb2xUb2tlbih0b2tlbiwgYml0bWFwLCBjdXJyZW50WClcbiAgICAgICAgICAgICAgICBpZiBzaXplIHRoZW4gY3VycmVudFggKz0gc2l6ZS53aWR0aFxuICAgICAgICAgICAgICAgIEBwcm9jZXNzQ29udHJvbFRva2VuKHRva2VuLCB5ZXMsIGxpbmUpXG4gICAgICAgICAgICBlbHNlIGlmIHRva2VuLnZhbHVlLmxlbmd0aCA+IDBcbiAgICAgICAgICAgICAgICB0b2tlbi5hcHBseUZvcm1hdChAZm9udClcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IHRva2VuLnZhbHVlXG4gICAgICAgICAgICAgICAgaWYgIWRyYXdBbGwgYW5kIEB0b2tlbkluZGV4ID09IGkgYW5kIHZhbHVlLmxlbmd0aCA+IGxlbmd0aFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnN1YnN0cmluZygwLCBsZW5ndGgpXG4gICAgICAgICAgICAgICAgaWYgdmFsdWUgIT0gXCJcXG5cIlxuICAgICAgICAgICAgICAgICAgICBzaXplID0gQGZvbnQubWVhc3VyZVRleHRQbGFpbih2YWx1ZSkgIFxuICAgICAgICAgICAgICAgICAgICBiaXRtYXAuZHJhd1RleHQoY3VycmVudFgsIGxpbmUuaGVpZ2h0IC0gKHNpemUuaGVpZ2h0IC0gQGZvbnQuZGVzY2VudCkgLSBsaW5lLmRlc2NlbnQsIHNpemUud2lkdGgsIGJpdG1hcC5oZWlnaHQsIHZhbHVlLCAwLCAwKVxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50WCArPSBzaXplLndpZHRoXG4gICAgICAgICAgICAgICAgXG4gICAgICAgIGxpbmUuY29udGVudFdpZHRoID0gY3VycmVudFggKyBAZm9udC5tZWFzdXJlVGV4dFBsYWluKFwiIFwiKS53aWR0aCAgIFxuICAgICAgICBcbiAgICAjIyMqXG4gICAgKiBDcmVhdGVzIHRoZSBzcHJpdGUgZm9yIGEgc3BlY2lmaWVkIGxpbmUtb2JqZWN0LlxuICAgICpcbiAgICAqIEBtZXRob2QgY3JlYXRlU3ByaXRlXG4gICAgKiBAcHJpdmF0ZVxuICAgICogQHBhcmFtIHtPYmplY3R9IGxpbmUgLSBBIGxpbmUtb2JqZWN0LlxuICAgICogQHJldHVybiB7U3ByaXRlfSBBIG5ld2x5IGNyZWF0ZWQgc3ByaXRlIG9iamVjdCBjb250YWluaW5nIHRoZSBsaW5lLXRleHQgYXMgYml0bWFwLlxuICAgICMjI1xuICAgIGNyZWF0ZVNwcml0ZTogKGxpbmUpIC0+XG4gICAgICAgIGJpdG1hcCA9IEBjcmVhdGVCaXRtYXAobGluZSlcbiAgICAgICAgXG4gICAgICAgIEBjdXJyZW50WCA9IDBcbiAgICAgICAgQHdhaXRDb3VudGVyID0gMFxuICAgICAgICBAd2FpdEZvcktleSA9IG5vXG4gICAgICAgICAgICAgICAgXG4gICAgICAgIHNwcml0ZSA9IG5ldyBTcHJpdGUoR3JhcGhpY3Mudmlld3BvcnQpXG4gICAgICAgIHNwcml0ZS5iaXRtYXAgPSBiaXRtYXBcbiAgICAgICAgc3ByaXRlLnZpc2libGUgPSB5ZXNcbiAgICAgICAgc3ByaXRlLnogPSBAb2JqZWN0LnpJbmRleCArIDFcbiAgICAgICAgXG4gICAgICAgIHNwcml0ZS5zcmNSZWN0ID0gbmV3IFJlY3QoMCwgMCwgMCwgYml0bWFwLmhlaWdodClcbiAgICAgICAgXG4gICAgICAgIHJldHVybiBzcHJpdGVcbiAgICAgXG4gICAgIyMjKlxuICAgICogQ3JlYXRlcyB0aGUgc3ByaXRlcyBmb3IgYSBzcGVjaWZpZWQgYXJyYXkgb2YgbGluZS1vYmplY3RzLlxuICAgICpcbiAgICAqIEBtZXRob2QgY3JlYXRlU3ByaXRlc1xuICAgICogQHByaXZhdGVcbiAgICAqIEBzZWUgZ3MuQ29tcG9uZW50X01lc3NhZ2VUZXh0UmVuZGVyZXIuY3JlYXRlU3ByaXRlLlxuICAgICogQHBhcmFtIHtBcnJheX0gbGluZXMgLSBBbiBhcnJheSBvZiBsaW5lLW9iamVjdHMuXG4gICAgKiBAcmV0dXJuIHtBcnJheX0gQW4gYXJyYXkgb2Ygc3ByaXRlcy5cbiAgICAjIyNcbiAgICBjcmVhdGVTcHJpdGVzOiAobGluZXMpIC0+XG4gICAgICAgIEBmb250U2l6ZSA9IEBvYmplY3QuZm9udC5zaXplXG4gICAgICAgIHJlc3VsdCA9IFtdXG4gICAgICAgIGZvciBsaW5lLCBpIGluIGxpbmVzXG4gICAgICAgICAgICBzcHJpdGUgPSBAY3JlYXRlU3ByaXRlKGxpbmUpXG4gICAgICAgICAgICByZXN1bHQucHVzaChzcHJpdGUpXG4gICAgICAgIHJldHVybiByZXN1bHRcbiAgICBcbiAgICAjIyMqXG4gICAgKiBTdGFydHMgYSBuZXcgbGluZS5cbiAgICAqXG4gICAgKiBAbWV0aG9kIG5ld0xpbmVcbiAgICAjIyNcbiAgICBuZXdMaW5lOiAtPlxuICAgICAgICBAY3VycmVudFggPSAwXG4gICAgICAgIEBjdXJyZW50WSArPSBAY3VycmVudExpbmVIZWlnaHQgKyBAbGluZVNwYWNpbmdcbiAgICAgICAgXG4gICAgIyMjKlxuICAgICogRGlzcGxheXMgYSBmb3JtYXR0ZWQgdGV4dCBpbW1lZGlhdGVseSB3aXRob3V0IGFueSBkZWxheXMgb3IgYW5pbWF0aW9ucy4gVGhlXG4gICAgKiBDb21wb25lbnRfVGV4dFJlbmRlcmVyLmRyYXdGb3JtYXR0ZWRUZXh0IG1ldGhvZCBmcm9tIHRoZSBiYXNlLWNsYXNzIGNhbm5vdFxuICAgICogYmUgdXNlZCBoZXJlIGJlY2F1c2UgaXQgd291bGQgcmVuZGVyIHRvIHRoZSBnYW1lIG9iamVjdCdzIGJpdG1hcCBvYmplY3Qgd2hpbGVcbiAgICAqIHRoaXMgbWV0aG9kIGlzIHJlbmRlcmluZyB0byB0aGUgc3ByaXRlcy5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGRyYXdGb3JtYXR0ZWRUZXh0SW1tZWRpYXRlbHlcbiAgICAqIEBwYXJhbSB7bnVtYmVyfSB4IC0gVGhlIHgtY29vcmRpbmF0ZSBvZiB0aGUgdGV4dCdzIHBvc2l0aW9uLlxuICAgICogQHBhcmFtIHtudW1iZXJ9IHkgLSBUaGUgeS1jb29yZGluYXRlIG9mIHRoZSB0ZXh0J3MgcG9zaXRpb24uXG4gICAgKiBAcGFyYW0ge251bWJlcn0gd2lkdGggLSBEZXByZWNhdGVkLiBDYW4gYmUgbnVsbC5cbiAgICAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgLSBEZXByZWNhdGVkLiBDYW4gYmUgbnVsbC5cbiAgICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gVGhlIHRleHQgdG8gZHJhdy5cbiAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gd29yZFdyYXAgLSBJZiB3b3JkV3JhcCBpcyBzZXQgdG8gdHJ1ZSwgbGluZS1icmVha3MgYXJlIGF1dG9tYXRpY2FsbHkgY3JlYXRlZC5cbiAgICAjIyNcbiAgICBkcmF3Rm9ybWF0dGVkVGV4dEltbWVkaWF0ZWx5OiAoeCwgeSwgd2lkdGgsIGhlaWdodCwgdGV4dCwgd29yZFdyYXApIC0+XG4gICAgICAgIEBkcmF3Rm9ybWF0dGVkVGV4dCh4LCB5LCB3aWR0aCwgaGVpZ2h0LCB0ZXh0LCB3b3JkV3JhcClcbiAgICAgICAgXG4gICAgICAgIGxvb3BcbiAgICAgICAgICAgIEBuZXh0Q2hhcigpXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiBAbGluZSA+PSBAbWF4TGluZXNcbiAgICAgICAgICAgICAgICBAaXNSdW5uaW5nID0gbm9cbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICBAZHJhd05leHQoKVxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgYnJlYWsgdW5sZXNzIEBpc1J1bm5pbmdcbiAgICAgICAgICAgIFxuICAgICAgICBAY3VycmVudFkgKz0gQGN1cnJlbnRMaW5lSGVpZ2h0ICsgQGxpbmVTcGFjaW5nXG4gICAgICAgICAgICBcbiAgICAgICAgcmV0dXJuIG51bGxcbiAgICBcbiAgICBcbiAgICAjIyMqXG4gICAgKiBTdGFydHMgdGhlIHJlbmRlcmluZy1wcm9jZXNzIGZvciB0aGUgbWVzc2FnZS5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGRyYXdGb3JtYXR0ZWRUZXh0XG4gICAgKiBAcGFyYW0ge251bWJlcn0geCAtIFRoZSB4LWNvb3JkaW5hdGUgb2YgdGhlIHRleHQncyBwb3NpdGlvbi5cbiAgICAqIEBwYXJhbSB7bnVtYmVyfSB5IC0gVGhlIHktY29vcmRpbmF0ZSBvZiB0aGUgdGV4dCdzIHBvc2l0aW9uLlxuICAgICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gRGVwcmVjYXRlZC4gQ2FuIGJlIG51bGwuXG4gICAgKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gRGVwcmVjYXRlZC4gQ2FuIGJlIG51bGwuXG4gICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dCAtIFRoZSB0ZXh0IHRvIGRyYXcuXG4gICAgKiBAcGFyYW0ge2Jvb2xlYW59IHdvcmRXcmFwIC0gSWYgd29yZFdyYXAgaXMgc2V0IHRvIHRydWUsIGxpbmUtYnJlYWtzIGFyZSBhdXRvbWF0aWNhbGx5IGNyZWF0ZWQuXG4gICAgIyMjXG4gICAgZHJhd0Zvcm1hdHRlZFRleHQ6ICh4LCB5LCB3aWR0aCwgaGVpZ2h0LCB0ZXh0LCB3b3JkV3JhcCkgLT5cbiAgICAgICAgdGV4dCA9IHRleHQgfHwgXCIgXCIgIyBVc2UgYSBzcGFjZSBjaGFyYWN0ZXIgaWYgbm8gdGV4dCBpcyBzcGVjaWZpZWQuXG4gICAgICAgIEBmb250LnNldChAb2JqZWN0LmZvbnQpXG4gICAgICAgIEBzcGVlZCA9IDExIC0gTWF0aC5yb3VuZChHYW1lTWFuYWdlci5zZXR0aW5ncy5tZXNzYWdlU3BlZWQgKiAyLjUpXG4gICAgICAgIEBpc1J1bm5pbmcgPSB5ZXNcbiAgICAgICAgQGRyYXdJbW1lZGlhdGVseSA9IG5vXG4gICAgICAgIEBsaW5lQW5pbWF0aW9uQ291bnQgPSBAc3BlZWRcbiAgICAgICAgQGN1cnJlbnRMaW5lSGVpZ2h0ID0gMFxuICAgICAgICBAaXNXYWl0aW5nID0gbm9cbiAgICAgICAgQHdhaXRGb3JLZXkgPSBub1xuICAgICAgICBAY2hhckluZGV4ID0gMFxuICAgICAgICBAdG9rZW4gPSBudWxsXG4gICAgICAgIEB0b2tlbkluZGV4ID0gMFxuICAgICAgICBAbWVzc2FnZSA9IHRleHRcbiAgICAgICAgQGxpbmUgPSAwXG4gICAgICAgIEBjdXJyZW50TGluZSA9IEBsaW5lXG4gICAgICAgIGN1cnJlbnRYID0gQGN1cnJlbnRYXG4gICAgICAgIEBsaW5lcyA9IEBjYWxjdWxhdGVMaW5lcyhsY3NtKEBtZXNzYWdlKSwgd29yZFdyYXAsIEBjdXJyZW50WClcbiAgICAgICAgQHNwcml0ZXMgPSBAY3JlYXRlU3ByaXRlcyhAbGluZXMpXG4gICAgICAgIEBhbGxTcHJpdGVzID0gQGFsbFNwcml0ZXMuY29uY2F0KEBzcHJpdGVzKVxuICAgICAgICBAY3VycmVudFggPSBjdXJyZW50WFxuICAgICAgICBAY3VycmVudFNwcml0ZSA9IEBzcHJpdGVzW0BsaW5lXVxuICAgICAgICBAY3VycmVudFNwcml0ZS54ID0gQGN1cnJlbnRYICsgQG9iamVjdC5vcmlnaW4ueCArIEBvYmplY3QuZHN0UmVjdC54XG4gICAgICAgIEBtYXhMaW5lcyA9IEBjYWxjdWxhdGVNYXhMaW5lcyhAbGluZXMpXG4gICAgICAgIEB0b2tlbiA9IEBsaW5lc1tAbGluZV0/LmNvbnRlbnRbQHRva2VuSW5kZXhdIHx8IG5ldyBncy5SZW5kZXJlclRva2VuKG51bGwsIFwiXCIpXG4gICAgICAgIFxuICAgICAgICBcbiAgICAgICAgQHN0YXJ0KClcbiAgICAgXG4gICAgIyMjKlxuICAgICogU3RhcnRzIHRoZSBtZXNzYWdlLXJlbmRlcmluZyBwcm9jZXNzLlxuICAgICpcbiAgICAqIEBtZXRob2Qgc3RhcnRcbiAgICAqIEBwcm90ZWN0ZWRcbiAgICAjIyMgICAgIFxuICAgIHN0YXJ0OiAtPlxuICAgICAgICBpZiBHYW1lTWFuYWdlci50ZW1wU2V0dGluZ3Muc2tpcCBhbmQgR2FtZU1hbmFnZXIudGVtcFNldHRpbmdzLnNraXBUaW1lID09IDBcbiAgICAgICAgICAgIEBpbnN0YW50U2tpcCgpXG4gICAgICAgIGVsc2UgaWYgQG1heExpbmVzID09IDBcbiAgICAgICAgICAgICMgSWYgZmlyc3QgbGluZSBpcyBlbXB0eSB0aGVuIGl0IGRvZXNuJ3QgZml0IGludG8gY3VycmVudCBsaW5lLCBzbyBmaW5pc2guXG4gICAgICAgICAgICBpZiBAbGluZXNbMF0/LmNvbnRlbnQgPT0gXCJcIlxuICAgICAgICAgICAgICAgIEBmaW5pc2goKVxuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIEBtYXhMaW5lcyA9IDFcbiAgICAgICAgICAgICAgICBAZHJhd05leHQoKVxuICAgICAgICBlbHNlXG4gICAgICAgICAgICBAZHJhd05leHQoKVxuICAgICBcbiAgICAjIyMqXG4gICAgKiBTa2lwcyB0aGUgY3VycmVudCBtZXNzYWdlIGFuZCBmaW5pc2hlcyB0aGUgbWVzc2FnZS1wcm9jZXNzaW5nIGltbWVkaWF0ZWx5LiBUaGUgbWVzc2FnZVxuICAgICogdG9rZW5zIGFyZSBwcm9jZXNzZWQgYnV0IG5vdCByZW5kZXJlZC5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGluc3RhbnRTa2lwXG4gICAgIyMjICBcbiAgICBpbnN0YW50U2tpcDogLT5cbiAgICAgICAgbG9vcFxuICAgICAgICAgICAgaWYgQGxpbmUgPCBAbWF4TGluZXNcbiAgICAgICAgICAgICAgICBAbmV4dENoYXIoKVxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYgQGxpbmUgPj0gQG1heExpbmVzXG4gICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICBAcHJvY2Vzc1Rva2VuKClcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIGJyZWFrIHVubGVzcyBAaXNSdW5uaW5nIGFuZCBAbGluZSA8IEBtYXhMaW5lc1xuICAgICAgICBcbiAgICAgICAgQG9iamVjdC5ldmVudHM/LmVtaXQoXCJtZXNzYWdlV2FpdGluZ1wiLCB0aGlzKVxuICAgICAgICBAY29udGludWUoKVxuICAgICAgICBcbiAgICAjIyMqXG4gICAgKiBQcm9jZXNzZXMgdGhlIGN1cnJlbnQgdG9rZW4uXG4gICAgKlxuICAgICogQG1ldGhvZCBwcm9jZXNzVG9rZW5cbiAgICAjIyMgICAgXG4gICAgcHJvY2Vzc1Rva2VuOiAtPlxuICAgICAgICB0b2tlbiA9IG51bGxcbiAgICAgICAgXG4gICAgICAgIGlmIEB0b2tlbi5jb2RlP1xuICAgICAgICAgICAgdG9rZW4gPSBAcHJvY2Vzc0NvbnRyb2xUb2tlbihAdG9rZW4sIG5vKVxuICAgICAgICAgICAgaWYgdG9rZW4/XG4gICAgICAgICAgICAgICAgQHRva2VuID0gdG9rZW5cbiAgICAgICAgICAgICAgICBAdG9rZW4ub25TdGFydD8oKVxuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0b2tlbiA9IEB0b2tlblxuICAgICAgICAgICAgXG4gICAgICAgIHJldHVybiB0b2tlblxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuZ3MuQ29tcG9uZW50X01lc3NhZ2VUZXh0UmVuZGVyZXIgPSBDb21wb25lbnRfTWVzc2FnZVRleHRSZW5kZXJlciJdfQ==\n//# sourceURL=Component_MessageTextRenderer_127.js"
12 + "compiledContent": "var Component_MessageTextRenderer,\n extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n hasProp = {}.hasOwnProperty;\n\nComponent_MessageTextRenderer = (function(superClass) {\n extend(Component_MessageTextRenderer, superClass);\n\n Component_MessageTextRenderer.objectCodecBlackList = [\"onLinkClick\", \"onBatchDisappear\"];\n\n\n /**\n * Called if this object instance is restored from a data-bundle. It can be used\n * re-assign event-handler, anonymous functions, etc.\n * x\n * @method onDataBundleRestore.\n * @param Object data - The data-bundle\n * @param gs.ObjectCodecContext context - The codec-context.\n */\n\n Component_MessageTextRenderer.prototype.onDataBundleRestore = function(data, context) {\n var bitmap, customObject, j, l, len, len1, len2, line, m, message, n, ref, ref1, ref2;\n this.setupEventHandlers();\n l = 0;\n ref = this.object.messages;\n for (j = 0, len = ref.length; j < len; j++) {\n message = ref[j];\n if (this.object.settings.useCharacterColor) {\n this.object.font.color = new gs.Color(message.character.textColor);\n }\n this.lines = this.calculateLines(lcsm(message.text), true, 0);\n ref1 = this.lines;\n for (m = 0, len1 = ref1.length; m < len1; m++) {\n line = ref1[m];\n bitmap = this.createBitmap(line);\n if (line === this.line) {\n this.drawLineContent(line, bitmap, this.charIndex + 1);\n } else {\n this.drawLineContent(line, bitmap, -1);\n }\n this.allSprites[l].bitmap = bitmap;\n l++;\n }\n }\n ref2 = this.customObjects;\n for (n = 0, len2 = ref2.length; n < len2; n++) {\n customObject = ref2[n];\n SceneManager.scene.addObject(customObject);\n }\n return null;\n };\n\n\n /**\n * A text-renderer component to render an animated and interactive message text using\n * dimensions of the game object's destination-rectangle. The message is displayed\n * using a sprite for each line instead of drawing to the game object's bitmap object.\n *\n * @module gs\n * @class Component_MessageTextRenderer\n * @extends gs.Component_TextRenderer\n * @memberof gs\n * @constructor\n */\n\n function Component_MessageTextRenderer() {\n Component_MessageTextRenderer.__super__.constructor.apply(this, arguments);\n\n /**\n * An array containing all sprites of the current message.\n * @property sprites\n * @type gs.Sprite[]\n * @protected\n */\n this.sprites = [];\n\n /**\n * An array containing all sprites of all messages. In NVL mode\n * a page can contain multiple messages.\n * @property allSprites\n * @type gs.Sprite[]\n * @protected\n */\n this.allSprites = [];\n\n /**\n * An array containing all line-objects of the current message.\n * @property lines\n * @type gs.TextRendererLine[]\n * @readOnly\n */\n this.lines = null;\n\n /**\n * The line currently rendered.\n * @property line\n * @type number\n * @readOnly\n */\n this.line = 0;\n\n /**\n * The left and right padding per line.\n * @property padding\n * @type number\n */\n this.padding = 6;\n\n /**\n * The minimum height of the line currently rendered. If 0, the measured\n * height of the line will be used.\n * @property minLineHeight\n * @type number\n */\n this.minLineHeight = 0;\n\n /**\n * The spacing between text lines in pixels.\n * @property lineSpacing\n * @type number\n */\n this.lineSpacing = 2;\n\n /**\n * The line currently rendered.\n * @property currentLine\n * @type number\n * @protected\n */\n this.currentLine = 0;\n\n /**\n * The height of the line currently rendered.\n * @property currentLineHeight\n * @type number\n * @protected\n */\n this.currentLineHeight = 0;\n\n /**\n * Index of the current character to draw.\n * @property charIndex\n * @type number\n * @readOnly\n */\n this.charIndex = 0;\n\n /**\n * Position of the message caret. The caret is like an invisible\n * cursor pointing to the x/y coordinates of the last rendered character of\n * the message. That position can be used to display a waiting- or processing-animation for example.\n * @property caretPosition\n * @type gs.Point\n * @readOnly\n */\n this.caretPosition = new gs.Point();\n\n /**\n * Indicates that the a message is currently in progress.\n * @property isRunning\n * @type boolean\n * @readOnly\n */\n this.isRunning = false;\n\n /**\n * The current x-coordinate of the caret/cursor.\n * @property currentX\n * @type number\n * @readOnly\n */\n this.currentX = 0;\n\n /**\n * The current y-coordinate of the caret/cursor.\n * @property currentY\n * @type number\n * @readOnly\n */\n this.currentY = 0;\n\n /**\n * The current sprites used to display the current text-line/part.\n * @property currentSprite\n * @type gs.Sprite\n * @readOnly\n */\n this.currentSprite = null;\n\n /**\n * Indicates if the message-renderer is currently waiting like for a user-action.\n * @property isWaiting\n * @type boolean\n * @readOnly\n */\n this.isWaiting = false;\n\n /**\n * Indicates if the message-renderer is currently waiting for a key-press or mouse/touch action.\n * @property waitForKey\n * @type boolean\n * @readOnly\n */\n this.waitForKey = false;\n\n /**\n * Number of frames the message-renderer should wait before continue.\n * @property waitCounter\n * @type number\n */\n this.waitCounter = 0;\n\n /**\n * Speed of the message-drawing. The smaller the value, the faster the message is displayed.\n * @property speed\n * @type number\n */\n this.speed = 1;\n\n /**\n * Indicates if the message should be rendered immedialtely without any animation or delay.\n * @property drawImmediately\n * @type boolean\n */\n this.drawImmediately = false;\n\n /**\n * Indicates if the message should wait for a user-action or a certain amount of time\n * before finishing.\n * @property waitAtEnd\n * @type boolean\n */\n this.waitAtEnd = true;\n\n /**\n * The number of frames to wait before finishing a message.\n * before finishing.\n * @property waitAtEndTime\n * @type number\n */\n this.waitAtEndTime = 0;\n\n /**\n * Indicates if auto word-wrap should be used. Default is <b>true</b>\n * @property wordWrap\n * @type boolean\n */\n this.wordWrap = true;\n\n /**\n * Custom game objects which are alive until the current message is erased. Can be used to display\n * animated icons, etc.\n * @property customObjects\n * @type gs.Object_Base[]\n */\n this.customObjects = [];\n\n /**\n * A hashtable/dictionary object to store custom-data useful like for token-processing. The data must be\n * serializable.\n * @property customObjects\n * @type Object\n */\n this.customData = {};\n\n /**\n * A callback function called if the player clicks on a non-stylable link (LK text-code) to trigger\n * the specified common event.\n * @property onLinkClick\n * @type Function\n */\n this.onLinkClick = function(e) {\n var event, eventId;\n eventId = e.data.linkData.commonEventId;\n event = RecordManager.commonEvents[eventId];\n if (!event) {\n event = RecordManager.commonEvents.first((function(_this) {\n return function(x) {\n return x.name === eventId;\n };\n })(this));\n if (event) {\n eventId = event.index;\n }\n }\n if (!event) {\n return SceneManager.scene.interpreter.jumpToLabel(eventId);\n } else {\n return SceneManager.scene.interpreter.callCommonEvent(eventId, null, true);\n }\n };\n\n /**\n * A callback function called if a batched messsage has been faded out. It triggers the execution of\n * the next message.\n * @property onBatchDisappear\n * @type Function\n */\n this.onBatchDisappear = (function(_this) {\n return function(e) {\n _this.drawImmediately = false;\n _this.isWaiting = false;\n _this.object.opacity = 255;\n return _this.executeBatch();\n };\n })(this);\n }\n\n\n /**\n * Serializes the message text-renderer into a data-bundle.\n * @method toDataBundle\n * @return {Object} A data-bundle.\n */\n\n Component_MessageTextRenderer.prototype.toDataBundle = function() {\n var bundle, ignore, k;\n ignore = [\"object\", \"font\", \"sprites\", \"allSprites\", \"currentSprite\", \"currentX\"];\n bundle = {\n currentSpriteIndex: this.sprites.indexOf(this.currentSprite)\n };\n for (k in this) {\n if (ignore.indexOf(k) === -1) {\n bundle[k] = this[k];\n }\n }\n return bundle;\n };\n\n\n /**\n * Disposes the message text-renderer and all sprites used to display\n * the message.\n * @method dispose\n */\n\n Component_MessageTextRenderer.prototype.dispose = function() {\n var j, len, ref, ref1, results, sprite;\n Component_MessageTextRenderer.__super__.dispose.apply(this, arguments);\n this.disposeEventHandlers();\n ref = this.allSprites;\n results = [];\n for (j = 0, len = ref.length; j < len; j++) {\n sprite = ref[j];\n if ((ref1 = sprite.bitmap) != null) {\n ref1.dispose();\n }\n results.push(sprite.dispose());\n }\n return results;\n };\n\n\n /**\n * Removes all attached event handlers \n * the message.\n * @method disposeEventHandlers\n */\n\n Component_MessageTextRenderer.prototype.disposeEventHandlers = function() {\n gs.GlobalEventManager.offByOwner(\"mouseUp\", this.object);\n return gs.GlobalEventManager.offByOwner(\"keyUp\", this.object);\n };\n\n\n /**\n * Adds event-handlers for mouse/touch events\n *\n * @method setupEventHandlers\n */\n\n Component_MessageTextRenderer.prototype.setupEventHandlers = function() {\n gs.GlobalEventManager.offByOwner(\"mouseUp\", this.object);\n gs.GlobalEventManager.offByOwner(\"keyUp\", this.object);\n gs.GlobalEventManager.on(\"mouseUp\", ((function(_this) {\n return function(e) {\n if (_this.object.findComponentByName(\"animation\") || (GameManager.settings.autoMessage.enabled && !GameManager.settings.autoMessage.stopOnAction)) {\n return;\n }\n if (_this.isWaiting && !(_this.waitCounter > 0 || _this.waitForKey)) {\n e.breakChain = true;\n _this[\"continue\"]();\n } else {\n e.breakChain = _this.isRunning;\n _this.drawImmediately = !_this.waitForKey;\n _this.waitCounter = 0;\n _this.waitForKey = false;\n _this.isWaiting = false;\n }\n if (_this.waitForKey) {\n if (Input.Mouse.buttons[Input.Mouse.LEFT] === 2) {\n e.breakChain = true;\n Input.clear();\n _this.waitForKey = false;\n return _this.isWaiting = false;\n }\n }\n };\n })(this)), null, this.object);\n return gs.GlobalEventManager.on(\"keyUp\", ((function(_this) {\n return function(e) {\n if (Input.keys[Input.C] && (!_this.isWaiting || (_this.waitCounter > 0 || _this.waitForKey))) {\n _this.drawImmediately = !_this.waitForKey;\n _this.waitCounter = 0;\n _this.waitForKey = false;\n _this.isWaiting = false;\n }\n if (_this.isWaiting && !_this.waitForKey && !_this.waitCounter && Input.keys[Input.C]) {\n _this[\"continue\"]();\n }\n if (_this.waitForKey) {\n if (Input.keys[Input.C]) {\n Input.clear();\n _this.waitForKey = false;\n return _this.isWaiting = false;\n }\n }\n };\n })(this)), null, this.object);\n };\n\n\n /**\n * Sets up the renderer. Registers necessary event handlers.\n * @method setup\n */\n\n Component_MessageTextRenderer.prototype.setup = function() {\n return this.setupEventHandlers();\n };\n\n\n /**\n * Restores the message text-renderer's state from a data-bundle.\n * @method restore\n * @param {Object} bundle - A data-bundle containing message text-renderer state.\n */\n\n Component_MessageTextRenderer.prototype.restore = function(bundle) {\n var k;\n for (k in bundle) {\n if (k === \"currentSpriteIndex\") {\n this.currentSprite = this.sprites[bundle.currentSpriteIndex];\n } else {\n this[k] = bundle[k];\n }\n }\n if (this.sprites.length > 0) {\n this.currentY = this.sprites.last().y - this.object.origin.y - this.object.dstRect.y;\n this.line = this.maxLines;\n this.isWaiting = this.isWaiting || this.isRunning;\n }\n return null;\n };\n\n\n /**\n * Continues message-processing if currently waiting.\n * @method continue\n */\n\n Component_MessageTextRenderer.prototype[\"continue\"] = function() {\n var duration, fading, ref, ref1;\n this.isWaiting = false;\n if (this.line >= this.lines.length) {\n this.isRunning = false;\n return (ref = this.object.events) != null ? ref.emit(\"messageFinish\", this) : void 0;\n } else {\n if ((ref1 = this.object.events) != null) {\n ref1.emit(\"messageBatch\", this);\n }\n fading = GameManager.tempSettings.messageFading;\n duration = GameManager.tempSettings.skip ? 0 : fading.duration;\n return this.object.animator.disappear(fading.animation, fading.easing, duration, gs.CallBack(\"onBatchDisappear\", this));\n }\n };\n\n\n /**\n * Updates the text-renderer.\n * @method update\n */\n\n Component_MessageTextRenderer.prototype.update = function() {\n var j, len, len1, m, object, ref, ref1, ref2, sprite;\n ref = this.allSprites;\n for (j = 0, len = ref.length; j < len; j++) {\n sprite = ref[j];\n sprite.opacity = this.object.opacity;\n sprite.visible = this.object.visible;\n sprite.ox = -this.object.offset.x;\n sprite.oy = -this.object.offset.y;\n sprite.mask.value = this.object.mask.value;\n sprite.mask.vague = this.object.mask.vague;\n sprite.mask.source = this.object.mask.source;\n sprite.mask.type = this.object.mask.type;\n }\n ref1 = this.customObjects;\n for (m = 0, len1 = ref1.length; m < len1; m++) {\n object = ref1[m];\n object.opacity = this.object.opacity;\n object.visible = this.object.visible;\n }\n if (!this.isRunning && this.waitCounter > 0) {\n this.waitCounter--;\n if (this.waitCounter === 0) {\n this[\"continue\"]();\n }\n return;\n }\n if (this.object.visible && ((ref2 = this.lines) != null ? ref2.length : void 0) > 0) {\n this.updateLineWriting();\n this.updateWaitForKey();\n this.updateWaitCounter();\n return this.updateCaretPosition();\n }\n };\n\n\n /**\n * Indicates if its a batched messages.\n *\n * @method isBatched\n * @return If <b>true</b> it is a batched message. Otherwise <b>false</b>.\n */\n\n Component_MessageTextRenderer.prototype.isBatched = function() {\n return this.lines.length > this.maxLines;\n };\n\n\n /**\n * Indicates if the batch is still in progress and not done.\n *\n * @method isBatchInProgress\n * @return If <b>true</b> the batched message is still not done. Otherwise <b>false</b>\n */\n\n Component_MessageTextRenderer.prototype.isBatchInProgress = function() {\n return this.lines.length - this.line > this.maxLines;\n };\n\n\n /**\n * Starts displaying the next page of text if a message is too long to fit\n * into one message box.\n *\n * @method executeBatch\n */\n\n Component_MessageTextRenderer.prototype.executeBatch = function() {\n this.clearAllSprites();\n this.lines = this.lines.slice(this.line);\n this.line = 0;\n this.currentX = 0;\n this.currentY = 0;\n this.currentLineHeight = 0;\n this.tokenIndex = 0;\n this.charIndex = 0;\n this.token = this.lines[this.line].content[this.tokenIndex] || new gs.RendererToken(null, \"\");\n this.maxLines = this.calculateMaxLines(this.lines);\n this.lineAnimationCount = this.speed;\n this.sprites = this.createSprites(this.lines);\n this.allSprites = this.allSprites.concat(this.sprites);\n this.currentSprite = this.sprites[this.line];\n this.currentSprite.x = this.currentX + this.object.origin.x + this.object.dstRect.x;\n return this.drawNext();\n };\n\n\n /**\n * Calculates the duration(in frames) the message-renderer needs to display\n * the message.\n *\n * @method calculateDuration\n * @return {number} The duration in frames.\n */\n\n Component_MessageTextRenderer.prototype.calculateDuration = function() {\n var duration, j, len, len1, line, m, ref, ref1, token;\n duration = 0;\n if (this.lines != null) {\n ref = this.lines;\n for (j = 0, len = ref.length; j < len; j++) {\n line = ref[j];\n ref1 = line.content;\n for (m = 0, len1 = ref1.length; m < len1; m++) {\n token = ref1[m];\n if (token != null) {\n duration += this.calculateDurationForToken(token);\n }\n }\n }\n }\n return duration;\n };\n\n\n /**\n * Calculates the duration(in frames) the message-renderer needs to display\n * the specified line.\n *\n * @method calculateDurationForLine\n * @param {gs.RendererTextLine} line The line to calculate the duration for.\n * @return {number} The duration in frames.\n */\n\n Component_MessageTextRenderer.prototype.calculateDurationForLine = function(line) {\n var duration, j, len, ref, token;\n duration = 0;\n if (line) {\n ref = line.content;\n for (j = 0, len = ref.length; j < len; j++) {\n token = ref[j];\n if (token != null) {\n duration += this.calculateDurationForToken(token);\n }\n }\n }\n return duration;\n };\n\n\n /**\n * Calculates the duration(in frames) the message-renderer needs to process\n * the specified token.\n *\n * @method calculateDurationForToken\n * @param {string|Object} token - The token.\n * @return {number} The duration in frames.\n */\n\n Component_MessageTextRenderer.prototype.calculateDurationForToken = function(token) {\n var duration;\n duration = 0;\n if (token.code != null) {\n switch (token.code) {\n case \"W\":\n if (token.value !== \"A\") {\n duration = token.value / 1000 * Graphics.frameRate;\n }\n }\n } else {\n duration = token.value.length * this.speed;\n }\n return duration;\n };\n\n\n /**\n * Calculates the maximum of lines which can be displayed in one message.\n *\n * @method calculateMaxLines\n * @param {Array} lines - An array of line-objects.\n * @return {number} The number of displayable lines.\n */\n\n Component_MessageTextRenderer.prototype.calculateMaxLines = function(lines) {\n var height, j, len, line, result;\n height = 0;\n result = 0;\n for (j = 0, len = lines.length; j < len; j++) {\n line = lines[j];\n height += line.height + this.lineSpacing;\n if (this.currentY + height > this.object.dstRect.height) {\n break;\n }\n result++;\n }\n return Math.min(lines.length, result || 1);\n };\n\n\n /**\n * Displays the character or processes the next control-token.\n *\n * @method drawNext\n */\n\n Component_MessageTextRenderer.prototype.drawNext = function() {\n var lineSpacing, size, token;\n token = this.processToken();\n if ((token != null ? token.value.length : void 0) > 0) {\n this.char = this.token.value.charAt(this.charIndex);\n size = this.font.measureTextPlain(this.char);\n lineSpacing = this.lineSpacing;\n if (this.currentLine !== this.line) {\n this.currentLine = this.line;\n this.currentLineHeight = 0;\n }\n this.currentSprite.y = this.object.origin.y + this.object.dstRect.y + this.currentY;\n this.currentSprite.visible = true;\n this.drawLineContent(this.lines[this.line], this.currentSprite.bitmap, this.charIndex + 1);\n this.currentSprite.srcRect.width = this.currentSprite.bitmap.width;\n this.currentLineHeight = this.lines[this.line].height;\n return this.currentX = Math.min(this.lines[this.line].width, this.currentX + size.width);\n }\n };\n\n\n /**\n * Processes the next character/token of the message.\n * @method nextChar\n * @private\n */\n\n Component_MessageTextRenderer.prototype.nextChar = function() {\n var base, base1, results;\n results = [];\n while (true) {\n this.charIndex++;\n this.lineAnimationCount = this.speed;\n if ((this.token.code != null) || this.charIndex >= this.token.value.length) {\n if (typeof (base = this.token).onEnd === \"function\") {\n base.onEnd();\n }\n this.tokenIndex++;\n if (this.tokenIndex >= this.lines[this.line].content.length) {\n this.tokenIndex = 0;\n this.line++;\n this.currentSprite.srcRect.width = this.currentSprite.bitmap.width;\n this.currentSprite = this.sprites[this.line];\n if (this.currentSprite != null) {\n this.currentSprite.x = this.object.origin.x + this.object.dstRect.x;\n }\n if (this.line < this.maxLines) {\n this.currentY += (this.currentLineHeight || this.font.lineHeight) + this.lineSpacing * Graphics.scale;\n this.charIndex = 0;\n this.currentX = 0;\n this.token = this.lines[this.line].content[this.tokenIndex] || new gs.RendererToken(null, \"\");\n }\n } else {\n this.charIndex = 0;\n this.token = this.lines[this.line].content[this.tokenIndex] || new gs.RendererToken(null, \"\");\n }\n if (typeof (base1 = this.token).onStart === \"function\") {\n base1.onStart();\n }\n }\n if (!this.token || this.token.value !== \"\\n\" || !this.lines[this.line]) {\n break;\n } else {\n results.push(void 0);\n }\n }\n return results;\n };\n\n\n /**\n * Finishes the message. Depending on the message configuration, the\n * message text-renderer will now wait for a user-action or a certain amount\n * of time.\n *\n * @method finish\n */\n\n Component_MessageTextRenderer.prototype.finish = function() {\n var ref, ref1, ref2;\n if (this.waitAtEnd) {\n this.isWaiting = true;\n return (ref = this.object.events) != null ? ref.emit(\"messageWaiting\", this) : void 0;\n } else if (this.waitAtEndTime > 0) {\n this.waitCounter = this.waitAtEndTime;\n this.isWaiting = false;\n return (ref1 = this.object.events) != null ? ref1.emit(\"messageWaiting\", this) : void 0;\n } else {\n if ((ref2 = this.object.events) != null) {\n ref2.emit(\"messageWaiting\", this);\n }\n return this[\"continue\"]();\n }\n };\n\n\n /**\n * Returns the position of the caret in pixels. The caret is like an invisible\n * cursor pointing to the x/y coordinates of the last rendered character of\n * the message. That position can be used to display a waiting- or processing-animation for example.\n *\n * @method updateCaretPosition\n */\n\n Component_MessageTextRenderer.prototype.updateCaretPosition = function() {\n this.caretPosition.x = this.currentX + this.padding;\n return this.caretPosition.y = this.currentY + this.currentLineHeight / 2;\n };\n\n\n /**\n * Updates the line writing.\n *\n * @method updateLineWriting\n * @private\n */\n\n Component_MessageTextRenderer.prototype.updateLineWriting = function() {\n if (this.isRunning && !this.isWaiting && !this.waitForKey && this.waitCounter <= 0) {\n if (this.lineAnimationCount <= 0) {\n while (true) {\n if (this.line < this.maxLines) {\n this.nextChar();\n }\n if (this.line >= this.maxLines) {\n this.finish();\n } else {\n this.drawNext();\n }\n if (!((this.token.code || this.lineAnimationCount <= 0 || this.drawImmediately) && !this.waitForKey && this.waitCounter <= 0 && this.isRunning && this.line < this.maxLines)) {\n break;\n }\n }\n }\n if (GameManager.tempSettings.skip) {\n return this.lineAnimationCount = 0;\n } else {\n return this.lineAnimationCount--;\n }\n }\n };\n\n\n /**\n * Updates wait-for-key state. If skipping is enabled, the text renderer will\n * not wait for key press.\n *\n * @method updateWaitForKey\n * @private\n */\n\n Component_MessageTextRenderer.prototype.updateWaitForKey = function() {\n if (this.waitForKey) {\n this.isWaiting = !GameManager.tempSettings.skip;\n return this.waitForKey = this.isWaiting;\n }\n };\n\n\n /**\n * Updates wait counter if the text renderer is waiting for a certain amount of time to pass. If skipping is enabled, the text renderer will\n * not wait for the actual amount of time and sets the wait-counter to 1 frame instead.\n *\n * @method updateWaitForKey\n * @private\n */\n\n Component_MessageTextRenderer.prototype.updateWaitCounter = function() {\n if (this.waitCounter > 0) {\n if (GameManager.tempSettings.skip) {\n this.waitCounter = 1;\n }\n this.isWaiting = true;\n this.waitCounter--;\n if (this.waitCounter <= 0) {\n this.isWaiting = false;\n if (this.line >= this.maxLines) {\n return this[\"continue\"]();\n }\n }\n }\n };\n\n\n /**\n * Creates a token-object for a specified text-code.\n * \n * @method createToken\n * @param {string} code - The code/type of the text-code.\n * @param {string} value - The value of the text-code.\n * @return {Object} The token-object.\n */\n\n Component_MessageTextRenderer.prototype.createToken = function(code, value) {\n var data, i, j, ref, tokenObject;\n tokenObject = null;\n switch (code) {\n case \"CE\":\n data = value.split(\"/\");\n value = data.shift();\n value = isNaN(value) ? value : parseInt(value);\n for (i = j = 0, ref = data; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {\n if (data[i].startsWith('\"') && data[i].endsWith('\"')) {\n data[i] = data[i].substring(1, data[i].length - 1);\n } else {\n data[i] = isNaN(data[i]) ? data[i] : parseFloat(data[i]);\n }\n }\n tokenObject = {\n code: code,\n value: value,\n values: data\n };\n break;\n default:\n tokenObject = Component_MessageTextRenderer.__super__.createToken.call(this, code, value);\n }\n return tokenObject;\n };\n\n\n /**\n * <p>Measures a control-token. If a token produces a visual result like displaying an icon then it must return the size taken by\n * the visual result. If the token has no visual result, <b>null</b> must be returned. This method is called for every token when the message is initialized.</p> \n *\n * <p>This method is not called while the message is running. For that case, see <i>processControlToken</i> method which is called\n * for every token while the message is running.</p>\n *\n * @param {Object} token - A control-token.\n * @return {gs.Size} The size of the area taken by the visual result of the token or <b>null</b> if the token has no visual result.\n * @method analyzeControlToken\n * @protected\n */\n\n Component_MessageTextRenderer.prototype.measureControlToken = function(token) {\n return Component_MessageTextRenderer.__super__.measureControlToken.call(this, token);\n };\n\n\n /**\n * <p>Draws the visual result of a token, like an icon for example, to the specified bitmap. This method is called for every token when the message is initialized and the sprites for each\n * text-line are created.</p> \n *\n * <p>This method is not called while the message is running. For that case, see <i>processControlToken</i> method which is called\n * for every token while the message is running.</p>\n *\n * @param {Object} token - A control-token.\n * @param {gs.Bitmap} bitmap - The bitmap used for the current text-line. Can be used to draw something on it like an icon, etc.\n * @param {number} offset - An x-offset for the draw-routine.\n * @param {number} length - Determines how many characters of the token should be drawn. Can be ignored for tokens\n * not drawing any characters.\n * @method drawControlToken\n * @protected\n */\n\n Component_MessageTextRenderer.prototype.drawControlToken = function(token, bitmap, offset, length) {\n var data, j, len, linkData, results;\n switch (token.code) {\n case \"RT\":\n return Component_MessageTextRenderer.__super__.drawControlToken.call(this, token, bitmap, offset, length);\n case \"SLK\":\n if (token.customData.offsetX == null) {\n token.customData.offsetX = offset;\n }\n if (this.customData.linkData) {\n linkData = this.customData.linkData[this.line];\n if (linkData) {\n results = [];\n for (j = 0, len = linkData.length; j < len; j++) {\n data = linkData[j];\n results.push(this.sprites[this.line].bitmap.clearRect(data.cx, 0, data.width, data.height));\n }\n return results;\n }\n }\n }\n };\n\n\n /**\n * Processes a control-token. A control-token is a token which influences\n * the text-rendering like changing the fonts color, size or style. Changes \n * will be automatically applied to the game object's font.\n *\n * For message text-renderer, a few additional control-tokens like\n * speed-change, waiting, etc. needs to be processed here.\n *\n * This method is called for each token while the message is initialized and\n * also while the message is running. See <i>formattingOnly</i> parameter.\n *\n * @param {Object} token - A control-token.\n * @param {boolean} formattingOnly - If <b>true</b> the message is initializing right now and only \n * format-tokens should be processed which is necessary for the message to calculated sizes correctly.\n * @return {Object} A new token which is processed next or <b>null</b>.\n * @method processControlToken\n * @protected\n */\n\n Component_MessageTextRenderer.prototype.processControlToken = function(token, formattingOnly) {\n var animation, bitmap, character, duration, easing, expression, line, linkData, linkStart, object, params, ref, ref1, result, sound, textTokens, values;\n if (formattingOnly) {\n return Component_MessageTextRenderer.__super__.processControlToken.call(this, token);\n }\n result = null;\n switch (token.code) {\n case \"CR\":\n character = RecordManager.charactersArray.first(function(c) {\n var ref;\n return ((ref = c.name.defaultText) != null ? ref : c.name) === token.value;\n });\n if (character) {\n SceneManager.scene.currentCharacter = character;\n }\n break;\n case \"CE\":\n params = {\n \"values\": token.values\n };\n if ((ref = this.object.events) != null) {\n ref.emit(\"callCommonEvent\", this.object, {\n commonEventId: token.value,\n params: params,\n finish: false,\n waiting: true\n });\n }\n break;\n case \"X\":\n if (typeof token.value === \"function\") {\n token.value(this.object);\n }\n break;\n case \"A\":\n animation = RecordManager.animationsArray.first(function(a) {\n return a.name === token.value;\n });\n if (!animation) {\n animation = RecordManager.animations[token.value];\n }\n if ((animation != null ? animation.graphic.name : void 0) != null) {\n bitmap = ResourceManager.getBitmap(\"Graphics/Pictures/\" + animation.graphic.name);\n object = new gs.Object_Animation(animation);\n this.addCustomObject(object);\n this.currentX += Math.round(bitmap.width / animation.framesX);\n this.currentSprite.srcRect.width += Math.round(bitmap.width / animation.framesX);\n }\n break;\n case \"RT\":\n if (token.rtSize.width > token.rbSize.width) {\n this.currentX += token.rtSize.width;\n this.font.set(this.getRubyTextFont(token));\n } else {\n this.currentX += token.rbSize.width;\n }\n break;\n case \"LK\":\n if (token.value === 'E') {\n object = new ui.Object_Hotspot();\n object.enabled = true;\n object.setup();\n this.addCustomObject(object);\n object.dstRect.x = this.object.dstRect.x + this.object.origin.x + this.customData.linkData.cx;\n object.dstRect.y = this.object.dstRect.y + this.object.origin.y + this.customData.linkData.cy;\n object.dstRect.width = this.currentX - this.customData.linkData.cx;\n object.dstRect.height = this.currentLineHeight;\n object.events.on(\"click\", gs.CallBack(\"onLinkClick\", this), {\n linkData: this.customData.linkData\n }, this);\n } else {\n this.customData.linkData = {\n cx: this.currentX,\n cy: this.currentY,\n commonEventId: token.value,\n tokenIndex: this.tokenIndex\n };\n }\n break;\n case \"SLK\":\n if (token.value === 'E') {\n linkData = this.customData.linkData[this.line].last();\n line = this.lines[this.line].content;\n linkStart = this.findToken(this.tokenIndex - 1, \"SLK\", -1, line);\n textTokens = this.findTokensBetween(linkData.tokenIndex, this.tokenIndex, null, line);\n linkData.cx = linkStart.customData.offsetX;\n linkData.width = this.currentX - linkData.cx + this.padding;\n linkData.height = this.currentSprite.bitmap.height;\n object = new ui.Object_Text();\n object.text = textTokens.select((function(_this) {\n return function(x) {\n return x.value;\n };\n })(this)).join(\"\");\n object.formatting = false;\n object.wordWrap = false;\n object.ui = new ui.Component_UIBehavior();\n object.enabled = true;\n object.addComponent(object.ui);\n object.addComponent(new gs.Component_HotspotBehavior());\n object.behavior.padding.left = 0;\n object.behavior.padding.right = 0;\n object.dstRect.width = linkData.width;\n object.dstRect.height = linkData.height;\n if (linkData.styleIndex === -1) {\n ui.UIManager.addControlStyles(object, [\"hyperlink\"]);\n } else {\n ui.UIManager.addControlStyles(object, [\"hyperlink-\" + linkData.styleIndex]);\n }\n object.setup();\n this.addCustomObject(object);\n object.dstRect.x = this.currentSprite.x + linkData.cx;\n object.dstRect.y = this.object.dstRect.y + this.object.origin.y + linkData.cy;\n object.events.on(\"click\", gs.CallBack(\"onLinkClick\", this), {\n linkData: linkData\n }, this);\n } else {\n if (!this.customData.linkData) {\n this.customData.linkData = [];\n }\n if (!this.customData.linkData[this.line]) {\n this.customData.linkData[this.line] = [];\n }\n if ((ref1 = token.value) != null ? ref1.contains(\",\") : void 0) {\n values = token.value.split(\",\");\n this.customData.linkData[this.line].push({\n cx: this.currentX,\n cy: this.currentY,\n commonEventId: values[0],\n styleIndex: parseInt(values[1]),\n tokenIndex: this.tokenIndex\n });\n } else {\n this.customData.linkData[this.line].push({\n cx: this.currentY,\n cy: this.currentY,\n commonEventId: token.value,\n tokenIndex: this.tokenIndex,\n styleIndex: -1\n });\n }\n }\n break;\n case \"E\":\n expression = RecordManager.characterExpressionsArray.first(function(c) {\n var ref2;\n return ((ref2 = c.name.defaultText) != null ? ref2 : c.name) === token.value;\n });\n if (!expression) {\n expression = RecordManager.characterExpressions[token.value];\n }\n character = SceneManager.scene.currentCharacter;\n if ((expression != null) && ((character != null ? character.index : void 0) != null)) {\n duration = GameManager.defaults.character.expressionDuration;\n easing = gs.Easings.fromObject(GameManager.defaults.character.changeEasing);\n animation = GameManager.defaults.character.changeAnimation;\n object = SceneManager.scene.characters.first(function(c) {\n return c.rid === character.index;\n });\n if (object != null) {\n object.behavior.changeExpression(expression, animation, easing, duration);\n }\n }\n break;\n case \"SP\":\n sound = RecordManager.system.sounds[token.value - 1];\n AudioManager.playSound(sound);\n break;\n case \"S\":\n GameManager.settings.messageSpeed = token.value;\n break;\n case \"W\":\n this.drawImmediately = false;\n if (!GameManager.tempSettings.skip) {\n if (token.value === \"A\") {\n this.waitForKey = true;\n } else {\n this.waitCounter = Math.round(token.value / 1000 * Graphics.frameRate);\n }\n }\n break;\n case \"WE\":\n this.waitAtEnd = token.value === \"Y\";\n break;\n case \"DI\":\n this.drawImmediately = token.value === 1 || token.value === \"Y\";\n break;\n default:\n result = Component_MessageTextRenderer.__super__.processControlToken.call(this, token);\n }\n return result;\n };\n\n\n /**\n * Clears/Resets the text-renderer.\n *\n * @method clear\n */\n\n Component_MessageTextRenderer.prototype.clear = function() {\n var j, len, ref, ref1, ref2, sprite;\n this.charIndex = 0;\n this.currentX = 0;\n this.currentY = 0;\n this.line = 0;\n this.lines = [];\n this.clearCustomObjects();\n if ((ref = this.object.bitmap) != null) {\n ref.clear();\n }\n ref1 = this.allSprites;\n for (j = 0, len = ref1.length; j < len; j++) {\n sprite = ref1[j];\n sprite.dispose();\n if ((ref2 = sprite.bitmap) != null) {\n ref2.dispose();\n }\n }\n this.allSprites = [];\n return null;\n };\n\n\n /**\n * Clears/Disposes all sprites used to display the text-lines/parts.\n *\n * @method clearAllSprites\n */\n\n Component_MessageTextRenderer.prototype.clearAllSprites = function() {\n var j, len, ref, ref1, sprite;\n ref = this.allSprites;\n for (j = 0, len = ref.length; j < len; j++) {\n sprite = ref[j];\n sprite.dispose();\n if ((ref1 = sprite.bitmap) != null) {\n ref1.dispose();\n }\n }\n return null;\n };\n\n\n /**\n * Clears/Disposes the sprites used to display the text-lines/parts of the current/last message.\n *\n * @method clearSprites\n */\n\n Component_MessageTextRenderer.prototype.clearSprites = function() {\n var j, len, ref, ref1, sprite;\n ref = this.sprites;\n for (j = 0, len = ref.length; j < len; j++) {\n sprite = ref[j];\n sprite.dispose();\n if ((ref1 = sprite.bitmap) != null) {\n ref1.dispose();\n }\n }\n return null;\n };\n\n\n /**\n * Removes a game object from the message.\n *\n * @method removeCustomObject\n * @param object {gs.Object_Base} The game object to remove.\n */\n\n Component_MessageTextRenderer.prototype.removeCustomObject = function(object) {\n SceneManager.scene.removeObject(object);\n object.dispose();\n return this.customObjects.remove(object);\n };\n\n\n /**\n * Adds a game object to the message which is alive until the message is\n * erased. Can be used to display animationed-icons, etc. in a message.\n *\n * @method addCustomObject\n * @param object {gs.Object_Base} The game object to add.\n */\n\n Component_MessageTextRenderer.prototype.addCustomObject = function(object) {\n object.dstRect.x = this.object.dstRect.x + this.object.origin.x + this.currentX;\n object.dstRect.y = this.object.dstRect.y + this.object.origin.y + this.currentY;\n object.zIndex = this.object.zIndex + 1;\n object.update();\n SceneManager.scene.addObject(object);\n return this.customObjects.push(object);\n };\n\n\n /**\n * Clears the list of custom game objects. All game objects are disposed and removed\n * from the scene.\n *\n * @method clearCustomObjects\n * @param object {Object} The game object to add.\n */\n\n Component_MessageTextRenderer.prototype.clearCustomObjects = function() {\n var j, len, object, ref;\n ref = this.customObjects;\n for (j = 0, len = ref.length; j < len; j++) {\n object = ref[j];\n object.dispose();\n SceneManager.scene.removeObject(object);\n }\n return this.customObjects = [];\n };\n\n\n /**\n * Creates the bitmap for a specified line-object.\n *\n * @method createBitmap\n * @private\n * @param {Object} line - A line-object.\n * @return {Bitmap} A newly created bitmap containing the line-text.\n */\n\n Component_MessageTextRenderer.prototype.createBitmap = function(line) {\n var bitmap;\n this.font = this.object.font;\n bitmap = new Bitmap(this.object.dstRect.width, Math.max(this.minLineHeight, line.height));\n bitmap.font = this.font;\n return bitmap;\n };\n\n\n /**\n * Draws the line's content on the specified bitmap.\n *\n * @method drawLineContent\n * @protected\n * @param {Object} line - A line-object which should be drawn on the bitmap.\n * @param {gs.Bitmap} bitmap - The bitmap to draw the line's content on.\n * @param {number} length - Determines how many characters of the specified line should be drawn. You can \n * specify -1 to draw all characters.\n */\n\n Component_MessageTextRenderer.prototype.drawLineContent = function(line, bitmap, length) {\n var currentX, drawAll, i, j, len, ref, size, token, value;\n bitmap.clear();\n currentX = this.padding;\n drawAll = length === -1;\n ref = line.content;\n for (i = j = 0, len = ref.length; j < len; i = ++j) {\n token = ref[i];\n if (i > this.tokenIndex && !drawAll) {\n break;\n }\n if (token.code != null) {\n size = this.measureControlToken(token, bitmap);\n this.drawControlToken(token, bitmap, currentX);\n if (size) {\n currentX += size.width;\n }\n this.processControlToken(token, true, line);\n } else if (token.value.length > 0) {\n token.applyFormat(this.font);\n value = token.value;\n if (!drawAll && this.tokenIndex === i && value.length > length) {\n value = value.substring(0, length);\n }\n if (value !== \"\\n\") {\n size = this.font.measureTextPlain(value);\n bitmap.drawText(currentX, line.height - (size.height - this.font.descent) - line.descent, size.width, bitmap.height, value, 0, 0);\n currentX += size.width;\n }\n }\n }\n return line.contentWidth = currentX + this.font.measureTextPlain(\" \").width;\n };\n\n\n /**\n * Creates the sprite for a specified line-object.\n *\n * @method createSprite\n * @private\n * @param {Object} line - A line-object.\n * @return {Sprite} A newly created sprite object containing the line-text as bitmap.\n */\n\n Component_MessageTextRenderer.prototype.createSprite = function(line) {\n var bitmap, sprite;\n bitmap = this.createBitmap(line);\n this.currentX = 0;\n this.waitCounter = 0;\n this.waitForKey = false;\n sprite = new Sprite(Graphics.viewport);\n sprite.bitmap = bitmap;\n sprite.visible = true;\n sprite.z = this.object.zIndex + 1;\n sprite.srcRect = new Rect(0, 0, 0, bitmap.height);\n return sprite;\n };\n\n\n /**\n * Creates the sprites for a specified array of line-objects.\n *\n * @method createSprites\n * @private\n * @see gs.Component_MessageTextRenderer.createSprite.\n * @param {Array} lines - An array of line-objects.\n * @return {Array} An array of sprites.\n */\n\n Component_MessageTextRenderer.prototype.createSprites = function(lines) {\n var i, j, len, line, result, sprite;\n this.fontSize = this.object.font.size;\n result = [];\n for (i = j = 0, len = lines.length; j < len; i = ++j) {\n line = lines[i];\n sprite = this.createSprite(line);\n result.push(sprite);\n }\n return result;\n };\n\n\n /**\n * Starts a new line.\n *\n * @method newLine\n */\n\n Component_MessageTextRenderer.prototype.newLine = function() {\n this.currentX = 0;\n return this.currentY += this.currentLineHeight + this.lineSpacing;\n };\n\n\n /**\n * Displays a formatted text immediately without any delays or animations. The\n * Component_TextRenderer.drawFormattedText method from the base-class cannot\n * be used here because it would render to the game object's bitmap object while\n * this method is rendering to the sprites.\n *\n * @method drawFormattedTextImmediately\n * @param {number} x - The x-coordinate of the text's position.\n * @param {number} y - The y-coordinate of the text's position.\n * @param {number} width - Deprecated. Can be null.\n * @param {number} height - Deprecated. Can be null.\n * @param {string} text - The text to draw.\n * @param {boolean} wordWrap - If wordWrap is set to true, line-breaks are automatically created.\n */\n\n Component_MessageTextRenderer.prototype.drawFormattedTextImmediately = function(x, y, width, height, text, wordWrap) {\n this.drawFormattedText(x, y, width, height, text, wordWrap);\n while (true) {\n this.nextChar();\n if (this.line >= this.maxLines) {\n this.isRunning = false;\n } else {\n this.drawNext();\n }\n if (!this.isRunning) {\n break;\n }\n }\n this.currentY += this.currentLineHeight + this.lineSpacing;\n return null;\n };\n\n\n /**\n * Starts the rendering-process for the message.\n *\n * @method drawFormattedText\n * @param {number} x - The x-coordinate of the text's position.\n * @param {number} y - The y-coordinate of the text's position.\n * @param {number} width - Deprecated. Can be null.\n * @param {number} height - Deprecated. Can be null.\n * @param {string} text - The text to draw.\n * @param {boolean} wordWrap - If wordWrap is set to true, line-breaks are automatically created.\n */\n\n Component_MessageTextRenderer.prototype.drawFormattedText = function(x, y, width, height, text, wordWrap) {\n var currentX, ref;\n text = text || \" \";\n this.font.set(this.object.font);\n this.speed = 11 - Math.round(GameManager.settings.messageSpeed * 2.5);\n this.isRunning = true;\n this.drawImmediately = false;\n this.lineAnimationCount = this.speed;\n this.currentLineHeight = 0;\n this.isWaiting = false;\n this.waitForKey = false;\n this.charIndex = 0;\n this.token = null;\n this.tokenIndex = 0;\n this.message = text;\n this.line = 0;\n this.currentLine = this.line;\n currentX = this.currentX;\n this.lines = this.calculateLines(lcsm(this.message), wordWrap, this.currentX);\n this.sprites = this.createSprites(this.lines);\n this.allSprites = this.allSprites.concat(this.sprites);\n this.currentX = currentX;\n this.currentSprite = this.sprites[this.line];\n this.currentSprite.x = this.currentX + this.object.origin.x + this.object.dstRect.x;\n this.maxLines = this.calculateMaxLines(this.lines);\n this.token = ((ref = this.lines[this.line]) != null ? ref.content[this.tokenIndex] : void 0) || new gs.RendererToken(null, \"\");\n return this.start();\n };\n\n\n /**\n * Starts the message-rendering process.\n *\n * @method start\n * @protected\n */\n\n Component_MessageTextRenderer.prototype.start = function() {\n var ref;\n if (GameManager.tempSettings.skip && GameManager.tempSettings.skipTime === 0) {\n return this.instantSkip();\n } else if (this.maxLines === 0) {\n if (((ref = this.lines[0]) != null ? ref.content : void 0) === \"\") {\n return this.finish();\n } else {\n this.maxLines = 1;\n return this.drawNext();\n }\n } else {\n return this.drawNext();\n }\n };\n\n\n /**\n * Skips the current message and finishes the message-processing immediately. The message\n * tokens are processed but not rendered.\n *\n * @method instantSkip\n */\n\n Component_MessageTextRenderer.prototype.instantSkip = function() {\n var ref;\n while (true) {\n if (this.line < this.maxLines) {\n this.nextChar();\n }\n if (this.line >= this.maxLines) {\n break;\n } else {\n this.processToken();\n }\n if (!(this.isRunning && this.line < this.maxLines)) {\n break;\n }\n }\n if ((ref = this.object.events) != null) {\n ref.emit(\"messageWaiting\", this);\n }\n return this[\"continue\"]();\n };\n\n\n /**\n * Processes the current token.\n *\n * @method processToken\n */\n\n Component_MessageTextRenderer.prototype.processToken = function() {\n var base, token;\n token = null;\n if (this.token.code != null) {\n token = this.processControlToken(this.token, false);\n if (token != null) {\n this.token = token;\n if (typeof (base = this.token).onStart === \"function\") {\n base.onStart();\n }\n }\n } else {\n token = this.token;\n }\n return token;\n };\n\n return Component_MessageTextRenderer;\n\n})(gs.Component_TextRenderer);\n\ngs.Component_MessageTextRenderer = Component_MessageTextRenderer;\n\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU9BLElBQUEsNkJBQUE7RUFBQTs7O0FBQU07OztFQUNGLDZCQUFDLENBQUEsb0JBQUQsR0FBd0IsQ0FBQyxhQUFELEVBQWdCLGtCQUFoQjs7O0FBQ3hCOzs7Ozs7Ozs7MENBUUEsbUJBQUEsR0FBcUIsU0FBQyxJQUFELEVBQU8sT0FBUDtBQUNqQixRQUFBO0lBQUEsSUFBQyxDQUFBLGtCQUFELENBQUE7SUFDQSxDQUFBLEdBQUk7QUFFSjtBQUFBLFNBQUEscUNBQUE7O01BQ0ksSUFBRyxJQUFDLENBQUEsTUFBTSxDQUFDLFFBQVEsQ0FBQyxpQkFBcEI7UUFDSSxJQUFDLENBQUEsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFiLEdBQXlCLElBQUEsRUFBRSxDQUFDLEtBQUgsQ0FBUyxPQUFPLENBQUMsU0FBUyxDQUFDLFNBQTNCLEVBRDdCOztNQUVBLElBQUMsQ0FBQSxLQUFELEdBQVMsSUFBQyxDQUFBLGNBQUQsQ0FBZ0IsSUFBQSxDQUFLLE9BQU8sQ0FBQyxJQUFiLENBQWhCLEVBQW9DLElBQXBDLEVBQXlDLENBQXpDO0FBQ1Q7QUFBQSxXQUFBLHdDQUFBOztRQUNJLE1BQUEsR0FBUyxJQUFDLENBQUEsWUFBRCxDQUFjLElBQWQ7UUFDVCxJQUFHLElBQUEsS0FBUSxJQUFDLENBQUEsSUFBWjtVQUNJLElBQUMsQ0FBQSxlQUFELENBQWlCLElBQWpCLEVBQXVCLE1BQXZCLEVBQStCLElBQUMsQ0FBQSxTQUFELEdBQVcsQ0FBMUMsRUFESjtTQUFBLE1BQUE7VUFHSSxJQUFDLENBQUEsZUFBRCxDQUFpQixJQUFqQixFQUF1QixNQUF2QixFQUErQixDQUFDLENBQWhDLEVBSEo7O1FBSUEsSUFBQyxDQUFBLFVBQVcsQ0FBQSxDQUFBLENBQUUsQ0FBQyxNQUFmLEdBQXdCO1FBQ3hCLENBQUE7QUFQSjtBQUpKO0FBY0E7QUFBQSxTQUFBLHdDQUFBOztNQUNJLFlBQVksQ0FB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QSxHQUFjLFNBQUE7QUFDVixRQUFBO0lBQUEsS0FBQSxHQUFRO0lBRVIsSUFBRyx1QkFBSDtNQUNJLEtBQUEsR0FBUSxJQUFDLENBQUEsbUJBQUQsQ0FBcUIsSUFBQyxDQUFBLEtBQXRCLEVBQTZCLEtBQTdCO01BQ1IsSUFBRyxhQUFIO1FBQ0ksSUFBQyxDQUFBLEtBQUQsR0FBUzs7Y0FDSCxDQUFDO1NBRlg7T0FGSjtLQUFBLE1BQUE7TUFNSSxLQUFBLEdBQVEsSUFBQyxDQUFBLE1BTmI7O0FBUUEsV0FBTztFQVhHOzs7O0dBeHNDMEIsRUFBRSxDQUFDOztBQXV0Qy9DLEVBQUUsQ0FBQyw2QkFBSCxHQUFtQyIsInNvdXJjZXNDb250ZW50IjpbIiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuI1xuIyAgIFNjcmlwdDogQ29tcG9uZW50X01lc3NhZ2VUZXh0UmVuZGVyZXJcbiNcbiMgICAkJENPUFlSSUdIVCQkXG4jXG4jID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbmNsYXNzIENvbXBvbmVudF9NZXNzYWdlVGV4dFJlbmRlcmVyIGV4dGVuZHMgZ3MuQ29tcG9uZW50X1RleHRSZW5kZXJlclxuICAgIEBvYmplY3RDb2RlY0JsYWNrTGlzdCA9IFtcIm9uTGlua0NsaWNrXCIsIFwib25CYXRjaERpc2FwcGVhclwiXVxuICAgICMjIypcbiAgICAqIENhbGxlZCBpZiB0aGlzIG9iamVjdCBpbnN0YW5jZSBpcyByZXN0b3JlZCBmcm9tIGEgZGF0YS1idW5kbGUuIEl0IGNhbiBiZSB1c2VkXG4gICAgKiByZS1hc3NpZ24gZXZlbnQtaGFuZGxlciwgYW5vbnltb3VzIGZ1bmN0aW9ucywgZXRjLlxuICAgICogeFxuICAgICogQG1ldGhvZCBvbkRhdGFCdW5kbGVSZXN0b3JlLlxuICAgICogQHBhcmFtIE9iamVjdCBkYXRhIC0gVGhlIGRhdGEtYnVuZGxlXG4gICAgKiBAcGFyYW0gZ3MuT2JqZWN0Q29kZWNDb250ZXh0IGNvbnRleHQgLSBUaGUgY29kZWMtY29udGV4dC5cbiAgICAjIyNcbiAgICBvbkRhdGFCdW5kbGVSZXN0b3JlOiAoZGF0YSwgY29udGV4dCkgLT5cbiAgICAgICAgQHNldHVwRXZlbnRIYW5kbGVycygpXG4gICAgICAgIGwgPSAwXG4gICAgICAgIFxuICAgICAgICBmb3IgbWVzc2FnZSBpbiBAb2JqZWN0Lm1lc3NhZ2VzXG4gICAgICAgICAgICBpZiBAb2JqZWN0LnNldHRpbmdzLnVzZUNoYXJhY3RlckNvbG9yXG4gICAgICAgICAgICAgICAgQG9iamVjdC5mb250LmNvbG9yID0gbmV3IGdzLkNvbG9yKG1lc3NhZ2UuY2hhcmFjdGVyLnRleHRDb2xvcilcbiAgICAgICAgICAgIEBsaW5lcyA9IEBjYWxjdWxhdGVMaW5lcyhsY3NtKG1lc3NhZ2UudGV4dCksIHllcywgMClcbiAgICAgICAgICAgIGZvciBsaW5lIGluIEBsaW5lc1xuICAgICAgICAgICAgICAgIGJpdG1hcCA9IEBjcmVhdGVCaXRtYXAobGluZSlcbiAgICAgICAgICAgICAgICBpZiBsaW5lID09IEBsaW5lXG4gICAgICAgICAgICAgICAgICAgIEBkcmF3TGluZUNvbnRlbnQobGluZSwgYml0bWFwLCBAY2hhckluZGV4KzEpXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICBAZHJhd0xpbmVDb250ZW50KGxpbmUsIGJpdG1hcCwgLTEpXG4gICAgICAgICAgICAgICAgQGFsbFNwcml0ZXNbbF0uYml0bWFwID0gYml0bWFwXG4gICAgICAgICAgICAgICAgbCsrXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgXG4gICAgICAgIGZvciBjdXN0b21PYmplY3QgaW4gQGN1c3RvbU9iamVjdHNcbiAgICAgICAgICAgIFNjZW5lTWFuYWdlci5zY2VuZS5hZGRPYmplY3QoY3VzdG9tT2JqZWN0KVxuICAgICAgICAgICAgICAgIFxuICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICBcbiAgICAjIyMqXG4gICAgKiAgQSB0ZXh0LXJlbmRlcmVyIGNvbXBvbmVudCB0byByZW5kZXIgYW4gYW5pbWF0ZWQgYW5kIGludGVyYWN0aXZlIG1lc3NhZ2UgdGV4dCB1c2luZ1xuICAgICogIGRpbWVuc2lvbnMgb2YgdGhlIGdhbWUgb2JqZWN0J3MgZGVzdGluYXRpb24tcmVjdGFuZ2xlLiBUaGUgbWVzc2FnZSBpcyBkaXNwbGF5ZWRcbiAgICAqICB1c2luZyBhIHNwcml0ZSBmb3IgZWFjaCBsaW5lIGluc3RlYWQgb2YgZHJhd2luZyB0byB0aGUgZ2FtZSBvYmplY3QncyBiaXRtYXAgb2JqZWN0LlxuICAgICpcbiAgICAqICBAbW9kdWxlIGdzXG4gICAgKiAgQGNsYXNzIENvbXBvbmVudF9NZXNzYWdlVGV4dFJlbmRlcmVyXG4gICAgKiAgQGV4dGVuZHMgZ3MuQ29tcG9uZW50X1RleHRSZW5kZXJlclxuICAgICogIEBtZW1iZXJvZiBnc1xuICAgICogIEBjb25zdHJ1Y3RvclxuICAgICMjI1xuICAgIGNvbnN0cnVjdG9yOiAtPlxuICAgICAgICBzdXBlclxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIEFuIGFycmF5IGNvbnRhaW5pbmcgYWxsIHNwcml0ZXMgb2YgdGhlIGN1cnJlbnQgbWVzc2FnZS5cbiAgICAgICAgKiBAcHJvcGVydHkgc3ByaXRlc1xuICAgICAgICAqIEB0eXBlIGdzLlNwcml0ZVtdXG4gICAgICAgICogQHByb3RlY3RlZFxuICAgICAgICAjIyNcbiAgICAgICAgQHNwcml0ZXMgPSBbXVxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIEFuIGFycmF5IGNvbnRhaW5pbmcgYWxsIHNwcml0ZXMgb2YgYWxsIG1lc3NhZ2VzLiBJbiBOVkwgbW9kZVxuICAgICAgICAqIGEgcGFnZSBjYW4gY29udGFpbiBtdWx0aXBsZSBtZXNzYWdlcy5cbiAgICAgICAgKiBAcHJvcGVydHkgYWxsU3ByaXRlc1xuICAgICAgICAqIEB0eXBlIGdzLlNwcml0ZVtdXG4gICAgICAgICogQHByb3RlY3RlZFxuICAgICAgICAjIyNcbiAgICAgICAgQGFsbFNwcml0ZXMgPSBbXVxuICAgICAgICAjIyMqXG4gICAgICAgICogQW4gYXJyYXkgY29udGFpbmluZyBhbGwgbGluZS1vYmplY3RzIG9mIHRoZSBjdXJyZW50IG1lc3NhZ2UuXG4gICAgICAgICogQHByb3BlcnR5IGxpbmVzXG4gICAgICAgICogQHR5cGUgZ3MuVGV4dFJlbmRlcmVyTGluZVtdXG4gICAgICAgICogQHJlYWRPbmx5XG4gICAgICAgICMjI1xuICAgICAgICBAbGluZXMgPSBudWxsXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogVGhlIGxpbmUgY3VycmVudGx5IHJlbmRlcmVkLlxuICAgICAgICAqIEBwcm9wZXJ0eSBsaW5lXG4gICAgICAgICogQHR5cGUgbnVtYmVyXG4gICAgICAgICogQHJlYWRPbmx5XG4gICAgICAgICMjI1xuICAgICAgICBAbGluZSA9IDBcbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBUaGUgbGVmdCBhbmQgcmlnaHQgcGFkZGluZyBwZXIgbGluZS5cbiAgICAgICAgKiBAcHJvcGVydHkgcGFkZGluZ1xuICAgICAgICAqIEB0eXBlIG51bWJlclxuICAgICAgICAjIyNcbiAgICAgICAgQHBhZGRpbmcgPSA2XG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogVGhlIG1pbmltdW0gaGVpZ2h0IG9mIHRoZSBsaW5lIGN1cnJlbnRseSByZW5kZXJlZC4gSWYgMCwgdGhlIG1lYXN1cmVkXG4gICAgICAgICogaGVpZ2h0IG9mIHRoZSBsaW5lIHdpbGwgYmUgdXNlZC5cbiAgICAgICAgKiBAcHJvcGVydHkgbWluTGluZUhlaWdodFxuICAgICAgICAqIEB0eXBlIG51bWJlclxuICAgICAgICAjIyNcbiAgICAgICAgQG1pbkxpbmVIZWlnaHQgPSAwXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogVGhlIHNwYWNpbmcgYmV0d2VlbiB0ZXh0IGxpbmVzIGluIHBpeGVscy5cbiAgICAgICAgKiBAcHJvcGVydHkgbGluZVNwYWNpbmdcbiAgICAgICAgKiBAdHlwZSBudW1iZXJcbiAgICAgICAgIyMjXG4gICAgICAgIEBsaW5lU3BhY2luZyA9IDJcbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBUaGUgbGluZSBjdXJyZW50bHkgcmVuZGVyZWQuXG4gICAgICAgICogQHByb3BlcnR5IGN1cnJlbnRMaW5lXG4gICAgICAgICogQHR5cGUgbnVtYmVyXG4gICAgICAgICogQHByb3RlY3RlZFxuICAgICAgICAjIyNcbiAgICAgICAgQGN1cnJlbnRMaW5lID0gMFxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIFRoZSBoZWlnaHQgb2YgdGhlIGxpbmUgY3VycmVudGx5IHJlbmRlcmVkLlxuICAgICAgICAqIEBwcm9wZXJ0eSBjdXJyZW50TGluZUhlaWdodFxuICAgICAgICAqIEB0eXBlIG51bWJlclxuICAgICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgICAgIyMjXG4gICAgICAgIEBjdXJyZW50TGluZUhlaWdodCA9IDBcbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBJbmRleCBvZiB0aGUgY3VycmVudCBjaGFyYWN0ZXIgdG8gZHJhdy5cbiAgICAgICAgKiBAcHJvcGVydHkgY2hhckluZGV4XG4gICAgICAgICogQHR5cGUgbnVtYmVyXG4gICAgICAgICogQHJlYWRPbmx5XG4gICAgICAgICMjI1xuICAgICAgICBAY2hhckluZGV4ID0gMFxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIFBvc2l0aW9uIG9mIHRoZSBtZXNzYWdlIGNhcmV0LiBUaGUgY2FyZXQgaXMgbGlrZSBhbiBpbnZpc2libGVcbiAgICAgICAgKiBjdXJzb3IgcG9pbnRpbmcgdG8gdGhlIHgveSBjb29yZGluYXRlcyBvZiB0aGUgbGFzdCByZW5kZXJlZCBjaGFyYWN0ZXIgb2ZcbiAgICAgICAgKiB0aGUgbWVzc2FnZS4gVGhhdCBwb3NpdGlvbiBjYW4gYmUgdXNlZCB0byBkaXNwbGF5IGEgd2FpdGluZy0gb3IgcHJvY2Vzc2luZy1hbmltYXRpb24gZm9yIGV4YW1wbGUuXG4gICAgICAgICogQHByb3BlcnR5IGNhcmV0UG9zaXRpb25cbiAgICAgICAgKiBAdHlwZSBncy5Qb2ludFxuICAgICAgICAqIEByZWFkT25seVxuICAgICAgICAjIyNcbiAgICAgICAgQGNhcmV0UG9zaXRpb24gPSBuZXcgZ3MuUG9pbnQoKVxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIEluZGljYXRlcyB0aGF0IHRoZSBhIG1lc3NhZ2UgaXMgY3VycmVudGx5IGluIHByb2dyZXNzLlxuICAgICAgICAqIEBwcm9wZXJ0eSBpc1J1bm5pbmdcbiAgICAgICAgKiBAdHlwZSBib29sZWFuXG4gICAgICAgICogQHJlYWRPbmx5XG4gICAgICAgICMjI1xuICAgICAgICBAaXNSdW5uaW5nID0gbm9cbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBUaGUgY3VycmVudCB4LWNvb3JkaW5hdGUgb2YgdGhlIGNhcmV0L2N1cnNvci5cbiAgICAgICAgKiBAcHJvcGVydHkgY3VycmVudFhcbiAgICAgICAgKiBAdHlwZSBudW1iZXJcbiAgICAgICAgKiBAcmVhZE9ubHlcbiAgICAgICAgIyMjXG4gICAgICAgIEBjdXJyZW50WCA9IDBcbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBUaGUgY3VycmVudCB5LWNvb3JkaW5hdGUgb2YgdGhlIGNhcmV0L2N1cnNvci5cbiAgICAgICAgKiBAcHJvcGVydHkgY3VycmVudFlcbiAgICAgICAgKiBAdHlwZSBudW1iZXJcbiAgICAgICAgKiBAcmVhZE9ubHlcbiAgICAgICAgIyMjXG4gICAgICAgIEBjdXJyZW50WSA9IDBcbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBUaGUgY3VycmVudCBzcHJpdGVzIHVzZWQgdG8gZGlzcGxheSB0aGUgY3VycmVudCB0ZXh0LWxpbmUvcGFydC5cbiAgICAgICAgKiBAcHJvcGVydHkgY3VycmVudFNwcml0ZVxuICAgICAgICAqIEB0eXBlIGdzLlNwcml0ZVxuICAgICAgICAqIEByZWFkT25seVxuICAgICAgICAjIyNcbiAgICAgICAgQGN1cnJlbnRTcHJpdGUgPSBudWxsXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogSW5kaWNhdGVzIGlmIHRoZSBtZXNzYWdlLXJlbmRlcmVyIGlzIGN1cnJlbnRseSB3YWl0aW5nIGxpa2UgZm9yIGEgdXNlci1hY3Rpb24uXG4gICAgICAgICogQHByb3BlcnR5IGlzV2FpdGluZ1xuICAgICAgICAqIEB0eXBlIGJvb2xlYW5cbiAgICAgICAgKiBAcmVhZE9ubHlcbiAgICAgICAgIyMjXG4gICAgICAgIEBpc1dhaXRpbmcgPSBub1xuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIEluZGljYXRlcyBpZiB0aGUgbWVzc2FnZS1yZW5kZXJlciBpcyBjdXJyZW50bHkgd2FpdGluZyBmb3IgYSBrZXktcHJlc3Mgb3IgbW91c2UvdG91Y2ggYWN0aW9uLlxuICAgICAgICAqIEBwcm9wZXJ0eSB3YWl0Rm9yS2V5XG4gICAgICAgICogQHR5cGUgYm9vbGVhblxuICAgICAgICAqIEByZWFkT25seVxuICAgICAgICAjIyNcbiAgICAgICAgQHdhaXRGb3JLZXkgPSBub1xuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIE51bWJlciBvZiBmcmFtZXMgdGhlIG1lc3NhZ2UtcmVuZGVyZXIgc2hvdWxkIHdhaXQgYmVmb3JlIGNvbnRpbnVlLlxuICAgICAgICAqIEBwcm9wZXJ0eSB3YWl0Q291bnRlclxuICAgICAgICAqIEB0eXBlIG51bWJlclxuICAgICAgICAjIyNcbiAgICAgICAgQHdhaXRDb3VudGVyID0gMFxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIFNwZWVkIG9mIHRoZSBtZXNzYWdlLWRyYXdpbmcuIFRoZSBzbWFsbGVyIHRoZSB2YWx1ZSwgdGhlIGZhc3RlciB0aGUgbWVzc2FnZSBpcyBkaXNwbGF5ZWQuXG4gICAgICAgICogQHByb3BlcnR5IHNwZWVkXG4gICAgICAgICogQHR5cGUgbnVtYmVyXG4gICAgICAgICMjI1xuICAgICAgICBAc3BlZWQgPSAxXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogSW5kaWNhdGVzIGlmIHRoZSBtZXNzYWdlIHNob3VsZCBiZSByZW5kZXJlZCBpbW1lZGlhbHRlbHkgd2l0aG91dCBhbnkgYW5pbWF0aW9uIG9yIGRlbGF5LlxuICAgICAgICAqIEBwcm9wZXJ0eSBkcmF3SW1tZWRpYXRlbHlcbiAgICAgICAgKiBAdHlwZSBib29sZWFuXG4gICAgICAgICMjI1xuICAgICAgICBAZHJhd0ltbWVkaWF0ZWx5ID0gbm9cbiAgICAgICAgXG4gICAgICAgICMjIypcbiAgICAgICAgKiBJbmRpY2F0ZXMgaWYgdGhlIG1lc3NhZ2Ugc2hvdWxkIHdhaXQgZm9yIGEgdXNlci1hY3Rpb24gb3IgYSBjZXJ0YWluIGFtb3VudCBvZiB0aW1lXG4gICAgICAgICogYmVmb3JlIGZpbmlzaGluZy5cbiAgICAgICAgKiBAcHJvcGVydHkgd2FpdEF0RW5kXG4gICAgICAgICogQHR5cGUgYm9vbGVhblxuICAgICAgICAjIyNcbiAgICAgICAgQHdhaXRBdEVuZCA9IHllc1xuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIFRoZSBudW1iZXIgb2YgZnJhbWVzIHRvIHdhaXQgYmVmb3JlIGZpbmlzaGluZyBhIG1lc3NhZ2UuXG4gICAgICAgICogYmVmb3JlIGZpbmlzaGluZy5cbiAgICAgICAgKiBAcHJvcGVydHkgd2FpdEF0RW5kVGltZVxuICAgICAgICAqIEB0eXBlIG51bWJlclxuICAgICAgICAjIyNcbiAgICAgICAgQHdhaXRBdEVuZFRpbWUgPSAwXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogSW5kaWNhdGVzIGlmIGF1dG8gd29yZC13cmFwIHNob3VsZCBiZSB1c2VkLiBEZWZhdWx0IGlzIDxiPnRydWU8L2I+XG4gICAgICAgICogQHByb3BlcnR5IHdvcmRXcmFwXG4gICAgICAgICogQHR5cGUgYm9vbGVhblxuICAgICAgICAjIyNcbiAgICAgICAgQHdvcmRXcmFwID0geWVzXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogQ3VzdG9tIGdhbWUgb2JqZWN0cyB3aGljaCBhcmUgYWxpdmUgdW50aWwgdGhlIGN1cnJlbnQgbWVzc2FnZSBpcyBlcmFzZWQuIENhbiBiZSB1c2VkIHRvIGRpc3BsYXlcbiAgICAgICAgKiBhbmltYXRlZCBpY29ucywgZXRjLlxuICAgICAgICAqIEBwcm9wZXJ0eSBjdXN0b21PYmplY3RzXG4gICAgICAgICogQHR5cGUgZ3MuT2JqZWN0X0Jhc2VbXVxuICAgICAgICAjIyNcbiAgICAgICAgQGN1c3RvbU9iamVjdHMgPSBbXVxuICAgICAgICBcbiAgICAgICAgIyMjKlxuICAgICAgICAqIEEgaGFzaHRhYmxlL2RpY3Rpb25hcnkgb2JqZWN0IHRvIHN0b3JlIGN1c3RvbS1kYXRhIHVzZWZ1bCBsaWtlIGZvciB0b2tlbi1wcm9jZXNzaW5nLiBUaGUgZGF0YSBtdXN0IGJlXG4gICAgICAgICogc2VyaWFsaXphYmxlLlxuICAgICAgICAqIEBwcm9wZXJ0eSBjdXN0b21PYmplY3RzXG4gICAgICAgICogQHR5cGUgT2JqZWN0XG4gICAgICAgICMjI1xuICAgICAgICBAY3VzdG9tRGF0YSA9IHt9XG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogQSBjYWxsYmFjayBmdW5jdGlvbiBjYWxsZWQgaWYgdGhlIHBsYXllciBjbGlja3Mgb24gYSBub24tc3R5bGFibGUgbGluayAoTEsgdGV4dC1jb2RlKSB0byB0cmlnZ2VyXG4gICAgICAgICogdGhlIHNwZWNpZmllZCBjb21tb24gZXZlbnQuXG4gICAgICAgICogQHByb3BlcnR5IG9uTGlua0NsaWNrXG4gICAgICAgICogQHR5cGUgRnVuY3Rpb25cbiAgICAgICAgIyMjXG4gICAgICAgIEBvbkxpbmtDbGljayA9IChlKSAtPlxuICAgICAgICAgICAgZXZlbnRJZCA9IGUuZGF0YS5saW5rRGF0YS5jb21tb25FdmVudElkXG4gICAgICAgICAgICBldmVudCA9IFJlY29yZE1hbmFnZXIuY29tbW9uRXZlbnRzW2V2ZW50SWRdXG4gICAgICAgICAgICBpZiAhZXZlbnRcbiAgICAgICAgICAgICAgICBldmVudCA9IFJlY29yZE1hbmFnZXIuY29tbW9uRXZlbnRzLmZpcnN0ICh4KSA9PiB4Lm5hbWUgPT0gZXZlbnRJZFxuICAgICAgICAgICAgICAgIGV2ZW50SWQgPSBldmVudC5pbmRleCBpZiBldmVudFxuICAgICAgICAgICAgaWYgIWV2ZW50XG4gICAgICAgICAgICAgICAgU2NlbmVNYW5hZ2VyLnNjZW5lLmludGVycHJldGVyLmp1bXBUb0xhYmVsKGV2ZW50SWQpXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgU2NlbmVNYW5hZ2VyLnNjZW5lLmludGVycHJldGVyLmNhbGxDb21tb25FdmVudChldmVudElkLCBudWxsLCB5ZXMpXG4gICAgICAgIFxuICAgICAgICAjIyMqXG4gICAgICAgICogQSBjYWxsYmFjayBmdW5jdGlvbiBjYWxsZWQgaWYgYSBiYXRjaGVkIG1lc3NzYWdlIGhhcyBiZWVuIGZhZGVkIG91dC4gSXQgdHJpZ2dlcnMgdGhlIGV4ZWN1dGlvbiBvZlxuICAgICAgICAqIHRoZSBuZXh0IG1lc3NhZ2UuXG4gICAgICAgICogQHByb3BlcnR5IG9uQmF0Y2hEaXNhcHBlYXJcbiAgICAgICAgKiBAdHlwZSBGdW5jdGlvblxuICAgICAgICAjIyMgICAgXG4gICAgICAgIEBvbkJhdGNoRGlzYXBwZWFyID0gKGUpID0+IFxuICAgICAgICAgICAgQGRyYXdJbW1lZGlhdGVseSA9IG5vXG4gICAgICAgICAgICBAaXNXYWl0aW5nID0gbm9cbiAgICAgICAgICAgIEBvYmplY3Qub3BhY2l0eSA9IDI1NVxuICAgICAgICAgICAgQGV4ZWN1dGVCYXRjaCgpIFxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAjIyMqXG4gICAgKiBTZXJpYWxpemVzIHRoZSBtZXNzYWdlIHRleHQtcmVuZGVyZXIgaW50byBhIGRhdGEtYnVuZGxlLlxuICAgICogQG1ldGhvZCB0b0RhdGFCdW5kbGVcbiAgICAqIEByZXR1cm4ge09iamVjdH0gQSBkYXRhLWJ1bmRsZS5cbiAgICAjIyNcbiAgICB0b0RhdGFCdW5kbGU6IC0+XG4gICAgICAgIGlnbm9yZSA9IFtcIm9iamVjdFwiLCBcImZvbnRcIiwgXCJzcHJpdGVzXCIsIFwiYWxsU3ByaXRlc1wiLCBcImN1cnJlbnRTcHJpdGVcIiwgXCJjdXJyZW50WFwiXVxuICAgICAgICBidW5kbGUgPSB7IGN1cnJlbnRTcHJpdGVJbmRleDogQHNwcml0ZXMuaW5kZXhPZihAY3VycmVudFNwcml0ZSkgfVxuICAgICAgICBcbiAgICAgICAgZm9yIGsgb2YgdGhpc1xuICAgICAgICAgICAgaWYgaWdub3JlLmluZGV4T2YoaykgPT0gLTFcbiAgICAgICAgICAgICAgICBidW5kbGVba10gPSB0aGlzW2tdXG4gICAgICAgICAgICAgICAgXG4gICAgICAgIHJldHVybiBidW5kbGVcbiAgICAgXG4gICAgXG4gICAgICAgICAgICBcbiAgICAjIyMqXG4gICAgKiBEaXNwb3NlcyB0aGUgbWVzc2FnZSB0ZXh0LXJlbmRlcmVyIGFuZCBhbGwgc3ByaXRlcyB1c2VkIHRvIGRpc3BsYXlcbiAgICAqIHRoZSBtZXNzYWdlLlxuICAgICogQG1ldGhvZCBkaXNwb3NlXG4gICAgIyMjXG4gICAgZGlzcG9zZTogLT5cbiAgICAgICAgc3VwZXJcbiAgICAgICAgXG4gICAgICAgIEBkaXNwb3NlRXZlbnRIYW5kbGVycygpXG4gICAgICAgIFxuICAgICAgICBmb3Igc3ByaXRlIGluIEBhbGxTcHJpdGVzXG4gICAgICAgICAgICBzcHJpdGUuYml0bWFwPy5kaXNwb3NlKClcbiAgICAgICAgICAgIHNwcml0ZS5kaXNwb3NlKClcbiAgICAgXG4gICAgIyMjKlxuICAgICogUmVtb3ZlcyBhbGwgYXR0YWNoZWQgZXZlbnQgaGFuZGxlcnMgXG4gICAgKiB0aGUgbWVzc2FnZS5cbiAgICAqIEBtZXRob2QgZGlzcG9zZUV2ZW50SGFuZGxlcnNcbiAgICAjIyMgICAgICAgXG4gICAgZGlzcG9zZUV2ZW50SGFuZGxlcnM6IC0+XG4gICAgICAgIGdzLkdsb2JhbEV2ZW50TWFuYWdlci5vZmZCeU93bmVyKFwibW91c2VVcFwiLCBAb2JqZWN0KVxuICAgICAgICBncy5HbG9iYWxFdmVudE1hbmFnZXIub2ZmQnlPd25lcihcImtleVVwXCIsIEBvYmplY3QpXG4gICAgXG4gICAgIyMjKlxuICAgICogQWRkcyBldmVudC1oYW5kbGVycyBmb3IgbW91c2UvdG91Y2ggZXZlbnRzXG4gICAgKlxuICAgICogQG1ldGhvZCBzZXR1cEV2ZW50SGFuZGxlcnNcbiAgICAjIyMgXG4gICAgc2V0dXBFdmVudEhhbmRsZXJzOiAtPlxuICAgICAgICBncy5HbG9iYWxFdmVudE1hbmFnZXIub2ZmQnlPd25lcihcIm1vdXNlVXBcIiwgQG9iamVjdClcbiAgICAgICAgZ3MuR2xvYmFsRXZlbnRNYW5hZ2VyLm9mZkJ5T3duZXIoXCJrZXlVcFwiLCBAb2JqZWN0KVxuICAgICAgICBcbiAgICAgICAgZ3MuR2xvYmFsRXZlbnRNYW5hZ2VyLm9uIFwibW91c2VVcFwiLCAoKGUpID0+XG4gICAgICAgICAgICByZXR1cm4gaWYgQG9iamVjdC5maW5kQ29tcG9uZW50QnlOYW1lKFwiYW5pbWF0aW9uXCIpIG9yIChHYW1lTWFuYWdlci5zZXR0aW5ncy5hdXRvTWVzc2FnZS5lbmFibGVkIGFuZCAhR2FtZU1hbmFnZXIuc2V0dGluZ3MuYXV0b01lc3NhZ2Uuc3RvcE9uQWN0aW9uKVxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgI2lmIEBvYmplY3QuZHN0UmVjdC5jb250YWlucyhJbnB1dC5Nb3VzZS54IC0gQG9iamVjdC5vcmlnaW4ueCwgSW5wdXQuTW91c2UueSAtIEBvYmplY3Qub3JpZ2luLnkpXG4gICAgICAgICAgICBpZiBAaXNXYWl0aW5nIGFuZCBub3QgKEB3YWl0Q291bnRlciA+IDAgb3IgQHdhaXRGb3JLZXkpXG4gICAgICAgICAgICAgICAgZS5icmVha0NoYWluID0geWVzXG4gICAgICAgICAgICAgICAgQGNvbnRpbnVlKClcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICBlLmJyZWFrQ2hhaW4gPSBAaXNSdW5uaW5nXG4gICAgICAgICAgICAgICAgQGRyYXdJbW1lZGlhdGVseSA9ICFAd2FpdEZvcktleVxuICAgICAgICAgICAgICAgIEB3YWl0Q291bnRlciA9IDBcbiAgICAgICAgICAgICAgICBAd2FpdEZvcktleSA9IG5vXG4gICAgICAgICAgICAgICAgQGlzV2FpdGluZyA9IG5vXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiBAd2FpdEZvcktleVxuICAgICAgICAgICAgICAgIGlmIElucHV0Lk1vdXNlLmJ1dHRvbnNbSW5wdXQuTW91c2UuTEVGVF0gPT0gMlxuICAgICAgICAgICAgICAgICAgICBlLmJyZWFrQ2hhaW4gPSB5ZXNcbiAgICAgICAgICAgICAgICAgICAgSW5wdXQuY2xlYXIoKVxuICAgICAgICAgICAgICAgICAgICBAd2FpdEZvcktleSA9IG5vXG4gICAgICAgICAgICAgICAgICAgIEBpc1dhaXRpbmcgPSBub1xuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgKSwgbnVsbCwgQG9iamVjdFxuICAgICAgICBcbiAgICAgICAgZ3MuR2xvYmFsRXZlbnRNYW5hZ2VyLm9uIFwia2V5VXBcIiwgKChlKSA9PlxuICAgICAgICAgICAgaWYgSW5wdXQua2V5c1tJbnB1dC5DXSBhbmQgKCFAaXNXYWl0aW5nIG9yIChAd2FpdENvdW50ZXIgPiAwIG9yIEB3YWl0Rm9yS2V5KSlcbiAgICAgICAgICAgICAgICBAZHJhd0ltbWVkaWF0ZWx5ID0gIUB3YWl0Rm9yS2V5XG4gICAgICAgICAgICAgICAgQHdhaXRDb3VudGVyID0gMFxuICAgICAgICAgICAgICAgIEB3YWl0Rm9yS2V5ID0gbm9cbiAgICAgICAgICAgICAgICBAaXNXYWl0aW5nID0gbm9cbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIGlmIEBpc1dhaXRpbmcgYW5kICFAd2FpdEZvcktleSBhbmQgIUB3YWl0Q291bnRlciBhbmQgSW5wdXQua2V5c1tJbnB1dC5DXVxuICAgICAgICAgICAgICAgIEBjb250aW51ZSgpXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiBAd2FpdEZvcktleVxuICAgICAgICAgICAgICAgIGlmIElucHV0LmtleXNbSW5wdXQuQ11cbiAgICAgICAgICAgICAgICAgICAgSW5wdXQuY2xlYXIoKVxuICAgICAgICAgICAgICAgICAgICBAd2FpdEZvcktleSA9IG5vXG4gICAgICAgICAgICAgICAgICAgIEBpc1dhaXRpbmcgPSBub1xuICAgICAgICAgICAgICAgIFxuICAgICAgICApLCBudWxsLCBAb2JqZWN0XG4gICAgICAgIFxuICAgICMjIypcbiAgICAqIFNldHMgdXAgdGhlIHJlbmRlcmVyLiBSZWdpc3RlcnMgbmVjZXNzYXJ5IGV2ZW50IGhhbmRsZXJzLlxuICAgICogQG1ldGhvZCBzZXR1cFxuICAgICMjIyBcbiAgICBzZXR1cDogLT5cbiAgICAgICAgQHNldHVwRXZlbnRIYW5kbGVycygpXG4gICAgICAgIFxuICAgICMjIypcbiAgICAqIFJlc3RvcmVzIHRoZSBtZXNzYWdlIHRleHQtcmVuZGVyZXIncyBzdGF0ZSBmcm9tIGEgZGF0YS1idW5kbGUuXG4gICAgKiBAbWV0aG9kIHJlc3RvcmVcbiAgICAqIEBwYXJhbSB7T2JqZWN0fSBidW5kbGUgLSBBIGRhdGEtYnVuZGxlIGNvbnRhaW5pbmcgbWVzc2FnZSB0ZXh0LXJlbmRlcmVyIHN0YXRlLlxuICAgICMjI1xuICAgIHJlc3RvcmU6IChidW5kbGUpIC0+XG4gICAgICAgIGZvciBrIG9mIGJ1bmRsZVxuICAgICAgICAgICAgaWYgayA9PSBcImN1cnJlbnRTcHJpdGVJbmRleFwiXG4gICAgICAgICAgICAgICAgQGN1cnJlbnRTcHJpdGUgPSBAc3ByaXRlc1tidW5kbGUuY3VycmVudFNwcml0ZUluZGV4XVxuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIHRoaXNba10gPSBidW5kbGVba11cbiAgICAgICAgXG4gICAgICAgIGlmIEBzcHJpdGVzLmxlbmd0aCA+IDBcbiAgICAgICAgICAgIEBjdXJyZW50WSA9IEBzcHJpdGVzLmxhc3QoKS55IC0gQG9iamVjdC5vcmlnaW4ueSAtIEBvYmplY3QuZHN0UmVjdC55XG4gICAgICAgICAgICBAbGluZSA9IEBtYXhMaW5lc1xuICAgICAgICAgICAgQGlzV2FpdGluZyA9IEBpc1dhaXRpbmcgfHwgQGlzUnVubmluZ1xuICAgICAgICAgICAgXG4gICAgICAgIHJldHVybiBudWxsICAgIFxuICAgIFxuICAgIFxuICAgICMjIypcbiAgICAqIENvbnRpbnVlcyBtZXNzYWdlLXByb2Nlc3NpbmcgaWYgY3VycmVudGx5IHdhaXRpbmcuXG4gICAgKiBAbWV0aG9kIGNvbnRpbnVlXG4gICAgIyMjXG4gICAgY29udGludWU6IC0+IFxuICAgICAgICBAaXNXYWl0aW5nID0gbm9cbiAgIFxuICAgICAgICBpZiBAbGluZSA+PSBAbGluZXMubGVuZ3RoXG4gICAgICAgICAgICBAaXNSdW5uaW5nID0gbm9cbiAgICAgICAgICAgIEBvYmplY3QuZXZlbnRzPy5lbWl0KFwibWVzc2FnZUZpbmlzaFwiLCB0aGlzKVxuICAgICAgICBlbHNlXG4gICAgICAgICAgICBAb2JqZWN0LmV2ZW50cz8uZW1pdChcIm1lc3NhZ2VCYXRjaFwiLCB0aGlzKVxuICAgICAgICAgICAgZmFkaW5nID0gR2FtZU1hbmFnZXIudGVtcFNldHRpbmdzLm1lc3NhZ2VGYWRpbmdcbiAgICAgICAgICAgIGR1cmF0aW9uID0gaWYgR2FtZU1hbmFnZXIudGVtcFNldHRpbmdzLnNraXAgdGhlbiAwIGVsc2UgZmFkaW5nLmR1cmF0aW9uXG4gICAgICAgICAgICBAb2JqZWN0LmFuaW1hdG9yLmRpc2FwcGVhcihmYWRpbmcuYW5pbWF0aW9uLCBmYWRpbmcuZWFzaW5nLCBkdXJhdGlvbiwgZ3MuQ2FsbEJhY2soXCJvbkJhdGNoRGlzYXBwZWFyXCIsIHRoaXMpKVxuICAgICAgICAgICAgXG4gICAgIyMjKlxuICAgICogVXBkYXRlcyB0aGUgdGV4dC1yZW5kZXJlci5cbiAgICAqIEBtZXRob2QgdXBkYXRlXG4gICAgIyMjXG4gICAgdXBkYXRlOiAtPlxuICAgICAgICBmb3Igc3ByaXRlIGluIEBhbGxTcHJpdGVzXG4gICAgICAgICAgICBzcHJpdGUub3BhY2l0eSA9IEBvYmplY3Qub3BhY2l0eVxuICAgICAgICAgICAgc3ByaXRlLnZpc2libGUgPSBAb2JqZWN0LnZpc2libGVcbiAgICAgICAgICAgIHNwcml0ZS5veCA9IC1Ab2JqZWN0Lm9mZnNldC54XG4gICAgICAgICAgICBzcHJpdGUub3kgPSAtQG9iamVjdC5vZmZzZXQueVxuICAgICAgICAgICAgc3ByaXRlLm1hc2sudmFsdWUgPSBAb2JqZWN0Lm1hc2sudmFsdWVcbiAgICAgICAgICAgIHNwcml0ZS5tYXNrLnZhZ3VlID0gQG9iamVjdC5tYXNrLnZhZ3VlXG4gICAgICAgICAgICBzcHJpdGUubWFzay5zb3VyY2UgPSBAb2JqZWN0Lm1hc2suc291cmNlXG4gICAgICAgICAgICBzcHJpdGUubWFzay50eXBlID0gQG9iamVjdC5tYXNrLnR5cGVcbiAgICBcbiAgICAgICAgZm9yIG9iamVjdCBpbiBAY3VzdG9tT2JqZWN0c1xuICAgICAgICAgICAgb2JqZWN0Lm9wYWNpdHkgPSBAb2JqZWN0Lm9wYWNpdHlcbiAgICAgICAgICAgIG9iamVjdC52aXNpYmxlID0gQG9iamVjdC52aXNpYmxlXG4gICAgICAgICAgICBcbiAgICAgICAgaWYgbm90IEBpc1J1bm5pbmcgYW5kIEB3YWl0Q291bnRlciA+IDBcbiAgICAgICAgICAgIEB3YWl0Q291bnRlci0tXG4gICAgICAgICAgICBpZiBAd2FpdENvdW50ZXIgPT0gMFxuICAgICAgICAgICAgICAgIEBjb250aW51ZSgpXG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgICAgICBcbiAgICAgICAgaWYgQG9iamVjdC52aXNpYmxlIGFuZCBAbGluZXM/Lmxlbmd0aCA+IDBcbiAgICAgICAgICAgIEB1cGRhdGVMaW5lV3JpdGluZygpXG4gICAgICAgICAgICBAdXBkYXRlV2FpdEZvcktleSgpXG4gICAgICAgICAgICBAdXBkYXRlV2FpdENvdW50ZXIoKVxuICAgICAgICAgICAgQHVwZGF0ZUNhcmV0UG9zaXRpb24oKVxuICAgICAgICBcbiAgICAgXG4gICAgIyMjKlxuICAgICogSW5kaWNhdGVzIGlmIGl0cyBhIGJhdGNoZWQgbWVzc2FnZXMuXG4gICAgKlxuICAgICogQG1ldGhvZCBpc0JhdGNoZWRcbiAgICAqIEByZXR1cm4gSWYgPGI+dHJ1ZTwvYj4gaXQgaXMgYSBiYXRjaGVkIG1lc3NhZ2UuIE90aGVyd2lzZSA8Yj5mYWxzZTwvYj4uXG4gICAgIyMjXG4gICAgaXNCYXRjaGVkOiAtPiBAbGluZXMubGVuZ3RoID4gQG1heExpbmVzXG4gICAgXG4gICAgIyMjKlxuICAgICogSW5kaWNhdGVzIGlmIHRoZSBiYXRjaCBpcyBzdGlsbCBpbiBwcm9ncmVzcyBhbmQgbm90IGRvbmUuXG4gICAgKlxuICAgICogQG1ldGhvZCBpc0JhdGNoSW5Qcm9ncmVzc1xuICAgICogQHJldHVybiBJZiA8Yj50cnVlPC9iPiB0aGUgYmF0Y2hlZCBtZXNzYWdlIGlzIHN0aWxsIG5vdCBkb25lLiBPdGhlcndpc2UgPGI+ZmFsc2U8L2I+XG4gICAgIyMjXG4gICAgaXNCYXRjaEluUHJvZ3Jlc3M6IC0+IEBsaW5lcy5sZW5ndGggLSBAbGluZSA+IEBtYXhMaW5lc1xuICAgIFxuICAgICMjIypcbiAgICAqIFN0YXJ0cyBkaXNwbGF5aW5nIHRoZSBuZXh0IHBhZ2Ugb2YgdGV4dCBpZiBhIG1lc3NhZ2UgaXMgdG9vIGxvbmcgdG8gZml0XG4gICAgKiBpbnRvIG9uZSBtZXNzYWdlIGJveC5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGV4ZWN1dGVCYXRjaFxuICAgICMjIyBcbiAgICBleGVjdXRlQmF0Y2g6IC0+XG4gICAgICAgIEBjbGVhckFsbFNwcml0ZXMoKVxuICAgICAgICBAbGluZXMgPSBAbGluZXMuc2xpY2UoQGxpbmUpXG4gICAgICAgIEBsaW5lID0gMFxuICAgICAgICBAY3VycmVudFggPSAwXG4gICAgICAgIEBjdXJyZW50WSA9IDAgIFxuICAgICAgICBAY3VycmVudExpbmVIZWlnaHQgPSAwXG4gICAgICAgIEB0b2tlbkluZGV4ID0gMFxuICAgICAgICBAY2hhckluZGV4ID0gMFxuICAgICAgICBAdG9rZW4gPSBAbGluZXNbQGxpbmVdLmNvbnRlbnRbQHRva2VuSW5kZXhdIHx8IG5ldyBncy5SZW5kZXJlclRva2VuKG51bGwsIFwiXCIpO1xuICAgICAgICBAbWF4TGluZXMgPSBAY2FsY3VsYXRlTWF4TGluZXMoQGxpbmVzKVxuICAgICAgICBAbGluZUFuaW1hdGlvbkNvdW50ID0gQHNwZWVkXG4gICAgICAgIEBzcHJpdGVzID0gQGNyZWF0ZVNwcml0ZXMoQGxpbmVzKVxuICAgICAgICBAYWxsU3ByaXRlcyA9IEBhbGxTcHJpdGVzLmNvbmNhdChAc3ByaXRlcylcbiAgICAgICAgQGN1cnJlbnRTcHJpdGUgPSBAc3ByaXRlc1tAbGluZV1cbiAgICAgICAgQGN1cnJlbnRTcHJpdGUueCA9IEBjdXJyZW50WCArIEBvYmplY3Qub3JpZ2luLnggKyBAb2JqZWN0LmRzdFJlY3QueFxuICAgICAgICBAZHJhd05leHQoKVxuICAgIFxuICAgICMjIypcbiAgICAqIENhbGN1bGF0ZXMgdGhlIGR1cmF0aW9uKGluIGZyYW1lcykgdGhlIG1lc3NhZ2UtcmVuZGVyZXIgbmVlZHMgdG8gZGlzcGxheVxuICAgICogdGhlIG1lc3NhZ2UuXG4gICAgKlxuICAgICogQG1ldGhvZCBjYWxjdWxhdGVEdXJhdGlvblxuICAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgZHVyYXRpb24gaW4gZnJhbWVzLlxuICAgICMjIyAgICBcbiAgICBjYWxjdWxhdGVEdXJhdGlvbjogLT5cbiAgICAgICAgZHVyYXRpb24gPSAwXG4gICAgICAgIFxuICAgICAgICBpZiBAbGluZXM/XG4gICAgICAgICAgICBmb3IgbGluZSBpbiBAbGluZXNcbiAgICAgICAgICAgICAgICBmb3IgdG9rZW4gaW4gbGluZS5jb250ZW50XG4gICAgICAgICAgICAgICAgICAgIGlmIHRva2VuP1xuICAgICAgICAgICAgICAgICAgICAgICAgZHVyYXRpb24gKz0gQGNhbGN1bGF0ZUR1cmF0aW9uRm9yVG9rZW4odG9rZW4pXG4gICAgICAgIHJldHVybiBkdXJhdGlvblxuICAgIFxuICAgICMjIypcbiAgICAqIENhbGN1bGF0ZXMgdGhlIGR1cmF0aW9uKGluIGZyYW1lcykgdGhlIG1lc3NhZ2UtcmVuZGVyZXIgbmVlZHMgdG8gZGlzcGxheVxuICAgICogdGhlIHNwZWNpZmllZCBsaW5lLlxuICAgICpcbiAgICAqIEBtZXRob2QgY2FsY3VsYXRlRHVyYXRpb25Gb3JMaW5lXG4gICAgKiBAcGFyYW0ge2dzLlJlbmRlcmVyVGV4dExpbmV9IGxpbmUgVGhlIGxpbmUgdG8gY2FsY3VsYXRlIHRoZSBkdXJhdGlvbiBmb3IuXG4gICAgKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSBkdXJhdGlvbiBpbiBmcmFtZXMuXG4gICAgIyMjICAgICAgXG4gICAgY2FsY3VsYXRlRHVyYXRpb25Gb3JMaW5lOiAobGluZSkgLT5cbiAgICAgICAgZHVyYXRpb24gPSAwXG4gICAgICAgIFxuICAgICAgICBpZiBsaW5lXG4gICAgICAgICAgICBmb3IgdG9rZW4gaW4gbGluZS5jb250ZW50XG4gICAgICAgICAgICAgICAgaWYgdG9rZW4/XG4gICAgICAgICAgICAgICAgICAgIGR1cmF0aW9uICs9IEBjYWxjdWxhdGVEdXJhdGlvbkZvclRva2VuKHRva2VuKVxuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgIHJldHVybiBkdXJhdGlvblxuICAgICBcbiAgICAjIyMqXG4gICAgKiBDYWxjdWxhdGVzIHRoZSBkdXJhdGlvbihpbiBmcmFtZXMpIHRoZSBtZXNzYWdlLXJlbmRlcmVyIG5lZWRzIHRvIHByb2Nlc3NcbiAgICAqIHRoZSBzcGVjaWZpZWQgdG9rZW4uXG4gICAgKlxuICAgICogQG1ldGhvZCBjYWxjdWxhdGVEdXJhdGlvbkZvclRva2VuXG4gICAgKiBAcGFyYW0ge3N0cmluZ3xPYmplY3R9IHRva2VuIC0gVGhlIHRva2VuLlxuICAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgZHVyYXRpb24gaW4gZnJhbWVzLlxuICAgICMjIyAgICAgICAgICAgICAgICAgICAgXG4gICAgY2FsY3VsYXRlRHVyYXRpb25Gb3JUb2tlbjogKHRva2VuKSAtPlxuICAgICAgICBkdXJhdGlvbiA9IDBcbiAgICAgICAgXG4gICAgICAgIGlmIHRva2VuLmNvZGU/XG4gICAgICAgICAgICBzd2l0Y2ggdG9rZW4uY29kZVxuICAgICAgICAgICAgICAgIHdoZW4gXCJXXCJcbiAgICAgICAgICAgICAgICAgICAgaWYgdG9rZW4udmFsdWUgIT0gXCJBXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGR1cmF0aW9uID0gdG9rZW4udmFsdWUgLyAxMDAwICogR3JhcGhpY3MuZnJhbWVSYXRlXG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGR1cmF0aW9uID0gdG9rZW4udmFsdWUubGVuZ3RoICogQHNwZWVkXG4gICAgICAgICAgICAgICAgICAgIFxuICAgICAgICByZXR1cm4gZHVyYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICMjIypcbiAgICAqIENhbGN1bGF0ZXMgdGhlIG1heGltdW0gb2YgbGluZXMgd2hpY2ggY2FuIGJlIGRpc3BsYXllZCBpbiBvbmUgbWVzc2FnZS5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGNhbGN1bGF0ZU1heExpbmVzXG4gICAgKiBAcGFyYW0ge0FycmF5fSBsaW5lcyAtIEFuIGFycmF5IG9mIGxpbmUtb2JqZWN0cy5cbiAgICAqIEByZXR1cm4ge251bWJlcn0gVGhlIG51bWJlciBvZiBkaXNwbGF5YWJsZSBsaW5lcy5cbiAgICAjIyNcbiAgICBjYWxjdWxhdGVNYXhMaW5lczogKGxpbmVzKSAtPlxuICAgICAgICBoZWlnaHQgPSAwXG4gICAgICAgIHJlc3VsdCA9IDBcbiAgICAgICAgXG4gICAgICAgIGZvciBsaW5lIGluIGxpbmVzXG4gICAgICAgICAgICAgICAgaGVpZ2h0ICs9IGxpbmUuaGVpZ2h0ICsgQGxpbmVTcGFjaW5nXG4gICAgICAgICAgICAgICAgaWYgQGN1cnJlbnRZK2hlaWdodCA+IChAb2JqZWN0LmRzdFJlY3QuaGVpZ2h0KVxuICAgICAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICAgIHJlc3VsdCsrXG4gICAgIFxuICAgICAgICByZXR1cm4gTWF0aC5taW4obGluZXMubGVuZ3RoLCByZXN1bHQgfHwgMSlcbiAgICBcbiAgICAjIyMqXG4gICAgKiBEaXNwbGF5cyB0aGUgY2hhcmFjdGVyIG9yIHByb2Nlc3NlcyB0aGUgbmV4dCBjb250cm9sLXRva2VuLlxuICAgICpcbiAgICAqIEBtZXRob2QgZHJhd05leHRcbiAgICAjIyNcbiAgICBkcmF3TmV4dDogLT5cbiAgICAgICAgdG9rZW4gPSBAcHJvY2Vzc1Rva2VuKClcbiAgICAgICAgICAgIFxuICAgICAgICBpZiB0b2tlbj8udmFsdWUubGVuZ3RoID4gMFxuICAgICAgICAgICAgQGNoYXIgPSBAdG9rZW4udmFsdWUuY2hhckF0KEBjaGFySW5kZXgpXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIHNpemUgPSBAZm9udC5tZWFzdXJlVGV4dFBsYWluKEBjaGFyKSAgXG4gICAgICAgICAgICBsaW5lU3BhY2luZyA9IEBsaW5lU3BhY2luZ1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiBAY3VycmVudExpbmUgIT0gQGxpbmVcbiAgICAgICAgICAgICAgICBAY3VycmVudExpbmUgPSBAbGluZVxuICAgICAgICAgICAgICAgIyBAY3VycmVudFkgKz0gQGN1cnJlbnRMaW5lSGVpZ2h0ICsgbGluZVNwYWNpbmcgKiBHcmFwaGljcy5zY2FsZVxuICAgICAgICAgICAgICAgIEBjdXJyZW50TGluZUhlaWdodCA9IDBcblxuICAgICAgICAgICAgQGN1cnJlbnRTcHJpdGUueSA9IEBvYmplY3Qub3JpZ2luLnkgKyBAb2JqZWN0LmRzdFJlY3QueSArIEBjdXJyZW50WVxuICAgICAgICAgICAgQGN1cnJlbnRTcHJpdGUudmlzaWJsZSA9IHllc1xuICAgICAgICAgICAgQGRyYXdMaW5lQ29udGVudChAbGluZXNbQGxpbmVdLCBAY3VycmVudFNwcml0ZS5iaXRtYXAsIEBjaGFySW5kZXgrMSlcbiAgICAgICAgICAgIEBjdXJyZW50U3ByaXRlLnNyY1JlY3Qud2lkdGggPSBAY3VycmVudFNwcml0ZS5iaXRtYXAud2lkdGggI01hdGgubWluKEBjdXJyZW50U3ByaXRlLnNyY1JlY3Qud2lkdGggKyBzaXplLndpZHRoLCBAY3VycmVudFNwcml0ZS5iaXRtYXAud2lkdGgpXG4gICAgICAgIFxuICAgICAgICAgICAgQGN1cnJlbnRMaW5lSGVpZ2h0ID0gQGxpbmVzW0BsaW5lXS5oZWlnaHRcbiAgICAgICAgICAgIEBjdXJyZW50WCA9IE1hdGgubWluKEBsaW5lc1tAbGluZV0ud2lkdGgsIEBjdXJyZW50WCArIHNpemUud2lkdGgpXG4gICAgICAgICAgICBcbiAgICAjIyMqXG4gICAgKiBQcm9jZXNzZXMgdGhlIG5leHQgY2hhcmFjdGVyL3Rva2VuIG9mIHRoZSBtZXNzYWdlLlxuICAgICogQG1ldGhvZCBuZXh0Q2hhclxuICAgICogQHByaXZhdGVcbiAgICAjIyNcbiAgICBuZXh0Q2hhcjogLT5cbiAgICAgICAgbG9vcFxuICAgICAgICAgICAgQGNoYXJJbmRleCsrXG4gICAgICAgICAgICBAbGluZUFuaW1hdGlvbkNvdW50ID0gQHNwZWVkXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmIEB0b2tlbi5jb2RlPyBvciBAY2hhckluZGV4ID49IEB0b2tlbi52YWx1ZS5sZW5ndGhcbiAgICAgICAgICAgICAgICBAdG9rZW4ub25FbmQ/KClcbiAgICAgICAgICAgICAgICBAdG9rZW5JbmRleCsrXG4gICAgICAgICAgICAgICAgaWYgQHRva2VuSW5kZXggPj0gQGxpbmVzW0BsaW5lXS5jb250ZW50Lmxlbmd0aFxuICAgICAgICAgICAgICAgICAgICBAdG9rZW5JbmRleCA9IDBcbiAgICAgICAgICAgICAgICAgICAgQGxpbmUrK1xuICAgICAgICAgICAgICAgICAgICBAY3VycmVudFNwcml0ZS5zcmNSZWN0LndpZHRoID0gQGN1cnJlbnRTcHJpdGUuYml0bWFwLndpZHRoXG4gICAgICAgICAgICAgICAgICAgIEBjdXJyZW50U3ByaXRlID0gQHNwcml0ZXNbQGxpbmVdXG4gICAgICAgICAgICAgICAgICAgIGlmIEBjdXJyZW50U3ByaXRlP1xuICAgICAgICAgICAgICAgICAgICAgICAgQGN1cnJlbnRTcHJpdGUueCA9IEBvYmplY3Qub3JpZ2luLnggKyBAb2JqZWN0LmRzdFJlY3QueFxuICAgICAgICAgICAgICAgICAgICBpZiBAbGluZSA8IEBtYXhMaW5lc1xuICAgICAgICAgICAgICAgICAgICAgICAgQGN1cnJlbnRZICs9IChAY3VycmVudExpbmVIZWlnaHQgfHwgQGZvbnQubGluZUhlaWdodCkgKyBAbGluZVNwYWNpbmcgKiBHcmFwaGljcy5zY2FsZVxuICAgICAgICAgICAgICAgICAgICAgICAgQGNoYXJJbmRleCA9IDBcbiAgICAgICAgICAgICAgICAgICAgICAgIEBjdXJyZW50WCA9IDBcbiAgICAgICAgICAgICAgICAgICAgICAgIEB0b2tlbiA9IEBsaW5lc1tAbGluZV0uY29udGVudFtAdG9rZW5JbmRleF0gfHwgbmV3IGdzLlJlbmRlcmVyVG9rZW4obnVsbCwgXCJcIilcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIEBjaGFySW5kZXggPSAwXG4gICAgICAgICAgICAgICAgICAgIEB0b2tlbiA9IEBsaW5lc1tAbGluZV0uY29udGVudFtAdG9rZW5JbmRleF0gfHwgbmV3IGdzLlJlbmRlcmVyVG9rZW4obnVsbCwgXCJcIilcbiAgICAgICAgICAgICAgICBAdG9rZW4ub25TdGFydD8oKVxuXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmICFAdG9rZW4gb3IgQHRva2VuLnZhbHVlICE9IFwiXFxuXCIgb3IgIUBsaW5lc1tAbGluZV1cbiAgICAgICAgICAgICAgICBicmVha1xuICAgICMjIypcbiAgICAqIEZpbmlzaGVzIHRoZSBtZXNzYWdlLiBEZXBlbmRpbmcgb24gdGhlIG1lc3NhZ2UgY29uZmlndXJhdGlvbiwgdGhlXG4gICAgKiBtZXNzYWdlIHRleHQtcmVuZGVyZXIgd2lsbCBub3cgd2FpdCBmb3IgYSB1c2VyLWFjdGlvbiBvciBhIGNlcnRhaW4gYW1vdW50XG4gICAgKiBvZiB0aW1lLlxuICAgICpcbiAgICAqIEBtZXRob2QgZmluaXNoXG4gICAgIyMjXG4gICAgZmluaXNoOiAtPlxuICAgICAgICBpZiBAd2FpdEF0RW5kXG4gICAgICAgICAgICBAaXNXYWl0aW5nID0geWVzXG4gICAgICAgICAgICBAb2JqZWN0LmV2ZW50cz8uZW1pdChcIm1lc3NhZ2VXYWl0aW5nXCIsIHRoaXMpXG4gICAgICAgIGVsc2UgaWYgQHdhaXRBdEVuZFRpbWUgPiAwXG4gICAgICAgICAgICBAd2FpdENvdW50ZXIgPSBAd2FpdEF0RW5kVGltZVxuICAgICAgICAgICAgQGlzV2FpdGluZyA9IG5vXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIEBvYmplY3QuZXZlbnRzPy5lbWl0KFwibWVzc2FnZVdhaXRpbmdcIiwgdGhpcylcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgQG9iamVjdC5ldmVudHM/LmVtaXQoXCJtZXNzYWdlV2FpdGluZ1wiLCB0aGlzKVxuICAgICAgICAgICAgQGNvbnRpbnVlKClcbiAgICBcbiAgICAjIyMqXG4gICAgKiBSZXR1cm5zIHRoZSBwb3NpdGlvbiBvZiB0aGUgY2FyZXQgaW4gcGl4ZWxzLiBUaGUgY2FyZXQgaXMgbGlrZSBhbiBpbnZpc2libGVcbiAgICAqIGN1cnNvciBwb2ludGluZyB0byB0aGUgeC95IGNvb3JkaW5hdGVzIG9mIHRoZSBsYXN0IHJlbmRlcmVkIGNoYXJhY3RlciBvZlxuICAgICogdGhlIG1lc3NhZ2UuIFRoYXQgcG9zaXRpb24gY2FuIGJlIHVzZWQgdG8gZGlzcGxheSBhIHdhaXRpbmctIG9yIHByb2Nlc3NpbmctYW5pbWF0aW9uIGZvciBleGFtcGxlLlxuICAgICpcbiAgICAqIEBtZXRob2QgdXBkYXRlQ2FyZXRQb3NpdGlvblxuICAgICMjI1xuICAgIHVwZGF0ZUNhcmV0UG9zaXRpb246IC0+IFxuICAgICAgICBAY2FyZXRQb3NpdGlvbi54ID0gQGN1cnJlbnRYICsgQHBhZGRpbmcgICBcbiAgICAgICAgQGNhcmV0UG9zaXRpb24ueSA9IEBjdXJyZW50WSArIEBjdXJyZW50TGluZUhlaWdodC8yXG4gICAgICAgIFxuICAgICMjIypcbiAgICAqIFVwZGF0ZXMgdGhlIGxpbmUgd3JpdGluZy5cbiAgICAqXG4gICAgKiBAbWV0aG9kIHVwZGF0ZUxpbmVXcml0aW5nXG4gICAgKiBAcHJpdmF0ZVxuICAgICMjI1xuICAgIHVwZGF0ZUxpbmVXcml0aW5nOiAtPlxuICAgICAgICBpZiBAaXNSdW5uaW5nIGFuZCAhQGlzV2FpdGluZyBhbmQgIUB3YWl0Rm9yS2V5IGFuZCBAd2FpdENvdW50ZXIgPD0gMFxuICAgICAgICAgICAgaWYgQGxpbmVBbmltYXRpb25Db3VudCA8PSAwXG4gICAgICAgICAgICAgICAgbG9vcFxuICAgICAgICAgICAgICAgICAgICBpZiBAbGluZSA8IEBtYXhMaW5lc1xuICAgICAgICAgICAgICAgICAgICAgICAgQG5leHRDaGFyKClcbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBpZiBAbGluZSA+PSBAbWF4TGluZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIEBmaW5pc2goKVxuICAgICAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBAZHJhd05leHQoKVxuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrIHVubGVzcyAoQHRva2VuLmNvZGUgb3IgQGxpbmVBbmltYXRpb25Db3VudCA8PSAwIG9yIEBkcmF3SW1tZWRpYXRlbHkpIGFuZCAhQHdhaXRGb3JLZXkgYW5kIEB3YWl0Q291bnRlciA8PSAwIGFuZCBAaXNSdW5uaW5nIGFuZCBAbGluZSA8IEBtYXhMaW5lc1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiBHYW1lTWFuYWdlci50ZW1wU2V0dGluZ3Muc2tpcFxuICAgICAgICAgICAgICAgIEBsaW5lQW5pbWF0aW9uQ291bnQgPSAwXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgQGxpbmVBbmltYXRpb25Db3VudC0tXG4gICAgXG4gICAgIyMjKlxuICAgICogVXBkYXRlcyB3YWl0LWZvci1rZXkgc3RhdGUuIElmIHNraXBwaW5nIGlzIGVuYWJsZWQsIHRoZSB0ZXh0IHJlbmRlcmVyIHdpbGxcbiAgICAqIG5vdCB3YWl0IGZvciBrZXkgcHJlc3MuXG4gICAgKlxuICAgICogQG1ldGhvZCB1cGRhdGVXYWl0Rm9yS2V5XG4gICAgKiBAcHJpdmF0ZVxuICAgICMjI1xuICAgIHVwZGF0ZVdhaXRGb3JLZXk6IC0+XG4gICAgICAgIGlmIEB3YWl0Rm9yS2V5XG4gICAgICAgICAgICBAaXNXYWl0aW5nID0gIUdhbWVNYW5hZ2VyLnRlbXBTZXR0aW5ncy5za2lwXG4gICAgICAgICAgICBAd2FpdEZvcktleSA9IEBpc1dhaXRpbmdcbiAgICAgXG4gICAgIyMjKlxuICAgICogVXBkYXRlcyB3YWl0IGNvdW50ZXIgaWYgdGhlIHRleHQgcmVuZGVyZXIgaXMgd2FpdGluZyBmb3IgYSBjZXJ0YWluIGFtb3VudCBvZiB0aW1lIHRvIHBhc3MuIElmIHNraXBwaW5nIGlzIGVuYWJsZWQsIHRoZSB0ZXh0IHJlbmRlcmVyIHdpbGxcbiAgICAqIG5vdCB3YWl0IGZvciB0aGUgYWN0dWFsIGFtb3VudCBvZiB0aW1lIGFuZCBzZXRzIHRoZSB3YWl0LWNvdW50ZXIgdG8gMSBmcmFtZSBpbnN0ZWFkLlxuICAgICpcbiAgICAqIEBtZXRob2QgdXBkYXRlV2FpdEZvcktleVxuICAgICogQHByaXZhdGVcbiAgICAjIyMgICAgICAgXG4gICAgdXBkYXRlV2FpdENvdW50ZXI6IC0+XG4gICAgICAgIGlmIEB3YWl0Q291bnRlciA+IDBcbiAgICAgICAgICAgIGlmIEdhbWVNYW5hZ2VyLnRlbXBTZXR0aW5ncy5za2lwXG4gICAgICAgICAgICAgICAgQHdhaXRDb3VudGVyID0gMVxuICAgICAgICAgICAgQGlzV2FpdGluZyA9IHllc1xuICAgICAgICAgICAgQHdhaXRDb3VudGVyLS1cbiAgICAgICAgICAgIGlmIEB3YWl0Q291bnRlciA8PSAwXG4gICAgICAgICAgICAgICAgQGlzV2FpdGluZyA9IG5vXG4gICAgICAgICAgICAgICAgQGNvbnRpbnVlKCkgaWYgQGxpbmUgPj0gQG1heExpbmVzXG4gICAgICAgICAgICAgICAgXG4gICAgIyMjKlxuICAgICogQ3JlYXRlcyBhIHRva2VuLW9iamVjdCBmb3IgYSBzcGVjaWZpZWQgdGV4dC1jb2RlLlxuICAgICogXG4gICAgKiBAbWV0aG9kIGNyZWF0ZVRva2VuXG4gICAgKiBAcGFyYW0ge3N0cmluZ30gY29kZSAtIFRoZSBjb2RlL3R5cGUgb2YgdGhlIHRleHQtY29kZS5cbiAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFRoZSB2YWx1ZSBvZiB0aGUgdGV4dC1jb2RlLlxuICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgdG9rZW4tb2JqZWN0LlxuICAgICMjI1xuICAgIGNyZWF0ZVRva2VuOiAoY29kZSwgdmFsdWUpIC0+XG4gICAgICAgIHRva2VuT2JqZWN0ID0gbnVsbFxuICAgICAgICBcbiAgICAgICAgc3dpdGNoIGNvZGVcbiAgICAgICAgICAgIHdoZW4gXCJDRVwiXG4gICAgICAgICAgICAgICAgZGF0YSA9IHZhbHVlLnNwbGl0KFwiL1wiKVxuICAgICAgICAgICAgICAgIHZhbHVlID0gZGF0YS5zaGlmdCgpXG4gICAgICAgICAgICAgICAgdmFsdWUgPSBpZiBpc05hTih2YWx1ZSkgdGhlbiB2YWx1ZSBlbHNlIHBhcnNlSW50KHZhbHVlKVxuICAgICAgICAgICAgICAgIGZvciBpIGluIFswLi4uZGF0YV1cbiAgICAgICAgICAgICAgICAgICAgaWYgZGF0YVtpXS5zdGFydHNXaXRoKCdcIicpIGFuZCBkYXRhW2ldLmVuZHNXaXRoKCdcIicpXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhW2ldID0gZGF0YVtpXS5zdWJzdHJpbmcoMSwgZGF0YVtpXS5sZW5ndGgtMSlcbiAgICAgICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVtpXSA9IGlmIGlzTmFOKGRhdGFbaV0pIHRoZW4gZGF0YVtpXSBlbHNlIHBhcnNlRmxvYXQoZGF0YVtpXSlcbiAgICAgICAgICAgICAgICB0b2tlbk9iamVjdCA9IHsgY29kZTogY29kZSwgdmFsdWU6IHZhbHVlLCB2YWx1ZXM6IGRhdGEgIH1cbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0b2tlbk9iamVjdCA9IHN1cGVyKGNvZGUsIHZhbHVlKVxuICAgICAgIFxuICAgICAgICAgICAgICAgIFxuICAgICAgICByZXR1cm4gdG9rZW5PYmplY3QgXG4gICAgIyMjKlxuICAgICogPHA+TWVhc3VyZXMgYSBjb250cm9sLXRva2VuLiBJZiBhIHRva2VuIHByb2R1Y2VzIGEgdmlzdWFsIHJlc3VsdCBsaWtlIGRpc3BsYXlpbmcgYW4gaWNvbiB0aGVuIGl0IG11c3QgcmV0dXJuIHRoZSBzaXplIHRha2VuIGJ5XG4gICAgKiB0aGUgdmlzdWFsIHJlc3VsdC4gSWYgdGhlIHRva2VuIGhhcyBubyB2aXN1YWwgcmVzdWx0LCA8Yj5udWxsPC9iPiBtdXN0IGJlIHJldHVybmVkLiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgZm9yIGV2ZXJ5IHRva2VuIHdoZW4gdGhlIG1lc3NhZ2UgaXMgaW5pdGlhbGl6ZWQuPC9wPiBcbiAgICAqXG4gICAgKiA8cD5UaGlzIG1ldGhvZCBpcyBub3QgY2FsbGVkIHdoaWxlIHRoZSBtZXNzYWdlIGlzIHJ1bm5pbmcuIEZvciB0aGF0IGNhc2UsIHNlZSA8aT5wcm9jZXNzQ29udHJvbFRva2VuPC9pPiBtZXRob2Qgd2hpY2ggaXMgY2FsbGVkXG4gICAgKiBmb3IgZXZlcnkgdG9rZW4gd2hpbGUgdGhlIG1lc3NhZ2UgaXMgcnVubmluZy48L3A+XG4gICAgKlxuICAgICogQHBhcmFtIHtPYmplY3R9IHRva2VuIC0gQSBjb250cm9sLXRva2VuLlxuICAgICogQHJldHVybiB7Z3MuU2l6ZX0gVGhlIHNpemUgb2YgdGhlIGFyZWEgdGFrZW4gYnkgdGhlIHZpc3VhbCByZXN1bHQgb2YgdGhlIHRva2VuIG9yIDxiPm51bGw8L2I+IGlmIHRoZSB0b2tlbiBoYXMgbm8gdmlzdWFsIHJlc3VsdC5cbiAgICAqIEBtZXRob2QgYW5hbHl6ZUNvbnRyb2xUb2tlblxuICAgICogQHByb3RlY3RlZFxuICAgICMjI1xuICAgIG1lYXN1cmVDb250cm9sVG9rZW46ICh0b2tlbikgLT4gcmV0dXJuIHN1cGVyKHRva2VuKVxuICAgICAgICBcbiAgICAjIyMqXG4gICAgKiA8cD5EcmF3cyB0aGUgdmlzdWFsIHJlc3VsdCBvZiBhIHRva2VuLCBsaWtlIGFuIGljb24gZm9yIGV4YW1wbGUsIHRvIHRoZSBzcGVjaWZpZWQgYml0bWFwLiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgZm9yIGV2ZXJ5IHRva2VuIHdoZW4gdGhlIG1lc3NhZ2UgaXMgaW5pdGlhbGl6ZWQgYW5kIHRoZSBzcHJpdGVzIGZvciBlYWNoXG4gICAgKiB0ZXh0LWxpbmUgYXJlIGNyZWF0ZWQuPC9wPiBcbiAgICAqXG4gICAgKiA8cD5UaGlzIG1ldGhvZCBpcyBub3QgY2FsbGVkIHdoaWxlIHRoZSBtZXNzYWdlIGlzIHJ1bm5pbmcuIEZvciB0aGF0IGNhc2UsIHNlZSA8aT5wcm9jZXNzQ29udHJvbFRva2VuPC9pPiBtZXRob2Qgd2hpY2ggaXMgY2FsbGVkXG4gICAgKiBmb3IgZXZlcnkgdG9rZW4gd2hpbGUgdGhlIG1lc3NhZ2UgaXMgcnVubmluZy48L3A+XG4gICAgKlxuICAgICogQHBhcmFtIHtPYmplY3R9IHRva2VuIC0gQSBjb250cm9sLXRva2VuLlxuICAgICogQHBhcmFtIHtncy5CaXRtYXB9IGJpdG1hcCAtIFRoZSBiaXRtYXAgdXNlZCBmb3IgdGhlIGN1cnJlbnQgdGV4dC1saW5lLiBDYW4gYmUgdXNlZCB0byBkcmF3IHNvbWV0aGluZyBvbiBpdCBsaWtlIGFuIGljb24sIGV0Yy5cbiAgICAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgLSBBbiB4LW9mZnNldCBmb3IgdGhlIGRyYXctcm91dGluZS5cbiAgICAqIEBwYXJhbSB7bnVtYmVyfSBsZW5ndGggLSBEZXRlcm1pbmVzIGhvdyBtYW55IGNoYXJhY3RlcnMgb2YgdGhlIHRva2VuIHNob3VsZCBiZSBkcmF3bi4gQ2FuIGJlIGlnbm9yZWQgZm9yIHRva2Vuc1xuICAgICogbm90IGRyYXdpbmcgYW55IGNoYXJhY3RlcnMuXG4gICAgKiBAbWV0aG9kIGRyYXdDb250cm9sVG9rZW5cbiAgICAqIEBwcm90ZWN0ZWRcbiAgICAjIyNcbiAgICBkcmF3Q29udHJvbFRva2VuOiAodG9rZW4sIGJpdG1hcCwgb2Zmc2V0LCBsZW5ndGgpIC0+XG4gICAgICAgIHN3aXRjaCB0b2tlbi5jb2RlXG4gICAgICAgICAgICB3aGVuIFwiUlRcIiAjIFJ1YnkgVGV4dFxuICAgICAgICAgICAgICAgIHN1cGVyKHRva2VuLCBiaXRtYXAsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgICAgICAgd2hlbiBcIlNMS1wiICMgU3R5bGFibGUgTGlua1xuICAgICAgICAgICAgICAgIGlmICF0b2tlbi5jdXN0b21EYXRhLm9mZnNldFg/XG4gICAgICAgICAgICAgICAgICAgIHRva2VuLmN1c3RvbURhdGEub2Zmc2V0WCA9IG9mZnNldFxuICAgICAgICAgICAgICAgIGlmIEBjdXN0b21EYXRhLmxpbmtEYXRhXG4gICAgICAgICAgICAgICAgICAgIGxpbmtEYXRhID0gQGN1c3RvbURhdGEubGlua0RhdGFbQGxpbmVdXG4gICAgICAgICAgICAgICAgICAgIGlmIGxpbmtEYXRhIHRoZW4gZm9yIGRhdGEgaW4gbGlua0RhdGFcbiAgICAgICAgICAgICAgICAgICAgICAgIEBzcHJpdGVzW0BsaW5lXS5iaXRtYXAuY2xlYXJSZWN0KGRhdGEuY3gsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEud2lkdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuaGVpZ2h0KVxuICAgICAgICAgICAgICAgIFxuICAgICBcbiAgICAjIyMqXG4gICAgKiBQcm9jZXNzZXMgYSBjb250cm9sLXRva2VuLiBBIGNvbnRyb2wtdG9rZW4gaXMgYSB0b2tlbiB3aGljaCBpbmZsdWVuY2VzXG4gICAgKiB0aGUgdGV4dC1yZW5kZXJpbmcgbGlrZSBjaGFuZ2luZyB0aGUgZm9udHMgY29sb3IsIHNpemUgb3Igc3R5bGUuIENoYW5nZXMgXG4gICAgKiB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgYXBwbGllZCB0byB0aGUgZ2FtZSBvYmplY3QncyBmb250LlxuICAgICpcbiAgICAqIEZvciBtZXNzYWdlIHRleHQtcmVuZGVyZXIsIGEgZmV3IGFkZGl0aW9uYWwgY29udHJvbC10b2tlbnMgbGlrZVxuICAgICogc3BlZWQtY2hhbmdlLCB3YWl0aW5nLCBldGMuIG5lZWRzIHRvIGJlIHByb2Nlc3NlZCBoZXJlLlxuICAgICpcbiAgICAqIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBmb3IgZWFjaCB0b2tlbiB3aGlsZSB0aGUgbWVzc2FnZSBpcyBpbml0aWFsaXplZCBhbmRcbiAgICAqIGFsc28gd2hpbGUgdGhlIG1lc3NhZ2UgaXMgcnVubmluZy4gU2VlIDxpPmZvcm1hdHRpbmdPbmx5PC9pPiBwYXJhbWV0ZXIuXG4gICAgKlxuICAgICogQHBhcmFtIHtPYmplY3R9IHRva2VuIC0gQSBjb250cm9sLXRva2VuLlxuICAgICogQHBhcmFtIHtib29sZWFufSBmb3JtYXR0aW5nT25seSAtIElmIDxiPnRydWU8L2I+IHRoZSBtZXNzYWdlIGlzIGluaXRpYWxpemluZyByaWdodCBub3cgYW5kIG9ubHkgXG4gICAgKiBmb3JtYXQtdG9rZW5zIHNob3VsZCBiZSBwcm9jZXNzZWQgd2hpY2ggaXMgbmVjZXNzYXJ5IGZvciB0aGUgbWVzc2FnZSB0byBjYWxjdWxhdGVkIHNpemVzIGNvcnJlY3RseS5cbiAgICAqIEByZXR1cm4ge09iamVjdH0gQSBuZXcgdG9rZW4gd2hpY2ggaXMgcHJvY2Vzc2VkIG5leHQgb3IgPGI+bnVsbDwvYj4uXG4gICAgKiBAbWV0aG9kIHByb2Nlc3NDb250cm9sVG9rZW5cbiAgICAqIEBwcm90ZWN0ZWRcbiAgICAjIyNcbiAgICBwcm9jZXNzQ29udHJvbFRva2VuOiAodG9rZW4sIGZvcm1hdHRpbmdPbmx5KSAtPlxuICAgICAgICByZXR1cm4gc3VwZXIodG9rZW4pIGlmIGZvcm1hdHRpbmdPbmx5XG4gICAgICAgIHJlc3VsdCA9IG51bGxcbiAgICAgICAgXG4gICAgICAgIHN3aXRjaCB0b2tlbi5jb2RlXG4gICAgICAgICAgICB3aGVuIFwiQ1JcIiAjIENoYW5nZSBDdXJyZW50IENoYXJhY3RlclxuICAgICAgICAgICAgICAgIGNoYXJhY3RlciA9IFJlY29yZE1hbmFnZXIuY2hhcmFjdGVyc0FycmF5LmZpcnN0IChjKSAtPiAoYy5uYW1lLmRlZmF1bHRUZXh0ID8gYy5uYW1lKSA9PSB0b2tlbi52YWx1ZVxuICAgICAgICAgICAgICAgIGlmIGNoYXJhY3RlclxuICAgICAgICAgICAgICAgICAgICBTY2VuZU1hbmFnZXIuc2NlbmUuY3VycmVudENoYXJhY3RlciA9IGNoYXJhY3RlclxuICAgICAgICAgICAgd2hlbiBcIkNFXCIgIyBDYWxsIENvbW1vbiBFdmVudFxuICAgICAgICAgICAgICAgIHBhcmFtcyA9IHsgXCJ2YWx1ZXNcIjogdG9rZW4udmFsdWVzIH1cbiAgICAgICAgICAgICAgICBAb2JqZWN0LmV2ZW50cz8uZW1pdChcImNhbGxDb21tb25FdmVudFwiLCBAb2JqZWN0LCB7IGNvbW1vbkV2ZW50SWQ6IHRva2VuLnZhbHVlLCBwYXJhbXM6IHBhcmFtcywgZmluaXNoOiBubywgd2FpdGluZzogeWVzIH0pXG4gICAgICAgICAgICB3aGVuIFwiWFwiICMgU2NyaXB0XG4gICAgICAgICAgICAgICAgdG9rZW4udmFsdWU/KEBvYmplY3QpXG4gICAgICAgICAgICB3aGVuIFwiQVwiICMgUGxheSBBbmltYXRpb25cbiAgICAgICAgICAgICAgICBhbmltYXRpb24gPSBSZWNvcmRNYW5hZ2VyLmFuaW1hdGlvbnNBcnJheS5maXJzdCAoYSkgLT4gYS5uYW1lID09IHRva2VuLnZhbHVlXG4gICAgICAgICAgICAgICAgaWYgIWFuaW1hdGlvblxuICAgICAgICAgICAgICAgICAgICBhbmltYXRpb24gPSBSZWNvcmRNYW5hZ2VyLmFuaW1hdGlvbnNbdG9rZW4udmFsdWVdXG4gICAgICAgICAgICAgICAgaWYgYW5pbWF0aW9uPy5ncmFwaGljLm5hbWU/XG4gICAgICAgICAgICAgICAgICAgIGJpdG1hcCA9IFJlc291cmNlTWFuYWdlci5nZXRCaXRtYXAoXCJHcmFwaGljcy9QaWN0dXJlcy8je2FuaW1hdGlvbi5ncmFwaGljLm5hbWV9XCIpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdCA9IG5ldyBncy5PYmplY3RfQW5pbWF0aW9uKGFuaW1hdGlvbilcbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgIEBhZGRDdXN0b21PYmplY3Qob2JqZWN0KVxuICAgICAgICAgICAgICAgICAgICBAY3VycmVudFggKz0gTWF0aC5yb3VuZChiaXRtYXAud2lkdGggLyBhbmltYXRpb24uZnJhbWVzWClcbiAgICAgICAgICAgICAgICAgICAgQGN1cnJlbnRTcHJpdGUuc3JjUmVjdC53aWR0aCArPSBNYXRoLnJvdW5kKGJpdG1hcC53aWR0aCAvIGFuaW1hdGlvbi5mcmFtZXNYKVxuICAgICAgICAgICAgXG4gICAgICAgICAgICB3aGVuIFwiUlRcIiAjIFJ1YnkgVGV4dFxuICAgICAgICAgICAgICAgIGlmIHRva2VuLnJ0U2l6ZS53aWR0aCA+IHRva2VuLnJiU2l6ZS53aWR0aFxuICAgICAgICAgICAgICAgICAgICBAY3VycmVudFggKz0gdG9rZW4ucnRTaXplLndpZHRoXG4gICAgICAgICAgICAgICAgICAgIEBmb250LnNldChAZ2V0UnVieVRleHRGb250KHRva2VuKSlcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIEBjdXJyZW50WCArPSB0b2tlbi5yYlNpemUud2lkdGhcbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB3aGVuIFwiTEtcIiAjIExpbmsgICAgICBcbiAgICAgICAgICAgICAgICBpZiB0b2tlbi52YWx1ZSA9PSAnRScgIyBFbmQgTGlua1xuICAgICAgICAgICAgICAgICAgICBvYmplY3QgPSBuZXcgdWkuT2JqZWN0X0hvdHNwb3QoKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuZW5hYmxlZCA9IHllc1xuICAgICAgICAgICAgICAgICAgICBvYmplY3Quc2V0dXAoKVxuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgQGFkZEN1c3RvbU9iamVjdChvYmplY3QpXG4gICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuZHN0UmVjdC54ID0gQG9iamVjdC5kc3RSZWN0LnggKyBAb2JqZWN0Lm9yaWdpbi54ICsgQGN1c3RvbURhdGEubGlua0RhdGEuY3hcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmRzdFJlY3QueSA9IEBvYmplY3QuZHN0UmVjdC55ICsgQG9iamVjdC5vcmlnaW4ueSArIEBjdXN0b21EYXRhLmxpbmtEYXRhLmN5XG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5kc3RSZWN0LndpZHRoID0gQGN1cnJlbnRYIC0gQGN1c3RvbURhdGEubGlua0RhdGEuY3hcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmRzdFJlY3QuaGVpZ2h0ID0gQGN1cnJlbnRMaW5lSGVpZ2h0XG5cbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmV2ZW50cy5vbihcImNsaWNrXCIsIGdzLkNhbGxCYWNrKFwib25MaW5rQ2xpY2tcIiwgdGhpcyksIGxpbmtEYXRhOiBAY3VzdG9tRGF0YS5saW5rRGF0YSwgdGhpcylcbiAgICAgICAgICAgICAgICBlbHNlICMgQmVnaW4gTGlua1xuICAgICAgICAgICAgICAgICAgICBAY3VzdG9tRGF0YS5saW5rRGF0YSA9IHsgY3g6IEBjdXJyZW50WCwgY3k6IEBjdXJyZW50WSwgY29tbW9uRXZlbnRJZDogdG9rZW4udmFsdWUsIHRva2VuSW5kZXg6IEB0b2tlbkluZGV4IH1cbiAgICAgICAgICAgIHdoZW4gXCJTTEtcIiAjIFN0eWxlYWJsZSBMaW5rXG4gICAgICAgICAgICAgICAgaWYgdG9rZW4udmFsdWUgPT0gJ0UnICMgRW5kIExpbmtcbiAgICAgICAgICAgICAgICAgICAgbGlua0RhdGEgPSBAY3VzdG9tRGF0YS5saW5rRGF0YVtAbGluZV0ubGFzdCgpXG4gICAgICAgICAgICAgICAgICAgIGxpbmUgPSBAbGluZXNbQGxpbmVdLmNvbnRlbnRcbiAgICAgICAgICAgICAgICAgICAgbGlua1N0YXJ0ID0gQGZpbmRUb2tlbihAdG9rZW5JbmRleC0xLCBcIlNMS1wiLCAtMSwgbGluZSlcbiAgICAgICAgICAgICAgICAgICAgdGV4dFRva2VucyA9IEBmaW5kVG9rZW5zQmV0d2VlbihsaW5rRGF0YS50b2tlbkluZGV4LCBAdG9rZW5JbmRleCwgbnVsbCwgbGluZSlcbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgIGxpbmtEYXRhLmN4ID0gbGlua1N0YXJ0LmN1c3RvbURhdGEub2Zmc2V0WFxuICAgICAgICAgICAgICAgICAgICBsaW5rRGF0YS53aWR0aCA9IEBjdXJyZW50WCAtIGxpbmtEYXRhLmN4ICsgQHBhZGRpbmdcbiAgICAgICAgICAgICAgICAgICAgbGlua0RhdGEuaGVpZ2h0ID0gQGN1cnJlbnRTcHJpdGUuYml0bWFwLmhlaWdodFxuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0ID0gbmV3IHVpLk9iamVjdF9UZXh0KClcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnRleHQgPSB0ZXh0VG9rZW5zLnNlbGVjdCgoeCkgPT4geC52YWx1ZSkuam9pbihcIlwiKVxuICAgICAgICAgICAgICAgICAgICAjb2JqZWN0LnNpemVUb0ZpdCA9IHllc1xuICAgICAgICAgICAgICAgICAgICBvYmplY3QuZm9ybWF0dGluZyA9IG5vXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC53b3JkV3JhcCA9IG5vXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC51aSA9IG5ldyB1aS5Db21wb25lbnRfVUlCZWhhdmlvcigpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5lbmFibGVkID0geWVzXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5hZGRDb21wb25lbnQob2JqZWN0LnVpKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuYWRkQ29tcG9uZW50KG5ldyBncy5Db21wb25lbnRfSG90c3BvdEJlaGF2aW9yKCkpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5iZWhhdmlvci5wYWRkaW5nLmxlZnQgPSAwXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5iZWhhdmlvci5wYWRkaW5nLnJpZ2h0ID0gMFxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuZHN0UmVjdC53aWR0aCA9IGxpbmtEYXRhLndpZHRoXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5kc3RSZWN0LmhlaWdodCA9IGxpbmtEYXRhLmhlaWdodFxuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgaWYgbGlua0RhdGEuc3R5bGVJbmRleCA9PSAtMVxuICAgICAgICAgICAgICAgICAgICAgICAgdWkuVUlNYW5hZ2VyLmFkZENvbnRyb2xTdHlsZXMob2JqZWN0LCBbXCJoeXBlcmxpbmtcIl0pXG4gICAgICAgICAgICAgICAgICAgIGVsc2UgXG4gICAgICAgICAgICAgICAgICAgICAgICB1aS5VSU1hbmFnZXIuYWRkQ29udHJvbFN0eWxlcyhvYmplY3QsIFtcImh5cGVybGluay1cIitsaW5rRGF0YS5zdHlsZUluZGV4XSlcbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5zZXR1cCgpXG4gICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBAYWRkQ3VzdG9tT2JqZWN0KG9iamVjdClcbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5kc3RSZWN0LnggPSBAY3VycmVudFNwcml0ZS54ICsgbGlua0RhdGEuY3hcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmRzdFJlY3QueSA9IEBvYmplY3QuZHN0UmVjdC55ICsgQG9iamVjdC5vcmlnaW4ueSArIGxpbmtEYXRhLmN5XG5cbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmV2ZW50cy5vbihcImNsaWNrXCIsIGdzLkNhbGxCYWNrKFwib25MaW5rQ2xpY2tcIiwgdGhpcyksIGxpbmtEYXRhOiBsaW5rRGF0YSwgdGhpcylcbiAgICAgICAgICAgICAgICBlbHNlICMgQmVnaW4gTGlua1xuICAgICAgICAgICAgICAgICAgICBpZiAhQGN1c3RvbURhdGEubGlua0RhdGFcbiAgICAgICAgICAgICAgICAgICAgICAgIEBjdXN0b21EYXRhLmxpbmtEYXRhID0gW11cbiAgICAgICAgICAgICAgICAgICAgaWYgIUBjdXN0b21EYXRhLmxpbmtEYXRhW0BsaW5lXVxuICAgICAgICAgICAgICAgICAgICAgICAgQGN1c3RvbURhdGEubGlua0RhdGFbQGxpbmVdID0gW11cbiAgICAgICAgICAgICAgICAgICAgaWYgdG9rZW4udmFsdWU/LmNvbnRhaW5zKFwiLFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gdG9rZW4udmFsdWUuc3BsaXQoXCIsXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBAY3VzdG9tRGF0YS5saW5rRGF0YVtAbGluZV0ucHVzaCh7IGN4OiBAY3VycmVudFgsIGN5OiBAY3VycmVudFksIGNvbW1vbkV2ZW50SWQ6IHZhbHVlc1swXSwgc3R5bGVJbmRleDogcGFyc2VJbnQodmFsdWVzWzFdKSwgdG9rZW5JbmRleDogQHRva2VuSW5kZXggfSlcbiAgICAgICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgQGN1c3RvbURhdGEubGlua0RhdGFbQGxpbmVdLnB1c2goeyBjeDogQGN1cnJlbnRZLCBjeTogQGN1cnJlbnRZLCBjb21tb25FdmVudElkOiB0b2tlbi52YWx1ZSwgdG9rZW5JbmRleDogQHRva2VuSW5kZXgsIHN0eWxlSW5kZXg6IC0xIH0pXG4gICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgd2hlbiBcIkVcIiAjIENoYW5nZSBFeHByZXNzaW9uXG4gICAgICAgICAgICAgICAgZXhwcmVzc2lvbiA9IFJlY29yZE1hbmFnZXIuY2hhcmFjdGVyRXhwcmVzc2lvbnNBcnJheS5maXJzdCAoYykgLT4gKGMubmFtZS5kZWZhdWx0VGV4dCA/IGMubmFtZSkgPT0gdG9rZW4udmFsdWVcbiAgICAgICAgICAgICAgICBpZiAhZXhwcmVzc2lvblxuICAgICAgICAgICAgICAgICAgICBleHByZXNzaW9uID0gUmVjb3JkTWFuYWdlci5jaGFyYWN0ZXJFeHByZXNzaW9uc1t0b2tlbi52YWx1ZV1cbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgY2hhcmFjdGVyID0gU2NlbmVNYW5hZ2VyLnNjZW5lLmN1cnJlbnRDaGFyYWN0ZXJcbiAgICAgICAgICAgICAgICBpZiBleHByZXNzaW9uPyBhbmQgY2hhcmFjdGVyPy5pbmRleD9cbiAgICAgICAgICAgICAgICAgICAgZHVyYXRpb24gPSBHYW1lTWFuYWdlci5kZWZhdWx0cy5jaGFyYWN0ZXIuZXhwcmVzc2lvbkR1cmF0aW9uXG4gICAgICAgICAgICAgICAgICAgIGVhc2luZyA9IGdzLkVhc2luZ3MuZnJvbU9iamVjdChHYW1lTWFuYWdlci5kZWZhdWx0cy5jaGFyYWN0ZXIuY2hhbmdlRWFzaW5nKVxuICAgICAgICAgICAgICAgICAgICBhbmltYXRpb24gPSBHYW1lTWFuYWdlci5kZWZhdWx0cy5jaGFyYWN0ZXIuY2hhbmdlQW5pbWF0aW9uXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdCA9IFNjZW5lTWFuYWdlci5zY2VuZS5jaGFyYWN0ZXJzLmZpcnN0IChjKSAtPiBjLnJpZCA9PSBjaGFyYWN0ZXIuaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0Py5iZWhhdmlvci5jaGFuZ2VFeHByZXNzaW9uKGV4cHJlc3Npb24sIGFuaW1hdGlvbiwgZWFzaW5nLCBkdXJhdGlvbilcbiAgXG4gICAgICAgICAgICB3aGVuIFwiU1BcIiAjIFBsYXkgU291bmRcbiAgICAgICAgICAgICAgICBzb3VuZCA9IFJlY29yZE1hbmFnZXIuc3lzdGVtLnNvdW5kc1t0b2tlbi52YWx1ZS0xXVxuICAgICAgICAgICAgICAgIEF1ZGlvTWFuYWdlci5wbGF5U291bmQoc291bmQpXG4gICAgICAgICAgICB3aGVuIFwiU1wiICMgQ2hhbmdlIFNwZWVkXG4gICAgICAgICAgICAgICAgR2FtZU1hbmFnZXIuc2V0dGluZ3MubWVzc2FnZVNwZWVkID0gdG9rZW4udmFsdWVcbiAgICAgICAgICAgIHdoZW4gXCJXXCIgIyBXYWl0XG4gICAgICAgICAgICAgICAgQGRyYXdJbW1lZGlhdGVseSA9IG5vXG4gICAgICAgICAgICAgICAgaWYgIUdhbWVNYW5hZ2VyLnRlbXBTZXR0aW5ncy5za2lwXG4gICAgICAgICAgICAgICAgICAgIGlmIHRva2VuLnZhbHVlID09IFwiQVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBAd2FpdEZvcktleSA9IHllc1xuICAgICAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBAd2FpdENvdW50ZXIgPSBNYXRoLnJvdW5kKHRva2VuLnZhbHVlIC8gMTAwMCAqIEdyYXBoaWNzLmZyYW1lUmF0ZSlcbiAgICAgICAgICAgIHdoZW4gXCJXRVwiICMgV2FpdCBhdCBFbmRcbiAgICAgICAgICAgICAgICBAd2FpdEF0RW5kID0gdG9rZW4udmFsdWUgPT0gXCJZXCJcbiAgICAgICAgICAgIHdoZW4gXCJESVwiICMgRHJhdyBJbW1lZGlhbHR5XG4gICAgICAgICAgICAgICAgQGRyYXdJbW1lZGlhdGVseSA9IHRva2VuLnZhbHVlID09IDEgb3IgdG9rZW4udmFsdWUgPT0gXCJZXCIgIyBEcmF3IGltbWVkaWF0ZWx5XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gc3VwZXIodG9rZW4pXG4gICAgICAgIFxuICAgICAgICByZXR1cm4gcmVzdWx0ICAgICAgICBcbiAgICAjIyMqXG4gICAgKiBDbGVhcnMvUmVzZXRzIHRoZSB0ZXh0LXJlbmRlcmVyLlxuICAgICpcbiAgICAqIEBtZXRob2QgY2xlYXJcbiAgICAjIyNcbiAgICBjbGVhcjogLT5cbiAgICAgICAgQGNoYXJJbmRleCA9IDBcbiAgICAgICAgQGN1cnJlbnRYID0gMFxuICAgICAgICBAY3VycmVudFkgPSAwXG4gICAgICAgIEBsaW5lID0gMFxuICAgICAgICBAbGluZXMgPSBbXVxuICAgICAgICBAY2xlYXJDdXN0b21PYmplY3RzKClcbiAgICAgICAgQG9iamVjdC5iaXRtYXA/LmNsZWFyKClcbiAgICAgICAgXG4gICAgICAgIGZvciBzcHJpdGUgaW4gQGFsbFNwcml0ZXNcbiAgICAgICAgICAgIHNwcml0ZS5kaXNwb3NlKClcbiAgICAgICAgICAgIHNwcml0ZS5iaXRtYXA/LmRpc3Bvc2UoKVxuICAgICAgICBAYWxsU3ByaXRlcyA9IFtdXG4gICAgICAgIHJldHVybiBudWxsXG4gICAgXG4gICAgIyMjKlxuICAgICogQ2xlYXJzL0Rpc3Bvc2VzIGFsbCBzcHJpdGVzIHVzZWQgdG8gZGlzcGxheSB0aGUgdGV4dC1saW5lcy9wYXJ0cy5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGNsZWFyQWxsU3ByaXRlc1xuICAgICMjI1xuICAgIGNsZWFyQWxsU3ByaXRlczogLT5cbiAgICAgICAgZm9yIHNwcml0ZSBpbiBAYWxsU3ByaXRlc1xuICAgICAgICAgICAgc3ByaXRlLmRpc3Bvc2UoKVxuICAgICAgICAgICAgc3ByaXRlLmJpdG1hcD8uZGlzcG9zZSgpXG4gICAgICAgICAgICBcbiAgICAgICAgcmV0dXJuIG51bGxcbiAgICBcbiAgICAjIyMqXG4gICAgKiBDbGVhcnMvRGlzcG9zZXMgdGhlIHNwcml0ZXMgdXNlZCB0byBkaXNwbGF5IHRoZSB0ZXh0LWxpbmVzL3BhcnRzIG9mIHRoZSBjdXJyZW50L2xhc3QgbWVzc2FnZS5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGNsZWFyU3ByaXRlc1xuICAgICMjIyAgICAgICAgXG4gICAgY2xlYXJTcHJpdGVzOiAtPlxuICAgICAgICBmb3Igc3ByaXRlIGluIEBzcHJpdGVzXG4gICAgICAgICAgICBzcHJpdGUuZGlzcG9zZSgpXG4gICAgICAgICAgICBzcHJpdGUuYml0bWFwPy5kaXNwb3NlKClcbiAgICAgICAgICAgIFxuICAgICAgICByZXR1cm4gbnVsbFxuICAgIFxuICAgIFxuICAgICMjIypcbiAgICAqIFJlbW92ZXMgYSBnYW1lIG9iamVjdCBmcm9tIHRoZSBtZXNzYWdlLlxuICAgICpcbiAgICAqIEBtZXRob2QgcmVtb3ZlQ3VzdG9tT2JqZWN0XG4gICAgKiBAcGFyYW0gb2JqZWN0IHtncy5PYmplY3RfQmFzZX0gVGhlIGdhbWUgb2JqZWN0IHRvIHJlbW92ZS5cbiAgICAjIyNcbiAgICByZW1vdmVDdXN0b21PYmplY3Q6IChvYmplY3QpIC0+XG4gICAgICAgIFNjZW5lTWFuYWdlci5zY2VuZS5yZW1vdmVPYmplY3Qob2JqZWN0KVxuICAgICAgICBvYmplY3QuZGlzcG9zZSgpXG4gICAgICAgIEBjdXN0b21PYmplY3RzLnJlbW92ZShvYmplY3QpXG4gICAgICAgIFxuICAgICMjIypcbiAgICAqIEFkZHMgYSBnYW1lIG9iamVjdCB0byB0aGUgbWVzc2FnZSB3aGljaCBpcyBhbGl2ZSB1bnRpbCB0aGUgbWVzc2FnZSBpc1xuICAgICogZXJhc2VkLiBDYW4gYmUgdXNlZCB0byBkaXNwbGF5IGFuaW1hdGlvbmVkLWljb25zLCBldGMuIGluIGEgbWVzc2FnZS5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGFkZEN1c3RvbU9iamVjdFxuICAgICogQHBhcmFtIG9iamVjdCB7Z3MuT2JqZWN0X0Jhc2V9IFRoZSBnYW1lIG9iamVjdCB0byBhZGQuXG4gICAgIyMjXG4gICAgYWRkQ3VzdG9tT2JqZWN0OiAob2JqZWN0KSAtPlxuICAgICAgICBvYmplY3QuZHN0UmVjdC54ID0gQG9iamVjdC5kc3RSZWN0LnggKyBAb2JqZWN0Lm9yaWdpbi54ICsgQGN1cnJlbnRYXG4gICAgICAgIG9iamVjdC5kc3RSZWN0LnkgPSBAb2JqZWN0LmRzdFJlY3QueSArIEBvYmplY3Qub3JpZ2luLnkgKyBAY3VycmVudFlcbiAgICAgICAgb2JqZWN0LnpJbmRleCA9IEBvYmplY3QuekluZGV4ICsgMVxuICAgICAgICBvYmplY3QudXBkYXRlKClcbiAgICAgICAgXG4gICAgICAgIFNjZW5lTWFuYWdlci5zY2VuZS5hZGRPYmplY3Qob2JqZWN0KVxuICAgICAgICBAY3VzdG9tT2JqZWN0cy5wdXNoKG9iamVjdClcbiAgICAgXG4gICAgIyMjKlxuICAgICogQ2xlYXJzIHRoZSBsaXN0IG9mIGN1c3RvbSBnYW1lIG9iamVjdHMuIEFsbCBnYW1lIG9iamVjdHMgYXJlIGRpc3Bvc2VkIGFuZCByZW1vdmVkXG4gICAgKiBmcm9tIHRoZSBzY2VuZS5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGNsZWFyQ3VzdG9tT2JqZWN0c1xuICAgICogQHBhcmFtIG9iamVjdCB7T2JqZWN0fSBUaGUgZ2FtZSBvYmplY3QgdG8gYWRkLlxuICAgICMjIyAgIFxuICAgIGNsZWFyQ3VzdG9tT2JqZWN0czogLT5cbiAgICAgICAgZm9yIG9iamVjdCBpbiBAY3VzdG9tT2JqZWN0c1xuICAgICAgICAgICAgb2JqZWN0LmRpc3Bvc2UoKVxuICAgICAgICAgICAgU2NlbmVNYW5hZ2VyLnNjZW5lLnJlbW92ZU9iamVjdChvYmplY3QpXG4gICAgICAgICAgICBcbiAgICAgICAgQGN1c3RvbU9iamVjdHMgPSBbXVxuICAgIFxuICAgICMjIypcbiAgICAqIENyZWF0ZXMgdGhlIGJpdG1hcCBmb3IgYSBzcGVjaWZpZWQgbGluZS1vYmplY3QuXG4gICAgKlxuICAgICogQG1ldGhvZCBjcmVhdGVCaXRtYXBcbiAgICAqIEBwcml2YXRlXG4gICAgKiBAcGFyYW0ge09iamVjdH0gbGluZSAtIEEgbGluZS1vYmplY3QuXG4gICAgKiBAcmV0dXJuIHtCaXRtYXB9IEEgbmV3bHkgY3JlYXRlZCBiaXRtYXAgY29udGFpbmluZyB0aGUgbGluZS10ZXh0LlxuICAgICMjI1xuICAgIGNyZWF0ZUJpdG1hcDogKGxpbmUpIC0+XG4gICAgICAgIEBmb250ID0gQG9iamVjdC5mb250XG4gICAgICAgIGJpdG1hcCA9IG5ldyBCaXRtYXAoQG9iamVjdC5kc3RSZWN0LndpZHRoLCBNYXRoLm1heChAbWluTGluZUhlaWdodCwgbGluZS5oZWlnaHQpKVxuICAgICAgICBiaXRtYXAuZm9udCA9IEBmb250XG4gICAgICAgXG4gICAgICAgIHJldHVybiBiaXRtYXBcbiAgICBcbiAgICAjIyMqXG4gICAgKiBEcmF3cyB0aGUgbGluZSdzIGNvbnRlbnQgb24gdGhlIHNwZWNpZmllZCBiaXRtYXAuXG4gICAgKlxuICAgICogQG1ldGhvZCBkcmF3TGluZUNvbnRlbnRcbiAgICAqIEBwcm90ZWN0ZWRcbiAgICAqIEBwYXJhbSB7T2JqZWN0fSBsaW5lIC0gQSBsaW5lLW9iamVjdCB3aGljaCBzaG91bGQgYmUgZHJhd24gb24gdGhlIGJpdG1hcC5cbiAgICAqIEBwYXJhbSB7Z3MuQml0bWFwfSBiaXRtYXAgLSBUaGUgYml0bWFwIHRvIGRyYXcgdGhlIGxpbmUncyBjb250ZW50IG9uLlxuICAgICogQHBhcmFtIHtudW1iZXJ9IGxlbmd0aCAtIERldGVybWluZXMgaG93IG1hbnkgY2hhcmFjdGVycyBvZiB0aGUgc3BlY2lmaWVkIGxpbmUgc2hvdWxkIGJlIGRyYXduLiBZb3UgY2FuIFxuICAgICogc3BlY2lmeSAtMSB0byBkcmF3IGFsbCBjaGFyYWN0ZXJzLlxuICAgICMjI1xuICAgIGRyYXdMaW5lQ29udGVudDogKGxpbmUsIGJpdG1hcCwgbGVuZ3RoKSAtPlxuICAgICAgICBiaXRtYXAuY2xlYXIoKVxuICAgICAgICBjdXJyZW50WCA9IEBwYWRkaW5nXG4gICAgICAgIGRyYXdBbGwgPSBsZW5ndGggPT0gLTFcbiAgICAgICAgXG4gICAgICAgIGZvciB0b2tlbiwgaSBpbiBsaW5lLmNvbnRlbnRcbiAgICAgICAgICAgIGJyZWFrIGlmIGkgPiBAdG9rZW5JbmRleCBhbmQgIWRyYXdBbGxcbiAgICAgICAgICAgIGlmIHRva2VuLmNvZGU/XG4gICAgICAgICAgICAgICAgc2l6ZSA9IEBtZWFzdXJlQ29udHJvbFRva2VuKHRva2VuLCBiaXRtYXApXG4gICAgICAgICAgICAgICAgQGRyYXdDb250cm9sVG9rZW4odG9rZW4sIGJpdG1hcCwgY3VycmVudFgpXG4gICAgICAgICAgICAgICAgaWYgc2l6ZSB0aGVuIGN1cnJlbnRYICs9IHNpemUud2lkdGhcbiAgICAgICAgICAgICAgICBAcHJvY2Vzc0NvbnRyb2xUb2tlbih0b2tlbiwgeWVzLCBsaW5lKVxuICAgICAgICAgICAgZWxzZSBpZiB0b2tlbi52YWx1ZS5sZW5ndGggPiAwXG4gICAgICAgICAgICAgICAgdG9rZW4uYXBwbHlGb3JtYXQoQGZvbnQpXG4gICAgICAgICAgICAgICAgdmFsdWUgPSB0b2tlbi52YWx1ZVxuICAgICAgICAgICAgICAgIGlmICFkcmF3QWxsIGFuZCBAdG9rZW5JbmRleCA9PSBpIGFuZCB2YWx1ZS5sZW5ndGggPiBsZW5ndGhcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5zdWJzdHJpbmcoMCwgbGVuZ3RoKVxuICAgICAgICAgICAgICAgIGlmIHZhbHVlICE9IFwiXFxuXCJcbiAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IEBmb250Lm1lYXN1cmVUZXh0UGxhaW4odmFsdWUpICBcbiAgICAgICAgICAgICAgICAgICAgYml0bWFwLmRyYXdUZXh0KGN1cnJlbnRYLCBsaW5lLmhlaWdodCAtIChzaXplLmhlaWdodCAtIEBmb250LmRlc2NlbnQpIC0gbGluZS5kZXNjZW50LCBzaXplLndpZHRoLCBiaXRtYXAuaGVpZ2h0LCB2YWx1ZSwgMCwgMClcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFggKz0gc2l6ZS53aWR0aFxuICAgICAgICAgICAgICAgIFxuICAgICAgICBsaW5lLmNvbnRlbnRXaWR0aCA9IGN1cnJlbnRYICsgQGZvbnQubWVhc3VyZVRleHRQbGFpbihcIiBcIikud2lkdGggICBcbiAgICAgICAgXG4gICAgIyMjKlxuICAgICogQ3JlYXRlcyB0aGUgc3ByaXRlIGZvciBhIHNwZWNpZmllZCBsaW5lLW9iamVjdC5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGNyZWF0ZVNwcml0ZVxuICAgICogQHByaXZhdGVcbiAgICAqIEBwYXJhbSB7T2JqZWN0fSBsaW5lIC0gQSBsaW5lLW9iamVjdC5cbiAgICAqIEByZXR1cm4ge1Nwcml0ZX0gQSBuZXdseSBjcmVhdGVkIHNwcml0ZSBvYmplY3QgY29udGFpbmluZyB0aGUgbGluZS10ZXh0IGFzIGJpdG1hcC5cbiAgICAjIyNcbiAgICBjcmVhdGVTcHJpdGU6IChsaW5lKSAtPlxuICAgICAgICBiaXRtYXAgPSBAY3JlYXRlQml0bWFwKGxpbmUpXG4gICAgICAgIFxuICAgICAgICBAY3VycmVudFggPSAwXG4gICAgICAgIEB3YWl0Q291bnRlciA9IDBcbiAgICAgICAgQHdhaXRGb3JLZXkgPSBub1xuICAgICAgICAgICAgICAgIFxuICAgICAgICBzcHJpdGUgPSBuZXcgU3ByaXRlKEdyYXBoaWNzLnZpZXdwb3J0KVxuICAgICAgICBzcHJpdGUuYml0bWFwID0gYml0bWFwXG4gICAgICAgIHNwcml0ZS52aXNpYmxlID0geWVzXG4gICAgICAgIHNwcml0ZS56ID0gQG9iamVjdC56SW5kZXggKyAxXG4gICAgICAgIFxuICAgICAgICBzcHJpdGUuc3JjUmVjdCA9IG5ldyBSZWN0KDAsIDAsIDAsIGJpdG1hcC5oZWlnaHQpXG4gICAgICAgIFxuICAgICAgICByZXR1cm4gc3ByaXRlXG4gICAgIFxuICAgICMjIypcbiAgICAqIENyZWF0ZXMgdGhlIHNwcml0ZXMgZm9yIGEgc3BlY2lmaWVkIGFycmF5IG9mIGxpbmUtb2JqZWN0cy5cbiAgICAqXG4gICAgKiBAbWV0aG9kIGNyZWF0ZVNwcml0ZXNcbiAgICAqIEBwcml2YXRlXG4gICAgKiBAc2VlIGdzLkNvbXBvbmVudF9NZXNzYWdlVGV4dFJlbmRlcmVyLmNyZWF0ZVNwcml0ZS5cbiAgICAqIEBwYXJhbSB7QXJyYXl9IGxpbmVzIC0gQW4gYXJyYXkgb2YgbGluZS1vYmplY3RzLlxuICAgICogQHJldHVybiB7QXJyYXl9IEFuIGFycmF5IG9mIHNwcml0ZXMuXG4gICAgIyMjXG4gICAgY3JlYXRlU3ByaXRlczogKGxpbmVzKSAtPlxuICAgICAgICBAZm9udFNpemUgPSBAb2JqZWN0LmZvbnQuc2l6ZVxuICAgICAgICByZXN1bHQgPSBbXVxuICAgICAgICBmb3IgbGluZSwgaSBpbiBsaW5lc1xuICAgICAgICAgICAgc3ByaXRlID0gQGNyZWF0ZVNwcml0ZShsaW5lKVxuICAgICAgICAgICAgcmVzdWx0LnB1c2goc3ByaXRlKVxuICAgICAgICByZXR1cm4gcmVzdWx0XG4gICAgXG4gICAgIyMjKlxuICAgICogU3RhcnRzIGEgbmV3IGxpbmUuXG4gICAgKlxuICAgICogQG1ldGhvZCBuZXdMaW5lXG4gICAgIyMjXG4gICAgbmV3TGluZTogLT5cbiAgICAgICAgQGN1cnJlbnRYID0gMFxuICAgICAgICBAY3VycmVudFkgKz0gQGN1cnJlbnRMaW5lSGVpZ2h0ICsgQGxpbmVTcGFjaW5nXG4gICAgICAgIFxuICAgICMjIypcbiAgICAqIERpc3BsYXlzIGEgZm9ybWF0dGVkIHRleHQgaW1tZWRpYXRlbHkgd2l0aG91dCBhbnkgZGVsYXlzIG9yIGFuaW1hdGlvbnMuIFRoZVxuICAgICogQ29tcG9uZW50X1RleHRSZW5kZXJlci5kcmF3Rm9ybWF0dGVkVGV4dCBtZXRob2QgZnJvbSB0aGUgYmFzZS1jbGFzcyBjYW5ub3RcbiAgICAqIGJlIHVzZWQgaGVyZSBiZWNhdXNlIGl0IHdvdWxkIHJlbmRlciB0byB0aGUgZ2FtZSBvYmplY3QncyBiaXRtYXAgb2JqZWN0IHdoaWxlXG4gICAgKiB0aGlzIG1ldGhvZCBpcyByZW5kZXJpbmcgdG8gdGhlIHNwcml0ZXMuXG4gICAgKlxuICAgICogQG1ldGhvZCBkcmF3Rm9ybWF0dGVkVGV4dEltbWVkaWF0ZWx5XG4gICAgKiBAcGFyYW0ge251bWJlcn0geCAtIFRoZSB4LWNvb3JkaW5hdGUgb2YgdGhlIHRleHQncyBwb3NpdGlvbi5cbiAgICAqIEBwYXJhbSB7bnVtYmVyfSB5IC0gVGhlIHktY29vcmRpbmF0ZSBvZiB0aGUgdGV4dCdzIHBvc2l0aW9uLlxuICAgICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gRGVwcmVjYXRlZC4gQ2FuIGJlIG51bGwuXG4gICAgKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gRGVwcmVjYXRlZC4gQ2FuIGJlIG51bGwuXG4gICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dCAtIFRoZSB0ZXh0IHRvIGRyYXcuXG4gICAgKiBAcGFyYW0ge2Jvb2xlYW59IHdvcmRXcmFwIC0gSWYgd29yZFdyYXAgaXMgc2V0IHRvIHRydWUsIGxpbmUtYnJlYWtzIGFyZSBhdXRvbWF0aWNhbGx5IGNyZWF0ZWQuXG4gICAgIyMjXG4gICAgZHJhd0Zvcm1hdHRlZFRleHRJbW1lZGlhdGVseTogKHgsIHksIHdpZHRoLCBoZWlnaHQsIHRleHQsIHdvcmRXcmFwKSAtPlxuICAgICAgICBAZHJhd0Zvcm1hdHRlZFRleHQoeCwgeSwgd2lkdGgsIGhlaWdodCwgdGV4dCwgd29yZFdyYXApXG4gICAgICAgIFxuICAgICAgICBsb29wXG4gICAgICAgICAgICBAbmV4dENoYXIoKVxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYgQGxpbmUgPj0gQG1heExpbmVzXG4gICAgICAgICAgICAgICAgQGlzUnVubmluZyA9IG5vXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgQGRyYXdOZXh0KClcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgIGJyZWFrIHVubGVzcyBAaXNSdW5uaW5nXG4gICAgICAgICAgICBcbiAgICAgICAgQGN1cnJlbnRZICs9IEBjdXJyZW50TGluZUhlaWdodCArIEBsaW5lU3BhY2luZ1xuICAgICAgICAgICAgXG4gICAgICAgIHJldHVybiBudWxsXG4gICAgXG4gICAgXG4gICAgIyMjKlxuICAgICogU3RhcnRzIHRoZSByZW5kZXJpbmctcHJvY2VzcyBmb3IgdGhlIG1lc3NhZ2UuXG4gICAgKlxuICAgICogQG1ldGhvZCBkcmF3Rm9ybWF0dGVkVGV4dFxuICAgICogQHBhcmFtIHtudW1iZXJ9IHggLSBUaGUgeC1jb29yZGluYXRlIG9mIHRoZSB0ZXh0J3MgcG9zaXRpb24uXG4gICAgKiBAcGFyYW0ge251bWJlcn0geSAtIFRoZSB5LWNvb3JkaW5hdGUgb2YgdGhlIHRleHQncyBwb3NpdGlvbi5cbiAgICAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aCAtIERlcHJlY2F0ZWQuIENhbiBiZSBudWxsLlxuICAgICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodCAtIERlcHJlY2F0ZWQuIENhbiBiZSBudWxsLlxuICAgICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUaGUgdGV4dCB0byBkcmF3LlxuICAgICogQHBhcmFtIHtib29sZWFufSB3b3JkV3JhcCAtIElmIHdvcmRXcmFwIGlzIHNldCB0byB0cnVlLCBsaW5lLWJyZWFrcyBhcmUgYXV0b21hdGljYWxseSBjcmVhdGVkLlxuICAgICMjI1xuICAgIGRyYXdGb3JtYXR0ZWRUZXh0OiAoeCwgeSwgd2lkdGgsIGhlaWdodCwgdGV4dCwgd29yZFdyYXApIC0+XG4gICAgICAgIHRleHQgPSB0ZXh0IHx8IFwiIFwiICMgVXNlIGEgc3BhY2UgY2hhcmFjdGVyIGlmIG5vIHRleHQgaXMgc3BlY2lmaWVkLlxuICAgICAgICBAZm9udC5zZXQoQG9iamVjdC5mb250KVxuICAgICAgICBAc3BlZWQgPSAxMSAtIE1hdGgucm91bmQoR2FtZU1hbmFnZXIuc2V0dGluZ3MubWVzc2FnZVNwZWVkICogMi41KVxuICAgICAgICBAaXNSdW5uaW5nID0geWVzXG4gICAgICAgIEBkcmF3SW1tZWRpYXRlbHkgPSBub1xuICAgICAgICBAbGluZUFuaW1hdGlvbkNvdW50ID0gQHNwZWVkXG4gICAgICAgIEBjdXJyZW50TGluZUhlaWdodCA9IDBcbiAgICAgICAgQGlzV2FpdGluZyA9IG5vXG4gICAgICAgIEB3YWl0Rm9yS2V5ID0gbm9cbiAgICAgICAgQGNoYXJJbmRleCA9IDBcbiAgICAgICAgQHRva2VuID0gbnVsbFxuICAgICAgICBAdG9rZW5JbmRleCA9IDBcbiAgICAgICAgQG1lc3NhZ2UgPSB0ZXh0XG4gICAgICAgIEBsaW5lID0gMFxuICAgICAgICBAY3VycmVudExpbmUgPSBAbGluZVxuICAgICAgICBjdXJyZW50WCA9IEBjdXJyZW50WCAjTWF0aC5tYXgoQGN1cnJlbnRYLCBAcGFkZGluZylcbiAgICAgICAgQGxpbmVzID0gQGNhbGN1bGF0ZUxpbmVzKGxjc20oQG1lc3NhZ2UpLCB3b3JkV3JhcCwgQGN1cnJlbnRYKVxuICAgICAgICBAc3ByaXRlcyA9IEBjcmVhdGVTcHJpdGVzKEBsaW5lcylcbiAgICAgICAgQGFsbFNwcml0ZXMgPSBAYWxsU3ByaXRlcy5jb25jYXQoQHNwcml0ZXMpXG4gICAgICAgIEBjdXJyZW50WCA9IGN1cnJlbnRYXG4gICAgICAgIEBjdXJyZW50U3ByaXRlID0gQHNwcml0ZXNbQGxpbmVdXG4gICAgICAgIEBjdXJyZW50U3ByaXRlLnggPSBAY3VycmVudFggKyBAb2JqZWN0Lm9yaWdpbi54ICsgQG9iamVjdC5kc3RSZWN0LnhcbiAgICAgICAgQG1heExpbmVzID0gQGNhbGN1bGF0ZU1heExpbmVzKEBsaW5lcylcbiAgICAgICAgQHRva2VuID0gQGxpbmVzW0BsaW5lXT8uY29udGVudFtAdG9rZW5JbmRleF0gfHwgbmV3IGdzLlJlbmRlcmVyVG9rZW4obnVsbCwgXCJcIilcbiAgICAgICAgXG4gICAgICAgIFxuICAgICAgICBAc3RhcnQoKVxuICAgICBcbiAgICAjIyMqXG4gICAgKiBTdGFydHMgdGhlIG1lc3NhZ2UtcmVuZGVyaW5nIHByb2Nlc3MuXG4gICAgKlxuICAgICogQG1ldGhvZCBzdGFydFxuICAgICogQHByb3RlY3RlZFxuICAgICMjIyAgICAgXG4gICAgc3RhcnQ6IC0+XG4gICAgICAgIGlmIEdhbWVNYW5hZ2VyLnRlbXBTZXR0aW5ncy5za2lwIGFuZCBHYW1lTWFuYWdlci50ZW1wU2V0dGluZ3Muc2tpcFRpbWUgPT0gMFxuICAgICAgICAgICAgQGluc3RhbnRTa2lwKClcbiAgICAgICAgZWxzZSBpZiBAbWF4TGluZXMgPT0gMFxuICAgICAgICAgICAgIyBJZiBmaXJzdCBsaW5lIGlzIGVtcHR5IHRoZW4gaXQgZG9lc24ndCBmaXQgaW50byBjdXJyZW50IGxpbmUsIHNvIGZpbmlzaC5cbiAgICAgICAgICAgIGlmIEBsaW5lc1swXT8uY29udGVudCA9PSBcIlwiXG4gICAgICAgICAgICAgICAgQGZpbmlzaCgpXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgQG1heExpbmVzID0gMVxuICAgICAgICAgICAgICAgIEBkcmF3TmV4dCgpXG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIEBkcmF3TmV4dCgpXG4gICAgIFxuICAgICMjIypcbiAgICAqIFNraXBzIHRoZSBjdXJyZW50IG1lc3NhZ2UgYW5kIGZpbmlzaGVzIHRoZSBtZXNzYWdlLXByb2Nlc3NpbmcgaW1tZWRpYXRlbHkuIFRoZSBtZXNzYWdlXG4gICAgKiB0b2tlbnMgYXJlIHByb2Nlc3NlZCBidXQgbm90IHJlbmRlcmVkLlxuICAgICpcbiAgICAqIEBtZXRob2QgaW5zdGFudFNraXBcbiAgICAjIyMgIFxuICAgIGluc3RhbnRTa2lwOiAtPlxuICAgICAgICBsb29wXG4gICAgICAgICAgICBpZiBAbGluZSA8IEBtYXhMaW5lc1xuICAgICAgICAgICAgICAgIEBuZXh0Q2hhcigpXG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiBAbGluZSA+PSBAbWF4TGluZXNcbiAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIEBwcm9jZXNzVG9rZW4oKVxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgYnJlYWsgdW5sZXNzIEBpc1J1bm5pbmcgYW5kIEBsaW5lIDwgQG1heExpbmVzXG4gICAgICAgIFxuICAgICAgICBAb2JqZWN0LmV2ZW50cz8uZW1pdChcIm1lc3NhZ2VXYWl0aW5nXCIsIHRoaXMpXG4gICAgICAgIEBjb250aW51ZSgpXG4gICAgICAgIFxuICAgICMjIypcbiAgICAqIFByb2Nlc3NlcyB0aGUgY3VycmVudCB0b2tlbi5cbiAgICAqXG4gICAgKiBAbWV0aG9kIHByb2Nlc3NUb2tlblxuICAgICMjIyAgICBcbiAgICBwcm9jZXNzVG9rZW46IC0+XG4gICAgICAgIHRva2VuID0gbnVsbFxuICAgICAgICBcbiAgICAgICAgaWYgQHRva2VuLmNvZGU/XG4gICAgICAgICAgICB0b2tlbiA9IEBwcm9jZXNzQ29udHJvbFRva2VuKEB0b2tlbiwgbm8pXG4gICAgICAgICAgICBpZiB0b2tlbj9cbiAgICAgICAgICAgICAgICBAdG9rZW4gPSB0b2tlblxuICAgICAgICAgICAgICAgIEB0b2tlbi5vblN0YXJ0PygpXG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRva2VuID0gQHRva2VuXG4gICAgICAgICAgICBcbiAgICAgICAgcmV0dXJuIHRva2VuXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG5ncy5Db21wb25lbnRfTWVzc2FnZVRleHRSZW5kZXJlciA9IENvbXBvbmVudF9NZXNzYWdlVGV4dFJlbmRlcmVyIl19\n//# sourceURL=Component_MessageTextRenderer_126.js"
13 13 },
14 14 "summary": [
15 15 "name",