from matplotlib.pyplot import text
import pygame
import os
from pygame import Vector2
from Fruit import Fruit

from Player import Player
from Direction import Direction
from InputDirection import InputDirection

class Game():
    def __init__(self, width, height):
        # prerequisites
        self.WIDTH = width
        self.HEIGHT = height
        self.WIN = pygame.display.set_mode((self.WIDTH, self.HEIGHT))
        pygame.init()
        pygame.display.set_caption("Snake Solver")
        self.clock = pygame.time.Clock()

        # useful consts
        self.WHITE = (255, 255, 255)
        self.FPS = 60

        self.BOARD_WIDTH, self.BOARD_HEIGHT = 20, 15
        self.BOARD_SIZES = (self.BOARD_WIDTH, self.BOARD_HEIGHT)

        TILE_WIDTH, TILE_HEIGHT = 50, 50
        self.TILE_SIZES = (TILE_WIDTH, TILE_HEIGHT)
        self.sizes = Vector2(50, 50)

        self.SPEED = 20
        self.score = 0

        # RL variables
        self.stagnate_steps = 0

        # loading images
        self.A_IMAGE = pygame.image.load(os.path.join("assets", "a.png"))
        self.A_IMAGE = pygame.transform.scale(self.A_IMAGE, (TILE_WIDTH, TILE_WIDTH))
        self.FRUIT_IMAGE = pygame.image.load(os.path.join("assets", "fruit.png"))
        self.FRUIT_IMAGE = pygame.transform.scale(self.FRUIT_IMAGE, (TILE_WIDTH, TILE_WIDTH))
        self.SNAKE_IMAGE = pygame.image.load(os.path.join("assets", "SolidnySnake.png"))

        # font
        pygame.font.init()
        self.my_font = pygame.font.SysFont('Comic Sans MS', 50)
        self.text_sur = self.my_font.render(str(self.score), False, (0,0,0))

        # load objects
        self.first_pos = Vector2(0, 0)
        self.player = Player(self.A_IMAGE, self.first_pos, self.sizes)
        self.first_fruit_pos = Vector2((int)(self.BOARD_HEIGHT/2), (int)(self.BOARD_WIDTH/2))
        self.fruit = Fruit(self.FRUIT_IMAGE, self.first_fruit_pos, self.sizes)

    def play_step(self, action):

        self.stagnate_steps += 1
        direction = self.convert_array_to_direction(action, self.player.get_current_direction())
        # input
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        # move to the next direction
        self.do_move_2(direction) # we know we are able to move because of checks in model (hopefully)

        # check if game is over
        reward = 0
        game_over = False
        if not self.can_move() or self.stagnate_steps > 60 * len(self.player.get_player_part_queue()):
            game_over = True
            reward -= 10
            return reward, game_over, self.score

        # check food
        if self.does_player_hit_fruit(self.player.get_current_head_pos(), self.fruit.get_fruit_pos()):
            reward += 10
            self.do_fruit()

        # update ui and clock
        self.draw_window()
        self.clock.tick(self.SPEED)

        # return game over and score
        return reward, game_over, self.score

    def main(self):
        clock = pygame.time.Clock()
        run = True
        while run:
            clock.tick(self.FPS)
            events = pygame.event.get()
            self.read_input(events)

            for event in events:
                if event.type == pygame.QUIT:
                    run = False

            if not self.can_move():
                self.reset()

            self.draw_window()

        pygame.quit()

    # UI-related methods

    def draw_window(self):
        self.WIN.fill(self.WHITE)

        self._draw_game_elements()
        self._draw_score()
        self._draw_lines()

        pygame.display.update()

    def _draw_game_elements(self):
        for i in self.player.get_player_part_queue():
            self.WIN.blit(i.image, i.box_info.box.topleft)

        self.WIN.blit(self.fruit.image, self.fruit.box_info.box.topleft)
        self.WIN.blit(self.SNAKE_IMAGE, Vector2(1050, 300))

    def _draw_score(self):
        text_sur = self.my_font.render(f"SCORE {str(self.score)}", False, (0,0,0))
        self.WIN.blit(text_sur, (1150, 50))

    def _draw_lines(self):
        pygame.draw.line(self.WIN, (50,50,50), (0, 0), (1000, 0), 1)
        pygame.draw.line(self.WIN, (50,50,50), (0, 750), (1000, 750), 1)
        pygame.draw.line(self.WIN, (50,50,50), (1000, 0), (1000, 750), 1)

    # game logic related methods

    def reset(self):
        self.player.reset()
        self.fruit.reset()
        self.fruit.set_random_pos(self.player.get_player_part_queue(), self.BOARD_SIZES)
        self.score = 0
        self.stagnate_steps = 0

    def read_input(self, events):
        for event in events:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    if self.is_next_move_possible(self.player.get_current_head_pos(), self.player.get_player_part_queue(), Direction.LEFT):
                        self.player.move_one_step(Direction.LEFT)
                        if self.does_player_hit_fruit(self.player.get_current_head_pos(), self.fruit.get_fruit_pos()):
                            self.do_fruit()
                if event.key == pygame.K_RIGHT:
                    if self.is_next_move_possible(self.player.get_current_head_pos(), self.player.get_player_part_queue(), Direction.RIGHT):
                        self.player.move_one_step(Direction.RIGHT)
                        if self.does_player_hit_fruit(self.player.get_current_head_pos(), self.fruit.get_fruit_pos()):
                            self.do_fruit()
                if event.key == pygame.K_DOWN:
                    if self.is_next_move_possible(self.player.get_current_head_pos(), self.player.get_player_part_queue(), Direction.DOWN):
                        self.player.move_one_step(Direction.DOWN)
                        if self.does_player_hit_fruit(self.player.get_current_head_pos(), self.fruit.get_fruit_pos()):
                            self.do_fruit()
                if event.key == pygame.K_UP:
                    if self.is_next_move_possible(self.player.get_current_head_pos(), self.player.get_player_part_queue(), Direction.UP):
                        self.player.move_one_step(Direction.UP)
                        if self.does_player_hit_fruit(self.player.get_current_head_pos(), self.fruit.get_fruit_pos()):
                            self.do_fruit()

                # alternative way of moving (testing)
                if event.key == pygame.K_a:
                    standardized_input = self.convert_input_to_direction(InputDirection.TURN_COUNTERCLOCKWISE, current_dir=self.player.get_current_direction())
                    self.do_move(standardized_input)
                if event.key == pygame.K_w:
                    standardized_input = self.convert_input_to_direction(InputDirection.FORWARD, current_dir=self.player.get_current_direction())
                    self.do_move(standardized_input)
                if event.key == pygame.K_d:
                    standardized_input = self.convert_input_to_direction(InputDirection.TURN_CLOCKWISE, current_dir=self.player.get_current_direction())
                    self.do_move(standardized_input)

    def convert_input_to_direction(self, input_dir, current_dir):
        if input_dir == InputDirection.FORWARD:
            new_dir = current_dir
        elif input_dir == InputDirection.TURN_CLOCKWISE:
            new_dir = Direction.get_clockwise(current_dir)
        elif input_dir == InputDirection.TURN_COUNTERCLOCKWISE:
            new_dir = Direction.get_counterclockwise(current_dir)

        return new_dir

    def convert_array_to_direction(self, array_dir, current_dir):
        if array_dir == InputDirection.FORWARD.value:
            return current_dir
        if array_dir == InputDirection.TURN_CLOCKWISE.value:
            return Direction.get_clockwise(current_dir)
        if array_dir == InputDirection.TURN_COUNTERCLOCKWISE.value:
            return Direction.get_counterclockwise(current_dir)

    def do_move_2(self, direction):
        self.player.move_one_step(direction)

    def do_move(self, direction):
        if self.is_next_move_possible(self.player.get_current_head_pos(), self.player.get_player_part_queue(), direction):
            self.player.move_one_step(direction)
            if self.does_player_hit_fruit(self.player.get_current_head_pos(), self.fruit.get_fruit_pos()):
                self.do_fruit()

    # temporary func
    def do_fruit(self):
        self.score += 1
        self.fruit.set_random_pos(self.player.get_player_part_queue(), self.BOARD_SIZES)
        self.player.increase_in_size_by_one()

    # TO-DO refactor
    def is_next_point_possible(self, point_pos):
        return not self.does_player_hit_itself(point_pos.x, point_pos.y, self.player.get_player_part_queue()) and self.is_within_board(point_pos.x, point_pos.y, self.BOARD_WIDTH, self.BOARD_HEIGHT)

    def is_next_move_possible(self, player_pos, player_parts_queue, direction):
        next_pos_x = player_pos.x + direction.value.x
        next_pos_y = player_pos.y + direction.value.y

        return not self.does_player_hit_itself(next_pos_x, next_pos_y, player_parts_queue) and self.is_within_board(next_pos_x, next_pos_y, self.BOARD_WIDTH, self.BOARD_HEIGHT)

    def is_within_board(self, next_pos_x, next_pos_y, board_width, board_height):
        return next_pos_x >= 0 and next_pos_x < board_width and next_pos_y >= 0 and next_pos_y < board_height

    def does_player_hit_itself(self, next_pos_x, next_pos_y, player_parts_queue):
        for part in player_parts_queue:
            part_grid_pos = part.get_grid_pos()
            if next_pos_x == part_grid_pos.x and next_pos_y == part_grid_pos.y:
                return True

        return False

    def does_player_hit_fruit(self, player_pos, fruit_pos):
        return player_pos.x == fruit_pos.x and player_pos.y == fruit_pos.y

    def can_move(self):
        result = False

        player_pos = self.player.get_current_head_pos()
        player_parts_queue = self.player.get_player_part_queue()
        directions = [Direction.LEFT, Direction.RIGHT, Direction.UP, Direction.DOWN]
        for direction in directions:
            if(self.is_next_move_possible(player_pos, player_parts_queue, direction)):
                result = True

        return result


import dummyml
import numpy as np
import pytest
import os

def test_fit():
    class_num = 10
    input_dim = 28*28
    dataset_size = 6000
    nbclsfr = dummyml.naive_bayes_classifier(input_dim,class_num)
    nbclsfr.fit(np.zeros((dataset_size,input_dim)), np.ones((dataset_size,class_num)))

    result = nbclsfr(np.ones((input_dim,)))
    assert result.size == class_num
    sum_of_result = sum(result)
    assert sum_of_result == pytest.approx(1,0.01)

def test_save_load():
    class_num = 10
    input_dim = 28*28
    dataset_size = 600
    nbclsfr = dummyml.naive_bayes_classifier(input_dim,class_num)
    nbclsfr.fit(np.zeros((dataset_size,input_dim)), np.ones((dataset_size,class_num)))

    model_dir = "./model/"
    if not os.path.exists(model_dir):
        os.mkdir(model_dir)
    model_path = model_dir + "test.dmy"
    nbclsfr.save(model_path)
    assert os.path.isfile(model_path)

    nbclsfr_2 = dummyml.naive_bayes_classifier(1,1)
    nbclsfr_2.load(model_path)
    assert nbclsfr_2(np.ones((input_dim,))).size == class_num

    with pytest.raises(Exception) as e:
        nbclsfr_2.load('./whateverFileDoesntExist.dmy')


