# Import Library
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tqdm import tqdm
#%%
# 버스 이용률 시각화
# 데이터 제공 : 전주시 버스 정책과

data = pd.read_csv('C:/Users/hyunj/Desktop/전주공모전자료/제공받은데이터/버스이용률.csv', encoding='utf-8')
data.info()
#%%
# 한글 폰트 사용을 위해서 세팅
from matplotlib import font_manager, rc
font_path = "C:/Windows/Fonts/NGULIM.TTF"
font = font_manager.FontProperties(fname=font_path).get_name()
rc('font', family=font)
#%%
# 승차인원 ',' 전처리하기 : object -> int

for i in tqdm(range(len(data)), desc = "승차인원 object -> int 데이터 전처리 중") :
    temp = data.loc[i, '승차인원']
    temp_list = temp.split(',')
    temp_num = int(temp_list[0] + temp_list[1])
    data.loc[i, '승차인원'] = temp_num
#%%
'''
===============================================================================
버스 이용률 시각화
===============================================================================
'''

# 코로나 발생은 2019년 12월 31일 -> 2019년 & 2020년 비교, 2019년 & 2021년 비교, 2019년 & 2022년 비교

total_2019 = sum(data.loc[(data['연도'] == 2019), '승차인원'])
total_2020 = sum(data.loc[(data['연도'] == 2020), '승차인원'])
total_2021 = sum(data.loc[(data['연도'] == 2021), '승차인원'])
total_2019_6 = sum(data.loc[(data['연도'] == 2019) &
                            ((data['월'] == 1) | (data['월'] == 2) | (data['월'] == 3) | (data['월'] == 4) | (data['월'] == 5) | (data['월'] == 6)), '승차인원'])
total_2022_6 = sum(data.loc[(data['연도'] == 2022) &
                            ((data['월'] == 1) | (data['월'] == 2) | (data['월'] == 3) | (data['월'] == 4) | (data['월'] == 5) | (data['월'] == 6)), '승차인원'])

# 2019 - 2020 - 2021 전체 버스 이용률 꺾은선 그래프
plt.figure(figsize=(10,8))
x_axis = [0,1,2]
label_x_axis = ['2019', '2020', '2021']
plt.plot(x_axis, [total_2019, total_2020, total_2021], marker = "*")
plt.axvline(x=0.5, color='r', linestyle='--', linewidth=3)
plt.xticks(x_axis, label_x_axis)
plt.title('연도별 버스 이용률')
plt.show()
#%%
# 2019년 6월까지의 데이터와 2022년 6월까지의 데이터 비교하기
plt.figure(figsize=(10,8))
x_axis = [0,1]
label_x_axis = ['2019년 6월까지', '2022년 6월까지']
plt.plot(x_axis, [total_2019_6, total_2022_6], marker = "*")
plt.axvline(x=0.5, color='r', linestyle='--', linewidth=3)
plt.xticks(x_axis, label_x_axis)
plt.title('연도별 버스 이용률')
plt.show()
#%%
# 2019 & 2020 & 2021 & 2022년 6월까지의 데이터 비교하기
#%%
# 월 별로 데이터 분석해보기
years = [2019, 2020, 2021, 2022]
months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

month_2019 = []
month_2020 = []
month_2021 = []
month_2022 = []
for year in years :
    for month in months :
        if(year == 2022 and month == 7) :
            break
        temp = data.loc[(data['연도'] ==year) & (data['월'] == month), '승차인원']
        exec("month_{}.append(temp)".format(year))

# 2019 - 2020 - 2021 - 2022 월 별로 데이터 시각화
plt.figure(figsize=(10,8))
x_axis = [i for i in range(12)]
label_x_axis = [str(i) + '월' for i in range(12)]
plt.xticks(x_axis, label_x_axis)
plt.plot(x_axis, month_2019, color = 'red', label = '2019', marker = "*")
plt.plot(x_axis, month_2020, color = 'blue', label = '2020', marker = "*")
plt.plot(x_axis, month_2021, color = 'green', label = '2021', marker = "*")
plt.plot([0, 1, 2, 3, 4, 5], month_2022, color = 'violet', label = '2022', marker = "*")
plt.title('월별 버스 이용률')
plt.legend()
plt.show()
#%%


import scrapy

class OnlankaSpider(scrapy.Spider):
    name = "onlanka"

    start_urls = [
        'https://www.onlanka.com/'
    ]

    def parse(self, response):
        for news_item in response.css('div.post.type-post'):
            yield {
                'title': news_item.css('a::attr(title)').extract_first(),
                'content': news_item.css('div.post-content p::text').extract(),
                'link': news_item.css('div.read-more a::attr(href)').extract_first(),
                'date_published': news_item.css('span.published::text').extract_first(),
                'category': news_item.css('div.post-category a::text').extract_first()
            }

        next_page = response.css('div.previous a::attr(href)').extract_first()
        if next_page is not None:
            yield response.follow(next_page, callback=self.parse)


import os
import pathlib
import logging
from rest_framework import serializers

from base.serializer import ICBaseModelSerializer, ICBaseSerializer
from base.utils.format import format_completed_process
from website.applications.app_factory import AppFactory
from website.models import WebsiteModel
from website.models.utils import get_section, insert_section, update_nginx_server_name

class SSLConfigSerializer(ICBaseSerializer):
    class CertbotSerializer(ICBaseSerializer):
        email = serializers.EmailField(
            required=False, allow_null=True, help_text="defaults to current user."
        )
        provider = serializers.CharField(default="letsencrypt", allow_null=True)

    class PathSerializer(ICBaseSerializer):
        certificate = serializers.CharField(
            required=False,
            allow_null=True,
            help_text="specify the path to save the certificate.",
        )
        key = serializers.CharField(
            required=False,
            allow_null=True,
            help_text="specify the path to save the key.",
        )

    certbot = CertbotSerializer(
        required=False,
        allow_null=True,
    )
    path = PathSerializer(
        required=False,
        allow_null=True,
    )
    method = serializers.CharField(default="http-01")

class WebsiteDomainConfigSerializer(ICBaseSerializer):
    domain = serializers.CharField(max_length=512)
    extra_domain = serializers.CharField(max_length=10240, allow_null=True)

    def update(self, instance: WebsiteModel, validated_data):
        domain = validated_data.get("domain")
        extra_domain = validated_data.get("extra_domain")
        old_domain = instance.domain
        if domain and domain != instance.domain:
            os.system(f"rm -rf  /etc/nginx/sites-enabled/{instance.domain}.conf")
            os.system(f"rm -rf  /etc/nginx/sites-available/{instance.domain}.conf")
            instance.ssl_enable = False
            instance.domain = domain

        if extra_domain and extra_domain != instance.extra_domain:
            instance.ssl_enable = False
            instance.extra_domain = extra_domain
            # 1.domain.com,2.domain,3.domain -> 1.domain.com 2.domain 3.domain
            # or
            # 1.domain.com
            # 2.domain
            # 3.domain
            # -> 1.domain.com 2.domain 3.domain
            extra_domain = instance.extra_domain.replace(",", " ").replace("\n", " ")

            instance.valid_web_server_config = update_nginx_server_name(
                instance.valid_web_server_config, instance.domain, extra_domain
            )

        available_nginx_config = f"/etc/nginx/sites-available/{instance.domain}.conf"
        enabled_nginx_config = f"/etc/nginx/sites-enabled/{instance.domain}.conf"

        with open(available_nginx_config, "w") as f:
            f.write(instance.valid_web_server_config)

        if not pathlib.Path(enabled_nginx_config).exists():
            os.system(f"ln -s {available_nginx_config} {enabled_nginx_config}")

        os.system("systemctl reload nginx")

        instance.save()
        instance.get_application().update_domain(old_domain, instance.domain)
        return validated_data

    def validate_extra_domain(self, val: str):
        if val:
            val = val.replace("\n", " ").replace("\t", " ")
            val = val.replace("  ", " ").replace("  ", " ").replace(" ", ",")
        return val

class DefaultWebsuteConfigSerializer(ICBaseSerializer):
    web_server_config = serializers.CharField(max_length=204800)

    def update(self, instance: WebsiteModel, validated_data):
        app = instance.get_application_module(instance.get_app_website_config())
        web_server_config = instance.get_nginx_config()

        if isinstance(app.read(), str):
            user_area_config = app.read()
        else:
            user_area_config = app.read().nginx

        web_server_config = insert_section(web_server_config, user_area_config, "user")
        return {"web_server_config": web_server_config}

class WebsiteConfigSerializer(ICBaseSerializer):
    web_server_config = serializers.CharField(max_length=204800)

    def update(self, instance: WebsiteModel, validated_data):
        web_server_config = validated_data.get("web_server_config")

        app = instance.get_application_module(instance.get_app_website_config())

        data = instance.get_nginx_config()
        user_config = get_section(web_server_config, "user")
        data = insert_section(data, user_config, "user")

        instance.valid_web_server_config = data

        r = instance.is_valid_configuration_001()
        if r.returncode != 0:
            raise serializers.ValidationError(
                {
                    "web_server_config": "Invalid configuration 001:"
                    + format_completed_process(r)
                }
            )
        else:
            if instance.is_valid_configuration_002(instance.valid_web_server_config):
                instance.save()
            else:
                raise serializers.ValidationError(
                    {
                        "web_server_config": "Invalid configuration 002:"
                        + format_completed_process(r)
                    }
                )
            return instance.valid_web_server_config

