from __future__ import division

from .atmospheric_model import AtmosphericLayer, phase_covariance_von_karman, fried_parameter_from_Cn_squared
from ..statistics import SpectralNoiseFactoryMultiscale
from ..field import Field, RegularCoords, UnstructuredCoords, CartesianGrid
from .finite_atmospheric_layer import FiniteAtmosphericLayer

import numpy as np
from scipy import linalg
from scipy.ndimage import affine_transform

import time
import warnings

class InfiniteAtmosphericLayer(AtmosphericLayer):
	def __init__(self, input_grid, Cn_squared=None, L0=np.inf, velocity=0, height=0, stencil_length=2, use_interpolation=False):
		self._initialized = False

		AtmosphericLayer.__init__(self, input_grid, Cn_squared, L0, velocity, height)

		# Check properties of input_grid
		if not input_grid.is_('cartesian'):
			raise ValueError('Input grid must be cartesian.')
		if not input_grid.is_regular:
			raise ValueError('Input grid must be regularly spaced')
		if not input_grid.ndim == 2:
			raise ValueError('Input grid must be two-dimensional.')

		self.stencil_length = stencil_length
		self.use_interpolation = use_interpolation

		self._make_stencils()
		self._make_covariance_matrices()
		self._make_AB_matrices()
		self._make_initial_phase_screen()

		self.center = np.zeros(2)

		self._initialized = True

	def _recalculate_matrices(self):
		if self._initialized:
			self._make_covariance_matrices()
			self._make_AB_matrices()

	def _make_stencils(self):
		# Vertical
		self.new_grid_bottom = CartesianGrid(RegularCoords(self.input_grid.delta, [self.input_grid.dims[0], 1], self.input_grid.zero - np.array([0, self.input_grid.delta[1]])))

		self.stencil_bottom = Field(np.zeros(self.input_grid.size, dtype='bool'), self.input_grid).shaped
		self.stencil_bottom[:self.stencil_length,:] = True

		for i, n in enumerate(np.random.geometric(0.5, self.input_grid.dims[0])):
			self.stencil_bottom[(n + self.stencil_length - 1) % self.input_grid.dims[1],i] = True

		self.stencil_bottom = self.stencil_bottom.ravel()
		self.num_stencils_vertical = np.sum(self.stencil_bottom)

		# Horizontal
		self.new_grid_left = CartesianGrid(RegularCoords(self.input_grid.delta, [1, self.input_grid.dims[1]], self.input_grid.zero - np.array([self.input_grid.delta[0], 0])))

		self.stencil_left = Field(np.zeros(self.input_grid.size, dtype='bool'), self.input_grid).shaped
		self.stencil_left[:,:self.stencil_length] = True

		for i, n in enumerate(np.random.geometric(0.5, self.input_grid.dims[1])):
			self.stencil_left[i,(n + self.stencil_length - 1) % self.input_grid.dims[0]] = True

		self.stencil_left = self.stencil_left.ravel()
		self.num_stencils_horizontal = np.sum(self.stencil_left)

	def _make_covariance_matrices(self):
		phase_covariance = phase_covariance_von_karman(fried_parameter_from_Cn_squared(1, 1), self.L0)

		# Vertical
		x = np.concatenate((self.input_grid.x[self.stencil_bottom], self.new_grid_bottom.x))
		x = np.concatenate([x - xx for xx in x])
		y = np.concatenate((self.input_grid.y[self.stencil_bottom], self.new_grid_bottom.y))
		y = np.concatenate([y - yy for yy in y])

		separations = CartesianGrid(UnstructuredCoords((x, y)))
		n = self.new_grid_bottom.size + self.num_stencils_vertical
		self.cov_matrix_vertical = phase_covariance(separations).reshape((n, n))

		# Horizontal
		x = np.concatenate((self.input_grid.x[self.stencil_left], self.new_grid_left.x))
		x = np.concatenate([x - xx for xx in x])
		y = np.concatenate((self.input_grid.y[self.stencil_left], self.new_grid_left.y))
		y = np.concatenate([y - yy for yy in y])

		separations = CartesianGrid(UnstructuredCoords((x, y)))
		n = self.new_grid_left.size + self.num_stencils_horizontal
		self.cov_matrix_horizontal = phase_covariance(separations).reshape((n, n))

	def _make_AB_matrices(self):
		# Vertical
		n = self.num_stencils_vertical
		cov_zz = self.cov_matrix_vertical[:n,:n]
		cov_xz = self.cov_matrix_vertical[n:, :n]
		cov_zx = self.cov_matrix_vertical[:n, n:]
		cov_xx = self.cov_matrix_vertical[n:, n:]

		cf = linalg.cho_factor(cov_zz)
		inv_cov_zz = linalg.cho_solve(cf, np.eye(cov_zz.shape[0]))

		self.A_vertical = cov_xz.dot(inv_cov_zz)

		BBt = cov_xx - self.A_vertical.dot(cov_zx)

		U, S, Vt = np.linalg.svd(BBt)
		L = np.sqrt(S[:self.input_grid.dims[0]])

		self.B_vertical = U * L

		# Horizontal
		n = self.num_stencils_horizontal
		cov_zz = self.cov_matrix_horizontal[:n,:n]
		cov_xz = self.cov_matrix_horizontal[n:, :n]
		cov_zx = self.cov_matrix_horizontal[:n, n:]
		cov_xx = self.cov_matrix_horizontal[n:, n:]

		cf = linalg.cho_factor(cov_zz)
		inv_cov_zz = linalg.cho_solve(cf, np.eye(cov_zz.shape[0]))

		self.A_horizontal = cov_xz.dot(inv_cov_zz)

		BBt = cov_xx - self.A_horizontal.dot(cov_zx)

		U, S, Vt = np.linalg.svd(BBt)
		L = np.sqrt(S[:self.input_grid.dims[1]])

		self.B_horizontal = U * L

	def _make_initial_phase_screen(self):
		oversampling = 16
		layer = FiniteAtmosphericLayer(self.input_grid, self.Cn_squared, self.outer_scale, self.velocity, self.height, oversampling)
		self._achromatic_screen = layer.phase_for(1)
		self._shifted_achromatic_screen = self._achromatic_screen

	def _extrude(self, where=None):
		flipped = (where == 'top') or (where == 'right')
		horizontal = (where == 'left') or (where == 'right')

		if where == 'top' or where == 'right':
			screen = self._achromatic_screen[::-1]
		else:
			screen = self._achromatic_screen

		if horizontal:
			stencil = self.stencil_left
			A = self.A_horizontal
			B = self.B_horizontal
		else:
			stencil = self.stencil_bottom
			A = self.A_vertical
			B = self.B_vertical

		stencil_data = screen[stencil]
		random_data = np.random.normal(0, 1, size=B.shape[1])
		new_slice = A.dot(stencil_data) + B.dot(random_data) * np.sqrt(self._Cn_squared)

		screen = screen.shaped

		if horizontal:
			screen = np.hstack((new_slice[:,np.newaxis], screen[:,:-1]))
		else:
			screen = np.vstack((new_slice[np.newaxis,:], screen[:-1,:]))

		screen = Field(screen, self.input_grid)

		if flipped:
			self._achromatic_screen = screen[::-1,::-1].ravel()
		else:
			self._achromatic_screen = screen.ravel()

	def phase_for(self, wavelength):
		return self._shifted_achromatic_screen / wavelength

	def reset(self):
		self._make_initial_phase_screen()
		self.center = np.zeros(2)
		self._t = 0

	def evolve_until(self, t):
		if t is None:
			self.reset()
			return

		old_center = np.round(self.center / self.input_grid.delta).astype('int')

		self.center = self.velocity * t
		new_center = np.round(self.center / self.input_grid.delta).astype('int')

		delta = new_center - old_center

		for i in range(abs(delta[0])):
			if delta[0] < 0:
				self._extrude('left')
			else:
				self._extrude('right')

		for i in range(abs(delta[1])):
			if delta[1] < 0:
				self._extrude('bottom')
			else:
				self._extrude('top')

		if self.use_interpolation:
			# Use bilinear interpolation to interpolate the achromatic phase screen to the correct position.
			# This is to avoid sudden shifts by discrete pixels.
			ps = self._achromatic_screen.shaped
			sub_delta = self.center - new_center * self.input_grid.delta
			with warnings.catch_warnings():
				warnings.filterwarnings('ignore', message='The behaviour of affine_transform with a one-dimensional array supplied for the matrix parameter has changed in scipy 0.18.0.')
				self._shifted_achromatic_screen = affine_transform(ps, np.array([1,1]), (sub_delta / self.input_grid.delta)[::-1], mode='nearest', order=1).ravel()
		else:
			self._shifted_achromatic_screen = self._achromatic_screen

	@property
	def Cn_squared(self):
		return self._Cn_squared

	@Cn_squared.setter
	def Cn_squared(self, Cn_squared):
		self._Cn_squared = Cn_squared

	@property
	def outer_scale(self):
		return self._L0

	@outer_scale.setter
	def L0(self, L0):
		self._L0 = L0

		self._recalculate_matrices()


#!/bin/env python

import os
import sys
import random
import subprocess as sub
import getopt
import time

def identity(x):
    return x

def cygpath(x):
    command = ["cygpath", "-wp", x]
    p = sub.Popen(command,stdout=sub.PIPE)
    output, errors = p.communicate()
    lines = output.split("\n")
    return lines[0]

if sys.platform == "cygwin":
    normclasspath = cygpath
else:
    normclasspath = identity

CUSTOM_CONF_FILE = ""
CONFIG_OPTS = []
STATUS = 0
JKUBERNETES_DIR = "/".join(os.path.realpath( __file__ ).split("/")[:-2])
JKUBERNETES_CONF_DIR = os.getenv("JKUBERNETES_CONF_DIR", JKUBERNETES_DIR + "/conf" )
CONFIG_OPTS = []
EXCLUDE_JARS = []
INCLUDE_JARS = []

API_SERVER_ADDRESS = ""
JKUBERNETES_CREATE_YAML_PATH = ""

def check_java():
    check_java_cmd = 'which java'
    ret = os.system(check_java_cmd)
    if ret != 0:
        print("Failed to find java, please add java to PATH")
        sys.exit(-1)

def print_commands():
    """Print all client commands and link to documentation"""
    print ("kubectl command [-s http://apiserverip:port]")
    print ("Commands:\n\t",  "\n\t".join(sorted(COMMANDS.keys())))
    print ("\nHelp:", "\n\thelp", "\n\thelp <command>")
    print ("\nDocumentation for the jkubernetes client can be found at https://github.com/gwisoft/jkubernetes/wiki/jkubernetes-Chinese-Documentation\n")

def get_jars_full(adir):
    ret = []
    temp = adir.strip()
    print (temp == "")

    if temp == "":
         return ret
    files = os.listdir(adir)
    for f in files:
        if f.endswith(".jar") == False:
            continue
        filter = False
        for exclude_jar in EXCLUDE_JARS:
            if f.find(exclude_jar) >= 0:
                filter = True
                break

        if filter == True:
            print ("Don't add " + f + " to classpath")
        else:
            ret.append(adir + "/" + f)
    return ret

def unknown_command(*args):
    print ("Unknown command: [kubectl %s]" % ' '.join(sys.argv[1:]))
    print_usage()

def print_usage(command=None):
    """Print one help message or list of available commands"""
    if command != None:
        if command in COMMANDS:
            print (COMMANDS[command].__doc__ or
                  "No documentation provided for <%s>" % command)
        else:
           print ("<%s> is not a valid command" % command)
    else:
        print_commands()

def parse_config_opts_and_args(args):
	curr = args[:]
	curr.reverse()
	config_list = []
	args_list = []

	while len(curr) > 0:
		token = curr.pop()
		if token == "-s":
			global API_SERVER_ADDRESS
			API_SERVER_ADDRESS = curr.pop()
		elif token == "-c":
			config_list.append(curr.pop())
		elif token == "--config":
			global CUSTOM_CONF_FILE
			CUSTOM_CONF_FILE = curr.pop()
		else:
			args_list.append(token)
	print ("config_list=")
	print (config_list)
	print ("args_list=")
	print (args_list)
	return config_list, args_list

