import ormar
import sqlalchemy
import databases
from typing import Optional

from src.settings import DATABASE_URL

metadata = sqlalchemy.MetaData()
engine = sqlalchemy.create_engine(DATABASE_URL)
database = databases.Database(DATABASE_URL)

class User(ormar.Model):
    class Meta:
        tablename = "Users"
        metadata = metadata
        database = database

    id: int = ormar.Integer(primary_key=True)
    email: str = ormar.String(max_length=255, unique=True)
    password: str = ormar.String(max_length=255)
    phone: str = ormar.String(min_length=10, max_length=10)
    confirmed: bool = ormar.Boolean(default=False)

class UserAddress(ormar.Model):
    class Meta:
        tablename = "UserAddress"
        metadata = metadata
        database = database

    id: int = ormar.Integer(primary_key=True)
    user: User = ormar.ForeignKey(User, nullable=False)
    address: str = ormar.Text()

class Admin(ormar.Model):
    class Meta:
        tablename = "Admins"
        metadata = metadata
        database = database

    id: int = ormar.Integer(primary_key=True)
    user: User = ormar.ForeignKey(User, nullable=False)

class Product(ormar.Model):
    class Meta:
        tablename = "Products"
        metadata = metadata
        database = database

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=255, unique=True)
    description: str = ormar.Text()
    price: float = ormar.Float()
    quantity: int = ormar.Integer()

class ProductImage(ormar.Model):
    class Meta:
        tablename = "ProductImages"
        metadata = metadata
        database = database

    id: int = ormar.Integer(primary_key=True)
    product: Product = ormar.ForeignKey(Product, nullable=False)
    path: str = ormar.String(max_length=255)

class Cart(ormar.Model):
    class Meta:
        tablename = "Carts"
        metadata = metadata
        database = database

    id: int = ormar.Integer(primary_key=True)
    user: User = ormar.ForeignKey(User, nullable=False)
    product: Product = ormar.ForeignKey(Product, nullable=False)

class Category(ormar.Model):
    class Meta:
        tablename = "Categories"
        metadata = metadata
        database = database

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=10)
    categorytype: str = ormar.String(max_length=10)

class CategoryProductLink(ormar.Model):
    class Meta:
        tablename = "CategoryProductLink"
        metadata = metadata
        database = database

    id: int = ormar.Integer(primary_key=True)
    category: Category = ormar.ForeignKey(Category, nullable=False)
    product: Product = ormar.ForeignKey(Product, nullable=False)

class Order(ormar.Model):
    class Meta:
        tablename = "Orders"
        metadata = metadata
        database = database

    id: int = ormar.Integer(primary_key=True)
    product: Product = ormar.ForeignKey(Product, nullable=False)
    price: float = ormar.Float()
    quantity: int = ormar.Integer()

class Payment(ormar.Model):
    class Meta:
        tablename = "Payments"
        metadata = metadata
        database = database

    id: int = ormar.Integer(primary_key=True)
    user: User = ormar.ForeignKey(User, nullable=False)
    order: Order = ormar.ForeignKey(Order, nullable=False)

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=255, unique=True)
    description: str = ormar.Text()
    price: float = ormar.Float()
    quantity: int = ormar.Integer()

metadata.create_all(engine)


import dataclasses
import re
from dataclasses import dataclass
from functools import partial
from types import TracebackType
from typing import (
    Any,
    Callable,
    Dict,
    Iterator,
    List,
    Optional,
    Pattern,
    Tuple,
    Type,
    Union,
)

import torch.utils.hooks
from torch import Tensor, nn

@dataclass
class Event:
    name: str
    type: Type[nn.Module]
    grad: bool
    value: Any
    args: Tuple[Any, ...]
    kwargs: Dict[str, Any]

@dataclass
class Stash:
    name: str
    type: Type[nn.Module]
    grad: bool
    value: Any  # output(s) or grad_output(s)

    @property
    def first_value(self) -> Any:
        def _value(v: Any) -> Any:
            if isinstance(v, (tuple, list)) and len(v) >= 1:
                return _value(v[0])
            return v

        return _value(self.value)

StashFn = Callable[[Event], Stash]
StashValueFn = Callable[[Tensor], Any]

def rmap_tensor(value: Any, fn: Callable[[Tensor], Any]) -> Any:
    if isinstance(value, (tuple, list)):
        return type(value)(rmap_tensor(a, fn) for a in value)
    if isinstance(value, dict):
        return {rmap_tensor(k, fn): rmap_tensor(a, fn) for k, a in value.items()}
    if dataclasses.is_dataclass(value):
        return type(value)(**{k: rmap_tensor(v, fn) for k, v in value.__dict__.items()})
    if isinstance(value, Tensor):
        return fn(value)
    return value

def default_stash_value(tensor: Tensor) -> Tensor:
    return tensor.detach().cpu().clone()

def default_stash(event: Event, stash_value: StashValueFn) -> Stash:
    return Stash(
        event.name, event.type, event.grad, rmap_tensor(event.value, stash_value)
    )

def get_stash_fn(
    stash_value: Optional[StashValueFn] = None, stash: Optional[StashFn] = None
) -> StashFn:
    if stash_value and stash:
        raise ValueError("Cannot provide StashValueFn and StashFn to get_stash_fn()")
    if stash:
        return stash
    return partial(default_stash, stash_value=stash_value or default_stash_value)

NamePattern = Union[None, Pattern[str], str]

class Tracker:
    def __init__(self, stash: StashFn):
        self.stashes: List[Stash] = []
        self._handles: List[torch.utils.hooks.RemovableHandle] = []
        self._stash = stash

    # Registration/tracking

    def __enter__(self) -> "Tracker":
        return self

    def __exit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc: Optional[BaseException],
        traceback: Optional[TracebackType],
    ) -> None:
        self.unregister()

    def clear(self) -> None:
        self.stashes.clear()

    def register(self, module: nn.Module, name: str = "", grad: bool = True) -> None:
        self._handles.append(
            module.register_forward_hook(
                partial(self._forward_hook, name=name), with_kwargs=True
            )
        )
        if grad:
            self._handles.append(
                module.register_full_backward_pre_hook(
                    partial(self._backward_hook, name=name)
                )
            )

    def register_all(
        self,
        module: nn.Module,
        grad: bool = True,
        include: NamePattern = None,
        exclude: NamePattern = None,
    ) -> None:
        include = re.compile(include) if isinstance(include, str) else include
        exclude = re.compile(exclude) if isinstance(exclude, str) else exclude
        for name, child in module.named_modules():
            if ((not include) or include.search(name)) and not (
                exclude and exclude.search(name)
            ):
                self.register(child, name, grad=grad)

    def unregister(self) -> None:
        for handle in self._handles:
            handle.remove()
        self._handles.clear()

    def _forward_hook(
        self,
        module: nn.Module,
        args: Tuple[Any],
        kwargs: Dict[str, Any],
        output: Any,
        *,
        name: str,
    ) -> None:
        self.stashes.append(
            self._stash(Event(name, type(module), False, output, args, kwargs))
        )

    def _backward_hook(self, module: nn.Module, grad_output: Any, *, name: str) -> None:
        self.stashes.append(
            self._stash(Event(name, type(module), True, grad_output, (), {}))
        )

    # Read results

    def __str__(self) -> str:
        return f"Tracker(stashes={len(self)}, tracking={len(self._handles)})"

    def __iter__(self) -> Iterator[Stash]:
        return iter(self.stashes)

    def __getitem__(self, index: int) -> Stash:
        return self.stashes[index]

    def __len__(self) -> int:
        return len(self.stashes)

    def to_frame(
        self,
        stat: Callable[[Tensor], Tensor] = torch.std,
        stat_name: Optional[str] = None,
    ) -> "pandas.DataFrame":  # type:ignore[name-defined] # NOQA: F821
        import pandas

        column_name = (
            getattr(stat, "__name__", "value") if stat_name is None else stat_name
        )

        def to_item(stash: Stash) -> Dict[str, Any]:
            d = stash.__dict__.copy()
            d.pop("value")
            v = stash.first_value
            d[column_name] = stat(v).item() if isinstance(v, Tensor) else None
            d["type"] = f"{stash.type.__module__}.{stash.type.__name__}"
            return d

        return pandas.DataFrame.from_dict(map(to_item, self))  # type:ignore[arg-type]

def track(
    module: nn.Module,
    grad: bool = True,
    include: NamePattern = None,
    exclude: NamePattern = None,
    stash_value: Optional[StashValueFn] = None,
    stash: Optional[StashFn] = None,
) -> Tracker:
    tracker = Tracker(get_stash_fn(stash_value=stash_value, stash=stash))
    tracker.register_all(module, grad=grad, include=include, exclude=exclude)
    return tracker

track.__doc__ = __doc__

__all__ = [
    "Event",
    "Stash",
    "StashFn",
    "StashValueFn",
    "rmap_tensor",
    "default_stash_value",
    "default_stash",
    "get_stash_fn",
    "Tracker",
    "track",
]


import sys
import logging
from pathlib import Path

try:
    import argcomplete
except ImportError:
    # We can live without argcomplete, we only lose tab completions.
    argcomplete = None

from pepclibs.helperlibs import Logging, ArgParse
from pepclibs.helperlibs.Exceptions import Error
from wultlibs.deploylibs import _Deploy
from wulttools import _Common
from wulttools.wult import _WultCommon, ToolInfo

VERSION = ToolInfo.VERSION
TOOLNAME = ToolInfo.TOOLNAME

# The deployment information dictionary. See 'DeployBase.__init__()' for details.
_WULT_DEPLOY_INFO = {
    "installables" : {
        "wult" : {
            "category" : "drivers",
            "minkver"  : "5.6",
            "deployables" : ("wult", "wult_igb", "wult_tdt", "wult_hrt", ),
        },
        "wult-hrt-helper" : {
            "category" : "bpfhelpers",
            "minkver"  : "5.15",
            "deployables" : ("wult-hrt-helper", ),
        },
        "wult-tdt-helper" : {
            "category" : "bpfhelpers",
            "minkver"  : "5.15",
            "deployables" : ("wult-tdt-helper", ),
        },
    },
}

_LOG = logging.getLogger()
Logging.setup_logger(prefix=TOOLNAME)

