#Check
import bpy
import os
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
val = input("Enter the name of the python file(Make sure it is in .obj format): ")
bpy.ops.import_scene.obj(filepath=val + ".obj")
for obj in bpy.context.scene.objects:
    if(obj.type == 'MESH'):
        mesh = obj.data
        objectToSelect = bpy.data.objects[mesh.name]
        objectToSelect.select_set(True)
        bpy.context.view_layer.objects.active = objectToSelect
        bpy.context.object.data.remesh_voxel_size = 0.01
        bpy.ops.object.voxel_remesh()
        bpy.ops.object.editmode_toggle()
        bpy.ops.mesh.select_all(action='SELECT')
        bpy.ops.mesh.mark_sharp(clear=True)
        bpy.ops.object.editmode_toggle()
        bpy.ops.object.shade_smooth()
        bpy.context.object.data.use_auto_smooth = False
        val = input("Enter the name of the output file: ")
        bpy.ops.export_scene.obj(filepath = val + ".obj")


import datetime

from django.http import HttpResponse
from django.shortcuts import render

# Create your views here.
from django.views import View

from .models import Evento, Pais
from .forms import pais_form, evento_form

from django.views.decorators.http import require_http_methods

@require_http_methods(["GET"])
def home_view(request):
    eventos = Evento.objects.all()
    return render(request, 'home.html', {'eventos': eventos})

@require_http_methods(["GET", "POST"])
def pais_view(request):
    if request.method == 'GET':
        form = pais_form()
    else:
        # create a form instance and populate it with data from the request:
        form = pais_form(request.POST)
        if form.is_valid():
            # process the data in form.cleaned_data as required
            obj = Pais(**form.cleaned_data)
            obj.save()
            # redirect to a new URL:
            return HttpResponse('PAIS AGREGADO CON EXITO/')

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

@require_http_methods(["GET", "POST"])
def evento_view(request):
    if request.method == 'GET':
        form = evento_form()
    else:
        # create a form instance and populate it with data from the request:
        form = evento_form(request.POST)
        if form.is_valid():
            obj = Evento(**form.cleaned_data)
            obj.save()
            return HttpResponse('EVENTO AGREGADO CON EXITO/')

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


from __future__ import annotations
from dataclasses import dataclass
from enum import Enum
from typing import List, Optional

# External Dependencies:
import numpy as np
import torch

class AnnotationBoundingBox:
    """Class to parse a bounding box annotated by SageMaker Ground Truth Object Detection

    Pre-calculates all box TLHWBR metrics (both absolute and relative) on init, for efficient and
    easy processing later.
    """

    def __init__(self, manifest_box: dict, image_height: int, image_width: int):
        self._class_id = manifest_box["class_id"]
        self._abs_top = manifest_box["top"]
        self._abs_left = manifest_box["left"]
        self._abs_height = manifest_box["height"]
        self._abs_width = manifest_box["width"]
        self._abs_bottom = self.abs_top + self.abs_height
        self._abs_right = self.abs_left + self.abs_width
        self._rel_top = self._abs_top / image_height
        self._rel_left = self._abs_left / image_width
        self._rel_height = self._abs_height / image_height
        self._rel_width = self._abs_width / image_width
        self._rel_bottom = self._abs_bottom / image_height
        self._rel_right = self._abs_right / image_width

    @property
    def class_id(self):
        return self._class_id

    @property
    def abs_top(self):
        return self._abs_top

    @property
    def abs_left(self):
        return self._abs_left

    @property
    def abs_height(self):
        return self._abs_height

    @property
    def abs_width(self):
        return self._abs_width

    @property
    def abs_bottom(self):
        return self._abs_bottom

    @property
    def abs_right(self):
        return self._abs_right

    @property
    def rel_top(self):
        return self._rel_top

    @property
    def rel_left(self):
        return self._rel_left

    @property
    def rel_height(self):
        return self._rel_height

    @property
    def rel_width(self):
        return self._rel_width

    @property
    def rel_bottom(self):
        return self._rel_bottom

    @property
    def rel_right(self):
        return self._rel_right

class BoundingBoxAnnotationResult:
    """Class to parse the result field saved by a SageMaker Ground Truth Object Detection job"""

    def __init__(self, manifest_obj: dict):
        """Initialize a BoundingBoxAnnotationResult

        Arguments
        ---------
        manifest_obj : dict
            The contents of the output field of a record in a SMGT Object Detection labelling job
            output manifest, or equivalent.
        """
        try:
            image_size_spec = manifest_obj["image_size"][0]
            self._image_height = int(image_size_spec["height"])
            self._image_width = int(image_size_spec["width"])
            self._image_depth = (
                int(image_size_spec["depth"]) if "depth" in image_size_spec else None
            )
        except Exception as e:
            raise ValueError(
                "".join(
                    (
                        "manifest_obj must be a dictionary including 'image_size': a list of ",
                        "length 1 whose first/only element is a dict with integer properties ",
                        f"'height' and 'width', optionally also 'depth'. Got: {manifest_obj}",
                    )
                )
            ) from e
        assert (
            len(manifest_obj["image_size"]) == 1
        ), f"manifest_obj['image_size'] must be a list of len 1. Got: {manifest_obj['image_size']}"

        try:
            self._boxes = [
                AnnotationBoundingBox(
                    b,
                    image_height=self._image_height,
                    image_width=self._image_width,
                )
                for b in manifest_obj["annotations"]
            ]
        except Exception as e:
            raise ValueError(
                "".join(
                    (
                        "manifest_obj['annotations'] must be a list-like of absolute TLHW bounding box ",
                        f"dicts with class_id. Got {manifest_obj['annotations']}",
                    )
                )
            ) from e

    @property
    def image_height(self):
        return self._image_height

    @property
    def image_width(self):
        return self._image_width

    @property
    def image_depth(self):
        return self._image_depth

    @property
    def boxes(self):
        return self._boxes

    def normalized_boxes(
        self,
        return_tensors: Optional[str] = None,
    ):
        """Annotation boxes in 0-1000 normalized x0,y0,x1,y1 array/tensor format as per LayoutLM"""
        raw_zero_to_one_list = [
            [
                box.rel_left,
                box.rel_top,
                box.rel_right,
                box.rel_bottom,
            ]
            for box in self._boxes
        ]
        if return_tensors == "np" or not return_tensors:
            if len(raw_zero_to_one_list) == 0:
                npresult = np.zeros((0, 4), dtype="long")
            else:
                npresult = (np.array(raw_zero_to_one_list) * 1000).astype("long")
            return npresult if return_tensors else npresult.tolist()
        elif return_tensors == "pt":
            if len(raw_zero_to_one_list) == 0:
                return torch.zeros((0, 4), dtype=torch.long)
            else:
                return (torch.FloatTensor(raw_zero_to_one_list) * 1000).long()
        else:
            raise ValueError("return_tensors must be None, 'np' or 'pt'. Got: %s" % return_tensors)

class OCRReviewStatus(str, Enum):
    """Ternary status for OCR transcription review

    TODO: Merge/share with postproc Lambda function if possible?
    """

    correct = "correct"
    unclear = "unclear"
    wrong = "wrong"

@dataclass
class OCREntityWithTranscriptReview:
    detection_id: str
    ocr_status: OCRReviewStatus
    box_ixs: List[int]
    class_id: int  # TODO: This is optional in postproc Lambda's data model, re-align
    raw_text: str  # TODO: This is optional in postproc Lambda's data model, re-align
    target_text: Optional[str]
    label: Optional[str]

    @classmethod
    def from_dict(cls, raw: dict) -> OCREntityWithTranscriptReview:
        """Parse an individual entity annotation as produced by custom SMGT task UI+post-proc"""
        raw_text = raw["rawText"]
        ocr_status = OCRReviewStatus[raw["ocrStatus"]]
        target_text = raw.get("targetText")
        if target_text is None:
            if ocr_status != OCRReviewStatus.wrong:
                target_text = raw_text
            else:
                raise ValueError(
                    "Entity annotation is missing targetText field, but is tagged with ocrStatus "
                    "'wrong' so we can't take the rawText as target: %s" % raw
                )

        return cls(
            detection_id=raw["detectionId"],
            ocr_status=ocr_status,
            box_ixs=raw["boxIxs"],
            class_id=raw["classId"],
            raw_text=raw_text,
            target_text=target_text,
            label=raw.get("label"),
        )

class BBoxesWithTranscriptReviewsAnnotationResult(BoundingBoxAnnotationResult):
    """Result field saved by an SMGT job using the custom entities-with-transcription-reviews task

    This custom task, introduced via the notebooks and implemented by custom Liquid HTML template
    and pre/post-processing Lambda functions, outputs data compatible with the standard bounding box
    task UI but enriched with consolidated (overlapping) per-class regions and transcription reviews
    for each region.
    """

    entities: List[OCREntityWithTranscriptReview]

    def __init__(self, manifest_obj: dict):
        # Parse the bounding boxes themselves via superclass:
        super().__init__(manifest_obj)
        # Parse the OCR entities:
        if "entities" not in manifest_obj:
            raise ValueError(
                "SMGT manifest is missing 'entities' key, which should be generated by the custom "
                "task template but not the built-in bounding box UI. Using bbox-only annotations "
                "for a seq2seq training job is not currently supported."
            )
        self.entities = [
            OCREntityWithTranscriptReview.from_dict(e) for e in manifest_obj["entities"]
        ]


""" Module for the color options class """
from PyQt5.QtCore import QSize
from PyQt5.QtWidgets import (QWidget, QPushButton, QLabel, QGridLayout,
                             QGroupBox, QRadioButton, QHBoxLayout, QColorDialog)

from matplotlib.backends.qt_compat import QtWidgets

