import CoreFoundation
import objc
from PyObjCTools.TestSupport import (
    TestCase,
    min_os_level,
    os_level_key,
    os_release,
    skipUnless,
)

class TestRunLoop(TestCase):
    def testTypes(self):
        self.assertIsCFType(CoreFoundation.CFRunLoopRef)
        self.assertIsCFType(CoreFoundation.CFRunLoopSourceRef)
        self.assertIsCFType(CoreFoundation.CFRunLoopObserverRef)

        try:
            if objc.lookUpClass("__NSCFTimer") is CoreFoundation.CFRunLoopTimerRef:
                return
        except objc.error:
            pass
        try:
            if objc.lookUpClass("NSCFTimer") is CoreFoundation.CFRunLoopTimerRef:
                return
        except objc.error:
            pass
        self.assertIsCFType(CoreFoundation.CFRunLoopTimerRef)

    def testConstants(self):
        self.assertEqual(CoreFoundation.kCFRunLoopRunFinished, 1)
        self.assertEqual(CoreFoundation.kCFRunLoopRunStopped, 2)
        self.assertEqual(CoreFoundation.kCFRunLoopRunTimedOut, 3)
        self.assertEqual(CoreFoundation.kCFRunLoopRunHandledSource, 4)
        self.assertEqual(CoreFoundation.kCFRunLoopEntry, (1 << 0))
        self.assertEqual(CoreFoundation.kCFRunLoopBeforeTimers, (1 << 1))
        self.assertEqual(CoreFoundation.kCFRunLoopBeforeSources, (1 << 2))
        self.assertEqual(CoreFoundation.kCFRunLoopBeforeWaiting, (1 << 5))
        self.assertEqual(CoreFoundation.kCFRunLoopAfterWaiting, (1 << 6))
        self.assertEqual(CoreFoundation.kCFRunLoopExit, (1 << 7))
        self.assertEqual(CoreFoundation.kCFRunLoopAllActivities, 0x0FFFFFFF)
        self.assertIsInstance(CoreFoundation.kCFRunLoopDefaultMode, str)
        self.assertIsInstance(CoreFoundation.kCFRunLoopCommonModes, str)

    def testGetTypeID(self):
        self.assertIsInstance(CoreFoundation.CFRunLoopGetTypeID(), int)
        self.assertIsInstance(CoreFoundation.CFRunLoopSourceGetTypeID(), int)
        self.assertIsInstance(CoreFoundation.CFRunLoopObserverGetTypeID(), int)
        self.assertIsInstance(CoreFoundation.CFRunLoopTimerGetTypeID(), int)

    def testRunloop(self):
        runloop_mode = CoreFoundation.kCFRunLoopDefaultMode
        runloop_mode = "pyobjctest.cfrunloop"

        loop = CoreFoundation.CFRunLoopGetCurrent()
        self.assertIsInstance(loop, CoreFoundation.CFRunLoopRef)
        loop = CoreFoundation.CFRunLoopGetMain()
        self.assertIsInstance(loop, CoreFoundation.CFRunLoopRef)
        mode = CoreFoundation.CFRunLoopCopyCurrentMode(loop)
        if mode is not None:
            self.assertIsInstance(mode, str)
        self.assertResultIsCFRetained(CoreFoundation.CFRunLoopCopyAllModes)
        allmodes = CoreFoundation.CFRunLoopCopyAllModes(loop)
        self.assertIsInstance(allmodes, CoreFoundation.CFArrayRef)
        self.assertNotEqual(len(allmodes), 0)
        for mode in allmodes:
            self.assertIsInstance(mode, str)
        CoreFoundation.CFRunLoopAddCommonMode(loop, "pyobjctest")
        allmodes = CoreFoundation.CFRunLoopCopyAllModes(loop)

        tm = CoreFoundation.CFRunLoopGetNextTimerFireDate(loop, runloop_mode)
        self.assertIsInstance(tm, float)
        b = CoreFoundation.CFRunLoopIsWaiting(loop)
        self.assertIsInstance(b, bool)
        CoreFoundation.CFRunLoopWakeUp(loop)
        CoreFoundation.CFRunLoopStop(loop)

        res = CoreFoundation.CFRunLoopRunInMode("mode", 2.0, True)
        self.assertIsInstance(res, int)
        self.assertEqual(res, CoreFoundation.kCFRunLoopRunFinished)

        # CoreFoundation.CFRunLoopRun is hard to test reliably
        self.assertHasAttr(CoreFoundation, "CFRunLoopRun")

    def testObserver(self):
        runloop_mode = CoreFoundation.kCFRunLoopDefaultMode
        runloop_mode = "pyobjctest.cfrunloop"

        rl = CoreFoundation.CFRunLoopGetCurrent()

        data = {}
        state = []

        def callback(observer, activity, info):
            state.append((observer, activity, info))

        observer = CoreFoundation.CFRunLoopObserverCreate(
            None,
            CoreFoundation.kCFRunLoopEntry | CoreFoundation.kCFRunLoopExit,
            True,
            4,
            callback,
            data,
        )
        self.assertIsInstance(observer, CoreFoundation.CFRunLoopObserverRef)
        ctx = CoreFoundation.CFRunLoopObserverGetContext(observer, None)
        self.assertIs(ctx, data)
        self.assertIs(CoreFoundation.CFRunLoopObserverDoesRepeat(observer), True)
        self.assertEqual(CoreFoundation.CFRunLoopObserverGetOrder(observer), 4)
        self.assertIs(CoreFoundation.CFRunLoopObserverIsValid(observer), True)
        self.assertEqual(
            CoreFoundation.CFRunLoopObserverGetActivities(observer),
            CoreFoundation.kCFRunLoopEntry | CoreFoundation.kCFRunLoopExit,
        )
        CoreFoundation.CFRunLoopObserverInvalidate(observer)
        self.assertIs(CoreFoundation.CFRunLoopObserverIsValid(observer), False)
        ctx = CoreFoundation.CFRunLoopObserverGetContext(observer, None)
        self.assertIs(ctx, objc.NULL)
        observer = CoreFoundation.CFRunLoopObserverCreate(
            None,
            CoreFoundation.kCFRunLoopEntry | CoreFoundation.kCFRunLoopExit,
            True,
            4,
            callback,
            data,
        )
        self.assertIsInstance(observer, CoreFoundation.CFRunLoopObserverRef)
        self.assertIs(
            CoreFoundation.CFRunLoopContainsObserver(rl, observer, runloop_mode), False
        )
        CoreFoundation.CFRunLoopAddObserver(rl, observer, runloop_mode)
        self.assertIs(
            CoreFoundation.CFRunLoopContainsObserver(rl, observer, runloop_mode), True
        )

        # Use dummy stream to ensure that the runloop actually performs work
        strval = b"hello world"
        stream = CoreFoundation.CFReadStreamCreateWithBytesNoCopy(
            None, strval, len(strval), CoreFoundation.kCFAllocatorNull
        )
        self.assertIsInstance(stream, CoreFoundation.CFReadStreamRef)
        CoreFoundation.CFReadStreamScheduleWithRunLoop(stream, rl, runloop_mode)
        res = CoreFoundation.CFRunLoopRunInMode(runloop_mode, 1.0, True)
        self.assertIsInstance(res, int)
        CoreFoundation.CFReadStreamUnscheduleFromRunLoop(stream, rl, runloop_mode)

        self.assertNotEqual(len(state), 0)
        for item in state:
            self.assertIs(item[0], observer)
            self.assertIn(
                item[1], (CoreFoundation.kCFRunLoopEntry, CoreFoundation.kCFRunLoopExit)
            )
            self.assertIs(item[2], data)
        CoreFoundation.CFRunLoopRemoveObserver(rl, observer, runloop_mode)
        self.assertIs(
            CoreFoundation.CFRunLoopContainsObserver(rl, observer, runloop_mode), False
        )

    def testTimer(self):
        runloop_mode = CoreFoundation.kCFRunLoopDefaultMode
        runloop_mode = "pyobjctest.cfrunloop"
        rl = CoreFoundation.CFRunLoopGetCurrent()

        state = []
        data = {}

        def callback(timer, info):
            state.append((timer, info))

        timer = CoreFoundation.CFRunLoopTimerCreate(None, 0, 0.5, 0, 0, callback, data)

        r = CoreFoundation.CFRunLoopTimerGetNextFireDate(timer)
        self.assertIsInstance(r, float)
        CoreFoundation.CFRunLoopTimerSetNextFireDate(timer, r + 2)
        r2 = CoreFoundation.CFRunLoopTimerGetNextFireDate(timer)
        self.assertEqual(int(r2), int(r + 2))

        r = CoreFoundation.CFRunLoopTimerGetInterval(timer)
        self.assertEqual(r, 0.5)

        self.assertIs(CoreFoundation.CFRunLoopTimerGetContext(timer, None), data)
        self.assertIs(CoreFoundation.CFRunLoopTimerDoesRepeat(timer), True)
        self.assertEqual(CoreFoundation.CFRunLoopTimerGetOrder(timer), 0)
        self.assertIs(CoreFoundation.CFRunLoopTimerIsValid(timer), True)
        CoreFoundation.CFRunLoopTimerInvalidate(timer)
        self.assertIs(CoreFoundation.CFRunLoopTimerIsValid(timer), False)
        self.assertIs(CoreFoundation.CFRunLoopTimerGetContext(timer, None), objc.NULL)
        timer = CoreFoundation.CFRunLoopTimerCreate(None, 0, 0.5, 0, 0, callback, data)
        self.assertIs(
            CoreFoundation.CFRunLoopContainsTimer(rl, timer, runloop_mode), False
        )
        CoreFoundation.CFRunLoopAddTimer(rl, timer, runloop_mode)
        self.assertIs(
            CoreFoundation.CFRunLoopContainsTimer(rl, timer, runloop_mode), True
        )
        res = CoreFoundation.CFRunLoopRunInMode(runloop_mode, 1.3, True)
        self.assertIsInstance(res, int)

        CoreFoundation.CFRunLoopTimerInvalidate(timer)
        CoreFoundation.CFRunLoopRemoveTimer(rl, timer, runloop_mode)
        self.assertIs(
            CoreFoundation.CFRunLoopContainsTimer(rl, timer, runloop_mode), False
        )
        self.assertFalse(len(state) < 3)
        for item in state:
            self.assertIs(item[0], timer)
            self.assertIs(item[1], data)

    def testSource(self):
        runloop_mode = CoreFoundation.kCFRunLoopDefaultMode
        runloop_mode = "pyobjctest.cfrunloop"

        rl = CoreFoundation.CFRunLoopGetCurrent()

        state = []
        data = {}

        def schedule(info, rl, mode):
            state.append(["schedule", info, rl, mode])

        def cancel(info, rl, mode):
            state.append(["cancel", info, rl, mode])

        def perform(info):
            state.append(["perform", info])

        source = CoreFoundation.CFRunLoopSourceCreate(
            None, 55, (0, schedule, cancel, perform, data)
        )
        self.assertIsInstance(source, CoreFoundation.CFRunLoopSourceRef)
        ctx = CoreFoundation.CFRunLoopSourceGetContext(source, None)
        self.assertIsInstance(ctx, tuple)
        self.assertEqual(ctx[0], 0)
        self.assertEqual(ctx[1], schedule)
        self.assertEqual(ctx[2], cancel)
        self.assertEqual(ctx[3], perform)
        self.assertEqual(ctx[4], data)

        self.assertEqual(CoreFoundation.CFRunLoopSourceGetOrder(source), 55)
        self.assertIs(CoreFoundation.CFRunLoopSourceIsValid(source), True)
        CoreFoundation.CFRunLoopSourceInvalidate(source)
        self.assertIs(CoreFoundation.CFRunLoopSourceIsValid(source), False)
        source = CoreFoundation.CFRunLoopSourceCreate(
            None, 55, (0, schedule, cancel, perform, data)
        )
        self.assertIsInstance(source, CoreFoundation.CFRunLoopSourceRef)
        self.assertIs(
            CoreFoundation.CFRunLoopContainsSource(rl, source, runloop_mode), False
        )
        CoreFoundation.CFRunLoopAddSource(rl, source, runloop_mode)
        self.assertIs(
            CoreFoundation.CFRunLoopContainsSource(rl, source, runloop_mode), True
        )
        self.assertEqual(len(state), 1)
        self.assertEqual(state[0][0], "schedule")
        self.assertIs(state[0][1], data)
        self.assertIs(state[0][2], rl)
        self.assertEqual(state[0][3], runloop_mode)
        del state[:]

        res = CoreFoundation.CFRunLoopRunInMode(runloop_mode, 0.5, True)
        self.assertIsInstance(res, int)
        # self.assertEqual(res, CoreFoundation.kCFRunLoopRunTimedOut)

        self.assertEqual(len(state), 0)

        CoreFoundation.CFRunLoopSourceSignal(source)

        res = CoreFoundation.CFRunLoopRunInMode(runloop_mode, 0.5, True)
        self.assertIsInstance(res, int)
        self.assertEqual(res, CoreFoundation.kCFRunLoopRunHandledSource)

        self.assertEqual(len(state), 1)
        self.assertEqual(state[0][0], "perform")
        self.assertIs(state[0][1], data)
        del state[:]

        CoreFoundation.CFRunLoopRemoveSource(rl, source, runloop_mode)
        self.assertIs(
            CoreFoundation.CFRunLoopContainsSource(rl, source, runloop_mode), False
        )
        self.assertEqual(len(state), 1)
        self.assertEqual(state[0][0], "cancel")
        self.assertIs(state[0][1], data)
        self.assertIs(state[0][2], rl)
        self.assertEqual(state[0][3], runloop_mode)

    @skipUnless(
        not (
            os_level_key("10.13") <= os_level_key(os_release()) < os_level_key("10.15")
        ),
        "Crash on 10.13, 10.14??",
    )
    @min_os_level("10.6")
    def testFunctions10_6(self):
        self.assertArgIsBlock(CoreFoundation.CFRunLoopPerformBlock, 2, b"v")

        runloop_mode = CoreFoundation.kCFRunLoopDefaultMode
        rl = CoreFoundation.CFRunLoopGetCurrent()

        lst = []

        def doit():
            lst.append(True)

        CoreFoundation.CFRunLoopPerformBlock(rl, runloop_mode, doit)
        res = CoreFoundation.CFRunLoopRunInMode(runloop_mode, 0.5, True)
        self.assertIsInstance(res, int)

        self.assertEqual(lst, [True])

    @skipUnless(
        not (
            os_level_key("10.13") <= os_level_key(os_release()) < os_level_key("10.15")
        ),
        "Crash on 10.13, 10.14??",
    )
    @min_os_level("10.7")
    def testFunctions10_7(self):
        self.assertArgIsBOOL(CoreFoundation.CFRunLoopObserverCreateWithHandler, 2)
        self.assertArgIsBlock(
            CoreFoundation.CFRunLoopObserverCreateWithHandler,
            4,
            b"v^{__CFRunLoopObserver=}" + objc._C_NSUInteger,
        )

        lst = []

        def record(observer, activity):
            lst.append((observer, activity))

        ref = CoreFoundation.CFRunLoopObserverCreateWithHandler(
            None, CoreFoundation.kCFRunLoopAllActivities, False, 0, record
        )
        self.assertIsInstance(ref, CoreFoundation.CFRunLoopObserverRef)

        runloop_mode = CoreFoundation.kCFRunLoopDefaultMode
        rl = CoreFoundation.CFRunLoopGetCurrent()

        CoreFoundation.CFRunLoopAddObserver(rl, ref, runloop_mode)
        res = CoreFoundation.CFRunLoopRunInMode(runloop_mode, 0.5, True)
        CoreFoundation.CFRunLoopRemoveObserver(rl, ref, runloop_mode)

        self.assertNotEqual(lst, [])
        for a, b in lst:
            self.assertEqual(a, ref)
            self.assertIsInstance(b, int)

        self.assertArgIsBlock(
            CoreFoundation.CFRunLoopTimerCreateWithHandler, 5, b"v^{__CFRunLoopTimer=}"
        )
        lst = []
        ref = CoreFoundation.CFRunLoopTimerCreateWithHandler(
            None,
            CoreFoundation.CFAbsoluteTimeGetCurrent() + 2.9,
            0.0,
            0,
            0,
            lambda x: lst.append(x),
        )
        self.assertIsInstance(ref, CoreFoundation.CFRunLoopTimerRef)

        CoreFoundation.CFRunLoopAddTimer(rl, ref, runloop_mode)
        res = CoreFoundation.CFRunLoopRunInMode(runloop_mode, 6.0, True)
        self.assertIsInstance(res, int)
        CoreFoundation.CFRunLoopRemoveTimer(rl, ref, runloop_mode)

        import __main__

        # XXX: See issue #11 in the pyobjc tracker
        if "setup" in __main__.__file__:
            return

        self.assertNotEqual(lst, [])
        for a in lst:
            self.assertEqual(a, ref)

    @min_os_level("10.9")
    def testFunctions10_9(self):
        lst = []
        ref = CoreFoundation.CFRunLoopTimerCreateWithHandler(
            None,
            CoreFoundation.CFAbsoluteTimeGetCurrent() + 2.9,
            0.0,
            0,
            0,
            lambda x: lst.append(x),
        )
        self.assertIsInstance(ref, CoreFoundation.CFRunLoopTimerRef)
        CoreFoundation.CFRunLoopTimerSetTolerance(ref, 5.0)
        v = CoreFoundation.CFRunLoopTimerGetTolerance(ref)
        self.assertIsInstance(v, float)


