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

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

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