#
# Author: John Tran <jhtran@att.com>
#         Julien Danjou <julien@danjou.info>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Tests for ceilometer/storage/impl_sqlalchemy.py

.. note::
  In order to run the tests against real SQL server set the environment
  variable CEILOMETER_TEST_SQL_URL to point to a SQL server before running
  the tests.

"""

import datetime
import repr

import mock
from oslo.utils import timeutils

from ceilometer.alarm.storage import impl_sqlalchemy as impl_sqla_alarm
from ceilometer.storage import impl_sqlalchemy
from ceilometer.storage import models
from ceilometer.storage.sqlalchemy import models as sql_models
from ceilometer.tests import base as test_base
from ceilometer.tests import db as tests_db
from ceilometer.tests.storage import test_storage_scenarios as scenarios

@tests_db.run_with('sqlite')
class CeilometerBaseTest(tests_db.TestBase):

    def test_ceilometer_base(self):
        base = sql_models.CeilometerBase()
        base['key'] = 'value'
        self.assertEqual('value', base['key'])

@tests_db.run_with('sqlite')
class TraitTypeTest(tests_db.TestBase):
    # TraitType is a construct specific to sqlalchemy.
    # Not applicable to other drivers.

    def test_trait_type_exists(self):
        tt1 = self.conn._get_or_create_trait_type("foo", 0)
        self.assertTrue(tt1.id >= 0)
        tt2 = self.conn._get_or_create_trait_type("foo", 0)
        self.assertEqual(tt2.id, tt1.id)
        self.assertEqual(tt2.desc, tt1.desc)
        self.assertEqual(tt2.data_type, tt1.data_type)

    def test_new_trait_type(self):
        tt1 = self.conn._get_or_create_trait_type("foo", 0)
        self.assertTrue(tt1.id >= 0)
        tt2 = self.conn._get_or_create_trait_type("blah", 0)
        self.assertNotEqual(tt1.id, tt2.id)
        self.assertNotEqual(tt1.desc, tt2.desc)
        # Test the method __repr__ returns a string
        self.assertTrue(repr.repr(tt2))

    def test_trait_different_data_type(self):
        tt1 = self.conn._get_or_create_trait_type("foo", 0)
        self.assertTrue(tt1.id >= 0)
        tt2 = self.conn._get_or_create_trait_type("foo", 1)
        self.assertNotEqual(tt1.id, tt2.id)
        self.assertEqual(tt2.desc, tt1.desc)
        self.assertNotEqual(tt1.data_type, tt2.data_type)
        # Test the method __repr__ returns a string
        self.assertTrue(repr.repr(tt2))

@tests_db.run_with('sqlite')
class EventTypeTest(tests_db.TestBase):
    # EventType is a construct specific to sqlalchemy
    # Not applicable to other drivers.

    def test_event_type_exists(self):
        et1 = self.conn._get_or_create_event_type("foo")
        self.assertTrue(et1.id >= 0)
        et2 = self.conn._get_or_create_event_type("foo")
        self.assertEqual(et2.id, et1.id)
        self.assertEqual(et2.desc, et1.desc)

    def test_event_type_unique(self):
        et1 = self.conn._get_or_create_event_type("foo")
        self.assertTrue(et1.id >= 0)
        et2 = self.conn._get_or_create_event_type("blah")
        self.assertNotEqual(et1.id, et2.id)
        self.assertNotEqual(et1.desc, et2.desc)
        # Test the method __repr__ returns a string
        self.assertTrue(repr.repr(et2))

class MyException(Exception):
    pass

@tests_db.run_with('sqlite')
class EventTest(tests_db.TestBase):
    def test_string_traits(self):
        model = models.Trait("Foo", models.Trait.TEXT_TYPE, "my_text")
        trait = self.conn._make_trait(model, None)
        self.assertEqual(models.Trait.TEXT_TYPE, trait.trait_type.data_type)
        self.assertIsNone(trait.t_float)
        self.assertIsNone(trait.t_int)
        self.assertIsNone(trait.t_datetime)
        self.assertEqual("my_text", trait.t_string)
        self.assertIsNotNone(trait.trait_type.desc)

    def test_int_traits(self):
        model = models.Trait("Foo", models.Trait.INT_TYPE, 100)
        trait = self.conn._make_trait(model, None)
        self.assertEqual(models.Trait.INT_TYPE, trait.trait_type.data_type)
        self.assertIsNone(trait.t_float)
        self.assertIsNone(trait.t_string)
        self.assertIsNone(trait.t_datetime)
        self.assertEqual(100, trait.t_int)
        self.assertIsNotNone(trait.trait_type.desc)

    def test_float_traits(self):
        model = models.Trait("Foo", models.Trait.FLOAT_TYPE, 123.456)
        trait = self.conn._make_trait(model, None)
        self.assertEqual(models.Trait.FLOAT_TYPE, trait.trait_type.data_type)
        self.assertIsNone(trait.t_int)
        self.assertIsNone(trait.t_string)
        self.assertIsNone(trait.t_datetime)
        self.assertEqual(123.456, trait.t_float)
        self.assertIsNotNone(trait.trait_type.desc)

    def test_datetime_traits(self):
        now = datetime.datetime.utcnow()
        model = models.Trait("Foo", models.Trait.DATETIME_TYPE, now)
        trait = self.conn._make_trait(model, None)
        self.assertEqual(models.Trait.DATETIME_TYPE,
                         trait.trait_type.data_type)
        self.assertIsNone(trait.t_int)
        self.assertIsNone(trait.t_string)
        self.assertIsNone(trait.t_float)
        self.assertEqual(now, trait.t_datetime)
        self.assertIsNotNone(trait.trait_type.desc)

    def test_bad_event(self):
        now = datetime.datetime.utcnow()
        m = [models.Event("1", "Foo", now, []),
             models.Event("2", "Zoo", now, [])]

        with mock.patch.object(self.conn, "_record_event") as mock_save:
            mock_save.side_effect = MyException("Boom")
            problem_events = self.conn.record_events(m)
        self.assertEqual(2, len(problem_events))
        for bad, event in problem_events:
            self.assertEqual(bad, models.Event.UNKNOWN_PROBLEM)

    def test_get_none_value_traits(self):
        model = sql_models.Trait(None, None, 5)
        self.assertIsNone(model.get_value())
        self.assertTrue(repr.repr(model))

    def test_event_repr(self):
        ev = sql_models.Event('msg_id', None, False)
        ev.id = 100
        self.assertTrue(repr.repr(ev))

@tests_db.run_with('sqlite')
class RelationshipTest(scenarios.DBTestBase):
    # Note: Do not derive from SQLAlchemyEngineTestBase, since we
    # don't want to automatically inherit all the Meter setup.

    @mock.patch.object(timeutils, 'utcnow')
    def test_clear_metering_data_meta_tables(self, mock_utcnow):
        mock_utcnow.return_value = datetime.datetime(2012, 7, 2, 10, 45)
        self.conn.clear_expired_metering_data(3 * 60)

        session = self.conn._engine_facade.get_session()
        meta_tables = [sql_models.MetaText, sql_models.MetaFloat,
                       sql_models.MetaBigInt, sql_models.MetaBool]
        for table in meta_tables:
            self.assertEqual(0, (session.query(table)
                                 .filter(~table.id.in_(
                                     session.query(sql_models.Sample.id)
                                     .group_by(sql_models.Sample.id))).count()
                                 ))

class CapabilitiesTest(test_base.BaseTestCase):
    # Check the returned capabilities list, which is specific to each DB
    # driver

    def test_capabilities(self):
        expected_capabilities = {
            'meters': {'pagination': False,
                       'query': {'simple': True,
                                 'metadata': True,
                                 'complex': False}},
            'resources': {'pagination': False,
                          'query': {'simple': True,
                                    'metadata': True,
                                    'complex': False}},
            'samples': {'pagination': True,
                        'groupby': True,
                        'query': {'simple': True,
                                  'metadata': True,
                                  'complex': True}},
            'statistics': {'pagination': False,
                           'groupby': True,
                           'query': {'simple': True,
                                     'metadata': True,
                                     'complex': False},
                           'aggregation': {'standard': True,
                                           'selectable': {
                                               'max': True,
                                               'min': True,
                                               'sum': True,
                                               'avg': True,
                                               'count': True,
                                               'stddev': True,
                                               'cardinality': True}}
                           },
            'events': {'query': {'simple': True}}
        }

        actual_capabilities = impl_sqlalchemy.Connection.get_capabilities()
        self.assertEqual(expected_capabilities, actual_capabilities)

    def test_alarm_capabilities(self):
        expected_capabilities = {
            'alarms': {'query': {'simple': True,
                                 'complex': True},
                       'history': {'query': {'simple': True,
                                             'complex': True}}},
        }

        actual_capabilities = impl_sqla_alarm.Connection.get_capabilities()
        self.assertEqual(expected_capabilities, actual_capabilities)

    def test_storage_capabilities(self):
        expected_capabilities = {
            'storage': {'production_ready': True},
        }
        actual_capabilities = (impl_sqlalchemy.
                               Connection.get_storage_capabilities())
        self.assertEqual(expected_capabilities, actual_capabilities)


import wave
import matplotlib.pyplot as plt
import numpy as np

if __name__ == "__main__":
    obj = wave.open("files/output.wav", "rb")

    frame_rate = obj.getframerate()
    n_frames = obj.getnframes()
    signal_wave = obj.readframes(-1)

    obj.close()

    duration = n_frames / frame_rate
    signal_array = np.frombuffer(signal_wave, dtype=np.int16)
    times = np.linspace(0, duration, num=n_frames)

    plt.figure(figsize=(15, 5))
    plt.plot(times, signal_array)
    plt.title("Audio signal")
    plt.ylabel("Signal Wave")
    plt.xlabel("Time (s)")
    plt.xlim(0, duration)
    plt.show()


from collections import deque

from Algorithms.Trees.base import BinaryTreeNode, create_bst

class InorderIterator:
    def __init__(self, root):
        self.q = deque()
        self.collect_queue(root)

    def collect_queue(self, root: BinaryTreeNode):
        tmp = root
        while tmp:
            self.q.append(tmp)
            tmp = tmp.left

    # hasNext - given name
    def hasNext(self):
        if self.q:
            return True

    # getNext - given name
    def getNext(self):
        el = self.q.pop()
        self.collect_queue(el.right)
        return el

def inorder_using_iterator(root):
    inorder_iter = InorderIterator(root)
    result = ""
    while inorder_iter.hasNext():
        ptr = inorder_iter.getNext()
        result += str(ptr.data) + " "
    return result

arr = [25, 125, 200, 300, 75, 50, 12, 35, 60, 75]
root = create_bst(arr)
print("Inorder Iterator = ", end="")
print(inorder_using_iterator(root))


import torch
import torch.nn as nn
import json
from config.base_config import cfg
import torch.nn.functional as F
from model.adapter import Adapter
class baseNet(nn.Module):
    def __init__(self, vocab_size, pretrained_emb=None):
        super(baseNet, self).__init__()
        self.vocab_size = vocab_size

        self.embedding = nn.Embedding(
            num_embeddings=vocab_size,
            embedding_dim=cfg.WORD_EMB_SIZE
        )
        self.input_dropout = nn.Dropout(0.1)
        self.mlp = nn.Sequential(nn.Linear(cfg.WORD_EMB_SIZE, cfg.WORD_EMB_SIZE),
                                 nn.ReLU())
        # Loading the GloVe embedding weights
        # if cfg.USE_GLOVE:
        #     self.embedding.weight.data.copy_(torch.from_numpy(pretrained_emb))

        self.adapter=Adapter()

        self.lstm = nn.LSTM(
            input_size=cfg.WORD_EMB_SIZE,
            hidden_size=cfg.HIDDEN_SIZE,
            num_layers=1,
            batch_first=True
        )

        self.fuse_proj=nn.Linear(3072,cfg.HIDDEN_SIZE)
        self.conf_proj = nn.Linear(cfg.HIDDEN_SIZE , 1)
        self.bbox_proj = nn.Linear(cfg.HIDDEN_SIZE , 4)

    def forward(self,*inputs):

        qvec, img_feat, spt_feat = inputs
        # input_lengths = (qvec != 0).sum(1)

        lang_feat = self.embedding(qvec)
        lang_feat=self.input_dropout(lang_feat)
        lang_feat=self.mlp(lang_feat)
        lang_feat, (h_n, c_n) = self.lstm(lang_feat)
        # print(qvec)

        lang_pooled=h_n[-1]
        # L2 Normalize
        lang_feat = F.normalize(input=lang_pooled,dim=-1, p=2)  # perform Lp normalization of inputs over specified dimension,这里p=2
        img_feat= F.normalize(input=img_feat,dim=-1, p=2)

        # vis_feat,vis_mask=self.adapter(img_feat,spt_feat)

        #fusion
        lang_feat=lang_feat.unsqueeze(1).repeat(1,img_feat.size(1),1)
        fuse_feat=torch.cat([lang_feat,img_feat],-1)
        fuse_feat=F.relu(self.fuse_proj(fuse_feat))

        # # predict confidence
        query_score_pred = self.conf_proj(fuse_feat).view(-1, cfg.RPN_TOPN)

        # # predict bbox
        query_bbox_pred = self.bbox_proj(fuse_feat)

        return query_score_pred, query_bbox_pred


""""
This file will do the API call to get the image URL from the city as argument

