import enum
from datetime import datetime
from typing import TYPE_CHECKING, Any, ClassVar
from uuid import UUID

import sqlalchemy
import sqlalchemy as sa
from sqlalchemy import (
    TIMESTAMP,
    BigInteger,
    Boolean,
    ForeignKey,
    Index,
    Integer,
    String,
    Text,
    UniqueConstraint,
)
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import (
    Mapped,
    MappedColumn,
    declared_attr,
    mapped_column,
    relationship,
)
from sqlalchemy_utils.types.ts_vector import TSVectorType

from polar.config import settings
from polar.enums import Platforms
from polar.kit.db.models import RecordModel
from polar.kit.extensions.sqlalchemy import PostgresUUID, StringEnum
from polar.types import JSONAny

if TYPE_CHECKING:  # pragma: no cover
    from polar.models.issue_reference import IssueReference
    from polar.models.organization import Organization
    from polar.models.pledge import Pledge
    from polar.models.repository import Repository

class IssueFields:
    class State(str, enum.Enum):
        OPEN = "open"
        CLOSED = "closed"

    platform: Mapped[Platforms] = mapped_column(StringEnum(Platforms), nullable=False)
    external_id: Mapped[int] = mapped_column(Integer, nullable=False)

    @declared_attr
    def organization_id(cls) -> MappedColumn[UUID]:
        return mapped_column(
            PostgresUUID,
            ForeignKey("organizations.id"),
            nullable=False,
            index=True,
        )

    @declared_attr
    def organization(cls) -> "Mapped[Organization]":
        return relationship("Organization", lazy="raise")

    @declared_attr
    def repository_id(cls) -> "MappedColumn[UUID]":
        return mapped_column(
            PostgresUUID,
            ForeignKey("repositories.id"),
            nullable=False,
            index=True,
        )

    @declared_attr
    def repository(cls) -> "Mapped[Repository]":
        return relationship("Repository", lazy="raise")

    number: Mapped[int] = mapped_column(Integer, nullable=False)

    title: Mapped[str] = mapped_column(String, nullable=False)
    body: Mapped[str | None] = mapped_column(Text, nullable=True)
    comments: Mapped[int | None] = mapped_column(Integer, nullable=True)

    author: Mapped[JSONAny] = mapped_column(JSONB(none_as_null=True), nullable=True)
    author_association: Mapped[str | None] = mapped_column(String, nullable=True)
    labels: Mapped[JSONAny] = mapped_column(JSONB(none_as_null=True), nullable=True)
    assignee: Mapped[JSONAny] = mapped_column(JSONB(none_as_null=True), nullable=True)
    assignees: Mapped[JSONAny] = mapped_column(JSONB(none_as_null=True), nullable=True)
    milestone: Mapped[JSONAny] = mapped_column(JSONB(none_as_null=True), nullable=True)
    closed_by: Mapped[JSONAny] = mapped_column(JSONB(none_as_null=True), nullable=True)
    reactions: Mapped[JSONAny] = mapped_column(JSONB(none_as_null=True), nullable=True)

    state: Mapped[str] = mapped_column(StringEnum(State), nullable=False)
    state_reason: Mapped[str | None] = mapped_column(String, nullable=True)

    issue_closed_at: Mapped[datetime | None] = mapped_column(
        TIMESTAMP(timezone=True), nullable=True
    )
    issue_created_at: Mapped[datetime] = mapped_column(
        TIMESTAMP(timezone=True), nullable=False
    )
    issue_modified_at: Mapped[datetime | None] = mapped_column(
        TIMESTAMP(timezone=True), nullable=True
    )

    title_tsv: Mapped[TSVectorType] = mapped_column(
        TSVectorType("title", regconfig="simple"),
        sa.Computed("to_tsvector('simple', \"title\")", persisted=True),
    )

issue_fields_mutables = {
    "title",
    "body",
    "comments",
    "author",
    "author_association",
    "labels",
    "assignee",
    "assignees",
    "milestone",
    "closed_by",
    "reactions",
    "state",
    "state_reason",
    "issue_closed_at",
    "issue_modified_at",
}

class Issue(IssueFields, RecordModel):
    __tablename__ = "issues"
    __table_args__ = (
        UniqueConstraint("external_id"),
        UniqueConstraint("platform", "external_lookup_key"),
        UniqueConstraint("organization_id", "repository_id", "number"),
        # Search index
        Index("idx_issues_title_tsv", "title_tsv", postgresql_using="gin"),
        Index(
            "idx_issues_id_closed_at",
            "id",
            "issue_closed_at",
        ),
        Index(
            "idx_issues_pledged_amount_sum",
            "pledged_amount_sum",
        ),
        # TODO: deprecated, remove when we've migrated to positive_reactions_count and
        # total_engagement_count
        Index(
            "idx_issues_reactions_plus_one",
            sqlalchemy.text("((reactions::jsonb ->> 'plus_one')::int)"),
            postgresql_using="btree",
        ),
        Index(
            "idx_issues_positive_reactions_count",
            "positive_reactions_count",
        ),
        Index(
            "idx_issues_positive_total_engagement_count",
            "total_engagement_count",
        ),
    )

    TRANSFERRABLE_PROPERTIES: ClassVar[set[str]] = {
        "pledge_badge_embedded_at",
        "pledge_badge_ever_embedded",
        "pledge_badge_currently_embedded",
        "has_pledge_badge_label",
        "badge_custom_content",
        "funding_goal",
        "pledged_amount_sum",
        "needs_confirmation_solved",
        "confirmed_solved_at",
        "confirmed_solved_by",
    }

    external_lookup_key: Mapped[str] = mapped_column(String, nullable=True, index=True)

    pledge_badge_embedded_at: Mapped[datetime | None] = mapped_column(
        TIMESTAMP(timezone=True), nullable=True
    )
    pledge_badge_ever_embedded: Mapped[bool] = mapped_column(
        Boolean, nullable=False, default=False
    )
    pledge_badge_currently_embedded: Mapped[bool] = mapped_column(
        Boolean, nullable=False, default=False
    )

    has_pledge_badge_label: Mapped[bool] = mapped_column(
        Boolean, nullable=False, default=False
    )

    badge_custom_content: Mapped[str | None] = mapped_column(
        String,
        nullable=True,
        default=None,
    )

    github_issue_etag: Mapped[str | None] = mapped_column(String, nullable=True)
    github_issue_fetched_at: Mapped[datetime | None] = mapped_column(
        TIMESTAMP(timezone=True), nullable=True
    )

    github_timeline_etag: Mapped[str | None] = mapped_column(String, nullable=True)
    github_timeline_fetched_at: Mapped[datetime | None] = mapped_column(
        TIMESTAMP(timezone=True), nullable=True
    )

    @declared_attr
    def references(cls) -> "Mapped[list[IssueReference]]":
        return relationship("IssueReference", lazy="raise", viewonly=True)

    @declared_attr
    def pledges(cls) -> "Mapped[list[Pledge]]":
        return relationship(
            "Pledge",
            lazy="raise",
            viewonly=True,
        )

    funding_goal: Mapped[int | None] = mapped_column(
        BigInteger, nullable=True, default=None
    )

    # calculated sum of pledges, used for sorting and in Public APIs
    pledged_amount_sum: Mapped[int] = mapped_column(
        BigInteger, nullable=False, default=0
    )

    issue_has_in_progress_relationship: Mapped[bool] = mapped_column(
        Boolean, nullable=False, server_default="false"
    )

    issue_has_pull_request_relationship: Mapped[bool] = mapped_column(
        Boolean, nullable=False, server_default="false"
    )

    positive_reactions_count: Mapped[int] = mapped_column(
        Integer, nullable=False, default=0
    )

    total_engagement_count: Mapped[int] = mapped_column(
        Integer, nullable=False, default=0
    )

    needs_confirmation_solved: Mapped[bool] = mapped_column(
        Boolean, default=False, nullable=False
    )

    confirmed_solved_at: Mapped[datetime | None] = mapped_column(
        TIMESTAMP(timezone=True), nullable=True
    )

    confirmed_solved_by: Mapped[UUID | None] = mapped_column(
        PostgresUUID,
        ForeignKey("users.id"),
        nullable=True,
    )

    # a number between 0 and 100
    # share of rewards that will go to contributors of this issue
    upfront_split_to_contributors: Mapped[int | None] = mapped_column(
        Integer, nullable=True
    )

    @classmethod
    def contains_pledge_badge_label(cls, labels: Any) -> bool:
        if not labels:
            return False

        return any(
            label["name"].lower() == settings.GITHUB_BADGE_EMBED_LABEL
            for label in labels
        )


from fpdf import FPDF

pdf = FPDF(orientation='P', unit='pt', format='A4')
pdf.add_page()

pdf.image('logo.jpeg', w=80, h=80)

pdf.set_font(family='Times', style='B', size=24)
pdf.cell(w=0, h=50, txt='Offerta', align='C', border=1, ln=1)

pdf.set_font(family='Times', style='B', size=14)
pdf.cell(w=0, h=15, txt='Description', ln=1)
pdf.set_font(family='Times', size=12)
content = '''
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque euismod, erat vitae tincidunt congue, mi felis varius nisi, quis consectetur nibh ipsum ac urna. Pellentesque iaculis erat massa, in accumsan sapien tempor vel. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Duis convallis enim nisi. Donec imperdiet varius mi non pharetra. Aliquam sit amet dictum sapien. Pellentesque orci eros, malesuada ac tristique non, finibus ut risus.
'''
pdf.multi_cell(w=0, h=15, txt=content)

pdf.set_font(family='Times', style='B', size=14)
pdf.cell(w=100, h=25, txt='Kindom:')

pdf.set_font(family='Times', size=14)
pdf.cell(w=100, h=25, txt='Animalia', ln=1)

pdf.set_font(family='Times', style='B', size=14)
pdf.cell(w=100, h=25, txt='ABC:')

pdf.set_font(family='Times', size=14)
pdf.cell(w=100, h=25, txt='DEF', ln=1)

pdf.output('output.pdf')

import os
os.system('output.pdf')


from django.contrib.auth import login, authenticate
from django.contrib.auth.decorators import login_required

from django.shortcuts import render, redirect
from ob_system.forms import SignUpForm, LoginForm

from django.http import Http404
from django.core.exceptions import ObjectDoesNotExist, EmptyResultSet

from .models import Booking, Report, Archive, CriminalProfile, CashBail
from .forms import BookingForm, ReportingForm, CriminalProfileForm, CashBailForm
from .filters import SearchFilter