class WebsiteModelSerializer(ICBaseModelSerializer):
    ssl_config = SSLConfigSerializer(required=False)
    # ssl_config = serializers.SerializerMethodField('_ssl_config')
    database_id = serializers.SerializerMethodField("_get_database_id")
    database_name = serializers.SerializerMethodField()
    web_server_type_text = serializers.SerializerMethodField("_web_server_type_text")
    status_text = serializers.SerializerMethodField("_status_text")

    class Meta:
        model = WebsiteModel
        fields = "__all__"

    def create(self, validated_data):
        instance: WebsiteModel = super(WebsiteModelSerializer, self).create(
            validated_data
        )

        # 1.Create folder and file
        if instance.index_root == "/var/www/html":
            logging.info(f"mkdir -p  /var/www/{instance.domain}")
            logging.info(f"chown www-data.www-data -R {instance.index_root}")
            instance.index_root = f"/var/www/{instance.domain}"

        else:
            logging.info(f"mkdir -p  {instance.index_root}")
            logging.info(f"chown www-data.www-data -R {instance.index_root}")

        try:
            os.system(f"mkdir -p  {instance.index_root}")
            os.system(f"chown www-data.www-data -R {instance.index_root}")
        except Exception as e:
            logging.exception(f"create and chmod {instance.index_root} failed!")
        nginx_config_path = f"/etc/nginx/sites-available/{instance.domain}.conf"
        os.system(f"touch {nginx_config_path}")

        # 2.Init SSL config
        instance.or_create_ssl_config()

        # 3.Reset created instance 'ssl_enable',
        # enable website ssl: post website/{instance_pk}/enable_ssl/
        # disable website ssl: post website/{instance_pk}/disable_ssl/
        instance.ssl_enable = False

        # 4.Write web server config

        app_factory = AppFactory
        app_factory.load()

        if instance.application is None:
            text = "与君初相识，犹如故人归。嗨，别来无恙！ <br> Hello World！"
            app = app_factory.get_application_module(
                "NginxApplication",
                instance.get_app_website_config(),
                {"name": "New website", "text": text},
            )
            instance.application = "NginxApplication"
        else:
            app = app_factory.get_application_module(
                instance.application,
                instance.get_app_website_config(),
                instance.application_config,
            )

        web_server_config = instance.get_nginx_config()

        if isinstance(app.read(), str):
            user_area_config = app.read()
        else:
            user_area_config = app.read().nginx

        web_server_config = insert_section(web_server_config, user_area_config, "user")
        old_config = instance.valid_web_server_config
        instance.valid_web_server_config = web_server_config

        is_valid_configuration_001 = instance.is_valid_configuration_001()
        logging.debug(is_valid_configuration_001)

        if is_valid_configuration_001.returncode == 0:
            logging.debug("instance.is_valid_configuration_001()")
            if instance.is_valid_configuration_002(web_server_config):
                os.system("systemctl reload nginx")
                instance.status = instance.StatusType.VALID
                instance.status_info = "ok"
            else:
                instance.status = instance.StatusType.ERROR
                instance.status_info = "002:nginx configuration error.r"

        else:
            if old_config is None:
                raise serializers.ValidationError(
                    {
                        "cmd": format_completed_process(is_valid_configuration_001),
                        "valid_web_server_config": instance.valid_web_server_config,
                    }
                )
            instance.valid_web_server_config = old_config
            instance.status = instance.StatusType.ERROR
            instance.status_info = "001:nginx configuration error."

        if instance.extra_domain is None:
            extra_domain = None
        else:
            extra_domain = instance.extra_domain.replace(",", " ").replace("\n", " ")

        instance.valid_web_server_config = update_nginx_server_name(
            instance.valid_web_server_config, instance.domain, extra_domain
        )

        # 5.Create application instance
        # post application/{instance_pk}/app_create/

        instance.save()
        return instance

    def update(self, instance, validated_data):
        return super(WebsiteModelSerializer, self).update(instance, validated_data)

    def _ssl_config(self, obj: WebsiteModel) -> SSLConfigSerializer:
        return SSLConfigSerializer(obj.ssl_config)

    def _get_database_id(self, obj: WebsiteModel):
        if hasattr(obj, "databasemodel"):
            return obj.databasemodel.id

    def _web_server_type_text(self, obj: WebsiteModel):
        return obj.get_web_server_type_display()

    def _status_text(self, obj: WebsiteModel):
        return obj.get_status_display()

    def get_database_name(self, obj: WebsiteModel):
        if hasattr(obj, "databasemodel"):
            return obj.databasemodel.name

    def validate(self, data):
        return data


import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome()
driver.maximize_window()
driver.get('http://localhost:8089/Home/user/login.html')

def find_ele(lacator):

     return WebDriverWait(driver,10,1).until(lambda x:x.find_element(*lacator))

find_ele((By.XPATH,'//*[@id="username"]')).send_keys("13488888888")
find_ele((By.XPATH,'//*[@id="password"]')).send_keys('123456')
find_ele((By.XPATH,'//*[@id="verify_code"]')).send_keys('8888')
find_ele((By.XPATH,'//*[@id="loginform"]/div/div[6]/a')).click()
time.sleep(2)
driver.get('http://localhost:8089/Home/Goods/goodsInfo/id/65.html')

ele =find_ele((By.XPATH,'//*[@id="number"]'))
js = "arguments[0].value=''"
driver.execute_script(js,ele)

# find_ele((By.XPATH,'//*[@id="join_cart"]')).click()
time.sleep(2)
# driver.switch_to.frame(0)
# print(find_ele((By.XPATH, '//*[@id="addCartBox"]/div[1]/div/span')).text)
# find_ele((By.XPATH,'//*[@id="addCartBox"]/div[1]/div/div/a[1]')).click()
# time.sleep(2)
# driver.switch_to.default_content()
#
# time.sleep(2)
find_ele((By.XPATH,'//*[@id="number"]')).send_keys('2')
# driver.quit()


#!/usr/bin/env python3

# supposed examples to call:
# python3 ./scripts/build_test_macos_travisci.py -g Xcode -source_dir $TRAVIS_BUILD_DIR -build_dir $TRAVIS_BUILD_DIR/build/Xcode --build_type Debug
# python3 ./scripts/build_test_macos_travisci.py -g Xcode -source_dir $TRAVIS_BUILD_DIR -build_dir $TRAVIS_BUILD_DIR/build/Xcode --build_type Release -notclear
# python3 ./scripts/build_test_macos_travisci.py -g Ninja -source_dir $TRAVIS_BUILD_DIR -build_dir $TRAVIS_BUILD_DIR/build/Ninja/Debug --build_type Debug
# python3 ./scripts/build_test_macos_travisci.py -g Ninja -source_dir $TRAVIS_BUILD_DIR -build_dir $TRAVIS_BUILD_DIR/build/Ninja/Release --build_type Release

import os
import subprocess
import argparse
import shutil
import sys

def remove_dir(path):
  command = ['rm'] + ["-rf", path]
  try:
    subprocess.run(command, check = True)
  except subprocess.CalledProcessError as e:
    s = " "
    print(f"Command [{s.join(command)}] exit with code {e.returncode}")
    sys.exit(e.returncode)

def run_cmake(*args):
  command = ['cmake'] + list(args)
  try:
    subprocess.run(command, check=True)
  except subprocess.CalledProcessError as e:
    s = " "
    print(f"Command [{s.join(command)}] exit with code {e.returncode}")
    sys.exit(e.returncode)

def run_ctest(*args):
  command = ['ctest'] + list(args)
  try:
    subprocess.run(command, check=True)
  except subprocess.CalledProcessError as e:
    s = " "
    print(f"Command [{s.join(command)}] exit with code {e.returncode}")
    sys.exit(e.returncode)

def cmake_configure_build_test(IS_SHARED_LIBS, NOT_CLEAR_BUILD_DIR, BUILD_TYPE, CMAKE_GENERATOR, BUILD_DIR, SOURCE_DIR):
  print(f"IS_SHARED_LIBS:[{IS_SHARED_LIBS}]")
  print(f"NOT_CLEAR_BUILD_DIR:[{NOT_CLEAR_BUILD_DIR}]")
  print(f"BUILD_TYPE:[{BUILD_TYPE}]")
  print(f"CMAKE_GENERATOR:[{CMAKE_GENERATOR}]")
  print(f"BUILD_DIR:[{BUILD_DIR}]")
  print(f"SOURCE_DIR:[{SOURCE_DIR}]")

  if os.path.exists(BUILD_DIR):
    if not NOT_CLEAR_BUILD_DIR:
      remove_dir(BUILD_DIR)
      os.makedirs(BUILD_DIR, exist_ok=True)
  else:
    os.makedirs(BUILD_DIR, exist_ok=True)

  print(f"\nCurrent working directory1:[{os.getcwd()}]\n")
  os.chdir(BUILD_DIR)
  print(f"\nCurrent working directory2:[{os.getcwd()}]\n")

  IS_SHARED_LIBS_STR = str(IS_SHARED_LIBS)

  print(f"CMake configure:[cmake -DBUILD_SHARED_LIBS={IS_SHARED_LIBS_STR} -DCMAKE_BUILD_TYPE={BUILD_TYPE} -G {CMAKE_GENERATOR} {SOURCE_DIR}]\n")
  run_cmake(f"-DBUILD_SHARED_LIBS={IS_SHARED_LIBS_STR}", f"-DCMAKE_BUILD_TYPE={BUILD_TYPE}", "-G", CMAKE_GENERATOR, SOURCE_DIR)

  print(f"\nCMake build:[cmake --build . --config {BUILD_TYPE}]\n")
  run_cmake('--build', '.', '--config', BUILD_TYPE)

  print(f"\nCTest run unit tests:[ctest -VV --output-on-failure -C {BUILD_TYPE}]")
  run_ctest('-VV', '--output-on-failure', '-C', BUILD_TYPE)

def main():
  parser = argparse.ArgumentParser(description="""
  This script does:
    1. Create build directory and cd to it.
    2. Run CMake with specified generator type to generate project.
    3. Run CMake to build project.
    4. Run CTest to execute unit tests.
  """)
  parser.add_argument('--is_shared_libs', '-shared', action='store_true', help='If specified - build shared library and static otherwise.')
  parser.add_argument('--not_clear_build_dir', '-notclear', action='store_true', help='If specified - BUILD_DIR will not be cleared before cmake call')
  parser.add_argument('--build_type', default='Debug', choices=['Debug', 'Release'], help='Build type.')
  parser.add_argument('-g', default='Ninja', choices=['Xcode', 'Ninja'], help='CMake generator type.')
  parser.add_argument('-build_dir', default='./build', help='Relative or full path to build directory.')
  parser.add_argument('-source_dir', default='./', help='Relative or full path to directory with root CMakeLists.txt file.')

  args = parser.parse_args()

  IS_SHARED_LIBS = args.is_shared_libs
  NOT_CLEAR_BUILD_DIR = args.not_clear_build_dir
  BUILD_TYPE = args.build_type
  CMAKE_GENERATOR = args.g
  BUILD_DIR = os.path.abspath(args.build_dir)
  SOURCE_DIR = os.path.abspath(args.source_dir)

  cmake_configure_build_test(IS_SHARED_LIBS, NOT_CLEAR_BUILD_DIR, BUILD_TYPE, CMAKE_GENERATOR, BUILD_DIR, SOURCE_DIR)

if __name__ == "__main__":
  main()


#!/usr/bin/python3
"""list 10 commits (from the most recent to oldest)
of the repository “rails” by the user “rails”"""

import requests
from sys import argv

