import pandas as pd
import re

default_units = {'speed': 'km/h',
                 'distance': 'km',
                 'weight': 'kg',
                 'height': 'cm'}

units_conversions = {}

# Team 2
def convert_time(time: str, time_format: str = None, mode: str = 'flag'):
    """
        Converts string with time into pd.Timedelta object

        Parameters
        ----------
        time: string

        time_format: string
            if mode = flag : valid flags for pd.to_datetime function
            if mode = regex : raw string with regex. Each unit of time to be included in the result
                              should be named group of regex. One of the following values should be used as a key:
                              {'days', 'seconds', 'microseconds', 'milliseconds', 'minutes', 'hours', 'weeks'}
                              Example of valid regex:
                              r"(?P<hours>[\d]{0,2})\:?(?P<minutes>[\d]{2})\:(?P<seconds>[\d]{2}).[\d]{3}"
            default = None : Default call of to_timedelta function without flags

        mode: string with value 'flag' or 'regex'
            flag for using flag mode (matching time using flags recognised by pd.to_datetime),
            regex for using regex patterns matching time

        Returns
        -------
        pd.Timedelta object if operation was successful, else returns time parameter as a string.
        """
    possible_keys = {'days', 'seconds', 'microseconds', 'milliseconds', 'minutes', 'hours', 'weeks'}
    if mode == 'flag':
        try:
            dt_time = pd.to_datetime(time, 'ignore', format=time_format)
            try:
                return pd.to_timedelta(dt_time)
            except ValueError:
                return pd.to_timedelta(str(dt_time.time()))
        except (TypeError, AttributeError):
            return str(time)

    elif mode == 'regex':
        if re_compiler(time_format) is True:
            try:
                time_dict = re.search(time_format, time).groupdict()
                time_dict = dict_comprehension(possible_keys, time_dict)
                return pd.Timedelta(**time_dict)
            except (AttributeError, KeyError):
                return str(time)
        else:
            return str(time)

# Team 2
def convert_date(date: str, date_format: str = None, mode: str = 'flag'):
    """

    Parameters
    ----------
    date : date in string format
    date_format: string
        if mode = flag : valid flags for pd.to_datetime function
        if mode = regex : raw string with regex. Each unit of date to be included in the result
                          should be named group of regex. One of the following values should be used as a key:
                          {'year', 'month', 'day', 'hour', 'minute', 'second', 'time_zone'}
                          Example of valid regex:
                          r"(?P<day>[\d]{2}) (?P<month>[\w]{3}) (?P<year>[\d]{2})"
        default = None : Default call of to_datetime function without flags
    mode : string
        flag for using flag mode (matching date using flags recognised by pd.to_datetime),
        regex for using regex patterns matching date
    Returns
    -------
    pd.Timestamp object if operation was successful, else returns date parameter as a string.

    """
    possible_keys = {'year', 'month', 'day', 'hour', 'minute', 'second', 'time_zone'}
    if mode == 'flag':
        try:
            return pd.to_datetime(date, 'ignore', format=date_format)
        except ValueError:
            return str(date)
    elif mode == 'regex':
        if re_compiler(date_format) is True:
            try:
                date_dict = re.search(date_format, date).groupdict()
                date_dict = dict_comprehension(possible_keys, date_dict)
                return pd.Timestamp(**date_dict)
            except (AttributeError, KeyError, TypeError):
                return str(date)
        else:
            return str(date)

# Team 2
def convert_units(datatables: list):
    pass

# Team 2
def clean_data(datatables: list, meta: list, clean_prop: list):
    def set_meta_obj(dt_list, meta_list):
        """
        Function to set right Metadata object as a DataTable.meta attribute

        :param dt_list: List of Datatable objects
        :type dt_list: list

        :param meta_list: List of MetaData objects
        :type meta_list: list
        """
        for dt, meta in zip(dt_list, meta_list):
            dt.meta = meta

    def rename_columns(dt_list, cd_list):
        """
        Function to rename and drop columns according to CleanData.columns attribute

        :param dt_list: List of Datatable objects
        :type dt_list: list

        :param cd_list: List of CleanData objects
        :type cd_list: list
        """
        for dt, cd in zip(dt_list, cd_list):
            for col in dt.dt.columns:
                if col not in cd.columns.keys():
                    dt.dt = dt.dt.drop(columns=col)
            dt.dt = dt.dt.rename(columns=cd.columns)

    def fill_values(dt_list, cd_list):
        """
        Function to fill missing values according to CleanData.missing_data attribute

        :param dt_list: List of Datatable objects
        :type dt_list: list

        :param cd_list: List of CleanData objects
        :type cd_list: list
        """
        for dt, cd in zip(dt_list, cd_list):
            for col in dt.dt.columns:
                if not cd.missing_data[col]['permitted']:
                    if cd.missing_data[col]['fill_value'] is not None:
                        dt.dt[col] = dt.dt[col].fillna(value=cd.missing_data[col]['fill_value'])
                    elif cd.missing_data[col]['fill_method'] is not None:
                        dt.dt[col] = dt.dt[col].fillna(method=cd.missing_data[col]['fill_method'])
                    elif cd.missing_data[col]['fill_value'] is None and cd.missing_data[col]['fill_method'] is None:
                        dt.dt[col] = dt.dt[col].dropna()

    def set_index(dt_list, meta_list):
        """
        Function to set index according to Metada.index attribute

        :param dt_list: List of Datatable objects
        :type dt_list: list

        :param meta_list: List of MetaData objects
        :type meta_list: list
        """
        for dt, meta in zip(dt_list, meta_list):
            dt.dt = dt.dt.set_index(meta.index)

    def set_datetime(dt_list, cd_list):
        """
        Function to set datetime values according to CleanData.date_time attribute

        :param dt_list: List of Datatable objects
        :type dt_list: list

        :param cd_list: List of CleanData objects
        :type cd_list: list
        """
        for dt, cd in zip(dt_list, cd_list):
            for col in dt.dt.columns:
                if col in cd.date_time and cd.date_time[col] == 'datetime':
                    dt.dt[col] = dt.dt[col].apply(convert_date, args=(cd.patterns[col][0], cd.patterns[col][1]))
                elif col in cd.date_time and col not in cd.patterns:
                    dt.dt[col] = pd.to_datetime(dt.dt[col])

    def set_timedelta(dt_list, cd_list):
        """
        Function to set timedelta values according to CleanData.date_time attribute

        :param dt_list: List of Datatable objects
        :type dt_list: list

        :param cd_list: List of CleanData objects
        :type cd_list: list
        """
        for dt, cd in zip(dt_list, cd_list):
            for col in dt.dt.columns:
                if col in cd.date_time and cd.date_time[col] == 'timedelta':
                    dt.dt[col] = dt.dt[col].apply(convert_time, args=(cd.patterns[col][0], cd.patterns[col][1]))
                elif col in cd.date_time and col not in cd.patterns:
                    dt.dt[col] = pd.to_timedelta(dt.dt[col])

    def set_categorical(dt_list, cd_list):
        """
        Function to change datatype according to CleanData.categorical attribute

        :param dt_list: List of Datatable objects
        :type dt_list: list

        :param cd_list: List of CleanData objects
        :type cd_list: list
        """
        for dt, cd in zip(dt_list, cd_list):
            for col in dt.dt.columns:
                if col in cd.categorical:
                    dt.dt[col] = dt.dt[col].astype('category')

    set_meta_obj(datatables, meta)
    rename_columns(datatables, clean_prop)
    fill_values(datatables, clean_prop)
    set_index(datatables, meta)
    set_datetime(datatables, clean_prop)
    set_timedelta(datatables, clean_prop)
    set_categorical(datatables, clean_prop)

def re_compiler(format: str) -> bool:
    """
    Checks if provided regex is valid

    Parameters
    ----------
    format: raw string with regex pattern

    Returns
    -------
    bool True if regex compiles, else False
    """

    try:
        re.compile(format)
        return True

    except re.error:
        return False

def get_month_number(value: str) -> int:
    """

    Parameters
    ----------
    value: string containing short or full month name - min 3 chars long

    Returns
    -------
    int representing month number
    """
    return {'jan': 1,
            'feb': 2,
            'mar': 3,
            'apr': 4,
            'may': 5,
            'jun': 6,
            'jul': 7,
            'aug': 8,
            'sep': 9,
            'oct': 10,
            'nov': 11,
            'dec': 12
            }[value[:3].lower()]

def dict_comprehension(possible_keys: set, initial_dict: dict) -> dict:
    """

    Parameters
    ----------
    possible_keys: set with strings representing possible keys expected in the dictionary
    initial_dict: dictionary created using groupdict method on re.search object

    Returns
    -------
    dictionary validated for containing relevant keys

    """
    for k, v in initial_dict.copy().items():
        try:
            initial_dict[k] = int(v)
        except ValueError:
            initial_dict[k] = get_month_number(v)
    new_dict = {k if k in possible_keys else None: 0 if v == '' else int(v) for k, v in initial_dict.items()}
    if None in new_dict.keys():
        raise KeyError
    return new_dict


class SomeModel:
    def predict(self, message: str) -> float:
        """Метод определяет качество фитбека получаемого в строке message.
        Оценка качества зависит от длины комментария.
        Структура фитбека:
        "Оценка\nкомментнарий"
        """
        message_partition = message.partition("\n")
        if message_partition[0] == "":
            raise ValueError("Отсутствует оценка")
        if message_partition[2] == "":
            raise ValueError("Отсутствует комментарий")
        try:
            mark = int(message_partition[0])
            if 0 <= mark <= 5:
                return 1 - (1 / len(message_partition[2]) ** (1 / 2))
            return None
        except TypeError:
            raise TypeError("Оценка может быть только Int") from None
        except ValueError:
            raise ValueError("Оценка вне диапазона возможных значений") from None

def predict_message_mood(
    message: str,
    model: SomeModel,
    bad_thresholds: float = 0.3,
    good_thresholds: float = 0.8,
) -> str:
    result = model.predict(message)
    if result < bad_thresholds:
        return "неуд"
    if result > good_thresholds:
        return "отл"
    return "норм"


from flask import Flask, render_template, request
from flask_ckeditor import CKEditor, CKEditorField
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired

app = Flask(__name__)
app.config['SECRET_KEY'] = 'super_secret_key'

ckeditor = CKEditor(app)

class CommentForm(FlaskForm):
    name = StringField("Nome", validators=[DataRequired()])
    comment = CKEditorField("Commento", validators=[DataRequired()])
    submit = SubmitField('Invia')

@app.route('/', methods=["GET", "POST"])
def index():
    my_form = CommentForm()
    if my_form.validate_on_submit():
        my_name = request.form['name']
        my_comment = my_form.comment.data
        return render_template('comment.html', name=my_name, comment=my_comment)
    return render_template('index.html', form=my_form)

if __name__ == "__main__":
    app.run(debug=True)


from turtle import Turtle
MOVE_DIST = 20
UP = 90
DOWN = 270
RIGHT = 0
LEFT = 180