import datetime as dt
import datetime

from dal import autocomplete

from django.contrib.sites.shortcuts import get_current_site
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
from django.template.loader import render_to_string
from .tokens import account_activation_token

from django.contrib.auth.models import User
from django.utils.encoding import force_text
from django.utils.http import urlsafe_base64_decode

# Create your views here.
@login_required(login_url='/accounts/login/')
def officer_login(request):

    try:

        if request.method == 'POST':

            form = LoginForm(request.POST)

            if form.is_valid():

                user = form.save(commit=False)
                user.is_active = True
                user.save()

                return redirect(index)

            else:

                form = LoginForm()

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

        else:

            form = LoginForm()

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

    except Exception as exception:

        raise exception

@login_required(login_url='/accounts/login/')
def signup(request):

    try:

        if request.method == 'POST':
            form = SignUpForm(request.POST)
            if form.is_valid():
                user = form.save(commit=False)
                user.is_active = False
                user.save()

                current_site = get_current_site(request)
                subject = 'Activate Your Account'
                message = render_to_string('emailing/account_activation_email.html', {
                    'user': user,
                    'domain': current_site.domain,
                    'uid': urlsafe_base64_encode(force_bytes(user.pk)),
                    'token': account_activation_token.make_token(user),
                })
                user.email_user(subject, message)

                return redirect('account_activation_sent')
        else:
            form = SignUpForm()
        return render(request, 'signup.html', {'form': form})

    except Exception as exception:

        raise exception

def account_activation_sent(request):

    return render(request, 'emailing/account_activation_sent.html')

@login_required(login_url='/accounts/login/')
def activate(request, uidb64, token):
    try:
        uid = force_text(urlsafe_base64_decode(uidb64))
        user = User.objects.get(pk=uid)
    except (TypeError, ValueError, OverflowError, User.DoesNotExist):
        user = None

    if user is not None and account_activation_token.check_token(user, token):
        user.is_active = True
        user.profile.email_confirmed = True
        user.save()
        return redirect('login')
    else:
        return render(request, 'emailing/account_activation_invalid.html')

# The landing page
@login_required(login_url='/accounts/login/')
def index(request):

    suspect_list = CriminalProfile.objects.all()

    suspect_filter = SearchFilter(request.GET, queryset=suspect_list)

    # return render(request, 'search/searchlist.html', {'filter': suspect_filter})

    return render(request, 'index.html',{'filter': suspect_filter})

# occurrence book
@login_required(login_url='/accounts/login/')
def occurrence_book(request):

    '''
    :param request: current day reports
    :return: current day bookings and reports
    '''

    # if not request.user.is_authenticated():
    #
    #     return Archive.objects.none()

    try:
        date = dt.date.today()

        bookings = Booking.current_day_bookings().order_by('-time')

        reports = Report.current_day_reports().order_by('-time')

        try:

            if request.method == 'POST':

                reportingform = ReportingForm(request.POST)
                suspectform = CriminalProfileForm(request.POST)

                if reportingform.is_valid():

                    reporting = reportingform.save(commit=False)
                    reporting.user = request.user
                    reporting.save()

                    return redirect(occurrence_book)

                else:

                    reportingform = ReportingForm()

                if suspectform.is_valid():

                    profile = suspectform.save(commit=False)
                    profile.user = request.user
                    profile.save()

                    return redirect('search')

                else:

                    suspectform = CriminalProfileForm()

                    return render(request, 'occurrence-book/occurrence.html', {'reportingform': reportingform, 'date': date,
                                                                               'bookings': bookings, 'reports': reports,
                                                                               'suspectform': suspectform})

            else:

                reportingform = ReportingForm()
                suspectform = CriminalProfileForm()

                return render(request, 'occurrence-book/occurrence.html', {'reportingform': reportingform, 'date': date,
                                                                           'bookings': bookings, 'reports': reports,
                                                                           'suspectform': suspectform})

        except Exception as exception:

            raise exception

    except Exception as exception:

        raise exception

# Archives page
@login_required(login_url='/accounts/login/')
def archives(request):

    '''
    :param request:
    :return: list of searched record e.g bookings and reports

    '''

    try:

        return render(request, 'archives/archive.html')

    except ValueError:

        raise Http404()

#  Cash bail page
@login_required(login_url='/accounts/login/')
def cash_bail(request):

    '''
    :param request: list of current day bailed out suspects
    :return:
    '''
    date = dt.date.today()

    # now = datetime.datetime.now().strftime('%H:%M:%S')
    bail = CashBail.objects.all()

    try:

        if request.method == 'POST':

            form = CashBailForm(request.POST)

            if form.is_valid():

                bail = form.save(commit=False)

                bail.user = request.user

                bail.save()

                return redirect(cash_bail)

            else:

                form = CashBailForm()

                return render(request, 'occurrence-book/cashbail.html', {'form': form,'date':date,'bail':bail})

        else:

            form = CashBailForm()

            return render(request, 'occurrence-book/cashbail.html', {'form': form,'date':date,'bail':bail})

    except Exception as exception:

        raise exception

# return render(request, 'occurrence-book/cashbail.html',{'date':date,'bail':bail})

@login_required(login_url='/accounts/login/')
def create_criminal_profile(request):

    '''
    :param request: function to create a new suspect profile
    :return: created suspect profile
    '''

    try:

        if request.method == 'POST':

            form = CriminalProfileForm(request.POST)

            if form.is_valid():

                profile = form.save(commit=False)

                profile.user = request.user

                profile.save()

                return redirect(occurrence_book)

            else:

                form = CriminalProfileForm()

                return render(request, 'occurrence-book/occurrence.html', {'form': form})

        else:

            form = CriminalProfileForm()

            return render(request, 'occurrence-book/occurrence.html', {'form': form})

    except Exception as exception:

        raise exception

@login_required(login_url='/accounts/login/')
def cashbailform(request):

    '''
    :param request: function to record a bailed out suspect
    :return: list of all bailed out suspects
    '''

    try:

        if request.method == 'POST':

            form = CashBailForm(request.POST)

            if form.is_valid():

                bail = form.save(commit=False)

                bail.user = request.user

                bail.save()

                return redirect(cash_bail)

            else:

                form = CashBailForm()

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

        else:

            form = CashBailForm()

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

    except Exception as exception:

        raise exception

@login_required(login_url='/accounts/login/')
def criminal_profile(request, criminalprofile_id_no):

    '''

    :param request: single suspect
    :param criminalprofile_id_no:
    :return: suspect profile and related items
    '''

    try:

        profile = CriminalProfile.objects.get(id_no=criminalprofile_id_no)

        bookings = Booking.objects.filter(criminal=profile).all().order_by('-id')

        try:

            if request.method == 'POST':

                form = BookingForm(request.POST)

                if form.is_valid():
                    booking = form.save(commit=False)
                    booking.user = request.user
                    booking.save()

                    return redirect(occurrence_book)

                else:

                    form = BookingForm()

                    return render(request, 'profiles/criminal-profile.html', {'profile': profile, 'bookings': bookings,
                                                                              'form': form})

            else:

                form = BookingForm()

                return render(request, 'profiles/criminal-profile.html', {'profile': profile, 'bookings': bookings,
                                                                          'form': form})

        except Exception as exception:

            raise exception

    except Exception as exception:

        raise exception

@login_required(login_url='/accounts/login/')
def search_results(request):

    try:

        if 'q' in request.GET and request.GET['q']:

            search_term = request.GET.get('q')

            bookings = Booking.search_by_pub_date(search_term).all()

            reportings = Report.search_by_pub_date(search_term).all()

            return render(request, 'archives/archive.html', {'bookings': bookings, 'reportings': reportings})

        else:

            message = "You haven't searched for any term"

            return render(request, 'searched-tag.html', {"message": message,})

    except Exception as exception:
        raise exception

@login_required(login_url='/accounts/login/')
def search(request):

    '''

    :param request: function to search db for searched item
    :return: return related searched items from the database
    '''

    suspect_list = CriminalProfile.objects.all()

    suspect_filter = SearchFilter(request.GET, queryset=suspect_list)

    return render(request, 'search/searchlist.html', {'filter': suspect_filter})


'''
A viewer for cta events, currently only LSTs are supported

Usage:
    cta_event_viewer.py [options]

Options:
    --ip=<ip>       the ip to listen to [default: 127.0.0.1]
    --port=<port>   the port to listen to [default: 5000]
    --rows=<rows>   number of rows of telescope views [default: 2]
    --cols=<cols>   number of columns of telescope views [default: 2]
'''
from telescope import LST
from windows import TelescopeEventView
import Tkinter as tk
from itertools import cycle
import numpy as np
from read import ReadProtoBuf
from threading import Event

from collections import deque
from docopt import docopt

args = docopt(__doc__)

queue = deque(maxlen=100)
stop_event = Event()

def check_queue():
    if len(queue) > 0:
        root.event_generate('<<new_event>>')
    root.after(10, check_queue)

def handle_new_event(event):
    viewer = next(viewers)
    event = queue.popleft()
    print(len(queue))
    viewer.data = np.array(event.data)

root = tk.Tk()

reader = ReadProtoBuf(
    args['--ip'],
    args['--port'],
    queue,
    stop_event,
)

viewers = []
for i in range(int(args['--rows'])):
    root.rowconfigure(i, weight=1)
    for j in range(int(args['--cols'])):
        root.columnconfigure(j, weight=1)
        viewer = TelescopeEventView(root, LST, cmap='hot')
        viewer.grid(row=i, column=j, sticky='nswe')
        viewers.append(viewer)

viewers = cycle(viewers)
root.bind('<<new_event>>', handle_new_event)

if __name__ == '__main__':
    try:
        reader.start()
        root.after(1, check_queue)
        root.mainloop()
    except (SystemExit, KeyboardInterrupt):
        pass
    stop_event.set()


import argparse
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from IPython import embed

from sklearn_lvq import GrlvqModel, GmlvqModel
from sklearn_lvq.utils import plot2d
from sklearn.preprocessing import LabelEncoder
from tqdm.auto import tqdm

from transformers import RobertaTokenizer, RobertaModel
import torch

tokenizer = RobertaTokenizer.from_pretrained("roberta-base")

model = RobertaModel.from_pretrained("roberta-base")

def get_embeddings(text: str, tokenizer: RobertaTokenizer, model: RobertaModel) -> np.array:
    inputs = tokenizer(text, return_tensors="pt")
    outputs = model(**inputs)
    pooled_output = outputs.pooler_output.detach().cpu().numpy()
    return pooled_output