class ColorOptions(QWidget):
    """ Class for the color options channel """
    def __init__(self,data,parent,chn_ops):
        """ Constructor for color options.

            Args:
                data - the channel info object
                parent - the main (parent) window
                chn_ops - the channel options window
        """
        super().__init__()
        center_point = QtWidgets.QDesktopWidget().availableGeometry().center()
        self.width = int(parent.width / 2)
        self.height = int(parent.height / 3)
        self.left = int(center_point.x() - self.width / 2)
        self.top = int(center_point.y() - self.height / 2)
        self.title = 'Choose colors'
        self.data = data
        self.parent = parent
        self.chn_ops = chn_ops
        self.lt_custom = "#ffffff"
        self.rt_custom = "#ffffff"
        self.mid_custom = "#ffffff"
        self.setup_ui()

    def setup_ui(self):
        """ Setup UI for the color options window.
        """

        grid_lt = QGridLayout()

        lbl_info = QLabel("Select the color for each channel:"
                        + "\nPlease note that any non-standard channel "
                        + "\nor names not recognized by the program will be "
                        + "\nassigned the color of the midline.")
        grid_lt.addWidget(lbl_info,0,0)

        lbl_left = QLabel("Left hemisphere:")
        grid_lt.addWidget(lbl_left,1,0)
        lbl_right = QLabel("Right hemisphere:")
        grid_lt.addWidget(lbl_right,2,0)
        lbl_mid = QLabel("Midline:")
        grid_lt.addWidget(lbl_mid,3,0)

        groupbox_left_colors = QGroupBox()
        self.radio_col_r_lt = QRadioButton("R")
        self.radio_col_g_lt = QRadioButton("G")
        self.radio_col_b_lt = QRadioButton("B")
        self.radio_col_k_lt = QRadioButton("")
        self.k_btn_lt = QPushButton("Custom")
        self.k_btn_lt.clicked.connect(self.select_col_k_lt)
        hbox_left = QHBoxLayout()
        hbox_left.addWidget(self.radio_col_r_lt)
        hbox_left.addWidget(self.radio_col_g_lt)
        hbox_left.addWidget(self.radio_col_b_lt)
        hbox_left.addWidget(self.radio_col_k_lt)
        hbox_left.addWidget(self.k_btn_lt)
        groupbox_left_colors.setLayout(hbox_left)
        grid_lt.addWidget(groupbox_left_colors, 1,1)

        groupbox_right_colors = QGroupBox()
        self.radio_col_r_rt = QRadioButton("R")
        self.radio_col_g_rt = QRadioButton("G")
        self.radio_col_b_rt = QRadioButton("B")
        self.radio_col_k_rt = QRadioButton("")
        self.k_btn_rt = QPushButton("Custom")
        self.k_btn_rt.clicked.connect(self.select_col_k_rt)
        hbox_right = QHBoxLayout()
        hbox_right.addWidget(self.radio_col_r_rt)
        hbox_right.addWidget(self.radio_col_g_rt)
        hbox_right.addWidget(self.radio_col_b_rt)
        hbox_right.addWidget(self.radio_col_k_rt)
        hbox_right.addWidget(self.k_btn_rt)
        groupbox_right_colors.setLayout(hbox_right)
        grid_lt.addWidget(groupbox_right_colors, 2,1)

        groupbox_mid_colors = QGroupBox()
        self.radio_col_r_mid = QRadioButton("R")
        self.radio_col_g_mid = QRadioButton("G")
        self.radio_col_b_mid = QRadioButton("B")
        self.radio_col_k_mid = QRadioButton("")
        self.k_btn_mid = QPushButton("Custom")
        self.k_btn_mid.clicked.connect(self.select_col_k_mid)
        hbox_mid = QHBoxLayout()
        hbox_mid.addWidget(self.radio_col_r_mid)
        hbox_mid.addWidget(self.radio_col_g_mid)
        hbox_mid.addWidget(self.radio_col_b_mid)
        hbox_mid.addWidget(self.radio_col_k_mid)
        hbox_mid.addWidget(self.k_btn_mid)
        groupbox_mid_colors.setLayout(hbox_mid)
        grid_lt.addWidget(groupbox_mid_colors, 3,1)

        self._set_init_col("lt")
        self._set_init_col("rt")
        self._set_init_col("mid")

        btn_exit = QPushButton('Ok', self)
        btn_exit.clicked.connect(self.check)
        grid_lt.addWidget(btn_exit,4,0)
        self.setLayout(grid_lt)

        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.resize(QSize(self.width, self.height))

        self.show()

    def select_col_k_lt(self):
        """ Color picker.
        """
        color = QColorDialog.getColor()
        self.sender().setStyleSheet("background-color: " + color.name())
        self.lt_custom = color.name()

    def select_col_k_rt(self):
        """ Color picker.
        """
        color = QColorDialog.getColor()
        self.sender().setStyleSheet("background-color: " + color.name())
        self.rt_custom = color.name()

    def select_col_k_mid(self):
        """ Color picker.
        """
        color = QColorDialog.getColor()
        self.sender().setStyleSheet("background-color: " + color.name())
        self.mid_custom = color.name()

    def _set_init_col(self, hemi):
        """ Function to set the initial color.

            Args:
                hemi: "lt", "rt", or "mid"
        """
        if eval("self.data." + hemi + "_col") == "r":
            eval("self.radio_col_r_" + hemi).setChecked(1)
        elif eval("self.data." + hemi + "_col") == "b":
            eval("self.radio_col_b_" + hemi).setChecked(1)
        elif eval("self.data." + hemi + "_col") == "#1f8c45":
            eval("self.radio_col_g_" + hemi).setChecked(1)
        else:
            eval("self.radio_col_k_" + hemi).setChecked(1)
            eval("self.k_btn_" + hemi).setStyleSheet(
                "background-color: " + eval("self.data." + hemi + "_col"))

    def _get_col(self, hemi):
        """ Function to get the color.

            Args:
                hemi: "lt", "rt", or "mid"
            Returns:
                the color in hex
        """
        if eval("self.radio_col_r_" + hemi).isChecked():
            return "r"
        elif eval("self.radio_col_b_" + hemi).isChecked():
            return "b"
        elif eval("self.radio_col_g_" + hemi).isChecked():
            return '#1f8c45'
        else:
            col = eval("self." + hemi + "_custom")
            if col == "#ffffff":
                self.parent.throw_alert("Please click \"Custom\" to select a custom color.")
                return ""
            return col

    def check(self):
        """ Function to get colors and exit.
        """
        if (self._get_col("rt") == "" or self._get_col("lt") == ""
            or self._get_col("mid") == ""):
            return
        self.data.rt_col = self._get_col("rt")
        self.data.lt_col = self._get_col("lt")
        self.data.mid_col = self._get_col("mid")
        # redo setting data, channel names, and colors
        self.chn_ops.check()
        self.parent.call_initial_move_plot()
        self.close_window()

    def close_window(self):
        """ Closes the window.
        """
        self.parent.color_win_open = 0
        self.close()

    def closeEvent(self, event):
        """ Called when the window is closed.
        """
        self.parent.color_win_open = 0
        event.accept()


from aiodocker.util import task
from urllib.parse import urlparse
import aiohttp
import json
import logging
import os.path
import ssl

__all__ = ['DockerHandler']

log = logging.getLogger(__name__)

class DockerHandler:

    def __init__(self, host, version, cert_path=None, tls_verify=None):
        cert, cert_ca = search_certs(cert_path)
        host, socket, connector = connect(host, tls_verify, cert, cert_ca)

        self.host = host
        self.socket = socket
        self.connector = connector

        self.version = version
        self.cert_path = cert_path
        self.tls_verify = tls_verify
        self.cert = cert
        self.cert_ca = cert_ca

    def get(self, path, **kwargs):
        """
        Short-cut towards :meth:`request`
        """
        return self.request('GET', path, **kwargs)

    def post(self, path, **kwargs):
        """
        Short-cut towards :meth:`request`
        """
        return self.request('POST', path, **kwargs)

    def put(self, path, **kwargs):
        """
        Short-cut towards :meth:`request`
        """
        return self.request('PUT', path, **kwargs)

    def delete(self, path, **kwargs):
        """
        Short-cut towards :meth:`request`
        """
        return self.request('DELETE', path, **kwargs)

    @task
    def request(self, method, path, **kwargs):
        version = kwargs.pop('version', self.version)
        url = '%s/v%s/%s' % (self.host, version, path.lstrip('/'))
        params = kwargs.get('params', {}).copy()
        kwargs['params'] = parameters(params)
        kwargs.setdefault('connector', self.connector)

        response = yield from aiohttp.request(method, url, **kwargs)
        return response

def parameters(data):

    def prepare(obj):
        if obj is True:
            return '1'
        if obj is False:
            return '0'
        if isinstance(obj, dict):
            return clean(obj)
        if isinstance(obj, (list, set, tuple)):
            return [prepare(elt) for elt in obj]
        return obj

    def clean(data):
        return {k: prepare(v) for k, v in data.items() if v is not None}

    response = clean(data)
    for k, v in response.items():
        if isinstance(v, (dict, list, set, tuple)):
            response[k] = json.dumps(v)
    return response

def connect(host, tls_verify, cert, cert_ca):
    parsed = urlparse(host)
    if parsed.scheme == 'unix':
        return connect_unix(parsed.path)
    else:
        return connect_tcp(host, tls_verify, cert, cert_ca)

def connect_unix(path):
    socket = path
    connector = aiohttp.TCPConnector(path=path)
    return 'http://127.0.0.1', socket, connector

def connect_tcp(host, tls_verify, cert, cert_ca):
    parsed = urlparse(host)
    scheme, hostname, port = parsed.scheme, parsed.hostname, parsed.port

    if scheme == 'tcp':
        scheme = 'https' if tls_verify else 'http'

    connector = None
    if scheme == 'https':
        context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
        context.verify_mode = ssl.CERT_NONE
        if cert:
            context.load_cert_chain(*cert)
        connector = aiohttp.TCPConnector(verify_ssl=True,
                                         ssl_context=context)

    host = '%s://%s%s' % (scheme, hostname, (':%s' % port if port else ''))
    return host, None, connector

def search_certs(cert_path):
    cert, cert_ca = None, None

    if not cert_path:
        return cert, cert_ca

    cert_path = os.path.expanduser(cert_path)

    a = os.path.join(cert_path, 'cert.pem')
    b = os.path.join(cert_path, 'key.pem')
    if not os.path.isfile(a):
        log.warn('cert file is missing %s' % a)
        return cert, cert_ca

    if os.path.isfile(b):
        cert = a, b
    else:
        log.info('key file not found %s' % b)
        cert = a,

    c = os.path.join(cert_path, 'ca.pem')
    if os.path.isfile(c):
        cert_ca = c
    else:
        log.info('ca file is missing %s' % c)
    return cert, cert_ca


class Node(object):
    """A trie node"""

    def __init__(self, key, value=None):
        """
        Initialize the trie node.
            Parameters:
                key (string): The key of the node is a single character. If a longer
                    key is used, errors might be caused. A root node can have a longer
                    key because it is never used.
                value: The value that the node will store.
        """
        super(Node, self).__init__()
        self.children = []
        self.key = key
        self.value = value

    def insert(self, key, value):
        """
        Insert a key-value instance in the trie. If the key is an empty string,
        the value  is inserted in this node. Otherwise, the value will be recurrently
        propagated deeper in the trie until each letter of the key is assigned to
        a node and the deepest node will contain the value.
        If the value is a dictionary, a new trie will be created containing
        the key-value pairs of the dictionary. The new trie will be assigned
        as a value at the appropriate node.
            Parameters:
                key (string): The key under which the value will be stored
                value: The value that the trie will store.
        """
        if len(key) == 0:
            #If the key is empty the value must be inserted in this node
            if isinstance(value, dict):
                #If the value is a dictionary, we must construct a sub-trie
                n = Node(key="")
                for nk, nv in value.items():
                    n.insert(nk, nv)

                self.value = n
            else:
                #If the value is not a dictionary we can just insert it
                self.value = value
        elif len(self.children) == 0:
            #If this node has no children create one with the given key and value
            newNode = Node(key[0])
            newNode.insert(key[1:], value)
            self.children.append(newNode)
        else:
            #If the node already has children, find where the value must go
            for i, child in enumerate(self.children):
                if key[0] == child.key:
                    child.insert(key[1:], value)
                    break
                elif key[0] < child.key:
                    newNode = Node(key[0])
                    newNode.insert(key[1:], value)
                    self.children.insert(i, newNode)
                    break
                elif i == len(self.children) - 1:
                    #If we reached the end of the loop we must insert at the end
                    newNode = Node(key[0])
                    newNode.insert(key[1:], value)
                    self.children.append(newNode)
                    break

    def find(self, key):
        """
        Searches for the given key in the trie. If the key is an empty string
        then the value of the current node is returned. Otherwise the first letter
        of the key is searched in the node's children and the rest of the key
        is searched recurrently in the appropriate child.
            Parameters:
                key (string): The key to search for.
            Return:
                None if the value is not found, otherwise returns the corresponding
                value
        """
        if len(key) == 0:
            return self.value
        else:
            for child in self.children:
                if key[0] == child.key:
                    return child.find(key[1:])
        return None

    def delete(self, key):
        """
        Searches for the given key in the trie and sets its value to None.
        Works similarly to the Node.find() method
            Parameters:
                key (string): The key to delete.
            Return:
                True if the value was found and deleted, otherwise False
        """
        if len(key) == 0:
            if self.value != None:
                self.value = None
                return True
            else:
                return False
        else:
            for child in self.children:
                if key[0] == child.key:
                    return child.delete(key[1:])
        return False

    def _print(self, key_prefix):
        """
        A reccurrent helping method for creating a string representation of the
        trie
            Parameters:
                key_prefix (string): The key gathered from the previously
                    traversed nodes
            Return:
                ret (dictionary): A dictionary containing all the key-value
                pairs of the node
                ret_str (string): A printable string version of the afforementioned
                dictionary
        """
        ret = {}
        cur_key = key_prefix + self.key

        if self.value != None:
            if isinstance(self.value, Node):
                ret[cur_key] = str(self.value)
            else:
                ret[cur_key] = self.value

        for child in self.children:
            child_ret, child_ret_str = child._print(cur_key)
            ret.update(child_ret)

        ret_str = "{"
        for i, (key, val) in enumerate(ret.items()):
            if i != 0:
                ret_str += " ; "
            ret_str += f"{key} : {val}"
        ret_str += "}"

        return ret, ret_str

    def __str__(self):
        """
        Return a printable string representation of the trie, using the
        reccurent Node._print() method
        """
        ret, ret_str = self._print("")
        return ret_str

