From aa17a402199a47e0ea5fc8d999559261afb79b54 Mon Sep 17 00:00:00 2001 From: Jeremy Labrado Date: Fri, 5 Dec 2025 11:37:31 +0100 Subject: [PATCH 1/2] feat: enhance product summary with health goals, religious requirements, and improved UI - Add support for health goals and religious dietary requirements in product analysis - Include detailed nutritional data (calories, carbs, sugars, fats, proteins, fiber, salt) - Integrate allergen tags, product labels, and categories from Open Food Facts API - Improve prompt to conditionally include only user-specified preferences - Modernize UI with card-based design for AI summary and generated images - Add emoji icons and improved typography for better visual hierarchy - Maintain comprehensive translations for all 5 languages (EN, FR, ES, IT, AR) --- README.md | 2 +- lambda/barcode_product_summary/index.js | 147 ++++++++++++------ lambda/recipe_step_by_step/index.js | 2 +- resources/ui/src/assets/i18n/all.ts | 10 ++ .../pages/components/barcode_ingredients.tsx | 6 +- .../components/barcode_product_summary.tsx | 98 +++++++----- 6 files changed, 171 insertions(+), 94 deletions(-) diff --git a/README.md b/README.md index 4b03d6e..d147258 100644 --- a/README.md +++ b/README.md @@ -223,7 +223,7 @@ The output format is a Markdown file to faciliate the display of the recipe on t - **Challenge**: Present the application in multiple languages -- **Solution**: The same prompt is utilized, but the LLM is instructed to generate the output in a specific language, catering to the user's language preference (English/French). +- **Solution**: The same prompt is utilized, but the LLM is instructed to generate the output in a specific language, catering to the user's language preference (English, French, Spanish, Italian, Arabic). The UI includes comprehensive translations for all features including allergen warnings, ingredient descriptions, and nutritional information. **Direct Allergen Detection and Nutritional Analysis** diff --git a/lambda/barcode_product_summary/index.js b/lambda/barcode_product_summary/index.js index e4d6b49..b639ce7 100644 --- a/lambda/barcode_product_summary/index.js +++ b/lambda/barcode_product_summary/index.js @@ -12,56 +12,93 @@ const PRODUCT_TABLE_NAME = process.env.PRODUCT_TABLE_NAME; const PRODUCT_SUMMARY_TABLE_NAME = process.env.PRODUCT_SUMMARY_TABLE_NAME; const MODEL_ID = "anthropic.claude-3-haiku-20240307-v1:0"; const bedrockRuntimeClient = new client_bedrock_runtime_1.BedrockRuntimeClient({ region: process.env.REGION || 'us-east-1' }); -function generateProductSummaryPrompt(userAllergies, userPreference, productIngredients, productName, language) { - return `Human: - You are a nutrition expert with the task to provide recommendations about a specific product for the user based on the user's allergies and preferences. - Your task involves the following steps: +function generateProductSummaryPrompt(userAllergies, userPreference, userHealthGoal, userReligion, productIngredients, productName, productAllergens, productNutriments, productLabels, productCategories, language) { + // Format nutriments for display + let nutrimentInfo = ''; + if (productNutriments && Object.keys(productNutriments).length > 0) { + nutrimentInfo = '\n\n'; + if (productNutriments['energy-kcal_100g']) + nutrimentInfo += `Calories: ${productNutriments['energy-kcal_100g']} kcal\n`; + if (productNutriments['carbohydrates_100g']) + nutrimentInfo += `Carbohydrates: ${productNutriments['carbohydrates_100g']}g\n`; + if (productNutriments['sugars_100g']) + nutrimentInfo += `Sugars: ${productNutriments['sugars_100g']}g\n`; + if (productNutriments['fat_100g']) + nutrimentInfo += `Fat: ${productNutriments['fat_100g']}g\n`; + if (productNutriments['saturated-fat_100g']) + nutrimentInfo += `Saturated Fat: ${productNutriments['saturated-fat_100g']}g\n`; + if (productNutriments['proteins_100g']) + nutrimentInfo += `Protein: ${productNutriments['proteins_100g']}g\n`; + if (productNutriments['fiber_100g']) + nutrimentInfo += `Fiber: ${productNutriments['fiber_100g']}g\n`; + if (productNutriments['salt_100g']) + nutrimentInfo += `Salt: ${productNutriments['salt_100g']}g\n`; + nutrimentInfo += '\n'; + } + // Format allergens - only if user has allergies + let allergenInfo = ''; + if (userAllergies && productAllergens && productAllergens.length > 0) { + allergenInfo = `\n${productAllergens.join(', ')}\n`; + } + // Format labels + let labelInfo = ''; + if (productLabels && productLabels.length > 0) { + labelInfo = `\n${productLabels.join(', ')}\n`; + } + // Format categories + let categoryInfo = ''; + if (productCategories) { + categoryInfo = `\n${productCategories}\n`; + } + // Build instructions based on what user has set + let instructions = `You are a nutrition expert providing recommendations about a specific product. - 1. Use the user's allergy information, if provided, to ensure that the ingredients in the product are suitable for the user. - 2. Use the user's preferences, if provided, to ensure that the user will enjoy the product. Note that the product can contain additives listed in the additives. Make sure these additives are compatible with user allergies and preferences. - 3. Present three benefits and three disadvantages for the product, ensuring that each list consists of precisely three points. - 4. Provide nutritional recommendations for the product based on its ingredients and the user's needs. - - If the user's allergy information or preferences are not provided or are empty, offer general nutritional advice on the product. - - Example: - Chocolate and hazelnut spread - - {{ - Sucre, sirop de glucose, NOISETTES entières torréfiées, matières grasses végétales (palme, karité), beurre de cacao¹, LAIT entier en poudre, PETIT-LAIT filtré en poudre, LAIT écrémé concentré sucré (LAIT écrémé, sucre), sirop de glucose-fructose, pâte de cacao¹, blancs d'ŒUFS en poudre, émulsifiant (lécithines). Peut contenir ARACHIDES, autres FRUITS À COQUE (AMANDES, NOIX DE CAJOU, NOIX DE PECAN) et SOJA. ¹Bilan massique certifié Rainforest Alliance. www.ra.org/fr. - }} - - - I don't like chocolate - - Response: - - - - Although Nutella contains a small amount of calcium and iron, it's not very nutritious and high in sugar, calories and fat. - - - - {{benefit}} - - - {{disadvantage}} - - + Your task: + `; + if (userAllergies) { + instructions += `1. CRITICAL: Check if any product allergens match the user's allergies (${userAllergies}). If there is a match, prominently warn the user.\n`; + } + if (userPreference) { + instructions += `${userAllergies ? '2' : '1'}. Check if product labels match dietary preferences (${userPreference}). Use labels for direct matching, or analyze categories and ingredients.\n`; + } + if (userHealthGoal) { + instructions += `${(userAllergies ? 1 : 0) + (userPreference ? 1 : 0) + 1}. Use nutritional data to assess if the product aligns with the health goal: ${userHealthGoal}.\n`; + } + if (userReligion) { + instructions += `${(userAllergies ? 1 : 0) + (userPreference ? 1 : 0) + (userHealthGoal ? 1 : 0) + 1}. Check if product labels match religious requirement: ${userReligion}.\n`; + } + instructions += `- Present three nutritional benefits and three nutritional disadvantages for the product based on actual nutritionalvalues. + If the user's information is not provided or is empty, offer general nutritional advice based on the product's nutritional data. + IMPORTANT: Only mention allergens, dietary preferences, health goals, or religious requirements if the user has specified them. Do not discuss aspects the user hasn't set.`; + let userContext = ''; + if (userAllergies) + userContext += `\n${userAllergies}`; + if (userHealthGoal) + userContext += `\n${userHealthGoal}`; + if (userPreference) + userContext += `\n${userPreference}`; + if (userReligion) + userContext += `\n${userReligion}`; + return `Human: + ${instructions} - Provide recommendation for the following product - ${productName} - - ${productIngredients} - - ${userAllergies} - ${userPreference} + Provide recommendation for the following product: + ${productName} + ${productIngredients} + ${allergenInfo} + ${labelInfo} + ${categoryInfo} + ${nutrimentInfo} + + For the user: + ${userContext} + Provide the response in the third person, in ${language}, skip the preambule, disregard any content at the end and provide only the response in this Markdown format: markdown - Describe potential_health_issues, preference_matter and recommendation here combines in one single short paragraph + Describe allergen warnings (if any), dietary label compatibility, religious requirement compatibility, health goal compatibility, dietary preference compatibility, and recommendation here combined in one single short paragraph #### Benefits title here - Describe benefits here @@ -102,7 +139,7 @@ function calculateHash(productCode, userAllergies, userPreferenceData, language) * * @param productCode - The code of the product to retrieve information for. * @param language - The language for the product information. - * @returns A tuple containing product name, ingredients, and additives if the product is found in the database; otherwise, returns [null, null, null]. + * @returns A tuple containing product name, ingredients, additives, allergens, and nutriments if the product is found in the database; otherwise, returns [null, null, null, null, null]. */ async function getProductFromDb(productCode, language) { try { @@ -116,15 +153,23 @@ async function getProductFromDb(productCode, language) { // Check if the item exists if (Item) { const item = (0, util_dynamodb_1.unmarshall)(Item); - return [item.product_name || null, item.ingredients || null, item.additives || null]; + return [ + item.product_name || null, + item.ingredients || null, + item.additives || null, + item.allergens_tags || null, + item.nutriments || null, + item.labels_tags || null, + item.categories || null + ]; } else { - return [null, null, null]; + return [null, null, null, null, null, null, null]; } } catch (e) { console.error('Error while getting the Product from database', e); - return [null, null, null]; + return [null, null, null, null, null, null, null]; } } async function getProductSummary(productCode, paramsHash) { @@ -249,9 +294,11 @@ async function messageHandler(event, responseStream) { const language = body.language; const userPreferenceKeys = Object.keys(body.preferences).filter(key => body.preferences[key]); const userAllergiesKeys = Object.keys(body.allergies).filter(key => body.allergies[key]); + const userHealthGoal = body.healthGoal || ''; + const userReligion = body.religion || ''; const userPreferenceString = userPreferenceKeys.join(', '); const userAllergiesString = userAllergiesKeys.join(', '); - const [productName, productIngredients, productAdditives] = await getProductFromDb(productCode, language); + const [productName, productIngredients, productAdditives, productAllergens, productNutriments, productLabels, productCategories] = await getProductFromDb(productCode, language); if (productName && productIngredients) { logger.info("Product found"); } @@ -265,7 +312,7 @@ async function messageHandler(event, responseStream) { logger.info("Product Summary not found in the database"); const ingredientKeys = Object.keys(productIngredients); const ingredientsString = ingredientKeys.join(', '); - const promptText = generateProductSummaryPrompt(userAllergiesString, userPreferenceString, ingredientsString, productName, language); + const promptText = generateProductSummaryPrompt(userAllergiesString, userPreferenceString, userHealthGoal, userReligion, ingredientsString, productName, productAllergens || [], productNutriments || {}, productLabels || [], productCategories || '', language); productSummary = await generateSummary(promptText, responseStream); await putProductSummaryToDynamoDB(productCode, hashValue, productSummary); } @@ -280,4 +327,4 @@ async function messageHandler(event, responseStream) { responseStream.end(); } exports.handler = awslambda.streamifyResponse(messageHandler); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw4REFBMEY7QUFDMUYsMERBQW9EO0FBRXBELDBEQUF1RDtBQUV2RCxtQ0FBb0M7QUFDcEMsNEVBQTZHO0FBRTdHLE1BQU0sTUFBTSxHQUFHLElBQUksZUFBTSxFQUFFLENBQUM7QUFDNUIsTUFBTSxRQUFRLEdBQUcsSUFBSSxnQ0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBRXhDLE1BQU0sa0JBQWtCLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQTtBQUN6RCxNQUFNLDBCQUEwQixHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsMEJBQTBCLENBQUE7QUFDekUsTUFBTSxRQUFRLEdBQUcsd0NBQXdDLENBQUE7QUFJekQsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLDZDQUFvQixDQUFDLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxJQUFJLFdBQVcsRUFBRSxDQUFDLENBQUM7QUFzQ3JHLFNBQVMsNEJBQTRCLENBQ2pDLGFBQXFCLEVBQ3JCLGNBQXNCLEVBQ3RCLGtCQUEwQixFQUMxQixXQUFtQixFQUNuQixRQUFnQjtJQUVoQixPQUFPOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzBCQXFDZSxXQUFXOztZQUV6QixrQkFBa0I7OzRCQUVGLGFBQWE7OEJBQ1gsY0FBYzt5REFDYSxRQUFROzs7Ozs7Ozs7Ozs7OztXQWN0RCxDQUFDO0FBQ1osQ0FBQztBQUVELFNBQVMsc0JBQXNCLENBQUMsR0FBMkI7SUFDdkQsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNyRCxPQUFPLGtCQUFrQixDQUFDO0FBQzlCLENBQUM7QUFJRCxTQUFTLGFBQWEsQ0FDbEIsV0FBbUIsRUFDbkIsYUFBa0IsRUFDbEIsa0JBQXVCLEVBQ3ZCLFFBQWdCO0lBRWhCOzs7Ozs7Ozs7O09BVUc7SUFFSCx1Q0FBdUM7SUFDdkMsTUFBTSxnQkFBZ0IsR0FBRyxzQkFBc0IsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFBLGdDQUFnQztJQUMvRixNQUFNLHFCQUFxQixHQUFHLHNCQUFzQixDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFFekUsMERBQTBEO0lBQzFELE1BQU0sa0JBQWtCLEdBQUcsR0FBRyxXQUFXLEdBQUcsZ0JBQWdCLEdBQUcscUJBQXFCLEdBQUcsUUFBUSxFQUFFLENBQUM7SUFDbEcscUJBQXFCO0lBQ3JCLE1BQU0sV0FBVyxHQUFHLElBQUEsbUJBQVUsRUFBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFbEYsT0FBTyxXQUFXLENBQUM7QUFDdkIsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxXQUFtQixFQUFFLFFBQWdCO0lBRWpFLElBQUk7UUFDQSxNQUFNLEVBQUUsSUFBSSxHQUFJLEVBQUUsRUFBRSxHQUFHLE1BQU0sUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLGdDQUFjLENBQUM7WUFDMUQsU0FBUyxFQUFFLGtCQUFrQjtZQUM3QixHQUFHLEVBQUU7Z0JBQ0QsWUFBWSxFQUFFLEVBQUUsQ0FBQyxFQUFFLFdBQVcsRUFBRTtnQkFDaEMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxFQUFFLFFBQVEsRUFBRTthQUM1QjtTQUNKLENBQUMsQ0FBQyxDQUFDO1FBQ0osMkJBQTJCO1FBQzNCLElBQUksSUFBSSxFQUFFO1lBQ04sTUFBTSxJQUFJLEdBQUcsSUFBQSwwQkFBVSxFQUFDLElBQUksQ0FBZ0IsQ0FBQztZQUM3QyxPQUFPLENBQUMsSUFBSSxDQUFDLFlBQVksSUFBSSxJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVcsSUFBSSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsQ0FBQztTQUN4RjthQUFNO1lBQ0gsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDN0I7S0FDSjtJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1IsT0FBTyxDQUFDLEtBQUssQ0FBQywrQ0FBK0MsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNsRSxPQUFPLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztLQUM3QjtBQUNMLENBQUM7QUFFRCxLQUFLLFVBQVUsaUJBQWlCLENBQUMsV0FBbUIsRUFBRSxVQUFrQjtJQUNwRTs7Ozs7O09BTUc7SUFFSCxNQUFNLEVBQUUsSUFBSSxHQUFJLEVBQUUsRUFBRSxHQUFHLE1BQU0sUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLGdDQUFjLENBQUM7UUFDMUQsU0FBUyxFQUFFLDBCQUEwQjtRQUNyQyxHQUFHLEVBQUU7WUFDRCxZQUFZLEVBQUUsRUFBRSxDQUFDLEVBQUUsV0FBVyxFQUFFO1lBQ2hDLFdBQVcsRUFBRSxFQUFFLENBQUMsRUFBRSxVQUFVLEVBQUU7U0FDakM7S0FDSixDQUFDLENBQUMsQ0FBQztJQUVKLElBQUksSUFBSSxFQUFFO1FBQ1IsTUFBTSxJQUFJLEdBQUcsSUFBQSwwQkFBVSxFQUFDLElBQUksQ0FBdUIsQ0FBQztRQUNwRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7S0FDckI7U0FBTTtRQUNMLE9BQU8sSUFBSSxDQUFDO0tBQ2I7QUFDTCxDQUFDO0FBRUQsS0FBSyxVQUFVLGVBQWUsQ0FBQyxVQUFVLEVBQUUsY0FBYztJQUVyRCxNQUFNLE9BQU8sR0FBRztRQUNaLFFBQVEsRUFBRTtZQUNOO2dCQUNJLElBQUksRUFBRSxNQUFNO2dCQUNaLE9BQU8sRUFBRTtvQkFDTDt3QkFDSSxNQUFNLEVBQUUsTUFBTTt3QkFDZCxNQUFNLEVBQUUsVUFBVTtxQkFDckI7aUJBQ0o7YUFDSjtTQUNKO1FBQ0QsVUFBVSxFQUFFLEdBQUc7UUFDZixXQUFXLEVBQUUsR0FBRztRQUNoQixpQkFBaUIsRUFBRSxvQkFBb0I7S0FDeEMsQ0FBQztJQUNKLE1BQU0sTUFBTSxHQUFHO1FBQ1gsT0FBTyxFQUFFLFFBQVE7UUFDakIsV0FBVyxFQUFFLGtCQUFrQjtRQUMvQixNQUFNLEVBQUUsa0JBQWtCO1FBQzFCLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQztLQUNoQyxDQUFDO0lBQ0YsSUFBSSxVQUFVLEdBQUcsRUFBRSxDQUFDO0lBQ3BCLElBQUk7UUFDQSxJQUFJO1lBQ0EsTUFBTSxPQUFPLEdBQUcsSUFBSSw2REFBb0MsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNqRSxNQUFNLFFBQVEsR0FBRyxNQUFNLG9CQUFvQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUMxRCxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDO1lBQzdCLElBQUksS0FBSyxFQUFFLE1BQU0sS0FBSyxJQUFJLE1BQU0sSUFBSSxFQUFFLEVBQUU7Z0JBQ3BDLDhEQUE4RDtnQkFDOUQsSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFO29CQUNmLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQzlCLElBQUksV0FBVyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQzVDLENBQUM7b0JBQ0YsSUFBSSxhQUFhLENBQUMsSUFBSSxLQUFNLHFCQUFxQixJQUFJLGFBQWEsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLFlBQVksRUFBQzt3QkFDN0YsY0FBYyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFBO3dCQUM5QyxVQUFVLElBQUksYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUM7cUJBQ3hDO2lCQUNGO3FCQUFNO29CQUNMLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxLQUFLLEVBQUUsQ0FBQyxDQUFBO2lCQUNqQzthQUNGO1lBRUQsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQTtTQUNqQztRQUFDLE9BQU8sR0FBRyxFQUFFO1lBQ1YsZUFBZTtZQUNmLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBVSxDQUFDLENBQUM7U0FDNUI7S0FDSjtJQUNELE9BQU8sQ0FBQyxFQUFFO1FBQ04sTUFBTSxDQUFDLEtBQUssQ0FBQyxtQ0FBbUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNyRCxVQUFVLEdBQUcsZ0NBQWdDLENBQUM7S0FDakQ7SUFDRCxPQUFPLFVBQVUsQ0FBQztBQUN0QixDQUFDO0FBRUQsS0FBSyxVQUFVLHdCQUF3QixDQUFDLE9BQWUsRUFBRSxjQUFjO0lBRW5FLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQztJQUNsQixJQUFJLGdCQUFnQixHQUFHLE9BQU8sQ0FBQztJQUUvQiw4Q0FBOEM7SUFDOUMsT0FBTyxnQkFBZ0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1FBQ2hDLGdEQUFnRDtRQUNoRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFckQsd0RBQXdEO1FBQ3hELE1BQU0sS0FBSyxHQUFHLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFFbkQsNkJBQTZCO1FBQzdCLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFbkIsb0RBQW9EO1FBQ3BELGdCQUFnQixHQUFHLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztLQUN4RDtJQUVELHlEQUF5RDtJQUN6RCxLQUFLLE1BQU0sS0FBSyxJQUFJLE1BQU0sRUFBRTtRQUN4QixNQUFNLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsaUJBQWlCO1FBQ3hFLGNBQWMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUE7S0FFOUI7QUFDTCxDQUFDO0FBS0QsS0FBSyxVQUFVLDJCQUEyQixDQUFDLFlBQW9CLEVBQUUsV0FBbUIsRUFBRSxPQUFlO0lBQ2pHLElBQUk7UUFDQSxNQUFNLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxnQ0FBYyxDQUFDO1lBQ25DLFNBQVMsRUFBRSwwQkFBMEI7WUFDckMsSUFBSSxFQUFFO2dCQUNGLFlBQVksRUFBRSxFQUFFLENBQUMsRUFBRSxZQUFZLEVBQUU7Z0JBQ2pDLFdBQVcsRUFBRSxFQUFFLENBQUMsRUFBRSxXQUFXLEVBQUU7Z0JBQy9CLE9BQU8sRUFBRSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUU7YUFDMUI7U0FDSixDQUFDLENBQUMsQ0FBQztRQUNKLE1BQU0sQ0FBQyxLQUFLLENBQUMsNkJBQTZCLENBQUMsQ0FBQztLQUMvQztJQUFDLE9BQU8sS0FBSyxFQUFFO1FBQ1osT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDbEM7QUFDTCxDQUFDO0FBRUQsS0FBSyxVQUFVLGNBQWMsQ0FBRSxLQUFLLEVBQUUsY0FBYztJQUVoRCxJQUFJO1FBQ0EsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFZLENBQUMsQ0FBQztRQUUxQixNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3RELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7UUFDckMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUUvQixNQUFNLGtCQUFrQixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUM5RixNQUFNLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUV6RixNQUFNLG9CQUFvQixHQUFHLGtCQUFrQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMzRCxNQUFNLG1CQUFtQixHQUFHLGlCQUFpQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUd6RCxNQUFNLENBQUMsV0FBVyxFQUFFLGtCQUFrQixFQUFFLGdCQUFnQixDQUFDLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDMUcsSUFBSSxXQUFXLElBQUksa0JBQWtCLEVBQUU7WUFDbkMsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztTQUdoQzthQUFNO1lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO1lBQ2xELE1BQU0sSUFBSSxLQUFLLENBQUMsbUNBQW1DLENBQUMsQ0FBQztTQUN4RDtRQUVELE1BQU0sU0FBUyxHQUFHLGFBQWEsQ0FBQyxXQUFXLEVBQUUsbUJBQW1CLEVBQUUsb0JBQW9CLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFFbEcsSUFBSSxjQUFjLEdBQUcsTUFBTSxpQkFBaUIsQ0FBQyxXQUFXLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLGNBQWMsRUFBRTtZQUNqQixNQUFNLENBQUMsSUFBSSxDQUFDLDJDQUEyQyxDQUFDLENBQUM7WUFDekQsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1lBQ3ZELE1BQU0saUJBQWlCLEdBQUcsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUVwRCxNQUFNLFVBQVUsR0FBRyw0QkFBNEIsQ0FDM0MsbUJBQW1CLEVBQ25CLG9CQUFvQixFQUNwQixpQkFBaUIsRUFDakIsV0FBVyxFQUNYLFFBQVMsQ0FDWixDQUFDO1lBQ0YsY0FBYyxHQUFHLE1BQU0sZUFBZSxDQUFDLFVBQVUsRUFBRSxjQUFjLENBQUMsQ0FBQztZQUNuRSxNQUFNLDJCQUEyQixDQUFDLFdBQVcsRUFBRSxTQUFTLEVBQUUsY0FBYyxDQUFDLENBQUM7U0FDN0U7YUFDSTtZQUNELE1BQU0sd0JBQXdCLENBQUMsY0FBYyxFQUFFLGNBQWMsQ0FBQyxDQUFBO1NBRWpFO1FBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsY0FBYyxFQUFFLENBQUMsQ0FBQztLQUNyRDtJQUFDLE9BQU8sS0FBSyxFQUFFO1FBQ1osT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDbEM7SUFDRCxjQUFjLENBQUMsR0FBRyxFQUFFLENBQUM7QUFDekIsQ0FBQztBQUVZLFFBQUEsT0FBTyxHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxjQUFjLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IER5bmFtb0RCQ2xpZW50LCBHZXRJdGVtQ29tbWFuZCwgUHV0SXRlbUNvbW1hbmQgfSBmcm9tIFwiQGF3cy1zZGsvY2xpZW50LWR5bmFtb2RiXCI7XG5pbXBvcnQgeyB1bm1hcnNoYWxsIH0gZnJvbSBcIkBhd3Mtc2RrL3V0aWwtZHluYW1vZGJcIjtcbmltcG9ydCB7IFRyYWNlciB9IGZyb20gXCJAYXdzLWxhbWJkYS1wb3dlcnRvb2xzL3RyYWNlclwiO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSBcIkBhd3MtbGFtYmRhLXBvd2VydG9vbHMvbG9nZ2VyXCI7XG5pbXBvcnQgeyBBUElHYXRld2F5UHJveHlFdmVudFYyLCBIYW5kbGVyLCBDb250ZXh0IH0gZnJvbSAnYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7IEJlZHJvY2tSdW50aW1lQ2xpZW50LCBJbnZva2VNb2RlbFdpdGhSZXNwb25zZVN0cmVhbUNvbW1hbmQgfSBmcm9tIFwiQGF3cy1zZGsvY2xpZW50LWJlZHJvY2stcnVudGltZVwiO1xuXG5jb25zdCBsb2dnZXIgPSBuZXcgTG9nZ2VyKCk7XG5jb25zdCBkeW5hbW9kYiA9IG5ldyBEeW5hbW9EQkNsaWVudCh7fSk7XG5cbmNvbnN0IFBST0RVQ1RfVEFCTEVfTkFNRSA9IHByb2Nlc3MuZW52LlBST0RVQ1RfVEFCTEVfTkFNRVxuY29uc3QgUFJPRFVDVF9TVU1NQVJZX1RBQkxFX05BTUUgPSBwcm9jZXNzLmVudi5QUk9EVUNUX1NVTU1BUllfVEFCTEVfTkFNRVxuY29uc3QgTU9ERUxfSUQgPSBcImFudGhyb3BpYy5jbGF1ZGUtMy1oYWlrdS0yMDI0MDMwNy12MTowXCJcblxuXG5cbmNvbnN0IGJlZHJvY2tSdW50aW1lQ2xpZW50ID0gbmV3IEJlZHJvY2tSdW50aW1lQ2xpZW50KHsgcmVnaW9uOiBwcm9jZXNzLmVudi5SRUdJT04gfHwgJ3VzLWVhc3QtMScgfSk7XG5cblxuZGVjbGFyZSBnbG9iYWwge1xuICAgIG5hbWVzcGFjZSBhd3NsYW1iZGEge1xuICAgICAgZnVuY3Rpb24gc3RyZWFtaWZ5UmVzcG9uc2UoXG4gICAgICAgIGY6IChcbiAgICAgICAgICBldmVudDogQVBJR2F0ZXdheVByb3h5RXZlbnRWMixcbiAgICAgICAgICByZXNwb25zZVN0cmVhbTogTm9kZUpTLldyaXRhYmxlU3RyZWFtLFxuICAgICAgICAgIGNvbnRleHQ6IENvbnRleHRcbiAgICAgICAgKSA9PiBQcm9taXNlPHZvaWQ+XG4gICAgICApOiBIYW5kbGVyO1xuICAgIH1cbn1cblxuXG5cbmludGVyZmFjZSBQcm9kdWN0SXRlbSB7XG4gICAgcHJvZHVjdF9jb2RlOiBzdHJpbmc7XG4gICAgbGFuZ3VhZ2U6IHN0cmluZztcbiAgICBwcm9kdWN0X25hbWU/OiBzdHJpbmc7XG4gICAgaW5ncmVkaWVudHM/OiBzdHJpbmc7XG4gICAgYWRkaXRpdmVzPzogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgUHJvZHVjdFN1bW1hcnlJdGVtIHtcbiAgICBwcm9kdWN0X2NvZGU6IHN0cmluZztcbiAgICBwYXJhbXNfaGFzaDogc3RyaW5nO1xuICAgIHN1bW1hcnk6IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIFN1bW1hcnlEYXRhIHtcbiAgICByZWNvbW1lbmRhdGlvbnM6IHN0cmluZ1tdO1xuICAgIGJlbmVmaXRzOiBzdHJpbmdbXTtcbiAgICBkaXNhZHZhbnRhZ2VzOiBzdHJpbmdbXTtcbiAgfVxuXG5cbmZ1bmN0aW9uIGdlbmVyYXRlUHJvZHVjdFN1bW1hcnlQcm9tcHQoXG4gICAgdXNlckFsbGVyZ2llczogc3RyaW5nLFxuICAgIHVzZXJQcmVmZXJlbmNlOiBzdHJpbmcsXG4gICAgcHJvZHVjdEluZ3JlZGllbnRzOiBzdHJpbmcsXG4gICAgcHJvZHVjdE5hbWU6IHN0cmluZyxcbiAgICBsYW5ndWFnZTogc3RyaW5nXG4gICAgKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYEh1bWFuOlxuICAgICAgICAgIFlvdSBhcmUgYSBudXRyaXRpb24gZXhwZXJ0IHdpdGggdGhlIHRhc2sgdG8gcHJvdmlkZSByZWNvbW1lbmRhdGlvbnMgYWJvdXQgYSBzcGVjaWZpYyBwcm9kdWN0IGZvciB0aGUgdXNlciBiYXNlZCBvbiB0aGUgdXNlcidzIGFsbGVyZ2llcyBhbmQgcHJlZmVyZW5jZXMuIFxuICAgICAgICAgIFlvdXIgdGFzayBpbnZvbHZlcyB0aGUgZm9sbG93aW5nIHN0ZXBzOlxuXG4gICAgICAgICAgMS4gVXNlIHRoZSB1c2VyJ3MgYWxsZXJneSBpbmZvcm1hdGlvbiwgaWYgcHJvdmlkZWQsIHRvIGVuc3VyZSB0aGF0IHRoZSBpbmdyZWRpZW50cyBpbiB0aGUgcHJvZHVjdCBhcmUgc3VpdGFibGUgZm9yIHRoZSB1c2VyLlxuICAgICAgICAgIDIuIFVzZSB0aGUgdXNlcidzIHByZWZlcmVuY2VzLCBpZiBwcm92aWRlZCwgdG8gZW5zdXJlIHRoYXQgdGhlIHVzZXIgd2lsbCBlbmpveSB0aGUgcHJvZHVjdC4gTm90ZSB0aGF0IHRoZSBwcm9kdWN0IGNhbiBjb250YWluIGFkZGl0aXZlcyBsaXN0ZWQgaW4gdGhlIGFkZGl0aXZlcy4gTWFrZSBzdXJlIHRoZXNlIGFkZGl0aXZlcyBhcmUgY29tcGF0aWJsZSB3aXRoIHVzZXIgYWxsZXJnaWVzIGFuZCBwcmVmZXJlbmNlcy5cbiAgICAgICAgICAzLiBQcmVzZW50IHRocmVlIGJlbmVmaXRzIGFuZCB0aHJlZSBkaXNhZHZhbnRhZ2VzIGZvciB0aGUgcHJvZHVjdCwgZW5zdXJpbmcgdGhhdCBlYWNoIGxpc3QgY29uc2lzdHMgb2YgcHJlY2lzZWx5IHRocmVlIHBvaW50cy5cbiAgICAgICAgICA0LiBQcm92aWRlIG51dHJpdGlvbmFsIHJlY29tbWVuZGF0aW9ucyBmb3IgdGhlIHByb2R1Y3QgYmFzZWQgb24gaXRzIGluZ3JlZGllbnRzIGFuZCB0aGUgdXNlcidzIG5lZWRzLlxuICBcbiAgICAgICAgICBJZiB0aGUgdXNlcidzIGFsbGVyZ3kgaW5mb3JtYXRpb24gb3IgcHJlZmVyZW5jZXMgYXJlIG5vdCBwcm92aWRlZCBvciBhcmUgZW1wdHksIG9mZmVyIGdlbmVyYWwgbnV0cml0aW9uYWwgYWR2aWNlIG9uIHRoZSBwcm9kdWN0LlxuICBcbiAgICAgICAgICBFeGFtcGxlOlxuICAgICAgICAgIDxwcm9kdWN0X25hbWU+Q2hvY29sYXRlIGFuZCBoYXplbG51dCBzcHJlYWQ8L3Byb2R1Y3RfbmFtZT5cbiAgICAgICAgICA8cHJvZHVjdF9pbmdyZWRpZW50cz5cbiAgICAgICAgICB7e1xuICAgICAgICAgICAgICBTdWNyZSwgc2lyb3AgZGUgZ2x1Y29zZSwgTk9JU0VUVEVTIGVudGnDqHJlcyB0b3Jyw6lmacOpZXMsIG1hdGnDqHJlcyBncmFzc2VzIHbDqWfDqXRhbGVzIChwYWxtZSwga2FyaXTDqSksIGJldXJyZSBkZSBjYWNhb8K5LCBMQUlUIGVudGllciBlbiBwb3VkcmUsIFBFVElULUxBSVQgZmlsdHLDqSBlbiBwb3VkcmUsIExBSVQgw6ljcsOpbcOpIGNvbmNlbnRyw6kgc3VjcsOpIChMQUlUIMOpY3LDqW3DqSwgc3VjcmUpLCBzaXJvcCBkZSBnbHVjb3NlLWZydWN0b3NlLCBww6J0ZSBkZSBjYWNhb8K5LCBibGFuY3MgZCfFklVGUyBlbiBwb3VkcmUsIMOpbXVsc2lmaWFudCAobMOpY2l0aGluZXMpLiBQZXV0IGNvbnRlbmlyIEFSQUNISURFUywgYXV0cmVzIEZSVUlUUyDDgCBDT1FVRSAoQU1BTkRFUywgTk9JWCBERSBDQUpPVSwgTk9JWCBERSBQRUNBTikgZXQgU09KQS4gwrlCaWxhbiBtYXNzaXF1ZSBjZXJ0aWZpw6kgUmFpbmZvcmVzdCBBbGxpYW5jZS4gd3d3LnJhLm9yZy9mci5cbiAgICAgICAgICB9fVxuICAgICAgICAgIDwvcHJvZHVjdF9pbmdyZWRpZW50cz5cbiAgICAgICAgICA8dXNlcl9hbGxlcmdpZXM+PC91c2VyX2FsbGVyZ2llcz5cbiAgICAgICAgICA8dXNlcl9wcmVmZXJlbmNlcz5JIGRvbid0IGxpa2UgY2hvY29sYXRlPC91c2VyX3ByZWZlcmVuY2VzPlxuICAgICAgICAgIDwvZXhhbXBsZT5cbiAgICAgICAgICBSZXNwb25zZTogXG4gICAgICAgICAgPGRhdGE+XG4gICAgICAgICAgICAgIDxyZWNvbW1lbmRhdGlvbnM+XG4gICAgICAgICAgICAgICAgICA8cmVjb21tZW5kYXRpb24+XG4gICAgICAgICAgICAgICAgICBBbHRob3VnaCBOdXRlbGxhIGNvbnRhaW5zIGEgc21hbGwgYW1vdW50IG9mIGNhbGNpdW0gYW5kIGlyb24sIGl0J3Mgbm90IHZlcnkgbnV0cml0aW91cyBhbmQgaGlnaCBpbiBzdWdhciwgY2Fsb3JpZXMgYW5kIGZhdC5cbiAgICAgICAgICAgICAgICAgIDwvcmVjb21tZW5kYXRpb24+XG4gICAgICAgICAgICAgIDwvcmVjb21tZW5kYXRpb25zPlxuICAgICAgICAgICAgICA8YmVuZWZpdHM+XG4gICAgICAgICAgICAgICAgICA8YmVuZWZpdD57e2JlbmVmaXR9fTwvYmVuZWZpdD5cbiAgICAgICAgICAgICAgPC9iZW5lZml0cz5cbiAgICAgICAgICAgICAgPGRpc2FkdmFudGFnZXM+XG4gICAgICAgICAgICAgICAgICA8ZGlzYWR2YW50YWdlPnt7ZGlzYWR2YW50YWdlfX08L2Rpc2FkdmFudGFnZT5cbiAgICAgICAgICAgICAgPC9kaXNhZHZhbnRhZ2VzPiAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgPC9kYXRhPlxuICBcbiAgICAgICAgICBQcm92aWRlIHJlY29tbWVuZGF0aW9uIGZvciB0aGUgZm9sbG93aW5nIHByb2R1Y3RcbiAgICAgICAgICA8cHJvZHVjdF9uYW1lPiR7cHJvZHVjdE5hbWV9PC9wcm9kdWN0X25hbWU+XG4gICAgICAgICAgPHByb2R1Y3RfaW5ncmVkaWVudHM+XG4gICAgICAgICAgJHtwcm9kdWN0SW5ncmVkaWVudHN9XG4gICAgICAgICAgPC9wcm9kdWN0X2luZ3JlZGllbnRzPlxuICAgICAgICAgIDx1c2VyX2FsbGVyZ2llcz4ke3VzZXJBbGxlcmdpZXN9PC91c2VyX2FsbGVyZ2llcz5cbiAgICAgICAgICA8dXNlcl9wcmVmZXJlbmNlcz4ke3VzZXJQcmVmZXJlbmNlfTwvdXNlcl9wcmVmZXJlbmNlcz5cbiAgICAgICAgICBQcm92aWRlIHRoZSByZXNwb25zZSBpbiB0aGUgdGhpcmQgcGVyc29uLCBpbiAke2xhbmd1YWdlfSwgc2tpcCB0aGUgcHJlYW1idWxlLCBkaXNyZWdhcmQgYW55IGNvbnRlbnQgYXQgdGhlIGVuZCBhbmQgcHJvdmlkZSBvbmx5IHRoZSByZXNwb25zZSBpbiB0aGlzIE1hcmtkb3duIGZvcm1hdDpcblxuXG4gICAgICAgIG1hcmtkb3duXG5cbiAgICAgICAgRGVzY3JpYmUgcG90ZW50aWFsX2hlYWx0aF9pc3N1ZXMsIHByZWZlcmVuY2VfbWF0dGVyIGFuZCByZWNvbW1lbmRhdGlvbiBoZXJlIGNvbWJpbmVzIGluIG9uZSBzaW5nbGUgc2hvcnQgcGFyYWdyYXBoXG5cbiAgICAgICAgIyMjIyBCZW5lZml0cyB0aXRsZSBoZXJlXG4gICAgICAgIC0gRGVzY3JpYmUgYmVuZWZpdHMgaGVyZVxuXG4gICAgICAgICMjIyMgRGlzYWR2YW50YWdlcyB0aXRsZSBoZXJlXG4gICAgICAgIC0gRGVzY3JpYmUgZGlzYWR2YW50YWdlcyBoZXJlXG4gICAgICAgICAgXG4gICAgICAgICAgQXNzaXN0YW50OlxuICAgICAgICAgIGA7XG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlQ29tYmluZWRTdHJpbmcob2JqOiB7IFtrZXk6IHN0cmluZ106IGFueSB9KTogc3RyaW5nIHtcbiAgICBjb25zdCBjb25jYXRlbmF0ZWRTdHJpbmcgPSBPYmplY3Qua2V5cyhvYmopLmpvaW4oJycpO1xuICAgIHJldHVybiBjb25jYXRlbmF0ZWRTdHJpbmc7XG59XG5cblxuXG5mdW5jdGlvbiBjYWxjdWxhdGVIYXNoKFxuICAgIHByb2R1Y3RDb2RlOiBzdHJpbmcsXG4gICAgdXNlckFsbGVyZ2llczogYW55LFxuICAgIHVzZXJQcmVmZXJlbmNlRGF0YTogYW55LFxuICAgIGxhbmd1YWdlOiBzdHJpbmdcbiAgICApOiBzdHJpbmcge1xuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZXMgYSBTSEEtMjU2IGhhc2ggYmFzZWQgb24gdmFyaW91cyBpbnB1dCBkYXRhLlxuICAgICAqXG4gICAgICogQHBhcmFtIHVzZXJBbGxlcmdpZXMgLSBBIHN0cmluZyBjb250YWluaW5nIHVzZXIgYWxsZXJnaWVzIGRhdGEuXG4gICAgICogQHBhcmFtIHVzZXJQcmVmZXJlbmNlRGF0YSAtIEEgc3RyaW5nIGNvbnRhaW5pbmcgdXNlciBwcmVmZXJlbmNlIGRhdGEuXG4gICAgICogQHBhcmFtIHByb2R1Y3RJbmdyZWRpZW50cyAtIEEgc3RyaW5nIGNvbnRhaW5pbmcgcHJvZHVjdCBpbmdyZWRpZW50cyBkYXRhLlxuICAgICAqIEBwYXJhbSBwcm9kdWN0TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9kdWN0LlxuICAgICAqIEBwYXJhbSBsYW5ndWFnZSAtIFRoZSBsYW5ndWFnZS5cbiAgICAgKiBAcGFyYW0gcHJvZHVjdEFkZGl0aXZlcyAtIEEgc3RyaW5nIGNvbnRhaW5pbmcgcHJvZHVjdCBhZGRpdGl2ZXMgZGF0YS5cbiAgICAgKiBAcmV0dXJucyBUaGUgU0hBLTI1NiBoYXNoIHZhbHVlIGNhbGN1bGF0ZWQgYmFzZWQgb24gdGhlIGNvbmNhdGVuYXRlZCBzdHJpbmcgcmVwcmVzZW50YXRpb25zIG9mIHRoZSBpbnB1dCBkYXRhLlxuICAgICAqL1xuXG4gICAgLy8gQ29udmVydCBkaWN0aW9uYXJpZXMgdG8gSlNPTiBzdHJpbmdzXG4gICAgY29uc3QgdXNlckFsbGVyZ2llc1N0ciA9IGdlbmVyYXRlQ29tYmluZWRTdHJpbmcodXNlckFsbGVyZ2llcyk7Ly9KU09OLnN0cmluZ2lmeSh1c2VyQWxsZXJnaWVzKTtcbiAgICBjb25zdCB1c2VyUHJlZmVyZW5jZURhdGFTdHIgPSBnZW5lcmF0ZUNvbWJpbmVkU3RyaW5nKHVzZXJQcmVmZXJlbmNlRGF0YSk7XG4gICAgXG4gICAgLy8gQ29uY2F0ZW5hdGUgdGhlIHN0cmluZyByZXByZXNlbnRhdGlvbnMgb2YgdGhlIHZhcmlhYmxlc1xuICAgIGNvbnN0IGNvbmNhdGVuYXRlZFN0cmluZyA9IGAke3Byb2R1Y3RDb2RlfSR7dXNlckFsbGVyZ2llc1N0cn0ke3VzZXJQcmVmZXJlbmNlRGF0YVN0cn0ke2xhbmd1YWdlfWA7XG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBoYXNoXG4gICAgY29uc3QgaGFzaGVkVmFsdWUgPSBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoY29uY2F0ZW5hdGVkU3RyaW5nKS5kaWdlc3QoJ2hleCcpO1xuICAgIFxuICAgIHJldHVybiBoYXNoZWRWYWx1ZTtcbn1cblxuLyoqXG4gKiBSZXRyaWV2ZXMgcHJvZHVjdCBpbmZvcm1hdGlvbiBmcm9tIHRoZSBkYXRhYmFzZSB1c2luZyB0aGUgcHJvdmlkZWQgcHJvZHVjdCBjb2RlLlxuICpcbiAqIEBwYXJhbSBwcm9kdWN0Q29kZSAtIFRoZSBjb2RlIG9mIHRoZSBwcm9kdWN0IHRvIHJldHJpZXZlIGluZm9ybWF0aW9uIGZvci5cbiAqIEBwYXJhbSBsYW5ndWFnZSAtIFRoZSBsYW5ndWFnZSBmb3IgdGhlIHByb2R1Y3QgaW5mb3JtYXRpb24uXG4gKiBAcmV0dXJucyBBIHR1cGxlIGNvbnRhaW5pbmcgcHJvZHVjdCBuYW1lLCBpbmdyZWRpZW50cywgYW5kIGFkZGl0aXZlcyBpZiB0aGUgcHJvZHVjdCBpcyBmb3VuZCBpbiB0aGUgZGF0YWJhc2U7IG90aGVyd2lzZSwgcmV0dXJucyBbbnVsbCwgbnVsbCwgbnVsbF0uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdldFByb2R1Y3RGcm9tRGIocHJvZHVjdENvZGU6IHN0cmluZywgbGFuZ3VhZ2U6IHN0cmluZyk6IFByb21pc2U8W3N0cmluZyB8IG51bGwsIHN0cmluZyB8IG51bGwsIHN0cmluZyB8IG51bGxdPiB7XG5cbiAgICB0cnkge1xuICAgICAgICBjb25zdCB7IEl0ZW0gID0ge30gfSA9IGF3YWl0IGR5bmFtb2RiLnNlbmQobmV3IEdldEl0ZW1Db21tYW5kKHtcbiAgICAgICAgICAgIFRhYmxlTmFtZTogUFJPRFVDVF9UQUJMRV9OQU1FLFxuICAgICAgICAgICAgS2V5OiB7XG4gICAgICAgICAgICAgICAgcHJvZHVjdF9jb2RlOiB7IFM6IHByb2R1Y3RDb2RlIH0sXG4gICAgICAgICAgICAgICAgbGFuZ3VhZ2U6IHsgUzogbGFuZ3VhZ2UgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KSk7XG4gICAgICAgIC8vIENoZWNrIGlmIHRoZSBpdGVtIGV4aXN0c1xuICAgICAgICBpZiAoSXRlbSkge1xuICAgICAgICAgICAgY29uc3QgaXRlbSA9IHVubWFyc2hhbGwoSXRlbSkgYXMgUHJvZHVjdEl0ZW07XG4gICAgICAgICAgICByZXR1cm4gW2l0ZW0ucHJvZHVjdF9uYW1lIHx8IG51bGwsIGl0ZW0uaW5ncmVkaWVudHMgfHwgbnVsbCwgaXRlbS5hZGRpdGl2ZXMgfHwgbnVsbF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gW251bGwsIG51bGwsIG51bGxdO1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciB3aGlsZSBnZXR0aW5nIHRoZSBQcm9kdWN0IGZyb20gZGF0YWJhc2UnLCBlKTtcbiAgICAgICAgcmV0dXJuIFtudWxsLCBudWxsLCBudWxsXTtcbiAgICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldFByb2R1Y3RTdW1tYXJ5KHByb2R1Y3RDb2RlOiBzdHJpbmcsIHBhcmFtc0hhc2g6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgc3VtbWFyeSBvZiBhIHByb2R1Y3QgZnJvbSB0aGUgZGF0YWJhc2UgdXNpbmcgdGhlIHByb2R1Y3QgY29kZSBhbmQgcGFyYW1ldGVycyBoYXNoLlxuICAgICAqXG4gICAgICogQHBhcmFtIHByb2R1Y3RDb2RlIC0gVGhlIGNvZGUgb2YgdGhlIHByb2R1Y3QuXG4gICAgICogQHBhcmFtIHBhcmFtc0hhc2ggLSBUaGUgaGFzaCB2YWx1ZSByZXByZXNlbnRpbmcgcGFyYW1ldGVycy5cbiAgICAgKiBAcmV0dXJucyBUaGUgc3VtbWFyeSBvZiB0aGUgcHJvZHVjdCBpZiBmb3VuZCBpbiB0aGUgZGF0YWJhc2U7IG90aGVyd2lzZSwgcmV0dXJucyBudWxsLlxuICAgICAqL1xuICBcbiAgICBjb25zdCB7IEl0ZW0gID0ge30gfSA9IGF3YWl0IGR5bmFtb2RiLnNlbmQobmV3IEdldEl0ZW1Db21tYW5kKHtcbiAgICAgICAgVGFibGVOYW1lOiBQUk9EVUNUX1NVTU1BUllfVEFCTEVfTkFNRSxcbiAgICAgICAgS2V5OiB7XG4gICAgICAgICAgICBwcm9kdWN0X2NvZGU6IHsgUzogcHJvZHVjdENvZGUgfSxcbiAgICAgICAgICAgIHBhcmFtc19oYXNoOiB7IFM6IHBhcmFtc0hhc2ggfVxuICAgICAgICB9XG4gICAgfSkpO1xuICBcbiAgICBpZiAoSXRlbSkge1xuICAgICAgY29uc3QgaXRlbSA9IHVubWFyc2hhbGwoSXRlbSkgYXMgUHJvZHVjdFN1bW1hcnlJdGVtO1xuICAgICAgcmV0dXJuIGl0ZW0uc3VtbWFyeTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBnZW5lcmF0ZVN1bW1hcnkocHJvbXB0VGV4dCwgcmVzcG9uc2VTdHJlYW0pIHtcblxuICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgIG1lc3NhZ2VzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgcm9sZTogXCJ1c2VyXCIsXG4gICAgICAgICAgICAgICAgY29udGVudDogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBcInR5cGVcIjogXCJ0ZXh0XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBcInRleHRcIjogcHJvbXB0VGV4dFxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgfVxuICAgICAgICBdLFxuICAgICAgICBtYXhfdG9rZW5zOiA1MDAsXG4gICAgICAgIHRlbXBlcmF0dXJlOiAwLjUsXG4gICAgICAgIGFudGhyb3BpY192ZXJzaW9uOiBcImJlZHJvY2stMjAyMy0wNS0zMVwiXG4gICAgICB9O1xuICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgbW9kZWxJZDogTU9ERUxfSUQsXG4gICAgICAgIGNvbnRlbnRUeXBlOiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgICAgYWNjZXB0OiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkocGF5bG9hZCksXG4gICAgfTtcbiAgICBsZXQgY29tcGxldGlvbiA9ICcnO1xuICAgIHRyeSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBjb21tYW5kID0gbmV3IEludm9rZU1vZGVsV2l0aFJlc3BvbnNlU3RyZWFtQ29tbWFuZChwYXJhbXMpO1xuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBiZWRyb2NrUnVudGltZUNsaWVudC5zZW5kKGNvbW1hbmQpO1xuICAgICAgICAgICAgY29uc3QgZXZlbnRzID0gcmVzcG9uc2UuYm9keTtcbiAgICAgICAgICAgIGZvciBhd2FpdCAoY29uc3QgZXZlbnQgb2YgZXZlbnRzIHx8IFtdKSB7XG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgdGhlIHRvcC1sZXZlbCBmaWVsZCB0byBkZXRlcm1pbmUgd2hpY2ggZXZlbnQgdGhpcyBpcy5cbiAgICAgICAgICAgICAgICBpZiAoZXZlbnQuY2h1bmspIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGRlY29kZWRfZXZlbnQgPSBKU09OLnBhcnNlKFxuICAgICAgICAgICAgICAgICAgICBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUoZXZlbnQuY2h1bmsuYnl0ZXMpLFxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgIGlmIChkZWNvZGVkX2V2ZW50LnR5cGUgID09PSAnY29udGVudF9ibG9ja19kZWx0YScgJiYgZGVjb2RlZF9ldmVudC5kZWx0YS50eXBlID09PSAndGV4dF9kZWx0YScpe1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVN0cmVhbS53cml0ZShkZWNvZGVkX2V2ZW50LmRlbHRhLnRleHQpXG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRpb24gKz0gZGVjb2RlZF9ldmVudC5kZWx0YS50ZXh0O1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoYGV2ZW50ID0gJHtldmVudH1gKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXG4gICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdTdHJlYW0gZW5kZWQhJylcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAvLyBoYW5kbGUgZXJyb3JcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnIgYXMgYW55KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoYEVycm9yIHdoaWxlIGdlbmVyYXRpbmcgc3VtbWFyeTogJHtlfWApO1xuICAgICAgICBjb21wbGV0aW9uID0gXCJFcnJvciB3aGlsZSBnZW5lcmF0aW5nIHN1bW1hcnlcIjtcbiAgICB9XG4gICAgcmV0dXJuIGNvbXBsZXRpb247XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNpbXVsYXRlU3VtbWFyeVN0cmVhbWluZyhjb250ZW50OiBzdHJpbmcsIHJlc3BvbnNlU3RyZWFtKTogUHJvbWlzZTx2b2lkPiB7XG4gICBcbiAgICBjb25zdCBjaHVua3MgPSBbXTtcbiAgICBsZXQgcmVtYWluaW5nQ29udGVudCA9IGNvbnRlbnQ7XG5cbiAgICAvLyBMb29wIHVudGlsIGFsbCBjb250ZW50IGlzIHNwbGl0IGludG8gY2h1bmtzXG4gICAgd2hpbGUgKHJlbWFpbmluZ0NvbnRlbnQubGVuZ3RoID4gMCkge1xuICAgICAgICAvLyBHZW5lcmF0ZSBhIHJhbmRvbSBjaHVuayBzaXplIGJldHdlZW4gMSBhbmQgMTBcbiAgICAgICAgY29uc3QgY2h1bmtTaXplID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMTApICsgMTtcblxuICAgICAgICAvLyBUYWtlIGEgY2h1bmsgb2YgY29udGVudCB3aXRoIHRoZSBnZW5lcmF0ZWQgY2h1bmsgc2l6ZVxuICAgICAgICBjb25zdCBjaHVuayA9IHJlbWFpbmluZ0NvbnRlbnQuc2xpY2UoMCwgY2h1bmtTaXplKTtcblxuICAgICAgICAvLyBBZGQgdGhlIGNodW5rIHRvIHRoZSBhcnJheVxuICAgICAgICBjaHVua3MucHVzaChjaHVuayk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIHRoZSB0YWtlbiBjaHVuayBmcm9tIHRoZSByZW1haW5pbmcgY29udGVudFxuICAgICAgICByZW1haW5pbmdDb250ZW50ID0gcmVtYWluaW5nQ29udGVudC5zbGljZShjaHVua1NpemUpO1xuICAgIH1cblxuICAgIC8vIFNpbXVsYXRlIHN0cmVhbWluZyBieSBlbWl0dGluZyBlYWNoIGNodW5rIHdpdGggYSBkZWxheVxuICAgIGZvciAoY29uc3QgY2h1bmsgb2YgY2h1bmtzKSB7XG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCA1MCkpOyAvLyBTaW11bGF0ZSBkZWxheVxuICAgICAgICByZXNwb25zZVN0cmVhbS53cml0ZShjaHVuaylcblxuICAgIH1cbn1cblxuXG5cblxuYXN5bmMgZnVuY3Rpb24gcHV0UHJvZHVjdFN1bW1hcnlUb0R5bmFtb0RCKHByb2R1Y3RfY29kZTogc3RyaW5nLCBwYXJhbXNfaGFzaDogc3RyaW5nLCBzdW1tYXJ5OiBzdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBkeW5hbW9kYi5zZW5kKG5ldyBQdXRJdGVtQ29tbWFuZCh7XG4gICAgICAgICAgICBUYWJsZU5hbWU6IFBST0RVQ1RfU1VNTUFSWV9UQUJMRV9OQU1FLFxuICAgICAgICAgICAgSXRlbToge1xuICAgICAgICAgICAgICAgIHByb2R1Y3RfY29kZTogeyBTOiBwcm9kdWN0X2NvZGUgfSxcbiAgICAgICAgICAgICAgICBwYXJhbXNfaGFzaDogeyBTOiBwYXJhbXNfaGFzaCB9LFxuICAgICAgICAgICAgICAgIHN1bW1hcnk6IHsgUzogc3VtbWFyeSB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pKTtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKFwiU3VtbWFyeSBzYXZlZCBpbnRvIGRhdGFiYXNlXCIpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvcjpcIiwgZXJyb3IpO1xuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gbWVzc2FnZUhhbmRsZXIgKGV2ZW50LCByZXNwb25zZVN0cmVhbSkge1xuXG4gICAgdHJ5IHtcbiAgICAgICAgbG9nZ2VyLmluZm8oZXZlbnQgYXMgYW55KTtcblxuICAgICAgICBjb25zdCBib2R5ID0gZXZlbnQuYm9keSA/IEpTT04ucGFyc2UoZXZlbnQuYm9keSkgOiB7fTtcbiAgICAgICAgY29uc3QgcHJvZHVjdENvZGUgPSBib2R5LnByb2R1Y3RDb2RlO1xuICAgICAgICBjb25zdCBsYW5ndWFnZSA9IGJvZHkubGFuZ3VhZ2U7XG5cbiAgICAgICAgY29uc3QgdXNlclByZWZlcmVuY2VLZXlzID0gT2JqZWN0LmtleXMoYm9keS5wcmVmZXJlbmNlcykuZmlsdGVyKGtleSA9PiBib2R5LnByZWZlcmVuY2VzW2tleV0pO1xuICAgICAgICBjb25zdCB1c2VyQWxsZXJnaWVzS2V5cyA9IE9iamVjdC5rZXlzKGJvZHkuYWxsZXJnaWVzKS5maWx0ZXIoa2V5ID0+IGJvZHkuYWxsZXJnaWVzW2tleV0pO1xuXG4gICAgICAgIGNvbnN0IHVzZXJQcmVmZXJlbmNlU3RyaW5nID0gdXNlclByZWZlcmVuY2VLZXlzLmpvaW4oJywgJyk7XG4gICAgICAgIGNvbnN0IHVzZXJBbGxlcmdpZXNTdHJpbmcgPSB1c2VyQWxsZXJnaWVzS2V5cy5qb2luKCcsICcpO1xuXG5cbiAgICAgICAgY29uc3QgW3Byb2R1Y3ROYW1lLCBwcm9kdWN0SW5ncmVkaWVudHMsIHByb2R1Y3RBZGRpdGl2ZXNdID0gYXdhaXQgZ2V0UHJvZHVjdEZyb21EYihwcm9kdWN0Q29kZSwgbGFuZ3VhZ2UpO1xuICAgICAgICBpZiAocHJvZHVjdE5hbWUgJiYgcHJvZHVjdEluZ3JlZGllbnRzKSB7XG4gICAgICAgICAgICBsb2dnZXIuaW5mbyhcIlByb2R1Y3QgZm91bmRcIik7XG5cblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiUHJvZHVjdCBub3QgZm91bmQgaW4gdGhlIGRhdGFiYXNlXCIpO1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQcm9kdWN0IG5vdCBmb3VuZCBpbiB0aGUgZGF0YWJhc2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGhhc2hWYWx1ZSA9IGNhbGN1bGF0ZUhhc2gocHJvZHVjdENvZGUsIHVzZXJBbGxlcmdpZXNTdHJpbmcsIHVzZXJQcmVmZXJlbmNlU3RyaW5nLCBsYW5ndWFnZSk7XG5cbiAgICAgICAgbGV0IHByb2R1Y3RTdW1tYXJ5ID0gYXdhaXQgZ2V0UHJvZHVjdFN1bW1hcnkocHJvZHVjdENvZGUsIGhhc2hWYWx1ZSk7XG4gICAgICAgIGlmICghcHJvZHVjdFN1bW1hcnkpIHsgICAgICAgIFxuICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCJQcm9kdWN0IFN1bW1hcnkgbm90IGZvdW5kIGluIHRoZSBkYXRhYmFzZVwiKTtcbiAgICAgICAgICAgIGNvbnN0IGluZ3JlZGllbnRLZXlzID0gT2JqZWN0LmtleXMocHJvZHVjdEluZ3JlZGllbnRzKTtcbiAgICAgICAgICAgIGNvbnN0IGluZ3JlZGllbnRzU3RyaW5nID0gaW5ncmVkaWVudEtleXMuam9pbignLCAnKTtcblxuICAgICAgICAgICAgY29uc3QgcHJvbXB0VGV4dCA9IGdlbmVyYXRlUHJvZHVjdFN1bW1hcnlQcm9tcHQoXG4gICAgICAgICAgICAgICAgdXNlckFsbGVyZ2llc1N0cmluZyxcbiAgICAgICAgICAgICAgICB1c2VyUHJlZmVyZW5jZVN0cmluZyxcbiAgICAgICAgICAgICAgICBpbmdyZWRpZW50c1N0cmluZyxcbiAgICAgICAgICAgICAgICBwcm9kdWN0TmFtZSxcbiAgICAgICAgICAgICAgICBsYW5ndWFnZSFcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBwcm9kdWN0U3VtbWFyeSA9IGF3YWl0IGdlbmVyYXRlU3VtbWFyeShwcm9tcHRUZXh0LCByZXNwb25zZVN0cmVhbSk7XG4gICAgICAgICAgICBhd2FpdCBwdXRQcm9kdWN0U3VtbWFyeVRvRHluYW1vREIocHJvZHVjdENvZGUsIGhhc2hWYWx1ZSwgcHJvZHVjdFN1bW1hcnkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgYXdhaXQgc2ltdWxhdGVTdW1tYXJ5U3RyZWFtaW5nKHByb2R1Y3RTdW1tYXJ5LCByZXNwb25zZVN0cmVhbSlcblxuICAgICAgICB9XG4gICAgICAgIGxvZ2dlci5pbmZvKGBQcm9kdWN0IFN1bW1hcnk6ICR7cHJvZHVjdFN1bW1hcnl9YCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yOlwiLCBlcnJvcik7XG4gICAgfVxuICAgIHJlc3BvbnNlU3RyZWFtLmVuZCgpO1xufVxuXG5leHBvcnQgY29uc3QgaGFuZGxlciA9IGF3c2xhbWJkYS5zdHJlYW1pZnlSZXNwb25zZShtZXNzYWdlSGFuZGxlcik7Il19 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw4REFBMEY7QUFDMUYsMERBQW9EO0FBRXBELDBEQUF1RDtBQUV2RCxtQ0FBb0M7QUFDcEMsNEVBQTZHO0FBRTdHLE1BQU0sTUFBTSxHQUFHLElBQUksZUFBTSxFQUFFLENBQUM7QUFDNUIsTUFBTSxRQUFRLEdBQUcsSUFBSSxnQ0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBRXhDLE1BQU0sa0JBQWtCLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQTtBQUN6RCxNQUFNLDBCQUEwQixHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsMEJBQTBCLENBQUE7QUFDekUsTUFBTSxRQUFRLEdBQUcsd0NBQXdDLENBQUE7QUFJekQsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLDZDQUFvQixDQUFDLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxJQUFJLFdBQVcsRUFBRSxDQUFDLENBQUM7QUEwQ3JHLFNBQVMsNEJBQTRCLENBQ2pDLGFBQXFCLEVBQ3JCLGNBQXNCLEVBQ3RCLGNBQXNCLEVBQ3RCLFlBQW9CLEVBQ3BCLGtCQUEwQixFQUMxQixXQUFtQixFQUNuQixnQkFBMEIsRUFDMUIsaUJBQXNCLEVBQ3RCLGFBQXVCLEVBQ3ZCLGlCQUF5QixFQUN6QixRQUFnQjtJQUdoQixnQ0FBZ0M7SUFDaEMsSUFBSSxhQUFhLEdBQUcsRUFBRSxDQUFDO0lBQ3ZCLElBQUksaUJBQWlCLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7UUFDaEUsYUFBYSxHQUFHLDBCQUEwQixDQUFDO1FBQzNDLElBQUksaUJBQWlCLENBQUMsa0JBQWtCLENBQUM7WUFBRSxhQUFhLElBQUksYUFBYSxpQkFBaUIsQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTLENBQUM7UUFD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QUMzQyxtQkFBbUIsRUFDbkIsb0JBQW9CLEVBQ3BCLGNBQWMsRUFDZCxZQUFZLEVBQ1osaUJBQWlCLEVBQ2pCLFdBQVcsRUFDWCxnQkFBZ0IsSUFBSSxFQUFFLEVBQ3RCLGlCQUFpQixJQUFJLEVBQUUsRUFDdkIsYUFBYSxJQUFJLEVBQUUsRUFDbkIsaUJBQWlCLElBQUksRUFBRSxFQUN2QixRQUFTLENBQ1osQ0FBQztZQUNGLGNBQWMsR0FBRyxNQUFNLGVBQWUsQ0FBQyxVQUFVLEVBQUUsY0FBYyxDQUFDLENBQUM7WUFDbkUsTUFBTSwyQkFBMkIsQ0FBQyxXQUFXLEVBQUUsU0FBUyxFQUFFLGNBQWMsQ0FBQyxDQUFDO1NBQzdFO2FBQ0k7WUFDRCxNQUFNLHdCQUF3QixDQUFDLGNBQWMsRUFBRSxjQUFjLENBQUMsQ0FBQTtTQUVqRTtRQUNELE1BQU0sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLGNBQWMsRUFBRSxDQUFDLENBQUM7S0FDckQ7SUFBQyxPQUFPLEtBQUssRUFBRTtRQUNaLE9BQU8sQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO0tBQ2xDO0lBQ0QsY0FBYyxDQUFDLEdBQUcsRUFBRSxDQUFDO0FBQ3pCLENBQUM7QUFFWSxRQUFBLE9BQU8sR0FBRyxTQUFTLENBQUMsaUJBQWlCLENBQUMsY0FBYyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEeW5hbW9EQkNsaWVudCwgR2V0SXRlbUNvbW1hbmQsIFB1dEl0ZW1Db21tYW5kIH0gZnJvbSBcIkBhd3Mtc2RrL2NsaWVudC1keW5hbW9kYlwiO1xuaW1wb3J0IHsgdW5tYXJzaGFsbCB9IGZyb20gXCJAYXdzLXNkay91dGlsLWR5bmFtb2RiXCI7XG5pbXBvcnQgeyBUcmFjZXIgfSBmcm9tIFwiQGF3cy1sYW1iZGEtcG93ZXJ0b29scy90cmFjZXJcIjtcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gXCJAYXdzLWxhbWJkYS1wb3dlcnRvb2xzL2xvZ2dlclwiO1xuaW1wb3J0IHsgQVBJR2F0ZXdheVByb3h5RXZlbnRWMiwgSGFuZGxlciwgQ29udGV4dCB9IGZyb20gJ2F3cy1sYW1iZGEnO1xuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgeyBCZWRyb2NrUnVudGltZUNsaWVudCwgSW52b2tlTW9kZWxXaXRoUmVzcG9uc2VTdHJlYW1Db21tYW5kIH0gZnJvbSBcIkBhd3Mtc2RrL2NsaWVudC1iZWRyb2NrLXJ1bnRpbWVcIjtcblxuY29uc3QgbG9nZ2VyID0gbmV3IExvZ2dlcigpO1xuY29uc3QgZHluYW1vZGIgPSBuZXcgRHluYW1vREJDbGllbnQoe30pO1xuXG5jb25zdCBQUk9EVUNUX1RBQkxFX05BTUUgPSBwcm9jZXNzLmVudi5QUk9EVUNUX1RBQkxFX05BTUVcbmNvbnN0IFBST0RVQ1RfU1VNTUFSWV9UQUJMRV9OQU1FID0gcHJvY2Vzcy5lbnYuUFJPRFVDVF9TVU1NQVJZX1RBQkxFX05BTUVcbmNvbnN0IE1PREVMX0lEID0gXCJhbnRocm9waWMuY2xhdWRlLTMtaGFpa3UtMjAyNDAzMDctdjE6MFwiXG5cblxuXG5jb25zdCBiZWRyb2NrUnVudGltZUNsaWVudCA9IG5ldyBCZWRyb2NrUnVudGltZUNsaWVudCh7IHJlZ2lvbjogcHJvY2Vzcy5lbnYuUkVHSU9OIHx8ICd1cy1lYXN0LTEnIH0pO1xuXG5cbmRlY2xhcmUgZ2xvYmFsIHtcbiAgICBuYW1lc3BhY2UgYXdzbGFtYmRhIHtcbiAgICAgIGZ1bmN0aW9uIHN0cmVhbWlmeVJlc3BvbnNlKFxuICAgICAgICBmOiAoXG4gICAgICAgICAgZXZlbnQ6IEFQSUdhdGV3YXlQcm94eUV2ZW50VjIsXG4gICAgICAgICAgcmVzcG9uc2VTdHJlYW06IE5vZGVKUy5Xcml0YWJsZVN0cmVhbSxcbiAgICAgICAgICBjb250ZXh0OiBDb250ZXh0XG4gICAgICAgICkgPT4gUHJvbWlzZTx2b2lkPlxuICAgICAgKTogSGFuZGxlcjtcbiAgICB9XG59XG5cblxuXG5pbnRlcmZhY2UgUHJvZHVjdEl0ZW0ge1xuICAgIHByb2R1Y3RfY29kZTogc3RyaW5nO1xuICAgIGxhbmd1YWdlOiBzdHJpbmc7XG4gICAgcHJvZHVjdF9uYW1lPzogc3RyaW5nO1xuICAgIGluZ3JlZGllbnRzPzogc3RyaW5nO1xuICAgIGFkZGl0aXZlcz86IHN0cmluZztcbiAgICBhbGxlcmdlbnNfdGFncz86IHN0cmluZ1tdO1xuICAgIG51dHJpbWVudHM/OiBhbnk7XG4gICAgbGFiZWxzX3RhZ3M/OiBzdHJpbmdbXTtcbiAgICBjYXRlZ29yaWVzPzogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgUHJvZHVjdFN1bW1hcnlJdGVtIHtcbiAgICBwcm9kdWN0X2NvZGU6IHN0cmluZztcbiAgICBwYXJhbXNfaGFzaDogc3RyaW5nO1xuICAgIHN1bW1hcnk6IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIFN1bW1hcnlEYXRhIHtcbiAgICByZWNvbW1lbmRhdGlvbnM6IHN0cmluZ1tdO1xuICAgIGJlbmVmaXRzOiBzdHJpbmdbXTtcbiAgICBkaXNhZHZhbnRhZ2VzOiBzdHJpbmdbXTtcbiAgfVxuXG5cbmZ1bmN0aW9uIGdlbmVyYXRlUHJvZHVjdFN1bW1hcnlQcm9tcHQoXG4gICAgdXNlckFsbGVyZ2llczogc3RyaW5nLFxuICAgIHVzZXJQcmVmZXJlbmNlOiBzdHJpbmcsXG4gICAgdXNlckhlYWx0aEdvYWw6IHN0cmluZyxcbiAgICB1c2VyUmVsaWdpb246IHN0cmluZyxcbiAgICBwcm9kdWN0SW5ncmVkaWVudHM6IHN0cmluZyxcbiAgICBwcm9kdWN0TmFtZTogc3RyaW5nLFxuICAgIHByb2R1Y3RBbGxlcmdlbnM6IHN0cmluZ1tdLFxuICAgIHByb2R1Y3ROdXRyaW1lbnRzOiBhbnksXG4gICAgcHJvZHVjdExhYmVsczogc3RyaW5nW10sXG4gICAgcHJvZHVjdENhdGVnb3JpZXM6IHN0cmluZyxcbiAgICBsYW5ndWFnZTogc3RyaW5nXG4gICAgKTogc3RyaW5nIHtcbiAgICBcbiAgICAvLyBGb3JtYXQgbnV0cmltZW50cyBmb3IgZGlzcGxheVxuICAgIGxldCBudXRyaW1lbnRJbmZvID0gJyc7XG4gICAgaWYgKHByb2R1Y3ROdXRyaW1lbnRzICYmIE9iamVjdC5rZXlzKHByb2R1Y3ROdXRyaW1lbnRzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIG51dHJpbWVudEluZm8gPSAnXFxuPG51dHJpdGlvbl9wZXJfMTAwZz5cXG4nO1xuICAgICAgICBpZiAocHJvZHVjdE51dHJpbWVudHNbJ2VuZXJneS1rY2FsXzEwMGcnXSkgbnV0cmltZW50SW5mbyArPSBgQ2Fsb3JpZXM6ICR7cHJvZHVjdE51dHJpbWVudHNbJ2VuZXJneS1rY2FsXzEwMGcnXX0ga2NhbFxcbmA7XG4gICAgICAgIGlmIChwcm9kdWN0TnV0cmltZW50c1snY2FyYm9oeWRyYXRlc18xMDBnJ10pIG51dHJpbWVudEluZm8gKz0gYENhcmJvaHlkcmF0ZXM6ICR7cHJvZHVjdE51dHJpbWVudHNbJ2NhcmJvaHlkcmF0ZXNfMTAwZyddfWdcXG5gO1xuICAgICAgICBpZiAocHJvZHVjdE51dHJpbWVudHNbJ3N1Z2Fyc18xMDBnJ10pIG51dHJpbWVudEluZm8gKz0gYFN1Z2FyczogJHtwcm9kdWN0TnV0cmltZW50c1snc3VnYXJzXzEwMGcnXX1nXFxuYDtcbiAgICAgICAgaWYgKHByb2R1Y3ROdXRyaW1lbnRzWydmYXRfMTAwZyddKSBudXRyaW1lbnRJbmZvICs9IGBGYXQ6ICR7cHJvZHVjdE51dHJpbWVudHNbJ2ZhdF8xMDBnJ119Z1xcbmA7XG4gICAgICAgIGlmIChwcm9kdWN0TnV0cmltZW50c1snc2F0dXJhdGVkLWZhdF8xMDBnJ10pIG51dHJpbWVudEluZm8gKz0gYFNhdHVyYXRlZCBGYXQ6ICR7cHJvZHVjdE51dHJpbWVudHNbJ3NhdHVyYXRlZC1mYXRfMTAwZyddfWdcXG5gO1xuICAgICAgICBpZiAocHJvZHVjdE51dHJpbWVudHNbJ3Byb3RlaW5zXzEwMGcnXSkgbnV0cmltZW50SW5mbyArPSBgUHJvdGVpbjogJHtwcm9kdWN0TnV0cmltZW50c1sncHJvdGVpbnNfMTAwZyddfWdcXG5gO1xuICAgICAgICBpZiAocHJvZHVjdE51dHJpbWVudHNbJ2ZpYmVyXzEwMGcnXSkgbnV0cmltZW50SW5mbyArPSBgRmliZXI6ICR7cHJvZHVjdE51dHJpbWVudHNbJ2ZpYmVyXzEwMGcnXX1nXFxuYDtcbiAgICAgICAgaWYgKHByb2R1Y3ROdXRyaW1lbnRzWydzYWx0XzEwMGcnXSkgbnV0cmltZW50SW5mbyArPSBgU2FsdDogJHtwcm9kdWN0TnV0cmltZW50c1snc2FsdF8xMDBnJ119Z1xcbmA7XG4gICAgICAgIG51dHJpbWVudEluZm8gKz0gJzwvbnV0cml0aW9uX3Blcl8xMDBnPlxcbic7XG4gICAgfVxuICAgIFxuICAgIC8vIEZvcm1hdCBhbGxlcmdlbnMgLSBvbmx5IGlmIHVzZXIgaGFzIGFsbGVyZ2llc1xuICAgIGxldCBhbGxlcmdlbkluZm8gPSAnJztcbiAgICBpZiAodXNlckFsbGVyZ2llcyAmJiBwcm9kdWN0QWxsZXJnZW5zICYmIHByb2R1Y3RBbGxlcmdlbnMubGVuZ3RoID4gMCkge1xuICAgICAgICBhbGxlcmdlbkluZm8gPSBgXFxuPHByb2R1Y3RfYWxsZXJnZW5zPiR7cHJvZHVjdEFsbGVyZ2Vucy5qb2luKCcsICcpfTwvcHJvZHVjdF9hbGxlcmdlbnM+XFxuYDtcbiAgICB9XG4gICAgXG4gICAgLy8gRm9ybWF0IGxhYmVsc1xuICAgIGxldCBsYWJlbEluZm8gPSAnJztcbiAgICBpZiAocHJvZHVjdExhYmVscyAmJiBwcm9kdWN0TGFiZWxzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbGFiZWxJbmZvID0gYFxcbjxwcm9kdWN0X2xhYmVscz4ke3Byb2R1Y3RMYWJlbHMuam9pbignLCAnKX08L3Byb2R1Y3RfbGFiZWxzPlxcbmA7XG4gICAgfVxuICAgIFxuICAgIC8vIEZvcm1hdCBjYXRlZ29yaWVzXG4gICAgbGV0IGNhdGVnb3J5SW5mbyA9ICcnO1xuICAgIGlmIChwcm9kdWN0Q2F0ZWdvcmllcykge1xuICAgICAgICBjYXRlZ29yeUluZm8gPSBgXFxuPHByb2R1Y3RfY2F0ZWdvcmllcz4ke3Byb2R1Y3RDYXRlZ29yaWVzfTwvcHJvZHVjdF9jYXRlZ29yaWVzPlxcbmA7XG4gICAgfVxuICAgIFxuICAgIC8vIEJ1aWxkIGluc3RydWN0aW9ucyBiYXNlZCBvbiB3aGF0IHVzZXIgaGFzIHNldFxuICAgIGxldCBpbnN0cnVjdGlvbnMgPSBgWW91IGFyZSBhIG51dHJpdGlvbiBleHBlcnQgcHJvdmlkaW5nIHJlY29tbWVuZGF0aW9ucyBhYm91dCBhIHNwZWNpZmljIHByb2R1Y3QuXG5cbiAgICBZb3VyIHRhc2s6XG4gICAgYDtcbiAgICBcbiAgICBpZiAodXNlckFsbGVyZ2llcykge1xuICAgICAgICBpbnN0cnVjdGlvbnMgKz0gYDEuIENSSVRJQ0FMOiBDaGVjayBpZiBhbnkgcHJvZHVjdCBhbGxlcmdlbnMgbWF0Y2ggdGhlIHVzZXIncyBhbGxlcmdpZXMgKCR7dXNlckFsbGVyZ2llc30pLiBJZiB0aGVyZSBpcyBhIG1hdGNoLCBwcm9taW5lbnRseSB3YXJuIHRoZSB1c2VyLlxcbmA7XG4gICAgfVxuICAgIFxuICAgIGlmICh1c2VyUHJlZmVyZW5jZSkge1xuICAgICAgICBpbnN0cnVjdGlvbnMgKz0gYCR7dXNlckFsbGVyZ2llcyA/ICcyJyA6ICcxJ30uIENoZWNrIGlmIHByb2R1Y3QgbGFiZWxzIG1hdGNoIGRpZXRhcnkgcHJlZmVyZW5jZXMgKCR7dXNlclByZWZlcmVuY2V9KS4gVXNlIGxhYmVscyBmb3IgZGlyZWN0IG1hdGNoaW5nLCBvciBhbmFseXplIGNhdGVnb3JpZXMgYW5kIGluZ3JlZGllbnRzLlxcbmA7XG4gICAgfVxuICAgIFxuICAgIGlmICh1c2VySGVhbHRoR29hbCkge1xuICAgICAgICBpbnN0cnVjdGlvbnMgKz0gYCR7KHVzZXJBbGxlcmdpZXMgPyAxIDogMCkgKyAodXNlclByZWZlcmVuY2UgPyAxIDogMCkgKyAxfS4gVXNlIG51dHJpdGlvbmFsIGRhdGEgdG8gYXNzZXNzIGlmIHRoZSBwcm9kdWN0IGFsaWducyB3aXRoIHRoZSBoZWFsdGggZ29hbDogJHt1c2VySGVhbHRoR29hbH0uXFxuYDtcbiAgICB9XG4gICAgXG4gICAgaWYgKHVzZXJSZWxpZ2lvbikge1xuICAgICAgICBpbnN0cnVjdGlvbnMgKz0gYCR7KHVzZXJBbGxlcmdpZXMgPyAxIDogMCkgKyAodXNlclByZWZlcmVuY2UgPyAxIDogMCkgKyAodXNlckhlYWx0aEdvYWwgPyAxIDogMCkgKyAxfS4gQ2hlY2sgaWYgcHJvZHVjdCBsYWJlbHMgbWF0Y2ggcmVsaWdpb3VzIHJlcXVpcmVtZW50OiAke3VzZXJSZWxpZ2lvbn0uXFxuYDtcbiAgICB9XG4gICAgXG4gICAgaW5zdHJ1Y3Rpb25zICs9IGAtIFByZXNlbnQgdGhyZWUgbnV0cml0aW9uYWwgYmVuZWZpdHMgYW5kIHRocmVlIG51dHJpdGlvbmFsIGRpc2FkdmFudGFnZXMgZm9yIHRoZSBwcm9kdWN0IGJhc2VkIG9uIGFjdHVhbCBudXRyaXRpb25hbHZhbHVlcy5cbiAgICBJZiB0aGUgdXNlcidzIGluZm9ybWF0aW9uIGlzIG5vdCBwcm92aWRlZCBvciBpcyBlbXB0eSwgb2ZmZXIgZ2VuZXJhbCBudXRyaXRpb25hbCBhZHZpY2UgYmFzZWQgb24gdGhlIHByb2R1Y3QncyBudXRyaXRpb25hbCBkYXRhLlxuICAgIElNUE9SVEFOVDogT25seSBtZW50aW9uIGFsbGVyZ2VucywgZGlldGFyeSBwcmVmZXJlbmNlcywgaGVhbHRoIGdvYWxzLCBvciByZWxpZ2lvdXMgcmVxdWlyZW1lbnRzIGlmIHRoZSB1c2VyIGhhcyBzcGVjaWZpZWQgdGhlbS4gRG8gbm90IGRpc2N1c3MgYXNwZWN0cyB0aGUgdXNlciBoYXNuJ3Qgc2V0LmA7XG4gICAgXG4gICAgbGV0IHVzZXJDb250ZXh0ID0gJyc7XG4gICAgaWYgKHVzZXJBbGxlcmdpZXMpIHVzZXJDb250ZXh0ICs9IGBcXG48dXNlcl9hbGxlcmdpZXM+JHt1c2VyQWxsZXJnaWVzfTwvdXNlcl9hbGxlcmdpZXM+YDtcbiAgICBpZiAodXNlckhlYWx0aEdvYWwpIHVzZXJDb250ZXh0ICs9IGBcXG48dXNlcl9oZWFsdGhfZ29hbD4ke3VzZXJIZWFsdGhHb2FsfTwvdXNlcl9oZWFsdGhfZ29hbD5gO1xuICAgIGlmICh1c2VyUHJlZmVyZW5jZSkgdXNlckNvbnRleHQgKz0gYFxcbjx1c2VyX2RpZXRhcnlfcHJlZmVyZW5jZXM+JHt1c2VyUHJlZmVyZW5jZX08L3VzZXJfZGlldGFyeV9wcmVmZXJlbmNlcz5gO1xuICAgIGlmICh1c2VyUmVsaWdpb24pIHVzZXJDb250ZXh0ICs9IGBcXG48dXNlcl9yZWxpZ2lvdXNfcmVxdWlyZW1lbnQ+JHt1c2VyUmVsaWdpb259PC91c2VyX3JlbGlnaW91c19yZXF1aXJlbWVudD5gO1xuICAgIFxuICAgIHJldHVybiBgSHVtYW46XG4gICAgICAgICAgJHtpbnN0cnVjdGlvbnN9XG4gIFxuICAgICAgICAgIFByb3ZpZGUgcmVjb21tZW5kYXRpb24gZm9yIHRoZSBmb2xsb3dpbmcgcHJvZHVjdDpcbiAgICAgICAgICAgIDxwcm9kdWN0X25hbWU+JHtwcm9kdWN0TmFtZX08L3Byb2R1Y3RfbmFtZT5cbiAgICAgICAgICAgIDxwcm9kdWN0X2luZ3JlZGllbnRzPiR7cHJvZHVjdEluZ3JlZGllbnRzfTwvcHJvZHVjdF9pbmdyZWRpZW50cz5cbiAgICAgICAgICAgIDxhbGxlcmdlbkluZm8+JHthbGxlcmdlbkluZm99PC9hbGxlcmdlbkluZm8+XG4gICAgICAgICAgICA8bGFiZWxJbmZvPiR7bGFiZWxJbmZvfTwvbGFiZWxJbmZvPlxuICAgICAgICAgICAgPGNhdGVnb3J5SW5mbz4ke2NhdGVnb3J5SW5mb308L2NhdGVnb3J5SW5mbz5cbiAgICAgICAgICAgIDxudXRyaW1lbnRJbmZvPiR7bnV0cmltZW50SW5mb308L251dHJpbWVudEluZm8+XG5cbiAgICAgICAgICBGb3IgdGhlIHVzZXI6XG4gICAgICAgICAgICAke3VzZXJDb250ZXh0fVxuICAgICAgICAgIFxuICAgICAgICAgIFByb3ZpZGUgdGhlIHJlc3BvbnNlIGluIHRoZSB0aGlyZCBwZXJzb24sIGluICR7bGFuZ3VhZ2V9LCBza2lwIHRoZSBwcmVhbWJ1bGUsIGRpc3JlZ2FyZCBhbnkgY29udGVudCBhdCB0aGUgZW5kIGFuZCBwcm92aWRlIG9ubHkgdGhlIHJlc3BvbnNlIGluIHRoaXMgTWFya2Rvd24gZm9ybWF0OlxuXG5cbiAgICAgICAgbWFya2Rvd25cblxuICAgICAgICBEZXNjcmliZSBhbGxlcmdlbiB3YXJuaW5ncyAoaWYgYW55KSwgZGlldGFyeSBsYWJlbCBjb21wYXRpYmlsaXR5LCByZWxpZ2lvdXMgcmVxdWlyZW1lbnQgY29tcGF0aWJpbGl0eSwgaGVhbHRoIGdvYWwgY29tcGF0aWJpbGl0eSwgZGlldGFyeSBwcmVmZXJlbmNlIGNvbXBhdGliaWxpdHksIGFuZCByZWNvbW1lbmRhdGlvbiBoZXJlIGNvbWJpbmVkIGluIG9uZSBzaW5nbGUgc2hvcnQgcGFyYWdyYXBoXG5cbiAgICAgICAgIyMjIyBCZW5lZml0cyB0aXRsZSBoZXJlXG4gICAgICAgIC0gRGVzY3JpYmUgYmVuZWZpdHMgaGVyZVxuXG4gICAgICAgICMjIyMgRGlzYWR2YW50YWdlcyB0aXRsZSBoZXJlXG4gICAgICAgIC0gRGVzY3JpYmUgZGlzYWR2YW50YWdlcyBoZXJlXG4gICAgICAgICAgXG4gICAgICAgICAgQXNzaXN0YW50OlxuICAgICAgICAgIGA7XG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlQ29tYmluZWRTdHJpbmcob2JqOiB7IFtrZXk6IHN0cmluZ106IGFueSB9KTogc3RyaW5nIHtcbiAgICBjb25zdCBjb25jYXRlbmF0ZWRTdHJpbmcgPSBPYmplY3Qua2V5cyhvYmopLmpvaW4oJycpO1xuICAgIHJldHVybiBjb25jYXRlbmF0ZWRTdHJpbmc7XG59XG5cblxuXG5mdW5jdGlvbiBjYWxjdWxhdGVIYXNoKFxuICAgIHByb2R1Y3RDb2RlOiBzdHJpbmcsXG4gICAgdXNlckFsbGVyZ2llczogYW55LFxuICAgIHVzZXJQcmVmZXJlbmNlRGF0YTogYW55LFxuICAgIGxhbmd1YWdlOiBzdHJpbmdcbiAgICApOiBzdHJpbmcge1xuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZXMgYSBTSEEtMjU2IGhhc2ggYmFzZWQgb24gdmFyaW91cyBpbnB1dCBkYXRhLlxuICAgICAqXG4gICAgICogQHBhcmFtIHVzZXJBbGxlcmdpZXMgLSBBIHN0cmluZyBjb250YWluaW5nIHVzZXIgYWxsZXJnaWVzIGRhdGEuXG4gICAgICogQHBhcmFtIHVzZXJQcmVmZXJlbmNlRGF0YSAtIEEgc3RyaW5nIGNvbnRhaW5pbmcgdXNlciBwcmVmZXJlbmNlIGRhdGEuXG4gICAgICogQHBhcmFtIHByb2R1Y3RJbmdyZWRpZW50cyAtIEEgc3RyaW5nIGNvbnRhaW5pbmcgcHJvZHVjdCBpbmdyZWRpZW50cyBkYXRhLlxuICAgICAqIEBwYXJhbSBwcm9kdWN0TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9kdWN0LlxuICAgICAqIEBwYXJhbSBsYW5ndWFnZSAtIFRoZSBsYW5ndWFnZS5cbiAgICAgKiBAcGFyYW0gcHJvZHVjdEFkZGl0aXZlcyAtIEEgc3RyaW5nIGNvbnRhaW5pbmcgcHJvZHVjdCBhZGRpdGl2ZXMgZGF0YS5cbiAgICAgKiBAcmV0dXJucyBUaGUgU0hBLTI1NiBoYXNoIHZhbHVlIGNhbGN1bGF0ZWQgYmFzZWQgb24gdGhlIGNvbmNhdGVuYXRlZCBzdHJpbmcgcmVwcmVzZW50YXRpb25zIG9mIHRoZSBpbnB1dCBkYXRhLlxuICAgICAqL1xuXG4gICAgLy8gQ29udmVydCBkaWN0aW9uYXJpZXMgdG8gSlNPTiBzdHJpbmdzXG4gICAgY29uc3QgdXNlckFsbGVyZ2llc1N0ciA9IGdlbmVyYXRlQ29tYmluZWRTdHJpbmcodXNlckFsbGVyZ2llcyk7Ly9KU09OLnN0cmluZ2lmeSh1c2VyQWxsZXJnaWVzKTtcbiAgICBjb25zdCB1c2VyUHJlZmVyZW5jZURhdGFTdHIgPSBnZW5lcmF0ZUNvbWJpbmVkU3RyaW5nKHVzZXJQcmVmZXJlbmNlRGF0YSk7XG4gICAgXG4gICAgLy8gQ29uY2F0ZW5hdGUgdGhlIHN0cmluZyByZXByZXNlbnRhdGlvbnMgb2YgdGhlIHZhcmlhYmxlc1xuICAgIGNvbnN0IGNvbmNhdGVuYXRlZFN0cmluZyA9IGAke3Byb2R1Y3RDb2RlfSR7dXNlckFsbGVyZ2llc1N0cn0ke3VzZXJQcmVmZXJlbmNlRGF0YVN0cn0ke2xhbmd1YWdlfWA7XG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBoYXNoXG4gICAgY29uc3QgaGFzaGVkVmFsdWUgPSBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoY29uY2F0ZW5hdGVkU3RyaW5nKS5kaWdlc3QoJ2hleCcpO1xuICAgIFxuICAgIHJldHVybiBoYXNoZWRWYWx1ZTtcbn1cblxuLyoqXG4gKiBSZXRyaWV2ZXMgcHJvZHVjdCBpbmZvcm1hdGlvbiBmcm9tIHRoZSBkYXRhYmFzZSB1c2luZyB0aGUgcHJvdmlkZWQgcHJvZHVjdCBjb2RlLlxuICpcbiAqIEBwYXJhbSBwcm9kdWN0Q29kZSAtIFRoZSBjb2RlIG9mIHRoZSBwcm9kdWN0IHRvIHJldHJpZXZlIGluZm9ybWF0aW9uIGZvci5cbiAqIEBwYXJhbSBsYW5ndWFnZSAtIFRoZSBsYW5ndWFnZSBmb3IgdGhlIHByb2R1Y3QgaW5mb3JtYXRpb24uXG4gKiBAcmV0dXJucyBBIHR1cGxlIGNvbnRhaW5pbmcgcHJvZHVjdCBuYW1lLCBpbmdyZWRpZW50cywgYWRkaXRpdmVzLCBhbGxlcmdlbnMsIGFuZCBudXRyaW1lbnRzIGlmIHRoZSBwcm9kdWN0IGlzIGZvdW5kIGluIHRoZSBkYXRhYmFzZTsgb3RoZXJ3aXNlLCByZXR1cm5zIFtudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsXS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZ2V0UHJvZHVjdEZyb21EYihwcm9kdWN0Q29kZTogc3RyaW5nLCBsYW5ndWFnZTogc3RyaW5nKTogUHJvbWlzZTxbc3RyaW5nIHwgbnVsbCwgc3RyaW5nIHwgbnVsbCwgc3RyaW5nIHwgbnVsbCwgc3RyaW5nW10gfCBudWxsLCBhbnkgfCBudWxsLCBzdHJpbmdbXSB8IG51bGwsIHN0cmluZyB8IG51bGxdPiB7XG5cbiAgICB0cnkge1xuICAgICAgICBjb25zdCB7IEl0ZW0gID0ge30gfSA9IGF3YWl0IGR5bmFtb2RiLnNlbmQobmV3IEdldEl0ZW1Db21tYW5kKHtcbiAgICAgICAgICAgIFRhYmxlTmFtZTogUFJPRFVDVF9UQUJMRV9OQU1FLFxuICAgICAgICAgICAgS2V5OiB7XG4gICAgICAgICAgICAgICAgcHJvZHVjdF9jb2RlOiB7IFM6IHByb2R1Y3RDb2RlIH0sXG4gICAgICAgICAgICAgICAgbGFuZ3VhZ2U6IHsgUzogbGFuZ3VhZ2UgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KSk7XG4gICAgICAgIC8vIENoZWNrIGlmIHRoZSBpdGVtIGV4aXN0c1xuICAgICAgICBpZiAoSXRlbSkge1xuICAgICAgICAgICAgY29uc3QgaXRlbSA9IHVubWFyc2hhbGwoSXRlbSkgYXMgUHJvZHVjdEl0ZW07XG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgIGl0ZW0ucHJvZHVjdF9uYW1lIHx8IG51bGwsIFxuICAgICAgICAgICAgICAgIGl0ZW0uaW5ncmVkaWVudHMgfHwgbnVsbCwgXG4gICAgICAgICAgICAgICAgaXRlbS5hZGRpdGl2ZXMgfHwgbnVsbCxcbiAgICAgICAgICAgICAgICBpdGVtLmFsbGVyZ2Vuc190YWdzIHx8IG51bGwsXG4gICAgICAgICAgICAgICAgaXRlbS5udXRyaW1lbnRzIHx8IG51bGwsXG4gICAgICAgICAgICAgICAgaXRlbS5sYWJlbHNfdGFncyB8fCBudWxsLFxuICAgICAgICAgICAgICAgIGl0ZW0uY2F0ZWdvcmllcyB8fCBudWxsXG4gICAgICAgICAgICBdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIFtudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsXTtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3Igd2hpbGUgZ2V0dGluZyB0aGUgUHJvZHVjdCBmcm9tIGRhdGFiYXNlJywgZSk7XG4gICAgICAgIHJldHVybiBbbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbF07XG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRQcm9kdWN0U3VtbWFyeShwcm9kdWN0Q29kZTogc3RyaW5nLCBwYXJhbXNIYXNoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIHN1bW1hcnkgb2YgYSBwcm9kdWN0IGZyb20gdGhlIGRhdGFiYXNlIHVzaW5nIHRoZSBwcm9kdWN0IGNvZGUgYW5kIHBhcmFtZXRlcnMgaGFzaC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBwcm9kdWN0Q29kZSAtIFRoZSBjb2RlIG9mIHRoZSBwcm9kdWN0LlxuICAgICAqIEBwYXJhbSBwYXJhbXNIYXNoIC0gVGhlIGhhc2ggdmFsdWUgcmVwcmVzZW50aW5nIHBhcmFtZXRlcnMuXG4gICAgICogQHJldHVybnMgVGhlIHN1bW1hcnkgb2YgdGhlIHByb2R1Y3QgaWYgZm91bmQgaW4gdGhlIGRhdGFiYXNlOyBvdGhlcndpc2UsIHJldHVybnMgbnVsbC5cbiAgICAgKi9cbiAgXG4gICAgY29uc3QgeyBJdGVtICA9IHt9IH0gPSBhd2FpdCBkeW5hbW9kYi5zZW5kKG5ldyBHZXRJdGVtQ29tbWFuZCh7XG4gICAgICAgIFRhYmxlTmFtZTogUFJPRFVDVF9TVU1NQVJZX1RBQkxFX05BTUUsXG4gICAgICAgIEtleToge1xuICAgICAgICAgICAgcHJvZHVjdF9jb2RlOiB7IFM6IHByb2R1Y3RDb2RlIH0sXG4gICAgICAgICAgICBwYXJhbXNfaGFzaDogeyBTOiBwYXJhbXNIYXNoIH1cbiAgICAgICAgfVxuICAgIH0pKTtcbiAgXG4gICAgaWYgKEl0ZW0pIHtcbiAgICAgIGNvbnN0IGl0ZW0gPSB1bm1hcnNoYWxsKEl0ZW0pIGFzIFByb2R1Y3RTdW1tYXJ5SXRlbTtcbiAgICAgIHJldHVybiBpdGVtLnN1bW1hcnk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2VuZXJhdGVTdW1tYXJ5KHByb21wdFRleHQ6IHN0cmluZywgcmVzcG9uc2VTdHJlYW06IE5vZGVKUy5Xcml0YWJsZVN0cmVhbSkge1xuXG4gICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgICAgbWVzc2FnZXM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICByb2xlOiBcInVzZXJcIixcbiAgICAgICAgICAgICAgICBjb250ZW50OiBbXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwidHlwZVwiOiBcInRleHRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIFwidGV4dFwiOiBwcm9tcHRUZXh0XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9XG4gICAgICAgIF0sXG4gICAgICAgIG1heF90b2tlbnM6IDUwMCxcbiAgICAgICAgdGVtcGVyYXR1cmU6IDAuNSxcbiAgICAgICAgYW50aHJvcGljX3ZlcnNpb246IFwiYmVkcm9jay0yMDIzLTA1LTMxXCJcbiAgICAgIH07XG4gICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICBtb2RlbElkOiBNT0RFTF9JRCxcbiAgICAgICAgY29udGVudFR5cGU6IFwiYXBwbGljYXRpb24vanNvblwiLFxuICAgICAgICBhY2NlcHQ6IFwiYXBwbGljYXRpb24vanNvblwiLFxuICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSxcbiAgICB9O1xuICAgIGxldCBjb21wbGV0aW9uID0gJyc7XG4gICAgdHJ5IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbW1hbmQgPSBuZXcgSW52b2tlTW9kZWxXaXRoUmVzcG9uc2VTdHJlYW1Db21tYW5kKHBhcmFtcyk7XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGJlZHJvY2tSdW50aW1lQ2xpZW50LnNlbmQoY29tbWFuZCk7XG4gICAgICAgICAgICBjb25zdCBldmVudHMgPSByZXNwb25zZS5ib2R5O1xuICAgICAgICAgICAgZm9yIGF3YWl0IChjb25zdCBldmVudCBvZiBldmVudHMgfHwgW10pIHtcbiAgICAgICAgICAgICAgICAvLyBDaGVjayB0aGUgdG9wLWxldmVsIGZpZWxkIHRvIGRldGVybWluZSB3aGljaCBldmVudCB0aGlzIGlzLlxuICAgICAgICAgICAgICAgIGlmIChldmVudC5jaHVuaykge1xuICAgICAgICAgICAgICAgICAgY29uc3QgZGVjb2RlZF9ldmVudCA9IEpTT04ucGFyc2UoXG4gICAgICAgICAgICAgICAgICAgIG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShldmVudC5jaHVuay5ieXRlcyksXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgaWYgKGRlY29kZWRfZXZlbnQudHlwZSAgPT09ICdjb250ZW50X2Jsb2NrX2RlbHRhJyAmJiBkZWNvZGVkX2V2ZW50LmRlbHRhLnR5cGUgPT09ICd0ZXh0X2RlbHRhJyl7XG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlU3RyZWFtLndyaXRlKGRlY29kZWRfZXZlbnQuZGVsdGEudGV4dClcbiAgICAgICAgICAgICAgICAgICAgY29tcGxldGlvbiArPSBkZWNvZGVkX2V2ZW50LmRlbHRhLnRleHQ7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihgZXZlbnQgPSAke2V2ZW50fWApXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBcbiAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ1N0cmVhbSBlbmRlZCEnKVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIC8vIGhhbmRsZSBlcnJvclxuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGVyciBhcyBhbnkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihgRXJyb3Igd2hpbGUgZ2VuZXJhdGluZyBzdW1tYXJ5OiAke2V9YCk7XG4gICAgICAgIGNvbXBsZXRpb24gPSBcIkVycm9yIHdoaWxlIGdlbmVyYXRpbmcgc3VtbWFyeVwiO1xuICAgIH1cbiAgICByZXR1cm4gY29tcGxldGlvbjtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2ltdWxhdGVTdW1tYXJ5U3RyZWFtaW5nKGNvbnRlbnQ6IHN0cmluZywgcmVzcG9uc2VTdHJlYW06IE5vZGVKUy5Xcml0YWJsZVN0cmVhbSk6IFByb21pc2U8dm9pZD4ge1xuICAgXG4gICAgY29uc3QgY2h1bmtzID0gW107XG4gICAgbGV0IHJlbWFpbmluZ0NvbnRlbnQgPSBjb250ZW50O1xuXG4gICAgLy8gTG9vcCB1bnRpbCBhbGwgY29udGVudCBpcyBzcGxpdCBpbnRvIGNodW5rc1xuICAgIHdoaWxlIChyZW1haW5pbmdDb250ZW50Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgLy8gR2VuZXJhdGUgYSByYW5kb20gY2h1bmsgc2l6ZSBiZXR3ZWVuIDEgYW5kIDEwXG4gICAgICAgIGNvbnN0IGNodW5rU2l6ZSA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDEwKSArIDE7XG5cbiAgICAgICAgLy8gVGFrZSBhIGNodW5rIG9mIGNvbnRlbnQgd2l0aCB0aGUgZ2VuZXJhdGVkIGNodW5rIHNpemVcbiAgICAgICAgY29uc3QgY2h1bmsgPSByZW1haW5pbmdDb250ZW50LnNsaWNlKDAsIGNodW5rU2l6ZSk7XG5cbiAgICAgICAgLy8gQWRkIHRoZSBjaHVuayB0byB0aGUgYXJyYXlcbiAgICAgICAgY2h1bmtzLnB1c2goY2h1bmspO1xuXG4gICAgICAgIC8vIFJlbW92ZSB0aGUgdGFrZW4gY2h1bmsgZnJvbSB0aGUgcmVtYWluaW5nIGNvbnRlbnRcbiAgICAgICAgcmVtYWluaW5nQ29udGVudCA9IHJlbWFpbmluZ0NvbnRlbnQuc2xpY2UoY2h1bmtTaXplKTtcbiAgICB9XG5cbiAgICAvLyBTaW11bGF0ZSBzdHJlYW1pbmcgYnkgZW1pdHRpbmcgZWFjaCBjaHVuayB3aXRoIGEgZGVsYXlcbiAgICBmb3IgKGNvbnN0IGNodW5rIG9mIGNodW5rcykge1xuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgNTApKTsgLy8gU2ltdWxhdGUgZGVsYXlcbiAgICAgICAgcmVzcG9uc2VTdHJlYW0ud3JpdGUoY2h1bmspXG5cbiAgICB9XG59XG5cblxuXG5cbmFzeW5jIGZ1bmN0aW9uIHB1dFByb2R1Y3RTdW1tYXJ5VG9EeW5hbW9EQihwcm9kdWN0X2NvZGU6IHN0cmluZywgcGFyYW1zX2hhc2g6IHN0cmluZywgc3VtbWFyeTogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZHluYW1vZGIuc2VuZChuZXcgUHV0SXRlbUNvbW1hbmQoe1xuICAgICAgICAgICAgVGFibGVOYW1lOiBQUk9EVUNUX1NVTU1BUllfVEFCTEVfTkFNRSxcbiAgICAgICAgICAgIEl0ZW06IHtcbiAgICAgICAgICAgICAgICBwcm9kdWN0X2NvZGU6IHsgUzogcHJvZHVjdF9jb2RlIH0sXG4gICAgICAgICAgICAgICAgcGFyYW1zX2hhc2g6IHsgUzogcGFyYW1zX2hhc2ggfSxcbiAgICAgICAgICAgICAgICBzdW1tYXJ5OiB7IFM6IHN1bW1hcnkgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KSk7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhcIlN1bW1hcnkgc2F2ZWQgaW50byBkYXRhYmFzZVwiKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3I6XCIsIGVycm9yKTtcbiAgICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1lc3NhZ2VIYW5kbGVyIChldmVudDogQVBJR2F0ZXdheVByb3h5RXZlbnRWMiwgcmVzcG9uc2VTdHJlYW06IE5vZGVKUy5Xcml0YWJsZVN0cmVhbSkge1xuXG4gICAgdHJ5IHtcbiAgICAgICAgbG9nZ2VyLmluZm8oZXZlbnQgYXMgYW55KTtcblxuICAgICAgICBjb25zdCBib2R5ID0gZXZlbnQuYm9keSA/IEpTT04ucGFyc2UoZXZlbnQuYm9keSkgOiB7fTtcbiAgICAgICAgY29uc3QgcHJvZHVjdENvZGUgPSBib2R5LnByb2R1Y3RDb2RlO1xuICAgICAgICBjb25zdCBsYW5ndWFnZSA9IGJvZHkubGFuZ3VhZ2U7XG5cbiAgICAgICAgY29uc3QgdXNlclByZWZlcmVuY2VLZXlzID0gT2JqZWN0LmtleXMoYm9keS5wcmVmZXJlbmNlcykuZmlsdGVyKGtleSA9PiBib2R5LnByZWZlcmVuY2VzW2tleV0pO1xuICAgICAgICBjb25zdCB1c2VyQWxsZXJnaWVzS2V5cyA9IE9iamVjdC5rZXlzKGJvZHkuYWxsZXJnaWVzKS5maWx0ZXIoa2V5ID0+IGJvZHkuYWxsZXJnaWVzW2tleV0pO1xuICAgICAgICBjb25zdCB1c2VySGVhbHRoR29hbCA9IGJvZHkuaGVhbHRoR29hbCB8fCAnJztcbiAgICAgICAgY29uc3QgdXNlclJlbGlnaW9uID0gYm9keS5yZWxpZ2lvbiB8fCAnJztcblxuICAgICAgICBjb25zdCB1c2VyUHJlZmVyZW5jZVN0cmluZyA9IHVzZXJQcmVmZXJlbmNlS2V5cy5qb2luKCcsICcpO1xuICAgICAgICBjb25zdCB1c2VyQWxsZXJnaWVzU3RyaW5nID0gdXNlckFsbGVyZ2llc0tleXMuam9pbignLCAnKTtcblxuXG4gICAgICAgIGNvbnN0IFtwcm9kdWN0TmFtZSwgcHJvZHVjdEluZ3JlZGllbnRzLCBwcm9kdWN0QWRkaXRpdmVzLCBwcm9kdWN0QWxsZXJnZW5zLCBwcm9kdWN0TnV0cmltZW50cywgcHJvZHVjdExhYmVscywgcHJvZHVjdENhdGVnb3JpZXNdID0gYXdhaXQgZ2V0UHJvZHVjdEZyb21EYihwcm9kdWN0Q29kZSwgbGFuZ3VhZ2UpO1xuICAgICAgICBpZiAocHJvZHVjdE5hbWUgJiYgcHJvZHVjdEluZ3JlZGllbnRzKSB7XG4gICAgICAgICAgICBsb2dnZXIuaW5mbyhcIlByb2R1Y3QgZm91bmRcIik7XG5cblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiUHJvZHVjdCBub3QgZm91bmQgaW4gdGhlIGRhdGFiYXNlXCIpO1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQcm9kdWN0IG5vdCBmb3VuZCBpbiB0aGUgZGF0YWJhc2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGhhc2hWYWx1ZSA9IGNhbGN1bGF0ZUhhc2gocHJvZHVjdENvZGUsIHVzZXJBbGxlcmdpZXNTdHJpbmcsIHVzZXJQcmVmZXJlbmNlU3RyaW5nLCBsYW5ndWFnZSk7XG5cbiAgICAgICAgbGV0IHByb2R1Y3RTdW1tYXJ5ID0gYXdhaXQgZ2V0UHJvZHVjdFN1bW1hcnkocHJvZHVjdENvZGUsIGhhc2hWYWx1ZSk7XG4gICAgICAgIGlmICghcHJvZHVjdFN1bW1hcnkpIHsgICAgICAgIFxuICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCJQcm9kdWN0IFN1bW1hcnkgbm90IGZvdW5kIGluIHRoZSBkYXRhYmFzZVwiKTtcbiAgICAgICAgICAgIGNvbnN0IGluZ3JlZGllbnRLZXlzID0gT2JqZWN0LmtleXMocHJvZHVjdEluZ3JlZGllbnRzKTtcbiAgICAgICAgICAgIGNvbnN0IGluZ3JlZGllbnRzU3RyaW5nID0gaW5ncmVkaWVudEtleXMuam9pbignLCAnKTtcblxuICAgICAgICAgICAgY29uc3QgcHJvbXB0VGV4dCA9IGdlbmVyYXRlUHJvZHVjdFN1bW1hcnlQcm9tcHQoXG4gICAgICAgICAgICAgICAgdXNlckFsbGVyZ2llc1N0cmluZyxcbiAgICAgICAgICAgICAgICB1c2VyUHJlZmVyZW5jZVN0cmluZyxcbiAgICAgICAgICAgICAgICB1c2VySGVhbHRoR29hbCxcbiAgICAgICAgICAgICAgICB1c2VyUmVsaWdpb24sXG4gICAgICAgICAgICAgICAgaW5ncmVkaWVudHNTdHJpbmcsXG4gICAgICAgICAgICAgICAgcHJvZHVjdE5hbWUsXG4gICAgICAgICAgICAgICAgcHJvZHVjdEFsbGVyZ2VucyB8fCBbXSxcbiAgICAgICAgICAgICAgICBwcm9kdWN0TnV0cmltZW50cyB8fCB7fSxcbiAgICAgICAgICAgICAgICBwcm9kdWN0TGFiZWxzIHx8IFtdLFxuICAgICAgICAgICAgICAgIHByb2R1Y3RDYXRlZ29yaWVzIHx8ICcnLFxuICAgICAgICAgICAgICAgIGxhbmd1YWdlIVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHByb2R1Y3RTdW1tYXJ5ID0gYXdhaXQgZ2VuZXJhdGVTdW1tYXJ5KHByb21wdFRleHQsIHJlc3BvbnNlU3RyZWFtKTtcbiAgICAgICAgICAgIGF3YWl0IHB1dFByb2R1Y3RTdW1tYXJ5VG9EeW5hbW9EQihwcm9kdWN0Q29kZSwgaGFzaFZhbHVlLCBwcm9kdWN0U3VtbWFyeSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBhd2FpdCBzaW11bGF0ZVN1bW1hcnlTdHJlYW1pbmcocHJvZHVjdFN1bW1hcnksIHJlc3BvbnNlU3RyZWFtKVxuXG4gICAgICAgIH1cbiAgICAgICAgbG9nZ2VyLmluZm8oYFByb2R1Y3QgU3VtbWFyeTogJHtwcm9kdWN0U3VtbWFyeX1gKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3I6XCIsIGVycm9yKTtcbiAgICB9XG4gICAgcmVzcG9uc2VTdHJlYW0uZW5kKCk7XG59XG5cbmV4cG9ydCBjb25zdCBoYW5kbGVyID0gYXdzbGFtYmRhLnN0cmVhbWlmeVJlc3BvbnNlKG1lc3NhZ2VIYW5kbGVyKTsiXX0= \ No newline at end of file diff --git a/lambda/recipe_step_by_step/index.js b/lambda/recipe_step_by_step/index.js index 90a1f04..b45e518 100644 --- a/lambda/recipe_step_by_step/index.js +++ b/lambda/recipe_step_by_step/index.js @@ -134,4 +134,4 @@ async function messageHandler(event, responseStream) { responseStream.end(); } exports.handler = awslambda.streamifyResponse(messageHandler); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwREFBdUQ7QUFDdkQsMERBQXVEO0FBR3ZELDRFQUE2RztBQWU3RyxNQUFNLFFBQVEsR0FBRyx3Q0FBd0MsQ0FBQTtBQUV6RCxNQUFNLE1BQU0sR0FBRyxJQUFJLGVBQU0sRUFBRSxDQUFDO0FBQzVCLE1BQU0sTUFBTSxHQUFHLElBQUksZUFBTSxFQUFFLENBQUM7QUFJNUIsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLDZDQUFvQixDQUFDLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxJQUFJLFdBQVcsRUFBRSxDQUFDLENBQUM7QUFLckcsS0FBSyxVQUFVLG1CQUFtQixDQUFDLFFBQWdCLEVBQUUsTUFBTSxFQUFFLGNBQWM7SUFFdkUsTUFBTSxZQUFZLEdBQUcsMmlCQUEyaUIsQ0FBQztJQUdqa0IsTUFBTSxVQUFVLEdBQUc7b0JBQ0gsTUFBTSxDQUFDLEtBQUs7MEJBQ04sTUFBTSxDQUFDLFdBQVc7NEJBQ2hCLE1BQU0sQ0FBQyxXQUFXLElBQUksTUFBTSxDQUFDLG9CQUFvQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzswQkF5Qm5ELFFBQVE7O2lIQUUrRSxDQUFDO0lBRTlHLE1BQU0sT0FBTyxHQUFHO1FBQ1osUUFBUSxFQUFFO1lBQ047Z0JBQ0ksSUFBSSxFQUFFLE1BQU07Z0JBQ1osT0FBTyxFQUFFO29CQUNMO3dCQUNJLE1BQU0sRUFBRSxNQUFNO3dCQUNkLE1BQU0sRUFBRSxVQUFVO3FCQUNyQjtpQkFDSjthQUNKO1NBQ0o7UUFDRCxVQUFVLEVBQUUsSUFBSTtRQUNoQixNQUFNLEVBQUUsWUFBWTtRQUNwQixXQUFXLEVBQUUsR0FBRztRQUNoQixjQUFjLEVBQUUsQ0FBQyxXQUFXLENBQUM7UUFDN0IsaUJBQWlCLEVBQUUsb0JBQW9CO0tBQ3hDLENBQUM7SUFDSixNQUFNLE1BQU0sR0FBRztRQUNYLE9BQU8sRUFBRSxRQUFRO1FBQ2pCLFdBQVcsRUFBRSxrQkFBa0I7UUFDL0IsTUFBTSxFQUFFLGtCQUFrQjtRQUMxQixJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUM7S0FDaEMsQ0FBQztJQUNGLElBQUksVUFBVSxHQUFHLEVBQUUsQ0FBQztJQUNwQixJQUFJO1FBQ0EsSUFBSTtZQUNBLElBQUksWUFBWSxHQUFHLElBQUksQ0FBQztZQUN4QixJQUFJLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztZQUMzQixNQUFNLE9BQU8sR0FBRyxJQUFJLDZEQUFvQyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2pFLE1BQU0sUUFBUSxHQUFHLE1BQU0sb0JBQW9CLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzFELE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUM7WUFDN0IsSUFBSSxLQUFLLEVBQUUsTUFBTSxLQUFLLElBQUksTUFBTSxJQUFJLEVBQUUsRUFBRTtnQkFDcEMsOERBQThEO2dCQUM5RCxJQUFJLEtBQUssQ0FBQyxLQUFLLEVBQUU7b0JBQ2YsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FDOUIsSUFBSSxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FDNUMsQ0FBQztvQkFDRixJQUFJLGFBQWEsQ0FBQyxJQUFJLEtBQU0scUJBQXFCLElBQUksYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUFDO3dCQUU3RixNQUFNLElBQUksR0FBRyxhQUFhLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQzt3QkFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEdBQUMsSUFBSSxDQUFDLENBQUE7d0JBRXpCLGdEQUFnRDt3QkFDaEQsNEJBQTRCO3dCQUM1QixNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7d0JBQ3RDLFVBQVUsSUFBSSxhQUFhLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQzt3QkFFdkMsSUFBRyxZQUFZLEVBQUM7NEJBQ1osaUJBQWlCLElBQUksSUFBSSxDQUFDOzRCQUMxQixPQUFPLENBQUMsR0FBRyxDQUFDLG9CQUFvQixHQUFDLGlCQUFpQixDQUFDLENBQUE7NEJBQ25ELElBQUksaUJBQWlCLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxFQUFFO2dDQUMzQyxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFBO2dDQUN4QixZQUFZLEdBQUcsS0FBSyxDQUFDO2dDQUNyQixNQUFNLFVBQVUsR0FBRyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQztnQ0FDbkYsTUFBTSxhQUFhLEdBQUcsaUJBQWlCLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dDQUM5RCxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dDQUMzQixjQUFjLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDOzZCQUNyQzt5QkFFSjs2QkFBSTs0QkFDSCxPQUFPLENBQUMsR0FBRyxDQUFDLDRCQUE0QixHQUFDLElBQUksQ0FBQyxDQUFBOzRCQUM5QyxjQUFjLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFBO3lCQUMzQjtxQkFFSjtpQkFHRjtxQkFBTTtvQkFDTCxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsS0FBSyxFQUFFLENBQUMsQ0FBQTtpQkFDakM7YUFDRjtZQUdELE1BQU0sQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUE7U0FDakM7UUFBQyxPQUFPLEdBQUcsRUFBRTtZQUNWLGVBQWU7WUFDZixNQUFNLENBQUMsS0FBSyxDQUFDLEdBQVUsQ0FBQyxDQUFDO1NBQzVCO0tBQ0o7SUFDRCxPQUFPLENBQUMsRUFBRTtRQUNOLE1BQU0sQ0FBQyxLQUFLLENBQUMsbUNBQW1DLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDckQsVUFBVSxHQUFHLGdDQUFnQyxDQUFDO0tBQ2pEO0lBQ0QsT0FBTyxVQUFVLENBQUM7QUFDdEIsQ0FBQztBQUlELEtBQUssVUFBVSxjQUFjLENBQUUsS0FBSyxFQUFFLGNBQWM7SUFFaEQsSUFBSTtRQUNBLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBWSxDQUFDLENBQUM7UUFFMUIsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUN0RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQy9CLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDM0IsTUFBTSxXQUFXLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQ2hGLDRFQUE0RTtLQUUvRTtJQUFDLE9BQU8sS0FBSyxFQUFFO1FBQ1osT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDbEM7SUFDRCxjQUFjLENBQUMsR0FBRyxFQUFFLENBQUM7QUFDekIsQ0FBQztBQUVZLFFBQUEsT0FBTyxHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxjQUFjLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRyYWNlciB9IGZyb20gXCJAYXdzLWxhbWJkYS1wb3dlcnRvb2xzL3RyYWNlclwiO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSBcIkBhd3MtbGFtYmRhLXBvd2VydG9vbHMvbG9nZ2VyXCI7XG5pbXBvcnQgeyBBUElHYXRld2F5UHJveHlFdmVudFYyLCBIYW5kbGVyLCBDb250ZXh0IH0gZnJvbSAnYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7IEJlZHJvY2tSdW50aW1lQ2xpZW50LCBJbnZva2VNb2RlbFdpdGhSZXNwb25zZVN0cmVhbUNvbW1hbmQgfSBmcm9tIFwiQGF3cy1zZGsvY2xpZW50LWJlZHJvY2stcnVudGltZVwiO1xuXG5kZWNsYXJlIGdsb2JhbCB7XG4gICAgbmFtZXNwYWNlIGF3c2xhbWJkYSB7XG4gICAgICBmdW5jdGlvbiBzdHJlYW1pZnlSZXNwb25zZShcbiAgICAgICAgZjogKFxuICAgICAgICAgIGV2ZW50OiBBUElHYXRld2F5UHJveHlFdmVudFYyLFxuICAgICAgICAgIHJlc3BvbnNlU3RyZWFtOiBOb2RlSlMuV3JpdGFibGVTdHJlYW0sXG4gICAgICAgICAgY29udGV4dDogQ29udGV4dFxuICAgICAgICApID0+IFByb21pc2U8dm9pZD5cbiAgICAgICk6IEhhbmRsZXI7XG4gICAgfVxufVxuXG5cbmNvbnN0IE1PREVMX0lEID0gXCJhbnRocm9waWMuY2xhdWRlLTMtaGFpa3UtMjAyNDAzMDctdjE6MFwiXG5cbmNvbnN0IHRyYWNlciA9IG5ldyBUcmFjZXIoKTtcbmNvbnN0IGxvZ2dlciA9IG5ldyBMb2dnZXIoKTtcblxuXG5cbmNvbnN0IGJlZHJvY2tSdW50aW1lQ2xpZW50ID0gbmV3IEJlZHJvY2tSdW50aW1lQ2xpZW50KHsgcmVnaW9uOiBwcm9jZXNzLmVudi5SRUdJT04gfHwgJ3VzLWVhc3QtMScgfSk7XG5cblxuXG5cbmFzeW5jIGZ1bmN0aW9uIGdlbmVyYXRlUmVjaXBlU3RlcHMobGFuZ3VhZ2U6IHN0cmluZywgcmVjaXBlLCByZXNwb25zZVN0cmVhbSkge1xuXG4gICAgY29uc3Qgc3lzdGVtUHJvbXB0ID0gXCJZb3VyIHRhc2sgaXMgdG8gZ2VuZXJhdGUgcGVyc29uYWxpemVkIHJlY2lwZSBpZGVhcyBiYXNlZCBvbiB0aGUgdXNlcidzIGlucHV0IG9mIGF2YWlsYWJsZSBpbmdyZWRpZW50cyBhbmQgZGlldGFyeSBwcmVmZXJlbmNlcy4gVXNlIHRoaXMgaW5mb3JtYXRpb24gdG8gc3VnZ2VzdCBhIHZhcmlldHkgb2YgY3JlYXRpdmUgYW5kIGRlbGljaW91cyByZWNpcGVzIHRoYXQgY2FuIGJlIG1hZGUgdXNpbmcgdGhlIGdpdmVuIGluZ3JlZGllbnRzIHdoaWxlIGFjY29tbW9kYXRpbmcgdGhlIHVzZXIncyBkaWV0YXJ5IG5lZWRzLCBpZiBhbnkgYXJlIG1lbnRpb25lZC4gRm9yIGVhY2ggcmVjaXBlLCBwcm92aWRlIGEgYnJpZWYgZGVzY3JpcHRpb24sIGEgbGlzdCBvZiByZXF1aXJlZCBpbmdyZWRpZW50cywgYW5kIGEgc2ltcGxlIHNldCBvZiBpbnN0cnVjdGlvbnMuIEVuc3VyZSB0aGF0IHRoZSByZWNpcGVzIGFyZSBlYXN5IHRvIGZvbGxvdywgbnV0cml0aW91cywgYW5kIGNhbiBiZSBwcmVwYXJlZCB3aXRoIG1pbmltYWwgYWRkaXRpb25hbCBpbmdyZWRpZW50cyBvciBlcXVpcG1lbnQuXCI7XG5cblxuICAgIGNvbnN0IHByb21wdFRleHQgPSBgXG4gICAgUmVjaXBlZSB0aXRsZToke3JlY2lwZS50aXRsZX1cbiAgICBSZWNpcGVlIGRlc2NyaXB0aW9uOiR7cmVjaXBlLmRlc2NyaXB0aW9ufVxuICAgIEF2YWlsYWJsZSBpbmdyZWRpZW50czoke3JlY2lwZS5pbmdyZWRpZW50c30gJHtyZWNpcGUub3B0aW9uYWxfaW5ncmVkaWVudHN9XG4gICAgXG4gICAgQW5zd2VyIG11c3QgYmUgaW4gdGhlIGZvbGxvd2luZyBtYXJrZG93biBmb3JtYXQ6XG4gICAgIyMjIFN0ZXAgMTogW1N0ZXAgVGl0bGVdXG4gICAgLSBBY3Rpb24gMTogW0FjdGlvbiBkZXNjcmlwdGlvbl0gXG4gICAgLSBBY3Rpb24gMjogW0FjdGlvbiBkZXNjcmlwdGlvbl1cblxuICAgICoqSW5ncmVkaWVudHM6KiogW0luZ3JlZGllbnQgMV0sIFtJbmdyZWRpZW50IDJdLCBbSW5ncmVkaWVudCAzXVxuXG4gICAgIyMjIFN0ZXAgMjogW1N0ZXAgVGl0bGVdXG4gICAgLSBBY3Rpb24gMTogW0FjdGlvbiBkZXNjcmlwdGlvbl1cbiAgICAtIEFjdGlvbiAyOiBbQWN0aW9uIGRlc2NyaXB0aW9uXVxuXG4gICAgKipJbmdyZWRpZW50czoqKiBbSW5ncmVkaWVudCAxXSwgW0luZ3JlZGllbnQgMl1cblxuICAgICMjIyBTdGVwIDM6IFtTdGVwIFRpdGxlXVxuICAgIC0gQWN0aW9uIDE6IFtBY3Rpb24gZGVzY3JpcHRpb25dXG4gICAgLSBBY3Rpb24gMjogW0FjdGlvbiBkZXNjcmlwdGlvbl1cblxuICAgICoqSW5ncmVkaWVudHM6KiogW0luZ3JlZGllbnQgMV0sIFtJbmdyZWRpZW50IDJdLCBbSW5ncmVkaWVudCAzXSwgW0luZ3JlZGllbnQgNF1cblxuICAgIERlc2NyaWJlIHRoZSBhY3Rpb25zIGluIGVhY2ggc3RlcCB3aXRoIGRldGFpbGVkIGJ1dCBjb25jaXNlIGRlc2NyaXB0aW9ucywgaW5jbHVkaW5nIGluZ3JlZGllbnRzIG5lZWRlZCwgcXVhbnRpdGllcywgdGltZSwgYW5kIGFueSBhcHBsaWFuY2VzIHJlcXVpcmVkLiBFbnN1cmUgeW91ciB0b25lIGlzIGVuZ2FnaW5nIGFuZCBmcmllbmRseS5cbiAgICBcbiAgICBPbmx5IHVzZSBpbmdyZWRpZW50cyBwcmVzZW50IGluIHRoZSBwcm92aWRlZCByZWNpcGUuXG5cbiAgICBSZXNwb25zZSBtdXN0IGJlIGluICR7bGFuZ3VhZ2V9LlxuXG4gICAgVGhpbmsgc3RlcCBieSBzdGVwIGFuZCBlbGFib3JhdGUgeW91ciB0aG91Z2h0cyBpbnNpZGUgPHRoaW5raW5nPjwvdGhpbmtpbmc+IHRoZW4gYW5zd2VyIGluIGEgbWFya2Rvd24gZm9ybWF0YDtcblxuICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgIG1lc3NhZ2VzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgcm9sZTogXCJ1c2VyXCIsXG4gICAgICAgICAgICAgICAgY29udGVudDogW1xuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBcInR5cGVcIjogXCJ0ZXh0XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBcInRleHRcIjogcHJvbXB0VGV4dFxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgfVxuICAgICAgICBdLFxuICAgICAgICBtYXhfdG9rZW5zOiAxMDAwLFxuICAgICAgICBzeXN0ZW06IHN5c3RlbVByb21wdCxcbiAgICAgICAgdGVtcGVyYXR1cmU6IDAuNSxcbiAgICAgICAgc3RvcF9zZXF1ZW5jZXM6IFsnPC9hbnN3ZXI+J10sXG4gICAgICAgIGFudGhyb3BpY192ZXJzaW9uOiBcImJlZHJvY2stMjAyMy0wNS0zMVwiXG4gICAgICB9O1xuICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgbW9kZWxJZDogTU9ERUxfSUQsXG4gICAgICAgIGNvbnRlbnRUeXBlOiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgICAgYWNjZXB0OiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkocGF5bG9hZCksXG4gICAgfTtcbiAgICBsZXQgY29tcGxldGlvbiA9ICcnO1xuICAgIHRyeSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsZXQgYWNjdW11bGF0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIGxldCBhY2N1bXVsYXRlZENodW5rcyA9ICcnO1xuICAgICAgICAgICAgY29uc3QgY29tbWFuZCA9IG5ldyBJbnZva2VNb2RlbFdpdGhSZXNwb25zZVN0cmVhbUNvbW1hbmQocGFyYW1zKTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYmVkcm9ja1J1bnRpbWVDbGllbnQuc2VuZChjb21tYW5kKTtcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50cyA9IHJlc3BvbnNlLmJvZHk7XG4gICAgICAgICAgICBmb3IgYXdhaXQgKGNvbnN0IGV2ZW50IG9mIGV2ZW50cyB8fCBbXSkge1xuICAgICAgICAgICAgICAgIC8vIENoZWNrIHRoZSB0b3AtbGV2ZWwgZmllbGQgdG8gZGV0ZXJtaW5lIHdoaWNoIGV2ZW50IHRoaXMgaXMuXG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50LmNodW5rKSB7XG4gICAgICAgICAgICAgICAgICBjb25zdCBkZWNvZGVkX2V2ZW50ID0gSlNPTi5wYXJzZShcbiAgICAgICAgICAgICAgICAgICAgbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGV2ZW50LmNodW5rLmJ5dGVzKSxcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICBpZiAoZGVjb2RlZF9ldmVudC50eXBlICA9PT0gJ2NvbnRlbnRfYmxvY2tfZGVsdGEnICYmIGRlY29kZWRfZXZlbnQuZGVsdGEudHlwZSA9PT0gJ3RleHRfZGVsdGEnKXtcbiAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRleHQgPSBkZWNvZGVkX2V2ZW50LmRlbHRhLnRleHQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwidGV4dD1cIit0ZXh0KVxuXG4gICAgICAgICAgICAgICAgICAgIC8vcmVzcG9uc2VTdHJlYW0ud3JpdGUoZGVjb2RlZF9ldmVudC5kZWx0YS50ZXh0KVxuICAgICAgICAgICAgICAgICAgICAvL2FjY3VtdWxhdGVkQ2h1bmtzICs9IHRleHQ7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGRlY29kZWRfZXZlbnQuZGVsdGEudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBsZXRpb24gKz0gZGVjb2RlZF9ldmVudC5kZWx0YS50ZXh0O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmKGFjY3VtdWxhdGluZyl7XG4gICAgICAgICAgICAgICAgICAgICAgICBhY2N1bXVsYXRlZENodW5rcyArPSB0ZXh0O1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJhY2N1bXVsYXRlZENodW5rcz1cIithY2N1bXVsYXRlZENodW5rcylcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhY2N1bXVsYXRlZENodW5rcy5pbmNsdWRlcygnPC90aGlua2luZz4nKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwidGFnIGZvdW5kXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWNjdW11bGF0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RhcnRJbmRleCA9IGFjY3VtdWxhdGVkQ2h1bmtzLmluZGV4T2YoXCI8L3RoaW5raW5nPlwiKSArIFwiPC90aGlua2luZz5cIi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVtYWluaW5nVGV4dCA9IGFjY3VtdWxhdGVkQ2h1bmtzLnN1YnN0cmluZyhzdGFydEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhyZW1haW5pbmdUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZVN0cmVhbS53cml0ZShyZW1haW5pbmdUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcInJlc3BvbnNlU3RyZWFtIHdyaXRlIHRleHQ9XCIrdGV4dClcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlU3RyZWFtLndyaXRlKHRleHQpXG4gICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICB9XG5cblxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoYGV2ZW50ID0gJHtldmVudH1gKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXG4gICAgICAgICAgICBcbiAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ1N0cmVhbSBlbmRlZCEnKVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIC8vIGhhbmRsZSBlcnJvclxuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGVyciBhcyBhbnkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihgRXJyb3Igd2hpbGUgZ2VuZXJhdGluZyBzdW1tYXJ5OiAke2V9YCk7XG4gICAgICAgIGNvbXBsZXRpb24gPSBcIkVycm9yIHdoaWxlIGdlbmVyYXRpbmcgc3VtbWFyeVwiO1xuICAgIH1cbiAgICByZXR1cm4gY29tcGxldGlvbjtcbn1cblxuXG5cbmFzeW5jIGZ1bmN0aW9uIG1lc3NhZ2VIYW5kbGVyIChldmVudCwgcmVzcG9uc2VTdHJlYW0pIHtcblxuICAgIHRyeSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKGV2ZW50IGFzIGFueSk7XG5cbiAgICAgICAgY29uc3QgYm9keSA9IGV2ZW50LmJvZHkgPyBKU09OLnBhcnNlKGV2ZW50LmJvZHkpIDoge307XG4gICAgICAgIGNvbnN0IGxhbmd1YWdlID0gYm9keS5sYW5ndWFnZTtcbiAgICAgICAgY29uc3QgcmVjaXBlID0gYm9keS5yZWNpcGU7XG4gICAgICAgIGNvbnN0IHJlY2lwZVN0ZXBzID0gYXdhaXQgZ2VuZXJhdGVSZWNpcGVTdGVwcyhsYW5ndWFnZSwgcmVjaXBlLCByZXNwb25zZVN0cmVhbSk7XG4gICAgICAgIC8vYXdhaXQgcHV0UHJvZHVjdFN1bW1hcnlUb0R5bmFtb0RCKHByb2R1Y3RDb2RlLCBoYXNoVmFsdWUsIHByb2R1Y3RTdW1tYXJ5KTtcbiAgICAgICAgXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yOlwiLCBlcnJvcik7XG4gICAgfVxuICAgIHJlc3BvbnNlU3RyZWFtLmVuZCgpO1xufVxuXG5leHBvcnQgY29uc3QgaGFuZGxlciA9IGF3c2xhbWJkYS5zdHJlYW1pZnlSZXNwb25zZShtZXNzYWdlSGFuZGxlcik7Il19 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwREFBdUQ7QUFDdkQsMERBQXVEO0FBR3ZELDRFQUE2RztBQWU3RyxNQUFNLFFBQVEsR0FBRyx3Q0FBd0MsQ0FBQTtBQUV6RCxNQUFNLE1BQU0sR0FBRyxJQUFJLGVBQU0sRUFBRSxDQUFDO0FBQzVCLE1BQU0sTUFBTSxHQUFHLElBQUksZUFBTSxFQUFFLENBQUM7QUFJNUIsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLDZDQUFvQixDQUFDLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxJQUFJLFdBQVcsRUFBRSxDQUFDLENBQUM7QUFLckcsS0FBSyxVQUFVLG1CQUFtQixDQUFDLFFBQWdCLEVBQUUsTUFBVyxFQUFFLGNBQXFDO0lBRW5HLE1BQU0sWUFBWSxHQUFHLDJpQkFBMmlCLENBQUM7SUFHamtCLE1BQU0sVUFBVSxHQUFHO29CQUNILE1BQU0sQ0FBQyxLQUFLOzBCQUNOLE1BQU0sQ0FBQyxXQUFXOzRCQUNoQixNQUFNLENBQUMsV0FBVyxJQUFJLE1BQU0sQ0FBQyxvQkFBb0I7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7MEJBeUJuRCxRQUFROztpSEFFK0UsQ0FBQztJQUU5RyxNQUFNLE9BQU8sR0FBRztRQUNaLFFBQVEsRUFBRTtZQUNOO2dCQUNJLElBQUksRUFBRSxNQUFNO2dCQUNaLE9BQU8sRUFBRTtvQkFDTDt3QkFDSSxNQUFNLEVBQUUsTUFBTTt3QkFDZCxNQUFNLEVBQUUsVUFBVTtxQkFDckI7aUJBQ0o7YUFDSjtTQUNKO1FBQ0QsVUFBVSxFQUFFLElBQUk7UUFDaEIsTUFBTSxFQUFFLFlBQVk7UUFDcEIsV0FBVyxFQUFFLEdBQUc7UUFDaEIsY0FBYyxFQUFFLENBQUMsV0FBVyxDQUFDO1FBQzdCLGlCQUFpQixFQUFFLG9CQUFvQjtLQUN4QyxDQUFDO0lBQ0osTUFBTSxNQUFNLEdBQUc7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Z0MsQ0FBQztLQUNqRDtJQUNELE9BQU8sVUFBVSxDQUFDO0FBQ3RCLENBQUM7QUFJRCxLQUFLLFVBQVUsY0FBYyxDQUFFLEtBQTZCLEVBQUUsY0FBcUM7SUFFL0YsSUFBSTtRQUNBLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBWSxDQUFDLENBQUM7UUFFMUIsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUN0RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQy9CLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDM0IsTUFBTSxXQUFXLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQ2hGLDRFQUE0RTtLQUUvRTtJQUFDLE9BQU8sS0FBSyxFQUFFO1FBQ1osT0FBTyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDbEM7SUFDRCxjQUFjLENBQUMsR0FBRyxFQUFFLENBQUM7QUFDekIsQ0FBQztBQUVZLFFBQUEsT0FBTyxHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxjQUFjLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRyYWNlciB9IGZyb20gXCJAYXdzLWxhbWJkYS1wb3dlcnRvb2xzL3RyYWNlclwiO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSBcIkBhd3MtbGFtYmRhLXBvd2VydG9vbHMvbG9nZ2VyXCI7XG5pbXBvcnQgeyBBUElHYXRld2F5UHJveHlFdmVudFYyLCBIYW5kbGVyLCBDb250ZXh0IH0gZnJvbSAnYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7IEJlZHJvY2tSdW50aW1lQ2xpZW50LCBJbnZva2VNb2RlbFdpdGhSZXNwb25zZVN0cmVhbUNvbW1hbmQgfSBmcm9tIFwiQGF3cy1zZGsvY2xpZW50LWJlZHJvY2stcnVudGltZVwiO1xuXG5kZWNsYXJlIGdsb2JhbCB7XG4gICAgbmFtZXNwYWNlIGF3c2xhbWJkYSB7XG4gICAgICBmdW5jdGlvbiBzdHJlYW1pZnlSZXNwb25zZShcbiAgICAgICAgZjogKFxuICAgICAgICAgIGV2ZW50OiBBUElHYXRld2F5UHJveHlFdmVudFYyLFxuICAgICAgICAgIHJlc3BvbnNlU3RyZWFtOiBOb2RlSlMuV3JpdGFibGVTdHJlYW0sXG4gICAgICAgICAgY29udGV4dDogQ29udGV4dFxuICAgICAgICApID0+IFByb21pc2U8dm9pZD5cbiAgICAgICk6IEhhbmRsZXI7XG4gICAgfVxufVxuXG5cbmNvbnN0IE1PREVMX0lEID0gXCJhbnRocm9waWMuY2xhdWRlLTMtaGFpa3UtMjAyNDAzMDctdjE6MFwiXG5cbmNvbnN0IHRyYWNlciA9IG5ldyBUcmFjZXIoKTtcbmNvbnN0IGxvZ2dlciA9IG5ldyBMb2dnZXIoKTtcblxuXG5cbmNvbnN0IGJlZHJvY2tSdW50aW1lQ2xpZW50ID0gbmV3IEJlZHJvY2tSdW50aW1lQ2xpZW50KHsgcmVnaW9uOiBwcm9jZXNzLmVudi5SRUdJT04gfHwgJ3VzLWVhc3QtMScgfSk7XG5cblxuXG5cbmFzeW5jIGZ1bmN0aW9uIGdlbmVyYXRlUmVjaXBlU3RlcHMobGFuZ3VhZ2U6IHN0cmluZywgcmVjaXBlOiBhbnksIHJlc3BvbnNlU3RyZWFtOiBOb2RlSlMuV3JpdGFibGVTdHJlYW0pIHtcblxuICAgIGNvbnN0IHN5c3RlbVByb21wdCA9IFwiWW91ciB0YXNrIGlzIHRvIGdlbmVyYXRlIHBlcnNvbmFsaXplZCByZWNpcGUgaWRlYXMgYmFzZWQgb24gdGhlIHVzZXIncyBpbnB1dCBvZiBhdmFpbGFibGUgaW5ncmVkaWVudHMgYW5kIGRpZXRhcnkgcHJlZmVyZW5jZXMuIFVzZSB0aGlzIGluZm9ybWF0aW9uIHRvIHN1Z2dlc3QgYSB2YXJpZXR5IG9mIGNyZWF0aXZlIGFuZCBkZWxpY2lvdXMgcmVjaXBlcyB0aGF0IGNhbiBiZSBtYWRlIHVzaW5nIHRoZSBnaXZlbiBpbmdyZWRpZW50cyB3aGlsZSBhY2NvbW1vZGF0aW5nIHRoZSB1c2VyJ3MgZGlldGFyeSBuZWVkcywgaWYgYW55IGFyZSBtZW50aW9uZWQuIEZvciBlYWNoIHJlY2lwZSwgcHJvdmlkZSBhIGJyaWVmIGRlc2NyaXB0aW9uLCBhIGxpc3Qgb2YgcmVxdWlyZWQgaW5ncmVkaWVudHMsIGFuZCBhIHNpbXBsZSBzZXQgb2YgaW5zdHJ1Y3Rpb25zLiBFbnN1cmUgdGhhdCB0aGUgcmVjaXBlcyBhcmUgZWFzeSB0byBmb2xsb3csIG51dHJpdGlvdXMsIGFuZCBjYW4gYmUgcHJlcGFyZWQgd2l0aCBtaW5pbWFsIGFkZGl0aW9uYWwgaW5ncmVkaWVudHMgb3IgZXF1aXBtZW50LlwiO1xuXG5cbiAgICBjb25zdCBwcm9tcHRUZXh0ID0gYFxuICAgIFJlY2lwZWUgdGl0bGU6JHtyZWNpcGUudGl0bGV9XG4gICAgUmVjaXBlZSBkZXNjcmlwdGlvbjoke3JlY2lwZS5kZXNjcmlwdGlvbn1cbiAgICBBdmFpbGFibGUgaW5ncmVkaWVudHM6JHtyZWNpcGUuaW5ncmVkaWVudHN9ICR7cmVjaXBlLm9wdGlvbmFsX2luZ3JlZGllbnRzfVxuICAgIFxuICAgIEFuc3dlciBtdXN0IGJlIGluIHRoZSBmb2xsb3dpbmcgbWFya2Rvd24gZm9ybWF0OlxuICAgICMjIyBTdGVwIDE6IFtTdGVwIFRpdGxlXVxuICAgIC0gQWN0aW9uIDE6IFtBY3Rpb24gZGVzY3JpcHRpb25dIFxuICAgIC0gQWN0aW9uIDI6IFtBY3Rpb24gZGVzY3JpcHRpb25dXG5cbiAgICAqKkluZ3JlZGllbnRzOioqIFtJbmdyZWRpZW50IDFdLCBbSW5ncmVkaWVudCAyXSwgW0luZ3JlZGllbnQgM11cblxuICAgICMjIyBTdGVwIDI6IFtTdGVwIFRpdGxlXVxuICAgIC0gQWN0aW9uIDE6IFtBY3Rpb24gZGVzY3JpcHRpb25dXG4gICAgLSBBY3Rpb24gMjogW0FjdGlvbiBkZXNjcmlwdGlvbl1cblxuICAgICoqSW5ncmVkaWVudHM6KiogW0luZ3JlZGllbnQgMV0sIFtJbmdyZWRpZW50IDJdXG5cbiAgICAjIyMgU3RlcCAzOiBbU3RlcCBUaXRsZV1cbiAgICAtIEFjdGlvbiAxOiBbQWN0aW9uIGRlc2NyaXB0aW9uXVxuICAgIC0gQWN0aW9uIDI6IFtBY3Rpb24gZGVzY3JpcHRpb25dXG5cbiAgICAqKkluZ3JlZGllbnRzOioqIFtJbmdyZWRpZW50IDFdLCBbSW5ncmVkaWVudCAyXSwgW0luZ3JlZGllbnQgM10sIFtJbmdyZWRpZW50IDRdXG5cbiAgICBEZXNjcmliZSB0aGUgYWN0aW9ucyBpbiBlYWNoIHN0ZXAgd2l0aCBkZXRhaWxlZCBidXQgY29uY2lzZSBkZXNjcmlwdGlvbnMsIGluY2x1ZGluZyBpbmdyZWRpZW50cyBuZWVkZWQsIHF1YW50aXRpZXMsIHRpbWUsIGFuZCBhbnkgYXBwbGlhbmNlcyByZXF1aXJlZC4gRW5zdXJlIHlvdXIgdG9uZSBpcyBlbmdhZ2luZyBhbmQgZnJpZW5kbHkuXG4gICAgXG4gICAgT25seSB1c2UgaW5ncmVkaWVudHMgcHJlc2VudCBpbiB0aGUgcHJvdmlkZWQgcmVjaXBlLlxuXG4gICAgUmVzcG9uc2UgbXVzdCBiZSBpbiAke2xhbmd1YWdlfS5cblxuICAgIFRoaW5rIHN0ZXAgYnkgc3RlcCBhbmQgZWxhYm9yYXRlIHlvdXIgdGhvdWdodHMgaW5zaWRlIDx0aGlua2luZz48L3RoaW5raW5nPiB0aGVuIGFuc3dlciBpbiBhIG1hcmtkb3duIGZvcm1hdGA7XG5cbiAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgICBtZXNzYWdlczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHJvbGU6IFwidXNlclwiLFxuICAgICAgICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgXCJ0eXBlXCI6IFwidGV4dFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJ0ZXh0XCI6IHByb21wdFRleHRcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH1cbiAgICAgICAgXSxcbiAgICAgICAgbWF4X3Rva2VuczogMTAwMCxcbiAgICAgICAgc3lzdGVtOiBzeXN0ZW1Qcm9tcHQsXG4gICAgICAgIHRlbXBlcmF0dXJlOiAwLjUsXG4gICAgICAgIHN0b3Bfc2VxdWVuY2VzOiBbJzwvYW5zd2VyPiddLFxuICAgICAgICBhbnRocm9waWNfdmVyc2lvbjogXCJiZWRyb2NrLTIwMjMtMDUtMzFcIlxuICAgICAgfTtcbiAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIG1vZGVsSWQ6IE1PREVMX0lELFxuICAgICAgICBjb250ZW50VHlwZTogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgIGFjY2VwdDogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHBheWxvYWQpLFxuICAgIH07XG4gICAgbGV0IGNvbXBsZXRpb24gPSAnJztcbiAgICB0cnkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgbGV0IGFjY3VtdWxhdGluZyA9IHRydWU7XG4gICAgICAgICAgICBsZXQgYWNjdW11bGF0ZWRDaHVua3MgPSAnJztcbiAgICAgICAgICAgIGNvbnN0IGNvbW1hbmQgPSBuZXcgSW52b2tlTW9kZWxXaXRoUmVzcG9uc2VTdHJlYW1Db21tYW5kKHBhcmFtcyk7XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGJlZHJvY2tSdW50aW1lQ2xpZW50LnNlbmQoY29tbWFuZCk7XG4gICAgICAgICAgICBjb25zdCBldmVudHMgPSByZXNwb25zZS5ib2R5O1xuICAgICAgICAgICAgZm9yIGF3YWl0IChjb25zdCBldmVudCBvZiBldmVudHMgfHwgW10pIHtcbiAgICAgICAgICAgICAgICAvLyBDaGVjayB0aGUgdG9wLWxldmVsIGZpZWxkIHRvIGRldGVybWluZSB3aGljaCBldmVudCB0aGlzIGlzLlxuICAgICAgICAgICAgICAgIGlmIChldmVudC5jaHVuaykge1xuICAgICAgICAgICAgICAgICAgY29uc3QgZGVjb2RlZF9ldmVudCA9IEpTT04ucGFyc2UoXG4gICAgICAgICAgICAgICAgICAgIG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShldmVudC5jaHVuay5ieXRlcyksXG4gICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgaWYgKGRlY29kZWRfZXZlbnQudHlwZSAgPT09ICdjb250ZW50X2Jsb2NrX2RlbHRhJyAmJiBkZWNvZGVkX2V2ZW50LmRlbHRhLnR5cGUgPT09ICd0ZXh0X2RlbHRhJyl7XG4gICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXh0ID0gZGVjb2RlZF9ldmVudC5kZWx0YS50ZXh0O1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcInRleHQ9XCIrdGV4dClcblxuICAgICAgICAgICAgICAgICAgICAvL3Jlc3BvbnNlU3RyZWFtLndyaXRlKGRlY29kZWRfZXZlbnQuZGVsdGEudGV4dClcbiAgICAgICAgICAgICAgICAgICAgLy9hY2N1bXVsYXRlZENodW5rcyArPSB0ZXh0O1xuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhkZWNvZGVkX2V2ZW50LmRlbHRhLnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0aW9uICs9IGRlY29kZWRfZXZlbnQuZGVsdGEudGV4dDtcblxuICAgICAgICAgICAgICAgICAgICBpZihhY2N1bXVsYXRpbmcpe1xuICAgICAgICAgICAgICAgICAgICAgICAgYWNjdW11bGF0ZWRDaHVua3MgKz0gdGV4dDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiYWNjdW11bGF0ZWRDaHVua3M9XCIrYWNjdW11bGF0ZWRDaHVua3MpXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWNjdW11bGF0ZWRDaHVua3MuaW5jbHVkZXMoJzwvdGhpbmtpbmc+JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcInRhZyBmb3VuZFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjY3VtdWxhdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0SW5kZXggPSBhY2N1bXVsYXRlZENodW5rcy5pbmRleE9mKFwiPC90aGlua2luZz5cIikgKyBcIjwvdGhpbmtpbmc+XCIubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlbWFpbmluZ1RleHQgPSBhY2N1bXVsYXRlZENodW5rcy5zdWJzdHJpbmcoc3RhcnRJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8ocmVtYWluaW5nVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2VTdHJlYW0ud3JpdGUocmVtYWluaW5nVGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgIH1lbHNle1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJyZXNwb25zZVN0cmVhbSB3cml0ZSB0ZXh0PVwiK3RleHQpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZVN0cmVhbS53cml0ZSh0ZXh0KVxuICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGBldmVudCA9ICR7ZXZlbnR9YClcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgXG4gICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdTdHJlYW0gZW5kZWQhJylcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAvLyBoYW5kbGUgZXJyb3JcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlcnIgYXMgYW55KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoYEVycm9yIHdoaWxlIGdlbmVyYXRpbmcgc3VtbWFyeTogJHtlfWApO1xuICAgICAgICBjb21wbGV0aW9uID0gXCJFcnJvciB3aGlsZSBnZW5lcmF0aW5nIHN1bW1hcnlcIjtcbiAgICB9XG4gICAgcmV0dXJuIGNvbXBsZXRpb247XG59XG5cblxuXG5hc3luYyBmdW5jdGlvbiBtZXNzYWdlSGFuZGxlciAoZXZlbnQ6IEFQSUdhdGV3YXlQcm94eUV2ZW50VjIsIHJlc3BvbnNlU3RyZWFtOiBOb2RlSlMuV3JpdGFibGVTdHJlYW0pIHtcblxuICAgIHRyeSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKGV2ZW50IGFzIGFueSk7XG5cbiAgICAgICAgY29uc3QgYm9keSA9IGV2ZW50LmJvZHkgPyBKU09OLnBhcnNlKGV2ZW50LmJvZHkpIDoge307XG4gICAgICAgIGNvbnN0IGxhbmd1YWdlID0gYm9keS5sYW5ndWFnZTtcbiAgICAgICAgY29uc3QgcmVjaXBlID0gYm9keS5yZWNpcGU7XG4gICAgICAgIGNvbnN0IHJlY2lwZVN0ZXBzID0gYXdhaXQgZ2VuZXJhdGVSZWNpcGVTdGVwcyhsYW5ndWFnZSwgcmVjaXBlLCByZXNwb25zZVN0cmVhbSk7XG4gICAgICAgIC8vYXdhaXQgcHV0UHJvZHVjdFN1bW1hcnlUb0R5bmFtb0RCKHByb2R1Y3RDb2RlLCBoYXNoVmFsdWUsIHByb2R1Y3RTdW1tYXJ5KTtcbiAgICAgICAgXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yOlwiLCBlcnJvcik7XG4gICAgfVxuICAgIHJlc3BvbnNlU3RyZWFtLmVuZCgpO1xufVxuXG5leHBvcnQgY29uc3QgaGFuZGxlciA9IGF3c2xhbWJkYS5zdHJlYW1pZnlSZXNwb25zZShtZXNzYWdlSGFuZGxlcik7Il19 \ No newline at end of file diff --git a/resources/ui/src/assets/i18n/all.ts b/resources/ui/src/assets/i18n/all.ts index 3796a08..fc9e64d 100644 --- a/resources/ui/src/assets/i18n/all.ts +++ b/resources/ui/src/assets/i18n/all.ts @@ -38,6 +38,8 @@ const customTranslations: Record> = { ingredients_desc_additive: "Click on each additive to view AI-generated detailed descriptions", ingredients_no_additive: "The product does not have additives", + allergen_warning_title: "Allergen Warning", + allergen_warning_message: "This product contains allergens you're sensitive to:", summary_title: "Summary of ingredients generated by AI", summary_benefits_title: "Benefits", summary_disadvantages_title: "Disadvantages", @@ -128,6 +130,8 @@ const customTranslations: Record> = { ingredients_desc_additive: "Cliquez sur chaque additif pour voir les descriptions détaillées générées par l'IA", ingredients_no_additive: "Le produit ne contient pas d'additifs", + allergen_warning_title: "Avertissement Allergène", + allergen_warning_message: "Ce produit contient des allergènes auxquels vous êtes sensible :", summary_title: "Résumé des ingrédients généré par IA", summary_benefits_title: "Avantages", summary_disadvantages_title: "Inconvénients", @@ -220,6 +224,8 @@ const customTranslations: Record> = { ingredients_no_additive: "Il prodotto non contiene additivi", ingredients_desc_additive: "Fai clic su ogni additivo per visualizzare le descrizioni dettagliate generate dall’AI", + allergen_warning_title: "Avviso Allergeni", + allergen_warning_message: "Questo prodotto contiene allergeni a cui sei sensibile:", summary_title: "Riepilogo degli ingredienti generato dall’AI", summary_benefits_title: "Benefici", summary_disadvantages_title: "Svantaggi", @@ -313,6 +319,8 @@ const customTranslations: Record> = { ingredients_no_additive: "El producto no contiene aditivos", ingredients_desc_additive: "Haz clic en cada aditivo para ver descripciones detalladas generadas por IA", + allergen_warning_title: "Advertencia de Alérgenos", + allergen_warning_message: "Este producto contiene alérgenos a los que eres sensible:", summary_title: "Resumen de ingredientes generados por IA", summary_benefits_title: "Beneficios", summary_disadvantages_title: "Desventajas", @@ -398,6 +406,8 @@ arabic:{ "ingredients_desc_ingredient": "انقر على كل مكون لعرض الوصف التفصيلي الناتج عن الذكاء الاصطناعي", "ingredients_desc_additive": "انقر على كل إضافة لعرض الوصف التفصيلي الناتج عن الذكاء الاصطناعي", "ingredients_no_additive": "المنتج لا يحتوي على إضافات", + "allergen_warning_title": "تحذير من مسببات الحساسية", + "allergen_warning_message": "يحتوي هذا المنتج على مسببات حساسية تؤثر عليك:", "summary_title": "ملخص المكونات الناتجة عن الذكاء الاصطناعي", "summary_benefits_title": "الفوائد", "summary_disadvantages_title": "العيوب", diff --git a/resources/ui/src/pages/components/barcode_ingredients.tsx b/resources/ui/src/pages/components/barcode_ingredients.tsx index e9f1038..ac69854 100644 --- a/resources/ui/src/pages/components/barcode_ingredients.tsx +++ b/resources/ui/src/pages/components/barcode_ingredients.tsx @@ -39,9 +39,7 @@ const BarcodeIngredients: React.FC = ({ const [ingredientsError, setIngredientsError] = useState(""); const fetchData = async () => { - console.log( - `call backend with scannedCode: ${productCode} and language: ${language}` - ); + setApiResponse(null); setLoading(true); @@ -53,13 +51,11 @@ const BarcodeIngredients: React.FC = ({ ); if (!response.error) { - console.log("response=" + JSON.stringify(response)); const keyValueArray = Object.entries(response.ingredients_description); const newIngredients = keyValueArray.map(([key, value]) => ({ label: key, description: value, })); - console.log(newIngredients); setIngredients(newIngredients); diff --git a/resources/ui/src/pages/components/barcode_product_summary.tsx b/resources/ui/src/pages/components/barcode_product_summary.tsx index b2f013c..f1e520a 100644 --- a/resources/ui/src/pages/components/barcode_product_summary.tsx +++ b/resources/ui/src/pages/components/barcode_product_summary.tsx @@ -142,12 +142,14 @@ const BarcodeProductSummary: React.FC = ({ return (
{loadingSummary && ( -
+
- Loading Summary of Ingredients... +
+ {currentTranslations["summary_title"].replace("Summary of ingredients generated by AI", "Loading AI Analysis")}... +
- )}{" "} + )} {summaryError ? ( {summaryError} @@ -156,42 +158,64 @@ const BarcodeProductSummary: React.FC = ({ <> {recommendation && (
- - - - + + {/* AI Summary Card */} +
+
+ +

{currentTranslations["summary_title"]} - - } - - > - - - - {currentTranslations['image_title']} +

+
+
+ +
+
+ + {/* AI Generated Image Card */} + {(image || loadingImage) && ( +
+
+
+ 🎨 +

+ {currentTranslations['image_title']} +

- ), - height: "100%", - }} - > - {currentTranslations['image_title']} - - - +
+
+ {currentTranslations['image_title']} +
+
+ )}
)} From 4751d501ebe6fb2ea4679cc0edb2cc587f184094 Mon Sep 17 00:00:00 2001 From: Jeremy Labrado Date: Mon, 8 Dec 2025 09:07:23 +0100 Subject: [PATCH 2/2] feat: modernize barcode scanning UI/UX with tabs, nutritional cards, and allergen detection - Add tab-based navigation (AI Summary, Ingredients, Additives) with translations in 5 languages - Display compact nutritional info cards (calories, salt, sugar, protein) in horizontal row for mobile - Implement visual allergen flagging with red gradient borders and warning icons - Add multi-language allergen keyword detection (English, French, Spanish, Italian, Arabic) - Enhance empty state with phone icon, clear instructions, and numbered step badges - Add preference check with warning alert before scanning - Improve loading states with split feedback (scan confirmation + spinner) - Add prominent allergen warning banner with translated messages - Replace side-by-side layout with mobile-friendly tabs - Add search icon to scan button --- resources/ui/src/assets/i18n/all.ts | 15 + resources/ui/src/pages/components/barcode.tsx | 131 ++++++-- .../pages/components/barcode_ingredients.tsx | 300 ++++++++++++------ 3 files changed, 337 insertions(+), 109 deletions(-) diff --git a/resources/ui/src/assets/i18n/all.ts b/resources/ui/src/assets/i18n/all.ts index fc9e64d..9d9c2d8 100644 --- a/resources/ui/src/assets/i18n/all.ts +++ b/resources/ui/src/assets/i18n/all.ts @@ -38,6 +38,9 @@ const customTranslations: Record> = { ingredients_desc_additive: "Click on each additive to view AI-generated detailed descriptions", ingredients_no_additive: "The product does not have additives", + tab_ai_summary: "AI Summary", + tab_ingredients: "Ingredients", + tab_additives: "Additives", allergen_warning_title: "Allergen Warning", allergen_warning_message: "This product contains allergens you're sensitive to:", summary_title: "Summary of ingredients generated by AI", @@ -130,6 +133,9 @@ const customTranslations: Record> = { ingredients_desc_additive: "Cliquez sur chaque additif pour voir les descriptions détaillées générées par l'IA", ingredients_no_additive: "Le produit ne contient pas d'additifs", + tab_ai_summary: "Résumé IA", + tab_ingredients: "Ingrédients", + tab_additives: "Additifs", allergen_warning_title: "Avertissement Allergène", allergen_warning_message: "Ce produit contient des allergènes auxquels vous êtes sensible :", summary_title: "Résumé des ingrédients généré par IA", @@ -222,6 +228,9 @@ const customTranslations: Record> = { ingredients_desc_ingredient: "Fai clic su ogni ingrediente per visualizzare le descrizioni dettagliate generate dall’AI", ingredients_no_additive: "Il prodotto non contiene additivi", + tab_ai_summary: "Riepilogo IA", + tab_ingredients: "Ingredienti", + tab_additives: "Additivi", ingredients_desc_additive: "Fai clic su ogni additivo per visualizzare le descrizioni dettagliate generate dall’AI", allergen_warning_title: "Avviso Allergeni", @@ -317,6 +326,9 @@ const customTranslations: Record> = { ingredients_desc_ingredient: "Haz clic en cada ingrediente para ver descripciones detalladas generadas por IA", ingredients_no_additive: "El producto no contiene aditivos", + tab_ai_summary: "Resumen IA", + tab_ingredients: "Ingredientes", + tab_additives: "Aditivos", ingredients_desc_additive: "Haz clic en cada aditivo para ver descripciones detalladas generadas por IA", allergen_warning_title: "Advertencia de Alérgenos", @@ -406,6 +418,9 @@ arabic:{ "ingredients_desc_ingredient": "انقر على كل مكون لعرض الوصف التفصيلي الناتج عن الذكاء الاصطناعي", "ingredients_desc_additive": "انقر على كل إضافة لعرض الوصف التفصيلي الناتج عن الذكاء الاصطناعي", "ingredients_no_additive": "المنتج لا يحتوي على إضافات", + "tab_ai_summary": "ملخص الذكاء الاصطناعي", + "tab_ingredients": "المكونات", + "tab_additives": "الإضافات", "allergen_warning_title": "تحذير من مسببات الحساسية", "allergen_warning_message": "يحتوي هذا المنتج على مسببات حساسية تؤثر عليك:", "summary_title": "ملخص المكونات الناتجة عن الذكاء الاصطناعي", diff --git a/resources/ui/src/pages/components/barcode.tsx b/resources/ui/src/pages/components/barcode.tsx index 576d81b..98812a3 100644 --- a/resources/ui/src/pages/components/barcode.tsx +++ b/resources/ui/src/pages/components/barcode.tsx @@ -4,6 +4,7 @@ import Button from "@cloudscape-design/components/button"; import Ingredients from "./barcode_ingredients"; import Badge from "@cloudscape-design/components/badge"; import Link from "@cloudscape-design/components/link"; +import Alert from "@cloudscape-design/components/alert"; import { Box, Container, @@ -43,10 +44,17 @@ const Barcode: React.FC = () => { const [productCode, setProductCode] = useState(""); const [showScanner, setShowScanner] = useState(false); const [tempProductCode, setTempProductCode] = useState(""); + const [hasPreferences, setHasPreferences] = useState(false); const currentTranslations = customTranslations[language]; // Get translations for the current language or fallback to English let html5QrcodeScanner: any; + // Check if user has set preferences + useEffect(() => { + const stored = localStorage.getItem("userPreferences"); + setHasPreferences(!!stored); + }, []); + function onScanFailure(error: unknown) { console.warn(`Code scan error = ${error}`); } @@ -122,7 +130,11 @@ const Barcode: React.FC = () => { >
{!showScanner && ( - )} @@ -153,27 +165,106 @@ const Barcode: React.FC = () => {
{!showScanner && ( - -
-

{currentTranslations["scan_main_title"]}

- - -
-

- 1{" "} - {currentTranslations["scan_label_1"]}{" "} - - {currentTranslations["scan_label_2"]} - -

-

- 2{" "} - {currentTranslations["scan_label_3"]} -

+
+ {!hasPreferences && ( + + To get personalized nutritional information, please{" "} + set your preferences before scanning. + + )} + +
+
+ 📱 +
+

+ {currentTranslations["scan_main_title"]} +

+

+ Point your camera at a product barcode +

+
+ +
+
+
+ 1 +
+ + {currentTranslations["scan_label_1"]}{" "} + + {currentTranslations["scan_label_2"]} + + +
+ +
+
+ 2
- + + {currentTranslations["scan_label_3"]} + +
- +
)}
diff --git a/resources/ui/src/pages/components/barcode_ingredients.tsx b/resources/ui/src/pages/components/barcode_ingredients.tsx index ac69854..72854f0 100644 --- a/resources/ui/src/pages/components/barcode_ingredients.tsx +++ b/resources/ui/src/pages/components/barcode_ingredients.tsx @@ -6,7 +6,7 @@ import Button from "@cloudscape-design/components/button"; import TextContent from "@cloudscape-design/components/text-content"; import Spinner from "@cloudscape-design/components/spinner"; import Alert from "@cloudscape-design/components/alert"; -import { ColumnLayout, Container } from "@cloudscape-design/components"; +import { Container, Tabs, Box, ColumnLayout } from "@cloudscape-design/components"; import Header from "@cloudscape-design/components/header"; import { SpaceBetween } from "@cloudscape-design/components"; import { callAPI } from "../../assets/js/custom"; @@ -37,6 +37,43 @@ const BarcodeIngredients: React.FC = ({ const [loading, setLoading] = useState(true); // Added loading state const [productName, setProductName] = useState(true); // Added loading state const [ingredientsError, setIngredientsError] = useState(""); + const [nutriments, setNutriments] = useState(null); + const [allergensTags, setAllergensTags] = useState([]); + + // Check if ingredient matches user allergens + const isAllergen = (ingredientLabel: string): boolean => { + const stored = localStorage.getItem("userPreferences"); + if (!stored) return false; + + try { + const prefs = JSON.parse(stored); + const userAllergies = prefs.allergies || []; + + // Check if ingredient label contains any user allergen + const lowerLabel = ingredientLabel.toLowerCase(); + + // Common allergen keywords in multiple languages + const allergenKeywords: Record = { + milk: ["milk", "lait", "leche", "latte"], + eggs: ["egg", "oeuf", "huevo", "uovo"], + peanuts: ["peanut", "arachide", "cacahuete", "arachidi"], + tree_nuts: ["nut", "noix", "nuez", "noci", "almond", "amande", "cashew", "cajou"], + soy: ["soy", "soja", "soia"], + wheat: ["wheat", "blé", "trigo", "grano"], + fish: ["fish", "poisson", "pescado", "pesce"], + shellfish: ["shellfish", "crustacé", "marisco", "crostacei", "shrimp", "crevette"], + sesame: ["sesame", "sésame", "sésamo", "sesamo"] + }; + + return userAllergies.some((allergy: any) => { + const allergyValue = allergy.value.toLowerCase(); + const keywords = allergenKeywords[allergyValue] || [allergyValue]; + return keywords.some(keyword => lowerLabel.includes(keyword)); + }); + } catch { + return false; + } + }; const fetchData = async () => { @@ -60,6 +97,8 @@ const BarcodeIngredients: React.FC = ({ setIngredients(newIngredients); setProductName(response.product_name); + setNutriments(response.nutriments || null); + setAllergensTags(response.allergens_tags || []); const myAdditives:Additive [] = []; for (const key in response.additives_description) { @@ -98,11 +137,19 @@ const BarcodeIngredients: React.FC = ({ {loading && (
- + - {currentTranslations["scan_scanned_label"]}:{" "} - {productCode} | - {currentTranslations["scan_scanning_label"]}... +
+ + {currentTranslations["scan_scanned_label"]}:{" "} + {productCode} +
+
+ +
+ + {currentTranslations["scan_scanning_label"]}... +
@@ -118,94 +165,169 @@ const BarcodeIngredients: React.FC = ({ {apiResponse && (
- -
- - - {currentTranslations["scan_scanned_label"]}:{" "} - {productCode} |{" "} - {currentTranslations["product_name_label"]}:{" "} - {productName} - - -
- - ({ - id: `${item.id}`, - content: ( - - - - ), - }))} - /> - } - header={ -
- {currentTranslations["ingredients_title1"]} -
- } - > -

- {" "} - {currentTranslations["ingredients_desc_ingredient"]} + {/* Product Header Card */} + + +

+

+ {productName} +

+

+ {currentTranslations["scan_scanned_label"]}: {productCode}

- +
- {additives && ( - 0 ? ( - ({ - id: `${item.id}`, - content: ( - - - - ), - }))} - /> - ) : null - } - header={ -
- {currentTranslations["ingredients_title2"]} -
- } - > - {additives.length > 0 ? ( -

- {currentTranslations["ingredients_desc_additive"]} -

- ) : ( -

The product does not have additives

- )} - -
+ {/* Nutritional Info Cards */} + {nutriments && ( +
+
+
🔥
+
+ {nutriments["energy-kcal_100g"] || "N/A"} +
+
kcal
+
+
+
🧂
+
+ {nutriments["salt_100g"] ? `${nutriments["salt_100g"]}g` : "N/A"} +
+
Salt
+
+
+
🍬
+
+ {nutriments["sugars_100g"] ? `${nutriments["sugars_100g"]}g` : "N/A"} +
+
Sugar
+
+
+
💪
+
+ {nutriments["proteins_100g"] ? `${nutriments["proteins_100g"]}g` : "N/A"} +
+
Protein
+
+
+ )} + + {/* Allergen Warning */} + {allergensTags && allergensTags.length > 0 && ( + + ⚠️ {currentTranslations["allergen_warning_title"]} +
+ {currentTranslations["allergen_warning_message"]} {allergensTags.map(tag => tag.replace("en:", "")).join(", ")} +
)} -
-
+
+ - + {/* Tabs for Ingredients, Additives, and AI Summary */} + + ), + }, + { + label: currentTranslations["tab_ingredients"], + id: "ingredients", + content: ( + + +

+ {currentTranslations["ingredients_desc_ingredient"]} +

+ { + const isAllergenItem = isAllergen(item.label); + return { + id: `${item.id}`, + content: ( + +
+ +
+
+ ), + }; + })} + /> +
+
+ ), + }, + { + label: currentTranslations["tab_additives"], + id: "additives", + content: ( + + + {additives.length > 0 ? ( + <> +

+ {currentTranslations["ingredients_desc_additive"]} +

+ ({ + id: `${item.id}`, + content: ( + + + + ), + }))} + /> + + ) : ( +

The product does not have additives

+ )} +
+
+ ), + }, + ]} + />
)}