def create_dataset(csv_file: str, cap=100):
    df = pd.read_csv(csv_file)
    # df = df[df['updated_label'].isin(['ad populum', 'ad hominem'])]
    texts = df['masked_articles'].tolist()
    labels = df['updated_label'].tolist()

    embeddings = []
    for text in tqdm(texts, leave=False):
        embeddings.append(get_embeddings(text, tokenizer, model))
    return np.array(embeddings), np.array(labels)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--input_file", type=str, default="edu_train.csv")

    args = parser.parse_args()

    embeddings, labels = create_dataset(args.input_file)
    embeddings = embeddings.squeeze(axis=1)

    label_encoder = LabelEncoder()
    label_encoder.fit(labels)

    labels_encoded = label_encoder.transform(labels).reshape(-1, 1)

    print('GMLVQ:')

    gmlvq = GmlvqModel()
    gmlvq.fit(embeddings, labels)
    plot2d(gmlvq, embeddings, labels, 1, 'gmlvq')

    print('classification accuracy:', gmlvq.score(embeddings, labels))
    plt.show()

    embed()
    exit()


import pygame
from random import randint

class Card(pygame.sprite.Sprite):
    """Class Card

    Attributes:
        image (pygame.Surface): The image/sprite for your card
        ih (int): How tall your card is (in px)
        iw (int): How wide your card is (in px)

        hm (int):
        mm (int):
        lm (int):
        am (int):

        name (str):
        desc (str):

    """
    def __init__(self, image, ih, iw):
        super(Card, self).__init__()

        self.image = pygame.image.load(image)
        self.image = pygame.transform.scale(self.image, (iw, ih))
        self.rect = self.image.get_rect()

        # Sets stats to random values between -5 and 5
        self.hm = randint(-5, 5)
        self.mm = randint(-5, 5)
        self.lm = randint(-5, 5)
        self.am = randint(-5, 5)
        self.__randomizer()

        # Initializes the title of the card and its description
        self.name = " the "
        self.desc = ""
        self.__name_desc()

    # Corrects any invalid stat totals (all variables must add to 0)
    def __randomizer(self):
        total = self.hm + self.mm + self.lm + self.am
        args = [self.hm, self.mm, self.lm, self.am]
        while total != 0:
            random = randint(0, 3)
            if 5 > args[random] > -5:
                if total > 0:
                    if random == 0:
                        self.hm -= 1
                    if random == 1:
                        self.mm -= 1
                    if random == 2:
                        self.lm -= 1
                    if random == 3:
                        self.am -= 1
                    args[random] -= 1
                    total -= 1
                if total < 0:
                    if random == 0:
                        self.hm += 1
                    if random == 1:
                        self.mm += 1
                    if random == 2:
                        self.lm += 1
                    if random == 3:
                        self.am += 1
                    args[random] += 1
                    total += 1

    # Sets the title of the card and its description
    def __name_desc(self):
        args = [self.hm, self.mm, self.lm, self.am]
        args.sort(reverse=True)
        if args[0] == 0:
            self.name += "Balanced"
            self.desc += "All stats equal"
        elif args[0] > 3:
            if args[0] == self.hm:
                self.name += "Steadfast"
                self.desc += "Substantial increase in health"
            if args[0] == self.mm:
                self.name += "Swift"
                self.desc += "Substantial increase in speed"
            if args[0] == self.lm:
                self.name += "Favored"
                self.desc += "Substantial increase in luck"
            if args[0] == self.am:
                self.name += "Merciless"
                self.desc += "Substantial increase in attack"
        else:
            if args[0] == self.hm:
                if args[1] == self.mm:
                    self.name += "Resilient"
                    self.desc += "Moderate increase in health and speed"
                if args[1] == self.lm:
                    self.name += "Gifted"
                    self.desc += "Moderate increase in health and luck"
                if args[1] == self.am:
                    self.name += "Barbarous"
                    self.desc += "Moderate increase in health and attack"
            if args[0] == self.mm:
                if args[1] == self.hm:
                    self.name += "Resilient"
                    self.desc += "Moderate increase in health and speed"
                if args[1] == self.lm:
                    self.name += "Nimble"
                    self.desc += "Moderate increase in speed and luck"
                if args[1] == self.am:
                    self.name += "Rutheless"
                    self.desc += "Moderate increase in speed and attack"
            if args[0] == self.lm:
                if args[1] == self.hm:
                    self.name += "Gifted"
                    self.desc += "Moderate increase in health and luck"
                if args[1] == self.mm:
                    self.name += "Nimble"
                    self.desc += "Moderate increase in speed and luck"
                if args[1] == self.am:
                    self.name += "Calculated"
                    self.desc += "Moderate increase in luck and attack"
            if args[0] == self.am:
                if args[1] == self.hm:
                    self.name += "Barbarous"
                    self.desc += "Moderate increase in health and attack"
                if args[1] == self.mm:
                    self.name += "Ruthless"
                    self.desc += "Moderate increase in speed and attack"
                if args[1] == self.lm:
                    self.name += "Calculated"
                    self.desc += "Moderate increase in luck and attack"

    def get_stats(self) -> tuple:
        """Wrap up the stats of the card and return
        Used by `Entity` class in *entity.entity.py*

        Returns:
            tuple: the packaged stats of the card

        """
        return tuple([self.hm, self.mm, self.lm, self.am])


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from linearRegression.linearRegression import LinearRegression
import torch
torch.manual_seed(10)

x = np.array([i*np.pi/180 for i in range(60,300,4)]).reshape(-1,1)
np.random.seed(10)  #Setting seed for reproducibility
y = 4*x**2 + 7 + np.random.normal(0,3,len(x)).reshape(-1,1)

'''
lr = LinearRegression()
lr.fit_normal(x.reshape(1,-1),y)
y_hat = lr.predict(x.reshape(-1,1))
plt.plot(x, y, 'ro')
plt.plot(x, y_hat, 'b')

plt.show()
'''

lr = 0.01

coef = np.random.uniform(0, 5, size=[x.shape[1]+1,1])
loss_prev = np.inf

x = np.concatenate((np.ones((x.shape[0],1)),x),axis=1)
for i in range(10):
  plt.figure(figsize=(10,10))
  plt.plot(x[:, 1:], y, 'ro')
  y_pred = np.dot(x,coef)
  D = (2/x.shape[0]) * np.sum(np.dot(x.T, y_pred - y))
  loss = np.sum(np.square(y_pred - y))
  if np.abs(loss_prev - loss) < 0.0001:
    print(i, 'Converged')
    break
  if loss_prev == np.inf:
    loss_prev = loss
  coef = coef - lr * D
  loss_prev = loss
  plt.plot(x[:, 1:], y_pred, label = 'Loss: ' + str(np.sqrt(loss)))
  plt.legend()
  plt.title('Iteration: ' + str(i))
  plt.savefig('lr_'+str(i)+'.png')


import sublime

import sys
import threading

import hashlib

# Helper module
try:
    from .helper import H
except:
    from helper import H

# Settings variables
try:
    from . import settings as S
except:
    import settings as S

# DBGp protocol constants
try:
    from . import dbgp
except:
    import dbgp

try:
    from . import grld
except:
    import grld

# Config module
from .config import get_value

# Log module
from .log import debug, info

# Protocol module
from .protocol import ProtocolConnectionException

# Util module
from .util import get_real_path

# View module
from .view import DATA_CONTEXT, DATA_STACK, DATA_WATCH, DATA_COROUTINES, DATA_EVALUATE, TITLE_WINDOW_WATCH, generate_context_output, generate_stack_output, generate_coroutines_output, has_debug_view, render_regions, show_content, show_file, show_panel_content

ACTION_BREAK = "action_break"
ACTION_EVALUATE = "action_evaluate"
ACTION_EXECUTE = "action_execute"
ACTION_INIT = "action_init"
ACTION_REMOVE_BREAKPOINT = "action_remove_breakpoint"
ACTION_SET_BREAKPOINT = "action_set_breakpoint"
ACTION_STATUS = "action_status"
ACTION_USER_EXECUTE = "action_user_execute"
ACTION_WATCH = "action_watch"
ACTION_SET_CURRENT_STACK_LEVEL = "action_set_current_stack_level"
ACTION_SET_SELECTED_THREAD = "action_set_selected_thread"

def is_connected(show_status=False):
    """
    Check if client is connected to debugger engine.

    Keyword arguments:
    show_status -- Show message why client is not connected in status bar.
    """
    if S.PROTOCOL and S.PROTOCOL.connected:
        return True
    elif S.PROTOCOL and show_status:
        sublime.status_message('GRLD: Waiting for response from debugger engine.')
    elif show_status:
        sublime.status_message('GRLD: No GRLD session running.')
    return False

def is_execution_broken():
    return S.BREAKPOINT_ROW or S.BREAKPOINT_EXCEPTION

def connection_error(exception):
    """
    Template for showing error message on connection error/loss.

    Keyword arguments:
    message -- Exception/reason of connection error/loss.
    """
    info("Connection lost with debugger engine.")
    debug(message)
    # Reset connection

    with S.PROTOCOL as protocol:
        protocol.disconnect(exception)
        #protocol.clear()

    # Render breakpoint markers
    #render_regions()

def update_socket_loop():
    if not S.PROTOCOL:
        return

    try:
        with S.PROTOCOL as protocol:
            protocol.update()
    except ProtocolConnectionException as e:
        protocol.disconnect(e)
        return

    sublime.set_timeout(lambda: sublime.status_message('GRLD: Connected'), 0)
    sublime.set_timeout_async(update_socket_loop, 100)

