from django.shortcuts import render, redirect, get_object_or_404, HttpResponseRedirect
from django.urls import reverse, reverse_lazy
from django.views.generic import DetailView, ListView
from django.views.generic.edit import UpdateView, DeleteView, FormView, FormMixin
from django.db import IntegrityError
from django.core.exceptions import ValidationError
import random

# GEODJANGO IMPORTS

# For annotating and calculating distance
from django.contrib.gis.db.models.functions import Distance

# For filtering queryset based on distance provided
from django.contrib.gis.measure import D

# For Using Point on a map
from django.contrib.gis.geos import Point

from django.db.models import Q
from django.core.paginator import Paginator

from django.contrib.auth.views import LoginView

from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login

# from django.contrib import messages

from .forms import SearchForm, ShopForm
from .models import shop, Cuisine, Price, Type_of_food, Type_of_item
from .utils import random_string_generator

from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse
from taggit.models import Tag

# GENERAL VIEWS

def Home(request):
	return render(request, 'food/home.html')

def Explore(request):
	return render(request, 'food/explore.html')

def Search(request):
	return render(request, 'food/search.html')

def Error(request):
	return render(request, 'food/errorfinding.html')

def SaveError(request):
	return render(request, 'food/saveerror.html')

def About(request):
	return render(request, 'food/about.html')

def Contact(request):
	return render(request, 'food/contact.html')

def Privacy(request):
	return render(request, 'food/privacy.html')

def is_valid_queryparam(param):
	return param != '' and param is not None

def handler404(request, exception):
    return render(request, 'food/404.html', status=404)

def handler500(request):
    return render(request, 'food/500.html', status=500)

# LOGIN SECTION

class CustomLoginView(LoginView):
	template_name = 'food/login.html'
	fields = '__all__'
	redirect_authenticated_user = True

	def get_success_url(self):
		return reverse_lazy('food:food_list')

class RegisterPage(FormView):
	template_name = 'food/register.html'
	form_class = UserCreationForm
	redirect_authenticated_user = True
	success_url = reverse_lazy('food:food_list')

	def form_valid(self,form):
		user = form.save()
		if user is not None:
			login(self.request, user)
		return super(RegisterPage, self).form_valid(form)

	def get (self, *args, **kwargs):
		if self.request.user.is_authenticated:
			return redirect('food:food_list')
		return super(RegisterPage, self).get(*args, **kwargs)

# COMMUNITY SECTION

class CommunityfullListView(ListView):
	model = shop
	template_name = 'food/communitylist.html'
	paginate_by = 10

	def get_queryset(self):
		queryset = super().get_queryset().filter(user='1')

		search_input = self.request.GET.get('Search') or ''

		if search_input:
			queryset = queryset.filter(name__icontains=search_input)

		return queryset

	def get_context_data(self, **kwargs):
		context = super().get_context_data(**kwargs)

		paginator = context['paginator']
		page_numbers_range = 10  # Display 5 page numbers
		max_index = len(paginator.page_range)

		page = self.request.GET.get('page')

		current_page = int(page) if page else 1

		start_index = int((current_page - 1) / page_numbers_range) * page_numbers_range
		end_index = start_index + page_numbers_range
		if end_index >= max_index:
			end_index = max_index

		page_range = paginator.page_range[start_index:end_index]
		context['page_range'] = page_range

		return context

class CommunityListView(FormMixin, ListView):
	model = shop
	form_class = SearchForm
	template_name = 'food/communitysearch.html'

	def get_context_data(self, **kwargs):
		context = super().get_context_data(**kwargs)

		context['object_list'] = context['object_list'].filter(user='1')

		return context

	def get(self, request, *args, **kwargs):
		response = super().get(request, *args, **kwargs)
		# if 'random' in request.GET:
		form = self.get_form()
		if form.is_valid():
			return self.form_valid(form)
		else:
			return self.form_invalid(form)

		return response

	def get_form_kwargs(self):
		kwargs = super().get_form_kwargs()
		if self.request.method == 'GET' and self.request.GET:
			kwargs['data'] = self.request.GET

		return kwargs

	def form_valid(self, form):
		kwargs = {
			'query': form.cleaned_data['address'],

		}
		point = form.get_point(kwargs['query'])
		late_hours = self.request.GET.get('late_hours')
		price = self.request.GET.get('price')
		cuisine = self.request.GET.get('cuisine')
		type_of_food = self.request.GET.get('type_of_food')
		option_of_food = self.request.GET.get('option_of_food')
		halal = self.request.GET.get('halal')
		distance_limit = self.request.GET.get('distance_limit')
		randoming = self.request.GET.get('randoming')
		object_list = shop.objects.all()
		context = {'object_list': object_list}

		if point:
			kwargs['point'] = point
			user_location = Point(point['longitude'], point['latitude'], srid=4326)
			kwargs['object_list'] = super().get_queryset().annotate(distance=Distance(user_location,
   'location')
    ).order_by('distance')

		if is_valid_queryparam(price) and price != 'Any':
			kwargs['object_list'] = kwargs['object_list'].filter(price__costs=price)

		if late_hours == 'on':
			kwargs['object_list'] = kwargs['object_list'].filter(late_hours=True)

		if halal == 'on':
			kwargs['object_list'] = kwargs['object_list'].filter(halal=True)

		if is_valid_queryparam(cuisine) and cuisine != 'Any':
			kwargs['object_list'] = kwargs['object_list'].filter(cuisine__options=cuisine)

		if is_valid_queryparam(type_of_food) and type_of_food != 'Any':
			kwargs['object_list'] = kwargs['object_list'].filter(type_of_food__variety=type_of_food)

		if is_valid_queryparam(option_of_food) and option_of_food != 'Any':
			kwargs['object_list'] = kwargs['object_list'].filter(type_of_item__choices=option_of_food)

		kwargs['object_list'] = kwargs['object_list'].filter(location__distance_lte=(user_location, D(km=distance_limit)))

		if randoming == 'on':
			randomised_list = kwargs['object_list'].order_by('?').first()
			kwargs['object_list'] = kwargs['object_list'].filter(name__icontains=randomised_list.name)

		kwargs['object_list'] = kwargs['object_list']
		return self.render_to_response(self.get_context_data(**kwargs))

class CommunityDetailView(FormMixin, DetailView):
	model = shop
	template_name = 'food/community_detail.html'
	form_class = SearchForm

	def get (self, *args, **kwargs):
		person = self.get_object().user.id

		if person == 1:
			return super(CommunityDetailView, self).get(*args, **kwargs)
		else:
		 	return redirect('food:community_list')

def save_to_me(request,id):
	user = request.user

	destination = get_object_or_404(shop, id=id)

	if user == '':
		return redirect('communitylist/')
	else:
		name = destination.name
		location= destination.location
		price = destination.price
		cuisine = destination.cuisine
		type_of_food = destination.type_of_food
		type_of_item = destination.type_of_item
		late_hours = destination.late_hours
		new_slug = destination.slug
		address = destination.address
		directions = destination.directions
		halal = destination.halal
		description = destination.description
		referrence_Number = destination.referrence_Number

		slug = "{name}{randstr}".format(
				name = new_slug,
				randstr=random_string_generator(size=4)
			)

		ins = shop(user=user, name=name, location=location, price=price, cuisine=cuisine, type_of_food=type_of_food, type_of_item=type_of_item, late_hours=late_hours, slug=slug, address=address, directions=directions, halal=halal, description=description, referrence_Number=referrence_Number)
		try:
			ins.save()
		except IntegrityError as err:

			return HttpResponseRedirect(reverse('food:saveerror'))

		# return redirect('food:community_list')
		return HttpResponseRedirect(reverse('food:community_list'))

# PERSONAL LIST SECTION

class AllListView(LoginRequiredMixin, ListView):
	model = shop
	template_name = 'food/foodlist.html'
	paginate_by = 10

	def get_queryset(self):
		queryset = super().get_queryset().filter(user=self.request.user)

		search_input = self.request.GET.get('Search') or ''

		if search_input:
			queryset = queryset.filter(name__icontains=search_input)

		return queryset

	def get_context_data(self, **kwargs):
		context = super().get_context_data(**kwargs)

		paginator = context['paginator']
		page_numbers_range = 10  # Display 5 page numbers
		max_index = len(paginator.page_range)

		page = self.request.GET.get('page')

		current_page = int(page) if page else 1

		start_index = int((current_page - 1) / page_numbers_range) * page_numbers_range
		end_index = start_index + page_numbers_range
		if end_index >= max_index:
			end_index = max_index

		page_range = paginator.page_range[start_index:end_index]
		context['page_range'] = page_range

		return context

class FoodDetailView(FormMixin, DetailView):
	model = shop
	template_name = 'food/food_detail.html'
	form_class = SearchForm

	def get (self, *args, **kwargs):
		user = self.request.user.id
		person = self.get_object().user.id

		if user == person or person == 1:
			return super(FoodDetailView, self).get(*args, **kwargs)
		else:
			return redirect('food:food_list')

class FoodListView(LoginRequiredMixin, FormMixin, ListView):
	model = shop
	form_class = SearchForm
	template_name = 'food/foodsearch.html'

	def get_context_data(self, **kwargs):
		context = super().get_context_data(**kwargs)
		context['object_list'] = context['object_list'].filter(user=self.request.user)

		return context

	def get(self, request, *args, **kwargs):
		response = super().get(request, *args, **kwargs)
		# if 'random' in request.GET:
		form = self.get_form()
		if form.is_valid():
			return self.form_valid(form)
		else:
			return self.form_invalid(form)

		return response

	def get_form_kwargs(self):
		kwargs = super().get_form_kwargs()
		if self.request.method == 'GET' and self.request.GET:
			kwargs['data'] = self.request.GET

		return kwargs

	def form_valid(self, form):
		kwargs = {
			'query': form.cleaned_data['address'],
		}
		point = form.get_point(kwargs['query'])
		late_hours = self.request.GET.get('late_hours')
		price = self.request.GET.get('price')
		cuisine = self.request.GET.get('cuisine')
		type_of_food = self.request.GET.get('type_of_food')
		option_of_food = self.request.GET.get('option_of_food')
		halal = self.request.GET.get('halal')
		distance_limit = self.request.GET.get('distance_limit')
		randoming = self.request.GET.get('randoming')

		if point:
			kwargs['point'] = point
			user_location = Point(point['longitude'], point['latitude'], srid=4326)
			kwargs['object_list'] = super().get_queryset().annotate(distance=Distance(user_location,
   'location')
    ).order_by('distance')

		if is_valid_queryparam(price) and price != 'Any':
			kwargs['object_list'] = kwargs['object_list'].filter(price__costs=price)

		if late_hours == 'on':
			kwargs['object_list'] = kwargs['object_list'].filter(late_hours=True)

		if halal == 'on':
			kwargs['object_list'] = kwargs['object_list'].filter(halal=True)

		if is_valid_queryparam(cuisine) and cuisine != 'Any':
			kwargs['object_list'] = kwargs['object_list'].filter(cuisine__options=cuisine)

		if is_valid_queryparam(type_of_food) and type_of_food != 'Any':
			kwargs['object_list'] = kwargs['object_list'].filter(type_of_food__variety=type_of_food)

		if is_valid_queryparam(option_of_food) and option_of_food != 'Any':
			kwargs['object_list'] = kwargs['object_list'].filter(type_of_item__choices=option_of_food)

		kwargs['object_list'] = kwargs['object_list'].filter(location__distance_lte=(user_location, D(km=distance_limit)))

		if randoming == 'on':
			randomised_list = kwargs['object_list'].order_by('?').first()
			kwargs['object_list'] = kwargs['object_list'].filter(name__icontains=randomised_list.name)

		kwargs['object_list'] = kwargs['object_list']
		return self.render_to_response(self.get_context_data(**kwargs))

