from sqlalchemy import create_engine, and_
from sqlalchemy.orm import sessionmaker
import sqlalchemy.orm.query
from datetime import datetime
import os.path
import csv
import scipy.stats as stats
import sys

from cogent.base.model import *

reading_types = ['temperature', 'd_temperature', 'humidity', 'd_humidity', 'tsr', 'par', 'battery', 'd_battery', 'co2', 'aq', 'voc', 'cc','duty','error','size_v1','cc_min','cc_max','cc_kwh']
node_types = ['standard', 'electricity', 'co2', 'aq', 'heat_meter']
reading_limits = {
        'temperature' : (0.0, 50.0),
        'humidity'    : (0.0, 100.0),
        'co2'         : (0.0, 6000.0)
    }

# Yes, run this when this file is imported
calib = {}

def fetch_calib(filename, dtype):
    calib_file = csv.reader(open(os.path.join(os.path.dirname(__file__), 'Calibration', filename), 'r'), delimiter=',')

    for row in calib_file:
        if len(row) == 2:
            node_id,c = row
            m = 1.0
        elif len(row) == 3:
            node_id,m,c = row
        else:
            continue

        if m == '':
            m = 1.0
        if c == '':
            c = 0.0

        node_id = int(node_id)
        m = float(m)
        c = float(c)

        if node_id not in calib:
            calib[node_id] = {}

        calib[node_id][dtype] = (m, c)

fetch_calib('temp_coeffs.csv', 'temperature')
fetch_calib('hum_coeffs.csv', 'humidity')
fetch_calib('co2_coeffs.csv', 'co2')
fetch_calib('voc_coeffs.csv', 'voc')
fetch_calib('aq_coeffs.csv', 'aq')
fetch_calib('cc_coeffs.csv', 'cc')

def get_calibration(session, node_id, reading_type):
    try:
        values = calib[node_id][reading_type]
    except:
        values = (1.0, 0.0)
    return values

def get_calibration_db(session, node_id, reading_type):
	rtype_id = reading_types.index(reading_type)
	row = session.query(Sensor.calibrationSlope, Sensor.calibrationOffset).filter(and_(Sensor.nodeId == node_id, Sensor.sensorTypeId == rtype_id)).first()
	if row == None: return (1.0, 0.0)
	return (row.calibrationSlope, row.calibrationOffset)

def _query_by_node_and_type(session, node_id, reading_type, start_time, end_time, filter_values = True):
    rtype_id = reading_types.index(reading_type)
    if reading_type in reading_limits and filter_values:
        return session.query(Reading.time, Reading.value).filter(and_(
            Reading.time >= start_time,
            Reading.time < end_time,
            Reading.nodeId == node_id,
            Reading.typeId == rtype_id,
            Reading.value >= reading_limits[reading_type][0],
            Reading.value <= reading_limits[reading_type][1]))
    else:
        return session.query(Reading.time, Reading.value).filter(and_(
            Reading.time >= start_time,
            Reading.time < end_time,
            Reading.nodeId == node_id,
            Reading.typeId == rtype_id))

def _query_by_type(session, reading_type, start_time, end_time, filter_values = True):
    rtype_id = reading_types.index(reading_type)
    if reading_type in reading_limits and filter_values:
        return session.query(Reading.nodeId, Reading.time, Reading.value).filter(and_(
            Reading.time >= start_time,
            Reading.time < end_time,
            Reading.typeId == rtype_id,
            Reading.value >= reading_limits[reading_type][0],
            Reading.value <= reading_limits[reading_type][1]))

    else:
        return session.query(Reading.nodeId, Reading.time, Reading.value).filter(and_(
            Reading.time >= start_time,
            Reading.time < end_time,
            Reading.typeId == rtype_id))

def create_db_engine_mysql(username, database, host='localhost'):
    _DBURL = 'mysql://%s@%s/%s?connect_timeout=1' % (username, host, database)
    engine = create_engine(_DBURL, echo=False)
    return engine

def create_session(db_engine):
    Session = sessionmaker(bind=db_engine)
    return Session()

def create_session_mysql(username, database, host='localhost'):
    db_engine = create_db_engine_mysql(username, database, host)
    return create_session(db_engine)

# Need to add an optional Deployment specification
def get_house_address(session, house_id):
    row = session.query(House).filter(House.id==house_id).first()
    return row.address

def get_house_id(session, address):
    row = session.query(House).filter(House.address==address).first()
    return row.id

def get_node_locations_by_house(session, house_id, include_external=True):
    node_details={}

    rows = session.query(Node).filter(Node.houseId==house_id).join(House, Room).order_by(House.address, Room.name)
    for row in rows:
        node_id = int(row.id)

        if row.nodeTypeId == node_types.index('electricity'):
            if include_external:
                node_details['External'] = node_id
        else:
            node_details[row.room.name] = node_id

    return node_details

def get_data_by_type(session, reading_type, start_time = datetime.fromtimestamp(0), end_time = datetime.now(), postprocess=True, cal_func=get_calibration):
    if reading_type in ['d_temperature', 'd_humidity', 'd_battery', 'cc', 'duty', 'error', 'size_v1', 'cc_min', 'cc_max', 'cc_kwh'] and postprocess:
        print >> sys.stderr, "Cleaning is being applied to reading type %s, this is not generally wanted. Check your code!" % reading_type

    rows = _query_by_type(session, reading_type, start_time, end_time, filter_values = False)
    rows.order_by(Reading.time)

    data = {}
    for row in rows:
        node_id = int(row.nodeId)
        if node_id not in data:
            data[node_id] = []
        data[node_id].append((row.time, row.value))

    if cal_func != None:
        for node_id,values in data.iteritems():
            m, c = cal_func(session, node_id, reading_type)
            data[node_id] = [(row[0], m * row[1] + c) for row in values]

    if postprocess:
        data = clean_data(data, reading_type)

    return data

def get_data_by_node_and_type(session, node_id, reading_type, start_time = datetime.fromtimestamp(0), end_time = datetime.now(), postprocess=True, cal_func=get_calibration):
    if reading_type in ['d_temperature', 'd_humidity', 'd_battery', 'cc', 'duty', 'error', 'size_v1', 'cc_min', 'cc_max', 'cc_kwh'] and postprocess:
        print >> sys.stderr, "Cleaning is being applied to reading type %s, this is not generally wanted. Check your code!" % reading_type

    rows = _query_by_node_and_type(session, node_id, reading_type, start_time, end_time, filter_values = False)
    rows.order_by(Reading.time)

    data = []
    for time,value in rows:
        data.append((time, value))

    if cal_func != None:
        m, c = cal_func(session, node_id, reading_type)
        data = [(row[0], m * row[1] + c) for row in data]

    if postprocess:
        data = clean_data(data, reading_type)

    return data

def clean_data(data, reading_type = None):
    if len(data) == 0: return data

    if type(data) == list:
        return _clean_data(data, reading_type)
    elif type(data) == dict:
        cleaned = {}
        for key,value in data.iteritems():
            cd = clean_data(value, reading_type)
            if len(cd) > 0: cleaned[key] = cd
        return cleaned
    elif type(data) == sqlalchemy.orm.query.Query:
        clean_data(data.all(), reading_type)
    else:
        import sys
        print >> sys.stderr, "Bad data for cleaning:", type(data)
        exit(1)

def _clean_data(data, reading_type = None):
    if reading_type != None and reading_type in reading_limits:
        lt, ut = reading_limits[reading_type]
        data = filter(lambda x: x[1] >= lt and x[1] <= ut, data)
    ub, lb = _get_outlier_thresholds([x[1] for x in data])
    cleaned = []
    for (time, value) in data:
        if ((value < ub) and (value > lb)):
            cleaned.append((time, value))
    return cleaned

def _get_outlier_thresholds(data):
    # 1.5 times the IQR from the upper and lower quartiles (2 times the IQR from the median)
    lq  = stats.scoreatpercentile(data, 25)			# Lower quartile (25%)
    uq  = stats.scoreatpercentile(data, 75)			# Upper quartile (75%)
    iqr = uq - lq					                # Interquartile range
    ub  = uq + (1.5 * iqr)			                # Upper outlier threshold
    lb  = lq - (1.5 * iqr)			                # Lower outlier threshold
    return (ub, lb)

def get_yield(session, node_id, reading_type, start_time = datetime.fromtimestamp(0), end_time = datetime.now()):
    days = int((end_time - start_time).days)
    expected_rows = float(days * 288.)

    rows = _query_by_node_and_type(session, node_id, reading_type, start_time, end_time)
    row_count = float(rows.count())

    return (row_count * 100.0) / expected_rows

def get_houses(session):
    houses = {}
    for hid, addr, depl in session.query(House.id, House.address, Deployment.name):
        if depl not in houses:
            houses[depl] = []
        houses[depl].append((hid, addr))
    return houses

def node_is_battery_powered(session, node_id):
    return node_id < 2000

def get_node_type(session, node_id):
    return session.query(Node.nodeTypeId).filter(Node.id==node_id).first()[0]

def node_has_co2(session, node_id):
    node_type = get_node_type(session, node_id)
    if node_type in [2, 3]:
        return True
    return False

def node_has_cc(session, node_id):
    node_type = get_node_type(session, node_id)
    if node_type == 1:
        return True
    return False

def node_has_voc(session, node_id):
    node_type = get_node_type(session, node_id)
    if node_type == 3:
        return True
    return False

def node_has_aq(session, node_id):
    node_type = get_node_type(session, node_id)
    if node_type == 3:
        return True
    return False


#!/usr/bin/python3

# from selenium import webdriver
# from selenium.webdriver.common.keys import Keys
# from selenium.webdriver.common.action_chains import ActionChains
import requests
import json

names = []

def newRandom():
    newRandom.r2 = requests.get('https://www.thecocktaildb.com/api/json/v1/1/random.php')

named = ""
while (len(names) < 30):
    newRandom()
    r1 = json.loads(newRandom.r2.text)
    name = r1['drinks'][0]["strDrink"]
    if name not in names:
        newName = name.replace(" ", ".")
        print("name",newName)
        names.append(newName)
    elif name in names:
        newRandom()
        if name not in names:
            newName = name.replace(" ", ".")
            print("name",newName)
            names.append(newName)

    print(names)

r3 = requests.get("https://www.godaddy.com/domainsearch/find?checkAvail=1&domainToCheck={}".format(names[0]))


#!/usr/bin/env python3
import cv2
from p1n2 import *
import os
import matplotlib.pyplot as plt
import numpy as np

def seq_test_obj(test_object):
    object_attributes = []
    '''
    convert to gray_scale img
    '''

    rows,cols,channel = test_object.shape
    new_image = np.zeros((rows+60, cols+60,3),dtype = np.uint8 )
    new_image[30 : rows+30 , 30:cols+30 ,:] = test_object

    image = new_image.copy()
    img = new_image.copy()

    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    thresh_val = 128

    binary_image = binarize(gray_image, thresh_val = thresh_val)
        #cv2.imwrite('output/' + img_name + "_binary.png", binary_image)

    labeled_image = label(binary_image)
    #plt.imshow(labeled_image,cmap='gray')
    #plt.show()
    #cv2.imwrite('output/' + img_name + "_labeled.png", labeled_image)

    attribute_list = get_attribute(labeled_image)
    #print('attribute list:')
    #print(attribute_list)

    edge_image = detect_edges(binary_image, sigma=0.3, threshold = 0.225 )
    #cv2.imwrite("output/" + img_name + "_edges.png", edge_image)

    edge_attribute_list = get_edge_attribute(labeled_image, edge_image)
    #print('edge attribute list:')
    #print(edge_attribute_list)
    #attributed_edge_image = draw_edge_attributes(img, edge_attribute_list)
    #cv2.imwrite("output/" + img_name + "_edge_attributes.png", attributed_edge_image)
    #plt.imshow(attributed_edge_image)
    #plt.show()

    circle_attribute_list = get_circle_attribute(labeled_image, gray_image)
    #print('circle attribute list:')
    #print(circle_attribute_list)
    #attributed_circle_image = draw_circle_attributes(img, circle_attribute_list)
    #plt.imshow(attributed_circle_image)
    #plt.show()
    #cv2.imwrite("output/" + img_name + "_circle_attributes.png", attributed_circle_image)
    object_attributes.append({
                                  'attribute_list': attribute_list,
                                  'edge_attribute_list': edge_attribute_list,
                                  'circle_attribute_list': circle_attribute_list
                                  })

    return object_attributes

