"""
    Author: Jiajie Chen
    Date: Apr 24, 2016
"""

import numpy as np
from scipy.optimize import fmin_ncg

class logisticRegression(object):
    def __init__(self, theta=None, lambd=0.0,
                 cost=0.0, max_iter=100, tol=1e-5, solver='newton-cg',
                 verbose=False):
        self.theta = theta
        self.lambd = lambd
        self.cost = cost
        self.max_iter = max_iter
        self.tol = tol
        self.solver=solver
        self.verbose=verbose

    def fit(self, X, y):
        X_c = np.column_stack((np.ones(X.shape[0]),X))
        self.theta = np.zeros(X.shape[1]+1)
        if self.solver == 'newton-cg':
            self.theta = fmin_ncg(self.costFunction, self.theta,
                                  fprime=self.gradient, args=(X_c, y),
                                  maxiter=self.max_iter, avextol=self.tol,
                                  disp=self.verbose)
        else:
            pass
        self.cost = self.costFunction(self.theta, X_c, y)

    def get_prob(self, X):
        X_c = np.column_stack((np.ones(X.shape[0]),X))
        return self.sigmoid(X_c.dot(self.theta))

    def predict(self, X):
        return (self.get_prob(X)>0.5).astype(int)

    def accuracy(self, y_pred, y_true):
        if isinstance(y_pred, list): y_pred=np.array(y_pred)
        if isinstance(y_true, list): y_pred=np.array(y_true)
        return np.mean(y_pred == y_true)

    def sigmoid(self, z):
        """z can be a matrix, vector or scalar"""
        if isinstance(z, list): z=np.array(z)
        return 1/(1+np.exp(-z))

    def costFunction(self, theta, X_c, y):
        n_row = X_c.shape[0]
        J = (1.0/n_row)*(-np.log(self.sigmoid(X_c.dot(theta))).dot(y)
                         -np.log(1-self.sigmoid(X_c.dot(theta))).dot(1-y))\
             + ((1.0*self.lambd)/(2*n_row))*np.sum(theta[1:]**2)
        return J

    def gradient(self, theta, X_c, y):
        n_row, n_col = X_c.shape
        grad = np.empty(theta.shape)
        grad[0] = (1.0/n_row)*X_c[:,0].T.dot(self.sigmoid(X_c.dot(theta))-y)
        grad[1:] = (1.0/n_row)*X_c[:,1:].T.dot(self.sigmoid(X_c.dot(theta))-y)+(float(self.lambd)/n_row)*theta[1:]
        return grad
# end


from django.conf import settings
from django.conf.urls import url
from django.contrib.auth.views import LogoutView as logout, LoginView as login
from django.urls import path
from inc_mgmt import views as v

app_name = 'inc_mgmt'
urlpatterns = [
    url(r'^register/$', v.self_register, name='register'),
    url(r'^login/$', login.as_view(), {'next_page': settings.LOGIN_REDIRECT_URL}, name='login'),
    url(r'^logout/$', logout.as_view(), {'next_page': settings.LOGOUT_REDIRECT_URL}, name='logout'),
    url(r'^register/confirm_account/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', v.confirm_account, name='confirm_account'),
    url(r'^activate_account/list/$', v.activate_user_list, name='activate_user_list'),
    url('ajax/activate_account/', v.activate_user, name='activate_user'),
    path('', v.index, name='index'),
    path('<area_name>/ticket/list/', v.ticket_list, name='ticket_list'),
    path('<area_name>/ticket/list/<fast_status_filter>/', v.ticket_list, name='ticket_list'),
    path('<area_name>/ticket/new/', v.ticket_new, name='ticket_new'),
    path('<area_name>/ticket/<ticket_id>/detail/', v.ticket_detail, name='ticket_detail'),
    path('<area_name>/ticket/<ticket_id>/change/', v.ticket_change, name='ticket_change'),
    path('ajax/update_ticket/', v.ticket_update, name='ticket_update'),
]


import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
fig = plt.figure()
ax = plt.axes(projection='3d')
z = np.linspace(0,1,100)
x = z*np.sin(z)
y = z*np.cos(z)
ax.plot3D(x,y,z,'g')
plt.show()


import sys
import time
from serial import Serial
from serial.tools import list_ports

from .config_handler import ConfigHandler

class UtilityHandler:

    arduino = None

    def write(message):
        UtilityHandler.arduino.write(message.encode())

    def init():
        print("""
        > Simulador ADS-B
        >> Autor: Caio Rondon Botelho de Carvalho
        >> Versao: 1.0v
        """)

        #
        # LISTA DIPOSITIVOS
        #

        # capturando dispositivos
        devices = list(list_ports.comports())
        # termina programa se nao encontra dispositivo para comunicacao
        if not devices:
            print("Nenhum dispositivo encontrado! Favor verificar.")
            sys.exit(0)

        print("Listando dispositivos conectados:\n[Numero] - 'Descricao'")
        for i, device in enumerate(devices):
            print ("["+ str(i) + "] - '" + str(device) + "'")

        #
        # ESCOLHER DISPOSITIVOS
        #
        opc = input("\nEscolha o numero que representa o Arduino. Qualquer letra para sair.\n> ")

        try:
            d = int(opc)
            # captura dispositivo escolhido
            arduino_info = devices[d]
            UtilityHandler.arduino = Serial(arduino_info.device, ConfigHandler.baudrate)
            time.sleep(2) # tempo para conexao ser estabelecida
            print("Conectado!")
        except ValueError:
            sys.exit(0)
        except Exception as e:
            print(str(e))
            print("Nao foi possivel se conectar ao dispositivo selecionado")
            sys.exit(1)

        return


from typing import Dict

import requests
from requests import Response

BASE_URL = 'https://aw3.automationintesting.online'
MESSAGE_ENDPOINT = f'{BASE_URL}/message'

def create_message(payload: Dict) -> Response:
    response = requests.post(MESSAGE_ENDPOINT, json=payload)
    if not response.ok:
        raise ConnectionError(f'Unable to create message: {response.content}')
    return response


'''
Mob class.
Classes Turret and Mob inherits from class Entity
'''

# ------ Importations ------

import pygame
import math
from isometric import IsoSprite, isoutils
import constants as cst
from . import misc,entity

# ------ Mob Class ------

class Mob(entity.Entity):
    ''' Classe de base des monstres traversant le niveau '''

    def __init__(self, path_to_image, tile_pos=None):
        entity.Entity.__init__(self, path_to_image, tile_pos)
        self.spritesheet = self.image
        self.anim_key = 0  # 0, 1 or 2 (x on spritesheet)
        self.state = 0  # 0 front, 1 left, 2 right, 3 back (y on spritesheet)
        self.anim_speed = 5  # sprite anims every anim_speed frames
        self.anim_counter = 0  # increments every frame
        self.size = 32  # pixels

        # v force rect to be of size self.size, not spritesheet's size !
        new_iso_rect = pygame.Rect((0, 0), (self.size, self.size))
        new_iso_rect.center = self.iso_pos
        self.set_iso_rect(new_iso_rect)
        new_rect = pygame.Rect((0, 0), isoutils.iso_to_cart(self.size, self.size))
        new_rect.center = self.pos
        self.set_rect(new_rect)
        # ^
        self.image = None
        self.update_image()

        # game settings
        self.speed = 3  # chasing speed
        self.is_flying = False
        self.hp = 0

    ## ------ Graphical functions ------

    def update_image(self):
        mask_rect = pygame.Rect(self.anim_key*self.size, self.state*self.size, self.size, self.size)
        self.image = self.spritesheet.subsurface(mask_rect)

    def update(self):
        super().update()
        # update the animation
        self.anim_counter += 1
        if self.anim_counter == self.anim_speed:
            self.anim_counter = 0
            self.anim_key = (self.anim_key + 1) % 3
            self.update_image()

    def display(self, screen):
        '''
        display(self, screen) :
            displays the Sprite onto the screen.
        '''
        super().display(screen)
        if cst.DEBUG:
            pygame.draw.rect(screen, pygame.Color("blue"), self.rect, 2)
            pygame.draw.rect(screen, pygame.Color("red"), self.iso_rect, 2)

    ## ------ Behavior and AI functions ------

    def find_path(self, obstacles, target):
        '''
        find_path(self,obstacles) -> path list
            implementation of the A* algorithm. The heuristic used is the euclidean distance.
            return a list of tiles to walk on in order to get to the target avoiding obstacles. The path is the shortest possible path
            if no path is available, returns None.

            obstacles = dict where dict[(i,j)] is True if and only if there is an obstacle on case (i,j)
            target = the coordinate tupple of the case to reach
        '''

        # Data structures
        get_default_dict = lambda default_value: dict(((i, j), default_value) for i in range(cst.MAP_WIDTH) for j in range(cst.MAP_WIDTH))
        passage = get_default_dict(None)
        distance = get_default_dict(float('inf'))
        seen = get_default_dict(False)
        pq = PriorityQueue()

        # Initialisation
        seen[self.case] = True
        distance[self.case] = 0
        pq.put((0,self.case))

        # Processing
        try :
            while not seen[target] :
                prio, case = pq.get()
                if not seen[case] :
                    for vois in get_neightbors(case,obstacles):
                        new_distance = distance[case] + heuristic(target, vois)
                        if not seen[vois] and new_distance < distance[vois]:
                            pq.put((new_distance, vois))
                            distance[vois] = new_distance
                            passage[vois] = case
                seen[case] = True
        except Empty:
            return None
        else:
            # Post-Processing. Extracting path from datas
            shortest_path = []
            pos = target
            while pos != self.case :
                shortest_path.append(pos)
                pos = passage[pos]
            shortest_path.reverse()  # shortest_path was (goal -> init) and we want (init -> goal)
            return shortest_path


from django import forms

class UserBookForm(forms.Form):
    CHOICES = [
        ('te', 'Temporary Exchange'),
        ('pe', 'Permanent Exchange'),
        ('rt', 'Rental'),
        ('sl', 'Sale')
    ]
    health = forms.DecimalField(label='',
        required = True,
        widget=forms.TextInput(
            attrs={'placeholder':'Health'}
        )
    )

    moe = forms.ChoiceField(required=True,
        choices = CHOICES,
        label = ''
    )

    ebook = forms.FileField(
        label = 'Ebook',
        required = False
    )

    def clean_health(self):
        health = self.cleaned_data.get('health')
        if int(health) >= 0 and int(health) <= 5:
            return health
        raise forms.ValidationError('Health Not In Range')


import os
import zipfile

SOURCE_ZIP_NAME = 'source_code.zip'

def zip_dir(directory: str, zip_file: str):
    with zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED) as zipf:
        for root, dirs, files in os.walk(directory):
            for file in files:
                zipf.write(os.path.join(root, file))

def zip_source():
    if os.path.exists(SOURCE_ZIP_NAME):
        os.remove(SOURCE_ZIP_NAME)
    zip_dir('src', SOURCE_ZIP_NAME)
    print(f'Zip file created: {SOURCE_ZIP_NAME}')

