import sys
if sys.version_info < (3, 0):
    sys.stderr.write("""\
ERROR: ScratchABit requires Python 3.3 or higher. You are running it with
following Python version:
---
%s
---
Try running it as 'python3 %s' and/or install suitable version.

""" % (sys.version, sys.argv[0]))
    sys.exit(1)

import os
import os.path
import time
import re
import string
import binascii
import logging as log
import argparse

from scratchabit import engine
import idaapi

from picotui.widgets import *
from picotui import editorext as editor
from picotui.screen import Screen
from picotui.editorext import Viewer
from picotui.menu import *
from picotui.dialogs import *

from scratchabit import utils
from scratchabit import help
from scratchabit import saveload
from scratchabit import actions
from scratchabit import uiprefs

HEIGHT = 21

MENU_PREFS = 2000
MENU_PLUGIN = 2001
MENU_ADD_TO_FUNC = 2002
MENU_WRITE_ALL_HTML = 2003

class AppClass:

    def set_show_bytes(self, show_bytes):
        self.show_bytes = show_bytes
        sz = 8 + 1
        if APP.show_bytes:
            sz += show_bytes * 2 + 1
        engine.DisasmObj.LEADER_SIZE = sz

APP = AppClass()

def disasm_one(p):
    insnsz = p.ana()
    p.out()
    print("%08x %s" % (p.cmd.ea, p.cmd.disasm))
    p.cmd.ea += p.cmd.size
    p.cmd.size = 0