'''

    Args:
        object_database: a list training images and each training image is stored as dictionary with keys name and image
        test_object: test image, a 2D unit8 array

    Returns:
        object_names: a list of filenames from object_database whose patterns match the test image
        You will need to use functions from p1n2.py
'''

def best_match(object_database, test_object):
    object_attributes = []
    for obj in object_database:
        #print("###################################")
        #print(obj['name'])
        '''
        convert to gray_scale img
        '''
        rows,cols,channel = obj['image'].shape

        new_image = np.zeros((rows+60, cols+60,channel),dtype = np.uint8 )
        new_image[30 : rows+30 , 30:cols+30 , :] = obj['image']
        obj['image'] =new_image
        image = obj['image'].copy()
        img =obj['image'].copy()

        gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        thresh_val = 128

        binary_image = binarize(gray_image, thresh_val = thresh_val)
        #cv2.imwrite('output/' + img_name + "_binary.png", binary_image)

        labeled_image = label(binary_image)
        #cv2.imwrite('output/' + img_name + "_labeled.png", labeled_image)

        attribute_list = get_attribute(labeled_image)
        #print('attribute list:')
        #print(attribute_list)

        edge_image = detect_edges(binary_image, sigma=0.3, threshold = 0.225 )
        #cv2.imwrite("output/" + img_name + "_edges.png", edge_image)

        edge_attribute_list = get_edge_attribute(labeled_image, edge_image)
        #print('edge attribute list:')
        #print(edge_attribute_list)
        #attributed_edge_image = draw_edge_attributes(img, edge_attribute_list)
        #cv2.imwrite("output/" + img_name + "_edge_attributes.png", attributed_edge_image)
        #plt.imshow(attributed_edge_image)
        #plt.show()

        circle_attribute_list = get_circle_attribute(labeled_image, gray_image)
        #print('circle attribute list:')
        #print(circle_attribute_list)
        #attributed_circle_image = draw_circle_attributes(img, circle_attribute_list)
        #plt.imshow(attributed_circle_image)
        #plt.show()

        #cv2.imwrite("output/" + img_name + "_circle_attributes.png", attributed_circle_image)
        object_attributes.append({'name': obj['name'] ,
                                  'attribute_list': attribute_list,
                                  'edge_attribute_list': edge_attribute_list,
                                  'circle_attribute_list': circle_attribute_list
                                  })

    # TODO
    object_names = []
    test_object = seq_test_obj(test_object)
    test_objs = test_object[0]
    test_objs_num = len(test_objs['attribute_list'])
    train_objs_num = len(object_attributes)

    for test_num in range(test_objs_num):

        grade1 = 0.0
        grade2 = 0.0
        grade3 = 0.0
        grades = np.zeros((train_objs_num))

        for train_num in range(train_objs_num):
            obj = object_attributes[train_num]

            val1 = np.abs(obj[ 'attribute_list'][0]['roundedness'] - test_objs['attribute_list'][test_num]['roundedness'] )
            if (val1 <= 0.04 ):
                grade1 = 100
            if (0.04<val1 and val1<=0.08):
                grade1 = 80
            if (0.08<val1 and val1<=0.1):
                grade1 = 60
            if (0.1< val1 ):
                grade1 = 0.0

            lines_num1 = len( obj['edge_attribute_list'][0])
            lines_num2 = len( test_objs['edge_attribute_list'][test_num])
            val2 = np.maximum(lines_num1 , lines_num2) / np.maximum ( 1e-4 , np.minimum(lines_num1 , lines_num2))
            if(lines_num1 == lines_num2):
                theta_dif1 = []
                theta_dif2 = []
                length_list1 = []
                length_list2 = []
                if(lines_num1 == 1):
                    grade2 = 100

                if(lines_num1 >1):
                    #print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
                    #print(test_num , train_num)
                    #print(lines_num1)
                    #print(obj['edge_attribute_list'])
                    #print(test_objs['edge_attribute_list'])

                    for line_num in range(0,lines_num1):
                        length = obj['edge_attribute_list'][0][line_num]['length']
                        length_list1.append(length)

                        length = test_objs['edge_attribute_list'][test_num][line_num]['length']
                        length_list2.append(length)

                    length_list1.sort()
                    length_list2.sort()
                    list1 = np.array(length_list1, dtype = np.float)
                    list1 = list1/np.max(list1)

                    list2 = np.array(length_list2, dtype = np.float)
                    list2 = list2/np.max(list2)

                    error1 = np.sum( np.abs(list1 - list2) )

                    for line_num in range(1,lines_num1):
                        theta1 = obj['edge_attribute_list'][0][line_num]['angle']
                        theta2 = obj['edge_attribute_list'][0][line_num-1]['angle']

                        tmp_theta = np.abs(theta1-theta2)
                        if(tmp_theta > np.pi/2):
                            tmp_theta = tmp_theta - np.pi/2
                        theta_dif1.append( tmp_theta  )

                        theta1 = test_objs['edge_attribute_list'][test_num][line_num]['angle']
                        theta2 = test_objs['edge_attribute_list'][test_num][line_num-1]['angle']

                        tmp_theta = np.abs(theta1-theta2)
                        if(tmp_theta > np.pi/2):
                            tmp_theta = tmp_theta - np.pi/2
                        theta_dif2.append( tmp_theta )
                    theta_dif1.sort()
                    theta_dif2.sort()
                    dif1 = np.array(theta_dif1, dtype = np.float)
                    dif2 = np.array(theta_dif2, dtype = np.float)

                    error2 = np.sum(np.abs(dif1-dif2))

                    if(error2 <= np.pi/6.0 and error1<=0.2):
                        grade2 = 100
                    if(error2 > np.pi/6.0 or error1>0.2 ):
                        grade2 = 50

            if (lines_num1 !=lines_num2 and 1.0<val2 <1.1):
                grade2 = 50
            if (1.1< val2 and val2<= 1.5):
                grade2 = 40
            if (1.5< val2 and val2<=5.0):
                grade2 = 20
            if (5 < val2):
                grade2 = 0

            circles_num1 = len( obj['circle_attribute_list'][0])
            circles_num2 = len( test_objs['circle_attribute_list'][test_num])
            grade3 = 0.0
            if(circles_num1 == circles_num2):
                grade3 = 100.0
            grades[ train_num ] = grade1*0.4 + grade2*0.4 + grade3*0.2

            #print(test_num ,train_num)
            #print(grade1,' ',grade2,' ',grade3)
        match = np.argmax(grades)
        object_names.append( object_attributes[match]['name'] )
    return object_names

def main(argv):
    img_name = argv[0]
    #img_name = 'many_objects_1'
    #img_name = 'test1'
    test_img = cv2.imread('test/' + img_name + '.png', cv2.IMREAD_COLOR)

    train_im_names = os.listdir('train/')
    object_database = []

    for train_im_name in train_im_names:
        train_im = cv2.imread('train/' + train_im_name, cv2.IMREAD_COLOR)
        object_database.append({'name': train_im_name, 'image':train_im})
    object_names = best_match(object_database, test_img)
    print(object_names)

if __name__ == '__main__':
    main(sys.argv[1:])

# example usage: python p3.py test1


#coding=utf-8
__author__ = 'CoderSong'
__date__ = '2019/4/16 21:36'

from django import forms
from .models import Comment

'''表单用来收集并向服务器提交用户输入的数据，当用户想要发表评论时，
    根据表单要求发表评论，之后点击评论按钮，这些数据就会发送给某个URL，
    每一个URL对应一个视图函数来处理用户通过表单提交的数据，
    如果合法，那么Django就会将其写入到数据库中，如果不合法，Django就会将错误信息返回给用户，要求用户重新输入合法数据格式
'''
class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        '''model = Comment 表明这个表单对应的数据库模型是 Comment 类
            fields指明表单要显示的字段
        '''
        fields = ['name','email','url','text']


from django.contrib.auth.decorators import login_required

#####################################
# HTML routing imports
#####################################
from django.shortcuts import get_object_or_404, render, redirect
from django.http import HttpResponseRedirect
from django.urls import reverse
# templates
from django.template.loader import render_to_string
# json / serializers
from django.http import JsonResponse

#####################################
# django utils
#####################################
# messages
from django.contrib import messages
# time zones
from django.utils import timezone
# pagination
from django.core.paginator import Paginator, EmptyPage

#####################################
# Necessary models
#####################################
from users.models import CustomUser
from .models import Post,Comment
# notifications
from core.models import NotificationPost, NotificationUser

#####################################
# Necessary forms
#####################################
from .forms import PostForm, CommentForm
from newsfeed.forms import HelpRequestForm

# note! (08/14/22)
# rqeuest.is_ajax has recently be depreciated.
# since this is an archive, here is a new function to replace it.
def is_ajax(request):
    return request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'

@login_required
def viewIndex(request,page=1):
	###################################
	# Inputs:
	# request, page for pagination
	# Outputs:
	# render
	# Utility:
	# view called for index
	###################################

	# note that create post is handled in a different view
	# we use form action to create the objects
	formPostForm = PostForm()
	formCommentForm = CommentForm()

	# order the posts
	# Create a dictionary of {Post:Post comments sorted}
	qsPosts = Post.objects.order_by('-pub_date')

	intPostsPerPage = 3
	# paginate based on number of posts
	paginator = Paginator(qsPosts,intPostsPerPage)

	try:
		qsPosts = paginator.page(page)
	except EmptyPage:
		# if exceed limit go to last page
		qsPosts = paginator.page(paginator.num_pages)

	context = {
		"qsPosts":qsPosts,
		"formPostForm":formPostForm,
		"formCommentForm":formCommentForm,
	}
	# NOTE!
	# request.is_ajax() is depreciated in newer versions of django
	if is_ajax(request):
		posts_html = render_to_string(
			"communities/t/posts.html",
			{'qsPosts':qsPosts}
		)
		data = {
			'posts_html':posts_html,
			'has_next':qsPosts.has_next()
		}
		return JsonResponse(data)

	return render(request,'communities/index.html',context = context)

@login_required
def viewPostPrepare(request):
	context = {

	}

	return render(request,'communities/post_prepare.html',context=context)

@login_required
def viewPostCreate(request):
	###################################
	# Inputs:
	# request
	# Outputs:
	# redirect
	# Utility:
	# view called to create a post
	###################################
	modelPost = Post()

	formPostForm = PostForm(instance=modelPost)

	if request.method == "POST":

		# fill with post data
		formPostForm = PostForm(request.POST)

		modelCreatedPost = formPostForm.save(commit=False)

		formPostForm = PostForm(request.POST)

		if formPostForm.is_valid():
			# save the object
			user = request.user

			modelCreatedPost.author = user

			modelCreatedPost.save()

			# show message that post created
			messages.success(request, "Post created.")

			# redirect
			return redirect(reverse('communities:index',kwargs={"page":1}))

	context = {
		"formPostForm":formPostForm,
	}
	return redirect(reverse('communities:index',kwargs={"page":1}))

