import os,os.path
from PIL import Image

valid_images = [".jpg",".gif",".png",".tga"]
img_dir = input("Enter image folder path: ")
pdf_name = input("Enter pdf name: ")
pdf_path = os.path.join(img_dir,pdf_name+".pdf")
imagelist=[]
path=[]
i=0
for f in os.listdir(img_dir):
    ext = os.path.splitext(f)[1]
    if ext.lower() not in valid_images:
        continue
    if i==0:
        im1=Image.open(os.path.join(img_dir,f))
        path.append(os.path.join(img_dir,f))
        if im1.mode == 'RGBA':
            im1 = im1.convert('RGB')
        i=i+1
    else:
        im=Image.open(os.path.join(img_dir,f))
        path.append(os.path.join(img_dir,f))
        if im.mode == 'RGBA':
            im = im.convert('RGB')
        imagelist.append(im)
print(path)
im1.save(pdf_path, "PDF" ,resolution=100.0, save_all=True, append_images=imagelist)

'''
Convert each image to pdf

import os
from PIL import Image

page = 1
folder = input("Enter image folder path: ")
for pic in os.listdir(folder):
    if pic.endswith('.png') or pic.endswith('.jpg'):
        img = Image.open(os.path.join(folder,pic))
        pdfTitle = os.path.join(folder,'pdfs','{}.pdf'.format(page))
        img.save(pdfTitle)
        page += 1
'''


from vizdoom import *
import numpy as np
import math
from gym.core import Env
from gym.spaces.discrete import Discrete
from gym.spaces.box import Box
from model.util import *

x_bank = [-320, -120, 120]
y_bank = [-320, -120, 120]

class NaviEnv(Env):
    def __init__(self):
        self.game = DoomGame()
        self.game.load_config("O:\\Doom\\scenarios\\cig_flat.cfg")
        self.game.set_doom_scenario_path("O:\\Doom\\scenarios\\cig_flat_small.wad")
        self.game.set_doom_map("map01")
        self.game.add_game_args("-host 1 -deathmatch +timelimit 1.0 "
                           "+sv_forcerespawn 1 +sv_noautoaim 1 +sv_respawnprotect 1 +sv_spawnfarthest 1 +sv_nocrouch 1 "
                           "+viz_respawn_delay 1")
        self.game.add_game_args("+name AI +colorset 0")
        self.game.set_doom_map("map02")
        self.game.add_available_game_variable(GameVariable.POSITION_X)
        self.game.add_available_game_variable(GameVariable.POSITION_Y)
        self.game.add_available_game_variable(GameVariable.SELECTED_WEAPON_AMMO)
        self.game.add_available_game_variable(GameVariable.HEALTH)
        self.game.add_available_game_variable(GameVariable.ARMOR)
        #self.game.set_labels_buffer_enabled(True)
        self.game.set_depth_buffer_enabled(True)
        self.game.set_mode(Mode.PLAYER)
        self.game.init()
        self.action_space = Discrete(3)
        self.observation_space = Box(low=0, high=255, shape=(84, 84, 3), dtype=np.uint8)

        self._reset_path_history()

    def reset(self):
        self.game.new_episode()
        self._reset_path_history()
        return get_observation(self.game.get_state(), real_frame=True)

    def seed(self, seed=None):
        self.game.set_seed(seed)
        return [seed]

    def step(self, action):
        one_hot_action = [[1,0,0,0,0,0], [0,1,0,0,0,0], [0,0,0,0,1,0]]
        old_health = self.game.get_game_variable(GameVariable.HEALTH)
        old_ammo = self.game.get_game_variable(GameVariable.SELECTED_WEAPON_AMMO)
        old_armor = self.game.get_game_variable(GameVariable.ARMOR)
        self.game.make_action(one_hot_action[action])
        new_health = self.game.get_game_variable(GameVariable.HEALTH)
        new_ammo = self.game.get_game_variable(GameVariable.SELECTED_WEAPON_AMMO)
        new_armor = self.game.get_game_variable(GameVariable.ARMOR)
        location_rew = self._register_visit()
        collection_rew = 0
        if new_health - old_health > 0:
            collection_rew += 1
        if new_ammo - old_ammo > 0:
            collection_rew += 1
        if new_armor - old_armor > 0:
            collection_rew += 1

        depth_rew = 0
        if self.game.get_state() is not None:
            depth_buffer = self.game.get_state().depth_buffer.astype(np.int32)[:202, :]
            depth_sum = np.sum(np.max(depth_buffer, axis=0))
            if depth_sum < 10000:
                depth_rew = (depth_sum - 8000) / 80000
        rew = location_rew + collection_rew * 100 + depth_rew * 0.1
        done = self.game.is_episode_finished()
        if done:
            self.game.new_episode()
        obs = get_observation(self.game.get_state(), real_frame=True)
        return obs, rew, done, None

    def render(self, mode='human'):
        pass

    def close(self):
        self.game.close()

    def _reset_path_history(self):
        self.path_history = np.ones([3,3], dtype=np.float32)

    def _register_visit(self):
        self.path_history = np.maximum(self.path_history * 0.98, 1)
        pos_x = self.game.get_game_variable(GameVariable.POSITION_X)
        pos_y = self.game.get_game_variable(GameVariable.POSITION_Y)
        x_block, y_block = 0, 0
        for i in range(len(x_bank)):
            if pos_x < x_bank[i]:
                x_block = i
                break
        for i in range(len(y_bank)):
            if pos_y < y_bank[i]:
                y_block = i
                break
        if self.path_history[x_block, y_block] < 20:
            self.path_history[x_block, y_block] += 1
        return 1 / float(self.path_history[x_block, y_block])

if __name__ == '__main__':
    env = NaviEnv()
    rew = 0
    for i in range(1000):
        print(i)
        _, r, _, _ = env.step(0)
        rew += r
    print(rew / 1000)


import torch
import torch.nn as nn

from models.network import Network
from src.utils import get_derivative

