from tracetools.signatures.xpdf_poppler import XpdfPopplerFrame, LexType, \
    LexObj, XpdfPopplerMomentSignature, XpdfPopplerValueSignature, \
    XpdfPopplerPTTracker as Tracker, \
    LexerObjFrame as XpdfPopplerLexerObjFrame, \
    MakeStreamFrame as XpdfPopplerMakeStreamFrame, \
    NewParserMoment as XpdfPopplerNewParserMoment, \
    XpdfPopplerPTMoment, \
    GfxStreamSig as XpdfPopplerGfxStreamSig, \
    XRefConstructSigBase

from tracetools.signatures.pdf import PDFPT as PT
from tracetools.signatures.pdf import PDFEnum
from tracetools.signatures.signatures import ReturnSignature, \
    NewFrameMoment, SigID
from tracetools.signatures.versions import Version
from tracetools.log_entries import is_kind, MemEntry, CallEntry, PCEntry
from aenum import IntEnum, auto
from tracetools.signatures.context import DataContext, ParseReason
import dataclasses

class PopplerFrame(XpdfPopplerFrame):
    lib_name = "libpoppler.so.94"

class LexerObjFrame(XpdfPopplerLexerObjFrame, PopplerFrame):

    @classmethod
    def setup(cls):
        cls.callpcs = [cls.addrs_of("lexergetobj%d" % i, 1)
                       for i in range(1, 4)]
        cls.lib_start = Version.lib_starts(cls.lib_name, 1)

class MakeStreamFrame(XpdfPopplerMakeStreamFrame, PopplerFrame):
    fn_names = ["_ZN6Parser10makeStreamEO6ObjectPh14CryptAlgorithmiiiib"]

    def on_pop(self, new_top):
        super(MakeStreamFrame, self).on_pop(new_top)
        if self.shift_count < 2:
            self.OOPS("Shift should have been called at least 2 times",
                      f"but was only called {self.shift_count} time(s)")
        elif self.shift_count == 2:
            print("Note: endstream() missing from stream or incorrect "
                  "stream length, this is a fixup")
        # todo: if `make_stream_set_length` address/flag reached
        # this means that poppler substituted calculated length into
        # stream's dictionary
        new_top.register_pt_node(self.pt, self)

class XrefStmEntryType(IntEnum):
    FREE = 0
    UNCOMPRESSED = auto()
    COMPRESSED = auto()
    NONE = auto()

class ReadXRefStreamFrame(PopplerFrame):
    sig_id_name = "READ_XREF_STREAM"
    log_type = CallEntry
    attr_name = "target_addr"
    fn_names = ["_ZN4XRef21readXRefStreamSectionEP6StreamPKiii"]
    entry_type_idx = [XrefStmEntryType.FREE,
                      XrefStmEntryType.UNCOMPRESSED,
                      XrefStmEntryType.COMPRESSED]

    @classmethod
    def setup(cls):
        cls.gen_addrs = cls.addrs_of("xref_stm_section_gen")

    def __init__(self, flagged_sig):
        sigs = set([self.manager.sig_from_id(s) for s in
                    [SigID.XREF_STREAM_ENTRY_NUM,
                     SigID.XREF_STREAM_ENTRY_GEN,
                     SigID.XREF_STREAM_ENTRY_OFFSET]])
        self.num = None
        self.gen = None
        self.type = None
        self.offset = None
        pt = PT(PDFEnum.XREF_STREAM_TABLE)
        pt.add_context(ParseReason.create(self))
        super(ReadXRefStreamFrame, self).__init__(
            flagged_sig, pt_tracking_sigs=sigs, pt=pt,
        )

    def register_num(self, val, pc):
        self.num = val

    def register_gen(self, val, pc):
        self.gen = val
        self.type = int(self.entry_type_idx[self.gen_addrs.index(pc)])
        children = [PT(PDFEnum.INT, value=getattr(self, n))
                    for n in ["num", "gen", "offset", "type"]]
        self.add_pt_child(
            PT(PDFEnum.XREF_TABLE_ENTRY, children=children)
        )

    def register_offset(self, val, pc):
        self.offset = val

    def on_pop(self, new_top):
        self.do_register_pt(self.pt)
        super(ReadXRefStreamFrame, self).on_pop(new_top)

    def debug_string(self):
        return super(ReadXRefStreamFrame, self).debug_string() + \
            f"\nnum: {self.num}, gen: {self.gen}, offset: " + \
            f"{self.offset}, type: {self.type}"

class PopplerMomentSignature(XpdfPopplerMomentSignature):
    lib_name = "libpoppler.so.94"

class PopplerValueSignature(XpdfPopplerValueSignature, PopplerMomentSignature):
    pass

class PopplerPTTracker(Tracker):
    tracker_name = "poppler"
    _name = "tracetools.signatures.poppler"
    sig_bases = [PopplerMomentSignature]
    frame_bases = [PopplerFrame]
    _old = Tracker.frame_bases
    Tracker.frame_bases = frame_bases
    ArrayFrame = Tracker.do_register_subcls("ArrayFrame")
    DictFrame = Tracker.do_register_subcls("DictFrame")
    IntFrame = Tracker.do_register_subcls("IntFrame")
    GetObjFrame = Tracker.do_register_subcls("GetObjFrame")
    NewParserFrame = Tracker.do_register_subcls("NewParserFrame")
    GfxStreamFrame = Tracker.do_register_subcls("GfxStreamFrame",
                                                attr={"fn_names":
                                                      ["_ZN3Gfx2goEb"]})
    ShiftObjFrame = Tracker.do_register_subcls("ShiftObjFrame",
                                               attr={"fn_names":
                                                     ["_ZN6Parser5shiftEi",
                                                      "_ZN6Parser5shiftEPKci"]})
    FetchFrame = Tracker.do_register_subcls("FetchFrame",
                                            attr={"fn_names":
                                                  ["_ZN4XRef5fetchEiii"]})
    ConstructXRefFrame = Tracker.do_register_subcls("ConstructXRefFrame",
                                                    attr={"fn_names":
                                                          ["_ZN4XRef13constructXRefEPbb"]})
    Tracker.frame_bases = _old
    register_subcls = [
        ("ParserGetObj", sig_bases,
         {
            "push_frame_class": GetObjFrame,
            "fn_names": ["_ZN6Parser6getObjEbPh14CryptAlgorithmiiiib"]
         }),
        ("GetParserObjId", sig_bases, {"parent_frame_class": GetObjFrame}),
        ("ShiftObjId", sig_bases, {}),
        ("LexerGetObjCalled", sig_bases, {"fn_names": ["_ZN5Lexer6getObjEi",
                                                       "_ZN5Lexer6getObjEPKci"]}),
        ("GetObjSimpleMoment", sig_bases, {}),
        ("GetObjIntMoment", sig_bases, {"push_frame_class": IntFrame}),

        ("DictValueMoment", sig_bases, {}),
        ("DoubleObj", sig_bases, {}),
        ("BoolObj", sig_bases, {}),
        ("LexStrVal", sig_bases, {}),
        ("IntObj", sig_bases, {}),
        ("ObjInfoSig", sig_bases, {}),
        ("NewDictMoment", sig_bases, {"push_frame_class": DictFrame,
                                      "parent_frame_class": DictFrame}),
        ("NewArrayMoment", sig_bases, {"push_frame_class": ArrayFrame,
                                       "parent_frame_class": ArrayFrame}),
        ("DictFrameReturn", sig_bases, {"enable_sig_frame_class": GetObjFrame,
                                        "parent_frame_class": DictFrame}),
        ("CopyStringMoment", [], {"caller_lib_name": "libpoppler.so.94",
                                  "additional_libs": ["libpoppler.so.94"],
                                  "supported_group_ids": ["poppler"]}),
        ("ObjFetchXRefGen", sig_bases, {"parent_frame_class": FetchFrame}),
        ("ObjFetchXRefNum", sig_bases, {"parent_frame_class": FetchFrame}),
        ("ErrorSig", sig_bases, {"parent_frame_class": GfxStreamFrame,
                                 "flag_addr_fn_name":
                                 "_Z5error13ErrorCategoryxPKcz"}),
        ("XRefConstructNum", sig_bases, {"parent_frame_class":
                                         ConstructXRefFrame}),
        ("XRefConstructGen", sig_bases, {"parent_frame_class":
                                         ConstructXRefFrame}),
        ("XRefConstructOffset", sig_bases, {"parent_frame_class":
                                            ConstructXRefFrame}),
        ("XRefConstructId", sig_bases, {"parent_frame_class":
                                        ConstructXRefFrame}),

    ]

class PopplerNewFrameMoment(PopplerMomentSignature, NewFrameMoment):
    pass

class PopplerPTMoment(XpdfPopplerPTMoment, PopplerMomentSignature):
    parent_frame_class = PopplerPTTracker.GetObjFrame

class RecursionErrorMoment(PopplerPTMoment):
    sig_id_name = "RECURSION_ERROR"
    log_type = CallEntry
    attr_name = "pc"
    remove_when_flagged = True

    def get_lex_obj(self):
        return LexObj(LexType.ERROR)

    @classmethod
    def setup(cls):
        # rec_virtpc = 0x2bb20e  # Parser.cc:88, Object::Object()
        cls.rec_value = cls.addrs_of("recursion_error", 1)
        cls.check_values = [cls.rec_value]

class ArrayFrameReturn(ReturnSignature, PopplerPTMoment):
    sig_id_name = "ARRAY_FRAME_RETURN"
    log_type = CallEntry
    attr_name = "pc"
    pt_container_type = PDFEnum.ARRAY_END
    expected_lex_objvalue = b"]"
    expected_lex_objtype = LexType.CMD
    parent_frame_class = PopplerPTTracker.ArrayFrame

    @classmethod
    def setup(cls):
        # virtpc = 0x2bb346  # Parser.cc:104, basic block when shift() called
        # eofvirtpc = 0x2bb31f  # Parser.cc:101, getPos()
        # recursionerror = 0x2bb61f  # Parser.cc:196 Object(objError)
        cls.check_value = cls.addrs_of("array_end", 1)
        cls.eof_value = cls.addrs_of("array_end_eof", 1)
        cls.rec_error_pc = cls.addrs_of("array_end_recursion_error", 1)
        cls.check_values = [cls.eof_value, cls.rec_error_pc]

    def reset(self):
        self.eof = False
        self.recursion_error = False

    def package_pt_obj(self, obj: LexObj) -> PT:
        if self.recursion_error:
            return PT(PDFEnum.ERROR)
        elif self.eof:
            return PT(PDFEnum.EOF)
        else:
            return super(ArrayFrameReturn, self).package_pt_obj(obj)

    def get_lex_obj(self):
        return self.manager.shift_objs.obj1()

    def check_lex_obj(self, obj: LexObj) -> bool:
        if self.eof:
            return self._do_check("obj type", obj, LexType.EOF, "type")
        elif not self.recursion_error:
            return self._do_check("obj type", obj, LexType.CMD, "type") and \
                self._do_check("obj value", obj, b"]", "value")
        else:
            # nothing to enforce if there was a recursion error
            return True

    def do_log_entry(self, log_entry):
        if (is_kind(log_entry, PCEntry) and
           log_entry.pc == self.check_value) or \
           (is_kind(log_entry, CallEntry) and
            log_entry.pc in self.check_values):
            if log_entry.pc == self.eof_value:
                self.eof = True
            elif log_entry.pc == self.rec_error_pc:
                self.recursion_error = True
            self.do_flag(log_entry)