import pandas as pd
from bs4 import BeautifulSoup as Soup
import requests
from re import match

def get_imdb_search_url(title, year):
    # produce a search url for imdb for a given title and year
    return 'https://www.imdb.com/search/title/?' + \
           'title={}&'.format(title.replace(' ', '+')) + \
           'title_type=feature&' + \
           'release_date={}-01-01,{}-12-31'.format(year-1, year+1)  # +/- 1 year as they seem to differ sometimes

def get_goodreads_search_url(title, author):
    # produce a search url for goodreads for a given title & year
    return 'https://www.goodreads.com/search?utf8=%E2%9C%93&query={}'.format((title+' '+author).replace(' ', '+'))

def imdb_rating(film):
    # returns the imdb rating for film
    # returns -1 if there are no search results for film
    # returns -2 if no exact title match, when mulitple films were found for film's name and year
    url = get_imdb_search_url(title=film['film_title'], year=film['film_year'])
    results_page = Soup(requests.get(url).text, features='html.parser')  # search for film & year and cook
    results = results_page.find_all('div', {'class': 'inline-block ratings-imdb-rating'})  # ratings-imdb-rating
    if len(results) == 0:
        return -1  # no results found for title and year
    if len(results) > 1:  # more than one result
        film_titles = results_page.find_all('h3', {'class': 'lister-item-header'})  # list search results
        film_titles = [title.find('a').get_text() for title in film_titles]  # extract titles from list
        if film['film_title'] in film_titles:
            return results[film_titles.index(film['film_title'])]['data-value']  # match title, return rating at that index
        else:
            return -2  # more than one result and no exact match to title found
    return float(results[0]['data-value'])

def remove_stars_span(goodreads_search_result):
    # cleaning
    # removes span tag in search results
    for span in goodreads_search_result.find_all('span', {'class': 'stars staticStars notranslate'}):
        span.decompose()
    return goodreads_search_result

def title_from_goodreads_url(url):
    # extract book title from url
    # '/book/show/2956.The_Adventures_of_Huckleberry_Finn?from_search=true&from_srp=true&qid=qcSdUb4S3c&rank=1'
    title = match(r'/book/show/[0-9]+[\.\-](.+)\?from_search.+', url).groups()[0]
    return title.replace('_', ' ')

def clean_up(title):
    # clean up the title for consistent searching
    out = title.lower()
    # remove any leading 'the'
    if out[:4].lower() == 'the ':
        out = out[4:]
    # remove '-', '.' and ',' characters
    out = out.replace('-', ' ').replace('.', ' ').replace('  ', ' ').replace(',', '')
    return out

def extract_rating_from_minirating_span(minirating_span):
    return float(match(r' (.+) avg rating — .+ ratings?', remove_stars_span(minirating_span).get_text()).groups()[0])

def goodreads_rating(book):
    url = get_goodreads_search_url(book['book_title'], book['book_author'])
    results_page = Soup(requests.get(url).text, features='html.parser')  # search for film & year and cook
    results = results_page.find_all('span', {'class': 'minirating'})  # get list of results
    if len(results) == 0:
        return -1  # no results found for title and year
    if len(results) > 1:
        titles = results_page.find_all('a', {'class': 'bookTitle'})  # list search results
        book_title = clean_up(book['book_title'])
        if book_title == 'adventure':
            x = 1
        result_titles = (clean_up(title_from_goodreads_url(title['href']))
                         for title in titles[:min(5, len(titles))])  # generator to extract title from results (top 5)
        i = 0  # index counter
        for result_title in result_titles:
            if result_title == book_title:
                # get rating
                return extract_rating_from_minirating_span(results[i])  # return rating at matching index
            i += 1
        return -2  # more than one result and no exact match to title found
    return extract_rating_from_minirating_span(results[0])  # return rating

# import data
books_and_films = pd.read_csv('books_and_films.csv')
# books_and_films = pd.read_csv('book_and_films_with_imdb_rating.csv').head(100)

# gather film rating from IMDb & GoodReads, and save
books_and_films['film_rating_imdb'] = books_and_films.apply(imdb_rating, axis=1)
books_and_films['book_rating_goodreads'] = books_and_films.apply(goodreads_rating, axis=1)
books_and_films.to_csv('book_and_films_with_ratings.csv', index=False)

pass


import sys
from time import time as timeSeconds
from torch import load, from_numpy
from torch import no_grad as noGradientComputing
from torch.cuda import empty_cache as cudaEmptyCache
from torch.nn import DataParallel
from numpy import float16

from torch.utils.data import Dataset, DataLoader

sys.path.append("/home/carlos/Thesis_GOD/detectron2/Pose_Estimation")
from lib.network.rtpose_vgg import get_model
from lib.config.default import update_config
from lib.config.default import _C as cfg
from lib.utils.common import CocoPart
from lib.utils.paf_to_pose import paf_to_pose_cpp
from lib.datasets.preprocessing import vgg_preprocess, rtpose_preprocess
from lib.network import im_transform

'''
MS COCO annotation order:
0: nose	   		1: l eye		2: r eye	3: l ear	4: r ear
5: l shoulder	6: r shoulder	7: l elbow	8: r elbow
9: l wrist		10: r wrist		11: l hip	12: r hip	13: l knee
14: r knee		15: l ankle		16: r ankle

The order in this work:
(0-'nose'	1-'neck' 2-'right_shoulder' 3-'right_elbow' 4-'right_wrist'
5-'left_shoulder' 6-'left_elbow'	    7-'left_wrist'  8-'right_hip'
9-'right_knee'	 10-'right_ankle'	11-'left_hip'   12-'left_knee'
13-'left_ankle'	 14-'right_eye'	    15-'left_eye'   16-'right_ear'
17-'left_ear' )
'''

