import time
import mpi4py.MPI as MPI

import maia
import maia.pytree        as PT
import maia.utils.logging as mlog
from   maia.factory  import dist_from_part
from   maia.transfer import utils                as TEU
from   maia.utils    import np_utils, layouts, py_utils
from   .extraction_utils   import local_pl_offset, LOC_TO_DIM, get_partial_container_stride_and_order
from   .point_cloud_utils  import create_sub_numbering

import numpy as np

import Pypdm.Pypdm as PDM

DIMM_TO_DIMF = { 0: {'Vertex':'Vertex'},
               # 1: {'Vertex': None,    'EdgeCenter':None, 'FaceCenter':None, 'CellCenter':None},
                 2: {'Vertex':'Vertex', 'EdgeCenter':'EdgeCenter', 'FaceCenter':'CellCenter'},
                 3: {'Vertex':'Vertex', 'EdgeCenter':'EdgeCenter', 'FaceCenter':'FaceCenter', 'CellCenter':'CellCenter'}}

class Extractor:
  def __init__( self,
                part_tree, point_list, location, comm,
                equilibrate=True,
                graph_part_tool="hilbert"):

    self.part_tree     = part_tree
    self.exch_tool_box = list()
    self.comm          = comm

    # Get zones by domains
    part_tree_per_dom = dist_from_part.get_parts_per_blocks(part_tree, comm).values()
    # Check : monodomain
    assert len(part_tree_per_dom) == 1

    # ExtractPart dimension
    self.dim    = LOC_TO_DIM[location]
    assert self.dim in [0,2,3], "[MAIA] Error : dimensions 0 and 1 not yet implemented"
    #CGNS does not support 0D, so keep input dim in this case (which is 3 since 2d is not managed)
    cell_dim = 3 if location == 'Vertex' else self.dim

    # ExtractPart CGNSTree
    extracted_tree = PT.new_CGNSTree()
    extracted_base = PT.new_CGNSBase('Base', cell_dim=cell_dim, phy_dim=3, parent=extracted_tree)

    assert graph_part_tool in ["hilbert","parmetis","ptscotch"]
    assert not( (self.dim==0) and graph_part_tool in ['parmetis', 'ptscotch']),\
           '[MAIA] Vertex extraction not available with parmetis or ptscotch partitioning. Please check your script.'

    # Compute extract part of each domain
    for i_domain, part_zones in enumerate(part_tree_per_dom):
      extracted_zone, etb = extract_part_one_domain(part_zones, point_list[i_domain], self.dim, comm,
                                                    equilibrate=equilibrate,
                                                    graph_part_tool=graph_part_tool)
      self.exch_tool_box.append(etb)
      if PT.Zone.n_vtx(extracted_zone)!=0:
        PT.add_child(extracted_base, extracted_zone)
    self.extracted_tree = extracted_tree

  def exchange_fields(self, fs_container):
    # Get zones by domains (only one domain for now)
    part_tree_per_dom = dist_from_part.get_parts_per_blocks(self.part_tree, self.comm).values()

    # Get zone from extractpart
    extracted_zones = PT.get_all_Zone_t(self.extracted_tree)
    assert len(extracted_zones) <= 1
    extracted_zone = extracted_zones[0] if len(extracted_zones)!=0 else None

    for container_name in fs_container:
      # Loop over domains
      for i_domain, part_zones in enumerate(part_tree_per_dom):
        exchange_field_one_domain(part_zones, extracted_zone, self.dim, self.exch_tool_box[i_domain], \
            container_name, self.comm)

  def get_extract_part_tree(self) :
    return self.extracted_tree

def exchange_field_one_domain(part_zones, part_zone_ep, mesh_dim, exch_tool_box, container_name, comm) :

  loc_correspondance = {'Vertex'    : 'Vertex',
                        'FaceCenter': 'Cell',
                        'CellCenter': 'Cell'}

  # > Retrieve fields name + GridLocation + PointList if container
  #   is not know by every partition
  mask_zone = ['MaskedZone', None, [], 'Zone_t']
  dist_from_part.discover_nodes_from_matching(mask_zone, part_zones, container_name, comm, \
      child_list=['GridLocation', 'BCRegionName', 'GridConnectivityRegionName'])

  fields_query = lambda n: PT.get_label(n) in ['DataArray_t', 'IndexArray_t']
  dist_from_part.discover_nodes_from_matching(mask_zone, part_zones, [container_name, fields_query], comm)
  mask_container = PT.get_child_from_name(mask_zone, container_name)
  if mask_container is None:
    raise ValueError("[maia-extract_part] asked container for exchange is not in tree")

  # > Manage BC and GC ZSR
  ref_zsr_node    = mask_container
  bc_descriptor_n = PT.get_child_from_name(mask_container, 'BCRegionName')
  gc_descriptor_n = PT.get_child_from_name(mask_container, 'GridConnectivityRegionName')
  assert not (bc_descriptor_n and gc_descriptor_n)
  if bc_descriptor_n is not None:
    bc_name      = PT.get_value(bc_descriptor_n)
    dist_from_part.discover_nodes_from_matching(mask_zone, part_zones, ['ZoneBC_t', bc_name], comm, child_list=['PointList', 'GridLocation_t'])
    ref_zsr_node = PT.get_child_from_predicates(mask_zone, f'ZoneBC_t/{bc_name}')
  elif gc_descriptor_n is not None:
    gc_name      = PT.get_value(gc_descriptor_n)
    dist_from_part.discover_nodes_from_matching(mask_zone, part_zones, ['ZoneGridConnectivity_t', gc_name], comm, child_list=['PointList', 'GridLocation_t'])
    ref_zsr_node = PT.get_child_from_predicates(mask_zone, f'ZoneGridConnectivity_t/{gc_name})')

  gridLocation = PT.Subset.GridLocation(ref_zsr_node)
  partial_field = PT.get_child_from_name(ref_zsr_node, 'PointList') is not None
  assert gridLocation in ['Vertex', 'FaceCenter', 'CellCenter']

  # > FlowSolution node def by zone
  if part_zone_ep is not None :
    if PT.get_label(mask_container) == 'FlowSolution_t':
      FS_ep = PT.new_FlowSolution(container_name, loc=DIMM_TO_DIMF[mesh_dim][gridLocation], parent=part_zone_ep)
    elif PT.get_label(mask_container) == 'ZoneSubRegion_t':
      FS_ep = PT.new_ZoneSubRegion(container_name, loc=DIMM_TO_DIMF[mesh_dim][gridLocation], parent=part_zone_ep)
    else:
      raise TypeError

  # > Get PTP and parentElement for the good location
  ptp        = exch_tool_box['part_to_part'][gridLocation]

  # LN_TO_GN
  _gridLocation    = {"Vertex" : "Vertex", "FaceCenter" : "Element", "CellCenter" : "Cell"}

  if part_zone_ep is not None:
    elt_n            = part_zone_ep if gridLocation!='FaceCenter' else PT.Zone.NGonNode(part_zone_ep)
    if elt_n is None :return
    part1_elt_gnum_n = PT.maia.getGlobalNumbering(elt_n, _gridLocation[gridLocation])
    part1_ln_to_gn   = [PT.get_value(part1_elt_gnum_n)]

  # Get reordering informations if point_list
  # https://stackoverflow.com/questions/8251541/numpy-for-every-element-in-one-array-find-the-index-in-another-array
  if partial_field:
    pl_gnum1, stride = get_partial_container_stride_and_order(part_zones, container_name, gridLocation, ptp, comm)

  # > Field exchange
  for fld_node in PT.get_children_from_label(mask_container, 'DataArray_t'):
    fld_name = PT.get_name(fld_node)
    fld_path = f"{container_name}/{fld_name}"

    if partial_field:
      # Get field and organize it according to the gnum1_come_from arrays order
      fld_data = list()
      for i_part, part_zone in enumerate(part_zones) :
        fld_n = PT.get_node_from_path(part_zone,fld_path)
        fld_data_tmp = PT.get_value(fld_n) if fld_n is not None else np.empty(0, dtype=np.float64)
        fld_data.append(fld_data_tmp[pl_gnum1[i_part]])
      p2p_type = PDM._PDM_PART_TO_PART_DATA_DEF_ORDER_GNUM1_COME_FROM

    else :
      fld_data = [PT.get_node_from_path(part_zone,fld_path)[1] for part_zone in part_zones]
      stride   = 1
      p2p_type = PDM._PDM_PART_TO_PART_DATA_DEF_ORDER_PART2

    # Reverse iexch
    req_id = ptp.reverse_iexch(PDM._PDM_MPI_COMM_KIND_P2P,
                               p2p_type,
                               fld_data,
                               part2_stride=stride)
    part1_stride, part1_data = ptp.reverse_wait(req_id)

    # Interpolation and placement
    if part_zone_ep is not None:
      i_part = 0
      PT.new_DataArray(fld_name, part1_data[i_part], parent=FS_ep)

  # Build PL with the last exchange stride
  if partial_field:
    if len(part1_data)!=0 and part1_data[0].size!=0:
      new_point_list = np.where(part1_stride[0]==1)[0] if part1_data[0].size!=0 else np.empty(0, dtype=np.int32)
      point_list = new_point_list + local_pl_offset(part_zone_ep, LOC_TO_DIM[gridLocation])+1
      new_pl_node = PT.new_PointList(name='PointList', value=point_list.reshape((1,-1), order='F'), parent=FS_ep)
      partial_part1_lngn = [part1_ln_to_gn[0][new_point_list]]
    else:
      partial_part1_lngn = []

    # Update global numbering in FS
    partial_gnum = create_sub_numbering(partial_part1_lngn, comm)
    if part_zone_ep is not None and len(partial_gnum)!=0:
      PT.maia.newGlobalNumbering({'Index' : partial_gnum[0]}, parent=FS_ep)