class FoodUpdate(LoginRequiredMixin, UpdateView):
	model = shop
	fields  = ['name', 'address', 'description', 'cuisine', 'price', 'late_hours']
	template_name = 'food/update_form.html'
	success_url = reverse_lazy('food:food_list')

	def get (self, *args, **kwargs):
		user = self.request.user.id
		person = self.get_object().user.id
		if user == person:
			return super(FoodUpdate, self).get(*args, **kwargs)
		else:
			return redirect('food:food_list')

class DeleteView(LoginRequiredMixin, DeleteView):
	model = shop
	context_object_name = 'shop'
	success_url = reverse_lazy('food:food_list')

# Addition of extra places

class showform(LoginRequiredMixin, FormView):
	template_name = 'food/addplaces.html'
	form_class = ShopForm
	success_url = reverse_lazy('food:food_list')

	def form_valid(self, form):
		kwargs = {
				'query': form.cleaned_data['address'],
			}
		point = form.get_point(kwargs['query'])

		if point:
			kwargs['point'] = point
			location = Point(point['longitude'], point['latitude'], srid=4326)

			lon = point['longitude']
			lat = point['latitude']

			name = self.request.POST['name']

			user = self.request.user

			late_hours = form.cleaned_data['late_hours']

			halal = form.cleaned_data['halal']

			address = point['formatted_address']

			cuisine = self.request.POST['cuisine']
			cuisine = Cuisine.objects.get(options=cuisine)

			price = self.request.POST['price']
			price = Price.objects.get(costs=price)

			type_of_food = self.request.POST['type_of_food']
			type_of_food = Type_of_food.objects.get(variety=type_of_food)

			type_of_item = self.request.POST['option_of_food']
			type_of_item = Type_of_item.objects.get(choices=type_of_item)

			description = self.request.POST['description']

			open_hours = self.request.POST['open_hours']

			directions = "http://maps.google.com/maps?z=12&t=m&q=loc:"+str(lat)+"+"+str(lon)

			slug = "{name}-{randstr}".format(
				name = name,
				randstr=random_string_generator(size=4)
			)

			ins = shop(user=user, name=name, location=location, price=price, cuisine=cuisine, type_of_food=type_of_food, type_of_item=type_of_item, late_hours=late_hours, slug=slug, address=address, directions=directions, halal=halal, description=description ,open_hours=open_hours)

			ins.save()

		else:
			print('cant retrieve the point')

		context = {
    	    'form': form,
    	}

		return super(showform, self).form_valid(form)


"""
The Turbowarp Cloud Variables File.
Go to https://scratch.mit.edu/projects/578255313/ for the Scratch Encode/Decode Engine!
"""
import ssl  # Used if the Certificate is expired specially in Windows 10 machine
import json
import time
import websocket

from scratchconnect import Exceptions
from scratchconnect.scEncoder import Encoder

_website = "scratch.mit.edu"
_login = f"https://{_website}/login/"
_api = f"api.{_website}"

class TurbowarpCloudConnection:
    def __init__(self, project_id, username):
        """
        Main class to connect cloud variables
        """
        self.project_id = project_id
        self.username = username
        self._make_connection()
        self.encoder = Encoder()

    def _send_packet(self, packet):
        """
        Don't use this
        """
        self._ws.send(json.dumps(packet) + "\n")

    def _make_connection(self):
        """
        Don't use this
        """
        self._ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE})
        self._ws.connect("wss://clouddata.turbowarp.org",
                         origin="https://turbowarp.org",
                         enable_multithread=True)
        self._send_packet(
            {
                "method": "handshake",
                "user": self.username,
                "project_id": str(self.project_id),
            }
        )

    def get_variable_data(self):
        """
        Returns the cloud variable data
        """
        data = json.loads(self._ws.recv())
        return data

    def set_cloud_variable(self, variable_name, value):
        """
        Set a cloud variable
        :param variable_name: Variable name
        :param value: Variable value
        """

        if str(value).isdigit() and value == '':
            raise Exceptions.InvalidCloudValue(f"The Cloud Value should be a set of digits and not '{value}'!")

        try:
            if len(str(value)) > 256:
                raise ValueError(
                    "Scratch has Cloud Variable Limit of 256 Characters per variable. Try making the value shorter!")
            if str(variable_name.strip())[0] != "☁":
                n = f"☁ {variable_name.strip()}"
            else:
                n = f"{variable_name.strip()}"
            packet = {
                "method": "set",
                "name": n,
                "value": str(value),
                "user": self.username,
                "project_id": str(self.project_id),
            }
            self._send_packet(packet)
            return True
        except ConnectionAbortedError or BrokenPipeError:
            self._make_connection()
            time.sleep(0.1)
            self.set_cloud_variable(variable_name, value)
            return False

    def encode(self, text):
        """
        Encode a text. For example: A -> 1
        Go to https://scratch.mit.edu/projects/578255313/ for the Scratch Engine!
        :param text: The text to encode
        """
        return self.encoder.encode(text)

    def decode(self, encoded_text):
        """
        Decode a text. For example: 1 -> A
        Go to https://scratch.mit.edu/projects/578255313/ for the Scratch Engine!
        :param encoded_text: The text to decode
        """
        return self.encoder.decode(encoded_text)

    def encode_list(self, data):
        """
        Encode a Python List
        :param data: The list
        """
        return self.encoder.encode_list(data)

    def decode_list(self, encoded_data):
        """
        Decode a Python List
        :param encoded_data: The data to be decoded
        """
        return self.encoder.decode_list(encoded_data)


import argparse
import os

import numpy as np

from src.config import lstm_cfg, lstm_cfg_ascend
from src.dataset import lstm_create_dataset, convert_to_mindrecord
from src.lstm import SentimentNet
from mindspore import Tensor, nn, Model, context
from mindspore.nn import Accuracy, Recall, F1
from mindspore.train.serialization import load_checkpoint, load_param_into_net

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='MindSpore LSTM Example')
    parser.add_argument('--preprocess', type=str, default='false', choices=['true', 'false'],
                        help='whether to preprocess data.')
    parser.add_argument('--aclimdb_path', type=str, default="./aclImdb",
                        help='path where the dataset is stored.')
    parser.add_argument('--glove_path', type=str, default="./glove",
                        help='path where the GloVe is stored.')
    parser.add_argument('--preprocess_path', type=str, default="./preprocess",
                        help='path where the pre-process data is stored.')
    parser.add_argument('--ckpt_path', type=str, default=None,
                        help='the checkpoint file path used to evaluate model.')
    parser.add_argument('--device_target', type=str, default="Ascend", choices=['GPU', 'CPU', 'Ascend'],
                        help='the target device to run, support "GPU", "CPU". Default: "Ascend".')
    args = parser.parse_args()

    context.set_context(
        mode=context.GRAPH_MODE,
        save_graphs=False,
        device_target=args.device_target)

    if args.device_target == 'Ascend':
        cfg = lstm_cfg_ascend
    else:
        cfg = lstm_cfg

    if args.preprocess == "true":
        print("============== Starting Data Pre-processing ==============")
        convert_to_mindrecord(cfg.embed_size, args.aclimdb_path, args.preprocess_path, args.glove_path)

    embedding_table = np.loadtxt(os.path.join(args.preprocess_path, "weight.txt")).astype(np.float32)
    # DynamicRNN in this network on Ascend platform only support the condition that the shape of input_size
    # and hiddle_size is multiples of 16, this problem will be solved later.
    if args.device_target == 'Ascend':
        pad_num = int(np.ceil(cfg.embed_size / 16) * 16 - cfg.embed_size)
        if pad_num > 0:
            embedding_table = np.pad(embedding_table, [(0, 0), (0, pad_num)], 'constant')
        cfg.embed_size = int(np.ceil(cfg.embed_size / 16) * 16)

    network = SentimentNet(vocab_size=embedding_table.shape[0],
                           embed_size=cfg.embed_size,
                           num_hiddens=cfg.num_hiddens,
                           num_layers=cfg.num_layers,
                           bidirectional=cfg.bidirectional,
                           num_classes=cfg.num_classes,
                           weight=Tensor(embedding_table),
                           batch_size=cfg.batch_size)

    loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
    ds_eval = lstm_create_dataset(args.preprocess_path, cfg.batch_size, training=False)

    model = Model(network, loss, metrics={'acc': Accuracy(), 'recall': Recall(), 'f1': F1()})

    print("============== Starting Testing ==============")
    param_dict = load_checkpoint(args.ckpt_path)
    load_param_into_net(network, param_dict)
    if args.device_target == "CPU":
        acc = model.eval(ds_eval, dataset_sink_mode=False)
    else:
        acc = model.eval(ds_eval)
    print("============== {} ==============".format(acc))


from .models import Vehicle_Bookings_Log
from django.utils import timezone
def delete_expired_discounts():
    current_time = timezone.now()
    end_of_rent = Vehicle_Bookings_Log.objects.filter(returned_on__lte = current_time)
    for log in end_of_rent:
        vehicle = log.vehicle
        vehicle.is_booked = False
        vehicle.save()


import sys
from collections import deque
input = sys.stdin.readline

def dslr(n):
    ret = []
    d = n * 2
    ret.append((d, 'D') if d <= 9999 else (d % 10000, 'D'))
    ret.append((n - 1, 'S') if n > 0 else (9999, 'S'))
    strn = str(n + 10000)[1:]
    l = strn[1:] + strn[0]
    r = strn[-1] + strn[:-1]
    ret.append((int(l), 'L'))
    ret.append((int(r), 'R'))
    return ret

def bfs(a, b):
    dq = deque()
    dq.append([a,[]])
    chk = [False] * 10000

    while dq:
        n, com = dq.popleft()
        for val, oper in dslr(n):
            if not chk[val]:
                ncom = com + [oper]
                chk[val] = True
                if val == b:
                    print(''.join(ncom))
                    return
                dq.append((val, ncom))

for _ in range(int(input())):
    a, b = map(int, input().split())
    bfs(a, b)


#38 archivoexternosII :manipulación del puntero
from io import open

archivo_texto=open("archivopython2.txt","r")

print(archivo_texto.read())  #puntero al inicio del contenido del txt, y empieza a leer
print(archivo_texto.read())  #cuando termina de leer el puntero se encuentra al final, por lo tanto no imprime nada

#seek()

print("*********Usando seek *********")

archivo_texto.seek(0)      #puntero se regresa al principio
print(archivo_texto.read())

archivo_texto.seek(9)  #puntero en el caracter de la posicion 9(contando vacios tmbn)  e imprime lo de la pos7 y lo demás
print(archivo_texto.read())

archivo_texto.seek(0)
print(archivo_texto.read(9)) #lee hasta donde diga que se posicione el puntero,sin lo que este en la pos7 y adelante

#seguir imprimiendo desde donde se quedó
print(archivo_texto.read())

archivo_texto.seek(0)
#leyendo desde la mitad
archivo_texto.seek(len(archivo_texto.read())/2)
print(archivo_texto.read())

# leer desde la sigueinte linea
archivo_texto.seek(0)
archivo_texto.seek(len(archivo_texto.readline()))
print(archivo_texto.read())

#LECTURA Y ESCRITURA   r+

archivo_texto1=open("archivopython3.txt","r+")
#archivo_texto1.write("JUGOS")
#print(archivo_texto1.read()) #no aparece modificado aun
print(archivo_texto1.readlines())

#modificamos  una linea del txt