class DisasmViewer(editor.EditorExt):

    def __init__(self, *args):
        super().__init__(*args)
        self.model = None
        self.addr_stack = []
        self.search_str = ""
        self.def_color = C_PAIR(C_CYAN, C_BLUE)

    def set_model(self, model):
        self.model = model
        self.set_lines(model.lines())
        # Invalidate top_line. Assuming goto_*() will be called
        # after set_model().
        self.top_line = sys.maxsize

    def show_line(self, l, i):
        show_bytes = APP.show_bytes
        res = l
        if not isinstance(l, str):
            res = "%08x " % l.ea
            if show_bytes > 0:
                bin = ""
                if not l.virtual:
                    b = self.model.AS.get_bytes(l.ea, l.size)
                    bin = str(binascii.hexlify(b[:show_bytes]), "ascii")
                    if l.size > show_bytes:
                        bin += "+"
                res += idaapi.fillstr(bin, show_bytes * 2 + 1)
            res += l.indent + l.render()

        COLOR_MAP = {
            engine.Label: C_PAIR(C_GREEN, C_BLUE),
            engine.AreaWrapper: C_PAIR(C_YELLOW, C_BLUE),
            engine.FunctionWrapper: C_PAIR(C_B_YELLOW, C_BLUE),
            engine.Xref: C_PAIR(C_MAGENTA, C_BLUE),
            engine.Unknown: C_PAIR(C_WHITE, C_BLUE),
            engine.Data: C_PAIR(C_MAGENTA, C_BLUE),
            engine.String: C_PAIR(C_B_MAGENTA, C_BLUE),
            engine.Fill: C_PAIR(C_B_BLUE, C_BLUE),
        }
        c = COLOR_MAP.get(type(l), self.def_color)
        self.attr_color(c)
        super().show_line(res, i)
        self.attr_reset()

    def handle_input(self, key):
        try:
            return super().handle_input(key)
        except Exception as ex:
            self.show_exception(ex)
            return None

    def goto_addr(self, to_addr, col=None, from_addr=None):
        if to_addr is None:
            self.show_status("No address-like value to go to")
            return
        subno = -1
        if isinstance(to_addr, tuple):
            to_addr, subno = to_addr
        adj_addr = self.model.AS.adjust_addr_reverse(to_addr)
        if adj_addr is None:
            self.show_status("Unknown address: 0x%x" % to_addr)
            return
        to_addr = adj_addr

        # If we can position cursor within current screen, do that,
        # to avoid jumpy UI
        no = self.model.addr2line_no(to_addr, subno)
        if no is not None:
            if self.line_visible(no):
                self.goto_line(no, col=col)
                if from_addr is not None:
                    self.addr_stack.append(from_addr)
                return

        # Otherwise, re-render model around needed address, and redraw screen
        t = time.time()
        model = engine.render_partial_around(to_addr, 0, HEIGHT * 2)
        self.show_status("Rendering time: %fs" % (time.time() - t))
        if not model:
            self.show_status("Unknown address: 0x%x" % to_addr)
            return
        self.set_model(model)

        no = self.model.addr2line_no(to_addr, subno)
        if no is not None:
            if from_addr is not None:
                self.addr_stack.append(from_addr)
            if not self.goto_line(no, col=col):
                # Need to redraw always, because we changed underlying model
                self.redraw()
        else:
            self.show_status("Unknown address: %x" % to_addr)

    def update_model(self, stay_on_real=False):
        """Re-render model and update screen in such way that cursor stayed
        on the same line (as far as possible).
        stay_on_real == False - try to stay on same relative line no. for
        the current address.
        stay_on_real == True - try to stay on the line which contains real
        bytes for the current address (use this if you know that cursor
        stayed on such line before the update).
        """
        addr, subno = self.cur_addr_subno()
        t = time.time()
        model = engine.render_partial_around(addr, subno, HEIGHT * 2)
        self.show_status("Rendering time: %fs" % (time.time() - t))
        self.set_model(model)
        if stay_on_real:
            self.cur_line = model.target_addr_lineno_real
        else:
            self.cur_line = model.target_addr_lineno
        self.top_line = self.cur_line - self.row
        #log.debug("update_model: addr=%x, row=%d, cur_line=%d, top_line=%d" % (addr, self.row, self.cur_line, self.top_line))
        self.redraw()

    def handle_cursor_keys(self, key):
        cl = self.cur_line
        if super().handle_cursor_keys(key):
            if self.cur_line == cl:
                return True
            #log.debug("handle_cursor_keys: cur: %d, total: %d", self.cur_line, self.total_lines)
            if self.cur_line <= HEIGHT or self.total_lines - self.cur_line <= HEIGHT:
                log.debug("handle_cursor_keys: triggering update")
                self.update_model()

            return True
        else:
            return False

    def cur_addr(self):
        line = self.get_cur_line()
        return line.ea

    # Address of the next line. It may be the same address as the
    # current line, as several lines may "belong" to the same address,
    # (virtual lines like headers, etc.)
    def next_line_addr_subno(self):
        try:
            l = self.content[self.cur_line + 1]
            return (l.ea, l.subno)
        except:
            return None

    # Return next address following the current line. May need to skip
    # few virtual lines.
    def next_addr(self):
        addr = self.cur_addr()
        n = self.cur_line + 1
        try:
            while self.content[n].ea == addr:
                n += 1
            return self.content[n].ea
        except:
            return None

    def cur_addr_subno(self):
        line = self.get_cur_line()
        return (line.ea, line.subno)

    def cur_operand_no(self, line):
        col = self.col - engine.DisasmObj.LEADER_SIZE - len(line.indent)
        #self.show_status("Enter pressed: %s, %s" % (col, line))
        for i, pos in enumerate(line.arg_pos):
            if pos[0] <= col <= pos[1]:
                return i
        return -1

    def analyze_status(self, cnt):
        self.show_status("Analyzing (%d insts so far)" % cnt)

    def expect_flags(self, fl, allowed_flags):
        if fl not in allowed_flags:
            self.show_status("Undefine first (u key)")
            return False
        return True

    def show_exception(self, e):
        log.exception("Exception processing user command")
        L = 3
        T = 2
        W = 74
        H = 20
        self.dialog_box(L, T, W, H)
        v = Viewer(L + 1, T + 1, W - 2, H - 2)
        import traceback
        v.set_lines([
            "Exception occurred processing the command. Press Esc to continue.",
            "Recommended action is saving database, quitting and comparing",
            "database files with backup copies for possibility of data loss",
            "or corruption. The exception was also logged to scratchabit.log.",
            "Please report way to reproduce it to",
            "https://github.com/pfalcon/ScratchABit/issues",
            "",
        ] + traceback.format_exc().splitlines())
        v.loop()
        self.redraw()

    def resolve_expr(self, expr):
        if expr:
            if expr[0].isdigit():
                return int(expr, 0)
            else:
                words = expr.split("+", 1)
                addend = 0
                if len(words) > 1:
                    try:
                        addend = int(words[1], 0)
                    except:
                        pass
                to_addr = self.model.AS.resolve_label(words[0])
                if to_addr is None:
                    return
                return to_addr + addend

    def require_non_func(self, fl):
        if fl & ~(self.model.AS.FUNC | self.model.AS.ALT_CODE) != self.model.AS.CODE:
            self.show_status("Code required")
            return False
        if fl & self.model.AS.FUNC:
            self.show_status("Already a function")
            return False
        return True

    #
    # UI action handlers
    #

    def action_goto(self):
        d = Dialog(4, 4, title="Go to")
        d.add(1, 1, WLabel("Label/addr:"))
        entry = WAutoComplete(20, "", self.model.AS.get_label_list())
        entry.popup_h = 12
        entry.finish_dialog = ACTION_OK
        d.add(13, 1, entry)
        d.add(1, 2, WLabel("Press Down to auto-complete"))
        res = d.loop()
        self.redraw()

        if res == ACTION_OK:
            value = entry.get()
            if '0' <= value[0] <= '9':
                addr = int(value, 0)
            else:
                addr = self.model.AS.resolve_label(value)
            self.goto_addr(addr, from_addr=self.cur_addr())

    def action_make_ascii(self):
        addr = self.cur_addr()
        fl = self.model.AS.get_flags(addr)
        if not self.expect_flags(fl, (self.model.AS.DATA, self.model.AS.UNK)):
            return
        sz = 0
        label = "s_"
        while True:
            b = self.model.AS.get_byte(addr)
            fl = self.model.AS.get_flags(addr)
            if not (0x20 <= b <= 0x7e or b in (0x0a, 0x0d)):
                if b == 0:
                    sz += 1
                break
            if fl not in (self.model.AS.UNK, self.model.AS.DATA, self.model.AS.DATA_CONT):
                break
            c = chr(b)
            if c < '0' or c in string.punctuation:
                c = '_'
            label += c
            addr += 1
            sz += 1
        if sz > 0:
            self.model.AS.set_flags(self.cur_addr(), sz, self.model.AS.STR, self.model.AS.DATA_CONT)
            self.model.AS.make_unique_label(self.cur_addr(), label)
            self.update_model()

    def handle_edit_key(self, key):
        if key in ACTION_MAP:
            return ACTION_MAP[key](self)

        line = self.get_cur_line()
        if key == editor.KEY_ENTER:
            line = self.get_cur_line()
            log.info("Enter pressed: %s" % line)
            op_no = self.cur_operand_no(line)
            self.show_status("Enter pressed: %s, %s" % (self.col, op_no))
            to_addr = None
            # No longer try to jump only to addresses in args, parse
            # textual representation below
            if False and isinstance(line, engine.DisasmObj):
                if op_no >= 0:
                    o = line[op_no]
                    to_addr = o.get_addr()
                if to_addr is None:
                    o = line.get_operand_addr()
                    if o:
                        to_addr = o.get_addr()
            if to_addr is None:
                pos = self.col - line.LEADER_SIZE - len(line.indent)
                word = utils.get_word_at_pos(line.cache, pos)
                self.show_status("Enter pressed: %s, %s, %s" % (self.col, op_no, word))
                to_addr = self.resolve_expr(word)
                if to_addr is None:
                    self.show_status("Unknown address: %s" % word)
                    return
            self.goto_addr(to_addr, from_addr=self.cur_addr_subno())
        elif key == editor.KEY_ESC:
            if self.addr_stack:
                self.show_status("Returning")
                self.goto_addr(self.addr_stack.pop())
        elif key == b"q":
            res = ACTION_OK
            if self.model.AS.changed:
                res = DConfirmation("There're unsaved changes. Quit?").result()
            if res == ACTION_OK:
                return editor.KEY_QUIT
            self.redraw()
        elif key == b"\x1b[5;5~":  # Ctrl+PgUp
            self.goto_addr(self.model.AS.min_addr(), from_addr=line.ea)
        elif key == b"\x1b[6;5~":  # Ctrl+PgDn
            self.goto_addr(self.model.AS.max_addr(), from_addr=line.ea)
        elif key == b"c":
            addr = self.cur_addr()
            self.show_status("Analyzing at %x" % addr)
            engine.add_entrypoint(addr, False)
            engine.analyze(self.analyze_status)
            self.update_model()

        elif key == b"C":
            addr = self.cur_addr()
            self.show_status("Analyzing at %x" % addr)
            self.model.AS.make_alt_code(addr)
            engine.add_entrypoint(addr, False)
            engine.analyze(self.analyze_status)
            self.update_model()

        elif key == b"F":
            addr = self.cur_addr()
            fl = self.model.AS.get_flags(addr, 0xff)
            if not self.require_non_func(fl):
                return
            self.show_status("Retracing as a function...")
            self.model.AS.make_label("fun_", addr)
            engine.add_entrypoint(addr, True)
            engine.analyze(self.analyze_status)
            self.update_model()
            self.show_status("Retraced as a function")

        elif key == MENU_ADD_TO_FUNC:
            addr = self.cur_addr()
            if actions.add_code_to_func(APP, addr):
                self.update_model()

        elif key == b"d":
            addr = self.cur_addr()
            fl = self.model.AS.get_flags(addr)
            if not self.expect_flags(fl, (self.model.AS.DATA, self.model.AS.UNK)):
                return
            if fl == self.model.AS.UNK:
                self.model.AS.set_flags(addr, 1, self.model.AS.DATA, self.model.AS.DATA_CONT)
            else:
                sz = self.model.AS.get_unit_size(addr)
                self.model.undefine_unit(addr)
                sz *= 2
                if sz > 4: sz = 1
                self.model.AS.set_flags(addr, sz, self.model.AS.DATA, self.model.AS.DATA_CONT)
            self.update_model()
        elif key == b"f":
            addr = self.cur_addr()
            fl = self.model.AS.get_flags(addr)
            if not self.expect_flags(fl, (self.model.AS.UNK,)):
                return

            off, area = self.model.AS.addr2area(self.cur_addr())
            # Don't cross area boundaries with filler
            remaining = area[engine.END] - addr + 1
            sz = 0
            while remaining:
                try:
                    fl = self.model.AS.get_flags(addr)
                except engine.InvalidAddrException:
                    break
                if fl != self.model.AS.UNK:
                    break
                b = self.model.AS.get_byte(addr)
                if b not in (0, 0xff):
                    self.show_status("Filler must consist of 0x00 or 0xff")
                    return
                sz += 1
                addr += 1
                remaining -= 1
            if sz > 0:
                self.model.AS.make_filler(self.cur_addr(), sz)
                self.update_model()

        elif key == b"u":
            addr = self.cur_addr()
            self.model.undefine_unit(addr)
            self.update_model()

        elif key == b"h":
            op_no = self.cur_operand_no(self.get_cur_line())
            if op_no >= 0:
                addr = self.cur_addr()
                subtype = self.model.AS.get_arg_prop(addr, op_no, "subtype")
                if subtype != engine.IMM_ADDR:
                    next_subtype = {
                        engine.IMM_UHEX: engine.IMM_UDEC,
                        engine.IMM_UDEC: engine.IMM_UHEX,
                    }
                    self.model.AS.set_arg_prop(addr, op_no, "subtype", next_subtype[subtype])
                    self.redraw()
                    self.show_status("Changed arg #%d to %s" % (op_no, next_subtype[subtype]))
        elif key == b"o":
            addr = self.cur_addr()
            line = self.get_cur_line()
            o = line.get_operand_addr()
            if not o:
                self.show_status("Cannot convert operand to offset")
                return
            if o.type != idaapi.o_imm or not self.model.AS.is_valid_addr(o.get_addr()):
                self.show_status("Cannot convert operand to offset: #%s: %s" % (o.n, o.type))
                return

            if self.model.AS.get_arg_prop(addr, o.n, "subtype") == engine.IMM_ADDR:
                self.model.AS.unmake_arg_offset(addr, o.n, o.get_addr())
            else:
                self.model.AS.make_arg_offset(addr, o.n, o.get_addr())
            self.update_model(True)
        elif key == b";":
            addr = self.cur_addr()
            comment = self.model.AS.get_comment(addr) or ""
            res = DMultiEntry(60, 5, comment.split("\n"), title="Comment:").result()
            if res != ACTION_CANCEL:
                res = "\n".join(res).rstrip("\n")
                self.model.AS.set_comment(addr, res)
                self.update_model()
            else:
                self.redraw()
        elif key == b"n":
            addr = self.cur_addr()
            label = self.model.AS.get_label(addr)
            def_label = self.model.AS.get_default_label(addr)
            s = label or def_label
            while True:
                res = DTextEntry(30, s, title="New label:").result()
                if not res:
                    break
                if res == def_label:
                    res = addr
                else:
                    if self.model.AS.label_exists(res):
                        s = res
                        self.show_status("Duplicate label")
                        continue
                self.model.AS.set_label(addr, res)
                if not label:
                    # If it's new label, we need to add it to model
                    self.update_model()
                    return
                break
            self.redraw()

        elif key == editor.KEY_F1:
            help.help(self)
            self.redraw()
        elif key == b"S":
            self.show_status("Saving...")
            timer = time.time()
            saveload.save_state(project_dir)
            timer = time.time() - timer
            log.info("Saved database in %fs", timer)
            self.model.AS.changed = False
            self.show_status("Saved in %fs" % timer)
        elif key == b"\x11":  # ^Q
            class IssueList(WListBox):
                def render_line(self, l):
                    return "%08x %s" % l
            d = Dialog(4, 4, title="Problems list")
            lw = IssueList(40, 16, self.model.AS.get_issues())
            lw.finish_dialog = ACTION_OK
            d.add(1, 1, lw)
            res = d.loop()
            self.redraw()
            if res == ACTION_OK:
                val = lw.get_cur_line()
                if val:
                    self.goto_addr(val[0], from_addr=self.cur_addr())

        elif key == b"i":
            off, area = self.model.AS.addr2area(self.cur_addr())
            props = area[engine.PROPS]
            percent = 100 * off / (area[engine.END] - area[engine.START] + 1)
            func = self.model.AS.lookup_func(self.cur_addr())
            func = self.model.AS.get_label(func.start) if func else None
            status = "Area: 0x%x %s (%s): %.1f%%, func: %s" % (
                area[engine.START], props.get("name", "noname"), props["access"], percent, func
            )
            subarea = self.model.AS.lookup_subarea(self.cur_addr())
            if subarea:
                status += ", subarea: " + subarea[2]
            self.show_status(status)
        elif key == b"I":
            from scratchabit import memmap
            addr = memmap.show(self.model.AS, self.cur_addr())
            if addr is not None:
                self.goto_addr(addr, from_addr=self.cur_addr())
            self.redraw()
        elif key == b"W":
            out_fname = "out.lst"
            actions.write_disasm_all(APP, out_fname, feedback_obj=self)
            self.show_status("Disassembly listing written: " + out_fname)
        elif key == MENU_WRITE_ALL_HTML:
            out_fname = "out.html"
            with open(out_fname, "w") as f:
                f.write("<pre>\n")
                m = actions.HTMLSaveModel(f, self)
                m.aspace = self.model.AS
                engine.render_partial(m, 0, 0, 10000000)
                f.write("</pre>\n")
            self.show_status("Disassembly HTML listing written: " + out_fname)
        elif key == b"\x17":  # Ctrl+W
            outfile = actions.write_func_by_addr(APP, self.cur_addr(), feedback_obj=self)
            if outfile:
                self.show_status("Wrote file: %s" % outfile)
        elif key == b"\x15":  # Ctrl+U
            # Next undefined
            addr = self.cur_addr()
            flags = self.model.AS.get_flags(addr)
            if flags == self.model.AS.UNK:
                # If already on undefined, skip the current stride of them,
                # as they indeed go in batches.
                while True:
                    flags = self.model.AS.get_flags(addr)
                    if flags != self.model.AS.UNK:
                        break
                    addr = self.model.AS.next_addr(addr)
                    if addr is None:
                        break

            if addr is not None:
                while True:
                    flags = self.model.AS.get_flags(addr)
                    if flags == self.model.AS.UNK:
                        self.goto_addr(addr, from_addr=self.cur_addr())
                        break
                    addr = self.model.AS.next_addr(addr)
                    if addr is None:
                        break

            if addr is None:
                self.show_status("There're no further undefined strides")

        elif key == b"\x06":  # Ctrl+F
            # Next non-function
            addr = self.cur_addr()
            flags = self.model.AS.get_flags(addr, ~ADDRESS_SPACE.ALT_CODE)
            if flags == self.model.AS.CODE:
                # If already on non-func code, skip the current stride of it,
                # as it indeed go in batches.
                while True:
                    flags = self.model.AS.get_flags(addr, ~ADDRESS_SPACE.ALT_CODE)
                    self.show_status("fl=%x" % flags)
                    if flags not in (self.model.AS.CODE, self.model.AS.CODE_CONT):
                        break
                    addr = self.model.AS.next_addr(addr)
                    if addr is None:
                        break

            if addr is not None:
                while True:
                    flags = self.model.AS.get_flags(addr, ~ADDRESS_SPACE.ALT_CODE)
                    if flags == self.model.AS.CODE:
                        self.goto_addr(addr, from_addr=self.cur_addr())
                        break
                    addr = self.model.AS.next_addr(addr)
                    if addr is None:
                        break

            if addr is None:
                self.show_status("There're no further non-function code strides")

        elif key in (b"/", b"?"):  # "/" and Shift+"/"

            class FoundException(Exception): pass

            class TextSearchModel(engine.Model):
                def __init__(self, substr, ctrl, this_addr, this_subno):
                    super().__init__()
                    self.search = substr
                    self.ctrl = ctrl
                    self.this_addr = this_addr
                    self.this_subno = this_subno
                    self.cnt = 0
                def add_object(self, addr, line):
                    super().add_object(addr, line)
                    # Skip virtual lines before the line from which we started
                    if addr == self.this_addr and line.subno < self.this_subno:
                        return
                    txt = line.render()
                    idx = txt.find(self.search)
                    if idx != -1:
                        raise FoundException((addr, line.subno), idx + line.LEADER_SIZE + len(line.indent))
                    if self.cnt % 256 == 0:
                        self.ctrl.show_status("Searching: 0x%x" % addr)
                    self.cnt += 1
                    # Don't accumulate lines
                    self._lines = []
                    self._addr2line = {}

            if key == b"/":
                d = Dialog(4, 4, title="Text Search")
                d.add(1, 1, WLabel("Search for:"))
                entry = WTextEntry(20, self.search_str)
                entry.finish_dialog = ACTION_OK
                d.add(13, 1, entry)
                res = d.loop()
                self.redraw()
                self.search_str = entry.get_text()
                if res != ACTION_OK or not self.search_str:
                    return
                addr, subno = self.cur_addr_subno()
            else:
                addr, subno = self.next_line_addr_subno()

            try:
                engine.render_from(TextSearchModel(self.search_str, self, addr, subno), addr, 10000000)
            except FoundException as res:
                self.goto_addr(res.args[0], col=res.args[1], from_addr=self.cur_addr())
            else:
                self.show_status("Not found: " + self.search_str)

        elif key == MENU_PREFS:
            uiprefs.handle(APP)

        elif key == MENU_PLUGIN:
            res = DTextEntry(30, "", title="Plugin module name:").result()
            self.redraw()
            if res:
                self.show_status("Running '%s' plugin..." % res)
                call_script(res)
                self.update_model()
                self.show_status("Plugin '%s' ran successfully" % res)
        else:
            self.show_status("Unbound key: " + repr(key))

ACTION_MAP = {
    b"g": DisasmViewer.action_goto,
    b"a": DisasmViewer.action_make_ascii,
}

CPU_PLUGIN = None
ENTRYPOINTS = []
APP.show_bytes = 4

def filter_config_line(l):
    l = re.sub(r"#.*$", "", l)
    l = l.strip()
    return l

