import argparse
import logging
import os, json, math, time, shutil
import numpy as np

import pathlib2
import tensorflow as tf

DEVELOP_MODE = False
NBUCKETS = 5 # for embeddings
NUM_EXAMPLES = 1000*1000 * 20 # assume 20 million examples
DNN_HIDDEN_UNITS = '128,64,32'

CSV_COLUMNS  = ('duration,end_station_id,bike_id,ts,day_of_week,start_station_id' +
                ',start_latitude,start_longitude,end_latitude,end_longitude' +
                ',euclidean,loc_cross,prcp,max,min,temp,dewp').split(',')
LABEL_COLUMN = 'duration'
DEFAULTS     = [[0.0],['na'],['na'],[0.0],['na'],['na'],
               [0.0],[0.0],[0.0],[0.0],
               [0.0],['na'],[0.0],[0.0],[0.0],[0.0], [0.0]]

STRATEGY = tf.distribute.MirroredStrategy()
TRAIN_BATCH_SIZE = 64 * STRATEGY.num_replicas_in_sync

def load_dataset(pattern, batch_size=1):
  return tf.data.experimental.make_csv_dataset(pattern, batch_size, CSV_COLUMNS, DEFAULTS)

def features_and_labels(features):
  label = features.pop('duration') # this is what we will train for
  features.pop('bike_id')
  return features, label

def read_dataset(pattern, batch_size, mode=tf.estimator.ModeKeys.TRAIN, truncate=None):
  dataset = load_dataset(pattern, batch_size)
  dataset = dataset.map(features_and_labels, num_parallel_calls=tf.data.experimental.AUTOTUNE)
  if mode == tf.estimator.ModeKeys.TRAIN:
    dataset = dataset.repeat().shuffle(batch_size*10)
    # dataset = dataset.repeat()
  dataset = dataset.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)
  # dataset = dataset.prefetch(1)
  if truncate is not None:
    dataset = dataset.take(truncate)
  return dataset

# Build a wide-and-deep model.
def wide_and_deep_classifier(inputs, linear_feature_columns, dnn_feature_columns,
    dnn_hidden_units, learning_rate):
    deep = tf.keras.layers.DenseFeatures(dnn_feature_columns, name='deep_inputs')(inputs)
    layers = [int(x) for x in dnn_hidden_units.split(',')]
    for layerno, numnodes in enumerate(layers):
        deep = tf.keras.layers.Dense(numnodes, activation='relu', name='dnn_{}'.format(layerno+1))(deep)
    wide = tf.keras.layers.DenseFeatures(linear_feature_columns, name='wide_inputs')(inputs)
    both = tf.keras.layers.concatenate([deep, wide], name='both')
    output = tf.keras.layers.Dense(1, name='dur')(both)
    model = tf.keras.Model(inputs, output)
    optimizer = tf.keras.optimizers.RMSprop(learning_rate)
    model.compile(loss='mse', optimizer=optimizer,
                 metrics=['mse', 'mae'])
    return model

def create_model(learning_rate, load_checkpoint):

  # duration,end_station_id,bike_id,ts,day_of_week,start_station_id,start_latitude,start_longitude,end_latitude,end_longitude,
  # euclidean,loc_cross,prcp,max,min,temp,dewp

  real = {
      colname : tf.feature_column.numeric_column(colname)
            for colname in
  #            ('ts,start_latitude,start_longitude,end_latitude,end_longitude,euclidean,prcp,max,min,temp,dewp').split(',')
              ('ts,euclidean,prcp,max,min,temp,dewp').split(',')

  }
  sparse = {
        'day_of_week': tf.feature_column.categorical_column_with_vocabulary_list('day_of_week',
                    vocabulary_list='1,2,3,4,5,6,7'.split(',')),
        'end_station_id' : tf.feature_column.categorical_column_with_hash_bucket('end_station_id', hash_bucket_size=800),
        'start_station_id' : tf.feature_column.categorical_column_with_hash_bucket('start_station_id', hash_bucket_size=800),
        'loc_cross' : tf.feature_column.categorical_column_with_hash_bucket('loc_cross', hash_bucket_size=21000),
  #      'bike_id' : tf.feature_column.categorical_column_with_hash_bucket('bike_id', hash_bucket_size=14000)
  }

  inputs = {
      colname : tf.keras.layers.Input(name=colname, shape=(), dtype='float32')
            for colname in real.keys()
  }
  inputs.update({
      colname : tf.keras.layers.Input(name=colname, shape=(), dtype='string')
            for colname in sparse.keys()
  })

  # embed all the sparse columns
  embed = {
         'embed_{}'.format(colname) : tf.feature_column.embedding_column(col, 10)
            for colname, col in sparse.items()
  }
  real.update(embed)

  # one-hot encode the sparse columns
  sparse = {
      colname : tf.feature_column.indicator_column(col)
            for colname, col in sparse.items()
  }

  if DEVELOP_MODE:
      print(sparse.keys())
      print(real.keys())

  model = None
  print('num replicas...')
  print(STRATEGY.num_replicas_in_sync)

  with STRATEGY.scope():
    if load_checkpoint:
      learning_rate = 0.0000001
    logging.info("using learning rate {}".format(learning_rate))
    model = wide_and_deep_classifier(
        inputs,
        linear_feature_columns = sparse.values(),
        dnn_feature_columns = real.values(),
        dnn_hidden_units = DNN_HIDDEN_UNITS,
        learning_rate=learning_rate)
    if load_checkpoint:
      logging.info("loading model weights from {}".format(load_checkpoint))
      model.load_weights(load_checkpoint)

  model.summary()
  return model