@login_required
def viewLikeUnlikePost(request,post_id):
	###################################
	# Inputs:
	# request, int
	# Outputs:
	# redirect
	# Utility:
	# view to like or unlike a post
	###################################
	modelPost = get_object_or_404(Post,id=post_id)

	if(modelPost.user_likes.filter(id=request.user.id).exists()):
		modelPost.user_likes.remove(request.user)
	else:

		modelPost.user_likes.add(request.user)

		################
		# Create a notification.
		# populate all fields
		################

		# notify that they liked post
		modelNotificationPost = NotificationPost()
		# give sender
		modelNotificationPost.sender = request.user
		# give recipient
		modelNotificationPost.recipient = modelPost.author
		# link to post
		modelNotificationPost.post = modelPost
		# give text
		modelNotificationPost.text = "{} has liked your post {}.".format(request.user,modelPost.title)

		modelNotificationPost.save()

	return redirect(reverse('communities:index',kwargs={"page":1}))

@login_required
def viewPostDetail(request, slug,username):
	###################################
	# Inputs:
	# request, str slug, str username
	# Outputs:
	# render
	# Utility:
	# view for see post by user
	###################################
	modelPostAuthor = get_object_or_404(CustomUser, username=username)
	modelPost = get_object_or_404(Post,slug=slug,author=modelPostAuthor)

	# filter only those comments that are not replies
	listmodelComments = modelPost.comments.filter(active = True).order_by("pub_date")

	# form for creating a comment
	formCommentForm = CommentForm()

	context = {
		"modelPost":modelPost,
		"listPostComments":listmodelComments,
		"formCommentForm":formCommentForm,
	}
	return render(request, 'communities/post_detail.html',context)

@login_required
def viewProfile(request, username,page=1):
	###################################
	# Inputs:
	# request, str username, page for pagination
	# Outputs:
	# render
	# Utility:
	# view called for public profile
	###################################

	modelUser = get_object_or_404(CustomUser, username = username)
	qsPosts = modelUser.created_post_set.order_by('-pub_date')

	# pagination number of posts per page
	intPostsPerPage = 3
	# paginate based on number of posts
	paginator = Paginator(qsPosts,intPostsPerPage)

	try:
		qsPosts = paginator.page(page)
	except EmptyPage:
		# if exceed limit go to last page
		qsPosts = paginator.page(paginator.num_pages)

	context = {
		"modelViewedUser": modelUser,
		"qsPosts":qsPosts,
	}

	return render(request, "communities/profile.html",context)

############
# Creating comments
# With reference to:
# https://stackoverflow.com/questions/44837733/how-to-make-add-replies-to-comments-in-django
############
@login_required
def viewCreateComment(request,username,slug):
	###################################
	# Inputs:
	# request, str username, str slug
	# Outputs:
	# redirect
	# Utility:
	# view to create comments (or replies)
	###################################
	# get the author
	modelPostAuthor = get_object_or_404(CustomUser,username = username)
	# get the post
	modelPost = get_object_or_404(Post, slug = slug,author = modelPostAuthor)

	if request.method == "POST":
		# get the current user
		modelUser = request.user

		# form for comment
		formCommentForm = CommentForm(data=request.POST)

		if formCommentForm.is_valid():
			modelParentObj = None
			# try to get parent comment id from hidden input
			try:
				intParentId = int(request.POST.get("intParentId"))
			except:
				intParentId = None
			# if parent has been submitted get the parent's id
			if intParentId:
				modelParentObj = Comment.objects.get(id=intParentId)
				# if there exists a parent
				if modelParentObj:
					# create reply
					modelReplyComment = formCommentForm.save(commit=False)
					# put user with comment
					modelReplyComment.author = modelUser
					# put the parent id in the reply
					modelReplyComment.parent = modelParentObj
					# since reply, notify the person you reply to
					modelNotificationToReply = NotificationPost()
					modelNotificationToReply.sender = request.user
					modelNotificationToReply.recipient = modelParentObj.author
					modelNotificationToReply.text = "{} has replied to your comment on post {}.".format(request.user.username,modelPost.title)
					modelNotificationToReply.post = modelPost
					modelNotificationToReply.save()

			# Else, this is a normal comment
			# create but dont save to db
			modelNewComment = formCommentForm.save(commit = False)
			modelNewComment.post = modelPost
			modelNewComment.author = modelUser
			# save
			modelNewComment.save()

			# create a notification for the other users
			# always notify the post owner
			modelNotificationToParent = NotificationPost()
			modelNotificationToParent.sender = request.user
			modelNotificationToParent.recipient = modelPost.author
			modelNotificationToParent.text= "{} has commented on your post {}.".format(request.user.username,modelPost.title)
			modelNotificationToParent.post = modelPost
			modelNotificationToParent.save()
		# if form not valid, show message
		else:
			messages.warning(request,"Message could not be sent. Please try again.")

	return redirect(reverse('communities:post-detail',kwargs={'username':modelPost.author.username,'slug':modelPost.slug}))

@login_required
def viewPostDelete(request,post_id):
	###################################
	# Inputs:
	# request, int
	# Outputs:
	# redirect
	# Utility:
	# view to delete posts
	###################################
	modelPost = get_object_or_404(Post, id = post_id)
	modelPostAuthor = modelPost.author

	###########
	# always check if the user that is calling the function is the user who owns the thing
	###########
	if request.user == modelPostAuthor:
		modelPost.delete()

	return redirect(reverse('communities:index',kwargs={"page":1}))

@login_required
def viewDeleteComment(request,comment_id):
	###################################
	# Inputs:
	# request, int
	# Outputs:
	# HttpResponseRedirect
	# Utility:
	# view to delete comments
	###################################
	modelComment = get_object_or_404(Comment,id = comment_id)
	modelParentPost = modelComment.post
	modelCommentAuthor = modelComment.author

	if request.user == modelCommentAuthor:
		modelComment.delete()

	return redirect(reverse("communities:post-detail",kwargs = {'username':modelParentPost.author.username,'slug':modelParentPost.slug}))

@login_required
def viewAddRemoveFollow(request, username):
	###################################
	# Inputs:
	# request, str username
	# Outputs:
	# HttpResponseRedirect
	# Utility:
	# add or remove follow a user
	###################################
	modelUserToBeFollowed = get_object_or_404(CustomUser,username=username)

	modelCurrentUser = request.user

	if modelCurrentUser != modelUserToBeFollowed:
		if modelUserToBeFollowed not in modelCurrentUser.follows.all():
			# follow
			modelCurrentUser.follows.add(modelUserToBeFollowed)
		else:
			# unfollow
			modelCurrentUser.follows.remove(modelUserToBeFollowed)

	# this never runs if use ajax
	return HttpResponseRedirect('/')

@login_required
def viewLeaderboardIndex(request):
	if not request.user.is_pod_plus_member:
		messages.warning(request,"Only POD+ members may access this page.")
		return redirect("communities:index")

	# else they are a member
	context = {

	}

	return render(request,'communities/leaderboard.html',context=context)


import csv
from bubble_sort_week2 import bubble_sort

def read_columns_from_csv (filename, column_name):

    # Given a csv file this function will read in defined column header and return the contents as a list.
    # : param list : filename : Path to the CSV file and column_name : Name of the target column
    # : return : a list from the specified column

    with open (filename , mode = 'r') as file:
        csv_file = csv.DictReader (file)
        column_data = []

        for row in csv_file:
            if column_name in row:
                column_data.append(int(row[column_name]))

    return (column_data)

def get_minimum_value (list):

    # Given a list of numbers as input this function will return the minimum value .
    # : param list : the list of numbers given as input
    # : return : the minimum value in the list

    minimum = list [0]
    for l in list:
        if l < minimum:
            minimum = l
    return minimum

def get_average (list) :

# Given a list of numbers as input this function will return the numerical average .
# : param list : the list of numbers given as input
# : return : the numerical average of the list

    total = 0
    for l in list :
        total += l

    average = total / len ( list )
    return average

def get_median_value ( list ) :

    # Given a list of numbers as input this function will return the median value .
    # : param list : the function bubble_sort and a list of numbers are given as inputs
    # : return : the median (middle) value of the list

    list1 = list.copy()
    bubble_sort ( list1 )
    median = list1 [ int ( len ( list1 ) /2) ]
    return median

def get_mode (list) :

    # Given a list of numbers as input this function will return the mode value (apears most often) .
    # : param list : a list of numbers are given as inputs
    # : return : the mode value of the list

    highest_freq = 0
    mode = scores [0]
    for score in scores :
        frequency = 0
        for score2 in scores :
            if score == score2 :
                frequency += 1
        if frequency > highest_freq :
            mode = score
            highest_freq = frequency
    return mode

def get_maximum_value ( list ) :

    # Given a list of numbers as input this function will return the maximum value .
    # : param list : the list of numbers given as input
    # : return : the maximum value in the list

    maximum = list [0]
    for l in list :
        if maximum > l :
            maximum = l
        return maximum

def get_sum_of_sq_diff(list):

    # Given a list of numbers and average of the numbers as inputs this function will return the sum of the squared difference.
    # : param list : the list of numbers and a function called "get_average" are given as inputs
    # : return : the sum of squared differences of the list

    mean = get_average(list)
    return sum((x - mean) ** 2 for x in list)

def get_variance(list):

    # Given a list of numbers and the sum of squared differences of the numbers as inputs this function will return the variance.
    # : param list : the list of numbers and a function called "get_sum_of_sq_diff" are given as inputs
    # : return : the variance of the list

    sum_squared_diff = get_sum_of_sq_diff(list)
    return sum_squared_diff / len(list)

def get_stddev(list):

    # Given a list of numbers and the variance of the numbers as inputs this function will return the standard deviation.
    # : param list : the list of numbers and a function called "get_variance" are given as inputs
    # : return : the standard deviation of the list

    variance = get_variance(list)
    return variance ** 0.5

if __name__ == "__main__" :

    csv_file_path = 'example.csv'
    column_name = 'Score'
    scores = read_columns_from_csv(csv_file_path, column_name)

    #scores = read_columns_from_csv ('example.csv')

    average = get_average (scores)
    minimum = get_minimum_value (scores)
    maximum = get_maximum_value (scores)
    median = get_median_value (scores)
    mode = get_mode (scores)
    var = get_variance (scores)
    stddev = get_stddev (scores)

print(f' Average : { average } \n Median : { median } \n Smallest : { minimum } \n Largest : { maximum } ')
print(f' Mode : { mode } \n Variance : {var} \n Stanard Deviation : {stddev}')

import statistics

minimum_value = min(scores)
average_value = statistics.mean(scores)
median_value = statistics.median(scores)
mode_value = statistics.mode(scores)

print("Using the 'statistics' library \nthe minimum value is " + str(minimum_value) + '\n' + "the average is " + str(average_value) + '\n' + "the median is " + str(median_value) + '\n' + "and the mode is " + str(mode_value) )


from setuptools import setup, find_packages
import os

_home = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'Products', 'AttachmentField')

version = open(os.path.join(_home, 'version.txt')).read().strip()

setup(
    name='Products.AttachmentField',
    version=version,
    description="AttachmentField/Widget for Plone",
    long_description=(open(os.path.join(_home, "README.txt")).read() +
                      "\n\n" +
                      open(os.path.join(_home, "CHANGES")).read()),
    # Get more strings from http://www.python.org/pypi?%3Aaction=list_classifiers
    classifiers=[
        "Programming Language :: Python",
        "Framework :: Plone",
        "Topic :: Software Development :: Libraries :: Python Modules",
        ],
    keywords='Plone',
    author='Ingeniweb',
    author_email='support@ingeniweb.com',
    maintainer='Alex Clark',
    maintainer_email='aclark@aclark.net',
    url='http://github.com/collective/Products.AttachmentField',
    license='GPL',
    packages=find_packages(exclude=['ez_setup']),
    namespace_packages=['Products'],
    include_package_data=True,
    zip_safe=False,
    install_requires=[
        'setuptools',
        # -*- Extra requirements: -*-
        ],
    entry_points="""
    # -*- Entry points: -*-
    """,
    )


