from __future__ import print_function, unicode_literals

from select import kqueue, kevent # Raises ImportError if no select.poll
import errno
import select

from collections import deque

from versile.internal import _vexport, _v_silent
from versile.reactor.waitr import VFDWaitReactor

__all__ = ['VKqueueReactor']
__all__ = _vexport(__all__)

_KQ_FILTER_READ = select.KQ_FILTER_READ
_KQ_FILTER_WRITE = select.KQ_FILTER_WRITE
_KQ_EV_ADD = select.KQ_EV_ADD
_KQ_EV_DELETE = select.KQ_EV_DELETE
_KQ_EV_EOF = select.KQ_EV_EOF
_KQ_EV_ERROR = select.KQ_EV_ERROR

class VKqueueReactor(VFDWaitReactor):
    """Reactor which uses :func:`select.kqueue` to controls it event loop.

    The reactor uses :func:`select.kqueue` for non-blocking monitoring
    descriptors. It also employes an internal messaging system to
    allow other systems to wake up the event loop by signalling over
    an internal pipe system.

    Only available on systems that support :func:`select.kqueue`\ .

    """
    # The reactor uses level-based triggering

    def __init__(self, daemon=False):
        super(VKqueueReactor, self).__init__(daemon=daemon)
        self.__kqueue = kqueue()
        self.__rfd = set()
        self.__wfd = set()
        self.__robj = dict() # fd -> obj
        self.__wobj = dict() # fd -> obj

    def _fd_wait(self, timeout):
        if timeout is not None and timeout < 0:
            timeout = None

        y_events = deque()
        # HARDCODED - listening for maximum 1M events, as kqueue.control does
        # not support passing 'unlimited'
        try:
            p_events = self.__kqueue.control(None, 0x100000, timeout)
        except IOError as e:
            # Return if interrupted by signal handler, not catching can
            # interfere e.g. with interactive use in a python interpreter
            if e.errno == errno.EINTR:
                return deque()
        except Exception as e:
            raise e
        for event in p_events:
            fd = event.ident
            _rd_event = (event.filter == _KQ_FILTER_READ)
            _wr_event = (event.filter == _KQ_FILTER_WRITE)
            _error = event.flags & _KQ_EV_ERROR or event.flags & _KQ_EV_EOF

            if _rd_event:
                f_obj = self.__robj.get(fd, None)
                if f_obj is None:
                    f_obj = fd
                if _error:
                    y_events.append((self._FD_READ_ERROR, f_obj))
                else:
                    y_events.append((self._FD_READ, f_obj))
            if _wr_event:
                f_obj = self.__wobj.get(fd, None)
                if f_obj is None:
                    f_obj = fd
                if _error:
                    y_events.append((self._FD_WRITE_ERROR, f_obj))
                else:
                    y_events.append((self._FD_WRITE, f_obj))
        return y_events

    def _add_read_fd(self, fd):
        if not isinstance(fd, (int, long)):
            fd, f_obj = fd.fileno(), fd
        else:
            f_obj = None
        if fd < 0:
            raise IOError('Invalid file descriptor')
        if fd in self.__rfd:
            return

        try:
            ev = kevent(fd, _KQ_FILTER_READ, _KQ_EV_ADD)
            self.__kqueue.control([ev], 0)
        except Exception as e:
            raise IOError('Failed to update kqueue object: %s' % e)
        else:
            self.__rfd.add(fd)
            if f_obj is not None:
                self.__robj[fd] = f_obj

    def _add_write_fd(self, fd):
        if not isinstance(fd, (int, long)):
            fd, f_obj = fd.fileno(), fd
        else:
            f_obj = None
        if fd < 0:
            raise IOError('Invalid file descriptor')
        if fd in self.__wfd:
            return

        try:
            ev = kevent(fd, _KQ_FILTER_WRITE, _KQ_EV_ADD)
            self.__kqueue.control([ev], 0)
        except Exception as e:
            raise IOError('Failed to update kqueue object: %s' % e)
        else:
            self.__wfd.add(fd)
            if f_obj is not None:
                self.__wobj[fd] = f_obj

    def _remove_read_fd(self, fd):
        if not isinstance(fd, (int, long)):
            fd, f_obj = fd.fileno(), fd
        else:
            f_obj = None
        if fd < 0:
            # With proper sequencing of removing vs. closing in the
            # reactor thread, this should not happen - however, in
            # case it does, we check here whether f_obj is registered
            # with self.__robj or self.__wobj and if so remove the associated
            # (no longer valid) descriptor.
            if f_obj:
                self.__purge_old_fd_obj(f_obj)
            _v_silent(IOError('Tried to _remove_read_fd invalid descriptor'))
            return
        if fd not in self.__rfd:
            return

        try:
            ev = kevent(fd, _KQ_FILTER_READ, _KQ_EV_DELETE)
            self.__kqueue.control([ev], 0)
        except Exception as e:
            raise IOError('Failed to update kqueue object: %s' % e)
        finally:
            self.__rfd.discard(fd)
            self.__robj.pop(fd, None)

    # Apply isinstance(int, long) also to poll, epoll etc.
    def _remove_write_fd(self, fd):
        if not isinstance(fd, (int, long)):
            fd, f_obj = fd.fileno(), fd
        else:
            f_obj = None
            fd = fd.fileno()
        if fd < 0:
            # With proper sequencing of removing vs. closing in the
            # reactor thread, this should not happen - however, in
            # case it does, we check here whether f_obj is registered
            # with self.__robj or self.__wobj and if so remove the associated
            # (no longer valid) descriptor.
            if f_obj:
                self.__purge_old_fd_obj(f_obj)
            _v_silent(IOError('Tried to _remove_read_fd invalid descriptor'))
            return
        if fd not in self.__wfd:
            return

        try:
            ev = kevent(fd, _KQ_FILTER_WRITE, _KQ_EV_DELETE)
            self.__kqueue.control([ev], 0)
        except Exception as e:
            raise IOError('Failed to update kqueue object: %s' % e)
        finally:
            self.__wfd.discard(fd)
            self.__wobj.pop(fd, None)

    def _fd_done(self):
        self.__kqueue.close()
        self.__kqueue = None
        self.__rfd.clear()
        self.__wfd.clear()
        self.__robj.clear()
        self.__wobj.clear()

    def __purge_old_fd_obj(self, fd_obj):
        for f, o in self.__robj.items():
            if o is fd_obj:
                try:
                    self._remove_read_fd(f)
                except Exception as e:
                    _v_silent(e)
                break

        for f, o in self.__wobj.items():
            if o is fd_obj:
                try:
                    self._remove_write_fd(f)
                except Exception as e:
                    _v_silent(e)
                break


l=input()
s=list(l)
for i in range(len(s)):
	x=ord(s[i])
	if(97<=x<=122):
		x=x-32
		s[i]=chr(x)
	elif(65<=x<=90):
		x=x+32
		s[i]=chr(x)
print("".join(s))


# This file is part of django-ca (https://github.com/mathiasertl/django-ca).
#
# django-ca is free software: you can redistribute it and/or modify it under the terms of the GNU General
# Public License as published by the Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# django-ca is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along with django-ca. If not, see
# <http://www.gnu.org/licenses/>.

"""The docker-test subcommand generates the Docker image using various base images."""
import argparse
import os
import subprocess
import sys

from devscripts import config
from devscripts.commands import DevCommand
from devscripts.out import err, info, ok

class Command(DevCommand):
    """Build the Docker image using various base images."""

    def add_arguments(self, parser: argparse.ArgumentParser) -> None:
        project_config = config.get_project_config()
        parser.add_argument(
            "-i",
            "--image",
            action="append",
            dest="images",
            choices=project_config["docker"]["alpine-images"],
            metavar=project_config["docker"]["metavar"],
            help="Base images to test on, may be given multiple times.",
        )
        parser.add_argument(
            "--no-cache", default=False, action="store_true", help="Use Docker cache to speed up builds."
        )
        parser.add_argument(
            "--fail-fast", action="store_true", default=False, help="Stop if any docker process fails."
        )
        parser.add_argument("--keep-image", action="store_true", default=False, help="Do not remove images.")
        parser.add_argument("-l", "--list", action="store_true", help="List images and exit.")

    def handle(self, args: argparse.Namespace) -> None:  # pylint: disable=too-many-branches
        docker_runs = []

        project_config = config.get_project_config()
        images = args.images or project_config["docker"]["alpine-images"]

        if args.list:
            for image in images:
                print(image)
            return

        for image in images:
            info(f"### Testing {image} ###")
            tag = f"django-ca-test-{image}"

            cmd = ["docker", "build"]

            if args.no_cache:
                cmd.append("--no-cache")
            if image != "default":
                cmd += ["--build-arg", f"IMAGE={image}"]

            cmd += [
                "-t",
                tag,
            ]
            cmd.append(".")

            print(" ".join(cmd))

            logdir = ".docker"
            logpath = os.path.join(logdir, f"{image}.log")
            if not os.path.exists(logdir):
                os.makedirs(logdir)

            env = dict(os.environ, DOCKER_BUILDKIT="1")

            try:
                with subprocess.Popen(
                    cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env
                ) as proc, open(logpath, "bw") as stream:
                    while True:
                        byte = proc.stdout.read(1)  # type: ignore[union-attr]  # not None due to arguments
                        if byte:
                            sys.stdout.buffer.write(byte)
                            sys.stdout.flush()
                            stream.write(byte)
                            # logfile.flush()
                        else:
                            break

                if proc.returncode == 0:
                    ok(f"{image} passed.")
                    docker_runs.append({"image": image, "success": True, "error": ""})
                else:
                    failed_str = f"# {image} failed: return code {proc.returncode}. #"

                    # pylint: disable-next=consider-using-f-string  # just more convenient
                    err("%s\n%s\n%s\n\n" % ("#" * len(failed_str), failed_str, "#" * len(failed_str)))
                    docker_runs.append(
                        {
                            "image": image,
                            "success": False,
                            "error": f"return code: {proc.returncode}",
                        }
                    )

            except Exception as e:  # pylint: disable=broad-except; to make sure we test all images
                msg = f"{image}: {type(e).__name__} {e}"
                docker_runs.append({"image": image, "success": False, "error": msg})
                err(f"\n{msg}\n")
                if args.fail_fast:
                    sys.exit(1)
            finally:
                if not args.keep_image:
                    self.run("docker", "image", "rm", tag, check=False)

        print("\nSummary of test runs:")
        for run in docker_runs:
            if run["success"]:
                ok(f"  {run['image']}: passed.")
            else:
                err(f"  {run['image']}: {run['error']}")

        failed_images = sorted([r["image"] for r in docker_runs if not r["success"]])
        if not failed_images:
            ok("\nCongratulations :)")
        else:
            err(f"\nSome images failed ({', '.join(failed_images)})")
            sys.exit(1)


# Slide 1 - Monte Carlo Simulation

import numpy as np
def rand_perm(n):
  perm = np.arange(1,n+1)
  for i in np.arange(n-1):
    j = int(i+np.floor((n-i)*np.random.random(1)))
    swap = perm[i].copy()
    perm[i] = perm[j].copy()
    perm[j] = swap
  return perm
print(rand_perm(6)) ; print(np.random.choice(6,6, replace=False) + 1)

# Slide 2 - Monte Carlo Simulation
import numpy as np
def f(x):
  return np.log(x)/2