import sqlite3
from Conta_Bancaria import Conta

class banco:

  def __init__(self, nome_arquivo):
    self.conexao = sqlite3.connect(nome_arquivo)
    self.criar_tabela()

  def criar_tabela(self):
    cursor = self.conexao.cursor()
    cursor.execute(
      """
      CREATE TABLE IF NOT EXISTS contas(
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        nome TEXT NOT NULL,
        saldo REAL NOT NULL
      )
      """
    )
    self.conexao.commit()

  def criar_conta(self, nome, saldo=0.0):
    cursor = self.conexao.cursor()
    cursor.execute(
      """
      INSERT INTO contas (nome, saldo) VALUES (?,?)
      """, (nome, saldo)
    )
    self.conexao.commit()
    return cursor.lastrowid

  def buscar_conta(self, id_conta):
    cursor = self.conexao.cursor()
    conta = cursor.execute(
      """
      SELECT id, nome, saldo FROM contas WHERE id = ?
      """,(id_conta)
    )
    dados = cursor.fetchone()
    if dados:
      id, nome, saldo = dados
      return Conta(id, nome, saldo)
    return None

  def depositar(self, id_conta, valor):
    conta = self.buscar_conta(id_conta)
    if conta:
      if conta.deposito_valido(valor):
        cursor = self.conexao.cursor()
        cursor.execute(
          """
          UPDATE contas SET saldo = ? WHERE id = ?
          """, (conta.saldo, conta.numero_conta)
        )
        self.conexao.commit()

  def sacar(self, id_conta, valor):
    conta = self.buscar_conta(id_conta)
    if conta:
      if conta.saque_valido(valor):
        cursor = self.conexao.cursor()
        cursor.execute(
          """
          UPDATE contas SET saldo = ? WHERE id = ?
          """, (conta.saldo, conta.numero_conta)
        )
        self.conexao.commit()
  def deletar(self, id_conta):
    cursor = self.conexao.cursor()
    cursor.execute(
      """
      DELETE FROM contas
    WHERE id = ?
      """,(id_conta)
    )


import os
import torch
import numpy as np
from torch.autograd import Variable
import torch.nn as nn
from torch.nn import init

def build_embed(path):
    embed = {}
    eword = []
    with open(path, 'r') as f:
        for line in f:
            token = line.split()
            word = token[0]
            eword.append(word)
            value = np.asarray(token[1:], dtype='float32')
            embed[word] = value
        f.close()
    print('Found %s word vectors.' % len(embed))
    return embed, eword

def build_corpus(path):
    word2idx = {}
    idx2word = []
    trainlbl = []
    testlbl = []

    assert os.path.exists(path)

    train = os.path.join(path, 'train.txt')
    test = os.path.join(path, 'test.txt')

    with open(train, 'r') as f:
        for line in f:
            sents = line.split('\t')
            trainlbl.append(sents[0])
            words = sents[2].split()
            for word in words:
                if word not in word2idx:
                    idx2word.append(word)
                    word2idx[word] = len(idx2word) - 1
            words = sents[6].split()
            for word in words:
                if word not in word2idx:
                    idx2word.append(word)
                    word2idx[word] = len(idx2word) - 1

    with open(test, 'r') as f:
        for line in f:
            sents = line.split('\t')
            testlbl.append(sents[0])
            words = sents[2].split()
            for word in words:
                if word not in word2idx:
                    idx2word.append(word)
                    word2idx[word] = len(idx2word) - 1
            words = sents[6].split()
            for word in words:
                if word not in word2idx:
                    idx2word.append(word)
                    word2idx[word] = len(idx2word) - 1

    return word2idx, idx2word, trainlbl, testlbl

def build_vector(embed, dim, vocab, line):
    sents = line.split('\t')
    lsent = sents[2].split()
    rsent = sents[6].split()

    lsentm = Variable(torch.FloatTensor(torch.zeros(len(lsent), dim)))
    rsentm = Variable(torch.FloatTensor(torch.zeros(len(rsent), dim)))

    for i in range(len(lsent)):
        if lsent[i] in vocab:
            #print embed[lsent[i]]
            lsentm[i] = torch.from_numpy(embed[lsent[i]]).view(1, dim)
        else:
            w = torch.Tensor(1, dim)
            w = nn.init.normal(w, 0, 0.1)
            lsentm[i] = w

    for i in range(len(rsent)):
        if rsent[i] in vocab:
            #print embed[rsent[i]]
            rsentm[i] = torch.from_numpy(embed[rsent[i]]).view(1, dim)
        else:
            w = torch.Tensor(1, dim)
            w = nn.init.normal(w, 0, 0.1)
            rsentm[i] = w

    return lsentm, rsentm

# path = "/home/hjp/Downloads/msc/"
# word2idx, idx2word, trainlbl, testlbl = build_corpus(path)
# print word2idx
# print idx2word
# print len(word2idx)
# print len(idx2word)
# print trainlbl
# print len(trainlbl)
# print len(testlbl)
#def word2emb(word, emb):

#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
# class Dictionary(object):
#     def __init__(self):
#         self.word2idx = {}
#         self.idx2word = []
#
#     def add_word(self, word):
#         if word not in self.word2idx:
#             self.idx2word.append(word)
#             self.word2idx[word] = len(self.idx2word) - 1
#         return self.word2idx[word]
#
#     def __len__(self):
#         return len(self.idx2word)
#
#
#
# def vocab(x):
#     x.sum()
#
# with open('/home/hjp/Downloads/msc/glove.6B.50d.txt') as f:
#     for line in f:
#         print line
#
# def readMSC():
#     return


import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import pandas as pd
from torch.utils.data import DataLoader, TensorDataset
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix, classification_report
import seaborn as sns

# Load dataset
df = pd.read_csv(r'./data/task2/diabetes_binary.csv')
X = df.iloc[:, :-1].values
y = df.iloc[:, -1].values

#scale X array
scaler = StandardScaler()
X = scaler.fit_transform(X)

# Split and Create Dataset
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=42)

X_train = torch.FloatTensor(X_train).unsqueeze(1)
y_train = torch.LongTensor(y_train)
X_test = torch.FloatTensor(X_test).unsqueeze(1)
y_test = torch.LongTensor(y_test)
train_dataset = TensorDataset(X_train, y_train)
test_dataset = TensorDataset(X_test, y_test)
for batch in [128]:
    train_loader = DataLoader(dataset=train_dataset, batch_size=batch, shuffle=True)
    test_loader = DataLoader(dataset=test_dataset, batch_size=batch, shuffle=False)

