###############################################
# Author: Aniruddha Gokhale
# Updated by: Patrick Muradaz
# Vanderbilt University
# Purpose: Subscriber application for PAs
# Semester: Spring 2023
###############################################
#
# The key steps for the subscriber application are
# (1) parse command line and configure application level parameters
# (2) obtain the subscriber middleware object and configure it.
# (3) As in the publisher, register ourselves with the discovery service
# (4) since we are a subscriber, we need to ask the discovery service to
#     let us know of each publisher that publishes the topic of interest to
#     us. Then our middleware object will connect its SUB socket to all these
#     publishers for the Direct strategy else connect just to the broker.
# (5) Subscriber will always be in an event loop waiting for some matching
#     publication to show up. We also compute the latency for dissemination and
#     store all these time series data in some database for later analytics.
#
# Import statements
import sys, os, time, argparse, configparser, logging, random
sys.path.append(os.getcwd())
from Apps.Common.common import handle_exception, dump
from Apps.Common.topic_selector import TopicSelector
from Apps.Subscriber.middleware import SubscriberMW

"""SubscriberAppln class"""
class SubscriberAppln():

  """constructor"""
  def __init__(self, logger):
    self.logger = logger      # internal logger for print statements
    self.name = None          # our name (some unique name)
    self.addr = None          # our advertised IP address
    self.port = None          # port num where we are going to publish our topics
    self.topiclist = None     # the different topics that we subscribe to
    self.lookup = None        # one of the diff ways we do lookup
    self.dissemination = None # direct or via broker
    self.mw_obj = None        # handle to the underlying Middleware object

  """configure/initialize"""
  def configure(self, args):
    try:
      self.logger.debug("SubscriberAppln::configure")
      # initialize our variables
      self.name = args.name
      self.port = args.port
      self.addr = args.addr
      # Now, get the configuration object
      config = configparser.ConfigParser()
      config.read(args.config)
      self.lookup = config["Discovery"]["Strategy"]
      self.dissemination = config["Dissemination"]["Strategy"]
      # Now get our topic list of interest
      ts = TopicSelector()
      # self.topiclist = ts.interest()
      self.topiclist = ["light", "humidity"]
      # Now setup up our underlying middleware object
      self.mw_obj = SubscriberMW(self.logger)
      self.mw_obj.configure(args)
      self.logger.info("Subscriber app configured.")
      dump(self.logger, "SubscriberAppln", self.addr, self.port,
           name=self.name, topiclist=self.topiclist)
    except Exception as e: handle_exception(e)

  """driver program"""
  def driver(self):
    try:
      self.logger.debug("SubscriberAppln::driver")
      # Use middleware to register us with the discovery service
      self.logger.info("Registering app with discovery service.")
      result = self.mw_obj.register(self.name, self.topiclist)
      self.logger.debug(f"SubscriberAppln::driver - result: {str(result)}")
      self.logger.info("Subscriber app registered.")
      # Keep checking with the discovery service if we are ready to go
      self.logger.info("Waiting for all ready from discovery service.")
      while(not self.mw_obj.is_ready()): time.sleep(0.5)  # sleep between calls
      self.logger.info("All sub and pub apps registered and ready.")
      time.sleep(random.uniform(0.0, 1.0)) # sleep for a bit to not overwhelm system
      # Now, find the publishers that match our topics
      self.logger.info("Locating all publishers for our topics.")
      pubs = self.mw_obj.locate_pubs(self.topiclist)
      # Finally, subscribe and listen to the publishers
      self.logger.info("Subscribing to relevant publishers.")
      self.mw_obj.sub_to_pubs(pubs, self.topiclist)
    except Exception as e: handle_exception(e)

"""Parse command line arguments"""
def parseCmdLineArgs():
  # instantiate a ArgumentParser object
  parser = argparse.ArgumentParser(description="Subscriber Application")
  # Now specify all the optional arguments we support
  parser.add_argument(
    "-n", "--name", default="sub",
    help="Some name assigned to us. Keep it unique per subscriber."
  )
  parser.add_argument(
    "-a", "--addr", default="localhost",
    help="IP addr of this subscriber to advertise (default: localhost)"
  )
  parser.add_argument(
    "-p", "--port", default="5566",
    help="Port number on which our underlying subscriber ZMQ service runs, " +
      "default=5566"
  )
  parser.add_argument(
    "-d", "--discovery", default="localhost:5555",
     help="IP Addr:Port combo for the discovery service, " +
      "default localhost:5555"
  )
  parser.add_argument(
    "-c", "--config", default="Apps/Common/config.ini",
    help="configuration file (default: Apps/Common/config.ini)"
  )
  parser.add_argument(
    "-l", "--loglevel", type=int, default=logging.INFO,
    choices=[
      logging.DEBUG,logging.INFO,logging.WARNING,
      logging.ERROR,logging.CRITICAL
    ],
    help="logging level, choices 10,20,30,40,50: default 20=logging.INFO"
  )
  return parser.parse_args()

"""Main program"""
def main():
  try:
    # obtain a system wide logger and initialize it to debug to begin with
    logging.debug("Main - acquire a child logger to log messages in")
    logger = logging.getLogger("SubAppln")
    # first parse the arguments
    logger.debug("Main: parse command line arguments")
    args = parseCmdLineArgs()
    # reset the log level to as specified
    logger.debug("Main: resetting log level to {}".format(args.loglevel))
    logger.setLevel(args.loglevel)
    logger.debug("Main: effective log level is {}".format(logger.getEffectiveLevel()))
    # Obtain a subscriber application
    logger.debug("Main: obtain the object")
    sub_app = SubscriberAppln(logger) # get the object
    sub_app.configure(args)           # configure the object
    sub_app.driver()                  # invoke the object driver
  except Exception as e: handle_exception(e)