n = 10**4
print(np.mean(f(np.random.geometric(2/3, n))))
x = np.arange(1,n+1)
print(np.sum(np.log(x)/3**x))

cards = ["rat", "Ox", "Tiger", "Rabbit", "Dragon", "Snake",
         "Horse", "Sheep", "Monkey", "Rooster", "Dog", "Pig"]

def coupon_col1(cards):
    ncards = len(cards)
    getcards = np.zeros(ncards)
    success = 0
    nTrials = 0
    while success == 0:
        nTrials += 1
        purchase = int(np.floor(ncards * np.random.random(1)))
        getcards[purchase] = 1
        if np.sum(getcards) == ncards:
            success = 1
    return nTrials

print(coupon_col1(cards))
nreps = 10 ** 4
n = len(cards)
x = [coupon_col1(cards) for i in range(nreps)]
print(np.mean(x));
print(np.sum(n / (n + 1 - np.arange(1, n + 1))))

# Slide 3 - The Inverse Transform Method

import numpy as np
import pandas as pd
from scipy.stats import poisson
def poisson_sim(lamb):
  X = 0
  px = np.exp(-lamb)
  Fx = px
  U = np.random.random(1)
  while Fx < U:
    X += 1
    px *= lamb/X
    Fx += px
  return X

nreps = 10**4
lamb = 0.5
poissonX = pd.DataFrame([poisson_sim(lamb) for i in range(nreps)])

print(poissonX.value_counts()/nreps)
print(list(map(lambda x: round(poisson.pmf(x, 0.5),4), np.arange(5+1))))
print(np.mean(poissonX)/np.var(poissonX))

# Slide 4 - The Inverse Transform Method
from scipy.stats import poisson
import numpy as np
import pandas as pd

def binom_sim(n,p):
  X = 0; px = (1-p)**n ; Fx = px ; U = np.random.random(1)
  while Fx < U:
    X += 1
    px *= p/(1-p)*(n-X+1)/X
    Fx += px
  return X
def poisson_sim(lamb):
  X = 0
  px = np.exp(-lamb)
  Fx = px
  U = np.random.random(1)
  while Fx < U:
    X += 1
    px *= lamb/X
    Fx += px
  return X
nreps = 10**4 ; n = 10**2 ; p = 0.005
binomX = pd.DataFrame([binom_sim(n,p) for i in range(nreps)])
print(binomX.value_counts()/nreps)

lamb = 0.5
poissonX = pd.DataFrame([poisson_sim(lamb) for i in range(nreps)])
print(poissonX.value_counts()/nreps)
print(list(map(lambda x: round(poisson.pmf(x, 0.5),4), np.arange(5+1))))

def pois_falls(N):
  temp = np.random.random(N)
  falls = (1/N < temp)*(temp < 2/N)
  return sum(falls)==0
N = 10**3; print(pois_falls(N))
nreps = 10**4 ; count1 = [pois_falls(N) for i in range(nreps)]
print(1/np.mean(count1)) ; print(np.exp(1))

# Slide 5 - The Inverse Transform Method
import numpy as np
import matplotlib.pyplot as plt
n = 10**4 ; u = np.random.random(n)
X = np.tan(np.pi*(u-1/2))
print(np.median(X)) ; print(np.mean(X))
print(np.mean(abs(X))) ; print(np.var(X))

X = np.log(u/(1-u))
plt.hist(X, bins=30, density=True)
plt.ylim([0, 0.3])
xs = np.linspace(-8,8)
ys = np.exp(-xs)/(1+np.exp(-xs))**2
plt.plot(xs,ys, color="red")
plt.show()
print(np.median(X)) ; print(np.mean(X))

# Slide 6 - The Inverse Transform Method
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(17)

n = 10**4 ; u = np.random.random(n)
X = np.sqrt(-2*np.log(1-u))
plt.hist(X, bins=30, density=True)
plt.ylim([0,0.8])
xs = np.linspace(0,5)
ys = xs*np.exp(-xs**2/2)
plt.plot(xs,ys,color="red")
plt.show()

plt.clf()
np.random.seed(15)
n = 10**3; u = np.random.random(n)
X = np.log(2*u)*(u < 1/2) - np.log(2*(1-u))*(1/2 <u)
plt.hist(X, bins=25, density=True)
plt.xlim([-6,6])
plt.ylim([0,0.6])
xs = np.linspace(-6,6,1000)
ys = np.exp(-abs(xs))/2
plt.plot(xs,ys)
plt.show()

# Slide 7 - Transform Methods
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import beta
import scipy.stats as stats
nreps = 10**3
def beta_sim(n,m):
  X = np.sum(np.log(np.random.random(n)))
  Y = np.sum(np.log(np.random.random(m)))
  return X/(X+Y)

beta_rv = [beta_sim(3,2) for i in range(nreps)]
print(np.mean(beta_rv))
q = list(map(lambda x: beta.ppf(x,3,2), np.linspace(0,1,nreps)))
stats.probplot(q, dist=stats.beta, sparams=(3,2), plot=plt)
plt.show()

# Slide 8 - Generating Normal RV : Box-Muller Transformtion

import numpy as np
nsim = 10**5 ; z = np.zeros(int((nsim/2))*2).reshape(int(nsim/2),2)
for i in np.arange(nsim/2):
  i = int(i)
  u = np.random.random(2)
  z[i,0] = np.sqrt(-2*np.log(u[0]))*np.cos(2*np.pi*u[1])
  z[i,1] = np.sqrt(-2*np.log(u[0]))*np.sin(2*np.pi*u[1])

print(z)

# Slide 9 - Generating Normal RV : Central Limit Theorem
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm

nsim = 10**4 ; n =30
x = np.random.random(nsim*n).reshape(nsim,n)
xbar1 = np.sqrt(12*n)*(np.mean(x, axis=1)-1/2)
print(np.mean(xbar1))
plt.hist(xbar1, bins=30, density=True)
plt.xlabel("Standardized Xbar")
plt.title("Standard Normal Random Numbers generated by CLT")

xs = np.arange(-4, 4, 0.05)
ys = list(map(lambda x: norm.pdf(x,0,1), xs))
plt.plot(xs, ys)
plt.show()

plt.clf()

nsim = 10**4 ; n =30
x = np.random.random(nsim*n).reshape(nsim,n)
sx = np.std(x, axis=1)
tn = np.sqrt(n)*(np.mean(x, axis=1)-1/2)/sx
plt.hist(tn, bins=30, density=True)
plt.xlim([-3,3])
xs = np.arange(-3,3,0.05)
ys = list(map(lambda x: norm.pdf(x,0,1), xs))
plt.plot(xs, ys, color="red")
plt.title("Studentized Normal Random Numbers generated by CLT")
plt.xlabel("Studentized Sample Mean")
plt.show()

# Slide 10 - Student¡¯s t-Distribution
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde
from scipy.stats import norm, t
np.random.seed(100)
nsim=10**4 ; n = 4
x = np.random.normal(1,2,n*nsim).reshape(nsim,n)
xbar = np.mean(x, axis=1)
sx = np.std(x, axis=1)
stx = np.sqrt(n)*(xbar-1)/sx
plt.hist(stx, density=True, bins=100)
plt.ylim([0, 0.5])
plt.xlim([-6,6])
plt.title("Simulating t(3) random variables")
density = gaussian_kde(stx)
xs = np.linspace(-6, 6, 800)
plt.plot(xs,density(xs), color="black")

x1 = np.arange(-4, 4, 0.01)
z1 = list(map(lambda x: norm.pdf(x, 0, 1), x1))
plt.plot(x1, z1, color="indianred", linestyle=(0,(4.5,1.5)))
t1 = list(map(lambda x: t.pdf(x, 3), x1))
plt.plot(x1, t1, color="blue", linestyle=(0,(3,1,1,1)))
plt.legend(["studentized xbar", "N(0,1)","t(3)"], loc=(0.6,0.7))
plt.show()

# Slide 11 - Simulating t-distribution
from scipy.stats import chi2,t,gamma, norm
import numpy as np
import matplotlib.pyplot as plt

def t_sim1(r):
  x = np.random.normal(0, 1, 1)
  y = chi2.rvs(df=r, size=1)
  t_rv = x/(np.sqrt(y/r))
  return t_rv

np.random.seed(10)
t_rvs = [t_sim1(3) for i in range(10**4)]
print(np.mean(t_rvs)) ; print(np.var(t_rvs))
print(np.var(t.rvs(df=3, size=10**4)))

def t_sim2(r):
  y = gamma.rvs(a=r/2, loc=1/2, size=1)
  t_rv = np.random.normal(0, np.sqrt(r/y), 1)
  return t_rv

np.random.seed(15)
t_rvs = np.array([t_sim2(3) for i in range(10**4)]).reshape(-1)

plt.hist(t_rvs, density=True, bins=100)
plt.xlabel("Studentized Sample Mean")
plt.title("Simulating t(3) Random Numbers")
plt.xlim([-6,6])
plt.ylim([0,0.5])

xs = np.arange(-3, 3, 0.01)
ys = list(map(lambda x: norm.pdf(x, 0, 1), xs))
plt.plot(xs, ys, color="blue")
x1 = np.arange(-6, 6, 0.01)
y1 = list(map(lambda x: t.pdf(x,3), x1))
plt.plot(x1, y1, color="red")
plt.show()

# Slide 12 - Simulating t-distribution
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import t
import scipy.stats as stats

def t_sim3(r):
  u = np.random.random(2)
  t_rv = np.sqrt(r*((u[0])**(-2/r)-1)) * np.cos(2*np.pi*u[1])
  return t_rv

np.random.seed(20)
nreps = 10**4
t_rvs = [t_sim3(3) for i in range(nreps)]
q = list(map(lambda x: t.ppf(q=x,df=3), np.linspace(0,1,nreps)))
stats.probplot(q, dist=stats.t, sparams=(3,), plot=plt)
plt.show()

# Slide 13 - Method of Composition : Mixture Representation
from scipy.stats import expon, poisson, geom
import numpy as np
import pandas as pd
np.random.seed(3)
n=10**4 ; lamb=2
x = expon.rvs(scale=1/lamb, size=n)
y = pd.DataFrame(np.array(list(map(lambda x: poisson.rvs(mu=x, size=1), x))).reshape(-1))
print(y.value_counts()/n)
print(list(map(lambda x: round(geom.pmf(x, p=2/3, loc=-1),3), np.arange(0,9))))

# Slide 14 - Method of Composition : Mixture Representation
from scipy.stats import expon
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(10)
n = 10**3 ; u =np.random.random(n)
y = -np.log(1-u)
x = expon.rvs(scale=y, size=n)
print(np.mean(x/y))

np.random.seed(11)
n = 10**3 ; u1 =np.random.random(n)
u2 = np.random.random(n)
x = -np.log(1-u1)*(2*(u2<1/2)-1)
plt.hist(x, bins=25, density=True)
plt.xlim([-6,6])
plt.ylim([0,0.6])

xs = np.linspace(-6,6,1000)
ys = np.exp(-abs(xs))/2
plt.plot(xs,ys)
plt.show()


def calc(num):
	total=[num,num*2,num*3,num*4,num*5,num*6]
	li=[frozenset(str(a)) for a in total ]
	return len(set(li))==1
def main():
	num=1
	base=False
	while not base:
		base=calc(num)
		num+=1
	print("Answer is {0}".format(num-1))
main()
#Answer is 142857!.. i did it


import pandas as pd
import numpy as np
import json
import os
from typing import Union, List, Dict