def main():

  logging.getLogger().setLevel(logging.INFO)
  parser = argparse.ArgumentParser(description='ML Trainer')
  parser.add_argument(
      '--epochs', type=int,
      default=1)
  parser.add_argument(
      '--steps-per-epoch', type=int,
      default=-1)  # if set to -1, don't override the normal calcs for this
  parser.add_argument(
      '--workdir',
      required=True)
  parser.add_argument(
      '--data-dir',
      default='gs://aju-dev-demos-codelabs/bikes_weather/')
  # use this arg to load the model weights from a pre-existing checkpoint (this is not the
  # same as the 'checkpoint_path'). These weights must be from a model of the same architecture.
  parser.add_argument(
      '--load-checkpoint',
      )
  parser.add_argument(
      '--train-output-path',
      )

  args = parser.parse_args()
  logging.info("Tensorflow version " + tf.__version__)

  TRAIN_DATA_PATTERN = args.data_dir + "train*"
  EVAL_DATA_PATTERN = args.data_dir + "test*"
  OUTPUT_DIR='{}/bwmodel/trained_model'.format(args.workdir)
  logging.info('Writing trained model to {}'.format(OUTPUT_DIR))
  learning_rate = 0.001

  if DEVELOP_MODE:
    dataset = load_dataset(TRAIN_DATA_PATTERN)
    for n, data in enumerate(dataset):
      numpy_data = {k: v.numpy() for k, v in data.items()} # .numpy() works only in eager mode
      print(numpy_data)
      if n>3: break

    print("Checking input pipeline")
    one_item = read_dataset(TRAIN_DATA_PATTERN, batch_size=2, truncate=1)
    print(list(one_item)) # should print one batch of 2 items

  train_batch_size = TRAIN_BATCH_SIZE
  eval_batch_size = 1000
  if args.steps_per_epoch == -1:  # calc based on dataset size
    steps_per_epoch = NUM_EXAMPLES // train_batch_size
  else:
    steps_per_epoch = args.steps_per_epoch
  logging.info('using {} steps per epoch'.format(steps_per_epoch))

  train_dataset = read_dataset(TRAIN_DATA_PATTERN, train_batch_size)
  eval_dataset = read_dataset(EVAL_DATA_PATTERN, eval_batch_size, tf.estimator.ModeKeys.EVAL,
     eval_batch_size * 100 * STRATEGY.num_replicas_in_sync
  )

  model = create_model(learning_rate, args.load_checkpoint)

  checkpoint_path = '{}/checkpoints/bikes_weather.cpt'.format(OUTPUT_DIR)
  logging.info("checkpoint path: %s", checkpoint_path)
  cp_callback = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
                                                   save_weights_only=True,
                                                   verbose=1)
  tb_callback = tf.keras.callbacks.TensorBoard(log_dir='{}/logs'.format(OUTPUT_DIR),
                                               update_freq=10000)

  logging.info("training model....")
  history = model.fit(train_dataset,
                      validation_data=eval_dataset,
                      validation_steps=eval_batch_size,
                      epochs=args.epochs,
                      steps_per_epoch=steps_per_epoch,
                      callbacks=[cp_callback  # , tb_callback
                      ]
                     )
  logging.info(history.history.keys())

  ts = str(int(time.time()))
  export_dir = '{}/export/bikesw/{}'.format(OUTPUT_DIR, ts)
  logging.info('Exporting to {}'.format(export_dir))

  try:
    logging.info("exporting model....")
    tf.saved_model.save(model, export_dir)
    if args.train_output_path:
      logging.info("train_output_path: %s", args.train_output_path)
      pathlib2.Path(args.train_output_path).parent.mkdir(parents=True)
      export_path = '{}/export/bikesw'.format(OUTPUT_DIR)
      logging.info('export path: {}'.format(export_path))
      pathlib2.Path(args.train_output_path).write_text(export_path)
  except Exception as e:  # hmm. retry once if error
    logging.warning(e)
    logging.info("retrying...")
    time.sleep(10)
    logging.info("again ... exporting model....")
    tf.saved_model.save(model, export_dir)
    if args.train_output_path:
      logging.info("train_output_path: %s", args.train_output_path)
      pathlib2.Path(args.train_output_path).parent.mkdir(parents=True)
      export_path = '{}/export/bikesw'.format(OUTPUT_DIR)
      pathlib2.Path(args.train_output_path).write_text(export_path)

if __name__ == "__main__":
  main()


# attachedLocalSpace
#
# closestPolygonAndWeights
#   input:
#     p     a point in world space
#     mesh  a mesh node the p attach to
#
#   return:
#     the vertex id list of polygon nearest to p
#     vertex weights with which the point on nearest polygon can be combined.
#
import pymel.core as pm
import pymel.core.datatypes as dt
import maya.cmds as cmds
import maya.OpenMaya as om

def pointInTriangle(a,b,c,p):
    v0 = b - a
    v1 = c - a
    v2 = p - a

    dot00 = v0.dot(v0)
    dot01 = v0.dot(v1)
    dot02 = v0.dot(v2)
    dot11 = v1.dot(v1)
    dot12 = v1.dot(v2)

    inverDeno = 1 / (dot00 * dot11 - dot01 * dot01)

    u = (dot11 * dot02 - dot01 * dot12) * inverDeno
    v = (dot00 * dot12 - dot01 * dot02) * inverDeno

    if v < -1e-3 or v > 1 or u < -1e-3 or u > 1:
        return False,u,v

    return u + v <= 1 + 1e-3,u,v

def meshNodeAndMatrix(mesh):
    meshNode = pm.PyNode(mesh)
    parentNode = meshNode.parent(0)
    invWorldMat = parentNode.worldInverseMatrix.get()
    worldMat = parentNode.worldMatrix.get()
    return meshNode, worldMat, invWorldMat

def createMeshIntersector(mesh):
    meshNode, worldMat, invWorldMat = meshNodeAndMatrix(mesh)
    itersector = om.MMeshIntersector()
    # triIdArray = om.MIntArray()
    # for i in triIdList:
    #     triIdArray.append(i)

    om.MMeshIntersector.create(itersector, meshNode.__apimobject__(), invWorldMat)
    return itersector

def closestPolygonAndWeights(p, mesh, meshIntersector):
    meshNode, worldMat, invWorldMat = meshNodeAndMatrix(mesh)

    pointOnMesh = om.MPointOnMesh()
    meshIntersector.getClosestPoint(p, pointOnMesh)

    polyId = pointOnMesh.faceIndex()
    triId = pointOnMesh.triangleIndex()
    cp = pointOnMesh.getPoint()

    u_util = om.MScriptUtil()
    u_util.createFromDouble(0)
    u_ptr = u_util.asFloatPtr()

    v_util = om.MScriptUtil()
    v_util.createFromDouble(0)
    v_ptr = v_util.asFloatPtr()

    pointOnMesh.getBarycentricCoords(u_ptr, v_ptr)
    triVids = meshNode.getPolygonTriangleVertices(polyId, triId)
    return triVids, u_util.getFloat(u_ptr), v_util.getFloat(v_ptr)

def closestMatrix(u, v, mesh, vids):
    meshNode, worldMat, invWorldMat = meshNodeAndMatrix(mesh)

    p3 = [ dt.Point(meshNode.getPoint(i)) * worldMat for i in vids ]
    xAxis = p3[1] - p3[0];
    zAxis = p3[2] - p3[0];

    orgP = p3[0] + xAxis * u + zAxis * v;

    yAxis = xAxis.cross(zAxis);
    yAxis.normalize();
    xAxis.normalize();
    zAxis = xAxis.cross(yAxis);
    zAxis.normalize();

    return dt.Matrix(
        xAxis.x, xAxis.y, xAxis.z, 0.0,
        yAxis.x, yAxis.y, yAxis.z, 0.0,
        zAxis.x, zAxis.y, zAxis.z, 0.0,
        orgP.x, orgP.y, orgP.z, 1.0 );

def makeAttachLocalSpace(attachedTransNode, mesh, pIds, wList):
    if not cmds.pluginInfo("skelTree",q=True,l=True):
        cmds.loadPlugin("skelTree")

    node = cmds.createNode("attachedLocalSpace")
    cmds.connectAttr("{}.outMesh".format(mesh),"{}.inMesh".format(node))

    transNode = cmds.listRelatives(mesh, p=True)[0]
    cmds.connectAttr("{}.worldMatrix".format(transNode),"{}.inWorldMatrix".format(node))
    for i in range(len(pIds)):
        cmds.setAttr("{}.mInPList[{}].inPntId".format(node, i), pIds[i])
        cmds.setAttr("{}.mInPList[{}].inWeight".format(node, i), wList[i])

    rootTransNode = cmds.group(em=True, n="attachedGroup")
    cmds.connectAttr("{}.outTranslate".format(node), "{}.translate".format(rootTransNode),f=True)
    cmds.connectAttr("{}.outRotate".format(node), "{}.rotate".format(rootTransNode),f=True)
    cmds.parent(attachedTransNode, rootTransNode)

def transformAttachToMesh(transNode, mesh):
    p=cmds.xform(transNode, q=True, ws=True, t=True)
    vIds, w = closestPolygonAndWeights(dt.Point(p), mesh)
    makeAttachLocalSpace(transNode, mesh, vIds, w)

def transformAttachToMeshSel():
    transList = cmds.ls(sl=True)
    if len(transList) < 2:
        print("Two nodes should be selected! the first one should be attached node and the second one should be target mesh.")

    targetMesh = cmds.ls(transList[-1],dag=True,type="mesh",noIntermediate=True)[0]
    for trans in transList[:-1]:
        transformAttachToMesh(trans, targetMesh)

