import json
from datetime import datetime
from io import BytesIO

import face_recognition
import requests
from picamera2 import Picamera2
import RPi.GPIO as GPIO
import time
from app.mqtt_client import publish_to_mqtt
from app.util.files_utils import upload_image
from config import Config

# Configurar los pines GPIO
GPIO.setmode(GPIO.BCM)

TRIG = 23  # Pin 16 como TRIG
ECHO = 24  # Pin 18 como ECHO

# Única instancia de Picamera2
picam2 = Picamera2()

def take_picture(camera):
    try:
        camera_config = camera.create_still_configuration(main={"size": (1920, 1080)})
        camera.configure(camera_config)
        camera.start()
        time.sleep(2)
        picture_path = "app/static/images/last_photo.jpg"
        camera.capture_file(picture_path)
        check_for_face_and_upload(picture_path)
    finally:
        camera.stop()

def check_for_face_and_upload(picture_path):
    from app import db
    from app.models import User, FailedLoginAttempt
    sent_image = face_recognition.load_image_file(picture_path)
    sent_encodings = face_recognition.face_encodings(sent_image)
    if not sent_encodings:
        print("No se encontró una cara en la imagen")
        return

    sent_encoding = sent_encodings[0]

    face_found = False

    # Cargar la imagen de la persona
    print("Cargando imagen de persona")
    image_url = upload_image('last_photo.jpg')

    for user in User.query.all():
        user_image_url = user.image_url
        response = requests.get(user_image_url)
        user_image = face_recognition.load_image_file(BytesIO(response.content))

        user_encodings = face_recognition.face_encodings(user_image)
        if not user_encodings:
            # No se encontró rostro en la imagen del usuario
            continue

        user_encoding = user_encodings[0]
        results = face_recognition.compare_faces([user_encoding], sent_encoding)
        if results[0]:
            face_found = True
            print(f"Se encontró una coincidencia con {user.name}")

    if not face_found:
        print("No se encontró una coincidencia con ningún usuario")
        failed_attempt = FailedLoginAttempt(attempted_url=image_url)
        db.session.add(failed_attempt)
        db.session.commit()

        attempt_data = {
            "url": image_url,
        }

        attempt_data2 = {
            "time": datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
        }

        publish_to_mqtt(Config.MQTT_TOPIC, json.dumps(attempt_data))
        publish_to_mqtt(Config.MQTT_TOPIC, json.dumps(attempt_data2))

def measure_distance():
    GPIO.setup(TRIG, GPIO.OUT)
    GPIO.setup(ECHO, GPIO.IN)

    GPIO.output(TRIG, False)
    time.sleep(2)

    GPIO.output(TRIG, True)
    time.sleep(0.00001)
    GPIO.output(TRIG, False)

    start_time = time.time()

    while GPIO.input(ECHO) == 0:
        start_time = time.time()

    while GPIO.input(ECHO) == 1:
        end_time = time.time()

    pulse_duration = end_time - start_time
    distance = pulse_duration * 17150
    distance = round(distance, 2)

    return distance

def initialize_photo_process():
    try:
        while True:
            distance = measure_distance()
            print(f"Distance: {distance} cm")

            # Define la distancia prudente para tomar la foto
            if distance < 100:  # por ejemplo, menos de 100 cm
                take_picture(picam2)
                # Tiempo de espera después de tomar una foto
                time.sleep(10)
            else:
                # Tiempo de espera para la próxima medición de distancia
                time.sleep(1)
    except KeyboardInterrupt:
        print("Stopping distance measurement...")
    finally:
        GPIO.cleanup()


from warnings import filterwarnings

filterwarnings("ignore")

import os
import pickle
import random
import sys

import numpy as np
import torch
import torch.backends.cudnn as cudnn
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torchvision
import torchvision.models as models
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score
from sklearn.mixture import GaussianMixture

import dataloader_clothing1M as dataloader
from preset_parser import *