archivo_texto1.seek(0)
lista_texto=archivo_texto1.readlines()
lista_texto[1]="linea insertada \n"

archivo_texto1.seek(0)
archivo_texto1.writelines(lista_texto)
archivo_texto1.close()


#!/opt/conda/envs/dsenv/bin/python
from joblib import load
import pandas as pd
import pyspark.sql.functions as f
from pyspark.ml.functions import vector_to_array
from pyspark.sql.types import StructType, StructField, DoubleType, StringType, BooleanType, TimestampType
from pyspark.ml.linalg import VectorUDT

import os
import sys

SPARK_HOME = "/usr/lib/spark3"
PYSPARK_PYTHON = "/opt/conda/envs/dsenv/bin/python"
os.environ["PYSPARK_PYTHON"]= PYSPARK_PYTHON
os.environ["PYSPARK_DRIVER_PYTHON"]= PYSPARK_PYTHON
os.environ["SPARK_HOME"] = SPARK_HOME

PYSPARK_HOME = os.path.join(SPARK_HOME, "python/lib")
sys.path.insert(0, os.path.join(PYSPARK_HOME, "py4j-0.10.9.3-src.zip"))
sys.path.insert(0, os.path.join(PYSPARK_HOME, "pyspark.zip"))

from pyspark import SparkConf
from pyspark.sql import SparkSession
from pyspark.sql.types import *

conf = SparkConf()

spark = SparkSession.builder.config(conf=conf).appName("SparkML_hw").getOrCreate()

model = load(sys.argv[6])

model = spark.sparkContext.broadcast(model)

@f.pandas_udf(FloatType())
def predict(vector):
    pred = model.value.predict(vector.tolist())
    return pd.Series(pred)

schema = StructType([
    StructField("vote", StringType()),
    StructField("verified", BooleanType()),
    StructField("reviewTime", StringType()),
    StructField("reviewerID", StringType()),
    StructField("asin", StringType()),
    StructField("id", StringType()),
    StructField("reviewerName", StringType()),
    StructField("reviewText", StringType()),
    StructField("summary", StringType()),
    StructField("unixReviewTime", TimestampType()),
    StructField("words", VectorUDT()),
    StructField("words_without_stop", VectorUDT()),
    StructField("words_hashed", VectorUDT()),
    StructField("words_final", VectorUDT())
])

df = spark.read.json(sys.argv[2], schema=schema)

df = df.withColumn('label_pred', predict(vector_to_array('words_final')))
#df = df.withColumn("id",f.monotonically_increasing_id())
df = df.fillna({"label_pred": 0.0})
print(df.select("id", "label_pred").show(10))
df.select("id", "label_pred").write.mode('overwrite').csv(sys.argv[4], header='false')
spark.stop()


#!/usr/bin/env python
import sys
sys.path.append('./lib/')
from boris_method import boris_push
from emf import EMF
from particle import Particle
from radiation import spectrum_calculation
from plotter import PlotTrajectory, PlotSpectrum, PlotDiagramm
import numpy as np

import matplotlib.pyplot as plt

# Config
nt = 1000
t_span = (0., 100.)

q = 1.
m = 1.
x0 = np.array([0, 0, 0]).astype(np.double)
p0 = np.array([-10.0, 0.0, 0.0]).astype(np.double)
ReactionForce = True

objPtcl = Particle(q, m, x0, p0)
objEMF = EMF(0, 10)

trj = boris_push(objPtcl, objEMF, t_span, nt, ReactionForce)

PlotTrajectory(trj[0], trj[1]).draw()

n = np.array([0, 1, 0]).astype(np.double)
frequencies_bound = (0., 6.28)
freq_dens = 500
spct = spectrum_calculation(trj[0], trj[1], trj[2], trj[3], n, frequencies_bound, freq_dens, objPtcl)

PlotSpectrum(spct[0], spct[1]).draw()

tht_span = (0., 2*np.pi)
nTht = 628

tht = np.linspace(tht_span[0], tht_span[1], nTht)
heatmap = np.zeros((nTht, freq_dens))
for i in range(nTht):
    n[0] = np.sin(tht[i])
    n[1] = 0
    n[2] = np.cos(tht[i])
    heatmap[i][:] = spectrum_calculation(trj[0], trj[1], trj[2], trj[3], n, frequencies_bound, freq_dens, objPtcl)[1][:]
else:
    omg = np.linspace(frequencies_bound[0], frequencies_bound[1], freq_dens)

X, Y = np.meshgrid(omg, tht)

PlotDiagramm(X, Y, heatmap).draw()


import os

from setuptools import find_packages, setup

from errortext import __version__

# Read the long description from the README file.
_setup_folder = os.path.dirname(__file__)
with open(os.path.join(_setup_folder, "README.md"), encoding="utf-8") as readme_file:
    long_description = readme_file.read()

setup(
    name="errortext",
    version=__version__,
    description="Provide error messages for Python exceptions, even if the original message is empty",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/roskakori/errortext",
    project_urls={
        "Changes": "https://github.com/roskakori/errortext/blob/main/CHANGES.md",
        "Issue Tracker": "https://github.com/roskakori/errortext/issues",
    },
    author="Thomas Aglassinger",
    author_email="roskakori@users.sourceforge.net",
    license="BSD",
    classifiers=[
        "Development Status :: 4 - Beta",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: BSD License",
        "Natural Language :: English",
        "Operating System :: OS Independent",
        "Programming Language :: Python :: 3 :: Only",
        "Programming Language :: Python :: 3.6",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Topic :: Software Development",
    ],
    keywords=["error", "error handling", "error message", "exception", "exception handling"],
    packages=find_packages(exclude=["tests"]),
    install_requires=[""],
    python_requires=">=3.6",
)


import argparse
import requests
from string import Template

def main():

  ####################################
  ### Parse command line arguments ###
  ####################################
  parser = argparse.ArgumentParser()

  parser.add_argument('--newRelicApiKey', help='New Relic API Key.')
  parser.add_argument('--accountId', help='New Relic Account ID.')
  parser.add_argument('--notificationChannelId', help='ID of the notification channel.')
  parser.add_argument('--workflowName', help='Name of the workflow.')
  parser.add_argument('--alertPolicyIds', help='IDs of the alert policies in CSV format.')

  args = parser.parse_args()

  newRelicApiKey = args.newRelicApiKey
  if newRelicApiKey == None:
    print('New Relic API Key is not given!')
    return

  accountId = args.accountId
  if accountId == None:
    print('Account ID is not given!')
    return

  notificationChannelId = args.notificationChannelId
  if notificationChannelId == None:
    print('Notification channel ID is not given!')
    return

  workflowName = args.workflowName
  if workflowName == None:
    print('Workflow name is not given!')
    return

  alertPolicyIds = args.alertPolicyIds
  if alertPolicyIds == None:
    print('Alert policy ID(s) are not given!')
    return
  #########

  #######################
  ### Execute request ###
  #######################
  headers = {
    "Api-Key": newRelicApiKey,
    "Content-Type": 'application/json'
  }

  queryTemplate = Template("""
  mutation {
    aiWorkflowsCreateWorkflow(createWorkflowData: {
      destinationConfigurations: {
        channelId: "$notificationChannelId"
      },
      mutingRulesHandling: NOTIFY_ALL_ISSUES,
      workflowEnabled: true,
      name: "$workflowName",
      destinationsEnabled: true,
      issuesFilter: {
        name: "Test",
        predicates: {
          attribute: "labels.policyIds",
          operator: CONTAINS,
          values: "$alertPolicyIds"
        },
        type: FILTER
      }
    },
    accountId: $accountId
  ) {
      workflow {
        id
      }
      errors {
        type
        description
      }
    }
  }
  """)

  # Put variables
  query = queryTemplate.substitute(
    accountId=accountId,
    notificationChannelId=notificationChannelId,
    workflowName=workflowName,
    alertPolicyIds=alertPolicyIds,
  )

  # Execute request
  request = requests.post(
    'https://api.eu.newrelic.com/graphql',
    json={'query': query},
    headers=headers
  )

  if request.status_code != 200:
    print("Query failed to run by returning code of {}. {}".format(request.status_code, query))
    return

  result = request.json()
  print(result)
  #########

main()


from sklearn.manifold import t_sne
import matplotlib.pyplot as plt
import os
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
import numpy as np
from torch.autograd import Variable

def plot_features(source_features, target_features):

    tsne_source = t_sne.TSNE().fit_transform(source_features.cpu())
    tsne_target = t_sne.TSNE().fit_transform(target_features.cpu())

    # plt.close()
    plt.scatter(tsne_source[:, 0], tsne_source[:, 1], color='b', s=1, label='svhn')
    plt.scatter(tsne_target[:, 0], tsne_target[:, 1], color='r', s=1, label='mnist')
    plt.title('lstm_model')
    plt.legend()
    plt.show()

    save_dir = './results/img/tsne_features/'
    if not os.path.isdir(save_dir):
        os.makedirs(save_dir)
    plt.savefig(save_dir + 'lstm_model' + '.png')
    print('Figure saved at ' + save_dir + '.png')

    return tsne_source,tsne_target
def plot_tsne(source_features,target_features,src_id,tgt_id,state='before'):
    tsne_source = TSNE(n_components=2,random_state=1).fit_transform(source_features.cpu())
    tsne_target = TSNE(n_components=2,random_state=1).fit_transform(target_features.cpu())
    fig, ax = plt.subplots(figsize=(16, 10))
    # scatter_src = ax.scatter(tsne_source[:, 0], tsne_source[:, 1], c=y_test.cpu())
    # scatter_tgt = ax.scatter(tsne_target[:, 0], tsne_target[:, 1], c=y_test.cpu())

    plt.scatter(tsne_source[:, 0], tsne_source[:, 1], color='b', s=1, label=src_id)
    plt.scatter(tsne_target[:, 0], tsne_target[:, 1], color='r', s=1, label=tgt_id)
    plt.legend()
    # legend1 = ax.legend(*scatter.legend_elements(),
    #                     loc="lower left", title="Classes")
    # ax.add_artist(legend1)

    save_dir = './results/img/tsne_2/'
    if not os.path.isdir(save_dir):
        os.makedirs(save_dir)
    plt.savefig(save_dir + 'lstm_model_'+'_'+ src_id +'_'+ tgt_id+'_'+state+'train_data.png')
    plt.show()
    return tsne_source,tsne_target

# fig=plt.figure(figsize=(16,10))
# plt.xticks(np.arange(0,205,5))
# plt.title('RMSE of LSTM Same Domain')
# for i in range(0,len(rmse_plot_test)):
#     plt.plot(rmse_plot_test[i], label='Dataset %s'%i)
# plt.legend()
# plt.show()
# fig.savefig('lstm_same_domain.png')
#
# #%% md
#
# ### Cross Domain Plotting
#
# #%%
#
# x=[];y=[]
# for i in range (4):
#      for j in range(4):
#         if i != j:
#             x.append(i)
#             y.append(j)
# print(x,y)
# #=======================#
#
# fig=plt.figure(figsize=(16,10))
# # plt.xticks(np.arange(0,205,5))
# plt.rcParams.update({'font.size': 10})
# plt.axvline(x=99, color='green',linestyle='dashed')
# plt.axvline(x=33, colosr='orange',linestyle='dashed')
# plt.axvline(x=102, color='blue',linestyle='dashed')
# #plt.yticks(np.arange(0,130,10))
# plt.yscale('log')
# plt.title('RMSE of CNN_MMD')
# markers=[',', '+', 'o', '.', 'o', '*', '^','>', '<', ',','+','^' ]
# for i in range(0,3):
#     plt.plot(rmse_cnn_mmd[i], marker=markers[i], label="FD00%d ---> FD00%d " % (x[i]+1,y[i]+1))
# plt.legend()
# plt.show()


