# Kobee Raveendran
# University of Central Florida
# CAP5610 Assignment 1 - Fall 2019
# 9/13/2019

import csv
import numpy as np
import random
import pandas as pd
#import seaborn as sns
import matplotlib.pyplot as plt
import os

# loads dataset from 'iris.data' in root project directory
# as a 2-dimensional list of lists
# rows = training + testing examples
# cols = labels
#   > cols 0 - 3: features
#   > col 4: class label, encoded from string to integer
def load_dataset():
    with open('iris.data', 'r') as file:
        lines = csv.reader(file)

        dataset = list(lines)[:-1]

    for row in dataset:
        class_label = row[4][5:]

        row[:-1] = list(map(float, row[:-1]))

        if class_label == 'setosa':
            row[4] = 0

        elif class_label == 'versicolor':
            row[4] = 1

        else:
            row[4] = 2

    return dataset

# splits the dataset loaded by the function above
# into k-equally partitioned sections
# where one partition serves as the test set and
# all others become the training set
def generate_k_folds(dataset, k = 5):

    random.shuffle(dataset)

    avg, mod = divmod(len(dataset), k)

    folds = list(dataset[i * avg + min(i, mod):(i + 1) * avg + min(i + 1, mod)] for i in range(k))

    return folds

# generates text-based and plot-based confusion matrix
# inputs:
#   - actual: array of the actual class labels for the test set
#   - predicted: array of the predicted class labels for every element of the test set
#   - plot_title: string representing title of the confusion matrix (for matplotlib plot)
#   - num_classes: number of unique classes in dataset
#   - filename: if provided, saves the plot of the confusion matrix locally in folder 'plots'
def generate_confusion_matrix(actual, predicted, plot_title, num_classes = 3, filename = None):
    confusion_matrix = np.zeros((num_classes, num_classes), dtype = int)

    for i in range(len(actual)):
        confusion_matrix[actual[i]][predicted[i]] += 1

    print('\n\n' + plot_title)
    print(confusion_matrix)

    # using matplotlib only
    fig, ax = plt.subplots()
    im = ax.imshow(confusion_matrix, interpolation = 'nearest', cmap = plt.cm.Blues)
    ax.figure.colorbar(im, ax = ax)
    ax.set(xticks = np.arange(confusion_matrix.shape[0]),
           yticks = np.arange(confusion_matrix.shape[1]),
           xticklabels = ['setosa', 'versicolor', 'virginica'],
           yticklabels = ['setosa', 'versicolor', 'virginica'],
           xlabel = 'Predicted class',
           ylabel = 'True class')

    plt.title(plot_title, y = 1.12)

    ax.xaxis.set_label_position('top')
    ax.xaxis.tick_top()

    plt.setp(ax.get_xticklabels(), ha = 'center', rotation_mode = 'anchor')

    threshold = confusion_matrix.max() / 2

    for i in range(confusion_matrix.shape[0]):
        for j in range(confusion_matrix.shape[1]):
            ax.text(j, i, format(confusion_matrix[i, j], 'd'), ha = 'center', va = 'center',
            color = 'white' if confusion_matrix[i, j] > threshold else 'black')

    fig.tight_layout()

    if filename:
        if not os.path.isdir('plots'):
            os.makedirs('plots')

        plt.savefig('plots/' + filename)

    return ax

# TODO: maybe move the plotting of the confusion matrix to a standalone function
def average_confusion_matrices(confusion_matrices):

    agg_cm = np.matrix([[0, 0, 0], [0, 0, 0], [0, 0, 0]])

    for matrix in confusion_matrices:
        agg_cm = agg_cm + matrix

    agg_cm = np.divide(agg_cm, len(confusion_matrices))

    filename = 'nb_average_cm.png'

    print(agg_cm)

    fig, ax = plt.subplots()
    im = ax.imshow(agg_cm, interpolation = 'nearest', cmap = plt.cm.Blues)
    ax.figure.colorbar(im, ax = ax)
    ax.set(xticks = np.arange(agg_cm.shape[0]),
           yticks = np.arange(agg_cm.shape[1]),
           xticklabels = ['setosa', 'versicolor', 'virginica'],
           yticklabels = ['setosa', 'versicolor', 'virginica'],
           xlabel = 'Predicted class',
           ylabel = 'True class')

    plt.title('Avg of Naive Bayes CMs', y = 1.12)

    ax.xaxis.set_label_position('top')
    ax.xaxis.tick_top()

    plt.setp(ax.get_xticklabels(), ha = 'center', rotation_mode = 'anchor')

    threshold = agg_cm.max() / 2

    for i in range(agg_cm.shape[0]):
        for j in range(agg_cm.shape[1]):
            ax.text(j, i, format(agg_cm[i, j], '.2f'), ha = 'center', va = 'center',
            color = 'white' if agg_cm[i, j] > threshold else 'black')

    fig.tight_layout()

    if filename:
        if not os.path.isdir('plots'):
            os.makedirs('plots')

        plt.savefig('plots/' + filename)

# ignore: I only used this to create the aggregate matrix for the best-performing knn condition
# and one for naive bayes
'''
knn_fold1 = np.matrix([[8, 0, 0], [0, 14, 0], [0, 0, 8]])
knn_fold2 = np.matrix([[9, 0, 0], [0, 10, 0], [0, 0, 11]])
knn_fold3 = np.matrix([[15, 0, 0], [0, 8, 1], [0, 0, 6]])
knn_fold4 = np.matrix([[10, 0, 0], [0, 10, 0], [0, 0, 10]])
knn_fold5 = np.matrix([[8, 0, 0], [0, 5, 2], [0, 1, 14]])
'''
'''
nb_fold1 = np.matrix([[11, 0, 0], [0, 8, 0], [0, 2, 9]])
nb_fold2 = np.matrix([[7, 0, 0], [0, 12, 0], [0, 1, 10]])
nb_fold3 = np.matrix([[12, 0, 0], [0, 8, 1], [0, 1, 8]])
nb_fold4 = np.matrix([[11, 0, 0], [0, 12, 0], [0, 0, 7]])
nb_fold5 = np.matrix([[9, 0, 0], [0, 8, 1], [0, 0, 12]])

average_confusion_matrices([nb_fold1, nb_fold2, nb_fold3, nb_fold4, nb_fold5])
'''


import json
import os.path

import geopy.distance
import networkx as nx
import numpy as np
import osmnx as ox
from geojson import FeatureCollection
from osgeo import ogr
from shapely.geometry import MultiPoint, Polygon
from tqdm import tqdm

from tracking_decorator import TrackingDecorator

def get_isochrone(logger, graph, start_point, travel_time, distance_attribute="time"):
    try:
        return get_possible_routes(
            graph=graph,
            start_point=start_point,
            travel_time=travel_time,
            distance_attribute=distance_attribute,
            calculate_walking_distance=True
        )
    except Exception as e:
        logger.log_line(f"✗ Exception: {str(e)}")
        return None, 0

def get_isochrone_metrics(logger, data_path, city_id, start_point, subgraph, walking_distance_meters):
    try:
        nodes, edges = ox.graph_to_gdfs(subgraph)

        # Define valid polygons
        polygon_file = os.path.join(data_path, "cities", city_id, "boundaries", "boundaries.geojson")
        valid_polygons = get_polygons(read_geojson(polygon_file))

        longitudes, latitudes = get_convex_hull(nodes=nodes)
        points = []

        # Filter points that are outside city limits
        for point in zip(longitudes, latitudes):

            p = ogr.Geometry(ogr.wkbPoint)
            p.AddPoint(point[0], point[1])

            # Check if point is within city limits
            if is_in_desired_area(p, valid_polygons):
                points.append([point[0], point[1]])
            else:
                logger.log_line(f"{city_id} point outside city {point[0]}, {point[1]}")

        convex_hull_polygon = Polygon(points)

        transport_distances_meters = get_distances(start_point=start_point, points=points)

        return np.mean(transport_distances_meters) + walking_distance_meters, \
               np.median(transport_distances_meters) + walking_distance_meters, \
               np.min(transport_distances_meters) + walking_distance_meters, \
               np.max(transport_distances_meters) + walking_distance_meters, \
               convex_hull_polygon.area
    except Exception as e:
        logger.log_line(f"✗ Exception: {str(e)}")
        return 0, 0, 0, 0, 0

def is_in_desired_area(point, valid_polygons):
    for polygon in valid_polygons:
        if point.Within(polygon):
            return True

    return False

def read_geojson(file_path):
    file = open(file_path)
    return json.load(file)

def get_polygons(geojson):
    polygons = []

    # Extract polygons from inhabitants file
    features = geojson["features"]

    for feature in features:
        geom = feature["geometry"]
        geom = json.dumps(geom)
        polygon = ogr.CreateGeometryFromJson(geom)

        polygons.append(polygon)

    return polygons

def get_possible_routes(graph, start_point, travel_time, distance_attribute, calculate_walking_distance=False):
    center_node, distance_to_nearest_node = ox.nearest_nodes(
        G=graph,
        X=start_point[1],
        Y=start_point[0],
        return_dist=True
    )

    if calculate_walking_distance:
        walking_speed_meters_per_minute = 100
        walking_time_minutes = distance_to_nearest_node / walking_speed_meters_per_minute

        walking_time_minutes_max = walking_time_minutes if walking_time_minutes < travel_time else travel_time
        walking_distance_meters = walking_time_minutes_max * walking_speed_meters_per_minute

        radius = travel_time - walking_time_minutes
    else:
        walking_distance_meters = 0
        radius = travel_time

    if radius > 0:
        return nx.ego_graph(graph, center_node, radius=radius, distance=distance_attribute), walking_distance_meters
    else:
        return None, walking_distance_meters

def get_convex_hull(nodes):
    return MultiPoint(nodes.reset_index()["geometry"]).convex_hull.exterior.coords.xy

def get_distances(start_point, points):
    return [geopy.distance.geodesic(point, start_point).meters for point in points]

def write_points_to_geojson(file_path, coords, travel_time):
    features = []
    for coord in coords:
        feature = {}
        feature["geometry"] = {"type": "Point", "coordinates": [coord["lon"], coord["lat"]]}
        feature["type"] = "Feature"
        feature["properties"] = {
            "mean_spatial_distance_" + str(travel_time) + "min": coord[
                "mean_spatial_distance_" + str(travel_time) + "min"],
            "median_spatial_distance_" + str(travel_time) + "min": coord[
                "median_spatial_distance_" + str(travel_time) + "min"],
            "min_spatial_distance_" + str(travel_time) + "min": coord[
                "min_spatial_distance_" + str(travel_time) + "min"],
            "max_spatial_distance_" + str(travel_time) + "min": coord[
                "max_spatial_distance_" + str(travel_time) + "min"],
            "area_" + str(travel_time) + "min": coord[
                "area_" + str(travel_time) + "min"],
        }
        features.append(feature)

    collection = FeatureCollection(features)

    with open(file_path, "w") as f:
        f.write("%s" % collection)