if __name__ == '__main__':
    n = Node("")
    n.insert("abc", 42)
    n.insert("abc", 22)
    n.insert("abcd", {"key1": 1, "key2": "aaa", "key3": 20.2})
    n.insert("la", {"key": 1, "ke": {"foo":100, "empty": {}}})

    print(n.find("abc"))
    print(n.delete("abc"))
    print(n.delete("aabc"))
    print(n.find("abc"))

    print(n.find("abcd"))
    print(n.find("abcd").find("key1"))
    print(n.find("abcd").find("key2"))
    print(n.find("abcd").find("key3"))
    print(n.find("la").find("ke").find("foo"))
    print(n)


from flask import Flask, request, redirect
from twilio.twiml.messaging_response import MessagingResponse
from modules.status_response import transition

app = Flask(__name__)
app.config.from_object(__name__)

@app.route("/", methods=['GET', 'POST'])
def route():
    """Respond to incoming calls with a simple text message."""
    from_number = request.values.get('From', None)
    body = request.values.get('Body', None)
    resp = MessagingResponse()
    message = "You sent: " + body + " from " + from_number
    # resp.message(message)
    # send.send_sms(from_number, body)
    transition(from_number, body)
    # return str(resp)
    return '200'
    # resp = MessagingResponse()
    # message = "You sent: " + body + " from " + from_number
    # resp.message(message)
    # return str(resp)

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


from betdaqlightweight import enums

def selection_info(selection_id, from_trade_id=None):
    resp = {'_selectionId': selection_id}
    if from_trade_id is not None:
        resp['_fromTradeId'] = from_trade_id
    return resp

def place_order(
        selection_id,
        stake,
        price,
        polarity,
        expected_selection_reset_count,
        expected_withdrawal_sequence_number,
        cancel_on_in_running=True,
        cancel_if_selection_reset=True,
        expires_at=None,
        withdrawal_reprice_option=enums.WithdrawRepriceOption.Cancel.value,
        kill_type=enums.OrderKillType.FillOrKillDontCancel.value,
        fill_or_kill_threshold=0.0,
        punter_reference_number=1
):
    """
    Create an place order to send to exchange.

    :param selection_id: Id number of the selection on which the order is to be placed
    :type selection_id: int
    :param stake: Amount for which the order is to be placed for.
    :type stake: float
    :param price: Price at which order is to be placed.
    :type price: float
    :param polarity: side on which order is to be placed.
    :type polarity: betdaqlightweight.enums.Polarity
    :param expected_selection_reset_count: must match SelectionResetCount value in GetMarketInformation and GetPrices
                                        to ensure state of the market before placing a bet. If not matching server
                                        bet will not be placed and error is raised.
    :type expected_selection_reset_count: int
    :param expected_withdrawal_sequence_number: should match withdrawalSequenceNumber value in GetMarketInformation and
                                             GetPrices. If not matching server then your bet WILL be accepted, but it
                                             will be repriced.
    :type expected_withdrawal_sequence_number: int
    :param cancel_on_in_running: Cancel any unmatched orders when the market changes to an in-running market.
    :type cancel_on_in_running: bool
    :param cancel_if_selection_reset: Cancel any unmatched bets if the selection is reset.
                                   This can occur when the Market is reset (eg a goal is scored).
    :type cancel_if_selection_reset: bool
    :param expires_at: Specify a specific time for an order to expire, times in the past are instantly cancelled.
    :type expires_at: datetime.datetime
    :param withdrawal_reprice_option: Define what to do with the order in case of withdrawal, default to cancel.
    :type withdrawal_reprice_option: betdaqlightweight.enums.WithdrawalRepriceOption
    :param kill_type: whether to define order as a type of Fill/Kill order, default order will be limit order.
    :type kill_type: betdaqlightweight.enums.OrderKillType
    :param fill_or_kill_threshold: Lower limit for order to be partially filled. only required if KillType is
                                FillOrKill or FillOrKillDontCancel
    :type fill_or_kill_threshold: float
    :param punter_reference_number: optional ID provided for customers own reference.
    :type punter_reference_number: int
    :return: dictionary of all order information which can be sent to exchange.
    """
    resp = {
        '_SelectionId': selection_id,
        '_Stake': stake,
        '_Price': price,
        '_Polarity': polarity,
        '_ExpectedSelectionResetCount': expected_selection_reset_count,
        '_ExpectedWithdrawalSequenceNumber': expected_withdrawal_sequence_number,
        '_CancelOnInRunning': cancel_on_in_running,
        '_CancelIfSelectionReset': cancel_if_selection_reset,
        '_WithdrawalRepriceOption': withdrawal_reprice_option,
        '_KillType': kill_type,
        '_FillOrKillThreshold': fill_or_kill_threshold,
        '_PunterReferenceNumber': punter_reference_number
    }

    if expires_at is not None:
        resp['_ExpiresAt'] = expires_at

    return resp

def update_order(
        bet_id,
        delta_stake,
        price,
        expected_selection_reset_count,
        expected_withdrawal_sequence_number,
        cancel_on_in_running=None,
        cancel_if_selection_reset=None,
        set_to_be_sp_if_unmatched=None
):
    """
    Create an update order to send to exchange.

    :param bet_id: ID of the bet to be updated.
    :type bet_id: int
    :param delta_stake: Amount to change the stake of the bet by.
    :type delta_stake: float
    :param price: Price at which to place bet at.
    :type price: float
    :param expected_selection_reset_count: must match SelectionResetCount value in GetMarketInformation and GetPrices
                                        to ensure state of the market before placing a bet. If not matching server
                                        bet will not be placed and error is raised.
    :type expected_selection_reset_count: int
    :param expected_withdrawal_sequence_number: should match withdrawalSequenceNumber value in GetMarketInformation and
                                             GetPrices. If not matching server then your bet WILL be accepted, but it
                                             will be repriced.
    :type expected_withdrawal_sequence_number: int
    :param cancel_on_in_running: Cancel any unmatched orders when the market changes to an in-running market.
    :type cancel_on_in_running: betdaq_py.enums.Boolean
    :param cancel_if_selection_reset: Cancel any unmatched bets if the selection is reset.
                                   This can occur when the Market is reset (eg a goal is scored).
    :type cancel_if_selection_reset: betdaq_py.enums.Boolean
    :param set_to_be_sp_if_unmatched: whether to set bet to SP when market turns in play if it is unmatched.
    :type set_to_be_sp_if_unmatched: betdaq_py.enums.Boolean
    :return: dictionary of the order information to update on exchange.
    """

    resp = {
        '_BetId': bet_id,
        '_DeltaStake': delta_stake,
        '_Price': price,
        '_ExpectedSelectionResetCount': expected_selection_reset_count,
        '_ExpectedWithdrawalSequenceNumber': expected_withdrawal_sequence_number,
    }

    if cancel_on_in_running is not None:
        resp['_CancelOnInRunning'] = cancel_on_in_running

    if cancel_if_selection_reset is not None:
        resp['_CancelIfSelectionReset'] = cancel_if_selection_reset

    if set_to_be_sp_if_unmatched is not None:
        resp['_SetToBeSPIfUnmatched'] = set_to_be_sp_if_unmatched
    return resp


import itertools
def longest_repetition(chars):
    if chars=='':
        return ('',0)
    arr=[]
    for x,y in itertools.groupby(chars):
         arr.append(''.join(y))
    max=len(arr[0])
    maxi=arr[0][0]
    for i in range(len(arr)):
        if len(arr[i])>max:
            max=len(arr[i])
            maxi=arr[i][0]
    return(maxi,max)


import logging
from collections import OrderedDict
from typing import List

from .db import DBConfig
from .errors import UnsupportedAppError

class GamestPlugin:
    SETTINGS_TAB_NAME = "Plugin"
    def __init__(self, application):
        self.logger = logging.getLogger(__name__ + '.' + self.__class__.__name__)
        self.application = application

        self.config = DBConfig(owner=self.__class__.__name__)

    def cleanup(self):
        raise NotImplementedError

    @classmethod
    def get_settings_template(cls):
        return OrderedDict()

class GamestPersistentPlugin(GamestPlugin):
    pass

class GamestSessionPlugin(GamestPlugin):
    start_bind = None
    end_bind = None

    def __init__(self, application):
        super().__init__(application)
        self.play_session = application.play_session

class NotificationService(GamestPersistentPlugin):
    user_name = None

    def notify(self, msg):
        raise NotImplementedError

class GameReporterPlugin(GamestSessionPlugin):
    PATH_ENDSWITH : List[str] = []

    def __init__(self, application):
        super().__init__(application)

        if self.user_app_ids and (self.play_session.user_app_id not in self.user_app_ids):
            self.logger.debug(
                "User app ID did not match: %s not in %s (configured)",
                self.play_session.user_app_id,
                ', '.join(str(i) for i in self.user_app_ids))
            raise UnsupportedAppError(
                "Current user_app_id: {}. Configured: {}.".format(
                    self.play_session.user_app_id,
                    ', '.join(str(i) for i in self.user_app_ids)))
        elif not self.user_app_ids and not (self.play_session.user_app.path and any(self.play_session.user_app.path.endswith(p) for p in self.PATH_ENDSWITH)):
            self.logger.debug("Path did not match: %s.", self.play_session.user_app.path)
            raise UnsupportedAppError("Current app path does not match a supported path.")

        self.job = None

    @property
    def user_app_ids(self):
        return self.config.getlist('user_app_ids', type=int)

    @property
    def send_begin(self):
        return self.config.getboolean('send_begin', fallback=True)

    @property
    def send_end(self):
        return self.config.getboolean('send_end', fallback=True)

    @property
    def add_status_updates(self):
        return self.config.getboolean('add_status_updates', fallback=True)

    @property
    def interval(self):
        return self.config.get('interval', type=int, fallback=60)

    @classmethod
    def get_settings_template(cls):
        d = super().get_settings_template()
        d[(cls.__name__, 'send_begin')] = {
            'name' : 'Notify on game begin',
            'type' : 'bool',
            'default' : True,
            'hint' : "If checked, send a notification when a game session begins.",
        }
        d[(cls.__name__, 'send_end')] = {
            'name' : 'Notify on game end',
            'type' : 'bool',
            'default' : True,
            'hint' : "If checked, send a notification when a game session ends.",
        }
        d[(cls.__name__, 'add_status_updates')] = {
            'name' : 'Save updates in DB',
            'type' : 'bool',
            'default' : True,
            'hint' : "If checked, status updates from this plugin will be saved to the database.",
        }
        d[(cls.__name__, 'interval')] = {
            'name' : 'Update interval (minutes)',
            'type' : 'text',
            'validate' : int,
            'default' : '60',
            'hint' : "How often to send updates, in minutes.",
        }
        d[(cls.__name__, 'user_app_ids')] = {
            'name' : 'UserApp IDs',
            'type' : 'list',
            'hint' : ("By default, this plugin determines which game is running based on the "
                      "executable path. This can fail if your executable has an unexpected "
                      "filename or if another game has the same filename. In that case, set the "
                      "UserApp ID to the number displayed when gamest is detecting the game, and "
                      "this plugin will activate only for that app.\n"
                      "\n"
                      "To specify multiple app IDs (e.g. for different game versions), put one ID "
                      "per line.")
        }
        return d

    def get_report(self):
        raise NotImplementedError

    def report_update(self, game_end=False):
        self.logger.debug("report_update called")
        if game_end:
            report_text = "{{user_name}} played **{}**:\n\n".format(self.play_session.user_app.app)
        else:
            report_text = "{{user_name}} is playing **{}**:\n\n".format(self.play_session.user_app.app)
        try:
            report_details = self.get_report()
            if report_details:
                if self.add_status_updates:
                    self.play_session.add_status_update(report_details)
                report_text = report_text + report_details
                for s in filter(lambda p: isinstance(p, NotificationService), self.application.persistent_plugins):
                    s.notify(report_text)
            else:
                self.logger.debug("No difference since report.")
        except Exception:
            self.logger.exception("Failed to build update.")
        finally:
            if self.application.RUNNING and self.play_session is self.application.play_session:
                self.job = self.application.after(self.interval*60*1000, self.report_update)

    def onGameStart(self, e):
        self.logger.debug("onGameStart called")
        if self.send_begin:
            self.job = self.application.after(35000, self.report_update)
        else:
            self.job = self.application.after(self.interval*60*1000, self.report_update)

    def onGameEnd(self, e):
        self.logger.debug("onGameEnd called")
        if self.send_end:
            self.report_update(game_end=True)
        self.cleanup()

    def cleanup(self):
        if self.job:
            self.application.after_cancel(self.job)