class OpenPosePredictor:
    bottomBodyPartsIndex = [CocoPart.RKnee.value, CocoPart.RAnkle.value, CocoPart.LKnee.value, CocoPart.LAnkle.value,
                            CocoPart.Background.value]

    def __init__(self, args):
        """
        :param args: attributes:
            - dev: str
            - opM: path to model file
            - opB: batch size
        """
        update_config(cfg, args)
        self.devices = args.dev
        self.weights = args.opM
        self.batchSize = args.opB
        self.model = None

    def initModelForLoop(self):
        """
        Called before a predictIteration().
        """
        self.model = get_model('vgg19')
        self.model.load_state_dict(load(self.weights))
        if len(self.devices) > 0:
            self.model = DataParallel(self.model).cuda()
        self.model.float()
        self.model.eval()

    def predictIteration(self, inputs):
        """
        Returns predicted features from inputs.
        :param inputs: iterable of images.
        """
        loader = DataLoader(OpenPoseDataSet(inputs, cfg), batch_size=self.batchSize, pin_memory=True)
        nBatches = len(loader)
        processedOutputs = []
        with noGradientComputing():
            if len(self.devices) > 0:
                for i,data in enumerate(loader):
                    print("OP batch :", i + 1, "/", nBatches)
                    heatmaps, pafs = self.model(data.cuda())[0][0:2]
                    heatMapsCPU, pafsCPU = heatmaps.cpu().data.numpy().transpose(0, 2, 3,
                                                                                1), pafs.cpu().data.numpy().transpose(
                        0, 2, 3, 1)
                    for paf, heatMap in zip(pafsCPU, heatMapsCPU):
                        processedOutputs.append((paf_to_pose_cpp(paf, heatMap, cfg)))
                    del heatmaps, pafs, heatMapsCPU, pafsCPU, data
                    cudaEmptyCache()
            else:
                for data in loader:
                    output = self.model(data)
                    self.outputsModel.append(output[0][0:2])
                    self.semaphoreInputs.release()
                    del output
        self.retainUpperKeypoints(processedOutputs)
        del loader.dataset, loader
        return processedOutputs

    def __call__(self, inputs):
        """
        Initializes model and processes inputs, deletes model.
        """
        self.model = get_model('vgg19')
        self.model.load_state_dict(load(self.weights))
        if len(self.devices) > 1:
            self.model = DataParallel(self.model).cuda()
        else:
            self.model.cuda()
        self.model.float()
        self.model.eval()
        loader = DataLoader(OpenPoseDataSet(inputs, cfg), batch_size=self.batchSize, pin_memory=True)
        processedOutputs = []
        nBatches = len(loader)
        step=max(1,nBatches //10)
        ti = timeSeconds()
        with noGradientComputing():
            for i, data in enumerate(loader):
                if i%step==0:
                    print("OP batch :", i+1, "/", nBatches)
                heatmaps, pafs = self.model(data.cuda())[0][0:2]
                heatMapsCPU, pafsCPU = heatmaps.cpu().data.numpy().transpose(0, 2, 3,
                                                                                1), pafs.cpu().data.numpy().transpose(
                        0, 2, 3, 1)
                for paf, heatMap in zip(pafsCPU, heatMapsCPU):
                    processedOutputs.append((paf_to_pose_cpp(paf, heatMap, cfg)))
                del heatmaps, pafs, heatMapsCPU, pafsCPU, data
                cudaEmptyCache()
        self.retainUpperKeypoints(processedOutputs)
        ti = timeSeconds() - ti
        print("Keypoints detection :", ti, "seconds;", len(inputs) / ti, "frames per second")
        del loader.dataset, loader, self.model
        cudaEmptyCache()
        return processedOutputs

    def retainUpperKeypoints(self,outputs):
        """
        Remove bottom body parts and casts the remaining to float 16-b type.
        """
        for output in outputs:
            for human in output:
                for index, part in human.body_parts.items():
                    if index in OpenPosePredictor.bottomBodyPartsIndex:
                        del part
                    else:
                        part.x = float16(part.x)
                        part.y = float16(part.y)

class OpenPoseDataSet(Dataset):
    def __init__(self, inputs, cfg):
        self.inp_size = cfg.DATASET.IMAGE_SIZE
        self.factor = cfg.MODEL.DOWNSAMPLE
        self.inputs = inputs

    def __len__(self):
        return len(self.inputs)

    def __getitem__(self, item):
        return from_numpy(
            #vgg_preprocess(im_transform.crop_with_factor(self.inputs[item], self.inp_size, factor=self.factor,
            #                                            is_ceil=True)[0])).float()
            rtpose_preprocess(im_transform.crop_with_factor(self.inputs[item], self.inp_size, factor=self.factor,
                                is_ceil=True)[0])).float()


import copy
import numpy as np
import torch
import torch.nn.functional as F
from tqdm import tqdm
import model.PTI.dnnlib as dnnlib

def project(
        G,
        target: torch.Tensor,  # [C,H,W] and dynamic range [0,255], W & H must match G output resolution
        *,
        num_steps=1000,
        w_avg_samples=10000,
        initial_learning_rate=0.01,
        initial_noise_factor=0.05,
        lr_rampdown_length=0.25,
        lr_rampup_length=0.05,
        noise_ramp_length=0.75,
        regularize_noise_weight=1e5,
        verbose=False,
        device: torch.device,
        initial_z=None
):

    def logprint(*args):
        if verbose:
            print(*args)

    G = copy.deepcopy(G).eval().requires_grad_(False).to(device).float()    # type: ignore

    # Compute w stats.
    logprint(f'Computing W midpoint and stddev using {w_avg_samples} samples...')
    z_samples = np.random.RandomState(123).randn(w_avg_samples, G.style_dim)
    w_samples = G.get_latent(torch.from_numpy(z_samples).float().to(device)).unsqueeze(1)   # [N, L, C]
    w_samples = w_samples[:, :1, :].cpu().numpy().astype(np.float32)  # [N, 1, C]
    w_avg = np.mean(w_samples, axis=0, keepdims=True)  # [1, 1, C]
    w_avg_tensor = torch.from_numpy(w_avg).to(device)
    w_std = (np.sum((w_samples - w_avg) ** 2) / w_avg_samples) ** 0.5

    start_z = initial_z

    # Setup noise inputs.
    # noise_bufs = {name: buf for (name, buf) in G.synthesis.named_buffers() if 'noise_const' in name}

    # Load VGG16 feature detector.
    url = 'https://nvlabs-fi-cdn.nvidia.com/stylegan2-ada-pytorch/pretrained/metrics/vgg16.pt'
    with dnnlib.util.open_url(url) as f:
        vgg16 = torch.jit.load(f).eval().to(device)

    # Features for target image.
    target_images = target.unsqueeze(0).to(device).to(torch.float32)
    if target_images.shape[2] > 256:
        target_images = F.interpolate(target_images, size=(256, 256), mode='area')
    target_features = vgg16(target_images, resize_images=False, return_lpips=True)

    # pylint: disable=not-callable
    z_opt = torch.tensor(start_z, dtype=torch.float32, device=device, requires_grad=True).unsqueeze(0)

    # Init noise.
    noises = G.make_noise()
    for noise in noises:
        noise.requires_grad = True

    optimizer = torch.optim.Adam([z_opt] + noises, betas=(0.9, 0.999), lr=5e-3)

    for step in tqdm(range(num_steps)):
        w_opt = G.get_latents(z_opt)

        # Learning rate schedule.
        t = step / num_steps
        w_noise_scale = w_std * initial_noise_factor * max(0.0, 1.0 - t / noise_ramp_length) ** 2
        lr_ramp = min(1.0, (1.0 - t) / lr_rampdown_length)
        lr_ramp = 0.5 - 0.5 * np.cos(lr_ramp * np.pi)
        lr_ramp = lr_ramp * min(1.0, t / lr_rampup_length)
        lr = initial_learning_rate * lr_ramp
        for param_group in optimizer.param_groups:
            param_group['lr'] = lr

        # Synth images from opt_w.
        w_noise = torch.randn_like(w_opt) * w_noise_scale
        ws = (w_opt + w_noise)

        synth_images, _ = G([ws], input_is_latent=True, noise=noises, return_latents=False)

        # Downsample image to 256x256 if it's larger than that. VGG was built for 224x224 images.
        synth_images = (synth_images + 1) * (255 / 2)
        if synth_images.shape[2] > 256:
            synth_images = F.interpolate(synth_images, size=(256, 256), mode='area')

        # Features for synth images.
        synth_features = vgg16(synth_images, resize_images=False, return_lpips=True)
        dist = (target_features - synth_features).square().sum()

        # Noise regularization.
        reg_loss = 0.0
        for noise in noises:  # must be [1,1,H,W] for F.avg_pool2d()
            while True:
                reg_loss += (noise * torch.roll(noise, shifts=1, dims=3)).mean() ** 2
                reg_loss += (noise * torch.roll(noise, shifts=1, dims=2)).mean() ** 2
                if noise.shape[2] <= 8:
                    break
                noise = F.avg_pool2d(noise, kernel_size=2)
        loss = dist + reg_loss * regularize_noise_weight

        # Step
        optimizer.zero_grad(set_to_none=True)
        loss.requires_grad = True
        loss.backward()
        optimizer.step()
        logprint(f'step {step + 1:>4d}/{num_steps}: dist {dist:<4.2f} loss {float(loss):<5.2f}')

        # Normalize noise.
        with torch.no_grad():
            for i, noise in enumerate(noises):
                noises[i] -= noise.mean()
                noises[i] *= noise.square().mean().rsqrt()

    del G
    return z_opt


# coding=utf-8
from __future__ import absolute_import

import datetime
import os
import re
from zipfile import ZipFile

import octoprint.filemanager.util
import octoprint.plugin
from octoprint.util import RepeatedTimer

class UltimakerFormatPackagePlugin(octoprint.plugin.SettingsPlugin,
								   octoprint.plugin.AssetPlugin,
								   octoprint.plugin.TemplatePlugin,
								   octoprint.plugin.EventHandlerPlugin,
								   octoprint.plugin.SimpleApiPlugin):

	def __init__(self):
		self._fileRemovalTimer = None
		self._fileRemovalLastDeleted = {}
		self._fileRemovalLastAdded = {}
		self._folderRemovalTimer = None
		self._folderRemovalLastDeleted = {}
		self._folderRemovalLastAdded = {}
		self._waitForAnalysis = False
		self._analysis_active = False
		self.regex_extension = re.compile("\.(?:gco(?:de)?(?:\.ufp)?)$")

	##~~ SettingsPlugin mixin

	def get_settings_defaults(self):
		return {'installed': True, 'installed_version': self._plugin_version, 'inline_thumbnail': False,
				'scale_inline_thumbnail': False, 'inline_thumbnail_scale_value': "50",
				'inline_thumbnail_position_left': False, 'align_inline_thumbnail': False,
				'inline_thumbnail_align_value': "left", 'state_panel_thumbnail': True,
				'state_panel_thumbnail_scale_value': "100", 'state_panel_thumbnail_add_break': False,
				'resize_filelist': False, 'filelist_height': "306", 'scale_inline_thumbnail_position': False}

	##~~ AssetPlugin mixin

	def get_assets(self):
		return {'js': ["js/UltimakerFormatPackage.js"], 'css': ["css/UltimakerFormatPackage.css"]}

	##~~ TemplatePlugin mixin

	def get_template_configs(self):
		return [
			{'type': "settings", 'custom_bindings': False, 'template': "UltimakerFormatPackage_settings.jinja2"},
		]

	##~~ EventHandlerPlugin mixin

	def on_event(self, event, payload):
		if event not in ["FileAdded", "FileRemoved", "MetadataAnalysisStarted", "MetadataAnalysisFinished",
						 "FolderRemoved", "FolderAdded"]:
			return

		if event == "FolderRemoved" and payload["storage"] == "local":
			self._logger.debug("Folder removed %s" % payload["name"])
			self._folderRemovalLastDeleted[payload["name"]] = payload
			self._folder_removal_timer_start()
		if event == "FolderAdded":
			self._logger.debug("Folder added %s" % payload["name"])
			self._folderRemovalLastAdded[payload["name"]] = payload

		# Hack that deletes uploaded ufp file from upload path
		if event == "FileAdded" and "ufp" in payload["type"]:
			old_name = payload["path"]  # self._settings.global_get_basefolder("uploads") + "/" +
			ufp_file = self.get_plugin_data_folder() + "/" + payload["path"]
			if os.path.exists(ufp_file):
				os.remove(ufp_file)
			self._file_manager.remove_file("local", old_name)
			return
		if event == "MetadataAnalysisStarted" and payload["path"].endswith(".gcode"):
			self._waitForAnalysis = True
			return
		if event == "MetadataAnalysisFinished" and payload["path"].endswith(".gcode"):
			self._waitForAnalysis = False
			return
		if event == "FileAdded" and payload["path"].endswith(".gcode"):
			self._logger.debug("File added %s" % payload["name"])
			self._fileRemovalLastAdded[payload["name"]] = payload
		if event == "FileRemoved" and payload["name"].endswith(".gcode"):
			self._logger.debug("File removed %s" % payload["name"])
			self._fileRemovalLastDeleted[payload["name"]] = payload
			self._file_removal_timer_start()
			return

	##~~ Folder Removal Timer

	def _folder_removal_timer_start(self):
		if self._folderRemovalTimer is None:
			self._logger.debug("Starting removal timer.")
			self._folderRemovalTimer = RepeatedTimer(5, self._folder_removal_timer_task)
			self._folderRemovalTimer.start()

	def _folder_removal_timer_stop(self):
		self._logger.debug("Cancelling timer and setting everything None.")
		if self._folderRemovalTimer is not None:
			self._folderRemovalTimer.cancel()
			self._folderRemovalTimer = None

	def _folder_removal_timer_task(self):
		if self._waitForAnalysis:
			return

		for key in list(self._folderRemovalLastDeleted):
			if self._folderRemovalLastAdded.get(key, False):
				folder_src = self.get_plugin_data_folder() + "/" + self._folderRemovalLastDeleted[key]["path"]
				folder_dest = self.get_plugin_data_folder() + "/" + self._folderRemovalLastAdded[key]["path"]
				self._logger.debug("Folder moved from: {} to: {}".format(folder_src, folder_dest))
				if os.path.exists(folder_src):
					import shutil
					shutil.move(folder_src, folder_dest)
					file_list = self._file_manager.list_files(path=self._folderRemovalLastAdded[key]["path"],
															  recursive=True)
					local_files = file_list["local"]
					results = {'no_thumbnail': [], 'no_thumbnail_src': []}
					for file_key, file in local_files.items():
						results = self._process_gcode(local_files[file_key], results)
					self._logger.debug("Scan results: {}".format(results))

				self._folderRemovalLastAdded.pop(key)
			else:
				self._logger.debug("Folder deleted: {}".format(self._folderRemovalLastDeleted[key]["path"]))
				import shutil
				shutil.rmtree(self.get_plugin_data_folder() + "/" + self._folderRemovalLastDeleted[key]["path"],
							  ignore_errors=True)
				self._folderRemovalLastDeleted.pop(key)

		self._folder_removal_timer_stop()
		self._event_bus.fire("UpdatedFiles", {"type": "printables"})

	##~~ File Removal Timer

	def _file_removal_timer_start(self):
		if self._fileRemovalTimer is None:
			self._logger.debug("Starting removal timer.")
			self._fileRemovalTimer = RepeatedTimer(5, self._file_removal_timer_task)
			self._fileRemovalTimer.start()

	def _file_removal_timer_stop(self):
		self._logger.debug("Cancelling timer and setting everything None.")
		if self._fileRemovalTimer is not None:
			self._fileRemovalTimer.cancel()
			self._fileRemovalTimer = None

	def _file_removal_timer_task(self):
		if self._waitForAnalysis:
			return
		for key in list(self._fileRemovalLastDeleted):
			thumbnail = "{}/{}".format(self.get_plugin_data_folder(),
									   self.regex_extension.sub(".png", self._fileRemovalLastDeleted[key]["path"]))
			ufp_file = "{}/{}".format(self.get_plugin_data_folder(),
									  self.regex_extension.sub(".png", self._fileRemovalLastDeleted[key]["path"]))
			gcode_file = "%s/%s" % (self.get_plugin_data_folder(), self._fileRemovalLastDeleted[key]["path"])
			# clean up double slashes
			thumbnail = thumbnail.replace("//", "/")
			ufp_file = ufp_file.replace("//", "/")
			gcode_file = gcode_file.replace("//", "/")
			if self._fileRemovalLastAdded.get(key, False):
				# copy thumbnail to new path and update metadata
				thumbnail_new = "{}/{}".format(self.get_plugin_data_folder(), self.regex_extension.sub(".png",
																									   self._fileRemovalLastAdded[
																										   key][
																										   "path"]))
				thumbnail_new = thumbnail_new.replace("//", "/")
				thumbnail_new_path = os.path.dirname(thumbnail_new)
				self._logger.debug(thumbnail)
				self._logger.debug(thumbnail_new)
				self._logger.debug(thumbnail_new_path)
				if not os.path.exists(thumbnail_new_path):
					os.makedirs(thumbnail_new_path)
				if os.path.exists(thumbnail_new):
					os.remove(thumbnail_new)
				if thumbnail != thumbnail_new and os.path.exists(thumbnail):
					os.rename(thumbnail, thumbnail_new)
				if os.path.exists(thumbnail_new):
					self._logger.debug("Updating thumbnail url.")
					thumbnail_url = "plugin/UltimakerFormatPackage/thumbnail/{}?{:%Y%m%d%H%M%S}".format(
						self.regex_extension.sub(".png", self._fileRemovalLastAdded[key]["path"]),
						datetime.datetime.now()).replace("//", "/")
					self._file_manager.set_additional_metadata("local", self._fileRemovalLastAdded[key]["path"],
															   "thumbnail", thumbnail_url, overwrite=True)
					self._file_manager.set_additional_metadata("local", self._fileRemovalLastAdded[key]["path"],
															   "thumbnail_src", self._identifier, overwrite=True)

				self._fileRemovalLastAdded.pop(key)

			# remove files just in case they are left behind.
			if os.path.exists(thumbnail):
				os.remove(thumbnail)
			if os.path.exists(ufp_file):
				os.remove(ufp_file)
			if os.path.exists(gcode_file):
				os.remove(gcode_file)

			self._fileRemovalLastDeleted.pop(key)

		self._file_removal_timer_stop()

	##~~ Utility Functions

	def deep_get(self, d, keys, default=None):
		"""
		Example:
			d = {'meta': {'status': 'OK', 'status_code': 200}}
			deep_get(d, ['meta', 'status_code'])		  # => 200
			deep_get(d, ['garbage', 'status_code'])	   # => None
			deep_get(d, ['meta', 'garbage'], default='-') # => '-'
		"""
		assert type(keys) is list
		if d is None:
			return default
		if not keys:
			return d
		return self.deep_get(d.get(keys[0]), keys[1:], default)

	##~~ SimpleApiPlugin mixin

	def _process_gcode(self, gcode_file, results=[]):
		self._logger.debug(gcode_file["path"])
		if gcode_file.get("type") == "machinecode":
			self._logger.debug(gcode_file.get("thumbnail"))
			if gcode_file.get("path", False):
				png_path = self.regex_extension.sub(".png", gcode_file["path"])
				full_path = self.get_plugin_data_folder() + "/" + png_path
				self._logger.debug("Checking if {} exists".format(full_path))
				if os.path.exists(full_path):
					results["no_thumbnail_src"].append(gcode_file["path"])
					self._logger.debug("Setting metadata for %s" % gcode_file["path"])
					thumbnail_url = "plugin/UltimakerFormatPackage/thumbnail/{}?{:%Y%m%d%H%M%S}".format(png_path,
																										datetime.datetime.now()).replace(
						"//", "/")
					self._file_manager.set_additional_metadata("local", gcode_file["path"], "thumbnail", thumbnail_url,
															   overwrite=True)
					self._file_manager.set_additional_metadata("local", gcode_file["path"], "thumbnail_src",
															   self._identifier, overwrite=True)
				elif gcode_file.get("thumbnail_src") == self._identifier:
					results["no_thumbnail"].append(gcode_file["path"])
					self._logger.debug("Removing metadata for %s" % gcode_file["path"])
					self._file_manager.remove_additional_metadata("local", gcode_file["path"], "thumbnail_src")
					self._file_manager.remove_additional_metadata("local", gcode_file["path"], "thumbnail")
				else:
					results["no_thumbnail"].append(gcode_file["path"])
		elif gcode_file.get("type") == "folder" and not gcode_file.get("children") is None:
			children = gcode_file["children"]
			for key, file in children.items():
				self._process_gcode(children[key], results)
		return results

	def get_api_commands(self):
		return {'crawl_files': []}

	def on_api_command(self, command, data):
		import flask
		from octoprint.server import user_permission
		if not user_permission.can():
			return flask.make_response("Insufficient rights", 403)

		if command == "crawl_files":
			self._logger.debug("Crawling Files")
			file_list = self._file_manager.list_files(recursive=True)
			local_files = file_list["local"]
			results = {'no_thumbnail': [], 'no_thumbnail_src': []}
			for key, file in local_files.items():
				results = self._process_gcode(local_files[key], results)
			return flask.jsonify(results)

	##-- UFP upload extenstion tree hook
	def get_extension_tree(self, *args, **kwargs):
		return {'machinecode': {'ufp': ["ufp"]}}

	##~~ UFP upload preprocessor hook
	def ufp_upload(self, path, file_object, links=None, printer_profile=None, allow_overwrite=True, *args, **kwargs):
		ufp_extensions = [".ufp"]
		name, extension = os.path.splitext(file_object.filename)
		if extension in ufp_extensions:
			ufp_filename = self.get_plugin_data_folder() + "/" + path
			png_filename = ufp_filename.replace(".ufp", ".png")
			gco_filename = ufp_filename.replace(".ufp", ".gcode")
			ufp_filepath = os.path.dirname(ufp_filename)

			if not os.path.exists(ufp_filepath):
				os.makedirs(ufp_filepath)

			file_object.save(ufp_filename)
			with ZipFile(ufp_filename, 'r') as zipObj:
				try:
					with open(png_filename, 'wb') as thumbnail:
						thumbnail.write(zipObj.read("/Metadata/thumbnail.png"))
				except KeyError:
					png_filename = None
				with open(gco_filename, 'wb') as f:
					f.write(zipObj.read("/3D/model.gcode"))

			file_wrapper = octoprint.filemanager.util.DiskFileWrapper(path.replace(".ufp", ".gcode"), gco_filename,
																	  move=True)
			uploaded_file = self._file_manager.add_file("local", file_wrapper.filename, file_wrapper,
														allow_overwrite=True)

			if png_filename:
				self._logger.debug('Adding thumbnail url to metadata')
				thumbnail_path = path.replace(".ufp", ".png")
				thumbnail_url = "plugin/UltimakerFormatPackage/thumbnail/{}?{:%Y%m%d%H%M%S}".format(thumbnail_path,
																									datetime.datetime.now())
				self._file_manager.set_additional_metadata("local", uploaded_file, "thumbnail", thumbnail_url,
														   overwrite=True)
				self._file_manager.set_additional_metadata("local", uploaded_file, "thumbnail_src", self._identifier,
														   overwrite=True)

			return octoprint.filemanager.util.DiskFileWrapper(path, ufp_filename)
		return file_object

	##~~ Routes hook
	def route_hook(self, server_routes, *args, **kwargs):
		from octoprint.server.util.tornado import LargeResponseHandler, path_validation_factory
		from octoprint.util import is_hidden_path
		return [
			(r"thumbnail/(.*)", LargeResponseHandler,
			 {'path': self.get_plugin_data_folder(), 'as_attachment': False, 'path_validation': path_validation_factory(
				 lambda path: not is_hidden_path(path), status_code=404)})
		]

	def additional_excludes_hook(self, excludes, *args, **kwargs):
		if "uploads" in excludes:
			return ["."]
		return []

	##~~ Softwareupdate hook

	def get_update_information(self):
		return {'UltimakerFormatPackage': {'displayName': "Cura Thumbnails", 'displayVersion': self._plugin_version,
										   'type': "github_release", 'user': "jneilliii",
										   'repo': "OctoPrint-UltimakerFormatPackage", 'current': self._plugin_version,
										   'stable_branch': {'name': "Stable", 'branch': "master",
															 'comittish': ["master"]}, 'prerelease_branches': [
				{'name': "Release Candidate", 'branch': "rc", 'comittish': ["rc", "master"]}
			], 'pip': "https://github.com/jneilliii/OctoPrint-UltimakerFormatPackage/archive/{target_version}.zip"}}

__plugin_name__ = "Cura Thumbnails"
__plugin_pythoncompat__ = ">=2.7,<4"

def __plugin_load__():
	global __plugin_implementation__
	__plugin_implementation__ = UltimakerFormatPackagePlugin()

	global __plugin_hooks__
	__plugin_hooks__ = {
		"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information,
		"octoprint.filemanager.extension_tree": __plugin_implementation__.get_extension_tree,
		"octoprint.filemanager.preprocessor": __plugin_implementation__.ufp_upload,
		"octoprint.server.http.routes": __plugin_implementation__.route_hook,
		"octoprint.plugin.backup.additional_excludes": __plugin_implementation__.additional_excludes_hook
	}

{'shutil': 'shutil', 'flask': 'flask', 'user_permission': 'octoprint.server.user_permission', 'LargeResponseHandler': 'octoprint.server.util.tornado.LargeResponseHandler', 'path_validation_factory': 'octoprint.server.util.tornado.path_validation_factory', 'is_hidden_path': 'octoprint.util.is_hidden_path'}


import argparse
import orjson

from temperature_ranges import quartile_range_generator, temperature_transformer

def init_argparser():
    parser = argparse.ArgumentParser(allow_abbrev=False)
    parser.add_argument("-f","--file", type=str, required=True)

    return parser

if __name__ == "__main__":
    parser = init_argparser()

    args = parser.parse_args()

    temperature_data = {}

    with open(args.file, 'r') as fptr:
        temperature_data = orjson.loads(fptr.read())

    transformed_data = temperature_transformer.transformer(
        temperature_data
    )

    ranges = quartile_range_generator.quartile(transformed_data)

    print(ranges)


#!/usr/bin/env python3

import subprocess
import os
import os.path
import unittest
import sys
from typing import List, Optional
import re

tc = unittest.TestCase()
tc.maxDiff = None
assertEquals = tc.assertEquals

PROJECT_FOLDER = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))