class Snake:
    def __init__(self):
        self.location = -40
        self.ls = []
        for x in range(0, 3):
           self.add_s(self.location, 0)
           self.location += 20
        self.head = self.ls[0]
    def add_s(self, locationX, locationY):
        self.s = Turtle()
        self.s.penup()
        self.s.shape("square")
        self.s.color("white")
        self.s.goto(locationX, locationY)
        self.ls.append(self.s)
    def extend(self):
        self.add_s(self.ls[-1].xcor(),self.ls[-1].ycor())

    def move(self):
        for seq_num in range(len(self.ls) - 1, 0, -1):
            new_x =  self.ls[seq_num - 1].xcor()
            new_y =  self.ls[seq_num - 1].ycor()
            self.ls[seq_num].goto(new_x, new_y)
        self.ls[0].forward(MOVE_DIST)
    def right(self):
        if self.head.heading()!= LEFT:
            self.head.setheading(RIGHT)
    def left(self):
        if self.head.heading() != RIGHT:
            self.head.setheading(LEFT)
    def up(self):
        if self.head.heading() != DOWN:
            self.head.setheading(UP)
    def down(self):
        if self.head.heading() != UP:
            self.head.setheading(DOWN)

    def reset(self):
        for s in self.ls:
            s.goto(1000, 1000)
        self.ls.clear()
        for x in range(0, 3):
            self.add_s(self.location, 0)
            self.location += 20
        self.head = self.ls[0]


import os
import time
import json

import wx
import metroEmuGobal as gv
import railwayMgr as mapMgr
import railwayPanel as pnlFunction
import railwayPanelMap as pnlMap
import dataMgr as dm

FRAME_SIZE = (1800, 1030)

#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
class UIFrame(wx.Frame):
    """ Main UI frame window."""
    def __init__(self, parent, id, title):
        """ Init the UI and parameters """
        wx.Frame.__init__(self, parent, id, title, size=FRAME_SIZE)
        self.SetIcon(wx.Icon(gv.ICO_PATH))
        # No boader frame:
        # wx.Frame.__init__(self, parent, id, title, style=wx.MINIMIZE_BOX | wx.STAY_ON_TOP)
        # self.SetBackgroundColour(wx.Colour(30, 40, 62))
        self.SetBackgroundColour(wx.Colour(200, 210, 200))
        #self.SetTransparent(gv.gTranspPct*255//100)
        # Init the global variables:
        self._initGlobals()
        # Build the top menu bar.
        self._buildMenuBar()
        # Build UI sizer
        self.SetSizer(self._buidUISizer())
        # Add the bottom status bar under single line mode.
        self.statusbar = self.CreateStatusBar(1)
        self.statusbar.SetStatusText('Test mode: %s' %str(gv.gTestMD))
        # Set the periodic call back
        self.updateLock = False
        # Define the data manager parallel thread.
        gv.iDataMgr = dm.DataManager(self)
        gv.iDataMgr.start()

        self.lastPeriodicTime = time.time()
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.periodic)
        self.timer.Start(gv.PERIODIC)
        self.Bind(wx.EVT_CLOSE, self.onClose)
        gv.gDebugPrint("Metro-System real world main frame inited.", logType=gv.LOG_INFO)

#--UIFrame---------------------------------------------------------------------
    def _initGlobals(self):
        # Init the global parameters used only by this module
        gv.gTrackConfig['weline'] = {'id':'weline', 'num': 4, 'color': wx.Colour(52, 169, 129),
                                     'stationCfg': gv.CONFIG_DICT['WE_STATION_CFG'], 'icon': 'welabel.png'}
        gv.gTrackConfig['nsline'] = {'id':'nsline', 'num': 3, 'color': wx.Colour(233, 0, 97),
                                     'stationCfg': gv.CONFIG_DICT['NC_STATION_CFG'], 'icon': 'nslabel.png'}
        gv.gTrackConfig['ccline'] = {'id':'ccline', 'num': 3, 'color': wx.Colour(255, 136, 0),
                                     'stationCfg': gv.CONFIG_DICT['CC_STATION_CFG'], 'icon': 'cclabel.png'}
        gv.gTrackConfig['mtline'] = {'id':'mtline', 'num': 0, 'color': wx.Colour(200, 210, 200),
                                     'stationCfg': gv.CONFIG_DICT['MT_STATION_CFG'], 'icon': None}
        # Init all the global instance
        # if gv.gCollsionTestFlg: gv.gTestMD = False # disable the test mode flag to fetch the signal from PLC
        # Init all the train list
        self.trainCfgFiles = [filename for filename in os.listdir(gv.gTrainCfgDir) if filename.endswith('.json')]
        gv.gDebugPrint("Avalible Scenario file: %s" %str(self.trainCfgFiles), logType=gv.LOG_INFO)
        gv.iMapMgr = mapMgr.MapMgr(self)

#--UIFrame---------------------------------------------------------------------
    def _buildMenuBar(self):
        menubar = wx.MenuBar()  # Creat the function menu bar.
        # Add the config menu

        # load scenario
        configMenu = wx.Menu()
        scenarioItem = wx.MenuItem(configMenu, 100, text = "Load Scenario",kind = wx.ITEM_NORMAL)
        configMenu.Append(scenarioItem)
        self.Bind(wx.EVT_MENU, self.onLoadScenario, scenarioItem)
        menubar.Append(configMenu, '&Config')

        # Add the about menu.
        helpMenu = wx.Menu()
        aboutItem = wx.MenuItem(helpMenu, 200,text = "Help",kind = wx.ITEM_NORMAL)
        helpMenu.Append(aboutItem)
        self.Bind(wx.EVT_MENU, self.onHelp, aboutItem)
        menubar.Append(helpMenu, '&About')

        self.SetMenuBar(menubar)

#--UIFrame---------------------------------------------------------------------
    def _buidUISizer(self):
        """ Build the main UI Sizer. """
        flagsL = wx.LEFT
        mSizer = wx.BoxSizer(wx.HORIZONTAL)
        mSizer.AddSpacer(5)
        # Add the train control panels.
        vbox0 = self._buildTrainCtrlSizer()
        mSizer.Add(vbox0, flag=flagsL, border=2)
        mSizer.AddSpacer(5)
        mSizer.Add(wx.StaticLine(self, wx.ID_ANY, size=(-1, 980),
                                 style=wx.LI_VERTICAL), flag=flagsL, border=2)
        mSizer.AddSpacer(5)
        # Add the real word display panel.
        vbox1 = wx.BoxSizer(wx.VERTICAL)
        vbox1.AddSpacer(5)
        font = wx.Font(12, wx.DECORATIVE, wx.NORMAL, wx.BOLD)
        label = wx.StaticText(self, label= "RealWorld Metro System Emulator")
        label.SetFont(font)
        vbox1.Add(label, flag=wx.CENTRE, border=2)
        vbox1.AddSpacer(5)
        gv.iMapPanel = self.mapPanel = pnlMap.PanelMap(self)
        vbox1.Add(gv.iMapPanel, flag=wx.CENTRE, border=2)
        mSizer.Add(vbox1, flag=flagsL, border=2)
        return mSizer