class IdentifierPlugin(GamestPersistentPlugin):
    def candidates(self):
        return []

    def identify_game(self):
        return None

    def clear_cache(self):
        pass


from django.urls import path, include
from competence import views
from competence import views_bundles
# from competence import api
# from competence.api import views as apiviews

app_name="competence"
urlpatterns = [
    # path('', views.CompetenceList.as_view(), name="competence"),
    path('', views.competenceList, name="competence"),
    path('api/', include('competence.api.urls')),

    path('create/', views.competenceCreate, name="create"),
    path('test2/', views.comptest2, name="comptest2"),
    path('table/', views.table_comp, name="table-comp"),
    path('table/<int:pk>/', views.table_qty, name="table_qty"),

    # path('endpoints/', views.get_endpoints, name="endpoints"),

    path('<int:pk>/', include([
        path('', views.competenceUpdate, name='update'),
        path('delete/', views.deleteCompetence, name="delete"),
    ])),

    # COMPETENCE BUNDLES--
    path('bundles/',include([
        path('', views_bundles.bundle_list, name='bundles'),
        path('create/', views_bundles.bundle_create, name='bundle-create'), # create a new bundle
        path('<int:pk>/delete/', views_bundles.bundle_delete, name='bundle-delete'),
        path('<int:pk>/update/', views_bundles.bundle_update, name='bundle-update'),
        path('<int:pk>/retrieve/', views_bundles.bundle_retrieve, name='bundle-retrieve'),

        path('<int:pk>/add/', views_bundles.bundle_competences_add, name='bundle-competences-add'),
        path('competence/<int:competenceid>/delete/', views_bundles.bundle_competence_remove, name='bundle-competence-remove'),
        # path('<int:bundleid>/competence/<int:competeceid>/', views_bundles.bundle_competence_remove, name='bundle-competence-remove'),

        # path('<int:pk>/', views_bundles.bundle_competences, name='bundle-competences'),

    ])),

]

#HTMX
urlpatterns+=[
    path('list/', views.competenceList, name="list"),
]


from nltk.corpus import stopwords
import csv
import re
import math
import numpy as np

#polarity,summary,reviewText,year

ndtype=[('a',int), ('b', float), ('c', int)]

my_data = np.genfromtxt('data/cleanbow.csv', delimiter=',')

with open('phase1_movie_reviews-train.csv') as csv_file:
	for line in csv_file:

		group = re.search('(.*?),(.*?),(.*),(.*)', line)

		sentiment = group.group(1)
		summary = group.group(2)
		reviewText = group.group(2)
		year = group.group(3)

		polarity = 0
		size = 0

		for word in my_data:
			polarity += word[1]
			size += 1


#!/usr/bin/env python
import pickle
import sys

def max_match_segment( line, dic ):
    maxlen = 0
    for i in dic:
        if len(i) > maxlen:
            maxlen = len(i)
        else:
            continue
    # print(maxlen)
    # 确定最大词长

    s1 = line[:maxlen]
    result = []
    log = 0

    for i in range(len(line)):
        while s1 not in dic:
            if len(s1)>1:
                s1 = s1[:-1]
            elif len(s1) <= 1 and len(line)>maxlen:
                result.append(s1)
                line = line[1:]
                s1 = line[:maxlen]
                break
            elif len(s1) <= 1 and len(line) <= maxlen:
                result.append(s1)
                line = line[1:]
                s1 = line
                break

        else:
            result.append(s1)
            l_index = line.index(s1)

            line = line[l_index+len(s1):]
            s1 = line[:maxlen]

    return result

if __name__=="__main__":
    try:
        fpi=open(sys.argv[1], "r")
    except:
        print(sys.stderr, "failed to open file")
        sys.exit(1)

    try:
        dic = pickle.load(open(sys.argv[2],'rb+'))
    except:
        print(sys.stderr, "failed to load dict")
        sys.exit(1)

    for line in fpi:
        print("\t".join(max_match_segment(line.strip(), dic)))


# this file has all the code for running this demo, for latest updates pull from:
# https://gist.github.com/yashbonde/cadb515b6c658f18147d948fac685c7b

import torch
import numpy as np
import re
from time import sleep
from tqdm import trange

class Response():
  """Class that makes getting generated results chill, simply `print(out)`"""
  def __init__(self, out, t):
    self.t = t
    self.sequences = out.sequences.cpu().tolist()
    self.scores = [x.cpu().numpy() for x in out.scores] if out.scores != None else None
    self.hidden_states = [
      [y.cpu().numpy() for y in x]
      for x in out.hidden_states
    ] if out.hidden_states != None else None
    self.attentions = [
      [y.cpu().numpy() for y in x]
      for x in out.attentions
    ] if out.attentions != None else None

    self.decoded = self.t.batch_decode(self.sequences, skip_special_tokens = True)

  def __repr__(self):
    str_ = ""
    for x in self.decoded:
      str_ += x + "\n"
      str_ += "-"* 70 + "\n"
    return str_

  def __len__(self):
    return len(self.decoded)

  def __getitem__(self, i):
    return self.decoded[i]

  def __iter__(self):
    for x in self.decoded:
      yield x

class GPT():
  """Make GPT a first class object and using it as simple as possible.
  First define the model and tokenizer

  >>> device = torch.device("cuda:0") if torch.cuda.is_available() else "CPU"
  >>> tokenizer = AutoTokenizer.from_pretrained(name)
  >>> model = AutoModelForCausalLM.from_pretrained(name, cache_dir = "../hf-cache/").eval().to(device)
  Make GPT wrapper: output is `Response`, a class with __repr__ overloaded so print gives the generation
  >>> gpt = GPT(model, tokenizer)
  >>> out = gpt("Hello world", n = 10, r = 2)
  >>> out
  ... Hello world!" "Hello?" "Yeah, I'm in
    ----------------------------------------------------------------------
    Hello world" command, that is, the command that
    ----------------------------------------------------------------------
  """
  def __init__(self, model, tokenizer):
    self.model = model
    self.tokenizer = tokenizer
    self.eot_id = tokenizer.eos_token_id
    self.device = self.model.device

  def set_seed(self, seed):
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)

  @torch.no_grad()
  def __call__(
    self,
    prompt: str,
    n: int = 16, # number of tokens
    r: int = 1, # number of sequences
    do_sample = True,
    temp = 0.9,
    top_p = 0.9,
    top_k = None,
    output_scores = None,
    output_hidden_states = None,
    output_attentions = None,
    stop_sequence = None,
    return_response = True,
    **gen_kwargs
  ):
    """ __call__ overloader initialises the model.generate() function. We emphasise
    a lot more on most powerful arguments, but you can always pass custom kwargs through
    `gen_kwargs`. As you can see that we have not added many beam-search related arguments.
    Args:
      prompt (str): prompt string, tokens will be generated in continuation
      n (int, optional): number of tokens to return
      r (int, optional): number of sequences to return
      temp (float, optional): sampling temperature
      top_p (float, optional): tokens whose probability adds up to this are considered
      top_k (int, optional): top-k tokens to consider for each distribution
      output_scores (bool, optional): output scores for each generted token, returns shape `[r,n]`
      output_hidden_states (bool, optional): output the hidden states of the generation, returns shape `[r,n+1,...]`
      output_attentions (bool, optional): Whether or not to return the attentions tensors of all attention layers
      stop_sequence (str, optional): Stop generation once the first token of this string is achieved
      return_response (bool, optional): To parse the generated dictionary to `Response` class
      gen_kwargs (dict, optional): any extra arguments to pass to the model.generate() method
    Returns:
      if return_response:
       Response instance
      else:
       model.generate() output
    """
    t = self.tokenizer
    m = self.model

    # tokenize the input prompt and stop token if provided
    input_ids = t(prompt, return_tensors = "pt")["input_ids"].to(self.device)
    if stop_sequence is not None:
      eos_token_id = t(stop_sequence)["input_ids"][0]
    else:
      eos_token_id = self.eot_id

    # generate the items
    out = m.generate(
      input_ids,
      max_length = len(input_ids[0]) + n,
      temperature = temp,
      top_p=top_p,
      top_k=top_k,
      num_return_sequences=r,
      pad_token_id = self.eot_id,
      output_scores = output_scores,
      output_hidden_states = output_hidden_states,
      output_attentions = output_attentions,
      do_sample = do_sample,
      return_dict_in_generate = True,
      eos_token_id = eos_token_id,
      **gen_kwargs
    )

    # return items or
    if return_response:
      return Response(out, t)
    else:
      return out

  def classify(
    self,
    prompt: str,
    labels: list,
    softmax_temp = 0.9,
    add_unknown = False,
    **gen_kwargs,
  ) -> dict:
    """Perform classification directly.
    NOTE: ensure that first tokens in labels are not the same.
    Args:
      prompt (str): prompt string to be given as input
      labels (list): list of strings that are labels
      gen_kwargs (dict, optional): extra arguments to be passed for generation
      softmax_temp (float, optional): temprature for scoring labels. Defaults to 0.9.
      add_unknown (bool, optional): adds an extra "Unknown" label. Defaults to False.
    Returns:
      dict: values are 0. if model returns 'nan'
    """
    # we will use the same format that OpenAI uses for GPT-3
    # read: https://beta.openai.com/docs/guides/classifications
    # We normalize all labels by `label.strip().lower().capitalize()` at the API
    # backend. Thus corresponding output labels are always capitalized.
    unq_options = set([x.strip().lower().capitalize() for x in labels])
    unq_options = sorted(list(unq_options))

    # each label must have a distinct first token, because classification
    # works by looking only one step ahead. Also encode the labels with extra
    # white space prepended.
    label_ids = [self.tokenizer.encode(" " + x)[0] for x in unq_options]

    out = self(prompt, n = 1, r = 1, output_scores = True, **gen_kwargs, return_response = False)
    logits = out.scores[0][0]
    logits = (logits / softmax_temp)[label_ids].softmax(-1).cpu()
    logits = logits.numpy()

    scores = {o:i for o,i in zip(unq_options, logits)}

    # naaaaan - check
    scores = {k: 0. if np.isnan(l) else l for k,l in scores.items()}

    if add_unknown:
      # fill the Probability for the special "Unknown" token
      scores["Unknown"] = 1 - sum(scores.values())

    return scores

# ---- pipelines

def check_english_language(sentence, gpt):
  if isinstance(sentence, list):
    return [
      check_english_language(s) for s in sentence
    ]
  prompt = """This classifies whether the input sequence into it's language
###
sentence: "GPT2 is a state of the art neural language model, that can be trained to make good quality predictions for many different tasks including text classification and machine translation."
language: English
###
sentence: "कोरोना पर होगा ड्रोन अटैक: ICMR की योजना- दुर्गम इलाकों में ड्रोन से होगी वैक्सीन की डिलीवरी, तेलंगाना सरकार ने ऐसा प्रोजेक्ट लॉन्च किया"
language: Hindi
###
sentence: "фантастический роман Алексея Николаевича Толстого о путешествии землян на Марс. Текст написан в основном в эмиграции, первое издание вышло в Петрограде в 1923 году и неоднократно перепечатывалось."
language: Russian
###
sentence: {sentence}
language:"""
  p = prompt.format(sentence = sentence)
  out = gpt(p, n = 4, r = 1, stop_sequence="###", temp=0.7, do_sample = False)[0]
  out = out[len(p):].strip().split("\n")[0]
  return out