def _build_arguments_parser():
    """Build and return the arguments parser object."""

    text = f"{TOOLNAME} - a tool for measuring C-state latency."
    parser = ArgParse.SSHOptsAwareArgsParser(description=text, prog=TOOLNAME, ver=VERSION)

    text = "Force coloring of the text output."
    parser.add_argument("--force-color", action="store_true", help=text)
    subparsers = parser.add_subparsers(title="commands", dest="a command")
    subparsers.required = True

    #
    # Create parsers for the "deploy" command.
    #
    subpars = _Deploy.add_deploy_cmdline_args(TOOLNAME, _WULT_DEPLOY_INFO, subparsers,
                                              _deploy_command, argcomplete=argcomplete)
    text = """Deploy the eBPF helper, but do not deploy the drivers. This is a debug and development
              option, do not use it for other purposes."""
    subpars.add_argument("--skip-drivers", action="store_true", help=text)

    #
    # Create parsers for the "scan" command.
    #
    text = "Scan for available devices."
    descr = """Scan for available devices."""
    subpars = subparsers.add_parser("scan", help=text, description=descr)
    subpars.set_defaults(func=_Common.scan_command)
    subpars.add_argument("--all", action="store_true",
                         help=_Common.get_scan_all_descr(TOOLNAME))

    ArgParse.add_ssh_options(subpars)

    #
    # Create parsers for the "start" command.
    #
    text = "Start the measurements."
    descr = """Start measuring and recording C-state latency."""
    subpars = subparsers.add_parser("start", help=text, description=descr)
    subpars.set_defaults(func=_start_command)

    ArgParse.add_ssh_options(subpars)

    subpars.add_argument("-c", "--datapoints", default=1000000, metavar="COUNT", dest="dpcnt",
                         help=_Common.DATAPOINTS_DESCR)
    subpars.add_argument("--time-limit", dest="tlimit", metavar="LIMIT",
                         help=_Common.TIME_LIMIT_DESCR)
    subpars.add_argument("--exclude", action=ArgParse.OrderedArg,
                         help=_Common.EXCL_START_DESCR)
    subpars.add_argument("--include", action=ArgParse.OrderedArg, help=_Common.INCL_DESCR)
    text = f"""{_Common.KEEP_FILTERED_DESCR} Here is an example. Suppose you want to collect
               100000 datapoints where PC6 residency is greater than 0. In this case, you can use
               these options: -c 100000 --exclude="PC6%% == 0". The result will contain 100000
               datapoints, all of them will have non-zero PC6 residency. But what if you do not want
               to simply discard the other datapoints, because they are also interesting? Well, add
               the '--keep-filtered' option. The result will contain, say, 150000 datapoints, 100000
               of which will have non-zero PC6 residency."""
    subpars.add_argument("--keep-filtered", action="store_true", help=text)

    arg = subpars.add_argument("-o", "--outdir", type=Path, help=_Common.START_OUTDIR_DESCR)
    if argcomplete:
        arg.completer = argcomplete.completers.DirectoriesCompleter()

    subpars.add_argument("--reportid", help=_Common.START_REPORTID_DESCR)

    subpars.add_argument("--stats", default="default", help=_Common.STATS_DESCR)

    subpars.add_argument("--stats-intervals", help=_Common.STAT_INTERVALS_DESCR)

    subpars.add_argument("--list-stats", action="store_true",
                         help=_Common.LIST_STATS_DESCR % TOOLNAME)

    text = f"""This tool works by scheduling a delayed event, then sleeping and waiting for it to
               happen. This step is referred to as a "measurement cycle" and it is usually repeated
               many times. The launch distance defines how far in the future the delayed event is
               scheduled. By default this tool randomly selects launch distance within a range. The
               default range is [0,4ms], but you can override it with this option. Specify a
               comma-separated range (e.g '--ldist 10,5000'), or a single value if you want launch
               distance to be precisely that value all the time.  The default unit is microseconds,
               but you can use the following specifiers as well: {_Common.DURATION_NS_SPECS_DESCR}.
               For example, '--ldist 10us,5ms' would be a [10,5000] microseconds range. Too small
               values may cause failures or prevent the SUT from reaching deep C-states. If the
               range starts with 0, the minimum possible launch distance value allowed by the
               delayed event source will be used. The optimal launch distance range is
               system-specific."""
    subpars.add_argument("-l", "--ldist", help=text, default="0,4000")

    text = """The logical CPU number to measure, default is CPU 0."""
    subpars.add_argument("--cpunum", help=text, type=int, default=0)

    text = f"""{TOOLNAME.title()} receives raw datapoints from the driver, then processes them, and
               then saves the processed datapoint in the 'datapoints.csv' file. The processing
               involves converting TSC cycles to microseconds, so {TOOLNAME} needs SUT's TSC rate.
               TSC rate is calculated from the datapoints, which come with TSC counters and
               timestamps, so TSC rate can be calculated as "delta TSC / delta timestamp". In other
               words, {TOOLNAME} needs two datapoints to calculate TSC rate. However, the datapoints
               have to be far enough apart, and this option defines the distance between the
               datapoints (in seconds). The default distance is 10 seconds, which means that
               {TOOLNAME} will keep collecting and buffering datapoints for 10s without processing
               them (because processing requires TSC rate to be known). After 10s, {TOOLNAME} will
               start processing all the buffered datapoints, and then the newly collected
               datapoints. Generally, longer TSC calculation time translates to better accuracy."""
    subpars.add_argument("--tsc-cal-time", default="10s", help=text)

    text = f"""{TOOLNAME.title()} receives raw datapoints from the driver, then processes them, and
               then saves the processed datapoint in the 'datapoints.csv' file. In order to keep the
               CSV file smaller, {TOOLNAME} keeps only the essential information, and drops the rest.
               For example, raw timestamps are dropped. With this option, however, {TOOLNAME} saves
               all the raw data to the CSV file, along with the processed data."""
    subpars.add_argument("--keep-raw-data", action="store_true", dest="keep_rawdp", help=text)

    text = f"""This option exists for debugging and troubleshooting purposes. Please, do not use
               for other reasons. If {TOOLNAME} loads kernel modules, they get unloaded after the
               measurements are done. But with this option {TOOLNAME} will not unload the
               modules."""
    subpars.add_argument("--no-unload", action="store_true", help=text)

    subpars.add_argument("--report", action="store_true", help=_Common.START_REPORT_DESCR)
    subpars.add_argument("--force", action="store_true", help=_Common.START_FORCE_DESCR)

    text = """The ID of the device to use for measuring the latency. For example, it can be a PCI
              address of the Intel I210 device, or "tdt" for the TSC deadline timer block of the
              CPU. Use the 'scan' command to get supported devices."""
    subpars.add_argument("devid", nargs= '?' if '--list-stats' in sys.argv else None, help=text)

    #
    # Create parsers for the "report" command.
    #
    text = "Create an HTML report."
    descr = """Create an HTML report for one or multiple test results."""
    subpars = subparsers.add_parser("report", help=text, description=descr)
    subpars.set_defaults(func=_report_command)

    subpars.add_argument("-o", "--outdir", type=Path,
                         help=_Common.get_report_outdir_descr(TOOLNAME))
    subpars.add_argument("--exclude", action=ArgParse.OrderedArg, help=_Common.EXCL_DESCR)
    subpars.add_argument("--include", action=ArgParse.OrderedArg, help=_Common.INCL_DESCR)
    subpars.add_argument("--even-up-dp-count", action="store_true", dest="even_dpcnt",
                         help=_Common.EVEN_UP_DP_DESCR)

    # Format axes options' help texts with default axes.
    xaxes_help = _Common.XAXES_DESCR % _WultCommon.get_axes("xaxes", escape_percent=True)
    yaxes_help = _Common.YAXES_DESCR % _WultCommon.get_axes("yaxes", escape_percent=True)
    hist_help = _Common.HIST_DESCR % _WultCommon.get_axes("hist", escape_percent=True)
    chist_help = _Common.CHIST_DESCR % _WultCommon.get_axes("chist", escape_percent=True)
    subpars.add_argument("-x", "--xaxes", help=xaxes_help)
    subpars.add_argument("-y", "--yaxes", help=yaxes_help)
    subpars.add_argument("--hist", help=hist_help)
    subpars.add_argument("--chist", help=chist_help)

    subpars.add_argument("--reportids", help=_Common.REPORTIDS_DESCR)
    subpars.add_argument("--report-descr", help=_Common.REPORT_DESCR)
    subpars.add_argument("--relocatable", action="store_true", help=_Common.RELOCATABLE_DESCR)
    subpars.add_argument("--list-metrics", action="store_true",
                         help=_Common.LIST_METRICS_DESCR)

    text = """Generate HTML report with a pre-defined set of diagrams and histograms. Possible
              values: 'small' or 'large'. This option is mutually exclusive with '--xaxes',
              '--yaxes', '--hist', '--chist'."""
    subpars.add_argument("--size", dest="report_size", type=str, help=text)

    text = f"""One or multiple {TOOLNAME} test result paths."""
    subpars.add_argument("respaths", nargs="+", type=Path, help=text)

    #
    # Create parsers for the "filter" command.
    #
    text = "Filter datapoints out of a test result."
    subpars = subparsers.add_parser("filter", help=text, description=_Common.FILT_DESCR)
    subpars.set_defaults(func=_Common.filter_command)

    subpars.add_argument("--exclude", action=ArgParse.OrderedArg, help=_Common.EXCL_DESCR)
    subpars.add_argument("--include", action=ArgParse.OrderedArg, help=_Common.INCL_DESCR)
    subpars.add_argument("--exclude-metrics", action=ArgParse.OrderedArg, dest="mexclude",
                         help=_Common.MEXCLUDE_DESCR)
    subpars.add_argument("--include-metrics", action=ArgParse.OrderedArg, dest="minclude",
                         help=_Common.MINCLUDE_DESCR)
    subpars.add_argument("--human-readable", action="store_true",
                         help=_Common.FILTER_HUMAN_DESCR)
    subpars.add_argument("-o", "--outdir", type=Path, help=_Common.FILTER_OUTDIR_DESCR)
    subpars.add_argument("--list-metrics", action="store_true",
                         help=_Common.LIST_METRICS_DESCR)
    subpars.add_argument("--reportid", help=_Common.FILTER_REPORTID_DESCR)

    text = f"The {TOOLNAME} test result path to filter."
    subpars.add_argument("respath", type=Path, help=text)

    #
    # Create parsers for the "calc" command.
    #
    text = f"Calculate summary functions for a {TOOLNAME} test result."
    descr = f"""Calculates various summary functions for a {TOOLNAME} test result (e.g., the median
                value for one of the CSV columns)."""
    subpars = subparsers.add_parser("calc", help=text, description=descr)
    subpars.set_defaults(func=_Common.calc_command)

    subpars.add_argument("--exclude", action=ArgParse.OrderedArg, help=_Common.EXCL_DESCR)
    subpars.add_argument("--include", action=ArgParse.OrderedArg, help=_Common.INCL_DESCR)
    subpars.add_argument("--exclude-metrics", action=ArgParse.OrderedArg, dest="mexclude",
                         help=_Common.MEXCLUDE_DESCR)
    subpars.add_argument("--include-metrics", action=ArgParse.OrderedArg, dest="minclude",
                         help=_Common.MINCLUDE_DESCR)
    subpars.add_argument("-f", "--funcs", help=_Common.FUNCS_DESCR)
    subpars.add_argument("--list-funcs", action="store_true", help=_Common.LIST_FUNCS_DESCR)
    subpars.add_argument("--list-metrics", action="store_true", help=_Common.LIST_METRICS_DESCR)

    text = f"""The {TOOLNAME} test result path to calculate summary functions for."""
    subpars.add_argument("respath", type=Path, help=text, nargs='?')

    if argcomplete:
        argcomplete.autocomplete(parser)

    return parser

def parse_arguments():
    """Parse input arguments."""

    parser = _build_arguments_parser()

    args = parser.parse_args()
    args.toolname = TOOLNAME
    args.toolver = VERSION
    args.deploy_info = _WULT_DEPLOY_INFO

    return args

def _deploy_command(args):
    """Implements the 'wult deploy' command."""

    from wulttools.wult import _WultDeploy # pylint: disable=import-outside-toplevel

    if args.skip_drivers:
        del args.deploy_info["installables"]["wult"]

    _WultDeploy.deploy_command(args)

def _start_command(args):
    """Implements the 'wult start' command."""

    from wulttools.wult import _WultStart # pylint: disable=import-outside-toplevel

    _WultStart.start_command(args)

def _report_command(args):
    """Implements the 'wult report' command."""

    from wulttools.wult import _WultReport # pylint: disable=import-outside-toplevel

    _WultReport.report_command(args)

def main():
    """Script entry point."""

    try:
        args = parse_arguments()

        if not getattr(args, "func", None):
            _LOG.error("please, run '%s -h' for help.", TOOLNAME)
            return -1

        args.func(args)
    except KeyboardInterrupt:
        _LOG.info("Interrupted, exiting")
        return -1
    except Error as err:
        _LOG.error_out(err)

    return 0

# The script entry point.
if __name__ == "__main__":
    sys.exit(main())


'''A collection of numpy-based tools and statistical measures.'''
from numpy import *
from scipy.stats import gaussian_kde
from scipy.optimize import minimize_scalar

def between(x, l, h, inc=0):
   '''Return boolean array of values between bounds.

   Args:
      x (array):  array to work on
      l (float):  lower bound
      h (float):  upper bound
      inc (bool):  Inclusive bounds?

   Returns:
      boolean array with same shape as x
   '''

   if inc: return greater_equal(x,l)*less_equal(x,h)
   else: return greater(x,l)*less(x,h)

def getsqrt(x,rep=0):
   '''Compute square root, replacing invalid results.

   Args:
      x (array):  array to work on
      rep (float):  value to fill for invalid results

   Returns:
      sqrt(x):  array with same shape as x
   '''
   y = less_equal(x,0)
   y2 = isfinite(x)
   y = logical_and(y,y2)
   z = multiply(x,logical_not(y))
   return sqrt(z)+rep*y

def extrema(x):
   '''Returns the max/min of an array'''
   return asarray([minimum.reduce(x), maximum.reduce(x)])

def divz(x,y=1,repl=0.0,out=None):
   '''compute division with replacement of bad values.

   Args:
      x (array):  numerator
      y (array):  denominator
      repl (float): value to fill for invalid results
      out (bool):  output dtype of array.

   Returns:
      array:  result of x/y with replacemnt
   '''

   if len(shape(y)) or len(shape(x)):
      if len(shape(y)): bad = equal(y,0.0)
      else: bad = ones(x.shape)*(y==0.0)
      not_bad = 1-bad
      numer = (x*not_bad)
      denom = (y+bad)
      a = (repl*bad)
      if out: a = a.astype(out)
      b = (numer/denom)
      if out: b = b.astype(out)
      c = (a + b)
      if out: c = c.astype(out)
      return c
   else:
      if y == 0: return repl
      else: return x/y