def extract_part_one_domain(part_zones, point_list, dim, comm,
                            equilibrate=True,
                            graph_part_tool="hilbert"):
  """
  TODO : AJOUTER LE CHOIX PARTIONNEMENT
  """
  n_part_in  = len(part_zones)
  n_part_out = 1 if equilibrate else n_part_in

  pdm_ep = PDM.ExtractPart(dim, # face/cells
                           n_part_in,
                           n_part_out,
                           equilibrate,
                           eval(f"PDM._PDM_SPLIT_DUAL_WITH_{graph_part_tool.upper()}"),
                           True,
                           comm)

  # Loop over domain zone : preparing extract part
  for i_part, part_zone in enumerate(part_zones):
    # Get NGon + NFac
    cx, cy, cz = PT.Zone.coordinates(part_zone)
    vtx_coords = np_utils.interweave_arrays([cx,cy,cz])

    ngon  = PT.Zone.NGonNode(part_zone)
    nface = PT.Zone.NFaceNode(part_zone)

    cell_face_idx = PT.get_child_from_name(nface, "ElementStartOffset" )[1]
    cell_face     = PT.get_child_from_name(nface, "ElementConnectivity")[1]
    face_vtx_idx  = PT.get_child_from_name(ngon,  "ElementStartOffset" )[1]
    face_vtx      = PT.get_child_from_name(ngon,  "ElementConnectivity")[1]

    vtx_ln_to_gn, face_ln_to_gn, cell_ln_to_gn = TEU.get_entities_numbering(part_zone)

    n_cell = cell_ln_to_gn.shape[0]
    n_face = face_ln_to_gn.shape[0]
    n_edge = 0
    n_vtx  = vtx_ln_to_gn .shape[0]

    pdm_ep.part_set(i_part,
                    n_cell, n_face, n_edge, n_vtx,
                    cell_face_idx, cell_face    ,
                    None, None, None,
                    face_vtx_idx , face_vtx     ,
                    cell_ln_to_gn, face_ln_to_gn,
                    None,
                    vtx_ln_to_gn , vtx_coords)

    pdm_ep.selected_lnum_set(i_part, point_list[i_part] - local_pl_offset(part_zone, dim) - 1)

  pdm_ep.compute()

  # > Reconstruction du maillage de l'extract part
  n_extract_cell = pdm_ep.n_entity_get(0, PDM._PDM_MESH_ENTITY_CELL  )
  n_extract_face = pdm_ep.n_entity_get(0, PDM._PDM_MESH_ENTITY_FACE  )
  n_extract_edge = pdm_ep.n_entity_get(0, PDM._PDM_MESH_ENTITY_EDGE  )
  n_extract_vtx  = pdm_ep.n_entity_get(0, PDM._PDM_MESH_ENTITY_VERTEX)

  size_by_dim = {0: [[n_extract_vtx, 0             , 0]], # not yet implemented
                 1:   None                              , # not yet implemented
                 2: [[n_extract_vtx, n_extract_face, 0]],
                 3: [[n_extract_vtx, n_extract_cell, 0]] }

  # > ExtractPart zone construction
  extracted_zone = PT.new_Zone(PT.maia.conv.add_part_suffix('Zone', comm.Get_rank(), 0),
                               size=size_by_dim[dim],
                               type='Unstructured')

  ep_vtx_ln_to_gn  = pdm_ep.ln_to_gn_get(0,PDM._PDM_MESH_ENTITY_VERTEX)
  PT.maia.newGlobalNumbering({"Vertex" : ep_vtx_ln_to_gn}, parent=extracted_zone)

  # > Grid coordinates
  cx, cy, cz = layouts.interlaced_to_tuple_coords(pdm_ep.vtx_coord_get(0))
  extract_grid_coord = PT.new_GridCoordinates(parent=extracted_zone)
  PT.new_DataArray('CoordinateX', cx, parent=extract_grid_coord)
  PT.new_DataArray('CoordinateY', cy, parent=extract_grid_coord)
  PT.new_DataArray('CoordinateZ', cz, parent=extract_grid_coord)

  if dim == 0:
    PT.maia.newGlobalNumbering({'Cell' : np.empty(0, dtype=ep_vtx_ln_to_gn.dtype)}, parent=extracted_zone)

  # > NGON
  if dim >= 2:
    ep_face_vtx_idx, ep_face_vtx  = pdm_ep.connectivity_get(0, PDM._PDM_CONNECTIVITY_TYPE_FACE_VTX)
    ngon_n = PT.new_NGonElements( 'NGonElements',
                                  erange  = [1, n_extract_face],
                                  ec      = ep_face_vtx,
                                  eso     = ep_face_vtx_idx,
                                  parent  = extracted_zone)

    ep_face_ln_to_gn = pdm_ep.ln_to_gn_get(0, PDM._PDM_MESH_ENTITY_FACE)
    PT.maia.newGlobalNumbering({'Element' : ep_face_ln_to_gn}, parent=ngon_n)
    if dim == 2:
      PT.maia.newGlobalNumbering({'Cell' : ep_face_ln_to_gn}, parent=extracted_zone)

  # > NFACES
  if dim == 3:
    ep_cell_face_idx, ep_cell_face = pdm_ep.connectivity_get(0, PDM._PDM_CONNECTIVITY_TYPE_CELL_FACE)
    nface_n = PT.new_NFaceElements('NFaceElements',
                                    erange  = [n_extract_face+1, n_extract_face+n_extract_cell],
                                    ec      = ep_cell_face,
                                    eso     = ep_cell_face_idx,
                                    parent  = extracted_zone)

    ep_cell_ln_to_gn = pdm_ep.ln_to_gn_get(0, PDM._PDM_MESH_ENTITY_CELL)
    PT.maia.newGlobalNumbering({'Element' : ep_cell_ln_to_gn}, parent=nface_n)
    PT.maia.newGlobalNumbering({'Cell' : ep_cell_ln_to_gn}, parent=extracted_zone)

    maia.algo.nface_to_pe(extracted_zone, comm)

  # - Get PTP by vertex and cell
  ptp = dict()
  if equilibrate:
    ptp['Vertex']       = pdm_ep.part_to_part_get(PDM._PDM_MESH_ENTITY_VERTEX)
    if dim >= 2: # NGON
      ptp['FaceCenter'] = pdm_ep.part_to_part_get(PDM._PDM_MESH_ENTITY_FACE)
    if dim == 3: # NFACE
      ptp['CellCenter'] = pdm_ep.part_to_part_get(PDM._PDM_MESH_ENTITY_CELL)

  # - Get parent elt
  parent_elt = dict()
  parent_elt['Vertex']       = pdm_ep.parent_ln_to_gn_get(0,PDM._PDM_MESH_ENTITY_VERTEX)
  if dim >= 2: # NGON
    parent_elt['FaceCenter'] = pdm_ep.parent_ln_to_gn_get(0,PDM._PDM_MESH_ENTITY_FACE)
  if dim == 3: # NFACE
    parent_elt['CellCenter'] = pdm_ep.parent_ln_to_gn_get(0,PDM._PDM_MESH_ENTITY_CELL)

  exch_tool_box = {'part_to_part' : ptp, 'parent_elt' : parent_elt}

  return extracted_zone, exch_tool_box

def extract_part_from_zsr(part_tree, zsr_name, comm,
                          # transfer_fields=True
                          containers_name=[], **options):
  """Extract the submesh defined by the provided ZoneSubRegion from the input volumic
  partitioned tree.

  Dimension of the output mesh is set up accordingly to the GridLocation of the ZoneSubRegion.
  Submesh is returned as an independant partitioned CGNSTree and includes the relevant connectivities.

  In addition, containers specified in ``containers_name`` list are transfered to the extracted tree.
  Containers to be transfered can be either of label FlowSolution_t or ZoneSubRegion_t.

  Args:
    part_tree       (CGNSTree)    : Partitioned tree from which extraction is computed. Only U-NGon
      connectivities are managed.
    zsr_name        (str)         : Name of the ZoneSubRegion_t node
    comm            (MPIComm)     : MPI communicator
    containers_name (list of str) : List of the names of the fields containers to transfer
                                    on the output extracted tree.
    **options: Options related to the extraction.
  Returns:
    extracted_tree (CGNSTree)  : Extracted submesh (partitioned)

  Extraction can be controled by the optional kwargs:

    - ``graph_part_tool`` (str) -- Partitioning tool used to balance the extracted zones.
      Admissible values are ``hilbert, parmetis, ptscotch``. Note that
      vertex-located extractions require hilbert partitioning. Defaults to ``hilbert``.

  Important:
    - Input tree must be unstructured and have a ngon connectivity.
    - Partitions must come from a single initial domain on input tree.

  See also:
    :func:`create_extractor_from_zsr` takes the same parameters, excepted ``containers_name``,
    and returns an Extractor object which can be used to exchange containers more than once through its
    ``Extractor.exchange_fields(container_name)`` method.

  Example:
    .. literalinclude:: snippets/test_algo.py
      :start-after: #extract_from_zsr@start
      :end-before:  #extract_from_zsr@end
      :dedent: 2
  """

  start = time.time()
  extractor = create_extractor_from_zsr(part_tree, zsr_name, comm, **options)

  if containers_name:
    extractor.exchange_fields(containers_name)
  end = time.time()

  extracted_tree = extractor.get_extract_part_tree()

  # Print some light stats
  elts_kind = ['vtx', 'edges', 'faces', 'cells'][extractor.dim]
  if extractor.dim == 0:
    n_cell = sum([PT.Zone.n_vtx(zone) for zone in PT.iter_all_Zone_t(extracted_tree)])
  else:
    n_cell = sum([PT.Zone.n_cell(zone) for zone in PT.iter_all_Zone_t(extracted_tree)])
  n_cell_all = comm.allreduce(n_cell, MPI.SUM)
  mlog.info(f"Extraction from ZoneSubRegion \"{zsr_name}\" completed ({end-start:.2f} s) -- "
            f"Extracted tree has locally {mlog.size_to_str(n_cell)} {elts_kind} "
            f"(Σ={mlog.size_to_str(n_cell_all)})")

  return extracted_tree

def create_extractor_from_zsr(part_tree, zsr_path, comm, **options):
  """Same as extract_part_from_zsr, but return the extractor object."""
  # Get zones by domains

  graph_part_tool = options.get("graph_part_tool", "hilbert")

  part_tree_per_dom = dist_from_part.get_parts_per_blocks(part_tree, comm)

  # Get point_list for each partitioned zone and group it by domain
  point_list = list()
  location = ''
  for domain, part_zones in part_tree_per_dom.items():
    point_list_domain = list()
    for part_zone in part_zones:
      zsr_node     = PT.get_node_from_path(part_zone, zsr_path)
      if zsr_node is not None:
        #Follow BC or GC link
        related_node = PT.getSubregionExtent(zsr_node, part_zone)
        zsr_node     = PT.get_node_from_path(part_zone, related_node)
        point_list_domain.append(PT.get_child_from_name(zsr_node, "PointList")[1][0])
        location = PT.Subset.GridLocation(zsr_node)
      else: # ZSR does not exists on this partition
        point_list_domain.append(np.empty(0, np.int32))
    point_list.append(point_list_domain)

  # Get location if proc has no zsr
  location = comm.allreduce(location, op=MPI.MAX)

  return Extractor(part_tree, point_list, location, comm,
                   graph_part_tool=graph_part_tool)

def extract_part_from_bc_name(part_tree, bc_name, comm,
                              transfer_dataset=True,
                              containers_name=[],
                              **options):
  """Extract the submesh defined by the provided BC name from the input volumic
  partitioned tree.

  Behaviour and arguments of this function are similar to those of :func:`extract_part_from_zsr`
  (``zsr_name`` becomes ``bc_name``). Optional ``transfer_dataset`` argument allows to
  transfer BCDataSet from BC to the extracted mesh (default to ``True``).

  Example:
    .. literalinclude:: snippets/test_algo.py
      :start-after: #extract_from_bc_name@start
      :end-before:  #extract_from_bc_name@end
      :dedent: 2
  """

  # Local copy of the part_tree to add ZSR
  l_containers_name = containers_name
  local_part_tree   = PT.shallow_copy(part_tree)
  part_tree_per_dom = dist_from_part.get_parts_per_blocks(local_part_tree, comm)

  # Adding ZSR to tree
  there_is_bcdataset = False
  for domain, part_zones in part_tree_per_dom.items():
    for part_zone in part_zones:
      bc_n = PT.get_node_from_name_and_label(part_zone, bc_name, 'BC_t')
      if bc_n is not None:
        zsr_bc_n  = PT.new_ZoneSubRegion(name=bc_name, bc_name=bc_name, parent=part_zone)
        if transfer_dataset:
          assert PT.get_child_from_predicates(bc_n, 'BCDataSet_t/IndexArray_t') is None,\
                 'BCDataSet_t with PointList aren\'t managed'
          ds_arrays = PT.get_children_from_predicates(bc_n, 'BCDataSet_t/BCData_t/DataArray_t')
          for ds_array in ds_arrays:
            PT.new_DataArray(name=PT.get_name(ds_array), value=PT.get_value(ds_array), parent=zsr_bc_n)
          if len(ds_arrays) != 0:
            there_is_bcdataset = True
            # PL and Location is needed for data exchange, but this should be done in ZSR func
            for name in ['PointList', 'GridLocation']:
              PT.add_child(zsr_bc_n, PT.get_child_from_name(bc_n, name))

  if transfer_dataset and comm.allreduce(there_is_bcdataset, MPI.LOR):
    l_containers_name = containers_name + [bc_name] # not to change the initial containers_name list

  return extract_part_from_zsr(local_part_tree, bc_name, comm, l_containers_name, **options)


# -*- coding: utf-8 -*-
import random
import json
import cardsource
from bs4 import BeautifulSoup as bs

def pick_rand(vocab):
    if len(vocab) < 20:
        rand = vocab
    else:
        rand = random.sample(vocab, 20)
    return rand

def make_deck():
    vocab = {}
    card_source = [cardsource.BASIC, cardsource.ADVANCED] # Include source file

    list_name = ["basic", "advanced"]

    for n, source in enumerate(card_source):

        soup = bs(source, "html.parser")
        vocab_list = soup.find(class_='SetPage-termsList')

        for child in vocab_list:

            term = child.find(class_='SetPageTerm-wordText').find(class_='TermText').getText().strip()
            definition = child.find(class_='SetPageTerm-definitionText').find(class_='TermText').getText().strip()

            vocab[term] = {"def": definition, "learned": False, "list": list_name[n]}

    with open('test.json', 'w') as outfile:
        json.dump(vocab, outfile)