class SocketHandler(threading.Thread):
    def __init__(self, action, **options):
        threading.Thread.__init__(self)
        self.action = action
        self.options = options
        self.current_thread = 'current' # thread currently running in Lua (since the last time execution stopped)
        self.selected_thread = 'current' # selected thread from UI
        self.current_stack_level = 1

    def get_option(self, option, default_value=None):
        if option in self.options.keys():
            return self.options[option]
        return default_value

    def run_command(self, command, args=None):
        if not isinstance(args, dict):
            args = {}
        self.timeout(lambda: self._run_command(command, args))

    def _run_command(self, command, args=None):
        try:
            sublime.active_window().run_command(command, args)
        except:
            # In case active_window() is not available
            pass

    def run_view_command(self, command, args=None):
        if not isinstance(args, dict):
            args = {}
        self.timeout(lambda: self._run_view_command)

    def _run_view_command(self, command, args=None):
        try:
            sublime.active_window().active_view().run_command(command, args)
        except:
            # In case there is no active_view() available
            pass

    def status_message(self, message):
        sublime.set_timeout(lambda: sublime.status_message(message), 100)

    def timeout(self, function):
        sublime.set_timeout(function, 0)

    def run(self):
        # Make sure an action is defined
        if not self.action:
            return
        try:
            S.SESSION_BUSY = True
            # Evaluate
            if self.action == ACTION_BREAK:
                self.execute_break()
            elif self.action == ACTION_EVALUATE:
                self.evaluate(self.get_option('expression'), self.get_option('view'))
            # Execute
            elif self.action == ACTION_EXECUTE:
                self.execute(self.get_option('command'))
            # Init
            elif self.action == ACTION_INIT:
                self.init()
            # Remove breakpoint
            elif self.action == ACTION_REMOVE_BREAKPOINT:
                self.remove_breakpoint(self.get_option('filename'), self.get_option('lineno'))
            # Set breakpoint
            elif self.action == ACTION_SET_BREAKPOINT:
                # TODO: support conditional bps
                active = True # self.get_option('expression')
                self.set_breakpoint(self.get_option('filename'), self.get_option('lineno'), active)
            # Status
            elif self.action == ACTION_STATUS:
                self.status()
            # User defined execute
            elif self.action == ACTION_USER_EXECUTE:
                self.user_execute(self.get_option('command'), self.get_option('args'))
            # Watch expression
            elif self.action == ACTION_WATCH:
                self.watch_expression()
            elif self.action == ACTION_SET_CURRENT_STACK_LEVEL:
                self.set_current_stack_level(self.get_option('stack_level'))
                pass
            elif self.action == ACTION_SET_SELECTED_THREAD :
                self.set_current_stack_level(self.get_option('selected_thread'))
                pass
        # Show dialog on connection error
        except ProtocolConnectionException as e:
            self.timeout(lambda: connection_error(e))
        finally:
            S.SESSION_BUSY = False

    def execute_break(self):
        with S.PROTOCOL as protocol:
            protocol.send('break', 'running')

    def evaluate(self, expression, view):
        if not expression or not is_connected():
            return
        # Send 'eval' command to debugger engine with code to evaluate
        response = self.evaluate_expression(expression, self.current_thread, self.current_stack_level)

        transformed_response = self.transform_grld_eval_response(response)
        response_str = generate_context_output(transformed_response, values_only=True, multiline=False)

        self.timeout(lambda: view.run_command('grld_update_evaluate_line_response', {'response': response_str}))

    def execute(self, command):
        # Do not execute if no command is set
        if not command or not is_connected():
            return

        # Reset previous breakpoint values
        S.BREAKPOINT_EXCEPTION = None
        S.BREAKPOINT_ROW = None
        S.CONTEXT_DATA.clear()
        self.watch_expression()

        # Send command to debugger engine
        with S.PROTOCOL as protocol:
            protocol.send(command)

        if command == grld.RUN:
            self.run_command('grld_layout')

        #self.timeout(lambda: render_regions())

    def get_value(self, grld_id):
        with S.PROTOCOL as protocol:
            protocol.send('getValue')
            protocol.send(grld_id)
            response = protocol.read()

        return response

    def is_table(self, variable):
        if type(variable) != dict: return False
        if 'value' not in variable: return False
        value = variable['value']
        if type(value) != dict: return False
        if 'type' not in value: return False

        return value['type'] == 'table'

    def transform_grld_table(self, table_variable, parent_table_refs):
        name = table_variable['name']
        table_values = table_variable['value']
        table_ref = table_values['short']
        id = table_values['id']
        type = table_values['type']
        assert type == 'table', "table_variable passed to transform_grld_table must of type 'table'"

        parent_table_refs.append(table_ref)

        table_children = self.get_value(id)
        transformed_children = {}
        for i, child in table_children.items():

            if self.is_table(child):
                child_table_ref = child['value']['short']
                if child_table_ref in parent_table_refs: # special value if table child is a reference to the table itself (avoid infinite recursion)
                    idx = parent_table_refs.index(child_table_ref)
                    num_tables_up_from_child = len(parent_table_refs) - idx - 1
                    if num_tables_up_from_child == 0:
                        description = '<circular reference to this table>'
                    else:
                        description = '<circular reference to a parent table {} levels up>'.format(num_tables_up_from_child)

                    transformed_children[i] =  {'name': child['name'], 'type':'table-ref', 'value': description}
                else:
                    transformed_children[i] = self.transform_grld_variable(child, parent_table_refs)
            else:
                transformed_children[i] = self.transform_grld_variable(child, parent_table_refs)

        return {'name': name, 'type': type, 'value': table_ref, 'numchildren': len(transformed_children.keys()), 'children': transformed_children}

    def transform_grld_variable(self, variable, parent_table_refs=None):
        name = variable['name']

        # if nothing is returned, GRLD returns {name = '<no result'>}
        if not 'value' in variable:
            return {'name': '', 'value': name, 'type': ''}

        if self.is_table(variable):
            return self.transform_grld_table(variable, parent_table_refs or []) #handle tables separately

        value = variable['value']
        if type(value) == dict:
            value_type = value['type']
            value = value['short']
        else:
            if type(value) == bool:
                value_type = 'boolean'
            elif type(value) == int or type(value) == float:
                value_type = 'number'
            elif type(value) == str:
                value_type = 'string'
            else:
                value_type = '?'

        return {'name': name, 'value': str(value), 'type': value_type}

    def transform_grld_eval_response(self, eval_response, scope=None):
        transformed = {}
        for i, var in eval_response.items():
            transformed_item = self.transform_grld_variable(var)

            if scope:
                name = "(%s) %s" % (scope, transformed_item['name'])
                transformed_item['name'] = name
            else:
                name = transformed_item['name']

            transformed[i] = transformed_item

        return transformed

    def transform_grld_context_response(self, context_response, scope):
        return self.transform_grld_eval_response(context_response, scope)

    def get_context_values(self, thread, stack_level):
        """
        Get variables in current context.
        """
        if not is_connected():
            return

        context = H.new_dictionary()
        try:
            # local variables
            #if get_value(S.KEY_SUPER_GLOBALS):
            with S.PROTOCOL as protocol:
                protocol.send("locals")
                protocol.send(thread)
                protocol.send(stack_level)
                response = protocol.read()
                properties = self.transform_grld_context_response(response, "local")
                context.update(properties)

                # upvalues
                protocol.send("upvalues")
                protocol.send(thread)
                protocol.send(stack_level)
                response = protocol.read()
                properties = self.transform_grld_context_response(response, "upvalue")
                context.update(properties)
        except ProtocolConnectionException as e:
            self.timeout(lambda: connection_error(e))

        # Store context variables in session
        S.CONTEXT_DATA = context

        return generate_context_output(context)

    def get_stack_values(self):
        """
        Get stack information for current context.
        """
        response = None
        if is_connected():
            try:
                with S.PROTOCOL as protocol:
                    # Get stack information
                    protocol.send("callstack")
                    protocol.send(self.current_thread)
                    response = protocol.read()
            except ProtocolConnectionException as e:
                self.timeout(lambda: connection_error(e))

        #response should be something like: {"1": {"name": <name of thing>, "namewhat": (global|local|method|field|''), "what": (Lua, C, main), "source": @<filename>, "line": line in file}}
        return response

    def evaluate_expression(self, expression, thread, stack_level):
        try:
            with S.PROTOCOL as protocol:
                protocol.send('evaluate')
                protocol.send('=' + expression) #TODO: should we always add '='?
                protocol.send(thread)
                protocol.send(stack_level)

                response = protocol.read()
        except ProtocolConnectionException as e:
            self.timeout(lambda: connection_error(e))

        return response

    def get_watch_values(self, thread, stack_level):
        """
        Evaluate all watch expressions in current context.
        """

        for index, item in enumerate(S.WATCH):
            # Reset value for watch expression
            S.WATCH[index]['value'] = None

            # Evaluate watch expression when connected to debugger engine
            if is_connected():
                if item['enabled']:
                    watch_value = self.evaluate_expression(item['expression'], thread, stack_level)

                    S.WATCH[index]['value'] = self.transform_grld_eval_response(watch_value)

    def init(self):
        if not is_connected():
            return

        with S.PROTOCOL as protocol:
            protocol.register_command_cb('break', (lambda filename, line: self.handle_break_command(filename, line)))
            protocol.register_command_cb('synchronize', (lambda: self.handle_synchronize_command()))
            # Connection initialization
            client_name = protocol.read()

            # # Set breakpoints for files
            for filename, breakpoint_data in S.BREAKPOINT.items():
                if breakpoint_data:
                    for lineno, bp in breakpoint_data.items():
                        if bp['enabled']:
                            # TODO: support conditional bps
                            active = True #bp['expression']
                            self.set_breakpoint(filename, lineno, active)
                            debug('breakpoint_set: ' + filename + ':' + lineno)

            if get_value(S.KEY_BREAK_ON_START):
                protocol.send("break", "running")

        update_socket_loop()

        #self.timeout(lambda: render_regions())

    def remove_breakpoint(self, filename, lineno):
        if not is_connected():
            return

        self.set_breakpoint(filename, lineno, False)

    def set_breakpoint(self, filename, lineno, active=True):
        if not filename or not lineno or not is_connected():
            return

        with S.PROTOCOL as protocol:
            # Get path of file on server
            fileuri = get_real_path(filename, True)
            # Set breakpoint
            protocol.send("setbreakpoint", "running")
            protocol.send({"source": fileuri, "line": int(lineno), "value": active}, "running")

        #self.timeout(lambda: render_regions())

    def set_exception(self, exception):
        if not is_connected():
            return

        with S.PROTOCOL as protocol:
            protocol.send(dbgp.BREAKPOINT_SET, t='exception', x='"%s"' % exception)
            response = protocol.read()

    def status(self):
        raise NotImplementedError('status is not implemented yet')
        #if not is_connected():
        #    return

        #with S.PROTOCOL as protocol:
        #    # Send 'status' command to debugger engine
        #    protocol.send(dbgp.STATUS)
        #    response = protocol.read()

        ## Show response in status bar
        #self.status_message("GRLD status: " + response.get(dbgp.ATTRIBUTE_REASON) + ' - ' + response.get(dbgp.ATTRIBUTE_STATUS))

    def user_execute(self, command, args=None):
        if not command or not is_connected():
            return

        with S.PROTOCOL as protocol:
            # Send command to debugger engine
            protocol.send(command, args)
            response = protocol.read(return_string=True)

        # Show response data in output panel
        self.timeout(lambda: show_panel_content(response))

    def watch_expression(self, thread=None, stack_level=None):
        if not thread:
            thread = self.current_thread

        if not stack_level:
            stack_level = self.current_stack_level

        # Evaluate watch expressions
        self.get_watch_values(thread, stack_level)
        # Show watch expression
        self.timeout(lambda: self._watch_expression(self.get_option('check_watch_view', False)))

    def _watch_expression(self, check_watch_view):
        # Do not show if we only want to show content when Watch view is not available
        if check_watch_view and not has_debug_view(TITLE_WINDOW_WATCH):
            return

        show_content(DATA_WATCH)

        #self.timeout(lambda: render_regions())

    def set_current_stack_level(self, stack_level):
        self.current_stack_level = stack_level

    def set_selected_thread(self, selected_thread):
        self.selected_thread = selected_thread

    def get_all_coroutines(self):
        with S.PROTOCOL as protocol:
            protocol.send('coroutines')
            response = protocol.read()

        count = len(response.keys())
        response[count + 1] = {'id': 'main'} # always include a 'main' coroutine. This is how GRLD references the main Lua thread.

        return response

    def update_current_thread(self, coroutines_dict):
        with S.PROTOCOL as protocol:
            protocol.send('currentthread')
            current_thread = protocol.read()

        # GRLD only passes back co-routines that are NOT 'main'. So, if current_thread is not in the list, then 'main' is the current thread.
        coroutine_ids = (coroutine_descriptor['id'] for coroutine_descriptor in coroutines_dict.values())
        if current_thread not in coroutine_ids:
            current_thread = 'main'

        self.current_thread = current_thread

    def update_contextual_data(self, thread, stack_level):
        # Context variables
        context = self.get_context_values(thread, stack_level)
        self.timeout(lambda: show_content(DATA_CONTEXT, context))

        # Watch expressions
        self.watch_expression(thread, stack_level)

        # Render breakpoint markers
        #self.timeout(lambda: render_regions())

    def handle_break_command(self, filename, line):
        S.SESSION_BUSY = True
        filename = get_real_path(filename)

        # Show debug/status output
        self.status_message('GRLD: Break')
        info('Break: ' + filename )
        # Store line number of breakpoint for displaying region marker
        S.BREAKPOINT_ROW = { 'filename': filename, 'lineno': str(line) }

        # Focus/Open file window view
        self.timeout(lambda: show_file(filename, line))

        coroutines_dict = self.get_all_coroutines()

        self.update_current_thread(coroutines_dict)

        coroutines_str = generate_coroutines_output(coroutines_dict, self.current_thread)
        self.timeout(lambda: show_content(DATA_COROUTINES, coroutines_str))

        # Stack history
        stack = self.get_stack_values()
        if stack:
            stack_levels = [int(level) for level in stack.keys()]
            min_stack_level =  min(stack_levels)
            self.current_stack_level = min_stack_level
            stack_str = generate_stack_output(stack)
        else:
            stack_str = H.unicode_string('[{level}] {filename}.{where}:{lineno}\n' \
                                        .format(level=0, where='{main}', lineno=1, filename=fileuri))

        self.timeout(lambda: show_content(DATA_STACK, stack_str))

        self.update_contextual_data(self.current_thread, self.current_stack_level)

        #self.timeout(lambda: render_regions())

        S.SESSION_BUSY = False

    def handle_synchronize_command(self):
        S.SESSION_BUSY = True

        with S.PROTOCOL as protocol:
            # synchronize expects us to return the # of active breakpoints (this is actually not implemented, we MUST return 0 here)
            protocol.send(0)

            # next we need to send the "breakOnConnection" value, this is configurable, but we'll just always return false for now
            protocol.send(False)

        S.SESSION_BUSY = False