def rms( x,y=None):
   '''Compute the RMS of an array

   Args:
      x (array): array to work on
      y (float):  the average of x

   Returns:
      float:  RMS
   '''
   if len(x) > 2:
      if y == None: y=average(x)
      return sqrt(mean(power(subtract(x,y),2)))
   else: return 0.0

def getexp(x,flo=-1000,fhi=1000):
   '''Compute the exp(x) with replacement to avoid overflows

   Args:
      x (array): array to work on
      flo (float):  floor value
      fhi (float):  ceiling value

   Returns:
      array:  exp(x) with values 0 were over/underflow occurs.
   '''

   x2 = x.astype(longfloat)
   y = greater(x2,flo)*less(x2,fhi)
   y2 = isfinite(x2)
   y = logical_and(y,y2)
   g = exp(y*x2)*y
   g = where(isnan(g),0.0,g).astype(x.dtype)
   return g

def bwt( x, iter=3):
   '''Copute the bi-weight estimator.

   Args:
      x (array):  array to work on
      iter (int):  number of iterations

   Returns:
      float:  the biweight estimator
   '''

   x=asarray(x)
   ns = sqrt(len(x))
   if len(x)>0: M = median(x)
   else: M=0.0
   if len(x) <= 2:
      S = 0*M
   else:
      MAD = median(abs(x-M))
      if not MAD.any(): MAD = rms(x-M)*0.6745
      if MAD.any():
         for i in range(iter):
            u6 = divz(x-M,MAD)/6.0
            omuu62 = power(1-power(u6,2),2)
            g6 = less(abs(u6),1.0)
            M = M + add.reduce(g6*(x-M)*omuu62)/add.reduce(g6*omuu62)
            u9 = divz(x-M,MAD)/9.0
            omuu9 = 1-power(u9,2)
            omuu59 = 1-5*power(u9,2)
            g9 = less(abs(u9),1.0)
            S = ns * divz(sqrt(add.reduce(g9*power(x-M,2)*power(omuu9,4))),
                          abs(add.reduce(g9*omuu9*omuu59)))
            MAD = 0.6745*S
      else: M,S = mean(x),0.0
   return [M,S]

def mode(arr):
   '''Measure the mode of the array. The distribution is modeled by a
   kernel density estimate, which is then used to find the mode.'''

   X = arr.ravel()
   kernel = gaussian_kde(X)

   # Now minimize. As a bracket we'll go from -3*sigma to 3*sigma around
   # the median
   med = median(X)
   sig = 1.49*median(absolute(X-med))
   res = minimize_scalar(lambda x: -kernel(x)[0], bracket=[med-sig,med+sig])
   return res.x


import cv2