if __name__ == "__main__":
    a = "https://api.github.com/repos"
    URL = "{}/{}/{}/commits".format(a, argv[2], argv[1])
    resp = requests.get(URL)
    commits = resp.json()
    for c in commits[:10]:
        print(c.get("sha"), end=": ")
        print(c.get("commit").get("author").get("name"))


import torch
import torch.nn as nn
import torch.optim as optim
from prot2vec.tools.datasets import FastSemanticSimilarityDataset
from prot2vec.tools.utils import TrainingProgress
from datetime import datetime
import matplotlib.pyplot as plt
from prot2vec.models import (SiameseSimilarityNet, SiameseSimilarityPerceptronNet,
                             SiameseSimilaritySmall, SiameseSimilaritySmallPerceptron)
from prot2vec.models import count_parameters, save_checkpoint
from itertools import product
from prot2vec.Utils import Configuration
import pickle
import os

def run(run_config, gpu_device, train_only):
    # this is a best effort thing, the user must know the name of the device
    # otherwise this script will simply fail
    device = gpu_device if torch.cuda.is_available() else 'cpu'
    print(f'Using {device} device')

    config = Configuration.load_run(run_config)

    batch_size_train = config["model"]["batch_size_train"]
    batch_size_val = config["model"]["batch_size_val"]

    dir_train = config["dataset"]["dir_train"]
    dir_val = config["dataset"]["dir_val"]

    interpro_pca = config["dataset"]["interpro_pca"]
    num_pca = config["dataset"]["num_pca"]
    interpro_filename = config["dataset"]["interpro_filename"]
    semantic_similarity_filename = config["dataset"]["semantic_similarity_filename"]

    print('Loading training set...')
    ss_bp_train = FastSemanticSimilarityDataset(dir_train,
                                                batch_size=batch_size_train,
                                                shuffle=True,
                                                interpro_pca=interpro_pca,
                                                num_pca=num_pca,
                                                interpro_filename=interpro_filename,
                                                semantic_similarity_filename=semantic_similarity_filename)
    print("train", ss_bp_train.dataset_len)
    print("train", ss_bp_train.interpro_df.shape)

    if not train_only:
        print('Loading validation set...')
        ss_bp_val = FastSemanticSimilarityDataset(dir_val,
                                                  batch_size=batch_size_val,
                                                  shuffle=True,
                                                  interpro_pca=interpro_pca,
                                                  num_pca=num_pca,
                                                  interpro_filename=interpro_filename,
                                                  semantic_similarity_filename=semantic_similarity_filename)
    # ss_bp_train = SemanticSimilarityOnDeviceDataset('../83333/train_data/', device)
    # ss_bp_val = SemanticSimilarityOnDeviceDataset('../83333/val_data/', device)
    # ss_bp_test = SemanticSimilarityOnDeviceDataset('../83333/test_data/', device)

    # ss_bp_train = SemanticSimilarityDatasetDevice('E:/prot2vec/83333/train_data/',
    #                                               device, 'E:/prot2vec/83333/train_data/tensor.pt')
    # ss_bp_val = SemanticSimilarityDatasetDevice('E:/prot2vec/83333/val_data/',
    #                                             device, 'E:/prot2vec/83333/val_data/tensor.pt')
    # ss_bp_test = SemanticSimilarityDatasetDevice('E:/prot2vec/83333/test_data/',
    #                                              device, 'E:/prot2vec/83333/test_data/tensor.pt')

        print("validation", ss_bp_val.dataset_len)
        print("validation", ss_bp_val.interpro_df.shape)

    model_classes = [
        SiameseSimilarityNet, SiameseSimilarityPerceptronNet,
        SiameseSimilaritySmall, SiameseSimilaritySmallPerceptron
    ]
    model_classes = [SiameseSimilarityNet]

    activations = ['relu', 'sigmoid']
    activations = ['sigmoid']

    num_interpro_features = ss_bp_train.interpro_df.shape[1]

    for model_class, activation in product(model_classes, activations):

        model = model_class(num_interpro_features,
                            activation=activation,
                            dim_first_hidden_layer=config["model"]["dim_first_hidden_layer"]).to(device)

        count_parameters(model)

        optimizer = optim.Adam(model.parameters(),
                               lr=config["optimizer"]["learning_rate"])
        num_epochs = config["training"]["num_epochs"]
        criterion = nn.MSELoss()
        save_name = f'[{model.name()}]-{num_epochs}_epochs.pt'
        alias = config["model"]["alias"]
        print(f'running {save_name} with alias {alias}')
        save_name = save_name if alias == "infer" else alias
        save_filename_model = os.path.join(config["model"]["dir_model_output"], save_name)

        best_val_loss = float("Inf")
        train_losses = []
        val_losses = []

        with TrainingProgress() as progress:
            epochs = progress.add_task("[green]Epochs", progress_type="epochs", total=num_epochs)
            for epoch in range(num_epochs):
                running_loss = 0.0
                model.train()
                training = progress.add_task(f"[magenta]Training [{epoch+1}]",
                                             total=len(ss_bp_train), progress_type="training")
                if not train_only:
                    validation = progress.add_task(f"[cyan]Validation [{epoch+1}]",
                                                   total=len(ss_bp_val), progress_type="validation")

                for curr_batch, (p1, p2, sim) in enumerate(ss_bp_train):
                    # forward
                    p1 = p1.to(device)
                    p2 = p2.to(device)
                    sim = sim.to(device)
                    outputs = model(p1, p2)
                    loss = criterion(outputs, sim)

                    # backward and optimize
                    optimizer.zero_grad()
                    loss.backward()
                    optimizer.step()
                    running_loss += loss.item()
                    progress.advance(training)

                n = len(ss_bp_train)
                avg_train_loss = running_loss / n
                train_losses.append(avg_train_loss)

                if not train_only:
                    val_running_loss = 0.0
                    with torch.no_grad():
                        model.eval()
                        for num_batch, (p1, p2, sim) in enumerate(ss_bp_val):
                            p1 = p1.to(device)
                            p2 = p2.to(device)
                            sim = sim.to(device)
                            outputs = model(p1, p2)
                            loss = criterion(outputs, sim)
                            val_running_loss += loss.item()
                            progress.advance(validation)
                    avg_val_loss = val_running_loss / len(ss_bp_val)
                    val_losses.append(avg_val_loss)

                    print('Epoch [{}/{}],Train Loss: {:.4f}, Valid Loss: {:.8f}'
                          .format(epoch + 1, num_epochs, avg_train_loss, avg_val_loss))
                    if avg_val_loss < best_val_loss:
                        best_val_loss = avg_val_loss
                        save_checkpoint(save_filename_model, model, optimizer, best_val_loss)
                else:
                        save_checkpoint(save_filename_model, model, optimizer, -1)

                progress.tasks[training].visible = False
                if not train_only:
                    progress.tasks[validation].visible = False
                progress.advance(epochs)

        # plotting of training and validation loss
        fix, axs = plt.subplots(nrows=2, figsize=(10, 10), facecolor='white')
        for i, ax in enumerate(axs):
            ax.set_xlabel('Epoch')
            ax.set_ylabel('Loss')
            ax.grid(ls=':', zorder=1)
            if i != 0:
                ax.set_yscale('log')
                ax.set_ylabel('Loss (log scale)')
            ax.plot(train_losses, label='Train Loss')
            ax.plot(val_losses, label="Validation Loss")
            ax.legend(loc='upper right')
        basename = os.path.join(
            config["training"]["dir_training_out"],
            f"loss-evol-[{save_name}]-[{datetime.today().strftime('%Y-%m-%d-%H-%M-%S')}]"
        )
        figname = f'{basename}.png'
        dataname = f'{basename}.pkl'
        plt.savefig(figname)
        plt.close('all')
        with open(dataname, 'wb') as f:
            pickle.dump(train_losses, f)
            pickle.dump(val_losses, f)

    print("Finished Training")

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser("Train a prot2vec model.")
    parser.add_argument("--run-config", "--c",
                        help="Path to the run configuration file",
                        required=True)
    parser.add_argument("--gpu-device", "--g",
                        help="The name of the gpu device, `cuda` by default",
                        default="cuda",
                        required=False)
    parser.add_argument("--train-only", "--t", action="store_true")
    args = parser.parse_args()
    run(args.run_config, args.gpu_device, args.train_only)


import scipy.io as sio
import numpy as np
from liegroups import SE3, SO3

def load_data_1(data_filename):
    #Data loader for Emmett's Synethetic datasets
    data_dict = sio.loadmat(data_filename)
    pose_array = data_dict['T_vki_list']
    T_vki = [SE3.from_matrix(pose_array[i, :, :]) for i in range(pose_array.shape[0])]
    pose_array = data_dict['T_ci_list']
    T_ci = [SE3.from_matrix(pose_array[i, :, :]) for i in range(pose_array.shape[0])]
    extcal = data_dict['extcal']
    return T_vki, T_ci, extcal

def load_data_from_numpy(data_filename):
    pose_array = np.load(data_filename)
    T = [SE3.from_matrix(pose_array[i, :, :]) for i in range(pose_array.shape[0])]

    return T

def load_data_from_txt(data_filename):
    raw_data = np.loadtxt(data_filename)
    mat_list = []
    for row in range(raw_data.shape[0]):
        matrix = np.eye(4)
        matrix[:3, :] = np.reshape(raw_data[row, :], (3, 4))
        mat_list.append(matrix)

    T = [SE3.from_matrix(mat_list[i]) for i in range(len(mat_list))]

    return T

def load_brookshire_data(data_filename):
    data_dict = sio.loadmat(data_filename)
    pose_array = data_dict['T_v_rel_list']
    T_v_rel = [SE3.from_matrix(pose_array[:, :, i]) for i in range(pose_array.shape[2])]
    pose_array = data_dict['T_c_rel_list']
    T_c_rel = [SE3.from_matrix(pose_array[:, :, i]) for i in range(pose_array.shape[2])]
    extcal = data_dict['extcal']
    return T_v_rel, T_c_rel, extcal

def results_saver(data_filename, results):
    results_name_base = data_filename.replace(".mat", "")
    keys = results.keys()
    for key in keys:
        results_dict = results[key]
        results_filename = results_name_base + "_" + key + ".mat"
        sio.savemat(results_filename, results_dict)
    return

def print_brookshire_results():
    results = sio.loadmat("../results/brookshire_data_RCH.mat")
    print(results["dual_trans_error"])
    print(results["dual_rot_error"])
    print(results["dual_alpha_error"])
    print(results["rel_trans_error"])
    print(results["rel_rot_error"])
    print(results["rel_alpha_error"])
    return

