import json
import logging
from concurrent.futures import ThreadPoolExecutor
import os
import consts as consts
from gcp.resources.resource_handler import ResourceHandler
from google.cloud import asset_v1
from port.client import PortClient
import jq

logger = logging.getLogger(__name__)

class ResourcesHandler:
    def __init__(self, config, context):
        self.config = config
        self.context = context
        self.region = os.environ.get('FUNCTION_REGION')
        self.project_id = context.resource['name'].split('/')[1]
        self.user_id = f"accountid/{self.project_id} region/{self.region}"
        port_client_id = self.config.get('port_client_id') if self.config.get('keep_cred') else self.config.pop(
            'port_client_id')
        port_client_secret = self.config.get('port_client_secret') if self.config.get('keep_cred') else self.config.pop(
            'port_client_secret')
        self.port_client = PortClient(port_client_id, port_client_secret,
                                      user_agent=f"{consts.PORT_GCP_EXPORTER_NAME}/{consts.GCP_EXPORTER_VERSION} ({self.user_id})",
                                      api_url=self.config.get('port_api_url', consts.PORT_API_URL))
        self.event = self.config.get('event')
        self.bucket_name = self.config['bucket_name']
        self.gcp_entities = set(self.config.get('gcp_entities', []))
        self.resources_config = self.config['resources']
        self.skip_delete = self.config.get('skip_delete', False)

    def handle(self):
        if self.event and self.event.get('data') :  # Single events from SQS
            logger.info("Handle events from GCP Pub/Sub")
            for record in self.event.get('data'):
                try:
                    print(record)
                    self._handle_single_resource(record)
                except Exception as e:
                    logger.error(f"Failed to handle event: {self.event}, error: {e}")
            return

        logger.info("Starting upsert of GCP resources to Port")

        self._upsert_resources()
        logger.info("Done upsert of GCP resources to Port")

        # if not self.skip_delete:
        #     logger.info("Starting delete process of stale resources from Port")
        #     self._delete_stale_resources()
        #     logger.info("Done deleting stale resources from Port")

        logger.info("Done handling your resources")

    def _upsert_resources(self):
        for resource in self.resources_config:
            resource_handler = ResourceHandler(resource, self.port_client, self.region, self.project_id)
            result = resource_handler.handle()
            self.gcp_entities.update(result.get('gcp_entities', set()))

            self.skip_delete = result.get('skip_delete', False) if not self.skip_delete else self.skip_delete

    # Event-based synchronisation feature, not done yet
    # def _handle_single_resource(self, resource):
    #     assert 'identifier' in resource, "Event must include 'identifier'"
    #     assert 'region' in resource, "Event must include 'region'"
    #     region = jq.first(resource['region'], resource)
    #     identifier = jq.first(resource['identifier'], resource)
    #
    #     action_type = str(jq.first(resource.get('action', '"upsert"'), resource)).lower()
    #     assert action_type in ['upsert', 'delete'], f"Action should be one of 'upsert', 'delete'"
    #
    #     resource_config = [resource_config for resource_config in self.resources_config
    #                         if resource_config['kind'] == resource['resource_type'] and resource_config['identifier'] == identifier]
    #     assert resource_config, f"Resource config not found for kind: {resource['resource_type']}"
    #
    #     project_scope = f'projects/{self.project_id}'
    #     gcp_request = {"scope": project_scope,
    #                    "query": f'resourceProperties.id={identifier}',
    #                    "asset_types": [self.kind],
    #                    "page_size": consts.GOOGLE_API_PAGE_SIZE}
    #
    #     try:
    #         gcp_cloudassets_client = asset_v1.AssetServiceClient()
    #         response = gcp_cloudassets_client.search_all_resources(request=gcp_request)
    #     except Exception as e:
    #         logger.error(f"Failed to extract or transform resource: {identifier}, kind: {self.kind}, error: {e}")
    #
    #     for resource in response:
    #         resource_handler = ResourceHandler(resource_config, self.port_client, self.region, self.project_id)
    #         resource_handler.handle_single_resource_item(resource, identifier, action_type)

    # def _delete_stale_resources(self):
    #     query = {"combinator": "and",
    #              "rules": [{"property": "$datasource", "operator": "contains", "value": consts.PORT_GCP_EXPORTER_NAME},
    #                        {"property": "$datasource", "operator": "contains", "value": self.user_id}]}
    #     port_entities = self.port_client.search_entities(query)
    #
    #     with ThreadPoolExecutor(max_workers=consts.MAX_DELETE_WORKERS) as executor:
    #         executor.map(self.port_client.delete_entity,
    #                      [entity for entity in port_entities
    #                       if f"{entity.get('blueprint')};{entity.get('identifier')}" not in self.gcp_entities])


import discord, os, asyncio, random
from discord.ext import commands
from key import DISCORD_API_TOKEN

intents = discord.Intents.default()
intents.message_content = True
client = commands.Bot(command_prefix="!", intents=discord.Intents.all())

@client.event
async def on_ready():
    await client.tree.sync()
    print(f"{client.user.name} is connected!")

@client.command()
async def teste(ctx):
    await ctx.send("teste")

@client.event
async def on_message(msg):

    sanchez = 240872587566120971
    if msg.author.id == sanchez:
        f = open(f"database/Obs/{msg.author.name}.txt", "a")
        f.write(f"{msg.content}\n")
    else:
        pass

async def load():
    for filename in os.listdir('./commands'):
        if filename.endswith('.py'):
            await client.load_extension(f'commands.{filename[:-3]}')
            print(f'{filename} is ready!')

async def main():
    async with client:
        await load()
        await client.start(DISCORD_API_TOKEN)

asyncio.run(main())


from src.eufyhome.method.Base_Page import BasePage
from src.config.config import GlobalVar
global Page

"""
app登陆注册页面操作
"""

class TimeZonePage(BasePage):

    def __init__(self, driver):
        super().__init__(driver)
        if self.platform == GlobalVar.IOS:
            from src.eufyhome.ios.app.TimeZoneActivity import TimeZoneActivity
        else:
            from src.eufyhome.android.app.TimeZoneActivity import TimeZoneActivity
        global Page
        Page = TimeZoneActivity()

    def move_top(self):
        """
        滑到顶部
        :return:
        """
        for i in range(20):
            if self.wait_exist(Page.time_one, 5):
                break
            else:
                self.swipe_by_element('down', 0.2, 0.8, 0.5, None, 1000)

    def read_timezone1(self):
        """
        读取第一个时区的名称
        :return:
        """
        return self.get_text(Page.time_one)

    def read_time_list(self):
        """
        读取时区列表
        :return:
        """
        if self.platform == 'ios':
            # ios列表的时区名字位置会变化，无法准确读取名称，后期优化
            return self.get_elements(Page.timezone_item)
        timezone_list = set()
        for i in range(20):
            flag = False
            els = self.get_elements(Page.timezone_item)
            for el in els:
                text = el.text
                if text not in timezone_list:
                    flag = True
                    timezone_list.add(text)
            if flag:
                self.swipe_by_element('up', 0.75, 0.2, 0.5, None, 2250)
            else:
                break
        return timezone_list

    def is_beijing(self):
        """
        当前时区是否为北京
        :return:
        """
        if self.platform == 'ios':
            flag = self.compare_img(('xpath', '//XCUIElementTypeImage[@name="common_icon_select"]/..'), 'beijing', 3)
        else:
            flag = self.wait_exist(Page.is_beijing)
        return flag

    def is_hongkong(self):
        """
        当前时区是否为香港
        :return:
        """
        if self.platform == 'ios':
            flag = self.compare_img(('xpath', '//XCUIElementTypeImage[@name="common_icon_select"]/..'), 'hongkong', 3)
        else:
            flag = self.wait_exist(Page.is_hongkong)
        return flag

    def select_timezone(self, timezone):
        """
        选择时区
        :param timezone:
        :return:
        """
        # if self.platform == 'ios':
        #     self.swipe_by_element('down', 0.8, 0.5, 0.5, None, 2000)
        if timezone == 'beijing':
            self.tap_element(Page.beijing)
        elif timezone == 'hongkong':
            self.tap_element(Page.hongkong)
        else:
            raise Exception(timezone+'暂不支持')
        self.loading()

    def back_system(self):
        """
        返回
        :return:
        """
        self.tap_element(Page.back_system)


from flask import request, current_app, jsonify
from flask_restx import Resource, Api, Namespace, fields
from flask_jwt_extended import *
from sqlalchemy import text
import time

Admin = Namespace(
    name='Admin',
    description="관리자 API"
)

#CORS(app)
#CORS(app, resources={r'*': {'origins': '*'}})