#--UIFrame---------------------------------------------------------------------
    def _buildTrainCtrlSizer(self):
        flagsL = wx.LEFT
        vbox0 = wx.BoxSizer(wx.VERTICAL)
        vbox0.AddSpacer(5)
        font = wx.Font(12, wx.DECORATIVE, wx.NORMAL, wx.BOLD)
        label = wx.StaticText(self, label="Trains Control")
        label.SetFont(font)
        vbox0.Add(label, flag=flagsL, border=2)
        vbox0.AddSpacer(5)
        for key, panelCfg in gv.gTrackConfig.items():
            img, color = panelCfg['icon'], panelCfg['color']
            if img is None: continue
            img = os.path.join(gv.IMG_FD, img)
            png = wx.Image(img, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
            sublabel = wx.StaticBitmap(self, -1, png, (10, 5), (png.GetWidth(), png.GetHeight()))
            vbox0.Add(sublabel, flag=flagsL, border=2)
            for i in range(panelCfg['num']):
                trainPanel = pnlFunction.PanelTainCtrl(self, panelCfg['id'], i, bgColor=color)
                vbox0.Add(trainPanel, flag=flagsL, border=2)
                vbox0.AddSpacer(5)
        img = os.path.join(gv.IMG_FD, 'buttonSample.png')
        png = wx.Image(img, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        btnSample = wx.StaticBitmap(self, -1, png, (10, 5), (png.GetWidth(), png.GetHeight()))
        vbox0.Add(btnSample, flag=flagsL, border=2)
        self.collisionCB = wx.CheckBox(self, label = 'Auto collision avoidance')
        self.collisionCB.SetValue(gv.gCollAvoid)
        self.collisionCB.Bind(wx.EVT_CHECKBOX, self.onCollisionSet)
        vbox0.Add(self.collisionCB, flag=flagsL, border=2)
        return vbox0

#--UIFrame---------------------------------------------------------------------
    def periodic(self, event):
        """ Call back every periodic time."""
        now = time.time()
        if (not self.updateLock) and now - self.lastPeriodicTime >= gv.gUpdateRate:
            print("main frame update at %s" % str(now))
            self.lastPeriodicTime = now
            # update the manager.
            gv.iMapMgr.periodic(now)
            # apply the state on the map panel.
            self.mapPanel.periodic(now)

#-----------------------------------------------------------------------------
    def onCollisionSet(self, event):
        gv.gCollAvoid = self.collisionCB.IsChecked()
        gv.gDebugPrint("Trains automated collision avoidance enable: %s" %str(gv.gCollAvoid), logType=gv.LOG_INFO)

    def changeCAcheckboxState(self, state):
        self.collisionCB.SetValue(state)

#-----------------------------------------------------------------------------
    def onLoadScenario(self, event):
        self.scenarioDialog = wx.SingleChoiceDialog(self,
                                                    'Select Scenario',
                                                    'Scenario selection',
                                                    self.trainCfgFiles)
        resp = self.scenarioDialog.ShowModal()
        if resp == wx.ID_OK:
            trainConfigName = self.scenarioDialog.GetStringSelection()
            trainConfigPath = os.path.join(gv.gTrainCfgDir, trainConfigName)
            if os.path.exists(trainConfigPath):
                with open(trainConfigPath) as json_file:
                    trainConfigDict = json.load(json_file)
                    if gv.iMapMgr:
                        self.updateLock = True
                        gv.iMapMgr.resetTrainsPos(trainConfigDict)
                        self.updateLock = False
        self.scenarioDialog.Destroy()
        self.scenarioDialog = None

#-----------------------------------------------------------------------------
    def onHelp(self, event):
        """ Pop-up the Help information window. """
        wx.MessageBox(' If there is any bug, please contact: \n\n \
                        Author:      Yuancheng Liu \n \
                        Email:       liu_yuan_cheng@hotmail.com \n \
                        Created:     2023/05/02 \n \
                        GitHub Link: https://github.com/LiuYuancheng/Metro_emulator \n',
                    'Help', wx.OK)

#-----------------------------------------------------------------------------
    def onClose(self, evt):
        gv.iDataMgr.stop()
        self.timer.Stop()
        self.Destroy()

#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
class MyApp(wx.App):
    def OnInit(self):
        gv.iMainFrame = UIFrame(None, -1, gv.UI_TITLE)
        gv.iMainFrame.Show(True)
        return True

#-----------------------------------------------------------------------------
if __name__ == '__main__':
    app = MyApp(0)
    app.MainLoop()


from Converter.Node import Node

class BinaryTree:
    def __init__(self, function):
        self.root = Node(function.start, function, None)
        return

    def addNode(self, function):
        root = self.root
        while True:
            if function.start <= root.key:
                if root.left is None:
                    root.left = Node(function.start, function, root)
                    break
                else:
                    root = root.left
            else:
                if root.right is None:
                    root.right = Node(function.start, function, root)
                    break
                else:
                    root = root.right

    def getParent(self, start, end, root=None):
        if root is None:
            root = self.root

        node = None
        while True:
            if start <= root.key:
                if root.left is None:
                    node = root
                    break
                root = root.left
            else:
                if root.right is None:
                    node = root
                    break
                root = root.right

        if end is None:
            return node.value

        while True:
            if node.parent is None:
                break

            if node.value.end is None:
                node = node.parent
                continue

            if node.value.start < start and node.value.end > end:
                break

            node = node.parent

        return node.value


import bs4
import uuid

# Use the default python parser as this is lenient and does not
# wrap content in extra tags
PYBLOQS_ID_PREFIX = "pybloqs_id_"
DEFAULT_PARSER = "html.parser"

def parse(string):
    """
    Parses the string into a beautiful soup tree.

    :param string: String to parse.
    :return: Soup.
    """
    return bs4.BeautifulSoup(string, DEFAULT_PARSER)

def root(tag_name="html", doctype=None):
    """
    Creates a new soup with the given root element.

    :param tag_name: Root element tag name.
    :param doctype: Optional doctype tag to add.
    :return: Soup.
    """
    soup = parse("")
    if doctype is not None:
        soup.append(bs4.Doctype(doctype))
    tag = soup.new_tag(tag_name)
    tag.soup = soup
    soup.append(tag)
    return tag

def render(item, pretty=True, encoding="utf8"):
    """
    Renders the given element into a string.

    :param item: Item to render. Must be an element or soup instance.
    :param pretty: Toggles pretty formatting of the resulting string.
    :return: Rendered content.
    """
    return item.prettify(encoding=encoding) if pretty else str(item)

def append_to(parent, tag, **kwargs):
    """
    Append an element to the supplied parent.

    :param parent: Parent to append to.
    :param tag: Tag to create.
    :param args: Tag args.
    :param kwargs: Tag kwargs.
    :return: New element.
    """
    if hasattr(parent, "soup"):
        soup = parent.soup
    else:
        soup = parent.find_parent("html")

    # Create Tag explicitly instead of using new_tag, otherwise attribute "name" leads to clash with tag-name in bs4
    new_tag = bs4.Tag(builder=soup.builder, name=tag, attrs=kwargs)

    new_tag.soup = soup

    parent.append(new_tag)

    return new_tag

def js_elem(container=None, script=None):
    """
    Constructs a Javascript element and appends it to the container.

    :param container: Container to add the element to.
    :param script: Javascript code.
    :return: New element.
    """
    if container is None:
        el = root("script")
    else:
        el = append_to(container, "script", type="text/javascript")
    if script is not None:
        el.string = script
    return el

def set_id_generator(generator):
    """
    Sets the global id generator function (must be a python generator function)

    :param generator: Generator function to use.
    """
    global _id_generator
    _id_generator = generator

def id_generator_uuid():
    """
    Generates unique identifiers using the `uuid` package.
    """
    while True:
        yield str(uuid.uuid4()).replace("-", "")

def id_generator_sequential():
    """
    Generatres unique identifiers sequentially from a known constant seed.
    """
    counter = 0

    while True:
        yield PYBLOQS_ID_PREFIX + str(counter)
        counter += 1

def id_generator():
    return _id_generator()

_id_generator = id_generator_sequential


from bs4 import BeautifulSoup
import requests
from fake_useragent import UserAgent

url = "http://www.shenjidaili.com/open/"

if __name__ == '__main__':
    response = requests.get(url, headers={"User-Agent": UserAgent().random})
    proxy_list = []
    if response.status_code == 200:
        soup = BeautifulSoup(response.text, "lxml")
        soup_https = soup.select("#pills-stable_https > table")[0].find_all("tr")
        soup_http = soup.select("#pills-stable_http > table")[0].find_all("tr")
        soup = soup_http + soup_https
        for proxy_info in soup:
            proxy_event = proxy_info.select("td")
            if "端口" in proxy_event[1].string:
                continue
            proxy = proxy_event[3].string.lower() + "://" + proxy_event[0].string
            proxy_list.append(proxy)

    test_url = {"http":"http://ipv4.icanhazip.com/", "https": "https://ipv4.icanhazip.com/"}
    for proxy in proxy_list:
        print(proxy)
        ip_type = proxy[0:5].replace(":","")
        requests.get(test_url[ip_type], timeout=15, proxies={ip_type: proxy}, headers={"User-Agent": UserAgent().random})


from typing import Optional

from bsuite.baselines import base
import dm_env
from dm_env import specs
import numpy as np

class Random(base.Agent):
  """A random agent."""

  def __init__(self,
               action_spec: specs.DiscreteArray,
               seed: Optional[int] = None):
    self._num_actions = action_spec.num_values
    self._rng = np.random.RandomState(seed)

  def select_action(self, timestep: dm_env.TimeStep) -> base.Action:
    del timestep
    return self._rng.randint(self._num_actions)

  def update(self,
             timestep: dm_env.TimeStep,
             action: base.Action,
             new_timestep: dm_env.TimeStep) -> None:
    del timestep
    del action
    del new_timestep

def default_agent(obs_spec: specs.Array, action_spec: specs.DiscreteArray,
                  **kwargs) -> Random:
  del obs_spec  # for compatibility
  return Random(action_spec=action_spec, **kwargs)


import bisect

# I believe your class nodo is lacking some information,
# gonna reimplement it here in an attempt to see if there is
# really a need to have all the variables I am going to use
class Cell:
    def __init__(self, g, h, f, parent):
        self.g = g
        self.h = h
        self.f = f
        self.parent = parent

class Pair:
    def __init__(self, f, position):
        self.f = f
        self.position = position
    def __getitem__(self, val):
        return self.cell
    def __lt__(self, other):
        return self.f < other.f
    def __gt__(self, other):
        return self.f > other.f
    def __eq__(self, other):
        return self.f == other.f

def validDestination(self, origin, dest):
         if (self.esta_dentro(origin) == False):
            #print("Origin is out of bounds!")
            return False
         elif (self.esta_dentro(dest) == False):
            #print("Destination is out of bounds!")
            return False
         elif (self.mapa[origin] == MURO):
            #print("Origin is blocked!")
            return False
         elif (self.mapa[dest] == MURO):
            #print("Destination is blocked!")
            return False
         elif (origin == dest):
            #print("Already in destination")
            return False

         return True

def getPath(self, data, dest):
    pos = dest

    path = []

    while (data[pos].parent != pos):
        path.insert(0, pos)
        pos = data[pos].parent

    path.insert(0, pos)

    return path

def AStarSearch(self, origin, dest):
    if (self.validDestination(origin, dest) == False):
        return list()

    closedCellList = {(x,y) : False for x in range(self.ancho_mapa) for y in range(self.alto_mapa)}
    cellData = {(x, y) : Cell(float("inf"), float("inf"), float("inf"), None) for x in range(self.ancho_mapa) for y in range(self.alto_mapa)}

    cellData[origin].g = 0
    cellData[origin].h = 0
    cellData[origin].f = 0
    cellData[origin].parent = origin

    openCellList = []
    bisect.insort(openCellList, Pair(0.0, origin))

    while(len(openCellList) > 0):
        openCell = openCellList.pop(0)

        parentPos = openCell.position

        closedCellList[parentPos] = True
        neighbours = self.vecinos4(parentPos)

        for neighbour in neighbours:
            newF = 0.0
            newG = 0.0
            newH = 0.0
            if (neighbour == dest):
                cellData[neighbour].parent = parentPos
                return self.getPath(cellData, dest)
            elif (closedCellList[neighbour] == False):
                newG = cellData[parentPos].g + 1
                newH = distancia(neighbour, dest)
                newF = newG + newH

                if (cellData[neighbour].f > newF):
                    bisect.insort(openCellList, Pair(newF, neighbour))
                    cellData[neighbour].f = newF
                    cellData[neighbour].g = newG
                    cellData[neighbour].h = newH
                    cellData[neighbour].parent = parentPos
    #print("No path found")
    return list()


#!/usr/bin/env python3

theInput = 1352
coordDest = (31, 39)
myMap = []
visitedLocs = []
pathLocs = []

def isWall(x, y, pInput):
    if x >= 0 and y >= 0:
        return sum(list(int(i) for
                        i in "{0:b}".format(x**2 + 3 * x + 2 * x * y
                                            + y + y * y + pInput))) % 2
    else:
        return 1

class Node():
    def __init__(self, pDepth, pPosX, pPosY, pParent):
        self.posX = pPosX
        self.posY = pPosY
        self.depth = pDepth
        self.childs = []
        visitedLocs.append((pPosX, pPosY))
        self.visited = False
        self.isWinner()
        # print('new at {} {}'.format(self.posX, self.posY))

    def isWinner(self):
        if (self.posX, self.posY) == coordDest:
            pathLocs.append((self.posX, self.posY))

            raise Exception("found a winner at depth {}".format(self.depth))

    def grow(self):
        if not self.visited:
            possiblePos = [(self.posX-1, self.posY),
                           (self.posX+1, self.posY),
                           (self.posX, self.posY-1),
                           (self.posX, self.posY+1)]
            for aPos in possiblePos:
                if (not isWall(*aPos, theInput) and
                   aPos not in visitedLocs):
                    try:
                        newChild = Node(self.depth+1, *aPos, self)
                    except Exception as e:
                        pathLocs.append((self.posX, self.posY))
                        raise Exception(e)
                    self.childs.append(newChild)
            self.visited = True
        else:
            for child in self.childs:
                try:
                    child.grow()
                except Exception as e:
                    pathLocs.append((self.posX, self.posY))
                    raise Exception(e)

# basically implement another BFS in a tree
rootNode = Node(0, 1, 1, None)
try:
    while(True):
        rootNode.grow()
except Exception as e:
    for y in range(45):
        myMap.append([])
        for x in range(45):
            myMap[y].append(isWall(x, y, theInput))
            if (x, y) in pathLocs:
                print("\033[92m"+str(myMap[y][x])+"\033[0m", end='')
            elif myMap[y][x]:
                print("\033[91m"+str(myMap[y][x])+"\033[0m", end='')
            else:
                print(myMap[y][x], end='')
        print()

    print(e)
    input()

visitedLocs = []
rootNode = Node(0, 1, 1, None)

for i in range(50):
    rootNode.grow()

for y in range(45):
    myMap.append([])
    for x in range(45):
        myMap[y].append(isWall(x, y, theInput))
        if (x, y) in visitedLocs:
            print("\033[92m"+str(myMap[y][x])+"\033[0m", end='')
        elif myMap[y][x]:
            print("\033[91m"+str(myMap[y][x])+"\033[0m", end='')
        else:
            print(myMap[y][x], end='')
    print()

print("location number is {}".format(len(visitedLocs)))


FOREST_SIZE=[100,100,100,100] #四个视角随机森林规模
TREE_DEPTH=[7,4,15,10] #四个视角随机森林的最大深度
RULE_POOL=[500,700,500,1000] #规则池大小

from forestBuild import build_forest as build_forest #随机森林模型构建
from getRule import get_rule as get_rule#抽取规则
import multiprocessing
# from .forestBuild import build_forest as build_forest #随机森林模型构建
# from .getRule import get_rule as get_rule#抽取规则

import pandas as pd
import datetime

f_offset_l=[0,881,1859,2882] #特征偏移量
view_l=[0,1,2,3] #视角列表 通过遍历视角列表来生成规则  改变列表就能重新生成规则

def mainRule(experiment_amount):
    #构建随机森林
    forest_l,f_v_acc_l,f_t_acc_l=[],[],[]

    for v in view_l: #遍历视角列表生成规则

        print("\n\n------e", experiment_amount, "view",v,"------")  #视角生成规则
        #生成对应视图的随机森林  只需要返回森林  森林准确率记录在视角对应txt文件中  四个视角独立生成随机森林  互不干扰
        x_train_df, y_train_df, forest, t_acc = build_forest(FOREST_SIZE[v], TREE_DEPTH[v], v, experiment_amount) #创建随机森林

        #生成规则   输出acc和规则数目   并将acc和数目保存在txt文件中
        amount = get_rule(x_train_df, y_train_df, forest, FOREST_SIZE[v], RULE_POOL[v], v, f_offset_l[v],experiment_amount)

        #输出acc和数目
        print("test_acc=",t_acc)
        print("final_rule_amount",amount)

        #将情况存入txt文件中
        now_time = datetime.datetime.now()
        time_str = datetime.datetime.strftime(now_time, '%Y-%m-%d %H:%M:%S')
        with open("ruleInformation/view"+str(v)+".txt", "a+") as f:
            f.write(time_str + "\n")
            f.write("experiment_amount" + str(experiment_amount) + "\n")
            f.write(" test_acc:" + str(t_acc) + "\n")
            f.write("rule_amount:" + str(amount) + "\n\n\n")
        f.close()

# for i in range(5):
#     mainRule(i+1)
if __name__ == '__main__':
    # multiprocessing.freeze_support()
    # 创建 5 个进程，每个进程分别执行一次实验
    processes = []
    for i in range(1, 6):
        p = multiprocessing.Process(target=mainRule, args=(i,))
        p.start()
        processes.append(p)

    # 等待所有进程执行完毕
    for p in processes:
        p.join()

    print("所有实验已完成")


#!/usr/bin/env python
# coding: utf-8

# ## 공룡메카드 배틀기술 정리

from bs4 import BeautifulSoup
from selenium import webdriver
import time

url = 'https://namu.wiki/w/%ED%83%80%EC%9D%B4%EB%8B%88%EC%86%8C%EC%96%B4#s-4'
list_tinyskill = []

def get_page(): #웹드라이버 가동
    driver = webdriver.Chrome()
    driver.get(url)
    return driver

def arrange_html(p_driver): #페이지에서 불필요한 부분 없애고 필요한 부분만 추출
    res = driver.execute_script("return document.documentElement.outerHTML")

    # 페이지를 오브젝트로 변환
    print('페이지를 파싱중..')
    print()
    bsObj = BeautifulSoup(res, 'html.parser')
    len(bsObj.select('body > div.content-wrapper > article > div.wiki-content.clearfix > div > div'))
    all = bsObj.select('body > div.content-wrapper > article > div.wiki-content.clearfix > div > div')

    print('공룡기술 부분만 선택 합니다.')
    print()
    target = all[58] #공룡 기술이 들어있는 리스트 부분
    target_p = target.select('p') # p만 골라서 저장

    print('불필요한 부분은 리스트에서 삭제함.')
    print()
    del target_p[2],target_p[0] #필요없는 설명부분과 공백 삭제. 끝에서 삭제를 해야 순서가 바뀌지 않음.
    driver.quit()

    return target_p

def make_dic(p_target, p_list): #타이니소어와 기술들을 사전으로 만들기
    k = 0
    for i in range(int(len(p_target)/9)):
        dic = {
        'name' : p_target[k].text,
        'skill_1' : p_target[k + 1].text,
        'skill_1_desc' : p_target[k + 2].text,
        'skill_2' : p_target[k + 3].text,
        'skill_2_desc' : p_target[k + 4].text,
        'skill_3' : p_target[k + 5].text,
        'skill_3_desc' : p_target[k + 6].text,
        'skill_4' : p_target[k + 7].text,
        'skill_4_desc' : p_target[k + 8].text
        }
        p_list.append(dic)
        k = k + 9
    return p_list

def make_txt(p_list): #파일 생성하기
    print('파일을 생성중...')
    print()
    txt_file = open('tinyskill_181209.txt', 'w')
    for i in p_list:
        txt_file.write('%s \n' % (i['name']))
        txt_file.write('\t 기술 1. %s : %s \n' %(i['skill_1'], i['skill_1_desc']))
        txt_file.write('\t 기술 2. %s : %s \n' %(i['skill_2'], i['skill_2_desc']))
        txt_file.write('\t 기술 3. %s : %s \n' %(i['skill_3'], i['skill_3_desc']))
        txt_file.write('\t 기술 4. %s : %s \n' %(i['skill_4'], i['skill_4_desc']))
        txt_file.write('\n')
    txt_file.close()
    print('작업완료..')

# #### 실행문

driver = get_page()
time.sleep(2)
target = arrange_html(driver)
time.sleep(2)
list_tinyskill = make_dic(target, list_tinyskill)
make_txt(list_tinyskill)

# In[ ]:


from dataflow.flow.api_models import Model
from dataflow.flow.handlers.forms import FlowModelNodeForm
from dataflow.flow.handlers.nodes.base_node.base_processing_node import ProcessingNode
from dataflow.flow.node_types import NodeTypes
from dataflow.shared.meta.processing.data_processing_helper import DataProcessingHelper
from dataflow.shared.model.model_helper import ModelHelper

class ModelNode(ProcessingNode):
    default_storage_type = "hdfs"
    channel_storage_type = "kafka"

    node_type = NodeTypes.MODEL
    node_form = FlowModelNodeForm
    config_attrs = [
        "bk_biz_id",
        "table_name",
        "output_name",
        "name",
        "from_result_table_ids",
        "model_params",
        "model_version_id",
        "model_id",
        "serving_scheduler_params",
        "training_scheduler_params",
        "training_when_serving",
        "auto_upgrade",
        "training_when_serving",
        "training_from_instance",
    ]

    def add_after(self, username, from_node_ids, form_data):
        # 创建 processing
        instance_params = self.build_instance_params(username, form_data)
        response_data = ModelHelper.create_processing(**instance_params)
        # 设置当前节点的 processing_id
        self.processing_id = response_data["processing_id"]
        result_table_ids = [response_data["result_table_id"]]
        rts_heads_tails = {
            "result_table_ids": result_table_ids,
            "heads": result_table_ids,
            "tails": result_table_ids,
        }
        return rts_heads_tails

    def update_after(self, username, from_node_ids, form_data, prev=None, after=None):
        instance_params = self.build_instance_params(username, form_data)
        instance_params.update({"processing_id": self.processing_id})
        response_data = ModelHelper.update_processing(**instance_params)
        result_table_ids = [response_data["result_table_id"]]

        rts_heads_tails = {
            "result_table_ids": result_table_ids,
            "heads": result_table_ids,
            "tails": result_table_ids,
        }
        return rts_heads_tails

    def remove_before(self, username):
        super(ModelNode, self).remove_before(username)
        self.delete_dp_with_rollback(ModelHelper.delete_processing)

    def build_instance_params(self, username, config):
        o_algo_model = Model(model_id=config["model_id"], model_version_id=config["model_version_id"])

        default_kwargs = {
            "project_id": self.project_id,
            "bk_biz_id": config["bk_biz_id"],
            "table_name": config["table_name"],
        }
        _algo_model_params = o_algo_model.render_config_tempalte(
            o_algo_model.model_config_template, config["model_params"], default_kwargs
        )
        serving_mode = config["serving_scheduler_params"]["serving_mode"]
        instance_params = {
            "submitted_by": username,
            "project_id": self.project_id,
            "bk_biz_id": config["bk_biz_id"],
            "model_version_id": config["model_version_id"],
            "model_id": config["model_id"],
            "model_params": _algo_model_params,
            "auto_upgrade": config["auto_upgrade"],
            "training_when_serving": config["training_when_serving"],
            "training_from_instance": config["training_from_instance"],
            "serving_scheduler_params": self.build_scheduler_params(config["serving_scheduler_params"])
            if serving_mode != "realtime"
            else {},
            "serving_mode": serving_mode,
            "training_scheduler_params": {},
        }
        if config["training_scheduler_params"]:
            instance_params["training_scheduler_params"] = self.build_scheduler_params(
                config["training_scheduler_params"]
            )

        return instance_params

    @staticmethod
    def build_scheduler_params(scheduler_params):
        """
        组装调度参数
        @note: 当 scheduler_params 为 None 时，返回 {}
        @param scheduler_params: dict，举例，
            {
                'value': 1,
                'period': 'd',
                'first_run_time': '2017-02-20 04:30:00'

            }
        @return: dict
            {
                'period': '1d',
                'first_run_time': '2017-02-20 04:30:00'
            }
        """
        if scheduler_params is None:
            return {}

        return {
            "period": "{}{}".format(scheduler_params["value"], scheduler_params["period"])
            if scheduler_params["value"] and scheduler_params["period"]
            else None,
            "first_run_time": scheduler_params["first_run_time"],
        }

    @staticmethod
    def get_models(project_ids):
        response_data = ModelHelper.get_models(
            [
                "model_id",
                "model_version_id",
                "model_name",
                "description",
                "version_description",
            ],
            project_ids,
            True,
            True,
            True,
            "complete",
        )
        return response_data

    @property
    def processing_type(self):
        """
        注意，模型节点可能是实时模型节点，也可能是离线模型节点
        不允许用户修改修改 processing_type
        @return:
        """
        processing_type = DataProcessingHelper.get_data_processing_type(self.processing_id)
        return processing_type

    @property
    def serving_mode(self):
        return self.get_config(loading_latest=False)["serving_scheduler_params"]["serving_mode"]


import requests
from bs4 import BeautifulSoup
import time
import openpyxl
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
import re
import sqlite3
import datetime
import set_mappin
import get_mansion

def get_all_mansion(load_url, num):
    # データベースに接続する
    conn = sqlite3.connect('teikyou_hantei.db', detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES)
    cur = conn.cursor()
    dbname = 'teikyou_hantei.db'
    transaction_id = get_mansion.randomname(8)
    # "TIMESTAMP"コンバータ関数 をそのまま ”DATETIME” にも使う
    sqlite3.dbapi2.converters['DATETIME'] = sqlite3.dbapi2.converters['TIMESTAMP']

    try:
        speed = 0
        speed_han = 2

        # ローカルに保存しているChrome Driverを指定(※デプロイするときはコメントアウトする)
        # p = pathlib.Path('../mansionProject/chromedriver')

        # Heroku上のChrome Driverを指定(※デプロイするときはコメントを外す)
        p = '/app/.chromedriver/bin/chromedriver'

        # Headless Chromeをあらゆる環境で起動させるオプション
        options = Options()
        options.add_argument('--disable-gpu');
        options.add_argument('--disable-extensions');
        options.add_argument('--proxy-server="direct://"');
        options.add_argument('--proxy-bypass-list=*');
        options.add_argument('--start-maximized');
        options.add_argument('--headless');

        driver = webdriver.Chrome(executable_path=p, chrome_options=options)

        if get_mansion.table_isexist(conn, cur) == False:
            get_mansion.create_table(conn, cur)
            db_id = 1
        else:
            try:
                db_id = cur.execute('SELECT id FROM teikyou_hantei ORDER BY id DESC LIMIT 1').fetchone()[0]
                print(db_id)
                db_id += 1
            except Exception as e:
                print(e)
                db_id = 1

        i = int(num)
        mansions = []

        if "&page" in load_url:
            load_url = re.sub('&([0-9a-zA-Z]*)=([0-9]*)', "", load_url)
            print("正規化:" + load_url)
        elif "?page" in load_url:
            load_url = re.sub('?([0-9a-zA-Z]*)=([0-9]*)', "", load_url)
            print("正規化:" + load_url)

        try:
            load_url = load_url + '&page=' + str(i)
            print(load_url)
            html = requests.get(load_url)
            soup = BeautifulSoup(html.content, "html.parser")
            city_name = soup.find(id='breadcrumb_3').text
        except Exception as e:
            load_url = re.sub('&([0-9a-zA-Z]*)=([0-9]*)', "", load_url)
            print(load_url)
            load_url = load_url + '?page=' + str(i)
            html = requests.get(load_url)
            soup = BeautifulSoup(html.content, "html.parser")
            city_name = soup.find(id='breadcrumb_3').text

        try:
            i_max = soup.find(class_='pagination__current-page').text
            i_max = i_max.replace(str(i) + "/", "")
        except Exception as e:
            i_max = 2
        print("pageMax:" + str(i_max))
        while i < int(i_max):
            try:
                load_url = load_url + '&page=' + str(i)
                html = requests.get(load_url)
                soup = BeautifulSoup(html.content, "html.parser")
            except Exception as e:
                load_url = load_url + '?page=' + str(i)
                html = requests.get(load_url)
                soup = BeautifulSoup(html.content, "html.parser")
            # すべてのheadingクラスを検索して、その文字列を表示する
            for element in soup.find_all(class_="heading"):
                try:
                    print(element.text)
                    if 'の建物' in element.text:
                        continue
                    elif get_mansion.db_search(cur, element.text) == True:
                        print('マンション名過去取得済み')
                        continue
                    elif get_mansion.past_search(mansions, element.text) == True:
                        print('マンション名が配列に重複しています')
                        continue
                    else:
                        mansions.append(element.text)
                except Exception as e:
                    print(e)
                    mansions.append(element.text)
                    print(element.text)

            i += 1

        print(mansions)

        time.sleep(3)
        driver.get("https://www.google.com/maps/")

        addresses = []
        time.sleep(4 + speed)

        element = driver.find_element_by_class_name('tactile-searchbox-input')
        element.send_keys(city_name)
        element.send_keys(Keys.ENTER)
        time.sleep(2)
        element = driver.find_element_by_id('sb_cb50')
        element.click()

        for i in range(len(mansions)):
            time.sleep(1 + speed)
            element = driver.find_element_by_class_name('tactile-searchbox-input')
            element.send_keys(mansions[i])
            element.send_keys(Keys.ENTER)
            time.sleep(2 + speed)

            try:
                element = driver.find_element_by_class_name('section-hero-header-title-subtitle')
                if element.text == "":
                    element = driver.find_element_by_class_name('ugiz4pqJLAG__primary-text')
                    if element.text == "":
                        addresses.append("取得できませんでした")
                addresses.append(element.text)
                time.sleep(2 + speed)
            except Exception as e:
                print(e)
                addresses.append("取得できませんでした")

            element = driver.find_element_by_id('sb_cb50')
            element.click()

        print(addresses)

        # ワークブックを新規作成する
        book = openpyxl.Workbook()
        # シートを取得し名前を変更する
        sheet = book.active
        sheet.title = '提供判定結果'

        sheet.cell(row=1, column=1).value = "マンション名"
        sheet.cell(row=1, column=2).value = "住所"
        sheet.cell(row=1, column=3).value = "判定結果"

        zip1 = []
        zip2 = []
        addresses_num3 = []
        addresses_num4 = []
        addresses_num5 = []

        for j in range(len(mansions)):
            print(mansions[j])
            print(addresses[j])
            sheet.cell(row=j + 2, column=1).value = mansions[j]  # セルに値を設定する
            sheet.cell(row=j + 2, column=2).value = addresses[j]

            address = addresses[j]

            if address == '取得できませんでした':
                zip1.append("")
                zip2.append("")
                addresses_num3.append("")
                addresses_num4.append("")
                addresses_num5.append("")
                continue

            try:
                post_code = re.findall(r'\d+', address)
                print(post_code)

                if len(post_code[0]) == 3 and len(post_code[1]) == 4:
                    zip1.append(post_code[0])
                    zip2.append(post_code[1])
                    addresses_num3.append(post_code[2])
                    addresses_num4.append(post_code[3])
                    try:
                        if post_code[4] != None:
                            addresses_num5.append(post_code[4])
                        else:
                            addresses_num5.append("")
                    except Exception as e:
                        print(e)
                        addresses_num5.append("")
                else:
                    zip1.append("")
                    zip2.append("")
                    addresses_num3.append("")
                    addresses_num4.append("")
                    addresses_num5.append("")
            except Exception as e:
                print(e)
                zip1.append("")
                zip2.append("")
                addresses_num3.append("")
                addresses_num4.append("")
                addresses_num5.append("")

        print(zip1)
        print(zip2)
        print(addresses_num3)
        print(addresses_num4)

        # 幅調整
        sheet.column_dimensions['A'].width = 40
        sheet.column_dimensions['B'].width = 50

        driver.close()

        # ワークブックに名前をつけて保存する
        book.save('result.xlsx')

        driver = webdriver.Chrome(p)
        for z in range(len(addresses)):

            if "取得できません" in addresses[z] or zip1[z] == "":
                continue

            driver.get("https://flets-w.com/cart/?etc_data_kks=kantan%3D1%40")
            time.sleep(5 + speed_han)

            print("----------------------------")
            print(mansions[z])
            print(addresses[z])

            results = []
            driver.maximize_window()

            element = driver.find_element_by_id('p_mansion_1')
            element.click()
            time.sleep(1 + speed_han)

            element = driver.find_element_by_id('zip1')
            element.send_keys(zip1[z])
            time.sleep(1 + speed_han)

            element = driver.find_element_by_id('zip2')
            element.send_keys(zip2[z])
            time.sleep(1 + speed_han)

            element = driver.find_element_by_class_name('btn_area_zip')
            element.click()
            time.sleep(3 + speed_han)

            if '丁目' in addresses[z]:

                if addresses_num3[z] != "":
                    print("丁目：" + addresses_num3[z])
                    try:
                        elements = driver.find_elements_by_partial_link_text(addresses_num3[z])
                        print("丁目が数件部分一致")
                        element = elements[1]

                    except Exception as e:
                        print(e)
                        try:
                            print("丁目を1件再検索")
                            time.sleep(speed_han)
                            element = driver.find_element_by_partial_link_text(addresses_num3[z])
                        except Exception as e:
                            print(e)
                            result = "提供可否不明"
                            sheet.cell(row=z + 2, column=3).value = result
                            sheet.column_dimensions['C'].width = 20
                            print("id:" + str(db_id) + " マンション名:" + mansions[z] + " 住所:" + addresses[z] + " 提供結果:" + result + " トランザクションID:" + transaction_id + " 日付:" + str(datetime.datetime.now()))
                            cur.execute('INSERT INTO teikyou_hantei VALUES (?, ?, ?, ?, ?, ?)',
                                        (db_id, mansions[z], addresses[z], result, transaction_id, datetime.datetime.now()))
                            db_id += 1
                            # ワークブックに名前をつけて保存する
                            book.save('result.xlsx')
                            time.sleep(5 + speed_han)
                            continue

                    element.click()
                    time.sleep(2 + speed_han)

                if addresses_num4[z] != "":
                    print("番地：" + addresses_num4[z])
                    try:
                        element = driver.find_element_by_link_text(addresses_num4[z])
                        # if len(elements) > 1:
                        #     element = elements[1]
                        # else:
                        #     element = elements[0]
                        print("番地が一致しました")
                        element.click()
                        time.sleep(2 + speed_han)
                    except Exception as e:
                        print(e)
                        print("番地を1件再検索")
                        element = driver.find_element_by_partial_link_text(addresses_num4[z])
                        element.click()
                        time.sleep(2 + speed_han)

                if addresses_num5[z] != "":
                    print("号：" + addresses_num5[z])
                    try:
                        print("号を検索")
                        elements = driver.find_elements_by_link_text(addresses_num5[z])
                        if len(elements) > 1:
                            element = elements[1]
                        else:
                            element = elements[0]

                        element.click()
                        time.sleep(2 + speed_han)
                    except Exception as e:
                        print(e)
                        try:
                            print("号を1件再検索")
                            element = driver.find_element_by_link_text(addresses_num5[z])
                            element.click()
                        except Exception as e:
                            print(e)
                            result = "提供可否不明"
                            sheet.cell(row=z + 2, column=3).value = result
                            sheet.column_dimensions['C'].width = 20
                            print("id:" + str(db_id) + " マンション名:" + mansions[z] + " 住所:" + addresses[z] + " 提供結果:" + result + " トランザクションID:" + transaction_id + " 日付:" + str(datetime.datetime.now()))
                            cur.execute('INSERT INTO teikyou_hantei VALUES (?, ?, ?, ?, ?, ?)', (db_id, mansions[z], addresses[z], result, transaction_id, datetime.datetime.now()))
                            db_id += 1
                            # ワークブックに名前をつけて保存する
                            book.save('result.xlsx')
                            time.sleep(5 + speed_han)
                            continue

                else:
                    result = "提供可否不明"
                    sheet.cell(row=z + 2, column=3).value = result
                    sheet.column_dimensions['C'].width = 20

                    # ワークブックに名前をつけて保存する
                    book.save('result.xlsx')
                    time.sleep(5 + speed_han)
                    continue
            else:
                print("丁目なし")
                print("番地" + addresses_num3[z])
                time.sleep(speed_han)
                element = driver.find_element_by_xpath('//*[@id="list-box"]/ul/li/a')
                element.click()
                time.sleep(speed_han)
                try:
                    element = driver.find_element_by_link_text(addresses_num3[z])
                except Exception as e:
                    print(e)
                    try:
                        print("丁目を1件再検索")
                        time.sleep(speed_han)
                        element = driver.find_element_by_link_text(addresses_num3[z])
                    except Exception as e:
                        print(e)
                        print("丁目がないため1つ目をクリック")
                        element = driver.find_element_by_xpath('//*[@id="list-box"]/ul/li/a')

                element.click()
                time.sleep(2 + speed_han)

                print("号：" + addresses_num4[z])
                try:
                    element = driver.find_element_by_link_text(addresses_num4[z])
                    print("号が一致しました")
                    element.click()
                    time.sleep(2 + speed_han)
                except Exception as e:
                    try:
                        print(e)
                        print("号を1件再検索")
                        element = driver.find_element_by_partial_link_text(addresses_num4[z])
                        element.click()
                        time.sleep(2 + speed_han)
                    except Exception as e:
                        print(e)
                        result = "提供可否不明"
                        sheet.cell(row=z + 2, column=3).value = result
                        sheet.column_dimensions['C'].width = 20
                        print("id:" + str(db_id) + " マンション名:" + mansions[z] + " 住所:" + addresses[z] + " 提供結果:" + result + " トランザクションID:" + transaction_id + " 日付:" + str(datetime.datetime.now()))
                        cur.execute('INSERT INTO teikyou_hantei VALUES (?, ?, ?, ?, ?, ?)', (db_id, mansions[z], addresses[z], result, transaction_id, datetime.datetime.now()))
                        db_id += 1
                        # ワークブックに名前をつけて保存する
                        book.save('result.xlsx')
                        time.sleep(5 + speed_han)
                        continue

            try:
                element = driver.find_element_by_xpath('//*[@id="list-box"]/ul/li/a')
                if element.text != "":
                    element.click()
                    time.sleep(4 + speed_han)

                hantei_address = driver.find_element_by_id('kakutei-box').text
                print(hantei_address)
                element = driver.find_element_by_xpath('//*[@id="btn-hantei"]/a')
                element.click()
                time.sleep(8 + speed_han)
            except Exception as e:
                print(e)
                try:
                    hantei_address = driver.find_element_by_id('kakutei-box').text
                    print(hantei_address)
                    element = driver.find_element_by_xpath('//*[@id="btn-hantei"]/a')
                    element.click()
                    time.sleep(8 + speed_han)
                except Exception as e:
                    print(e)
                    element = driver.find_element_by_xpath('//*[@id="list-box"]/ul/li/a')
                    element.click()

            try:
                time.sleep(3)
                element = driver.find_element_by_id('tab_wrap_inner')
                print(element.text)
            except Exception as e:
                print(e)
                element = driver.find_element_by_xpath('//*[@id="btn-hantei"]/a')
                element.click()
                time.sleep(8 + speed_han)

                element = driver.find_element_by_id('tab_wrap_inner')
                print(element.text)

            if "ファミリー・" in element.text:
                result = "ファミリー隼"
            elif "提供条件が整った場合にご提供いたしますので" in element.text:
                result = "提供不可"
            elif "お申し込み可能なサービスやご提供時期については弊社にて調査後" in element.text:
                result = "調査中"
            elif "ＶＤＳＬ方式" in element.text:
                result = "ＶＤＳＬ方式"
            elif "マンションミニ" in element.text:
                result = "ミニ隼"
            elif "マンション・スーパーハイスピードタイプ 隼" in element.text:
                result = "隼"
            else:
                result = element.text

            results.append(result)
            # sheet.cell(row=z + 2, column=3).value = hantei_address
            sheet.cell(row=z + 2, column=3).value = result
            sheet.column_dimensions['C'].width = 20
            sheet.column_dimensions['D'].width = 20

            print("id:" + str(db_id) + " マンション名:" + mansions[z] + " 住所:" + addresses[z] + " 提供結果:" + result + " トランザクションID:" + transaction_id + " 日付:" + str(datetime.datetime.now()))
            cur.execute('INSERT INTO teikyou_hantei VALUES (?, ?, ?, ?, ?, ?)', (db_id, mansions[z], addresses[z], result, transaction_id, datetime.datetime.now()))
            # 保存を実行（忘れると保存されないので注意）
            conn.commit()
            db_id += 1

            # ワークブックに名前をつけて保存する
            book.save('result.xlsx')

            time.sleep(5 + speed_han)

        driver.close()

        print("提供判定が完了しました")
        try:
            contents = cur.execute('SELECT * FROM teikyou_hantei WHERE transaction_id = ?', (transaction_id,)).fetchall()
            set_mappin.set_mappin(transaction_id)
        except Exception as e:
            print(e)
        # DB接続を閉じる
        # conn.close()
        return contents

    except Exception as e:
        print("提供判定に失敗しました")
        print(e)
        e = e
        return e


from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle
from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.tests.utils import ERPNextTestCase, change_settings

class TestPackedItem(ERPNextTestCase):
	"Test impact on Packed Items table in various scenarios."
	@classmethod
	def setUpClass(cls) -> None:
		make_item("_Test Product Bundle X", {"is_stock_item": 0})
		make_item("_Test Bundle Item 1", {"is_stock_item": 1})
		make_item("_Test Bundle Item 2", {"is_stock_item": 1})
		make_item("_Test Normal Stock Item", {"is_stock_item": 1})

		make_product_bundle(
			"_Test Product Bundle X",
			["_Test Bundle Item 1", "_Test Bundle Item 2"],
			qty=2
		)

	def test_adding_bundle_item(self):
		"Test impact on packed items if bundle item row is added."
		so = make_sales_order(item_code = "_Test Product Bundle X", qty=1,
			do_not_submit=True)

		self.assertEqual(so.items[0].qty, 1)
		self.assertEqual(len(so.packed_items), 2)
		self.assertEqual(so.packed_items[0].item_code, "_Test Bundle Item 1")
		self.assertEqual(so.packed_items[0].qty, 2)

	def test_updating_bundle_item(self):
		"Test impact on packed items if bundle item row is updated."
		so = make_sales_order(item_code = "_Test Product Bundle X", qty=1,
			do_not_submit=True)

		so.items[0].qty = 2 # change qty
		so.save()

		self.assertEqual(so.packed_items[0].qty, 4)
		self.assertEqual(so.packed_items[1].qty, 4)

		# change item code to non bundle item
		so.items[0].item_code = "_Test Normal Stock Item"
		so.save()

		self.assertEqual(len(so.packed_items), 0)

	def test_recurring_bundle_item(self):
		"Test impact on packed items if same bundle item is added and removed."
		so_items = []
		for qty in [2, 4, 6, 8]:
			so_items.append({
				"item_code": "_Test Product Bundle X",
				"qty": qty,
				"rate": 400,
				"warehouse": "_Test Warehouse - _TC"
			})

		# create SO with recurring bundle item
		so = make_sales_order(item_list=so_items, do_not_submit=True)

		# check alternate rows for qty
		self.assertEqual(len(so.packed_items), 8)
		self.assertEqual(so.packed_items[1].item_code, "_Test Bundle Item 2")
		self.assertEqual(so.packed_items[1].qty, 4)
		self.assertEqual(so.packed_items[3].qty, 8)
		self.assertEqual(so.packed_items[5].qty, 12)
		self.assertEqual(so.packed_items[7].qty, 16)

		# delete intermediate row (2nd)
		del so.items[1]
		so.save()

		# check alternate rows for qty
		self.assertEqual(len(so.packed_items), 6)
		self.assertEqual(so.packed_items[1].qty, 4)
		self.assertEqual(so.packed_items[3].qty, 12)
		self.assertEqual(so.packed_items[5].qty, 16)

		# delete last row
		del so.items[2]
		so.save()

		# check alternate rows for qty
		self.assertEqual(len(so.packed_items), 4)
		self.assertEqual(so.packed_items[1].qty, 4)
		self.assertEqual(so.packed_items[3].qty, 12)

	@change_settings("Selling Settings", {"editable_bundle_item_rates": 1})
	def test_bundle_item_cumulative_price(self):
		"Test if Bundle Item rate is cumulative from packed items."
		so = make_sales_order(item_code = "_Test Product Bundle X", qty=2,
			do_not_submit=True)

		so.packed_items[0].rate = 150
		so.packed_items[1].rate = 200
		so.save()

		self.assertEqual(so.items[0].rate, 350)
		self.assertEqual(so.items[0].amount, 700)

	def test_newly_mapped_doc_packed_items(self):
		"Test impact on packed items in newly mapped DN from SO."
		so_items = []
		for qty in [2, 4]:
			so_items.append({
				"item_code": "_Test Product Bundle X",
				"qty": qty,
				"rate": 400,
				"warehouse": "_Test Warehouse - _TC"
			})

		# create SO with recurring bundle item
		so = make_sales_order(item_list=so_items)

		dn = make_delivery_note(so.name)
		dn.items[1].qty = 3 # change second row qty for inserting doc
		dn.save()

		self.assertEqual(len(dn.packed_items), 4)
		self.assertEqual(dn.packed_items[2].qty, 6)
		self.assertEqual(dn.packed_items[3].qty, 6)


import os
import sys
import argparse
import random
import pickle
from itertools import count
import numpy as np
import numpy.linalg as la
from statistics import mean

import torch
from mujoco_py import MjViewer, load_model_from_path, MjSim

from networks.dqn import DQN
from networks.dqn import Geom_DQN
from networks.dqn import DRQN
from networks.tactile_net import TactileNet
from robot_sim import RobotSim
from sim_param import SimParameter

from utils.action_buffer import ActionSpace, TactileObs
from utils.normalize import Multimodal_Normalizer
from utils.velcro_utils import VelcroUtil
from utils.gripper_util import change_sim

NUM_TENDON = 216

def select_action(args, observation, policy_net, tactile_net, hidden_state, cell_state):
    sample = random.random()
    p_threshold = 0.05

    with torch.no_grad():
        tactile_net.eval()
        policy_net.eval()
        torch_obs = torch.from_numpy(observation).float().to(args.device).unsqueeze(0)
        h_tac, c_tac = tactile_net.init_hidden_states(args.device)
        tactile_ft = tactile_net.forward(torch_obs, hidden_state=h_tac, cell_state=c_tac)

        model_out = policy_net(tactile_ft.unsqueeze(1), batch_size=1, time_step=1, hidden_state=hidden_state, cell_state=cell_state)
        out = model_out[0]
        hidden_state = model_out[1][0]
        cell_state = model_out[1][1]

        if sample > p_threshold:
            action = int(torch.argmax(out[0]))
            return action, hidden_state, cell_state
        else:
            return random.randrange(0, args.outdim), hidden_state, cell_state

def test_network(args, policy_net, tactile_net, normalizer, robot, obs_space, performance):
    hidden_state, cell_state = policy_net.init_hidden_states(1, args.device)

    action_space = ActionSpace(dp=0.06, df=10)
    ACTIONS = ['left', 'right', 'forward', 'backward', 'up', 'down']
    broken_so_far = 0

    t = 0
    action = 4
    collision = 0

    while t < args.max_iter:

        if args.position:
            multistep_obs = np.empty((0, args.indim-6))
        elif args.force:
            multistep_obs = np.empty((0, args.indim-390))
        else:
            multistep_obs = np.empty((0, args.indim))

        prev_action = action

        for k in range(args.len_ub):
            # Observe tactile features and stack them
            tactile_obs = obs_space.get_state()
            normalizer.observe(tactile_obs)
            tactile_obs = normalizer.normalize(tactile_obs)

            if args.position:
                tactile_obs = tactile_obs[6:]
            elif args.force:
                tactile_obs = tactile_obs[:6]

            multistep_obs = np.vstack((multistep_obs, tactile_obs))

            # current jpos
            current_pos = robot.get_gripper_jpos()[:3]

            # Perform action
            delta = action_space.get_action(ACTIONS[action])['delta'][:3]
            target_position = np.add(robot.get_gripper_jpos()[:3], np.array(delta))
            target_pose = np.hstack((target_position, robot.get_gripper_jpos()[3:]))
            robot.move_joint(target_pose, True, args.grip_force, hap_sample = args.hap_sample)

            # check collision number
            collision += robot.feedback_buffer['collision']

            # Observe new state
            obs_space.update(robot.get_gripper_xpos(),            # 24
                                     robot.get_all_touch_buffer(args.hap_sample))     # 30x6

            displacement = la.norm(robot.get_gripper_jpos()[:3] - current_pos)

            if displacement / 0.06 < 0.7:
                break

        # input stiched multi-step tactile observation into tactile-net to generate tactile feature
        action, hidden_state, cell_state = select_action(args, multistep_obs, policy_net, tactile_net,
                                                         hidden_state, cell_state)

        # record actions in this epoch
        # act_sequence.append(prev_action)

        # Get reward
        done, num = robot.update_tendons()
        failure = robot.check_slippage()
        if num > broken_so_far:
            broken_so_far = num

        t += k + 1

        if done or failure:
            ratio_broken = float(num) / float(NUM_TENDON)
            if ratio_broken < 0.2:
                performance['tendon_hist'][0] += 1
            elif ratio_broken >= 0.2 and ratio_broken < 0.4:
                performance['tendon_hist'][1] += 1
            elif ratio_broken >= 0.4 and ratio_broken < 0.6:
                performance['tendon_hist'][2] += 1
            elif ratio_broken >= 0.6 and ratio_broken < 0.8:
                performance['tendon_hist'][3] += 1
            else:
                performance['tendon_hist'][4] += 1
            performance['num_broken'].append(num)
            if done:
                performance['success'].append(1)
                performance['time'].append(t + 1)
            if failure:
                performance['success'].append(0)
                performance['time'].append(t + 1)
            performance['collision'].append(collision)
            return performance
            break

    ################## exceed max iterations ####################
    performance['success'].append(0)
    performance['time'].append(args.max_iter)
    ratio_broken = float(num) / float(NUM_TENDON)
    performance['num_broken'].append(num)
    if ratio_broken < 0.2:
        performance['tendon_hist'][0] += 1
    elif ratio_broken >= 0.2 and ratio_broken < 0.4:
        performance['tendon_hist'][1] += 1
    elif ratio_broken >= 0.4 and ratio_broken < 0.6:
        performance['tendon_hist'][2] += 1
    elif ratio_broken >= 0.6 and ratio_broken < 0.8:
        performance['tendon_hist'][3] += 1
    else:
        performance['tendon_hist'][4] += 1
    performance['collision'].append(collision)
    return performance

def main(args):
    if not os.path.isdir(args.result_dir):
        os.makedirs(args.result_dir)
    parent = os.path.dirname(os.path.abspath(__file__))
    # load test xml files
    test_file = os.path.join(parent, 'tests/test_xmls/temp_1_{}.pickle'.format(args.case))
    params = pickle.load(open(test_file, 'rb'))
    # params = params[:6]
    if args.shuffle:
        random.shuffle(params)

    num_test = len(params)
    print('                    ++++++++++++++++++++++++++')
    print('                    +++ Now running case {} +++'.format(args.case))
    print('                    ++++++++++++++++++++++++++\n\n')

    # Create our policy net and a target net
    policy_net = DRQN(args.ftdim, args.outdim).to(args.device)
    if args.position:
        tactile_net = TactileNet(args.indim-6, args.ftdim).to(args.device)
    elif args.force:
        tactile_net = TactileNet(args.indim-390, args.ftdim).to(args.device)
    else:
        tactile_net = TactileNet(args.indim, args.ftdim).to(args.device)

    # Setup the state normalizer
    normalizer = Multimodal_Normalizer(num_inputs = args.indim, device=args.device)

    if args.weight_policy:
        checkpoint = torch.load(args.weight_policy)
        policy_net.load_state_dict(checkpoint['policy_net_1'])
    if args.weight_tactile:
        checkpoint = torch.load(args.weight_tactile)
        tactile_net.load_state_dict(checkpoint['tactile_net_1'])
    if args.normalizer_file:
        if os.path.exists(args.normalizer_file):
            normalizer.restore_state(args.normalizer_file)

    # Create robot, reset simulation and grasp handle
    model = load_model_from_path(args.model_path)
    sim = MjSim(model)
    sim_param = SimParameter(sim)
    sim.step()
    if args.render:
        viewer = MjViewer(sim)
    else:
        viewer = None

    robot = RobotSim(sim, viewer, sim_param, args.render, args.break_thresh)

    tactile_obs_space = TactileObs(robot.get_gripper_xpos(),            # 24
                         robot.get_all_touch_buffer(args.hap_sample))   # 30 x 6

    performance = {'time':[], 'success':[], 'num_broken':[], 'tendon_hist':[0,0,0,0,0], 'collision':[]}

    for i in range(num_test):
        velcro_params = params[i]
        geom, origin_offset, euler, radius = velcro_params
        print('\n\nTest {} Velcro parameters are: {}, {}, {}, {}'.format(i, geom, origin_offset, euler, radius))
        change_sim(robot.mj_sim, geom, origin_offset, euler, radius)
        robot.reset_simulation()
        ret = robot.grasp_handle()
        performance = test_network(args, policy_net, tactile_net, normalizer, robot, tactile_obs_space, performance)
        print('Success: {}, time: {}, num_broken: {}, collision:{} '.format(
                performance['success'][-1], performance['time'][-1], performance['num_broken'][-1], performance['collision'][-1]))

    print('Finished opening velcro with haptics test \n')
    success = np.array(performance['success'])
    time = np.array(performance['time'])
    print('Successfully opened the velcro in: {}% of cases'.format(100 * np.sum(success) / len(performance['success'])))
    print('Average time to open: {}'.format(np.average(time[success>0])))
    # print('Action histogram for the test is: {}'.format(performance['action_hist']))

    # collision = np.array(performance['collision'])
    # threshold = 3000
    # high_success = float(np.sum(success[collision<threshold])) / float(np.sum(np.ones(num_test)[collision<threshold]))
    # low_success =  float(np.sum(success[collision>threshold])) / float(np.sum(np.ones(num_test)[collision>threshold]))
    # print('high_success: {} low_success: {} '.format(high_success, low_success))

    ablation = 'None'
    if args.position:
        ablation = 'position'
    if args.force:
        ablation = 'force'
    checkpoint = args.weight_policy.split('/')[-1]
    out_fname = 'case{}_{}_{}.txt'.format(args.case, ablation, checkpoint)
    with open(os.path.join(args.result_dir, out_fname), 'w+') as f:
        f.write('Time: {}\n'.format(performance['time']))
        f.write('Success: {}\n'.format(performance['success']))
        f.write('Successfully opened the velcro in: {}% of cases\n'.format(100 * np.sum(success) / len(performance['success'])))
        f.write('Average time to open: {}\n'.format(np.average(time[success>0])))
        f.write('Num_broken: {}\n'.format(performance['num_broken']))
        f.write('Tendon histogram: {}\n'.format(performance['tendon_hist']))
        f.write('collision: {}\n'.format(performance['collision']))
        # f.write('high_success: {} low_success: {} '.format(high_success, low_success))
    f.close()

if __name__ == "__main__":

    parser = argparse.ArgumentParser(description='PyTorch Tactile Test')
    ablation = parser.add_mutually_exclusive_group(required=True)
    ablation.add_argument('--none', action='store_true', help='include position, shear and tactile in observation')
    ablation.add_argument('--position', action='store_true', help='remove position from observation')
    ablation.add_argument('--force', action='store_true', help='remove tactile from observation')

    parser.add_argument('--model_path', required=True, help='XML model to load')
    parser.add_argument('--case', required=True, type=int, help='test case to load')
    parser.add_argument('--device', default='cuda', help='device')
    parser.add_argument('--indim', default=234, type=int, help='observation space size')
    parser.add_argument('--outdim', default=6, type=int, help='action space size')
    parser.add_argument('--ftdim', default=150, type=int, help='tactile feature size')
    parser.add_argument('--break_thresh', default=0.06, type=float, help='velcro breaking threshold')
    parser.add_argument('--max_iter', default=200, type=float, help='max number of iterations per epoch')
    parser.add_argument('--grip_force', default=400, type=float, help='gripping force')
    parser.add_argument('--len_ub', default=15, type=int, help='upper bound of multistep agent takes')
    parser.add_argument('--render', action='store_true', help='turn on rendering')
    parser.add_argument('--shuffle', action='store_true', help='shuffle the velcro parameters after loading')
    parser.add_argument('--weight_policy', default=None, help='checkpoint file to load to resume training')
    parser.add_argument('--normalizer_file', default=None, help='normalizer file to load to resume training')
    parser.add_argument('--weight_tactile', default=None, help='normalizer file to load to resume training')
    parser.add_argument('--hap_sample', default=30, type=int, help='number of haptics samples feedback in each action excution')
    parser.add_argument('--result_dir', default='/home/jc/logs/', help='dir to store results')

    args = parser.parse_args()
    main(args)


# Реализуйте алгоритм перемешивания элементов списка.
# Без функции shuffle из модуля random, другие методы использовать можно.

from random import sample

def task010():
    my_list = [4, 5, 6, 7, 8, 9, 10, 11]
    length = len(my_list)
    index_list = create_index_list(length)
    print(index_list)
    new_original_list = original_list(index_list, my_list)
    print(new_original_list)

def create_index_list(long):
    list_2 = []
    for el in range(long):
        list_2.append(el)
    return sample(list_2, long)

def original_list(new_idx_list, one_list):
    answer_list = []
    for el in new_idx_list:
        answer_list.append(one_list[el])
    return answer_list

task010()


import os
import os.path as path
import random

from splicing.utils.spliceai_utils import get_architecture

def get_args(parser):

    ###########################################################################
    # Workflow
    ###########################################################################
    parser.add_argument('-pretrain', action='store_true')
    parser.add_argument('-save_feats', action='store_true')
    parser.add_argument('-finetune', action='store_true')
    parser.add_argument('-test_baseline', action='store_true')
    parser.add_argument('-test_graph', action='store_true')

    ###########################################################################
    # Directory & model saving
    ###########################################################################
    parser.add_argument('-modelid', type=str, default="0", dest='model_id',
        help='Model identifier, placed in front of other folder name defining args.')
    parser.add_argument('-save_mode', type=str, choices=['all', 'best'],
        default='best')

    ###########################################################################
    # Model loading
    ###########################################################################
    parser.add_argument('-load_pretrained', action='store_true')
    parser.add_argument(
        '-mpass', '--model_pass', type=int, default=10, dest='model_pass',
        help='The pass number of the SpliceAI model to load.')
    parser.add_argument(
        '-midx', '--model_index', type=int, default=1, dest='model_index',
        help='The index of the SpliceAI model to load.')
    parser.add_argument(
        '-mit', '--model_iteration', type=int, default=10, required=False,
        dest='model_iteration',
        help='The iteration (pass) of the SpliceAI model to load.')
    parser.add_argument('-load_gcn', action='store_true')

    ###########################################################################
    # General Training Params
    ###########################################################################
    parser.add_argument(
        '-vi', '--validation_interval', type=int, default=128,
        dest='validation_interval', help='Per how many epochs to validate.')
    parser.add_argument(
        '-li', '--log_interval', type=int, default=128,
        dest='log_interval', help='Per how many updates to log to WandB.')
    parser.add_argument(
        '-test', action='store_true',
        help="Compute test scores at every full validation interval"
    )

    ###########################################################################
    # Data params
    ###########################################################################
    parser.add_argument(
        '-cl', '--context_length', dest='context_length',
        choices = [80, 400], required=True,
        type=int, help='The context length to use.')
    parser.add_argument(
        '-ws', '--window_size', dest='window_size',
        choices = [1000, 5000], type=int, required=True,
        help='Size of the pretrain batches and graph windows.')

    ###########################################################################
    # SpliceAI / Pretraining args
    ###########################################################################
    parser.add_argument(
        '-w', '--class_weights', type=int, nargs=3, default=(1, 1, 1),
        dest='class_weights', help='Class weights to use.')
    parser.add_argument(
        '-npass', '--passes', type=int, default=10,
        dest='passes', help='Number of passes over the train dataset to do.')
    parser.add_argument('-cnn_lr', type=float, default=0.001)
    parser.add_argument('-cnn_sched', type=str, default='multisteplr',
        choices = ['multisteplr', 'reducelr'],
        help='Scheduler to use for pretraining'
    )

    ###########################################################################
    # General Finetune Training Params
    ###########################################################################
    parser.add_argument(
        '-gbs', '--graph_batch_size', dest='graph_batch_size', type=int,
        default=32, help='Batch size for finetuning.')
    parser.add_argument(
        '-fep', '--finetune_epochs', dest='finetune_epochs', type=int,
        default=6, help='Number of epochs for graph training.')

    # Optimizer and lrs
    parser.add_argument('-ft_optim', type=str, choices=['adam', 'sgd'],
        default='adam')
    parser.add_argument('-weight_decay', type=float, default=1e-6,
                        help='SGD weight decay')
    parser.add_argument('-nr_lr', type=float, default=0.001)
    parser.add_argument('-gcn_lr', type=float, default=0.001)
    parser.add_argument('-full_lr', type=float, default=0.0001)

    # Scheduler: three types - StepLr, MultiStepLR, ReduceLROnPlateau
    parser.add_argument(
        '-ft_sched', dest='ft_sched', type=str, default='reducelr',
        choices = ['steplr', 'multisteplr', 'reducelr'],
        help='Scheduler to use for finetuning'
    )

    # StepLR params
    parser.add_argument(
        '-lr_decay', dest='lr_decay', type=float, default=0.5,
        help='The factor by which to decrease the learning rate')
    parser.add_argument(
        '-lr_step_size', dest='lr_step_size', type=int, default=1,
        help='After how many passes to decrease learning rate')

    # ReduceLROnPlateau params
    parser.add_argument(
        '-rlr_factor', type=float, default=0.1,
        help="Factor by which the learning rate will be reduced."
    )
    parser.add_argument(
        '-rlr_patience', type=int, default=2,
        help='Number of epochs with no improvement after which '\
            'learning rate will be reduced.'
    )
    parser.add_argument(
        '-rlr_threshold', type=int, default=1e-2,
        help="Threshold for measuring the new optimum, to only "\
            "focus on significant changes."
    )

    # Boost Graph
    parser.add_argument(
        '-boost_period', type=int, default=1,
        help='Update full model weights only every x iterations,'\
            'default 1 means updates every epoch.'
    )

    ###########################################################################
    ### Graph Model parameters
    ###########################################################################
    parser.add_argument(
        '-nc', '--n_channels', type=int, default=32, dest='n_channels',
        help='Number of convolution channels to use.'
    )
    parser.add_argument(
        '-nhidd', '--hidden_size', type=int, default=64, dest='hidden_size',
        help='The dimensionality of the hidden layer in the graph network.')
    parser.add_argument(
        '-rep', '--node_representation',
        type=str,
        default='min-max',
        dest='node_representation',
        choices = ['average', 'max', 'min', 'min-max', 'conv1d', 'pca', 'summary', 'zeros'],
        help='How to construct the node representation '
             'from the nucleotide representations.'
    )
    parser.add_argument(
        '--pca_dims',
        type=int,
        default=2,
        help='compnents that the 5000 features get reduced to for the node representation')
    parser.add_argument('-gcn_dropout', type=float, default=0.2)
    parser.add_argument('-nr_model', type=str, default="clem_bn",
        choices = ["clem_bn", "linbig", "linmed", "linsmall"],
        help='Version of the node representation architecture to use.')
    parser.add_argument('-gat_conv', action='store_true')
    parser.add_argument('-n_heads', default=1, type=int)

    #parser.add_argument("-rep_size", type=int, default=128,
    #    help="Size of the initial node representation before 1D convolution")
    #parser.add_argument('-gate', action='store_true')

    ###########################################################################
    ### Graph initialization
    ###########################################################################
    parser.add_argument('-A_saliency', action='store_true')
    parser.add_argument('-adj_type', type=str,
        choices=['constant', 'hic', 'both', 'random', 'none', ''],
        default='hic'
    )
    parser.add_argument('-hicnorm', type=str,
                        choices=['KR', 'VC', 'SQRTVC', ''], default='SQRTVC')
    parser.add_argument('-hicsize', type=str,
                        choices=['125000', '250000', '500000', '1000000'],
                        default='500000')

    ###########################################################################
    # Full Model Parameters
    ###########################################################################
    parser.add_argument(
        '-nhidd_f', '--hidden_size_full', type=int, default=128,
        dest='hidden_size_full',
        help='The dimensionality of the hidden layer in the final network.')
    parser.add_argument(
        '-nt_conv', action='store_true'
    )
    parser.add_argument(
        '-zeronuc', action='store_true'
    )
    parser.add_argument(
        '-zeronodes', action='store_true'
    )
    parser.add_argument(
        '-ingrad', action='store_true', help='Analyze input gradients.'
    )
    parser.add_argument(
        '-nhs', '--node_headstart', dest='node_headstart', type=int, default=0,
        help='Number of epochs to train on node representations only.')
    parser.add_argument('-full_dropout', type=float, default=0.5)

    ###########################################################################
    # Logging Args
    ###########################################################################
    parser.add_argument('-wb', '--wandb', dest='wandb', action='store_true')
    parser.add_argument('-wbn', dest='wandb_name', default="", type=str,
        help="Name of wandb run.")

    opt = parser.parse_args()
    return opt

def config_args(opt, config):
    """ set up the 'opt' object to score the run config """

    opt.ft_random_id = str(random.randint(1, 1000000))

    # OUR DATA DIRECTORIES
    opt.splice_data_root = path.join(
        config['DATA_DIRECTORY'], config['DATA_PIPELINE']['output_dir'])
    opt.results_dir = path.join(
        config['DATA_DIRECTORY'], config['TRAINING']['results_dir'])

    # Workflow
    assert sum([opt.pretrain, opt.save_feats, opt.finetune, opt.test_baseline, opt.test_graph]) == 1, \
        "Must have only one of: -pretrain, -save_feats, -finetune"

    if opt.pretrain:
        opt.workflow = "pretrain"
    elif opt.save_feats:
        opt.workflow = "save_feats"
    elif opt.finetune:
        opt.workflow = "finetune"
    elif opt.test_baseline:
        assert opt.load_pretrained, 'Have to load pretrained model'
        opt.workflow = 'test_baseline'
    elif opt.test_graph:
        assert opt.load_pretrained, 'Have to load pretrained model'
        opt.workflow = 'test_graph'

    opt.test_baseline_models_dir = path.join(
        config['DATA_DIRECTORY'], config['TRAINING']['test_baseline_models_dir'])
    opt.test_graph_models_dir = path.join(
        config['DATA_DIRECTORY'], config['TRAINING']['test_graph_models_dir'])

    opt.cell_type = 'GM12878'

    # CNN args:
    kernel_size, dilation_rate, batch_size = get_architecture(
        opt.context_length
    )

    opt.kernel_size = kernel_size
    opt.dilation_rate = dilation_rate
    opt.batch_size = batch_size

    opt.model_name = f'{opt.model_id}_splice_ai'
    opt.model_name += '.ws_' + str(opt.window_size)
    opt.model_name += '.cl_' + str(opt.context_length)

    if opt.save_feats:
        opt.pretrain = False
        opt.train_ratio = 1.0

    if opt.finetune:
        opt.model_name += '/finetune' + '_' + opt.ft_random_id

    opt.model_name = path.join(opt.results_dir, opt.cell_type, opt.model_name)

    opt.graph_data_root = path.join(
        config['DATA_DIRECTORY'],
        config['DATA_PIPELINE']['output_dir']
    )
    opt.dataset = path.join(opt.graph_data_root, opt.cell_type)
    opt.cuda = True

    if opt.save_feats:
        opt.batch_size = 512

    # Directory handling
    assert not (os.path.exists(opt.model_name) and opt.pretrain), \
        "Model directory already exists, please specify another -modelid"

    assert not (os.path.exists(opt.model_name) and opt.finetune), \
        "Finetune model directory already exists"

    assert not opt.node_representation == "pca", "PCA is broken rn"

    assert opt.context_length % 2 == 0

    return opt


from __future__ import division, print_function
import sys, os
from iotbx import reflection_file_reader
import iotbx.pdb
import mmtbx.model

def run(args):
  if (len(args) != 2):
    raise RuntimeError("Please specify two file names.")
  fn_1 = args[0]
  fn_2 = args[1]
  model_filename, reflection_filename = None, None

  for fn in (fn_1, fn_2):
    if os.path.splitext(fn)[1] == '.mtz' and reflection_filename is None:
      reflection_filename = fn
    elif os.path.splitext(fn)[1] == '.pdb' and model_filename is None:
      model_filename = fn
    else:
      raise RuntimeError("Please specify one model file and one reflection file.")

  print('Model file name: ', model_filename)
  print('Reflection file name: ', reflection_filename)

  pdb_inp = iotbx.pdb.input(file_name=model_filename)
  model = mmtbx.model.manager(model_input = pdb_inp)

  miller_arrays = reflection_file_reader.any_reflection_file(
    file_name = reflection_filename).as_miller_arrays()

  for ma in miller_arrays:
    if (ma.info().label_string()=="FOBS,SIGFOBS"):
      f_obs = ma
    if (ma.info().label_string()=='R-free-flags'):
      r_free_flags = ma

if (__name__ == "__main__"):
  run(sys.argv[1:])


import sys
sys.stdin=open('bj2151.txt','r')

dx=[1,0,-1,0]
dy=[0,1,0,-1]
def IS(y,x):
    return -1<y<N and -1<x<N
N=int(input())
Arr=[list(map(str,input()))for y in range(N)]
Que,Map,R=[],[[[999]*4for __ in range(N)] for _ in range(N)],987654321
for i in range(N):
    for j in range(N):
        if Arr[i][j]=='#':
            for d in range(4):
                y,x=i+dy[d],j+dx[d]
                if IS(y,x) and Arr[y][x]!='*':
                    Que.append((i,j,d,0))
            Arr[i][j]='*'
            break
    if Que:break
while Que:
    Q=[]
    for q in Que:
        if Arr[q[0]][q[1]]=='#' and q[3]<R:R=q[3];continue
        Y,X,M=q[0]+dy[q[2]],q[1]+dx[q[2]],q[3]
        if IS(Y,X) and Arr[Y][X]!='*':
            if Arr[Y][X]=='!':
                nM=M+1
                for d in [-1,1]:
                    nD=(q[2]+d)%4
                    if Map[Y][X][nD]<=nM:continue
                    Map[Y][X][nD]=nM
                    Q.append((Y,X,nD,nM))
            if Map[Y][X][q[2]]<=M:continue
            Map[Y][X][q[2]]=M
            Q.append((Y,X,q[2],M))
    Que=Q
if R==987654321:print(-1)
else:print(R)