from mpl_toolkits.basemap import Basemap, cm
from netCDF4 import Dataset
import numpy as np
import matplotlib.pyplot as plt
import glob
import matplotlib
import matplotlib as mpl
import maputil as mu
#import tcrevars
#reload(tcrevars)
###from tcrevars import * !!!!!!!!!!!!!!!!

def dummyplot():
    x=[0,1,2,3,4,5,6]
    y=[6,4,7,1,8,9,7]
    s4 = {'ls':'','marker':'.',"markevery":2,'markersize':20,'markeredgewidth':0}
    #s4 = {'ls':':'}

    plt.plot(x,y,**s4)
    plt.show()

###### FUNCTIONS related to a Netcdf4 file###########

def plotncdfS(nc,vname,tno):
    ''' Spatial plot of a specific time step (tno) of a given variable (vname) from a netcdf file (nc: tavg type).'''
    # create figure and axes instances
    fig = plt.figure()
    # fig = plt.figure(figsize=(8,8))
    # ax = fig.add_axes([0.1,0.1,0.8,0.8])

    m = Basemap(projection='cyl',lon_0=-90,resolution='c')
    lon2d,lat2d = np.meshgrid(nc.variables['longitude'][:],nc.variables['latitude'][:])

    # map feaures
    m.drawcoastlines()
    m.drawparallels(np.arange(-90.,90.,45.))
    m.drawmeridians(np.arange(-180.,180.,45.))

    # draw filled contours.
    clevs=myscales(vname)

    if isinstance(clevs,str):
        cs = m.contourf(lon2d,lat2d,nc.variables[vname][tno],latlon='false')
    else:
        cs = m.contourf(lon2d,lat2d,nc.variables[vname][tno],clevs,latlon='false')

    # add colorbar.
    cbar = m.colorbar(cs,location='bottom',pad="5%")
    cbar.set_label(nc.variables[vname].units)

    # add title and show
    plt.title(nc.variables[vname].long_name)

#    ts1=nc.variables['time'][tno]
#    ts2=nc.variables['time'].units

#    print ts1,ts2
#    fig.show()
    return fig

def plotncdfT(nc,vname):
    ''' Plot temporal series of a given variable from a netcdf object (nc: tsi type)'''

    xunits=nc.variables['time'].units
    yunits=nc.variables[vname].units

    h=plt.plot(nc.variables['time'][:],nc.variables[vname][:],lw=2)
    #plt.xlim(6000,6099)
    #plt.ylim(13.24,13.31)
    plt.ylabel(nc.variables[vname].long_name.split()[-1]+' ('+yunits+')')
    plt.xlabel('time ('+xunits+')')
    plt.title(nc.variables[vname].long_name)

    ax = plt.gca()
    ax.ticklabel_format(useOffset=False)
    ax.grid(b=True, which='major', linestyle='--')
#    mpl.ticker.ScalarFormatter(useOffset=False)
#    ax.yaxis.set_major_formatter(y_formatter)
#    plt.show()
    return h

###### FUNCTIONS related to a Field() object ###########

class Field():
    """ Classe Field:
    attributes: data, sname, lname, fc (conversion factor), units, scale"""

def extTA(ncfile,vname):
    '''Extract time average into a Field object
    ncfile: tavg.nc'''

    nc = Dataset(ncfile)
    ff = Field()
    ff.vname = vname
    ff.data = nc.variables[vname]
    ff.lats = nc.variables['latitude']
    ff.lons = nc.variables['longitude']
    ff.scale = myscales(vname)
    ff.time=nc.variables['time']

#    convertfield(ff)
    return ff

def extTS(ncfile,vname):
    '''Extract space averaged time series into a Field object
    ncfile: tsi.nc'''
    nc = Dataset(ncfile)
    ff = Field()
    ff.vname = vname
    ff.data = nc.variables[vname]
    ff.scale = myscales(vname)
    ff.time=nc.variables['time']

 #   convertfield(ff)
    return ff

def extTSGP(ncfile,vname):
    '''Extract time series at a specific grid into a Field object
    ncfile: tavg.nc'''
    nc = Dataset(ncfile)
    ff = Field()
    ff.vname = vname
    ff.data = nc.variables[vname]
    ff.scale = myscales(vname)
    ff.data=ff.data[:,80,55]
#    ff.data.units=nc.variables[vname].units
#    ff.data.units='ewrewre'
    ff.time=nc.variables['time']

 #   convertfield(ff)
    return ff

# Deprecated - see maputil.py
def plotmap(field,tno):
    ''' Plot a specific time step (tno) of a Field object.'''
    # create figure and axes instances
    fig = plt.figure()
    # fig = plt.figure(figsize=(8,8))
    # ax = fig.add_axes([0.1,0.1,0.8,0.8])

    m = Basemap(projection='cyl',lon_0=-90,resolution='c')
    lon2d,lat2d = np.meshgrid(field.lons,field.lats)

    # map feaures
    m.drawcoastlines()
    m.drawparallels(np.arange(-90.,90.,45.))
    m.drawmeridians(np.arange(-180.,180.,45.))

    # draw filled contours.
    clevs=field.scale

    if isinstance(clevs,str):
        cs = m.contourf(lon2d,lat2d,field.data[tno],latlon='false')
    else:
        cs = m.contourf(lon2d,lat2d,field.data[tno],clevs,latlon='false')

    # add colorbar.
    cbar = m.colorbar(cs,location='bottom',pad="5%")
    cbar.set_label(field.data.units)

    # add title and show
    plt.title(field.data.long_name)

    #fig.show()
    return fig

######### INFO FUNCTIONS ###########

def myscales(vname):
    if vname is 'A_sat':
        scale=np.arange(-50,40,5)
    elif vname is 'F_precip':
        #scale=[0., 1.,2.,3.,4.,5.]
        scale=np.arange(0,8,1)
    else:
        scale='No scale defined for this variable.'

    return scale

# def convertfield(ff):
#     if ff.vname is 'F_precip':
#         ff.data=86400*ff.data
#         ff.units='mm/day'

#####################################################
############ Spatial plot from raw data

def plotraw2map(data,tno,scale,title,units,nc,simdir,outdir,fname):
    ''' Plot a specific time step (tno) of a 3-D matrix.'''

    # create figure and axes instances
    fig = plt.figure()
    # fig = plt.figure(figsize=(8,8))
    # ax = fig.add_axes([0.1,0.1,0.8,0.8])

    m = Basemap(projection='cyl',lon_0=-90,resolution='c')
    lon2d,lat2d = np.meshgrid(nc.variables['longitude'][:],nc.variables['latitude'][:])

    # map feaures
    m.drawcoastlines()
    m.drawparallels(np.arange(-90.,90.,45.))
    m.drawmeridians(np.arange(-180.,180.,45.))

    # draw filled contours.
    clevs=np.arange(scale[0],scale[1],scale[2])

#    if isinstance(clevs,str):
#    cs = m.contourf(lon2d,lat2d,data[tno],latlon='false')
#    else:
    cs = m.contourf(lon2d,lat2d,data[tno],clevs,latlon='false')

    # add colorbar.
    cbar = m.colorbar(cs,location='bottom',pad="5%")
    cbar.set_label(units)

    # add title and show
    plt.title(title)

    fig.show()

    if outdir:
        plt.savefig(outdir+fname+'.eps')
        plt.savefig(outdir+fname+'.png',dpi=60)

    return fig

################## Fonction colormap ##############################

# Moved to maputils
# def easycmap(ncol):

#     cmap = mpl.cm.jet
#     cstep=cmap.N/float(ncol)
#     cmapdiscrete=[cmap(int(i)) for i in np.arange(0,cmap.N,cstep)]
#     #cmaplist = [cmap(i) for i in range(cmap.N)]
#     #cmap = cmap.from_list('Custom cmap', cmaplist, cmap.N)
#     #bounds = linspace(0,len(my_values),len(my_values)+1)

#     #print np.arange(0,cmap.N-1,cstep)

#     return cmapdiscrete

def cmap_discretize(cmap, N):
    """Return a discrete colormap from the continuous colormap cmap.

    cmap: colormap instance, eg. cm.jet.
    N: number of colors.

    Example
    x = resize(arange(100), (5,100))
    djet = cmap_discretize(cm.jet, 5)
    imshow(x, cmap=djet)
    """

    if type(cmap) == str:
        cmap = matplotlib.cm.get_cmap(cmap)
        colors_i = np.concatenate((np.linspace(0, 1., N), (0.,0.,0.,0.)))
        colors_rgba = cmap(colors_i)
        indices = np.linspace(0, 1., N+1)
        cdict = {}
    for ki,key in enumerate(('red','green','blue')):
        cdict[key] = [ (indices[i], colors_rgba[i-1,ki], colors_rgba[i,ki]) for i in xrange(N+1) ]

    # Return colormap object.
    return matplotlib.colors.LinearSegmentedColormap(cmap.name + "_%d"%N, cdict, 1024)

####################### Legend and Color cycle ###########################

def legcolsty(numcol=11,mixid=1):
    '''cx: palette de couleurs
    sx: types de symbole'''

    # c1='b'
    # c2='g'
    # c3='r'
    # c4='m'
    # c5='c'
    # c6='y'
    # c7=(0.6,0.3,0.2)
    # c8=(0.5,0.5,0.5)
    # c9=(1,127./255,0)
    # c10=(0,250./255.,154./255.)
    # c11=(1,20./255,147./255)
    #s4 = {'ls':'--',"marker": "d","markevery":5,'markersize':4,'markeredgewidth':0,'lw':0.}
    #s4 = {'ls':'','marker':'.',"markevery":10,'markersize':10,'markeredgewidth':0}

    c0=(0,0,0)
    s1 = {'ls':'-','lw':3}
    s2 = {'ls':'--','lw':3}
    s3 = {'ls':':','lw':6}

    # Mixids
    if mixid==1:
        colv0=mu.easycmap(numcol)
        colv1=colv0
        colv2=[colv0[i] for i in (0,2,4,10)]
        colv=colv0+colv1+colv2+['k']
        lstyv=numcol*[s1]+numcol*[s2]+5*[s3]
    elif mixid==3:
        colv0=mu.easycmap(numcol)
        colv1=colv0
        colv2=[colv0[i] for i in (0,2,4,10)]
        colv=colv0+colv1+colv2+['k']
        lstyv=numcol*[s1]+numcol*[s2]+5*[s1]
    elif mixid==2:
        offsize=8
        colv0=mu.easycmap(numcol)
        colv1=colv0
        colv2=mu.easycmap(offsize)              #8 param!
        colv=colv0+colv1+colv2
        lstyv=numcol*[s1]+numcol*[s1]+offsize*[s2]
    elif mixid==4:
        # RCP only, numcol = num PE and CE
        colv0=mu.easycmap(numcol)
        colv1=colv0
        colv2=[colv0[i] for i in (0,2,4,10)]
        colv=colv2+colv2
        lstyv=4*[s1]+4*[s2]

    # ver pour 11+4+1+4
    # colv0=easycmap(11)
    # colv1=[colv0[i] for i in (0,2,4,10)]+['k']+[colv0[i] for i in (0,2,4,10)]
    # colv=colv0+colv1
    # lstyv=11*[s1]+5*[s2]+4*[s3]

    # pour version 1 du papier
    # colv0=mu.easycmap(numcol)
    # colv1=mu.easycmap(numcol)
    # colv2=[colv0[i] for i in (0,2,4,10)]
    # colv=colv0+colv1+colv2+[c0]+[c0]
    # lstyv=numcol*[s1]+numcol*[s2]+4*[s4]+2*[s4]

    #+4*[s4]+2*[s4]

    # colv1=[colv0[i] for i in (0,2,4,10)]+['k']+[colv0[i] for i in (0,2,4,10)]

    # colv=colv0+colv1

    # colv1=[colv0[i] for i in (0,2,4,10)]+['k']+[colv0[i] for i in (0,2,4,10)]
    # colv=colv0+colv1
    # lstyv=11*[s1]+5*[s2]+4*[s3]

    #lstyv=lstyv[mixid:]

    # General Graphics parameters
    #mpl.rcParams['axes.color_cycle']=colv[mixid:]
    mpl.rcParams['axes.color_cycle']=colv
    mpl.rcParams['legend.frameon']='False'
    mpl.rcParams.update({'font.size': 24})
    #mpl.rcParams.update({'legend.fontsize': 11})
    mpl.rcParams.update({'legend.fontsize': 18})
    mpl.rcParams.update({'grid.linewidth': 0.5})

    return lstyv