class SessionException(Exception):
    pass


# 100/100 in Judge

from collections import deque

ducks_dict = {
    "Darth Vader Ducky": {"Requirements": [0, 60], "Given_Away": 0},
    "Thor Ducky": {"Requirements": [61, 120], "Given_Away": 0},
    "Big Blue Rubber Ducky": {"Requirements": [121, 180], "Given_Away": 0},
    "Small Yellow Rubber Ducky": {"Requirements": [181, 240], "Given_Away": 0}
}

programmers_single_task_time_completion = deque([int(x) for x in input().split()])
number_of_tasks = [int(x) for x in input().split()]
ducks_max_value = 240

while programmers_single_task_time_completion and number_of_tasks:
    current_programmer_time = programmers_single_task_time_completion[0]
    current_tasks = number_of_tasks[-1]
    current_calculation = current_programmer_time * current_tasks
    if current_calculation > ducks_max_value:
        programmers_single_task_time_completion.append(programmers_single_task_time_completion.popleft())
        number_of_tasks[-1] -= 2
    else:
        for duck, duck_info in ducks_dict.items():
            duck_matched = False
            min_range_duck = duck_info["Requirements"][0]
            max_range_duck = duck_info["Requirements"][1]

            if min_range_duck <= current_calculation <= max_range_duck:
                duck_info["Given_Away"] += 1
                programmers_single_task_time_completion.popleft()
                number_of_tasks.pop()
                break
else:
    print(f"Congratulations, all tasks have been completed! Rubber ducks rewarded:")
    for duck, duck_info in ducks_dict.items():
        print(f"{duck}: {duck_info['Given_Away']}")

# ###################################################
# Test_Code_1:
# 10 15 12 18 22 6
# 12 16 5 6 9 1
# ---------------------------------------------------
# Output_1:
# Congratulations, all tasks have been completed! Rubber ducks rewarded:
# Darth Vader Ducky: 1
# Thor Ducky: 3
# Big Blue Rubber Ducky: 1
# Small Yellow Rubber Ducky: 1
# ###################################################

02. Python_Advanced_Jan2023/12. Retake/01. Rubber_Duck_Debuggers_v1.py


import pymongo
from bson.son import SON
import pprint

client = pymongo.MongoClient('mongodb://localhost:27017')
db = client.cmc

raw_data = db.raw_data
entities = db.entities

ids = []

for row in raw_data.find({}, { 'id': 1 }):
    try:
        ids.index(int(row['id']))
    except:
        ids.append(int(row['id']))

for entity_id in sorted(ids):
    first = raw_data.find_one({ 'id': str(entity_id) })

    entity = {
        'id': entity_id,
        'nome': first['nome'],
        'cargo': first['cargo'],
        'grupo': first['grupo']
    }

    docs = raw_data.find(
                { 'id': str(entity_id) },
                {'id': 0, 'grupo': 0, 'nome': 0, 'cargo': 0, '_id': 0}
            ).sort('mesano')

    for doc in docs:
        mesano = doc['mesano']
        entity[mesano] = {}

        for field in doc:
            if field is 'mesano':
                continue
            entity[mesano][field] = doc[field]

    entities.insert_one(entity)


import pandas as pd
import numpy as np
import robin_stocks.robinhood as robin
import yfinance as yf
import datetime as dt
import indicators
import credentials
import pyotp
import pickle
from csv import writer