def results_loader(prefixes, dataset_name, constraints):
    data_dict = {}
    for prefix in prefixes:
        prefix_dict = {}
        for constraint in constraints:
            filename = "../results/" + prefix + "_" + dataset_name + "_" + constraint
            prefix_dict[constraint] =sio.loadmat(filename)
        data_dict[prefix] = prefix_dict
    return data_dict

def inertial_to_relative(pose_list, offset=1, reverse=False):
    #Changes SE3 poses from relative to intertial to relative vs timestamps
    if not reverse:
        rel_pose_list = [pose_list[i].dot(pose_list[i + offset].inv()) for i in range(0, len(pose_list) - offset, offset)] #This makes the poses T_{s_is_i+1}
    else:
        rel_pose_list = [pose_list[i].inv().dot(pose_list[i + offset]) for i in range(0, len(pose_list) - offset, offset)] #This makes the poses T_{s_is_i+1}

    return rel_pose_list

def inertial_to_relative_numpy(pose_list, offset=1):
    rel_pose_list = [pose_list[i].dot(np.linalg.inv(pose_list[i + offset])) for i in range(0, len(pose_list) - offset, offset)]

    return rel_pose_list

def add_noise(pose_list, trans_noise, rot_noise):
    ''' Add Noise to the pose measurements as a percentage of the translation and rotation magnitude'''
    #Create the translation noise vectors
    trans_noise_sigma = trans_noise * np.linalg.norm(np.array([pose.trans  for pose in pose_list]), axis=1)
    trans_noise_vec = [np.random.randn((3))*trans_noise_sigma[i] for i in range(len(pose_list))]

    #Create the rotation noise vectors
    rot_noise_sigma = rot_noise *np.linalg.norm(np.array([pose.rot.log()  for pose in pose_list]), axis=1)
    rot_noise_unit_vecs = np.random.rand(3, len(pose_list))
    rot_noise_unit_vecs=  rot_noise_unit_vecs/ np.linalg.norm(rot_noise_unit_vecs, axis=0)
    rot_noise_vec = [rot_noise_sigma[i] * np.random.randn() * rot_noise_unit_vecs[:, i]  for i in range(len(pose_list))]

    #Add the noise to the poses
    noisy_poses = [SE3(rot=SO3.exp(rot_noise_vec[i]).dot(pose.rot), trans=pose.trans + trans_noise_vec[i]) for i, pose in enumerate(pose_list)]

    return noisy_poses


from pathlib import Path
import numpy as np

from type_def import Converter, MultiConverter, Storage, TechnologyType, CodeGenerator, Code, InputEnergy, OutputEnergy
from misc import CodeBook, seperator_to_csv, ConverterStorageCodeBook, StorageCodeBook
from build_in_functions import iterate_mapping
from load_data import dump_transmission_db, load_transmission_db

def converter_detail_block(code, input_energy, out_energy, is_bidirectional, year, efficiency, total_cost, lifetime, OaM_rate, converter_list):
    name = code
    comment = "this is a comment"
    if input_energy != InputEnergy.ELECTRIC_ENERGY:
        input_energy = input_energy.upper()
    converter_list.append(["#code",code,"#name",name,"#input",input_energy,"#output",*(i for i in out_energy),"#bidirectional",is_bidirectional,"#comment",comment])
    #efficiency row
    type_ = "DVP_linear"

    start_date = str(year) + "-01-01_00:00"
    converter_list.append(["efficiency_new","#type",type_,"#data",start_date,efficiency])

    converter_list.append(["cost","#type",type_,"#data",start_date,total_cost])

    converter_list.append(["lifetime","#type",type_,"#data",start_date,lifetime])

    converter_list.append(["OaM_rate","#type",type_,"#data",start_date,OaM_rate])
    #last_row
    converter_list.append(["#endblock"])

def converter_block(technology, technology_type, input_energy, out_energy, year, efficiency, lifetime, total_cost, OaM_rate, e2p_ratio, converter_list):
    if technology_type in (TechnologyType.BATTERY, TechnologyType.PUMPED):
        is_bidirectional = str(True).lower()
    else:
        is_bidirectional = str(False).lower()

    # if technology_type == TechnologyType.HYDROGEN_GAS:
    #     code = Code.H2_ELECTROLYSER
    #     inp_energy = InputEnergy.ELECTRIC_ENERGY
    #     out_energy = [OutputEnergy.H2]
    #     efficiency = 1
    #     total_cost = total_cost*(e2p_ratio[0]/(e2p_ratio[0]+1))/2
    #     converter_detail_block(code, inp_energy, out_energy, is_bidirectional, year, efficiency, total_cost, lifetime, OaM_rate, converter_list)

    # if technology_type == TechnologyType.HYDROGEN_FUELCELL:
    #     code = Code.H2_ELECTROLYSER_FC
    #     inp_energy = InputEnergy.ELECTRIC_ENERGY
    #     out_energy = [OutputEnergy.H2_FC]
    #     efficiency = 1
    #     total_cost = total_cost*(e2p_ratio[0]/(e2p_ratio[0]+1))/2
    #     converter_detail_block(code, inp_energy, out_energy, is_bidirectional, year, efficiency, total_cost, lifetime, OaM_rate, converter_list)

    code = CodeBook[CodeGenerator(technology, technology_type, input_energy).to_str()]
    if technology_type in ConverterStorageCodeBook.keys():
        code = ConverterStorageCodeBook[technology_type].code
        input_energy = ConverterStorageCodeBook[technology_type].input_energy
        out_energy = [ConverterStorageCodeBook[technology_type].output_energy]
        efficiency = 1

    if technology_type == TechnologyType.BATTERY:
        total_cost = total_cost*(e2p_ratio[0]/(e2p_ratio[0]+1))
    elif technology_type == TechnologyType.PUMPED:
        total_cost = total_cost*(e2p_ratio[0]/(e2p_ratio[0]+1))

    if code == Code.WIND_OFF:
        input_energy = InputEnergy.WIND_OFF
    elif code == Code.WIND_ONS:
        input_energy = InputEnergy.WIND_ONS
    elif code == Code.TRANSMISSION_IMPORT:
        input_energy = InputEnergy.TRADE_IMPORT

    input_energy = input_energy.replace(" ","_")
    input_energy = InputEnergy.ELECTRIC_ENERGY if input_energy == InputEnergy.ELECTRICITY else input_energy

    converter_detail_block(code, input_energy, out_energy, is_bidirectional, year, efficiency, total_cost, lifetime, OaM_rate, converter_list)

def storage_detail_block(technology_type, year, efficiency, lifetime, total_cost, OaM_rate, e2p_ratio, storage_list):
    code = StorageCodeBook[technology_type].code
    input_energy = StorageCodeBook[technology_type].input_energy
    out_energy = StorageCodeBook[technology_type].output_energy
    name = code
    storage_list.append(["#code",code,"#name",name,"#input",input_energy,"#output", out_energy])
    #efficiency row
    type_ = "DVP_linear"
    start_date = str(year) + "-01-01_00:00"
    storage_list.append(["efficiency_new","#type",type_,"#data",start_date,efficiency])

    if technology_type == TechnologyType.BATTERY:
        total_cost = total_cost/(e2p_ratio+1)
    elif technology_type == TechnologyType.HYDROGEN_FUELCELL:
        total_cost = total_cost/(e2p_ratio+1)
    elif technology_type == TechnologyType.HYDROGEN_GAS:
        total_cost = total_cost/(e2p_ratio+1)
    elif technology_type == TechnologyType.PUMPED:
        total_cost = total_cost/(e2p_ratio+1)

    storage_list.append(["cost","#type",type_,"#data",start_date,total_cost])

    storage_list.append(["lifetime","#type",type_,"#data",start_date,lifetime])

    storage_list.append(["OaM_rate","#type",type_,"#data",start_date,OaM_rate])
    #last_row
    storage_list.append(["#endblock"])

def multiconverter_detail_block(technology, technology_type, input_energy, out_energy, year, emission_factor, efficiency, lifetime, total_cost, OaM_rate, multiconverter_list):
    code = CodeBook[CodeGenerator(technology, technology_type, input_energy).to_str()]
    name = code
    input_energy = input_energy.replace(" ","_")
    input_energy = InputEnergy.ELECTRIC_ENERGY if input_energy == InputEnergy.ELECTRICITY else input_energy.upper()
    multiconverter_list.append(["#code",code,"#name",name,"#input",input_energy])
    #output_energy row
    if ('co2' or 'CO2') not in out_energy:
        out_energy.append('CO2')

    multiconverter_list.append(["#output",*(i for i in out_energy)])
    #conversion row
    if emission_factor == 0:
        emission_factor = 1e-9
    else:
        emission_factor = 1000*emission_factor

    multiconverter_list.append(["#conversion",str(-1),emission_factor])
    #efficiency row
    type_ = "DVP_linear"

    start_date = str(year) + "-01-01_00:00"
    multiconverter_list.append(["efficiency_new","#type",type_,"#data",start_date,efficiency])

    multiconverter_list.append(["cost","#type",type_,"#data",start_date,total_cost])

    multiconverter_list.append(["lifetime","#type",type_,"#data",start_date,lifetime])

    multiconverter_list.append(["OaM_rate","#type",type_,"#data",start_date,OaM_rate])
    #last_row
    multiconverter_list.append(["#endblock"])

def transmission_detail_block(region_A, region_B, technology, technology_type, input_energy, out_energy, year, efficiency, lifetime, total_cost, OaM_rate, transmission_list):
    code  = 'hvac' + '_' + region_A + '_' + region_B
    name = str(technology_type) + '_' + 'Elec'
    is_bidirectional = str(True).lower()
    input_energy = InputEnergy.ELECTRIC_ENERGY if input_energy == InputEnergy.ELECTRICITY else input_energy.upper()
    transmission_list.append(["#code",code,"#name",name,"#input",input_energy,"#output",*(i for i in out_energy),"#bidirectional",is_bidirectional])
    #efficiency row
    type_ = "DVP_linear"

    start_date = str(year) + "-01-01_00:00"
    transmission_list.append(["efficiency_new","#type",type_,"#data",start_date,efficiency])

    transmission_list.append(["cost","#type",type_,"#data",start_date,total_cost])

    transmission_list.append(["lifetime","#type",type_,"#data",start_date,lifetime])

    transmission_list.append(["OaM_rate","#type",type_,"#data",start_date,OaM_rate])

    transmission_list.append(["length_dep_loss","#type",type_,"#data",start_date,str(0)])
    transmission_list.append(["length_dep_cost","#type",type_,"#data",start_date,str(0)])
    #last_row
    transmission_list.append(["#endblock"])

