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 json

from bs4 import BeautifulSoup

def find_elements(bs_content, structure):

    circuit = bs_content.find(structure)
    elements = [tag.name for tag in circuit.find_all() if "list" in tag.name]
    total_components = {}
    for element in elements:
        components = circuit.find(element)
        components = circuit.find_all(element.replace("_list",""))
        total_components[element.replace("_list","")] = {}
        if components is not None:
            for component in components:
                tags = [(tag.name,tag.text) for tag in component.find_all()]
                for i in range(len(tags)):
                    tag_name = tags[i][0]
                    tag_value = tags[i][1]
                    if i == 0:
                        total_components[element.replace("_list","")][tag_value] = {}
                    else:
                        total_components[element.replace("_list","")][tags[0][1]][tag_name] = tag_value

    with open(structure + ".json", "w") as file:
        json.dump(total_components, file, indent=2)

def main(archieve):

    with open(archieve, "r") as file:
        content = file.readlines()
        content = "".join(content)

        bs_content = BeautifulSoup(content,"lxml")

    find_elements(bs_content,"powerflow")
    find_elements(bs_content,"assert")
    find_elements(bs_content,"tape")

archieve = "ejemplo.xml"
main(archieve)


from typing import Optional, Any
from hyperiontf.logging import getLogger, Logger

from hyperiontf.typing import (
    ContentSwitchingException,
    StaleElementReferenceException,
    DEFAULT_CONTENT,
)
from hyperiontf.typing import AnyContentContainer
from .iframe import IFrame

class ContentManager:
    """
    The ContentManager class manages context switching for WebPage and Iframe instances.

    It allows switching the context to different iframes within the page.
    """

    def __init__(
        self,
        owner: AnyContentContainer,
        logger: Logger = getLogger("PageObject"),
        current_content: Optional[str] = DEFAULT_CONTENT,
    ):
        """
        Initialize the ContentManager with the provided owner, logger, and current_content.

        :param owner: The WebPage or WebView instance that owns the context.
        :param logger: The logger to use for logging context switching information.
        :param current_content: The initial current context of the manager, defaults to 'default'.
        """
        self.owner = owner
        self.current_context = current_content
        self._logger = logger

    @property
    def automation_adapter(self):
        """
        Get the automation_adapter from the owner, if available.

        :return: The automation_adapter if available, otherwise None.
        """
        if hasattr(self.owner, "automation_adapter"):
            return self.owner.automation_adapter
        return None

    def set_context(self, iframe: Any):
        """
        Set the context to the provided iframe.

        :param iframe: The IFrame instance to switch the context to.
        :raises ContextSwitchingException: If context switching fails.
        """
        # The 'element_adapter' is used to resolve element references and can trigger API calls to find elements or
        # recover from errors. To ensure the correct logging order, we first retrieve the 'element_adapter' before
        # posting a content switch message. This way, the log chronology remains accurate.
        adapter = iframe.element_adapter
        self._logger.debug(
            f"[{self.owner.__full_name__}] Switching content to '{iframe.__full_name__}' iframe."
        )
        self.automation_adapter.switch_to_iframe(adapter)
        self.current_context = iframe.__full_name__

    def set_default_context(self):
        """
        Set the context to the default page context.

        This method switches back to the default context of the page or WebView.
        """
        self._logger.debug(
            f"[{self.owner.__full_name__}] Switching content to default - page content."
        )
        self.automation_adapter.switch_to_default_content()
        self.current_context = DEFAULT_CONTENT

    def resolve_content(self, target: Any, force: bool = False):
        """
        Resolve the context to the target IFrame or default context.

        :param target: The target IFrame to resolve the context to.
        :param force: If True, forces the context to switch even if the current context is already the target.
        """
        if self.current_context == target.__full_name__ and not force:
            return

        if not isinstance(target, IFrame):
            if self.current_context == DEFAULT_CONTENT:
                return
            # If the target is not an IFrame, then traverse back to the page or WebView where the context is default.
            return self.set_default_context()

        try:
            self.set_context(target)
        except ContentSwitchingException as e:
            self._logger.debug(
                f"[{self.owner.__full_name__}] Exception Intercepted!\n{e.__class__.__name__}: {str(e)}"
            )
            # If an exception occurred during context switching, attempt to resolve the parent context first,
            # and then retry setting the target context.
            parent_holder = target.document_holder
            if parent_holder != target:
                parent_holder.__resolve__()
            self.set_context(target)
        except StaleElementReferenceException as e:
            self._logger.debug(
                f"[{self.owner.__full_name__}] Exception Intercepted!\n{e.__class__.__name__}: {str(e)}"
            )
            target.find_itself()
            target.__resolve__()

    # Define an alias for resolve_context
    resolve = resolve_content


import time
import random
import colors
import numpy as np