if __name__=='__main__':

    for n in range(0, 50):

        with open('vocab.json') as data_file:
            vocab = json.load(data_file)

        learned = {}

        word_list = []
        for word in vocab:
            word_list.append(word)
        random_list = pick_rand(word_list)

        for term in random_list:
            learned[term] = {"def": vocab[term]["def"], "list": vocab[term]["list"]}
            vocab.pop(term, None)
        filename = 'week/week%d.json' % n
        with open(filename, 'w') as outfile:

            json.dump(learned, outfile)

        with open('vocab.json', 'w') as outfile:
            json.dump(vocab, outfile)


import matplotlib
import numpy as np
import matplotlib.ticker as ticker
import matplotlib.pyplot as plt
from cherab.core.math import Slice3D, sample3d_points, samplevector2d_grid, samplevector3d_grid, samplevector3d_points, ConstantVector3D, sample2d_grid, sample3d_points, samplevector3d_grid
from cherab.core import Plasma
from cherab.core.atomic.elements import carbon, deuterium

def plot_contour(function3d):

    #Extracting the Distribution function strength frtom the plasam object
    X = [0]
    Y = np.linspace(0,1.75,100)
    Z = np.linspace(-1.5, 1.5 ,100)
    Dist = np.squeeze(sample2d_grid(Slice3D(function3d,'x',0),Y,Z))

    #plotting the Bfield
    fig, ax = plt.subplots()
    CS = ax.contour(Y, Z, np.transpose(Dist), levels = 20)
    fmt = ticker.ScalarFormatter()
    fmt.set_scientific(True)
    fmt.set_powerlimits((0,1))
    fmt.create_dummy_axis()
    ax.clabel(CS, inline = 1, fmt = fmt )
    ax.set_title('Density [per m^3]')
    ax.set(xlabel = '[m]', ylabel = '[m]')
    cbar = fig.colorbar(CS, cmap='plasma', extend='both')
    cbar.minorticks_on()
    plt.show()

    """
    #Extracting the Bfield strength frtom the plasam object
    X = [0]
    Y = np.linspace(0,2,100)
    Z = np.linspace(-2.2, 2.2 ,200)
    B_field3D = np.squeeze(samplevector3d_grid(plasma.b_field,X,Y,Z))
    B_field3DScalar = np.linalg.norm(B_field3D,axis = 2)
    """

def plot_contourSCP(function3d):

    plt.rc('font', size=18)
    plt.rc('axes', titlesize=18)
    plt.rc('axes', labelsize=18)
    plt.rc('xtick', labelsize=18)
    plt.rc('ytick', labelsize=18)
    plt.rc('legend', fontsize=18)
    plt.rc('figure', titlesize=20)

    #Extracting the Distribution function strength frtom the plasam object
    X = [0]
    Y = np.linspace(0,1.75,500)
    Z = np.linspace(-1.5, 1.5 ,500)
    Dist = np.squeeze(sample2d_grid(Slice3D(function3d,'x',0),Y,Z))

    Dist = np.ma.masked_where(Dist < 0.01,Dist)
    cmap = plt.cm.RdGy_r
    cmap.set_bad(color='red',alpha = 0)
    #plotting the Bfield
    fig, ax = plt.subplots(figsize = (6,7))
    ax.imshow(Dist.T,extent = [0,1.75,-1.5,1.5],cmap = cmap,origin = 'lower',alpha = 0.9)
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    ax.spines['bottom'].set_color('snow')
    ax.spines['left'].set_color('snow')
    ax.xaxis.label.set_color('snow')
    ax.yaxis.label.set_color('snow')
    ax.tick_params(axis='both', colors='snow')
    ax.set_xticks([0,0.5,1,1.5])
    # ax.yaxis.set_ticks_position('left')
    # ax.xaxis.set_ticks_position('bottom')

    plt.xlabel('R (m)')
    plt.ylabel('Z (m)')
    # plt.title('Sampled Balmer Series Spectrum')
    fig.savefig('SCP/TokDensDeu.png', transparent=True)
    plt.show()

def plot_velocity(function3Dvector):

    X = [0]
    Y = np.linspace(0, 1.75, 100)
    X2 = np.linspace(0, 1.75, 100)
    Y2 = [0]
    Z = np.linspace(-1.5, 1.5, 100)
    Z2 = np.zeros(100)
    midline = np.array([Z2,Y,Z2]).T
    print(midline.shape)
    values = np.linalg.norm(np.squeeze(samplevector3d_grid(function3Dvector,X,Y,Z)),axis=2).T
    valuesRot = np.linalg.norm(np.squeeze(samplevector3d_grid(function3Dvector, X2, Y2, Z)), axis=2).T
    ValuesMid = np.linalg.norm(np.squeeze(samplevector3d_points(function3Dvector, midline)), axis=1).T

    fig, [ax,ax3] = plt.subplots(2,1)
    im = ax.imshow(values, vmin = np.min(values), vmax = np.max(values))
    #im2 = ax2.imshow(valuesRot, vmin=np.min(values), vmax=np.max(values))
    ax.set_aspect('equal')
    ax.set(title = 'particle velocity')
    cbar = fig.colorbar(im, cmap = 'plasma' ,extend = 'both',label = 'velocity [m/s]')
    cbar.minorticks_on()
    #ax2.set_aspect('equal')
    #ax2.set(title='particle velocity')
    ax3.plot(Y,ValuesMid,marker = 'o')

    plt.show()
def plot_mag_field(function3Dvector):
    X = [0]
    Y = np.linspace(0.1, 1.5, 10)
    Z = np.linspace(-2, 2, 10)

    values = np.linalg.norm(np.squeeze(samplevector2d_grid(function3Dvector,Y,Z)),axis=2).T

    fig, [ax, ax1] = plt.subplots(2,1)
    im = ax.imshow(values, vmin = np.min(values), vmax = np.max(values))

    ax.set_aspect('equal')
    ax.set(title = 'Magnetic Field')
    cbar = fig.colorbar(im, cmap = 'plasma' ,extend = 'both',label = 'B-Field [T]')
    cbar.minorticks_on()

    plt.show()

def save_parameters(plasma,filename):
    vel = save_velocity(plasma.composition[carbon, 6].distribution.bulk_velocity)
    temp =save_temperature(plasma.composition[carbon, 6].distribution.effective_temperature)
    den =save_density(plasma.composition[carbon, 6].distribution.density)
    dden = save_edensity(plasma.composition[deuterium, 1].distribution.density)
    eden = save_edensity(plasma.electron_distribution.density)
    np.savez('Data/Inputs/InputData%s' %filename, velocity = vel, temperature = temp, density = den, edensity = eden, ddensity = dden, zeff = save_Zeff(plasma), b_field = save_Bfield(plasma)) #, edensity = eden
    return

def save_velocity(function3Dvector):
    Y = np.load('Data/Inputs/RtoFnumber.npy')
    Z2 = np.zeros(np.size(Y))
    midline = np.array([Z2,Y,Z2]).T
    ValuesMid = np.linalg.norm(np.squeeze(samplevector3d_points(function3Dvector, midline)), axis=1).T
    return np.stack([ValuesMid, Y])

def save_temperature(function3D):
    Y = np.load('Data/Inputs/RtoFnumber.npy')
    X = np.zeros(np.size(Y))
    Z = np.zeros(np.size(Y))
    midline = np.array([X, Y, Z]).T
    ValuesMid = sample3d_points(function3D,midline)
    return np.stack([ValuesMid, Y])

def save_density(function3D):
    Y = np.load('Data/Inputs/RtoFnumber.npy')
    X = np.zeros(np.size(Y))
    Z = np.zeros(np.size(Y))
    midline = np.array([X, Y, Z]).T
    ValuesMid = sample3d_points(function3D,midline)
    return np.stack([ValuesMid, Y])

def save_edensity(function3D):
    Fiber_to_R = np.load('Data/Inputs/RtoFnumber.npy')
    X = np.zeros(np.size(Fiber_to_R))
    Y = Fiber_to_R
    Z = np.zeros(np.size(Fiber_to_R))
    midline = np.array([X, Y, Z]).T
    ValuesMid = sample3d_points(function3D,midline)
    return  ValuesMid

def save_Zeff(plasma):
    Y = np.load('Data/Inputs/RtoFnumber.npy')
    ValuesMid = np.zeros(np.size(Y))
    for i, y in enumerate(Y[2:]):
        ValuesMid[i+2] = plasma.z_effective(0,y,0)
    print(ValuesMid)
    return ValuesMid

def save_Bfield(plasma):
    Y = np.load('Data/Inputs/RtoFnumber.npy')
    print(Y.shape)
    ValuesMid = np.zeros(np.size(Y))
    for i, y in enumerate(Y):
        ValuesMid[i] = plasma.b_field(0,y,0).length
    return ValuesMid


from PIL import Image
from matplotlib import pyplot as plt
from copy import deepcopy, copy
import time
import random
import cv2
import os
import numpy as np
from matplotlib import pyplot as plt

dir = os.path.dirname(__file__)

def filterImageGaussMedian():
    image_uri = os.path.join(dir, '../plate_detection/test_data/images/test.jpg')
    image = cv2.imread(image_uri)
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # --> median
    median = cv2.medianBlur(gray_image, 5)
    median2 = cv2.medianBlur(gray_image, 11)

    # --> gauss
    gauss = cv2.GaussianBlur(gray_image, (5, 5), 0)
    gauss2 = cv2.GaussianBlur(gray_image, (11, 11), 0)

    # --> average
    blur = cv2.blur(gray_image,(5,5))

    fig, arr = plt.subplots(2, 3)

    arr[0][0].imshow(gray_image, cmap="gray")
    arr[0][1].imshow(median, cmap="gray")
    arr[0][2].imshow(median2, cmap="gray")
    # arr[1][0].imshow(gauss, cmap="gray")
    arr[1][1].imshow(gauss, cmap="gray")
    arr[1][2].imshow(gauss2, cmap="gray")

    arr[0][0].set_title('a)')
    arr[0][1].set_title('b)')
    arr[0][2].set_title('c)')
    arr[1][1].set_title("d)")
    arr[1][2].set_title('e)')
    plt.show()

def salt_pepper_noise(image, prob, noise):
    '''
    Adding salt and pepper noise to image
    prob: Probability of the noise
    noise: 0 - salt, 1 - pepper
    '''
    output = np.zeros(image.shape,np.uint8)
    thres = 1 - prob
    for i in range(image.shape[0]):
        for j in range(image.shape[1]):
            rdn = random.random()

            if noise is 0:
                if rdn > thres:
                    output[i][j] = 255
                else:
                    output[i][j] = image[i][j]
            else:
                if rdn < prob:
                    output[i][j] = 0
                else:
                    output[i][j] = image[i][j]
    return output

def filterImageErosionDilation():
    image_uri = os.path.join(dir, '../plate_detection/test_data/images/test.jpg')
    image = cv2.imread(image_uri)
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    salt_noise_image = salt_pepper_noise(gray_image, 0.09, 0)
    pepper_noise_image = salt_pepper_noise(gray_image, 0.09, 1)

    kernel = np.ones((3, 3), np.uint8)

    # --> erosion
    erosion_salt = cv2.erode(salt_noise_image, kernel, iterations=1)

    # --> dilation
    dilation_pepper = cv2.dilate(pepper_noise_image, kernel, iterations=1)

    # --> bad example
    bad_erosion_pepper = cv2.erode(pepper_noise_image, kernel, iterations=1)

    fig, arr = plt.subplots(2, 3)

    arr[0][0].imshow(gray_image, cmap="gray")
    arr[0][1].imshow(salt_noise_image, cmap="gray")
    arr[0][2].imshow(erosion_salt, cmap="gray")
    arr[1][0].imshow(pepper_noise_image, cmap="gray")
    arr[1][1].imshow(dilation_pepper, cmap="gray")
    arr[1][2].imshow(bad_erosion_pepper, cmap="gray")

    arr[0][0].set_title('a)')
    arr[0][1].set_title('b)')
    arr[0][2].set_title('c)')
    arr[1][0].set_title("d)")
    arr[1][1].set_title("e)")
    arr[1][2].set_title("f)")
    plt.show()