def write_nodes_to_geojson(file_path, graph):
    features = []

    if len(graph.nodes) > 0:
        for node_id in graph.nodes:
            node = graph.nodes[node_id]
            feature = {}
            feature["geometry"] = {"type": "Point", "coordinates": [node["x"], node["y"]]}
            feature["type"] = "Feature"
            features.append(feature)

    collection = FeatureCollection(features)

    with open(file_path, "w") as f:
        f.write("%s" % collection)

def write_polygon_to_geojson(file_path, graph):
    features = []
    coordinates = []

    for node_id in graph.nodes:
        node = graph.nodes[node_id]
        coordinates.append([node["x"], node["y"]])

    if len(graph.nodes) > 0:
        feature = {}
        feature["geometry"] = {"type": "Polygon", "coordinates": coordinates}
        feature["type"] = "Feature"
        features.append(feature)

    collection = FeatureCollection(features)

    with open(file_path, "w") as f:
        f.write("%s" % collection)

#
# Main
#

class IsochroneBuilder:

    @TrackingDecorator.track_time
    def run(self, logger, data_path, results_path, city_id, graph, sample_points, travel_time, start_time, end_time):
        points_with_spatial_distance = []
        failed_points = []

        # Make results path
        os.makedirs(os.path.join(results_path), exist_ok=True)

        for point_index in tqdm(iterable=range(len(sample_points)),
                                total=len(sample_points),
                                desc="Build isochrone",
                                unit="point"):
            point = sample_points[point_index]
            start_point = (float(point["lat"]), float(point["lon"]))

            # Calculate isochrone
            subgraph, walking_distance_meters = get_isochrone(
                logger=logger,
                graph=graph,
                start_point=start_point,
                travel_time=travel_time
            )

            # Determine isochrone metrics
            mean_spatial_distance, median_spatial_distance, min_spatial_distance, max_spatial_distance, area = get_isochrone_metrics(
                logger=logger,
                data_path=data_path,
                city_id=city_id,
                start_point=start_point,
                subgraph=subgraph,
                walking_distance_meters=walking_distance_meters
            )

            point_with_spatial_distance = {
                "lon": point["lon"],
                "lat": point["lat"],
                "mean_spatial_distance_" + str(travel_time) + "min": mean_spatial_distance,
                "median_spatial_distance_" + str(travel_time) + "min": median_spatial_distance,
                "min_spatial_distance_" + str(travel_time) + "min": min_spatial_distance,
                "max_spatial_distance_" + str(travel_time) + "min": max_spatial_distance,
                "area_" + str(travel_time) + "min": area
            }

            if mean_spatial_distance > 0:
                points_with_spatial_distance.append(point_with_spatial_distance)
            else:
                failed_points.append(point_with_spatial_distance)

        write_points_to_geojson(
            file_path=os.path.join(results_path, f"isochrones-{str(travel_time)}min-{start_time}-{end_time}.geojson"),
            coords=points_with_spatial_distance,
            travel_time=travel_time
        )

        write_points_to_geojson(
            file_path=os.path.join(results_path, f"isochrones-{str(travel_time)}min-{start_time}-{end_time}-failed.geojson"),
            coords=failed_points,
            travel_time=travel_time
        )

        return points_with_spatial_distance, failed_points

    @TrackingDecorator.track_time
    def run_for_place(self, logger, data_path, results_path, city_id, graph, travel_time, place):
        points_with_spatial_distance = []
        failed_points = []
        start_point = (place[1], place[0])

        # Make results path
        os.makedirs(os.path.join(results_path), exist_ok=True)

        # Calculate isochrone
        subgraph, walking_distance_meters = get_isochrone(
            logger=logger,
            graph=graph,
            start_point=start_point,
            travel_time=travel_time
        )

        # Determine isochrone metrics
        mean_spatial_distance, median_spatial_distance, min_spatial_distance, max_spatial_distance, area = get_isochrone_metrics(
            logger=logger,
            data_path=data_path,
            city_id=city_id,
            start_point=start_point,
            subgraph=subgraph,
            walking_distance_meters=walking_distance_meters
        )

        write_nodes_to_geojson(file_path=os.path.join(results_path, "isochrone-nodes-" + str(travel_time) + ".geojson"), graph=subgraph)
        write_polygon_to_geojson(file_path=os.path.join(results_path, "isochrone-hull-" + str(travel_time) + ".geojson"), graph=subgraph)

        point_with_spatial_distance = {
            "lon": start_point[1],
            "lat": start_point[0],
            "mean_spatial_distance_" + str(travel_time) + "min": mean_spatial_distance,
            "median_spatial_distance_" + str(travel_time) + "min": median_spatial_distance,
            "min_spatial_distance_" + str(travel_time) + "min": min_spatial_distance,
            "max_spatial_distance_" + str(travel_time) + "min": max_spatial_distance,
            "area_" + str(travel_time) + "min": area
        }

        if mean_spatial_distance > 0:
            points_with_spatial_distance.append(point_with_spatial_distance)
        else:
            failed_points.append(point_with_spatial_distance)

        write_points_to_geojson(
            file_path=os.path.join(results_path, "isochrones-" + str(travel_time) + ".geojson"),
            coords=points_with_spatial_distance,
            travel_time=travel_time
        )

        write_points_to_geojson(
            file_path=os.path.join(results_path, "isochrones-" + str(travel_time)) + "-failed.geojson",
            coords=failed_points,
            travel_time=travel_time
        )

        return points_with_spatial_distance, failed_points


from collections import deque

d = deque()

for _ in range(int(input())):
    inp = input().split(' ')
    if inp[0] == "append":
        d.append(int(inp[1]))
    elif inp[0] == "appendleft":
        d.appendleft(int(inp[1]))
    elif inp[0] == "pop":
        d.pop()
    elif inp[0] == "popleft":
        d.popleft()

print(*d)

# A deque is a double-ended queue. It can be used to add or remove elements from both ends.
# Deques support thread safe, memory efficient appends and pops from either side of the deque with
# approximately the same O(1) performance in either direction.

"""d = deque()
d.append(1)
print(d)
d.appendleft(2)
print(d)
d.clear()
print(d)
d.extend('1')
print(d)
d.extendleft('234')
print(d)
print(d.count('1'))
d.pop()
print(d)
d.popleft()
print(d)
d.extend('7896')
print(d)
d.remove('2')
print(d)
d.reverse()
print(d)
d.rotate(3)
print(d)"""


# 15486 : 퇴사 2
import sys, itertools

input = sys.stdin.readline
comb = []
N = int(input())

counseling = []
confirm = [0] * N

for _ in range(N):
    day, pay = map(sys.stdin.readline().split())
    counseling.append((_, day, pay))

for i in range(N, 0, -1):
    comb += list(itertools.combinations(list(range(N)), i))


"""
All available requests.
"""

import os, re
import traceback
from importlib import import_module
from muddery.server.settings import SETTINGS
from muddery.server.utils.logger import logger
from muddery.common.utils.utils import class_from_path
from muddery.common.utils.utils import get_module_path

class ElementSet(object):
    """
    All available classes.
    """
    def __init__(self):
        self.module_dict = {}
        self.class_dict = {}

        self.all_loaded = False
        self.match_class = re.compile(r'^class\s+(\w+)\s*.*$')
        self.match_key = re.compile(r""" {4}element_type\s*=\s*("|')(.+)("|')\s*$""")

    def load_files(self, component_path):
        """
        Get elements' file path.
        """
        if not component_path:
            return

        module = import_module(component_path)
        base_path = module.__path__
        if not base_path:
            return

        base_path = base_path[0]
        for root, dirs, files in os.walk(base_path):
            for filename in files:
                name, ext = os.path.splitext(filename)
                if ext != ".py":
                    continue

                with open(os.path.join(root, filename), "r", encoding="utf-8") as fp:
                    class_name = ""
                    for line in fp.readlines():
                        if not class_name:
                            match = self.match_class.match(line)
                            if match:
                                class_name = match.group(1)
                        else:
                            match = self.match_key.match(line)
                            if match:
                                key_name = match.group(2)

                                module_path = component_path
                                if base_path == root:
                                    module_path += "." + name + "." + class_name
                                else:
                                    relative_path = get_module_path(os.path.relpath(root, base_path))
                                    module_path += "." + relative_path + "." + name + "." + class_name

                                if key_name in self.module_dict:
                                    logger.log_debug("Element %s is replaced by %s." % (key_name, module_path))

                                self.module_dict[key_name] = module_path
                                class_name = ""

    def load_classes(self):
        """
        Add all elements from the element_type path.

        To prevent loop import, call this method later.
        """
        if self.all_loaded:
            return

        for key in self.module_dict:
            if key in self.class_dict:
                continue
            cls = class_from_path(self.module_dict[key])
            self.class_dict[key] = cls

        self.all_loaded = True

    def get(self, key):
        """
        Get a element_type recursively.
        """
        if key in self.class_dict:
            return self.class_dict[key]
        elif key in self.module_dict:
            try:
                cls = class_from_path(self.module_dict[key])
                if key in self.class_dict:
                    if self.class_dict[key] != cls:
                        logger.log_debug("Element %s is replaced by %s." % (key, cls))
                self.class_dict[key] = cls
                return cls
            except Exception as e:
                logger.log_trace("Load module error: %s" % e)

        # If can not find the element, return the base element.
        from muddery.server.elements.base_element import BaseElement
        return BaseElement

    def get_module(self, key):
        """
        Get a element_type's module path.
        """
        return self.module_dict.get(key, None)

    def get_group(self, group_key):
        """
        Get an element_type and all its children.
        """
        self.load_classes()

        group_class = self.class_dict[group_key]
        element_types = {group_key: group_class}

        for key in self.class_dict:
            if issubclass(self.class_dict[key], group_class):
                element_types[key] = self.class_dict[key]

        return element_types

    def get_class_models(self, key):
        """
        Get an element type's models.
        """
        cls = self.get(key)
        if cls:
            return cls.get_models()
        else:
            return []

    def get_all_info(self):
        """
        Get all element type's information.

        Return: (dict) all element type's information.
        """
        self.load_classes()

        info = {}
        for key, cls in self.class_dict.items():
            # Get the class's parent which has another element name.
            bases = cls.__bases__
            parent_type = ""
            while not parent_type:
                has_element_type = False
                for base in bases:
                    if hasattr(base, "element_type") and base.element_type:
                        has_element_type = True

                        if base.element_type != cls.element_type:
                            parent_type = base.element_type
                        else:
                            bases = base.__bases__
                        break

                if not has_element_type:
                    break

            info[key] = {
                "name": cls.element_name,
                "parent": parent_type
            }

        return info