"""

import json
import requests

image_ext = ['jpg', 'png']
def getcities():
    url = "https://api.teleport.org/api/urban_areas/"
    response = requests.get(url)
    response.raise_for_status()
    data = json.loads(response.text)

    cityData = data["_links"]["ua:item"]
    file = open("data.txt", "w")
    for i in cityData:
        file.write(i['name'] + " ")
    file.close()


"""
Sequential Child-Combination Tree-LSTM Network for PolEval 2017 evaluation campaign
Implementation inspired by "Efficient recursive (tree-structured) neural networks in TensorFlow" available at https://github.com/erickrf/treernn
"""

import sys

import numpy as np
import tensorflow as tf

import data

CHILDREN_NB = 5

word2idx, train_data, test_data = data.parse()

embed_size = 16
label_size = 3
max_epochs = 3
lr = 0.01

with tf.variable_scope('embed'):
    embeddings = tf.get_variable('embeddings', [len(word2idx), embed_size])

with tf.variable_scope('lstm'):
    W_i = tf.get_variable('W_i', [2 * embed_size, embed_size])
    W_f = tf.get_variable('W_f', [2 * embed_size, embed_size])
    W_o = tf.get_variable('W_o', [2 * embed_size, embed_size])
    W_g = tf.get_variable('W_g', [2 * embed_size, embed_size])
    c = tf.get_variable('c', [embed_size])

with tf.variable_scope('output'):
    V = tf.get_variable('V', [embed_size, label_size])
    bs = tf.get_variable('bs', [1, label_size])

children_placeholders = [tf.placeholder(tf.int32, (None), name='children_' + str(j) + '_placeholder') for j in range(CHILDREN_NB)]
node_word_indices_placeholder = tf.placeholder(tf.int32, (None), name='node_word_indices_placeholder')
y = tf.placeholder(tf.int32, (None), name='y')

def tree_lstm():

    tensor_array = tf.TensorArray(
        tf.float32,
        size=0,
        dynamic_size=True,
        clear_after_read=False,
        infer_shape=False)

    def embed_word(word_index):
        return tf.expand_dims(tf.gather(embeddings, word_index), 0)

    def lstm(x, state):
        i = tf.nn.sigmoid(tf.matmul(tf.concat([x, state], 1), W_i))
        f = tf.nn.sigmoid(tf.matmul(tf.concat([x, state], 1), W_f))
        o = tf.nn.sigmoid(tf.matmul(tf.concat([x, state], 1), W_o))
        g = tf.nn.tanh(tf.matmul(tf.concat([x, state], 1), W_g))
        new_c = c * f + g * i
        tf.assign(c, tf.squeeze(new_c))
        r = tf.nn.tanh(new_c) * o
        return r

    def loop_body(tensor_array, i):
        node_word_index = tf.gather(node_word_indices_placeholder, i)
        children = [tf.gather(children_placeholders[j], i) for j in range(CHILDREN_NB)]
        node_tensor = embed_word(node_word_index)

        for child in children:
            node_tensor = tf.cond(child > -1,
                                  lambda: lstm(node_tensor, tensor_array.read(child)),
                                  lambda: node_tensor)
        tensor_array = tensor_array.write(i, node_tensor)
        i = tf.add(i, 1)
        return tensor_array, i

    loop_cond = lambda tensor_array, i: \
        tf.less(i, tf.squeeze(tf.shape(node_word_indices_placeholder)))
    tensor_array, _ = tf.while_loop(
        loop_cond, loop_body, [tensor_array, 0], parallel_iterations=1)

    logits = tf.matmul(tensor_array.concat(), V) + bs

    return logits

logits = tree_lstm()
prediction = tf.argmax(logits, 1)
loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=y)
train_op = tf.train.AdamOptimizer(lr).minimize(loss)

def build_feed_dict(node):

    tree, labels, words, _ = node

    nodes_list = []
    data.left_traverse(-1, tree, nodes_list)
    nodes_list.pop(-1)

    feed_dict = {
        node_word_indices_placeholder: [words[node] for node in nodes_list],
        y: [labels[node] for node in nodes_list],
    }
    for j in range(CHILDREN_NB):
        feed_dict[children_placeholders[j]] = [tree[node][j] if len(tree[node]) > j else -1 for node in nodes_list]
    for j in range(CHILDREN_NB):
        feed_dict[children_placeholders[j]] = [nodes_list.index(f) if f > -1 else -1 for f in feed_dict[children_placeholders[j]]]

    return feed_dict

def predict(sess, data):

    y_pred = []
    y_true = []

    for step, t in enumerate(data):
        feed_dict = build_feed_dict(t)
        pred, y_i = sess.run([prediction, y], feed_dict=feed_dict)
        y_pred.append(pred)
        y_true.append(y_i)

    list_flatten = lambda l: [item for sublist in l for item in sublist]

    y_pred = list_flatten(y_pred)
    y_true = list_flatten(y_true)

    acc = np.equal(y_true, y_pred).mean()

    return acc

with tf.Session() as sess:
    saver = tf.train.Saver()
    sess.run(tf.initialize_all_variables())

    for epoch in range(1, max_epochs + 1):
        print('\n\nepoch {}'.format(epoch))

        for step, t in enumerate(train_data):
            feed_dict = build_feed_dict(t)
            sess.run([train_op], feed_dict=feed_dict)
            sys.stdout.write('\r{} / {}'.format(step, len(train_data)))
            sys.stdout.flush()

        acc = predict(sess, train_data)
        sys.stdout.write('\r{} / {}\ttrain acc: {}'.format(step, len(train_data), acc))
        sys.stdout.flush()

    saver.save(sess, 'models/model')

    saver.restore(sess, 'models/model')
    acc = predict(sess, test_data)
    sys.stdout.write('\n\ntest acc: {}'.format(acc))# test


#improting all the required packages
import logging
import csv
import os
import numpy as np
import pandas as pd
import luigi
from download_loan_data import Download_loan_data
import warnings
warnings.filterwarnings('ignore')

#function to generate the loggs
def getLogger(dir):
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    handler = logging.FileHandler(dir)
    handler.setLevel(logging.INFO)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    return logger

#function to check is directory exists
def funCheckDir(filepath):
    directory = os.path.dirname(filepath) # defining directory path
    if not os.path.exists(directory): # checking if directory already exists
        os.makedirs(directory) # making a directory
        return False
    else :
        try:
            os.remove(filepath)
        except OSError:
            pass
        return True

#function to write the data in chunks
def chunker(seq, size):
    return (seq[pos:pos + size] for pos in range(0, len(seq), size))

def funConsolidateLoanData(loanDataCSVPath):

    #reading data from CSV
    df = pd.read_csv(loanDataCSVPath, skiprows=1)

    #return data frame
    return df

def funCleanNFillMissingLoanData(df):

    #removing string 'months' from term and convertinng into int
    df['term'] = (df['term'].str.extract('(\d+)')).astype(int)

    #extracting number from emp_length and convertinng into int
    df['emp_length'] = df['emp_length'].str.extract('(\d+)')
    df['emp_length'] = df['emp_length'].fillna(0).astype(int)

    #removing '%' from int_rate and converting into float
    df['int_rate'] = df['int_rate'].apply(lambda x: float(x.rstrip("%")))

    #removing '%' from int_rate and converting into float
    df['revol_util'] = df['revol_util'].astype(str)
    df['revol_util'] = df['revol_util'].apply(lambda x: float(x.rstrip("%")))

    #deriving a column cr_line_history, to show how old is credit history
    df['earliest_cr_line'] = df['earliest_cr_line'].fillna(df['issue_d'])

    df['earliest_cr_line'] = df['earliest_cr_line'].str.split('-')
    df['cr_line_month'] = df['earliest_cr_line'].str[0]
    df['cr_line_year'] = (df['earliest_cr_line'].str[1]).astype(int)
    del df['earliest_cr_line']

    #deriving issue_month and issue_year from the issue_d column
    df['issue_d'] = df['issue_d'].str.split('-')
    df['issue_month'] = df['issue_d'].str[0]
    df['issue_year'] = (df['issue_d'].str[1]).astype(int)
    del df['issue_d']

    #filling NaN with 'Unknown'
    df['title'] = df['title'].fillna('Unknown')

    #filling NaN with 0
    df['delinq_2yrs'] = df['delinq_2yrs'].fillna(0)
    df['inq_last_6mths'] = df['inq_last_6mths'].fillna(0)

    #filling NaN with mode
    df['open_acc'] = df['open_acc'].fillna(df['open_acc'].mode())
    df['pub_rec'] = df['pub_rec'].fillna(df['pub_rec'].mode())
    df['total_acc'] = df['total_acc'].fillna(df['total_acc'].mode())
    df['collections_12_mths_ex_med'] = df['collections_12_mths_ex_med'].fillna(df['collections_12_mths_ex_med'].mode())
    df['acc_now_delinq'] = df['acc_now_delinq'].fillna(df['acc_now_delinq'].mode())
    df['tot_coll_amt'] = df['tot_coll_amt'].fillna(df['tot_coll_amt'].mode())
    df['tot_cur_bal'] = df['tot_cur_bal'].fillna(df['tot_cur_bal'].mode())
    df['total_rev_hi_lim'] = df['total_rev_hi_lim'].fillna(df['total_rev_hi_lim'].mode())
    df['acc_open_past_24mths'] = df['acc_open_past_24mths'].fillna(df['acc_open_past_24mths'].mode())
    df['avg_cur_bal'] = df['avg_cur_bal'].fillna(df['avg_cur_bal'].mode())
    df['bc_open_to_buy'] = df['bc_open_to_buy'].fillna(df['bc_open_to_buy'].mode())
    df['bc_util'] = df['bc_util'].fillna(df['bc_util'].mode())
    df['chargeoff_within_12_mths'] = df['chargeoff_within_12_mths'].fillna(df['chargeoff_within_12_mths'].mode())
    df['delinq_amnt'] = df['delinq_amnt'].fillna(df['delinq_amnt'].mode())
    df['mo_sin_old_il_acct'] = df['mo_sin_old_il_acct'].fillna(df['mo_sin_old_il_acct'].mode())
    df['mo_sin_old_rev_tl_op'] = df['mo_sin_old_rev_tl_op'].fillna(df['mo_sin_old_rev_tl_op'].mode())
    df['mo_sin_rcnt_rev_tl_op'] = df['mo_sin_rcnt_rev_tl_op'].fillna(df['mo_sin_rcnt_rev_tl_op'].mode())
    df['mo_sin_rcnt_tl'] = df['mo_sin_rcnt_tl'].fillna(df['mo_sin_rcnt_tl'].mode())
    df['mort_acc'] = df['mort_acc'].fillna(df['mort_acc'].mode())
    df['mths_since_recent_bc'] = df['mths_since_recent_bc'].fillna(df['mths_since_recent_bc'].mode())
    df['num_accts_ever_120_pd'] = df['num_accts_ever_120_pd'].fillna(df['num_accts_ever_120_pd'].mode())
    df['num_actv_bc_tl'] = df['num_actv_bc_tl'].fillna(df['num_actv_bc_tl'].mode())
    df['num_actv_rev_tl'] = df['num_actv_rev_tl'].fillna(df['num_actv_rev_tl'].mode())
    df['num_bc_sats'] = df['num_bc_sats'].fillna(df['num_bc_sats'].mode())
    df['num_bc_tl'] = df['num_bc_tl'].fillna(df['num_bc_tl'].mode())
    df['num_op_rev_tl'] = df['num_op_rev_tl'].fillna(df['num_op_rev_tl'].mode())
    df['num_rev_accts'] = df['num_rev_accts'].fillna(df['num_rev_accts'].mode())
    df['num_rev_tl_bal_gt_0'] = df['num_rev_tl_bal_gt_0'].fillna(df['num_rev_tl_bal_gt_0'].mode())
    df['num_sats'] = df['num_sats'].fillna(df['num_sats'].mode())
    df['num_tl_120dpd_2m'] = df['num_tl_120dpd_2m'].fillna(df['num_tl_120dpd_2m'].mode())
    df['num_tl_30dpd'] = df['num_tl_30dpd'].fillna(df['num_tl_30dpd'].mode())
    df['num_tl_90g_dpd_24m'] = df['num_tl_90g_dpd_24m'].fillna(df['num_tl_90g_dpd_24m'].mode())
    df['num_tl_op_past_12m'] = df['num_tl_op_past_12m'].fillna(df['num_tl_op_past_12m'].mode())
    df['pct_tl_nvr_dlq'] = df['pct_tl_nvr_dlq'].fillna(df['pct_tl_nvr_dlq'].mode())
    df['percent_bc_gt_75'] = df['percent_bc_gt_75'].fillna(df['percent_bc_gt_75'].mode())
    df['pub_rec_bankruptcies'] = df['pub_rec_bankruptcies'].fillna(df['pub_rec_bankruptcies'].mode())
    df['tax_liens'] = df['tax_liens'].fillna(df['tax_liens'].mode())
    df['tot_hi_cred_lim'] = df['tot_hi_cred_lim'].fillna(df['tot_hi_cred_lim'].mode())
    df['total_bal_ex_mort'] = df['total_bal_ex_mort'].fillna(df['total_bal_ex_mort'].mode())
    df['total_bc_limit'] = df['total_bc_limit'].fillna(df['total_bc_limit'].mode())
    df['total_il_high_credit_limit'] = df['total_il_high_credit_limit'].fillna(df['total_il_high_credit_limit'].mode())

    #filling NaN with mean
    df['annual_inc'] = df['annual_inc'].fillna(df['annual_inc'].mean())

    df['cr_line_history'] = df['issue_year'] - df['cr_line_year']

    df['fico_range_avg'] = (df[['fico_range_high', 'fico_range_low']].mean(axis=1)).round()

    df['last_fico_avg'] = (df[['last_fico_range_high', 'last_fico_range_low']].mean(axis=1)).round()
    df['last_fico_avg'].fillna(df['fico_range_avg'], inplace=True)
    df['last_fico_avg'] = np.where(df['last_fico_avg'] == 0, df['fico_range_avg'], df['last_fico_avg'])

    #return data frame
    return df

#function to categorize the columns
def funCategorizeLoanData(df):

    #'bad' loan_status
    bad_loan_status_indicators = ["Charged Off",
                    "Default",
                    "Does not meet the credit policy. Status:Charged Off",
                    "In Grace Period",
                    "Default Receiver",
                    "Late (16-30 days)",
                    "Late (31-120 days)"]
    #creating a binary column for the bad Loan Status
    df['loan_status_binary'] = np.where(df['loan_status'].isin(bad_loan_status_indicators) , 0, 1)

    #'bad' home_ownership
    bad_home_ownership_indicators = ["RENT",
                    "NONE",
                    "OTHER",
                    "ANY"]

    #creating a binary column for the bad Loan Status
    df['home_ownership_binary'] = np.where(df['home_ownership'].isin(bad_home_ownership_indicators) , 0, 1)

    #assuming 'Verified' and 'Verified Source' means the same
    df['verification_status_binary'] = np.where(df['verification_status'] == 'Not Verified' , 0, 1)

    #converting to category
    df['application_type_binary'] = (df['application_type']).astype('category')

    #creating bins based on quantiles and converting to category
    df['loan_amnt_category'] = (pd.qcut(df['loan_amnt'], 10)).astype(str)
    df['loan_amnt_category_code'] = (pd.qcut(df['loan_amnt'], 10)).astype('category')
    df['loan_amnt_category'] = df['loan_amnt_category'].map(lambda x: x.lstrip('(').rstrip(']').lstrip('['))
    df['loan_amnt_category'] = df['loan_amnt_category'].str.split(',')
    df['loan_amnt_From'] = (df['loan_amnt_category'].str[0])
    df['loan_amnt_To'] = ((df['loan_amnt_category'].str[1]).map(lambda x: x.strip()))
    del df['loan_amnt_category']

    df['annual_inc_category'] = (pd.qcut(df['annual_inc'], 10)).astype(str)
    df['annual_inc_category_code'] = (pd.qcut(df['annual_inc'], 10)).astype('category')
    df['annual_inc_category'] = df['annual_inc_category'].map(lambda x: x.lstrip('(').rstrip(']').lstrip('['))
    df['annual_inc_category'] = df['annual_inc_category'].str.split(',')
    df['annual_inc_From'] = (df['annual_inc_category'].str[0])
    df['annual_inc_To'] = ((df['annual_inc_category'].str[1]).map(lambda x: x.strip()))
    del df['annual_inc_category']

    bins = [0,299,508,527,545,563,581,599,617,635,654,672,690,708,726,744,762,780,799,817,835,850]
    groupNames = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20']
    df['Credit_Score_Code'] = pd.cut(pd.to_numeric(df['fico_range_avg'], errors='coerce'), bins, labels=groupNames)
    df['Credit_Score_Code'] = (df['Credit_Score_Code']).astype(int)
    df['Credit_Score_Category'] = pd.cut(pd.to_numeric(df['fico_range_avg'], errors='coerce'), bins)
    df['Credit_Score_Category'] = (df['Credit_Score_Category']).astype(str)
    df['Credit_Score_Category'] = df['Credit_Score_Category'].map(lambda x: x.lstrip('(').rstrip(']'))
    df['Credit_Score_Category'] = df['Credit_Score_Category'].str.split(',')
    df['Credit_Score_From'] = (df['Credit_Score_Category'].str[0]).astype(int)
    df['Credit_Score_To'] = ((df['Credit_Score_Category'].str[1]).map(lambda x: x.strip())).astype(int)
    del df['Credit_Score_Category']

    df['Last_Credit_Score_Code'] = pd.cut(pd.to_numeric(df['last_fico_avg'], errors='coerce'), bins, labels=groupNames)
    df['Last_Credit_Score_Code'] = (df['Last_Credit_Score_Code']).astype(int)

    #converting all the category columns to int by taking category-code
    cat_columns = df.select_dtypes(['category']).columns
    df[cat_columns] = df[cat_columns].apply(lambda x: x.cat.codes)

    #return data frame
    return df

#function to perform aggregations
def main():
    #defining the file-directory
    fileDir = os.path.dirname(os.path.realpath('__file__'))

    #Logging started
    logFilePath = fileDir+'/Logs/missing_data_analysis.log'
    funCheckDir(logFilePath)
    logger = getLogger(logFilePath)
    logger.info("Application started....")

    #cleaning and filling missing loan data started
    loanFilePath = fileDir+'/CleanedData/LoanData.csv'
    funCheckDir(loanFilePath)
    logger.info("Cleaning and filling missing loan data started")

    #defining data frame for the consolidated loan data
    dfLoanData = pd.DataFrame()

    #reading loan data stats
    for directory, subdirectory, filenames in  os.walk(fileDir + '/Downloads/LoanData/'):
        for filename in filenames:
            if filename == 'LoanStats3a_securev1.csv':
                logger.info("Working on file: " + filename + '....')
                # print("Working on file: " + filename + '....')
                df = funConsolidateLoanData(os.path.join(directory, filename))

                df.drop(['zip_code'], axis = 1, inplace = True)
                df.drop(['url'], axis = 1, inplace = True)
                df.drop(['desc'], axis = 1, inplace = True)
                df.drop(['emp_title'], axis = 1, inplace = True)

                idx = df[df['id'] == 'Loans that do not meet the credit policy'].index
                df = df[:39786]

                df.dropna(how = 'all', inplace = True)
                df.dropna(thresh = 2, inplace = True)

                dfLoanData =  pd.concat([df, dfLoanData], ignore_index=True)
            else:
                logger.info("Working on file: " + filename + '....')
                # print("Working on file: " + filename + '....')
                df = funConsolidateLoanData(os.path.join(directory, filename))
                df.drop(['zip_code'], axis = 1, inplace = True)
                df.drop(['url'], axis = 1, inplace = True)
                df.drop(['desc'], axis = 1, inplace = True)
                df.drop(['emp_title'], axis = 1, inplace = True)

                df.dropna(how = 'all', inplace = True)
                df.dropna(thresh = 2, inplace = True)
                dfLoanData =  pd.concat([df, dfLoanData], ignore_index=True)

    #dropping columns having more than 10% of rows as NaN
    logger.info("Dropping columns having more than '10%' of rows as NaN")
    dfLoanData = dfLoanData.dropna(thresh=len(dfLoanData) * 0.9, axis=1)

    logger.info("Total number of columns under consideration : " + str(len(dfLoanData.columns)))

    #cleaning and filling missing data
    logger.info("Cleaning and filling missing data")
    dfLoanData = funCleanNFillMissingLoanData(dfLoanData)

    #categorizing the columns
    logger.info("Categorizing the columns of loan data")
    dfLoanData = funCategorizeLoanData(dfLoanData)

    #writing data frame to the LoanData.csv
    logger.info("Writing data frame to the LoanData.csv")
    withHeaders = True
    for i in chunker(dfLoanData,50000):
        if(withHeaders):
            i.to_csv(loanFilePath, index=False, mode='a')
            withHeaders = False
        else:
            i.to_csv(loanFilePath, index=False, mode='a', header = False)
    logger.info("Total number of records in loan data : "+str(len(dfLoanData)))
    logger.info("Cleaned Loan data is available at "+loanFilePath)

    #Logging finished
    logger.info("Application finished....")
    logging.shutdown()

class Clean_loan_data(luigi.Task):
    def requires(self):
        return Download_loan_data()

    def output(self):
        return luigi.LocalTarget('CleanedData/LoanData.csv')

    def run(self):
        main()


import random
import operator
import matplotlib.pyplot
import matplotlib.animation
import agentframework9 as agentframework
import csv

#Retrieve environment information from text file.
f = open("in.txt")

environment = []

for line in f:
    parsed_line = str.split(line,",")
    rowlist = []
    for word in parsed_line:
        rowlist.append(float(word))
    environment.append(rowlist)
#print(environment)
f.close()

#Define the figure.
fig = matplotlib.pyplot.figure(figsize=(7,7))
ax = fig.add_axes([0, 0, 1, 1])

#Define the number of agents, wolves and iterations.
#Set the neighbourhood.
num_of_agents = 10
num_of_wolves = 20
num_of_iterations = 100
neighbourhood = 20
agents = []
wolves = []

#Make the agents.
for i in range(num_of_agents):
    agents.append(agentframework.Agent(agents, environment))

#Make the wolves.
for i in range(num_of_wolves):
    wolves.append(agentframework.Wolf(environment))

carry_on = True

#Define 'update' for the animation to show each new move.
def update(frame_number):
    fig.clear()
    global carry_on

    #Move the agents.
    #Have them eat and share their store with neighbours.
    for j in range(num_of_iterations):
        for i in range(num_of_agents):
            random.shuffle(agents)
            agents[i].move()
            agents[i].eat()
            agents[i].share_with_neighbours(neighbourhood)

        #Move the wolves.
        for i in range(num_of_wolves):
            wolves[i].move()
            for i in range(num_of_agents):
                #If the wolves are in the same location, have them empty the agent store.
                if wolves[i].getx() == agents[i].getx() and wolves[i].gety() == agents[i].gety():
                    wolves[i].store += agents[i].store
                    agents[i].store = 0
                else:
                    pass

#Include stopping condition.
    if random.random() < 0.1:
        carry_on = False
        print("stopping condition")

#Make the plot.
    width = len(environment)
    height = len(environment[0])
    matplotlib.pyplot.xlim(0, width)
    matplotlib.pyplot.ylim(0, height)
    for i in range(num_of_agents):
        matplotlib.pyplot.imshow(environment)
        matplotlib.pyplot.scatter(agents[i].x,agents[i].y, c = 'blue')
        matplotlib.pyplot.scatter(wolves[i].x,wolves[i].y, c = 'red')

    #print out agent info
    #for i in range(num_of_agents):
        #print(agents[i].__str__())

#Define the 'gen_function'.
def gen_function(b = [0]):
    a = 0
    global carry_on
    while (a < 10) & (carry_on) :
        yield a
        a = a + 1

#Create animation including the stopping condition.
animation = matplotlib.animation.FuncAnimation(fig, update, frames=gen_function, repeat=False)
matplotlib.pyplot.show()

#Store the list of agents.
storelist =[]
for agent in agents:
    storelist.append(agent.getstore())
totalstore = sum(storelist)

#Use one agent to find another agents information.
print (agents[0].agent_list[1]._x)

#Save the store list information.
f = open("store.txt", 'a')
writer = csv.writer(f)
f.write(str(totalstore)+ ', ')
f.close()

#Save the environment information.
f2 = open("environment.txt", 'w')
writer = csv.writer(f2, delimiter=' ')
f2.write(str(environment))
f2.close()


#!/usr/bin/python3
""" Base module """
import json
import csv

class Base:
    """ Base class """
    __nb_objects = 0

    def __init__(self, id=None):
        """ id models constructor """
        if id is None:
            Base.__nb_objects += 1
            self.id = Base.__nb_objects
        else:
            self.id = id

    @staticmethod
    def to_json_string(list_dictionaries):
        """ convert a dictionarie into string
        this function is used as a complement of
        to_dictionary method to store the current obj state
        into a json file
        """
        if list_dictionaries is None or len(list_dictionaries) == 0:
            return "[]"
        else:
            return json.dumps(list_dictionaries)

    @staticmethod
    def from_json_string(json_string):
        """ convert a json reprentation into a
        python object. Usefull to read json files
        """
        if json_string is None:
            return []
        else:
            return json.loads(json_string)

    @classmethod
    def save_to_file(cls, list_objs):
        """ save a obj or objs into a json file """
        new_list = []
        if list_objs is not None:
            for obj in list_objs:
                new_list.append(obj.to_dictionary())
        with open(cls.__name__+".json", mode="w", encoding="UTF8") as f:
            f.write(cls.to_json_string(new_list))

    @classmethod
    def save_to_file_csv(cls, list_objs):
        """ used to save an obj or some obj into a csv file """
        doc = cls.__name__+".csv"
        with open(doc, mode="w", encoding="UTF8", newline='') as f:
            writer = csv.writer(f)
            for obj in list_objs:
                if cls.__name__ == "Rectangle":
                    writer.writerow(
                        [obj.id, obj.width, obj.height, obj.x, obj.y])
                else:
                    writer.writerow(
                        [obj.id, obj.size, obj.x, obj.y])

    @classmethod
    def load_from_file_csv(cls):
        """ load an obj from a csv file """
        doc = cls.__name__+".csv"
        with open(doc, mode="r", encoding="UTF8", newline='') as f:
            csv_reader = csv.reader(f)
            instances = []
            keys = {}
            for obj in csv_reader:
                if cls.__name__ == "Rectangle":
                    keys["width"] = int(obj[1])
                    keys["height"] = int(obj[2])
                    keys["x"] = int(obj[3])
                    keys["y"] = int(obj[4])
                    keys["id"] = int(obj[0])
                    instances.append(cls.create(**keys))
                else:
                    keys["size"] = int(obj[1])
                    keys["x"] = int(obj[2])
                    keys["y"] = int(obj[3])
                    keys["id"] = int(obj[0])
                    instances.append(cls.create(**keys))
            return instances

    @classmethod
    def create(cls, **dictionary):
        """ create an instance from a dictionary
        or an argument list. Usually when you recover
        an obj from a csv or json file, you first get
        a dictionary or a list, this function is usefull
        to load the last instances
        """
        if cls.__name__ == "Rectangle":
            new = cls(1, 1)
            new.update(**dictionary)
        else:
            new = cls(1)
            new.update(**dictionary)
        return new

    @classmethod
    def load_from_file(cls):
        """ recover an obj from a json file """
        try:
            with open(cls.__name__+".json", mode="r", encoding="UTF8") as f:
                instances = []
                json = cls.from_json_string(f.read())
                for obj in json:
                    instances.append(cls.create(**obj))
                return instances
        except FileNotFoundError:
            return []


import requests
import os
import time
import threading
from bs4 import BeautifulSoup

def download_page(url):
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0"}
    headers={"User-Agent":"Mozilla/5.0"}
    r=requests.get(url,headers=headers)
    r.encoding='utf-8'
    return r.text

def get_list(html):
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0"}
    soup=BeautifulSoup(html,'html.parser')
    pic_list=soup.find_all('div',class_='pic')
    if not os.path.exists('douban'):
        os.makedirs('douban')
    for pic in pic_list:
        num = pic.find('em').text
        img_tag = pic.find('img')
        img =img_tag.get('src')
        alt =img_tag.get('alt')
        r = requests.get(img,headers=headers)
        with open('douban/{}'.format(num+'_'+alt+'.jpg'),'wb') as f:
            f.write(r.content)
            time.sleep(3)

def execute(url):
    page_html = download_page(url)
    get_list(page_html)

def main():
    pages=[ i for i in range(225,250,25)]
    for i in pages:
        url = 'https://movie.douban.com/top250?start={}'.format(i)
        execute(url)

main()


import cv2
import imutils
import pytesseract

# Inicializar la cámara
captura = cv2.VideoCapture(0)

while True:
    # Capturar el fotograma de la cámara
    _, fotograma = captura.read()
    print('llega al for')
    # Redimensionar el fotograma para facilitar el procesamiento
    fotograma = imutils.resize(fotograma, width=600)

    # Convertir el fotograma a escala de grises
    gris = cv2.cvtColor(fotograma, cv2.COLOR_BGR2GRAY)

    # Aplicar un filtro de suavizado para reducir el ruido
    suavizado = cv2.bilateralFilter(gris, 11, 17, 17)

    # Detectar los bordes en el fotograma utilizando Canny
    bordes = cv2.Canny(suavizado, 30, 200)

    # Encontrar los contornos en el fotograma
    contornos, _ = cv2.findContours(bordes.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    contornos = sorted(contornos, key=cv2.contourArea, reverse=True)[:10]

    # Inicializar la variable que almacenará la patente
    patente = None

    for contorno in contornos:
        # Aproximar el contorno a un polígono
        perimetro = cv2.arcLength(contorno, True)
        approx = cv2.approxPolyDP(contorno, 0.018 * perimetro, True)

        # Si el contorno tiene cuatro vértices, se considera una posible patente
        if len(approx) == 4:
            patente = approx
            break

    if patente is not None:
        # Dibujar el contorno de la patente en el fotograma
        cv2.drawContours(fotograma, [patente], -1, (0, 255, 0), 3)

        # Recortar la región del fotograma que contiene la patente
        (x, y, w, h) = cv2.boundingRect(patente)
        patente_recortada = suavizado[y:y + h, x:x + w]

        # Aplicar OCR a la región de la patente
        texto_patente = pytesseract.image_to_string(patente_recortada, lang='eng')

        # Imprimir el texto de la patente
        print('Patente:', texto_patente)

    # Mostrar el fotograma resultante
    cv2.imshow('Fotograma', fotograma)

    # Detener el bucle si se presiona la tecla 'q'
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# Liberar los recursos y cerrar las ventanas
captura.release()
cv2.destroyAllWindows()


# This program will analyze the financial statements and stock
# quote of any publically traded company listed in Yahoo Finance
# using financial ratio analysis.
#
# The program output a report file in HTML or PDF format of the
# results of the analysis.
#
# The comments in this program will be written in Javadoc style. This ensures
# compatibility with Doxygen documentation tool.

import requests
import pandas as pd
import numpy as np

# Constants

ROUNDING_PRECISION = 3

#
# Stores financial data from financial statements in one
# convenient place.
class FinancialData (object):
    # Initializes the financial data class by collecting data
    # from specified financial statements.
    def __init__ (self, balSht, incStmt, cfStmt, stkQte, dates):
        # Balance Sheet Values
        self.__cce = pd.to_numeric(balSht["Cash And Cash Equivalents"])
        self.__currLia = pd.to_numeric(balSht["Total Current Liabilities"])
        self.__currAssets = pd.to_numeric(balSht["Total Current Assets"])
        self.__shortTermInv = pd.to_numeric(balSht["Short Term Investments"])
        self.__NR = pd.to_numeric(balSht["Net Receivables"])
        self.__inventory = pd.to_numeric(balSht["Inventory"])
        self.__totalAssets = pd.to_numeric(balSht["Total Assets"])
        self.__totalLia = pd.to_numeric(balSht["Total Liabilities"])
        self.__totalSE = pd.to_numeric(balSht["Total Stockholder Equity"])

        # Income Statement Values
        self.__sales = pd.to_numeric(incStmt["Total Revenue"])
        self.__gp = pd.to_numeric(incStmt["Gross Profit"])
        self.__noil = pd.to_numeric(incStmt["Operating Income or Loss"])
        self.__ie = pd.to_numeric(incStmt["Interest Expense"])
        self.__ebit = pd.to_numeric(\
                        incStmt["Earnings Before Interest and Taxes"])
        self.__cor = pd.to_numeric(incStmt["Cost of Revenue"])

        # Net Income Value
        temp = incStmt["Net Income"]
        temp.columns = ["NanCol", "Net Income"]
        self.__ni = pd.to_numeric(temp["Net Income"])

        # Cash Flow Statement Values
        self.__ocf = pd.to_numeric(cfStmt\
                       ["Total Cash Flow From Operating Activities"])

    def getCashAndCashEquivalents (self):
        return self.__cce

    def getCurrentLiabilities (self):
        return self.__currLia

    def getCurrentAssets (self):
        return self.__currAssets

    def getShortTermInvestments(self):
        return self.__shortTermInv

    def getNetReceivables(self):
        return self.__NR

    def getInventory(self):
        return self.__inventory

    def getTotalAssets(self):
        return self.__totalAssets

    def getTotalLiabilities(self):
        return self.__totalLia

    def getTotalStockholderEquity(self):
        return self.__totalSE

    def getTotalShareholderEquity(self):
        return self.getTotalStockholderEquity();

    def getSales(self):
        return self.__sales

    def getTotalRevenue(self):
        return self.getSales();

    def getGrossProfit(self):
        return self.__gp

    def getOperatingIncomeOrLoss(self):
        return self.__noil

    def getNetOperatingIncomeOrLoss(self):
        return self.getOperatingIncomeOrLoss()

    def getInterestExpense(self):
        return self.__ie

    def getOperatingCashFlows(self):
        return self.__ocf

    def getEBIT(self):
        return self.__ebit

    def getCostOfRevenue(self):
        return self.__cor

    def getCOR(self):
        return self.getCostOfRevenue()

    def getNetIncome(self):
        return self.__ni

# Functions

# Retrieves financial statements and stock quote of a company
# from Yahoo's website.
def getFinancialStatementsFromYahoo (ticker):
    # URLs of various documents.
    url_cf_stmt = \
        "https://finance.yahoo.com/quote/%s/cash-flow?p=%s" %(ticker,ticker)
    url_income_stmt = \
        "https://finance.yahoo.com/quote/%s/financials?p=%s" %(ticker,ticker)
    url_balance_sheet = \
    "https://finance.yahoo.com/quote/%s/balance-sheet?p=%s" %(ticker,ticker)
    url_stock_quote = "https://finance.yahoo.com/quote/%s/" %(ticker)

    # To be on the safe side, we disguise this request as a Web Browser
    # request by adding this header.
    #
    # The request MIGHT successfully work without this header.

    myHeader = {
      "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.75 Safari/537.36",
      "X-Requested-With": "XMLHttpRequest"
    }

    # Make a request for EACH document
    requestCfStmt = requests.get(url_cf_stmt, headers=myHeader)
    print("Retrieved Cash Flow Statement.")
    requestBalSht = requests.get(url_balance_sheet, headers=myHeader)
    print("Retrieved Balance Sheet.")
    requestIncStmt = requests.get(url_income_stmt, headers=myHeader)
    print("Retrieved Income Statement.")
    requestStkQte = requests.get(url_stock_quote,headers=myHeader)
    print("Retrieved Stock Quote Statement.")

    # Format the tables into Pandas Dataflows
    # Note: It is best to have repetitve code, so that
    # the code can easily be changed if Yahoo Inc changes
    # its website's formatting.
    tablesCfStmt = pd.read_html(requestCfStmt.text)
    tablesBalSht = pd.read_html(requestBalSht.text)
    tablesIncStmt = pd.read_html(requestIncStmt.text)
    tablesStkQte = pd.read_html(requestStkQte.text)

    cfStmt = tablesCfStmt[0].transpose()
    cfStmt.columns = cfStmt.iloc[0]
    cfStmt = cfStmt[1:]

    balSht = tablesBalSht[0].transpose()
    balSht.columns = balSht.iloc[0]
    balSht = balSht[1:]

    incStmt = tablesIncStmt[0].transpose()
    incStmt.columns = incStmt.iloc[0]
    incStmt = incStmt[1:]

    stkQte0 = tablesStkQte[0].transpose()
    stkQte0.columns = stkQte0.iloc[0]
    stkQte1 = tablesStkQte[1].transpose()
    stkQte1.columns = stkQte1.iloc[0]
    stkQte = stkQte0.join(stkQte1, how='left')[1:]

    dates = incStmt[incStmt.columns[0]].values

    # Return stock information.
    return balSht, incStmt, cfStmt, stkQte, dates

# Calculates the Weighted Average Cost of Capital (WACC) of the firm.
# Parameters are retrieved from getFinancialStatementsFromYahoo().
def calculateWACC(balSht, incStmt, stkQte):
    # Calculate the cost of debt for the most recent year.
    interestExpense = np.array(list(map(int,\
                        incStmt["Interest Expense"].values[1:])))
    totalDebt = np.array(list(map(int,\
                        balSht["Total Liabilities"].values[1:])))

    costOfDebt4Yrs = np.abs(interestExpense)/totalDebt

    costOfDebt = pd.DataFrame({"K_d":costOfDebt4Yrs})[:1]\
        ["K_d"].values[0]

    # Calculate the Cost of Equity for the most recent year,
    # using the current beta value.
    beta = float(stkQte["Beta (3Y Monthly)"].values)

    # These rates are educated guesses.
    riskFreeRate = 0.02 # 2% Assumed
    marketRate = 0.098 # Average historical rate of return for S&P 500.

    costOfEquity = riskFreeRate + beta*(marketRate - riskFreeRate)

    totalLiabilities = float(balSht["Total Liabilities"][1])
    totalEquity = float(balSht["Total Stockholder Equity"][1])
    totalLiaEquity = totalLiabilities + totalEquity

    # Calculate WACC
    WACC = (totalLiabilities/totalLiaEquity)*costOfDebt +\
        (totalEquity/totalLiaEquity)*costOfEquity

    return WACC

# Liquidity Ratios
def calculateCashRatio (dates):
    global financialData
    cce = financialData.getCashAndCashEquivalents()
    currLia = financialData.getCurrentLiabilities()

    ratioAsSeries = cce/currLia

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Cash Ratio"])

def calculateQuickRatio (dates):
    global financialData
    cce = financialData.getCashAndCashEquivalents()
    si = financialData.getShortTermInvestments()
    nr = financialData.getNetReceivables()
    qa = cce + si + nr
    currLia = financialData.getCurrentLiabilities()

    ratioAsSeries = qa/currLia

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Quick Ratio"])

def calculateCurrentRatio (dates):
    global financialData
    currAssets = financialData.getCurrentAssets()
    currLia = financialData.getCurrentLiabilities()

    ratioAsSeries = currAssets/currLia

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Current Ratio"])

def calculateWorkingCapital(dates):
    global financialData
    currAssets = financialData.getCurrentAssets()
    currLia = financialData.getCurrentLiabilities()

    # Since all numbers are in thousands, we multiply
    # current assets and liabilities each by 1000.
    ratioAsSeries = 1000*currAssets - 1000*currLia

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Working Capital (WC)"])

def calculateCashToWorkingCapitalRatio(dates):
    global financialData
    cce = financialData.getCashAndCashEquivalents()
    wc = calculateWorkingCapital(dates)
    wc_series = wc["Working Capital (WC)"]
    wc_series.index = cce.index

    # CCE in thousands, working capital in exact amount.
    ratioAsSeries = 1000*cce/wc_series

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Cash To WC Ratio"])

def calculateInventoryToWorkingCapitalRatio(dates):
    global financialData
    inventory = financialData.getInventory()
    wc = calculateWorkingCapital(dates)
    wc_series = wc["Working Capital (WC)"]
    wc_series.index = inventory.index

    # Inventory in thousands, working capital in exact amount.
    ratioAsSeries = 1000*inventory/wc_series

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Inventory To WC Ratio"])

def salesToWorkingCapitalRatio(dates):
    global financialData
    sales = financialData.getSales()
    wc = calculateWorkingCapital(dates)
    wc_series = wc["Working Capital (WC)"]
    wc_series.index = sales.index

    # Sales in thousands, working capital in exact amount.
    ratioAsSeries = 1000*sales/wc_series

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Sales To WC Ratio"])

def salesToCurrentAssetsRatio(dates):
    global financialData
    sales = financialData.getSales()
    ca = financialData.getCurrentAssets()

    ratioAsSeries = sales/ca

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Sales To Current Assets Ratio"])

# Solvency Ratios

def calculateDebtRatio(dates):
    global financialData
    tl = financialData.getTotalLiabilities()
    ta = financialData.getTotalAssets()

    ratioAsSeries = tl/ta

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Debt Ratio"])

def calculateEquityRatio(dates):
    global financialData
    te = financialData.getTotalStockholderEquity()
    ta = financialData.getTotalAssets()

    ratioAsSeries = te/ta

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Equity Ratio"])

def calculateDebtToEquityRatio(dates):
    global financialData
    te = financialData.getTotalStockholderEquity()
    tl = financialData.getTotalLiabilities()
    ratioAsSeries = tl/te

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Debt to Equity Ratio"])

def calculateDebtToIncomeRatio(dates):
    global financialData
    tl = financialData.getTotalLiabilities()
    gp = financialData.getGrossProfit()

    ratioAsSeries = tl/gp

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Debt to Income Ratio"])

def calculateDebtServiceCoverageRatio(dates):
    global financialData
    noi = financialData.getOperatingIncomeOrLoss()
    ie = financialData.getInterestExpense()

    ratioAsSeries = noi/ie

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Debt Service Coverage Ratio"])

def calculateCashFlowToDebtRatio(dates):
    global financialData
    ocf = financialData.getOperatingCashFlows()
    tl = financialData.getTotalLiabilities()

    ratioAsSeries = ocf/tl

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Cash Flow to Debt Ratio"])

def calculateWCToDebtRatio(dates):
    global financialData
    tl = financialData.getTotalLiabilities()
    wc = calculateWorkingCapital(dates)
    wc_series = wc["Working Capital (WC)"]
    wc_series.index = tl.index

    ratioAsSeries = wc_series/tl

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["WC to Debt Ratio"])

def calculateTimesInterestEarned(dates):
    global financialData
    ebit = financialData.getEBIT()
    ie = np.abs(financialData.getInterestExpense())

    ratioAsSeries = ebit/ie

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Times Interest Earned"])

# Efficiency Ratios

def calculateAssetTurnoverRatio(dates):
    global financialData
    sales = financialData.getSales()
    totalAssets = financialData.getTotalAssets().values
    avgAssets = np.array([None]*len(totalAssets))

    for index in range(len(totalAssets)-1):
        avgAssets[index] = 0.5*(totalAssets[index]+totalAssets[index+1])

    avgAssets = pd.Series(avgAssets, index=range(1,len(avgAssets)+1))

    ratioAsSeries = sales/avgAssets

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Asset Turnover Ratio"])

def calculateInventoryTurnoverRatio(dates):
    global financialData
    cor = financialData.getCOR()
    totalInventory = financialData.getInventory().values
    avgInventory = np.array([None]*len(totalInventory))

    for index in range(len(totalInventory)-1):
        avgInventory[index] = 0.5*(totalInventory[index]+totalInventory[index+1])

    avgInventory = pd.Series(avgInventory, index=range(1,len(avgInventory)+1))

    ratioAsSeries = cor/avgInventory

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Inventory Turnover Ratio"])

def calculateAccountsReceivableTurnoverRatio(dates):
    global financialData
    sales = financialData.getSales()
    totalAR = financialData.getNetReceivables().values
    avgAR = np.array([None]*len(totalAR))

    for index in range(len(totalAR)-1):
        avgAR[index] = 0.5*(totalAR[index]+totalAR[index+1])

    avgAR = pd.Series(avgAR, index=range(1,len(avgAR)+1))

    ratioAsSeries = sales/avgAR

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Accounts Receivable Turnover Ratio"])

# Profitability Ratios

def calculateROARatio(dates):
    global financialData
    ni = financialData.getNetIncome()
    totalAssets = financialData.getTotalAssets().values
    avgAssets = np.array([None]*len(totalAssets))

    for index in range(len(totalAssets)-1):
        avgAssets[index] = 0.5*(totalAssets[index]+totalAssets[index+1])

    avgAssets = pd.Series(avgAssets, index=range(1,len(avgAssets)+1))

    ratioAsSeries = ni/avgAssets

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Return on Assets"])

def calculateROERatio(dates):
    global financialData
    ni = financialData.getNetIncome()
    totalSE = financialData.getTotalStockholderEquity()

    ratioAsSeries = ni / totalSE

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Return on Equity"])

def calculateROSRatio(dates):
    global financialData
    ebit = financialData.getEBIT()
    sales = financialData.getSales()

    ratioAsSeries = ebit / sales

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Return on Sales"])

def calculateNetProfitMarginRatio(dates):
    global financialData
    ni = financialData.getNetIncome()
    sales = financialData.getSales()

    ratioAsSeries = ni/sales

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Net Profit Margin Ratio"])

def calculateGrossProfitMarginRatio(dates):
    global financialData
    gp = financialData.getGrossProfit()
    sales = financialData.getSales()

    ratioAsSeries = gp/sales

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Gross Profit Margin Ratio"])

def calculateOperatingProfitMarginRatio(dates):
    global financialData
    op = financialData.getOperatingIncomeOrLoss()
    sales = financialData.getSales()

    ratioAsSeries = op/sales

    return pd.DataFrame(ratioAsSeries.values, index=dates,\
                        columns=["Operating Profit Margin Ratio"])

# Report-generating Functions
def getLiquidityRatios(dates):
    listOfRatioTables = [calculateCashRatio(dates),
    calculateQuickRatio(dates),calculateCurrentRatio(dates),
    calculateWorkingCapital(dates),
    calculateCashToWorkingCapitalRatio(dates),
    calculateInventoryToWorkingCapitalRatio(dates),
    salesToWorkingCapitalRatio(dates),
    salesToCurrentAssetsRatio(dates)]

    table = listOfRatioTables[0]

    for index in range(1,len(listOfRatioTables)):
        table = table.join(listOfRatioTables[index], how="left")

    return table.round(ROUNDING_PRECISION).astype(object).transpose()

def getSolvencyRatios(dates):
    listOfRatioTables = \
    [calculateDebtRatio(dates),
     calculateEquityRatio(dates),
     calculateDebtToEquityRatio(dates),
     calculateDebtToIncomeRatio(dates),
     calculateDebtServiceCoverageRatio(dates),
     calculateCashFlowToDebtRatio(dates),
     calculateWCToDebtRatio(dates),
     calculateTimesInterestEarned(dates)]

    table = listOfRatioTables[0]

    for index in range(1,len(listOfRatioTables)):
        table = table.join(listOfRatioTables[index], how="left")

    return table.round(ROUNDING_PRECISION).astype(object).transpose()

def getEfficiencyRatios(dates):
    listOfRatioTables = \
    [calculateAssetTurnoverRatio(dates),
     calculateInventoryTurnoverRatio(dates),
     calculateAccountsReceivableTurnoverRatio(dates)]

    table = listOfRatioTables[0]

    for index in range(1,len(listOfRatioTables)):
        table = table.join(listOfRatioTables[index], how="left")

    return table.round(ROUNDING_PRECISION).astype(object).transpose()

def getProfitabilityRatios(dates):
    listOfRatioTables = \
    [calculateROARatio(dates),\
     calculateROERatio(dates),\
     calculateROSRatio(dates),\
     calculateNetProfitMarginRatio(dates),\
     calculateGrossProfitMarginRatio(dates),\
     calculateOperatingProfitMarginRatio(dates)]

    table = listOfRatioTables[0]

    for index in range(1,len(listOfRatioTables)):
        table = table.join(listOfRatioTables[index], how="left")

    return table.round(ROUNDING_PRECISION).astype(object).transpose()

def createMasterReport(dates):
    liqTable = getLiquidityRatios(dates)
    solvTable = getSolvencyRatios(dates)
    effTable = getEfficiencyRatios(dates)
    profitTable = getProfitabilityRatios(dates)

    liqTableHTML = liqTable.to_html() # "liqRatios.html"
    solvTableHTML = solvTable.to_html() # "solvRatios.html"
    effTableHTML = effTable.to_html() # "effRatios.html"
    profitTableHTML = profitTable.to_html()

    header = \
    """
    <html>
    <head>
    <title> Financial Ratios </title>
    <body>
    """

    liqTableHTML = \
    """
    <h1> <u> Liquidity Ratios </u> </h1>
    """ + liqTableHTML

    solvTableHTML = \
    """
    <h1> <u> Solvency Ratios </u> </h1>
    """ + solvTableHTML

    effTableHTML = \
    """
    <h1> <u> Efficiency Ratios </u> </h1>
    """ + effTableHTML

    profitTableHTML = \
    """
    <h1> <u> Profitability Ratios </u> </h1>
    """ + profitTableHTML

    footer = \
    """
    </body>
    </html>
    """

    src = header + liqTableHTML + solvTableHTML + effTableHTML + \
        profitTableHTML + footer

    myFile = open("FinancialRatios.html", "w")
    myFile.write(src)
    myFile.close()

# Main Program
if __name__ == "__main__":
    balSht, incStmt, cfStmt, stkQte, dates = \
        getFinancialStatementsFromYahoo("KO")
    financialData = FinancialData(balSht, incStmt, cfStmt, stkQte, dates)
    createMasterReport(dates)


from DCNN_transfer_learning.init import *

import torchvision
from torchvision import datasets, models, transforms
from torchvision.datasets import ImageFolder
import torch.nn as nn

# normalization used to train VGG
# see https://pytorch.org/hub/pytorch_vision_vgg/
mean = np.array([0.485, 0.456, 0.406])
std = np.array([0.229, 0.224, 0.225])
transforms_norm = transforms.Normalize(mean=mean, std=std) # to normalize colors on the imagenet dataset

import seaborn as sns
import sklearn.metrics
from scipy import stats
from scipy.special import logit

# VGG-16 datasets initialisation
def datasets_transforms(image_size=args.image_size, c=1, p=0, num_workers=1, batch_size=args.batch_size, **kwargs):
    data_transforms = {
        'train': transforms.Compose([
            transforms.Resize((int(image_size), int(image_size))),
            transforms.AutoAugment(), # https://pytorch.org/vision/master/transforms.html#torchvision.transforms.AutoAugment
            transforms.RandomGrayscale(p=p),
            transforms.ToTensor(),      # Convert the image to pyTorch Tensor data type.
            transforms_norm ]),

        'val': transforms.Compose([
            transforms.Resize((int(image_size), int(image_size))),
            transforms.AutoAugment(), # https://pytorch.org/vision/master/transforms.html#torchvision.transforms.AutoAugment
            transforms.RandomGrayscale(p=p),
            transforms.ToTensor(),      # Convert the image to pyTorch Tensor data type.
            transforms_norm ]),

        'test': transforms.Compose([
            transforms.Resize((int(image_size), int(image_size))),
            transforms.RandomGrayscale(p=p),
            transforms.ColorJitter(contrast=c), # https://pytorch.org/vision/0.8/_modules/torchvision/transforms/transforms.html#ColorJitter
            transforms.ToTensor(),      # Convert the image to pyTorch Tensor data type.
            transforms_norm ]),
    }

    image_datasets = {
        folder: datasets.ImageFolder(
            paths[folder],
            transform=data_transforms[folder]
        )
        for folder in args.folders
    }

    dataloaders = {
        folder: torch.utils.data.DataLoader(
            image_datasets[folder], batch_size=batch_size,
            shuffle=False if folder == "test" else True, num_workers=num_workers
        )
        for folder in args.folders
    }

    dataset_sizes = {folder: len(image_datasets[folder]) for folder in args.folders}

    return dataset_sizes, dataloaders, image_datasets, data_transforms

(dataset_sizes, dataloaders, image_datasets, data_transforms) = datasets_transforms(image_size=args.image_size)

for folder in args.folders : print(f"Loaded {dataset_sizes[folder]} images under {folder}")
class_names = image_datasets['train'].classes
print("Classes: ", image_datasets['train'].classes)
n_output = len(os.listdir(paths['train']))


import curses
from curses import panel

class EndgameScreen(object):
    #def __init__(self, title, items, stdscreen):
    def __init__(self, stdscreen):
        maxY, maxX = stdscreen.getmaxyx()
        self.position = 0

        rows = 10
        cols = 40

        y = maxY // 2 - (rows//2)
        x = maxX // 2 - (cols//2)

        self.content = [
            "THANK YOU FOR PLAYING",
            "",
            "https://linktr.ee/evildojo",
            "https://evildojo.com",
            "https://twitch.tv/darkmage666",
            "https://github.com/mikedesu/textrpg"
        ]

        self.window = stdscreen.subwin(rows, cols , y, x)
        self.window.keypad(1)
        self.panel = panel.new_panel(self.window)
        self.panel.hide()
        panel.update_panels()

    #def navigate(self, n):
    #    self.position += n
    #    if self.position < 0:
    #        self.position = 0
    #    elif self.position >= len(self.items):
    #        self.position = len(self.items) - 1

    def display(self):
        self.panel.top()
        self.panel.show()
        self.window.clear()
        rows, cols = self.window.getmaxyx()

        #while True:
        self.window.refresh()
        curses.doupdate()
        self.window.border('|','|','-','-','+','+','+','+')
        offsetY = 1
        offsetX = 1

        for line in self.content:
            self.window.addstr( offsetY, offsetX, line )
            offsetY += 1

        key = self.window.getch()
        #    break

        self.window.clear()
        self.panel.hide()
        panel.update_panels()
        curses.doupdate()


# |------------------------------------| Initialisation |------------------------------------|
import random
import pygame

pygame.init()

RED = (255, 0, 0)
ORANGE = (255, 127, 0)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
GREY = (127, 127, 127)
BLACK = (0, 0, 0)

d1 = pygame.image.load('d1.png')                            # this section initializes all the variables
d2 = pygame.image.load('d2.png')                            # and saves some data that will be needed later
d3 = pygame.image.load('d3.png')
d4 = pygame.image.load('d4.png')
d5 = pygame.image.load('d5.png')
d6 = pygame.image.load('d6.png')

size = (500, 600)
screen = pygame.display.set_mode(size)

pygame.display.set_caption("Pigs Game")

done = False

clock = pygame.time.Clock()

font = pygame.font.SysFont("arial", 20)

mouse_state = 0
mouse_x = 0
mouse_y = 0

maxScore = 50
noDice = 1

gameState = -1

turn = 1

roll1 = 0
roll2 = 0
roll3 = 0

bot = 1

# |------------------------------------| Button Setup |------------------------------------|

class Button:

    def __init__(self):
        self.textBoxes = {}

    # ----Clicked In----
    @staticmethod
    def clickedIn(x, y, width, height):                                     # this method checks if the button
        global mouse_state, mouse_x, mouse_y                                # is being clicked
        if mouse_state == 1 and x <= mouse_x <= (x + width) \
                and y <= mouse_y <= (y + height):
            return True

    # ----Clicked Out----
    @staticmethod
    def clickedOut(x, y, width, height):                                    # this method checks if the button
        global mouse_state, mouse_x, mouse_y                                # isn't being clicked
        if mouse_state == 1 and (mouse_x < x or mouse_x > (x + width)) \
                or mouse_state == 1 and (mouse_y < y or mouse_y > (y + height)):
            return True

    # ----Hovering----
    @staticmethod
    def hovering(x, y, width, height):                                      # this method checks if the button
        global mouse_state, mouse_x, mouse_y                                # is being hovered over
        if mouse_state == 0 and x <= mouse_x <= (x + width) \
                and y <= mouse_y <= (y + height):
            return True

    # ----Click Button----
    def clickButton(self, x, y, width, height, normalColour, hoverColour, textFont, text, textColour,
                    stateHolding=False,
                    stateVariable=0, state=1):
        if not self.clickedIn(x, y, width, height) and not self.hovering(x, y, width, height):
            pygame.draw.rect(screen, normalColour, (x, y, width, height))
        elif self.hovering(x, y, width, height):                            # this method uses the previous methods
            pygame.draw.rect(screen, hoverColour, (x, y, width, height))    # to check the state of the button and
        if stateHolding and stateVariable == state:                         # designates its look respectively and
            pygame.draw.rect(screen, hoverColour, (x, y, width, height))    # also gives an output when clicked
        buttonText = textFont.render(text, True, textColour)
        buttonText_x = buttonText.get_rect().width
        buttonText_y = buttonText.get_rect().height
        screen.blit(buttonText, (((x + (width / 2)) - (buttonText_x / 2)), ((y + (height / 2)) - (buttonText_y / 2))))
        if self.clickedIn(x, y, width, height):
            return True

# |------------------------------------| Info Bar Code |------------------------------------|

def infoBar():
    global gameState
    global turn
    pygame.draw.rect(screen, GREY, (0, 0, 500, 115))
    pygame.draw.line(screen, BLACK, (0, 115), (500, 115), 4)

    if gameState == 0 or gameState == -3 or gameState == -5:
        text = font.render("GOAL: " + str(game.goal), True, BLACK)
        text_x = text.get_rect().width
        text_y = text.get_rect().height
        screen.blit(text, ((250 - (text_x / 2)), (35 - (text_y / 2))))
        if gameState == 0 or gameState == -3:
            text = font.render("Player1's score: " + str(game.score1), True, BLACK)
        else:
            text = font.render("Bot1's score: " + str(game.score1), True, BLACK)    # this section dictates the way
        text_x = text.get_rect().width                                              # the game screen looks and
        text_y = text.get_rect().height                                             # which text appears based on
        screen.blit(text, ((150 - (text_x / 2)), (80 - (text_y / 2))))              # who is playing what
        if gameState == 0:
            text = font.render("Player2's score: " + str(game.score2), True, BLACK)
        elif gameState == -3:
            text = font.render("The Bot's score: " + str(game.score2), True, BLACK)
        else:
            text = font.render("Bot2's score: " + str(game.score2), True, BLACK)
        text_x = text.get_rect().width
        text_y = text.get_rect().height
        screen.blit(text, ((350 - (text_x / 2)), (80 - (text_y / 2))))
        if turn == 1:
            if gameState == 0 or gameState == -3:
                text = font.render("Player 1's Turn", True, BLACK)
            else:
                text = font.render("Bot1's Turn", True, BLACK)                      # and this decides based on
            text_x = text.get_rect().width                                          # whose turn it is
            text_y = text.get_rect().height
            screen.blit(text, ((250 - (text_x / 2)), (150 - (text_y / 2))))
        else:
            if gameState == 0:
                text = font.render("Player 2's Turn", True, BLACK)
            elif gameState == -3:
                text = font.render("The Bot's Turn", True, BLACK)
            else:
                text = font.render("Bot2's Turn", True, BLACK)
            text_x = text.get_rect().width
            text_y = text.get_rect().height
            screen.blit(text, ((250 - (text_x / 2)), (150 - (text_y / 2))))

        text = font.render("This round's total: " + str(game.roundT), True, BLACK)
        text_x = text.get_rect().width
        text_y = text.get_rect().height
        screen.blit(text, ((250 - (text_x / 2)), (200 - (text_y / 2))))

        if game.dice != 2:                                              # ------------------------------
            if roll1 == 1:
                screen.blit(d1, (150, 220))
            elif roll1 == 2:
                screen.blit(d2, (150, 220))                     # this section is the code that displays
            elif roll1 == 3:                                    # the dice. it decides the number of dice to
                screen.blit(d3, (150, 220))                     # be shown and shows the correct face for what
            elif roll1 == 4:                                    # was rolled
                screen.blit(d4, (150, 220))
            elif roll1 == 5:
                screen.blit(d5, (150, 220))
            else:
                screen.blit(d6, (150, 220))
            if game.dice == 3:                                          # ------------------------------
                if roll2 == 1:
                    screen.blit(d1, (0, 220))
                elif roll2 == 2:
                    screen.blit(d2, (0, 220))
                elif roll2 == 3:
                    screen.blit(d3, (0, 220))
                elif roll2 == 4:
                    screen.blit(d4, (0, 220))
                elif roll2 == 5:
                    screen.blit(d5, (0, 220))
                else:                                                   # this bit adds the second and
                    screen.blit(d6, (0, 220))                           # third dice if there are
                if roll3 == 1:                                          # meant to be three of them
                    screen.blit(d1, (300, 220))
                elif roll3 == 2:
                    screen.blit(d2, (300, 220))
                elif roll3 == 3:
                    screen.blit(d3, (300, 220))
                elif roll3 == 4:
                    screen.blit(d4, (300, 220))
                elif roll3 == 5:
                    screen.blit(d5, (300, 220))
                else:
                    screen.blit(d6, (300, 220))
        else:                                                           # ------------------------------
            if roll1 == 1:
                screen.blit(d1, (75, 220))
            elif roll1 == 2:
                screen.blit(d2, (75, 220))
            elif roll1 == 3:
                screen.blit(d3, (75, 220))
            elif roll1 == 4:
                screen.blit(d4, (75, 220))
            elif roll1 == 5:
                screen.blit(d5, (75, 220))
            else:                                                           # and this bit shows two dice
                screen.blit(d6, (75, 220))                                  # for the two dice option
            if roll2 == 1:                                                  # i've had to do it like this
                screen.blit(d1, (225, 220))                                 # due to positioning issues
            elif roll2 == 2:                                                # so if the number of dice is
                screen.blit(d2, (225, 220))                                 # two it needs this entirely
            elif roll2 == 3:                                                # separate set of coordinates
                screen.blit(d3, (225, 220))
            elif roll2 == 4:
                screen.blit(d4, (225, 220))
            elif roll2 == 5:
                screen.blit(d5, (225, 220))
            else:
                screen.blit(d6, (225, 220))

    elif gameState == 1:  # p1                                              # ------------------------------
        text = font.render("PLAYER 1 WINS", True, BLACK)
        text_x = text.get_rect().width
        text_y = text.get_rect().height                                     # this section shows the win screens
        screen.blit(text, ((150 - (text_x / 2)), (50 - (text_y / 2))))      # it was easier to do them as separate
    elif gameState == 2:  # p2                                              # sections of the main game display
        text = font.render("PLAYER 2 WINS", True, BLACK)                    # rather than making an entirely new
        text_x = text.get_rect().width                                      # def statement for them because they
        text_y = text.get_rect().height                                     # are so simple
        screen.blit(text, ((150 - (text_x / 2)), (50 - (text_y / 2))))
    if gameState == 1 or gameState == 2:
        if button.clickButton(325, 25, 150, 50, RED, ORANGE, font, "RESET", BLACK):
            gameState = -1
            game.reset(0, 0)

    if gameState == 0:                                                      # ------------------------------
        if button.clickButton(160, 480, 80, 30, RED, ORANGE, font, "MENU", BLACK):
            gameState = -1
        if button.clickButton(260, 480, 80, 30, RED, ORANGE, font, "QUIT", BLACK):
            pygame.quit()
        if button.clickButton(160, 440, 80, 30, RED, ORANGE, font, "ROLL", BLACK):
            game.roll()
        if button.clickButton(260, 440, 80, 30, RED, ORANGE, font, "BANK", BLACK):
            if turn == 1:
                game.score1 += game.roundT
                if game.score1 >= game.goal:                            # this section is the code for what is
                    gameState = 1                                       # displayed when it is a player vs player match
                else:                                                   # and the bank score function
                    turn = 2
            else:
                game.score2 += game.roundT
                if game.score2 >= game.goal:
                    gameState = 2
                else:
                    turn = 1
            game.roundT = 0
    if gameState == -3:                                                     # ------------------------------
        if button.clickButton(160, 480, 80, 30, RED, ORANGE, font, "MENU", BLACK):
            gameState = -1
        if button.clickButton(260, 480, 80, 30, RED, ORANGE, font, "QUIT", BLACK):
            pygame.quit()
        if turn == 2:
            text = font.render("The AI is currently taking it's turn", True, BLACK)
            text_x = text.get_rect().width
            text_y = text.get_rect().height
            screen.blit(text, ((250 - (text_x / 2)), (440 - (text_y / 2))))
            if bot == 1:
                game.Bot1()                                                 # this is the code for when a player
            elif bot == 2:                                                  # faces off against a bot
                game.Bot2()
        elif turn == 1:
            if button.clickButton(160, 440, 80, 30, RED, ORANGE, font, "ROLL", BLACK):
                game.roll()
            if button.clickButton(260, 440, 80, 30, RED, ORANGE, font, "BANK", BLACK):
                if turn == 1:
                    game.score1 += game.roundT
                    if game.score1 >= game.goal:
                        gameState = 1
                    else:
                        turn = 2
                game.roundT = 0
    if gameState == -5:                                                     # ------------------------------
        if button.clickButton(160, 480, 80, 30, RED, ORANGE, font, "MENU", BLACK):
            gameState = -1
        if button.clickButton(260, 480, 80, 30, RED, ORANGE, font, "QUIT", BLACK):
            pygame.quit()
        text = font.render("the AI is currently taking it's turn", True, BLACK)
        text_x = text.get_rect().width                                              # this is the code for when
        text_y = text.get_rect().height                                             # the AIs do battle
        screen.blit(text, ((250 - (text_x / 2)), (440 - (text_y / 2))))
        if turn == 1:
            game.Bot1()
        elif turn == 2:
            game.Bot2()

# |------------------------------------| Menu Code |------------------------------------|

def menu():
    global gameState
    screen.fill(GREY)
    text = font.render("PIGS   GAME", True, BLACK)
    text_x = text.get_rect().width
    text_y = text.get_rect().height
    screen.blit(text, ((250 - (text_x / 2)), (100 - (text_y / 2))))
    text = font.render("MENU", True, BLACK)
    text_x = text.get_rect().width
    text_y = text.get_rect().height
    screen.blit(text, ((250 - (text_x / 2)), (150 - (text_y / 2))))         # this section of code is for which
    text = font.render("Normal Games", True, BLACK)                         # buttons are displayed on the main menu
    text_x = text.get_rect().width
    text_y = text.get_rect().height
    screen.blit(text, ((150 - (text_x / 2)), (240 - (text_y / 2))))
    text = font.render("Fancy Games", True, BLACK)
    text_x = text.get_rect().width
    text_y = text.get_rect().height
    screen.blit(text, ((350 - (text_x / 2)), (240 - (text_y / 2))))
    if button.clickButton(100, 260, 100, 50, RED, ORANGE, font, "SMALL", BLACK):
        game.reset(100, 1)
        gameState = 0
    if button.clickButton(100, 370, 100, 50, RED, ORANGE, font, "MEDIUM", BLACK):
        game.reset(250, 1)
        gameState = 0
    if button.clickButton(100, 480, 100, 50, RED, ORANGE, font, "LARGE", BLACK):
        game.reset(500, 2)
        gameState = 0
    if button.clickButton(300, 260, 100, 50, RED, ORANGE, font, "CUSTOM", BLACK):
        gameState = -2
    if button.clickButton(300, 370, 100, 50, RED, ORANGE, font, "AI", BLACK):
        gameState = -4
    if button.clickButton(300, 480, 100, 50, RED, ORANGE, font, "QUIT", BLACK):
        pygame.quit()

# |------------------------------------| Custom Menu Code |------------------------------------|

def custom():
    global maxScore, noDice, gameState
    screen.fill(GREY)
    text = font.render("CUSTOM MENU", True, BLACK)
    text_x = text.get_rect().width
    text_y = text.get_rect().height
    screen.blit(text, ((250 - (text_x / 2)), (100 - (text_y / 2))))
    text = font.render("GOAL: " + str(maxScore), True, BLACK)
    text_x = text.get_rect().width
    text_y = text.get_rect().height
    screen.blit(text, ((225 - (text_x / 2)), (180 - (text_y / 2))))
    if button.clickButton(300, 160, 20, 20, RED, ORANGE, font, " /\ ", BLACK):
        if maxScore < 1000:
            maxScore += 50
    if button.clickButton(300, 180, 20, 20, RED, ORANGE, font, " \/ ", BLACK):
        if maxScore > 50:
            maxScore -= 50                                                      # this section of code is for the
    text = font.render("DICE: " + str(noDice), True, BLACK)                     # customisation options page and
    text_x = text.get_rect().width                                              # all included buttons
    text_y = text.get_rect().height
    screen.blit(text, ((230 - (text_x / 2)), (260 - (text_y / 2))))
    if button.clickButton(300, 240, 20, 20, RED, ORANGE, font, " /\ ", BLACK):
        if noDice < 3:
            noDice += 1
    if button.clickButton(300, 260, 20, 20, RED, ORANGE, font, " \/ ", BLACK):
        if noDice > 1:
            noDice -= 1
    if button.clickButton(200, 390, 100, 60, RED, ORANGE, font, "START", BLACK):
        game.reset(maxScore, noDice)
        gameState = 0
    if button.clickButton(210, 480, 80, 30, RED, ORANGE, font, "MENU", BLACK):
        gameState = -1
    if button.clickButton(210, 530, 80, 30, RED, ORANGE, font, "QUIT", BLACK):
        pygame.quit()

# |------------------------------------| AI Menu Code |------------------------------------|

def AI():
    global maxScore, gameState, bot
    screen.fill(GREY)
    text = font.render("AI MENU", True, BLACK)
    text_x = text.get_rect().width
    text_y = text.get_rect().height
    screen.blit(text, ((250 - (text_x / 2)), (100 - (text_y / 2))))
    if button.clickButton(100, 200, 100, 50, RED, ORANGE, font, "EASY", BLACK):
        game.reset(100, 1)
        gameState = -3
        bot = 1                                                                   # this section of code is for all
    text = font.render("An easy bot to warm up on", True, BLACK)                  # options regarding AIs such as
    text_x = text.get_rect().width                                                # which one you want to fight or if
    text_y = text.get_rect().height                                               # you want to watch them battle
    screen.blit(text, ((330 - (text_x / 2)), (225 - (text_y / 2))))               # each other
    if button.clickButton(100, 300, 100, 50, RED, ORANGE, font, "HARD", BLACK):
        game.reset(100, 1)
        gameState = -3
        bot = 2
    text = font.render("Something to annoy you", True, BLACK)
    text_x = text.get_rect().width
    text_y = text.get_rect().height
    screen.blit(text, ((330 - (text_x / 2)), (325 - (text_y / 2))))
    if button.clickButton(100, 400, 100, 50, RED, ORANGE, font, "AI BATTLE", BLACK):
        game.reset(100, 1)
        gameState = -5
    text = font.render("Let them fight each other", True, BLACK)
    text_x = text.get_rect().width
    text_y = text.get_rect().height
    screen.blit(text, ((330 - (text_x / 2)), (425 - (text_y / 2))))
    if button.clickButton(100, 500, 100, 50, RED, ORANGE, font, "MAIN MENU", BLACK):
        gameState = -1
    if button.clickButton(300, 500, 100, 50, RED, ORANGE, font, "QUIT", BLACK):
        pygame.quit()

# |------------------------------------| Game Logic Code + Bots |------------------------------------|

class Game:
    def __init__(self, goal, dice):
        self.goal = goal                                        # this initialises all necessary variables
        self.dice = dice                                        # for the class 'Game'
        self.score1 = 0
        self.score2 = 0
        self.roundT = 0
        self.cool_down = 500
        self.last = 0

    def roll(self):                                             # ------------------------------
        global turn, roll1, roll2, roll3
        now = pygame.time.get_ticks()
        if now - self.last >= self.cool_down:
            self.last = now
            roll1 = random.randint(1, 6)
            roll2 = random.randint(1, 6)
            roll3 = random.randint(1, 6)
            if game.dice == 1:
                num = roll1
            elif game.dice == 2:                                # this is the roll function and is
                num = roll1 + roll2                             # adaptable depending on the number
            else:                                               # of dice rolled
                num = roll1 + roll2 + roll3
            if num == game.dice:
                game.roundT = 0
                if turn == 1:
                    turn = 2
                else:
                    turn = 1
            else:
                game.roundT += num
            return game.roundT

    def Bot1(self):                                             # ------------------------------
        global gameState, turn
        x = turn
        if game.roundT >= 10 and turn == x:
            if turn == 2:
                pygame.time.delay(1000)
                game.score2 += game.roundT
                if game.score2 >= game.goal:
                    gameState = 2
                else:                                       # this is the easy bot code and is very
                    turn = 1                                # simple only holding until it has over 10
            else:                                           # score before banking. it is a decent
                pygame.time.delay(1000)                     # initial strategy but is in no way the best
                game.score1 += game.roundT
                if game.score1 >= game.goal:
                    gameState = 1
                else:
                    turn = 2
            game.roundT = 0
        elif game.roundT < 10 and turn == x:
            pygame.time.delay(1000)
            self.roll()

    def Bot2(self):                                             # ------------------------------
        global gameState, turn
        x = turn

        if game.score2 == 0 and game.roundT < 21 and turn == x:
            pygame.time.delay(1000)
            self.roll()
        elif 21 < game.score2 <= 27 and game.roundT < 20 and turn == x:
            pygame.time.delay(1000)
            self.roll()
        elif 41 <= game.score2 <= 46 and game.roundT < 19 and turn == x:
            pygame.time.delay(1000)
            self.roll()
        elif 47 <= game.score2 <= 52 and game.roundT < 17 and turn == x:
            pygame.time.delay(1000)
            self.roll()
        elif 61 <= game.score2 <= 66 and game.roundT <= 15 and turn == x:
            pygame.time.delay(1000)
            self.roll()
        elif 67 <= game.score1 <= 74 and game.roundT <= 11 and turn == x:
            pygame.time.delay(1000)
            self.roll()
        elif game.score2 >= 75 and (game.roundT + game.score2) < 100 and turn == x:
            pygame.time.delay(1000)
            self.roll()
        elif game.score1 >= 80 and game.roundT < (game.goal - game.score2) and turn == x:
            pygame.time.delay(1000)
            self.roll()

        elif turn == 2:
            pygame.time.delay(1000)                     # this is the hard bot and its strategy is to hold to
            game.score2 += game.roundT                  # varying amounts depending on how much score it has
            if game.score2 >= game.goal:                # and how much score the opponent has making it more
                gameState = 2                           # comprehensive and tougher to beat
            else:
                turn = 1
            game.roundT = 0
        elif turn == 1:
            pygame.time.delay(1000)
            game.score1 += game.roundT
            if game.score1 >= game.goal:
                gameState = 1
            else:
                turn = 2
            game.roundT = 0

    def reset(self, goal, dice):                               # ------------------------------
        global turn
        self.goal = goal
        self.dice = dice                                       # this resets the game to a fresh state so
        self.score1 = 0                                        # that when its played again there are no
        self.score2 = 0                                        # accidental left over variables from
        self.roundT = 0                                        # the previous game
        turn = 1

# |------------------------------------| Main Loop |------------------------------------|

button = Button()
game = Game(0, 0)

while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        if event.type == pygame.MOUSEBUTTONDOWN:
            mouse_state = event.button
            pygame.mouse.set_pos(mouse_x, mouse_y)
        else:
            mouse_state = 0                                     # this is the main loop of the program and
#                                                               # is what drives the display and the checking
    mouse_x = pygame.mouse.get_pos()[0]                         # of weather the buttons have been pressed
    mouse_y = pygame.mouse.get_pos()[1]                         # it sets the frame rate to 60 times a second
#                                                               # and depending on the global variable gameState
    screen.fill(WHITE)                                          # it will display a different page to the user
#                                                               # then the def statement for that page will
    if gameState == -1:                                         # set the looks of the gui and which buttons
        menu()                                                  # are available to press

    elif gameState == -2:
        custom()

    elif 0 <= gameState <= 2 or gameState == -3 or gameState == -5:
        infoBar()

    elif gameState == -4:
        AI()

    pygame.display.flip()

    clock.tick(60)

pygame.quit()


"""
This module has an implementation of Bootstrapped DQN, which is described in
- Deep Exploration via Bootstrapped DQN
  - URL: https://arxiv.org/abs/1602.04621