def image_open_close():
    image_uri = os.path.join(dir, '../plate_detection/test_data/images/tor_binarize.png')
    image = cv2.imread(image_uri)

    kernel = np.ones((3, 3), np.uint8)
    image_open = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
    image_close = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)

    fig, arr = plt.subplots(2, 2)

    arr[0][0].imshow(image, cmap="gray")
    arr[0][1].imshow(image_open, cmap="gray")
    arr[1][1].imshow(image_close, cmap="gray")

    arr[0][0].set_title('a)')
    arr[0][1].set_title('b)')
    arr[1][1].set_title('c)')
    plt.show()

# filterImageGaussMedian()
filterImageErosionDilation()
# image_open_close()


import socket
import json

HOST = '127.0.0.1'  # The server's hostname or IP address
PORT = 65432        # The port used by the server

def inserimento(testo):
  print(testo)
  valore=input(">>>")
  return valore

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
  s.connect((HOST, PORT))
  while True:
    # Prendo il primo numero
    primoNumero=inserimento("Inserisci il primo numero. exit() per uscire")
    # Controllo se l'utente vuole uscire. In questo caso esco dal ciclo while. Il client chiuderà la connessione uscendo dal with
    if primoNumero=="exit()":
      break
    # Converto a float
    primoNumero=float(primoNumero)
    # Inserimento altri parametri
    operazione=inserimento("Inserisci l'operazione(+,-,*,/,%)")
    secondoNumero=float(inserimento("Inserisci il secondo numero"))
    # Preparo il messaggio. Attenzione al dumps
    messaggio=json.dumps({'primoNumero':primoNumero,'operazione':operazione,'secondoNumero':secondoNumero})
    # Invio il messaggio. Attenzione all'encode
    s.sendall(messaggio.encode("UTF-8"))
    # Aspetto la risposta del server
    data = s.recv(1024)
    # Stampo la risposta del server
    print('Risultato:', data.decode())


import pygame.font

class ScoreBoard:

    def __init__(self, ai_settings, screen, stats):
        """Initialize scorekeeping attributes"""
        self.screen = screen
        self.screen_rect = screen.get_rect()
        self.ai_settings = ai_settings
        self.stats = stats

        # Font settings for scoring information
        self.text_color = (3, 241, 17)
        self.font = pygame.font.SysFont(None, 48)

        # initialize
        self.p_score_image = False
        self.p_score_rect = False
        self.cp_score_image = False
        self.cp_score_rect = False
        self.win_score_image = False
        self.win_score_rect = False
        self.winner_font = False
        self.winner_image = False
        self.winner_image_rect = False

        # Prepare the initial score images.
        self.prep_score()
        self.prep_winning_score()

    def prep_score(self):

        p_score_str = int(self.stats.p_score)
        self.p_score_image = self.font.render(str(p_score_str), True, self.text_color, self.ai_settings.bg_color)

        # Display the player score to the left of net
        self.p_score_rect = self.p_score_image.get_rect()
        self.p_score_rect.right = self.screen_rect.centerx - 20
        self.p_score_rect.top = 40

        cp_score_str = self.stats.cp_score
        self.cp_score_image = self.font.render(str(cp_score_str), True, self.text_color, self.ai_settings.bg_color)

        # Display the computer score to the right of net
        self.cp_score_rect = self.cp_score_image.get_rect()
        self.cp_score_rect.left = self.screen_rect.centerx + 20
        self.cp_score_rect.top = 40

    def prep_winning_score(self):
        self.win_score_image = self.font.render('15', True, self.text_color, self.ai_settings.bg_color)
        self.win_score_rect = self.win_score_image.get_rect()
        self.win_score_rect.centerx = self.screen_rect.centerx
        self.win_score_rect.top = self.screen_rect.top

    def show_score(self):
        """Draw scores and ships to the screen"""
        self.screen.blit(self.p_score_image, self.p_score_rect)
        self.screen.blit(self.cp_score_image, self.cp_score_rect)
        self.screen.blit(self.win_score_image, self.win_score_rect)

    def prep_p_winner(self):
            self.winner_font = pygame.font.SysFont(None, 50)
            self.winner_image = self.winner_font.render('Player Wins!', True, self.text_color,
                                                        self.ai_settings.bg_color)
            self.winner_image_rect = self.winner_image.get_rect()
            self.winner_image_rect.center = self.screen_rect.center

    def prep_cp_winner(self):
            self.winner_font = pygame.font.SysFont(None, 50)
            self.winner_image = self.winner_font.render('AI Wins!', True, self.text_color, self.ai_settings.bg_color)
            self.winner_image_rect = self.winner_image.get_rect()
            self.winner_image_rect.centerx = self.screen_rect.centerx
            self.winner_image_rect.centery = self.screen_rect.centery

    def draw_winner(self):
            self.screen.blit(self.winner_image, self.winner_image_rect)


from flask import (
    Blueprint, flash, g, redirect, render_template, request, current_app, url_for, session
)
from werkzeug.exceptions import abort
from SolrClient import SolrClient
from solrq import Q
import math
import re

bp = Blueprint('search', __name__)

def set_key(dictionary, key, value):
    if key not in dictionary:
        dictionary[key] = value
    else:
        value += dictionary[key]
        dictionary[key] = value

def collect(fac):
    """
    faculteiten kunnen op de volgende manieren voorkomen:
    ["FNWI"]
    ["FNWI / Instituut voor Theoretische Fysica"]
    ["FNWI / Instituut voor Theoretische Fysica", "FNWI"]
    ["FNWI / Instituut voor Theoretische Fysica", "FNWI / Instituut voor Theoretische Fysica""]
    NB de tweede (of derde...) kan hetzelfde zijn maar kan ook 'n andere faculteit zijn

    """
    items = dict()
    for key, value in fac.items():
        # faculteiten met evt. met 'n komma in de naam; die moet er uit voor de facet-list
        key = re.sub(',', '', key)
        key += ','
        # first, split on comma
        faculties = key.split(',')
        # loop over results
        for faculty in faculties:
            if (faculty == ''):
                continue
            faculty += '/'
            faculty, dummy = faculty.split('/', 1)
            faculty = faculty.strip()
            set_key(items, faculty, value)
    return items

def buildQuery():
    """
    faculteit kan meerdere keren voorkomen
    vandaar de dict.getlist
    zie: https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.MultiDict
    NB nu ff niet geimplementeerd
    dit werkt niet: return Q(text="amsterdam", type="master", faculteit="FEB", faculteit="FMG")
    dit werkt wel:  return Q(text="amsterdam", type="master", faculteit="FEB") & Q(faculteit="FMG")
    """
    dict = request.args
    dict.getlist('faculteit')
    return Q(**dict)

def simple_query(page):
    d = dict()
    query = buildQuery()
    print(query)
    solr = SolrClient(current_app.config['SOLR'])
    res = solr.query('scripties',{
            'q':query,
            'rows':'0',
    })
    count = res.get_num_found()
    pages = math.ceil(count/10)
    start = (page-1)*10
    res = solr.query('scripties',{
            'q':query,
            'rows':'10',
            'start':start,
            'fl':'id,titel,auteur,jaar',
            'facet':True,
            'facet.field':['jaar','type', 'faculteit'],
    })
    facets = res.get_facets()
    d['result'] = res
    d['pages']  = pages
    d['page']   = page
    d['f_jaar'] = facets['jaar']
    d['f_type'] = facets['type']
    d['f_faculteit'] = collect(facets['faculteit'])
    d['f'] = request.args.get('faculteit')
    d['j'] = request.args.get('jaar')
    d['t'] = request.args.get('type')
    return d

def detail_query(key):
    solr = SolrClient(current_app.config['SOLR'])
    q = 'id:{}'.format(key)
    res = solr.query('scripties',{
            'q':q,
            'fl':'titel,auteur,jaar,supervisor,type,faculteit,opleiding,taal',
    })
    return res

@bp.route('/result/')
@bp.route('/result/<int:page>/')
def result(page=1):
    result = simple_query(page)
    if page > result['pages']:
        abort(404)
    return render_template('results.html', result=result, section="results")

@bp.route('/detail/<key>')
def detail(key):
    result = detail_query(key)
    return render_template('detail.html', result=result)


from flask import render_template
from app import app
from app.forms import LoginForm

@app.route('/')
@app.route('/index')
def index():
    user = {'username': 'Den Smyk'}
    posts = [
        {
            'author' : {'username': 'John'},
            'body': 'Beautiful day in Portland!'
        },
        {
            'author' : {'username': 'Susan'},
            'body': 'The Avengers movie was so cool!'
        },
        {
            'author' : {'username': 'Іванко'},
            'body': 'Яка погана риба у вас!'
        }
    ]
    return render_template('index.html', title='Home', user=user, posts = posts)

@app.route('/login')
def login():
    form = LoginForm()
    return render_template('login.html', title='Sign In', form=form)


import sys
from os import path
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox

errorIcon = path.join(path.dirname(__file__), "error.png")

class UI_MainWindow(object):

    def errorBox(self):
        msg = QMessageBox()
        msg.setWindowTitle("Error")
        msg.setText("Lost connection")
        msg.setWindowIcon(QtGui.QIcon(errorIcon))
        msg.setStandardButtons(QMessageBox.Ok)
        x = msg.exec_()

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(660, 780)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(0, 0, 661, 781))
        self.label.setStyleSheet("background-color:rgba(255,255,255,255);")
        self.label.setText("")
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(0, 0, 661, 781))
        self.label_2.setStyleSheet("background-color:rgba(186, 191, 148, 180);")
        self.label_2.setText("")
        self.label_2.setObjectName("label_2")

################################################## Phía trên là khung và màu nền ####################################################

########################################################### Date Input ##############################################################

        self.dateEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.dateEdit.setGeometry(QtCore.QRect(70, 60, 220, 40))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.dateEdit.setFont(font)
        self.dateEdit.setStyleSheet("background-color: rgba(0,0,0,0);\n"
"border:none;\n"
"border-bottom:2px solid rgba(46,82,101,200);\n"
"color: rgba(0,0,0,240);\n"
"padding-bottom: 7px;")
        self.dateEdit.setText("")
        self.dateEdit.setCursorMoveStyle(QtCore.Qt.VisualMoveStyle)
        self.dateEdit.setObjectName("dateEdit")

####################################################### Text (Không cần quan tâm) ###############################################

##################################################### Message Input ###########################################################

        self.message = QtWidgets.QLineEdit(self.centralwidget)
        self.message.setGeometry(QtCore.QRect(70, 130, 220, 40))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.message.setFont(font)
        self.message.setStyleSheet("background-color: rgba(0,0,0,0);\n"
"border:none;\n"
"border-bottom:2px solid rgba(46,82,101,200);\n"
"color: rgba(0,0,0,240);\n"
"padding-bottom: 7px;")
        self.message.setText("")
        self.message.setCursorMoveStyle(QtCore.Qt.VisualMoveStyle)
        self.message.setObjectName("message")

######################################################### Bank Input #########################################################

        self.bank = QtWidgets.QLineEdit(self.centralwidget)
        self.bank.setGeometry(QtCore.QRect(370, 60, 220, 40))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.bank.setFont(font)
        self.bank.setStyleSheet("background-color: rgba(0,0,0,0);\n"
"border:none;\n"
"border-bottom:2px solid rgba(46,82,101,200);\n"
"color: rgba(0,0,0,240);\n"
"padding-bottom: 7px;")
        self.bank.setText("")
        self.bank.setObjectName("bank")