companies=list(pd.read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies')[0]['Symbol'])

def trade():
  totp = pyotp.TOTP(credentials.mfa).now()
  robin.login(credentials.username, credentials.password, mfa_code = totp)
  owned = robin.build_holdings()

  start_date = '20' + (dt.datetime.now() - dt.timedelta(days = 60)).strftime(('%y-%m-%d'))
  # print(start_date)
  stoch_owned = []
  with open('stoch.pkl', 'rb') as f:
    stoch_owned = pickle.load(f)

  with open('trades.csv', 'a') as f:
    writ = writer(f)

    # bought = 0
    for i, comp in enumerate(companies):
      # print(comp)
      df = yf.download(tickers= comp, start= start_date, interval="1h", threads=False).reset_index()
      df = df[['Adj Close','High','Low','Volume']]

      indicators.RSI_Adj(df,14)
      indicators.MACD(df,12,26,9)
      indicators.Stochastic(df,14,3)
      # print(len(df))
      # print(i) if i%25 == 0 else _

      stoch_buy = False
      for index, row in df[::-1].iterrows():
        if row['%K'] < 20 and row['%D'] < 20:
          stoch_buy = True
          break
        elif row['%K'] > 80 or row['%D'] > 80:
          stoch_buy = False
          break

      last_row = df.iloc[-1]
      #print(last_row['RSI Adj'])
      if stoch_buy and last_row['RSI Adj'] > 50 and last_row['MACD'] > last_row['Signal'] and (comp not in stoch_owned):
        #buy
        cost = last_row['Adj Close']
        writ.writerow([dt.datetime.now() - dt.timedelta(hours=4), comp, 'BUY', last_row['RSI Adj'], 0, cost,'Stoch'])
        stoch_owned.append(comp)
        # print(last_row['Adj Close'])
        # print(bought)

      if last_row['RSI Adj'] < 25 and last_row['RSI Adj'] > 0.0 and (comp not in owned):

        print('Buy',comp,last_row['Adj Close'])
        bought = robin.orders.order_buy_market(comp, round(50/last_row['Adj Close'],4), timeInForce='gfd')
        print(bought,'bought',type(bought))
        if bought != None and bought != {}:
          writ.writerow([dt.datetime.now() - dt.timedelta(hours=4), comp, 'BUY',bought['quantity'], float(bought['quantity']) * last_row['Adj Close'],last_row['Adj Close'],'RSI'])

      stoch_sell = False
      for index,row in df[::-1].iterrows():
        if row['%K'] > 80 and row['%D'] > 80:
          stoch_sell = True
          break
        elif row['%K'] < 20 or row['%D'] < 20:
          stoch_sell = False
          break

      if comp in owned:
        print('In Owned', comp, last_row['RSI Adj'])

      if (comp in stoch_owned and stoch_sell and last_row['RSI Adj'] < 50 and last_row['MACD'] < last_row['Signal']):
        #sell
        cost = last_row['Adj Close']
        writ.writerow([dt.datetime.now() - dt.timedelta(hours=4), comp, 'SELL', last_row['RSI Adj'], 0, cost,'Stoch'])
        stoch_owned.remove(comp)

      if last_row['RSI Adj'] > 75 and (comp in owned):

        print('Sell',comp,last_row['Adj Close'])
        sold = robin.orders.order_sell_fractional_by_quantity(comp, owned[comp]['quantity'])
        print(sold, 'sold',type(sold))
        if sold != None and sold != {}:
          writ.writerow([dt.datetime.now() - dt.timedelta(hours=4), comp, 'SELL',sold['quantity'], float(sold['quantity']) * last_row['Adj Close'],last_row['Adj Close'],'RSI'])

    robin.logout()

  with open('stoch.pkl', 'wb') as f:
    pickle.dump(stoch_owned,f)

  f.close()


import sys
import time
import aiohttp
import asyncio
import configparser
import re
import json

IN = "input"
OUT = "output"
CONNECT = "connect"
DISCONNECT = "disconnect"
SERVERS = ['Goloman', 'Hands', 'Holiday', 'Welsh', 'Wilkes']
PROPAGATION_MAP = {
    'Goloman': ['Hands', 'Holiday', 'Wilkes'],
    'Hands': ['Goloman', 'Wilkes'],
    'Holiday': ['Goloman', 'Welsh', 'Wilkes'],
    'Welsh': ['Holiday'],
    'Wilkes': ['Goloman', 'Hands', 'Holiday']
}
SERVER_PORT_MAP = {
    'Goloman': 12777,
    'Hands': 12778,
    'Holiday': 12779,
    'Welsh': 12780,
    'Wilkes': 12781
}
SERVER_FN_MAP = {
    'Goloman': "goloman_log.txt",
    'Hands': "hands_log.txt",
    'Holiday': "holiday_log.txt",
    'Welsh': "welsh_log.txt",
    'Wilkes': "wilkes_log.txt",
}
SERVER_STATUS = {
    'Goloman': 0,
    'Hands': 0,
    'Holiday': 0,
    'Welsh': 0,
    'Wilkes': 0
}
HOST = '127.0.0.1'
server_name = ""
clients= {}
log = None

# Config file used for secret stuff like the API Key
config = configparser.ConfigParser()
config.read('config.ini')

def main():
    if len(sys.argv) != 2:
        print("Invalid number of arguments!")
        print_usage()
        exit(1)

    global server_name
    server_name = sys.argv[1]
    if server_name not in SERVERS:
        print("Invalid server name provided: {}".format(server_name))
        print_usage()
        exit(1)

    # print("\n\nStarting server: {}...\n\n".format(server_name))
    setup_log()

    loop = asyncio.get_event_loop()
    coro = asyncio.start_server(handle_event, '127.0.0.1', SERVER_PORT_MAP[server_name])
    server = loop.run_until_complete(coro)
    broadcast = loop.run_until_complete(broadcast_status())

    try:
        loop.run_forever()
    except KeyboardInterrupt:
        pass

    server.close()
    loop.run_until_complete(server.wait_closed())
    loop.close()

    # print("\n\n{} going offline\n\nDumping log...".format(server_name))
    # dump_log()
    log.close()

async def broadcast_status():
    for s in PROPAGATION_MAP[server_name]:
        if s == server_name:
            continue
        try:
            r, w = await asyncio.open_connection(HOST, SERVER_PORT_MAP[s])
            if SERVER_STATUS[s] == 0:
                SERVER_STATUS[s] = 1
                log_message(CONNECT, f"Connection established to {s}")
            m = f"ONLINE {server_name}"
            w.write(m.encode())
            await w.drain()
            # print("Closing client socket")
            w.close()
        except:
            # print(f"Got no response from {s}")
            if SERVER_STATUS[s] == 1:
                SERVER_STATUS[s] = 0
            log_message(DISCONNECT, f"Failed to connect to {s}")
            pass

async def handle_event(reader, writer):
    data = await reader.read()
    message = data.decode()
    addr = writer.get_extra_info('peername')
    # print(f"Receieved {message} from {addr}")

    async with aiohttp.ClientSession() as session:
        await handle_message(message, addr, writer, session)
        # print(f"---\nDone processing. New clients: {clients}\n---")

# Processes a message m received presumably from an async event.
# TODO field validation
async def handle_message(m, source, writer, session):
    connection = source
    log_message(IN, m, connection)
    t_received = time.time()

    if m.startswith('IAMAT '):
        await handle_client_location(m, t_received, source, writer)
    elif m.startswith('WHATSAT '):
        await handle_client_query(m, source, session, writer)
    elif m.startswith('AT '):
        await handle_propagation(m)
    elif m.startswith('ONLINE'):
        handle_server_status(m)
    else:
        # print("\nUnknown message received: ", m)
        await send_message(f"? {m}", [source], writer)

def handle_server_status(m):
    log_message(CONNECT, f"Connection established to {m.split()[1]}")

# Process a client IAMAT location message m
async def handle_client_location(m, t, source, writer):
    m = m.strip()
    # print("\nReceived location message: ", m)
    m_parse = m.split()

    if len(m_parse) != 4:
        await send_message(f"? {m}", [source], writer)
        return

    client_id = m_parse[1]
    client_location = m_parse[2]
    client_timestamp = float(m_parse[3])

    t_delta = t - client_timestamp
    t_prefix = '+' if t_delta >= 0 else '-'
    t_delta_s = t_prefix + str(t_delta)

    if not is_valid_location(client_location):
        await send_message(f"? {m}", [source], writer)
        return

    store_client_data(client_id, client_location, client_timestamp, t_delta_s)
    # print(f"Storing {client_id} location: {client_location}")

    # Respond to client
    response = "AT {} {} {}".format(server_name, t_delta_s, m)
    await send_message(response, [source], writer)

    # Propagate location information
    propagate_list = \
        [SERVER_PORT_MAP[s] for s in PROPAGATION_MAP[server_name]]
    propagation = "AT {} {} {} {} {}" \
                  .format(server_name, t_delta_s, client_id,
                          client_location, client_timestamp)
    await send_message(propagation, propagate_list)

# Process client query m
async def handle_client_query(m, source, session, writer):
    m = m.strip()
    # print("\nReceived query: ", m)
    m_parse = m.split()

    if len(m_parse) != 4:
        await send_message(f"? {m}", [source], writer)
        return

    target_client = m_parse[1]
    radius = m_parse[2]
    max_results = m_parse[3]

    client_data = get_client_data(target_client)
    if not client_data:
        # print(f"No client data for {target_client}")
        await send_message(f"? {m}", [source], writer)
        return

    try:
        lat, long = re.findall("[+-]{1}[0-9]+[.]*[0-9]+",
                    client_data['location'])
    except:
        await send_message(f"? {m}", [source], writer)
        return

    gcpapi_res = await nearby_search(f"{lat},{long}", int(radius),
                              int(max_results), session)

    if not gcpapi_res:
        await send_message(f"? {m}", [source], writer)
        return

    # Trim results to maximum
    results = gcpapi_res['results']
    gcpapi_res['results'] = results[0:min(int(max_results), len(results))]

    formatted_gcpapi_response = json.dumps(gcpapi_res, indent=4) + '\n'
    message_to_client = "AT {} {} {} {} {}\n{}" \
                        .format(client_data['server'], client_data['timedelta'],
                                target_client, client_data['location'],
                                client_data['timestamp'], formatted_gcpapi_response)
    await send_message(message_to_client, [source], writer)

# Makes REST GET call to Google Places API nearby search
async def nearby_search(location, radius, max_count, session):
    output = "json"
    key = config['KEYS']['places_api_key']
    if radius < 0 or radius > 50 or max_count > 20 or max_count < 0:
        return None
    get_request = \
        "https://maps.googleapis.com/maps/api/place/nearbysearch/{}?key={}&location={}&radius={}" \
        .format(output, key, location, radius)
    return await fetch(session, get_request)

# Process propagation flood message m. Propagation messages should have form:
# AT [server] [timedelta] [client id] [location] [timestamp]
async def handle_propagation(m):
    m = m.strip()
    # print("Flood message received: ", m)
    m_parse = m.split()

    if len(m_parse) != 6:
        # print("Invalid format for propagation message: too many entries.")
        return

    server = m_parse[1]
    timedelta = m_parse[2]
    client_id = m_parse[3]
    client_location = m_parse[4]
    timestamp = float(m_parse[5])

    # Check to see if we already have the latest client update
    last_client_report = get_client_data(client_id)
    if last_client_report and last_client_report['timestamp'] == timestamp:
        # print(f"{client_id} location already updated... ignoring")
        return

    # Otherwise store new data and propagate
    store_client_data(client_id, client_location, timestamp, timedelta, server)
    # print(f"Storing {client_id} location: {client_location}")
    propagate_list = \
        [SERVER_PORT_MAP[s] for s in PROPAGATION_MAP[server_name]]
    # print(f"Propagation list: {propagate_list}")
    await send_message(m, propagate_list)

# Store reported client location
def store_client_data(c_id, location, timestamp, timedelta, server=None):
    if not server:
        server = server_name

    clients[c_id] = {
        "server": server,
        "location": location,
        "timestamp": timestamp,
        "timedelta": timedelta
    }

# Given the client id c, return the location of that client
def get_client_data(c):
    if c in clients:
        return clients[c]
    else:
        return None

def is_valid_location(l):
    return len(re.findall("[+-]{1}[0-9]+[.]*[0-9]+", l)) == 2

# Send TCP message to another server or client. Sends to all nodes indicated by
# id in list d. Write using writer w
async def send_message(m, d, w=None):
    open_connection_flag = False if w else True
    for target in d:
        try:
          if open_connection_flag:
              # print(f"Opening connection to HOST: {HOST}, a: {target}")
              r, w = await asyncio.open_connection(HOST, target)
          log_message(OUT, m, target)
          # print("\n{} sending message to {}: \n{}"
                # .format(server_name, target, m))
          w.write(m.encode())
          await w.drain()
          # print("Closing client socket")
          w.close()
        except:
          log_message(DISCONNECT, f"Failed to connect to {target}")

# Setup log
def setup_log():
  global log
  log = open(SERVER_FN_MAP[server_name], "w+")

# Save a message into the server log
def log_message(m_type, m, connection=""):
    if m_type == IN:
        prefix = "<<<"
    elif m_type == OUT:
        prefix = ">>>"
    elif m_type == CONNECT:
        prefix = "***"
    elif m_type == DISCONNECT:
        prefix = "!!!"
    else:
        prefix = "INVALID_LOG_REQUEST"

    to_log = "{} {} {}\n".format(prefix, connection, m)

    # TODO: batch write LOG to a file at some point
    log.write(to_log)
    log.flush()

# Print log contents to console
def dump_log():
    for _ in log: print(_)
    print()

async def run_tests(session):
    print("Running tests...")

    # IAMAT valid
    await handle_message("IAMAT kiwi.cs.ucla.edu +34.068930-118.445127 1520023934.918963997", "fake.source.com", session)
    # IAMAT valid with weird spaces
    await handle_message("IAMAT   kiwi.cs.ucla.edu    +34.068930-118.445127     1520023934.918963997", "fake.source.com", session)
    # Invalid IAMAT: too many entries
    await handle_message("IAMAT kiwi.cs.ucla.edu +34.068930-118.445127 1520023934.918963997 extraextra", "fake.source.com", session)
    # Invalid IAMAT: bad location
    await handle_message("IAMAT kiwi.cs.ucla.edu +34.068930118.445127 1520023934.918963997", "fake.source.com", session)

    # WHATSAT valid
    await handle_message("WHATSAT kiwi.cs.ucla.edu 10 1", "fake.source.com", session)

    # WHATSAT invalid radius
    await handle_message("WHATSAT kiwi.cs.ucla.edu 10000 5", "fake.source.com", session)
    await handle_message("WHATSAT kiwi.cs.ucla.edu -1 5", "fake.source.com", session)

    # WHATSAT invalid maxcount
    await handle_message("WHATSAT kiwi.cs.ucla.edu 10 50", "fake.source.com", session)
    await handle_message("WHATSAT kiwi.cs.ucla.edu 10 -1", "fake.source.com", session)

    # Propagation message valid
    await handle_message("AT kiwi.cs.ucla.edu +34.068930-118.445127 1520023934.918963997", "fake.source.com", session)

    # Propagation message entry count different
    await handle_message("AT +34.068930-118.445127 1520023934.918963997", "fake.source.com", session)

    # Unrecognized command
    await handle_message("MUFUFU hello", "fake.source.com", session)
    print("Done!")

def print_usage():
    print("\nUsage: python server.py [server_name]")
    print("Valid server names: 'Goloman', 'Hands', 'Holiday', 'Welsh', "
          "'Wilkes'")

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.json()

def port2name(port):
    for s in SERVER_PORT_MAP.keys():
        if SERVER_PORT_MAP[s] == port:
            return s

if __name__ == "__main__":
    main()


import logging

from django.contrib.gis.db.models import PointField
from django.core.exceptions import ValidationError
from django.db import models
from phonenumber_field.modelfields import PhoneNumberField

from ..states import states
from ..utils import full_url
from .geo import ZipCode
from .user import User

logger = logging.getLogger(__name__)

class Awg(models.Model):
    class AwgType(models.TextChoices):
        SHELTER_ONLY = "SHELTER_ONLY", "Shelter only"
        FOSTER_ONLY = "FOSTER_ONLY", "Foster only"
        SHELTER_AND_FOSTER = "SHELTER_AND_FOSTER", "Both Shelter and Foster"

    class AwgStatus(models.TextChoices):
        APPLIED = "APPLIED", "Applied"
        PUBLISHED = "PUBLISHED", "Published"
        UNPUBLISHED = "UNPUBLISHED", "Unpublished"

    id = models.AutoField(primary_key=True, verbose_name="CAIM ID")
    name = models.CharField(max_length=100, verbose_name="Organization name")
    petfinder_id = models.CharField(max_length=32, blank=True, null=True, default=None)
    status = models.CharField(
        max_length=16,
        choices=AwgStatus.choices,
        default=AwgStatus.APPLIED,
        verbose_name="Listing status",
    )
    description = models.TextField(blank=True)
    awg_type = models.CharField(
        max_length=32,
        choices=AwgType.choices,
        default=None,
        blank=True,
        null=True,
        verbose_name="Organization type",
    )

    has_501c3_tax_exemption = models.BooleanField(
        default=False, verbose_name="501c3 tax exempt charity"
    )
    company_ein = models.CharField(
        max_length=16,
        blank=True,
        null=True,
        default=None,
        verbose_name="Employer Identification Number (EIN)",
    )

    workwith_dogs = models.BooleanField(default=False, verbose_name="Works with dogs?")
    workwith_cats = models.BooleanField(default=False, verbose_name="Works with cats?")
    workwith_other = models.BooleanField(
        default=False, verbose_name="Works with other animals?"
    )

    geo_location = PointField()
    zip_code = models.CharField(max_length=16, blank=True, null=True, default=None)
    city = models.CharField(max_length=32, blank=True, null=True, default=None)
    state = models.CharField(max_length=2, choices=states.items())
    is_exact_location_shown = models.BooleanField(
        default=False, verbose_name="Show exact location?"
    )
    email = models.EmailField(max_length=255, blank=True, null=True, default=None)
    phone = PhoneNumberField(blank=True, null=True, default=None)
    website_url = models.URLField(
        max_length=255, blank=True, null=True, default=None, verbose_name="Website URL"
    )
    facebook_url = models.URLField(
        max_length=255, blank=True, null=True, default=None, verbose_name="Facebook URL"
    )
    instagram_url = models.URLField(
        max_length=255,
        blank=True,
        null=True,
        default=None,
        verbose_name="Instagram URL",
    )
    twitter_url = models.URLField(
        max_length=255, blank=True, null=True, default=None, verbose_name="Twitter URL"
    )
    tiktok_url = models.URLField(
        max_length=255, blank=True, null=True, default=None, verbose_name="TikTok URL"
    )

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        try:
            zip_info = ZipCode.objects.get(zip_code=self.zip_code)
            self.geo_location = zip_info.geo_location
        except Exception:
            logger.warn("ZIP code not valid")
        super(Awg, self).save(*args, **kwargs)

    def get_absolute_url(self):
        return full_url(f"/organization/{self.id}")

    def user_is_member_of_awg(self, user):
        if not user.id:
            return False
        member = self.awgmember_set.filter(user=user).first()
        return bool(member)

    def get_permissions_for_user(self, user):
        ret = []
        if not user.id:
            return ret
        # If CAIM staff, all permissions
        if user.is_staff:
            ret.append("EDIT_PROFILE")
            ret.append("MANAGE_ANIMALS")
            ret.append("MANAGE_MEMBERS")
            ret.append("MANAGE_APPLICATIONS")
        # Look for AWGMember for this user and AWG
        member = self.awgmember_set.filter(user=user).first()
        if member:
            if member.canEditProfile:
                ret.append("EDIT_PROFILE")
            if member.canManageAnimals:
                ret.append("MANAGE_ANIMALS")
            if member.canManageMembers:
                ret.append("MANAGE_MEMBERS")
            if member.canManageApplications:
                ret.append("MANAGE_APPLICATIONS")
            if member.canViewApplications:
                ret.append("VIEW_APPLICATIONS")
        return ret

    def is_currently_published(self):
        return self.status == Awg.AwgStatus.PUBLISHED

    def clean(self):
        # Validate zip_code
        if self.zip_code:
            zip_info = ZipCode.objects.filter(zip_code=self.zip_code).first()
            if not zip_info:
                raise ValidationError({"zip_code": "Invalid US zip code"})

class AwgMember(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    awg = models.ForeignKey(Awg, on_delete=models.CASCADE)
    canEditProfile = models.BooleanField(default=False)
    canManageAnimals = models.BooleanField(default=False)
    canManageMembers = models.BooleanField(default=False)
    canManageApplications = models.BooleanField(default=False)
    canViewApplications = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = (
            "user",
            "awg",
        )

    def __str__(self) -> str:
        return f"{self.user} - {self.awg}"

    def to_dict(self):
        return {
            "id": self.id,
            "user_id": self.user_id,
            "user_email": self.user.email,
            "user_username": self.user.username,
            "awg_id": self.awg_id,
            "canEditProfile": self.canEditProfile,
            "canManageAnimals": self.canManageAnimals,
            "canManageMembers": self.canManageMembers,
            "canManageApplications": self.canManageApplications,
            "canViewApplications": self.canViewApplications,
        }


import re
import datetime
import dateutil.parser

def id_to_datetime(snowflake_id: int) -> datetime.datetime:
    """Convert snowflake ID to timestamp."""
    return datetime.datetime.fromtimestamp(
        ((snowflake_id >> 22) + 1420070400000) / 1000
    )

def format_date(timestamp: datetime.datetime) -> str:
    """Convert timestamp to date."""
    return timestamp.strftime("%Y-%m-%d")

def format_datetime(timestamp: datetime.datetime) -> str:
    """Convert timestamp to date and time."""
    return timestamp.strftime("%Y-%m-%d %H:%M:%S")

def format_seconds(time: int) -> str:
    """Convert seconds to human-readable time."""
    time = int(time)
    D = 3600 * 24
    H = 3600
    M = 60

    d = int((time - (time % D)) / D)
    h = int((time - (time % H)) / H) % 24
    m = int((time - (time % M)) / M) % 60
    s = time % 60

    if d > 0:
        return f"{d} d, {h:02}:{m:02}:{s:02}"
    if h > 0:
        return f"{h}:{m:02}:{s:02}"
    return f"{m}:{s:02}"

def parse_iso8601_datetime(string: str) -> datetime.datetime:
    """Prase ISO 8601 time string.

    Raises:
        ValueError: When the supplied string cannot be converted to datetime.
    """
    return dateutil.parser.isoparse(string)

def parse_fuzzy_datetime(
    string: str, *, relative_to: datetime.datetime = None
) -> datetime.datetime:
    """Parses datetime string and returns a datetime.

    Takes either a relative string in the #w#d#h#m format (weeks, days, hours, minutes)
    or any other format that `dateutil.parser` takes.

    `dateutil.parser` is set to `dayfirst=True` and `yearfirst=False`,
    so for ambiguous formats like 10/11/12 the resulting datetime would take
    it as day 10 of month 11 of year 2012.

    If the resulting datetime is today but the time already happened,
    it automatically adds 1 day to the datetime.
    This usually happens if `string` contains only time.

    Args:
        string: String to parse
        relative_to: Timestamp to compare relative time against

    Returns:
        datetime: resulting datetime

    Raises:
        dateutil.parser.ParserError: Raised for invalid or unknown string formats,
            if the provided tzinfo is not in a valid format, or if an invalid date
            would be created.
        OverflowError: Raised if the parsed date exceeds the largest valid C
            integer on your system.
    """
    has_relative_to: bool = True
    if relative_to is None:
        relative_to = datetime.datetime.now()
        has_relative_to = False

    regex = re.compile(
        r"(?!\s*$)(?:(?P<weeks>\d+)(?: )?(?:w)(?:\D)*)?(?:(?P<days>\d+)(?: )"
        r"?(?:d)(?:\D)*)?(?:(?P<hours>\d+)(?: )?(?:h)(?:\D)*)?(?:(?P<minutes>\d+)(?: )"
        r"?(?:m)(?:\D)*)?",
        re.IGNORECASE
    )
    result = re.fullmatch(regex, string)
    if result is not None:
        match_dict = result.groupdict(default=0)
        end_time = relative_to + datetime.timedelta(
            weeks=int(match_dict["weeks"]),
            days=int(match_dict["days"]),
            hours=int(match_dict["hours"]),
            minutes=int(match_dict["minutes"]),
        )
        return end_time

    end_time = dateutil.parser.parse(timestr=string, dayfirst=True, yearfirst=False)

    # Fix the date if `relative_to` is set; it is most likely not today
    if has_relative_to:
        end_time = end_time.replace(
            year=relative_to.year, month=relative_to.month, day=relative_to.day
        )

    # Fix the date by a day if the requested time already passed
    if end_time.date() == relative_to.date() and end_time < relative_to:
        end_time = end_time + datetime.timedelta(days=1)

    return end_time

def parse_datetime(string: str) -> datetime.datetime:
    """Attempt to parse both ISO 8601 and fuzzy formats of date."""
    try:
        return parse_iso8601_datetime(string)
    except ValueError:
        return parse_fuzzy_datetime(string)


import csv
from django.conf import settings
from django.core.management.base import BaseCommand
from core.models import STATION_LOCATION

class Command(BaseCommand):
    help = "Load data from Staion file"

    def handle(self, *args, **options):
        data_file = settings.BASE_DIR / 'data' / 'station_coordinate.csv'
        keys = ('Name', 'decimalLatitude','decimalLongitude')

        records = []
        with open(data_file, 'r', encoding="utf-8-sig") as csvfile:
            reader = csv.DictReader(csvfile)
            for row in reader:
                records.append({k: row[k] for k in keys})

        for record in records:
            STATION_LOCATION.objects.get_or_create(
                station_name=record['Name'],
                latitude=record['decimalLatitude'],
                longitude=record['decimalLongitude']
            )


#!/usr/bin/env python3

from http.server import HTTPServer, BaseHTTPRequestHandler
import json

class ServiceHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        length = int(self.headers.get('content-length'))
        body = json.loads(self.rfile.read(length))
        print(f'{body["messageId"]} {body["body"]}')
        self.wfile.write('ok'.encode())
        return

# Server Initialization
server = HTTPServer(('127.0.0.1', 8312), ServiceHandler)
server.serve_forever()


"""
A module for registering Python linting tasks.
"""

# built-in
from pathlib import Path
from typing import Dict, List

# third-party
from vcorelib.platform import is_windows
from vcorelib.task import Inbox, Outbox, Phony
from vcorelib.task.manager import TaskManager
from vcorelib.task.subprocess.run import SubprocessLogMixin

# internal
from vmklib.tasks.args import environ_fallback_split
from vmklib.tasks.python import PREFIX

class PythonLinter(SubprocessLogMixin):
    """A task for running a Python linter."""

    default_requirements = {"venv"}

    @staticmethod
    def source_args(cwd: Path, project: str, **kwargs) -> List[str]:
        """Get Python sources within a package."""

        sources = []
        if kwargs.get("python_lint_source_args", True):
            sources = [
                cwd.joinpath("tests"),
                cwd.joinpath(project),
                cwd.joinpath("setup.py"),
            ]

            # This breaks on Windows because of symbolic linking. It's okay
            # to lose the linting coverage for the not-unit-tested workflow
            # code.
            if not is_windows():
                sources.append(cwd.joinpath("tasks"))

        return list(str(x) for x in filter(lambda x: x.exists(), sources))

    async def run(self, inbox: Inbox, outbox: Outbox, *args, **kwargs) -> bool:
        """Run a Python linter."""

        cwd: Path = args[0]
        project: str = args[1]
        linter: str = kwargs.get("package", kwargs.get("linter", "UNKNOWN"))

        return await self.exec(
            str(inbox["venv"]["venv{python_version}"]["bin"].joinpath(linter)),
            *args[2:],
            # Get extra arguments from the environment.
            *environ_fallback_split(
                "PY_LINT_" + linter.upper() + "_EXTRA_ARGS", **kwargs
            ),
            *PythonLinter.source_args(cwd, project, **kwargs),
        ) or kwargs.get("ignore_errors", False)

def register(
    manager: TaskManager,
    project: str,
    cwd: Path,
    substitutions: Dict[str, str],
) -> bool:
    """Register Python linting tasks to the manager."""

    prefix = PREFIX

    # A target ensuring that linter packages are installed.
    for kind in ["install", "upgrade"]:
        manager.register(
            Phony(prefix + f"lint-{kind}"),
            [
                f"{prefix}{kind}-{x}"
                for x in ["pylint", "flake8", "black", "ruff", "mypy", "isort"]
            ],
        )

    manager.register(
        PythonLinter(prefix + "lint-{package}", cwd, project),
        [prefix + "install-{package}"],
    )

    line_length = ["--line-length", str(substitutions.get("line_length", 79))]

    isort_args = line_length + [
        "--profile",
        substitutions.get("isort_profile", "black"),
        "--fss",
        "-m",
        "3",
    ]

    manager.register(
        PythonLinter(
            prefix + "format-check-isort",
            cwd,
            project,
            "--check-only",
            *isort_args,
            linter="isort",
        ),
        [f"{prefix}install-isort"],
    )

    manager.register(
        PythonLinter(
            prefix + "format-isort",
            cwd,
            project,
            *isort_args,
            linter="isort",
        ),
        [f"{prefix}install-isort"],
    )

    manager.register(
        PythonLinter(
            prefix + "format-check-black",
            cwd,
            project,
            "--check",
            *line_length,
            linter="black",
        ),
        [f"{prefix}install-black"],
    )

    manager.register(
        PythonLinter(
            prefix + "format-black",
            cwd,
            project,
            *line_length,
            linter="black",
        ),
        # Depend on 'isort' so that we don't format multiple files at the same
        # time.
        [f"{prefix}install-black", prefix + "format-isort"],
    )

    manager.register(
        Phony(prefix + "format-check"),
        [prefix + "format-check-black", prefix + "format-check-isort"],
    )
    manager.register(
        Phony(prefix + "format"),
        # 'black' depends on 'isort' already.
        [prefix + "format-black"],
    )
    manager.register(
        Phony(prefix + "lint"),
        [
            prefix + "lint-flake8",
            prefix + "lint-pylint",
            prefix + "lint-ruff",
            prefix + "format-check",
        ],
    )

    return True


import pandas as pd

def update_embeddings(df):

    import tiktoken
    # from openai.embeddings_utils import get_embedding, cosine_similarity
    tokenizer = tiktoken.get_encoding("cl100k_base")

    df['n_tokens'] = df.texto.apply(lambda x: len(tokenizer.encode(x)))
    max_tokens = 200

    def split_into_many(text, max_tokens = max_tokens):

        # Split the text into sentences
        sentences = text.split('. ')
        # Get the number of tokens for each sentence
        n_tokens = [len(tokenizer.encode(" " + sentence)) for sentence in sentences]
        print(n_tokens)
        chunks = []
        tokens_so_far = 0
        chunk = []

        # Loop through the sentences and tokens joined together in a tuple
        for sentence, token in zip(sentences, n_tokens):

            # If the number of tokens so far plus the number of tokens in the current sentence is greater
            # than the max number of tokens, then add the chunk to the list of chunks and reset
            # the chunk and tokens so far
            if tokens_so_far + token > max_tokens:
                chunks.append(". ".join(chunk) + ".")
                chunk = []
                tokens_so_far = 0

            # If the number of tokens in the current sentence is greater than the max number of
            # tokens, go to the next sentence
            if token > max_tokens:
                continue

            # Otherwise, add the sentence to the chunk and add the number of tokens to the total
            chunk.append(sentence)
            tokens_so_far += token + 1

        return chunks

    shortened = []

    # Loop through the dataframe
    for row in df.iterrows():

        # If the text is None, go to the next row
        if row[1]['texto'] is None:
            continue

        # If the number of tokens is greater than the max number of tokens, split the text into chunks
        if row[1]['n_tokens'] > max_tokens:
            shortened += split_into_many(row[1]['texto'])

        # Otherwise, add the text to the list of shortened texts
        else:
            shortened.append( row[1]['texto'] )

    df2 = pd.DataFrame(shortened, columns = ['texto'])
    df2['n_tokens'] = df.texto.apply(lambda x: len(tokenizer.encode(x)))

    import openai
    import os
    from dotenv import load_dotenv

    load_dotenv()
    openai.api_key = os.getenv('OPENAI_API_KEY')
    df['embeddings'] = df.texto.apply(lambda x: openai.Embedding.create(input=x, engine='text-embedding-ada-002')['data'][0]['embedding'])
    df.to_csv('embeddings.csv', index=False)
    print("embeddings atualizados")


from setuptools import setup
from wssh import __version__

with open('requirements.txt') as f:
    required = f.read().splitlines()

setup(
    name='wssh',
    version=__version__,
    author='wixb50',
    author_email='wixb50@gmail.com',
    packages=[
        'wssh'
    ],
    scripts=[
        'bin/wssh',
        'bin/wsshd'
    ],
    package_data={'': ['static/*', 'templates/*']},
    include_package_data=True,
    zip_safe=False,
    install_requires=required,
    description='SSH to WebSockets tool.',
    long_description='wssh is a SSH to WebSockets Bridge that lets you invoke a remote shell using nothing but HTTP.',
    keywords='SSH to WebSockets tool',
    license='GNU Affero GPL v3+',
    url='https://github.com/wixb50/wssh',
    download_url='https://github.com/wixb50/wssh',
    classifiers=[
        'Development Status :: 5 - Production/Stable',
        'Environment :: Console',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
        'Natural Language :: English',
        'Operating System :: POSIX',
        'Operating System :: POSIX :: Linux',
        'Programming Language :: Python :: 3',
        'Topic :: Communications :: Email',
        'Topic :: Utilities',
    ]
)


from bs4 import BeautifulSoup
import requests

word = str(input("Define "))
url = f"https://www.merriam-webster.com/dictionary/{word}"
results = requests.get(url).content
soup = BeautifulSoup(results, "lxml")
first = soup.find("a", class_="important-blue-link")
partofSpeech= first.text
seconds = soup.find("span", class_="dtText")
definition = seconds.text
print(f"\n\n{word.capitalize()} ({partofSpeech.capitalize()})\n{definition}\n")