ELEMENT_SET = ElementSet()
ELEMENT = ELEMENT_SET.get
ELEMENT_SET.load_files(SETTINGS.PATH_ELEMENTS_BASE)
ELEMENT_SET.load_files(SETTINGS.PATH_ELEMENTS_CUSTOM)


from celery import Celery
from flask_mail import Message

from _15thnight.email import mailer
from _15thnight.twilio_client import send_sms

try:
    from config import CELERY_BROKER
except:
    from configdist import CELERY_BROKER

celery = Celery('15thnight', broker=CELERY_BROKER)

def init_app(app):
    TaskBase = celery.Task

    class ContextTask(TaskBase):
        abstract = True

        def __call__(self, *args, **kwargs):
            with app.app_context():
                return TaskBase.__call__(self, *args, **kwargs)

    celery.Task = ContextTask

@celery.task
def queue_send_message(email, number, subject, body):
    """
    Celery task to send messages out in sms and email.
    """
    if number:
        send_sms(to_number=number, body=body)
    message = Message(body=body, subject=subject, recipients=[email])
    mailer.send(message)

@celery.task
def queue_send_email(message):
    mailer.send(message)


from .Utils.Util_Classes import *
from .Utils.preprocessor import *
from .Utils.Util_Functions import *
import spacy

def extract_tuples(inp):
	# Doc is the tokenized spacy document with all relationships
	root,verb_list,doc,sentence = preprocess(inp)
	verb = root
	verbs1 = [ "is" , "was" ,"were","are" , "been", "be"]
	verbs2 = ["has", "had", "have","having"]
	verbs3 = [""]
	aux_tups = []
	if len(verb_list) > 1:
		for ent in doc.ents:
	#         print(ent.text,ent.label_)
			#doc2 =  nlp(ent.text)
			if(ent.label_=="CARDINAL"):
				#Split the numbers and units
				ents = ent.text.split(' ')
				for i in range(len(ents)):
					try:
						ents[i] = w2n.word_to_num(ents[i])
					except:
						if(re.match(r"[-+]?\d*\.\d+|\d+", ents[i])):
							ents[i] = float(ents[i])
							sentence = sentence.replace(ent.text,str(ents[i]*int(w2n.word_to_num(ents[i+1]))))
						else:
							ents[i] = ents[i]
							break
		nlp = spacy.load("en")
		doc = nlp(sentence)
		for i in doc:
			if(i.dep_=="prep"):
				for j in i.children:
					if(j.dep_=="pobj" or j.dep_=="dobj"):
						print(i.head.text,i.text,j.text)
						aux_tups.append(Rels(i.head.text,i.text,j.text))
						if(i.text=="between"):
							for m in j.children:
								if(m.dep_=="conj"):
									print(m.text)
	else:
		if(verb.text in verbs1):
			tuples = plotTuple()
			print("Case 1")
			for i in verb.children:
				if(i.dep_=="nsubj" and (i.pos_ == "NOUN" or i.pos_ == "PROPN")):
					print(i.text)
		#             print(find_compound_dependencies(i,i.text))
					if i.pos_ == "PROPN":
						tuples.subject = i.text
					else:
						tuples.domain = i.text
						tuples.attribute = find_compound_dependencies(i,i.text)
					for j in i.children:
						if (j.dep_ == "poss" and (j.pos_=="PROPN" or j.pos_=="NOUN" or j.pos_=="PRON")):
							print(j.text)
							tuples.subject = j.text
						if(j.dep_ == "prep" and (j.text=="of" or j.text=="for") and j.pos_=="ADP"):
							print(j.text)
							print(find_compound_dependencies(j,j.text))
							for m in j.children:
								if(m.dep_ == "pobj" and (m.pos_ == "NOUN" or m.pos_ == "PROPN" or m.pos_ == "PRON")):
									print(i.text,j.text,m.text)
									print(find_compound_dependencies(m,m.text))
									tuples.subject = m.text
									break
							break
					for j in verb.children:
						if(j.dep_ == "attr"):
							print(j.text)
							#print(find_compound_dependencies(j,j.text))
							if j.text == "%":
								for k in j.children:
									if k.pos_ == "NUM":
										print(k.text)
										tuples.value = k.text+j.text
							else:
								tuples.value = find_compound_dependencies(j,j.text)
							break
				if(i.dep_ == "nsubj" and (i.pos_ == "NOUN" or i.pos_ == "PROPN" or i.pos_=="PRON")):
					for j in i.children:
						if(j.dep_=="acomp" and (j.pos_ == "ADJ" or j.pos_ == "ADV")):
							for k in j.children:
								if(k.dep_ == "npadvmod"):
									print(k.text,j.text,i.text)
									break
							break
		elif(verb.text in verbs2):
			tuples = plotTuple()
			print("Case 2")
			for i in verb.children:
				if(i.dep_=="dobj" and (i.pos_=="NOUN" or i.pos_=="PROPN")):
					if i.pos_ == "NOUN":
						tuples.domain = i.text
						tuples.attribute = find_compound_dependencies(i,i.text)
					for j in i.children:
						if(j.dep_=="prep" and j.pos_=="ADP"):
							print(j.text)
							print(find_compound_dependencies(j,j.text))
							for m in j.children:
								if(m.dep_=="pobj"):
									print(m.text,j.text,i.text)
									tuples.value = find_compound_dependencies(m,m.text)
									break
							break
					for j in verb.children:
						if(j.dep_=="nsubj" and (j.pos_ == "NOUN" or j.pos_ == "PROPN" or j.pos_=="PRON")):
							print(j.text)
							if j.pos_ == "PROPN":
								tuples.subject = j.text
				elif(i.dep_=="nsubj" and (i.pos_=="NOUN" or i.pos_=="PROPN" or i.pos_=="PRON")):
					if i.pos_ == "PROPN":
						tuples.subject = i.text
					for j in i.children:
						if(j.dep_=="dobj"):
							tuples.domain = j.text
							tuples.attribute = find_compound_dependencies(j,j.text)
							for m in j.children:
								if(m.text=="of" and m.dep_=="prep" and m.pos_=="ADP"):
									tuples.value = m.text
									print(m.text,j.text,i.text)
									break
							break
		else:
			print("Case 3")
			tuples = plotTuple()
			for i in verb.children:
				if(i.dep_=="attr" or i.dep_=="acomp"):
					for j in verb.children:
						if(j.dep_=="nsubj" and (j.pos_ == "NOUN" or j.pos_ == "PROPN" or j.pos_=="PRON")):
							for m in j.children:
								if(m.dep_=="poss" and (m.pos_=="PROPN" or m.pos_=="NOUN")):
									print(m.text,j.text.i.text)
									break
							break
					break
				if(i.dep_=="auxpass" and i.text in verbs1):
					for j in verb.children:
						if(j.dep_=="nsubjpass" and (j.pos_ == "NOUN" or j.pos_ == "PROPN" or j.pos_=="PRON")):
							for m in verb.children:
								if(m.dep_=="prep" and m.pos_=="ADP"):
									for n in m.children:
										if(n.dep_=="pobjprint(find_compound_dependencies(i,i.text))"):
											print(n.text,m.text,j.text,i.text)
											break
									break
							break
					break
				if (i.dep_ =="nsubj") and (i.pos_ == "NOUN" or i.pos_ == "PROPN" or i.pos_ == "PRON"):
					print(i.text)
					tuples.domain = i.text
					for j in i.children:
						if j.dep_ == "poss" and (j.pos_ == "PROPN" or j.pos_ == "NOUN" or j.pos_ == "PRON"):
							print(j.text)
							tuples.subject = j.text
							break
					for j in verb.children:
						if (j.dep_ == "dobj") and j.pos_ == "NUM":
							print(find_compound_dependencies(j,j.text))
							tuples.value = find_compound_dependencies(j,j.text)
					break
	if len(aux_tups) != 0:
		res = [i.get_res() for i in aux_tups]

	final_results = []

	if len(verb_list) > 1:
		tuples = get_data_from_string(doc,res)
		for i in tuples:
			final_results.append(i.get_tuple())
	else:
		#work with normal tuple
		final_results.append(tuples.get_tuple())
	print(final_results)
	return final_results


"""Factory for creating a transfer learning models."""
import dacite.core

from simba_ml.prediction.time_series import models
from simba_ml.prediction.time_series.models import transfer_learning_model
from simba_ml.prediction.time_series.config import (
    time_series_config,
)
from simba_ml.prediction.time_series.models import model_to_transfer_learning_model

class ModelNotFoundError(Exception):
    """Raised when a model type is not found."""

model_config_creation_funcs: dict[
    str,
    tuple[
        type[models.model.ModelConfig],
        type[transfer_learning_model.TransferLearningModel],
    ],
] = {}

def register(
    model_id: str,
    config_class: type[models.model.ModelConfig],
    model_class: type[transfer_learning_model.TransferLearningModel],
) -> None:
    """Register a new model type.

    Args:
        model_id: the model type to register.
        config_class: the configuration class for the model.
        model_class: the model class.
    """
    model_config_creation_funcs[model_id] = (config_class, model_class)

def unregister(model_id: str) -> None:
    """Unregister a model type.

    Args:
        model_id: the model type to unregister.
    """
    model_config_creation_funcs.pop(model_id, None)

def create(
    model_id: str,
    model_dict: dict[str, object],
    time_series_params: time_series_config.TimeSeriesConfig,
) -> transfer_learning_model.TransferLearningModel:
    """Create a model of a specific type, given JSON data.

    Args:
        model_id: the model type to create.
        model_dict: the JSON data to use to create the model.
        time_series_params: the time series configuration.

    Returns:
        The created model if model can be created, None otherwise.

    Raises:
        ModelNotFoundError: if the model type is unknown.
    """
    try:
        config_class, Model_class = model_config_creation_funcs[model_id]
    except KeyError as e:
        raise ModelNotFoundError(f"Model type {model_id} not found") from e

    model_config: models.model.ModelConfig = dacite.from_dict(
        data_class=config_class, data=model_dict, config=dacite.Config(strict=True)
    )
    model = Model_class(time_series_params, model_config)
    return model

register(
    "LastValuePredictor",
    models.last_value_predictor.LastValuePredictorConfig,
    model_to_transfer_learning_model.model_to_transfer_learning_model_with_pretraining(
        models.last_value_predictor.LastValuePredictor
    ),
)


import sys
from collections import deque

input = lambda: sys.stdin.readline().rstrip()

def print(*args, sep=' ', end='\n'):
    sys.stdout.write(sep.join(map(str, args)))
    sys.stdout.write(end)

def solution():
    n = int(input())
    q = deque([1])
    seen = {1}
    ans = [-1 for i in range(n)]
    while q:
        num = q.popleft()
        for factor in [2, 3, 5]:
            x = num * factor % n
            if x not in seen:
                q.append(x)
                seen.add(x)
                ans[x] = num
    print(*ans)

