import os
import sys
import bpy

from atlasutil import atlas

def make(blendfile, sources, atlases, textures_path='textures'):
    lib = Library(blendfile, sources, atlases, textures_path)
    lib.build()

def constrain_size(width, height, size):
    if width > size or height > size:
        scale = min(size / width, size / height)
        width *= scale
        height *= scale
    return width, height

class LibraryError(Exception): pass

class Library(object):
    def __init__(self, blendfile, sources, atlases, textures_path):
        self.basepath = os.path.dirname(blendfile)
        self.blendfile = blendfile
        self.sources = sources
        self.textures_path = textures_path

        self.atlases = []
        for atlas_def in atlases:
            margin = trim = 0.
            name, params = atlas_def[0].split('@')
            dimensions, *rest = params.split(':')
            width, height = map(float, dimensions.split('x'))
            if len(rest) > 0:
                margin = float(rest[0])
            if len(rest) > 1:
                trim = float(rest[1])
            atlas_obj = LibraryAtlas(
                self, name, atlas_def[1:], width, height, margin, trim)
            self.atlases.append(atlas_obj)

        self.atlas_textures_path = os.path.join(self.basepath, self.textures_path)
        if not os.path.exists(self.atlas_textures_path):
            os.makedirs(self.atlas_textures_path)

    def build(self):
        self.import_groups()

        # attempt to pack all atlases first
        for atlas in self.atlases:
            atlas.step_1()

        # render each atlas
        for atlas in self.atlases:
            atlas.step_2()

        self.save_blendfile()

    def import_groups(self):
        group_names = []
        for atlas in self.atlases:
            group_names.extend(atlas.group_names)

        imported_groups = []
        for group in group_names:
            for source in self.sources:
                bpy.ops.wm.link_append(
                    filename=group,
                    filepath=os.path.join(
                        os.sep + os.sep, os.path.basename(source), 'Group', group),
                    directory=os.path.abspath(
                        os.path.join(self.basepath, source, 'Group')) + os.sep,
                    link=True, instance_groups=False)
                if group in bpy.data.groups:
                    sys.stdout.write(
                        'A  %s:%s\n' % (os.path.basename(source), group))
                    break

        diff = set(group_names) - set(bpy.data.groups.keys())
        if len(diff):
            for group in diff:
                sys.stdout.write('!  %s\n' % group)
            raise LibraryError('missing groups')

        bpy.ops.object.make_local(type='ALL')

    def save_blendfile(self):
        bpy.ops.wm.save_as_mainfile(
            filepath=os.path.abspath(os.path.join(self.basepath, self.blendfile)),
            check_existing=False)

class LibraryAtlas(atlas.Atlas):
    def __init__(
        self, library, name, groups, width, height,
        margin=0., trim=0.):

        super(LibraryAtlas, self).__init__(width, height, [], margin, trim)
        self.library = library
        self.name = name

        self.group_names = []
        self.group_sizes = {}
        for group in groups:
            if '@' in group:
                group_name, size = group.split('@', 1)
                size = float(size)
            else:
                group_name = group
                size = -1
            self.group_names.append(group_name)
            self.group_sizes[group_name] = size
        self.image_locations = []

    def step_1(self):
        self.make_meshes()
        self.collect_images()
        self.pack()

    def step_2(self):
        self.render()
        self.adjust_library_data()

    def make_meshes(self):
        mesh_id = 0
        for group_name in self.group_names:
            for obj in bpy.data.groups[group_name].objects:
                if not obj.type == 'MESH':
                    continue
                obj.data = obj.data.copy()
                obj.data.name = '%s_%i' % (self.name, mesh_id)
                mesh_id += 1

    def collect_images(self):
        # TODO: handle images packed in blendfile
        image_map = {}
        material_map = {}
        for group_name in self.group_names:
            max_size = self.group_sizes[group_name]
            for obj in bpy.data.groups[group_name].objects:
                if not obj.type == 'MESH':
                    continue
                mesh = obj.data
                for mslot in obj.material_slots:
                    images = material_map.setdefault(mslot.material, [])
                    for tslot in mslot.material.texture_slots:
                        if (not tslot or
                            not tslot.texture or
                            tslot.texture.type != 'IMAGE' or
                            not tslot.texture.image or
                            tslot.texture.image.source != 'FILE'):
                            continue

                        channels = []
                        if tslot.use_map_color_diffuse:
                            channels.append('color')
                        if tslot.use_map_color_spec:
                            channels.append('specular')
                        if tslot.use_map_emit:
                            channels.append('emit')
                        if tslot.use_map_normal:
                            channels.append('normal')
                        if not channels:
                            continue

                        image = tslot.texture.image
                        if tslot.uv_layer:
                            uv_texture = mesh.uv_textures[tslot.uv_layer]
                        else:
                            uv_texture = mesh.uv_textures.active
                        if max_size > 0:
                            width, height = constrain_size(
                                image.size[0], image.size[1], max_size)
                        else:
                            width, height = image.size
                        if image not in image_map:
                            lib_image = image_map[image] = LibraryImage(0, 0, {})
                        else:
                            lib_image = image_map[image]
                        lib_image.width = max(width, lib_image.width)
                        lib_image.height = max(height, lib_image.height)

                        if mesh not in lib_image.meshes:
                            lib_image.meshes.append(mesh)
                        if tslot.texture not in lib_image.textures:
                            lib_image.textures.append(tslot.texture)
                        if uv_texture not in lib_image.uv_textures:
                            lib_image.uv_textures.append(uv_texture)
                        for channel in channels:
                            lib_image.channels[channel] = image.filepath

                        images.append(lib_image)

        self.images = []
        for material, images in material_map.items():
            width = 0
            height = 0
            meshes = set()
            textures = set()
            uv_textures = set()
            channels = {}

            for image in images:
                width = max(width, image.width)
                height = max(height, image.height)
                meshes.update(image.meshes)
                textures.update(image.textures)
                uv_textures.update(image.uv_textures)
                channels.update(image.channels)

            lib_image = LibraryImage(width, height, channels)
            lib_image.meshes = list(meshes)
            lib_image.textures = list(textures)
            lib_image.uv_textures = list(uv_textures)

            self.images.append(lib_image)

    def pack(self):
        try:
            return super(LibraryAtlas, self).pack()
        except atlas.PackOverflow as exc:
            raise atlas.PackOverflow(self.name)

    def render(self):
        self.chart = super(LibraryAtlas, self).render(os.path.join(
            self.library.atlas_textures_path,
            '%s_%%(channel)s.png' % self.name))

    def adjust_library_data(self):
        atlas_images = dict(
            (i, bpy.data.images.load(i))
            for i in set([d for (s, c, d, l) in self.chart]))
        for dest, image in atlas_images.items():
            image.name = os.path.basename(dest).rsplit('.', 1)[0]
        altered_uv_textures = []

        for src, channel, dest, location in self.chart:
            x, y, width, height = location
            x /= float(self.width)
            y /= float(self.height)
            width /= float(self.width)
            height /= float(self.height)

            # TODO: this next part is pretty fragile, might need a
            # more robust way to install atlas textures

            atlas_image = atlas_images[dest]
            for texture in src.textures:
                texture.image = atlas_image

            for uv_texture in src.uv_textures:
                if uv_texture not in altered_uv_textures:
                    for item in uv_texture.data:
                        if channel == 'color':
                            item.image = atlas_image
                        for co in item.uv:
                            co[0] = co[0] * width + x
                            co[1] = co[1] * height + y
                    altered_uv_textures.append(uv_texture)

class LibraryImage(atlas.Image):
    def __init__(self, *args, **kwargs):
        super(LibraryImage, self).__init__(*args, **kwargs)
        self.meshes = []
        self.textures = []
        self.uv_textures = []


"""GDB Pretty-printers and utility commands for MongoDB
"""
import gdb.printing
import glob
import os
import sys

try:
    import bson
    import bson.json_util
    import collections
    from bson.codec_options import CodecOptions
except ImportError as e:
    print("Warning: Could not load bson library for Python '" + str(sys.version) + "'.")
    print("Check with the pip command if pymongo 3.x is installed.")
    bson = None

def get_unique_ptr(obj):
    """Read the value of a libstdc++ std::unique_ptr"""
    return obj["_M_t"]['_M_head_impl']

###################################################################################################
#
# Pretty-Printers
#
###################################################################################################

class StatusPrinter(object):
    """Pretty-printer for mongo::Status"""
    OK = 0  # ErrorCodes::OK

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

    def to_string(self):
        if not self.val['_error']:
            return 'Status::OK()'

        code = self.val['_error']['code']
        # Remove the mongo::ErrorCodes:: prefix. Does nothing if not a real ErrorCode.
        code = str(code).split('::')[-1]

        info = self.val['_error'].dereference()
        location = info['location']
        reason = info['reason']
        if location:
            return 'Status(%s, %s, %s)' % (code, reason, location)
        else:
            return 'Status(%s, %s)' % (code, reason)

class StatusWithPrinter:
    """Pretty-printer for mongo::StatusWith<>"""
    def __init__(self, val):
        self.val = val

    def to_string(self):
        if not self.val['_status']['_error']:
            return 'StatusWith(OK, %s)' % (self.val['_t'])

        code = self.val['_status']['_error']['code']

        # Remove the mongo::ErrorCodes:: prefix. Does nothing if not a real ErrorCode.
        code = str(code).split('::')[-1]

        info = self.val['_status']['_error'].dereference()
        location = info['location']
        reason = info['reason']
        if location:
            return 'StatusWith(%s, %s, %s)' % (code, reason, location)
        else:
            return 'StatusWith(%s, %s)' % (code, reason)

class StringDataPrinter:
    """Pretty-printer for mongo::StringData"""

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

    def display_hint(self):
        return 'string'

    def to_string(self):
        size = self.val["_size"]
        if size == -1:
            return self.val['_data'].lazy_string()
        else:
            return self.val['_data'].lazy_string(length=size)

class BSONObjPrinter:
    """Pretty-printer for mongo::BSONObj"""

    def __init__(self, val):
        self.val = val
        self.ptr = self.val['_objdata'].cast(gdb.lookup_type('void').pointer())
        self.size = self.ptr.cast(gdb.lookup_type('int').pointer()).dereference()

    def display_hint(self):
        return 'map'

    def children(self):
        if not bson:
            return

        inferior = gdb.selected_inferior()
        buf = bytes(inferior.read_memory(self.ptr, self.size))
        options = CodecOptions(document_class=collections.OrderedDict)
        bsondoc = bson.BSON.decode(buf, codec_options=options)

        for k, v in bsondoc.items():
            yield 'key', k
            yield 'value', bson.json_util.dumps(v)

    def to_string(self):
        ownership = "owned" if self.val['_ownedBuffer']['_buffer']['_holder']['px'] else "unowned"

        size = self.size
        if size < 5 or size > 17 * 1024 * 1024:
            size = hex(size)

        if size == 5:
            return "%s empty BSONObj @ %s" % (ownership, self.ptr)
        else:
            return "%s BSONObj %s bytes @ %s" % (ownership, size, self.ptr)