# transformAttachToMeshSel()


import requests
from bs4 import BeautifulSoup
import numpy as np
import pandas as pd
# import time

url = r'https://oilprice.com/'

# Request
r1 = requests.get(url)
r1.status_code

# We'll save in coverpage the cover page content
coverpage = r1.content

# Soup creation
soup1 = BeautifulSoup(coverpage, 'html5lib')

# This doesn't work with oilprice.com!
coverpage_news = soup1.find_all('h2', class_='newsBlock__title')
len(coverpage_news)

coverpage_news[0].get_text()
coverpage_news[-1].get_text()

for data in soup1.find_all('h2'):
    print(data)

almsot_data = soup1.find_all('div', class_='newsBlock')
type(almsot_data) # == bs4.element.ResultSet
len(almsot_data )
first_half_almost_data = almsot_data[0]

data  = first_half_almost_data.find_all('a', class_='newsBlock__article')
data[0]['href']
data[0].get_text()


#!/usr/bin/env python

import sys
from dataclasses import replace
from enum import IntEnum
from parser.parser.exceptions import (
    MissingNonTerminalTypes,
    MissingRootNonTerminalType,
    ParseError,
    UnexpectedNonTerminalTypes,
)
from parser.parser.models import (
    ConcatenationExpression,
    ConjunctionExpression,
    Expression,
    NonTerminalExpression,
    OptionalExpression,
    RepeatExpression,
    TerminalExpression,
    Tree,
)
from parser.tokenizer.tokenizer import Token
from typing import Dict, List, Optional, Set

class Parser:
    def __init__(
        self,
        *,
        filename: str,
        code: str,
        tokens: List[Token],
        non_terminal_rules: Dict[IntEnum, Expression],
        pruned_non_terminals: Set[IntEnum],
        root_token: str = "ROOT",
        verbose: bool = False,
    ) -> None:
        self.filename = filename
        self.code = code
        self.tokens = tokens
        self.non_terminal_rules = non_terminal_rules
        self.pruned_non_terminals = pruned_non_terminals
        self.root_token = root_token
        self.verbose = verbose

    def parse(self) -> Tree:
        self._check_non_terminal_rules()

        non_terminal_enum_type = type(next(iter(self.non_terminal_rules.keys())))
        root_non_terminal = non_terminal_enum_type[self.root_token]
        root_expr = self.non_terminal_rules[root_non_terminal]

        tree = self._parse(root_expr, 0)
        tree.token_type = root_non_terminal

        if tree.token_count != len(self.tokens):
            assert tree.token_count < len(self.tokens)
            first_unexpected_token = self.tokens[tree.token_count]
            raise ParseError(self.filename, self.code, first_unexpected_token.offset)

        empty_tree = Tree(0, 0, root_non_terminal, [])

        pruned_tree = _prune_no_token_type(tree) or empty_tree

        pruned_tree = (
            _prune_by_token_types(pruned_tree, self.pruned_non_terminals) or empty_tree
        )

        return pruned_tree

    def _print_parse_debug_info(self, expr: Expression, offset: int) -> None:
        if not self.verbose:
            return

        expr_token_type = "<None>"
        if isinstance(expr, (TerminalExpression, NonTerminalExpression)):
            expr_token_type = expr.token_type.name

        if offset >= len(self.tokens):
            token_type = "<EOF>"
        else:
            token_type = self.tokens[offset].type.name

        print(
            f"DEBUG | Parser"
            + f" | offset={offset:>5}"
            + f" | token_type={token_type:>30}"
            + f" | try to match with {expr_token_type:>30}",
            file=sys.stderr,
        )

    def _parse(self, expr: Expression, offset: int) -> Tree:
        self._print_parse_debug_info(expr, offset)

        if offset >= len(self.tokens):

            if isinstance(expr, (RepeatExpression, OptionalExpression)):
                # No more tokens available, but we don't need any
                return Tree(offset, 0, None, [])

            raise ParseError(self.filename, self.code, offset)

        parse_funcs = {
            ConcatenationExpression: self._parse_concatenation,
            ConjunctionExpression: self._parse_conjunction,
            NonTerminalExpression: self._parse_non_terminal,
            OptionalExpression: self._parse_optional,
            RepeatExpression: self._parse_repeat,
            TerminalExpression: self._parse_terminal,
        }

        # Should not fail, so if this raises a KeyError, we want the parser to crash.
        parse_func = parse_funcs[type(expr)]

        return parse_func(expr, offset)

    def _parse_conjunction(self, expr: Expression, offset: int) -> Tree:
        assert isinstance(expr, ConjunctionExpression)

        parsed: Optional[Tree] = None

        for child in expr.children:
            try:
                parsed = self._parse(child, offset)
                break
            except ParseError:
                continue

        if not parsed:
            raise ParseError(self.filename, self.code, offset)

        return Tree(
            parsed.token_offset,
            parsed.token_count,
            None,
            [parsed],
        )

    def _parse_repeat(self, expr: Expression, offset: int) -> Tree:
        assert isinstance(expr, RepeatExpression)

        children: List[Tree] = []
        child_offset = offset

        while True:
            try:
                parsed = self._parse(expr.child, child_offset)
            except ParseError:
                break
            else:
                children.append(parsed)
                child_offset += parsed.token_count

        return Tree(
            offset,
            child_offset - offset,
            None,
            children,
        )

    def _parse_optional(self, expr: Expression, offset: int) -> Tree:
        assert isinstance(expr, OptionalExpression)

        children: List[Tree] = []
        length = 0

        try:
            parsed = self._parse(expr.child, offset)
            children = [parsed]
            length = parsed.token_count
        except ParseError:
            pass

        return Tree(
            offset,
            length,
            None,
            children,
        )

    def _parse_concatenation(self, expr: Expression, offset: int) -> Tree:
        assert isinstance(expr, ConcatenationExpression)

        sub_trees: List[Tree] = []

        child_offset = offset

        for child in expr.children:
            parsed = self._parse(child, child_offset)
            sub_trees.append(parsed)
            child_offset += parsed.token_count

        return Tree(
            offset,
            child_offset - offset,
            None,
            sub_trees,
        )

    def _parse_terminal(self, expr: Expression, offset: int) -> Tree:
        assert isinstance(expr, TerminalExpression)

        if self.tokens[offset].type != expr.token_type:
            raise ParseError(self.filename, self.code, offset)

        return Tree(offset, 1, expr.token_type, [])

    def _parse_non_terminal(self, expr: Expression, offset: int) -> Tree:
        assert isinstance(expr, NonTerminalExpression)

        non_terminal_expansion = self.non_terminal_rules[expr.token_type]
        child = self._parse(non_terminal_expansion, offset)
        return Tree(child.token_offset, child.token_count, expr.token_type, [child])

    def _check_non_terminal_rules(self) -> None:
        tokens_enum = type(list((self.non_terminal_rules.keys()))[0])

        unexpected_keys = self.non_terminal_rules.keys() - set(tokens_enum)
        missing_keys: Set[IntEnum] = set(tokens_enum) - self.non_terminal_rules.keys()

        if "ROOT" not in tokens_enum.__members__:
            raise MissingRootNonTerminalType

        if missing_keys:
            raise MissingNonTerminalTypes(missing_keys)

        if unexpected_keys:
            raise UnexpectedNonTerminalTypes(unexpected_keys)

def _get_descendants_without_token_types(
    tree: Tree, token_types: Set[IntEnum]
) -> List[Tree]:
    with_token_type: List[Tree] = []

    for child in tree.children:
        if child.token_type in token_types:
            with_token_type += _get_descendants_without_token_types(child, token_types)
        else:
            with_token_type.append(
                replace(
                    child,
                    children=_get_descendants_without_token_types(child, token_types),
                )
            )

    return with_token_type