GUID = re.compile(
    r'.*[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}.*')
JAVA_VERSION = re.compile(r'.*Java version:.*vendor: Oracle Corporation.*')

def compare_lines(expected: str, actual: str) -> None:
    expected_lines = expected.splitlines()
    actual_lines = actual.splitlines()

    error_found = False

    if (len(expected_lines) != len(actual_lines)):
        error_found = True
        print("Expected %d lines, found %d lines." %
              (len(expected_lines), len(actual_lines)))

    for i in range(min(len(expected_lines), len(actual_lines))):
        if expected_lines[i] == actual_lines[i]:
            continue

        if GUID.match(expected_lines[i]) and GUID.match(actual_lines[i]):
            continue

        if JAVA_VERSION.match(expected_lines[i]) and JAVA_VERSION.match(actual_lines[i]):
            continue

        error_found = True
        print("%d: expected: %s" % (i, expected_lines[i]))
        print("%d: actual  : %s" % (i, actual_lines[i]))

    if error_found:
        with open("/tmp/expected.txt", mode='w', encoding='utf-8') as f:
            f.writelines(expected_lines)
        with open("/tmp/actual.txt", mode='w', encoding='utf-8') as f:
            f.writelines(actual_lines)
        print("Comparison differences found")
        sys.exit(1)