"""Main entry point"""
if __name__ == "__main__":
  # set underlying default logging capabilities
  logging.basicConfig(level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  main()


#!/usr/bin/env -S python -W ignore

# anonymize.py

# Standard library imports
import json
import uuid
import random
import argparse

# Third-party imports
from faker import Faker

# Local application/library imports
# ...

fake = Faker()

def anonymize_data(data, anonymization_rules):
    """Recursively anonymize specific fields in the given data."""
    if isinstance(data, dict):
        return {key: anonymize_value(key, value, anonymization_rules) for key, value in data.items()}

    if isinstance(data, list):
        return [anonymize_data(item, anonymization_rules) for item in data]

    return data

def anonymize_value(key, value, anonymization_rules):
    """Anonymize individual value based on the key using provided faker functions."""
    if key in anonymization_rules:
        faker_function = anonymization_rules[key]
        return faker_function()

    if isinstance(value, (dict, list)):
        return anonymize_data(value, anonymization_rules)

    return value

def anonymize_json_file(input_file, output_file, anonymization_rules):
    """Read JSON from file, anonymize it, and write to another file."""
    with open(input_file, "r", encoding="utf-8") as file:
        data = json.load(file)

    anonymized_data = anonymize_data(data, anonymization_rules)

    with open(output_file, "w", encoding="utf-8") as file:
        json.dump(anonymized_data, file, indent=4)

def main():
    """
    Anonymizes the JSON data in the specified file.

    Args:
        file (str): The JSON file to be anonymized.

    Returns:
        None
    """
    parser = argparse.ArgumentParser(description="Anonymize JSON data.")
    parser.add_argument("file", help="The JSON file to be anonymized")

    args = parser.parse_args()

    input_file = args.file
    output_file = f"{input_file}.anon.json"

    anonymization_rules = {
        "created": lambda: fake.date_time_this_month().isoformat(" "),
        "updated": lambda: fake.date_time_this_month().isoformat(" "),
        "name": fake.name,
        "display_name": fake.name,
        "city": fake.city,
        "description": lambda: fake.text(max_nb_chars=80),
        "second_line": lambda: fake.text(max_nb_chars=20),
        "public_nick_name": fake.name,
        "id": lambda: random.randrange(100000, 999999),
        "monetary_account_id": lambda: random.randrange(100000, 999999),
        "iban": fake.iban,
        "url": fake.url,
        "target_url": fake.url,
        "uuid": lambda: str(uuid.uuid4()),
        "anchor_uuid": lambda: str(uuid.uuid4()),
        "attachment_public_uuid": lambda: str(uuid.uuid4()),
        "latitude": lambda: float(fake.latitude()),
        "longitude": lambda: float(fake.longitude()),
        "altitude": lambda: float(random.uniform(0, 1) * 100),
    }

    anonymize_json_file(input_file, output_file, anonymization_rules)
    print(f"Anonymized file saved as: {output_file}")

if __name__ == "__main__":
    main()


# https://leetcode.com/problems/maximize-score-after-n-operations/
from functools import cache
from typing import *
from math import gcd
import bisect

class Solution:
    def maxScoreOLD(self, nums: List[int]) -> int:
        n = len(nums) // 2
        gcds = []
        for i in range(len(nums)):
            for j in range(i + 1, len(nums)):
                g = (gcd(nums[i], nums[j]), i, j)
                bisect.insort(gcds, g)

        d = {}

        def myFilter(local_gcds, ind):
            ele = set(local_gcds[ind][1:])

            def test(x):
                if x[1] in ele or x[2] in ele:
                    return False
                return True

            return list(filter(test, local_gcds))

        def DB(local_gcds, local_n) -> int:
            if not local_n:
                return 0
            if (tuple(local_gcds), local_n) in d:
                return d[(tuple(local_gcds), local_n)]
            if len(local_gcds) == 1:
                d[(tuple(local_gcds), local_n)] = local_gcds[0][0] * local_n
                return d[(tuple(local_gcds), local_n)]
            ans = DB(myFilter(local_gcds[:], -1), local_n - 1) + local_n * local_gcds[-1][0]
            local_i = len(local_gcds) - 2
            while local_i:
                t1 = DB(myFilter(local_gcds[:], local_i), local_n - 1) + local_n * local_gcds[local_i][0]
                ans = t1 if t1 > ans else ans
                local_i -= 1
            d[(tuple(local_gcds), local_n)] = ans
            return ans

        return DB(gcds, n)

    def maxScore(self, nums: List[int]) -> int:
        @cache
        def DB(local_nums, n):
            if not local_nums:
                return 0
            ans = 0
            for i in range(len(local_nums)):
                for j in range(i + 1, len(local_nums)):
                    new = local_nums[:i] + local_nums[i + 1:j] + local_nums[j + 1:]
                    ans = max(ans, n * gcd(local_nums[i], local_nums[j]) + DB(tuple(new), n - 1))
            return ans

        return DB(tuple(nums), len(nums) // 2)

S = Solution()
# X = S.maxScore([6, 3, 4, 3, 5, 3, 5, 10, 10, 3, 1, 7, 3, 3])
X = S.maxScore(
    [109497, 983516, 698308, 409009, 310455, 528595, 524079, 18036, 341150, 641864, 913962, 421869, 943382, 295019])
# Y = S.maxScore1(
#     [109497, 983516, 698308, 409009, 310455, 528595, 524079, 18036, 341150, 641864, 913962, 421869, 943382, 295019])
print(X)


"""
Distributed under the terms of the BSD 3-Clause License.

The full license is in the file LICENSE, distributed with this software.

Author: Jun Zhu
"""
from collections import OrderedDict
from itertools import chain
from typing import Optional, Union

from ..backend.QtCore import pyqtSignal, QPointF, Qt

from ..graphics_item import MouseCursorStyle, PlotItem
from .axis_widget import AxisWidget
from .canvas import Canvas
from .legend_widget import LegendWidget
from .plot_widget import PlotWidget

class GraphWidget(PlotWidget):
    """PlotWidget for displaying graphs."""

    def __init__(self, *, parent=None):
        super().__init__(parent=parent)

        self._plot_items = OrderedDict()  # PlotItem: None
        self._plot_items_y2 = OrderedDict()  # PlotItem: None
        self._canvas_y2 = None

        self._legend = None

        self._initUI()
        self._initConnections()

    def _initConnections(self) -> None:
        """Override."""
        super()._initConnections()
        self._canvas.setMouseMode(self._canvas.MouseMode.Pan)
        self._setMouseCursorStyle(MouseCursorStyle.Cross)
        self._canvas.getMenuAction("Cursor_Show").setChecked(False)

    def _initAxisItems(self):
        """Override."""
        for name, edge, pos in (
                ('bottom', Qt.Edge.BottomEdge, self._AXIS_BOTTOM_LOC),
                ('left', Qt.Edge.LeftEdge, self._AXIS_LEFT_LOC),
                ('right', Qt.Edge.RightEdge, self._AXIS_RIGHT_LOC)
        ):
            axis = AxisWidget(edge, parent=self)

            self._axes[name] = axis
            self._layout.addItem(axis, *pos)
            axis.setFlag(axis.GraphicsItemFlag.ItemNegativeZStacksBehindParent)

        x_axis = self._axes['bottom']
        x_axis.linkToCanvas(self._canvas)
        x_axis.log_Scale_toggled_sgn.connect(self._onLogXScaleToggled)

        y_axis = self._axes['left']
        y_axis.linkToCanvas(self._canvas)
        y_axis.log_Scale_toggled_sgn.connect(self._onLogYScaleToggled)

        # y2 axis
        y2_axis = self._axes['right']
        y2_axis.hide()
        y2_axis.log_Scale_toggled_sgn.connect(self._onLogY2ScaleToggled)

    def _onMouseCursorMoved(self, pos: QPointF) -> None:
        """Override."""
        super()._onMouseCursorMoved(pos)
        self._setMouseCursorText(pos.x(), pos.y())

    def _updateMouseCursorLabel(self) -> None:
        """Override."""
        pos = self._mouse_cursor.pos()
        pos = self._canvas.mapFromItemToView(self, pos)
        self._setMouseCursorText(pos.x(), pos.y())

    def _setMouseCursorText(self, x: float, y: float) -> None:
        self._mouse_cursor.setLabel(f"    {x:.1f}, {y:.1f}")

    def clearData(self) -> None:
        """Override."""
        for item in chain(self._plot_items, self._plot_items_y2):
            item.clearData()

    def _onLogXScaleToggled(self, state: bool):
        for item in chain(self._plot_items, self._plot_items_y2):
            item.setLogX(state)
        self._canvas.updateAutoRange()

    def _onLogYScaleToggled(self, state: bool):
        for item in self._plot_items:
            item.setLogY(state)
        self._canvas.updateAutoRange()

    def _onLogY2ScaleToggled(self, state: bool):
        for item in self._plot_items_y2:
            item.setLogY(state)
        self._canvas_y2.updateAutoRange()

    def addItem(self, item, *, y2: bool = False) -> None:
        """Override."""
        if y2:
            canvas = self._canvas_y2
            if canvas is None:
                canvas = Canvas(parent=self)
                y2_axis = self._axes['right']
                y2_axis.linkToCanvas(canvas)
                y2_axis.show()
                canvas.linkXTo(self._canvas)
                canvas.setZValue(self._canvas.zValue() - 1)
                self._canvas_y2 = canvas
                # _vb_y2 is not added to the layout
                self._canvas.geometryChanged.connect(
                    lambda: canvas.setGeometry(self._canvas.geometry()))
        else:
            canvas = self._canvas

        if isinstance(item, PlotItem):
            if y2:
                if self._axes['bottom'].logScale():
                    item.setLogX(True)

                self._plot_items_y2[item] = None
            else:
                if self._axes['bottom'].logScale():
                    item.setLogX(True)

                if self._axes['left'].logScale():
                    item.setLogY(True)

                self._plot_items[item] = None

            if self._legend is not None:
                self._legend.addItem(item)

        canvas.addItem(item)

    def removeItem(self, item):
        """Override."""
        if item in self._plot_items_y2:
            del self._plot_items_y2[item]
            if self._legend is not None:
                self._legend.removeItem(item)
            self._canvas_y2.removeItem(item)
            return

        if item in self._plot_items:
            del self._plot_items[item]
            if self._legend is not None:
                self._legend.removeItem(item)

        self._canvas.removeItem(item)

    def addLegend(self, pos: Optional[Union[tuple, list, QPointF]] = None,
                  **kwargs):
        """Add a LegendWidget if it does not exist."""
        if self._legend is None:
            self._legend = LegendWidget(parent=self._canvas, **kwargs)

            for item in chain(self._plot_items, self._plot_items_y2):
                self._legend.addItem(item)

            if pos is None:
                # TODO: use a value which is proportional to the plot size
                pos = QPointF(10., 10.)
            elif not isinstance(pos, QPointF):
                pos = QPointF(*pos)

            self._legend.setPos(pos)

        return self._legend

    def showLegend(self, visible: bool = True) -> None:
        """Show or hide the legend.

        :param visible: whether to show the legend.
        """
        self._legend.setVisible(visible)


import numpy as np
import scipy.constants as spc
from matplotlib import pyplot as plt
from netCDF4 import date2num
import spiceypy as spice
import cartopy.crs as ccrs

from .. import ocean
from .. import atmosphere
from .. import spacecraft as sc
from .. import dielectric

def plot_raw_inputs():
    o = ocean.ocean(mode='flat')

    lat = np.arange(90, -90, -1)
    lon = np.arange(-180, 180, 1)
    llat, llon = np.meshgrid(lat, lon, indexing='ij')
    current_time = date2num(o.time, o.time_reference)
    sst = o.sst_interp((llat, llon)) - spc.zero_Celsius
    sss = o.sss_interp((llat, llon))
    land = o.landmask_interp((llat, llon))
    uwind = o.uwind_interp((current_time, llat, llon))
    vwind = o.vwind_interp((current_time, llat, llon))
    prwtr = o.prwtr_interp((current_time, llat, llon))
    TEC = o.TEC_interp((llat, llon))
    del o
    plt.figure()
    plt.title('Sea Surface Temperature')
    plt.imshow(sst, cmap='jet')
    plt.colorbar(orientation='horizontal')
    plt.clim(vmin=0, vmax=30)

    plt.figure()
    plt.title('Sea Surface Salinity')
    plt.imshow(sss, cmap='jet')
    plt.colorbar(orientation='horizontal')
    plt.clim(vmin=30, vmax=38)

    plt.figure()
    plt.title('Land mask')
    plt.imshow(land, cmap='jet')

    plt.figure()
    plt.title('Zonal Wind')
    plt.imshow(uwind, cmap='jet')
    plt.colorbar(orientation='horizontal')

    plt.figure()
    plt.title('Meridional Wind')
    plt.imshow(vwind, cmap='jet')
    plt.colorbar(orientation='horizontal')

    plt.figure()
    plt.title('Precipitable Water')
    plt.imshow(prwtr, cmap='jet')
    plt.colorbar(orientation='horizontal')

    plt.figure()
    plt.title('Total Electron Content')
    plt.imshow(TEC, cmap='jet')
    plt.colorbar(orientation='horizontal')

    plt.show()
    plt.close('all')

def plot_TB_map():
    mesh_spacing = 1
    lat_flat = np.linspace(89.5, -89.5, int(180 / mesh_spacing))
    lon_flat = np.linspace(-179.5, 179.5, int(360 / mesh_spacing))
    lon, lat = np.meshgrid(lon_flat, lat_flat)
    o = ocean.ocean(mode='flat')
    omap = o.get_ocean_TB(np.array([1e3]), theta=40)
    omap_v = omap[0][0] * (1 - o.landmask_interp((lat, lon)))
    omap_h = omap[1][0] * (1 - o.landmask_interp((lat, lon)))
    omap_v[omap_v < 50] = np.nan
    omap_h[omap_h < 50] = np.nan
    fig, ax = plt.subplots()
    ax = plt.axes(projection=ccrs.PlateCarree())
    ax.coastlines()
    ax.gridlines(color='k', draw_labels=True)
    extent = (-179.5, 179.5, -89.5, 89.5)
    mode = np.median(omap_v[omap_v > 20])
    offset = 10
    plot = ax.imshow(omap_v, origin='upper', extent=extent, transform=ccrs.PlateCarree(), cmap='turbo', vmin=mode - offset, vmax=mode + offset)
    fig.colorbar(plot, shrink=1, pad=0.1, label='Brightness Temperature (K)', orientation='horizontal')
    plt.savefig('Vpol_TB.png', dpi=300, transparent=True)

    fig2, ax2 = plt.subplots()
    ax2 = plt.axes(projection=ccrs.PlateCarree())
    ax2.coastlines()
    ax2.gridlines(color='k', draw_labels=True)
    extent = (-179.5, 179.5, -89.5, 89.5)
    mode = np.median(omap_h[omap_h > 20])
    offset = 10
    plot = ax2.imshow(omap_h, origin='upper', extent=extent, transform=ccrs.PlateCarree(), cmap='turbo', vmin=mode - offset, vmax=mode + offset)
    fig2.colorbar(plot, shrink=1, pad=0.1, label='Brightness Temperature (K)', orientation='horizontal')
    plt.savefig('Hpol_TB.png', dpi=300, transparent=True)

def plot_dielectric():
    frequency = np.logspace(3, 6, 1000)
    salinity = np.linspace(30, 40, 10)
    temperature = 293 * np.ones(len(salinity))
    eps = dielectric.h2o_liquid_saline_KleinSwift(frequency[:, np.newaxis], temperature[np.newaxis, :], salinity[np.newaxis, :])
    plt.figure()
    plt.loglog(frequency, np.real(eps))
    plt.figure()
    plt.loglog(frequency, -np.imag(eps))

def plot_spectrum():

    o = ocean.ocean(mode='flat')
    frequency = np.linspace(0.5e3, 100e3, 1000)
    TBV, TBH = o.get_ocean_TB(frequency=frequency, sst=300, sss=35, uwind=0, vwind=0, gal_max=0, lat=0, angle=40)

    plt.figure()
    plt.title(r'Ocean Emission Spectrum')
    plt.semilogx(frequency / 1e3, TBH, label=r'T$_B^H$')
    plt.semilogx(frequency / 1e3, TBV, label=r'T$_B^V$')
    plt.xlabel('Frequency (GHz)')
    plt.ylabel('Brightness Temperature (K)')
    plt.grid(b=True)
    plt.text(1.1, 201, r'T: 300K, S: 35 psu, $\theta$: 40$^\circ$')
    plt.legend()
    plt.savefig('freq_spectrum.png', format='png', dpi=300, transparent=True)

    angle = np.linspace(0, 80, 100)
    TBV, TBH = o.get_quick_ocean_TB(frequency=1e3, sst=300, sss=35, uwind=0, vwind=0, gal_max=0, lat=0, angle=angle)

    plt.figure()
    plt.title(r'Ocean Emission with Angle')
    plt.plot(angle, TBH, label=r'T$_B^H$')
    plt.plot(angle, TBV, label=r'T$_B^V$')
    plt.xlabel('Angle (Degrees)')
    plt.ylabel('Brightness Temperature (K)')
    plt.grid(b=True)
    plt.text(11, 240, r'T: 300K, S: 35 psu, F: 1 GHz')
    plt.legend()
    plt.savefig('angle_spectrum.png', format='png', dpi=300, transparent=True)

    wind = np.linspace(0, 20, 100)
    TBV, TBH = o.get_quick_ocean_TB(frequency=1e3, sst=300, sss=35, uwind=wind, vwind=0, gal_max=0, lat=0, angle=20)

    plt.figure()
    plt.title(r'Ocean Emission with Wind speed')
    plt.plot(wind, TBH, label=r'T$_B^H$')
    plt.plot(wind, TBV, label=r'T$_B^V$')
    plt.xlabel('Wind speed (m/s)')
    plt.ylabel('Brightness Temperature (K)')
    plt.grid(b=True)
    plt.text(2.5, 90.4, r'T: 300K, S: 35 psu, F: 1 GHz, $\theta$: 20$^\circ$')
    plt.legend()
    plt.savefig('wind_spectrum.png', format='png', dpi=300, transparent=True)

    gal = np.linspace(0, 20, 100)
    TBV, TBH = o.get_quick_ocean_TB(frequency=1e3, sst=300, sss=35, uwind=0, vwind=0, gal_max=gal, lat=0, angle=20)

    plt.figure()
    plt.title(r'Ocean Emission with Wind speed')
    plt.plot(gal, TBH, label=r'T$_B^H$')
    plt.plot(gal, TBV, label=r'T$_B^V$')
    plt.xlabel('Galactic Brightness Temperature (K)')
    plt.ylabel('Brightness Temperature (K)')
    plt.grid(b=True)
    plt.text(2.5, 104, r'T: 300K, S: 35 psu, F: 1 GHz, $\theta$: 20$^\circ$')
    plt.legend()
    plt.savefig('gal_spectrum.png', format='png', dpi=300, transparent=True)

    sst = np.linspace(273, 323, 100)
    TBV, TBH = o.get_quick_ocean_TB(frequency=1e3, sst=sst, sss=35, uwind=0, vwind=0, gal_max=0, lat=0, angle=20)

    plt.figure()
    plt.title(r'Ocean Emission with Temperature')
    plt.plot(sst, TBH, label=r'T$_B^H$')
    plt.plot(sst, TBV, label=r'T$_B^V$')
    plt.xlabel('Sea Surface Temperature (K)')
    plt.ylabel('Brightness Temperature (K)')
    plt.grid(b=True)
    plt.text(290, 96, r'S: 35 psu, F: 1 GHz, $\theta$: 20$^\circ$')
    plt.legend()
    plt.savefig('sst_spectrum.png', format='png', dpi=300, transparent=True)

    sss = np.linspace(30, 40, 100)
    TBV, TBH = o.get_quick_ocean_TB(frequency=1e3, sst=300, sss=sss, uwind=0, vwind=0, gal_max=0, lat=0, angle=20)

    plt.figure()
    plt.title(r'Ocean Emission with Salinity')
    plt.plot(sss, TBH, label=r'T$_B^H$')
    plt.plot(sss, TBV, label=r'T$_B^V$')
    plt.xlabel('Sea Surface Salinity (psu)')
    plt.ylabel('Brightness Temperature (K)')
    plt.grid(b=True)
    plt.text(32, 95, r'T: 300K, F: 1 GHz, $\theta$: 20$^\circ$')
    plt.legend()
    plt.savefig('sss_spectrum.png', format='png', dpi=300, transparent=True)

def plot_weighting_function():
    res = 0.2
    ghz = np.array([23.8, 31.4, 50.3, 52.8, 53.596, 54.40, 54.94, 55.50, 57.29, 57.61, 89])
    atm = atmosphere.atmosphere()
    angle = np.radians(40)
    t = np.array([300.])
    p = np.array([1e5])
    prwtr = np.array([0])
    lwtr = np.array([0])
    T, P, dens, wv, lw = atm.isa_profiles(t, p, prwtr, lwtr, res=res)
    tau, tbar = atm.mrtm(ghz, P[::-1], T[::-1], wv[::-1], lw[::-1])
    transup = np.exp(-1 * np.cumsum(tau / np.cos(angle), axis=0))
    wup = -np.gradient(transup, axis=0)
    z = np.arange(0, 100 - res, res)[::-1]
    cmap = plt.cm.viridis(np.linspace(0, 1, len(ghz)))
    for i in range(len(ghz)):
        plt.plot(wup[:, i], z, color=cmap[i], label='%.2f GHz' % ghz[i])
    plt.legend()
    plt.xlabel('Weighting Function')
    plt.ylabel('Altitude')
    plt.xlim(0, np.max(wup) + 0.2 * np.max(wup))
    plt.ylim(0, 110)
    plt.legend()
    plt.tight_layout()
    plt.savefig('weight.png', dpi=300, transparent=True)

def plot_spacecraft_tracks():
    s = sc.spacecraft()
    epochs = np.arange(0, 5 * 24 * 60 * 60, 2)
    s.write_tle_kernels(inclination=np.radians(98.12), height=680e3, look_angle=40, start_epoch=epochs[0], end_epoch=epochs[-1] + 1)
    pos, times = spice.spkpos('-999', epochs, 'ITRF93', 'NONE', '399')
    ll_arr = np.array([spice.reclat(x) for x in pos])
    # spoint = np.array([spice.sincpt('ELLIPSOID', 'EARTH', epochs[x], 'ITRF93', 'LT+S', '-999', 'SPACECRAFT', point[x])[0] for x in range(0, len(epochs))])
    splist = []
    for x in range(0, len(epochs)):
        try:
            spoint = spice.sincpt('ELLIPSOID', 'EARTH', epochs[x], 'ITRF93', 'NONE', '-999', 'RADIOMETER', np.array([1, 0, 0]))
        except spice.stypes.NotFoundError:
            spoint = [np.array([1, 0, 0]), 0]
        splist.append(spoint[0])
        pos, light = spice.spkpos('-999', epochs[x], 'ITRF93', 'LT+S', '399')
        pp = spice.reclat(pos)
        # print('SPK Lat: %f' % np.degrees(pp[2]))
        # print('SPK Lon: %f' % np.degrees(pp[1]))
        # print(spoint[0])
        # pp = spice.reclat(spoint[0])
        # print('CK Lat: %f' % np.degrees(pp[2]))
        # print('CK Lon: %f' % np.degrees(pp[1]))
    ll_parr = np.array([spice.reclat(x) for x in splist])
    ax = plt.axes(projection=ccrs.PlateCarree())
    ax.coastlines()
    ax.plot(np.degrees(ll_arr[:, 1]), np.degrees(ll_arr[:, 2]), transform=ccrs.PlateCarree(), linestyle='none', marker='.', color='blue')
    ax.plot(np.degrees(ll_parr[:, 1]), np.degrees(ll_parr[:, 2]), transform=ccrs.PlateCarree(), linestyle='none', marker='.', color='red')
    ax.set_extent([-180, 180, -90, 90])

    # Revists
    # import cartopy.crs as ccrs
    # from skimage import filters
    # lonbins = np.arange(-180, 180 + 3, 3)
    # latbins = np.arange(-90, -30 + 1, 1)
    # lats = np.degrees(ll_parr[:, 2])
    # lons = np.degrees(ll_parr[:, 1])
    # res, lonb, latb = np.histogram2d(lons, lats, bins=[lonbins, latbins], density=False)
    # gi = filters.gaussian(res.T, sigma=2)
    # ax = plt.subplot(1, 1, 1, projection=ccrs.SouthPolarStereo())
    # plt.pcolormesh(lonb, latb, gi / np.max(gi.flatten()), transform=ccrs.PlateCarree())
    # plt.colorbar()
    # ax.coastlines()
    # ax.gridlines(color='k', linestyle=':')
    # ax.set_extent([-180, 180, -90, -60], crs=ccrs.PlateCarree())

    return ll_parr

def visual_reference(epoch):
    s = sc.spacecraft()
    height = 700e3
    s.write_tle_kernels(inclination=np.radians(80), height=height)

    fig = plt.figure(figsize=(10, 20))
    ax = fig.add_subplot(211, projection='3d')

    # Plot Earth
    u = np.linspace(0, 2 * np.pi, 500)
    v = np.linspace(0, np.pi, 500)
    rad = s.earth_mean_radius / 1e3
    x = rad * np.outer(np.cos(u), np.sin(v))
    y = rad * np.outer(np.sin(u), np.sin(v))
    z = rad * np.outer(np.ones(np.size(u)), np.cos(v))
    ax.plot_wireframe(x, y, z, color='black', alpha=0.4)
    pos, times = spice.spkpos('-999', epoch, 'ITRF93', 'NONE', '399')
    pos_norm = pos * (rad / np.linalg.norm(pos))
    ax.scatter(pos[0], pos[1], pos[2], color='blue')
    ax.quiver(0, 0, 0, pos_norm[0], pos_norm[1], pos_norm[2], arrow_length_ratio=0.1, color='blue')

    pos2, times = spice.spkpos('399', epoch, 'SPACECRAFT', 'NONE', '-999')
    mat = spice.pxform('SPACECRAFT', 'ITRF93', epoch)
    pos2 = mat @ pos2
    pos2_norm = pos2 * ((height / 1e3) / np.linalg.norm(pos))
    ax.quiver(pos[0], pos[1], pos[2], pos2_norm[0], pos2_norm[1], pos2_norm[2], color='red')

    try:
        spoint = spice.sincpt('ELLIPSOID', 'EARTH', epoch, 'ITRF93', 'NONE', '-999', 'SPACECRAFT', np.array([1, 0, 0]))[0]
        ax.scatter(spoint[0], spoint[1], spoint[2], color='green')
        ll_arr2 = spice.reclat(spoint)
        print("Lon/Lat SPOINT: %f, %f" % (np.degrees(ll_arr2[1]), np.degrees(ll_arr2[2])))

    except:
        ll_arr2 = np.array([1, 0, 0])

    ll_arr = spice.reclat(pos)
    ax2 = fig.add_subplot(212, projection=ccrs.PlateCarree())
    ax2.coastlines()
    ax2.plot(np.degrees(ll_arr[1]), np.degrees(ll_arr[2]), transform=ccrs.PlateCarree(), linestyle='none', marker='.', color='blue')
    ax2.plot(np.degrees(ll_arr2[1]), np.degrees(ll_arr2[2]), transform=ccrs.PlateCarree(), linestyle='none', marker='.', color='green')
    ax2.set_extent([-180, 180, -90, 90])
    print("Lon/Lat SUB: %f, %f" % (np.degrees(ll_arr[1]), np.degrees(ll_arr[2])))

def plot_spacecraft_temps():
    o = ocean.ocean()
    s = sc.spacecraft()
    s.write_tle_kernels(inclination=np.radians(80), height=700e3, angle=40)
    epochs = np.arange(0, 1 * 60 * 60, 1)  # np.arange(0, 1 * 24 * 60 * 60, 1 * 60)
    splist = []
    for x in range(0, len(epochs)):
        try:
            spoint = spice.sincpt('ELLIPSOID', 'EARTH', epochs[x], 'ITRF93', 'NONE', '-999', 'RADIOMETER', np.array([1, 0, 0]))
        except spice.stypes.NotFoundError:
            spoint = [np.array([1, 0, 0]), 0]
        splist.append(spoint[0])
        pos, light = spice.spkpos('-999', epochs[x], 'ITRF93', 'LT+S', '399')
        pp = spice.reclat(pos)
        print('SPK Lat: %f' % np.degrees(pp[2]))
        print('SPK Lon: %f' % np.degrees(pp[1]))
        print(spoint[0])
        pp = spice.reclat(spoint[0])
        print('CK Lat: %f' % np.degrees(pp[2]))
        print('CK Lon: %f' % np.degrees(pp[1]))
    ll_parr = np.array([spice.reclat(x) for x in splist])
    llat, llon = np.meshgrid(np.degrees(ll_parr[:, 2]), np.degrees(ll_parr[:, 1]))
    TBV, TBH, U, V = o.get_ocean_TB(1e3, llat, llon, theta=40)  # Placeholder for true angle calc

    plt.figure(1)
    ax = plt.axes(projection=ccrs.PlateCarree())
    ax.coastlines()
    ax.scatter(np.degrees(ll_parr[:, 1]), np.degrees(ll_parr[:, 2]), c=np.diag(TBV[0, :, :]), cmap='viridis', transform=ccrs.PlateCarree(), s=1)
    # ax.colorbar()

    ax.set_extent([-180, 180, -90, 90])
    plt.savefig('TBV2.pdf', format='pdf', dpi=300)

    plt.figure(2)
    ax2 = plt.axes(projection=ccrs.PlateCarree())
    ax2.coastlines()
    ax2.scatter(np.degrees(ll_parr[:, 1]), np.degrees(ll_parr[:, 2]), c=np.diag(TBH[0, :, :]), cmap='viridis', transform=ccrs.PlateCarree(), s=1)
    # ax.colorbar()

    ax2.set_extent([-180, 180, -90, 90])
    plt.savefig('TBH2.pdf', format='pdf', dpi=300)


#!/usr/bin/env python
"""Common fixtures for functional serving tests"""
import pytest
from falcon import testing

from orion.serving.webapi import WebApi
from orion.testing import OrionState

@pytest.fixture()
def ephemeral_storage():
    storage = {"type": "legacy", "database": {"type": "EphemeralDB"}}
    with OrionState(storage=storage) as cfg:
        yield cfg

@pytest.fixture()
def client(ephemeral_storage):
    """Mock the falcon.API instance for testing with an in memory database"""
    yield testing.TestClient(WebApi(ephemeral_storage.storage, {}))

@pytest.fixture()
def client_with_frontends_uri(ephemeral_storage):
    """Mock the falcon.API instance for testing with custom frontend_uri"""
    yield testing.TestClient(
        WebApi(
            ephemeral_storage.storage,
            {
                "storage": ephemeral_storage.storage,
                "frontends_uri": ["http://123.456", "http://example.com"],
            },
        )
    )


import os
import sys
from django.core.exceptions import ImproperlyConfigured
import yaml
from contracts import contract

@contract
def get_env_variable(var_name, required=True, default=None, as_yaml=True, warning=None):
    """Get the environment variable, process and return, or raise exception.

    :type var_name: string
    :type required: bool
    :type default: string|bool|None|int
    :type as_yaml: bool
    :type warning: string|None

    :rtype: string|bool|seq|int|None

    """

    if default is not None:
        required = False

    try:
        answer = os.environ[var_name]
        if as_yaml:
            answer = yaml.safe_load(answer)
        return answer

    except KeyError:
        if warning:
            sys.stdout.write("WARNING: {} not present in the environment\n".format(var_name))
            sys.stdout.write(warning + "\n")

        if required:
            raise ImproperlyConfigured("{} is required".format(var_name))
        else:
            return default


from typing import Dict, List
from assetuniverse import AssetUniverse
import numpy as np
import scipy.optimize as opt
import pandas as pd

class Subportfolio(object):
    def __init__(self, params: Dict, au: AssetUniverse, assets: pd.DataFrame, id: int, total_ids: int, rebalance_dates: pd.DatetimeIndex):
        self.lookback = params[0]
        self.momentum_metric = params[1]
        self.subportfolio_threshold = params[2]
        self.subportfolio_min_keep = params[3]
        self.max_ind_allocation = params[4]

        self.au = au
        self.rebalance_dates = rebalance_dates

        self.target_weights = self.set_target_weights()

        # Print status
        if id % 10 == 0 and id > 0:
            print(f'Finished subportfolio: {id} of {total_ids}')

    def set_target_weights(self):
        """Set the target weights on all rebalance dates
        """
        tickers = self.au.tickers(include_cash=False, include_borrow_rate=False)
        target_weights = self.au.prices(tickers=tickers).copy(deep=True)*0     # Reset to 0
        earliest_rebalance = self.au.prices(tickers=tickers).index[self.lookback + 1]
        for date_window_end in self.rebalance_dates:
            if date_window_end > earliest_rebalance:
                date_window_start = date_window_end - np.timedelta64(int(7.4*self.lookback/5), 'D')
                best_assets = self.sort_by_metric(date_window_start, date_window_end)
                target_weights.loc[date_window_end, :] = self.optimize_target_weights(
                    best_assets,
                    date_window_start,
                    date_window_end
                )

        return target_weights

    def optimize_target_weights(self, assets: List, date_window_start, date_window_end):
        """Calculate the optimal target weights given the history of returns

        Parameters
        ----------
        returns : pd.DataFrame
            History of returns
        """
        # covmatrix = self.au.returns().loc[date_window_start:date_window_end, assets].cov().values
        covmatrix = self.au.covariance_matrix(assets, date_window_start, date_window_end)
        cons = [
            {'type': 'eq', 'fun': lambda x: np.sum(x) - 1.0},           # sum of weights must match 1.0
            ]

        result = opt.minimize(
            fun=self._expected_variance,
            x0=np.ones(len(assets))/len(assets),
            args=covmatrix,
            method='SLSQP',
            constraints=cons,
            bounds=opt.Bounds(0, self.max_ind_allocation),
            tol=1e-13,
            options={'maxiter': 1000, 'disp': False}
        )
        optimized_weights = result.x.transpose()

        tickers = self.au.tickers(include_cash=False, include_borrow_rate=False)
        weights = pd.Series(
            data=np.zeros(len(tickers)),
            index=tickers
            )
        weights.loc[assets] = optimized_weights
        return weights

    def _expected_variance(self, weights, covmatrix):
        return np.matmul(weights, np.matmul(covmatrix, weights.T))

    def sort_by_metric(self, date_window_start, date_window_end) -> List:
        tickers = self.au.tickers(include_cash=False, include_borrow_rate=False)
        metric, ascending = self.momentum_metric(
            self.au.prices(tickers=tickers, start=date_window_start, end=date_window_end),
            self.au.returns(tickers=tickers, start=date_window_start, end=date_window_end),
            self.lookback
            )
        metric = metric.sort_values(ascending=ascending)
        num_keep = int(np.ceil(max(self.subportfolio_threshold*len(tickers), self.subportfolio_min_keep)))
        return metric[-num_keep:].index.to_list()

class FixedAllocationSubportfolio(Subportfolio):
    def __init__(self, percentage_allocations: List, au: AssetUniverse, assets: pd.DataFrame, rebalance_dates: pd.DatetimeIndex):
        self.percentage_allocations = percentage_allocations
        self.au = au
        self.rebalance_dates = rebalance_dates
        self.target_weights = self.set_target_weights()

    def set_target_weights(self):
        tickers = self.au.tickers(include_cash=False, include_borrow_rate=False)
        target_weights = self.au.prices(tickers=tickers).copy(deep=True)*0     # Reset to 0
        for date_window_end in self.rebalance_dates:
            target_weights.loc[date_window_end, :] = self.percentage_allocations

        return target_weights


import numpy as np
from PIL import Image
import pickle
import LogisticRegression
from scipy.special import expit

def mean_std(X):
    return (X - np.mean(X)) / np.std(X)

def binary_predict(image_loc, theta_loc):
    np_im = convert_image(image_loc)
    theta = pickle.load(open(theta_loc, 'rb'))
    prediction = LogisticRegression.predict(np_im, theta)
    print("Output:", str(prediction))
    if (prediction >= 0.5):
        print("Predicted Value:", str(1))
    else:
        print("Predicted Value:", str(0))

    return prediction

def multiclass_predict(image_loc):
    np_im = convert_image(image_loc)
    predictions = np.zeros([10, 1])
    for numClass in range(10):
        theta = np.load("Multiclass_weights6k 10I/class" + str(numClass) + "weights.npy")
        predictions[numClass] = LogisticRegression.predict(np_im, theta)
    print(predictions)
    print("Prediction:" + str(np.where(predictions == max(predictions))[0]))

def multiclass_predict_optim(image_loc, weights_loc):
    np_im = convert_image(image_loc)
    predictions = np.zeros([10, 1])
    theta = np.load(weights_loc)
    print("Theta shape: " + str(theta.shape))
    print("Image shape: " + str(np_im.shape))
    predictions = LogisticRegression.predict(np_im, theta)
    print(predictions)
    largest = 0
    for i in range(predictions.shape[1]):
        if predictions[0, i] > predictions[0, largest]:
            largest = i
    print("Predicted value:" + str(largest))
    return largest

def convert_image(image_loc):
    image = Image.open(image_loc).convert('L')
    np_im = np.array(image)
    np_im = np.reshape(np_im, (1, np_im.shape[1] * np_im.shape[1]))
    np_im = mean_std(np_im)
    return np_im


import datetime
from subredditsCall import datastore
from subredditsCall import reddit

def timer(time, id):
    hour = time/3600
    found_time = False

    while(not(found_time)):
        now = datetime.datetime.now()
        todays_hour = now.replace(hour=time, minute=0, second=0)
        almost_hour = now.replace(hour=time,minute=0,second=1)
        if(now == todays_hour) or (now == almost_hour):
            f = datastore.returnData(id)[1]
            return reddit.pick_sub(f)


import logging

logger = logging.getLogger('curve-editor')

from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt

from .canvas import Canvas
from .curves import BezierCurve, PolygonalCurve, InterpolationPolynomialCurve, RationalBezierCurve, CubicSpline
from .model import CurvesModel

from .states import SelectCurveState, RemoveCurveState, MoveCurveState, DuplicateCurveState, DefaultState

from .ui.MainWindow import Ui_MainWindow

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, *args, obj=None, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setupUi(self)

        self.actionSave.triggered.connect(self.save)
        self.actionLoad.triggered.connect(self.load)
        self.actionNew.triggered.connect(self.new)
        self.actionScreenshot.triggered.connect(self.screenshot)

        self.actionToggleCurvesList.triggered.connect(self.toggle_curves_list)

        self.selected_curve = None

        self.model = CurvesModel(parent=self)
        self.model.layoutChanged.connect(self.model_changed)

        self.canvas = Canvas()
        self.canvas.setModel(self.model)

        self.listView.setModel(self.model)
        self.listView.clicked['QModelIndex'].connect(self.curve_selected)

        scene = QtWidgets.QGraphicsScene()
        scene.addItem(self.canvas)
        self.graphicsView.setScene(scene)

        self.model.updated()
        self.add_toolbar()

        self.dockWidget.hide()

    def model_changed(self):
        logger.info('Update window')

        if self.selected_curve is not self.model.selected_curve:
            if self.selected_curve is not None:
                self.removeToolBar(self.selected_curve.toolbar)
                if self.selected_curve.extra_toolbar is not None:
                    self.removeToolBar(self.selected_curve.extra_toolbar)

            self.selected_curve = self.model.selected_curve

            if self.selected_curve is not None:
                if self.selected_curve.toolbar is not None:
                    self.addToolBarBreak()
                    self.addToolBar(Qt.LeftToolBarArea,
                                    self.selected_curve.toolbar)
                    self.selected_curve.toolbar.show()

                    if self.selected_curve.extra_toolbar is not None:
                        self.addToolBarBreak()
                        self.addToolBar(Qt.LeftToolBarArea,
                                        self.selected_curve.extra_toolbar)
                        self.selected_curve.extra_toolbar.show()

                    logger.info("Added toolbar")

    def new_bezier_action_triggered(self):
        curve = BezierCurve("")
        self.model.add(curve, selected=True)

        curve.add_node_action.trigger()
        curve.show_nodes_action.trigger()

    def new_rational_bezier_action_triggered(self):
        curve = RationalBezierCurve("")
        self.model.add(curve, selected=True)

        curve.add_node_action.trigger()
        curve.show_nodes_action.trigger()

    def new_polygonal_action_triggered(self):
        curve = PolygonalCurve("")
        self.model.add(curve, selected=True)

        curve.add_node_action.trigger()
        curve.show_nodes_action.trigger()

    def new_polynomial_action_triggered(self):
        curve = InterpolationPolynomialCurve("")
        self.model.add(curve, selected=True)

        curve.add_node_action.trigger()
        curve.show_nodes_action.trigger()

    def new_cubic_spline_action_triggered(self):
        curve = CubicSpline("")
        self.model.add(curve, selected=True)

        curve.add_node_action.trigger()
        curve.show_nodes_action.trigger()

    def select_curve_action_triggered(self, state):
        if state:
            logger.info("select curve mode")
            self.model.state = SelectCurveState(self)
        else:
            self.model.state = DefaultState()

    def add_toolbar(self):
        new_curve_button = QtWidgets.QToolButton(self)
        new_curve_button.setText("New Curve ▼")
        new_curve_button.setPopupMode(QtWidgets.QToolButton.InstantPopup)
        new_curve_menu = QtWidgets.QMenu(new_curve_button)

        new_bezier_action = QtWidgets.QAction("Bezier", self)
        new_bezier_action.triggered.connect(self.new_bezier_action_triggered)
        new_curve_menu.addAction(new_bezier_action)

        new_rational_bezier_action = QtWidgets.QAction("Rational Bezier", self)
        new_rational_bezier_action.triggered.connect(self.new_rational_bezier_action_triggered)
        new_curve_menu.addAction(new_rational_bezier_action)

        new_polygonal_action = QtWidgets.QAction("Polygonal", self)
        new_polygonal_action.triggered.connect(self.new_polygonal_action_triggered)
        new_curve_menu.addAction(new_polygonal_action)

        new_polynomial_action = QtWidgets.QAction("Interpolation Polynomial", self)
        new_polynomial_action.triggered.connect(self.new_polynomial_action_triggered)
        new_curve_menu.addAction(new_polynomial_action)

        new_cubic_spline_action = QtWidgets.QAction("Cubic Spline", self)
        new_cubic_spline_action.triggered.connect(self.new_cubic_spline_action_triggered)
        new_curve_menu.addAction(new_cubic_spline_action)

        new_curve_button.setMenu(new_curve_menu)
        self.toolBar.addWidget(new_curve_button)

        self.select_action = QtWidgets.QAction("Select curve", self)
        self.select_action.triggered.connect(self.select_curve_action_triggered)
        self.select_action.setCheckable(True)
        self.toolBar.addAction(self.select_action)

        self.remove_curve_action = QtWidgets.QAction("Remove curve", self)
        self.remove_curve_action.triggered.connect(self.remove_curve_action_triggered)
        self.remove_curve_action.setCheckable(True)
        self.toolBar.addAction(self.remove_curve_action)

        self.move_curve_action = QtWidgets.QAction("Move curve", self)
        self.move_curve_action.triggered.connect(self.move_curve_action_triggered)
        self.move_curve_action.setCheckable(True)
        self.toolBar.addAction(self.move_curve_action)

        self.duplicate_curve_action = QtWidgets.QAction("Duplicate curve", self)
        self.duplicate_curve_action.triggered.connect(self.duplicate_curve_action_triggered)
        self.duplicate_curve_action.setCheckable(True)
        self.toolBar.addAction(self.duplicate_curve_action)

        # self.addToolBarBreak()

    def curve_selected(self, index):
        index = index.row()
        logger.info(index)

        self.model.select(index)

    def remove_curve_action_triggered(self, state):
        if state:
            logger.info("remove curve mode")
            self.model.state = RemoveCurveState(self)
        else:
            self.model.state = DefaultState()

    def move_curve_action_triggered(self, state):
        if state:
            logger.info("move curve mode")
            self.model.state = MoveCurveState(self)
        else:
            self.model.state = DefaultState()

    def duplicate_curve_action_triggered(self, state):
        if state:
            self.model.state = DuplicateCurveState(self)
        else:
            self.model.state = DefaultState()

    def toggle_curves_list(self):
        if self.dockWidget.isHidden():
            self.dockWidget.show()
        else:
            self.dockWidget.hide()

    def screenshot(self):
        options = QtWidgets.QFileDialog.Options()
        options |= QtWidgets.QFileDialog.DontUseNativeDialog
        filename, _ = QtWidgets.QFileDialog.getSaveFileName(self,
                                                            "Screenshot",
                                                            "",
                                                            "PNG (*.png)",
                                                            options=options)

        if filename:
            if not filename.endswith(".png"):
                filename += ".png"

            self.canvas.screenshot(filename)

    def new(self):
        self.model.new()

    def save(self):
        options = QtWidgets.QFileDialog.Options()
        options |= QtWidgets.QFileDialog.DontUseNativeDialog
        filename, _ = QtWidgets.QFileDialog.getSaveFileName(self,
                                                            "Save",
                                                            "",
                                                            "JSON (*.json)",
                                                            options=options)

        if filename:
            if not filename.endswith(".json"):
                filename += ".json"

            self.model.save(filename)

    def load(self):
        options = QtWidgets.QFileDialog.Options()
        options |= QtWidgets.QFileDialog.DontUseNativeDialog
        filename, _ = QtWidgets.QFileDialog.getOpenFileName(self,
                                                            "Open",
                                                            "",
                                                            "JSON (*.json)",
                                                            options=options)

        if filename:
            if not filename.endswith(".json"):
                filename += ".json"

            self.model.load(filename)


import glob
import os
import re
import shutil
import tempfile
import urlparse

import pyauto_functional  # Must be imported before pyauto
import pyauto
import test_utils

class OmniboxTest(pyauto.PyUITest):
  """Test cases for the omnibox."""

  def Debug(self):
    """Test method for experimentation.

    This method will not run automatically.
    """
    import time
    while True:
      self.pprint(self.GetOmniboxInfo().omniboxdict)
      time.sleep(1)

  def testFocusOnStartup(self):
    """Verify that the omnibox has focus on startup."""
    self.WaitUntilOmniboxReadyHack()
    self.assertTrue(self.GetOmniboxInfo().Properties('has_focus'))

  def testHistoryResult(self):
    """Verify that the omnibox can fetch items from the history."""
    url = self.GetFileURLForDataPath('title2.html')
    title = 'Title Of Awesomeness'
    self.AppendTab(pyauto.GURL(url))
    def _VerifyHistoryResult(query_list, description, windex=0):
      """Verify result matching given description for given list of queries."""
      for query_text in query_list:
        matches = test_utils.GetOmniboxMatchesFor(
            self, query_text, windex=windex,
            attr_dict={'description': description})
        self.assertTrue(matches)
        self.assertEqual(1, len(matches))
        item = matches[0]
        self.assertEqual(url, item['destination_url'])
    # Query using URL & title.
    _VerifyHistoryResult([url, title], title)
    # Verify results in another tab.
    self.AppendTab(pyauto.GURL())
    _VerifyHistoryResult([url, title], title)
    # Verify results in another window.
    self.OpenNewBrowserWindow(True)
    self.WaitUntilOmniboxReadyHack(windex=1)
    _VerifyHistoryResult([url, title], title, windex=1)
    # Verify results in an incognito window.
    self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW)
    self.WaitUntilOmniboxReadyHack(windex=2)
    _VerifyHistoryResult([url, title], title, windex=2)

  def _VerifyOmniboxURLMatches(self, url, description, windex=0):
    """Verify URL match results from the omnibox.

    Args:
      url: The URL to use.
      description: The string description within the history page and Google
                   search to match against.
      windex: The window index to work on. Defaults to 0 (first window).
    """
    matches_description = test_utils.GetOmniboxMatchesFor(
        self, url, windex=windex, attr_dict={'description': description})
    self.assertEqual(1, len(matches_description))
    if description == 'Google Search':
      self.assertTrue(re.match('http://www.google.com/search.+',
                               matches_description[0]['destination_url']))
    else:
      self.assertEqual(url, matches_description[0]['destination_url'])

  def testFetchHistoryResultItems(self):
    """Verify omnibox fetches history items in 2nd tab, window and incognito."""
    url = self.GetFileURLForDataPath('title2.html')
    title = 'Title Of Awesomeness'
    desc = 'Google Search'
    # Fetch history page item in the second tab.
    self.AppendTab(pyauto.GURL(url))
    self._VerifyOmniboxURLMatches(url, title)
    # Fetch history page items in the second window.
    self.OpenNewBrowserWindow(True)
    self.NavigateToURL(url, 1, 0)
    self._VerifyOmniboxURLMatches(url, title, windex=1)
    # Fetch google search items in incognito window.
    self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW)
    self.NavigateToURL(url, 2, 0)
    self._VerifyOmniboxURLMatches(url, desc, windex=2)

  def testSelect(self):
    """Verify omnibox popup selection."""
    url1 = self.GetFileURLForDataPath('title2.html')
    url2 = self.GetFileURLForDataPath('title1.html')
    title1 = 'Title Of Awesomeness'
    self.NavigateToURL(url1)
    self.NavigateToURL(url2)
    matches = test_utils.GetOmniboxMatchesFor(self, 'file://')
    self.assertTrue(matches)
    # Find the index of match for |url1|.
    index = None
    for i, match in enumerate(matches):
      if match['description'] == title1:
        index = i
    self.assertTrue(index is not None)
    self.OmniboxMovePopupSelection(index)  # Select |url1| line in popup.
    self.assertEqual(url1, self.GetOmniboxInfo().Text())
    self.OmniboxAcceptInput()
    self.assertEqual(title1, self.GetActiveTabTitle())

  def testInlineAutoComplete(self):
    """Verify inline autocomplete for a pre-visited URL."""
    self.NavigateToURL('http://www.google.com')
    matches = test_utils.GetOmniboxMatchesFor(self, 'goog')
    self.assertTrue(matches)
    # Omnibox should suggest auto completed URL as the first item.
    matches_description = matches[0]
    self.assertTrue('www.google.com' in matches_description['contents'])
    self.assertEqual('history-url', matches_description['type'])
    # The URL should be inline-autocompleted in the omnibox.
    self.assertTrue('google.com' in self.GetOmniboxInfo().Text())

  def testCrazyFilenames(self):
    """Test omnibox query with filenames containing special chars.

    The files are created on the fly and cleaned after use.
    """
    filename = os.path.join(self.DataDir(), 'downloads', 'crazy_filenames.txt')
    zip_names = self.EvalDataFrom(filename)
    # We got .zip filenames. Change them to .html.
    crazy_filenames = [x.replace('.zip', '.html') for x in zip_names]
    title = 'given title'

    def _CreateFile(name):
      """Create the given html file."""
      fp = open(name, 'w')  # |name| could be unicode.
      print >>fp, '<title>%s</title>' % title
      print >>fp, 'This is a junk file named