class QuestionUpload:
    def __init__(self, file_uploaded: Union[str, pd.DataFrame] = None,
                 save_as: str = "Default_DB" # file_name: str = None
                 ):
        """
        Initialize the class with any necessary attributes or parameters
        :param file_uploaded: file name or dataframe that contains the questions to upload
        """
        self.file_uploaded = file_uploaded
        self.save_as = save_as
        self.file_format = None

    def upload_questions(self, file_, file_type: str = "csv"):
        """
        Uploads questions from a file and converts it to a pandas DataFrame
        :param file_: file object or file path
        :param file_type: type of file being uploaded i.e csv, txt or json. Defaults to csv.
        :return: DataFrame containing the questions
        """
        if file_type == 'csv':
            questions_df = pd.read_csv(file_)
            self.file_format = "csv"

        elif file_type == 'txt':
            questions_df = pd.read_csv(file_, delimiter='\t')
            self.file_format = "txt"

        elif file_type == 'json':
            questions_df = pd.read_json(file_)
            self.file_format = "json"

        else:
            raise ValueError(f"Invalid file type: {file_type}. Supported types are 'csv', 'txt', and 'json'.")

        return questions_df

    def save_questions(self, questions: Union[list, pd.Series, str]) -> None:
        """
        Saves the questions to the specified file format
        :param questions: list, pandas series or json of questions
        """
        if os.path.isfile(self.save_as):
            raise FileExistsError(f"File {self.save_as} already exists.")

        if isinstance(questions, list):
            if self.file_format == "csv":
                pd.DataFrame(questions).to_csv(self.save_as, index=False)
            elif self.file_format == "json":
                with open(self.save_as, "w") as f:
                    json.dump(questions, f)
            else:
                raise ValueError(f"Invalid file format: {self.file_format}. Only csv and json are supported.")

        elif isinstance(questions, pd.Series):
            if self.file_format == "csv":
                questions.to_csv(self.save_as, index=False)
            elif self.file_format == "json":
                with open(self.save_as, "w") as f:
                    json.dump(questions.to_list(), f)

    def edit_questions(self, questions: Union[List[str], pd.Series, dict],
                       index: int,
                       new_question: str):
        """
        Edits a question at a given index
        :param questions: list, pandas series, or dict containing questions
        :param index: index of the question to edit
        :param new_question: the new question to replace the old one
        :return: the updated list, pandas series, or dict
        """
        if isinstance(questions, list):
            questions[index] = new_question

        elif isinstance(questions, pd.Series):
            questions.iloc[index] = new_question

        elif isinstance(questions, dict):
            questions[index] = new_question

        else:
            raise TypeError("Invalid type for questions. Should be list, pandas series, or dict.")

        return questions


# BINARY TREE INCLUDES
"""
Write a function, binary_search_tree_includes, that takes in the root of a binary search tree containing numbers and a target value.
The function should return a boolean indicating whether or not the target is found within the tree.

A Binary Search Tree is a binary tree where all values within a node's left subtree are smaller than the node's value
and all values in a node's right subtree are greater than or equal to the node's value.

Your solution should have a best case runtime of O(log(n)).
"""
class Node:
   def __init__(self, val):
     self.val = val
     self.left = None
     self.right = None

def binary_search_tree_includes(root, target):
    # base case
    if not root:
        return False

    # target was found
    if root.val == target:
        return True

    # keep searching. compare value to decide if we should go left or right
    if target < root.val:
        return binary_search_tree_includes(root.left, target)
    else:
        return binary_search_tree_includes(root.right, target)

a = Node(12)
b = Node(5)
c = Node(18)
d = Node(3)
e = Node(9)
f = Node(19)

a.left = b
a.right = c
b.left = d
b.right = e
c.right = f

#      12
#    /   \
#   5     18
#  / \     \
# 3   9     19

assert binary_search_tree_includes(a, 9) == True
assert binary_search_tree_includes(a, 15) == False

print("All tests passed!")


from tuple_support import get_data, get_data2, Reading

# for d in get_data():
#     print('({}, {}), reading: {}'.format(
#         d[1], d[0], d[2]
#     ))

for d in get_data2():
    print('({}, {}), reading: {}'.format(
        d.x, d.y, d.value
    ))

t = (1,2,3,4)
r = Reading(*t)
print(r)


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

# import glob, os, re, shutil
# from subprocess import call

#
# what's actually done here is:
# 1. delete silence from the beginning until the first sound (greater than -52 d)
# 2. cut the following 1.8 seconds
# 3. reverse the cut part
# 4. delete silence from the beginning of the reversed cut part
# 5. reverse the cut part back
# 6. save the cut part to a new file
# 7. restart the process on the remainder of the original file

# "/Users/yairshefi/temp/cut/sox-14.4.1/sox a-p.wav word.wav silence 1 0.1 -52d trim 0 1.8 reverse silence 1 0.1 -52d reverse : newfile : restart"

import glob, os, re, shutil
from subprocess import call
from nameAudioFilesByCsv_en import renameAudioFiles
from convertWavToMp3 import convert

pathToSox = '/Users/yairshefi/temp/cut/sox-14.4.1/sox'
inputDir = '/Users/yairshefi/git/SLPlay/mobile/corona/original/audio/words/en/17apr15/'
# inputDir = '/Users/yairshefi/temp/'
inpuFileName = 'Jenna2'
audioExtension = '.wav'
inputAudioPath = inputDir + inpuFileName + audioExtension
slicedDuration = '1.5'
silenceDecibels = '-82d'

(inputName, ext) = re.split('\.', inputAudioPath)
outputDirBaseName = inputName + '_sliced' + silenceDecibels
wavOutputDir = outputDirBaseName + '_wav'
audioOutputPrefix = 'word'
wavOutputFileNameTemplate = wavOutputDir + '/' + audioOutputPrefix + audioExtension

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

call( [ pathToSox, inputAudioPath, wavOutputFileNameTemplate, 'silence', '1', '0.1', silenceDecibels, 'trim', '0', slicedDuration, 'reverse', 'silence', '1', '0.1', silenceDecibels, 'reverse', ':', 'newfile', ':', 'restart' ] )

inputCsvPath = inputDir + inpuFileName + '.csv'
startLine = 0
renameAudioFiles( inputCsvPath, wavOutputDir, audioOutputPrefix, startLine )

mp3OutputPath = outputDirBaseName + '_mp3'
convert( wavOutputDir, mp3OutputPath )


import sys
sys.stdin = open('input.txt')

# 문자열의 뒤에 A 추가
# 문자열 뒤집고 뒤에 B를 추가

S = input()
T = input()
# S -> T
# 뒤에만 추가가 가능하다는 점!
def possible(S, T):
    while True:
        if S == T:
            return 1
        elif len(S) == len(T):
            return 0
        c = T[-1]
        T = T[0:-1]
        if c == 'B':
            T = T[::-1]

print(possible(S, T))


"""
14361 숫자가 같은 배수
"""
for tt in range(1, int(input()) + 1):
    ls = [0] * 11
    n = int(input())
    mult = [i * n for i in range(2, 10)]
    ans = 'impossible'
    for i in str(n):
        ls[int(i)] += 1
    for i in mult:
        temp = [0] * 11
        for j in str(i):
            temp[int(j)] += 1
        if temp == ls:
            ans = 'possible'
            break

    print(f'#{tt} {ans}')


# -*- coding: utf-8 -*-
import json
import logging
from copy import deepcopy
from datetime import datetime
from enum import IntEnum

from addict import Dict
from console.exception.main import (EnvAlreadyExist, ErrDepVolumeNotFound, ErrInvalidVolume, InnerPortNotFound, InvalidEnvName,
                                    ServiceHandleException, ServiceRelationAlreadyExist)
from console.repositories.app import service_repo, service_source_repo
from console.repositories.app_config import port_repo, volume_repo
from console.repositories.probe_repo import probe_repo
from console.repositories.service_backup_repo import service_backup_repo
from console.services.app_actions import app_manage_service
from console.services.app_actions.app_restore import AppRestore
from console.services.app_actions.exception import ErrBackupNotFound
from console.services.app_actions.properties_changes import (PropertiesChanges, get_template_component,
                                                             get_upgrade_app_template)
from console.services.app_config import (AppPortService, env_var_service, mnt_service)
from console.services.app_config.app_relation_service import \
    AppServiceRelationService
from console.services.app_config.component_graph import component_graph_service
from console.services.app_config.service_monitor import service_monitor_repo
from console.services.backup_service import \
    groupapp_backup_service as backup_service
from console.services.exception import ErrDepServiceNotFound
from console.services.plugin import app_plugin_service
from django.db import transaction
from www.apiclient.regionapi import RegionInvokeApi
from www.apiclient.regionapibaseclient import RegionApiBaseHttpClient
from www.tenantservice.baseservice import BaseTenantService
from www.utils.crypt import make_uuid

logger = logging.getLogger("default")
region_api = RegionInvokeApi()
app_port_service = AppPortService()
app_relation_service = AppServiceRelationService()
baseService = BaseTenantService()

class AsyncAction(IntEnum):
    BUILD = 0
    UPDATE = 1
    NOTHING = 2

# priority: build > update > nothing
priority = {AsyncAction.BUILD.value: 0, AsyncAction.UPDATE.value: 1, AsyncAction.NOTHING.value: 2}

class PropertyType(IntEnum):
    """type of property
    ALL: do not distinguish, use all properties
    ORDINARY: ordinary properties
    DEPENDENT: properties that need to handle dependencies
    """
    ALL = 0
    ORDINARY = 1
    DEPENDENT = 2

class AppDeployService(object):
    def __init__(self):
        self.impl = OtherService()

    def set_impl(self, impl):
        self.impl = impl

    def pre_deploy_action(self, tenant, service, version=None):
        """perform pre-deployment actions"""
        if service.service_source == "market":
            # TODO: set app template init MarketService
            self.impl = MarketService(tenant, service, version)

        self.impl.pre_action()

    def get_async_action(self):
        return self.impl.get_async_action()

    def execute(self, tenant, service, user, is_upgrade, version, committer_name=None, oauth_instance=None):
        async_action = self.get_async_action()
        logger.info("service id: {}; async action is '{}'".format(service.service_id, async_action))
        if async_action == AsyncAction.BUILD.value:
            code, msg, event_id = app_manage_service.deploy(tenant, service, user, oauth_instance=oauth_instance)
        elif async_action == AsyncAction.UPDATE.value:
            code, msg, event_id = app_manage_service.upgrade(
                tenant, service, user, committer_name, oauth_instance=oauth_instance)
        else:
            return 200, "", ""
        return code, msg, event_id

    def deploy(self, tenant, service, user, version, committer_name=None, oauth_instance=None):
        """
        After the preparation is completed, emit a deployment task to the data center.
        """
        self.pre_deploy_action(tenant, service, version)

        return self.execute(tenant, service, user, version, committer_name, oauth_instance=oauth_instance)

class OtherService(object):
    """
    Services outside the market service
    """

    def pre_action(self):
        logger.info("type: other; pre-deployment action.")

    def get_async_action(self):
        return AsyncAction.BUILD.value