def run_single_test(folder_name: str) -> None:
    run_external_process_test(folder_name, "jenny-expected.txt")

def run_single_info_test(folder_name: str) -> None:
    run_external_process_test(folder_name,
                              "jenny-expected-info.txt",
                              ["--info"])

def run_external_process_test(folder_name: str,
                              expected_output_file_name: str,
                              extra_parameters: List[str] = None) -> None:
    if extra_parameters is None:
        extra_parameters = []

    print("Testing: {0} ({1})".format(folder_name, " ".join(extra_parameters)))

    expected_file = None  # type: Optional[str]
    current_folder = os.curdir

    search_folder = "{0}/{1}".format(PROJECT_FOLDER, folder_name)

    os.chdir(search_folder)

    for folder, folders, files in os.walk(search_folder):
        if expected_output_file_name in files:
            expected_file = "{0}/{1}".format(folder, expected_output_file_name)
            break

    popen_parameters = ["%s/jenny" % PROJECT_FOLDER, "--keepLog"]
    popen_parameters.extend(extra_parameters)

    p = subprocess.Popen(popen_parameters,
                         stdin=subprocess.PIPE,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)

    stdout, stderr = p.communicate()  # type: bytes, bytes
    error_code = p.returncode

    process_output = stdout.decode('utf-8')

    if error_code != 0 and 'fail' not in folder_name:
        print("Program failed with error code: %d" % error_code)
        # print("Program STDOUT: %s" % process_output)
        # print("Program STDERR: %s" % stderr.decode('utf-8'))

    assert expected_file

    with open(expected_file) as f:
        expected_content = f.read()
        compare_lines(expected_content, process_output)

    if error_code != 0 and 'fail' not in folder_name:
        print("Even if the output was equal, the program exited with "
              "exit code: %d" % error_code)
        sys.exit(1)

    os.chdir(current_folder)

tests_to_run = [
    "features/ansiColor-support",
    "features/archiveArtifacts",
    "features/build-environment-variables",
    "features/checkout-preserves-permissions",
    "features/child-section-skip/parent",
    "features/credentials-in-container",
    "features/current-build",
    "features/different-work-folder/parent",
    "features/dir-step",
    "features/external-classes",
    "features/failing-project",
    "features/failing-sh-inside-docker",
    "features/library-annotation-mock",
    "features/mock-missing-functions",
    "features/multiple-nodes",
    "features/overwrite-environment-variables",
    "features/parameters-boolean-value",
    "features/stash-unstash",
    "features/testset/parent",
    "features/upstream-pipeline-trigger",

    # these tests need docker
    "features/write-file",
    "features/sh-support",

    "features/docker-user-id-inside",
    "features/docker-support",
    "features/junit-support"
]

if len(sys.argv) > 1:
    tests_to_run = sys.argv[1:]

for test in tests_to_run:
    run_single_test(test)
    run_single_info_test(test)


#!/usr/bin/env python

from __future__ import print_function

import argparse
import time
import sys

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

def pir_read(pir_pin):
    GPIO.setup(pir_pin, GPIO.IN)  # activate input
    return GPIO.input(pir_pin)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='motionsensor')
    parser.add_argument("--pin", type=int, default=23)
    parser.add_argument("--outfile", "-o", type=str, default="/tmp/motionsensor.value")
    parser.add_argument("--debug", action="store_true")
    options = parser.parse_args()

    if options.debug:
        print("using pin %d" % options.pin)

    while True:
        value = pir_read(options.pin)
        if options.debug:
            print("%s: " % time.asctime(), file=sys.stderr, end='')
            print(value)
        with open(options.outfile, "wb") as f:
            f.write("%d" % value)
        time.sleep(0.5)


#!/usr/bin/env python3
"""The script provides a GUI interface for converting bibtex to the markdown style which is used in this repo.
The user may need to install these external packages:

Usage:
    pip install bibtexparser PyQt5
    ./ref_convert.py

Author:
    weipeng0098@126.com - 2021/8/10 17:16

Version:
    0.0.1

"""

import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QPlainTextEdit, QFormLayout, QApplication
from bibtexparser.bparser import BibTexParser
import bibtexparser
import re

def handle_title(_title: str):
    _title = re.compile('[{}]').sub('', _title.strip())
    return _title

def handle_author(author: str):
    author = ', '.join(list(map(lambda x: ' '.join(x.strip().split(', ')[::-1]), author.split('and'))))
    return author

def handle_url(url: str):
    try:
        arxiv_identifier = re.compile('http://arxiv.org/abs/([\d\.]+)').findall(url)[0]
        url = f'http://arxiv.org/pdf/{arxiv_identifier}.pdf'
    except:
        pass
    return url

def bib_parser(bibref: str):
    parser = BibTexParser(common_strings=True)
    parser.ignore_nonstandard_types = False
    parser.homogenise_fields = False
    bib = bibtexparser.loads(bibref, parser)

    lines = []

    for entry in bib.entries:
        title = handle_title(entry['title'])
        author = handle_author(entry['author'])
        try:
            journal = entry['journal']
        except:
            journal = '**UNKNOWN_JOURNAL**'

        try:
            year = entry['year']
        except:
            year = '**UNKNOWN_YEAR**'
        try:
            url = entry['url']
            url = handle_url(url)
        except:
            url = ''
        lines.append(f"1. **{title}**, *{author}*, {journal}, {year}. [[paper]({url})][[code]()]")
    target = '\n'.join(lines)
    return target

def bib_convert():
    bibtex_str = bib_parser(bibtexEdit.toPlainText())
    targetEdit.setPlainText(bibtex_str)

app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle('Bibtex-Markdown converter')
layout = QFormLayout()

bibtexEdit = QPlainTextEdit()
layout.addRow('bibtex:', bibtexEdit)
bibtexEdit.setFixedWidth(1000)

targetEdit = QPlainTextEdit()
layout.addRow('markdown:', targetEdit)
targetEdit.setFixedWidth(1000)

btn = QPushButton('Convert')
btn.clicked.connect(bib_convert)
layout.addRow('Convert', btn)

btn = QPushButton('Clear')
btn.clicked.connect(bibtexEdit.clear)
btn.clicked.connect(targetEdit.clear)
layout.addRow('Clear', btn)

window.setLayout(layout)
window.show()
sys.exit(app.exec_())


""" gRPC server """

from concurrent import futures
import logging
import time
from typing import Iterable

import grpc

from helloworld import helloworld_pb2, helloworld_pb2_grpc

class Greeter(helloworld_pb2_grpc.GreeterServicer):
    def SayHello(
        self,
        request: helloworld_pb2.HelloRequest,
        context: grpc.ServicerContext
    ) -> helloworld_pb2.HelloReply:
        return helloworld_pb2.HelloReply(message=f'Hello, {request.name}!')

    def SayHelloStreamReply(
        self,
        request: helloworld_pb2.HelloRequest,
        context: grpc.ServicerContext
    ) -> Iterable[helloworld_pb2.HelloReply]:
        print(f'got request: {request.name}')
        for _ in range(10):
            yield helloworld_pb2.HelloReply(message=f'Hello, {request.name}!')
            time.sleep(1)

def serve():
    port = '50051'

    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    helloworld_pb2_grpc.add_GreeterServicer_to_server(
        Greeter(), server)

    server.add_insecure_port('[::]:' + port)
    server.start()

    print("Server started, listening on " + port)
    server.wait_for_termination()

if __name__ == '__main__':
    logging.basicConfig()
    serve()


import json

import rackClass
import deviceClass

def populateDevices(VAC):
    device = deviceClass.Device()
    device.initializeDeviceData()
    device.collectDeviceData(VAC)
    deviceData = device.deviceData

    return deviceData

def readDevices(dev, VAC):
    deviceData = list()
    devicePower = list()
    for d in dev:
        device = deviceClass.Device()
        device.readDeviceData(d)
        device.computeData(VAC)
        deviceData.append(device.deviceData)
        devicePower.append(device.deviceKW)

    return deviceData, devicePower

def writeOut(rackOutput):
    with open("rackAssessment.json", "w") as o:
        o.write(json.dumps(rackOutput, indent=4))

    return print("File successfully written")

def main():
    rackList = list()
    rackOutput = dict()
    VAC = 120
    count = 1
    mode = 1

    # Mode indicates if the process is manual or reads from template JSON
    # 0 = manual and 1 = read from file
    if mode == 0:
        rackAmount = input("How many racks in datacenter?: ")
        for i in range(rackAmount):
            rackList.append(rackClass.Rack())

        for rack in rackList:
            rack.initializeData()
            deviceAmount = input(f"How many devices in {rack.name}: ")
            for i in range(int(deviceAmount)):
                deviceData = populateDevices(VAC)
                rack.deviceList.append(deviceData)
            rackOutInfo = rack.rackData()
            rackOutput.update({f"Rack_{count}": rackOutInfo})
            count += 1
    else:
        rackJSON = list()
        allDevices = list()
        rackBTU = list()
        rackAmount = 0

        with open("rackTemplate.json", "r") as rackTemplate:
            template = json.load(rackTemplate)

        for i in template:
            rackList.append(rackClass.Rack())
            rackDetail = template.get(i)
            rackJSON.append(rackDetail)
            deviceJSON = rackDetail.get("deviceList")
            allDevices.append(deviceJSON)

        for rack in rackList:
            for d in rackJSON:
                rack.readData(d)
            for dev in allDevices:
                deviceData, devicePower = readDevices(dev, VAC)
                rack.deviceList.append(deviceData)
                rack.maxKWPerRack(devicePower)
                rack.totalRackBTU()
            rackOutInfo = rack.rackData()
            rackOutput.update({f"Rack_{count}": rackOutInfo})
            count += 1

    writeOut(rackOutput)

if __name__ == "__main__":
    main()


#!/usr/bin/env python
from collections import UserList
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D  # noqa  # Ignore complaints about Axes3D not being used

class Plot3D:

    def __init__(self, *, xlim=(-100, 400), ylim=(-400, 400), zlim=(-50, 500)):
        self.fig = plt.figure()
        self.ax = self.fig.add_subplot(111, projection='3d')
        self.ax.set_xlim(*xlim)
        self.ax.set_ylim(*ylim)
        self.ax.set_zlim(*zlim)

        plt.show(block=False)
        self.fig.canvas.draw()
        self.fig.canvas.flush_events()
        self.background = self.fig.canvas.copy_from_bbox(self.ax.bbox)

        self.plots = custom_list()
        self.get_next_color = self._next_color()

    def update(self, *args):
        """Updates the plot with given points.

        Plot is redrawn with line plots updated to go through given points.
        (Assume base starts at (0,0,0)

        Args:
            End point of each section
        """
        self.fig.canvas.restore_region(self.background)
        points = [(0, 0, 0), *args]
        for i in range(1, len(points)):
            plot = self.plots.setdefault(self, i - 1)  # Because of the extra (0,0,0) the index is off
            current_point = points[i]
            prior_point = points[i - 1]
            plot.set_xdata([prior_point[0], current_point[0]])
            plot.set_ydata([prior_point[1], current_point[1]])
            plot.set_3d_properties([prior_point[2], current_point[2]])

        for i, plot in enumerate(self.plots):
            if i < len(args):
                self.ax.draw_artist(plot)

        self.fig.canvas.blit(self.ax.bbox)
        self.fig.canvas.flush_events()

    def _next_color(self):
        while True:
            yield 'ro-'
            yield 'ro-'
            yield 'go-'
            yield 'go-'
            yield 'bo-'
            yield 'bo-'

    def close(self):
        plt.close(self.fig)