######################################################### Button Send ########################################################

        self.send = QtWidgets.QPushButton(self.centralwidget)
        self.send.setGeometry(QtCore.QRect(220, 230, 190, 40))
        font = QtGui.QFont()
        font.setPointSize(11)
        font.setBold(True)
        font.setWeight(75)
        self.send.setFont(font)
        self.send.setStyleSheet("QPushButton#send{\n"
"    background-color: qlineargradient(spread:pad, x1:0, y1:0.505682, x2:1, y2:0.477, stop:0 rgba(11, 131, 120, 219), stop:1 rgba(85, 98, 112, 226));\n"
"    color:rgba(255,255,255,210);\n"
"    border-radius:5px;\n"
"}\n"
"\n"
"QPushButton#send:hover{\n"
"    background-color: qlineargradient(spread:pad, x1:0, y1:0.505682, x2:1, y2:0.477, stop:0 rgba(150, 123, 111, 219), stop:1 rgba(85, 81, 84, 226));\n"
"}\n"
"\n"
"QPushButton#send:pressed{\n"
"    padding-left:5px;\n"
"    padding-top:5px;\n"
"    background-color:rgba(150,123,111,255);\n"
"}")
        self.send.setObjectName("send")

####################################################### Button Disconnect ###################################################

        self.disconnect = QtWidgets.QPushButton(self.centralwidget)
        self.disconnect.setGeometry(QtCore.QRect(220, 300, 190, 40))
        font = QtGui.QFont()
        font.setPointSize(11)
        font.setBold(True)
        font.setWeight(75)
        self.disconnect.setFont(font)
        self.disconnect.setStyleSheet("QPushButton#disconnect{\n"
"    background-color: qlineargradient(spread:pad, x1:0, y1:0.505682, x2:1, y2:0.477, stop:0 rgba(11, 131, 120, 219), stop:1 rgba(85, 98, 112, 226));\n"
"    color:rgba(255,255,255,210);\n"
"    border-radius: 5px;\n"
"}\n"
"\n"
"QPushButton#disconnect:hover{\n"
"    background-color: qlineargradient(spread:pad, x1:0, y1:0.505682, x2:1, y2:0.477, stop:0 rgba(150, 123, 111, 219), stop:1 rgba(85, 81, 84, 226));\n"
"}\n"
"\n"
"QPushButton#disconnect:pressed{\n"
"    padding-left:5px;\n"
"    padding-top:5px;\n"
"    background-color:rgba(150,123,111,255);\n"
"}\n"
"\n"
"\n"
"")
        self.disconnect.setObjectName("disconnect")

####################################################### Phần OutPut cho Client ##############################################

        self.listView = QtWidgets.QTextEdit(self.centralwidget)
        self.listView.setGeometry(QtCore.QRect(10, 380, 640, 350))
        self.listView.setObjectName("listView")

######################################################## Currency Input #######################################################

        self.currency = QtWidgets.QLineEdit(self.centralwidget)
        self.currency.setGeometry(QtCore.QRect(370, 130, 220, 40))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.currency.setFont(font)
        self.currency.setStyleSheet("background-color: rgba(0,0,0,0);\n"
"border:none;\n"
"border-bottom:2px solid rgba(46,82,101,200);\n"
"color: rgba(0,0,0,240);\n"
"padding-bottom: 7px;")
        self.currency.setText("")
        self.currency.setObjectName("currency")

#################################################################################################################################

        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Client"))
        MainWindow.setWindowIcon(QtGui.QIcon('client.png'))
        self.message.setPlaceholderText(_translate("MainWindow", "Messenger"))
        self.dateEdit.setPlaceholderText(_translate("MainWindow", "Date"))
        self.bank.setPlaceholderText(_translate("MainWindow", "Bank"))
        self.send.setText(_translate("MainWindow", "Send"))
        self.disconnect.setText(_translate("MainWindow", "Disconnect"))
        self.currency.setPlaceholderText(_translate("MainWindow", "Currency"))

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = UI_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())


import numpy as np
import tensorflow as tf
from tensorflow import keras
import cv2

# Paso 1: Preprocesar las imágenes
# Supongamos que tienes un conjunto de datos etiquetado, donde las imágenes y las etiquetas están en dos listas separadas.
# Aquí, cargamos una imagen de ejemplo y la procesamos para que tenga un tamaño fijo y se normalice.

image = cv2.imread(r"C:\Users\Raderly\Documents\TrabajoTerminal\Algoritmos\espora.jpg")  # Reemplaza 'espora.jpg' con la ruta de tu imagen
# Display the image

image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # Convertir la imagen a escala de grises

image = cv2.resize(image, (128, 128))  # Redimensionar la imagen a un tamaño fijo (ajusta según tus necesidades)
image = image / 255.0  # Normalizar los valores de píxeles al rango [0, 1]
image = np.expand_dims(image, axis=0)  # Agregar una dimensión para crear un lote (batch)

# Paso 2: Definir el modelo de la red neuronal
model = keras.Sequential([
    keras.layers.Flatten(input_shape=(128, 128)),  # Aplanar la imagen
    keras.layers.Dense(128, activation='relu'),  # Capa oculta con activación ReLU
    keras.layers.Dense(2, activation='softmax')  # Capa de salida con dos neuronas (por ejemplo, "espora" y "no espora")
])

# Paso 3: Compilar el modelo
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

# Paso 4: Entrenar el modelo (suponiendo que tengas un conjunto de datos etiquetado)
# X_train contiene tus imágenes de entrenamiento y y_train las etiquetas correspondientes.
# Ajusta estos datos según tu conjunto de datos real.
X_train = image # Ejemplo con una sola imagen de entrenamiento
y_train = np.array([1])  # Suponiendo que 0 representa "espora" y 1 representa "no espora"
#print(X_train.shape)
#print(y_train.shape)

model.fit(X_train, y_train, epochs=10)  # Ajusta el número de épocas según sea necesario

# Paso 5: Hacer predicciones en nuevas imágenes
# Aquí cargamos una nueva imagen (new_image) y hacemos una predicción.
new_image = cv2.imread(r"C:\Users\Raderly\Documents\TrabajoTerminal\Algoritmos\nueva_espora.jpg")  # Reemplaza 'nueva_espora.jpg' con la ruta de tu nueva imagen
new_image = cv2.cvtColor(new_image, cv2.COLOR_BGR2GRAY)
new_image = cv2.resize(new_image, (128, 128))
new_image = new_image / 255.0
new_image = np.expand_dims(new_image, axis=0)

predictions = model.predict(new_image)
predicted_class = np.argmax(predictions)
print(predicted_class)
# La variable 'predicted_class' contendrá la etiqueta predicha (0 para "espora" o 1 para "no espora").


from flask import Flask, render_template, Response, request
# emulated camera
import cv2, numpy as np
from threading import Thread
from darknet import darknet

#1. 사용할 변수 선언
# config_path ="C:/Users/bitcamp/anaconda3/Lib/site-packages/darknet/train/my_yolov3.cfg"
config_path = "D:/python_module/darknet-master/build\darknet/x64/project/myyolov3.cfg"
# weigh_path = "C:/Users/bitcamp/anaconda3/Lib/site-packages/darknet/train/my_yolov3_final.weights"
# weigh_path = "D:/python_module/darknet-master/build/darknet/x64/project/backup/myyolov3_final.weights"
weigh_path = "D:/python_module/darknet-master/build/darknet/x64/project/backup/myyolov3_last.weights"
# meta_path = "C:/Users/bitcamp/anaconda3/Lib/site-packages/darknet/train/my_data.data"
meta_path = "D:/python_module/darknet-master/build\darknet/x64/project/my.data"
# video_path = "C:/Users/bitcamp/anaconda3/Lib/site-packages/darknet/data/video/4-1.mp4"
video_path = "D:/python_module/darknet-master/build\darknet/x64/project/22-2.mp4"
threshold = 0.25

# video1 = "C:/Users/bitcamp/anaconda3/Lib/site-packages/darknet/data/video/16-3.mp4"
# video2 = "C:/Users/bitcamp/anaconda3/Lib/site-packages/darknet/data/video/4-1.mp4"

video1 = "D:/python_module/darknet-master/build\darknet/x64/project/22-2.mp4"
video2 = "D:/python_module/darknet-master/build\darknet/x64/project/26-4.mp4"

#2. 관련 파일 load
# cfg(모델관련)와 weight 파일 아스키코드로 load
net = darknet.load_net(bytes(config_path, "ascii"), bytes(weigh_path, "ascii"), 0)
# data(classes, train, valid, names, backup의 경로가 명시된 텍스트파일)  아스키코드로 load
meta = darknet.load_meta(bytes(meta_path, "ascii"))
# 비디오의 프레임을 추출하는 VideoCapture 함수
cap = cv2.VideoCapture(video_path)

#3. WebcamVideoStream : camera를 thread 이용해서 열어준다
class WebcamVideoStream:
        # camera 시작
       def __init__(self, src=0):
           print("init")
           self.stream = cv2.VideoCapture(src)
           (self.grabbed, self.frame) = self.stream.read()

           self.stopped = False

        # thread를 이용해서 시작
       def start(self):
           print("start thread")
           t = Thread(target=self.update, args=())
           # daemon 쓰레드란 백그라운드에서 실행되는 쓰레드. 메인쓰레드가 종료되면 즉시 종료
           t.daemon = True
           t.start()
           return self

        # 프레임 업데이트
       def update(self):
           print("read")
           while True:
               if self.stopped:
                   return

               (self.grabbed, self.frame) = self.stream.read()

       def read(self):
           return self.frame

       def stop(self):
           self.stopped = True

video = [(1,video1), (2,video2)]
app = Flask(__name__)

@app.route('/')
def run():
    rows = video
    # camera_index.html의 템플릿을 불러온다. 즉, 동영상 리스트를 불러온다
    return render_template("camera_index.html", rows=rows)

@app.route('/index')
def index():
    # http://192.168.0.120:5000/index?id=2
    # request.args는 url 파라미터 값을 키=값 쌍으로 가지고 있는 딕셔너리 형태
    ids = request.args.get('id')
    print(ids)
    rows = video
    return render_template('camera.html', rows=[rows[int(ids)-1]])

def gen(camera):
        # """Video streaming generator function."""
    i = 0
    while True:
        i += 1
        image = camera.read()
        image = cv2.resize(image, dsize=(640, 480), interpolation=cv2.INTER_AREA)
        print(i)
        # if not ret:
            # break
        frame = darknet.nparray_to_image(image)
        r = darknet.detect_image(net, meta, frame, thresh=.5, hier_thresh=.5, nms=.45, debug= False)
        print(r)
        boxes = []

        for k in range(len(r)):
            width = r[k][2][2]
            height = r[k][2][3]
            center_x = r[k][2][0]
            center_y = r[k][2][1]
            bottomLeft_x = center_x - (width / 2)
            bottomLeft_y = center_y - (height / 2)
            x, y, w, h = bottomLeft_x, bottomLeft_y, width, height
            mytexts = r[k][0]
            mythresh = r[k][1]
            boxes.append((x, y, w, h, mytexts, mythresh))
        print(1)

        for k in range(len(boxes)):
            x, y, w, h, texts, threshs = boxes[k]
            top = max(0, np.floor(x + 0.5).astype(int))
            left = max(0, np.floor(y + 0.5).astype(int))
            right = min(image.shape[1], np.floor(x + w + 0.5).astype(int))
            bottom = min(image.shape[0], np.floor(y + h + 0.5).astype(int))
            # cv2.rectangle(image, (top, left), (right, bottom), (0, 255, 0), 1)

            if texts.decode('utf-8') == 'normal':
                cv2.rectangle(image, (top, left), (right, bottom), (255, 0, 0), 2)
                cv2.putText(image, texts.decode('utf-8') + '('+ str(threshs*100)[:5] + '%)', (top, left-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0))

            elif texts.decode('utf-8') == 'fighting':
                cv2.rectangle(image, (top, left), (right, bottom), (0, 0, 255), 2)
                cv2.putText(image, texts.decode('utf-8') + '('+ str(threshs*100)[:5] + '%)', (top, left-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255))

            # cv2.line(image, (top + int(w / 2), left), (top + int(w / 2), left + int(h)), (0,255,0), 3)
            # cv2.line(image, (top, left + int(h / 2)), (top + int(w), left + int(h / 2)), (0,255,0), 3)
            # cv2.circle(image, (top + int(w / 2), left + int(h / 2)), 2, tuple((0,0,255)), 5)

        # cv2.imshow('frame', image)
        # out.write(image)
        ret, jpeg = cv2.imencode('.jpg', image)
        darknet.free_image(frame) ## darknet에서 쓰는 c언어 동적할당 해제해주는 함수(써주어야 메모리가 버틴다.)

        if jpeg is not None:
            yield (b'--frame\r\n'
                    b'Content-Type: image/jpeg\r\n\r\n' + jpeg.tobytes() + b'\r\n')
        else:
            print("frame is none")