def _prune_by_token_types(tree: Tree, token_types: Set[IntEnum]) -> Optional[Tree]:
    descendants_with_token_type = _get_descendants_without_token_types(
        tree, token_types
    )

    children = [
        Tree(
            child.token_offset,
            child.token_count,
            child.token_type,
            _get_descendants_without_token_types(child, token_types),
        )
        for child in descendants_with_token_type
    ]

    return Tree(tree.token_offset, tree.token_count, tree.token_type, children)

def _get_descendants_with_token_type(tree: Tree) -> List[Tree]:
    with_token_type: List[Tree] = []

    for child in tree.children:
        if child.token_type is None:
            with_token_type += _get_descendants_with_token_type(child)
        else:
            with_token_type.append(
                replace(child, children=_get_descendants_with_token_type(child))
            )

    return with_token_type

def _prune_no_token_type(tree: Tree) -> Optional[Tree]:
    assert tree.token_type is not None

    return Tree(
        tree.token_offset,
        tree.token_count,
        tree.token_type,
        _get_descendants_with_token_type(tree),
    )


import copy
import os
import torch

class StateCacher(object):
    def __init__(
            self,
            model,
            optimizer,
            criterion,
            memory_cache=True,
            cache_dir=None,
    ):
        # Check if the optimizer is already attached to a scheduler
        self.optimizer = optimizer
        self._check_for_scheduler()

        self.model = model
        self.criterion = criterion
        self.in_memory = memory_cache
        self.cache_dir = cache_dir

        if self.cache_dir is None:
            import tempfile

            self.cache_dir = tempfile.gettempdir()
        else:
            if not os.path.isdir(self.cache_dir):
                raise ValueError("Given `cache_dir` is not a valid directory.")

        # Save the original state of the model and optimizer so they can be restored if
        # needed
        self.cached = {}
        self.model_device = next(self.model.parameters()).device
        self.store("model", self.model.state_dict())
        self.store("optimizer", self.optimizer.state_dict())

    def store(self, key, state_dict):
        if self.in_memory:
            self.cached.update({key: copy.deepcopy(state_dict)})
        else:
            fn = os.path.join(self.cache_dir, "state_{}_{}.pt".format(key, id(self)))
            self.cached.update({key: fn})
            torch.save(state_dict, fn)

    def retrieve(self, key):
        if key not in self.cached:
            raise KeyError("Target {} was not cached.".format(key))

        if self.in_memory:
            return self.cached.get(key)
        else:
            fn = self.cached.get(key)
            if not os.path.exists(fn):
                raise RuntimeError(
                    "Failed to load state in {}. File doesn't exist anymore.".format(fn)
                )
            state_dict = torch.load(fn, map_location=lambda storage, location: storage)
            return state_dict

    def _check_for_scheduler(self):
        for param_group in self.optimizer.param_groups:
            if "initial_lr" in param_group:
                raise RuntimeError("Optimizer already has a scheduler attached to it")

    def reset(self):
        """Restores the model and optimizer to their initial states."""

        self.model.load_state_dict(self.retrieve("model"))
        self.optimizer.load_state_dict(self.retrieve("optimizer"))
        self.model.to(self.model_device)

    def __del__(self):
        """Check whether there are unused cached files existing in `cache_dir` before
        this instance being destroyed."""

        if self.in_memory:
            return

        for k in self.cached:
            if os.path.exists(self.cached[k]):
                os.remove(self.cached[k])


#!/bin/python3

import argparse
import shutil
import os

PATH_BACKEND = "/home/exploit/backend/"

vuln_manager_src = 'vuln_manager_samples/%s.xml'
vuln_manager_dst = PATH_BACKEND + 'vulnerability_manager/nvd_db/nvdcve-2.0-Demo.xml'

rss_server_src = 'rss_server/entries_rss/%s.xml'
rss_server_dst = 'rss_server/enabled_entries_rss/%s.xml'

def simulate(test_name):

    path = '/'.join(vuln_manager_dst.split('/')[:-1])

    if not os.path.isdir(path):
        os.makedirs(path, True)
    shutil.copy(vuln_manager_src % (test_name), vuln_manager_dst)

    path = '/'.join(rss_server_dst.split('/')[:-1])
    if not os.path.isdir(path):
        os.makedirs(path, True)
    shutil.copy(rss_server_src % (test_name), rss_server_dst % (test_name))

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('testName', type=str)

    args = parser.parse_args()
    simulate(args.testName)


import logging
import os

from flask import Flask, render_template, redirect, url_for, request, send_from_directory

import settings
from instacard import lobadapter
from instacard.instagramadapter import InstagramAdapter
from instacard.repo import TinyRepo

logger = logging.getLogger(__name__)

def create_app():
    app = Flask(__name__)

    insta = InstagramAdapter(settings.USERNAME, settings.PASSWORD)
    repo = TinyRepo(settings.DB_URL)
    lobadapter.init(settings.LOB_API_KEY)

    @app.route('/')
    def index():
        usernames = repo.usernames()
        return render_template('index.html', usernames=usernames)

    @app.route('/favicon.ico')
    def fav():
        logger.warning(f'404 Fav: {request.referrer}')
        return send_from_directory(os.path.join(app.root_path, 'static'),
                               'instagram.png', mimetype='image/png')

    @app.route('/<username>')
    def posts(username):
        userinfo = insta.get_user_info(username)
        posts = []

        for p in insta.feed(userinfo.user_id):
            if not repo.check_done(username, p.media_id, p.carousel_index):
                posts.append(p)
        return render_template('posts.html', userinfo=userinfo, posts=posts)

    @app.route('/<username>/<media_id>/<int:carousel_index>/front')
    def front(username, media_id, carousel_index):
        userinfo = insta.get_user_info(username)
        postinfo = insta.post(media_id, carousel_index)

        if postinfo is None:
            logger.warning('no post found: %s, %s' % (username, media_id))
            return 'Post not found', 404

        return lobadapter.render_front(postinfo, userinfo)

    @app.route('/<username>/<media_id>/<int:carousel_index>/back')
    def back(username, media_id, carousel_index):
        userinfo = insta.get_user_info(username)
        postinfo = insta.post(media_id, carousel_index)

        if postinfo is None:
            logger.warning('no post found: %s, %s' % (username, media_id))
            return 'Post not found', 404

        return lobadapter.render_back(postinfo, userinfo)

    @app.route('/<username>/<media_id>/<int:carousel_index>/skip')
    def skip(username, media_id, carousel_index):
        if not repo.check_done(username, media_id, carousel_index):
            logger.info('skip %s, %s' % (username, media_id))
            repo.processed(username, media_id, carousel_index, True)
        else:
            logger.warning('already processed %s, %s' % (username, media_id))
        return redirect(url_for('posts', username=username))

    @app.route('/<username>/<media_id>/<int:carousel_index>/send_postcard')
    def send_postcard(username, media_id, carousel_index):
        if not repo.check_done(username, media_id, carousel_index):
            userinfo = insta.get_user_info(username)
            postinfo = insta.post(media_id, carousel_index)

            if postinfo is None:
                logger.warning('no post found: %s, %s' % (username, media_id))
                return redirect(url_for('posts', username=username))

            lobadapter.send_postcard(userinfo, postinfo, settings.default_address)
            logger.info('send_postcard %s, %s' % (username, media_id))
            repo.processed(username, postinfo.media_id, carousel_index, False)
        else:
            logger.warning('already processed %s, %s' % (username, media_id))
        return redirect(url_for('posts', username=username))

    return app