class custom_list(UserList):

    def get(self, index, default=None):
        try:
            return self.data[index]
        except IndexError:
            return default

    def setdefault(self, parent, index):
        try:
            return self.data[index]
        except IndexError:
            default = parent.ax.plot([0, 1], [0, 1], [0, 1], next(parent.get_next_color))[0]
            self.data.append(default)
            return default

if __name__ == '__main__':
    from time import sleep
    plot3d = Plot3D()
    points = [
        [(50, 50, 50), (50, 50, 150), (50, 50, 250), (150, 50, 250), (250, 50, 250), (250, 150, 250)],
        [(50, 50, 50), (50, 50, 150), (50, 50, 250), (150, 50, 250)],
        [(50, 50, 50), (50, 50, 150), (50, 50, 250), (150, 50, 250), (250, 50, 250), (250, 150, 250)],
    ]

    for point in points:
        plot3d.update(*point)
        sleep(5)


'''
Note about the script:
The python script to parse the sample FASTQ files, merge lanes and save it into gz files.

Required Packages: Biopython, Regex(not standard Python regex), numpy, pandas, os, glob

The output of this script will be:
	1.An 'analyzed' folder with a sub folder for each sample
	2.The folder for each sample contains an 'extractedBarcodes' folder which will contain 4 files:
		a. sampleName_counts or sampleName_counts_liberal - contains the barcode sequence, number of barcodes counted and number of UMIs associated
		b. sampleName_UMICounts or sampleName_UMICounts_liberal - contains the barcode sequence along with number of associated UMIs
		c. sampleName_UMIs or sampleName_UMIs_liberal - contains the barcode sequence, its quality score for first instance and the list of associated UMIs
		d. sampleName_readCountsOnly or sampleName_readCountsOnly_liberal - contains the barccode sequence and its count number
	3. If excluded reads is true, more files which contain details about bad samples are also outputted to the same folder. It will contain details of barcodes missing vector sequences, having bad quality score or having four repeated bases contiguously
	4. A summary text file containing details about length of barcode dictionary, number of UMIs and number of bad Barcodes classified into different issues.

Command to run this file: python3 <path to Envelope.py> <path to Experiment directory> <path to Script> "--staggerFile" <path to Stagger File> "-r", "--checkVector", args.checkVector,"-l", args.barcodeLength, "-Q",args.minPhred ,"-e", args.excludeReads

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------'''

import os
import subprocess
import csv
from argparse import ArgumentParser
import glob
import multiprocessing

# Define the worker function for processing each sample
def process_sample(sample_info):
    sample, stagger, additional_args = sample_info
    command = ["python3", pathExtractionScript, args.experiment, sample, "-s", stagger] + additional_args
    # print(f"Processing sample: {sample}")
    subprocess.run(command)

if __name__ == "__main__":
    # ... (your existing code to parse command line arguments)
    parser = ArgumentParser()
    parser.add_argument("experiment", help = "Specify the path to the experiment directory")
    parser.add_argument("pathScript", help = "Specify the path containing the script files.", type = str)
    parser.add_argument("--pathStaggerFile", help = "Specify the path to the file containing information on length of stagger for each sample")
    parser.add_argument("-r", "--includeReads", help = "If specified, output additional tables with barcodes and only read counts or UMI counts. Otherwise outputs only one table with both counts", action = 'store_true')
    parser.add_argument("-checkVector", help = "Option to check vector sequence before or on both sides of the barcode sequence.", default = "both", choices = ["both", "before"])
    parser.add_argument("-barcodeLength", help = "If check_vector before specified, input here your desired barcode length. Default is 100", default = "100", type = str)
    parser.add_argument("-Q", "--minPhred", help = "Specify the minimum phredscore required to include a readout. Filters reads with more than 5 bases before the barcode with low phredscore.", default = "14", type = str)
    parser.add_argument("-e", "--excludedReads", help = "If specified, output txt.gz files containing reads excluded from the UMI and count files.")
    args = parser.parse_args()

    # pathExtractionScript is the location to the file that has the script to extract barcode
    pathExtractionScript = os.path.join(args.pathScript,"Step1_extractBarcode","parseFastqMain.py" )

    #Move to experiment directory
    os.chdir(args.experiment)

    # Including Stagger details for each sample
    if args.pathStaggerFile is not None:
        samples = []
        staggers = []
        with open(args.pathStaggerFile, 'r') as file:
            tmp = csv.reader(file)
            for line in tmp:
                samples.append(line[0])
                staggers.append(str(line[1]))
    else:
        samples = [os.path.basename(i) for i in glob.glob("raw/*")]
        staggers = ['0'] * len(samples)

    print(samples)

    #Format additional arguments
    additionalArguments = ["-checkVector", args.checkVector, "--minPhred", args.minPhred]
    if args.includeReads:
        additionalArguments.extend(["--includeReads"])
    if args.checkVector == "before":
        additionalArguments.extend(["-barcodeLength", args.barcodeLength])
    if args.excludedReads == "True":
        additionalArguments.append(["--excludedReads"])

    # Create a list of sample information tuples
    sample_info_list = [(sample, stagger, additionalArguments) for sample, stagger in zip(samples, staggers)]

    # Number of worker processes to use (adjust as needed)
    num_processes = multiprocessing.cpu_count()

    # Create a multiprocessing pool
    with multiprocessing.Pool(num_processes) as pool:
        # Distribute the work across processes for each sample
        pool.map(process_sample, sample_info_list)

    print("All samples processed.")


import pandas as pd
from shutil import copyfile
import os
import sys
import re
import datetime
import argparse
import ProgressBar

def count_sample(label_list, df_data):
    print("----"*8)
    for key in label_list.keys():
        print(label_list[key]+":", (df_data['labeling'] == key).sum())
    print("----"*8)

def create_data_file(df_data, label_list, complete_data='./complete_data.txt', sampled_data='./sampled_data.txt'):

    if not os.path.exists(sampled_data):
        # 观察当前数据集样本分布
        count_sample(label_list, df_data)

        # 修改文件格式
        df_data['file_name'] = df_data['file_name'].map(lambda s: re.sub(r'[^\.]\w*$', 'tiff', s))
        # 生成新的格式的完整标签文件
        df_data.to_csv(complete_data, sep=" ", index=False)

        # 从每一个category随机抽取1000个样本
        df = pd.DataFrame()
        for key in label_list.keys():
            df = df.append( df_data[df_data['labeling']==key].sample(1000, axis=0) )
        df = df.reset_index(drop=True)

        # 观察随机采样后数据集的样本分布
        count_sample(label_list, df)
        # 生成抽样后的标签文件
        df.to_csv(sampled_data, sep=" ", index=False)
        print("create complete_data sampled_data...")
    else:
        print(sampled_data + " is existed")

def  batch_copy(label_list, sampled_data='./sampled_data.txt', dataset_path='./drive/MyDrive/Dataset/GeoTIFF/', source_path='./GeoTIFF/'):
    # 读取 sampled_data
    df = pd.read_table(sampled_data, sep=" ")

    # 判断复制路径是否存在
    if not os.path.exists(dataset_path):
        for key in label_list.keys():
            os.makedirs(dataset_path+key)
        print('create copy path...')
    else:
        print('target path ' + dataset_path + " is existed")

    # 判断源数据集是否存在
    if not os.path.exists(source_path):
        print('can not find source dataset')
        return

    # 创建日志
    log_path = './log.txt'
    line_num = 1
    if not os.path.exists(log_path):
        with open(log_path, 'w') as f:
            nowtime = datetime.datetime.now().strftime('%Y-%m-%d-%H:%M:%S')
            f.write('create time: ' + nowtime + '\n')
        print('create log...')
    else:
        with open(log_path, 'r') as f:
            line = f.readlines()
            line_num = len(line)
        print(line_num)

    # 绘制progeress bar
    pb = ProgressBar.ProgressBar(len(df))
    # 复制文件到Google drive中
    start_loc = line_num - 1
    with open(log_path,'a') as f:
        for i in range(start_loc, len(df)):
            file_name = df['file_name'][i]
            source = "./GeoTIFF/" + file_name
            target = dataset_path + file_name
            pb.update(i)
            try:
                copyfile(source, target)
                nowtime = datetime.datetime.now().strftime('%Y-%m-%d-%H:%M:%S')
                f.write(str(i) + ' ' + source + ' ' + nowtime + '\n')
            except IOError as e:
                print("Unable to copy file. %s" %e)
                exit(1)
            except:
                print("Unexpected error:", sys.exc_info())
                exit(1)

def main():
    # 设置命令行参数
    parser = argparse.ArgumentParser(description="extract small dataset from a larg one")
    parser.add_argument('-s', '--source', default='/home/qingren/下载/Dataset/TenGeoP-SARwv/58683.txt')
    args = parser.parse_args()

    source_file = args.source
    df_data = pd.read_table(source_file, sep=" ", header=None,
                    names=["file_name", "labeling", "swatch", "capture_time", "latitude", "longitude"])
    label_list = {"F": "Pure Ocean Waves", "G": "Wind Streaks", "H": "Micro Convective Cells",
                "I": "Rain Cells", "J": "Biological Slicks", "K": "Sea Ice",
                "L": "Iceberg", "M": "Low Wind Area", "N": "Atmospheric Front", "O": "Oceanic Front"}
    create_data_file(df_data, label_list)
    batch_copy(label_list)

if __name__ == "__main__":
    main()


from flask import Flask, render_template, Response
from flask_cors import CORS, cross_origin
import confluent_kafka
import uuid
import json
import os
from config_loader import load_config

# load configs
load_config()

app = Flask(__name__)
CORS(app)
app.config['DEBUG'] = os.environ.get('debugger')

# @app.route('/')
# def index():
#     return(render_template('index.html'))

#Consumer API
@app.route('/topic/<topicname>')
def get_messages(topicname):
    def events():
        bootstrap_servers = os.environ.get('bootstrap_servers')
        conf = {'bootstrap.servers': bootstrap_servers,
                'session.timeout.ms': 6000,
                'group.id': uuid.uuid1(),
                'default.topic.config': {'auto.offset.reset': 'latest'}
                }
        consumer = confluent_kafka.Consumer(**conf)

        consumer.subscribe([topicname])
        while True:
            msg = consumer.poll(1)
            if msg is None:
                continue
            elif not msg.error():
                yield 'data:{0}\n\n'.format(msg.value().decode())

    return Response(events(), mimetype="text/event-stream")