@Admin.route('/change_permission')
class Series_List_All(Resource):
    def post(self):
        """글 게시를 허용/비허용."""
        # 1. 시리즈 id를 parameter로 받아옴.
        author_id = int(request.form['author_id'])
        writing_id = int(request.form['writing_id'])
        permission = int(request.form['permission'])

        # 2. 시리즈 id에 해당하는 모든 글 정보를 DB에서 가져옴.
        #    이 때, permission은 0(TRUE)여야 함. permission이 1인 글은 아직 게시가 허락되지 않은 것.
        current_app.database.execute(text("""
                                                            UPDATE Writing SET permission = :permission WHERE id = :writing_id ;
                                                        """), {
            'writing_id': writing_id,
            'permission': permission
        })

        writingnumdata = current_app.database.execute(text("""
                                                            Select Count(*) From Writing Where series_id IN (SELECT series_id FROM Writing WHERE id = :writing_id AND permission = :permission )
                                                        """), {
            'writing_id': writing_id,
            'permission': 1
        })

        # 유저가 글 등록하고 수락 시 작가로 변환
        if permission == 1:
            current_app.database.execute(text("""
                                                            UPDATE User SET is_author = 1 WHERE id = :author_id ;
                                                        """), {
                'author_id': author_id
            })
            # 시리즈의 글 전체 갯수를 세서 writing_num 업데이트
            current_app.database.execute(text("""
                                                            UPDATE Series SET writing_num = :writing_num WHERE id IN (SELECT series_id FROM Writing WHERE id = :writing_id )
                                                        """), {
                'writing_id': writing_id,
                'writing_num': writingnumdata['Count(*)']+1
            })
        else:
            current_app.database.execute(text("""
                                                            UPDATE Series SET writing_num = :writing_num WHERE id IN (SELECT series_id FROM Writing WHERE id = :writing_id )
                                                        """), {
                'writing_id': writing_id,
                'writing_num': writingnumdata['Count(*)']-1
            })

        return jsonify({'result': 'success'})

@Admin.route('/all')
class Series_List_Allfd(Resource):
    def post(self):
        # 1. 시리즈 id를 parameter로 받아옴.
        permission = int(request.form['permission'])

        writing_list = current_app.database.execute(text("""
                                        SELECT * FROM Writing WHERE permission = :permission ;
                                    """), {'permission':permission}).fetchall()
# 3. 등록된 글이 있다면 모든 글의 정보를 리턴.
        if len(writing_list) > 0:
            d_writing_list = []
            for writing in writing_list:
                # permission 값을 가지고 업로드 여부를 체크함.
                d_writing = dict(writing)

                if d_writing['permission'] == 0:
                    d_writing['is_uploaded'] = False
                else:
                    d_writing['is_uploaded'] = True

                # series_id -> series_name
                d_writing['series_name'] = current_app.database.execute(text("""
                                                                                SELECT title FROM Series WHERE id = :series_id;
                                                                                """), {
                    'series_id': d_writing['series_id']
                }).fetchone()['title']

                d_writing_list.append(d_writing)

            return jsonify([{
                    'id': writing['id'],
                    'series_id': writing['series_id'],
                    'series_name': writing['series_name'],
                    'author_id': writing['author_id'],
                    'is_uploaded': writing['is_uploaded'],
                    'episode_num': writing['episode_num'],
                    'title': writing['title'],
                    'image': writing['image'],
                    'date': writing['date'],
                    'comment_num': writing['comment_num'],
                    'hits': writing['hits']
                } for writing in d_writing_list])
        else:
            return jsonify([])


import random

def is_sorrted(values):
    for index in range(len(values) - 1):
        if values[index] > values[index + 1]:
            return False

    return True

def bogo_sort(values):
    attempts = 0

    while not is_sorrted(values):
        random.shuffle(values)
        attempts += 1

    print(attempts)
    return values

print(bogo_sort([54,62,93,17,77,55,20]))


import sys
import os
from github import Github
from dotenv import load_dotenv
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

load_dotenv()

path = os.getenv("FILEPATH")
github_token = os.getenv('GITHUB_TOKEN')

def create():
    folderName = str(sys.argv[1])
    os.makedirs(path + str(folderName))
    user = Github(github_token).get_user()
    user.create_repo(folderName)
    logger.info("Succesfully created repository {}".format(folderName))

if __name__ == "__main__":
    create()


import numpy as np
import pandas as pd
import pydeck
import streamlit as st
from converter import Converter
from load_data import load_coordinates_csv, load_real_estate_csv

REAL_ESTATE_CSV_FILE_NAME = "data/マンション情報_札幌.csv"
COORDINATES_CSV_FILE_NAME = "data/位置情報_札幌.csv"

df_pos = load_coordinates_csv(COORDINATES_CSV_FILE_NAME)
st.write('位置', df_pos)

df_rs = load_real_estate_csv(REAL_ESTATE_CSV_FILE_NAME)
st.write('マンション情報', df_rs)

df_rs2020 = df_rs[(df_rs['取引時点'] >= 2010)].copy()
df_rs2020['_70平米換算取引価格'] = (df_rs2020['取引価格（総額）'] * (70 / df_rs2020['面積（㎡）'])).astype(np.int64)

df_area_groups = df_rs2020[['地区名', '_70平米換算取引価格']].groupby('地区名')
st.write('Groups')
df_result = df_area_groups.mean().astype(np.int64)

for index, row in df_result.iterrows():
    #st.write(index, Converter.replace_area_number_to_kansuji(index))
    df_pos_area = df_pos[
        df_pos["大字町丁目名"].str.contains(Converter.replace_area_number_to_kansuji(index))]
    #st.write(df_pos_area)
    #st.write(index, Converter.to_hankaku(index), Converter.replace_area_number_to_kansuji(index), df_pos_area)
    #st.write(df_pos_area[["緯度", "経度"]].mean())
    lat, lon = df_pos_area[["緯度", "経度"]].mean()
    df_result.at[index, '緯度'] = lat
    df_result.at[index, '経度'] = lon
    #st.write(lat, lon)

st.pydeck_chart(pydeck.Deck(
    map_style='mapbox://styles/mapbox/streets-v11',
    width=1200,
    height=800,
    initial_view_state=pydeck.ViewState(
        latitude=43.05,
        longitude=141.35,
        zoom=10.5,
        pitch=50,
    ),
    layers=[
        pydeck.Layer(
            'HeatmapLayer',
            data=df_result,
            get_position='[経度, 緯度]',
            get_weight='_70平米換算取引価格',
            opacity=0.8,
            radius_pixels=70,
            elevation_scale=50,
            elevation_range=[0, 1000],
            threshold=0.03
        )
    ],
))

st.pydeck_chart(pydeck.Deck(
    map_style='mapbox://styles/mapbox/streets-v11',
    initial_view_state=pydeck.ViewState(
        latitude=43.05,
        longitude=141.35,
        zoom=10.5,
        pitch=50,
    ),
    layers=[
        pydeck.Layer(
            'GridLayer',
            data=df_result,
            get_position='[経度, 緯度]',
            get_elevation_weight='_70平米換算取引価格',
            get_fill_color=[255, 0, 0, 255],
            cell_size=500,
            elevation_scale=20,
            elevation_range=[0, 100],
            #pickable=True,
            extruded=True,
        ),
    ],
))


from src.backend.PluginManager.ActionBase import ActionBase

# Import gtk modules
import gi
gi.require_version("Gtk", "4.0")
gi.require_version("Adw", "1")
from gi.repository import Gtk, Adw

from PIL import Image, ImageEnhance
import os
import math