import os
import sys
import json

data = dict()
data["node"] = dict()
data["link"] = dict()

def loadDataDirectory(dirPath):
    '''
    Given the directory path to where the
    network tree is stored, this will traverse
    through the directory and grab all of the
    geojson files.
    '''
    for dirName, subDir, fileList in os.walk(dirPath):
        for fileName in fileList:
            if "json" in fileName:
                absPath = os.path.join(dirName, fileName)
                loadGeojson(absPath)

def loadGeojson(path):
    '''
    Opens given geojson file
    Checks the contents of the json file
    Sorts it by the type of content by storing it into
    a dict
    '''
    geofile = None
    geodata = None

    try:
        geofile = open(path, 'r')
        geodata = json.load(geofile)
    except Exception as e:
        print("{} does not exist or JSON file failed to parse\n{}\e".format(path,e))

    if not geodata:
        return
    if not "properties" in geodata:
        return
    if not "prmname" in geodata["properties"]:
        return

    #set directory path of geojson file to get csv files
    geodata["dirpath"] = os.path.dirname(path)
    # #set directory path of csv/other files related to geojson file
    # geodata["geofolder"] = os.path.join(geodata["dirpath"], geofolder)

    if geodata["properties"]["type"] in ['Diversion', 'Return Flow']:
        data["link"][geodata["properties"]["prmname"]] = geodata
    else:
        data["node"][geodata["properties"]["prmname"]] = geodata

def generatePRI():

    result = ''
    result += '..       ***** NODE DEFINITIONS *****\n'
    result += '..       \n'
    result += nodeData()

    result += '..       \n'
    result += '..       \n'
    result += '..       \n'
    result += 'LINK     DIVR     SOURCE    SINK    1.000    0.00\n'
    result += 'LD     Continuity Link\n'
    result += '..       \n'

    result += '..       ***** INFLOW DEFINITIONS *****\n'
    result += '..       \n'
    result += inflowData()
    result += '..       \n'

    result += '..       ***** STORAGE LINK DEFINITIONS *****\n'
    result += '..       \n'
    result += rstoData()

    result += divrData()
    result += "STOP\n"

    return result

def nodeData():
    nodeOutput = ''
    nodeSorted = data["node"].keys()
    nodeSorted.sort()

    for node in nodeSorted:
        geojson = data["node"][node]

        name = geojson["properties"]["prmname"]
        desc = geojson["properties"]["description"]
        initStorage = ''
        endStorage = ''
        areaCapFactor = ''

        if "initialstorage" in geojson["properties"]:
            initStorage = geojson["properties"]["initialstorage"]
        if "endingstorage" in geojson["properties"]:
            endStorage = geojson["properties"]["endingstorage"]
        if "areacapfactor" in geojson["properties"]:
            initStorage = geojson["properties"]["areacapfactor"]

        nodeOutput += "NODE     {} {} {} {}\n".format(name, initStorage, areaCapFactor, endStorage)
        nodeOutput += "ND       {}\n".format(desc)
        nodeOutput += "..         \n"

    return nodeOutput

def inflowData():
    inflowOutput = ''
    inflowSorted = data["node"].keys()
    inflowSorted.sort()

    for inflow in inflowSorted:
        geojson = data["node"][inflow]

        if not "inflows" in geojson["properties"] or not geojson["properties"]["inflows"]:
            continue

        name = geojson["properties"]["prmname"]

        desc = geojson["properties"]["inflows"]["default"]["description"]

        inflowOutput += "LINK      {:<10}{:<10}{:<10}{:<10}{:<10}\n".format("INFL","SOURCE", name, "1.000","0.00")
        #inflowOutput += "LINK      INFL      SOURCE    {}   1.000     0.00\n".format(name)
        inflowOutput += "LD        {}\n".format(desc)
        inflowOutput += "IN        A={} B={} C={} E={} F={}\n".format("","SOURCE_" + name, "FLOW_LOC(KAF)", "1MON", "")
        inflowOutput += "..        \n"

    return inflowOutput

def rstoData():
    rstoOutput = ''
    rstoSorted = data["node"].keys()
    rstoSorted.sort()

    for rsto in rstoSorted:
        geojson = data["node"][rsto]

        if not geojson["properties"]["type"] in ["Surface Storage", "Groundwater Storage"]:
            continue

        name = geojson["properties"]["prmname"]
        desc = geojson["properties"]["description"]
        costs = geojson["properties"]["costs"]

        bounds = ''
        if "bounds" in geojson["properties"]:
            bounds = geojson["properties"]["bounds"]

        boundTable = getBounds(geojson)

        lowerConst = boundTable["lowerConst"]
        upperConst = boundTable["upperConst"]
        BL = boundTable["BL"]
        BU = boundTable["BU"]
        QL = boundTable["QL"]
        QU = boundTable["QU"]
        EV = ''
        PS = ''
        LD = "LD        {}\n".format(desc)

        link = "LINK      {:<10}{:<10}{:<10}{:<10}{:<10}{:<10}\n".format("RSTO",name, name, "1.000",lowerConst,upperConst)

        #COSTS
        if costs["type"] == "Monthly Variable":
            EV = "EV        A={} B={} C={} F={}\n".format("",name,"EVAP_RATE(FT)", desc)
            for month in ["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"]:
                PS += "PS        MO={} A={} B={} C={} D={} E={} F={}\n".format(month,"UCD CAP1", name, "Q(K$-KAF)-P","",month,"")
        elif costs["type"] == "Annual Variable":
            monthLabel = "JAN-DEC"
            PS = "PS        MO={} A={} B={} C={} D={} E={} F={}\n".format(monthLabel,"UCD CAP1","DUMMY","Q(K$-KAF)-P","","", "")
        else: #All variables
            PS = "PS        MO={} A={} B={} C={} D={} E={} F={}\n".format("ALL","UCD CAP1","DUMMY","BLANK","","", "")

        QI = "QI        A={} B={} C={} D={} E={} F={}\n".format("", name, "STOR", "", "1MON", "")

        rstoOutput += link + LD + QL + QU + BL + BU + EV + PS + QI + "..      \n"

    return rstoOutput

def getBounds(geojson):
    boundsTable = dict()
    boundsTable["lowerConst"] = ''
    boundsTable["upperConst"] = ''
    boundsTable["BU"] = ''
    boundsTable["BL"] = ''
    boundsTable["QL"] = ''
    boundsTable["QU"] = ''

    boundsList = geojson["properties"]["bounds"]

    for bounds in boundsList:

        #list , months
        if bounds["type"] in ["LBM","UBM"]:
            filename = "{}.csv".format(bounds["type"])
            filepath = os.path.join(geojson["dirpath"], filename)
            boundscsv = open(filepath, 'r')
            boundslist = []
            for line in boundscsv:
                line = line.strip()
                splitdata = line.split(",")
                if splitdata[0] in ["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"]:
                    boundslist.append(splitdata[1])

            mboundkey = "BU"
            if bounds["type"] == "LBM":
                mboundkey = "BL"

            boundsTable[mboundkey] = "{}        {}\n".format(mboundkey, ','.join(boundslist))

        #constants
        if bounds["type"] == "LBC":
            boundsTable["lowerConst"] = bounds["bound"]
        if bounds["type"] == "UBC":
            boundsTable["upperConst"] = bounds["bound"]

        #Time Series
        if bounds["type"] == "LBT":
            boundsTable["QL"] = "QL        A={} B={} C={} D={} E={} F={}\n".format("",geojson["properties"]["prmname"], "STOR_LBC(KAF)","", "1MON", geojson["properties"]["description"])
        if bounds["type"] == "UBT":
            boundsTable["QU"] = "QU        A={} B={} C={} D={} E={} F={}\n".format("",geojson["properties"]["prmname"], "STOR_LBC(KAF)","", "1MON", geojson["properties"]["description"])

    return boundsTable

