# -*- coding: utf-8 -*-
"""
Created on Wed Nov 14 23:55:26 2018

@author: chenjing34
"""

import numpy as np  # linear algebra
import pandas as pd  # data processing, CSV file I/O (e.g. pd.read_csv)
import mlstudiosdk.modules
import mlstudiosdk.solution_gallery
from mlstudiosdk.modules.components.component import LComponent
from mlstudiosdk.modules.components.utils.orange_table_2_data_frame import table2df
from mlstudiosdk.modules.components.utils.orange_table_2_data_frame import df2table
from mlstudiosdk.modules.algo.data import Domain, Table
from mlstudiosdk.modules.algo.evaluation import Results
from mlstudiosdk.modules.algo.data.variable import DiscreteVariable, ContinuousVariable
from mlstudiosdk.modules.utils.itemlist import MetricFrame
from mlstudiosdk.modules.utils.metricType import MetricType
from sklearn.model_selection import train_test_split
from mlstudiosdk.exceptions.exception_base import Error
import itertools
import random
import string
import shutil
import jieba
import os
import glob  # find file directories and files
import fasttext  # model
import codecs
import re
import warnings
from tempfile import NamedTemporaryFile, TemporaryDirectory

warnings.filterwarnings('ignore')

class Multiple_text_Classifier(LComponent):
    category = 'Nature Language Processing'
    name = "Multiple Text Classifier"
    title = "Multiple Text Classifier"
    # create the current file path

    inputs = [("Train Data", mlstudiosdk.modules.algo.data.Table, "set_traindata"),
              ("Test Data", mlstudiosdk.modules.algo.data.Table, "set_testdata")
              ]
    outputs = [
        ("News", mlstudiosdk.modules.algo.data.Table),
        ("Predictions", Table),
        ("Evaluation Results", mlstudiosdk.modules.algo.evaluation.Results),
        ("Columns", list),
        ("Metas", list),
        ("Metric Score", MetricFrame),
        ("Metric", MetricType)
    ]

    def __init__(self):
        super().__init__()
        self.train_data = None
        self.test_data = None
        self.file_path = None
        self.classifier = None
        self.root_path = self.get_dataset_path()  # data set path, like stopwords.txt
        self.model_path = None  # temporary file/dir path
        self.classifier_code = None
        self.temporary_dir = None

    def get_mlstudiosdk_path(self):
        return os.path.dirname(mlstudiosdk.__file__)

    def get_dataset_path(self):
        dataset_path = os.path.join(self.get_mlstudiosdk_path(), 'dataset', 'dataset_for_nlp',
                                    "Multiple_text_Classifier")
        return dataset_path

    def set_traindata(self, data):
        self.train_data = data

    def set_testdata(self, data):
        self.test_data = data

    def set_file_path(self):
        # ran_str = ''.join(random.sample(string.ascii_letters + string.digits, random.randint(5, 12)))
        #
        # # self.file_path = os.path.join(os.getcwd(), ran_str)
        # self.file_path = os.path.join(self.model_path, ran_str)
        #
        # while os.path.exists(self.file_path):
        #     ran_str = ''.join(random.sample(string.ascii_letters + string.digits, random.randint(5, 12)))
        #     self.file_path = os.path.join(self.model_path, ran_str)
        #     # self.file_path = os.path.join(os.getcwd(), ran_str)
        # if not os.path.exists(self.file_path):
        #     os.makedirs(self.file_path)
        if self.temporary_dir is not None:
            self.temporary_dir.cleanup()
            # in case the last time run model, stop by accident, and did not run cleanup()
        self.temporary_dir = TemporaryDirectory(prefix=None, dir=self.model_path)
        self.file_path = self.temporary_dir.name

    def label_str2number(self, data):
        label_str_raw = list(set(data[self.label_name]))
        format = lambda x: int(label_str_raw.index(x))
        data[self.label_name] = data[self.label_name].map(format)
        return data, label_str_raw

    def label_number2str(self, data, label_str_raw):
        format = lambda x: label_str_raw[x]
        data = data.astype({self.label_name: 'int'})
        data[self.label_name] = data[self.label_name].map(format)
        return data

    def merge_result(self, data_len, legal_pre, legal_pre_pro, legal_test_data_id):
        # combine pre and predict possibility that can be predicted and data can not(illegal data)
        pre = [len(self.label_domain) - 1] * data_len
        pre_prob = [[None] * (len(self.label_domain) - 1)] * data_len
        for id_index in range(len(legal_pre)):
            id = legal_test_data_id[id_index]
            pre[id] = legal_pre[id_index]
            pre_prob[id] = legal_pre_pro[id_index]
        return np.array(pre), np.array(pre_prob)

    def files(self, curr_dir='.', ext='fasttext_*.txt'):
        """Files in the current directory"""
        for i in glob.glob(os.path.join(curr_dir, ext)):
            yield (i)

    def remove_files(self, rootdir, ext, show=False):
        """Delete the matching files in the rootdir directory"""
        for i in self.files(rootdir, ext):
            # if show:
            # print('如下文件已被删除:',i)
            os.remove(i)

    def get_name(self):
        # get label & sentence columns name
        self.label_name = self.train_data.domain.class_var.name
        # self.label_name = 'label'
        #         if len(self.train_data.domain.variables)-len(self.train_data.domain.class_vars) > 1 \
        #                 or len(self.train_data.domain.attributes) > 1:
        #             from mlstudiosdk.exceptions.ExceptionBase import Error
        #             raise Error("too many features")
        self.sentence_name = self.train_data.domain.attributes[0].name

    def add_commentid(self, df_input):

        df_input = df_input.reset_index(drop=True)
        return df_input

    def merge_possibility(self, data_len, possibility, legal_test_data_id):
        # combine neg/posi possibilty with illegal
        pos_new = [[None] * 2] * data_len
        for id_index in range(len(possibility)):
            id = legal_test_data_id[id_index]
            pos_new[id] = possibility[id_index]
        return np.array(pos_new)

    def merge_data(self, origin, result):
        # result table to origin table's meta
        domain = origin.domain
        attributes, classes = domain.attributes, domain.class_vars
        meta_attrs = domain.metas
        new_domain = Domain(attributes, classes, meta_attrs + result.domain.variables)
        new_table = Table.from_table(new_domain, origin)
        for attr in result.domain:
            new_table.get_column_view(attr)[0][:] = result.get_column_view(attr)[0][:]
        return new_table

    # define a program for text reprocessing
    def text_split(self, data, data_type):
        # get the columns list
        colums_names = data.columns.values.tolist()
        # filter'id','content' columns to get the column names of multiple tags
        colums_names_list = colums_names[2:]
        # get the 'content' columns
        text_name = self.text_clomn_name
        # in case self.train_data do not have ID
        # get 'content' column text,convert to list
        text_set = data[[text_name]].values.tolist()
        # get the stopwords list
        stopwords = {}.fromkeys([line.rstrip() for line in codecs.open(os.path.join(self.root_path, "stopwords.txt"),
                                                                       'r', 'utf-8-sig')])
        # split data by data_type
        if data_type == 'trainingset' or data_type == 'validationset':
            # loop through the operation

            with open(os.path.join(self.file_path, 'fasttext_' + data_type + '.txt'), 'w', encoding='utf-8')as f:

                for i in range(len(text_set)):
                    temp1 = ' '.join(jieba.cut(str(text_set[i])))
                    texts1 = [word for word in temp1.split() if word not in stopwords]
                    texts1 = " ".join(texts1)

                    # Add the prefix '__label__' to the label column
                    temp2 = '__label__' + str(list(data[self.label_name])[i]) + ' ,'
                    temp3 = texts1 + ' ' + temp2
                    f.write(temp3 + '\n')
            f.close()
        else:
            # deal with the data_type'testset'
            with open(os.path.join(self.file_path, 'fasttext_' + data_type + '.txt'), 'w', encoding='utf-8')as f:
                for i in range(len(text_set)):
                    # Note: the testset dataset has only a context column and no prefix '__label__'
                    temp1 = ' '.join(jieba.cut(str(text_set[i])))
                    texts1 = [word for word in temp1.split() if word not in stopwords]
                    texts1 = " ".join(texts1)
                    # texts1 = str(re.findall(u'[\u4e00-\u9fa5-\d+\.\d]+'," ".join(texts1)))
                    temp3 = texts1
                    f.write(temp3 + '\n')
            f.close()
        return colums_names_list

    def run(self):
        try:
            self.root_path = self.get_dataset_path()
            self.text_clomn_name = self.train_data.domain.attributes[0].name
            # os.chdir(self.root_path)
            self.get_name()

            self.set_file_path()
            test_data = table2df(self.test_data)

            #         try:
            #             test_data.iloc[:, :-len(self.test_data.domain.class_vars)] = \
            #                 test_data.iloc[:, :-len(self.test_data.domain.class_vars)].astype('float')
            #         except Exception as e:
            #             print(e)
            #             raise Error('data must be numeric')
            test_data = test_data.dropna(subset=[self.label_name])
            test_data, test_label_domain = self.label_str2number(test_data)
            test_data = self.add_commentid(test_data)

            if len(test_data) != len(self.test_data):
                raise Error("test data missing label")

            test_data_raw = test_data  # test data may delete some records
            y_test_visual = test_data_raw[self.label_name]
            train_data = table2df(self.train_data)
            train_data = self.add_commentid(train_data)
            #         try:
            #             train_data.iloc[:, :-len(self.train_data.domain.class_vars)] = \
            #                 train_data.iloc[:, :-len(self.train_data.domain.class_vars)].astype('float')
            #         except Exception as e:
            #             print(e)
            #             raise Error('data must be numeric')
            if len(test_data.columns) != len(train_data.columns):
                raise Error('train data and test data must match')
            train_data = train_data.dropna(subset=[self.label_name])
            train_data, self.label_domain = self.label_str2number(train_data)
            #        print("self.label_domain",self.label_domain)
            Traina, validationa = train_test_split(train_data, train_size=0.8, random_state=1234)
            Traina = self.add_commentid(Traina)
            validationa = self.add_commentid(validationa)
            self.text_split(Traina, 'trainingset')
            legal_test_data_id = list(test_data.index)
            test_split = test_data.drop([self.label_name], axis=1)
            self.text_split(test_data, 'testset')
            self.text_split(test_split, 'test_split')
            self.text_split(validationa, 'validationset')
            # training the model

            """---------add by wwang29----"""
            try:
                classifier_model = NamedTemporaryFile(suffix=".model.bin", dir=self.file_path)
                self.classifier = fasttext.supervised(os.path.join(self.file_path, 'fasttext_trainingset.txt'),
                                                      os.path.splitext(classifier_model.name)[0], label_prefix='__label__',
                                                      epoch=200, min_count=3, word_ngrams=3, ws=10, thread=32, lr=0.1,
                                                      dim=200, bucket=5000000)
                self.classifier_code = classifier_model.read()
            finally:
                classifier_model.close()

            # self.classifier = fasttext.supervised(os.path.join(self.file_path, 'fasttext_trainingset.txt'),
            #                                       os.path.join(self.model_path, 'fasttext_test.model'), label_prefix='__label__',
            #                                       epoch=200, min_count=3, word_ngrams=3, ws=10, thread=32, lr=0.1, dim=200,
            #                                       bucket=5000000)

            """--------end wwang29---------"""

            train_result = self.classifier.test(os.path.join(self.file_path, 'fasttext_trainingset.txt'))
            train_score = train_result.precision
            validation_result = self.classifier.test(os.path.join(self.file_path, 'fasttext_validationset.txt'))
            val_score = validation_result.precision
            test_set = open(os.path.join(self.file_path, 'fasttext_test_split.txt'), 'r', encoding='utf-8-sig')
            predict_label = self.classifier.predict(test_set)
            int_index = []
            for index in predict_label:
                int_index.append(int(index[0]))

            test_set1 = open(os.path.join(self.file_path, 'fasttext_test_split.txt'), 'r', encoding='utf-8-sig')
            wind_pre_prob = self.classifier.predict_proba(test_set1)
            wind_pre_prob_two_c = wind_pre_prob
            wind_pre_prob_index = []
            for index in wind_pre_prob:
                wind_pre_prob_index.append(index[0][1])

            """-----------calculate probility-------------------------------"""
            if len(self.label_domain) == 2:
                metas = [DiscreteVariable('predict', self.label_domain),
                         ContinuousVariable('negative probability'),
                         ContinuousVariable('positive probability')]
            else:
                metas = [DiscreteVariable('predict', self.label_domain),
                         ContinuousVariable('others'),
                         ContinuousVariable('selected class prob')]

            new_two_prob_positive = []
            new_two_prob_negative = []

            for index, item in enumerate(wind_pre_prob_index):
                new_two_prob_negative.append(1 - item)
                new_two_prob_positive.append(item)

            wind_pre_prob = np.array([np.array(new_two_prob_negative), np.array(new_two_prob_positive)])
            wind_pre_prob = wind_pre_prob.T
            total_pre_prob = self.merge_possibility(len(test_data_raw), wind_pre_prob, legal_test_data_id)
            cols = [np.array(int_index).reshape(-1, 1), wind_pre_prob]
            aa = np.array(int_index).reshape(-1, 1)

            tbl = np.column_stack((np.array(int_index).reshape(-1, 1), wind_pre_prob))

            res = Table.from_numpy(Domain(metas), tbl)
            final_result = self.merge_data(self.test_data, res)

            results = None
            N = len(test_data)  # note that self.test_data is orange Table
            results = Results(self.test_data[legal_test_data_id], store_data=True)
            results.folds = None
            results.row_indices = np.arange(N)
            results.actual = np.array(y_test_visual[legal_test_data_id])
            results.predicted = np.array([int_index])

            results.probabilities = np.array([wind_pre_prob])
            # results.probabilities = wind_pre_prob

            """-----changed by wwang29-------"""
            # in sentiment classifier we add "illegal data" in domain, so -1, here, we do not use that
            if len(self.label_domain) > 2:
                results.probabilities = None
            elif len(self.label_domain) == 2:
                # test_set2 = open(os.path.join(self.file_path, 'fasttext_test_split.txt'), 'r', encoding='utf-8-sig')
                # wind_pre_prob = self.classifier.predict_proba(test_set2)
                pro_two_class = []
                for p_index in range(len(wind_pre_prob_two_c)):
                    local_ = [0, 1]
                    local_[results.predicted[0][p_index]] = wind_pre_prob_two_c[p_index][0][1]
                    local_[results.predicted[0][p_index]-1] = 1 - wind_pre_prob_two_c[p_index][0][1]
                    pro_two_class.append(local_)
                pro_two_class = np.array(pro_two_class)

                results.probabilities[0] = pro_two_class
            """-----------change end by wwang29-----------------"""
            print("predicted", results.predicted[0])
            print("actual", results.actual)

            results.learner_names = ['Multiple_text_Classifier']
            # self.send("Predictions", predictions)
            self.send("Evaluation Results", results)

            metric_frame = MetricFrame([[val_score], [train_score]], index=["hyperparam_searcher", "modeler"],
                                       columns=[MetricType.ACCURACY.name])
            self.send("Metric Score", metric_frame)
            self.send("Columns", cols)
            self.send("Metas", metas)
            self.send("Metric", MetricType.ACCURACY)

            # print(MetricType.ACCURACY)
            print("metric_frame", metric_frame)
            print("result:", results.predicted, results.predicted.shape)

            self.send('News', final_result)
            self.remove_files(self.file_path, 'fasttext_*.txt', show=True)
            test_set.close()
            test_set1.close()
            # self.classifier = None  # in order to pickle the model model
            self.train_data = None
            self.test_data = None
        finally:
            self.temporary_dir.cleanup()
            self.temporary_dir = None

    def rerun(self):
        try:
            self.root_path = self.get_dataset_path()
            """--------add by wwang29---------"""
            if self.temporary_dir is not None:
                self.temporary_dir.cleanup()
            self.set_file_path()

            # os.chdir(self.root_path)
            self.remove_files(self.file_path, 'fasttext_*.txt', show=True)  # in case did not removed
            test_data = table2df(self.test_data)
            test_data = self.add_commentid(test_data)
            #         test_data = test_data.dropna(subset=[self.label_name])
            text_split = test_data
            test_data_raw = test_data  # test data may delete some records
            #         text_split= test_data.drop([self.label_name], axis=1)
            self.text_split(text_split, 'test_split')
            legal_test_data_id = list(test_data.index)

            test_set = open(os.path.join(self.file_path, 'fasttext_test_split.txt'), 'r', encoding='utf-8-sig')
            predict_label = self.classifier.predict(test_set)
            predict_label_df = pd.DataFrame(predict_label)
            int_index = []
            for index in predict_label:
                int_index.append(int(index[0]))

            test_set1 = open(os.path.join(self.file_path, 'fasttext_test_split.txt'), 'r', encoding='utf-8-sig')
            wind_pre_prob = self.classifier.predict_proba(test_set1)
            wind_pre_prob_index = []
            for index in wind_pre_prob:
                wind_pre_prob_index.append(index[0][1])

            """-----------calculate probility-------------------------------"""

            if len(self.label_domain) == 2:
                metas = [DiscreteVariable('predict', self.label_domain),
                         ContinuousVariable('negative probability'),
                         ContinuousVariable('positive probability')]
            else:
                metas = [DiscreteVariable('predict', self.label_domain),
                         ContinuousVariable('others'),
                         ContinuousVariable('selected class prob')]

            new_two_prob_positive = []
            new_two_prob_negative = []

            for index, item in enumerate(wind_pre_prob_index):
                new_two_prob_negative.append(1 - item)
                new_two_prob_positive.append(item)

            wind_pre_prob = np.array([np.array(new_two_prob_negative), np.array(new_two_prob_positive)])
            wind_pre_prob = wind_pre_prob.T
            total_pre_prob = self.merge_possibility(len(test_data_raw), wind_pre_prob, legal_test_data_id)
            cols = [np.array(int_index).reshape(-1, 1), wind_pre_prob]
            aa = np.array(int_index).reshape(-1, 1)

            tbl = np.column_stack((np.array(int_index).reshape(-1, 1), wind_pre_prob))

            res = Table.from_numpy(Domain(metas), tbl)
            final_result = self.merge_data(self.test_data, res)

            self.send("News", final_result)
            self.send("Metric Score", None)
            self.send("Metas", metas)
            self.send("Columns", cols)
            # self.remove_files(self.file_path, '*', show=True)
            self.remove_files(self.file_path, 'fasttext_*.txt', show=True)
            print('rerun')
            test_set.close()
            test_set1.close()
            # shutil.rmtree(self.file_path)
            # self.classifier = None  # in order to pickle the model model
            self.train_data = None
            self.test_data = None
        finally:
            self.temporary_dir.cleanup()
            self.temporary_dir = None

    def __getstate__(self):
        odict = super(Multiple_text_Classifier, self).__getstate__()
        odict["train_data"] = None
        odict["test_data"] = None
        odict["temporary_dir"] = None
        odict["file_path"] = None
        odict["root_path"] = None
        odict["classifier"] = None
        return odict

    def __setstate__(self, state):
        self.__dict__.update(state)
        try:
            classifier_model = NamedTemporaryFile(suffix=".model.bin")
            classifier_model.write(self.classifier_code)

            self.classifier = fasttext.load_model(classifier_model.name
                                                  , label_prefix="__label__")
        finally:
            classifier_model.close()