# Define network architecture
class DiabetesNet(nn.Module):
    def __init__(self):
        super(DiabetesNet, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Conv1d(1, 32, kernel_size=3, padding=1),
            nn.BatchNorm1d(32),
            nn.ReLU(),
            nn.MaxPool1d(2))
        # No layer 2
        self.layer2 = nn.Sequential(
            nn.Linear(32 * ((X_train.shape[2] // 2)), 8),  #
            nn.Dropout(0.5))
        self.fc = nn.Linear(8, 2)  # Binary classification

    def forward(self, x):
        out = self.layer1(x)
        # No layer 2
        out = out.view(out.size(0), -1)
        out = self.layer2(out)
        out = self.fc(out)
        return out

# Initialize the model and optimizer
net = DiabetesNet()
optimizer = optim.Adam(net.parameters(), lr=0.01)
criterion = nn.CrossEntropyLoss()

# Tracking Loss and Accuracy
train_losses = []
test_losses = []
train_accuracies = []
test_accuracies = []

num_epochs = 50  # Set the number of epochs

# Training loop
for epoch in range(num_epochs):
    for i, (features, labels) in enumerate(train_loader):
        optimizer.zero_grad()
        outputs = net(features)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
    train_losses.append(loss.item())

    # Validation
    with torch.no_grad():
        output = net(X_test)
        test_loss = criterion(output, y_test)
        test_losses.append(test_loss.item())

        # Calculate the training accuracy
        output_train = net(X_train)
        _, pred_train = torch.max(output_train, 1)
        train_accuracy = (pred_train == y_train).float().mean()
        train_accuracies.append(train_accuracy)

        # Calculate the test accuracy
        _, pred_test = torch.max(output, 1)
        test_accuracy = (pred_test == y_test).float().mean()
        test_accuracies.append(test_accuracy)

    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}, Test Loss: {test_loss.item():.4f}, Train Accuracy: {train_accuracy:.2f}, Test Accuracy: {test_accuracy:.2f}')

# Plotting the training and test accuracy
plt.figure()
plt.plot(train_accuracies, label='Training Accuracy')
plt.plot(test_accuracies, label='Test Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.title('Accuracy vs. Epochs')
plt.show()

# Plotting the training and test loss
plt.figure()
plt.plot(train_losses, label='Training Loss')
plt.plot(test_losses, label='Test Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.title('Loss vs. Epochs')
plt.show()

# Final evaluation
with torch.no_grad():
    outputs = net(X_test)
    _, predicted = torch.max(outputs, 1)
    cm = confusion_matrix(y_test, predicted)
    cr = classification_report(y_test, predicted)
    print("Confusion Matrix:")
    print(cm)
    print("Classification Report:")
    print(cr)

    # Heatmap for Confusion Matrix
    sns.heatmap(cm, annot=True, fmt='d')
    plt.xlabel('Predicted')
    plt.ylabel('True')
    plt.show()


import os
import matplotlib.pyplot as plt
from operator import itemgetter
from collections import OrderedDict

directory_path = {
    'mp3': "/Users/barber/Data/Research/File-type-identification/very-small-data/mp3",
    'hwp': "/Users/barber/Data/Research/File-type-identification/very-small-data/hwp",
    'pdf': "/Users/barber/Data/Research/File-type-identification/very-small-data/pdf",
    'jpg': "/Users/barber/Data/Research/File-type-identification/very-small-data/jpg",
    'png': "/Users/barber/Data/Research/File-type-identification/very-small-data/png"
}

file_size_in_bytes = 4096
max_process_size_in_bytes = 3 * 1024 * 1024 # 3 MB
# max_process_size_in_bytes = 700 * file_size_in_bytes # 700 Fragments
gram_size = 50

def main():
    fig = plt.figure()
    ax1 = fig.add_subplot(111)
    plt.title('all, 50-gram, 3 MB')

    for file_type, directory in directory_path.items():

        if not os.path.exists(directory):
            exit(-1)

        if not directory.endswith("/"):
            directory += "/"

        fragments_processed = 0
        fragments_to_process = int(max_process_size_in_bytes / file_size_in_bytes)

        next_type_flag = False

        for file_name in os.listdir(directory):
            if next_type_flag:
                break

            if file_name.startswith("."):
                continue

            file_path = directory + file_name
            separator_frequency = dict()
            with open(file_path, "rb") as file:
                fragment = file.read(file_size_in_bytes)
                while len(fragment) == file_size_in_bytes:

                    for index in range(0, file_size_in_bytes - gram_size + 1):
                        separator = int.from_bytes(fragment[index:(index + gram_size)], byteorder='big')
                        if separator in separator_frequency:
                            separator_frequency[separator] += 1
                        else:
                            separator_frequency[separator] = 1

                    fragments_processed += 1
                    if fragments_processed >= fragments_to_process:
                        print("Processed {}.".format(file_type))
                        ordered_frequency = OrderedDict(
                            sorted(separator_frequency.items(), key=itemgetter(1), reverse=True))
                        x = list(ordered_frequency.keys())[:4096]
                        y = list(ordered_frequency.values())[:4096]
                        ax1.scatter(x, y, s=2, label=file_type)
                        # fragment_frequency.output.close();
                        next_type_flag = True
                        break

                    if next_type_flag:
                        break

                    fragment = file.read(file_size_in_bytes)

    box = ax1.get_position()
    ax1.set_position([box.x0, box.y0 + box.height * 0.1,
                     box.width, box.height * 0.9])

    # Put a legend below current axis
    ax1.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), ncol=5)
    plt.show()

if __name__ == "__main__":
    main()


import logging
import os
import re
import signal
import sys
import warnings

# primary public APIs

def configure_logging(logging_config, **kwargs):
    """
    Configure the logging module using the specific configuration object, which
    should be an instance of logging_config.LoggingConfig (usually of a
    subclass).  Any keyword args will be passed to the object's
    configure_logging() method.

    Every entry point should call this method at application startup.
    """
    LoggingManager.logging_config_object = logging_config
    logging_config.configure_logging(**kwargs)

def get_logging_manager(manage_stdout_and_stderr=False, redirect_fds=False):
    """
    Create a LoggingManager that's managing sys.stdout and sys.stderr.

    Every entry point that wants to capture stdout/stderr and/or use
    LoggingManager to manage a stack of destinations should call this method
    at application startup.
    """
    if redirect_fds:
        manager = FdRedirectionLoggingManager()
    else:
        manager = LoggingManager()
    if manage_stdout_and_stderr:
        manager.manage_stdout()
        manager.manage_stderr()
    return manager

# implementation follows

logger = logging.getLogger()

def _current_handlers():
    return set(logger.handlers)

_caller_code_to_skip_in_logging_stack = set()

def do_not_report_as_logging_caller(func):
    """Decorator to annotate functions we will tell logging not to log."""
    # These are not the droids you are looking for.
    # You may go about your business.
    _caller_code_to_skip_in_logging_stack.add(func.func_code)
    return func

# Copied from Python 2.4 logging/__init__.py Logger.findCaller and enhanced.
# The logging code remains the same and compatible with this monkey patching
# through at least Python version 2.6.2.
def _logging_manager_aware_logger__find_caller(unused):
    """
    Find the stack frame of the caller so that we can note the source
    file name, line number and function name.
    """
    f = sys._getframe(2).f_back
    rv = "(unknown file)", 0, "(unknown function)"
    while hasattr(f, "f_code"):
        co = f.f_code
        filename = os.path.normcase(co.co_filename)
        if filename == logging._srcfile:
            f = f.f_back
            continue
        # START additional code.
        if co in _caller_code_to_skip_in_logging_stack:
            f = f.f_back
            continue
        # END additional code.
        rv = (filename, f.f_lineno, co.co_name)
        break
    return rv

if sys.version_info[:2] > (2, 7):
    warnings.warn('This module has not been reviewed for Python %s' %
                  sys.version)

# Monkey patch our way around logging's design...
_original_logger__find_caller = logging.Logger.findCaller
logging.Logger.findCaller = _logging_manager_aware_logger__find_caller

class LoggingFile(object):

    """
    File-like object that will receive messages pass them to the logging
    infrastructure in an appropriate way.
    """

    def __init__(self, prefix='', level=logging.DEBUG,
                 logger=logging.getLogger()):
        """
        :param prefix - The prefix for each line logged by this object.
        """

        self._prefix = prefix
        self._level = level
        self._buffer = []
        self._logger = logger

    @do_not_report_as_logging_caller
    def write(self, data):
        """"
        Writes data only if it constitutes a whole line. If it's not the case,
        store it in a buffer and wait until we have a complete line.
        :param data - Raw data (a string) that will be processed.
        """
        # splitlines() discards a trailing blank line, so use split() instead
        data_lines = data.split('\n')
        if len(data_lines) > 1:
            self._buffer.append(data_lines[0])
            self._flush_buffer()
        for line in data_lines[1:-1]:
            self._log_line(line)
        if data_lines[-1]:
            self._buffer.append(data_lines[-1])

    @do_not_report_as_logging_caller
    def writelines(self, lines):
        """"
        Writes itertable of lines

        :param lines: An iterable of strings that will be processed.
        """
        for data in lines:
            self.write(data)

    @do_not_report_as_logging_caller
    def _log_line(self, line):
        """
        Passes lines of output to the logging module.
        """
        self._logger.log(self._level, self._prefix + line)

    @do_not_report_as_logging_caller
    def _flush_buffer(self):
        if self._buffer:
            self._log_line(''.join(self._buffer))
            self._buffer = []

    @do_not_report_as_logging_caller
    def flush(self):
        self._flush_buffer()

    def isatty(self):
        return False

class SortingLoggingFile(LoggingFile):

    """
    File-like object that will receive messages and pass them to the logging
    infrastructure. It decides where to pass each line by applying a regex
    to it and seeing which level it matched.
    """

    def __init__(self, prefix='', level_list=[('ERROR', logging.ERROR),
                                              ('WARN', logging.WARN), ('INFO', logging.INFO),
                                              ('DEBUG', logging.DEBUG)], logger=logging.getLogger()):
        super(SortingLoggingFile, self).__init__(prefix=prefix, logger=logger)
        self._level_list = [(re.compile(x), y) for x, y in level_list]

    @do_not_report_as_logging_caller
    def _log_line(self, line):
        for pattern, level in self._level_list:
            if pattern.search(line):
                self._logger.log(level, self._prefix + line)
                break
        else:
            self._logger.log(logging.ERROR, 'UNMATCHED_LOG_LEVEL: ' +
                             self._prefix + line)

class _StreamManager(object):

    """
    Redirects all output for some output stream (normally stdout or stderr) to
    the logging module by replacing the file objects with a new LoggingFile
    that calls logging.log().
    """

    def __init__(self, stream, level, stream_setter):
        """
        :param stream: stream object to manage
        :param level: level at which data written to the stream will be logged
        :param stream_setter: function accepting a stream object that will
                replace the given stream in its original location.
        """
        self._stream = stream
        self._level = level
        self._stream_setter = stream_setter
        self._logging_stream = None

    def _replace_with_logger(self):
        self._logging_stream = LoggingFile(level=self._level)
        self._stream_setter(self._logging_stream)

    def _restore_stream(self):
        self._stream_setter(self._stream)

    def flush(self):
        self._logging_stream.flush()

    def start_logging(self):
        """Start directing the stream to the logging module."""
        self._replace_with_logger()

    def stop_logging(self):
        """Restore the stream to its original settings."""
        self._restore_stream()

    def on_push_context(self, context):
        """
        Called when the logging manager is about to push a new context onto the
        stack and has changed logging settings.  The StreamHandler can modify
        the context to be saved before returning.
        """
        pass

    def on_restore_context(self, context):
        """
        Called when the logging manager is restoring a previous context.
        """
        pass

class LoggingManager(object):

    """
    Manages a stack of logging configurations, allowing clients to conveniently
    add and remove logging destinations.  Also keeps a list of StreamManagers
    to easily direct streams into the logging module.
    """

    STREAM_MANAGER_CLASS = _StreamManager

    logging_config_object = None

    def __init__(self):
        """
        This class should not ordinarily be constructed directly (other than in
        tests).  Use the module-global factory method get_logging_manager()
        instead.
        """
        if self.logging_config_object is None:
            raise RuntimeError('You must call configure_logging() before this')

        # _context_stack holds a stack of context dicts.  Each context dict
        # contains:
        # * old_handlers: list of registered logging Handlers
        # contexts may also be extended by _StreamHandlers
        self._context_stack = []
        self._streams = []
        self._started = False

    def manage_stream(self, stream, level, stream_setter):
        """
        Tells this manager to manage the given stream.  All data written to the
        stream will be directed to the logging module instead.  Must be called
        before start_logging().

        :param stream: stream to manage
        :param level: level to log data written to this stream
        :param stream_setter: function to set the stream to a new object
        """
        if self._started:
            raise RuntimeError('You must call this before start_logging()')
        self._streams.append(self.STREAM_MANAGER_CLASS(stream, level,
                                                       stream_setter))

    def _sys_stream_setter(self, stream_name):
        assert stream_name in ('stdout', 'stderr'), stream_name

        def set_stream(file_object):
            setattr(sys, stream_name, file_object)
        return set_stream

    def manage_stdout(self):
        self.manage_stream(sys.stdout, logging.INFO,
                           self._sys_stream_setter('stdout'))

    def manage_stderr(self):
        self.manage_stream(sys.stderr, self.logging_config_object.stderr_level,
                           self._sys_stream_setter('stderr'))

    def start_logging(self):
        """
        Begin capturing output to the logging module.
        """
        for stream_manager in self._streams:
            stream_manager.start_logging()
        self._started = True

    def stop_logging(self):
        """
        Restore output to its original state.
        """
        while self._context_stack:
            self._pop_context()

        for stream_manager in self._streams:
            stream_manager.stop_logging()

        self._started = False

    def _clear_all_handlers(self):
        for handler in _current_handlers():
            logger.removeHandler(handler)

    def _get_context(self):
        return {'old_handlers': _current_handlers()}

    def _push_context(self, context):
        for stream_manager in self._streams:
            stream_manager.on_push_context(context)
        self._context_stack.append(context)

    def _flush_all_streams(self):
        for stream_manager in self._streams:
            stream_manager.flush()

    def _add_log_handlers(self, add_handlers_fn):
        """
        Modify the logging module's registered handlers and push a new context
        onto the stack.
        :param add_handlers_fn: function to modify the registered logging
        handlers. Accepts a context dictionary which may be modified.
        """
        self._flush_all_streams()
        context = self._get_context()

        add_handlers_fn(context)

        self._push_context(context)

    class _TaggingFormatter(logging.Formatter):

        """
        Delegates to a given formatter, but prefixes each line of output with a
        tag.
        """

        def __init__(self, base_formatter, tag):
            self.base_formatter = base_formatter
            prefix = tag + ' : '
            self._fmt = base_formatter._fmt.replace('%(message)s',
                                                    prefix + '%(message)s')
            self.datefmt = base_formatter.datefmt

    def _add_tagging_formatter(self, tag):
        for handler in _current_handlers():
            tagging_formatter = self._TaggingFormatter(handler.formatter, tag)
            handler.setFormatter(tagging_formatter)

    def _do_redirect(self, stream=None, filename=None, level=None,
                     clear_other_handlers=False):
        """
        :param clear_other_handlers - if true, clear out all other logging
        handlers.
        """
        assert bool(stream) != bool(filename)  # xor
        if not self._started:
            raise RuntimeError('You must call start_logging() before this')

        def add_handler(context):
            if clear_other_handlers:
                self._clear_all_handlers()

            if stream:
                handler = self.logging_config_object.add_stream_handler(stream)
            else:
                handler = self.logging_config_object.add_file_handler(filename)

            if level:
                handler.setLevel(level)

        self._add_log_handlers(add_handler)

    def redirect(self, filename):
        """Redirect output to the specified file"""
        self._do_redirect(filename=filename, clear_other_handlers=True)

    def redirect_to_stream(self, stream):
        """Redirect output to the given stream"""
        self._do_redirect(stream=stream, clear_other_handlers=True)

    def tee_redirect(self, filename, level=None):
        """Tee output to the specified file"""
        self._do_redirect(filename=filename, level=level)

    def tee_redirect_to_stream(self, stream):
        """Tee output to the given stream"""
        self._do_redirect(stream=stream)

    def tee_redirect_debug_dir(self, debug_dir, log_name=None, tag=None):
        """
        Tee output to a full new set of debug logs in the given directory.
        """
        def add_handlers(context):
            if tag:
                self._add_tagging_formatter(tag)
                context['tag_added'] = True
            self.logging_config_object.add_debug_file_handlers(
                debug_dir, log_name=log_name)
        self._add_log_handlers(add_handlers)

    def _restore_context(self, context):
        for stream_handler in self._streams:
            stream_handler.on_restore_context(context)

        # restore logging handlers
        old_handlers = context['old_handlers']
        for handler in _current_handlers() - old_handlers:
            handler.close()
        self._clear_all_handlers()
        for handler in old_handlers:
            logger.addHandler(handler)

        if 'tag_added' in context:
            for handler in _current_handlers():
                tagging_formatter = handler.formatter
                handler.setFormatter(tagging_formatter.base_formatter)

    def _pop_context(self):
        self._flush_all_streams()
        context = self._context_stack.pop()
        self._restore_context(context)

    def undo_redirect(self):
        """
        Undo the last redirection (that hasn't yet been undone).

        If any subprocesses have been launched since the redirection was
        performed, they must have ended by the time this is called.  Otherwise,
        this will hang waiting for the logging subprocess to end.
        """
        if not self._context_stack:
            raise RuntimeError('No redirects to undo')
        self._pop_context()

    def restore(self):
        """
        Same as undo_redirect().  For backwards compatibility with
        fd_stack.
        """
        self.undo_redirect()

class _FdRedirectionStreamManager(_StreamManager):

    """
    Like StreamManager, but also captures output from subprocesses by modifying
    the underlying file descriptors.

    For the underlying file descriptors, we spawn a subprocess that writes all
    input to the logging module, and we point the FD to that subprocess.  As a
    result, every time we redirect output we need to spawn a new subprocess to
    pick up the new logging settings (without disturbing any existing processes
    using the old logging subprocess).

    If, one day, we could get all code using utils.run() and friends to launch
    subprocesses, we'd no longer need to handle raw FD output, and we could
    get rid of all this business with subprocesses.  Another option would be
    to capture all stray output to a single, separate destination.
    """

    def __init__(self, stream, level, stream_setter):
        if not hasattr(stream, 'fileno'):
            # with fake, in-process file objects, subprocess output won't be
            # captured. this should never happen in normal use, since the
            # factory methods will only pass sys.stdout and sys.stderr.
            raise ValueError("FdRedirectionLoggingManager won't work with "
                             "streams that aren't backed by file "
                             "descriptors")

        super(_FdRedirectionStreamManager, self).__init__(stream, level,
                                                          stream_setter)
        self._fd = stream.fileno()
        self._fd_copy_stream = None

    def _point_stream_handlers_to_copy(self):
        """
        point logging StreamHandlers that point to this stream to a safe
        copy of the underlying FD. otherwise, StreamHandler output will go
        to the logging subprocess, effectively getting doubly logged.
        """
        fd_copy = os.dup(self._fd)
        self._fd_copy_stream = os.fdopen(fd_copy, 'w')
        self._redirect_logging_stream_handlers(self._stream,
                                               self._fd_copy_stream)

    def _restore_stream_handlers(self):
        """ point logging StreamHandlers back to the original FD """
        self._redirect_logging_stream_handlers(self._fd_copy_stream,
                                               self._stream)
        self._fd_copy_stream.close()

    def _redirect_logging_stream_handlers(self, old_stream, new_stream):
        """
        Redirect all configured logging StreamHandlers pointing to
        old_stream to point to new_stream instead.
        """
        for handler in _current_handlers():
            points_to_stream = (isinstance(handler, logging.StreamHandler) and
                                hasattr(handler.stream, 'fileno') and
                                handler.stream.fileno() == old_stream.fileno())
            if points_to_stream:
                logger.removeHandler(handler)
                handler.close()  # doesn't close the stream, just the handler

                new_handler = logging.StreamHandler(new_stream)
                new_handler.setLevel(handler.level)
                new_handler.setFormatter(handler.formatter)
                for log_filter in handler.filters:
                    new_handler.addFilter(log_filter)
                logger.addHandler(new_handler)

    def start_logging(self):
        super(_FdRedirectionStreamManager, self).start_logging()
        self._point_stream_handlers_to_copy()

    def stop_logging(self):
        super(_FdRedirectionStreamManager, self).stop_logging()
        self._restore_stream_handlers()

    def _spawn_logging_subprocess(self):
        """
        Spawn a subprocess to log all input to the logging module with the
        current settings, and direct output to it.
        """
        read_end, write_end = os.pipe()
        pid = os.fork()
        if pid:  # parent
            os.close(read_end)
            os.dup2(write_end, self._fd)  # point FD to the subprocess
            os.close(write_end)
            return pid
        else:  # child
            try:
                os.close(write_end)
                # ensure this subprocess doesn't hold any pipes to others
                os.close(1)
                os.close(2)
                self._run_logging_subprocess(read_end)  # never returns
            except Exception:
                # don't let exceptions in the child escape
                try:
                    logging.exception('Logging subprocess died:')
                finally:
                    os._exit(1)

    def _run_logging_subprocess(self, read_fd):
        """
        Always run from a subprocess.  Read from read_fd and write to the
        logging module until EOF.
        """
        signal.signal(signal.SIGTERM, signal.SIG_DFL)  # clear handler
        input_file = os.fdopen(read_fd, 'r')
        for line in iter(input_file.readline, ''):
            logging.log(self._level, line.rstrip('\n'))
        os._exit(0)

    def _context_id(self):
        return '%s_context' % id(self)

    def on_push_context(self, context):
        # adds a context dict for this stream, $id_context, with the following:
        # * old_fd: FD holding a copy of the managed FD before launching a new
        #   subprocess.
        # * child_pid: PID of the logging subprocess launched
        fd_copy = os.dup(self._fd)
        child_pid = self._spawn_logging_subprocess()
        my_context = {'old_fd': fd_copy, 'child_pid': child_pid}
        context[self._context_id()] = my_context

    def on_restore_context(self, context):
        my_context = context[self._context_id()]

        # shut down subprocess
        child_pid = my_context['child_pid']
        try:
            os.close(self._fd)
            os.waitpid(child_pid, 0)
        except OSError:
            logging.exception('Failed to cleanly shutdown logging subprocess:')

        # restore previous FD
        old_fd = my_context['old_fd']
        os.dup2(old_fd, self._fd)
        os.close(old_fd)

class FdRedirectionLoggingManager(LoggingManager):

    """
    A simple extension of LoggingManager to use FdRedirectionStreamManagers,
    so that managed streams have their underlying FDs redirected.
    """

    STREAM_MANAGER_CLASS = _FdRedirectionStreamManager

    def start_logging(self):
        super(FdRedirectionLoggingManager, self).start_logging()
        # spawn the initial logging subprocess
        self._push_context(self._get_context())

    def undo_redirect(self):
        # len == 1 would mean only start_logging() had been called (but no
        # redirects had occurred)
        if len(self._context_stack) < 2:
            raise RuntimeError('No redirects to undo')
        super(FdRedirectionLoggingManager, self).undo_redirect()


# Create your views here.

from ine.models import dict_ccaa, dict_provinces, dict_municipalities
from ine.serializers import dict_ccaa_Serializer, dict_provinces_Serializer, dict_municipalities_Serializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response

from scripts.utils import normalize_text

class dict_ccaa_List(APIView):
    """
    Retrieve a list with all CCAA.
    """

    def get(self, request):
        ccaa = dict_ccaa.objects.all()
        serializer = dict_ccaa_Serializer(ccaa, many=True)
        return Response(serializer.data)

class ccaa_Detail(APIView):

    def get_object(self, nombre):
        try:
            return dict_ccaa.objects.get(NOMBRE=nombre)
        except dict_ccaa.DoesNotExist:
            raise Http404

    def get(self, request, nombre):
        """
        Retrieve a list with the NOMBRE of a CA.

        ####    * Required NOMBRE.
        ####    Example: Andalucía
        """
        ccaa = self.get_object(nombre)
        serializer = dict_ccaa_Serializer(ccaa)
        return Response(serializer.data)

class dict_provinces_List(APIView):
    """
    Retrieve a list with all CCAA.
    """

    def get(self, request):
        provinces = dict_provinces.objects.all()
        serializer = dict_provinces_Serializer(provinces, many=True)
        return Response(serializer.data)

class provinces_Detail(APIView):

    def get_object(self, nombre):
        try:
            return dict_provinces.objects.get(NOMBRE=nombre)
        except dict_provinces.DoesNotExist:
            raise Http404

    def get(self, request, nombre):
        """
        Retrieve a list with the NOMBRE of a province.

        ####    * Required NOMBRE.
        ####    Example: Cádiz
        """
        provinces = self.get_object(nombre)
        serializer = dict_provinces_Serializer(provinces)
        return Response(serializer.data)

class dict_municipalities_List(APIView):
    """
    Retrieve a list with all CCAA.
    """

    def get(self, request):
        municipalities = dict_municipalities.objects.all()
        serializer = dict_municipalities_Serializer(municipalities, many=True)
        return Response(serializer.data)

class municipalities_Detail(APIView):

    def get_object(self, nombre):
        try:
            return dict_municipalities.objects.get(NOMBRE=nombre)
        except dict_municipalities.DoesNotExist:
            raise Http404

    def get(self, request, nombre):
        """
        Retrieve a list with the NOMBRE of a municipalitie.

        ####    * Required NOMBRE.
        ####    Example: Jerez de la Frontera
        """
        municipalities = self.get_object(nombre)
        serializer = dict_municipalities_Serializer(municipalities)
        return Response(serializer.data)

class suggest_Nombre(APIView):
    """
    Retrieve a list with suggested names for an input string.

    ####    * Required NOMBRE.
    ####    Example: jerez
    """

    def get(self, request, nombre):
        ccaa = dict_ccaa.objects.values_list('NOMBRE', flat=True)
        provinces = dict_provinces.objects.values_list('NOMBRE', flat=True)
        municipalities = dict_municipalities.objects.values_list('NOMBRE', flat=True)

        results = []
        for c in ccaa:
            result = normalize_text.evaluate_strings(nombre, c)
            if result:
                result['source'] = 'Comunidad Autónoma'
                results.append(result)

        for p in provinces:
            result = normalize_text.evaluate_strings(nombre, p)
            if result:
                result['source'] = 'Provincia'
                results.append(result)

        for m in municipalities:
            result = normalize_text.evaluate_strings(nombre, m)
            if result:
                result['source'] = 'Municipio'
                results.append(result)

        results = sorted(results, key=lambda d: d['score_%'], reverse=True)

        nombres = []
        for r in results:
            nombres.append({"Nombre": r['string'], "Entidad": r['source']})

        return Response(nombres)


#!/usr/bin/env python3
import serial
import time

while True:
    try:
        ser = serial.Serial('/dev/ttyACM0', 115200, timeout=1.0)
        print("Successfully connected to Serial.")
        break
    except serial.SerialException:
        print("Could not connect to Serial. Trying again.")
        time.sleep(1)

time.sleep(3)
ser.reset_input_buffer()
print("Serial OK")

try:
    while True:
        time.sleep(1)
        print("Sending message to Arduino")
        ser.write("Hello from Raspberry Pi\n".encode('utf-8'))
        while ser.in_waiting <= 0:
            time.sleep(0.01)
        response = ser.readline().decode('utf-8').rstrip()
        print(response)
except KeyboardInterrupt:
    print("Close Serial Communication.")
    ser.close()


#연구소2(17141번)
########################################################
    # 문제: https://www.acmicpc.net/problem/17141
    # BFS, 브루트포스 알고리즘
    # 몇가지 고려해야할 요소가 있어서 신경쓸 부분이 있는 문제였음
########################################################
import sys
from collections import deque
from itertools import combinations
input=sys.stdin.readline
N,M=map(int,input().split())
board=[]
virus=[]
dydx=[(-1,0),(0,1),(1,0),(0,-1)]
empt_cnt=0
for i in range(N):
    board.append(list(map(int,input().split())))
    for j in range(N):
        if board[i][j]==2:
            virus.append((i,j))
            empt_cnt+=1 # M개의 위치 외에 board[i][j]는 바이러스를 퍼뜨릴 수 있는 빈 공간이 되는 것이므로 board[i][j]==2일 때도 empt_cnt+=1
        elif board[i][j]==0:
            empt_cnt+=1
INF=sys.maxsize

def find_min_time(virus):
    t=INF
    for v_pos in list(combinations(virus,M)):
        q=deque(v_pos)
        time=[[INF]*N for i in range(N)]
        for i,j in v_pos:
            time[i][j]=0
        tmp_t=0 # -INF로 했더니 바이러스를 놓자마자 모든 칸이 다 채워지는 경우에는 0을 출력해야하나 -INF를 출력해버림. 따라서 초기값은 0으로 설정해야함
        cnt=empt_cnt-M # 바이러스를 M개 놓았으니 M을 빼줘야함
        while q:
            y,x=q.popleft()
            for dy,dx in dydx:
                ny,nx=y+dy,x+dx
                if 0<=ny<N and 0<=nx<N:
                    if board[ny][nx]==0 or board[ny][nx]==2: # 처음 바이러스를 퍼뜨린 위치가 아닌 가능성 있는 위치도 2이므로 board[ny][nx]==2일 때도 고려
                        if time[ny][nx]==INF: # 다음 갈 곳이 time배열이 INF면 첫 방문이므로 그 때에만 cnt-=1을 해줌
                            cnt-=1
                        if time[y][x]+1<time[ny][nx]:
                            time[ny][nx]=time[y][x]+1
                            q.append((ny,nx))
                            tmp_t=max(time[ny][nx],tmp_t) # 바이러스가 퍼지는 최대 시간을 갱신
        if cnt==0: # cnt가 0개가 되었을 때, 바이러스가 다 퍼진 것이므로 최솟값을 갱신한다
            t=min(t,tmp_t)
    if t==INF:
        return -1
    return t

print(find_min_time(virus))


import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), "../../utils"))
sys.path.append('../..')
sys.path.append('..')
import matplotlib as mpl