def transmission_detail(technology, technology_type, inp_energy, out_energy, year, efficiency, lifetime, cost_per_len, OaM_rate, transmission_list, SCENARIO_ID):
    dump_transmission_db(SCENARIO_ID)
    data = load_transmission_db(SCENARIO_ID)
    links = iterate_mapping(data,"scalars_transmission[? year == `{}` && parameter_name == 'installed capacity' && technology_type=='{}'].region".format(year, technology_type))
    for link in links:
        if len(link) == 2:
            try:
                length = iterate_mapping(data,"scalars_transmission[? year == `{}` && parameter_name == 'distance' && technology_type=='{}' && region==['{}','{}']].value".format(year, technology_type, link[0], link[1]))[0]
            except:
                length = 300
            total_cost = length*1000 * cost_per_len
            transmission_detail_block(link[0], link[1], technology, technology_type, inp_energy, out_energy, year, efficiency, lifetime, total_cost, OaM_rate, transmission_list)

def primary_energy_block(energy, year, base, value, energy_list):
    if energy != InputEnergy.ELECTRIC_ENERGY:
        energy = energy.upper()
    energy_list.append(['#code', energy, '#name', energy])
    table = 'TBD_lookupTable'
    energy_list.append(['cost_table', '#type', table])
    type_ = 'DVP_const'
    start_date = str(year) + "-01-01_00:00"
    energy_list.append(['base', '#type', type_,'#data', start_date, base])
    energy_list.append(['value', '#type', type_,'#data', start_date, value])
    energy_list.append(['#endtable'])
    energy_list.append(['#endblock'])

def link_detail_block(link, year, length, installation, link_list):
    region_A = link[0]
    region_B = link[1]
    code = ("_").join([region_A, region_B])
    link_list.append(["#code",code,"#region_A",region_A,"#region_B",region_B])
    #length row
    type_ = "DVP_const"
    start_date = str(year) + "-01-01_00:00"
    link_list.append(["length","#type",type_,"#data",start_date,length])
    # converter_code row
    converter_code = 'hvac_' + code
    link_list.append(["#converter","#code",converter_code])
    #installation row
    link_list.append(["installation","#type",type_,"#data",start_date,installation])

    link_list.append(["#endblock"])

def timeseries_detail_block(year, region, input_energy, timeseries, cwd):
    csv_list = []
    csv_list.append(["#comment","===============generation time series============================================"])
    base_type = "DVP_const"
    base = 1000000
    year = year.replace('T','_')[:-3]
    csv_list.append(["base", "#type", base_type, "#data", year, base])
    value_type = "TS_repeat_const"
    csv_list.append(["value", "#type", value_type, "#interval", "1h", "#start", year, "#data", *(t for t in timeseries)])
    csv_list.append(["#endtable"])

    filename = year.split("-")[0] + '/TimeSeries/' + region + '/' + region + '_' + input_energy.replace(" ","_").upper() + '.csv'
    seperator_to_csv(csv_list, filename, cwd)

def primary_energy_minus_one_detail_block(year, cwd):
    csv_list = []
    csv_list.append(["#comment","unlimited -1 primary ressource"])
    base_type = "DVP_const"
    base = 1E15
    date = str(year) + "-01-01_00:00"
    csv_list.append(["base", "#type", base_type, "#data", date, base])
    value_type = "DVP_linear"
    value = -1
    csv_list.append(["value", "#type", value_type, "#data", date, value])
    csv_list.append(["#endtable"])

    filename = str(year) + '/TimeSeries/PrimaryEnergyUnlimited_minusOne.csv'
    seperator_to_csv(csv_list, filename, cwd)

def installation_list_result(year, cwd):
    csv_list = []
    csv_list.append(["#comment","MOUNTING-CODE.TECH-CODE;DATA-TYPE;DATA(may contain placeholders varxy);(if applicable) next lines:;#varxy;INIT-POINT;lBOUND;uBOUND;"])
    csv_list.append(["#empty"])
    filename = str(year) + '/InstallationListResult.csv'
    seperator_to_csv(csv_list, filename, cwd)

def region_detail_block(region, year, demand_per_a, region_csv):
    region_csv.append(["#code", region, "#name", region])
    type_dyn = "TS_repeat_const"
    start_date = year.replace('T','_')[:-3]

    source_path = "./TimeSeries/" + region + "/demand_elec.csv"
    region_csv.append(["demand_electric_dyn", "#type", type_dyn, "#interval", "1h", "#start", start_date, "#data_source_path", source_path])
    type_a = "DVP_linear"
    region_csv.append(["demand_electric_per_a", "#type", type_a, "#data", start_date, demand_per_a])

def region_primary_energy_block(region, input_energy, region_csv):
    region_csv.append(["#primary_energy", "#code", input_energy.replace(' ','_').upper()])
    lookUpTable = "TBD_lookupTable"
    energy = input_energy.replace(" ","_").upper()
    source_path = "./TimeSeries/" + region + "/" + region + "_" + energy + ".csv"
    region_csv.append(["potential", "#type", lookUpTable, "#data_source_path", source_path])

def determine_primary_source_path(year, region, input_energy, cwd):
    year = year.split('-')[0]
    domestic_limit_path = '{}/{}/TimeSeries/PrimaryEnergyLimited_{}_{}.csv'.format(cwd, year, region, input_energy)
    if Path(domestic_limit_path).exists():
        return './TimeSeries/PrimaryEnergyLimited_{}_{}.csv'.format(region, input_energy)
    else:
        return './TimeSeries/PrimaryEnergyUnlimited_minusOne.csv'

def region_primary_energy_block_minusone(year, region, input_energy, region_csv, cwd):
    region_csv.append(["#primary_energy", "#code", input_energy.replace(' ','_').upper()])
    lookUpTable = "TBD_lookupTable"
    source_path = determine_primary_source_path(year, region, input_energy, cwd)
    region_csv.append(["potential", "#type", lookUpTable, "#data_source_path", source_path])

def region_converter_block(region, code, installation, start_date, end_date, region_csv):
    region_csv.append(["#converter", "#code", code])
    converter_type = "DVP_const"
    region_csv.append(["installation", "#type", converter_type, "#data", start_date, installation, end_date, 0])

def region_multiconverter_block(region, code, installation, start_date, end_date, region_csv):
    region_csv.append(["#multi-converter", "#code", code])
    converter_type = "DVP_const"
    region_csv.append(["installation", "#type", converter_type, "#data", start_date, installation, end_date, 0])

def region_storage_block(region, code, installation, start_date, end_date, region_csv):
    region_csv.append(["#storage", "#code", code])
    converter_type = "DVP_const"
    region_csv.append(["installation", "#type", converter_type, "#data", start_date, installation, end_date, 0])

TRADE_DEMAND = {}
TRADE_DEMAND[2016]=[]
TRADE_DEMAND[2030]=[]
TRADE_DEMAND[2050]=[]
TIME_DEMAND={}
TIME_DEMAND[2016]=[]
TIME_DEMAND[2030]=[]
TIME_DEMAND[2050]=[]

def region_dir_block(region, year, timeseries, trade_series, outputs_primary_energy, trade_primary_energy, outputs_converter, e2p_ratio, data, region_csv, cwd):
    dirname = year.split("-")[0]+'/regions/'
    Path(dirname).mkdir(exist_ok=True, parents=True)

    demand_per_a = find_demand(trade_series, timeseries, year)

    region_detail_block(region, year, demand_per_a, region_csv)

    input_energies = set([output['energy'] for output in outputs_primary_energy if output['energy']])
    for input_energy in input_energies:
        if input_energy != InputEnergy.AIR:
            region_primary_energy_block(region, input_energy, region_csv)

    for output in outputs_primary_energy:
        input_energy = output['energy']
        if input_energy == InputEnergy.AIR:
            tech_type = output['tech_type']
            if tech_type == TechnologyType.ONSHORE:
                input_energy = InputEnergy.WIND_ONS
            elif tech_type == TechnologyType.OFFSHORE:
                input_energy = InputEnergy.WIND_OFF

            region_primary_energy_block(region, input_energy, region_csv)

    if len(trade_primary_energy):
        region_primary_energy_block(region, 'trade import', region_csv)

    outputs_converter_set = set([output['energy'] for output in outputs_converter])
    for input_energy in outputs_converter_set:
        if input_energy not in (output['energy'] for output in outputs_primary_energy) and input_energy not in ('unknown', 'electricity'):
            region_primary_energy_block_minusone(year, region, input_energy, region_csv, cwd)

    for output in outputs_converter:
        input_energy = output['energy']
        tech = output['tech']
        if tech in [mconverter.value for mconverter in MultiConverter]:
            region_primary_energy_block_minusone(year, region, "CO2", region_csv, cwd)
            break

    for output in outputs_converter:
        input_energy = output['energy']
        tech = output['tech']
        tech_type = output['tech_type']
        installation = output['installation']/1000.0
        year = year.split("-")[0]
        start_date = str(year) + "-01-01_00:00"
        end_date = str(int(year)+1) + "-01-01 00:00:00"
        if CodeGenerator(tech, tech_type, input_energy).to_str() in CodeBook:
            code = CodeBook[CodeGenerator(tech, tech_type, input_energy).to_str()]
        else:
            continue

        if (tech in [converter.value for converter in Converter] or tech_type=='trade import' or\
            (tech=='generator' and tech_type==TechnologyType.GAS and input_energy==InputEnergy.HYDROGEN)):
            region_converter_block(region, code, installation, start_date, end_date, region_csv)

        # if tech_type == TechnologyType.HYDROGEN_GAS:
            # code = Code.H2_ELECTROLYSER
            # region_converter_block(region, code, installation, start_date, end_date, region_csv)

        # if tech_type == TechnologyType.HYDROGEN_FUELCELL:
            # code = Code.H2_ELECTROLYSER_FC
            # region_converter_block(region, code, installation, start_date, end_date, region_csv)

        if tech_type in ConverterStorageCodeBook.keys():
            code = ConverterStorageCodeBook[tech_type].code
            region_converter_block(region, code, installation, start_date, end_date, region_csv)

    for output in outputs_converter:
        input_energy = output['energy']
        tech = output['tech']
        tech_type = output['tech_type']
        installation = output['installation']/1000.0
        year = year.split("-")[0]
        start_date = str(year) + "-01-01_00:00"
        end_date = str(int(year)+1) + "-01-01_00:00"
        if CodeGenerator(tech, tech_type, input_energy).to_str() in CodeBook:
            code = CodeBook[CodeGenerator(tech, tech_type, input_energy).to_str()]
        else:
            continue

        code = CodeBook[CodeGenerator(tech, tech_type, input_energy).to_str()]

        if tech in [mconverter.value for mconverter in MultiConverter]:
            region_multiconverter_block(region, code, installation, start_date, end_date, region_csv)

    for output in outputs_converter:
        input_energy = output['energy']
        tech = output['tech']
        tech_type = output['tech_type']
        installation = output['installation']
        year = year.split("-")[0]
        start_date = str(year) + "-01-01_00:00"
        end_date = str(int(year)+1) + "-01-01_00:00"
        if CodeGenerator(tech, tech_type, input_energy).to_str() in CodeBook:
            code = CodeBook[CodeGenerator(tech, tech_type, input_energy).to_str()]
        else:
            continue
        code = CodeBook[CodeGenerator(tech, tech_type, input_energy).to_str()]
        if tech in [storage.value for storage in Storage]:
            try:
                ratio = [e2p['E2P'] for e2p in e2p_ratio if e2p['tech_type'] == tech_type][0]
            except:
                ratio = 1
            storage_installation = installation * ratio
            region_storage_block(region, code, storage_installation, start_date, end_date, region_csv)

    region_csv.append(["#endblock"])