class DFC(Network):
    def __init__(self, encoder, decoder, config) -> None:
        super().__init__(encoder, decoder, name="DFC")

        self._target_lr = config.target_lr
        self._alpha_di = config.alpha_di

    @property
    def layer_sizes(self):
        return [layer.out_features for layer in self.layers]

    @property
    def activations(self):
        return [layer.activations for layer in self.layers]

    @property
    def linear_activations(self):
        return [layer.linear_activations for layer in self.layers]

    def backward(self):
        self._set_targets()
        self._non_dynamical_inversion()

        for layer in self.layers:
            layer.backward()

    def _set_targets(self):
        """MSE loss solution"""
        self.targets = (
            1 - 2 * self._target_lr
        ) * self.y_hat + 2 * self._target_lr * self.y

    def _calculate_full_jacobian(self):
        Js = []

        activations_derivatives = [
            layer.activation_derivative(layer.linear_activations)
            for layer in self.layers
        ]
        bsz = self.layers[0].activations.shape[0]

        # TODO DFC misses bias

        output_sz = self.layers[-1].out_features

        # Last layer
        Js.append(
            activations_derivatives[-1].view(bsz, output_sz, 1)
            * torch.eye(output_sz).repeat(bsz, 1, 1)
        )
        # Rest of the layers
        for i in range(len(self.layers) - 2, -1, -1):
            J = activations_derivatives[i].unsqueeze(1) * torch.matmul(
                Js[-1], self.layers[i + 1].weights
            )
            Js.append(J)

        Js.reverse()

        return torch.cat(Js, dim=2)

    def _non_dynamical_inversion(self):
        J = self._calculate_full_jacobian()
        J_T = J.transpose(1, 2)

        error = self.targets - self.y_hat
        error = error.unsqueeze(2)

        u = torch.linalg.solve(
            torch.matmul(J, J_T) + self._alpha_di * torch.eye(J.shape[1]), error
        )

        delta_v = torch.matmul(J_T, u).squeeze(-1)
        delta_vs = torch.tensor_split(
            delta_v,
            torch.cumsum(torch.tensor(self.layer_sizes[:-1]), dim=0).cpu(),
            dim=1,
        )

        rs = [self.input]

        for i, layer in enumerate(self.layers):
            v_ff = torch.matmul(rs[i], layer.weights.t())
            v_ff += layer.bias.unsqueeze(0).expand_as(v_ff)
            v = v_ff + delta_vs[i]

            r_ff = layer.activation_fn(v_ff)
            r = layer.activation_fn(v)
            rs.append(r)

            layer.v_ff = v_ff
            layer.v = v
            layer.delta_v = delta_vs[i]

            layer.r = r
            layer.r_ff = r_ff
            layer.r_prev = rs[i]

        # self.u = u