class DictKeyMoment(PopplerPTMoment):
    sig_id_name = "DICT_KEY"
    remove_when_flagged = True
    pt_container_type = PDFEnum.DICT_KEY
    parent_frame_class = PopplerPTTracker.DictFrame

    def __init__(self, key_obj=None):
        # when DICT_KEY is registered by DictFrame or by DICT_VALUE,
        # the DICT_KEY object is obj1, but it it is registered by
        # a DICT_KEY moment, which happens when there is an error
        # parsing the previous key, the key object is obj2() b/c
        # shift() is called after the dict key error moment happens
        # and before the next DICT_KEY moment
        super(DictKeyMoment, self).__init__()
        self.first_lex_obj = key_obj if key_obj else self.first_lex_obj

    @classmethod
    def setup(cls):
        # self.dict_start_obj = dict_start_obj
        # virtpc = 0x2bb3f9  # Parser.cc:123
        # not_name_err = 0x2bb4c8  # Parser.cc:112 Parser::getPos()
        # other_err = 0x2bb61f  # Parser.cc:196 Object(objError)
        cls.dict_key = cls.addrs_of("dict_key", 1)
        cls.not_name_err_pc = cls.addrs_of("dict_key_not_name", 1)
        cls.other_err_pc = cls.addrs_of("dict_key_other_err", 1)
        cls.check_values = [cls.dict_key, cls.not_name_err_pc,
                            cls.other_err_pc]

    def reset(self):
        self.error = False
        self.not_name = False

    def do_log_entry(self, log_entry):
        if is_kind(log_entry, PCEntry) and \
           self.dict_key == log_entry.pc:
            self.do_flag(log_entry)
        elif is_kind(log_entry, CallEntry):
            if self.not_name_err_pc == log_entry.pc:
                self.not_name = True
                self.do_flag(log_entry)
            elif self.other_err_pc == log_entry.pc:
                self.error = True
                self.do_flag(log_entry)

    def package_pt_obj(self, obj):
        self.pt_container_type = PDFEnum.DICT_KEY_ERROR \
            if self.error or self.not_name else PDFEnum.DICT_KEY
        return super(DictKeyMoment, self).package_pt_obj(obj)

    def flag_enable_sigs(self):
        if self.not_name:
            next_sig = self.manager.sig_from_id(SigID.DICT_KEY,
                                                self.manager.shift_objs.obj2())
        elif not self.error:
            next_sig = self.manager.sig_from_id(SigID.DICT_VALUE)
        if next_sig:
            self.parent_sig_enable_frame.add_ghostsite_sig(next_sig)

class Int64Obj(PopplerValueSignature):
    sig_id_name = "INT64_VAL"
    flag_addr_name = "obj_int64_val"

class NewParserXrefID(PopplerValueSignature):
    sig_id_name = "NEW_PARSER_XREF_ID"
    parent_frame_class = PopplerPTTracker.NewParserFrame
    flag_addr_name = "lexer_xref_id"
    remove_when_flagged = False
    log_type = MemEntry
    attr_name = "pc"
    struct_format = "Q"

    def flag(self):
        self.parent_frame.register_xref_id(
            self.unpack_val(self.flagged_entry.value)
        )

# not really using this for anything at the moment,
# but i'm curious as to whether poppler creates
# multiple XRef instances/XRef copies
class NewXrefID(PopplerMomentSignature):
    sig_id_name = "NEW_XREF"
    flag_addr_name = "new_xref_id"
    remove_when_flagged = False
    log_type = MemEntry
    attr_name = "pc"

    @dataclasses.dataclass(repr=False)
    class XRefInfo(DataContext):
        xref_id: str
        stack_str: str

    def reset(self):
        self.all_objs = []

    def flag(self):
        # addr is address of XRef->capacity field
        # print("New XRef at %x" % self.flagged_entry.addr - 24)
        self.all_objs.append(
            self.XRefInfo("%x" % (self.flagged_entry.addr - 24),
                          str(self.manager.ml.stack))
        )

class NewParserMoment(XpdfPopplerNewParserMoment):
    lib_name = "libpoppler.so.94"
    push_frame_class = PopplerPTTracker.NewParserFrame
    fn_names = ["_ZN6ParserC1EP4XRefP6Streamb",
                "_ZN6ParserC1EP4XRefP6Objectb",
                "_ZN6ParserC2EP4XRefP6Streamb",
                "_ZN6ParserC2EP4XRefP6Objectb"]

    class Where(IntEnum):
        UNKNOWN = 0
        PARSE_ENTRY = auto()
        OBJ_STREAM_0 = auto()
        OBJ_STREAM_1 = auto()
        READ_XREF = auto()
        XREF_FETCH = auto()
        CONSTRUCT_XREF = auto()
        LINEARIZATION = auto()
        GFX_STREAM = auto()
        HINTS = auto()

    @classmethod
    def setup(cls):
        cls.parse_entry_start = cls.addrs_of("xref_parse_entry_start", 1)
        cls.parse_entry_end = cls.addrs_of("xref_parse_entry_end", 1)
        cls.obj_stream = cls.addrs_of("xref_obj_new_parser")
        cls.read_xref_start = cls.addrs_of("xref_read_start", 1)
        cls.read_xref_end = cls.addrs_of("xref_read_end", 1)
        cls.xref_fetch_start = cls.addrs_of("xref_fetch_start", 1)
        cls.xref_fetch_end = cls.addrs_of("xref_fetch_end", 1)
        cls.xref_fetch_obj = cls.addrs_of("xref_fetch", 1)
        cls.construct_xref_start = cls.addrs_of("construct_xref_start", 1)
        cls.construct_xref_end = cls.addrs_of("construct_xref_end", 1)
        cls.linearization_start = cls.addrs_of("linearization_start", 1)
        cls.linearization_end = cls.addrs_of("linearization_end", 1)
        cls.hints_new = cls.addrs_of("hint_new_parser", 1)
        cls.gfx_new = cls.addrs_of("gfx_display_new_parser", 1)

    def flag(self):
        # lookup address of caller
        callsite = self.manager.ml.stack.top()
        pc = callsite.pc

        def _in_range(start, end):
            return start <= pc and pc < end
        if _in_range(self.parse_entry_start, self.parse_entry_end):
            self.where = self.Where.PARSE_ENTRY
        elif _in_range(self.read_xref_start, self.read_xref_end):
            self.where = self.Where.READ_XREF
        elif _in_range(self.construct_xref_start, self.construct_xref_end):
            self.where = self.Where.CONSTRUCT_XREF
        elif pc == self.obj_stream[0]:
            self.where = self.Where.OBJ_STREAM_0
        elif pc == self.obj_stream[1]:
            self.where = self.Where.OBJ_STREAM_1
        elif _in_range(self.linearization_start, self.linearization_end):
            self.where = self.Where.LINEARIZATION
        elif _in_range(self.xref_fetch_start, self.xref_fetch_end):
            self.where = self.Where.XREF_FETCH
        elif pc == self.gfx_new:
            self.where = self.Where.GFX_STREAM
        elif pc == self.hints_new:
            self.where == self.Where.HINTS
        else:
            self.where = self.Where.UNKNOWN
        # now determine container type
        if self.where in [self.Where.LINEARIZATION, self.Where.HINTS,
                          self.Where.XREF_FETCH]:
            self.container = PDFEnum.INDIRECT_OBJ
        elif self.where in [self.Where.OBJ_STREAM_0, self.Where.OBJ_STREAM_1]:
            self.container = PDFEnum.STREAM_CONTENTS
        elif self.where == self.Where.PARSE_ENTRY:
            self.container = PDFEnum.XREF_OBJ
        elif self.where == self.Where.CONSTRUCT_XREF:
            self.container = PDFEnum.CONTAINER
        elif self.where == self.Where.GFX_STREAM:
            self.container = PDFEnum.GFX_IMAGE_STREAM
        elif self.where == self.Where.READ_XREF:
            self.container = PDFEnum.XREF_TABLE
        else:
            self.container = PDFEnum.UNKNOWN

class NewParserIdMoment(PopplerMomentSignature):
    sig_id_name = "NEW_PARSER_ID"
    log_type = MemEntry
    attr_name = "pc"
    remove_when_flagged = True
    parent_frame_class = PopplerPTTracker.NewParserFrame

    @classmethod
    def setup(cls):
        # cls.new_parser_stream_id = cls.addrs_of("new_parser_stream_id", 1)
        # cls.new_parser_obj_id = cls.addrs_of("new_parser_obj_id", 1)
        cls.new_parser_stream_id_2 = cls.addrs_of("new_parser_stream_id_2", 1)
        cls.new_parser_obj_id_2 = cls.addrs_of("new_parser_obj_id_2", 1)
        # cls.check_pcs = [cls.new_parser_stream_id, cls.new_parser_obj_id]
        cls.check_values = [cls.new_parser_stream_id_2,
                            cls.new_parser_obj_id_2]

    def reset(self):
        self.obj_id = None
        self.flagged = False

    def flag(self):
        # we generally use inlineImg as the parser ID (but here we use
        # allowStreams because it is accessed before lexer.getObj) ,
        # so add the difference between the offsets of the two
        # instance fields
        if self.flagged_entry.typ == self.flagged_entry.READ:
            self.obj_id = self.flagged_entry.value + 0xe0
        else:
            # some versions of poppler are hooked differently
            self.obj_id = self.flagged_entry.addr
        self.parent_frame.register_parser_id(self.obj_id)

class GetObjError(PopplerMomentSignature):
    sig_id_name = "GET_OBJ_ERROR"
    remove_when_flagged = True

    @classmethod
    def setup(cls):
        cls.check_values = cls.addrs_of("array_end_recursion_error")

    def flag(self):
        self.parent_frame.set_pt_as(PDFEnum.ERROR)

class IntFrameReturn(ReturnSignature, PopplerMomentSignature):
    sig_id_name = "INT_FRAME_RETURN"
    remove_when_flagged = True
    log_type = CallEntry
    attr_name = "pc"
    flag_addr_name = "int_frame_ret"

    @classmethod
    def setup(cls):
        cls.check_values = cls.addrs_of("int_frame_ret")

    def reset(self):
        self.is_reference = False
        self.is_error = False

    def flag(self):
        idx = self.check_values.index(self.flagged_entry.pc)
        self.is_reference = idx == 0
        self.is_error = idx == 2

class XRefStmSig(XRefConstructSigBase, PopplerMomentSignature):
    parent_frame_class = ReadXRefStreamFrame

    def flag(self):
        getattr(self.parent_frame, f"register_{self.entry_field}")(
            self.unpack_val(self.flagged_entry.value), self.flagged_entry.pc
        )

class XrefStreamOffset(XRefStmSig):
    sig_id_name = "XREF_STREAM_ENTRY_OFFSET"
    flag_addr_name = "xref_stm_section_offset"
    entry_field = "offset"
    struct_format = "Q"

class XrefStreamGen(XRefStmSig):
    sig_id_name = "XREF_STREAM_ENTRY_GEN"
    flag_addr_name = "xref_stm_section_gen"
    entry_field = "gen"
    struct_format = "Q"

class XrefStreamNum(XRefStmSig):
    sig_id_name = "XREF_STREAM_ENTRY_NUM"
    flag_addr_name = "xref_stm_section_idx2"
    entry_field = "num"
    struct_format = "i"

class GfxStreamSig(XpdfPopplerGfxStreamSig, PopplerMomentSignature):
    parent_frame_class = PopplerPTTracker.GfxStreamFrame
    reg_names = XpdfPopplerGfxStreamSig.reg_names
    reg_names["gfx_update_display"] = "register_update_display"
    reg_names["gfx_command_aborted"] = "register_command_aborted",

# embedded CMap/CIDFont parsing -- see also CharCodeToUnicode::parseCMap1, CharCodeToUnicode.cc


"""\
Tensorflow skin lesion classification example
"""
import argparse
import os
import random
import sys
from datetime import datetime

import imgaug.augmenters as iaa
import numpy as np
# os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import optimizers

import models
import utils
from dataset import ISICClassification

# Set seed value
seed_value = 50
os.environ['PYTHONHASHSEED'] = str(seed_value)
random.seed(seed_value)
np.random.seed(seed_value)
tf.random.set_seed(seed_value)