def find_demand(trade_series, timeseries, year):
    try:
        demand_per_a_trade = sum(trade_series[0])/1000.0
    except:
        demand_per_a_trade = 0
    try:
        demand_per_a_time = sum(timeseries[0])/1000.0
    except:
        demand_per_a_time = 0

    try:
        year = int(year.split("-")[0])
    except:
        year = int(year)

    TRADE_DEMAND[year].append(demand_per_a_trade)
    TIME_DEMAND[year].append(demand_per_a_time)
    demand_per_a = demand_per_a_time + demand_per_a_trade
    return demand_per_a

def installation_list_block(name, installed_capacity, region_code_installation_value, installation_csv, year):
    start_date = "{}-01-01_00:00".format(year)
    end_date = "{}-01-01_00:00".format(year+1)
    installation_csv.append([name, "#type", "DVP_linear", "#data", start_date, "var0", end_date, 0,''])
    # installation_csv.append(["#var0", installed_capacity, installed_capacity, region_code_installation_value,''])
    installation_csv.append(["#var0", 0, 0, region_code_installation_value,''])


from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QToolTip, QMessageBox, QMainWindow, QGridLayout, QLabel, QLineEdit, QComboBox, QTextEdit
import socket
import setuptools
import psutil
import netaddr
import netifaces
import threading
import os
import platform
import sys
import shutil
from PyQt5.QtCore import *

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Le serveur de chat")
        self.resize(300, 400)
        self.setup_ui()

    def setup_ui(self):
        self.label = QLabel("Serveur")
        self.line_edit = QLineEdit("127.0.0.1")
        self.label2 = QLabel("Port")
        self.line_edit2 = QLineEdit("10000")
        self.button = QPushButton("Démarrer le serveur")
        self.label3 = QLabel("Nombre maximum de clients")
        self.line_edit3 = QLineEdit("5")
        self.text_edit = QTextEdit()
        self.text_edit.setReadOnly(True)

        self.button.clicked.connect(self.demarrer_serveur)

        layout = QGridLayout()
        layout.addWidget(self.label, 0, 0)
        layout.addWidget(self.line_edit, 0, 1)
        layout.addWidget(self.label2, 1, 0)
        layout.addWidget(self.line_edit2, 1, 1)
        layout.addWidget(self.label3, 2, 0)
        layout.addWidget(self.line_edit3, 2, 1)
        layout.addWidget(self.button, 3, 0, 1, 3)
        layout.addWidget(self.text_edit, 4, 0, 1, 3)
        self.setLayout(layout)

    def demarrer_serveur(self):
        self.serveur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.serveur.bind((self.line_edit.text(), int(self.line_edit2.text())))
        self.serveur.listen(int(self.line_edit3.text()))
        # self.button.setEnabled(True)
        self.button.setText("Arrêter le serveur")
        self.label.setText("Serveur démarré")
        self.button.clicked.connect(self.arreter_serveur)
        self.label2.setText("Attente de connexion")
        self.label3.setText("Nombre de clients connectés : 0")
        self.thread_ecoute = threading.Thread(target=self.ecoute)
        self.thread_ecoute.start()

    def arreter_serveur(self):
        self.serveur.close()
        self.label.setText("Serveur")
        self.label2.setText("Port")
        self.label3.setText("Nombre maximum de clients")
        self.button.clicked.connect(self.demarrer_serveur)
        self.button.setEnabled(True)
        self.text_edit.clear()

    def ecoute(self):
        while True:
            self.connexion, self.adresse = self.serveur.accept()
            self.label2.setText("Connexion établie avec {}".format(self.adresse))
            self.thread_reception = threading.Thread(target=self.reception)
            self.thread_reception.start()

    def reception(self):
        while True:
            self.message_recu = self.connexion.recv(1024).decode()
            self.text_edit.append(self.message_recu)
            self.label3.setText("Nombre de clients connectés : {}".format(len(threading.enumerate())-2))

if __name__ == "__main__":
    app = QApplication([])
    window = Window()
    window.show()
    app.exec_()


from games.balance_game import BalanceGame
from lib.utilities import load_obj
from lib.activator_funcs import sigmoid
from lib.fixed_top_nn import FixedTopologyNeuralNetwork
import sys

sampling_counts = 1
if len(sys.argv) > 1:
    sampling_counts = int(sys.argv[1])

bestIndiv = None
bestIndivScore = None
model = load_obj(800, 'models/cartpole/cmaes_cartpole')
game = BalanceGame()
topology = [(4, sigmoid), (1, sigmoid)]

for i in range(sampling_counts):
    indiv = model.sample()[0]
    score = game.play(FixedTopologyNeuralNetwork(4,topology, indiv))
    if not bestIndivScore or bestIndivScore < score:
        bestIndivScore = score
        bestIndiv = indiv

print(game.play(FixedTopologyNeuralNetwork(4,topology, bestIndiv), render=True, games_amount=3))


#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
Created on Wed Dec 27 11:19:14 2017