class UnorderedFastKeyTablePrinter:
    """Pretty-printer for mongo::UnorderedFastKeyTable<>"""

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

        # Get the value_type by doing a type lookup
        valueTypeName = val.type.strip_typedefs().name + "::value_type"
        valueType = gdb.lookup_type(valueTypeName).target()
        self.valueTypePtr = valueType.pointer()

    def display_hint(self):
        return 'map'

    def to_string(self):
        return "UnorderedFastKeyTablePrinter<%s> with %s elems " % (
            self.val.type.template_argument(0), self.val["_size"])

    def children(self):
        cap = self.val["_area"]["_hashMask"] + 1
        it = get_unique_ptr(self.val["_area"]["_entries"])
        end = it + cap

        if it == 0:
            return

        while it != end:
            elt = it.dereference()
            it += 1
            if not elt['_used']:
                continue

            value = elt['_data']["__data"].cast(self.valueTypePtr).dereference()

            yield ('key', value['first'])
            yield ('value', value['second'])

class DecorablePrinter:
    """Pretty-printer for mongo::Decorable<>"""

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

        decl_vector = val["_decorations"]["_registry"]["_decorationInfo"]
        # TODO: abstract out navigating a std::vector
        self.start = decl_vector["_M_impl"]["_M_start"]
        finish = decl_vector["_M_impl"]["_M_finish"]
        decinfo_t = gdb.lookup_type('mongo::DecorationRegistry::DecorationInfo')
        self.count = int((int(finish) - int(self.start)) / decinfo_t.sizeof)

    def display_hint(self):
        return 'map'

    def to_string(self):
        return "Decorable<%s> with %s elems " % (self.val.type.template_argument(0),
                                                 self.count)

    def children(self):
        decorationData = get_unique_ptr(self.val["_decorations"]["_decorationData"])

        for index in range(self.count):
            descriptor = self.start[index]
            dindex = int(descriptor["descriptor"]["_index"])

            # In order to get the type stored in the decorable, we examine the type of its
            # constructor, and do some string manipulations.
            # TODO: abstract out navigating a std::function
            type_name = str(descriptor["constructor"]["_M_functor"]["_M_unused"]["_M_object"])
            type_name = type_name[0:len(type_name) - 1]
            type_name = type_name[0: type_name.rindex(">")]
            type_name = type_name[type_name.index("constructAt<"):].replace("constructAt<", "")

            # If the type is a pointer type, strip the * at the end.
            if type_name.endswith('*'):
                type_name = type_name[0:len(type_name) - 1]
            type_name = type_name.rstrip()

            # Cast the raw char[] into the actual object that is stored there.
            type_t = gdb.lookup_type(type_name)
            obj = decorationData[dindex].cast(type_t)

            yield ('key', "%d:%s:%s" % (index, obj.address, type_name))
            yield ('value', obj)

def find_match_brackets(search, opening='<', closing='>'):
    """Returns the index of the closing bracket that matches the first opening bracket.
       Returns -1 if no last matching bracket is found, i.e. not a template.

       Example:
         'Foo<T>::iterator<U>''
         returns 5
    """
    index = search.find(opening)
    if index == -1:
        return -1

    start = index + 1
    count = 1
    str_len = len(search)
    for index in range(start, str_len):
        c = search[index]

        if c == opening:
            count += 1
        elif c == closing:
            count -= 1

        if count == 0:
            return index

    return -1

class MongoSubPrettyPrinter(gdb.printing.SubPrettyPrinter):
    """Sub pretty printer managed by the pretty-printer collection"""

    def __init__(self, name, prefix, is_template, printer):
        super(MongoSubPrettyPrinter, self).__init__(name)
        self.prefix = prefix
        self.printer = printer
        self.is_template = is_template

class MongoPrettyPrinterCollection(gdb.printing.PrettyPrinter):
    """MongoDB-specific printer printer collection that ignores subtypes.
    It will match 'HashTable<T> but not 'HashTable<T>::iterator' when asked for 'HashTable'.
    """

    def __init__(self):
        super(MongoPrettyPrinterCollection, self).__init__("mongo", [])

    def add(self, name, prefix, is_template, printer):
        self.subprinters.append(MongoSubPrettyPrinter(name, prefix, is_template, printer))

    def __call__(self, val):

        # Get the type name.
        lookup_tag = gdb.types.get_basic_type(val.type).tag
        if not lookup_tag:
            lookup_tag = val.type.name
        if not lookup_tag:
            return None

        index = find_match_brackets(lookup_tag)

        # Ignore subtypes of classes
        # We do not want HashTable<T>::iterator as an example, just HashTable<T>
        if index == -1 or index + 1 == len(lookup_tag):
            for printer in self.subprinters:
                if printer.enabled and (
                   (printer.is_template and lookup_tag.find(printer.prefix) == 0) or
                   (not printer.is_template and lookup_tag == printer.prefix)):
                    return printer.printer(val)

        return None

def build_pretty_printer():
    pp = MongoPrettyPrinterCollection()
    pp.add('BSONObj', 'mongo::BSONObj', False, BSONObjPrinter)
    pp.add('Decorable', 'mongo::Decorable', True, DecorablePrinter)
    pp.add('Status', 'mongo::Status', False, StatusPrinter)
    pp.add('StatusWith', 'mongo::StatusWith', True, StatusWithPrinter)
    pp.add('StringData', 'mongo::StringData', False, StringDataPrinter)
    pp.add('UnorderedFastKeyTable', 'mongo::UnorderedFastKeyTable', True, UnorderedFastKeyTablePrinter)
    return pp

###################################################################################################
#
# Commands
#
###################################################################################################
# Dictionary of commands so we can write a help function that describes the MongoDB commands.
mongo_commands = {}

def register_mongo_command(obj, name, command_class):
    """Register a command with no completer as a mongo command"""
    global mongo_commands
    gdb.Command.__init__(obj, name, command_class)

    mongo_commands[name] = obj.__doc__

class DumpGlobalServiceContext(gdb.Command):
    """Dump the Global Service Context"""

    def __init__(self):
        register_mongo_command(self, "mongodb-service-context", gdb.COMMAND_DATA)

    def invoke(self, arg, _from_tty):
        gdb.execute("print *('mongo::(anonymous namespace)::globalServiceContext')")

# Register command
DumpGlobalServiceContext()

class MongoDBAnalyze(gdb.Command):
    """Analyze MongoDB process"""

    def __init__(self):
        register_mongo_command(self, "mongodb-analyze", gdb.COMMAND_STATUS)

    def invoke(self, arg, _from_tty):
        print("Running Hang Analyzer Supplement")
        if len(gdb.objfiles()) == 0:
            print("Skipping, not attached to an inferior")
            return

        main_binary_name = gdb.objfiles()[0].filename

        if main_binary_name.endswith('mongod'):
            self.analyze_mongod()
        else:
            print("No process specific analysis done for: %s" % (main_binary_name))

    def analyze_mongod(self):
        """GDB in-process python supplement"""

        try:

            # Call into mongod, and dump the state of lock manager
            # Note that output will go to mongod's standard output, not the debugger output window
            gdb.execute("call ('mongo::(anonymous namespace)::globalLockManager').dump()",
                        from_tty=False, to_string=False)
        except gdb.Error as gdberr:
            print("Ignoring error '%s'" % str(gdberr))

# Register command
MongoDBAnalyze()

class MongoDBHelp(gdb.Command):
    """Dump list of mongodb commands"""

    def __init__(self):
        gdb.Command.__init__(self, "mongodb-help", gdb.COMMAND_DATA)

    def invoke(self, arg, _from_tty):
        print("Command - Description")
        for key in mongo_commands:
            print("%s - %s" % (key, mongo_commands[key]))

# Register command
MongoDBHelp()

###################################################################################################
#
# Setup
#
###################################################################################################

# Register pretty-printers, replace existing mongo printers
gdb.printing.register_pretty_printer(
    gdb.current_objfile(),
    build_pretty_printer(),
    True)

print("MongoDB GDB pretty-printers and commands loaded, run 'mongodb-help' for list of commands")


import tkinter as tk

class Calculator:
	def __init__(self):

		self.root = tk.Tk()
		self.root.title('Калькулятор')
		self.root.geometry('300x350')
		self.root.resizable(False, False)

		#создание поля ввода
		self.entry = tk.Entry(self.root, width=15, bd=1, font=('Arial', 20), justify=tk.RIGHT)
		self.entry.grid(row=0, column=0, columnspan=3, stick='wens')
		self.entry.insert(0, '0')

		self.digit = 1
		self.digit_buttons = []
		self.d_buttons = ['=', '+', '-' , '*', '/']

		#создание кнопок цифр путем цикла и пакуем их в список
		for r in range(1, 5):
			for col in range(3):
				self.digit_buttons.append(tk.Button(self.root, text=f'{self.digit}', bg='grey', bd=2, font=('Arial', 15), command=lambda x=self.digit: self.click_button(x-1)))
				self.digit_buttons[self.digit-1].grid(row=r, column=col, stick='wens', padx=1, pady=1)
				#заменяем "десятку" на "ноль" и завершаем цикл
				if self.digit_buttons[self.digit-1]['text'] == '10':
					self.digit_buttons[self.digit-1]['text'] = '0'
					self.digit_buttons[self.digit-1].grid(row=4, column=1, stick='wens', padx=1, pady=1)
					break
				self.digit+=1

		#создание кнопки "очистить"
		self.clean_button = tk.Button(self.root, text='C', font=('Arial', 15), command=self.clean_win)
		self.clean_button.grid(row=4, column=2, stick='wens', padx=1, pady=1)

		#создание кнопки "отмена/назад"
		self.back_button = tk.Button(self.root, text='←', font=('Arial', 25), command=self.back_mean)
		self.back_button.grid(row=4, column=0, stick='wens', padx=1, pady=1)

		#создание кнопок "операции"
		for d in range(len(self.d_buttons)):
				self.button = tk.Button(self.root, text=f'{self.d_buttons[d]}', font=('Arial', 25), command=lambda x=d: self.operator_handler(x))
				self.button.grid(row=d, column=3, stick='wens', padx=1, pady=1)

		for x in range(5):
			self.root.grid_columnconfigure(x, minsize=70)
			self.root.grid_rowconfigure(x, minsize=70)

		tk.mainloop()

	#создание обработкича "знаков операций"
	def operator_handler(self, x):
		self.value = self.entry.get()
		if self.d_buttons[x] == '=':
			self.sum = eval(self.value)
			self.entry.delete(0, tk.END)
			self.entry.insert(0, int(self.sum))
		else:
			self.value = self.entry.get() + self.d_buttons[x]
			self.entry.delete(0, tk.END)
			if self.value[0] =='0' and len(self.value) > 1:
				self.entry.insert(0, self.value[1:])
			else:
				self.entry.insert(0, self.value)

	#создание обработчика для "кнопок цифр"
	def click_button(self, x):
		self.value = self.entry.get() + str(self.digit_buttons[x]['text'])
		self.entry.delete(0, tk.END)
		if self.value[0] == '0' and len(self.value) > 1:
			self.entry.insert(0, self.value[1:])
		else:
			self.entry.insert(0, self.value)

	#создание обработчик "очистить"
	def clean_win(self):
		self.entry.delete(0, tk.END)
		self.entry.insert(0, '0')

	#создание обработчика "отмены/назад"
	def back_mean(self):
		self.value = self.entry.get()[:-1]
		self.entry.delete(0, tk.END)
		self.entry.insert(0, self.value)
		if len(self.value) == 0:
			self.entry.insert(0, '0')

if __name__ == '__main__':
	app = Calculator()


#!/usr/bin/python

GRID_SIZE = 10
NBR_STEPS = 100
THRESHOLD = 9