import numpy as np
import numpy.random as random
import time
import os.path
from astropy.io import fits
import plot

import astropy.units as u
from astropy.coordinates import SkyCoord
import sunpy.coordinates
from sunpy.coordinates import frames
import track
import misc

downsample_coef = .5
num_chunks = 1

for file_date in ["2013-02-03", "2013-02-04"]:

    hdul = fits.open(f"{file_date}_hmi.M_720s.fits")

    try:
        os.remove(f"{file_date}_2.fits")
    except:
        pass

    output = fits.open(f"{file_date}_2.fits", mode="append")
    hdu = fits.ImageHDU(data=None, header=None)
    output.append(hdu)

    metadata = hdul[1].header

    t_rec = metadata['T_REC']

    date = t_rec[:10]
    date = date[:4] + "-" + date[5:7] + "-" +date[8:10]

    hrs = t_rec[11:13]
    mins = t_rec[14:16]
    secs = t_rec[17:19]

    obs_time_0 = f"{date} {hrs}:{mins}:{secs}"

    sdo_lon_0 = metadata['CRLN_OBS']
    sdo_lat_0 = metadata['CRLT_OBS']
    sdo_dist_0 = metadata['DSUN_OBS']

    observer_0 = frames.HeliographicStonyhurst(0.*u.deg, sdo_lat_0*u.deg, radius=sdo_dist_0*u.m, obstime=obs_time_0)

    nx = int(round(metadata['NAXIS1']*downsample_coef))
    ny = int(round(metadata['NAXIS2']*downsample_coef))

    xs1 = (np.arange(1, nx + 1)).astype(float)
    ys1 = (np.arange(1, ny + 1)).astype(float)
    xys = np.transpose([np.tile(xs1, ny), np.repeat(ys1, nx)])

    data = hdul[1].data
    max_val = np.nanmax(data)
    fltr = np.isnan(data)
    data[fltr] = max_val

    if downsample_coef < 1:
        data = misc.sample_image(data, downsample_coef)
    fltr = data > .9*max_val
    data[fltr] = np.nan

    fltr0 = fltr
    xys = xys[np.logical_not(fltr).flatten()]

    for i in np.arange(1, len(hdul), 10):
        metadata = hdul[i].header

        a = metadata['CROTA2']*np.pi/180

        dx = metadata['CRVAL1']
        dy = metadata['CRVAL2']
        arcsecs_per_pix_x = metadata['CDELT1']/downsample_coef
        arcsecs_per_pix_y = metadata['CDELT2']/downsample_coef
        coef_x = 1./arcsecs_per_pix_x
        coef_y = 1./arcsecs_per_pix_y
        xc = metadata['CRPIX1']*downsample_coef
        yc = metadata['CRPIX2']*downsample_coef

        t_rec = metadata['T_REC']

        date = t_rec[:10]
        date = date[:4] + "-" + date[5:7] + "-" +date[8:10]

        hrs = t_rec[11:13]
        mins = t_rec[14:16]
        secs = t_rec[17:19]

        obs_time = f"{date} {hrs}:{mins}:{secs}"

        sdo_lon = metadata['CRLN_OBS']
        sdo_lat = metadata['CRLT_OBS']
        sdo_dist = metadata['DSUN_OBS']

        ###########################################################################
        if (i - 1) % 10 == 0:
            data = hdul[i].data
            max_val = np.nanmax(data)
            fltr = np.isnan(data)
            data[fltr] = max_val

            data = misc.sample_image(data, downsample_coef)
            fltr = data > .9*max_val
            data[fltr] = np.nan
            test_plot = plot.plot(nrows=1, ncols=1, size=plot.default_size(1000, 1000))
            test_plot.colormap(data, show_colorbar=True)
            test_plot.save(f"image{date}_{i}.png")
            test_plot.close()

            metadata['NAXIS1'] = nx
            metadata['NAXIS2'] = ny

            metadata['CDELT1'] = arcsecs_per_pix_x
            metadata['CDELT2'] = arcsecs_per_pix_y
            metadata['CRPIX1'] = xc
            metadata['CRPIX2'] = yc

            hdu = fits.ImageHDU(data=data, header=metadata)

            output.append(hdu)
            output.flush()

    output.close()
    hdul.close()


