Fix deck gen truncation: increase max_tokens to 16384, add JSON repair

Root cause: Perplexity deck generation hit the 8192 max_tokens limit,
truncating the JSON response mid-string at card ~70-80. json.loads()
fails with 'Unterminated string' and the fallback also couldn't recover.

Fixes:
- Bump DECK_GEN_MAX_TOKENS from 8192 to 16384 (primary fix)
- Add _repair_truncated_json() to PerplexityClient — if token limit is
  still hit, salvages all complete card objects from the truncated JSON
  instead of returning a 422 error
- Add OUTPUT EFFICIENCY instructions to system prompt to reduce per-card
  verbosity (shorter reasons, fewer synergy_with entries)
- Add 'truncated' flag to response so UI can warn if deck is incomplete
- Log warning when recovered deck has <90 cards
This commit is contained in:
KoalaTrapLord committed 2026-03-12 14:47:41 +00:00
1 parent e571f06894
commit 44bc86b665
5 files changed
+117 -20

No files matched your search

+86 -1
View File
@@ -268,7 +268,92 @@ class PerplexityClient:
return json.loads(text[start:i+1])
except (json.JSONDecodeError, TypeError):
return None
return None
# If we get here, JSON was truncated (depth > 0). Try to repair.
return PerplexityClient._repair_truncated_json(text[start:])
@staticmethod
def _repair_truncated_json(text: str) -> Optional[dict]:
"""
Attempt to repair truncated JSON from max_tokens cutoff.
Strategy: find the last complete array element in "cards",
then close all open brackets/braces.
"""
logger.info("Attempting truncated JSON repair (%d chars)...", len(text))
# Find the last complete card object (ends with }) in the cards array
# Walk backwards to find the last closing brace that ends a valid card
last_good = -1
depth = 0
in_string = False
escape_next = False
for i in range(len(text)):
ch = text[i]
if escape_next:
escape_next = False
continue
if ch == '\\' and in_string:
escape_next = True
continue
if ch == '"':
in_string = not in_string
continue
if in_string:
continue
if ch == '{':
depth += 1
elif ch == '}':
depth -= 1
if depth >= 1:
# This closes a nested object (like a card) — mark as potential cutoff
last_good = i
if last_good == -1:
return None
# Take text up to the last complete nested object
truncated = text[:last_good + 1]
# Now figure out what we need to close.
# Re-scan to get the closing sequence.
close_depth = 0
in_arr = 0
in_str = False
esc = False
for ch in truncated:
if esc:
esc = False
continue
if ch == '\\' and in_str:
esc = True
continue
if ch == '"':
in_str = not in_str
continue
if in_str:
continue
if ch == '{':
close_depth += 1
elif ch == '}':
close_depth -= 1
elif ch == '[':
in_arr += 1
elif ch == ']':
in_arr -= 1
# Build closing sequence
suffix = ']' * in_arr + '}' * close_depth
repaired = truncated + suffix
try:
result = json.loads(repaired)
card_count = len(result.get('cards', []))
logger.info("JSON repair succeeded: recovered %d cards", card_count)
return result
except (json.JSONDecodeError, TypeError) as e:
logger.warning("JSON repair failed: %s", e)
return None
def check_status(self) -> dict:
"""Quick health check — try a minimal API call."""
+1 -1
View File
@@ -45,7 +45,7 @@ DECK_GEN_PROVIDER = os.environ.get("DECK_GEN_PROVIDER", "perplexity")
# Model for deck generation (sonar = fast/$0.004, sonar-pro = deep/$0.04)
DECK_GEN_MODEL = os.environ.get("DECK_GEN_MODEL", "sonar")
DECK_GEN_TEMPERATURE = float(os.environ.get("DECK_GEN_TEMPERATURE", "0.2"))
DECK_GEN_MAX_TOKENS = int(os.environ.get("DECK_GEN_MAX_TOKENS", "8192"))
DECK_GEN_MAX_TOKENS = int(os.environ.get("DECK_GEN_MAX_TOKENS", "16384"))
# ── Smart Substitution Settings ───────────────────────────────
# Minimum embedding similarity to accept a substitute without Perplexity fallback
+7 -1
View File
@@ -31,4 +31,10 @@ IMPORTANT:
- Provide realistic USD price estimates
- The commander MUST be included in the cards list with its real category (Creature, Planeswalker, etc.)
- Assign the correct bracket level based on the cards chosen and combos present
- List Game Changer cards explicitly in the bracket section"""
- List Game Changer cards explicitly in the bracket section
OUTPUT EFFICIENCY (critical):
- Keep each card's "reason" under 15 words — brief is better
- Keep "synergy_with" to at most 2-3 card names per card
- Do not repeat the card's own name in synergy_with
- Omit estimated_price_usd if you are unsure — 0 is fine"""
+7 -3
View File
@@ -243,9 +243,12 @@ class DeckGeneratorV3:
)
raw_deck = response.parsed_json
logger.info("Deck generated: %d cards, bracket %d",
len(raw_deck.get("cards", [])),
raw_deck.get("bracket", {}).get("level", 0))
card_count = len(raw_deck.get("cards", []))
truncated = card_count < 90 # Commander decks should have ~100 cards
logger.info("Deck generated: %d cards, bracket %d%s",
card_count,
raw_deck.get("bracket", {}).get("level", 0),
" (TRUNCATED — response may have hit token limit)" if truncated else "")
# Step 5: Check ownership and build enriched card list
cards_with_status = self._check_ownership(raw_deck.get("cards", []))
@@ -270,6 +273,7 @@ class DeckGeneratorV3:
},
"model": response.model,
"citations": response.citations,
"truncated": truncated,
}
# ── Step 5: Ownership Check ──────────────────────────────
+16 -14
View File
@@ -56,12 +56,13 @@ Install-B64 -R 'coach\__init__.py' -B $b
$b = 'IyBDb2FjaCBjbGllbnRzIOKAlCBQZXJwbGV4aXR5LCBMTSBTdHVkaW8K'
Install-B64 -R 'coach\clients\__init__.py' -B $b
# coach/clients/perplexity_client.py (9,727 bytes)
# coach/clients/perplexity_client.py (12,494 bytes)
$b = 'IiIiCkNvbW1hbmRlciBBSSBMYWIg4oCUIFBlcnBsZXhpdHkgU29uYXIgU3RydWN0dXJlZCBPdXRwdXQgQ2xpZW50CuKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkApVc2VzIHRoZSBvcGVuYWkgU0RLIHRvIGNhbGwgUGVycGxleGl0eSdzIGNoYXQvY29tcGxldGlvbnMgZW5kcG9pbnQKd2l0aCByZXNwb25zZV9mb3JtYXQ6IGpzb25fc2NoZW1hIGZvciBndWFyYW50ZWVkIHN0cnVjdHVyZWQgb3V0cHV0LgoKU3VwcG9ydHMgYm90aCBzb25hciAoZmFzdCwgY2hlYXApIGFuZCBzb25hci1wcm8gKGRlZXAsIHRob3JvdWdoKS4KIiIiCgppbXBvcnQganNvbgppbXBvcnQgbG9nZ2luZwppbXBvcnQgYXN5bmNpbwpmcm9tIHR5cGluZyBpbXBvcnQgT3B0aW9uYWwKCmZyb20gb3BlbmFpIGltcG9ydCBPcGVuQUkKCmxvZ2dlciA9IGxvZ2dpbmcuZ2V0TG9nZ2VyKCJjb2FjaC5wcGx4IikKCiMg4pSA4pSAIFBlcnBsZXhpdHkgTW9kZWxzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgApTT05BUiA9ICJzb25hciIKU09OQVJfUFJPID0gInNvbmFyLXBybyIKU09OQVJfREVFUF9SRVNFQVJDSCA9ICJzb25hci1kZWVwLXJlc2VhcmNoIgoKCmNsYXNzIFBlcnBsZXhpdHlSZXNwb25zZToKICAgICIiIlBhcnNlZCByZXNwb25zZSBjb250YWluZXIgZnJvbSBQZXJwbGV4aXR5IEFQSS4iIiIKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBjb250ZW50OiBzdHIsIHBhcnNlZF9qc29uOiBPcHRpb25hbFtkaWN0XSwKICAgICAgICAgICAgICAgICBwcm9tcHRfdG9rZW5zOiBpbnQsIGNvbXBsZXRpb25fdG9rZW5zOiBpbnQsCiAgICAgICAgICAgICAgICAgbW9kZWw6IHN0ciwgY2l0YXRpb25zOiBsaXN0W3N0cl0gPSBOb25lKToKICAgICAgICBzZWxmLmNvbnRlbnQgPSBjb250ZW50CiAgICAgICAgc2VsZi5wYXJzZWRfanNvbiA9IHBhcnNlZF9qc29uCiAgICAgICAgc2VsZi5wcm9tcHRfdG9rZW5zID0gcHJvbXB0X3Rva2VucwogICAgICAgIHNlbGYuY29tcGxldGlvbl90b2tlbnMgPSBjb21wbGV0aW9uX3Rva2VucwogICAgICAgIHNlbGYubW9kZWwgPSBtb2RlbAogICAgICAgIHNlbGYuY2l0YXRpb25zID0gY2l0YXRpb25zIG9yIFtdCgogICAgQHByb3BlcnR5CiAgICBkZWYgb2soc2VsZikgLT4gYm9vbDoKICAgICAgICByZXR1cm4gc2VsZi5wYXJzZWRfanNvbiBpcyBub3QgTm9uZQoKCmNsYXNzIFBlcnBsZXhpdHlDbGllbnQ6CiAgICAiIiIKICAgIFBlcnBsZXhpdHkgU29uYXIgQVBJIGNsaWVudCB1c2luZyB0aGUgb3BlbmFpIFNESy4KCiAgICBVc2FnZToKICAgICAgICBjbGllbnQgPSBQZXJwbGV4aXR5Q2xpZW50KGFwaV9rZXk9InBwbHgtLi4uIikKICAgICAgICByZXNwID0gY2xpZW50LmNoYXRfc3RydWN0dXJlZCgKICAgICAgICAgICAgc3lzdGVtX3Byb21wdD0iWW91IGFyZSBhIGRlY2sgYnVpbGRlci4iLAogICAgICAgICAgICB1c2VyX3Byb21wdD0iQnVpbGQgYSBkZWNrIGZvci4uLiIsCiAgICAgICAgICAgIGpzb25fc2NoZW1hPWRlY2tfc2NoZW1hLAogICAgICAgICAgICBzY2hlbWFfbmFtZT0iRGVja0xpc3QiLAogICAgICAgICkKICAgICAgICBpZiByZXNwLm9rOgogICAgICAgICAgICBkZWNrID0gcmVzcC5wYXJzZWRfanNvbgogICAgIiIiCgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGFwaV9rZXk6IHN0ciwgbW9kZWw6IHN0ciA9IFNPTkFSLAogICAgICAgICAgICAgICAgIHRpbWVvdXQ6IGludCA9IDEyMCk6CiAgICAgICAgaWYgbm90IGFwaV9rZXk6CiAgICAgICAgICAgIHJhaXNlIFZhbHVlRXJyb3IoIlBlcnBsZXhpdHkgQVBJIGtleSBpcyByZXF1aXJlZCIpCiAgICAgICAgc2VsZi5hcGlfa2V5ID0gYXBpX2tleQogICAgICAgIHNlbGYubW9kZWwgPSBtb2RlbAogICAgICAgIHNlbGYudGltZW91dCA9IHRpbWVvdXQKICAgICAgICBzZWxmLl9jbGllbnQgPSBPcGVuQUkoCiAgICAgICAgICAgIGFwaV9rZXk9YXBpX2tleSwKICAgICAgICAgICAgYmFzZV91cmw9Imh0dHBzOi8vYXBpLnBlcnBsZXhpdHkuYWkiLAogICAgICAg' +
'ICAgICB0aW1lb3V0PXRpbWVvdXQsCiAgICAgICAgKQoKICAgIGRlZiBjaGF0X3N0cnVjdHVyZWQoCiAgICAgICAgc2VsZiwKICAgICAgICBzeXN0ZW1fcHJvbXB0OiBzdHIsCiAgICAgICAgdXNlcl9wcm9tcHQ6IHN0ciwKICAgICAgICBqc29uX3NjaGVtYTogZGljdCwKICAgICAgICBzY2hlbWFfbmFtZTogc3RyID0gInJlc3BvbnNlIiwKICAgICAgICBtb2RlbDogc3RyID0gTm9uZSwKICAgICAgICB0ZW1wZXJhdHVyZTogZmxvYXQgPSAwLjIsCiAgICAgICAgbWF4X3Rva2VuczogaW50ID0gODE5MiwKICAgICkgLT4gUGVycGxleGl0eVJlc3BvbnNlOgogICAgICAgICIiIgogICAgICAgIFNlbmQgYSBjaGF0IHJlcXVlc3Qgd2l0aCBzdHJ1Y3R1cmVkIEpTT04gb3V0cHV0LgoKICAgICAgICBBcmdzOgogICAgICAgICAgICBzeXN0ZW1fcHJvbXB0OiBTeXN0ZW0gbWVzc2FnZQogICAgICAgICAgICB1c2VyX3Byb21wdDogVXNlciBtZXNzYWdlCiAgICAgICAgICAgIGpzb25fc2NoZW1hOiBKU09OIFNjaGVtYSBkaWN0IGZvciByZXNwb25zZV9mb3JtYXQKICAgICAgICAgICAgc2NoZW1hX25hbWU6IE5hbWUgZm9yIHRoZSBzY2hlbWEgKHVzZWQgaW4gcmVzcG9uc2VfZm9ybWF0KQogICAgICAgICAgICBtb2RlbDogT3ZlcnJpZGUgbW9kZWwgKHNvbmFyLCBzb25hci1wcm8pCiAgICAgICAgICAgIHRlbXBlcmF0dXJlOiBTYW1wbGluZyB0ZW1wZXJhdHVyZSAoMC4w4oCTMS4wKQogICAgICAgICAgICBtYXhfdG9rZW5zOiBNYXggb3V0cHV0IHRva2VucwoKICAgICAgICBSZXR1cm5zOgogICAgICAgICAgICBQZXJwbGV4aXR5UmVzcG9uc2Ugd2l0aCBwYXJzZWRfanNvbiBndWFyYW50ZWVkIGJ5IHNjaGVtYQogICAgICAgICIiIgogICAgICAgIHVzZV9tb2RlbCA9IG1vZGVsIG9yIHNlbGYubW9kZWwKCiAgICAgICAgbWVzc2FnZXMgPSBbCiAgICAgICAgICAgIHsicm9sZSI6ICJzeXN0ZW0iLCAiY29udGVudCI6IHN5c3RlbV9wcm9tcHR9LAogICAgICAgICAgICB7InJvbGUiOiAidXNlciIsICJjb250ZW50IjogdXNlcl9wcm9tcHR9LAogICAgICAgIF0KCiAgICAgICAgdHJ5OgogICAgICAgICAgICByZXNwb25zZSA9IHNlbGYuX2NsaWVudC5jaGF0LmNvbXBsZXRpb25zLmNyZWF0ZSgKICAgICAgICAgICAgICAgIG1vZGVsPXVzZV9tb2RlbCwKICAgICAgICAgICAgICAgIG1lc3NhZ2VzPW1lc3NhZ2VzLAogICAgICAgICAgICAgICAgdGVtcGVyYXR1cmU9dGVtcGVyYXR1cmUsCiAgICAgICAgICAgICAgICBtYXhfdG9rZW5zPW1heF90b2tlbnMsCiAgICAgICAgICAgICAgICByZXNwb25zZV9mb3JtYXQ9ewogICAgICAgICAgICAgICAgICAgICJ0eXBlIjogImpzb25fc2NoZW1hIiwKICAgICAgICAgICAgICAgICAgICAianNvbl9zY2hlbWEiOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICJuYW1lIjogc2NoZW1hX25hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICJzY2hlbWEiOiBqc29uX3NjaGVtYSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgKQoKICAgICAgICAgICAgY2hvaWNlID0gcmVzcG9uc2UuY2hvaWNlc1swXQogICAgICAgICAgICBjb250ZW50ID0gY2hvaWNlLm1lc3NhZ2UuY29udGVudCBvciAiIgogICAgICAgICAgICB1c2FnZSA9IHJlc3BvbnNlLnVzYWdlCgogICAgICAgICAgICAjIFBhcnNlIHRoZSBzdHJ1Y3R1cmVkIEpTT04KICAgICAgICAgICAgcGFyc2VkID0gTm9uZQogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBwYXJzZWQgPSBqc29uLmxvYWRzKGNvbnRlbnQpCiAgICAgICAgICAgIGV4Y2VwdCAoanNvbi5KU09ORGVjb2RlRXJyb3IsIFR5cGVFcnJvcikgYXMgZToKICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuaW5nKCJGYWlsZWQgdG8gcGFyc2Ugc3RydWN0dXJlZCByZXNwb25zZTogJXMiLCBlKQogICAgICAgICAgICAgICAgIyBGYWxsYmFjazogdHJ5IGV4dHJhY3RpbmcgSlNPTiBvYmplY3QKICAgICAgICAgICAgICAgIHBhcnNlZCA9IHNlbGYuX2V4dHJhY3RfanNvbihjb250ZW50KQoKICAgICAgICAgICAgIyBFeHRyYWN0IGNpdGF0aW9ucyBpZiBhdmFpbGFibGUKICAgICAgICAgICAgY2l0YXRpb25zID0gW10KICAgICAgICAgICAgaWYgaGFzYXR0cihyZXNwb25zZSwgJ2NpdGF0aW9ucycpIGFuZCByZXNwb25zZS5jaXRhdGlvbnM6CiAgICAgICAgICAgICAgICBjaXRhdGlvbnMgPSByZXNwb25zZS5jaXRhdGlvbnMKCiAgICAgICAgICAgIGxvZ2dlci5pbmZvKAog' +
'ICAgICAgICAgICAgICAgIltwcGx4XSBtb2RlbD0lcyB0b2tlbnM9KCVkIHByb21wdCwgJWQgY29tcGxldGlvbikgcGFyc2VkPSVzIiwKICAgICAgICAgICAgICAgIHVzZV9tb2RlbCwKICAgICAgICAgICAgICAgIHVzYWdlLnByb21wdF90b2tlbnMgaWYgdXNhZ2UgZWxzZSAwLAogICAgICAgICAgICAgICAgdXNhZ2UuY29tcGxldGlvbl90b2tlbnMgaWYgdXNhZ2UgZWxzZSAwLAogICAgICAgICAgICAgICAgInllcyIgaWYgcGFyc2VkIGVsc2UgIm5vIiwKICAgICAgICAgICAgKQoKICAgICAgICAgICAgcmV0dXJuIFBlcnBsZXhpdHlSZXNwb25zZSgKICAgICAgICAgICAgICAgIGNvbnRlbnQ9Y29udGVudCwKICAgICAgICAgICAgICAgIHBhcnNlZF9qc29uPXBhcnNlZCwKICAgICAgICAgICAgICAgIHByb21wdF90b2tlbnM9dXNhZ2UucHJvbXB0X3Rva2VucyBpZiB1c2FnZSBlbHNlIDAsCiAgICAgICAgICAgICAgICBjb21wbGV0aW9uX3Rva2Vucz11c2FnZS5jb21wbGV0aW9uX3Rva2VucyBpZiB1c2FnZSBlbHNlIDAsCiAgICAgICAgICAgICAgICBtb2RlbD11c2VfbW9kZWwsCiAgICAgICAgICAgICAgICBjaXRhdGlvbnM9Y2l0YXRpb25zLAogICAgICAgICAgICApCgogICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCJbcHBseF0gQVBJIGNhbGwgZmFpbGVkOiAlcyIsIGUpCiAgICAgICAgICAgIHJhaXNlCgogICAgZGVmIGNoYXRfcGxhaW4oCiAgICAgICAgc2VsZiwKICAgICAgICBzeXN0ZW1fcHJvbXB0OiBzdHIsCiAgICAgICAgdXNlcl9wcm9tcHQ6IHN0ciwKICAgICAgICBtb2RlbDogc3RyID0gTm9uZSwKICAgICAgICB0ZW1wZXJhdHVyZTogZmxvYXQgPSAwLjIsCiAgICAgICAgbWF4X3Rva2VuczogaW50ID0gNDA5NiwKICAgICkgLT4gUGVycGxleGl0eVJlc3BvbnNlOgogICAgICAgICIiIgogICAgICAgIFNlbmQgYSBwbGFpbiBjaGF0IHJlcXVlc3Qgd2l0aG91dCBzdHJ1Y3R1cmVkIG91dHB1dC4KICAgICAgICBVc2VkIGZvciBzdWJzdGl0dXRpb24gZmFsbGJhY2sgcXVlcmllcyB3aGVyZSBzY2hlbWEKICAgICAgICBjb21wbGlhbmNlIGlzIGxlc3MgY3JpdGljYWwuCiAgICAgICAgIiIiCiAgICAgICAgdXNlX21vZGVsID0gbW9kZWwgb3Igc2VsZi5tb2RlbAoKICAgICAgICBtZXNzYWdlcyA9IFsKICAgICAgICAgICAgeyJyb2xlIjogInN5c3RlbSIsICJjb250ZW50Ijogc3lzdGVtX3Byb21wdH0sCiAgICAgICAgICAgIHsicm9sZSI6ICJ1c2VyIiwgImNvbnRlbnQiOiB1c2VyX3Byb21wdH0sCiAgICAgICAgXQoKICAgICAgICB0cnk6CiAgICAgICAgICAgIHJlc3BvbnNlID0gc2VsZi5fY2xpZW50LmNoYXQuY29tcGxldGlvbnMuY3JlYXRlKAogICAgICAgICAgICAgICAgbW9kZWw9dXNlX21vZGVsLAogICAgICAgICAgICAgICAgbWVzc2FnZXM9bWVzc2FnZXMsCiAgICAgICAgICAgICAgICB0ZW1wZXJhdHVyZT10ZW1wZXJhdHVyZSwKICAgICAgICAgICAgICAgIG1heF90b2tlbnM9bWF4X3Rva2VucywKICAgICAgICAgICAgKQoKICAgICAgICAgICAgY2hvaWNlID0gcmVzcG9uc2UuY2hvaWNlc1swXQogICAgICAgICAgICBjb250ZW50ID0gY2hvaWNlLm1lc3NhZ2UuY29udGVudCBvciAiIgogICAgICAgICAgICB1c2FnZSA9IHJlc3BvbnNlLnVzYWdlCgogICAgICAgICAgICAjIFRyeSB0byBwYXJzZSBhcyBKU09OIGFueXdheQogICAgICAgICAgICBwYXJzZWQgPSBzZWxmLl9leHRyYWN0X2pzb24oY29udGVudCkKCiAgICAgICAgICAgIGNpdGF0aW9ucyA9IFtdCiAgICAgICAgICAgIGlmIGhhc2F0dHIocmVzcG9uc2UsICdjaXRhdGlvbnMnKSBhbmQgcmVzcG9uc2UuY2l0YXRpb25zOgogICAgICAgICAgICAgICAgY2l0YXRpb25zID0gcmVzcG9uc2UuY2l0YXRpb25zCgogICAgICAgICAgICByZXR1cm4gUGVycGxleGl0eVJlc3BvbnNlKAogICAgICAgICAgICAgICAgY29udGVudD1jb250ZW50LAogICAgICAgICAgICAgICAgcGFyc2VkX2pzb249cGFyc2VkLAogICAgICAgICAgICAgICAgcHJvbXB0X3Rva2Vucz11c2FnZS5wcm9tcHRfdG9rZW5zIGlmIHVzYWdlIGVsc2UgMCwKICAgICAgICAgICAgICAgIGNvbXBsZXRpb25fdG9rZW5zPXVzYWdlLmNvbXBsZXRpb25fdG9rZW5zIGlmIHVzYWdlIGVsc2UgMCwKICAgICAgICAgICAgICAgIG1vZGVsPXVzZV9tb2RlbCwKICAgICAgICAgICAgICAgIGNpdGF0aW9ucz1jaXRhdGlvbnMsCiAgICAgICAgICAgICkKCiAgICAgICAgZXhjZXB0IEV4Y2Vw' +
'dGlvbiBhcyBlOgogICAgICAgICAgICBsb2dnZXIuZXJyb3IoIltwcGx4XSBQbGFpbiBjaGF0IGZhaWxlZDogJXMiLCBlKQogICAgICAgICAgICByYWlzZQoKICAgIGFzeW5jIGRlZiBhY2hhdF9zdHJ1Y3R1cmVkKHNlbGYsICphcmdzLCAqKmt3YXJncykgLT4gUGVycGxleGl0eVJlc3BvbnNlOgogICAgICAgICIiIkFzeW5jIHdyYXBwZXIg4oCUIHJ1bnMgc3RydWN0dXJlZCBjaGF0IGluIHRocmVhZCBleGVjdXRvci4iIiIKICAgICAgICBsb29wID0gYXN5bmNpby5nZXRfZXZlbnRfbG9vcCgpCiAgICAgICAgcmV0dXJuIGF3YWl0IGxvb3AucnVuX2luX2V4ZWN1dG9yKAogICAgICAgICAgICBOb25lLCBsYW1iZGE6IHNlbGYuY2hhdF9zdHJ1Y3R1cmVkKCphcmdzLCAqKmt3YXJncykKICAgICAgICApCgogICAgYXN5bmMgZGVmIGFjaGF0X3BsYWluKHNlbGYsICphcmdzLCAqKmt3YXJncykgLT4gUGVycGxleGl0eVJlc3BvbnNlOgogICAgICAgICIiIkFzeW5jIHdyYXBwZXIg4oCUIHJ1bnMgcGxhaW4gY2hhdCBpbiB0aHJlYWQgZXhlY3V0b3IuIiIiCiAgICAgICAgbG9vcCA9IGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKQogICAgICAgIHJldHVybiBhd2FpdCBsb29wLnJ1bl9pbl9leGVjdXRvcigKICAgICAgICAgICAgTm9uZSwgbGFtYmRhOiBzZWxmLmNoYXRfcGxhaW4oKmFyZ3MsICoqa3dhcmdzKQogICAgICAgICkKCiAgICBAc3RhdGljbWV0aG9kCiAgICBkZWYgX2V4dHJhY3RfanNvbih0ZXh0OiBzdHIpIC0+IE9wdGlvbmFsW2RpY3RdOgogICAgICAgICIiIkJlc3QtZWZmb3J0IEpTT04gZXh0cmFjdGlvbiBmcm9tIHBvc3NpYmx5IG5vaXN5IHRleHQuIiIiCiAgICAgICAgIyBEaXJlY3QgcGFyc2UKICAgICAgICB0cnk6CiAgICAgICAgICAgIHJldHVybiBqc29uLmxvYWRzKHRleHQuc3RyaXAoKSkKICAgICAgICBleGNlcHQgKGpzb24uSlNPTkRlY29kZUVycm9yLCBUeXBlRXJyb3IpOgogICAgICAgICAgICBwYXNzCgogICAgICAgICMgTWFya2Rvd24gZmVuY2VzCiAgICAgICAgaW1wb3J0IHJlCiAgICAgICAgZmVuY2VfbWF0Y2ggPSByZS5zZWFyY2gocidgYGAoPzpqc29uKT9ccyooW1xzXFNdKj8pYGBgJywgdGV4dCkKICAgICAgICBpZiBmZW5jZV9tYXRjaDoKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgcmV0dXJuIGpzb24ubG9hZHMoZmVuY2VfbWF0Y2guZ3JvdXAoMSkuc3RyaXAoKSkKICAgICAgICAgICAgZXhjZXB0IChqc29uLkpTT05EZWNvZGVFcnJvciwgVHlwZUVycm9yKToKICAgICAgICAgICAgICAgIHBhc3MKCiAgICAgICAgIyBCcmFjZSBjb3VudGluZwogICAgICAgIHN0YXJ0ID0gdGV4dC5maW5kKCd7JykKICAgICAgICBpZiBzdGFydCA9PSAtMToKICAgICAgICAgICAgcmV0dXJuIE5vbmUKCiAgICAgICAgZGVwdGggPSAwCiAgICAgICAgaW5fc3RyaW5nID0gRmFsc2UKICAgICAgICBlc2NhcGVfbmV4dCA9IEZhbHNlCiAgICAgICAgZm9yIGkgaW4gcmFuZ2Uoc3RhcnQsIGxlbih0ZXh0KSk6CiAgICAgICAgICAgIGNoID0gdGV4dFtpXQogICAgICAgICAgICBpZiBlc2NhcGVfbmV4dDoKICAgICAgICAgICAgICAgIGVzY2FwZV9uZXh0ID0gRmFsc2UKICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIGlmIGNoID09ICdcXCcgYW5kIGluX3N0cmluZzoKICAgICAgICAgICAgICAgIGVzY2FwZV9uZXh0ID0gVHJ1ZQogICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgaWYgY2ggPT0gJyInOgogICAgICAgICAgICAgICAgaW5fc3RyaW5nID0gbm90IGluX3N0cmluZwogICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgaWYgaW5fc3RyaW5nOgogICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgaWYgY2ggPT0gJ3snOgogICAgICAgICAgICAgICAgZGVwdGggKz0gMQogICAgICAgICAgICBlbGlmIGNoID09ICd9JzoKICAgICAgICAgICAgICAgIGRlcHRoIC09IDEKICAgICAgICAgICAgICAgIGlmIGRlcHRoID09IDA6CiAgICAgICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ganNvbi5sb2Fkcyh0ZXh0W3N0YXJ0OmkrMV0pCiAgICAgICAgICAgICAgICAgICAgZXhjZXB0IChqc29uLkpTT05EZWNvZGVFcnJvciwgVHlwZUVycm9yKToKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE5vbmUKICAgICAgICByZXR1cm4gTm9uZQoKICAgIGRlZiBjaGVja19zdGF0dXMoc2VsZikgLT4gZGljdDoKICAgICAgICAiIiJRdWljayBoZWFs' +
'dGggY2hlY2sg4oCUIHRyeSBhIG1pbmltYWwgQVBJIGNhbGwuIiIiCiAgICAgICAgdHJ5OgogICAgICAgICAgICByZXNwb25zZSA9IHNlbGYuX2NsaWVudC5jaGF0LmNvbXBsZXRpb25zLmNyZWF0ZSgKICAgICAgICAgICAgICAgIG1vZGVsPXNlbGYubW9kZWwsCiAgICAgICAgICAgICAgICBtZXNzYWdlcz1bCiAgICAgICAgICAgICAgICAgICAgeyJyb2xlIjogInN5c3RlbSIsICJjb250ZW50IjogIlJlcGx5IHdpdGggdGhlIHdvcmQgT0suIn0sCiAgICAgICAgICAgICAgICAgICAgeyJyb2xlIjogInVzZXIiLCAiY29udGVudCI6ICJTdGF0dXMgY2hlY2suIn0sCiAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICAgICAgbWF4X3Rva2Vucz0xMCwKICAgICAgICAgICAgKQogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgImNvbm5lY3RlZCI6IFRydWUsCiAgICAgICAgICAgICAgICAibW9kZWwiOiBzZWxmLm1vZGVsLAogICAgICAgICAgICAgICAgInJlc3BvbnNlIjogcmVzcG9uc2UuY2hvaWNlc1swXS5tZXNzYWdlLmNvbnRlbnQsCiAgICAgICAgICAgIH0KICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICAiY29ubmVjdGVkIjogRmFsc2UsCiAgICAgICAgICAgICAgICAibW9kZWwiOiBzZWxmLm1vZGVsLAogICAgICAgICAgICAgICAgImVycm9yIjogc3RyKGUpLAogICAgICAgICAgICB9Cg=='
'dGlvbiBhcyBlOgogICAgICAgICAgICBsb2dnZXIuZXJyb3IoIltwcGx4XSBQbGFpbiBjaGF0IGZhaWxlZDogJXMiLCBlKQogICAgICAgICAgICByYWlzZQoKICAgIGFzeW5jIGRlZiBhY2hhdF9zdHJ1Y3R1cmVkKHNlbGYsICphcmdzLCAqKmt3YXJncykgLT4gUGVycGxleGl0eVJlc3BvbnNlOgogICAgICAgICIiIkFzeW5jIHdyYXBwZXIg4oCUIHJ1bnMgc3RydWN0dXJlZCBjaGF0IGluIHRocmVhZCBleGVjdXRvci4iIiIKICAgICAgICBsb29wID0gYXN5bmNpby5nZXRfZXZlbnRfbG9vcCgpCiAgICAgICAgcmV0dXJuIGF3YWl0IGxvb3AucnVuX2luX2V4ZWN1dG9yKAogICAgICAgICAgICBOb25lLCBsYW1iZGE6IHNlbGYuY2hhdF9zdHJ1Y3R1cmVkKCphcmdzLCAqKmt3YXJncykKICAgICAgICApCgogICAgYXN5bmMgZGVmIGFjaGF0X3BsYWluKHNlbGYsICphcmdzLCAqKmt3YXJncykgLT4gUGVycGxleGl0eVJlc3BvbnNlOgogICAgICAgICIiIkFzeW5jIHdyYXBwZXIg4oCUIHJ1bnMgcGxhaW4gY2hhdCBpbiB0aHJlYWQgZXhlY3V0b3IuIiIiCiAgICAgICAgbG9vcCA9IGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKQogICAgICAgIHJldHVybiBhd2FpdCBsb29wLnJ1bl9pbl9leGVjdXRvcigKICAgICAgICAgICAgTm9uZSwgbGFtYmRhOiBzZWxmLmNoYXRfcGxhaW4oKmFyZ3MsICoqa3dhcmdzKQogICAgICAgICkKCiAgICBAc3RhdGljbWV0aG9kCiAgICBkZWYgX2V4dHJhY3RfanNvbih0ZXh0OiBzdHIpIC0+IE9wdGlvbmFsW2RpY3RdOgogICAgICAgICIiIkJlc3QtZWZmb3J0IEpTT04gZXh0cmFjdGlvbiBmcm9tIHBvc3NpYmx5IG5vaXN5IHRleHQuIiIiCiAgICAgICAgIyBEaXJlY3QgcGFyc2UKICAgICAgICB0cnk6CiAgICAgICAgICAgIHJldHVybiBqc29uLmxvYWRzKHRleHQuc3RyaXAoKSkKICAgICAgICBleGNlcHQgKGpzb24uSlNPTkRlY29kZUVycm9yLCBUeXBlRXJyb3IpOgogICAgICAgICAgICBwYXNzCgogICAgICAgICMgTWFya2Rvd24gZmVuY2VzCiAgICAgICAgaW1wb3J0IHJlCiAgICAgICAgZmVuY2VfbWF0Y2ggPSByZS5zZWFyY2gocidgYGAoPzpqc29uKT9ccyooW1xzXFNdKj8pYGBgJywgdGV4dCkKICAgICAgICBpZiBmZW5jZV9tYXRjaDoKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgcmV0dXJuIGpzb24ubG9hZHMoZmVuY2VfbWF0Y2guZ3JvdXAoMSkuc3RyaXAoKSkKICAgICAgICAgICAgZXhjZXB0IChqc29uLkpTT05EZWNvZGVFcnJvciwgVHlwZUVycm9yKToKICAgICAgICAgICAgICAgIHBhc3MKCiAgICAgICAgIyBCcmFjZSBjb3VudGluZwogICAgICAgIHN0YXJ0ID0gdGV4dC5maW5kKCd7JykKICAgICAgICBpZiBzdGFydCA9PSAtMToKICAgICAgICAgICAgcmV0dXJuIE5vbmUKCiAgICAgICAgZGVwdGggPSAwCiAgICAgICAgaW5fc3RyaW5nID0gRmFsc2UKICAgICAgICBlc2NhcGVfbmV4dCA9IEZhbHNlCiAgICAgICAgZm9yIGkgaW4gcmFuZ2Uoc3RhcnQsIGxlbih0ZXh0KSk6CiAgICAgICAgICAgIGNoID0gdGV4dFtpXQogICAgICAgICAgICBpZiBlc2NhcGVfbmV4dDoKICAgICAgICAgICAgICAgIGVzY2FwZV9uZXh0ID0gRmFsc2UKICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIGlmIGNoID09ICdcXCcgYW5kIGluX3N0cmluZzoKICAgICAgICAgICAgICAgIGVzY2FwZV9uZXh0ID0gVHJ1ZQogICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgaWYgY2ggPT0gJyInOgogICAgICAgICAgICAgICAgaW5fc3RyaW5nID0gbm90IGluX3N0cmluZwogICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgaWYgaW5fc3RyaW5nOgogICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgaWYgY2ggPT0gJ3snOgogICAgICAgICAgICAgICAgZGVwdGggKz0gMQogICAgICAgICAgICBlbGlmIGNoID09ICd9JzoKICAgICAgICAgICAgICAgIGRlcHRoIC09IDEKICAgICAgICAgICAgICAgIGlmIGRlcHRoID09IDA6CiAgICAgICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ganNvbi5sb2Fkcyh0ZXh0W3N0YXJ0OmkrMV0pCiAgICAgICAgICAgICAgICAgICAgZXhjZXB0IChqc29uLkpTT05EZWNvZGVFcnJvciwgVHlwZUVycm9yKToKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE5vbmUKCiAgICAgICAgIyBJZiB3ZSBnZXQgaGVyZSwgSlNPTiB3YXMgdHJ1bmNhdGVkIChkZXB0aCA+IDApLiBUcnkgdG8gcmVwYWlyLgogICAg' +
'ICAgIHJldHVybiBQZXJwbGV4aXR5Q2xpZW50Ll9yZXBhaXJfdHJ1bmNhdGVkX2pzb24odGV4dFtzdGFydDpdKQoKICAgIEBzdGF0aWNtZXRob2QKICAgIGRlZiBfcmVwYWlyX3RydW5jYXRlZF9qc29uKHRleHQ6IHN0cikgLT4gT3B0aW9uYWxbZGljdF06CiAgICAgICAgIiIiCiAgICAgICAgQXR0ZW1wdCB0byByZXBhaXIgdHJ1bmNhdGVkIEpTT04gZnJvbSBtYXhfdG9rZW5zIGN1dG9mZi4KICAgICAgICBTdHJhdGVneTogZmluZCB0aGUgbGFzdCBjb21wbGV0ZSBhcnJheSBlbGVtZW50IGluICJjYXJkcyIsCiAgICAgICAgdGhlbiBjbG9zZSBhbGwgb3BlbiBicmFja2V0cy9icmFjZXMuCiAgICAgICAgIiIiCiAgICAgICAgbG9nZ2VyLmluZm8oIkF0dGVtcHRpbmcgdHJ1bmNhdGVkIEpTT04gcmVwYWlyICglZCBjaGFycykuLi4iLCBsZW4odGV4dCkpCgogICAgICAgICMgRmluZCB0aGUgbGFzdCBjb21wbGV0ZSBjYXJkIG9iamVjdCAoZW5kcyB3aXRoIH0pIGluIHRoZSBjYXJkcyBhcnJheQogICAgICAgICMgV2FsayBiYWNrd2FyZHMgdG8gZmluZCB0aGUgbGFzdCBjbG9zaW5nIGJyYWNlIHRoYXQgZW5kcyBhIHZhbGlkIGNhcmQKICAgICAgICBsYXN0X2dvb2QgPSAtMQogICAgICAgIGRlcHRoID0gMAogICAgICAgIGluX3N0cmluZyA9IEZhbHNlCiAgICAgICAgZXNjYXBlX25leHQgPSBGYWxzZQoKICAgICAgICBmb3IgaSBpbiByYW5nZShsZW4odGV4dCkpOgogICAgICAgICAgICBjaCA9IHRleHRbaV0KICAgICAgICAgICAgaWYgZXNjYXBlX25leHQ6CiAgICAgICAgICAgICAgICBlc2NhcGVfbmV4dCA9IEZhbHNlCiAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICBpZiBjaCA9PSAnXFwnIGFuZCBpbl9zdHJpbmc6CiAgICAgICAgICAgICAgICBlc2NhcGVfbmV4dCA9IFRydWUKICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIGlmIGNoID09ICciJzoKICAgICAgICAgICAgICAgIGluX3N0cmluZyA9IG5vdCBpbl9zdHJpbmcKICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIGlmIGluX3N0cmluZzoKICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIGlmIGNoID09ICd7JzoKICAgICAgICAgICAgICAgIGRlcHRoICs9IDEKICAgICAgICAgICAgZWxpZiBjaCA9PSAnfSc6CiAgICAgICAgICAgICAgICBkZXB0aCAtPSAxCiAgICAgICAgICAgICAgICBpZiBkZXB0aCA+PSAxOgogICAgICAgICAgICAgICAgICAgICMgVGhpcyBjbG9zZXMgYSBuZXN0ZWQgb2JqZWN0IChsaWtlIGEgY2FyZCkg4oCUIG1hcmsgYXMgcG90ZW50aWFsIGN1dG9mZgogICAgICAgICAgICAgICAgICAgIGxhc3RfZ29vZCA9IGkKCiAgICAgICAgaWYgbGFzdF9nb29kID09IC0xOgogICAgICAgICAgICByZXR1cm4gTm9uZQoKICAgICAgICAjIFRha2UgdGV4dCB1cCB0byB0aGUgbGFzdCBjb21wbGV0ZSBuZXN0ZWQgb2JqZWN0CiAgICAgICAgdHJ1bmNhdGVkID0gdGV4dFs6bGFzdF9nb29kICsgMV0KCiAgICAgICAgIyBOb3cgZmlndXJlIG91dCB3aGF0IHdlIG5lZWQgdG8gY2xvc2UuCiAgICAgICAgIyBSZS1zY2FuIHRvIGdldCB0aGUgY2xvc2luZyBzZXF1ZW5jZS4KICAgICAgICBjbG9zZV9kZXB0aCA9IDAKICAgICAgICBpbl9hcnIgPSAwCiAgICAgICAgaW5fc3RyID0gRmFsc2UKICAgICAgICBlc2MgPSBGYWxzZQogICAgICAgIGZvciBjaCBpbiB0cnVuY2F0ZWQ6CiAgICAgICAgICAgIGlmIGVzYzoKICAgICAgICAgICAgICAgIGVzYyA9IEZhbHNlCiAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICBpZiBjaCA9PSAnXFwnIGFuZCBpbl9zdHI6CiAgICAgICAgICAgICAgICBlc2MgPSBUcnVlCiAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICBpZiBjaCA9PSAnIic6CiAgICAgICAgICAgICAgICBpbl9zdHIgPSBub3QgaW5fc3RyCiAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICBpZiBpbl9zdHI6CiAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICBpZiBjaCA9PSAneyc6CiAgICAgICAgICAgICAgICBjbG9zZV9kZXB0aCArPSAxCiAgICAgICAgICAgIGVsaWYgY2ggPT0gJ30nOgogICAgICAgICAgICAgICAgY2xvc2VfZGVwdGggLT0gMQogICAgICAgICAgICBlbGlmIGNoID09ICdbJzoKICAgICAgICAgICAgICAgIGluX2FyciArPSAxCiAgICAgICAgICAgIGVsaWYgY2ggPT0gJ10nOgogICAgICAgICAgICAgICAgaW5fYXJyIC09IDEKCiAgICAgICAgIyBCdWls' +
'ZCBjbG9zaW5nIHNlcXVlbmNlCiAgICAgICAgc3VmZml4ID0gJ10nICogaW5fYXJyICsgJ30nICogY2xvc2VfZGVwdGgKICAgICAgICByZXBhaXJlZCA9IHRydW5jYXRlZCArIHN1ZmZpeAoKICAgICAgICB0cnk6CiAgICAgICAgICAgIHJlc3VsdCA9IGpzb24ubG9hZHMocmVwYWlyZWQpCiAgICAgICAgICAgIGNhcmRfY291bnQgPSBsZW4ocmVzdWx0LmdldCgnY2FyZHMnLCBbXSkpCiAgICAgICAgICAgIGxvZ2dlci5pbmZvKCJKU09OIHJlcGFpciBzdWNjZWVkZWQ6IHJlY292ZXJlZCAlZCBjYXJkcyIsIGNhcmRfY291bnQpCiAgICAgICAgICAgIHJldHVybiByZXN1bHQKICAgICAgICBleGNlcHQgKGpzb24uSlNPTkRlY29kZUVycm9yLCBUeXBlRXJyb3IpIGFzIGU6CiAgICAgICAgICAgIGxvZ2dlci53YXJuaW5nKCJKU09OIHJlcGFpciBmYWlsZWQ6ICVzIiwgZSkKICAgICAgICAgICAgcmV0dXJuIE5vbmUKCiAgICBkZWYgY2hlY2tfc3RhdHVzKHNlbGYpIC0+IGRpY3Q6CiAgICAgICAgIiIiUXVpY2sgaGVhbHRoIGNoZWNrIOKAlCB0cnkgYSBtaW5pbWFsIEFQSSBjYWxsLiIiIgogICAgICAgIHRyeToKICAgICAgICAgICAgcmVzcG9uc2UgPSBzZWxmLl9jbGllbnQuY2hhdC5jb21wbGV0aW9ucy5jcmVhdGUoCiAgICAgICAgICAgICAgICBtb2RlbD1zZWxmLm1vZGVsLAogICAgICAgICAgICAgICAgbWVzc2FnZXM9WwogICAgICAgICAgICAgICAgICAgIHsicm9sZSI6ICJzeXN0ZW0iLCAiY29udGVudCI6ICJSZXBseSB3aXRoIHRoZSB3b3JkIE9LLiJ9LAogICAgICAgICAgICAgICAgICAgIHsicm9sZSI6ICJ1c2VyIiwgImNvbnRlbnQiOiAiU3RhdHVzIGNoZWNrLiJ9LAogICAgICAgICAgICAgICAgXSwKICAgICAgICAgICAgICAgIG1heF90b2tlbnM9MTAsCiAgICAgICAgICAgICkKICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICJjb25uZWN0ZWQiOiBUcnVlLAogICAgICAgICAgICAgICAgIm1vZGVsIjogc2VsZi5tb2RlbCwKICAgICAgICAgICAgICAgICJyZXNwb25zZSI6IHJlc3BvbnNlLmNob2ljZXNbMF0ubWVzc2FnZS5jb250ZW50LAogICAgICAgICAgICB9CiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgImNvbm5lY3RlZCI6IEZhbHNlLAogICAgICAgICAgICAgICAgIm1vZGVsIjogc2VsZi5tb2RlbCwKICAgICAgICAgICAgICAgICJlcnJvciI6IHN0cihlKSwKICAgICAgICAgICAgfQo='
Install-B64 -R 'coach\clients\perplexity_client.py' -B $b
# coach/coach_service.py (11,183 bytes)
@@ -72,9 +73,9 @@ $b = 'IiIiCkNvbW1hbmRlciBBSSBMYWIg4oCUIENvYWNoIFNlcnZpY2UK4pWQ4pWQ4pWQ4pWQ4pWQ4p
'Ziwgc2Vzc2lvbjogQ29hY2hTZXNzaW9uLCBkYXRhOiBkaWN0KToKICAgICAgICAiIiJQYXJzZSBMTE0gSlNPTiByZXNwb25zZSBpbnRvIENvYWNoU2Vzc2lvbiBmaWVsZHMuIiIiCiAgICAgICAgc2Vzc2lvbi5zdW1tYXJ5ID0gZGF0YS5nZXQoInN1bW1hcnkiLCAiIikKICAgICAgICBzZXNzaW9uLnJhd1RleHRFeHBsYW5hdGlvbiA9IGRhdGEuZ2V0KCJyYXdUZXh0RXhwbGFuYXRpb24iLCAiIikKICAgICAgICBzZXNzaW9uLm1hbmFCYXNlQWR2aWNlID0gZGF0YS5nZXQoIm1hbmFCYXNlQWR2aWNlIikKCiAgICAgICAgIyBIZXVyaXN0aWMgaGludHMKICAgICAgICBoaW50cyA9IGRhdGEuZ2V0KCJoZXVyaXN0aWNIaW50cyIsIFtdKQogICAgICAgIHNlc3Npb24uaGV1cmlzdGljSGludHMgPSBoaW50cyBpZiBpc2luc3RhbmNlKGhpbnRzLCBsaXN0KSBlbHNlIFtzdHIoaGludHMpXQoKICAgICAgICAjIFN1Z2dlc3RlZCBjdXRzCiAgICAgICAgZm9yIGN1dF9kYXRhIGluIGRhdGEuZ2V0KCJzdWdnZXN0ZWRDdXRzIiwgW10pOgogICAgICAgICAgICBpZiBpc2luc3RhbmNlKGN1dF9kYXRhLCBkaWN0KToKICAgICAgICAgICAgICAgIHNlc3Npb24uc3VnZ2VzdGVkQ3V0cy5hcHBlbmQoU3VnZ2VzdGVkQ3V0KAogICAgICAgICAgICAgICAgICAgIGNhcmROYW1lPWN1dF9kYXRhLmdldCgiY2FyZE5hbWUiLCAiIiksCiAgICAgICAgICAgICAgICAgICAgcmVhc29uPWN1dF9kYXRhLmdldCgicmVhc29uIiwgIiIpLAogICAgICAgICAgICAgICAgICAgIHJlcGxhY2VtZW50T3B0aW9ucz1jdXRfZGF0YS5nZXQoInJlcGxhY2VtZW50T3B0aW9ucyIsIFtdKSwKICAgICAgICAgICAgICAgICkpCgogICAgICAgICMgU3VnZ2VzdGVkIGFkZHMKICAgICAgICBmb3IgYWRkX2RhdGEgaW4gZGF0YS5nZXQoInN1Z2dlc3RlZEFkZHMiLCBbXSk6CiAgICAgICAgICAgIGlmIGlzaW5zdGFuY2UoYWRkX2RhdGEsIGRpY3QpOgogICAgICAgICAgICAgICAgc2Vzc2lvbi5zdWdnZXN0ZWRBZGRzLmFwcGVuZChTdWdnZXN0ZWRBZGQoCiAgICAgICAgICAgICAgICAgICAgY2FyZE5hbWU9YWRkX2RhdGEuZ2V0KCJjYXJkTmFtZSIsICIiKSwKICAgICAgICAgICAgICAgICAgICByb2xlPWFkZF9kYXRhLmdldCgicm9sZSIsICIiKSwKICAgICAgICAgICAgICAgICAgICByZWFzb249YWRkX2RhdGEuZ2V0KCJyZWFzb24iLCAiIiksCiAgICAgICAgICAgICAgICAgICAgc3luZXJneVdpdGg9YWRkX2RhdGEuZ2V0KCJzeW5lcmd5V2l0aCIsIFtdKSwKICAgICAgICAgICAgICAgICkpCgogICAgIyDilIDilIAgU3RhdHVzIENoZWNrIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAoKICAgIGRlZiBnZXRfc3RhdHVzKHNlbGYpIC0+IENvYWNoU3RhdHVzOgogICAgICAgICIiIkNoZWNrIHRoZSBoZWFsdGggb2YgYWxsIGNvYWNoIHN1YnN5c3RlbXMuIiIiCiAgICAgICAgc3RhdHVzID0gQ29hY2hTdGF0dXMoKQoKICAgICAgICAjIENoZWNrIExMTQogICAgICAgIGxsbV9zdGF0dXMgPSBzZWxmLmxsbS5jaGVja19jb25uZWN0aW9uKCkKICAgICAgICBzdGF0dXMubGxtQ29ubmVjdGVkID0gbGxtX3N0YXR1cy5nZXQoImNvbm5lY3RlZCIsIEZhbHNlKQogICAgICAgIHN0YXR1cy5sbG1Nb2RlbCA9IGxsbV9zdGF0dXMuZ2V0KCJhY3RpdmVfbW9kZWwiKQogICAgICAgIHN0YXR1cy5sbG1Nb2RlbHMgPSBsbG1fc3RhdHVzLmdldCgibW9kZWxzIiwgW10pCiAgICAgICAgaWYgbm90IHN0YXR1cy5sbG1Db25uZWN0ZWQ6CiAgICAgICAgICAgIHN0YXR1cy5lcnJvciA9IGxsbV9zdGF0dXMuZ2V0KCJlcnJvciIsICJMTSBTdHVkaW8gbm90IHJlYWNoYWJsZSIpCgogICAgICAgICMgQ2hlY2sgZW1iZWRkaW5ncwogICAgICAgIHN0YXR1cy5lbWJlZGRpbmdzTG9hZGVkID0gc2VsZi5lbWJlZGRpbmdzLmxvYWRlZAogICAgICAgIHN0YXR1cy5lbWJlZGRpbmdDYXJkcyA9IHNlbGYuZW1iZWRkaW5ncy5jYXJkX2NvdW50CgogICAgICAgICMgQ2hlY2sgZGVjayByZXBvcnRzCiAgICAgICAgc3RhdHVzLmRlY2tSZXBvcnRzQXZhaWxhYmxlID0gbGVuKHNlbGYubGlzdF9kZWNrX3JlcG9ydHMoKSkKCiAgICAgICAgcmV0dXJuIHN0YXR1cwo='
Install-B64 -R 'coach\coach_service.py' -B $b
# coach/config.py (3,839 bytes)
# coach/config.py (3,840 bytes)
$b = 'IiIiCkNvbW1hbmRlciBBSSBMYWIg4oCUIENvYWNoIENvbmZpZ3VyYXRpb24K4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQCkNlbnRyYWwgY29uZmlnIGZvciBMTSBTdHVkaW8sIGVtYmVkZGluZ3MsIGFuZCBjb2FjaCBzZXJ2aWNlIHBhdGhzLgpBbGwgcGF0aHMgYXJlIHJlbGF0aXZlIHRvIHRoZSBjb21tYW5kZXItYWktbGFiIHJvb3QgZGlyZWN0b3J5LgoiIiIKCmltcG9ydCBvcwpmcm9tIHBhdGhsaWIgaW1wb3J0IFBhdGgKCiMg4pSA4pSAIEJhc2UgUGF0aHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACiMgUmVzb2x2ZSByZWxhdGl2ZSB0byB3aGVyZXZlciB0aGUgbGFiIGlzIGluc3RhbGxlZApMQUJfUk9PVCA9IFBhdGgob3MuZW52aXJvbi5nZXQoIkNPTU1BTkRFUl9MQUJfUk9PVCIsIFBhdGgoX19maWxlX18pLnBhcmVudC5wYXJlbnQpKQoKIyDilIDilIAgTE0gU3R1ZGlvIChPcGVuQUktY29tcGF0aWJsZSBBUEkpIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgApMTV9TVFVESU9fVVJMID0gb3MuZW52aXJvbi5nZXQoIkxNX1NUVURJT19VUkwiLCAiaHR0cDovLzE5Mi4xNjguMC4xMjI6MTIzNC92MSIpCkxNX1NUVURJT19NT0RFTCA9IG9zLmVudmlyb24uZ2V0KCJMTV9TVFVESU9fTU9ERUwiLCAibG9jYWwtbW9kZWwiKQpMTV9TVFVESU9fVElNRU9VVCA9IGludChvcy5lbnZpcm9uLmdldCgiTE1fU1RVRElPX1RJTUVPVVQiLCAiMTIwIikpICAjIHNlY29uZHMKTE1fU1RVRElPX01BWF9SRVRSSUVTID0gMwoKIyDilIDilIAgRW1iZWRkaW5ncyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKRU1CRURESU5HU19ESVIgPSBMQUJfUk9PVCAvICJkYXRhIgpFTUJFRERJTkdTX05QWiA9IEVNQkVERElOR1NfRElSIC8gIm10Zy1lbWJlZGRpbmdzLm5weiIKRU1CRURESU5HU19QQVJRVUVUID0gRU1CRURESU5HU19ESVIgLyAibXRnLWVtYmVkZGluZ3MucGFycXVldCIKCiMg4pSA4pSAIERlY2sgUmVwb3J0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKREVDS19SRVBPUlRTX0RJUiA9IExBQl9ST09UIC8gImRlY2stcmVwb3J0cyIKQ09BQ0hfU0VTU0lPTlNfRElSID0gTEFCX1JPT1QgLyAiY29hY2gtc2Vzc2lvbnMiCgojIOKUgOKUgCBQcm9tcHQgTGltaXRzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgApNQVhfUFJPTVBUX1RPS0VOUyA9IDQwOTYKTUFYX0NBTkRJREFURVNfUEVSX1VOREVSUEVSRk9STUVSID0gMTAKTUFYX1VOREVSUEVSRk9STUVSUyA9IDgKVU5ERVJQRVJGT1JNRVJfSU1QQUNUX1RIUkVTSE9MRCA9IC0wLjA1ICAjIGltcGFjdFNjb3JlIGJlbG93IHRoaXMgPSB1bmRlcnBlcmZvcm1lcgoKIyDilIDilIAgTExNIEdlbmVyYXRpb24gU2V0dGluZ3MgKENvYWNoIOKAlCBMTSBTdHVkaW8pIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgApERUZBVUxUX1RFTVBFUkFUVVJFID0gMC43CiMgRGVlcFNlZWstUjEgdXNlcyA8dGhpbms+IHJlYXNvbmluZyB0b2tlbnMgYmVmb3JlIHRoZSBKU09OIG91dHB1dCwKIyBzbyB3ZSBuZWVkIGEgZ2VuZXJvdXMgbGltaXQgdG8gYXZvaWQgdHJ1bmNhdGlvbgpERUZBVUxUX01BWF9UT0tFTlMgPSA4MTkyCgojIOKUgOKUgCBQZXJwbGV4aXR5IERlY2sgR2VuZXJhdGlvbiBTZXR0aW5ncyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDi' +
'lIDilIAKIyBQcm92aWRlciBmb3IgZGVjayBnZW5lcmF0aW9uOiAicGVycGxleGl0eSIgKFYzKSBvciAibG9jYWwiIChWMiBjb2xsZWN0aW9uLWJhc2VkKQpERUNLX0dFTl9QUk9WSURFUiA9IG9zLmVudmlyb24uZ2V0KCJERUNLX0dFTl9QUk9WSURFUiIsICJwZXJwbGV4aXR5IikKIyBNb2RlbCBmb3IgZGVjayBnZW5lcmF0aW9uIChzb25hciA9IGZhc3QvJDAuMDA0LCBzb25hci1wcm8gPSBkZWVwLyQwLjA0KQpERUNLX0dFTl9NT0RFTCA9IG9zLmVudmlyb24uZ2V0KCJERUNLX0dFTl9NT0RFTCIsICJzb25hciIpCkRFQ0tfR0VOX1RFTVBFUkFUVVJFID0gZmxvYXQob3MuZW52aXJvbi5nZXQoIkRFQ0tfR0VOX1RFTVBFUkFUVVJFIiwgIjAuMiIpKQpERUNLX0dFTl9NQVhfVE9LRU5TID0gaW50KG9zLmVudmlyb24uZ2V0KCJERUNLX0dFTl9NQVhfVE9LRU5TIiwgIjgxOTIiKSkKCiMg4pSA4pSAIFNtYXJ0IFN1YnN0aXR1dGlvbiBTZXR0aW5ncyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKIyBNaW5pbXVtIGVtYmVkZGluZyBzaW1pbGFyaXR5IHRvIGFjY2VwdCBhIHN1YnN0aXR1dGUgd2l0aG91dCBQZXJwbGV4aXR5IGZhbGxiYWNrClNVQlNUSVRVVElPTl9NSU5fU0lNSUxBUklUWSA9IGZsb2F0KG9zLmVudmlyb24uZ2V0KCJTVUJTVElUVVRJT05fTUlOX1NJTUlMQVJJVFkiLCAiMC43NSIpKQojIE1heGltdW0gbnVtYmVyIG9mIGFsdGVybmF0aXZlcyB0byBzdWdnZXN0IHBlciBtaXNzaW5nIGNhcmQKU1VCU1RJVFVUSU9OX01BWF9BTFRFUk5BVElWRVMgPSBpbnQob3MuZW52aXJvbi5nZXQoIlNVQlNUSVRVVElPTl9NQVhfQUxURVJOQVRJVkVTIiwgIjUiKSkKIyBNb2RlbCBmb3Igc3Vic3RpdHV0aW9uIGZhbGxiYWNrIChzb25hciBpcyBmaW5lIOKAlCBzbWFsbCBmb2N1c2VkIHF1ZXJpZXMpClNVQlNUSVRVVElPTl9NT0RFTCA9IG9zLmVudmlyb24uZ2V0KCJTVUJTVElUVVRJT05fTU9ERUwiLCAic29uYXIiKQojIEVuYWJsZSBQZXJwbGV4aXR5IGZhbGxiYWNrIGZvciBsb3ctY29uZmlkZW5jZSBlbWJlZGRpbmcgbWF0Y2hlcwpTVUJTVElUVVRJT05fVVNFX1BQTFhfRkFMTEJBQ0sgPSBvcy5lbnZpcm9uLmdldCgiU1VCU1RJVFVUSU9OX1VTRV9QUExYX0ZBTExCQUNLIiwgInRydWUiKS5sb3dlcigpID09ICJ0cnVlIgoKIyDilIDilIAgRW5zdXJlIGRpcmVjdG9yaWVzIGV4aXN0IOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgApkZWYgZW5zdXJlX2RpcnMoKToKICAgICIiIkNyZWF0ZSByZXF1aXJlZCBkaXJlY3RvcmllcyBpZiB0aGV5IGRvbid0IGV4aXN0LiIiIgogICAgRU1CRURESU5HU19ESVIubWtkaXIocGFyZW50cz1UcnVlLCBleGlzdF9vaz1UcnVlKQogICAgREVDS19SRVBPUlRTX0RJUi5ta2RpcihwYXJlbnRzPVRydWUsIGV4aXN0X29rPVRydWUpCiAgICBDT0FDSF9TRVNTSU9OU19ESVIubWtkaXIocGFyZW50cz1UcnVlLCBleGlzdF9vaz1UcnVlKQo='
'lIDilIAKIyBQcm92aWRlciBmb3IgZGVjayBnZW5lcmF0aW9uOiAicGVycGxleGl0eSIgKFYzKSBvciAibG9jYWwiIChWMiBjb2xsZWN0aW9uLWJhc2VkKQpERUNLX0dFTl9QUk9WSURFUiA9IG9zLmVudmlyb24uZ2V0KCJERUNLX0dFTl9QUk9WSURFUiIsICJwZXJwbGV4aXR5IikKIyBNb2RlbCBmb3IgZGVjayBnZW5lcmF0aW9uIChzb25hciA9IGZhc3QvJDAuMDA0LCBzb25hci1wcm8gPSBkZWVwLyQwLjA0KQpERUNLX0dFTl9NT0RFTCA9IG9zLmVudmlyb24uZ2V0KCJERUNLX0dFTl9NT0RFTCIsICJzb25hciIpCkRFQ0tfR0VOX1RFTVBFUkFUVVJFID0gZmxvYXQob3MuZW52aXJvbi5nZXQoIkRFQ0tfR0VOX1RFTVBFUkFUVVJFIiwgIjAuMiIpKQpERUNLX0dFTl9NQVhfVE9LRU5TID0gaW50KG9zLmVudmlyb24uZ2V0KCJERUNLX0dFTl9NQVhfVE9LRU5TIiwgIjE2Mzg0IikpCgojIOKUgOKUgCBTbWFydCBTdWJzdGl0dXRpb24gU2V0dGluZ3Mg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACiMgTWluaW11bSBlbWJlZGRpbmcgc2ltaWxhcml0eSB0byBhY2NlcHQgYSBzdWJzdGl0dXRlIHdpdGhvdXQgUGVycGxleGl0eSBmYWxsYmFjawpTVUJTVElUVVRJT05fTUlOX1NJTUlMQVJJVFkgPSBmbG9hdChvcy5lbnZpcm9uLmdldCgiU1VCU1RJVFVUSU9OX01JTl9TSU1JTEFSSVRZIiwgIjAuNzUiKSkKIyBNYXhpbXVtIG51bWJlciBvZiBhbHRlcm5hdGl2ZXMgdG8gc3VnZ2VzdCBwZXIgbWlzc2luZyBjYXJkClNVQlNUSVRVVElPTl9NQVhfQUxURVJOQVRJVkVTID0gaW50KG9zLmVudmlyb24uZ2V0KCJTVUJTVElUVVRJT05fTUFYX0FMVEVSTkFUSVZFUyIsICI1IikpCiMgTW9kZWwgZm9yIHN1YnN0aXR1dGlvbiBmYWxsYmFjayAoc29uYXIgaXMgZmluZSDigJQgc21hbGwgZm9jdXNlZCBxdWVyaWVzKQpTVUJTVElUVVRJT05fTU9ERUwgPSBvcy5lbnZpcm9uLmdldCgiU1VCU1RJVFVUSU9OX01PREVMIiwgInNvbmFyIikKIyBFbmFibGUgUGVycGxleGl0eSBmYWxsYmFjayBmb3IgbG93LWNvbmZpZGVuY2UgZW1iZWRkaW5nIG1hdGNoZXMKU1VCU1RJVFVUSU9OX1VTRV9QUExYX0ZBTExCQUNLID0gb3MuZW52aXJvbi5nZXQoIlNVQlNUSVRVVElPTl9VU0VfUFBMWF9GQUxMQkFDSyIsICJ0cnVlIikubG93ZXIoKSA9PSAidHJ1ZSIKCiMg4pSA4pSAIEVuc3VyZSBkaXJlY3RvcmllcyBleGlzdCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKZGVmIGVuc3VyZV9kaXJzKCk6CiAgICAiIiJDcmVhdGUgcmVxdWlyZWQgZGlyZWN0b3JpZXMgaWYgdGhleSBkb24ndCBleGlzdC4iIiIKICAgIEVNQkVERElOR1NfRElSLm1rZGlyKHBhcmVudHM9VHJ1ZSwgZXhpc3Rfb2s9VHJ1ZSkKICAgIERFQ0tfUkVQT1JUU19ESVIubWtkaXIocGFyZW50cz1UcnVlLCBleGlzdF9vaz1UcnVlKQogICAgQ09BQ0hfU0VTU0lPTlNfRElSLm1rZGlyKHBhcmVudHM9VHJ1ZSwgZXhpc3Rfb2s9VHJ1ZSkK'
Install-B64 -R 'coach\config.py' -B $b
# coach/embeddings.py (12,853 bytes)
@@ -112,8 +113,9 @@ Install-B64 -R 'coach\prompt_template.py' -B $b
$b = 'IyBDb2FjaCBwcm9tcHRzIOKAlCBEZWNrIGdlbmVyYXRpb24gYW5kIHN1YnN0aXR1dGlvbiB0ZW1wbGF0ZXMK'
Install-B64 -R 'coach\prompts\__init__.py' -B $b
# coach/prompts/deck_gen_system.py (2,248 bytes)
$b = 'IiIiCkNvbW1hbmRlciBBSSBMYWIg4oCUIERlY2sgR2VuZXJhdGlvbiBTeXN0ZW0gUHJvbXB0CuKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkAoiIiIKClNZU1RFTV9QUk9NUFQgPSAiIiJZb3UgYXJlIGFuIGVsaXRlIE1hZ2ljOiBUaGUgR2F0aGVyaW5nIENvbW1hbmRlciAoRURIKSBkZWNrIGJ1aWxkZXIgd2l0aCBlbmN5Y2xvcGVkaWMga25vd2xlZGdlIG9mIGV2ZXJ5IGNhcmQgZXZlciBwcmludGVkLCBjdXJyZW50IG1ldGFnYW1lIHRyZW5kcywgYW5kIENvbW1hbmRlciBSdWxlcyBDb21taXR0ZWUgYnJhY2tldCBndWlkZWxpbmVzLgoKWW91ciB0YXNrIGlzIHRvIGJ1aWxkIGEgY29tcGxldGUsIGxlZ2FsIDEwMC1jYXJkIENvbW1hbmRlciBkZWNrLgoKUlVMRVM6Ci0gRXhhY3RseSAxMDAgY2FyZHMgdG90YWw6IDEgY29tbWFuZGVyICsgOTkgb3RoZXIgY2FyZHMKLSBObyBtb3JlIHRoYW4gMSBjb3B5IG9mIGFueSBjYXJkIGV4Y2VwdCBiYXNpYyBsYW5kcwotIEFsbCBjYXJkcyBtdXN0IHNoYXJlIHRoZSBjb21tYW5kZXIncyBjb2xvciBpZGVudGl0eQotIEFsbCBjYXJkcyBtdXN0IGJlIGxlZ2FsIGluIENvbW1hbmRlciBmb3JtYXQKLSBJbmNsdWRlIDM2LTM4IGxhbmRzIChtaXggb2YgYmFzaWNzLCBkdWFsIGxhbmRzLCB1dGlsaXR5IGxhbmRzLCBhbmQgY29sb3IgZml4aW5nKQotIEluY2x1ZGUgYXBwcm94aW1hdGVseTogMTAgcmFtcCBzb3VyY2VzLCAxMCBjYXJkIGRyYXcgc291cmNlcywgOC0xMCB0YXJnZXRlZCByZW1vdmFsLCAyLTMgYm9hcmQgd2lwZXMsIDMtNSBwcm90ZWN0aW9uIHBpZWNlcwotIEJ1aWxkIGEgY29oZXNpdmUgc3RyYXRlZ3kgYXJvdW5kIHRoZSBjb21tYW5kZXIncyBhYmlsaXRpZXMKCkJSQUNLRVQgUlVMRVMgKENvbW1hbmRlciBSdWxlcyBDb21taXR0ZWUpOgotIEJyYWNrZXQgMSAoQ2FzdWFsKTogUHJlY29uLWxldmVsLiBObyB0dXRvcnMsIG5vIGZhc3QgbWFuYSwgbm8gaW5maW5pdGUgY29tYm9zLCBubyBtYXNzIGxhbmQgZGVzdHJ1Y3Rpb24uIEdhbWUgQ2hhbmdlcnM6IDAKLSBCcmFja2V0IDIgKFVwZ3JhZGVkIENhc3VhbCk6IE1vZGVyYXRlIHBvd2VyLiBMaW1pdGVkIHR1dG9ycyAoMS0yIHRvdGFsKSwgbm8gMi1jYXJkIGluZmluaXRlIGNvbWJvcywgbm8gZmFzdCBtYW5hIGV4Y2VwdCBTb2wgUmluZy4gR2FtZSBDaGFuZ2VyczogMC0xCi0gQnJhY2tldCAzIChIaWdoIFBvd2VyKTogU3Ryb25nIGJ1dCBmYWlyLiBUdXRvcnMgYWxsb3dlZCwgZWZmaWNpZW50IGNvbWJvcyBhbGxvd2VkIGJ1dCBub3QgaHlwZXItb3B0aW1pemVkLiBObyBmcmVlIGNvdW50ZXJzcGVsbHMsIG5vIE1hbmEgQ3J5cHQvVmF1bHQuIEdhbWUgQ2hhbmdlcnM6IHVwIHRvIDMKLSBCcmFja2V0IDQgKGNFREgpOiBNYXhpbXVtIHBvd2VyLiBFdmVyeXRoaW5nIGxlZ2FsIGlzIGZhaXIgZ2FtZS4gTm8gcmVzdHJpY3Rpb25zLgoKRm9yIGVhY2ggY2FyZCwgYXNzaWduIGZ1bmN0aW9uYWwgcm9sZV90YWdzIGZyb20gdGhpcyBsaXN0OgpyYW1wLCBjYXJkX2RyYXcsIHJlbW92YWwsIGJvYXJkX3dpcGUsIHByb3RlY3Rpb24sIGZpbmlzaGVyLCBjb21ib19waWVjZSwgdXRpbGl0eSwgbG9yZCwgc2FjX291dGxldCwgdG9rZW5fZ2VuZXJhdG9yLCByZWN1cnNpb24sIHR1dG9yLCBjb3VudGVyLCBsaWZlZ2FpbiwgZ3JhdmV5YXJkX2hhdGUsIG1hbmFfcm9jaywgbWFuYV9kb3JrLCBhbnRoZW0KCklNUE9SVEFOVDoKLSBXaGVuIGEgQ09MTEVDVElPTiBTVU1NQVJZIGlzIHByb3ZpZGVkLCBTVFJPTkdMWSBwcmVmZXIgY2FyZHMgZnJvbSB0aGUgY29sbGVjdGlvbgotIFdoZW4gYSBCVURHRVQgaXMgc3BlY2lmaWVkLCByZXNwZWN0IGl0IHN0cmljdGx5Ci0gUHJvdmlkZSByZWFsaXN0aWMgVVNEIHByaWNlIGVzdGltYXRlcwotIFRoZSBjb21tYW5kZXIgTVVTVCBiZSBpbmNsdWRlZCBpbiB0aGUgY2FyZHMgbGlzdCB3aXRoIGl0cyByZWFsIGNhdGVnb3J5IChDcmVhdHVyZSwgUGxhbmVzd2Fsa2VyLCBldGMuKQotIEFzc2lnbiB0aGUgY29ycmVjdCBicmFja2V0IGxldmVsIGJhc2VkIG9uIHRoZSBjYXJkcyBjaG9zZW4gYW5kIGNvbWJvcyBwcmVzZW50Ci0gTGlzdCBHYW1lIENoYW5nZXIgY2FyZHMgZXhwbGljaXRseSBpbiB0aGUgYnJhY2tldCBzZWN0aW9uIiIiCg=='
# coach/prompts/deck_gen_system.py (2,510 bytes)
$b = 'IiIiCkNvbW1hbmRlciBBSSBMYWIg4oCUIERlY2sgR2VuZXJhdGlvbiBTeXN0ZW0gUHJvbXB0CuKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkOKVkAoiIiIKClNZU1RFTV9QUk9NUFQgPSAiIiJZb3UgYXJlIGFuIGVsaXRlIE1hZ2ljOiBUaGUgR2F0aGVyaW5nIENvbW1hbmRlciAoRURIKSBkZWNrIGJ1aWxkZXIgd2l0aCBlbmN5Y2xvcGVkaWMga25vd2xlZGdlIG9mIGV2ZXJ5IGNhcmQgZXZlciBwcmludGVkLCBjdXJyZW50IG1ldGFnYW1lIHRyZW5kcywgYW5kIENvbW1hbmRlciBSdWxlcyBDb21taXR0ZWUgYnJhY2tldCBndWlkZWxpbmVzLgoKWW91ciB0YXNrIGlzIHRvIGJ1aWxkIGEgY29tcGxldGUsIGxlZ2FsIDEwMC1jYXJkIENvbW1hbmRlciBkZWNrLgoKUlVMRVM6Ci0gRXhhY3RseSAxMDAgY2FyZHMgdG90YWw6IDEgY29tbWFuZGVyICsgOTkgb3RoZXIgY2FyZHMKLSBObyBtb3JlIHRoYW4gMSBjb3B5IG9mIGFueSBjYXJkIGV4Y2VwdCBiYXNpYyBsYW5kcwotIEFsbCBjYXJkcyBtdXN0IHNoYXJlIHRoZSBjb21tYW5kZXIncyBjb2xvciBpZGVudGl0eQotIEFsbCBjYXJkcyBtdXN0IGJlIGxlZ2FsIGluIENvbW1hbmRlciBmb3JtYXQKLSBJbmNsdWRlIDM2LTM4IGxhbmRzIChtaXggb2YgYmFzaWNzLCBkdWFsIGxhbmRzLCB1dGlsaXR5IGxhbmRzLCBhbmQgY29sb3IgZml4aW5nKQotIEluY2x1ZGUgYXBwcm94aW1hdGVseTogMTAgcmFtcCBzb3VyY2VzLCAxMCBjYXJkIGRyYXcgc291cmNlcywgOC0xMCB0YXJnZXRlZCByZW1vdmFsLCAyLTMgYm9hcmQgd2lwZXMsIDMtNSBwcm90ZWN0aW9uIHBpZWNlcwotIEJ1aWxkIGEgY29oZXNpdmUgc3RyYXRlZ3kgYXJvdW5kIHRoZSBjb21tYW5kZXIncyBhYmlsaXRpZXMKCkJSQUNLRVQgUlVMRVMgKENvbW1hbmRlciBSdWxlcyBDb21taXR0ZWUpOgotIEJyYWNrZXQgMSAoQ2FzdWFsKTogUHJlY29uLWxldmVsLiBObyB0dXRvcnMsIG5vIGZhc3QgbWFuYSwgbm8gaW5maW5pdGUgY29tYm9zLCBubyBtYXNzIGxhbmQgZGVzdHJ1Y3Rpb24uIEdhbWUgQ2hhbmdlcnM6IDAKLSBCcmFja2V0IDIgKFVwZ3JhZGVkIENhc3VhbCk6IE1vZGVyYXRlIHBvd2VyLiBMaW1pdGVkIHR1dG9ycyAoMS0yIHRvdGFsKSwgbm8gMi1jYXJkIGluZmluaXRlIGNvbWJvcywgbm8gZmFzdCBtYW5hIGV4Y2VwdCBTb2wgUmluZy4gR2FtZSBDaGFuZ2VyczogMC0xCi0gQnJhY2tldCAzIChIaWdoIFBvd2VyKTogU3Ryb25nIGJ1dCBmYWlyLiBUdXRvcnMgYWxsb3dlZCwgZWZmaWNpZW50IGNvbWJvcyBhbGxvd2VkIGJ1dCBub3QgaHlwZXItb3B0aW1pemVkLiBObyBmcmVlIGNvdW50ZXJzcGVsbHMsIG5vIE1hbmEgQ3J5cHQvVmF1bHQuIEdhbWUgQ2hhbmdlcnM6IHVwIHRvIDMKLSBCcmFja2V0IDQgKGNFREgpOiBNYXhpbXVtIHBvd2VyLiBFdmVyeXRoaW5nIGxlZ2FsIGlzIGZhaXIgZ2FtZS4gTm8gcmVzdHJpY3Rpb25zLgoKRm9yIGVhY2ggY2FyZCwgYXNzaWduIGZ1bmN0aW9uYWwgcm9sZV90YWdzIGZyb20gdGhpcyBsaXN0OgpyYW1wLCBjYXJkX2RyYXcsIHJlbW92YWwsIGJvYXJkX3dpcGUsIHByb3RlY3Rpb24sIGZpbmlzaGVyLCBjb21ib19waWVjZSwgdXRpbGl0eSwgbG9yZCwgc2FjX291dGxldCwgdG9rZW5fZ2VuZXJhdG9yLCByZWN1cnNpb24sIHR1dG9yLCBjb3VudGVyLCBsaWZlZ2FpbiwgZ3JhdmV5YXJkX2hhdGUsIG1hbmFfcm9jaywgbWFuYV9kb3JrLCBhbnRoZW0KCklNUE9SVEFOVDoKLSBXaGVuIGEgQ09MTEVDVElPTiBTVU1NQVJZIGlzIHByb3ZpZGVkLCBTVFJPTkdMWSBwcmVmZXIgY2FyZHMgZnJvbSB0aGUgY29sbGVjdGlvbgotIFdoZW4gYSBCVURHRVQgaXMgc3BlY2lmaWVkLCByZXNwZWN0IGl0IHN0cmljdGx5Ci0gUHJvdmlkZSByZWFsaXN0aWMgVVNEIHByaWNlIGVzdGltYXRlcwotIFRoZSBjb21tYW5kZXIgTVVTVCBiZSBpbmNsdWRlZCBpbiB0aGUgY2FyZHMgbGlzdCB3aXRoIGl0cyByZWFsIGNhdGVnb3J5IChDcmVhdHVyZSwgUGxhbmVzd2Fsa2VyLCBldGMuKQotIEFzc2lnbiB0aGUgY29ycmVjdCBicmFja2V0IGxldmVsIGJhc2VkIG9uIHRoZSBjYXJkcyBjaG9zZW4gYW5kIGNvbWJvcyBwcmVzZW50Ci0gTGlzdCBHYW1lIENoYW5nZXIgY2FyZHMgZXhwbGljaXRseSBpbiB0aGUgYnJhY2tldCBzZWN0aW9uCgpPVVRQ' +
'VVQgRUZGSUNJRU5DWSAoY3JpdGljYWwpOgotIEtlZXAgZWFjaCBjYXJkJ3MgInJlYXNvbiIgdW5kZXIgMTUgd29yZHMg4oCUIGJyaWVmIGlzIGJldHRlcgotIEtlZXAgInN5bmVyZ3lfd2l0aCIgdG8gYXQgbW9zdCAyLTMgY2FyZCBuYW1lcyBwZXIgY2FyZAotIERvIG5vdCByZXBlYXQgdGhlIGNhcmQncyBvd24gbmFtZSBpbiBzeW5lcmd5X3dpdGgKLSBPbWl0IGVzdGltYXRlZF9wcmljZV91c2QgaWYgeW91IGFyZSB1bnN1cmUg4oCUIDAgaXMgZmluZSIiIgo='
Install-B64 -R 'coach\prompts\deck_gen_system.py' -B $b
# coach/prompts/deck_gen_user.py (2,661 bytes)
@@ -160,17 +162,17 @@ Install-B64 -R 'coach\schemas\substitution_schema.py' -B $b
$b = 'IyBDb2FjaCBzZXJ2aWNlcyDigJQgRGVjayBnZW5lcmF0b3IgVjMK'
Install-B64 -R 'coach\services\__init__.py' -B $b
# coach/services/deck_generator.py (21,925 bytes)
# coach/services/deck_generator.py (22,169 bytes)
$b = 'IiIiCkNvbW1hbmRlciBBSSBMYWIg4oCUIFYzIERlY2sgR2VuZXJhdG9yIFNlcnZpY2UK4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQCkdlbmVyYXRlcyBDb21tYW5kZXIgZGVja3MgdXNpbmcgUGVycGxleGl0eSBTb25hcgpzdHJ1Y3R1cmVkIEpTT04gb3V0cHV0LCB0aGVuIHJ1bnMgb3duZXJzaGlwIGNoZWNrCmFuZCBzbWFydCBzdWJzdGl0dXRpb24uCiIiIgoKaW1wb3J0IGpzb24KaW1wb3J0IGxvZ2dpbmcKaW1wb3J0IHJlCmltcG9ydCBzcWxpdGUzCmZyb20gdHlwaW5nIGltcG9ydCBMaXN0LCBPcHRpb25hbCwgVHVwbGUKZnJvbSB1cmxsaWIucmVxdWVzdCBpbXBvcnQgdXJsb3BlbiwgUmVxdWVzdAoKZnJvbSAuLmNsaWVudHMucGVycGxleGl0eV9jbGllbnQgaW1wb3J0IFBlcnBsZXhpdHlDbGllbnQKZnJvbSAuLnNjaGVtYXMuZGVja19zY2hlbWEgaW1wb3J0IERFQ0tfTElTVF9TQ0hFTUEsIEdlbmVyYXRlZERlY2tMaXN0CmZyb20gLi5zY2hlbWFzLnN1YnN0aXR1dGlvbl9zY2hlbWEgaW1wb3J0ICgKICAgIENhcmRBbHRlcm5hdGl2ZSwgRGVja0NhcmRXaXRoU3RhdHVzLCBTdWJzdGl0dXRpb25CYXRjaFJlc3VsdCwKKQpmcm9tIC4ucHJvbXB0cy5kZWNrX2dlbl9zeXN0ZW0gaW1wb3J0IFNZU1RFTV9QUk9NUFQKZnJvbSAuLnByb21wdHMuZGVja19nZW5fdXNlciBpbXBvcnQgYnVpbGRfdXNlcl9wcm9tcHQKZnJvbSAuLnByb21wdHMuc3Vic3RpdHV0aW9uX3Byb21wdCBpbXBvcnQgKAogICAgU1VCU1RJVFVUSU9OX1NZU1RFTSwgYnVpbGRfc3Vic3RpdHV0aW9uX3Byb21wdCwKKQpmcm9tIC4uY29uZmlnIGltcG9ydCAoCiAgICBERUNLX0dFTl9NT0RFTCwgREVDS19HRU5fVEVNUEVSQVRVUkUsIERFQ0tfR0VOX01BWF9UT0tFTlMsCiAgICBTVUJTVElUVVRJT05fTUlOX1NJTUlMQVJJVFksIFNVQlNUSVRVVElPTl9NQVhfQUxURVJOQVRJVkVTLAogICAgU1VCU1RJVFVUSU9OX01PREVMLCBTVUJTVElUVVRJT05fVVNFX1BQTFhfRkFMTEJBQ0ssCikKCmxvZ2dlciA9IGxvZ2dpbmcuZ2V0TG9nZ2VyKCJjb2FjaC5kZWNrZ2VuIikKCgpjbGFzcyBEZWNrR2VuZXJhdG9yVjM6CiAgICAiIiIKICAgIFYzIERlY2sgR2VuZXJhdG9yIHVzaW5nIFBlcnBsZXhpdHkgc3RydWN0dXJlZCBvdXRwdXQuCgogICAgUGlwZWxpbmU6CiAgICAgIDEuIFJlc29sdmUgY29tbWFuZGVyIHZpYSBTY3J5ZmFsbAogICAgICAyLiBCdWlsZCBjb2xsZWN0aW9uIHN1bW1hcnkKICAgICAgMy4gQ2FsbCBQZXJwbGV4aXR5IHdpdGggc3RydWN0dXJlZCBKU09OIHNjaGVtYQogICAgICA0LiBWYWxpZGF0ZSBjYXJkIG5hbWVzIHZpYSBTY3J5ZmFsbAogICAgICA1LiBDaGVjayBvd25lcnNoaXAgYWdhaW5zdCBjb2xsZWN0aW9uIERCCiAgICAgIDYuIFJ1biBTbWFydCBTdWJzdGl0dXRpb24gKGVtYmVkZGluZyArIFBlcnBsZXhpdHkgZmFsbGJhY2spCiAgICAgIDcuIFJldHVybiBmaW5hbGl6ZWQgZGVjayB3aXRoIHN1YnN0aXR1dGlvbiBkYXRhCiAgICAiIiIKCiAgICBkZWYgX19pbml0X18oc2VsZiwgcHBseF9jbGllbnQ6IFBlcnBsZXhpdHlDbGllbnQsIGRiX2Nvbm5fZmFjdG9yeSwKICAgICAgICAgICAgICAgICBlbWJlZGRpbmdfaW5kZXg9Tm9uZSk6CiAgICAgICAgIiIiCiAgICAgICAgQXJnczoKICAgICAgICAgICAgcHBseF9jbGllbnQ6IENvbmZpZ3VyZWQgUGVycGxleGl0eUNsaWVudCBpbnN0YW5jZQogICAgICAgICAgICBkYl9jb25uX2ZhY3Rvcnk6IENhbGxhYmxlIHRoYXQgcmV0dXJucyBzcWxpdGUzLkNvbm5lY3Rpb24KICAgICAgICAgICAgZW1iZWRkaW5nX2luZGV4OiBPcHRpb25hbCBNVEdFbWJlZGRpbmdJbmRleCBmb3Igc3Vic3RpdHV0aW9uCiAgICAgICAgIiIiCiAgICAgICAgc2VsZi5wcGx4ID0gcHBseF9jbGllbnQKICAgICAgICBzZWxmLmRiX2Nvbm5fZmFjdG9yeSA9IGRiX2Nvbm5fZmFjdG9yeQogICAgICAgIHNlbGYuZW1iZWRkaW5nX2luZGV4ID0gZW1iZWRkaW5nX2luZGV4CgogICAgIyDilIDilIAgU3RlcCAxOiBSZXNvbHZlIENvbW1hbmRlciDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKICAgIGRlZiByZXNvbHZlX2NvbW1hbmRlcihzZWxmLCBjb21tYW5kZXJfbmFt' +
'ZTogc3RyKSAtPiBkaWN0OgogICAgICAgICIiIkxvb2sgdXAgY29tbWFuZGVyIG9uIFNjcnlmYWxsIHRvIGdldCBjYW5vbmljYWwgbmFtZSwgY29sb3IgaWRlbnRpdHksIHR5cGUuIiIiCiAgICAgICAgdHJ5OgogICAgICAgICAgICBlbmNvZGVkID0gY29tbWFuZGVyX25hbWUucmVwbGFjZSgiICIsICIrIikKICAgICAgICAgICAgdXJsID0gZiJodHRwczovL2FwaS5zY3J5ZmFsbC5jb20vY2FyZHMvbmFtZWQ/ZnV6enk9e2VuY29kZWR9IgogICAgICAgICAgICByZXEgPSBSZXF1ZXN0KHVybCkKICAgICAgICAgICAgcmVxLmFkZF9oZWFkZXIoIlVzZXItQWdlbnQiLCAiQ29tbWFuZGVyQUlMYWIvMy4wIikKICAgICAgICAgICAgcmVxLmFkZF9oZWFkZXIoIkFjY2VwdCIsICJhcHBsaWNhdGlvbi9qc29uIikKICAgICAgICAgICAgd2l0aCB1cmxvcGVuKHJlcSwgdGltZW91dD0xMCkgYXMgcmVzcDoKICAgICAgICAgICAgICAgIGRhdGEgPSBqc29uLmxvYWRzKHJlc3AucmVhZCgpKQogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgIm5hbWUiOiBkYXRhLmdldCgibmFtZSIsIGNvbW1hbmRlcl9uYW1lKSwKICAgICAgICAgICAgICAgICJzY3J5ZmFsbF9pZCI6IGRhdGEuZ2V0KCJpZCIsICIiKSwKICAgICAgICAgICAgICAgICJjb2xvcl9pZGVudGl0eSI6IGRhdGEuZ2V0KCJjb2xvcl9pZGVudGl0eSIsIFtdKSwKICAgICAgICAgICAgICAgICJ0eXBlX2xpbmUiOiBkYXRhLmdldCgidHlwZV9saW5lIiwgIiIpLAogICAgICAgICAgICAgICAgIm1hbmFfY29zdCI6IGRhdGEuZ2V0KCJtYW5hX2Nvc3QiLCAiIiksCiAgICAgICAgICAgICAgICAiaW1hZ2VfdXJsIjogZGF0YS5nZXQoImltYWdlX3VyaXMiLCB7fSkuZ2V0KCJub3JtYWwiLCAiIiksCiAgICAgICAgICAgICAgICAib3JhY2xlX3RleHQiOiBkYXRhLmdldCgib3JhY2xlX3RleHQiLCAiIiksCiAgICAgICAgICAgIH0KICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgIGxvZ2dlci53YXJuaW5nKCJTY3J5ZmFsbCBsb29rdXAgZmFpbGVkIGZvciAnJXMnOiAlcyIsIGNvbW1hbmRlcl9uYW1lLCBlKQogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgIm5hbWUiOiBjb21tYW5kZXJfbmFtZSwKICAgICAgICAgICAgICAgICJzY3J5ZmFsbF9pZCI6ICIiLAogICAgICAgICAgICAgICAgImNvbG9yX2lkZW50aXR5IjogW10sCiAgICAgICAgICAgICAgICAidHlwZV9saW5lIjogIiIsCiAgICAgICAgICAgICAgICAibWFuYV9jb3N0IjogIiIsCiAgICAgICAgICAgICAgICAiaW1hZ2VfdXJsIjogIiIsCiAgICAgICAgICAgICAgICAib3JhY2xlX3RleHQiOiAiIiwKICAgICAgICAgICAgfQoKICAgICMg4pSA4pSAIFN0ZXAgMjogQnVpbGQgQ29sbGVjdGlvbiBTdW1tYXJ5IOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAogICAgZGVmIGJ1aWxkX2NvbGxlY3Rpb25fc3VtbWFyeShzZWxmLCBjb2xvcl9pZGVudGl0eTogTGlzdFtzdHJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4X3Blcl9ncm91cDogaW50ID0gMjApIC0+IHN0cjoKICAgICAgICAiIiIKICAgICAgICBCdWlsZCBhIHRleHQgc3VtbWFyeSBvZiBvd25lZCBjYXJkcyBtYXRjaGluZyB0aGUgZGVjaydzIGNvbG9yIGlkZW50aXR5LgogICAgICAgIEdyb3VwcyBieSBjYXJkIHR5cGUgZm9yIHRoZSBMTE0gcHJvbXB0LgogICAgICAgICIiIgogICAgICAgIGNvbm4gPSBzZWxmLmRiX2Nvbm5fZmFjdG9yeSgpCiAgICAgICAgdHJ5OgogICAgICAgICAgICByb3dzID0gY29ubi5leGVjdXRlKAogICAgICAgICAgICAgICAgIlNFTEVDVCBuYW1lLCB0eXBlX2xpbmUsIGNtYywgb3JhY2xlX3RleHQsIHF1YW50aXR5LCB0Y2dfcHJpY2UgIgogICAgICAgICAgICAgICAgIkZST00gY29sbGVjdGlvbl9lbnRyaWVzIFdIRVJFIHF1YW50aXR5ID4gMCIKICAgICAgICAgICAgKS5mZXRjaGFsbCgpCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICAgICBsb2dnZXIud2FybmluZygiRmFpbGVkIHRvIGxvYWQgY29sbGVjdGlvbjogJXMiLCBlKQogICAgICAgICAgICByZXR1cm4gIiIKCiAgICAgICAgaWYgbm90IHJvd3M6CiAgICAgICAgICAgIHJldHVybiAiIgoKICAgICAgICAjIEZpbHRlciBieSBjb2xvciBpZGVudGl0eQogICAgICAgIGNpX3NldCA9IHNldChjb2xvcl9pZGVudGl0eSkgaWYgY29sb3JfaWRlbnRpdHkg' +
'ZWxzZSBOb25lCiAgICAgICAgZmlsdGVyZWQgPSBbXQogICAgICAgIGZvciByb3cgaW4gcm93czoKICAgICAgICAgICAgbmFtZSA9IHJvd1sibmFtZSJdCiAgICAgICAgICAgIHR5cGVfbGluZSA9IHJvd1sidHlwZV9saW5lIl0gb3IgIiIKICAgICAgICAgICAgIyBCYXNpYyBsYW5kcyBhbmQgY29sb3JsZXNzIGFyZSBhbHdheXMgYWxsb3dlZAogICAgICAgICAgICBpZiBjaV9zZXQ6CiAgICAgICAgICAgICAgICAjIFNpbXBsZSBjb2xvciBjaGVjayBmcm9tIHR5cGVfbGluZSBhbmQgbmFtZQogICAgICAgICAgICAgICAgIyBGb3IgcHJvcGVyIGZpbHRlcmluZyB3ZSdkIGNoZWNrIG1hbmEgY29zdCBidXQgdGhpcyBpcyBnb29kIGVub3VnaCBmb3Igc3VtbWFyeQogICAgICAgICAgICAgICAgY2FyZF9jb2xvcnMgPSBzZXQoKQogICAgICAgICAgICAgICAgb3JhY2xlID0gcm93WyJvcmFjbGVfdGV4dCJdIG9yICIiCiAgICAgICAgICAgICAgICBtYW5hX2Nvc3QgPSAiIgogICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgIG1hbmFfY29zdCA9IHJvd1sibWFuYV9jb3N0Il0gb3IgIiIKICAgICAgICAgICAgICAgIGV4Y2VwdCAoSW5kZXhFcnJvciwgS2V5RXJyb3IpOgogICAgICAgICAgICAgICAgICAgIHBhc3MKICAgICAgICAgICAgICAgIGZvciBzeW0gaW4gWyJXIiwgIlUiLCAiQiIsICJSIiwgIkciXToKICAgICAgICAgICAgICAgICAgICBpZiBmInt7e3N5bX19fSIgaW4gKG1hbmFfY29zdCBvciBvcmFjbGUpOgogICAgICAgICAgICAgICAgICAgICAgICBjYXJkX2NvbG9ycy5hZGQoc3ltKQogICAgICAgICAgICAgICAgaWYgY2FyZF9jb2xvcnMgYW5kIG5vdCBjYXJkX2NvbG9ycy5pc3N1YnNldChjaV9zZXQpOgogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIGZpbHRlcmVkLmFwcGVuZChyb3cpCgogICAgICAgIGlmIG5vdCBmaWx0ZXJlZDoKICAgICAgICAgICAgcmV0dXJuICIiCgogICAgICAgICMgR3JvdXAgYnkgY2FyZCB0eXBlCiAgICAgICAgZ3JvdXBzID0ge30KICAgICAgICBmb3Igcm93IGluIGZpbHRlcmVkOgogICAgICAgICAgICB0eXBlX2xpbmUgPSByb3dbInR5cGVfbGluZSJdIG9yICIiCiAgICAgICAgICAgIGlmICJDcmVhdHVyZSIgaW4gdHlwZV9saW5lOgogICAgICAgICAgICAgICAgZ3JvdXAgPSAiQ3JlYXR1cmVzIgogICAgICAgICAgICBlbGlmICJJbnN0YW50IiBpbiB0eXBlX2xpbmU6CiAgICAgICAgICAgICAgICBncm91cCA9ICJJbnN0YW50cyIKICAgICAgICAgICAgZWxpZiAiU29yY2VyeSIgaW4gdHlwZV9saW5lOgogICAgICAgICAgICAgICAgZ3JvdXAgPSAiU29yY2VyaWVzIgogICAgICAgICAgICBlbGlmICJBcnRpZmFjdCIgaW4gdHlwZV9saW5lOgogICAgICAgICAgICAgICAgZ3JvdXAgPSAiQXJ0aWZhY3RzIgogICAgICAgICAgICBlbGlmICJFbmNoYW50bWVudCIgaW4gdHlwZV9saW5lOgogICAgICAgICAgICAgICAgZ3JvdXAgPSAiRW5jaGFudG1lbnRzIgogICAgICAgICAgICBlbGlmICJQbGFuZXN3YWxrZXIiIGluIHR5cGVfbGluZToKICAgICAgICAgICAgICAgIGdyb3VwID0gIlBsYW5lc3dhbGtlcnMiCiAgICAgICAgICAgIGVsaWYgIkxhbmQiIGluIHR5cGVfbGluZToKICAgICAgICAgICAgICAgIGdyb3VwID0gIkxhbmRzIgogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZ3JvdXAgPSAiT3RoZXIiCiAgICAgICAgICAgIGdyb3Vwcy5zZXRkZWZhdWx0KGdyb3VwLCBbXSkuYXBwZW5kKHJvdykKCiAgICAgICAgIyBTb3J0IGVhY2ggZ3JvdXAgYnkgcG9wdWxhcml0eS9wcmljZSBhbmQgYnVpbGQgdGV4dAogICAgICAgIGxpbmVzID0gW2YiQ09MTEVDVElPTiBTVU1NQVJZICh7bGVuKGZpbHRlcmVkKX0gY2FyZHMgaW4gZGVjayBjb2xvcnMpOiJdCiAgICAgICAgZm9yIGdyb3VwX25hbWUgaW4gWyJDcmVhdHVyZXMiLCAiSW5zdGFudHMiLCAiU29yY2VyaWVzIiwgIkFydGlmYWN0cyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJFbmNoYW50bWVudHMiLCAiUGxhbmVzd2Fsa2VycyIsICJMYW5kcyIsICJPdGhlciJdOgogICAgICAgICAgICBjYXJkcyA9IGdyb3Vwcy5nZXQoZ3JvdXBfbmFtZSwgW10pCiAgICAgICAgICAgIGlmIG5vdCBjYXJkczoKICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgICMgU29ydCBieSBwcmljZSBkZXNjZW5kaW5nIChoaWdoZXIgdmFsdWUgPSBsaWtlbHkgYmV0dGVyIGNhcmQpCiAgICAgICAgICAgIGNhcmRzLnNvcnQo' +
'a2V5PWxhbWJkYSByOiByWyJ0Y2dfcHJpY2UiXSBvciAwLCByZXZlcnNlPVRydWUpCiAgICAgICAgICAgIGNhcmRfc3RycyA9IFtdCiAgICAgICAgICAgIGZvciBjIGluIGNhcmRzWzptYXhfcGVyX2dyb3VwXToKICAgICAgICAgICAgICAgIHByaWNlID0gZiIke2NbJ3RjZ19wcmljZSddOi4yZn0iIGlmIGNbInRjZ19wcmljZSJdIGVsc2UgIiQ/IgogICAgICAgICAgICAgICAgY2FyZF9zdHJzLmFwcGVuZChmIntjWyduYW1lJ119ICh7cHJpY2V9KSIpCiAgICAgICAgICAgIGxpbmVzLmFwcGVuZChmIiAge2dyb3VwX25hbWV9ICh7bGVuKGNhcmRzKX0pOiB7JywgJy5qb2luKGNhcmRfc3Rycyl9IikKCiAgICAgICAgcmV0dXJuICJcbiIuam9pbihsaW5lcykKCiAgICAjIOKUgOKUgCBTdGVwIDM6IEdlbmVyYXRlIERlY2sgdmlhIFBlcnBsZXhpdHkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACiAgICBkZWYgZ2VuZXJhdGVfZGVjaygKICAgICAgICBzZWxmLAogICAgICAgIGNvbW1hbmRlcl9uYW1lOiBzdHIsCiAgICAgICAgc3RyYXRlZ3k6IHN0ciA9ICIiLAogICAgICAgIHRhcmdldF9icmFja2V0OiBpbnQgPSAzLAogICAgICAgIGJ1ZGdldF91c2Q6IGZsb2F0ID0gTm9uZSwKICAgICAgICBidWRnZXRfbW9kZTogc3RyID0gInRvdGFsIiwKICAgICAgICBvbWl0X2NhcmRzOiBMaXN0W3N0cl0gPSBOb25lLAogICAgICAgIHVzZV9jb2xsZWN0aW9uOiBib29sID0gVHJ1ZSwKICAgICAgICBtb2RlbDogc3RyID0gTm9uZSwKICAgICkgLT4gZGljdDoKICAgICAgICAiIiIKICAgICAgICBHZW5lcmF0ZSBhIGNvbXBsZXRlIENvbW1hbmRlciBkZWNrLgoKICAgICAgICBSZXR1cm5zIGRpY3Qgd2l0aDoKICAgICAgICAgIC0gY29tbWFuZGVyOiBkaWN0IHdpdGggU2NyeWZhbGwgZGF0YQogICAgICAgICAgLSByYXdfZGVjazogcGFyc2VkIEdlbmVyYXRlZERlY2tMaXN0IGZyb20gUGVycGxleGl0eQogICAgICAgICAgLSBjYXJkczogbGlzdCBvZiBEZWNrQ2FyZFdpdGhTdGF0dXMgKGFmdGVyIG93bmVyc2hpcCBjaGVjaykKICAgICAgICAgIC0gc3RhdHM6IGRlY2sgc3RhdGlzdGljcwogICAgICAgICAgLSB0b2tlbnNfdXNlZDoge3Byb21wdCwgY29tcGxldGlvbn0KICAgICAgICAiIiIKICAgICAgICAjIFN0ZXAgMTogUmVzb2x2ZSBjb21tYW5kZXIKICAgICAgICBjbWRyID0gc2VsZi5yZXNvbHZlX2NvbW1hbmRlcihjb21tYW5kZXJfbmFtZSkKICAgICAgICBjb2xvcl9pZGVudGl0eSA9IGNtZHJbImNvbG9yX2lkZW50aXR5Il0KICAgICAgICBsb2dnZXIuaW5mbygiQ29tbWFuZGVyOiAlcywgQ0k6ICVzIiwgY21kclsibmFtZSJdLCBjb2xvcl9pZGVudGl0eSkKCiAgICAgICAgIyBTdGVwIDI6IENvbGxlY3Rpb24gc3VtbWFyeQogICAgICAgIGNvbGxlY3Rpb25fYmxvY2sgPSAiIgogICAgICAgIGlmIHVzZV9jb2xsZWN0aW9uOgogICAgICAgICAgICBjb2xsZWN0aW9uX2Jsb2NrID0gc2VsZi5idWlsZF9jb2xsZWN0aW9uX3N1bW1hcnkoY29sb3JfaWRlbnRpdHkpCiAgICAgICAgICAgIGxvZ2dlci5pbmZvKCJDb2xsZWN0aW9uIHN1bW1hcnk6ICVkIGNoYXJzIiwKICAgICAgICAgICAgICAgICAgICAgICAgbGVuKGNvbGxlY3Rpb25fYmxvY2spIGlmIGNvbGxlY3Rpb25fYmxvY2sgZWxzZSAwKQoKICAgICAgICAjIFN0ZXAgMzogQnVpbGQgcHJvbXB0cwogICAgICAgIHVzZXJfcHJvbXB0ID0gYnVpbGRfdXNlcl9wcm9tcHQoCiAgICAgICAgICAgIGNvbW1hbmRlcj1jbWRyWyJuYW1lIl0sCiAgICAgICAgICAgIGNvbW1hbmRlcl90eXBlPWNtZHJbInR5cGVfbGluZSJdLAogICAgICAgICAgICBjb2xvcl9pZGVudGl0eT1jb2xvcl9pZGVudGl0eSwKICAgICAgICAgICAgc3RyYXRlZ3k9c3RyYXRlZ3ksCiAgICAgICAgICAgIHRhcmdldF9icmFja2V0PXRhcmdldF9icmFja2V0LAogICAgICAgICAgICBidWRnZXRfdXNkPWJ1ZGdldF91c2QsCiAgICAgICAgICAgIGJ1ZGdldF9tb2RlPWJ1ZGdldF9tb2RlLAogICAgICAgICAgICBvbWl0X2NhcmRzPW9taXRfY2FyZHMsCiAgICAgICAgICAgIGNvbGxlY3Rpb25fc3VtbWFyeT1jb2xsZWN0aW9uX2Jsb2NrLAogICAgICAgICkKCiAgICAgICAgIyBTdGVwIDQ6IENhbGwgUGVycGxleGl0eSB3aXRoIHN0cnVjdHVyZWQgb3V0cHV0CiAgICAgICAgdXNlX21vZGVsID0gbW9kZWwgb3IgREVDS19HRU5fTU9ERUwKICAgICAgICBsb2dnZXIuaW5mbygiQ2FsbGluZyBQZXJwbGV4aXR5ICglcykgZm9y' +
'IGRlY2sgZ2VuZXJhdGlvbi4uLiIsIHVzZV9tb2RlbCkKCiAgICAgICAgcmVzcG9uc2UgPSBzZWxmLnBwbHguY2hhdF9zdHJ1Y3R1cmVkKAogICAgICAgICAgICBzeXN0ZW1fcHJvbXB0PVNZU1RFTV9QUk9NUFQsCiAgICAgICAgICAgIHVzZXJfcHJvbXB0PXVzZXJfcHJvbXB0LAogICAgICAgICAgICBqc29uX3NjaGVtYT1ERUNLX0xJU1RfU0NIRU1BLAogICAgICAgICAgICBzY2hlbWFfbmFtZT0iRGVja0xpc3QiLAogICAgICAgICAgICBtb2RlbD11c2VfbW9kZWwsCiAgICAgICAgICAgIHRlbXBlcmF0dXJlPURFQ0tfR0VOX1RFTVBFUkFUVVJFLAogICAgICAgICAgICBtYXhfdG9rZW5zPURFQ0tfR0VOX01BWF9UT0tFTlMsCiAgICAgICAgKQoKICAgICAgICBpZiBub3QgcmVzcG9uc2Uub2s6CiAgICAgICAgICAgIHJhaXNlIFZhbHVlRXJyb3IoCiAgICAgICAgICAgICAgICBmIlBlcnBsZXhpdHkgcmV0dXJuZWQgaW52YWxpZCByZXNwb25zZToge3Jlc3BvbnNlLmNvbnRlbnRbOjMwMF19IgogICAgICAgICAgICApCgogICAgICAgIHJhd19kZWNrID0gcmVzcG9uc2UucGFyc2VkX2pzb24KICAgICAgICBsb2dnZXIuaW5mbygiRGVjayBnZW5lcmF0ZWQ6ICVkIGNhcmRzLCBicmFja2V0ICVkIiwKICAgICAgICAgICAgICAgICAgICAgbGVuKHJhd19kZWNrLmdldCgiY2FyZHMiLCBbXSkpLAogICAgICAgICAgICAgICAgICAgICByYXdfZGVjay5nZXQoImJyYWNrZXQiLCB7fSkuZ2V0KCJsZXZlbCIsIDApKQoKICAgICAgICAjIFN0ZXAgNTogQ2hlY2sgb3duZXJzaGlwIGFuZCBidWlsZCBlbnJpY2hlZCBjYXJkIGxpc3QKICAgICAgICBjYXJkc193aXRoX3N0YXR1cyA9IHNlbGYuX2NoZWNrX293bmVyc2hpcChyYXdfZGVjay5nZXQoImNhcmRzIiwgW10pKQoKICAgICAgICAjIFN0ZXAgNjogQ29tcHV0ZSBzdGF0cwogICAgICAgIHN0YXRzID0gc2VsZi5fY29tcHV0ZV9zdGF0cyhjYXJkc193aXRoX3N0YXR1cykKCiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgImNvbW1hbmRlciI6IGNtZHIsCiAgICAgICAgICAgICJjb2xvcl9pZGVudGl0eSI6IGNvbG9yX2lkZW50aXR5LAogICAgICAgICAgICAicmF3X2RlY2siOiByYXdfZGVjaywKICAgICAgICAgICAgImNhcmRzIjogW2MubW9kZWxfZHVtcCgpIGZvciBjIGluIGNhcmRzX3dpdGhfc3RhdHVzXSwKICAgICAgICAgICAgInN0YXRzIjogc3RhdHMsCiAgICAgICAgICAgICJzdHJhdGVneV9zdW1tYXJ5IjogcmF3X2RlY2suZ2V0KCJzdHJhdGVneV9zdW1tYXJ5IiwgIiIpLAogICAgICAgICAgICAiYnJhY2tldCI6IHJhd19kZWNrLmdldCgiYnJhY2tldCIsIHt9KSwKICAgICAgICAgICAgImFyY2hldHlwZSI6IHJhd19kZWNrLmdldCgiYXJjaGV0eXBlIiwgIiIpLAogICAgICAgICAgICAicmVhc29uaW5nIjogcmF3X2RlY2suZ2V0KCJyZWFzb25pbmciLCB7fSksCiAgICAgICAgICAgICJlc3RpbWF0ZWRfdG90YWxfdXNkIjogcmF3X2RlY2suZ2V0KCJlc3RpbWF0ZWRfdG90YWxfdXNkIiwgMCksCiAgICAgICAgICAgICJ0b2tlbnNfdXNlZCI6IHsKICAgICAgICAgICAgICAgICJwcm9tcHQiOiByZXNwb25zZS5wcm9tcHRfdG9rZW5zLAogICAgICAgICAgICAgICAgImNvbXBsZXRpb24iOiByZXNwb25zZS5jb21wbGV0aW9uX3Rva2VucywKICAgICAgICAgICAgfSwKICAgICAgICAgICAgIm1vZGVsIjogcmVzcG9uc2UubW9kZWwsCiAgICAgICAgICAgICJjaXRhdGlvbnMiOiByZXNwb25zZS5jaXRhdGlvbnMsCiAgICAgICAgfQoKICAgICMg4pSA4pSAIFN0ZXAgNTogT3duZXJzaGlwIENoZWNrIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAogICAgZGVmIF9jaGVja19vd25lcnNoaXAoc2VsZiwgY2FyZHM6IExpc3RbZGljdF0pIC0+IExpc3RbRGVja0NhcmRXaXRoU3RhdHVzXToKICAgICAgICAiIiIKICAgICAgICBDcm9zcy1yZWZlcmVuY2UgZ2VuZXJhdGVkIGNhcmRzIGFnYWluc3QgdGhlIGNvbGxlY3Rpb24gREIuCiAgICAgICAgU2V0cyBvd25lZC9zY3J5ZmFsbF9pZC9vd25lZF9xdHkgYW5kIHJlYWwgcHJpY2UuCiAgICAgICAgIiIiCiAgICAgICAgY29ubiA9IHNlbGYuZGJfY29ubl9mYWN0b3J5KCkKICAgICAgICBlbnJpY2hlZCA9IFtdCgogICAgICAgIGZvciBjYXJkIGluIGNhcmRzOgogICAgICAgICAgICBuYW1lID0gY2FyZC5nZXQoIm5hbWUiLCAiIikKICAgICAgICAgICAgaWYgbm90IG5h' +
'bWU6CiAgICAgICAgICAgICAgICBjb250aW51ZQoKICAgICAgICAgICAgIyBMb29rIHVwIGluIGNvbGxlY3Rpb24KICAgICAgICAgICAgcm93ID0gY29ubi5leGVjdXRlKAogICAgICAgICAgICAgICAgIlNFTEVDVCBuYW1lLCBzY3J5ZmFsbF9pZCwgcXVhbnRpdHksIHRjZ19wcmljZSwgdHlwZV9saW5lLCBjbWMgIgogICAgICAgICAgICAgICAgIkZST00gY29sbGVjdGlvbl9lbnRyaWVzIFdIRVJFIG5hbWUgPSA/IENPTExBVEUgTk9DQVNFIExJTUlUIDEiLAogICAgICAgICAgICAgICAgKG5hbWUsKQogICAgICAgICAgICApLmZldGNob25lKCkKCiAgICAgICAgICAgIGlzX293bmVkID0gYm9vbChyb3cgYW5kIHJvd1sicXVhbnRpdHkiXSBhbmQgcm93WyJxdWFudGl0eSJdID4gMCkKCiAgICAgICAgICAgIGVucmljaGVkX2NhcmQgPSBEZWNrQ2FyZFdpdGhTdGF0dXMoCiAgICAgICAgICAgICAgICBuYW1lPXJvd1sibmFtZSJdIGlmIHJvdyBlbHNlIG5hbWUsCiAgICAgICAgICAgICAgICBjb3VudD1jYXJkLmdldCgiY291bnQiLCAxKSwKICAgICAgICAgICAgICAgIGNhdGVnb3J5PWNhcmQuZ2V0KCJjYXRlZ29yeSIsICIiKSwKICAgICAgICAgICAgICAgIHJvbGVfdGFncz1jYXJkLmdldCgicm9sZV90YWdzIiwgW10pLAogICAgICAgICAgICAgICAgcmVhc29uPWNhcmQuZ2V0KCJyZWFzb24iLCAiIiksCiAgICAgICAgICAgICAgICBlc3RpbWF0ZWRfcHJpY2VfdXNkPSgKICAgICAgICAgICAgICAgICAgICByb3VuZChyb3dbInRjZ19wcmljZSJdLCAyKSBpZiByb3cgYW5kIHJvd1sidGNnX3ByaWNlIl0KICAgICAgICAgICAgICAgICAgICBlbHNlIGNhcmQuZ2V0KCJlc3RpbWF0ZWRfcHJpY2VfdXNkIiwgMCkKICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICBzeW5lcmd5X3dpdGg9Y2FyZC5nZXQoInN5bmVyZ3lfd2l0aCIsIFtdKSwKICAgICAgICAgICAgICAgIG93bmVkPWlzX293bmVkLAogICAgICAgICAgICAgICAgb3duZWRfcXR5PWludChyb3dbInF1YW50aXR5Il0pIGlmIHJvdyBhbmQgcm93WyJxdWFudGl0eSJdIGVsc2UgMCwKICAgICAgICAgICAgICAgIHNjcnlmYWxsX2lkPXJvd1sic2NyeWZhbGxfaWQiXSBpZiByb3cgZWxzZSAiIiwKICAgICAgICAgICAgICAgIHN0YXR1cz0ib3duZWQiIGlmIGlzX293bmVkIGVsc2UgIm1pc3NpbmciLAogICAgICAgICAgICApCiAgICAgICAgICAgIGVucmljaGVkLmFwcGVuZChlbnJpY2hlZF9jYXJkKQoKICAgICAgICByZXR1cm4gZW5yaWNoZWQKCiAgICAjIOKUgOKUgCBTdGVwIDY6IFNtYXJ0IFN1YnN0aXR1dGlvbiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKICAgIGRlZiBydW5fc3Vic3RpdHV0aW9uKAogICAgICAgIHNlbGYsCiAgICAgICAgY2FyZHM6IExpc3RbRGVja0NhcmRXaXRoU3RhdHVzXSwKICAgICAgICBjb21tYW5kZXI6IGRpY3QsCiAgICAgICAgc3RyYXRlZ3k6IHN0ciA9ICIiLAogICAgKSAtPiBTdWJzdGl0dXRpb25CYXRjaFJlc3VsdDoKICAgICAgICAiIiIKICAgICAgICBSdW4gdGhlIFNtYXJ0IFN1YnN0aXR1dGlvbiBFbmdpbmUgb24gbWlzc2luZyBjYXJkcy4KCiAgICAgICAgUGlwZWxpbmU6CiAgICAgICAgICBhKSBJZGVudGlmeSBtaXNzaW5nIGNhcmRzCiAgICAgICAgICBiKSBGb3IgZWFjaDogdHJ5IGVtYmVkZGluZyBzaW1pbGFyaXR5IChmcmVlLCBmYXN0KQogICAgICAgICAgYykgRm9yIGxvdy1jb25maWRlbmNlIG1hdGNoZXM6IGJhdGNoIFBlcnBsZXhpdHkgZmFsbGJhY2sKICAgICAgICAgIGQpIEF1dG8tc2VsZWN0IGJlc3Qgc3Vic3RpdHV0ZSBwZXIgY2FyZAoKICAgICAgICBSZXR1cm5zIFN1YnN0aXR1dGlvbkJhdGNoUmVzdWx0IHdpdGggYWxsIGNhcmRzIHVwZGF0ZWQuCiAgICAgICAgIiIiCiAgICAgICAgY29sb3JfaWRlbnRpdHkgPSBjb21tYW5kZXIuZ2V0KCJjb2xvcl9pZGVudGl0eSIsIFtdKQogICAgICAgIG1pc3NpbmcgPSBbYyBmb3IgYyBpbiBjYXJkcyBpZiBub3QgYy5vd25lZF0KICAgICAgICBvd25lZCA9IFtjIGZvciBjIGluIGNhcmRzIGlmIGMub3duZWRdCgogICAgICAgIGlmIG5vdCBtaXNzaW5nOgogICAgICAgICAgICByZXR1cm4gU3Vic3RpdHV0aW9uQmF0Y2hSZXN1bHQoCiAgICAgICAgICAgICAgICB0b3RhbF9jYXJkcz1sZW4oY2FyZHMpLAogICAgICAgICAgICAgICAgb3duZWRfY291bnQ9bGVuKG93bmVkKSwKICAgICAgICAgICAgICAgIHN1' +
'YnN0aXR1dGVkX2NvdW50PTAsCiAgICAgICAgICAgICAgICBtaXNzaW5nX2NvdW50PTAsCiAgICAgICAgICAgICAgICBjYXJkcz1jYXJkcywKICAgICAgICAgICAgKQoKICAgICAgICBsb2dnZXIuaW5mbygiU3Vic3RpdHV0aW9uOiAlZCBtaXNzaW5nIC8gJWQgb3duZWQiLCBsZW4obWlzc2luZyksIGxlbihvd25lZCkpCgogICAgICAgICMgQnVpbGQgbGlzdCBvZiBvd25lZCBjYXJkIG5hbWVzIGZvciBzdWJzdGl0dXRpb24gcG9vbAogICAgICAgIGNvbm4gPSBzZWxmLmRiX2Nvbm5fZmFjdG9yeSgpCiAgICAgICAgb3duZWRfcG9vbF9yb3dzID0gY29ubi5leGVjdXRlKAogICAgICAgICAgICAiU0VMRUNUIERJU1RJTkNUIG5hbWUgRlJPTSBjb2xsZWN0aW9uX2VudHJpZXMgV0hFUkUgcXVhbnRpdHkgPiAwIgogICAgICAgICkuZmV0Y2hhbGwoKQogICAgICAgIG93bmVkX3Bvb2wgPSBbclsibmFtZSJdIGZvciByIGluIG93bmVkX3Bvb2xfcm93c10KCiAgICAgICAgIyBFeGNsdWRlIGNhcmRzIGFscmVhZHkgaW4gdGhlIGRlY2sKICAgICAgICBkZWNrX25hbWVzID0gc2V0KGMubmFtZS5sb3dlcigpIGZvciBjIGluIGNhcmRzKQogICAgICAgIGF2YWlsYWJsZV9wb29sID0gW24gZm9yIG4gaW4gb3duZWRfcG9vbCBpZiBuLmxvd2VyKCkgbm90IGluIGRlY2tfbmFtZXNdCgogICAgICAgICMgYSkgRW1iZWRkaW5nIHBhc3MKICAgICAgICBuZWVkc19wcGx4X2ZhbGxiYWNrID0gW10KICAgICAgICBmb3IgY2FyZCBpbiBtaXNzaW5nOgogICAgICAgICAgICBlbWJlZGRpbmdfYWx0cyA9IHNlbGYuX2VtYmVkZGluZ19zdWJzdGl0dXRpb24oCiAgICAgICAgICAgICAgICBjYXJkLCBjb2xvcl9pZGVudGl0eSwgYXZhaWxhYmxlX3Bvb2wKICAgICAgICAgICAgKQogICAgICAgICAgICBjYXJkLmFsdGVybmF0aXZlcyA9IGVtYmVkZGluZ19hbHRzCgogICAgICAgICAgICAjIENoZWNrIGlmIGJlc3QgbWF0Y2ggbWVldHMgdGhyZXNob2xkCiAgICAgICAgICAgIGlmIGVtYmVkZGluZ19hbHRzIGFuZCBlbWJlZGRpbmdfYWx0c1swXS5zaW1pbGFyaXR5X3Njb3JlID49IFNVQlNUSVRVVElPTl9NSU5fU0lNSUxBUklUWToKICAgICAgICAgICAgICAgIGNhcmQuc2VsZWN0ZWRfc3Vic3RpdHV0ZSA9IGVtYmVkZGluZ19hbHRzWzBdLm5hbWUKICAgICAgICAgICAgICAgIGNhcmQuc3RhdHVzID0gInN1YnN0aXR1dGVkIgogICAgICAgICAgICAgICAgIyBSZW1vdmUgc2VsZWN0ZWQgZnJvbSBwb29sCiAgICAgICAgICAgICAgICBpZiBjYXJkLnNlbGVjdGVkX3N1YnN0aXR1dGUubG93ZXIoKSBpbiBbbi5sb3dlcigpIGZvciBuIGluIGF2YWlsYWJsZV9wb29sXToKICAgICAgICAgICAgICAgICAgICBhdmFpbGFibGVfcG9vbCA9IFtuIGZvciBuIGluIGF2YWlsYWJsZV9wb29sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiBuLmxvd2VyKCkgIT0gY2FyZC5zZWxlY3RlZF9zdWJzdGl0dXRlLmxvd2VyKCldCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBuZWVkc19wcGx4X2ZhbGxiYWNrLmFwcGVuZChjYXJkKQoKICAgICAgICAjIGIpIFBlcnBsZXhpdHkgZmFsbGJhY2sgZm9yIGxvdy1jb25maWRlbmNlIG1hdGNoZXMKICAgICAgICBpZiBuZWVkc19wcGx4X2ZhbGxiYWNrIGFuZCBTVUJTVElUVVRJT05fVVNFX1BQTFhfRkFMTEJBQ0s6CiAgICAgICAgICAgIHNlbGYuX3BwbHhfc3Vic3RpdHV0aW9uKAogICAgICAgICAgICAgICAgbmVlZHNfcHBseF9mYWxsYmFjaywgYXZhaWxhYmxlX3Bvb2wsCiAgICAgICAgICAgICAgICBjb21tYW5kZXIsIHN0cmF0ZWd5CiAgICAgICAgICAgICkKCiAgICAgICAgIyBDb3VudCByZXN1bHRzCiAgICAgICAgc3Vic3RpdHV0ZWQgPSBzdW0oMSBmb3IgYyBpbiBjYXJkcyBpZiBjLnN0YXR1cyA9PSAic3Vic3RpdHV0ZWQiKQogICAgICAgIHN0aWxsX21pc3NpbmcgPSBzdW0oMSBmb3IgYyBpbiBjYXJkcyBpZiBjLnN0YXR1cyA9PSAibWlzc2luZyIpCgogICAgICAgIHJldHVybiBTdWJzdGl0dXRpb25CYXRjaFJlc3VsdCgKICAgICAgICAgICAgdG90YWxfY2FyZHM9bGVuKGNhcmRzKSwKICAgICAgICAgICAgb3duZWRfY291bnQ9bGVuKG93bmVkKSwKICAgICAgICAgICAgc3Vic3RpdHV0ZWRfY291bnQ9c3Vic3RpdHV0ZWQsCiAgICAgICAgICAgIG1pc3NpbmdfY291bnQ9c3RpbGxfbWlzc2luZywKICAgICAgICAgICAgY2FyZHM9Y2FyZHMsCiAgICAgICAgKQoKICAgIGRlZiBfZW1iZWRkaW5nX3N1YnN0aXR1dGlvbigKICAgICAg' +
'ICBzZWxmLAogICAgICAgIGNhcmQ6IERlY2tDYXJkV2l0aFN0YXR1cywKICAgICAgICBjb2xvcl9pZGVudGl0eTogTGlzdFtzdHJdLAogICAgICAgIGF2YWlsYWJsZV9wb29sOiBMaXN0W3N0cl0sCiAgICApIC0+IExpc3RbQ2FyZEFsdGVybmF0aXZlXToKICAgICAgICAiIiJGaW5kIGVtYmVkZGluZy1zaW1pbGFyIG93bmVkIGNhcmRzIGFzIHN1YnN0aXR1dGVzLiIiIgogICAgICAgIGlmIG5vdCBzZWxmLmVtYmVkZGluZ19pbmRleCBvciBub3Qgc2VsZi5lbWJlZGRpbmdfaW5kZXgubG9hZGVkOgogICAgICAgICAgICByZXR1cm4gW10KCiAgICAgICAgIyBVc2UgdGhlIGVtYmVkZGluZ3Mgc2VhcmNoIHRvIGZpbmQgc2ltaWxhciBjYXJkcwogICAgICAgIG1hdGNoZXMgPSBzZWxmLmVtYmVkZGluZ19pbmRleC5zZWFyY2hfc2ltaWxhcigKICAgICAgICAgICAgcXVlcnlfY2FyZD1jYXJkLm5hbWUsCiAgICAgICAgICAgIGNvbG9yX2ZpbHRlcj1jb2xvcl9pZGVudGl0eSBpZiBjb2xvcl9pZGVudGl0eSBlbHNlIE5vbmUsCiAgICAgICAgICAgIHR5cGVfZmlsdGVyPWNhcmQuY2F0ZWdvcnkgaWYgY2FyZC5jYXRlZ29yeSBlbHNlIE5vbmUsCiAgICAgICAgICAgIGV4Y2x1ZGVfY2FyZHM9W2NhcmQubmFtZV0sCiAgICAgICAgICAgIHRvcF9uPVNVQlNUSVRVVElPTl9NQVhfQUxURVJOQVRJVkVTICogMywgICMgT3Zlci1mZXRjaCwgdGhlbiBmaWx0ZXIgdG8gb3duZWQKICAgICAgICApCgogICAgICAgICMgRmlsdGVyIHRvIG9ubHkgY2FyZHMgaW4gdGhlIGF2YWlsYWJsZSBwb29sCiAgICAgICAgcG9vbF9sb3dlciA9IHNldChuLmxvd2VyKCkgZm9yIG4gaW4gYXZhaWxhYmxlX3Bvb2wpCiAgICAgICAgYWx0ZXJuYXRpdmVzID0gW10KICAgICAgICBmb3IgbWF0Y2ggaW4gbWF0Y2hlczoKICAgICAgICAgICAgaWYgbWF0Y2gubmFtZS5sb3dlcigpIGluIHBvb2xfbG93ZXI6CiAgICAgICAgICAgICAgICAjIENvbXB1dGUgcm9sZSBvdmVybGFwCiAgICAgICAgICAgICAgICBtYXRjaF9yb2xlcyA9IFtdICAjIFdvdWxkIG5lZWQgY2FyZCdzIHJvbGVfdGFncyBmcm9tIERCCiAgICAgICAgICAgICAgICByb2xlX292ZXJsYXAgPSBsaXN0KHNldChjYXJkLnJvbGVfdGFncykgJiBzZXQobWF0Y2hfcm9sZXMpKSBpZiBtYXRjaF9yb2xlcyBlbHNlIFtdCgogICAgICAgICAgICAgICAgYWx0ZXJuYXRpdmVzLmFwcGVuZChDYXJkQWx0ZXJuYXRpdmUoCiAgICAgICAgICAgICAgICAgICAgbmFtZT1tYXRjaC5uYW1lLAogICAgICAgICAgICAgICAgICAgIHNpbWlsYXJpdHlfc2NvcmU9bWF0Y2guc2ltaWxhcml0eSwKICAgICAgICAgICAgICAgICAgICByZWFzb249ZiJTaW1pbGFyIHRvIHtjYXJkLm5hbWV9IChjb3NpbmUgc2ltOiB7bWF0Y2guc2ltaWxhcml0eTouM2Z9KSIsCiAgICAgICAgICAgICAgICAgICAgc291cmNlPSJlbWJlZGRpbmciLAogICAgICAgICAgICAgICAgICAgIHJvbGVfb3ZlcmxhcD1yb2xlX292ZXJsYXAsCiAgICAgICAgICAgICAgICAgICAgY21jX2RlbHRhPW1hdGNoLm1hbmFfdmFsdWUgLSAoY2FyZC5lc3RpbWF0ZWRfcHJpY2VfdXNkIG9yIDApLAogICAgICAgICAgICAgICAgKSkKCiAgICAgICAgICAgICAgICBpZiBsZW4oYWx0ZXJuYXRpdmVzKSA+PSBTVUJTVElUVVRJT05fTUFYX0FMVEVSTkFUSVZFUzoKICAgICAgICAgICAgICAgICAgICBicmVhawoKICAgICAgICByZXR1cm4gYWx0ZXJuYXRpdmVzCgogICAgZGVmIF9wcGx4X3N1YnN0aXR1dGlvbigKICAgICAgICBzZWxmLAogICAgICAgIG1pc3NpbmdfY2FyZHM6IExpc3RbRGVja0NhcmRXaXRoU3RhdHVzXSwKICAgICAgICBhdmFpbGFibGVfcG9vbDogTGlzdFtzdHJdLAogICAgICAgIGNvbW1hbmRlcjogZGljdCwKICAgICAgICBzdHJhdGVneTogc3RyLAogICAgKToKICAgICAgICAiIiIKICAgICAgICBCYXRjaCBQZXJwbGV4aXR5IGZhbGxiYWNrIGZvciBjYXJkcyB3aXRoIGxvdyBlbWJlZGRpbmcgY29uZmlkZW5jZS4KICAgICAgICBNdXRhdGVzIHRoZSBjYXJkcyBpbi1wbGFjZSB3aXRoIHN1YnN0aXR1dGlvbiBkYXRhLgogICAgICAgICIiIgogICAgICAgIGlmIG5vdCBhdmFpbGFibGVfcG9vbDoKICAgICAgICAgICAgcmV0dXJuCgogICAgICAgICMgQnVpbGQgdGhlIHJlcXVlc3QKICAgICAgICBtaXNzaW5nX2RpY3RzID0gWwogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAibmFtZSI6IGMubmFtZSwKICAgICAgICAgICAgICAgICJyb2xlX3RhZ3MiOiBjLnJvbGVfdGFncywKICAgICAgICAgICAg' +
'ICAgICJjYXRlZ29yeSI6IGMuY2F0ZWdvcnksCiAgICAgICAgICAgICAgICAicmVhc29uIjogYy5yZWFzb24sCiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm9yIGMgaW4gbWlzc2luZ19jYXJkcwogICAgICAgIF0KCiAgICAgICAgdXNlcl9wcm9tcHQgPSBidWlsZF9zdWJzdGl0dXRpb25fcHJvbXB0KAogICAgICAgICAgICBtaXNzaW5nX2NhcmRzPW1pc3NpbmdfZGljdHMsCiAgICAgICAgICAgIGFsbG93ZWRfY2FyZHM9YXZhaWxhYmxlX3Bvb2xbOjIwMF0sICAjIExpbWl0IHRvIGF2b2lkIHRva2VuIG92ZXJmbG93CiAgICAgICAgICAgIGNvbW1hbmRlcj1jb21tYW5kZXIuZ2V0KCJuYW1lIiwgIiIpLAogICAgICAgICAgICBjb2xvcl9pZGVudGl0eT1jb21tYW5kZXIuZ2V0KCJjb2xvcl9pZGVudGl0eSIsIFtdKSwKICAgICAgICAgICAgc3RyYXRlZ3k9c3RyYXRlZ3ksCiAgICAgICAgKQoKICAgICAgICB0cnk6CiAgICAgICAgICAgIGZyb20gLi5zY2hlbWFzLnN1YnN0aXR1dGlvbl9zY2hlbWEgaW1wb3J0IFNVQlNUSVRVVElPTl9SRVNQT05TRV9TQ0hFTUEKICAgICAgICAgICAgcmVzcG9uc2UgPSBzZWxmLnBwbHguY2hhdF9zdHJ1Y3R1cmVkKAogICAgICAgICAgICAgICAgc3lzdGVtX3Byb21wdD1TVUJTVElUVVRJT05fU1lTVEVNLAogICAgICAgICAgICAgICAgdXNlcl9wcm9tcHQ9dXNlcl9wcm9tcHQsCiAgICAgICAgICAgICAgICBqc29uX3NjaGVtYT1TVUJTVElUVVRJT05fUkVTUE9OU0VfU0NIRU1BLAogICAgICAgICAgICAgICAgc2NoZW1hX25hbWU9IlN1YnN0aXR1dGlvblJlc3BvbnNlIiwKICAgICAgICAgICAgICAgIG1vZGVsPVNVQlNUSVRVVElPTl9NT0RFTCwKICAgICAgICAgICAgICAgIHRlbXBlcmF0dXJlPTAuMSwKICAgICAgICAgICAgICAgIG1heF90b2tlbnM9NDA5NiwKICAgICAgICAgICAgKQoKICAgICAgICAgICAgaWYgbm90IHJlc3BvbnNlLm9rOgogICAgICAgICAgICAgICAgbG9nZ2VyLndhcm5pbmcoIlBlcnBsZXhpdHkgc3Vic3RpdHV0aW9uIGZhbGxiYWNrIGZhaWxlZCDigJQgbm9uLUpTT04gcmVzcG9uc2UiKQogICAgICAgICAgICAgICAgcmV0dXJuCgogICAgICAgICAgICBzdWJzID0gcmVzcG9uc2UucGFyc2VkX2pzb24uZ2V0KCJzdWJzdGl0dXRpb25zIiwgW10pCiAgICAgICAgICAgIGxvZ2dlci5pbmZvKCJQZXJwbGV4aXR5IHN1Z2dlc3RlZCAlZCBzdWJzdGl0dXRpb25zIiwgbGVuKHN1YnMpKQoKICAgICAgICAgICAgIyBBcHBseSBzdWJzdGl0dXRpb25zCiAgICAgICAgICAgIGNhcmRfYnlfbmFtZSA9IHtjLm5hbWUubG93ZXIoKTogYyBmb3IgYyBpbiBtaXNzaW5nX2NhcmRzfQogICAgICAgICAgICBmb3Igc3ViIGluIHN1YnM6CiAgICAgICAgICAgICAgICBvcmlnID0gc3ViLmdldCgib3JpZ2luYWwiLCAiIikubG93ZXIoKQogICAgICAgICAgICAgICAgc3Vic3RpdHV0ZSA9IHN1Yi5nZXQoInN1YnN0aXR1dGUiLCAiIikKICAgICAgICAgICAgICAgIHJlYXNvbiA9IHN1Yi5nZXQoInJlYXNvbiIsICIiKQoKICAgICAgICAgICAgICAgIGlmIG9yaWcgaW4gY2FyZF9ieV9uYW1lIGFuZCBzdWJzdGl0dXRlOgogICAgICAgICAgICAgICAgICAgIGNhcmQgPSBjYXJkX2J5X25hbWVbb3JpZ10KICAgICAgICAgICAgICAgICAgICAjIEFkZCBhcyB0b3AgYWx0ZXJuYXRpdmUKICAgICAgICAgICAgICAgICAgICBwcGx4X2FsdCA9IENhcmRBbHRlcm5hdGl2ZSgKICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT1zdWJzdGl0dXRlLAogICAgICAgICAgICAgICAgICAgICAgICBzaW1pbGFyaXR5X3Njb3JlPTAuODAsICAjIE5vbWluYWwgc2NvcmUgZm9yIFBlcnBsZXhpdHkgc3VnZ2VzdGlvbnMKICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uPXJlYXNvbiwKICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlPSJwZXJwbGV4aXR5IiwKICAgICAgICAgICAgICAgICAgICAgICAgcm9sZV9vdmVybGFwPXN1Yi5nZXQoInJvbGVfb3ZlcmxhcCIsIFtdKSwKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgIyBJbnNlcnQgYXQgZnJvbnQKICAgICAgICAgICAgICAgICAgICBjYXJkLmFsdGVybmF0aXZlcy5pbnNlcnQoMCwgcHBseF9hbHQpCiAgICAgICAgICAgICAgICAgICAgY2FyZC5zZWxlY3RlZF9zdWJzdGl0dXRlID0gc3Vic3RpdHV0ZQogICAgICAgICAgICAgICAgICAgIGNhcmQuc3RhdHVzID0gInN1YnN0aXR1dGVkIgoKICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAg' +
'IGxvZ2dlci5lcnJvcigiUGVycGxleGl0eSBzdWJzdGl0dXRpb24gZmFsbGJhY2sgZXJyb3I6ICVzIiwgZSkKCiAgICAjIOKUgOKUgCBTdGF0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKICAgIEBzdGF0aWNtZXRob2QKICAgIGRlZiBfY29tcHV0ZV9zdGF0cyhjYXJkczogTGlzdFtEZWNrQ2FyZFdpdGhTdGF0dXNdKSAtPiBkaWN0OgogICAgICAgICIiIkNvbXB1dGUgZGVjayBzdGF0aXN0aWNzIGZyb20gdGhlIGVucmljaGVkIGNhcmQgbGlzdC4iIiIKICAgICAgICBieV9jYXRlZ29yeSA9IHt9CiAgICAgICAgYnlfc3RhdHVzID0geyJvd25lZCI6IDAsICJzdWJzdGl0dXRlZCI6IDAsICJtaXNzaW5nIjogMH0KICAgICAgICB0b3RhbF9wcmljZSA9IDAuMAogICAgICAgIG93bmVkX3ByaWNlID0gMC4wCiAgICAgICAgbWlzc2luZ19wcmljZSA9IDAuMAogICAgICAgIHJvbGVfY291bnRzID0ge30KCiAgICAgICAgZm9yIGNhcmQgaW4gY2FyZHM6CiAgICAgICAgICAgIGNhdCA9IGNhcmQuY2F0ZWdvcnkgb3IgIk90aGVyIgogICAgICAgICAgICBieV9jYXRlZ29yeVtjYXRdID0gYnlfY2F0ZWdvcnkuZ2V0KGNhdCwgMCkgKyBjYXJkLmNvdW50CiAgICAgICAgICAgIGJ5X3N0YXR1c1tjYXJkLnN0YXR1c10gPSBieV9zdGF0dXMuZ2V0KGNhcmQuc3RhdHVzLCAwKSArIDEKICAgICAgICAgICAgcHJpY2UgPSBjYXJkLmVzdGltYXRlZF9wcmljZV91c2QgKiBjYXJkLmNvdW50CiAgICAgICAgICAgIHRvdGFsX3ByaWNlICs9IHByaWNlCiAgICAgICAgICAgIGlmIGNhcmQub3duZWQ6CiAgICAgICAgICAgICAgICBvd25lZF9wcmljZSArPSBwcmljZQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgbWlzc2luZ19wcmljZSArPSBwcmljZQogICAgICAgICAgICBmb3Igcm9sZSBpbiBjYXJkLnJvbGVfdGFnczoKICAgICAgICAgICAgICAgIHJvbGVfY291bnRzW3JvbGVdID0gcm9sZV9jb3VudHMuZ2V0KHJvbGUsIDApICsgMQoKICAgICAgICBsYW5kX2NvdW50ID0gYnlfY2F0ZWdvcnkuZ2V0KCJMYW5kIiwgMCkKICAgICAgICBub25sYW5kX2NvdW50ID0gc3VtKHYgZm9yIGssIHYgaW4gYnlfY2F0ZWdvcnkuaXRlbXMoKSBpZiBrICE9ICJMYW5kIikKCiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgInRvdGFsX2NhcmRzIjogc3VtKGMuY291bnQgZm9yIGMgaW4gY2FyZHMpLAogICAgICAgICAgICAibGFuZF9jb3VudCI6IGxhbmRfY291bnQsCiAgICAgICAgICAgICJub25sYW5kX2NvdW50Ijogbm9ubGFuZF9jb3VudCwKICAgICAgICAgICAgImJ5X2NhdGVnb3J5IjogYnlfY2F0ZWdvcnksCiAgICAgICAgICAgICJieV9zdGF0dXMiOiBieV9zdGF0dXMsCiAgICAgICAgICAgICJyb2xlX2NvdW50cyI6IHJvbGVfY291bnRzLAogICAgICAgICAgICAidG90YWxfcHJpY2VfdXNkIjogcm91bmQodG90YWxfcHJpY2UsIDIpLAogICAgICAgICAgICAib3duZWRfcHJpY2VfdXNkIjogcm91bmQob3duZWRfcHJpY2UsIDIpLAogICAgICAgICAgICAibWlzc2luZ19wcmljZV91c2QiOiByb3VuZChtaXNzaW5nX3ByaWNlLCAyKSwKICAgICAgICB9Cg=='
'IGRlY2sgZ2VuZXJhdGlvbi4uLiIsIHVzZV9tb2RlbCkKCiAgICAgICAgcmVzcG9uc2UgPSBzZWxmLnBwbHguY2hhdF9zdHJ1Y3R1cmVkKAogICAgICAgICAgICBzeXN0ZW1fcHJvbXB0PVNZU1RFTV9QUk9NUFQsCiAgICAgICAgICAgIHVzZXJfcHJvbXB0PXVzZXJfcHJvbXB0LAogICAgICAgICAgICBqc29uX3NjaGVtYT1ERUNLX0xJU1RfU0NIRU1BLAogICAgICAgICAgICBzY2hlbWFfbmFtZT0iRGVja0xpc3QiLAogICAgICAgICAgICBtb2RlbD11c2VfbW9kZWwsCiAgICAgICAgICAgIHRlbXBlcmF0dXJlPURFQ0tfR0VOX1RFTVBFUkFUVVJFLAogICAgICAgICAgICBtYXhfdG9rZW5zPURFQ0tfR0VOX01BWF9UT0tFTlMsCiAgICAgICAgKQoKICAgICAgICBpZiBub3QgcmVzcG9uc2Uub2s6CiAgICAgICAgICAgIHJhaXNlIFZhbHVlRXJyb3IoCiAgICAgICAgICAgICAgICBmIlBlcnBsZXhpdHkgcmV0dXJuZWQgaW52YWxpZCByZXNwb25zZToge3Jlc3BvbnNlLmNvbnRlbnRbOjMwMF19IgogICAgICAgICAgICApCgogICAgICAgIHJhd19kZWNrID0gcmVzcG9uc2UucGFyc2VkX2pzb24KICAgICAgICBjYXJkX2NvdW50ID0gbGVuKHJhd19kZWNrLmdldCgiY2FyZHMiLCBbXSkpCiAgICAgICAgdHJ1bmNhdGVkID0gY2FyZF9jb3VudCA8IDkwICAjIENvbW1hbmRlciBkZWNrcyBzaG91bGQgaGF2ZSB+MTAwIGNhcmRzCiAgICAgICAgbG9nZ2VyLmluZm8oIkRlY2sgZ2VuZXJhdGVkOiAlZCBjYXJkcywgYnJhY2tldCAlZCVzIiwKICAgICAgICAgICAgICAgICAgICAgY2FyZF9jb3VudCwKICAgICAgICAgICAgICAgICAgICAgcmF3X2RlY2suZ2V0KCJicmFja2V0Iiwge30pLmdldCgibGV2ZWwiLCAwKSwKICAgICAgICAgICAgICAgICAgICAgIiAoVFJVTkNBVEVEIOKAlCByZXNwb25zZSBtYXkgaGF2ZSBoaXQgdG9rZW4gbGltaXQpIiBpZiB0cnVuY2F0ZWQgZWxzZSAiIikKCiAgICAgICAgIyBTdGVwIDU6IENoZWNrIG93bmVyc2hpcCBhbmQgYnVpbGQgZW5yaWNoZWQgY2FyZCBsaXN0CiAgICAgICAgY2FyZHNfd2l0aF9zdGF0dXMgPSBzZWxmLl9jaGVja19vd25lcnNoaXAocmF3X2RlY2suZ2V0KCJjYXJkcyIsIFtdKSkKCiAgICAgICAgIyBTdGVwIDY6IENvbXB1dGUgc3RhdHMKICAgICAgICBzdGF0cyA9IHNlbGYuX2NvbXB1dGVfc3RhdHMoY2FyZHNfd2l0aF9zdGF0dXMpCgogICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICJjb21tYW5kZXIiOiBjbWRyLAogICAgICAgICAgICAiY29sb3JfaWRlbnRpdHkiOiBjb2xvcl9pZGVudGl0eSwKICAgICAgICAgICAgInJhd19kZWNrIjogcmF3X2RlY2ssCiAgICAgICAgICAgICJjYXJkcyI6IFtjLm1vZGVsX2R1bXAoKSBmb3IgYyBpbiBjYXJkc193aXRoX3N0YXR1c10sCiAgICAgICAgICAgICJzdGF0cyI6IHN0YXRzLAogICAgICAgICAgICAic3RyYXRlZ3lfc3VtbWFyeSI6IHJhd19kZWNrLmdldCgic3RyYXRlZ3lfc3VtbWFyeSIsICIiKSwKICAgICAgICAgICAgImJyYWNrZXQiOiByYXdfZGVjay5nZXQoImJyYWNrZXQiLCB7fSksCiAgICAgICAgICAgICJhcmNoZXR5cGUiOiByYXdfZGVjay5nZXQoImFyY2hldHlwZSIsICIiKSwKICAgICAgICAgICAgInJlYXNvbmluZyI6IHJhd19kZWNrLmdldCgicmVhc29uaW5nIiwge30pLAogICAgICAgICAgICAiZXN0aW1hdGVkX3RvdGFsX3VzZCI6IHJhd19kZWNrLmdldCgiZXN0aW1hdGVkX3RvdGFsX3VzZCIsIDApLAogICAgICAgICAgICAidG9rZW5zX3VzZWQiOiB7CiAgICAgICAgICAgICAgICAicHJvbXB0IjogcmVzcG9uc2UucHJvbXB0X3Rva2VucywKICAgICAgICAgICAgICAgICJjb21wbGV0aW9uIjogcmVzcG9uc2UuY29tcGxldGlvbl90b2tlbnMsCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJtb2RlbCI6IHJlc3BvbnNlLm1vZGVsLAogICAgICAgICAgICAiY2l0YXRpb25zIjogcmVzcG9uc2UuY2l0YXRpb25zLAogICAgICAgICAgICAidHJ1bmNhdGVkIjogdHJ1bmNhdGVkLAogICAgICAgIH0KCiAgICAjIOKUgOKUgCBTdGVwIDU6IE93bmVyc2hpcCBDaGVjayDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKICAgIGRlZiBfY2hlY2tfb3duZXJzaGlwKHNlbGYsIGNhcmRzOiBMaXN0W2RpY3RdKSAtPiBMaXN0W0RlY2tDYXJkV2l0aFN0YXR1c106CiAgICAgICAgIiIiCiAgICAgICAgQ3Jvc3MtcmVmZXJlbmNlIGdlbmVyYXRlZCBjYXJkcyBh' +
'Z2FpbnN0IHRoZSBjb2xsZWN0aW9uIERCLgogICAgICAgIFNldHMgb3duZWQvc2NyeWZhbGxfaWQvb3duZWRfcXR5IGFuZCByZWFsIHByaWNlLgogICAgICAgICIiIgogICAgICAgIGNvbm4gPSBzZWxmLmRiX2Nvbm5fZmFjdG9yeSgpCiAgICAgICAgZW5yaWNoZWQgPSBbXQoKICAgICAgICBmb3IgY2FyZCBpbiBjYXJkczoKICAgICAgICAgICAgbmFtZSA9IGNhcmQuZ2V0KCJuYW1lIiwgIiIpCiAgICAgICAgICAgIGlmIG5vdCBuYW1lOgogICAgICAgICAgICAgICAgY29udGludWUKCiAgICAgICAgICAgICMgTG9vayB1cCBpbiBjb2xsZWN0aW9uCiAgICAgICAgICAgIHJvdyA9IGNvbm4uZXhlY3V0ZSgKICAgICAgICAgICAgICAgICJTRUxFQ1QgbmFtZSwgc2NyeWZhbGxfaWQsIHF1YW50aXR5LCB0Y2dfcHJpY2UsIHR5cGVfbGluZSwgY21jICIKICAgICAgICAgICAgICAgICJGUk9NIGNvbGxlY3Rpb25fZW50cmllcyBXSEVSRSBuYW1lID0gPyBDT0xMQVRFIE5PQ0FTRSBMSU1JVCAxIiwKICAgICAgICAgICAgICAgIChuYW1lLCkKICAgICAgICAgICAgKS5mZXRjaG9uZSgpCgogICAgICAgICAgICBpc19vd25lZCA9IGJvb2wocm93IGFuZCByb3dbInF1YW50aXR5Il0gYW5kIHJvd1sicXVhbnRpdHkiXSA+IDApCgogICAgICAgICAgICBlbnJpY2hlZF9jYXJkID0gRGVja0NhcmRXaXRoU3RhdHVzKAogICAgICAgICAgICAgICAgbmFtZT1yb3dbIm5hbWUiXSBpZiByb3cgZWxzZSBuYW1lLAogICAgICAgICAgICAgICAgY291bnQ9Y2FyZC5nZXQoImNvdW50IiwgMSksCiAgICAgICAgICAgICAgICBjYXRlZ29yeT1jYXJkLmdldCgiY2F0ZWdvcnkiLCAiIiksCiAgICAgICAgICAgICAgICByb2xlX3RhZ3M9Y2FyZC5nZXQoInJvbGVfdGFncyIsIFtdKSwKICAgICAgICAgICAgICAgIHJlYXNvbj1jYXJkLmdldCgicmVhc29uIiwgIiIpLAogICAgICAgICAgICAgICAgZXN0aW1hdGVkX3ByaWNlX3VzZD0oCiAgICAgICAgICAgICAgICAgICAgcm91bmQocm93WyJ0Y2dfcHJpY2UiXSwgMikgaWYgcm93IGFuZCByb3dbInRjZ19wcmljZSJdCiAgICAgICAgICAgICAgICAgICAgZWxzZSBjYXJkLmdldCgiZXN0aW1hdGVkX3ByaWNlX3VzZCIsIDApCiAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgc3luZXJneV93aXRoPWNhcmQuZ2V0KCJzeW5lcmd5X3dpdGgiLCBbXSksCiAgICAgICAgICAgICAgICBvd25lZD1pc19vd25lZCwKICAgICAgICAgICAgICAgIG93bmVkX3F0eT1pbnQocm93WyJxdWFudGl0eSJdKSBpZiByb3cgYW5kIHJvd1sicXVhbnRpdHkiXSBlbHNlIDAsCiAgICAgICAgICAgICAgICBzY3J5ZmFsbF9pZD1yb3dbInNjcnlmYWxsX2lkIl0gaWYgcm93IGVsc2UgIiIsCiAgICAgICAgICAgICAgICBzdGF0dXM9Im93bmVkIiBpZiBpc19vd25lZCBlbHNlICJtaXNzaW5nIiwKICAgICAgICAgICAgKQogICAgICAgICAgICBlbnJpY2hlZC5hcHBlbmQoZW5yaWNoZWRfY2FyZCkKCiAgICAgICAgcmV0dXJuIGVucmljaGVkCgogICAgIyDilIDilIAgU3RlcCA2OiBTbWFydCBTdWJzdGl0dXRpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACiAgICBkZWYgcnVuX3N1YnN0aXR1dGlvbigKICAgICAgICBzZWxmLAogICAgICAgIGNhcmRzOiBMaXN0W0RlY2tDYXJkV2l0aFN0YXR1c10sCiAgICAgICAgY29tbWFuZGVyOiBkaWN0LAogICAgICAgIHN0cmF0ZWd5OiBzdHIgPSAiIiwKICAgICkgLT4gU3Vic3RpdHV0aW9uQmF0Y2hSZXN1bHQ6CiAgICAgICAgIiIiCiAgICAgICAgUnVuIHRoZSBTbWFydCBTdWJzdGl0dXRpb24gRW5naW5lIG9uIG1pc3NpbmcgY2FyZHMuCgogICAgICAgIFBpcGVsaW5lOgogICAgICAgICAgYSkgSWRlbnRpZnkgbWlzc2luZyBjYXJkcwogICAgICAgICAgYikgRm9yIGVhY2g6IHRyeSBlbWJlZGRpbmcgc2ltaWxhcml0eSAoZnJlZSwgZmFzdCkKICAgICAgICAgIGMpIEZvciBsb3ctY29uZmlkZW5jZSBtYXRjaGVzOiBiYXRjaCBQZXJwbGV4aXR5IGZhbGxiYWNrCiAgICAgICAgICBkKSBBdXRvLXNlbGVjdCBiZXN0IHN1YnN0aXR1dGUgcGVyIGNhcmQKCiAgICAgICAgUmV0dXJucyBTdWJzdGl0dXRpb25CYXRjaFJlc3VsdCB3aXRoIGFsbCBjYXJkcyB1cGRhdGVkLgogICAgICAgICIiIgogICAgICAgIGNvbG9yX2lkZW50aXR5ID0gY29tbWFuZGVyLmdldCgiY29sb3JfaWRlbnRpdHkiLCBbXSkKICAgICAgICBtaXNzaW5nID0gW2Mg' +
'Zm9yIGMgaW4gY2FyZHMgaWYgbm90IGMub3duZWRdCiAgICAgICAgb3duZWQgPSBbYyBmb3IgYyBpbiBjYXJkcyBpZiBjLm93bmVkXQoKICAgICAgICBpZiBub3QgbWlzc2luZzoKICAgICAgICAgICAgcmV0dXJuIFN1YnN0aXR1dGlvbkJhdGNoUmVzdWx0KAogICAgICAgICAgICAgICAgdG90YWxfY2FyZHM9bGVuKGNhcmRzKSwKICAgICAgICAgICAgICAgIG93bmVkX2NvdW50PWxlbihvd25lZCksCiAgICAgICAgICAgICAgICBzdWJzdGl0dXRlZF9jb3VudD0wLAogICAgICAgICAgICAgICAgbWlzc2luZ19jb3VudD0wLAogICAgICAgICAgICAgICAgY2FyZHM9Y2FyZHMsCiAgICAgICAgICAgICkKCiAgICAgICAgbG9nZ2VyLmluZm8oIlN1YnN0aXR1dGlvbjogJWQgbWlzc2luZyAvICVkIG93bmVkIiwgbGVuKG1pc3NpbmcpLCBsZW4ob3duZWQpKQoKICAgICAgICAjIEJ1aWxkIGxpc3Qgb2Ygb3duZWQgY2FyZCBuYW1lcyBmb3Igc3Vic3RpdHV0aW9uIHBvb2wKICAgICAgICBjb25uID0gc2VsZi5kYl9jb25uX2ZhY3RvcnkoKQogICAgICAgIG93bmVkX3Bvb2xfcm93cyA9IGNvbm4uZXhlY3V0ZSgKICAgICAgICAgICAgIlNFTEVDVCBESVNUSU5DVCBuYW1lIEZST00gY29sbGVjdGlvbl9lbnRyaWVzIFdIRVJFIHF1YW50aXR5ID4gMCIKICAgICAgICApLmZldGNoYWxsKCkKICAgICAgICBvd25lZF9wb29sID0gW3JbIm5hbWUiXSBmb3IgciBpbiBvd25lZF9wb29sX3Jvd3NdCgogICAgICAgICMgRXhjbHVkZSBjYXJkcyBhbHJlYWR5IGluIHRoZSBkZWNrCiAgICAgICAgZGVja19uYW1lcyA9IHNldChjLm5hbWUubG93ZXIoKSBmb3IgYyBpbiBjYXJkcykKICAgICAgICBhdmFpbGFibGVfcG9vbCA9IFtuIGZvciBuIGluIG93bmVkX3Bvb2wgaWYgbi5sb3dlcigpIG5vdCBpbiBkZWNrX25hbWVzXQoKICAgICAgICAjIGEpIEVtYmVkZGluZyBwYXNzCiAgICAgICAgbmVlZHNfcHBseF9mYWxsYmFjayA9IFtdCiAgICAgICAgZm9yIGNhcmQgaW4gbWlzc2luZzoKICAgICAgICAgICAgZW1iZWRkaW5nX2FsdHMgPSBzZWxmLl9lbWJlZGRpbmdfc3Vic3RpdHV0aW9uKAogICAgICAgICAgICAgICAgY2FyZCwgY29sb3JfaWRlbnRpdHksIGF2YWlsYWJsZV9wb29sCiAgICAgICAgICAgICkKICAgICAgICAgICAgY2FyZC5hbHRlcm5hdGl2ZXMgPSBlbWJlZGRpbmdfYWx0cwoKICAgICAgICAgICAgIyBDaGVjayBpZiBiZXN0IG1hdGNoIG1lZXRzIHRocmVzaG9sZAogICAgICAgICAgICBpZiBlbWJlZGRpbmdfYWx0cyBhbmQgZW1iZWRkaW5nX2FsdHNbMF0uc2ltaWxhcml0eV9zY29yZSA+PSBTVUJTVElUVVRJT05fTUlOX1NJTUlMQVJJVFk6CiAgICAgICAgICAgICAgICBjYXJkLnNlbGVjdGVkX3N1YnN0aXR1dGUgPSBlbWJlZGRpbmdfYWx0c1swXS5uYW1lCiAgICAgICAgICAgICAgICBjYXJkLnN0YXR1cyA9ICJzdWJzdGl0dXRlZCIKICAgICAgICAgICAgICAgICMgUmVtb3ZlIHNlbGVjdGVkIGZyb20gcG9vbAogICAgICAgICAgICAgICAgaWYgY2FyZC5zZWxlY3RlZF9zdWJzdGl0dXRlLmxvd2VyKCkgaW4gW24ubG93ZXIoKSBmb3IgbiBpbiBhdmFpbGFibGVfcG9vbF06CiAgICAgICAgICAgICAgICAgICAgYXZhaWxhYmxlX3Bvb2wgPSBbbiBmb3IgbiBpbiBhdmFpbGFibGVfcG9vbAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgbi5sb3dlcigpICE9IGNhcmQuc2VsZWN0ZWRfc3Vic3RpdHV0ZS5sb3dlcigpXQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgbmVlZHNfcHBseF9mYWxsYmFjay5hcHBlbmQoY2FyZCkKCiAgICAgICAgIyBiKSBQZXJwbGV4aXR5IGZhbGxiYWNrIGZvciBsb3ctY29uZmlkZW5jZSBtYXRjaGVzCiAgICAgICAgaWYgbmVlZHNfcHBseF9mYWxsYmFjayBhbmQgU1VCU1RJVFVUSU9OX1VTRV9QUExYX0ZBTExCQUNLOgogICAgICAgICAgICBzZWxmLl9wcGx4X3N1YnN0aXR1dGlvbigKICAgICAgICAgICAgICAgIG5lZWRzX3BwbHhfZmFsbGJhY2ssIGF2YWlsYWJsZV9wb29sLAogICAgICAgICAgICAgICAgY29tbWFuZGVyLCBzdHJhdGVneQogICAgICAgICAgICApCgogICAgICAgICMgQ291bnQgcmVzdWx0cwogICAgICAgIHN1YnN0aXR1dGVkID0gc3VtKDEgZm9yIGMgaW4gY2FyZHMgaWYgYy5zdGF0dXMgPT0gInN1YnN0aXR1dGVkIikKICAgICAgICBzdGlsbF9taXNzaW5nID0gc3VtKDEgZm9yIGMgaW4gY2FyZHMgaWYgYy5zdGF0dXMgPT0gIm1pc3NpbmciKQoKICAgICAgICByZXR1cm4gU3Vic3RpdHV0aW9u' +
'QmF0Y2hSZXN1bHQoCiAgICAgICAgICAgIHRvdGFsX2NhcmRzPWxlbihjYXJkcyksCiAgICAgICAgICAgIG93bmVkX2NvdW50PWxlbihvd25lZCksCiAgICAgICAgICAgIHN1YnN0aXR1dGVkX2NvdW50PXN1YnN0aXR1dGVkLAogICAgICAgICAgICBtaXNzaW5nX2NvdW50PXN0aWxsX21pc3NpbmcsCiAgICAgICAgICAgIGNhcmRzPWNhcmRzLAogICAgICAgICkKCiAgICBkZWYgX2VtYmVkZGluZ19zdWJzdGl0dXRpb24oCiAgICAgICAgc2VsZiwKICAgICAgICBjYXJkOiBEZWNrQ2FyZFdpdGhTdGF0dXMsCiAgICAgICAgY29sb3JfaWRlbnRpdHk6IExpc3Rbc3RyXSwKICAgICAgICBhdmFpbGFibGVfcG9vbDogTGlzdFtzdHJdLAogICAgKSAtPiBMaXN0W0NhcmRBbHRlcm5hdGl2ZV06CiAgICAgICAgIiIiRmluZCBlbWJlZGRpbmctc2ltaWxhciBvd25lZCBjYXJkcyBhcyBzdWJzdGl0dXRlcy4iIiIKICAgICAgICBpZiBub3Qgc2VsZi5lbWJlZGRpbmdfaW5kZXggb3Igbm90IHNlbGYuZW1iZWRkaW5nX2luZGV4LmxvYWRlZDoKICAgICAgICAgICAgcmV0dXJuIFtdCgogICAgICAgICMgVXNlIHRoZSBlbWJlZGRpbmdzIHNlYXJjaCB0byBmaW5kIHNpbWlsYXIgY2FyZHMKICAgICAgICBtYXRjaGVzID0gc2VsZi5lbWJlZGRpbmdfaW5kZXguc2VhcmNoX3NpbWlsYXIoCiAgICAgICAgICAgIHF1ZXJ5X2NhcmQ9Y2FyZC5uYW1lLAogICAgICAgICAgICBjb2xvcl9maWx0ZXI9Y29sb3JfaWRlbnRpdHkgaWYgY29sb3JfaWRlbnRpdHkgZWxzZSBOb25lLAogICAgICAgICAgICB0eXBlX2ZpbHRlcj1jYXJkLmNhdGVnb3J5IGlmIGNhcmQuY2F0ZWdvcnkgZWxzZSBOb25lLAogICAgICAgICAgICBleGNsdWRlX2NhcmRzPVtjYXJkLm5hbWVdLAogICAgICAgICAgICB0b3Bfbj1TVUJTVElUVVRJT05fTUFYX0FMVEVSTkFUSVZFUyAqIDMsICAjIE92ZXItZmV0Y2gsIHRoZW4gZmlsdGVyIHRvIG93bmVkCiAgICAgICAgKQoKICAgICAgICAjIEZpbHRlciB0byBvbmx5IGNhcmRzIGluIHRoZSBhdmFpbGFibGUgcG9vbAogICAgICAgIHBvb2xfbG93ZXIgPSBzZXQobi5sb3dlcigpIGZvciBuIGluIGF2YWlsYWJsZV9wb29sKQogICAgICAgIGFsdGVybmF0aXZlcyA9IFtdCiAgICAgICAgZm9yIG1hdGNoIGluIG1hdGNoZXM6CiAgICAgICAgICAgIGlmIG1hdGNoLm5hbWUubG93ZXIoKSBpbiBwb29sX2xvd2VyOgogICAgICAgICAgICAgICAgIyBDb21wdXRlIHJvbGUgb3ZlcmxhcAogICAgICAgICAgICAgICAgbWF0Y2hfcm9sZXMgPSBbXSAgIyBXb3VsZCBuZWVkIGNhcmQncyByb2xlX3RhZ3MgZnJvbSBEQgogICAgICAgICAgICAgICAgcm9sZV9vdmVybGFwID0gbGlzdChzZXQoY2FyZC5yb2xlX3RhZ3MpICYgc2V0KG1hdGNoX3JvbGVzKSkgaWYgbWF0Y2hfcm9sZXMgZWxzZSBbXQoKICAgICAgICAgICAgICAgIGFsdGVybmF0aXZlcy5hcHBlbmQoQ2FyZEFsdGVybmF0aXZlKAogICAgICAgICAgICAgICAgICAgIG5hbWU9bWF0Y2gubmFtZSwKICAgICAgICAgICAgICAgICAgICBzaW1pbGFyaXR5X3Njb3JlPW1hdGNoLnNpbWlsYXJpdHksCiAgICAgICAgICAgICAgICAgICAgcmVhc29uPWYiU2ltaWxhciB0byB7Y2FyZC5uYW1lfSAoY29zaW5lIHNpbToge21hdGNoLnNpbWlsYXJpdHk6LjNmfSkiLAogICAgICAgICAgICAgICAgICAgIHNvdXJjZT0iZW1iZWRkaW5nIiwKICAgICAgICAgICAgICAgICAgICByb2xlX292ZXJsYXA9cm9sZV9vdmVybGFwLAogICAgICAgICAgICAgICAgICAgIGNtY19kZWx0YT1tYXRjaC5tYW5hX3ZhbHVlIC0gKGNhcmQuZXN0aW1hdGVkX3ByaWNlX3VzZCBvciAwKSwKICAgICAgICAgICAgICAgICkpCgogICAgICAgICAgICAgICAgaWYgbGVuKGFsdGVybmF0aXZlcykgPj0gU1VCU1RJVFVUSU9OX01BWF9BTFRFUk5BVElWRVM6CiAgICAgICAgICAgICAgICAgICAgYnJlYWsKCiAgICAgICAgcmV0dXJuIGFsdGVybmF0aXZlcwoKICAgIGRlZiBfcHBseF9zdWJzdGl0dXRpb24oCiAgICAgICAgc2VsZiwKICAgICAgICBtaXNzaW5nX2NhcmRzOiBMaXN0W0RlY2tDYXJkV2l0aFN0YXR1c10sCiAgICAgICAgYXZhaWxhYmxlX3Bvb2w6IExpc3Rbc3RyXSwKICAgICAgICBjb21tYW5kZXI6IGRpY3QsCiAgICAgICAgc3RyYXRlZ3k6IHN0ciwKICAgICk6CiAgICAgICAgIiIiCiAgICAgICAgQmF0Y2ggUGVycGxleGl0eSBmYWxsYmFjayBmb3IgY2FyZHMgd2l0aCBsb3cgZW1iZWRkaW5nIGNvbmZpZGVuY2UuCiAgICAgICAgTXV0YXRlcyB0aGUgY2FyZHMgaW4tcGxh' +
'Y2Ugd2l0aCBzdWJzdGl0dXRpb24gZGF0YS4KICAgICAgICAiIiIKICAgICAgICBpZiBub3QgYXZhaWxhYmxlX3Bvb2w6CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICAjIEJ1aWxkIHRoZSByZXF1ZXN0CiAgICAgICAgbWlzc2luZ19kaWN0cyA9IFsKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgIm5hbWUiOiBjLm5hbWUsCiAgICAgICAgICAgICAgICAicm9sZV90YWdzIjogYy5yb2xlX3RhZ3MsCiAgICAgICAgICAgICAgICAiY2F0ZWdvcnkiOiBjLmNhdGVnb3J5LAogICAgICAgICAgICAgICAgInJlYXNvbiI6IGMucmVhc29uLAogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvciBjIGluIG1pc3NpbmdfY2FyZHMKICAgICAgICBdCgogICAgICAgIHVzZXJfcHJvbXB0ID0gYnVpbGRfc3Vic3RpdHV0aW9uX3Byb21wdCgKICAgICAgICAgICAgbWlzc2luZ19jYXJkcz1taXNzaW5nX2RpY3RzLAogICAgICAgICAgICBhbGxvd2VkX2NhcmRzPWF2YWlsYWJsZV9wb29sWzoyMDBdLCAgIyBMaW1pdCB0byBhdm9pZCB0b2tlbiBvdmVyZmxvdwogICAgICAgICAgICBjb21tYW5kZXI9Y29tbWFuZGVyLmdldCgibmFtZSIsICIiKSwKICAgICAgICAgICAgY29sb3JfaWRlbnRpdHk9Y29tbWFuZGVyLmdldCgiY29sb3JfaWRlbnRpdHkiLCBbXSksCiAgICAgICAgICAgIHN0cmF0ZWd5PXN0cmF0ZWd5LAogICAgICAgICkKCiAgICAgICAgdHJ5OgogICAgICAgICAgICBmcm9tIC4uc2NoZW1hcy5zdWJzdGl0dXRpb25fc2NoZW1hIGltcG9ydCBTVUJTVElUVVRJT05fUkVTUE9OU0VfU0NIRU1BCiAgICAgICAgICAgIHJlc3BvbnNlID0gc2VsZi5wcGx4LmNoYXRfc3RydWN0dXJlZCgKICAgICAgICAgICAgICAgIHN5c3RlbV9wcm9tcHQ9U1VCU1RJVFVUSU9OX1NZU1RFTSwKICAgICAgICAgICAgICAgIHVzZXJfcHJvbXB0PXVzZXJfcHJvbXB0LAogICAgICAgICAgICAgICAganNvbl9zY2hlbWE9U1VCU1RJVFVUSU9OX1JFU1BPTlNFX1NDSEVNQSwKICAgICAgICAgICAgICAgIHNjaGVtYV9uYW1lPSJTdWJzdGl0dXRpb25SZXNwb25zZSIsCiAgICAgICAgICAgICAgICBtb2RlbD1TVUJTVElUVVRJT05fTU9ERUwsCiAgICAgICAgICAgICAgICB0ZW1wZXJhdHVyZT0wLjEsCiAgICAgICAgICAgICAgICBtYXhfdG9rZW5zPTQwOTYsCiAgICAgICAgICAgICkKCiAgICAgICAgICAgIGlmIG5vdCByZXNwb25zZS5vazoKICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuaW5nKCJQZXJwbGV4aXR5IHN1YnN0aXR1dGlvbiBmYWxsYmFjayBmYWlsZWQg4oCUIG5vbi1KU09OIHJlc3BvbnNlIikKICAgICAgICAgICAgICAgIHJldHVybgoKICAgICAgICAgICAgc3VicyA9IHJlc3BvbnNlLnBhcnNlZF9qc29uLmdldCgic3Vic3RpdHV0aW9ucyIsIFtdKQogICAgICAgICAgICBsb2dnZXIuaW5mbygiUGVycGxleGl0eSBzdWdnZXN0ZWQgJWQgc3Vic3RpdHV0aW9ucyIsIGxlbihzdWJzKSkKCiAgICAgICAgICAgICMgQXBwbHkgc3Vic3RpdHV0aW9ucwogICAgICAgICAgICBjYXJkX2J5X25hbWUgPSB7Yy5uYW1lLmxvd2VyKCk6IGMgZm9yIGMgaW4gbWlzc2luZ19jYXJkc30KICAgICAgICAgICAgZm9yIHN1YiBpbiBzdWJzOgogICAgICAgICAgICAgICAgb3JpZyA9IHN1Yi5nZXQoIm9yaWdpbmFsIiwgIiIpLmxvd2VyKCkKICAgICAgICAgICAgICAgIHN1YnN0aXR1dGUgPSBzdWIuZ2V0KCJzdWJzdGl0dXRlIiwgIiIpCiAgICAgICAgICAgICAgICByZWFzb24gPSBzdWIuZ2V0KCJyZWFzb24iLCAiIikKCiAgICAgICAgICAgICAgICBpZiBvcmlnIGluIGNhcmRfYnlfbmFtZSBhbmQgc3Vic3RpdHV0ZToKICAgICAgICAgICAgICAgICAgICBjYXJkID0gY2FyZF9ieV9uYW1lW29yaWddCiAgICAgICAgICAgICAgICAgICAgIyBBZGQgYXMgdG9wIGFsdGVybmF0aXZlCiAgICAgICAgICAgICAgICAgICAgcHBseF9hbHQgPSBDYXJkQWx0ZXJuYXRpdmUoCiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU9c3Vic3RpdHV0ZSwKICAgICAgICAgICAgICAgICAgICAgICAgc2ltaWxhcml0eV9zY29yZT0wLjgwLCAgIyBOb21pbmFsIHNjb3JlIGZvciBQZXJwbGV4aXR5IHN1Z2dlc3Rpb25zCiAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbj1yZWFzb24sCiAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZT0icGVycGxleGl0eSIsCiAgICAgICAgICAgICAgICAgICAgICAgIHJvbGVfb3ZlcmxhcD1zdWIuZ2V0KCJyb2xlX292ZXJsYXAiLCBbXSksCiAgICAgICAgICAgICAgICAgICAgKQog' +
'ICAgICAgICAgICAgICAgICAgICMgSW5zZXJ0IGF0IGZyb250CiAgICAgICAgICAgICAgICAgICAgY2FyZC5hbHRlcm5hdGl2ZXMuaW5zZXJ0KDAsIHBwbHhfYWx0KQogICAgICAgICAgICAgICAgICAgIGNhcmQuc2VsZWN0ZWRfc3Vic3RpdHV0ZSA9IHN1YnN0aXR1dGUKICAgICAgICAgICAgICAgICAgICBjYXJkLnN0YXR1cyA9ICJzdWJzdGl0dXRlZCIKCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICAgICBsb2dnZXIuZXJyb3IoIlBlcnBsZXhpdHkgc3Vic3RpdHV0aW9uIGZhbGxiYWNrIGVycm9yOiAlcyIsIGUpCgogICAgIyDilIDilIAgU3RhdHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACiAgICBAc3RhdGljbWV0aG9kCiAgICBkZWYgX2NvbXB1dGVfc3RhdHMoY2FyZHM6IExpc3RbRGVja0NhcmRXaXRoU3RhdHVzXSkgLT4gZGljdDoKICAgICAgICAiIiJDb21wdXRlIGRlY2sgc3RhdGlzdGljcyBmcm9tIHRoZSBlbnJpY2hlZCBjYXJkIGxpc3QuIiIiCiAgICAgICAgYnlfY2F0ZWdvcnkgPSB7fQogICAgICAgIGJ5X3N0YXR1cyA9IHsib3duZWQiOiAwLCAic3Vic3RpdHV0ZWQiOiAwLCAibWlzc2luZyI6IDB9CiAgICAgICAgdG90YWxfcHJpY2UgPSAwLjAKICAgICAgICBvd25lZF9wcmljZSA9IDAuMAogICAgICAgIG1pc3NpbmdfcHJpY2UgPSAwLjAKICAgICAgICByb2xlX2NvdW50cyA9IHt9CgogICAgICAgIGZvciBjYXJkIGluIGNhcmRzOgogICAgICAgICAgICBjYXQgPSBjYXJkLmNhdGVnb3J5IG9yICJPdGhlciIKICAgICAgICAgICAgYnlfY2F0ZWdvcnlbY2F0XSA9IGJ5X2NhdGVnb3J5LmdldChjYXQsIDApICsgY2FyZC5jb3VudAogICAgICAgICAgICBieV9zdGF0dXNbY2FyZC5zdGF0dXNdID0gYnlfc3RhdHVzLmdldChjYXJkLnN0YXR1cywgMCkgKyAxCiAgICAgICAgICAgIHByaWNlID0gY2FyZC5lc3RpbWF0ZWRfcHJpY2VfdXNkICogY2FyZC5jb3VudAogICAgICAgICAgICB0b3RhbF9wcmljZSArPSBwcmljZQogICAgICAgICAgICBpZiBjYXJkLm93bmVkOgogICAgICAgICAgICAgICAgb3duZWRfcHJpY2UgKz0gcHJpY2UKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIG1pc3NpbmdfcHJpY2UgKz0gcHJpY2UKICAgICAgICAgICAgZm9yIHJvbGUgaW4gY2FyZC5yb2xlX3RhZ3M6CiAgICAgICAgICAgICAgICByb2xlX2NvdW50c1tyb2xlXSA9IHJvbGVfY291bnRzLmdldChyb2xlLCAwKSArIDEKCiAgICAgICAgbGFuZF9jb3VudCA9IGJ5X2NhdGVnb3J5LmdldCgiTGFuZCIsIDApCiAgICAgICAgbm9ubGFuZF9jb3VudCA9IHN1bSh2IGZvciBrLCB2IGluIGJ5X2NhdGVnb3J5Lml0ZW1zKCkgaWYgayAhPSAiTGFuZCIpCgogICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICJ0b3RhbF9jYXJkcyI6IHN1bShjLmNvdW50IGZvciBjIGluIGNhcmRzKSwKICAgICAgICAgICAgImxhbmRfY291bnQiOiBsYW5kX2NvdW50LAogICAgICAgICAgICAibm9ubGFuZF9jb3VudCI6IG5vbmxhbmRfY291bnQsCiAgICAgICAgICAgICJieV9jYXRlZ29yeSI6IGJ5X2NhdGVnb3J5LAogICAgICAgICAgICAiYnlfc3RhdHVzIjogYnlfc3RhdHVzLAogICAgICAgICAgICAicm9sZV9jb3VudHMiOiByb2xlX2NvdW50cywKICAgICAgICAgICAgInRvdGFsX3ByaWNlX3VzZCI6IHJvdW5kKHRvdGFsX3ByaWNlLCAyKSwKICAgICAgICAgICAgIm93bmVkX3ByaWNlX3VzZCI6IHJvdW5kKG93bmVkX3ByaWNlLCAyKSwKICAgICAgICAgICAgIm1pc3NpbmdfcHJpY2VfdXNkIjogcm91bmQobWlzc2luZ19wcmljZSwgMiksCiAgICAgICAgfQo='
Install-B64 -R 'coach\services\deck_generator.py' -B $b
# deck_sources/__init__.py (236 bytes)