def get_adjacent_coords(idx):
    x, y = idx % GRID_SIZE, idx // GRID_SIZE
    adjs = [(x - 1, y - 1), (x, y - 1), (x + 1, y - 1), (x - 1, y), (x + 1, y), (x - 1, y + 1), (x, y + 1), (x + 1, y + 1)]
    adjs = filter(None, [adj if 0 <= adj[0] < GRID_SIZE and 0 <= adj[1] < GRID_SIZE else None for adj in adjs])
    return list(map(lambda c: c[1] * GRID_SIZE + c[0], adjs))

def handle_flashes(idx, flash_map):
    flash_map[idx][1] = True
    adj_c = get_adjacent_coords(idx)
    for c_idx in adj_c:
        flash_map[c_idx][0] += 1
        if not flash_map[c_idx][1] and flash_map[c_idx][0] > THRESHOLD:
            handle_flashes(c_idx, flash_map)

def flash_calculator(octopuses, first_sync_flash=False) -> int:
    nbr_flashes, i = 0, 0
    flash_map = [[o, False] for o in octopuses]

    while True:
        i += 1
        if not first_sync_flash:
            if i > NBR_STEPS:
                break

        flash_map = [[o + 1, False] for o, hf in flash_map]
        for idx in range(len(flash_map)):
            if flash_map[idx][0] > THRESHOLD and not flash_map[idx][1]:
                handle_flashes(idx, flash_map)

        step_nbr_flashes = [f[1] for f in flash_map].count(True)
        if first_sync_flash:
            if step_nbr_flashes == GRID_SIZE * GRID_SIZE:
                return i
        else:
            nbr_flashes += [f[1] for f in flash_map].count(True)

        flash_map = [(0, False) if o > THRESHOLD else (o, False) for o, hf in flash_map]

    return nbr_flashes

def main():
    octopuses = [int(v) for v in open("inputs/input11", 'r').read().replace("\n", "")]

    print("Part 1:", flash_calculator(octopuses))
    print("Part 2:", flash_calculator(octopuses, first_sync_flash=True))

if __name__ == "__main__":
    main()


import socket

def server():
    host = '127.0.0.1'
    port = 5000

    s = socket.socket()
    s.bind((host, port))

    s.listen(1)
    c, addr = s.accept()

    print("Polaczenie z: ", str(addr))
    while True:
        data = c.recv(1024)
        if not data:
            break
        print("od uzytkownika odebrano: "+str(data, 'utf-8'))
        data = str(data, 'utf-8').upper()
        print(" wysylanie: "+str(data))
        c.send(data.encode("utf8"))
    c.close()

if __name__ == "__main__":
    server()


import numpy as np
import pandas as pandas
import pymongo
from sklearn import linear_model
import sklearn
from sklearn.utils import shuffle
from pymongo import MongoClient
from pprint import pprint
import pickle
import json
import csv
import time

# TODO: have node js add csv and json to
#  directory then execute script

def main():
    while (1):
        client = pymongo.MongoClient('mongodb://localhost:27017/')
        db = client["MachineLearning"]
        collection1 = db["Data"]
        while collection1.count() < 1:
            pass
        time.sleep(1)
        x = collection1.find_one()

        collection2 = db[x['dataset']]
        #print(collection2.find("G1"))

        # serverStatusResult = db.command("serverStatus")
        # pprint(serverStatusResult)

        dataset = x['dataset']
        attributes = x['attributes']
        predict = x['predict']
        attributes.append(predict)

        cursor = collection2.find()
        mongo_docs = list(cursor)
        docs = pandas.DataFrame(columns = [])
        for num, doc in enumerate(mongo_docs):
            doc["_id"] = (doc["_id"])
            doc_id = doc["_id"]
            series_obj = pandas.Series(doc,name = doc_id)
            docs = docs.append(series_obj)

        docs.to_csv("susling.csv")

        f = open("ha.csv", "wt")
        with open("susling.csv", 'r') as csv_file:
            csv_reader = csv.reader(csv_file)
            for line in csv_reader:
                for i in line:
                    f.write(str(i))
                    f.write('\n')

        count1 = 0
        count2 = 1
        test = False
        f = open("ha.csv", "r").readlines()
        with open("final.csv", "w") as outfile:
            for index, line in enumerate(f):
                # if (index != 1 and index != 3 and index != 4 and index != 6 and index != 7 and index != 9 and index != 10 and index != 12 and index != 13):
                #     outfile.write(line)
                if (index == 1):
                    pass
                if (index != count1 and index != count2):
                    outfile.write(line)
                    count1 += 3
                    count2 += 3

        f = open("final.csv")
        data = pandas.read_csv(f, sep=";")
        data = data[attributes]
        data = shuffle(data)

        x = np.array(data.drop([predict], 1))
        y = np.array(data[predict])
        x_train, x_test, y_train, y_test = sklearn.model_selection.train_test_split(x, y, test_size=0.1)

        best = 0
        for _ in range(20):
            x_train, x_test, y_train, y_test = sklearn.model_selection.train_test_split(x, y, test_size=0.1)

            linear = linear_model.LinearRegression()

            linear.fit(x_train, y_train)
            acc = linear.score(x_test, y_test)
            print("Accuracy: " + str(acc))

            if acc > best:
                best = acc
                with open("studentgrades.pickle", "wb") as f:
                    pickle.dump(linear, f)

        # LOAD MODEL
        pickle_in = open("studentgrades.pickle", "rb")
        linear = pickle.load(pickle_in)

        # print("-------------------------")
        # print('Coefficient: \n', linear.coef_)
        # print('Intercept: \n', linear.intercept_)
        # print("-------------------------")

        print(best)
        predicted= linear.predict(x_test)
        for x in range(len(predicted)):
            print(predicted[x], x_test[x], y_test[x])

        outputString = "Your model has been trained with {} accuracy.".format(best)
        output = {
            'output': outputString
        }

        result = db.reviews.insert_one(output)
        print(result)
        collection1.drop()
        collection2.drop()

if __name__== "__main__":
    main()
# TODO: send results back through node js sus stuff so it can be displayed on website


import os
import tensorflow as tf
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import RobustScaler
from keras.models import Sequential
from keras.layers import Dense
import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score

# Déterminer le répertoire du script
from util import gen_tf2_pgm

script_dir = os.path.dirname(os.path.realpath(__file__))

# Charger le jeu de données CICIDS2017 au format CSV
data_path = os.path.join(script_dir, 'archive/MachineLearningCSV/MachineLearningCVE/Friday-WorkingHours-Afternoon-DDos.pcap_ISCX.csv')
data = pd.read_csv(data_path, skipinitialspace=True)

# Enlever la première ligne (header) de X_data
data = data.iloc[1:]

# Remplacer les valeurs manquantes (NaN) par la moyenne des colonnes respectives
data = data.fillna(data.mean())

# Supprimer les lignes contenant des valeurs infinies
data = data.replace([np.inf, -np.inf], np.nan)
data = data.dropna()

# Extraire les fonctionnalités (X) et les étiquettes (y)
X_data = data.drop(columns=["Label"])
y_labels = data['Label']

# Convertir les étiquettes en valeurs numériques
y_labels = y_labels.apply(lambda label: 0 if label == "BENIGN" else 1)

# Utiliser RobustScaler pour normaliser les données
scaler = RobustScaler()
X_data = scaler.fit_transform(X_data)

# Fractionner les données en ensembles d'entraînement et de test
X_train, X_test, y_train, y_test = train_test_split(X_data, y_labels, test_size=0.2, random_state=42)

# Créer le modèle
model = Sequential([
    Dense(200, input_dim=X_train.shape[1], activation='relu'),
    Dense(500, activation='relu'),
    Dense(200, activation='relu'),
    Dense(2, activation='softmax')  # Assurez-vous d'ajuster le nombre de classes ici
])