def divrData():
    divrOutput = ''
    divrSorted = data["link"].keys()
    divrSorted.sort()

    for divr in divrSorted:
        geojson = data["link"][divr]

        if geojson["properties"]["type"] != "Diversion":
            continue

        name      = geojson["properties"]["prmname"]
        origin    = geojson["properties"]["origin"]
        terminus = geojson["properties"]["terminus"]
        amplitude = geojson["properties"]["amplitude"]
        desc      = geojson["properties"]["description"]

        bounds = ''
        if "bounds" in geojson["properties"]:
            bounds = geojson["properties"]["bounds"]

        boundTable = getBounds(geojson)

        lowerConst = boundTable["lowerConst"]
        upperConst = boundTable["upperConst"]
        BL = boundTable["BL"]
        BU = boundTable["BU"]
        QL = boundTable["QL"]
        QU = boundTable["QU"]

        costTable = getCosts(geojson)
        cost = costTable["cost"]
        PQ = costTable["PQ"]

        QI = "QI        A={} B={} C={} D={} E={} F={}\n".format("", name, "FLOW_DIV(KAF)", "", "1MON", "")

        link = "LINK      {:<10}{:<10}{:<10}{:<10}{:<10}\n".format("DIVR",origin, terminus, amplitude, cost, lowerConst, upperConst)
        LD = "{:<10}{}\n".format("LD",desc)

        divrOutput += link + LD + QL + QU + BL + BU + PQ + QI + "..      \n"

    return divrOutput

def getCosts(geojson):
    costTable = dict()
    costTable["cost"] = ''
    costTable["PQ"] = ''
    costTable["QI"] = ''

    if not "costs" in geojson["properties"]:
        return costTable

    origin    = geojson["properties"]["origin"]
    terminus = geojson["properties"]["terminus"]
    costs = geojson["properties"]["costs"]

    if "cost" in costs:
        costTable["cost"] = costs["cost"]

    if costs["type"] == "Monthly Variable":
        PQ = ''
        for month in ["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"]:
            PQ += "{:<10}MO={} A={} B={} C={} D={} E={} F={}\n".format("PQ", month, "", origin + "_" + terminus, "Q(K$-KAF)", "", month, "", "")
        costTable["PQ"] = PQ
    else:
        costTable["PQ"] = "{:<10}MO={} A={} B={} C={} D={} E={} F={}\n".format("PQ", "ALL", "", "DUMMY", "BLANK", "", "", "", "")

    return costTable

if __name__ == '__main__':
    if len(sys.argv) == 2:
        loadDataDirectory(sys.argv[1])
        #print(generatePRI())
        # print(nodeData())
        # print(inflowData())
        # print(rstoData())
        print(divrData())


# ele usou reflect pra comparar com imageJ
import numpy as np
from numpy import asarray
from PIL import Image
from scipy import ndimage

# Funções de abrir a imagem do ImageJ

def openImageJ(path_image):
    image_in = Image.open(path_image)
    image_np = np.array(image_in)
    print('Imagem filtrada no ImageJ')
    printImage(image_np)

def printImage(image):
    print(image)
    print(image.dtype)
    print(image.min(), image.max())

# Função de converter a imagem em um numpy array
def converting(image):
    img_array = np.array(image).astype(int)
    print('Imagem Original')
    printImage(img_array)
    return img_array

# Função de realizar a convolução
def convolution(img_array, k):
    im = ndimage.convolve(img_array, k, mode='reflect')
    print("Imagem após somente a convolução")
    printMinMax(im)
    im = replaceNegativeValues(im)
    return im

# Função de exibir o máx e min
def printMinMax(im):
    print()
    print(im)
    print(im.min(),im.max())

# Função de converter para int para permitir valores negativos
def replaceNegativeValues(im):
    im = np.where(im < 0, 0, im)
    print('Imagem após convolução e substituição zero')
    printMinMax(im)
    return im

# Função de converter array em imagem tipo usint uint8
def convertUint8(im):
    image_out = Image.fromarray(im.astype('uint8'))
    image_out.show()
    return image_out

# Abrir Imagem Original
image = Image.open('../Images/Filo.jpg')
image.show()

#RESPOSTA DA ALTERNATIVA A
print('-------------------Alternativa A-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-a.tif')

# Converter imagem original em array
img_array = converting(image)

# Kernel (A) -  # Convolução usando filtro no modo reflect
K_A = np.array([[0, 0, 0],
                [0, 1, 0],
                [0, 0, 0]])

# Aplicando convolução
im = convolution(img_array, K_A)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/a.jpg')

#RESPOSTA DA ALTERNATIVA B

print('-------------------Alternativa B-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-b.tif')

# Kernel (B) -  # Convolução usando filtro no modo reflect
K_B = np.array([[1, 0, -1],
                [0, 0, 0],
                [-1, 0, 1]])

# Aplicando convolução
im = convolution(img_array, K_B)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/b.jpg')

#RESPOSTA DA ALTERNATIVA C

print('-------------------Alternativa C-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-c.tif')

# Kernel (C) -  # Convolução usando filtro no modo reflect
K_C = np.array([[0, -1, 0],
                [-1, 4, -1],
                [0, -1, 0]])

# Aplicando convolução
im = convolution(img_array, K_C)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/c.jpg')

#RESPOSTA DA ALTERNATIVA C

print('-------------------Alternativa D-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-d.tif')

# Kernel (D) -  # Convolução usando filtro no modo reflect
K_D = np.array([[-1, -1, -1],
                [-1, 8, -1],
                [-1, -1, -1]])

# Aplicando convolução
im = convolution(img_array, K_D)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/d.jpg')

print('-------------------Alternativa E-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-e.tif')

# Kernel (E) -  # Convolução usando filtro no modo reflect
K_E = np.array([[0, -1, 0],
                [-1, 5, -1],
                [0, -1, 0]])

# Aplicando convolução
im = convolution(img_array, K_E)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/e.jpg')

print('-------------------Alternativa F-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-f.tif')

# Kernel (F) -  # Convolução usando filtro no modo reflect
K_F = np.array([[1, 1, 1],
                [1, 1, 1],
                [1, 1, 1]])

# Multiplicando pela constante
result_f = K_F*(1/9)

# Aplicando convolução
im = convolution(img_array, result_f)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/f.jpg')

print('-------------------Alternativa G-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-g.tif')

# Kernel (G) -  # Convolução usando filtro no modo reflect
K_G = np.array([[1, 2, 1],
                [2, 4, 2],
                [1, 2, 1]])

# Multiplicando pela constante
result_g = K_G*(1/16)

# Aplicando convolução
im = convolution(img_array, result_g)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/g.jpg')

print('-------------------Alternativa H-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-h.tif')

# Kernel (H) -  # Convolução usando filtro no modo reflect
K_H = np.array([[1, 4, 6, 4, 1],
                [4, 16, 24, 16, 4],
                [6, 24, 36, 24, 6],
                [4, 16, 24, 16, 4],
                [1, 4, 6, 4, 1]])

# Multiplicando pela constante
result_h = K_H*(1/256)

# Aplicando convolução
im = convolution(img_array, result_h)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/h.jpg')

print('-------------------Alternativa I-----------------------')
# Imagem filtrada usando ImageJ para comparação
openImageJ('../Images/ImageJ/Filo-ImageJ-i.tif')

