#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
#
# generated by wxGlade 1.0.4 on Tue Apr 25 15:00:54 2023
#
import wx
# begin wxGlade: dependencies
# end wxGlade
# begin wxGlade: extracode
from pubsub import pub
from simple_database import Env, install_package, interp
import sys
class Controller(object):
def __init__(self):
pub.subscribe(self.read, "Controller")
self.table = {"OnNewFile": "new_file",
"OnOpen": "open_file",
"OnSaveFile": "save_file",
"OnSaveFileAs": "save_file_as",
"OnQuit": "quit",
"OnAddCD": "insert_value",
"Delete": "delete"}
def read(self, x, env):
pub.sendMessage("Model.eval",
x = [self.table[x[0]]] + x[1:],
env = env)
class Model(object):
def __init__(self):
pub.subscribe(self.eval, "Model")
def eval(self, x, env):
pub.sendMessage("View.SetProperties", env = interp(x, env))
def OnNewFile(self):
with NewFile(self) as fileDialog:
if fileDialog.ShowModal() == wx.ID_CANCEL:
return
pub.sendMessage("Controller.read",
x = ["OnNewFile", fileDialog.GetPath()],
env = self.env)
def OnOpen(self):
with OpenFile(self) as fileDialog:
if fileDialog.ShowModal() == wx.ID_CANCEL:
return
pub.sendMessage("Controller.read",
x = ["OnOpen", fileDialog.GetPath()],
env = self.env)
def OnSaveFileAs(self):
with SaveFileAs(self) as fileDialog:
if fileDialog.ShowModal() == wx.ID_CANCEL:
return
pub.sendMessage("Controller.read",
x = ["OnSaveFileAs", fileDialog.GetPath()],
env = self.env)
# end wxGlade
class View(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: View.__init__
self.env = install_package()
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((400, 300))
self.SetTitle("Simple Database")
# Menu Bar
self.frame_menubar = wx.MenuBar()
wxglade_tmp_menu = wx.Menu()
item = wxglade_tmp_menu.Append(wx.ID_ANY, u"新規作成\tCtrl+N", "")
self.Bind(wx.EVT_MENU, self.lambda event: OnNewFile(self), item)
item = wxglade_tmp_menu.Append(wx.ID_ANY, u"開く...\tCtrl+O", "")
self.Bind(wx.EVT_MENU, self.lambda event: OnOpen(self), item)
item = wxglade_tmp_menu.Append(wx.ID_ANY, u"保存\tCtrl+S", "")
self.Bind(wx.EVT_MENU, lambda event: pub.sendMessage('Controller.read', x = ['OnSaveFile'], env = self.env), item)
item = wxglade_tmp_menu.Append(wx.ID_ANY, u"名前を付けて保存...\tShift+Ctrl+S", "")
self.Bind(wx.EVT_MENU, self.lambda event: OnSaveAs(self), item)
item = wxglade_tmp_menu.Append(wx.ID_ANY, "Quit\tCtrl+Q", "")
self.Bind(wx.EVT_MENU, lambda event: pub.sendMessage('Controller.read', x = ['OnQuit'], env = self.env), item)
self.frame_menubar.Append(wxglade_tmp_menu, u"ファイル")
self.SetMenuBar(self.frame_menubar)
# Menu Bar end
sizer_1 = wx.BoxSizer(wx.VERTICAL)
self.AddCD = wx.Button(self, wx.ID_ANY, "AddCD")
sizer_1.Add(self.AddCD, 0, 0, 0)
self.list_ctrl_1 = wx.ListCtrl(self, wx.ID_ANY, style=wx.LC_HRULES | wx.LC_REPORT | wx.LC_VRULES)
self.list_ctrl_1.AppendColumn(u"タイトル", format=wx.LIST_FORMAT_LEFT, width=-1)
self.list_ctrl_1.AppendColumn(u"アーティスト", format=wx.LIST_FORMAT_LEFT, width=-1)
self.list_ctrl_1.AppendColumn(u"レーティング", format=wx.LIST_FORMAT_LEFT, width=-1)
self.list_ctrl_1.AppendColumn(u"リップ", format=wx.LIST_FORMAT_LEFT, width=-1)
sizer_1.Add(self.list_ctrl_1, 1, wx.EXPAND, 0)
self.SetSizer(sizer_1)
self.Layout()
pub.subscribe(self.SetProperties, 'View')
self.Bind(wx.EVT_BUTTON, lambda event: AddCDDialog(self).ShowModal(), self.AddCD)
self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.rclick, self.list_ctrl_1)
# end wxGlade
def rclick(self, event): # wxGlade: View.<event_handler>
print("Event handler 'rclick' not implemented!")
event.Skip()
# end of class View
class AddCDDialog(wx.Dialog):
def __init__(self, *args, **kwds):
# begin wxGlade: AddCDDialog.__init__
self.env = args[0].env
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE
wx.Dialog.__init__(self, *args, **kwds)
self.SetTitle("Add CD")
sizer_1 = wx.BoxSizer(wx.VERTICAL)
grid_sizer_1 = wx.GridSizer(4, 2, 0, 0)
sizer_1.Add(grid_sizer_1, 1, wx.EXPAND, 0)
Title = wx.StaticText(self, wx.ID_ANY, u"タイトル")
grid_sizer_1.Add(Title, 0, wx.ALIGN_CENTER, 0)
self.text_ctrl_1 = wx.TextCtrl(self, wx.ID_ANY, "")
grid_sizer_1.Add(self.text_ctrl_1, 0, wx.ALIGN_CENTER, 0)
Artist = wx.StaticText(self, wx.ID_ANY, u"アーティスト")
grid_sizer_1.Add(Artist, 0, wx.ALIGN_CENTER, 0)
self.text_ctrl_2 = wx.TextCtrl(self, wx.ID_ANY, "")
grid_sizer_1.Add(self.text_ctrl_2, 0, wx.ALIGN_CENTER, 0)
Rating = wx.StaticText(self, wx.ID_ANY, u"レーティング")
grid_sizer_1.Add(Rating, 0, wx.ALIGN_CENTER, 0)
self.text_ctrl_3 = wx.TextCtrl(self, wx.ID_ANY, "")
grid_sizer_1.Add(self.text_ctrl_3, 0, wx.ALIGN_CENTER, 0)
Ripped = wx.StaticText(self, wx.ID_ANY, u"リップ")
grid_sizer_1.Add(Ripped, 0, wx.ALIGN_CENTER, 0)
self.text_ctrl_4 = wx.TextCtrl(self, wx.ID_ANY, "")
grid_sizer_1.Add(self.text_ctrl_4, 0, wx.ALIGN_CENTER, 0)
sizer_2 = wx.StdDialogButtonSizer()
sizer_1.Add(sizer_2, 0, wx.ALIGN_RIGHT | wx.ALL, 4)
self.button_OK = wx.Button(self, wx.ID_OK, "")
self.button_OK.SetDefault()
sizer_2.AddButton(self.button_OK)
self.button_CANCEL = wx.Button(self, wx.ID_CANCEL, "")
sizer_2.AddButton(self.button_CANCEL)
sizer_2.Realize()
self.SetSizer(sizer_1)
sizer_1.Fit(self)
self.SetAffirmativeId(self.button_OK.GetId())
self.SetEscapeId(self.button_CANCEL.GetId())
self.Layout()
self.Bind(wx.EVT_BUTTON, lambda event: self.OnAddCD(), self.button_OK)
self.Bind(wx.EVT_BUTTON, lambda event: self.Destroy(), self.button_CANCEL)
# end wxGlade
# end of class AddCDDialog
class NewFile(wx.Dialog):
def __init__(self, *args, **kwds):
# begin wxGlade: NewFile.__init__
self.env = args[0].env
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE
wx.Dialog.__init__(self, *args, **kwds)
self.SetTitle(u"新規作成")
self.Layout()
# end wxGlade
# end of class NewFile
class OpenFile(wx.Dialog):
def __init__(self, *args, **kwds):
# begin wxGlade: OpenFile.__init__
self.env = args[0].env
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE
wx.Dialog.__init__(self, *args, **kwds)
self.SetTitle(u"開く...")
self.Layout()
# end wxGlade
# end of class OpenFile
class SaveFileAs(wx.Dialog):
def __init__(self, *args, **kwds):
# begin wxGlade: SaveFileAs.__init__
self.env = args[0].env
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_DIALOG_STYLE
wx.Dialog.__init__(self, *args, **kwds)
self.SetTitle(u"名前を付けて保存...")
self.Layout()
# end wxGlade
# end of class SaveFileAs
class SimpleDatabase(wx.App):
def OnInit(self):
self.View = View(None, wx.ID_ANY, "")
self.SetTopWindow(self.View)
self.View.Show()
return True
# end of class SimpleDatabase
if __name__ == "__main__":
SimpleDatabase = SimpleDatabase(0)
SimpleDatabase.MainLoop()
IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwojIC0qLSBjb2Rpbmc6IFVURi04IC0qLQojCiMgZ2VuZXJhdGVkIGJ5IHd4R2xhZGUgMS4wLjQgb24gVHVlIEFwciAyNSAxNTowMDo1NCAyMDIzCiMKCmltcG9ydCB3eAoKIyBiZWdpbiB3eEdsYWRlOiBkZXBlbmRlbmNpZXMKIyBlbmQgd3hHbGFkZQoKIyBiZWdpbiB3eEdsYWRlOiBleHRyYWNvZGUKZnJvbSBwdWJzdWIgaW1wb3J0IHB1Ygpmcm9tIHNpbXBsZV9kYXRhYmFzZSBpbXBvcnQgRW52LCBpbnN0YWxsX3BhY2thZ2UsIGludGVycAppbXBvcnQgc3lzCgpjbGFzcyBDb250cm9sbGVyKG9iamVjdCk6CiAgICBkZWYgX19pbml0X18oc2VsZik6CiAgICAgICAgcHViLnN1YnNjcmliZShzZWxmLnJlYWQsICJDb250cm9sbGVyIikKICAgICAgICBzZWxmLnRhYmxlID0geyJPbk5ld0ZpbGUiOiAibmV3X2ZpbGUiLAogICAgICAgICAgICAgICAgICAgICAgIk9uT3BlbiI6ICJvcGVuX2ZpbGUiLAogICAgICAgICAgICAgICAgICAgICAgIk9uU2F2ZUZpbGUiOiAic2F2ZV9maWxlIiwKICAgICAgICAgICAgICAgICAgICAgICJPblNhdmVGaWxlQXMiOiAic2F2ZV9maWxlX2FzIiwKICAgICAgICAgICAgICAgICAgICAgICJPblF1aXQiOiAicXVpdCIsCiAgICAgICAgICAgICAgICAgICAgICAiT25BZGRDRCI6ICJpbnNlcnRfdmFsdWUiLAogICAgICAgICAgICAgICAgICAgICAgIkRlbGV0ZSI6ICJkZWxldGUifQogICAgZGVmIHJlYWQoc2VsZiwgeCwgZW52KToKICAgICAgICBwdWIuc2VuZE1lc3NhZ2UoIk1vZGVsLmV2YWwiLAogICAgICAgICAgICAgICAgICAgICAgICB4ID0gW3NlbGYudGFibGVbeFswXV1dICsgeFsxOl0sCiAgICAgICAgICAgICAgICAgICAgICAgIGVudiA9IGVudikKCmNsYXNzIE1vZGVsKG9iamVjdCk6CiAgICBkZWYgX19pbml0X18oc2VsZik6CiAgICAgICAgcHViLnN1YnNjcmliZShzZWxmLmV2YWwsICJNb2RlbCIpCiAgICBkZWYgZXZhbChzZWxmLCB4LCBlbnYpOgogICAgICAgIHB1Yi5zZW5kTWVzc2FnZSgiVmlldy5TZXRQcm9wZXJ0aWVzIiwgZW52ID0gaW50ZXJwKHgsIGVudikpCmRlZiBPbk5ld0ZpbGUoc2VsZik6CiAgICB3aXRoIE5ld0ZpbGUoc2VsZikgYXMgZmlsZURpYWxvZzoKICAgICAgICBpZiBmaWxlRGlhbG9nLlNob3dNb2RhbCgpID09IHd4LklEX0NBTkNFTDoKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgcHViLnNlbmRNZXNzYWdlKCJDb250cm9sbGVyLnJlYWQiLAogICAgICAgICAgICAgICAgICAgICAgICB4ID0gWyJPbk5ld0ZpbGUiLCBmaWxlRGlhbG9nLkdldFBhdGgoKV0sCiAgICAgICAgICAgICAgICAgICAgICAgIGVudiA9IHNlbGYuZW52KQpkZWYgT25PcGVuKHNlbGYpOgogICAgd2l0aCBPcGVuRmlsZShzZWxmKSBhcyBmaWxlRGlhbG9nOgogICAgICAgIGlmIGZpbGVEaWFsb2cuU2hvd01vZGFsKCkgPT0gd3guSURfQ0FOQ0VMOgogICAgICAgICAgICByZXR1cm4KICAgICAgICBwdWIuc2VuZE1lc3NhZ2UoIkNvbnRyb2xsZXIucmVhZCIsCiAgICAgICAgICAgICAgICAgICAgICAgIHggPSBbIk9uT3BlbiIsIGZpbGVEaWFsb2cuR2V0UGF0aCgpXSwKICAgICAgICAgICAgICAgICAgICAgICAgZW52ID0gc2VsZi5lbnYpCmRlZiBPblNhdmVGaWxlQXMoc2VsZik6CiAgICB3aXRoIFNhdmVGaWxlQXMoc2VsZikgYXMgZmlsZURpYWxvZzoKICAgICAgICBpZiBmaWxlRGlhbG9nLlNob3dNb2RhbCgpID09IHd4LklEX0NBTkNFTDoKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgcHViLnNlbmRNZXNzYWdlKCJDb250cm9sbGVyLnJlYWQiLAogICAgICAgICAgICAgICAgICAgICAgICB4ID0gWyJPblNhdmVGaWxlQXMiLCBmaWxlRGlhbG9nLkdldFBhdGgoKV0sCiAgICAgICAgICAgICAgICAgICAgICAgIGVudiA9IHNlbGYuZW52KQojIGVuZCB3eEdsYWRlCgoKY2xhc3MgVmlldyh3eC5GcmFtZSk6CiAgICBkZWYgX19pbml0X18oc2VsZiwgKmFyZ3MsICoqa3dkcyk6CiAgICAgICAgIyBiZWdpbiB3eEdsYWRlOiBWaWV3Ll9faW5pdF9fCiAgICAgICAgc2VsZi5lbnYgPSBpbnN0YWxsX3BhY2thZ2UoKQogICAgICAgIGt3ZHNbInN0eWxlIl0gPSBrd2RzLmdldCgic3R5bGUiLCAwKSB8IHd4LkRFRkFVTFRfRlJBTUVfU1RZTEUKICAgICAgICB3eC5GcmFtZS5fX2luaXRfXyhzZWxmLCAqYXJncywgKiprd2RzKQogICAgICAgIHNlbGYuU2V0U2l6ZSgoNDAwLCAzMDApKQogICAgICAgIHNlbGYuU2V0VGl0bGUoIlNpbXBsZSBEYXRhYmFzZSIpCgogICAgICAgICMgTWVudSBCYXIKICAgICAgICBzZWxmLmZyYW1lX21lbnViYXIgPSB3eC5NZW51QmFyKCkKICAgICAgICB3eGdsYWRlX3RtcF9tZW51ID0gd3guTWVudSgpCiAgICAgICAgaXRlbSA9IHd4Z2xhZGVfdG1wX21lbnUuQXBwZW5kKHd4LklEX0FOWSwgdSLmlrDopo/kvZzmiJBcdEN0cmwrTiIsICIiKQogICAgICAgIHNlbGYuQmluZCh3eC5FVlRfTUVOVSwgc2VsZi5sYW1iZGEgZXZlbnQ6IE9uTmV3RmlsZShzZWxmKSwgaXRlbSkKICAgICAgICBpdGVtID0gd3hnbGFkZV90bXBfbWVudS5BcHBlbmQod3guSURfQU5ZLCB1IumWi+OBjy4uLlx0Q3RybCtPIiwgIiIpCiAgICAgICAgc2VsZi5CaW5kKHd4LkVWVF9NRU5VLCBzZWxmLmxhbWJkYSBldmVudDogT25PcGVuKHNlbGYpLCBpdGVtKQogICAgICAgIGl0ZW0gPSB3eGdsYWRlX3RtcF9tZW51LkFwcGVuZCh3eC5JRF9BTlksIHUi5L+d5a2YXHRDdHJsK1MiLCAiIikKICAgICAgICBzZWxmLkJpbmQod3guRVZUX01FTlUsIGxhbWJkYSBldmVudDogcHViLnNlbmRNZXNzYWdlKCdDb250cm9sbGVyLnJlYWQnLCB4ID0gWydPblNhdmVGaWxlJ10sIGVudiA9IHNlbGYuZW52KSwgaXRlbSkKICAgICAgICBpdGVtID0gd3hnbGFkZV90bXBfbWVudS5BcHBlbmQod3guSURfQU5ZLCB1IuWQjeWJjeOCkuS7mOOBkeOBpuS/neWtmC4uLlx0U2hpZnQrQ3RybCtTIiwgIiIpCiAgICAgICAgc2VsZi5CaW5kKHd4LkVWVF9NRU5VLCBzZWxmLmxhbWJkYSBldmVudDogT25TYXZlQXMoc2VsZiksIGl0ZW0pCiAgICAgICAgaXRlbSA9IHd4Z2xhZGVfdG1wX21lbnUuQXBwZW5kKHd4LklEX0FOWSwgIlF1aXRcdEN0cmwrUSIsICIiKQogICAgICAgIHNlbGYuQmluZCh3eC5FVlRfTUVOVSwgbGFtYmRhIGV2ZW50OiBwdWIuc2VuZE1lc3NhZ2UoJ0NvbnRyb2xsZXIucmVhZCcsIHggPSBbJ09uUXVpdCddLCBlbnYgPSBzZWxmLmVudiksIGl0ZW0pCiAgICAgICAgc2VsZi5mcmFtZV9tZW51YmFyLkFwcGVuZCh3eGdsYWRlX3RtcF9tZW51LCB1IuODleOCoeOCpOODqyIpCiAgICAgICAgc2VsZi5TZXRNZW51QmFyKHNlbGYuZnJhbWVfbWVudWJhcikKICAgICAgICAjIE1lbnUgQmFyIGVuZAoKICAgICAgICBzaXplcl8xID0gd3guQm94U2l6ZXIod3guVkVSVElDQUwpCgogICAgICAgIHNlbGYuQWRkQ0QgPSB3eC5CdXR0b24oc2VsZiwgd3guSURfQU5ZLCAiQWRkQ0QiKQogICAgICAgIHNpemVyXzEuQWRkKHNlbGYuQWRkQ0QsIDAsIDAsIDApCgogICAgICAgIHNlbGYubGlzdF9jdHJsXzEgPSB3eC5MaXN0Q3RybChzZWxmLCB3eC5JRF9BTlksIHN0eWxlPXd4LkxDX0hSVUxFUyB8IHd4LkxDX1JFUE9SVCB8IHd4LkxDX1ZSVUxFUykKICAgICAgICBzZWxmLmxpc3RfY3RybF8xLkFwcGVuZENvbHVtbih1IuOCv+OCpOODiOODqyIsIGZvcm1hdD13eC5MSVNUX0ZPUk1BVF9MRUZULCB3aWR0aD0tMSkKICAgICAgICBzZWxmLmxpc3RfY3RybF8xLkFwcGVuZENvbHVtbih1IuOCouODvOODhuOCo+OCueODiCIsIGZvcm1hdD13eC5MSVNUX0ZPUk1BVF9MRUZULCB3aWR0aD0tMSkKICAgICAgICBzZWxmLmxpc3RfY3RybF8xLkFwcGVuZENvbHVtbih1IuODrOODvOODhuOCo+ODs+OCsCIsIGZvcm1hdD13eC5MSVNUX0ZPUk1BVF9MRUZULCB3aWR0aD0tMSkKICAgICAgICBzZWxmLmxpc3RfY3RybF8xLkFwcGVuZENvbHVtbih1IuODquODg+ODlyIsIGZvcm1hdD13eC5MSVNUX0ZPUk1BVF9MRUZULCB3aWR0aD0tMSkKICAgICAgICBzaXplcl8xLkFkZChzZWxmLmxpc3RfY3RybF8xLCAxLCB3eC5FWFBBTkQsIDApCgogICAgICAgIHNlbGYuU2V0U2l6ZXIoc2l6ZXJfMSkKCiAgICAgICAgc2VsZi5MYXlvdXQoKQogICAgICAgIHB1Yi5zdWJzY3JpYmUoc2VsZi5TZXRQcm9wZXJ0aWVzLCAnVmlldycpCgogICAgICAgIHNlbGYuQmluZCh3eC5FVlRfQlVUVE9OLCBsYW1iZGEgZXZlbnQ6IEFkZENERGlhbG9nKHNlbGYpLlNob3dNb2RhbCgpLCBzZWxmLkFkZENEKQogICAgICAgIHNlbGYuQmluZCh3eC5FVlRfTElTVF9JVEVNX1JJR0hUX0NMSUNLLCBzZWxmLnJjbGljaywgc2VsZi5saXN0X2N0cmxfMSkKICAgICAgICAjIGVuZCB3eEdsYWRlCgogICAgZGVmIHJjbGljayhzZWxmLCBldmVudCk6ICAjIHd4R2xhZGU6IFZpZXcuPGV2ZW50X2hhbmRsZXI+CiAgICAgICAgcHJpbnQoIkV2ZW50IGhhbmRsZXIgJ3JjbGljaycgbm90IGltcGxlbWVudGVkISIpCiAgICAgICAgZXZlbnQuU2tpcCgpCgojIGVuZCBvZiBjbGFzcyBWaWV3CgpjbGFzcyBBZGRDRERpYWxvZyh3eC5EaWFsb2cpOgogICAgZGVmIF9faW5pdF9fKHNlbGYsICphcmdzLCAqKmt3ZHMpOgogICAgICAgICMgYmVnaW4gd3hHbGFkZTogQWRkQ0REaWFsb2cuX19pbml0X18KICAgICAgICBzZWxmLmVudiA9IGFyZ3NbMF0uZW52CiAgICAgICAga3dkc1sic3R5bGUiXSA9IGt3ZHMuZ2V0KCJzdHlsZSIsIDApIHwgd3guREVGQVVMVF9ESUFMT0dfU1RZTEUKICAgICAgICB3eC5EaWFsb2cuX19pbml0X18oc2VsZiwgKmFyZ3MsICoqa3dkcykKICAgICAgICBzZWxmLlNldFRpdGxlKCJBZGQgQ0QiKQoKICAgICAgICBzaXplcl8xID0gd3guQm94U2l6ZXIod3guVkVSVElDQUwpCgogICAgICAgIGdyaWRfc2l6ZXJfMSA9IHd4LkdyaWRTaXplcig0LCAyLCAwLCAwKQogICAgICAgIHNpemVyXzEuQWRkKGdyaWRfc2l6ZXJfMSwgMSwgd3guRVhQQU5ELCAwKQoKICAgICAgICBUaXRsZSA9IHd4LlN0YXRpY1RleHQoc2VsZiwgd3guSURfQU5ZLCB1IuOCv+OCpOODiOODqyIpCiAgICAgICAgZ3JpZF9zaXplcl8xLkFkZChUaXRsZSwgMCwgd3guQUxJR05fQ0VOVEVSLCAwKQoKICAgICAgICBzZWxmLnRleHRfY3RybF8xID0gd3guVGV4dEN0cmwoc2VsZiwgd3guSURfQU5ZLCAiIikKICAgICAgICBncmlkX3NpemVyXzEuQWRkKHNlbGYudGV4dF9jdHJsXzEsIDAsIHd4LkFMSUdOX0NFTlRFUiwgMCkKCiAgICAgICAgQXJ0aXN0ID0gd3guU3RhdGljVGV4dChzZWxmLCB3eC5JRF9BTlksIHUi44Ki44O844OG44Kj44K544OIIikKICAgICAgICBncmlkX3NpemVyXzEuQWRkKEFydGlzdCwgMCwgd3guQUxJR05fQ0VOVEVSLCAwKQoKICAgICAgICBzZWxmLnRleHRfY3RybF8yID0gd3guVGV4dEN0cmwoc2VsZiwgd3guSURfQU5ZLCAiIikKICAgICAgICBncmlkX3NpemVyXzEuQWRkKHNlbGYudGV4dF9jdHJsXzIsIDAsIHd4LkFMSUdOX0NFTlRFUiwgMCkKCiAgICAgICAgUmF0aW5nID0gd3guU3RhdGljVGV4dChzZWxmLCB3eC5JRF9BTlksIHUi44Os44O844OG44Kj44Oz44KwIikKICAgICAgICBncmlkX3NpemVyXzEuQWRkKFJhdGluZywgMCwgd3guQUxJR05fQ0VOVEVSLCAwKQoKICAgICAgICBzZWxmLnRleHRfY3RybF8zID0gd3guVGV4dEN0cmwoc2VsZiwgd3guSURfQU5ZLCAiIikKICAgICAgICBncmlkX3NpemVyXzEuQWRkKHNlbGYudGV4dF9jdHJsXzMsIDAsIHd4LkFMSUdOX0NFTlRFUiwgMCkKCiAgICAgICAgUmlwcGVkID0gd3guU3RhdGljVGV4dChzZWxmLCB3eC5JRF9BTlksIHUi44Oq44OD44OXIikKICAgICAgICBncmlkX3NpemVyXzEuQWRkKFJpcHBlZCwgMCwgd3guQUxJR05fQ0VOVEVSLCAwKQoKICAgICAgICBzZWxmLnRleHRfY3RybF80ID0gd3guVGV4dEN0cmwoc2VsZiwgd3guSURfQU5ZLCAiIikKICAgICAgICBncmlkX3NpemVyXzEuQWRkKHNlbGYudGV4dF9jdHJsXzQsIDAsIHd4LkFMSUdOX0NFTlRFUiwgMCkKCiAgICAgICAgc2l6ZXJfMiA9IHd4LlN0ZERpYWxvZ0J1dHRvblNpemVyKCkKICAgICAgICBzaXplcl8xLkFkZChzaXplcl8yLCAwLCB3eC5BTElHTl9SSUdIVCB8IHd4LkFMTCwgNCkKCiAgICAgICAgc2VsZi5idXR0b25fT0sgPSB3eC5CdXR0b24oc2VsZiwgd3guSURfT0ssICIiKQogICAgICAgIHNlbGYuYnV0dG9uX09LLlNldERlZmF1bHQoKQogICAgICAgIHNpemVyXzIuQWRkQnV0dG9uKHNlbGYuYnV0dG9uX09LKQoKICAgICAgICBzZWxmLmJ1dHRvbl9DQU5DRUwgPSB3eC5CdXR0b24oc2VsZiwgd3guSURfQ0FOQ0VMLCAiIikKICAgICAgICBzaXplcl8yLkFkZEJ1dHRvbihzZWxmLmJ1dHRvbl9DQU5DRUwpCgogICAgICAgIHNpemVyXzIuUmVhbGl6ZSgpCgogICAgICAgIHNlbGYuU2V0U2l6ZXIoc2l6ZXJfMSkKICAgICAgICBzaXplcl8xLkZpdChzZWxmKQoKICAgICAgICBzZWxmLlNldEFmZmlybWF0aXZlSWQoc2VsZi5idXR0b25fT0suR2V0SWQoKSkKICAgICAgICBzZWxmLlNldEVzY2FwZUlkKHNlbGYuYnV0dG9uX0NBTkNFTC5HZXRJZCgpKQoKICAgICAgICBzZWxmLkxheW91dCgpCgogICAgICAgIHNlbGYuQmluZCh3eC5FVlRfQlVUVE9OLCBsYW1iZGEgZXZlbnQ6IHNlbGYuT25BZGRDRCgpLCBzZWxmLmJ1dHRvbl9PSykKICAgICAgICBzZWxmLkJpbmQod3guRVZUX0JVVFRPTiwgbGFtYmRhIGV2ZW50OiBzZWxmLkRlc3Ryb3koKSwgc2VsZi5idXR0b25fQ0FOQ0VMKQogICAgICAgICMgZW5kIHd4R2xhZGUKCiMgZW5kIG9mIGNsYXNzIEFkZENERGlhbG9nCgpjbGFzcyBOZXdGaWxlKHd4LkRpYWxvZyk6CiAgICBkZWYgX19pbml0X18oc2VsZiwgKmFyZ3MsICoqa3dkcyk6CiAgICAgICAgIyBiZWdpbiB3eEdsYWRlOiBOZXdGaWxlLl9faW5pdF9fCiAgICAgICAgc2VsZi5lbnYgPSBhcmdzWzBdLmVudgogICAgICAgIGt3ZHNbInN0eWxlIl0gPSBrd2RzLmdldCgic3R5bGUiLCAwKSB8IHd4LkRFRkFVTFRfRElBTE9HX1NUWUxFCiAgICAgICAgd3guRGlhbG9nLl9faW5pdF9fKHNlbGYsICphcmdzLCAqKmt3ZHMpCiAgICAgICAgc2VsZi5TZXRUaXRsZSh1IuaWsOimj+S9nOaIkCIpCiAgICAgICAgc2VsZi5MYXlvdXQoKQogICAgICAgICMgZW5kIHd4R2xhZGUKCiMgZW5kIG9mIGNsYXNzIE5ld0ZpbGUKCmNsYXNzIE9wZW5GaWxlKHd4LkRpYWxvZyk6CiAgICBkZWYgX19pbml0X18oc2VsZiwgKmFyZ3MsICoqa3dkcyk6CiAgICAgICAgIyBiZWdpbiB3eEdsYWRlOiBPcGVuRmlsZS5fX2luaXRfXwogICAgICAgIHNlbGYuZW52ID0gYXJnc1swXS5lbnYKICAgICAgICBrd2RzWyJzdHlsZSJdID0ga3dkcy5nZXQoInN0eWxlIiwgMCkgfCB3eC5ERUZBVUxUX0RJQUxPR19TVFlMRQogICAgICAgIHd4LkRpYWxvZy5fX2luaXRfXyhzZWxmLCAqYXJncywgKiprd2RzKQogICAgICAgIHNlbGYuU2V0VGl0bGUodSLplovjgY8uLi4iKQogICAgICAgIHNlbGYuTGF5b3V0KCkKICAgICAgICAjIGVuZCB3eEdsYWRlCgojIGVuZCBvZiBjbGFzcyBPcGVuRmlsZQoKY2xhc3MgU2F2ZUZpbGVBcyh3eC5EaWFsb2cpOgogICAgZGVmIF9faW5pdF9fKHNlbGYsICphcmdzLCAqKmt3ZHMpOgogICAgICAgICMgYmVnaW4gd3hHbGFkZTogU2F2ZUZpbGVBcy5fX2luaXRfXwogICAgICAgIHNlbGYuZW52ID0gYXJnc1swXS5lbnYKICAgICAgICBrd2RzWyJzdHlsZSJdID0ga3dkcy5nZXQoInN0eWxlIiwgMCkgfCB3eC5ERUZBVUxUX0RJQUxPR19TVFlMRQogICAgICAgIHd4LkRpYWxvZy5fX2luaXRfXyhzZWxmLCAqYXJncywgKiprd2RzKQogICAgICAgIHNlbGYuU2V0VGl0bGUodSLlkI3liY3jgpLku5jjgZHjgabkv53lrZguLi4iKQogICAgICAgIHNlbGYuTGF5b3V0KCkKICAgICAgICAjIGVuZCB3eEdsYWRlCgojIGVuZCBvZiBjbGFzcyBTYXZlRmlsZUFzCgpjbGFzcyBTaW1wbGVEYXRhYmFzZSh3eC5BcHApOgogICAgZGVmIE9uSW5pdChzZWxmKToKICAgICAgICBzZWxmLlZpZXcgPSBWaWV3KE5vbmUsIHd4LklEX0FOWSwgIiIpCiAgICAgICAgc2VsZi5TZXRUb3BXaW5kb3coc2VsZi5WaWV3KQogICAgICAgIHNlbGYuVmlldy5TaG93KCkKICAgICAgICByZXR1cm4gVHJ1ZQoKIyBlbmQgb2YgY2xhc3MgU2ltcGxlRGF0YWJhc2UKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICBTaW1wbGVEYXRhYmFzZSA9IFNpbXBsZURhdGFiYXNlKDApCiAgICBTaW1wbGVEYXRhYmFzZS5NYWluTG9vcCgpCg==