import igraph as ig
import plotly.graph_objects as go
from django.conf import settings
from django.shortcuts import render
from django_elasticsearch_dsl_drf.constants import (
    SUGGESTER_COMPLETION,
    SUGGESTER_PHRASE,
    SUGGESTER_TERM,
)
from django_elasticsearch_dsl_drf.filter_backends import (
    CompoundSearchFilterBackend,
    DefaultOrderingFilterBackend,
    FacetedSearchFilterBackend,
    FilteringFilterBackend,
    OrderingFilterBackend,
    SuggesterFilterBackend,
)
from plotly.offline import plot

from radical_translations.agents.documents import AgentDocument
from radical_translations.agents.models import Agent, Organisation, Person
from radical_translations.agents.serializers import AgentDocumentSerializer
from radical_translations.core.views import BaseDetailView, BaseDocumentViewSet
from radical_translations.utils.search import PageNumberPagination

ES_FACET_OPTIONS = settings.ES_FACET_OPTIONS
ES_FUZZINESS_OPTIONS = settings.ES_FUZZINESS_OPTIONS

class AgentDetailView(BaseDetailView):
    model = Agent

def agent_list(request):
    return render(request, "agents/agent_list.html")

class AgentViewSet(BaseDocumentViewSet):
    document = AgentDocument
    serializer_class = AgentDocumentSerializer

    filter_backends = [
        FilteringFilterBackend,
        FacetedSearchFilterBackend,
        OrderingFilterBackend,
        DefaultOrderingFilterBackend,
        CompoundSearchFilterBackend,
        # the suggester backend needs to be the last backend
        SuggesterFilterBackend,
    ]

    lookup_field = "id"

    faceted_search_fields = {
        "meta": {"field": "meta", "enabled": True, "options": ES_FACET_OPTIONS},
        "year": {
            "field": "year",
            "enabled": True,
            "options": ES_FACET_OPTIONS,
        },
        "gender": {
            "field": "gender",
            "enabled": True,
            "options": ES_FACET_OPTIONS,
        },
        "place_birth": {
            "field": "place_birth.address.raw",
            "enabled": True,
            "options": ES_FACET_OPTIONS,
        },
        "place_death": {
            "field": "place_death.address.raw",
            "enabled": True,
            "options": ES_FACET_OPTIONS,
        },
        "noble": {
            "field": "noble",
            "enabled": True,
            "options": ES_FACET_OPTIONS,
        },
        "main_place": {
            "field": "based_near.address.raw",
            "enabled": True,
            "options": ES_FACET_OPTIONS,
        },
        "other_places": {
            "field": "main_places.address.raw",
            "enabled": True,
            "options": ES_FACET_OPTIONS,
        },
        "role": {
            "field": "roles.label.raw",
            "enabled": True,
            "options": ES_FACET_OPTIONS,
        },
        "language": {
            "field": "languages.label.raw",
            "enabled": True,
            "options": ES_FACET_OPTIONS,
        },
        "anonymous": {
            "field": "anonymous",
            "enabled": True,
            "options": ES_FACET_OPTIONS,
        },
    }

    filter_fields = {
        "meta": "meta",
        "year": "year",
        "gender": "gender",
        "place_birth": "place_birth.address.raw",
        "place_death": "place_death.address.raw",
        "noble": "noble",
        "other_places": "main_places.address.raw",
        "main_place": "based_near.address.raw",
        "role": "roles.label.raw",
        "language": "languages.label.raw",
        "anonymous": "anonymous",
    }

    ordering_fields = {
        "name": "name_sort",
        "year": "year",
    }
    ordering = ["_score", "name_sort", "year"]

    pagination_class = PageNumberPagination

    name_search_options = ES_FUZZINESS_OPTIONS
    name_search_options["boost"] = 2

    search_fields = {
        "name": name_search_options,
        "content": ES_FUZZINESS_OPTIONS,
    }

    suggester_fields = {
        "suggest_field": {
            "field": "name.suggest",
            "suggesters": [SUGGESTER_COMPLETION, SUGGESTER_PHRASE, SUGGESTER_TERM],
            "default_suggester": SUGGESTER_COMPLETION,
            "options": {"skip_duplicates": True, "size": 20},
        },
    }

def network(request):
    g = ig.Graph(directed=True)

    for org in Organisation.objects.exclude(roles__label__in=["archives", "library"]):
        g.add_vertex(name=f"agent-{org.id}", title=str(org), group=1)

    for person in Person.objects.all():
        group = 2

        if person.gender == "m":
            group = 3
        elif person.gender == "u":
            group = 4

        g.add_vertex(name=f"agent-{person.id}", title=str(person), group=group)

    for person in Person.objects.all():
        node_id = f"agent-{person.id}"

        for known in person.knows.all():
            g.add_edge(node_id, f"agent-{known.id}", label="knows")

        for org in person.member_of.all():
            g.add_edge(node_id, f"agent-{org.id}", label="member of")

    node_labels = g.vs["title"]
    node_groups = g.vs["group"]
    edge_labels = g.es["label"]

    layout = g.layout_graphopt()

    # nodes coordinates
    range_n = range(len(node_labels))
    nodes_x = [layout[i][0] for i in range_n]
    nodes_y = [layout[i][1] for i in range_n]

    # edges coordinates
    edges_x = []
    edges_y = []
    for e in g.get_edgelist():
        edges_x += [layout[e[0]][0], layout[e[1]][0], None]
        edges_y += [layout[e[0]][1], layout[e[1]][1], None]

    nodes_scatter = go.Scatter(
        x=nodes_x,
        y=nodes_y,
        mode="markers",
        marker=dict(
            symbol=node_groups,
            size=5,
            color=node_groups,
            colorscale="Viridis",
            line=dict(color="rgb(50,50,50)", width=0.5),
        ),
        text=node_labels,
        hoverinfo="text",
    )

    edges_scatter = go.Scatter(
        x=edges_x,
        y=edges_y,
        mode="lines",
        line=dict(width=1),
        line_shape="spline",
        marker=dict(color="rgb(125,125,125)"),
        text=edge_labels,
        hoverinfo="text",
    )

    axis = dict(
        showline=False,
        zeroline=False,
        showgrid=False,
        showticklabels=False,
        title="",
    )

    go_layout = go.Layout(
        font=dict(size=12),
        autosize=False,
        width=1000,
        height=1000,
        hovermode="closest",
        xaxis=dict(axis),
        yaxis=dict(axis),
    )

    fig = go.Figure(data=[edges_scatter, nodes_scatter], layout=go_layout)

    plot_div = plot(fig, output_type="div", include_plotlyjs=False)

    return render(request, "agents/network.html", context={"plot_div": plot_div})


from django.http import HttpResponse
from django.shortcuts import render
import json
from .models import *
def index(request):
    ob1 = Global_Indices.objects.all()[:5]
    ob2 = MAS_BSE.objects.all()[:5]
    ob3 = MAS_NSE.objects.all()[:5]
    ob4 = FD_CASH.objects.all()[:3]
    ob5 = FD_FII.objects.all()[:3]
    ob6 = Indian_Indices.objects.all()[:5]
    labels = []
    data = []

    queryset = graph.objects.all()
    for i in queryset:
        labels.append(i.year)
        data.append(i.price)

    d = {'tb1': ob1,'tb2': ob2,'tb3': ob3,'tb4': ob4,'tb5': ob5,'tb6':ob6,'year':labels,'price':data}
    return render(request, 'home.html',context=d)

def viewmore(request,id):
    obj1 = Global_Indices.objects.all()
    obj2 = Indian_Indices.objects.all()
    obj3 = MAS_BSE.objects.all()
    obj4 = MAS_NSE.objects.all()
    obj5 = FD_CASH.objects.all()
    obj6 = FD_FII.objects.all()

    if id==1:
        heading = 'Global Indices'
        header = ['Name','Current Value','Change','% Chg','Open','High','Low','Prev Close']
        rows = []
        for i in obj1:
            rows.append([i.Name,i.Currrent_value,i.change,i.Per_change,i.Open,i.High,i.Low,i.pre_close])
    elif id==2:
        heading = 'Indian_Indices'
        header = ['Name','Current Value','Change','% Chg','Open','High','Low']
        rows = []
        for i in obj2:
            rows.append([i.Name,i.Currrent_value,i.change,i.Per_change,i.Open,i.High,i.Low])
    elif id==3:
        heading = 'MOST ACTIVE STOCKS BSE'
        header = ['Company Name','Group','High','Low','Last Price','% Change','Values (Rs. cr.)']
        rows = []
        for i in obj3:
            rows.append([i.Company_name,i.Group,i.High,i.Low,i.Last_Price,i.Per_change,i.Values_in_RS])
    elif id==4:
        heading = 'MOST ACTIVE STOCKS NSE'
        header =['Company Name','High','Low','Last Price','% Change','Values (Rs. cr.)']
        rows = []
        for i in obj4:
            rows.append([i.Company_name,i.High,i.Low,i.Last_Price,i.Per_change,i.Values_in_RS])
    elif id==5:
        heading = "FII & DII TRADING ACTIVITY DURING MAY '20"
        header = ['Date','Gross Purchase','Gross Sales','Net Purchase / Sales','Gross Purchase','Gross Sales','Net Purchase / Sales']
        rows = []
        for i in obj5:
            rows.append([i.F_date,i.F_gross_purchase,i.F_gross_sales,i.F_net_purchase_orsale,i.D_gross_purchase,i.D_gross_sales,i.D_net_purchase_orsale])
    elif id==6:
        heading = "FII & DII TRADING ACTIVITY DURING MAY '20"
        header = ['Date','Gross Purchase','Gross Sales','Net Purchase / Sales','Gross Purchase','Gross Sales','Net Purchase / Sales']
        rows = []
        for i in obj6:
            rows.append([i.E_date,i.E_gross_purchase,i.E_gross_sales,i.E_net_purchase_orsale,i.DE_gross_purchase,i.DE_gross_sales,i.DE_net_purchase_orsale])

    return render(request,"Viewmore.html",{'heading':heading,'header':header,'rows':rows})


from sklearn.metrics import (
    mean_squared_error, r2_score,
    mean_absolute_error, accuracy_score,
    f1_score, roc_auc_score,
    log_loss
)
import pandas as pd
import numpy as np
from pandas import concat

REGRESSION = 0
CLASSIFICATION = 1

def tvd(real, pred):
    def get_pdf(data, size, ds_size):
        z = np.zeros(size)
        ind, v = np.unique(data, return_counts=True)
        v = v / ds_size
        np.put(z, ind.astype(int), v)
        return z
    size = int(max(np.max(real), np.max(pred))) + 1
    ds_size = len(real)
    d1 = get_pdf(real, size, ds_size)
    d2 = get_pdf(pred, size, ds_size)
    return 0.5 * np.sum(np.abs(d1 - d2))