import copy
import cv2
import dask.array as da
import numpy as np
import xarray as xr

from pyproj import Transformer
from rasterio.transform import Affine, xy
from rasterio.crs import CRS
from rasterio import warp
from scipy.optimize import differential_evolution
from scipy.signal import convolve2d
from scipy.interpolate import interp1d

def affine_from_grid(xi, yi):
    """Retrieve the affine transformation from a gridded set of coordinates.
    This function (unlike rasterio.transform functions) can also handle rotated grids

    Parameters
    ----------
    xi: np.ndarray (2D)
        gridded x-coordinates
    yi: np.ndarray (2D)
        gridded y-coordinates

    Returns
    -------
    obj : rasterio.transform.Affine
    """

    xul, yul = xi[0, 0], yi[0, 0]
    xcol, ycol = xi[0, 1], yi[0, 1]
    xrow, yrow = xi[1, 0], yi[1, 0]
    dx_col = xcol - xul
    dy_col = ycol - yul
    dx_row = xrow - xul
    dy_row = yrow - yul
    return Affine(dx_col, dy_col, xul, dx_row, dy_row, yul)

def delayed_to_da(delayed_das, shape, dtype, coords, attrs={}, name=None, object_type=xr.DataArray):
    """Convert a list of delayed 2D arrays (assumed to be time steps of grids) into a 3D xr.DataArray with dask arrays
    with all axes.

    Parameters
    ----------
    delayed_das: xr.DataArray or list
    shape: tuple
        foreseen shape of data arrays (rows, cols)
    dtype: str or dtype
        e.g. "uint8" of data arrays
    coords: tuple of str
        dimensions of the xr.DataArray being prepared, usually ("time", "y", "x").
    attrs: dict, optional
        attributes for xr.DataArray (default: {})
    name: str, optional
        name of variable, default: None
    object_type: type
        type of object to create from lazy array (default: xr.DataArray)

    Returns
    -------
    object of object_type
        default: xr.DataArray
    """
    if isinstance(delayed_das, list):
        data_array = da.stack(
            [da.from_delayed(
                d,
                dtype=dtype,
                shape=shape
            ) for d in delayed_das],
            axis=0
        )
    else:
        data_array = da.from_delayed(
            delayed_das,
            dtype=dtype,
            shape=shape
        )
    for n, (coord, values) in enumerate(coords.items()):
        assert(len(values) == data_array.shape[n]), f"Length of {coord} axis {len(values)} is not equal to amount of data arrays {data_array.shape[n]}"
    return object_type(
        data_array,
        dims=tuple(coords.keys()),
        coords=coords,
        attrs=attrs,
        name=name
    )