#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""API Contract Test Case for divisions endpoint."""
import logging
from typing import Union

import pytest
import requests
from jsonschema import validate

from trafficops.tosession import TOSession

# Create and configure logger
logger = logging.getLogger()

Primitive = Union[bool, int, float, str, None]

def test_division_contract(to_session: TOSession,
	response_template_data: list[Union[dict[str, object], list[object], Primitive]],
	division_post_data: dict[str, object]) -> None:
	"""
	Test step to validate keys, values and data types from divisions endpoint
	response.
	:param to_session: Fixture to get Traffic Ops session.
	:param response_template_data: Fixture to get response template data from a prerequisites file.
	:param division_post_dat: Fixture to get sample division data and actual division response.
	"""
	# validate division keys from divisions get response
	logger.info("Accessing divisions endpoint through Traffic ops session.")

	division_name = division_post_data.get("name")
	if not isinstance(division_name, str):
		raise TypeError("malformed cdn in prerequisite data; 'name' not a string")

	division_get_response: tuple[
		Union[dict[str, object], list[Union[dict[str, object], list[object], Primitive]], Primitive],
		requests.Response
	] = to_session.get_divisions(query_params={"name": division_name})
	try:
		division_data = division_get_response[0]
		if not isinstance(division_data, list):
			raise TypeError("malformed API response; 'response' property not an array")

		first_division = division_data[0]
		if not isinstance(first_division, dict):
			raise TypeError("malformed API response; first division in response is not an dict")

		logger.info("Division Api get response %s", first_division)
		division_response_template = response_template_data.get("divisions")
		if not isinstance(division_response_template, dict):
			raise TypeError(
				f"Division response template data must be a dict, not '{type(division_response_template)}'")

		# validate division values from prereq data in divisions get response.
		prereq_values = division_post_data["name"]
		get_values = first_division["name"]

		assert validate(instance=first_division, schema=division_response_template) is None
		assert get_values == prereq_values
	except IndexError:
		logger.error("Either prerequisite data or API response was malformed")
		pytest.fail("Failed due to malformation")


# importing libraries
from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtGui
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from rdflib import Graph, Namespace, Literal
from rdflib.namespace import OWL, RDF, RDFS
from rdflib.plugins.sparql import prepareQuery
import rdflib.plugins.sparql as sparql
import sys, os

aplication_path = os.path.dirname(sys.executable)

# Creation of pyqt5 app
App = QApplication(sys.argv)
win = QMainWindow()
central = QWidget()
win.setCentralWidget(central)

# Widgets used
list_widget = QListWidget()
list_widget2 = QListWidget()
button_accept = QPushButton()
button_return = QPushButton()
label = None

# RDFLib (SmartCity.Madrid)
g = Graph()
g.bind("owl", OWL)
g.bind("rdf", RDF)
g.bind("rdfs", RDFS)

dbo = Namespace("http://www.smartcity.madrid.es/mobility/")
g.bind("dbo", dbo)

data = "output-with-links.nt"
g.parse(data, format="nt")

class Window(QMainWindow):

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

        # setting title
        self.setWindowTitle("Movilidad Madrid")

        # setting geometry
        self.setGeometry(100, 100, 500, 400)

        # calling the Main Window method (Menu)
        self.UiComponents()

        # showing all the widgets (Menu)
        self.show()

    # Second Screen (Once you press the button)
    def buttonReturn():
        window.show()
        win.close()

    # Second Screen (Once you press the button)
    def buttonClicked(_list_widget):

        # creating the widgets
        button_return = QPushButton(win)

        # setting geometry to the widgets
        button_return.setGeometry(30, 595, 135, 30)

        # button widget actions
        button_return.setText("Atrás")

        rows = _list_widget.selectedItems()
        row = rows[0].text()

        # variables for SPARQL queries
        selected = ""
        busList = []
        busListW = []
        lrList =[]
        lrListW =[]
        underList = []
        underListW = []

        # District that has been selected in the last Screen
        items = list_widget.selectedItems()
        for x in range(len(list_widget)):
            if (list_widget.item(x).isSelected()):
                selected = list_widget.item(x).text()

        # Queries To SmartCity.Madrid
        # Bus
        queryB = 'SELECT DISTINCT ?y ?w WHERE { ?y <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.smartcity.madrid.es/mobility/ontology/Bus>. ?y <http://www.smartcity.madrid.es/mobility/ontology/District_Name> "' + selected + '" . ?y <http://www.w3.org/2002/07/owl#sameAs>  ?w . }'
        queryBpq = sparql.prepareQuery(queryB)

        for bus in g.query(queryBpq):
            busList.append(bus.y)
            busListW.append(bus.w)

        # Light rail
        queryLR = 'SELECT DISTINCT ?y ?w WHERE { ?y <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.smartcity.madrid.es/mobility/ontology/LightMetro>. ?y <http://www.smartcity.madrid.es/mobility/ontology/District_Name> "' + selected + '" . ?y <http://www.w3.org/2002/07/owl#sameAs>  ?w . }'
        queryLRpq = sparql.prepareQuery(queryLR)

        for lightRail in g.query(queryLRpq):
            lrList.append(lightRail.y)
            lrListW.append(lightRail.w)

        # Metro
        queryM = 'SELECT DISTINCT ?y ?w WHERE { ?y <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.smartcity.madrid.es/mobility/ontology/Metro>. ?y <http://www.smartcity.madrid.es/mobility/ontology/District_Name> "' + selected + '" . ?y <http://www.w3.org/2002/07/owl#sameAs>  ?w . }'
        queryMpq = sparql.prepareQuery(queryM)

        for metro in g.query(queryMpq):
            underList.append(metro.y)
            underListW.append(metro.w)

        # SCROLLS for the results
        widgetM = QWidget(win)
        widgetB = QWidget(win)
        widgetLR = QWidget(win)
        voxM = QVBoxLayout(win)
        voxB = QVBoxLayout(win)
        voxLR = QVBoxLayout(win)
        scrollAreaM = QScrollArea(win)
        scrollAreaB = QScrollArea(win)
        scrollAreaLR = QScrollArea(win)

        # Metro Scroll
        txtResultQueryM = QLabel(win)
        voxM.addWidget(txtResultQueryM)
        for i in range(len(underList)):
            txtResultQueryM = QLabel(win)
            if i%2 == 0:
                txtResultQueryM.setText(""+ underList[i] +"")
                txtResultQueryM.setTextFormat(Qt.RichText)
                txtResultQueryM.setTextInteractionFlags(Qt.TextBrowserInteraction)
                txtResultQueryM.setOpenExternalLinks(True)

                voxM.addWidget(txtResultQueryM)

        # Bus Scroll
        txtResultQueryB = QLabel(win)
        voxB.addWidget(txtResultQueryB)
        for i in range(len(busList)):
            txtResultQueryB = QLabel(win)
            txtResultQueryB.setText(""+ busList[i] +"")
            txtResultQueryB.setTextFormat(Qt.RichText)
            txtResultQueryB.setTextInteractionFlags(Qt.TextBrowserInteraction)
            txtResultQueryB.setOpenExternalLinks(True)

            voxB.addWidget(txtResultQueryB)

        # LightRail Scroll
        txtResultQueryLR = QLabel(win)
        voxLR.addWidget(txtResultQueryLR)
        for i in range(len(lrList)):
            txtResultQueryLR = QLabel(win)
            if i%2 != 0:
                txtResultQueryLR.setText(""+ lrList[i] +"")
                txtResultQueryLR.setTextFormat(Qt.RichText)
                txtResultQueryLR.setTextInteractionFlags(Qt.TextBrowserInteraction)
                txtResultQueryLR.setOpenExternalLinks(True)

                voxLR.addWidget(txtResultQueryLR)

        widgetM.setLayout(voxM)
        widgetB.setLayout(voxB)
        widgetLR.setLayout(voxLR)

        # ScrollArea Metro
        scrollAreaM.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        scrollAreaM.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        scrollAreaM.setWidgetResizable(True)
        scrollAreaM.setGeometry(200, 80, 640, 150)
        scrollAreaM.setWidget(widgetM)

        # ScrollArea Bus
        scrollAreaB.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        scrollAreaB.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        scrollAreaB.setWidgetResizable(True)
        scrollAreaB.setGeometry(200, 80+190, 640, 150)
        scrollAreaB.setWidget(widgetB)

        # ScrollArea LightRail
        scrollAreaLR.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        scrollAreaLR.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        scrollAreaLR.setWidgetResizable(True)
        scrollAreaLR.setGeometry(200, 80+190+190, 640, 150)
        scrollAreaLR.setWidget(widgetLR)

        title = QLabel("Movilidad en el distrito " + selected, win)
        title.setGeometry(200, -13, 280, 80)
        img = QLabel(win)
        path = os.path.join(os.path.dirname(sys.modules[__name__].__file__), 'distritos_madrid.png')
        mapDistritos = QPixmap(path)
        img.setPixmap(mapDistritos)
        img.setGeometry(1, 100, 200, 200)
        titleM = QLabel("Metros:", win)
        titleM.setGeometry(220, 25, 280, 80)
        titleB = QLabel("Buses:", win)
        titleB.setGeometry(220, 25+190, 280, 80)
        titleLR = QLabel("Metros ligeros:", win)
        titleLR.setGeometry(220, 25+190+190, 280, 80)
        button_return.clicked.connect(lambda: Window.buttonReturn())
        win.show()
        win.setGeometry(100, 100, 860, 640)
        win.setWindowTitle('Movilidad Madrid')
        window.hide()

    # method for components
    def UiComponents(self):
        global list_widget
        global button_accept

        # creating the widgets
        list_widget = QListWidget(self)
        button_accept = QPushButton(self)

        # setting geometry to the widgets
        list_widget.setGeometry(50, 70, 190, 300)
        button_accept.setGeometry(260, 345, 135, 30)

        # button widget actions
        button_accept.setText("Elegir Distrito")

        # list widget items (Districts in order)
        centro = QListWidgetItem("Centro")
        arganzuela = QListWidgetItem("Arganzuela")
        retiro = QListWidgetItem("Retiro")
        salamanca = QListWidgetItem("Salamanca")
        chamartin = QListWidgetItem("Chamartin")
        tetuan = QListWidgetItem("Tetuan")
        chamberi = QListWidgetItem("Chamberi")
        fuencarral_elpardo = QListWidgetItem("Fuencarral-El Pardo")
        moncloa_aravaca = QListWidgetItem("Moncloa-Aravaca")
        latina = QListWidgetItem("Latina")
        carabanchel = QListWidgetItem("Carabanchel")
        usera = QListWidgetItem("Usera")
        puentedevallecas = QListWidgetItem("Puente de Vallecas")
        moratalaz = QListWidgetItem("Moratalaz")
        ciudadlineal = QListWidgetItem("Ciudad Lineal")
        hortaleza = QListWidgetItem("Hortaleza")
        villaverde = QListWidgetItem("Villaverde")
        villadevallecas = QListWidgetItem("Villa de Vallecas")
        vicalvaro = QListWidgetItem("Vicalvaro")
        sanblas_canillejas = QListWidgetItem("San blas-Canillejas")
        barajas = QListWidgetItem("Barajas")

        # adding items to the list widget
        list_widget.addItem(centro)
        list_widget.addItem(arganzuela)
        list_widget.addItem(retiro)
        list_widget.addItem(salamanca)
        list_widget.addItem(chamartin)
        list_widget.addItem(tetuan)
        list_widget.addItem(chamberi)
        list_widget.addItem(fuencarral_elpardo)
        list_widget.addItem(moncloa_aravaca)
        list_widget.addItem(latina)
        list_widget.addItem(carabanchel)
        list_widget.addItem(usera)
        list_widget.addItem(puentedevallecas)
        list_widget.addItem(moratalaz)
        list_widget.addItem(ciudadlineal)
        list_widget.addItem(hortaleza)
        list_widget.addItem(villaverde)
        list_widget.addItem(villadevallecas)
        list_widget.addItem(vicalvaro)
        list_widget.addItem(sanblas_canillejas)
        list_widget.addItem(barajas)

        # setting selection mode property
        list_widget.setSelectionMode(QAbstractItemView.SingleSelection)

        # creating a label
        label = QLabel("Distritos :", self)

        # setting geometry to the label
        label.setGeometry(50, 15, 280, 80)

        # making label multi line
        label.setWordWrap(True)
        button_accept.clicked.connect(lambda: Window.buttonClicked(list_widget))
        label.setWordWrap(True)
        ttl1 = QLabel("Movilidad en Madrid", self)
        ttl1.setGeometry(200, -13, 280, 80)
        img = QLabel(self)
        path = os.path.join(os.path.dirname(sys.modules[__name__].__file__), 'distritos_madrid.png')
        mapDistritos = QPixmap(path)
        img.setPixmap(mapDistritos)
        img.setGeometry(300, 100, 200, 200)