class MarketService(object):
    """
    Define some methods for upgrading market services.
    """

    def __init__(self, tenant, service, version, all_component_one_model=None, component_change_info=None, app_version=None):
        self.tenant = tenant
        self.service = service
        self.market_name = None
        # tenant service models
        self.all_component_one_model = all_component_one_model
        self.service_source = service_source_repo.get_service_source(tenant.tenant_id, service.service_id)
        self.install_from_cloud = self.service_source.is_install_from_cloud()
        self.market_name = self.service_source.get_market_name()
        # If no version is specified, the default version is used.
        self.async_action = None
        if not version:
            version = self.service_source.version
            self.async_action = AsyncAction.BUILD.value
        self.version = version
        self.group_key = self.service_source.group_key
        self.changes = component_change_info
        if app_version:
            self.template = json.loads(app_version.app_template)
            self.template_update_time = app_version.update_time
        else:
            self.template = None
            self.template_update_time = None
        self.update_source = False
        # data that has been successfully changed
        self.changed = {}
        self.backup = None

        self.update_funcs = self._create_update_funcs()
        self.sync_funcs = self._create_sync_funcs()
        self.restore_func = self._create_restore_funcs()
        self.async_build, self.async_update = self._create_async_action_tbl()

        self.app_restore = AppRestore(tenant, service)
        self.auto_restore = True

    def dummy_func(self, changes):
        logger.debug("dummy_func")

    def set_properties(self, typ3=PropertyType.ALL.value):
        """
        Types of service properties are ordinary and dependent. when updating an application,
        you need to process the ordinary properties first and then the dependent ones.
        In addition, you don't need to distinguish properties when you roll back.
        """
        all_update_funcs = self._create_update_funcs()
        all_sync_funcs = self._create_sync_funcs()
        m = {
            PropertyType.ORDINARY.value: [
                "deploy_version", "app_version", "image", "slug_path", "envs", "connect_infos", "ports", "volumes", "probe",
                "component_graphs", "component_monitors"
            ],
            PropertyType.DEPENDENT.value: ["dep_services", "dep_volumes", "plugins"]
        }
        keys = m.get(typ3, None)
        if keys is None:
            self.update_funcs = all_update_funcs
            self.sync_funcs = all_sync_funcs
            return
        self.update_funcs = {key: all_update_funcs[key] for key in keys if key in all_update_funcs}
        self.sync_funcs = {key: all_sync_funcs[key] for key in keys if key in all_sync_funcs}

    def _create_update_funcs(self):
        return {
            "deploy_version": self._update_deploy_version,
            "app_version": self._update_version,
            "image": self.dummy_func,
            "slug_path": self.dummy_func,
            "envs": self._update_inner_envs,
            "connect_infos": self._update_outer_envs,
            "ports": self._update_ports,
            "volumes": self._update_volumes,
            "probe": self._update_probe,
            "dep_services": self._update_dep_services,
            "dep_volumes": self._update_dep_volumes,
            "plugins": self._update_plugins,
            "component_graphs": self._update_component_graphs,
            "component_monitors": self._update_component_monitors,
        }

    def _create_sync_funcs(self):
        return {
            "deploy_version": self.dummy_func,
            "app_version": self.dummy_func,
            "image": self.dummy_func,
            "slug_path": self.dummy_func,
            "envs": self._sync_inner_envs,
            "connect_infos": self._sync_outer_envs,
            "ports": self._sync_ports,
            "volumes": self._sync_volumes,
            "probe": self._sync_probe,
            "dep_services": self._sync_dep_services,
            "dep_volumes": self._sync_dep_volumes,
            "plugins": self._sync_plugins,
            "component_monitors": self._sync_component_monitors,
        }

    def _create_restore_funcs(self):
        return {
            "deploy_version": self.dummy_func,
            "app_version": self.dummy_func,
            "image": self.dummy_func,
            "slug_path": self.dummy_func,
            "envs": self._restore_inner_envs,
            "connect_infos": self._restore_outer_envs,
            "ports": self._restore_ports,
            "volumes": self._restore_volumes,
            "probe": self._restore_probe,
            "dep_services": self._restore_dep_services,
            "dep_volumes": self._restore_dep_volumes,
            "plugins": self._restore_plugins,
            "service": self._restore_service,
            "service_source": self._restore_service_source,
        }

    @staticmethod
    def _create_async_action_tbl():
        """
        create an asynchronous action corresponding to the modification of each property
        asynchronous action: build, update or nothing
        """
        async_build = ["deploy_version", "image", "slug_path"]
        async_update = ["envs", "connect_infos", "ports", "volumes", "probe", "dep_services", "dep_volumes", "plugins"]
        return async_build, async_update

    def pre_action(self):
        """
        raise RbdAppNotFound
        raise RecordNotFound
        raise ErrServiceSourceNotFound
        """
        logger.info("type: market; service id: {}; pre-deployment action.".format(self.service.service_id))
        backup = self.create_backup()
        logger.info("service id: {}; backup id: {}; backup successfully.".format(self.service.service_id, backup.backup_id))
        self.set_changes()

        try:
            with transaction.atomic():
                self.modify_property()
                self.sync_region_property()
        except RegionApiBaseHttpClient.CallApiError as e:
            logger.exception(e)
            logger.error("service id: {}; failed to change properties for market service: {}".format(
                self.service.service_id, e))
            self.restore_backup(backup)
            # when a single service is upgraded, if a restore occurs,
            # there is no need to emit an asynchronous action.
            self.async_action = AsyncAction.NOTHING.value

    def set_changes(self):
        pc = None
        if not self.template:
            pc = PropertiesChanges(
                self.service,
                self.tenant,
                all_component_one_model=self.all_component_one_model,
                install_from_cloud=self.install_from_cloud)
            template = get_upgrade_app_template(self.tenant, self.version, pc)
            self.template = template
            self.template_update_time = pc.template_updatetime
        if not self.changes and self.changes != {} and pc:
            _, changes = pc.get_property_changes(template=template)
            logger.debug("service id: {}; dest version: {}; changes: {}".format(self.service.service_id, self.version, changes))
            self.changes = changes

    def create_backup(self):
        """create_backup
        Create a pre-service backup to prepare for deployment failure
        """
        backup_data = backup_service.get_service_details(self.tenant, self.service)
        backup = {
            "region_name": self.service.service_region,
            "tenant_id": self.tenant.tenant_id,
            "service_id": self.service.service_id,
            "backup_id": make_uuid(),
            "backup_data": json.dumps(backup_data),
            "create_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            "update_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        }
        return service_backup_repo.create(**backup)

    def modify_property(self):
        """
        Perform modifications to the given properties. must be called after `set_changes`.
        """
        component = get_template_component(self.template, self.service_source)
        # if component is null, maybe new app not have this component
        if component:
            if not self.update_source:
                self._update_service(component)
                self._update_service_source(component, self.version, self.template_update_time)
                self.update_source = True
            if not self.changes:
                return
            changes = deepcopy(self.changes)
            if changes:
                for k, v in list(changes.items()):
                    func = self.update_funcs.get(k, None)
                    if func is None:
                        continue
                    func(v)
        else:
            raise ServiceHandleException(msg="component is not exist", msg_show="该版本模版不存在该组件，无法进行升级")

    @staticmethod
    def _compare_async_action(a, b):
        """
        compare a, b, two asynchronous actions, returning the ones with higher priority
        """
        if priority[a] < priority[b]:
            return a
        return b

    def get_async_action(self):
        """ get asynchronous action
        must be called after `set_changes`.
        """
        if self.install_from_cloud:
            return AsyncAction.BUILD.value
        if self.async_action is not None:
            return self.async_action
        changes = deepcopy(self.changes)
        async_action = AsyncAction.NOTHING.value
        if changes:
            for key in changes:
                async_action = self._compare_async_action(async_action, self._key_action(key))
        return async_action

    def _key_action(self, key):
        if key in self.async_build:
            return AsyncAction.BUILD.value
        if key in self.async_update:
            return AsyncAction.UPDATE.value
        return AsyncAction.NOTHING.value

    def sync_region_property(self):
        """
        After modifying the properties on the console side, you need to
        synchronize with the region side. must be called after `set_changes`.
        raise: RegionApiBaseHttpClient.CallApiError
        """
        if not self.changes:
            return
        changes = deepcopy(self.changes)
        if changes:
            for k, v in list(changes.items()):
                func = self.sync_funcs.get(k, None)
                if func is None:
                    continue
                func(v)
                self.changed[k] = v

    def restore_backup(self, backup=None):
        """
        Restore data in the region based on backup information
        when an error occurs during deployment.
        """
        logger.info("service id: {}; changed properties: {}; restore service from backup".format(
            self.service.service_id, json.dumps(self.changed)))
        if backup is None:
            # use the latest backup
            backup = service_backup_repo.get_newest_by_sid(self.tenant.tenant_id, self.service.service_id)
        if backup is None:
            raise ErrBackupNotFound(self.service.service_id)

        self._update_changed()

        async_action = AsyncAction.NOTHING.value
        for k, v in list(self.changed.items()):
            func = self.restore_func.get(k, None)
            if func is None:
                continue
            try:
                func(backup)
            except RegionApiBaseHttpClient.CallApiError as e:
                # ignore restore error
                logger.error("service id: {}; failed to restore {}; {}".format(self.service.service_id, k, e))
            async_action = self._compare_async_action(async_action, self._key_action(k))
        self.async_action = async_action

    def _update_changed(self):
        if not self.changed:
            logger.info("service id: {}; no specified changed, will restore \
                all properties".format(self.service.service_id))
            self.changed = self._create_restore_funcs()
        logger.debug("changed to be restored: {}".format(self.changed))

    def _update_service(self, app):
        share_image = app.get("share_image", None)
        if share_image:
            self.service.image = share_image
        self.service.cmd = app.get("cmd", "")
        self.service.version = app["version"]
        self.service.save()

    def _update_service_source(self, app, version, template_updatetime):
        new_extend_info = {}
        share_image = app.get("share_image", None)
        share_slug_path = app.get("share_slug_path", None)
        if share_image and app.get("service_image", None):
            new_extend_info = app["service_image"]
        if share_slug_path:
            slug_info = app.get("service_slug")
            slug_info["slug_path"] = share_slug_path
            new_extend_info = slug_info
        new_extend_info["source_deploy_version"] = app.get("deploy_version")

        if app.get("service_share_uuid", None):
            service_share_uuid = app.get("service_share_uuid")
        else:
            service_share_uuid = app.get("service_key", "")
        new_extend_info["source_service_share_uuid"] = service_share_uuid
        if template_updatetime:
            if type(template_updatetime) == datetime:
                new_extend_info["update_time"] = template_updatetime.strftime('%Y-%m-%d %H:%M:%S')
            elif type(template_updatetime) == str:
                new_extend_info["update_time"] = template_updatetime
        if self.install_from_cloud:
            new_extend_info["install_from_cloud"] = True
            new_extend_info["market"] = "default"
            new_extend_info["market_name"] = self.market_name
        data = {
            "extend_info": json.dumps(new_extend_info),
            "version": version,
        }
        logger.debug("service id: {}; data: {}; update service source.".format(self.service.service_id, data))
        service_source_repo.update_service_source(self.tenant.tenant_id, self.service.service_id, **data)

    def _update_deploy_version(self, dv):
        if not dv["is_change"]:
            return
        self.service.deploy_version = dv["new"]
        self.service.save()

    def _update_version(self, v):
        if not v["is_change"]:
            return
        self.service.version = v["new"]
        self.service.save()

    def _update_inner_envs(self, envs):
        self._update_envs(envs, "inner")

    def _update_outer_envs(self, envs):
        self._update_envs(envs, "outer")

    def _update_envs(self, envs, scope):
        if envs is None:
            return
        logger.debug("service id: {}; update envs; data: {}".format(self.service.service_id, envs))
        # create envs
        add = envs.get("add", [])
        for env in add:
            container_port = env.get("container_port", 0)
            value = env.get("attr_value", "")
            name = env.get("name", "")
            attr_name = env.get("attr_name", "")
            is_change = env.get("is_change", True)
            if not attr_name:
                continue
            if container_port == 0 and value == "**None**":
                value = self.service.service_id[:8]
            try:
                env_var_service.create_env_var(self.service, container_port, name, attr_name, value, is_change, scope)
            except (EnvAlreadyExist, InvalidEnvName) as e:
                logger.warning("failed to create env: {}; will ignore this env".format(e))

    def _update_component_graphs(self, component_graphs):
        if not component_graphs:
            return
        add = component_graphs.get("add", [])
        component_graph_service.bulk_create(self.service.service_id, add)

    def _update_component_monitors(self, component_monitors):
        if not component_monitors:
            return
        add = component_monitors.get("add", [])
        service_monitor_repo.bulk_create_component_service_monitors(self.tenant, self.service, add)

    def _sync_inner_envs(self, envs):
        self._sync_envs(envs, "inner")

    def _sync_outer_envs(self, envs):
        self._sync_envs(envs, "outer")

    def _sync_envs(self, envs, scope):
        """
        raise RegionApiBaseHttpClient.CallApiError
        """
        if envs is None:
            return
        logger.debug("service id: {}; sync envs; data: {}".format(self.service.service_id, envs))
        add = envs.get("add", [])
        for env in add:
            body = self._create_env_body(env, scope)
            if not body:
                continue
            try:
                region_api.add_service_env(self.service.service_region, self.tenant.tenant_name, self.service.service_alias,
                                           body)
            except region_api.CallApiError as e:
                if e.status == 400:
                    logger.warning("env name: {}; failed to create env: {}".format(env["attr_name"], e))
                    continue
                res = Dict({"status": e.status})
                raise region_api.CallApiError(e.apitype, e.url, e.method, res, e.body)

    def _restore_inner_envs(self, backup):
        self._restore_envs(backup, "inner")

    def _restore_outer_envs(self, backup):
        self._restore_envs(backup, "outer")

    def _restore_envs(self, backup, scope):
        backup_data = json.loads(backup.backup_data)
        if isinstance(backup_data, list):
            service_env_vars = backup_data[0].get("service_env_vars", [])
        else:
            service_env_vars = backup_data.get("service_env_vars", [])

        if not self.auto_restore:
            self.app_restore.envs(service_env_vars)

        body = {"scope": scope, "envs": []}
        for env in service_env_vars:
            if scope != env["scope"]:
                continue
            body["envs"].append(self._create_env_body(env, scope))
        try:
            region_api.restore_properties(self.service.service_region, self.tenant.tenant_name, self.service.service_alias,
                                          "/app-restore/envs", body)
        except RegionApiBaseHttpClient.CallApiError as e:
            # ignore restore envs error:
            logger.error("backup id: {}; failed to restore envs: {}".format(backup.backup_id, e))

    def _create_env_body(self, env, scope):
        """
        convert env to the body needed to add environment variables to the region
        """
        container_port = env.get("container_port", 0)
        if 'attr_name' not in env:
            return
        if container_port == 0 and env.get("attr_value") == "**None**":
            env["attr_value"] = self.service.service_id[:8]
        result = {
            "container_port": container_port,
            "tenant_id": self.service.tenant_id,
            "service_id": self.service.service_id,
            "name": env.get("name"),
            "attr_name": env["attr_name"],
            "attr_value": str(env.get("attr_value")),
            "is_change": True,
            "scope": scope,
            "env_name": env["attr_name"],
            "env_value": str(env.get("attr_value")),
            "enterprise_id": self.tenant.enterprise_id
        }
        return result

    def _create_envs_4_ports(self, port):
        container_port = int(port["container_port"])
        port_alias = self.service.service_alias.upper()
        host_env = {
            "name": "连接地址",
            "attr_name": port_alias + str(port["container_port"]) + "_HOST",
            "attr_value": "127.0.0.1",
            "is_change": False,
        }
        port_env = {
            "name": "端口",
            "attr_name": port_alias + str(port["container_port"]) + "_PORT",
            "attr_value": container_port,
            "is_change": False,
        }
        return [host_env, port_env]

    def update_port_data(self, port):
        container_port = int(port["container_port"])
        port_alias = self.service.service_alias.upper()
        k8s_service_name = port.get("k8s_service_name", self.service.service_alias)
        if k8s_service_name:
            filter_port = port_repo.get_by_k8s_service_name(self.tenant.tenant_id, k8s_service_name)
            if filter_port and self.service.service_id:
                k8s_service_name = k8s_service_name + "-" + make_uuid(
                )[-4:] if self.service.service_id != filter_port.service_id else k8s_service_name
            port["k8s_service_name"] = k8s_service_name
        port["tenant_id"] = self.tenant.tenant_id
        port["service_id"] = self.service.service_id
        port["mapping_port"] = container_port
        port["port_alias"] = port_alias

    def _update_ports(self, ports):
        if ports is None:
            return

        add = ports.get("add", [])
        envs = {"add": []}
        for port in add:
            self.update_port_data(port)
            port_repo.add_service_port(**port)
            if not port["is_inner_service"]:
                continue
            envs["add"].extend(self._create_envs_4_ports(port))
        upd = ports.get("upd", [])
        for port in upd:
            self.update_port_data(port)
            port_repo.update(**port)
        if not envs["add"]:
            return
        self._update_envs(envs, "outer")

    def _sync_ports(self, ports):
        """
        raise RegionApiBaseHttpClient.CallApiError
        """
        if ports is None:
            return
        add = ports.get("add", [])
        envs = {"add": []}
        for port in add:
            self.update_port_data(port)
            if not port["is_inner_service"]:
                continue
            envs["add"].extend(self._create_envs_4_ports(port))
        upd = ports.get("upd", [])
        for port in upd:
            self.update_port_data(port)
        add_body = {"port": add, "enterprise_id": self.tenant.enterprise_id}
        region_api.add_service_port(self.service.service_region, self.tenant.tenant_name, self.service.service_alias, add_body)
        upd_body = {"port": upd, "enterprise_id": self.tenant.enterprise_id}
        region_api.update_service_port(self.service.service_region, self.tenant.tenant_name, self.service.service_alias,
                                       upd_body)

        if envs:
            self._sync_outer_envs(envs)

    def _restore_ports(self, backup):
        backup_data = json.loads(backup.backup_data)
        if isinstance(backup_data, list):
            service_ports = backup_data[0].get("service_ports", [])
        else:
            service_ports = backup_data.get("service_ports", [])

        if not self.auto_restore:
            self.app_restore.ports(service_ports)

        try:
            body = {"ports": service_ports}
            region_api.restore_properties(self.service.service_region, self.tenant.tenant_name, self.service.service_alias,
                                          "/app-restore/ports", body)
        except RegionApiBaseHttpClient.CallApiError as e:
            # ignore restore ports error:
            logger.error("backup id: {}; failed to restore ports: {}".format(backup.backup_id, e))

    def _update_volumes(self, volumes):
        for volume in volumes.get("add"):
            volume["service_id"] = self.service.service_id
            host_path = "/grdata/tenant/{0}/service/{1}{2}".format(self.tenant.tenant_id, self.service.service_id,
                                                                   volume["volume_path"])
            volume["host_path"] = host_path
            file_content = volume.get("file_content", None)
            if file_content is not None:
                volume.pop("file_content")
            logger.debug("add volume {} for component {}".format(volume["volume_name"], self.service.service_id))
            v = volume_repo.add_service_volume(**volume)
            if not file_content and volume["volume_type"] != "config-file":
                continue
            file_data = {"service_id": self.service.service_id, "volume_id": v.ID, "file_content": file_content}
            _ = volume_repo.add_service_config_file(**file_data)
        for volume in volumes.get("upd"):
            # only volume of type config-file can be updated,
            # and only the contents of the configuration file can be updated.
            file_content = volume.get("file_content", None)
            if not file_content and volume["volume_type"] != "config-file":
                continue
            v = volume_repo.get_service_volume_by_name(self.service.service_id, volume["volume_name"])
            if not v:
                logger.warning("service id: {}; volume name: {}; failed to update volume: \
                    volume not found.".format(self.service.service_id, volume["volume_name"]))
            logger.debug("update volume {} for component {}".format(v.volume_name, self.service.service_id))
            cfg = volume_repo.get_service_config_file(v)
            cfg.file_content = file_content
            cfg.save()

    def _sync_volumes(self, volumes):
        """
        raise RegionApiBaseHttpClient.CallApiError
        """
        for volume in volumes.get("add"):
            volume["enterprise_id"] = self.tenant.enterprise_id
            try:
                region_api.add_service_volumes(self.service.service_region, self.tenant.tenant_name, self.service.service_alias,
                                               volume)
            except RegionApiBaseHttpClient.CallApiError as e:
                if not e.body or "is exist" not in e.body.msg:
                    logger.exception(e)
                    raise e

    def _restore_volumes(self, backup):
        backup_data = json.loads(backup.backup_data)
        if isinstance(backup_data, list):
            service_config_file = backup_data[0].get("service_config_file", [])
            service_volumes = backup_data[0].get("service_volumes", [])
        else:
            service_config_file = backup_data.get("service_config_file", [])
            service_volumes = backup_data.get("service_volumes", [])
        cfgfs = {item["volume_id"]: item["file_content"] for item in service_config_file}

        if not self.auto_restore:
            self.app_restore.volumes(service_volumes, service_config_file)

        body = {"volumes": []}
        for item in service_volumes:
            item_id = item.get("ID")
            if not item_id:
                item["file_content"] = ""
            else:
                item["file_content"] = cfgfs.get(item_id, "")
            body["volumes"].append(item)
        try:
            region_api.restore_properties(self.service.service_region, self.tenant.tenant_name, self.service.service_alias,
                                          "/app-restore/volumes", body)
        except RegionApiBaseHttpClient.CallApiError as e:
            # ignore restore volumes error:
            logger.error("backup id: {}; failed to restore volumes: {}".format(backup.backup_id, e))

    def _update_probe(self, probe):
        logger.debug("probe: {}".format(probe))
        add = probe.get("add")
        if add:
            add["probe_id"] = make_uuid()
            probe_repo.update_or_create(self.service.service_id, add)
        upd = probe.get("upd", None)
        if upd:
            probe_repo.update_or_create(self.service.service_id, upd)

    def _sync_probe(self, probe):
        """
        raise RegionApiBaseHttpClient.CallApiError
        """
        p = probe_repo.get_probe(self.service.service_id)
        data = p.to_dict()
        data["is_used"] = 1 if data["is_used"] else 0
        add = probe.get("add", None)
        if add:
            region_api.add_service_probe(self.service.service_region, self.tenant.tenant_name, self.service.service_alias, data)
        upd = probe.get("upd", None)
        if upd:
            region_api.update_service_probec(self.service.service_region, self.tenant.tenant_name, self.service.service_alias,
                                             data)

    def _restore_probe(self, backup):
        backup_data = json.loads(backup.backup_data)
        if isinstance(backup_data, list):
            pd = backup_data[0].get("service_probes", [])
        else:
            pd = backup_data.get("service_probes", [])
        if pd:
            probe = pd[0]
            probe["is_used"] = 1 if probe["is_used"] else 0
        else:
            probe = ""

        if not self.auto_restore:
            self.app_restore.probe(probe)

        try:
            region_api.restore_properties(self.service.service_region, self.tenant.tenant_name, self.service.service_alias,
                                          "/app-restore/probe", probe)
        except RegionApiBaseHttpClient.CallApiError as e:
            # ignore restore probe error:
            logger.error("backup id: {}; failed to restore probe: {}".format(backup.backup_id, e))

    def _update_dep_services(self, dep_services):
        def create_dep_service(dep_service_id):
            try:
                app_relation_service.create_service_relation(self.tenant, self.service, dep_service_id)
            except (ErrDepServiceNotFound, ServiceRelationAlreadyExist, InnerPortNotFound) as e:
                logger.warning("failed to create service relation: {}".format(e))

        add = dep_services.get("add", [])
        for dep_service in add:
            create_dep_service(dep_service["service_id"])

    def _sync_dep_services(self, dep_services):
        def sync_dep_service(dep_service_id):
            """
            raise RegionApiBaseHttpClient.CallApiError
            """
            dep_service = service_repo.get_service_by_service_id(dep_service_id)
            body = dict()
            body["dep_service_id"] = dep_service.service_id
            body["tenant_id"] = self.tenant.tenant_id
            body["dep_service_type"] = dep_service.service_type
            body["enterprise_id"] = self.tenant.enterprise_id
            region_api.add_service_dependency(self.service.service_region, self.tenant.tenant_name, self.service.service_alias,
                                              body)

        add = dep_services.get("add", [])
        for dep_service in add:
            sync_dep_service(dep_service["service_id"])

    def _restore_dep_services(self, backup):
        backup_data = json.loads(backup.backup_data)
        if isinstance(backup_data, list):
            service_relation = backup_data[0].get("service_relation", [])
        else:
            service_relation = backup_data.get("service_relation", [])

        if not self.auto_restore:
            self.app_restore.dep_services(service_relation)

        body = {"deps": []}
        for item in service_relation:
            body["deps"].append({
                "dep_service_id": item["dep_service_id"],
                "dep_service_type": item["dep_service_type"],
            })
        try:
            region_api.restore_properties(self.service.service_region, self.tenant.tenant_name, self.service.service_alias,
                                          "/app-restore/deps", body)
        except RegionApiBaseHttpClient.CallApiError as e:
            # ignore restore service relations error:
            logger.error("backup id: {}; failed to restore service relations: {}".format(backup.backup_id, e))

    def _update_dep_volumes(self, dep_volumes):
        def create_dep_vol(dep_volume):
            data = {
                "service_id": dep_volume["service_id"],
                "volume_name": dep_volume["mnt_name"],
                "path": dep_volume["mnt_dir"]
            }
            try:
                mnt_service.create_service_volume(self.tenant, self.service, data)
            except (ErrInvalidVolume, ErrDepVolumeNotFound) as e:
                logger.warning("failed to create dep volume: {}".format(e))

        add = dep_volumes.get("add", [])
        for dep_volume in add:
            create_dep_vol(dep_volume)

    def _sync_dep_volumes(self, dep_volumes):
        def sync_dep_vol(dep_vol_info):
            """
            raise RegionApiBaseHttpClient.CallApiError
            """
            dep_vol = volume_repo.get_service_volume_by_name(dep_vol_info["service_id"], dep_vol_info["mnt_name"])
            if dep_vol is None:
                logger.warning("dep service id: {}; volume name: {}; fail to \
                    sync dep volume: dep volume not found".format(dep_vol_info["service_id"], dep_vol_info["mnt_name"]))
                return
            data = {
                "depend_service_id": dep_vol.service_id,
                "volume_name": dep_vol.volume_name,
                "volume_path": dep_vol_info['mnt_dir'].strip(),
                "enterprise_id": self.tenant.enterprise_id,
                "volume_type": dep_vol.volume_type
            }
            if dep_vol.volume_type == "config-file":
                config_file = volume_repo.get_service_config_file(dep_vol)
                data["file_content"] = config_file.file_content
            region_api.add_service_dep_volumes(self.service.service_region, self.tenant.tenant_name, self.service.service_alias,
                                               data)

        add = dep_volumes.get("add", [])
        for dep_vol in add:
            sync_dep_vol(dep_vol)

    def _restore_dep_volumes(self, backup):
        backup_data = json.loads(backup.backup_data)
        if isinstance(backup_data, list):
            dep_vols = backup_data[0].get("service_mnts", [])
        else:
            dep_vols = backup_data.get("service_mnts", [])

        if not self.auto_restore:
            self.app_restore.dep_volumes(dep_vols)

        body = {"dep_vols": []}
        for dv in dep_vols:
            body["dep_vols"].append({
                "dep_service_id": dv["dep_service_id"],
                "volume_path": dv["mnt_dir"],
                "volume_name": dv["mnt_name"]
            })
        try:
            region_api.restore_properties(self.service.service_region, self.tenant.tenant_name, self.service.service_alias,
                                          "/app-restore/depvols", body)
        except RegionApiBaseHttpClient.CallApiError as e:
            # ignore restore service dependent volumes error:
            logger.error("backup id: {}; failed to restore service dependent volumes: {}".format(backup.backup_id, e))

    def _update_plugins(self, plugins):
        logger.debug("start updating plugins; plugin datas: {}".format(plugins))
        add = plugins.get("add", [])
        try:
            app_plugin_service.create_plugin_4marketsvc(self.service.service_region, self.tenant, self.service,
                                                        self.template["apps"], self.version, add)
        except ServiceHandleException as e:
            logger.exception(e)

        delete = plugins.get("delete", [])
        for plugin in delete:
            app_plugin_service.delete_service_plugin_relation(self.service, plugin["plugin_id"])
            app_plugin_service.delete_service_plugin_config(self.service, plugin["plugin_id"])

    def _sync_plugins(self, plugins):
        """
        raise RegionApiBaseHttpClient.CallApiError
        """
        logger.debug("start syncing plugins; plugin datas: {}".format(plugins))
        add = plugins.get("add", [])
        for plugin in add:
            data = app_plugin_service.build_plugin_data_4marketsvc(self.tenant, self.service, plugin)
            if data:
                region_api.install_service_plugin(self.service.service_region, self.tenant.tenant_name,
                                                  self.service.service_alias, data)

        delete = plugins.get("delete", [])
        for plugin in delete:
            region_api.uninstall_service_plugin(self.service.service_region, self.tenant.tenant_name, plugin["plugin_id"],
                                                self.service.service_alias)

    def _sync_component_monitors(self, component_monitors):
        logger.debug("start syncing component_monitors; component_monitors datas: {}".format(component_monitors))
        monitors = service_monitor_repo.list_by_service_ids(self.tenant.tenant_id, [self.service.service_id])
        for monitor in monitors:
            req = {
                "name": monitor.name,
                "path": monitor.path,
                "port": monitor.port,
                "service_show_name": monitor.service_show_name,
                "interval": monitor.interval,
            }
            try:
                region_api.create_service_monitor(self.tenant.enterprise_id, self.service.service_region,
                                                  self.tenant.tenant_name, self.service.service_alias, req)
            except RegionApiBaseHttpClient.CallApiError as e:
                logger.error("failed to create_component_monitor: {}".format(e))

    def _restore_plugins(self, backup):
        backup_data = json.loads(backup.backup_data)
        if isinstance(backup_data, list):
            relations = backup_data[0].get("service_plugin_relation", [])
        else:
            relations = backup_data.get("service_plugin_relation", [])

        if not self.auto_restore:
            self.app_restore.plugins(relations)

        body = {"plugins": []}
        for r in relations:
            body["plugins"].append({
                "plugin_id": r["plugin_id"],
                "version_id": r["build_version"],
                "switch": r["plugin_status"],
            })
        try:
            region_api.restore_properties(self.service.service_region, self.tenant.tenant_name, self.service.service_alias,
                                          "/app-restore/plugins", body)
        except RegionApiBaseHttpClient.CallApiError as e:
            # ignore restore service plugins error:
            logger.error("backup id: {}; failed to restore service plugins: {}".format(backup.backup_id, e))

    def _restore_service(self, backup):
        backup_data = json.loads(backup.backup_data)
        if isinstance(backup_data, list):
            service_base = backup_data[0].get("service_base", None)
        else:
            service_base = backup_data.get("service_base", None)
        if not self.app_restore:
            self.app_restore.svc(service_base)

    def _restore_service_source(self, backup):
        backup_data = json.loads(backup.backup_data)
        if isinstance(backup_data, list):
            service_source = backup_data[0].get("service_source", None)
        else:
            service_source = backup_data.get("service_source", None)
        if not self.auto_restore:
            self.app_restore.svc_source(service_source)