class DFC_layer(nn.Module):
    def __init__(
        self, in_features, out_features, activation_fn=nn.ReLU(), name="DFC_layer"
    ) -> None:
        super(DFC_layer, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.activation_fn = activation_fn
        self.name = name

        self.activation_derivative = get_derivative(self.activation_fn)

        self.feedforward = nn.Sequential(
            nn.Linear(self.in_features, self.out_features), self.activation_fn
        )
        nn.init.kaiming_normal_(self.feedforward[0].weight)
        self._weights = self.feedforward[0].weight
        self._bias = self.feedforward[0].bias

    @property
    def weights(self):
        return self._weights

    @property
    def bias(self):
        return self._bias

    @property
    def shape(self):
        return self._weights.shape

    def forward(self, x):
        a = torch.matmul(x, self.weights.t())
        a += self.bias.unsqueeze(0).expand_as(a)
        self.activations = self.activation_fn(a)
        self.linear_activations = a

        return self.activations

    def backward(self):
        teaching_signal = self.r - self.r_ff

        bsz = self.r_prev.shape[0]
        weights_grad = -2 * 1.0 / bsz * teaching_signal.t().mm(self.r_prev)
        bias_grad = -2 * teaching_signal.mean(dim=0)

        self._weights.grad = weights_grad
        self._bias.grad = bias_grad


while True:
    data = input()
    if data == '.':
        break
    bracket = []
    flag = True
    for i in data:
        if i == '[' or i == '(':
            bracket.append(i)
        elif i == ']' or i == ')':
            if len(bracket) == 0:
                flag = False
                break
            x = bracket.pop()
            if (i == ']' and x != '[') or (i == ')' and x != '('):
                flag = False
    print('yes') if flag and not bracket else print('no')


from __future__ import annotations

import typing

import plotly

import pandas as pd

# pylint: disable=wrong-import-position
if typing.TYPE_CHECKING:
    import BaseOpts

import PlotUtilsPlotly
import Utils
import BaseDB

from BaseLog import log_error, log_info
from Plotting import plotmissionsingle

@plotmissionsingle
def mission_int_sensors(
    base_opts: BaseOpts.BaseOptions,
    mission_str: list,
    dive=None,
    generate_plots=True,
    dbcon=None,
) -> tuple[list, list]:
    """Plots internal pressure, RH, temp"""
    log_info("Starting mission_int_sensors")

    if dbcon == None:
        conn = Utils.open_mission_database(base_opts)
        log_info("mission_int_sensors db opened")
    else:
        conn = dbcon

    if not conn:
        log_error("Could not open mission database")
        return ([], [])

    if dive == None:
        clause = ""
    else:
        clause = f"WHERE dive <= {dive}"

    fig = plotly.graph_objects.Figure()
    df = None
    try:
        df = pd.read_sql_query(
            f"SELECT dive,log_HUMID,log_INTERNAL_PRESSURE from dives {clause} ORDER BY dive ASC",
            conn,
        ).sort_values("dive")
    except:
        log_error("Could not fetch needed columns", "exc")
        if dbcon == None:
            conn.close()
            log_info("mission_int_sensors db closed")
        return ([], [])

    df_int_temperature = None
    try:
        df_int_temperature = pd.read_sql_query(
            f"SELECT dive,log_TEMP from dives {clause} ORDER BY dive ASC",
            conn,
        ).sort_values("dive")
    except pd.errors.DatabaseError as e:
        if e.args[0].endswith("no such column: log_TEMP"):
            pass
        else:
            log_error("Unexpected error fetching log_TEMP", "exc")

    for v in ["log_INTERNAL_PRESSURE", "log_HUMID"]:
        if len(df["dive"].to_numpy()) > 0:
            m, b = Utils.dive_var_trend(
                base_opts, df["dive"].to_numpy(), df[v].to_numpy()
            )
            BaseDB.addValToDB(
                base_opts, df["dive"].to_numpy()[-1], f"{v}_slope", m, con=conn
            )

    if dbcon == None:
        try:
            conn.commit()
        except Exception as e:
            conn.rollback()
            log_error(f"Failed commit, MissionIntSensors {e}", "exc")

        log_info("mission_int_sensors db closed")
        conn.close()

    if not generate_plots:
        log_info("Returning")
        return ([], [])

    fig.add_trace(
        {
            "name": "Internl Pressure",
            "x": df["dive"],
            "y": df["log_INTERNAL_PRESSURE"],
            "yaxis": "y1",
            "mode": "lines",
            "line": {
                "dash": "solid",
                "color": "DarkMagenta",
                "width": 1,
            },
            "hovertemplate": "Internal Pressure
Dive %{x:.0f}
pressure %{y:.2f} psia<extra></extra>",
        }
    )

    fig.add_trace(
        {
            "name": "Relative Humidity",
            "x": df["dive"],
            "y": df["log_HUMID"],
            "yaxis": "y2",
            "mode": "lines",
            "line": {
                "dash": "solid",
                "color": "DarkBlue",
                "width": 1,
            },
            "hovertemplate": "Relative Humidity
Dive %{x:.0f}
RH %{y:.2f} percent<extra></extra>",
        }
    )
    if df_int_temperature is not None:
        fig.add_trace(
            {
                "name": "Temperature",
                "x": df_int_temperature["dive"],
                "y": df_int_temperature["log_TEMP"],
                "yaxis": "y3",
                "mode": "lines",
                "line": {
                    "dash": "solid",
                    "color": "Red",
                    "width": 1,
                },
                "hovertemplate": "Temperature
Dive %{x:.0f}
T %{y:.2f}C<extra></extra>",
            }
        )

    title_text = f"{mission_str}
Internal Sensors"

    fig.update_layout(
        {
            "xaxis": {
                "title": "Dive Number",
                "showgrid": True,
                "domain": [0.0, 0.9],
            },
            "yaxis": {
                "title": "Internal Pressure (psia)",
                "showgrid": True,
                "tickformat": ".02f",
                "position": 0.0,
            },
            "yaxis2": {
                "title": "Relative Humidity",
                "overlaying": "y1",
                "side": "right",
                "showgrid": False,
                "tickformat": ".02f",
                "position": 0.9,
            },
            "yaxis3": {
                "title": "Temperature (C)",
                "overlaying": "y1",
                "anchor": "free",
                "side": "right",
                "position": 1,
                "showgrid": False,
            },
            "legend": {
                "x": 1.05,
                "y": 1,
            },
            "title": {
                "text": title_text,
                "xanchor": "center",
                "yanchor": "top",
                "x": 0.5,
                "y": 0.95,
            },
            "margin": {
                "b": 120,
            },
        },
    )
    return (
        [fig],
        PlotUtilsPlotly.write_output_files(
            base_opts,
            "eng_mission_int_sensors",
            fig,
        ),
    )


from datetime import datetime
import sys, os
from os import path

from services import helper
from services.batch_processor import BatchProcessor
from services.logging import get_logger
import pytz

logger = get_logger()

def extract_event(item):
    return item.get('_source')

def execute_api_request(item):
    # logger.info('aq: {}'.format(item))
    event = extract_event(item)
    event['date'] = helper.datetime_format_for_lifecycle(datetime.now(pytz.timezone('America/Sao_Paulo')))
    del event['process']
    del event['squad']
    del event['company_id']
    del event['event_name']
    del event['system_name']
    logger.info(event)

def handler():
    target = sys.argv[1]

    logger.info("---------------------------------------------------------")
    logger.info("Beginning at {}".format(datetime.now(tz=pytz.timezone("America/Sao_Paulo"))))
    logger.info("---------------------------------------------------------")

    service = BatchProcessor()
    try:
        if path.isdir(target):
            logger.info('Target {} is a directory'.format(target))
            service.read_dir(target)
        elif path.isfile(target):
            logger.info('Target {} is a file'.format(target))
            service.add_file(target)
        else:
            raise FileNotFoundError("Target not found {}".format(target))

        service.process(execute_api_request)

    except Exception as err:
        logger.error(err)
    finally:
        result = service.get_results()

    logger.info("---------------------------------------------------------")
    logger.info("Finishing at {}".format(datetime.now(tz=pytz.timezone("America/Sao_Paulo"))))
    logger.info("---------------------------------------------------------")

    if result['total_files'] > 0:
        logger.info('Total processed files: {}'.format(result['total_files']))
        # logger.info('Total processed files with success: {}'.format(result['total_files']))
        # logger.info('Total processed files with error: {}'.format(result['total_files']))
        logger.info('Total processed items: {}'.format(result['total_items']))
        logger.info('Total processed requests: {}'.format(result['total_request']))
        # logger.info('Total items per file: {}'.format(result['total_items_per_file']))
        # logger.info("---------------------------------------------------------")
        # logger.info('{} - {} - {}'.format('bucket', 'bucket_file_name', 'uploaded?'))
        # logger.info("---------------------------------------------------------")

        # for res in result['items']:
        #     logger.info('{} - {} - {}'.format(res['bucket'], res['bucket_file_name'], res['uploaded']))

    logger.info("---------------------------------------------------------")
    logger.info("Exiting ...")
    logger.info("---------------------------------------------------------")

# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    handler()


#1. Use getGeocodeLocation to get the latitude and longitude coordinates of the location string.

#2.  Use foursquare API to find a nearby restaurant with the latitude, longitude, and mealType strings.
#HINT: format for url will be something like https://api.foursquare.com/v2/venues/search?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&v=20130815&ll=40.7,-74&query=sushi

#3. Grab the first restaurant
#4. Get a  300x300 picture of the restaurant using the venue_id (you can change this by altering the 300x300 value in the URL or replacing it with 'orginal' to get the original picture
#5. Grab the first image
#6. If no image is available, insert default a image url
#7. Return a dictionary containing the restaurant name, address, and image url

from geocode import getGeocodeLocation
import requests
from dotenv import dotenv_values

# Get enviroment variables
config = dotenv_values(".env")

def findARestaurant(mealType: str, location: str) -> dict:
	"""
    Grab information about restaurants from Foursquare API

    :param mealType: Type of food to search
    :param location: String with the place to search
	:return: dictionary containing the restaurant name, address, and image url
    """

	# Keys for Foursquare API
	CLIENT_ID = config["CLIENT_ID"]
	CLIENT_SECRET = config["CLIENT_SECRET"]

	latitude, longitude = getGeocodeLocation(location) # Function to get lat, long coordinates from google map's API
	locationString = str(latitude) + ", " + str(longitude)
	params = dict(
		client_id=CLIENT_ID,
		client_secret=CLIENT_SECRET,
		v='20180323',
		ll=locationString,
		query=mealType,
		limit=1
	)
	try:
		url = 'https://api.foursquare.com/v2/venues/search'
		resp = requests.get(url=url, params=params)
		data = resp.json()
		if data["meta"]["code"] == 200:
			# Grab main info of the first restaurant
			first_restaurant = data["response"]["venues"][0]
			info_restaurant = {}
			info_restaurant["Restaurant name"] = first_restaurant["name"]
			restaurant_address = first_restaurant["location"]["formattedAddress"]
			info_restaurant["Restaurant address"] = " ".join(restaurant_address)

			# Grab image of the restaurant
			restaurant_id = first_restaurant["id"]
			url_photos = f'https://api.foursquare.com/v2/venues/{restaurant_id}/photos'
			params = dict(
				client_id=CLIENT_ID,
				client_secret=CLIENT_SECRET,
				v='20180323',
			)
			resp = requests.get(url=url_photos, params=params)
			photos_data = resp.json()
			if photos_data["meta"]["code"] == 200:
				first_photo = photos_data.get("response").get("photos").get("items")
				if len(first_photo) != 0:
					image_url = first_photo[0]["prefix"] + "300x300" + first_photo[0]["suffix"]
				else:
					image_url = "https://st4.depositphotos.com/14953852/22772/v/600/depositphotos_227725020-stock-illustration-no-image-available-icon-flat.jpg"
				info_restaurant["Image url"] = image_url
			else:
				raise Exception(f'Error type: {photos_data["meta"]["errorType"]}, Code: {photos_data["meta"]["code"]}')
			#Print values of the first restaurant
			for key, value in info_restaurant.items():
				print(f"{key}: {value}", end="")
			print("-" * 100)
		else:
			print(f'Error type: {data["meta"]["errorType"]}, Code: {data["meta"]["code"]}')
	except requests.HTTPError as http_err:
		print(f'HTTP error occurred: {http_err}')
	except Exception as err:
		print(f'Other error occurred: {err}')

if __name__ == '__main__':
	findARestaurant("Pizza", "Tokyo, Japan")
	findARestaurant("Tacos", "Jakarta, Indonesia")
	findARestaurant("Tapas", "Maputo, Mozambique")
	findARestaurant("Falafel", "Cairo, Egypt")
	findARestaurant("Spaghetti", "New Delhi, India")
	findARestaurant("Cappuccino", "Geneva, Switzerland")
	findARestaurant("Sushi", "Los Angeles, California")
	findARestaurant("Steak", "La Paz, Bolivia")
	findARestaurant("Gyros", "Sydney, Australia")


from node import Node

#we can do this without a buffer but we would have to
#use a double loop to check that some current node isn't
#equal to any other nodes.

#remove duplicates from an unsorted linked list
#linear space and time
def removeDuplicates(ll):

	if ll:		#empty list check
		curr, prev = ll, None
		h = {}			#count for data values we find

		while curr:
			if curr.data not in h:
				#first occurance
				h[curr.data] = 1
				#move prev pointer to curr
				prev = curr
			else:
				#duplicate - remove duplicate by moving prev
				prev.next = curr.next

			#move curr pointer
			curr = curr.next

	return ll

ll = Node(4)
lst = [Node(1), Node(4), Node(6), Node(1), Node(3)]

curr = ll
while lst:
	curr.next = lst.pop(0)
	curr = curr.next

new_ll = removeDuplicates(ll)
curr = new_ll

while curr:
	print(curr.data)
	curr = curr.next


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

# Define a class to receive the characteristics of each line detection
class Line():
    def __init__(self):
        # was the line detected in the last iteration?
        self.detected = False
        # x values of the last n fits of the line
        self.recent_xfitted = []
        #average x values of the fitted line over the last n iterations
        self.bestx = None
        #polynomial coefficients averaged over the last n iterations
        self.best_fit = None
        #polynomial coefficients for the most recent fit
        self.current_fit = [np.array([False])]
        #radius of curvature of the line in some units
        self.radius_of_curvature = None
        #distance in meters of vehicle center from the line
        self.line_base_pos = None
        #difference in fit coefficients between last and new fits
        self.diffs = np.array([0,0,0], dtype='float')
        #x values for detected line pixels
        self.allx = None
        #y values for detected line pixels
        self.ally = None

def sliding_line_finding(binary_warped):
    left_lane  = Line()
    right_lane = Line()
    # Assuming you have created a warped binary image called "binary_warped"
    # Take a histogram of the bottom half of the image
    histogram = np.sum(binary_warped[np.int(binary_warped.shape[0]/2):,:], axis=0)

    # Create an output image to draw on and  visualize the result
    out_img = np.dstack((binary_warped, binary_warped, binary_warped))*255
    # Find the peak of the left and right halves of the histogram
    # These will be the starting point for the left and right lines
    midpoint = np.int(histogram.shape[0]/2)
    leftx_base = np.argmax(histogram[:midpoint])
    rightx_base = np.argmax(histogram[midpoint:]) + midpoint

    # Choose the number of sliding windows
    nwindows = 9
    # Set height of windows
    window_height = np.int(binary_warped.shape[0]/nwindows)
    # Identify the x and y positions of all nonzero pixels in the image
    nonzero = binary_warped.nonzero()
    nonzeroy = np.array(nonzero[0])
    nonzerox = np.array(nonzero[1])
    # Current positions to be updated for each window
    leftx_current = leftx_base
    rightx_current = rightx_base
    # Set the width of the windows +/- margin
    margin = 80
    # Set minimum number of pixels found to recenter window
    minpix = 50
    # Create empty lists to receive left and right lane pixel indices
    left_lane_inds = []
    right_lane_inds = []

    # Step through the windows one by one
    for window in range(nwindows):
        # Identify window boundaries in x and y (and right and left)
        win_y_low = binary_warped.shape[0] - (window+1)*window_height
        win_y_high = binary_warped.shape[0] - window*window_height
        win_xleft_low = leftx_current - margin
        win_xleft_high = leftx_current + margin
        win_xright_low = rightx_current - margin
        win_xright_high = rightx_current + margin
        # Draw the windows on the visualization image
        cv2.rectangle(out_img,(win_xleft_low,win_y_low),(win_xleft_high,win_y_high),(0,255,0), 3)
        cv2.rectangle(out_img,(win_xright_low,win_y_low),(win_xright_high,win_y_high),(0,255,0), 3)
        # Identify the nonzero pixels in x and y within the window
        good_left_inds = ((nonzeroy >= win_y_low) & (nonzeroy < win_y_high) & (nonzerox >= win_xleft_low) & (nonzerox < win_xleft_high)).nonzero()[0]
        good_right_inds = ((nonzeroy >= win_y_low) & (nonzeroy < win_y_high) & (nonzerox >= win_xright_low) & (nonzerox < win_xright_high)).nonzero()[0]
        # Append these indices to the lists
        left_lane_inds.append(good_left_inds)
        right_lane_inds.append(good_right_inds)
        # If you found > minpix pixels, recenter next window on their mean position
        if len(good_left_inds) > minpix:
            leftx_current = np.int(np.mean(nonzerox[good_left_inds]))
        if len(good_right_inds) > minpix:
            rightx_current = np.int(np.mean(nonzerox[good_right_inds]))

    # Concatenate the arrays of indices
    left_lane_inds = np.concatenate(left_lane_inds)
    right_lane_inds = np.concatenate(right_lane_inds)

    # Extract left and right line pixel positions
    leftx = nonzerox[left_lane_inds]
    lefty = nonzeroy[left_lane_inds]
    rightx = nonzerox[right_lane_inds]
    righty = nonzeroy[right_lane_inds]

    # Fit a second order polynomial to each
    left_fit = np.polyfit(lefty, leftx, 2)
    right_fit = np.polyfit(righty, rightx, 2)

    left_lane.allx = nonzerox[left_lane_inds]
    left_lane.ally = nonzeroy[left_lane_inds]
    right_lane.allx = nonzerox[right_lane_inds]
    right_lane.ally = nonzeroy[right_lane_inds]
    left_lane.current_fit = left_fit
    right_lane.current_fit = right_fit

    return left_lane,right_lane

def line_finding_after_sliding(binary_warped,left_lane,right_lane):

    nonzero = binary_warped.nonzero()
    nonzeroy = np.array(nonzero[0])
    nonzerox = np.array(nonzero[1])
    margin = 100

    left_fit = left_lane.current_fit
    right_fit = right_lane.current_fit

    left_lane_inds = ((nonzerox > (left_fit[0]*(nonzeroy**2) + left_fit[1]*nonzeroy + left_fit[2] - margin)) & (nonzerox < (left_fit[0]*(nonzeroy**2) + left_fit[1]*nonzeroy + left_fit[2] + margin)))
    right_lane_inds = ((nonzerox > (right_fit[0]*(nonzeroy**2) + right_fit[1]*nonzeroy + right_fit[2] - margin)) & (nonzerox < (right_fit[0]*(nonzeroy**2) + right_fit[1]*nonzeroy + right_fit[2] + margin)))

    # Again, extract left and right line pixel positions
    left_lane.allx = nonzerox[left_lane_inds]
    left_lane.ally = nonzeroy[left_lane_inds]
    right_lane.allx = nonzerox[right_lane_inds]
    right_lane.ally = nonzeroy[right_lane_inds]

    # Fit a second order polynomial to each
    left_fit = np.polyfit(left_lane.ally, left_lane.allx, 2)
    right_fit = np.polyfit(right_lane.ally, right_lane.allx, 2)
    # Generate x and y values for plotting
    ploty = np.linspace(0, binary_warped.shape[0]-1, binary_warped.shape[0] )
    left_fitx = left_fit[0]*ploty**2 + left_fit[1]*ploty + left_fit[2]
    right_fitx = right_fit[0]*ploty**2 + right_fit[1]*ploty + right_fit[2]
    left_lane.current_fit = left_fit
    right_lane.current_fit = right_fit
    return left_lane,right_lane

def draw(binary_warped, left_lane, right_lane, image, Minv):

    left_fit=left_lane.current_fit
    right_fit=right_lane.current_fit
    ploty = np.linspace(0, binary_warped.shape[0]-1, binary_warped.shape[0] )
    left_fitx = left_fit[0]*ploty**2 + left_fit[1]*ploty + left_fit[2]
    right_fitx = right_fit[0]*ploty**2 + right_fit[1]*ploty + right_fit[2]

    # Create an image to draw the lines on
    warp_zero = np.zeros_like(binary_warped).astype(np.uint8)
    color_warp = np.dstack((warp_zero, warp_zero, warp_zero))

    # Recast the x and y points into usable format for cv2.fillPoly()
    pts_left = np.array([np.transpose(np.vstack([left_fitx, ploty]))])
    pts_right = np.array([np.flipud(np.transpose(np.vstack([right_fitx, ploty])))])
    pts = np.hstack((pts_left, pts_right))

    # Draw the lane onto the warped blank image
    cv2.fillPoly(color_warp, np.int_([pts]), (0,255, 0))

    # Warp the blank back to original image space using inverse perspective matrix (Minv)
    newwarp = cv2.warpPerspective(color_warp, Minv, (image.shape[1], image.shape[0]))
    # Combine the result with the original image
    result = cv2.addWeighted(image, 1, newwarp, 0.3, 0)

    return result

def measure_curvature(binary_warped, left_lane, right_lane):

    left_fit=left_lane.current_fit
    right_fit=right_lane.current_fit
    ploty = np.linspace(0, binary_warped.shape[0]-1, binary_warped.shape[0] )
    y_eval = np.max(ploty)
    ym_per_pix = 30/720 # meters per pixel in y dimension
    xm_per_pix = 3.7/700 # meters per pixel in x dimension

    left_fitx = left_fit[0]*ploty**2 + left_fit[1]*ploty + left_fit[2]
    right_fitx = right_fit[0]*ploty**2 + right_fit[1]*ploty + right_fit[2]

    # Fit new polynomials to x,y in world space
    left_fit_cr = np.polyfit(ploty*ym_per_pix, left_fitx*xm_per_pix, 2)
    right_fit_cr = np.polyfit(ploty*ym_per_pix, right_fitx*xm_per_pix, 2)

    # Calculate the new radii of curvature
    left_curveradius = ((1 + (2*left_fit_cr[0]*y_eval*ym_per_pix + left_fit_cr[1])**2)**1.5) / np.absolute(2*left_fit_cr[0])
    right_curveradius = ((1 + (2*right_fit_cr[0]*y_eval*ym_per_pix + right_fit_cr[1])**2)**1.5) / np.absolute(2*right_fit_cr[0])

    return left_curveradius,right_curveradius

def compute_offset(binary_warped, left_lane, right_lane):

    left_fit=left_lane.current_fit
    right_fit=right_lane.current_fit

    left_fitx = left_fit[0]*binary_warped.shape[0]**2 + left_fit[1]*binary_warped.shape[0] + left_fit[2]
    right_fitx = right_fit[0]*binary_warped.shape[0]**2 + right_fit[1]*binary_warped.shape[0] + right_fit[2]
    xm_per_pix = 3.7/700

    #center of the image
    center_img = binary_warped.shape[1]/2

    #cam position respect to the center
    center_cam = (left_fitx+right_fitx)/2
    center_pos = (center_img-center_cam)*xm_per_pix

    return center_pos


class Node:
    def __init__(self, name, parent):
        self.name = name
        self.count = 1
        self.parent = parent
        self.children = {}
        self.next = None
    def inc(self, num = 1):
        self.count += num
    def show(self, ind = 1):
        print("Deep %d: %s, %d" % (ind, self.name, self.count))
        if self.parent == None:
            print("  Parent: None")
        else:
            print("  Parent: %s" % self.parent.name)
        childList = [child.name for child in self.children.values()]
        print("  Children:%s" % str(childList))
        for child in self.children.values():
            child.show(ind + 1)
if __name__ == "__main__":
    a = Node('a', 2, None)
    b = Node('b', 1, a)
    c = Node('c', 1, a)
    d = Node('d', 0, b)
    a.children = [b, c]
    b.children = [d]
    a.show()


# lorinda.julia.main.py
from _spy.vitollino.main import Cena, Elemento, Texto, STYLE
from _spy.vitollino.main import INVENTARIO as inv

from ruzwana.main import inventario

STYLE["width"]=800
STYLE["heigth"]="200px"

LILY = "https://i.imgur.com/UGyg7N2.png"
NENA = " https://i.imgur.com/SZ2Q8yp.png"
PEROLA = " https://i.imgur.com/CWuMMvW.png"
JACKSON = " https://i.imgur.com/XeNSqrz.png"
LEILA = " https://i.imgur.com/Vpw3hbY.png"
MATA = "https://i0.wp.com/www.sosma.org.br/wp-content/uploads/2020/08/imagem1-1.jpg"
ESCOLA = "https://i.imgur.com/4PaLeQW.jpg"
TUCANO = "https://i.imgur.com/mS9ASAx.png"
CORDA ="https://i.imgur.com/sD6vJLJ.png"
FACA =" https://i.imgur.com/T6W0qHH.png"
FOGO =" https://i.imgur.com/oH55GvU.png"
KIT =" https://i.imgur.com/ZVrPHcl.png"
MAPA ="https://i.imgur.com/dXllrys.png"
BUSSULA =" https://i.imgur.com/5OMt7f2.png"
PLAY= ""

class revista1():
    def __init__(self):
        self.escola=Cena(img=ESCOLA)

        Texto(self.escola,"Num futuro distante, um grupo de amigos estudavam e se divertiam juntos e além disso,  tinham poderes especiais, entretanto por conta de uma pandemia, toda a população humana foi obrigada a viver em isolamento."
                        "Após dois anos de confinamento a vacina foi descoberta, após a vacinação em massa,"
                        "os estudantes voltaram a se encontrar. Os amigos, que moravam mais perto da Mata Atlântica, na cidade de São Paulo,"
                        "começaram a perceber o sumiço de alguns animais, e se reuniram para desvendar esse mistério!" ).vai()
        self.escola.vai()
        self.lily=Elemento(img=LILY,x=220,y=400,w=100,h=200)
        self.nena=Elemento(img=NENA,x=120,y=400,w=100,h=200)
        self.perola=Elemento(img=PEROLA,x=320,y=400,w=100,h=200)
        self.jackson=Elemento(img=JACKSON,x=420,y=400,w=120,h=220)
        self.leila=Elemento(img=LEILA,x=520,y=400,w=100,h=200)
        self.lily.entra(self.escola)
        self.nena.entra(self.escola)
        self.perola.entra(self.escola)
        self.jackson.entra(self.escola)
        self.leila.entra(self.escola)
        self.escola.direita=Cena(vai=self.amem)
    def amem(self):
        self.mata=Cena(img=MATA)
        inventario(cena=self.mata)
        self.mata.vai()
        Texto(self.mata, "caracteristicas dos personagens , click para descobrir seu personagem").vai()
        self.mata.esquerda=self.escola
        self.escola.direita=self.mata
        self.mata.esquerda=self.escola
        self.nena.entra(self.mata)
        self.nena.tit="Olá eu sou a Nena, eu amo cuidar do planeta, sou organixa e monitoro tudo, por isso que eu trouxe uma bússula"
        self.perola.entra(self.mata)
        self.perola.tit="Olá,eu sou a Pérola,eu sou bastante forte e sou da equipe de resgate do meu bairro, por isso eu trouxe o kit de primeiros socorros"
        self.lily.entra(self.mata)
        self.lily.tit="Olá eu sou a Lily Raquel, eu sou bem otimista e desbravadora, por isso trouxe um facão"
        self.jackson.entra(self.mata)
        self.jackson.tit="Olá eu sou o Jackson,me colocaram como líder do grupo,pois sou muito corajoso e bom em defesa, estou levando um mapa e corda "
        self.leila.entra(self.mata)
        self.leila.tit=" olá eu sou a leila, sou bem quieta e discreta, me pediram para trazer o fogo"
        # self.mata.entra=Elemento(vai=self.personagem)

        Texto(self.mata,).vai()
        self.leila.entra(self.mata)

        self.escola.vai()
revista1()


def add_10(value):
    """ value에 10을 더한 값을 돌려주는 함수"""
    if value > 10:
        return 10
    else:
        return value + 10

n = add_10(12)
print(n)

n = round(1.5)
print(n)


import pytesseract
from pytesseract import Output
import  matplotlib.pyplot as plt
import cv2
img = cv2.imread('./images/100.jpg')

d = pytesseract.image_to_data(img, output_type=Output.DICT)
n_boxes = len(d['level'])
for i in range(n_boxes):
    (x, y, w, h) = (d['left'][i], d['top'][i], d['width'][i], d['height'][i])
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
    crop_img = img[y:y+h, x:x+w]
    plt.imshow(crop_img)
    plt.savefig(str(i))
cv2.imshow('img', img)
#cv2.waitKey(0)
'''
import cv2
import pytesseract
def to_text(path):
  img = cv2.imread(path)
  print(type(img))
  from PIL import Image
  # Adding custom options
  text = pytesseract.image_to_string(img)
  return text

print(to_text("./images/100.jpg"))
'''


from __future__ import division
from typing import Iterator, Optional

import torch
from torch.utils.data import Dataset
from torch.utils.data import DistributedSampler as _DistributedSampler

from mmseg.core.utils import sync_random_seed
from mmseg.utils import get_device

class DistributedSampler(_DistributedSampler):
    """DistributedSampler inheriting from
    `torch.utils.data.DistributedSampler`.

    Args:
        datasets (Dataset): the dataset will be loaded.
        num_replicas (int, optional): Number of processes participating in
            distributed training. By default, world_size is retrieved from the
            current distributed group.
        rank (int, optional):  Rank of the current process within num_replicas.
            By default, rank is retrieved from the current distributed group.
        shuffle (bool): If True (default), sampler will shuffle the indices.
        seed (int): random seed used to shuffle the sampler if
            :attr:`shuffle=True`. This number should be identical across all
            processes in the distributed group. Default: ``0``.
    """

    def __init__(self,
                 dataset: Dataset,
                 num_replicas: Optional[int] = None,
                 rank: Optional[int] = None,
                 shuffle: bool = True,
                 seed=0) -> None:
        super().__init__(
            dataset, num_replicas=num_replicas, rank=rank, shuffle=shuffle)

        # In distributed sampling, different ranks should sample
        # non-overlapped data in the dataset. Therefore, this function
        # is used to make sure that each rank shuffles the data indices
        # in the same order based on the same seed. Then different ranks
        # could use different indices to select non-overlapped data from the
        # same data list.
        device = get_device()
        self.seed = sync_random_seed(seed, device)

    def __iter__(self) -> Iterator:
        """
         Yields:
            Iterator: iterator of indices for rank.
        """
        # deterministically shuffle based on epoch
        if self.shuffle:
            g = torch.Generator()
            # When :attr:`shuffle=True`, this ensures all replicas
            # use a different random ordering for each epoch.
            # Otherwise, the next iteration of this sampler will
            # yield the same ordering.
            g.manual_seed(self.epoch + self.seed)
            indices = torch.randperm(len(self.dataset), generator=g).tolist()
        else:
            indices = torch.arange(len(self.dataset)).tolist()

        # add extra samples to make it evenly divisible
        indices += indices[:(self.total_size - len(indices))]
        assert len(indices) == self.total_size

        # subsample
        indices = indices[self.rank:self.total_size:self.num_replicas]
        assert len(indices) == self.num_samples

        return iter(indices)


import logging

from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.contrib.auth import get_user_model
from .models import (AccountProjectModel, AccountModel, AccountPermissionsModel, AccountDevicesModel,
                     AccountParameterModel, AccountTagOPCModel, AccountModbusRegisterModel,
                     AccountHistoryModel, AccountParameterOPDModel)
from .forms import (CreateProjectForm, EditAdminForm, NewAdminUserForm, CreateDeviceForm, AddRegisterModbusForm,
                    AddParameterOPDForm, AddTagOPCForm, AddParameterForm, DelParameterForm)
from django.shortcuts import redirect
from django.shortcuts import get_object_or_404

def check_own_project(request, project_id):
    user = request.user
    current_account = AccountModel.users.get(user=user)
    prj_id = get_object_or_404(AccountProjectModel, id=project_id)
    if len(prj_id.permissions.filter(account=current_account)) == 0:
        return False
    return True

def write_history_str(pr, strin, acc):
    history_str = AccountHistoryModel(action=acc.user.username + ": " + strin)
    history_str.save()
    pr.history_project.add(history_str)
    pr.save()

@login_required
def account(request):
    user = request.user
    account = AccountModel.users.get(user=user)
    list_projects = AccountProjectModel.projects.filter(users=account)
    if request.method == 'POST':
        form = CreateProjectForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            account_permissions = AccountPermissionsModel(account=account, admin="Чтение и запись",
                                                          device="Чтение и запись")
            account_permissions.save()
            pr = AccountProjectModel(name_project=cd['name'])
            pr.save()
            pr.permissions.add(account_permissions)
            pr.users.add(account)
            write_history_str(pr, "Создан проект " + cd['name'], account)
    else:
        form = CreateProjectForm()
    return render(request,
                  'account/account.html',
                  {'account': account,
                   'form': form,
                   'list_projects': list_projects
                   })

@login_required
def project(request, id):
    if not check_own_project(request, id):
        return redirect(account)
    prj_id = get_object_or_404(AccountProjectModel, id=id)
    history = prj_id.history_project.all()
    return render(request,
                  'account/project.html',
                  {'prj_id': prj_id,
                   'history': history})

@login_required
def admin(request, id):
    if not check_own_project(request, id):
        return redirect(account)
    prj_id = get_object_or_404(AccountProjectModel, id=id)
    perm = prj_id.permissions.all()
    user = request.user
    current_account = AccountModel.users.get(user=user)
    current_account_perm = prj_id.permissions.get(account=current_account)
    if current_account_perm.admin == "Нет прав":
        return redirect(project, id=prj_id.id)
    if request.method == 'POST':
        if "use" in request.POST:
            admin_form = EditAdminForm(id, request.POST)
            if admin_form.is_valid():
                cd = admin_form.cleaned_data
                choice_actions = cd['choice_actions']
                if not current_account_perm.id == cd['perm_id'].id and current_account_perm.admin == "Чтение и запись":
                    if choice_actions == "admin":
                        permm = AccountPermissionsModel.objects.get(id=cd['perm_id'].id)
                        if permm.admin == "Чтение и запись":
                            permm.admin = "Чтение"
                            write_history_str(prj_id, "Права администрации " + permm.account.user.username + " изменены на Чтение", current_account)
                        elif permm.admin == "Чтение":
                            permm.admin = "Нет прав"
                            write_history_str(prj_id, "Права администрации " + permm.account.user.username + " изменены на Нет прав",
                                              current_account)
                        else:
                            permm.admin = "Чтение и запись"
                            write_history_str(prj_id, "Права администрации " + permm.account.user.username + " изменены на Чтение и запись",
                                              current_account)
                        permm.save()
                    if choice_actions == "device":
                        permm = AccountPermissionsModel.objects.get(id=cd['perm_id'].id)
                        if permm.device == "Чтение и запись":
                            permm.device = "Чтение"
                            write_history_str(prj_id,
                                              "Права на управление устройствами " + permm.account.user.username + " изменены на Чтение",
                                              current_account)
                        elif permm.device == "Чтение":
                            permm.device = "Нет прав"
                            write_history_str(prj_id,
                                              "Права на управление устройствами " + permm.account.user.username + " изменены на Нет прав",
                                              current_account)
                        else:
                            permm.device = "Чтение и запись"
                            write_history_str(prj_id,
                                              "Права на управление устройствами " + permm.account.user.username + " изменены на Чтение и запись",
                                              current_account)
                        permm.save()
                    if choice_actions == "del":
                        permm = AccountProjectModel.projects.get(id=id).permissions.get(id=cd['perm_id'].id)
                        AccountProjectModel.projects.get(id=id).permissions.remove(permm)
                        acc = AccountProjectModel.projects.get(id=id).users.get(id=cd['perm_id'].account.id)
                        AccountProjectModel.projects.get(id=id).users.remove(acc)
                        write_history_str(prj_id, permm.account.user.username + " удален из проекта",
                                          current_account)
        else:
            admin_form = EditAdminForm(id)
        if "new" in request.POST:
            new_user = NewAdminUserForm(request.POST)
            if new_user.is_valid() and current_account_perm.admin == "Чтение и запись":
                cd = new_user.cleaned_data
                acc = AccountModel.users.get(user=get_user_model().objects.get(username=cd['new_user']))
                item = AccountProjectModel.projects.get(id=id)
                if len(item.users.filter(id=acc.id)) == 0:
                    item.users.add(acc)
                    write_history_str(prj_id,
                                      "Добавлен " + acc.user.username + " в проект.",
                                      current_account)
                    p = AccountPermissionsModel(account=acc)
                    p.save()
                    item.permissions.add(p)
                    item.save()
        else:
            new_user = NewAdminUserForm()
    else:
        new_user = NewAdminUserForm()
        admin_form = EditAdminForm(id)
    return render(request,
                  'account/admin.html',
                  {'prj_id': prj_id, 'admin_form': admin_form, 'perm': perm, 'new_user': new_user})

@login_required
def devices(request, id):
    if not check_own_project(request, id):
        return redirect(account)
    prj_id = get_object_or_404(AccountProjectModel, id=id)
    user = request.user
    current_account = AccountModel.users.get(user=user)
    current_account_perm = prj_id.permissions.get(account=current_account)
    if current_account_perm.device == "Нет прав":
        return redirect(project, id=prj_id.id)
    dvs = AccountDevicesModel.objects.filter(project=prj_id)
    if request.method == 'POST':
        create_form = CreateDeviceForm(request.POST)
        if create_form.is_valid() and current_account_perm.device == "Чтение и запись":
            cd = create_form.cleaned_data
            device = AccountDevicesModel(name_device=cd['name'], type_device=cd['type_device'], project=prj_id)
            device.save()
    else:
        create_form = CreateDeviceForm()
    return render(request,
                  'account/devices.html',
                  {'prj_id': prj_id, 'create_form': create_form, "dvs": dvs})

@login_required
def device(request, id):
    device = get_object_or_404(AccountDevicesModel, id=id)
    prj = get_object_or_404(AccountProjectModel, id=device.project.id)
    params = AccountParameterModel.objects.filter(device=device)

    user = request.user
    current_account = AccountModel.users.get(user=user)
    current_account_perm = prj.permissions.get(account=current_account)

    if current_account_perm.device == "Нет прав":
        return redirect(project, id=prj.id)

    if request.method == 'POST':
        form = AddParameterForm()
        if "del" in request.POST:
            form_del = DelParameterForm(id, request.POST)
            if form_del.is_valid() and current_account_perm.device == "Чтение и запись":
                cd = form_del.cleaned_data
                AccountParameterModel.objects.get(id=cd['parameter'].id).delete()
        else:
            form_del = DelParameterForm(id)
        if "modbus" in request.POST:
            form = AddParameterForm(request.POST)
            form_modbus = AddRegisterModbusForm(request.POST)
            if form.is_valid() and form_modbus.is_valid() and current_account_perm.device == "Чтение и запись":
                cd = form.cleaned_data
                cd1 = form_modbus.cleaned_data
                param = AccountParameterModel(name_parameter=cd['name_parameter'],
                                              type_parameter=cd['type_parameter'],
                                              device=device)
                param.save()
                modbus_reg = AccountModbusRegisterModel(number_device=cd1['number_device'],
                                                        number_function_read=cd1['number_function_read'],
                                                        address_read=cd1['address_read'],
                                                        number_function_write=cd1['number_function_write'],
                                                        address_write=cd1["address_write"])
                modbus_reg.save()
                param.modbus_register = modbus_reg
                param.save()

        else:
            form_modbus = AddRegisterModbusForm()
    else:
        form_modbus = AddRegisterModbusForm()
        form = AddParameterForm()
        form_del = DelParameterForm(id)
    return render(
        request,
        'account/device.html',
        {
            'prj': prj,
            'device': device,
            "form_modbus": form_modbus,
            'form_del': form_del,
            'form': form,
            'params': params
        }
    )

@login_required
def monitors(request, id):
    return render(request,
                  'account/devices.html',
                  {})

@login_required
def monitor(request, id):
    prj = get_object_or_404(AccountProjectModel, id=device.project.id)
    return render(request,
                  'account/devices.html',
                  {})


"""Parse Beech source code into a Beech Tree object."""
from __future__ import annotations

from .errors import ParseError
from .lexer import Lexer, Token, TokenType
from .beech_types import Tree, Key, Value, List, Symbol

class Parser:
    def __init__(self, source: str):
        self._lexer = Lexer(source)
        self._current_token: Token = self._lexer.next_token()  # Start with the first token.
        self._previous_token: Token = Token.empty()  # Initialise with an empty token to avoid using None.
        self._current_tree: Tree | List = {}

    def parse(self) -> Tree:
        """Parse the source code."""
        return self._beech()

    def _beech(self) -> Tree:
        while not self._check(TokenType.EMPTY):
            key: Key
            if self._match(TokenType.SYMBOL):
                key = Symbol(self._previous_token.value)
            elif self._match(TokenType.STRING):
                key = self._previous_token.value
            else:
                break  # End of tree.
            self._expect_whitespace()
            value = self._value()
            if key in self._current_tree:
                raise ParseError("Keys in a tree must be unique.")
            self._current_tree[key] = value
            if self._check_any(TokenType.SYMBOL, TokenType.STRING):
                # If we're not at the end of the tree, expect whitespace before the next key.
                self._expect_whitespace()
        return self._current_tree

    def _tree(self) -> Tree:
        previous_tree = self._current_tree
        new_tree: Tree = {}
        self._current_tree = new_tree
        self._beech()
        self._current_tree = previous_tree
        self._expect(TokenType.RIGHT_BRACE)
        return new_tree

    def _list(self) -> List:
        new_list: List = []
        previous_tree = self._current_tree
        self._current_tree = new_list
        while not self._check_any(TokenType.RIGHT_BRACKET, TokenType.EMPTY):
            new_list.append(self._value())
            if not self._check(TokenType.RIGHT_BRACKET):
                self._expect_whitespace()
        self._expect(TokenType.RIGHT_BRACKET)
        self._current_tree = previous_tree
        return new_list

    def _value(self) -> Value:
        if self._match(TokenType.STRING):
            return self._previous_token.value
        elif self._match(TokenType.SYMBOL):
            return Symbol(self._previous_token.value)
        elif self._match(TokenType.LEFT_BRACE):
            return self._tree()
        elif self._match(TokenType.LEFT_BRACKET):
            return self._list()
        else:
            raise ParseError(f"Unexpected token {self._current_token}")

    def _advance(self):
        self._previous_token = self._current_token
        self._current_token = self._lexer.next_token()

    def _expect(self, token_type: TokenType) -> None:
        if not self._match(token_type):
            raise ParseError(f"Expected {token_type} but got {self._current_token.type}")

    def _expect_whitespace(self) -> None:
        if not self._current_token.has_whitespace_before:
            raise ParseError(f"Expect whitespace before {self._current_token.type}")

    def _check(self, token_type: TokenType) -> bool:
        return self._current_token.type == token_type

    def _check_any(self, *types: TokenType) -> bool:
        return any(self._check(t) for t in types)

    def _match(self, token_type: TokenType) -> bool:
        if not self._check(token_type):
            return False

        self._advance()
        return True


#!/usr/bin/env python
# _*_ encoding: utf-8 _*_
# ---------------------------------------
# Created by: Jlfme<jlfgeek@gmail.com>
# Created on: 2016-02-28 23:10:18
# ---------------------------------------

from myspider.utils.python import load_object

class UserAgentMiddleware(object):

    def process_request(self, request, curl):
        # default headers
        headers = request.settings.get('REQUEST_HEADERS', None)
        if headers is not None:
            for k, v in headers.items():
                if k not in request.headers:
                    request.headers[k] = v

        # make user-agent
        ua = "Mozilla/5.0 (compatible; My_Spider/1.0)"
        if not request.headers.get('user-agent', None):
            if request.settings.get('USER_AGENT_CLASS', None):
                user_agent_cls = load_object(request.settings['USER_AGENT_CLASS'])
                if not hasattr(user_agent_cls, 'agent'):
                    raise NotImplementedError
                ua = user_agent_cls.agent()
            elif request.settings.get('DEFAULT_USER_AGENT', None):
                ua = request.settings.get('DEFAULT_USER_AGENT')
            request.headers['user-agent'] = ua


"""

"""

data = """dataone: 81070

arxiv_oai: 72681

crossref: 71312

pubmed: 47506

figshare: 36462

scitech: 18362

clinicaltrials: 10244

plos: 9555

mit: 2488

vtech: 713

cmu: 601

columbia: 386

calpoly: 377

opensiuc: 293

doepages: 123

stcloud: 47

spdataverse: 40

trinity: 32

texasstate: 31

valposcholar: 26

utaustin: 13

uwashington: 12

uiucideals: 6

ucescholarship: 0

upennsylvania: 0

utaustin: 0

waynestate: 0"""

def return_providers(provider_data=None):

    if not provider_data:

        provider_data = data

    providers = []

    lines = provider_data.split('\n')

    for line in lines:

        if line != '':

            line_split = line.split(':')

            provider = line_split[0]

            providers.append(provider)

    return providers