import googlemaps
import os

def get_place_by_postal_code(postal_code):
    gmaps = googlemaps.Client(key=os.environ["GOOGLE_PLACES_API"])
    results = gmaps.geocode(address=postal_code, components={"country": "BR"})
    if results:
        geocode_result = results[0]
        return adapt_result(geocode_result)

    return None

def adapt_result(geocode_result):
    address_components = geocode_result.get("address_components", {})
    place = {}
    types = {
        "postal_code": "postal_code",
        "route": "street",
        "sublocality": "neighbourhood",
        "administrative_area_level_2": "city",
        "administrative_area_level_1": "federal_unity",
    }
    location = geocode_result.get("geometry", {}).get("location", {})
    place["latitude"] = location.get("lat")
    place["longitude"] = location.get("lng")
    place["places_id"] = geocode_result.get("place_id")
    for address_component in address_components:
        long_name = address_component.get("long_name")
        short_name = address_component.get("short_name")
        for key, value in types.items():
            if key in address_component.get("types"):
                place[value] = {"long_name": long_name, "short_name": short_name}
                del types[key]
                break

    return place


import numpy.random as random

from network import Network

class Communication():
    """
    1回の通信を管理するオブジェクト。
    """
    def __init__(self, network: Network, s_node: int, e_node: int, service_time: int = 1, arrival_interval: int = 1) -> None:
        """
        コンストラクタ。

        引数
        - network: ネットワーク
        - s_node: 開始ノード
        - e_node: 終了ノード
        - service_time: 通信時間（初期値は1）
        - arrival_interval: 通信の到着間隔（初期値は1）
        """
        self.s_node = s_node
        self.e_node = e_node
        self.network = network
        self.path = []
        self.service_time = service_time
        self.arrival_interval = arrival_interval
        self.is_communicating = False

    def __getmetric_distribution(self, average: int) -> int:
        return random.geometric(1 / average)

    def set_service_time_by_geometric_distribution(self, average: int = 1) -> None:
        """
        幾何分布に従う通信時間を設定する。

        引数
        - average: 平均（初期値は1）
        """
        self.service_time = self.__getmetric_distribution(average)

    def set_arrival_interval_by_geometric_distribution(self, average: int = 1) -> None:
        """
        幾何分布に従う通信の到着間隔を設定する。

        引数
        - average: 平均（初期値は1）
        """
        self.arrival_interval = self.__getmetric_distribution(average)

    def get_service_time(self) -> int:
        """
        通信時間を返す。
        """
        return self.service_time

    def get_arrival_interval(self) -> int:
        """
        通信の到着間隔を返す。
        """
        return self.arrival_interval

    def get_path(self) -> list:
        """
        経路を返す。
        """
        return self.path

    def set_path_by(self, algorithm: int) -> list:
        """
        経路を設定する。

        引数
        - algorithm: 経路の決定方法
            - 1: 最小ホップ経路を用いた固定経路
            - 2: 最大路を用いた固定経路
            - 3: 最小ホップ経路を用いた要求時経路
            - 4: 最大路を用いた要求時経路
            - 5: 最短最大路を用いた固定経路
            - 6: 最短最大路を用いた要求時経路
        """
        if algorithm == 1:
            self.path = self.network.shortest_path_between(self.s_node, self.e_node, self.network.get())
        elif algorithm == 2:
            self.path = self.network.widest_path_between(self.s_node, self.e_node, self.network.get())
        elif algorithm == 3:
            self.path = self.network.shortest_path_between(self.s_node, self.e_node, self.network.get_current())
        elif algorithm == 4:
            self.path = self.network.widest_path_between(self.s_node, self.e_node, self.network.get_current())
        elif algorithm == 5:
            self.path = self.network.shortest_widest_path_between(self.s_node, self.e_node, self.network.get())
        elif algorithm == 6:
            self.path = self.network.shortest_widest_path_between(self.s_node, self.e_node, self.network.get_current())
        else:
            raise Exception("algorithmの値が不正です。")

    def start(self) -> bool:
        """
        通信の開始。もし容量があれば容量を1減らし、Trueを返す。
        """
        if self.is_communicating:
            raise Exception("通信中です。")

        if self.network.start(self.path):
            self.is_communicating = True
            return True
        else:
            return False

    def end(self) -> None:
        """
        通信の終了。容量を増やす。
        """
        if not self.is_communicating:
            raise Exception("通信が開始されていません。")

        self.is_communicating = False
        self.network.end(self.path)

if __name__ == "__main__":
    network = Network()
    s_node, e_node = network.random_two_nodes()
    communication = Communication(network, s_node, e_node)
    communication.set_path_by(1)
    print(f"path: {communication.get_path()}")
    communication.start()
    communication.end()


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from IPython.display import clear_output

class MountainCar:
    def __init__(self, position_min=-1.2, position_max=0.5, velocity_min=-0.07, velocity_max=0.07):
        self.position_min = position_min
        self.position_max = position_max
        self.velocity_min = velocity_min
        self.velocity_max = velocity_max

        self.actions = np.array([-1, 0, 1])
        self.reset()

    def reset(self):
        self.game_over = False
        self.position = np.random.uniform(low=self.position_min, high=self.position_max)
        self.velocity = np.random.uniform(low=self.velocity_min, high=self.velocity_max)

    def make_step(self, action):
        """Given an action, move the car.

        Makes sure that position and velocity stay within specified bounds.
        Updates self.game_over if the right position bound is reached.

        @param action: an integer representing one of three actions
            -1 = full throttle reverse
             0 = zero throttle
             1 = full throttle forward

        @return reward: a float always valuing -1

        """
        if action not in self.actions:
            raise ValueError("The action value (", action, ") should be one of", self.actions)
        self.game_over = False
        self.velocity = self.velocity + 0.001 * action - 0.0025 * np.cos(3 * self.position)
        self.velocity = np.clip(self.velocity, a_min=self.velocity_min, a_max=self.velocity_max)

        self.position = self.position + self.velocity
        self.position = np.clip(self.position, a_min=self.position_min, a_max=self.position_max)
        if self.position == self.position_min:
            self.velocity = 0
        if self.position == self.position_max:
            self.game_over = True
        reward = -1.0
        return reward

    def plot(self, clear_the_output=True):
        if clear_the_output:
            clear_output(wait=True)

        fig, ax = plt.subplots()
        ax.axis([self.position_min, self.position_max, -1.1, 1.1])
        ax.set_aspect('equal', adjustable='box')
        ax.grid(False)  # disable the grid
        xes = np.linspace(start=-1.2, stop=0.5, num=120)
        ys = np.sin(3 * xes)
        # Plot mountain
        ax.plot(xes, ys)
        # Plot "car"
        p = mpatches.Circle((self.position, np.sin(3 * self.position)), 0.05, color="red")
        ax.add_patch(p)
        plt.show()


import numpy as np
#from skdata.mnist.views import OfficialImageClassification
from matplotlib import pyplot as plt
from tsne import bh_sne
from load import mnist

# load up data
#data = OfficialImageClassification(x_dtype="float32")
trX, teX, trY, teY = mnist(onehot=True)
x_data = trX
y_data = trY

print(len(x_data))
print(len(y_data))

# convert image data to float64 matrix. float64 is need for bh_sne
x_data = np.asarray(x_data).astype('float64')
x_data = x_data.reshape((x_data.shape[0], -1))

# For speed of computation, only run on a subset
n = 5000
x_data = x_data[:n]
y_data = y_data[:n]

# perform t-SNE embedding
vis_data = bh_sne(x_data)

# plot the result
vis_x = vis_data[:, 0]
vis_y = vis_data[:, 1]

# convert labels
labels = []
for arr in y_data:
    labels.append(np.argmax(arr))

plt.scatter(vis_x, vis_y, c=labels, cmap=plt.cm.get_cmap("jet", 10))

#plt.scatter(vis_x, vis_y, 20, labels)
plt.colorbar(ticks=range(10))
plt.clim(-0.5, 9.5)
plt.savefig("tsne5k")


import os
import tempfile
import sys
from global_functions.appConstant import content_persona_ai_drive_url
from global_functions.Enums import EnumContentRowStates
from global_functions.send_to_db import get_content_list_by_content_id, get_content_list_by_state, update_content_rowState
from services.duplicate import remove_duplicate_similar_frames
from services.file import move_extracted_frames, read_integer
from services.video import extract_frames, open_video

def main(threshold_value):
    while True:
        # Create a temporary directory to work with
        with tempfile.TemporaryDirectory() as tmp_dir:
            # Fetch content information from the database
            target_row_state_wfa = EnumContentRowStates.WaitingForAnalysis.value
            wfa_content_list = get_content_list_by_state(target_row_state_wfa)
            if wfa_content_list:
                content = wfa_content_list[0]
                content_id = content.ID
                starting_frame = 0
                # Build the input video path
                input_path = content_persona_ai_drive_url + content.RELATED_URL
                # Open the video file
                video = open_video(input_path)
                # Update the content row state to indicate splitting is in progress
                target_row_state_split = EnumContentRowStates.Splitting.value
                update_content_rowState(content.ID, target_row_state_split)
                # Extract frames from the video
                extract_frames(video, tmp_dir, content_id, starting_frame)
                video.release()  # Release the video file
                # Build the output folder path
                movie_dir = os.path.dirname(input_path)
                output_folder_path = os.path.join(movie_dir, "frames")
                # Remove duplicated and similar frames
                remove_duplicate_similar_frames(output_folder_path, tmp_dir, threshold_value)
                # Move extracted frames to the final folder
                move_extracted_frames(tmp_dir, output_folder_path)
                # Update the content row state to indicate splitting is complete
                target_row_state_splitted = EnumContentRowStates.Splitted.value
                update_content_rowState(content_id, target_row_state_splitted)

if __name__ == "__main__":
    print(sys.argv)
    if len(sys.argv) != 2:
        # Print usage instructions if incorrect number of arguments provided
        print("Usage: python main.py threshold_value")
    else:
        # Convert command-line arguments to appropriate data types
        threshold_value = int(sys.argv[1])
        # Call the main function with the provided arguments
        main(threshold_value)


# -- import packages: -------------------------------------------------------
import os
from tqdm.notebook import tqdm

# -- import local dependencies: ---------------------------------------------
from . import _scanpy_funcs as funcs
from ._format_scanpy_results import format_scanpy_results
from ... import _tools as tl

def _n_cells(adata):
    return adata.shape[0]

def _run_scanpy_traced(adata):

    adata_ = adata.copy()

    run_scanpy = funcs.TracedScanpy()
    run_scanpy(adata=adata_)
    resource_df = run_scanpy.outs[1]

    return run_scanpy, resource_df

# -- API-facing exe and collection of results: ------------------------------
def run_scanpy(adata,
               n_iters=5,
               method_dir="./scanpy_benchmark_results",
               dataset="unspecified_dataset",
               n_cells=None,
               parent_path=os.getcwd(),
               debug=False,
             ):

    outs = {}

    if not n_cells:
        n_cells = _n_cells(adata)

    for i in tqdm(range(n_iters)):
        filename = tl.mk_save_path(method_dir, dataset, ext=".zip")
        run_outs = _run_scanpy_traced(adata)
        if debug:
            return run_outs
        outs[i] = format_scanpy_results(run = run_outs,
                              save_filename = filename,
                              dataset = dataset,
                              n_cells = n_cells,
                              run_iter = i,
                              return_saved_outs=True
                             )

    return outs


import argparse
import base64
import os
import time
from typing import Dict
from typing import List
from typing import Union

import cv2
import numpy as np
import paddle
import paddle.vision.transforms as transforms
from paddlenlp.transformers.clip.tokenizer import CLIPTokenizer

import paddlehub as hub
from . import models
from paddlehub.module.module import moduleinfo
from paddlehub.module.module import runnable
from paddlehub.module.module import serving

def cv2_to_base64(image):
    data = cv2.imencode('.jpg', image)[1]
    return base64.b64encode(data.tobytes()).decode('utf8')