# Filename: q3_miles_to_kilometre.py
# Name: Ambrose Tan
# Date created: 20130121
# Date modified: 20130121
# Description: Converting miles into kilometers

miles = 0
miles = float(input("Enter number of miles: \n"))
miles *= 1.60934
print("Number of miles =", "{:.3f}".format(miles))


from random import randint
import threading
import time

class Probability:

    def __init__(self, d, i, t):
        self.d = d
        self.i = i
        self.t = t
        self.a = []
        self.p = [[], []]

    def calcTries(self):
        for x in range(1, self.i + 1):
            while True:
                if randint(1, self.d) == self.d:
                    self.t += 1
                    print("iteration: {}, tries: {}".format(x, self.t))
                    self.a.append(self.t)
                    self.t = 0
                    break
                else:
                    self.t += 1
            global counter
            counter += 1
            # time.sleep(0.001)
            print(counter)

    def calcPercentages(self):
        for i in range(len(self.a)):
            if self.a[i] < self.d:
                self.p[0].append(self.a[i])
            elif self.a[i] > self.d:
                self.p[1].append(self.a[i])
        for j in range(len(self.p)):
            print("{} {}: {}%".format("<" if j == 0 else ">", self.d, round(float(len(self.p[j])) / len(self.a) * 100, 2)))

if __name__ == "__main__":
    droprate = 500
    iterations = 100000
    counter = 0
    t = time.time()
    threads = 2
    threadList = []

    init = Probability(droprate, iterations / 2, 0)

    # init.calcTries()
    # init.calcTries()

    for i in range(threads):
        t = threading.Thread(target=init.calcTries())
        t.start()
        threadList.append(t)

    print("done in: ", time.time() - t)
    print("total iterations: ", counter)