'''
Remember to change the Working Directory in run configuration to Google_Hashcode_2022!
'''
if __name__ == '__main__':
    zip_source()


from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.core.exceptions import ObjectDoesNotExist

from django_extensions.db.fields import CreationDateTimeField, ModificationDateTimeField

class DjangoManager(models.Manager):
    def versions(self):
        return [("django_%s" % (x.version), "Django %s" % (x.version)) for x in self.model.objects.all().order_by("version")]

    def add_object_compatibility(self, object, version):
        try:
            django_object = self.model.objects.get(version = version)
        except ObjectDoesNotExist:
            django_object = None

        content_type_object = ContentType.objects.get_for_model(object.__class__)
        try:
            comp = DjangoCompatibility.objects.get(content_type = content_type_object,
                                                   object_id = object.id,
                                                   django = django_object)
        except ObjectDoesNotExist:
            comp = DjangoCompatibility(content_type = content_type_object, object_id = object.id, django = django_object)
            comp.save()
        return comp

    def versions_for_object(self, object):
        content_type_object = ContentType.objects.get_for_model(object.__class__)
        return ["django_%s" % (x.django.version) for x in DjangoCompatibility.objects.filter(content_type = content_type_object, object_id = object.id)]

class PythonManager(models.Manager):
    def versions(self):
        return [("python_%s" % (x.version), "Python %s" % (x.version)) for x in self.model.objects.all().order_by("version")]

    def add_object_compatibility(self, object, version):
        try:
            python_object = self.model.objects.get(version = version)
        except ObjectDoesNotExist:
            python_object = None

        content_type_object = ContentType.objects.get_for_model(object.__class__)
        try:
            comp = PythonCompatibility.objects.get(content_type = content_type_object,
                                                   object_id = object.id,
                                                   python = python_object)
        except ObjectDoesNotExist:
            comp = PythonCompatibility(content_type = content_type_object, object_id = object.id, python = python_object)
            comp.save()
        return comp

    def versions_for_object(self, object):
        content_type_object = ContentType.objects.get_for_model(object.__class__)
        return ["python_%s" % (x.python.version) for x in PythonCompatibility.objects.filter(content_type = content_type_object, object_id = object.id)]

class SourceManager(models.Manager):
    def parse_source_data(self, data):
        import re
        final_sources = []
        sources = [x for x in data.split(",") if x.strip()]
        for source in sources:
            uri = source
            final_sources.append(('http', uri))
        return final_sources

    def add_sources(self, object, sources):
        final_sources = []
        for source in sources:
            source_object = self.model.objects.add_source(object, source[0], source[1])
            final_sources.append(source_object)
        return final_sources

    def add_source(self, object, protocol, uri):
        content_type_object = ContentType.objects.get_for_model(object.__class__)
        object_id = object.id
        mode = SourceMode.objects.get(name = protocol)
        source = self.model(active = True,
                            content_type = content_type_object,
                            object_id = object_id,
                            mode = mode,
                            uri = uri)
        source.save()
        return source

class SourceMode(models.Model):
    name = models.CharField(max_length = 75, unique = True)

    def __unicode__(self):
        return self.name

class Source(models.Model):
    active = models.BooleanField(default = True)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey()
    mode = models.ForeignKey(SourceMode)
    uri = models.TextField()

    date_created = CreationDateTimeField()
    date_modified = ModificationDateTimeField()

    objects = SourceManager()

    def __unicode__(self):
        return "%s::%s" % (self.mode.name, self.uri)

class PythonPackage(models.Model):
    name = models.CharField(max_length = 75)
    version = models.TextField()