def rainbow(state, prev=None, beat=False, colorscheme=colors.ocean):
    # shift the whole state by one pixel
    state[:, 1:] = state[:, :-1]
    if beat:
        # insert a new pixel at position one
        state[:, 0] = random.choice(colorscheme)
    else:
        # leaft position one empty
        state[:, 0] = np.tile(0, (1, 3))
    return state

def shifter(state, prev=None, beat=False):
    # simply shifts whatever shate it gets by one.
    # can be used in combination with other filters
    # to combine the effects
    state[:, 1:] = state[:, :-1]
    state[:, 0] = np.tile(0, (1, 3))
    return state

def segment_shade(state, segments=2):
    #state_len = len(state)
    #segment_len= state_len / segments
    #for idx in range(0, state_len, segment_len*2):
    #    #print idx
    #    state[0, idx: idx+segment_len] = 0
    #    state[1, idx: idx+segment_len] = 0
    #    state[2, idx: idx+segment_len] = 0
    state[0, 0:75] = 0
    state[1, 0:75] = 0
    state[2, 0:75] = 0
    return state

def rolling_shift(state, localstate=0, beat=False):
    if not beat:
        return state, localstate
    localstate += 1 #int(beat*4)
    state = np.roll(state, localstate, axis=1)
    return state, localstate

def allglow(state, beat=False, localstate=0, colorscheme=colors.darkblue):
    fade = colorscheme + colorscheme[::-1]
    if localstate:
        localstate -= 1
        idx = len(fade) - localstate - 1
        state[0, :] = fade[idx][0]
        state[1, :] = fade[idx][1]
        state[2, :] = fade[idx][2]
        return state, localstate
    else:
        # reset state to dark
        state.fill(0)
    if beat:
        localstate = len(fade)
        state[0, :] = fade[0][0]
        state[1, :] = fade[0][1]
        state[2, :] = fade[0][2]
    return state, localstate

def strobe(state, prev=None, beat=False, localstate=0, color=(0xf5, 0, 0x57)):
    if localstate:
        localstate -= 1
        return state, localstate
    else:
        # reset state to dark
        state.fill(0)
    if beat:
        # set all leds in our state to #f50057
        state[0, :] = color[0]
        state[1, :] = color[1]
        state[2, :] = color[2]
        # keep it for the next 4 iterations
        localstate = 4
    return state, localstate

def glow(state, prev=None, beat=False, localstate=None, colorscheme=colors.ocean, width=1):
    if not localstate:
        localstate = {}

    shape_len = max(state.shape)
    if beat:
        ## initialize a  glow on a random position
        #localstate[random.choice(range(max(state.shape)))] = 1
        idx = random.choice(range(shape_len))
        localstate[idx] = 1

    # we'll be modifying localstate, so make a copy before we iterate
    # over it.
    cpy = localstate.copy()
    for idx, val in cpy.items():
        color = None
        if val < len(colorscheme):
            if abs(val) > 0:
                color = colorscheme[abs(val)]
                localstate[idx] = val + 1
            else:
                #del localstate[idx]
                color = [0, 0, 0]
            state[0, idx:min(shape_len, idx+width)] = color[0]
            state[1, idx:min(shape_len, idx+width)] = color[1]
            state[2, idx:min(shape_len, idx+width)] = color[2]
        elif val == len(colorscheme):
            localstate[idx] = -(val-1)
    return state, localstate


# https://leetcode.com/problems/find-k-pairs-with-smallest-sums/

from queue import PriorityQueue

def kSmallestPairs(nums1: list, nums2: list, k: int):
    m, n = len(nums1), len(nums2)
    ans = []
    que = PriorityQueue()
    [que.put((nums1[i] + nums2[0], i, 0)) for i in range(m)]

    while que.qsize() and len(ans) < k:
        _, i, j = que.get()
        ans.append([nums1[i], nums2[j]])
        if j + 1 < n:
            que.put((nums1[i] + nums2[j + 1], i, j + 1))

    return ans

if __name__ == "__main__":
    nums1 = [1, 1, 2]
    nums2 = [1, 2, 3]
    print(kSmallestPairs(nums1, nums2, 10))