class BdioProject(object):

    id = None
    type = "Project"
    name = None
    external_id = None
    relationships = None
    version = None

    attribute_map = {
        "id": "@id",
        "type": "@type",
        "name": "name",
        "external_id": "externalIdentifier",
        "relationships": "relationship",
        "version": "revision"
    }

    def __init__(self):
        pass

    def __eq__(self, other):
        if isinstance(other, BdioProject):
            id = self.id == other.id
            type = self.type == other.type
            name = self.name == other.name
            external_id = self.external_id == other.external_id
            version = self.version == other.version
            relationships = True
            if self.relationships is not None and other.relationships is not None:
                relationships = len(self.relationships) == len(
                    other.relationships)
                if relationships:
                    for relationship in self.relationships:
                        if not relationship in other.relationships:
                            relationships = False
                            break
            elif self.relationships != other.relationships:
                # One is set to None
                relationships = False
            return (id and type and name and external_id and version and relationships)
        else:
            return False

    def __ne__(self, other):
        return not self.__eq__(other)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Slackbot module for ImitateBot."""

from time import sleep
import signal
import sys
import re
try:
  import ConfigParser
except ImportError:
  import configparser as ConfigParser

import markovify
from slacksocket import SlackSocket
from imitate_db import ImitateDB

COMMAND_REGEX = re.compile(r"^!imitate <@(?P<user>U[A-Z0-9]+)>[ ]*$", flags=re.IGNORECASE)

class ImitateBot(object):
  """The bot that handles everything Slack related."""

  def __exit__(self, exc_type, exc_value, exc_traceback):
    """Ensure SlackSocket thread is closed before quitting."""
    self.close()

  def close(self):
    """Prevent quit until SlackSocket thread is closed."""
    if self._initialised and self._started and not self._closing:
      self._closing = True
      self.slack.close()
      while self.slack._thread.isAlive():
        sleep(0.01)

  def __init__(self, bot_key, db_in, bot_id=None, debug_mode=False, imitate_attempts=100):
    """Setup variables for bot."""
    if bot_key is None:
      raise Exception("Slack Bot Key Required")
    else:
      self.bot_key = bot_key
    self._initialised = True
    self._started = False
    self._closing = False
    self.slack = None
    self.db = db_in
    self.bot_id = bot_id
    self.debug_mode = debug_mode
    self.imitate_attempts = imitate_attempts

  def start(self):
    """Start SlackSocket thread and enter main loop."""
    self.slack = SlackSocket(
      self.bot_key,
      translate=False,
      event_filters=["message"]
    )
    self._started = True
    for event in self.slack.events():
      self.handle_message(event)

  def imitate(self, name):
    """Generate an imitate string for a user."""
    if self.slack._find_user_name(name):
      if self.debug_mode:
        print("[debug] Generating chain for:", name if name else None)
      mk_text = self.db.get_name_messages_string(name)
      if self.debug_mode:
        print("[debug] Got", len(mk_text if mk_text else ""), "characters of data")
      if mk_text is None:
        return None
      mk = markovify.NewlineText(mk_text.decode('utf8'))
      result = None
      for _ in range(self.imitate_attempts):
        result = mk.make_sentence(tires=100, max_words=2500)
        if result:
          break
      return result
    if self.debug_mode:
      print("[debug] Could not find user:", name if name else None)
    return False

  def handle_message(self, event):
    """Parse messages and react in the necessary way."""
    if "user" not in event.event:
      return
    if event.event.get("subtype") == "bot_message":
      return
    if self.bot_id is not None and event.event["user"] == self.bot_id:
      return
    if event.event["text"].startswith("!imitate"):
      if event.event["text"] == "!imitate":
        self.slack.send_msg("Hi! I'm an experimental imitate bot running via the ReggieBot user.", channel_id=event.event["channel"], confirm=False)
      else:
        command = COMMAND_REGEX.match(event.event["text"])
        if command:
          msg = self.imitate(command.group("user"))
          if msg:
            self.slack.send_msg("I think <@" + command.group("user") + "> might say:\n" + ">>> " + msg, channel_id=event.event["channel"], confirm=False)
          else:
            if msg is None:
              self.slack.send_msg("Not enough data on user...", channel_id=event.event["channel"], confirm=False)
            else:
              self.slack.send_msg("User not found!", channel_id=event.event["channel"], confirm=False)
        else:
          self.slack.send_msg("Usage: !imitate @USERNAME", channel_id=event.event["channel"], confirm=False)
          print("[debug] Weird stuff:", event.event)
    else:
      self.db.add_message(event.event["user"], event.event["text"])

if __name__ == "__main__":
  config = ConfigParser.ConfigParser()
  config.read("imitate.cfg")

  print("Imitate Bot Initialising...")

  debug = config.get("imitate_bot", "debug").lower() == "true" or config.get("imitate_bot", "debug") == "1"

  db = ImitateDB(debug_mode=debug)
  bot = ImitateBot(config.get("imitate_bot", "bot_auth_token"), db, config.get("imitate_bot", "bot_id"), debug_mode=debug)

  def _exit_signal_handler(sig, frame):
    print('Exiting...')
    bot.close()
    db.close()
    sys.exit(0)

  signal.signal(signal.SIGINT, _exit_signal_handler)
  signal.signal(signal.SIGTERM, _exit_signal_handler)

  print("Starting Bot...")
  bot.start()


import os
from jinja2 import Template
from pathlib import Path

# Assuming all variables to capture starts with this prefix.
# These variables will be available in the template with- and without the prefix.
VARIABLE_PREFIX = 'T_'

def main():
    template_file = Path(os.environ.get('TEMPLATE_FILE'))
    if not template_file.exists():
        raise Exception(f'{template_file} does not exist!')

    template = Template(template_file.read_text())
    variables = {}
    for env_key in os.environ:
        if env_key.startswith(VARIABLE_PREFIX):
            env_value = os.environ.get(env_key)
            # Add both variants - the user should decide which one to use
            variables[env_key.removeprefix(VARIABLE_PREFIX)] = env_value
            variables[env_key] = env_value
    print(template.render(variables))

if __name__ == "__main__":
    main()


import tensorflow as tf
from NTlib.train.CenterFbUpTrainBN2D import CenterFbUpTrainBN2D
import numpy as np
from scipy import misc
from sys import argv

input_placer = tf.placeholder(tf.float32,(None,None,None,None))
gold_placer = tf.placeholder(tf.float32,(None,2))
learn_rate_placer = tf.placeholder(tf.float32)
keep_prob = tf.placeholder(tf.float32)

with tf.Session() as sess:
	wd = float(argv[1])
	wdo = float(argv[2])
	lr = float(argv[3])
	print('Init Train')
	fu = CenterFbUpTrainBN2D(sess, input_placer, gold_placer, keep_prob,
					learn_rate_placer, wd = wd, wdo = wdo, angle_xy = 60)
	#variables = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,scope = "fg_"+str(30)+'_'+str(30))
	fu.saver = tf.train.Saver()

	print('Train')
	fu.train(epic_num = 3,keep_prob = 1.0, batch_size = 128,
		learning_rate = lr)
	fu.saver.save(fu.sess,'./model/2d/version_'+'0'+'/model_center_'+str(60)+'.ckpt')
	#line_indexes_1 = [[x - (41 - 1)//2,0,0] for x in range(41)]
	"""
	line_indexes_1 = [[x - (41-1)//2,0,0] for x in range(41)] + \
					 [[x - (41-1)//2,-1,0] for x in range(41)] + \
					 [[x - (41-1)//2,1,0] for x in range(41)] + \
					 [[x - (41-1)//2,0,1] for x in range(41)] + \
					 [[x - (41-1)//2,0,-1] for x in range(41)]
	angles_xy = np.pi / 6
	angles_xz = np.pi / 6
	tmp_rot = np.array(
			   [[np.cos(angles_xy) * np.cos(angles_xz),
				 -np.sin(angles_xy),
				 np.cos(angles_xy) * np.sin(angles_xz)
				],
				[np.sin(angles_xy) * np.cos(angles_xz),
				 np.cos(angles_xy),
				 np.sin(angles_xy) * np.sin(angles_xz)
				],
				[-np.sin(angles_xz),
				 0,
				 np.cos(angles_xz)
				]
			   ])
	result_1 = np.int_(np.dot(line_indexes_1,tmp_rot))
	image3D = np.zeros((64,64,64))
	noise = np.random.normal(0,0.1,(64,64,64))
	brightness = np.random.random() * (0.8 - 0.2) + 0.2
	image3D[result_1[:,0] + 32, result_1[:,1] + 32, result_1[:,2] + 32] = 255
	image3D = (image3D + noise * 255)*brightness
	misc.imsave('testi0.png',np.max(image3D,axis = 0))
	misc.imsave('testi1.png',np.max(image3D,axis = 1))
	misc.imsave('testi2.png',np.max(image3D,axis = 2))

	#img3D_mat = sio.loadmat('./data/neuron/test.mat')
	#image3D = img3D_mat['img']
	#image3D = image3D[200:300,50:200,325:455] * 255
	#print(np.max(image3D))
	fu.test(image3D)
	"""


from django.urls import path
from . import views

app_name = 'events'

urlpatterns = [
    path('schoolassembly/' , views.schoolassembly , name='schoolassembly'),
    path('trips/' , views.trips , name='trips'),
    path('upcomingevents/' , views.upcomingevents , name='upcomingevents'),
    # path('message/' , views.message , name='message'),
    # path('principal/' , views.principal , name='principal'),
    # path('vice_principal/' , views.vice_principal , name='vice_principal'),
    # path('headmistress/' , views.headmistress , name='headmistress'),
]


#!/usr/bin/python

import spidev, time, struct
import numpy
import matplotlib.pyplot as plt
from collections import deque
from drawnow import *

# Initialize SPI bus
spi = spidev.SpiDev()
spi.open(0, 0)

plt.ion()

resist = deque([], maxlen=10)

def make_fig():
	plt.plot(list(resist), 'ro-')

try:
	# Last byte succesfully received from the slave
	last = 0
	# Commands to ask for a float byteArray to the slave
	# The sequence 'abcd' starts with the MSB
	# 'a' : 1st byte
	# 'b' : 2nd byte
	# 'c' : 3rd byte
	# 'd' : 4th byte
	commands = [ord(char) for char in 'wxyz']

	while True:
		x = bytearray()
		j = 0
		# This is to read a byte array of len(commands)
		# float -> len(commands) == 4
		while j < len(commands):
			command = commands[j]
			msg = spi.xfer2([command])
			# Since the RPi reads the SPDR of the slave it needs to
			# dismiss garbage
			if (msg[0] not in commands) and msg[0] != last:
				x.append(msg[0])
				last = msg[0]
				j += 1

		r = struct.unpack('f', x)[0]

		# Plot live
		resist.append(r)
		drawnow(make_fig)
		# print r, time.time() # Byte array is unpacked into float
except(KeyboardInterrupt):
	spi.close()


import math, os, sys, time, random, shutil, logging, csv, json

import netCDF4
import numpy as np
from osgeo import gdal, osr, ogr
import pandas as pd
import geopandas as gpd
from collections import OrderedDict
import logging
import scipy

import geoecon as ge
import hazelbean as hb
import multiprocessing

L = hb.get_logger('process_ssp_scenarios')

def extract_lulc(p):
    if p.tasks['extract_lulc']:

        for scenario_name in p.scenario_names:
            scenario_dir = os.path.join(p.task_dirs['extract_lulc'], scenario_name)
            hb.create_dirs(scenario_dir)

            filename = 'multiple-states_input4MIPs_landState_ScenarioMIP_UofMD-' + scenario_name + '-2-1-f_gn_2015-2100.nc'
            states_path = os.path.join(p.scenarios_data_dir, filename)

            for year in p.years:
                year_dir = os.path.join(scenario_dir, str(year))
                os.mkdir(year_dir)
                L.info('Extracting from ' + states_path)

                ge.extract_geotiff_from_netcdf(states_path, year_dir, year - 2015) #0 = 2015, last year is 85=2100

    else:
        pass

def resample_lulc(p):
    if p.tasks['resample_lulc']:
        match_af = hb.ArrayFrame(p.base_data_ha_per_cell_path)
        match_r_path = p.match_r_path
        hb.reproject_to_cylindrical(match_af.uri, match_r_path)
        # hb.reproject_to_epsg(match_af.uri, match_r_path, 54012)
        match_r_af = hb.ArrayFrame(match_r_path)

        for scenario in p.scenario_names:
            for year  in p.years:
                read_dir = os.path.join(p.task_dirs['extract_lulc'], scenario, str(year))
                write_dir = os.path.join(p.resample_lulc_dir, scenario, str(year))
                hb.create_dirs(write_dir)
                for filename in hb.list_files_in_dir_recursively(read_dir, filter_extensions=['.tif']):
                    input_path = os.path.join(read_dir, filename)
                    output_path = os.path.join(write_dir, os.path.basename(filename) + '.tif')
                    print('input output', input_path, output_path)

                    hb.align_dataset_to_match(input_path, match_r_path, output_path)
    else:
        pass

def extract_management(p):
    if p.tasks['extract_management']:
        for scenario_name in p.scenario_names:
            scenario_dir = os.path.join(p.scenarios_data_dir, scenario_name)
            hb.create_directories(scenario_dir)

            management_path = os.path.join(scenario_dir, 'management.nc')

            # hb.create_dirs([p.2015_management_dir, p.2030_management_dir, p.2050_management_dir, p.2070_management_dir, p.2100_management_dir])
            #
            # ge.extract_geotiff_from_netcdf(management_path, p.2015_management_dir, 0) #0 = 2015, last year is 85=2100
            # ge.extract_geotiff_from_netcdf(management_path, p.2030_management_dir, 15) #0 = 2015, last year is 85=2100
            # ge.extract_geotiff_from_netcdf(management_path, p.2050_management_dir, 35) #0 = 2015, last year is 85=2100
            # ge.extract_geotiff_from_netcdf(management_path, p.2070_management_dir, 55) #0 = 2015, last year is 85=2100
            # ge.extract_geotiff_from_netcdf(management_path, p.2100_management_dir, 85) #0 = 2015, last year is 85=2100
    else:
        pass
def convert_states_to_ag_extent(p):
    if p.tasks['convert_states_to_ag_extent']:

        def add_crop_layers_from_dir(input_dir):

            crop_layer_names = [
                "c4per ^ area_fraction ^ C4 perennial crops.tif",
                "c4ann ^ area_fraction ^ C4 annual crops.tif",
                "c3per ^ area_fraction ^ C3 perennial crops.tif",
                "c3nfx ^ area_fraction ^ C3 nitrogen-fixing crops.tif",
                "c3ann ^ area_fraction ^ C3 annual crops.tif",
            ]
            uris_to_combine = [os.path.join(input_dir, i) for i in crop_layer_names]
            print('uris_to_combine', uris_to_combine)
            match_af = hb.ArrayFrame(uris_to_combine[0])
            proportion_cultivated = np.zeros(match_af.shape)
            mask = np.where((match_af.data >= 0.0) & (match_af.data <= 1.0))
            for uri in uris_to_combine:
                proportion_cultivated[mask] += hb.ArrayFrame(uri).data[mask]

            return proportion_cultivated

        match_path = os.path.join(p.task_dirs['extract_lulc'], p.scenario_names[0], str(p.years[0]), "c4per ^ area_fraction ^ C4 perennial crops.tif")

        for scenario_name in p.scenario_names:
            print('task_dirs', p.task_dirs['extract_lulc'])
            scenario_dir = os.path.join(p.task_dirs['extract_lulc'], scenario_name)
            for year in p.years:
                input_dir = os.path.join(p.task_dirs['extract_lulc'], scenario_name, str(year))
                print(input_dir)

                array = add_crop_layers_from_dir(input_dir)

                output_dir = os.path.join(p.task_dirs['convert_states_to_ag_extent'], scenario_name, str(year))
                hb.create_dirs(output_dir)
                output_path = os.path.join(output_dir, 'proportion_ag.tif')

                hb.save_array_as_geotiff(array, output_path, match_path)
        else:
            pass
if __name__ == '__main__':

    p = hb.ProjectFlow('process_ssp_scenarios')

    p.scenarios_data_dir = os.path.join(hb.EXTERNAL_BULK_DATA_DIR, 'lulc\\luh2')
    p.scenario_names = [
        'IMAGE-ssp126',
        'AIM-ssp360',
        'MAGPIE-ssp585',
    ]

    # p.years = [2015, 2050]
    p.years = [2015, 2050]

    p.tasks['extract_lulc'] = 1
    p.tasks['resample_lulc'] = 1
    p.tasks['extract_management'] = 1
    p.tasks['convert_states_to_ag_extent'] = 1

    args = OrderedDict()
    args['skip_extract_lulc'] = 1
    args['skip_resample_lulc'] = 1
    args['skip_extract_management'] = 1
    args['skip_convert_states_to_ag_extent'] = 0
    p.execute(args)


# class node():
#     def __init__(self,id, *args, **kwargs):
#         self.id=id
#         self.child=[]
#         self.state=[]

#     def add_child(self,n,state):
#         self.child+=[n]
#         self.state+=[state]

n=int(input())
dist=[None]*n
node=list(range(n))
for i in range(n):
    dist[i]=[-1]*n
for i in range(n-1):
    u,v,c=map(int,input().split(" "))
    dist[u-1][v-1]=c-1
    dist[v-1][u-1]=c-1
def search(id,parent,state):
    # print("search",id)
    res=state
    for i in range(n):
        if i!=parent:
            # print(id,i,"dist",dist[id][i])
            if dist[id][i]>=0:
                res+=search(i,id,dist[id][i])
    if res==0:
        if id in node:
            node.remove(id)
        for i in range(n):
            dist[id][i]=-1
            dist[i][id]=-1
    return res
final=[]

def count_leaf(id,parent):
    is_leaf=1
    res=0
    for i in range(n):
        if i!=parent:
            # print(id,i,"dist",dist[id][i])
            if dist[id][i]>=0:
                # print(id,i,"dist",dist[id][i])
                is_leaf=0
                res+=count_leaf(i,id)
    if is_leaf==1:
        global final
        final+=[id]
    return res+is_leaf
count_leaf(0,0)
search(0,0,0)
final=[x+1 for x in final]
print(len(final))
print(" ".join(map(str,final)))


"""
Create ASIF file for IAH and DFW based on ERG data.
"""
import numpy as np
import pandas as pd
from copy import deepcopy
import lxml
from lxml import etree
from pathlib import Path
import pathlib
from airportei.utilis import PATH_INTERIM

DEFAULT_APU_TIME = 13.0

class AsifXml:
    def __init__(
        self, path_inputs_: pathlib.WindowsPath, path_xml_templ_: pathlib.WindowsPath
    ):
        self.path_inputs = path_inputs_
        self.path_xml_templ = path_xml_templ_
        self.asif_tre = lxml.etree._ElementTree()
        self.asif_rt = lxml.etree._Element()
        self.elem_before_trackopset = lxml.etree._Element()
        self.asif_trackopset_a = lxml.etree._Element()
        self.asif_trackopset_d = lxml.etree._Element()
        self.asif_trackopset_dict = {}
        self.asif_annualzn = lxml.etree._Element()
        self.trk = pd.DataFrame
        self.layout = pd.DataFrame
        self.ltos = pd.DataFrame
        self.acftops = pd.DataFrame
        self.heliops = pd.DataFrame
        self.hasheli = False
        self.set_tree_trk_layout_ops()
        self.analysis_arpt = self.layout.apt_code.values[0]
        self.nm = f"{self.analysis_arpt}_2019"
        self.starttime = "2019-01-01T08:00:00"
        self.dur = "24"
        self.taximod = "UserSpecified"
        self.acftPerfModel = "SAE1845"
        self.bankAngle = "true"
        self.description = f"{self.analysis_arpt} 2019 Emissions"
        self.layoutname = ""
        self.case_nm = self.nm + "_ems"
        self.case_src = "Aircraft"
        self.aputime = str(13.0)

    def set_tree_trk_layout_ops(self) -> None:
        parser = etree.XMLParser(remove_blank_text=True)
        self.asif_tre = etree.parse(str(self.path_xml_templ), parser)
        self.asif_rt = self.asif_tre.getroot()
        self.elem_before_trackopset = self.asif_tre.find(".//case//duration")
        self.asif_trackopset_a = self.asif_rt.xpath(
            ".//optype[text()='A']/ancestor::trackOpSet"
        )[0]
        self.asif_trackopset_d = self.asif_rt.xpath(
            ".//optype[text()='D']/ancestor::trackOpSet"
        )[0]
        self.asif_trackopset_dict = {
            "A": self.asif_trackopset_a,
            "D": self.asif_trackopset_d,
        }
        self.asif_annualzn = self.asif_tre.find(".//annualization")
        x_asif_in = pd.ExcelFile(self.path_inputs)
        self.layout = x_asif_in.parse("layout", index_col=0)
        self.trk = x_asif_in.parse("track", index_col=0)
        self.ltos = x_asif_in.parse("ltos", index_col=0)
        self.heliops = self.ltos.loc[lambda df: ~df.anp_helicopter_id.isna()]
        self.acftops = self.ltos.loc[lambda df: df.anp_helicopter_id.isna()]
        if len(self.heliops) != 0:
            self.hasheli = True

    def set_scn_meta(
        self,
    ) -> None:
        scn_attr = {
            "name": self.nm,
            "startTime": self.starttime,
            "duration": self.dur,
            "taxiModel": self.taximod,
            "acftPerfModel": self.acftPerfModel,
            "bankAngle": self.bankAngle,
            "description": self.description,
            "airportLayoutName": self.layout.name.values[0],
        }
        for key, val in scn_attr.items():
            self.asif_tre.find(f".//{key}").text = val

    def set_case_meta(self) -> None:
        case_meta_attr = {
            "case//caseId": str(0),
            "case//name": self.case_nm,
            "case//source": self.case_src,
            "case//startTime": self.starttime,
            "case//duration": self.dur,
        }
        for key, val in case_meta_attr.items():
            self.asif_tre.find(f".//{key}").text = val

    def set_trackopsets(self, assignDefaultGse_="true") -> None:
        self.asif_trackopset_dict["A"].getparent().remove(
            self.asif_trackopset_dict["A"]
        )
        self.asif_trackopset_dict["D"].getparent().remove(
            self.asif_trackopset_dict["D"]
        )
        aircraft_types = {"aircraft": 0, "helicopter": 1}
        for aircraft_type in aircraft_types.values():
            if (aircraft_type == 1) and (not self.hasheli):
                continue
            for op_type in ["A", "D"]:
                if aircraft_type == 0:
                    ops = self.acftops
                elif aircraft_type == 1:
                    ops = self.heliops
                else:
                    raise ValueError("aircraft_type should be either 0 or 1.")
                ops_fil = ops.loc[lambda df: (df.op_type == op_type)]
                trk_fil = self.trk.loc[
                    lambda df: (df.aircraft_type == aircraft_type)
                    & (df.op_type == op_type)
                ]
                asif_trackopset_dcpy = deepcopy(self.asif_trackopset_dict[op_type])
                self.set_track(
                    trk_fil_=trk_fil, asif_trackopset_dcpy_=asif_trackopset_dcpy
                )
                self.set_ops(
                    op_type_=op_type,
                    ops_fil_=ops_fil,
                    trk_fil_=trk_fil,
                    asif_trackopset_dcpy_=asif_trackopset_dcpy,
                    assignDefaultGse_=assignDefaultGse_,
                )
                self.elem_before_trackopset.addnext(asif_trackopset_dcpy)
                self.set_annualization()

    def set_track(
        self, trk_fil_: pd.DataFrame, asif_trackopset_dcpy_: lxml.etree._Element
    ) -> None:
        asif_trackopset_dcpy_.find(".//name").text = trk_fil_.track_name.values[0]
        asif_trackopset_dcpy_.find(".//optype").text = trk_fil_.op_type.values[0]
        asif_trackopset_dcpy_.find(".//airport").text = self.analysis_arpt
        asif_trackopset_dcpy_.find(".//runway").text = str(
            trk_fil_.rwy_end_name.values[0]
        )
        asif_trackopset_dcpy_.find(".//type").text = trk_fil_.segment_type.values[0]
        asif_trackopset_dcpy_.find(".//distance").text = str(
            trk_fil_.dist_or_rad.values[0]
        )
        assert trk_fil_.turn_angle.values[0] == 0, "Handle non-zero turn " "angle."

    def set_ops(
        self,
        op_type_: str,
        ops_fil_: pd.DataFrame,
        trk_fil_: pd.DataFrame,
        asif_trackopset_dcpy_: lxml.etree._Element,
        assignDefaultGse_: str,
    ) -> None:
        asif_ops = asif_trackopset_dcpy_.find(".//operations")
        asif_op = asif_trackopset_dcpy_.find(".//operation")
        asif_op_dcpy = deepcopy(asif_op)
        # Remove the operation from the template. Will replace them with the
        # correct operation for each aircraft in the fleetmix.
        asif_ops.remove(asif_op)
        for idx, row in ops_fil_.iterrows():
            asif_op_dcpy_dcpy = deepcopy(asif_op_dcpy)
            asif_op_dcpy_dcpy.find(".//id").text = op_type_ + str(row.ids)
            asif_op_dcpy_dcpy.find(".//airframeModel").text = row.arfm_mod
            asif_op_dcpy_dcpy.find(".//engineCode").text = row.engine_code
            asif_op_dcpy_dcpy.find(".//assignDefaultGse").text = assignDefaultGse_
            if row.apu_name != row.apu_name:
                asif_op_dcpy_dcpy.find(".//apuName").getparent().remove(
                    asif_op_dcpy_dcpy.find(".//apuName")
                )
                if op_type_ == "A":
                    asif_op_dcpy_dcpy.find(".//arrivalApuTime").getparent().remove(
                        asif_op_dcpy_dcpy.find(".//arrivalApuTime")
                    )
                else:
                    asif_op_dcpy_dcpy.find(".//departureApuTime").getparent().remove(
                        asif_op_dcpy_dcpy.find(".//departureApuTime")
                    )
            else:
                asif_op_dcpy_dcpy.find(".//apuName").text = row.apu_name
                if op_type_ == "A":
                    asif_op_dcpy_dcpy.find(".//arrivalApuTime").text = str(self.aputime)
                else:
                    asif_op_dcpy_dcpy.find(".//departureApuTime").text = str(
                        self.aputime
                    )
            asif_op_dcpy_dcpy.find(".//numOperations").text = str(row.ltos)
            asif_op_dcpy_dcpy.find(".//opType").text = row.op_type
            if op_type_ == "A":
                asif_op_dcpy_dcpy.find(".//arrivalAirport").text = self.analysis_arpt
                asif_op_dcpy_dcpy.find(".//arrivalRunway").text = str(
                    trk_fil_.rwy_end_name.values[0]
                )
                asif_op_dcpy_dcpy.find(".//onTime").text = self.starttime
            else:
                asif_op_dcpy_dcpy.find(".//departureAirport").text = self.analysis_arpt
                asif_op_dcpy_dcpy.find(".//departureRunway").text = str(
                    trk_fil_.rwy_end_name.values[0]
                )
                asif_op_dcpy_dcpy.find(".//offTime").text = self.starttime
            asif_op_dcpy_dcpy.find(".//saeProfile").text = row.profile
            asif_op_dcpy_dcpy.find(".//stageLength").text = str(row.stage_len)
            asif_ops.append(asif_op_dcpy_dcpy)

    def set_annualization(self) -> None:
        self.asif_annualzn.find(".//name").text = "baseline"
        self.asif_annualzn.find(".//annualizationCase//name").text = self.case_nm

    def write_asif(self, path_out: pathlib.WindowsPath) -> None:
        self.asif_tre.write(str(path_out), pretty_print=True)
        ...

    def getasifxml(self, path_inputs: str, path_xmltempl: str) -> etree._ElementTree:
        ...

if __name__ == "__main__":
    fac_ids = ["iah", "dfw"]
    starttime = "2020-01-01T08:00:00"
    path_asif_in = Path(
        r"C:\Users\a-bibeka\PycharmProjects\airport_ei\data\processed\epa_ltos_review"
    )
    suffix = ""
    TESTING = False
    assignDefaultGse = "true"
    for fac_id in fac_ids:
        path_xml_temp = Path.home().joinpath(PATH_INTERIM, "template_asif_scenario.xml")
        asif_input_fi = Path.home().joinpath(
            path_asif_in, "{}_input_fi_epa.xlsx".format(fac_id)
        )
        asifxml_obj = AsifXml(path_inputs_=asif_input_fi, path_xml_templ_=path_xml_temp)
        asifxml_obj.starttime = starttime
        path_asif_out = Path.home().joinpath(
            path_asif_in,
            "{}_scn_asif{}.xml".format(asifxml_obj.analysis_arpt.lower(), suffix),
        )
        asifxml_obj.set_tree_trk_layout_ops()
        asifxml_obj.set_scn_meta()
        asifxml_obj.set_case_meta()
        asifxml_obj.set_trackopsets(assignDefaultGse_=assignDefaultGse)
        asifxml_obj.set_annualization()
        asifxml_obj.write_asif(path_out=path_asif_out)


##Elias Howell | 10/16/2019 | Lab Assignment 6
##
##This program takes an entered monetary value, calculates their change,
##  and prints out the # of bills and coins used to make change for said amount
##
##Algorithm:
##  0)Request monetary value from user converted to type float
##  1)Validates that userAmount is valid floating point
##  1)Determine # of bills or coins by assigning "currencyType" to "userAmount" divided by "currencyValue"
##  2)Use integer division to avoid a fractional # for bills and coins
##  3)Lastly, subtract "currencyValue" times # of bill or coins from "userAmount"
##  4)Repeat 1-4

def main():
    userAmount = input("Enter an amount of money to be converted to change: $")

    #Validates userAmount is a valid floating point
    while userAmount.isdigit() == False and '.'  not in userAmount:
        print("Invalid entry. Must be a floating point value.")
        userAmount = input("Enter an amount of money to be converted to change: $")

    makeChange(float(userAmount))

#Determines # of bills and coins through integer division of user amount by currency value
#Then subtracts that from user amount, repeats in descending order then prints number of bills and coins
def makeChange(userAmount):
    hundreds, userAmount = divide(userAmount, 100)
    fifties, userAmount = divide(userAmount, 50)
    twenties, userAmount = divide(userAmount, 20)
    tens, userAmount = divide(userAmount, 10)
    fives, userAmount = divide(userAmount, 5)
    ones, userAmount = divide(userAmount, 1)
    quarters, userAmount = divide(userAmount, .25)
    dimes, userAmount = divide(userAmount, .10)
    nickels, userAmount = divide(userAmount, .05)
    pennies, userAmount = divide(userAmount, .01)

    #Cast from float to int to remove decimal, then to str for concatenation
    print("\n\nHand the customer the following amounts of each: ")
    print("$100 x " + str(int(hundreds)))
    print("$50  x " + str(int(fifties)))
    print("$20  x " + str(int(twenties)))
    print("$10  x " + str(int(tens)))
    print("$5   x " + str(int(fives)))
    print("$1   x " + str(int(ones)))
    print("25¢  x " + str(int(quarters)))
    print("10¢  x " + str(int(dimes)))
    print("5¢   x " + str(int(nickels)))
    print("1¢   x " + str(int(pennies)))

#Determines # of bills and coins through integer division of user amount by currency value
#Then subtracts that from user amount, repeats in descending order
def divide(userAmount, currencyValue):
    numOfCurrency = userAmount // currencyValue
    userAmount = userAmount - (currencyValue * numOfCurrency) + .0001
    return numOfCurrency, userAmount

main()


# -*- coding: utf-8 -*-
"""
@author: longshuicui
@date  :   2021/1/30
@function:
934. Shortest Bridge (Medium)
https://leetcode.com/problems/shortest-bridge/
题目描述
    给定一个二维 0-1 矩阵，其中 1 表示陆地， 0 表示海洋，每个位置与上下左右相连。已知矩
    阵中有且只有两个岛屿，求最少要填海造陆多少个位置才可以将两个岛屿相连。
输入输出样例
    输入是一个二维整数数组，输出是一个非负整数，表示需要填海造陆的位置数。
    Input:
    [[1,1,1,1,1],
    [1,0,0,0,1],
    [1,0,1,0,1],
    [1,0,0,0,1],
    [1,1,1,1,1]]
    Output: 1
题解
    求解两个岛屿的最短距离问题。先用深度优先搜索找到一个岛屿，然后再用广度优先搜索找到最近的岛屿
"""
from collections import deque

def shortestBridgeIteration(grid):
    m, n = len(grid), len(grid[0])

    def neighbors(r, c):
        for nr, nc in ((r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)):
            if 0 <= nr < m and 0 <= nc < n:
                yield nr, nc

    def getIslands():
        # DFS
        done = set()
        islands = []
        for i, row in enumerate(grid):
            for j, val in enumerate(row):
                if val and (i, j) not in done:
                    stack = [(i, j)]  # 入栈
                    seen = {(i, j)}
                    while stack:
                        r, c = stack.pop()  # 出栈
                        for nr, nc in neighbors(r, c):
                            if grid[nr][nc] and (nr, nc) not in seen:  # 判断是否满足条件
                                stack.append((nr, nc))  # 入栈
                                seen.add((nr, nc))
                    done |= seen
                    islands.append(seen)
        return islands

    # 找到岛屿
    source, target = getIslands()
    # BFS
    queue = deque([(node, 0) for node in source])
    done = set(source)
    while queue:
        node, d = queue.popleft()
        if node in target:
            return d - 1
        for nr, nc in neighbors(*node):
            if (nr, nc) not in done:
                queue.append(((nr, nc), d + 1))
                done.add((nr, nc))

grid = [[0, 1, 0],
        [0, 0, 0],
        [0, 0, 1]]
res = shortestBridgeIteration(grid)
print(res)


import operator

class Mention:
    """Class for maintaining the meta data associated with a mention in a document."""

    def __init__(self, constituent, max_cands, gold_labels=None):
        """Initializes Mention from Constituent from EL View """

        # tuple for maintaining start and end of span
        self.span = (constituent["start"],constituent["end"])
        # label assigned by the EL system
        self.label = constituent["label"]
        self.score = constituent["score"]
        # gold label if supplied
        self.gold = -1
        # candidate titles for mention. list of tuples (title, score)
        self.candidate_titles = []

        label_score_map = constituent["labelScoreMap"]
        for label, score in label_score_map.items():
            self.candidate_titles.append((label,score))
        self.candidate_titles.sort(key=operator.itemgetter(1),reverse=True)
        self.candidate_titles = self.candidate_titles[:max_cands]

        # find index of gold in candidate titles list
        if gold_labels != None:
            gold_comp = [i for i, tup in enumerate(self.candidate_titles) \
                            if tup[0] == gold_labels[self.span]]

            if gold_comp:
                self.gold = gold_comp[0]
            else:
                self.gold = None

# end Mention class

class Document:
    """Class for representing a document for coherence."""

    def __init__(self, ta_id,el_view, max_cands, gold_view=None,
                    discard_unlinkable=False, discard_no_recall=False):
        """Initializes a Document from an EL view."""
        # list of mentions in the document
        self.mentions = []
        # number of mentions to use in scoring -- only includes mentions
        # which weren't linked to NIL by the EL system
        self.m = None
        # dictionary which maps tuples of spans to the gold label annotation
        self.gold_labels = None
        # if gold annotations are provided, instantiate dictionary of golds
        if gold_view != None:
            gold_constituents = gold_view.get_cons()

            self.gold_labels = {}
            for gold in gold_constituents:
                self.gold_labels[(gold["start"],gold["end"])] = gold["label"]

        # populate mentions list from constituents from an EL view
        constituents = el_view.get_cons()

        for constituent in constituents:
            if constituent["labelScoreMap"]:
                if discard_unlinkable and self._all_unk(constituent):
                        continue
                mention = Mention(constituent, max_cands,\
                    gold_labels=self.gold_labels)
                if discard_no_recall and mention.gold == None:
                    continue
                self.mentions.append(mention)
        self.mentions = [mention for mention in self.mentions if mention.gold != None]
        self.m = len(self.mentions)
        #for mention in self.mentions:
        #    if mention.gold != 0:
        #        titles = [x[0] for x in mention.candidate_titles]
        #        print(titles, "\t", mention.gold, "\t", mention.label, "\t", self.m)

    def _all_unk(self, constituent):
        """Checks if all Wikipedia titles in the constituent are unk.

        @param: constituent: mention to check
        """
        known = [kb_id for kb_id in list(constituent["labelScoreMap"].keys())\
            if "unk_wid" not in kb_id]
        return len(known) == 0

# end Document


import comtypes.client
import pyautocad
import time
import copy
import os
from pyautocad import Autocad, APoint

acad = Autocad(create_if_not_exists=True)
acad = comtypes.client.CreateObject('AutoCAD.Application', dynamic=True)
in_file = input("address")
#C:\Users\q0010\Desktop\新增資料夾 (3)\
import xlwt
file = xlwt.Workbook()
nn = input("save")
#demo.xls
savename=in_file + nn
table = file.add_sheet('exchange')
for subdir, dirs, files in os.walk(in_file):
        all_file=files
        print (files)
        break
d300=0
for fil in all_file:
        if 'dwg' in fil:
                fill=fil

                acad = comtypes.client.GetActiveObject('AutoCAD.Application', dynamic=True)
                time.sleep(3)
                doc = acad.Documents.Open(in_file + fill)
                acad = Autocad(create_if_not_exists=True)
                d301=0
                for text in acad.iter_objects('Text'):
                    x=text.InsertionPoint[0]
                    y=text.InsertionPoint[1]
                    if 699<x<832 and 70<y<87:
                        print (text.TextString)
                        hh=text.TextString
                        table.write(d300,d301,hh)
                        d301=d301+1
        d300=d300+1

doc.close(in_file + fill)
file.save(savename)
f=os.system("taskkill /f /IM acad.exe")


"""
Created on Sat Aug 20 21:47:53 2022

@author: Lavanya_Kudli
"""
import biosteam as bst
import biosteam.units
import thermosteam as tmo
from thermosteam import functional as fn
from chemicals import atoms_to_Hill
import thermosteam as tmo
from thermosteam import Chemicals
from thermo import TDependentProperty
#chems is a list of all the chemicals used in this biorefinery

chems = tmo.Chemicals([
#Chemicals used in biodiesel production
        tmo.Chemical('Sodium_methoxide',formula ='NaOCH3',phase = 'l',default = True),
        tmo.Chemical('Methanol'),
#Chemical for acid degumming
        tmo.Chemical('Citric_acid'),

##chemical for representing phospholipids, taken directly from lipidcane biorefinery
        tmo.Chemical('Phosphatidylinositol',
                      formula='C47H83O13P',
                      search_db=False,
                      CAS='383907-36-6',
                      MW = 	886.56,
                      default=True,
                      Hf=1000*(-316.67*4 - 2466.4),#TODO: find a better assumption,assuming LLL with 4 bonds HF
                      phase = 'l',
                      ),
#Crude glycerol is a product of transesterification
        tmo.Chemical('Glycerol'),
#TAGs of High oleic sunflower oil
        tmo.Chemical('OOO', search_ID = '122-32-7',Hf = 1000*(-76.494*18 - 815.18),phase_ref = 'l' ),#from cane>chemicals
        tmo.Chemical('LnLnLn', search_ID = '537-40-6',Hf = 1000*(-316.67*3 - 2466.4)),#This is Trilinolein
#Below TAG's not a part of the database
         tmo.Chemical('LLL',
                      search_ID = '7049-66-3',#Based on reference search in CAS Finder
                      search_db = False,
                      formula = 'C54H96O6',#Based on reference search in CAS Finder
                      phase = 'l',
                      Hf = (((2/3)*(-76.494*18 - 815.18))+((1/3)*(-316.67*2 - 2466.4)))*1000
                      ),
        tmo.Chemical('OOL',
                     search_ID = '28880-78-6',#Based on reference search in CAS Finder
                     search_db = False,
                     formula = 'C57H102O6',#Based on reference search in CAS Finder
                     phase = 'l',
                     Hf = (((2/3)*(-76.494*18 - 815.18))+((1/3)*(-316.67*2 - 2466.4)))*1000
                     ),
        tmo.Chemical('LLO',
                         search_ID = '28409-91-8',#Based on reference search in CAS Finder
                         search_db = False,
                         formula = 'C57H100O6',#Based on reference search in CAS Finder
                         phase = 'l',
                         Hf = (((2/3)*(-316.67*2 - 2466.4))+((1/3)*(-76.494*18 - 815.18)))*1000
                         ),
        tmo.Chemical('SOO',
                         search_ID = '29590-02-1',#Based on reference search in CAS Finder
                         search_db = False,
                         formula = 'C57H106O6',#Based on reference search in CAS Finder
                         phase = 'l',
                         Hf = 1000*(((1/3)*( -59.571*18 - 1358.7))+((2/3)*(-76.494*18 - 815.18)))
                         ),
        tmo.Chemical('PLO',
                         search_ID = '26836-35-1',#Based on reference search in CAS Finder
                         search_db = False,
                         formula = 'C55H100O6',#Based on reference search in CAS Finder
                         phase = 'l',
                         Hf = 1000*(((1/3)*(-76.494*18 - 815.18)) + ((1/3)*(-316.67*2 - 2466.4)) + ((1/3)*(-59.571*16 - 1358.7)))
                         ),

        tmo.Chemical('PoOO',
                     search_ID = '38703-17-2',#Based on reference search in CAS Finder
                     search_db = False,
                     formula = 'C55H100O6',#Based on reference search in CAS Finder
                     phase = 'l',
                     Hf = 1000*(((1/3)*(-76.494*16 - 815.18))+ ((2/3)*(-76.494*18 - 815.18)))),
        tmo.Chemical('POO',
                 search_ID = '27071-84-7',#Based on reference search in CAS Finder
                 search_db = False,
                 formula = 'C55H102O6',#Based on reference search in CAS Finder
                 phase = 'l',
                 Hf = 1000*(((2/3)*(-76.494*18 - 815.18)) + ((1/3)*(-59.571*16 - 1358.7)))
                 ),

        tmo.Chemical('POS',
                 search_ID = '26836-31-7',#Based on reference search in CAS Finder
                 search_db = False,
                 formula = 'C55H104O6', #Based on reference search in CAS Finder
                 phase = 'l',
                 Hf = 1000*(((1/3)*(-76.494*18 - 815.18)) + ((1/3)*(-59.571*16 - 1358.7)) + ((1/3)*( -59.571*18 - 1358.7)))
                 ),

        tmo.Chemical('POP',
                 search_ID = '28409-94-1',#Based on reference search in CAS Finder
                 search_db = False,
                 formula = 'C53H100O6',#Based on reference search in CAS Finder
                 phase = 'l',
                 Hf = (((2/3)*(-59.571*16 - 1358.7)) + ((1/3)*(-76.494*18 - 815.18)))*1000
                 ),

        tmo.Chemical('PLS',
                 search_ID = '26836-32-8',#Based on reference search in CAS Finder
                 search_db = False,
                 formula = 'C55H102O6',#Based on reference search in CAS Finder
                 phase = 'l',
                 Hf = 1000*(((1/3)*(-59.571*16 - 1358.7)) +((1/3)*(-59.571*18 - 1358.7))+ ((1/3)*( -316.67*2 - 2466.4)))
                 ),
        tmo.Chemical('PPP',
                     search_ID = 'Tripalmitin',
                     Hf = 1000*(-59.571*16 - 1358.7)
                     ),

##Chemicals part of Biodiesel
        tmo.Chemical('Methyl_oleate'),
        tmo.Chemical('Methyl_palmitate'),
        tmo.Chemical('Methyl_stearate'),
        tmo.Chemical('Methyl_linoleate'),
        tmo.Chemical('Methyl_palmitoleate',search_ID ='1120-25-8'),

#Dihydroxylation chemicals
            tmo.Chemical('Hydrogen_peroxide'),
            tmo.Chemical('Water'),
#Dihydroxylation products
#Product 1
        tmo.Chemical('MDHSA',
                     search_ID = '1115-01-1',
                     Hf = -947.7*1000 #Wikepedia value for https://en.wikipedia.org/wiki/Stearic_acid
                    ),
#Product 2
#Ref for dihydroxy_palmitic_acid: https://www.chemsrc.com/en/cas/29242-09-9_803992.html
        tmo.Chemical('Dihydroxy_palmitic_acid',
                 search_ID = '29242-09-9',
                 search_db = False,
                 Tb = 458 + 273.15,#CAS finder: 458.0±25.0 °C,Press: 760 Torr
                 formula = 'C16H32O4',
                 MW = 288.42+273.15,
                 Hf = -892*1000 #Wikepedia value for https://en.wikipedia.org/wiki/Palmitic_acid
                 ),
#Product 3
        tmo.Chemical('Methyl_9_10_dihydroxylinoleate',
                 search_ID = '62071-03-8',
                 search_db = False,
                 MW = 328.492,
                 Tb = 449.4+273.15,#CAS finder: Tb =449.4±35.0 °C,Press: 760 Torr
                 formula = 'C19H36O4',
                 Hf = -634.7*1000 #TODO: Ref:https://webbook.nist.gov/cgi/cbook.cgi?ID=C60333&Mask=2
                 ),

# Products of oxidative_cleavage
        tmo.Chemical('Monomethyl_azelate'),
        tmo.Chemical('Suberic_acid'),
        tmo.Chemical('Caprylic_acid'),
        tmo.Chemical('Hexanoic_acid'),
        tmo.Chemical('Heptanoic_acid'),
        tmo.Chemical('Hexanoic_acid'),
        tmo.Chemical('Malonic_acid'),
        tmo.Chemical('Pelargonic_acid'),

# Products of hydrolysis
        tmo.Chemical('Palmitic_acid'),
        tmo.Chemical('Stearic_acid'),
        tmo.Chemical('Oleic_acid'),
        tmo.Chemical('Linoleic_acid', search_ID = '60-33-3'),
        tmo.Chemical('Palmitoleic_acid', search_ID = '373-49-9'),
        tmo.Chemical('Azelaic_acid'),

# Oxidants used and other gaseous products
        tmo.Chemical('Nitrogen',phase = 'g'),
        tmo.Chemical('Oxygen',phase = 'g'),
        tmo.Chemical('Carbon_dioxide',phase = 'g'),

#Solvent for countercurrent extraction of monocarboxylic acids
        tmo.Chemical('Octane'),
        tmo.Chemical('Cycloheptane'),
        tmo.Chemical('Bicyclo_octane',search_ID = '6221-55-2'),
        tmo.Chemical('Toluene'),

## Catalysts used in the process
## Tungstic_acid boiling point: https://en.wikipedia.org/wiki/Tungstic_acid
       tmo.Chemical('Tungsten',default = True),
       tmo.Chemical('Tungstic_acid',
                  Tb = 1746,
                  default = True,
                  formula = 'H2WO4',
                  phase = 'l'),
        tmo.Chemical('Tungstate_ion',
                 search_db = False,
                 CAS = '12737-86-9',
                 formula = 'O4W-2',
                 MW =  tmo.Chemical('Tungstic_acid').MW,#TODO: check this assumption
                 phase = 'l',
                 default = True,
                 Tb = 5828.15 #Based on tungsten's BP
                 ),
        tmo.Chemical('Cobalt',default = True),
        tmo.Chemical('Hydrogen',default = True),
        tmo.Chemical('Hydrogen_ion',
                 Tb = 20.271,#Based on hydrogen's BP
                 phase = 'l',
                 formula = 'H+',
                 default = True
                 ),
        tmo.Chemical('Cobalt_chloride',
                     search_ID = '7646-79-9',
                     phase = 'l'
                     ),
        tmo.Chemical('Cobalt_acetate_tetrahydrate',
                      phase = 'l',#TODO: explore phase
                      search_ID = '6147-53-1',
                      Tb = 117.1+273.15,
                      Hf = 0.45 #TODO: change
                      ),
        tmo.Chemical('Acetate',phase = 'l', default = True),
        tmo.Chemical('Acetate_ion', phase = 'l', search_ID = '71-50-1',default = True),
        tmo.Chemical('Cobalt_ion',search_ID ='Cobalt(2+)',  phase = 'l',
                      Tb=3200.15,#Based on cobalt's BP
                      default = True),
##Chemicals required for catalyst recovery
        tmo.Chemical('Calcium_hydroxide',default = True,phase = 'l'),#assumed this phase because it is soluble in the reaction media it is used in
        tmo.Chemical('Calcium_chloride',phase = 'l'),
        tmo.Chemical.blank('Calcium_tungstate',
                       CAS = '7790-75-2',
                       MW = 287.92,
                       Tb = 5828.15, #Based on tungsten's BP
                       formula = 'CaWO4',
                       phase = 'l',
                       Hf = 0.45),#TODO: change
        tmo.Chemical('Calcium_acetate',phase = 'l', default = True),
        tmo.Chemical('Cobalt_hydroxide',phase = 'l', default = True),
        tmo.Chemical('HCl2',phase = 'l',search_ID = 'HCl'),
        tmo.Chemical('Sodium_hydroxide_liquid',phase = 'l', search_ID ='NaOH'),
        tmo.Chemical('Sodium_acetate', phase = 'l'),
##Resin for hydrolysis
##Sulfonated_polystyrene with a search_ID = '98-70-4', lacks Hvap data, hence polystyrene's properties were used
##Boiling point based on amberlyte
# Ref:##https://www.chemsrc.com/en/cas/39389-20-3_843683.html#:~:text=amberlyst%28r%29%2015%20CAS%20Number%3A%2039389-20-3%3A%20Molecular%20Weight%3A%20314.39900%3A,Point%3A%20266.3%C2%BAC%3A%20Symbol%3A%20GHS07%3A%20Signal%20Word%3A%20Warning%20%C3%97
        tmo.Chemical('polystyrene_based_catalyst',
                     search_ID='Polystyrene',
                     Tb = 516.7+273.15,
                     phase = 's',
                     default=True),
##For imported lipidcane module compatibility
        tmo.Chemical('MonoOlein',search_ID = '111-03-5'),
        tmo.Chemical('Dipalmitin'),
        tmo.Chemical('Monopalmitin'),
#Natural gas for heating purposes
        tmo.Chemical('Natural_gas',
                     search_ID = 'CH4'),
#Chemicals required by the boilerturbogenerator
        tmo.Chemical('Ash',
                     MW = 1,
                     phase = 's',
                     search_db=False,
                     default = True,
                     Hf = 0),
        tmo.Chemical('P4O10',
                     phase = 's',
                     default = True),
        tmo.Chemical('SO2',
                     phase = 'g',
                     ),
    tmo.Chemical('CO', search_ID='CarbonMonoxide',
                 phase='g', Hf=-26400* 4.184),#Ref: lactic acid chemicals
    tmo.Chemical('NH3', phase='g', Hf=-10963*4.184),
    tmo.Chemical('NO', search_ID='NitricOxide', phase='g'),
    tmo.Chemical('NO2', phase='g'),
    tmo.Chemical('H2S', phase='g', Hf=-4927*4.184),
    tmo.Chemical('SO2', phase='g'),
    tmo.Chemical('CaSO4',search_ID = 'Calcium_sulfate'),
    tmo.Chemical('Calcium_dihydroxide', phase='s', Hf=-235522*4.184),
#WWTs sludge based on cellulosic.chemicals
        tmo.Chemical('WWTsludge',
                     search_db = False,
                     formula="CH1.64O0.39N0.23S0.0035",
                     Hf=-23200.01*4.184,
                     phase = 'l',
                     default = True,
                     )
                 ])

#Fitting data for MMA based on ChemSep
# Ts = [i + 273.15 for i in  (148, 159, 120, 185.5, )]
# Psats = [i / 760 * 101325 for i in (1, 3, 0.03, 11, )]
# res, stats = TDependentProperty.fit_data_to_model(Ts=Ts, data=Psats, model='Antoine', do_statistics=True, multiple_tries=True, model_kwargs={'base': 10.0})
# method = 'ANTOINE_POLING'
# chems['Monomethyl_azelate'].Psat.ANTOINE_POLING_coefs = res['A'], res['B'], res['C']
# chems['Monomethyl_azelate'].Psat.all_methods.add(method)
# chems['Monomethyl_azelate'].Psat.method = method
# chems['Monomethyl_azelate'].Psat.T_limits[method] = (100, chems['Monomethyl_azelate'].Psat.Tc)
chems['Monomethyl_azelate'].Pc = 2.39587E+06#Chemical compound generator DWSIM
chems['Monomethyl_azelate'].Tc = 837.971#Chemical compound generator DWSIM
chems['Monomethyl_azelate'].omega = 1.09913#Chemical compound generator DWSIM
chems['Monomethyl_azelate'].Tb = 650.2#Chemical compound generator DWSIM

#properties of TAGs that are missing
# chems.OOO.Cn.l.method = 'DADGOSTAR_SHAW'
# chems.PPP.Cn.l.method = 'DADGOSTAR_SHAW'
chems.Methyl_palmitate.Cn.l.method = 'DADGOSTAR_SHAW'
chems.Palmitic_acid.Cn.l.method = 'DADGOSTAR_SHAW'
chems.Stearic_acid.Cn.l.method = 'DADGOSTAR_SHAW'
chems.Oleic_acid.Cn.l.method = 'DADGOSTAR_SHAW'
chems.Octane.Cn.l.method = 'DADGOSTAR_SHAW'
chems.Natural_gas.Cn.l.method = 'DADGOSTAR_SHAW'
# chems.Cobalt_chloride.Cn.l.method = 'ROWLINSON_BONDI'

chems.OOO.copy_models_from(chems.PPP,['mu',
                                      # 'Cn'
                                      ])
chems.LnLnLn.copy_models_from(chems.PPP,['mu'])
TAGs_with_unknown_props = [ 'LLL',
                            'OOL','LLO','SOO',
                            'PLO','PoOO','POO',
                            'POS','POP','PLS'
                          ]
for i in TAGs_with_unknown_props:
    chems[i].Tb = chems.OOO.Tb
    chems[i].copy_models_from(chems.PPP,['mu'])

## The oxidative cleavage catalyst properties are based on cobalt chloride
chems.Cobalt_acetate_tetrahydrate.copy_models_from(chems.Cobalt_chloride,
                                                      ['sigma',
                                                       #'Hvap',
                                                       #'Psat',
                                                       'kappa',
                                                       #'Cn',
                                                       ])
## The density of cobalt acetate tetrahydrate is available in the literature, rho is 1730 Kg/m3
## https://scifinder-n.cas.org/searchDetail/substance/634d77a73c1f076117e95f61/substanceDetails
## Cobalt acetate dissolution reaction data
V_of_cobalt_acetate_tetrahydrate = fn.rho_to_V(1730,chems['Cobalt_acetate_tetrahydrate'].MW)
chems.Cobalt_acetate_tetrahydrate.V.add_model(V_of_cobalt_acetate_tetrahydrate,
                                                 top_priority = True)
chems.Tungstic_acid.copy_models_from(chems.Tungsten,
                                     ['Hvap','Psat'])
# chems.Tungstic_acid.V.add_model(fn.rho_to_V(rho=5.59,#https://en.wikipedia.org/wiki/Tungstic_acid
                                            # MW = chems.Tungstic_acid))
## Tungstate ion default to properties
chems.Tungstate_ion.copy_models_from(chems.Tungsten,
                                     ['Hvap','Psat',
                                      'Cn','mu'
                                     ])
## Hydrogen ion defaults to properties of hydrogen
chems.Hydrogen_ion.copy_models_from(chems.Hydrogen,
                                       ['Hvap',
                                        'Psat',
                                        'mu',
                                        'Cn'])
chems.Cobalt_ion.copy_models_from(chems.Cobalt,
                                       ['Hvap',
                                        'Psat'])

for i in ['Hydrogen_ion','Tungstate_ion','Cobalt_ion']:
    V = fn.rho_to_V(rho=1e5, MW=chems[i].MW)
    chems[i].V.add_model(V, top_priority=True)
## Products of the precipitation reaction
## https://scifinder-n.cas.org/searchDetail/substance/634db2343c1f076117eb77ce/substanceDetails
chems.Calcium_hydroxide.V.add_model(fn.rho_to_V(2.34,
                                                chems.Calcium_hydroxide.MW),
                                                top_priority = True)

chems.Calcium_tungstate.copy_models_from(chems.Tungsten,
                                            ['Hvap',
                                             'Psat','Cn'])
chems.Calcium_tungstate.V.add_model(fn.rho_to_V(5800,
                                                chems.Calcium_tungstate.MW),
                                                top_priority = True)
chems.Acetate_ion.copy_models_from((chems.Acetate),
                                      ['mu',
                                       'Psat',
                                       'Hvap',
                                       'sigma',
                                       ])
Acetate_rho = chems.Acetate.rho(298.15,101325)
chems.Acetate_ion.V.add_method(chems.Acetate_ion.MW*10E-3/Acetate_rho)
chems.Calcium_acetate.V.add_method(chems.Calcium_acetate.MW*0.000001/1.5)#density from: https://pubchem.ncbi.nlm.nih.gov/compound/Calcium-acetate#section=Density
chems.Cobalt_hydroxide.V.add_method(chems.Cobalt_hydroxide.MW*1.0E-6/3.597)
# chems.Cobalt_hydroxide.copy_models_from(tmo.Chemical('NaOH'),['Psat'])
#TODO: change the below
chems.Calcium_hydroxide.copy_models_from(tmo.Chemical('NaOH'),['Psat'])
chems.Calcium_chloride.copy_models_from(tmo.Chemical('NaOH'),['Psat'])
chems.Calcium_acetate.copy_models_from(tmo.Chemical('NaOH'),['Psat'])
## Modelling properties of dihydroxylated compounds as MDHSA
##TODO: find better assumptions for these below
chems.Dihydroxy_palmitic_acid.copy_models_from(chems.MDHSA,
                                                  ['Hvap',
                                                   'Psat',
                                                   'Cn',
                                                   'V',
                                                   'mu'
                                                   ])

chems.Methyl_9_10_dihydroxylinoleate.copy_models_from(chems.MDHSA,
                                                         ['Hvap',
                                                          'Psat',
                                                          'Cn',
                                                          'V',#rho_methyldihydroxylinoleate = 0.980±0.06 g/cm3,Temp: 20 °C; Press: 760 Torr
                                                              #rho similar to MDHSA
                                                          'mu',
                                                          ])
chems.Methyl_9_10_dihydroxylinoleate.Pc = chems.MDHSA.Pc
chems.Cobalt_hydroxide.copy_models_from(chems.Cobalt_chloride,
                                        ['Hvap','Psat'])
chems.Cobalt_hydroxide.Tb = 100+273.15 #https://www.chembk.com/en/chem/Cobalt%20hydroxide
##Adding missing dortmund properties for the following chemicals
chems.Methyl_palmitoleate.Dortmund.set_group_counts_by_name({'CH3': 2,
                                                                'CH2': 11,
                                                                'CH2COO': 1,
                                                                'CH=CH' : 1})

chems.Nitrogen.PSRK.set_group_counts_by_name({'N2':1})

chems.LLL.Dortmund.set_group_counts_by_name({'CH3': 3,
                                             'CH2': 11+11+11+2,
                                             'CH=CH': 2+2+2,
                                             'CH2COO':3,
                                             'CH':1
                                             })

chems.OOL.Dortmund.set_group_counts_by_name({'CH3': 3,
                                             'CH2': 13+13+11+2,
                                             'CH=CH': 4,
                                             'CH2COO':3,
                                             'CH':1
                                             })
chems.LLO.Dortmund.set_group_counts_by_name({'CH3': 3,
                                             'CH2': 11+13 +11+2,
                                             'CH=CH': 5,
                                             'CH2COO': 3,
                                             'CH':1
                                             })

chems.SOO.Dortmund.set_group_counts_by_name({'CH3':3,
                                             'CH2':15+13+13+2,
                                             'CH=CH':2,
                                             'CH2COO':3,
                                             'CH':1
                                             })
chems.PLO.Dortmund.set_group_counts_by_name({'CH3':3,
                                             'CH2':11+13+13+2,
                                             'CH=CH':2+1,
                                             'CH2COO': 1+1+1,
                                             'CH':1
                                             })
chems.PoOO.Dortmund.set_group_counts_by_name({'CH3':3,
                                              'CH2':11+13+13+2,
                                              'CH=CH':1+1+1,
                                              'CH2COO': 1+1+1,
                                              'CH':1
                                                    })
chems.POO.Dortmund.set_group_counts_by_name({'CH3':3,
                                             'CH2':13+13+13+2,
                                             'CH=CH':1,
                                             'CH2COO': 1+1+1,
                                             'CH':1
                                             })
chems.POS.Dortmund.set_group_counts_by_name({'CH3':3,
                                             'CH2':13+13+15+2,
                                             'CH=CH':1,
                                             'CH2COO': 1,
                                             'CH':1
                                             })
chems.POO.Dortmund.set_group_counts_by_name({'CH3':3,
                                             'CH2':13+13+13+2,
                                             'CH=CH':1+1,
                                             'CH2COO': 1+1+1,
                                             'CH':1
                                             })

chems.POP.Dortmund.set_group_counts_by_name({'CH3':3,
                                    'CH2':13+13+13+2,
                                    'CH=CH':1,
                                    'CH2COO': 1+1+1,
                                    'CH':1
                                              })
chems.PLS.Dortmund.set_group_counts_by_name({'CH3':3,
                                             'CH2':13+11+15+2,
                                             'CH=CH':2,
                                             'CH2COO': 1+1+1,
                                             'CH':1 })

chems.Dihydroxy_palmitic_acid.Dortmund.set_group_counts_by_name({'CH3':1,
                                                        'COOH':1,
                                                        'CH2':12,
                                                        'CH':2,
                                                        'OH(S)':2})
chems.Methyl_9_10_dihydroxylinoleate.Dortmund.set_group_counts_by_name({'CH3':2,
                                                               'CH2':11,
                                                               'CH=CH':1,
                                                               'CH':2,
                                                               'CH2COO':1,
                                                               'OH(S)':2})
chems.Dipalmitin.Dortmund.set_group_counts_by_name({'CH3':2,
                                                    'CH2COO':2,
                                                    'CH2':13+13+2,
                                                    'CH':1,
                                                    'OH(P)':1
                                                    })
###############################################################################################################
def OOO_CCPsat_model(T):
      R = 8.314
      theta = 298.15
      ln10 = 2.30258509
      return ((-91320000/(R*theta*ln10))+ ((169240000/R*ln10)*((1/theta) - (1/T))))
# chems.OOO.Psat.add_method(f=OOO_CCPsat_model, Tmin=323.15, Tmax=573.15)

def LLL_CCPsat_model(T):
      R = 8.314
      theta = 298.15
      ln10 = 2.30258509
      return (-91320000/(R*theta*ln10))+ ((169240000/R*ln10)*((1/theta) - (1/T)))
chems.LLL.Psat.add_method(f=LLL_CCPsat_model, Tmin=323.15, Tmax=573.15)

def OOL_CCPsat_model(T):
      R = 8.314
      theta = 298.15
      ln10 = 2.30258509
      return (-91320000/(R*theta*ln10))+ ((169240000/R*ln10)*((1/theta) - (1/T)))
chems.OOL.Psat.add_method(f=OOL_CCPsat_model, Tmin=323.15, Tmax=573.15)

def LLO_CCPsat_model(T):
      R = 8.314
      theta = 298.15
      ln10 = 2.30258509
      return (-91320000/(R*theta*ln10))+ ((169240000/R*ln10)*((1/theta) - (1/T)))
chems.LLO.Psat.add_method(f=LLO_CCPsat_model, Tmin=323.15, Tmax=573.15)

def SOO_CCPsat_model(T):
      R = 8.314
      theta = 298.15
      ln10 = 2.30258509
      return (-91320000/(R*theta*ln10))+ ((169240000/R*ln10)*((1/theta) - (1/T)))
chems.SOO.Psat.add_method(f=SOO_CCPsat_model, Tmin=323.15, Tmax=573.15)

def PLO_CCPsat_model(T):
      R = 8.314
      theta = 298.15
      ln10 = 2.30258509
      return (-89250000/(R*theta*ln10))+ ((166740000/R*ln10)*((1/theta) - (1/T)))
chems.PLO.Psat.add_method(f=PLO_CCPsat_model, Tmin=323.15, Tmax=573.15)

def PoOO_CCPsat_model(T):
      R = 8.314
      theta = 298.15
      ln10 = 2.30258509
      return (-89250000/(R*theta*ln10))+ ((166740000/R*ln10)*((1/theta) - (1/T)))
chems.PoOO.Psat.add_method(f=PoOO_CCPsat_model, Tmin=323.15, Tmax=573.15)

def POO_CCPsat_model(T):
      R = 8.314
      theta = 298.15
      ln10 = 2.30258509
      return (-89250000/(R*theta*ln10))+ ((166740000/R*ln10)*((1/theta) - (1/T)))
chems.POO.Psat.add_method(f=POO_CCPsat_model, Tmin=323.15, Tmax=573.15)

def POS_CCPsat_model(T):
      R = 8.314
      theta = 298.15
      ln10 = 2.30258509
      return (-89250000/(R*theta*ln10))+ ((166740000/R*ln10)*((1/theta) - (1/T)))
chems.POS.Psat.add_method(f=POS_CCPsat_model, Tmin=323.15, Tmax=573.15)

def POP_CCPsat_model(T):
      R = 8.314
      theta = 298.15
      ln10 = 2.30258509
      return (-87180000/(R*theta*ln10))+ ((164240000/R*ln10)*((1/theta) - (1/T)))
chems.POP.Psat.add_method(f=POP_CCPsat_model, Tmin=323.15, Tmax=573.15)

def PLS_CCPsat_model(T):
      R = 8.314
      theta = 298.15
      ln10 = 2.30258509
      return (-89250000/(R*theta*ln10))+ ((166740000/R*ln10)*((1/theta) - (1/T)))
chems.PLS.Psat.add_method(f=PLS_CCPsat_model, Tmin=323.15, Tmax=573.15)
###############################################################################################33
#The model returns values in J/mol.K
def OOO_Cnl_model(T):
      return (3*(397600 + 540.89*T) + (61355 + 148.23*T))*(1/1000)
# chems.OOO.Cn.l.add_method(f=OOO_Cnl_model, Tmin= 298.15, Tmax=453.15)
chems.LLL.Cn.add_method(f=OOO_Cnl_model, Tmin= 298.15, Tmax=453.15)
chems.LLO.Cn.add_method(f=OOO_Cnl_model, Tmin= 298.15, Tmax=453.15)
chems.OOL.Cn.add_method(f=OOO_Cnl_model, Tmin= 298.15, Tmax=453.15)

#The below Psat models return values in Pa (N/m)
def SOO_Cnl_model(T):
      return (2*(397600 + 540.89*T) + (366930 + 685.76*T)+ (61355 + 148.23*T))*(1/1000)
chems.SOO.Cn.add_method(f=SOO_Cnl_model,Tmin= 298.15, Tmax=453.15)

def PoOO_Cnl_model(T):
      return (2*(397600 + 540.89*T) +(330360 + 616.35*T) + (61355 + 148.23*T))*(1/1000)
chems.PoOO.Cn.add_method(f=PoOO_Cnl_model, Tmin= 298.15, Tmax=453.15)
chems.PLO.Cn.add_method(f=PoOO_Cnl_model, Tmin= 298.15, Tmax=453.15)
chems.POO.Cn.add_method(f=PoOO_Cnl_model, Tmin= 298.15, Tmax=453.15)

def POP_Cnl_model(T):
      return (1*(397600 + 540.89*T) +2*(330360 + 616.35*T) + (61355 + 148.23*T))*(1/1000)
chems.POP.Cn.add_method(f=POP_Cnl_model, Tmin= 298.15, Tmax=453.15)

def PLS_Cnl_model(T):
      return (1*(397600 + 540.89*T) +1*(330360 + 616.35*T) + 1*(366930 + 685.76*T) + (61355 + 148.23*T))*(1/1000)
chems.PLS.Cn.add_method(f=POP_Cnl_model, Tmin= 298.15, Tmax=453.15)
chems.POS.Cn.add_method(f=POP_Cnl_model, Tmin= 298.15, Tmax=453.15)
###############################################################################################33
#Adding the molar volumes
def OOO_Vl_model(T):
      return ((3*((1 + 0.0009865*T)/4.2924)) + ((1 + 20.048*T)/0.00076923))*(1/1000)
# chems.OOO.V.l.add_method(f=OOO_Vl_model, Tmin= 258.15, Tmax=516.15)
# TODO: check what methodP means ...in the V.l definition
def LLL_Vl_model(T):
      return ((3*((1 + 0.00074102*T)/4.1679)) + ((1 + 20.048*T)/0.00076923))*(1/1000)
chems.LLL.V.add_method(f=LLL_Vl_model, Tmin= 258.15, Tmax=516.15)
def OOL_Vl_model(T):
      return ((1*((1 + 0.00074102*T)/4.1679)) + (2*((1 + 0.0009865*T)/4.2924))+  ((1 + 20.048*T)/0.00076923))*(1/1000)
chems.OOL.V.add_method(f=OOL_Vl_model, Tmin= 258.15, Tmax=516.15)
def LLO_Vl_model(T):
      return ((2*((1 + 0.00074102*T)/4.1679)) + (1*((1 + 0.0009865*T)/4.2924))+  ((1 + 20.048*T)/0.00076923))*(1/1000)
chems.LLO.V.add_method(f=LLO_Vl_model, Tmin= 258.15, Tmax=516.15)
def SOO_Vl_model(T):
      return ((1*((1 + 0.0014091*T)/4.6326)) + (2*((1 + 0.0009865*T)/4.2924))+  ((1 + 20.048*T)/0.00076923))*(1/1000)
chems.SOO.V.add_method(f=SOO_Vl_model, Tmin= 258.15, Tmax=516.15)
def PLO_Vl_model(T):
      return ((1*((1 + 0.0013008*T)/5.0524))+ (1*((1 + 0.00074102*T)/4.1679)) + (1*((1 + 0.0009865*T)/4.2924)) + ((1 + 20.048*T)/0.00076923))*(1/1000)
chems.PLO.V.add_method(f=PLO_Vl_model, Tmin= 258.15, Tmax=516.15)
def PoOO_Vl_model(T):
      return ((1*((1 + 0.0013008*T)/5.0524))+ (2*((1 + 0.0009865*T)/4.2924)) + ((1 + 20.048*T)/0.00076923))*(1/1000)
chems.PoOO.V.add_method(f=PoOO_Vl_model, Tmin= 258.15, Tmax=516.15)
def POO_Vl_model(T):
      return ((1*((1 + 0.0013008*T)/5.0524))+ (2*((1 + 0.0009865*T)/4.2924)) + ((1 + 20.048*T)/0.00076923))*(1/1000)
chems.POO.V.add_method(f=POO_Vl_model, Tmin= 258.15, Tmax=516.15)
def POS_Vl_model(T):
      return ((1*((1 + 0.0013008*T)/5.0524))+ (1*((1 + 0.0009865*T)/4.2924)) +(1*((1 + 0.0014091*T)/4.6326))+ ((1 + 20.048*T)/0.00076923))*(1/1000)
chems.POS.V.add_method(f=POS_Vl_model, Tmin= 258.15, Tmax=516.15)
def POP_Vl_model(T):
      return ((2*((1 + 0.0013008*T)/5.0524))+ (1*((1 + 0.0009865*T)/4.2924)) + ((1 + 20.048*T)/0.00076923))*(1/1000)
chems.POP.V.add_method(f=POP_Vl_model, Tmin= 258.15, Tmax=516.15)
def PLS_Vl_model(T):
      return ((1*((1 + 0.0013008*T)/5.0524))+ (1*((1 + 0.00074102*T)/4.1679)) +(1*((1 + 0.0014091*T)/4.6326))+  ((1 + 20.048*T)/0.00076923))*(1/1000)
chems.PLS.V.add_method(f=PLS_Vl_model, Tmin= 258.15, Tmax=516.15)

#Adding viscosity for the unknown TAGS
#TODO: add viscosity
# [ 'LLL','OOL','LLO','SOO',
#         'PLO','PoOO','POO',
#          'POS','POP','PLS']

########Heat of formation ##########################################################################
#LiquidMethanol and Sodium_methoxide were added for cane biorefinery compatibility
LiquidMethanol = tmo.Chemical('Methanol').at_state(phase='l', copy=True)
chems.Sodium_methoxide.copy_models_from (LiquidMethanol,
                                            ['V', 'sigma',
                                              'kappa', 'Cn',
                                                'Psat','mu'])
#Properties of chemicals required by the boilerturbogenerator based on cane.chemicals.py
chems.Ash.Cn.add_model(0.09 * 4.184 * chems.Ash.MW)
for chemical in [chems.Ash,chems.P4O10]:
    V = fn.rho_to_V(rho=1540, MW=chemical.MW)
    chemical.V.add_model(V, top_priority=True)

#The below NaOH and HCl are based on the cane refinery chemicals.py module
def create_new_chemical(ID, phase='s', **constants):
        solid = tmo.Chemical.blank(ID, phase=phase, **constants)
        chems.append(solid)
        return solid

NaOH = create_new_chemical('NaOH', formula='NaOH')
HCl = create_new_chemical('HCl', formula='HCl')
# Solubles don't occupy much volume
for chemical in (HCl, NaOH,):
        V = fn.rho_to_V(rho=1e5, MW=chemical.MW)
        chemical.V.add_model(V, top_priority=True)
        chemical.default()
NaOH.copy_models_from(tmo.Chemical('NaOH'),['Psat'])
HCl.copy_models_from(tmo.Chemical('HCl'),['Psat'])

chems.Ash.copy_models_from(tmo.Chemical('Water'),['Psat'])
chems.P4O10.copy_models_from(tmo.Chemical('Water'),['Psat'])
chems.WWTsludge.copy_models_from(tmo.Chemical('Water'),['Psat'])

for chemical in chems: chemical.default()
#TODO: add viscosity for all the catalyst related chems

chems.compile()
chems.define_group('TAG', ('OOO','LLL','OOL',
                           'LLO','SOO','PLO',
                           'PoOO','POO','POS',
                           'POP','PLS'))

chems.define_group('Lipid', ('OOO','LLL','OOL',
                           'LLO','SOO','PLO',
                           'PoOO','POO','POS',
                           'POP','PLS'))
chems.define_group('Oil', ('OOO','LLL','OOL',
                           'LLO','SOO','PLO',
                           'PoOO','POO','POS',
                           'POP','PLS'))

chems.define_group('Biodiesel', ('Methyl_oleate',
                                 'Methyl_palmitate',
                                 'Methyl_stearate',
                                 'Methyl_linoleate',
                                 'Methyl_palmitoleate'))

#composition of VM_Naphtha based on https://www.cdc.gov/niosh/npg/npgd0664.html#:~:text=None%20reported%20%5BNote%3A%20VM%26P%20Naphtha%20is%20a%20refined,Exposure%20Routes%20inhalation%2C%20ingestion%2C%20skin%20and%2For%20eye%20contact
chems.define_group('VM_Naphtha',['Octane',
                                 'Cycloheptane',
                                 'Bicyclo_octane',
                                 'Toluene'],
                                 composition = [0.55,
                                                0.30,
                                                0.02,
                                                0.12])
chems.define_group('COSOxNOxH2S',['NO', 'NO2',
                                  'SO2','CO', 'H2S'])

chems.define_group('Air', ['Oxygen', 'Nitrogen'],composition=[0.21,0.79])
chems.set_synonym('Water', 'H2O')
chems.set_synonym('Carbon_dioxide','CO2')
chems.set_synonym('Phosphatidylinositol','PL')
chems.set_synonym('MonoOlein', 'MAG')
chems.set_synonym('Dipalmitin', 'DAG')
chems.set_synonym('Hydrogen_ion', 'H+')
chems.set_synonym('Pelargonic_acid','Nonanoic_acid')
chems.set_synonym('HCl2','Liquid_HCl')
# chems.set_synonym('Calcium_dihydroxide', 'Lime')
chems.set_synonym('CaSO4', 'Gypsum')
# chems.set_synonyn('WWTs_sludge','Biomass')
# chems.show()

# Reference for below: Fragment-Based Approach for Estimating Thermophysical Properties of Fats and
# Vegetable Oils for Modeling Biodiesel Production Processes
#Dict for gibbs free energies
# {GOOO : 91320000,GLLL : 91320000,
#  GOOL : 91320000,GLLO : 91320000,
#  GSOO : 91320000,GPLO : 89250000,
#  GPoOO : 89250000,GPOO : 89250000,
#  GPOS : 89250000,GPOP : 87180000,
#  GPLS : 89250000}
#Dict for enthalpy of vapourisation
# {HOOO : 169240000,HLLL : 169240000,
#  HOOL : 169240000,HLLO : 169240000,
#  HSOO : 169240000,HPLO : 166740000,
#  HPoOO :166740000,HPOO : 166740000,
#  HPOS : 166740000,HPOP : 164240000,
#  HPLS : 166740000}
#Hf_formation_(OOO):-76.494*18 - 815.18
#Hf_formation_(PPP):- -59.571*16 - 1358.7
#Hf_formation_(PoPoPo):- -76.494*16 - 815.18
#Hf_formation_(SSS):- -59.571*18 - 1358.7
#Hf_formation_(LLL):-  -316.67*2 - 2466.4
#Hf_formation_(LnLnLn):-  -316.67*3 - 2466.4