def base64_to_cv2(b64str):
    data = base64.b64decode(b64str.encode('utf8'))
    data = np.frombuffer(data, np.uint8)
    data = cv2.imdecode(data, cv2.IMREAD_COLOR)
    return data

@moduleinfo(
    name='lseg',
    version='1.0.0',
    type="CV/semantic_segmentation",
    author="",
    author_email="",
    summary="Language-driven Semantic Segmentation.",
)
class LSeg(models.LSeg):

    def __init__(self):
        super(LSeg, self).__init__()
        self.default_pretrained_model_path = os.path.join(self.directory, 'ckpts', 'LSeg.pdparams')
        state_dict = paddle.load(self.default_pretrained_model_path)
        self.set_state_dict(state_dict)
        self.eval()
        self.transforms = transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5]),
        ])
        self.tokenizer = CLIPTokenizer.from_pretrained('openai/clip-vit-base-patch32')

        self.language_recognition = hub.Module(name='baidu_language_recognition')
        self.translate = hub.Module(name='baidu_translate')

    @staticmethod
    def get_colormap(n):
        assert n <= 256, "num_class should be less than 256."

        pallete = [0] * (256 * 3)

        for j in range(0, n):
            lab = j
            pallete[j * 3 + 0] = 0
            pallete[j * 3 + 1] = 0
            pallete[j * 3 + 2] = 0
            i = 0
            while (lab > 0):
                pallete[j * 3 + 0] |= (((lab >> 0) & 1) << (7 - i))
                pallete[j * 3 + 1] |= (((lab >> 1) & 1) << (7 - i))
                pallete[j * 3 + 2] |= (((lab >> 2) & 1) << (7 - i))
                i = i + 1
                lab >>= 3

        return np.asarray(pallete, dtype=np.uint8).reshape(256, 1, 3)

    def segment(self,
                image: Union[str, np.ndarray],
                labels: Union[str, List[str]],
                visualization: bool = False,
                output_dir: str = 'lseg_output') -> Dict[str, Union[np.ndarray, Dict[str, np.ndarray]]]:
        if isinstance(image, str):
            image = cv2.imread(image)
        elif isinstance(image, np.ndarray):
            image = image
        else:
            raise Exception("image should be a str / np.ndarray")

        if isinstance(labels, str):
            labels = [labels, 'other']
            print('"other" category label is automatically added because the length of labels is equal to 1')
            print('new labels: ', labels)
        elif isinstance(labels, list):
            if len(labels) == 1:
                labels.append('other')
                print('"other" category label is automatically added because the length of labels is equal to 1')
                print('new labels: ', labels)
            elif len(labels) == 0:
                raise Exception("labels should not be empty.")
        else:
            raise Exception("labels should be a str or list.")

        class_num = len(labels)

        labels_ = list(set(labels))
        labels_.sort(key=labels.index)
        labels = labels_

        input_labels = []
        for label in labels:
            from_lang = self.language_recognition.recognize(query=label)
            if from_lang != 'en':
                label = self.translate.translate(query=label, from_lang=from_lang, to_lang='en')
            input_labels.append(label)

        labels_dict = {k: v for k, v in zip(input_labels, labels)}

        input_labels_ = list(set(input_labels))
        input_labels_.sort(key=input_labels.index)
        input_labels = input_labels_

        labels = []
        for input_label in input_labels:
            labels.append(labels_dict[input_label])

        if len(labels) < class_num:
            print('remove the same labels...')
            print('new labels: ', labels)

        h, w = image.shape[:2]
        image = image[:-(h % 32) if h % 32 else None, :-(w % 32) if w % 32 else None]
        images = self.transforms(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)).unsqueeze(0)
        texts = self.tokenizer(input_labels, padding=True, return_tensors="pd")['input_ids']

        with paddle.no_grad():
            results = self.forward(images, texts)
            results = paddle.argmax(results, 1).cast(paddle.uint8)
            gray_seg = results.numpy()[0]

        colormap = self.get_colormap(len(labels))
        color_seg = cv2.applyColorMap(gray_seg, colormap)
        mix_seg = cv2.addWeighted(image, 0.5, color_seg, 0.5, 0.0)

        classes_seg = {}
        for i, label in enumerate(labels):
            mask = ((gray_seg == i).astype('uint8') * 255)[..., None]
            classes_seg[label] = np.concatenate([image, mask], 2)

        if visualization:
            save_dir = os.path.join(output_dir, str(int(time.time())))
            if not os.path.isdir(save_dir):
                os.makedirs(save_dir)
            for label, dst in classes_seg.items():
                cv2.imwrite(os.path.join(save_dir, '%s.png' % label), dst)

        return {'gray': gray_seg, 'color': color_seg, 'mix': mix_seg, 'classes': classes_seg}

    @runnable
    def run_cmd(self, argvs):
        """
        Run as a command.
        """
        self.parser = argparse.ArgumentParser(description="Run the {} module.".format(self.name),
                                              prog='hub run {}'.format(self.name),
                                              usage='%(prog)s',
                                              add_help=True)
        self.parser.add_argument('--input_path', type=str, help="path to image.")
        self.parser.add_argument('--labels', type=str, nargs='+', help="segmentation labels.")
        self.parser.add_argument('--output_dir',
                                 type=str,
                                 default='lseg_output',
                                 help="The directory to save output images.")
        args = self.parser.parse_args(argvs)
        self.segment(image=args.input_path, labels=args.labels, visualization=True, output_dir=args.output_dir)
        return 'segmentation results are saved in %s' % args.output_dir

    @serving
    def serving_method(self, image, **kwargs):
        """
        Run as a service.
        """
        image = base64_to_cv2(image)
        results = self.segment(image=image, **kwargs)

        return {
            'gray': cv2_to_base64(results['gray']),
            'color': cv2_to_base64(results['color']),
            'mix': cv2_to_base64(results['mix']),
            'classes': {k: cv2_to_base64(v)
                        for k, v in results['classes'].items()}
        }


import openai
from openai.error import RateLimitError
from time import sleep
import numpy as np
import os, json
from .RedisUtil import RedisUtil
from redis import Redis
from redis.commands.search.query import Query
from redis.commands.search.result import Result
from langchain.docstore.document import Document
from langchain.chains.qa_with_sources import load_qa_with_sources_chain
from langchain.llms import AzureOpenAI

class DocumentEmbedding:
    def __init__(self, document_embedding_deployment_name, \
                 query_embedding_deployment_name, \
                 summerization_deployment_name, \
                 vector_field_name='vector', \
                 qa_chain_type = 'map_rerank') -> None:
        openai.api_type = "azure"
        openai.api_key = os.getenv("OPENAI_API_KEY")
        openai.api_base = os.getenv("OPENAI_API_BASE")
        openai.api_version = os.getenv("OPENAI_API_VERSION") #openai api version m
        self.document_embedding_deployment_name = os.getenv("DOCUMENT_MODEL_NAME")
        self.query_embedding_deployment_name =os.getenv("QUERY_MODEL_NAME")
        self.summerization_deployment_name = os.getenv("DEPLOYMENT_NAME")
        self.vector_field_name = vector_field_name
        self.qa_chain_type = qa_chain_type
        self.documents = []
        self.redis=None

    def get_embedding(self, text: str, engine: str, tobytes=True):
        while True:
            try:
                embedding = openai.Embedding().create(input=[text], engine=engine)["data"][0]["embedding"]
                break;
            except RateLimitError:
                sleep(2)
        if tobytes:
            return np.array(embedding).astype(np.float32).tobytes()
        else:
            return embedding

    def build_redis_index(self):
        if self.redis is None:
            self.redis = RedisUtil(vector_field_name=self.vector_field_name,number_of_vectors=len(self.documents))
            self.redis.redis_conn.flushall()
            self.redis.create_flat_index()
        self.redis.load_vectors(self.documents)

    def convert_redis_query_result_to_document(self, query_results):
        docs = []
        for r in query_results:
            source = r.document_name + ":"+str(r.page_number)
            docs.append(Document(page_content=r.page_text,lookup_str="", metadata={"source":source}))
        return docs

    def query(self, query_text:str, topK=5):
        if self.redis is not None:
            query_vector = self.get_embedding(query_text, engine=self.query_embedding_deployment_name)
            #prepare the query
            q = Query(f'*=>[KNN {topK} @{self.vector_field_name} $vec_param AS vector_score]').\
                        sort_by('vector_score').\
                        paging(0,topK).\
                        return_fields('vector_score','document_name','page_number','page_text').\
                        dialect(2)
            params_dict = {"vec_param": query_vector}

            #Execute the query
            query_results = self.redis.redis_conn.ft().search(q, query_params = params_dict)
            print(query_results)

            # Convert results to Document type in langchain
            docs = self.convert_redis_query_result_to_document(query_results.docs)
            print(docs)

            # Call qna_source_chain
            chain = load_qa_with_sources_chain(AzureOpenAI(temperature=0, deployment_name=self.summerization_deployment_name), \
                                               chain_type=self.qa_chain_type, \
                                               metadata_keys=['source'], \
                                               return_intermediate_steps=True)
            results = chain({"input_documents": docs, "question": query_text}, return_only_outputs=False)
            #Print similar products found
            # for r in results.docs:
            #     print("Score: ", r.vector_score, " "* 5, "Document Name: ", r.document_name, " "*5, "Page Number: ", r.page_number)
            #     print("  Text: ", r.page_text)
        else:
            results=""
        return results

    def load_documents(self, source_folder: str, use_redis:bool=True, verbose:bool=True):
        tobytes = True if use_redis else False

        for file in os.listdir(source_folder):
            if verbose:
                print('\n\nLoading file:', file)
            with open(os.path.join(source_folder, file)) as f:
                page_content= json.loads(f.read())
            self.documents.extend([{'document_key':page_content['filename'].split('/')[-1] + '-' + str(page['page_number']),\
                                'document_name':page_content['filename'].split('/')[-1],\
                                'file_path':page_content['filename'],\
                                'page_number': page['page_number'],\
                                'page_text': page['page_content'],\
                                self.vector_field_name: self.get_embedding(page['page_content'], \
                                                                           self.document_embedding_deployment_name, \
                                                                           tobytes=tobytes) } \
                                for page in page_content['content'] ])
        if use_redis:
            self.build_redis_index()

    def add_document_embedding(self, tobytes=True):
        assert self.documents is not None, 'No documents to process.'
        # for item in self.documents:
        #     item[self.vector_field_name] = self.get_embedding(item['page_text'], tobytes=tobytes)


arr = []
arr.apend(list(map(int,input().split())))
max = 0
a= 0
b = 0
for i in range(9):
    for j in range(9):
        if(max <= arr[i][j]):
            max = arr[i][j]
            a = i+1
            b = j+1

print(max)
print(a, b)


# 18870 좌표 압축
# https://www.acmicpc.net/problem/18870

N = int(input())
spots = list(map(int, input().split()))

# 시간초과
# for i in range(N):
#     cnt = 0
#     for j in range(N):
#         # i번째 원소보다 작고,
#         # 현재 j번째 원소가 j번째 이전에 안나왔으면 (즉 중복 제거)
#         if spots[i] > spots[j] and spots[j] not in spots[:j]:
#             cnt += 1
#     ans.append(cnt)

# 중복제거후 오름차순 정렬을 하면 인덱스가 갯수가 된다
s_list = sorted(set(spots), reverse=False)
dic = {s_list[i] : i for i in range(len(s_list))}

for i in spots:
    print(dic[i], end=" ")


# tsja: an attempt to a SmartGrid solution
# Dirk Kuiper (12416657) & Lars Zwaan (12414069)
# part of Programmeertheorie, Minor Programmeren, UvA
# output draws a visual representation and produces a .json

import matplotlib.pyplot as plt
import numpy as np
import json
import pandas as pd

from classes.house import House
from classes.battery import Battery
from classes.cable import Cable