# Kernel (I) -  # Convolução usando filtro no modo reflect
K_I = np.array([[1, 4, 6, 4, 1],
                [4, 16, 24, 16, 4],
                [6, 24, -476, 24, 6],
                [4, 16, 24, 16, 4],
                [1, 4, 6, 4, 1]])

# Multiplicando pela constante
result_i = K_I * (-1/256)

# Aplicando convolução
im = convolution(img_array, result_i)

# Convertendo array em imagem tipo usint uint8 e salvando imagem
img_out = convertUint8(im)
img_out.save('../Images/i.jpg')


#!/usr/bin/python3

# from os import SCHED_OTHER
from enum import Enum, auto
from re import X
from which_pyqt import PYQT_VER
if PYQT_VER == 'PYQT5':
	from PyQt5.QtCore import QLineF, QPointF
elif PYQT_VER == 'PYQT4':
	from PyQt4.QtCore import QLineF, QPointF
else:
	raise Exception('Unsupported Version of PyQt: {}'.format(PYQT_VER))

import math

# Used to compute the bandwidth for banded version
MAXINDELS = 3
SEQRETURNLEN = 100

# Used to implement Needleman-Wunsch scoring
MATCH = -3
INDEL = 5
SUB = 1

# Indicates the direction the previous cell in the matrix
class Direction(Enum):
	LEFT = auto()
	TOP = auto()
	DIAGONAL = auto()

# Contains the costVal, previous cell which helped calculate that, and the direction the previous cell came from
# Space: O(1)
class Cost:
	def __init__(self, cost:int, prev:tuple, dir:Direction):
		self.costVal = cost
		self.prev = prev
		self.direction = dir

	def __eq__(self, other):
		return (self.costVal, self.prev, self.direction) == (other.costVal, other.prev, self.direction)

class GeneSequencing:
	def __init__( self ):
		pass

	# Print the cost dictionary
	def printDict(self, seq1, seq2):
		table_data = [[]]
		# Put the first row aka listing the seq1
		for i in range(-1, self.numColumns):
			if i == -1:
				table_data[0].append(" ")
			elif i == 0:
				table_data[0].append("_")
			else:
				table_data[0].append(seq1[i-1])

		for i in range(0, self.numRows):
			table_data.append([])
			last = len(table_data)-1
			for j in range(-1, self.numColumns):
				if j == -1 and i == 0:
					table_data[last].append("_")
				elif j == -1:
					table_data[last].append(seq2[i-1])
				else:
					string = "" #f"({i},{j}):"
					item = self.costDict.get(tuple((i, j)))
					if type(item) == Cost:
						string += f"{item.costVal}"
					else:
						string += " "
					table_data[last].append(string)

		formatString = "{: >5} "
		for row in table_data:
			for item in row:
				print(formatString.format(item), end="")
			print()
		print()

	# Traverse through the matrix and build up the alignment strings
	# Time: O(x), Space: O(1) [x=max(len(seq1), len(seq2))]
	def getAlignmentStrings(self, seq1, seq2, cell:tuple):
		alignment1, alignment2 = "", ""
		while not (cell[0] == 0 and cell[1] == 0):
			cost = self.costDict.get(cell)
			if cost.direction == Direction.LEFT:
				alignment1 += seq1[cell[1]-1]
				alignment2 += "-"
			elif cost.direction == Direction.TOP:
				alignment1 += "-"
				alignment2 += seq2[cell[0]-1]
			elif cost.direction == Direction.DIAGONAL:
				alignment1 += seq1[cell[1]-1]
				alignment2 += seq2[cell[0]-1]
			cell = cost.prev

		#Reverse strings and cut to 100, Time: O(x)
		return alignment1[::-1][:100], alignment2[::-1][:100]

	# Check the banded setting and return the value, Time: O(1)
	def checkBanded(self, trueVal, falseVal):
		if self.banded:
			return trueVal
		else:
			return falseVal

	# Given two sequences, find the optimal alignment of Insert/Deletion, Substitution or Match
	#    @required _seq1_(top of matrix) and _seq2_(side of matrix) are two sequences to be aligned
	#    @required _banded_ is a boolean for computing banded alignment or full alignment
	# 	 @required align_length_ = how many base pairs to use in computing the alignment
	# UNBAN_Time: O(mn) UNBAN_Space: O(mn) [seq1=m, seq2=n]
	# BAN_Time: O(kn) BAN_Space: O(kn) [k=2(MAXINDELS)+1, seq2=n]
	def align(self, seq1, seq2, banded, align_length):
		#Cut sequences and check for matching
		if len(seq1) > align_length:
			seq1 = seq1[:align_length]
		if len(seq2) > align_length:
			seq2 = seq2[:align_length]
		if seq1 == seq2:
			return {'align_cost':len(seq1)*MATCH, 'seqi_first100':seq1, 'seqj_first100':seq2}

		self.banded = banded
		self.numColumns = len(seq1)+1
		self.numRows = len(seq2)+1

		# CostDict => Key[tuple((rowIndex, columnIndex))] : [Cost(val:int, prevCellTuple, prevDirection)]
		# UNBAN_Space: O(mn), BAN_Space: O(kn)
		self.costDict = dict()

		self.costDict[tuple((0,0))] = Cost(0, None, None)

		# Fill first row, UNBAN_Time: O(n), BAN_Time: O(k+1)
		numFirstRow = self.checkBanded(min(1+MAXINDELS,self.numColumns), self.numColumns)
		for i in range(1, numFirstRow):
			self.costDict[tuple((0,i))] = Cost(i*INDEL, tuple((0, i-1)), Direction.LEFT)

		#Fill first col, UNBAN_Time: O(m), BAN_Time: O(k+1)
		numFirstCol = self.checkBanded(min(1+MAXINDELS,self.numRows), self.numRows)
		for i in range(1, numFirstCol):
			self.costDict[tuple((i,0))] = Cost(i*INDEL, tuple((i-1, 0)), Direction.TOP)

		#Run algorithm for all cells, UNBAN_Time: O((m-1)*(n-1)), BAN_Time: O(k*n)
		for rowIndex in range(1, self.numRows):
			colStart = self.checkBanded(max(rowIndex-MAXINDELS,1), 1)
			colEnd = self.checkBanded(min(rowIndex+MAXINDELS+1,self.numColumns), self.numColumns)

			# Calculate costs with priority: left > top > diagonal
			for colIndex in range(colStart, colEnd):
				minCost = Cost(math.inf, None, None)

				# Calculate diagonal cost if match/sub
				diagonalPrevCell = tuple((rowIndex-1, colIndex-1))
				diagonalPrevCost = self.costDict.get(diagonalPrevCell)
				if diagonalPrevCost is not None:
					diagonalCost = Cost(diagonalPrevCost.costVal, diagonalPrevCell, Direction.DIAGONAL)
					if (seq1[colIndex-1] == seq2[rowIndex-1]):
						diagonalCost.costVal += MATCH
					else:
						diagonalCost.costVal += SUB
					if diagonalCost.costVal < minCost.costVal:
						minCost = diagonalCost

				# Calculate top cost if indel
				topPrevCell = tuple((rowIndex-1, colIndex))
				topPrevCost = self.costDict.get(topPrevCell)
				if topPrevCost is not None:
					topCost = Cost(topPrevCost.costVal+INDEL, topPrevCell, Direction.TOP)
					if topCost.costVal <= minCost.costVal:
						minCost = topCost

				# Calculate left cost if indel
				leftPrevCell = tuple((rowIndex, colIndex-1))
				leftPrevCost = self.costDict.get(leftPrevCell)
				if leftPrevCost is not None:
					leftCost = Cost(leftPrevCost.costVal+INDEL, leftPrevCell, Direction.LEFT)
					if leftCost.costVal <= minCost.costVal:
						minCost = leftCost

				self.costDict[tuple((rowIndex,colIndex))] = minCost
				# self.printDict(seq1, seq2)

		cell = tuple((len(seq2), len(seq1)))
		cost = self.costDict.get(cell)
		score = math.inf
		if cost is not None: # This would happen if it is outside of the band
			score = cost.costVal
		if score != math.inf:
			alignment1, alignment2 = self.getAlignmentStrings(seq1, seq2, cell)
		else:
			alignment1 = alignment2 = "No Alignment Possible"
		# print(alignment1)
		# print(alignment2)

		return {'align_cost':score, 'seqi_first100':alignment1, 'seqj_first100':alignment2}