%s
' % repr(name)
      print >>fp, ''
      fp.close()

    crazy_fileurls = []
    # Temp dir for hosting crazy filenames.
    temp_dir = tempfile.mkdtemp(prefix='omnibox')
    # Windows has a dual nature dealing with unicode filenames.
    # While the files are internally saved as unicode, there's a non-unicode
    # aware API that returns a locale-dependent coding on the true unicode
    # filenames.  This messes up things.
    # Filesystem-interfacing functions like os.listdir() need to
    # be given unicode strings to "do the right thing" on win.
    # Ref: http://boodebr.org/main/python/all-about-python-and-unicode
    try:
      for filename in crazy_filenames:  # |filename| is unicode.
        file_path = os.path.join(temp_dir, filename.encode('utf-8'))
        _CreateFile(os.path.join(temp_dir, filename))
        file_url = self.GetFileURLForPath(file_path)
        crazy_fileurls.append(file_url)
        self.NavigateToURL(file_url)

      # Verify omnibox queries.
      for file_url in crazy_fileurls:
        matches = test_utils.GetOmniboxMatchesFor(self,
            file_url, attr_dict={'type': 'url-what-you-typed',
                                 'description': title})
        self.assertTrue(matches)
        self.assertEqual(1, len(matches))
        self.assertTrue(os.path.basename(file_url) in
                        matches[0]['destination_url'])
    finally:
      shutil.rmtree(unicode(temp_dir))  # Unicode so that Win treats nicely.

  def testSuggest(self):
    """Verify suggested results in omnibox."""
    matches = test_utils.GetOmniboxMatchesFor(self, 'apple')
    self.assertTrue(matches)
    self.assertTrue([x for x in matches if x['type'] == 'search-suggest'])

  def testDifferentTypesOfResults(self):
    """Verify different types of results from omnibox.

    This includes history result, bookmark result, suggest results.
    """
    url = 'http://www.google.com/'
    title = 'Google'
    search_string = 'google'
    self.AddBookmarkURL(  # Add a bookmark.
        self.GetBookmarkModel().BookmarkBar()['id'], 0, title, url)
    self.NavigateToURL(url)  # Build up history.
    matches = test_utils.GetOmniboxMatchesFor(self, search_string)
    self.assertTrue(matches)
    # Verify starred result (indicating bookmarked url).
    self.assertTrue([x for x in matches if x['starred'] == True])
    for item_type in ('history-url', 'search-what-you-typed',
                      'search-suggest',):
      self.assertTrue([x for x in matches if x['type'] == item_type])

  def testSuggestPref(self):
    """Verify no suggests for omnibox when suggested-services disabled."""
    search_string = 'apple'
    self.assertTrue(self.GetPrefsInfo().Prefs(pyauto.kSearchSuggestEnabled))
    matches = test_utils.GetOmniboxMatchesFor(self, search_string)
    self.assertTrue(matches)
    self.assertTrue([x for x in matches if x['type'] == 'search-suggest'])
    # Disable suggest-service.
    self.SetPrefs(pyauto.kSearchSuggestEnabled, False)
    self.assertFalse(self.GetPrefsInfo().Prefs(pyauto.kSearchSuggestEnabled))
    matches = test_utils.GetOmniboxMatchesFor(self, search_string)
    self.assertTrue(matches)
    # Verify there are no suggest results.
    self.assertFalse([x for x in matches if x['type'] == 'search-suggest'])

  def testAutoCompleteForSearch(self):
    """Verify omnibox autocomplete for search."""
    search_string = 'youtu'
    verify_string = 'youtube'
    matches = test_utils.GetOmniboxMatchesFor(self, search_string)
    # Retrieve last contents element.
    matches_description = matches[-1]['contents'].split()
    self.assertEqual(verify_string, matches_description[0])

  def _GotContentHistory(self, search_text, url):
    """Check if omnibox returns a previously-visited page for given search text.

    Args:
      search_text: The string search text.
      url: The string URL to look for in the omnibox matches.

    Returns:
      True, if the omnibox returns the previously-visited page for the given
      search text, or False otherwise.
    """
    # Omnibox doesn't change results if searching the same text repeatedly.
    # So setting '' in omnibox before the next repeated search.
    self.SetOmniboxText('')
    matches = test_utils.GetOmniboxMatchesFor(self, search_text)
    matches_description = [x for x in matches if x['destination_url'] == url]
    return 1 == len(matches_description)

  def testContentHistory(self):
    """Verify omnibox results when entering page content.

    Test verifies that visited page shows up in omnibox on entering page
    content.
    """
    url = self.GetFileURLForPath(
        os.path.join(self.DataDir(), 'find_in_page', 'largepage.html'))
    self.NavigateToURL(url)
    self.assertTrue(self.WaitUntil(
        lambda: self._GotContentHistory('British throne', url)))

  def testOmniboxSearchHistory(self):
    """Verify page navigation/search from omnibox are added to the history."""
    url = self.GetFileURLForDataPath('title2.html')
    self.NavigateToURL(url)
    self.AppendTab(pyauto.GURL('about:blank'))
    self.SetOmniboxText('java')
    self.WaitUntilOmniboxQueryDone()
    self.OmniboxAcceptInput()
    history = self.GetHistoryInfo().History()
    self.assertEqual(2, len(history))
    self.assertEqual(url, history[1]['url'])
    self.assertEqual('java - Google Search', history[0]['title'])

  def _VerifyHasBookmarkResult(self, matches):
    """Verify that we have a bookmark result.

    Args:
      matches: A list of match items, as returned by
               test_utils.GetOmniboxMatchesFor().
    """
    matches_starred = [result for result in matches if result['starred']]
    self.assertTrue(matches_starred)
    self.assertEqual(1, len(matches_starred))

  def _CheckBookmarkResultForVariousInputs(self, url, title, windex=0):
    """Check if we get the bookmark for complete and partial inputs.

    Args:
      url: A string URL.
      title: A string title for the given URL.
      windex: The window index to use.  Defaults to 0 (first window).
    """
    # Check if the complete URL would get the bookmark.
    url_matches = test_utils.GetOmniboxMatchesFor(self, url, windex=windex)
    self._VerifyHasBookmarkResult(url_matches)
    # Check if the complete title would get the bookmark.
    title_matches = test_utils.GetOmniboxMatchesFor(self, title, windex=windex)
    self._VerifyHasBookmarkResult(title_matches)
    # Check if the partial URL would get the bookmark.
    split_url = urlparse.urlsplit(url)
    partial_url = test_utils.GetOmniboxMatchesFor(
        self, split_url.scheme, windex=windex)
    self._VerifyHasBookmarkResult(partial_url)
    # Check if the partial title would get the bookmark.
    split_title = title.split()
    search_term = split_title[len(split_title) - 1]
    partial_title = test_utils.GetOmniboxMatchesFor(
        self, search_term, windex=windex)
    self._VerifyHasBookmarkResult(partial_title)

  def testBookmarkResultInNewTabAndWindow(self):
    """Verify omnibox finds bookmarks in search options of new tabs/windows."""
    url = self.GetFileURLForDataPath('title2.html')
    self.NavigateToURL(url)
    title = 'This is Awesomeness'
    bookmarks = self.GetBookmarkModel()
    bar_id = bookmarks.BookmarkBar()['id']
    self.AddBookmarkURL(bar_id, 0, title, url)
    bookmarks = self.GetBookmarkModel()
    nodes = bookmarks.FindByTitle(title)
    self.AppendTab(pyauto.GURL(url))
    self._CheckBookmarkResultForVariousInputs(url, title)
    self.OpenNewBrowserWindow(True)
    self.assertEqual(2, self.GetBrowserWindowCount())
    self.NavigateToURL(url, 1, 0)
    self._CheckBookmarkResultForVariousInputs(url, title, windex=1)
    self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW)
    self.assertEqual(3, self.GetBrowserWindowCount())
    self.NavigateToURL(url, 2, 0)
    self._CheckBookmarkResultForVariousInputs(url, title, windex=2)

  def testAutoCompleteForNonAsciiSearch(self):
    """Verify can search/autocomplete with non-ASCII incomplete keywords."""
    search_string = u'\u767e'
    verify_string = u'\u767e\u5ea6\u4e00\u4e0b'
    matches = test_utils.GetOmniboxMatchesFor(self, search_string)
    self.assertTrue(verify_string in matches[-1]['contents'])