# find the total cable length of a certain house-battery configuration
def find_cable_length():

    cable_length = 0

    for cab in Cable._registry:
        cable_length += cab.length

    return cable_length

# draw a visualisation of the grid, all battery networks in 1 plot
def draw_all_plot(DISTRICT, CONFIG, SWITCH):

    fig, ax = plt.subplots()
    ax.set_title("District: {}, Total shared cable length:{}".format(DISTRICT, find_cable_length()))

    # some nice ticks and grid etc
    ax.set(xlim=(-5, 55), xticks=np.arange(0, 51, 5),
           ylim=(-5, 55), yticks=np.arange(0, 51, 5))
    ax.minorticks_on()
    ax.grid(which='both')

    # makes grid a nice square to give proper idea of distances
    ax.set_aspect("equal")

    bat_coords = [[], []]
    hou_coords = [[], []]

    # gather coords of all object instances and format in scatterable way
    for hou in House._registry:
        hou_coords[0].append(hou.x)
        hou_coords[1].append(hou.y)

    for bat in Battery._registry:
        bat_coords[0].append(bat.x)
        bat_coords[1].append(bat.y)

    ax.scatter(bat_coords[0], bat_coords[1], c='red', label="batteries")
    ax.scatter(hou_coords[0], hou_coords[1], c='blue', label="houses")

    for cab in Cable._registry:
        ax.plot(cab.x_coords, cab.y_coords, c='green')

    ax.legend()
    plt.savefig('output/plots/{}_all_{}_{}.png'.format(DISTRICT, CONFIG, SWITCH))

    return

# draw a visualisation of the grid, repeated for each battery network
def draw_rep_plot(DISTRICT, CONFIG, SWITCH):

    bat_coords = [[], []]
    for bat in Battery._registry:
        bat_coords[0].append(bat.x)
        bat_coords[1].append(bat.y)

    hou_coords = [[], []]
    for hou in House._registry:
        hou_coords[0].append(hou.x)
        hou_coords[1].append(hou.y)

    # gather coords of all object instances and format in scatterable way
    batnet = 0
    for bat in Battery._registry:
        batnet += 1
        fig, ax = plt.subplots()

        # some nice ticks and grid etc
        ax.set(xlim=(-5, 55), xticks=np.arange(0, 51, 5),
               ylim=(-5, 55), yticks=np.arange(0, 51, 5))
        ax.minorticks_on()
        ax.grid(which='both')

        # makes grid a nice square to give proper idea of distances
        ax.set_aspect("equal")

        ax.set_title("District: {}, Total shared cable length:{}".format(DISTRICT, find_cable_length()))

        ax.scatter(bat_coords[0], bat_coords[1], c='red', label="batteries")
        ax.scatter(hou_coords[0], hou_coords[1], c='blue', label="houses")

        # this doesnt work anymore as bat has wrong cables somehow
        for cab in bat.cables:
            ax.plot(cab.x_coords, cab.y_coords, c='green')

        ax.legend()
        plt.savefig('output/plots/{}_rep{}_{}_{}.png'.format(DISTRICT, batnet, CONFIG, SWITCH))

    return

# output a json file in the specified format to use check50
def make_json(DISTRICT):
    # some constants that might differ later
    battery_price = 5000
    cable_price = 9
    number_batteries = 5
    costs_shared = (number_batteries * battery_price +
                    find_cable_length() * cable_price)

    # create a list that will be outputted to jason, made of dicts
    output = []

    # a subdict for general info
    general_dict = dict()
    general_dict["costs-shared"] = costs_shared
    general_dict["district"] = DISTRICT

    output.append(general_dict)

    # a subdict for each battery
    for bat in Battery._registry:
        bat_dict = dict()
        bat_dict["location"] = "{},{}".format(bat.x, bat.y)
        bat_dict["capacity"] = bat.capacity

        all_hou_list = []
        # a subdict for each house
        for hou in bat.connected_to:
            hou_dict = dict()

            hou_dict["location"] = "{},{}".format(hou.x, hou.y)
            hou_dict["output"] = hou.maxoutput

            cable_list = []

            # at each cable segment coordinate as a line to the cable dict
            for cable_idx in range(hou.cable.length):
                x = hou.cable.x_coords[cable_idx]
                y = hou.cable.y_coords[cable_idx]
                cable_list.append("{},{}".format(x, y))

            hou_dict["cables"] = cable_list
            all_hou_list.append(hou_dict)

        bat_dict["houses"] = all_hou_list
        output.append(bat_dict)

    with open('output/output.json', 'w') as fp:
        json.dump(output, fp)

    return

# recreate all house, battery and cable objects from the best saved json
def jason_remakes():

    # reset registry's; load new ones from output.json
    Cable._registry = []
    House._registry = []
    Battery._registry = []

    with open('output/output.json', 'r') as fp:
        data = json.load(fp)

    for bat in data[1:]:

        x = int(bat['location'].split(',')[0])
        y = int(bat['location'].split(',')[1])
        cap = bat['capacity']

        # note: dont add actual id here but guess we dont need it here anymore
        battery = Battery(0, x, y, cap)

        for hou in bat['houses']:
            x = int(hou['location'].split(',')[0])
            y = int(hou['location'].split(',')[1])
            maxoutput = hou['output']

            x_coords = []
            y_coords = []
            for cabpoint in hou['cables']:
                x_coords.append(int(cabpoint.split(',')[0]))
                y_coords.append(int(cabpoint.split(',')[1]))

            cable = Cable(x_coords, y_coords, len(x_coords))

            # note: dont add actual id here but guess we dont need it here anymore
            house = House(0, x, y, maxoutput, cable)

            battery.connected_to.append(house)
            battery.cables.append(cable)

    return

# make a csv file of all lengths to later make a histogram
def length_csv(lengths):
    dict = {'length': lengths}
    df = pd.DataFrame(dict)
    df.to_csv('output/lengths.csv', index=False)

    return

# make a histogram of all total cable lengths from the saved csv
def csv_hist(DISTRICT, CONFIG, SWITCH, number_options):

    df = pd.read_csv('output/lengths.csv')
    df.plot(kind='hist',
            bins=int(number_options / 10),
            title='Histogram of cable lengths of district: {},'
                ' attempts: {}'.format(DISTRICT, number_options))
    plt.xlabel('Total cable length')
    plt.ylabel("Frequency")
    plt.savefig('output/plots/{}_hist_{}_{}.png'.format(DISTRICT, CONFIG, SWITCH))

    return


import time
import numpy as np
import tensorflow as tf
import reader