class PythonPackageDependency(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    base_object = generic.GenericForeignKey()

    depends_on = models.ForeignKey(PythonPackage)

class Django(models.Model):
    version = models.CharField(max_length = 75, unique = True)

    objects = DjangoManager()

    def __unicode__(self):
        return "Django %s" % (self.version)

class Python(models.Model):
    version = models.CharField(max_length = 75, unique = True)

    objects = PythonManager()

    def __unicode__(self):
        return "Python %s" % (self.version)

class DjangoCompatibility(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    base_object = generic.GenericForeignKey()

    django = models.ForeignKey(Django)

    def name(self):
        return self.django.__unicode__()

class PythonCompatibility(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    base_object = generic.GenericForeignKey()

    python = models.ForeignKey(Python)

    def name(self):
        return self.python.__unicode__()


#!/usr/bin/env python

def str2bool(v):
    import argparse
    if isinstance(v, bool):
        return v
    if v.lower() in ('yes', 'true', 't', 'y', '1'):
        return True
    elif v.lower() in ('no', 'false', 'f', 'n', '0'):
        return False
    else:
        raise argparse.ArgumentTypeError('Boolean value expected.')

def parse_args():
    import argparse

    p = argparse.ArgumentParser(description="Copy files")
    p.add_argument(
        'path', type=str, help='source file path')
    p.add_argument(
        'type', type=str, help='file type to copy')
    p.add_argument(
        'target', type=str, help='path to copy files to')
    p.add_argument(
        'max_size', type=int, help='size in MB to copy')
    p.add_argument(
        'max_files_per_folder', type=int,
        help='max files for per folder for target 0=unlimited')
    p.add_argument(
        '--clear-cache', type=str2bool,
        nargs='?', const=True, default=False,
        help='clear the cache')

    return p.parse_args()

def get_files(file_path, file_type):

    # TODO fix shitty portability
    cf = file_path.replace('/', '_') + '_' + file_type
    cache_file = f'cache/{cf}.pickle'
    files = read_cache(cache_file)

    if files:
        return files

    from pathlib import Path
    file_list = []
    count = 0
    for path in Path(file_path).rglob(f'*.{file_type}'):
        count += 1
        file_list.append((path, path.stat().st_size))
        if count % 100 == 0:
            print(f'Found {count} files')

    # Save cache
    # cache based on source folder
    with open(cache_file, 'wb') as f:
        import pickle
        pickle.dump(file_list, f)
    return file_list

def get_copy_files(files, max_size):
    import random
    print("Randomising...")
    random.shuffle(files)
    print("Randomised.")
    current_size = 0
    file_list = []
    for file in files:
        # Use base 10 for MB
        if current_size + file[1] > max_size*1000*1000:
            break
        file_list.append(file[0])
        current_size += file[1]
    return file_list

def copy_files(files, target_folder, max_files_per_folder):
    import shutil
    import pathlib
    fno = 0
    fc = 0
    for file in files:
        if max_files_per_folder == 0:
            tf = target_folder
        else:
            tf = target_folder + f'/{fno:08d}'
            if fc == 0:
                pathlib.Path(tf).mkdir(parents=True, exist_ok=True)
            tf = tf + f'/{fc:02d}.mp3'
        print(f"copying {file} to {tf}")
        try:
            shutil.copy(str(file), tf)
            fc += 1
            if fc >= max_files_per_folder:
                fno += 1
                fc = 0
        except Exception:
            print(f"ERROR: Failed to copy {file}")

def read_cache(cache_file):
    import pickle

    try:
        with open(cache_file, 'rb') as f:
            cache = pickle.load(f)
    except FileNotFoundError:
        print("Not found")
        cache = None
    return cache

args = parse_args()
if args.clear_cache:
    import pathlib
    # TODO improve shitty portability
    cache_file = args.path.replace('/', '_') + '_' + args.type
    f = pathlib.Path(f'cache/{cache_file}.pickle')
    if f.is_file():
        f.unlink()

file_list = get_files(args.path, args.type)
files = get_copy_files(file_list, args.max_size)

copy_files(files, args.target, args.max_files_per_folder)


import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
import matplotlib.patches as patches
import cv2
# write your script here, we recommend the above libraries for making your animation
from LucasKanadeBasis import LucasKanadeBasis
from LucasKanade import LucasKanade

# write your script here, we recommend the above libraries for making your animation
frames = np.load('../data/sylvseq.npy')
bases = np.load('../data/sylvbases.npy')

H, W, T = frames.shape
sylvseqrects = np.zeros((T, 4))

rect1 = np.array([101, 61, 155, 107]).astype('float').T
rect2 = np.array([101, 61, 155, 107]).astype('float').T

fig=plt.figure(figsize=(4, 1))
columns = 5
rows = 1
index = 1

for i in range(1, T):

	p1 = LucasKanadeBasis(frames[:, :, i-1], frames[:, :, i], rect1, bases)
	p2 = LucasKanade(frames[:, :, i-1], frames[:, :, i], rect2)
	rect1 += np.array([p1[1], p1[0], p1[1], p1[0]]).T

	sylvseqrects[i, :] = rect1
	rect2 += np.array([p2[1], p2[0], p2[1], p2[0]]).T

	print('frame: ', i)

	frame = frames[:, :, i].copy()
	cv2.rectangle(frame, (int(rect1[0]),int(rect1[1])), (int(rect1[2]),int(rect1[3])),(255), 1)
	cv2.rectangle(frame, (int(rect2[0]),int(rect2[1])), (int(rect2[2]),int(rect2[3])),(0), 1)

	cv2.imshow('input', frame)

	if i in [1, 200, 300, 350, 400]:

		rect_patch = patches.Rectangle((rect1[0],rect1[1]),
										rect1[2]-rect1[0],
										rect1[3]-rect1[1],
										linewidth=1,edgecolor='y',facecolor='none')

		rect_lk_patch = patches.Rectangle((rect2[0],rect2[1]),
										rect2[2]-rect2[0],
										rect2[3]-rect2[1],
										linewidth=1,edgecolor='g',facecolor='none')

		ax = fig.add_subplot(rows, columns, index)
		ax.add_patch(rect_patch)
		ax.add_patch(rect_lk_patch)

		ax.imshow(frames[:, :, i], cmap='gray')
		ax.get_yaxis().set_visible(False)
		ax.get_xaxis().set_visible(False)
		index+=1

	if cv2.waitKey(10) == ord('q'):
		break
np.save('sylvseqrects.npy', sylvseqrects)
cv2.destroyAllWindows()
plt.show()


import pygame
from .constants import BLACK, WHITE, BLUE, SQUARE_SIZE, ROWS, COLS, RED
from othello.board import Board
from .piece import Piece

LEFT = (0, -1)
TOP_LEFT = (-1, -1)
TOP = (-1, 0)
TOP_RIGHT = (-1, 1)
RIGHT = (0, 1)
BOTTOM_RIGHT = (1, 1)
BOTTOM = (1, 0)
BOTOTM_LEFT = (1, -1)

DIRECTIONS = (TOP_LEFT   , TOP   ,    TOP_RIGHT,
              LEFT       ,                RIGHT,
              BOTOTM_LEFT, BOTTOM, BOTTOM_RIGHT)

class Game:
    def __init__(self, win):
        self._init()
        self.win = win

    def update(self):
        self.board.draw(self.win)
        self.draw_valid_moves(self.valid_moves)
        # self.draw_opponent_neighbors(self.opponent_neighbors)
        pygame.display.update()

    def _init(self):
        self.selected = None
        self.board = Board()
        self.turn = BLACK
        self.black_count = 2
        self.white_count = 2
        self.valid_moves = set()
        self.opponent_neighbors = set()

    def reset(self):
        self._init()

    def step(self, row, col):
        initial_blacks = len(self.board.black_pieces_coordinates)
        initial_whites = len(self.board.white_pieces_coordinates)

        self._spawn_piece(row, col)

        next_state = self.board.board
        reward = self.white_count - initial_whites
        done = True

        return next_state, reward, done

    def _spawn_piece(self, row, col):

        if (row, col) in self.valid_moves:
            self.board.spawn_piece(row, col, self.turn)
            self.flip_pieces(row, col)
            # print('BLACK: ', self.black_count, ' | WHITE: ', self.white_count)
            print('BLACK: ', len(self.board.black_pieces_coordinates), ' | WHITE: ', len(self.board.white_pieces_coordinates))
            self.change_turn()
        else:
            print('Not a valid move!')

# PROBLEMA ME TO FLIP PIECES

    def flip_pieces(self, row, col):
        flipping_directions = set()
        piece = self.board.board[row][col]

        # this loop starts from the spawned piece position and extends to all directions while it finds oppponent pieces
        # if it a finds the current player's piece along this path, all oppponent piece in this path should be flip,
        # so the direction is stored

        for direction in DIRECTIONS:
            neighbor_position = tuple(x + y for x, y in zip((row, col), direction))
            if(neighbor_position[0] >= 0 and neighbor_position[1] >= 0 and
               neighbor_position[0] < ROWS and neighbor_position[1] < ROWS):
                next_piece = self.board.get_piece(neighbor_position[0], neighbor_position[1])

                while(next_piece == self.get_opponent()):
                    next_piece_coordinates = tuple(x + y for x, y in zip(next_piece.get_position(), direction))
                    if(next_piece_coordinates[0] < ROWS and next_piece_coordinates[1] < ROWS and
                       next_piece_coordinates[0] >= 0 and next_piece_coordinates[1] >= 0):
                           next_piece = self.board.get_piece(next_piece_coordinates[0], next_piece_coordinates[1])
                    else:
                        break

                    if next_piece == self.turn:
                       flipping_directions.add(direction)

        # we iterate once again from the spawned piece position, only to the flipping direction,
        # we flip all enemy piece along this path

        for direction in flipping_directions:
            neighbor_position = tuple(x + y for x, y in zip((row, col), direction))
            if(neighbor_position[0] >= 0 and neighbor_position[1] >= 0 and
               neighbor_position[0] < ROWS and neighbor_position[1] < ROWS):
                next_piece = self.board.get_piece(neighbor_position[0], neighbor_position[1])
                next_piece_coordinates = neighbor_position
                print(next_piece_coordinates)

                while( next_piece == self.get_opponent() ):
                    self.board.get_player_pieces(self.turn).add(next_piece.get_position())
                    # self.change_score()
                    self.board.get_opponent_pieces(self.turn).remove(next_piece.get_position())
                    self.board.board[next_piece.get_position()[0]][next_piece.get_position()[1]] = Piece(next_piece_coordinates[0], next_piece_coordinates[1], self.turn)

                    # added numbers board
                    pos  = next_piece.get_position()

                    if self.turn == WHITE:
                        self.board.board_QTable[pos[0]][pos[1]] = 1
                    elif self.turn == BLACK:
                        self.board.board_QTable[pos[0]][pos[1]] = -1

                    # end of initial numbes board addition

                    next_piece_coordinates = tuple(x + y for x, y in zip((next_piece_coordinates[0], next_piece_coordinates[1]), direction))
                    next_piece = self.board.get_piece(next_piece_coordinates[0], next_piece_coordinates[1])

    def change_turn(self):

        if self.turn == BLACK:
            self.turn = WHITE
        else:
            self.turn = BLACK

        self.valid_moves=self.get_valid_moves()

        if(len(self.valid_moves)) == 0:
            if( len(self.board.black_pieces_coordinates) +  len(self.board.white_pieces_coordinates) == 64):
              print('The game ended!')
              print('FINAL SCORE: ', 'BLACK: ', len(self.board.black_pieces_coordinates), ' | WHITE: ', len(self.board.white_pieces_coordinates))
              if(len(self.board.black_pieces_coordinates) > len(self.board.white_pieces_coordinates)):
                print('BLACK HAS WON')
              elif(len(self.board.white_pieces_coordinates) > len(self.board.black_pieces_coordinates)):
                print('WHITE HAS WON')
              elif(len(self.board.white_pieces_coordinates) == len(self.board.black_pieces_coordinates)):
                print('IT IS A TIE')
              else:
                print('Error calculating score')

            else:
                self.change_turn()
                print('----||||||----')
                print('~~~~~~~~~~~~~~')
                print('NO VALID MOVES')
                print('IT IS ', self.turn, '`s turn again!')
                print('~~~~~~~~~~~~~~')
                print('----||||||----')

    def get_valid_moves(self):
        opponent_adjuscent_cells = set()
        moves = set()

        for piece in self.board.get_opponent_pieces(self.turn):
            for direction in DIRECTIONS:
                neighbor=self.get_opponents_neighbors(piece, direction, opponent_adjuscent_cells)
                if(neighbor != None):
                    opponent_adjuscent_cells.add(neighbor)

        #mexri edw doylevei kala pernw ola ta adjuscent cells tou antipalou
        self.opponent_neighbors = opponent_adjuscent_cells

        for opponent_adjuscent_cell in opponent_adjuscent_cells:
            for direction in DIRECTIONS:
                possible_move = tuple(x + y for x, y in zip(opponent_adjuscent_cell, direction))
                if (possible_move[0] < ROWS and possible_move[1] < ROWS and
                    possible_move[0] >= 0 and possible_move[1] >= 0):

                    next_piece = self.board.get_piece(possible_move[0], possible_move[1])

                    while(next_piece == self.get_opponent()):
                         next_piece_coordinates = tuple(x + y for x, y in zip(next_piece.get_position(), direction))
                         if(next_piece_coordinates[0] < ROWS and next_piece_coordinates[1] < ROWS and
                            next_piece_coordinates[0] >= 0 and next_piece_coordinates[1] >= 0):
                                next_piece = self.board.get_piece(next_piece_coordinates[0], next_piece_coordinates[1])
                         else:
                             break

                         if next_piece == self.turn:
                            moves.add(opponent_adjuscent_cell)

        return moves

    def get_opponents_neighbors(self, piece, direction, moves):
        neighbor = tuple(x + y for x, y in zip(piece, direction))

        if neighbor not in moves:
            if(neighbor[0] >= 0 and neighbor[1] >= 0 and neighbor[0] < ROWS and neighbor[1] < ROWS):
                if(self.board.get_piece(neighbor[0], neighbor[1]) != None):
                    if self.board.get_piece(neighbor[0], neighbor[1]) == 0:
                        return neighbor

    def get_opponent(self):
        if self.turn == BLACK:
            return WHITE
        elif self.turn == WHITE :
            return BLACK

    def change_score(self):
        if self.turn == BLACK:
            self.black_count += 1
            self.white_count -= 1
        elif self.turn == WHITE:
            self.white_count += 1
            self.black_count -= 1

    def get_piece_count(self):
        if self.turn == BLACK:
            return self.black_count
        elif self.turn == WHITE:
            return self.white_count

    def next_piece_in_direction(self, current_tile, direction):
        next_piece = tuple(x + y for x, y in zip(current_tile, direction))

        if(next_piece[0] > ROWS - 1 or next_piece[1] > ROWS - 1 or
           next_piece[0] < 0 or next_piece[1] < 0):
            return False

        if(self.board.get_piece(next_piece[0], next_piece[1]) == self.get_opponent()):
            self.next_piece_in_direction(next_piece, direction)
        elif(self.board.get_piece(next_piece[0], next_piece[1]) == self.turn):
            return True
        else:
            return False

    def draw_valid_moves(self, moves):
        for move in moves:
            row, col = move
            pygame.draw.circle(self.win, BLUE, (col * SQUARE_SIZE + SQUARE_SIZE//2, row * SQUARE_SIZE + SQUARE_SIZE//2), 15)

    def draw_opponent_neighbors(self, opponent_neighbors):
        for move in opponent_neighbors:
            row, col = move
            pygame.draw.circle(self.win, RED, (col * SQUARE_SIZE + SQUARE_SIZE//2, row * SQUARE_SIZE + SQUARE_SIZE//2), 10)


import os
import argparse
from langchain.llms import OpenAI
from langchain import PromptTemplate
from langchain.chains import LLMChain, SequentialChain
import warnings
from datasets import load_dataset
from evaluate import load
import numpy as np
from wasabi import color
import pyutils.io as io
import tqdm.auto as tqdm

def create_math_qa_chain(llm):
    initial_solution_prompt_template = """
    You will be given a math problem with multiple-choice answers. Reason through the problem step-by-step, and finally respond with the letter corresponding to the right answer choice.
    Question:
    {text}
    Options:
    {options}
    """
    initial_solution_prompt = PromptTemplate(
        input_variables=["text", "options"],
        template=initial_solution_prompt_template,
    )
    initial_solution_chain = LLMChain(llm=llm, prompt=initial_solution_prompt, output_key="initial_solution")

    feedback_prompt_template = """
    You will be given a math problem with multiple-choice answers, and a proposed answer and explanation from a student. If answer is already correct, just ouput \"CORRECT\".
    Instruction:
    {text}
    Options:
    {options}
    Student's answer:
    {initial_solution}
    """
    ilf_feedback_prompt = PromptTemplate(
        input_variables=["text", "options", "initial_solution"],
        template=feedback_prompt_template
    )
    feedback_chain = LLMChain(llm=llm, prompt=ilf_feedback_prompt, output_key="feedback")

    refinement_prompt_template = """
    You will be given a math problem with multiple-choice answers, and a proposed answer and explanation from a student. You will also be provided feedback a teacher provided on that initial solution. Based on the feedback, reason through the problem step-by-step, and finally respond with the letter corresponding to the right answer choice.
    Instruction:
    {text}
    Options:
    {options}
    Student's answer:
    {initial_solution}
    Teacher's feedback:
    {feedback}
    """
    ilf_refinement_prompt = PromptTemplate(
        input_variables=["text", "options", "initial_solution", "feedback"],
        template=refinement_prompt_template
    )
    refinement_chain = LLMChain(llm=llm, prompt=ilf_refinement_prompt, output_key="refinement")

    ilf_chain = SequentialChain(
        chains=[initial_solution_chain, feedback_chain, refinement_chain],
        input_variables=["text", "options"],
        output_variables=["initial_solution", "feedback", "refinement"],
    )
    return ilf_chain

def create_mbpp_chain(llm):
    initial_solution_prompt_template = """
    You will be given a Python programming task and one unit test. Write a function that satisfies the specification in task description and passes the unit test. Imporant: Do not include the test case in your solution!
    Instruction:
    {text}
    Unit test:
    {test_list[0]}
    """
    initial_solution_prompt = PromptTemplate(
        input_variables=["text", "test_list"],
        template=initial_solution_prompt_template,
    )
    initial_solution_chain = LLMChain(llm=llm, prompt=initial_solution_prompt, output_key="initial_solution")

    feedback_prompt_template = """
    You will be given a Python programming task, one unit test and a candidate solution. Your job is to provide short feedback on how to improve the candidate solution such that it satisfies the specification in task description and passes the unit test. Be as concise as possible! Do not provide the corrected solution, limit yourself to short feedback in natural language. Focus on correctness, not on following Python style guide or good variable naming. Don't require docstring or test cases. If the solution is already okay, just ouput \"OK\".
    Instruction:
    {text}
    Unit test:
    {test_list[0]}
    Code:
    {initial_solution}
    """
    ilf_feedback_prompt = PromptTemplate(
        input_variables=["text", "test_list", "initial_solution"],
        template=feedback_prompt_template
    )
    feedback_chain = LLMChain(llm=llm, prompt=ilf_feedback_prompt, output_key="feedback")

    refinement_prompt_template = """
    You will be given a Python programming task, one unit test, an initial solution and feedback an expert provided on that initial solution. Your job is to rewrite the initial solution based on the feedback.
    Instruction:
    {text}
    Unit test:
    {test_list[0]}
    Initial solution:
    {initial_solution}
    Feedback:
    {feedback}
    """
    ilf_refinement_prompt = PromptTemplate(
        input_variables=["text", "test_list", "initial_solution", "feedback"],
        template=refinement_prompt_template
    )
    refinement_chain = LLMChain(llm=llm, prompt=ilf_refinement_prompt, output_key="refinement")

    ilf_chain = SequentialChain(
        chains=[initial_solution_chain, feedback_chain, refinement_chain],
        input_variables=["text", "test_list"],
        output_variables=["initial_solution", "feedback", "refinement"],
    )
    return ilf_chain

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--model_name",)
    parser.add_argument("--dataset", choices=["math_qa", "mbpp"])
    parser.add_argument("--output_path")
    parser.add_argument("--phase", choices=["train", "validation"], default="train")
    parser.add_argument("--num_examples", type=int, default=100)
    args = parser.parse_args()
    llm = OpenAI(model_name=args.model_name)
    if args.dataset == "math_qa":
        ilf_chain = create_math_qa_chain(llm)
    elif args.dataset == "mbpp":
        ilf_chain = create_mbpp_chain(llm)
    else:
        raise KeyError(args.dataset)
    os.makedirs(os.path.split(args.output_path)[0], exist_ok=True)
    ds = load_dataset(args.dataset, split=args.phase)
    outputs_list = []
    for i in tqdm.trange(args.num_examples):
        inputs = ds[i]
        if args.dataset == "math_qa":
            outputs = ilf_chain({"text": inputs["Problem"], "options": inputs["options"]})
        elif args.dataset == "mbpp":
            outputs = ilf_chain(inputs)
        else:
            raise KeyError(args.dataset)
        outputs_list.append(outputs)
    io.write_jsonl(outputs_list, args.output_path)

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
"""Config for the Trunk.
"""

__authors__ = "emenager, tnavez"
__contact__ = "etienne.menager@inria.fr, tanguy.navez@inria.fr"
__version__ = "1.0.0"
__copyright__ = "(c) 2020, Inria"
__date__ = "Jun 29 2022"

import sys
import pathlib
sys.path.insert(0, str(pathlib.Path(__file__).parent.absolute())+"/../")
sys.path.insert(0, str(pathlib.Path(__file__).parent.absolute()))

from Libraries.BaseConfig import BaseConfig

import Mesh.Constants as Const

class Config(BaseConfig):
    def __init__(self):
        super(Config,self).__init__("ContactFinger")
        self.scene_name = "3ContactFinger"
        self.nb_robot = 3
        self.set_scene_config({"source": [-400.0, -50, 100],
                               "target": [30, -25, 100],
                               "goalPos": [0., 35.0, -95.0, 0.0, 0.0, 0.0],
                               "contact_radius": 2,
                               "nb_contact_points": 3
})

    def get_actuators_variables(self):
        return {"cable1": [0, 0, 20],
                "cable2": [0, 0, 20]}

    def get_contacts_variables(self):
        x_comp = 30
        y_comp = 10
        z_comp = 20
        return {"contactP1_x": [x_comp, -40, 40],
                "contactP1_y": [y_comp, -20, 40],
                "contactP1_z": [z_comp, -2, 30],
                "contactP2_x": [x_comp, -40, 40],
                "contactP2_y": [y_comp, -20, 40],
                "contactP2_z": [z_comp, -2, 30],
                "contactP3_x": [x_comp, -40, 40],
                "contactP3_y": [y_comp, -20, 40],
                "contactP3_z": [z_comp, -2, 30]}

    def get_n_dt(self):
        return 5

    def get_n_eq_dt(self):
        return 1

    def get_trajectory(self):
        import numpy as np
        goals = []
        circle_center= np.array([0., 35.0, -95.0, 0, 0, 0])
        goals.append(circle_center)

        circle_radius = 1
        # circle_radius = 1.5
        n_samples = 20
        for i in range(n_samples):
            goals.append(circle_center + np.array([circle_radius * np.cos(2 * np.pi * i / n_samples), circle_radius * np.sin(2 * np.pi * i / n_samples),
                 0, 0, 0, 0]))
        return goals


import time

from elasticsearch_dsl import connections
from protobuf_to_dict import dict_to_protobuf
from protobufs.services.post import containers_pb2 as post_containers
from protobufs.services.profile import containers_pb2 as profile_containers
from protobufs.services.search.containers import entity_pb2
from protobufs.services.search.containers import search_pb2
from protobufs.services.team import containers_pb2 as team_containers
from ..stores.es import types
import service.control
import yaml

from services.test import mocks

from .base import ESTestCase

_fixtures = None
_executed = False

class Test(ESTestCase):

    def setUp(self):
        super(Test, self).setUp()
        organization_id = _fixtures['profiles'][0]['organization_id']
        self.organization = mocks.mock_organization(id=organization_id)
        self.profile = mocks.mock_profile(organization_id=self.organization.id)
        token = mocks.mock_token(profile_id=self.profile.id, organization_id=self.organization.id)
        self.client = service.control.Client('search', token=token)
        self.mock.instance.dont_mock_service('search')
        global _executed
        if not _executed:
            self._setup_fixtures(_fixtures)
            _executed = True

    @classmethod
    def setUpClass(cls):
        super(Test, cls).setUpClass()
        with open('search/fixtures/acme.yml') as read_file:
            global _fixtures
            _fixtures = yaml.load(read_file)

    def _update_entities(self, entity_type, containers):
        self.client.call_action(
            'update_entities',
            type=entity_type,
            ids=[c.id for c in containers],
        )
        # give the documents time to index
        time.sleep(1)

    def _setup_profile_fixtures(self, profile_fixtures):
        if not profile_fixtures:
            return

        containers = [dict_to_protobuf(f, profile_containers.ProfileV1) for f in profile_fixtures]
        self.mock.instance.register_mock_object(
            service='profile',
            action='get_profiles',
            return_object=containers,
            return_object_path='profiles',
            mock_regex_lookup='profile:get_profiles:.*',
        )
        self._update_entities(entity_pb2.PROFILE, containers)

    def _setup_team_fixtures(self, team_fixtures):
        if not team_fixtures:
            return

        containers = [dict_to_protobuf(f, team_containers.TeamV1) for f in team_fixtures]
        self.mock.instance.register_mock_object(
            service='team',
            action='get_teams',
            return_object=containers,
            return_object_path='teams',
            mock_regex_lookup='team:get_teams:.*',
        )
        self._update_entities(entity_pb2.TEAM, containers)

    def _setup_post_fixtures(self, post_fixtures):
        if not post_fixtures:
            return

        containers = [dict_to_protobuf(f, post_containers.PostV1) for f in post_fixtures]
        self.mock.instance.register_mock_object(
            service='post',
            action='get_posts',
            return_object=containers,
            return_object_path='posts',
            mock_regex_lookup='post:get_posts:.*',
        )
        self._update_entities(entity_pb2.POST, containers)

    def _setup_fixtures(self, fixtures):
        es = connections.connections.get_connection()
        es.indices.delete('*')
        self.client.call_action('create_index')
        self._setup_profile_fixtures(fixtures.get('profiles', []))
        self._setup_team_fixtures(fixtures.get('teams', []))
        self._setup_post_fixtures(fixtures.get('posts', []))

    def verify_top_results(
            self,
            result_object_type,
            fields,
            results,
            top_results=3,
            query=None,
            should_be_present=True,
        ):
        present = False
        for result in results[:top_results]:
            result_object = getattr(result, result_object_type)
            all_match = False
            for field, expected_value in fields.iteritems():
                value = getattr(result_object, field)
                if callable(expected_value) and expected_value(value):
                    all_match = True
                elif value == expected_value:
                    all_match = True
            if all_match:
                present = True
                break

        if should_be_present:
            message = 'Expected a match in the top %s results for: %s%s' % (
                top_results,
                fields,
                ' (query: %s)' % (query,) if query else '',
            )
            self.assertTrue(present, message)
        else:
            message = 'Didn\'t expect a match in the top %s results for: %s%s' % (
                top_results,
                fields,
                ' (query: %s)' % (query,) if query else '',
            )
            self.assertFalse(present, message)

    def test_search_query_required(self):
        with self.assertFieldError('query', 'MISSING'):
            self.client.call_action('search_v2')

    #def test_search_profile_email(self):
        #response = self.client.call_action('search_v2', query='meghan@acme.com')
        #results = response.result.results
        ## should only have 1 result since this is an exact match
        #self.assertEqual(len(results), 1)
        #top_hit = results[0]
        #profile = top_hit.profile
        #self.assertEqual(profile.email, 'meghan@acme.com')
        #self.assertEqual(profile.display_title, 'Customer Service Agent (Customer Support)')
        #self.assertEqual(profile.full_name, 'Meghan Ward')

    def test_search_profile_partial_full_name(self):
        response = self.client.call_action('search_v2', query='meg')
        self.verify_top_results(
            'profile',
            {'email': 'meghan@acme.com', 'full_name': 'Meghan Ward'},
            response.result.results,
        )

    def test_search_profile_first_name(self):
        response = self.client.call_action('search_v2', query='Meghan')
        self.verify_top_results(
            'profile',
            {'email': 'meghan@acme.com'},
            response.result.results,
        )

    def test_search_profile_last_name(self):
        response = self.client.call_action('search_v2', query='Ward')
        self.verify_top_results(
            'profile',
            {'email': 'meghan@acme.com'},
            response.result.results,
        )

    def test_search_profile_name_title(self):
        response = self.client.call_action('search_v2', query='Meg Customer Service Agent')
        self.verify_top_results(
            'profile',
            {'email': 'meghan@acme.com'},
            response.result.results,
            top_results=1,
        )

    def test_search_profile_name_department(self):
        response = self.client.call_action('search_v2', query='Meg in Customer Support')
        self.verify_top_results(
            'profile',
            {'email': 'meghan@acme.com'},
            response.result.results,
        )

    def test_search_profile_nick_name_last_name(self):
        response = self.client.call_action('search_v2', query='Meg Ward')
        self.verify_top_results(
            'profile',
            {'email': 'meghan@acme.com'},
            response.result.results,
            top_results=1,
        )

    def test_search_team_name(self):
        response = self.client.call_action('search_v2', query='Customer Support')
        self.verify_top_results(
            'team',
            {'name': 'Customer Support'},
            response.result.results,
            top_results=1,
        )

    def test_search_team_partial_name(self):
        response = self.client.call_action('search_v2', query='Customer')
        self.verify_top_results(
            'team',
            {'name': 'Customer Support'},
            response.result.results,
            top_results=1,
        )
        response = self.client.call_action('search_v2', query='Support')
        self.verify_top_results(
            'team',
            {'name': 'Customer Support'},
            response.result.results,
        )
        response = self.client.call_action('search_v2', query='Cust')
        self.verify_top_results(
            'team',
            {'name': 'Customer Support'},
            response.result.results,
        )

    def test_search_post_phising_email(self):
        _verify = lambda response, query: self.verify_top_results(
            'post',
            {'title': lambda y: 'phishing' in y},
            response.result.results,
            top_results=1,
            query=query,
        )

        queries = [
            'phishing',
            'phishing email',
            'suspicious email',
            'suspicious call',
        ]
        for query in queries:
            response = self.client.call_action('search_v2', query=query)
            _verify(response, query)

    def test_search_post_travel_request(self):
        _verify = lambda response, query: self.verify_top_results(
            'post',
            {'title': lambda y: 'go somewhere for work' in y},
            response.result.results,
            top_results=1,
            query=query,
        )

        queries = [
            'travel request',
            'booking travel',
            'booking flight',
            'booking hotel',
            'travelling for work',
            'going to a conference',
        ]
        for query in queries:
            response = self.client.call_action('search_v2', query=query)
            _verify(response, query)

    def test_search_post_arbiter_how_to(self):
        _verify = lambda response, query: self.verify_top_results(
            'post',
            {'title': lambda y: 'What is Arbiter?'},
            response.result.results,
            query=query,
        )

        queries = [
            'Arbiter',
            'website testing framework',
        ]
        for query in queries:
            response = self.client.call_action('search_v2', query=query)
            _verify(response, query)

    def test_search_category_profiles(self):
        # verify a normal search returns a team
        response = self.client.call_action('search_v2', query='Customer Support')
        self.verify_top_results(
            'team',
            {'name': 'Customer Support'},
            response.result.results,
            top_results=1,
        )

        response = self.client.call_action(
            'search_v2',
            query='Customer Support',
            category=search_pb2.PROFILES,
        )
        self.verify_top_results(
            'profile',
            {'display_title': lambda x: 'Customer Support' in x},
            response.result.results,
            top_results=1,
        )

    def test_search_category_teams(self):
        # verify a normal search returns a person
        response = self.client.call_action('search_v2', query='Customer Support')
        self.verify_top_results(
            'profile',
            {'display_title': lambda x: 'Customer Support' in x},
            response.result.results,
            top_results=10,
        )

        response = self.client.call_action(
            'search_v2',
            query='Customer Support',
            category=search_pb2.TEAMS,
        )
        self.verify_top_results(
            'profile',
            {'display_title': lambda x: 'Customer Support' in x},
            response.result.results,
            top_results=10,
            should_be_present=False,
        )

    def test_search_category_posts(self):
        # verify a normal search returns a person
        response = self.client.call_action('search_v2', query='Taylor')
        self.verify_top_results(
            'profile',
            {'full_name': lambda x: 'Taylor' in x},
            response.result.results,
        )

        response = self.client.call_action(
            'search_v2',
            query='Taylor',
            category=search_pb2.POSTS,
        )
        self.verify_top_results(
            'profile',
            {'full_name': lambda x: 'Taylor' in x},
            response.result.results,
            top_results=10,
            should_be_present=False,
        )

    def test_search_hashtags(self):
        response = self.client.call_action('search_v2', query='#engineering')
        self.verify_top_results(
            'post',
            {'title': 'Hashtag'},
            response.result.results,
        )

    def test_search_partial_email_shouldnt_rank_higher_than_partial_name(self):
        """Several partial matches on a name should rank higher than on an email.

        Given the following two profiles:
            1:
                name: Marco Zappacosta
                email: marco@acme.com
            2:
                name: Marco de Almeida
                email: mfa@acme.com

        Searching for "Marco Almeida" should return profile 2 as the top result.
        """
        response = self.client.call_action(
            'search_v2',
            query='marco almeida',
            category=search_pb2.PROFILES,
        )
        self.verify_top_results(
            'profile',
            {'email': 'mfa@acme.com'},
            response.result.results,
            top_results=1,
        )

    #def test_search_exact_email_match(self):
        #response = self.client.call_action('search_v2', query='marco@acme.com')
        #self.verify_top_results(
            #'profile',
            #{'email': 'marco@acme.com'},
            #response.result.results,
            #top_results=1,
        #)

    def test_search_raw_content_match_higher_than_title_match(self):
        response = self.client.call_action('search_v2', query='video conferencing')
        hit = response.result.results[0]
        self.assertIn('video conferencing', hit.highlight['content'])

    def test_search_team_name_highlighting_partial(self):
        response = self.client.call_action(
            'search_v2',
            query='Dev',
            category=search_pb2.TEAMS,
        )
        hit = response.result.results[0]
        self.assertTrue(hit.highlight['name'].startswith('DevOps'))

    def test_search_team_name_highlighting(self):
        response = self.client.call_action(
            'search_v2',
            query='Customer Support',
            category=search_pb2.TEAMS,
        )
        hit = response.result.results[0]
        self.assertEqual(hit.highlight['name'], 'Customer Support')

    def test_search_team_description_highlighting(self):
        response = self.client.call_action(
            'search_v2',
            query='site up',
            category=search_pb2.TEAMS,
        )
        hit = response.result.results[0]
        self.assertIn('site up', hit.highlight['description'])

    def test_search_profile_full_name_highlighting(self):
        response = self.client.call_action('search_v2', query='Meg')
        hit = response.result.results[0]
        self.assertTrue(hit.highlight['full_name'].startswith('Meghan'))
        response = self.client.call_action('search_v2', query='Meghan')
        hit = response.result.results[0]
        self.assertTrue(hit.highlight['full_name'].startswith('Meghan'))

        response = self.client.call_action('search_v2', query='Ward')
        hit = response.result.results[0]
        self.assertTrue(hit.highlight['full_name'].endswith('Ward'))

        response = self.client.call_action('search_v2', query='Meghan Ward')
        hit = response.result.results[0]
        self.assertEqual(hit.highlight['full_name'], 'Meghan Ward')

    def test_search_profile_display_title_highlighting(self):
        response = self.client.call_action(
            'search_v2',
            query='Sr. Account',
            category=search_pb2.PROFILES,
        )
        hit = response.result.results[0]
        self.assertTrue(
            hit.highlight['display_title'].startswith(
                'Sr. Account Manager',
            )
        )

        response = self.client.call_action(
            'search_v2',
            query='Manager',
            category=search_pb2.PROFILES,
        )
        hit = response.result.results[0]
        self.assertIn('Manager', hit.highlight['display_title'])

    def test_search_post_title_highlighting(self):
        response = self.client.call_action(
            'search_v2',
            query='Arbit',
            category=search_pb2.POSTS,
        )
        hit = response.result.results[0]
        self.assertIn('Arbiter', hit.highlight['title'])

    def test_search_post_title_highlighting_return_full_fragment(self):
        response = self.client.call_action(
            'search_v2',
            query='expense',
            category=search_pb2.POSTS,
        )
        hit = response.result.results[0]
        expected_title = (
            'How do I fill out an expense report with some really really long'
            ' title to make sure that we return the full field?'
        )
        self.assertIn(expected_title, hit.highlight['title'])

    def test_search_post_content_highlighting(self):
        response = self.client.call_action(
            'search_v2',
            query='Marco Zappacosta',
            category=search_pb2.POSTS,
        )
        hit = response.result.results[0]
        self.assertIn('Marco Zappacosta', hit.highlight['content'])
        self.assertEqual(len(hit.highlight['content']), 174)

    def test_search_result_has_tracking_details(self):
        response = self.client.call_action('search_v2', query='Meghan Ward')
        hit = response.result.results[0]
        profile = hit.profile
        tracking_details = hit.tracking_details
        self.assertEqual(tracking_details.document_id, profile.id)
        self.assertEqual(tracking_details.document_type, types.ProfileV1._doc_type.name)

    def test_search_post_does_not_have_content(self):
        response = self.client.call_action(
            'search_v2',
            query='Arbiter',
            category=search_pb2.POSTS,
        )
        self.assertFalse(any([result.post.content for result in response.result.results]))

    def test_search_does_not_index_html_content(self):
        response = self.client.call_action(
            'search_v2',
            query='div strong',
            category=search_pb2.POSTS,
        )
        self.assertFalse(response.result.results)
        response = self.client.call_action(
            'search_v2',
            query='some bold section',
            category=search_pb2.POSTS,
        )
        self.assertTrue(response.result.results)
        self.assertIn(
            'Some Bold Section',
            response.result.results[0].highlight['content'],
        )


from collections.abc import Iterator

def get_diagnostic_code(input_list, list_of_inputs, logging=False):
    if not isinstance(list_of_inputs, Iterator):
        list_of_inputs = iter(list_of_inputs)
    input_list.extend([0] * 10000)
    i = 0
    relative_base = 0

    while True:
        op_code = input_list[i]
        mode_1 = int(op_code / 100) % 10
        mode_2 = int(op_code / 1000) % 10
        mode_3 = int(op_code / 10000) % 10
        op_code = op_code % 100

        if op_code == 99:
            break

        if mode_1 == 1:
            value_1 = i+1
        elif mode_1 == 0:
            value_1 = input_list[i+1]
        elif mode_1 == 2:
            value_1 = input_list[i+1] + relative_base

        if mode_2 == 1:
            value_2 = i+2
        elif mode_2 == 0:
            value_2 = input_list[i+2]
        elif mode_2 == 2:
            value_2 = input_list[i+2] + relative_base

        try:
            if mode_3 == 1:
                value_3 = i+3
            elif mode_3 == 0:
                value_3 = input_list[i+3]
            elif mode_3 == 2:
                value_3 = input_list[i+3] + relative_base
        except Exception:
            pass

        if op_code == 1:
            input_list[value_3] = input_list[value_1] + input_list[value_2]
            i += 4
        elif op_code == 2:
            input_list[value_3] = input_list[value_1] * input_list[value_2]
            i += 4
        elif op_code == 3:
            input_list[value_1] = next(list_of_inputs)
            i += 2
        elif op_code == 4:
            value = input_list[value_1]
            if logging:
                print(value)
            yield value
            i += 2
        elif op_code == 5:
            if input_list[value_1]:
                i = input_list[value_2]
            else:
                i += 3
        elif op_code == 6:
            if input_list[value_1] == 0:
                i = input_list[value_2]
            else:
                i += 3
        elif op_code == 7:
            if input_list[value_1] < input_list[value_2]:
                input_list[value_3] = 1
            else:
                input_list[value_3] = 0
            i += 4
        elif op_code == 8:
            if input_list[value_1] == input_list[value_2]:
                input_list[value_3] = 1
            else:
                input_list[value_3] = 0
            i += 4
        elif op_code == 9:
            relative_base += input_list[value_1]
            i += 2
        else:
            print("INVALID OP CODE: " + str(op_code))

def initalise_game_board(game_runner, board_size):
    global board, score
    for _ in range(board_size + 1):
        x = next(game_runner)
        y = next(game_runner)
        value = next(game_runner)
        if (x, y) == (-1, 0):
            score = value
        else:
            game_board[x, y] = value

def move_joystick():
    global game_board
    ball = [k for k, v in game_board.items() if v == 4][0][0]
    paddle = [k for k, v in game_board.items() if v == 3][0][0]
    if paddle < ball:
        return 1
    elif paddle > ball:
        return -1
    return 0

def update_board(game_runner):
    global score
    value = None
    while value != 4:
        try:
            x = next(game_runner)
        except StopIteration:
            break
        y = next(game_runner)
        value = next(game_runner)
        if (x, y) == (-1, 0):
            score = value
        else:
            game_board[x, y] = value

if __name__ == '__main__':
    # 0 empty tile
    # 1 wall tile
    BLOCK_TILES = 2
    # 3 horizontal paddle tile
    # 4 ball tile

    # Get the input data
    with open('input/day_13.txt') as f:
        file_data = f.read()
    input_list = [int(x) for x in file_data.split(',')]

    # Part 1:
    global game_board
    game_board = {}
    game_runner = get_diagnostic_code(input_list, [])
    for x in game_runner:
        y = next(game_runner)
        value = next(game_runner)
        game_board[x, y] = value
    print('Number of block tiles:', list(game_board.values()).count(BLOCK_TILES))

    # Part 2:
    board_size = len(game_board)
    inputs = []
    game_runner = get_diagnostic_code([2] + input_list[1:], inputs)
    initalise_game_board(game_runner, board_size)
    while True:
        if list(game_board.values()).count(2) == 0:
            break
        inputs.append(move_joystick())
        update_board(game_runner)

    print('Final score:' + str(score))


import torch,torchvision
import torch.nn as nn
import torch.nn.functional as F
import torchvision.transforms as transforms
from torchvision import models
from torch import optim
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from PIL import Image
import cv2
import os

device='cuda' if torch.cuda.is_available() else 'cpu'
print(torch.cuda.is_available())

train_transform=transforms.Compose([
transforms.ToTensor(),
    transforms.Resize((224,224)),
    transforms.RandomAffine(degrees=(25)),
    transforms.RandomRotation(25),
    transforms.RandomHorizontalFlip(0.5),
    transforms.RandomVerticalFlip(0.5),
    transforms.Normalize((0.5,0.5,0.5),(1,1,1))
    ])
transform=transforms.Compose([
    transforms.ToTensor(),
    transforms.Resize((224,224)),
    transforms.Normalize((0.5,0.5,0.5),(1,1,1))
])

train_data=torchvision.datasets.ImageFolder('dataset/dataset_/train',transform=train_transform)
test_data=torchvision.datasets.ImageFolder('dataset/dataset_/test',transform=transform)
val_data=torchvision.datasets.ImageFolder('dataset/dataset_/val',transform=transform)

classes=train_data.class_to_idx
print(classes)
print(len(classes))

batch_size=32
epochs=200
num_classes=4
load_model=True

train_loader=torch.utils.data.DataLoader(train_data,batch_size=batch_size,shuffle=True)
test_loader=torch.utils.data.DataLoader(test_data,batch_size=batch_size,shuffle=True)
val_loader=torch.utils.data.DataLoader(val_data,batch_size=batch_size,shuffle=True)

model_ft = models.resnet18(pretrained=True)
num_ftrs = model_ft.fc.in_features
model_ft.fc = nn.Linear(num_ftrs, 4)

model_ft = model_ft.to(device)
model_ft

loss_fn=nn.CrossEntropyLoss()
optimizer=optim.SGD(model_ft.parameters(),lr=0.0001)

path="models"

for epoch in range(epochs):
    for i,(images,labels) in enumerate(train_loader):
        images=images.to(device)
        labels=labels.to(device)
        outputs=model_ft(images)
        loss=loss_fn(outputs,labels)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    print('Epoch [{}/{}],loss {}'.format(epoch+1,epochs,loss.item()))
    torch.save(model_ft.state_dict(),os.path.join(path,'epoch-{}.pt'.format(epoch)))

with torch.no_grad():
    correct=0
    total=0
    for i,(images,labels) in enumerate(val_loader):
        images=images.to(device)
        labels=labels.to(device)
        outputs=model_ft(images)
        pred=torch.max(outputs,1)[1]
        total+=labels.size(0)
        correct += (pred == labels).sum().item()
        accu=correct/total
    print("Accuracy :%.2f"%accu)


from django.shortcuts import render
from .models import Articles
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.template.context_processors import csrf

def articles(request):
    articles_list = Articles.objects.all().order_by("-date")
    paginator = Paginator(articles_list,5)
    page = request.GET.get('page',1)
    try:
        articles = paginator.page(page)
    except PageNotAnInteger:
        articles = paginator.page(1)
    except EmptyPage:
        articles = paginator.page(paginator.num_pages)
    return render(request, 'news/posts.html', {'articles': articles})

def article(request, article_id=1):
    args = {}
    args.update(csrf(request))
    args['article'] = Articles.objects.get(id=article_id)
    return render(request, 'news/post.html', args)


import json, threading
import re, requests
from lxml import etree
from queue import Queue

class DouBan(threading.Thread):
    def __init__(self, q=None):
        super().__init__()
        self.base_url = 'https://movie.douban.com/chart'
        self.headers = {
            'User-Agent':
            'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36',
            'Referer': 'https://movie.douban.com/explore'
        }
        self.q = q
        self.ajax_url = 'https://movie.douban.com/j/chart/top_list?type={}&interval_id=100%3A90&action=&start={}&limit=20'

    # 获取网页的源码
    def get_content(self, url, headers):
        response = requests.get(url, headers=headers)
        return response.text

    # 获取电影指定信息
    def get_movie_info(self, text):
        text = json.loads(text)
        item = {}
        for data in text:
            score = data['score']
            image = data['cover_url']
            title = data['title']
            actors = data['actors']
            detail_url = data['url']
            vote_count = data['vote_count']
            types = data['types']
            item['评分'] = score
            item['图片'] = image
            item['电影名'] = title
            item['演员'] = actors
            item['详情页链接'] = detail_url
            item['评价数'] = vote_count
            item['电影类别'] = types
            print(item)

    # 获取电影api数据的
    def get_movie(self):
        headers = {
            'X-Requested-With':
            'XMLHttpRequest',
            'User-Agent':
            'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36',
        }

        # 获取api数据，并判断分页
        while True:
            if self.q.empty():
                break
            n = 0
            while True:
                text = self.get_content(self.ajax_url.format(self.q.get(), n),
                                        headers=headers)
                if text == '[]':
                    break
                self.get_movie_info(text)
                n += 20

    # 获取所有类型的type——id
    def get_types(self):
        html_str = self.get_content(self.base_url,
                                    headers=self.headers)  # 分类页首页
        html = etree.HTML(html_str)
        types = html.xpath(
            '//div[@class="types"]/span/a/@href')  # 获得每个分类的连接，但是切割type
        # print(types)
        type_list = []
        for i in types:
            p = re.compile('type=(.*?)&interval_id=')  # 筛选id，拼接到api接口的路由
            type = p.search(i).group(1)
            type_list.append(type)
        return type_list

    def run(self):
        self.get_movie()

if __name__ == '__main__':
    # 创建消息队列
    q = Queue()
    # 将任务队列初始化，将我们的type放到消息队列中
    t = DouBan()
    types = t.get_types()
    for tp in types:
        q.put(tp[0])
    # 创建一个列表，列表的数量就是开启线程的树木
    crawl_list = [1, 2, 3, 4]
    for crawl in crawl_list:
        # 实例化对象
        movie = DouBan(q=q)
        movie.start()


#

# 使用python asyncio编写tcp服务端，要求: 监听7000端口, 设置端口可重用, 新建连接的时候打印新连接信息，断开连接的时候也打印断开时的信息，连接设置tcp nodelay选项, 使用包头为: 4字节做包体长度, 4字节做pack_id, 8字节做user_id。

import asyncio
import struct
import datetime
import yaml
import logging

async def handle_client(reader, writer):
    peername = writer.get_extra_info('peername')
    print(f'New connection from {peername}')
    # socket = writer.get_extra_info('socket')
    # socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
    try:
        while True:
            # 读取包头
            header = await reader.readexactly(16)
            body_length, pack_id, user_id = struct.unpack('!LLQ', header)

            # 读取包体
            body = await reader.readexactly(body_length)

            print(f'Received {len(header) + len(body)} bytes from {peername}: pack_id={pack_id}, user_id={user_id}, body={body}')

            # 回复响应
            response = b'OK'
            response_header = struct.pack('!LLQ', len(response), pack_id, user_id)
            writer.write(response_header + response)
            await writer.drain()
    except asyncio.exceptions.IncompleteReadError:
        pass
    finally:
        # 连接关闭时打印当前时间
        print(f'Connection from {peername} closed at {datetime.datetime.now()}')
        writer.close()

async def main():
    server = await asyncio.start_server(handle_client, '127.0.0.1', 7000, reuse_port=True)

    print('Server started')

    async with server:
        await server.serve_forever()

if __name__ == '__main__':
    asyncio.run(main())


#-*- encoding: UTF-8 -*-
from django import forms
from AlyMoly.mantenedor.models import Bodega
from AlyMoly.movimiento.models import ProductoBodega, Ingreso, Producto, Egreso, Traspaso
from AlyMoly.utils import widgets

class IngresoMercaderiaForm(forms.ModelForm):

    def __init__(self,*args,**kwargs):
        super(IngresoMercaderiaForm,self).__init__(*args,**kwargs)
        try:
            self.initial['bodega'] = unicode(kwargs['instance'].existencia.bodega.id)
            self.initial['existencia'] = unicode(kwargs['instance'].existencia.producto.codigo_barra)
        except KeyError:
            #No existe la instancia en un formulario de no-edición
            pass

    bodega = forms.ModelChoiceField(
                               required=True,
                               label=u"Bodega",
                               queryset=Bodega.objects.all(),
                               widget=forms.Select(attrs={'style':'width:230px'}),
                               help_text=u"Seleccione la Bodega"
                               )

    existencia = forms.CharField(label=u"Producto",
                                 widget=widgets.NombreProductoWidget())

    def clean(self):
        cleaned_data = self.cleaned_data
        bodega = cleaned_data.get("bodega")
        producto = cleaned_data.get("existencia")

        if bodega and producto:
            cleaned_data["existencia"] = ProductoBodega.objects.get(bodega=bodega,producto=producto)

        return cleaned_data

    def clean_existencia(self):
        "Verifica que exista el codigo de barra de existencia"
        data = self.cleaned_data["existencia"]
        try:
            producto = Producto.objects.get(codigo_barra=data)
            return producto
        except:
            raise forms.ValidationError(u"No existe el código de barra ingresado.")

    class Meta:
        model = Ingreso
        fields = '__all__'

class EgresoMercaderiaForm(forms.ModelForm):

    def __init__(self,*args,**kwargs):
        super(EgresoMercaderiaForm,self).__init__(*args,**kwargs)
        try:
            self.initial['bodega'] = unicode(kwargs['instance'].existencia.bodega.id)
            self.initial['existencia'] = unicode(kwargs['instance'].existencia.producto.codigo_barra)
        except KeyError:
            #No existe la instancia en un formulario de no-edición
            pass

    bodega = forms.ModelChoiceField(
                               required=True,
                               label=u"Bodega",
                               queryset=Bodega.objects.all(),
                               widget=forms.Select(attrs={'style':'width:230px'}),
                               help_text=u"Seleccione la Bodega"
                               )

    existencia = forms.CharField(label=u"Producto",
                                 widget=widgets.NombreProductoWidget())

    def clean_existencia(self):
        "Verifica que exista el codigo de barra de existencia"
        data = self.cleaned_data["existencia"]
        try:
            producto = Producto.objects.get(codigo_barra=data)
            return producto
        except:
            raise forms.ValidationError(u"No existe el código de barra ingresado.")

    def clean(self):
        """ Valida lo siguiente:
        - Evita descontar mas existencias de la que existen en bodega
        - Soporta el egreso de productos compuestos
        """
        cleaned_data = self.cleaned_data
        bodega = cleaned_data.get("bodega")
        producto = cleaned_data.get("existencia")
        cantidad = cleaned_data.get("cantidad")
        if bodega and producto and cantidad:
            cleaned_data["existencia"] = ProductoBodega.objects.get(bodega=bodega,producto=producto)
            registro = None
            try:
                registro = ProductoBodega.objects.get(bodega=bodega,producto__compone=producto)
                total = registro.existencia - (registro.producto.cantidad_compone * cantidad)
            except ProductoBodega.DoesNotExist:
                registro = ProductoBodega.objects.get(bodega=bodega,producto=producto)
                total = registro.existencia - cantidad
            if total < 0 and not self.instance.id:
                del cleaned_data['cantidad']
                raise forms.ValidationError(u"No hay existencias suficientes para realizar el egreso desde la bodega.")

        return cleaned_data

    class Meta:
        model = Egreso
        fields = '__all__'

class TraspasoForm(forms.ModelForm):

    def __init__(self,*args,**kwargs):
        super(TraspasoForm,self).__init__(*args,**kwargs)
        try:
            if kwargs['instance']:
                self.initial['producto'] = unicode(kwargs['instance'].producto.codigo_barra)
        except KeyError:
            #No existe la instancia en un formulario de no-edición
            pass

    producto = forms.CharField(label=u'Producto',
                               widget=widgets.NombreProductoWidget())

    def clean(self):
        """Valida lo siguiente
        -bodegas seleccionadas son distintas
        -bodega de origen tiene existencias suficientes"""
        cleaned_data = self.cleaned_data
        origen = cleaned_data.get("origen")
        destino = cleaned_data.get("destino")
        producto = cleaned_data.get("producto")
        cantidad = cleaned_data.get("cantidad")

        if origen and destino and producto and cantidad:
            if origen == destino:
                raise forms.ValidationError(u"Debe seleccionar bodegas distintas.")
            registro = None
            try:
                registro = ProductoBodega.objects.get(bodega=origen,producto__compone=producto)
                total = registro.existencia - (registro.producto.cantidad_compone * cantidad)
            except ProductoBodega.DoesNotExist:
                registro = ProductoBodega.objects.get(bodega=origen,producto=producto)
                total = registro.existencia - cantidad
            if total < 0 and not self.instance.id:
                raise forms.ValidationError(u"No hay existencias suficientes para traspasar desde la bodega de origen \"%s\"." % origen)

        # Se retorna el diccioario de datos limpios
        return cleaned_data

    def clean_producto(self):
        value = self.cleaned_data['producto']
        try:
            return Producto.objects.get(codigo_barra=value)
        except Producto.DoesNotExist:
            raise forms.ValidationError(u'No existe el producto de código de barra "%s".' % value)

    class Meta:
        model = Traspaso
        fields = '__all__'


import json
from functools import partial

from pytest import fixture, mark
from traitlets.config import Config

from ..generic import GenericOAuthenticator
from .mocks import setup_oauth_mock

def user_model(username, **kwargs):
    """Return a user model"""
    return {
        "username": username,
        "scope": "basic",
        "groups": ["group1"],
        **kwargs,
    }

@fixture
def generic_client(client):
    setup_oauth_mock(
        client,
        host='generic.horse',
        access_token_path='/oauth/access_token',
        user_path='/oauth/userinfo',
    )
    return client

def _get_authenticator(**kwargs):
    return GenericOAuthenticator(
        token_url='https://generic.horse/oauth/access_token',
        userdata_url='https://generic.horse/oauth/userinfo',
        **kwargs,
    )

@fixture
def get_authenticator(generic_client):
    """
    http_client can't be configured, only passed as argument to the constructor.
    """
    return partial(_get_authenticator, http_client=generic_client)

@mark.parametrize(
    "test_variation_id,class_config,expect_allowed,expect_admin",
    [
        # no allow config tested
        ("00", {}, False, None),
        # allow config, individually tested
        ("01", {"allow_all": True}, True, None),
        ("02", {"allowed_users": {"user1"}}, True, None),
        ("03", {"allowed_users": {"not-test-user"}}, False, None),
        ("04", {"admin_users": {"user1"}}, True, True),
        ("05", {"admin_users": {"not-test-user"}}, False, None),
        ("06", {"allowed_groups": {"group1"}}, True, None),
        ("07", {"allowed_groups": {"test-user-not-in-group"}}, False, None),
        ("08", {"admin_groups": {"group1"}}, True, True),
        ("09", {"admin_groups": {"test-user-not-in-group"}}, False, False),
        # allow config, some combinations of two tested
        (
            "10",
            {
                "allow_all": False,
                "allowed_users": {"not-test-user"},
            },
            False,
            None,
        ),
        (
            "11",
            {
                "allowed_users": {"not-test-user"},
                "admin_users": {"user1"},
            },
            True,
            True,
        ),
        (
            "12",
            {
                "allowed_groups": {"group1"},
                "admin_groups": {"group1"},
            },
            True,
            True,
        ),
        (
            "13",
            {
                "allowed_groups": {"group1"},
                "admin_groups": {"test-user-not-in-group"},
            },
            True,
            False,
        ),
        (
            "14",
            {
                "allowed_groups": {"test-user-not-in-group"},
                "admin_groups": {"group1"},
            },
            True,
            True,
        ),
        (
            "15",
            {
                "allowed_groups": {"test-user-not-in-group"},
                "admin_groups": {"test-user-not-in-group"},
            },
            False,
            False,
        ),
        (
            "16",
            {
                "admin_users": {"user1"},
                "admin_groups": {"group1"},
            },
            True,
            True,
        ),
        (
            "17",
            {
                "admin_users": {"user1"},
                "admin_groups": {"test-user-not-in-group"},
            },
            True,
            True,
        ),
        (
            "18",
            {
                "admin_users": {"not-test-user"},
                "admin_groups": {"group1"},
            },
            True,
            True,
        ),
        (
            "19",
            {
                "admin_users": {"not-test-user"},
                "admin_groups": {"test-user-not-in-group"},
            },
            False,
            False,
        ),
    ],
)
async def test_generic(
    get_authenticator,
    generic_client,
    test_variation_id,
    class_config,
    expect_allowed,
    expect_admin,
):
    print(f"Running test variation id {test_variation_id}")
    c = Config()
    c.GenericOAuthenticator = Config(class_config)
    c.GenericOAuthenticator.username_claim = "username"
    authenticator = get_authenticator(config=c)

    handled_user_model = user_model("user1")
    handler = generic_client.handler_for_user(handled_user_model)
    auth_model = await authenticator.get_authenticated_user(handler, None)

    if expect_allowed:
        assert auth_model
        assert set(auth_model) == {"name", "admin", "auth_state"}
        assert auth_model["admin"] == expect_admin
        auth_state = auth_model["auth_state"]
        assert json.dumps(auth_state)
        assert "access_token" in auth_state
        assert "oauth_user" in auth_state
        assert "refresh_token" in auth_state
        assert "scope" in auth_state
        user_info = auth_state[authenticator.user_auth_state_key]
        assert auth_model["name"] == user_info[authenticator.username_claim]
    else:
        assert auth_model == None

async def test_generic_data(get_authenticator, generic_client):
    c = Config()
    c.GenericOAuthenticator.allow_all = True
    authenticator = get_authenticator()

    handled_user_model = user_model("user1")
    handler = generic_client.handler_for_user(handled_user_model)
    data = {"testing": "data"}
    auth_model = await authenticator.authenticate(handler, data)

    assert auth_model

async def test_generic_callable_username_key(get_authenticator, generic_client):
    c = Config()
    c.GenericOAuthenticator.allow_all = True
    c.GenericOAuthenticator.username_key = lambda r: r["alternate_username"]
    authenticator = get_authenticator(config=c)

    handled_user_model = user_model("user1", alternate_username="zoe")
    handler = generic_client.handler_for_user(handled_user_model)
    auth_model = await authenticator.get_authenticated_user(handler, None)

    assert auth_model["name"] == "zoe"

async def test_generic_claim_groups_key_callable(get_authenticator, generic_client):
    c = Config()
    c.GenericOAuthenticator.claim_groups_key = lambda r: r["policies"]["roles"]
    c.GenericOAuthenticator.allowed_groups = ["super_user"]
    authenticator = get_authenticator(config=c)

    handled_user_model = user_model("user1", policies={"roles": ["super_user"]})
    handler = generic_client.handler_for_user(handled_user_model)
    auth_model = await authenticator.get_authenticated_user(handler, None)

    assert auth_model

async def test_generic_claim_groups_key_nested_strings(
    get_authenticator, generic_client
):
    c = Config()
    c.GenericOAuthenticator.claim_groups_key = "permissions.groups"
    c.GenericOAuthenticator.admin_groups = ["super_user"]
    authenticator = get_authenticator(config=c)

    handled_user_model = user_model("user1", permissions={"groups": ["super_user"]})
    handler = generic_client.handler_for_user(handled_user_model)
    auth_model = await authenticator.get_authenticated_user(handler, None)

    assert auth_model
    assert auth_model["admin"]

@mark.parametrize(
    "name, allowed",
    [
        ("allowed", True),
        ("notallowed", False),
    ],
)
async def test_check_allowed_no_auth_state(get_authenticator, name, allowed):
    authenticator = get_authenticator(allowed_users={"allowed"})
    # allow check always gets called with no auth model during Hub startup
    # these are previously-allowed users who should pass until subsequent
    # this check is removed in JupyterHub 5
    assert await authenticator.check_allowed(name, None)


"""Signup processing (Waiting list and payments).

So far only dummy functionality, i.e. if a payment is posted, all courses
are set to accepted.

As soon as we have payment service provider, the definite functionality needs
to be implemented.

TODO: Send notification mails
"""

import json
from functools import wraps
from itertools import chain

from bson import ObjectId
from flask import current_app, abort
from eve.methods.patch import patch_internal

def wrap_response(function):
    """Wrapper to modify payload for successful requests (status 2xx)."""
    @wraps(function)
    def _wrapped(_, response):
        if response.status_code // 100 == 2:
            payload = json.loads(response.get_data(as_text=True))

            if '_items' in payload:
                function(payload['_items'])
            else:
                function([payload])

            response.set_data(json.dumps(payload))
    return _wrapped

@wrap_response
def new_signups(signups):
    """Update the status for all signups to a course."""
    def get_id(course):
        """Return the course id, necessary to cope with embedding.

        If the client requests `course` to be embedded, it will be a dict
        with the id as key. Otherwise `course` will be just the id.
        """
        return course['_id'] if isinstance(course, dict) else course

    # Remove duplicates by using a set
    courses = set(get_id(item['course']) for item in signups)
    # Re-format signups into a dict so we can update them easier later
    signups_by_id = {str(item['_id']): item for item in signups}

    modified = chain.from_iterable(update_signups(course)
                                   for course in courses)

    for _id in modified:
        # Update response payload if needed
        try:
            signups_by_id[_id]['status'] = 'reserved'
        except AttributeError:
            pass  # Not in response, nothing to do

def deleted_signup(signup):
    """Update status of course the signup belonged to."""
    update_signups(signup['course'])

def patched_signup(update, original):
    """Update status of all signups of the original and new course."""
    # Only need to do something if course is changed
    if 'course' in update:
        update_signups(update['course'])
        update_signups(original['course'])

def patched_course(update, original):
    """If the number of spots changed, update signups of course."""
    if 'spots' in update:
        update_signups(original['_id'])

def block_course_deletion(course):
    """If a course has signups, it can't be deleted."""
    count = current_app.data.driver.db['signups'].count({
        'course': course['_id']
    })

    if count > 0:
        abort(409, "Course cannot be deleted as long as it has signups.")

def update_signups(course_id):
    """Update waiting list for a course.

    The course id can be given as string or ObjectId.

    We can assume that the course exists, otherwise Eve stops earlier.

    Return list of ids of all reserved signups.
    """
    course_id = ObjectId(course_id)  # Ensure we are working with ObjectId

    # Determine how many spots the course has
    total_spots = (current_app.data.driver.db['courses']
                   .find_one({'_id': course_id}, projection={'spots': 1})
                   .get('spots', 0))

    # Next, count current signups not on waiting list
    signups = current_app.data.driver.db['signups']
    taken_spots = signups.count({'course': course_id,
                                 'status': {'$ne': 'waiting'}})

    available_spots = total_spots - taken_spots

    if available_spots <= 0:
        return []

    # Finally, get as many signups on the waiting list as spots available
    # sort by _updated, use nethz as tie breaker
    chosen_signups = signups.find({'course': course_id,
                                   'status': 'waiting'},
                                  projection=['_id'],
                                  sort=[('_updated', 1), ('nethz', 1)],
                                  limit=available_spots)

    signup_ids = [item['_id'] for item in chosen_signups]

    signups.update_many({'_id': {'$in': signup_ids}},
                        {'$set': {'status': 'reserved'}})

    return [str(item) for item in signup_ids]

def mark_as_paid(payments):
    """After successful payment, set status to `accepted`."""
    # Check if payments is not a list
    if not isinstance(payments, list):
        payments = [payments]

    for payment in payments:

        for signup in payment['signups']:
            data = {'status': 'accepted'}
            patch_internal('signups',
                           _id=str(signup),
                           payload=data,
                           concurrency_check=False,
                           skip_validation=True)

def mark_as_unpaid(payments):
    """Before a payment is deleted, set status to `reserved`."""
    # Check if payments is not a list
    if not isinstance(payments, list):
        payments = [payments]

    for payment in payments:

        for signup in payment['signups']:
            data = {'status': 'reserved'}
            patch_internal('signups',
                           _id=str(signup),
                           payload=data,
                           concurrency_check=False,
                           skip_validation=True)


from airflow import DAG
from airflow.operators.dummy_operator import DummyOperator
from airflow.models import Param
from common.operators.gce import (
    StartGCEOperator,
    StopGCEOperator,
    CloneRepositoryGCEOperator,
    SSHGCEOperator,
)
from airflow.providers.google.cloud.operators.bigquery import (
    BigQueryExecuteQueryOperator,
    BigQueryInsertJobOperator,
)
import datetime
from pathlib import Path
from common.config import (
    GCP_PROJECT_ID,
    DAG_FOLDER,
    ENV_SHORT_NAME,
    DATA_GCS_BUCKET_NAME,
    BIGQUERY_TMP_DATASET,
)
from common.utils import get_airflow_schedule

from common.alerts import task_fail_slack_alert

from common import macros

SQL_BASE_PATH = Path("dependencies/export_posthog/sql")

GCE_INSTANCE = f"export-posthog-{ENV_SHORT_NAME}"
BASE_PATH = "data-gcp/jobs/etl_jobs/internal/posthog"
dag_config = {
    "PROJECT_NAME": GCP_PROJECT_ID,
    "ENV_SHORT_NAME": ENV_SHORT_NAME,
}

default_dag_args = {
    "start_date": datetime.datetime(2020, 12, 21),
    "retries": 1,
    "on_failure_callback": task_fail_slack_alert,
    "retry_delay": datetime.timedelta(minutes=5),
    "project_id": GCP_PROJECT_ID,
}
DATE = "{{ ts_nodash }}"

dag_config = {
    "STORAGE_PATH": f"gs://{DATA_GCS_BUCKET_NAME}/posthog_export_{ENV_SHORT_NAME}/export_posthog_{DATE}",
    "BASE_DIR": "data-gcp/jobs/etl_jobs/internal/export_posthog/",
}

gce_params = {
    "instance_name": f"export-posthog-data-{ENV_SHORT_NAME}",
    "instance_type": "n1-standard-16",
}

schedule_dict = {"prod": "0 8 * * *", "dev": "0 12 * * *", "stg": "0 10 * * *"}

with DAG(
    "export_posthog",
    default_args=default_dag_args,
    description="Export to analytics data posthog",
    schedule_interval=get_airflow_schedule(schedule_dict[ENV_SHORT_NAME]),
    catchup=False,
    dagrun_timeout=datetime.timedelta(minutes=1440),
    user_defined_macros=macros.default,
    template_searchpath=DAG_FOLDER,
    params={
        "branch": Param(
            default="production" if ENV_SHORT_NAME == "prod" else "master",
            type="string",
        ),
        "instance_type": Param(
            default=gce_params["instance_type"],
            type="string",
        ),
        "instance_name": Param(
            default=gce_params["instance_name"],
            type="string",
        ),
        "days": Param(
            default=0,
            type="integer",
        ),
    },
) as dag:
    start = DummyOperator(task_id="start", dag=dag)
    export_tasks = []
    for sql_query in ["export_firebase_pro_events", "export_firebase_native_events"]:
        table_id = f"{DATE}_{sql_query}"
        export_task = BigQueryExecuteQueryOperator(
            task_id=f"{sql_query}",
            sql=(SQL_BASE_PATH / f"{sql_query}.sql").as_posix(),
            write_disposition="WRITE_TRUNCATE",
            use_legacy_sql=False,
            destination_dataset_table=f"{BIGQUERY_TMP_DATASET}.{table_id}",
            dag=dag,
        )

        export_bq = BigQueryInsertJobOperator(
            task_id=f"{sql_query}_to_bucket",
            configuration={
                "extract": {
                    "sourceTable": {
                        "projectId": GCP_PROJECT_ID,
                        "datasetId": BIGQUERY_TMP_DATASET,
                        "tableId": table_id,
                    },
                    "compression": None,
                    "destinationUris": f"{dag_config['STORAGE_PATH']}/{table_id}/data-*.parquet",
                    "destinationFormat": "PARQUET",
                }
            },
            dag=dag,
        )
        export_task.set_upstream(start)
        export_bq.set_upstream(export_task)

        export_tasks.append(export_bq)

    gce_instance_start = StartGCEOperator(
        task_id="gce_start_task",
        preemptible=False,
        instance_name="{{ params.instance_name }}",
        instance_type="{{ params.instance_type }}",
        retries=2,
        labels={"job_type": "long_task"},
    )

    fetch_code = CloneRepositoryGCEOperator(
        task_id="fetch_code",
        instance_name="{{ params.instance_name }}",
        python_version="3.10",
        command="{{ params.branch }}",
        retries=2,
    )

    install_dependencies = SSHGCEOperator(
        task_id="install_dependencies",
        instance_name="{{ params.instance_name }}",
        base_dir=dag_config["BASE_DIR"],
        command="pip install -r requirements.txt --user",
        dag=dag,
    )

    pro_storage_path = (
        f"{dag_config['STORAGE_PATH']}/{DATE}_export_firebase_pro_events/"
    )
    native_storage_path = (
        f"{dag_config['STORAGE_PATH']}/{DATE}_export_firebase_native_events/"
    )

    firebase_pro_events_export = SSHGCEOperator(
        task_id="firebase_pro_events_export",
        instance_name="{{ params.instance_name }}",
        base_dir=dag_config["BASE_DIR"],
        command="python main.py " f"--source-gs-path {pro_storage_path}",
        dag=dag,
    )

    native_events_export = SSHGCEOperator(
        task_id="native_events_export",
        instance_name="{{ params.instance_name }}",
        base_dir=dag_config["BASE_DIR"],
        command="python main.py " f"--source-gs-path {native_storage_path}",
        dag=dag,
    )

    gce_instance_stop = StopGCEOperator(
        task_id="gce_stop_task", instance_name="{{ params.instance_name }}"
    )

    (
        export_tasks
        >> gce_instance_start
        >> fetch_code
        >> install_dependencies
        >> firebase_pro_events_export
        >> native_events_export
        >> gce_instance_stop
    )