def format_sentence(sentence, gpt):
  if isinstance(sentence, list):
    out = []
    for s in sentence:
      out.append(format_sentence(s))
      sleep(0.5)
    return out

  # try keeping len(sentence.split()) ~ 54
  gpt.set_seed(90)
  prompt = """Correct the sentence in each input and return properly formatted sentence
###
sentence: "everyone in this part of the world thinks i am a fraud but i know who i am."
correct: "Everyone in this part of the world thinks I am a fraud, but I know who I am."
###
sentence: "hey everybody welcome to the all in podcast it was a slow news week so we decided we'd  give you a special episode we're gonna go around the horn with our special picks we're each gonna."
correct: "Hey everybody, welcome to the all in podcast. It was a slow news week so we decided we'd give you a special episode. We're gonna go around the horn with our special picks, we're each gonna"
###
sentence:"{sentence}"
correct:"""

  p = prompt.format(sentence = sentence)
  n = len(gpt.tokenizer.tokenize(sentence)) + 10 # margin of error
  g = gpt(p, n, r=1, stop_sequence = "\n", temp = 1.0, top_p = 1.0)[0]
  # clean up the response
  s = g.split("###")[-2 if g.endswith('###') else -1]
  res = s.split("\n")[2][8:].replace('"', '').strip()
  return res[:-1]

def get_keywords(text, gpt, r = 4):
  prompt = """Get keywords from each text

###

Text: "Black-on-black ware is a 20th- and 21st-century pottery tradition developed by the
Puebloan Native American ceramic artists in Northern New Mexico. Traditional reduction-fired
blackware has been made for centuries by pueblo artists. Black-on-black ware of the past century
is produced with a smooth surface, with the designs applied through selective burnishing or the
application of refractory slip. Another style involves carving or incising designs and
selectively polishing the raised areas. For generations several families from Kha'po
Owingeh and P'ohwhóge Owingeh pueblos have been making black-on-black ware with the
techniques passed down from matriarch potters. Artists from other pueblos have also produced
black-on-black ware. Several contemporary artists have created works honoring the pottery of
their ancestors."

Keywords: Pueblo, art, pottery, black, black ware

###

Text: "{text}"

Keywords:"""

  p = prompt.format(text = text)
  words = set()

  # prevents GPU OOM by batching instead of parallel requests
  for _ in range(0, r+1, 2):
    out = gpt(
      p, r = 2, n = 20, stop_sequence="\n", temp = 0.9,
      repetitive_penalty = 0.9 # don't repeat the same thing over and over again
    )

    for s in out:
      ws = s.split("###")[2].split("\nKeywords:")[-1].split(",")
      for w in ws:
        w = w.strip().lower()
        # print("--->", w, w in ["pueblo", "art", "pottery", "black", "black ware"])
        if w and len(w.split()) < 4 and w not in ["pueblo", "art", "pottery", "black", "black ware"]:
          words.add(w)

        for _w in w.split()[:2]:
          words.add(_w)

  return list(words)

def clean_keywords(keywords, gpt):
  print(keywords)
  if isinstance(keywords[0], list):
    return [clean_keywords[x] for x in keywords]

  # make the keywords a sentence for prompt
  k = ", ".join(keywords)
  k = re.sub(r"[^\w\'\s,]", "", k)

  prompt = '''This app removed duplicate words from a list of words

###

Sentence: "reddity, redditt, a red list, the, redditor, culture, community, redditor list, a redditor, reddiquette, redditr, queer, r/quinoa, quinoa, reddit, redditer, reddits"

Important words: reddit, culture, community, quinoa, r/quinoa

###

Setence: "podcasts, podcast, episode, all in, all i, special podcast, all in podcast, all ian, in, all i"

Important words: all in podcast

###

Sentence: "street, wall, stock, wall street, hedge fund, stock pick, thesis, stock analyst, bet, obey, angle, stock tip, quote, new york, gamestop"

Important words: wall street, hedge fund, new york, gamestop

###

Sentence: {sentence}

Important words:'''

  p = prompt.format(sentence = k)

  out = gpt(p, n = 32, r = 5, temp = 1.0, top_p = 0.9, stop_sequence="\n",)

  words = set()
  for x in out:
    ws = x.split("###")[-1].split("Important words:")[-1].strip().split(",")
    for w in ws:
      words.add(w.strip())
  return list(words)

# ----- main functions

def get_keywords_from_caption(captions: list, gpt: GPT):
  """
  Args:
    captions (list): captions is the list with output of function `Processor.parse_captions()`
      each element having the following structure:
      {
        "id": [<id: int>],
        "from": <from:datetime>,
        "to": <to:datetime>,
        "content": <str>
      }
    gpt (GPT): loaded GPT wrapper

  Returns:
      [type]: [description]
  """

  capstr = " ".join([x["content"] for x in captions])

  # step 1: format the sentence
  format_buff_size = 100
  fsent = []
  pbar = trange(0, len(capstr), format_buff_size)
  for i in pbar:
    r = format_sentence(" ".join(capstr.split()[i:i+format_buff_size]) + ".", gpt)
    fsent.append(r)
    pbar.set_description(f"Cleaned {i+1} sentences!")

  # step 2: get keywords
  words = []
  pbar = trange(len(fsent))
  for _, o in zip(pbar, fsent):
    out = get_keywords(o, gpt)
    words.append(out)
    pbar.set_description(f"Got {sum([len(x) for x in words])} keywords from {len(words)} sentences")

  # step 3: clean the key-words
  w2 = []
  pbar = trange(len(words))
  for _, w in zip(pbar, words):
      out = clean_keywords(", ".join(w), gpt)
      w2.append(out)

  return w2


#coding:utf-8

"""
ID:          tabloid.test_dsqlrequests
TITLE:       DROP TABLE fails if executing in ES and DML at the same execute block is performed in autonomous transaction
DESCRIPTION:
    Regression detected in 5.0.0.435, build 19.03.2022
    https://github.com/FirebirdSQL/firebird/commit/6214b12028501cdc2875ad7d0deb62c4822060b8
    Checked on 5.0.0.964, 4.0.3.2903, 3.0.11.33664.
"""

import pytest
from firebird.qa import *

db = db_factory()

test_script = """
    set term ^;
    recreate table test (id int primary key)^
    commit^
    execute block as
    begin
      execute statement 'drop table test';
      in autonomous transaction do
        execute statement ( 'insert into test values ( ? ) ') (1);
    end^
    commit^
"""

act = isql_act('db', test_script)

expected_stderr = """
"""

@pytest.mark.version('>=3.0')
def test_1(act: Action):
    act.expected_stderr = expected_stderr
    act.execute()
    assert act.clean_stderr == act.clean_expected_stderr


import input_data
import tensorflow as tf
import matplotlib.pyplot as plt

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

# 定义变量
x = tf.placeholder("float", [None, 784])
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
# 建立回归模型
y = tf.nn.softmax(tf.matmul(x,W) + b)
# 样本实际值
y_ = tf.placeholder("float", [None,10])
# 用交叉熵表示损失
cross_entropy = -tf.reduce_sum(y_*tf.log(y))
# 构建梯度下降优化器
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
# 初始化变量
init = tf.initialize_all_variables()

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

xx=range(1000)
yy=[]
loss=[]

sess = tf.Session()
sess.run(init)
for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
    # 记录准确率
    yy.append(sess.run(accuracy, feed_dict={x: batch_xs, y_: batch_ys}))
    # 记录损失
    loss.append(sess.run(cross_entropy, feed_dict={x: batch_xs, y_: batch_ys}))

print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
print(sess.run(cross_entropy, feed_dict={x: batch_xs, y_: batch_ys}))

sess.close()

plt.figure()
plt.plot(xx,yy,color="blue")
plt.figure()
plt.plot(xx,loss,color="red")
plt.legend()
plt.show()


"""
This module defines the all the global variables needed by the database module
"""

__author__ = "Marc Bermejo"
__credits__ = ["Marc Bermejo"]
__license__ = "GPL-3.0"
__version__ = "0.1.0"
__maintainer__ = "Marc Bermejo"
__email__ = "mbermejo@bcn3dtechnologies.com"
__status__ = "Development"

from flask_sqlalchemy import SQLAlchemy

#################################
# SQLALCHEMY CONNECTION MANAGER #
#################################

db_conn = SQLAlchemy()


import pandas as pd
import numpy as np
pd.options.display.float_format = '{:,.3f}'.format

def safe_rename(df, rename_dict):
    """Rename columns in a dataframe, but only if they exist.
    """
    for old_col, new_col in rename_dict.items():
        assert old_col in df.columns, "Column %s not found in dataframe" % col
        assert new_col not in df.columns, "Column %s already exists in dataframe" % new_col
    df.rename(columns=rename_dict, inplace=True)
    return df

a = pd.read_csv(r'/media/awmundy/Windows/bio/age_related_steatohepatitis/outputs/young_vs_old/all_dge_table.csv')
# supplementary file posted to GEO
b = pd.read_excel(r'/media/awmundy/Windows/bio/age_related_steatohepatitis/supplemental_data/GSE216592_ct-vs-aging.all.annot2.xls.xlsx',
                  engine='openpyxl')

rename_rep = {'ct1_fpkm': 'young_1',
              'ct2_fpkm': 'young_2',
              'ct3_fpkm': 'young_3',
              'aging2_fpkm': 'old_1',
              'aging3_fpkm': 'old_2',
              'aging5_fpkm': 'old_3',
              'Symbol': 'gene_id',
              'FDR': 'adj_p',
              'log2(fc)' : 'logfc'
              }

rename_me = {'adj.P.Val': 'adj_p',
             'logFC': 'logfc',
             }

a = safe_rename(a, rename_me)
b = safe_rename(b, rename_rep)
cols = list(rename_rep.values())
a = a[cols].copy()
b = b[cols].copy()
a['adj_p_sig'] = np.where(a['adj_p'] < 0.05, 1, 0)
b['adj_p_sig'] = np.where(b['adj_p'] < 0.05, 1, 0)
print('my sig genes count:', a['adj_p_sig'].sum()) #1017
print('their sig genes count:', b['adj_p_sig'].sum()) #3186

# drop 24 duplicate records for genes, keeping higher value ones bc sometimes one copy is all 0
b.sort_values(by=['gene_id', 'young_1'], ascending=False, inplace=True)
b.drop_duplicates(subset='gene_id', inplace=True)

m = pd.merge(a, b, on='gene_id', how='outer', validate='1:1', suffixes=('_a', '_b'), indicator=True)
print(m['_merge'].value_counts())

# similar logfc for genes we both call significant
msk =m['_merge'] == 'both'
msk &= m['adj_p_sig_a'] == 1
print('my logfc')
print(m[msk]['logfc_a'].describe()) # mean .340
print('their logfc')
print(m[msk]['logfc_b'].describe()) # mean .307

# read in gene sets, adding flag to gene level data for if it's in at least one of the sets
gene_sets = pd.read_csv('/media/awmundy/Windows/bio/age_related_steatohepatitis/custom_gene_sets/custom_gene_sets.csv')
m['in_gene_sets']= np.where(m['gene_id'].isin(gene_sets['gene_symbol']), 1, 0)

#construct flag cols for if the counts are non 0
m['young_non_zero_b'] = 0
m['old_non_zero_b'] = 0
for col_type in ['young', 'old']:
    count_col = f'{col_type}_non_zero_b'
    cols = [f'{col_type}_{i}_b' for i in range(1, 4)]
    for col in cols:
        msk = ~np.isclose(m[col], 0)
        m.loc[msk, count_col] += 1
m['total_non_zero_b'] = m['young_non_zero_b'] + m['old_non_zero_b']