def load_symbols(fname):
    with open(fname) as f:
        for l in f:
            l = filter_config_line(l)
            if not l:
                continue
            m = re.search(r"\b([A-Za-z_$.][A-Za-z0-9_$.]*)\s*=\s*((0x)?[0-9A-Fa-f]+)", l)
            if m:
                #print(m.groups())
                ENTRYPOINTS.append((m.group(1), int(m.group(2), 0)))
            else:
                print("Warning: cannot parse entrypoint info from: %r" % l)

# Allow undescores to separate digit groups
def str2int(s):
    return int(s.replace("_", ""), 0)

def parse_range(arg):
    # name start(len)
    # name start-end
    if "(" in arg:
        m = re.match(r"(.+?)\s*\(\s*(.+?)\s*\)", arg)
        start = str2int(m.group(1))
        end = start + str2int(m.group(2)) - 1
    else:
        m = re.match(r"(.+)\s*-\s*(.+)", arg)
        start = str2int(m.group(1))
        end = str2int(m.group(2))
    return start, end

def parse_entrypoints(f):
    for l in f:
        l = filter_config_line(l)
        if not l:
            continue
        if l[0] == "[":
            return l
        m = re.match(r'load "(.+?)"', l)
        if m:
            load_symbols(m.group(1))
        else:
            label, addr = [v.strip() for v in l.split("=")]
            ENTRYPOINTS.append((label, str2int(addr)))
    return ""

def parse_subareas(f):
    subareas = []
    for l in f:
        l = filter_config_line(l)
        if not l:
            continue
        if l[0] == "[":
            return l

        args = l.split()
        assert len(args) == 2
        start, end = parse_range(args[1])
        engine.ADDRESS_SPACE.add_subarea(start, end, args[0])
    engine.ADDRESS_SPACE.finish_subareas()
    return ""

def load_target_file(loader, fname):
    print("Loading %s..." % fname)
    timer = time.time()
    entry = loader.load(engine.ADDRESS_SPACE, fname)
    log.info("Loaded %s in %fs, entrypoint: %s", fname, time.time() - timer, hex(entry) if entry is not None else None)
    if entry is not None:
        ENTRYPOINTS.append(("_ENTRY_", entry))

def parse_disasm_def(fname):
    global CPU_PLUGIN
    with open(fname) as f:
        for l in f:
            l = filter_config_line(l)
            if not l:
                continue
            #print(l)
            while True:
                if not l:
                    #return
                    break
                if l[0] == "[":
                    section = l[1:-1]
                    print("Processing section: %s" % section)
                    if section == "entrypoints":
                        l = parse_entrypoints(f)
                    elif section == "subareas":
                        l = parse_subareas(f)
                    else:
                        assert 0, "Unknown section: " + section
                else:
                    break

            if not l:
                break

            if l.startswith("load"):
                args = l.split()
                if args[2][0] in string.digits:
                    addr = str2int(args[2])
                    print("Loading %s @0x%x" % (args[1], addr))
                    engine.ADDRESS_SPACE.load_content(open(args[1], "rb"), addr)
                else:
                    print("Loading %s (%s plugin)" % (args[1], args[2]))
                    loader = __import__(args[2])
                    load_target_file(loader, args[1])
            elif l.startswith("cpu "):
                args = l.split()
                CPU_PLUGIN = __import__(args[1])
                if hasattr(CPU_PLUGIN, "arch_id"):
                    engine.set_arch_id(CPU_PLUGIN.arch_id)
                print("Loading CPU plugin %s" % (args[1]))
            elif l.startswith("show bytes "):
                args = l.split()
                APP.show_bytes = int(args[2])
            elif l.startswith("area "):
                args = l.split()
                assert len(args) == 4
                start, end = parse_range(args[2])
                a = engine.ADDRESS_SPACE.add_area(start, end, {"name": args[1], "access": args[3].upper()})
                print("Adding area: %s" % engine.str_area(a))
            else:
                assert 0, "Unknown directive: " + l

class MainScreen:

    def __init__(self):
        self.screen_size = Screen.screen_size()
        self.e = DisasmViewer(1, 2, self.screen_size[0] - 2, self.screen_size[1] - 4)

        menu_file = WMenuBox([
            ("Save (Shift+s)", b"S"),
            ("Write disasm (Shift+w)", b"W"),
            ("Write disasm in HTML", MENU_WRITE_ALL_HTML),
            ("Write function (Ctrl+w)", b"\x17"),
            ("Quit (q)", b"q")
        ])
        menu_goto = WMenuBox([
            ("Follow (Enter)", KEY_ENTER), ("Return (Esc)", KEY_ESC),
            ("Goto... (g)", b"g"), ("Search disasm... (/)", b"/"),
            ("Search next (Shift+/)", b"?"), ("Next undefined (Ctrl+u)", b"\x15"),
            ("Next non-function code (Ctrl+f)", b"\x06"),
        ])
        menu_edit = WMenuBox([
            ("Undefined (u)", b"u"),
            ("Code (c)", b"c"),
            ("Alt code (Shift+c)", b"C"),
            ("Data (d)", b"d"),
            ("ASCII String (a)", b"a"), ("Filler (f)", b"f"), ("Make label (n)", b"n"),
            ("Mark function start (F)", b"F"), ("Add code to function", MENU_ADD_TO_FUNC),
            ("Number/Address (o)", b"o"), ("Hex/dec (h)", b"h"),
        ])
        menu_analysis = WMenuBox([
            ("Info (whereami) (i)", b"i"), ("Memory map (Shift+i)", b"I"),
            ("Issue list (Ctrl+q)", b"\x11"),
            ("Run plugin...", MENU_PLUGIN),
            ("Preferences...", MENU_PREFS),
        ])
        menu_help = WMenuBox([
            ("Help (F1)", KEY_F1), ("About...", "about"),
        ])
        self.menu_bar = WMenuBar([
            ("File", menu_file), ("Goto", menu_goto), ("Edit", menu_edit),
            ("Analysis", menu_analysis), ("Help", menu_help)
        ])
        self.menu_bar.permanent = True

    def redraw(self, allow_cursor=True):
        self.menu_bar.redraw()
        self.e.attr_color(C_B_WHITE, C_BLUE)
        self.e.draw_box(0, 1, self.screen_size[0], self.screen_size[1] - 2)
        self.e.attr_reset()
        self.e.redraw()
        if allow_cursor:
            self.e.cursor(True)

    def loop(self):
        while 1:
            key = self.e.get_input()
            if isinstance(key, list):
                x, y = key
                if self.menu_bar.inside(x, y):
                    self.menu_bar.focus = True

            if self.menu_bar.focus:
                res = self.menu_bar.handle_input(key)
                if res == ACTION_CANCEL:
                    self.menu_bar.focus = False
                elif res is not None and res is not True:

                    res = self.e.handle_input(res)
                    if res is not None and res is not True:
                        return res
            else:
                if key == KEY_F9:
                    self.menu_bar.focus = True
                    self.menu_bar.redraw()
                    continue

                res = self.e.handle_input(key)

                if res is not None and res is not True:
                    return res

def call_script(script, progress_func=None):
    mod = __import__(script)
    main_f = getattr(mod, "main", None)
    if main_f:
        main_f(APP)
    # A script might have queues some entrypoints, etc.
    # Analyze them now.
    engine.analyze(progress_func)

if __name__ == "__main__":

    argp = argparse.ArgumentParser(description="ScratchABit interactive disassembler")
    argp.add_argument("file", help="Input file (binary or disassembly .def)")
    argp.add_argument("--script", action="append", help="Run script from file after loading environment")
    argp.add_argument("--save", action="store_true", help="Save DB after --script and quit; don't show UI")
    args = argp.parse_args()

    # Plugin dirs are relative to the dir where scratchabit.py resides.
    # sys.path[0] below provide absolute path of this dir, resolved for
    # symlinks.
    plugin_dirs = ["plugins", "plugins/cpu", "plugins/loader"]
    for d in plugin_dirs:
        sys.path.append(os.path.join(sys.path[0], d))
    log.basicConfig(filename="scratchabit.log", format='%(asctime)s %(message)s', level=log.DEBUG)
    log.info("=" * 30 + " Started " + "=" * 30)

    if args.file.endswith(".def"):
        parse_disasm_def(args.file)
        project_name = args.file.rsplit(".", 1)[0]
    else:
        import default_plugins
        for loader_id in default_plugins.loaders:
            loader = __import__(loader_id)
            arch_id = loader.detect(args.file)
            if arch_id:
                break
        if not arch_id:
            print("Error: file '%s' not recognized by default loaders" % args.file)
            sys.exit(1)
        if arch_id not in default_plugins.cpus:
            print("Error: no plugin for CPU '%s' as detected for file '%s'" % (arch_id, args.file))
            sys.exit(1)

        engine.set_arch_id(arch_id)
        load_target_file(loader, args.file)
        CPU_PLUGIN = __import__(default_plugins.cpus[arch_id])
        project_name = args.file

    p = CPU_PLUGIN.PROCESSOR_ENTRY()
    if hasattr(p, "config"):
        p.config()
    engine.set_processor(p)
    if hasattr(p, "help_text"):
        help.set_cpu_help(p.help_text)
    APP.cpu_plugin = p
    APP.aspace = engine.ADDRESS_SPACE
    APP.is_ui = False
    engine.ADDRESS_SPACE.is_loading = True

    # Calc various offset based on show_bytes value
    APP.set_show_bytes(APP.show_bytes)

    # Strip suffix if any from def filename
    project_dir = project_name + ".scratchabit"

    if saveload.save_exists(project_dir):
        timer = time.time()
        saveload.load_state(project_dir)
        log.info("Loaded database in %fs", time.time() - timer)
    else:
        timer = time.time()
        for label, addr in ENTRYPOINTS:
            if engine.arch_id == "arm_32" and addr & 1:
                addr &= ~1
                engine.ADDRESS_SPACE.make_alt_code(addr)
            if engine.ADDRESS_SPACE.is_exec(addr):
                engine.add_entrypoint(addr)
            engine.ADDRESS_SPACE.make_unique_label(addr, label)
        def _progress(cnt):
            sys.stdout.write("Performing initial analysis... %d\r" % cnt)
        engine.analyze(_progress)
        log.info("Performed initial analysis in %fs", time.time() - timer)
        print()

    #engine.print_address_map()

    if args.script:
        def _progress(cnt):
            sys.stdout.write("Performing analysis after running script(s)... %d\r" % cnt)
        for script in args.script:
            call_script(script, _progress)

    if args.save:
        saveload.save_state(project_dir)
        sys.exit()

    addr_stack = []
    show_addr = None
    if os.path.exists(project_dir + "/session.addr_stack"):
        addr_stack = saveload.load_addr_stack(project_dir)
        if addr_stack:
            show_addr = addr_stack.pop()
            log.info("Loaded saved address stack, last address: 0x%x", show_addr)
    if show_addr is None:
        if ENTRYPOINTS:
            show_addr = ENTRYPOINTS[0][1]
            if engine.arch_id == "arm_32":
                 show_addr &= ~1
        else:
            show_addr = engine.ADDRESS_SPACE.min_addr()

    log.info("Starting UI")

    t = time.time()
    #_model = engine.render()
    _model = engine.render_partial_around(show_addr, 0, HEIGHT * 2)
    print("Rendering time: %fs" % (time.time() - t))
    #print(_model.lines())
    #sys.exit()

    engine.ADDRESS_SPACE.is_loading = False
    engine.ADDRESS_SPACE.changed = False
    Screen.init_tty()
    try:
        Screen.cls()
        Screen.enable_mouse()
        main_screen = MainScreen()
        APP.main_screen = main_screen
        APP.is_ui = True
        main_screen.e.set_model(_model)
        main_screen.e.addr_stack = addr_stack
        main_screen.e.goto_addr(show_addr)
        Screen.set_screen_redraw(main_screen.redraw)
        main_screen.redraw()
        main_screen.e.show_status("Press F1 for help, F9 for menus")
        main_screen.loop()
    except:
        log.exception("Unhandled exception")
        raise
    finally:
        Screen.goto(0, main_screen.screen_size[1])
        Screen.cursor(True)
        Screen.disable_mouse()
        Screen.deinit_tty()
        Screen.wr("\n\n")
        saveload.save_session(project_dir, main_screen.e)