from collections import defaultdict

def topological_sort(graph):
    def dfs(node):
        nonlocal is_possible
        visited[node] = 1

        for neighbor in graph[node]:
            if visited[neighbor] == 0:
                dfs(neighbor)
            elif visited[neighbor] == 1:
                is_possible = False

        visited[node] = 2
        result.append(node)

    visited = defaultdict(int)
    result = []
    is_possible = True

    for node in list(graph.keys()):  # Use a copy of keys to avoid "dictionary changed size during iteration"
        if visited[node] == 0:
            dfs(node)

    if not is_possible:
        return None

    return result[::-1]

def find_execution_order(node_dict):
    graph = defaultdict(list)

    for node, node_info in node_dict.items():
        subscribed_to = node_info.get('subscribedTo', [])
        for subscribed_node in subscribed_to:
            graph[subscribed_node].append(node)

    execution_order = topological_sort(graph)
    if execution_order is None:
        return None
    #reverse the array and return
    return execution_order[::-1]

if __name__ == '__main__':
    # Example usage:
    node_dict = {
        'node1': {'subscribedTo': ['node2']},
        'node2': {'subscribedTo': ['node3', 'node4']},
        'node3': {'subscribedTo': ["node1"]},
        'node4': {'subscribedTo': []},
        'node5': {'subscribedTo': ['node2', "node1"]}
    }

    execution_order = find_execution_order(node_dict)

    if execution_order is None:
        print("Cyclic dependency found in the example dict. Execution order is not possible.")
    else:
        print("Execution order for the example dict:", execution_order)