class OmniboxLiveTest(pyauto.PyUITest):
  """Test cases for the omnibox that hit live servers (such as Google)."""

  def ExtraChromeFlags(self):
    """Override default list of extra flags used in pyauto tests."""
    # Force the suggest field trial group. This doesn't guarantee that there
    # will be no experimental behaviour, but there's no other way to disable
    # all suggest field trials at the moment. TODO(mpearson): Consider allowing
    # the suggest_url to be overridden using a flag (so that we can omit the
    # "sugexp=chrome,mod=<n>" CGI param), or provide some other way to turn off
    # all suggest field trials.
    return ['--force-fieldtrials=OmniboxSearchSuggest/10/']

  def testGoogleSearch(self):
    """Verify Google search item in omnibox results."""
    search_text = 'hello world'
    verify_str = 'Google Search'
    url_re = 'http://www.google.com/search\?.*q=hello\+world.*'
    matches_description = test_utils.GetOmniboxMatchesFor(
        self, search_text, attr_dict={'description': verify_str})
    self.assertTrue(matches_description)
    # There should be a least one entry with the description Google. Suggest
    # results may end up having 'Google Search' in them, so use >=.
    self.assertTrue(len(matches_description) >= 1)
    item = matches_description[0]
    self.assertTrue(re.search(url_re, item['destination_url']))
    self.assertEqual('search-what-you-typed', item['type'])

