Subversion Repository Public Repository

Nextrek

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
    "uid": "118CE96FK8F58A440CSAA11E22CCAF101A06",
    "isLoaded": true,
    "lastModificationTime": 0,
    "items": {
        "name": "Component_MessageTextRenderer",
        "type": "game_script",
        "order": 11,
        "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",
        "parentId": "D3325122KACDEA4515SB731E37A42B9D779F",
        "folder": false,
        "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"
    },
    "summary": [
        "name",
        "type",
        "order"
    ]
}

Commits for Nextrek/s2s/data/118CE96FK8F58A440CSAA11E22CCAF101A06.json

Diff revisions: vs.
Revision Author Commited Message
1086 Diff Diff ASorrentino picture ASorrentino Fri 11 May, 2018 21:50:37 +0000
1084 MOliva picture MOliva Fri 11 May, 2018 12:41:55 +0000