@app.route('/index/video_feed')
def video_feed():
        ids = request.args.get('id')
        print(ids)
        """Video streaming route. Put this in the src attribute of an img tag."""
        return Response(gen(WebcamVideoStream(src=video[int(ids)-1][1]).start()),
                       mimetype='multipart/x-mixed-replace; boundary=frame')

if __name__ == '__main__':
       app.run(host='127.0.0.1', debug=True, threaded=True)


# -*- coding: utf-8 -*-
"""
Created on Mon Apr  6 18:50:48 2020

@author: Adref
"""

# This module is here to illustrate the principal points about MapReduce

# Imports

from collections import defaultdict

# Example of a simple function to count words in a collection
# Here we can easily do that

def wordCount(text):
    counts = defaultdict(int)
    for word in text.split():
        counts[word.lower()] += 1
    return counts

'''
Now if we have a text wich has more than a 30 M words we can't do the count with a simple function, thats take a lot of time
In this case we can illustrate the main aspect of MapReduce
We are going to work on two extracts from the text of the song "Le Jour se lève" by Grand Corps Malade

'''

# We supposed that our data is splited and cleaned from the stop words, etc finally we got that

D1 = {"./lot1.txt" : "jour lève notre grissaille"}
D2 = {"./lot2.txt" : "trottoir notre ruelle notre tour"}
D3 = {"./lot3.txt" : "jour lève notre envie vous"}
D4 = {"./lot4.txt" : "faire comprendre tous notre tour"}

def map(key, value):
    intermediate = []
    for word in value.split():
        intermediate.append((word, 1))
    return intermediate

'''
Example :
    (Lot1, "jour lève notre grissaille") -> [(jour, 1), (lève, 1), (notre, 1), (grissaille, 1)]
'''

# now we can go to implement the reduce function
# so we have for each key a list of values, the main goal of reduce is to compute all times the key appear in fragments
# input : (key, list_values) - output : (key, value)
def reduce(key, values):
    result = 0
    for c in values:
        result += c
    return (key, result)

'''
MapReduce -> " divide and rule "

the main steps :
    1. Choose a way to split the data
    2. Choose the key to use for the targeted problem
    3. Write the function code for the MAP operation
    4. Write the function code for the REDUCE operation

'''

# the MapReduce is a good strategy, but it isn't always easy to reformulate
# It's even sometimes impossible  !!!!

# To familiarize with the MapReduce logique we go to implement others examples

'''
First Example: Multiplication (Matrix * Vector) for the famous alogrithm PageRank used to schedule
              the results of a research web

steps :

    - Matrix is stocked as a triplet (i, j, M[i][j]) and we don't represent the 0's positions
    - The same thing for the Vector V (i, V[i])
    - here we have 2 cases:

        ./ Case 1: V is small enough ro fit in the memory of the Map node

            * Map(key, value) will give us the peers (i, M[i][j] * V[i])
                SHUFFLE & SORT : Groups all values assosicieted with the same key i in a pair (i, [v1, v2, ...])
            * Reduce(key, value) will sum all vaulues with a gaven key

        ./ Case 2: V is too large to fit in the memory of the Map node

            Here we have to split V to horizontal stripes and M to virticla stripes and we apply the same strategy
'''

'''
Second Example: Navigate the database tables (Films, directors)

            FILMS(ID_Film*, Title, Nb_hours, #ID_Director)
            Directors(ID_Director*, Name)

the problem can be easy using SQL but when we are in big dimension, here we will need an other solution

we will use Reduce-Side Join (mean that the join operation we will apply it in the REDUCE part)

Steps:

    - Concatination of the tables on one unique table
    - Apply map(key, value) here the key is the name of file (last table) and value is the content <string, int, string>
        example: (123, (Films, Fast&Furious))
    - SHUFFLE & SORT to structure the results of map() as peers (key, [v1, v2, ...])
        example: (123, [(Films, F&F), (Director, James)])
    - Apply reduce(key, value) collect the films title for the same director

'''

def map(key,value):
    intermediate = []
    for i in value:
        intermediate.append((i[1], (i[0], i[1:])))
    return intermediate


import streamlit as st
from cg_utils import *

# Get text-to-text FMs
t2t_fms = get_t2t_fms(fm_vendors)
# Programming languages for code translation
pr_langs = ["C++", "Java", "JavaScript", "Python", "COBOL", "Go"]
# Construct promt template for code translation
prompt_template = """
You are an expert software developer in {tgt_lang}.
You will translate the code below from to {tgt_lang} while following coding best practices and accurate syntax.

{code}

"""

def main():
    """Main function for app"""
    st.set_page_config(page_title="Amazon Bedrock Playpen", layout="wide")
    css = '''

    '''
    st.write(css, unsafe_allow_html=True)
    st.header("Code Translation with Amazon Bedrock FMs")
    st.markdown("Select a **foundation model** and a target **programming language**, enter **code**,  and click **Translate**! Refer the [Demo Overview](Solutions%20Overview) for a description of the solution.")
    col1, col2, col3 = st.columns([0.8,2,2])
    with col1:
        # st.markdown("

", unsafe_allow_html=True)
        fm = st.selectbox('Select Foundation Model',t2t_fms,key="fm_key")
        tgt_lang = st.selectbox("Select target programming language", pr_langs, key="tgt_lang_key")
        fm_prompt_validation = st.empty()
        if "src_lang_code_key" not in st.session_state:
            st.session_state.src_lang_code_key = ""
        if "tgt_code" not in st.session_state:
            tgt_code = ""
        if st.button("Translate", type="primary"):
            if len(st.session_state.src_lang_code_key) < 50:
                with fm_prompt_validation.container():
                    st.error('Your question must contain at least 50 characters.', icon="ðŸš¨")
            else:
                prompt = prompt_template.format(code=st.session_state.src_lang_code_key, tgt_lang=st.session_state.tgt_lang_key)
                tgt_code = f"
{ask_fm(st.session_state.fm_key,prompt)}
"
    with col2:
        src_lang_code = st.text_area("Enter code to be translated in the text area below:",key="src_lang_code_key")
    with col3:
        # st.markdown("

", unsafe_allow_html=True)
        st.markdown(tgt_code, unsafe_allow_html=True)

# Main
if __name__ == "__main__":
    main()


'''
Coding: utf-8
Author: vector-wlc
Date: 2022-12-30 20:28:52
Description:
'''
import torch
import numpy as np

def load_data(npy_dir: str, train_rate: float = 0.75, batch_size: int = 64) -> tuple:
    x = np.load(npy_dir + "x.npy")
    y = np.load(npy_dir + "y.npy")
    # 由于 x 的数据维度要求为 N 1 C T， 至于为什么第二维多了一个看似没有意义的 1
    # 是因为在图像处理那边，图片的数据集的维度就是 N 3 W H，3 就是图片的 RGB 通道

    x = torch.from_numpy(x).float()
    y = torch.from_numpy(y)
    x = torch.unsqueeze(x, 1)

    total_num = len(x)
    train_num = int(total_num * train_rate)
    train_dataset = torch.utils.data.TensorDataset(
        x[:train_num], y[:train_num])
    test_dataset = torch.utils.data.TensorDataset(
        x[train_num:], y[train_num:])
    train_data_loader = torch.utils.data.DataLoader(
        dataset=train_dataset,
        batch_size=batch_size,
        shuffle=True
    )
    test_data_loader = torch.utils.data.DataLoader(
        dataset=test_dataset,
        batch_size=batch_size,
        shuffle=False
    )

    return train_data_loader, test_data_loader

def train_model(train_loader, model, epochs):
    device = torch.device(
        "cuda" if torch.cuda.is_available() else "cpu")
    model = model.to(device)
    loss_func = torch.nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(
        model.parameters()
    )

    for epoch in range(epochs):
        running_loss = 0.0
        batch_size = None
        size_loss = 0
        for index, data in enumerate(train_loader):
            x, y = data
            x = x.to(device)
            y = y.to(device)
            model_out = model(x)

            loss = loss_func(model_out, y.long())
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            running_loss += float(loss.item())
        print(
            f'\repochs: {epoch + 1} / {epochs}\tTrain loss: {running_loss:.4f}', end='')
    print('\nFinish Training!')

def test_model(test_loader, model):
    device = torch.device(
        "cuda" if torch.cuda.is_available() else "cpu")
    model = model.to(device)
    correct_num = 0
    total_num = 0
    for index, data in enumerate(test_loader):
        x, y = data
        x = x.to(device)
        y = y.to(device)
        model_out = model(x)

        _, pred = torch.max(model_out, 1)
        correct_num += np.sum(
            pred.cpu().numpy() == y.cpu().numpy()
        )
        total_num += len(y)
    print('\nTest acc: ' + str(correct_num / total_num))


# Consecutive prime sum
#
# The prime 41, can be written as the sum of six consecutive primes:
#
# 41 = 2 + 3 + 5 + 7 + 11 + 13
# This is the longest sum of consecutive primes that adds to a prime below one-hundred.
#
# The longest sum of consecutive primes below one-thousand that adds to a prime, contains 21 terms, and is equal to 953.
#
# Which prime, below one-million, can be written as the sum of the most consecutive primes?

# !!! work only if you know numbers 'below' and 'terms' !!!

import sympy

def prime_(below):
    prime_numbers = []
    n = 1
    while True:
        if sympy.isprime(n):
            if n < below:
                prime_numbers.append(n)
            else:
                break
        n += 1
    return prime_numbers

def prime_sum(below, terms):
    list_ = prime_(below)
    result = 0
    a, b = 0, terms
    while True:
        if result < sum(list_[a:b]):
            result = sum(list_[a:b])
        a += 1
        b += 1
        if result >= below:
            break
        print(result)

if __name__ == '__main__':
    prime_sum(1000000, 543)


# %% [markdown]
# # Assignment 4
# | Topic | Information |
# | --------  |  -------- |
# | Team Members       | Antonio Cascio & Krystian Confeiteiro |
# | Professor  | Dr. Jack |
# | Course     | DS 440 - 01DB |
# | Assignment | Assignment 4 |
# | Date       | 09/29/2023 (submitted **10/03/2023**) |
#
# ## Assignment Objective
# Use [seaborn](https://seaborn.pydata.org/) to do [explorative data analysis (EDA)](https://en.wikipedia.org/wiki/Exploratory_data_analysis) with this `.csv` file in Google Colab, generate 5 different graphs and explain the results in the resultant graphs using the flight delay statistics of flights from Daytona Beach to ATL and CLT are recorded from [FAA ASPM website](https://aspm.faa.gov/apm/sys/main.asp) and saved in `DS440_assignment4_data_FA23.csv` from the [DS 440 - Assignment 4 FA23 Canvas page](https://erau.instructure.com/courses/163647/assignments/3312890#submit). You can *also* download the data from in our [Assignment 4 Google Drive folder](https://drive.google.com/drive/folders/1wWIdr0zu7_Q7yCXqqM01zviF58LwTHqo?usp=sharing).
#
# # Assignment Layout
# - Part 1
#   - Reading & analysis of data
#   - Discuss analysis of the data
# - Part 2
#   - Plotting & data visualization
#   - Make five plots and discuss them
#
# ## Part Sources
# ### Part 1
# - Type(s) of statistical analysis
#     - Descriptive statistics
#     - Probability distributions
#     - Multivariate analysis
# - Types of plots
#   1. Heatmap
#   2. Horizontal bar plot
#   3. Conditional kernel density estimate
#   4. Diagonal correlation matrix
#   5. Histogram
#
# # Assignment Checklist
# - Read the dataset with [pandas](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.shape.html) or [seaborn](https://seaborn.pydata.org/)
# - Complete explorative data analysis on the flight delay statistics dataset
# - Create five plots
# - Plot explanations