class PTBInput(object):

    def __init__(self, config, data, name=None):
        #number of batches
        self.batch_size = batch_size = config.batch_size
        self.num_step = num_steps = config.num_steps
        #number of epochs each batch
        self.epoch_size = ((len(data) // batch_size) - 1) // num_steps
        self.input_data, self.targets = reader.ptb_producer(
            data, batch_size, num_steps, name=name
        )

class PTBModel(object):

    def __init__(self, is_training, config, input_):
        self._input = input_

        batch_size = input_.batch_size
        num_steps = input_.num_steps#几个LSTM cells
        size = config.hidden_size#一个LSTM cell输入X的维度
        vocab_size = config.vocab_size
        def lstm_cell():
            return tf.contrib.rnn.BasicLSTMCell(
                size, forget_bias = 0.0, state_is_tuple = True
            )
        attn_cell = lstm_cell
        if is_training and config.keep_prob < 1:
            def attn_cell():
                return tf.contrib.rnn.DropoutWrapper(
                    lstm_cell(), output_keep_prob = config.keep_prob
                )

        cell = tf.contrib.rnn.MultiRNNCell(
            [attn_cell() for _ in range(config.num_layers)],
            state_is_tuple=True
        )

        self._initial_state = cell.zero_state(batch_size, tf.float32)

        with tf.device('/cpu:0'):
            embedding = tf.get_variable(
                "embedding", [vocab_size, size], dtype=tf.float32
            )
            inputs = tf.nn.embedding_lookup(embedding, input_.input_data)

        if is_training and config.keep_prob < 1:
            inputs = tf.nn.dropout(inputs, config.keep_prob)

        outputs = []
        state = self._initial_state
        with tf.variable_scope("RNN"):
            for time_step in range(num_steps):
                if time_step > 0:
                    tf.get_variable_scope().reuse_variables()
                #state_is_tuple = TRUE
                #inputs[batch里的第几个sample,第几个word,word的第几维]
                (cell_output, state) = cell(inputs[:, time_step, :], state)
                outputs.append(cell_output)

        output = tf.reshape(tf.concat(outputs, 1), [-1, size])#num_steps * size
        softmax_w = tf.get_variable(
            "softmax_x", [size, vocab_size], dtype=tf.float32
        )

        softmax_b = tf.get_variable("softmax_b", [vocab_size], dtype=tf.float32)

        logits = tf.matmul(output, softmax_w) + softmax_b
        loss = tf.contrib.legacy_seq2seq.seqence_loss_by_example(
            [logits],
            [tf.reshape(input_.targets, [-1])],
            [tf.ones([batch_size * num_steps], dtype=tf.float32)]
        )
        self._cost = cost = tf.reduce_sum(loss) / batch_size
        self._final_state = state

        if not is_training:
            return

        self._lr = tf.Variable(0.0, trainable=False)
        tvars = tf.trainable_variables()


import tensorflow as tf
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from process_data import *
import pandas as pd

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'  # or any {'0', '1', '2'}

class WindowGenerator():
    def __init__(self, input_width, label_width, shift, voice_number, batch_size=32,
                 label_columns=None, use_features=True, shuffle=True):
        self.batch_size = batch_size
        # load all input and teacher values
        self.dat, self.shift_conversion_key = extract_features(voice_number=voice_number)

        self.feature_names = ["log_pitch","chroma_x", "chroma_y", "c5_x", "c5_y"]
        self.one_hot_names = []
        for i in range(len(self.shift_conversion_key)):
            self.one_hot_names.append("shift_%d" % i)

        self.column_names = self.feature_names + self.one_hot_names

        self.df = pd.DataFrame(data = self.dat, dtype=float, columns=self.column_names)
#         # Normalise features
#         self.mean_df = self.df.iloc[:, :5].mean()
#         self.std_df = self.df.iloc[:, :5].std()
#         self.df.iloc[:, :5] = (
#             self.df.iloc[:, :5] - self.mean_df) / self.std_df

        labels_all = list(self.df.columns)
        self.label_columns = labels_all[5:]

        # Work out the label column indices.
        if self.label_columns is not None:
            self.label_columns_indices = {
                name: i for i, name in enumerate(self.label_columns)}

        self.column_indices = {name: i for i,
                               name in enumerate(self.df.columns)}

        # split the data
        n = len(self.df)
        self.train_df = self.df[0:int(n*0.7)]  # train split 70% of data
        self.val_df = self.df[int(n*0.7):int(n*0.9)]  # validation split 20% of data
        self.test_df = self.df[int(n*0.9):]  # test split 10% of data

        # normalise data
        self.mean_train = self.train_df.iloc[:,:5].mean()
        self.std_train = self.train_df.iloc[:,:5].std()

        self.train_df.iloc[:,:5] = (self.train_df.iloc[:,:5] - self.mean_train) / self.std_train
        self.val_df.iloc[:,:5] = (self.val_df.iloc[:,:5] - self.mean_train) / self.std_train
        self.test_df.iloc[:,:5] = (self.test_df.iloc[:,:5] - self.mean_train) / self.std_train

        # Work out the window parameters.
        self.input_width = input_width
        self.label_width = label_width
        self.shift = shift

        self.total_window_size = input_width + shift

        self.input_slice = slice(0, input_width)
        # self.input_slice = slice(0, self.total_window_size - self.label_width)
        self.input_indices = np.arange(self.total_window_size)[
            self.input_slice]

        self.label_start = self.total_window_size - self.label_width
        self.labels_slice = slice(self.label_start, None)
        self.label_indices = np.arange(self.total_window_size)[
            self.labels_slice]

#         Make timeseries dataset with windows
        self.full_dataset = self.make_dataset(self.df)
        self.train = self.make_dataset(self.train_df, shuffle=shuffle)
        self.val = self.make_dataset(self.val_df, shuffle=shuffle)
        self.test = self.make_dataset(self.test_df, shuffle=shuffle)

    @property
    def example(self):
        """Get and cache an example batch of `inputs, labels` for plotting."""
        result = getattr(self, '_example', None)
        if result is None:
            # No example batch was found, so get one from the `.train` dataset
            result = next(iter(self.train))
            # And cache it for next time
            self._example = result
        return result

    @property
    def test_no_shuffle(self):
        return self.make_dataset(self.df, shuffle=False).unbatch()

    def __repr__(self):
        return '\n'.join([
            f'Total window size: {self.total_window_size}',
            f'Input indices: {self.input_indices}',
            f'Input columns name(s): {self.column_names}'
            f'Label indices: {self.label_indices}',
            f'Label column name(s): {self.label_columns}'])

    def split_window(self, features):
        inputs = features[:, self.input_slice, :]
        labels = features[:, self.labels_slice, :]
#         print('------------------------')
#         print(inputs)
#         print(labels)
#         print(np.shape(labels))
#         print(self.label_columns)
        # label columns is a one-hot encoding vector
        if self.label_columns is not None:
            labels = tf.stack(
                [labels[:, :, self.column_indices[name]]
                    for name in self.label_columns],
                axis=-1)

        # Slicing doesn't preserve static shape information, so set the shapes
        # manually. This way the `tf.data.Datasets` are easier to inspect.
        inputs.set_shape([None, self.input_width, None])
#         tf.reshape(labels, [None, self.label_width])
        labels.set_shape([None, self.label_width, None])
        labels = tf.squeeze(labels, axis=1)

        return inputs, labels

    def make_dataset(self, data, shuffle=True):

        data = np.array(data, dtype=np.float32)

        ds = tf.keras.preprocessing.timeseries_dataset_from_array(
            data=data,
            targets=None,
            sequence_length=self.total_window_size,
            sequence_stride=1,
            shuffle=shuffle,
            batch_size=self.batch_size,)

        ds = ds.map(self.split_window)

        return ds

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

def plot_linear_model_weights(linear_model, window_generator):
    plt.bar(x=range(len(window_generator.train_df.columns)),
            height=linear_model.layers[0].kernel[:, 0].numpy())
    axis = plt.gca()
    axis.set_xticks(range(len(window_generator.train_df.columns)))
    _ = axis.set_xticklabels(window_generator.train_df.columns, rotation=90)
    plt.show()

def make_plot(train_std, df, train_mean):
    df_std = (df - train_mean) / train_std
    df_std = df_std.melt(var_name='Column', value_name='Normalized')
    plt.figure(figsize=(12, 6))
    ax = sns.violinplot(x='Column', y='Normalized', data=df_std)
    _ = ax.set_xticklabels(df.keys(), rotation=90)
    fig = ax.get_figure()
    fig.savefig("normalized_violin_features.png")

# batch = multiSte.test.take(1)
# print(batch, type(batch), np.shape(batch))

# prediction = linear.predict(batch)
# print(prediction, prediction.shape, type(prediction))

# val_performance = {}
# performance = {}
# val_performance['Linear'] = linear.evaluate(single_step_window.val)
# performance['Linear'] = linear.evaluate(single_step_window.test, verbose=0)


import csv
import heapq
import sys

'''EFFICIENT APPROACH USING HEAPS'''

print('\n\nSOLUTION USING HEAPS\n')

with open(sys.argv[1],'r') as marks:
    c_reader = csv.reader(marks)

    next(c_reader)

    total = []
    mtopper = {'name':None,'marks':0}
    btopper = {'name':None,'marks':0}
    etopper = {'name':None,'marks':0}
    ptopper = {'name':None,'marks':0}
    ctopper = {'name':None,'marks':0}
    htopper = {'name':None,'marks':0}
    count = 0
    for line in c_reader:
        ltotal = 0
        for i in range(1,7):
            ltotal += int(line[i])
        heapq.heappush(total,(ltotal,line[0]))
        count+=1
        if(count == 4):
            heapq.heappop(total)
            count = 3

        if(int(line[1])>mtopper['marks']):
            mtopper['name'] = line[0]
            mtopper['marks'] = int(line[1])
        if(int(line[2])>btopper['marks']):
            btopper['name'] = line[0]
            btopper['marks'] = int(line[2])
        if(int(line[3])>etopper['marks']):
            etopper['name'] = line[0]
            etopper['marks'] = int(line[3])
        if(int(line[4])>ptopper['marks']):
            ptopper['name'] = line[0]
            ptopper['marks'] = int(line[4])
        if(int(line[5])>ctopper['marks']):
            ctopper['name'] = line[0]
            ctopper['marks'] = int(line[5])
        if(int(line[6])>htopper['marks']):
            htopper['name'] = line[0]
            htopper['marks'] = int(line[6])

    print('\n\nTopper in Math is: ',mtopper['name'])
    print('Topper in Biology is: ',btopper['name'])
    print('Topper in English is: ',etopper['name'])
    print('Topper in Physics is: ',ptopper['name'])
    print('Topper in Chemistry is: ',ctopper['name'])
    print('Topper in Hindi is: ',htopper['name'])
    print('\n\nBest students in the class are : ',heapq.nlargest(3,total))

'''Big O Notation for finding individual subject toppers is O(n)
       So in each iteration checking for five subjects gives O(5n) which is equal to O(n) so LINEAR TIME COMPLEXITY'''

'''Big O Notation for finding Top Three Students is O(nlogk) k being the no. of toppers required
   We're inserting ltotal to one heap which takes O(logk) since it has only k elements which is 3 here and that is repeated n times so O(nlogk)'''

'''BRUTE FORCE APPROACH'''

print('\n\nSOLUTION USING THREE ITERATIONS\n')
with open(sys.argv[len(sys.argv)-1],'r') as marklist:
    csv_reader = csv.reader(marklist)
    next(csv_reader)

    mtopper2 = {'name':None,'marks':0}
    btopper2 = {'name':None,'marks':0}
    etopper2 = {'name':None,'marks':0}
    ptopper2 = {'name':None,'marks':0}
    ctopper2 = {'name':None,'marks':0}
    htopper2 = {'name':None,'marks':0}

    toppers = {
               'name1':None,'marks1':0,
               'name2':None,'marks2':0,
               'name3':None,'marks3':0
              }

    for line in csv_reader:
        ltotal = 0
        for i in range(1,7):
            ltotal += int(line[i])

        if(int(line[1])>mtopper2['marks']):
            mtopper2['name'] = line[0]
            mtopper2['marks'] = int(line[1])
        if(int(line[2])>btopper2['marks']):
            btopper2['name'] = line[0]
            btopper2['marks'] = int(line[2])
        if(int(line[3])>etopper2['marks']):
            etopper2['name'] = line[0]
            etopper2['marks'] = int(line[3])
        if(int(line[4])>ptopper2['marks']):
            ptopper2['name'] = line[0]
            ptopper2['marks'] = int(line[4])
        if(int(line[5])>ctopper2['marks']):
            ctopper2['name'] = line[0]
            ctopper2['marks'] = int(line[5])
        if(int(line[6])>htopper2['marks']):
            htopper2['name'] = line[0]
            htopper2['marks'] = int(line[6])

        if(ltotal>toppers['marks1'] and ltotal>toppers['marks2'] and ltotal>toppers['marks3'] ):
            toppers['name3'] = toppers['name2']
            toppers['marks3'] = toppers['marks2']
            toppers['name2'] = toppers['name1']
            toppers['marks2'] = toppers['marks1']
            toppers['name1'] = line[0]
            toppers['marks1'] = ltotal
        elif(ltotal<toppers['marks1'] and ltotal>toppers['marks2']):
            toppers['name3'] = toppers['name2']
            toppers['marks3'] = toppers['marks2']
            toppers['name2'] = line[0]
            toppers['marks2'] = ltotal
        elif(ltotal<toppers['marks2'] and ltotal>toppers['marks3']):
            toppers['name3'] = line[0]
            toppers['marks3'] = ltotal
        else:
            continue

    print('\n\nTopper in Math is: ',mtopper2['name'])
    print('Topper in Biology is: ',btopper2['name'])
    print('Topper in English is: ',etopper2['name'])
    print('Topper in Physics is: ',ptopper2['name'])
    print('Topper in Chemistry is: ',ctopper2['name'])
    print('Topper in Hindi is: ',htopper2['name'])
    print('\n\nBest students in the class are : ',(toppers['name1']+' First Rank',toppers['name2']+' Second Rank',toppers['name3']+' Third Rank'))

    '''Big O Notation for finding individual subject toppers is O(n)
       So in each iteration checking for five subjects gives O(5n) which is equal to O(n) so LINEAR TIME COMPLEXITY'''

    '''Big O Notation for finding individual topper is O(n)
       So it takes 3 iterations for Toppers list which has K (3 here) students so O(Kn) where k is no. of toppers
       or O(3n) which is equal to O(n) so LINEAR TIME COMPLEXITY'''


def main():
    n, m = input().split()
    n = int(n)
    m = int(m)

    #put elements inside list
    lst = list(map(int, input().split()))

    #check if the sum of elements are > m
    rst = []

    sum = 0
    for i in range(0, n):
        for j in range(i+1, n):
            for k in range(j+1, n):
                if(sum + lst[k] < m):
                    #print(lst[i], lst[j], lst[k])
                    sum = lst[i] + lst[j] + lst[k]
                    #print(sum)
                    if(sum <= m):
                        rst.append(sum)
                        sum = 0
                    else:
                        sum = 0

    #print(rst)

  #print the smallest differences
    min = rst[0]
    for i in range(0, len(rst)):
        if(rst[i] > min):
            min = rst[i]

    print(min)

main()


import os.path

from aws_cdk.aws_s3_assets import Asset
from constructs import Construct
from requests import get

from aws_cdk import (
    # Duration,
    Aspects,
    CfnOutput,
    Tag,
    Stack,
    aws_ec2 as ec2,
    aws_iam as iam,
    aws_autoscaling as asg,
)

dirname = os.path.dirname(__file__)

# Get My external IP address
def get_my_external_ip():
    ip = get('https://api.ipify.org').content.decode('utf8')
    return f"{ip}/32"

class BaseVPC(Stack):

    @property
    def vpc(self):
        return self._vpc

    @property
    def asg(self):
        return self._asg

    @property
    def asg_sg(self):
        return self._asg_sg

    def create_ssm_endpoint(self, vpc):
        """
            Create ssm endpoint via AWS CDk
            :param vpc:
            :return:

        """

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # VPC
        self._vpc = ec2.Vpc(self, "VPC",
            vpc_name="vpc-workshop",
            ip_addresses=ec2.IpAddresses.cidr("172.30.0.0/24"),
            enable_dns_hostnames=True,
            enable_dns_support=True,
            nat_gateways=0,
            subnet_configuration=[
                ec2.SubnetConfiguration(
                    name="public",
                    subnet_type=ec2.SubnetType.PUBLIC
                ),
                ec2.SubnetConfiguration(
                    name="private",
                    subnet_type=ec2.SubnetType.PRIVATE_WITH_EGRESS
                )
            ]
        )
        Aspects.of(self._vpc).add( Tag("Name", "vpc-workshop-lab"))
        # # Create ssm endpoint via AWS CDk
        # CodeWhisperer doesn't know CDK API documents
        # self._ssm_endpoint = SsmEndpoint(self, "SsmEndpoint", vpc=self._vpc)

        # import SG by ID
        security_group = ec2.SecurityGroup.from_security_group_id(
            self, "SG", self._vpc.vpc_default_security_group,
            mutable=False
        )

        ec2.InterfaceVpcEndpoint(self, "VPC Endpoint",
            vpc=self._vpc,
            service=ec2.InterfaceVpcEndpointService(f"com.amazonaws.{self.region}.ssm", 443),
            # Choose which availability zones to place the VPC endpoint in, based on
            # available AZs
            subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
            security_groups=[security_group]
        )

        # AMI
        amzn_linux = ec2.MachineImage.latest_amazon_linux2(
            edition=ec2.AmazonLinuxEdition.STANDARD,
            virtualization=ec2.AmazonLinuxVirt.HVM,
            storage=ec2.AmazonLinuxStorage.GENERAL_PURPOSE
            )

        # Instance Role and SSM Managed Policy
        role = iam.Role(self, "InstanceSSM", assumed_by=iam.ServicePrincipal("ec2.amazonaws.com"))

        role.add_managed_policy(iam.ManagedPolicy.from_aws_managed_policy_name("AmazonSSMManagedInstanceCore"))

        # create security group with whilelist MyIp
        self._asg_sg = ec2.SecurityGroup(
            self, "ASG_SG",
            vpc=self._vpc,
            allow_all_outbound=True,
            description="Security Group for ASG"
        )

        # allow only MyIp
        self._asg_sg.add_ingress_rule(
            peer = ec2.Peer.ipv4(get_my_external_ip()),
            connection=ec2.Port.all_tcp()
        )

        self._asg = asg.AutoScalingGroup(
            self, "ASG",
            vpc = self._vpc,
            vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC),
            instance_type=ec2.InstanceType("t2.micro"),
            machine_image=amzn_linux,
            min_capacity=0,
            max_capacity=1,
            desired_capacity=0,
            security_group=self._asg_sg,
            role=role
        )

        CfnOutput(self, "VPC ID", value=self._vpc.vpc_id)
        CfnOutput(self, "ASG ID", value=self._asg.auto_scaling_group_name)
        CfnOutput(self, "ASG SG ID", value=self._asg_sg.security_group_id)

        # # Script in S3 as Asset
        # asset = Asset(self, "Asset", path=os.path.join(dirname, "configure.sh"))
        # local_path = self._instance.user_data.add_s3_download_command(
        #     bucket=asset.bucket,
        #     bucket_key=asset.s3_object_key
        # )

        # Userdata executes script from S3
        # self._instance.user_data.add_execute_file_command(
        #     file_path=local_path
        #     )
        # asset.grant_read(self._instance.role)

                # Instance
        # self._instance = ec2.Instance(self, "Instance",
        #     instance_type=ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
        #     machine_image=amzn_linux,
        #     vpc = self._vpc,
        #     role = role,
        #     vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC)
        # )


import pandas as pd
import matplotlib.pyplot as plt

kalibrierung_file = 'E:\Projektarbeit\Data\Muffenmessung_September\Analysierbar\Kalibrierung_ohne_pi_Muffe1_201.csv'
kalibrierung_data = pd.read_csv(kalibrierung_file, sep=';')
print(kalibrierung_data)

muffe1_file = 'E:\Projektarbeit\Data\Muffenmessung_September\Analysierbar\Muffe1_Messung1_ohnepirichtig_201points.csv'
muffe1_data = pd.read_csv(muffe1_file, sep=';')
print(muffe1_data)

muffe2_file = 'E:\Projektarbeit\Data\Muffenmessung_September\Analysierbar\Muffe1_50ohm_ohnepirichtig_201points.csv'
muffe2_data = pd.read_csv(muffe2_file, sep=';')
print(muffe2_data)

def singleplotting(data, set_color, file):
    font_title = {'family': 'Arial',
    'weight': 'normal',
    'size': 16,
    }

    font1 = {'family': 'Arial',
    'weight': 'normal',
    'size': 12,
    }

    x = data['Frequency (Hz)'] * (10 ** -6)
    y = -data['Trace 1: Gain: Magnitude (dB)'] + kalibrierung_data['Trace 1: Gain: Magnitude (dB)']

    plt.title('Diagramm der Dämpfungen in Frequenzen', font_title)
    plt.xlabel('Frequenz [MHz]', font1)
    plt.ylabel('Dämpfung [dB]', font1)
    plt.xticks(fontsize = 12, fontfamily = 'Arial')
    plt.yticks(fontsize = 12, fontfamily = 'Arial')
    plt.plot(x,y, color = set_color)
    plt.savefig(file, dpi=1000)
    plt.show()

def multipleplotting():
    font_title = {'family': 'Arial',
    'weight': 'normal',
    'size': 16,
    }

    font1 = {'family': 'Arial',
    'weight': 'normal',
    'size': 12,
    }

    x1 = muffe1_data['Frequency (Hz)'] * (10 ** -6)
    y1 = -muffe1_data['Trace 1: Gain: Magnitude (dB)'] + kalibrierung_data['Trace 1: Gain: Magnitude (dB)']
    x2 = muffe2_data['Frequency (Hz)'] * (10 ** -6)
    y2 = -muffe2_data['Trace 1: Gain: Magnitude (dB)'] + kalibrierung_data['Trace 1: Gain: Magnitude (dB)']

    plt.figure(figsize=(10,6))
    plt.style.use('seaborn')
    plt.title('Diagramm der Dämpfungen in Abhängigkeit von Frequenzen', font_title)
    plt.xlabel('Frequenz [MHz]', font1)
    plt.ylabel('Dämpfung [dB]', font1)
    plt.xticks(fontsize = 12, fontfamily = 'Arial')
    plt.yticks(fontsize = 12, fontfamily = 'Arial')
    plt.plot(x1,y1, color = 'green', label = 'Leerlauf')
    plt.plot(x2,y2, color = 'red', label = '50 Ohm')
    plt.legend(prop = font1, loc = 'lower right')
    plt.savefig('E:\Projektarbeit\Data\Muffenmessung_September\Analysierbar\Multipleplotting.png', dpi=1000)
    plt.show()

#singleplotting(muffe1_data, 'blue', 'E:\Projektarbeit\Data\Muffenmessung_September\Analysierbar\Muffe1_Messung1_ohnepi_201points.png')
#singleplotting(muffe2_data, 'green', 'E:\Projektarbeit\Data\Muffenmessung_September\Analysierbar\Muffe1_Messung1_ohnepirichtig_201points.png')
#singleplotting(muffe3_data, 'red', 'E:\Projektarbeit\Data\Muffenmessung_September\Analysierbar\Muffe1_50ohm_ohnepirichtig_201points.png')

multipleplotting()


# works for python 2
# modules to read data from urls
import urllib
import urllib2
import string
import sys
from bs4 import BeautifulSoup

# make program look like a browser, user_agent
user_agent = 'Mozilla/5 (Solaris 10) Gecko'
headers = { 'User-Agent' : user_agent }

# pass in the word into the search bar a.k.a create html form
values = {'s' :  sys.argv[1]}
# urlencode the word
data = urllib.urlencode(values)
# makes the request/form
request = urllib2.Request("https://www.dict.cc/", data, headers)
# sends the request/form to the website
response = urllib2.urlopen(request)

# read the html code form the website
the_page = response.read()
# turns the data into string
pool = BeautifulSoup(the_page, "html.parser")

# get BeautifulSoup.ResultSet and return all td with class td7nl
results = pool.findAll('td', attrs={'class' : 'td7nl'})
source = ''
translations = []

# loop through the results
for result in results:
	word = ''
	# for each td's text
	for tmp in result.findAll(text=True):
		word = word + " " + unicode(tmp).encode("utf-8")
	# append data
	if source == '':
		source = word
	else:
		translations.append((source, word))

# print out data
for translation in translations:
	print("%s => %s") % (translation[0], translation[1])


import pandas as pd
import itertools
import json
text1,text2,labels = [],[],[]

title_data = []
content_data = []
with open('/home/xiaoguzai/数据集/第五届“达观杯” 基于大规模预训练模型的风险事件标签识别数据集/new_try.json','r') as load_f:
    load_dict = json.load(load_f)
    for data in load_dict:
        title_data.append(data['title'])
        content_data.append(data['content'])
        #total_data.append(data['title'])
        #total_data.append(data['content'])
#content_data长度截取:3000,title_data长度截取:150

new_content_data = []
for data in content_data:
    print(len(data))

import json
from bertmodels import Bert,Config
vocab_file = r'/home/xiaoguzai/代码/第五届“达观杯” 基于大规模预训练模型的风险事件标签识别/bert-base-count3-HMCN-F/pretrain/bert_model/vocab.txt'
vocab_size = len(open(vocab_file,'r').readlines())
with open('/home/xiaoguzai/数据集/bert-uncased-pytorch/config.json','r',encoding='utf8')as fp:
    json_data = json.load(fp)
json_data['vocab_size'] = vocab_size
print('json_data = ')
print(json_data)
config = Config(**json_data)

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import Dataset,DataLoader
from tokenization import FullTokenizer
import numpy as np
vocab_file = "/home/xiaoguzai/代码/第五届“达观杯” 基于大规模预训练模型的风险事件标签识别/bert-base-count3-HMCN-F/pretrain/bert_model/vocab.txt"
tokenizer = FullTokenizer(vocab_file=vocab_file)
#预训练程序不需要大改，同一个程序不同的方法实现预训练
from nezha_pretraining import nezha_pretraining_store_id_data

def sequence_padding(inputs,maxlen,padding = 0):
    length = maxlen
    pad_width = [(0,0) for _ in np.shape(inputs[0])]
    #print('pad_width = ')
    #print(pad_width)
    outputs = []
    for x in inputs:
        #print('x = ')
        #print(x)
        x = x[:length]
        pad_width[0] = (0,length-len(x))
        x = np.pad(x,pad_width,'constant',constant_values=padding)
        outputs.append(x)
    return np.array(outputs)

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
class ClassificationDataset(Dataset):
    def __init__(self,text,maxlen):
        self.text = text
        self.maxlen = maxlen
        token_data,token_id,segment_id,mask_id = [],[],[],[]
        #sequence填充可以最后统一实现
        for index in tqdm(range(len(self.text))):
        #!!!这里构成ClassificationDataset之中的tqdm还可以优化并行操作
            current_text = text[index]
            current_token = tokenizer.tokenize(current_text)
            current_token = ["[CLS]"]+current_token
            current_id = tokenizer.convert_tokens_to_ids(current_token)
            if len(current_token) > maxlen-1:
                current_token = current_token[:maxlen-1]
                current_id = current_id[:maxlen-1]
            current_token = current_token+["[SEP]"]
            current_id = current_id+tokenizer.convert_tokens_to_ids(["[SEP]"])
            #current_segment_id = [0]*len(current_id)
            #current_mask_id = [1]*len(current_id)

            token_data.append(current_token)
            token_id.append(current_id)
            #segment_id.append(current_segment_id)
            #mask_id.append(current_mask_id)
        self.token_data = token_data
        self.token_id = token_id
        #self.segment_id = segment_id
        #self.mask_id = mask_id
        begin = 5
        self.input_id,self.label = nezha_pretraining_store_id_data(token_id,token_data,vocab_file,begin,vocab_size)

        self.input_id = sequence_padding(self.input_id,maxlen)
        #self.segment_id = sequence_padding(self.segment_id,maxlen)
        #self.mask_id = sequence_padding(self.mask_id,maxlen)
        self.label = sequence_padding(self.label,maxlen)
        #self.tensors = [torch.tensor(self.input_id,dtype=torch.long).to(device),
        #               torch.tensor(self.label,dtype=torch.long).to(device)]
        self.tensors = [torch.tensor(self.input_id,dtype=torch.long),
                        torch.tensor(self.label,dtype=torch.long)]

    def __len__(self):
        return len(self.token_id)

    def __getitem__(self,index):
        return tuple(tensor[index] for tensor in self.tensors)

    def sequence_padding(self,inputs,padding = 0):
        length = self.maxlen
        if len(inputs) > length:
            inputs = inputs[:length]
        outputs = []
        pad_width = (0,length-len(inputs))
        x = np.pad(inputs,pad_width,'constant',constant_values=padding)
        return x
r"""
title_dataset = ClassificationDataset(title_data,maxlen=150)
title_data_iter = DataLoader(title_dataset,batch_size=2,shuffle=True)

content_maxlen = 500
content_dataset = ClassificationDataset(content_data,maxlen=maxlen)
content_data_iter = DataLoader(content_dataset,batch_size=20,shuffle=True)
"""

from bertmodels import Bert
from tqdm import tqdm
config.with_mlm = True
model = Bert(config)
optimizer = torch.optim.AdamW(model.parameters())
loss_func = torch.nn.CrossEntropyLoss()
#torch.cuda.set_device(0)
model = model.to(device)
model = nn.DataParallel(model)
model.train()
#content_maxlen = 500
content_maxlen = 300
for epoch in range(400):
    print('epoch {}'.format(epoch+1))
    train_loss = 0
    train_acc = 0
    for filenum in range(1,300):
        title_data = []
        content_data = []
        filename = '/home/xiaoguzai/数据集/第五届“达观杯” 基于大规模预训练模型的风险事件标签识别数据集/data/unlabeled_data'+str(filenum)+'.json'
        with open(filename,'r') as load_f:
            load_dict = json.load(load_f)
            print('load file %s'%filename)
            for data in tqdm(load_dict):
                title_data.append(data['title'])
                currentcontent = data['content']
                currentlen = len(currentcontent)
                if currentlen%content_maxlen == 0:
                    totalnumber = currentlen//content_maxlen
                else:
                    totalnumber = currentlen//content_maxlen
                    totalnumber = totalnumber+1
                for number in range(totalnumber):
                    right = min(currentlen,(number+1)*content_maxlen)
                    content_data.append(currentcontent[number*content_maxlen:right])
            print('load %s finish'%filename)
        print('begin %s title_dataset'%filename)
        title_dataset = ClassificationDataset(title_data,maxlen=150)
        title_dataset_len = len(title_dataset)
        title_data_iter = DataLoader(title_dataset,batch_size=128,shuffle=True)
        del(title_dataset)
        del(title_data)
        #batch_size = 256
        print('title_dataset finish')
        print('*********************begin train**********************')
        for batch_token_ids,batch_labels in tqdm(title_data_iter,colour='blue'):
            batch_token_ids = batch_token_ids.to(device)
            batch_labels = batch_labels.to(device)
            output = model(batch_token_ids)
            output = output.view(-1,vocab_size)
            batch_labels = batch_labels.view(-1)
            loss = loss_func(output,batch_labels)
            train_loss += loss
            pred = torch.max(output, 1)[1]
            train_correct = (pred == batch_labels).sum()
            train_acc += train_correct
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        print('Train Loss: {:.6f}, Acc: {:.6f}'.format(train_loss, train_acc/title_dataset_len))
        del(title_data_iter)
        torch.cuda.empty_cache()
        print('********************finish train***********************')
        print('begin %s content_dataset'%filename)
        content_dataset = ClassificationDataset(content_data,maxlen=content_maxlen)
        content_data_iter = DataLoader(content_dataset,batch_size=64,shuffle=True)
        #batch_size = 128
        content_dataset_len = len(content_dataset)
        del(content_data)
        del(content_dataset)
        print('content_dataset finish')
        print('####################begin train########################')
        for batch_token_ids,batch_labels in tqdm(content_data_iter,colour='red'):
            batch_token_ids = batch_token_ids.to(device)
            batch_labels = batch_labels.to(device)
            #数据较大的时候拿出一个批次再放入gpu之中
            output = model(batch_token_ids)
            output = output.view(-1,vocab_size)
            batch_labels = batch_labels.view(-1)
            loss = loss_func(output,batch_labels)
            train_loss += loss
            pred = torch.max(output, 1)[1]
            train_correct = (pred == batch_labels).sum()
            train_acc += train_correct
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        print('Train Loss: {:.6f}, Acc: {:.6f}'.format(train_loss, train_acc/content_dataset_len))
        del(content_data_iter)
        torch.cuda.empty_cache()
        print('####################finish train########################')
    if epoch%50 == 0:
        torch.save(model.state_dict(),'/home/xiaoguzai/数据集/第五届“达观杯” 基于大规模预训练模型的风险事件标签识别数据集/model_epoch='+str(epoch)+'.pth')


#Receiver's end
#!/usr/bin/python

import socket as s
ip="127.0.0.1"
port=4444

sk=s.socket(s.AF_INET,s.SOCK_DGRAM)
sk.bind((ip,port))
cont=1
while cont==1:
	data=sk.recvfrom(100)
	print(data[0])
	msg=raw_input("enter your msg :")
	sk.sendto(msg,data[1])

	cont=input("Press 1 for continue and 0 for end : ")


from datetime import datetime
ano = datetime.now()

dados = {}
from datetime import date
dados['nome'] = str(input('Nome: '))
ADN = int(input('Ano de nacimento: '))
dados['idade'] = ano.year - ADN
dados['CTPS'] = int(input('Número da carteira de trabalho(0 não tem): '))
if dados['CTPS'] != 0:
    dados['contratação'] = int(input('Ano de contratação: '))
    dados['salario'] = float(input('Informe seu salário: R$'))
    ap = 35 - (ano.year - dados['contratação'])
    dados['aposentadoria'] = dados['idade'] + ap

for k, v in dados.items():
    print(f'{k.upper()} = {v}')


from typing import Any, Dict, Optional

from didsdk.exceptions import AttributeException
from didsdk.protocol.base_param import BaseParam
from didsdk.protocol.claim_attribute import ClaimAttribute
from didsdk.protocol.hash_attribute import HashedAttribute

class BaseClaim:
    ATTRIBUTE_TYPE = "attrType"
    ATTRIBUTE = "attr"
    HASH_TYPE = HashedAttribute.ATTR_TYPE

    def __init__(
        self, attribute_type: str, attribute: "ClaimAttribute" = None, algorithm: str = None, values: Dict = None
    ):
        if attribute_type == self.HASH_TYPE:
            self.attribute_type: str = attribute_type
        else:
            raise ValueError(f'"Unsupported Attribute Type({attribute_type})')

        if attribute:
            self.attribute = attribute
        elif algorithm:
            self.attribute = HashedAttribute(alg=algorithm, values=values)
        else:
            raise AttributeException("BaseClaim must need one of ClaimAttribute and algorithm.")

    def to_json(self) -> Dict[str, Any]:
        return {
            self.ATTRIBUTE_TYPE: self.attribute_type,
            self.ATTRIBUTE: {"alg": self.attribute.alg, "value": self.attribute.hashed_values},
        }

    @classmethod
    def from_json(cls, json_data: Dict):
        attribute_type: str = str(json_data.get(cls.ATTRIBUTE_TYPE))
        attribute: Optional["ClaimAttribute"] = None
        attr_object: Dict = json_data.get(cls.ATTRIBUTE)

        if attribute_type == cls.HASH_TYPE:
            attribute = HashedAttribute.from_json(attr_object, True)
        else:
            raise AttributeException(f"Unsupported Attribute Type({attribute_type})")

        return BaseClaim(attribute_type, attribute)

    def verify(self, base_param: BaseParam):
        return self.attribute.verify(base_param)


from __future__ import print_function

import logging
import os
import random
import requests

from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime
from flask import Flask

SERVICE_PORT = int(os.environ.get('SERVICE_PORT', 5000))
MARATHON = str(os.environ.get('MARATHON_HOST', 'marathon.service.consul'))
MIN_CONTAINERS = int(os.environ.get('MIN_CONTAINERS', 2))
MIN_LIFETIME_SECS = int(os.environ.get('MIN_LIFETIME_SECS', 300))
INTERVAL_SECONDS = int(os.environ.get('RUNTIME_INTERVAL_SECS', 300))
AMMO = int(os.environ.get('AMMO', 5))

url = 'http://%s:8080/v2/tasks' % MARATHON
logging.basicConfig(level=logging.os.environ.get('LOG_LEVEL', 'INFO'))

def shoot(container):
    logging.info("#~> BANG! [fragged:%s]" % (container))
    data = {"ids": [str(container)]}
    result = requests.post(url + '/delete', json=data).json()
    logging.info(result)

def take_aim():
    clip = AMMO
    targets = {}
    tasks = requests.get(url).json()
    quad_damage = False

    if random.random() * 10 > 8:
        logging.info('#~> picked up QUAD DAMAGE')
        quad_damage = True

    if random.random() * 10 > 8:
        logging.info('#~> picked up AMMO')
        clip += AMMO

    for t in tasks['tasks']:
        app_name = t['appId'].strip('/')
        id = t['id']

        # TODO: don't kill $self unless GOD-mode is enabled
        # if app_name == SELF:
        #    continue

        if t['state'] != 'TASK_RUNNING':
            logging.info('#~> Player not joined')
            continue

        started = datetime.strptime(t['startedAt'], '%Y-%m-%dT%H:%M:%S.%fZ')
        now = datetime.now()
        if (now - started).total_seconds() < MIN_LIFETIME_SECS:
            logging.info('#~> Spawn kills disabled by server [%s]' % app_name)
            continue

        if app_name in targets:
            targets[app_name].add(id)
        else:
            targets[app_name] = {id}

    imps = targets.items()
    random.shuffle(imps)
    for app, containers in imps:
        if len(containers) > MIN_CONTAINERS:
            if clip > 0:
                clip -= 1
                shoot(random.choice(tuple(containers)))
                if quad_damage:
                    shoot(random.choice(tuple(containers)))

app = Flask(__name__)

@app.route("/")
def home():
    return """
BFG9000
"""

@app.route("/status")
def status():
    return "OK"

@app.route("/metrics")
def metrics():
    return """# not implemented"""

def run():
    logging.info('#~> /give BFG9000')

    take_aim()

    scheduler = BackgroundScheduler({'apscheduler.timezone': 'UTC'})
    scheduler.add_job(take_aim, 'interval', seconds=INTERVAL_SECONDS)
    scheduler.start()

    try:
        app.run(host="0.0.0.0", port=SERVICE_PORT, threaded=False)
    finally:
        scheduler.shutdown()


def extractConfusedTranslations(item):
	'''
	Parser for 'Confused Translations'
	'''

	vol, chp, frag, postfix = extractVolChapterFragmentPostfix(item['title'])
	if not (chp or vol) or "preview" in item['title'].lower():
		return False

	tagmap = {
		'Youkoso Jitsuryoku'                      : 'Youkoso Zitsuryoku Shijou Shugi no Kyoushitsu e',
		'Gamers!'                                 : 'Gamers!',

	}

	for tag, sname in tagmap.items():
		if tag in item['tags']:
			return buildReleaseMessageWithType(item, sname, vol, chp, frag=frag)

	return False


import copy
from algo import ConstraintParams

def default_neighbor_state_fn(constraint_params):
    graph = constraint_params.graph
    curr_state = constraint_params.curr_state
    if curr_state is None:
        neighbors = [n for n in graph.nodes]
    else:
        neighbors = graph.get_edges(curr_state)
    return neighbors

def default_process_state_fn(graph, curr_state, global_memory):
    pass

def default_is_success_state_fn(constraint_params):
    return True

"""
Outputs a list of successful terminal states.
"""
def generate_plans(graph, initial_states, neighbor_state_fn, success_state_fn, process_state_fn):
    global_memory = {}
    queue = copy.copy(initial_states)
    success_states = set()
    while len(queue) > 0:
        state = queue.pop()
        # print("Popping {0}".format(state.node.entity.name))
        # Process state (make any edits to global memory if needed)
        # process_state_fn(graph, state, global_memory)

        constraint_params = ConstraintParams(graph, state, None, global_memory)

        # Check if successful final state. If so, add it to successful plan states.
        if success_state_fn(constraint_params):
            success_states.add(state)

        # Get state neighbors and add to queue
        neighbors = neighbor_state_fn(constraint_params)
        #print("\tFound {} neighbors".format(len(neighbors)))
        queue.extend(neighbors)

    return success_states


#!/usr/bin/env python3
def one(input1, input2):
	st1 = len(input1)
	st2 = len(input2)
	if len(input1)> len(input2):
		return input1
	elif len(input2)> len(input1):
		return input2
	else:
		return input1+" "+input2

	# <QUESTION 2>

    # Return the string that is between the first and last appearance of "bert" in the given string

	# Return the empty string "" if there is not 2 occurances of "bert"

	# IGNORE CASE

    # <EXAMPLES>

	# <HINT>

	# What was the name of the function we have seen to seperate a String? How can we make a string all upper or lower case?

	# Use your CLI to access the Python documentation and get help manipulating strings - help(str).

def two(input):
	string = input
	stren = ''
	for i in range(len(string)):
		if 'bert' in string.lower():
			stren = string[i]+string[i+1]+string[i+2]+string[i+3]
			stren = stren.lower()
		if stren == 'bert':
			string = string[i+4:]
			break
	if 'bert' in string.lower():
		for i in range(len(string)):
			stren = string[i]+string[i+1]+string[i+2]+string[i+3]
			stren = stren.lower()
			if stren == 'bert':
				string = string[:i]
				break

	else:
		string = ''

	#string = string[::-1]
	return string

	# <QUESTION 3>

    # given a number
	# if this number is divisible by 3 return "fizz"
	# if this number is divisible by 5 return "buzz"
	# if this number is divisible by both 3 and 5 return "fizzbuzz"
	# if this number is not divisible by 3 or 5 return "null"

    # <EXAMPLES>

	# <HINT>

	# No Hints for this question

def three(arg1):
	if arg1%15==0:
		return 'fizzbuzz'
	elif arg1 % 3 == 0:
		return 'fizz'
	elif arg1 % 5 == 0:
		return 'buzz'
	else:
		return "null"

	# <QUESTION 4>

    # Given a string seperate the string into the individual numbers present, then add each digit of each number to get a final value for each number

	# String example = "55 72 86"

	# "55" will = the integer 10
	# "72" will = the integer 9
	# "86" will = the integer 14

	# You then need to return the highest value, in the example above this would be 14.

    # <EXAMPLES>

	# <HINT>

	# help(int) for working with numbers and help(str) for working with Strings.

def four(arg1):
	numbers = arg1.split()
	values = []
	for i, el in enumerate(numbers):
		c=0
		for p in range(len(el)):
			c+=int(el[p])
		values.append(c)
	return max(values)

	# <QUESTION 5>

    # Given a large string that represents a csv, the structure of each record will be as follows:

    # owner,nameOfFile,encrypted?,fileSize

    # "Bert,private.key,True,1447,Bert,public.key,False,1318,Jeff,private.key,False,1445"

    # For each record, if it is not encrypted, return the names of the owners of the files in a String Array.
    # Do not include duplicate names.
	# If all records are encrypted, return an empty Array.

    # <EXAMPLES>

	# <HINT>

	# Dont't forget, False is a String, not a Boolean value in the Tests above.

	# help(str) and help(list), you might also need to use a function that can create a list of numbers for you, try help(range).

def five(input):
	order = input.split(',')
	names =[]
	for i, el in enumerate(order):
		if el == 'private.key':
			if order[i+1]=='False':
				names.append(order[i-1])

	return names

	# <QUESTION 6>

    # There is a well known mnemonic which goes "I before E, except after C", which is used to determine which order "ei" or "ie" should be in a word.

    # Write a function which returns the boolean True if a string follows the mnemonic, and returns the boolean False if not.

	# <EXAMPLES>

	# <HINT>

	# Step through the logic here in order to solve the problem, you may find help(range) helpful.

def six(input):
	for i in range(len(input)):
		if input[i]=='i' and input[i+1]=='e' and input[i-1] != 'c':
			return True
		elif input[i]=='e' and input[i+1]=='i' and input[i-1] == 'c':
			return True
	return False

	# <QUESTION 7>

    # Write a function which returns the integer number of vowels in a given string.
    # You should ignore case.

	# <EXAMPLES>

	# <HINTS>

	# How do we ignore case in a String? help(str) may offer some insight.

def seven(input):
	vowels ='AEIOUaeiou'
	c = 0
	for i in range(len(input)):
		if input[i] in vowels:
			c+=1
	return c

	# <QUESTION 8>

	# Write a function which takes an input (between 1 and 10 inclusive) and multiplies it by all the numbers before it.
	# eg If the input is 4, the function calculates 4x3x2x1 = 24

	# <EXAMPLES>

	# <HINT>

	# You may need to create a list of numbers from 0 to i, take a look at help(range).

def eight(input):
	c = 1
	for i in range(1,input+1):
		c*=i

	return c

	# <QUESTION 9>

    # Given a string and a char, returns the position in the String where the char first appears.
    # Ensure the positions are numbered correctly, please refer to the examples for guidance.
    # DO NOT ignore case
    # IGNORE whitespace
    # If the char does not occur, return the number -1.

    # <EXAMPLES>

	# <HINT>

	# Take a look at the documentation for Strings, List and range.

def nine(inputString, char):
	pos = -1
	inputString=inputString.replace(" ","")
	if char in inputString:
		pos = inputString.index(char)+1
	return pos

	# <QUESTION 10>

    # Given a string, int and a char, return a boolean value if the 'nth'
    # (represented by the int provided) char of the String supplied is the same as the char supplied.
    # The int provided will NOT always be less than than the length of the String.
    # IGNORE case and Whitespace.

    # <EXAMPLES>

	# How do we find the length of a container, take a look at help(len), you will also need to look at help(str) for String manipulation.

def ten(string, int, char):
	if len(string)<int:
		return False
	if string[int-1].lower()==char.lower():
		return True
	else:
		return False


"""Downloading the MNIST dataset and storing as TFRecords."""

import os
import tensorflow as tf
from tensorflow.keras.datasets import mnist
from convert import encode

def save_training_data(images, labels, filename):
  """Convert Keras MNIST data into TFRecords."""
  assert images.shape[0] == labels.shape[0]
  num_examples = images.shape[0]

  with tf.io.TFRecordWriter(filename) as writer:

    for index in range(num_examples):

      image = images[index]
      label = labels[index]
      example = encode(image, label)
      writer.write(example.SerializeToString())

def download_mnist():
  (x_train, y_train), (x_test, y_test) = mnist.load_data()

  data_dir = os.path.expanduser("./data/")
  if not os.path.exists(data_dir):
    os.makedirs(data_dir)

  save_training_data(x_train, y_train, os.path.join(data_dir, "train.tfrecord"))
  save_training_data(x_test, y_test, os.path.join(data_dir, "test.tfrecord"))


from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from .forms import AktuellesForm

#from django.http import HttpResponse

from .models import Aktuelles

def aktuelles(request):
    aktuelles = Aktuelles.objects.filter(published_date__lte=timezone.now()).order_by('start_date')
    return render(request, 'home/aktuelles.html', {'aktuelles': aktuelles})

def aktuell_detail(request, pk):
    aktuell = get_object_or_404(Aktuelles, pk=pk)
    return render(request, 'home/aktuell_detail.html', {'aktuell': aktuell})

@login_required
def aktuell_neu(request):
    if request.method == "POST":
        form = AktuellesForm(request.POST)
        if form.is_valid():
            aktuell = form.save(commit=False)
            aktuell.author = request.user
            # wenn kein draft erzeugt werden soll, sondern gleich publiziert werden soll dann published_date setzen
            # aktuell.published_date = timezone.now()
            aktuell.save()
            return redirect('home.views.aktuell_detail', pk=aktuell.pk)
    else:
        form = AktuellesForm()
    return render(request, 'home/aktuell_edit.html', {'form': form})

@login_required
def aktuell_edit(request, pk):
    aktuell = get_object_or_404(Aktuelles, pk=pk)
    if request.method == "POST":
        form = AktuellesForm(request.POST, instance=aktuell)
        if form.is_valid():
            aktuell = form.save(commit=False)
            aktuell.author = request.user
            aktuell.published_date = timezone.now()
            aktuell.save()
            return redirect('home.views.aktuell_detail', pk=aktuell.pk)
    else:
        form = AktuellesForm(instance=aktuell)
    return render(request, 'home/aktuell_edit.html', {'form': form})

@login_required
def aktuell_draft_list(request):
    aktuelles = Aktuelles.objects.filter(published_date__isnull=True).order_by('created_date')
    return render(request, 'home/aktuell_draft_list.html', {'aktuelles': aktuelles})

@login_required
def aktuell_publish(request, pk):
    aktuell = get_object_or_404(Aktuelles, pk=pk)
    aktuell.publish()
    return redirect('home.views.aktuell_detail', pk=pk)

@login_required
def aktuell_remove(request, pk):
    aktuell = get_object_or_404(Aktuelles, pk=pk)
    aktuell.delete()
    return redirect('home.views.aktuelles')


import multiprocessing
from copy import deepcopy

if True:
    multiprocessing.set_start_method("spawn", True)
import concurrent.futures
from dataclasses import dataclass
from time import time
from typing import Any, Callable, List, Tuple, cast

import numpy as np
from pyomo.environ import Objective, maximize

from src.evaluation import average_opt_results
from src.objective import admm_objective_function
from src.prepare_problem import (
    InstanceInformation,
    OptimizationResult,
    Problem,
    get_variables_and_params,
)
from src.problem import OptimizationInstance, SolverInstance

@dataclass
class Iteration:
    """Dataclass for storing the results of an iteration of ADMM."""

    iteration: int
    cost: List[float]
    total_cost: float
    conv1: float
    conv2: float
    conv3: float
    bar_p_up_reserve: np.ndarray
    bar_alpha: float
    bar_beta: float
    prev_p_up_reserve: np.ndarray
    prev_alpha: np.ndarray
    prev_beta: np.ndarray

    @property
    def distance(self) -> float:
        return self.conv1 + self.conv2 + self.conv3

    @property
    def mean_cost(self) -> float:
        return cast(float, np.mean(self.cost))

    @property
    def std_cost(self) -> float:
        return cast(float, np.std(self.cost))

    def converged(self, tol: float) -> bool:
        return self.distance < tol

def _solve_func(payload: Any) -> Tuple[InstanceInformation, OptimizationResult, float]:
    data, objective, gamma, rho, omega, bar_p_up_reserve, bar_alpha, bar_beta = payload
    generic_solver_instance = SolverInstance()
    inst = generic_solver_instance.model.create_instance(data=data)
    total_objective = objective(inst) + admm_objective_function(
        inst,
        gamma,
        rho,
        omega,
        bar_p_up_reserve,
        bar_alpha,
        bar_beta,
    )
    # total_objective = objective(inst)
    inst.objective = Objective(rule=total_objective, sense=maximize)
    inst.lambda_policy_1.activate()
    inst.one_lambda_constraint_1.deactivate()
    inst.one_lambda_constraint_2.deactivate()
    # inst.alpha.fix(0)
    # inst.beta.fix(0.001)
    # optimal_reserve = [
    #     0.0,
    #     0.77,
    #     0.0,
    #     0.78,
    #     0.8,
    #     0.79,
    #     1.09,
    #     0.0,
    #     0.0,
    #     1.28,
    #     1.28,
    #     1.29,
    #     1.29,
    #     1.26,
    #     1.27,
    #     1.27,
    #     1.27,
    #     1.26,
    #     1.23,
    #     1.17,
    #     1.16,
    #     1.05,
    #     0.86,
    #     0.8,
    # ]
    # for i in range(24):
    #     inst.p_up_reserve[i].fix(max(optimal_reserve[i] - 0.01, 0))
    SolverInstance.run_solver(inst, False)
    return (
        get_variables_and_params(inst),
        Problem.get_result(inst, if_print=False),
        # Problem.get_result(inst, if_print=True),
        inst.objective.expr(),
    )

class ADMM:
    def __init__(
        self,
        generic_solver_instance: SolverInstance,
        instance: OptimizationInstance,
        objective: Callable,
        gamma: float = 1,
        max_iter: int = 20,
        min_iter: int = 3,
        tol: float = 0.1,
    ):
        self.generic_solver_instance = generic_solver_instance
        self.instance = instance
        self.nb_scenarios = instance.nb_scenarios
        self.objective = objective

        self.gamma = gamma
        self.max_iter = max_iter
        self.min_iter = min_iter
        self.tol = tol

        print(
            f"ADMM: scenarios={self.nb_scenarios}, gamma={gamma}, max_iter={max_iter}, tol={tol}"
        )

    def calculate_error(self, a: np.ndarray, b: np.ndarray) -> float:
        # assert a.shape == b.shape
        # return np.sum(np.sqrt((np.mean((a - b) ** 2, axis=0))))
        return np.sum(np.mean(abs(a - b), axis=0))

    def solve_sweep(
        self,
        bar_p_up_reserve: np.ndarray,
        bar_alpha: float,
        bar_beta: float,
        rho: List[np.ndarray],
        prev_p_up_reserve: np.ndarray,
        prev_alpha: np.ndarray,
        prev_beta: np.ndarray,
        iteration_cost: List[float],
        iteration_opt_result: List[OptimizationResult],
    ) -> None:

        start = time()
        # no gamme penalty in the first iteration
        gamma = self.gamma if len(iteration_cost) > 0 else 0
        all_data = []
        for omega in range(self.nb_scenarios):
            all_data.append(
                (
                    SolverInstance.instance_to_dict(self.instance(omega, omega + 1)),
                    self.objective,
                    gamma,
                    rho,
                    omega,
                    bar_p_up_reserve,
                    bar_alpha,
                    bar_beta,
                )
            )

        if self.nb_scenarios >= 20:
            # Solve in parallel if there are many scenarios
            with concurrent.futures.ProcessPoolExecutor() as executor:
                gen = executor.map(_solve_func, all_data)
        else:
            # Solve sequentially if there are few scenarios
            gen = map(_solve_func, all_data)

        # _data = [
        #     SolverInstance.instance_to_dict(self.instance),
        #     self.objective,
        #     0,
        #     rho,
        #     0,
        #     bar_p_up_reserve,
        #     bar_alpha,
        #     bar_beta,
        # ]
        # normal_solve = _solve_func(_data)

        for omega, (instance_info, opt_result, objective_val) in enumerate(gen):
            # Get variable results
            _p_up_reserve = instance_info.p_up_reserve
            _alpha = instance_info.alpha
            _beta = instance_info.beta

            # assert opt_result.total_cost <= opt_result.base_cost_today

            iteration_cost.append(objective_val)
            iteration_opt_result.append(opt_result)

            # Store optimization results for this scenario
            prev_p_up_reserve[omega, :] = _p_up_reserve
            prev_alpha[omega] = _alpha
            prev_beta[omega] = _beta

        print(f"Solving sweep took {time() - start} seconds")

    def run_admm(self) -> List[Iteration]:
        # Initialize and run ADMM
        # NOTE: we assume equal probability for each scenario
        # TODO: make admm work with one lambda_bid as well

        # Specifiy consensus variables for ADMM
        prev_p_up_reserve = np.tile(
            self.instance.p_base * (1 - self.instance.mask), (self.nb_scenarios, 1)
        )
        prev_alpha = np.zeros(self.nb_scenarios)
        prev_beta = np.zeros(self.nb_scenarios)
        shape1 = prev_p_up_reserve.shape
        shape2 = prev_beta.shape

        bar_p_up_reserve = np.mean(prev_p_up_reserve, axis=0)
        assert bar_p_up_reserve.shape[0] == self.instance.n_hours
        bar_alpha = np.mean(prev_alpha)
        bar_beta = np.mean(prev_beta)

        # Initialize rho
        rho = [
            np.zeros(shape=shape1),
            np.zeros(shape=shape2),
            np.zeros(shape=shape2),
        ]

        j = 0
        runs = []
        print("Running ADMM...")
        while True:
            # p_up_reserve = deepcopy(prev_p_up_reserve)
            # alpha = deepcopy(prev_alpha)
            # beta = deepcopy(prev_beta)

            iteration_cost = []  # type:ignore
            iteration_opt_result = []  # type:ignore

            self.solve_sweep(
                bar_p_up_reserve,
                cast(float, bar_alpha),
                cast(float, bar_beta),
                rho,
                prev_p_up_reserve,
                prev_alpha,
                prev_beta,
                iteration_cost,
                iteration_opt_result,
            )

            # Recalculate average values, i.e. consensus variable values
            bar_p_up_reserve = np.mean(prev_p_up_reserve, axis=0)
            bar_alpha = np.mean(prev_alpha)
            bar_beta = np.mean(prev_beta)

            print("ADMM In-sample results:")
            print(
                f"bar_p_up_reserve={bar_p_up_reserve.round(2)}, bar_alpha={bar_alpha}, bar_beta={bar_beta}"
            )
            base_cost = np.mean([r.base_cost_today for r in iteration_opt_result])
            total_cost = np.mean([r.total_cost for r in iteration_opt_result])
            reserve_payment = np.mean([r.reserve_payment for r in iteration_opt_result])
            activation_payment = np.mean([r.act_payment for r in iteration_opt_result])
            penalty = np.mean([r.penalty_cost for r in iteration_opt_result])
            print(
                f"reserve_payment={reserve_payment}, activation_payment={activation_payment}, penalty={penalty}"
            )
            print(f"base_cost={base_cost}\ntotal_cost={total_cost}")

            # Update Lagrangian multipliers
            rho[0] = rho[0] + self.gamma * (prev_p_up_reserve - bar_p_up_reserve)
            rho[1] = rho[1] + self.gamma * (prev_alpha - bar_alpha)
            rho[2] = rho[2] + self.gamma * (prev_beta - bar_beta)

            # TODO: distance and convergence criteria is wrong somehow
            # conv1 = self.calculate_error(prev_p_up_reserve, p_up_reserve)
            # conv2 = self.calculate_error(prev_alpha, alpha)
            # conv3 = self.calculate_error(prev_beta, beta)
            conv1 = self.calculate_error(prev_p_up_reserve, bar_p_up_reserve)
            conv2 = self.calculate_error(prev_alpha, bar_alpha)  # type:ignore
            conv3 = self.calculate_error(prev_beta, bar_beta)  # type:ignore

            # save iteration results
            runs.append(
                Iteration(
                    j,
                    iteration_cost,
                    0,
                    conv1,
                    conv2,
                    conv3,
                    bar_p_up_reserve,
                    bar_alpha,  # type:ignore
                    bar_beta,  # type:ignore
                    deepcopy(prev_p_up_reserve),
                    deepcopy(prev_alpha),
                    deepcopy(prev_beta),
                )
            )
            print("True in-sample results:")
            info, opt_res = self.prepare_in_sample_results(runs[-1], tee=False)
            print(
                f"reserve_payment={opt_res.reserve_payment}, activation_payment={opt_res.act_payment}, penalty={opt_res.penalty_cost}"
            )
            print(f"base_cost={opt_res.base_cost_today}")
            print(f"total_cost={opt_res.total_cost}")

            print(
                f"\n\nIteration {j}: distance={round(runs[-1].distance,3)}, total_cost={round(opt_res.total_cost, 2)}\n\n"
            )
            runs[-1].total_cost = opt_res.total_cost

            if (
                runs[-1].converged(self.tol) or j > self.max_iter
            ) and j > self.min_iter:
                print(f"\n\nADMM has converged after {j} iterations\n\n")
                break

            j += 1

        return runs

    def make_p_up_reserve_feasible(self, last_iter: Iteration) -> np.ndarray:
        # Make p_up_reserve feasible by ensuring it is always less than p_base
        p_up_reserve = last_iter.bar_p_up_reserve
        for i in range(self.instance.n_hours):
            # reservation can't be bigger than baseline power
            p_up_reserve[i] = min(p_up_reserve[i], self.instance.p_base[i])
            p_up_reserve[i] = p_up_reserve[i] * (1 - self.instance.mask[i])
        return p_up_reserve

    def make_lambda_bid_feasible(
        self, instance: OptimizationInstance, last_iter: Iteration
    ) -> float:
        # Make lambda_bid feasible by ensuring it is always non-negative
        # by increasing beta until lambda_bid is non-negative
        alpha = last_iter.bar_alpha
        beta = last_iter.bar_beta

        # our bid policy
        lambda_bid = np.diff(instance.lambda_spot, append=5) * alpha + beta

        if (lambda_bid < 0).any():
            beta += abs(np.min(lambda_bid)) + 1e-4
            # lambda_bid = np.maximum(lambda_bid, 0)
        return beta

    def prepare_in_sample_results(self, last_iter: Iteration, tee: bool = True) -> Any:
        # Get results from last iteration
        # Only used for ADMM where we need to evaluate the in-sample problem
        # using average parameter values.
        # TODO: perhaps parallelize this and move to "evaluation.py"

        # NOTE: we assume equal probability for each scenario
        p_up_reserve = self.make_p_up_reserve_feasible(last_iter)

        # TODO: chunk size > 1 does NOT give same base cost. Something is wrong. Use 1 for now.
        chunk_size = 1
        opt_results = []
        if tee:
            print(f"Preparing in-sample results with chunk size {chunk_size} ...")
        start = time()
        # for omega in range(self.nb_scenarios):
        for i, chunk_instance in enumerate(self.instance.chunk_generator(chunk_size)):
            if tee:
                print(f"   Evaluating chunk {i+1}...")
            chunk_instance.max_lambda_bid = 15
            problem = Problem(self.generic_solver_instance, chunk_instance)
            Problem.customize_constraints(
                problem.model_instance, self.instance.one_lambda
            )
            problem.set_objective(self.objective(problem.model_instance))
            # fix variables
            for i in range(self.instance.n_hours):
                problem.model_instance.p_up_reserve[i].fix(p_up_reserve[i])
            problem.model_instance.alpha.fix(last_iter.bar_alpha)
            beta = self.make_lambda_bid_feasible(chunk_instance, last_iter)
            problem.model_instance.beta.fix(beta)

            opt_result = problem.solve(tee=False)
            opt_results.append(opt_result)
            # inst_info = get_variables_and_params(problem.model_instance)

        avg_opt_result = average_opt_results(opt_results)
        # assert avg_opt_result.total_cost <= avg_opt_result.base_cost_today
        if tee:
            print(f"In-sample results prepared in {time() - start} seconds")

        return (get_variables_and_params(problem.res_instance), avg_opt_result)  # type: ignore


from logs import logDecorator as lD
import jsonref, psycopg2

from lib.celery.App import app

config = jsonref.load(open('../config/config.json'))
logBase = config['logging']['logBase'] + 'lib.celeryWorkerExample.worker_1'

@app.task
@lD.log(logBase + '.add')
def add(logger, a, b):
    '''add two supplied items

    This example takes two arguments and adds them together. This
    is much like the function available with ``lib.testLib.simpleLib.py``
    and will be used only for the purpose of having a very simple function
    that can be run via a Celery worker. This function will return the
    result of the sum, or ``None`` in the case that there was an error.
    Handling errors within distributed computing tasks is generally
    complicated and needs a significant amount of thought to be put in
    while programming.

    Parameters
    ----------
    logger : {logging.logger}
        The logging instance that will log information about the execution.
        Rememebr that this is a significantly different logger than the
        one that will finally run the system. In a distributed system it
        is possible that multiple loggers will interact differently with
        different loggers and thus colating the different logs might be a
        significant challenge.
    a : {any type that supports an addition}
        The first element of the binary addition operation
    b : {any type that supports addition}
        The second element of the binary addition operation

    Returns
    -------
    type(a+b)
        Result of the addition of the two input values. In case of an error, this
        is going to return a ``None``
    '''

    try:
        result = a+b
        return result
    except Exception as e:
        logger.error('Unable to log the task: {e}')
        return None

    return