# def legendcolors(bid=-1):

#     c1='b'
#     c2='g'
#     c3='r'
#     c4='c'
#     c5='m'
#     c6='y'
#     c7=(0.6,0.3,0.2)
#     c8=(0.5,0.5,0.5)
#     c9=(1,127./255,0)
#     c10=(0,250./255.,154./255.)
#     c11=(1,20./255,147./255)

#     #mpl.rcParams['axes.color_cycle']=[c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11]
#     mpl.rcParams['axes.color_cycle']=[c1,c2,c3,c4,c5,c6,c2,c4,c6,c7,c11]

#     print str(mpl.rcParams['axes.color_cycle']) #mpl.rcParams['axes.color_cycle']=['b','g','r','c','m','y',(0.6,0.3,0.2),(0.5,0.5,0.5),(1,127./255,0),(0,250./255.,	154./255.)]

#     if bid >= 0:
#         #mpl.rcParams['axes.color_cycle'].pop(bid)
#         mpl.rcParams['axes.color_cycle'].insert(bid,'k')
#     else:
#         mpl.rcParams['axes.color_cycle'].append('k')
#     print str(mpl.rcParams['axes.color_cycle'])

#     mpl.rcParams['legend.frameon']='False'

#     #mpl.rcParams['axes.color_cycle'].insert(bid,mpl.rcParams['axes.color_cycle'].pop(-1))

def testcolorcycle(nc):

    #legendcolors()
    legcolsty()
    nx=100
    x=np.arange(0,nx)
    plt.figure()

    tlist=[]

    for i in np.arange(0,nc):
        #y=i*np.random.randn(nx)
        y=(i+0.1)*x
        plt.plot(x,y,lw=2)
        tlist.append(str(i))

    plt.legend(tlist,2)
    plt.show()

################## Fonction diagnostiques ########################

def diagemi(ncfile):

    nc = Dataset(ncfile)

    nt=nc.variables['time'].size
    diagem=np.zeros(nt)

    for tt in np.arange(1,nt):
        dA=nc.variables['A_totcarb'][tt] - nc.variables['A_totcarb'][tt-1]
        dL=nc.variables['L_totcarb'][tt] - nc.variables['L_totcarb'][tt-1]
        dO=nc.variables['O_totcarb'][tt] - nc.variables['O_totcarb'][tt-1]
        diagem[tt]=dA+dL+dO

    return diagem

#if __name__ == "__main__":
#    import sys
#    plottime(int(sys.argv[1])).show()
#    raw_input('Press enter.')


"""
The Tournesol Twitter Bot admin interface.
"""

from urllib.parse import urljoin

from django.conf import settings
from django.contrib import admin
from django.utils.html import format_html

from .models.tweeted import TweetInfo

@admin.register(TweetInfo)
class TwitterBotAdmin(admin.ModelAdmin):
    """Twitter Bot Admin class"""

    raw_id_fields = ("video",)
    readonly_fields = ("datetime_tweet",)

    list_display = (
        "video",
        "get_video_name",
        "get_video_uploader",
        "bot_name",
        "datetime_tweet",
        "get_twitter_link",
        "get_video_link",
        "tweet_id",
    )
    search_fields = ("video__uid", "video__metadata__name", "video__metadata__uploader")
    list_filter = ["bot_name"]

    @staticmethod
    @admin.display(description="URL of the tweet")
    def get_twitter_link(obj):
        """Return the URI of the tweet."""
        return format_html(
            'Tweet',
            obj.bot_name,
            obj.tweet_id,
        )

    @staticmethod
    @admin.display(ordering="video__metadata__name", description="Video name")
    def get_video_name(obj):
        """Return the video name."""
        return obj.video.metadata.get("name")

    @staticmethod
    @admin.display(ordering="video__metadata__uploader", description="Video uploader")
    def get_video_uploader(obj):
        """Return the video uploader."""
        return obj.video.metadata.get("uploader")

    @staticmethod
    @admin.display(description="Tournesol link")
    def get_video_link(obj):
        """
        Return the Tournesol front end URI of the video, in the poll `videos`.
        """
        video_uri = urljoin(
            settings.REST_REGISTRATION_MAIN_URL, f"entities/yt:{obj.video.video_id}"
        )
        return format_html('Play ▶', video_uri)


import shutil
import cv2
import numpy as np
import os
from matplotlib import pyplot as plt
import time
import mediapipe as mp
# Create a hand landmarker instance with the image mode:

mp_hands = mp.solutions.hands

# mp_holistic = mp.solutions.holistic
mp_drawing = mp.solutions.drawing_utils

def mediapipe_detection(image,model):
    image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
    image.flags.writeable = False
    results = model.process(image)
    image.flags.writeable = True
    image = cv2.cvtColor(image,cv2.COLOR_RGB2BGR)
    return image,results

def draw_styled_landmarks(image,results):
    mp_drawing.draw_landmarks(image,results.left_hand_landmarks, mp_hands.HAND_CONNECTIONS,
                             mp_drawing.DrawingSpec(color=(121,22,76), thickness=1, circle_radius=4),
                             mp_drawing.DrawingSpec(color=(121,44,250), thickness=1, circle_radius=2)
                             )

    mp_drawing.draw_landmarks(image,results.right_hand_landmarks, mp_hands.HAND_CONNECTIONS,
                             mp_drawing.DrawingSpec(color=(245,117,66), thickness=1, circle_radius=1),
                             mp_drawing.DrawingSpec(color=(245,66,230), thickness=1, circle_radius=1)
                             )

def extract_keypoints(results):
    lh = np.array([[res.x, res.y, res.z] for res in results.left_hand_landmarks.landmark]).flatten() if results.left_hand_landmarks else np.zeros(21*3)
    rh = np.array([[res.x, res.y, res.z] for res in results.right_hand_landmarks.landmark]).flatten() if results.right_hand_landmarks else np.zeros(21*3)
    return np.concatenate([lh,rh])

DATA_PATH = os.path.join('processed_data')
#Actions
actions = np.array(['accident','call','doctor','help','hot','lose','pain','thief'])

# create normalized data

local_data_path = os.path.join('data\Raw_Data')
normalized_data_path = os.path.join('normalized')

arr = []

normalized_frames = 60

def normalize_data():
    for action in os.listdir(local_data_path):
        action_path = os.path.join(local_data_path,action)
        os.mkdir(os.path.join(normalized_data_path,action))
        for video_name in os.listdir(action_path):
            video_path = os.path.join(action_path,video_name)
            # print(video_path)
            cap = cv2.VideoCapture(video_path)

            total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
            fps = int(cap.get(cv2.CAP_PROP_FPS))

            frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
            frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
            fourcc = cv2.VideoWriter_fourcc(*'mp4v')

            path= os.path.join(normalized_data_path,action,video_name)
            out = cv2.VideoWriter(path,fourcc,fps,(frame_width,frame_height))
            print(path)
            if total_frames < normalized_frames:
                extra_frames_required = normalized_frames-total_frames
                for _ in range(total_frames):
                    ret,frame = cap.read()
                    if ret:
                        out.write(frame)
                        if extra_frames_required>0:
                            out.write(frame)
                            # cv2.imshow('frams',frame)
                            # if cv2.waitKey(30) & 0xFF == ord('q'):
                            #     break
                            extra_frames_required -= 1
            else:
                for _ in range(normalized_frames):
                    ret,frame = cap.read()
                    if ret:
                        out.write(frame)
            cap.release()
            out.release()

# normalize_data()

# Create a hand landmarker instance with the image mode:
def create_processed_data_with_hand_soluntion():
    mp_hands = mp.solutions.hands

    # Now second step is to set the hands function which will hold the landmarks points
    hands = mp_hands.Hands(static_image_mode=False, max_num_hands=2, min_detection_confidence=0.3,min_tracking_confidence=0.3)

    # Last step is to set up the drawing function of hands landmarks on the image
    mp_drawing = mp.solutions.drawing_utils

    # shutil.rmtree(DATA_PATH)
    os.mkdir(DATA_PATH)
    for action in os.listdir(normalized_data_path):
        action_path = os.path.join(normalized_data_path,action)
        os.mkdir(os.path.join(DATA_PATH,action))
        print(action)
        for video_name in os.listdir(action_path):
            print(video_name)
            video_path = os.path.join(action_path,video_name)
            cap = cv2.VideoCapture(video_path)
            total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

            # make directort
            new_path = os.path.join(DATA_PATH,action,os.path.splitext(video_name)[0])
            os.mkdir(new_path)
            # print(total_frames)

            prev_hands_present=[0,0]
            prev_hands=[[],[]]
            prev_frame=[0,0]

            for frame_num in range(total_frames):
                ret, frame = cap.read()
                image,results = mediapipe_detection(frame,hands)

                hand_coords = [[],[]]

                hands_present=[0,0]
                if not(results.multi_hand_landmarks):
                    break

                for a in results.multi_handedness:
                    if(a.classification[0].label=='Left' and a.classification[0].score>0.85):
                        # print(a.classification)
                        prev_hands_present[0]=1
                        hands_present[0]=1
                    else:
                        # print(a.classification)
                        prev_hands_present[1]=1
                        hands_present[1]=1

                # print(hands_present)

                hands_recorded=[0,0]
                for hand_no, hand_landmarks in enumerate(results.multi_hand_landmarks):
                    if(hand_no>1):
                        break

                    if(hands_present[0] and hands_present[1]):
                        hand_no=hand_no
                    elif(hands_present[0]):
                        hand_no=0
                    else:
                        hand_no=1

                    if(hands_recorded[hand_no]):
                        continue
                    else:
                        hands_recorded[hand_no]=1

                    prev_hands[hand_no]=hand_landmarks
                    prev_frame[hand_no]=frame_num

                    hand_coords[hand_no].append(np.array([[res.x, res.y, res.z] for res in hand_landmarks.landmark]).flatten())

                    mp_drawing.draw_landmarks(
                        frame,
                        hand_landmarks,
                        mp_hands.HAND_CONNECTIONS,
                        mp_drawing.DrawingSpec(color=(245,117,66), thickness=1, circle_radius=1),
                        mp_drawing.DrawingSpec(color=(245,66,230), thickness=1, circle_radius=1))

                # print(len(hand_coords[0]),len(hand_coords[1]))
                # print(len(hand_coords[0][0]) if len(hand_coords[0])!=0 else "," ,len(hand_coords[1][0]) if len(hand_coords[1])!=0 else ",")
                # print(hands_present,prev_hands_present)

                for hand_no in range(len(hands_present)):
                    if(not(prev_hands_present[hand_no]) or hands_present[hand_no] or abs(prev_frame[hand_no]-frame_num)>3):
                        continue
                    # else:
                    #     print(hand_no,frame_num,video_name)

                    hand_landmarks=prev_hands[hand_no]
                    if(type(hand_landmarks)==type([])):
                        continue
                    # else:
                    #     print(hand_no,frame_num,video_name)
                    #     print(hand_landmarks.landmark)

                    hand_coords[hand_no].append(np.array([[res.x, res.y, res.z] for res in hand_landmarks.landmark]).flatten())

                    mp_drawing.draw_landmarks(
                        frame,
                        hand_landmarks,
                        mp_hands.HAND_CONNECTIONS,
                        mp_drawing.DrawingSpec(color=(245,117,66), thickness=1, circle_radius=1),
                        mp_drawing.DrawingSpec(color=(245,66,230), thickness=1, circle_radius=1))

                # print(len(hand_coords[0][0]) if len(hand_coords[0])!=0 else "," ,len(hand_coords[1][0]) if len(hand_coords[1])!=0 else ",")

                if len(hand_coords[0])==0:
                    hand_coords[0].append(np.array(np.zeros(21*3)))

                if len(hand_coords[1])==0:
                    hand_coords[1].append(np.array(np.zeros(21*3)))

                keypoints = np.concatenate([hand_coords[0][0],hand_coords[1][0]])
                # print(len(keypoints),"/n")
                npy_path = os.path.join(new_path,str(frame_num))
                # print(npy_path)
                np.save(npy_path,keypoints)
                # print(keypoints)

                # cv2.imshow('OpenCV feed', frame)
                # if cv2.waitKey(10) & 0xFF == ord('q'):
                #     exit(0)
            # break
            cap.release()

    cv2.destroyAllWindows()