# %% [markdown]
# # Part 1

# %% [markdown]
# ## Reading & Analysis

# %%
import pandas as pd

# read data with pandas
DATA = pd.read_csv("DS440_assignment4_data_FA23.csv")
DESCRIPTION = DATA.describe()

print("Dataset shape:\n", DATA.shape)
print("Dataset:")
DATA.head(15)

# %%
print("\nDescriptive analysis of dataset:\n-------------------------------\n")

# %%
import warnings
from typing import Literal, Tuple

import seaborn as sns
from matplotlib import pyplot as plt
from pandas import DataFrame

warnings.filterwarnings("ignore")

def plt_catplot(
    data: DataFrame = None,
    xy_hue: Tuple[str, str, str] = None,
    save_as: str = None,
    plt_type: Literal["bar", "violin", "swarm"] = None,
):
    if plt_type in {"bar", "violin", "swarm"}:
        FIG = sns.catplot(
            data=data, kind=plt_type, x=xy_hue[0], y=xy_hue[1], hue=xy_hue[2]
        )
        if save_as:
            FIG.savefig(save_as)
    elif not plt_type:
        for plttype in ["bar", "violin", "swarm"]:
            FIG2 = sns.catplot(
                data=data, kind=plttype, x=xy_hue[0], y=xy_hue[1], hue=xy_hue[2]
            )
            FIG2.savefig(f"{plttype}.jpg")

XY_HUE = ("GateDepartureDelay", "ArrivalHour", "FlightCount")
with plt.ioff():
    # bar, swarm, and violin plots
    plt_catplot(DATA, XY_HUE)

    # line plot
    fig = sns.lineplot(x=XY_HUE[0], y=XY_HUE[1], hue=XY_HUE[2], data=DATA)
    fig = fig.get_figure()
    fig.savefig("lineplot.jpg")

    # final plot: grouped barplot
    X, Y, HUE = "FlightCount", "DepartureHour", "Arrival"
    G = sns.catplot(
        data=DATA,
        kind="bar",
        x=X,
        y=Y,
        hue=HUE,
        errorbar="sd",
        palette="dark",
        alpha=0.6,
        height=6,
    )

    G.despine(left=True)
    G.set_axis_labels("On time Dept.", "On Time Arrivals")
    G.legend.set_title("Depts. & Arrivals")
    G.savefig("grouped_bar.jpg")

Fall 2023/DS 440/(001) Assignments/Assignment 4/cascio_and_confeiteiro_DS440_assignment_4.py


import pandas as pd
import csv
from collections import defaultdict, Counter

#Percentage of Hobbyist & not Hobbyist. [%age of people coding as a hobby??]
with open('survey_results_public.csv') as f:
    csv_reader = csv.DictReader(f)

    #hobbyist_counter= {'Yes':0,
    #                  'No': 0
    #                 }
    #hobbyist_counter = defaultdict(int)
    hobbyist_counter = Counter()

    for line in csv_reader:
        hobbyist_counter[line["Hobbyist"]] += 1

    total = hobbyist_counter['Yes'] + hobbyist_counter['No']

    percentage_yes = hobbyist_counter['Yes']/total * 100
    percentage_yes = round(percentage_yes,2)

    percentage_no = hobbyist_counter['No']/total * 100
    percentage_no = round(percentage_no,2)

    print(f'Percentage of people that do coding as a hobby: {percentage_yes}')
    print(f'Percentage of people that don\'t coding as a hobby: {percentage_no}')

#for plotting results
from matplotlib import pyplot as plt
plt.style.use('fivethirtyeight')

slices = [ percentage_yes, percentage_no ]
labels = ['people that like', 'people that don\'t']
explode= [ 0, 0.1 ]

plt.pie(slices, labels=labels, wedgeprops={'edgecolor':'black'},
        explode=explode,shadow=True, startangle=90, autopct='%1.1f%%')
plt.title("Coding As a Hobby")
plt.tight_layout()
plt.show()


import logging
import json
import azure.functions as func
from .classes import Dolar

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    try:
        dolar = Dolar()

        value = dolar.get_value()
    except:
        value = 'None'

    if value:
        return func.HttpResponse(
            json.dumps(value)
        )
    else:
        return func.HttpResponse(
            {'error': '400'},
            status_code=100
        )


import os
import json

def get_prefills():
	res = dict()

	session_dirs = [d for d in os.listdir() if "Session " in d]

	for dn in session_dirs:
		path = os.path.join(dn, "Preparation")

		if not os.path.isdir(path):
			continue

		k = int(dn.split("Session ")[1])
		v = [f.split(".")[0] for f in os.listdir(path) if ".pdf" == f[-4:] and len(f.split(".")[0]) == 8]

		res[k] = v

	with open("prefills.json", "w") as f:
		json.dump(res, f, sort_keys=True, indent=4)

if __name__ == "__main__":
	get_prefills()


from __future__ import annotations

from argparse import ArgumentParser
from typing import Sequence
from coverage import Coverage, CoverageException

def make_html_report(db: str, report: str) -> int:
    try:
        cov = Coverage(db)
        cov.load()
        cov.html_report(directory=report)
        return 0

    except CoverageException as e:
        print(str(e))
        return 1

def main(argv: Sequence[str] | None = None) -> int:
    parser = ArgumentParser()
    parser.add_argument("--input", type=str, default="./test.coverage", help="Coverage report file")
    parser.add_argument("--output", type=str, default="./htmlcov", help="Coverage html report path")
    args = parser.parse_args(argv)
    return make_html_report(
        db=args.input,
        report=args.output,
    )

if __name__ == "__main__":
    raise SystemExit(main())


from collections import deque
from typing import List, Tuple
from agent import Agent
from tqdm import tqdm
import numpy as np
from unityagents import UnityEnvironment
import logging
from matplotlib import pyplot as plt

def ddpg_train(agent: Agent, env: UnityEnvironment, n_episodes=2000, max_t=1000, print_every=100, min_mean_score=30) -> List[float]:
    """
    Train the agent using DDPG algorithm with the given environment.

    :param agent: Agent to train,
    :param env: Unity environment,
    :param n_episodes: Number of episodes to train the agent,
    :param max_t: Maximum number of time steps per episode
    :param print_every: Print the average score every print_every episode
    :param min_mean_score: Minimum mean score to stop the training

    :return: List of scores
    """

    # Extract the default brain
    brain_name = env.brain_names[0]

    scores = []
    scores_window = deque(maxlen=100)

    # Loop over episodes
    for episode in tqdm(range(n_episodes)):
        env_info = env.reset(train_mode=True)[brain_name]            # reset the environment
        num_agents = len(env_info.agents)                            # get the number of agents (constant for all episodes)
        states = env_info.vector_observations                        # get the current state (for each agent)
        agent.reset()                                                # reset the agent noise
        score = np.zeros(num_agents)                                 # initialize the score (for each agent)

        # Loop over time steps, until the episode is done or max_t is reached
        for t in range(max_t):
            actions = agent.act(states)                              # select an action (for each agent)

            env_info = env.step(actions)[brain_name]                 # send the action to the environment
            next_states = env_info.vector_observations               # get the next states (for each agent)
            rewards = env_info.rewards                               # get the rewards (for each agent)
            dones = env_info.local_done                              # see if episodes have finished (for each agent)

            agent.step(states, actions, rewards, next_states, dones) # update the agents
            score += rewards                                         # update the scores (for each agent)
            states = next_states                                     # roll over the state to next time step (for each agent)

            if np.any(dones):                                      # exit loop if episode finished for any agent
                break

        agent.checkpoint()                                           # save the model weights

        scores.append(np.mean(score))                                # save the average score
        scores_window.append(np.mean(score))                         # save the average score for the last 100 episodes

        if episode % print_every == 0:
            logging.info('\rEpisode: \t{} \tScore: \t{:.2f} \tAverage Score: \t{:.2f}'.format(episode, np.mean(score), np.mean(scores_window)))

        if np.mean(scores_window) >= min_mean_score:
            logging.info('\nEnvironment solved in {:d} episodes!\tAverage Score: {:.2f}'.format(episode, np.mean(scores_window)))
            break

    plt.plot(np.arange(1, len(scores)+1), scores)
    plt.ylabel('Score')
    plt.xlabel('Episode #')
    plt.show()

    return scores


import plotly.express as px
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots

df_dates = pd.DataFrame()
df_covid_data = None
df_covid = None
df_normal = None

collisions_borough_covid = None

collisions_borough_normal = None

def initialize_values(df):
    global df_dates
    global df_covid_data
    global df_covid
    global df_normal
    global collisions_borough_covid
    global collisions_borough_normal

    df_dates['Crash count per day'] = df['CRASH DATE'].value_counts()
    df_dates['Injured persons per day'] = df.groupby('CRASH DATE').sum().loc[:,'NUMBER OF PERSONS INJURED']
    df_dates['Killed persons per day'] = df.groupby('CRASH DATE').sum().loc[:,'NUMBER OF PERSONS KILLED']
    df_dates.index.name="Date"
    df_dates = df_dates.reset_index()
    df_dates['Year'] = df_dates['Date'].dt.year

    df_covid_data = pd.read_csv("data/NYC_covid19_filtered_file.csv")
    df_covid_data['DATE_OF_INTEREST'] = pd.to_datetime(df_covid_data['DATE_OF_INTEREST'])

    df_covid = df[df['CRASH DATE'] >= '03/1/2020']
    df_normal = df[df['CRASH DATE'] < '03/1/2020']

    collisions_borough_covid = df_covid['BOROUGH'].value_counts()
    collisions_borough_normal = df_normal['BOROUGH'].value_counts()

def covid19_nyc_fig(df):
    if (df_covid_data == None):
        initialize_values(df)

    fig = px.line(x=df_covid_data['DATE_OF_INTEREST'], y=df_covid_data['CASE_COUNT'],labels={'x': 'Date', 'y': 'Amount of COVID19 cases'},
        title="Confirmed COVID19 cases in NYC plotted versus dates in 2020")
    return fig

def covid19_time_incidents_fig(df):
    # input df_dates
    fig = px.scatter(df_dates, x="Date", y=["Crash count per day","Injured persons per day"],
        title='Change in Number of Incidents over Time' ,range_x=['2012-07-01','2021-03-26'], range_y=[0,1200]
        ,labels={'variable':''})
    fig.update_layout(yaxis_title='Count per Day', legend=dict(orientation="h",yanchor="bottom",y=1.0,xanchor="left",x=0), )

    fig.add_vline(x='2020-03-01')
    fig.add_annotation(x='2020-03-01', y=1000,text="1st of March of 2020                                  ", showarrow=True,align='left', font=dict(size=16),valign="bottom")
    fig.add_annotation(x='2020-03-01', y=1200,text="""First confirmed COVID-19 case in NYC""",showarrow=True,yshift=1,font=dict(size=16))
    fig.add_annotation(x='2016-03-01', y=1100,text="""No COVID""",showarrow=False,yshift=1,font=dict(size=16))
    fig.add_annotation(x='2020-10-01', y=1100,text="""COVID""",showarrow=False,yshift=1,font=dict(size=16))

    fig.add_vrect(x0='2020-03-01', x1='2021-11-01', line_width=0, fillcolor="red", opacity=0.2)
    fig.add_vrect(x0='2012-01-01', x1='2020-03-01', line_width=0, fillcolor="green", opacity=0.2)
    return fig

def covid_19_incidents_cases_fig(df):
    subfig = make_subplots(specs=[[{"secondary_y": True}]])

    # create two independent figures with px.line each containing data from multiple columns
    fig = px.scatter(df_dates[df_dates['Year']>2019], x='Date', y=['Crash count per day', 'Injured persons per day',],range_y=[0,100])
    fig2 = px.line(df_covid_data,x='DATE_OF_INTEREST' ,y=['CASE_COUNT'])

    fig2.update_traces(yaxis="y2")
    subfig.add_traces(fig.data + fig2.data)
    subfig.layout.xaxis.title="Date"
    subfig.layout.title= 'Change in Incidents over Time and Daily Corona Cases'
    subfig.layout.yaxis.title="Count per Day"
    subfig.layout.yaxis2.title="New daily COVID Cases"
    subfig.update_xaxes(range=['2020-02-01', '2021-01-01'], row=1, col=1)
    subfig.for_each_trace(lambda t: t.update(line=dict(color=t.marker.color)))
    subfig.update_layout(legend=dict(orientation="h",yanchor="bottom",y=1.0,xanchor="left",x=0))
    return subfig