def depth_integrate(depth, v, v_corr=0.85, name="q"):
    """Integrate velocities [m s-1] to depth-integrated velocity [m2 s-1] using depth information

    Parameters
    ----------
    depth : DataArray (points)
        bathymetry depths (ref. CRS)
    v : DataArray (time, points)
        effective velocity at surface [m s-1]
    v_corr : float (range: 0-1), optional
        typically close to 1, correction factor from surface to depth-average (default: 0.85)
    name: str, optional
        name of DataArray (default: "q")

    Returns
    -------
    q: DataArray (time, points)
        depth integrated velocity [m2 s-1]
    """
    # compute the depth average velocity
    q = v * v_corr * depth
    q.attrs = {
        "standard_name": "velocity_depth",
        "long_name": "velocity averaged over depth",
        "units": "m2 s-1",
    }
    # set name
    q.name = name
    return q

def distance_pts(c1, c2):
    """Compute distance between c1 and c2

    Parameters
    ----------

    c1 : tuple
        (x, y), coordinate 1
    c2: tuple
        (x, y), coordinate 2

    Returns
    -------
    dist : float
        distance between c1 and c2
    """
    x1, y1 = c1
    x2, y2 = c2
    return ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5

def deserialize_attr(data_array, attr, dtype=np.array, args_parse=False):
    """Return a deserialized version of said property (assumed to be stored as a string) of DataArray.

    Parameters
    ----------
    obj: xr.DataArray
        attributes of interest
    attr: str
        name of attributes
    dtype: object type, optional
        function will try to perform type(eval(attr)), default np.array
    args_parse: boolean, optional
        if True, function will try to return type(*eval(attr)), assuming attribute contains list
        of arguments (default: False)

    Returns
    -------
    parsed_arg: type defined by user
        parsed attribute, of type defined by arg type
    """
    assert hasattr(data_array, attr), f'frames do not contain attribute with name "{attr}'
    attr_obj = getattr(data_array, attr)
    if args_parse:
        return dtype(*eval(attr_obj))
    return dtype(eval(attr_obj))

def get_axes(cols, rows, resolution):
    """Retrieve a locally spaced axes for surface velocimetry results on the basis of resolution and row and
    col distances from the original frames

    Parameters
    ----------
    cols: list
        ints, columns, sampled from the original projected frames
    rows: list
        ints, rows, sampled from the original projected frames
    resolution: float
        resolution of original frames

    Returns
    -------
    obj : np.ndarray
        x-axis with origin at the left
    obj2 : np.ndarray
        y-axis with origin on the top

    """
    spacing_x = np.diff(cols[0])[0]
    spacing_y = np.diff(rows[:, 0])[0]
    x = np.linspace(
        resolution / 2 * spacing_x,
        (len(cols[0]) - 0.5) * resolution * spacing_x,
        len(cols[0]),
    )
    y = np.flipud(
        np.linspace(
            resolution / 2 * spacing_y,
            (len(rows[:, 0]) - 0.5) * resolution * spacing_y,
            len(rows[:, 0]),
        )
    )
    return x, y

def get_xs_ys(cols, rows, transform):
    """Computes rasters of x and y coordinates, based on row and column counts and a defined transform.

    Parameters
    ----------
    cols: list of ints
        column counts
    rows: list of ints
        row counts
    transform: np.ndarray (1D)
        rasterio compatible transform parameters

    Returns
    -------
    xs : np.ndarray (MxN)
        x-coordinates
    ys : np.ndarray (MxN)
        y-coordinates
    """
    xs, ys = xy(transform, rows, cols)
    xs, ys = np.array(xs), np.array(ys)
    return xs, ys

def get_lons_lats(xs, ys, src_crs, dst_crs=CRS.from_epsg(4326)):
    """Computes raster of longitude and latitude coordinates (default) of a certain raster set of coordinates in a local
    coordinate reference system. User can supply an alternative coordinate reference system if projection other than
    WGS84 Lat Lon is needed.

    Parameters
    ----------
    xs : np.ndarray (MxN)
        x-coordinates
    ys : np.ndarray (MxN)
        y-coordinates
    src_crs : int, dict or str
        Coordinate Reference System (of source coordinates). Accepts EPSG codes (int or str) proj (str or dict) or wkt
        (str).
    dst_crs : int, dict or str, optional
        Coordinate Reference System (of target coordinates). Accepts EPSG codes (int or str) proj (str or dict) or wkt
        (str). default: CRS.from_epsg(4326) for wGS84 lat-lon

    Returns
    -------
    lons : np.ndarray (MxN)
        longitude coordinates
    lats: np.ndarray (MxN)
        latitude coordinates
    """
    lons, lats = warp.transform(src_crs, dst_crs, xs.flatten(), ys.flatten())
    lons, lats = (
        np.array(lons).reshape(xs.shape),
        np.array(lats).reshape(ys.shape),
    )
    return lons, lats

def log_profile(X, z0, k_max, s0=0., s1=0.):
    """Returns values of a log-profile function

    Parameters
    ----------
    X: tuple with np.ndarrays
        (depth [m], distance to bank [m]) arrays of equal length
    z0: float
        depth with zero velocity [m]
    k_max: float
        maximum scale factor of log-profile function [-]
    s0: float, optional
        distance from bank (defaukt: 0.) where k equals zero (and thus velocity is zero) [m]
    s1: float, optional
        distance from bank (default: 0. meaning no difference over distance) where k=k_max (k cannot be larger than
        k_max) [m]

    Returns
    -------
    velocity : np.ndarray
        V values from log-profile, equal shape as arrays inside X [m s-1]
    """
    z, s = X
    k = k_max * np.minimum(np.maximum((s-s0)/(s1-s0), 0), 1)
    v = k*np.maximum(np.log(np.maximum(z, 1e-6)/z0), 0)
    return v

def mse(pars, func, X, Y):
    """mean of sum of squares between evaluation of function with provided parameters and X input, and Y as dependent variable.

    Parameters
    ----------
    pars : list or tuple
        parameter passed as *args to func
    func: function def
        receiving X and *pars as input and returning predicted Y as result
    X: tuple with lists or array-likes
        indepent variable(s).
    Y: list or array-like
        dependent variable, predicted by func

    Returns
    -------

    Y_pred : list or array-like
        predicted Y from X and pars by func
    """
    Y_pred = func(X, *pars)
    mse = np.sum((Y_pred - Y) ** 2)
    return mse

def neighbour_stack(array, stride=1, missing=-9999.):
    """Builds a stack of arrays from a 2-D input array, constructed by permutation in space using a provided stride.

    Parameters
    ----------
    array : np.ndarray (2D)
        any values (may contain NaN)
    stride : int, optional
        stride used to determine relevant neighbours (default: 1)
    missing : float, optional
        a temporary missing value, used to be able to convolve NaNs

    Returns
    -------
    obj : np.array (3D)
        stack of 2-D arrays, with strided neighbours (length 1st dim : (stride*2+1)**2 )
    """
    array[np.isnan(array)] = missing
    array_move = []
    for vert in range(-stride, stride+1):
        for horz in range(-stride, stride+1):
            conv_arr = np.zeros((abs(vert)*2+1, abs(horz)*2+1))
            _y = int(np.floor((abs(vert)*2+1)/2)) + vert
            _x = int(np.floor((abs(horz)*2+1)/2)) + horz
            conv_arr[_y, _x] = 1
            array_move.append(convolve2d(array, conv_arr, mode="same", fillvalue=np.nan))
    array_move = np.stack(array_move)
    # replace missings by Nan
    array_move[np.isclose(array_move, missing)] = np.nan
    return array_move

def optimize_log_profile(
        z,
        v,
        dist_bank=None,
        bounds=([0.001, 0.1], [-20, 20], [0., 5], [0., 100]),
        workers=2,
        popsize=100,
        updating="deferred",
        seed=0,
        **kwargs
):

    """optimize velocity log profile relation of v=k*max(z/z0) with k a function of distance to bank and k_max
    A differential evolution optimizer is used.

    Parameters
    ----------
    z : list
        depths [m]
    v : list
        surface velocities [m s-1]
    dist_bank : list
        distances to bank [m]
    **kwargs : keyword arguments for scipy.optimize.differential_evolution

    Returns
    -------
    pars : dict
        fitted parameters of log_profile {z_0, k_max, s0 and s1}
    """
    if dist_bank is None:
        dist_bank = np.inf(len(v))
    v = np.array(v)
    z = np.array(z)
    X = (z, dist_bank)
    Y = v
    result = differential_evolution(
        wrap_mse,
        args=(log_profile, X, Y),
        bounds=bounds,
        workers=workers,
        popsize=popsize,
        updating=updating,
        seed=seed,
        **kwargs
    )
    # unravel parameters
    z0, k_max, s0, s1 = result.x
    return {"z0": z0, "k_max": k_max, "s0": s0, "s1": s1}

def rotate_u_v(u, v, theta, deg=False):
    """Rotate u and v components of vector counter clockwise by an amount of rotation.

    Parameters
    ----------
    u : float, np.ndarray or xr.DataArray
        x-direction component of vector
    v : float, np.ndarray or xr.DataArray
        y-direction component of vector
    theta : float
        amount of counter clockwise rotation in radians or degrees (dependent on deg)
    deg : boolean, optional
        if True, theta is defined in degrees, otherwise radians (default: False)

    Returns
    -------
    u_rot : float, np.ndarray or xr.DataArray
        rotated x-direction component of vector
    v_rot : float, np.ndarray or xr.DataArray
        rotated y-direction component of vector
    """
    if deg:
        # convert to radians first
        theta = np.radians(theta)
    c, s = np.cos(theta), np.sin(theta)
    r = np.array(((c, -s), (s, c)))
    # compute rotations with dot-product
    u2 = r[0, 0] * u + r[0, 1] * v
    v2 = r[1, 0] * u + r[1, 1] * v
    return u2, v2