create_processed_data_with_hand_soluntion()

def create_processed_data_with_holistic():
    holistic = mp.solutions.holistic.Holistic(min_detection_confidence=0.2, min_tracking_confidence=0.2,static_image_mode=False,smooth_landmarks=True)
    shutil.rmtree(DATA_PATH)
    os.mkdir(DATA_PATH)

    for action in os.listdir(normalized_data_path):
        action_path = os.path.join(normalized_data_path,action)
        os.mkdir(os.path.join(DATA_PATH,action))
        print(action)
        for video_name in os.listdir(action_path):
            print(video_name)
            video_path = os.path.join(action_path,video_name)
            cap = cv2.VideoCapture(video_path)
            total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

            # make directort
            new_path = os.path.join(DATA_PATH,action,os.path.splitext(video_name)[0])
            os.mkdir(new_path)

            for frame_num in range(total_frames):
                ret, frame = cap.read()
                image,results = mediapipe_detection(frame,holistic)

                # draw_styled_landmarks(image,results)

                # #Wait Logic
                # if frame_num==0:
                #     cv2.putText(image,'Starting Collection',(120,200),
                #                 cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),4,cv2.LINE_AA)
                #     cv2.putText(image,'Collecting frames for {} Video Number {}'.format(action,video_name),(15,12),
                #                 cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),1,cv2.LINE_AA)
                #     cv2.waitKey(2000)

                # else:
                #     cv2.putText(image,'Collecting frames for {} Video Number {}'.format(action,video_name),(15,12),
                #                 cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),1,cv2.LINE_AA)

                #NEW Export keypoints
                keypoints = extract_keypoints(results)
                npy_path = os.path.join(new_path,str(frame_num))
                np.save(npy_path,keypoints)

                #Show to Screen
                # cv2.imshow('OpenCV feed', image)

                # #Breaking the Feed
                # if cv2.waitKey(10) & 0xFF == ord('q'):
                #     break

    cap.release()
    cv2.destroyAllWindows()

# create_processed_data_with_holistic()


import json
from pprint import pprint
import os

from natsort import natsorted
from ruamel.yaml.comments import CommentedMap
from tabulate import tabulate

from waltz.registry import Registry
from waltz.resources.resource import Resource
from waltz.tools.html_markdown_utilities import add_to_front_matter, extract_front_matter, hide_data_in_html, m2h
from waltz.tools.utilities import blockpy_string_to_datetime, to_friendly_date_from_datetime
from waltz.resources.blockpy.blockpy_resource import BlockPyResource

class BlockPyGroup(BlockPyResource):
    name = "blockpy_group"
    name_plural = "blockpy_groups"
    category_names = ["blockpy_group", "blockpy_groups"]
    folder_file = 'index'

    @classmethod
    def decode_json(cls, registry: Registry, data: str, args):
        raw_data = json.loads(data)
        result = CommentedMap()
        result['title'] = raw_data['url']
        result['display title'] = raw_data['name']
        result['resource'] = cls.name
        result['position'] = raw_data['position']
        # Identity
        result['identity'] = CommentedMap()
        result['identity']['owner id'] = raw_data['owner_id']
        result['identity']['owner email'] = raw_data['owner_id__email']
        result['identity']['course id'] = raw_data['course_id']
        # TODO: Fixed, need to remove value
        result['identity']['version downloaded'] = raw_data.get('version', None)
        result['identity']['created'] = to_friendly_date_from_datetime(
            blockpy_string_to_datetime(raw_data['date_created']))
        result['identity']['modified'] = to_friendly_date_from_datetime(
            blockpy_string_to_datetime(raw_data['date_modified']))
        # Forked
        if raw_data['forked_id']:
            result['forked'] = CommentedMap()
            # TODO: Look up forked's url for more info; or perhaps automatically have it downloaded along?
            result['forked']['id'] = raw_data['forked_id']
            result['forked']['version'] = raw_data['forked_version']
        problems = "\n".join(map(str, raw_data['problems']))
        # TODO: Finish dumping the problems
        extra_files = []
        return add_to_front_matter(problems, result), extra_files

    @classmethod
    def encode_json(cls, registry: Registry, data, args):
        # TODO: Finish this
        raise NotImplementedError("Oops, not done yet!")
        regular, waltz, body = extract_front_matter(data)
        identity = waltz.get('identity', {})
        problems = []
        groups = {}
        for question in waltz.get('questions', []):
            if isinstance(question, str):
                # Look up quiz question name
                questions.append(QuizQuestion.encode_question_by_title(registry, question, args))
            elif 'group' in question:
                # This is a question group
                group = QuizGroup.encode_group(registry, question, args)
                groups[group['name']] = group
                questions.extend(QuizGroup.encode_questions(registry, question, args))
            else:
                # This is an embedded question
                questions.append(QuizQuestion.encode_question(registry, question, args))
        # TODO: total_estimated_points from the questions
        return json.dumps({
            'title': waltz['title'],
            'published': waltz.get('published', False),
            'description': body,
            # Settings
            'quiz_type': settings.get('quiz_type', 'assignment'),
            'points_possible': settings.get('points_possible'),
            'allowed_attempts': settings.get('allowed_attempts'),
            'scoring_policy': settings.get('scoring_policy'),
            # Timing
            'due_at': from_friendly_date(timing.get('due_at')),
            'unlock_at': from_friendly_date(timing.get('unlock_at')),
            'lock_at': from_friendly_date(timing.get('lock_at')),
            # Secrecy
            'one_question_at_a_time': secrecy.get('one_question_at_a_time'),
            'shuffle_answers': secrecy.get('shuffle_answers'),
            'time_limit': secrecy.get('time_limit'),
            'cant_go_back': secrecy.get('cant_go_back'),
            'show_correct_answers': secrecy.get('show_correct_answers'),
            'show_correct_answers_last_attempt': secrecy.get('show_correct_answers_last_attempt'),
            'show_correct_answers_at': secrecy.get('show_correct_answers_at'),
            'hide_correct_answers_at': secrecy.get('hide_correct_answers_at'),
            'hide_results': secrecy.get('hide_results'),
            'one_time_results': secrecy.get('one_time_results'),
            'access_code': secrecy.get('access_code'),
            'ip_filter': secrecy.get('ip_filter'),
            # Questions and Groups
            'questions': questions,
            'groups': groups
        })


import pandas as pd
from selenium import webdriver
from bs4 import BeautifulSoup
import time

tlist = []
elist = []

browser = webdriver.Chrome('C:/Temp/chromedriver')
browser.get("https://www.lottecinema.co.kr/NLCHS/Movie/List?flag=5")
browser.implicitly_wait(3)

# 메뉴 선택 - 예매순
menu = browser.find_elements_by_css_selector('#contents div ul li a')
scd = None
for m in menu:
    if m.text == "예매순":
        mv = m
    #print(t.text)
mv.click()  # 클릭

ck = None
while True:
    try:
        sp = browser.find_elements_by_css_selector('#contents div button span')
        for i in sp :
            if i.text == '펼쳐보기':
                ck = i
        ck.click()
    except:
        break

# 영화 제목
title = browser.find_elements_by_css_selector('#contents div ul li.screen_add_box div.btm_info strong')
movie = None
for t in title :
    if t == 'tit_info':
        movie = t
   #print(t.text)
    tlist.append(t.text)
print(tlist)

# 예매율
em = browser.find_elements_by_css_selector('#contents div ul li div span span em')
per = None
for t in em:
    if t == 'tit_info':
        per = t
    #print(t.text)
    elist.append(t.text)

dict_data = zip(tlist, elist)
data = pd.DataFrame(dict_data, columns=['title', 'percent'])
print(data)

time.sleep(5)  # 5초 대기
browser.quit()  # 브라우저 종료


import sys
import numpy as np
import logging
LOGGER = logging.getLogger(__name__)

from pypoisson import poisson_reconstruction
from . import memsurfer_cmod
from .trimesh import TriMesh
from .utils import Timer, test_overlapping_points

# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
class Membrane(object):
    """
       Class to create and manipulate membrane surfaces
    """

    # --------------------------------------------------------------------------
    # constructor
    def __init__(self, points, **kwargs):
        """
        points: ndarray of shape (npoints, 3)
        kwargs:
                labels:         label for each point
                periodic:       boolean flag for periodicity (default: False)
                bbox:           ndarray of shape (nverts, 3)
                                    required for periodic domain
                boundary_layer: float value for boundary layer thickess (default: 0.2)
                                    used only for periodic domain
        """
        # 3d points
        if points.shape[1] !=  3:
            raise ValueError(f'Membrane needs 3D points: got {points.shape}')

        self.points = points
        self.npoints = self.points.shape[0]

        # periodicity information
        self.periodic = kwargs.get('periodic', False)
        if self.periodic:
            self.blayer = kwargs.get('boundary_layer', 0.2)
            if 'bbox' not in list(kwargs.keys()):
                raise ValueError('Periodic membrane needs 3D bounding box: ndarray (2 ,3)')

        # bounding box may be not given, but is needed for periodicity
        if 'bbox' in list(kwargs.keys()):
            self.bbox = kwargs['bbox']
            if self.bbox.shape[0] not in [2, 3]:
                raise ValueError('Membrane needs 3D bounding box: ndarray (2 ,3)')

        # labels for points
        if 'labels' in list(kwargs.keys()):
            self.labels = kwargs['labels']
            if self.labels.shape[0] != self.npoints or len(self.labels.shape) > 1:
                raise ValueError('Membrane expects one label per point')
        else:
            self.labels = None

        LOGGER.info(f'Initializing Membrane with {self.points.shape} points')
        LOGGER.info(f'\t actual bbox = {self.points.min(axis=0)} {self.points.max(axis=0)}')
        if self.periodic and 'bbox' in list(kwargs.keys()):
            LOGGER.info(f'\t given periodic bbox = {self.bbox[0]} {self.bbox[1]}')

        # create point set object
        self.points = self.points.astype(np.float32)
        self.bbox = self.bbox.astype(np.float32)
        self.pset = memsurfer_cmod.PointSet(self.points)

        # check for overlapping points, but no fix!
        test_overlapping_points(self.points, fix=False)

        # different constructs we will compute
        self.pnormals = None
        self.spoints = None
        self.ppoints = None

        self.surf_poisson = None
        self.memb_planar = None
        self.memb_smooth = None
        self.memb_exact = None

        # other properties
        self.attributes = {}

    # --------------------------------------------------------------------------
    def fit_points_to_box_xy(self):
        """
            Fit the points in a periodic domain to the given bounding box
        """
        nadjusted = 0
        boxw = self.bbox[1,:] - self.bbox[0,:]
        for d in range(2):

            l = np.where(self.points[:,d] < self.bbox[0,d])[0]
            if l.shape[0] > 0:
                self.points[l,d] = self.points[l,d] + boxw[d]
                nadjusted += l.shape[0]

            r = np.where(self.points[:,d] > self.bbox[1,d])[0]
            if r.shape[0] > 0:
                self.points[r,d] = self.points[r,d] - boxw[d]
                nadjusted += r.shape[0]

        if nadjusted > 0:
            LOGGER.info(f'\t adjusted bbox = {self.points.min(axis=0)} {self.points.max(axis=0)}')

        return nadjusted

    # --------------------------------------------------------------------------
    def compute_pnormals(self, knbrs=18, ndir_hint=+1):
        """
            Estimate normals for the point set, using k nearest neighhbors
        """
        if self.pnormals is not None:
            return self.pnormals

        cverbose = LOGGER.isEnabledFor(logging.DEBUG)

        LOGGER.info('Computing normals')
        mtimer = Timer()

        # this function will duplicate points within the boundary layer
        if self.periodic:
            self.pset.set_periodic(self.bbox.reshape(-1).tolist(), self.blayer, cverbose)

        self.pset.need_normals(knbrs, cverbose)
        normals = self.pset.get_normals()
        if len(normals) != 3*self.npoints:
            raise ValueError(f'PointSet computed incorrect normals (got {len(normals)} values')

        self.pnormals = np.array(normals).reshape(self.npoints, 3)
        self.pnormals = self.pnormals.astype(np.float32)

        # if the max absolute z doesnt match ndir, then need to invert
        maxAbsZ = np.argmax(np.abs(self.pnormals[:,2]))
        if self.pnormals[maxAbsZ, 2] * ndir_hint < 0:
            LOGGER.debug('Inverting normals')
            self.pnormals *= -1.0

        mtimer.end()
        LOGGER.info(f'Computed {self.pnormals.shape} normals! took {mtimer}')
        LOGGER.info(f'\t normals = {self.pnormals.min(axis=0)}, {self.pnormals.max(axis=0)}')
        return self.pnormals

    # --------------------------------------------------------------------------
    def compute_approx_surface(self, exactness_level=10):
        """
            Compute an approximating surface using Poisson recronstruction
                exactness_level:  controls the smoothness
                        larger exactness_level will fit the points more --> less smooth
        """
        self.compute_pnormals()

        LOGGER.info(f'Computing Poisson surface for {self.npoints} points')
        mtimer = Timer()
        sfaces, sverts = poisson_reconstruction(self.points.tolist(),
                                                self.pnormals.tolist(),
                                                depth=exactness_level)
        mtimer.end()
        LOGGER.info(f'Poisson surface computed! took {mtimer}. '
                    f'created {len(sfaces)} faces and {len(sverts)} vertices.')

        # represent the poisson surface as a triangulation
        self.surf_poisson = TriMesh(sverts, faces=sfaces, label='surf_poisson')

        #self.surf_poisson.write_vtp('_temp3.vtp', {})#params)
        #self.surf_poisson.remesh()
        #self.surf_poisson.write_vtp('_temp3_remeshed.vtp', {})#params)
        LOGGER.info(self.surf_poisson)

    # --------------------------------------------------------------------------
    def compute_membrane_surface(self):
        """
            Compute the membrane surfaces that pass
                through the given set of points
        """

        # 1. parameterize the membrane surface
        self.surf_poisson.parameterize()

        # 2. project the points on the surface and 2D plane
        (self.spoints, self.ppoints) = self.surf_poisson.project_on_surface_and_plane(self.points)

        # 2b. handle overlapping points
        test_overlapping_points(self.spoints, fix=True)
        test_overlapping_points(self.ppoints, fix=True)

        # 3. create a 2D triangulation of the projected points
        self.memb_planar = TriMesh(self.ppoints, periodic=self.periodic, label='memb_planar')
        self.memb_smooth = TriMesh(self.spoints, periodic=self.periodic, label='memb_smooth')
        self.memb_exact  = TriMesh(self.points,  periodic=self.periodic, label='memb_exact')

        if self.periodic:

            # use the bbox of parameterized vertices (= bbox of poisson surface)
            # that is the absolute maximum
            bb0, bb1 = self.surf_poisson.parameterization_bbox()
            self.memb_planar.set_bbox(bb0, bb1)

            # bounding box of the points projected on the surface
            bb0 = self.spoints.min(axis=0)
            bb1 = self.spoints.max(axis=0)
            self.memb_smooth.set_bbox(bb0, bb1)

            # bounding box of the actual points
            bb0 = self.points.min(axis=0)
            bb1 = self.points.max(axis=0)
            self.memb_exact.set_bbox(bb0, bb1)

        # compute delaunay triangulation of the planar points
        self.memb_planar.compute_delaunay()
        self.memb_smooth.copy_triangulation(self.memb_planar)
        self.memb_exact.copy_triangulation(self.memb_planar)

        # ----------------------------------------------------------------------
        # change the bounding box of the planar surface
        if self.periodic:
            bb0 = self.ppoints.min(axis=0)
            bb1 = self.ppoints.max(axis=0)
            self.memb_planar.set_bbox(bb0, bb1)

    # --------------------------------------------------------------------------
    def compute_properties(self, mtype='smooth'):

        assert mtype == 'smooth' or mtype == 'exact'
        if mtype == 'exact':
            self.memb_exact.compute_normals()
            self.memb_exact.compute_pointareas()
            self.memb_exact.compute_curvatures()
        else:
            self.memb_smooth.compute_normals()
            self.memb_smooth.compute_pointareas()
            self.memb_smooth.compute_curvatures()

    # --------------------------------------------------------------------------
    # compute density of points given by plabels
        # on every vertex
    def compute_density(self, type, sigma, name, get_nlipdis, labels=[]):

        nlabels = len(labels)

        if type < 1 or type > 3:
            raise InvalidArgument(f'Invalid density type, {type}. Should be 1 (geodesic), 2 (2D) or 3 (3D)')

        # if labels are not available
        if nlabels == 0 and self.labels.shape is None:
            raise ValueError('Cannot compute density of selected labels, because point labels are not available')

        # estimate density of all points
        if nlabels == 0:
            self.attributes[name] = self.memb_smooth.compute_density(type, sigma, name, get_nlipdis, np.empty([0]))
            return

        # estimate density of a subset of points
        # still compute on all vertices
        if self.labels.shape is None:
            raise ValueError('Cannot compute density of selected labels, because point labels are not available')

        lidxs = np.where(np.in1d(self.labels, labels))[0]
        self.attributes[name] = self.memb_smooth.compute_density(type, sigma, name, get_nlipdis, lidxs)

    # --------------------------------------------------------------------------
    @staticmethod
    def compute_thickness(a, b, mtype='smooth'):

        assert mtype in ['smooth', 'exact']
        if mtype == 'exact':
            a.properties['thickness'] = a.memb_exact.compute_distance_to_surface(b.memb_exact)
            b.properties['thickness'] = b.memb_exact.compute_distance_to_surface(a.memb_exact)
        else:
            a.properties['thickness'] = a.memb_smooth.compute_distance_to_surface(b.memb_smooth)
            b.properties['thickness'] = b.memb_smooth.compute_distance_to_surface(a.memb_smooth)

    # --------------------------------------------------------------------------
    @staticmethod
    def compute_densities(membranes, types, sigmas, get_nlipdis, l):

        labels = [] if l == 'all' else [l]
        for t in types:
            for s in sigmas:
                name = 'density_type{0}_{1}_k{2:.1f}'.format(t, l, s)
                for m in membranes:
                    m.compute_density(t, s, name, get_nlipdis, labels)

    # --------------------------------------------------------------------------
    # A static method that computes and returns a membrane object
    # --------------------------------------------------------------------------
    @staticmethod
    def compute(positions, labels, bbox, periodic):

        knbrs = 18

        # initialize the membrane!
        m = Membrane(positions, labels=labels, periodic=periodic, bbox=bbox)

        # compute the membrane
        m.fit_points_to_box_xy()
        m.compute_pnormals(knbrs)
        m.compute_approx_surface()
        m.compute_membrane_surface()
        return m

    # --------------------------------------------------------------------------
    # --------------------------------------------------------------------------
    def write_all(self, outprefix, params={}):

        pparams = {'normals': self.pnormals}
        if self.labels.shape != (0, 0):
            pparams['labels'] = self.labels

        if True:
            if 'shells' in self.memb_smooth.attributes: #self.memb_smooth.shells is not None:
                pparams['shells'] = self.memb_smooth.attributes['shells']

            # create a temporary mesh just to output the points
            TriMesh(self.points).write_vtp(outprefix+'_points.vtp', pparams)

        if True:
            self.surf_poisson.write_vtp(outprefix + '_surface_poisson.vtp')

        if True:
            for key in list(self.attributes.keys()):
                params[key] = self.attributes[key]

            if 'labels' in pparams.keys():
                params['labels'] = pparams['labels']

            self.memb_planar.write_vtp(outprefix+'_planar.vtp', params)
            self.memb_exact.write_vtp(outprefix+'_membrane_exact.vtp', params)
            self.memb_smooth.write_vtp(outprefix+'_membrane_smooth.vtp', params)

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


import datetime

from aiogram import Router
from aiogram.fsm.context import FSMContext
from aiogram.methods import SendMessage, EditMessageText, DeleteMessage, AnswerCallbackQuery
from aiogram.types import Message, CallbackQuery

from bot import keyboards as kb
from bot.const import NewPost, TypeFile
from bot.db import users, channels, Channels, Post, postChannels, PostChannel, File, media, UrlButton, posts, \
    urlButtons, hiddenButtons, HiddenButton
from bot.states import States
from bot.utils.GetMessage import get_mes
from bot.utils.send_post import send, get_info_post

router = Router()

def check_int(ch: str) -> bool:
    return ch.isdigit()

def get_kb_duration(new_post: NewPost):
    button = {}

    if new_post.duration == 3:
        button.update({"✅3 часа": "duration_3"})
    else:
        button.update({"3 часа": "duration_3"})

    if new_post.duration == 72:
        button.update({"✅72 часа": "duration_72"})
    else:
        button.update({"72 часа": "duration_72"})

    if new_post.duration == 168:
        button.update({"✅7 дней": "duration_168"})
    else:
        button.update({"7 дней": "duration_168"})

    if new_post.duration == 336:
        button.update({"✅14 дней": "duration_336"})
    else:
        button.update({"14 дней": "duration_336"})

    if new_post.duration == 0:
        button.update({"✅Всегда": "duration_0"})
    else:
        button.update({"Всегда": "duration_0"})

    button.update({"<< Назад": "repeat", "Применить": "continue"})
    keyboard = kb.create_keyboard(button, 2, 2, 1, 2)
    return keyboard