def main():
    t = 1
    while t:
        solution()
        t -= 1

if __name__ == '__main__':
    main()


from __future__ import print_function
from contra import BloomFilter, CountFilter, BigCountFilter
import random
import sys
from tempfile import NamedTemporaryFile

def test_filter_basic():
    """
    Test basic essentials: contruct, add, get
    """
    bf = BloomFilter(90, 2)
    bf.insert(101)
    assert bf.query(101) is True
    assert bf.query(100) is False

    cf = CountFilter(120, 2)
    cf.insert(101)
    assert cf.query(101) == 1
    assert cf.query(100) == 0
    for i in range(100):
        cf.insert(101)
    assert cf.query(101) == 101

    bcf = BigCountFilter(200, 2)
    bcf.insert(101)
    assert bcf.query(101) == 1
    assert bcf.query(100) == 0
    for i in range(1024):
        bcf.insert(101)
    assert bcf.query(101) == 1025

def test_filter_size():
    bf = BloomFilter(90, 2)
    # 90 bytes / 2 hash functions * 8 buckets per byte = 360 buckets per table
    # The closest prime numbers to 360 are 359 and 353
    assert len(bf) == 359 + 353
    bf.insert(101)
    assert len(bf) == 359 + 353

    # 2000 bytes / 2 hash functions * 1 bucket per byte = 1000 buckets per table
    cf = CountFilter(2000, 2)
    assert len(cf) == 997 + 991
    cf.insert(101)
    assert len(cf) == 997 + 991

    # 16000 bytes / 4 hash functions / 4 bytes per bucket per byte = 1000 buckets per table
    bcf = BigCountFilter(16000)
    assert len(bcf) == 997 + 991 + 983 + 977
    bcf.insert(101)
    assert len(bcf) == 997 + 991 + 983 + 977

def test_filter_save_load():
    # Populate a count filter with 100 random elements between 1 and 100,000,
    # each element with a random abundance between 1 and 10.
    counts = CountFilter(5e4, 4)
    testcounts = dict()
    for _ in range(100):
        element = random.randint(0, 1e5)
        abund = random.randint(1, 10)
        testcounts[element] = abund
        for _ in range(abund):
            counts.insert(element)

    # Save the filter to disk, load it again, and check to make sure everything
    # matches.
    loadcounts = CountFilter(1, 1)
    with NamedTemporaryFile(suffix='.kct') as diskfile:
        counts.save(diskfile.name)
        loadcounts.load(diskfile.name)
    for e in range(int(1e5)):
        if e in testcounts:
            assert loadcounts.query(e) == testcounts[e]
        else:
            assert loadcounts.query(e) == 0


import unittest
from collections import namedtuple
from ripe.atlas.tools.renderers.aggregate_ping import Renderer
from ripe.atlas.sagan import Result

from ..base import capture_sys_output