"""
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),
                }


# -*- 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


import numpy as np
import csv

def main():
    """ EXERCISE 1.3, 1.4, 1.5 """

    testValues = {
        1: {'a':2, 'b': 2, 'c': 3, 'alpha': -1, 'beta': 1},
        2: {'a': 2, 'b': 2, 'c': 3, 'alpha': 2.5, 'beta': -1},
        3: {'a': 2, 'b': 2, 'c': 3, 'alpha': -1, 'beta': 3},
        4: {'a': 2, 'b': 2, 'c': 3, 'alpha': 7, 'beta': -3},
    }

    for i in range(1,5):
        a = testValues[i]['a']
        b = testValues[i]['b']
        c = testValues[i]['c']

        alpha = testValues[i]['alpha']
        beta = testValues[i]['beta']

        print(f"When a={a}, b={b}, c={c}, and alpha={alpha}, beta={beta}")

        A = np.matrix([[alpha, beta, beta],
                       [beta, alpha, beta],
                       [beta, beta, alpha]])

        X0 = np.array([
            [a],
            [b],
            [c]
        ])
        with open(f'results_{i}.csv', 'w', newline='') as new_file:

            csv_writer = csv.writer(new_file)
            csv_writer.writerow(['n', 'a_n', 'b_n', 'c_n', 'avg'])
            for n in range(1, 21):
                Xn = (A**n)*X0
                a_n = Xn[0].A[0][0]
                b_n = Xn[1].A[0][0]
                c_n = Xn[2].A[0][0]
                avg = round((a_n+b_n+c_n)/3, 5)
                print(f"{n},{a_n},{b_n},{c_n}")
                csv_writer.writerow([n, a_n, b_n, c_n, avg])

            print()

main()


#Data Types

#string

print("Hello"[0])
print("123" + "345")

#integer

print(123 + 345)

#float

print(3.14)

#boolean

True
False

num_char = len(input("What is your name?\n"))
#print("Your name has" + num_char + "characters.") - выдаст ошибку
print(type(num_char))
new_num_char = str(num_char)
print(type(new_num_char))
print("Your name has " + new_num_char + " characters.")

#На входе получаем  двузначное число и печатаем сумму его цифр
two_digit_number = input("Type a two digit number: ")
a = int(two_digit_number[0])
b = int(two_digit_number[1])
print(a + b)

# Математические операции
# 2+3 -
# 3-2
# 3/2
# 3*2
# 2**3 = 2*2*2
# Порядок выполнения действий () , ** , * / , + -

#Калькулятор веса
# 🚨 Don't change the code below 👇
height = input("enter your height in m: ")
weight = input("enter your weight in kg: ")
# 🚨 Don't change the code above 👆

#Write your code below this line 👇
bmi = int(weight)/float(height)**2
bmi_as_int = int(bmi)
print(int(bmi_as_int))

result = 4/2
result /=2
score = 0
score +=1

#f-String - позволяет выводить различные типы данных
print(f"your score is {result}")

# 🚨 Don't change the code below 👇
age = input("What is your current age?")
# 🚨 Don't change the code above 👆

#Write your code below this line 👇

age_int = int(age)
age_lost = 90-age_int
days = age_lost*365
weeks = age_lost*52
months = age_lost*12
print(f"You have {days} days, {weeks} weeks, and {months} months left.")

#Если счет составил $150.00, разделенный на 5 человек, с 12% чаевых.

#Каждый человек должен заплатить (150,00 / 5) * 1,12 = 33,6
#Отформатируйте результат с точностью до 2 знаков после запятой = 33,60

#Совет: Существует два способа округления числа. Возможно, вам придется немного погуглить, чтобы решить эту проблему.💪

#Write your code below this line 👇

print("Welcome to the tip calculator!")
bill = float(input("What was the total bill? $"))
would = int(input("How much tip would you like to give? 10, 12, or 15? "))
people = int(input("How many people to split the bill? "))
tip = would / 100
result = (bill / people) + (bill / people) * tip
print(f"Each person should pay: ${round(result, 2)}")


# 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')


#!/usr/bin/env python3
import subprocess
import sys
import time

SERVER_SCRIPT_NAME = "server.py"
SERVER_LOCATION = ""

def start_server(staring_script_name):
    command = sys.executable + " " + staring_script_name

    server_stdout = open("server_stdout.out", "w")
    server_stderr = open("server_stderr.out", "w")

    proc = subprocess.Popen(command, stdout=server_stdout, stderr=server_stderr, shell=True)
    while proc.poll() is None:
        time.sleep(10)

if __name__ == '__main__':
    start_server(SERVER_SCRIPT_NAME)


import pyblish.api
from openpype.pipeline import (
    PublishXmlValidationError,
    PublishValidationError,
    registered_host,
)

class ValidateWorkfileMetadataRepair(pyblish.api.Action):
    """Store current context into workfile metadata."""

    label = "Use current context"
    icon = "wrench"
    on = "failed"

    def process(self, context, _plugin):
        """Save current workfile which should trigger storing of metadata."""
        current_file = context.data["currentFile"]
        host = registered_host()
        # Save file should trigger
        host.save_workfile(current_file)

class ValidateWorkfileMetadata(pyblish.api.ContextPlugin):
    """Validate if wokrfile contain required metadata for publising."""

    label = "Validate Workfile Metadata"
    order = pyblish.api.ValidatorOrder

    families = ["workfile"]

    actions = [ValidateWorkfileMetadataRepair]

    required_keys = {"project_name", "asset_name", "task_name"}

    def process(self, context):
        workfile_context = context.data["workfile_context"]
        if not workfile_context:
            raise PublishValidationError(
                "Current workfile is missing whole metadata about context.",
                "Missing context",
                (
                    "Current workfile is missing metadata about task."
                    " To fix this issue save the file using Workfiles tool."
                )
            )

        missing_keys = []
        for key in self.required_keys:
            value = workfile_context.get(key)
            if not value:
                missing_keys.append(key)

        if missing_keys:
            raise PublishXmlValidationError(
                self,
                "Current workfile is missing metadata about {}.".format(
                    ", ".join(missing_keys)
                ),
                formatting_data={
                    "missing_metadata": ", ".join(missing_keys)
                }
            )


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}")


def solution(n:int):
    while n > 99:
        r = n / 10
        l = n - (10 * r)
        n = 5 * l + r
        return (n - 7 * (n / 7)) == 0
print(solution(448))

# Hackerrank TuSimple

def printTable(n):
    pRow = [i + 1 for i in range(n)]
    i = 0
    while i < n:
        j = 0

        while j < n:
            space = len(str(pRow[j] * n)) - len(str(pRow[j] * (i + 1)))
            newStr = str(pRow[j] * (i + 1)) + " " + (" " * space)
            print(newStr,end="")
            j += 1
        print()
        i += 1
printTable(15)


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()


import sys
import time
import math
import numpy as np

# Constants
DEBUG = True

INF = 9999999

REAPER = 0
DESTROYER = 1
DOOF = 2
TANKER = 3
WRECK = 4
TAR_POOL = 5
OIL_POOL = 6

PLAYER_NUM = 3
AREA_RADIUS = 6000
REAPER_RADIUS = 400

# Class
class Reaper:
    def __init__(self, unit_id, player_id, mass,
                       radius, x, y, vx, vy, extra, extra2):
        self.player_id = player_id
        self.unit_id = unit_id
        self.mass = mass
        self.radius = radius
        self.x = x
        self.y = y
        self.vx = vx
        self.vy = vy
        self.extra = extra
        self.extra2 = extra2

class Destroyer:
    def __init__(self, unit_id, mass,
                       radius, x, y, vx, vy, extra, extra2):
        self.unit_id = unit_id
        self.mass = mass
        self.radius = radius
        self.x = x
        self.y = y
        self.vx = vx
        self.vy = vy
        self.extra = extra
        self.extra2 = extra2
        self.target = -1

class Doof:
    def __init__(self, unit_id, mass,
                       radius, x, y, vx, vy, extra, extra2):
        self.unit_id = unit_id
        self.mass = mass
        self.radius = radius
        self.x = x
        self.y = y
        self.vx = vx
        self.vy = vy
        self.extra = extra
        self.extra2 = extra2
        self.target = -1

class Tanker:
    def __init__(self, unit_id,
                       mass, radius, x, y, extra, extra2):
        self.unit_id = unit_id
        self.mass = mass
        self.radius = radius
        self.x = x
        self.y = y
        self.extra = extra
        self.extra2 = extra2

class Wreck:
    def __init__(self, unit_id,
                       mass, radius, x, y, extra, extra2):
        self.unit_id = unit_id
        self.mass = mass
        self.radius = radius
        self.x = x
        self.y = y
        self.extra = extra
        self.extra2 = extra2

class TarPool:
    def __init__(self, unit_id,
                       mass, radius, x, y, extra, extra2):
        self.unit_id = unit_id
        self.mass = mass
        self.radius = radius
        self.x = x
        self.y = y
        self.extra = extra
        self.extra2 = extra2

class OilPool:
    def __init__(self, unit_id,
                       mass, radius, x, y, extra, extra2):
        self.unit_id = unit_id
        self.mass = mass
        self.radius = radius
        self.x = x
        self.y = y
        self.extra = extra
        self.extra2 = extra2

# Global
score = []
rage = []
my_reaper = None
op_reaper = []
my_destroyer = None
op_destroyer = []
my_doof = None
op_doof = []
tanker = []
wreck = []
tar_pool = []
oil_pool = []

# Function
def game_turn_input():
    global score, rage
    global my_reaper, op_reaper, my_destroyer, op_destroyer, my_doof, op_doof
    global tanker, wreck, tar_pool, oil_pool

    score = [None for x in range(PLAYER_NUM)]
    for i in range(PLAYER_NUM):
        score[i] = int(input())
        if DEBUG:
            sys.stderr.write(str(score[i]) + "\n")

    rage = [None for x in range(PLAYER_NUM)]
    for i in range(PLAYER_NUM):
        rage[i] = int(input())
        if DEBUG:
            sys.stderr.write(str(rage[i]) + "\n")

    my_reaper = None
    op_reaper = []
    my_destroyer = None
    op_destroyer = []
    my_doof = None
    op_doof = []
    tanker = []
    wreck = []
    tar_pool = []
    oil_pool = []

    unit_count = int(input())
    if DEBUG:
        sys.stderr.write(str(unit_count) + "\n")

    for i in range(unit_count):
        unit_id, unit_type, player_id, mass, radius, x, y, vx, vy, extra, extra2 = input().split()
        if DEBUG:
            sys.stderr.write(unit_id + " " + unit_type + " " + player_id + " "
                           + mass + " " + radius + " " + x + " " + y + " "
                           + vx + " " + vy + " " + extra + " " + extra2 + "\n")

        unit_id = int(unit_id)
        unit_type = int(unit_type)
        player_id = int(player_id)
        mass = float(mass)
        radius = int(radius)
        x = int(x)
        y = int(y)
        vx = int(vx)
        vy = int(vy)
        extra = int(extra)
        extra2 = int(extra2)

        if unit_type == REAPER:
            if player_id == 0:
                my_reaper = Reaper(unit_id, player_id, mass, radius, x, y, vx, vy, extra, extra2)
            else:
                op_reaper.append(Reaper(unit_id, player_id, mass, radius,
                    x, y, vx, vy, extra, extra2))

        elif unit_type == DESTROYER:
            if player_id == 0:
                my_destroyer = Destroyer(unit_id, mass, radius, x, y, vx, vy, extra, extra2)
            else:
                op_destroyer.append(Destroyer(unit_id, mass, radius,
                    x, y, vx, vy, extra, extra2))

        elif unit_type == DOOF:
            if player_id == 0:
                my_doof = Doof(unit_id, mass, radius, x, y, vx, vy, extra, extra2)
            else:
                op_doof.append(Doof(unit_id, mass, radius,
                    x, y, vx, vy, extra, extra2))

        elif unit_type == TANKER:
            tanker.append(Tanker(unit_id, mass, radius, x, y, extra, extra2))

        elif unit_type == WRECK:
            wreck.append(Wreck(unit_id, mass, radius, x, y, extra, extra2))

        elif unit_type == TAR_POOL:
            tar_pool.append(TarPool(unit_id, mass, radius, x, y, extra, extra2))

        elif unit_type == OIL_POOL:
            oil_pool.append(OilPool(unit_id, mass, radius, x, y, extra, extra2))

def dist2D(x1, y1, x2, y2):
    return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)

def sigmoid(x):
    return 1 / (1 + math.exp(-x))

def speed(vx, vy):
    return math.sqrt(vx**2 + vy**2)

def think_reaper():
    global rage

    start_time = time.time()

    dist_min = INF

    nx = -1
    ny = -1
    throttle = 100

    for w in wreck:
        dist = dist2D(my_reaper.x, my_reaper.y, w.x, w.y)
        # 既に相手のReaperがいたら諦める。
        for r in op_reaper:
            dist_op = dist2D(r.x, r.y, w.x, w.y)
            if dist > w.radius and dist_op < w.radius:
                break
        else:
            if dist < dist_min:
                dist_min = dist
                nx = w.x
                ny = w.y
                xx = my_reaper.x + my_reaper.vx / 0.2
                yy = my_reaper.y + my_reaper.vy / 0.2
                if dist2D(xx, yy, w.x, w.y) < w.radius:
                    throttle = 1
                else:
                    dist_2 = dist2D(xx, yy, w.x, w.y)
                    throttle = int(300 * sigmoid(dist_2))

    # wreckがなかったら、Destroyerが一番近いTankerに近寄っておく。
    if dist_min == INF:
        nx = my_destroyer.x
        ny = my_destroyer.y
        xx = my_reaper.x + my_reaper.vx / 0.2
        yy = my_reaper.y + my_reaper.vy / 0.2

        for d in [my_destroyer] + op_destroyer:
            for t in tanker:
                dist = dist2D(d.x, d.y, t.x, t.y)
                if dist < dist_min:
                    dist = dist_min
                    nx = t.x
                    ny = t.y
                if dist2D(xx, yy, d.x, d.y) < d.radius:
                    throttle = 0
                else:
                    dist_2 = dist2D(xx, yy, t.x, t.y)
                    throttle = int(300 * sigmoid(dist_2))

    elapsed = time.time() - start_time

    print(nx, ny, throttle, elapsed)

def think_destroyer():
    global rage

    start_time = time.time()

    # 相手のWreckを取られそうだったら、Grenadeを投げる。
    if rage[0] >= 60:
        for w in wreck:
            dist = dist2D(my_destroyer.x, my_destroyer.y, w.x, w.y)
            if dist < 2000:
                my_dist = dist2D(my_reaper.x, my_reaper.y, w.x, w.y)
                # 相手がこのWreckから水を得そうならば、Grenadeを投擲。
                for r in op_reaper:
                    dx = w.x - r.x
                    dy = w.y - r.y
                    dot = dx * r.vx + dy * r.vy
                    if dot > 0:
                        op_dist = dist2D(w.x, w.y, r.x, r.y)
                        if op_dist < my_dist and op_dist < 3000:
                            print("SKILL", w.x, w.y)
                            rage[0] -= 60
                            return
    dist_min = INF

    nx = -1
    ny = -1

    # 前ターンに狙ったものがあれば、それを狙う。
    for t in tanker:
        if t.unit_id == my_destroyer.target:
            nx = t.x
            ny = t.x
            break
    # 一番近いものを壊せばいいわけではない。相手に取られそうな場合には破壊しない。
    else:
        for t in tanker:
            dist = dist2D(my_destroyer.x, my_destroyer.y, t.x, t.y)
            my_dist = dist2D(my_reaper.x, my_reaper.y, t.x, t.y)
            op_dist_min = INF
            for r in op_reaper:
                dist_op = dist2D(r.x, r.y, t.x, t.y)
                if dist_op < op_dist_min:
                    op_dist_min = dist_op

            if dist < dist_min and my_dist < op_dist_min:
                dist_min = dist
                nx = t.x
                ny = t.y
                my_destroyer.target = t.unit_id

    elapsed = time.time() - start_time
    print(nx, ny, 300, elapsed)

def think_doof():
    global rage

    start_time = time.time()

    # とりあえず最も近い相手のReaperにフルスロットルで近づいてみる。
    # 行きたいところに先回りして、邪魔をする。

    # Wreckが取られそうならOil Poolを作成。
    # ToDo: ほかのUnitがrage を使用していたら、rageが足りなくなるかもしれないことに注意。
    if rage[0] >= 30:
        # 今自分のDoofがWreckにいるか
        for w in wreck:
            dist = dist2D(my_doof.x, my_doof.y, w.x, w.y)
            if dist < 2000:
                my_dist = dist2D(my_reaper.x, my_reaper.y, w.x, w.y)
                # 相手がこのWreckから水を得そうならば、Oil Poolを作成
                # 水を得そうとは、
                #  - ある程度距離が近い (ToDo)
                #  - Wreckに向かっている
                for r in op_reaper:
                    dx = w.x - r.x
                    dy = w.y - r.y
                    dot = dx * r.vx + dy * r.vy
                    if dot > 0:
                        op_dist = dist2D(w.x, w.y, r.x, r.y)
                        if op_dist < my_dist and op_dist < 3000:
                            print("SKILL", w.x, w.y)
                            rage[0] -= 30
                            return

    score_max_op_player = 1 if score[1] > score[2] else 2
    dist_min = INF
    nx = -1
    ny = -1
    throttle = 100

    for r in op_reaper:
        if r.player_id == score_max_op_player:
            dist = dist2D(my_doof.x, my_doof.y, r.x, r.y)
            if dist < dist_min:
                dist_min = dist
                nx = r.x
                ny = r.y
                throttle = int(300 * sigmoid(dist_min))

    elapsed = time.time() - start_time
    print(nx, ny, throttle, elapsed)

if __name__ == "__main__":
    # main loop
    while True:
        game_turn_input()
        think_reaper()
        think_destroyer()
        think_doof()


import time

from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtGui import QPainter, QPen
from PyQt5.QtWidgets import (QMainWindow, QAction)

from childFuction import *
from DDA_Line import DDALine
from Breseham_Line import BresehamLine
from circle import Circle
from ellipse import Ellipse

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        # 接受信息
        self.position = None
        # 输出的所有点
        self.points = []
        # 将要输出到屏幕上的点
        self.outPoints = []
        # 设置标志位此时达到不同算法的切换
        self.signal = 0
        # 表示此时将要加入到输出队列的下一个点
        self.index = 0
        self.initUI()
        # 直接在主函数中初始化函数

    def initUI(self):
        menubar = self.menuBar()
        fileMenu = menubar.addMenu("Function")

        self.statusBar()
        # 增加第一个菜单栏下的工具
        LineAct = QAction(QIcon(""), "Line", self)
        LineAct.setStatusTip('')
        LineAct.triggered.connect(self.childWindow_one)

        fileMenu.addAction(LineAct)
        # 增加第二个菜单栏下的工具
        BresenhamAct = QAction(QIcon(""), "Bresenham Line", self)
        BresenhamAct.setStatusTip("")
        BresenhamAct.triggered.connect(self.childWindow_two)

        fileMenu.addAction(BresenhamAct)

        CircleAct = QAction(QIcon(""), "circle", self)
        CircleAct.setStatusTip("")
        CircleAct.triggered.connect(self.childWindow_three)

        fileMenu.addAction(CircleAct)

        EllipseAct = QAction(QIcon(""), "Ellipse", self)
        EllipseAct.setStatusTip("")
        EllipseAct.triggered.connect(self.childWindow_four)

        fileMenu.addAction(EllipseAct)

        # 鼠标控制
        # self.mouseControl()
        # 鼠标控制结束

        # 刷新控制
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.repaint)
        self.timer.start(10)
        # 刷新控制结束，控制秒数为1秒，上面的单位是毫秒计时

        self.resize(800, 600)
        self.center()
        self.setWindowTitle("draw the graph")

    # def mouseControl(self):
    #     x = 0
    #     y = 0
    #
    #     self.text = "x: {0},  y: {1}".format(x, y)
    #     self.label = QLabel(self.text, self)
    #     self.label.move(-100, -100)
    #     self.setMouseTracking(True)
    #
    # def mouseMoveEvent(self, e):
    #     重写鼠标事件
    #     size = self.size()
    # x = e.x() - size.width() / 2
    # y = size.height() / 2 - e.y()
    #
    # text = "x: {0},  y: {1}".format(x, y)
    # self.statusBar().showMessage(text)

    def paintEvent(self, event):
        # 重写画笔事件
        qp = QPainter()
        qp.begin(self)
        self.drawCoordinate(qp)
        if self.signal == 1:
            self.drawDDALine(qp)
        if self.signal == 2:
            self.drawBresehamLine(qp)
        if self.signal == 3:
            self.drawCircle(qp)
        if self.signal == 4:
            self.drawEllipse(qp)

        qp.end()

    def center(self):
        # 使屏幕居中
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    # 在此处改主窗口事件
    def childWindow_one(self):
        # 子窗口事件，同时连接了信号槽
        self.childOne = childWindowOne()
        self.childOne.show()

        self.position = None
        self.points = None
        self.signal = 1
        self.outPoints = []
        self.index = 0

        self.childOne._signal.connect(self.getMessageOne)

    def childWindow_two(self):
        self.childTwo = childWindowTwo()
        self.childTwo.show()

        self.position = None
        self.points = None
        self.signal = 2
        self.outPoints = []
        self.index = 0

        self.childTwo._signal.connect(self.getMessageTwo)

    def childWindow_three(self):
        self.childThree = childWindowThree()
        self.childThree.show()

        self.position = None
        self.points = None
        self.signal = 3
        self.outPoints = []
        self.index = 0

        self.childThree._signal.connect(self.getMessageThree)

    def childWindow_four(self):
        self.childFour = childWindowFour()
        self.childFour.show()

        self.position = None
        self.points = None
        self.signal = 4
        self.outPoints = []
        self.index = 0

        self.childFour._signal.connect(self.getMessageFour)

    # 在此处定义接受信息的信号槽
    def getMessageOne(self, x0, y0, xEnd, yEnd):
        # 加入第一个事件的事件槽
        self.position = x0, y0, xEnd, yEnd

    def getMessageTwo(self, x0, y0, xEnd, yEnd):
        self.position = x0, y0, xEnd, yEnd

    def getMessageThree(self, x, y, r):
        self.position = x, y, r

    def getMessageFour(self, x, y, rx, ry):
        self.position = x, y, rx, ry

    def drawCoordinate(self, qp):
        pen = QPen(Qt.black, 1, Qt.SolidLine)
        qp.setPen(pen)
        size = self.size()
        centerPoint = (size.width() / 2, size.height() / 2)
        # 坐标轴的线
        qp.drawLine(0, size.height() / 2, size.width(), size.height() / 2)
        qp.drawLine(size.width() / 2, 0, size.width() / 2, size.height())

        # 坐标轴的小轴和字
        pen = QPen(Qt.black, 1, Qt.SolidLine)
        qp.setFont(QFont('Courier New', 5))
        qp.setPen(pen)
        for xInc in range(10, int(centerPoint[0]), 10):
            x = centerPoint[0]
            y = centerPoint[1]

            if xInc % 100 == 0:
                qp.drawText(x + xInc, y + 10, str(xInc))
                qp.drawText(x - xInc, y + 10, str(xInc))
                qp.drawLine(x + xInc, y, x + xInc, y - 10)
                qp.drawLine(x - xInc, y, x - xInc, y - 10)

            qp.drawLine(x + xInc, y, x + xInc, y - 5)
            qp.drawLine(x - xInc, y, x - xInc, y - 5)

        for yInc in range(10, int(centerPoint[1]), 10):
            x = centerPoint[0]
            y = centerPoint[1]
            if yInc % 100 == 0:
                qp.drawText(x - 20, y + yInc, str(yInc))
                qp.drawText(x - 20, y - yInc, str(yInc))
                qp.drawLine(x, y + yInc, x + 10, y + yInc)
                qp.drawLine(x, y - yInc, x + 10, y - yInc)

            qp.drawLine(x, y + yInc, x + 5, y + yInc)
            qp.drawLine(x, y - yInc, x + 5, y - yInc)

    def drawDDALine(self, qp):
        pen = QPen(Qt.black, 2, Qt.SolidLine)
        qp.setPen(pen)
        size = self.size()

        if self.position is not None:
            self.points = DDALine(self.position, size)
            if self.index < len(self.points):
                self.outPoints.append(self.points[self.index])
                self.index += 1
            # 用index调控每一次要输出的数目
        for outPoint in self.outPoints:
            qp.drawPoint(outPoint[0], outPoint[1])
            # self.position = None

    def drawBresehamLine(self, qp):
        pen = QPen(Qt.black, 2, Qt.SolidLine)
        qp.setPen(pen)
        size = self.size()

        if self.position is not None:
            self.points = BresehamLine(self.position, size)
            if self.index < len(self.points):
                self.outPoints.append(self.points[self.index])
                self.index += 1
            # 用index调控每一次要输出的数目
        for outPoint in self.outPoints:
            qp.drawPoint(outPoint[0], outPoint[1])
            # self.position = None

    def drawCircle(self, qp):
        pen = QPen(Qt.black, 2, Qt.SolidLine)
        qp.setPen(pen)
        size = self.size()

        if self.position is not None:
            self.points = Circle(self.position, size)
            if self.index < len(self.points):
                self.outPoints.append(self.points[self.index])
                self.index += 1
            # 用index调控每一次要输出的数目
        for outPoint in self.outPoints:
            qp.drawPoint(outPoint[0], outPoint[1])
            # self.position = None

    def drawEllipse(self, qp):
        pen = QPen(Qt.black, 2, Qt.SolidLine)
        qp.setPen(pen)
        size = self.size()

        if self.position is not None:
            self.points = Ellipse(self.position, size)
            if self.index < len(self.points):
                self.outPoints.append(self.points[self.index])
                self.index += 1
            # 用index调控每一次要输出的数目
        for outPoint in self.outPoints:
            qp.drawPoint(outPoint[0], outPoint[1])
            # self.position = None

# 下面定义为外置代码


'''
题目描述
每个句子由多个单词组成，句子中的每个单词的长度都可能不一样，我们假设每个单词的长度Ni为该单词的重量，你需要做的就是给出整个句子的平均重量V。

解答要求
时间限制：1000ms, 内存限制：64MB
输入
输入只有一行，包含一个字符串S(长度不会超过100)，代表整个句子，句子中只包含大小写的英文字母，每个单词之间有一个空格。

输出
输出句子S的平均重量V(四舍五入保留两位小数)。

样例
输入样例 1

Who Love Solo
输出样例 1

3.67
'''

while True:
    try:
        s = input().split()
        print('{:.2f}'.format(sum(map(len, s))/len(s)))
    except:
        break


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
        # проверка


"""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 nuke
from openpype.hosts.nuke.api import (
    NukeCreator,
    NukeCreatorError,
    maintained_selection
)