if __name__ == '__main__':
    app.run()


from __future__ import absolute_import
import time

from traits.api import List, Float, Bool

from pychron.core.helpers.strtools import to_bool
from pychron.globals import globalv
from pychron.hardware import get_float
from pychron.spectrometer.base_magnet import BaseMagnet
from six.moves import range

class ThermoMagnet(BaseMagnet):
    """
    Magnet interface to Qtegra.

    uses MFTable object of mapping dac to mass
    """

    protected_detectors = List

    use_detector_protection = Bool
    use_beam_blank = Bool

    # detector_protection_threshold = Float(0.1)  # DAC units
    beam_blank_threshold = Float(0.1)  # DAC units

    # ===============================================================================
    # ##positioning
    # ===============================================================================
    def set_dac(
        self,
        v,
        verbose=True,
        settling_time=None,
        use_dac_changed=True,
        use_af_demag=True,
    ):
        # if not self._wait_lock(2):
        #     self.debug('Unabled to obtain set_dac lock. Another thread is moving the magnet')
        #     return
        if verbose:
            self.debug("setting magnet DAC")
            self.debug("current  : {:0.6f}".format(self._dac))
            self.debug("requested: {:0.6f}".format(v))

        dv = abs(self._dac - v)
        if verbose:
            self.debug("Delta Dac: {:0.6f}".format(dv))

        unprotect = []
        unblank = False

        if self.use_detector_protection:
            if verbose:
                self.debug("Checking detector protection. dv={:0.5f}".format(dv))
            for pd in self.protected_detectors:
                det = self.spectrometer.get_detector(pd)
                if verbose:
                    self.debug(
                        'Checking detector "{}". '
                        "Protection Threshold: {} (V)".format(
                            pd, det.protection_threshold
                        )
                    )
                if det is None:
                    self.warning("Invalid detector to protect: {}".format(pd))
                    continue
                if det.protection_threshold and dv > det.protection_threshold:
                    self.ask("ProtectDetector {},On".format(pd), verbose=verbose)
                    resp = self.ask("GetDeflection {}".format(pd), verbose=verbose)
                    unprotect.append(pd)
                    if verbose:
                        self.debug("Protected = {}".format(resp))

        if self.use_beam_blank:
            if dv > self.beam_blank_threshold:
                self.ask("BlankBeam True", verbose=verbose)
                unblank = True

        if self.use_af_demagnetization and use_af_demag:
            if dv > self.af_demag_threshold or use_af_demag == "force":
                if verbose:
                    self.debug(
                        "Do AF Demag. UseAFDemag={}, "
                        "delta_volts={}, threshold={}".format(
                            use_af_demag, dv, self.af_demag_threshold
                        )
                    )
                self.ask("BlankBeam True", verbose=verbose)
                unblank = True
                self._do_af_demagnetization(
                    v, lambda dd: self.ask("SetMagnetDAC {}".format(dd))
                )
        else:
            if verbose:
                self.debug(
                    "AF Demag not enabled. "
                    "self.use_af_demag={}, use_af_demag={}".format(
                        self.use_af_demagnetization, use_af_demag
                    )
                )
        self.ask("SetMagnetDAC {}".format(v), verbose=verbose)

        change = dv > 1e-7
        if change:
            if settling_time is None:
                settling_time = self.settling_time
            if verbose:
                self.debug(
                    "Magnet settling time: {:0.3f} {:0.3f}".format(
                        settling_time, self.settling_time
                    )
                )
            if settling_time > 0:
                time.sleep(settling_time)
                if verbose:
                    self.debug("Magnet settling complete")

            if unprotect or unblank:
                if verbose:
                    self.debug("Wait for magnet to stop moving")
                for i in range(50):
                    if not to_bool(self.ask("GetMagnetMoving", verbose=verbose)):
                        break
                    time.sleep(0.25)
                if verbose:
                    self.debug("Magnet move complete")

                if unprotect:
                    if verbose:
                        self.debug("Unprotect detectors")
                    for d in unprotect:
                        self.ask("ProtectDetector {},Off".format(d), verbose=verbose)
                        self.ask("GetDeflection {}".format(d), verbose=verbose)

                if unblank:
                    if verbose:
                        self.debug("Unblank beam")
                    self.ask("BlankBeam False", verbose=verbose)

        self._dac = v

        if globalv.experiment_debug:
            change = True

        if verbose:
            self.debug("set_dac. change={}".format(change))
        # self._wait_release()
        if use_dac_changed and change:
            self.dac_changed = True

        return change

    @get_float(default=0)
    def read_dac(self):
        return self.ask("GetMagnetDAC")

# ============= EOF =============================================


import functools
from typing import Callable, Any

def debag(func: Callable) -> Callable:
    """Функция декоратор для вывода дополнительной информации"""
    @functools.wraps(func)
    def finding_errors(*args: Any, **kwargs: Any) -> None:
        """Проверяем наличие переданных аргументов
        и выводим на экран отработунное действие с заходом в функцию"""
        if kwargs and args:
            print('Вызывается {0} ("{1}", age="{2}")'
                  .format(func.__name__, *args, kwargs.get('age')))
            print("'{fun}' вернула значение: "
                  .format(fun=func.__name__), func(*args, **kwargs))
            print(func(*args, **kwargs))
            print()
        elif kwargs:
            print('Вызывается {0} (name="{1}", age="{2}")'
                  .format(func.__name__, kwargs.get('name'),
                          kwargs.get('age')))
            print("'{fun}' вернула значение: "
                  .format(fun=func.__name__), func(**kwargs))
            print(func(**kwargs))
            print()
        elif args:
            print('Вызывается {0} ("{1}")'.format(func.__name__, *args))
            print("'{fun}' вернула значение: "
                  .format(fun=func.__name__), func(*args))
            print(func(*args))
            print()

    return finding_errors

@debag
def greeting(name: Any, age=None) -> str:
    """Функция приветствие либо определения возраста
    в зависимости от количества аргументов определяется вывод
    данных"""
    if age:
        return "Ого, {name}! Тебе уже {age} лет, ты быстро растешь!"\
            .format(name=name, age=age)
    else:
        return "Привет, {name}!".format(name=name)

print(greeting.__doc__)
greeting("Том")
greeting("Миша", age=100)
greeting(name="Катя", age=16)


# Approach 2: Fast and Slow Pointers
# https://leetcode.com/problems/delete-the-middle-node-of-a-linked-list/solution/

# Intuition:
# The key of this approach is that we have two pointers fast and slow traversing the linked list at the same time,
# and fast traverses twice as fast as slow. Therefore, when fast reaches the end of the linked list, slow is right
# in the middle! We only need one iteration to reach the middle node!

# Algorithm:
# 1.If there is only one node, return null.
# 2.Otherwise, initialize two pointers slow and fast, with slow pointing to head and fast pointing to the second
#   successor node of head.
# 3.While neither fast and fast.next is null:
#   -   we move fast forward by 2 nodes.
#   -   we move slow forward by 1 node.
# 4.Now slow is the predecessor of the middle node, delete the middle node.
# 5.Return head.

from typing import Optional

# Definition for singly-linked list.
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution:
    def deleteMiddle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # Edge case: return None if there is only one node.
        if head.next == None:
            return None

        count = 0
        p1 = p2 = head

        # First pass, count the number of nodes in the linked list using 'p1'.
        while p1:
            count += 1
            p1 = p1.next

        # Get the index of the node to be deleted.
        middle_index = count // 2

        # Second pass, let 'p2' move toward the predecessor of the middle node.
        for _ in range(middle_index - 1):
            p2 = p2.next

        # Delete the middle node and return 'head'.
        p2.next = p2.next.next
        return head

head = [1,3,4,7,1,2,6]
obj = Solution()
print(obj.deleteMiddle(head))

# Complexity Analysis:
# Let n be the length of the input linked list.
# Time complexity : O(n).
# - We stop the iteration when the pointer fast reaches the end, fast moves forward 2 nodes per step, so there are
#   at most n/2 steps.
# - In each step, we move both fast and slow, which takes a constant amount of time.
# - Removing the middle node also takes constant time.
# - In summary, the overall time complexity is O(n).
# Space complexity : O(1). We only need two pointers, thus the space complexity is O(1).


import os, pygame, sys

pygame.init()

size = width, height = 800, 800
speed = [1, 1]
black = 0, 0, 0

screen = pygame.display.set_mode(size)

ball = pygame.image.load("intro_ball.gif")
ballrect = ball.get_rect()
clock = pygame.time.Clock()
anim = [pygame.image.load('animation_boby\\fly_1\\' + ii).convert_alpha() for ii in
        os.listdir('animation_boby\\fly_1\\')]
i = -1
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT: sys.exit()

    ballrect = ballrect.move(speed)
    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
    if ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]

    i += 1
    screen.fill(black)
    screen.blit(anim[i % len(anim)], (0, 0))
    pygame.display.flip()
    clock.tick(60)


# Numerical libraries
import numpy as np
# Import Polynomial Regression library
from sklearn.preprocessing import PolynomialFeatures, MinMaxScaler, StandardScaler
# Linear Regression Library
from sklearn.linear_model import LinearRegression

from sklearn.ensemble import RandomForestRegressor
# Cross-Validation related Libraries
from sklearn import preprocessing
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import KFold
#Import Lasso for Dimension Reduction
from sklearn.linear_model import Lasso
# For splitting the dataset into test and Train
from sklearn.model_selection import train_test_split
# For K-Means Clustering
from sklearn.cluster import KMeans
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error
from sklearn import metrics
# to handle data in form of rows and columns
import pandas as pd
# importing ploting libraries
import matplotlib.pyplot as plt
from scipy.stats import zscore

import seaborn as sns

powerPlant = pd.read_csv("Folds5x2_pp.csv", header=0 , names = ['Temp','Vacuum','Pressure','Humidity','Power'])

power_z = powerPlant.apply(zscore)

x = powerPlant[['Temp', 'Vacuum', 'Pressure', 'Humidity']]
y = powerPlant['Power']

## Returns in-sample error for already fit model
def calc_train_error(X_train, y_train, model, scaler=None):
    predictions = model.predict(X_train)
    if scaler is not None:
        y_train = scaler.inverse_transform(y_train.reshape(-1, 1))
        predictions = scaler.inverse_transform(predictions.reshape(-1, 1))
    mse = mean_squared_error(y_train, predictions)
    rmse = np.sqrt(mse)
    mae = mean_absolute_error(y_train, predictions)
    return rmse, mae
## Returns out-of-sample error for already fit model
def calc_validation_error(X_test, y_test, model, scaler=None):
    predictions = model.predict(X_test)
    if scaler is not None:
        y_test = scaler.inverse_transform(y_test.reshape(-1, 1))
        predictions = scaler.inverse_transform(predictions.reshape(-1, 1))

    mse = mean_squared_error(y_test, predictions)
    rmse = np.sqrt(mse)
    mae = mean_absolute_error(y_test, predictions)
    return rmse, mae