if __name__ == "__main__":
    args = parse_args("./presets.json")
    logs = open(os.path.join(args.checkpoint_path, "saved", "metrics.log"), "a")

    random.seed(args.seed)
    torch.manual_seed(args.seed)
    torch.cuda.manual_seed_all(args.seed)

    # Training
    def train(epoch, net, net2, optimizer, labeled_trainloader, unlabeled_trainloader):
        net.train()
        net2.eval()  # fix one network and train the other

        unlabeled_train_iter = iter(unlabeled_trainloader)
        num_iter = (len(labeled_trainloader.dataset) // args.batch_size) + 1
        for (
            batch_idx,
            (
                inputs_x,
                inputs_x2,
                inputs_x3,
                inputs_x4,
                labels_x,
                w_x,
            ),
        ) in enumerate(labeled_trainloader):
            try:
                inputs_u, inputs_u2, inputs_u3, inputs_u4 = unlabeled_train_iter.next()
            except:
                unlabeled_train_iter = iter(unlabeled_trainloader)
                inputs_u, inputs_u2, inputs_u3, inputs_u4 = unlabeled_train_iter.next()
            batch_size = inputs_x.size(0)

            # Transform label to one-hot
            labels_x = torch.zeros(batch_size, args.num_class).scatter_(
                1, labels_x.view(-1, 1), 1
            )
            w_x = w_x.view(-1, 1).type(torch.FloatTensor)

            inputs_x, inputs_x2, inputs_x3, inputs_x4, labels_x, w_x = (
                inputs_x.cuda(),
                inputs_x2.cuda(),
                inputs_x3.cuda(),
                inputs_x4.cuda(),
                labels_x.cuda(),
                w_x.cuda(),
            )
            inputs_u, inputs_u2, inputs_u3, inputs_u4 = (
                inputs_u.cuda(),
                inputs_u2.cuda(),
                inputs_u3.cuda(),
                inputs_u4.cuda(),
            )

            with torch.no_grad():
                # label co-guessing of unlabeled samples
                outputs_u_1 = net(inputs_u3)
                outputs_u_2 = net(inputs_u4)
                outputs_u_3 = net2(inputs_u3)
                outputs_u_4 = net2(inputs_u4)

                pu = (
                    torch.softmax(outputs_u_1, dim=1)
                    + torch.softmax(outputs_u_2, dim=1)
                    + torch.softmax(outputs_u_3, dim=1)
                    + torch.softmax(outputs_u_4, dim=1)
                ) / 4
                ptu = pu ** (1 / args.T)  # temparature sharpening

                targets_u = ptu / ptu.sum(dim=1, keepdim=True)  # normalize
                targets_u = targets_u.detach()

                # label refinement of labeled samples
                outputs_x_1 = net(inputs_x3)
                outputs_x_2 = net(inputs_x4)

                px = (
                    torch.softmax(outputs_x_1, dim=1)
                    + torch.softmax(outputs_x_2, dim=1)
                ) / 2
                px = w_x * labels_x + (1 - w_x) * px
                ptx = px ** (1 / args.T)  # temparature sharpening

                targets_x = ptx / ptx.sum(dim=1, keepdim=True)  # normalize
                targets_x = targets_x.detach()

            # mixmatch
            l = np.random.beta(args.alpha, args.alpha)
            l = max(l, 1 - l)

            all_inputs = torch.cat([inputs_x, inputs_x2, inputs_u, inputs_u2], dim=0)
            all_targets = torch.cat([targets_x, targets_x, targets_u, targets_u], dim=0)

            idx = torch.randperm(all_inputs.size(0))

            input_a, input_b = all_inputs, all_inputs[idx]
            target_a, target_b = all_targets, all_targets[idx]

            mixed_input = (
                l * input_a[: batch_size * 2] + (1 - l) * input_b[: batch_size * 2]
            )
            mixed_target = (
                l * target_a[: batch_size * 2] + (1 - l) * target_b[: batch_size * 2]
            )

            logits = net(mixed_input)

            Lx = -torch.mean(
                torch.sum(F.log_softmax(logits, dim=1) * mixed_target, dim=1)
            )

            # regularization
            prior = torch.ones(args.num_class) / args.num_class
            prior = prior.cuda()
            pred_mean = torch.softmax(logits, dim=1).mean(0)
            penalty = torch.sum(prior * torch.log(prior / pred_mean))

            loss = Lx + penalty

            # compute gradient and do SGD step
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            sys.stdout.write("\r")
            sys.stdout.write(
                "Clothing1M | Epoch [%3d/%3d] Iter[%3d/%3d]\t  Labeled loss: %.4f "
                % (epoch, args.num_epochs - 1, batch_idx + 1, num_iter, Lx.item())
            )
            sys.stdout.flush()

        sys.stdout.write("\r")
        sys.stdout.flush()

    def warmup(net, optimizer, dataloader):
        net.train()
        for batch_idx, (inputs, labels, path) in enumerate(dataloader):
            inputs, labels = inputs.cuda(), labels.cuda()
            optimizer.zero_grad()
            outputs = net(inputs)
            loss = CEloss(outputs, labels)

            penalty = conf_penalty(outputs)
            L = loss + penalty
            L.backward()
            optimizer.step()

            sys.stdout.write("\r")
            sys.stdout.write(
                "|Warm-up: Iter[%3d/%3d]\t CE-loss: %.4f  Conf-Penalty: %.4f"
                % (batch_idx + 1, args.num_batches, loss.item(), penalty.item())
            )
            sys.stdout.flush()

    def val(net, val_loader, k):
        net.eval()
        all_targets = []
        all_predicted = []
        with torch.no_grad():
            for batch_idx, (inputs, targets) in enumerate(val_loader):
                inputs, targets = inputs.cuda(), targets.cuda()
                outputs = net(inputs)
                _, predicted = torch.max(outputs, 1)

                all_targets += targets.tolist()
                all_predicted += predicted.tolist()
        accuracy = accuracy_score(all_targets, all_predicted)
        precision = precision_score(all_targets, all_predicted, average="weighted")
        recall = recall_score(all_targets, all_predicted, average="weighted")
        f1 = f1_score(all_targets, all_predicted, average="weighted")
        print("\n| Validation\t Net%d  Acc: %.2f%%" % (k, accuracy * 100))
        if accuracy > best_acc[k - 1]:
            best_acc[k - 1] = accuracy
            print("| Saving Best Net%d ..." % k)
            save_point = os.path.join(
                args.checkpoint_path, "saved", args.preset + ".net%d.pth.tar" % (k)
            )
            torch.save(net.state_dict(), save_point)
        return accuracy, precision, recall, f1

    def test(net1, net2, test_loader):
        net1.eval()
        net2.eval()
        correct = 0
        total = 0
        all_targets = []
        all_predicted = []
        with torch.no_grad():
            for batch_idx, (inputs, targets) in enumerate(test_loader):
                inputs, targets = inputs.cuda(), targets.cuda()
                outputs1 = net1(inputs)
                outputs2 = net2(inputs)
                outputs = outputs1 + outputs2
                _, predicted = torch.max(outputs, 1)

                all_targets += targets.tolist()
                all_predicted += predicted.tolist()

        accuracy = accuracy_score(all_targets, all_predicted)
        precision = precision_score(all_targets, all_predicted, average="weighted")
        recall = recall_score(all_targets, all_predicted, average="weighted")
        f1 = f1_score(all_targets, all_predicted, average="weighted")
        results = (
            "Final Metrics, Accuracy: %.3f, Precision: %.3f, Recall: %.3f, F1: %.3f"
            % (
                accuracy * 100,
                precision * 100,
                recall * 100,
                f1 * 100,
            )
        )
        print("\n" + results + "\n")
        logs.write(results + "\n")
        logs.flush()

    def eval_train(epoch, model):
        model.eval()
        num_samples = args.num_batches * args.batch_size
        losses = torch.zeros(num_samples)
        paths = []
        n = 0
        with torch.no_grad():
            for batch_idx, (inputs, targets, path) in enumerate(eval_loader):
                inputs, targets = inputs.cuda(), targets.cuda()
                outputs = model(inputs)
                loss = CE(outputs, targets)
                for b in range(inputs.size(0)):
                    losses[n] = loss[b]
                    paths.append(path[b])
                    n += 1
                sys.stdout.write("\r")
                sys.stdout.write("| Evaluating loss Iter %3d\t" % (batch_idx))
                sys.stdout.flush()

        losses = (losses - losses.min()) / (losses.max() - losses.min())
        losses = losses.reshape(-1, 1)
        gmm = GaussianMixture(n_components=2, max_iter=10, reg_covar=5e-4, tol=1e-2)
        gmm.fit(losses)
        prob = gmm.predict_proba(losses)
        prob = prob[:, gmm.means_.argmin()]
        return prob, paths

    class NegEntropy(object):
        def __call__(self, outputs):
            probs = torch.softmax(outputs, dim=1)
            return torch.mean(torch.sum(probs.log() * probs, dim=1))

    def create_model(devices=[0]):
        model = models.resnet50(pretrained=True)
        model.fc = nn.Linear(2048, args.num_class)
        model = model.cuda()
        model = torch.nn.DataParallel(model, device_ids=devices).cuda()
        return model

    loader = dataloader.clothing_dataloader(
        root=args.data_path,
        batch_size=args.batch_size,
        warmup_batch_size=args.warmup_batch_size,
        num_workers=args.num_workers,
        num_batches=args.num_batches,
        augmentation_strategy=args,
    )

    print("| Building net")
    devices = range(torch.cuda.device_count())
    net1 = create_model(devices)
    net2 = create_model(devices)
    cudnn.benchmark = True

    optimizer1 = optim.SGD(
        net1.parameters(), lr=args.learning_rate, momentum=0.9, weight_decay=1e-3
    )
    optimizer2 = optim.SGD(
        net2.parameters(), lr=args.learning_rate, momentum=0.9, weight_decay=1e-3
    )
    best_acc = [0, 0]

    if args.pretrained_path != "":
        with open(args.pretrained_path + f"/saved/{args.preset}.pkl", "rb") as p:
            unpickled = pickle.load(p)
        net1.load_state_dict(unpickled["net1"])
        net2.load_state_dict(unpickled["net2"])
        optimizer1.load_state_dict(unpickled["optimizer1"])
        optimizer2.load_state_dict(unpickled["optimizer2"])
        best_acc = unpickled["best_acc"]
        epoch = unpickled["epoch"] + 1
    else:
        epoch = 0

    CE = nn.CrossEntropyLoss(reduction="none")
    CEloss = nn.CrossEntropyLoss()
    conf_penalty = NegEntropy()

    while epoch < args.num_epochs:
        lr = args.learning_rate
        if epoch >= args.lr_switch_epoch:
            lr /= 10
        for param_group in optimizer1.param_groups:
            param_group["lr"] = lr
        for param_group in optimizer2.param_groups:
            param_group["lr"] = lr

        if epoch < args.warm_up:  # warm up
            train_loader = loader.run("warmup")
            print("Warmup Net1")
            warmup(net1, optimizer1, train_loader)
            train_loader = loader.run("warmup")
            print("\nWarmup Net2")
            warmup(net2, optimizer2, train_loader)
            size_l1, size_u1, size_l2, size_u2 = (
                len(train_loader.dataset),
                0,
                len(train_loader.dataset),
                0,
            )
        else:
            sys.stdout.flush()
            print("\n==== net 1 evaluate next epoch training data loss ====")
            eval_loader = loader.run(
                "eval_train"
            )  # evaluate training data loss for next epoch
            prob1, paths1 = eval_train(epoch, net1)
            print("\n==== net 2 evaluate next epoch training data loss ====")
            eval_loader = loader.run("eval_train")
            prob2, paths2 = eval_train(epoch, net2)

            pred1 = prob1 > args.p_threshold  # divide dataset
            pred2 = prob2 > args.p_threshold

            print("\n\nTrain Net1")
            labeled_trainloader, unlabeled_trainloader = loader.run(
                "train", pred2, prob2, paths=paths2
            )  # co-divide
            size_l1, size_u1 = (
                len(labeled_trainloader.dataset),
                len(unlabeled_trainloader.dataset),
            )
            train(
                epoch,
                net1,
                net2,
                optimizer1,
                labeled_trainloader,
                unlabeled_trainloader,
            )  # train net1
            print("\nTrain Net2")
            labeled_trainloader, unlabeled_trainloader = loader.run(
                "train", pred1, prob1, paths=paths1
            )  # co-divide
            size_l2, size_u2 = (
                len(labeled_trainloader.dataset),
                len(unlabeled_trainloader.dataset),
            )
            train(
                epoch,
                net2,
                net1,
                optimizer2,
                labeled_trainloader,
                unlabeled_trainloader,
            )  # train net2

        val_loader = loader.run("val")  # validation
        acc1, prec1, rec1, f1_1 = val(net1, val_loader, 1)
        acc2, prec2, rec2, f1_2 = val(net2, val_loader, 2)
        results = "Test Epoch: %d, Accuracy: %.3f & %.3f, Precision: %.3f & %.3f, Recall: %.3f & %.3f, F1: %.3f & %.3f, L_1: %d, U_1: %d, L_2: %d, U_2: %d" % (
            epoch,
            acc1 * 100,
            acc2 * 100,
            prec1 * 100,
            prec2 * 100,
            rec1 * 100,
            rec2 * 100,
            f1_1 * 100,
            f1_2 * 100,
            size_l1,
            size_u1,
            size_l2,
            size_u2,
        )
        print("\n" + results + "\n")
        logs.write(results + "\n")
        logs.flush()
        if (epoch + 1) % args.save_every == 0 or epoch == args.warm_up - 1:
            data_dict = {
                "epoch": epoch,
                "net1": net1.state_dict(),
                "net2": net2.state_dict(),
                "optimizer1": optimizer1.state_dict(),
                "optimizer2": optimizer2.state_dict(),
                "best_acc": best_acc,
            }
            checkpoint_model = open(
                os.path.join(args.checkpoint_path, "all", f"model_{epoch}.pkl"), "wb"
            )
            pickle.dump(data_dict, checkpoint_model)
            saved_model = open(
                os.path.join(args.checkpoint_path, "saved", f"{args.preset}.pkl"), "wb"
            )
            pickle.dump(data_dict, saved_model)
        epoch += 1

    test_loader = loader.run("test")
    net1.load_state_dict(
        torch.load(
            os.path.join(args.checkpoint_path, "saved", args.preset + ".net1.pth.tar")
        )
    )
    net2.load_state_dict(
        torch.load(
            os.path.join(args.checkpoint_path, "saved", args.preset + ".net2.pth.tar")
        )
    )
    test(net1, net2, test_loader)


import bisect
import logging
import random
import subprocess
import sys
from enum import Enum
from operator import attrgetter

import settings as s
from actors.EventManager import EventManager, EventType
from actors.Simulation import Simulation
from actors.Solution import Action
from actors.Task import Task, Status
from actors.TrafficObserver import TrafficObserver
from actors.Vehicle import TaskGeneratorVehicle, ProcessorVehicle, ConnectionStatus
from actors.constant import Color
from dispatch_tasks import send_task_data_to_cloud, send_task_data_to_processor
from sumo_traci import SumoVehicle
from utils import get_estimated_tx_time_between_stations, get_estimated_tx_time_station_to_cloud, check_connection

class AssignmentMethod(Enum):
    AGGRESSIVE = "AGGRESSIVE"
    ADAPTIVE = "ADAPTIVE"
    OPTIMUM = "OPTIMUM"
    ONLY_CLOUD = "ONLY_CLOUD"

class TaskProcessorMatching:
    task = None
    processor = None
    task_penalty_score = None
    estimated_tx_time = None

    def __init__(self, task, processor, task_penalty_score, estimated_tx_time):
        self.task = task
        self.processor = processor
        self.task_penalty_score = task_penalty_score
        self.estimated_tx_time = estimated_tx_time

    def __repr__(self) -> str:
        return f"Task#{self.task.no}: owner:{self.task.owner} candidateProcessor:{self.processor} " \
               f"penalty:{self.task_penalty_score} estimatedTx:{self.estimated_tx_time:.0f}"

class TaskOrganizer:
    pool = None
    tasks_being_processed_on_cloud = None
    active_tasks = None
    completed_tasks = None
    cloud_thresholds = None
    available_task_processors = {}
    download_processes = None
    traffic_count_on_ap = None
    solution = None

    def __init__(self, solution=None):
        self.available_task_processors = {}
        self.tasks_being_processed_on_cloud = []
        TaskOrganizer.cloud_thresholds = list(s.CLOUD_PROBABILITY_BY_POOL_SIZE.keys())
        TaskOrganizer.cloud_thresholds.sort()

        self.pool = []
        self.active_tasks = {}
        self.completed_tasks = []
        self.download_processes = {}
        self.traffic_count_on_ap = {}
        self.solution = solution

    def check_events(self, current_time):
        events = EventManager.get_events_on_time_t(current_time)
        for event in events:
            logging.info(f"{Color.CYAN}NEW EVENT: {event}{Color.ENDC}")
            if event.event_type == EventType.PROCESS_COMPLETE:
                self.completed_tasks.append(event.task)
                self.active_tasks.pop(event.task.no)
                event.task.status = Status.COMPLETED
                if event.task.is_assigned_to_cloud:
                    logging.info(f"Task#{event.task.no} process on cloud is complete.")
                else:
                    processor = event.task.assigned_processor
                    logging.info(f"Task#{event.task.no} process on processor {processor.sumo_id} is complete.")
                    processor.start_to_process_next_task(current_time)

    def check_download_processes(self, current_time):
        for task_no, process in self.download_processes.copy().items():
            state = process.poll()
            if state is not None:
                task = self.active_tasks[task_no]
                self.download_processes.pop(task_no)
                if task.status in [Status.OWNER_LEFT, Status.PROCESSOR_LEFT]:
                    logging.info(f"{Color.ORANGE}Task#{task_no} was {task.status.name}. Skipping...{Color.ENDC}")
                    continue
                destination = "Cloud" if task.is_assigned_to_cloud else task.assigned_processor.station.name
                logging.info(f"{Color.ORANGE}Task#{task_no} data transferr output: "
                             f"{task.owner.station.name}->{destination}{Color.ENDC}")
                out, err = process.communicate()
                if err:
                    logging.info(
                        f"Err for Task#{task.no}: {err.decode()}")
                    if task.is_assigned_to_cloud:
                        Simulation.cloud_server.popen("ping -c 3 %s" % task.owner.station.wintfs[0].ip)
                    else:
                        task.assigned_processor.station.popen("ping -c 3 %s" % task.owner.station.wintfs[0].ip)
                    defaults = {'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE}
                    self.download_processes[task_no] = subprocess.Popen(process.args, **defaults)
                    continue
                task_identifier = task.get_task_identifier()
                logging.info(f"Upload data report({task_identifier}):\n{out.decode()}")
                Simulation.upload_reports[task_identifier] = out
                task.server_process.kill()
                task.server_process.wait()
                for ping_process in task.ping_processes:
                    ping_process.kill()
                    ping_process.wait()
                task.set_tx_complete(current_time)

    def get_next_task_pair(self, current_time, processors):
        task_scores = []
        for task in self.pool:
            if not check_connection(f"Task#{task.no} owner", task.owner):
                continue
            best_matching_for_task = None
            for processor in processors:
                if not check_connection("Processor", processor):
                    continue
                if task.size > processor.remaining_queue_size:
                    continue
                tx_time = get_estimated_tx_time_between_stations(current_time, task.owner.station, processor.station,
                                                                 task)
                if tx_time > s.ALLOWED_MAX_TX_TIME:
                    continue
                earliest_time_to_process_task = processor.estimated_earliest_time_to_process_new_task
                processing_time = task.get_process_time(processor.process_speed)
                estimated_task_end_time = max(current_time + tx_time, earliest_time_to_process_task) + processing_time
                task_penalty_score = task.get_predicted_penalty_score(estimated_task_end_time)
                if best_matching_for_task and best_matching_for_task.task_penalty_score < task_penalty_score:
                    continue
                best_matching_for_task = TaskProcessorMatching(task, processor, task_penalty_score, tx_time)
                task_scores.append(best_matching_for_task)
        if task_scores:
            logging.info(f"Candidate pairs: {task_scores}")
            pair = max(task_scores, key=attrgetter('task_penalty_score'))
            return pair
        else:
            return False

    def aggressive_assignment(self, current_time, processors):
        new_matching = self.get_next_task_pair(current_time, processors)
        if new_matching:
            self.assign_task_to_processor(current_time, new_matching)
            return self.aggressive_assignment(current_time, processors)

    def adaptive_assignment(self, current_time, processors):
        processors_with_no_active_download_operation = []
        for processor in processors:
            has_download_job = False
            for task in processor.queue:
                if task.status == Status.TX_PROCESSOR:
                    has_download_job = True
                    break
            if not has_download_job:
                processors_with_no_active_download_operation.append(processor)
                logging.debug(f"Processor{processor} queue: {processor.queue}")
        new_matching = self.get_next_task_pair(current_time, processors_with_no_active_download_operation)
        while new_matching:
            processors_with_no_active_download_operation.remove(new_matching.processor)
            self.assign_task_to_processor(current_time, new_matching)
            new_matching = self.get_next_task_pair(current_time, processors_with_no_active_download_operation)
        if new_matching:
            self.assign_task_to_processor(current_time, new_matching)
            return self.aggressive_assignment(current_time, processors)

    def assignment_from_solution(self, current_time):
        for task in self.pool.copy():
            action = self.solution.decisions[task.no]
            if action == Action.SKIP:
                continue
            if not check_connection(f"Task#{task.no} owner", task.owner):
                continue
            if action.sumo_id in Simulation.all_vehicles:
                processor = Simulation.all_vehicles[action.sumo_id]
                if processor.departure_time:
                    self.pool.remove(task)
                    task.set_assignment_to_cloud(current_time)
                    self.assign_to_cloud(current_time, task)
                    continue
                if task.size > processor.remaining_queue_size:
                    logging.info(f"Processor queue size is not enough for task#{task.no}")
                    continue
                # if not check_connection("Processor", processor):
                #     continue
                self.pool.remove(task)
                estimated_tx_time = get_estimated_tx_time_between_stations(current_time, task.owner.station,
                                                                           processor.station,
                                                                           task)
                task.set_estimated_tx_end_time(current_time, estimated_tx_time)
                task.status = Status.TX_PROCESSOR
                processor.assign_task(current_time, task)
                download_process = send_task_data_to_processor(task, Simulation.nat_host_ip)
                self.download_processes[task.no] = download_process
                TrafficObserver.increment_traffic_on_sta(task.owner.station.name)
                TrafficObserver.increment_traffic_on_sta(processor.station.name)

    def handle_tasks(self, current_time):
        self.check_events(current_time)
        self.check_download_processes(current_time)
        processors_not_leaving_soon = [processor for processor in self.available_task_processors.values() if
                                       not processor.is_leaving_soon and
                                       processor.connection_status == ConnectionStatus.CONNECTED]
        if AssignmentMethod(s.ASSIGNMENT_METHOD) == AssignmentMethod.AGGRESSIVE:
            self.aggressive_assignment(current_time, processors_not_leaving_soon)
        elif AssignmentMethod(s.ASSIGNMENT_METHOD) == AssignmentMethod.ADAPTIVE:
            self.adaptive_assignment(current_time, processors_not_leaving_soon)
        elif AssignmentMethod(s.ASSIGNMENT_METHOD) == AssignmentMethod.OPTIMUM:
            self.assignment_from_solution(current_time)
        elif AssignmentMethod(s.ASSIGNMENT_METHOD) == AssignmentMethod.ONLY_CLOUD:
            pass
        else:
            logging.error("Wrong task assignment setting is set")
            sys.exit(1)

    def add_task(self, current_time, task):
        self.active_tasks[task.no] = task
        pool_size = len(self.pool)
        logging.info(f"{Color.DARK_WHITE}Current pool size: {pool_size}{Color.ENDC} ")
        threshold_index = bisect.bisect_right(TaskOrganizer.cloud_thresholds, pool_size) - 1
        cloud_probability = s.CLOUD_PROBABILITY_BY_POOL_SIZE[TaskOrganizer.cloud_thresholds[threshold_index]]
        lottery = random.random()
        is_assigned_to_cloud = lottery < cloud_probability

        if AssignmentMethod(s.ASSIGNMENT_METHOD) == AssignmentMethod.OPTIMUM:
            if self.solution.decisions[task.no] == Action.CLOUD:
                is_assigned_to_cloud = True
            else:
                is_assigned_to_cloud = False
        elif AssignmentMethod(s.ASSIGNMENT_METHOD) == AssignmentMethod.ONLY_CLOUD:
            is_assigned_to_cloud = True
        if is_assigned_to_cloud:
            task.set_assignment_to_cloud(current_time)
            self.assign_to_cloud(current_time, task)
        else:
            self.pool.append(task)
            task.assign_to_pool(current_time)
        logging.info(f"{task}")
        return task

    def assign_task_to_processor(self, current_time, new_matching):
        self.pool.remove(new_matching.task)
        estimated_tx_time = new_matching.estimated_tx_time
        new_matching.task.set_estimated_tx_end_time(current_time, estimated_tx_time)
        new_matching.task.status = Status.TX_PROCESSOR
        new_matching.processor.assign_task(current_time, new_matching.task)
        download_process = send_task_data_to_processor(new_matching.task, Simulation.nat_host_ip)
        self.download_processes[new_matching.task.no] = download_process
        TrafficObserver.increment_traffic_on_sta(new_matching.task.owner.station.name)
        TrafficObserver.increment_traffic_on_sta(new_matching.processor.station.name)

    def assign_to_cloud(self, current_time, new_task):
        estimated_tx_time = get_estimated_tx_time_station_to_cloud(current_time, new_task)
        new_task.set_estimated_tx_end_time(current_time, estimated_tx_time)
        download_process = send_task_data_to_cloud(Simulation.cloud_server, Simulation.cloud_server_ip, new_task,
                                                   Simulation.nat_host_ip)
        self.download_processes[new_task.no] = download_process
        TrafficObserver.increment_traffic_on_sta(new_task.owner.station.name)
        TrafficObserver.increment_traffic_on_cloud()

    def add_to_available_task_processors(self, vehicle):
        self.available_task_processors[vehicle.sumo_id] = vehicle
        logging.debug(f"New processor vehicle is added: {vehicle.sumo_id}")

    def remove_from_available_task_processors(self, vehicle_id):
        if vehicle_id in self.available_task_processors:
            self.available_task_processors.pop(vehicle_id)
            logging.debug(f"Processor vehicle is removed: {vehicle_id}")
        else:
            logging.info(f"Processor vehicle is already removed: {vehicle_id}")

    def handle_vehicle_departure(self, vehicle):
        is_processor = isinstance(vehicle, ProcessorVehicle)
        if is_processor and vehicle.iperf_server_processes:
            for iperf_server_process in vehicle.iperf_server_processes:
                iperf_server_process.kill()
                iperf_server_process.wait()
        for task in vehicle.task_list:
            if task.status not in [Status.TX_CLOUD, Status.TX_PROCESSOR, Status.ON_POOL]:
                continue
            if is_processor:
                task.status = Status.PROCESSOR_LEFT
                logging.error(
                    f"{Color.RED}Task#{task.no} processor {vehicle.station.name} is left the area."
                    f"Reassigning the task.{Color.ENDC}")
                Simulation.number_of_reassigned_tasks += 1
                self.add_task(Simulation.current_time, task)
                task.assigned_processor.drop_task(Simulation.current_time, task)
                TrafficObserver.decrement_traffic_on_sta(task.owner.station.name)
            else:
                task.status = Status.OWNER_LEFT
                task.owner_departure_time = Simulation.current_time
                logging.error(
                    f"{Color.RED}Task#{task.no} owner {vehicle.station.name} is left the area.{Color.ENDC}")
                if task in self.pool:
                    self.pool.remove(task)
                elif task.is_assigned_to_cloud:
                    TrafficObserver.decrement_traffic_on_cloud()
                else:
                    task.assigned_processor.drop_task(Simulation.current_time, task)
                    TrafficObserver.decrement_traffic_on_sta(task.assigned_processor.station.name)
            if task.tx_process:
                task.tx_process.kill()
                task.tx_process.wait()
                task.server_process.kill()
                task.server_process.wait()
                for ping_process in task.ping_processes:
                    ping_process.kill()
                    ping_process.wait()
            if task.no in self.download_processes:
                self.download_processes.pop(task.no)

if __name__ == '__main__':
    logging.basicConfig(level=getattr(logging, s.LOG_LEVEL), format="%(asctime)s %(levelname)s -> %(message)s")
    task_organizer = TaskOrganizer()
    for i in range(900):
        sumo_vehicle = SumoVehicle("veh%d" % i, type_abbreviation=random.choice(["E", "T"]), route_length=350)
        task_generator_vehicle = TaskGeneratorVehicle(sumo_vehicle, None, i)
        size = random.randint(*s.TASK_SIZE)
        deadline = random.randint(*s.DEADLINE)
        dummy_task = Task(i, task_generator_vehicle, size, deadline)
        task_organizer.add_task(i, dummy_task)


from threading import Event
from twisted.internet import reactor
from pydra.cluster.tasks.tasks import Task

class WorkerProxy():
    """
    Class for proxying worker functions
    """
    worker_key = "WorkerProxy"

    def get_worker(self):
        return self

    def get_key(self):
        return None

class StartupAndWaitTask(Task):
    """
    Task that runs indefinitely.  Used for tests that
    require a task with state STATUS_RUNNING.  This task
    uses a lock so that the testcase can request the lock
    and effectively pause the task at specific places to
    verify its internal state
    """

    def __init__(self):
        self.starting_event = Event()   # used to lock task until _work() is called
        self.running_event = Event()    # used to lock running loop
        self.finished_event = Event()   # used to lock until Task.work() is complete
        self.failsafe = None
        self.data = None
        Task.__init__(self)

    def clear_events(self):
        """
        This clears threads waiting on events.  This function will
        call set() on all the events to ensure nothing is left waiting.
        """
        self.starting_event.set()
        self.running_event.set()
        self.finished_event.set()

    def work(self, args={}, callback=None, callback_args={}):
        """
        extended to add locks at the end of the work
        """
        try:
            # set a failsafe to ensure events get cleared
            self.failsafe = reactor.callLater(5, self.clear_events)

            ret = Task.work(self, args, callback, callback_args)
            self.finished_event.set()

        finally:
            if self.failsafe:
                self.failsafe.cancel()

        return ret

    def _work(self, data=None):
        """
        'Work' until an external object modifies the STOP_FLAG flag
        """
        self.data = data
        self.starting_event.set()

        while not self.STOP_FLAG:
            # wait for the running_event.  This  prevents needless looping
            # and still simulates a task that is working
            self.running_event.wait(5)

        return self.data


import pygame as pg

pg.init()

width = 600
height = 800

window = pg.display.set_mode((width, height))

pg.display.set_caption('fishing game')

backgroun_image = pg.image.load("img/background.png")
backgroun_image = pg.transform.scale(backgroun_image, (width, height))

# 좌표 기준으로 이미지를 (0, 0) 위치에 두어야 해당 위치 기준으로 이미지가 놓아지는 형태이다.
window.blit(backgroun_image, (0, 0))

# 이미지를 넣어주었으면, display를 업데이트 해주어야 한다.
pg.display.update()

# 마우스를 누르거나, 키보드를 누르는 각 이벤트가 특정 동작 queue에 쌓이며, 해당 이벤트를 while에서 처리하도록 한다.
while True:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            quit()


#!/usr/bin/env python

##################################################
## DEPENDENCIES
import sys
import os
import os.path
try:
    import builtins as builtin
except ImportError:
    import __builtin__ as builtin
from os.path import getmtime, exists
import time
import types
from Cheetah.Version import MinCompatibleVersion as RequiredCheetahVersion
from Cheetah.Version import MinCompatibleVersionTuple as RequiredCheetahVersionTuple
from Cheetah.Template import Template
from Cheetah.DummyTransaction import *
from Cheetah.NameMapper import NotFound, valueForName, valueFromSearchList, valueFromFrameOrSearchList
from Cheetah.CacheRegion import CacheRegion
import Cheetah.Filters as Filters
import Cheetah.ErrorCatchers as ErrorCatchers

##################################################
## MODULE CONSTANTS
VFFSL=valueFromFrameOrSearchList
VFSL=valueFromSearchList
VFN=valueForName
currentTime=time.time
__CHEETAH_version__ = '2.4.4'
__CHEETAH_versionTuple__ = (2, 4, 4, 'development', 0)
__CHEETAH_genTime__ = 1458422848.980832
__CHEETAH_genTimestamp__ = 'Sat Mar 19 16:27:28 2016'
__CHEETAH_src__ = '/home/jeb/Repositories/rosmod/gui/templates/rapidxml_utils_hpp.tmpl'
__CHEETAH_srcLastModified__ = 'Tue Mar  8 10:57:08 2016'
__CHEETAH_docstring__ = 'Autogenerated by Cheetah: The Python-Powered Template Engine'

if __CHEETAH_versionTuple__ < RequiredCheetahVersionTuple:
    raise AssertionError(
      'This template was compiled with Cheetah version'
      ' %s. Templates compiled before version %s must be recompiled.'%(
         __CHEETAH_version__, RequiredCheetahVersion))

##################################################
## CLASSES

class rapidxml_utils_hpp(Template):

    ##################################################
    ## CHEETAH GENERATED METHODS

    def __init__(self, *args, **KWs):

        super(rapidxml_utils_hpp, self).__init__(*args, **KWs)
        if not self._CHEETAH__instanceInitialized:
            cheetahKWArgs = {}
            allowedKWs = 'searchList namespaces filter filtersLib errorCatcher'.split()
            for k,v in KWs.items():
                if k in allowedKWs: cheetahKWArgs[k] = v
            self._initCheetahInstance(**cheetahKWArgs)

    def respond(self, trans=None):

        ## CHEETAH: main method generated for this template
        if (not trans and not self._CHEETAH__isBuffering and not callable(self.transaction)):
            trans = self.transaction # is None unless self.awake() was called
        if not trans:
            trans = DummyTransaction()
            _dummyTrans = True
        else: _dummyTrans = False
        write = trans.response().write
        SL = self._CHEETAH__searchList
        _filter = self._CHEETAH__currentFilter

        ########################################
        ## START - generated method body

        write(u'''#ifndef RAPIDXML_UTILS_HPP_INCLUDED\r
#define RAPIDXML_UTILS_HPP_INCLUDED\r
\r
// Copyright (C) 2006, 2009 Marcin Kalicinski\r
// Version 1.13\r
// Revision $DateTime: 2009/05/13 01:46:17 $\r
//! \\file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful\r
//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.\r
\r
#include "rapidxml.hpp"\r
#include <vector>\r
#include <string>\r
#include <fstream>\r
#include <stdexcept>\r
\r
namespace rapidxml\r
{\r
\r
    //! Represents data loaded from a file\r
    template<class Ch = char>\r
    class file\r
    {\r
        \r
    public:\r
        \r
        //! Loads file into the memory. Data will be automatically destroyed by the destructor.\r
        //! \\param filename Filename to load.\r
        file(const char *filename)\r
        {\r
            using namespace std;\r
\r
            // Open stream\r
            basic_ifstream<Ch> stream(filename, ios::binary);\r
            if (!stream)\r
                throw runtime_error(string("cannot open file ") + filename);\r
            stream.unsetf(ios::skipws);\r
            \r
            // Determine stream size\r
            stream.seekg(0, ios::end);\r
            size_t size = stream.tellg();\r
            stream.seekg(0);   \r
            \r
            // Load data and add terminating 0\r
            m_data.resize(size + 1);\r
            stream.read(&m_data.front(), static_cast<streamsize>(size));\r
            m_data[size] = 0;\r
        }\r
\r
        //! Loads file into the memory. Data will be automatically destroyed by the destructor\r
        //! \\param stream Stream to load from\r
        file(std::basic_istream<Ch> &stream)\r
        {\r
            using namespace std;\r
\r
            // Load data and add terminating 0\r
            stream.unsetf(ios::skipws);\r
            m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());\r
            if (stream.fail() || stream.bad())\r
                throw runtime_error("error reading stream");\r
            m_data.push_back(0);\r
        }\r
        \r
        //! Gets file data.\r
        //! \\return Pointer to data of file.\r
        Ch *data()\r
        {\r
            return &m_data.front();\r
        }\r
\r
        //! Gets file data.\r
        //! \\return Pointer to data of file.\r
        const Ch *data() const\r
        {\r
            return &m_data.front();\r
        }\r
\r
        //! Gets file data size.\r
        //! \\return Size of file data, in characters.\r
        std::size_t size() const\r
        {\r
            return m_data.size();\r
        }\r
\r
    private:\r
\r
        std::vector<Ch> m_data;   // File data\r
\r
    };\r
\r
    //! Counts children of node. Time complexity is O(n).\r
    //! \\return Number of children of node\r
    template<class Ch>\r
    inline std::size_t count_children(xml_node<Ch> *node)\r
    {\r
        xml_node<Ch> *child = node->first_node();\r
        std::size_t count = 0;\r
        while (child)\r
        {\r
            ++count;\r
            child = child->next_sibling();\r
        }\r
        return count;\r
    }\r
\r
    //! Counts attributes of node. Time complexity is O(n).\r
    //! \\return Number of attributes of node\r
    template<class Ch>\r
    inline std::size_t count_attributes(xml_node<Ch> *node)\r
    {\r
        xml_attribute<Ch> *attr = node->first_attribute();\r
        std::size_t count = 0;\r
        while (attr)\r
        {\r
            ++count;\r
            attr = attr->next_attribute();\r
        }\r
        return count;\r
    }\r
\r
}\r
\r
#endif\r
''')

        ########################################
        ## END - generated method body

        return _dummyTrans and trans.response().getvalue() or ""

    ##################################################
    ## CHEETAH GENERATED ATTRIBUTES

    _CHEETAH__instanceInitialized = False

    _CHEETAH_version = __CHEETAH_version__

    _CHEETAH_versionTuple = __CHEETAH_versionTuple__

    _CHEETAH_genTime = __CHEETAH_genTime__

    _CHEETAH_genTimestamp = __CHEETAH_genTimestamp__

    _CHEETAH_src = __CHEETAH_src__

    _CHEETAH_srcLastModified = __CHEETAH_srcLastModified__

    _mainCheetahMethod_for_rapidxml_utils_hpp= 'respond'

## END CLASS DEFINITION

if not hasattr(rapidxml_utils_hpp, '_initCheetahAttributes'):
    templateAPIClass = getattr(rapidxml_utils_hpp, '_CHEETAH_templateClass', Template)
    templateAPIClass._addCheetahPlumbingCodeToClass(rapidxml_utils_hpp)

# CHEETAH was developed by Tavis Rudd and Mike Orr
# with code, advice and input from many other volunteers.
# For more information visit http://www.CheetahTemplate.org/

##################################################
## if run from command line:
if __name__ == '__main__':
    from Cheetah.TemplateCmdLineIface import CmdLineIface
    CmdLineIface(templateObj=rapidxml_utils_hpp()).run()


from setuptools import setup, find_packages

with open("requirements.txt") as f:
	install_requires = f.read().strip().split("\n")

# get version from __version__ variable in tacten_vending_machine/__init__.py
from tacten_vending_machine import __version__ as version

setup(
	name="tacten_vending_machine",
	version=version,
	description="Manufactures Vending Machines and deploy it to customer sites",
	author="Aerele Technologies",
	author_email="hello@aerele.in",
	packages=find_packages(),
	zip_safe=False,
	include_package_data=True,
	install_requires=install_requires
)


from flask import jsonify, url_for, request, g
from . import api
from ..models import Comment, Post, Permit
from .. import db
from ..decorators import require_api_permit

@api.route('/comment/<int:comment_id>')
def get_comment(comment_id):
    comment = Comment.query.filter_by(id=comment_id).first_or_404()
    return jsonify(comment.to_json())

@api.route('/post/<int:post_id>/comments/')
def get_post_comments(post_id):
    comments = Comment.query.filter_by(post_id=post_id).all()
    return jsonify({
        'comments': [comment.to_json() for comment in comments],
        'post': url_for('api.get_post', post_id=post_id, _external=True),
    })

@api.route('/post/<int:post_id>/comments/', methods=['POST'])
@require_api_permit(Permit.comment)
def write_comment(post_id):
    post = Post.query.get_or_404(post_id)
    comment = Comment(content=request.json.get('comment'))
    comment.post = post
    comment.author = g.current_user
    db.session.add(comment)
    db.session.commit()
    return jsonify({comment.to_json()}, 201,
                   {'Location': url_for('api.get_comment', comment_id=comment.id, _external=True)})


# --- Import the data for the game, the artwork and any required modules:
from art import logo, vs, lost
from game_data import data
from clear import clear_screen
import random
import time

# --- display the main logo:
print(logo)
print("The first round will start in two seconds.")
time.sleep(2)
clear_screen()

# --- Determine the length of the list that contains all the choices. Reduce by one to match it to the list indexes:
items_in_data = (len(data)-1)

# --- Define a function for the bulk of the game:
def play_game():
    # --- set game_over to False:
    game_over = False
    score = 0
    # --- Until game_over is True, the game will continue to play:
    while game_over is False:
        # --- Generate two random numbers between 0 and the maximum number in the list.
        a_choice = data[random.randint(0, items_in_data)]
        b_choice = data[random.randint(0, items_in_data)]
        # --- Display the two results.
        print(f"\033[1;36;40mChoice A: {a_choice['name']}, a {a_choice['description']} from {a_choice['country']}.")
        print(vs)
        print(f"\033[1;35;40mChoice B: {b_choice['name']}, a {b_choice['description']} from {b_choice['country']}.\n")
        # --- Ask the player for their choice:
        players_choice = input("\033[1;37;40mPlease chose which is higher, \033[1;36;40mA \033[1;37;40mor \033[1;35;40mB\033[1;37;40m: ")
        if players_choice == "A" or players_choice == "a":
            # --- If A is higher than B, you will get to play again.
            if a_choice["follower_count"] > b_choice["follower_count"]:
                print("\n\033[1;32;40mYou are correct. Another round will start in two seconds.")
                score +=1
                time.sleep(2)
                clear_screen()
            # --- If B and A are the same, start another round:
            elif a_choice["follower_count"] == b_choice["follower_count"]:
                print("\n\033[1;32;40mThey are the same. Another round will start in two seconds.")
                time.sleep(2)
                clear_screen()
            # --- If A is lower than B, set game_over to true and end the game.
            else:
                print("\n\033[1;31;40mA was lower.\n")
                print(f"Your final score was: {score}")
                time.sleep(3)
                game_over = True
                clear_screen()
                print(lost)
                time.sleep(2)
        elif players_choice == "B" or players_choice == "b":
            # --- If B is higher than A, you will get to play again.
            if b_choice["follower_count"] > a_choice["follower_count"]:
                print("\n\033[1;32;40mYou are correct. Another round will start in two seconds.")
                score +=1
                time.sleep(2)
                clear_screen()
            # --- If B and A are the same, start another round:
            elif b_choice["follower_count"] == a_choice["follower_count"]:
                print("\n\033[1;32;40mThey are the same. Another round will start in two seconds.")
                time.sleep(2)
                clear_screen()
            # --- If B is lower than A, set game_over to true and end the game.
            else:
                print("\n\033[1;31;40mB was lower.\n")
                print(f"Your final score was: {score}")
                time.sleep(3)
                game_over = True
                clear_screen()
                print(lost)
                time.sleep(2)
        else:
            # --- For any input provided other than A, a, B or b,
            print("\nPlease enter either A or B. Another round will start in two seconds.")
            time.sleep(2)
            clear_screen()

# --- Start the game:
play_game()


import matplotlib.pyplot as plt
import math

class Point:
    """
    Class of points
    """
    __slots__ = "x", "y"

    def __init__(self, x, y) -> None:
        self.x = x
        self.y = y

    def __str__(self) -> str:
        return "(" + str(self.x) + ", " + str(self.y) + ")"

    def __eq__(self, o: object) -> bool:
        return self.x == o.x and self.y == o.y

class LineSegment:
    """
    Class of line segments
    """
    __slots__ = "point1", "point2", "slope", "length"

    def has_point(self, point):
        """
        check if one of the points is point
        :param point: the point to compare other points with
        :return: True if the point is same as one of the points of line segment
        """
        return self.point1 == point or self.point2 == point

    def swap_points(self):
        """
        Swaps the order of points of the current line segment
        :return: None
        """
        self.point1, self.point2 = self.point2, self.point1

    def __init__(self, point1, point2) -> None:
        """
        Initialise the line
        :param point1: point 1 of the line
        :param point2: point 2 of the line
        """
        self.point1 = point1
        self.point2 = point2
        if point2.x != point1.x:
            self.slope = (point2.y - point1.y) / (point2.x - point1.x)
        else:
            self.slope = None
        self.length = math.sqrt(
            (point2.y - point1.y) * (point2.y - point1.y) + (point2.x - point1.x) * (point2.x - point1.x))

    def __eq__(self, o: object) -> bool:
        """
        Define how to compare the lines
        :param o: other line
        :return: True if the other line is same as this line other wise False
        """
        return (self.point1 == o.point1 and self.point2 == o.point2) or (
                self.point1 == o.point2 and self.point2 == o.point1)

    def __str__(self) -> str:
        """
        String representation of the line
        :return:
        """
        return "<" + str(self.point1) + "-" + str(self.point2) + ">"

def sign(num):
    """
    gives the sign of the number
    :param num: the number whose sign is needed
    :return: +1 if the number is positive or 0 else -1
    """
    if num == 0:
        return 0
    elif num < 0:
        return -1
    else:
        return 1

def print_points(points):
    """
    Print the linst of points one at a time
    :param points:
    :return:
    """
    for point in points:
        print(point, end=" ")
    print()

def print_lines(lines, tag):
    """
    Prints the list of lines one at a time
    :param lines: list of lines to print
    :param tag: descriptor that print along with the lines
    :return:
    """
    if tag:
        print(tag)
    for line in lines:
        print(line)
    print()

def plot_points_and_hull(points, hull):
    """
    plots the list of points and hull using the matplotlib library
    :param points: list of points to be plotted
    :param hull: list of points making the hull
    :return: None
    """
    fig = plt.figure()
    x_arr = [p.x for p in points]
    y_arr = [p.y for p in points]
    plt.plot(x_arr, y_arr, 'ro')
    hull.append(hull[0])
    hull_x_arr = [h.x for h in hull]
    hull_y_arr = [h.y for h in hull]
    plt.plot(hull_x_arr, hull_y_arr)
    plt.show()

def write_to_file(filename, points):
    """
    writes the list of points -- points to the file mentioned
    :param filename: name of the file to write to
    :param points: list of points to write to the file
    :return: None
    """
    print("writing to file")
    with open(filename, 'w') as f:
        f.write(str(len(points)) + "\n")
        for point in points:
            f.write(str(point) + "\n")

def read_from_file(filename):
    """
    reads the file and makes a list of points
    :param filename: name of the file
    :return: list of points read from the file in a list data structure
    """
    with open(filename) as f:
        num_points = f.readline()
        points = []
        for line in f:
            line = line.strip()
            x, y = line.split()
            points.append(Point(float(x), float(y)))
    return points

def get_lowest_point(points) -> Point:
    """
    Calculates the lowest in the list of points by value in y coordinate
    :param points: list of points to check
    :return: point that has the lowest y value
    """
    min_y_point = points[0]

    for point in points:
        if point.y < min_y_point.y:
            min_y_point = point
    return min_y_point


from PIL import Image, ImageFont, ImageDraw
from io import BytesIO
from textwrap import wrap
from random import randint
import requests

def among_us(text):
    url = "https://raw.githubusercontent.com/north-developers/among-us-bot/master/additionally/"
    random = randint(1,12)

    font = ImageFont.truetype(BytesIO(requests.get(url + "bold.ttf").content), 60)
    imposter = Image.open(BytesIO(requests.get(f"{url}{random}.png").content))
    text_ = "\n".join(["\n".join(wrap(part, 30)) for part in text.split("\n")])
    w, h = ImageDraw.Draw(Image.new("RGB", (1, 1))).multiline_textsize(text_, font, stroke_width=2)
    text = Image.new("RGBA", (w + 30, h + 30))
    ImageDraw.Draw(text).multiline_text((15,15), text_, "#FFF", font, stroke_width=2, stroke_fill="#000")
    w = imposter.width + text.width + 10
    h = max(imposter.height, text.height)
    image = Image.new("RGBA", (w, h))
    image.paste(imposter, (0, h-imposter.height), imposter)
    image.paste(text, (w-text.width, 0), text)
    image.thumbnail((512, 512))
    output = BytesIO()
    output.name = "imposter.webp"
    image.save(output)
    output.seek(0)

    return output


import threading
import time
import pynput
from pynput.mouse import Controller,Button
from pynput.keyboard import Listener,KeyCode

delay = 0.001
buton = Button.left

start_stop_key = KeyCode(char='s')
exit_key = KeyCode(char='e')

class ClickMouse(threading.Thread):
    def __init__(self,delay,button):
        super().__init__()

        self.delay = delay
        self.button = button

        self.running = False

        self.program_running = True

    def start_click(self):
        self.running =  True

    def stop_click(self):
        self.running = False

    def exit(self):
        self.stop_click()
        self.program_running = False

    def run(self):
        while self.program_running:
            while self.running:
                mouse.click(self.button)
                time.sleep(delay)

print("Press ",start_stop_key.char,"start")
print("Press ",exit_key,"exit")
mouse = Controller()
click_t = ClickMouse(delay,buton)
click_t.start()

def on_press(key):
    if key == start_stop_key:
        if click_t.running:
            click_t.stop_click()

        else:
            click_t.start_click()

    elif key == exit_key:
        click_t.exit()
        listener.stop()

with Listener(on_press=on_press) as listener:
    listener.join()


from jedi import Script

def convert_completion(completion, index):
    converted = dict(type=completion.type, label=completion.name_with_symbols)
    if completion.type != "keyword": # Keywords have obvious meanings yet non-useful docstrings
        converted["info"] = completion.docstring()
    # Jedi does sorting, so give earlier element highest boost
    converted["boost"] = -index
    return converted

def autocomplete(context):
    # Ensure before-match is not None
    before = context.get("before", {"text": "", "from": context["pos"]})
    complete_from = before["from"]
    if context["explicit"] or before["text"]:
        completions = Script(context["text"]).complete(line=context["line"], column=context["column"])
        # Convert Jedi completions to CodeMirror objects
        options = [convert_completion(c, i)
                   for (i, c) in enumerate(completions)]
        if "." in before["text"]:
            # Completing a property access, so complete from end of match
            complete_from = before["to"]
    else:
        # Don't complete for emptry string unless asked for
        options = []
    return {
        "options": options,
        "from": complete_from
    }


import pygame
import random
import sys
import time
pygame.init()

# Images
icon = pygame.image.load("sortingIcon1024.png")

# Make screen
screen = pygame.display.set_mode((500, 500))
screen.fill((255, 169, 94))
pygame.display.set_caption("Sorting Algorithm Visualisation")
pygame.display.set_icon(icon)

# Variables
numberArray = [None] * 100

# Fill array with random numbers
for i in range(0, len(numberArray)):
    numberArray[i] = random.randint(200, 600)

def displayArray(arr):
    x = 0
    for i in range(0, len(arr) - 1):
        pygame.draw.rect(screen, (63, 82, 209), (x, 0, 10, arr[i]))
        x += 10
    pygame.display.update()

def quickSort(arr):
    length = len(arr)
    if length <= 1:
        return arr
    else:
        pivot = arr.pop()

    greater = []
    lower = []

    for num in arr:
        if num > pivot:
            greater.append(num)

        else:
            lower.append(num)

    screen.fill((255, 169, 94))
    displayArray(lower + [pivot] + greater)
    pygame.display.update()
    time.sleep(0.20)
    return quickSort(lower) + [pivot] + quickSort(greater)

displayArray(numberArray)
time.sleep(2)
sorted = quickSort(numberArray)
screen.fill((255, 169, 94))
pygame.display.update()
time.sleep(2)
displayArray(sorted)

notExit = True
while notExit:
    for event in pygame.event.get():
        # If the player presses the exit window button, then quit the program
        if event.type == pygame.QUIT:
            notExit = False


from tuning import Tuning
import usb.core
import usb.util
import time
import sounddevice as sd
import numpy as np
import socket
from multiprocessing import Process
import select

"""
master

combination of client and server sending only X and Y to main collection server
- requires newer pi
"""

#v0.1

#client config
addr = ("", 12000)
device_id = "0"
buffer_size = 10

#serv config
server_addr = ("192.168.1.67", 12000)
team_id = 'bonksquad'

def loc_serv(addr, team_id, timeout=0.001):
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server_socket.bind(('', 12000))

    """
    slim serv for inter-team processing
    """

    sig_ttl = 1
    distance_between = 4  # in feet
    num_units = 2
    units = {}

    for n in range(num_units):
        units[n] = {
            "doa": -1,
            "mag": 'na',
            "ttl": 0
        }

    server_socket.setblocking(0)

    while True:
        ready = select.select([server_socket], [], [], timeout)

        if ready[0]:
            message = server_socket.recv(2000)

            vals = message.decode('utf-8').split(',')
            id = int(vals[0])
            # populate dict
            if len(vals) == 2:
                # check if no detection
                if units[id]['ttl'] > 0:
                    units[id]['ttl'] = units[id]['ttl'] - 1
                else:
                    units[id]['doa'] = -1
                    units[id]['mag'] = 'na'
            else:
                # populate if detection
                units[id]['doa'] = int(vals[1])
                units[id]['mag'] = 'na'
                units[id]['ttl'] = sig_ttl

            # check if sync det within ttl
            if (units[0]['ttl'] > 0 and units[1]['ttl'] > 0):
                print("Source located:", "Unit 0:", units[0], "Unit 1:", units[1])
                #  triangle quick maths
                ang_a = np.deg2rad(units[0]['doa'])
                ang_b = np.deg2rad(units[1]['doa'])  # taken care of client side
                ang_c = np.deg2rad(180 - (units[0]['doa'] + units[1]['doa']))
                side_a = ((np.sin(ang_a) / np.sin(ang_c)) * distance_between)
                side_b = ((np.sin(ang_b) / np.sin(ang_c)) * distance_between)

                # position based on unit 1
                x = side_a * np.cos(ang_b)
                y = side_a * np.sin(ang_b)
                cords = (team_id + "," + str(x) + "," + str(y))
                cords = cords.encode('utf-8')
                server_socket.sendto(message, addr)
                units[0]['ttl'] = 0
                units[1]['ttl'] = 0

serv_process = Process(target=loc_serv, args=(server_addr, team_id))
serv_process.daemon = True
serv_process.start()

#main

client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

dev = usb.core.find(idVendor=0x2886, idProduct=0x0018)

Mic_tuning = Tuning(dev)

start = time.time()
while True:
    try:
        doa_buff = []
        count = 0
        for _ in range(buffer_size):

            if device_id == "0":
                doa = Mic_tuning.direction
            else:
                doa = (180 - Mic_tuning.direction) % 380
            v_det = Mic_tuning.is_voice()
            if v_det == 1 and 1 < doa < 179:
                doa_buff.append(doa)

        if len(doa_buff):
            doa_avg = np.mean(np.array(doa_buff))
            val_avg = 'na'
            message = device_id + "," + str(int(doa_avg)) + "," + str(val_avg)
            message = message.encode('utf-8')
        else:
            message = device_id + "," + "ND"
            message = message.encode('utf-8')

        client_socket.sendto(message, addr)

    except KeyboardInterrupt:
        break


# 템플릿 렌더를 위해 임포트 / 단축형404에러 호출
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect  # html 응답을 위한 임포트
from django.urls import reverse
# from django.http import Http404  # 404오류 임포트
from .models import Question, reverse  # 데이터베이스 접근을 위한 모델 임포트

# Create your views here.

def index(req):
    # Question 모델의 데이터를 날짜순으로 가져와서 변수에 담는다.
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    # 템플릿을 불러온다
    # 가져온 질문 목록을 , 로 구분하여 이어 붙인뒤 변수에 담는다.
    context = {
        'latest_question_list': latest_question_list,
    }
    # 화면에 출력될 내용을 전달한다.
    # render 매서드를 불러들인뒤 2번째 인자로 템플릿파일을 지정한다.
    # render(응답, '템플릿경로', 템플릿에 전달할 키&값)
    return render(req, 'polls/index.html', context)

def detail(req, question_id):
    """
      try:
          # Question 테이블에 pk가 question_id인 값을 question에 담는다
          question = Question.objects.get(pk=question_id)
      except Question.DoesNotExist:
          # Question 테이블에 pk가 question_id인 값이 존재 하지 않으면 에러 발생시키기
          raise Http404("Question does not exist")  # raise로 에러 발생
    """
    # 위 try & except 방식으로 404 에러를 구현 해도 되지만 아래 숏컷 메서드를 통해 단순하게 구현 할 수 있다!
    question = get_object_or_404(question, pk=question_id)
    return render(req, 'polls/detail.html', {'question': question})

def results(req, question_id):
    question = get_object_or_404(question, pk=question_id)

    return render(req, 'polls/results.html', {'question': question})

def vote(req, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=req.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        return render(req, 'polls/detail.html', {'question': qeustion, 'error_message': 'you didnt select a choice.'})
    else:
        selected_choice.votes += 1
        selected_choice.save()

    return HttpResponseRedirect(reverse('polls:reaults', args=(question.id,)))


# -- coding: utf-8 --

import sys
import time
import msvcrt
import numpy as np
import cv2

from ctypes import *

sys.path.append("../MvImport")
from MvCameraControl_class import *

# ch: 开一个40MB的图像数据缓存大小 | en: Open a 40MB Image Buffer Size

if __name__ == "__main__":

    deviceList = MV_CC_DEVICE_INFO_LIST()
    tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE

    # ch:枚举设备 | en:Enum device
    ret = MvCamera.MV_CC_EnumDevices(tlayerType, deviceList)
    if ret != 0:
        print ("enum devices fail! ret[0x%x]" % ret)
        sys.exit()

    if deviceList.nDeviceNum == 0:
        print ("find no device!")
        sys.exit()

    print ("Find %d devices!" % deviceList.nDeviceNum)

    for i in range(0, deviceList.nDeviceNum):
        mvcc_dev_info = cast(deviceList.pDeviceInfo[i], POINTER(MV_CC_DEVICE_INFO)).contents
        if mvcc_dev_info.nTLayerType == MV_GIGE_DEVICE:
            print ("\ngige device: [%d]" % i)
            strModeName = ""
            for per in mvcc_dev_info.SpecialInfo.stGigEInfo.chModelName:
                strModeName = strModeName + chr(per)
            print ("device model name: %s" % strModeName)

            nip1 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24)
            nip2 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16)
            nip3 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8)
            nip4 = (mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff)
            print ("current ip: %d.%d.%d.%d\n" % (nip1, nip2, nip3, nip4))
        elif mvcc_dev_info.nTLayerType == MV_USB_DEVICE:
            print ("\nu3v device: [%d]" % i)
            strModeName = ""
            for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chModelName:
                if per == 0:
                    break
                strModeName = strModeName + chr(per)
            print ("device model name: %s" % strModeName)

            strSerialNumber = ""
            for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chSerialNumber:
                if per == 0:
                    break
                strSerialNumber = strSerialNumber + chr(per)
            print ("user serial number: %s" % strSerialNumber)

    nConnectionNum = input("please input the index number of the device to connect:")

    if int(nConnectionNum) >= deviceList.nDeviceNum:
        print ("intput error!")
        sys.exit()

    # ch:创建相机实例 | en:Creat Camera Object
    cam = MvCamera()

    # ch:选择设备并创建句柄 | en:Select device and create handle
    stDeviceList = cast(deviceList.pDeviceInfo[int(nConnectionNum)], POINTER(MV_CC_DEVICE_INFO)).contents

    ret = cam.MV_CC_CreateHandle(stDeviceList)
    if ret != 0:
        print ("create handle fail! ret[0x%x]" % ret)
        sys.exit()

    # ch:打开设备 | en:Open device
    ret = cam.MV_CC_OpenDevice(MV_ACCESS_Exclusive, 0)
    if ret != 0:
        print ("open device fail! ret[0x%x]" % ret)
        sys.exit()

    # ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
    if stDeviceList.nTLayerType == MV_GIGE_DEVICE:
        nPacketSize = cam.MV_CC_GetOptimalPacketSize()
        if int(nPacketSize) > 0:
            ret = cam.MV_CC_SetIntValue("GevSCPSPacketSize",nPacketSize)
            if ret != 0:
                print ("Warning: Set Packet Size fail! ret[0x%x]" % ret)
        else:
            print ("Warning: Get Packet Size fail! ret[0x%x]" % nPacketSize)

    # ch:设置触发模式为off | en:Set trigger mode as off
    ret = cam.MV_CC_SetEnumValue("TriggerMode", MV_TRIGGER_MODE_OFF)
    if ret != 0:
        print ("set trigger mode fail! ret[0x%x]" % ret)
        sys.exit()

    # ch:设置图像像素格式为mono8 | en：Set pixel format as mono8
    ret = cam.MV_CC_SetEnumValue("PixelFormat", 0x01080001)
    if ret != 0:
        print("Set pixel format fail! ret[0x%x]"% ret)
        sys.exit()

    # ch:开始取流 | en:Start grab image
    ret = cam.MV_CC_StartGrabbing()
    if ret != 0:
        print ("start grabbing fail! ret[0x%x]" % ret)
        sys.exit()

    global MAX_BUF_SIZE
    MAX_BUF_SIZE = 1024 * 1024 * 40
    mv_frame_info = MV_FRAME_OUT_INFO_EX()
    memset(byref(mv_frame_info), 0, sizeof(mv_frame_info))
    data_buf = (c_ubyte * MAX_BUF_SIZE)()

    # ch: 获取一帧图像 | en: Get one frame
    ret = cam.MV_CC_GetOneFrameTimeout(data_buf, MAX_BUF_SIZE, mv_frame_info, 1000)
    if ret != 0:
        print("Get one frame fail! ret[0x%x]"% ret)
        sys.exit()

    # ch: 保存RGB裸数据至opencv | en: Save RGB raw data to numpy array for opencv
    data_buf_ch = data_buf[0:mv_frame_info.nFrameLen:1]

    data_buf_copy = np.array(data_buf_ch)

    #print(mv_frame_info.nFrameLen)
    #data_r = data_buf_copy[0:mv_frame_info.nFrameLen:3]
    #data_g = data_buf_copy[1:mv_frame_info.nFrameLen:3]
    #data_b = data_buf_copy[2:mv_frame_info.nFrameLen:3]
    data_mono_arr = data_buf_copy.reshape(mv_frame_info.nHeight, mv_frame_info.nWidth)
    #data_r_arr = data_r.reshape(mv_frame_info.nHeight, mv_frame_info.nWidth)
    #data_g_arr = data_g.reshape(mv_frame_info.nHeight, mv_frame_info.nWidth)
    #data_b_arr = data_b.reshape(mv_frame_info.nHeight, mv_frame_info.nWidth)

    numArray = np.zeros([mv_frame_info.nHeight, mv_frame_info.nWidth, 3],"uint8")

    numArray[:, :, 2] = data_mono_arr
    numArray[:, :, 1] = data_mono_arr
    numArray[:, :, 0] = data_mono_arr

    cv2.imshow("",numArray)
    cv2.waitKey()
    # ch:停止取流 | en:Stop grab image
    ret = cam.MV_CC_StopGrabbing()
    if ret != 0:
        print ("stop grabbing fail! ret[0x%x]" % ret)
        sys.exit()

    # ch:关闭设备 | Close device
    ret = cam.MV_CC_CloseDevice()
    if ret != 0:
        print ("close deivce fail! ret[0x%x]" % ret)
        sys.exit()

    # ch:销毁句柄 | Destroy handle
    ret = cam.MV_CC_DestroyHandle()
    if ret != 0:
        print ("destroy handle fail! ret[0x%x]" % ret)
        sys.exit()

    del data_buf

_testcodes/GIGE 카메라 (HIKVISION) 영상화면출력/업체측 원본코드.py


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

__author__ = 'Sunbeam Rahman'
__date__   = '30/01/2022 21:21:21'
__email__  = 'sunbeam.rahman@live.com'

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

import streamlit as st

# create a sidebar
st.sidebar.title('Sidebar')