import discord
from discord.ext import commands
from discord import Embed
import pandas as pd

class BlackMarket(commands.Cog):
    fruits = [
        {"emoji": "🍎", "name": "Garden Fruit"},
        {"emoji": "🍏", "name": "Hero Fruit"},
        {"emoji": "🍊", "name": "Dark Fruit"},
        {"emoji": "🍋", "name": "Round Fruit"},
        {"emoji": "🍌", "name": "Triangle Fruit"},
        {"emoji": "🍉", "name": "Heart Fruit"},
        {"emoji": "🍆", "name": "Square Fruit"},
        {"emoji": "🍇", "name": "Chao Fruit"},
        {"emoji": "🍓", "name": "Smart Fruit"},
        {"emoji": "🍒", "name": "Power Fruit"},
        {"emoji": "🍑", "name": "Run Fruit"},
        {"emoji": "🍐", "name": "Swim Fruit"},
        {"emoji": "🍍", "name": "Fly Fruit"},
        {"emoji": "🥝", "name": "Tasty Fruit"},
        {"emoji": "🍄", "name": "Strange Mushroom"},
    ]

    chaos_drives = [
        {"emoji": "🪛", "name": "Hero Drive"},
        {"emoji": "🪛", "name": "Dark Drive"},
        {"emoji": "🪛", "name": "Smart Drive"},
        {"emoji": "🪛", "name": "Power Drive"},
        {"emoji": "🪛", "name": "Swim Drive"},
        {"emoji": "🪛", "name": "Run Drive"},
        {"emoji": "🪛", "name": "Swim Drive"},
        {"emoji": "🪛", "name": "Fly Drive"},
        {"emoji": "🪛", "name": "Strange Drive"},
    ]

    def __init__(self, bot):
        self.bot = bot
        self.embed_color = 0x1abc9c  # Replace this with the color you want to use for your embeds

    async def buy_command(self, ctx, *args):
        db_cog = self.bot.get_cog('Database')

        item = None
        quantity = 1

        # Parse args for item and quantity
        for arg in args:
            if arg.isdigit():
                quantity = int(arg)
            else:
                if item is None:
                    item = arg.lower()
                else:
                    item = item + " " + arg.lower()

        item = item.rstrip('s')  # remove trailing 's'

        # If no item specified, send an error message
        if item is None:
            await ctx.send("You didn't specify an item to buy.")
            return

        fruit = next((fruit for fruit in self.fruits if fruit['name'].lower() == item), None)
        if fruit is None:
            await ctx.send(f"Item '{item}' does not exist.")
            return

        price = 15 * quantity

        balance = await db_cog.get_rings(str(ctx.guild.id), str(ctx.author.id))

        if balance < price:
            await ctx.send(f"You do not have enough rings to buy {quantity} '{item}'.")
            return

        new_balance = balance - price
        await db_cog.store_rings(str(ctx.guild.id), str(ctx.author.id), new_balance)

        new_data = pd.DataFrame([(quantity, item)], columns=['quantity', 'item'])
        await db_cog.store_inventory(str(ctx.guild.id), str(ctx.author.id), new_data)  # Now passing the DataFrame directly to store_inventory

        # Adjust item name for quantity
        item_name = item if quantity == 1 else item + 's'

        await ctx.send(f"You have bought {quantity} '{item_name}' for {price} rings.")

    async def market_command(self, ctx):
        embed = Embed(title="Black Market", description="Here's what you can buy:", color=self.embed_color)

        fruits = [dict(fruit, price=15) for fruit in self.fruits]

        for i in range(0, len(fruits), 3):
            for j in range(3):
                if i+j < len(fruits):
                    fruit = fruits[i+j]
                    embed.add_field(name=f'{fruit["emoji"]} {fruit["name"]}', value=f'Price: {fruit["price"]} rings\n', inline=True)
                else:
                    embed.add_field(name='\u200b', value='\u200b', inline=True)

        await ctx.send(embed=embed)

    async def inventory_command(self, ctx):
        db_cog = self.bot.get_cog('Database')
        user_id = str(ctx.author.id)
        embed = Embed(title=f"{ctx.author.name}'s Inventory", description="Here's what you have:", color=self.embed_color)

        df = await db_cog.get_inventory(str(ctx.guild.id), user_id)

        if df is not None:
            grouped_df = df.groupby('item').sum().reset_index()
            inventory_items = grouped_df.to_dict('records')

            for i in range(0, len(inventory_items), 3):
                for j in range(3):
                    if i+j < len(inventory_items):
                        item = inventory_items[i+j]
                        embed.add_field(name=item['item'].capitalize(), value=f'Quantity: {item["quantity"]}\n', inline=True)
                    else:
                        embed.add_field(name='\u200b', value='\u200b', inline=True)

        await ctx.send(embed=embed)

    async def give_rings_command(self, ctx):
        db_cog = self.bot.get_cog('Database')
        guild_id = str(ctx.guild.id)
        user_id = str(ctx.author.id)

        # Add the rings to the user's current rings
        current_rings = await db_cog.get_rings(guild_id, user_id)
        if current_rings is None:
            new_rings = 100000
        else:
            new_rings = current_rings + 100000

        # Store the new amount of rings
        await db_cog.store_rings(guild_id, user_id, new_rings)

        await ctx.send(f"You have been given 100,000 rings! You now have {new_rings} rings.")

    async def rings_command(self, ctx, member: discord.Member = None):
        """Check your or someone else's ring balance"""
        member = member or ctx.author
        rings = await self.bot.cogs['Database'].get_rings(ctx.guild.id, str(member.id))
        embed = discord.Embed(title="Rings", description=f"{member.mention} has {rings} rings", color=discord.Color.gold())
        await ctx.send(embed=embed)

async def setup(bot):
    await bot.add_cog(BlackMarket(bot))
    print("Black Market cog loaded")


import setuptools

from os import path
this_directory = path.abspath(path.dirname(__file__))
with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f:
    long_description = f.read()

setuptools.setup(
    name='amazonstoreprice',
    packages=['amazonstoreprice'],
    package_dir={'amazonestoreprice': 'amazonstoreprice'},
    version='0.1.7',
    install_requires=['requests', 'beautifulsoup4'],
    description='Find the price on Amazon store starting from url',
    long_description=long_description,
    long_description_content_type='text/markdown',
    author='Alessandro Sbarbati',
    author_email='miriodev@gmail.com',
    url='https://github.com/Mirio/amazonstoreprice',
    download_url='https://github.com/Mirio/amazonstoreprice/tarball/0.1',
    keywords=['Amazon', 'amazonprice', 'amazonstoreprice', "amazonstore"],
    license='BSD',
    classifiers=["License :: OSI Approved :: BSD License",
                 "Programming Language :: Python :: 3",
                 "Topic :: Software Development :: Libraries :: Python Modules",
                 "Topic :: Utilities"],
)