# create the instance of our Window
window = Window()

# start the app
sys.exit(App.exec())


import json

import ephem
import pytest
from ephem import Observer

from app.helpers import DateTimeEncoder
from app.planets import Sun
from app.views import ObjectsPositionView

#
# def async_test(f):
#     def wrapper(*args, **kwargs):
#         coro = asyncio.coroutine(f)
#         future = coro(*args, **kwargs)
#         loop = asyncio.get_event_loop()
#         loop.run_until_complete(future)
#
#     return wrapper
#
#
# class TestMoon(TestCase):
#     def test_moon_day_calulcation(self):
#         dt = datetime.utcnow()
#         moon = ephem.Moon()
#
#         obs = ephem.Observer()
#         obs.lat = '52.26312730000001'
#         obs.lon = '104.3399244'
#
#         new_moon = ephem.previous_new_moon(dt)
#         next_new_moon = ephem.next_new_moon(dt)
#         next_full_moon = ephem.next_full_moon(dt).datetime() + timedelta(hours=8)
#         last_day = new_moon
#         for i in range(1, 32):
#             obs.date = last_day
#             day_end = obs.next_rising(moon, last_day, True)
#             print("day {} {} - {}".format(i, last_day.datetime() + timedelta(hours=8),
#                                           day_end.datetime() + timedelta(hours=8)))
#             if day_end > next_new_moon:
#                 break
#             last_day = day_end
#
#         moon.compute(obs)
# #         print(moon)
#
# @pytest.fixture
# def observer():
#     obs = ephem.Observer()
#     obs.lat = '52.26312730000001'
#     obs.lon = '104.3399244'
#     return obs
#
#
# async def test_compute_moon(test_client):
#     view = ObjectsPositionView(None)
#     await view.set_location('52.26312730000001', '104.3399244')
#
#
# async def test_computation(test_client):
#     view = ObjectsPositionView(None)
#     await view.set_location(52.26312730000001, 104.3399244)
#     await view.update_positions()

@pytest.fixture
def observer():
    obs = ephem.Observer()
    obs.lat = '52.26312730000001'
    obs.lon = '104.3399244'
    return obs

@pytest.fixture
def view():
    v = ObjectsPositionView(None)
    return v

async def test_profile_computation(view: ObjectsPositionView):
    for _ in range(10000):
        await view.update_positions()
        server_time = view.observer.date.datetime().utcnow().isoformat()
        msg = json.dumps({
            'planets': [planet.to_dict() for name, planet in view.planets.items()],
            'server_time': server_time
        }, cls=DateTimeEncoder)

def test_sun_day(observer):
    planet = Sun()
    planet.compute(observer)

def test_asc_coordinate(observer: Observer):
    asc = ephem.Equatorial(0, 0)
    asc.compute(observer)
    print (asc.az)


import cv2 as cv
import pytesseract
import PIL.Image
from matplotlib import pyplot as plt

"""
Python segmentation modes:
0 = Orientation and script detection (OSD) only.
1 = Automatic page segmentation with OSD.
2 = Automatic page segmentation, but no OSD, or OCR.
3 = Fully automatic page segmentation, but no OSD. (Default)
4 = Assume a single column of text of variable sizes.
5 = Assume a single uniform block of vertically aligned text.
6 = Assume a single uniform block of text.
7 = Treat the image as a single text line.
8 = Treat the image as a single word.
9 = Treat the image as a single word in a circle.
10 = Treat the image as a single character.
11 = Sparse text. Find as much text as possible in no particular order.
12 = Sparse text with OSD.
13 = Raw line. Treat the image as a single text line, bypassing hacks that are Tesseract-specific.

"""

"""
OCR Engine modes:
0 = Original Tesseract only.
1 = Neural nets LSTM only.
2 = Tesseract + LSTM.
3 = Default, based on what is available.
"""

myconfig = r'--oem 3 --psm 6'

wellPerformingConfigs = {
    1: r'--oem 3 --psm 11',
    2: r'--oem 3 --psm 3',
    3: r'--oem 3 --psm 1',
    4: r'--oem 3 --psm 12',
}

# text_cropped = pytesseract.image_to_string(PIL.Image.open('cropped.png'), config=myconfig)
# text_cropped_1 = pytesseract.image_to_string(PIL.Image.open('cropped2.png'), config=myconfig)
# text_uncropped = pytesseract.image_to_string(PIL.Image.open('uncropped.1920x1080.png'), config=myconfig)
# # print(text_cropped + "\n\n\n"+ text_cropped_1)
# print(text_uncropped)

# text1 = pytesseract.image_to_string(PIL.Image.open('1280x720.png'), config=myconfig)
# text2 = pytesseract.image_to_string(PIL.Image.open('1440x900.png'), config=myconfig)
# text3 = pytesseract.image_to_string(PIL.Image.open('1680x1050.png'), config=myconfig)

# print(text2)
cropped = "cropped.png"
cropped1 = "cropped1.png"
cropped2 = "cropped2.png"
uncropped1 = "uncropped.1920x1080.png"
uncropped2 = "1280x720.png"
uncropped3 = "1440x900.png"
uncropped4 = "1680x1050.png"

img = cv.imread(uncropped4)
# convert to grayscale
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# image binarization
_,tresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY|cv.THRESH_OTSU)
# height, width = img.shape
# print(width, height)

## draw boxes on individual characters
# boxes = pytesseract.image_to_boxes(img, config=myconfig)
# print(boxes)
# for box in boxes.splitlines():
#     box = box.split(' ')
#     x, y, w, h = int(box[1]), int(box[2]), int(box[3]), int(box[4])
#     cv.rectangle(img, (x, height-y), (w, height-h), (255, 0, 0), 1)
#     cv.putText(img, box[0], (x, height-y+25), cv.FONT_HERSHEY_COMPLEX, 1, (50, 50, 255), 2)

# draw boxes on words
data = pytesseract.image_to_data(tresh, config=myconfig, output_type=pytesseract.Output.DICT, lang='eng')
print(data['text'])
amountOfWords = len(data['text'])
for i in range(amountOfWords):
    if float(data['conf'][i]) > 30:
        x, y, w, h = int(data['left'][i]), int(data['top'][i]), int(data['width'][i]), int(data['height'][i])
        cv.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 1)
        cv.putText(img, data['text'][i], (x, y), cv.FONT_HERSHEY_COMPLEX, 1, (50, 50, 255), 2)

plt.imshow(tresh, cmap='gray')
plt.show()


import unittest

from security.encryption.symmetric.aes import AdvancedEncryptionStandard
from security.encryption.symmetric.des import DataEncryptionStandard

class SymmetricTests(unittest.TestCase):
    def setUp(self):
        DataEncryptionStandard.set_key("unittest")
        AdvancedEncryptionStandard.set_key("unittestunittest")

    def test_des(self):
        word = "Test Message"
        hashed_word = DataEncryptionStandard.encrypt(word)
        self.assertNotEqual(word, hashed_word)
        self.assertEqual(word, DataEncryptionStandard.decrypt(hashed_word))

    def test_aes(self):
        word = "Test Message"
        hashed_word = AdvancedEncryptionStandard.encrypt(word)
        self.assertNotEqual(word, hashed_word)
        self.assertEqual(word, AdvancedEncryptionStandard.decrypt(hashed_word))


import pickle
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from utils.utils_func import dura_intersection_ts,unique_with_idx_nd,stack_with_padding,stack_with_repeat_2d