if __name__ == '__main__':
  pyauto_functional.Main()


import ibapi
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
from ibapi.order import Order
from time import sleep
import threading
from datetime import datetime
from multiprocessing import Queue
from multiprocessing import queues
from ibapi.commission_report import CommissionReport
from ibapi.wrapper import TickerId
import pandas as pd

contract_dict = {"EURUSD" :("EUR",'USD'), 'EURGBP': ('EUR','GBP'), 'EURJPY': ('EUR','JPY'),'EURCHF':('EUR','CHF'), "EURCAD": ("EUR","CAD"), 'EURAUD': ('EUR','AUD'),'EURNZD':('EUR','NZD'),
                 "GBPUSD": ("GBP",'USD'),'USDJPY' :('USD','JPY'),'USDCHF':('USD','CHF'),'USDCAD':('USD','CAD'),'AUDUSD':('AUD','USD'),'NZDUSD':('NZD','USD'),
                 'GBPJPY' : ('GBP','JPY'),'GBPCHF':('GBP','CHF'),'GBPCAD':('GBP','CAD'),'GBPAUD':('GBP','AUD'),'GBPNZD':('GBP','NZD'),
                 "CHFJPY": ("CHF",'JPY'),'CADJPY':('CAD','JPY'),'AUDJPY':('AUD','JPY'), 'NZDJPY':('NZD','JPY'),
                 'CADCHF':('CAD','CHF'), 'AUDCHF':( 'AUD','CHF'),'NZDCHF':('NZD','CHF'),
                 'AUDCAD':('AUD','CAD'), 'AUDNZD':('AUD','NZD'),
                 'NZDCAD':('NZD','CAD'),
                 'USDSEK': ('USD','SEK'), 'USDRUB': ('USD','RUB'), 'USDNOK': ('USD','NOK'), 'USDMXN': ('USD','MXN'), 'USDDKK': ('USD','DKK'), 'USDCNH': ('USD','CNH'),
                 }