- Randomized Prior Functions for Deep Reinforcement Learning
  - URL: https://arxiv.org/abs/1806.03335
"""
import copy
from typing import Optional

import numpy as np
import torch
from torch import Tensor
from torch.nn import functional as F

from ..config import Config
from ..envs import EnvTransition
from ..prelude import Action, Array, State
from ..replay import BootDQNReplayFeed
from .base import DQNLikeAgent, Netout

class BootDQNAgent(DQNLikeAgent):
    SAVED_MEMBERS = "net", "policy", "total_steps", "target_net"

    def __init__(self, config: Config) -> None:
        super().__init__(config)
        if not self.env._spec.is_discrete():
            raise RuntimeError("DQN only supports discrete action space.")
        self.net = config.net("bootdqn")
        self.target_net = copy.deepcopy(self.net)
        self.optimizer = config.optimizer(self.net.parameters())
        self.policy = config.explorer()
        self.eval_policy = config.explorer(key="eval")
        self.replay = config.replay_buffer()
        self.active_head = 0
        if self.replay.feed is not BootDQNReplayFeed:
            raise RuntimeError("BootDQNAgent needs BootDQNReplayFeed")

    def set_mode(self, train: bool = True) -> None:
        self.net.train(mode=train)

    @torch.no_grad()
    def eval_action(self, state: Array, net_outputs: Optional[Netout] = None) -> Action:
        return self.eval_policy.select_action(state, self.net, net_outputs).item()

    def action(self, state: State) -> Action:
        if self.train_started:
            with torch.no_grad():
                qs = self.net.q_i_s(self.active_head, self.env.extract(state)).detach()
            return self.policy.select_from_value(qs).item()
        else:
            return self.env._spec.random_action()

    def store_transition(
        self,
        state: State,
        action: Action,
        transition: EnvTransition,
    ) -> None:
        randn = np.random.uniform(0, 1, self.config.num_ensembles)
        # Masks some observations per ensemble
        mask = randn < self.config.replay_prob
        self.replay.append(
            state,
            action,
            transition.state,
            transition.reward,
            transiiton.terminal,
            mask,
        )
        # If the episode ends, change the executing policy
        if terminal:
            self.active_head = np.random.randint(self.config.num_ensembles)

    @torch.no_grad()
    def _q_next(self, next_states: Array) -> Tensor:
        return self.net(next_states).max(axis=-1)[0]

    def train(self, replay_feed: BootDQNReplayFeed) -> None:
        obs = [ob.to_array(self.env.extract) for ob in replay_feed]
        states, actions, next_states, rewards, done, mask = map(np.asarray, zip(*obs))
        q_next = self._q_next(next_states)
        r = self.tensor(rewards).unsqueeze_(-1)
        discount = self.tensor(1.0 - done).mul_(self.config.discount_factor)
        q_target = r + discount.unsqueeze_(-1) * q_next
        q_current = self.net.q_s_a(states, actions)
        loss = F.mse_loss(q_current, q_target, reduction="none")
        masked_loss = loss.masked_select(self.tensor(mask, dtype=torch.bool)).mean()
        self._backward(masked_loss, self.optimizer, self.net.parameters())
        self.network_log(q_value=q_current.mean().item(), value_loss=masked_loss.item())
        if self.update_steps > 0 and self.update_steps % self.config.sync_freq == 0:
            self.target_net.load_state_dict(self.net.state_dict())