def parse_config_opts(config_list):
    global CONFIG_OPTS
    if len(config_list) > 0:
        for config in config_list:
            CONFIG_OPTS.append(config)

def filter_array(array):
    ret = []
    for item in array:
        temp = item.strip()
        if temp != "":
            ret.append(temp)
    return ret

def get_config_opts():
    global CONFIG_OPTS
    print ("-Dkubernetes.options=" + (','.join(CONFIG_OPTS)).replace(' ', "%%%%"))
    return "-Dkubernetes.options=" + (','.join(CONFIG_OPTS)).replace(' ', "%%%%")

#扩展的jar包入参
def get_exclude_jars():
    global EXCLUDE_JARS
    return " -Dexclude.jars=" + (','.join(EXCLUDE_JARS))

def create(args):
	"""
	kubectl create -f ***.yaml
	"""
	pass

	args = parse_client_createopts(args)

	childopts = get_client_customopts() + get_exclude_jars() + get_client_createopts()
	print ("childopts=")
	print (childopts)
	exec_jkubernetes_class(
        "org.gwisoft.jkubernetes.kubectl.KubectlCreate",
        jvmtype="-client -Xms256m -Xmx256m",
        sysdirs=[JKUBERNETES_CONF_DIR, JKUBERNETES_DIR + "/bin",CUSTOM_CONF_FILE],
        args=args,
        childopts=childopts,
        isBackgroundRun="false")

def kube(args):
	"""
	kubectl kube
	"""
	pass

	childopts = get_client_customopts() + get_exclude_jars()
	print ("childopts=")
	print (childopts)
	exec_jkubernetes_class(
        "org.gwisoft.jkubernetes.daemon.kube.KubeServer",
        jvmtype="-server -Xms256m -Xmx256m",
        sysdirs=[JKUBERNETES_CONF_DIR, JKUBERNETES_DIR + "/bin",CUSTOM_CONF_FILE],
        args=args,
        childopts=childopts,
        isBackgroundRun="true")

def kubelet(args):
    """
    kubectl kubelet
    """
    pass

    childopts = get_client_customopts() + get_exclude_jars()
    print ("childopts=")
    print (childopts)
    exec_jkubernetes_class(
        "org.gwisoft.jkubernetes.daemon.kubelet.Kubelet",
        jvmtype="-server -Xms256m -Xmx256m",
        sysdirs=[JKUBERNETES_CONF_DIR, JKUBERNETES_DIR + "/bin",CUSTOM_CONF_FILE],
        args=args,
        childopts=childopts,
        isBackgroundRun="true")

def delete(args):
    """
    kubectl delete -f ***.yaml
    """
    pass

    args = parse_client_createopts(args)

    childopts = get_client_customopts() + get_exclude_jars() + get_client_createopts()
    print ("childopts=")
    print (childopts)
    exec_jkubernetes_class(
        "org.gwisoft.jkubernetes.kubectl.KubectlDelete",
        jvmtype="-server -Xms256m -Xmx256m",
        sysdirs=[JKUBERNETES_CONF_DIR, JKUBERNETES_DIR + "/bin",CUSTOM_CONF_FILE],
        args=args,
        childopts=childopts,
        isBackgroundRun="false")

def rollingUpdate(args):
    """
    kubectl rolling-update [old topology name] -f ***.yaml
    """
    pass

    args = parse_client_createopts(args)

    childopts = get_client_customopts() + get_exclude_jars() + get_client_createopts()
    print ("childopts=")
    print (childopts)
    exec_jkubernetes_class(
        "org.gwisoft.jkubernetes.kubectl.KubectlRollingUpdate",
        jvmtype="-server -Xms256m -Xmx256m",
        sysdirs=[JKUBERNETES_CONF_DIR, JKUBERNETES_DIR + "/bin",CUSTOM_CONF_FILE],
        args=args,
        childopts=childopts,
        isBackgroundRun="false")

def replace(args):
    """
    kubectl replace -f ***.yaml
    """
    pass

    args = parse_client_createopts(args)

    childopts = get_client_customopts() + get_exclude_jars() + get_client_createopts()
    print ("childopts=")
    print (childopts)
    exec_jkubernetes_class(
        "org.gwisoft.jkubernetes.kubectl.KubectlReplace",
        jvmtype="-server -Xms256m -Xmx256m",
        sysdirs=[JKUBERNETES_CONF_DIR, JKUBERNETES_DIR + "/bin",CUSTOM_CONF_FILE],
        args=args,
        childopts=childopts,
        isBackgroundRun="false")

def get(args):
    """
    kubectl get po [topology name]
    """
    pass

    childopts = get_client_customopts() + get_exclude_jars()
    print ("childopts=")
    print (childopts)
    exec_jkubernetes_class(
        "org.gwisoft.jkubernetes.kubectl.KubectlGet",
        jvmtype="-server -Xms256m -Xmx256m",
        sysdirs=[JKUBERNETES_CONF_DIR, JKUBERNETES_DIR + "/bin",CUSTOM_CONF_FILE],
        args=args,
        childopts=childopts,
        isBackgroundRun="false")

def get_client_createopts():
	ret = (" -Dkubernetes.create.yaml=" + JKUBERNETES_CREATE_YAML_PATH + " -Dkubernetes.apiserver.address=" + API_SERVER_ADDRESS)
	return ret

def parse_client_createopts(args):
	print ("parse_client_createopts=")
	print (args)
	curr = args
	curr.reverse()
	args_list = []
	while len(curr) > 0:
		token = curr.pop()
		print (token == "-f")
		if token == "-f":
			global JKUBERNETES_CREATE_YAML_PATH
			JKUBERNETES_CREATE_YAML_PATH = curr.pop()
		else:
			args_list.append(token)
	print (args_list)
	return 	args_list

def exec_jkubernetes_class(klass, jvmtype="-server", sysdirs=[], args=[], childopts="",isBackgroundRun=""):

    args_str = " ".join(args)

    command = "java " + " -Dkubernetes.home=" + JKUBERNETES_DIR + " " + get_config_opts() + " " + childopts + " -cp " + get_classpath(sysdirs) + " " + klass + " " + args_str

    print ("Running: " + command)
    global STATUS
    STATUS = os.execvp("java", filter_array(command.split(" ")))

#系统自定义的配置入参
def get_client_customopts():
    ret = ("")
    """
    ret = (" -Dkubernetes.root.logger=INFO,stdout -Dlogback.configurationFile=" + JKUBERNETES_DIR +
           "/conf/client_logback.xml -Dlog4j.configuration=File:" + JKUBERNETES_DIR +
           "/conf/client_log4j.properties")
    """
    return ret

def get_classpath(extrajars):
    ret = []
    ret.extend(extrajars)
    ret.extend(get_jars_full(JKUBERNETES_DIR))
    ret.extend(get_jars_full(JKUBERNETES_DIR + "/lib"))
    ret.extend(INCLUDE_JARS)
    return normclasspath(":".join(ret))

def main():
	if len(sys.argv) <= 1:
		print_usage()
		sys.exit(-1)

	global CONFIG_OPTS
	config_list, args = parse_config_opts_and_args(sys.argv[1:])
	parse_config_opts(config_list)
	COMMAND = args[0]
	ARGS = args[1:]
	if COMMANDS.get(COMMAND) == None:
		unknown_command(COMMAND)
		sys.exit(-1)
	if len(ARGS) != 0 and ARGS[0] == "help":
		print_usage(COMMAND)
		sys.exit(0)
	try:
		(COMMANDS.get(COMMAND,"help"))(ARGS)
	except Exception as msg:
		print(msg)
		print_usage(COMMAND)
		sys.exit(-1)
	sys.exit(STATUS)

COMMANDS = {"create": create,"kube":kube,"kubelet":kubelet,"delete":delete,"rolling-update":rollingUpdate,"replace":replace,"get":get}

if __name__ == "__main__":
    #check_java()
    main()


import cv2
import numpy as np
from matplotlib import pyplot as plt

from .log import logger

MATCHER_DEBUG = False
FLANN_INDEX_KDTREE = 0
GOOD_DISTANCE_LIMIT = 0.7
SIFT = cv2.SIFT_create()

def is_in_poly(p, poly):
    """
    :param p: [x, y]
    :param poly: [[], [], [], [], ...]
    :return:
    """
    px, py = p
    is_in = False
    for i, corner in enumerate(poly):
        next_i = i + 1 if i + 1 < len(poly) else 0
        x1, y1 = corner
        x2, y2 = poly[next_i]
        if (x1 == px and y1 == py) or (x2 == px and y2 == py):  # if point is on vertex
            is_in = True
            break
        if min(y1, y2) < py <= max(y1, y2):  # find horizontal edges of polygon
            x = x1 + (py - y1) * (x2 - x1) / (y2 - y1)
            if x == px:  # if point is on edge
                is_in = True
                break
            elif x > px:  # if point is on left-side of line
                is_in = not is_in
    return is_in