futures_dict = {'ZF':('ZF','USD','ECBOT','20190628','1000'),'ZB':('ZB','USD','ECBOT','20190619','1000'),'ZN':('ZN','USD','ECBOT','20190619','1000'),
           'BTP': ('BTP', 'EUR', 'DTB', '20190606', '1000'),'GBL':('GBL','EUR','DTB','20190606','1000'),'GBM':('GBM','EUR','DTB','20190606','1000'),
           'OAT': ('OAT', 'EUR', 'DTB', '20190606', '1000'),
                'ES':('ES','USD','GLOBEX_IND','20190621','50'),'NQ':('NQ','USD','GLOBEX_IND','20190621','20'),
                'DESX5': ('DESX5', 'EUR', 'DTB', '20191220', '100'),'YM': ('YM', 'USD', 'ECBOT', '20190621', '5'),
                'Z': ('Z', 'GBP', 'ICEEU', '20190621', '1000'),'SMI': ('SMI', 'CHF', 'SOFFEX', '20190621', '10'),
                'R': ('R', 'GBP', 'ICEEU', '20190626', '1000')}

KEYS = ['time','open','high','low','close']

class tickThread(threading.Thread):
    req_id = 0

    def __init__(self, threadID, conn):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.conn = conn

    def run(self):
        self.conn.run()