class CreateCamera(NukeCreator):
    """Add Publishable Camera"""

    identifier = "create_camera"
    label = "Camera (3d)"
    family = "camera"
    icon = "camera"

    # plugin attributes
    node_color = "0xff9100ff"

    def create_instance_node(
        self,
        node_name,
        knobs=None,
        parent=None,
        node_type=None
    ):
        with maintained_selection():
            if self.selected_nodes:
                node = self.selected_nodes[0]
                if node.Class() != "Camera3":
                    raise NukeCreatorError(
                        "Creator error: Select only camera node type")
                created_node = self.selected_nodes[0]
            else:
                created_node = nuke.createNode("Camera2")

            created_node["tile_color"].setValue(
                int(self.node_color, 16))

            created_node["name"].setValue(node_name)

            return created_node

    def create(self, subset_name, instance_data, pre_create_data):
        # make sure subset name is unique
        self.check_existing_subset(subset_name)

        instance = super(CreateCamera, self).create(
            subset_name,
            instance_data,
            pre_create_data
        )

        return instance

    def set_selected_nodes(self, pre_create_data):
        if pre_create_data.get("use_selection"):
            self.selected_nodes = nuke.selectedNodes()
            if self.selected_nodes == []:
                raise NukeCreatorError(
                    "Creator error: No active selection")
            elif len(self.selected_nodes) > 1:
                raise NukeCreatorError(
                    "Creator error: Select only one camera node")
        else:
            self.selected_nodes = []