#Author-HeNeos
#Description-Many triangles, I love triangles

import adsk.core, adsk.fusion, adsk.cam, traceback
import math

def get_points(n, angle, r):
    ans = [[0.0, 0.0]]*n
    for i in range(0, n):
        ans[i] = [r*math.cos(angle + 2*i*math.pi/n), r*math.sin(angle + 2*i*math.pi/n)]
    return ans

def run(context):
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        ui.messageBox('Are you ready')
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        rootComp = design.rootComponent
        sketches = rootComp.sketches
        xyPlane = rootComp.xYConstructionPlane
        # Create a new ObjectCollection.

        revolves = rootComp.features.revolveFeatures

        r = 4
        loftFeats = rootComp.features.loftFeatures
        loftInput = loftFeats.createInput(adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
        loftSectionsObj = loftInput.loftSections
        n = 6
        for i in range(0, 100):
            angle = (math.pi)*abs(math.sin(i/10))

            ctorPlanes = rootComp.constructionPlanes
            plane = ctorPlanes.createInput()
            offset = adsk.core.ValueInput.createByString(str(i)+" cm")
            plane.setByOffset(xyPlane, offset)
            Plane = ctorPlanes.add(plane)
            sketch = sketches.add(Plane)
            lines = sketch.sketchCurves.sketchLines

            Points = []
            Lines = []
            p = get_points(n, angle, r)
            for j in range(0, n):
                point = adsk.core.Point3D.create(p[j][0], p[j][1], 0)
                Points.append(point)

            for j in range(0, n-1):
                line = lines.addByTwoPoints(Points[j], Points[j+1])
                Lines.append(line)
            Lines.append(lines.addByTwoPoints(Points[n-1], Points[0]))

            for i in range(0, n-1):
                sketch.sketchCurves.sketchArcs.addFillet(Lines[i], Lines[i].endSketchPoint.geometry, Lines[i+1], Lines[i+1].startSketchPoint.geometry, 0.5)
            sketch.sketchCurves.sketchArcs.addFillet(Lines[n-1], Lines[n-1].endSketchPoint.geometry, Lines[0], Lines[0].startSketchPoint.geometry, 0.5)

            profile = sketch.profiles.item(0)
            sketch.isVisible = False
            Plane.isLightBulbOn = False
            loftSectionsObj.add(profile)

        loftInput.isSolid=True
        loftFeats.add(loftInput)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

    #axis = lines.addByTwoPoints(adsk.core.Point3D.create(-1,-4,0), adsk.core.Point3D.create(1,-4,0))
    #circle1 = circles.addByCenterRadius(adsk.core.Point3D.create(0,0,0), 2)

def stop(context):
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        ui.messageBox('Finished')

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


import sys
from tqdm import tqdm
import pandas as pd

def compare_smaller_count(counts1, counts2):
    pass

def anno_segment_compare(item1, item2):
    seq_name1, start1, end1, counts1 = item1
    seq_name2, start2, end2, counts2 = item2

    if len(counts1.keys()) > len(counts2.keys()):
        return 1
    elif len(counts1.keys()) == len(counts2.keys()):
        mins1 = list(counts1.values())
        if len(mins1) == 0:
            return 0
        mins1.sort()
        mins2 = list(counts2.values())
        mins2.sort()

        #comparison = 0
        for i in range(min(len(mins1),len(mins2))):
            if mins1[i] > mins2[i]:
                return 1
            elif mins1[i] < mins2[i]:
                return -1
        return 0

        '''smaller_count1 = min(counts1.values()) if len(counts1.values()) > 0 else 0
        smaller_count2 = min(counts2.values()) if len(counts2.values()) > 0 else 0
        if smaller_count1 >= smaller_count2:
            return 1
        elif smaller_count1 == smaller_count2:
            return 0
        else:
            return -1'''
    else:
        return -1

def anno_segment_bigger(segment1, segment2):
    comparison = anno_segment_compare(segment1, segment2)
    if comparison == 1:
        return True
    else:
        return False

def print_segment(segment):
    seq_name, start, end, counts = segment
    print(seq_name+"["+str(start)+":"+str(end)+"] = "
        + ";".join([str(key)+"="+str(val) for key, val in counts.items()]))

def segment_to_seq(all_seqs, segment):
    seq_name, start, end, counts = segment
    if seq_name in all_seqs:
        seq = all_seqs[seq_name][start:end]
        return seq_name, seq
    else:
        return seq_name, None

def get_segment(annotations, seq_name, start, window):
    end = start+window
    segment_annos = annotations[(annotations['start'] >= start) & (annotations['end'] <= end)]
    counts = {source: len(annos) for source, annos in segment_annos.groupby(['source'])}
    return seq_name, start, end, counts

def get_gff_attributes(attrs):
    try:
        parts = attrs.split(";")
    except:
        print("Could not split the following attributes:")
        print(str(attrs))
        raise ValueError("Attribute spliting error")
    last_named_part = 0
    for i in range(1,len(parts)):
        if "=" in parts[i]:
            last_named_part = i
        else:
            parts[last_named_part] += ";"+parts[i]
            parts[i] = ""
    values = {}
    for part in parts:
        if len(part) > 0:
            ab = part.split("=")
            if len(ab) == 2:
                name = ab[0]
                val = ab[1].lstrip("'").rstrip("'")
                values[name] = val
    return values

def get_gff_attributes_str(attrs):
    x = ""
    for key in attrs.keys():
        value = attrs[key]
        x += key+"="+value+";"
    x = x.rstrip(";")
    return x

def read_gff(gff_path, feature = "transcript", get_types = True):
    print("Loading " + gff_path)
    df = pd.read_csv(gff_path, sep="\t", header=None,
        names = ["seqname", "source", "feature", "start", "end",
        "score", "strand", "frame", "attribute"])
    #print("\tFiltering features")
    df = df[df["feature"] == feature]
    #print("\tUpdating attributes")
    if get_types:
        #df["attribute"] = df.apply(lambda row: row["attribute"], axis=1)
        df["rna_type"]  = df.apply(
                            lambda row: get_gff_attributes(row["attribute"])["type"],
                            axis = 1)
        df["ID"]  = df.apply(lambda row: get_gff_attributes(row["attribute"])["ID"],
                            axis = 1)
    chr_groups = {name: annos.sort_values(by=['start', 'end']) for name, annos in df.groupby(["seqname"])}
    return chr_groups

def get_ids_from_segments(segments, source_name, annotations):
    ids = set()
    for seg in segments:
        seq_name, start, end, counts = seg
        if source_name in counts:
            if seq_name in annotations:
                annos = annotations[seq_name]
                source_annos = annos[annos['source'] == source_name]
                selected_ann = source_annos[(source_annos['start'] >= start) & (source_annos['end'] <= end)]
                ids_selected = selected_ann['ID'].tolist()
                ids.update(ids_selected)
    return ids

def get_best_segment(seq_name, annotations, step, window):
    current_start = 0
    end = max(annotations['end'].tolist())
    max_iters = end/step
    #progress_bar = tqdm(total=max_iters)
    best_segment = get_segment(annotations, seq_name, current_start, window)
    current_start += step
    #progress_bar.update(1)
    while current_start+window <= end:
        segment = get_segment(annotations, seq_name, current_start, window)
        if anno_segment_bigger(segment, best_segment):
            best_segment = segment
            #print_segment(best_segment)
        current_start += step
        #progress_bar.update(1)
    #progress_bar.close()
    return best_segment

def sliceString(string, max_len):
    slices = []
    for x in range(0,int(len(string)/max_len)+1):
            slices.append(string[x*max_len:(x+1)*max_len])
    return slices

def seqListToDict(seqs):
    x = {}
    for pair in seqs:
        key = pair[0].rstrip("\n").lstrip(">")
        val = pair[1]
        x[key] = val
    return x

def shortFastaHeader(seq):
    name = seq[0].split("|")[0]
    name = name.split(" ")[0]
    return (name,seq[1])

def writeFastaSeqs(validSeqs, output_fasta, lineWidth = 60):
    seqs = list()
    for pair in validSeqs:
        header = pair[0]
        if header[-1] != '\n':
            header += "\n"
        if header[0] != '>':
            header = ">" + header
        seq = pair[1]
        slices = sliceString(seq.replace('\n', '').replace('\r', ''), lineWidth)
        contig = ""
        for i in range(0,len(slices)):
            contig += slices[i] + "\n"
        contig += "\n"
        seqs.append((header,contig))

    with open(output_fasta, "w") as fasta:
        for pair in seqs:
            fasta.write(pair[0])
            fasta.write(pair[1])

def readSeqsFromFasta(input_fasta):
    seqs = dict()
    with open(input_fasta, "r") as fasta:
        contigName = ""
        seq = ""
        lines = fasta.readlines()
        for line in lines:
            if len(line) > 0:
                if line[0] == '>':
                    if len(seq) > 0:
                        seq = seq.replace("\n","")
                        contigName = contigName.replace("\n","").replace(">","").split()[0]
                        #print("loaded " + contigName)
                        seqs[contigName] = seq
                    contigName = line
                    seq = ""
                else:
                    if len(seq) > 0:
                        seq += "\n"
                    seq += line.rstrip("\n").lstrip("\n")
        seq = seq.replace("\n","")
        contigName = contigName.replace("\n","").replace(">","").split()[0]
        #print("loaded " + contigName)
        seqs[contigName] = seq
    return seqs

def readSeqsFromFasta_list(input_fasta):
    seqs = list()
    with open(input_fasta, "r") as fasta:
        contigName = ""
        seq = ""
        lines = fasta.readlines()
        for line in lines:
            if len(line) > 0:
                if line[0] == '>':
                    if len(seq) > 0:
                        seq = seq.replace("\n","")
                        contigName = contigName.replace("\n","").replace(">","").split()[0]
                        seqs.append((contigName, seq))
                    contigName = line
                    seq = ""
                else:
                    if len(seq) > 0:
                        seq += "\n"
                    seq += line.rstrip("\n").lstrip("\n")
        seq = seq.replace("\n","")
        contigName = contigName.replace("\n","").replace(">","").split()[0]
        seqs.append((contigName,seq))
    return seqs

def filterSeqs(seqs, ids):
    lower_ids = set()
    for i in ids:
        lower_ids.add(i.lower())
    ids = lower_ids
    validSeqs = list()
    invalidSeqs = list()
    for header, seq in tqdm(seqs):
        h = header.lower()
        h = h.lstrip(">").rstrip("\n").split(" ")[0].split("|")[0]
        valid = False
        for a in ids:
            if a in h:
                valid = True
        if not valid:
            valid = ((h in ids)
                or (h.rstrip("\n") in ids)
                or (header.lower() in ids))
        if valid:
            validSeqs.append((header, seq))
        else:
            invalidSeqs.append((header, seq))
    return validSeqs, invalidSeqs

def filter_fasta(valid_ids, fasta_path, output_path):
    seqs = readSeqsFromFasta_list(fasta_path)
    valid, invalid = filterSeqs(seqs, valid_ids)
    writeFastaSeqs(valid, output_path)

def filter_gff(valid_ids, gff_path, output_path):
    with open(output_path, 'w') as out_stream:
        with open(gff_path, 'r') as in_stream:
            for line in in_stream:
                last_cell = line.rstrip("\n").split("\t")[-1]
                found = False
                for a in valid_ids:
                    if a in last_cell:
                        found = True
                if found:
                    out_stream.write(line)

annotation_path = sys.argv[1]
genome_path = sys.argv[2]
transcripts_fasta_path = sys.argv[3]
reference_fasta_path = sys.argv[4]
db_fasta_path = sys.argv[5]
reference_gff_path = sys.argv[6]
step = 100000
window = 7000000
contigs_to_get = 3
output = sys.argv[7]

gff_data = read_gff(annotation_path)

segments = []
import functools
for chr_name, annotations in tqdm(gff_data.items()):
    new_segment = get_best_segment(chr_name, annotations, step, window)
    segments.append(new_segment)
    segments.sort(key=functools.cmp_to_key(anno_segment_compare), reverse=True)

best_segments = segments[:contigs_to_get]
for segment in best_segments:
    print_segment(segment)

rnasamba_ids = get_ids_from_segments(best_segments,
    "rnasamba", gff_data)
reference_mapping_ids = get_ids_from_segments(best_segments,
    "reference_mapping", gff_data)
db_alignment_ids = get_ids_from_segments(best_segments,
    "db_alignment", gff_data)
reference_ids = get_ids_from_segments(best_segments,
    "reference", gff_data)

print(rnasamba_ids)
filter_fasta([".".join(x.split(".")[:-1]) for x in rnasamba_ids],
            transcripts_fasta_path, output+"-transcripts.fasta")
print(reference_mapping_ids)
filter_fasta([".".join(x.split(".")[:-1]) for x in reference_mapping_ids],
            reference_fasta_path, output+"-reference.fasta")
print(db_alignment_ids)
filter_fasta([".".join(x.split(".")[:-1]) for x in db_alignment_ids],
            db_fasta_path, output+"-db.fasta")
print(reference_ids)
filter_gff([".".join(x.split(".")[:-1]) for x in reference_ids],
            reference_gff_path, output+"-reference.gff")

print("Loading genome")
all_seqs = readSeqsFromFasta(genome_path)
seqs = {}
for segment in best_segments:
    seq_name, seq = segment_to_seq(all_seqs, segment)
    if seq != None:
        seqs[seq_name] = seq
        print_segment(segment)
    else:
        print(seq_name + " not found in genome.")
with open(output + "-genome.fasta", 'w') as stream:
    for seq_name, seq in seqs.items():
        stream.write(">"+seq_name+"\n"+seq+"\n")


from gpiozero import Buzzer, LED, TrafficLights
from time import sleep

buzzer = Buzzer(15)
lights = TrafficLights(25, 8, 21)
red, yellow, green = lights.red, lights.yellow, lights.green
left = LED(13)
right = LED(14)

def toggle(components, time):
    for component in components:
        on(component)
    sleep(time)
    for component in components:
        off(component)

def on(component):
    component.on()

def off(component):
    component.off()

def blink(led: LED):
    for _ in range(5):
        toggle((led, buzzer), 1)
        sleep(1)

def loop():
    while True:
        print("Green on for 5 seconds")
        toggle([green], 5)
        print("Blinking yellow with buzzer 5 times in 10 seconds")
        blink(yellow)
        print("Red on for 5 seconds")
        blink(red, 4)
        print("Buzzer on for 1 second")
        toggle([red, buzzer], 1)
        sleep(1)

try:
    print("Starting loop")
    loop()
except KeyboardInterrupt:
    print("KeyboardInterrupt - exiting")
    lights.close()
    buzzer.close()


import nltk,score,math,preprosess
'''

    ##semantic analysis
        i) strip suffix from each sentence(lightweight stemming)
        ii)find similarity
        iii)if similar remove low scored
    '''
#suffix striping:::::
def suffixSt(word):
    # suffix dictionary
    suffix = {
        1: [u"ি", u"ই", u"আ", u"ো", u"া", u"ঈ", u"ই", u"অ", u"ও", u"এ",
            u"র", u"য়", u"ব", u"স", u" ঊ", u"ু", u"ো", u"ে", u"ী", u"য়", u"ক", "য়", "ল", "ছ", "ব"],
        2: [u"য়ে", u"না", u"লি", u"নি", u"না", u"য়া", u"ায়", u"ড়ি", u"িস", u"ান", u"ের", u"ার", u"ান", u"কু", u"কা",
            u"বি",
            u"তে", u"রা", u"বে", u"মি",
            u"সি", u" আল", u" উক", u"ড়ে", u"কে", u"টা", u"টি", u"টু", u"কা", u" রি", u"তি", " তা", "িল", "িক", "েক",
            "েত", "েই", "আও", "আন", " আত", " আই", " অন", " অত", " অক", "ড়ে", "ড়ি", "ড়া", "সে", "সা", "লা", "মি",
            "ভর", "নি", "তি", "তা", "টে", "টা", "চে", "কে", "কা", "এল", "উড়", "উক", "আল", "আর", "আম", "আত", "আচ", "আই",
            "অড়", "অল", "তো",
            "েছ", "েল", "ছে","েও"],
        3: ["ওয়া", " উরি", "উয়া", "উনি", "উকা", u"দের", "য়ের", "কায়", "কার", "েরা",
            "িলা", "িনি", "তেই", "টাই", "ইয়ে", " ইয়া", " ইলে", " আরী", " আরি", u"আনো", " আনি", " আকু", " আইত",
            " অন্ত", " অনি", " অনা", " অতি", " অতা", " োয়া", "ুয়া", "ুন্তি", "ুনি", "ুকা", "ুকা", "সিয়", "মন্ত", "ভরা",
            "য়োন", "খান", "গুল", "পনা", "তুত", "উয়া", "উলি", "উরে", "ইয়া", "আলো", "আলি", "আলা", "আরু", "আরি", "আমো",
            "আমি",
            "আনো", "আনি", "আচি", "আইত",
            "চ্ছ", "েছে", "েলো", "ওয়া", "মান"],
        4: [u"েদের", " অন্তি", "টিয়া", "কিয়া", " উন্তি", u"য়েরা", u"ভাবে", "খানা", "খানি", "গুলো", "গুলি", "পারা",
            "পানো",
            "ইয়াল", "য়েছে", "চ্ছি", "চ্ছে", "েছেন"],
        5: [u"দেরকে", "চ্ছিল", "চ্ছিস", u"য়েদের", "ওয়ালা", "উড়িয়া"],
        6: [u"েদেরকে", "চ্ছিলেন"],
        7: [u"য়েদেরকে"]
    }
    for w in 7, 6, 5, 4, 3, 2, 1:
        if len(word) > w + 1:
            for s in suffix[w]:
                if word.endswith(s):
                    return word[:-w]
    return word

#make one sent list:::::
def makeList(sent):
    tok=nltk.word_tokenize(sent)
    li=[]
    for w in tok:
        li.append(suffixSt(w))
    return li

#making total list:::::::
def makeTolist(allsent):
    lst=[]
    for sen in allsent:
        lst.append(makeList(sen))
    return lst

##Get cosine
def get_cosine(vec1, vec2):
    #here A n B
    intersection = set(vec1.keys()) & set(vec2.keys())
    #dot product of teo sentence
    numerator = sum([vec1[x] * vec2[x] for x in intersection])

    sum1 = sum([vec1[x] ** 2 for x in vec1.keys()])
    sum2 = sum([vec2[x] ** 2 for x in vec2.keys()])

    denominator = math.sqrt(sum1) * math.sqrt(sum2)
    #avoid null space vectors
    if not denominator:
        return 0.0
    else:
        return float(numerator) / denominator

#cosine similarity check for all passage
"""
check all sentence 2d  matrix  form

"""
def getCoVal(allItm,priSum):
    n=len(allItm)
   # print(allItm)
    cos=[]
    algn1=[]
    algn2=[]
    cos.append(" "+priSum[0])
    for i in range(0,n):
        for j in range(i+1,n):
            vec1=score.scoreWord(allItm[i])
            vec2=score.scoreWord(allItm[j])
            cosi=get_cosine(vec1,vec2)
            #sentences set gen exceptin 95% simalarity sentence
            if cosi<0.95 and priSum[j] not in cos:
                cos.append(priSum[j])
    return cos

'''

'''
def finalSummary(priSummary):
    stemmedList = makeTolist(priSummary)
    final = getCoVal(stemmedList, priSummary)
    finalText = " । \n".join(final) + "।"

    return finalText


import cv2
print(cv2.__version__)

dispW=640
dispH=480
flip=0 # flip because raspi cam is upside down

boxW = 120
boxH = 100
boxThickness = 10

boxX=0
boxY = 0

stageX = 1
stageY = 1

camSet='nvarguscamerasrc !  video/x-raw(memory:NVMM), width=3264, height=2464, format=NV12, framerate=21/1 ! nvvidconv flip-method='+str(flip)+' ! video/x-raw, width='+str(dispW)+', height='+str(dispH)+', format=BGRx ! videoconvert ! video/x-raw, format=BGR ! appsink'
cam=cv2.VideoCapture(camSet)
#cam=cv2.VideoCapture(1)
while True:
    ret, frame=cam.read()

    if boxX >= dispW-boxW and stageX == 1:
        stageX = 2
    if boxX <= 0 and stageX == 2:
        stageX = 1

    if boxY >= dispH-boxH and stageY == 1:
        stageY = 2
    if boxY <= 0 and stageY == 2:
        stageY = 1

    if stageX == 1:
        boxX+=5
    if stageX == 2:
        boxX-=5

    if stageY == 1:
        boxY+=5
    if stageY == 2:
        boxY-=5

    frame=cv2.rectangle(frame,(boxX,boxY),(boxX+boxW,boxY+boxH),(255,255,255),boxThickness) #add a rectangle to the frame using openCV(CV2), identify topleft and bottomright coords, choose colour (BGR), linewidth
    cv2.imshow('piCam',frame)
    cv2.moveWindow('piCam',0,0)
    if cv2.waitKey(1)==ord('q'):
        break
cam.release()
cv2.destroyAllWindows()


import requests
import argparse
import sys
import pdb

# Configure CLI argument parsing.
parser = argparse.ArgumentParser(
		description="Enumerate files & directories with the ability to exclude results based on string-matching against HTML content body."
)
parser.add_argument('-u', metavar='"https://example.com/"', type=str, required=True)
parser.add_argument('-w', metavar='"~/Wordlist.txt"', type=str, required=True)
parser.add_argument('-e', metavar='"login,sign-in"', required=False, type=str, help='Comma-separated list of strings to exclude.')
parser.add_argument('--v', required=False, action='store_true', help='Verbose output.')

# Assign arguments.
base_url = parser.parse_args().u
wordlist = parser.parse_args().w
exclusions = parser.parse_args().e
verbose = parser.parse_args().v

# Parse exclusions.
if exclusions is not None:
		if "," in exclusions:
				exclusions_list = exclusions.split(",")
		else:
				exclusions_list = [exclusions]
else:
		exclusions_list = []

# Append trailing / if not in URL.
if not base_url.endswith('/'):
	base_url = base_url + "/"

wordlist_lines = open(wordlist, encoding='latin-1').readlines()
output_file = open(f"WebFileEnum.log", 'a')

# Loop through wordlist.
for line in wordlist_lines:

	# Remove trailing newline.
	line = line.strip()

	_r = requests.get(base_url + line)

	# Continue w/ loop if an exclusion matches response body.
	is_excluded = False

	for e in exclusions_list:
		if e.lower() in _r.text.lower():
			is_excluded = True

	if is_excluded:
		if verbose: print(f"[EXCLUSION HIT] {base_url}{line}")
		continue

	# Write output to console & log if status code is anything but 404 (Not Found).
	if _r.status_code != 404:
		print(f"[{_r.status_code}] {base_url}{line}")
		output_file.write(f"[{_r.status_code}] {base_url}{line}\n")


#Question 1 -
#Description - Create a small command-line program in Python to calculate the total invoice amount for the below purchases -
#Book - Introduction to Python Programming : Rs 499.00
#Book - Python Libraries Cookbook : Rs. 855.00
#Book - Data Science in Python : Rs. 645.00
#Taxes and additional charges are described as details -
#GST : 12%
#Delivery Charges : Rs. 250.00

x=float(input("Enter no. of 'Introduction to python programming' books:"))*499
y=float(input("Enter no. of 'Python libraries Cookbook' books:"))*855
z=float(input("Enter no. of 'Data Science in Python' books:"))*645
total=x+y+z
GST=float(total*0.012)
Delivery_charges=250
Total_amount=total+GST+Delivery_charges
print(Total_amount)