"""
news_source_international.py: Scraping functions for the most read International News Sources

__author__ = "Fernando P. Lopes"
__email__ = "fpedrosa@gmail.com"

"""
from app.aml_utils import getpage, parsepage, get_ns

def __fox(soup):
    """
   Gets the most read news from the Fox News page
   :param soup: the BeautifulSoup object
   :return: a list with the most read news from the Fox News page
   """
    # DEPRECATED due to removal of Most read news section
    news = []
    anchors = soup.find('section', id='trending').find('ol').find_all('a')

    for a in anchors:
        title = a.string
        link = a['href']
        news.append(dict(title=title, link=link))
    return news

def __wp(soup):
    """
   Gets the most read news from the Washington Post page
   :param soup: the BeautifulSoup object
   :return: a list with the most read news from the Washington Post page
   """
    news = []
    anchors = soup.find('div', id='post-most-rr').find_all('a')

    for a in anchors:
        link = a['href']
        title = a.find('div', class_='headline').text
        news.append(dict(title=title, link=link))
    return news

def __tg(soup):
    """
   Gets the most read news from the The Guardian page
   :param soup: the BeautifulSoup object
   :return: a list with the most read news from the The Guardian page
   """
    news = []
    anchors = soup.find('div', id='tabs-popular-1').find_all('a')

    for a in anchors:
        link = a['href']
        title = a.text
        news.append(dict(title=title, link=link))
    return news

def __lf(soup):
    """
   Gets the most read news from the Le Figaro page
   :param soup: the BeautifulSoup object
   :return: a list with the most read news from the Le Figaro page
   """
    news = []
    anchors = soup.find('div', class_='fig-toparticles__main').find_all('a')

    for a in anchors:
        link = a['href']
        title = a.text
        news.append(dict(title=title, link=link))
    return news

def __tt(soup):
    """
   Gets the most read news from The Telegraph page
   :param soup: the BeautifulSoup object
   :return: a list with the most read news from the The Telegraph page
   """
    # DEPRECATED - Can't access source code due to script
    news = []
    ns = get_ns('tt')

    headers = soup.find('ol', class_='js-list-of-entities__container list-of-entities__container tmg-particle-most-read-carousel__list')\
        .find_all('h3', class_='list-of-entities__item-body-headline')

    for h in headers:
        a = h.find('a')
        link = ns.url + a['href']
        title = a.text
        news.append(dict(title=title, link=link))
    return news

def __ep(soup):
    """
   Gets the most read news from El País page
   :param soup: the BeautifulSoup object
   :return: a list with the most read news from the El País page
   """
    news = []
    anchors = soup.find('div', id='lmv_todo').find_all('a')

    for a in anchors:
        link = a['href']
        # noinspection PyUnusedLocal
        title = 'not-found'

        # Sometimes the item has a Span element (Video icon), sometimes it doesn't
        span = a.find('span')
        if span is None:
            title = a.string
        else:
            title = span.next_sibling.string

        news.append(dict(title=title, link=link))
    return news

def __reu(soup):
    """
   Gets the most read news from Reuters page
   :param soup: the BeautifulSoup object
   :return: a list with the most read news from Reuters page
   """
    news = []

    div = soup.find('div', class_='news-headline-list medium')
    h3s = div.find_all('h3', class_='story-title')

    for h in h3s:
        link = 'http://www.reuters.com' + h.parent['href']
        title = h.string
        news.append(dict(title=title, link=link))
    return news

def __ny(soup):
    """
    DEPRECATED
   Gets the most read news from NY Times page
   :param soup: the BeautifulSoup object
   :return: a list with the most read news from the NY Times page
   """
    news = []
    divs = soup.find_all('div', class_='story')

    for d in divs[:10]:
        link = d.h3.a['href']
        title = d.h3.a.string

        news.append(dict(title=title, link=link))
    return news

# Strategy Pattern - a dictionary of functions. Key: the name of the News Source. Value: the Function to execute
strategies = dict(fox=__fox, wp=__wp, tg=__tg, lf=__lf, tt=__tt, ep=__ep, ny=__ny, reu=__reu)

def get_most_read(key):
    """
    Gets the most read news from a given page

    :param key: the key of the source page (e.g: g1)
    :return: a list with the most read news from the page and the name of news source
    """
    ns = get_ns(key)
    response, content = getpage(ns.url)  # Download the page
    soup = parsepage(content)  # Then we parse it
    strategy = strategies[key]  # Then we execute the selected Strategy based on the source
    return strategy(soup), ns.name


import torch
import torch.nn as nn
from mmcv.cnn import ConvModule

from enseg.ops import resize
from enseg.models.builder import DECODE_SEG
from enseg.models.decode_gen.base import BaseGen
from enseg.models.decode_seg.psp_head import PPM

