from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from random import randint, choice
class Toe(QWidget):
def __init__ (self):
self.turn = 0
self.first_cross = ''
self.grid = [0,1,2,3,4,5,6,7,8]
self.status = ['e','e','e','e','e','e','e','e','e']
self.lines = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[6,4,2]]
self.finish = 0
self.buttons = []
QWidget. __init__ (self)
self.resize(360, 435)
self.setMaximumSize(360,435)
self.setMinimumSize(360,435)
self.one = QPushButton(self)
self.one.clicked.connect(lambda event= '<Button-1>' : self.set_it(self.one, 0))
self.one.setGeometry(QRect(40,70,70,60))
self.one.setText('...')
self.buttons.append(self.one)
self.two = QPushButton(self)
self.two.clicked.connect(lambda event= '<Button-1>' : self.set_it(self.two, 1))
self.two.setGeometry(QRect(140,70,70,60))
self.two.setText('...')
self.buttons.append(self.two)
self.three = QPushButton(self)
self.three.clicked.connect(lambda event= '<Button-1>' : self.set_it(self.three, 2))
self.three.setGeometry(QRect(240,70,70,60))
self.three.setText('...')
self.buttons.append(self.three)
self.four = QPushButton(self)
self.four.clicked.connect(lambda event= '<Button-1>' : self.set_it(self.four, 3))
self.four.setGeometry(QRect(40,155,70,60))
self.four.setText('...')
self.buttons.append(self.four)
self.five = QPushButton(self)
self.five.clicked.connect(lambda event= '<Button-1>' : self.set_it(self.five, 4))
self.five.setGeometry(QRect(140,155,70,60))
self.five.setText('...')
self.buttons.append(self.five)
self.six = QPushButton(self)
self.six.clicked.connect(lambda event= '<Button-1>' : self.set_it(self.six, 5))
self.six.setGeometry(QRect(240,155,70,60))
self.six.setText('...')
self.buttons.append(self.six)
self.seven = QPushButton(self)
self.seven.clicked.connect(lambda event= '<Button-1>' : self.set_it(self.seven, 6))
self.seven.setGeometry(QRect(40,240,70,60))
self.seven.setText('...')
self.buttons.append(self.seven)
self.eight = QPushButton(self)
self.eight.clicked.connect(lambda event= '<Button-1>' : self.set_it(self.eight, 7))
self.eight.setGeometry(QRect(140,240,70,60))
self.eight.setText('...')
self.buttons.append(self.eight)
self.nine = QPushButton(self)
self.nine.clicked.connect(lambda event= '<Button-1>' : self.set_it(self.nine, 8))
self.nine.setGeometry(QRect(240,240,70,60))
self.nine.setText('...')
self.buttons.append(self.nine)
self.result = QLabel('', self)
self.result.setGeometry(QRect(125,360,111,18))
self.crossornull = QCheckBox(self)
self.crossornull.setGeometry(QRect(335, 25, 16, 16))
self.startgame = QPushButton(self)
self.startgame.setGeometry(QRect(175,20,80,30))
self.startgame.setText("Старт!")
self.startgame.clicked.connect(self.start)
self.fornull = QLabel("За 'нолик':", self)
self.fornull.setGeometry(QRect(270,25, 55,12))
self.setWindowTitle("Tic-tac-toe")
self.mylevel = QComboBox(self)
self.mylevel.addItems(['Easy', 'Normal', 'Dead end'])
self.mylevel.setGeometry(QRect(88,20,70,30))
self.leveltext = QLabel('Сложность:', self)
self.leveltext.setGeometry(10,30,58,15)
self.show()
def set_it(self, button, n):
if self.mylevel.currentText() == 'Easy':
if not self.crossornull.isChecked():
button.setText('X')
button.setDisabled(True)
self.grid.remove(n)
self.status[n] = 'X'
if not self.check():
self.easy_ai('O')
else:
button.setText('O')
button.setDisabled(True)
self.grid.remove(n)
self.status[n] = 'O'
if not self.check():
self.easy_ai('X')
elif self.mylevel.currentText() == 'Normal':
if not self.crossornull.isChecked():
button.setText('X')
button.setDisabled(True)
self.grid.remove(n)
self.status[n] = 'X'
if not self.check():
self.normal_ai('O')
else:
button.setText('O')
button.setDisabled(True)
self.grid.remove(n)
self.status[n] = 'O'
if not self.check():
self.normal_ai('X')
elif self.mylevel.currentText() == 'Dead end':
if not self.crossornull.isChecked():
button.setText('X')
button.setDisabled(True)
self.grid.remove(n)
self.status[n] = 'X'
if not self.check():
self.deadend_ai('O')
else:
button.setText('O')
button.setDisabled(True)
self.grid.remove(n)
self.status[n] = 'O'
if not self.check():
self.deadend_ai('X')
def start(self):
self.turn = 0
self.finish = 0
self.grid = [0,1,2,3,4,5,6,7,8]
self.status = ['e','e','e','e','e','e','e','e','e']
for elem in self.buttons:
elem.setText('...')
elem.setDisabled(False)
self.result.setText('')
if self.crossornull.isChecked():
if self.mylevel.currentText() == 'Easy':
self.easy_ai('X')
elif self.mylevel.currentText() == 'Normal':
self.normal_ai('X')
elif self.mylevel.currentText() == 'Dead end':
self.deadend_ai('X')
def easy_ai (self, sign, choose=''):
if len(self.grid) > 0:
if choose == '':
choose = choice(self.grid)
self.grid.remove(choose)
if choose == 0:
self.one.setText(sign)
self.one.setDisabled(True)
elif choose == 1:
self.two.setText(sign)
self.two.setDisabled(True)
elif choose == 2:
self.three.setText(sign)
self.three.setDisabled(True)
elif choose == 3:
self.four.setText(sign)
self.four.setDisabled(True)
elif choose == 4:
self.five.setText(sign)
self.five.setDisabled(True)
elif choose == 5:
self.six.setText(sign)
self.six.setDisabled(True)
elif choose == 6:
self.seven.setText(sign)
self.seven.setDisabled(True)
elif choose == 7:
self.eight.setText(sign)
self.eight.setDisabled(True)
else:
self.nine.setText(sign)
self.nine.setDisabled(True)
self.status[choose] = sign
self.check()
def normal_ai(self, sign, hlp=0):
test = 0
p = 0 #~!!!!
if sign == 'O':
enemy = 'X'
else: enemy = 'O'
if len(self.grid) >= 8:
self.easy_ai(sign)
else:
for elem in self.lines:
for i in elem:
if self.status[i] == sign:
test+=1
if test > 1 and any(self.status[k] == 'e' for k in elem):
self.easy_ai(sign, int(list(filter(lambda j : self.status[j] == 'e', elem))[0]))
p+=1
break
if test > 1 and p > 0:
break
test = 0
if p == 0:
test = 0
for elem in self.lines:
for i in elem:
if self.status[i] == enemy:
test+=1
if test > 1 and any(self.status[k] == 'e' for k in elem):
self.easy_ai(sign, int(list(filter(lambda j : self.status[j] == 'e', elem))[0]))
p+=1
break
if test > 1 and p > 0:
break
test = 0
if test <= 1 and p == 0:
if hlp == 0:
self.easy_ai(sign)
else:
self.deadend_ai(sign, iam=0)
def deadend_ai(self, sign, iam=1):
arr = [0,2,6,8]
lin = [1,5,7,3]
if sign == 'X':
if self.turn == 0:
self.easy_ai(sign, 4)
self.turn+=1
elif self.turn == 1:
self.turn+=1
if self.status[0] == 'O':
self.easy_ai(sign, 8)
elif self.status[1] == 'O':
self.easy_ai(sign, 6)
elif self.status[2] == 'O':
self.easy_ai(sign, 6)
elif self.status[3] == 'O':
self.easy_ai(sign, 2)
elif self.status[5] == 'O':
self.easy_ai(sign, 6)
elif self.status[6] == 'O':
self.easy_ai(sign, 2)
elif self.status[7] == 'O':
self.easy_ai(sign, 0)
else:
self.easy_ai(sign, 0)
elif self.turn > 1:
self.normal_ai(sign)
elif sign == 'O':
if self.turn == 0:
self.turn+=1
if self.status[4] == 'X':
n = choice(arr)
self.easy_ai(sign, n)
self.first_cross = 'c'
elif self.status[4] != 'X' and (self.status[0] == 'X' or self.status[2] == 'X' or self.status[6] == 'X' or self.status[8] == 'X'):
self.easy_ai(sign, 4)
self.first_cross = 'co'
else:
self.first_cross = 'line'
self.easy_ai(sign, 4)
elif self.turn > 0 and self.first_cross == 'c':
if iam==1:
self.normal_ai(sign, hlp=1)
else:
try:
n = choice([i for i in arr if i in self.grid])
self.easy_ai(sign, n)
except:
self.easy_ai(sign)
elif self.turn > 0 and self.first_cross == 'co':
if self.turn == 1:
if iam == 1:
self.normal_ai(sign, hlp=1)
else:
self.turn+=1
try:
if self.status[0] == 'X':
self.easy_ai(sign, 8)
elif self.status[2] == 'X':
self.easy_ai(sign, 6)
elif self.status[6] == 'X':
self.easy_ai(sign, 2)
elif self.status[8] == 'X':
self.easy_ai(sign, 0)
except:
n = choice([i for i in lin if i in self.grid])
self.easy_ai(sign, n)
else:
self.normal_ai(sign)
elif self.turn > 0 and self.first_cross == 'line':
if self.turn == 1:
if iam == 1:
self.normal_ai(sign, hlp=1)
else:
if self.status[0] == 'X' or self.status[2] == 'X' or self.status[6] == 'X' or self.status[8] == 'X':
print('!222@')
try:
if self.status[0] == 'X':
self.easy_ai(sign, 8)
elif self.status[2] == 'X':
self.easy_ai(sign, 6)
elif self.status[6] == 'X':
self.easy_ai(sign, 2)
elif self.status[8] == 'X':
self.easy_ai(sign, 0)
self.turn+=1
except:
self.normal_ai(sign)
elif (self.status[1] == 'X' and self.status[7] == 'X') or (self.status[3] == 'X' and self.status[5] == 'X'):
n = choice(arr)
self.easy_ai(sign, n)
self.turn+=1
elif ((self.status[3] == 'X' and self.status[1] == 'X') or (self.status[1] == 'X' and self.status[5] == 'X') or
(self.status[5] == 'X' and self.status[7] == 'X') or (self.status[7] == 'X' and self.status[3] == 'X')):
if (self.status[3] == 'X' and self.status[1] == 'X'):
self.easy_ai(sign, 0)
elif (self.status[1] == 'X' and self.status[5] == 'X'):
self.easy_ai(sign, 2)
elif (self.status[5] == 'X' and self.status[7] == 'X'):
self.easy_ai(sign, 8)
elif (self.status[7] == 'X' and self.status[3] == 'X'):
self.easy_ai(sign, 6)
self.turn+=1
elif self.turn > 1:
self.normal_ai(sign)
def check(self):
for elem in self.lines:
if all(self.status[i] == 'X' for i in elem) and not self.crossornull.isChecked():
self.result.setText("<html><head/><body><p><span style=\" font-size:12pt; color:green;\">Вы выиграли!</span></p></body></html>")
self.finish += 1
if all(self.status[i] == 'X' for i in elem) and self.crossornull.isChecked():
self.result.setText("<html><head/><body><p><span style=\" font-size:12pt; color:red;\">Вы проиграли.</span></p></body></html>")
self.finish+=1
if all(self.status[i] == 'O' for i in elem) and self.crossornull.isChecked():
self.result.setText("<html><head/><body><p><span style=\" font-size:12pt; color:green;\">Вы выиграли!</span></p></body></html>")
self.finish+=1
if all(self.status[i] == 'O' for i in elem) and not self.crossornull.isChecked():
self.result.setText("<html><head/><body><p><span style=\" font-size:12pt; color:red;\">Вы проиграли.</span></p></body></html>")
self.finish+=1
if len(self.grid) < 1 and self.finish == 0:
self.result.setText("<html><head/><body><p><span style=\" font-size:12pt; color:grey;\"><center>Ничья.</center></span></p></body></html>")
if self.finish > 0:
return True
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = Toe()
sys.exit(app.exec_())
ZnJvbSBQeVF0NS5RdENvcmUgaW1wb3J0ICoKZnJvbSBQeVF0NS5RdEd1aSBpbXBvcnQgKgpmcm9tIFB5UXQ1LlF0V2lkZ2V0cyBpbXBvcnQgKgpmcm9tIHJhbmRvbSBpbXBvcnQgcmFuZGludCwgY2hvaWNlCgpjbGFzcyBUb2UoUVdpZGdldCk6CgogICAgZGVmIF9faW5pdF9fIChzZWxmKToKCiAgICAgICAgc2VsZi50dXJuID0gMAogICAgICAgIHNlbGYuZmlyc3RfY3Jvc3MgPSAnJwogICAgICAgIHNlbGYuZ3JpZCA9IFswLDEsMiwzLDQsNSw2LDcsOF0KICAgICAgICBzZWxmLnN0YXR1cyA9IFsnZScsJ2UnLCdlJywnZScsJ2UnLCdlJywnZScsJ2UnLCdlJ10KICAgICAgICBzZWxmLmxpbmVzID0gW1swLDEsMl0sWzMsNCw1XSxbNiw3LDhdLFswLDMsNl0sWzEsNCw3XSxbMiw1LDhdLFswLDQsOF0sWzYsNCwyXV0KICAgICAgICBzZWxmLmZpbmlzaCA9IDAKICAgICAgICBzZWxmLmJ1dHRvbnMgPSBbXQogICAgICAgIFFXaWRnZXQuIF9faW5pdF9fIChzZWxmKQogICAgICAgIHNlbGYucmVzaXplKDM2MCwgNDM1KQogICAgICAgIHNlbGYuc2V0TWF4aW11bVNpemUoMzYwLDQzNSkKICAgICAgICBzZWxmLnNldE1pbmltdW1TaXplKDM2MCw0MzUpCiAgICAgICAgc2VsZi5vbmUgPSBRUHVzaEJ1dHRvbihzZWxmKQogICAgICAgIHNlbGYub25lLmNsaWNrZWQuY29ubmVjdChsYW1iZGEgZXZlbnQ9ICc8QnV0dG9uLTE+JyA6IHNlbGYuc2V0X2l0KHNlbGYub25lLCAwKSkKICAgICAgICBzZWxmLm9uZS5zZXRHZW9tZXRyeShRUmVjdCg0MCw3MCw3MCw2MCkpCiAgICAgICAgc2VsZi5vbmUuc2V0VGV4dCgnLi4uJykKICAgICAgICBzZWxmLmJ1dHRvbnMuYXBwZW5kKHNlbGYub25lKQogICAgICAgIHNlbGYudHdvID0gUVB1c2hCdXR0b24oc2VsZikKICAgICAgICBzZWxmLnR3by5jbGlja2VkLmNvbm5lY3QobGFtYmRhIGV2ZW50PSAnPEJ1dHRvbi0xPicgOiBzZWxmLnNldF9pdChzZWxmLnR3bywgMSkpCiAgICAgICAgc2VsZi50d28uc2V0R2VvbWV0cnkoUVJlY3QoMTQwLDcwLDcwLDYwKSkKICAgICAgICBzZWxmLnR3by5zZXRUZXh0KCcuLi4nKQogICAgICAgIHNlbGYuYnV0dG9ucy5hcHBlbmQoc2VsZi50d28pCiAgICAgICAgc2VsZi50aHJlZSA9IFFQdXNoQnV0dG9uKHNlbGYpCiAgICAgICAgc2VsZi50aHJlZS5jbGlja2VkLmNvbm5lY3QobGFtYmRhIGV2ZW50PSAnPEJ1dHRvbi0xPicgOiBzZWxmLnNldF9pdChzZWxmLnRocmVlLCAyKSkKICAgICAgICBzZWxmLnRocmVlLnNldEdlb21ldHJ5KFFSZWN0KDI0MCw3MCw3MCw2MCkpCiAgICAgICAgc2VsZi50aHJlZS5zZXRUZXh0KCcuLi4nKQogICAgICAgIHNlbGYuYnV0dG9ucy5hcHBlbmQoc2VsZi50aHJlZSkKICAgICAgICBzZWxmLmZvdXIgPSBRUHVzaEJ1dHRvbihzZWxmKQogICAgICAgIHNlbGYuZm91ci5jbGlja2VkLmNvbm5lY3QobGFtYmRhIGV2ZW50PSAnPEJ1dHRvbi0xPicgOiBzZWxmLnNldF9pdChzZWxmLmZvdXIsIDMpKQogICAgICAgIHNlbGYuZm91ci5zZXRHZW9tZXRyeShRUmVjdCg0MCwxNTUsNzAsNjApKQogICAgICAgIHNlbGYuZm91ci5zZXRUZXh0KCcuLi4nKQogICAgICAgIHNlbGYuYnV0dG9ucy5hcHBlbmQoc2VsZi5mb3VyKQogICAgICAgIHNlbGYuZml2ZSA9IFFQdXNoQnV0dG9uKHNlbGYpCiAgICAgICAgc2VsZi5maXZlLmNsaWNrZWQuY29ubmVjdChsYW1iZGEgZXZlbnQ9ICc8QnV0dG9uLTE+JyA6IHNlbGYuc2V0X2l0KHNlbGYuZml2ZSwgNCkpCiAgICAgICAgc2VsZi5maXZlLnNldEdlb21ldHJ5KFFSZWN0KDE0MCwxNTUsNzAsNjApKQogICAgICAgIHNlbGYuZml2ZS5zZXRUZXh0KCcuLi4nKQogICAgICAgIHNlbGYuYnV0dG9ucy5hcHBlbmQoc2VsZi5maXZlKQogICAgICAgIHNlbGYuc2l4ID0gUVB1c2hCdXR0b24oc2VsZikKICAgICAgICBzZWxmLnNpeC5jbGlja2VkLmNvbm5lY3QobGFtYmRhIGV2ZW50PSAnPEJ1dHRvbi0xPicgOiBzZWxmLnNldF9pdChzZWxmLnNpeCwgNSkpCiAgICAgICAgc2VsZi5zaXguc2V0R2VvbWV0cnkoUVJlY3QoMjQwLDE1NSw3MCw2MCkpCiAgICAgICAgc2VsZi5zaXguc2V0VGV4dCgnLi4uJykKICAgICAgICBzZWxmLmJ1dHRvbnMuYXBwZW5kKHNlbGYuc2l4KQogICAgICAgIHNlbGYuc2V2ZW4gPSBRUHVzaEJ1dHRvbihzZWxmKQogICAgICAgIHNlbGYuc2V2ZW4uY2xpY2tlZC5jb25uZWN0KGxhbWJkYSBldmVudD0gJzxCdXR0b24tMT4nIDogc2VsZi5zZXRfaXQoc2VsZi5zZXZlbiwgNikpCiAgICAgICAgc2VsZi5zZXZlbi5zZXRHZW9tZXRyeShRUmVjdCg0MCwyNDAsNzAsNjApKQogICAgICAgIHNlbGYuc2V2ZW4uc2V0VGV4dCgnLi4uJykKICAgICAgICBzZWxmLmJ1dHRvbnMuYXBwZW5kKHNlbGYuc2V2ZW4pCiAgICAgICAgc2VsZi5laWdodCA9IFFQdXNoQnV0dG9uKHNlbGYpCiAgICAgICAgc2VsZi5laWdodC5jbGlja2VkLmNvbm5lY3QobGFtYmRhIGV2ZW50PSAnPEJ1dHRvbi0xPicgOiBzZWxmLnNldF9pdChzZWxmLmVpZ2h0LCA3KSkKICAgICAgICBzZWxmLmVpZ2h0LnNldEdlb21ldHJ5KFFSZWN0KDE0MCwyNDAsNzAsNjApKQogICAgICAgIHNlbGYuZWlnaHQuc2V0VGV4dCgnLi4uJykKICAgICAgICBzZWxmLmJ1dHRvbnMuYXBwZW5kKHNlbGYuZWlnaHQpCiAgICAgICAgc2VsZi5uaW5lID0gUVB1c2hCdXR0b24oc2VsZikKICAgICAgICBzZWxmLm5pbmUuY2xpY2tlZC5jb25uZWN0KGxhbWJkYSBldmVudD0gJzxCdXR0b24tMT4nIDogc2VsZi5zZXRfaXQoc2VsZi5uaW5lLCA4KSkKICAgICAgICBzZWxmLm5pbmUuc2V0R2VvbWV0cnkoUVJlY3QoMjQwLDI0MCw3MCw2MCkpCiAgICAgICAgc2VsZi5uaW5lLnNldFRleHQoJy4uLicpCiAgICAgICAgc2VsZi5idXR0b25zLmFwcGVuZChzZWxmLm5pbmUpCiAgICAgICAgc2VsZi5yZXN1bHQgPSBRTGFiZWwoJycsIHNlbGYpCiAgICAgICAgc2VsZi5yZXN1bHQuc2V0R2VvbWV0cnkoUVJlY3QoMTI1LDM2MCwxMTEsMTgpKQogICAgICAgIHNlbGYuY3Jvc3Nvcm51bGwgPSBRQ2hlY2tCb3goc2VsZikKICAgICAgICBzZWxmLmNyb3Nzb3JudWxsLnNldEdlb21ldHJ5KFFSZWN0KDMzNSwgMjUsIDE2LCAxNikpCiAgICAgICAgc2VsZi5zdGFydGdhbWUgPSBRUHVzaEJ1dHRvbihzZWxmKQogICAgICAgIHNlbGYuc3RhcnRnYW1lLnNldEdlb21ldHJ5KFFSZWN0KDE3NSwyMCw4MCwzMCkpCiAgICAgICAgc2VsZi5zdGFydGdhbWUuc2V0VGV4dCgi0KHRgtCw0YDRgiEiKQogICAgICAgIHNlbGYuc3RhcnRnYW1lLmNsaWNrZWQuY29ubmVjdChzZWxmLnN0YXJ0KQogICAgICAgIHNlbGYuZm9ybnVsbCA9IFFMYWJlbCgi0JfQsCAn0L3QvtC70LjQuic6Iiwgc2VsZikKICAgICAgICBzZWxmLmZvcm51bGwuc2V0R2VvbWV0cnkoUVJlY3QoMjcwLDI1LCA1NSwxMikpCiAgICAgICAgc2VsZi5zZXRXaW5kb3dUaXRsZSgiVGljLXRhYy10b2UiKQogICAgICAgIHNlbGYubXlsZXZlbCA9IFFDb21ib0JveChzZWxmKQogICAgICAgIHNlbGYubXlsZXZlbC5hZGRJdGVtcyhbJ0Vhc3knLCAnTm9ybWFsJywgJ0RlYWQgZW5kJ10pCiAgICAgICAgc2VsZi5teWxldmVsLnNldEdlb21ldHJ5KFFSZWN0KDg4LDIwLDcwLDMwKSkKICAgICAgICBzZWxmLmxldmVsdGV4dCA9IFFMYWJlbCgn0KHQu9C+0LbQvdC+0YHRgtGMOicsIHNlbGYpCiAgICAgICAgc2VsZi5sZXZlbHRleHQuc2V0R2VvbWV0cnkoMTAsMzAsNTgsMTUpCiAgICAgICAgCiAgICAgICAgc2VsZi5zaG93KCkKCiAgICBkZWYgc2V0X2l0KHNlbGYsIGJ1dHRvbiwgbik6CiAgICAgICAgaWYgc2VsZi5teWxldmVsLmN1cnJlbnRUZXh0KCkgPT0gJ0Vhc3knOgogICAgICAgICAgICBpZiBub3Qgc2VsZi5jcm9zc29ybnVsbC5pc0NoZWNrZWQoKToKICAgICAgICAgICAgICAgIGJ1dHRvbi5zZXRUZXh0KCdYJykKICAgICAgICAgICAgICAgIGJ1dHRvbi5zZXREaXNhYmxlZChUcnVlKQogICAgICAgICAgICAgICAgc2VsZi5ncmlkLnJlbW92ZShuKQogICAgICAgICAgICAgICAgc2VsZi5zdGF0dXNbbl0gPSAnWCcKICAgICAgICAgICAgICAgIGlmIG5vdCBzZWxmLmNoZWNrKCk6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKCdPJykKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIGJ1dHRvbi5zZXRUZXh0KCdPJykKICAgICAgICAgICAgICAgIGJ1dHRvbi5zZXREaXNhYmxlZChUcnVlKQogICAgICAgICAgICAgICAgc2VsZi5ncmlkLnJlbW92ZShuKQogICAgICAgICAgICAgICAgc2VsZi5zdGF0dXNbbl0gPSAnTycKICAgICAgICAgICAgICAgIGlmIG5vdCBzZWxmLmNoZWNrKCk6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKCdYJykKICAgICAgICBlbGlmIHNlbGYubXlsZXZlbC5jdXJyZW50VGV4dCgpID09ICdOb3JtYWwnOgogICAgICAgICAgICBpZiBub3Qgc2VsZi5jcm9zc29ybnVsbC5pc0NoZWNrZWQoKToKICAgICAgICAgICAgICAgIGJ1dHRvbi5zZXRUZXh0KCdYJykKICAgICAgICAgICAgICAgIGJ1dHRvbi5zZXREaXNhYmxlZChUcnVlKQogICAgICAgICAgICAgICAgc2VsZi5ncmlkLnJlbW92ZShuKQogICAgICAgICAgICAgICAgc2VsZi5zdGF0dXNbbl0gPSAnWCcKICAgICAgICAgICAgICAgIGlmIG5vdCBzZWxmLmNoZWNrKCk6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5ub3JtYWxfYWkoJ08nKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgYnV0dG9uLnNldFRleHQoJ08nKQogICAgICAgICAgICAgICAgYnV0dG9uLnNldERpc2FibGVkKFRydWUpCiAgICAgICAgICAgICAgICBzZWxmLmdyaWQucmVtb3ZlKG4pCiAgICAgICAgICAgICAgICBzZWxmLnN0YXR1c1tuXSA9ICdPJwogICAgICAgICAgICAgICAgaWYgbm90IHNlbGYuY2hlY2soKToKICAgICAgICAgICAgICAgICAgICBzZWxmLm5vcm1hbF9haSgnWCcpCiAgICAgICAgZWxpZiBzZWxmLm15bGV2ZWwuY3VycmVudFRleHQoKSA9PSAnRGVhZCBlbmQnOgogICAgICAgICAgICBpZiBub3Qgc2VsZi5jcm9zc29ybnVsbC5pc0NoZWNrZWQoKToKICAgICAgICAgICAgICAgIGJ1dHRvbi5zZXRUZXh0KCdYJykKICAgICAgICAgICAgICAgIGJ1dHRvbi5zZXREaXNhYmxlZChUcnVlKQogICAgICAgICAgICAgICAgc2VsZi5ncmlkLnJlbW92ZShuKQogICAgICAgICAgICAgICAgc2VsZi5zdGF0dXNbbl0gPSAnWCcKICAgICAgICAgICAgICAgIGlmIG5vdCBzZWxmLmNoZWNrKCk6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5kZWFkZW5kX2FpKCdPJykKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIGJ1dHRvbi5zZXRUZXh0KCdPJykKICAgICAgICAgICAgICAgIGJ1dHRvbi5zZXREaXNhYmxlZChUcnVlKQogICAgICAgICAgICAgICAgc2VsZi5ncmlkLnJlbW92ZShuKQogICAgICAgICAgICAgICAgc2VsZi5zdGF0dXNbbl0gPSAnTycKICAgICAgICAgICAgICAgIGlmIG5vdCBzZWxmLmNoZWNrKCk6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5kZWFkZW5kX2FpKCdYJykKICAgICAgICAgICAgCiAgICBkZWYgc3RhcnQoc2VsZik6CiAgICAgICAgc2VsZi50dXJuID0gMAogICAgICAgIHNlbGYuZmluaXNoID0gMAogICAgICAgIHNlbGYuZ3JpZCA9IFswLDEsMiwzLDQsNSw2LDcsOF0KICAgICAgICBzZWxmLnN0YXR1cyA9IFsnZScsJ2UnLCdlJywnZScsJ2UnLCdlJywnZScsJ2UnLCdlJ10KICAgICAgICBmb3IgZWxlbSBpbiBzZWxmLmJ1dHRvbnM6CiAgICAgICAgICAgIGVsZW0uc2V0VGV4dCgnLi4uJykKICAgICAgICAgICAgZWxlbS5zZXREaXNhYmxlZChGYWxzZSkKICAgICAgICBzZWxmLnJlc3VsdC5zZXRUZXh0KCcnKQogICAgICAgIGlmIHNlbGYuY3Jvc3Nvcm51bGwuaXNDaGVja2VkKCk6CiAgICAgICAgICAgIGlmIHNlbGYubXlsZXZlbC5jdXJyZW50VGV4dCgpID09ICdFYXN5JzoKICAgICAgICAgICAgICAgIHNlbGYuZWFzeV9haSgnWCcpCiAgICAgICAgICAgIGVsaWYgc2VsZi5teWxldmVsLmN1cnJlbnRUZXh0KCkgPT0gJ05vcm1hbCc6CiAgICAgICAgICAgICAgICBzZWxmLm5vcm1hbF9haSgnWCcpCiAgICAgICAgICAgIGVsaWYgc2VsZi5teWxldmVsLmN1cnJlbnRUZXh0KCkgPT0gJ0RlYWQgZW5kJzoKICAgICAgICAgICAgICAgIHNlbGYuZGVhZGVuZF9haSgnWCcpCiAgICAgICAgICAgICAgICAKICAgIGRlZiBlYXN5X2FpIChzZWxmLCBzaWduLCBjaG9vc2U9JycpOgogICAgICAgIGlmIGxlbihzZWxmLmdyaWQpID4gMDoKICAgICAgICAgICAgaWYgY2hvb3NlID09ICcnOgogICAgICAgICAgICAgICAgY2hvb3NlID0gY2hvaWNlKHNlbGYuZ3JpZCkKICAgICAgICAgICAgc2VsZi5ncmlkLnJlbW92ZShjaG9vc2UpCiAgICAgICAgICAgIGlmIGNob29zZSA9PSAwOgogICAgICAgICAgICAgICAgc2VsZi5vbmUuc2V0VGV4dChzaWduKQogICAgICAgICAgICAgICAgc2VsZi5vbmUuc2V0RGlzYWJsZWQoVHJ1ZSkKICAgICAgICAgICAgZWxpZiBjaG9vc2UgPT0gMToKICAgICAgICAgICAgICAgIHNlbGYudHdvLnNldFRleHQoc2lnbikKICAgICAgICAgICAgICAgIHNlbGYudHdvLnNldERpc2FibGVkKFRydWUpCiAgICAgICAgICAgIGVsaWYgY2hvb3NlID09IDI6CiAgICAgICAgICAgICAgICBzZWxmLnRocmVlLnNldFRleHQoc2lnbikKICAgICAgICAgICAgICAgIHNlbGYudGhyZWUuc2V0RGlzYWJsZWQoVHJ1ZSkKICAgICAgICAgICAgZWxpZiBjaG9vc2UgPT0gMzoKICAgICAgICAgICAgICAgIHNlbGYuZm91ci5zZXRUZXh0KHNpZ24pCiAgICAgICAgICAgICAgICBzZWxmLmZvdXIuc2V0RGlzYWJsZWQoVHJ1ZSkKICAgICAgICAgICAgZWxpZiBjaG9vc2UgPT0gNDoKICAgICAgICAgICAgICAgIHNlbGYuZml2ZS5zZXRUZXh0KHNpZ24pCiAgICAgICAgICAgICAgICBzZWxmLmZpdmUuc2V0RGlzYWJsZWQoVHJ1ZSkKICAgICAgICAgICAgZWxpZiBjaG9vc2UgPT0gNToKICAgICAgICAgICAgICAgIHNlbGYuc2l4LnNldFRleHQoc2lnbikKICAgICAgICAgICAgICAgIHNlbGYuc2l4LnNldERpc2FibGVkKFRydWUpCiAgICAgICAgICAgIGVsaWYgY2hvb3NlID09IDY6CiAgICAgICAgICAgICAgICBzZWxmLnNldmVuLnNldFRleHQoc2lnbikKICAgICAgICAgICAgICAgIHNlbGYuc2V2ZW4uc2V0RGlzYWJsZWQoVHJ1ZSkKICAgICAgICAgICAgZWxpZiBjaG9vc2UgPT0gNzoKICAgICAgICAgICAgICAgIHNlbGYuZWlnaHQuc2V0VGV4dChzaWduKQogICAgICAgICAgICAgICAgc2VsZi5laWdodC5zZXREaXNhYmxlZChUcnVlKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgc2VsZi5uaW5lLnNldFRleHQoc2lnbikKICAgICAgICAgICAgICAgIHNlbGYubmluZS5zZXREaXNhYmxlZChUcnVlKQogICAgICAgICAgICBzZWxmLnN0YXR1c1tjaG9vc2VdID0gc2lnbgogICAgICAgICAgICBzZWxmLmNoZWNrKCkKCiAgICBkZWYgbm9ybWFsX2FpKHNlbGYsIHNpZ24sIGhscD0wKToKICAgICAgICB0ZXN0ID0gMAogICAgICAgIHAgPSAwICN+ISEhIQogICAgICAgIGlmIHNpZ24gPT0gJ08nOgogICAgICAgICAgICBlbmVteSA9ICdYJwogICAgICAgIGVsc2U6IGVuZW15ID0gJ08nCiAgICAgICAgaWYgbGVuKHNlbGYuZ3JpZCkgPj0gODoKICAgICAgICAgICAgc2VsZi5lYXN5X2FpKHNpZ24pCiAgICAgICAgZWxzZToKICAgICAgICAgICAgZm9yIGVsZW0gaW4gc2VsZi5saW5lczoKICAgICAgICAgICAgICAgIGZvciBpIGluIGVsZW06CiAgICAgICAgICAgICAgICAgICAgaWYgc2VsZi5zdGF0dXNbaV0gPT0gc2lnbjoKICAgICAgICAgICAgICAgICAgICAgICAgdGVzdCs9MQogICAgICAgICAgICAgICAgICAgIGlmIHRlc3QgPiAxIGFuZCBhbnkoc2VsZi5zdGF0dXNba10gPT0gJ2UnIGZvciBrIGluIGVsZW0pOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmVhc3lfYWkoc2lnbiwgaW50KGxpc3QoZmlsdGVyKGxhbWJkYSBqIDogc2VsZi5zdGF0dXNbal0gPT0gJ2UnLCBlbGVtKSlbMF0pKQogICAgICAgICAgICAgICAgICAgICAgICBwKz0xCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgICAgICBpZiB0ZXN0ID4gMSBhbmQgcCA+IDA6CiAgICAgICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgICAgIHRlc3QgPSAwCgogICAgICAgICAgICBpZiBwID09IDA6CiAgICAgICAgICAgICAgICB0ZXN0ID0gMAogICAgICAgICAgICAgICAgZm9yIGVsZW0gaW4gc2VsZi5saW5lczoKICAgICAgICAgICAgICAgICAgICBmb3IgaSBpbiBlbGVtOgogICAgICAgICAgICAgICAgICAgICAgICBpZiBzZWxmLnN0YXR1c1tpXSA9PSBlbmVteToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlc3QrPTEKICAgICAgICAgICAgICAgICAgICAgICAgaWYgdGVzdCA+IDEgYW5kIGFueShzZWxmLnN0YXR1c1trXSA9PSAnZScgZm9yIGsgaW4gZWxlbSk6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmVhc3lfYWkoc2lnbiwgaW50KGxpc3QoZmlsdGVyKGxhbWJkYSBqIDogc2VsZi5zdGF0dXNbal0gPT0gJ2UnLCBlbGVtKSlbMF0pKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcCs9MQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsKICAgICAgICAgICAgICAgICAgICBpZiB0ZXN0ID4gMSBhbmQgcCA+IDA6CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgICAgICAgICAgdGVzdCA9IDAKICAgICAgICAgICAgaWYgdGVzdCA8PSAxIGFuZCBwID09IDA6CiAgICAgICAgICAgICAgICBpZiBobHAgPT0gMDoKICAgICAgICAgICAgICAgICAgICBzZWxmLmVhc3lfYWkoc2lnbikKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5kZWFkZW5kX2FpKHNpZ24sIGlhbT0wKQoKICAgIGRlZiBkZWFkZW5kX2FpKHNlbGYsIHNpZ24sIGlhbT0xKToKICAgICAgICBhcnIgPSBbMCwyLDYsOF0KICAgICAgICBsaW4gPSBbMSw1LDcsM10KICAgICAgICBpZiBzaWduID09ICdYJzoKICAgICAgICAgICAgaWYgc2VsZi50dXJuID09IDA6CiAgICAgICAgICAgICAgICBzZWxmLmVhc3lfYWkoc2lnbiwgNCkKICAgICAgICAgICAgICAgIHNlbGYudHVybis9MQogICAgICAgICAgICBlbGlmIHNlbGYudHVybiA9PSAxOgogICAgICAgICAgICAgICAgc2VsZi50dXJuKz0xCiAgICAgICAgICAgICAgICBpZiBzZWxmLnN0YXR1c1swXSA9PSAnTyc6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKHNpZ24sIDgpCiAgICAgICAgICAgICAgICBlbGlmIHNlbGYuc3RhdHVzWzFdID09ICdPJzoKICAgICAgICAgICAgICAgICAgICBzZWxmLmVhc3lfYWkoc2lnbiwgNikKICAgICAgICAgICAgICAgIGVsaWYgc2VsZi5zdGF0dXNbMl0gPT0gJ08nOgogICAgICAgICAgICAgICAgICAgIHNlbGYuZWFzeV9haShzaWduLCA2KQogICAgICAgICAgICAgICAgZWxpZiBzZWxmLnN0YXR1c1szXSA9PSAnTyc6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKHNpZ24sIDIpCiAgICAgICAgICAgICAgICBlbGlmIHNlbGYuc3RhdHVzWzVdID09ICdPJzoKICAgICAgICAgICAgICAgICAgICBzZWxmLmVhc3lfYWkoc2lnbiwgNikKICAgICAgICAgICAgICAgIGVsaWYgc2VsZi5zdGF0dXNbNl0gPT0gJ08nOgogICAgICAgICAgICAgICAgICAgIHNlbGYuZWFzeV9haShzaWduLCAyKQogICAgICAgICAgICAgICAgZWxpZiBzZWxmLnN0YXR1c1s3XSA9PSAnTyc6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKHNpZ24sIDApCiAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgIHNlbGYuZWFzeV9haShzaWduLCAwKQogICAgICAgICAgICBlbGlmIHNlbGYudHVybiA+IDE6CiAgICAgICAgICAgICAgICBzZWxmLm5vcm1hbF9haShzaWduKQogICAgICAgIGVsaWYgc2lnbiA9PSAnTyc6CiAgICAgICAgICAgIGlmIHNlbGYudHVybiA9PSAwOgogICAgICAgICAgICAgICAgc2VsZi50dXJuKz0xCiAgICAgICAgICAgICAgICBpZiBzZWxmLnN0YXR1c1s0XSA9PSAnWCc6CiAgICAgICAgICAgICAgICAgICAgbiA9IGNob2ljZShhcnIpCiAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKHNpZ24sIG4pCiAgICAgICAgICAgICAgICAgICAgc2VsZi5maXJzdF9jcm9zcyA9ICdjJwogICAgICAgICAgICAgICAgZWxpZiBzZWxmLnN0YXR1c1s0XSAhPSAnWCcgYW5kIChzZWxmLnN0YXR1c1swXSA9PSAnWCcgb3Igc2VsZi5zdGF0dXNbMl0gPT0gJ1gnIG9yIHNlbGYuc3RhdHVzWzZdID09ICdYJyBvciAgc2VsZi5zdGF0dXNbOF0gPT0gJ1gnKToKICAgICAgICAgICAgICAgICAgICBzZWxmLmVhc3lfYWkoc2lnbiwgNCkKICAgICAgICAgICAgICAgICAgICBzZWxmLmZpcnN0X2Nyb3NzID0gJ2NvJwogICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICBzZWxmLmZpcnN0X2Nyb3NzID0gJ2xpbmUnCiAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKHNpZ24sIDQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgZWxpZiBzZWxmLnR1cm4gPiAwIGFuZCBzZWxmLmZpcnN0X2Nyb3NzID09ICdjJzoKICAgICAgICAgICAgICAgIGlmIGlhbT09MToKICAgICAgICAgICAgICAgICAgICBzZWxmLm5vcm1hbF9haShzaWduLCBobHA9MSkKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgICAgICBuID0gY2hvaWNlKFtpIGZvciBpIGluIGFyciBpZiBpIGluIHNlbGYuZ3JpZF0pCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuZWFzeV9haShzaWduLCBuKQogICAgICAgICAgICAgICAgICAgIGV4Y2VwdDoKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKHNpZ24pCiAgICAgICAgICAgIGVsaWYgc2VsZi50dXJuID4gMCBhbmQgc2VsZi5maXJzdF9jcm9zcyA9PSAgJ2NvJzoKICAgICAgICAgICAgICAgIGlmIHNlbGYudHVybiA9PSAxOgogICAgICAgICAgICAgICAgICAgIGlmIGlhbSA9PSAxOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLm5vcm1hbF9haShzaWduLCBobHA9MSkKICAgICAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnR1cm4rPTEKICAgICAgICAgICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgc2VsZi5zdGF0dXNbMF0gPT0gJ1gnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuZWFzeV9haShzaWduLCA4KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxpZiBzZWxmLnN0YXR1c1syXSA9PSAnWCc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKHNpZ24sIDYpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGlmIHNlbGYuc3RhdHVzWzZdID09ICdYJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmVhc3lfYWkoc2lnbiwgMikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsaWYgc2VsZi5zdGF0dXNbOF0gPT0gJ1gnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuZWFzeV9haShzaWduLCAwKQogICAgICAgICAgICAgICAgICAgICAgICBleGNlcHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuID0gY2hvaWNlKFtpIGZvciBpIGluIGxpbiBpZiBpIGluIHNlbGYuZ3JpZF0pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmVhc3lfYWkoc2lnbiwgbikKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5ub3JtYWxfYWkoc2lnbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICBlbGlmIHNlbGYudHVybiA+IDAgYW5kIHNlbGYuZmlyc3RfY3Jvc3MgPT0gICdsaW5lJzoKICAgICAgICAgICAgICAgIGlmIHNlbGYudHVybiA9PSAxOgogICAgICAgICAgICAgICAgICAgIGlmIGlhbSA9PSAxOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLm5vcm1hbF9haShzaWduLCBobHA9MSkKICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICAgICAgaWYgc2VsZi5zdGF0dXNbMF0gPT0gJ1gnIG9yIHNlbGYuc3RhdHVzWzJdID09ICdYJyBvciBzZWxmLnN0YXR1c1s2XSA9PSAnWCcgb3Igc2VsZi5zdGF0dXNbOF0gPT0gJ1gnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpbnQoJyEyMjJAJykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiBzZWxmLnN0YXR1c1swXSA9PSAnWCc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuZWFzeV9haShzaWduLCA4KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsaWYgc2VsZi5zdGF0dXNbMl0gPT0gJ1gnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmVhc3lfYWkoc2lnbiwgNikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGlmIHNlbGYuc3RhdHVzWzZdID09ICdYJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKHNpZ24sIDIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxpZiBzZWxmLnN0YXR1c1s4XSA9PSAnWCc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuZWFzeV9haShzaWduLCAwKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYudHVybis9MQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZXB0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYubm9ybWFsX2FpKHNpZ24pCiAgICAgICAgICAgICAgICAgICAgICAgIGVsaWYgKHNlbGYuc3RhdHVzWzFdID09ICdYJyBhbmQgc2VsZi5zdGF0dXNbN10gPT0gJ1gnKSBvciAoc2VsZi5zdGF0dXNbM10gPT0gJ1gnIGFuZCBzZWxmLnN0YXR1c1s1XSA9PSAnWCcpOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgbiA9IGNob2ljZShhcnIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmVhc3lfYWkoc2lnbiwgbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYudHVybis9MQogICAgICAgICAgICAgICAgICAgICAgICBlbGlmICgoc2VsZi5zdGF0dXNbM10gPT0gJ1gnIGFuZCBzZWxmLnN0YXR1c1sxXSA9PSAnWCcpIG9yIChzZWxmLnN0YXR1c1sxXSA9PSAnWCcgYW5kIHNlbGYuc3RhdHVzWzVdID09ICdYJykgb3IKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHNlbGYuc3RhdHVzWzVdID09ICdYJyBhbmQgc2VsZi5zdGF0dXNbN10gPT0gJ1gnKSBvciAoc2VsZi5zdGF0dXNbN10gPT0gJ1gnIGFuZCBzZWxmLnN0YXR1c1szXSA9PSAnWCcpKToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLnN0YXR1c1szXSA9PSAnWCcgYW5kIHNlbGYuc3RhdHVzWzFdID09ICdYJyk6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKHNpZ24sIDApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGlmIChzZWxmLnN0YXR1c1sxXSA9PSAnWCcgYW5kIHNlbGYuc3RhdHVzWzVdID09ICdYJyk6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKHNpZ24sIDIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGlmIChzZWxmLnN0YXR1c1s1XSA9PSAnWCcgYW5kIHNlbGYuc3RhdHVzWzddID09ICdYJyk6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKHNpZ24sIDgpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGlmIChzZWxmLnN0YXR1c1s3XSA9PSAnWCcgYW5kIHNlbGYuc3RhdHVzWzNdID09ICdYJyk6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5lYXN5X2FpKHNpZ24sIDYpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnR1cm4rPTEgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBlbGlmIHNlbGYudHVybiA+IDE6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5ub3JtYWxfYWkoc2lnbikKICAgICAgICAgICAgICAgICAgICAgICAgCiAgICBkZWYgY2hlY2soc2VsZik6ICAgIAogICAgICAgIGZvciBlbGVtIGluIHNlbGYubGluZXM6CiAgICAgICAgICAgIGlmIGFsbChzZWxmLnN0YXR1c1tpXSA9PSAnWCcgZm9yIGkgaW4gZWxlbSkgYW5kIG5vdCBzZWxmLmNyb3Nzb3JudWxsLmlzQ2hlY2tlZCgpOgogICAgICAgICAgICAgICAgc2VsZi5yZXN1bHQuc2V0VGV4dCgiPGh0bWw+PGhlYWQvPjxib2R5PjxwPjxzcGFuIHN0eWxlPVwiIGZvbnQtc2l6ZToxMnB0OyBjb2xvcjpncmVlbjtcIj7QktGLINCy0YvQuNCz0YDQsNC70LghPC9zcGFuPjwvcD48L2JvZHk+PC9odG1sPiIpCiAgICAgICAgICAgICAgICBzZWxmLmZpbmlzaCArPSAxCiAgICAgICAgICAgIGlmIGFsbChzZWxmLnN0YXR1c1tpXSA9PSAnWCcgZm9yIGkgaW4gZWxlbSkgYW5kIHNlbGYuY3Jvc3Nvcm51bGwuaXNDaGVja2VkKCk6CiAgICAgICAgICAgICAgICBzZWxmLnJlc3VsdC5zZXRUZXh0KCI8aHRtbD48aGVhZC8+PGJvZHk+PHA+PHNwYW4gc3R5bGU9XCIgZm9udC1zaXplOjEycHQ7IGNvbG9yOnJlZDtcIj7QktGLINC/0YDQvtC40LPRgNCw0LvQuC48L3NwYW4+PC9wPjwvYm9keT48L2h0bWw+IikKICAgICAgICAgICAgICAgIHNlbGYuZmluaXNoKz0xCiAgICAgICAgICAgIGlmIGFsbChzZWxmLnN0YXR1c1tpXSA9PSAnTycgZm9yIGkgaW4gZWxlbSkgYW5kICBzZWxmLmNyb3Nzb3JudWxsLmlzQ2hlY2tlZCgpOgogICAgICAgICAgICAgICAgc2VsZi5yZXN1bHQuc2V0VGV4dCgiPGh0bWw+PGhlYWQvPjxib2R5PjxwPjxzcGFuIHN0eWxlPVwiIGZvbnQtc2l6ZToxMnB0OyBjb2xvcjpncmVlbjtcIj7QktGLINCy0YvQuNCz0YDQsNC70LghPC9zcGFuPjwvcD48L2JvZHk+PC9odG1sPiIpCiAgICAgICAgICAgICAgICBzZWxmLmZpbmlzaCs9MQogICAgICAgICAgICBpZiBhbGwoc2VsZi5zdGF0dXNbaV0gPT0gJ08nIGZvciBpIGluIGVsZW0pIGFuZCAgbm90IHNlbGYuY3Jvc3Nvcm51bGwuaXNDaGVja2VkKCk6CiAgICAgICAgICAgICAgICBzZWxmLnJlc3VsdC5zZXRUZXh0KCI8aHRtbD48aGVhZC8+PGJvZHk+PHA+PHNwYW4gc3R5bGU9XCIgZm9udC1zaXplOjEycHQ7IGNvbG9yOnJlZDtcIj7QktGLINC/0YDQvtC40LPRgNCw0LvQuC48L3NwYW4+PC9wPjwvYm9keT48L2h0bWw+IikKICAgICAgICAgICAgICAgIHNlbGYuZmluaXNoKz0xCiAgICAgICAgaWYgbGVuKHNlbGYuZ3JpZCkgPCAxIGFuZCBzZWxmLmZpbmlzaCA9PSAwOgogICAgICAgICAgICBzZWxmLnJlc3VsdC5zZXRUZXh0KCI8aHRtbD48aGVhZC8+PGJvZHk+PHA+PHNwYW4gc3R5bGU9XCIgZm9udC1zaXplOjEycHQ7IGNvbG9yOmdyZXk7XCI+PGNlbnRlcj7QndC40YfRjNGPLjwvY2VudGVyPjwvc3Bhbj48L3A+PC9ib2R5PjwvaHRtbD4iKQogICAgICAgIGlmIHNlbGYuZmluaXNoID4gMDoKICAgICAgICAgICAgcmV0dXJuIFRydWUKICAgICAgICAKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIGltcG9ydCBzeXMKICAgIGFwcCA9IFFBcHBsaWNhdGlvbihzeXMuYXJndikKICAgIHdpbmRvdyA9IFRvZSgpCiAgICBzeXMuZXhpdChhcHAuZXhlY18oKSk=