def covid_19_killed_pr_col_fig(df, boroughs):
    persons_killed_borough_covid = df_covid.groupby(df_covid['BOROUGH'])['NUMBER OF PERSONS KILLED'].sum()
    persons_killed_per_collisions_borough_covid = persons_killed_borough_covid/collisions_borough_covid
    persons_killed_borough_normal = df_normal.groupby(df_normal['BOROUGH'])['NUMBER OF PERSONS KILLED'].sum()
    persons_killed_per_collisions_borough_normal = persons_killed_borough_normal/collisions_borough_normal

    fig = go.Figure(data=[
        go.Bar(name='No COVID', x=boroughs, y=persons_killed_per_collisions_borough_normal),
        go.Bar(name='COVID', x=boroughs, y=persons_killed_per_collisions_borough_covid)
    ])
    fig.update_layout(title='Persons killed per collision across boroughs',barmode='group', yaxis_title='Persons killed per collision',
        xaxis_title='Borough',legend=dict(orientation="h",yanchor="bottom",y=1.02,xanchor="right",x=1),
        margin=dict(l=0, r=0, t=100, b=100),
    )
    return fig

def covid_19_injured_pr_col_fig(df, boroughs):
    persons_injured_borough_covid = df_covid.groupby(df_covid['BOROUGH'])['NUMBER OF PERSONS INJURED'].sum()
    persons_injured_per_collisions_borough_covid = persons_injured_borough_covid/collisions_borough_covid
    persons_injured_borough_normal = df_normal.groupby(df_normal['BOROUGH'])['NUMBER OF PERSONS INJURED'].sum()
    persons_injured_per_collisions_borough_normal = persons_injured_borough_normal/collisions_borough_normal

    fig = go.Figure(data=[
        go.Bar(name='No COVID', x=boroughs, y=persons_injured_per_collisions_borough_normal),
        go.Bar(name='COVID', x=boroughs, y=persons_injured_per_collisions_borough_covid)
    ])
    fig.update_layout(title='Persons injured per collision across boroughs',barmode='group',  yaxis_title='Persons injured per collision',
        xaxis_title='Borough',legend=dict( orientation="h",yanchor="bottom",y=1.02,xanchor="right",x=1),
        margin=dict(l=0, r=0, t=100, b=100),
        )
    return fig

def covid_19_crashes_factors_fig(df):
    crash_count_normal = df_normal['CRASH DATE'].value_counts().sum()
    crash_count_covid = df_covid['CRASH DATE'].value_counts().sum()

    factor_1_n = df_normal.groupby('CONTRIBUTING FACTOR VEHICLE 1').count().sort_values(by='CRASH DATE').iloc[:,0]
    factor_1_c = df_covid.groupby('CONTRIBUTING FACTOR VEHICLE 1').count().sort_values(by='CRASH DATE').iloc[:,0]

    factor_1_c = factor_1_c.sort_values()
    factor_1_n = factor_1_n.reindex(factor_1_c.index)
    n= 18
    fig = go.Figure(data=[
        go.Bar(name='No COVID', x=factor_1_n.index[-n:-1], y=factor_1_n.values[-n:-1]/crash_count_normal*100),
        go.Bar(name='COVID', x=factor_1_c.index[-n:-1], y=factor_1_c.values[-n:-1]/crash_count_covid*100)
    ])
    # Change the bar mode
    fig.update_layout(title='Factors for Crashes',yaxis_title='Percent of Total Number of Crashes' ,barmode='group',xaxis_title='Collision factor',
        legend=dict( orientation="h",yanchor="bottom",y=1.02,xanchor="right",x=1), margin=dict(l=0, r=0, t=100, b=100),
    )
    return fig


from typing import List , Callable , Optional , Awaitable
import databases
import sqlalchemy
from fastapi import FastAPI , Request , HTTPException
from fastapi.responses import HTMLResponse , FileResponse
from pydantic import BaseModel
from datetime import datetime
import asyncio
from functools import wraps
from fastapi.templating import Jinja2Templates

templates = Jinja2Templates(directory="templates")

# SQLAlchemy specific code, as with any other app
DATABASE_URL = "sqlite:///./secret_database.db"
# DATABASE_URL = "postgresql://user:password@postgresserver/db"

database = databases.Database(DATABASE_URL)

metadata = sqlalchemy.MetaData()

secrets = sqlalchemy.Table(
    "secrets",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.String, primary_key=True),
    sqlalchemy.Column("ciphertext", sqlalchemy.String),
    sqlalchemy.Column("timestamp" , sqlalchemy.Integer )
)

public_keys_table = sqlalchemy.Table(
    "publickeys",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.String, primary_key=True),
    sqlalchemy.Column("publickey" , sqlalchemy.String ),
    sqlalchemy.Column("timestamp" , sqlalchemy.Integer )
)
engine = sqlalchemy.create_engine(
    DATABASE_URL, connect_args={"check_same_thread": False}
)
metadata.create_all(engine)

class SecretIn(BaseModel):
    ciphertext: str
    id: str

class SecretOut(BaseModel):
    id: str
    ciphertext: str

class PublicKey(BaseModel):
    id:str
    publickey:str

app = FastAPI()

@app.on_event("startup")
async def startup():
    await database.connect()

@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()

@app.get("/doc_image")
async def doc_image():
    return FileResponse("share-secret-wf.jpg")

@app.get("/documentation", response_class=HTMLResponse)
async def doc_page(request: Request):
    return templates.TemplateResponse("doc.html",{"request": request})

@app.get("/start", response_class=HTMLResponse)
async def start_page(request: Request):
    return templates.TemplateResponse("start.html",{"request": request})

@app.get("/secrets/{item_id}", response_class=HTMLResponse)
async def read_secrets(request: Request, item_id : str):
    query = secrets.select().where(secrets.columns.id==item_id)
    result = await database.fetch_all(query)
    await database.execute(secrets.delete().where(secrets.columns.id==item_id))
    if not result :
        raise HTTPException(status_code=404,detail="Item not found",headers={"X-Error": "The item is missing or previously deleted"},)
    return templates.TemplateResponse("deliver.html", {"request": request, "id": result[0][0] , "ciphertext" : result[0][1]})

@app.get("/sendsecret/{item_id}", response_class=HTMLResponse)
async def read_keyss(request: Request, item_id : str):
    query = public_keys_table.select().where(public_keys_table.columns.id==item_id)
    result = await database.fetch_all(query)
    await database.execute(public_keys_table.delete().where(public_keys_table.columns.id==item_id))
    if not result :
        raise HTTPException(status_code=404,detail="Item not found",headers={"X-Error": "The item is missing or previously deleted"},)
    return templates.TemplateResponse("item2.html", {"request": request, "id": result[0][0] , "publickey" : result[0][1]})

@app.post("/addSecret/", response_model=SecretOut)
async def create_secret(secret: SecretIn):
    now_time = int(datetime.timestamp(datetime.now()))
    query = secrets.insert().values(ciphertext=secret.ciphertext, id=secret.id , timestamp=now_time)
    last_record_id = await database.execute(query)
    return {**secret.dict(), "id": last_record_id}

@app.post("/addReceiverPK/", response_model=PublicKey)
async def create_publickey(pk: PublicKey):
    now_time = int(datetime.timestamp(datetime.now()))
    query = public_keys_table.insert().values(publickey=pk.publickey, id=pk.id , timestamp=now_time)
    last_record_id = await database.execute(query)
    return {**pk.dict(), "id": last_record_id}

def repeat_every(*, seconds: float, wait_first: bool = False):
    def decorator(func: Callable[[], Optional[Awaitable[None]]]):
        is_coroutine = asyncio.iscoroutinefunction(func)

        @wraps(func)
        async def wrapped():
            async def loop():
                if wait_first:
                    await asyncio.sleep(seconds)
                while True:
                    try:
                        if is_coroutine:
                            await func()
                        else:
                            await run_in_threadpool(func)
                    except Exception as e:
                        #logger.error(str(e))
                        pass
                    await asyncio.sleep(seconds)

            asyncio.create_task(loop())

        return wrapped

    return decorator

async def delete_entry(table) :
    query = table.select()
    result = await database.fetch_all(query)
    if result :
        expired = list()
        now_time = int(datetime.timestamp(datetime.now()))
        for x in result :
            if now_time - x[2] > 60 * 60 * 24 :
                expired.append(x[0])
        for entry in expired :
            await database.execute(table.delete().where(table.columns.id==entry))

@app.on_event("startup")
@repeat_every(seconds=100)  # 24 hours
async def delete_old_entries():
    await delete_entry(secrets)
    await delete_entry(public_keys_table)


from collections import deque
import sys
input = sys.stdin.readline

# 변수 선언
N = int(input())
RGB = [list(map(str, input().strip())) for _ in range(N)]
visit = [[False for _ in range(N)] for _ in range(N)]
answer = [0, 0]
queue = deque()

# bfs 선언
def bfs(x, y):
    queue.append([x, y])
    visit[x][y] = True
    color = RGB[x][y]

    while queue:
        x, y = queue.popleft()
        dx = [1, -1, 0, 0]
        dy = [0, 0, 1, -1]

        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0 <= nx < N and 0 <= ny < N:
                # 색깔이 같고, 방문하지 않았다면 다음 탐색 대상
                if color == RGB[nx][ny] and not visit[nx][ny]:
                    queue.append([nx, ny])
                    visit[nx][ny] = True
    return None

# 탐색 시작: 일반인일때
for x in range(N):
    for y in range(N):
        if not visit[x][y]:
            bfs(x, y)
            answer[0] += 1

# 적녹색약은 빨강과 그린을 구별할 수 없다. 따라서 R 또는 G를 둘 중 하나로 통일한다.
for x in range(N):
    for y in range(N):
        if RGB[x][y] == 'G':
            RGB[x][y] = 'R'

# 재탐색해야 되니 방문 기록을 초기화해주자
visit = [[False for _ in range(N)] for _ in range(N)]

# 탐색 시작: 적녹색약일때
for x in range(N):
    for y in range(N):
        if not visit[x][y]:
            bfs(x, y)
            answer[1] += 1

# 정답 출력
for i in range(2):
    print(answer[i], end=" ")


from tqdm import tqdm
from dataset import SentimentClassifierDataset
from torch.utils.data import DataLoader
import config
import torch
import numpy as np
from sklearn import svm

def get_features(model, train=True, text=None):
    if train == True:
        dataset = SentimentClassifierDataset()
        n_samples = len(dataset)
        train_dataloader = DataLoader(
            dataset, batch_size=config.BATCH_SIZE, shuffle=False)
        labels = []
        features = []
        device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
        model.to(device)
        with torch.no_grad():
            for ind, d in tqdm(enumerate(train_dataloader), total=len(train_dataloader)):
                input_ids = d['input_ids'].to(device).long()
                attention_mask = d['attention_mask'].to(device).long()
                label = np.array(d['label'])
                labels.extend(label)
                feature = model(input_ids, attention_mask)
                features.extend(feature)
                del ind
                del d
        return np.array(features), np.array(labels)

    else:
        device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
        model.to(device)
        dataset = SentimentClassifierDataset(train=False, text=text)
        input_ids = [dataset.get_tokens(dataset.data)]
        attention_mask = dataset.get_attention_mask(np.array(input_ids[0]))

        with torch.no_grad():
            input_ids = torch.tensor(input_ids).to(device).long()
            attention_mask = torch.tensor(attention_mask).to(device).long()
            feature = model(input_ids, attention_mask)

        return np.array(feature)

def train_fn(X_train, y_train):
    clf = svm.SVC()
    clf.fit(X_train, y_train)
    return clf

def eval_fn(clf, X_test):
    return clf.predict(X_test)

def test_results(clf, test_data):
    return clf.predict(test_data)