@author: tgadfort
"""

import sys
if '/Users/tgadfort/Python' not in sys.path:
    sys.path.insert(0, '/Users/tgadfort/Python')

from pandas import read_csv, DataFrame, Series, to_numeric
from numpy import repeat, append
from sklearn import datasets

from logger import info
from mvapath import getDataDir
from fileio import getJoblib,saveJoblib
from fsio import setFile, isFile
from colInfo import getDim
from analyzeColumnData import writeDropList

def readCSV(filename):
    info("Reading data ["+filename+"]")
    pddata = read_csv(filename, low_memory=False)

    info("Read data with size "+getDim(pddata))
    return pddata

def readKeyValue(filename):
    info("Reading dict file ["+filename+"] into data frame", ind=6)
    pddata = DataFrame(filename)
    return pddata

def joinTrainTest(trainData, testData):
    info("Joining train and test data", ind=6)
    trainVal  = Series(repeat(1, trainData.shape[0]))
    trainData = trainData.assign(isTrain=trainVal.values)
    info("Train data has size "+getDim(trainData), ind=6)
    testVal   = Series(repeat(0, testData.shape[0]))
    testData  = testData.assign(isTrain=testVal.values)
    info("Test data has size "+getDim(testData), ind=6)
    pddf = trainData.append(testData)
    info("Combined data has size "+getDim(pddf), ind=6)
    return pddf

def joinTrainValid(trainData, validData):
    info("Joining train and validation data", ind=6)
    validVal  = Series(repeat(0, trainData.shape[0]))
    trainData = trainData.assign(isValid=validVal.values)
    info("Train data has size "+getDim(trainData), ind=6)
    validVal   = Series(repeat(1, validData.shape[0]))
    validData  = validData.assign(isValid=validVal.values)
    info("Validation data has size "+getDim(validData), ind=6)
    pddf = trainData.append(validData)
    info("Combined data has size "+getDim(pddf), ind=6)
    return pddf

def readDataset(config, name):
    info("Loading {0} dataset".format(name), ind=0)
    if name == "boston":
        ddata = datasets.load_boston()
    elif name == "diabetes":
        ddata = datasets.load_diabetes()
    elif name == "digits":
        ddata = datasets.load_diabetes()
    elif name == "cancer":
        ddata = datasets.load_breast_cancer()
    elif name == "wine":
        ddata = datasets.load_wine()
    else:
        raise ValueError("Name {0} is not recognized in readDatasets".format(name))

    X = ddata.data
    y = ddata.target
    y = y.reshape((y.shape[0],1))
    df = append(arr=X, values=y, axis=1)
    pddf = DataFrame(df)
    columns = list(ddata.feature_names)
    columns.append("TARGET")
    pddf.columns = columns
    return pddf

def makeDataset(config, name):
    info("Making {0} dataset".format(name))
    if name == "regression":
        X, y = datasets.make_regression(50000, 10, noise=10)
    elif name == "classification":
        X, y = datasets.make_classification(50000, 10)
    else:
        raise ValueError("Name {0} is not recognized in makeDataset".format(name))

    y = y.reshape((y.shape[0],1))
    df = append(arr=X, values=y, axis=1)
    pddf = DataFrame(df)
    columns = ["Var"+str(x) for x in range(X.shape[1])]
    columns.append("TARGET")
    pddf.columns = columns

    return pddf

def makeRegression(config):
    return makeDataset(config, "regression")

def makeClassification(config):
    return makeDataset(config, "classification")

def readKDD99(config):
    info("Getting KDD '99 data.")

    datadir      = getDataDir(config)
    outputConfig = config['output']
    compress     = outputConfig['compress']
    dataName     = setFile(datadir, outputConfig['name'])

    featureConfig = config['feature']
    dlFile        = setFile(datadir, featureConfig['dropList'])

    if isFile(dataName) and isFile(dlFile):
        info("Loading previously create data frames")
        pddf = getJoblib(dataName)
    else:
        info("Downloading KDD '99 data",ind=2)
        tmp = datasets.fetch_kddcup99()
        X = tmp['data']
        y = tmp['target']
        y = y.reshape((y.shape[0],1))
        pddf = DataFrame(append(arr=X, values=y, axis=1))

        tmp = pddf.head(n=1000)
        for column in tmp.columns:
            try:
                tmp[column].mean()
                pddf[column] = to_numeric(pddf[column], errors="coerce")
            except:
                continue

        colFile  = setFile(datadir, "names.dat")
        colnames = open(colFile).readlines()
        targets  = colnames[0].split(",")
        columns  = [x.split(":")[0] for x in colnames[1:]]
        columns.append("TARGET")
        pddf.columns = columns

        info("Saving data to {0}".format(dataName))
        saveJoblib(jlfile=dataName, jldata=pddf, compress=compress)

        info("Saving feature data to {0}".format(dlFile))
        writeDropList(dlFile, pddf, dlData = None)

    return pddf

def readUptake(config):
    info("Getting uptake data.")

    datadir      = getDataDir(config)
    outputConfig = config['output']
    compress     = outputConfig['compress']
    dataName     = setFile(datadir, outputConfig['name'])

    inputConfig  = config['input']
    trainName    = setFile(datadir, inputConfig['train'])
    validName    = setFile(datadir, inputConfig['valid'])

    featureConfig = config['feature']
    dlFile        = setFile(datadir, featureConfig['dropList'])

    if isFile(dataName) and isFile(dlFile):
        info("Loading previously create data frames")
        pddf = getJoblib(dataName)
    else:
        trainData = readCSV(trainName)
        validData = readCSV(validName)

        ## Remove 'market' from validation data
        validData.drop(labels='market', axis=1, inplace=True)

        pddf = joinTrainValid(trainData, validData)
        info("Saving training and validation data")
        saveJoblib(dataName, pddf, compress)
        info("Wrote training and validation data to "+dataName)

        info("Saving feature data")
        writeDropList(dlFile, pddf, dlData = None)

    return pddf

def readData(config):
    info("Getting data for analysis")

    ## Get name
    name     = config['name']

    ## Load the data we need
    if name == "uptake":
        pddf = readUptake(config)
    elif name == "kdd99":
        pddf = readKDD99(config)
    elif name in ["boston", "diabetes", "wine", "digits", "cancer"]:
        pddf = readDataset(config, name)
    elif name == "regression":
        pddf = makeRegression(config)
    elif name == "classification":
        pddf = makeClassification(config)
    else:
        raise ValueError("Name",name,"not recognized in readData()")

    info("Using data that is "+getDim(pddf), ind=0)
    return pddf


from django.contrib import messages
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import redirect, get_object_or_404
from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from django.views.generic import FormView, ListView,View,TemplateView
from django_datatables_view.base_datatable_view import BaseDatatableView
from django import forms
from django.forms import Form, CharField
from Ads_Project.functions import LoginRequiredMixin
from system.forms import IncreaseBalanceFrom
from system.models import Order, User, INCREASE_BALANCE_ORDER, History, Tabligh, COUNT_KHARI_HADAGHAL, TanzimatPaye ,PERFECT_USER_ID,PERFECT_TITLE,PERFECT_PASSPHRASE
from system.templatetags.app_filters import date_jalali
import hashlib
from datetime import datetime

def dargah_test_part_1(request):
    a = f"""
    next
    """
    return HttpResponse(a)

def dargah_test_part_2(request):
    pass

def dargah_test_part_2(request):
    pass

class IncreaseBalanceView(LoginRequiredMixin, FormView):
    template_name = 'system/Malli/Increase_Balance.html'
    form_class = IncreaseBalanceFrom
    success_url = reverse_lazy('ConfirmBalanceView')

    def get(self, request, *args, **kwargs):
        if request.GET.get('balance_increased'):
            messages.success(request, _("Your balance increased"))
        return super().get(request, *args, **kwargs)

    def form_valid(self, form):
        dargah_type = form.cleaned_data['dargah_type']
        how_much = form.cleaned_data['how_much']
        self.request.session['dargah_type'] = dargah_type
        self.request.session['how_much'] = how_much
        my_str=str(self.request.user.id)+' '+self.request.user.username+' '+ str(datetime.now())
        payment_id=hashlib.sha1(my_str.encode("UTF-8")).hexdigest()
        self.request.session['payment_id'] = payment_id
        Order.objects.create(type=INCREASE_BALANCE_ORDER,user=self.request.user,mablagh=float(how_much),payment_id=payment_id,status=0)
        '''user_id = self.request.POST.get('user', None)
        if user_id and (isinstance(user_id, int) or (isinstance(user_id, str) and user_id.isdigit())):
            user_id = int(user_id)
            if User.objects.filter(pk=user_id).exists():
                messages.error(self.request, _("User does not exist"))
                return super().form_invalid(form)

        else:
            user_id = self.request.user.id
        user = get_object_or_404(User, pk=int(user_id))
        user.add_to_kif_pool(form.cleaned_data['how_much'])
        History.objects.create(user=user, type='0', meghdar=int(form.cleaned_data['how_much']))'''

        return super(IncreaseBalanceView, self).form_valid(form)

    def form_invalid(self, form):
        return super().form_invalid(form)

class ConfirmBalanceView(LoginRequiredMixin, TemplateView):
    template_name = 'system/Malli/Confirmation_method.html'

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super().get_context_data(object_list=object_list, **kwargs)
        if self.request.session.get('dargah_type')=='1':
            form = Form()
            form.fields = {}
            action_url="https://perfectmoney.is/api/step1.asp"
            how_much=self.request.session.get("how_much")
            submit_name="PAYMENT_METHOD"
            dargah_type="Perfect Money"
            PERFECT_USER_ID_VALUE=TanzimatPaye.get_settings(PERFECT_USER_ID,0)
            PUI = forms.CharField(initial=PERFECT_USER_ID_VALUE, widget=forms.HiddenInput())
            form.fields["PAYEE_ACCOUNT"] = PUI
            PAYMENT_ID = forms.CharField(initial=self.request.session.get('payment_id'), widget=forms.HiddenInput())
            form.fields["PAYMENT_ID"] = PAYMENT_ID
            PERFECT_TITLE_VALUE=TanzimatPaye.get_settings(PERFECT_TITLE,0)
            PT = forms.CharField(initial=PERFECT_TITLE_VALUE, widget=forms.HiddenInput())
            form.fields["PAYEE_NAME"] = PT
            PAYMENT_AMOUNT = forms.CharField(initial=self.request.session.get("how_much"), widget=forms.HiddenInput())
            form.fields["PAYMENT_AMOUNT"] = PAYMENT_AMOUNT
            PAYMENT_UNITS = forms.CharField(initial="USD", widget=forms.HiddenInput())
            form.fields["PAYMENT_UNITS"] = PAYMENT_UNITS
            STATUS_URL = forms.CharField(initial="http://9ed79c3b.ngrok.io/system/perfectpaymentstatus", widget=forms.HiddenInput())
            form.fields["STATUS_URL"] = STATUS_URL
            PAYMENT_URL = forms.CharField(initial="http://9ed79c3b.ngrok.io/system/perfectpaymentsuccess", widget=forms.HiddenInput())
            form.fields["PAYMENT_URL"] = PAYMENT_URL
            PAYMENT_URL_METHOD = forms.CharField(initial="GET", widget=forms.HiddenInput())
            form.fields["PAYMENT_URL_METHOD"] = PAYMENT_URL_METHOD
            NOPAYMENT_URL = forms.CharField(initial="http://9ed79c3b.ngrok.io/system/perfect_money_F", widget=forms.HiddenInput())
            form.fields["NOPAYMENT_URL"] = NOPAYMENT_URL
            NOPAYMENT_URL_METHOD = forms.CharField(initial="GET", widget=forms.HiddenInput())
            form.fields["NOPAYMENT_URL_METHOD"] = NOPAYMENT_URL_METHOD
            context["form"]=form
            context["action_url"]=action_url
            context["how_much"]=how_much
            context["submit_name"]=submit_name
            context["dargah_type"]=dargah_type
        return context

    def get(self, request, *args, **kwargs):
        if "payment_id" in request.session:
            return super().get(request, *args, **kwargs)
        else:
            messages.error(request, "فاکتور دریافتی اشتباه است.")
            return redirect(reverse_lazy('increase_balance'))

class PerfectMoneyFailed(View):
    def get(self, request, *args, **kwargs):
        if "payment_id" in request.session:
            print(request.session.get('payment_id'))
            print(request.GET)
            del request.session['payment_id']
            messages.error(request, "پرداخت شما موفقیت آمیز نبود.")
        else:
            messages.error(request, "فاکتور دریافتی اشتباه است.")

        return redirect(reverse_lazy('increase_balance'))

class HistoryMaliListView(LoginRequiredMixin, ListView):
    model = History
    template_name = 'system/Malli/List_malihistory.html'

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super().get_context_data(object_list=object_list, **kwargs)
        return context

class HistoryMaliDatatableView(LoginRequiredMixin, BaseDatatableView):
    model = History
    columns = ['id', 'user', 'type', 'meghdar', 'created_at']

    def get_initial_queryset(self):
        user = self.request.user
        qs = super().get_initial_queryset()
        if user.is_superuser:
            return qs
        qs = qs.filter(user=user)
        return qs

    def render_column(self, row, column):
        if column == 'created_at':
            return date_jalali(row.created_at, 3)
        return super().render_column(row, column)

    def filter_queryset(self, qs):
        search = self.request.GET.get('search[value]', None)
        if self.request.user.is_superuser:
            if search:
                if search in _("deposit"):
                    qs = qs.filter(Q(type=0) | Q(meghdar__icontains=search) | Q(user__username__icontains=search))
                elif search in _("withdraw"):
                    qs = qs.filter(Q(type=1) | Q(meghdar__icontains=search | Q(user__username__icontains=search)))
                elif search in _("Transfer from income money to pocket money"):
                    qs = qs.filter(Q(type=2) | Q(meghdar__icontains=search) | Q(user__username__icontains=search))
                else:
                    qs = qs.filter(Q(meghdar__icontains=search) | Q(user__username__icontains=search))
        else:
            if search:
                if search in _("deposit"):
                    qs = qs.filter(Q(type=0) | Q(meghdar__icontains=search))
                elif search in _("withdraw"):
                    qs = qs.filter(Q(type=1) | Q(meghdar__icontains=search))
                elif search in _("Transfer from income money to pocket money"):
                    qs = qs.filter(Q(type=2) | Q(meghdar__icontains=search))
                else:
                    qs = qs.filter(Q(meghdar__icontains=search))
        return qs

class MoveDaramad2KifView(LoginRequiredMixin, FormView):
    template_name = 'system/Malli/move_daramad_kif.html'
    form_class = IncreaseBalanceFrom
    success_url = reverse_lazy('MoveDaramad2Kif')

    def get(self, request, *args, **kwargs):
        if request.GET.get('balance_increased'):
            messages.success(request, _("Your balance increased"))
        return super().get(request, *args, **kwargs)

    def form_valid(self, form):
        user = self.request.user
        get_value = int(form.cleaned_data['how_much'])

        indirect_allowed = user.allow_indirect()

        kif_daramad = user.get_kif_daramad()
        if (kif_daramad.current_recieved_direct + kif_daramad.current_recieved_indirect) >= get_value:
            if kif_daramad.current_recieved_indirect < kif_daramad.current_recieved_direct:
                if get_value >= kif_daramad.current_recieved_indirect:
                    get_value -= kif_daramad.current_recieved_indirect
                    kif_daramad.current_recieved_indirect = 0
                    if get_value > 0:
                        kif_daramad.current_recieved_direct -= get_value
                    kif_daramad.save()
                else:
                    kif_daramad.current_recieved_indirect -= get_value
                    kif_daramad.save()
            elif indirect_allowed:
                if get_value >= kif_daramad.current_recieved_direct:
                    get_value -= kif_daramad.current_recieved_direct
                    kif_daramad.current_recieved_direct = 0
                    if get_value > 0:
                        kif_daramad.current_recieved_indirect -= get_value
                    kif_daramad.save()
                else:
                    kif_daramad.current_recieved_direct -= get_value
                    kif_daramad.save()

            else:
                if get_value > kif_daramad.current_recieved_direct:
                    messages.error(self.request, _("Selected mount exceeds the withdrawable mount"))
                    return super(MoveDaramad2KifView, self).form_invalid(form)
                else:
                    kif_daramad.current_recieved_direct -= get_value
                    kif_daramad.save()
            get_value = int(form.cleaned_data['how_much'])
            kif_pol = user.get_kif_kif_pool()
            kif_pol.current_balance += int(get_value)
            kif_pol.save()
            History.objects.create(user=user, type='2', meghdar=int(form.cleaned_data['how_much']))
            messages.success(self.request, _("Selected mount is moved to your pocket money"))
            return super(MoveDaramad2KifView, self).form_valid(form)
        else:
            messages.error(self.request, _("Selected mount exceeds the withdrawable mount"))
            return super(MoveDaramad2KifView, self).form_invalid(form)

    def form_invalid(self, form):
        return super().form_invalid(form)


"""Gaussian descriptor class."""
import os

import ase
import ase.io
try:
    from lammps import lammps
    # For version compatibility; older lammps versions (the serial version
    # we still use on some machines) do not have these constants.
    try:
        from lammps import constants as lammps_constants
    except ImportError:
        pass
except ModuleNotFoundError:
    pass
import numpy as np

from mala.descriptors.lammps_utils import set_cmdlinevars, extract_compute_np
from mala.descriptors.descriptor import Descriptor
from mala.descriptors.atomic_density import AtomicDensity

class MinterpyDescriptors(Descriptor):
    """Class for calculation and parsing of Gaussian descriptors.

    Parameters
    ----------
    parameters : mala.common.parameters.Parameters
        Parameters object used to create this object.
    """

    def __init__(self, parameters):
        super(MinterpyDescriptors, self).__init__(parameters)
        self.verbosity = parameters.verbosity

    @property
    def data_name(self):
        """Get a string that describes the target (for e.g. metadata)."""
        return "Minterpy"

    @property
    def feature_size(self):
        """Get the feature dimension of this data."""
        return self.fingerprint_length

    @staticmethod
    def convert_units(array, in_units="None"):
        """
        Convert the units of a Gaussian descriptor.

        Since these do not really have units this function does nothing yet.

        Parameters
        ----------
        array : numpy.array
            Data for which the units should be converted.

        in_units : string
            Units of array.

        Returns
        -------
        converted_array : numpy.array
            Data in MALA units.
        """
        if in_units == "None" or in_units is None:
            return array
        else:
            raise Exception("Unsupported unit for Minterpy descriptors.")

    @staticmethod
    def backconvert_units(array, out_units):
        """
        Convert the units of a Gaussian descriptor.

        Since these do not really have units this function does nothing yet.

        Parameters
        ----------
        array : numpy.array
            Data in MALA units.

        out_units : string
            Desired units of output array.

        Returns
        -------
        converted_array : numpy.array
            Data in out_units.
        """
        if out_units == "None":
            return array
        else:
            raise Exception("Unsupported unit for Minterpy descriptors.")

    def _calculate(self, atoms, outdir, grid_dimensions, **kwargs):
        from lammps import lammps

        nx = grid_dimensions[0]
        ny = grid_dimensions[1]
        nz = grid_dimensions[2]

        # Check if we have to determine the optimal sigma value.
        if self.parameters.atomic_density_sigma is None:
            self.grid_dimensions = [nx, ny, nz]
            voxel = atoms.cell.copy()
            voxel[0] = voxel[0] / (self.grid_dimensions[0])
            voxel[1] = voxel[1] / (self.grid_dimensions[1])
            voxel[2] = voxel[2] / (self.grid_dimensions[2])
            self.parameters.atomic_density_sigma = AtomicDensity.\
                get_optimal_sigma(voxel)

        # Size of the local cube
        # self.parameters.minterpy_cutoff_cube_size

        # first grid point - for now just assume 0.0, 0.0, 0.0.
        # That is correct in 99% of the cases I am aware of, and once
        # we have a working implementation we can test and refine this.
        # first_grid_point = [0.0, 0.0, 0.0]

        # Get the unisolvent nodes.
        unisolvent_nodes = self._build_unisolvent_nodes()

        # Transform the unisolvent nodes into cartesian coordinates by assuming
        # small cubes around the grid points. Currently only works for cubic
        # cells.
        self.parameters.minterpy_point_list = []
        local_cube = atoms.cell.copy()
        local_cube[0] = local_cube[0] * (self.parameters.
                                         minterpy_cutoff_cube_size /
                                         local_cube[0][0])
        local_cube[1] = local_cube[1] * (self.parameters.
                                         minterpy_cutoff_cube_size /
                                         local_cube[0][0])
        local_cube[2] = local_cube[2] * (self.parameters.
                                         minterpy_cutoff_cube_size /
                                         local_cube[0][0])
        for i in range(np.shape(unisolvent_nodes)[0]):
            self.parameters.\
                minterpy_point_list.\
                append(np.matmul(local_cube, unisolvent_nodes[i]))

        # Array to hold descriptors.
        coord_length = 3 if self.parameters.descriptors_contain_xyz else 0
        minterpy_descriptors_np = \
            np.zeros([nx, ny, nz,
                      len(self.parameters.minterpy_point_list)+coord_length],
                     dtype=np.float64)
        self.fingerprint_length = \
            len(self.parameters.minterpy_point_list)+coord_length

        self.fingerprint_length = len(self.parameters.minterpy_point_list)
        # Perform one LAMMPS call for each point in the Minterpy point list.
        for idx, point in enumerate(self.parameters.minterpy_point_list):
            # Shift the atoms in negative direction of the point(s) we actually
            # want.
            atoms_copied = atoms.copy()
            atoms_copied.set_positions(atoms.get_positions()-np.array(point))

            # The rest is the stanfard LAMMPS atomic density stuff.
            lammps_format = "lammps-data"
            ase_out_path = os.path.join(outdir, "lammps_input.tmp")
            ase.io.write(ase_out_path, atoms_copied, format=lammps_format)

            # Create LAMMPS instance.
            lammps_dict = {}
            lammps_dict["sigma"] = self.parameters.atomic_density_sigma
            lammps_dict["rcutfac"] = self.parameters.atomic_density_cutoff
            lammps_dict["atom_config_fname"] = ase_out_path
            lmp = self._setup_lammps(nx, ny, nz, outdir, lammps_dict,
                                     log_file_name="lammps_mgrid_log.tmp")

            # For now the file is chosen automatically, because this is used
            # mostly under the hood anyway.
            filepath = __file__.split("minterpy")[0]
            if self.parameters._configuration["mpi"]:
                raise Exception("Minterpy descriptors cannot be calculated "
                                "in parallel yet.")
                # if self.parameters.use_z_splitting:
                #     runfile = os.path.join(filepath, "in.ggrid.python")
                # else:
                #     runfile = os.path.join(filepath, "in.ggrid_defaultproc.python")
            else:
                runfile = os.path.join(filepath, "in.ggrid_defaultproc.python")
            lmp.file(runfile)

            # Extract the data.
            nrows_ggrid = extract_compute_np(lmp, "ggrid",
                                             lammps_constants.LMP_STYLE_LOCAL,
                                             lammps_constants.LMP_SIZE_ROWS)
            ncols_ggrid = extract_compute_np(lmp, "ggrid",
                                             lammps_constants.LMP_STYLE_LOCAL,
                                             lammps_constants.LMP_SIZE_COLS)

            gaussian_descriptors_np = \
                extract_compute_np(lmp, "ggrid",
                                   lammps_constants.LMP_STYLE_LOCAL, 2,
                                   array_shape=(nrows_ggrid, ncols_ggrid))

            lmp.close()

            gaussian_descriptors_np = \
                gaussian_descriptors_np.reshape((grid_dimensions[2],
                                                 grid_dimensions[1],
                                                 grid_dimensions[0],
                                                 7))
            gaussian_descriptors_np = \
                gaussian_descriptors_np.transpose([2, 1, 0, 3])
            if self.parameters.descriptors_contain_xyz and idx == 0:
                minterpy_descriptors_np[:, :, :, 0:3] = \
                    gaussian_descriptors_np[:, :, :, 3:6].copy()

            minterpy_descriptors_np[:, :, :, coord_length+idx:coord_length+idx+1] = \
                gaussian_descriptors_np[:, :, :, 6:]

        return minterpy_descriptors_np, nx * ny * nz

    def _build_unisolvent_nodes(self, dimension=3):
        """
        Build the unisolvent nodes.

        Parameters
        ----------
        dimension : int
            Dimension of data (should always be 3 for 3D in our case).

        Returns
        -------
        nodes : numpy.array
            Two-dimensional array containing the nodes.
        """
        import minterpy as mp

        # Calculate the unisolvent nodes.
        mi = mp.MultiIndexSet.from_degree(spatial_dimension=dimension,
                                          poly_degree=self.parameters.minterpy_polynomial_degree,
                                          lp_degree=self.parameters.minterpy_lp_norm)
        unisolvent_nodes = mp.Grid(mi).unisolvent_nodes
        return unisolvent_nodes