def main(args):
    # Print settings
    for k, v in vars(args).items():
        print(f'{k}: {v}')

    display_step = 5
    num_classes = 8
    size = (224, 224, 3)  # size of images

    # Runtime initialization will not allocate all memory on GPU
    physical_devices = tf.config.list_physical_devices('GPU')
    try:
        tf.config.experimental.set_memory_growth(physical_devices[0], True)
    except:
        # Invalid device or cannot modify virtual devices once initialized.
        pass
    # Create checkpoints dir
    os.makedirs('saved_models', exist_ok=True)

    optimizer = optimizers.SGD(learning_rate=args.learning_rate, momentum=0.9)
    loss_fn = keras.losses.SparseCategoricalCrossentropy(from_logits=False)

    # model = models.vgg16(input_shape=size, num_classes=num_classes, classifier_activation='softmax')
    model = models.resnet50(input_shape=size, num_classes=num_classes, classifier_activation='softmax')
    model.build(input_shape=size)
    model.summary()

    if args.checkpoints:
        if os.path.exists(args.checkpoints):
            print(f'Loading checkpoints: {args.checkpoints}')
            model.load_weights(args.checkpoints)
        else:
            print(f'Checkpoints `{args.checkpoints}` not found', file=sys.stderr)

    os.makedirs("logs/scalars/", exist_ok=True)
    logdir = "logs/scalars/" + datetime.now().strftime("%Y%m%d-%H%M%S") + f"-{args.name}"
    summary_writer = tf.summary.create_file_writer(logdir)

    if args.train:
        # Same augs as C++
        train_aug = iaa.Sequential([
            iaa.Resize(size=size[:-1], interpolation='cubic'),
            iaa.Fliplr(p=0.5),
            iaa.Flipud(p=0.5),
            iaa.Rotate(rotate=(-180, 180)),
            iaa.AdditivePoissonNoise(lam=(0, 10)),
            iaa.GammaContrast(gamma=(.8, 1.5)),
            iaa.GaussianBlur(sigma=(.0, .8)),
            iaa.CoarseDropout(p=(.02, .1), size_percent=(0.02, 0.05), per_channel=0.5),
        ])

        val_aug = iaa.Sequential([iaa.Resize(size=size[:-1], interpolation='cubic')])

        training_dataset = ISICClassification(args.dataset, 'training', args.batch_size, train_aug)
        training_tfdata = training_dataset.map_samples(args.epochs)
        training_iter = iter(training_tfdata)

        validation_dataset = ISICClassification(args.dataset, 'validation', args.batch_size, val_aug, shuffle=False)
        validation_tfdata = validation_dataset.map_samples(args.epochs)
        validation_iter = iter(validation_tfdata)

        train_loss = tf.keras.metrics.Mean(name='train_loss')
        train_metric = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')
        val_metric = tf.keras.metrics.SparseCategoricalAccuracy(name='val_accuracy')

        best_accuracy = 0.
        for e in range(1, args.epochs + 1):
            train_loss.reset_states()
            train_metric.reset_states()
            val_metric.reset_states()

            total_preds = []
            total_labels = []
            for step in range(1, len(training_dataset)):
                images, labels = next(training_iter)

                # Run the optimization to update W and b values
                with tf.GradientTape() as tape:
                    pred = model(images)
                    loss = loss_fn(labels, pred)
                total_preds.append(pred)
                total_labels.append(labels)

                gradients = tape.gradient(loss, model.trainable_variables)

                # Update W and b following gradients
                optimizer.apply_gradients(zip(gradients, model.trainable_variables))

                # Log loss and metric
                train_loss.update_state(loss)
                train_metric.update_state(labels, pred)
                if step % display_step == 0:
                    print("\rTraining {:d}/{:d} (batch {:d}/{:d}) - Loss: {:.4f} - Accuracy: {:.4f}".format(
                        e, args.epochs, step, len(training_dataset), train_loss.result(), train_metric.result()
                    ), end="", flush=True)

            cm = utils.calculate_confusion_matrix(tf.concat(total_labels, axis=0), tf.concat(total_preds, axis=0))
            with summary_writer.as_default():
                tf.summary.scalar('loss/' + train_loss.name, train_loss.result(), step=e - 1)
                tf.summary.scalar('accuracy/' + train_metric.name, train_metric.result(), step=e - 1)
                tf.summary.image("cm/training_cm", cm, step=e)

            total_preds = []
            total_labels = []

            # Do validation
            print("\nValidation {:d}/{:d}".format(e, args.epochs), end="", flush=True)
            for step in range(1, len(validation_dataset)):
                images, labels = next(validation_iter)
                pred = model(images)
                val_metric.update_state(labels, pred)
                total_preds.append(pred)
                total_labels.append(labels)

            cm = utils.calculate_confusion_matrix(tf.concat(total_labels, axis=0), tf.concat(total_preds, axis=0))
            with summary_writer.as_default():
                tf.summary.scalar('accuracy/' + val_metric.name, val_metric.result(), step=e - 1)
                tf.summary.image("cm/validation_cm", cm, step=e)

            # Compute accuracy and save checkpoints
            accuracy = val_metric.result()
            print(" - Accuracy: {:.4f}".format(accuracy), flush=True)

            if accuracy > best_accuracy:
                print(f"Saving checkpoints (accuracy: {accuracy:.4f} > {best_accuracy:.4f})", flush=True)
                best_accuracy = accuracy
                model.save_weights(f'saved_models/{args.name}.h5')

    if args.test:
        # Test model on test set
        test_aug = iaa.Sequential([iaa.Resize(size=size[:-1], interpolation='cubic')])
        test_dataset = ISICClassification(args.dataset, 'test', args.batch_size, test_aug)
        test_tfdata = test_dataset.map_samples(1)
        tensorboard = keras.callbacks.TensorBoard(log_dir=logdir)
        results = model.evaluate(test_tfdata, verbose=1, callbacks=[tensorboard])
        print("Test set loss and accuracy:", results)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('dataset', metavar='DATASET_YAML_PATH')
    parser.add_argument('-e', '--epochs', type=int, metavar='INT', default=50)
    parser.add_argument('-b', '--batch-size', type=int, metavar='INT', default=32)
    parser.add_argument('-l', '--learning-rate', type=float, metavar='FLOAT', default=1e-3)
    parser.add_argument('-n', '--name', metavar='DIR', help='Experiment name', default='isic_class')
    parser.add_argument('-c', '--checkpoints', metavar='CHECKPOINTS_PATH', help='Continue training from a checkpoint')
    parser.add_argument('--train', dest='train', action='store_true', help='Do train')
    parser.add_argument('--no-train', dest='train', action='store_false', help='Do not train')
    parser.add_argument('--test', dest='test', action='store_true', help='Do inference')
    parser.add_argument('--no-test', dest='test', action='store_false', help='Do not inference')
    parser.set_defaults(train=True, test=False)

    main(parser.parse_args())


import logging
from collections import defaultdict

logger = logging.getLogger(__name__)

def default_params():
    params = defaultdict(int)
    params["content_weight"] = 1.0
    params["token_budget"] = 200
    params["views_per_doc"] = 20
    params["sample_factor"] = 5
    params["sample_type"] = "random"
    params["min_words_per_view"] = 5
    return params

def _get_params():
    params = {}

    # we adjust budgets so that the average predicted summary words
    # is close to the validation set average reference summary words
    params["pubmed"] = {}
    params["pubmed"]["intrinsic_importance_model_id"] = "cku41vkj"
    params["pubmed"][
        "intrinsic_importance_model_url"
    ] = "https://www.dropbox.com/s/8birb30qhjxyqnr/model-cku41vkj%20v0.zip?dl=1"
    params["pubmed"][
        "dataset_url"
    ] = "https://www.dropbox.com/s/4vh8hfoio7r4vfl/factorsum-pubmed.zip?dl=1"
    params["pubmed"]["token_budget"] = 205
    params["pubmed"]["source_token_budget"] = 205
    params["pubmed"]["no_content_fixed_budget_adjust"] = 8
    params["pubmed"]["no_content_oracle_budget_adjust"] = 11
    params["pubmed"]["no_content_pegasus_budget_adjust"] = 7
    params["pubmed"]["no_content_bigbird_budget_adjust"] = 12
    params["pubmed"]["source_content_fixed_budget_adjust"] = 12
    params["pubmed"]["source_content_oracle_budget_adjust"] = 16
    params["pubmed"]["oracle_content_fixed_budget_adjust"] = 14
    params["pubmed"]["pegasus_content_fixed_budget_adjust"] = 30
    params["pubmed"]["bigbird_content_fixed_budget_adjust"] = 45
    params["pubmed"]["pegasus_content_pegasus_budget_adjust"] = 17
    params["pubmed"]["bigbird_content_bigbird_budget_adjust"] = 22
    params["pubmed"]["dataset_path"] = "scientific_papers"

    params["arxiv"] = {}
    params["arxiv"]["intrinsic_importance_model_id"] = "rs86h5g0"
    params["arxiv"][
        "intrinsic_importance_model_url"
    ] = "https://www.dropbox.com/s/apgdmfqqwz22p7e/model-rs86h5g0%20v0.zip?dl=1"
    params["arxiv"][
        "dataset_url"
    ] = "https://www.dropbox.com/s/tzlcptrgwu41un8/factorsum-arxiv.zip?dl=1"
    params["arxiv"]["token_budget"] = 165
    params["arxiv"]["source_token_budget"] = 165
    params["arxiv"]["no_content_fixed_budget_adjust"] = 2
    params["arxiv"]["no_content_oracle_budget_adjust"] = 4
    params["arxiv"]["no_content_pegasus_budget_adjust"] = 6
    params["arxiv"]["no_content_bigbird_budget_adjust"] = 5
    params["arxiv"]["source_content_fixed_budget_adjust"] = 2
    params["arxiv"]["source_content_oracle_budget_adjust"] = 4
    params["arxiv"]["oracle_content_fixed_budget_adjust"] = 7
    params["arxiv"]["pegasus_content_fixed_budget_adjust"] = 10
    params["arxiv"]["bigbird_content_fixed_budget_adjust"] = 15
    params["arxiv"]["pegasus_content_pegasus_budget_adjust"] = 15
    params["arxiv"]["bigbird_content_bigbird_budget_adjust"] = 12
    params["arxiv"]["dataset_path"] = "scientific_papers"

    params["govreport"] = {}
    params["govreport"]["intrinsic_importance_model_id"] = "2oklw1wt"
    params["govreport"][
        "intrinsic_importance_model_url"
    ] = "https://www.dropbox.com/s/tramsr8g27smuju/model-2oklw1wt%20v0.zip?dl=1"
    params["govreport"][
        "dataset_url"
    ] = "https://www.dropbox.com/s/vc5yyooa2o6euyj/factorsum-govreport.zip?dl=1"
    params["govreport"]["token_budget"] = 648
    params["govreport"]["source_token_budget"] = 648
    params["govreport"]["no_content_fixed_budget_adjust"] = 8
    params["govreport"]["no_content_oracle_budget_adjust"] = 8
    params["govreport"]["source_content_fixed_budget_adjust"] = -24
    params["govreport"]["source_content_oracle_budget_adjust"] = -16
    params["govreport"]["oracle_content_fixed_budget_adjust"] = -10
    params["govreport"]["no_content_bart-large_budget_adjust"] = 50
    params["govreport"]["bart-large_content_fixed_budget_adjust"] = 10
    params["govreport"]["bart-large_content_oracle_budget_adjust"] = 10
    params["govreport"]["bart-large_content_bart-large_budget_adjust"] = 50
    params["govreport"]["dataset_path"] = "ccdv/govreport-summarization"

    return params

def model_params(domain_name, budget_type=None, content_type=None, **kwargs):
    logger.debug(f"Getting model parameters for domain '{domain_name}'.")
    _default_params = default_params()
    _model_params = _get_params().get(domain_name)

    if _model_params is None:
        logger.warning(
            f"Config for domain '{domain_name}' not found. Creating a new config.")
        _model_params = {}

    _model_params["domain_name"] = domain_name
    _model_params.update(_default_params)

    # override params if values are not None
    for key, val in kwargs.items():
        if val is not None:
            _model_params[key] = val

    token_budget = _model_params.get("token_budget")
    # apply task-specific budget adjustment, if budget is not explicitly set
    if "token_budget" not in kwargs and budget_type and content_type:
        if token_budget is not None:
            budget_adjust_key = f"{content_type}_content_{budget_type}_budget_adjust"
            budget_adjust = _model_params.get(budget_adjust_key, 0)
            _model_params["token_budget"] = token_budget + budget_adjust

    # set source token budget for source content guidance
    if token_budget is not None and content_type and content_type == "source":
        source_budget = _model_params.get('source_token_budget')
        if source_budget is None:
            source_budget = _model_params["token_budget"]
            _model_params['source_token_budget'] = source_budget

    logger.debug(f"Model parameters for domain '{domain_name}': {_model_params}")
    return _model_params

def main() -> None:
    logging.basicConfig(
        level=logging.DEBUG,
        format='%(asctime)s %(levelname)s %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S',
        filename="basic.log"
    )

    logger.debug("This is a debug message in main().")
    logger.info("This is an info message in main().")
    logger.warning("This is a warning message in main().")

    # Logically placed messages within the main function
    for domain in ["pubmed", "arxiv", "govreport"]:
        params = model_params(domain)
        logger.info(f"Using model parameters for domain '{domain}': {params}")

    logger.debug("All tasks are complete in the main function.")
    logger.debug("1st task complete in the main function.")