class MediaAction(ActionBase):
    CONTROLS_KEY_IMAGE = True
    def __init__(self, deck_controller, page, coords):
        super().__init__(deck_controller=deck_controller, page=page, coords=coords)

        self.current_status = None

    def on_key_down(self):
        pass

    def on_key_up(self):
        pass

    def on_tick(self):
        pass

    def get_config_rows(self) -> "list[Adw.PreferencesRow]":
        # Init ui elements
        self.player_model = Gtk.StringList()
        self.player_selector = Adw.ComboRow(model=self.player_model, title="Bind to player:", subtitle="Specify the player to controll")
        self.player_selector.set_enable_search(True) #TODO: Implement

        self.label_toggle = Adw.SwitchRow(title="Show name of playing song", subtitle="Show the name of the currently playing song")
        self.thumbnail_toggle = Adw.SwitchRow(title="Show thumbnail of playing song", subtitle="Show the thumbnail of the currently playing song")

        self.load_config_defaults()

        self.player_selector.connect("notify::selected-item", self.on_change_player)
        self.label_toggle.connect("notify::active", self.on_toggle_label)
        self.thumbnail_toggle.connect("notify::active", self.on_toggle_thumbnail)

        return [self.player_selector, self.label_toggle, self.thumbnail_toggle]

    ## Custom methods
    def load_config_defaults(self):
        settings = self.get_settings()
        if settings == None:
            return

        show_label = settings.setdefault("show_label", True)
        show_thumbnail = settings.setdefault("show_thumbnail", True)

        # Update ui
        self.label_toggle.set_active(show_label)
        self.thumbnail_toggle.set_active(show_thumbnail)
        self.update_player_selector()

    def update_player_selector(self):
        # Clear the model
        for i in range(self.player_model.get_n_items()):
            self.player_model.remove(0)

        players = self.PLUGIN_BASE.mc.get_player_names(remove_duplicates=True)

        self.player_model.append("All Players")

        for player in players:
            self.player_model.append(player)

        # Add from settings if not already in the model
        if self.get_player_name() is not None:
            if self.get_player_name() not in players:
                self.player_model.append(self.get_player_name())

        # Select from settings
        if self.get_player_name() is not None:
            position = 0
            for i in range(self.player_model.get_n_items()):
                item = self.player_model.get_item(i).get_string()
                n = self.get_player_name()
                if self.player_model.get_item(i).get_string() == self.get_player_name():
                    position = i
                    break
            self.player_selector.set_selected(position)

    def on_change_player(self, combo, *args):
        settings = self.get_settings()
        if combo.get_selected_item().get_string() == "All Players":
            del settings["player_name"]
        else:
            settings["player_name"] = combo.get_selected_item().get_string()
        self.set_settings(settings)

    def get_player_name(self):
        settings = self.get_settings()
        if settings is not None:
            return settings.get("player_name")

    def show_title(self, reload_key = True) -> bool:
        if self.get_settings() == None:
            return False
        title = self.PLUGIN_BASE.mc.title(self.get_player_name())
        if self.get_settings().setdefault("show_label", True) and title is not None:
            label = None
            if isinstance(title, list):
                if len(title) > 0:
                    label = title[0]
                    # margins = [5, 0, 5, 10]
            if isinstance(title, str):
                if len(title) > 0:
                    label = title
                    # margins = [5, 0, 5, 10]
            self.set_bottom_label(self.shorten_label(label, 10), font_size=12, reload=reload_key)
            return True
        else:
            self.set_bottom_label(None, reload=reload_key)
            return False

    def shorten_label(self, label, length):
        if label is None:
            return
        if len(label) > length:
            return label[:length-2] + ".."
        return label

    def on_toggle_label(self, switch, *args):
        settings = self.get_settings()
        settings["show_label"] = switch.get_active()
        self.set_settings(settings)

    def on_toggle_thumbnail(self, switch, *args):
        settings = self.get_settings()
        settings["show_thumbnail"] = switch.get_active()
        self.set_settings(settings)

    def generate_image(self, icon:Image = None, icon_margins=[0, 0, 0, 0], background:Image=None):
        if background is None:
            background = Image.new("RGBA", (self.deck_controller.deck.key_image_format()["size"]), (0, 0, 0, 0))

        if icon is not None:
            # Resize
            icon_height = math.floor(self.deck_controller.deck.key_image_format()["size"][1]-icon_margins[1]-icon_margins[3])
            icon_width = math.floor(self.deck_controller.deck.key_image_format()["size"][0]-icon_margins[0]-icon_margins[2])

            icon = icon.resize((icon_width, icon_height), Image.Resampling.LANCZOS)

            x_pos = math.floor((background.width - icon_width)/2)
            y_pos = math.floor((background.height - icon_height)/2)

            background.paste(icon, (x_pos - icon_margins[1], y_pos - icon_margins[0]), icon)

        return background


import torch
import torch.nn as nn

from math import log, sqrt

"""EnhanceNet Model

Site:
  "EnhanceNet: Single Image Super-Resolution Through Automated Texture Synthesis (2017)" (https://arxiv.org/abs/1612.07919)
"""