# 5 or 6 samples with non-zero values for genes in the gene sets
msk = m['in_gene_sets'] == 1
print('distribution of non-zero sample counts across genes in the gene set')
print(m[msk]['total_non_zero_b'].value_counts())

msk = np.isclose(m['adj_p_sig_b'],1)
print('distribution of non-zero sample counts across genes they consider significant')
print(m[msk]['total_non_zero_b'].value_counts())

# generally the right_onlies are less significant, both and left_only seem very similar
print('p values of genes only i have')
print(m[m['_merge'] == 'left_only']['adj_p_a'].describe())
print('my p values for genes we both have')
print(m[m['_merge'] == 'both']['adj_p_a'].describe())
print('their p values for genes we both have')
print(m[m['_merge'] == 'both']['adj_p_b'].describe())

# about 80% are not signficant
msk = m['_merge'] == 'right_only'
print('significance for genes only they have in their data')
m[msk]['adj_p_sig_b'].value_counts(dropna=False)

# same mean logfc for both of us
msk = m['in_gene_sets'] == 1
print('my logfc for genes in the gene sets')
print(m[msk]['logfc_a'].describe())
print('their logfc for genes in the gene sets')
print(m[msk]['logfc_b'].describe())
print('my logfc minus theirs')
print((m[msk]['logfc_a'] - m[msk]['logfc_b']).describe())

# fibrosis and inflammation gene sets have positive logfc which makes sense
g = pd.merge(a, gene_sets, left_on='gene_id', right_on='gene_symbol', how='inner', validate='1:m')
grp = g.groupby('gs_name', as_index=False).agg({'logfc': ['mean']})
print('gene set logfc means, my logfc')
print(grp)

# missing genes in all dge table investigation
gene_sets = pd.read_csv('/media/awmundy/Windows/bio/age_related_steatohepatitis/custom_gene_sets/custom_gene_sets.csv')
gene_sets.sort_values(by='gene_symbol', inplace=True)
# dge = pd.read_csv('/media/awmundy/Windows/bio/age_related_steatohepatitis/outputs/young_vs_old/all_dge_table.csv')
dge = pd.read_csv('/media/awmundy/Windows/bio/age_related_steatohepatitis/outputs/young_vs_old/dge_table.csv')
dge['in_gene_sets']= np.where(dge['gene_id'].isin(gene_sets['gene_symbol']), 1, 0)
# fibrosis and inflammation have almost all genes in the data, but fatty acid is missing half
# RESOLVED, for all but 3 genes in fatty acid and one in fibrosis, issue was whitespace
# fat = gene_sets.loc[gene_sets['gs_name'] == 'Fatty Acid Oxidation Custom'].copy()
gene_sets['in_dge'] = np.where(gene_sets['gene_symbol'].isin(dge['gene_id']), 1, 0)
msk = gene_sets['in_dge'] == 0
print(gene_sets[msk])


###################################################################################
#
#       2019.7.10
#       建立血管三维图
#       ---------------------
#       作者：clovermini
#       来源：CSDN
#       原文：https://blog.csdn.net/baidu_33122327/article/details/86541585
#       版权声明：本文为博主原创文章，转载请附上博文链接！
#
###################################################################################

import os
import h5py
import numpy as np
import cv2

img_path = "D:/MINE_FILE/dataSet/CTA/CTA1/"
out_h5_path = 'D:/auxiliaryPlane/project/Python/medImgSegment/Documents/blood.h5'

dataset = np.zeros((178, 1208, 1261), np.float)

# 遍历指定地址下的所有图片
cnt_num = 0
img_list = sorted(os.listdir(img_path))
os.chdir(img_path)

for img in img_list:
    if img.endswith(".tif"):
        print(img)
        gray_img = cv2.imread(img, cv2.IMREAD_GRAYSCALE)
        print (gray_img.shape)
        dataset[cnt_num, :, :] = gray_img
        cnt_num += 1

with h5py.File(out_h5_path, 'w') as f:
    f['data'] = dataset  # 将数据写入文件的主键data下面


from pygame.image import load
from pygame import surface
from pygameimagetool import getPath
from scrollimage import Direction, ScrollImage

BACKGROUND = load(getPath("sprites", "background.png"))
FOREGROUND = load(getPath("sprites", "base.png"))
DIRECTION = Direction.HORIZONTAL

class Background(surface.Surface):

    def __init__(self, size, foreground_y, bg_speed, fg_speed, pipes):
        super().__init__(size)
        self.foreground_y = foreground_y
        self.bg = ScrollImage(BACKGROUND, DIRECTION, bg_speed)
        self.fg = ScrollImage(FOREGROUND, DIRECTION, fg_speed)
        self.pipes = pipes

    def draw(self, show_pipes=True):
        bg, fg = self.bg, self.fg
        self.blit(bg, (0, 0))
        show_pipes and self.pipes.group_pipes.draw(self)
        self.blit(fg, (0, self.foreground_y))
        bg.draw()
        fg.draw()

    def move(self):
        self.bg.move()
        self.fg.move()

    def update(self):
        self.draw()
        self.move()


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

from __future__ import (division, absolute_import, print_function,
                        unicode_literals)

def howSum(targetSum: int, numbers: list) -> list:

    table = [None] * (targetSum + 1)
    table[0] = []

    i = 0
    while i <= targetSum:
        try:
            if table[i] is not None:
                for num in numbers:
                    table[i + num] = [*table[i], num]
        except IndexError:
            pass
        i += 1

    return table[targetSum]

def main():
    print(howSum(7, [2, 3]))  # [3, 2, 2]
    print(howSum(7, [5, 3, 4, 7]))  # [7]
    print(howSum(7, [2, 4]))  # None
    print(howSum(8, [2, 3, 5]))  # [2, 2, 2, 2]
    print(howSum(300, [7, 14]))  # None

if __name__ == '__main__':
    main()


import os

# 3rd party module
import numpy

# Obtain the numpy include directory.  This logic works across numpy versions.
try:
    numpy_include = numpy.get_include()
except AttributeError:
    numpy_include = numpy.get_numpy_include()

name = "swig_filter"

# create the file names and modules names
mod_name = "_" + name
wrapper = name + ".i"
interface = name + "_wrap.cpp"

srcFiles = [interface, wrapper]
swig_opts = ['-c++', '-modern']
include_dirs = [numpy_include]

srcDir = os.path.abspath('src')

for root, dirs, files in os.walk(srcDir):

    for dir in dirs:
        full_path = os.path.join(srcDir, dir)
        swig_opts += ["-I" + full_path]
        include_dirs += [full_path]

for file in os.listdir(os.path.join(srcDir,'lib')):
    if file.endswith(".cxx") or file.endswith(".c"):
        srcFiles += [os.path.join(srcDir,'lib',file)]

print(srcFiles)
print(swig_opts)
print(include_dirs)


from prefect.infrastructure.docker import DockerContainer
from prefect.deployments import Deployment
from lab_three import alpha_flow

dock_block = DockerContainer.load("basic-docker-block")

#this example pulls a docker image i created in the ui (base python slim image for docker)
#and creates a deployment for alpha flow that will run inside the docker container
#also added some tags
docker_test = Deployment.build_from_flow(
    alpha_flow,
    "docker_two",
    apply= True,
    output= True,
    infrastructure=dock_block,
    tags=['test', 'shame', 'fear', 'docker'],
    work_queue_name = 'test_env'
)


count = 0

for i in range(168630, 718098):
    number = [int(d) for d in str(i)]
    match = True
    for y in range(len(number) - 1):
        if number[y] > number[y + 1]:
            match = False

    if match:
        for x in number:
            if number.count(x) == 2:
                print(number)
                count += 1
                break

print(count)


import numpy as np

# Values from https://www.researchgate.net/publication/321661766_Acoustic_impedance_properties_of_seafloor_sediments_off_the_coast_of_Southeastern_Hainan
Z_REFERENCE_VALUES = {
    'clayey silt' : 2390000,
    'silt' : 2550000,
    'sand silt clay' : 2660000,
    'sandy silt' : 2680000,
    'silty clay' : 3160000,
    'rock' : 17000000
}

Zp1_keys = ['clayey silt', 'silt', 'sand silt clay', 'sandy silt', 'silty clay']
Zp1_DEFAULT = np.mean([Z_REFERENCE_VALUES[key] for key in Zp1_keys])
Zp2_DEFAULT = Z_REFERENCE_VALUES['rock']


name = input("Enter file:")

handle = open(name)
time = dict()

for line in handle:
    if line ==" ":continue
    if not line.startswith("From"):continue
    words = line.split()
    a = line.find(":")-2
    b = line.find(":")
    word = line[a:b]
    time[word] = time.get(word,0)+1
lst = list()
for k,v in time.items():
    t = (k,v)
    lst.append(t)
lst = sorted(lst)

for k,v in lst:
    print(k,v)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import math
from typing import List, Optional, Tuple

import cv2
import numpy as np

from line_mapper import LineMapper
# from digit_recognizer_2 import create_recognizer
from solver import solve
from sudoku.solver import load_image, cut_out_field, find_corners, perspective_transform_contour, \
    extract_subcontour
from utils import show_image, wait_windows, scale_image_target_height, segment_length, get_line_coeffs

_GRID_LINES = 10

_VIZUALIZE = True

# image = load_image("../images/big-numbers.jpg")
# image = load_image("../images/slightly_blurry.jpg")
# image = load_image("../images/sudoku.jpg")
# image = load_image("../images/sudoku-rotated.jpg")
# image = load_image("../images/sudoku-1.jpg")
# image = load_image("../images/sudoku-2.jpg")
# image = load_image("../images/sudoku-2-rotated.jpg")
image = load_image("../images/warped.jpg")
# image = load_image("tmp/001.jpg")
# image = load_image("tmp/003.jpg")
# image = load_image("tmp/005.jpg")
# image = load_image("tmp/011.jpg")
# image = load_image("tmp/100.jpg")
# image = load_image("tmp/200.jpg")
# if _VIZUALIZE:
#     show_image("orig", image)

image = scale_image_target_height(image, 640)

t = time.time()

# Extract the field, its contour and corners.
field, field_contour, _, perspective_transform_matrix = cut_out_field(image)

field_gray = cv2.cvtColor(field.image, cv2.COLOR_BGR2GRAY)
if _VIZUALIZE:
    show_image("field_gray", field_gray)

# Adjust brightness.
field_gray_closed = cv2.morphologyEx(
    field_gray, cv2.MORPH_CLOSE,
    cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)))
field_gray_adj = np.divide(field_gray, field_gray_closed)
field_gray = cv2.normalize(field_gray_adj, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC1)
if _VIZUALIZE:
    show_image("field_gray adj", field_gray)

# Binarize the field.
bin_field = cv2.adaptiveThreshold(
    field_gray, maxValue=255,
    adaptiveMethod=cv2.ADAPTIVE_THRESH_MEAN_C,
    thresholdType=cv2.THRESH_BINARY_INV,
    blockSize=17,
    C=11)
if _VIZUALIZE:
    show_image("bin_field", bin_field)

# field_gray = cv2.GaussianBlur(field_gray, (7, 7), 0)

if _VIZUALIZE:
    show_image("field_gray no numbers", field_gray)