def print_metrics(real, prediction, problem_type=REGRESSION, emthresh=3500):
    if problem_type == REGRESSION:
        mse = mean_squared_error(real, prediction)
        mae = mean_absolute_error(real, prediction)
        r2 = r2_score(real, prediction)

        scores = {'mse': mse, 'mae': mae, 'r2': r2}

    elif problem_type == CLASSIFICATION:
        pred = np.round(prediction)
        scores = {
            'accuracy': accuracy_score(real, pred),
            'f1': f1_score(real, pred),
        }

    return scores

def calculate_scaling(training_paths):
    scaling = {}
    # calculate scaling factors
    for f in training_paths:
        df = pd.read_csv(f, index_col=False)
        for column in df.columns:
            if column not in scaling:
                scaling[column] = 0.
            scaling[column] = max(scaling[column], float(df[column].max()))
            if scaling[column] == 0.0:
                scaling[column] = 1.0
    return scaling

def resize(s, scaling):
    return s/scaling[s.name]

def prepare_files(files, window_size, scaling, target_column='size'):
    result = []

    for f in files:
        df = pd.read_csv(f, index_col=False)
        if scaling is not None:
            df = df.apply((lambda x: resize(x, scaling)), axis=0)
        flow_size = df[target_column]
        df[target_column] = flow_size
        # extend the window
        final_df = df.copy()
        for sample_num in range(1, window_size):
            shifted = df.shift(sample_num)
            shifted.columns = map(lambda x: x+str(sample_num), shifted.columns)
            final_df = concat([shifted, final_df], axis=1)

        final_df = final_df.fillna(0)
        final_df = final_df.drop(target_column, axis=1)

        result.append((final_df, flow_size))
    return result

def make_io(data):
    inputs = None
    outputs = None
    for d in data:
        i_data = d[0].values
        o_data = d[1].tolist()
        if inputs is None:
            inputs = i_data
            outputs = o_data
        else:
            inputs = np.append(inputs, i_data, axis=0)
            outputs = np.append(outputs, o_data)
    return (inputs, outputs)


#! /usr/bin/env python
# required imports and code exection for basic functionning
import errno
import logging
import os
from contextlib import contextmanager

from Crypto.Cipher import PKCS1_OAEP
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from flask import Flask
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy

try:
    from data.software import RELEASES, CVE
except Exception:
    # For examples, see in src/data/software.py.example
    RELEASES = {"MONARC": {"stable": "2.12.2"}}
    CVE = {}

@contextmanager
def open_r_error(filename, mode="r"):
    try:
        f = open(filename, mode)
    except OSError as err:
        yield None, err
    else:
        try:
            yield f, None
        finally:
            f.close()

def set_logging(
    log_path=None,
    log_level=logging.INFO,
    modules=(),
    log_format="%(asctime)s %(levelname)s %(message)s",
):
    if not modules:
        modules = (
            "bootstrap",
            "runserver",
            "web",
        )
    if log_path:
        if not os.path.exists(os.path.dirname(log_path)):
            os.makedirs(os.path.dirname(log_path))
        if not os.path.exists(log_path):
            open(log_path, "w").close()
        handler = logging.FileHandler(log_path)
    else:
        handler = logging.StreamHandler()
    formater = logging.Formatter(log_format)
    handler.setFormatter(formater)
    for logger_name in modules:
        logger = logging.getLogger(logger_name)
        logger.addHandler(handler)
        for handler in logger.handlers:
            handler.setLevel(log_level)
        logger.setLevel(log_level)

def create_directory(directory):
    """Creates the necessary directories (public uploads, etc.)."""
    if not os.path.exists(directory):
        try:
            os.makedirs(directory)
        except OSError as e:
            if e.errno != errno.EEXIST:
                raise

# Create Flask application
application = Flask("web", instance_relative_config=True)
try:
    application.config.from_pyfile("production.cfg", silent=False)
except Exception:
    application.config.from_pyfile("development.cfg", silent=False)

db = SQLAlchemy(application)
migrate = Migrate(application, db)

# Jinja filters
def datetimeformat(value, format="%Y-%m-%d %H:%M"):
    return value.strftime(format)

# def instance_domain_name(*args):
#     return request.url_root.replace('http', 'https').strip("/")

application.jinja_env.filters["datetimeformat"] = datetimeformat
# application.jinja_env.filters['instance_domain_name'] = instance_domain_name

# set_logging(application.config['LOG_PATH'])

# create_directory(application.config['GENERATED_SVG_FOLDER'])

CIPHER = None
with open_r_error(application.config["RSA_PRIVATE_KEY"], "rb") as (priv_key, err):
    if err:
        CIPHER = None
    else:
        rsa_private_key = priv_key.read()
        private_key = RSA.import_key(rsa_private_key)
        CIPHER = PKCS1_OAEP.new(private_key, hashAlgo=SHA256)


from django.shortcuts import render
from .forms import EventForm
from django.http import HttpResponseRedirect
from .models import EventUser

def home(request):
    users_count = EventUser.objects.count()

    submitted = False
    if request.method == "POST":
        form = EventForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect("?submitted")
    else:
        form = EventForm
        if "submitted" in request.GET:
            submitted = True
    return render(
        request,
        "home.html",
        {"form": form, "submitted": submitted, "users_count": users_count},
    )

def about(request):
    return render(request, "about.html", {})


import sqlite3
from sqlite3 import Error

def openConnection(_dbFile):
    print("++++++++++++++++++++++++++++++++++")
    print("Open database: ", _dbFile)

    conn = None
    try:
        conn = sqlite3.connect(_dbFile)
        print("success")
    except Error as e:
        print(e)

    return conn
    print("++++++++++++++++++++++++++++++++++")