if __name__ == "__main__":
    main()


from django.shortcuts import render
import pickle
import json
import pandas as pd

# load the model from disk
model = pickle.load(open('model.pkl', 'rb'))
map_add = json.load(open('map.json', 'r'))

def predict(Address, Size):
    X = pd.DataFrame([[Address, Size]], columns=['Address', 'Size(Acres)'])
    X['Address'] = X['Address'].map(map_add)
    prediction = model.predict(X)
    return int(prediction)

def home(request):
    params = {'add': list(map_add.keys())}
    return render(request, 'HouseRentPrediction/index.html', params)

def index(request):
    address = str(request.POST.get('address', 'others'))
    size = int(request.POST.get('size', '500'))
    pred = predict(address, size)
    params = {'add': list(map_add.keys()),
              'pred': f"Monthly Rent for {size} sqft in {address} is Rs {pred}"}
    return render(request, 'HouseRentPrediction/index.html', params)


import os
import csv
import io
import codecs

import utils
from core.file import File
from utils import LOG

class DupFinder:
    def __init__(self, path_list, filter_list):
        self.path_list = path_list
        self.filter_list = filter_list
        self.progress = 0
        self.step = None
        self.total = None

    def find(self):
        LOG.info("%s walk start", self.__class__.__name__)
        walker = Walker()
        self.__update_step(walker)
        file_instances = walker.walk(self.path_list)
        LOG.info("%s walk end", self.__class__.__name__)
        prev_filter = self.filter_list[0]
        prev_filter.set_files(file_instances)
        self.total = len(file_instances)
        self.__update_step(prev_filter)
        prev_filter.find()
        for _filter in self.filter_list[1:]:
            _filter.set_files(prev_filter.filtered_files)
            self.__update_step(_filter)
            _filter.find()
            prev_filter = _filter

    def __update_step(self, instance):
        self.step = instance

    def get_progress(self):
        return self.step.progress

    def get_total(self):
        return self.total

    def get_step(self):
        step_index = "0"
        try:
            step_index = str(self.filter_list.index(self.step) + 1)
        except ValueError:
            pass
        total_step = len(self.filter_list)
        step_name = self.step.__class__.__name__
        return "Step {0}/{1} {2}".format(step_index, total_step, step_name)

    def dump2file(self, output_file):
        LOG.debug("%s dump2file", self.__class__.__name__)
        if utils.get_python_version() == 3:
            fp = codecs.open(output_file, "w", "utf-8")
        else:
            fp = open(output_file, 'w')
        try:
            for files in self.sorted_dup_files:
                fp.write("================\n")
                for _file in files:
                    size = utils.size_renderer(_file.size)
                    fp.write("Size: {0}, File: {1}\n".format(size, _file.path))
        finally:
            fp.close()

    def dump2csv(self, output_csv):
        LOG.debug("%s dump2csv", self.__class__.__name__)
        rows = list()
        for files in self.sorted_dup_files:
            data = [utils.size_renderer(files[0].size)]
            #data.append(files[0].size)
            data.extend([_file.path for _file in files])
            rows.append(data)
        with open(output_csv, 'wb') as f:
            writer = UnicodeCSVWriter(f)
            writer.writerows(rows)

    @property
    def dup_files(self):
        return self.filter_list[-1].dup_files

    @property
    def sorted_dup_files(self, reverse=True):
        df = self.filter_list[-1].dup_files
        sort_files = sorted(df, key=lambda _files: _files[0].size,
                            reverse=reverse)
        return sort_files

    @property
    def character_table(self):
        return self.filter_list[-1].char_table

    @property
    def dup_size(self):
        total_size = 0
        for _file in self.filter_list[-1].filtered_files:
            total_size = total_size + _file.size
        return total_size

class Walker:
    def __init__(self):
        self.progress = 0

    def get_progress(self):
        return self.progress

    def walk(self, path_list):
        file_instances = list()
        for path in path_list:
            file_instances.extend(self.__path_walk(path))
        return file_instances

    def __path_walk(self, path):
        file_instances = list()
        for (root, dirs, files) in os.walk(path):
#            LOG.debug("{0} {1} {2}".format(root, dirs, files))
            for _file in files:
                filepath = os.path.join(root, _file)
                if os.path.exists(filepath):
                    file_instance = File(filepath)
                    file_instances.append(file_instance)
                    self.progress = self.progress + 1
        return file_instances

class UnicodeCSVWriter:
    """
    Python 3 version CSV Writer
    A CSV writer which will write rows to CSV file "f",
    which is encoded in the given encoding.
    """

    def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
        # Redirect output to a queue
        try:
            # python 2.7
            import StringIO
            self.queue = StringIO.StringIO()
        except:
            # python 3
            self.queue = io.StringIO()
        self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
        self.stream = f
        self.encoder = codecs.getincrementalencoder(encoding)()

    def writerow(self, row):
        try:
            # python 3
            self.writer.writerow([s for s in row])
        except TypeError:
            # python 2.7
            import StringIO
            self.queue = StringIO.StringIO()
            unicode_row = [unicode(str(s).encode("utf-8")) for s in row]
            self.writer.writerow(unicode_row)
        # Fetch UTF-8 output from the queue ...
        data = self.queue.getvalue()
        # ... and reencode it into the target encoding
        try:
            # python 3
            data = self.encoder.encode(data)
        except UnicodeDecodeError:
            # python 2.7
            data = data.decode("utf-8")
            data = self.encoder.encode(data)
        # write to the target stream
        self.stream.write(data)
        # empty queue
        self.queue.truncate(0)

    def writerows(self, rows):
        for row in rows:
            self.writerow(row)


import asyncio
import logging
from motor import motor_asyncio
from ... import di

logger = logging.getLogger(__name__)

@di.desc('storage', reg=False)
class MongodbInterface:
    """
    https://github.com/mongodb/motor
    """

    def __init__(self,
                 uri='localhost',
                 db_name='bots',
                 user_collection_name='user',
                 session_collection_name='session',
                 ):
        self.cx = None
        self.db = None
        self.session_collection = None
        self.user_collection = None
        self.uri = uri
        self.db_name = db_name
        self.session_collection_name = session_collection_name
        self.user_collection_name = user_collection_name

    async def start(self):
        loop = asyncio.get_event_loop()
        logger.debug('start')
        self.cx = motor_asyncio.AsyncIOMotorClient(self.uri, io_loop=loop)
        logger.debug(' create client for: {}'.format(self.uri))
        self.db = self.cx.get_database(self.db_name)
        logger.debug(' get db: {}'.format(self.db_name))
        self.session_collection = self.db.get_collection(self.session_collection_name)
        logger.debug(' get session collection: {}'.format(self.session_collection_name))
        self.user_collection = self.db.get_collection(self.user_collection_name)
        logger.debug(' get user collection: {}'.format(self.user_collection_name))

    async def stop(self):
        self.cx = None
        self.db = None
        self.session_collection = None
        self.user_collection = None

    async def clear_collections(self):
        await self.session_collection.drop()
        self.session_collection = self.db.get_collection(self.session_collection_name)
        await self.user_collection.drop()
        self.user_collection = self.db.get_collection(self.user_collection_name)

    async def get_session(self, **kwargs):
        session = await self.session_collection.find_one(kwargs)
        if not session:
            return None
        session.pop('lastModified', None)
        return session

    async def set_session(self, session):
        logger.info('set_session {}'.format(session))
        if '_id' in session:
            _id = session['_id']
            session.pop('lastModified', None)
            res = await self.session_collection.update_one(
                {'_id': _id},
                {
                    '$set': session,
                    '$currentDate': {
                        'lastModified': True
                    },
                },
            )

            if res.matched_count != 0:
                return _id

        return await self.session_collection.insert(session)

    async def new_session(self, user, **kwargs):
        logger.info('new_session for {}'.format(user))
        kwargs['user_id'] = kwargs.get('user_id', user['_id'])
        kwargs['stack'] = kwargs.get('stack', [])
        _id = await self.session_collection.insert(kwargs)
        return await self.session_collection.find_one({'_id': _id})

    async def get_user(self, **kwargs):
        if 'id' in kwargs:
            kwargs['_id'] = kwargs.get('id', None)
            del kwargs['id']
        user = await self.user_collection.find_one(kwargs)
        if not user:
            return None
        user.pop('lastModified', None)
        return user

    async def set_user(self, user):
        logger.info('set_user {}'.format(user))
        if '_id' in user:
            _id = user['_id']
            user.pop('lastModified', None)
            res = await self.user_collection.update_one(
                {'_id': _id},
                {
                    '$set': user,
                    '$currentDate': {
                        'lastModified': True
                    },
                },
            )
            if res.matched_count != 0:
                return _id
        return await self.user_collection.insert(user)

    # TODO: should be able to process dictionary
    async def new_user(self, **kwargs):
        logger.debug('store new user {}'.format(kwargs))
        _id = await self.user_collection.insert(kwargs)
        return await self.user_collection.find_one({'_id': _id})


""" This file tests the outputs of the CleanFlowline function
"""
import os
import pytest
import arcpy

from fg_tests_utils import *
from _05_CleanFlowline import CleanFlowline

# Define test parameters
output_workspace = "//mvrdfs/egis/Work/Office/Regional/ERDC/EMRRP_Sediment/Methods/FluvialGeomorph/tests/data/test.gdb"
stream_network   = os.path.join(output_workspace, "stream_network_edited")

# Create test fixtures
@pytest.fixture(scope = "module")
def flowline():
    # Call the CleanFlowline function with test data
    CleanFlowline(output_workspace, stream_network)
    # Return the flowline feature class
    flowline = arcpy.MakeFeatureLayer_management(
                   in_features = os.path.join(output_workspace,
                                              "flowline"),
                   out_layer = "flowline")
    return flowline

@pytest.fixture(scope = "module")
def flowline_stats(flowline):
    stat_fields = [["Name", "FIRST"]]
    case_field = "Name"
    fc_stat_table = fc_stats(workspace = output_workspace,
                             fc = flowline,
                             stat_fields = stat_fields,
                             case_field = case_field)
    yield fc_stat_table
    arcpy.Delete_management(
                  in_data = os.path.join(output_workspace, "fc_stat_table"))

# Test if feature class exists
def test_fc_exists_flowline(flowline):
    assert "flowline" in list_fcs(output_workspace)

# Test if field exists
def test_field_exists_Name(flowline):
    assert "Name" in list_fields(flowline)

# Test attribute values
def test_Name_first(flowline_stats):
    # The value of `Name` should be "Sinsinawa"
    assert field_stat(fc_stat_table = flowline_stats,
                      stat_field = "Name",
                      stat = "FIRST",
                      route_id_field = "Name",
                      route_name = "Sinsinawa") == "Sinsinawa"


# coding: utf-8
'''
Developer:Jose Sanchez
Date: 04/14/2020
notes: this will be our main code that will execute:
1.sonar distance check for obstacle avoidance
2.will keep track of the path
3.drive the motor and steer
4. use open CV for image deteccting along with zbar
5. if time allows connet to google server

'''
# import the necessary packages for video
from imutils.video import VideoStream
from pyzbar import pyzbar
import datetime
import imutils
import cv2
import sys

from time import sleep
import datetime
#from firebase import firebase

#import urllib2, urllib, httplib
import json
import os
from functools import partial

exit = False

#----------------
#this is for time and passing arg
import argparse
import time
#this is for threads
import threading
from threading  import Lock,Thread
#------------------------------------------------------------------------------------------motors
import RPi.GPIO as GPIO
import time

#a couple of delay constants time to
leg = .33# this tells me to keep it on
turn = 0.33# how long the motors are on

#set up control pins for motor driver
STBY = 31
AIN1 = 33
AIN2 = 35
PWMA = 37
BIN1 = 32
BIN2 = 36
PWMB = 38

GPIO.setmode(GPIO.BOARD)#use board pin numbers

#led
Blue = 16
Green = 22
Red = 40