class IBInterface(EWrapper, EClient):
    wrapper_dict = {EWrapper.nextValidId.__name__: Queue(), EWrapper.openOrder.__name__: Queue(),
                    EWrapper.orderStatus.__name__: Queue(), EWrapper.updatePortfolio.__name__: Queue(),
                    EWrapper.execDetails.__name__: Queue(), EWrapper.commissionReport.__name__:Queue()}
    def __init__(self, host, port, client_id,account):
        self.host = host
        self.port = port
        self.open_orders = {}
        self.open_positions = {}
        self.req_id = 0
        self.account = account
        EWrapper.__init__(self)
        EClient.__init__(self, wrapper=self)
        self.connect(host, port, client_id)
        self.startApi()
        tickThread(101010, self).start()
        if self.isConnected():
            1
        else:
            while self.isConnected() == False:

                print('Sleeping 40 seconds')
                sleep(40)
                self.disconnect()
                self.done = False
                self.connect(host, port, client_id)
                self.startApi()
                tickThread(101010, self).start()
        self.reqAccountUpdates(True,account)

    #*********** Wrapper Functions *********************#
    def error(self, reqId:TickerId, errorCode:int, errorString:str):

        print('############## ' + str(reqId) + ' : ' + str(errorCode) + ' : ' + str(errorString) + ' ###################')
        if errorCode == 2107:
            contract = self.create_contract("EURJPY", 'FX')
            self.getHistoricalData(contract, '', '1 D', '30 mins', 'ASK', 1, 1)
    def nextValidId(self, orderId: int):

        while self.wrapper_dict[EWrapper.nextValidId.__name__].qsize()>0:
            self.wrapper_dict[EWrapper.nextValidId.__name__].get()
        self.wrapper_dict[EWrapper.nextValidId.__name__].put(orderId)
        print('Next valid ID ' + str(orderId))

    def realtimeBar(self, reqId: int, time: int, open: float, high: float, low: float, close: float, volume: int,
                    WAP: float, count: int):
        data_dict = {}
        data_dict['open'] = open
        data_dict['high'] = high
        data_dict['low'] = low
        data_dict['close'] = close
        data_dict['time'] = time
        data_dict['volume'] = volume
        self.wrapper_dict[EWrapper.realtimeBar.__name__+str(reqId)].put(data_dict)

    def connectionClosed(self):
        super().connectionClosed()
        print('Connection Closed')

    def historicalData(self, reqId:int , bars : object):

        data_dict = {}
        data_dict['open'] = bars.open
        data_dict['high'] = bars.high
        data_dict['low'] = bars.low
        data_dict['close'] = bars.close
        data_dict['time'] = bars.date
        data_dict['volume'] = bars.volume
        self.wrapper_dict[EWrapper.historicalData.__name__+str(reqId)].put(data_dict)

    def historicalDataEnd(self, reqId:int, start:str, end:str):
        super().historicalDataEnd(reqId,start,end)
        print('Historicla Data End')
        self.wrapper_dict[EWrapper.historicalData.__name__ + str(reqId)].put('End')

    # def historicalDataUpdate(self, reqId: int, bar: object):
    #     wrapper_dict[EWrapper.historicalDataUpdate.__name__ + str(reqId)].put(bar)

    def openOrder(self, orderId:int, contract:Contract, order:Order,
                  orderState:object):
        data_dict ={}
        data_dict['orderId'] = orderId
        print('Order open with orderID : '+str(orderId) + " for contract : "+str(contract.symbol)+str(contract.currency))
        data_dict['contract'] = contract
        data_dict['order'] = order
        data_dict['orderState']  =orderState
        print(f'Order ID : {order.orderId}, action : {order.action}, type : {order.orderType}, quantity : {order.totalQuantity}, price : {order.lmtPrice}')
        self.wrapper_dict[EWrapper.openOrder.__name__].put(data_dict)

    def orderStatus(self, orderId:int , status:str, filled:float,
                    remaining:float, avgFillPrice:float, permId:int,
                    parentId:int, lastFillPrice:float, clientId:int,
                    whyHeld:str,mktCapPrice:float):
        data_dict = {}
        data_dict['status'] = status
        data_dict['filled'] = filled
        data_dict['remaining'] = remaining
        data_dict['avgFillPrice'] = avgFillPrice
        data_dict['permId'] = permId
        data_dict['parentId'] = parentId
        data_dict['lastFillPrice'] = lastFillPrice
        data_dict['clientId'] = clientId
        data_dict['whyHeld'] = whyHeld
        data_dict['mktCapPrice'] = mktCapPrice

        self.wrapper_dict[EWrapper.orderStatus.__name__].put(data_dict)

    def updatePortfolio(self, contract:Contract, position:float,
                        marketPrice:float, marketValue:float,
                        averageCost:float, unrealizedPNL:float,
                        realizedPNL:float, accountName:str):
        data_dict = {}
        data_dict['contract'] = contract
        data_dict['position'] = position
        data_dict['marketPrice'] = marketPrice
        data_dict['marketValue'] = marketValue
        data_dict['averageCost'] = averageCost
        data_dict['unrealizedPNL'] = unrealizedPNL
        data_dict['realizedPNL'] = realizedPNL
        data_dict['accountName'] = accountName
        self.wrapper_dict[EWrapper.updatePortfolio.__name__].put(data_dict)

    def execDetails(self, reqId:int, contract:Contract, execution:object):
        data_dict={}
        data_dict['contract'] = contract
        data_dict['execution'] = execution
        print("To API mas dinei auta " + str(execution.side) + ' '+contract.symbol+contract.currency + ' stis  '+str(execution.time) + " me timh "+str(execution.price) + ' kai lot '+str(execution.shares) + ' ston account '+ str(execution.acctNumber))
        self.wrapper_dict[EWrapper.execDetails.__name__].put(data_dict)

    def commissionReport(self, commissionReport:CommissionReport):
        data_dict = {}
        data_dict['commission'] = commissionReport
        print(commissionReport.realizedPNL)
        self.wrapper_dict[EWrapper.commissionReport.__name__].put(data_dict)

    #**************** Client Methods ******************#

    def req_next_valid_req_id(self):
        self.req_id += 1
        return self.req_id

    def check_conn(self):
        if (self.isConnected() == False):
            while self.isConnected() == False:
                sleep(60)
                self.connect(self.host, self.port, self.client_id)
        return True

    def check_req_id(self):
        self.nextValidId()

    def reqIds(self):
        super().reqIds(-1)
        sleep(0.5)
        queue = self.wrapper_dict[EWrapper.nextValidId.__name__]
        print("Testing ReqID")
        try:
            if queue.qsize()>0:
                id = queue.get(block=True,timeout=5)
            else:
                id =0
        except queues.Empty:
            id = 0
        return id

    def reqRealTimeBars(self, contract, barSize,
                        whatToShow, useRTH):
        req_id = self.req_next_valid_req_id()
        super().reqRealTimeBars(reqId=req_id, contract=contract, barSize=barSize,
                                whatToShow=whatToShow, useRTH=useRTH, realTimeBarsOptions=[])
        queue = Queue()
        self.wrapper_dict[EWrapper.realtimeBar.__name__+str(req_id)] = queue

        return queue

    def getHistoricalData(self,contract,end_date_time,duration_string,bar_size_setting, what_to_show,userth=1,format_date=2,keep_up_to_date = False ):
        req_id = self.req_next_valid_req_id()
        queue = Queue()
        self.wrapper_dict[EWrapper.historicalData.__name__ + str(req_id)] = queue
        super().reqHistoricalData(reqId=req_id,contract= contract,endDateTime=end_date_time,durationStr=duration_string,barSizeSetting=bar_size_setting,whatToShow=what_to_show,useRTH=userth,formatDate=format_date,keepUpToDate=keep_up_to_date,chartOptions=[])
        data = []
        queue = self.wrapper_dict[EWrapper.historicalData.__name__+str(req_id)]
        while True:
            try:
                z = queue.get(block=True,timeout=100)
                if z != 'End':
                    data.append(z)
                else:
                    break

            except queues.Empty:
                break

        return data

    def getOpenOrders(self):
        super().reqOpenOrders()
        queue = self.wrapper_dict[EWrapper.openOrder.__name__]

        data = []
        orders = []
        print('At open Orders, queue size : '+str(queue.qsize()))
        try:

            for i in range(queue.qsize()):
            #TODO: Sometimes this will fail with queue.Empty
                data.append(queue.get(block=False))
            orders = self.set_open_orders(data)
        except queues.Empty:
            orders = []
            print("Queue Empty")

        return orders
    def getAllOpenOrders(self):
        super().reqAllOpenOrders()
        queue = self.wrapper_dict[EWrapper.openOrder.__name__]
        data = []
        sleep(1)
        print('At all open Orders, queue size : '+str(queue.qsize()))
        try:

            for i in range(queue.qsize()):
            #TODO: Sometimes this will fail with queue.Empty
                data.append(queue.get(block=False))
            orders = self.set_open_orders(data)
        except queues.Empty:
            orders = []
            print("Queue Empty")

        return orders
    def getRealTimeHistoricalData(self,contract,end_date_time,duration_string,bar_size_setting, what_to_show,userth,format_date,keep_up_to_date = True):
        req_id = self.req_next_valid_req_id()
        queue = Queue()
        self.wrapper_dict[EWrapper.historicalDataUpdate.__name__ + str(req_id)] = queue
        queue2 = Queue()
        self.wrapper_dict[EWrapper.historicalData.__name__ + str(req_id)] = queue2
        super().reqHistoricalData(reqId=req_id, contract=contract, endDateTime=end_date_time,
                                  durationStr=duration_string, barSizeSetting=bar_size_setting, whatToShow=what_to_show,
                                  useRTH=userth, formatDate=format_date,keepUpToDate=keep_up_to_date,chartOptions=[])
        queue2 = self.wrapper_dict[EWrapper.historicalData.__name__ + str(req_id)]
        data = []
        while True:
            try:
                z = queue2.get(block=True)
                if z != 'End':
                    data.append(z)
                else:
                    break
            except queues.Empty:
                break

        return queue,data

    def getAccountPositions(self,account):
        super().reqAccountUpdates(True,account)
        queue = self.wrapper_dict[EWrapper.updatePortfolio.__name__]

        data = []
        try:

            for i in range(queue.qsize()):
                data.append(queue.get(block=False))
            positions = self.set_open_positions(data)
        except queues.Empty:
            positions = {}
            print("Queue Empty")

        return positions

    def currentTime(self, time: int):
        super().currentTime(time)
        self.serverTime = time
        print(time)

    def create_contract(self,symbol, contract_type):
        if contract_type == "FX":
            contract = Contract()
            contract.symbol = contract_dict[symbol][0] #FOAT DEC 17
            contract.secType = "CASH" #FUT
            contract.currency = contract_dict[symbol][1] #EUR
            contract.exchange = "IDEALPRO" #DTP
            return contract
        elif contract_type=='FUTURE':
            contract = Contract()
            contract.symbol = futures_dict[symbol][0]
            contract.secType = "FUT"
            contract.currency = futures_dict[symbol][1]
            contract.exchange = futures_dict[symbol][2]
            contract.lastTradeDateOrContractMonth=futures_dict[symbol][3]
            contract.multiplier = futures_dict[symbol][4]
            return contract

    def create_order(self,action,quantity,type,price = 0):
        order = Order()
        order.orderType = type
        if type != 'MKT':
            order.lmtPrice = price
            order.tif = 'GTC'
        order.action = action
        order.totalQuantity = quantity
        order.account = self.account
        print('Parent Order Quantity '+str(quantity))
        return order

    def sell(self,quantity,contract,open_position,take_profit_price=0,stop_loss_price=0,limit_orders_lot=0,is_combined=False,reduce_lot = False,order_type = 'MKT',price =0):
        total_orders = []
        parent_id = self.reqIds()
        sleep(0.7)
        print('Apo to sell to ID einai : '+str(parent_id))
        other_id = parent_id

        order= self.create_order('SELL',quantity+abs(open_position),order_type,price=price)
        order.orderId = parent_id
        total_orders.append(order)
        if take_profit_price!= 0:

            take_profit_order = Order()

            other_id +=1
            take_profit_order.orderId = other_id
            if reduce_lot:
                take_profit_order.action = 'SELL'
            else:
                take_profit_order.action = 'BUY'
            take_profit_order.lmtPrice = take_profit_price
            take_profit_order.orderType = 'LMT'
            take_profit_order.totalQuantity = limit_orders_lot
            print('Take Profit Order Quantity :'+str(take_profit_order.totalQuantity))
            take_profit_order.tif = 'GTC'
            take_profit_order.ocaType = 1
            take_profit_order.account = self.account
            take_profit_order.ocaGroup = contract.symbol+contract.currency + str(parent_id)
            total_orders.append(take_profit_order)
        if stop_loss_price !=0:

            stop_loss_order = Order()

            other_id += 1
            stop_loss_order.orderId = other_id
            if reduce_lot:
                stop_loss_order.action = 'SELL'
            else:
                stop_loss_order.action = 'BUY'
            stop_loss_order.auxPrice = stop_loss_price
            stop_loss_order.orderType = 'STP'
            stop_loss_order.totalQuantity = limit_orders_lot
            print('Stop Loss Order Quantity :' + str(stop_loss_order.totalQuantity))
            stop_loss_order.tif = 'GTC'
            stop_loss_order.ocaType = 1
            stop_loss_order.account = self.account
            stop_loss_order.ocaGroup = contract.symbol+contract.currency + str(parent_id)
            total_orders.append(stop_loss_order)

        orders = self.getOpenOrders()
        if is_combined==False:
            for open_order in orders:
                if contract.symbol + contract.currency in orders[open_order][1].ocaGroup:
                    self.cancelOrder(open_order)
        for every_order in total_orders:
            self.placeOrder(every_order.orderId, contract,every_order)
            sleep(2)

        return self.wrapper_dict[EWrapper.openOrder.__name__], self.wrapper_dict[EWrapper.orderStatus.__name__]

    def buy(self,quantity,contract,open_position,take_profit_price=0,stop_loss_price=0,limit_orders_lot=0, is_combined=False,reduce_lot = False,order_type = 'MKT',price =0):
        total_orders = []
        parent_id = self.reqIds()
        sleep(0.7)
        print('Apo to buy to ID einai : ' + str(parent_id))
        other_id = parent_id
        order= self.create_order('BUY',quantity+abs(open_position),order_type,price=price)
        order.orderId = parent_id
        total_orders.append(order)
        if take_profit_price!= 0:

            take_profit_order = Order()

            other_id +=1
            take_profit_order.orderId = other_id
            if reduce_lot:
                take_profit_order.action = 'BUY'
            else:
                take_profit_order.action = 'SELL'
            take_profit_order.lmtPrice = take_profit_price
            take_profit_order.orderType = 'LMT'
            take_profit_order.totalQuantity = limit_orders_lot
            take_profit_order.tif = 'GTC'
            take_profit_order.ocaType = 1
            take_profit_order.account = self.account
            take_profit_order.ocaGroup = contract.symbol+contract.currency  + str(parent_id)
            total_orders.append(take_profit_order)
        if stop_loss_price !=0:

            stop_loss_order = Order()

            other_id += 1
            stop_loss_order.orderId = other_id
            if reduce_lot:
                stop_loss_order.action = 'BUY'
            else:
                stop_loss_order.action = 'SELL'
            stop_loss_order.auxPrice = stop_loss_price
            stop_loss_order.orderType = 'STP'
            stop_loss_order.totalQuantity = limit_orders_lot
            stop_loss_order.tif = 'GTC'
            stop_loss_order.ocaType = 1
            stop_loss_order.account = self.account
            stop_loss_order.ocaGroup = contract.symbol+contract.currency + str(parent_id)
            total_orders.append(stop_loss_order)
        orders = self.getOpenOrders()
        if is_combined == False:
            for open_order in orders:
                if contract.symbol+contract.currency in orders[open_order][1].ocaGroup:
                    self.cancelOrder(open_order)
        for every_order in total_orders:
            self.placeOrder(every_order.orderId, contract,every_order)

        return self.wrapper_dict[EWrapper.openOrder.__name__], self.wrapper_dict[EWrapper.orderStatus.__name__]

    def set_open_positions(self,queue_positions):
        for order in queue_positions:
            self.open_positions[order['contract'].symbol+ order['contract'].currency] = dict(position=order['position'],unrealizedPNL= order['unrealizedPNL'])

        return self.open_positions

    def set_open_orders(self,queue_orders):
        self.open_orders= {}
        for order in queue_orders:
            self.open_orders[order['orderId']] = (order['contract'],order['order'],order['orderState'])

        return self.open_orders

    def reqExecutionDetails(self,filter):

        self.reqExecutions(reqId=1,execFilter=filter)
        queue =  self.wrapper_dict[EWrapper.execDetails.__name__]
        queue_commision = self.wrapper_dict[EWrapper.commissionReport.__name__]
        return queue, queue_commision

    def getAccountPositionsQueue(self,account):
        super().reqAccountUpdates(True,account)
        queue = self.wrapper_dict[EWrapper.updatePortfolio.__name__]
        return queue