class TestAggregatePing(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.results = [
            {u'af': 4, u'prb_id': 11421, u'result': [{u'rtt': 42.342895}, {u'rtt': 42.220215}, {u'rtt': 42.40614}], u'ttl': 53, u'avg': 42.3230833333, u'size': 48, u'from': u'178.11.85.39', u'proto': u'ICMP', u'timestamp': 1446146495, u'dup': 0, u'type': u'ping', u'sent': 3, u'msm_id': 2882184, u'fw': 4720, u'max': 42.40614, u'step': 240, u'src_addr': u'192.168.2.101', u'rcvd': 3, u'msm_name': u'Ping', u'lts': 3, u'dst_name': u'194.88.241.228', u'min': 42.220215, u'group_id': 2882184, u'dst_addr': u'194.88.241.228'},
            {u'af': 4, u'prb_id': 11779, u'result': [{u'rtt': 76.61127}, {u'rtt': 76.38997}, {u'rtt': 76.47354}], u'ttl': 51, u'avg': 76.4915933333, u'size': 48, u'from': u'79.106.99.242', u'proto': u'ICMP', u'timestamp': 1446146494, u'dup': 0, u'type': u'ping', u'sent': 3, u'msm_id': 2882184, u'fw': 4720, u'max': 76.61127, u'step': 240, u'src_addr': u'192.168.1.110', u'rcvd': 3, u'msm_name': u'Ping', u'lts': 127, u'dst_name': u'194.88.241.228', u'min': 76.38997, u'group_id': 2882184, u'dst_addr': u'194.88.241.228'},
            {u'af': 4, u'prb_id': 17854, u'result': [{u'rtt': 154.118}, {u'rtt': 154.197}, {u'rtt': 154.845}], u'ttl': 55, u'avg': 154.3866666667, u'size': 48, u'from': u'134.202.20.3', u'proto': u'ICMP', u'timestamp': 1446146493, u'dup': 0, u'type': u'ping', u'sent': 3, u'msm_id': 2882184, u'fw': 4700, u'max': 154.845, u'step': 240, u'src_addr': u'134.202.20.3', u'rcvd': 3, u'msm_name': u'Ping', u'lts': 1, u'dst_name': u'194.88.241.228', u'min': 154.118, u'group_id': 2882184, u'dst_addr': u'194.88.241.228'},
            {u'af': 4, u'prb_id': 3183, u'result': [{u'rtt': 42.263816}, {u'rtt': 42.196233}, {u'rtt': 42.342921}], u'ttl': 56, u'avg': 42.2676566667, u'size': 48, u'from': u'212.122.42.107', u'proto': u'ICMP', u'timestamp': 1446146494, u'dup': 0, u'type': u'ping', u'sent': 3, u'msm_id': 2882184, u'fw': 4720, u'max': 42.342921, u'step': 240, u'src_addr': u'192.168.189.1', u'rcvd': 3, u'msm_name': u'Ping', u'lts': 3, u'dst_name': u'194.88.241.228', u'min': 42.196233, u'group_id': 2882184, u'dst_addr': u'194.88.241.228'},
            {u'af': 4, u'prb_id': 3207, u'result': [{u'rtt': 218.077484}, {u'rtt': 36.921608}, {u'rtt': 38.99444}], u'ttl': 49, u'avg': 97.997844, u'size': 48, u'from': u'134.3.245.244', u'proto': u'ICMP', u'timestamp': 1446146494, u'dup': 0, u'type': u'ping', u'sent': 3, u'msm_id': 2882184, u'fw': 4720, u'max': 218.077484, u'step': 240, u'src_addr': u'10.30.0.4', u'rcvd': 3, u'msm_name': u'Ping', u'lts': 70, u'dst_name': u'194.88.241.228', u'min': 36.921608, u'group_id': 2882184, u'dst_addr': u'194.88.241.228'}
        ]
        cls.sagans = [
            Result.get(
                result,
                on_error=Result.ACTION_IGNORE,
                on_warning=Result.ACTION_IGNORE
            ) for result in cls.results
        ]

    def test_additional(self):
        """Tests whole functionality of additional unit."""
        expected_output = (
            "-- 194.88.241.228 ping statistics ---\n"
            "15 packets transmitted, 15 received, 0.0% loss\n"
            "rtt min/med/avg/max = 36.921608/42.406/82.693/218.077484 ms\n\n"
        )

        self.assertEquals(Renderer().additional(self.sagans), expected_output)

    def test_collect_stats(self):
        """Tests collect stats function."""

        renderer = Renderer()
        renderer.collect_stats(self.sagans)
        self.assertEquals(
            renderer.rtts,
            [
                42.343, 42.22, 42.406, 76.611, 76.39, 76.474, 154.118, 154.197,
                154.845, 42.264, 42.196, 42.343, 218.077, 36.922, 38.994
            ]
        )
        self.assertEquals(renderer.target, "194.88.241.228")
        self.assertEquals(renderer.sent_packets, 15)
        self.assertEquals(renderer.received_packets, 15)
        self.assertEquals(
            renderer.rtts_min,
            [42.220215, 76.38997, 154.118, 42.196233, 36.921608]
        )
        self.assertEquals(
            renderer.rtts_max,
            [42.40614, 76.61127, 154.845, 42.342921, 218.077484]
        )

    def test_collect_min_max_rtts(self):
        """Test use cases for collecting min max rtts."""
        renderer = Renderer()
        renderer.collect_min_max_rtts("min", 3)
        self.assertEquals(renderer.rtts_min, [3])
        renderer.collect_min_max_rtts("min", None)
        self.assertEquals(renderer.rtts_min, [3, 0])

        renderer.collect_min_max_rtts("max", 3)
        self.assertEquals(renderer.rtts_max, [3])
        renderer.collect_min_max_rtts("max", None)
        self.assertEquals(renderer.rtts_max, [3, 0])

    def test_collect_packets_rtt(self):
        """Test use cases for collecting rtts."""
        Packet = namedtuple("Packet", "rtt")
        packets = [Packet(rtt=2), Packet(rtt=3.2), Packet(rtt=5.0)]
        renderer = Renderer()
        renderer.collect_packets_rtt(packets)
        self.assertEquals(renderer.rtts, [2, 3.2, 5.0])

        packets = [Packet(rtt=None), Packet(rtt=3.2), Packet(rtt=5.0)]
        renderer = Renderer()
        renderer.collect_packets_rtt(packets)
        self.assertEquals(renderer.rtts, [0, 3.2, 5.0])

    def test_set_target(self):
        """Tests setting the target."""
        Sagan = namedtuple("Sagan", "destination_name")
        renderer = Renderer()
        sagan = Sagan(destination_name="1")
        renderer.set_target(sagan)
        self.assertEquals(renderer.target, "1")
        sagan = Sagan(destination_name="2")
        renderer.set_target(sagan)
        self.assertEquals(renderer.target, "1")

    def test_calculate_loss(self):
        """Test use cases for calculating loss."""
        renderer = Renderer()
        renderer.sent_packets = 10
        renderer.received_packets = 9
        self.assertEquals(renderer.calculate_loss(), 9.999999999999998)
        renderer.sent_packets = 0
        self.assertEquals(renderer.calculate_loss(), 0)
        renderer.received_packets = 0
        renderer.sent_packets = 10
        self.assertEquals(renderer.calculate_loss(), 100)
        renderer.received_packets = 5
        self.assertEquals(renderer.calculate_loss(), 50)

    def test_mean(self):
        """Test use cases for calculating mean."""
        renderer = Renderer()
        renderer.rtts = [0, 2.0, 5.0, 20]
        self.assertEquals(renderer.mean(), 6.75)
        renderer.rtts = [0, 2.0, 7.5, 5.0, 20]
        self.assertEquals(renderer.mean(), 6.9)
        renderer.rtts = [0, 2.0, 7.5, 5.0, 20, 50]
        self.assertEquals(renderer.mean(), 14.083)

    def test_median(self):
        """Test use cases for calculating median."""
        renderer = Renderer()
        renderer.rtts = [0, 2.0, 5.0, 20]
        self.assertEquals(renderer.median(), 3.5)
        renderer.rtts = [0, 2.0, 7.5, 5.0, 20]
        self.assertEquals(renderer.median(), 5)
        renderer.rtts = [0, 2.0, 7.5, 5.0, 20, 50]
        self.assertEquals(renderer.median(), 6.25)


#!/usr/bin/env python3
from Bio import Align
from Bio import SeqIO
import gzip
import pandas as pd
import csv
from Bio import pairwise2
from itertools import islice
import time
import multiprocessing

def align_DNA(query, target,
              alignment_method="pairwise2",
              mode='local',
              match_score=1,
              mismatch_score=-2,
              open_gap_score=-10,
              extend_gap_score=-1) -> dict:
    """
    Perform local alignment of two DNA sequences.

    Input: query -- Bio.Seq.Seq object, the sequencing read to map to target sequence
           target -- Bio.Seq.Seq object, the reference sequence.
           alignment_method -- the method used to perform sequence alignment, "pairwise2" or "PairwiseAligner", "pairwise2" is the default
           mode -- parameter to pass to the biopython Bio.Align.PairwiseAligner object.
           match_score, mismatch_score, open_gap_score, extend_gap_score -- parameters to pass to the biopython Bio.Align.PairwiseAligner object.

    Output: alignment_lib -- A dictionary object containing the information to describe the DNA level mutations.

    """

    # Standardize both sequences to upper cases.
    read_seq = query.upper()
    reference_seq = target.upper()

    if alignment_method=="PairwiseAligner":
    ### Alignment using PairwiseAligner
        # Create a PairwiseAligner object.
        aligner = Align.PairwiseAligner(mode='local',
                                        match_score=match_score,
                                        mismatch_score=mismatch_score,
                                        open_gap_score=open_gap_score,
                                        extend_gap_score=extend_gap_score)

        alignment = list(aligner.align(reference_seq, read_seq, strand='+'))[0]
        alignment_r = list(aligner.align(reference_seq, read_seq, strand='-'))[0]
        strand = 'forward'
        alignment_start=alignment.indices[1][alignment.indices[1] > 0].min()

        if alignment_r.score > alignment.score:
            strand = 'reverse'
            alignment = alignment_r
            read_seq = read_seq.reverse_complement()
            alignment_start = len(read_seq) - alignment.indices[1][alignment.indices[1] > 0].max() -1 ## the -1 is important. Otherwise the alignments on the reverse strands will be shifted by one digit to miss the one bp on the 5' end and gain one bp on the 3' end.

        reference = alignment[0] # str, with '-' for insertion
        query = alignment[1] # str, with '-' for deletion
        alignment_length = len(alignment[0]) # alignment[0] is the target sequence, with '-' for insertsion

    ### Alignment using PairwiseAligner done

    elif alignment_method=="pairwise2":
    ### Alignment using pairwise2 localms

        # perform alignment
        alignments = pairwise2.align.localms(read_seq,
                                             reference_seq,
                                             match_score,
                                             mismatch_score,
                                             open_gap_score,
                                             extend_gap_score,
                                             one_alignment_only=True)

        alignments_r = pairwise2.align.localms(read_seq.reverse_complement(),
                                               reference_seq,
                                               match_score,
                                               mismatch_score,
                                               open_gap_score,
                                               extend_gap_score,
                                               one_alignment_only=True)
        strand = 'forward'

        if alignments_r[0][2] > alignments[0][2]:
            alignments = alignments_r
            read_seq = read_seq.reverse_complement()
            strand = 'reverse'

        # Get the alignment with the highest score (assuming unique alignment)
        best_alignment = alignments[0]

        # Get the starting position
        alignment_start = best_alignment[3]
        alignment_end = best_alignment[4]

        # Calculate alignment statistics
        reference = best_alignment[1].strip('-')
        # alignment_length = len(re.findall(r'ATG.*', reference)[0])
        alignment_length = alignment_end - alignment_start
        query = best_alignment[0][alignment_start: alignment_start+alignment_length]

    ### Alignment using pairwise2 localms done

    insertions = []
    deletions = []
    substitutions = []

    for j in range(len(query)):
        if query[j] == '-':
            deletions.append(j)
        elif reference[j] == '-':
            insertions.append(j)
        elif (query[j] != reference[j]):
            substitutions.append(reference[j]+str(j)+query[j])

    alignment_lib={"sequence": read_seq[alignment_start:alignment_start+alignment_length-len(deletions)],
                   "read_length": len(read_seq),
                   "alignment_start": alignment_start,
                   "alignment_length": alignment_length,
                   "insertions": insertions,
                   "num_insertions": len(insertions),
                   "deletions":deletions,
                   "num_deletions":len(deletions),
                   "substitutions": substitutions,
                   "num_substitutions":len(substitutions),
                   "strand":strand}

    return alignment_lib

def align_DNA_write_to_csv(input_file,
                           output_file,
                           target,
                           alignment_method="pairwise2",
                           mode='local',
                           match_score=1,
                           mismatch_score=-2,
                           open_gap_score=-10,
                           extend_gap_score=-1,
                           set_num_iterations=True,
                           start_read=0,
                           num_iterations=500):
    """
    Function that reads in sequences from a .fastq.gz file, perform alignment and save each entry to .csv at a time.

    input: input_file -- str, input file path
           output_file -- str, output file path
           target -- Bio.Seq.Seq object, the reference sequence, to be passed into mutalign.align_DNA()
           alignment_method -- the method used to perform sequence alignment, "pairwise2" or "PairwiseAligner", "pairwise2" is the default
           mode -- parameter to pass to the biopython Bio.Align.PairwiseAligner object, , to be passed into mutalign.align_DNA()
           match_score, mismatch_score, open_gap_score, extend_gap_score -- parameters to pass to the biopython Bio.Align.PairwiseAligner object, to be passed into mutalign.align_DNA()
           set_num_iterations -- bool, whether or not the user intends to set an upper limit on the number of entries to process, default is True. When set to false, the function processes the entire fastq.gz set.
           start_iter -- int, the index of read to start reading.
           num_iterations -- int, to be set if set_num_iterations is True. Default is 500

    """
    with open(output_file, mode='w', newline='') as csv_file:

        # if user not intended to set the number of entries to align, the default is the iterate through the entire dataset
        if not set_num_iterations:
            with gzip.open(input_file, "rt") as handle:
                num_iterations = sum([1 for _ in SeqIO.parse(handle, 'fastq')])

        ct=0
        with gzip.open(input_file, "rt") as handle:
            seq_iter=SeqIO.parse(handle, 'fastq')
            if start_read !=0:
                seq_iter=islice(seq_iter, start_read, None)
            for record in seq_iter:

                try:
                    # prioritize the alignment method specified by user,
                    # using multithread to eliminate sequences causing dead kernal.
                    # Use multiprocessing to run PairwiseAligner with a timeout. The processing time increases 10% for each sequence. multithreading is more lightweight but really doesn't prevent the kernel from dying.
                    pool = multiprocessing.Pool(processes=1)
                    aligner_result = pool.apply_async(align_DNA, args=(record.seq, target),
                                                     kwds={'alignment_method':'PairwiseAligner',
                                                           'mode':mode,
                                                           'match_score':match_score,
                                                           'mismatch_score':mismatch_score,
                                                           'open_gap_score':open_gap_score,
                                                           'extend_gap_score':extend_gap_score})
                    alignment_result = aligner_result.get(timeout=5)  # Set an appropriate timeout value
                    pool.terminate()  # Terminate the process to free up resources
                except multiprocessing.TimeoutError:
                    # In case of timeout, use pairwise2 aligner instead
                    alignment_result = align_DNA(record.seq, target,
                                                    alignment_method='pairwise2',
                                                    mode=mode,
                                                    match_score=match_score,
                                                    mismatch_score=mismatch_score,
                                                    open_gap_score=open_gap_score,
                                                    extend_gap_score=extend_gap_score)

                except MemoryError:  # if pairwisealigner generates a memory error, use pairsise2
                    alignment_result = align_DNA(record.seq,
                                                 target=target,
                                                 alignment_method='pairwise2',
                                                 mode=mode,
                                                 match_score=match_score,
                                                 mismatch_score=mismatch_score,
                                                 open_gap_score=open_gap_score,
                                                 extend_gap_score=extend_gap_score)  # Assuming `target_sequence` is defined

                alignment_start=alignment_result["alignment_start"]
                alignment_length=alignment_result["alignment_length"]
                num_deletions=alignment_result["num_deletions"]
                # read_seq[alignment_start:alignment_start+alignment_length-num_deletions]

                alignment_result.update({'sequence_id':record.id})
                alignment_result.update({'quality':record.letter_annotations["phred_quality"][alignment_start:alignment_start+alignment_length-num_deletions]})

                if ct == 0: # first iteration writes the header
                    writer = csv.DictWriter(csv_file, fieldnames=alignment_result.keys())
                    writer.writeheader() # write the header for the output .csv file

                writer.writerow(alignment_result) # write one row per iteration

                ct+=1 # iterate until the set limit

                if ct%100 == 0:
                    print(f'{ct} iterations done')
                if ct >= num_iterations:
                    break

def align_all_DNA(file_path, target, exclude_short=False):
    """
    Extract every seq in a fastq.gz file, align them to a target seq and calculate
    indels and substitutions. Save results to a pandas DataFrame

    input: filepath -- str, path of the fastq.gz file
           target -- Bio.Seq.Seq object to be used as the target for alignment
           exclude_short -- int if not False, the minimum number of bps in the read to allow the read to be included to the output df
    """
    if file_path[-8:] != 'fastq.gz':
        raise TypeError('The input file should have a .fastq.gz format')

    with gzip.open(file_path, "rt") as handle:
        # Use SeqIO.parse() to read and parse the sequences
        record_list = []
        for record in SeqIO.parse(handle, "fastq"):
            record_lib={}
            record_lib['sequence_id'] = record.id
            record_lib['sequence'] = record.seq
            # when exclude_short is specified, short reads are excluded from the df.
            if (exclude_short) and (len(record.seq)<exclude_short):
                continue
            # when exclude_short is not specified, or if the read is long, info included in the output df
            else:
                record_lib['quality_scores'] = record.letter_annotations["phred_quality"]
                record_lib.update(align_DNA(record.seq, target))
                record_list.append(record_lib)

    return pd.DataFrame(record_list)


import base64
import imghdr

from tests.support.asserts import assert_error, assert_success
from tests.support.inline import inline

def take_element_screenshot(session, element_id):
    return session.transport.send(
        "GET",
        "session/{session_id}/element/{element_id}/screenshot".format(
            session_id=session.session_id,
            element_id=element_id,
        )
    )

def test_no_browsing_context(session, closed_window):
    response = take_element_screenshot(session, "foo")
    assert_error(response, "no such window")

def test_screenshot(session):
    session.url = inline("<input>")
    element = session.find.css("input", all=False)

    response = take_element_screenshot(session, element.id)
    value = assert_success(response)

    image = base64.decodestring(value)
    assert imghdr.what("", image) == "png"

def test_stale(session):
    session.url = inline("<input>")
    element = session.find.css("input", all=False)
    session.refresh()

    result = take_element_screenshot(session, element.id)
    assert_error(result, "stale element reference")


from datetime import datetime

from django.core.management.base import BaseCommand

from myapp_1.models import Client

class Command(BaseCommand):
    help = 'Create client'

    def handle(self, *args, **kwargs):
        client = Client(name='john conor', email='Judgment_Day@mail.com', telephone=000000000, address='Los Angeles',
                        registration_date=datetime.now())

        client.save()
        self.stdout.write(f'{client}')


import pandas as pd
from datetime import datetime
import requests
from bs4 import BeautifulSoup

import csv

fl = open('test_dataset.csv', 'w', encoding='UTF8')

header = ['source_url', 'access_datetime', 'content', 'word']
writer = csv.writer(fl, delimiter='&')
writer.writerow(header)

urls = ['https://kun.uz/uz/news/2022/12/01/uch-tomonlama-ittifoq-tashqi-kuchlar-qolidagi-ozbek-gazi-va-volodinning-hurmatsizligi-siyosatshunoslar-bilan-suhbat', 'https://stadion.uz/uz/news/detail/359943', 'https://qalampir.uz/uz/news/2050-yilga-borib-5-milliarddan-kup-odam-suv-tank-isligiga-uchraydi-bmt-73059', 'https://daryo.uz/2022/12/02/ozbekistonda-dam-olish-kunlari-qanday-ob-havo-boladi-3/']
for url in urls:
	response = requests.get(url)
	soup = BeautifulSoup(response.text, 'html.parser')
	page = soup.findAll('p')
	content = []
	acc_time = datetime.now().strftime("%m-%d-%Y, %H:%M")
	for pg in page:
		content.append(pg.get_text())
	words = ' '.join(content)
	word = words.split(" ")
	data = [url, acc_time, content, word]
	writer.writerow(data)


from collections import deque

dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
n, m, p = map(int, input().split())
answer = [0] * p
s = list(map(int, input().split()))
a = [list(input()) for _ in range(n)]
queue = [deque() for _ in range(p)]
next_queue = [deque() for _ in range(p)]

for i in range(n):
    for j in range(m):
        if a[i][j] != "." and a[i][j] != "#":
            a[i][j] = int(a[i][j]) - 1
            queue[a[i][j]].append((i, j))

while True:
    ok = False

    for i in range(p):
        d = [[0] * m for _ in range(n)]

        while queue[i]:
            ok = True
            x, y = queue[i].popleft()

            if d[x][y] == s[i]:
                next_queue[i].append((x, y))

            if a[x][y] != "." and a[x][y] != "#" and a[x][y] != i:
                continue

            a[x][y] = i

            for j in range(4):
                nx, ny = x + dx[j], y + dy[j]

                if 0 <= nx < n and 0 <= ny < m:
                    if a[nx][ny] == ".":
                        d[nx][ny] = d[x][y] + 1

                        if d[nx][ny] <= s[i]:
                            queue[i].append((nx, ny))
                            a[nx][ny] = i

        queue[i] = next_queue[i]
        next_queue[i] = deque()

    if not ok:
        break

for i in range(n):
    for j in range(m):
        if a[i][j] != "." and a[i][j] != "#":
            answer[a[i][j]] += 1

print(*answer)


from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from typing import List, Dict

from ...base_neko import BaseNeko

def assemble_markup(markup: List[List[Dict[str, str]]]) -> InlineKeyboardMarkup:
    final_markup = InlineKeyboardMarkup()
    for row in markup:
        row_buttons = []
        for button in row:
            row_buttons.append(InlineKeyboardButton(text=button['text'], url=button['url']))
        final_markup.add(*row_buttons)

    return final_markup

async def send_post(user_data: dict, chat_id: int, neko: BaseNeko):
    post_data = user_data['widget_broadcast']
    post_data['content_type'] = user_data['widget_broadcast_content_type']
    post_data['caption'] = user_data.get('widget_broadcast_post_caption')
    raw_markup = user_data.get('widget_broadcast_post_markup', [])

    if post_data['content_type'] == 'text':
        await neko.bot.send_message(
            text=post_data['caption'],
            parse_mode='HTML',
            disable_web_page_preview=True,
            reply_markup=assemble_markup(raw_markup),
            chat_id=chat_id
        )
    elif post_data['content_type'] == 'photo':
        await neko.bot.send_photo(
            photo=post_data['file_id'],
            parse_mode='HTML',
            caption=post_data['caption'],
            reply_markup=assemble_markup(raw_markup),
            chat_id=chat_id
        )
    elif post_data['content_type'] == 'video':
        await neko.bot.send_video(
            video=post_data['file_id'],
            parse_mode='HTML',
            caption=post_data['caption'],
            reply_markup=assemble_markup(raw_markup),
            chat_id=chat_id
        )
    else:
        await neko.bot.send_animation(
            animation=post_data['file_id'],
            parse_mode='HTML',
            caption=post_data['caption'],
            reply_markup=assemble_markup(raw_markup),
            chat_id=chat_id
        )


from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import Response
from dotenv import dotenv_values
import uvicorn
import copy
from datetime import datetime
from re import search
from multiprocessing import set_start_method

from src.models.debug import UpdateItemsCountData

from .internal import TreeService, NodeType, treeToJSON, MetaData, MetaType, CollectionService, BarcodeService, HistoryService, HistoryAction
from .models.search import InsertPath, DeletePath, DeleteItemList
from .models.add import InsertData, InsertHoldingItems
from fastapi.responses import JSONResponse

config = dotenv_values('.env')

try:
    set_start_method('spawn')
except RuntimeError:
    pass

def compareLocation(a, operator, b):
        commands = {
            ">" : lambda x, y : x > y,
            "<" : lambda x, y : x < y,
            ">=": lambda x, y : x >= y,
            "<=": lambda x, y : x <= y,
            "==": lambda x, y : x == y,
        }
        print(a, b)

        aNums, aChars = a.split("-")
        bNums, bChars = b.split("-")
        aNums = int(aNums)
        bNums = int(bNums)
        aChars = sum([ord(c) for c in aChars])
        bChars = sum([ord(c) for c in bChars])

        if  aChars == bChars:
            return commands[operator](aNums, bNums)

        return commands[operator](aChars, bChars)

def mergeSortByLocation(arr):
    print(arr)
    if len(arr) > 1:
        mid = len(arr)//2

        L = arr[:mid]
        R = arr[mid:]

        mergeSortByLocation(L)
        mergeSortByLocation(R)

        i = j = k = 0
        while i < len(L) and j < len(R):
            if compareLocation(L[i]['location'], "<", R[j]['location']):
                arr[k] = L[i]
                i += 1
            else:
                arr[k] = R[j]
                j += 1
            k += 1

        while i < len(L):
            arr[k] = L[i]
            i += 1
            k += 1
        while j < len(R):
            arr[k] = R[j]
            j += 1
            k += 1

app = FastAPI()

origins = [config["ORIGIN"]]
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

treeService = TreeService("tree", config['PATH'])
collectionService = CollectionService("warehouseDB", config['PATH'], CacheLength=1000000, threadSize=3)
historyService = HistoryService("logDB", config['PATH'], threadSize=3)
barcodeService = BarcodeService("barcode", config['PATH'])

# @app.on_event("shutdown")
# def shutdown_event():
#     treeService.saveObject()

@app.get("/", tags=["search"])
async def getHome():
    return Response(media_type="application/json", content=treeToJSON(treeService.navigationTree.root))

@app.get("/search", tags=["search"])
async def getSearch(path: str="", pattern: str=""):
    print(path, pattern)
    itemList = treeService.search(path, pattern)
    res = []
    for data in itemList:
        doc = collectionService.getDoc(data["id"])
        if not doc:
            return JSONResponse(status_code=404, content={"message": f"ID : {data['id']}, Item not found while searching items."})
        item = {
            "id": data["id"],
            "name": data["name"],
            "date": doc["date"],
            "path": doc["path"],
            "location": doc["location"]
        }
        res.append(item)
    return {
        "searchedResults":res
    }

@app.get("/warehouse", tags=["search"])
async def getWarehouse():
    return {
        "warehouses" :treeService.getWarehouses()
    }

@app.get("/warehouse/{warehouseName}/zone/{zoneName}", tags=["search"])
async def getShelfs(warehouseName: str, zoneName: str):
    return {
        "shelfs": treeService.getShelfs(f"warehouse{warehouseName}/zone{zoneName}")
    }

@app.get("/warehouse/{warehouseName}/zone/{zoneName}/shelf/{shelfName}", tags=["search"])
async def getItems(warehouseName: str, zoneName: str, shelfName: str):
    itemsId = treeService.getItems(f"warehouse{warehouseName}/zone{zoneName}/shelf{shelfName}")
    res = []
    for Id in itemsId:
        ## TODO process doc
        doc = copy.deepcopy(collectionService.getDoc(Id))
        if not doc:
            return JSONResponse(status_code=404, content={"message": f"ID : {Id}, Item not found while getting items."})
        doc["name"] = barcodeService.mapBarcode(doc["barcode"])["name"]
        del doc["tags"]
        del doc["barcode"]
        res.append(doc)

    mergeSortByLocation(res)
    return {
        "items" :res
    }

@app.post("/path", tags=["search"])
async def insertPath(insertPath: InsertPath):
    metaData = {
        "type": insertPath.type,
        "name": insertPath.name,
        "id": insertPath.name,
    }

    return {
        "isInserted": treeService.insert(NodeType.NON_ITEM, insertPath.path, metaData)
    }

@app.delete("/path", tags=["search"])
async def deletePath(deletePath: DeletePath):
    isDeleted, statusCode, message = treeService.deleteMultiple(NodeType.NON_ITEM, deletePath.path, deletePath.nameList)

    return JSONResponse(
        status_code=statusCode,
        content={
            "isDeleted": isDeleted,
            "message": message
        })

@app.get("/holding-items", tags=["add"])
async def getHoldingItems():
    holdingItems = collectionService.where("id","#",True, tags=["holding-items"])
    if type(holdingItems) == str:
        return {
            "holdingItems": []
        }
    itemsData = []
    for holdingItem in holdingItems:
        itemsData.append(barcodeService.mapBarcode(holdingItem['barcode'])['name'])

    processedHoldingItems = []
    for holdingItem, itemData in zip(holdingItems, itemsData):
        processedHoldingItems.append({
            "id": holdingItem['id'],
            "date": holdingItem['date'],
            "name": itemData
        })

    return {
        "holdingItems":processedHoldingItems
    }

@app.post("/holding-items", tags=["add"])
async def importItem(insertHoldingItems: InsertHoldingItems):
    barcodeList = insertHoldingItems.barcodeList
    try:
        products = []
        for barcode in barcodeList:
            products.append(barcodeService.mapBarcode(barcode))

        ids = []
        for barcode, product in zip(barcodeList, products):
            ids.append(collectionService.addDoc({
                "barcode": barcode,
                "date": datetime.now().isoformat()
            }, tags=[barcode, "holding-items"]))

        return {
            "isImported": True,
            "productIds": ids
        }
    except:

        return {
            "isImported": False
        }

@app.get("/item/{itemId}", tags=["search"])
async def getItemById(itemId: str):
    doc = collectionService.getDoc(itemId)
    if not doc:
        return JSONResponse(status_code=404, content={"message": f"ID : {itemId}, Item not found while getting item."})
    itemData = barcodeService.mapBarcode(doc["barcode"])
    res = {
        **itemData,
        **doc
    }

    #del res["barcode"]
    del res["tags"]
    del res["tag"]

    return res

@app.post("/item", tags=["add"])
async def insertItem(insertData: InsertData):
    # try:
        doc = collectionService.getDoc(insertData.id)
        if not doc:
            return JSONResponse(status_code=404, content={"message": f"ID : {insertData.id}, Item not found while adding item."})
        doc["path"] = insertData.path
        doc["location"] = insertData.location
        doc["date"] = datetime.now().isoformat()

        res = treeService.insert(NodeType.ITEM, insertData.path, {
            "name": insertData.name,
            "id": doc["id"],
            "type": MetaType.ITEM
        })

        if res:
            if "holding-items" in doc["tags"]:
                del doc["tags"]["holding-items"]
                collectionService.addTag(doc["id"], "InStorage")
            collectionService.updateDoc(insertData.id, doc)

            historyService.addLog({
                "action": str(HistoryAction.INSERT),
                "itemId": doc["id"],
                "name": barcodeService.mapBarcode(doc["barcode"])["name"],
                "date": doc["date"],
                "barcode": doc["barcode"]
            })

            return {
                "IsInserted":True
            }
        else:
            return {
               "IsInserted": False
            }
    # except:
        # return False

@app.delete("/item", tags=["search"])
async def deleteItem(deleteItemList: DeleteItemList):
    try:
        treeService.deleteMultiple(NodeType.ITEM, deleteItemList.path, deleteItemList.itemIdList)
        for id in deleteItemList.itemIdList:
            deletedDate = datetime.now().isoformat()

            collectionService.removeTag(id, "InStorage")
            collectionService.addTag(id, "OutStorage")

            doc = collectionService.getDoc(id)
            if not doc:
                return JSONResponse(status_code=404, content={"message": f"ID : {id}, Item not found while deleting."})
            collectionService.updateDoc(id, {
                **doc,
                "dateOut": deletedDate
            })

            historyService.addLog({
               "action": str(HistoryAction.EXPORT),
               "itemId": doc["id"],
                "name": barcodeService.mapBarcode(doc["barcode"])["name"],
                "date": deletedDate,
                "barcode": doc["barcode"]
            })

        return {
            "isDeleted":True
        }
    except:
        return {
            "isDeleted":False
        }

@app.get("/history", tags=["history"])
async def getHistory():
    hisDocList = copy.deepcopy(historyService.getHistory())
    for hisDoc in hisDocList:
        # hisDoc["id"] = hisDoc["itemId"]

        del hisDoc["tags"]
        # del hisDoc["itemId"]
        del hisDoc["barcode"]

    return {
        "histories":hisDocList
    }

@app.get("/history/search", tags=["history"])
async def searchHistory(pattern:str="", preDate:str="", postDate:str="", action:str=""):
    print("ENTERRR")

    res = []
    print(len(preDate), len(postDate))

    tags = {None} if len(action) == 0 else [action]

    if len(preDate) > 0 and len(postDate) > 0:
        docs = copy.deepcopy(historyService.searchByPeriod(preDate, postDate, tags=tags))

        if len(pattern) > 0:
            for doc in docs:
                if search(pattern=pattern, string=doc["name"]) is not None:
                    # doc["id"] = doc["itemId"]

                    del doc["tags"]
                    # del doc["itemId"]
                    del doc["barcode"]
                    res.append(doc)

        else:
            for doc in docs:
                # doc["id"] = doc["itemId"]

                del doc["tags"]
                # del doc["itemId"]
                del doc["barcode"]
                res.append(doc)

    elif len(pattern) > 0:
        docs = copy.deepcopy(historyService.getHistory(tags=tags))
        for doc in docs:
            if search(pattern=pattern, string=doc["name"]) is not None:
                # doc["id"] = doc["itemId"]

                del doc["tags"]
                # del doc["itemId"]
                del doc["barcode"]
                res.append(doc)

    elif len(preDate) == 0 and len(postDate) == 0:
        docs = copy.deepcopy(historyService.getHistory(tags=tags))
        for doc in docs:
            # doc["id"] = doc["itemId"]

            del doc["tags"]
            # del doc["itemId"]
            del doc["barcode"]
            res.append(doc)

    return {
        "searchedResults":res
    }

@app.post('/item-count', tags=["temporary"])
async def updateItemCount(updateItemsCountData: UpdateItemsCountData):
    path, count = updateItemsCountData.path, updateItemsCountData.count
    treeService.updateItemsCount(path, count)
    return True

if __name__ == "__main__":
    uvicorn.run("src.main:app", host=f'{config["HOST"]}', port=int(config["PORT"]), reload=False)


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

# 3rd party imports
import numpy as np
import xarray as xr
from scipy import constants, optimize

# Local imports
from ..pyrf.resample import resample
from ..pyrf.trace import trace
from ..pyrf.ts_scalar import ts_scalar
from ..pyrf.ts_tensor_xyz import ts_tensor_xyz

__author__ = "Louis Richard"
__email__ = "louisr@irfu.se"
__copyright__ = "Copyright 2020-2023"
__license__ = "MIT"
__version__ = "2.4.2"
__status__ = "Prototype"

def _f_one_pop(x, *args):
    i_e, i_aspoc, sc_pot_r = args
    return np.nansum(
        np.abs(
            i_e.data + i_aspoc.data - (x[0] * np.exp(-sc_pot_r.data / x[1])),
        ),
    )

def _f_two_pop(x, *args):
    i_e, i_aspoc, sc_pot_r = args
    return np.nansum(
        np.abs(
            i_e.data
            + i_aspoc.data
            - (x[0] * np.exp(-sc_pot_r.data / x[1]))
            + (x[2] * np.exp(-sc_pot_r.data / x[3])),
        ),
    )

def scpot2ne(sc_pot, n_e, t_e, i_aspoc: xr.DataArray = None):
    r"""Compute number density from spacecraft potential. Function uses number
    density and electron temperature to compute electron thermal current. A
    best fit of the photoelectron current to the thermal current is used to
    determine the photoelectron currents and temperatures. These are then used
    to construct a new number density from the spacecraft potential.

    Parameters
    ----------
    sc_pot : xarray.DataArray
        Time series of the spacecraft potential.
    n_e : xarray.DataArray
        Time series of the electron number density.
    t_e : xarray.DataArray
        Time series of the electron temperature. Function accepts scalar
        temperature or tensor (scalar temperature is used in either case).
    i_aspoc : xarray.DataArray, Optional
        Time series of the ASPOC current in :math:`\\mu` A.

    Returns
    -------
    n_esc : xarray.DataArray
        Time series of the number density estimated from SCpot, at the same
        resolution as ``sc_pot``.
    i_ph0 : float
        Value of the photoelectron currents ( :math:`\\mu` A) of the first
        population.
    t_ph0 : float
        Value of the temperature (eV) of the first population.
    i_ph1 : float
        Value of the photoelectron currents ( :math:`\\mu` A) of the second
        population.
    t_ph1 : float
        Value of the temperature (eV) of the second population.

    Notes
    -----
    Usual assumptions are made for thermal and photoelectron current, vis.,
    planar geometry for photoelectrons and spherical geometry for thermal
    electrons.
    Currently the calculation neglects the ion thermal current, secondary
    electrons, and other sources of current.
    ASPOC on does not work very well.

    """

    if i_aspoc is not None:
        i_aspoc = resample(i_aspoc, n_e)
    else:
        i_aspoc = ts_scalar(n_e.time.data, np.zeros(len(n_e)))

    # Check format of electron temperature (tensor)
    assert t_e.ndim == 3 and t_e.shape[1:] == (3, 3), "te must be timeseries of tensor"
    t_e = trace(ts_tensor_xyz(t_e.time.data, t_e.data)) / 3

    # Define constants
    m_e = constants.electron_mass
    q_e = constants.elementary_charge
    s_surf = 34

    v_eth = np.sqrt(2 * q_e * t_e.data / m_e)

    sc_pot_r = resample(sc_pot, n_e)

    # Thermal current in muA
    i_e = n_e.data * v_eth * (1 + sc_pot_r.data / t_e.data)
    i_e *= 1e12 * q_e * s_surf / (2 * np.sqrt(np.pi))

    # First a simple fit of Iph to Ie using 1 photoelectron population
    opt_p1 = optimize.fmin(
        _f_one_pop,
        x0=[500.0, 3.0],
        args=(i_e, i_aspoc, sc_pot_r),
        maxfun=5000,
    )

    # Fit of Iph to Ie for two photoelectron populations
    opt_p2 = optimize.fmin(
        _f_two_pop,
        x0=[opt_p1[0], opt_p1[1], 10.0, 10.0],
        args=(i_e, i_aspoc, sc_pot_r),
        maxfun=5000,
    )
    i_ph0, t_ph0, i_ph1, t_ph1 = opt_p2

    v_eth = np.sqrt(2 * q_e * resample(t_e, sc_pot).data / m_e)
    n_esc = i_ph0 * np.exp(-sc_pot.data / t_ph0) + i_ph1 * np.exp(
        -sc_pot.data / t_ph1,
    )
    n_esc /= s_surf * q_e * v_eth * (1 + sc_pot.data / resample(t_e, sc_pot).data)
    n_esc *= 2 * np.sqrt(np.pi) * 1e-12
    n_esc = ts_scalar(sc_pot.time.data, n_esc)

    return n_esc, i_ph0, t_ph0, i_ph1, t_ph1


from django.conf.urls import url
from zeus.views import site

urlpatterns = [
    url(r'^$', site.home, name='home'),
    url(r'^stvcount/$', site.stv_count, name='stv_count'),
    url(r'^terms/$', site.terms, name='terms'),
    url(r'^faqs/$', site.faqs_voter, name='faqs'),
    url(r'^faqs/voter/$', site.faqs_voter, name='faqs_voter'),
    url(r'^faqs/trustee/$', site.faqs_trustee, name='faqs_trustee'),
    url(r'^resources/$', site.resources, name='site_resources'),
    url(r'^contact/$', site.contact, name='site_contact'),
    url(r'^stats/$', site.stats, name='site_stats'),
    url(r'^demo$', site.demo, name='site_demo'),
    url(r'^error/(?P<code>[0-9]+)$', site.error, name='error')
]


print("Begin program: GetNYTimes2014ElectionResults.py")

from bs4 import BeautifulSoup
import requests
import csv

stateNameList = ["alabama",        "alaska",        "arizona",
                 "arkansas",       "california",    "colorado",
                 "connecticut",    "delaware",      "florida",
                 "georgia",        "hawaii",        "idaho",
                 "illinois",       "indiana",       "iowa",
                 "kansas",         "kentucky",      "louisiana",
                 "maine",          "maryland",      "massachusetts",
                 "michigan",       "minnesota",     "mississippi",
                 "missouri",       "montana",       "nebraska",
                 "nevada",         "new-hampshire", "new-jersey",
                 "new-mexico",     "new-york",      "north-carolina",
                 "north-dakota",   "ohio",          "oklahoma",
                 "oregon",         "pennsylvania",  "rhode-island",
                 "south-carolina", "south-dakota",  "tennessee",
                 "texas",          "utah",          "vermont",
                 "virginia",       "washington",    "west-virginia",
                 "wisconsin",      "wyoming"]

stateAbbrevList = ["al", "ak", "az", "ar", "ca", "co", "ct", "de", "fl",
                   "ga", "hi", "id", "il" ,"in", "ia", "ks", "ky", "la",
                   "me", "md", "ma", "mi", "mn", "ms", "mo", "mt", "ne",
                   "nv", "nh", "nj", "nm", "ny", "nc", "nd", "oh", "ok",
                   "or", "pa", "ri", "sc", "sd", "tn", "tx", "ut", "vt",
                   "va", "wa", "wv", "wi", "wy"]

csvName = "NYTimes2014elections.csv"

with open(csvName,"w", newline="", encoding="utf8") as csvfile:
    electionWriter = csv.writer(csvfile,delimiter=",")
    electionWriter.writerow (["State", "CongressionalMembership",
                              "Candidate1",  "PartyAffiliation1",  "Votes1",  "VotePercent1",
                              "Candidate2",  "PartyAffiliation2",  "Votes2",  "VotePercent2",
                              "Candidate3",  "PartyAffiliation3",  "Votes3",  "VotePercent3",
                              "Candidate4",  "PartyAffiliation4",  "Votes4",  "VotePercent4",
                              "Candidate5",  "PartyAffiliation5",  "Votes5",  "VotePercent5",
                              "Candidate6",  "PartyAffiliation6",  "Votes6",  "VotePercent6",
                              "Candidate7",  "PartyAffiliation7",  "Votes7",  "VotePercent7",
                              "Candidate8",  "PartyAffiliation8",  "Votes8",  "VotePercent8",
                              "Candidate9",  "PartyAffiliation9",  "Votes9",  "VotePercent9",
                              "Candidate10", "PartyAffiliation10", "Votes10", "VotePercent10",
                              "Candidate11", "PartyAffiliation11", "Votes11", "VotePercent11",
                              "Candidate12", "PartyAffiliation12", "Votes12", "VotePercent12"])

    for stateNum in range (0,50):
        print("Current state =", stateNameList[stateNum])

        url = "http://elections.nytimes.com/2014/" + stateNameList[stateNum] + "-elections"
        page = requests.get(url)
        soup = BeautifulSoup(page.text, "lxml")

        header = [stateNameList[stateNum], "Senate"]
        senateRace = soup.find(id="race-" + stateAbbrevList[stateNum] + "-senate-class-ii-2014-general")
        if senateRace!=None:
            data = []
            td = senateRace.find_all("td")
            datastring = "header[0],header[1]"
            noContest="no"
            for i in range (0,len(td)):
                currData = td[i].text.strip()
                currData = currData.replace("\n","")
                currData = " ".join(currData.split())
                if currData[-11:]=="Uncontested":
                    noContest = "yes"
                    currData = currData[:-11]
                if currData!="SHOW ALL HIDE":
                    data.append(currData)
                    datastring = datastring + ", data[" + str(i) + "]"
                    if i==(len(td)-1) and noContest=="yes":
                        for j in range (0,2):
                            data.append("")
                            nextI = i + 1 + j
                            datastring = datastring + ", data[" + str(nextI) + "]"
                        data.append("Uncontested")
                        nextI = nextI + 1
                        datastring = datastring + ", data[" + str(nextI) + "]"
            electionWriter.writerow(eval(datastring))

        header = [stateNameList[stateNum], "Senate Special"]
        senateSpecialRace = soup.find(id="race-" + stateAbbrevList[stateNum] + "-senate-class-ii-2014-special-general")
        if senateSpecialRace!=None:
            data = []
            td = senateSpecialRace.find_all("td")
            datastring = "header[0],header[1]"
            noContest="no"
            for i in range (0,len(td)):
                currData = td[i].text.strip()
                currData = currData.replace("\n","")
                currData = " ".join(currData.split())
                if currData[-11:]=="Uncontested":
                    noContest = "yes"
                    currData = currData[:-11]
                if currData!="SHOW ALL HIDE":
                    data.append(currData)
                    datastring = datastring + ", data[" + str(i) + "]"
                    if i==(len(td)-1) and noContest=="yes":
                        for j in range (0,2):
                            data.append("")
                            nextI = i + 1 + j
                            datastring = datastring + ", data[" + str(nextI) + "]"
                        data.append("Uncontested")
                        nextI = nextI + 1
                        datastring = datastring + ", data[" + str(nextI) + "]"
            electionWriter.writerow(eval(datastring))

        header = [stateNameList[stateNum], "Senate Special"]
        senateSpecialRace = soup.find(id="race-" + stateAbbrevList[stateNum] + "-senate-class-iii-2014-general")
        if senateSpecialRace!=None:
            data = []
            td = senateSpecialRace.find_all("td")
            datastring = "header[0],header[1]"
            noContest="no"
            for i in range (0,len(td)):
                currData = td[i].text.strip()
                currData = currData.replace("\n","")
                currData = " ".join(currData.split())
                if currData[-11:]=="Uncontested":
                    noContest = "yes"
                    currData = currData[:-11]
                if currData!="SHOW ALL HIDE":
                    data.append(currData)
                    datastring = datastring + ", data[" + str(i) + "]"
                    if i==(len(td)-1) and noContest=="yes":
                        for j in range (0,2):
                            data.append("")
                            nextI = i + 1 + j
                            datastring = datastring + ", data[" + str(nextI) + "]"
                        data.append("Uncontested")
                        nextI = nextI + 1
                        datastring = datastring + ", data[" + str(nextI) + "]"
            electionWriter.writerow(eval(datastring))

        houseDistrictNum = 1
        header = [stateNameList[stateNum], "House District " + str(houseDistrictNum)]
        nextHouse = soup.find(id="race-" + stateAbbrevList[stateNum] + "-house-district-" + str(houseDistrictNum) + "-2014-general")
        while nextHouse!=None:
            data = []
            td = nextHouse.find_all("td")
            datastring = "header[0],header[1]"
            noContest="no"
            for i in range (0,len(td)):
                currData = td[i].text.strip()
                currData = currData.replace("\n","")
                currData = " ".join(currData.split())
                if currData[-11:]=="Uncontested":
                    noContest = "yes"
                    currData = currData[:-11]
                if currData!="SHOW ALL HIDE":
                    data.append(currData)
                    datastring = datastring + ", data[" + str(i) + "]"
                    if i==(len(td)-1) and noContest=="yes":
                        for j in range (0,2):
                            data.append("")
                            nextI = i + 1 + j
                            datastring = datastring + ", data[" + str(nextI) + "]"
                        data.append("Uncontested")
                        nextI = nextI + 1
                        datastring = datastring + ", data[" + str(nextI) + "]"
            electionWriter.writerow(eval(datastring))

            houseDistrictNum = houseDistrictNum + 1
            header = [stateNameList[stateNum], "House District " + str(houseDistrictNum)]
            nextHouse = soup.find(id="race-" + stateAbbrevList[stateNum] + "-house-district-" + str(houseDistrictNum) + "-2014-general")

print("End program: GetNYTimes2014ElectionResults.py")

#Sources:
#https://docs.python.org/3/library/functions.html#eval
#http://stackoverflow.com/questions/961632/converting-integer-to-string-in-python
#http://stackoverflow.com/questions/6496884/compress-whitespaces-in-string
#http://www.tutorialspoint.com/python/string_join.htm
#http://www.tutorialspoint.com/python/string_replace.htm
#http://stackoverflow.com/questions/275018/how-can-i-remove-chomp-a-newline-in-python
#http://stackoverflow.com/questions/1762484/how-to-find-the-position-of-an-element-in-a-list-in-python
#http://stackoverflow.com/questions/663171/is-there-a-way-to-substring-a-string-in-python


import helper
import random

from bullet import Bullet

class Enemy(object):
    x = 0
    y = 0
    dx = 2
    dy = 0

    bdx = 0
    bdy = 0

    lx = 10
    ly = 10

    shootctr = 0
    shoottimer = 5

    health = 100

    colour = 'blue'

    def __init__(self,x,y,dx=None,dy=None,bdx=None,bdy=None):
        self.x = x
        self.y = y
        if dx:
            self.dx = dx
        if dy:
            self.dy = dy
        if bdx:
            self.bdx = bdx
        if bdy:
            self.bdy = bdy

    def step(self):
        self.x += self.dx
        self.y += self.dy
        self.shootctr += 1
        if self.shootctr % self.shoottimer == 0:
            self.shootctr = 0
            helper.makebullet(Bullet(self.x,self.y,self.bdx,self.bdy, type='enemy'))
            #helper.makebullet(Bullet(self.x,self.y,random.random()*2 - random.random()*2,random.random()*-40, ddx=0, ddy=1, type='enemy'))
            #helper.makebullet(Bullet(self.x+self.lx/2,self.y+self.ly,random.random()-random.random(),5,type='enemy'))
        if self.x >= helper.clenx or self.x <= 0:
            self.dx *= -1
        if self.y >= helper.cleny or self.y <= 0:
            self.dy *= -1
        self.checkhurt()

    def checkhurt(self):
        for bullet in helper.playerbullets:
            if bullet.type != 'enemy' and abs(bullet.x-self.x) <= self.lx and abs(bullet.y-self.y) <= self.ly:
                self.health -= bullet.damage
                helper.endbullet(bullet)
        if self.health < 0:
            helper.removeenemy(self)