#-----------------audio
class Buzzer(object):
 def __init__(self):
  GPIO.setmode(GPIO.BOARD)
  self.buzzer_pin = 29 #set to GPIO pin 5
  GPIO.setup(self.buzzer_pin, GPIO.IN)
  GPIO.setup(self.buzzer_pin, GPIO.OUT)
  print("buzzer ready")

 def __del__(self):
  class_name = self.__class__.__name__
  print (class_name, "finished")

 def buzz(self,pitch, duration):   #create the function “buzz” and feed it the pitch and duration)

  if(pitch==0):
   time.sleep(duration)
   return
  period = 1.0 / pitch     #in physics, the period (sec/cyc) is the inverse of the frequency (cyc/sec)
  delay = period / 2     #calcuate the time for half of the wave
  cycles = int(duration * pitch)   #the number of waves to produce is the duration times the frequency

  for i in range(cycles):    #start a loop from 0 to the variable “cycles” calculated above
   GPIO.output(self.buzzer_pin, True)   #set pin 18 to high
   time.sleep(delay)    #wait with pin 18 high
   GPIO.output(self.buzzer_pin, False)    #set pin 18 to low
   time.sleep(delay)    #wait with pin 18 low

 def play(self, tune):
  GPIO.setmode(GPIO.BOARD)
  GPIO.setup(self.buzzer_pin, GPIO.OUT)
  x=0

  print("Playing tune ",tune)
  if(tune==1):
    pitches=[262,294,330,349,392,440,494,523, 587, 659,698,784,880,988,1047]
    duration=0.1
    for p in pitches:
      self.buzz(p, duration)  #feed the pitch and duration to the function, “buzz”
      time.sleep(duration *0.5)
    for p in reversed(pitches):
      self.buzz(p, duration)
      time.sleep(duration *0.5)

  elif(tune==2):
    pitches=[262,330,392,523,1047]
    duration=[0.2,0.2,0.2,0.2,0.2,0,5]
    for p in pitches:
      self.buzz(p, duration[x])  #feed the pitch and duration to the function, “buzz”
      time.sleep(duration[x] *0.5)
      x+=1
  elif(tune==3):
    pitches=[392,294,0,392,294,0,392,0,392,392,392,0,1047,262]
    duration=[0.2,0.2,0.2,0.2,0.2,0.2,0.1,0.1,0.1,0.1,0.1,0.1,0.8,0.4]
    for p in pitches:
      self.buzz(p, duration[x])  #feed the pitch and duration to the func$
      time.sleep(duration[x] *0.5)
      x+=1

  elif(tune==4):
    pitches=[1047, 988,659]
    duration=[0.1,0.1,0.2]
    for p in pitches:
      self.buzz(p, duration[x])  #feed the pitch and duration to the func$
      time.sleep(duration[x] *0.5)
      x+=1

  elif(tune==5):
    pitches=[1047, 988,523]
    duration=[0.1,0.1,0.2]
    for p in pitches:
      self.buzz(p, duration[x])  #feed the pitch and duration to the func$
      time.sleep(duration[x] *0.5)
      x+=1

  GPIO.setup(self.buzzer_pin, GPIO.IN)

#--------------------end audio
GPIO.setup(Blue,GPIO.OUT)
GPIO.output(Blue,1)
GPIO.setup(Green,GPIO.OUT)
GPIO.output(Green,1)
GPIO.setup(Red,GPIO.OUT)
GPIO.output(Red,1)

#set the GPIO's to outputs
GPIO.setup(STBY, GPIO.OUT)
GPIO.setup(BIN1, GPIO.OUT)
GPIO.setup(AIN1, GPIO.OUT)
GPIO.setup(AIN2, GPIO.OUT)
GPIO.setup(BIN2, GPIO.OUT)
GPIO.setup(PWMA, GPIO.OUT)
GPIO.setup(PWMB, GPIO.OUT)

#set initial condiions, STBY
#is low, so no motors running
GPIO.output(STBY, GPIO.LOW)

GPIO.output(AIN1, GPIO.HIGH)
GPIO.output(AIN2, GPIO.LOW)
GPIO.output(PWMA, GPIO.HIGH)

GPIO.output(BIN1, GPIO.HIGH)
GPIO.output(BIN2, GPIO.LOW)
GPIO.output(PWMB, GPIO.HIGH)

#go into their own library, ultimately.
def go_forward(run_time):
    GPIO.output(AIN1, GPIO.LOW)
    GPIO.output(AIN2, GPIO.HIGH)
    GPIO.output(BIN1, GPIO.LOW)
    GPIO.output(BIN2, GPIO.HIGH)

    GPIO.output(STBY, GPIO.HIGH) #start
    time.sleep(run_time)
    GPIO.output(STBY, GPIO.LOW) #stop

def turn_left(run_time):
    GPIO.output(AIN1, GPIO.HIGH)
    GPIO.output(AIN2, GPIO.LOW)
    GPIO.output(BIN1, GPIO.LOW)
    GPIO.output(BIN2, GPIO.HIGH)

    GPIO.output(STBY, GPIO.HIGH) #start
    time.sleep(run_time)
    GPIO.output(STBY, GPIO.LOW) #stop

def turn_right(run_time):
    GPIO.output(AIN1, GPIO.LOW)
    GPIO.output(AIN2, GPIO.HIGH)
    GPIO.output(BIN1, GPIO.HIGH)
    GPIO.output(BIN2, GPIO.LOW)

    GPIO.output(STBY, GPIO.HIGH) #start
    time.sleep(run_time)
    GPIO.output(STBY, GPIO.LOW) #stop

def reverse(run_time):
    GPIO.output(AIN1, GPIO.HIGH)
    GPIO.output(AIN2, GPIO.LOW)
    GPIO.output(BIN1, GPIO.HIGH)
    GPIO.output(BIN2, GPIO.LOW)

    GPIO.output(STBY, GPIO.HIGH) #start
    time.sleep(run_time)
    GPIO.output(STBY, GPIO.LOW) #stop

#------------------------------------------------------------------------------------------sonar
#set GPIO Pins
GPIO_TRIGGER = 12
GPIO_ECHO = 18

#set GPIO direction (IN / OUT)
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
dist=0#global distacle value
lock = Lock()
def distance():
    while exit == False:
        global dist
        # set Trigger to HIGH
        GPIO.output(GPIO_TRIGGER, True)

        # set Trigger after 0.01ms to LOW
        time.sleep(0.00001)
        GPIO.output(GPIO_TRIGGER, False)

        StartTime = time.time()
        count = time.time()
        StopTime=time.time()
        # save StartTime
        while GPIO.input(GPIO_ECHO) == 0 and time.time()-count<0.1  and exit == False:
            StartTime = time.time()
            #print("first",time.time()-count)

        # save time of arrival
        while GPIO.input(GPIO_ECHO) == 1  and exit == False:
            StopTime = time.time()
            #print("second", time.time()-StopTime)
        # time difference between start and arrival
        TimeElapsed = StopTime - StartTime
        # multiply with the sonic speed (34300 cm/s)
        # and divide by 2, because there and back
        lock.acquire()
        dist = (TimeElapsed * 34300) / 2
        lock.release()
        #print ("Measured Distance = %.1f cm" % dist)
        time.sleep(1)

#------------------------------------------------------------------------------------------video
# initialize the video stream and allow the camera sensor to warm up
print("starting video stream..")
#vs = VideoStream(src=0).start()# this is for testing with a web cam not in use. We didn't have anymore equipment
vs = VideoStream(usePiCamera=True).start()
time.sleep(2.0)

#------------------------------------------------------------------------------------------

path= list()# global list so that we can keep track of the paths we are on

#define a function that will capture video for us