def closeConnection(_conn, _dbFile):
    print("++++++++++++++++++++++++++++++++++")
    print("Close database: ", _dbFile)

    try:
        _conn.close()
        print("success")
    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def create_View1(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Create V1")
    try:
        sql = """create view if not exists V1(c_custkey, c_name, c_address, c_phone, c_acctbal, c_mktsegment, c_comment, c_nation, c_region) as
                select c_custkey, c_name, c_address, c_phone, c_acctbal, c_mktsegment, c_comment, n_name , r_name from nation
                inner join customer on c_nationkey = n_nationkey
                inner join region on r_regionkey = n_regionkey;"""

        _conn.execute(sql)

        _conn.commit()
        print("success")

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def create_View2(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Create V2")

    try:
        sql = """create view if not exists V2(s_suppkey, s_name, s_address, s_phone, s_acctbal, s_comment, s_nation, s_region) as
                select s_suppkey, s_name, s_address, s_phone, s_acctbal, s_comment, n_name, r_name from nation
                inner join supplier on s_nationkey = n_nationkey
                inner join region on r_regionkey = n_regionkey;"""

        _conn.execute(sql)

        _conn.commit()
        print("success")

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def create_View5(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Create V5")

    try:
        sql = """create view if not exists V5(o_orderkey, o_custkey, o_orderstatus, o_totalprice, o_orderyear, o_orderpriority, o_clerk, o_shippriority, o_comment) as
                select o_orderkey, o_custkey, o_orderstatus, o_totalprice, o_orderdate, o_orderpriority, o_clerk, o_shippriority, o_comment from orders;"""

        _conn.execute(sql)

        _conn.commit()
        print("success")

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def create_View10(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Create V10")

    try:
        sql = """create view if not exists V10(p_type, min_discount, max_discount) as
                select p_type, min(l_discount), max(l_discount) from lineitem
                inner join part on p_partkey = l_partkey
                group by p_type;"""

        _conn.execute(sql)

        _conn.commit()
        print("success")

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def create_View151(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Create V151")

    try:
        sql = """create view if not exists V151(c_custkey, c_name, c_nationkey, c_acctbal) as
                select c_custkey, c_name, c_nationkey, c_acctbal
                from customer
                where c_acctbal > 0;"""

        _conn.execute(sql)

        _conn.commit()
        print("success")

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def create_View152(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Create V152")

    try:
        sql = """create view if not exists V152(s_suppkey, s_name, s_nationkey, s_acctbal) as
                select s_suppkey, s_name, s_nationkey, s_acctbal from supplier
                where s_acctbal < 0;"""

        _conn.execute(sql)

        _conn.commit()
        print("success")

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q1(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q1")

    Q1Output = open("output/1.out", "w")

    try:
        sql = """select V1.c_name, sum(round(o_totalprice, 2)) from orders
                inner join V1 on v1.c_custkey = o_custkey
                where V1.c_nation = 'FRANCE' and o_orderdate like '1995-__-__'
                group by V1.c_name;"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<10}|{:<10}'.format(
                row[0], row[1])
            print(data)
            Q1Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q2(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q2")

    Q2Output = open("output/2.out", "w")

    try:
        sql = """select V2.s_region, count(*) from V2
                group by V2.s_region;"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<12}|{:<10}'.format(
                row[0], row[1])
            print(data)
            Q2Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q3(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q3")

    Q3Output = open("output/3.out", "w")

    try:
        sql = """select V1.c_nation, count(*) from V1, orders
                where V1.c_custkey = o_custkey
                and V1.c_region = 'AMERICA'
                group by V1.c_nation;"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<15}|{:<10}'.format(
                row[0], row[1])
            print(data)
            Q3Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q4(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q4")

    Q4Output = open("output/4.out", "w")

    try:
        sql = """select V2.s_name, count(ps_partkey) from V2, partsupp
                inner join part on p_partkey = ps_partkey
                where ps_suppkey = V2.s_suppkey
                and V2.s_nation = 'CANADA' and p_size < 20
                group by V2.s_name;"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<15}|{:<10}'.format(
                row[0], row[1])
            print(data)
            Q4Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q5(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q5")

    Q5Output = open("output/5.out", "w")

    try:
        sql = """select V1.c_name, count(*)
                from V1, V5
                where V5.o_custkey = V1.c_custkey
                and V1.c_nation = 'GERMANY' and V5.o_orderyear like '1993-__-__'
                group by V1.c_name;"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<15}|{:<10}'.format(
                row[0], row[1])
            print(data)
            Q5Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q6(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q6")

    Q6Output = open("output/6.out", "w")

    try:
        sql = """select s_name, V5.o_orderpriority, count(distinct ps_partkey) from V5
                inner join lineitem on l_partkey = ps_partkey
                inner join partsupp on ps_suppkey = l_suppkey
                inner join supplier on s_suppkey = ps_suppkey
                inner join nation on n_nationkey = s_nationkey
                where l_orderkey = V5.o_orderkey
                and n_name = 'CANADA'
                group by s_name, V5.o_orderpriority;"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<15}|{:<15}|{:<10}'.format(
                row[0], row[1], row[2])
            print(data)
            Q6Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q7(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q7")

    Q7Output = open("output/7.out", "w")

    try:
        sql = """select V1.c_nation, V5.o_orderstatus, count(*) from V1, V5
                where V1.c_custkey = V5.o_custkey and V1.c_region = 'AMERICA'
                group by V1.c_nation, V5.o_orderstatus;"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<13}|{:<1}|{:<5}'.format(
                row[0], row[1], row[2])
            print(data)
            Q7Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q8(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q8")

    Q8Output = open("output/8.out", "w")

    try:
        sql = """select V2.s_nation, count(distinct l_orderkey) as co from V2, V5, lineitem
                where V5.o_orderkey = l_orderkey and l_suppkey = V2.s_suppkey and V5.o_orderstatus = 'F'
                and V5.o_orderyear like '1995-__-__'
                group by V2.s_nation
                having co > 50;"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<15}|{:<10}'.format(
                row[0], row[1])
            print(data)
            Q8Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q9(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q9")

    Q9Output = open("output/9.out", "w")

    try:
        sql = """select count(distinct V5.o_clerk) from V2, V5, lineitem
                where V5.o_orderkey = l_orderkey and l_suppkey = V2.s_suppkey
                and V2.s_nation = 'UNITED STATES';"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<10}'.format(
                row[0])
            print(data)
            Q9Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q10(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q10")

    Q10Output = open("output/10.out", "w")

    try:
        sql = """select V10.p_type, V10.min_discount, V10.max_discount from V10
                where V10.p_type like '%ECONOMY%' and V10.p_type like '%COPPER%'
                group by V10.p_type;"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<25}|{:<1}|{:<10}'.format(
                row[0], row[1], row[2])
            print(data)
            Q10Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q11(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q11")

    Q11Output = open("output/11.out", "w")

    try:
        sql = """select V2.s_region, V2.s_name, V2.s_acctbal from V2
                where V2.s_acctbal = (select MAX(V22.s_acctbal) from V2 as V22 where V22.s_region = V2.s_region);"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<12}|{:<10}|{:<10}'.format(
                row[0], row[1], row[2])
            print(data)
            Q11Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q12(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q12")

    Q12Output = open("output/12.out", "w")

    try:
        sql = """select V2.s_nation, max(V2.s_acctbal) as mb from V2
                group by V2.s_nation having mb > 9000;"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<15}|{:<10}'.format(
                row[0], row[1])
            print(data)
            Q12Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q13(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q13")

    Q13Output = open("output/13.out", "w")

    try:
        sql = """select count(*) from V1, V2, lineitem
                inner join orders on o_orderkey = l_orderkey
                where o_custkey = V1.c_custkey  and l_suppkey = V2.s_suppkey
                and V2.s_region = 'AFRICA' and V1.c_nation = 'UNITED STATES';"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<10}'.format(
                row[0])
            print(data)
            Q13Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q14(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q14")

    Q14Output = open("output/14.out", "w")

    try:
        sql = """select V2.s_region, V1.c_region, max(o_totalprice) from V2, orders, V1
                inner join lineitem on l_orderkey = o_orderkey
                where l_suppkey = V2.s_suppkey and o_custkey = V1.c_custkey
                group by V2.s_region, V1.c_region;"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<12}|{:<12}|{:<10}'.format(
                row[0], row[1], row[2])
            print(data)
            Q14Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def Q15(_conn):
    print("++++++++++++++++++++++++++++++++++")
    print("Q15")

    Q15Output = open("output/15.out", "w")

    try:
        sql = """select count(distinct l_orderkey) from V152, orders, V151
                inner join lineitem on l_orderkey = o_orderkey
                where l_suppkey = V152.s_suppkey
                and o_custkey = V151.c_custkey;"""

        cursor = _conn.cursor()
        cursor.execute(sql)
        rows = cursor.fetchall()
        for row in rows:
            data = '{:<12}'.format(
                row[0])
            print(data)
            Q15Output.write(data + '\n')

    except Error as e:
        print(e)

    print("++++++++++++++++++++++++++++++++++")

def main():
    database = r"tpch.sqlite"

    conn = openConnection(database)
    with conn:
        create_View1(conn)
        Q1(conn)

        create_View2(conn)
        Q2(conn)

        Q3(conn)
        Q4(conn)

        create_View5(conn)
        Q5(conn)

        Q6(conn)
        Q7(conn)
        Q8(conn)
        Q9(conn)

        create_View10(conn)
        Q10(conn)

        Q11(conn)
        Q12(conn)
        Q13(conn)
        Q14(conn)

        create_View151(conn)
        create_View152(conn)
        Q15(conn)

    closeConnection(conn, database)

if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-

"""This module defines various passive high-pass filter generators
"""

from typing import TYPE_CHECKING, Dict, Set, Any

import numbers

from bag.util.search import BinaryIterator
from bag.layout.util import BBox
from bag.layout.routing.base import TrackID, TrackManager
from bag.layout.template import TemplateBase

from abs_templates_ec.resistor.core import ResArrayBase, ResArrayBaseInfo

from ..substrate import SubstrateWrapper

if TYPE_CHECKING:
    from bag.layout.template import TemplateDB

class HighPassDiffCore(ResArrayBase):
    """A differential RC high-pass filter.

    Parameters
    ----------
    temp_db : :class:`bag.layout.template.TemplateDB`
        the template database.
    lib_name : str
        the layout library name.
    params : Dict[str, Any]
        the parameter values.
    used_names : Set[str]
        a set of already used cell names.
    **kwargs :
        dictionary of optional parameters.  See documentation of
        :class:`bag.layout.template.TemplateBase` for details.
    """

    def __init__(self, temp_db, lib_name, params, used_names, **kwargs):
        # type: (TemplateDB, str, Dict[str, Any], Set[str], **kwargs) -> None
        ResArrayBase.__init__(self, temp_db, lib_name, params, used_names, **kwargs)
        self._sch_params = None

    @property
    def sch_params(self):
        # type: () -> Dict[str, Any]
        return self._sch_params

    @classmethod
    def get_params_info(cls):
        # type: () -> Dict[str, str]
        return dict(
            w='unit resistor width, in meters.',
            h_unit='total height, in resolution units.',
            sub_type='the substrate type.',
            threshold='the substrate threshold flavor.',
            top_layer='The top layer ID',
            nser='number of resistors in series in a branch.',
            ndum='number of dummy resistors.',
            in_tr_info='Input track info.',
            out_tr_info='Output track info.',
            bias_idx='Bias port index.',
            vdd_tr_info='Supply track info.',
            res_type='Resistor intent',
            res_options='Configuration dictionary for ResArrayBase.',
            cap_spx='Capacitor horizontal separation, in resolution units.',
            cap_spy='Capacitor vertical space from resistor ports, in resolution units.',
            cap_margin='Capacitor space from edge, in resolution units.',
            half_blk_x='True to allow for half horizontal blocks.',
            show_pins='True to show pins.',
        )

    @classmethod
    def get_default_param_values(cls):
        # type: () -> Dict[str, Any]
        return dict(
            bias_idx=0,
            vdd_tr_info=None,
            res_type='standard',
            res_options=None,
            cap_spx=0,
            cap_spy=0,
            cap_margin=0,
            half_blk_x=True,
            show_pins=True,
        )

    def draw_layout(self):
        # type: () -> None
        w = self.params['w']
        h_unit = self.params['h_unit']
        sub_type = self.params['sub_type']
        threshold = self.params['threshold']
        top_layer = self.params['top_layer']
        nser = self.params['nser']
        ndum = self.params['ndum']
        in_tr_info = self.params['in_tr_info']
        out_tr_info = self.params['out_tr_info']
        bias_idx = self.params['bias_idx']
        vdd_tr_info = self.params['vdd_tr_info']
        res_type = self.params['res_type']
        res_options = self.params['res_options']
        cap_spx = self.params['cap_spx']
        cap_spy = self.params['cap_spy']
        cap_margin = self.params['cap_margin']
        half_blk_x = self.params['half_blk_x']
        show_pins = self.params['show_pins']

        res = self.grid.resolution
        lay_unit = self.grid.layout_unit
        w_unit = int(round(w / lay_unit / res))

        if res_options is None:
            my_options = dict(well_end_mode=2)

        else:
            my_options = res_options.copy()
            my_options['well_end_mode'] = 2
        # find resistor length
        info = ResArrayBaseInfo(self.grid, sub_type, threshold, top_layer=top_layer,
                                res_type=res_type, grid_type=None, ext_dir='y', options=my_options,
                                connect_up=True, half_blk_x=half_blk_x, half_blk_y=True)

        lmin, lmax = info.get_res_length_bounds()
        bin_iter = BinaryIterator(lmin, lmax, step=2)
        while bin_iter.has_next():
            lcur = bin_iter.get_next()
            htot = info.get_place_info(lcur, w_unit, 1, 1)[3]
            if htot < h_unit:
                bin_iter.save()
                bin_iter.up()
            else:
                bin_iter.down()

        # draw resistor
        l_unit = bin_iter.get_last_save()
        nx = 2 * (nser + ndum)
        self.draw_array(l_unit * lay_unit * res, w, sub_type, threshold, nx=nx, ny=1,
                        top_layer=top_layer, res_type=res_type, grid_type=None, ext_dir='y',
                        options=my_options, connect_up=True, half_blk_x=half_blk_x,
                        half_blk_y=True, min_height=h_unit)
        # connect resistors
        vdd, biasp, biasn, outp_h, outn_h, xl, xr = self.connect_resistors(ndum, nser, bias_idx)
        # draw MOM cap
        caplp, capln, caprp, caprn = self.draw_mom_cap(nser, xl, xr, cap_spx, cap_spy, cap_margin)

        # connect resistors to MOM cap, and draw metal resistors
        vm_layer = self.bot_layer_id + 1
        self.connect_to_tracks(outp_h, capln.track_id)
        self.connect_to_tracks(outn_h, caprn.track_id)

        # connect outputs to horizontal tracks
        hm_layer = vm_layer + 1
        pidx, nidx, tr_w = in_tr_info
        res_in_w = self.grid.get_track_width(hm_layer, tr_w, unit_mode=True)
        inp, inn = self.connect_differential_tracks(caplp, caprp, hm_layer, pidx, nidx, width=tr_w)
        tr_lower, tr_upper = inp.lower_unit, inp.upper_unit
        self.add_res_metal_warr(hm_layer, pidx, tr_lower - res_in_w, tr_lower, width=tr_w,
                                unit_mode=True)
        self.add_res_metal_warr(hm_layer, nidx, tr_lower - res_in_w, tr_lower, width=tr_w,
                                unit_mode=True)
        inp = self.add_wires(hm_layer, pidx, tr_lower - 2 * res_in_w, tr_lower - res_in_w,
                             width=tr_w, unit_mode=True)
        inn = self.add_wires(hm_layer, nidx, tr_lower - 2 * res_in_w, tr_lower - res_in_w,
                             width=tr_w, unit_mode=True)
        pidx, nidx, tr_w = out_tr_info
        res_out_w = self.grid.get_track_width(hm_layer, tr_w, unit_mode=True)
        self.connect_differential_tracks(capln, caprn, hm_layer, pidx, nidx, track_lower=tr_lower,
                                         track_upper=tr_upper, width=tr_w, unit_mode=True)
        self.add_res_metal_warr(hm_layer, pidx, tr_upper, tr_upper + res_out_w, width=tr_w,
                                unit_mode=True)
        self.add_res_metal_warr(hm_layer, nidx, tr_upper, tr_upper + res_out_w, width=tr_w,
                                unit_mode=True)
        outp = self.add_wires(hm_layer, pidx, tr_upper + res_out_w, tr_upper + 2 * res_out_w,
                              width=tr_w, unit_mode=True)
        outn = self.add_wires(hm_layer, nidx, tr_upper + res_out_w, tr_upper + 2 * res_out_w,
                              width=tr_w, unit_mode=True)
        # connect/export vdd
        if vdd_tr_info is None:
            self.add_pin('VDD_vm', vdd, label='VDD:', show=show_pins)
        else:
            self.add_pin('VDD_vm', vdd, label='VDD', show=show_pins)
            for tr_info in vdd_tr_info:
                tid = TrackID(hm_layer, tr_info[0], width=tr_info[1])
                self.add_pin('VDD', self.connect_to_tracks(vdd, tid), show=show_pins)
        # add pins
        self.add_pin('biasp', biasp, show=show_pins)
        self.add_pin('biasn', biasn, show=show_pins)
        self.add_pin('outp', outp, show=show_pins)
        self.add_pin('outn', outn, show=show_pins)
        self.add_pin('inp', inp, show=show_pins)
        self.add_pin('inn', inn, show=show_pins)

        self._sch_params = dict(
            l=l_unit * lay_unit * res,
            w=w,
            intent=res_type,
            nser=nser,
            ndum=ndum,
            res_in_info=(hm_layer, res_in_w * res * lay_unit, res_in_w * res * lay_unit),
            res_out_info=(hm_layer, res_out_w * res * lay_unit, res_out_w * res * lay_unit),
        )

    def connect_resistors(self, ndum, nser, bias_idx):
        nx = 2 * (nser + ndum)
        biasp = []
        biasn = []
        outp = outn = None
        for idx in range(ndum):
            biasp.extend(self.get_res_ports(0, idx))
            biasn.extend(self.get_res_ports(0, nx - 1 - idx))
        for idx in range(ndum, nser + ndum):
            cpl = self.get_res_ports(0, idx)
            cpr = self.get_res_ports(0, nx - 1 - idx)
            conn_par = (idx - ndum) % 2
            if idx == ndum:
                biasp.append(cpl[1 - conn_par])
                biasn.append(cpr[1 - conn_par])
            if idx == nser + ndum - 1:
                outp = cpl[conn_par]
                outn = cpr[conn_par]
            else:
                npl = self.get_res_ports(0, idx + 1)
                npr = self.get_res_ports(0, nx - 2 - idx)
                self.connect_wires([npl[conn_par], cpl[conn_par]])
                self.connect_wires([npr[conn_par], cpr[conn_par]])

        biasp = self.connect_wires(biasp)
        biasn = self.connect_wires(biasn)

        # connect bias wires to vertical tracks
        vm_layer = self.bot_layer_id + 1
        t0 = self.grid.find_next_track(vm_layer, 0, half_track=True,
                                       mode=1, unit_mode=True)
        t1 = self.grid.find_next_track(vm_layer, self.bound_box.right_unit, half_track=True,
                                       mode=-1, unit_mode=True)
        bp_tid = TrackID(vm_layer, t0 + bias_idx + 1)
        bn_tid = TrackID(vm_layer, t1 - bias_idx - 1)
        biasp = self.connect_to_tracks(biasp, bp_tid)
        biasn = self.connect_to_tracks(biasn, bn_tid)
        vdd = self.add_wires(vm_layer, t0, biasp.lower_unit, biasp.upper_unit,
                             num=2, pitch=t1 - t0, unit_mode=True)
        xl = self.grid.get_wire_bounds(vm_layer, t0 + 2, unit_mode=True)[1]
        xr = self.grid.get_wire_bounds(vm_layer, t1 - 2, unit_mode=True)[0]

        return vdd, biasp, biasn, outp, outn, xl, xr

    def draw_mom_cap(self, nser, xl, xr, cap_spx, cap_spy, cap_margin):
        res = self.grid.resolution

        # get port location
        bot_pin, top_pin = self.get_res_ports(0, 0)
        bot_pin_box = bot_pin.get_bbox_array(self.grid).base
        top_pin_box = top_pin.get_bbox_array(self.grid).base
        bnd_box = self.bound_box
        cap_yb_list = [bnd_box.bottom_unit + cap_spy, bot_pin_box.top_unit + cap_spy,
                       top_pin_box.top_unit + cap_spy]
        cap_yt_list = [bot_pin_box.bottom_unit - cap_spy, top_pin_box.bottom_unit - cap_spy,
                       bnd_box.top_unit - cap_spy]

        # draw MOM cap
        xc = bnd_box.xc_unit
        num_layer = 2
        bot_layer = self.bot_layer_id
        top_layer = bot_layer + num_layer - 1
        # set bottom parity based on number of resistors to avoid via-to-via spacing errors
        if nser % 2 == 0:
            bot_par_list = [(1, 0), (0, 1), (1, 0)]
        else:
            bot_par_list = [(0, 1), (1, 0), (0, 1)]

        spx_le = self.grid.get_line_end_space(bot_layer, 1, unit_mode=True)
        spx_le2 = -(-spx_le // 2)
        cap_spx2 = max(cap_spx // 2, spx_le2)
        cap_xl_list = [xl + cap_margin, xc + cap_spx2]
        cap_xr_list = [xc - cap_spx2, xr - cap_margin]

        rects = []
        capp_list, capn_list = [], []
        port_parity = {top_layer: (1, 0)}
        for cap_xl, cap_xr in zip(cap_xl_list, cap_xr_list):
            curp_list, curn_list = [], []
            for idx, (cap_yb, cap_yt, bot_par) in enumerate(zip(cap_yb_list, cap_yt_list,
                                                                bot_par_list)):
                port_parity[bot_layer] = bot_par
                cap_box = BBox(cap_xl, cap_yb, cap_xr, cap_yt, res, unit_mode=True)
                if idx == 1:
                    ports, cur_rects = self.add_mom_cap(cap_box, bot_layer, num_layer,
                                                        port_parity=port_parity,
                                                        return_cap_wires=True)
                    rects.extend(cur_rects[-1])
                else:
                    ports = self.add_mom_cap(cap_box, bot_layer, num_layer,
                                             port_parity=port_parity)
                capp, capn = ports[top_layer]
                curp_list.append(capp[0])
                curn_list.append(capn[0])

            capp_list.append(curp_list)
            capn_list.append(curn_list)
            port_parity[top_layer] = (0, 1)

        caplp = self.connect_wires(capp_list[0])[0]
        caprp = self.connect_wires(capp_list[1])[0]
        capln = self.connect_wires(capn_list[0])[0]
        caprn = self.connect_wires(capn_list[1])[0]

        # merge cap wires
        yb = caplp.lower_unit
        yt = caplp.upper_unit
        for rect in rects:
            box = BBox(rect.bbox.left_unit, yb, rect.bbox.right_unit, yt, res, unit_mode=True)
            self.add_rect(rect.layer, box)

        # return ports
        return caplp, capln, caprp, caprn

class HighPassDiff(SubstrateWrapper):
    """A differential RC high-pass filter with substrate contact.

    Parameters
    ----------
    temp_db : TemplateDB
        the template database.
    lib_name : str
        the layout library name.
    params : Dict[str, Any]
        the parameter values.
    used_names : Set[str]
        a set of already used cell names.
    **kwargs
        dictionary of optional parameters.  See documentation of
        :class:`bag.layout.template.TemplateBase` for details.
    """

    def __init__(self, temp_db, lib_name, params, used_names, **kwargs):
        # type: (TemplateDB, str, Dict[str, Any], Set[str], **kwargs) -> None
        SubstrateWrapper.__init__(self, temp_db, lib_name, params, used_names, **kwargs)

    @classmethod
    def get_params_info(cls):
        # type: () -> Dict[str, str]
        return dict(
            w='unit resistor width, in meters.',
            h_unit='total height, in resolution units.',
            sub_w='Substrate width.',
            sub_lch='Substrate channel length.',
            sub_type='the substrate type.',
            threshold='the substrate threshold flavor.',
            top_layer='The top layer ID',
            nser='number of resistors in series in a branch.',
            ndum='number of dummy resistors.',
            in_tr_info='Input track info.',
            out_tr_info='Output track info.',
            bias_idx='Bias port index.',
            vdd_tr_info='Supply track info.',
            res_type='Resistor intent',
            res_options='Configuration dictionary for ResArrayBase.',
            cap_spx='Capacitor horizontal separation, in resolution units.',
            cap_spy='Capacitor vertical space from resistor ports, in resolution units.',
            cap_margin='Capacitor space from edge, in resolution units.',
            sub_tr_w='substrate track width in number of tracks.  None for default.',
            sub_tids='Substrate contact tr_idx/tr_width tuples.',
            end_mode='substrate end mode flag.',
            show_pins='True to show pins.',
        )

    @classmethod
    def get_default_param_values(cls):
        # type: () -> Dict[str, Any]
        return dict(
            bias_idx=0,
            vdd_tr_info=None,
            res_type='standard',
            res_options=None,
            cap_spx=0,
            cap_spy=0,
            cap_margin=0,
            sub_tr_w=None,
            sub_tids=None,
            end_mode=15,
            show_pins=True,
        )

    def draw_layout(self):
        h_unit = self.params['h_unit']
        sub_w = self.params['sub_w']
        sub_lch = self.params['sub_lch']
        sub_type = self.params['sub_type']
        threshold = self.params['threshold']
        top_layer = self.params['top_layer']
        in_tr_info = self.params['in_tr_info']
        out_tr_info = self.params['out_tr_info']
        vdd_tr_info = self.params['vdd_tr_info']
        res_type = self.params['res_type']
        sub_tr_w = self.params['sub_tr_w']
        sub_tids = self.params['sub_tids']
        end_mode = self.params['end_mode']
        show_pins = self.params['show_pins']

        # compute substrate contact height, subtract from h_unit
        bot_end_mode, top_end_mode = self.get_sub_end_modes(end_mode)
        h_subb = self.get_substrate_height(self.grid, top_layer, sub_lch, sub_w, sub_type,
                                           threshold, end_mode=bot_end_mode, is_passive=True)
        h_subt = self.get_substrate_height(self.grid, top_layer, sub_lch, sub_w, sub_type,
                                           threshold, end_mode=top_end_mode, is_passive=True)

        hm_layer = ResArrayBase.get_port_layer_id(self.grid.tech_info) + 2
        tr_off = self.grid.find_next_track(hm_layer, h_subb, half_track=True, mode=1,
                                           unit_mode=True)
        params = self.params.copy()
        params['h_unit'] = h_unit - h_subb - h_subt
        params['in_tr_info'] = (in_tr_info[0] - tr_off, in_tr_info[1] - tr_off, in_tr_info[2])
        params['out_tr_info'] = (out_tr_info[0] - tr_off, out_tr_info[1] - tr_off, out_tr_info[2])
        if vdd_tr_info is not None:
            new_info_list = []
            for tr_info in vdd_tr_info:
                new_info_list.append((tr_info[0] - tr_off, tr_info[1]))
            params['vdd_tr_info'] = new_info_list
        self.draw_layout_helper(HighPassDiffCore, params, sub_lch, sub_w, sub_tr_w, sub_type,
                                threshold, show_pins, end_mode=end_mode, is_passive=True,
                                sub_tids=sub_tids, res_type=res_type)

        # do max space fill
        for lay_id in range(1, hm_layer):
            self.do_max_space_fill(lay_id, fill_pitch=2)
        self.fill_box = self.bound_box

class HighPassArrayCore(ResArrayBase):
    """An array of RC high-pass filter.

    Parameters
    ----------
    temp_db : :class:`bag.layout.template.TemplateDB`
        the template database.
    lib_name : str
        the layout library name.
    params : Dict[str, Any]
        the parameter values.
    used_names : Set[str]
        a set of already used cell names.
    **kwargs :
        dictionary of optional parameters.  See documentation of
        :class:`bag.layout.template.TemplateBase` for details.
    """

    def __init__(self, temp_db, lib_name, params, used_names, **kwargs):
        # type: (TemplateDB, str, Dict[str, Any], Set[str], **kwargs) -> None
        ResArrayBase.__init__(self, temp_db, lib_name, params, used_names, **kwargs)
        self._sch_params = None

    @property
    def sch_params(self):
        # type: () -> Dict[str, Any]
        return self._sch_params

    @classmethod
    def get_params_info(cls):
        # type: () -> Dict[str, str]
        return dict(
            w='unit resistor width, in meters.',
            h_unit='total height, in resolution units.',
            narr='Number of high-pass filters.',
            sub_type='the substrate type.',
            threshold='the substrate threshold flavor.',
            top_layer='The top layer ID',
            nser='number of resistors in series in a branch.',
            ndum='number of dummy resistors.',
            cap_h_list='List of capacitor heights, in resolution units.',
            port_tr_w='port widths, in number of tracks.',
            res_type='Resistor intent',
            res_options='Configuration dictionary for ResArrayBase.',
            cap_spx='Capacitor horizontal separation, in resolution units.',
            cap_spy='Capacitor vertical margin, in resolution units.',
            half_blk_x='True to allow for half horizontal blocks.',
            show_pins='True to show pins.',
        )

    @classmethod
    def get_default_param_values(cls):
        # type: () -> Dict[str, Any]
        return dict(
            port_tr_w=1,
            res_type='standard',
            res_options=None,
            cap_spx=0,
            cap_spy=0,
            half_blk_x=True,
            show_pins=True,
        )

    def draw_layout(self):
        # type: () -> None
        w = self.params['w']
        h_unit = self.params['h_unit']
        narr = self.params['narr']
        sub_type = self.params['sub_type']
        threshold = self.params['threshold']
        top_layer = self.params['top_layer']
        nser = self.params['nser']
        ndum = self.params['ndum']
        port_tr_w = self.params['port_tr_w']
        res_type = self.params['res_type']
        res_options = self.params['res_options']
        cap_spx = self.params['cap_spx']
        cap_spy = self.params['cap_spy']
        cap_h_list = self.params['cap_h_list']
        half_blk_x = self.params['half_blk_x']
        show_pins = self.params['show_pins']

        if nser % 2 != 0:
            raise ValueError('This generator only supports even nser.')

        res = self.grid.resolution
        lay_unit = self.grid.layout_unit
        w_unit = int(round(w / lay_unit / res))

        if res_options is None:
            my_options = dict(well_end_mode=2)
        else:
            my_options = res_options.copy()
            my_options['well_end_mode'] = 2
        # find resistor length
        info = ResArrayBaseInfo(self.grid, sub_type, threshold, top_layer=top_layer,
                                res_type=res_type, ext_dir='y', options=my_options,
                                connect_up=True, half_blk_x=half_blk_x, half_blk_y=True)

        lmin, lmax = info.get_res_length_bounds()
        bin_iter = BinaryIterator(lmin, lmax, step=2)
        while bin_iter.has_next():
            lcur = bin_iter.get_next()
            htot = info.get_place_info(lcur, w_unit, 1, 1)[3]
            if htot < h_unit:
                bin_iter.save()
                bin_iter.up()
            else:
                bin_iter.down()

        # draw resistor
        l_unit = bin_iter.get_last_save()
        nx = 2 * ndum + narr * nser
        self.draw_array(l_unit * lay_unit * res, w, sub_type, threshold, nx=nx, ny=1,
                        top_layer=top_layer, res_type=res_type, grid_type=None, ext_dir='y',
                        options=my_options, connect_up=True, half_blk_x=half_blk_x,
                        half_blk_y=True, min_height=h_unit)

        # get cap settings
        bot_layer = self.bot_layer_id + 1
        for lay in range(bot_layer, top_layer + 1):
            if self.grid.get_direction(lay) == 'x':
                cap_spx = max(cap_spx, self.grid.get_line_end_space(lay, 1, unit_mode=True))

        # connect resistors and draw MOM caps
        tmp = self._connect_resistors(narr, nser, ndum, cap_spx, port_tr_w, show_pins)
        rout_list, cap_x_list = tmp
        tmp = self._draw_mom_cap(cap_x_list, bot_layer, top_layer, cap_spy, cap_h_list,
                                 port_tr_w, show_pins)
        cout_list, ores_info, cres_info = tmp

        # connect bias resistor to cap
        for rout, cout in zip(rout_list, cout_list):
            self.connect_to_track_wires(rout, cout)

        # set schematic parameters
        self._sch_params = dict(
            narr=narr,
            ndum=ndum * 2,
            hp_params=dict(
                l=l_unit * lay_unit * res,
                w=w,
                intent=res_type,
                nser=nser,
                ndum=0,
                res_in_info=cres_info,
                res_out_info=ores_info,
                sub_name='VSS',
            ),
        )

    def _connect_supplies(self, supl_list, supr_list, show_pins):
        vm_layer = self.bot_layer_id + 1
        xm_layer = vm_layer + 1
        for sup_list, mode, name in ((supl_list, -1, 'VSSL'), (supr_list, 1, 'VSSR')):
            xc = sup_list[0].middle_unit
            vm_tr = self.grid.coord_to_nearest_track(vm_layer, xc, half_track=True, mode=mode,
                                                     unit_mode=True)
            sup = self.connect_to_tracks(sup_list, TrackID(vm_layer, vm_tr))
            xm_tr = self.grid.coord_to_nearest_track(xm_layer, sup.middle_unit, half_track=True,
                                                     unit_mode=True)
            sup = self.connect_to_tracks(sup, TrackID(xm_layer, xm_tr), min_len_mode=mode)
            self.add_pin(name, sup, label='VSS:', show=show_pins)

    def _connect_resistors(self, narr, nser, ndum, cap_spx, port_tr_w, show_pins):
        nx = 2 * ndum + narr * nser
        hm_layer = self.bot_layer_id
        vm_layer = hm_layer + 1

        # connect dummies
        supl_list = []
        supr_list = []
        for idx in range(ndum):
            supl_list.extend(self.get_res_ports(0, idx))
            supr_list.extend(self.get_res_ports(0, nx - 1 - idx))
        supl_list = self.connect_wires(supl_list)
        supr_list = self.connect_wires(supr_list)
        self._connect_supplies(supl_list, supr_list, show_pins)

        # get line-end margin so we can know capacitor horizontal spacing
        hm_sp_le = self.grid.get_line_end_space(hm_layer, 1, unit_mode=True)
        hm_vext = self.grid.get_via_extensions(hm_layer, 1, 1, unit_mode=True)[0]
        hm_margin = hm_sp_le + hm_vext

        if isinstance(port_tr_w, numbers.Integral):
            bias_spx = self.grid.get_space(vm_layer, port_tr_w, unit_mode=True)
        else:
            bias_spx = self.grid.get_space(vm_layer, port_tr_w[vm_layer], unit_mode=True)

        # get capacitor X interval, connect resistors, and get ports
        out_list = []
        cap_x_list = []
        cap_spx2 = cap_spx // 2
        for res_idx in range(narr):
            rl_idx = ndum + res_idx * nser
            # connect series resistors
            for idx in range(nser - 1):
                conn_par = idx % 2
                rcur_idx = rl_idx + idx
                portl = self.get_res_ports(0, rcur_idx)
                portr = self.get_res_ports(0, rcur_idx + 1)
                self.connect_wires([portl[conn_par], portr[conn_par]])

            # record ports
            rr_idx = rl_idx + nser - 1
            xl = self.get_res_bbox(0, rl_idx).left_unit
            xr = self.get_res_bbox(0, rr_idx).right_unit
            if res_idx % 2 == 1:
                out_list.append(self.get_res_ports(0, rl_idx)[1])
                bias = self.get_res_ports(0, rr_idx)[1]
                bias_tr = self.grid.find_next_track(vm_layer, xr - hm_margin, half_track=True,
                                                    mode=-1, unit_mode=True)
                wl = self.grid.get_wire_bounds(vm_layer, bias_tr, width=1, unit_mode=True)[0]
                cap_xl = xl + cap_spx2
                cap_xr = min(xr - cap_spx2, wl - bias_spx)
            else:
                out_list.append(self.get_res_ports(0, rr_idx)[1])
                bias = self.get_res_ports(0, rl_idx)[1]
                bias_tr = self.grid.find_next_track(vm_layer, xl + hm_margin, half_track=True,
                                                    mode=1, unit_mode=True)
                wr = self.grid.get_wire_bounds(vm_layer, bias_tr, width=1, unit_mode=True)[1]
                cap_xl = max(xl + cap_spx2, wr + bias_spx)
                cap_xr = xr - cap_spx2

            cap_x_list.append((cap_xl, cap_xr))
            bias = self.connect_to_tracks(bias, TrackID(vm_layer, bias_tr), min_len_mode=1)
            self.add_pin('bias<%d>' % res_idx, bias, show=show_pins)

        return out_list, cap_x_list

    def _draw_mom_cap(self, cap_x_list, bot_layer, top_layer, cap_spy, cap_h_list,
                      port_tr_w, show_pins):
        grid = self.grid
        res = grid.resolution

        # get port location
        bnd_box = self.bound_box
        cap_yt = bnd_box.top_unit - cap_spy

        # draw MOM cap
        num_layer = top_layer - bot_layer + 1

        out_list = []
        out_res_info = in_res_info = None
        for cap_idx, ((cap_xl, cap_xr), cap_h) in enumerate(zip(cap_x_list, cap_h_list)):
            cap_yb = max(bnd_box.bottom_unit + cap_spy, cap_yt - cap_h)
            cap_box = BBox(cap_xl, cap_yb, cap_xr, cap_yt, res, unit_mode=True)
            parity = cap_idx % 2
            port_par = (parity, 1 - parity)
            ports = self.add_mom_cap(cap_box, bot_layer, num_layer, port_widths=port_tr_w,
                                     port_parity={bot_layer: port_par, top_layer: port_par})
            if parity == 0:
                warr_in = ports[top_layer][1 - parity][0]
                out = ports[bot_layer][parity][0]
            else:
                warr_in = ports[top_layer][parity][0]
                out = ports[bot_layer][1 - parity][0]

            out_list.append(out)
            # draw output metal resistor and port
            out_port, out_res_info = self._add_metal_res(out, go_up=True)
            self.add_pin('out<%d>' % cap_idx, out_port, show=show_pins)
            # draw clock metal resistor and port
            in_port, in_res_info = self._add_metal_res(warr_in, go_up=False)
            self.add_pin('in<%d>' % cap_idx, in_port, show=show_pins)

        # return ports
        return out_list, out_res_info, in_res_info

    def _add_metal_res(self, warr, go_up=True):
        tid = warr.track_id
        tidx = tid.base_index
        lay_id = tid.layer_id
        tr_w = tid.width
        width = self.grid.get_track_width(lay_id, tid.width, unit_mode=True)
        if go_up:
            coord = warr.upper_unit
            self.add_res_metal_warr(lay_id, tidx, coord, coord + width, width=tr_w, unit_mode=True)
            port = self.add_wires(lay_id, tidx, coord + width, coord + 2 * width,
                                  width=tr_w, unit_mode=True)
        else:
            coord = warr.lower_unit
            self.add_res_metal_warr(lay_id, tidx, coord - width, coord, width=tr_w, unit_mode=True)
            port = self.add_wires(lay_id, tidx, coord - 2 * width, coord - width,
                                  width=tr_w, unit_mode=True)

        scale = self.grid.resolution * self.grid.layout_unit
        return port, (lay_id, width * scale, width * scale)

class HighPassArrayClkCore(TemplateBase):
    """An array of clock RC high-pass filters.

    Parameters
    ----------
    temp_db : :class:`bag.layout.template.TemplateDB`
        the template database.
    lib_name : str
        the layout library name.
    params : Dict[str, Any]
        the parameter values.
    used_names : Set[str]
        a set of already used cell names.
    **kwargs :
        dictionary of optional parameters.  See documentation of
        :class:`bag.layout.template.TemplateBase` for details.
    """

    def __init__(self, temp_db, lib_name, params, used_names, **kwargs):
        # type: (TemplateDB, str, Dict[str, Any], Set[str], **kwargs) -> None
        TemplateBase.__init__(self, temp_db, lib_name, params, used_names, **kwargs)
        self._sch_params = None

    @property
    def sch_params(self):
        # type: () -> Dict[str, Any]
        return self._sch_params

    @classmethod
    def get_params_info(cls):
        # type: () -> Dict[str, str]
        return dict(
            w='unit resistor width, in meters.',
            h_unit='total height, in resolution units.',
            sub_type='the substrate type.',
            threshold='the substrate threshold flavor.',
            top_layer='The top layer ID for HighPassArrayCore.',
            narr='Number of high-pass filters.',
            nser='number of resistors in series in a branch.',
            ndum='number of dummy resistors.',
            cap_h_list='List of capacitor heights, in resolution units.',
            tr_widths='track widths dictionary.',
            tr_spaces='track spacings dictionary.',
            port_tr_w='port widths, in number of tracks.',
            res_type='Resistor intent',
            res_options='Configuration dictionary for ResArrayBase.',
            cap_spx='Capacitor horizontal separation, in resolution units.',
            cap_spy='Capacitor vertical margin, in resolution units.',
            half_blk_x='True to allow for half horizontal blocks.',
            show_pins='True to show pins.',
        )

    @classmethod
    def get_default_param_values(cls):
        # type: () -> Dict[str, Any]
        return dict(
            port_tr_w=1,
            res_type='standard',
            res_options=None,
            cap_spx=0,
            cap_spy=0,
            half_blk_x=True,
            show_pins=True,
        )

    def draw_layout(self):
        top_layer = self.params['top_layer']
        narr = self.params['narr']
        tr_widths = self.params['tr_widths']
        tr_spaces = self.params['tr_spaces']
        show_pins = self.params['show_pins']

        params = self.params.copy()
        params['show_pins'] = False
        master = self.new_template(params=params, temp_cls=HighPassArrayCore)

        tr_manager = TrackManager(self.grid, tr_widths, tr_spaces, half_space=True)
        pidx, nidx, y0 = self._place_clock_wires(master, narr, top_layer, tr_manager)

        xm_layer = top_layer + 1
        xm_w = tr_manager.get_width(xm_layer, 'clk')

        inst = self.add_instance(master, 'XARR', loc=(0, y0), unit_mode=True)
        bnd_box = inst.bound_box.extend(y=0, unit_mode=True)
        self.set_size_from_bound_box(xm_layer, bnd_box, round_up=True)
        self.array_box = bnd_box
        self.add_cell_boundary(self.bound_box)

        # re-export/connect clocks
        vssl = inst.get_pin('VSSL')
        vssl = self.extend_wires(vssl, lower=0, unit_mode=True)
        vssr = inst.get_pin('VSSR')
        vssr = self.extend_wires(vssr, upper=bnd_box.right_unit, unit_mode=True)
        self.add_pin('VSSL', vssl, label='VSS:', show=show_pins)
        self.add_pin('VSSR', vssr, label='VSS:', show=show_pins)
        clkp_list = []
        clkn_list = []
        for idx in range(narr):
            suf = '<%d>' % idx
            self.reexport(inst.get_port('bias' + suf), show=show_pins)
            self.reexport(inst.get_port('out' + suf), show=show_pins)
            parity = idx % 4
            if parity == 0 or parity == 3:
                clkp_list.append(inst.get_pin('in' + suf))
            else:
                clkn_list.append(inst.get_pin('in' + suf))
        clkp, clkn = self.connect_differential_tracks(clkp_list, clkn_list, xm_layer, pidx, nidx,
                                                      width=xm_w)
        self.add_pin('clkp', clkp, show=show_pins)
        self.add_pin('clkn', clkn, show=show_pins)

        self._sch_params = master.sch_params

    def _place_clock_wires(self, master, narr, top_layer, tr_manager):
        yb_min = master.bound_box.top_unit
        for idx in range(narr):
            yb_min = min(yb_min, master.get_port('in<%d>' % idx).get_pins()[0].lower_unit)

        xm_layer = top_layer + 1
        xm_w = tr_manager.get_width(xm_layer, 'clk')

        pidx = self.grid.find_next_track(xm_layer, yb_min, tr_width=xm_w, half_track=True,
                                         mode=-1, unit_mode=True)
        nidx = tr_manager.get_next_track(xm_layer, pidx, 'clk', 'clk', up=False)

        edge_tr2 = int(round(2 * nidx)) - xm_w
        if edge_tr2 < -1:
            tr_pitch = self.grid.get_track_pitch(xm_layer, unit_mode=True)
            dy = (edge_tr2 + 1) * tr_pitch // 2
            blk_h = self.grid.get_block_size(top_layer, unit_mode=True)[1]
            dy = -(-dy // blk_h) * blk_h
            tr_delta = dy / tr_pitch
            pidx += tr_delta
            nidx += tr_delta
        else:
            dy = 0

        return pidx, nidx, dy

class HighPassArrayClk(SubstrateWrapper):
    """A wrapper with substrate contact around HighPassArrayClkCore

    Parameters
    ----------
    temp_db : TemplateDB
        the template database.
    lib_name : str
        the layout library name.
    params : Dict[str, Any]
        the parameter values.
    used_names : Set[str]
        a set of already used cell names.
    **kwargs
        dictionary of optional parameters.  See documentation of
        :class:`bag.layout.template.TemplateBase` for details.
    """

    def __init__(self, temp_db, lib_name, params, used_names, **kwargs):
        # type: (TemplateDB, str, Dict[str, Any], Set[str], **kwargs) -> None
        SubstrateWrapper.__init__(self, temp_db, lib_name, params, used_names, **kwargs)

    @classmethod
    def get_params_info(cls):
        # type: () -> Dict[str, str]
        return dict(
            w='unit resistor width, in meters.',
            h_unit='total height, in resolution units.',
            sub_w='Substrate width.',
            sub_lch='Substrate channel length.',
            sub_type='the substrate type.',
            threshold='the substrate threshold flavor.',
            top_layer='The top layer ID',
            narr='Number of high-pass filters.',
            nser='number of resistors in series in a branch.',
            ndum='number of dummy resistors.',
            cap_h_list='List of capacitor heights, in resolution units.',
            tr_widths='track widths dictionary.',
            tr_spaces='track spacings dictionary.',
            port_tr_w='port widths, in number of tracks.',
            res_type='Resistor intent',
            res_options='Configuration dictionary for ResArrayBase.',
            cap_spx='Capacitor horizontal separation, in resolution units.',
            cap_spy='Capacitor vertical margin, in resolution units.',
            sub_tr_w='substrate track width in number of tracks.  None for default.',
            end_mode='substrate end mode flag.',
            show_pins='True to show pins.',
        )

    @classmethod
    def get_default_param_values(cls):
        # type: () -> Dict[str, Any]
        return dict(
            port_tr_w=1,
            res_type='standard',
            res_options=None,
            cap_spx=0,
            cap_spy=0,
            sub_tr_w=None,
            end_mode=15,
            show_pins=True,
        )

    def draw_layout(self):
        h_unit = self.params['h_unit']
        sub_w = self.params['sub_w']
        sub_lch = self.params['sub_lch']
        sub_type = self.params['sub_type']
        threshold = self.params['threshold']
        top_layer = self.params['top_layer']
        res_type = self.params['res_type']
        sub_tr_w = self.params['sub_tr_w']
        end_mode = self.params['end_mode']
        show_pins = self.params['show_pins']

        # compute substrate contact height, subtract from h_unit
        bot_end_mode, top_end_mode = self.get_sub_end_modes(end_mode)
        h_subb = self.get_substrate_height(self.grid, top_layer + 1, sub_lch, sub_w, sub_type,
                                           threshold, end_mode=bot_end_mode, is_passive=True)

        params = self.params.copy()
        params['h_unit'] = h_unit - h_subb
        inst, sup_list = self.draw_layout_helper(HighPassArrayClkCore, params, sub_lch, sub_w,
                                                 sub_tr_w, sub_type, threshold, show_pins,
                                                 end_mode=end_mode, is_passive=True,
                                                 res_type=res_type, bot_only=True)
        self.fill_box = bnd_box = self.bound_box
        self.extend_wires(sup_list, lower=0, upper=bnd_box.right_unit, unit_mode=True)
        for lay in range(1, top_layer):
            self.do_max_space_fill(lay, bnd_box, fill_pitch=1.5)


"""
    Celery tasks. Some of them will be launched periodically from admin panel via django-celery-beat
"""

import time
from typing import Union, List, Optional, Dict

import telegram
from celery.utils.log import get_task_logger

from dtb.celery import app
from tgbot.handlers.broadcast_message.utils import _send_message, _from_celery_entities_to_entities, \
    _from_celery_markup_to_markup, _send_photo

logger = get_task_logger(__name__)

@app.task(ignore_result=True)
def broadcast_message(
        user_ids: List[Union[str, int]],
        text: str,
        entities: Optional[List[Dict]] = None,
        reply_markup: Optional[List[List[Dict]]] = None,
        sleep_between: float = 0.4,
        parse_mode=telegram.ParseMode.HTML,
) -> None:
    """ It's used to broadcast message to big amount of users """
    logger.info(f"Going to send message: '{text}' to {len(user_ids)} users")

    entities_ = _from_celery_entities_to_entities(entities)
    reply_markup_ = _from_celery_markup_to_markup(reply_markup)
    for user_id in user_ids:
        try:
            _send_message(
                user_id=user_id,
                text=text,
                entities=entities_,
                parse_mode=parse_mode,
                reply_markup=reply_markup_,
            )
            logger.info(f"Broadcast message was sent to {user_id}")
        except Exception as e:
            logger.error(f"Failed to send message to {user_id}, reason: {e}")
        time.sleep(max(sleep_between, 0.1))

    logger.info("Broadcast finished!")

from datetime import datetime
from django.conf import settings
from hfspace.anime import to_anime, to_dragness, to_jojo

@app.task(ignore_result=True)
def animefy(user_id: int, image_path: str):
    file_timestamp = int(datetime.now().timestamp())
    out_put = f"{settings.MEDIA_ROOT}/image/output_anime_{file_timestamp}.png"
    to_anime(image_path, out_put)
    _send_message(
        user_id=user_id,
        text="Думаю какой ты анимешник")
    _send_photo(user_id=user_id,
                photo_path=f"{settings.MEDIA_ROOT}/image/output_anime_{file_timestamp}.png")

@app.task(ignore_result=True)
def dragnify(user_id: int, image_path: str):
    file_timestamp = int(datetime.now().timestamp())
    out_put = f"{settings.MEDIA_ROOT}/image/output_dragness_{file_timestamp}.png"
    to_dragness(image_path, out_put)
    _send_message(
        user_id=user_id,
        text="Думаю какая ты Dragness")
    _send_photo(user_id=user_id,
                photo_path=f"{settings.MEDIA_ROOT}/image/output_dragness_{file_timestamp}.png")

@app.task(ignore_result=True)
def jojofy(user_id: int, image_path: str):
    file_timestamp = int(datetime.now().timestamp())
    out_put = f"{settings.MEDIA_ROOT}/image/output_jojo_{file_timestamp}.png"
    to_jojo(image_path, out_put)
    _send_message(
        user_id=user_id,
        text="Думаю какой ты jojo")
    _send_photo(user_id=user_id,
                photo_path=f"{settings.MEDIA_ROOT}/image/output_jojo_{file_timestamp}.png")


# -*- coding: utf-8 -*-
"""
Created on Sat May 26 20:41:25 2018

@author: visha
"""
import importlib
from config import ConfigBuilder
from workflow import WorkflowBuilder

class AppBuilder:
    def __init__(self, str):
        print("Inside the AppBuilder constructor")
        self.application = str
        self.configuration = ConfigBuilder(self.application)
        self.workflow = WorkflowBuilder(self.application)
        self.pipeline = []

    def buildPipeline(self):
        print("building workflow pipeline for application :: " + self.application)

        self.configuration.buildConfiguration()
        self.workflow.buildWorkflow()

        for instance in self.workflow.pipeline:
            print("adding instance to pipeline ::" + instance)
            #print(self.configuration.dictionary[process])
            self.pipeline.append(self.configuration.dictionary[instance])

if __name__ == "__main__":
    # Create an object:
    x = AppBuilder("")
    module = importlib.import_module('base.Classification.Classification')
    my_class = getattr(module, 'Classifier')
    my_instance = my_class('base')
    my_method = getattr(my_instance, 'sayHello')
    my_method()
    x.buildPipeline()

"""    tokenDict = {
    "cat": deal_with_a_cat,
    "dog": deal_with_a_dog,
    "bear": deal_with_a_bear,
    }
"""


from collections import deque
deq = deque()
N = int(input())
if N == 1:
    print(1)
    quit()
for n in range(1, N + 1):
    deq.append(n)
while True:
    deq.popleft()
    deq.append(deq[0])
    deq.popleft()
    if len(deq) == 1:
        break
print(deq[0])


"""
This module is used to interact directly with speedrun.com's API.
It will be accessed by functions in Commands.py
"""
# used to convert durations in the sr.com api
import isodate
import aiohttp

async def fetchname(userurl):
    async with aiohttp.ClientSession() as client:
        async with client.get(url=userurl) as r:
            Data = await r.json()
    name = Data["data"]["names"]["international"]
    return name

async def fetchabbreviation(name):
    Words = str(name).split(" ")
    url = 'http://www.speedrun.com/api/v1/games?name='
    for word in Words:
        if word != Words[-1]:
            url += "{}%20".format(word)
        else:
            url += word
    async with aiohttp.ClientSession() as client:
        async with client.get(url=url) as r:
            Data = await r.json()
    Data = Data['data']
    if len(Data) == 0:
        return "Invalid game name"
    else:
        return Data[0]["abbreviation"]

async def fetchcategories(game):
    try:
        url = 'http://www.speedrun.com/api/v1/games/{}/categories'.format(
            str(game))
        async with aiohttp.ClientSession() as client:
            async with client.get(url=url) as r:
                Data = await r.json()
        Dictionary = {}
        for category in Data["data"]:
            v_url = category["links"][2]["uri"]
            async with aiohttp.ClientSession() as client:
                async with client.get(url=v_url) as r:
                    VariableData = await r.json()
            # checks if a run has variables
            if VariableData["data"] == []:
                Dictionary[category["name"]] = [category["links"][5]["uri"]]
            else:
                data = VariableData["data"][0]["values"]["values"]
                for variable in dict.keys(data):
                    label = data[variable]["label"]
                    name = category["name"] + " - " + label
                    link = category["links"][5]["uri"]
                    Dictionary[name] = [link, variable]
        return Dictionary
    except:
        return "Invalid game name"

async def fetchtime(game, category, rank):
    Link = await fetchcategories(str(game))
    Link = Link[str(category)]
    url = Link[0]
    async with aiohttp.ClientSession() as client:
        async with client.get(url=url) as r:
            Data = await r.json()
    if len(Link) == 1:
        RunData = [run for run in Data["data"]["runs"]]
    else:
        variable = Link[1]
        RunData = []
        for run in Data["data"]["runs"]:
            for k, value in run["run"]["values"].items():
                    if value == variable:
                        RunData.append(run)
    RunCount = len(RunData)
    if not(rank in set(range(-RunCount, RunCount + 1))):
        return "bad rank"
    RunValues = []
    Runs = {}
    for run in RunData:
        Value = run["run"]["times"]["primary_t"]
        Time = isodate.parse_duration(run["run"]["times"]["primary"])
        Player = run["run"]["players"][0]
        if Player["rel"] == "user":
            Name = await fetchname(run["run"]["players"][0]["uri"])
        else:
            Name = Player["name"]
        if run["run"]["videos"] is None:
            Vod = "no vod"
        else:
            Vod = run["run"]["videos"]["links"][0]["uri"]
        Runinfo = {"name": Name, "time": Time, "vod": Vod}
        RunValues.append(Value)
        Runs[Value] = Runinfo
    Key = sorted(RunValues)[rank]
    return Runs[Key]


import time

from IAmHuman.stack_fsm import StackFSM
from IAmHuman.game_elements import *
from IAmHuman.mathf import *
from IAmHuman.quick_chat import QuickChat

from rlbot.agents.base_agent import BaseAgent, SimpleControllerState
from rlbot.utils.structures.game_data_struct import GameTickPacket

class IAmHuman(BaseAgent):

    def get_target_pos(self):
        if isinstance(self.target, Vector3):
            return self.target
        elif isinstance(self.target, GameObject):
            return self.target.location
        else:
            return None

    def initialize_agent(self):
        # This runs once before the bot starts up
        self.brain = StackFSM()
        self.brain.agent = self
        self.me = Car()
        self.teammates = []
        self.opponents = []
        self.ball = Ball()
        self.game_info = GameInfo()

        self.average_frame_time = 0
        self.fps = 60
        self.show_debug_info = True
        self.use_quick_chat = True
        self.quick_chat = QuickChat()

        self.target = Vector3([0, 0, 0])

    def get_output(self, game: GameTickPacket) -> SimpleControllerState:
        fps_start = time.time()
        self.preprocess(game)

        if self.brain.get_current_state() is None:
            # Prevent bot from doing nothing
            self.brain.push_only('QuickShot')

        if self.show_debug_info:
            self.render_cur_state()

        if self.use_quick_chat:
            self.quick_chat.check(self)

        controller = self.brain.update(self)
        self.calc_bot_fps(fps_start, time.time())

        return controller

    def calc_bot_fps(self, start_time, end_time):
        smoothing = 0.9
        self.average_frame_time = (self.average_frame_time * smoothing) + ((end_time - start_time) * (1 - smoothing))
        self.fps = 1 / self.average_frame_time

    def render_cur_state(self):
        self.renderer.begin_rendering()

        # Colors
        background_color = self.renderer.create_color(150, 0, 0, 0)
        text_color = self.renderer.create_color(255, 255, 255, 255)
        text_color2 = self.renderer.create_color(150, 255, 255, 255)
        green = self.renderer.create_color(255, 0, 255, 0)

        # Bot FPS
        self.renderer.draw_rect_2d(20, 220, 200, 25, True, background_color)
        self.renderer.draw_string_2d(25, 225, 1, 1, self.name + " FPS:",
                                     text_color)
        self.renderer.draw_string_2d(150, 225, 1, 1, str(int(round(self.fps))),
                                     green if (self.fps >= 60) else self.renderer.red())

        # States Stack
        self.renderer.draw_rect_2d(20, 250, 200, 100, True, background_color)
        self.renderer.draw_string_2d(25, 255, 1, 1, 'States Stack:',
                                     text_color)
        self.renderer.draw_string_2d(125, 255, 1, 1, self.brain.get_current_state().__class__.__name__, text_color)

        y_offset = 255
        for i, s in reversed(list(enumerate(self.brain.stack))):
            if i != len(self.brain.stack) - 1:
                y_offset += 20
                self.renderer.draw_string_2d(125, y_offset, 1, 1, self.brain.stack[i].__class__.__name__,
                                             text_color2)

        # State GUI
        self.brain.get_current_state().debug_render(self)

        self.renderer.end_rendering()

    def preprocess(self, game):
        # set up own car object
        self.me.rotation_matrix = calc_rotation_matrix([game.game_cars[self.index].physics.rotation.pitch,
                                                        game.game_cars[self.index].physics.rotation.yaw,
                                                        game.game_cars[self.index].physics.rotation.roll])
        self.preprocess_car(game.game_cars[self.index], self.me)

        # set up ball object
        self.preprocess_game_object(game.game_ball, self.ball)

        # set up game info object
        self.game_info.is_match_ended = game.game_info.is_match_ended
        self.game_info.seconds_elapsed = game.game_info.seconds_elapsed

        # set up other car objects
        self.teammates.clear()
        self.opponents.clear()

        for i, car in enumerate(game.game_cars):
            if i != self.index:
                new_car = Car()
                self.preprocess_car(game.game_cars[i], new_car)

                if car.team == self.me.team:
                    self.teammates.append(new_car)
                else:
                    self.opponents.append(new_car)

    def preprocess_game_object(self, object_data, game_object):
        game_object.location.data = [object_data.physics.location.x, object_data.physics.location.y,
                                     object_data.physics.location.z]
        game_object.rotation.data = [object_data.physics.rotation.pitch, object_data.physics.rotation.yaw,
                                     object_data.physics.rotation.roll]
        game_object.velocity.data = [object_data.physics.velocity.x, object_data.physics.velocity.y,
                                     object_data.physics.velocity.z]
        game_object.angular_velocity.data = [object_data.physics.angular_velocity.x,
                                             object_data.physics.angular_velocity.y,
                                             object_data.physics.angular_velocity.z]

        game_object.local_location = calc_local_vector(game_object.location - self.me.location, self.me.rotation_matrix)

    def preprocess_car(self, car_data, car_object):
        self.preprocess_game_object(car_data, car_object)

        car_object.stats.score = car_data.score_info.score
        car_object.stats.goals = car_data.score_info.goals
        car_object.stats.own_goals = car_data.score_info.own_goals
        car_object.stats.assists = car_data.score_info.assists
        car_object.stats.saves = car_data.score_info.saves
        car_object.stats.shots = car_data.score_info.shots
        car_object.stats.demolitions = car_data.score_info.demolitions

        car_object.is_demolished = car_data.is_demolished
        car_object.has_wheel_contact = car_data.has_wheel_contact
        car_object.boost = car_data.boost
        car_object.team = car_data.team

        car_object.rotation_matrix = calc_rotation_matrix(car_object.rotation.data)

        return car_object


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2017-05-12 09:24:35
# @Author  : wuyan
# @Version : V0.1
"""帮助模块，提供一些算法，数据抽取方式."""

from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals

import os
import logging
import re
import random
import string
# import shutil
import subprocess

# from datetime import datetime

def parser(relation_list):
    """
    抽取依赖数据，返回依赖顺序列表.

    Args:
        relation_list: 格式化依赖数据列表，eg： [('A', 'C'), ('A', 'D'), ('A', 'G')】
                       释义为：A -> C, A -> D, A -> G

    Returns:
        list: 顺序依赖列表元组，eg： [('A',), ('D',), ('B',), ('G', 'C'), ('F',)]
    """
    logging.info('Begin parser table relation!')
    result = []
    pre_elements = set()
    for e0, e1 in relation_list:
        pre_elements.add(e0)
        pre_elements.add(e1)
    while relation_list:
        elements_right = set()
        for _, e1 in relation_list:
            elements_right.add(e1)

        elements_left = pre_elements - elements_right
        next_list = []
        for i, e in enumerate(relation_list):
            if not e[0] in elements_left:
                next_list.append(e)
        relation_list = next_list
        pre_elements = pre_elements - elements_left
        result.append(tuple(elements_left))
    logging.info('End parser table relation!')
    return result

def random_string(length=10, repeat=True, type_=1):
    """生成随机字符串.

    Args:
        length: 10 生成字符串的长度
        repeat: True 是否能重复
        type_: 1 全部小写字母组成
               2 全部大写字母组成
               3 全部数字字符组成
               12 1和2组成
               23 2和3组成
               13 1和3组成
               123 1和2和3

    Returns:
        string: 返回生成的字符串
    """
    string_letters = string.printable
    if type_ == 1:
        string_letters = string.ascii_lowercase
    elif type_ == 2:
        string_letters = string.ascii_uppercase
    elif type_ == 3:
        string_letters = string.digits
    elif type_ == 12:
        string_letters = string.ascii_letters
    elif type_ == 13:
        string_letters = ''.join([string.ascii_lowercase, string.digits])
    elif type_ == 23:
        string_letters = ''.join([string.ascii_uppercase, string.digits])
    elif type_ == 123:
        string_letters = ''.join([string.ascii_letters, string.digits])

    if repeat:
        strings = ''.join(random.sample(string_letters, length))
    else:
        strings = ''.join(
            [random.choice(string_letters) for i in range(length)])
    return strings

def prepare_data(abs_path, abs_file):
    """
    文件数据预处理.
    3.遍历文件，将tables及依赖数据清洗出来
    4.将ddl语句按照table_name.sql文件名存储在save_path下
    5.返回tables_relation、tables_name, save_path, dml dict

    Futures：
        读取table data行数，并记录之，为多线程执行insert sql做准备。
    """
    logging.info('Begin prepare data!')
    dml_begin_re = r'^DROP TABLE IF EXISTS `(.*)`;$'
    dml_end_re = r"^\) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='.*';$"
    dml_ref_re = r".*CONSTRAINT `.*` FOREIGN KEY .* REFERENCES `(.*)` .*"
    ddl_begin_re = r'^LOCK TABLES `(.*)` WRITE;$'
    ddl_end_re = r'UNLOCK TABLES;'
    sql_set_check = u"""
    /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
    /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
    /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
    /*!40101 SET NAMES utf8 */;
    /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
    /*!40103 SET TIME_ZONE='+00:00' */;
    /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
    /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS,
    FOREIGN_KEY_CHECKS=0 */;
    /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
    /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
                     """
    dml = {}    # 存储dml代码
    tables_relation = []
    tables_name = []
    is_ddl, is_dml = False, False
    with open(abs_file, 'r') as f:
        dml_buffer = []
        dml_f = open(os.path.join(abs_path, 'dml.sql'), 'wt')
        dml_f.write(sql_set_check)
        for line in f:
            if re.match(dml_begin_re, line):
                is_dml, is_ddl = True, False
                # dml_buffer.append(line) # 避免写入两次
                # dml_f.write(line)
                table_name = re.match(dml_begin_re, line).group(1)
                tables_name.append(table_name)
            elif is_dml and re.match(dml_end_re, line):
                is_dml, is_ddl = False, False
                dml_buffer.append(line)
                dml_f.write(line)
                dml[table_name] = r'\n'.join(dml_buffer)
                dml_buffer = []
            elif re.match(ddl_begin_re, line):
                is_dml, is_ddl = False, True
                ddl_f = open(os.path.join(abs_path, table_name + '.sql'), 'wt')
                # ddl_f.write(line) # 避免写入两次
                # ddl_f.write(r'\n')
            elif is_ddl and re.match(ddl_end_re, line):
                is_dml, is_ddl = False, False
                ddl_f.write(line)
                # ddl_f.write(r'\n')
                ddl_f.close()

            if is_dml:
                dml_buffer.append(line)
                dml_f.write(line)
                result = re.match(dml_ref_re, line)
                if result:
                    ref_table_name = result.group(1)
                    tables_relation.append((ref_table_name, table_name))
            elif is_ddl:
                ddl_f.write(line)
                # ddl_f.write(r'\n')
        dml_f.close()
    logging.info('End prepare data!')
    return tables_relation, tables_name, abs_path, dml

def run_dml(command_, dml):
    """Run dml create tables."""
    command_ = command_.split(' ')
    command_.append(dml)
    out_bytes = subprocess.check_output('mysql -uroot -p123456 test2 < /tmp/test/dml.sql', shell=True)
    print(out_bytes.decode('utf-8'))

if __name__ == '__main__':
    # elements = [('A', 'C'), ('A', 'D'), ('A', 'G'), ('B', 'C'),
                # ('D', 'B'), ('D', 'E'), ('F', 'E'), ('G', 'F'), ('B', 'G')]
    # print(parser(elements))
    dml = r'/tmp/test/dml.sql'
    run_dml('mysql -uroot -p123456 test1 < ', r'/tmp/test/dml.sql')


import pygame

pygame.init() #초기화

#화면 크기
screen_width=626
screen_height=383
screen=pygame.display.set_mode((screen_width,screen_height))

#화면 타이틀
pygame.display.set_caption("Pang")

#배경 이미지
background=pygame.image.load("C:/Users/pixels-007/Desktop/준표/파이썬/background.jpg")
#이벤트
running=True
while running:
    for event in pygame.event.get():
        if event.type==pygame.QUIT: #창이 닫히는 이벤트
            running=False

    screen.blit(background,(0,0))
    pygame.display.update()

#ptgame 종료
pygame.quit()


import linecache as lc
from googletrans import Translator
from os import system, name
from os import SEEK_END

def rawcount(filename):
    f = open(filename, 'rb')
    lines = 1
    buf_size = 1024 * 1024
    read_f = f.raw.read

    buf = read_f(buf_size)
    while buf:
        lines += buf.count(b'\n')
        buf = read_f(buf_size)
    return lines

def main():
    last_per = 0
    translator = Translator()
    i = 1
    last_line = rawcount("text.txt")
    print("          ------------------------------")
    print("PROGRASS [", end='')
    while (i != last_line):
        # Using linecache.getline() method
        gfg = lc.getline('text.txt', i)
        translation = translator.translate(gfg, dest='fa')
        with open('result.txt', "a", encoding="utf-8") as f2:
            f2.writelines(translation.text)
            f2.writelines("\n")
            #f2.writelines(gfg)
            #f2.writelines("\n")

        percent = int((i / last_line) * 100)

        if(last_per!=percent):
            last_per = percent
            if ((last_per%10) == 0):
                print(" = ", end='')

        i += 1
    print("]\n\nSuccess!")

main()