class Base_C(nn.Module):
    def __init__(self,config,is_train=True):
        super().__init__()
        self.is_train = is_train

        ## 1. configs
        # 1.1 model configs
        self.num_pred_cats = config["num_pred_cats"]
        self.num_enti_cats = config["num_enti_cats"]
        self.dim_feat = config["dim_feat"]          # 2048 or 1024 (dimension of each bbox's RoI feature, depend on the detector)
        self.dim_clsme = config["dim_clsme"]
        self.dim_enti = config["dim_enti"]
        self.dim_ffn  = config["dim_ffn"]
        self.enco_pool_len = config["enco_pool_len"]
        self.bias_matrix_path = config["bias_matrix_path"]
        self.EntiNameEmb_path = config.get("EntiNameEmb_path",None)
        self.use_clsme = config["use_clsme"]
        self.rt_triplets_topk = config["rt_triplets_topk"]

        if self.EntiNameEmb_path is None:  # for trajs that have classseme feature
            self.EntiNameEmb = None
        else:                              # otherwise, use category of traj to get a classeme feature
            EntiNameEmb = np.load(self.EntiNameEmb_path)
            EntiNameEmb = torch.from_numpy(EntiNameEmb).float()
            self.EntiNameEmb = nn.Parameter(EntiNameEmb, requires_grad = False)
            # shape == (num_enti_cats,dim_emb) == (81,300) or (36, 300) # including background
            assert self.EntiNameEmb.shape == (self.num_enti_cats,self.dim_clsme)

        bias_matrix = np.load(self.bias_matrix_path)
        bias_matrix = torch.from_numpy(bias_matrix).float()
        self.bias_matrix = nn.Parameter(bias_matrix, requires_grad = True)  # shape == (num_enti_cats,num_enti_cats,num_pred_cats) # (81,81,51), including background
        assert self.bias_matrix.shape == (self.num_enti_cats,self.num_enti_cats,self.num_pred_cats)

        ## 3. layers for entity features initialization
        self.fc_feat2enti = nn.Sequential(
            nn.Linear(self.dim_feat,self.dim_enti),
            nn.ReLU(),
            nn.Linear(self.dim_enti,self.dim_enti),
            nn.ReLU()
        )
        self.fc_bbox2enti = nn.Sequential(
            nn.Linear(8,self.dim_enti),
            nn.ReLU(),
            nn.Linear(self.dim_enti,self.dim_enti),
            nn.ReLU()
        )
        self.conv_feat2enti = nn.Conv1d(self.dim_enti*2,self.dim_enti,kernel_size=3,padding=1,stride=2)

        self.fc_enti2enco = nn.Sequential(
            nn.Linear(self.dim_enti*self.enco_pool_len,self.dim_enti),
            nn.ReLU(),
            nn.Linear(self.dim_enti,self.dim_enti),
            nn.ReLU()
        )

        ## 5. layers for classification
        self.fc_pred2logits = nn.Sequential(
            nn.Linear(self.dim_clsme*2 + self.dim_enti*2, self.dim_ffn),
            nn.ReLU(),
            nn.Linear(self.dim_ffn,self.num_pred_cats)
        )

        self._reset_parameters()

    def _reset_parameters(self):
        skip_init_param_names = [
            "bias_matrix",
            "EntiNameEmb",
        ]
        for name,p in self.named_parameters():
            if name in skip_init_param_names:
                print("skip init param: {}".format(name))
                continue

            if p.dim() > 1:
                nn.init.xavier_normal_(p)

            if "bias" in name:
                nn.init.zeros_(p)

    def forward(self,proposal_list,pos_id_list=None,label_list=None,topk=10):

        if self.is_train:
            assert pos_id_list is not None
            assert label_list is not None

            return self._forward_train(proposal_list,pos_id_list,label_list)
        else:
            self.topk = topk
            return self._forward_test(proposal_list)

    def trajid2pairid(self,num_prop):
        mask = torch.ones(size=(num_prop,num_prop),dtype=torch.bool)
        mask[range(num_prop),range(num_prop)] = 0
        # print(mask)
        pair_ids = mask.nonzero(as_tuple=False)
        # print(pair_ids)

        return pair_ids

    def _forward_test(self,proposal_list):

        triplets = []
        for ii,proposal in enumerate(proposal_list):
            if proposal.num_proposals == 0:  # train 的时候 num_proposal == 0 的会被过滤掉
                triplets.append(None)
            else:
                pair_ids = self.trajid2pairid(proposal.num_proposals)
                pair_ids = pair_ids.to(proposal.traj_durations.device)
                pred_logits = self.forward_propagation(proposal,pair_ids)

                ret = self.construct_triplet(proposal,pred_logits,pair_ids)
                triplets.append(ret)

        return triplets

    def _preprocess_proposal(self,proposal):
        video_len,video_wh = proposal.video_len, proposal.video_wh
        w,h = video_wh
        traj_durations,bboxes_list,feature_list = proposal.traj_durations,proposal.bboxes_list,proposal.features_list
        # traj_durations: shape == (n_trajs,2)
        # bboxes_list： list[tensor], len == n_trajs, shape == (num_frames,4)
        # features_list # list[tensor], len==n_trajs, shape == (num_frames,1024)
        traj_bboxes = []
        traj_features = []
        for pid in range(len(bboxes_list)):
            bboxes = bboxes_list[pid].clone()  # shape == (num_frames, 4) tensor
            bboxes[:,0:4:2] /= w
            bboxes[:,1:4:2] /= h

            bbox_ctx = (bboxes[:,2] + bboxes[:,0])/2
            bbox_cty = (bboxes[:,3] + bboxes[:,1])/2
            bbox_w = bboxes[:,2] - bboxes[:,0]
            bbox_h = bboxes[:,3] - bboxes[:,1]

            diff_ctx = bbox_ctx[1:] - bbox_ctx[:-1]
            diff_cty = bbox_cty[1:] - bbox_cty[:-1]
            diff_w = bbox_w[1:] - bbox_w[:-1]
            diff_h = bbox_h[1:] - bbox_h[:-1]
            bbox_feat = [
                bbox_ctx,diff_ctx,
                bbox_cty,diff_cty,
                bbox_w,diff_w,
                bbox_h,diff_h
            ]
            bbox_feat = stack_with_padding(bbox_feat,dim=1) # shape == (n_frames,8)
            traj_bboxes.append(bbox_feat)

            features = feature_list[pid]
            traj_features.append(features)

        traj_bboxes = stack_with_repeat_2d(traj_bboxes,dim=0)     # shape == (n_trajs,max_frame, 8)
        traj_features = stack_with_repeat_2d(traj_features,dim=0) # shape == (n_trajs, max_frame, 1024)

        return traj_bboxes,traj_features,traj_durations

    def forward_propagation(self,proposal,pairid2trajids):
        n_trajs,video_len = proposal.num_proposals,proposal.video_len
        traj_bboxes,traj_features,traj_dura = self._preprocess_proposal(proposal)
        # shape == (n_trajs, max_frames,4), (n_trajs, max_frames,1024+300), (n_trajs, 2)
        traj_visual  = traj_features[:,:,:self.dim_feat]
        assert traj_visual.shape[2] == self.dim_feat
        if self.use_clsme:
            traj_classeme = traj_features[:,:,self.dim_feat:]  # shape == (n_trajs, max_frames,dim_clsme)
            if self.EntiNameEmb is None:  # i.e., if we don't use category embedding as classeme feature
                assert traj_classeme.shape[2] == self.dim_clsme

        traj_bboxes =   self.fc_bbox2enti(traj_bboxes)
        traj_visual = self.fc_feat2enti(traj_visual)
        enti_features = torch.cat([traj_bboxes,traj_visual],dim=-1)

        enti_features = enti_features.permute(0,2,1) # shape == (n_trajs, dim_state, max_frames)
        enti_nodes = self.conv_feat2enti(enti_features) # shape == (n_trajs, dim_state, max_frames//2)
        enti_nodes = enti_nodes.permute(0,2,1) # shape == (n_trajs,  max_frames//2, dim_state)

        ## encode
        enti2enco = enti_nodes.permute(0,2,1) # shape == (n_trajs, dim_state, max_frames//2)
        enti2enco = F.adaptive_max_pool1d(enti2enco,output_size=self.enco_pool_len) # shape == (n_trajs, dim_state, pool_outlen)
        enti2enco = enti2enco.reshape(n_trajs,-1)  # shape == (n_trajs, dim_state*pool_outlen)
        enti2enco = self.fc_enti2enco(enti2enco)    # shape == (n_trajs, dim_state)

        if self.use_clsme and (self.EntiNameEmb is None):
            traj_clsme_avg = traj_classeme.mean(dim=1) # shape == (n_enti,300)
        else:
            traj_clsme_avg = None

        pred_logits = self.prediction_head(pairid2trajids,proposal.cat_ids,traj_clsme_avg,enti2enco,proposal.video_name) # shpae == (n_querys, n_pred_cat)

        return pred_logits

    def extract_traj_features(self,proposal):
        n_trajs,video_len = proposal.num_proposals,proposal.video_len
        traj_bboxes,traj_features,traj_dura = self._preprocess_proposal(proposal)
        # shape == (n_trajs, max_frames,4), (n_trajs, max_frames,1024+300), (n_trajs, 2)
        traj_visual  = traj_features[:,:,:self.dim_feat]
        traj_classeme = traj_features[:,:,self.dim_feat:]  # shape == (n_trajs, max_frames,dim_clsme)
        if self.EntiNameEmb is None:
            assert traj_visual.shape[2] == self.dim_feat and traj_classeme.shape[2] == self.dim_clsme
        else:
            assert traj_visual.shape[2] == self.dim_feat #and traj_classeme.shape[2] == 0
            traj_classeme = None

        traj_bboxes =   self.fc_bbox2enti(traj_bboxes)
        traj_visual = self.fc_feat2enti(traj_visual)
        enti_features = torch.cat([traj_bboxes,traj_visual],dim=-1)

        enti_features = enti_features.permute(0,2,1) # shape == (n_trajs, dim_state, max_frames)
        enti_nodes = self.conv_feat2enti(enti_features) # shape == (n_trajs, dim_state, max_frames//2)
        enti_nodes = enti_nodes.permute(0,2,1) # shape == (n_trajs,  max_frames//2, dim_state)

        ## encode
        enti2enco = enti_nodes.permute(0,2,1) # shape == (n_trajs, dim_state, max_frames//2)
        enti2enco = F.adaptive_max_pool1d(enti2enco,output_size=self.enco_pool_len) # shape == (n_trajs, dim_state, pool_outlen)
        enti2enco = enti2enco.reshape(n_trajs,-1)  # shape == (n_trajs, dim_state*pool_outlen)
        enti2enco = self.fc_enti2enco(enti2enco)    # shape == (n_trajs, dim_state)

        return enti2enco,traj_dura

    def prediction_head(self,pairid2trajids,cat_ids,enti_clsme,enti_feat,video_name):
        # pairid2trajids  (n_pos_pairs,2)

        # cat_ids: shape == (n_enti,)
        # enti_clsme.shape ==(n_enti,300)
        # self.bias_matrix shape == (n_enti_cat,n_enti_cat,n_pred_cat) # (81,81,51), including background

        pred_socatid = cat_ids[pairid2trajids]  # enti categories, shape == (n_pos_pairs,2)
        pred_bias = self.bias_matrix[pred_socatid[:,0],pred_socatid[:,1],:] # shape == (n_querys,n_pred_cat)
        sub_feat = enti_feat[pairid2trajids[:,0],:]  # shape == (n_pos_pairs, dim_enti)
        obj_feat = enti_feat[pairid2trajids[:,1],:]  # shape == (n_pos_pairs, din_enti)

        if self.use_clsme:
            if self.EntiNameEmb is None:
                assert enti_clsme is not None
                sub_clsme = enti_clsme[pairid2trajids[:,0],:]  # shape == (n_pos_pairs, 300)
                obj_clsme = enti_clsme[pairid2trajids[:,1],:]  # shape == (n_pos_pairs, 300)
            else:
                assert enti_clsme is None
                sub_clsme = self.EntiNameEmb[pred_socatid[:,0],:]  # shape == (n_pos_pairs, 300)
                obj_clsme = self.EntiNameEmb[pred_socatid[:,1],:]  # shape == (n_pos_pairs, 300)
            # for x in [sub_clsme,obj_clsme,sub_feat,obj_feat]:
            #     print(x.shape)
            combined_features = torch.cat([sub_clsme,obj_clsme,sub_feat,obj_feat],dim=-1)  # shape == (n_querys,600+2*dim_enti)
        else:
            combined_features = torch.cat([sub_feat,obj_feat],dim=-1)  # shape == (n_querys,2*dim_enti)

        pred_logits = self.fc_pred2logits(combined_features)
        pred_logits = pred_logits + pred_bias

        return pred_logits

    def _forward_train(self,proposal_list,pos_id_list,label_list):

        # pos_id_list = [pairid2trajids, pairid2trajids,...]
        # label_list = [multihot,multihot,...]

        # pairid2trajids.shape == (n_pos_pairs,2)
        # multihot.shape == (n_pos_pairs,n_pred_cat)

        assert len(proposal_list) == len(label_list)
        batch_size = len(proposal_list)
        pred_logits = [self.forward_propagation(proposal,pairid2trajids) for proposal,pairid2trajids in zip(proposal_list,pos_id_list)]

        # pred_logits: shape == (n_pos_pairs, n_pred_cat)

        loss_dict = self.loss(pred_logits,label_list)

        total_loss = torch.stack(list(loss_dict.values())).sum()    # scalar tensor

        return total_loss, loss_dict

    def loss(self,pred_logits,label_list):

        pred_logits = torch.cat(pred_logits,dim=0) # (N_pos_pairs,n_pred_cat)
        labels = torch.cat(label_list)             # (N_pos_pairs,n_pred_cat)

        cls_loss = F.binary_cross_entropy_with_logits(pred_logits,labels,reduction='mean')
        # TODO use focal ?
        loss_dict = {
            "cls":cls_loss
        }
        return loss_dict

    def construct_triplet(self,proposal,pred_logits,pair_ids):
        # pred_cs.shape == (n_pred,2) center span

        pred_probs = torch.softmax(pred_logits,dim=-1)
        pred_scores,pred_catids = torch.topk(pred_probs,self.topk,dim=-1)  # shape == (n_anchors,k)
        pred_scores = pred_scores.reshape(-1) # shape == (n_ac*k,) # flatten as concatenate each row
        pred_catids = pred_catids.reshape(-1) # shape == (n_ac*k,)

        traj_duras = proposal.traj_durations.clone() # shape == (n_enti,2)
        n_traj = traj_duras.shape[0]

        enti_scores = proposal.scores            # shape == (n_enti,)
        enti_catids = proposal.cat_ids           # shape == (n_enti,)

        pred2so_ids = pair_ids          # enti index,  shape == (n_ac,2)
        pred2so_ids = torch.repeat_interleave(pred2so_ids,self.topk,dim=0) # shape == (n_ac*k,2)

        # filter the predicates linking to object/subject such that have no overlap
        dura_inters,dura_mask = dura_intersection_ts(traj_duras,traj_duras)  # shape == (n_traj,n_traj,2)
        dura_mask[range(n_traj),range(n_traj)] = 0
        pos_pred_mask = dura_mask[pred2so_ids[:,0],pred2so_ids[:,1]]  # shape = (n_ac*k,)
        if pos_pred_mask.sum() == 0:
            return None
        pos_pred_index = pos_pred_mask.nonzero(as_tuple=True)[0]

        pred2so_ids = pred2so_ids[pos_pred_index,:]  # shape == (n_pos,2)
        pred_scores =pred_scores[pos_pred_index]     # shape == (n_pos,)
        pred_catids =pred_catids[pos_pred_index]     # shape == (n_pos,)

        # triplets
        pred2so_catids = enti_catids[pred2so_ids] # shape == (n_pos,2)
        triplet_catids = torch.cat([pred_catids[:,None],pred2so_catids],dim=-1)  # shape == (n_pos,3) format: [pred_catid,subj_catid,obj_catid]

        # scores
        pred2so_scores = enti_scores[pred2so_ids]  # shape == (n_pos,2)
        triplet_scores = torch.cat([pred_scores[:,None],pred2so_scores],dim=-1) # shape == (n_pos,3)

        # filter the repeated triplets ( the post-processing in MM_paper1933)
        quintuples = torch.cat([triplet_catids,pred2so_ids],dim=-1)  # shape == (n_pos,5) format: [pred_catid,subj_catid,obj_catid,subj_tid,obj_tid]
        try:
            uniq_quintuples,index_map = unique_with_idx_nd(quintuples)        # shape == (n_unique,5) format: [pred_catid,subj_catid,obj_catid,subj_tid,obj_tid]
        except:
            print(quintuples.shape,pos_pred_mask.shape,pos_pred_mask.sum())
            print(dura_mask.sum(),dura_mask.shape)
            print(proposal.video_name)
            assert False

        uniq_triplet_ids = [idx[triplet_scores[idx,0].argmax()] for idx in index_map] # list of scalar tensor
        uniq_triplet_ids = torch.stack(uniq_triplet_ids)    # shape == (n_unique,)
        uniq_scores = triplet_scores[uniq_triplet_ids,:]      # shape == (n_unique,3)

        uniq_dura_inters = dura_inters[uniq_quintuples[:,3],uniq_quintuples[:,4],:] # shape == (n_unique,2)
        #TODO sort by socre and select top100?

        # filter out triplets whose pred_cat is __background__
        mask = uniq_quintuples[:,0] != 0
        uniq_quintuples = uniq_quintuples[mask,:]
        uniq_scores = uniq_scores[mask,:]
        uniq_dura_inters = uniq_dura_inters[mask,:]

        if self.rt_triplets_topk > 0:
            # sort by score and select top200 (for save GPU memory when doing the grounding stage)
            top200ids = uniq_scores.mean(dim=-1).argsort(descending=True)[:self.rt_triplets_topk]
            uniq_scores = uniq_scores[top200ids,:]
            uniq_quintuples = uniq_quintuples[top200ids,:]
            uniq_dura_inters = uniq_dura_inters[top200ids,:]

        uniq_query_ids = torch.empty(size=(uniq_scores.shape[0],))

        ret = (
            uniq_quintuples,    # shape == (n_unique,5)
            uniq_scores,        # shape == (n_unique,3)
            uniq_dura_inters,   # shape == (n_unique,2)
            uniq_query_ids,     # shape == (n_unique,)
        )

        return ret