@DECODE_SEG.register_module()
class BackGen(BaseGen):
    """
    输入是seg头的输出特征。一般分割头的处理过程为:feature->high dimension feature(BFHW)->seg logits(BCHW)
    我们取高维特征BFHW, 以及输入原始图像，进行图像翻译
    对于3*256*512图像:
    高维特征512*64*128
    原始图像3*256*512
    3*256*512+++++++++++++++++++++++++++++++|->3*256*512
        |->64*128*256++++++++++++++++++|->64*128*256
            |->128*64*128+512*64*128->128*64*128

    """

    def __init__(
        self, base_dim=64, seg_dim=512, act_cfg=dict(type="LeakyReLU"), **kwargs
    ):
        super(BackGen, self).__init__(
            act_cfg=act_cfg, in_channels=[], in_index=[], channels=1, **kwargs
        )
        self.down_layers = nn.ModuleList()
        self.downdeal_layers = nn.ModuleList()
        self.up_layers = nn.ModuleList()
        self.updeal_layers = nn.ModuleList()
        norm_act_cfg = dict(norm_cfg=self.norm_cfg, act_cfg=self.act_cfg,)
        cur_dim = base_dim
        channels = [
            (3, base_dim),
            (base_dim, base_dim * 2),
        ]
        for depth, channel in enumerate(channels):
            in_ch, out_ch = channel
            downdeal_layer = nn.Sequential(
                ConvModule(in_ch, out_ch // 2, 3, 1, 1, **norm_act_cfg),
                ConvModule(out_ch // 2, out_ch, 3, 1, 1, **norm_act_cfg),
            )
            down_layer = ConvModule(out_ch, out_ch, 4, 2, 1, **norm_act_cfg)
            in_ch = out_ch
            out_ch += out_ch
            self.downdeal_layers.append(downdeal_layer)
            self.down_layers.append(down_layer)
        self.neck = nn.Sequential(
            ConvModule(channels[-1][-1], seg_dim // 2, 3, 1, 1, **norm_act_cfg),
            ConvModule(seg_dim // 2, seg_dim, 3, 1, 1, **norm_act_cfg),
        )
        channels = [
            (seg_dim + seg_dim, base_dim*2),
            (base_dim*2+base_dim*2, base_dim),
            (base_dim + base_dim, base_dim),
        ]
        for depth, channel in enumerate(channels):
            in_ch, out_ch = channel
            updeal_layer = nn.Sequential(
                ConvModule(in_ch, in_ch // 2, 3, 1, 1, **norm_act_cfg),
                ConvModule(in_ch // 2, out_ch, 3, 1, 1, **norm_act_cfg),
            )
            up_layer = ConvModule(
                out_ch, out_ch, 4, 2, 1, **norm_act_cfg, conv_cfg=dict(type="deconv")
            )
            in_ch = out_ch
            out_ch += out_ch
            self.updeal_layers.append(updeal_layer)
            self.up_layers.append(up_layer)
        self.output = nn.Sequential(
            ConvModule(base_dim, base_dim, 7, 1, 3, **norm_act_cfg),
            ConvModule(base_dim, 3, 1, 1, norm_cfg=None, act_cfg=dict(type="Tanh")),
        )

    def forward_model(self, inputs, origin_img):
        """Forward function."""

        seg_feature = inputs
        img = origin_img
        x = img
        downdeal_features = []
        for down_layer, downdeal_layer in zip(self.down_layers, self.downdeal_layers):
            x = downdeal_layer(x)
            downdeal_features.append(x)
            x = down_layer(x)
        x = self.neck(x)
        downdeal_features.append(seg_feature)
        for up_layer, updeal_layer in zip(self.up_layers, self.updeal_layers):
            x = torch.cat([x, downdeal_features.pop()], 1)
            x = updeal_layer(x)
            x = up_layer(x)
        x = self.output(x)
        return x

if __name__ == "__main__":
    BackGen()


# -*- coding: utf-8 -*-

from __future__ import absolute_import

from vilya.libs.template import st
from vilya.models.project import CodeDoubanProject

_q_exports = []

class SettingsConfUI:
    _q_exports = []

    def __init__(self, proj_name):
        self.proj_name = proj_name

    def _q_index(self, request):
        user = request.user
        tdt = {
            'user': user,
            'project': CodeDoubanProject.get_by_name(self.proj_name),
            'request': request,
        }
        return st('settings/config.html', **tdt)


from behave import *
import requests
import configparser

@given('the book details are given')
def stepimpl(context):

    context.config = configparser.ConfigParser()
    context.config.read('Utilities/properties.ini')
    # print(type(config))

@when('Add Book API is executed')
def step_impl(context):
    postresp = requests.post(context.config['API']['baseUrl']+'/Library/Addbook.php', json=datatransfer(6306096),
                             headers={'Content-Type': 'application/json'})
    assert postresp.status_code == 200
    context.postresp_json = postresp.json()

@then('book is successfully added')
def step_impl(context):
    assert context.postresp_json['Msg'] == "successfully added"


import classes
import hand_rank
import random

def restore_deck(deck, drawn_cards):
	for card in drawn_cards:
		deck.cards.append(card)
	deck.shuffle()

def simulate_hands(hand, communal_cards, deck, num_simulations):
	result = 0.0
	for _ in range(num_simulations):
		sample_cards = deck.draw(num_cards = 2)
		sample_hand = classes.Hand(sample_cards[0], sample_cards[1])
		additional_communal_cards = deck.draw(num_cards = 5 - len(communal_cards))
		final_communal_cards = communal_cards + additional_communal_cards
		sample_hand_rank = hand_rank.get_rank(sample_hand.read_as_list() + final_communal_cards)
		this_hand_rank = hand_rank.get_rank(hand.read_as_list() + final_communal_cards)
		comparison = hand_rank.Rank.compare_ranks(this_hand_rank, sample_hand_rank)
		if comparison == 1:
			result += 1
		elif comparison == 0:
			result += 0.5

		restore_deck(deck, sample_cards + additional_communal_cards)

	return result


#!/usr/bin/python3
"""
 Sends a POST request to the passed URL with the email as
 a parameter, and displays the body of the response
"""

import urllib.request
from sys import argv

if __name__ == "__main__":
    try:
        with urllib.request.urlopen(argv[1]) as response:
            html = response.read().decode('utf-8')
            print(html)
    except urllib.error.HTTPError as error:
        print("Error code: {}".format(error.code))


"""
Part II: Take the data we just parsed and visualize it using
Python math libraries.
"""
from collections import Counter

import csv
import matplotlib.pyplot as plt
import numpy as np
import Parse

MY_FILE = "../data/sample_sfpd_incident_all.csv"

def visualize_days():
    """Visualize data by the day of week"""

    # get the parsed data from Parse.py
    data_file = Parse.parse(MY_FILE, ",")

    # variable counter iterates through each line
    # of data in parsed data, and counts how many
    # incidents occured in each day of the week
    counter = Counter(item["DayOfWeek"] for item in data_file)

    # seperate the counter to order it when plotting
    # dicionaries do no preserve order but lists do
    data_list = [
                 counter["Monday"],
                 counter["Tuesday"],
                 counter["Wednesday"],
                 counter["Thursday"],
                 counter["Friday"],
                 counter["Saturday"],
                 counter["Sunday"]
                 ]
    # plt.xticks() only accepts tuples for labeling x-axis
    day_tuple = tuple(["Mon", "Tues", "Wed", "Thurs", "Fri", "Sat", "Sun"])

    # assign the y-axis data to a matplotlib plot instance
    plt.plot(data_list)

    # assigning labels to the plot
    plt.xticks(range(len(day_tuple)), day_tuple)

    # save the plot
    plt.savefig("Days.png")
    #close figure
    plt.clf()

def visualize_type():
    """Visualize data by category in a bar graph"""

    # get parsed data
    data_file = Parse.parse(MY_FILE, ",")

    # returns a dict with the sum of the total incidents per Category
    counter = Counter(item["Category"] for item in data_file)

    # set labels based on the keys of counter
    # order does not matter
    labels = tuple(counter.keys())

    # set where the labels hit the x-axis
    xlocations = np.array(range(len(labels))) +0.5

    # width of each bar
    width = 0.5

    # assign data to a bar plot
    plt.bar(xlocations, counter.values(), width=width)

    # assign labels and tick locations to x-axis
    plt.xticks(xlocations + width / 2, labels, rotation=90)

    # provide spacing to prevent labels being cut off on graph
    plt.subplots_adjust(bottom=0.4)

    # create graph size
    plt.rcParams['figure.figsize'] = 12, 8

    #save the plot
    plt.savefig("Type.png")
    # close figure
    plt.clf()

def main():
    visualize_days()
    visualize_type()

if __name__ == "__main__":
    main()


import random

n = int(input("Enter N: "))
a = int(input("Enter A: "))
b = int(input("Enter B: "))

input_file_name = input("Enter output test file name: ")

f = open(input_file_name, "w")
f.write(str(n) + " " + str(a) + " " + str(b) + "\n")

sword_choices = ['NS', 'S']
time_choices = list(range(1, 1000000000))

chosen_times = []

for i in range(n):
    sword_choice = random.choice(sword_choices)
    time_choice = random.choice(time_choices)
    while time_choice in chosen_times:
        time_choices.pop(time_choices.index(time_choice))
        time_choice = random.choice(time_choices)
    if time_choice not in chosen_times:
        chosen_times.append(time_choice)
        f.write(sword_choice + " " + str(time_choice) + "\n")

f.close()


sample_dict= {'A':'Hello', 'B': 'World', 'C': 'Buddy'}

def get_output(dic, expresion):
    res = ""
    if " and " in expresion:
        element = expresion.split(" and ")
        for i in element:
            if dic.get(i):
                res += dic.get(i)
            else:
                continue
        return res

    elif " or " in expresion:
        aaa = expresion.split(" or ")
        for i in aaa:
            if dic.get(i):
                return dic.get(i)

def get_op(dic, expresion):
    if "(" and ")" in expresion:
        res = ""
        start, stop = expresion.find("("), expresion.find(")")
        if " and " or " or " in expresion[:start]:
            if " and " in expresion[:start]:
                element = expresion.split(" and ", 1)
                res += dic[element[0]]
                returned = get_output(dic, element[1][1:-1])
                res += returned
                return res

            elif " or " in expresion[:start]:
                element = expresion.split(" or ", 1)
                if dic.get(element[0]):
                        res += dic.get(element[0])
                        returned = get_output(dic, element[1][1:-1])
                        res += returned
                        return res
    else:
        res = get_output(dic, expresion)
        return res

sample_expresion = input("Please provide an expression to evaluate: ")
print(get_op(sample_dict, sample_expresion))


#!/usr/bin/env python

# /boot/config.txt needs this:
# dtoverlay=w1-gpio-pullup,gpiopin=4,extpullup=5,pullup=on

import os

sensors = []
for dirname, dirnames, filenames in os.walk('/sys/bus/w1/devices/'):
    # print path to all subdirectories first.
    for subdirname in dirnames:
        temppath = os.path.join(dirname, subdirname)
        if "28-" in temppath:
                sensors.append(temppath) # push
#               print temppath

    # Advanced usage:
    # editing the 'dirnames' list will stop os.walk() from recursing into there.
#    if '28-' in dirnames:
#        print "found a sensor"

#print "should probe these sensors"

for sensor in sensors:
        print (sensor)


import sqlite3

cx = sqlite3.connect('banco.db')  # sera criado um arquivo banco.db

cursor = cx.cursor() # cursor

              # Criando tabela
                # Aqui criamos os comandos sql
cursor.execute('''CREATE TABLE cliente
               id INT PRIMARY KEY AUTOINCREMENT NOT NULL,
               nome TEXT NOT NULL,
               idade INT NOT NULL,
               ''')

cursor.execute(''' INSERT INTO banco (id)''')
cx.commit()


# -*- encoding: utf-8 -*-
'''
@project :   LeetCode
@File    :   largestNumber.py
@Contact :   9824373@qq.com
@Desc    :
            给定一组非负整数，重新排列它们的顺序使之组成一个最大的整数。

            示例 1:

            输入: [10,2]
            输出: 210
            示例 2:

            输入: [3,30,34,5,9]
            输出: 9534330
            说明: 输出结果可能非常大，所以你需要返回一个字符串而不是整数。

            来源：力扣（LeetCode）
            链接：https://leetcode-cn.com/problems/largest-number
@Modify Time                @Author     @Version    @Desciption
------------                -------     --------    -----------
2020-03-03     zhan        1.0         None
'''
from typing import List
import functools

class Solution:
    def cmp(self,a,b):
        if str(a) + str(b) >str(b) + str(a):
            return -1
        else:
            return 1

    def largestNumber(self, nums: List[int]) -> str:
        if len(nums) == 0: return  '0'
        if len(nums) == 1: return  str(nums[0])

        for i, num in enumerate(nums):
            nums[i] = str(num)

        nums.sort(key = functools.cmp_to_key(self.cmp))
        ans = ''.join(nums) +  '1'
        ans.strip('0')
        if len(ans) == 1:
            ans = '0'
        else:
            ans = ans[0:-1]
        return ans

if __name__ == '__main__':
    a = [3, 30, 34, 5, 9]

    ans = Solution().largestNumber(a)
    print(ans)


from fastapi import FastAPI
from fastapi.responses import HTMLResponse

from app.endpoints import calendar, oauth2

app = FastAPI()
app.include_router(oauth2.router)
app.include_router(calendar.router)

@app.get("/", response_class=HTMLResponse)
def index():
    return """

            <title>SDS App</title>

Hello! Thanks for visiting SDS App!

    """

if __name__ == '__main__':
    from uvicorn import run

    run(app, port=8080)


#!/usr/bin/env python3.7
# coding: utf-8

from __future__ import unicode_literals

from ParsingShow import ParseRunInterfaceDeeperFile
from dictdiffer import diff
import pyparsing as pp
import argparse
from pprint import pprint
import pdb
import ntpath
import re
import sys
import yaml

import os.path, time

def parseSed(Str__):
	resultat=[]
	Sed=pp.Literal('s/').suppress()+pp.Word(pp.alphanums)+pp.Literal('/').suppress()+pp.Word(pp.alphanums)+pp.Literal('/').suppress()+pp.Optional(pp.Literal('g')).suppress()

	try:
		resultat=Sed.parseString(Str__,parseAll=True).asList()
	except pp.ParseException as e:
		print("Erreur parsing l'option replace")
		print("respecter la forme sed pour remplacer s/.../.../")
		sys.exit(1)

	return resultat

def replace_dict(dict__,str__,equipement):
	resultat=str__
	for key__ in dict__[equipement].keys():
		if re.search('[a-zA-Z]'+key__+'$',str__) or re.search('\s'+key__+'$',str__):
			resultat=str__.replace(key__,dict__[equipement][key__])
			break;
	return resultat

def filter_info(list_parser,filter=None,replace="",equipement=""):
	resultat={}

	if replace:
		if filter:
			for entry in list_parser[0].keys():
				if re.search(filter,entry):
					new_entry=replace_dict(replace,entry,equipement)
					resultat[new_entry]=list_parser[0][entry]

		else:
			for entry in list_parser[0].keys():
				new_entry=replace_dict(replace,entry)
				resultat[new_entry]=list_parser[0][entry]
	else:
		if filter:
			for entry in list_parser[0].keys():
				if re.search(filter,entry):
					resultat[entry]=list_parser[0][entry]
		else:
			for entry in list_parser[0].keys():
				resultat[entry]=list_parser[0][entry]

	return resultat

def print_diff(list_diff):
	resultat=[]
	for entry in list_diff:
		resultat.append(entry)

	return resultat

def print_time_file(file__):
	print("last modified "+ntpath.basename(file__)+":  "+time.ctime(os.path.getmtime(file__)))

if __name__ == '__main__':
	"Fonction principale"
	parser = argparse.ArgumentParser()

	parser.add_argument('file1')
	parser.add_argument('file2')
	parser.add_argument("--filter1", action="store",help="filtre sur les interfaces (regex) file 1",required=False)
	parser.add_argument("--filter2", action="store",help="filtre sur les interfaces (regex) file 2",required=False)
	parser.add_argument("-r", "--replace", action="store",help="fichier yaml",required=False)
	parser.add_argument("-e", "--equipement", action="store",default='SC2ASWIPP001',help="fichier yaml",required=False)

	args = parser.parse_args()
	print('\n')
	print_time_file(args.file1)
	print_time_file(args.file2)
	print('\n')

	Remplacement={}
	if args.replace:
		with open(args.replace, 'r' ) as model_yml:
			Remplacement = yaml.load(model_yml,Loader=yaml.SafeLoader)

	result=diff(filter_info(ParseRunInterfaceDeeperFile(args.file1),filter=args.filter1,replace=Remplacement,equipement=args.equipement),filter_info(ParseRunInterfaceDeeperFile(args.file2),filter=args.filter2,equipement=args.equipement))

	pprint(print_diff(result))


from pyspark import Row
from pyspark.sql import SparkSession
from pyspark.sql.functions import expr, regexp_replace

class ProductDimension:
	"""
		Reads dim.csv and
	"""

	def __init__(self, spark_session):
		self.spark = spark_session
		self.sc = self.spark.sparkContext

	def file_to_df(self):
		dim_lines = self.sc.textFile("data/dim.csv")
		header = dim_lines.first()
		dim_lines = dim_lines.filter(lambda r: r != header)
		dim_parts = dim_lines.map(lambda l: l.split(","))

		dim = dim_parts.map(lambda p: Row(
			is_banner=p[1],
			is_tax=p[2],
			is_market_place=p[3],
			material_status=p[4],
			current_price_range=p[5],
			cmc_division=p[6],
			cmc_business_unit=p[7],
			gender=p[8],
			product=p[9]
		))

		return self.spark.createDataFrame(dim)

	@staticmethod
	def gender_transform(df):
		gender = expr("UPPER(CASE WHEN gender IS NULL OR gender = '' THEN 'UNISSEX' ELSE gender END)")
		df = df.withColumn("gender", gender)
		df = df.withColumn("gender", regexp_replace(df['gender'], '(.)*(UNISEX)(.)*', 'UNISSEX'))
		df = df.withColumn("gender", regexp_replace(df['gender'], '(.)*(MASC){1}(.)*(FEM){1}(.)*', 'UNISSEX'))
		df = df.withColumn("gender", regexp_replace(df['gender'], '(.)*(FEM){1}(.)*(MASC){1}(.)*', 'UNISSEX'))
		df = df.withColumn("gender", regexp_replace(df['gender'], '(.)*(BEB)(.)*', 'BEBE'))
		df = df.withColumn(
			"gender", regexp_replace(
				df['gender'], '(.)*(NIÑ|MENIN|BOYS|GIRL|INFANTIL|JUVENIL)(.)*', 'INFANTIL'
			)
		)
		df = df.withColumn("gender", regexp_replace(df['gender'], '(.)*(FEM)(.)*', 'FEMININO'))
		df = df.withColumn("gender", regexp_replace(df['gender'], '(.)*(MASC)(.)*', 'MASCULINO'))

		return df

	def csv_to_tmp_view(self, view_name="dim"):
		df = self.file_to_df()
		df = self.gender_transform(df)

		df.createOrReplaceTempView(view_name)


# -*- coding: utf-8 -*-
"""
Created on Mon Apr  6 13:49:48 2020
@author: Bruna
"""

import sys
import os
import sqlite3
from contextlib import closing

from classes import Item
from classes import Customer

conn = sqlite3.connect("project.sqlite")
conn.row_factory = sqlite3.Row

def connect():
    global conn
    if not conn:
        if sys.platform == "win32":
            DB_FILE = "\Desktop\GBC\WINTER 2020\PYTHON\PROJECT\project.sqlite"
        else:
            HOME = os.environ["HOME"]
            DB_FILE = HOME + "/Documents/murach/python/_db/movies.sqlite"
            conn = sqlite3.connect(DB_FILE)
            conn.row_factory = sqlite3.Row

def close():
    if conn:
        conn.close()

def makeItem(row):
    return Item(row[0], row[1], row[2])

# TO DISPLAY THE ITEMS AVAILABLE IN THE DATABASE
def getItems():
    query = '''SELECT itemID AS ID,
                    name AS Item,
                    price AS Price
                FROM Item'''
    with closing(conn.cursor()) as c:
        c.execute(query)
        results = c.fetchall()

    items = []
    for row in results:
        items.append(makeItem(row))
    return items

# TO GET ONE SPECIFC ITEM IN THE DATABASE
def getItem(itemID):
    query = '''SELECT itemID AS ID, name AS Item, price AS Price
                FROM Item WHERE itemID = ?'''

    with closing(conn.cursor()) as c:
        c.execute(query, (itemID,))
        row = c.fetchone()

    item = makeItem(row)
    return item

# ADD A NEW CUSTOMER IN THE DATABASE
def addCustomer(customer):
    sql = '''INSERT INTO Customer (customerID, name)
            VALUES (?, ?)'''
    with closing(conn.cursor()) as c:
        c.execute(sql, (customer.customerID, customer.name))
        conn.commit()


import os, sys
import subprocess
import argparse

from profiler.profile_op.op_cfg import config2str, str2config
from utils.cutlass_api import OperationArgs, find_cutlass_kernel
from utils.device_info import DEVICE_INFO, short_device_name, query_cc

import tensorflow as tf

parser = argparse.ArgumentParser(prog="Test")
parser.add_argument('--cfg_str', type=str, default=None, help="If set, run one specific config")
parser.add_argument('--ops', type=str, default=None, help="OPs to run")
parser.add_argument('--target_gpu', type=str, default=None, help="target gpu")
parser.add_argument('--cache_path', type=str, default=None, help="Path to cache profile results")
args = parser.parse_args()

op2cutlass_kernel_type = {
    "MatMul": "gemm",
    # "MatMul": "sparsgemm",
    "Conv2D": "conv2d_fprop",
}

DTYPE_NAME_CONVERTER = {
    tf.dtypes.float16: "f16",
    tf.dtypes.float32: "f32"
}

if __name__ == "__main__":
    op_args = OperationArgs()

    op_args.kernel_type = op2cutlass_kernel_type[args.ops]

    capability = query_cc(args.target_gpu)
    op_args.cc_major = capability // 10
    op_args.cc_minor = capability % 10

    config = str2config(args.cfg_str)
    op_args.dtype = DTYPE_NAME_CONVERTER[config["dtype"]]
    op_args.m = config["N"]
    op_args.k = config["C_in"]
    op_args.n = config["C_out"]
    kernel = find_cutlass_kernel(op_args, verbose=False)

    cmd = ["cutlass_profiler"]
    cmd.append("--kernels={}".format(kernel))
    cmd.append("--m={}".format(op_args.m))
    cmd.append("--n={}".format(op_args.n))
    cmd.append("--k={}".format(op_args.k))
    cmd.append("--beta=1")
    cmd.append("--A={}".format(op_args.dtype))
    cmd.append("--B={}".format(op_args.dtype))
    cmd.append("--C={}".format(op_args.dtype))
    cmd.append("--accum={}".format(op_args.dtype))
    lines = subprocess.check_output(cmd, shell=False).decode('utf-8').split("\n")
    header = lines[-3].split(",")
    data = lines[-2].split(",")

    if args.cache_path is not None:
        with open(args.cache_path, 'a') as fp:
            fp.write("{},{},{},{}\n".format(
                data[header.index("Operation")],
                data[header.index("Bytes")],
                data[header.index("Flops")],
                data[header.index("Runtime")]
                ))

# cutlass_tensorop_h1688gemm_256x128_32x2_nn_align8


from django.shortcuts import render
from resumeApp.models import *
from resumeApp.forms import ContactForm
from django.core.mail import EmailMessage
from django.shortcuts import redirect
from django.template import Context
from django.template.loader import get_template
from django.contrib import messages

def home(request):
	jobs = Job.objects.all().order_by('-start_date')
	executive_summary = GeneralInfo.objects.values('executive_summary').get()
	education_list = Education.objects.all().order_by('-year')
	skills = GeneralInfo.objects.values('skills').get()
	context = {
		'jobs': jobs,
		'executive_summary': executive_summary,
		'education_list': education_list,
		'skills': skills,
	}
	return render(request, 'index.html', context)

def contact(request):
	form_class = ContactForm

	if request.method == 'POST':
		form = form_class(data=request.POST)

		if form.is_valid():
			contact_name = request.POST.get(
				'contact_name', '')
			contact_email = request.POST.get(
				'contact_email', '')
			form_content = request.POST.get('content', '')

			# Email the profile with the contact information
			template = get_template('contact_template.txt')
			context = Context({
				'contact_name': contact_name,
				'contact_email': contact_email,
				'form_content': form_content,
			})
			content = template.render(context)

			email = EmailMessage(
				"New Form Submission",
				content,
				"peterdimaria.com" + '',
				['dimaria.p@gmail.com'],
				headers={'Reply-To': contact_email}
			)
			email.send()
			messages.success(request, 'Your message was sent to Peter.')
			return redirect('/contact/')

	return render(request, 'contact.html', {'form': form_class})

def about(request):
	about_copy = GeneralInfo.objects.values('about').get()
	context = {
		'about': about_copy
	}
	return render(request, 'about.html', context)

def privacy_policy(request):
	privacy_policy_copy = GeneralInfo.objects.values('privacy_policy').get()
	context = {
		'privacy_policy': privacy_policy_copy,
	}
	return render(request, 'privacy_policy.html', context)


# Advent of Code - Day 4
# Part 2

class ElfRange:
    def __init__(self, lower_bound, upper_bound):
        self.lb = int(lower_bound)
        self.ub = int(upper_bound)

def parse_input(file):
    data = []
    for line in open(file):
        pair = line.strip().split(",")
        elf_pair = []
        for e in pair:
            lb, ub = e.split("-")
            elf_pair.append(ElfRange(lb, ub))
        data.append(elf_pair)
    return data

def in_range(val: int, elf: ElfRange):
    return elf.lb <= val <= elf.ub

def is_overlapping(e1: ElfRange, e2: ElfRange):
    return (
        in_range(e1.lb, e2)
        or in_range(e1.ub, e2)
        or in_range(e2.lb, e1)
        or in_range(e2.ub, e1)
    )

def get_overlapping_range_number(data):
    n_contained_range = 0
    for pair in data:
        if is_overlapping(pair[0], pair[1]):
            n_contained_range += 1
    return n_contained_range

def main():
    data = parse_input("input.txt")
    print(get_overlapping_range_number(data))

if __name__ == "__main__":
    main()


import json
import re
import types

import boto3
import botocore.exceptions
import botocore.errorfactory

from .lib import toiter, sip, jsonify
from .secrets import aws_credentials
from .secrets import (
  AWS_DEFAULT_REGION
)

import tenacity

AWS_BATCH_SIZE = 10 # send_message_batch's max batch size is 10

class ClientSideError(Exception):
  pass

retry = tenacity.retry(
  reraise=True,
  stop=tenacity.stop_after_attempt(4),
  wait=tenacity.wait_random_exponential(0.5, 60.0),
  retry=tenacity.retry_if_not_exception_type(ClientSideError),
)

class AWSTaskQueueAPI(object):
  def __init__(self, qurl, region_name=AWS_DEFAULT_REGION, **kwargs):
    """
    qurl: either a queue name (e.g. 'pull_queue') or a url
      like https://sqs.us-east-1.amazonaws.com/DIGITS/wms-pull-queue
    kwargs: Keywords for the underlying boto3.client constructor, other than `service_name`,
      `region_name`, `aws_secret_access_key`, or `aws_access_key_id`.
    """
    if 'region' in kwargs:
      region_name = kwargs.pop('region')

    matches = re.search(r'sqs.([\w\d-]+).amazonaws', qurl)

    if matches is not None:
      region_name, = matches.groups()
      self.qurl = qurl
    else:
      self.qurl = None

    credentials = aws_credentials()

    self.sqs = boto3.client('sqs',
      aws_secret_access_key=credentials.get('AWS_SECRET_ACCESS_KEY'),
      aws_access_key_id=credentials.get('AWS_ACCESS_KEY_ID'),
      region_name=region_name,
      **kwargs,
    )

    if self.qurl is None:
      self.qurl = self._get_qurl(qurl)

    self.batch_size = AWS_BATCH_SIZE

  @retry
  def _get_qurl(self, qurl):
    try:
      return self.sqs.get_queue_url(QueueName=qurl)["QueueUrl"]
    except Exception as err:
      print(f"Failed to fetch queue URL for: {qurl}")
      raise

  @property
  def enqueued(self):
    status = self.status()
    return (
      int(status['ApproximateNumberOfMessages'])
      + int(status['ApproximateNumberOfMessagesNotVisible'])
      + int(status['ApproximateNumberOfMessagesDelayed'])
    )

  @property
  def inserted(self):
    return float('NaN')

  @property
  def completed(self):
    return float('NaN')

  @property
  def leased(self):
    status = self.status()
    return int(status['ApproximateNumberOfMessagesNotVisible'])

  def is_empty(self):
    return self.enqueued == 0

  @retry
  def status(self):
    resp = self.sqs.get_queue_attributes(
      QueueUrl=self.qurl,
      AttributeNames=[
        'ApproximateNumberOfMessages',
        'ApproximateNumberOfMessagesNotVisible',
        'ApproximateNumberOfMessagesDelayed'
      ]
    )
    return resp['Attributes']

  @retry
  def insert(self, tasks, delay_seconds=0):
    tasks = toiter(tasks)

    total = 0
    # send_message_batch's max batch size is 10
    for batch in sip(tasks, self.batch_size):
      if len(batch) == 0:
        break

      entries = [ {
          "Id": str(j),
          "MessageBody": jsonify(task),
          "DelaySeconds": delay_seconds,
        } for j, task in enumerate(batch)
      ]

      try:
        resp = self.sqs.send_message_batch(
          QueueUrl=self.qurl,
          Entries=entries,
        )
      except botocore.exceptions.ClientError as error:
        http_code = error.response['ResponseMetadata']['HTTPStatusCode']
        if 400 <= int(http_code) < 500:
          raise ClientSideError(error)
        else:
          raise error

      total += len(entries)

    return total

  def add_insert_count(self, ct):
    pass

  def rezero(self):
    pass

  @retry
  def renew_lease(self, task, seconds):
    self.sqs.change_message_visibility(
      QueueUrl=self.qurl,
      ReceiptHandle=task.id,
      VisibilityTimeout=seconds,
    )

  def cancel_lease(self, task):
    self.renew_lease(task, 0)

  def release_all(self):
    raise NotImplementedError()

  def lease(self, seconds, num_tasks=1, wait_sec=20):
    if wait_sec is None:
      wait_sec = 20

    resp = self.sqs.receive_message(
      QueueUrl=self.qurl,
      AttributeNames=[
        'SentTimestamp'
      ],
      MaxNumberOfMessages=num_tasks,
      MessageAttributeNames=[
        'All'
      ],
      VisibilityTimeout=seconds,
      WaitTimeSeconds=wait_sec,
    )

    if 'Messages' not in resp:
      return []

    tasks = []
    for msg in resp['Messages']:
      task = json.loads(msg['Body'])
      task['id'] = msg['ReceiptHandle']
      tasks.append(task)
    return tasks

  def delete(self, task):
    if type(task) == str:
      rhandle = task
    else:
      try:
        rhandle = task._id
      except AttributeError:
        rhandle = task['id']

    try:
      self.sqs.delete_message(
        QueueUrl=self.qurl,
        ReceiptHandle=rhandle,
      )
    except botocore.exceptions.ClientError as err:
      pass

    return 1

  def tally(self):
    pass

  def purge(self, native=False):
    # can throw:
    # except botocore.errorfactory.PurgeQueueInProgress:
    if native:
      self.sqs.purge_queue(QueueUrl=self.qurl)
      return

    while self.enqueued:
      # visibility_timeout must be > 0 for delete to work
      tasks = self.lease(num_tasks=10, seconds=10)
      for task in tasks:
        self.delete(task)

  def __iter__(self):
    return iter(self.lease(num_tasks=10, seconds=0))


import os
import time
import argparse
import datetime
import numpy as np
import torch
import torch.optim as optim
from matplotlib import pyplot as plt
from torch.autograd import Variable
from torch.utils.data import DataLoader
from Models.actor import DRL4TSP
from Models.tsp.tspActor import NetworkTSP
from Models.tsp.tspPointerNetwork import CombinatorialRLTSP
from Tasks import vrp, tsp
from Models.critc import StateCritic, StateCriticTSP
from Tasks.tsp import TSPDataset
from utils.plots import plot_metrics, plot_models_metrics
torch.backends.cudnn.benchmark = True
torch.backends.cudnn.enabled = False
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print('Detected device {}'.format(device))

metrics_per_model = []

def test(data_loader, actor, reward_fn, render_fn=None, save_dir='.', num_plot=5):
    """Used to monitor progress on a validation set & optionally plot solution."""

    actor.eval()

    if not os.path.exists(save_dir):
        os.makedirs(save_dir)

    rewards = []
    for batch_idx, static in enumerate(data_loader):
        static = static.to(device)
        with torch.no_grad():
            tour_indices, _ = actor.forward(static, static)

        reward = reward_fn(static, tour_indices).mean().item()
        rewards.append(reward)

        if render_fn is not None and batch_idx < num_plot:
            name = 'batch%d_%2.4f.png' % (batch_idx, reward)
            path = os.path.join(save_dir, name)
            render_fn(static, tour_indices, path)

    actor.train()
    return np.mean(rewards)

def validate(data_loader, actor, reward_fn, render_fn=None, save_dir='.', num_plot=5):
    """Used to monitor progress on a validation set & optionally plot solution."""

    actor.eval()

    if not os.path.exists(save_dir):
        os.makedirs(save_dir)

    rewards = []
    for batch_idx, batch in enumerate(data_loader):

        static = batch

        static = static.to(device)

        with torch.no_grad():
            reward, probs, actions, actions_idxs = actor.forward(static)

        #reward = reward_fn(static, tour_indices).mean().item()
        rewards.append(reward)

        # if render_fn is not None and batch_idx < num_plot:
        #     name = 'batch%d_%2.4f.png' % (batch_idx, reward)
        #     path = os.path.join(save_dir, name)
        #     render_fn(static, actions_idxs, path)

    actor.train()
    return np.mean(rewards)

def train(actor, critic, task, num_nodes, train_data, valid_data, reward_fn,
          render_fn, batch_size, actor_lr, critic_lr, max_grad_norm, experiment,
          **kwargs):
    """Constructs the main actor & critic networks, and performs all training."""

    now = '%s' % datetime.datetime.now().time()
    now = now.replace(':', '_')
    save_dir = os.path.join(task, '%d' % num_nodes, now)

    print('Starting training')

    checkpoint_dir = os.path.join(save_dir, 'checkpoints')
    if not os.path.exists(checkpoint_dir):
        os.makedirs(checkpoint_dir)

    actor_optim = optim.Adam(actor.parameters(), lr=actor_lr)
    critic_optim = optim.Adam(critic.parameters(), lr=critic_lr)

    lr_decay = 1.0
    # lr_scheduler = optim.lr_scheduler.LambdaLR(actor_optim, lambda epoch: lr_decay ** epoch)

    train_loader = DataLoader(train_data, batch_size, True, num_workers=0)
    valid_loader = DataLoader(valid_data, batch_size, False, num_workers=0)

    best_reward = np.inf

    losses_per_epoch = []
    rewards_per_epoch = []
    critic_losses_per_epoch = []
    critic_rewards_per_epoch = []
    distances_per_epoch = []

    for epoch in range(epochs):

        actor.train()
        critic.train()

        times, losses, rewards, critic_rewards, distances, critic_losses = [], [], [], [], [], []

        epoch_start = time.time()
        beta = 0.9

        for batch_idx, batch in enumerate(train_loader):

            static = Variable(batch)

            static = static.to(device)

            # Full forward pass through the dataset
            reward, probs, actions, actions_idxs =actor(static)

            if batch_idx == 0:
                critic_exp_mvg_avg = reward.mean()
            else:
                critic_exp_mvg_avg = (critic_exp_mvg_avg * beta) + ((1. - beta) * reward.mean())

            # Sum the log probabilities for each city in the tour
            #reward = reward_fn(static, tour_indices)

            # Query the critic for an estimate of the reward
            #critic_est = critic(static).view(-1)
            logprobs = 0
            for prob in probs:
                logprob = torch.log(prob)
                logprobs += logprob
            logprobs[logprobs < -1000] = 0.

            advantage = (reward - critic_exp_mvg_avg)#- critic_est)

            reinforce = advantage  * logprobs
            actor_loss = reinforce.mean() # torch.mean(advantage.detach() * tour_logp)

            #critic_loss = torch.mean(advantage ** 2)

            actor_optim.zero_grad()
            actor_loss.backward()
            #torch.nn.utils.clip_grad_norm_(actor.parameters(), max_grad_norm)
            actor_optim.step()

            critic_exp_mvg_avg = critic_exp_mvg_avg.detach()
            # critic_optim.zero_grad()
            # critic_loss.backward()
            # torch.nn.utils.clip_grad_norm_(critic.parameters(), max_grad_norm)
            # critic_optim.step()
            #
            # critic_rewards.append(torch.mean(critic_est.detach()).item())
            # critic_losses.append(torch.mean(critic_loss.detach()).item())

            # actor reward is the absolute log probabilities of the chosen actions multiplied
            # by the advantage
            actor_reward = torch.mean(torch.abs(reinforce))

            rewards.append(actor_reward.item())

            losses.append(torch.mean(actor_loss.detach()).item())
            distances.append(torch.mean(reward).item())

        # epoch finished
        # lr_scheduler.step()

        # print(f'Learning rate for epoch {epoch}={lr_scheduler.get_lr()}')
        mean_critic_reward = np.mean(critic_rewards)
        mean_critic_loss = np.mean(critic_losses)
        mean_loss = np.mean(losses)
        mean_reward = np.mean(rewards)
        mean_distance = np.mean(distances)

        losses_per_epoch.append(mean_loss)
        rewards_per_epoch.append(mean_reward)
        distances_per_epoch.append(mean_distance)

        critic_losses_per_epoch.append(mean_critic_loss)
        critic_rewards_per_epoch.append(mean_critic_reward)

        # Save the weights
        epoch_dir = os.path.join(checkpoint_dir, '%s' % epoch)
        if not os.path.exists(epoch_dir):
            os.makedirs(epoch_dir)

        save_path = os.path.join(epoch_dir, 'actor.pt')
        torch.save(actor.state_dict(), save_path)

        save_path = os.path.join(epoch_dir, 'critic.pt')
        torch.save(critic.state_dict(), save_path)

        # Save rendering of validation set tours
        valid_dir = os.path.join(save_dir, '%s' % epoch)

        mean_valid = validate(valid_loader, actor, reward_fn, render_fn,
                              valid_dir, num_plot=5)

        print(
            f'Mean epoch {epoch}/{epochs}: loss={mean_loss}, reward={mean_reward}, distance={mean_distance}, val reward={mean_valid}')

    plt.clf()

    metrics = [distances_per_epoch,
               critic_losses_per_epoch,
               critic_rewards_per_epoch,
               losses_per_epoch,
               rewards_per_epoch]

    labels = ["Distances", "Critic loss", "Critic estimate", "Actor loss", "Actor reward"]

    metrics_per_model.append(metrics)
    plot_metrics(metrics,
                 labels,
                 experiment,
                 labels,
                 title="CVRP",
                 xlabel="Epochs")
    plt.clf()
    plt.plot(losses_per_epoch)
    plt.savefig(f"losses{experiment}.png")
    plt.clf()

    plt.plot(rewards_per_epoch)
    plt.savefig(f"rewards{experiment}.png")
    plt.clf()

    plt.plot(distances_per_epoch)
    plt.savefig(f"distances{experiment}.png")
    plt.clf()

    plt.plot(critic_losses_per_epoch)
    plt.savefig(f"critic_losses{experiment}.png")
    plt.clf()

    plt.plot(critic_rewards_per_epoch)
    plt.savefig(f"critic_rewards{experiment}.png")
    plt.clf()

    torch.save(actor.state_dict(), f'actor{experiment_name}.pt')
    torch.save(critic.state_dict(), f'critic{experiment_name}.pt')

def train_vrp(args):

    print('Starting TSP training')

    STATIC_SIZE = 2  # (x, y)
    train_data = TSPDataset(20, train_size,  args.seed + 1)
    valid_data = TSPDataset(20, args.valid_size,  args.seed + 2)

    # actor = NetworkTSP(STATIC_SIZE,
    #                 args.hidden_size,
    #                 None,
    #                 train_data.update_mask,
    #                 args.embedding,
    #                 args.num_layers,
    #                 args.dropout).to(device)

    embedding_size = 128
    hidden_size = 128
    n_glimpses = 1
    tanh_exploration = 10
    use_tanh = True
    batch_size = 128
    beta = 0.9
    max_grad_norm = 2.

    """Δημιουργούμε τα μοντέλα που θα εκπαιδεύσουμε."""

    actor = CombinatorialRLTSP(
        embedding_size,
        hidden_size,
        20,
        n_glimpses,
        tanh_exploration,
        use_tanh,
        tsp.reward,
        embedding="Graph",
        attention="Dot")

    # actor = CombinatorialRLTSP(
    #     args.hidden_size,
    #     args.hidden_size,
    #     20,
    #     1,
    #     10,
    #     True,
    #     tsp.reward,
    #     attention="Dot")

    print('Actor: {} '.format(actor))

    critic = StateCriticTSP(STATIC_SIZE, args.hidden_size, args.embedding).to(device)

    print('Critic: {}'.format(critic))

    kwargs = vars(args)
    kwargs['train_data'] = train_data
    kwargs['valid_data'] = valid_data
    kwargs['reward_fn'] = vrp.reward
    kwargs['render_fn'] = vrp.render

    if not args.test:
        train(actor, critic, **kwargs)

    # test_data = TSPDataset( args.train_size, num_nodes, args.seed + 2)
    #
    # test_dir = 'test'

    # testing
    # finding variation
    test_distances = []

    # for i in range(10):
    #     test_loader = DataLoader(test_data, args.batch_size, False, num_workers=0)
    #     avg_tour_length = test(test_loader, actor, vrp.reward, vrp.render, test_dir, num_plot=5)
    #     print('Average tour length: ', avg_tour_length)
    #
    #     test_distances.append(avg_tour_length)
    #
    #     variance = np.var(test_distances)
    #     plt.clf()
    #     plt.plot(test_distances)
    #     plt.title(f"Test distances, variance: {variance}")
    #     plt.savefig("testDistances.png")

if __name__ == '__main__':
    train_size = 15_000#_000
    num_nodess = [20]#, 50, 100]

    bss = [100]
    # bss = [256] -> oles kales oi metrikes ektos distances # [128, 256, 512]
    epochs = 20#0
    emb = ['conv']  # , 'lin', 'graph']
    critic_lr = 5e-1
    actor_lr = 1e-4

    for num_nodes_idx in range(len(num_nodess)):
        num_nodes = num_nodess[num_nodes_idx]
        bs = bss[0]
        embedding = emb[0]
        parser = argparse.ArgumentParser(description='Combinatorial Optimization')
        parser.add_argument('--seed', default=12345, type=int)
        parser.add_argument('--checkpoint', default=None)
        parser.add_argument('--test', action='store_true', default=False)
        parser.add_argument('--task', default='vrp')
        parser.add_argument('--nodes', dest='num_nodes', default=num_nodes, type=int)
        parser.add_argument('--actor_lr', default=actor_lr, type=float)
        parser.add_argument('--critic_lr', default=critic_lr, type=float)
        parser.add_argument('--max_grad_norm', default=2., type=float)
        parser.add_argument('--batch_size', default=bs, type=int)  # 256
        parser.add_argument('--hidden', dest='hidden_size', default=128, type=int)
        parser.add_argument('--dropout', default=0.1, type=float)
        parser.add_argument('--layers', dest='num_layers', default=1, type=int)
        parser.add_argument('--train-size', default=train_size, type=int)  # 0000
        parser.add_argument('--valid-size', default=1000, type=int)
        parser.add_argument('--embedding', default=embedding)

        experiment_name = f'TAHN_EXP_SP_CRITIC_AVG_nodes_{num_nodes}_{embedding}size{train_size}_bs{bs}_actLr{actor_lr}_criLr{critic_lr}'
        parser.add_argument('--experiment', default=experiment_name)

        args = parser.parse_args()

        train_vrp(args)

    # metric_labels = ["Distances", "Critic loss", "Critic reward", "Loss", "Reward"]
    # # labels = ['Conv embedding', 'Linear embedding', 'Graph embedding']
    # labels = ['10 nodes', '50 nodes', '100 nodes']
    #
    # plot_models_metrics(metrics_per_model[0],
    #                     metrics_per_model[1],
    #                     metrics_per_model[2],
    #                     labels,
    #                     metric_labels,
    #                     experiment_name)
    #
    # k = len(metrics_per_model)
    #
    # for i in range(k):
    #     print(metrics_per_model[i])


#
# 따라하며 배우는 파이썬과 데이터과학(생능출판사 2020)
# 심화문제 풀이, 302쪽
#
import matplotlib.pyplot as plt

fig, ax = plt.subplots(1, 4, figsize=(10, 3))

x = [x for x in range(7, 13)]
y = [456, 492, 578, 599, 670, 854]

ax[0].bar(x, y)
ax[1].plot(x, y)
ax[2].scatter(x, y)
ax[3].barh(x, y)

plt.show()


if __name__ == "__main__":
    # Training data is in a csv file called train.csv
    df = pd.read_csv("train.csv")

    # we create a new column called kfold and fill it with -1
    df["kfold"] = -1

    # the next step is to randomize the rows of the data
    df = df.sample(frac=1).reset_index(drop=True)

    # fetch targets
    y = df.quality.values

    # initiate the kfold class from model_selection module
    kf = model_selection.StratifiedKFold(n_splits=5)

    # fill the new kfold column
    for f, (t_, v_) in enumerate(kf.split(X=df, y=y)):
        df.loc[v_, 'kfold'] = f

    # save the new csv with kfold column
    df.to_csv("train_folds_skf.csv", index=False)


def tf_mirror_urls(url):
    """A helper for generating TF-mirror versions of URLs.

    Given a URL, it returns a list of the TF-mirror cache version of that URL
    and the original URL, suitable for use in `urls` field of `tf_http_archive`.
    """
    if not url.startswith("https://"):
        return [url]
    return [
        "https://storage.googleapis.com/mirror.tensorflow.org/%s" % url[8:],
        url,
    ]

def _get_env_var(ctx, name):
    if name in ctx.os.environ:
        return ctx.os.environ[name]
    else:
        return None

# Checks if we should use the system lib instead of the bundled one
def _use_system_lib(ctx, name):
    syslibenv = _get_env_var(ctx, "TF_SYSTEM_LIBS")
    if not syslibenv:
        return False
    return name in [n.strip() for n in syslibenv.split(",")]

def _get_link_dict(ctx, link_files, build_file):
    link_dict = {ctx.path(v): ctx.path(Label(k)) for k, v in link_files.items()}
    if build_file:
        # Use BUILD.bazel because it takes precedence over BUILD.
        link_dict[ctx.path("BUILD.bazel")] = ctx.path(Label(build_file))
    return link_dict

def _tf_http_archive_impl(ctx):
    # Construct all paths early on to prevent rule restart. We want the
    # attributes to be strings instead of labels because they refer to files
    # in the TensorFlow repository, not files in repos depending on TensorFlow.
    # See also https://github.com/bazelbuild/bazel/issues/10515.
    link_dict = _get_link_dict(ctx, ctx.attr.link_files, ctx.attr.build_file)

    # For some reason, we need to "resolve" labels once before the
    # download_and_extract otherwise it'll invalidate and re-download the
    # archive each time.
    # https://github.com/bazelbuild/bazel/issues/10515
    patch_files = ctx.attr.patch_file
    for patch_file in patch_files:
        if patch_file:
            ctx.path(Label(patch_file))

    if _use_system_lib(ctx, ctx.attr.name):
        link_dict.update(_get_link_dict(
            ctx = ctx,
            link_files = ctx.attr.system_link_files,
            build_file = ctx.attr.system_build_file,
        ))
    else:
        ctx.download_and_extract(
            url = ctx.attr.urls,
            sha256 = ctx.attr.sha256,
            type = ctx.attr.type,
            stripPrefix = ctx.attr.strip_prefix,
        )
        if patch_files:
            for patch_file in patch_files:
                patch_file = ctx.path(Label(patch_file)) if patch_file else None
                if patch_file:
                    ctx.patch(patch_file, strip = 1)

    for dst, src in link_dict.items():
        ctx.delete(dst)
        ctx.symlink(src, dst)

_tf_http_archive = repository_rule(
    implementation = _tf_http_archive_impl,
    attrs = {
        "sha256": attr.string(mandatory = True),
        "urls": attr.string_list(mandatory = True),
        "strip_prefix": attr.string(),
        "type": attr.string(),
        "patch_file": attr.string_list(),
        "build_file": attr.string(),
        "system_build_file": attr.string(),
        "link_files": attr.string_dict(),
        "system_link_files": attr.string_dict(),
    },
    environ = ["TF_SYSTEM_LIBS"],
)

def tf_http_archive(name, sha256, urls, **kwargs):
    """Downloads and creates Bazel repos for dependencies.

    This is a swappable replacement for both http_archive() and
    new_http_archive() that offers some additional features. It also helps
    ensure best practices are followed.

    File arguments are relative to the TensorFlow repository by default. Dependent
    repositories that use this rule should refer to files either with absolute
    labels (e.g. '@foo//:bar') or from a label created in their repository (e.g.
    'str(Label("//:bar"))').
    """
    if len(urls) < 2:
        fail("tf_http_archive(urls) must have redundant URLs.")

    if not any([mirror in urls[0] for mirror in (
        "mirror.tensorflow.org",
        "mirror.bazel.build",
        "storage.googleapis.com",
    )]):
        fail("The first entry of tf_http_archive(urls) must be a mirror " +
             "URL, preferrably mirror.tensorflow.org. Even if you don't have " +
             "permission to mirror the file, please put the correctly " +
             "formatted mirror URL there anyway, because someone will come " +
             "along shortly thereafter and mirror the file.")

    if native.existing_rule(name):
        print("\n\033[1;33mWarning:\033[0m skipping import of repository '" +
              name + "' because it already exists.\n")
        return

    _tf_http_archive(
        name = name,
        sha256 = sha256,
        urls = urls,
        **kwargs
    )

def _tf_vendored_impl(repository_ctx):
    parent_path = repository_ctx.path(repository_ctx.attr.parent).dirname

    # get_child doesn't allow slashes. Yes this is silly. bazel_skylib paths
    # doesn't work with path objects.
    relpath_parts = repository_ctx.attr.relpath.split("/")
    vendored_path = parent_path
    for part in relpath_parts:
        vendored_path = vendored_path.get_child(part)
    repository_ctx.symlink(vendored_path, ".")

tf_vendored = repository_rule(
    implementation = _tf_vendored_impl,
    attrs = {
        "parent": attr.label(default = "//:WORKSPACE"),
        "relpath": attr.string(),
    },
)


entrada = input()
entrada = entrada.split()
entrada = [int(_) for _ in entrada]

[linhas, colunas] = entrada

lista_entrada = [input() for _ in range(linhas)]
lista_entrada = [_.split() for _ in lista_entrada]

lista_palavras = input()
lista_palavras = lista_palavras.split()

palavras_linhas = lista_entrada[::-1][::-1]
palavras_linhas = [''.join(_) for _ in palavras_linhas]

palavras_colunas = []

for x in range(linhas):
  palavra = ''
  for y in range(colunas):
    palavra += lista_entrada[y][x]

  palavras_colunas.append(palavra)

def aparicoes(palavra, frase):
  if (palavra not in frase):
    return 0
  else:
    vezes = 0

    for indice in range(len(frase)):
      if frase[indice:indice + len(palavra)] == palavra:
        vezes += 1

  return vezes

dicionario = {}

for palavra in lista_palavras:
  dicionario[palavra] = 0

  for col in palavras_colunas:
    contagem = aparicoes(palavra, col)
    dicionario[palavra] += contagem

  for lin in palavras_linhas:
    contagem = aparicoes(palavra, lin)
    dicionario[palavra] += contagem

for chave in list(dicionario.keys()):
  print(f'{chave}: {dicionario[chave]}')


#https://leetcode.com/problems/sort-items-by-groups-respecting-dependencies/
#There are n items each belonging to zero or one of m groups where group[i] is the group that the i-th item belongs to and it's equal to -1 if the i-th item belongs to no group. The items and the groups are zero indexed. A group can have no item belonging to it.
#Return a sorted list of the items such that:
#The items that belong to the same group are next to each other in the sorted list.
#There are some relations between these items where beforeItems[i] is a list containing all the items that should come before the i-th item in the sorted array (to the left of the i-th item).
#Return any solution if there is more than one solution and return an empty list if there is no solution.

class Solution(object):
    def sortItems(self, n, m, group, beforeItems):
        """
        :type n: int
        :type m: int
        :type group: List[int]
        :type beforeItems: List[List[int]]
        :rtype: List[int]
        """
        def get_digits(n):
            res = []
            while n:
                res.append(n % 10)
                n /= 10
            return res[::-1]

        def get_permutations(n, k):
            res = 1
            for i in range(n, n-k, -1):
                res *= i
            return res

        def get_permutations_without_repetitions(n, k):
            res = 1
            for i in range(n, n-k, -1):
                res *= i
            for i in range(1, k+1):
                res /= i
            return res

        def get_count_without_repetitions(n):
            res = 0
            k = len(n)
            for i in range(1, k):
                res += 9 * get_permutations_without_repetitions(9, i-1)
            used = set()
            for i in range(k):
                for j in range(1 if i else 1, n[i]):
                    if j not in used:
                        res += get_permutations_without_repetitions(9-i, k-i-1)
                if n[i] in used:
                    break
                used.add(n[i])
            else:
                res += 1
            return res

        return n - get_count_without_repetitions(get_digits(n))


rock = '''
    _______
---'   ____)
      (_____)
      (_____)
      (____)
---.__(___)
'''

paper = '''
    _______
---'   ____)____
          ______)
          _______)
         _______)
---.__________)
'''

scissors = '''
    _______
---'   ____)____
          ______)
       __________)
      (____)
---.__(___)
'''

#Write your code below this line ðŸ‘‡
import random

selection = print(input("Let's play rock, paper and scissors, What do you will pick?, type 0 for rock, type 1 for paper or type 2 for scissors"))
selection = int
rndom = random.randint(0, 2)
pickbot = int(rndom)

if selection == 0 and rndom == 0 :
    print ("Draw")
elif selection == 0 and rndom == 1 :
    print("You lose")
elif selection == 0 and rndom == 2 :
    print("You win")
elif selection == 1 and rndom == 0 :
    print("You win")
elif selection == 1 and rndom == 1 :
    print ("Draw")
elif selection == 1 and rndom == 2 :
    print("You lose")
elif selection == 2 and rndom == 0 :
    print("You lose")
elif selection == 2 and rndom == 1 :
    print("You win")
elif selection == 2 and rndom == 2 :
    print ("Draw")


class Solution:
    def removeOccurrences(self, s: str, part: str) -> str:
        stack = []
        for i in range(len(s)):
            stack.append(s[i])
            if len(stack) >= len(part) and stack[-1] == part[-1]:
                if self.hasMatch(stack,part):
                    for _ in range(len(part)):
                        stack.pop()

        return "".join(stack)

    def hasMatch(self,stack,part):
        pointer = len(stack) - 1
        for i in range(len(part)-1,-1,-1):
            if part[i] != stack[pointer]:
                return False
            pointer -= 1
        return True