def velocity_fill(x, y, depth, v, groupby="quantile"):
    """Fill missing surface velocities using a velocity depth profile with

    Parameters
    ----------
    x : xr.DataArray (points)
        x-coordinates of bathymetry depths (ref. CRS)
    y : xr.DataArray (points)
        y-coordinates of bathymetry depths (ref. CRS)
    depth : xr.DataArray (points)
        depths [m]
    v : xr.DataArray (time, points)
        effective velocity at surface [m s-1]
    groupby: str, optional
        dimension over which data should be grouped, default: "quantile", dimension must exist in v, typically
        "quantile" or "time"

    Returns
    -------

    v_fill: xr.DataArray (quantile or time, points)
        filled surface velocities  [m s-1]
    """
    def fit(_v):
        pars = optimize_log_profile(depth[np.isfinite(_v).values], _v[np.isfinite(_v).values], dist_bank[np.isfinite(_v).values])
        _v[np.isnan(_v).values] = log_profile((depth[np.isnan(_v).values], dist_bank[np.isnan(_v).values]), **pars)
        # enforce that velocities are zero with zero depth
        _v[depth<=0] = 0.
        return np.maximum(_v, 0)

    z_dry = depth <= 0
    dist_bank = np.array([(((x[z_dry] - _x) ** 2 + (y[z_dry] - _y) ** 2) ** 0.5).min() for _x, _y, in zip(x, y)])
    # per time slice or quantile, fill missings
    v_group = copy.deepcopy(v).groupby(groupby)
    return v_group.map(fit)

def wrap_mse(pars_iter, *args):
    return mse(pars_iter, *args)

def xy_equidistant(x, y, distance, z=None):
    """Transforms a set of ordered in space x, y (and z if provided) coordinates into x, y (and z) coordinates with equal
    1-dimensional distance between them using piece-wise linear interpolation. Extrapolation is used for the last point
    to ensure the range of points covers at least the full range of x, y coordinates.

    Parameters
    ----------
    x : np.ndarray (1D)
        set of (assumed ordered) x-coordinates
    y : np.ndarray (1D)
        set of (assumed ordered) x-coordinates
    distance : float
        user demanded distance between equidistant samples measured in cumulated 1-dimensional distance from xy
        origin (first point)
    z : np.ndarray (1D), optional
        set of (assumed ordered) z-coordinates (default: None, meaning only x, y interpolated points are returned)

    Returns
    -------
    x_sample : np.ndarray (1D)
        interpolated x-coordinates for x, y, s (distance from first point), z
    y_sample : np.ndarray (1D)
        interpolated y-coordinates
    s_sample : np.ndarray (1D)
        interpolated s-coordinates, s being piece-wise linear distance from first point
    z_sample : np.ndarray (1D), optional
        interpolated z-coordinates (only returned if z is not None):
    """
    # estimate cumulative distance between points, starting with zero
    x_diff = np.concatenate((np.array([0]), np.diff(x)))
    y_diff = np.concatenate((np.array([0]), np.diff(y)))
    s = np.cumsum((x_diff ** 2 + y_diff ** 2) ** 0.5)

    # create interpolation functions for x and y coordinates
    f_x = interp1d(s, x, fill_value="extrapolate")
    f_y = interp1d(s, y, fill_value="extrapolate")

    # make equidistant samples
    s_sample = np.arange(s.min(), np.ceil((1 + s.max() / distance) * distance), distance)

    # interpolate x and y coordinates
    x_sample = f_x(s_sample)
    y_sample = f_y(s_sample)
    if z is None:
        return x_sample, y_sample, s_sample
    else:
        f_z = interp1d(s, z, fill_value="extrapolate")
        z_sample = f_z(s_sample)
        return x_sample, y_sample, z_sample, s_sample

def xy_angle(x, y):
    """Determine angle between x, y points.

    Parameters
    ----------
    x : np.ndarray (1D)
        set of (assumed ordered) x-coordinates
    y : np.ndarray (1D)
        set of (assumed ordered) x-coordinates

    Returns
    -------
    angle : np.ndarray (1D)
        angle between the point left and right of the point under consideration. The most left and right coordinates
        are based on the first and last 2 points respectively
    """
    angles = np.zeros(len(x))
    angles[1:-1] = np.arctan2(x[2:] - x[0:-2], y[2:] - y[0:-2])
    angles[0] = np.arctan2(x[1] - x[0], y[1] - y[0])
    angles[-1] = np.arctan2(x[-1] - x[-2], y[-1] - y[-2])
    return angles

def xy_to_perspective(x, y, resolution, M, reverse_y=None):
    """
    Back transform local meters-from-top-left coordinates from frame to original perspective of camera using M
    matrix, belonging to transformation from orthographic to local.

    Parameters
    ----------
    x : np.ndarray (1D)
        axis of x-coordinates in local projection with origin top-left, to be backwards projected
    y : np.ndarray (1D)
        axis of y-coordinates in local projection with origin top-left, to be backwards projected
    resolution : float
        resolution of original projected frames coordinates of x and y
    M : np.ndarray
        2x3 transformation matrix (generated with cv2.getPerspectiveTransform)

    Returns
    -------
    xp : np.ndarray (2D)
        perspective columns with shape len(y), len(x)
    yp : np.ndarray (2D)
        perspective rows with shape len(y), len(x)
    """
    cols, rows = x / resolution - 0.5, y / resolution - 0.5
    if reverse_y is not None:
        rows = reverse_y - rows
    # make list of coordinates, compatible with cv2.perspectiveTransform
    coords = np.float32([np.array([cols.flatten(), rows.flatten()]).transpose([1, 0])])
    coords_trans = cv2.perspectiveTransform(coords, M)
    xp = coords_trans[0][:, 0].reshape(cols.shape)
    yp = coords_trans[0][:, 1].reshape(cols.shape)
    return xp, yp

def xy_transform(x, y, crs_from, crs_to):
    """transforms set of x and y coordinates from one CRS to another

    Parameters
    ----------
    x : np.ndarray
        x-coordinates in crs_from
    y : np.ndarray
        y-coordinates in crs_from
    crs_from : int, dict or str, optional
        Coordinate Reference System (source). Accepts EPSG codes (int or str) proj (str or dict) or wkt (str).
    crs_to : int, dict or str, optional
        Coordinate Reference System (destination). Accepts EPSG codes (int or str) proj (str or dict) or wkt (str).

    Returns
    -------
    x_trans : np.ndarray
        x-coordinates transformed
    y_trans : np.ndarray
        y-coordinates transformed
    """
    transform = Transformer.from_crs(crs_from, crs_to, always_xy=True)
    # transform dst coordinates to local projection
    x_trans, y_trans = transform.transform(x, y)
    if np.all(np.isinf(x_trans)):
        raise ValueError("Transformation did not give valid results, please check if the provided crs of input coordinates is correct.")
    return transform.transform(x, y)


import pytest

from ai_ghostfunctions import keywords

@pytest.mark.parametrize(
    "kw,v",
    [
        (keywords.ASSISTANT, "assistant"),
        (keywords.USER, "user"),
        (keywords.SYSTEM, "system"),
        (keywords.CHAT_COMPLETION, "chat completion"),
        (keywords.COMPLETION, "completion"),
    ],
)
def test_keyword_value(kw: str, v: str) -> None:
    assert kw == v


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on 2/21/22

@author: moinSebi

"""

import argparse
import logging

logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p:')
logging.getLogger().setLevel(logging.INFO)
"""
**Script description**

Merging unique traversals of the same bubble
Input: Uniq traversal file from gSV -u and the corresponding GFA

Output:
    - File with the follwing stuff
        - 1. Bubbleid
        - 2. Group id
        - 3. Traversals