# Apply the Sobel operator of 2nd degree to both directions.
grad_x = cv2.Sobel(field_gray, ddepth=cv2.CV_64F, dx=2, dy=0, ksize=7, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
np.clip(grad_x, a_min=0, a_max=grad_x.max(), out=grad_x)
grad_x = cv2.normalize(grad_x, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC1)

grad_y = cv2.Sobel(field_gray, ddepth=cv2.CV_64F, dx=0, dy=2, ksize=7, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
np.clip(grad_y, a_min=0, a_max=grad_y.max(), out=grad_y)
grad_y = cv2.normalize(grad_y, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC1)

if _VIZUALIZE:
    show_image("grad_x", grad_x)
    show_image("grad_y", grad_y)

# Find the left and the top borders.

# Recalculate the contour and the corners on the perspective transformed image.
transformed_field_contour = perspective_transform_contour(field_contour, perspective_transform_matrix)
top_left_idx, top_right_idx, bottom_right_idx, bottom_left_idx = find_corners(transformed_field_contour)

# In the contour, points go counterclockwise.
# Top border: top right -> top left
# Right border: bottom right -> top right
# Bottom border: bottom left -> bottom right
# Left border: top left -> bottom left
top_border = extract_subcontour(transformed_field_contour, top_right_idx, top_left_idx)
# Change points order so they go from the top left corner.
top_border = np.flip(top_border, axis=0)
# # Swap x and y.
# top_border = np.flip(top_border, axis=1)
# right_border = extract_border(bottom_right_idx, top_right_idx)
bottom_border = extract_subcontour(transformed_field_contour, bottom_left_idx, bottom_right_idx)
left_border = extract_subcontour(transformed_field_contour, top_left_idx, bottom_left_idx)

cell_side = field.side // 9

def find_lines_1(work_image: np.ndarray, viz: np.ndarray, border: np.ndarray, border_mapper: LineMapper):
    gap = 5
    max_x_dist_between_points = gap * 3
    # y_center = 0
    y_center = border[0][1]
    y_center_max = border[-1][1]
    while y_center <= y_center_max:
        x_center = border_mapper.map_x(y_center)
        b = cell_side * 2

        lines = []
        for theta in range(0, 30 + 1):
            theta_tan = math.tan(math.radians(theta))

            line_top = []
            line_bottom = []
            top_wasted = False
            bottom_wasted = False
            for x_rel in range(0, b, gap):
                if top_wasted and bottom_wasted:
                    break

                x = x_rel + x_center

                if not top_wasted:
                    if (line_top and x - line_top[-1][0] < max_x_dist_between_points
                            or not line_top and x_rel < max_x_dist_between_points):
                        y_top = y_center - int(round(theta_tan * x_rel))
                        if y_top >= 0 and work_image[y_top, x] > 0:
                            line_top.append((x, y_top))
                    else:
                        top_wasted = True

                if not bottom_wasted:
                    if (line_bottom and x - line_bottom[-1][0] < max_x_dist_between_points
                            or not line_bottom and x_rel < max_x_dist_between_points):
                        y_bottom = y_center + int(round(theta_tan * x_rel))
                        if y_bottom < work_image.shape[0] and work_image[y_bottom, x] > 0:
                            line_bottom.append((x, y_bottom))
                    else:
                        bottom_wasted = True

            if not top_wasted and line_top:
                lines.append(line_top)
            # Prevent double adding.
            if not bottom_wasted and theta != 0 and line_bottom:
                lines.append(line_bottom)

        if not lines:
            y_center += 1
            continue

        max_line = max(lines, key=len)
        if len(max_line) > int(b // gap * 0.8):
            if _VIZUALIZE:
                for x, y in max_line:
                    cv2.circle(viz, (x, y), 1, (0, 0, 255), 1)
            y_center += cell_side // 2
        else:
            y_center += 1

def find_lines_2(work_image: np.ndarray, viz: np.ndarray, border: np.ndarray, border_mapper: LineMapper):
    border_start_x, border_start_y = border[0]
    border_end_x, border_end_y = border[-1]

    min_theta = 90 - 30
    max_theta = 90 + 30

    max_rho = work_image.shape[0] + work_image.shape[1]
    min_rho = -max_rho

    theta_step = 1
    rho_step = 1

    cells_in_sub = 3
    gap = 5

    num_theta = (max_theta - min_theta) // theta_step + 1
    num_rho = (max_rho - min_rho) // theta_step + 1
    hough_space = np.zeros((num_rho, num_theta), dtype=np.int32)
    hough_space2 = [
        [0 for _ in range(num_theta)] for _ in range(num_rho)
    ]
    points = [
        [[] for _ in range(num_theta)] for _ in range(num_rho)
    ]

    num_theta_sin = [None] * (max_theta - min_theta + 1)
    num_theta_cos = [None] * (max_theta - min_theta + 1)

    thetas = np.arange(min_theta, max_theta + 1, theta_step)
    theta_rads = np.radians(thetas)
    theta_sin = np.sin(theta_rads)
    theta_cos = np.cos(theta_rads)
    theta_off = (thetas - min_theta) // theta_step

    y_from = min(border_start_y, border_end_y)
    y_to = max(border_start_y, border_end_y)
    for y in range(y_from, y_to + 1):
        x_from = border_mapper.map_x(y)
        x_to = int(x_from + cell_side * cells_in_sub)

        y_sin = theta_sin * y

        for x in range(x_from, x_to + 1, gap):
            if work_image[y, x] == 0:
                continue

            rhos = theta_cos * x
            np.add(rhos, y_sin, out=rhos)
            rhos = np.int32(rhos)
            hough_space[rhos, theta_off] += 1

            # for theta in range(min_theta, max_theta, theta_step):
            #     theta_rad = math.radians(theta)
            #     rho = int(round(
            #         y * math.sin(theta_rad) + x * math.cos(theta_rad)
            #     ))
            #     rho = rho // rho_step
            #     theta_off = (theta - min_theta) // theta_step
            #     # hough_space[rho, theta_off] += 1
            #     hough_space2[rho][theta_off] += 1
            #     points[rho][theta_off].append((x, y))

    good = np.where(hough_space > (cell_side * cells_in_sub) / (gap * 1.1))  # todo no hardcoding
    for i in range(good[0].shape[0]):
        rho = good[0][i]
        theta = good[1][i]
        theta = theta * theta_step + min_theta
        theta_rad = math.radians(theta)
        a = np.cos(theta_rad)
        b = np.sin(theta_rad)
        x0 = a*rho
        y0 = b*rho
        x1 = int(x0 + 1000*(-b))
        y1 = int(y0 + 1000*(a))
        x2 = int(x0 - 1000*(-b))
        y2 = int(y0 - 1000*(a))
        cv2.line(viz, (x1,y1), (x2,y2), (0,0,255), 1)
    pass

_, grad_y_thresh = cv2.threshold(grad_y, 5, 255, cv2.THRESH_BINARY)
top_border_mapper = LineMapper(top_border)

_, grad_x_thresh = cv2.threshold(grad_x, 5, 255, cv2.THRESH_BINARY)
grad_x_thresh = cv2.rotate(grad_x_thresh, cv2.ROTATE_90_COUNTERCLOCKWISE)
left_border_mapper = LineMapper(left_border)

work_image_orig = grad_y
work_image = grad_y_thresh
# work_image = grad_x_thresh
border = left_border
# border = top_border
border_mapper = left_border_mapper
# border_mapper = top_border_mapper

viz = cv2.cvtColor(work_image, cv2.COLOR_GRAY2BGR)

# find_lines_1(work_image, viz, border, border_mapper)
# for _ in range(1000):
#     find_lines_1(work_image, viz, border, border_mapper)
    # find_lines_2(work_image, viz, border, border_mapper)
# find_lines_2(work_image, viz, border, border_mapper)

def find_next_line(current_line: np.ndarray, horizonal_look_ahead: int):
    x1 = top_border[0, 0]
    x2 = x1 + horizonal_look_ahead
    a, b = np.polyfit(current_line[:, 0], current_line[:, 1], 1)
    y1 = int(round(a * x1 + b))
    y2 = int(round(a * x2 + b))

    # print(math.degrees(math.atan(a)))

    def _relative_coords(x1: int, y1: int, x2: int, y2: int) -> Tuple[int, int, int, int]:
        assert x1 < x2
        x2 -= x1
        x1 = 0
        y_min = min(y1, y2)
        y1 -= y_min
        y2 -= y_min
        return x1, y1, x2, y2

    x1_rel, y1_rel, x2_rel, y2_rel = _relative_coords(x1, y1, x2, y2)

    def create_mask(x1_rel: int, y1_rel: int, x2_rel: int, y2_rel: int) -> Tuple[np.ndarray, int, int]:
        assert x1_rel < x2_rel
        mask = np.zeros((abs(y1_rel - y2_rel) + 1, x2_rel - x1_rel + 1), dtype=np.uint8)
        cv2.line(mask, (x1_rel, y1_rel), (x2_rel, y2_rel), 255, 1)
        return mask

    mask = create_mask(x1_rel, y1_rel, x2_rel, y2_rel)
    max_intersect = np.count_nonzero(mask)
    intersect_threshold = max_intersect * 0.7

    seen_max = None
    seen_max_y_off = None
    seen_max_x_off = None
    for y_off in range(y1 + cell_side // 3, y1 + cell_side * 2):
        x_off = left_border_mapper.map_x(y_off)

        sub_img = work_image[y_off:mask.shape[0] + y_off, x_off:mask.shape[1] + x_off]
        assert sub_img.shape == mask.shape

        intersect = np.bitwise_and(sub_img, mask)
        s = np.sum(intersect) // 255

        if s >= intersect_threshold:
            if seen_max is None or s > seen_max:
                seen_max = s
                seen_max_y_off = y_off
                seen_max_x_off = x_off

            # print(y_off, s)
            # cv2.line(viz, (x1_rel + x_off, y1_rel + y_off), (x2_rel + x_off, y2_rel + y_off), (0, 255, 0), 1)
        else:
            if seen_max is not None:
                # print("Stopping at", y_off)
                break
    else:
        assert False

    # todo optimization: don't refine if more than another threshold

    # print(seen_max, seen_max_x_off, seen_max_y_off)
    # cv2.line(viz, (x1_rel + seen_max_x_off, y1_rel + seen_max_y_off), (x2_rel + seen_max_x_off, y2_rel + seen_max_y_off), (0, 255, 0), 1)

    win_h_half = 2

    ys_centered = np.arange(win_h_half * 2 + 1) - win_h_half
    ys_centered = ys_centered[:, np.newaxis]

    x = x1_rel + seen_max_x_off
    y = y1_rel + seen_max_y_off

    dx = 5
    dy = a * dx
    points_to_collect = horizonal_look_ahead // dx
    line = []
    for i in range(points_to_collect):
        x_int = int(round(x))
        y_int = int(round(y))

        y_int = refine_point(x_int, y_int, 2,)
        if y_int is not None:
           line.append((x_int, y_int))

        # # cv2.rectangle(viz, (x_int, y_int - win_h_half), (x_int, y_int + win_h_half), (0, 255, 0), 1)
        # window = work_image_orig[y_int - win_h_half:y_int + win_h_half + 1, x_int:x_int + 1]
        # s = np.sum(window)
        # if s > 0:
        #     avg = np.sum(ys_centered * window) / s
        #     avg = int(round(avg))
        #     # print(avg)
        #     line.append((x_int, y_int + avg))

        x += dx
        y += dy
    return np.array(line)

def continue_line(line: List[np.ndarray]):
    win_h_half = 1

    ys_centered = np.arange(win_h_half * 2 + 1) - win_h_half
    ys_centered = ys_centered[:, np.newaxis]

    line = list(line)
    last_len = len(line)

    for run in range(1000):  # effectively infinite
        tail = np.array(line[-5:])
        a, b = np.polyfit(tail[:, 0], tail[:, 1], 1)
        x, y = tail[-1]
        dx = 5
        dy = a * dx

        if x >= field.margin + field.side:
            break

        skipped_steps = 0
        for _ in range(40):
            x += dx

            if x >= field.margin + field.side:
                break

            y += dy
            x_int = int(round(x))
            y_int = int(round(y))
            # cv2.circle(viz, (x_int, y_int), 2, (0, 0, 255), -1)
            # print(work_image[y_int, x_int])

            if run % 2 == 0:
                color = (0, 0, 255)
            else:
                color = (255, 0, 0)

            # if _VIZUALIZE:
            #     cv2.rectangle(viz, (x_int, y_int - win_h_half), (x_int, y_int + win_h_half), color, 1)
            window = work_image_orig[y_int - win_h_half:y_int + win_h_half + 1, x_int:x_int + 1]
            s = np.sum(window)
            if s > 0:
                avg = np.sum(ys_centered * window) / s
                avg = int(round(avg))
                if _VIZUALIZE:
                    cv2.circle(viz, (x_int, y_int + avg), 2, color, -1)
                line.append((x_int, y_int + avg))
                if avg != 0:
                    break
            else:
                skipped_steps += 1
                if skipped_steps >= 2:
                    break
                else:
                    continue

        if len(line) == last_len:
            break
        last_len = len(line)

def refine_point(x: int, y: int, win_h_half: int) -> Optional[int]:
    ys_centered = np.arange(win_h_half * 2 + 1) - win_h_half
    ys_centered = ys_centered[:, np.newaxis]
    window = work_image_orig[y - win_h_half:y + win_h_half + 1, x:x + 1]
    s = np.sum(window)
    if s > 0:
        avg = np.sum(ys_centered * window) / s
        avg = int(round(avg))
        return y + avg
    else:
        return None

horizonal_look_ahead = cell_side * 2

first_point_behind = np.argmax(top_border[:, 0] >= top_border[0, 0] + horizonal_look_ahead) + 1
current_line = top_border[:first_point_behind + 1]

if _VIZUALIZE:
    for x, y in top_border:
        y1 = refine_point(x, y, 2)
        if y1 is not None:
            y = y1
            cv2.circle(viz, (x, y), 1, (0, 255, 0), -1)

for i in range(8):
    # Due to noise and the border thickness, the first point is likely to be an outlier,
    # skipping it.
    current_line = current_line[1:, :]
    current_line = find_next_line(current_line, horizonal_look_ahead)
    if _VIZUALIZE:
        for x, y in current_line[1:]:
            cv2.circle(viz, (x, y), 1, (0, 255, 0), -1)
    continue_line(current_line)

if _VIZUALIZE:
    for x, y in bottom_border:
        y1 = refine_point(x, y, 2)
        if y1 is not None:
            y = y1
            cv2.circle(viz, (x, y), 1, (0, 255, 0), -1)

print()
print((time.time() - t) * 1000)

if _VIZUALIZE:
    show_image("grad_x_viz", viz, 700)
if _VIZUALIZE:
    wait_windows()
exit()

cells_in_sub = 3

x_from = 0
x_to = field.margin + cell_side * cells_in_sub
assert x_to > x_from

gap = 5

min_theta = 90 - 30
max_theta = 90 + 30
theta_step = 1
rho_step = 1

max_rho = image.shape[0] + (x_to - x_from)
min_rho = -max_rho

num_theta = (max_theta - min_theta) // theta_step + 1
num_rho = max_rho - min_rho + 1
hough_space = np.zeros((num_rho, num_theta), dtype=np.int32)
points = [
    [[] for _ in range(num_theta)] for _ in range(num_rho)
]
for y_center in range(grad_y_thresh.shape[0]):
    # TODO x should start with mapping
    for x_center in range(x_from, x_to, gap):
        if grad_y_thresh[y_center, x_center] == 0:
            continue
        for theta in range(min_theta, max_theta, theta_step):
            theta_rad = math.radians(theta)
            rho = int(round(
                y_center * math.sin(theta_rad) + x_center * math.cos(theta_rad)
            ))
            rho = rho // rho_step
            theta = (theta - min_theta) // theta_step
            hough_space[rho, theta] += 1
            points[rho][theta].append((x_center, y_center))

good = np.where(hough_space > (x_to - x_from) / gap / 100)  # todo no hardcoding
grad_y = cv2.cvtColor(grad_y, cv2.COLOR_GRAY2BGR)

lines = []
for i in range(good[0].shape[0]):
    rho = good[0][i]
    theta = good[1][i]
    line_points = points[rho][theta]
    line_points = sorted(line_points, key=lambda item: (item[0], item[1]))

    broken_line = False
    for j in range(len(line_points) - 1):
        x1 = line_points[j][0]
        x2 = line_points[j + 1][0]
        if abs(x1 - x2) > gap * 2.5:
            broken_line = True
            break
    if broken_line:
        continue

    [x1, y_top] = line_points[0]
    [x2, y2] = line_points[-1]
    length = segment_length(x1, y_top, x2, y2)
    if length / cell_side > cells_in_sub * 1.2:
        continue
    if length / cell_side < cells_in_sub * 0.6:
        continue

    rho = rho * rho_step
    theta = theta * theta_step + min_theta

    # print(rho, theta)
    # print(length / cell_side)

    lines.append((rho, theta, line_points))
    for x_center, y_center in line_points:
        cv2.circle(grad_y, (x_center, y_center), 1, (0, 0, 255), 1)
    # break

    # theta_rad = math.radians(theta)
    # a = np.cos(theta_rad)
    # b = np.sin(theta_rad)
    # x0 = a*rho
    # y0 = b*rho
    # x1 = int(x0 + 1000*(-b))
    # y1 = int(y0 + 1000*(a))
    # x2 = int(x0 - 1000*(-b))
    # y2 = int(y0 - 1000*(a))
    # cv2.line(sub_image,(x1,y1),(x2,y2),(0,0,255),1)

# cv2.line(grad_y, (10,10), (100, int(math.tan(math.radians(45)) * 100)), (0, 0, 255), 1)
# cv2.line(grad_y, (10,10), (100, int(math.tan(math.radians(30)) * 100)), (0, 0, 255), 1)
# cv2.line(grad_y, (10,10), (100, int(math.tan(math.radians(18)) * 100)), (0, 0, 255), 1)

lines = sorted(lines, key=lambda x: x[0])  # sort by rho

if _VIZUALIZE:
    show_image("xxx", grad_y, 700)

print((time.time() - t) * 1000)

if _VIZUALIZE:
    # show_image("unwrapped", unwrapped_viz)
    # show_image("wrapped back", wrapped_viz)
    # show_image("field_viz", field_viz, 700)
    pass

if _VIZUALIZE:
    wait_windows()


from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404, redirect, render
from django.http  import HttpResponseRedirect,Http404
from . forms import UpdateUserForm, UpdateUserProfileForm, UserRegisterForm,HoodForm,BusinessForm,PostForm
from .models import NeighbourHood,Business,Post,Profile
from django.contrib.auth.decorators import login_required
from django.urls import reverse
from django.forms.models import model_to_dict
from django.contrib import messages

def index(request):
    return render(request,'all-neighbour/home.html')

def register(request):
    if request.user.is_authenticated:
    #redirect user to the profile page
        return redirect('home')
    if request.method=="POST":
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            form.save()
            username = form.cleaned_data.get('username')
            return redirect('login')

    else:
        form = UserRegisterForm()
    return render(request,"registration/register.html",{'form':form})

@login_required(login_url='login')
def hoods(request):
    current_user=request.user
    hoods = NeighbourHood.objects.all()
    return render(request,"all-neighbour/hoods.html",{'hoods':hoods,'current_user':current_user})

@login_required(login_url='login')
def profile(request, username):
    current_user=request.user

    if request.method == 'POST':
        user_form = UpdateUserForm(request.POST, instance=request.user)
        profile_form = UpdateUserProfileForm(request.POST, request.FILES, instance=request.user.profile)
        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.save()
            return HttpResponseRedirect(request.path_info)
    else:
        user_form = UpdateUserForm(instance=request.user)
        profile_form = UpdateUserProfileForm(instance=request.user.profile)

    return render(request, 'all-neighbour/profile.html', {'user_form':user_form,'profile_form':profile_form})

@login_required(login_url='login')
def new_hood(request):
    if request.method == 'POST':
        form = HoodForm(request.POST, request.FILES)
        if form.is_valid():
            hood = form.save(commit=False)
            hood.admin = request.user
            hood.save()
            return HttpResponseRedirect(reverse("hoods"))
    else:
        form = HoodForm()
    return render(request, 'all-neighbour/newhood.html', {'form': form})

@login_required(login_url='login')
def user_hood(request,id):
    current_user = request.user
    hood = NeighbourHood.objects.get(id=id)
    members = Profile.objects.filter(neighbourhood=hood)
    businesses = Business.objects.filter(neighbourhood=hood)
    posts = Post.objects.filter(neighbourhood=hood)
    request.user.profile.neighbourhood = hood
    request.user.profile.save()

    return render(request, 'all-neighbour/user_hood.html', {'hood': hood,'businesses':businesses,
                                                            'posts':posts,'current_user':current_user,
                                                            'members':members})

@login_required(login_url='login')
def leave_hood(request,id):
    hood = NeighbourHood.objects.get(id=id)
    request.user.profile.neighbourhood = None
    request.user.profile.save()
    return redirect('hoods')

@login_required(login_url='login')
def new_business(request,id):
    hood = NeighbourHood.objects.get(id=id)
    title = 'ADD BUSINESS'
    if request.method=='POST':
        bus_form = BusinessForm(request.POST,request.FILES)
        if bus_form.is_valid():
            business = bus_form.save(commit=False)
            business.neighbourhood = hood
            business.owner = request.user.profile
            business.save()
            return redirect('my_hood', id)
    else:
        bus_form = BusinessForm()
    return render(request,'all-neighbour/business.html',{'bus_form':bus_form,'title':title})

@login_required(login_url='login')
def new_post(request,id):
    hood = NeighbourHood.objects.get(id=id)
    title = 'ADD POST'
    if request.method=='POST':
        post_form = PostForm(request.POST)
        if post_form.is_valid():
            post = post_form.save(commit=False)
            post.neighbourhood = hood
            post.owner = request.user
            post.save()
            return redirect('my_hood', id)
    else:
        post_form = PostForm()
    return render(request,'all-neighbour/post.html',{'post_form':post_form,'title':title})

@login_required(login_url='login')
def update_business(request,id,bus_id):
    instance= Business.objects.get(id=bus_id)
    title = 'UPDATE BUSINESS'
    if request.method=='POST':
        bus_form = BusinessForm(request.POST,request.FILES,instance=instance)
        if bus_form.is_valid():
            bus_form.save()
        return redirect('my_hood', id)
    else:
        # bus_form = BusinessForm(initial=model_to_dict(instance))
        bus_form = BusinessForm(instance=instance)
    return render(request,'all-neighbour/business.html',{'bus_form':bus_form,'title':title})

@login_required(login_url='login')
def update_post(request,id,post_id):
    title = 'UPDATE POST'
    instance= Post.objects.get(id=post_id)
    if request.method=='POST':
        post_form = PostForm(request.POST,instance=instance)
        if post_form.is_valid():
           post_form.save()
        return redirect('my_hood', id)
    else:
        post_form = PostForm(instance=instance)
    return render(request,'all-neighbour/post.html',{'post_form':post_form,'title':title})

@login_required(login_url='login')
def update_hood(request,id):
    title = 'UPDATE HOOD'
    instance= NeighbourHood.objects.get(id=id)
    if request.method=='POST':
        form = HoodForm(request.POST,request.FILES,instance=instance)
        if form.is_valid():
           form.save()
        messages.success(request, ('Hood Updated Successfullly'))
        return redirect('hoods')
    else:
        form = HoodForm(instance=instance)
    return render(request,'all-neighbour/newhood.html',{'form':form,'title':title})

@login_required(login_url='login')
def delete_business(request,id,bus_id):
    business= Business.objects.get(id=bus_id)
    business.delete_business()
    messages.info(request, ('Business Deleted'))
    return redirect('my_hood', id)

@login_required(login_url='login')
def delete_post(request,id,post_id):
    post= Post.objects.get(id=post_id)
    post.delete_post()
    messages.info(request, ('Post Deleted'))
    return redirect('my_hood', id)

@login_required(login_url='login')
def search_hood(request):
    current_user= request.user
    if request.method == 'GET':
        name = request.GET.get("name")
        hoods = NeighbourHood.objects.filter(name__icontains=name).all()

    return render(request, 'all-neighbour/search.html', {'hoods': hoods,'current_user':current_user})

def user_profile(request, username):
    current_user=request.user
    user_poster = get_object_or_404(User, username=username)

    if request.user == user_poster:
        return redirect('profile', username=request.user.username)

    return render(request, 'all-neighbour/member.html', {'user_poster': user_poster,
                                                     'current_user':current_user})