def imageRec():
    #wrapping it in a try loop incase the camera fails
    while exit==False:
        # grab the frame from the threaded video stream and resize it to  have a maximum width of 400 pixels
        frame = vs.read()
        frame = imutils.resize(frame, width=400)
        # find the barcodes in the frame and decode each of the barcodes
        barcodes = pyzbar.decode(frame)
        # loop over the detected barcodes
        for barcode in barcodes:
            # extract the bounding box location of the barcode and draw
            # the bounding box surrounding the barcode on the image
            (x, y, w, h) = barcode.rect
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
            # the barcode data is a bytes object so if we want to draw it
            # on our output image we need to convert it to a string first
            barcodeData = barcode.data.decode("utf-8")
            barcodeType = barcode.type
            # draw the barcode data and barcode type on the image
            text = "{} ({})".format(barcodeData, barcodeType)
            cv2.putText(frame, text, (x, y - 10),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
            if barcodeData not in path:
              path.append(barcodeData)
              print(path)

        #this is just to put the window where we want it for testing
        windowName="Robot Cam"
        cv2.namedWindow(windowName)#name the window
        # cv2.moveWindow(windowName,1200,10)#move and create the window
        cv2.imshow(windowName, frame)#display our window
        key = cv2.waitKey(1) & 0xFF # I added this to quit gracefully from keyboard
        #print(key)
        # if the `q` key was pressed, break from the loop
        if key == ord("q"):
                break
    # close the output CSV file do a bit of cleanup
    print("cleaning up...")
    cv2.destroyAllWindows()
    vs.stop()#this kills the camera

#create threads
videoThread = threading.Thread(target=imageRec)

distaceThread = threading.Thread(target=distance)

#starting the thread
videoThread.start()
distaceThread.start()

stage_one=False
stage_two=False
stage_three=False

#make the driving decisions
avg=0
tick=0
home=False
out=True
try:
    while out:

        #--------------------------------------------

        while (len(path)==0 ):
            stage_one=True
            print("Scann QR one ")
        if len(path)==1 and tick ==0:
            time.sleep(10)
            tick=1
            print("tick",tick)

        #print("this is len",len(path))
        if stage_one == True:
            print("st1 out dist",dist)
            if dist  > 30 :#this lets us move fwr is nothing has been found in path
                go_forward(leg)
                print("stage one fwr")
            else:
                print("str else dist",dist)

                if dist < 10 and dist > 0:
                    stage_one=False
                    stage_two=True
                    stage_three=False

        #--------------------------------------------
        if stage_two == True:
            print("stage2")
            print(dist)

            if dist  > 30 or dist < 0 :# if nothing is in path move fwr

                go_forward(leg)
            else:#this goes in when we hit the wall
                while len(path)<2:
                    print("in stg2 scan 2 QR")
                    turn_right(.2)
                    turn_left(.2)
                    #scan around for objects and qr codes

                    stage_two=False
                    stage_three=True
                if path[0]== "left":#this checks if the first scanns
                    turn_left(turn)
                    time.sleep(10)
                elif path[0]=="right":#this checks if need to turn right
                    turn_right(turn)
                    time.sleep(10)

         #--------------------------------------------
        if stage_three == True:#final stage we are going home
            print("stage 3")
            print(dist)
            if dist > 30 and dist < 0 and home==False:
                go_forward(leg)
            else:
                #might add a while loop to read the QR code
                #we are home so we shake
                turn_right(2)
                turn_left(2)
                print("home")
                home=True#we made it home
                stage_three=False#we exit stage 3
                out=False#this is we are done

    #---------------light show
    light=[0,1,0,1,1,1,0,0,1,1,1,0]
    l=[0,3,6,9]
    for a in l:
      GPIO.output(Blue,light[a])
      GPIO.output(Green,[a+1])
      GPIO.output(Red,[a+2])
    #---------------Play  audio to celebrate we are home and ready to graduate
    audio= [1,5,2,4,3]
    buzzer = Buzzer()
    for a in audio:
        buzzer.play(int(a))

except KeyboardInterrupt:
    exit=True
    videoThread.join()
    print("thread vide done")
    distaceThread.join()
    print("distance done")
    print(path)
    GPIO.cleanup()
    print("Ok ok, quitting")
    #sys.exit(1)

finally:
    exit=True
    videoThread.join()
    print("thread vide done")
    distaceThread.join()
    print("distance done")
    print(path)
    GPIO.cleanup()
    print("finall out")
    #sys.exit(1)


import discord
import settings
import random
import os
from functions import discord_library
from functions import permission
def start(client,message):
    if permission.check(message,1):
        msg = []
        for raw,x in enumerate(message.content[1:]):
            try:
                if int(x):
                    msg.append(x)
            except:
                msg.append(message.content[raw+1])
        content = str(msg).replace(",","")[1:-1].replace("'","").replace(" ","")
        faktor= []
        for x in msg:
            try:
                faktor.append(int(x))
            except:
                break
        try:
            numb = int(message.content[int(len(faktor)+2):])
            if content[len(faktor)]=="D" or content[len(faktor)]=="d":
                y = 0
                z = []
                faktor = ''.join(str(e) for e in faktor)
                for x in range(int(faktor)):
                    z.append(x)
                    z[x] = random.randint(1,numb)
                    y = y+z[x]
                return message.channel.send(embed=discord.Embed(color=discord.Color.blue(),description=("Es wurden "+str([(z[x]) for x in range(int(faktor))])[1:-1]+" gewürfelt!"+"\n Das sind "+str(y))))
        except:
            return message.channel.send(embed=discord.Embed(color=discord.Color.red(),description=("ERROR")))


import pygame.sprite
import Config
from Config import *
from Images.Animations.Animation import Animation

class laserflea(pygame.sprite.Sprite):
    class states():
        IDLELEFT = 0
        IDLERIGHT = 1
        IDLELTOR = 2
        IDLERTOL = 3
        LASERLEFT = 4
        LASERRIGHT = 5
        WALKLEFT = 6
        WALKRIGHT = 7
        WALKLTOR = 8
        WALKRTOL = 9
        DEATH = 10

    Config.WIN

    # constants
    counter = 0
    shootcounter = 0
    walklooper = 0

    # images
    idle = pygame.image.load("./Images/enemies/laser-flea/idle_change_direction.png").convert_alpha()
    idleleft = Animation(idle, 222, 222, flip=True, num=1)
    idleleft.currenty = (idleleft.dy * 2)
    idleleft.scalefactor = 200
    idleleft.build()
    idleleft = idleleft.animation
    idleright = Animation(idle, 222, 222, num=1)
    idleright.currenty = (idleright.dy * 2)
    idleright.scalefactor = 200
    idleright.build()
    idleright = idleright.animation

    idlertol = Animation(idle, 222, 222, flip=True, num=1)
    idlertol.scalefactor = 200
    idlertol.build()
    idlertol = idlertol.animation

    idleltor = Animation(idle, 222, 222, num=1)
    idleltor.scalefactor = 200
    idleltor.build()
    idleltor = idleltor.animation

    walk = pygame.image.load("./Images/enemies/laser-flea/walk_change_direction.png").convert_alpha()
    walkrtol = Animation(walk, 220, 230, num=1)
    walkrtol.scalefactor = 200
    walkrtol.build()
    walkrtol = walkrtol.animation

    walkltor = Animation(walk, 220, 230, flip=True, num=1)
    walkltor.scalefactor = 200
    walkltor.build()
    walkltor = walkltor.animation

    walkleft = walkrtol[10:]
    walkright = walkltor[10:]

    laseratk = pygame.image.load("./Images/enemies/laser-flea/lasser_swept.png").convert_alpha()
    laserleft = Animation(laseratk, 221, 224)
    laserleft.scalefactor = 200
    laserleft.build()
    laserleft = laserleft.animation[0:35]
    laserright = Animation(laseratk, 221, 224, flip=True)
    laserright.scalefactor = 200
    laserright.build()
    laserright = laserright.animation[0:35]

    laser = pygame.image.load("./Images/enemies/laser-flea/laser.png").convert_alpha()
    laser = Animation(laser, 1464, 133, scale=False)
    laser.build()
    laser = laser.animation[5:6]
    laser = laser[0]
    laser = pygame.transform.scale(laser, (laser.get_width(), 50)).convert_alpha()
    i = pygame.Surface((100, 64)).convert_alpha()
    i.fill((0, 0, 0, 0))
    i.blit(laser, (0 - 500, 0))
    laser = i
    laser = pygame.transform.scale(laser, (1500, laser.get_height()))

    animationdic = {
        0: idleleft,
        1: idleright,
        2: idleltor,
        3: idlertol,
        4: laserleft,
        5: laserright,
        6: walkleft,
        7: walkright,
        8: walkltor,
        9: walkrtol,
    }

    def __init__(self, direction):
        pygame.sprite.Sprite.__init__(self)
        self.dead = False
        self.grounded = True
        if direction == "right":
            self.state = self.states.WALKRIGHT
            self.animation = self.animationdic[self.state]
            self.image = self.animation[0]
            self.facing = "right"
        else:
            self.state = self.states.WALKLEFT
            self.animation = self.animationdic[self.state]
            self.image = self.animation[0]
            self.facing = "left"
        self.index = 0
        self.width = self.image.get_width()
        self.height = self.image.get_height()
        self.rect = self.image.get_rect()
        self.rect.center = (self.image.get_width()/2, self.image.get_height()/2)
        self.rect.x = map.get_width() - 2000
        self.rect.y = map.get_height() - (map.get_height()/4)
        self.vel = 3
        self.hitmask = pygame.mask.from_surface(self.image)
        self.shot = False
        self.health = 100

    def update(self):
        self.animation = self.animationdic[self.state]
        self.think()

        if self.state == self.states.LASERLEFT or self.state == self.states.LASERRIGHT:
            if self.counter >= 1:
                self.index += 1
                self.counter = 0
        elif self.state == self.states.IDLELEFT or self.state == self.states.IDLERIGHT or self.state == self.states.IDLELTOR or self.state == self.states.IDLERTOL:
            if self.counter >= 1:
                self.index += 1
                self.counter = 0
        else:
            if self.counter >= 1:
                self.index += 1
                self.counter = 0

        if self.state == self.states.IDLELEFT:
            self.image = self.animation[self.index]
            self.facing = "left"
            if self.index == len(self.animation) - 1:
                self.index = 0
                self.state = self.states.WALKLEFT
                self.animation = self.animationdic[self.state]
                self.image = self.animation[self.index]
        elif self.state == self.states.IDLERIGHT:
            self.image = self.animation[self.index]
            self.facing = "right"
            if self.index == len(self.animation) - 1:
                self.index = 0
                self.state = self.states.WALKRIGHT
                self.animation = self.animationdic[self.state]
                self.image = self.animation[self.index]
        elif self.state == self.states.IDLELTOR:
            self.image = self.animation[self.index]
            if self.index == len(self.animation) - 1:
                self.index = 0
                self.state = self.states.IDLERIGHT
                self.facing = "right"
                self.animation = self.animationdic[self.state]
                self.image = self.animation[self.index]
        elif self.state == self.states.IDLERTOL:
            self.image = self.animation[self.index]
            if self.index == len(self.animation) - 1:
                self.index = 0
                self.state = self.states.IDLELEFT
                self.facing = "left"
                self.animation = self.animationdic[self.state]
                self.image = self.animation[self.index]
        elif self.state == self.states.WALKLEFT:
            self.image = self.animation[self.index]
            self.rect.x -= self.vel
            self.facing = "left"
            if self.index == len(self.animation) - 1:
                self.index = 0
                if self.walklooper > 10:
                    self.walklooper = 0
                    self.state = self.states.WALKLTOR
                    self.animation = self.animationdic[self.state]
                    self.image = self.animation[self.index]
                else:
                    self.walklooper += 1
        elif self.state == self.states.WALKRIGHT:
            self.image = self.animation[self.index]
            self.rect.x += self.vel
            self.facing = "right"
            if self.index == len(self.animation) - 1:
                self.index = 0
                if self.walklooper > 10:
                    self.walklooper = 0
                    self.state = self.states.WALKRTOL
                    self.animation = self.animationdic[self.state]
                    self.image = self.animation[self.index]
                else:
                    self.walklooper += 1
        elif self.state == self.states.WALKLTOR:
            self.image = self.animation[self.index]
            if self.index == len(self.animation) - 1:
                self.index = 0
                self.state = self.states.WALKRIGHT
                self.facing = "right"
                self.animation = self.animationdic[self.state]
                self.image = self.animation[self.index]
        elif self.state == self.states.WALKRTOL:
            self.image = self.animation[self.index]
            if self.index == len(self.animation) - 1:
                self.index = 0
                self.state = self.states.WALKLEFT
                self.facing = "left"
                self.animation = self.animationdic[self.state]
                self.image = self.animation[self.index]
        elif self.state == self.states.LASERLEFT:
            self.image = self.animation[self.index]
            self.facing = "left"
            if not self.shot:
                if self.index >= len(self.animation) - 8:
                    self.shot = True
                    self.rect.x -= 1500
            if self.index >= len(self.animation) - 8:
                self.shootlaser()
            if self.index == len(self.animation) - 1:
                self.rect.x += 1500
                self.index = 0
                self.state = self.states.IDLELEFT
                self.animation = self.animationdic[self.state]
                self.image = self.animation[self.index]
                self.rect = Rect(self.rect.x, self.rect.y, self.image.get_width(), self.image.get_height())
                self.shot = False

        elif self.state == self.states.LASERRIGHT:
            self.facing = "right"
            self.image = self.animation[self.index]
            if self.index >= len(self.animation) - 8:
                self.shootlaser()
            if self.index == len(self.animation) - 1:
                self.index = 0
                self.state = self.states.IDLERIGHT
                self.animation = self.animationdic[self.state]
                self.image = self.animation[self.index]
                self.rect = Rect(self.rect.x, self.rect.y, self.image.get_width(), self.image.get_height())

        if self.rect.x <= 0:
            self.rect.x = 0
        if self.rect.right >= Config.map.get_width():
            self.rect.right = Config.map.get_width()

        self.grounded = False
        for g in ground_sprites:
            if self.rect.bottom <= g.rect.top + 15:
                if g.rect.left < self.rect.x < g.rect.right or (g.rect.left < self.rect.right < g.rect.right):
                    if self.rect.bottom >= g.rect.top:
                        self.rect.bottom = g.rect.top
                        self.grounded = True

        self.counter += 1
        if self.facing == "right":
            pygame.draw.line(Config.map, Config.RED, (self.rect.x, self.rect.y - 10), (self.rect.x + 200, self.rect.y - 10),
                             4)
            pygame.draw.line(Config.map, Config.GREEN, (self.rect.x, self.rect.y - 10),
                             (self.rect.x + ((self.health / 100) * 200), self.rect.y - 10), 4)
        else:
            pygame.draw.line(Config.map, Config.RED, (self.rect.x + self.rect.width - 200, self.rect.y - 10),
                             (self.rect.x + self.rect.width, self.rect.y - 10),
                             4)
            pygame.draw.line(Config.map, Config.GREEN, (self.rect.x + self.rect.width - 200, self.rect.y - 10),
                             (self.rect.x + self.rect.width - 200 + ((self.health / 100) * 200), self.rect.y - 10), 4)

        for p in player_sprite:
            for b in p.bullets:
                bx = b.rect.x
                by = b.rect.y
                sx = self.rect.x
                sy = self.rect.y

                offset = (bx - sx, by - sy)
                result = self.hitmask.overlap(b.hitmask, offset)
                if result:
                    if self.state != self.states.LASERLEFT or self.state != self.states.LASERRIGHT:
                        if (self.rect.center[1] - 20) <= b.rect.center[1] <= (self.rect.center[1] + 20):
                            if self.facing == "right":
                                if self.rect.right < p.rect.x:
                                    p.bullets.remove(b)
                                    if self.health > 0:
                                        self.health -= 5
                            else:
                                if self.rect.left > p.rect.x:
                                    p.bullets.remove(b)
                                    if self.health > 0:
                                        self.health -= 5
                    p.bullets.remove(b)

        if self.health <= 0:
            self.dead = True

    def think(self):
        for p in player_sprite:
            if self.state == self.states.WALKLEFT or self.state == self.states.IDLELEFT:
                if self.state != self.states.LASERLEFT:
                    if self.rect.y <= p.rect.top and (self.rect.bottom >= p.rect.bottom):
                        if self.rect.left - WIDTH/2 + 200 <= p.rect.right <= self.rect.left:
                            self.state = self.states.LASERLEFT
                            self.animation = self.animationdic[self.state]
                            self.index = 0
            elif self.state == self.states.WALKRIGHT or self.state == self.states.IDLERIGHT:
                if self.state != self.states.LASERRIGHT:
                    if self.rect.y <= p.rect.top and (self.rect.bottom >= p.rect.bottom):
                        if self.rect.right <= p.rect.left <= self.rect.right + WIDTH/2 - 100:
                            self.state = self.states.LASERRIGHT
                            self.animation = self.animationdic[self.state]
                            self.index = 0

    def shootlaser(self):

        if self.state == self.states.LASERLEFT:
            newimg = Surface(
                ((self.laser.get_width() + self.image.get_width()), self.image.get_height())).convert_alpha()
            newimg.fill((0, 0, 0, 0))
            newimg.blit(self.laser, (30, newimg.get_height()/2 - 25))
            newimg.blit(self.image, (newimg.get_width() - self.image.get_width(), 0))
            self.image = newimg
            self.rect = Rect(self.rect.x , self.rect.y, self.image.get_width(), self.image.get_height())
            self.hitmask = pygame.mask.from_surface(self.image)

        elif self.state == self.states.LASERRIGHT:
            newimg = Surface(
                ((self.laser.get_width() + self.image.get_width()), self.image.get_height())).convert_alpha()
            newimg.fill((0, 0, 0, 0))
            newimg.blit(self.laser, (self.image.get_width() - 30, newimg.get_height()/2 - 25))
            newimg.blit(self.image, (0, 0))
            self.image = newimg
            self.rect = Rect(self.rect.x, self.rect.y, self.image.get_width(), self.image.get_height())
            self.hitmask = pygame.mask.from_surface(self.image)

        for p in player_sprite:
            px = p.rect.x
            py = p.rect.y
            sx = self.rect.x
            sy = self.rect.y

            offset = (px - sx, py - sy)
            result = self.hitmask.overlap(p.hitmask, offset)
            if result:
                if p.health > 0:
                    p.damage(10)


import pickle as pkl
import matplotlib.pyplot as plt
import numpy as np
import os

def name_trans(key, method):
    name_trans = {'sgcn':'{}'.format(method),
                  'sgcn_plus':'{}+'.format(method),
                  'sgcn_plus_v2':'{}+(momentum)'.format(method),
                  'sgcn_pplus':'{}++'.format(method),
                  'sgcn_pplus_v2':'{}++(grad only)'.format(method),
                  'full':'Full-batch'}
    return name_trans[key]

def smooth(scalars, weight=0.8):  # Weight between 0 and 1
    last = scalars[0]  # First value in the plot (first timestep)
    smoothed = list()
    for point in scalars:
        smoothed_val = last * weight + (1 - weight) * point  # Calculate smoothed value
        smoothed.append(smoothed_val)                        # Save it
        last = smoothed_val                                  # Anchor the last smoothed value

    return smoothed

def draw_train_loss_epoch(results, method):
    fig, axs = plt.subplots()
    for key, values in results.items():
        key = name_trans(key, method)
        loss_train, loss_test, loss_train_all, f1, grad_vars, best_val_index = values
        loss_train = loss_train[:best_val_index]
        loss_train = smooth(loss_train)
        x = np.arange(len(loss_train))
        axs.plot(x,loss_train,label=key)

    axs.set_xlabel('epoch')
    axs.set_ylabel('loss')
    axs.grid(True)

    plt.title('{} - {} - train_loss/epoch'.format(method, dataset))
    fig.tight_layout()
    plt.legend()
    plt.savefig('{}_train_loss_epoch.pdf'.format(prefix))

def draw_test_loss_epoch(results, method):
    fig, axs = plt.subplots()
    for key, values in results.items():
        key = name_trans(key, method)
        loss_train, loss_test, loss_train_all, f1, grad_vars, best_val_index = values
        loss_test = loss_test[:best_val_index]
        loss_test = smooth(loss_test)
        x = np.arange(len(loss_test))
        axs.plot(x,loss_test,label=key)

    axs.set_xlabel('epoch')
    axs.set_ylabel('loss')
    axs.grid(True)

    plt.title('{} - {} - test_loss/epoch'.format(method, dataset))
    fig.tight_layout()
    plt.legend()
    plt.savefig('{}_test_loss_epoch.pdf'.format(prefix))

def draw_train_loss_step(results, method):
    fig, axs = plt.subplots()
    for key, values in results.items():
        key = name_trans(key, method)
        loss_train, loss_test, loss_train_all, f1, grad_vars, best_val_index = values
        loss_train_all = loss_train_all[:400]
        loss_train_all = smooth(loss_train_all)
        x = np.arange(len(loss_train_all))
        axs.plot(x,loss_train_all,label=key)

    axs.set_xlabel('steps')
    axs.set_ylabel('loss')
    axs.grid(True)

    plt.title('{} - {} - train_loss/step'.format(method, dataset))
    fig.tight_layout()
    plt.legend()
    plt.savefig('{}_train_loss_step.pdf'.format(prefix))

def draw_grad_variance(results, method):
    fig, axs = plt.subplots()
    for key, values in results.items():
        key = name_trans(key, method)
        loss_train, loss_test, loss_train_all, f1, grad_vars, best_val_index = values
        grad_vars = grad_vars[:200]
        grad_vars = smooth(grad_vars)
        x = np.arange(len(grad_vars))
        axs.plot(x,grad_vars,label=key)

    axs.set_xlabel('steps')
    axs.set_ylabel('gradient variance')
    axs.grid(True)

    plt.title('{} - {} - variances/step'.format(method, dataset))
    fig.tight_layout()
    plt.legend()
    plt.savefig('{}_grad_vars_step.pdf'.format(prefix))

def get_f1_score(results, dataset, method, f):
    for key, values in results.items():
        key = name_trans(key, method)
        loss_train, loss_test, loss_train_all, f1, grad_vars, best_val_index = values
        log = "{}, {}, {}, {}\n".format(dataset, method, key, f1)
        f.write(log)

datasets = ['Flickr', 'Reddit', 'PPI', 'PPI-large', 'Yelp']
methods = ['LADIES', 'FastGCN', 'GraphSage', 'GraphSaint']
f_log = open('f1_scores.txt', 'w')

for dataset in datasets:
    for method in methods:
        prefix = '{}_{}'.format(method.lower(), dataset.lower())
        if os.path.exists('{}.pkl'.format(prefix)):
            with open('{}.pkl'.format(prefix),'rb') as f:
                results = pkl.load(f)
            draw_train_loss_epoch(results, method)
            draw_test_loss_epoch(results, method)
            draw_train_loss_step(results, method)
            get_f1_score(results, dataset, method, f_log)
            draw_grad_variance(results, method)

f_log.close()


import numpy as np
import matplotlib.pyplot as plt
import utilities_lib as ul
import copy

from matplotlib.patches import Rectangle
import datetime as dt
from matplotlib import collections  as mc
from matplotlib.lines import Line2D

def barchart(self, X = [],Y = [],  # X-Y points in the graph.
        labels = [], legend = [],       # Basic Labelling
        color = None,  lw = 2, lw2 = 2,alpha = 1.0,  # Basic line properties
        nf = 0, na = 0,          # New axis. To plot in a new axis         # TODO: shareX option
        ax = None, position = [], projection = "2d", # Type of plot
        sharex = None, sharey = None,
        fontsize = 20,fontsizeL = 10, fontsizeA = 15,  # The font for the labels in the axis
        xlim = None, ylim = None, xlimPad = None, ylimPad = None, # Limits of vision
        ws = None, Ninit = 0,
        loc = "best",
        dataTransform = None,
        xaxis_mode = None,yaxis_mode = None,AxesStyle = None   # Automatically do some formatting :)
       ):

    # Management of the figure and properties
    ax = self.figure_management(nf, na, ax = ax, sharex = sharex, sharey = sharey,
                      projection = projection, position = position)
    ## Preprocess the data given so that it meets the right format
    X, Y = self.preprocess_data(X,Y,dataTransform)
    NpY, NcY = Y.shape
    NpX, NcX = Y.shape
    plots,plots_typ =  self.init_WidgetData(ws)

    ############### CALL PLOTTING FUNCTION ###########################

#    X = X.astype(dt.datetime)
#    self.X = self.X.astype(dt.datetime)
#    print X.shape
    High,Low, Open,Close = Y[:,0], Y[:,1], Y[:,2], Y[:,3]

#    print X
    width_unit = self.get_barwidth(X)
    dist = width_unit /2.2
    # High-Low
    linesHL = [[(X[i].astype(dt.datetime),Low[i]),(X[i].astype(dt.datetime), High[i])] for i in range(NpX)]
    linesO = [[(X[i].astype(dt.datetime) - dist,Open[i]),(X[i].astype(dt.datetime), Open[i])] for i in range(NpX)]
    linesC = [[(X[i].astype(dt.datetime),Close[i]),(X[i].astype(dt.datetime) + dist, Close[i])] for i in range(NpX)]

#    lines = [[(0, 1), (1, 1)], [(2, 3), (3, 3)], [(1, 2), (1, 3)]]
#    print mdates.date2num(X[i,0].astype(dt.datetime)), type(mdates.date2num(X[i,0].astype(dt.datetime)))
    self.zorder = self.zorder + 1  # Setting the properties
    colorFinal = self.get_color(color)

    # TODO: Handle the legend better
    if len(legend)>0:
        label_legend = legend[0]
    else:
        label_legend = None
    lcHL = mc.LineCollection(linesHL, colors= colorFinal, linewidths=lw, antialiased=True, label = label_legend)
    lcO = mc.LineCollection(linesO, colors= colorFinal, linewidths=lw2, antialiased=True)
    lcC = mc.LineCollection(linesC, colors= colorFinal, linewidths=lw2, antialiased=True)
    ax.add_collection(lcHL)
    ax.add_collection(lcO)
    ax.add_collection(lcC)

    ax.autoscale()  # TODO: The zoom is not changed if we do not say it !
#    ax.margins(0.1)
    ############### Last setting functions ###########################
    self.store_WidgetData(plots_typ, plots)     # Store pointers to variables for interaction

    self.update_legend(legend,NcY,ax = ax, loc = loc)    # Update the legend
    self.set_labels(labels)
    self.set_zoom(ax = ax, xlim = xlim,ylim = ylim, xlimPad = xlimPad,ylimPad = ylimPad)
    self.format_xaxis(ax = ax, xaxis_mode = xaxis_mode)
    self.format_yaxis(ax = ax, yaxis_mode = yaxis_mode)
    self.apply_style(nf,na,AxesStyle)

#    xfmt = mdates.DateFormatter('%b %d')
#    ax.xaxis.set_major_formatter(xfmt)
    return ax

def candlestick(self, X = [],Y = [],  # X-Y points in the graph.
        labels = [], legend = [],       # Basic Labelling
        color = None,  lw = 2, alpha = 1.0,  # Basic line properties
        nf = 0, na = 0,          # New axis. To plot in a new axis         # TODO: shareX option
        ax = None, position = [], projection = "2d", # Type of plot
        sharex = None, sharey = None,
        fontsize = 20,fontsizeL = 10, fontsizeA = 15,  # The font for the labels in the axis
        xlim = None, ylim = None, xlimPad = None, ylimPad = None, # Limits of vision
        ws = None, Ninit = 0,
        loc = "best",
        dataTransform = None,
        xaxis_mode = None,yaxis_mode = None,AxesStyle = None,   # Automatically do some formatting :)
        barwidth = None, colorup = "g", colordown = "r"
       ):

    # Management of the figure and properties
    ax = self.figure_management(nf, na, ax = ax, sharex = sharex, sharey = sharey,
                      projection = projection, position = position)
    ## Preprocess the data given so that it meets the right format
    X, Y = self.preprocess_data(X,Y,dataTransform)
    NpY, NcY = Y.shape
    plots,plots_typ =  self.init_WidgetData(ws)

    ##################### PREPROCESSING AND PLOTTING #######################

    # Prepare the data
    openp = Y[self.start_indx:self.end_indx,0]
    closep = Y[self.start_indx:self.end_indx,1]
    highp = Y[self.start_indx:self.end_indx,2]
    lowp = Y[self.start_indx:self.end_indx,3]

    dates = X[self.start_indx:self.end_indx]
    dates = ul.preprocess_dates(dates)
    if (type(barwidth) == type(None)):
        barwidth = self.get_barwidth(dates, barwidth) * 0.8

    # PLOTTING !!
    Npoints = dates.size

    OFFSET = barwidth / 2.0

    line_factor = 0.15
    barwidth_HL = barwidth * line_factor
    OFFSET_HL = barwidth_HL / 2.0

    lines = []
    patches = []
    for i in range(Npoints):
        if closep[i] >= openp[i] :
            color = colorup
            baseRectable = openp[i]
        else:
            color = colordown
            baseRectable = closep[i]

        height = np.abs(openp[i]  - closep[i])

        ## High-low line

#        line_HL = Line2D(
#            xdata=(dates[i],dates[i]), ydata=(lowp[i], highp[i]),
#            color=color,
#            linewidth=lw,
#            antialiased=True,
#        )

        rect_HL = Rectangle(
            xy=(dates[i] - OFFSET_HL, lowp[i]),
            width=barwidth_HL,
            height=highp[i] - lowp[i],
            facecolor=color,
            edgecolor=color,
        )

#        print type(dates[i]), type(OFFSET)
        ## Open Close rectangle
        rect_OP = Rectangle(
            xy=(dates[i] - OFFSET, baseRectable),
            width=barwidth,
            height=height,
            facecolor=color,
            edgecolor=color,
        )
        rect_OP.set_alpha(alpha)
#
#        lines.append(line_HL)
#        patches.append(rect_OP)

#        ax.add_line(line_HL)
        ax.add_patch(rect_OP)
        ax.add_patch(rect_HL)

#    lines = mc.LineCollection(lines)
#    ax.add_collection(lines)
#    ax.add_collection(patches)

    ax.autoscale()  # TODO: The zoom is not changed if we do not say it !
    ############### Last setting functions ###########################
    self.store_WidgetData(plots_typ, plots)     # Store pointers to variables for interaction

    self.update_legend(legend,NcY,ax = ax, loc = loc)    # Update the legend
    self.set_labels(labels)
    self.set_zoom(ax = ax, xlim = xlim,ylim = ylim, xlimPad = xlimPad,ylimPad = ylimPad)
    self.format_xaxis(ax = ax, xaxis_mode = xaxis_mode)
    self.format_yaxis(ax = ax, yaxis_mode = yaxis_mode)
    self.apply_style(nf,na,AxesStyle)

    self.plots_type.append(["candlestick"])
#    self.plots_list.append([plotting]) # We store the pointers to the plots

    data_i = [Y, ax]
    self.Data_list.append(data_i)

    return ax

def histogram(self, X,  bins = 20, orientation = "vertical",
        *args, **kwargs):

    hist, bin_edges = np.histogram(X, density=True, bins = bins)
    self.bar(bin_edges[:-1], hist, orientation = orientation,*args, **kwargs)

#    if (orientation == "vertical"):
#        self.plot(x_grid, y_values, nf = 0, *args, **kwargs)
#    else:
#        self.plot(y_values, x_grid, nf = 0, *args, **kwargs)

def Velero_graph(self, data,
                 labels = [],nf = 1,
                fake_dates = 1,
                 ws = -1):
    """ This function plots the Heiken Ashi of the data
    data[4][Ns] """

    colorFill = "green"  # Gold
    colorBg = "#7fffd4" # Aquamarine
    colorInc = '#FFD700'
    colorDec = "red"

    Close = data["Close"]
    Open = data["Open"]
    High = data["High"]
    Low = data["Low"]
    Volume = data["Volume"]
    dates = data.index

    if (fake_dates == 1):
        dates = np.array(range(len(dates)))

    Nsam = len(dates)  # Number of samples
    incBox = []
    decBox = []
    allBox = []
    # Calculate upper and lowe value of the box and the sign
    for i in range(Nsam):
        diff = Close[i] - Open[i]
    #        print diff
        if (diff >= 0):
            incBox.append(i)
        else:
            decBox.append(i)
        allBox.append(i)

    ## All_bars !!
    self.bar(dates[allBox], High[allBox] - Low[allBox], bottom = Low[allBox],
             barwidth = 0.1, color = colorFill, ws = ws, nf = 1)

    self.bar(dates[allBox], abs(Open[allBox] - Close[allBox]),
             bottom = np.min((Close[allBox],Close[allBox]),axis = 0),
             barwidth = 0.9, color = colorDec, ws = ws, nf = 0)

#    ## Increasing bars !!
#    self.bar(dates[incBox], Close[incBox] - Open[incBox], bottom = Open[incBox],
#             width = 0.9, color = colorInc, ws = ws, nf = nf)
#    self.bar(dates[incBox], High[incBox] - Close[incBox], bottom = Close[incBox],
#             width = 0.1, color = colorFill, ws = ws, nf = 0)
#    self.bar(dates[incBox], Open[incBox] - Low[incBox], bottom = Low[incBox],
#             width = 0.1, color = colorFill, ws = ws, nf = 0)
#
#    ## Decreasing bars !!
#    self.bar(dates[decBox], Open[decBox] - Close[decBox], bottom = Close[decBox],
#             width = 0.9, color = colorDec, ws = ws, nf = 0)
#    self.bar(dates[decBox], High[decBox] - Open[decBox], bottom = Open[decBox],
#             width = 0.1, color = colorFill, ws = ws, nf = 0)
#    self.bar(dates[decBox], Close[decBox] - Low[decBox], bottom = Low[decBox],
#             width = 0.1, color = colorFill, ws = ws, nf = 0)

#
    plt.ylim(min(Low)* (0.95))

#     Plot the volume
    self.bar(dates, Volume, alpha = 0.5,
             barwidth = 0.9, color = colorBg, ws = ws, nf = 0, na = 1)

    plt.ylim(plt.ylim()[0], max(Volume)* 4)

def Heiken_Ashi_graph(self, data, labels = [], nf = 1):
    r_close = data["Close"].values
    r_open = data["Open"].values
    r_max = data["High"].values
    r_min = data["Low"].values
    x_close  = (r_close + r_open + r_max + r_min)/4
    x_open = (r_close[1:] + x_close[:-1])/2  # Mean of the last

    # Insert the first open sin we cannot calcualte the prevoius
    # The other opion is to eliminate the first of everyone
    x_open = np.insert(x_open, 0, r_open[0], axis = 0)

#    print x_close.shape, x_open.shape
    x_max = np.max(np.array([r_max,x_close,x_open]), axis = 0)
    x_min = np.min(np.array([r_min,x_close,x_open]), axis = 0)

    ### Lets create another pandas dataframe with this data
    new_data = copy.deepcopy(data)
    new_data["Close"] = x_close
    new_data["Open"] = x_open
    new_data["High"] = x_max
    new_data["Low"] = x_min

    self.Velero_graph(new_data, labels = [], nf = 1)

#    x_close  = np.mean(data,0)
#    x_open = data[0][1:] + upper_box[:-1]  # Mean of the last

def plot_timeSeriesRange(self, X, Y, sigma, k = 1.96, nf = 0, legend = ["95% CI f(x)"]):
    # Plots the time series with its 1.96 percent interval
    gl = self
    gl.plot(X,Y, nf = 0,legend = legend)
    gl.plot_filled(X, np.concatenate([Y - 1.9600 * sigma,
           Y + 1.9600 * sigma],axis = 1), alpha = 0.5, nf = 0)

def plot_timeRegression(self,Xval, Yval, sigma,
                        Xtr, Ytr,sigma_eps = None,
                        labels = ["Gaussian Process Estimation","Time","Price"], nf = 0):
    # This is just a general plotting funcion for a timeSeries regression task:
    # Plot the function, the prediction and the 95% confidence interval based on
    # the MSE
    # eps is the estimated noise of the training samples.
    """
    sigma is the std of each of the validation samples
    sigma_eps is the considered observation noise
    """

    Xval = ul.fnp(Xval)
    Yval = ul.fnp(Yval)
    Xtr = ul.fnp(Xtr)
    Ytr = ul.fnp(Ytr)

    sigma = ul.fnp(sigma)
    sigma_eps = ul.fnp(sigma_eps)

    gl = self
    gl.plot(Xval,Yval, labels = labels, legend = ["Estimated Mean"], nf = nf)

    gl.plot_filled(Xval, np.concatenate([Yval - 1.9600 * sigma,
           Yval + 1.9600 * sigma],axis = 1), alpha = 0.5, legend = ["95% CI f(x)"])

    # If we are given some observaiton noise we also plot the estimation of it
    if type(sigma_eps) != type(None):
        # Ideally we have a func that tells us for each point, what is the observation noise.
        # We are suposed to know what is those values for training,
        # TODO: And for testing ? Would that help ? I think we are already assuming so in the computation of K.
        # The inner gaussian process can also be specified "alpha", we will research more about that later.
        # I guess it is for hesterodasticity.
        # We are gonna consider that the observation noise of the predicted samples is homocedastic.
        sigma = np.sqrt(sigma**2 + ul.fnp(sigma_eps)[0]**2)
        # TODO: maybe in the future differentiate between sigma_eps and dy
        gl.plot_filled(Xval, np.concatenate([Yval - 1.9600 * sigma,
               Yval + 1.9600 * sigma],axis = 1), alpha = 0.2, legend = ["95% CI y(x)"])

    # TODO: what is this     ec='None'

    if type(sigma_eps) != type(None):
        if (ul.fnp(sigma_eps).size == 1):
            sigma_eps = np.ones((Xtr.size,1)) * sigma_eps
        plt.errorbar(Xtr.ravel(), Ytr, sigma_eps, fmt='k.', markersize=10, label=u'Observations')
    else:
        gl.scatter(Xtr, Ytr, legend = ["Training Points"], color = "k")

def putamadere(wd):
    ## Previous velero plotting
    # The width of the bowes is the same for all and the x position is given by
    # the position

    ## Obtain the 4 parameters of the square
    ## Box parameters

    """ WE are gonna plot the Velas in one axis and the volume in others """

    ####### Plot all the cubes !!!!
    fig, ax = plt.subplots()

    fig.facecolor = colorBg

    for i in range(Ns):
        # Calculate upper and lowe value of the box and the sign
        diff = r_close[i] - r_open[i]
#        print diff
        if (diff >= 0):
            low_box = r_open[i]
            sign = colorInc
        else:
            low_box = r_close[i]
            sign = colorDec

        # Create the box
        ax.broken_barh([(date_indx[i] + 0.05, 1 - 0.1)],
                        (low_box, abs(diff)),
                         facecolors=sign)

        # Create the box upper line
        ax.broken_barh([(date_indx[i] + 0.45, 0.1)],
                        (low_box + abs(diff), r_max[i] - low_box + abs(diff)),
                         facecolors= "red")

        # Create the box lower line
        ax.broken_barh([(date_indx[i] + 0.45, 0.1)],
                        (r_min[i] , low_box - r_min[i]),
                         facecolors= "red")

    """ PLOT VOLUME """
    ax1_2 = ax.twinx()

    #ax1_2.plot(date, (ask-bid))
#    print volume.shape
#    print len(date)
    ax1_2.bar(date, volume, facecolor= colorFill,alpha=.5)
#    ax1_2.fill_between(date, 0, volume, facecolor= colorFill,alpha=.5)

#    broken_barh ( xranges, yrange, **kwargs)
#        xranges	sequence of (xmin, xwidth)
#        yrange	 sequence of (ymin, ywidth)

    plt.title(labels[0])
    plt.xlabel(labels[1])
    plt.ylabel(labels[2])

    if (len(labels) >3 ):
        plt.legend(labels[3])

#    plt.grid()
    plt.show()


#Implement a Stack using Queue Data Structure
from collections import deque
class Stack:
    def __init__(self):
        self.q1 = deque()
        self.q2 = deque()

    def add(self, data):
        while len(self.q1):
            self.q2.append(self.q1.pop())
        self.q1.append(data)
        while len(self.q2):
            self.q1.append(self.q2.pop())

    #Remove the top item from stack
    def pop(self):
        if not self.q1:
            print("Underflow")
            exit(0)
        front = self.q1.popleft()
        return front

if __name__ == '__main__':
    keys = [1,2,3,4,5]
    s = Stack()
    for key in keys:
        s.add(key)

    while s:
        print(s.pop())


import networkx as nx
import numpy as np
import matplotlib.pyplot as plt

G = nx.DiGraph()
G.add_nodes_from([
     ('A', {"NodeClass": "Pump"}),
     ('B', {"NodeClass": "Vessel"}),
     ('C', {"NodeClass": "Column"}),
     ('D', {"NodeClass": "Valve"}),
     ('E', {"NodeClass": "Vessel"}),
     ('F', {"NodeClass": "Pump"}),
     ('G', {"NodeClass": "Vessel"}),
     ('H', {"NodeClass": "Valve"}),
     ])

G.add_edges_from(
    [('A', 'B'), ('A', 'C'), ('D', 'B'), ('E', 'C'), ('E', 'F'),
     ('B', 'H'), ('B', 'G'), ('B', 'F'), ('C', 'G')])

p_influence = ['Pump', 'Valve']

nx.draw(G, cmap = plt.get_cmap('jet'), with_labels=True)

boundary_nodes = []
for node in G.nodes():
    if G._node[node]['NodeClass'] in p_influence:
        boundary_nodes.append(node)

p_zone_list = []
p_zone=[]

for b in boundary_nodes:
    boundary_nodes_wb=boundary_nodes
    boundary_nodes_wb.remove(b)
    for c in boundary_nodes_wb:
        path=nx.all_simple_paths(G,b,c)