def store_historical_data_to_file(symbol, currency, data):
    data = pd.DataFrame(data)
    data = data.set_index(pd.to_datetime(data['time']))
    data = data.drop('time',axis =1)

    store = pd.HDFStore('tick_data' + symbol + currency + '.h5')
    store.open()

    if ('/'+symbol+currency) in store.keys():
        idx = store.select(symbol+currency,where="index in data.index",columns=['index']).index

        print('Store ' + symbol + currency + ' was written with length ' + str(len(data.query('index not in @idx'))))
        # print(dataframe)
        store.append(symbol + currency, data.query('index not in @idx'), format='t')
    else:
        store.append(symbol + currency, data, format='t')
        print(data)
    store.close()

# def store_queue_to_file(queue,symbol,currency):
#
#             msg_array = []
#             times = []
#             while True:
#                 try:
#                     t1 = time.time()
#                     now = datetime.now()
#                     msg = queue.get(block = True)
#                     msg_array.append(msg)
#                     times.append(time.time() - t1)
#                     if pd.to_datetime(msg['time'], unit='s').second == 55:
#                         break
#
#
#                 except queues.Empty:
#                     break
#             data_dict_array = []
#             if len(msg_array) > 1:
#                 for msg in msg_array:
#                     data_dict = {}
#                     for key in KEYS:
#                         data_dict[key] = msg[key]
#                     data_dict_array.append(data_dict)
#
#                 dataframe = pd.DataFrame(data=data_dict_array)
#                 dataframe['time'] = pd.to_datetime(dataframe['time'], unit='s')
#
#
#                 dataframe = dataframe.set_index(pd.to_datetime(dataframe['time']))
#                 dataframe = dataframe.drop('time', axis=1)
#                 print(dataframe.index)
#
#                 store = pd.HDFStore('tick_data' + symbol + currency + '.h5')
#                 store.open()
#                 print('Store ' + symbol + currency + ' was written with length ' + str(len(dataframe)))
#                 # print(dataframe)
#                 store.append(symbol + currency, dataframe, format='t')
#
#                 store.close()

# def set_open_orders(orders):
#     for order in orders:
#
#         if order['order'].ocaGroup != '':
#             open_orders[order['orderId']] = order['order'].ocaGroup

# if __name__ == '__main__':
#
#     test = IBInterface(host='127.0.0.1', port=7496, client_id=101011,account = 'DU517095')
#     test.startApi()
#     #test.reqAllOpenOrders()
#
#
#     import time
#
#     time.sleep(1)
#
#     tickThread(101010, test).start()
#     test.reqIds()
#     test.reqCurrentTime()
#     print("Order ID " + str(test.nextValidOrderId))
#     sleep(2)
#     orders = test.getOpenOrders()
#     open_positions = test.getAccountPositions('DU517095')
#     #set_open_orders(orders)
#     contract = test.create_contract("EURJPY", 'FX')
#
#     test.sell(10000,contract,open_positions['EURJPY'],127.5,128.4)
#     x = test.reqIds()
#     x = test.check_conn()
#     #queryTime = datetime.now().replace(month = -6).strftime("yyyyMMdd HH:mm:ss")
#     #y, data = test.getRealTimeHistoricalData(contract,'','1 D','30 secs','MIDPOINT',1,1)
#     real_time_bars = {}
#     # for contracts in contract_dict:
#     #     contract = test.create_contract(contracts, 'FX')
#     #
#     #     data = test.getHistoricalData(contract,'','2 D','1 min','ASK',1,1)
#     #     store_historical_data_to_file(contract_dict[contracts][0], contract_dict[contracts][1],data)
#     #
#     # for contracts in contract_dict:
#     #     contract = test.create_contract(contracts, 'FX')
#     #     real_time_bars[contracts] = test.reqRealTimeBars(contract, 5, 'ASK', True)
#     # sleep(2)
#     # 1
#     # # contract = test.create_contract('AUDCAD','FX')
#     # #
#     # # y = test.reqRealTimeBars(contract, 5, "ASK", True)
#     # # print(x)
#     # while True:
#     #     for contracts in contract_dict:
#     #         if test.isConnected():
#     #
#     #             store_queue_to_file(real_time_bars[contracts], contract_dict[contracts][0], contract_dict[contracts][1])


import numpy as np
import scipy.integrate as intgr
import matplotlib.pyplot as plt

heaviside = lambda x: 0.5 * (np.sign(x) + 1)
gap_function = lambda a, l: lambda x: heaviside(x-a) * heaviside(a + l - x)

normal_concetrated_force_gen = lambda N, x0 = 0: lambda x: (-1) * N * heaviside(x - x0)

disturbed_force_gen = lambda f, l, x0 = 0: lambda x: f(x - x0) * gap_function(x0, l)(x)
normal_disturbed_force_gen = lambda f: lambda x:(-1) * intgr.quad(f, 0, x)[0] #use with "disturbed_force_gen function"
overall_disturbed_force = lambda f, l: intgr.quad(lambda x: intgr, 0, l)[0] #use with original d.force function

enlongation_gen = lambda N, E, A: lambda x: intgr.quad(lambda x: N(x)/E(x)/A(x), 0, x)[0]
tense_gen = lambda N, A: lambda x: N(x)/A(x)
#_gen functions used to produce final functions

#use if defined allowed enlongation
reaction_force_left= lambda w_max, length, E, A: (-1) * w_max * intgr.quad(lambda x: w_max*E*A(x)/x)[0]

def function_addition(a, b):
    return lambda x: a(x) + b(x)

def width_function_gen(A, L):
    #a_f = list()
    a_f = list([lambda x: A[0]*gap_function(0, L[0])(x)])
    a_f_gen = lambda j: lambda x: a_f[j-1](x) + A[j]*gap_function(L[j-1], L[j] - L[j - 1])(x)
    for i in range(1, len(A)):
        a_f.append(a_f_gen(i))
    return a_f[len(A) - 1]

def diagram(f, l,r, name = '', d = -1):
    if d == -1:
        d = 1000
    x = np.arange(l, r, abs(float(l - r))/d)
    y = map(f, x)
    ymx = max(y)
    ymn = min(y)
    #Настроим сетку
    plt.rc('text', usetex=False)
    plt.plot(x, y, color='green')
    plt.axhline(xmax = r)
    plt.axvline(ymax = ymx)
    plt.grid()
    plt.axis([l, r, ymn, ymx*1.5],'tight')
    #Создадим название графика
    plt.title(name)
    plt.show()

def diag_list(f, l, r, d = 1000):
    '''Функция строит график массива функций f в промежутке от l до r c количеством разбиений равным d'''
    x_ar = np.arange(l, r, abs(float(l - r))/d)
    y_ar = map(lambda a: map(a, x_ar), f)

    for i in range(len(y_ar)):
        y_t = y_ar[i]
        ymx = max(y_t)
        ymn = min(y_t)
        d = ymx - ymn
        plt.axhline(xmax = r, color = 'black')
        plt.axvline(ymax = ymx, color = 'black')
        plt.grid()
        plt.subplot(len(y_ar), 1, i+1)
        plt.plot(x_ar, y_t)
        plt.axis([l, r, ymn - d*0.01, ymx + d*0.1])

    plt.show()

def arr_red(iterble):
    cpr = list(iterble)
    for i in range(len(iterble)):
        iterble[i] = reduce(lambda a, b: a + b, cpr[:i + 1])


from typing import List

from fastapi import APIRouter, Depends

from app.core.security import get_request_user_id, is_consumer
from app.models.comment import CommentCreate, CommentRead
from app.services.comment import CommentService

router = APIRouter(tags=['comment'])

@router.get("",
            response_model=List[CommentRead]
            )
async def get_story_comments(
        story_id: int,
        comment_service: CommentService = Depends(CommentService)
):
    """
    Given a research story id, returns a list of all comments under that story:
    """
    return comment_service.get_story_comments(story_id)

@router.post("",
             response_model=CommentRead,
             dependencies=[Depends(is_consumer)]
             )
async def add_comment(
        comment: CommentCreate,
        comment_service: CommentService = Depends(CommentService),
        current_user_id: int = Depends(get_request_user_id)
):
    """
    Posts a comment under a research and if successful the id of the new comment
    """
    return comment_service.add_comment(comment, current_user_id)

@router.get("/like",
            response_model=bool,
            dependencies=[Depends(is_consumer)]
            )
async def get_comment_like(
        comment_id: int,
        comment_service: CommentService = Depends(CommentService),
        current_user_id: int = Depends(get_request_user_id)
):
    """
    Returns true/false on whether the current user has liked a comment
    """
    return comment_service.get_comment_like(comment_id, current_user_id)

@router.get("/likes",
            response_model=int
            )
async def get_num_likes(
        comment_id: int,
        comment_service: CommentService = Depends(CommentService),
):
    """
    Returns the number of likes on a comment
    """
    return comment_service.get_num_likes(comment_id)

@router.put("/like",
            response_model=None,
            dependencies=[Depends(is_consumer)]
            )
async def set_comment_like(
        comment_id: int,
        liked: bool,
        comment_service: CommentService = Depends(CommentService),
        current_user_id: int = Depends(get_request_user_id)
):
    """
    Sets a comment to either liked (true) or not liked (false) by the current user
    """
    comment_service.set_comment_like(current_user_id, comment_id, liked)


import requests
from bs4 import BeautifulSoup
import csv

# Define the base URL and headers
base_url = "https://www.amazon.in/s?k=bags&crid=2M096C61O4MLT&qid=1653308124&sprefix=ba%2Caps%2C283&ref=sr_pg_1"
headers = {
    "User-Agent": "use your user agent to bypass"
}

# Part 1: Scraping Product Listings
with open("amazon_products.csv", "w", newline="", encoding="utf-8") as csv_file:
    csv_writer = csv.writer(csv_file)
    csv_writer.writerow(["Product URL", "Product Name", "Product Price", "Rating", "Number of Reviews"])

    for page_number in range(1, 21):  # Scraping 20 pages
        params = {
            "k": "bags",
            "crid": "2M096C61O4MLT",
            "qid": "1653308124",
            "sprefix": "ba,aps,283",
            "ref": f"sr_pg_{page_number}",
        }
        response = requests.get(base_url, headers=headers, params=params)

        soup = BeautifulSoup(response.content, "html.parser")
        products = soup.find_all("div", class_="a-link-normal s-underline-text s-underline-link-text s-link-style a-text-normal")

        for product in products:
            product_url = product.find("a", class_="a-link-normal").get("href")
            product_name = product.find("span", class_="a-text-normal").text
            product_price = product.find("span", class_="a-price-whole").text
            rating = product.find("span", class_="a-icon-alt").text
            num_reviews = product.find("span", class_="a-size-base").text.split()[0]

            csv_writer.writerow([product_url, product_name, product_price, rating, num_reviews])

print(response.content)

# Part 2: Scraping Additional Product Information
product_urls = []
with open("amazon_products.csv", "r", encoding="utf-8") as csv_file:
    csv_reader = csv.reader(csv_file)
    next(csv_reader)  # Skip the header row
    for row in csv_reader:
        product_urls.append(row[0])  # Product URL is in the first column

with open("amazon_products_additional.csv", "w", newline="", encoding="utf-8") as csv_file_additional:
    csv_writer_additional = csv.writer(csv_file_additional)
    csv_writer_additional.writerow(["Product URL", "Description", "ASIN", "Product Description", "Manufacturer"])

    for product_url in product_urls:
        response = requests.get(product_url, headers=headers)

        soup = BeautifulSoup(response.content, "html.parser")

        # Extract information from the product page and add to the CSV
        description = soup.find("meta", {"name": "description"}).get("content", "")
        asin = soup.find("th", text="ASIN").find_next_sibling("td").text.strip()
        product_desc = soup.find("div", {"id": "productDescription"}).text.strip()
        manufacturer = soup.find("a", {"id": "bylineInfo"}).text.strip()

        csv_writer_additional.writerow([product_url, description, asin, product_desc, manufacturer])