class VideoStream():
    def __init__(self):
        """
        Constructor that returns a video camera input.
        """
        self.video = cv2.VideoCapture(0)

    def __del__(self):
        """
        Class destructor.
        """
        self.video.release()

    def get_frame_grs(self):
        """
        Camera input for processing.
        Returns a grayscale image.
        """
        success, image = self.video.read()
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        ret, jpeg = cv2.imencode('.jpg', image)
        return jpeg.tobytes()

    def get_frame_col(self):
        """
        Camera input for processing.
        Returns a color image.
        """
        success, image = self.video.read()
        ret, jpeg = cv2.imencode('.jpg', image)
        return jpeg.tobytes()

    def detect_faces(self):
        """
        Camera input for processing.
        Returns color image with face detection.
        """
        face_cc = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
        success, image = self.video.read()
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        faces = face_cc.detectMultiScale(gray, 1.3, 5)
        font = cv2.FONT_HERSHEY_SIMPLEX
        for (x, y, w, h) in faces:
            cv2.rectangle(image, (x, y), (x + w, y + h), (180, 255, 10), 2)
            cv2.putText(image, 'Face detected!', (x + w//6, y - 15),
                        font, 0.003*w, (255, 180, 10), 2, cv2.LINE_AA)
        ret, jpeg = cv2.imencode('.jpg', image)
        return jpeg.tobytes()


import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from DOE.utils.aux_tools import corrdot

def plot_doe(plot_type=0, filename='results'):
    # ------------------------------------------------------------------------------------------------------------------
    # Read and treat data

    doe_df = pd.read_csv(f'DOE/database/{filename}.csv')

    doe_df = _filterDoe(doe_df, type=filename)
    print("Df shape: ", doe_df.shape)

    filename_to_save = filename + f'_{doe_df.shape[0]}_por_{doe_df.shape[1]}'
    # ------------------------------------------------------------------------------------------------------------------
    # Plot the correlation matrix
    sns.set(style='white', font_scale=1.4)

    if plot_type == 0:

        # Simple plot
        fig = sns.pairplot(doe_df, kind="reg", corner=True, plot_kws={'line_kws': {'color': 'red'}})
        for ax in fig.axes.flatten():
            if ax is not None:
                # rotate x axis labels
                ax.set_xlabel(ax.get_xlabel(), rotation=45)
                # rotate y axis labels
                ax.set_ylabel(ax.get_ylabel(), rotation=45)
                # set y labels alignment
                ax.yaxis.get_label().set_horizontalalignment('right')

        # for axes in fig.axes.flat:
        #     if axes is not None:
        #         axes.set_ylabel(axes.get_ylabel(), rotation=0, horizontalalignment='right')

    elif plot_type == 1:
        # Complete plot
        # based on: https://stackoverflow.com/questions/48139899/correlation-matrix-plot-with-coefficients-on-one-side-scatterplots-on-another
        fig = sns.PairGrid(doe_df, diag_sharey=False)
        fig.map_lower(sns.regplot, lowess=True, line_kws={'color': 'black'})
        fig.map_diag(sns.histplot)
        fig.map_upper(corrdot)

    # Plot window
    plt.tight_layout()
    plt.show()

    fig.savefig(f'DOE/images/{filename_to_save}.png')

def _filterDoe(doe_df, type='resultsAll'):

    default_to_drop = ['deflection_cruise_aileron', 'deflection_cruise_rudder',
                           'deflection_cruise_flap',
                           'descentTime', 'timeClimb', 'neutral_point', 'cDRunAvl', 'alphaRun',
                           'timeTakeOff', 'fuelTakeOff',
                           'cd0', 'cd1', 'cd2', 'cDRun',
                           'cgPostionable', 'mtow', 'static_margin',
                           'fuelDescent', 'fuelClimb', 'cruiseRange',
                       'allElseCgPercentFuselage', 'speedTakeOff',
                       'deflection_cruise_elevator', 'fuelTotal']

    if type == 'resultsAll':
        outputs_to_drop = default_to_drop
    elif type == 'resultsWing':
        outputs_to_drop = default_to_drop + ['aspectRatioV', 'areaV', 'taperV', 'posXV', 'fuselageLength']
    elif type == 'resultsStab':
        outputs_to_drop = default_to_drop + ['aspectRatio', 'wingSecPercentage', 'wingArea', 'taperRatio1',
                                             'taperRatio2', 'fuselageLength']
    elif type == 'resultsFuselage':
        outputs_to_drop = default_to_drop + ['aspectRatio', 'wingSecPercentage', 'wingArea', 'taperRatio1',
                                             'taperRatio2', 'aspectRatioV', 'areaV', 'taperV', 'posXV']

    doe_df = doe_df.drop(columns=outputs_to_drop)

    renameColumns = {
        'aspectRatio': 'Alongamento',
        'wingSecPercentage': 'Divisão painel',
        'wingArea': 'Área Asa ($m^2$)',
        'taperRatio1': 'Afilamento primeira seção',
        'taperRatio2': 'Afilamento segunda seção',
        'aspectRatioV': 'Alongamento empenagem',
        'areaV': 'Área Empenagem ($m^2$)',
        'taperV': 'Afilamento empenagem',
        'posXV': 'Distância empenagem (m)',
        'fuselageLength': 'Comprimento fuselagem (m)',
        'deflection_cruise_elevator': 'Deflexão profundor (º)',
        'alphaStallWing': 'Ângulo de estol (º)',
        'stallPositionWing': 'Posição de estol da asa (%)',
        'weightEmpty': 'Peso vazio (kg)',
        'fuelTotal': 'Peso combustível (kg)',
        'runway': 'Pista de decolagem (m)',
        'speedTakeOff': 'Velocidade decolagem (m/s)',
        'range_all': 'Alcance (km)',
    }

    # -----------------------------------------
    # numRows = doe_df.shape[0]
    # doe_df = doe_df[doe_df['cruiseRange'] < 1200]
    # print(f"Cutted {numRows - doe_df.shape[0]}, range < 200")
    # -----------------------------------------
    numRows = doe_df.shape[0]
    doe_df = doe_df[doe_df['range_all'] > 0]
    print(f"Cutted {numRows - doe_df.shape[0]}, range > 0")

    # -----------------------------------------
    numRows = doe_df.shape[0]
    doe_df = doe_df[doe_df['range_all'] < 650]
    print(f"Cutted {numRows - doe_df.shape[0]}, range < 650")
    # -----------------------------------------
    # numRows = doe_df.shape[0]
    # doe_df = doe_df[doe_df['deflection_cruise_elevator'] < 0]
    # print(f"Cutted {numRows - doe_df.shape[0]}, elevator < 0")
    # -----------------------------------------
    numRows = doe_df.shape[0]
    doe_df = doe_df[doe_df['runway'] < 1200]
    print(f"Cutted {numRows - doe_df.shape[0]}, runaway < 1200")

    # -----------------------------------------
    numRows = doe_df.shape[0]
    doe_df = doe_df[doe_df['alphaStallWing'] > 0]
    print(f"Cutted {numRows - doe_df.shape[0]}, alphaStallWing > 0")

    # -----------------------------------------
    numRows = doe_df.shape[0]
    doe_df = doe_df[doe_df['stallPositionWing'] > 0]
    print(f"Cutted {numRows - doe_df.shape[0]}, stallPositionWing > 0")

    # -----------------------------------------
    # numRows = doe_df.shape[0]
    # doe_df = doe_df[doe_df['staticMargin'] > 0]
    # print(f"Cutted {numRows - doe_df.shape[0]}, staticMargin > 0")

    doe_df = doe_df.rename(columns=renameColumns)  # TODO:

    return doe_df

if __name__ == '__main__':
    plot_doe(filename='resultsAll')
    plot_doe(filename='resultsWing')
    plot_doe(filename='resultsStab')
    plot_doe(filename='resultsFuselage')


#!/usr/local/bin/checkio --domain=py run sum-by-type

# You have a list. Each value from that list can be either a string or an integer. Your task here is to return two values. The first one is a concatenation of all strings from the given list. The second one is a sum of all integers from the given list.
#
# Input:An array of strings ans integers
#
# Output:A list or tuple
#
# Precondition:both given ints should be between -1000 and 1000
#
#
# END_DESC

from typing import Tuple

def sum_by_types(items: list) -> Tuple[str, int]:
    result = ["", 0]
    for i in items:
        if isinstance(i, str):
            result[0] += i
        elif isinstance(i, int):
            result[1] += i
    return tuple(result)


from django.core.exceptions import SuspiciousOperation
from django.shortcuts import redirect, render, get_object_or_404

from .forms import LeadForm
from .models import Lead

def index(request):
    leads = Lead.objects.filter()

    return render(request, 'index.html', {'leads': leads})

def lead_detail(request, lead_id):
    lead_obj = get_object_or_404(Lead, id=lead_id)

    return render(request, 'lead_detail.html', {'lead': lead_obj})

def edit_lead(request, lead_id):
    if request.method == 'GET':
        lead_obj = get_object_or_404(Lead, id=lead_id)
        form = LeadForm(instance=lead_obj)

        return render(request, 'edit_lead.html', {'form': form, 'lead': lead_obj})

    elif request.method == 'POST':
        lead_obj = get_object_or_404(Lead, id=lead_id)
        form = LeadForm(request.POST, instance=lead_obj)

        if form.is_valid():
            form.save()

        return redirect('leads:lead_detail', lead_id=lead_id)

    else:
        raise SuspiciousOperation

def create_lead(request):
    if request.method == 'GET':
        form = LeadForm()

        return render(request, 'create_lead.html', {'form': form})

    elif request.method == 'POST':
        form = LeadForm(request.POST)

        if form.is_valid():
            instance = form.save(commit=False)
            instance.save()

            return redirect('leads:lead_detail', lead_id=instance.id)

        else:
            return render(request, 'create_lead.html', {'form': form})

    else:
        raise SuspiciousOperation

def delete_lead(request, lead_id):
    if request.method == 'POST':
        lead_obj = get_object_or_404(Lead, id=lead_id)
        lead_obj.delete()

    return redirect('leads:index')


import json

from django import template
from crams_contact.models import Contact
from crams_contact.models import ContactRole
from crams.models import EResearchBodyIDKey
from crams_contact.models import EResearchContactIdentifier
from crams_collection.models import Project
from crams_collection.models import ProjectID
from crams_collection.models import ProjectContact
from crams_allocation.models import Request

register = template.Library()

@register.filter(name='get_contact_name')
def get_contact_name(email):
    try:
        contact = Contact.objects.get(email=email)
        if contact.given_name:
            return contact.given_name + ' ' + contact.surname
        else:
            return contact.email
    except:
        return email

@register.filter(name='get_user_contact')
def get_user_contact(user_dict):
    email = user_dict
    if email:
        qs = Contact.objects.filter(email__iexact=email)
        if qs.count() > 0:
            return qs.first()

    return None

@register.filter(name='get_name_email')
# tries to get contact full name, if none return email
def get_name_email(updated_by):
    email = updated_by.get('email')
    contact = get_user_contact(email)
    if contact:
        return get_contact_name(contact.email)
    return None

@register.filter(name='filter_project_id')
def get_project_id(project_ids, system_to_search):
    search_tree_hierarchy = ['system', 'key']
    for project_id in project_ids:
        try:
            if DictSearch.search_tree_return_value(
                    search_tree_hierarchy, project_id) == system_to_search:
                return project_id['identifier']
        except Exception:
            pass

    return None

@register.filter(name='get_user_id')
def get_user_id(email, erb_key):
    try:
        erb_id_key = EResearchBodyIDKey.objects.get(key=erb_key)
        erb_contact_id = EResearchContactIdentifier.objects.get(
            contact__email=email, system_id=erb_id_key)

        return erb_contact_id.identifier
    except:
        return None

@register.filter(name='get_group_id')
def get_group_id(project_id, erb_key):
    try:
        erb_id_key = EResearchBodyIDKey.objects.get(key=erb_key)
        project_id = ProjectID.objects.get(
            project_id=project_id, system_id=erb_id_key)

        return project_id.identifier
    except:
        return None

@register.filter(name='filter_project_contact')
def get_project_contact_email(project_contacts, role_name):
    search_tree_hierarchy = ['contact_role']
    for project_contact in project_contacts:
        try:
            if DictSearch.search_tree_return_value(
                    search_tree_hierarchy, project_contact) == role_name:
                return project_contact['contact']['email']

        except Exception:
            pass

    return None

@register.filter(name='get_project_contacts')
def get_project_contacts(project_id):
    # NB: Django ORM distinct is not support by mysql
    # This query will only do a distinct on the email values
    # Therefore the following query will only return the emails and
    # not the expected ProjectContact objects
    pc_list = ProjectContact.objects.filter(
        project_id=project_id).order_by('contact__email').values(
        'contact__email').distinct()

    # get contact from email and append to contact_list
    contact_list = []
    for email in pc_list:
        contact = Contact.objects.get(email=email['contact__email'])
        contact_list.append(contact)

    return contact_list

@register.filter(name='get_project_contacts_by_role')
def get_project_contacts_by_role(prj_obj, role_name):
    # This function fetches the contact roles from deserialized
    # project object, should be used for first time submission since
    # the allocation request is not saved at time calling this function
    proj_json = json.dumps(prj_obj)
    print('======>tag --> prj_obj json: {}'.format(proj_json))
    if not prj_obj:
        return None

    prj_contacts = prj_obj.get('project_contacts')

    results = list()
    for prj_cont in prj_contacts:
        if prj_cont.get('contact_role').lower() == role_name.lower():
            results.append(prj_cont.get('contact').get('email'))

    return results

@register.filter(name='get_prj_cont_by_role')
def get_prj_cont_by_role(prj_contacts, role_name):
    results = list()
    for prj_cont in prj_contacts:
        role1 = prj_cont.get('contact_role').lower()
        role_required = role_name.lower()
        if prj_cont.get('contact_role').lower() == role_name.lower():
            contact_dict = prj_cont.get('contact')
            if contact_dict:
                email = contact_dict.get('email')
                if email:
                    results.append(email)

    return results

@register.filter(name='get_req_status_code')
def get_req_status_code(req_id):
    request = Request.object.get(pk=req_id)

    return request.request_status.code

@register.filter(name='display_dc_and_app_contacts')
def display_dc_and_app_contacts(prj_obj):
    proj_json = json.dumps(prj_obj)
    print('----- display_dc_and_app_contacts - proj_json: {}'.format(proj_json))
    try:
        req_id = prj_obj.get('id')
        print('---- request id: {}'.format(req_id))
        if not req_id:
            return None
    except:
        return None
    # get the requests from project id
    request = Request.objects.get(pk=req_id)

    # fetch the data custodians
    dc_list = get_project_contacts_by_role(prj_obj, 'Data Custodian')
    print('----> dc_list: {}'.format(dc_list))
    # fetch the applicant
    app_list = get_project_contacts_by_role(prj_obj, 'Applicant')
    print('----> app_list: {}'.format(app_list))
    # append string result
    result = ''
    i = 0
    while i < len(dc_list):
        result += get_contact_name(dc_list[i])
        if i != len(dc_list)-1:
            result += " \\ "
        i += 1

    if app_list:
        # only add app contact if they are not already in the dc list
        # business rule as of 12-02-2020: there should only be 1 applicant in racmon
        app = app_list[0]
    else:
        # in first submissions project_contacts do not include the applicant
        # need to fetch that from the request updated_by contact field
        # app = prj_obj.get('requests')[0].get('updated_by').get('email')
        app = request.updated_by.email

    if app not in dc_list:
        result += " \\ " + get_contact_name(app)
    print('----> result: {}'.format(result))
    return 'Dear ' + result

@register.filter(name='get_contact_names_by_role')
def get_contact_names_by_role(project_id, role_name):
    project = Project.objects.get(pk=project_id)
    erb = project.requests.first().e_research_system.e_research_body
    project_contacts = ProjectContact.objects.filter(project=project)
    contact_roles = ContactRole.objects.filter(e_research_body=erb, name=role_name)
    contact_names = ''
    if contact_roles:
        contact_role = contact_roles.first()
        project_contacts = project_contacts.filter(contact_role=contact_role)

        for project_contact in project_contacts:
            contact = project_contact.contact
            if contact.given_name:
                contact_name = contact.given_name + ' ' + contact.surname
            else:
                contact_name = contact.email
            contact_names += contact_name + ', '
        contact_names = contact_names.strip()[0:-1]
    return contact_names

@register.filter(name='filter_question_response')
def get_response_for_question(question_responses, question_key):
    search_tree_hierarchy = ['question', 'key']
    for question_response in question_responses:
        try:
            if DictSearch.search_tree_return_value(
                    search_tree_hierarchy, question_response) == question_key:
                return question_response['question_response']

        except Exception:
            pass

    return None

class DictSearch:
    ALL = '*'

    @classmethod
    def search_tree_return_value(cls, search_hierarchy, search_dict):
        """
        Search a multi-level Dictionary for a hierarchy of keys and return the
        value if found.
        Use wildcard '*' at any level for a blind search. The first match will
        be returned for such blind search.

        For example if the dict was
        {
            'question_response': '',
            'question': {
                   'key': 'usagepattern',
                   'question': 'Instance, object storage and volume storage'
                   },
            'id': 10346
        }

        For search_hierarchy ['question', 'key'] and ['*', 'key'] the same
          value will be returned i.e., 'usagepattern'

        But the return value for ['question', '*'] or ['*','*'] is arbitrary.
        Such constructs are useful for determining the minimum tree depth of
        the dictionary

        :param search_hierarchy:
        :param search_dict:
        :return:
        """
        remaining_tree = list(search_hierarchy)
        while remaining_tree:
            if isinstance(search_dict, dict):
                next_node = remaining_tree.pop(0)
                if next_node == DictSearch.ALL:
                    for value_sub_dict in search_dict.values():
                        try:
                            return DictSearch.search_tree_return_value(
                                remaining_tree, value_sub_dict)
                        except Exception:
                            continue
                elif next_node in search_dict:
                    return DictSearch.search_tree_return_value(
                        remaining_tree,
                        search_dict.get(next_node))
                else:
                    raise Exception('Tree Not Found')
            else:
                raise Exception('Tree Not Found')

        return search_dict


import asyncio
import curses
import glob
import os
import time
from itertools import cycle
from random import choice, randint

from curses_tools import draw_frame, get_frame_size, read_controls, \
    update_speed, get_garbage_delay_tics, PHRASES

CANVAS_BORDER_INDENT = 2
FRAME_BORDER_INDENT = 1
STARS_AMOUNT = 50  # TODO import amount from env or as argument
YEAR_WITH_GUN = 2000
EXPLOSION_FRAMES = [
    """\
           (_)
       (  (   (  (
      () (  (  )
        ( )  ()
    """,
    """\
           (_)
       (  (   (
         (  (  )
          )  (
    """,
    """\
            (
          (   (
         (     (
          )  (
    """,
    """\
            (
              (
            (
    """,
]

class Obstacle:

    def __init__(self, row, column, rows_size=1, columns_size=1, uid=None):
        self.row = row
        self.column = column
        self.rows_size = rows_size
        self.columns_size = columns_size
        self.uid = uid

    def get_bounding_box_frame(self):
        # increment box size to compensate obstacle movement
        rows, columns = self.rows_size + 1, self.columns_size + 1
        return '\n'.join(_get_bounding_box_lines(rows, columns))

    def get_bounding_box_corner_pos(self):
        return self.row - 1, self.column - 1

    def dump_bounding_box(self):
        row, column = self.get_bounding_box_corner_pos()
        return row, column, self.get_bounding_box_frame()

    def has_collision(self, obj_corner_row, obj_corner_column, obj_size_rows=1,
                      obj_size_columns=1):
        '''Determine if collision has occured. Return True or False.'''
        return has_collision(
            (self.row, self.column),
            (self.rows_size, self.columns_size),
            (obj_corner_row, obj_corner_column),
            (obj_size_rows, obj_size_columns),
        )

def _get_bounding_box_lines(rows, columns):
    yield ' ' + '-' * columns + ' '
    for _ in range(rows):
        yield '|' + ' ' * columns + '|'
    yield ' ' + '-' * columns + ' '

async def show_obstacles(canvas, obstacles):
    """Display bounding boxes of every obstacle in a list"""

    while True:
        boxes = []

        for obstacle in obstacles:
            boxes.append(obstacle.dump_bounding_box())

        for row, column, frame in boxes:
            draw_frame(canvas, row, column, frame)

        await sleep(1)

        for row, column, frame in boxes:
            draw_frame(canvas, row, column, frame, negative=True)

def _is_point_inside(corner_row, corner_column, size_rows, size_columns,
                     point_row, point_row_column):
    rows_flag = corner_row <= point_row < corner_row + size_rows
    columns_flag = corner_column <= point_row_column < corner_column + size_columns

    return rows_flag and columns_flag

def has_collision(obstacle_corner, obstacle_size, obj_corner, obj_size=(1, 1)):
    '''Determine if collision has occured. Return True or False.'''

    opposite_obstacle_corner = (
        obstacle_corner[0] + obstacle_size[0] - 1,
        obstacle_corner[1] + obstacle_size[1] - 1,
    )

    opposite_obj_corner = (
        obj_corner[0] + obj_size[0] - 1,
        obj_corner[1] + obj_size[1] - 1,
    )

    return any([
        _is_point_inside(*obstacle_corner, *obstacle_size, *obj_corner),
        _is_point_inside(*obstacle_corner, *obstacle_size,
                         *opposite_obj_corner),

        _is_point_inside(*obj_corner, *obj_size, *obstacle_corner),
        _is_point_inside(*obj_corner, *obj_size, *opposite_obstacle_corner),
    ])

async def explode(canvas, center_row, center_column):
    rows, columns = get_frame_size(EXPLOSION_FRAMES[0])
    corner_row = center_row - rows / 2
    corner_column = center_column - columns / 2

    curses.beep()
    for frame in EXPLOSION_FRAMES:
        draw_frame(canvas, corner_row, corner_column, frame)

        await sleep(1)
        draw_frame(canvas, corner_row, corner_column, frame, negative=True)
        await sleep(1)

async def fire(canvas, start_row, start_column, rows_speed=-0.3,
               columns_speed=0):
    """Display animation of gun shot, direction and speed can be specified."""

    row, column = start_row, start_column

    canvas.addstr(round(row), round(column), '*')
    await sleep(1)

    canvas.addstr(round(row), round(column), 'O')
    await sleep(1)
    canvas.addstr(round(row), round(column), ' ')

    row += rows_speed
    column += columns_speed

    symbol = '-' if columns_speed else '|'

    rows, columns = canvas.getmaxyx()
    max_row, max_column = rows - 1, columns - 1

    curses.beep()

    while 0 < row < max_row and 0 < column < max_column:
        for obstacle in obstacles:
            if obstacle.has_collision(row, column):
                obstacles_in_last_collisions.append(obstacle)
                return
        canvas.addstr(round(row), round(column), symbol)
        await sleep(1)
        canvas.addstr(round(row), round(column), ' ')
        row += rows_speed
        column += columns_speed

async def blink(canvas, row, column, symbol='*'):
    """Draw flickering symbol"""
    while True:
        await sleep(randint(0, STARS_AMOUNT))
        canvas.addstr(row, column, symbol, curses.A_DIM)
        await sleep(20)

        canvas.addstr(row, column, symbol)
        await sleep(3)

        canvas.addstr(row, column, symbol, curses.A_BOLD)
        await sleep(5)

        canvas.addstr(row, column, symbol)
        await sleep(3)

def get_next_coordinates(canvas, frame, row, column, rows_direction,
                         columns_direction, row_speed, column_speed):
    """Calculate rocket coordinate after user choose"""
    height, width = curses.window.getmaxyx(canvas)

    row_speed, column_speed = update_speed(
        row_speed,
        column_speed,
        rows_direction,
        columns_direction
    )

    row += row_speed
    column += column_speed
    frame_rows, frame_columns = get_frame_size(frame)

    row = max(
        min(height - frame_rows - FRAME_BORDER_INDENT, row),
        FRAME_BORDER_INDENT
    )

    column = max(
        min(width - frame_columns - FRAME_BORDER_INDENT, column),
        FRAME_BORDER_INDENT
    )

    return row, column, row_speed, column_speed

async def animate_spaceship(canvas, row, column, rockets, game_over_frame):
    """Calculate rocket coordinates and draw rocket"""
    row_speed = column_speed = 0
    for rocket in cycle(rockets):
        rows_direction, columns_direction, space_pressed = read_controls(
            canvas)
        row, column, row_speed, column_speed = get_next_coordinates(
            canvas,
            rocket,
            row,
            column,
            rows_direction,
            columns_direction,
            row_speed,
            column_speed
        )

        draw_frame(canvas, row, column, rocket)
        if space_pressed and year >= YEAR_WITH_GUN:
            frame_rows, frame_columns = get_frame_size(rocket)
            coroutines.append(fire(canvas, row, column + frame_columns // 2,
            rows_speed=-2))
        await sleep(1)
        draw_frame(canvas, row, column, rocket, negative=True)
        for obstacle in obstacles:
            if obstacle.has_collision(row, column):
                await show_gameover(canvas, game_over_frame)
                return

async def fly_garbage(canvas, column, garbage_frame, speed=0.5):
    """Animate garbage, flying from top to bottom. Сolumn position will stay same, as specified on start."""
    rows_number, columns_number = canvas.getmaxyx()

    column = max(column, 0)
    column = min(column, columns_number - 1)

    row = 0
    row_size, column_size = get_frame_size(garbage_frame)

    while row < rows_number:
        obstacle = Obstacle(row, column, row_size, column_size)
        obstacles.append(obstacle)

        draw_frame(canvas, row, column, garbage_frame)
        await sleep(1)
        draw_frame(canvas, row, column, garbage_frame, negative=True)
        obstacles.remove(obstacle)
        if obstacle in obstacles_in_last_collisions:
            await explode(canvas, row + row_size // 2,
                          column + column_size // 2)
            return
        row += speed

async def fill_orbit_with_garbage(canvas, garbages, width):
    for garbage in cycle(garbages):
        garbage_delay_tics = get_garbage_delay_tics(year)
        if not garbage_delay_tics:
            await sleep(1)
            continue
        column = randint(0, width)
        coroutines.append(fly_garbage(
            canvas, column=column, garbage_frame=garbage))
        await sleep(garbage_delay_tics)

async def sleep(tics=1):
    for _ in range(tics):
        await asyncio.sleep(0)

async def show_gameover(canvas, game_over_frame):
    height, width = curses.window.getmaxyx(canvas)
    row_size, column_size = get_frame_size(game_over_frame)
    row = height // 2 - row_size // 2
    column = width // 2 - column_size // 2
    while True:
        draw_frame(canvas, row, column, game_over_frame)
        await sleep(1)

async def change_year(delay=15):
    while True:
        await sleep(delay)
        global year
        year += 1

async def show_year(canvas):
    height, width = curses.window.getmaxyx(canvas)
    while True:
        year_info_canvas = canvas.derwin(3, width, height - 3, 0)
        year_info_canvas.border()
        year_phrase = PHRASES.get(year, '')
        year_message = f'Year: {year} - {year_phrase}' if year_phrase else f'Year: {year}'
        score = len(obstacles_in_last_collisions)
        score_message = f'Score: {score}'
        draw_frame(year_info_canvas, 1, 1, year_message)
        draw_frame(year_info_canvas, 1, width - len(score_message) - 1,
                   score_message)
        await sleep(1)
        draw_frame(year_info_canvas, 1, 1, year_message, negative=True)
        draw_frame(year_info_canvas, 1, width - len(score_message) - 1,
                   score_message, negative=True)

def upload_frames(path_to_frames, upload_counter=1):
    frames = []
    for filename in glob.glob(os.path.join(path_to_frames, '*.txt')):
        with open(os.path.join(os.getcwd(), filename), 'r') as frames_file:
            frame = frames_file.read()
            for _ in range(upload_counter):
                frames.append(frame)
    return frames

def draw(canvas):
    """Create game logic and draw the game"""
    rockets = upload_frames(os.path.join('frames', 'rockets'), 2)
    garbages = upload_frames(os.path.join('frames', 'trash'))
    game_over_frames = upload_frames(os.path.join('frames', 'game_over'))

    height, width = curses.window.getmaxyx(canvas)
    tic_timeout = 0.1
    canvas.border()
    curses.curs_set(False)
    canvas.nodelay(True)

    global year
    year = 1957

    global obstacles
    obstacles = []

    global obstacles_in_last_collisions
    obstacles_in_last_collisions = []

    global coroutines
    coroutines = [fire(canvas, height // 2, width // 2)]
    coroutines.append(animate_spaceship(
        canvas, height // 2, width // 2, rockets, game_over_frames[0]))
    coroutines.append(fill_orbit_with_garbage(canvas, garbages, width))
    symbols = ['+', '*', '.', ':']
    coroutines.extend([blink(
        canvas,
        randint(CANVAS_BORDER_INDENT, height - CANVAS_BORDER_INDENT),
        randint(CANVAS_BORDER_INDENT, width - CANVAS_BORDER_INDENT),
        choice(symbols)) for i in range(STARS_AMOUNT)
    ])
    coroutines.append(change_year())
    coroutines.append(show_year(canvas))

    while True:
        for coroutine in coroutines.copy():
            try:
                coroutine.send(None)

            except StopIteration:
                coroutines.remove(coroutine)
        canvas.refresh()
        time.sleep(tic_timeout)

if __name__ == '__main__':
    curses.update_lines_cols()
    curses.wrapper(draw)


import os
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import *
import subprocess
def set_height(height, points):
    n_height = [int(height * 0.1)]

    for i in range(1, points-1):
        n_height.append((height * 0.2 + n_height[i - 1]).astype(int))

    n_height.append((height * 0.1 + n_height[-1]).astype(int))
    print(n_height)
    return n_height

def set_text_geom(n_height):
    n_height = list(map(str, n_height))
    geometry_dis = ["Top	0.	0.	" + n_height[-1] + ".	structural\n",
                    "Basea	0.	0.	" + n_height[0] + ".	structural\n",
                    "Baseb	0.	0.	" + n_height[1]+ ".	structural\n",
                    "Basec	0.	0.	" + n_height[2] + ".	structural\n",
                    "Based	0.	0.	" + n_height[3] + ".	structural\n",
                    "Basee	0.	0.	" + n_height[4] + ".	structural\n"]
    return geometry_dis

def set_text_acc(signalAcc, signalDur, signalLen, signalDT,factor, pgv_factor):
    load_acc = []
    stage_acc = []
    for acc in range(len(signalAcc)):
        load_acc.append(
            "Dynamic Time-history Load	Base	x	acceleration	" + str(int(1000*factor*pgv_factor[acc])) + ".	" + signalAcc[acc] + "\n")
        stage_acc.append("0.0	"+ str(signalDur[acc]) +"	"+ str(signalLen[acc]) + "	"+ str(signalDT[acc]) + "\n")
    return load_acc, stage_acc

def replace_text(input_file, name_output_file, geometry_dis, uload_acc,ustage_acc, output_directory) :
    file = open(input_file, "r")
    list_of_lines = file.readlines()

    for changed_line in range(41, 47):
        list_of_lines[changed_line] = geometry_dis[changed_line - 41]
    list_of_lines[95] = uload_acc
    list_of_lines[100] = ustage_acc
    file = open(os.path.join(output_directory, name_output_file), "w")
    file.writelines(list_of_lines)
    file.close()

def generate_input_seismofiles(signalAcc, signalDur, signalLen, signalDT, pylon_lengths, input_file, output_file, output_directory, factor, pgv_factor):
    load_acc, stage_acc = set_text_acc(signalAcc, signalDur, signalLen, signalDT, factor, pgv_factor)
    plengths = list(map(str, (pylon_lengths / 1000).astype(int)))

    for pylon_i in range(len(pylon_lengths)):
        n_height = set_height(pylon_lengths[pylon_i], 6)
        geometry_dis = set_text_geom(n_height)
        for acc_i in range(len(load_acc)):
            seismo_input_file="P" + plengths[pylon_i] + "L_" +signalAcc[acc_i]+"_" + str(int(factor*10)) + output_file
            replace_text(input_file, seismo_input_file, geometry_dis, load_acc[acc_i], stage_acc[acc_i],output_directory)

def batch_run_files(input_seismo_file):
    command_exe ="D:\Outils\SStruct_Engine_v5_2.exe"+ " "+ input_seismo_file
    wholecmd="'"+'cmd /k '+ '{'+command_exe+'}'+"'"
    print(command_exe)
    os.system(command_exe )

def getting_info_file(input_file):  # INPUTFILE IS FILENAMES[i]
    file = open(input_file, "r")
    list_of_lines = file.readlines()
    file.close()
    return list_of_lines

def extracting_results_file(list_of_lines):
    # Declaring variables to extract from file
    time = []  # Time variable
    # CONTX = []  # Displacement of the control node
    CONTR = []  # Rotation of the control node
    # DRIFT = []  # Structural drift
    CURVZaS1 = []  # Curvature of the pylon at the base a of the structure
    CURVZaS2 = []  # Curvature of the pylon at the base a of the structure
    CURVZbS1 = []  # Curvature of the pylon at the base b  of the structure
    CURVZbS2 = []  # Curvature of the pylon at the base b  of the structure
    CURVZcS1 = []  # Curvature of the pylon at the base b  of the structure
    CURVZcS2 = []  # Curvature of the pylon at the base  c of the structure.
    DEPLX_O = []  # Horizontal displacement at the base of the structure
    DEPLX_H = []  # Horizontal displacement at the top of the structure
    DEPLZ_O = []  # Vertical displacement at the base of the structure
    DEPLZ_H = []  # Vertical displacement at the top of the structure
    ROTAZ_H = []  # Rotation at the top of the structure
    FORCX = []  # Horizontal reaction at the base
    FORCZ = []  # Vertical reaction at the base
    MOMEN_S = []  # Moment at the base of the structure
    relaHDisp = []
    relaVDisp = []
    SStrain_max_PLaS1 = []
    SStress_max_PLaS1 = []
    SStrain_min_PLaS1 = []
    SStress_min_PLaS1 = []
    CStrain_max_PLaS1 = []
    CStress_max_PLaS1 = []
    CStrain_min_PLaS1 = []
    CStress_min_PLaS1 = []
    SStrain_max_PLcS1 = []
    SStress_max_PLcS1 = []
    CStrain_max_PLcS1 = []
    CStress_max_PLcS1 = []
    outputNumber = []  # Output number
    element = 0
    count = 0
    for line in range(len(list_of_lines)):
        if list_of_lines[line] == ' Output-No.       Time\n':
            count = count + 1
    node_loc_displ = np.empty((7, count), dtype=object)
    # Reading and saving results
    for line in range(len(list_of_lines)):
        if list_of_lines[line] == ' Output-No.       Time\n':
            element = element + 1
            getline = list_of_lines[line + 1]
            outputNumber.append(getline.split()[0])
            time.append(float(getline.split()[1]))
            # FORCES AT THE BASE
            getline = list_of_lines[line + 5]
            FORCX.append(float(getline.split()[1]))
            FORCZ.append(float(getline.split()[3]))
            MOMEN_S.append(float(getline.split()[5]))
            # DISPLACEMENTS AT THE BASE
            getline = list_of_lines[line + 10]
            DEPLX_O.append(float(getline.split()[1]))
            DEPLZ_O.append(float(getline.split()[3]))
            # DISPLACEMENTS AT THE TOP OF THE STRUCTURE
            getline = list_of_lines[line + 11]
            DEPLX_H.append(float(getline.split()[1]))
            DEPLZ_H.append(float(getline.split()[3]))
            ROTAZ_H.append(float(getline.split()[5]))
            # CURVATURES
            getline = list_of_lines[line + 56]
            CURVZaS1.append(float(getline.split()[1]))
            CURVZaS2.append(float(getline.split()[3]))
            getline = list_of_lines[line + 57]
            CURVZbS1.append(float(getline.split()[1]))
            CURVZbS2.append(float(getline.split()[3]))
            getline = list_of_lines[line + 58]
            CURVZcS1.append(float(getline.split()[1]))
            CURVZcS2.append(float(getline.split()[3]))

            # DEPLACEMENTS RELATIFS
            getline = list_of_lines[line + 43]
            CONTR.append(float(getline.split()[4]))
            relaHDisp.append((DEPLX_H[element - 1] - DEPLX_O[element - 1]))
            relaVDisp.append((DEPLZ_H[element - 1] - DEPLZ_O[element - 1]))
            # CONCRETE AND STEEL STRESS AND STRAINS
            getline = list_of_lines[line + 85]
            SStrain_max_PLaS1.append(float(getline.split()[5]))
            SStress_max_PLaS1.append(float(getline.split()[6]))
            SStrain_min_PLaS1.append(float(getline.split()[3]))
            SStress_min_PLaS1.append(float(getline.split()[4]))
            getline = list_of_lines[line + 86]
            CStrain_max_PLaS1.append(float(getline.split()[3]))
            CStress_max_PLaS1.append(float(getline.split()[4]))
            CStrain_min_PLaS1.append(float(getline.split()[1]))
            CStress_min_PLaS1.append(float(getline.split()[2]))
            getline = list_of_lines[line + 97]
            SStrain_max_PLcS1.append(float(getline.split()[5]))
            SStress_max_PLcS1.append(float(getline.split()[6]))
            getline = list_of_lines[line + 98]
            CStrain_max_PLcS1.append(float(getline.split()[3]))
            CStress_max_PLcS1.append(float(getline.split()[4]))

            for element_loc in range(7):
                if element_loc == 0 :
                    node_loc_displ[element_loc, element - 1] = 0
                elif element_loc > 0 :
                    getline = list_of_lines[line + 41 + 2 * (element_loc-1)]
                    node_loc_displ[element_loc, element - 1] = float(getline.split()[2])

    return time, DEPLX_O, DEPLX_H, relaVDisp, ROTAZ_H, FORCZ, FORCX, MOMEN_S, CURVZaS2, CURVZbS1, CURVZaS1, CURVZbS2, CURVZcS1, CURVZcS2, CONTR, relaHDisp, node_loc_displ, SStrain_min_PLaS1, SStrain_max_PLaS1, CStrain_max_PLaS1, SStress_min_PLaS1, SStress_max_PLaS1, CStress_max_PLaS1, CStrain_min_PLaS1, CStress_min_PLaS1

def table_max_file(signal, case, factor, pgv, relaHDisp, relaVDisp, MOMEN_S,CURVZaS1, CStrain_max_PLaS1, CStrain_min_PLaS1, SStrain_max_PLaS1, SStrain_min_PLaS1, ROTAZ_H, DEPLX_O):
    ky = 0.00000036  # ky= 1.8*35/(30000*0.002*2925) 1/mm
    max_relaHDisp = max(abs(max(relaHDisp)), abs(min(relaHDisp))) / 1000 #m
    max_CDR = max(abs(max(CURVZaS1)), abs(min(CURVZaS1))) / ky
    max_MOMEN_S = max(abs(max(MOMEN_S)), abs(min(MOMEN_S)))/1000000000 # MN m
    max_CStrain = max(CStrain_max_PLaS1)
    min_CStrain = min(CStrain_min_PLaS1)
    max_SStrain = max(SStrain_max_PLaS1)
    min_SStrain = min(SStrain_min_PLaS1)
    max_ROTAZ_H = max(abs(max(ROTAZ_H )), abs(min(ROTAZ_H ))) # rad
    max_DEPLX_O = max(abs(max(DEPLX_O)), abs(min(DEPLX_O)))/1000  # m
    max_relaVDisp = max(abs(max(relaVDisp)), abs(min(relaVDisp)))/1000 #m
    #Creating list-table
    table_line = signal + " " + case + " " + factor + " " + pgv + " " + str('%.4f'%max_relaHDisp) + " " + str('%.4f'%max_DEPLX_O) + " " +  str('%.4f'%max_ROTAZ_H) + " " + str('%.4f'%max_ROTAZ_H)+ " " + str('%.4f'%max_CDR)+ " " + str('%.4f'%max_relaVDisp)+" " + str('%.2f'%max_MOMEN_S)+ " " + str('%.4f'%max_CStrain) + " " + str('%.4f'%min_CStrain) + " " + str('%.4f'%max_SStrain)+ " " + str('%.4f'%min_SStrain) +"\n"
    return (table_line)

def writing_textfile_results(output_directory, namefile, table):
    file = open(os.path.join(output_directory, namefile), "w")
    file.writelines(table)
    file.close()

def plotting_results(analysis_name, time, relaVDisp, FORCZ, FORCX, MOMEN_S, CURVZaS2, CURVZbS1, CURVZaS1, CURVZbS2, CURVZcS1, CURVZcS2, CONTR, relaHDisp, node_loc_displ, SStrain_min_PLaS1, SStrain_max_PLaS1, CStrain_max_PLaS1, SStress_min_PLaS1, SStress_max_PLaS1, CStress_max_PLaS1, CStrain_min_PLaS1, CStress_min_PLaS1):
    ##------------------------------------------------------------------------------------------- Plotting results
    rc('figure', figsize=(11.69, 8.27))
    # Time Histories
    plt.clf()
    plt.plot(time, relaHDisp, 'b-')
    plt.grid(True)
    plt.gca().xaxis.grid(True, which='minor')
    plt.gca().yaxis.grid(True, which='minor')
    plt.xlabel('Time [s]')
    plt.ylabel('Top horizontal displacement [mm]')
    plt.savefig(analysis_name + 'a_DeplX_TH.png')

    plt.clf()
    plt.plot(time, relaVDisp, 'b-')
    plt.grid(True)
    plt.gca().xaxis.grid(True, which='minor')
    plt.gca().yaxis.grid(True, which='minor')
    plt.xlabel('Time [s]')
    plt.ylabel('Top vertical displacement [mm]')
    plt.savefig(analysis_name +'b_DeplZ_TH.png')

    # Steel Strain - stress
    plt.clf()
    plt.plot(SStrain_max_PLaS1, SStress_max_PLaS1, 'k-')
    plt.plot(SStrain_min_PLaS1, SStress_min_PLaS1, 'g-')

    plt.grid(True)
    plt.gca().xaxis.grid(True, which='minor')
    plt.gca().yaxis.grid(True, which='minor')
    plt.xlabel('Strain [-]')
    plt.ylabel('Stress [MPa]')
    plt.savefig(analysis_name +'c_SteelStressStrain.png')
    # Concrete Strain - stress
    plt.clf()
    plt.plot(CStrain_max_PLaS1, CStress_max_PLaS1, '-k')
    plt.plot(CStrain_min_PLaS1, CStress_min_PLaS1, '-g')
    plt.grid(True)
    plt.gca().xaxis.grid(True, which='minor')
    plt.gca().yaxis.grid(True, which='minor')
    plt.limits = [min(CStrain_min_PLaS1), 0.0003, min(CStress_min_PLaS1), max(CStress_max_PLaS1)]
    plt.xlabel('Strain [-]')
    plt.ylabel('Stress [MPa]')
    plt.savefig(analysis_name +'d1_ConcreteStressStrain.png')

    # Concrete Strain - stress
    plt.clf()
    plt.plot(CStrain_max_PLaS1, CStress_max_PLaS1, '-k')
    plt.plot(CStrain_min_PLaS1, CStress_min_PLaS1, '-g')
    plt.grid(True)
    plt.gca().xaxis.grid(True, which='minor')
    plt.gca().yaxis.grid(True, which='minor')
    plt.xlabel('Strain [-]')
    plt.ylabel('Stress [MPa]')
    plt.savefig(analysis_name +'d2_ConcreteStressStrain.png')

    plt.clf()
    # Vertical force- Vertical displacement
    plt.plot(relaVDisp, FORCZ, 'b-')
    plt.grid(True)
    plt.gca().xaxis.grid(True, which='minor')
    plt.gca().yaxis.grid(True, which='minor')
    plt.xlabel('Top vertical displacement [mm]')
    plt.ylabel('Vertical reaction force [MN]')
    plt.savefig(analysis_name +'e_TopVerticalDisp_VForce.png')

    # Horizontal force - Horizontal displacement
    plt.clf()
    plt.plot(relaHDisp, FORCX, 'b-')
    plt.grid(True)
    plt.gca().xaxis.grid(True, which='minor')
    plt.gca().yaxis.grid(True, which='minor')
    plt.xlabel('Top horizontal displacement [mm]')
    plt.ylabel('Horizontal reaction force [MN]')
    plt.savefig(analysis_name +'f_TopHorizontalDisp_HForce.png')

    # Moment - Horizontal displacement
    plt.clf()
    plt.plot(relaHDisp, MOMEN_S, 'b-')
    plt.grid(True)
    plt.gca().xaxis.grid(True, which='minor')
    plt.gca().yaxis.grid(True, which='minor')
    plt.xlabel('Top horizontal displacement [mm]')
    plt.ylabel('Reaction moment [MNmm]')
    plt.savefig(analysis_name +'g_Moment_TopHorizontalDisp.png')

    # Moment - Rotation
    plt.clf()
    plt.plot(CONTR, MOMEN_S, 'r-', label='Base')
    plt.grid(True)
    plt.gca().xaxis.grid(True, which='minor')
    plt.gca().yaxis.grid(True, which='minor')
    # gca().legend()
    plt.xlabel('Rotation at PLa point A [rad]')
    plt.ylabel('Reaction moment [MNmm]')
    plt.savefig(analysis_name +'h_BaseMomentvsRotationCONTb.png')

    # Moment - Force
    plt.clf()
    plt.plot(FORCX, MOMEN_S, 'r-', label='Base')
    plt.grid(True)
    plt.gca().xaxis.grid(True, which='minor')
    plt.gca().yaxis.grid(True, which='minor')
    # gca().legend()
    plt.xlabel('Horizontal force at the base [N]')
    plt.ylabel('Moment at the base [MNmm]')
    plt.savefig(analysis_name +'i_BaseMomentvsHorizontalForce.png')

    # Moment - Displacement
    plt.clf()
    plt.plot(relaHDisp, MOMEN_S, 'r-', label='Base')
    plt.grid(True)
    plt.gca().xaxis.grid(True, which='minor')
    plt.gca().yaxis.grid(True, which='minor')
    # gca().legend()
    plt.xlabel('Top displacement [mm]')
    plt.ylabel('Moment at the base [MNmm]')
    plt.savefig(analysis_name +'j_BaseMomentvsHorizontalDisp.png')

    # Moment - Curvature
    plt.clf()
    plt.plot(CURVZaS1, MOMEN_S, 'r-', label='PLaS1')
    plt.plot(CURVZaS2, MOMEN_S, 'g-', label='PLaS2')
    plt.plot(CURVZbS1, MOMEN_S, 'b-', label='PLbS1')
    plt.plot(CURVZbS2, MOMEN_S, 'm-', label='PLbS2')
    plt.plot(CURVZcS1, MOMEN_S, 'k-', label='PLcS1')
    plt.plot(CURVZcS2, MOMEN_S, 'c-', label='PLcS2')
    plt.grid(True)
    plt.legend()
    plt.gca().xaxis.grid(True, which='minor')
    plt.gca().yaxis.grid(True, which='minor')
    plt.xlabel('Curvature [1/mm]')
    plt.ylabel('Moment at the base [MNmm]')
    plt.savefig(analysis_name +'k_BaseMomentvsCurvature.png')

    plt.clf()
    plt.plot(node_loc_displ, [0,0.021,0.142,0.34,0.54,0.74,0.92])
    plt.xlabel('Axial deformation dl [mm]')
    plt.ylabel('A-Gauss point location [x/L]')
    plt.savefig(analysis_name +'l_AxialDeformationdl_TH.png')


import matplotlib.pyplot as plt

# set background color
plt.style.use('dark_background')
fig = plt.figure(facecolor='#13120b')

x = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
y1 = [0, 0.12, 0.38, 0.5, 0.63, 0.71, 0.77, 0.81, 0.84, 0.81, 0.79]
y2 = [0, 0.14, 0.43, 0.50, 0.57, 0.61, 0.64, 0.66, 0.71, 0.69, 0.71]
y3 = [0, 0.11, 0.2, 0.37, 0.51, 0.59, 0.60, 0.58, 0.60, 0.57, 0.59]

# remove markers and set color for each line
plt.plot(x, y1, '-', color='red', label='EasyOCR')
plt.plot(x, y2, '-', color='green', label='KerasOCR')
plt.plot(x, y3, '-', color='blue', label='PyTesseract')

# set x and y axis labels
plt.xlabel('Percentage of characters recognized')
plt.ylabel('Percentage of words correctly recognized')

# set x and y ticks
plt.xticks(x)
plt.yticks([0, 0.2, 0.4, 0.6, 0.8, 1.0])

# set grid color
plt.grid(color='#5a5a5a')

# show legend
plt.legend()

# show plot
plt.show()


import sys
from PySide6.QtWidgets import QMainWindow, QApplication, QPushButton
from PySide6.QtCore import QSize
from PySide6.QtGui import QAction

class VentanaPySide(QMainWindow):
    def __init__(self):
        # Meotod init de la clase QMainWindow
        super().__init__()

        self.setWindowTitle('POO con PySide')

        # Ventana de tamaño fijo
        self.setFixedSize(QSize(600, 500))

        # Algunos componentes
        self._agregar_componentes()

    def _agregar_componentes(self):
        # Agregar Menú (pestañas como File, Edit, Selection, View, Go ...)
        menu = self.menuBar()
        menu_archivo = menu.addMenu('Archivo')
        opciones = menu.addMenu('Opciones')

        # Agregar opciones al menú (como nuevo, abrir, guardar, guardar como, cerrar)
        accion_nuevo = QAction('Nuevo', self)
        menu_archivo.addAction(accion_nuevo)

        # Agregar un texto a la barra de estado
        # Se muestra al poner el clic sobre "Nuevo"
        accion_nuevo.setStatusTip('Nuevo Archivo')

        # Agregamos un mensaje en la barra de estado
        # Se muestra al abrir la ventana
        self.statusBar().showMessage('Información de la barra de estado')

        # Botón
        boton = QPushButton('Nuevo botón')
        # Publicar el botón en la ventana
        self.setCentralWidget(boton)

if __name__ == '__main__':
    # app = QApplication(sys.argv)
    # sys.argv = Es para recibir argumentos de la líne ade comandos
    app = QApplication([]) # Vacio

    # Objeto tipo ventana
    ventana1 = VentanaPySide()
    ventana1.show()

    # Ejecutamos la ventana
    sys.exit(app.exec())


"""
RateLater model.
"""

from django.db import models

from core.models import User
from tournesol.models.poll import Poll

# The default minimum number of comparisons required to remove an entity from
# a user's rate-later list. When this constant is imported and used, the
# user's settings should take precedence over this default value.
RATE_LATER_AUTO_REMOVE_DEFAULT = 4

class RateLater(models.Model):
    """An `Entity` a user wants to rate later in a poll."""

    entity = models.ForeignKey(
        to="Entity",
        on_delete=models.CASCADE,
        help_text="The entity the user wants to save.",
        related_name="ratelaters",
    )
    user = models.ForeignKey(
        to=User,
        on_delete=models.CASCADE,
        help_text="The user who saves the entity.",
        related_name="ratelaters",
    )
    poll = models.ForeignKey(
        to=Poll,
        on_delete=models.CASCADE,
        help_text="The poll in which the user is saving the entity.",
        related_name="ratelaters",
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        help_text="Time at which the video is saved.",
        blank=True,
    )

    class Meta:
        ordering = ["user", "-created_at"]
        unique_together = ["poll", "user", "entity"]

    def __str__(self):
        return (
            f"poll:{self.poll}/user:{self.user}/entity:{self.entity}@{self.created_at}"
        )


from django.urls import path

from .views import listado_autor, listado_empleado, listado_libro, listado_socio, registro_libro

urlpatterns = [
    path('autores/', listado_autor, name='listado_autor'),
    path('empleados/', listado_empleado, name='listado_empleado'),
    path('libros/', listado_libro, name='listado_libro'),
    path('socios/', listado_socio, name='listado_socio'),
    path('libros/<int:id>', registro_libro, name='registro_libro'),

]


import hashlib
import json
from time import time

chain = []

def block(proof,previous_hash=None):
	transaction = {
	'sender' : 'Santoshi',
	'recepient' : 'Mike',
	'amount' : '500000 ETH'
	}

	data = {
	'index' : 1,
	'timestamps' : time(),
	'gas/fee' : 0.1,
	'proof' : proof,
	'previous_hash' : previous_hash,
	'uncle rewards' : '10000 ETH',
	'block rewards' : '41000 ETH',
	'difficulty' : '9,999,999,999',
	'total difficulty' : '9,999,999,999,999,999,999,999'

	}

	chain.append(block)
	print("block information",data)
	string_object = json.dumps(data)
	block_string = string_object.encode()

	raw_hash = hashlib.sha512(block_string)
	hex_hash = raw_hash.hexdigest()

	print("CODING HASH ERROR CODING HASH ERROR")

block(previous_hash = "BLAHBLAHBLAHBLAHBLAH FIRST HASH BLAHBLAHBLAHBLAHBLAH",proof=000)


from __future__ import division, print_function, absolute_import

import numpy as np

import tensorflow as tf

import tflearn

import matplotlib.colors
from scipy.stats import norm
import matplotlib.pyplot as plt

import pokedataset32_vae_functions as utilities

# 6 = Charizard
chosen_pokemon = 9  # Squirtle
chosen_pokemon = 13  # Caterpie
chosen_pokemon = 30  # Pikachu
chosen_pokemon = 146  # Jolteon
# chosen_pokemon = 161  # Dragonite
# chosen_pokemon = 252  # Porygon 2
chosen_pokemon_2 = 330  # Aaron
# chosen_pokemon = 427  # Jirachi
# chosen_pokemon = 622  # Darmanitan
# chosen_pokemon = 972  # shield doggo.

X_full_HSV, Y_full_HSV = \
    utilities.prepare_dataset_for_input_layer("pokedataset32_full_HSV_Two_Hot_Encoded.h5")

Y_full_HSV = Y_full_HSV * 0.5
expanded_full_X_HSV = np.append(X_full_HSV, Y_full_HSV, axis=1)

print("getting network to load model*******************")
network_instance = utilities.get_network()

network_instance = tflearn.regression(network_instance,
                                      optimizer='adam',
                                      metric='R2',
                                      loss=utilities.vae_loss,
                                      learning_rate=0.00001)  # adagrad? #adadelta #nesterov did good,

model = tflearn.DNN(network_instance)

print("LOADING MODEL.")

# This hasn't been commited yet, due to network restrictions (AKA slow upload connection).
# Double check to have a folder with the correct path here.
model_name = "_anime_V2_poke5"
model.load("saved_models/model_Jul_29_optim_adam_loss_vae_loss_"
           "last_activ_relu_latent_128_num_filters_512_1024_decoder_width_8" + model_name + ".tflearn")

print("MODEL SUCCESSFULLY LOADED.")

encoder_model = utilities.get_encoder_network(model)
generator_model = utilities.get_generative_network(model)
print("LOADED GENERATOR MODEL.")

black_images = np.zeros(shape=[1408, 3072])

num_samples = utilities.latent_dimension
mean = 0.00
std_dev = 1.00
range_variation = 20
"""x_axis = norm.ppf(np.linspace(0., 1., 100))
y_axis = norm.ppf(np.linspace(0., 1., 10))
one_per_latent = np.diag(np.ones(utilities.latent_dimension))*10.0"""
input_noise = np.random.normal(mean, std_dev, [utilities.latent_dimension])
input_noise_list = []
latent_dim_changes = []
for i in range(0, utilities.latent_dimension):
    # For each sample, make 10 of them
    for j in range(0, 11):
        temp_noise = np.copy(input_noise)
        temp_latent_change = np.zeros_like(temp_noise)
        temp_latent_change[i] = ((-range_variation / 2.0) + (j * range_variation / 10.0))
        latent_dim_changes.append(temp_latent_change)
        temp_noise[i] = temp_noise[i] + temp_latent_change[i]
        input_noise_list.append(temp_noise)

# input_noise = one_per_latent
"""# Add the fake types.
poke_type_1 = 'Fire'
poke_type_2 = 'None'
new_types_array = utilities.generate_all_one_type(num_samples,
                                                  in_type=poke_type_1, in_second_type=poke_type_2)
new_types_array = np.reshape(np.asarray(new_types_array), newshape=[new_types_array.shape[0],
                                                                    utilities.pokemon_types_dim])
new_types_array = new_types_array * 0.50
# new_types_array = new_types_array + Y_full_HSV
expanded_input_noise = np.append(input_noise, new_types_array, axis=1)"""

encoded_pokemon = utilities.predict_batches(expanded_full_X_HSV, encoder_model,
                                            in_samples_per_batch=64,
                                            in_input_name='input_images')

# Pick one pokemon and repeat it a number of times equal to the total noise samples
target_pokemon = encoded_pokemon[chosen_pokemon]
second_target_pokemon = encoded_pokemon[chosen_pokemon_2]
target_pokemon_difference = target_pokemon - second_target_pokemon
target_pokemon_difference = target_pokemon_difference/30.0  # Divided by the number of samples
interpolated_pokemon = []
for i in range(0, 30):
    current_interpolation = second_target_pokemon + (target_pokemon_difference * i)
    interpolated_pokemon.append(current_interpolation)
interpolated_transfer = utilities.predict_batches(interpolated_pokemon, generator_model,
                                                                     in_samples_per_batch=64,
                                                                     in_input_name='input_noise')

modified_encoded_pokemon = np.tile(target_pokemon, (len(latent_dim_changes), 1))
modified_encoded_pokemon = modified_encoded_pokemon + np.asarray(latent_dim_changes)

# Check how to do it in batches later.  input_noise_list
encode_decode_generated_samples_transfer = utilities.predict_batches(modified_encoded_pokemon, generator_model,
                                                                     in_samples_per_batch=64,
                                                                     in_input_name='input_noise')
# encode_decode_generated_samples = generator_model.predict({'input_noise': input_noise_list})

reconstructed_pixels_generated_transfer, reconstructed_types_generated_transfer = \
    utilities.reconstruct_pixels_and_types(encode_decode_generated_samples_transfer)

second_model_name = "_regular_V3_no_noise2"
model.load("saved_models/model_Jul_29_optim_adam_loss_vae_loss_"
           "last_activ_relu_latent_128_num_filters_512_1024_decoder_width_8" + second_model_name + ".tflearn",
           weights_only=True)

encoder_model_transfer = utilities.get_encoder_network(model)
generator_model_transfer = utilities.get_generative_network(model)
print("LOADED GENERATOR MODEL.")

encoded_pokemon = utilities.predict_batches(expanded_full_X_HSV, encoder_model_transfer,
                                            in_samples_per_batch=64,
                                            in_input_name='input_images_1')

# Pick one pokemon and repeat it a number of times equal to the total noise samples
target_pokemon = encoded_pokemon[chosen_pokemon]
modified_encoded_pokemon = np.tile(target_pokemon, (len(latent_dim_changes), 1))
modified_encoded_pokemon = modified_encoded_pokemon + np.asarray(latent_dim_changes)

encode_decode_generated_samples = utilities.predict_batches(modified_encoded_pokemon, generator_model_transfer,
                                                            in_samples_per_batch=64, in_input_name='input_noise_1')

reconstructed_pixels_generated, reconstructed_types_generated = \
    utilities.reconstruct_pixels_and_types(encode_decode_generated_samples)

utilities.export_latent_exploration_atlas(reconstructed_pixels_generated_transfer, reconstructed_pixels_generated,
                                          name_prefix='LatentExploration_TransferVSOriginal_',
                                          name_annotations='_range_var_' + str(range_variation))

# print('The number of ORIGINAL types correct types were: ')
# correct_indices = utilities.export_types_csv(Y_full_RGB[0:100], reconstructed_types_generated)

f, a = plt.subplots(1, 10, squeeze=False)  # figsize=(50, 2),
for i in range(10):
    temp = [[ii] for ii in list(reconstructed_pixels_generated[i])]
    a[0][i].imshow(np.reshape(temp, (32, 32, 3)))
    print("Types for Pokemon " + str(i) + " are: ")
    utilities.print_pokemon_types(reconstructed_types_generated[i])

f.show()
plt.draw()
plt.waitforbuttonpress()

# This is used to export an image only containing the ones whose types were correctly predicted by the NN.
"""correct_X_RGB = [X_full_RGB[i] for i in correct_indices]
correct_reconstructed_pixels = [reconstructed_pixels[i] for i in correct_indices]
utilities.export_as_atlas(correct_X_RGB, correct_reconstructed_pixels,
                          name_prefix='FORCED_TYPES_' + poke_type_1 + '_' + poke_type_2, name_annotations='correct')
"""


"""
This program allows to run Robobo Gym Environment as a module
"""

import numpy as np
import cv2
import zmq
from gym import spaces
import torch as th
import matplotlib.pyplot as plt
import seaborn as sns

from environments.srl_env import SRLGymEnv
from real_robots.constants import SERVER_PORT, HOSTNAME, MAX_STEPS
from real_robots.utils import recvMatrix
from state_representation.episode_saver import EpisodeSaver

RENDER_HEIGHT = 224
RENDER_WIDTH = 224
RELATIVE_POS = False

N_DISCRETE_ACTIONS = 4

# Init seaborn
sns.set()

def getGlobals():
    """
    :return: (dict)
    """
    return globals()

def bgr2rgb(bgr_img):
    """
    Convert an image from BGR to RGB
    :param bgr_img: np.ndarray
    :return: np.ndarray
    """
    return cv2.cvtColor(bgr_img, cv2.COLOR_BGR2RGB)

class RoboboEnv(SRLGymEnv):
    """
    Robobo robot Environment (Gym wrapper for Robobo Gazebo environment)
    The goal of robobo is to go to the location on the table
    (signaled with a circle sticker on the table)
    :param renders: (bool) Whether to display the GUI or not
    :param is_discrete: (bool) true if action space is discrete vs continuous
    :param log_folder: (str) name of the folder where recorded data will be stored
    :param state_dim: (int) When learning states
    :param learn_states: (bool)
    :param record_data: (bool) Set to true, record frames with the rewards.
    :param shape_reward: (bool) Set to true, reward = -distance_to_goal
    :param env_rank: (int) the number ID of the environment
    :param srl_pipe: (Queue, [Queue]) contains the input and output of the SRL model
    """

    def __init__(self, renders=False, is_discrete=True, log_folder="robobo_log_folder", state_dim=-1,
                 learn_states=False, srl_model="raw_pixels", record_data=False,
                 shape_reward=False, env_rank=0, srl_pipe=None):

        super(RoboboEnv, self).__init__(srl_model=srl_model,
                                        relative_pos=RELATIVE_POS,
                                        env_rank=env_rank,
                                        srl_pipe=srl_pipe)
        self.n_contacts = 0
        use_ground_truth = srl_model == 'ground_truth'
        use_srl = srl_model != 'raw_pixels'
        self.use_srl = use_srl or use_ground_truth
        self.use_ground_truth = use_ground_truth
        self.use_joints = False
        self.relative_pos = RELATIVE_POS
        self._is_discrete = is_discrete
        self.observation = []
        # Start simulation with first observation
        self._env_step_counter = 0
        self.episode_terminated = False
        self.state_dim = state_dim
        self._renders = renders
        self._shape_reward = shape_reward
        self.cuda = th.cuda.is_available()
        self.target_pos = None
        self.saver = None

        if self._is_discrete:
            self.action_space = spaces.Discrete(N_DISCRETE_ACTIONS)
        else:
            action_dim = 2
            self._action_bound = 1
            action_bounds = np.array([self._action_bound] * action_dim)
            self.action_space = spaces.Box(-action_bounds, action_bounds, dtype=np.float32)
        # SRL model
        if self.use_srl:
            if use_ground_truth:
                self.state_dim = self.getGroundTruthDim()
            self.dtype = np.float32
            self.observation_space = spaces.Box(low=-np.inf, high=np.inf, shape=(self.state_dim,), dtype=self.dtype)
        else:
            self.dtype = np.uint8
            self.observation_space = spaces.Box(low=0, high=255, shape=(RENDER_WIDTH, RENDER_HEIGHT, 3),
                                                dtype=self.dtype)

        if record_data:
            print("Recording data...")
            self.saver = EpisodeSaver(log_folder, 0, self.state_dim, globals_=getGlobals(),
                                      relative_pos=RELATIVE_POS,
                                      learn_states=learn_states)

        # Initialize Baxter effector by connecting to the Gym bridge ROS node:
        self.context = zmq.Context()
        self.socket = self.context.socket(zmq.PAIR)
        self.socket.connect("tcp://{}:{}".format(HOSTNAME, SERVER_PORT))

        # note: if takes too long, run first client, then server
        print("Waiting for server connection...")
        msg = self.socket.recv_json()
        print("Connected to server (received message: {})".format(msg))

        self.action = [0, 0]
        self.reward = 0
        self.robobo_pos = np.array([0, 0])

        # Initialize the state
        if self._renders:
            self.image_plot = None

    def step(self, action):
        """
        :action: (int)
        :return: (tensor (np.ndarray)) observation, int reward, bool done, dict extras)
        """
        assert self.action_space.contains(action)
        # Convert int action to action in (x,y,z) space
        self.action = action
        self._env_step_counter += 1

        # Send the action to the server
        self.socket.send_json({"command": "action", "action": self.action})

        # Receive state data (position, etc), important to update state related values
        self.getEnvState()

        #  Receive a camera image from the server
        self.observation = self.getObservation()
        done = self._hasEpisodeTerminated()
        if self.saver is not None:
            self.saver.step(self.observation, action, self.reward, done, self.getGroundTruth())
        if self.use_srl:
            return self.getSRLState(self.observation), self.reward, done, {}
        else:
            return self.observation, self.reward, done, {}

    def getEnvState(self):
        """
        Returns a dictionary containing info about the environment state.
        :return: (dict) state_data containing data related to the state: target_pos,
        robobo_pos and reward.
        """
        state_data = self.socket.recv_json()
        self.reward = state_data["reward"]
        self.target_pos = np.array(state_data["target_pos"])
        self.robobo_pos = np.array(state_data["position"])

        return state_data

    def getObservation(self):
        """
        Receive the observation image using a socket
        :return: (numpy ndarray) observation
        """
        # Receive a camera image from the server
        self.observation = recvMatrix(self.socket)
        # Resize it:
        self.observation = cv2.resize(self.observation, (RENDER_WIDTH, RENDER_HEIGHT), interpolation=cv2.INTER_AREA)
        return self.observation

    def getTargetPos(self):
        """
        :return (numpy array): Position of the target (button)
        """
        return self.target_pos

    @staticmethod
    def getGroundTruthDim():
        """
        :return: (int)
        """
        return 2

    def getGroundTruth(self):
        """
        Alias for getRoboboPos for compatibility between envs
        :return: (numpy array)
        """
        return np.array(self.getRoboboPos())

    def getRoboboPos(self):
        """
        :return: ([float])->  np.ndarray Position (x, y, z) of Baxter left gripper
        """
        return self.robobo_pos

    def reset(self):
        """
        Reset the environment
        :return: (numpy ndarray) first observation of the env
        """
        self.episode_terminated = False
        # Step count since episode start
        self._env_step_counter = 0
        self.socket.send_json({"command": "reset"})
        # Update state related variables, important step to get both data and
        # metadata that allow reading the observation image
        self.getEnvState()
        self.observation = self.getObservation()
        if self.saver is not None:
            self.saver.reset(self.observation, self.getTargetPos(), self.getGroundTruth())
        if self.use_srl:
            return self.getSRLState(self.observation)
        else:
            return self.observation

    def _hasEpisodeTerminated(self):
        """
        Returns True if the episode is over and False otherwise
        """
        if self.episode_terminated or self._env_step_counter > MAX_STEPS:
            return True
        return False

    def closeServerConnection(self):
        """
        To be called at the end of running the program, externally
        """
        print("Robobo_env client exiting and closing socket...")
        self.socket.send_json({"command": "exit"})
        self.socket.close()

    def render(self, mode='rgb_array'):
        """
        :param mode: (str)
        :return: (numpy array) BGR image
        """
        if mode != "rgb_array":
            print('render in human mode not yet supported')
            return np.array([])

        if self._renders:
            plt.ion()  # needed for interactive update
            if self.image_plot is None:
                plt.figure('Robobo RL')
                self.image_plot = plt.imshow(bgr2rgb(self.observation), cmap='gray')
                self.image_plot.axes.grid(False)
            else:
                self.image_plot.set_data(bgr2rgb(self.observation))
            plt.draw()
            # Wait a bit, so that plot is visible
            plt.pause(0.0001)
        return self.observation


import torch
from torch import nn

# ====================================================
# 如何初始化模型参数--Model
# ====================================================
class CustomModel(nn.Module):
    def __init__(self, cfg, config_path=None, pretrained=False):
        super().__init__()
        self.cfg = cfg
        self.fc_dropout = nn.Dropout(cfg.fc_dropout)
        self.fc = nn.Linear(self.config.hidden_size, self.cfg.target_size)
        self._init_weights(self.fc)
        self.attention = nn.Sequential(
            nn.Linear(self.config.hidden_size, 512),
            nn.Tanh(),
            nn.Linear(512, 1),
            nn.Softmax(dim=1)
        )
        self._init_weights(self.attention)

    def _init_weights(self, module):
        '''
        :初始化参数
        xavier初始化：nn.init.xavier_normal_(m.weight.data)
        kaiming初始化：nn.init.kaiming_normal_(m.weight.data)
        '''
        if isinstance(module, nn.Linear):  # linear层
            module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
            if module.bias is not None:
                module.bias.data.zero_()
        elif isinstance(module, nn.Embedding):  # embedding层
            module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
            if module.padding_idx is not None:
                module.weight.data[module.padding_idx].zero_()
        elif isinstance(module, nn.LayerNorm):  # layernorm层
            module.bias.data.zero_()
            module.weight.data.fill_(1.0)

    def feature(self, inputs):
        outputs = self.model(**inputs)
        last_hidden_states = outputs[0]  #last_hidden_states: torch.Size([16, 133, 1024])
#         print('last_hidden_states:',last_hidden_states.shape)
        # feature = torch.mean(last_hidden_states, 1)
        weights = self.attention(last_hidden_states)  # weights: torch.Size([16, 133, 1])
#         print('weights:',weights.shape)
        feature = torch.sum(weights * last_hidden_states, dim=1)  #[16,1024] attention
        return feature

    def forward(self, inputs):
        feature = self.feature(inputs)
        output = self.fc(self.fc_dropout(feature))
        return output