## fits model and returns the RMSE for in-sample error and out-of-sample error
def calc_metrics(X_train, y_train, X_test, y_test, model, scaler=None):
    '''fits model and returns the RMSE for in-sample error and out-of-sample error'''
    #
    train_error = calc_train_error(X_train, y_train, model, scaler)
    validation_error = calc_validation_error(X_test, y_test, model, scaler)
    return train_error, validation_error

# Run kfolds with Polynomial Features
def run_kfold_poly(k, lr_or_rf=True):
    degrees = [4]
    kf = KFold(n_splits=k, shuffle = True)
    x_array = np.asarray(x)
    result = []
    for degree in degrees:
        total_train_rmse = []
        total_train_mae = []
        total_val_rmse = []
        total_val_mae = []

        # Instantiating Model
        i = 0
        for train_index, val_index in kf.split(x_array,y):
            if lr_or_rf:
                model = LinearRegression()
            else:
                model = RandomForestRegressor(n_estimators=500, max_depth=5, max_features='auto')
            poly = PolynomialFeatures(degree = degree, interaction_only= True)
            x_poly = poly.fit_transform(x_array)
            # Split data
            x_train, x_val = x_array[train_index], x_array[val_index]
            y_train, y_val = y[train_index], y[val_index]
            if isinstance(model, RandomForestRegressor):
                y_train = y_train.ravel()
                y_val = y_val.ravel()
            model.fit(x_train, y_train)
            # Calculate Error
            train_error, val_error = calc_metrics(x_train, y_train, x_val, y_val, model)

            train_rmse = train_error[0]
            train_mae = train_error[1]
            val_rmse = val_error[0]
            val_mae = val_error[1]

            print("FOLD {}".format(i + 1))
            print("VAL RMSE: {}".format(val_rmse))
            print("VAL MAE: {}".format(val_mae))

            print("IMPORTANT FEATURES: ")
            importance = model.feature_importances_
            print(importance)

            total_train_rmse.append(train_rmse)
            total_val_rmse.append(val_rmse)
            total_train_mae.append(train_mae)
            total_val_mae.append(val_mae)
            i += 1
        if lr_or_rf:
            print("Linear Regression")
        else:
            print("Random Forest Regression")
        print("DEGREE: {}".format(degree))
        print("TRAINING RMSE: {} ------ VAL RMSE {}".format(round(np.mean(total_train_rmse), 4), round(np.mean(total_val_rmse), 4)))
        print("TRAINING MAE: {} ------ VAL MAE {}".format(round(np.mean(total_train_mae), 4), round(np.mean(total_val_mae), 4)))

# Run kfolds with Standared or MinMax Scaler
def run_kfold_scale(k, lr_or_rf=True, min_max_or_standar=True):
    kf = KFold(n_splits=k, shuffle = True)
    x_array = np.asarray(x)

    total_train_rmse = []
    total_train_mae = []
    total_val_rmse = []
    total_val_mae = []
    total_importance = []

    if min_max_or_standar:
        scaler = MinMaxScaler()
        y_scaler = MinMaxScaler()
    else:
        scaler = StandardScaler()
        y_scaler = StandardScaler()

    x_scale = scaler.fit_transform(x_array)
    y_scale = y_scaler.fit_transform(y.values.reshape(-1,1))
    i = 0
    # Instantiating Model
    for train_index, val_index in kf.split(x_scale,y):
        if lr_or_rf:
            model = LinearRegression()
        else:
            model = RandomForestRegressor(n_estimators=500, max_depth=5)
        # Split data
        x_train, x_val = x_scale[train_index], x_scale[val_index]
        y_train, y_val = y_scale[train_index], y_scale[val_index]
        if isinstance(model, RandomForestRegressor):
            y_train = y_train.ravel()
            y_val = y_val.ravel()
        model.fit(x_train, y_train)
        # Calculate Error

        train_error, val_error = calc_metrics(x_train, y_train, x_val, y_val, model, y_scaler)

        train_rmse = train_error[0]
        train_mae = train_error[1]
        val_rmse = val_error[0]
        val_mae = val_error[1]

        print("FOLD {}".format(i + 1))
        print("VAL RMSE: {}".format(val_rmse))
        print("VAL MAE: {}".format(val_mae))

        print("IMPORTANT FEATURES: ")
        i += 1
        if isinstance(model, RandomForestRegressor):
            importance = model.feature_importances_
            print(importance)
        else:
            importance = model.coef_
            print(importance)
        total_train_rmse.append(train_rmse)
        total_val_rmse.append(val_rmse)
        total_train_mae.append(train_mae)
        total_val_mae.append(val_mae)
        total_importance.append(importance)

    if lr_or_rf:
        print("Linear Regression")

    else:
        print("Random Forest Regression")

    if min_max_or_standar:
        print("MinMaxScaler")
    else:
        print("StandardScaler")

    print("TRAINING RMSE: {} ------ VAL RMSE {}".format(round(np.mean(total_train_rmse), 4), round(np.mean(total_val_rmse), 4)))
    print("TRAINING MAE: {} ------ VAL MAE {}".format(round(np.mean(total_train_mae), 4), round(np.mean(total_val_mae), 4)))

if __name__ == "__main__":
    # run_kfold_poly(k=10, lr_or_rf=False)
    run_kfold_scale(k=10, lr_or_rf=False, min_max_or_standar=True)
    run_kfold_scale(k=10, lr_or_rf=True, min_max_or_standar=True)


import numpy as np
import cv2

cap = cv2.VideoCapture(0)
eye_cascade = cv2.CascadeClassifier('/home/atom/Desktop/haarcascade_eye_tree_eyeglasses.xml')

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()

    # Our operations on the frame come here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    eyes = eye_cascade.detectMultiScale(gray)
    for (ex,ey,ew,eh) in eyes:
        cv2.rectangle(frame,(ex,ey),(ex+ew,ey+eh),(255,255,0),2)
        roi_gray = gray[ey:ey+eh, ex:ex+ew]
    #    ret,thresh = cv2.threshold(roi_gray,127,255,0)
    #    contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    #    img= cv2.drawContours(roi_gray,contours,-1,(0,255,0),3)

        cv2.imshow('alpha',roi_gray)

    # Display the resulting frame
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()


# using yahoo_fin
import pandas
from datetime import datetime
from pytz import timezone
import yfinance as yf
import yahoo_fin.stock_info as si

def get_time():
    return datetime.now(timezone('EST'))

def trading_hours():
    current_time = get_time()
    if current_time.strftime("%A") == "Saturday" or current_time.strftime("%A") == "Sunday":
        return False
    market_open = current_time.replace(hour=9, minute=30, second=0, microsecond=0)
    market_close = current_time.replace(hour=16, minute=0, second=0, microsecond=0)
    if current_time < market_open or current_time > market_close:
        return False
    return True

def check_ticker(ticker):
    try:
        return yf.Ticker(ticker).info
    except KeyError:
        print("Invalid Ticker! " + str(ticker) + " does not exist.")

def check_positive(price):
    try:
        assert (isinstance(price, float) or isinstance(price, int)) and price > 0
    except AssertionError:
        print("Invalid attempt! Target price must be a postive number.")
        return False
    return True

def get_name(ticker):
    # returns the official company name corresponding to the ticker
    if not check_ticker(ticker):
        return
    return yf.Ticker(ticker).info['longName']

def get_price(ticker):
    if not check_ticker(ticker):
        return
    return si.get_live_price(ticker)

def get_data(ticker):
    if not check_ticker(ticker):
        return
    return si.get_data(ticker)

def get_previous_close(ticker):
    if not check_ticker(ticker):
        return
    if not trading_hours():
        return get_data(ticker)['adjclose'][-2]
    return get_data(ticker)['adjclose'][-1]

def price_alert(ticker, target_price):
    if check_positive(target_price):
        name = get_name(ticker)
        if not name:
            return
        while True:
            current_price = get_price(ticker)
            if current_price >= target_price:
                print(name + " has reached the target price!")
                break

def daily_change(ticker):
    previous_close = get_previous_close(ticker)
    if not previous_close:
        return
    price = get_price(ticker)
    return round((price - previous_close) / previous_close * 100, 2)

def period_change(ticker, start, end):
    if not check_ticker(ticker):
        return
    try:
        data = si.get_data(ticker, start_date=start, end_date=end)
    except (AssertionError, ValueError):
        print("Please input valid dates for start and end in the form of a string in the format month-day-year represented by numerals.")
    start_price = data['open'][0]
    end_price = data['adjclose'][-1]
    return round((end_price - start_price) / start_price * 100, 2)

def print_change(ticker, start, end):
    name = get_name(ticker)
    if not name:
        return
    change = period_change(ticker, start, end)
    if change < 0:
        print(name + " has decreased by " + str(abs(change)) + "% from " + start + " to " + end + ".")
    else:
        print(name + " has increased by " + str(change) + "% from " + start + " to " + end + ".")

def percentage_alert(ticker, amount=5):
    name = get_name(ticker)
    if not name:
        return
    while True:
        change = daily_change(ticker)
        if abs(change) > amount:
            if change < 0:
                print(name + " has decreased by " + str(abs(change)) + "%.")
            else:
                print(name + " has increased by " + str(change) + "%.")
            break

def get_date(ticker):
    if not check_ticker(ticker):
        return
    return get_data(ticker)[''][-1]

class Portfolio:
    def __init__(self, *args):
        self.items = []
        self.target = []
        for arg in args:
            self.add_item(arg)

    def __str__(self):
        if not self.items:
            return "This portfolio is empty."
        names = "This portfolio contains "
        for item in self.items[:-1]:
            names += get_name(item) + ", "
        names += get_name(self.items[-1]) + "."
        return names

    def add_item(self, ticker):
        name = get_name(ticker)
        if not name:
            return
        if ticker not in self.items:
            self.items.append(ticker)
            self.target.append(0)
            print(name + " has successfully been added to the portfolio.")
        else:
            print(name + " is already in the portfolio.")

    def remove_item(self, ticker):
        name = get_name(ticker)
        if not name:
            return
        if ticker in self.items:
            self.target.pop(self.items.index(ticker))
            self.items.remove(ticker)
            print(name + " has successfully been removed from the portfolio.")
        else:
            print(name + " was not in portfolio.")

    def add_multiple(self, *args):
        for arg in args:
            self.add_item(arg)

    def remove_multiple(self, *args):
        for arg in args:
            self.remove_item(arg)

    def all_prices(self):
        for item in self.items:
            print(get_name(item) + " has price $" + str(get_price(item)))

    def set_target(self, ticker, target_price):
        if ticker not in self.items:
            print("Please input a valid ticker that is in the portfolio.")
            return
        name = get_name(ticker)
        if check_positive(target_price):
            self.target[self.items.index(ticker)] = target_price
            print("Target price for " + name + " has been updated.")

    def target_update(self):
        for i in range(len(self.items)):
            if self.target[i]:
                name = get_name(self.items[i])
                if get_price(self.items[i]) >= self.target[i]:
                    print(name + " has reached the target price!")
                else:
                    print(name + " has not reached the target price.")

    def daily_update(self):
        for item in self.items:
            change = daily_change(item)
            name = get_name(item)
            if change < 0:
                print(name + " has decreased by " + str(abs(change)) + "% today.")
            else:
                print(name + " has increased by " + str(change) + "% today.")