class FlannBasedMatcher():

    def __init__(self, origin):
        self.origin = origin
        self.kp, self.des = SIFT.detectAndCompute(origin, None)
        logger.debug(f'FlannBasedMatcher init: shape ({origin.shape})')

    def match(self, query, ret_square=True, draw=False, scope=None):
        if self.des is None:
            logger.debug('feature points is None')
            if ret_square:
                return None
            return False

        if scope is not None:
            logger.debug(f'before: {len(self.kp)}')
            logger.debug(f'scope: {scope}')
            kp0, des0 = [], []
            for kp, des in zip(self.kp, self.des):
                if scope[0][0] <= kp.pt[0] and scope[0][1] <= kp.pt[1] and kp.pt[0] <= scope[1][0] and kp.pt[1] <= scope[1][1]:
                    kp0.append(kp)
                    des0.append(des)
            logger.debug(f'after: {len(kp0)}')
            kp0, des0 = np.array(kp0), np.array(des0)
        else:
            kp0, des0 = self.kp, self.des

        h, w = query.shape
        kp, des = SIFT.detectAndCompute(query, None)

        index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
        search_params = dict(checks=50)
        flann = cv2.FlannBasedMatcher(index_params, search_params)
        matches = flann.knnMatch(des, des0, k=2)

        """store all the good matches as per Lowe's ratio test."""
        good = []
        for x, y in matches:
            if x.distance < GOOD_DISTANCE_LIMIT * y.distance:
                good.append(x)

        """draw the result"""
        if draw:
            result = cv2.drawMatches(
                query, kp, self.origin, kp0, good, None)
            plt.imshow(result, 'gray')
            plt.show()

        if len(good) <= 4 or len(good) / len(des) < 0.2:
            logger.debug(
                f'not enough good matches are found: {len(good)} / {len(matches)} / {len(des)} / {len(good) / len(des)}')
            if ret_square:
                return None
            return False

        """get the coordinates of good matches"""
        src_pts = np.float32(
            [kp[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
        dst_pts = np.float32(
            [kp0[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)

        """calculated transformation matrix and the mask"""
        M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
        matchesMask = mask.ravel().tolist()

        if M is None:
            logger.debug('calculated transformation matrix failed')
            if ret_square:
                return None
            return False

        pts = np.float32([[0, 0], [0, h-1], [w-1, h-1],
                         [w-1, 0]]).reshape(-1, 1, 2)
        dst = cv2.perspectiveTransform(pts, M)
        dst_list = np.int32(dst).reshape(4, 2).tolist()

        better = filter(lambda m: is_in_poly(
            kp0[m.trainIdx].pt, dst_list), good)
        better_kp_x = [kp[m.queryIdx].pt[0] for m in better]
        if len(better_kp_x):
            good_area_rate = np.ptp(better_kp_x) / w
        else:
            good_area_rate = 0

        """draw the result"""
        if draw or MATCHER_DEBUG:
            origin = np.array(self.origin)
            cv2.polylines(origin, [np.int32(dst)], True, 0, 2, cv2.LINE_AA)
            draw_params = dict(matchColor=(
                0, 255, 0), singlePointColor=None, matchesMask=matchesMask, flags=2)
            result = cv2.drawMatches(
                query, kp, origin, kp0, good, None, **draw_params)
            plt.imshow(result, 'gray')
            plt.show()

        if abs(dst[0][0][0] - dst[1][0][0]) > 30 or abs(dst[2][0][0] - dst[3][0][0]) > 30 or abs(dst[0][0][1] - dst[3][0][1]) > 30 or abs(dst[1][0][1] - dst[2][0][1]) > 30:
            logger.debug(f'square is not rectangle: {dst_list}')
            if ret_square:
                return None
            return False

        if good_area_rate < 0.5:
            logger.debug(f'good_area_rate is not enough: {good_area_rate}')
            if ret_square:
                return None
            return False

        logger.info(
            f'matches: {len(good)} / {len(matches)} / {len(des)} / {len(good) / len(des)} / {good_area_rate}')

        logger.debug(f'find in {dst_list}')

        if ret_square:
            return dst_list
        return True


# -*- coding:utf-8 -*-
"""
Author:
    Weichen Shen,wcshen1994@163.com

Reference:
    [1] Guo H, Tang R, Ye Y, et al. Deepfm: a factorization-machine based neural network for ctr prediction[J]. arXiv preprint arXiv:1703.04247, 2017.(https://arxiv.org/abs/1703.04247)

"""

import tensorflow as tf

from ..input_embedding import preprocess_input_embedding, get_linear_logit
from ..layers.core import PredictionLayer, DNN
from ..layers.interaction import FM
from ..layers.utils import concat_fun
from ..utils import check_feature_config_dict

def DeepFM(feature_dim_dict, embedding_size=8,
           use_fm=True, dnn_hidden_units=(128, 128), l2_reg_linear=0.00001, l2_reg_embedding=0.00001, l2_reg_dnn=0,
           init_std=0.0001, seed=1024, dnn_dropout=0, dnn_activation='relu', dnn_use_bn=False, task='binary'):
    """Instantiates the DeepFM Network architecture.

    :param feature_dim_dict: dict,to indicate sparse field and dense field like {'sparse':{'field_1':4,'field_2':3,'field_3':2},'dense':['field_4','field_5']}
    :param embedding_size: positive integer,sparse feature embedding_size
    :param use_fm: bool,use FM part or not
    :param dnn_hidden_units: list,list of positive integer or empty list, the layer number and units in each layer of DNN
    :param l2_reg_linear: float. L2 regularizer strength applied to linear part
    :param l2_reg_embedding: float. L2 regularizer strength applied to embedding vector
    :param l2_reg_dnn: float. L2 regularizer strength applied to DNN
    :param init_std: float,to use as the initialize std of embedding vector
    :param seed: integer ,to use as random seed.
    :param dnn_dropout: float in [0,1), the probability we will drop out a given DNN coordinate.
    :param dnn_activation: Activation function to use in DNN
    :param dnn_use_bn: bool. Whether use BatchNormalization before activation or not in DNN
    :param task: str, ``"binary"`` for  binary logloss or  ``"regression"`` for regression loss
    :return: A Keras model instance.
    """
    check_feature_config_dict(feature_dim_dict)

    deep_emb_list, linear_emb_list, dense_input_dict, inputs_list = preprocess_input_embedding(feature_dim_dict,
                                                                                embedding_size,
                                                                                l2_reg_embedding,
                                                                                l2_reg_linear, init_std,
                                                                                seed,
                                                                                create_linear_weight=True)

    linear_logit = get_linear_logit(linear_emb_list, dense_input_dict, l2_reg_linear)

    fm_input = concat_fun(deep_emb_list, axis=1)
    deep_input = tf.keras.layers.Flatten()(fm_input)
    fm_out = FM()(fm_input)
    deep_out = DNN(dnn_hidden_units, dnn_activation, l2_reg_dnn, dnn_dropout,
                   dnn_use_bn, seed)(deep_input)
    deep_logit = tf.keras.layers.Dense(
        1, use_bias=False, activation=None)(deep_out)

    if len(dnn_hidden_units) == 0 and use_fm == False:  # only linear
        final_logit = linear_logit
    elif len(dnn_hidden_units) == 0 and use_fm == True:  # linear + FM
        final_logit = tf.keras.layers.add([linear_logit, fm_out])
    elif len(dnn_hidden_units) > 0 and use_fm == False:  # linear +　Deep
        final_logit = tf.keras.layers.add([linear_logit, deep_logit])
    elif len(dnn_hidden_units) > 0 and use_fm == True:  # linear + FM + Deep
        final_logit = tf.keras.layers.add([linear_logit, fm_out, deep_logit])
    else:
        raise NotImplementedError

    output = PredictionLayer(task)(final_logit)
    model = tf.keras.models.Model(inputs=inputs_list, outputs=output)
    return model


# Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class PyWidgetsnbextension(PythonPackage):
    """IPython HTML widgets for Jupyter"""

    homepage = "https://pypi.python.org/pypi/widgetsnbextension"
    url      = "https://pypi.io/packages/source/w/widgetsnbextension/widgetsnbextension-1.2.6.tar.gz"

    version('1.2.6', '0aa4e152c9ba2d704389dc2453f448c7')

    depends_on('py-setuptools', type='build')
    depends_on('python@2.7:2.8,3.3:')
    depends_on('py-jupyter-notebook@4.2.0:', type=('build', 'run'))


from zerver.lib.test_classes import WebhookTestCase

TOPIC = "Zulip HQ"

class BasecampHookTests(WebhookTestCase):
    STREAM_NAME = "basecamp"
    URL_TEMPLATE = "/api/v1/external/basecamp?stream={stream}&api_key={api_key}"
    FIXTURE_DIR_NAME = "basecamp"

    def test_basecamp_makes_doc_active(self) -> None:
        expected_message = "Tomasz activated the document [New doc](https://3.basecamp.com/3688623/buckets/2957043/documents/432522214)."
        self._send_and_test_message("doc_active", expected_message)

    def test_basecamp_makes_doc_archived(self) -> None:
        expected_message = "Tomasz archived the document [new doc](https://3.basecamp.com/3688623/buckets/2957043/documents/434455988)."
        self._send_and_test_message("doc_archived", expected_message)

    def test_basecamp_makes_doc_changed_content(self) -> None:
        expected_message = "Tomasz changed content of the document [New doc edit](https://3.basecamp.com/3688623/buckets/2957043/documents/432522214)."
        self._send_and_test_message("doc_content_changed", expected_message)

    def test_basecamp_makes_doc_changed_title(self) -> None:
        expected_message = "Tomasz changed title of the document [New doc edit](https://3.basecamp.com/3688623/buckets/2957043/documents/432522214)."
        self._send_and_test_message("doc_title_changed", expected_message)

    def test_basecamp_makes_doc_publicized(self) -> None:
        expected_message = "Tomasz publicized the document [new doc](https://3.basecamp.com/3688623/buckets/2957043/documents/434455988)."
        self._send_and_test_message("doc_publicized", expected_message)

    def test_basecamp_makes_doc_created(self) -> None:
        expected_message = "Tomasz created the document [new doc](https://3.basecamp.com/3688623/buckets/2957043/documents/434455988)."
        self._send_and_test_message("doc_created", expected_message)

    def test_basecamp_makes_doc_trashed(self) -> None:
        expected_message = "Tomasz trashed the document [new doc](https://3.basecamp.com/3688623/buckets/2957043/documents/434455988)."
        self._send_and_test_message("doc_trashed", expected_message)

    def test_basecamp_makes_doc_unarchived(self) -> None:
        expected_message = "Tomasz unarchived the document [new doc](https://3.basecamp.com/3688623/buckets/2957043/documents/434455988)."
        self._send_and_test_message("doc_unarchive", expected_message)

    def test_basecamp_makes_questions_answer_archived(self) -> None:
        expected_message = "Tomasz archived the [answer](https://3.basecamp.com/3688623/buckets/2957043/questions/432527747/answers/2017-03-16#__recording_432529636) of the question [Question?](https://3.basecamp.com/3688623/buckets/2957043/questions/432527747)"
        self._send_and_test_message("questions_answer_archived", expected_message)

    def test_basecamp_makes_questions_answer_content_changed(self) -> None:
        expected_message = "Tomasz changed content of the [answer](https://3.basecamp.com/3688623/buckets/2957043/questions/432527747/answers/2017-03-16#__recording_432529636) of the question [Question](https://3.basecamp.com/3688623/buckets/2957043/questions/432527747)."
        self._send_and_test_message("questions_answer_content_changed", expected_message)

    def test_basecamp_makes_questions_answer_created(self) -> None:
        expected_message = "Tomasz created the [answer](https://3.basecamp.com/3688623/buckets/2957043/questions/432527747/answers/2017-03-16#__recording_432529636) of the question [Question](https://3.basecamp.com/3688623/buckets/2957043/questions/432527747)."
        self._send_and_test_message("questions_answer_created", expected_message)

    def test_basecamp_makes_questions_answer_trashed(self) -> None:
        expected_message = "Tomasz trashed the [answer](https://3.basecamp.com/3688623/buckets/2957043/question_answers/432529636) of the question [Question](https://3.basecamp.com/3688623/buckets/2957043/questions/432527747)."
        self._send_and_test_message("questions_answer_trashed", expected_message)

    def test_basecamp_makes_questions_answer_unarchived(self) -> None:
        expected_message = "Tomasz unarchived the [answer](https://3.basecamp.com/3688623/buckets/2957043/questions/432527747/answers/2017-03-16#__recording_432529636) of the question [Question](https://3.basecamp.com/3688623/buckets/2957043/questions/432527747)."
        self._send_and_test_message("questions_answer_unarchived", expected_message)

    def test_basecamp_makes_question_archived(self) -> None:
        expected_message = "Tomasz archived the question [Question](https://3.basecamp.com/3688623/buckets/2957043/questions/432527747)."
        self._send_and_test_message("question_archived", expected_message)

    def test_basecamp_makes_question_created(self) -> None:
        expected_message = "Tomasz created the question [Question](https://3.basecamp.com/3688623/buckets/2957043/questions/432527747)."
        self._send_and_test_message("question_created", expected_message)

    def test_basecamp_makes_question_trashed(self) -> None:
        expected_message = "Tomasz trashed the question [Question](https://3.basecamp.com/3688623/buckets/2957043/questions/432527747)."
        self._send_and_test_message("question_trashed", expected_message)

    def test_basecamp_makes_question_unarchived(self) -> None:
        expected_message = "Tomasz unarchived the question [Question](https://3.basecamp.com/3688623/buckets/2957043/questions/432527747)."
        self._send_and_test_message("question_unarchived", expected_message)

    def test_basecamp_makes_message_archived(self) -> None:
        expected_message = "Tomasz archived the message [Message Title new](https://3.basecamp.com/3688623/buckets/2957043/messages/430680605)."
        self._send_and_test_message("message_archived", expected_message)

    def test_basecamp_makes_message_content_change(self) -> None:
        expected_message = "Tomasz changed content of the message [Message Title new](https://3.basecamp.com/3688623/buckets/2957043/messages/430680605)."
        self._send_and_test_message("message_content_changed", expected_message)

    def test_basecamp_makes_message_created(self) -> None:
        expected_message = "Tomasz created the message [Message Title](https://3.basecamp.com/3688623/buckets/2957043/messages/430680605)."
        self._send_and_test_message("message_created", expected_message)

    def test_basecamp_makes_message_title_change(self) -> None:
        expected_message = "Tomasz changed subject of the message [Message Title new](https://3.basecamp.com/3688623/buckets/2957043/messages/430680605)."
        self._send_and_test_message("message_title_changed", expected_message)

    def test_basecamp_makes_message_trashed(self) -> None:
        expected_message = "Tomasz trashed the message [Message Title new](https://3.basecamp.com/3688623/buckets/2957043/messages/430680605)."
        self._send_and_test_message("message_trashed", expected_message)

    def test_basecamp_makes_message_unarchived(self) -> None:
        expected_message = "Tomasz unarchived the message [Message Title new](https://3.basecamp.com/3688623/buckets/2957043/messages/430680605)."
        self._send_and_test_message("message_unarchived", expected_message)

    def test_basecamp_makes_todo_list_created(self) -> None:
        expected_message = "Tomasz created the todo list [NEW TO DO LIST](https://3.basecamp.com/3688623/buckets/2957043/todolists/427050190)."
        self._send_and_test_message("todo_list_created", expected_message)

    def test_basecamp_makes_todo_list_description_changed(self) -> None:
        expected_message = "Tomasz changed description of the todo list [NEW TO DO LIST](https://3.basecamp.com/3688623/buckets/2957043/todolists/427050190)."
        self._send_and_test_message("todo_list_description_changed", expected_message)

    def test_basecamp_makes_todo_list_modified(self) -> None:
        expected_message = "Tomasz changed name of the todo list [NEW Name TO DO LIST](https://3.basecamp.com/3688623/buckets/2957043/todolists/427050190)."
        self._send_and_test_message("todo_list_name_changed", expected_message)

    def test_basecamp_makes_todo_assignment_changed(self) -> None:
        expected_message = "Tomasz changed assignment of the todo task [New task](https://3.basecamp.com/3688623/buckets/2957043/todos/427055624)."
        self._send_and_test_message("todo_assignment_changed", expected_message)

    def test_basecamp_makes_todo_completed(self) -> None:
        expected_message = "Tomasz completed the todo task [New task](https://3.basecamp.com/3688623/buckets/2957043/todos/427055624)."
        self._send_and_test_message("todo_completed", expected_message)

    def test_basecamp_makes_todo_uncompleted(self) -> None:
        expected_message = "Tomasz uncompleted the todo task [New task](https://3.basecamp.com/3688623/buckets/2957043/todos/427055624)."
        self._send_and_test_message("todo_uncompleted", expected_message)

    def test_basecamp_makes_todo_created(self) -> None:
        expected_message = "Tomasz created the todo task [New task](https://3.basecamp.com/3688623/buckets/2957043/todos/427055624)."
        self._send_and_test_message("todo_created", expected_message)

    def test_basecamp_makes_todo_due_on_changed(self) -> None:
        expected_message = "Tomasz changed due_on of the todo task [New task](https://3.basecamp.com/3688623/buckets/2957043/todos/427055624)."
        self._send_and_test_message("todo_due_on_changed", expected_message)

    def test_basecamp_makes_comment_created(self) -> None:
        expected_message = "Tomasz created the [comment](https://3.basecamp.com/3688623/buckets/2957043/todos/427055624#__recording_427058780) of the task [New task](https://3.basecamp.com/3688623/buckets/2957043/todos/427055624)."
        self._send_and_test_message("comment_created", expected_message)

    def _send_and_test_message(self, fixture_name: str, expected_message: str) -> None:
        self.check_webhook(fixture_name, TOPIC, expected_message)


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

# Copyright: (c) 2012, Jan-Piet Mens <jpmens () gmail.com>
# Copyright: (c) 2015, Ales Nosek <anosek.nosek () gmail.com>
# Copyright: (c) 2017, Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function
__metaclass__ = type

DOCUMENTATION = r'''
---
module: ini_file
short_description: Tweak settings in INI files
extends_documentation_fragment: files
description:
     - Manage (add, remove, change) individual settings in an INI-style file without having
       to manage the file as a whole with, say, M(ansible.builtin.template) or M(ansible.builtin.assemble).
     - Adds missing sections if they don't exist.
     - Before Ansible 2.0, comments are discarded when the source file is read, and therefore will not show up in the destination file.
     - Since Ansible 2.3, this module adds missing ending newlines to files to keep in line with the POSIX standard, even when
       no other modifications need to be applied.
options:
  path:
    description:
      - Path to the INI-style file; this file is created if required.
      - Before Ansible 2.3 this option was only usable as I(dest).
    type: path
    required: true
    aliases: [ dest ]
  section:
    description:
      - Section name in INI file. This is added if C(state=present) automatically when
        a single value is being set.
      - If left empty or set to C(null), the I(option) will be placed before the first I(section).
      - Using C(null) is also required if the config format does not support sections.
    type: str
    required: true
  option:
    description:
      - If set (required for changing a I(value)), this is the name of the option.
      - May be omitted if adding/removing a whole I(section).
    type: str
  value:
    description:
      - The string value to be associated with an I(option).
      - May be omitted when removing an I(option).
    type: str
  backup:
    description:
      - Create a backup file including the timestamp information so you can get
        the original file back if you somehow clobbered it incorrectly.
    type: bool
    default: no
  state:
    description:
      - If set to C(absent) the option or section will be removed if present instead of created.
    type: str
    choices: [ absent, present ]
    default: present
  no_extra_spaces:
    description:
      - Do not insert spaces before and after '=' symbol.
    type: bool
    default: no
  create:
    description:
      - If set to C(no), the module will fail if the file does not already exist.
      - By default it will create the file if it is missing.
    type: bool
    default: yes
  allow_no_value:
    description:
      - Allow option without value and without '=' symbol.
    type: bool
    default: no
notes:
   - While it is possible to add an I(option) without specifying a I(value), this makes no sense.
   - As of Ansible 2.3, the I(dest) option has been changed to I(path) as default, but I(dest) still works as well.
author:
    - Jan-Piet Mens (@jpmens)
    - Ales Nosek (@noseka1)
'''

EXAMPLES = r'''
# Before Ansible 2.3, option 'dest' was used instead of 'path'
- name: Ensure "fav=lemonade is in section "[drinks]" in specified file
  community.general.ini_file:
    path: /etc/conf
    section: drinks
    option: fav
    value: lemonade
    mode: '0600'
    backup: yes

- name: Ensure "temperature=cold is in section "[drinks]" in specified file
  community.general.ini_file:
    path: /etc/anotherconf
    section: drinks
    option: temperature
    value: cold
    backup: yes
'''

import os
import re
import tempfile
import traceback

from ansible.module_utils.basic import AnsibleModule

def match_opt(option, line):
    option = re.escape(option)
    return re.match('( |\t)*%s( |\t)*(=|$)' % option, line) \
        or re.match('#( |\t)*%s( |\t)*(=|$)' % option, line) \
        or re.match(';( |\t)*%s( |\t)*(=|$)' % option, line)

def match_active_opt(option, line):
    option = re.escape(option)
    return re.match('( |\t)*%s( |\t)*(=|$)' % option, line)

def do_ini(module, filename, section=None, option=None, value=None,
           state='present', backup=False, no_extra_spaces=False, create=True,
           allow_no_value=False):

    diff = dict(
        before='',
        after='',
        before_header='%s (content)' % filename,
        after_header='%s (content)' % filename,
    )

    if not os.path.exists(filename):
        if not create:
            module.fail_json(rc=257, msg='Destination %s does not exist !' % filename)
        destpath = os.path.dirname(filename)
        if not os.path.exists(destpath) and not module.check_mode:
            os.makedirs(destpath)
        ini_lines = []
    else:
        ini_file = open(filename, 'r')
        try:
            ini_lines = ini_file.readlines()
        finally:
            ini_file.close()

    if module._diff:
        diff['before'] = ''.join(ini_lines)

    changed = False

    # ini file could be empty
    if not ini_lines:
        ini_lines.append('\n')

    # last line of file may not contain a trailing newline
    if ini_lines[-1] == "" or ini_lines[-1][-1] != '\n':
        ini_lines[-1] += '\n'
        changed = True

    # append fake section lines to simplify the logic
    # At top:
    # Fake random section to do not match any other in the file
    # Using commit hash as fake section name
    fake_section_name = "ad01e11446efb704fcdbdb21f2c43757423d91c5"

    # Insert it at the beginning
    ini_lines.insert(0, '[%s]' % fake_section_name)

    # At botton:
    ini_lines.append('[')

    # If no section is defined, fake section is used
    if not section:
        section = fake_section_name

    within_section = not section
    section_start = 0
    msg = 'OK'
    if no_extra_spaces:
        assignment_format = '%s=%s\n'
    else:
        assignment_format = '%s = %s\n'

    for index, line in enumerate(ini_lines):
        if line.startswith('[%s]' % section):
            within_section = True
            section_start = index
        elif line.startswith('['):
            if within_section:
                if state == 'present':
                    # insert missing option line at the end of the section
                    for i in range(index, 0, -1):
                        # search backwards for previous non-blank or non-comment line
                        if not re.match(r'^[ \t]*([#;].*)?$', ini_lines[i - 1]):
                            if not value and allow_no_value:
                                ini_lines.insert(i, '%s\n' % option)
                            else:
                                ini_lines.insert(i, assignment_format % (option, value))
                            msg = 'option added'
                            changed = True
                            break
                elif state == 'absent' and not option:
                    # remove the entire section
                    del ini_lines[section_start:index]
                    msg = 'section removed'
                    changed = True
                break
        else:
            if within_section and option:
                if state == 'present':
                    # change the existing option line
                    if match_opt(option, line):
                        if not value and allow_no_value:
                            newline = '%s\n' % option
                        else:
                            newline = assignment_format % (option, value)
                        option_changed = ini_lines[index] != newline
                        changed = changed or option_changed
                        if option_changed:
                            msg = 'option changed'
                        ini_lines[index] = newline
                        if option_changed:
                            # remove all possible option occurrences from the rest of the section
                            index = index + 1
                            while index < len(ini_lines):
                                line = ini_lines[index]
                                if line.startswith('['):
                                    break
                                if match_active_opt(option, line):
                                    del ini_lines[index]
                                else:
                                    index = index + 1
                        break
                elif state == 'absent':
                    # delete the existing line
                    if match_active_opt(option, line):
                        del ini_lines[index]
                        changed = True
                        msg = 'option changed'
                        break

    # remove the fake section line
    del ini_lines[0]
    del ini_lines[-1:]

    if not within_section and option and state == 'present':
        ini_lines.append('[%s]\n' % section)
        if not value and allow_no_value:
            ini_lines.append('%s\n' % option)
        else:
            ini_lines.append(assignment_format % (option, value))
        changed = True
        msg = 'section and option added'

    if module._diff:
        diff['after'] = ''.join(ini_lines)

    backup_file = None
    if changed and not module.check_mode:
        if backup:
            backup_file = module.backup_local(filename)

        try:
            tmpfd, tmpfile = tempfile.mkstemp(dir=module.tmpdir)
            f = os.fdopen(tmpfd, 'w')
            f.writelines(ini_lines)
            f.close()
        except IOError:
            module.fail_json(msg="Unable to create temporary file %s", traceback=traceback.format_exc())

        try:
            module.atomic_move(tmpfile, filename)
        except IOError:
            module.ansible.fail_json(msg='Unable to move temporary \
                                   file %s to %s, IOError' % (tmpfile, filename), traceback=traceback.format_exc())

    return (changed, backup_file, diff, msg)

def main():

    module = AnsibleModule(
        argument_spec=dict(
            path=dict(type='path', required=True, aliases=['dest']),
            section=dict(type='str', required=True),
            option=dict(type='str'),
            value=dict(type='str'),
            backup=dict(type='bool', default=False),
            state=dict(type='str', default='present', choices=['absent', 'present']),
            no_extra_spaces=dict(type='bool', default=False),
            allow_no_value=dict(type='bool', default=False),
            create=dict(type='bool', default=True)
        ),
        add_file_common_args=True,
        supports_check_mode=True,
    )

    path = module.params['path']
    section = module.params['section']
    option = module.params['option']
    value = module.params['value']
    state = module.params['state']
    backup = module.params['backup']
    no_extra_spaces = module.params['no_extra_spaces']
    allow_no_value = module.params['allow_no_value']
    create = module.params['create']

    (changed, backup_file, diff, msg) = do_ini(module, path, section, option, value, state, backup, no_extra_spaces, create, allow_no_value)

    if not module.check_mode and os.path.exists(path):
        file_args = module.load_file_common_arguments(module.params)
        changed = module.set_fs_attributes_if_different(file_args, changed)

    results = dict(
        changed=changed,
        diff=diff,
        msg=msg,
        path=path,
    )
    if backup_file is not None:
        results['backup_file'] = backup_file

    # Mission complete
    module.exit_json(**results)

if __name__ == '__main__':
    main()


from flask import request, jsonify
import json
from urllib import parse as urlparse
import time
import sys

import sqlite3
from dnfp import app, apputils
from inventory import Inventory
from skilltree import SkillTree
from character import Character
from libutil import LibUtil as myutil

def get_neople_ids(name, server):
    server_dict={'안톤':'anton','바칼':'bakal','카인':'cain','카시야스':'casillas',
                '디레지에':'diregie','힐더':'hilder','프레이':'prey','시로코':'siroco'}
    s_id=server_dict[server]

    cha_id_url = 'servers/'+s_id+'/characters?characterName='+urlparse.quote(name)+'&'

    try:
        cha_id_dic=myutil.load_api(cha_id_url)
    except:
        raise

    cha_id=cha_id_dic['rows'][0]['characterId']

    return s_id, cha_id

def create_char_json(s_id, cha_id, test_mode = False, epic_status = False):
    character = Character(cha_id, s_id, test_mode, custom_data = None)
    if character.status[0] != 'ok':
        return character.status[1]

    character.do_create_char_dict(epic_status, None)

    return character.char_stat

def make_char_stat(s_id, cha_id, test_mode = False, epic_status = True):
    char_stat = create_char_json(s_id, cha_id, test_mode = test_mode, epic_status = epic_status)

    return char_stat

@app.route("/char", methods=("GET", "POST"))
def char_stat():
    name = request.args.get("name")
    server = request.args.get("server")

    sid, cid = get_neople_ids(name, server)

    char_stat = make_char_stat(sid, cid, test_mode = False, epic_status = False)
    return jsonify(char_stat)


from django.db import models
from django.contrib.auth.models import User

class SessionTable(models.Model):
    sess_id = models.CharField(max_length=15)
    name = models.CharField(max_length=15)

class VoteTable(models.Model):
    value = models.IntegerField()
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    sess_id = models.OneToOneField(SessionTable, on_delete=models.CASCADE)

class SessionResults(models.Model):
    value = models.IntegerField()
    user = models.ForeignKey(User, on_delete=models.CASCADE)


"""The Spark SQL dialect for ANSI Compliant Spark3.

Inherits from ANSI.
Spark SQL ANSI Mode is more restrictive regarding
keywords than the Default Mode, and still shares
some syntax with hive.

Based on:
- https://spark.apache.org/docs/latest/sql-ref.html
- https://spark.apache.org/docs/latest/sql-ref-ansi-compliance.html
- https://github.com/apache/spark/blob/master/sql/catalyst/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBase.g4
"""

from sqlfluff.core.parser import (
    AnyNumberOf,
    BaseSegment,
    Bracketed,
    CommentSegment,
    Conditional,
    Dedent,
    Delimited,
    Indent,
    NamedParser,
    OneOf,
    OptionallyBracketed,
    Ref,
    RegexLexer,
    Sequence,
    StringParser,
    SymbolSegment,
    Anything,
)

from sqlfluff.core.dialects import load_raw_dialect
from sqlfluff.core.parser.segments.raw import CodeSegment, KeywordSegment
from sqlfluff.dialects.dialect_spark3_keywords import (
    RESERVED_KEYWORDS,
    UNRESERVED_KEYWORDS,
)

ansi_dialect = load_raw_dialect("ansi")
hive_dialect = load_raw_dialect("hive")
spark3_dialect = ansi_dialect.copy_as("spark3")

spark3_dialect.patch_lexer_matchers(
    [
        # Spark SQL, only -- is used for single-line comment
        RegexLexer(
            "inline_comment",
            r"(--)[^\n]*",
            CommentSegment,
            segment_kwargs={"trim_start": "--"},
        ),
        # == and <=> are valid equal operations
        # <=> is a non-null equals in Spark SQL
        # https://spark.apache.org/docs/latest/api/sql/index.html#_10
        RegexLexer("equals", r"=|==|<=>", CodeSegment),
        # identifiers are delimited with `
        # within a delimited identifier, ` is used to escape special characters, including `
        # Ex: select `delimited `` with escaped` from `just delimited`
        # https://spark.apache.org/docs/latest/sql-ref-identifier.html#delimited-identifier
        RegexLexer("back_quote", r"`([^`]|``)*`", CodeSegment),
    ]
)

# Set the bare functions
spark3_dialect.sets("bare_functions").clear()
spark3_dialect.sets("bare_functions").update(
    [
        "CURRENT_DATE",
        "CURRENT_TIMESTAMP",
        "CURRENT_USER",
    ]
)

# Set the datetime units
spark3_dialect.sets("datetime_units").clear()
spark3_dialect.sets("datetime_units").update(
    [
        "YEAR",
        # Alternate syntax for YEAR
        "YYYY",
        "YY",
        "QUARTER",
        "MONTH",
        # Alternate syntax for MONTH
        "MON",
        "MM",
        "WEEK",
        "DAY",
        # Alternate syntax for DAY
        "DD",
        "HOUR",
        "MINUTE",
        "SECOND",
    ]
)

# Set Keywords
spark3_dialect.sets("unreserved_keywords").update(UNRESERVED_KEYWORDS)
spark3_dialect.sets("reserved_keywords").update(RESERVED_KEYWORDS)

# Set Angle Bracket Pairs
spark3_dialect.sets("angle_bracket_pairs").update(
    [
        ("angle", "StartAngleBracketSegment", "EndAngleBracketSegment", False),
    ]
)

# Real Segments
spark3_dialect.replace(
    ComparisonOperatorGrammar=OneOf(
        Ref("EqualsSegment"),
        Ref("EqualsSegment_a"),
        Ref("EqualsSegment_b"),
        Ref("GreaterThanSegment"),
        Ref("LessThanSegment"),
        Ref("GreaterThanOrEqualToSegment"),
        Ref("LessThanOrEqualToSegment"),
        Ref("NotEqualToSegment"),
        Ref("LikeOperatorSegment"),
    ),
    TemporaryGrammar=Sequence(
        Sequence("GLOBAL", optional=True),
        OneOf("TEMP", "TEMPORARY"),
    ),
    QuotedIdentifierSegment=NamedParser(
        "back_quote",
        CodeSegment,
        name="quoted_identifier",
        type="identifier",
        trim_chars=("`",),
    ),
)

spark3_dialect.add(
    # Add Hive Segments TODO : Is there a way to retrieve this w/o redefining?
    DoubleQuotedLiteralSegment=NamedParser(
        "double_quote",
        CodeSegment,
        name="quoted_literal",
        type="literal",
        trim_chars=('"',),
    ),
    JsonfileKeywordSegment=StringParser(
        "JSONFILE",
        KeywordSegment,
        name="json_file",
        type="file_format",
    ),
    RcfileKeywordSegment=StringParser(
        "RCFILE", KeywordSegment, name="rc_file", type="file_format"
    ),
    SequencefileKeywordSegment=StringParser(
        "SEQUENCEFILE", KeywordSegment, name="sequence_file", type="file_format"
    ),
    TextfileKeywordSegment=StringParser(
        "TEXTFILE", KeywordSegment, name="text_file", type="file_format"
    ),
    StartAngleBracketSegment=StringParser(
        "<", SymbolSegment, name="start_angle_bracket", type="start_angle_bracket"
    ),
    EndAngleBracketSegment=StringParser(
        ">", SymbolSegment, name="end_angle_bracket", type="end_angle_bracket"
    ),
    # Add Spark Segments
    EqualsSegment_a=StringParser(
        "==", SymbolSegment, name="equals", type="comparison_operator"
    ),
    EqualsSegment_b=StringParser(
        "<=>", SymbolSegment, name="equals", type="comparison_operator"
    ),
    FileKeywordSegment=StringParser(
        "FILE", KeywordSegment, name="file", type="file_type"
    ),
    JarKeywordSegment=StringParser("JAR", KeywordSegment, name="jar", type="file_type"),
    WhlKeywordSegment=StringParser("WHL", KeywordSegment, name="whl", type="file_type"),
    # Add relevant Hive Grammar
    BracketedPropertyListGrammar=hive_dialect.get_grammar(
        "BracketedPropertyListGrammar"
    ),
    CommentGrammar=hive_dialect.get_grammar("CommentGrammar"),
    FileFormatGrammar=hive_dialect.get_grammar("FileFormatGrammar"),
    LocationGrammar=hive_dialect.get_grammar("LocationGrammar"),
    PropertyGrammar=hive_dialect.get_grammar("PropertyGrammar"),
    SerdePropertiesGrammar=hive_dialect.get_grammar("SerdePropertiesGrammar"),
    StoredAsGrammar=hive_dialect.get_grammar("StoredAsGrammar"),
    StoredByGrammar=hive_dialect.get_grammar("StoredByGrammar"),
    StorageFormatGrammar=hive_dialect.get_grammar("StorageFormatGrammar"),
    SingleOrDoubleQuotedLiteralGrammar=hive_dialect.get_grammar(
        "SingleOrDoubleQuotedLiteralGrammar"
    ),
    TerminatedByGrammar=hive_dialect.get_grammar("TerminatedByGrammar"),
    # Add Spark Grammar
    BucketSpecGrammar=Sequence(
        Ref("ClusterSpecGrammar"),
        Ref("SortSpecGrammar", optional=True),
        "INTO",
        Ref("NumericLiteralSegment"),
        "BUCKETS",
    ),
    ClusterSpecGrammar=Sequence(
        "CLUSTERED",
        "BY",
        Ref("BracketedColumnReferenceListGrammar"),
    ),
    DatabasePropertiesGrammar=Sequence(
        "DBPROPERTIES", Ref("BracketedPropertyListGrammar")
    ),
    DataSourceFormatGrammar=OneOf(
        # Spark Core Data Sources
        # https://spark.apache.org/docs/latest/sql-data-sources.html
        "AVRO",
        "CSV",
        "JSON",
        "PARQUET",
        "ORC",
        "JDBC",
        # Community Contributed Data Sources
        "DELTA",  # https://github.com/delta-io/delta
        "XML",  # https://github.com/databricks/spark-xml
    ),
    PartitionSpecGrammar=Sequence(
        OneOf("PARTITION", Sequence("PARTITIONED", "BY")),
        Bracketed(
            Delimited(
                Sequence(
                    Ref("ColumnReferenceSegment"),
                    Ref("EqualsSegment", optional=True),
                    Ref("LiteralGrammar", optional=True),
                    Ref("CommentGrammar", optional=True),
                ),
            ),
        ),
    ),
    ResourceFileGrammar=OneOf(
        Ref("JarKeywordSegment"),
        Ref("WhlKeywordSegment"),
        Ref("FileKeywordSegment"),
    ),
    ResourceLocationGrammar=Sequence(
        "USING",
        Ref("ResourceFileGrammar"),
        Ref("SingleOrDoubleQuotedLiteralGrammar"),
    ),
    SortSpecGrammar=Sequence(
        "SORTED",
        "BY",
        Bracketed(
            Delimited(
                Sequence(
                    Ref("ColumnReferenceSegment"),
                    OneOf("ASC", "DESC", optional=True),
                )
            )
        ),
        optional=True,
    ),
    UnsetTablePropertiesGrammar=Sequence(
        "UNSET",
        "TBLPROPERTIES",
        Ref("IfExistsGrammar", optional=True),
        Bracketed(Delimited(Ref("SingleOrDoubleQuotedLiteralGrammar"))),
    ),
    TablePropertiesGrammar=Sequence(
        "TBLPROPERTIES", Ref("BracketedPropertyListGrammar")
    ),
)

# Hive Segments
@spark3_dialect.segment()
class RowFormatClauseSegment(hive_dialect.get_segment("RowFormatClauseSegment")):  # type: ignore
    """`ROW FORMAT` clause in a CREATE HIVEFORMAT TABLE statement."""

    type = "row_format_clause"

@spark3_dialect.segment()
class SkewedByClauseSegment(hive_dialect.get_segment("SkewedByClauseSegment")):  # type: ignore
    """`SKEWED BY` clause in a CREATE HIVEFORMAT TABLE statement."""

    type = "skewed_by_clause"

# Primitive Data Types
@spark3_dialect.segment()
class PrimitiveTypeSegment(BaseSegment):
    """Spark SQL Primitive data types.

    https://spark.apache.org/docs/latest/sql-ref-datatypes.html
    """

    type = "primitive_type"
    match_grammar = OneOf(
        "BOOLEAN",
        # TODO : not currently supported; add segment - see NumericLiteralSegment
        # "BYTE",
        "TINYINT",
        # TODO : not currently supported; add segment - see NumericLiteralSegment
        # "SHORT",
        "SMALLINT",
        "INT",
        "BIGINT",
        "FLOAT",
        "REAL",
        "DOUBLE",
        "DATE",
        "TIMESTAMP",
        "STRING",
        Sequence(
            OneOf("CHAR", "CHARACTER", "VARCHAR"),
            Bracketed(Ref("NumericLiteralSegment"), optional=True),
        ),
        "BINARY",
        Sequence(
            OneOf("DECIMAL", "DEC", "NUMERIC"),
            Bracketed(
                Ref("NumericLiteralSegment"),
                Ref("CommaSegment"),
                Ref("NumericLiteralSegment"),
                optional=True,
            ),
        ),
        "INTERVAL",
    )

@spark3_dialect.segment(replace=True)
class DatatypeSegment(PrimitiveTypeSegment):
    """Spark SQL Data types.

    https://spark.apache.org/docs/latest/sql-ref-datatypes.html
    """

    type = "data_type"
    match_grammar = OneOf(
        Ref("PrimitiveTypeSegment"),
        Sequence(
            "ARRAY",
            Bracketed(
                Ref("DatatypeSegment"),
                bracket_pairs_set="angle_bracket_pairs",
                bracket_type="angle",
            ),
        ),
        Sequence(
            "MAP",
            Bracketed(
                Sequence(
                    Ref("PrimitiveTypeSegment"),
                    Ref("CommaSegment"),
                    Ref("DatatypeSegment"),
                ),
                bracket_pairs_set="angle_bracket_pairs",
                bracket_type="angle",
            ),
        ),
        Sequence(
            "STRUCT",
            Bracketed(
                Delimited(
                    Sequence(
                        Ref("NakedIdentifierSegment"),
                        Ref("ColonSegment"),
                        Ref("DatatypeSegment"),
                        Ref("CommentGrammar", optional=True),
                    ),
                ),
                bracket_pairs_set="angle_bracket_pairs",
                bracket_type="angle",
            ),
        ),
    )

# Data Definition Statements
# http://spark.apache.org/docs/latest/sql-ref-syntax-ddl.html
@spark3_dialect.segment()
class AlterDatabaseStatementSegment(BaseSegment):
    """An `ALTER DATABASE/SCHEMA` statement.

    http://spark.apache.org/docs/latest/sql-ref-syntax-ddl-alter-database.html
    """

    type = "alter_database_statement"

    match_grammar = Sequence(
        "ALTER",
        OneOf("DATABASE", "SCHEMA"),
        Ref("DatabaseReferenceSegment"),
        "SET",
        Ref("DatabasePropertiesGrammar"),
    )

@spark3_dialect.segment(replace=True)
class AlterTableStatementSegment(BaseSegment):
    """A `ALTER TABLE` statement to change the table schema or properties.

    http://spark.apache.org/docs/latest/sql-ref-syntax-ddl-alter-table.html
    """

    type = "alter_table_statement"

    match_grammar = Sequence(
        "ALTER",
        "TABLE",
        Ref("TableReferenceSegment"),
        OneOf(
            # ALTER TABLE - RENAME TO `table_identifier`
            Sequence(
                "RENAME",
                "TO",
                Ref("TableReferenceSegment"),
            ),
            # ALTER TABLE - RENAME `partition_spec`
            Sequence(
                Ref("PartitionSpecGrammar"),
                "RENAME",
                "TO",
                Ref("PartitionSpecGrammar"),
            ),
            # ALTER TABLE - ADD COLUMNS
            Sequence(
                "ADD",
                "COLUMNS",
                Bracketed(
                    Delimited(
                        Ref("ColumnDefinitionSegment"),
                    ),
                ),
            ),
            # ALTER TABLE - ALTER OR CHANGE COLUMN
            Sequence(
                OneOf("ALTER", "CHANGE"),
                "COLUMN",
                Ref("ColumnReferenceSegment"),
                Sequence("TYPE", Ref("DatatypeSegment"), optional=True),
                Ref("CommentGrammar", optional=True),
                OneOf(
                    "FIRST",
                    Sequence("AFTER", Ref("ColumnReferenceSegment")),
                    optional=True,
                ),
                Sequence(OneOf("SET", "DROP"), "NOT NULL", optional=True),
            ),
            # ALTER TABLE - ADD PARTITION
            Sequence(
                "ADD",
                Ref("IfNotExistsGrammar", optional=True),
                AnyNumberOf(Ref("PartitionSpecGrammar")),
            ),
            # ALTER TABLE - DROP PARTITION
            Sequence(
                "DROP",
                Ref("IfExistsGrammar", optional=True),
                Ref("PartitionSpecGrammar"),
                Sequence("PURGE", optional=True),
            ),
            # ALTER TABLE - REPAIR PARTITION
            Sequence("RECOVER", "PARTITIONS"),
            # ALTER TABLE - SET PROPERTIES
            Sequence("SET", Ref("TablePropertiesGrammar")),
            # ALTER TABLE - UNSET PROPERTIES
            Ref("UnsetTablePropertiesGrammar"),
            # ALTER TABLE - SET SERDE
            Sequence(
                Ref("PartitionSpecGrammar", optional=True),
                "SET",
                OneOf(
                    Sequence(
                        "SERDEPROPERTIES",
                        Ref("BracketedPropertyListGrammar"),
                    ),
                    Sequence(
                        "SERDE",
                        Ref("SingleOrDoubleQuotedLiteralGrammar"),
                        Ref("SerdePropertiesGrammar", optional=True),
                    ),
                ),
            ),
            # ALTER TABLE - SET FILE FORMAT
            Sequence(
                Ref("PartitionSpecGrammar", optional=True),
                "SET",
                "FILEFORMAT",
                Ref("DataSourceFormatGrammar"),
            ),
            # ALTER TABLE - CHANGE FILE LOCATION
            Sequence(
                Ref("PartitionSpecGrammar"),
                "SET",
                Ref("LocationGrammar"),
            ),
        ),
    )

@spark3_dialect.segment()
class AlterViewStatementSegment(BaseSegment):
    """A `ALTER VIEW` statement to change the view schema or properties.

    https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-alter-view.html
    """

    type = "alter_view_statement"

    match_grammar = Sequence(
        "ALTER",
        "VIEW",
        Ref("TableReferenceSegment"),
        OneOf(
            Sequence(
                "RENAME",
                "TO",
                Ref("TableReferenceSegment"),
            ),
            Sequence("SET", Ref("TablePropertiesGrammar")),
            Ref("UnsetTablePropertiesGrammar"),
            Sequence(
                "AS",
                OptionallyBracketed(Ref("SelectStatementSegment")),
            ),
        ),
    )

@spark3_dialect.segment(replace=True)
class CreateDatabaseStatementSegment(BaseSegment):
    """A `CREATE DATABASE` statement.

    https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-database.html
    """

    type = "create_database_statement"
    match_grammar = Sequence(
        "CREATE",
        OneOf("DATABASE", "SCHEMA"),
        Ref("IfNotExistsGrammar", optional=True),
        Ref("DatabaseReferenceSegment"),
        Ref("CommentGrammar", optional=True),
        Ref("LocationGrammar", optional=True),
        Sequence(
            "WITH", "DBPROPERTIES", Ref("BracketedPropertyListGrammar"), optional=True
        ),
    )

@spark3_dialect.segment(replace=True)
class CreateFunctionStatementSegment(BaseSegment):
    """A `CREATE FUNCTION` statement.

    https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-function.html
    """

    type = "create_function_statement"

    match_grammar = Sequence(
        "CREATE",
        Sequence("OR", "REPLACE", optional=True),
        Ref("TemporaryGrammar", optional=True),
        "FUNCTION",
        Anything(),
    )

    parse_grammar = Sequence(
        "CREATE",
        Sequence("OR", "REPLACE", optional=True),
        Ref("TemporaryGrammar", optional=True),
        "FUNCTION",
        Ref("IfNotExistsGrammar", optional=True),
        Ref("FunctionNameIdentifierSegment"),
        "AS",
        Ref("SingleOrDoubleQuotedLiteralGrammar"),
        Ref("ResourceLocationGrammar", optional=True),
    )

@spark3_dialect.segment(replace=True)
class CreateTableStatementSegment(BaseSegment):
    """A `CREATE TABLE` statement using a Data Source or Like.

    http://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-table-datasource.html
    https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-table-like.html
    """

    type = "create_table_statement"

    match_grammar = Sequence(
        "CREATE",
        "TABLE",
        Ref("IfNotExistsGrammar", optional=True),
        Ref("TableReferenceSegment"),
        OneOf(
            # Columns and comment syntax:
            Sequence(
                Bracketed(
                    Delimited(
                        Sequence(
                            Ref("ColumnDefinitionSegment"),
                            Ref("CommentGrammar", optional=True),
                        ),
                    ),
                ),
            ),
            # Like Syntax
            Sequence(
                "LIKE",
                Ref("TableReferenceSegment"),
            ),
            optional=True,
        ),
        Sequence("USING", Ref("DataSourceFormatGrammar"), optional=True),
        Ref("RowFormatClauseSegment", optional=True),
        Ref("StoredAsGrammar", optional=True),
        Sequence("OPTIONS", Ref("BracketedPropertyListGrammar"), optional=True),
        Ref("PartitionSpecGrammar", optional=True),
        Ref("BucketSpecGrammar", optional=True),
        AnyNumberOf(
            Ref("LocationGrammar", optional=True),
            Ref("CommentGrammar", optional=True),
            Ref("TablePropertiesGrammar", optional=True),
        ),
        # Create AS syntax:
        Sequence(
            "AS",
            OptionallyBracketed(Ref("SelectableGrammar")),
            optional=True,
        ),
    )

@spark3_dialect.segment()
class CreateHiveFormatTableStatementSegment(hive_dialect.get_segment("CreateTableStatementSegment")):  # type: ignore
    """A `CREATE TABLE` statement using Hive format.

    https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-table-hiveformat.html
    """

    type = "create_table_statement"

@spark3_dialect.segment(replace=True)
class CreateViewStatementSegment(BaseSegment):
    """A `CREATE VIEW` statement.

    https://spark.apache.org/docs/3.0.0/sql-ref-syntax-ddl-create-view.html#syntax
    """

    type = "create_view_statement"

    match_grammar = Sequence(
        "CREATE",
        Ref("OrReplaceGrammar", optional=True),
        Ref("TemporaryGrammar", optional=True),
        "VIEW",
        Ref("IfNotExistsGrammar", optional=True),
        Ref("TableReferenceSegment"),
        # Columns and comment syntax:
        Sequence(
            Bracketed(
                Delimited(
                    Sequence(
                        Ref("ColumnReferenceSegment"),
                        Ref("CommentGrammar", optional=True),
                    ),
                ),
            ),
            optional=True,
        ),
        Ref("CommentGrammar", optional=True),
        Ref("TablePropertiesGrammar", optional=True),
        "AS",
        Ref("SelectableGrammar"),
        Ref("WithNoSchemaBindingClauseSegment", optional=True),
    )

@spark3_dialect.segment()
class DropFunctionStatementSegment(BaseSegment):
    """A `DROP FUNCTION` STATEMENT.

    https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-drop-function.html
    """

    type = "drop_function_statement"

    match_grammar = Sequence(
        "DROP",
        Ref("TemporaryGrammar", optional=True),
        "FUNCTION",
        Ref("IfExistsGrammar", optional=True),
        Ref("FunctionNameSegment"),
    )

@spark3_dialect.segment()
class MsckRepairTableStatementSegment(hive_dialect.get_segment("MsckRepairTableStatementSegment")):  # type: ignore
    """A `REPAIR TABLE` statement using Hive MSCK (Metastore Check) format.

    This class inherits from Hive since Spark leverages Hive format for this command and
    is dependent on the Hive metastore.

    https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-repair-table.html
    """

    type = "msck_repair_table_statement"

# Auxiliary Statements
@spark3_dialect.segment()
class AddExecutablePackage(BaseSegment):
    """A `ADD JAR` statement.

    https://spark.apache.org/docs/latest/sql-ref-syntax-aux-resource-mgmt-add-jar.html
    """

    type = "add_executable_package"

    match_grammar = Sequence(
        "ADD",
        Ref("ResourceFileGrammar"),
        Ref("SingleOrDoubleQuotedLiteralGrammar"),
    )

@spark3_dialect.segment(replace=True)
class StatementSegment(BaseSegment):
    """Overriding StatementSegment to allow for additional segment parsing."""

    match_grammar = ansi_dialect.get_segment("StatementSegment").match_grammar.copy()

    parse_grammar = ansi_dialect.get_segment("StatementSegment").parse_grammar.copy(
        # Segments defined in Spark3 dialect
        insert=[
            # Data Definition Statements
            Ref("AlterDatabaseStatementSegment"),
            Ref("AlterTableStatementSegment"),
            Ref("AlterViewStatementSegment"),
            Ref("CreateHiveFormatTableStatementSegment"),
            Ref("DropFunctionStatementSegment"),
            Ref("MsckRepairTableStatementSegment"),
            # Auxiliary Statements
            Ref("AddExecutablePackage"),
        ],
        remove=[
            Ref("TransactionStatementSegment"),
            Ref("CreateSchemaStatementSegment"),
            Ref("SetSchemaStatementSegment"),
            Ref("CreateExtensionStatementSegment"),
            Ref("CreateModelStatementSegment"),
            Ref("DropModelStatementSegment"),
        ],
    )

@spark3_dialect.segment(replace=True)
class JoinClauseSegment(BaseSegment):
    """Any number of join clauses, including the `JOIN` keyword.

    https://spark.apache.org/docs/3.0.0/sql-ref-syntax-qry-select-join.html
    TODO: Add NATURAL JOIN syntax.
    """

    type = "join_clause"
    match_grammar = Sequence(
        # NB These qualifiers are optional
        # TODO: Allow nested joins like:
        # ....FROM S1.T1 t1 LEFT JOIN ( S2.T2 t2 JOIN S3.T3 t3 ON t2.col1=t3.col1) ON tab1.col1 = tab2.col1
        OneOf(
            "CROSS",
            "INNER",
            Sequence(
                OneOf(
                    "FULL",
                    "LEFT",
                    "RIGHT",
                ),
                Ref.keyword("OUTER", optional=True),
            ),
            Sequence(
                Ref.keyword("LEFT", optional=True),
                "SEMI",
            ),
            Sequence(
                Ref.keyword("LEFT", optional=True),
                "ANTI",
            ),
            optional=True,
        ),
        Ref("JoinKeywords"),
        Indent,
        Sequence(
            Ref("FromExpressionElementSegment"),
            Conditional(Dedent, indented_using_on=False),
            # NB: this is optional
            OneOf(
                # ON clause
                Ref("JoinOnConditionSegment"),
                # USING clause
                Sequence(
                    "USING",
                    Indent,
                    Bracketed(
                        # NB: We don't use BracketedColumnReferenceListGrammar
                        # here because we're just using SingleIdentifierGrammar,
                        # rather than ObjectReferenceSegment or ColumnReferenceSegment.
                        # This is a) so that we don't lint it as a reference and
                        # b) because the column will probably be returned anyway
                        # during parsing.
                        Delimited(
                            Ref("SingleIdentifierGrammar"),
                            ephemeral_name="UsingClauseContents",
                        )
                    ),
                    Dedent,
                ),
                # Unqualified joins *are* allowed. They just might not
                # be a good idea.
                optional=True,
            ),
            Conditional(Indent, indented_using_on=False),
        ),
        Dedent,
    )

    get_eventual_alias = ansi_dialect.get_segment(
        "JoinClauseSegment"
    ).get_eventual_alias


"""A logging handler that emits to a Discord webhook."""
import requests
from logging import Handler

class DiscordHandler(Handler):
    """A logging handler that emits to a Discord webhook."""

    def __init__(self, webhook, *args, **kwargs):
        """Initialize the DiscordHandler class."""
        super().__init__(*args, **kwargs)
        self.webhook = webhook

    def emit(self, record):
        """Emit record to the Discord webhook."""
        json = {"content": self.format(record)}
        try:
            requests.post(self.webhook, json=json)
        except requests.RequestException:
            self.handleError(record)


"""
WSGI config for pithyquotes project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pithyquotes.settings')

application = get_wsgi_application()


""" Class to initialize common objects. """

import pickle
from pathlib import Path

################################################################
class Init():

  #---------------------------------------------------------------
  # Constructor
  #---------------------------------------------------------------
  def __init__(self, workdir, **kwargs):

    print('Init class created.')

    self.workdir = Path(workdir)
    self.cachedir = self.workdir / 'cache'
    print('workdir: {}'.format(self.workdir))
    print('cachedir: {}'.format(self.cachedir))

  #---------------------------------------------------------------
  # Initialize settings as class members of obj
  #---------------------------------------------------------------
  def Initialize(self, obj):

    obj.workdir = self.workdir
    obj.cachedir = self.cachedir
    obj.cachedir.mkdir(parents=True, exist_ok=True)

    obj.AllData = pickle.load((obj.workdir / 'default.p').open('rb'))

    #: Sets the collision systems for the entire project,
    #: where each system is a string of the form
    #: ``'<projectile 1><projectile 2><beam energy in GeV>'``,
    #: such as ``'PbPb2760'``, ``'AuAu200'``, ``'pPb5020'``.
    #: Even if the project uses only a single system,
    #: this should still be a list of one system string.
    obj.systems = obj.AllData["systems"]

    #: Design attribute. This is a list of
    #: strings describing the inputs.
    #: The default is for the example data.
    obj.keys = obj.AllData["keys"]

    #: Design attribute. This is a list of input
    #: labels in LaTeX for plotting.
    #: The default is for the example data.
    obj.labels = obj.AllData["labels"]

    #: Design attribute. This is list of tuples of
    #: (min,max) for each design input.
    #: The default is for the example data.
    obj.ranges = obj.AllData["ranges"]

    #: Design array to use - should be a numpy array.
    #: Keep at None generate a Latin Hypercube with above (specified) range.
    #: Design array for example is commented under default.
    obj.design_array = obj.AllData["design"]

    #: Dictionary of the model output.
    #: Form MUST be data_list[system][observable][subobservable][{'Y': ,'x': }].
    #:     'Y' is an (n x p) numpy array of the output.
    #:
    #:     'x' is a (1 x p) numpy array of numeric index of columns of Y (if exists). In the example data, x is p_T.
    #: This MUST be changed from None - no built-in default exists. Uncomment the line below default for example.
    obj.data_list = obj.AllData["model"]

    #: Dictionary for the model validation output
    #: Must be the same for as the model output dictionary
    #data_list_val = pickle.load((cachedir / 'model/validation/data_dict_val.p').open('rb'))
    obj.data_list_val = None

    #: Dictionary of the experimental data.
    #: Form MUST be exp_data_list[system][observable][subobservable][{'y':,'x':,'yerr':{'stat':,'sys'}}].
    #:      'y' is a (1 x p) numpy array of experimental data.
    #:
    #:      'x' is a (1 x p) numpy array of numeric index of columns of Y (if exists). In the example data, x is p_T.
    #:
    #:      'yerr' is a dictionary with keys 'stat' and 'sys'.
    #:
    #:      'stat' is a (1 x p) array of statistical errors.
    #:
    #:      'sys' is a (1 x p) array of systematic errors.
    #: This MUST be changed from None - no built-in default exists. Uncomment the line below default for example.
    obj.exp_data_list = obj.AllData["data"]

    #: Experimental covariance matrix.
    #: Set exp_cov = None to have the script estimate the covariance matrix.
    #: Example commented below default.
    obj.exp_cov = obj.AllData["cov"]

    #: Observables to emulate as a list of 2-tuples
    #: ``(obs, [list of subobs])``.
    obj.observables = obj.AllData["observables"]

  #---------------------------------------------------------------
  # Initialize settings as class members of obj
  #---------------------------------------------------------------
  def systems(self):

    AllData = pickle.load((self.workdir / 'default.p').open('rb'))

    #: Sets the collision systems for the entire project,
    #: where each system is a string of the form
    #: ``'<projectile 1><projectile 2><beam energy in GeV>'``,
    #: such as ``'PbPb2760'``, ``'AuAu200'``, ``'pPb5020'``.
    #: Even if the project uses only a single system,
    #: this should still be a list of one system string.
    return AllData["systems"]

  #---------------------------------------------------------------
  # Return formatted string of class members
  #---------------------------------------------------------------
  def __str__(self):
    s = []
    variables = self.__dict__.keys()
    for v in variables:
      s.append('{} = {}'.format(v, self.__dict__[v]))
    return "[i] {} with \n .  {}".format(self.__class__.__name__, '\n .  '.join(s))


#===============================================================================
# Copyright 2020 Intel Corporation
#
# 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.
#===============================================================================

import sys
import os
import argparse
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import bench

import numpy as np
from cuml import KMeans
import warnings
from sklearn.metrics.cluster import davies_bouldin_score

warnings.filterwarnings('ignore', category=FutureWarning)
parser = argparse.ArgumentParser(description='cuML K-means benchmark')
parser.add_argument('-i', '--filei', '--fileI', '--init',
                    type=str, help='Initial clusters')
parser.add_argument('-t', '--tol', type=float, default=0.,
                    help='Absolute threshold')
parser.add_argument('--maxiter', type=int, default=100,
                    help='Maximum number of iterations')
parser.add_argument('--samples-per-batch', type=int, default=32768,
                    help='Maximum number of iterations')
parser.add_argument('--n-clusters', type=int, help='Number of clusters')
params = bench.parse_args(parser, prefix='cuml', loop_types=('fit', 'predict'))

# Load and convert generated data
X_train, X_test, _, _ = bench.load_data(params)

if params.filei == 'k-means++':
    X_init = 'k-means++'
# Load initial centroids from specified path
elif params.filei is not None:
    X_init = np.load(params.filei).astype(params.dtype)
    params.n_clusters = X_init.shape[0]
# or choose random centroids from training data
else:
    np.random.seed(params.seed)
    centroids_idx = np.random.randint(0, X_train.shape[0],
                                      size=params.n_clusters)
    if hasattr(X_train, "iloc"):
        X_init = X_train.iloc[centroids_idx].to_pandas().values
    else:
        X_init = X_train[centroids_idx]

# Workaround for cuML kmeans fail
# when second call of 'fit' method causes AttributeError
def kmeans_fit(X):
    alg = KMeans(n_clusters=params.n_clusters, tol=params.tol,
                 max_iter=params.maxiter, init=X_init,
                 max_samples_per_batch=params.samples_per_batch)
    alg.fit(X)
    return alg

# Time fit
fit_time, kmeans = bench.measure_function_time(kmeans_fit, X_train, params=params)
train_predict = kmeans.predict(X_train)

# Time predict
predict_time, test_predict = bench.measure_function_time(kmeans.predict, X_test,
                                                         params=params)

X_train_host = bench.convert_to_numpy(X_train)
train_predict_host = bench.convert_to_numpy(train_predict)
acc_train = davies_bouldin_score(X_train_host, train_predict_host)

X_test_host = bench.convert_to_numpy(X_test)
test_predict_host = bench.convert_to_numpy(test_predict)

acc_test = davies_bouldin_score(X_test_host, test_predict_host)

bench.print_output(library='cuml', algorithm='kmeans',
                   stages=['training', 'prediction'], params=params,
                   functions=['KMeans.fit', 'KMeans.predict'],
                   times=[fit_time, predict_time], accuracy_type='davies_bouldin_score',
                   accuracies=[acc_train, acc_test], data=[X_train, X_test],
                   alg_instance=kmeans)


from .telescope import Telescope


from mcstats import mcstats

mcstats.registry.append(
    mcstats.MinecraftStat(
        'pot_flower',
        {
            'title': 'Florist',
            'desc': 'Flowers potted',
            'unit': 'int',
        },
        mcstats.StatReader(['minecraft:custom','minecraft:pot_flower'])
    ))


import unittest

from social_apis.networks.twitter_v2 import Twitter2
from config import tw_access_token

class TestTwitter2(unittest.TestCase):

    def setUp(self):
        self.tweet_ids = ['1261326399320715264', '1278347468690915330']
        self.api = Twitter2(access_token=tw_access_token)

    def test_get_tweet(self):
        self.api.get_tweet(id=self.tweet_ids[0])

    def test_get_tweets(self):
        self.api.get_tweets(ids=self.tweet_ids)

    def test_get_compliance_jobs(self):
        self.api.get_compliance_jobs(type='tweets')

    def test_quota_parsing(self):
        self.api.get_compliance_jobs(type='tweets')
        self.assertIsNotNone(self.api.get_quota())


#! /usr/bin/env python

# Copyright (c) 2014, Dawn Robotics Ltd
# All rights reserved.

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:

# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.

# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.

# 3. Neither the name of the Dawn Robotics Ltd nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import logging
import math
import time
import Queue
import mini_driver
import threading

#---------------------------------------------------------------------------------------------------
class RobotController:

    MIN_ANGLE = 0.0
    MAX_ANGLE = 180.0
    CENTRE_ANGLE = (MIN_ANGLE + MAX_ANGLE)/2.0

    MAX_UPDATE_TIME_DIFF = 0.25
    TIME_BETWEEN_SERVO_SETTING_UPDATES = 1.0
    TIME_BETWEEN_SENSOR_CONFIGURATION_UPDATES = 0.5

    JOYSTICK_DEAD_ZONE = 0.1
    MAX_ABS_NECK_SPEED = 30.0   # Degrees per second

    MOTION_COMMAND_TIMEOUT = 2.0 # If no commands for the motors are recieved in this time then
                                 # the motors (drive and servo) are set to zero speed

    #-----------------------------------------------------------------------------------------------
    def __init__( self, robotConfig ):

        self.miniDriver = mini_driver.MiniDriver()
        connected = self.miniDriver.connect()
        if not connected:
            raise Exception( "Unable to connect to the mini driver" )

        self.robotConfig = robotConfig
        self.leftMotorSpeed = 0
        self.rightMotorSpeed = 0
        self.panAngle = self.CENTRE_ANGLE
        self.tiltAngle = self.CENTRE_ANGLE

        self.panSpeed = 0.0
        self.tiltSpeed = 0.0

        self.lastServoSettingsSendTime = 0.0
        self.lastSensorConfigurationSendTime = 0.0
        self.lastUpdateTime = 0.0
        self.lastMotionCommandTime = time.time()

        self.piSensorModuleName = ""
        self.piSensorModule = None
        self.piSensorReader = None
        self.piSensorDict = {}

    #-----------------------------------------------------------------------------------------------
    def __del__( self ):

        self.disconnect()

    #-----------------------------------------------------------------------------------------------
    def disconnect( self ):

        self.miniDriver.disconnect()

    #-----------------------------------------------------------------------------------------------
    def getStatusDict( self ):

        presetMaxAbsMotorSpeed, presetMaxAbsTurnSpeed = self.miniDriver.getPresetMotorSpeeds()

        statusDict = {
            "batteryVoltage" : self.miniDriver.getBatteryVoltageReading().data,
            "presetMaxAbsMotorSpeed" : presetMaxAbsMotorSpeed,
            "presetMaxAbsTurnSpeed" : presetMaxAbsTurnSpeed,
            "sensors" : self.getSensorDict()
        }

        return statusDict

    #-----------------------------------------------------------------------------------------------
    def getSensorDict( self ):

        sensorDict = {
            "batteryVoltage" : self.miniDriver.getBatteryVoltageReading(),
            "digital" : self.miniDriver.getDigitalReadings(),
            "analog" : self.miniDriver.getAnalogReadings(),
            "ultrasonic" : self.miniDriver.getUltrasonicReading(),
            "encoders" : self.miniDriver.getEncodersReading(),
        }

        sensorDict.update( self.piSensorDict )

        return sensorDict

    #-----------------------------------------------------------------------------------------------
    def normaliseJoystickData( self, joystickX, joystickY ):

        stickVectorLength = math.sqrt( joystickX**2 + joystickY**2 )
        if stickVectorLength > 1.0:
            joystickX /= stickVectorLength
            joystickY /= stickVectorLength

        if stickVectorLength < self.JOYSTICK_DEAD_ZONE:
            joystickX = 0.0
            joystickY = 0.0

        return ( joystickX, joystickY )

    #-----------------------------------------------------------------------------------------------
    def centreNeck( self ):

        self.panAngle = self.CENTRE_ANGLE
        self.tiltAngle = self.CENTRE_ANGLE
        self.panSpeed = 0.0
        self.tiltSpeed = 0.0

    #-----------------------------------------------------------------------------------------------
    def setMotorJoystickPos( self, joystickX, joystickY ):

        joystickX, joystickY = self.normaliseJoystickData( joystickX, joystickY )

        if self.robotConfig.usePresetMotorSpeeds:

            maxAbsMotorSpeed, maxAbsTurnSpeed = self.miniDriver.getPresetMotorSpeeds()

        else:

            maxAbsMotorSpeed = self.robotConfig.customMaxAbsMotorSpeed
            maxAbsTurnSpeed = self.robotConfig.customMaxAbsTurnSpeed

        # Set forward speed from joystickY
        leftMotorSpeed = maxAbsMotorSpeed*joystickY
        rightMotorSpeed = maxAbsMotorSpeed*joystickY

        # Set turn speed from joystickX
        leftMotorSpeed += maxAbsTurnSpeed*joystickX
        rightMotorSpeed -= maxAbsTurnSpeed*joystickX

        leftMotorSpeed = max( -maxAbsMotorSpeed, min( leftMotorSpeed, maxAbsMotorSpeed ) )
        rightMotorSpeed = max( -maxAbsMotorSpeed, min( rightMotorSpeed, maxAbsMotorSpeed ) )

        self.leftMotorSpeed = leftMotorSpeed*self.robotConfig.leftMotorScale
        self.rightMotorSpeed = rightMotorSpeed

        self.lastMotionCommandTime = time.time()

    #-----------------------------------------------------------------------------------------------
    def setMotorSpeeds( self, leftMotorSpeed, rightMotorSpeed ):

        if self.robotConfig.usePresetMotorSpeeds:

            maxAbsMotorSpeed, maxAbsTurnSpeed = self.miniDriver.getPresetMotorSpeeds()

        else:

            maxAbsMotorSpeed = self.robotConfig.customMaxAbsMotorSpeed
            maxAbsTurnSpeed = self.robotConfig.customMaxAbsTurnSpeed

        self.leftMotorSpeed = max( -maxAbsMotorSpeed, min( leftMotorSpeed, maxAbsMotorSpeed ) )
        self.rightMotorSpeed = max( -maxAbsMotorSpeed, min( rightMotorSpeed, maxAbsMotorSpeed ) )

        self.lastMotionCommandTime = time.time()

    #-----------------------------------------------------------------------------------------------
    def setNeckJoystickPos( self, joystickX, joystickY ):

        joystickX, joystickY = self.normaliseJoystickData( joystickX, joystickY )

        # Set pan and tilt angle speeds
        self.panSpeed = -self.MAX_ABS_NECK_SPEED*joystickX
        self.tiltSpeed = -self.MAX_ABS_NECK_SPEED*joystickY

        self.lastMotionCommandTime = time.time()

    #-----------------------------------------------------------------------------------------------
    def setNeckAngles( self, panAngle, tiltAngle ):

        self.panAngle = max( self.MIN_ANGLE, min( panAngle, self.MAX_ANGLE ) )
        self.tiltAngle = max( self.MIN_ANGLE, min( tiltAngle, self.MAX_ANGLE ) )
        self.panSpeed = 0.0
        self.tiltSpeed = 0.0

        self.lastMotionCommandTime = time.time()

    #-----------------------------------------------------------------------------------------------
    def _loadPiSensorModule( self ):

        if self.robotConfig.piSensorModuleName != "":

            # Try to import the new sensor module
            newSensorModule = None
            try:

                newSensorModule = __import__( self.robotConfig.piSensorModuleName, fromlist=[''] )

            except Exception as e:
                logging.error( "Caught exception when trying to import Pi sensor module" )
                logging.error( str( e ) )

            if newSensorModule != None:

                # We have a new sensor module. Shutdown any existing sensor reader
                if self.piSensorReader != None:
                    self.piSensorReader.shutdown()
                    self.piSensorReader = None

                # Remove reference to existing sensor module
                self.piSensorModule = None
                self.piSensorModuleName = ""

                # Try to create the new Pi sensor reader
                newSensorReader = None

                try:

                    newSensorReader = newSensorModule.PiSensorReader()

                except Exception as e:
                    logging.error( "Caught exception when trying to create Pi sensor reader" )
                    logging.error( str( e ) )

                if newSensorReader != None:
                    self.piSensorModule = newSensorModule
                    self.piSensorModuleName = self.robotConfig.piSensorModuleName
                    self.piSensorReader = newSensorReader

    #-----------------------------------------------------------------------------------------------
    def update( self ):

        if not self.miniDriver.isConnected():
            return

        curTime = time.time()
        timeDiff = min( curTime - self.lastUpdateTime, self.MAX_UPDATE_TIME_DIFF )

        # Turn off the motors if we haven't received a motion command for a while
        if curTime - self.lastMotionCommandTime > self.MOTION_COMMAND_TIMEOUT:

            self.leftMotorSpeed = 0.0
            self.rightMotorSpeed = 0.0
            self.panSpeed = 0.0
            self.tiltSpeed = 0.0

        # Update the pan and tilt angles
        self.panAngle += self.panSpeed*timeDiff
        self.tiltAngle += self.tiltSpeed*timeDiff

        self.panAngle = max( self.MIN_ANGLE, min( self.panAngle, self.MAX_ANGLE ) )
        self.tiltAngle = max( self.MIN_ANGLE, min( self.tiltAngle, self.MAX_ANGLE ) )

        # Update the mini driver
        self.miniDriver.setOutputs(
            self.leftMotorSpeed, self.rightMotorSpeed, self.panAngle, self.tiltAngle )
        self.miniDriver.update()

        # Send servo settings if needed
        if curTime - self.lastServoSettingsSendTime >= self.TIME_BETWEEN_SERVO_SETTING_UPDATES:

            self.miniDriver.setPanServoLimits(
                self.robotConfig.panPulseWidthMin,
                self.robotConfig.panPulseWidthMax )
            self.miniDriver.setTiltServoLimits(
                self.robotConfig.tiltPulseWidthMin,
                self.robotConfig.tiltPulseWidthMax )

            self.lastServoSettingsSendTime = curTime

        # Send sensor configuration if needed
        if curTime - self.lastSensorConfigurationSendTime >= self.TIME_BETWEEN_SENSOR_CONFIGURATION_UPDATES:

            self.miniDriver.setSensorConfiguration( self.robotConfig.miniDriverSensorConfiguration )

            self.lastSensorConfigurationSendTime = curTime

        # Change the Pi sensor module if needed
        if self.robotConfig.piSensorModuleName != self.piSensorModuleName:
            self._loadPiSensorModule()

        # Read from any sensors attached to the Pi
        if self.piSensorReader != None:

            self.piSensorDict = {}
            try:
                self.piSensorDict = self.piSensorReader.readSensors()
            except Exception as e:
                logging.error( "Caught exception when trying to read from Pi sensor reader" )
                logging.error( str( e ) )

        self.lastUpdateTime = curTime