class ResidualBlock(nn.Module):
  def __init__(self, f: int = 3, n: int = 64) -> None:
    super().__init__()
    self.block = nn.Sequential(
      nn.Conv2d(in_channels=n, out_channels=n, kernel_size=f, padding=f//2, bias=False),
      nn.ReLU(),
      nn.Conv2d(in_channels=n, out_channels=n, kernel_size=f, padding=f//2, bias=False),
    )

  def forward(self, x):
    input = x
    x = self.block(x)
    x = torch.add(x, input)
    return x

class EnhanceNet(nn.Module):
  def __init__(self, scale: int, c: int = 3, f = 3, n: int = 64, l: int = 10) -> None:
    """EnhanceNet's Constructor

    Args:
      scale (int): number of scaling factor.
      c (int): number of channel the input/output image.
      f (int): spatial size of region.
      n (int): number of feature map.
      l (int): number of Residual Blocks.

    Examples:
      >>> EnhanceNet() # typical EnhanceNet parameters
    """
    super().__init__()
    self.scale = scale
    # Input Layer
    self.input = nn.Sequential(
      nn.Conv2d(in_channels=c, out_channels=n, kernel_size=f, padding=f//2, bias=False),
      nn.ReLU()
    )
    # Residubal Blocks
    self.residual = nn.Sequential(
      *[ResidualBlock(f=f, n=n) for _ in range(l)]
    )
    # Upscale Blocks
    self.upscale = nn.Sequential(
      *[nn.Sequential(
        nn.Upsample(scale_factor=2, mode='nearest'),
        nn.Conv2d(in_channels=n, out_channels=n, kernel_size=f, padding=f//2, bias=False),
        nn.ReLU()
      ) for _ in range(int(log(scale, 2)))]
    )
    # Output Layer
    self.output = nn.Sequential(
      nn.Conv2d(in_channels=n, out_channels=n, kernel_size=f, padding=f//2, bias=False),
      nn.ReLU(),
      nn.Conv2d(in_channels=n, out_channels=c, kernel_size=f, padding=f//2, bias=False),
    )

    for m in self.modules():
      if isinstance(m, nn.Conv2d):
        m.weight.data.normal_(0, sqrt(2. / (m.kernel_size[0] * m.kernel_size[1] * m.out_channels)))
        if m.bias is not None: m.bias.data.zero_()
    for m in self.residual.modules():
      if isinstance(m, nn.Conv2d):
        m.weight.data.normal_(0, sqrt(2. / (m.kernel_size[0] * m.kernel_size[1] * m.out_channels)) / l)

  def forward(self, x):
    input = x
    x = self.input(x)
    x = self.residual(x)
    x = self.upscale(x)
    x = self.output(x)
    x = torch.add(x, nn.functional.interpolate(input, scale_factor=self.scale, mode='bicubic', align_corners=False))
    return x

class EnhanceNetDiscriminator(nn.Module):
  def __init__(self, c: int = 3, size: tuple[int, int] = (128, 128)) -> None:
    """EnhanceNet's Discriminator Constructor

    Args:
      c (int): number of channel the input/output image.
      size (tuple(int, int)): image size (default: 128x128)

    Examples:
      >>> EnhanceNetDiscriminator() # typical EnhanceNetDiscriminator parameters
    """
    super().__init__()
    self.size = size
    # layers
    self.layers = nn.Sequential(
      nn.Conv2d(in_channels=c, out_channels=32, kernel_size=3, padding=3//2),
      nn.LeakyReLU(negative_slope=0.2, inplace=True),
      nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, stride=2, padding=3//2),
      nn.LeakyReLU(negative_slope=0.2, inplace=True),
      *[nn.Sequential(
        nn.Conv2d(in_channels=32 * (2 ** idx), out_channels=64 * (2 ** idx), kernel_size=3, padding=3//2),
        nn.LeakyReLU(negative_slope=0.2, inplace=True),
        nn.Conv2d(in_channels=64 * (2 ** idx), out_channels=64 * (2 ** idx), kernel_size=3, stride=2, padding=3//2),
        nn.LeakyReLU(negative_slope=0.2, inplace=True),
      ) for idx in range(4)],

      nn.Flatten(start_dim=1),

      nn.Linear(in_features=512 * ((self.size[0] // (2 ** 5)) * (self.size[1] // (2 ** 5))), out_features=1024),
      nn.LeakyReLU(negative_slope=0.2, inplace=True),
      nn.Linear(in_features=1024, out_features=1),
      nn.Sigmoid()
    )

  def forward(self, x):
    assert x.size()[-2:] == self.size, f'Input image size must be is {self.size}, got {x.size()[-2:]}'
    return self.layers(x)


from typing import Optional, Dict, List, Type, Any, Union, Tuple, Callable
from omspy.base import Broker
from omspy.order import Order, CompoundOrder
from omspy.models import OrderLock
import pendulum
from pydantic import BaseModel, ValidationError, validator
import logging

class BasicPeg(CompoundOrder):
    symbol: str
    side: str
    quantity: int
    timezone: str = "local"

    def __init__(self, **data) -> None:
        super().__init__(**data)
        pop_attribs = [
            "symbol",
            "side",
            "quantity",
            "timezone",
            "order_type",
            "connection",
        ]
        for attrib in pop_attribs:
            if attrib in data:
                data.pop(attrib)
        order = Order(
            symbol=self.symbol,
            quantity=self.quantity,
            side=self.side,
            timezone=self.timezone,
            order_type="LIMIT",
            **data
        )
        self.add(order)
        self.ltp[self.symbol] = 0

class PegMarket(BasicPeg):
    duration: int = 60
    peg_every: int = 10
    convert_to_market_after_expiry = True
    _next_peg: Optional[pendulum.DateTime]
    _num_pegs: int = 0
    _max_pegs: int = 0
    _expire_at: Optional[pendulum.DateTime]

    def __init__(self, **data) -> None:
        super().__init__(**data)
        self._max_pegs = int(self.duration / self.peg_every)
        self._num_pegs = 0
        self._expire_at = pendulum.now(tz=self.timezone).add(seconds=self.duration)
        self._next_peg = pendulum.now(tz=self.timezone).add(seconds=self.peg_every)

    def execute(self):
        self.orders[0].price = self.ref_price
        self.orders[0].execute(broker=self.broker, **self.order_args)

    @property
    def next_peg(self):
        return self._next_peg

    @property
    def num_pegs(self):
        return self._num_pegs

    @property
    def ref_price(self):
        return self.ltp.get(self.symbol)

    def run(self):
        order = self.orders[0]
        now = pendulum.now(self.timezone)
        if order.is_pending:
            if now > self.next_peg:
                self._next_peg = now.add(seconds=self.peg_every)
                order.modify(broker=self.broker, price=self.ref_price)
            if now > self._expire_at:
                if self.convert_to_market_after_expiry:
                    order.modify(broker=self.broker, order_type="MARKET")
                else:
                    order.cancel(self.broker)

class PegExisting(BaseModel):
    order: Order
    broker: Any
    timezone: Optional[str] = None
    duration: int = 60
    peg_every: int = 10
    done: bool = False
    order_args: Optional[Dict[str, str]] = None
    modify_args: Optional[Dict[str, str]] = None
    lock_duration: int = 2
    _next_peg: Optional[pendulum.DateTime] = None
    _num_pegs: int = 0
    _max_pegs: int = 0
    _expire_at: Optional[pendulum.DateTime]

    class Config:
        underscore_attrs_are_private = True

    def __init__(self, **data) -> None:
        super().__init__(**data)
        self._max_pegs = int(self.duration / self.peg_every)
        self._num_pegs = 0
        self._expire_at = pendulum.now(tz=self.timezone).add(seconds=self.duration)
        self._next_peg = pendulum.now(tz=self.timezone).add(seconds=self.peg_every)
        self.order.order_type = "LIMIT"
        self.order.trigger_price = 0
        if self.order_args is None:
            self.order_args = {}
        if self.modify_args is None:
            self.modify_args = {}

    @validator("order")
    def order_should_be_pending(cls, v):
        """
        Only accept a pending order
        """
        if not (v.is_pending):
            raise ValueError
        else:
            return v

    @property
    def next_peg(self) -> pendulum.DateTime:
        return self._next_peg

    @property
    def num_pegs(self) -> int:
        return self._num_pegs

    def execute(self) -> None:
        self.order.execute(broker=self.broker, **self.order_args)

    def _mark_done(self) -> None:
        """
        Mark whether the order is done
        """
        if self.order.is_done:
            self.done = True

    def run(self, ltp: float) -> None:
        if self.done:
            logging.warning("Order already done")
            return

        self._mark_done()
        order = self.order
        now = pendulum.now(self.timezone)
        if order.is_pending:
            if now > self._expire_at:
                if self.order.convert_to_market_after_expiry:
                    order.modify(
                        broker=self.broker, order_type="MARKET", **self.modify_args
                    )
                    order.add_lock(1, self.lock_duration)
                else:
                    order.cancel(self.broker)
                    order.add_lock(2, self.lock_duration)
            elif now > self.next_peg:
                self._next_peg = now.add(seconds=self.peg_every)
                order.modify(broker=self.broker, price=ltp, **self.modify_args)
                order.add_lock(1, self.lock_duration)

class PegSequential(BaseModel):
    """
    Peg orders in sequence and peg only when the
    previous order is complete
    skip_subsequent_if_failed
        if True, subsequent orders in the sequence would be skipped and the program would terminate
    force_order_type
        if True, all orders are forced as LIMIT order
        if False, non LIMIT orders are placed as is without order type and other arguments being changed
    """

    orders: List[Order]
    broker: Any
    timezone: Optional[str] = None
    duration: int = 12
    peg_every: int = 4
    lock_duration: int = 2
    order_args: Optional[Dict[str, str]] = None
    modify_args: Optional[Dict[str, str]] = None
    done: bool = False
    modify_args: Optional[Dict[str, str]] = None
    skip_subsequent_if_failed = False
    force_order_type = True
    _order: Optional[Union[Order, PegExisting]] = None
    _start_time: Optional[pendulum.DateTime] = None

    class Config:
        underscore_attrs_are_private = True

    def __init__(self, **data) -> None:
        super().__init__(**data)
        if self.order_args is None:
            self.order_args = {}
        if self.modify_args is None:
            self.modify_args = {}
        # Validate whether orders could be pegged
        for order in self.orders:
            if (self.force_order_type) or (order.order_type == "LIMIT"):
                peg = PegExisting(
                    order=order,
                    timezone=self.timezone,
                    duration=self.duration,
                    peg_every=self.peg_every,
                    lock_duration=self.lock_duration,
                    order_args=self.order_args,
                    modify_args=self.modify_args,
                )
        self._start_time = pendulum.now(tz=self.timezone)

    @property
    def has_expired(self) -> bool:
        """
        Whether the entire sequential order has expired.
        A sequential order is considered expired when the
        current time is greater than the maximum possible
        time taken by all the orders together
        Note
        ----
        1) total_time = duration*number of orders
        """
        total_time = self.duration * len(self.orders)
        if pendulum.now(tz=self.timezone) > self._start_time.add(seconds=total_time):
            return True
        else:
            return False

    @property
    def order(self) -> Optional[Union[Order, PegExisting]]:
        return self._order

    @property
    def completed(self) -> List[Order]:
        """
        returns the list of completed orders
        """
        return [order for order in self.orders if order.is_complete]

    @property
    def pending(self):
        """
        returns the list of pending orders
        """
        return [order for order in self.orders if order.is_pending]

    @property
    def all_complete(self):
        """
        Whether all orders are completed
        """
        return all([order.is_complete for order in self.orders])

    def get_current_order(self) -> Union[PegExisting, None]:
        """
        Get the current order to peg
        """
        for order in self.orders:
            if order.is_pending:
                if self.force_order_type or (order.order_type == "LIMIT"):
                    return PegExisting(
                        order=order,
                        broker=self.broker,
                        timezone=self.timezone,
                        duration=self.duration,
                        peg_every=self.peg_every,
                        lock_duration=self.lock_duration,
                        order_args=self.order_args,
                        modify_args=self.modify_args,
                    )
                else:
                    return order
        return None

    def set_current_order(self) -> Union[PegExisting, None]:
        """
        Set the current order for pegging
        Note
        ----
        1) Set the current order only when an existing peg
        order is complete or there is no peg order
        """
        if self.order is None:
            self._order = self.get_current_order()
        elif isinstance(self.order, PegExisting):
            if self.order.order.is_done:
                self._order = self.get_current_order()
        elif isinstance(self.order, Order):
            if self.order.is_done:
                self._order = self.get_current_order()
        return self.order

    def execute_all(self) -> None:
        # Execute all pending orders
        for order in self.orders:
            order.execute(broker=self.broker, **self.order_args)

    def cancel_all(self) -> None:
        # Cancel all pending orders
        for order in self.orders:
            order.cancel(broker=self.broker)

    def _process_order_after_expiry(self, order: Order) -> None:
        """
        Process an order after expiry based on the given flags
        """
        if not order.order_id:
            order.status = "CANCELED"
            return
        if order.cancel_after_expiry:
            order.cancel(broker=self.broker)
        elif order.convert_to_market_after_expiry:
            order.price = 0
            order.order_type = "MARKET"
            order.modify(broker=self.broker)

    def run_after_expiry(self) -> None:
        """
        Run this function after the overall peg time has expired.
        This function could be overriden to match customized functionality
        """
        if self.done:
            return
        for order in self.orders:
            if order.is_pending:
                self._process_order_after_expiry(order)

    def _mark_subsequent_orders_as_canceled(self) -> None:
        """
        Mark all subsequent orders as canceled if the
        existing order status is canceled or rejected
        """
        index = 0
        flag = False
        for i, order in enumerate(self.orders):
            if order.status in ("CANCELED", "CANCELLED", "REJECTED"):
                index = i
                flag = True
                break
        if flag and (index < len(self.orders) - 1):
            for i in range(index + 1, len(self.orders)):
                self.orders[i].status = "CANCELED"

    def run(self, ltp: Dict[str, float]) -> None:
        if self.done:
            return
        if self.skip_subsequent_if_failed:
            self._mark_subsequent_orders_as_canceled()
        self.set_current_order()
        peg = self.order
        # Run only when there is an order
        if peg:
            if isinstance(peg, PegExisting):
                if not (peg.order.order_id):
                    # Place the order if it has not been placed yet
                    peg.execute()
                symbol = peg.order.symbol
                last_price = ltp.get(symbol, 0)
                peg.run(ltp=last_price)
            elif isinstance(peg, Order):
                self.order.execute(broker=self.broker, **self.order_args)

        self._mark_done()

    def _mark_done(self) -> None:
        self.done = all([order.is_done for order in self.orders])


# -*- coding: utf-8 -*-
"""Pipeline tools for OpenPype Houdini integration."""
import os
import sys
import logging
import contextlib

import hou  # noqa

from openpype.host import HostBase, IWorkfileHost, ILoadHost, IPublishHost

import pyblish.api

from openpype.pipeline import (
    register_creator_plugin_path,
    register_loader_plugin_path,
    register_inventory_action_path,
    AVALON_CONTAINER_ID,
)
from openpype.pipeline.load import any_outdated_containers
from openpype.hosts.houdini import HOUDINI_HOST_DIR
from openpype.hosts.houdini.api import lib, shelves, creator_node_shelves

from openpype.lib import (
    register_event_callback,
    emit_event,
)

log = logging.getLogger("openpype.hosts.houdini")

AVALON_CONTAINERS = "/obj/AVALON_CONTAINERS"
CONTEXT_CONTAINER = "/obj/OpenPypeContext"
IS_HEADLESS = not hasattr(hou, "ui")

PLUGINS_DIR = os.path.join(HOUDINI_HOST_DIR, "plugins")
PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish")
LOAD_PATH = os.path.join(PLUGINS_DIR, "load")
CREATE_PATH = os.path.join(PLUGINS_DIR, "create")
INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory")

class HoudiniHost(HostBase, IWorkfileHost, ILoadHost, IPublishHost):
    name = "houdini"

    def __init__(self):
        super(HoudiniHost, self).__init__()
        self._op_events = {}
        self._has_been_setup = False

    def install(self):
        pyblish.api.register_host("houdini")
        pyblish.api.register_host("hython")
        pyblish.api.register_host("hpython")

        pyblish.api.register_plugin_path(PUBLISH_PATH)
        register_loader_plugin_path(LOAD_PATH)
        register_creator_plugin_path(CREATE_PATH)
        register_inventory_action_path(INVENTORY_PATH)

        log.info("Installing callbacks ... ")
        # register_event_callback("init", on_init)
        self._register_callbacks()
        register_event_callback("before.save", before_save)
        register_event_callback("save", on_save)
        register_event_callback("open", on_open)
        register_event_callback("new", on_new)

        pyblish.api.register_callback(
            "instanceToggled", on_pyblish_instance_toggled
        )

        self._has_been_setup = True
        # add houdini vendor packages
        hou_pythonpath = os.path.join(HOUDINI_HOST_DIR, "vendor")

        sys.path.append(hou_pythonpath)

        # Set asset settings for the empty scene directly after launch of
        # Houdini so it initializes into the correct scene FPS,
        # Frame Range, etc.
        # TODO: make sure this doesn't trigger when
        #       opening with last workfile.
        _set_context_settings()

        if not IS_HEADLESS:
            import hdefereval  # noqa, hdefereval is only available in ui mode
            # Defer generation of shelves due to issue on Windows where shelf
            # initialization during start up delays Houdini UI by minutes
            # making it extremely slow to launch.
            hdefereval.executeDeferred(shelves.generate_shelves)

        if not IS_HEADLESS:
            import hdefereval # noqa, hdefereval is only available in ui mode
            hdefereval.executeDeferred(creator_node_shelves.install)

    def workfile_has_unsaved_changes(self):
        return hou.hipFile.hasUnsavedChanges()

    def get_workfile_extensions(self):
        return [".hip", ".hiplc", ".hipnc"]

    def save_workfile(self, dst_path=None):
        # Force forwards slashes to avoid segfault
        if dst_path:
            dst_path = dst_path.replace("\\", "/")
        hou.hipFile.save(file_name=dst_path,
                         save_to_recent_files=True)
        return dst_path

    def open_workfile(self, filepath):
        # Force forwards slashes to avoid segfault
        filepath = filepath.replace("\\", "/")

        hou.hipFile.load(filepath,
                         suppress_save_prompt=True,
                         ignore_load_warnings=False)

        return filepath

    def get_current_workfile(self):
        current_filepath = hou.hipFile.path()
        if (os.path.basename(current_filepath) == "untitled.hip" and
                not os.path.exists(current_filepath)):
            # By default a new scene in houdini is saved in the current
            # working directory as "untitled.hip" so we need to capture
            # that and consider it 'not saved' when it's in that state.
            return None

        return current_filepath

    def get_containers(self):
        return ls()

    def _register_callbacks(self):
        for event in self._op_events.copy().values():
            if event is None:
                continue

            try:
                hou.hipFile.removeEventCallback(event)
            except RuntimeError as e:
                log.info(e)

        self._op_events[on_file_event_callback] = hou.hipFile.addEventCallback(
            on_file_event_callback
        )

    @staticmethod
    def create_context_node():
        """Helper for creating context holding node.

        Returns:
            hou.Node: context node

        """
        obj_network = hou.node("/obj")
        op_ctx = obj_network.createNode("subnet",
                                        node_name="OpenPypeContext",
                                        run_init_scripts=False,
                                        load_contents=False)

        op_ctx.moveToGoodPosition()
        op_ctx.setBuiltExplicitly(False)
        op_ctx.setCreatorState("OpenPype")
        op_ctx.setComment("OpenPype node to hold context metadata")
        op_ctx.setColor(hou.Color((0.081, 0.798, 0.810)))
        op_ctx.setDisplayFlag(False)
        op_ctx.hide(True)
        return op_ctx

    def update_context_data(self, data, changes):
        op_ctx = hou.node(CONTEXT_CONTAINER)
        if not op_ctx:
            op_ctx = self.create_context_node()

        lib.imprint(op_ctx, data)

    def get_context_data(self):
        op_ctx = hou.node(CONTEXT_CONTAINER)
        if not op_ctx:
            op_ctx = self.create_context_node()
        return lib.read(op_ctx)

    def save_file(self, dst_path=None):
        # Force forwards slashes to avoid segfault
        dst_path = dst_path.replace("\\", "/")

        hou.hipFile.save(file_name=dst_path,
                         save_to_recent_files=True)

def on_file_event_callback(event):
    if event == hou.hipFileEventType.AfterLoad:
        emit_event("open")
    elif event == hou.hipFileEventType.AfterSave:
        emit_event("save")
    elif event == hou.hipFileEventType.BeforeSave:
        emit_event("before.save")
    elif event == hou.hipFileEventType.AfterClear:
        emit_event("new")

def containerise(name,
                 namespace,
                 nodes,
                 context,
                 loader=None,
                 suffix=""):
    """Bundle `nodes` into a subnet and imprint it with metadata

    Containerisation enables a tracking of version, author and origin
    for loaded assets.

    Arguments:
        name (str): Name of resulting assembly
        namespace (str): Namespace under which to host container
        nodes (list): Long names of nodes to containerise
        context (dict): Asset information
        loader (str, optional): Name of loader used to produce this container.
        suffix (str, optional): Suffix of container, defaults to `_CON`.

    Returns:
        container (str): Name of container assembly

    """

    # Ensure AVALON_CONTAINERS subnet exists
    subnet = hou.node(AVALON_CONTAINERS)
    if subnet is None:
        obj_network = hou.node("/obj")
        subnet = obj_network.createNode("subnet",
                                        node_name="AVALON_CONTAINERS")

    # Create proper container name
    container_name = "{}_{}".format(name, suffix or "CON")
    container = hou.node("/obj/{}".format(name))
    container.setName(container_name, unique_name=True)

    data = {
        "schema": "openpype:container-2.0",
        "id": AVALON_CONTAINER_ID,
        "name": name,
        "namespace": namespace,
        "loader": str(loader),
        "representation": str(context["representation"]["_id"]),
    }

    lib.imprint(container, data)

    # "Parent" the container under the container network
    hou.moveNodesTo([container], subnet)

    subnet.node(container_name).moveToGoodPosition()

    return container

def parse_container(container):
    """Return the container node's full container data.

    Args:
        container (hou.Node): A container node name.

    Returns:
        dict: The container schema data for this container node.

    """
    data = lib.read(container)

    # Backwards compatibility pre-schemas for containers
    data["schema"] = data.get("schema", "openpype:container-1.0")

    # Append transient data
    data["objectName"] = container.path()
    data["node"] = container

    return data

def ls():
    containers = []
    for identifier in (AVALON_CONTAINER_ID,
                       "pyblish.mindbender.container"):
        containers += lib.lsattr("id", identifier)

    for container in sorted(containers,
                            # Hou 19+ Python 3 hou.ObjNode are not
                            # sortable due to not supporting greater
                            # than comparisons
                            key=lambda node: node.path()):
        yield parse_container(container)

def before_save():
    return lib.validate_fps()

def on_save():

    log.info("Running callback on save..")

    # update houdini vars
    lib.update_houdini_vars_context_dialog()

    nodes = lib.get_id_required_nodes()
    for node, new_id in lib.generate_ids(nodes):
        lib.set_id(node, new_id, overwrite=False)

def _show_outdated_content_popup():
    # Get main window
    parent = lib.get_main_window()
    if parent is None:
        log.info("Skipping outdated content pop-up "
                 "because Houdini window can't be found.")
    else:
        from openpype.widgets import popup

        # Show outdated pop-up
        def _on_show_inventory():
            from openpype.tools.utils import host_tools
            host_tools.show_scene_inventory(parent=parent)

        dialog = popup.Popup(parent=parent)
        dialog.setWindowTitle("Houdini scene has outdated content")
        dialog.setMessage("There are outdated containers in "
                          "your Houdini scene.")
        dialog.on_clicked.connect(_on_show_inventory)
        dialog.show()

def on_open():

    if not hou.isUIAvailable():
        log.debug("Batch mode detected, ignoring `on_open` callbacks..")
        return

    log.info("Running callback on open..")

    # update houdini vars
    lib.update_houdini_vars_context_dialog()

    # Validate FPS after update_task_from_path to
    # ensure it is using correct FPS for the asset
    lib.validate_fps()

    if any_outdated_containers():
        parent = lib.get_main_window()
        if parent is None:
            # When opening Houdini with last workfile on launch the UI hasn't
            # initialized yet completely when the `on_open` callback triggers.
            # We defer the dialog popup to wait for the UI to become available.
            # We assume it will open because `hou.isUIAvailable()` returns True
            import hdefereval
            hdefereval.executeDeferred(_show_outdated_content_popup)
        else:
            _show_outdated_content_popup()

        log.warning("Scene has outdated content.")

def on_new():
    """Set project resolution and fps when create a new file"""

    if hou.hipFile.isLoadingHipFile():
        # This event also triggers when Houdini opens a file due to the
        # new event being registered to 'afterClear'. As such we can skip
        # 'new' logic if the user is opening a file anyway
        log.debug("Skipping on new callback due to scene being opened.")
        return

    log.info("Running callback on new..")
    _set_context_settings()

    # It seems that the current frame always gets reset to frame 1 on
    # new scene. So we enforce current frame to be at the start of the playbar
    # with execute deferred
    def _enforce_start_frame():
        start = hou.playbar.playbackRange()[0]
        hou.setFrame(start)

    if hou.isUIAvailable():
        import hdefereval
        hdefereval.executeDeferred(_enforce_start_frame)
    else:
        # Run without execute deferred when no UI is available because
        # without UI `hdefereval` is not available to import
        _enforce_start_frame()

def _set_context_settings():
    """Apply the project settings from the project definition

    Settings can be overwritten by an asset if the asset.data contains
    any information regarding those settings.

    Examples of settings:
        fps
        resolution
        renderer

    Returns:
        None
    """

    lib.reset_framerange()
    lib.update_houdini_vars_context()

def on_pyblish_instance_toggled(instance, new_value, old_value):
    """Toggle saver tool passthrough states on instance toggles."""
    @contextlib.contextmanager
    def main_take(no_update=True):
        """Enter root take during context"""
        original_take = hou.takes.currentTake()
        original_update_mode = hou.updateModeSetting()
        root = hou.takes.rootTake()
        has_changed = False
        try:
            if original_take != root:
                has_changed = True
                if no_update:
                    hou.setUpdateMode(hou.updateMode.Manual)
                hou.takes.setCurrentTake(root)
                yield
        finally:
            if has_changed:
                if no_update:
                    hou.setUpdateMode(original_update_mode)
                hou.takes.setCurrentTake(original_take)

    if not instance.data.get("_allowToggleBypass", True):
        return

    nodes = instance[:]
    if not nodes:
        return

    # Assume instance node is first node
    instance_node = nodes[0]

    if not hasattr(instance_node, "isBypassed"):
        # Likely not a node that can actually be bypassed
        log.debug("Can't bypass node: %s", instance_node.path())
        return

    if instance_node.isBypassed() != (not old_value):
        print("%s old bypass state didn't match old instance state, "
              "updating anyway.." % instance_node.path())

    try:
        # Go into the main take, because when in another take changing
        # the bypass state of a note cannot be done due to it being locked
        # by default.
        with main_take(no_update=True):
            instance_node.bypass(not new_value)
    except hou.PermissionError as exc:
        log.warning("%s - %s", instance_node.path(), exc)


import json
import os.path

import numpy as np
import matplotlib.pyplot as plt

def read_file(path):
    with open(path, 'r') as a:
        data_str=a.read()
    data=json.loads(data_str)
    return data

def read_data(data):
    len=[]
    time=[]
    for i in data:
        len.append(data[i]['len'])
        time.append(data[i]['time'])

    avg_len=float(np.mean(len))
    avg_time=float(np.mean(time))
    return len, time, avg_len, avg_time

def draw(data, avg_data, name=""):
    plt.figure(figsize=(8, 5))
    line1, = plt.plot(data, color='red')
    line2, = plt.plot([avg_data for i in data], color='blue')
    plt.xlabel('Test Time')
    plt.ylabel('Round')
    plt.title('Round of killer bull')
    plt.legend(handles=[line1, line2],
               labels=['Round', 'Average round'],
               loc='best')
    plt.savefig('D:\\git_project\\cs520_final\\picture\\killer_bull_rounds.jpg')
    plt.show()

if __name__ == '__main__':
    current_path=os.path.dirname(os.path.abspath("__file__"))
    # file_name=os.path.join(current_path, "data_shy_bull.json")
    file_name = os.path.join(current_path, "data_killer_bull_25.json")
    data=read_file(file_name)
    a,b,c,d=read_data(data)
    # draw(a,c)


# -*- coding:utf-8 -*-
from __future__ import annotations
from typing import TYPE_CHECKING, List

import logging
import json
import os
import requests

from tqdm import tqdm

from utils import *

if TYPE_CHECKING:
    from typing import TypedDict

    class DataframeData(TypedDict):
        headers: List[str]
        data: List[List[str | int | bool]]

initial_prompt = "You are a helpful assistant."
API_URL = "https://api.openai.com/v1/chat/completions"

def get_response(
    openai_api_key, system_prompt, history, stream, selected_model
):
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {openai_api_key}",
    }

    history = [construct_system(system_prompt), *history]

    payload = {
        "model": selected_model,
        "messages": history,  # [{"role": "user", "content": f"{inputs}"}],
        "temperature": 1.0,  # 1.0,
        "top_p": 1.0,  # 1.0,
        "n": 1,
        "stream": stream,
        "presence_penalty": 0,
        "frequency_penalty": 0,
    }
    if stream:
        timeout = timeout_streaming
    else:
        timeout = timeout_all

    # 获取环境变量中的代理设置
    http_proxy = os.environ.get("HTTP_PROXY") or os.environ.get("http_proxy")
    https_proxy = os.environ.get("HTTPS_PROXY") or os.environ.get("https_proxy")

    # 如果存在代理设置，使用它们
    proxies = {}
    if http_proxy:
        logging.info(f"Using HTTP proxy: {http_proxy}")
        proxies["http"] = http_proxy
    if https_proxy:
        logging.info(f"Using HTTPS proxy: {https_proxy}")
        proxies["https"] = https_proxy

    # 如果有代理，使用代理发送请求，否则使用默认设置发送请求
    if proxies:
        response = requests.post(
            API_URL,
            headers=headers,
            json=payload,
            stream=True,
            timeout=timeout,
            proxies=proxies,
        )
    else:
        response = requests.post(
            API_URL,
            headers=headers,
            json=payload,
            stream=True,
            timeout=timeout,
        )
    return response

def stream_predict(
    openai_api_key,
    system_prompt,
    history,
    inputs,
    chatbot,
    all_token_counts,
    selected_model,
    fake_input=None,
    display_append=""
):
    def get_return_value():
        return chatbot, history, status_text, all_token_counts
    # logging.info("实时回答模式")
    partial_words = ""
    counter = 0
    status_text = "answering……"
    history.append(construct_user(inputs))
    history.append(construct_assistant(""))
    if fake_input:
        chatbot.append((fake_input, ""))
    else:
        chatbot.append((inputs, ""))
    user_token_count = 0
    if len(all_token_counts) == 0:
        system_prompt_token_count = count_token(construct_system(system_prompt))
        user_token_count = (
            count_token(construct_user(inputs)) + system_prompt_token_count
        )
    else:
        user_token_count = count_token(construct_user(inputs))
    all_token_counts.append(user_token_count)
    logging.info(f"input token count: {user_token_count}")
    yield get_return_value()
    try:
        response = get_response(
            openai_api_key,
            system_prompt,
            history,
            True,
            selected_model,
        )
    except requests.exceptions.ConnectTimeout:
        status_text = (
            standard_error_msg + connection_timeout_prompt + error_retrieve_prompt
        )
        yield get_return_value()
        return
    except requests.exceptions.ReadTimeout:
        status_text = standard_error_msg + read_timeout_prompt + error_retrieve_prompt
        yield get_return_value()
        return

    yield get_return_value()
    error_json_str = ""

    for chunk in tqdm(response.iter_lines()):
        if counter == 0:
            counter += 1
            continue
        counter += 1
        # check whether each line is non-empty
        if chunk:
            chunk = chunk.decode()
            chunklength = len(chunk)
            try:
                chunk = json.loads(chunk[6:])
            except json.JSONDecodeError:
                logging.info(chunk)
                error_json_str += chunk
                status_text = f"JSON file parsing error. Please reset the conversation. received content: {error_json_str}"
                yield get_return_value()
                continue
            # decode each line as response data is in bytes
            if chunklength > 6 and "delta" in chunk["choices"][0]:
                finish_reason = chunk["choices"][0]["finish_reason"]
                status_text = construct_token_message(
                    sum(all_token_counts), stream=True
                )
                if finish_reason == "stop":
                    yield get_return_value()
                    break
                try:
                    partial_words = (
                        partial_words + chunk["choices"][0]["delta"]["content"]
                    )
                except KeyError:
                    status_text = (
                        standard_error_msg
                        + "Token count has reached the maxtoken limit. Please reset the conversation. Current Token Count: "
                        + str(sum(all_token_counts))
                    )
                    yield get_return_value()
                    break
                history[-1] = construct_assistant(partial_words)
                chatbot[-1] = (chatbot[-1][0], partial_words+display_append)
                all_token_counts[-1] += 1
                yield get_return_value()

def predict_all(
    openai_api_key,
    system_prompt,
    history,
    inputs,
    chatbot,
    all_token_counts,
    selected_model,
    fake_input=None,
    display_append=""
):
    # logging.info("一次性回答模式")
    history.append(construct_user(inputs))
    history.append(construct_assistant(""))
    if fake_input:
        chatbot.append((fake_input, ""))
    else:
        chatbot.append((inputs, ""))
    all_token_counts.append(count_token(construct_user(inputs)))
    try:
        response = get_response(
            openai_api_key,
            system_prompt,
            history,
            False,
            selected_model,
        )
    except requests.exceptions.ConnectTimeout:
        status_text = (
            standard_error_msg + connection_timeout_prompt + error_retrieve_prompt
        )
        return chatbot, history, status_text, all_token_counts
    except requests.exceptions.ProxyError:
        status_text = standard_error_msg + proxy_error_prompt + error_retrieve_prompt
        return chatbot, history, status_text, all_token_counts
    except requests.exceptions.SSLError:
        status_text = standard_error_msg + ssl_error_prompt + error_retrieve_prompt
        return chatbot, history, status_text, all_token_counts
    response = json.loads(response.text)
    content = response["choices"][0]["message"]["content"]
    history[-1] = construct_assistant(content)
    chatbot[-1] = (chatbot[-1][0], content+display_append)
    total_token_count = response["usage"]["total_tokens"]
    all_token_counts[-1] = total_token_count - sum(all_token_counts)
    status_text = construct_token_message(total_token_count)
    return chatbot, history, status_text, all_token_counts

def predict(
    openai_api_key,
    system_prompt,
    history,
    inputs,
    chatbot,
    all_token_counts,
    stream=True,
    selected_model=MODELS[0],
    use_websearch=False,
    files = None,
    should_check_token_count=True,
):  # repetition_penalty, top_k

    old_inputs = ""
    link_references = ""

    if len(openai_api_key) != 51:
        status_text = standard_error_msg + no_apikey_msg
        logging.info(status_text)
        chatbot.append((inputs, ""))
        if len(history) == 0:
            history.append(construct_user(inputs))
            history.append("")
            all_token_counts.append(0)
        else:
            history[-2] = construct_user(inputs)
        yield chatbot, history, status_text, all_token_counts
        return

    yield chatbot, history, "answering……", all_token_counts

    if stream:
        # logging.info("使用流式传输")
        iter = stream_predict(
            openai_api_key,
            system_prompt,
            history,
            inputs,
            chatbot,
            all_token_counts,
            selected_model,
            fake_input=old_inputs,
            display_append=link_references
        )
        for chatbot, history, status_text, all_token_counts in iter:
            yield chatbot, history, status_text, all_token_counts
    else:
        # logging.info("不使用流式传输")
        chatbot, history, status_text, all_token_counts = predict_all(
            openai_api_key,
            system_prompt,
            history,
            inputs,
            chatbot,
            all_token_counts,
            selected_model,
            fake_input=old_inputs,
            display_append=link_references
        )
        yield chatbot, history, status_text, all_token_counts

    logging.info(f"The current token count is{all_token_counts}")


import numpy as np
from nas_cifar import training_n_out, gets_model, evaluate_in_test
from tqdm import tqdm

def in_bounds(point, bounds):
	# enumerate all dimensions of the point
	for d in range(len(bounds)):
		# check if out of bounds for this dimension
		if point[d] < bounds[d, 0] or point[d] > bounds[d, 1]:
			return False
	return True

def evolutionary(bounds, n_iter, step_size, mu, lam):
    best, best_eval = None, 1e+10
    # calculate the number of children per parent
    n_children = int(lam / mu)
    # initial population
    population = []

    for _ in range(lam):
        candidate = None
        while candidate is None or not in_bounds(candidate, bounds):
            candidate = bounds[:, 0] + np.random.rand(len(bounds)) * (bounds[:, 1] - bounds[:, 0])/2

        population.append(candidate)

	# perform the search
    the_bests=[]
    for epoch in range(n_iter):
        # evaluate fitness for the population
        scores = []
        for c in tqdm(range(len(population))):
             scores.append(training_n_out(epochs=2,
                                    batch_size=64,
                                    channel1=round(population[c][0]),
                                    channel2=round(population[c][1]),
                                    Kernel1=round(population[c][2]),
                                    Kernel2=round(population[c][3]),
                                    dropout=np.round(population[c][4],decimals=2)))

        # Minimize the Score
        # rank scores in ascending order

        ranks = np.argsort(np.argsort(scores))

        # select the indexes for the top mu ranked solutions
        selected = [i for i,_ in enumerate(ranks) if ranks[i] < mu]
        # create children from parents
        children = []
        for i in selected:
            # check if this parent is the best solution ever seen CHECK IF IS MAX OR MIN
            if scores[i] > best_eval:
                best, best_eval = population[i], scores[i]
                print('\n%d, Best: f(%s) = %.5f' % (epoch, best, best_eval))
                print('----------------------------\n')
                moment_model = gets_model(epochs=2,
                                            batch_size=1,
                                            channel1=round(best[0]),
                                            channel2=round(best[1]),
                                            Kernel1=round(best[2]),
                                            Kernel2=round(best[3]),
                                            dropout=np.round(best[4],decimals=2))

                trainable_count = moment_model.count_params()
                the_bests.append([best, best_eval, trainable_count])

            # create children for parent
            for _ in range(n_children):
                child = None
                while child is None or not in_bounds(child, bounds):
                    child = population[i] + np.multiply(np.random.randn(len(bounds)) , step_size)
                children.append(child)
        # replace population with children
        population = children
        best_model = gets_model(epochs=2,
                                batch_size=64,
                                channel1=round(best[0]),
                                channel2=round(best[1]),
                                Kernel1=round(best[2]),
                                Kernel2=round(best[3]),
                                dropout=np.round(best[4],decimals=2))

    return best, best_eval, the_bests, best_model

if __name__=='__main__':
    # Define range for input
    parameters = {'channel1' : [8,128],
                  'channel2' : [8,128],
                  'kernel1' :  [1,6],
                  'kernel2' :  [1,6],
                  'dropout' :  [0,1]}

    bounds = np.array([parameters['channel1'],
                       parameters['channel2'],
                       parameters['kernel1'],
                       parameters['kernel2'],
                       parameters['dropout'],
                       ])
    # Define the total iterations
    n_iter = 20
    # Number of parents selected
    mu = 3
    # The number of population
    lam = 15

    # Define the maximum step size
    step_size = [16,
                 16,
                 2,
                 2,
                 0.5]

    # Perform the evolution strategy (mu, lambda) search
    best, score, the_bests, best_model = evolutionary(bounds, n_iter, step_size, mu, lam)

    print('\n-----------------------------------------\n')
    print('Best Score\n')
    final_score = evaluate_in_test(epochs=15,
                                batch_size=64,
                                channel1=round(best[0]),
                                channel2=round(best[1]),
                                Kernel1=round(best[2]),
                                Kernel2=round(best[3]),
                                dropout=np.round(best[4],decimals=2))
    best_model.summary()

    print('f(%s) = %f' % (best, score))


import math

def main(x):
    n = len(x)
    s = 0
    x.insert(0, 0)
    for i in range(1, n + 1):
        s += 78 * (math.fabs(x[n+1-math.ceil(i/3)])**3)
    return 91 * s

if __name__ == '__main__':
    print(main([-0.36, 0.18]))


#
# @lc app=leetcode.cn id=42 lang=python3
#
# [42] 接雨水
#
# https://leetcode.cn/problems/trapping-rain-water/description/
#
# algorithms
# Hard (62.94%)
# Likes:    4529
# Dislikes: 0
# Total Accepted:    724K
# Total Submissions: 1.2M
# Testcase Example:  '[0,1,0,2,1,0,1,3,2,1,2,1]'
#
# 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图，计算按此排列的柱子，下雨之后能接多少雨水。
#
#
#
# 示例 1：
#
#
#
#
# 输入：height = [0,1,0,2,1,0,1,3,2,1,2,1]
# 输出：6
# 解释：上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图，在这种情况下，可以接 6 个单位的雨水（蓝色部分表示雨水）。
#
#
# 示例 2：
#
#
# 输入：height = [4,2,0,3,2,5]
# 输出：9
#
#
#
#
# 提示：
#
#
# n == height.length
# 1 <= n <= 2 * 10^4
# 0 <= height[i] <= 10^5
#
#
#

# @lc code=start
class Solution:
    def trap(self, height: List[int]) -> int:
        q = deque()
        res = 0
        for h in height:
            if len(q) == 0 or h < q[0]:
                q.append(h)
                continue
            l = q[0]
            while q:
                res += l - q[0]
                q.popleft()
            q.append(h)
        r = 0
        while q:
            c = q[-1]
            r = max(r, c)
            res += r-c
            q.pop()
        return res

# @lc code=end


from django.contrib import admin
from django.conf.urls import url
from products import views

urlpatterns = [
    # 1. API For All Products
    url(r'^product_list/$', views.index, name="home"),

    #2. API for All Category
    url(r'^categories/$', views.categories, name="categories"),

    #3. API for Sub Category againt a Category
    url(r'^sub_categories/(?P<category>\d+)/$', views.sub_categories, name="sub_categories"),

    #4. API for Products againt a Category
    url(r'^cat_products/(?P<category>\d+)/$', views.cat_products, name="cat_products"),

    #5. API for Products againt a Sub Category
    url(r'^sub_cat_products/(?P<subcategory>\d+)/$', views.sub_products, name="sub_products"),

    #6. API for Create or Delete Product(s)
    url(r'^add_products/$', views.ProductCreateView.as_view(), name="add_products"),
]


from file_manager import FileManager
from day import Day
from course import Course
from lecturer import Lecturer
from faculty import Faculty
from period import Period
from gams import *
from os import *

BASE_DIR = path.abspath('')
ws = GamsWorkspace(working_directory=BASE_DIR, system_directory='/Library/Frameworks/GAMS.framework/Resources')

def set_input_data(courses, lecturers, periods, faculty, groups):
    db = ws.add_database()

    c_python = [str(course.num) for course in courses]
    c = db.add_set("c", 1)
    for cp in c_python:
        c.add_record(cp)

    l_python = [str(lecturer.num) for lecturer in lecturers]
    l = db.add_set("l", 1)
    for lp in l_python:
        l.add_record(lp)

    d_python = [str(i) for i in range(1, 6)]
    d = db.add_set("d", 1)
    for dp in d_python:
        d.add_record(dp)

    last_d_python = 5
    last_d = db.add_set("last_d", 1)
    last_d.add_record(str(last_d_python))

    h_python = [str(period.num) for period in periods]
    h = db.add_set("h", 1)
    for hp in h_python:
        h.add_record(hp)

    j_python = [str(i) for i in range(1, faculty.groups + 1)]
    j = db.add_set("j", 1)
    for jp in j_python:
        j.add_record(jp)

#    print("c:", c_python)
#    print("l:", l_python)
#    print("d:", d_python)
#    print("h:", h_python)
#    print("j:", j_python)

    k_python = faculty.classes
#    print("k:", k_python)
    k = db.add_parameter("k", 0)
    k.add_record().value = k_python

    n_python = {}
    for course in courses:
        n_python[str(course.num)] = course.get_class_num()
#    print("n:", n_python)
    n = db.add_parameter_dc("n", [c])
    for cp in c_python:
        n.add_record(cp).value = n_python[cp]

    u_python = {}
    for course in courses:
        u_python[str(course.num)] = int(course.is_3_units())
#    print("u:", u_python)
    u = db.add_parameter_dc("u", [c])
    for cp in c_python:
        u.add_record(cp).value = u_python[cp]

    s_python = {}
    for record in groups:
        s_python[record[1], record[2]] = 1
#    print("s:", s_python)
    s = db.add_parameter_dc("s", [j, c])
    for jp in j_python:
        for cp in c_python:
            if (jp, cp) in s_python:
                s.add_record((jp, cp)).value = s_python[(jp, cp)]

    a_python = {}
    for course in courses:
        a_python[str(course.num), str(course.lecturer_num)] = 1
#    print("a:", a_python)
    a = db.add_parameter_dc("a", [c, l])
    for cp in c_python:
        for lp in l_python:
            if (cp, lp) in a_python:
                a.add_record((cp, lp)).value = a_python[(cp, lp)]

    b_python = {}
    for lecturer in lecturers:
        for date in lecturer.availabe_dates:
            b_python[str(lecturer.num), str(date.day.value), str(date.period_num)] = 1
#    print("b:", b_python)
    b = db.add_parameter_dc("b", [l, d, h])
    for lp in l_python:
        for dp in d_python:
            for hp in h_python:
                if (lp, dp, hp) in b_python:
                    b.add_record((lp, dp, hp)).value = b_python[(lp, dp, hp)]

    f_python = {"3": 1, "8": 1}
#    print("f:", f_python)
    f = db.add_parameter_dc("f", [h])
    for hp in h_python:
        if (hp) in f_python:
            f.add_record(hp).value = f_python[hp]

    g_python = {}
    for period in periods:
        val = 0
        if period.is_2_hours() == False:
            val = 1
        g_python[str(period.num)] = val
#    print("g:", g_python)
    g = db.add_parameter_dc("g", [h])
    for hp in h_python:
        g.add_record(hp).value = g_python[hp]

    t_python = {}
    for p1 in periods:
        for p2 in periods:
            if p1.has_intersec_with(p2):
                t_python[str(p1.num), str(p2.num)] = 1
#    print("t:", t_python)
    t = db.add_parameter_dc("t", [h, h])
    for hp in h_python:
        for hp1 in h_python:
            if hp != hp1:
                if (hp, hp1) in t_python:
                    t.add_record((hp, hp1)).value = t_python[(hp, hp1)]

    M_python = len(d_python) * len(h_python)
#    print("M:", M_python)
    M = db.add_parameter("M", 0)
    M.add_record().value = M_python

    return db

def run_model():
    opt = ws.add_options()
    opt.defines["gdxincname"] = db.name
    m = ws.add_job_from_file("CourseTimetabling02.gms")
    m.run(opt, databases=db)
    return m

def show_output_data(m):
    var_z1 = [rec.level for rec in m.out_db["z1"]]
    print("z1: ", int(var_z1[0]), "\n")

    var_z2 = [rec.level for rec in m.out_db["z2"]]
    print("z2: ", int(var_z2[0]), "\n")

    var_z3 = [rec.level for rec in m.out_db["z3"]]
    print("z3: ", int(var_z3[0]), "\n")

    results = []
    for rec in m.out_db["delta"]:
        if int(rec.level) != 0:
            results.append((rec.key(0), rec.key(1), rec.key(2)))

    return results

def set_courses_dates(results, courses):
    for result in results:
        index = Course.get_index_of_num(int(result[0]), courses)
        day = Day.get_day_with_value(int(result[1]))
        courses[index].insert_date(day, result[2])

def show_results(courses, periods):
    print("Weekly Schedule:")
    for course in courses:
        print(course.num, end=": ")
        for date in course.scheduled_dates:
            day = date.day.get_string()
            period_index = Period.get_index_of_num(int(date.period_num), periods)
            print(day, periods[period_index].get_string(), end=",    ")
        print()

dataset = input("Dataset Name:")

periods = []
periods.append(Period(1, 8, 10))
periods.append(Period(2, 10, 12))
periods.append(Period(3, 13, 15))
periods.append(Period(4, 15, 17))
periods.append(Period(5, 7.45, 9.15))
periods.append(Period(6, 9.15, 10.45))
periods.append(Period(7, 10.45, 12.15))
periods.append(Period(8, 13.30, 15))
periods.append(Period(9, 15, 16.30))

courses = Course.create_courses(dataset + "/Sheet 1.csv")
lecturers = Lecturer.create_lecturers(dataset + "/Sheet 2.csv")
Course.set_lecturers(dataset + "/Sheet 3.csv", courses)
faculty = Faculty.create_faculty(dataset + "/Sheet 5.csv")
groups = FileManager.read_from_csv(dataset + "/Sheet 4.csv")

db = set_input_data(courses, lecturers, periods, faculty, groups)
m = run_model()
results = show_output_data(m)
set_courses_dates(results, courses)

show_results(courses, periods)