# Compiler le modèle
model.compile(loss='sparse_categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

# Entraîner le modèle
history = model.fit(X_train, y_train, epochs=10,
                    batch_size=64, verbose=1,
                    validation_split=0.2)

# Fonction FGSM pour générer des exemples adversariaux
# def generate_adversarial_example(model, input_example, true_label, epsilon):
#     loss_object = tf.keras.losses.SparseCategoricalCrossentropy()
#     with tf.GradientTape() as tape:
#         tape.watch(input_example)
#         prediction = model(input_example)
#         loss = loss_object(true_label, prediction)
#     gradient = tape.gradient(loss, input_example)
#     perturbed_example = input_example + epsilon * tf.sign(gradient)
#     return perturbed_example

def evaluation_metrics(y_test, y_pred):
    print("accuracy_score: ", accuracy_score(y_test, y_pred))
    print("recall_score: ", recall_score(y_test, y_pred, average='weighted'))
    print("precision_score: ", precision_score(y_test, y_pred, average='weighted'))
    print("f1_score: ", f1_score(y_test, y_pred, average='weighted'))
    print("{:.3f}".format(accuracy_score(y_test, y_pred)), " & ", "{:.3f}".format(recall_score(y_test, y_pred, average='weighted')), " & ", "{:.3f}".format(precision_score(y_test, y_pred, average='weighted')), " & ", "{:.3f}".format(f1_score(y_test, y_pred, average='weighted')))
    return accuracy_score(y_test, y_pred)

# attack_functions = [gen_tf2_fgsm_attack, gen_tf2_bim, gen_tf2_pgm] #, gen_tf2_mim]
attack_functions = [gen_tf2_pgm]
label_attack = ["fgsm", "bim", "pgm"]
# label_attack = ["pgm"]
# epsilons = [.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5]
epsilons = [3.5, 4, 4.5, 5]

accuracies = []

for attack_function in attack_functions:
    print("<" * 15, attack_function, ">" * 15)
    # epsilon = 0.1
    acc = []
    for epsilon in epsilons:
    # for epsilon in [1]:
        print("-" * 35)
        print("eps: ", epsilon)
        # Convertir y_test en tableau NumPy pour les vraies étiquettes
        y_test_np = y_test.to_numpy()

        # Convertir les données d'entrée en tenseurs TensorFlow
        X_test_tf = tf.convert_to_tensor(X_test, dtype=tf.float32)
        y_test_tf = tf.convert_to_tensor(y_test_np, dtype=tf.int32)

        # Générer des exemples adversariaux pour le jeu de test
        perturbed_examples = attack_function(model, X_test_tf, epsilon)

        # Prédiction sur les exemples originaux et perturbés
        original_predictions = model.predict(X_test_tf)

        perturbed_predictions = np.argmax(model.predict(perturbed_examples), axis=1)
        # perturbed_predictions = model.predict(perturbed_examples)
        score = evaluation_metrics(perturbed_predictions, y_test)
        acc.append(score)
    accuracies.append(acc)

exit()

# Créer une figure et un axe
fig, ax = plt.subplots()

# Générer une courbe pour chaque attaque
color = ['r', 'g', 'b', 'c', 'm', 'y', 'k']

for i, attack in enumerate(label_attack):
    attack_accuracies = accuracies[i]
    ax.plot(epsilons, attack_accuracies, label=attack, color=color[i])

# Ajouter les labels et la légende
ax.set_xlabel('Epsilon value')
ax.set_ylabel('Accuracy')
ax.set_title('Accuracy as a function of Epsilon value for the {} attack method'.format(label_attack[0]))
ax.legend()

# Afficher le graphique
plt.show()

# # Afficher les résultats
# for i in range(len(X_test)):
#     original_pred_class = np.argmax(original_predictions[i])
#     perturbed_pred_class = np.argmax(perturbed_predictions[i])
#     print("Exemple", i+1)
#     print("Prédiction originale:", original_pred_class)
#     print("Confiance originale:", original_predictions[i][original_pred_class])
#     print("Prédiction perturbée:", perturbed_pred_class)
#     print("Confiance perturbée:", perturbed_predictions[i][perturbed_pred_class])
#     print("\n")

# ... (le reste du code pour afficher les graphiques, si nécessaire)
# Préparer les données pour le graphique
# labels = ['Classe ' + str(i) for i in range(len(original_predictions[0]))]
# original_probs = original_predictions[0]
# perturbed_probs = perturbed_predictions[0]
#
# # Créer un graphique à barres pour les probabilités originales et perturbées
# fig, ax = plt.subplots()
# x = np.arange(len(labels))
# width = 0.35
#
# rects1 = ax.bar(x - width/2, original_probs, width, label='Origine')
# rects2 = ax.bar(x + width/2, perturbed_probs, width, label='Perturbé')
#
# ax.set_ylabel('Probabilité')
# ax.set_title('Probabilités de prédictions originales et perturbées')
# ax.set_xticks(x)
# ax.set_xticklabels(labels)
# ax.legend()
#
# # Ajouter les étiquettes des probabilités au-dessus des barres
# def autolabel(rects):
#     for rect in rects:
#         height = rect.get_height()
#         ax.annotate('%.2f' % height,
#                     xy=(rect.get_x() + rect.get_width() / 2, height),
#                     xytext=(0, 3),  # 3 points de décalage
#                     textcoords="offset points",
#                     ha='center', va='bottom')
#
# autolabel(rects1)
# autolabel(rects2)
#
# fig.tight_layout()
#
# # Afficher le graphique
# plt.show()


commands = {}

def command(func):
    module = func.__module__.split(".")
    if module[0] != "booruer":
        raise Exception(f"Invalid module: {module[0]}")
    if module[1] != "commands":
        raise Exception(f"Invalid module: {module[1]}")

    module = module[2:]
    if func.__name__ != "__run__":
        module.append(func.__name__)

    current = commands

    for i, name in enumerate(module):
        if i == len(module) - 1:
            current[name] = func
        else:
            if name not in current:
                current[name] = {}
            current = current[name]

def load_all():
    from . import meta, tag
    from .danbooru import download
    from .booru import download


import os
from Bio import PDB

class ChainSplitter:
    def __init__(self, out_dir=None):
        """ Create parsing and writing objects, specify output directory. """
        self.parser = PDB.PDBParser(QUIET=True)
        self.writer = PDB.PDBIO()
        self.out_dir = out_dir

    def make_pdb(self, pdb_path, chain_letters, overwrite=False, struct=None):
        """ Create a new PDB file containing only the specified chains.

        Returns the path to the created file.

        :param pdb_path: full path to the crystal structure
        :param chain_letters: iterable of chain characters (case insensitive)
        :param overwrite: write over the output file if it exists
        """
        chain_letters = [chain.upper() for chain in chain_letters]

        # Input/output files
        (pdb_dir, pdb_fn) = os.path.split(pdb_path)
        pdb_id = pdb_fn[3:7]
        out_name = "%s_%s.pdb" % (pdb_id, "".join(chain_letters))
        out_path = os.path.join(self.out_dir, out_name)
        plural = "s" if (len(chain_letters) > 1) else ""  # for printing

        # Skip PDB generation if the file already exists
        if (not overwrite) and (os.path.isfile(out_path)):
            print("Chain%s %s of '%s' already extracted to '%s'." %
                    (plural, ", ".join(chain_letters), pdb_id, out_name))
            return out_path

        print("Extracting chain%s %s from %s..." % (plural,
                ", ".join(chain_letters), pdb_fn))

        # Get structure, write new file with only given chains
        if struct is None:
            struct = self.parser.get_structure(pdb_id, pdb_path)
        self.writer.set_structure(struct)
        self.writer.save(out_path, select=SelectChains(chain_letters))

        return out_path

class SelectChains(PDB.Select):
    """ Only accept the specified chains when saving. """
    def __init__(self, chain_letters):
        self.chain_letters = chain_letters

    def accept_chain(self, chain):
        return (chain.get_id() in self.chain_letters)

if __name__ == "__main__":
    """ Parses PDB id's desired chains, and creates new PDB structures. """
    import sys
    import argparse
    import os
    parser = argparse.ArgumentParser()
    parser.add_argument("-o", "--outpath",required=True, help="where to save the retrieved pdb file.")
    parser.add_argument("-p", "--pdbcid",required=True, help="the path of the template text file.")
    args = parser.parse_args()
    outpath = args.outpath
    pdbcid = args.pdbcid  #pdbcid means pdb chain id.
    pdbList = PDB.PDBList()
    splitter = ChainSplitter(outpath)  # Change me.

    with open(pdbcid) as pdb_chainidfile:
        for line in pdb_chainidfile:
            pdb_id = line[:4].lower()
            chain = line[4]
            pdb_fn = pdbList.retrieve_pdb_file(pdb_id,pdir=outpath,file_format="pdb")
            splitter.make_pdb(pdb_fn, chain)
            os.remove(pdb_fn)


class Parent():
    def __init__(self, last_name, eye_color):
        print("Parent Constructor called")
        self.last_name = last_name
        self.eye_color = eye_color

class Child(Parent):
    def __init__(self, last_name, eye_color, number_of_toys):
        print("Child Constructor called")
        Parent.__init__(self, last_name, eye_color)
        self.number_of_toys = number_of_toys

# darth_vadar = Parent("Skywalker", "black")
# print(darth_vadar.last_name)

luke_skywalker = Child("Skywalker", "hope", 1)
print(luke_skywalker.last_name)
print(luke_skywalker.number_of_toys)


import matplotlib.pyplot as plt

def plot_student_grades_vs_on_campus(x_label, y_label, grade_percentage_arr, on_campus_arr, dest):
    x = on_campus_arr
    y = grade_percentage_arr
    plt.plot(x, y, 'o', color='orange')
    plt.xlabel = x_label
    plt.ylabel = y_label
    plt.xticks(ticks=[0, 1], labels=['Off Campus', 'On Campus'])

    plt.title("Student performance off/on campus")
    plt.savefig(dest)
    plt.close()

def plot_student_grades_vs_is_working(x_label, y_label, grade_percentage_arr, is_working_arr, dest):
    x = is_working_arr
    y = grade_percentage_arr
    plt.plot(x, y, 'o', color='orange')
    plt.xlabel = x_label
    plt.ylabel = y_label
    plt.xticks(ticks=[0, 1], labels=['Not Working', 'Is Working'])

    plt.title("Student performance Working vs. Not Working")
    plt.savefig(dest)
    plt.close()

def plot_student_grades_vs_gpa(x_label, y_label, grade_percentage_arr, gpa_arr, dest):
    x = gpa_arr
    y = grade_percentage_arr
    plt.plot(x, y, 'o', color='orange')
    plt.xlabel = x_label
    plt.ylabel = y_label

    plt.title("Student Performance vs GPA")
    plt.savefig(dest)
    plt.close()

def plot_student_grades_vs_institution(x_label, y_label, grade_percentage_arr, gpa_arr, dest):
    x = gpa_arr
    y = grade_percentage_arr
    plt.plot(x, y, 'o', color='orange')
    plt.xlabel = x_label
    plt.ylabel = y_label
    plt.xticks(ticks=[1, 2, 3, 4, 5], labels=['Kansas State University', 'University of Kansas',
                                              'Wichita State University', 'Emporia State University',
                                              'Fort Hays State University'], fontsize='6')
    plt.title("Student Performance vs Student Institution")
    plt.savefig(dest)
    plt.close()

def plot_student_grades_vs_position(x_label, y_label, grade_percentage_arr, pos_arr, dest):
    x = pos_arr
    y = grade_percentage_arr
    plt.plot(x, y, 'o', color='orange')
    plt.xlabel = x_label
    plt.ylabel = y_label
    plt.xticks(ticks=[0, 1], labels=['No Position', 'Has Position'])
    plt.title("Student Performance vs Position In Club")
    plt.savefig(dest)
    plt.close()

def plot_student_grades_vs_department(x_label, y_label, grade_percentage_arr, dept_arr, dest):
    x = dept_arr
    y = grade_percentage_arr
    plt.plot(x, y, 'o', color='orange')
    plt.xlabel = x_label
    plt.ylabel = y_label
    plt.title("Student Performance vs Department")
    plt.savefig(dest)
    plt.close()


def fact(n):
    if n < 2:
        return 1
    else:
        return n * fact(n-1)

def binom(power):
    value = 0
    while value <= power:
        yield fact(power)/(fact(power-value)*fact(value))
        value +=1

def result(n,g=0):
    if n<g:
        return 0
    else:
        for i in binom(g):
            print(int(i), end =" ")
    print()
    result(n,g+1)

while True:
    try:
        n = int(input("Введіть степінь: "))
        if n<0:
            raise TypeError
    except ValueError:
        print("Невірний формат! Лише числа! Спробуйте ще раз!")
        continue
    except TypeError:
        print("Лише натуральні числа, будь-ласка!")
        continue

    result(n)

    m=input("\nЧи бажаєте продовжити? '+' - так '-' ні " )
    if m=="-":
        break


import sys

# enable python to find the module
module_path = Dir('.').srcnode().abspath
sys.path.append(module_path)
from build.perftest import compile_test

import os

Import('env')
my_env = env.Clone()

def cu_build_function(source, target, env):
  compile_test(str(source[0]), str(target[0]))

# define a rule to build a .cu from a .test
cu_builder = Builder(action = cu_build_function,
                     suffix = '.cu',
                     src_suffix = '.test')
my_env.Append(BUILDERS = {'CUFile' : cu_builder})

# define a rule to build a report from an executable
xml_builder = Builder(action = os.path.join('"' + str(my_env.Dir('.')), '$SOURCE" > $TARGET'),
                      suffix = '.xml',
                      src_suffix = my_env['PROGSUFFIX'])
my_env.Append(BUILDERS = {'XMLFile' : xml_builder})

my_env.Append(CPPPATH = [Dir('.').srcnode(), Dir('#/testing')])

cu_list = []
program_list = []
xml_list = []

build_files = [os.path.join('build', f) for f in ['perftest.py', 'test_function_template.cxx']]

# describe dependency graph:
# xml -> program -> .cu -> .test
for test in my_env.Glob('*.test'):
  cu = my_env.CUFile(test)
  my_env.Depends(cu, build_files)
  cu_list.append(cu)

  prog = my_env.Program(cu)
  program_list.append(prog)

  xml = my_env.XMLFile(prog)
  xml_list.append(xml)

# make aliases for groups of targets
run_performance_tests_alias = my_env.Alias("run_performance_tests", xml_list)
performance_tests_alias     = my_env.Alias("performance_tests", program_list)

# when no build target is specified, by default we build the programs
my_env.Default(performance_tests_alias)

# output a help message
my_env.Help("""
Type: 'scons' to build all performance test programs.
Type: 'scons run_performance_tests' to run all performance tests and output reports.
Type: 'scons <test name>' to build a single performance test program of interest.
Type: 'scons <test name>.xml' to run a single performance test of interest and output a report in an XML file.
""")


###################################
#
#   @filename: utils.py
#   @auth: Ryan Blais, V00863568
#   @desc: This python script contains utility
#          functions used in the main.py script
#          used in the University of Victoria
#          ECE 470, A01, course project
#

import keras.backend as K

# Segment Classes Reference
SEGMENT_CLASSES = {
    0 : 'NOT tumor',
    1 : 'NECROTIC/CORE', # or NON-ENHANCING tumor CORE
    2 : 'EDEMA',
    3 : 'ENHANCING' # original 4 -> converted into 3 later
}

############################
#
#   @fname: dice_coef
#   @param: y_true --> ground truth lables
#           y_pred --> predicted labels
#           smooth --> added to avoid division by 0
#   @desc:  Implementation of the Sorensen-Dice coefficient.
#           Is a measurement of similarity between sets with
#           a smoothing factor to prevent divide-by 0 errors.
#           Measures Dice coef including all 4 classes
#
def dice_coef(y_true, y_pred, smooth=1.0):
    n_classes = 4
    for i in range(n_classes):
        y_t_flat = K.flatten(y_true[:,:,:,i])
        y_p_flat = K.flatten(y_pred[:,:,:,i])
        intersection = K.sum(y_t_flat * y_p_flat)
        loss = ((2. * intersection + smooth) / (K.sum(y_t_flat) + K.sum(y_p_flat) + smooth))
        K.print_tensor(loss, message='loss value for class {} : '.format(SEGMENT_CLASSES[i]))
        if i == 0:
            total_loss = loss
        else:
            total_loss = total_loss + loss
    total_loss = total_loss / n_classes
    K.print_tensor(total_loss, message=' total dice coef: ')
    return total_loss

############################
#
#   @fname: dice_coef_none
#   @param: y_true --> ground truth lables
#           y_pred --> predicted labels
#           epsilon --> added to avoid division by 0
#   @desc:  Implementation of the Sorensen-Dice coefficient
#           specifically for class 0: No tumor
#           Is a measurement of similarity between sets with
#           a small factor added to denominator to
#           prevent divide-by 0 errors.
#
def dice_coef_none(y_true, y_pred, epsilon=1e-6):
    intersection = K.sum(K.abs(y_true[:,:,:,0] * y_pred[:,:,:,0]))
    return (2. * intersection) / (K.sum(K.square(y_true[:,:,:,0])) + K.sum(K.square(y_pred[:,:,:,0])) + epsilon)

############################
#
#   @fname: dice_coef_necrotic
#   @param: y_true --> ground truth lables
#           y_pred --> predicted labels
#           epsilon --> added to avoid division by 0
#   @desc:  Implementation of the Sorensen-Dice coefficient
#           specifically for class 1: Necrotic
#           Is a measurement of similarity between sets with
#           a small factor added to denominator to
#           prevent divide-by 0 errors.
#
def dice_coef_necrotic(y_true, y_pred, epsilon=1e-6):
    intersection = K.sum(K.abs(y_true[:,:,:,1] * y_pred[:,:,:,1]))
    return (2. * intersection) / (K.sum(K.square(y_true[:,:,:,1])) + K.sum(K.square(y_pred[:,:,:,1])) + epsilon)

############################
#
#   @fname: dice_coef_edema
#   @param: y_true --> ground truth lables
#           y_pred --> predicted labels
#           epsilon --> added to avoid division by 0
#   @desc:  Implementation of the Sorensen-Dice coefficient
#           specifically for class 2: Edema
#           Is a measurement of similarity between sets with
#           a small factor added to denominator to
#           prevent divide-by 0 errors.
#
def dice_coef_edema(y_true, y_pred, epsilon=1e-6):
    intersection = K.sum(K.abs(y_true[:,:,:,2] * y_pred[:,:,:,2]))
    return (2. * intersection) / (K.sum(K.square(y_true[:,:,:,2])) + K.sum(K.square(y_pred[:,:,:,2])) + epsilon)

############################
#
#   @fname: dice_coef_enhancing
#   @param: y_true --> ground truth lables
#           y_pred --> predicted labels
#           epsilon --> added to avoid division by 0
#   @desc:  Implementation of the Sorensen-Dice coefficient
#           specifically for class 3: Enhancing
#           Is a measurement of similarity between sets with
#           a small factor added to denominator to
#           prevent divide-by 0 errors.
#
def dice_coef_enhancing(y_true, y_pred, epsilon=1e-6):
    intersection = K.sum(K.abs(y_true[:,:,:,3] * y_pred[:,:,:,3]))
    return (2. * intersection) / (K.sum(K.square(y_true[:,:,:,3])) + K.sum(K.square(y_pred[:,:,:,3])) + epsilon)

############################
#
#   @fname: precision
#   @param: y_true --> ground truth lables
#           y_pred --> predicted labels
#   @desc:  Measure of the precision of model prediction
#
def precision(y_true, y_pred):
        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
        predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
        precision = true_positives / (predicted_positives + K.epsilon())
        return precision

############################
#
#   @fname: sensitivity
#   @param: y_true --> ground truth lables
#           y_pred --> predicted labels
#   @desc:  Measure of the sensitivity of model prediction
#
def sensitivity(y_true, y_pred):
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
    return true_positives / (possible_positives + K.epsilon())

############################
#
#   @fname: specificity
#   @param: y_true --> ground truth lables
#           y_pred --> predicted labels
#   @desc:  Measure of the specificity of model prediction
#
def specificity(y_true, y_pred):
    true_negatives = K.sum(K.round(K.clip((1-y_true) * (1-y_pred), 0, 1)))
    possible_negatives = K.sum(K.round(K.clip(1-y_true, 0, 1)))
    return true_negatives / (possible_negatives + K.epsilon())

############################
#
#   @fname: pathListIntoIds
#   @param: dirList   --> List of directories
#   @desc:  Converts list of directories into ids
#           so that they can be used to manipulate
#           the data more easily
#
def pathListIntoIds(dirList):
    x = []
    for i in range(0,len(dirList)):
        x.append(dirList[i][dirList[i].rfind('/')+1:])
    return x


__author__ = 'Cody'

from django.conf import settings
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.http import HttpRequest
from django_mako_plus.controller import view_function
from django.shortcuts import render
from django_mako_plus.controller.router import get_renderer
import chf.models as chfmod
from django.shortcuts import render
from django_mako_plus.controller.router import get_renderer
from django import forms
from django.contrib.auth.decorators import permission_required

templater = get_renderer('chf')

@view_function
#@permission_required('chf.add_item', login_url='/mylogin')
def process_request(request):

    params = {}

    if (request.urlparams[0]):
        items = chfmod.ProductSpecification.objects.filter(name__icontains=request.urlparams[0])
        params['items'] = items
        return templater.render_to_response(request, '/items.html', params)

    items = chfmod.ProductSpecification.objects.all()
    params['items'] = items

    print(items)

    return templater.render_to_response(request, '/items.html', params)

###############################################################

@view_function
def edit(request):

    params = {}

    try:
        item = chfmod.Item.objects.get(id=request.urlparams[0])
    except:
        return HttpResponseRedirect('/items')

    form = ItemEditForm(initial={

        'name': item.name,
        'description': item.description,
        'value': item.value,
        'standard_rental_price': item.standard_rental_price,
        'is_rentable': item.is_rentable,
    })
    if request.method == 'POST':
        form = ItemEditForm(request.POST)
        if form.is_valid():
            item.name = form.cleaned_data['name']
            item.description = form.cleaned_data['description']
            item.value = form.cleaned_data['value']
            item.standard_rental_price_price = form.cleaned_data['standard_rental_price']
            item.is_rentable = form.cleaned_data['is_rentable']
            item.save()
            return HttpResponseRedirect('/items')

    params['form'] = form
    return templater.render_to_response(request, '/items.edit.html', params)

class ItemEditForm(forms.Form):
    name = forms.CharField(required=True, max_length=100)
    description = forms.CharField(required=True, max_length=400)
    value = forms.DecimalField(required=True, max_digits=10, decimal_places=2)
    standard_rental_price = forms.DecimalField(required=True, max_digits=10, decimal_places=2)
    is_rentable = forms.BooleanField(required=False)

    def clean_username(self):
        user_count = chfmod.User.objects.filter(username=self.cleaned_data['username']).exclude(id=self.userid).count()
        if user_count >=1:
            raise forms.ValidationError("This username is already taken.")

        return self.cleaned_data['username']

@view_function
def create(request):
    '''Create new user'''
    item = chfmod.Item()
    item.name = ""
    item.description = ""
    item.is_rentable = False
    item.save()

    return HttpResponseRedirect('/items.edit/{}'.format(item.id))

###########################################################################

@view_function
def delete(request):

    params = {}

    try:
        item = chfmod.Item.objects.get(id=request.urlparams[0])
    except:
        return HttpResponseRedirect('/items')

    item.delete()
    return HttpResponseRedirect('/items')

###########################################################################

@view_function
def view(request):

    params = {}

    try:
        item = chfmod.ProductSpecification.objects.get(id=request.urlparams[0])
    except:
        return HttpResponseRedirect('/items')

    params['item'] = item

    return templater.render_to_response(request, '/items.view.html', params)


"""
Original Code: Toni Mlinarevic
Edited by: Jackson Barr
Modified to include timeout if ngram extraction takes too long / gets stuck
and wrapped extraction process in a function

For each file in input directory (which contains hexadecimal representations of executables),
find unique n-grams and save them in a new file of the same name in output directory

"""

import os
from tqdm import tqdm

from functools import wraps
import errno
import signal
from pathlib import Path
import pandas as pd
from numpy import savetxt

class TimeoutError(Exception):
    pass

# Decorator that uses signal library to raise error if ngram extraction takes longer than specified time
def timeout(seconds=10, error_message=os.strerror(errno.ETIME)):
    def decorator(func):
        def _handle_timeout(signum, frame):
            raise TimeoutError(error_message)

        def wrapper(*args, **kwargs):
            signal.signal(signal.SIGALRM, _handle_timeout)
            signal.alarm(seconds)
            try:
                result = func(*args, **kwargs)
            finally:
                signal.alarm(0)
            return result

        return wraps(func)(wrapper)

    return decorator

@timeout(20) # allows 20 seconds per file
def extract_ngrams(file, input_dir, output_dir, write = "text"):
    with open(input_dir +"/"+ file) as hex_file:
            hex_string = hex_file.read().replace("\n", "")

            n_grams = []
            for i in range(int(len(hex_string)/2)-1):
                n_grams.append(hex_string[i*2 : (i+n)*2])

            # Options to choose how data is stored
            if write == "panda":
                df = pd.DataFrame(n_grams)
                df.to_csv(output_dir  + "/" + file, index = False)
            elif write == "text":
                fileout = open(output_dir  + "/" + file,"w")
                for n_gram in n_grams:
                    fileout.write(n_gram + "\n")
                fileout.close()
            elif write == "numpy":
                filename = output_dir  + "/" + file
                savetxt(filename, n_grams, newline = "\n", fmt = "%s")

sub_dirs = ["00352_windows_good_test", "00355_windows_good_test", "00380_windows_good_train",
"00381_windows_good_test","00387_windows_good_train", "test_benign_dll", "test_benign_exe",
 "train_benign_dll1", "train_benign_dll2", "train_benign_exe"]

input_dir = "../XOR"
output_dir = "../hex_distinct/XOR_2grams"
n = 2 # n-gram size

if __name__ == "__main__":

    broken_files = []
    for dir in sub_dirs:
        filenames = sorted(os.walk(input_dir + "/" + dir))[0][2]

        if not os.path.exists(output_dir + "/" + dir):
            os.makedirs(output_dir + "/" + dir)

        print(dir)
        for filename in tqdm(filenames):
            in_dir = input_dir + "/" + dir
            out_dir = output_dir + "/" + dir
            try:
                extract_ngrams(filename, in_dir, out_dir)
            except Exception:
                broken_files.append(in_dir + "/" + filename)
                print("Skipping: " + in_dir + "/" + filename)

    df = pd.DataFrame(broken_files)
    df.to_csv("broken_files.csv", index = False)


import os
import whisper
import torch
import atlas_settings

#whisper can run on cpu but gpu is basically necessary

torch.cuda.is_available()
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
print(DEVICE)

model = whisper.load_model(atlas_settings.model_settings, device=DEVICE)
task=atlas_settings.whisper_task_settings
no_speech_threshold = atlas_settings.no_speech_threshold
lang = atlas_settings.language
output_directory = atlas_settings.transcripts_directory

print('looping..')
while True:
    oldest_file = atlas_settings.newest(atlas_settings.recordings_directory)

    audio = whisper.load_audio(atlas_settings.recordings_directory+oldest_file)
    audio = whisper.pad_or_trim(audio)
    mel = whisper.log_mel_spectrogram(audio).to(model.device)
    if lang == None:
        _, probs = model.detect_language(mel)

    options = whisper.DecodingOptions(language=lang, without_timestamps=True, fp16 = False)

    result = whisper.decode(model, mel, options)
    result = model.transcribe(atlas_settings.recordings_directory+oldest_file, task = task, no_speech_threshold=no_speech_threshold)

    if(atlas_settings.whisper_task_settings == "translate"):
        print(result['text'])
    elif(atlas_settings.whisper_task_settings == "transcribe"):
        new_file = atlas_settings.get_filename()
        with open(output_directory+new_file+'.txt', "w", encoding="utf-8") as file:
            file.write(repr(result['text']))
        file.close()

    # delete the file after transcription
    os.remove(os.path.join(atlas_settings.recordings_directory, oldest_file))


"""CLI application for a prefix-notation calculator."""
from arithmetic import (add, subtract, multiply, divide, square, cube,
                        power, mod, )

# Repeat forever
while True:

    # Get equation from user
    equation = input("Your equation: ")

    # Tokenize equation
    token = equation.split(" ")

    # Input validation
    #Too few entries
    if token[0] in ["+", "-", "*", "power", "/", "mod"] and len(token) < 3:
        print("Enter two numbers.")
        continue

    # Non-numeric Entries
    if not token[1].isdigit() or not token[2].isdigit():
        print ("please enter a number")
        continue

    # Invalid arithmetic symbol
    if token[0] not in ["+", "-", "*", "power", "square", "/", "cube", "mod"]:
        print ("Invalid Arithmatic")

    # assign variables to tokens and float
    arith = token[0]

    # assign variable if token[1]/token[2] exist
    if len(token) == 2:
        num1 = float(token[1])

    if len(token) == 3:
        num2 = float(token[2])

    # Quit if first token is q
    if token[0] == "q":
        quit()
    else:
        #Add function
        if arith == "+":
            print(add(num1, num2))
        # Subtract
        elif arith == "-":
            print(subtract(num1, num2))
        # multiply
        elif arith == "*":
            print(multiply(num1, num2))
        # divide
        elif arith == "/":
            print(divide(num1, num2))
        # square
        elif arith == "square":
            print(square(num1))
        # cube
        elif arith == "cube":
            print(cube(num1))
        # power
        elif arith == "pow":
            print(power(num1, num2))
        # mod
        elif arith == "mod":
            print(mod(num1, num2))


from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton as InKB

class Lecture:
    def __init__(self, data: tuple, table_name: str):
        self.table_name = table_name
        self.lect_semi = data[1]
        self.name = data[2]
        self.description = data[3]
        self.poster = data[4]
        self.lect_url = data[5]
        self.semi_url = data[6]
        self.comp_url = data[7]
        self.date = data[8]
        self.price = data[9]
        self._finished = data[10]

    @property
    def is_finished(self):
        return True if self._finished else False

    def info(self, price: bool = False):
        prefix = 'Лекция: ' if self.lect_semi == 1 else 'Семинар: '
        suffix = f'\n\nЦена лекции: {self.price} руб' if price else ''
        return prefix + f'{self.name}\n{self.description}' + suffix

    @property
    def buttons(self):
        btn_list = ['Лекция', 'Семинар', 'Конспект']
        url_list = [self.lect_url, self.semi_url, self.comp_url]
        btn_list = [InKB(text=btn_list[i], url=url_list[i]) for i in range(3) if url_list[i]]
        return btn_list


#reverse singly linked list
# 2 -> 3 -> 5
class LinkedList:
    def __init__(self, next = None,val = 0):
        self.next = next
        self.val = val

# 2 3 5
list1 = LinkedList(2)
list1.next = LinkedList(3)

def reverseLinkedList(list1):
    prev= None
    curr = list1
    while curr:
        next_node = curr.next
        curr.next = prev
        prev = curr
        curr = next_node
    return prev #return the head of the reversed linked list

# 1 2 3
# 2 4 5 6
# 1 2 2  3 4 5 6

def combineLinkedLists(list1, list2):
    list3 = LinkedList()
    curr = list3

    while list1 or list2:
        if list1:
            next_val = list1.val
            list1 = list1.next
        elif list2:
            next_val = list2.val
            list2 = list2.next
        else:
            #both have values
            if list1.val <= list2.val:
                next_val = list1.val
                list1= list1.next
            else:
                next_val = list2.val
                list2 = list2.next
        #update our 3rd linked list pointers
        curr.next = ListNode(next_val)
        curr = curr.next
    return list3.next


# Databricks notebook source
from pyspark.sql.types import *
from pyspark.sql.functions import *

# Device log files are written to the stream folder
inputPath = "wasbs://spark@ACCOUNT_NAME.blob.core.windows.net/stream/"

# Each log contains a device and a status
jsonSchema = StructType([
  StructField("device", StringType(), False),
  StructField("status", StringType(), False)
])

# Continually read dataframes from the stream based on the schema
inStream = spark.readStream.schema(jsonSchema).option("maxFilesPerTrigger", 1).json(inputPath)

# Filter the dataframe to include only errors, and count them per-device
countErrors = inStream.filter("status == 'error'").groupBy(window(current_timestamp(), "1 minute"), "device").count()

# Write the stream of processed data to a table (in memory for this example)
outStream = countErrors.writeStream.format("memory").queryName("counts").outputMode("complete").start()

# COMMAND ----------

# MAGIC %sql
# MAGIC -- Read the in-memory table
# MAGIC select device, window.start, window.end, count from counts

# COMMAND ----------

# stop processing the stream
outStream.stop()


def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i - 1
        while j >= 0 and key < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = key
    return arr

def main():
    l = list(map(int, input('Enter element of list: ').split()))
    l = insertion_sort(l)
    print('Sorted list is: ', l)

if __name__ == '__main__':
    main()


import requests
from decouple import config

FLIGHT_DEALS_SHEETY_API = config("FLIGHT_DEALS_SHEETY_API", default="")
auth = (config("FLIGHT_DEALS_BASIC_AUTH_USER", default=''), config("FLIGHT_DEALS_BASIC_AUTH_PASS", default=''))
USER_FLIGHT_DEALS_SHEETY_API = config("USER_FLIGHT_DEALS_SHEETY_API", default="")

class DataManager:
    def __init__(self):
        self.price_data = {}
        self.user_data = {}

    def get_price_data(self) -> {}:
        google_sheet_response = requests.get(f"{FLIGHT_DEALS_SHEETY_API}", auth=auth)
        google_sheet_response.raise_for_status()
        self.price_data = google_sheet_response.json()["prices"]
        print(self.price_data)
        return self.price_data

    def update_iata_code(self):
        for city in self.price_data:
            parameters = {
                "price": {
                    "iataCode": city["iataCode"]
                }
            }
            update_sheet = requests.put(f"{FLIGHT_DEALS_SHEETY_API}/{city['id']}", auth=auth,
                                        json=parameters)
            update_sheet.raise_for_status()

    def get_users_data(self) -> {}:
        google_sheet_response = requests.get(f"{USER_FLIGHT_DEALS_SHEETY_API}", auth=auth)
        google_sheet_response.raise_for_status()
        self.user_data = google_sheet_response.json()["users"]
        return self.user_data

    def post_users_data(self, f_name, l_name, email):
        params = {
            "user": {
                'firstName': f_name,
                'lastName': l_name,
                'email': email
            }
        }
        google_sheet_response = requests.post(f"{USER_FLIGHT_DEALS_SHEETY_API}", auth=auth, json=params)
        google_sheet_response.raise_for_status()
        print(google_sheet_response.json())
        return self.user_data


import numpy as np
from numpy.polynomial.polynomial import polyfit, polyvander, polyval

def basecorr1D(x=None, y=None, polyorder=0, window=20, *args,**kwargs):
    '''
    Function that achieve a baseline correction by fitting a function a the
    edge of the data via a window parameter.
    The baseline correction is carried out via the polyfit function:
        (https://numpy.org/doc/stable/reference/generated/numpy.polynomial.polynomial.polyfit.html)
    that Compute least-squares solution to equation V(x) * c = w * y, with V the
    Vandermonde matrix, c the polynomial coefficient, w some weights parameters
    and y the data column vector.

    p(x) = c_0 + c_1 * x + ... + c_n * x^n,

    This script is freely inspired by the easyspin suite from the Stefan Stoll lab
    (https://github.com/StollLab/EasySpin/)
    (https://easyspin.org/easyspin/)

    Script written by Timothée Chauviré (https://github.com/TChauvire/EPR_ESR_Suite/), 09/09/2020

    Parameters
    ----------
    x : abscissa of the data, TYPE : numpy data array, column vector
        DESCRIPTION. The default is None.
    y : data which baseline has to be corrected,
        TYPE : numpy data array, column vector
        It has to have the same size than x
        DESCRIPTION. The default is None.
    polyorder : order of the polynomial fitted for background subtraction
        TYPE : Integer, optional
        DESCRIPTION. The default is 0.
    window : window used at the start and the end of the data. TYPE: integer, optional
        DESCRIPTION. The default is 20.
        By instance, if window = 20, the fit of the background will be achieved on
        np.array([y[:20],y[-20:]]).ravel()

    Returns
    -------
    ynew : baseline corrected data.
        TYPE: numpy data array, same shape as input data y
    c : coefficient used for the polynomial fit as returned by the
        numpy.polynomial.polynomial.polyfit function
        TYPE : tuple of real values, coefficient of the polynomial from low order to high order rank.
    error_parameters : error associated with the polynomial coefficients,
        TYPE : tuple of real values,
        DESCRIPTION: This error is evaluated via the function error_vandermonde()
        by calculating the covariance matrix and diagonalize it.
    cov : Covariance matrix associated to the Vandermonde matrix of the fitted poynomial.
        TYPE : Square Matrix

    '''
    shape = y.shape
    if x.shape[0] != np.ravel(x).shape[0]:
        raise ValueError('y must be a column vector. basecorr1D function does not work on 2D arrays.')
    else:
        x = np.ravel(x)

    if y.shape[0] != np.ravel(y).shape[0]:
        raise ValueError('y must be a column vector. basecorr1D function does not work on 2D arrays.')
    else:
        y = np.ravel(y)

    if y.shape[0] != x.shape[0]:
        raise ValueError('x and y must be column vector of the same size.')

    ynew = np.full(y.shape,np.nan)
    xfit = np.array([x[:window],x[-window:]]).ravel()
    yfit = np.array([y[:window],y[-window:]]).ravel()
    c, stats = polyfit(xfit,yfit,polyorder,full=True)
    ynew = y-polyval(x,c)
    error_parameters,cov = error_vandermonde(x,residuals=stats[0],rank=polyorder)
    ynew = ynew.reshape(shape)
    return ynew,c,error_parameters,cov

def error_vandermonde(x,residuals=None,rank=None,*args,**kwargs):
    '''
    Function to generate 1) error estimation on parameters determined by the function
    coef, [residuals, rank, singular_values, rcond] = numpy.polynomial.polynomial.polyfit()
    2) covariance matrix associated.

    The Vandermonde matrix generated by vand = polyvander(x,rank)
    The Covariance matrix cov is obtained via the vandermonde matrix V
    via this numerical steps:
        1) compute np.dot(V.T,V).inv
        2) and multiply it by the residual/(nb of data points - nb of coefficients)
    The error parameters are then computed via : error_parameters = np.sqrt(np.diag(cov))

    Script written by Timothée Chauviré (https://github.com/TChauvire/EPR_ESR_Suite/), 09/09/2020

    Parameters
    ----------
    residuals : first value generated by polyfit in the list of the second output
        DESCRIPTION. float number. The default is None.
    vandermonde : Vandermonde matrix generated by vand = polyvander(x,rank)
        DESCRIPTION. The default is None.

    rank : necessary for multidimensional array
        DESCRIPTION. The default is None.

    Raises
    ------
    ValueError if rank is higher than the number of points
        "the number of data points must exceed order "
                                 "to scale the covariance matrix".

    Returns
    -------
    error_parameters : error uncertainties estimated on the parameters ordered
    from low to high polynomial order.
    By example for a linear model f(x)=a0+a1*x :
        error_parameters[0] = constant parameters a0,
        error_parameters[1] = slope a1.

    cov : covariance estimated for the Least-squares fit of a polynomial to data
        return a Matrix(Rank by rank)
    '''
    if len(x) <= rank:
        raise ValueError("the number of data points must exceed order "
                                 "to scale the covariance matrix")
    else:
        v = polyvander(x,rank) # generate the vandermonde matrix
        cov = residuals/(len(x) - rank)*np.linalg.inv(np.dot(v.T, v))
        error_parameters=np.sqrt(np.diag(cov))

    return error_parameters,cov


"""config URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from home import views as home_views
from checkout import views as checkout_views
from django.urls import include,path
from rest_framework import routers
from django.conf import settings
from django.conf.urls.static import static

router = routers.DefaultRouter()
router.register(r'product-entries',home_views.ProductEntryViewSet)
router.register(r'users',home_views.UserViewSet)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',home_views.home, name="home"),
    path('cart/add/<int:id>/', home_views.cart_add, name='cart_add'),
    path('cart/item_increment/<int:id>/',home_views.item_increment, name='item_increment'),
    path('cart/item_decrement/<int:id>/',home_views.item_decrement, name='item_decrement'),
    path('cart/item_clear/<int:id>/', home_views.item_remove, name='item_remove'),
    path('cart/cart-detail/',home_views.cart_detail,name='cart_detail'),
    path('api/v1/', include(router.urls)),
    path('api-auth/v1/', include('rest_framework.urls', namespace='rest_framework')),
    path('join/',home_views.user_join),
    path('login/', home_views.user_login),
    path('logout',home_views.user_logout),

    path('payment/', checkout_views.PaymentPageView, name='payment'),
    path('charge/', checkout_views.charge, name='charge'),
    path('orders/', checkout_views.Orders,name= 'orders'),
    path('about/', home_views.about_me),

]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


import base64
import os
import datetime
from typing import Optional

class Image:
    def __init__(self, filepath: str) -> None:
        self.filepath = filepath
        self.basename = os.path.basename(self.filepath)
        self.dirname = os.path.dirname(self.filepath)
        self.filename, self.fileext = os.path.splitext(self.basename)

        self.m_id = os.path.splitext(self.filename)[0]
        self.datetime = datetime.datetime.utcfromtimestamp(
            os.path.getmtime(filepath)
        )

        self.png_str = self.encode_png()
        self.slide_num: Optional[int] = None

    def encode_png(self) -> str:
        """Encodes an image to base64

        Returns:
            str: data uri of the image
        """
        with open(self.filepath, "rb") as f:
            png_str = "data:image/png;base64, " + base64.b64encode(
                f.read()
            ).decode("ascii")
        return png_str


#future leap year from current year to a final year
r= list()
yr1 = int(input("enter a year:"))
yr2= int(input("enter any year in the future:"))
for i in range(yr1,yr2+1):
	if i%4==0 and i%100== 0 and i%400==0:
	    r.append(i)
	elif i%4 ==0  and i%100 !=0:
	    r.append(i)
	else:
	    continue

print ("The leap years are:",r) #list of leap year


"""
Lunch Money - Categories

https://lunchmoney.dev/#categories
"""

import datetime
import json
import logging
from typing import List, Optional

from pydantic import Field

from lunchable._config import APIConfig
from lunchable.exceptions import LunchMoneyError
from lunchable.models._base import LunchableModel
from lunchable.models._core import LunchMoneyAPIClient
from lunchable.models._descriptions import _CategoriesDescriptions

logger = logging.getLogger(__name__)

class ModelCreateCategory(LunchableModel):
    """
    https://lunchmoney.dev/#create-category
    """

    name: str
    description: Optional[str] = None
    is_income: Optional[bool] = False
    exclude_from_budget: Optional[bool] = False
    exclude_from_totals: Optional[bool] = False

class CategoryChild(LunchableModel):
    """
    Child Entry on the Category Object
    """

    id: int
    name: str = Field(min_length=1, max_length=40)
    description: Optional[str] = Field(None, max_length=140)
    created_at: Optional[datetime.datetime] = None

class CategoriesObject(LunchableModel):
    """
    Lunch Money Spending Categories

    https://lunchmoney.dev/#categories-object
    """

    id: int = Field(description="A unique identifier for the category.")
    name: str = Field(
        min_length=1,
        max_length=40,
        description=_CategoriesDescriptions.name,
    )
    description: Optional[str] = Field(
        None, max_length=140, description=_CategoriesDescriptions.description
    )
    is_income: bool = Field(description=_CategoriesDescriptions.is_income)
    exclude_from_budget: bool = Field(
        description=_CategoriesDescriptions.exclude_from_budget
    )
    exclude_from_totals: bool = Field(
        description=_CategoriesDescriptions.exclude_from_totals
    )
    updated_at: Optional[datetime.datetime] = Field(
        None, description=_CategoriesDescriptions.updated_at
    )
    created_at: Optional[datetime.datetime] = Field(
        None, description=_CategoriesDescriptions.created_at
    )
    is_group: bool = Field(description=_CategoriesDescriptions.is_group)
    group_id: Optional[int] = Field(None, description=_CategoriesDescriptions.group_id)
    children: Optional[List[CategoryChild]] = Field(
        None,
        description=_CategoriesDescriptions.children,
    )

class _CategoriesParamsPut(LunchableModel):
    """
    https://lunchmoney.dev/#update-category
    """

    name: Optional[str] = Field(None, min_length=1, max_length=40)
    description: Optional[str] = Field(None, max_length=140)
    is_income: Optional[bool] = None
    exclude_from_budget: Optional[bool] = None
    exclude_from_totals: Optional[bool] = None
    group_id: Optional[int] = None

class _CategoriesParamsPost(LunchableModel):
    """
    https://lunchmoney.dev/#create-category-group
    """

    name: str
    description: Optional[str] = None
    is_income: Optional[bool] = False
    exclude_from_budget: Optional[bool] = False
    exclude_from_totals: Optional[bool] = False
    category_ids: Optional[List[int]] = None
    new_categories: Optional[List[str]] = None

class _CategoriesAddParamsPost(LunchableModel):
    """
    https://lunchmoney.dev/#add-to-category-group
    """

    category_ids: Optional[List[int]] = None
    new_categories: Optional[List[str]] = None

class CategoriesClient(LunchMoneyAPIClient):
    """
    Lunch Money Categories Interactions
    """

    def get_categories(self) -> List[CategoriesObject]:
        """
        Get Spending categories

        Use this endpoint to get a list of all categories associated with the user's account.
        https://lunchmoney.dev/#get-all-categories

        Returns
        -------
        List[CategoriesObject]
        """
        response_data = self.make_request(
            method=self.Methods.GET, url_path=APIConfig.LUNCHMONEY_CATEGORIES
        )
        categories = response_data["categories"]
        category_objects = [
            CategoriesObject.model_validate(item) for item in categories
        ]
        return category_objects

    def insert_category(
        self,
        name: str,
        description: Optional[str] = None,
        is_income: Optional[bool] = False,
        exclude_from_budget: Optional[bool] = False,
        exclude_from_totals: Optional[bool] = False,
    ) -> int:
        """
        Create a Spending Category

        Use this to create a single category
        https://lunchmoney.dev/#create-category

        Parameters
        ----------
        name: str
            Name of category. Must be between 1 and 40 characters.
        description: Optional[str]
            Description of category. Must be less than 140 categories. Defaults to None.
        is_income: Optional[bool]
            Whether or not transactions in this category should be treated as income.
            Defaults to False.
        exclude_from_budget: Optional[bool]
            Whether or not transactions in this category should be excluded from budgets.
            Defaults to False.
        exclude_from_totals: Optional[bool]
            Whether or not transactions in this category should be excluded from
            calculated totals. Defaults to False.

        Returns
        -------
        int
            ID of the newly created category
        """
        category_body = ModelCreateCategory(
            name=name,
            description=description,
            is_income=is_income,
            exclude_from_budget=exclude_from_budget,
            exclude_from_totals=exclude_from_totals,
        ).model_dump(exclude_none=True)
        response_data = self.make_request(
            method=self.Methods.POST,
            url_path=APIConfig.LUNCHMONEY_CATEGORIES,
            payload=category_body,
        )
        return response_data["category_id"]

    def get_category(self, category_id: int) -> CategoriesObject:
        """
        Get single category

        Use this endpoint to get hydrated details on a single category. Note that if
        this category is part of a category group, its properties (is_income,
        exclude_from_budget, exclude_from_totals) will inherit from the category group.

        https://lunchmoney.dev/#get-single-category

        Parameters
        ----------
        category_id : int
            Id of the Lunch Money Category

        Returns
        -------
        CategoriesObject
        """
        response_data = self.make_request(
            method=self.Methods.GET,
            url_path=[APIConfig.LUNCHMONEY_CATEGORIES, category_id],
        )
        return CategoriesObject.model_validate(response_data)

    def remove_category(self, category_id: int) -> bool:
        """
        Delete a single category

        Use this endpoint to delete a single category or category group. This will
        only work if there are no dependencies, such as existing budgets for the
        category, categorized transactions, categorized recurring items, etc. If
        there are dependents, this endpoint will return what the dependents are
        and how many there are.

        https://lunchmoney.dev/#delete-category

        Parameters
        ----------
        category_id : int
            Id of the Lunch Money Category

        Returns
        -------
        bool
        """
        response_data = self.make_request(
            method=self.Methods.DELETE,
            url_path=[APIConfig.LUNCHMONEY_CATEGORIES, category_id],
        )
        if response_data is not True:
            raise LunchMoneyError(
                f"That Category ({category_id}) has Dependents: "
                f"{json.dumps(response_data, indent=4)}"
            )
        return response_data

    def remove_category_force(self, category_id: int) -> bool:
        """
        Forcefully delete a single category

        Use this endpoint to force delete a single category or category group and
        along with it, disassociate the category from any transactions, recurring
        items, budgets, etc.

        Note: it is best practice to first try the Delete Category endpoint to ensure
        you don't accidentally delete any data. Disassociation/deletion of the data
        arising from this endpoint is irreversible!

        https://lunchmoney.dev/#force-delete-category

        Parameters
        ----------
        category_id : int
            Id of the Lunch Money Category

        Returns
        -------
        bool
        """
        response_data = self.make_request(
            method=self.Methods.DELETE,
            url_path=[APIConfig.LUNCHMONEY_CATEGORIES, category_id, "force"],
        )
        return response_data

    def update_category(
        self,
        category_id: int,
        name: Optional[str] = None,
        description: Optional[str] = None,
        is_income: Optional[bool] = None,
        exclude_from_budget: Optional[bool] = None,
        exclude_from_totals: Optional[bool] = None,
        group_id: Optional[int] = None,
    ) -> bool:
        """
        Update a single category

        Use this endpoint to update the properties for a single category or category group

        https://lunchmoney.dev/#update-category

        Parameters
        ----------
        category_id : int
            Id of the Lunch Money Category
        name: str
            Name of category. Must be between 1 and 40 characters.
        description: Optional[str]
            Description of category. Must be less than 140 categories. Defaults to None.
        is_income: Optional[bool]
            Whether or not transactions in this category should be treated as income.
            Defaults to False.
        exclude_from_budget: Optional[bool]
            Whether or not transactions in this category should be excluded from budgets.
            Defaults to False.
        exclude_from_totals: Optional[bool]
            Whether or not transactions in this category should be excluded from
            calculated totals. Defaults to False.
        group_id: Optional[int]
            For a category, set the group_id to include it in a category group

        Returns
        -------
        bool
        """
        payload = _CategoriesParamsPut(
            name=name,
            description=description,
            is_income=is_income,
            exclude_from_budget=exclude_from_budget,
            exclude_from_totals=exclude_from_totals,
            group_id=group_id,
        ).model_dump(exclude_none=True)
        response_data = self.make_request(
            method=self.Methods.PUT,
            url_path=[APIConfig.LUNCHMONEY_CATEGORIES, category_id],
            payload=payload,
        )
        return response_data

    def insert_category_group(
        self,
        name: str,
        description: Optional[str] = None,
        is_income: Optional[bool] = False,
        exclude_from_budget: Optional[bool] = False,
        exclude_from_totals: Optional[bool] = False,
        category_ids: Optional[List[int]] = None,
        new_categories: Optional[List[str]] = None,
    ) -> int:
        """
        Create a Spending Category Group

        Use this endpoint to create a single category group
        https://lunchmoney.dev/#create-category-group

        Parameters
        ----------
        name: str
            Name of category. Must be between 1 and 40 characters.
        description: Optional[str]
            Description of category. Must be less than 140 categories. Defaults to None.
        is_income: Optional[bool]
            Whether or not transactions in this category should be treated as income.
            Defaults to False.
        exclude_from_budget: Optional[bool]
            Whether or not transactions in this category should be excluded from budgets.
            Defaults to False.
        exclude_from_totals: Optional[bool]
            Whether or not transactions in this category should be excluded from
            calculated totals. Defaults to False.
        category_ids: Optional[List[int]]
            Array of category_id to include in the category group.
        new_categories: Optional[List[str]]
            Array of strings representing new categories to create and subsequently
            include in the category group.

        Returns
        -------
        int
            ID of the newly created category group
        """
        payload = _CategoriesParamsPost(
            name=name,
            description=description,
            is_income=is_income,
            exclude_from_budget=exclude_from_budget,
            exclude_from_totals=exclude_from_totals,
            category_ids=category_ids,
            new_categories=new_categories,
        ).model_dump(exclude_none=True)
        response_data = self.make_request(
            method=self.Methods.POST,
            url_path=[APIConfig.LUNCHMONEY_CATEGORIES, "group"],
            payload=payload,
        )
        return response_data["category_id"]

    def insert_into_category_group(
        self,
        category_group_id: int,
        category_ids: Optional[List[int]] = None,
        new_categories: Optional[List[str]] = None,
    ) -> CategoriesObject:
        """
        Add to a Category Group

        Use this endpoint to add categories (either existing or new) to a single
        category group

        https://lunchmoney.dev/#add-to-category-group

        Parameters
        ----------
        category_group_id: int
            Id of the Lunch Money Category Group
        category_ids: Optional[List[int]]
            Array of category_id to include in the category group.
        new_categories: Optional[List[str]]
            Array of strings representing new categories to create and subsequently
            include in the category group.

        Returns
        -------
        CategoriesObject
        """
        payload = _CategoriesAddParamsPost(
            category_ids=category_ids, new_categories=new_categories
        ).model_dump(exclude_none=True)
        response_data = self.make_request(
            method=self.Methods.POST,
            url_path=[
                APIConfig.LUNCHMONEY_CATEGORIES,
                "group",
                category_group_id,
                "add",
            ],
            payload=payload,
        )
        return CategoriesObject.model_validate(response_data)


#!/usr/bin/env python
#
# pcap.py
#
# Pcap file decoder for the standard TCP/IP stack
#
# This is a basic decoder for TCP packets composed of IP and ETH packets within
# a pcap file. Other types of packets are simply denoted with 'UNK' and are not
# decoded any further. This is used for post-mortem analysis of network traffic
# captured beforehand.
#
# As an example use, `tcpdump` can be used to capture packets to a pcap file:
#
#     sudo tcpdump -w example.pcap
#
# Output file can then be given to this script to print the decoded output:
#
#     ./pcap.py example.pcap
#
# An example output of this script is as follows:
#
#     -- ETH Layer -- Tue Jun  5 10:52:34 2012 -- 54 bytes
#             src: 00:12:cf:e5:54:a0
#             dst: 00:1f:3c:23:db:d3
#             typ: 8
#             -- IP Layer --
#                     src: 192.168.10.226
#                     dst: 192.168.11.12
#                     typ: 6
#                     -- TCP Layer --
#                             src: 64332
#                             dst: 5888
#                             seq: 1492699879
#                             ack: 3729068838
#                             dat: b''
#     -- ETH Layer -- Tue Jun  5 10:52:35 2012 -- 60 bytes
#             src: 00:1f:3c:23:db:d3
#             dst: 00:12:cf:e5:54:a0
#             typ: 8
#             -- IP Layer --
#                     src: 192.168.11.12
#                     dst: 192.168.10.226
#                     typ: 6
#                     -- TCP Layer --
#                             src: 5888
#                             dst: 64332
#                             seq: 3729068838
#                             ack: 1509477095
#                             dat: b'\x00\x00\x00\x00\x00\x00'
#
# Indentation follows packet levels so that you can utilize folding feature in
# your text editor to display packets at the desired level. Following settings
# are used for vim editor:
#
#     set foldmethod=indent
#     set foldenable
#     set foldlevel=0 " only show packets
#     set foldlevel=1 " decode ETH layer
#     set foldlevel=2 " decode IP layer
#     set foldlevel=3 " decode TCP layer
#
# You can also directly read from stdin as follows:
#
#     ./pcap example.pcap | vim -
#

import sys
import time
import struct

if len(sys.argv) < 2:
    sys.stderr.write(f"usage: {sys.argv[0]} [PCAP_FILE]\n")
    sys.exit(1)

def decode_eth(packet):
    src = struct.unpack("6B", packet[0:6])
    dst = struct.unpack("6B", packet[6:12])
    typ = struct.unpack("H", packet[12:14])[0]
    return src, dst, typ

def decode_ip(packet):
    typ = struct.unpack("B", packet[9:10])[0]
    src = struct.unpack("4B", packet[12:16])
    dst = struct.unpack("4B", packet[16:20])
    return src, dst, typ

def decode_tcp(packet):
    src = struct.unpack("H", packet[0:2])[0]
    dst = struct.unpack("H", packet[2:4])[0]
    seq = struct.unpack("I", packet[4:8])[0]
    ack = struct.unpack("I", packet[8:12])[0]
    return src, dst, seq, ack

with open(sys.argv[1], "rb") as f:
    bom, major, minor, off, cap, typ = struct.unpack("IHHQII", f.read(24))
    if typ != 1:
        sys.stderr.write("error: only ethernet frame is supported\n")
        sys.exit(1)

    while True:
        header = f.read(16)
        if not header:
            break

        sec, msec, real, size = struct.unpack("IIII", header)
        print("-- ETH Layer --", time.ctime(sec), "--", size, "bytes")
        packet = f.read(size)

        eth_src, eth_dst, eth_typ = decode_eth(packet)
        print("\tsrc:", ":".join("%02x" % i for i in eth_src))
        print("\tdst:", ":".join("%02x" % i for i in eth_dst))
        print("\ttyp:", eth_typ)

        if eth_typ != 8:
            print("\t-- UNK Layer --")
            print("\t\tdat:", packet[14:])
            continue

        ip_src, ip_dst, ip_typ = decode_ip(packet[14:])
        print("\t-- IP Layer --")
        print("\t\tsrc:", ".".join(str(i) for i in ip_src))
        print("\t\tdst:", ".".join(str(i) for i in ip_dst))
        print("\t\ttyp:", ip_typ)

        if ip_typ != 6:
            print("\t\t-- UNK Layer --")
            print("\t\t\tdat:", packet[34:])
            continue

        tcp_src, tcp_dst, tcp_seq, tcp_ack = decode_tcp(packet[34:])
        print("\t\t-- TCP Layer --")
        print("\t\t\tsrc:", tcp_src)
        print("\t\t\tdst:", tcp_dst)
        print("\t\t\tseq:", tcp_seq)
        print("\t\t\tack:", tcp_ack)
        print("\t\t\tdat:", packet[54:])


# -*- coding: utf-8 -*-
"""setup.py: setuptools control."""

import re
from setuptools import setup

version = re.search(
    '^__version__\s*=\s*"(.*)"',
    open('graphene_ai/graphene.py').read(),
    re.M
    ).group(1)

with open("README.rst", "rb") as f:
    long_descr = f.read().decode("utf-8")

setup(
    name = "graphene_ai",
    packages = ["graphene_ai"],
    entry_points = {
        "console_scripts": ['graphene = graphene.graphene:main']
        },
    version = '0.1',
    description = "Graphene AI API.",
    long_description = long_descr,
    author = "Francis Bautista",
    author_email = "francis.bautista07@gmail.com",
    keywords = ['GRAPHENE', 'AI', 'NATURAL LANGUAGE PROCESSING', 'MULTILINGUAL'],
    url = "https://github.com/graphene-ai/python-graphene-ai",
    install_requires=[
        'argparse',
        'urllib'
    ]
)