"""

def readTrans(ftrans):
    """

    Args:
        ftrans: file trans uniq input (s. gSV output)

    Returns:
        t: dict(bubbleid -> [[traversalid, "path"[node+,node2-]]
    """

    logging.info("Read trans file")
    t = dict()
    with open(ftrans) as file:
        for lines in file.readlines():
            lsplit = lines.split()
            if lsplit[0] in t:
                t[lsplit[0]].append([lsplit[1], lsplit[2]])
            else:
                t[lsplit[0]] = [[lsplit[1], lsplit[2]]]
    return t

def readGFA(fgfa):
    """

    Args:
        fgfa: file gfa input

    Returns:
        edges: Edges of the graph (Set((id1, dir1, id2, dir2))
        nodes: Nodes (Dict (id -> Seq)
        paths: Paths (Dict (name -> List)

    """
    logging.info("Read gfa file")
    # Read node, edge and path information
    edges = set()
    paths = dict()
    nodes = dict()
    with open(fgfa) as file:
        for x in file.readlines():
            if x.startswith("L"):
                l = x.split()
                o = (l[1], l[2], l[3], l[4])
                edges.add(o)
            elif x.startswith("S"):
                l = x.split()
                nodes[l[1]] = l[2]
            elif x.startswith("P"):

                l = x.split()
                if not l[1].startswith("Con"):
                    paths[l[1]] = [x for x in l[2].split(",")]
    return nodes, edges, paths

def getLen(s, nodes):
    """

    Args:
        s: tpath (transpath)
        nodes: nodes (from GFA)

    Returns:
        ll: Sum of all nodes in path
    """

    if len(s) == 0 or s == [""]:
        return 0
    ll = 0
    for x in s:
        ll += len(nodes[x])
    return ll

def inter(l1, l2):
    """
    Intersection of two paths
    Returns: Length of intersection, path1, path2
    """
    ls1 = set(l1.split(","))
    ls2 = set(l2.split(","))
    o = ls1.intersection(ls2)
    return [len(o), len(ls1), len(ls2)]

def inter2(l1, l2, nodes):
    """
    Intersection of two paths
    Returns: Length of intersection, path1, path2
    """
    #ls1 = set(l1.split(","))
    ls1= set([x[:-1] for x in l1.split(",")])

    #ls2 = set(l2.split(","))
    ls2 = set([x[:-1] for x in l2.split(",")])

    o = ls1.intersection(ls2)
    ls1priv = getLen(list(ls1 - o), nodes)
    ls1p = getLen(list(ls1), nodes)

    ls2priv = getLen(list(ls2 - o), nodes)
    ls2p = getLen(list(ls2), nodes)
    olen = getLen(list(o), nodes)
    return [ls1priv, ls1p, ls2priv, ls2p, olen]

def check2(t, nodes, intersection):
    """

    Args:
        t: trans input (s. above)
        nodes: nodes (gfa)
        intersection: Fraction of intersection
        diff: bp difference

   Help:

   Returns:
        bubble, group, all traversal (first is the representative)
    """
    logging.info("Clustering")

    result = dict()
    count = 0
    for bubble_id, traverals in t.items():
        groups = dict()
        # print([v[1]+[getLen(v[0][1], nodes)]])
        groups[0] = [traverals[0] + [getLen([x1[:-1] for x1 in traverals[0][1].split(",")], nodes)]]
        group_count = 1
        for x in traverals[1:]:
            id = -1
            trig = False;
            for group_id, trav in groups.items():
                glen = getLen([x1[:-1] for x1 in x[1].split(",")], nodes)
                node_intersection = inter2(x[1], trav[0][1], nodes)
                if (node_intersection[0]/node_intersection[1] < intersection) and (node_intersection[2]/node_intersection[3] < intersection):
                    if glen > trav[0][2]:
                        trig = True
                    id = group_id
                    break
            if id == -1:
                groups[group_count] = [x + [getLen([x1[:-1] for x1 in x[1].split(",")], nodes)]]
                group_count += 1
            else:
                if trig:
                    groups[id].insert(0, x + [getLen([x1[:-1] for x1 in x[1].split(",")], nodes)])
                else:
                    groups[id].append(x + [getLen([x1[:-1] for x1 in x[1].split(",")], nodes)])

        result[bubble_id] = groups
        count += 1;
    return result

def add_stats(data, nodes):
    logging.info("Add stats")

    # bubble_id, dict -> groups

    for k,v in data.items():

        # group -> intervals (id, nodes, len)
        for key, val in v.items():
            j = []
            for x in val:
                node_intersection = inter2(x[1], val[0][1], nodes)
                j.append(node_intersection[0]/node_intersection[1])
                x.append(node_intersection[0]/node_intersection[1])

def some_stats(data, stats) -> None:
    c = 0
    for k, v in data.items():
        c += len(v)
    c1 = 0
    for k, v in stats.items():
        c1 += len(v);
    logging.info("Number of traversals: {}".format(c1))
    logging.info("Number of bubbles: {}".format(len(data)))
    logging.info("Number of clusters: {}".format(c))

def writeFile(fout, data):
    """

    Args:
        fout: file output name
        data:

    Returns:
        - file
    """

    logging.info("Write files")
    with open(fout, "w") as file:
        for k, v in data.items():
            for k2, v2 in v.items():
                na = [x[0] for x in v2]
                file.write("{}\t{}\t{}\t{}\n".format(k, k2, v2[0][1], ",".join(na)))

def writeFile2(fout, data):
    """

    Args:
        fout: file output name
        data:

    Returns:
        - file
    """

    logging.info("Write files2")
    with open(fout, "w") as file:
        for k, v in data.items():
            for k2, v2 in v.items():
                na = [str(x[0]) for x in v2]
                na2 = [str(x[3]) for x in v2]
                file.write("{}\t{}\t{}\t{}\t{}\n".format(k, k2, v2[0][1], ",".join(na), ",".join(na2)))

if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    parser.add_argument("-g", "--gfa", help="gfa file", required=True)
    parser.add_argument("-u", "--uniq", help = "*traversal.unique.bubble.bed file ", required=True)
    parser.add_argument("-o", "--out", help = "output file name ", required=True)
    parser.add_argument("-i", "--intersection", help = "Fraction of private/total sequence", default=0.3)
    args = parser.parse_args()

    nodes, edges, paths = readGFA(args.gfa)
    stats = readTrans(args.uniq)

    interf = float(args.intersection)

    result = check2(stats, nodes, interf)
    add_stats(result, nodes)
    some_stats(result, stats)
    writeFile2(args.out, result)


import datetime
import json
import os

from flask import Flask, render_template, redirect
from flask_ngrok import run_with_ngrok
from flask_restful import Api, abort
from werkzeug.utils import secure_filename
from wtforms.validators import DataRequired

from data.category import Category
from data.game import Game
from flask import redirect, render_template
from flask_login import logout_user, login_required, login_user, LoginManager, current_user

from data import db_session, games_resources

from data.user import User
from forms.game import GameForm
from forms.login_form import LoginForm
from forms.profile import ProfileForm
from forms.search import SearchForm
from forms.user import RegisterForm

def page_not_found(e):
    return render_template('404.html'), 404

app = Flask(__name__)
run_with_ngrok(app)
app.register_error_handler(404, page_not_found)
app.config['SECRET_KEY'] = 'yandexlyceum_secret_key'
app.config['PERMANENT_SESSION_LIFETIME'] = datetime.timedelta(
    days=365
)
UPLOAD_PATH = 'static/data'
db_session.global_init("database.db")
login_manager = LoginManager()
login_manager.init_app(app)
api = Api(app)
api.add_resource(games_resources.GamesListResource, '/api/games')
api.add_resource(games_resources.GamesSearchResource, '/api/games/search/<game_title>')
api.add_resource(games_resources.GameResource, '/api/game/<int:game_id>')
api.add_resource(games_resources.UserEmailPremiumResource, '/api/user/<user_email>')

@app.route('/', methods=["GET", "POST"])
def index():
    db_sess = db_session.create_session()
    games = db_sess.query(Game).all()
    form = SearchForm()
    if form.validate_on_submit():
        return redirect('/search/{}'.format(form.search.data))
    print(current_user if current_user else "Не авторизаван")
    return render_template("main.html", games=games, form=form)

@login_manager.user_loader
def load_user(user_id):
    db_sess = db_session.create_session()
    return db_sess.query(User).get(user_id)

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        db_sess = db_session.create_session()
        user = db_sess.query(User).filter(User.email == form.email.data).first()
        if user and user.check_password(form.password.data):
            login_user(user, remember=form.remember_me.data)
            return redirect("/")
        return render_template('login2.html', message="Wrong login or password", form=form)
    return render_template('login2.html', title='Authorization', form=form)

@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect("/")

@app.route('/register', methods=['GET', 'POST'])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        if form.password.data != form.password_again.data:
            return render_template('register.html', title='Регистрация',
                                   form=form,
                                   message="Пароли не совпадают")
        db_sess = db_session.create_session()
        if db_sess.query(User).filter(User.email == form.email.data).first():
            return render_template('register.html', title='Регистрация',
                                   form=form,
                                   message="Такой пользователь уже есть")
        user = User(
            email=form.email.data,
            nickname=form.nickname.data,
            is_premium=form.premium.data

        )
        user.set_password(form.password.data)
        db_sess.add(user)
        db_sess.commit()
        return redirect('/login')
    return render_template('register.html', title='Регистрация', form=form)

@app.route('/addgame', methods=['GET', 'POST'])
@login_required
def add_game():
    form = GameForm()
    if form.validate_on_submit():
        db_sess = db_session.create_session()
        if db_sess.query(Game).filter(Game.title == form.title.data).all():
            return render_template('add_game.html', title='Дбавление Игры',
                                   form=form, message="Игра с таким названием уже существует")
        print(form.image_url.data, ":", form.image.check_validators([DataRequired()]))
        if form.image_url.data == "" and form.image.check_validators([DataRequired()]):
            return render_template('add_game.html', title='Добавление Игры',
                                   form=form, message="Нет картинки")
        game = Game(
            title=form.title.data,
            short_description=form.short_description.data,
            version=form.version.data,
            description=form.description.data,
            need_premium=form.need_premium.data,
            category_id=form.category.data
        )
        if form.image_url.data:
            game.image = form.image_url.data
        else:
            f = form.image.data
            filename = secure_filename(f.filename)
            img_path = os.path.join(
                UPLOAD_PATH, 'img', filename
            )
            f.save(img_path)
            game.image = '\\' + img_path

        f = form.url.data
        filename = secure_filename(f.filename)
        torrent_path = os.path.join(
            UPLOAD_PATH, 'torrent', filename
        )
        f.save(torrent_path)
        game.url = '\\' + torrent_path
        game.user_id = current_user.id
        db_sess = db_session.create_session()
        db_sess.add(game)
        db_sess.commit()
        return redirect('/addgame')
    return render_template('add_game.html', title='Регистрация Работы', form=form)

def n_to_br(string) -> str:
    s = str(string)
    print(list(s))
    s.replace("\n", "<br>")
    print(s)
    return s

@app.route('/aboutgame/<int:game_id>')
def about_game(game_id):
    db_sess = db_session.create_session()
    game = db_sess.query(Game).get(game_id)
    category = db_sess.query(Category).get(game.category_id)
    print(category)
    if game is None:
        abort(404)
    return render_template('about_game.html', game=game, category=category.title, n_to_br=n_to_br)

@app.route('/l')
def d():
    return render_template('index.html')

@app.route('/profile', methods=["GET", "POST"])
@login_required
def profile():
    form = ProfileForm()
    if form.validate_on_submit():
        db_sess = db_session.create_session()
        user = db_sess.query(User).get(current_user.id)
        if form.nickname.data:
            user.nickname = form.nickname.data
        if form.avatar.data.filename:
            f = form.avatar.data
            filename = secure_filename(f.filename)
            img_path = os.path.join(
                UPLOAD_PATH, 'img', filename
            )
            f.save(img_path)
            user.avatar = '\\' + img_path
        if form.avatar_url.data:
            user.avatar = form.avatar_url.data
        db_sess.commit()

    db_sess = db_session.create_session()
    user = db_sess.query(User).get(current_user.id)
    user_games = db_sess.query(Game).filter(Game.user_id == current_user.id)
    return render_template('profile.html', user=user, games=user_games, form=form)

@app.route('/search/category/<int:category_id>', methods=['GET', 'POST'])
def find_category(category_id):
    form = SearchForm()
    if form.validate_on_submit():
        return redirect('/search/{}'.format(form.search.data))
    db_sess = db_session.create_session()
    games = db_sess.query(Game).filter(Game.category_id == category_id).all()
    return render_template("main.html", games=games, form=form)

@app.route('/search/<game_title>', methods=['GET', 'POST'])
def search(game_title):
    form = SearchForm()
    if form.validate_on_submit():
        return redirect('/search/{}'.format(form.search.data))
    else:
        session = db_session.create_session()
        games = session.query(Game).all()
        dct = {}
        for game in games:
            dct[game.id] = 0
            i = 0
            if game_title.lower() in game.title.lower():
                dct[game.id] += len(game_title)
            if len(game_title) == len(game.title):
                dct[game.id] += len(game_title) // 2
            for char in zip(game.title.lower(), game_title.lower()):
                if i > len(game_title):
                    break
                if char[0] == char[1]:
                    dct[game.id] += 1
                i += 1
        lst = []
        for key, value in dct.items():
            lst.append((key, value))
        lst.sort(key=lambda x: x[1], reverse=True)

        game = session.query(Game).filter(Game.id.in_(
            [x[0] for x in
             list(filter(lambda x: lst[0][1] - 2 <= x[1] <= lst[0][1] + 2, lst))])).all()
        return render_template("main.html", games=game, form=form, value=game_title)

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


import string
import json
import random
from string import Template
import os
from collections import Counter, defaultdict
import settings
from tqdm import tqdm

class GeneratorBasic:
    def __init__(self, args, taskconfig, data_readers):
        self.idx=0
        self.args = args
        self.taskconfig = taskconfig
        if 'max_data' in self.taskconfig:
            self.max_data = self.taskconfig['max_data']
        else:
            self.max_data = args.max_data
        self.output_folder = args.tasks_output_folder
        self.out_file = self.taskconfig['task_name']
        self.data_readers = data_readers
        self.examples = []

    def generate_data(self):
        print('generating basic')

    def sample_and_write(self, instance_and_instructions):
        if type(instance_and_instructions) is None:
            print('Please refactor code so that the sample_and_write function performs sampling and writing')
        sequences, instruction_dict = instance_and_instructions
        print('len datareader_sequences Instances', len(sequences))
        if self.args.data_sample_type=='individual':
            data_dict_all = defaultdict(list)
            for dp in sequences:
                # import pdb;pdb.set_trace()
                data_dict_all[dp['dataset']].append(dp)
            # for d, dataset_reader in enumerate(self.data_readers):
            for dataname in data_dict_all.keys():
                datareader_sequences = data_dict_all[dataname]
                random.shuffle(datareader_sequences)
                # print('len(sequences)', len(datareader_sequences))
                datareader_sequences_sampled = random.sample(datareader_sequences, min(len(datareader_sequences), self.max_data))
                if 'Instances' not in instruction_dict: instruction_dict['Instances'] = []
                instruction_dict['Instances'] += datareader_sequences_sampled[:]
                # sequences = []

        elif self.args.data_sample_type=='common':
            random.shuffle(sequences)
            sequences = random.sample(sequences, min(len(sequences), self.max_data))
            instruction_dict['Instances'] = sequences

        else:# self.args.data_sample_type=='max':
            instruction_dict['Instances'] = sequences

        for s in sequences[-5:]:
            # print(s)
            pass

        print('writing to', self.out_file, 'size of data', len(sequences))

        with open(self.output_folder+'/'+self.out_file+'.json', 'w') as f:
            f.write(json.dumps(instruction_dict, indent=2))

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

    def __getitem__(self, idx):
        return self.examples[idx]


from collections import deque

def bfs(graph, startNode, visited):
    queue = deque([startNode])
    visited = list()

    while queue:
        node = queue.popleft()

        if node not in visited:
            visited.append(node)
            queue.extend(graph[node])
    return visited

def dfs(graph, startNode, visited):
    stack = deque([startNode])
    visited = list()

    while stack:
        node = stack.pop()

        if node not in visited:
            visited.append(node)
            stack.extend(reversed(graph[node]))
    return visited

n, m, v = map(int,input().split())

graph = [[] for i in range(n + 1)]

for _ in range(m):
    i, j = map(int, input().split())
    graph[i].append(j)
    graph[j].append(i)

print(graph)
print(dfs(graph, v, [False] * (n + 1)))
print(bfs(graph, v, [False] * (n + 1)))