def get_kb_time(new_post: NewPost):
    button = {}
    if new_post.time == 1:
        button.update({"✅1 час": 1})
    else:
        button.update({"1 час": 1})

    if new_post.time == 2:
        button.update({"✅1 часа": 2})
    else:
        button.update({"2 часа": 2})

    if new_post.time == 3:
        button.update({"✅3 часа": 3})
    else:
        button.update({"3 часа": 3})

    if new_post.time == 6:
        button.update({"✅6 часов": 6})
    else:
        button.update({"6 часов": 6})

    if new_post.time == 12:
        button.update({"✅12 часов": 12})
    else:
        button.update({"12 часов": 12})

    if new_post.time == 24:
        button.update({"✅24 часа": 24})
    else:
        button.update({"24 часа": 24})

    if new_post.time == 48:
        button.update({"✅48 часов": 48})
    else:
        button.update({"48 часа": 48})

    if new_post.time == 72:
        button.update({"✅72 часа": 72})
    else:
        button.update({"72 часа": 72})

    if new_post.time == 120:
        button.update({"✅5 дней": 120})
    else:
        button.update({"5 дней": 120})

    if new_post.time == 168:
        button.update({"✅7 дней": 168})
    else:
        button.update({"7 дней": 168})

    if new_post.time == 336:
        button.update({"✅14 дней": 336})
    else:
        button.update({"14 дней": 336})

    if new_post.time == 720:
        button.update({"✅1 месяц": 720})
    else:
        button.update({"1 месяц": 720})

    if new_post.time == 0:
        button.update({"✅Не повторять": 0})
    else:
        button.update({"Не повторять": 0})

    button.update({"<< Назад": "continue", "Продолжить >>": "next_time"})
    keyboard = kb.create_keyboard(button, 3, 3, 3, 3, 1, 2)
    return keyboard

def get_kb_by_choice_channel(data: Channels, new_post: NewPost):
    button = {}
    for channel in data:
        if channel.id in new_post.channels:
            button.update({f"✅{channel.name}": f"choice_{channel.id}"})
        else:
            button.update({channel.name: f"choice_{channel.id}"})
    button.update({"<< Назад": "continue"})
    keyboard = kb.create_keyboard(button)
    return keyboard

def get_button(new_post: NewPost) -> dict:
    button = {}
    if new_post.protect:
        button.update({"✅Защитить контент": "protect"})
    else:
        button.update({"❌Защитить контент": "protect"})
    button.update({"Выбор групп/каналов": "choice"})
    button.update({"Автоповтор": "repeat"})
    button.update({"Отложить": "delayed"})
    button.update({"<< Назад": "back_to_create_post"})
    button.update({"Опубликовать": "publish"})
    return button

@router.callback_query(lambda call: call.data == "continue" or call.data == "protect")
async def set_post(call: CallbackQuery, state: FSMContext):
    id = call.from_user.id
    user = users.get(id)
    data = await state.get_data()
    current_state = await state.get_state()
    if current_state == "States:new_post":
        await state.set_state(States.new_post)
    new_post: NewPost = data["post"]
    if call.data == "protect":
        new_post.protect = not new_post.protect
    if not new_post.channels:
        new_post.channels = [new_post.id_channel]
    button = get_button(new_post)
    await state.update_data(post=new_post)
    await EditMessageText(chat_id=id,
                          message_id=user.message_id,
                          text="Настройте параметры публикации нового поста",
                          reply_markup=kb.create_keyboard(button, 2, 2, 2))

@router.callback_query(States.new_post, lambda call: call.data == "choice" or "choice_" in call.data)
async def choice_channel(call: CallbackQuery, state: FSMContext):
    id = call.from_user.id
    user = users.get(id)
    data = await state.get_data()
    new_post: NewPost = data["post"]

    if "choice_" in call.data:
        id_channel = int(call.data.replace("choice_", ""))
        if id_channel == new_post.id_channel:
            await AnswerCallbackQuery(callback_query_id=call.id, text="Нельзя удалить основной канал/группу")
            return 200
        elif id_channel in new_post.channels:
            del new_post.channels[new_post.channels.index(id_channel)]
        else:
            new_post.channels.append(id_channel)
    keyboard = get_kb_by_choice_channel(channels, new_post)
    await EditMessageText(chat_id=id,
                          message_id=user.message_id,
                          text="Выберите группы/каналы для постинга",
                          reply_markup=keyboard)
    await state.update_data(post=new_post)

@router.callback_query(States.new_post, lambda call: call.data == "repeat" or check_int(call.data))
async def choice_repeat(call: CallbackQuery, state: FSMContext):
    id = call.from_user.id
    user = users.get(id)
    data = await state.get_data()
    new_post: NewPost = data["post"]
    if check_int(call.data):
        if int(call.data) == new_post.time:
            await AnswerCallbackQuery(callback_query_id=call.id, text="Уже установлено это время")
            return 200
        new_post.time = int(call.data)
    keyboard = get_kb_time(new_post)
    await EditMessageText(chat_id=id,
                          message_id=user.message_id,
                          text="Выберите периодичность автопостинга",
                          reply_markup=keyboard)

@router.callback_query(States.new_post, lambda call: call.data == "next_time" or "duration_" in call.data)
async def choice_repeat(call: CallbackQuery, state: FSMContext):
    id = call.from_user.id
    user = users.get(id)
    data = await state.get_data()
    new_post: NewPost = data["post"]
    if call.data != "next_time":
        if "duration_" in call.data:
            duration = int(call.data.replace("duration_", ""))
        else:
            duration = new_post.duration
        if duration == new_post.duration:
            await AnswerCallbackQuery(callback_query_id=call.id, text="Уже установлено это время")
            return 200
        new_post.duration = duration
    keyboard = get_kb_duration(new_post)
    await EditMessageText(chat_id=id,
                          message_id=user.message_id,
                          text="Выберите длительнось автопостинга",
                          reply_markup=keyboard)

@router.callback_query(States.new_post, lambda call: call.data == "delayed")
async def choice_repeat(call: CallbackQuery, state: FSMContext):
    id = call.from_user.id
    user = users.get(id)
    data = await state.get_data()
    new_post: NewPost = data["post"]
    await state.set_state(States.delayed)
    await state.update_data(post=new_post)
    text = "Введите когда нужно отправить пост, в формате ЧЧ:ММ\n"
    if new_post.delayed:
        text += f"Выбранное время: {new_post.delayed}"

    await EditMessageText(chat_id=id,
                          message_id=user.message_id,
                          text=text,
                          reply_markup=kb.create_keyboard({"<< Назад": "continue"}))

@router.message(States.delayed)
async def inp_delayed(message: Message, state: FSMContext):
    id = message.from_user.id
    user = users.get(id)
    data = await state.get_data()
    new_post: NewPost = data["post"]
    await DeleteMessage(chat_id=id, message_id=message.message_id)
    if ":" in message.text:
        hour, minutes = message.text.split(":")
        if check_int(hour) and check_int(minutes):
            hour, minutes = int(hour), int(minutes)
            print(hour, minutes)
            if 0 <= hour <= 24 and 0 <= minutes <= 60:
                new_post.delayed = message.text
    button = get_button(new_post)
    await EditMessageText(chat_id=id,
                          message_id=user.message_id,
                          text="Настройте параметры публикации нового поста",
                          reply_markup=kb.create_keyboard(button, 2, 2, 2))
    await state.set_state(States.new_post)
    await state.update_data(post=new_post)

@router.callback_query(States.new_post, lambda call: call.data == "publish" or call.data == "confirm_public")
async def publish_post(call: CallbackQuery, state: FSMContext):
    id = call.from_user.id
    user = users.get(id)
    data = await state.get_data()
    new_post: NewPost = data["post"]
    channel = channels.get(new_post.id_channel)
    if channel.confirm_public and call.data != "confirm_public":
        button = {"Подтвердить опубликование": "confirm_public",
                  "<< Назад": "continue"}
        keyboard = kb.create_keyboard(button)
        await EditMessageText(chat_id=id,
                              message_id=user.message_id,
                              text="Точно отправляем?",
                              reply_markup=keyboard)
    elif call.data == "confirm_public" or not channel.confirm_public:
        await DeleteMessage(chat_id=id, message_id=user.message_id)
        await DeleteMessage(chat_id=id, message_id=new_post.id_post)
        if new_post.media.type is TypeFile.Sticker:
            await DeleteMessage(chat_id=id, message_id=new_post.media.id_sticker)
        mes = await SendMessage(chat_id=id,
                                text=get_mes("messages/start.md"),
                                reply_markup=kb.start)

        user.message_id = mes.message_id
        users.update(user)

        post = Post(new_post.id_post)
        post.text = new_post.text
        post.protect = new_post.protect
        post.time = new_post.time
        post.duration = new_post.duration
        post.delayed = new_post.delayed
        if new_post.channels:
            for key in new_post.channels:
                post_channels = PostChannel(len(postChannels.get_keys()) + 1)
                post_channels.id_post = post.id
                post_channels.id_channel = key
                postChannels.add(post_channels)
        if new_post.media.path is not None:
            post.media = True
            file = File(len(media.get_keys()) + 1)
            file.path_to_file = new_post.media.path
            file.type = new_post.media.type.value
            file.id_post = new_post.id_post
            file.location = new_post.media.location
            media.add(file)
        if new_post.url_button is not None:
            post.button = True
            for el in new_post.url_button.button:
                button = UrlButton(len(urlButtons.get_keys()) + 1)
                button.name = el
                button.url = new_post.url_button.button[el]
                sizes = ""
                for i in new_post.url_button.sizes:
                    sizes += str(i) + " "
                button.sizes = sizes.strip()
                button.id_post = new_post.id_post
                urlButtons.add(button)
        if new_post.hidden_button is not None:
            post.button = True
            hid_button = HiddenButton(len(hiddenButtons.get_keys()) + 1)
            hid_button.name = new_post.hidden_button.name
            hid_button.text_by_subscriber = new_post.hidden_button.text_by_subscriber
            hid_button.text_by_not_subscriber = new_post.hidden_button.text_by_not_subscriber
            hid_button.id_post = new_post.id_post
            hiddenButtons.add(hid_button)

        if new_post.delayed is not None:
            hour, minute = new_post.delayed.split(":")
            hour, minute = int(hour), int(minute)
            now_time = datetime.datetime.now()
            if hour > now_time.hour:
                delayed = datetime.datetime(year=now_time.year, month=now_time.month, day=now_time.day,
                                            hour=hour, minute=minute)
            else:
                delayed = datetime.datetime(year=now_time.year, month=now_time.month,
                                            day=now_time.day + 1, hour=hour, minute=minute)
            post.delayed = delayed.timestamp()
            post.send_time = post.delayed

            if new_post.duration != 0:
                post.end_posting = delayed + datetime.timedelta(hours=new_post.duration)
                post.end_posting = post.end_posting.timestamp()
            else:
                post.end_posting = post.delayed

            posts.add(post)

        else:
            if new_post.time != 0:
                post.send_time = datetime.datetime.now() + datetime.timedelta(hours=new_post.time)
                post.send_time = post.send_time.timestamp()
            else:
                post.send_time = 0

            if new_post.duration != 0:
                post.end_posting = datetime.datetime.now() + datetime.timedelta(hours=new_post.duration)
                post.end_posting = post.end_posting.timestamp()
            else:
                post.end_posting = 0
            posts.add(post)
            data = get_info_post(post)
            text = data[0]
            protect = data[1]
            keyboard = data[2]
            send_media = data[3]
            id_channels = data[4]
            for id in id_channels:
                await send(id=id, text=text, protect_content=protect, keyboard=keyboard, send_media=send_media)
        await state.clear()

setting_post_router = router