import math
import numpy as np
from scipy import signal

# RPI4
from scipy.fftpack import fftshift
# PC
# from scipy.fft import fftshift

# fft parameter
N_FFT_point = 128
SamplingFreq = 650
fft_window = signal.windows.hamming(128)

def stft_crop(I_raw_data, Q_raw_data):
    # make complex input with I-data, Q-data and remove DC component
    complex_raw_data = []
    for i in range(0, 1920):
        complex_raw_data.append(
            complex(I_raw_data[i], Q_raw_data[i]))
    complex_raw_data_DC = complex_raw_data - np.mean(complex_raw_data)

    # stft
    f, t, Zxx = signal.stft(x=complex_raw_data_DC, fs=SamplingFreq, window=fft_window,
                            nperseg=N_FFT_point, nfft=N_FFT_point, noverlap=N_FFT_point//2, boundary=None)

    # fftshift
    Zxx = fftshift(abs(Zxx), axes=0)

    # crop image into 36x28 from 128x29
    Zxx = Zxx[46:82, 1:29]

    power_sum = 0

    # make fft result into integer from float
    for i in range(36):
        for j in range(28):
            Zxx[i][j] = math.ceil(abs(Zxx[i][j]))
            power_sum += Zxx[i][j] * Zxx[i][j]

    return Zxx, power_sum


import hashlib
import json
from functools import update_wrapper, wraps
from pathlib import Path

from django.conf import settings
from django.shortcuts import render
from django.urls import reverse

from .response import (
    AppShellLoadItResponse,
    AppShellRedirectResponse,
    BaseAppShellResponse,
)

def _decorate_urlpatterns(urlpatterns, decorator):
    """Decorate all the views in the passed urlpatterns list with the given decorator"""
    for pattern in urlpatterns:
        if hasattr(pattern, "url_patterns"):
            # this is an included RegexURLResolver; recursively decorate the views
            # contained in it
            _decorate_urlpatterns(pattern.url_patterns, decorator)

        if getattr(pattern, "callback", None):
            pattern.callback = update_wrapper(
                decorator(pattern.callback), pattern.callback
            )

    return urlpatterns

def appshell_enable(fn):
    """
    Wraps a view to make it load with the shell.
    """

    @wraps(fn)
    def wrapper(request, *args, **kwargs):
        request.shell_enabled = True
        response = fn(request, *args, **kwargs)

        if response.status_code == 301:
            return response

        # If the request was made by the shell (using `fetch()`, rather than a regular browser request)
        if request.META.get("HTTP_X_REQUESTED_WITH") == "Shell":
            if isinstance(response, BaseAppShellResponse):
                return response

            elif response.status_code == 302:
                return AppShellRedirectResponse(response["Location"])

            else:
                # Response couldn't be converted into a shell response. Reload the page
                return AppShellLoadItResponse()

        # Regular browser request
        if isinstance(response, BaseAppShellResponse):
            if settings.APPSHELL_VITE_SERVER_ORIGIN:
                # Development - Fetch JS/CSS from Vite server
                js = [
                    settings.APPSHELL_VITE_SERVER_ORIGIN + "/@vite/client",
                    settings.APPSHELL_VITE_SERVER_ORIGIN
                    + "/static/src/main.tsx",
                ]
                css = []
                vite_react_refresh_runtime = (
                    settings.APPSHELL_VITE_SERVER_ORIGIN + "/@react-refresh"
                )
            else:
                # Production - Use asset manifest to find URLs to bundled JS/CSS
                asset_manifest = json.loads(
                    Path("/client/manifest.json").read_text()
                )

                js = [
                    "/static/" + asset_manifest["src/main.tsx"]["file"],
                ]
                css = asset_manifest["src/main.tsx"]["css"]
                vite_react_refresh_runtime = None

            # Wrap the response with our shell bootstrap template
            return render(
                request,
                "appshell/bootstrap.html",
                {
                    "data": response.content.decode("utf-8"),
                    "globals_data": json.dumps(
                        {
                            "user": {
                                "displayName": request.user.get_full_name(),
                                "avatarUrl": "https://www.gravatar.com/avatar/{}?s=128&d=identicon".format(
                                    hashlib.md5(
                                        request.user.email.lower()
                                        .strip()
                                        .encode("utf-8")
                                    ).hexdigest()
                                ),
                            }
                            if request.user.is_authenticated
                            else None,
                            "urls": {
                                "userProfile": reverse("user_profile"),
                            },
                        }
                    ),
                    "js": js,
                    "css": css,
                    "vite_react_refresh_runtime": vite_react_refresh_runtime,
                },
            )
        else:
            return response

    return wrapper

def appshell_exempt(fn):
    """
    Excludes a view from the app shell to override appshell_enable_urlpatterns.
    """

    @wraps(fn)
    def wrapper(request, *args, **kwargs):
        request.shell_enabled = False
        return fn(request, *args, **kwargs)

    return wrapper

def appshell_enable_urlpatterns(urlpatterns):
    return _decorate_urlpatterns(urlpatterns, appshell_enable)


from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import selenium.webdriver.support.ui as ui
from selenium.webdriver.chrome.options import Options
import time

#Getting Chrome Driver and setting profile settings
options1 = Options()
options1.add_argument(r"--user-data-dir=C:\Users\Ayoub\AppData\Local\Google\Chrome\User Data 1")
options1.add_argument(r'--profile-directory=Profile 1')
browser = webdriver.Chrome("C:\Program Files (x86)\chromedriver.exe",options=options1)

#Load page
browser.get("https://google.com/search?q=python")

#Wait to find element in page
first_result = ui.WebDriverWait(browser, 15).until(lambda browser: browser.find_element_by_class_name('eKjLze'))
first_link = first_result.find_element_by_tag_name('a')

# Save the window opener (current window, do not mistaken with tab... not the same)
main_window = browser.current_window_handle

# Open the link in a new tab by sending key strokes on the element
# Use: Keys.CONTROL + Keys.SHIFT + Keys.RETURN to open tab on top of the stack
first_link.send_keys(Keys.CONTROL + Keys.RETURN)

# Switch tab to the new tab, which we will assume is the next one on the right
browser.find_element_by_tag_name('body').send_keys(Keys.CONTROL + Keys.TAB)
time.sleep(2)

# Put focus on current window which will be the window opener
browser.switch_to.window(main_window)
time.sleep(2)

# Switch window handles
browser.switch_to.window(browser.window_handles[1])

# Do stuff with buttons
#browser.find_element_by_tag_name('body').send_keys(Keys.CONTROL + 'w')


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

from django.db.models import Sum

from store.forms import AnularVentaForm
from store.functions import MiPaginador
from store.models import DetalleIngresoProducto
from store.values import ACCION_MODIFICAR
from store.ventas import *

@login_required(redirect_field_name='ret', login_url='/login')
def view(request):
    if request.method == 'POST':
        action = request.POST['action']
        if action == 'anular':
            venta = Venta.objects.get(pk=request.POST['id'])
            f = AnularVentaForm(request.POST)
            if f.is_valid():
                venta.valida = False
                venta.usuarioanula = request.user
                venta.motivoanulacion = f.cleaned_data['motivo']
                venta.save()

                salva_auditoria(request, venta, ACCION_MODIFICAR)

                # Actualizar Inventario
                for d in venta.detalles.all():
                    if InventarioReal.objects.filter(producto=d.producto).exists():
                        inventarioreal = InventarioReal.objects.filter(producto=d.producto)[0]
                        inventarioreal.cantidad = inventarioreal.cantidad + d.cantidad
                        ultimoingresoprod = None
                        if DetalleIngresoProducto.objects.filter(producto=d.producto).exists():
                            ultimoingresoprod = DetalleIngresoProducto.objects.filter(producto=d.producto).latest('id')
                        if ultimoingresoprod:
                            inventarioreal.valor = inventarioreal.valor + ultimoingresoprod.valor
                            inventarioreal.costo = inventarioreal.valor / inventarioreal.cantidad
                            inventarioreal.save()
                        else:
                            inventarioreal.valor = inventarioreal.valor + d.valor
                            inventarioreal.costo = inventarioreal.valor / inventarioreal.cantidad
                            inventarioreal.save()

                    else:
                        inventarioreal = InventarioReal(producto=d.producto,
                                                        cantidad=d.cantidad,
                                                        costo=d.pvp,
                                                        valor=d.valor)
                        inventarioreal.save()

                return HttpResponseRedirect('/cons_ventas')

            else:
                return HttpResponseRedirect('/cons_ventas?action=anular&id=' + str(venta.id))

    else:
        data = {'title': 'Consulta de Ventas'}
        addUserData(request, data)
        if 'action' in request.GET:
            action = request.GET['action']
            if action == 'detalle':
                data['venta'] = Venta.objects.get(pk=request.GET['idventa'])
                return render_to_response('cons_ventas/detalleventas.html', data)
            elif action == 'anular':
                data['venta'] = Venta.objects.get(pk=request.GET['id'])
                data['form'] = AnularVentaForm()
                return render_to_response('cons_ventas/anulaventa.html', data)
        else:
            search = None
            sesion = None

            if 'sesion' in request.GET:
                sesion = request.GET['sesion']
                data['sesionid'] = int(sesion) if sesion else ""
                data['sesion'] = SesionCaja.objects.get(pk=sesion) if sesion else ""
                data['totalventasesion'] = Venta.objects.filter(sesioncaja__id=sesion).aggregate(Sum('total'))['total__sum'] if sesion else ""
                data['cantidadventasesion'] = Venta.objects.filter(sesioncaja__id=sesion).count() if sesion else ""
                data['creditosesion'] = pagos_total_fecha_credito_sesion(data['sesion']) if sesion else ""
                data['valessesion'] = ""
                data['depositarsesion'] = data['totalventasesion'] - data['creditosesion'] - data['valessesion'] if sesion else ""
                data['promedioventasesion'] = Decimal(data['totalventasesion'] / data['cantidadventasesion']).quantize(Decimal(10) ** -2) if sesion else ""

            if 's' in request.GET:
                search = request.GET['s']

            if search:
                ventas = Venta.objects.filter(id__icontains=search)
            elif sesion:
                ventas = Venta.objects.filter(sesioncaja__id=sesion).order_by('-fecha', '-id', '-hora')
            else:
                ventas = Venta.objects.all()

            paging = MiPaginador(ventas, 25)
            p = 1
            try:
                if 'page' in request.GET:
                    p = int(request.GET['page'])
                page = paging.page(p)
            except:
                page = paging.page(1)

            data['paging'] = paging
            data['rangospaging'] = paging.rangos_paginado(p)
            data['page'] = page
            data['search'] = search if search else ""
            data['ventas'] = page.object_list
            data['sesionescaja'] = SesionCaja.objects.all().order_by('fecha')
            return render_to_response("cons_ventas/cons_ventas.html", data)


from typing import List

def average(values: List[float]) -> float:
    """values 내 수들의 평균을 반환한다. values 내 어떤 항목은 None일 수 있는데,
    None 값은 평균을 계산할 때 제외한다.

    >>> average([20, 30])
    25.0
    >>> average([None, 20, 30])
    25.0
    """

    count = 0 # 지금까지 본 값들의 개수
    total = 0 # 지금까지 본 값들의 합
    for value in values:
        if value is not None:
            total += value

        count += 1

    return total / count

if __name__ == '__main__':
    import doctest
    doctest.testmod()


from django import forms
from candidato.models import *

class FormHomePage(forms.Form):
    email = forms.EmailField(label=False)

class ColabDetailForm01(forms.ModelForm):
    class Meta:
        model = Questoes_parte1
        fields = ("campo_cpf", "ficou_sabendo", "objetivo", "como_conheceu", "candidato_why", "sucesso_prof",
                  "mundo_tins")

        exclude = ("codigo_id", "data_cadastro")
        widgets = {
            'campo_cpf':forms.TextInput(attrs={'readonly': 'readonly'})
        }

class ColabDetailForm02(forms.ModelForm):
    class Meta:
        model = Questoes_parte2
        fields = ("campo_cpf", "digitacao", "software", "hardware", "internet", "curso_extra", "trabalho_anterior",
                  "pret_salarial")

        exclude = ("codigo_id", "data_cadastro")
        widgets = {
            'campo_cpf':forms.TextInput(attrs={'readonly': 'readonly'})
        }

class ColabDetailForm03(forms.ModelForm):
    class Meta:
        model = Questoes_parte3
        fields = ("campo_cpf", "mark_digital", "auxilio_governo", "disponivel_viagem", "Notebook_disponivel",
                  "descreva_lider", "diferencial")

        exclude = ("codigo_id", "data_cadastro")
        widgets = {
            'campo_cpf':forms.TextInput(attrs={'readonly': 'readonly'})
        }

class ColabDetailForm04(forms.ModelForm):
    class Meta:
        model = Questoes_parte4
        fields = ("campo_cpf", "religiao", "praticante", "quem_deus", "residente", "possui_cnh", "categoria_cnh",
                  "possui_veiculo", "qual_veiculo")

        exclude = ("codigo_id", "data_cadastro")
        widgets = {
            'campo_cpf':forms.TextInput(attrs={'readonly': 'readonly'})
        }

class ColabDetailForm05(forms.ModelForm):
    class Meta:
        model = Questoes_parte5
        fields = ("campo_cpf", "possui_vicios", "qual_vicio", "Faz_no_lazer", "alergias", "qual_alergia",
                  "planejamento_pessoal", "sua_imagem")

        exclude = ("codigo_id", "data_cadastro")
        widgets = {
            'campo_cpf':
                forms.TextInput(attrs={'readonly': 'readonly'})
        }

class ColabDetailForm06(forms.ModelForm):
    class Meta:
        model = Questoes_parte6
        fields = ("campo_cpf", "fazer_bem", "dificu_enfrentou", "sua_saude", "melhor_filme", "livro_import",
                  "esporte_favorito", "cor_preferida", "musica_preferida")

        exclude = ("codigo_id", "data_cadastro")
        widgets = {
            'campo_cpf':
                forms.TextInput(attrs={'readonly': 'readonly'})
        }

class ColabDetailForm07(forms.ModelForm):
    class Meta:
        model = Questoes_parte7
        fields = ("campo_cpf", "acontece", "sua_forca", "sua_capacidade", "maior_erro", "maior_realiza",
                  "se_morrer", "pessoa_identif", "tipo_droga")

        exclude = ("codigo_id", "data_cadastro")
        widgets = {
            'campo_cpf':
                forms.TextInput(attrs={'readonly': 'readonly'})
        }

class ColabDetailForm08(forms.ModelForm):
    class Meta:
        model = Questoes_parte8
        fields = ("campo_cpf", "resolve_problema", "trab_equipe", "nervoso", "tres_comporta", "erro_trabalho",
                  "bebado_reage", "honestidade", "lealdade")

        exclude = ("codigo_id", "data_cadastro")
        widgets = {
            'campo_cpf':
                forms.TextInput(attrs={'readonly': 'readonly'})
        }

class ColabDetailForm09(forms.ModelForm):
    class Meta:
        model = Questoes_parte9
        fields = ("campo_cpf", "trabalho", "religiao_importa", "contrato_pj", "cnpj_ativo", "abrir_cnpj", "pontos_fortes",
                  "pontos_fracos", "texto_sobre_vc")

        exclude = ("codigo_id", "data_cadastro")
        widgets = {
            'campo_cpf':
                forms.TextInput(attrs={'readonly': 'readonly'})
        }

class ColabDetailForm10(forms.ModelForm):
    class Meta:
        model = Questoes_parte10
        fields = ("campo_cpf", "busca_informacoes", "aprende_rapido", "exec_tarefa", "feed_melhor", "reacao_feed",
                  "melhor_amigo", "precisou_aprender", "maior_orgulho")

        exclude = ("codigo_id", "data_cadastro")
        widgets = {
            'campo_cpf':
                forms.TextInput(attrs={'readonly': 'readonly'})
        }

class CriarFitCult01(forms.ModelForm):
    class Meta:
        model = Cad_colab_parte1
        fields = ("campo_cpf", "nome_candidato", "e_mail", "funcao_candidato", "cep_candidato",
                  "endereco_candidato", "bairro_candidato", "cidade_candidato", "uf_candidato")

        exclude = ("codigo_id", "data_cadastro", "ultima_altera")
        widgets = {
            'e_mail':
                forms.TextInput(attrs={'readonly': 'readonly'})
        }

class CriarFitCult02(forms.ModelForm):
    class Meta:
        model = Cad_colab_parte2
        fields = ("campo_cpf", "naturalidade_candidato", "data_nascimento", "estado_civil", "possui_filhos",
                  "quantos_filhos", "grau_escolar", "curso_academico", "periodo_curso", "faculdade_curso")

        exclude = ("codigo_id", "data_cadastro")
        widgets = {
            'campo_cpf':
            forms.TextInput(attrs={'readonly': 'readonly'})
        }

class CriarFitCult03(forms.ModelForm):
    class Meta:
        model = Cad_colab_parte3
        fields = ("campo_cpf", "pai_candidato", "mae_candidato", "telefone_residencia", "celular_candidato",
                  "instagram_candidato", "foto_candidato")

        exclude = ("codigo_id", "data_cadastro")
        widgets = {
            'campo_cpf':
            forms.TextInput(attrs={'readonly': 'readonly'})
        }


from PIL import Image, ImageFilter, ImageStat, ImageEnhance
import face_recognition, argparse
from os import path
from math import sqrt

def check_file_exist(path):
    try:
        with open(path, 'rb') as image_file:
            image = face_recognition.load_image_file(image_file)
            return image
    except OSError:
        pass

def brightness(image):
    # image = Image.open("./img/Brightness/camera.jpg")
    Exist = check_file_exist(image) # Image exist
    # Convert the image te RGB if it is a .gif for example
    image = Image.fromarray(Exist)
    imag = image.convert ('RGB')
    # coordinates of the pixel
    X,Y = 0,0
    # Get RGB
    pixelRGB = imag.getpixel((X,Y))
    R,G,B = pixelRGB
    brightness = sum([R,G,B])/3 # 0 is dark (black) and 255 is bright (white)
    print(brightness)
    return brightness

def brightness_detection(image):
    Brightness = brightness(image)
    threshold = 125.0
    if Brightness < threshold:
        print("{}: {:.2f}".format('Too dark brightness', Brightness)) # lay so thap phan
        return False
    else:
        print("{}: {:.2f}".format('Brightness is right', Brightness)) # lay so thap phan
        return True

def result_brightness(image):
    if brightness_detection(image) == True:
        return True
    else:
        return False

parser = argparse.ArgumentParser(
        description='Detects faces in the given image.')

parser.add_argument(
    "image",
    help='the image you\'d like to detect faces in.')

parser.add_argument(
    'mode', help='Set to call function need to do')

args = parser.parse_args()

if args.mode == 'brightness':
    result_brightness(args.image)

# RUNN python test.py ./img/Brightness/camera.jpg brightness


# Python Standard Library Imports
import copy

# Third Party (PyPI) Imports
from flask import (
    Blueprint,
    url_for,
)

# Phablytics Imports
from phablytics.utils import (
    fetch_users,
    get_user_by_username,
)
from phablytics.web.utils import custom_render_template as _r

users_endpoints = Blueprint(
    'users_endpoints',
    __name__,
    template_folder='templates'
)

@users_endpoints.route('', defaults={'page': 'index'})
def index(page):
    context_data = {
        'users': fetch_users(),
    }
    return _r('users/%s.html' % page, context_data=context_data)

@users_endpoints.route('/<username>')
def user_profile(username):
    user = get_user_by_username(username)
    context_data = {
        'user': user,
    }
    return _r('users/profile.html', context_data=context_data)