import unittest
import FlightsCore

class TestFlights(unittest.TestCase):

    def test_readroutes(self):
        l = FlightsCore.readroutes('data/routes.dat')
        self.assertTrue(len(l) == 67663, 'number of imported rows is not correct')
        self.assertTrue((l[0].Airline, l[0].Equipment) == ('2B','CR2'), l[0].Airline+ ' ' +l[0].Equipment )

    def test_readairports(self):
        l = FlightsCore.readairports('data/airports.dat')
        self.assertTrue(len(l) == 7184 , 'readairports does not work 1' )
        self.assertTrue(l['12057'].Latitude == 41.784400939941406 and l['12057'].Longitude == 123.49600219726562 , 'readairports does not work 2')

    def test_BuildGraph(self):
        row1 = FlightsCore.Route(
            Airline              = '1',
            AirlineID            = '2',
            SourceAirport        = '3',
            SourceAirportID      = '4',
            DestinationAirport   = '5',
            DestinationAirportID = '6',
            Codeshare            = '7',
            Stops                = '8',
            Equipment            = '9'
        )

        row2 = FlightsCore.Route(
            Airline              = '1',
            AirlineID            = '2',
            SourceAirport        = '3',
            SourceAirportID      = '4',
            DestinationAirport   = '51',
            DestinationAirportID = '61',
            Codeshare            = '7',
            Stops                = '8',
            Equipment            = '9'
        )

        row3 = FlightsCore.Route(
            Airline              = '1',
            AirlineID            = '2',
            SourceAirport        = '3',
            SourceAirportID      = '4',
            DestinationAirport   = '5',
            DestinationAirportID = '6',
            Codeshare            = '7',
            Stops                = '8',
            Equipment            = '9'
        )

        self.assertTrue(FlightsCore.buildgraph([row1, row2]) == {'4': {'6':1, '61':1}},'buildGraph does not work1')
        self.assertTrue(FlightsCore.buildgraph([row1, row2], direction='reversed') == {'6': {'4':1}, '61' : {'4':1}},'buildGraph does not work2')
        self.assertTrue(FlightsCore.buildgraph([row1, row2, row3]) == {'4': {'6':2, '61':1}},'buildGraph does not work3')

    def test_GetPath(self):
        graph = {
                    '1':{'2':1,'3':1},
                    '2':{'1':1,'4':1,'6':1},
                    '4':{'1':1,'5':1},
                    '5':{'1':1,'6':1}
                }

        a = FlightsCore.getpath(graph,'1','6')
        self.assertTrue(a == ['1','2','6'] , 'getPath does not work 1 result -> ' + str(a))

        b = FlightsCore.getpath(graph,'1','7')
        self.assertTrue(b == None , 'getPath does not work 2 result -> ' + str(b))

        c = FlightsCore.getpath(graph,'1','4')
        self.assertTrue(c == ['1','2','4'] , 'getPath does not work 3 result -> ' + str(c))

    def test_GetRoute(self):
        graph = {
            '1':{'2':1,'3':1},
            '2':{'1':1,'4':1,'6':1},
            '4':{'1':1,'5':1},
            '5':{'1':1,'6':1}
        }

        a = FlightsCore.getroute(graph,['1','6'])
        self.assertTrue(a == ['1','2','6'] , 'test_GetRoute does not work 1 result -> ' + str(a))

        b = FlightsCore.getroute(graph, ['1','4','6'])
        self.assertTrue(b == ['1','2','4','5','6'] , 'test_GetRoute does not work 2 result -> ' + str(b))

    def test_BuildStatMap(self):
        row1 = FlightsCore.Route(
            Airline              = 'AB',
            AirlineID            = '2',
            SourceAirport        = '3',
            SourceAirportID      = '4',
            DestinationAirport   = '5',
            DestinationAirportID = '6',
            Codeshare            = 'N',
            Stops                = '8',
            Equipment            = '9'
        )

        row2 = FlightsCore.Route(
            Airline              = 'CD',
            AirlineID            = '2',
            SourceAirport        = '3',
            SourceAirportID      = '4',
            DestinationAirport   = '5',
            DestinationAirportID = '6',
            Codeshare            = 'Y',
            Stops                = '8',
            Equipment            = '9'
        )

        k = FlightsCore.Key(SourceAirportID= '4' , DestinationAirportID='6')

        self.assertTrue(FlightsCore.buildstatmap([row1, row2]) == {k:{'shared': {'CD'}, 'independent': {'AB'}}},'buildstatmap does not work1')

    def test_BuildAirlinesMap(self):
        row1 = FlightsCore.Route(
            Airline              = 'AB',
            AirlineID            = '2',
            SourceAirport        = '3',
            SourceAirportID      = '4',
            DestinationAirport   = '5',
            DestinationAirportID = '4',
            Codeshare            = 'N',
            Stops                = '8',
            Equipment            = '9'
        )

        row2 = FlightsCore.Route(
            Airline              = 'CD',
            AirlineID            = '2',
            SourceAirport        = '3',
            SourceAirportID      = '4',
            DestinationAirport   = '5',
            DestinationAirportID = '4',
            Codeshare            = 'Y',
            Stops                = '8',
            Equipment            = '9'
        )

        m={
            '4':{
                   'in' : {
                            'AB':1,
                            'CD':1
                   },
                   'out': {
                            'AB':1,
                            'CD':1
                   }
            }
        }

       # print(FlightsCore.buildairlinesmap([row1, row2]))
        self.assertTrue(FlightsCore.buildairlinesmap([row1, row2]) == m,'BuildAirlinesMap does not work1')

    def test_GetTopDestinations(self):
        graph = {
            '1':{'2':1,'3':1},
            '11079':{'11097':1,'12044':3,'3859':6 , '3671' : 5,'3161' : 7, '3269' : 7,'3624' : 7,'4133' : 7},
            '4':{'1':1,'5':1},
            '5':{'1':1,'6':1}
        }

        b = FlightsCore.gettopdestinations(graph,'11079')
        #self.assertTrue(b == [['Buri Ram Airport', 7], ['Teterboro Airport', 7], ['Kota Kinabalu International Airport', 7], ['U-Tapao International Airport', 7], ['New Castle Airport', 6]] , 'gettopdestinations does not work 1 result -> ' + str(b))

    def test_getairportid(self):
        self.assertTrue(FlightsCore.getairportid( 'AGZ') == '791', 'getairportid does not work 1')
        self.assertTrue(FlightsCore.getairportid( 'FABE') == '793', 'getairportid does not work 2')

    def test_getairportids(self):
        i = FlightsCore.getairportids( ['AGZ','FABE'] )
        self.assertTrue(i == ['791', '793'], 'getairportids does not work 1')

    def test_generatepolyline(self):
        FlightsCore.generatepolyline('.', ['791', '793', '3960'])

    def test_getairportcode(self):
        self.assertTrue(FlightsCore.getairportcode( '791') == 'AGZ', 'getairportcode does not work 1')
        self.assertTrue(FlightsCore.getairportcode( '9134') == 'UIAR', 'getairportcode does not work 2')
        self.assertTrue(FlightsCore.getairportcode('11095') == 'PRX', 'getairportcode does not work 3')

    def test_generatedistribution(self):
        graph = FlightsCore.buildgraphwrapper()
        FlightsCore.generatedistribution(graph, '.', '3712' , 'departure')

if __name__ == '__main__':
    unittest.main()


#!/usr/bin/env python
# -*- coding: utf-8 -*-

from kivy.factory import Factory
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button

from electrum_zcash.gui.kivy.i18n import _
from electrum_zcash.logging import Logger
from electrum_zcash.plugin import run_hook

Builder.load_string('''
<PluginLabel@ButtonBehavior+Label>
    text_size: self.size
    halign: 'left'
    valign: 'middle'

<PluginWidget@BoxLayout>
    fullname: ''
    orientation: 'horizontal'
    size_hint: 0.6, None
    height: '48dp'
    CheckBox:
        id: cb
        disabled: False
        active: False
        size_hint: None, 1
        width: '48dp'
        on_active: root.on_cb_active(self.active)
    PluginLabel:
        on_release: cb.active = not cb.active
        text: root.fullname
        disabled: cb.disabled

<SettingsBox@BoxLayout>
    orientation: 'horizontal'
    size_hint: 0.4, None
    height: '48dp'

<PluginHelp@Button>
    help_text: ''
    size_hint: None, None
    size: '48dp', '48dp'
    text: '?'

<PluginsDialog@Popup>
    title: _('Plugins')
    BoxLayout:
        orientation: 'vertical'
        padding: '10dp', '10dp'
        ScrollView:
            GridLayout:
                id: grid
                cols: 3
                spacing: '5dp'
                size_hint: 1, None
                height: self.minimum_height
        Button:
            text: _('Close')
            size_hint: 1, None
            height: '48dp'
            on_release: root.dismiss()
''')

class PluginWidget(BoxLayout):

    def __init__(self, *, app, name, fullname, settings_box):
        super(PluginWidget, self).__init__()
        self.app = app
        self.fullname = fullname
        self.name = name
        self.settings_box = settings_box
        self.active = False

    def update_settings_box(self, plugin):
        settings_widget = None
        if plugin and plugin.requires_settings() and plugin.is_enabled():
            settings_widget = plugin.settings_widget(self.app)
        self.settings_box.update(settings_widget)

    def update(self, from_cb=False):
        plugins = self.app.plugins
        wallet = self.app.wallet
        p = plugins.get(self.name)
        cb = self.ids.cb
        cb.disabled = (not p and not plugins.is_available(self.name, wallet)
                       or p and not p.is_available()
                       or p and not p.can_user_disable())
        self.active = bool(p and p.is_enabled())
        self.update_settings_box(p)
        if cb.active != self.active:
            cb.active = self.active

    def on_cb_active(self, is_checked):
        if self.active != is_checked:
            self.app.plugins.toggle(self.name)
            self.update()
            run_hook('init_kivy', self.app)

class SettingsBox(BoxLayout):

    def update(self, widget):
        self.clear_widgets()
        if widget:
            self.add_widget(widget)

class PluginHelp(Button):

    def __init__(self, *, app, help_text):
        super(PluginHelp, self).__init__()
        self.app = app
        self.help_text = help_text

    def on_release(self):
            width = self.app.root.width * 0.8
            self.app.show_info_bubble(text=self.help_text, width=width,
                                      arrow_pos=None)

class PluginsDialog(Factory.Popup, Logger):

    def __init__(self, app):
        super(PluginsDialog, self).__init__()
        self.app = app
        self.config = app.electrum_config
        self.network = app.network
        plugins = app.plugins
        grid = self.ids.grid
        for i, plugin_dict in enumerate(plugins.descriptions.values()):
            if plugin_dict.get('registers_keystore'):
                continue
            try:
                module_name = plugin_dict['__name__']
                prefix, _separator, name = module_name.rpartition('.')
                settings_box = SettingsBox()
                plugin_widget = PluginWidget(app=app, name=name,
                                             fullname=plugin_dict['fullname'],
                                             settings_box=settings_box)
                grid.add_widget(plugin_widget)
                grid.add_widget(settings_box)

                help_text = plugin_dict['description']
                requires = plugin_dict.get('requires')
                if requires:
                    help_text += '\n\n' + _('Requires') + ':\n'
                    help_text += '\n'.join(map(lambda x: x[1], requires))
                plugin_help = PluginHelp(app=app, help_text=help_text)
                grid.add_widget(plugin_help)
            except Exception as e:
                self.logger.exception(f'cannot display plugin {name}')

    def update(self):
        for widget in self.ids.grid.children:
            if isinstance(widget, PluginWidget):
                widget.update()


import torch
import os

def _set_device(self):
    # GPUの設定
    if self.config['env']['cuda_string']=='cpu':
        self.device = torch.device('cpu')
    ## 何も設定されていないときはすべてのGPUを数え上げて使用
    elif self.config['env']['cuda_string'] is None:
        num_devices = torch.cuda.device_count()
        if num_devices>0:
            self.config['env']['cuda_string'] = ','.join([str(i) for i in range(num_devices)])
            self.device = torch.device('cuda:'+self.config['env']['cuda_string'])
            torch.backends.cudnn.benchmark = True
        else:
            self.config['env']['cuda_string'] = 'cpu'
            self.device = torch.device('cpu')
        os.environ['CUDA_VISIBLE_DEVICES'] = self.config['env']['cuda_string']
    ## 何か設定されていても実際にはtorchから見えるすべてのGPUを使用することとなる
    else:
        self.device = torch.device('cuda:'+','.join([str(i) for i in range(torch.cuda.device_count())]))
        torch.backends.cudnn.benchmark = True

'''
Trainerクラスに書いている
```
class Trainer:
    def _set_device(self):
        hogehoge
```
を

``from hellflame.snippets.torch_gpu import _set_device``
した上で
```
class Trainer:
    _set_device = _set_device
```
という感じにクラスプロパティ的に挿入するだけで良い．
'''


from __future__ import absolute_import, division, print_function
from collections import namedtuple

import numpy as np
import tensorflow as tf
import tensorflow.contrib.slim as slim
from keras.layers import Conv2D, Conv2DTranspose, MaxPooling2D, concatenate, Cropping2D, Dense, Flatten, Input, Reshape
from keras.models import Model
#from keras.models import load_model
#from keras.backend import
from layers import depth_to_disparity, disparity_difference, expand_dims, spatial_transformation, disparity_to_depth

from bilinear_sampler import *
from projective_transformer import *
from projective_transformer_inv import *

updeepvo_parameters = namedtuple('parameters',
                        'height, width, '
                        'baseline, '
                        'batch_size, '
                        'num_threads, '
                        'num_epochs, '
                        'alpha_image_loss, '
                        'image_loss_weight, disp_loss_weight, pose_loss_weight, gradient_loss_weight, temporal_loss_weight, '
                        'full_summary')

class UpdeepvoModel(object):
    """updeepvo model"""

    def __init__(self, params, mode, left, right, left_next, right_next, cam_params, reuse_variables=None, model_index=0):
        self.params = params
        self.mode = mode
        self.left = left
        self.right = right
        self.left_next = left_next
        self.right_next = right_next
        self.model_collection = ['model_' + str(model_index)]

        self.focal_length1_left = cam_params[:,0]*cam_params[:,8]
        self.focal_length2_left = cam_params[:,0]*cam_params[:,7]
        self.c0_left = cam_params[:,1]*cam_params[:,8]
        self.c1_left = cam_params[:,2]*cam_params[:,7]
        self.focal_length1_right = cam_params[:,3]*cam_params[:,8]
        self.focal_length2_right = cam_params[:,3]*cam_params[:,7]
        self.c0_right = cam_params[:,4]*cam_params[:,8]
        self.c1_right = cam_params[:,5]*cam_params[:,7]
        self.baseline = cam_params[:,6]

        self.reuse_variables = reuse_variables

        self.build_depth_architecture()
        self.build_pose_architecture()

        self.depthmap_left, self.depthmap_right, self.depthmap_left_next, self.depthmap_right_next, self.translation_left, self.rotation_left, self.translation_right, self.rotation_right, self.left_unc, self.right_unc = self.build_model(self.left, self.right, self.left_next, self.right_next)

        self.build_outputs()

        if self.mode == 'test':
            return

        self.build_losses()
        self.build_summaries()

    def gradient_x(self, img):
        gx = img[:,:,:-1,:] - img[:,:,1:,:]
        gx = tf.pad(gx, [[0, 0], [0, 0], [0, 1], [0, 0]], "CONSTANT")
        return gx

    def gradient_y(self, img):
        gy = img[:,:-1,:,:] - img[:,1:,:,:]
        gy = tf.pad(gy, [[0, 0], [0, 1], [0, 0], [0, 0]], "CONSTANT")
        return gy

    def generate_image_left(self, img, disp):
        return bilinear_sampler_1d_h(img, -disp)

    def generate_image_right(self, img, disp):
        return bilinear_sampler_1d_h(img, disp)

    def get_disparity_smoothness(self, disp, pyramid):
        disp_gradients_x = [self.gradient_x(d) for d in disp]
        disp_gradients_y = [self.gradient_y(d) for d in disp]

        image_gradients_x = [self.gradient_x(img) for img in pyramid]
        image_gradients_y = [self.gradient_y(img) for img in pyramid]

        weights_x = [tf.exp(-tf.reduce_mean(tf.abs(g), 3, keepdims=True)) for g in image_gradients_x]
        weights_y = [tf.exp(-tf.reduce_mean(tf.abs(g), 3, keepdims=True)) for g in image_gradients_y]

        smoothness_x = [disp_gradients_x[i] * weights_x[i] for i in range(4)]
        smoothness_y = [disp_gradients_y[i] * weights_y[i] for i in range(4)]
        return smoothness_x + smoothness_y

    def SSIM(self, x, y):
        C1 = 0.01 ** 2
        C2 = 0.03 ** 2

        mu_x = slim.avg_pool2d(x, 3, 1, 'VALID')
        mu_y = slim.avg_pool2d(y, 3, 1, 'VALID')

        sigma_x  = slim.avg_pool2d(x ** 2, 3, 1, 'VALID') - mu_x ** 2
        sigma_y  = slim.avg_pool2d(y ** 2, 3, 1, 'VALID') - mu_y ** 2
        sigma_xy = slim.avg_pool2d(x * y , 3, 1, 'VALID') - mu_x * mu_y

        SSIM_n = (2 * mu_x * mu_y + C1) * (2 * sigma_xy + C2)
        SSIM_d = (mu_x ** 2 + mu_y ** 2 + C1) * (sigma_x + sigma_y + C2)

        SSIM = SSIM_n / SSIM_d

        return tf.clip_by_value((1 - SSIM) / 2, 0, 1)

    def upsample_nn(self, input, ratio):
        s = input.get_shape().as_list()
        h = s[1]
        w = s[2]
        nh = h * ratio
        nw = w * ratio
        output = Lambda(lambda x: tf.image.resize_nearest_neighbor(x, [nh, nw]))(input)
        output.set_shape(output_shape)
        return output

    def scale_pyramid(self, img, num_scales):
        scaled_imgs = [img]
        s = img.get_shape().as_list()
        h = s[1]
        w = s[2]
        tmp_h = h
        tmp_w = w
        nh = h
        nw = w
        for i in range(num_scales - 1):
            nh = nh // 2
            nw = nw // 2
            if  tmp_h % 2 != 0:
                nh = nh +1
            if  tmp_w % 2 != 0:
                nw = nw +1
            scaled_imgs.append(tf.image.resize_area(img, [nh, nw]))
            scaled_imgs[i+1].set_shape([s[0],nh,nw,s[3]])
            tmp_h = nh
            tmp_w = nw
        return scaled_imgs

    def get_variance(self, x):
        variance = self.conv(x, 3, 3, 1, activation='softplus')
        variance = Lambda(lambda x: 0.01 + x)(variance)
        return variance

    def get_depth(self, x):
        depth = self.conv(x, 1, 3, 1, activation='sigmoid')
        depth = Lambda(lambda x: 80.0 * x)(depth)
        return depth

    @staticmethod
    def conv(input, channels, kernel_size, strides, activation='elu'):

        return Conv2D(channels, kernel_size=kernel_size, strides=strides, padding='same', activation=activation)(input)

    @staticmethod
    def deconv(input, channels, kernel_size, scale):

        output =  Conv2DTranspose(channels, kernel_size=kernel_size, strides=scale, padding='same')(input)
        output_shape = output._keras_shape
        output.set_shape(output_shape)
        return output
    @staticmethod
    def maxpool(input, kernel_size):

        return MaxPooling2D(pool_size=kernel_size, strides=2, padding='same', data_format=None)(input)

    def conv_block(self, input, channels, kernel_size):
        conv1 = self.conv(input, channels, kernel_size, 1)

        conv2 = self.conv(conv1, channels, kernel_size, 2)

        return conv2

    def deconv_block(self, input, channels, kernel_size, skip):

        deconv1 = self.deconv(input, channels, kernel_size, 2)
        if skip is not None:
            s = skip.shape

            if  s[1] % 2 != 0:
                deconv1 = Lambda(lambda x: x[:,:-1,:,:])(deconv1)
            if  s[2] % 2 != 0:
                deconv1 = Lambda(lambda x: x[:,:,:-1,:])(deconv1)

            concat1 = concatenate([deconv1, skip], 3)
        else:
            concat1 = deconv1

        iconv1 = self.conv(concat1, channels, kernel_size, 1)
        return iconv1

    def build_depth_architecture(self):

        with tf.variable_scope('depth_model',reuse=self.reuse_variables):

            input = Input(batch_shape=self.left.get_shape().as_list())

            # encoder
            conv1 = self.conv_block(input, 32, 7)

            conv2 = self.conv_block(conv1, 64, 5)

            conv3 = self.conv_block(conv2, 128, 3)

            conv4 = self.conv_block(conv3, 256, 3)

            conv5 = self.conv_block(conv4, 512, 3)

            conv6 = self.conv_block(conv5, 512, 3)

            conv7 = self.conv_block(conv6, 512, 3)

            skip1 = conv1

            skip2 = conv2

            skip3 = conv3

            skip4 = conv4

            skip5 = conv5

            skip6 = conv6

            # decoder1
            deconv7 = self.deconv_block(conv7, 512, 3, skip6)

            deconv6 = self.deconv_block(deconv7, 512, 3, skip5)

            deconv5 = self.deconv_block(deconv6, 256, 3, skip4)

            deconv4 = self.deconv_block(deconv5, 128, 3, skip3)
            disp4 = self.get_depth(deconv4)

            deconv3 = self.deconv_block(deconv4, 64, 3, skip2)
            disp3 = self.get_depth(deconv3)

            deconv2 = self.deconv_block(deconv3, 32, 3, skip1)
            disp2 = self.get_depth(deconv2)

            deconv1 = self.deconv_block(deconv2, 16, 3, None)

            s = self.left.shape
            if  s[1] % 2 != 0:
                deconv1 = Lambda(lambda x: x[:,:-1,:,:])(deconv1)
            if  s[2] % 2 != 0:
                deconv1 = Lambda(lambda x: x[:,:,:-1,:])(deconv1)

            disp1 = self.get_depth(deconv1)

            # decoder2

            deconv4_2 = self.deconv_block(deconv5, 128, 3, skip3)
            disp4_2 = self.get_variance(deconv4_2)

            deconv3_2 = self.deconv_block(deconv4_2, 64, 3, skip2)
            disp3_2 = self.get_variance(deconv3_2)

            deconv2_2 = self.deconv_block(deconv3_2, 32, 3, skip1)
            disp2_2 = self.get_variance(deconv2_2)

            deconv1_2 = self.deconv_block(deconv2_2, 16, 3, None)

            s = self.left.shape
            if  s[1] % 2 != 0:
                deconv1_2 = Lambda(lambda x: x[:,:-1,:,:])(deconv1_2)
            if  s[2] % 2 != 0:
                deconv1_2 = Lambda(lambda x: x[:,:,:-1,:])(deconv1_2)

            disp1_2 = self.get_variance(deconv1_2)

            disp_est  = [disp1, disp2, disp3, disp4, disp1_2, disp2_2, disp3_2, disp4_2]

            self.depth_model = Model(input, disp_est)

    def build_pose_architecture(self):

        with tf.variable_scope('pose_model',reuse=self.reuse_variables):
            input1 = Input(batch_shape=self.left.get_shape().as_list())

            input2 = Input(batch_shape=self.left.get_shape().as_list())

            input = concatenate([input1,input2], axis=3)

            conv1 = self.conv(input, 16, 7, 2, activation='relu')

            conv2 = self.conv(conv1, 32, 5, 2, activation='relu')

            conv3 = self.conv(conv2, 64, 3, 2, activation='relu')

            conv4 = self.conv(conv3, 128, 3, 2, activation='relu')

            conv5 = self.conv(conv4, 256, 3, 2, activation='relu')

            conv6 = self.conv(conv5, 256, 3, 2, activation='relu')

            conv7 = self.conv(conv6, 512, 3, 2, activation='relu')

            dim = np.prod(conv7.shape[1:])

            flat1 = Lambda(lambda x: tf.reshape(x, [-1, dim]))(conv7)

            # translation
            fc1_tran = Dense(512, input_shape=(dim,))(flat1)

            fc2_tran = Dense(512, input_shape=(512,))(fc1_tran)

            fc3_tran = Dense(3, input_shape=(512,))(fc2_tran)

            # rotation
            fc1_rot = Dense(512, input_shape=(dim,))(flat1)

            fc2_rot = Dense(512, input_shape=(512,))(fc1_rot)

            fc3_rot = Dense(3, input_shape=(512,))(fc2_rot)

            # pose uncertainty
            fc1_unc = Dense(512, input_shape=(dim,))(flat1)

            fc2_unc = Dense(512, input_shape=(512,))(fc1_unc)

            fc3_unc = Dense(21, input_shape=(512,))(fc2_unc)#, activation = 'softplus'

            self.pose_model = Model([input1,input2], [fc3_tran, fc3_rot, fc3_unc])

    def build_model(self,img_left,img_right,img_left_next,img_right_next):
        with slim.arg_scope([slim.conv2d, slim.conv2d_transpose], activation_fn=tf.nn.elu):
#            with tf.variable_scope('model',reuse=self.reuse_variables):

            self.left_pyramid  = self.scale_pyramid(img_left,  4)
            self.right_pyramid  = self.scale_pyramid(img_right,  4)
            self.left_next_pyramid  = self.scale_pyramid(img_left_next,  4)
            self.right_next_pyramid  = self.scale_pyramid(img_right_next,  4)

            disp_left = self.depth_model(img_left)
            [disp_left[i].set_shape(disp_left[i]._keras_shape) for i in range(8)]
            disp_right = self.depth_model(img_right)
            [disp_right[i].set_shape(disp_right[i]._keras_shape) for i in range(8)]

            disp_left_next = self.depth_model(img_left_next)
            [disp_left_next[i].set_shape(disp_left_next[i]._keras_shape) for i in range(8)]
            disp_right_next = self.depth_model(img_right_next)
            [disp_right_next[i].set_shape(disp_right_next[i]._keras_shape) for i in range(8)]

            [left_trans, left_rot, left_unc] = self.pose_model([img_left,img_left_next])
            [right_trans, right_rot, right_unc] = self.pose_model([img_right,img_right_next])

        return disp_left, disp_right, disp_left_next, disp_right_next, left_trans, left_rot, right_trans, right_rot, left_unc, right_unc

    def build_outputs(self):
        if self.mode == 'test':
            return

        # generate depth maps
        self.disparity_left = [disparity_to_depth(self.depthmap_left[i], self.baseline, self.focal_length1_left, self.params.width, 'depthmap_left') for i in range(4)]
        self.disparity_right = [disparity_to_depth(self.depthmap_right[i], self.baseline, self.focal_length1_right, self.params.width, 'depthmap_right') for i in range(4)]
        self.disparity_left_next = [disparity_to_depth(self.depthmap_left_next[i], self.baseline, self.focal_length1_left, self.params.width, 'depthmap_left_next') for i in range(4)]
        self.disparity_right_next = [disparity_to_depth(self.depthmap_right_next[i], self.baseline, self.focal_length1_right, self.params.width, 'depthmap_right_next') for i in range(4)]

        # generate estimates of left and right images
        self.left_est  = [self.generate_image_left(self.right_pyramid[i], self.disparity_right[i]) for i in range(4)]
        self.right_est = [self.generate_image_right(self.left_pyramid[i], self.disparity_left[i]) for i in range(4)]
        self.left_next_est  = [self.generate_image_left(self.right_next_pyramid[i], self.disparity_right_next[i]) for i in range(4)]
        self.right_next_est = [self.generate_image_right(self.left_next_pyramid[i], self.disparity_left_next[i]) for i in range(4)]

        # generate k th image
        self.left_k = projective_transformer_inv(self.left_next, self.focal_length1_left, self.focal_length2_left , self.c0_left, self.c1_left, self.depthmap_left_next[0], self.rotation_left, self.translation_left)
        self.right_k = projective_transformer_inv(self.right_next, self.focal_length1_right, self.focal_length2_right , self.c0_right, self.c1_right, self.depthmap_right_next[0], self.rotation_right, self.translation_right)

        # generate k+1 th image
        self.left_k_plus_one = projective_transformer(self.left, self.focal_length1_left, self.focal_length2_left , self.c0_left, self.c1_left, self.depthmap_left[0], self.rotation_left, self.translation_left)
        self.right_k_plus_one = projective_transformer(self.right, self.focal_length1_right, self.focal_length2_right , self.c0_right, self.c1_right, self.depthmap_right[0], self.rotation_right, self.translation_right)

#        # DISPARITY SMOOTHNESS
#        self.disp_left_smoothness  = self.get_disparity_smoothness(self.disparity_left,  self.left_pyramid)
#        self.disp_right_smoothness = self.get_disparity_smoothness(self.disparity_right, self.right_pyramid)
#        self.disp_left_next_smoothness  = self.get_disparity_smoothness(self.disparity_left_next,  self.left_next_pyramid)
#        self.disp_right_next_smoothness = self.get_disparity_smoothness(self.disparity_right_next, self.right_next_pyramid)

    def compute_temporal_loss(self, img_syn, img, uncertainty):

        # make uncertainty matrix (Q)
        L = tf.contrib.distributions.fill_triangular(uncertainty)
        Lt = tf.transpose(L,perm=[0, 2, 1])
        self.Q = tf.matmul(L,Lt)

        # make residual uncertainty
        img_diffs = [tf.reshape(tf.abs(img_syn[i] - img),[self.params.batch_size,-1]) for i in range(7)]
        res_diffs = [tf.reduce_mean(tf.abs(img_diffs[0]-img_diffs[i]),1) for i in range(7)]

        diffs_part = tf.stack([10.0*res_diffs[1],10.0*res_diffs[2],10.0*res_diffs[3],100.0*res_diffs[4],100.0*res_diffs[5],100.0*res_diffs[6]], axis=1)
        diffs_part = tf.expand_dims(diffs_part,2)
        diffs_part_t = tf.transpose(diffs_part,perm=[0, 2, 1])
        res_uncertainty = tf.matmul(tf.matmul(diffs_part_t,self.Q),diffs_part)

        res_u_norm = tf.norm(res_uncertainty,axis=[1,2])
        res_u_norm = Lambda(lambda x: 0.01 + x)(res_u_norm)
        res_u_plus = Lambda(lambda x: 1.0 + x)(res_u_norm)

        # dist
        diffs = tf.reduce_mean(tf.reshape(tf.square(img_syn[0] - img),[self.params.batch_size,-1]),1)
        dist = tf.divide(diffs, res_u_norm) + tf.log(res_u_plus)

        return tf.reduce_mean(dist)

    def compute_spatial_loss(self, img_syn, img, uncertainty):

#        uncertainty_norm = [Lambda(lambda x: 0.0001 + x)(uncertainty[i])  for i in range(4)]
        uncertainty_plus = [Lambda(lambda x: 1.0 + x)(uncertainty[i])  for i in range(4)]
        loss = [tf.divide(tf.square( img_syn[i] - img[i]), uncertainty[i])+ tf.log(uncertainty_plus[i])  for i in range(4)]
        mean_loss  = [tf.reduce_mean(l) for l in loss]

        return mean_loss

#    def compute_temporal_loss(self, img_syn, img, uncertainty):

#        # make uncertainty matrix (Q)
#        L = tf.contrib.distributions.fill_triangular(uncertainty)
#        Lt = tf.transpose(L,perm=[0, 2, 1])
#        self.Q = tf.matmul(L,Lt)

#        # make residual uncertainty
#        diffs = tf.reshape(tf.square(img_syn[0] - img),[self.params.batch_size,-1])
#        img_diffs = [tf.reshape(tf.abs(img_syn[i] - img),[self.params.batch_size,-1]) for i in range(7)]
#        res_diffs = [tf.abs(img_diffs[0]-img_diffs[i]) for i in range(7)]

#        diffs_part = tf.stack([10.0*res_diffs[1],10.0*res_diffs[2],10.0*res_diffs[3],100.0*res_diffs[4],100.0*res_diffs[5],100.0*res_diffs[6]], axis=1)
#        diffs_part_t = tf.transpose(diffs_part,perm=[0, 2, 1])

#        res_mul = tf.matmul(diffs_part_t,self.Q)
#        res_mul2 =  tf.multiply(res_mul,diffs_part_t)
#        res_uncertainty = tf.reduce_sum(res_mul2,2)

##        tf.where(tf.greater(x,0.0), x, x+0.001
##        x_mean = tf.reduce_mean(res_uncertainty)
##        res_uncertainty_norm = Lambda(lambda x: tf.where(tf.greater(x,0.0), x, x+x_mean) )(res_uncertainty)
#        res_uncertainty_norm = Lambda(lambda x: 0.0001 + x)(res_uncertainty)
#        res_uncertainty_plus = Lambda(lambda x: 1.0 + x)(res_uncertainty)

#        # dist
#        dist = tf.divide(diffs, res_uncertainty_norm) + tf.log(res_uncertainty_plus)
#        dist = tf.reduce_mean(dist)

#        return dist

    def build_losses(self):
        with tf.variable_scope('losses', reuse=self.reuse_variables):
#            # PHOTOMETRIC CONSISTENCY (spatial loss)
#            self.image_loss_left = self.compute_spatial_loss(self.left_est, self.left_pyramid, self.depthmap_left[4:])
#            self.image_loss_right = self.compute_spatial_loss(self.right_est, self.right_pyramid, self.depthmap_right[4:])
#            self.image_loss_left_next = self.compute_spatial_loss(self.left_next_est, self.left_next_pyramid, self.depthmap_left_next[4:])
#            self.image_loss_right_next = self.compute_spatial_loss(self.right_next_est, self.right_next_pyramid, self.depthmap_right_next[4:])
#            self.image_loss = tf.add_n(self.image_loss_left + self.image_loss_right + self.image_loss_left_next + self.image_loss_right_next)

#            # DISPARITY SMOOTHNESS
#            self.disp_left_loss  = [tf.reduce_mean(tf.abs(self.disp_left_smoothness[i]))  / 2 ** i for i in range(4)]
#            self.disp_right_loss = [tf.reduce_mean(tf.abs(self.disp_right_smoothness[i])) / 2 ** i for i in range(4)]
#            self.disp_left_next_loss  = [tf.reduce_mean(tf.abs(self.disp_left_next_smoothness[i]))  / 2 ** i for i in range(4)]
#            self.disp_right_next_loss = [tf.reduce_mean(tf.abs(self.disp_right_next_smoothness[i])) / 2 ** i for i in range(4)]
#            self.disp_gradient_loss = tf.add_n(self.disp_left_loss + self.disp_right_loss + self.disp_left_next_loss + self.disp_right_next_loss)

            # PHOTOMETRIC REGISTRATION (temporal loss)
            self.l1_left_k_plus_one = self.compute_temporal_loss(self.left_k_plus_one, self.left_next, self.left_unc)
            self.l1_right_k_plus_one = self.compute_temporal_loss(self.right_k_plus_one, self.right_next,self.right_unc)
            self.l1_left_k = self.compute_temporal_loss(self.left_k, self.left,self.left_unc)
            self.l1_right_k = self.compute_temporal_loss(self.right_k, self.right,self.right_unc)
            self.image_loss_temporal = self.l1_left_k_plus_one + self.l1_left_k + self.l1_right_k_plus_one + self.l1_right_k

            # TOTAL LOSS
            self.total_loss = self.image_loss_temporal
#            self.total_loss = self.params.image_loss_weight * self.image_loss + self.params.temporal_loss_weight * self.image_loss_temporal + self.params.gradient_loss_weight * self.disp_gradient_loss

    def build_summaries(self):
        # SUMMARIES
        with tf.device('/cpu:0'):
#            tf.summary.scalar('image_loss', self.image_loss, collections=self.model_collection)
            tf.summary.scalar('image_loss_temporal', self.image_loss_temporal, collections=self.model_collection)
#            tf.summary.scalar('disp_gradient_loss', self.disp_gradient_loss, collections=self.model_collection)
            tf.summary.image('left_k_plus_one',  self.left_k_plus_one[0],   max_outputs=3, collections=self.model_collection)
            tf.summary.image('left_est', self.left_est[0],  max_outputs=3, collections=self.model_collection)
            tf.summary.image('left', self.left,  max_outputs=3, collections=self.model_collection)
            tf.summary.image('left_next',  self.left_next,   max_outputs=3, collections=self.model_collection)
            tf.summary.image('disparity_left',  self.disparity_left[0],   max_outputs=3, collections=self.model_collection)
            tf.summary.image('spatial_variance',  self.depthmap_left[4],   max_outputs=3, collections=self.model_collection)

            txtPredictions = tf.Print(tf.as_string(self.Q),[tf.as_string(self.Q)], message='predictions', name='txtPredictions')
            tf.summary.text('predictions', txtPredictions, collections=self.model_collection)


"""
Copyright 2012 VMware, Inc.  All rights reserved. -- VMware Confidential

vProbe component installer.
"""
DEST = LIBDIR/'vmware'
class Vprobe(Installer):
   def InitializeInstall(self, old, new, upgrade):
      self.AddTarget('File', 'lib/bin/*', DEST/'bin')
      self.AddTarget('File', 'bin/*', BINDIR)

      self.SetPermission(DEST/'*', BINARY)
      self.SetPermission(BINDIR/'*', BINARY)


from persistor import Persistor
from utils.tickers import Tickers
from utils.metricnames import MetricNames

def main():

    persistor = Persistor()

    tickers = Tickers()
    metrics = MetricNames()

    for ticker in tickers.get_us_tickers():
        for metric in metrics.get_profitability_metrics():
            df = persistor.read_pickle('pickle', ticker, metric, 'profitability')
            if df is not None:
                persistor.write_dataframe_to_json_quarterly_basis('json/', ticker, metric, df, 'profitability')
            else:
                print(ticker + ' '  + metric + ' ' + 'dataframe doesn\'t exits')

if __name__ == '__main__':
    main()


from tkinter import *

#draws circle on board
def drawCircle(x, y):
    canvas_1.create_oval(x - 100, y  - 100, x + 100, y + 100, fill = "red", width = 3)

#draws non-religious cross on board
def drawNonReligiousCross(x, y):
    canvas_1.create_line(x - 100, y - 100, x + 100, y + 100, fill = "red", width = 3)
    canvas_1.create_line(x + 100, y - 100, x - 100, y + 100, fill = "red", width = 3)

def coordinateCheck(x, y):

    boardOvalX = 0
    boardOvalY = 0

    #checks x position of mouse click
    if (x == 0):                     #added to remove inital value of mouse click (error handler)
        boardOvalX = 0
    elif (x <= 250):
        boardOvalX = 1
    elif (x > 250 and x <= 500):
        boardOvalX = 2
    else:
        boardOvalX = 3

    #checks y position of mouse click
    if (y == 0):                     #added to remove inital value of mouse click (error handler)
        boardOvalY = 0
    elif (y <= 250):
        boardOvalY = 1
    elif (y > 250 and y <= 500):
        boardOvalY = 2
    else:
        boardOvalY = 3

    return str(boardOvalX) + str(boardOvalY)

#creates global variable for coordinates need to get coords from playerInput function
mouseX = 0
mouseY = 0
coordinates = '0'
gameWinner = 0

#gets mouse click and sets input to global variables: mouseX and mouseY
def playerInput(event):

    global gameWinner

    if (gameWinner != 0):
        return

    global mouseX, mouseY, clickError, turn

    mouseX, mouseY = event.x, event.y

    #converts mouse click into coordinates
    global coordinates

    #calls function that figures out which oval was clicked
    coordinates = coordinateCheck(mouseX, mouseY)

    #error handler that sees if oval clicked was previously owned
    legalMoveFlag = legalMoveCheck(coordinates)

    #checks to see if move clicked was legal
    if legalMoveFlag == 0:

        #draws legal clicked oval on board
        updateBoardOval(coordinates)

        #error handler for ending game message
        if (gameWinner == 0):
            updateTurn()

        #checks for end of game
        gameLogic()

        #error hangler making sure players second move is actually player 1's move (DO NOT REMOVE!)
        if turn == 1:
            updateTurn()

        #calls function to have computer place a move on the board
        getComputerMove()

        #checks for end of game
        gameLogic()

        #error hangler for ending game message
        if (gameWinner == 0):
            updateTurn()

#sets root to canvas funtion
root = Tk()
root2 = Tk()

#canvas size
CanWidth = 750
CanHeight = 750

#initializes canvas_1 which displays board
canvas_1 = Canvas(root, width = CanWidth, height = CanHeight)

#initializes canvas_2 which displays player information/winner condition
canvas_2 = Canvas(root2, width = 350, height = 200)

#title of canvas canvas_1 is generating
root.title('Tic Tac Toe')

#sets grid for canvas_1
canvas_1.grid(row = 0, column = 1)

#sets grid for canvas_2
canvas_2.grid(row = 0, column = 1)

#welcoime to the game!
canvas_2.create_text(175, 100, fill = "blue", font = "Times 20 italic bold", text = "Welcome! Click to begin.")

#draws the lines dividing the tic-tac-toe boxes
canvas_1.create_line(250, 0, 250, 750, fill = "blue", width = 3)
canvas_1.create_line(500, 0, 500, 750, fill = "blue", width = 3)
canvas_1.create_line(0, 250, 750, 250, fill = "blue", width = 3)
canvas_1.create_line(0, 500, 750, 500, fill = "blue", width = 3)

#gets size of screen game is being run on
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()

#calculate position x and y coordinates and then sets canvas_1 location to center of screen
x = (screen_width / 2) - (CanWidth / 2)
y = (screen_height / 2) - (CanHeight / 2)
root.geometry('%dx%d+%d+%d' % (CanWidth, CanHeight, x, y))

#checks for player mouse input
canvas_1.bind("<Button-1>", playerInput)

#oval class definition
class oval():
    def __init__(self, x, y, owner):
        self.x = x
        self.y = y
        self.owner = owner

#list created to hold all of board ovals
boardOvals = [0, 1, 2, 3, 4, 5, 6, 7, 8]

#manual creation of all 9 board ovals
boardOvals[0] = oval(125, 125, 0)
boardOvals[1] = oval(375, 125, 0)
boardOvals[2] = oval(625, 125, 0)
boardOvals[3] = oval(125, 375, 0)
boardOvals[4] = oval(375, 375, 0)
boardOvals[5] = oval(625, 375, 0)
boardOvals[6] = oval(125, 625, 0)
boardOvals[7] = oval(375, 625, 0)
boardOvals[8] = oval(625, 625, 0)

#draw shape on board based on user input
def updateBoardOval(string):

    global player, playerMoves, turn

    if turn == 1:
        player = player + 1

    if string == '11':
        boardOvals[0].owner = player
        if boardOvals[0].owner == 1:
            drawCircle(boardOvals[0].x, boardOvals[0].y)
            playerMoves[0] = 1
        elif boardOvals[0].owner == 2:
            drawNonReligiousCross(boardOvals[0].x, boardOvals[0].y)
    elif string == '21':
        boardOvals[1].owner = player
        if boardOvals[1].owner == 1:
            drawCircle(boardOvals[1].x, boardOvals[1].y)
            playerMoves[1] = 1
        elif boardOvals[1].owner == 2:
            drawNonReligiousCross(boardOvals[1].x, boardOvals[1].y)
    elif string == '31':
        boardOvals[2].owner = player
        if boardOvals[2].owner == 1:
            drawCircle(boardOvals[2].x, boardOvals[2].y)
            playerMoves[2] = 1
        elif boardOvals[2].owner == 2:
            drawNonReligiousCross(boardOvals[2].x, boardOvals[2].y)
    elif string == '12':
        boardOvals[3].owner = player
        if boardOvals[3].owner == 1:
            drawCircle(boardOvals[3].x, boardOvals[3].y)
            playerMoves[3] = 1
        elif boardOvals[3].owner == 2:
            drawNonReligiousCross(boardOvals[3].x, boardOvals[3].y)
    elif string == '22':
        boardOvals[4].owner = player
        if boardOvals[4].owner == 1:
            drawCircle(boardOvals[4].x, boardOvals[4].y)
            playerMoves[4] = 1
        elif boardOvals[4].owner == 2:
            drawNonReligiousCross(boardOvals[4].x, boardOvals[4].y)
    elif string == '32':
        boardOvals[5].owner = player
        if boardOvals[5].owner == 1:
            drawCircle(boardOvals[5].x, boardOvals[5].y)
            playerMoves[5] = 1
        elif boardOvals[5].owner == 2:
            drawNonReligiousCross(boardOvals[5].x, boardOvals[5].y)
    elif string == '13':
        boardOvals[6].owner = player
        if boardOvals[6].owner == 1:
            drawCircle(boardOvals[6].x, boardOvals[6].y)
            playerMoves[6] = 1
        elif boardOvals[6].owner == 2:
            drawNonReligiousCross(boardOvals[6].x, boardOvals[6].y)
    elif string == '23':
        boardOvals[7].owner = player
        if boardOvals[7].owner == 1:
            drawCircle(boardOvals[7].x, boardOvals[7].y)
            playerMoves[7] = 1
        elif boardOvals[7].owner == 2:
            drawNonReligiousCross(boardOvals[7].x, boardOvals[7].y)
    else:
        boardOvals[8].owner = player
        if boardOvals[8].owner == 1:
            drawCircle(boardOvals[8].x, boardOvals[8].y)
            playerMoves[8] = 1
        elif boardOvals[8].owner == 2:
            drawNonReligiousCross(boardOvals[8].x, boardOvals[8].y)

def legalMoveCheck(string):
    if string == '11':
        if boardOvals[0].owner == 0:
            return 0
    elif string == '21':
        if boardOvals[1].owner == 0:
            return 0
    elif string == '31':
        if boardOvals[2].owner == 0:
            return 0
    elif string == '12':
        if boardOvals[3].owner == 0:
            return 0
    elif string == '22':
        if boardOvals[4].owner == 0:
            return 0
    elif string == '32':
        if boardOvals[5].owner == 0:
            return 0
    elif string == '13':
        if boardOvals[6].owner == 0:
            return 0
    elif string == '23':
        if boardOvals[7].owner == 0:
            return 0
    elif string == '33':
        if boardOvals[8].owner == 0:
            return 0
    else:
        return 1

#global variable to keep track of turn
turn = 0
player = 1

def updateTurn():

    global turn, player

    turn = turn + 1

    #player 2
    if (turn % 2 == 0):
        player = 2
        canvas_2.delete("all")
        canvas_2.create_text(175, 100, fill = "blue", font = "Times 20 italic bold", text = "Player 2's turn!")

    #player 1
    else:
        player = 1
        canvas_2.delete("all")
        canvas_2.create_text(175, 100, fill = "blue", font = "Times 20 italic bold", text = "Player 1's turn!")

def gameLogic():

    global gameWinner

    if (boardOvals[0].owner == boardOvals[1].owner and boardOvals[1].owner == boardOvals[2].owner) and boardOvals[0].owner != 0:
        gameWinner = boardOvals[0].owner
        canvas_1.create_line(10, 125, 740, 125, fill = "black", width = 3)
    elif (boardOvals[3].owner == boardOvals[4].owner and boardOvals[4].owner == boardOvals[5].owner) and boardOvals[3].owner != 0:
        gameWinner = boardOvals[3].owner
        canvas_1.create_line(10, 375, 740, 375, fill = "black", width = 3)
    elif (boardOvals[6].owner == boardOvals[7].owner and boardOvals[7].owner == boardOvals[8].owner) and boardOvals[6].owner != 0:
        gameWinner = boardOvals[6].owner
        canvas_1.create_line(10, 625, 740, 625, fill = "black", width = 3)
    elif (boardOvals[0].owner == boardOvals[4].owner and boardOvals[4].owner == boardOvals[8].owner) and boardOvals[0].owner != 0:
        gameWinner = boardOvals[0].owner
        canvas_1.create_line(10, 10, 740, 740, fill = "black", width = 3)
    elif (boardOvals[2].owner == boardOvals[4].owner and boardOvals[4].owner == boardOvals[6].owner) and boardOvals[2].owner != 0:
        gameWinner = boardOvals[2].owner
        canvas_1.create_line(740, 10, 10, 740, fill = "black", width = 3)
    elif (boardOvals[0].owner == boardOvals[3].owner and boardOvals[3].owner == boardOvals[6].owner) and boardOvals[0].owner != 0:
        gameWinner = boardOvals[0].owner
        canvas_1.create_line(125, 10, 125, 740, fill = "black", width = 3)
    elif (boardOvals[1].owner == boardOvals[4].owner and boardOvals[4].owner == boardOvals[7].owner) and boardOvals[1].owner != 0:
        gameWinner = boardOvals[1].owner
        canvas_1.create_line(375, 10, 375, 740, fill = "black", width = 3)
    elif (boardOvals[2].owner == boardOvals[5].owner and boardOvals[5].owner == boardOvals[8].owner) and boardOvals[2].owner != 0:
        gameWinner = boardOvals[2].owner
        canvas_1.create_line(625, 10, 625, 740, fill = "black", width = 3)

    if gameWinner == 1:
        canvas_2.delete("all")
        canvas_2.create_text(175, 100, fill = "blue", font = "Times 20 italic bold", text = "Player 1 Wins!")
    elif gameWinner == 2:
        canvas_2.delete("all")
        canvas_2.create_text(175, 100, fill = "blue", font = "Times 20 italic bold", text = "Computer Wins!")

playerMoves = [0, 0, 0, 0, 0, 0, 0, 0, 0]

#defensive ai for now
def getComputerMove():

    global coordinates, playerMoves, turn

    if (turn == 2):
        #reacts to players first move row one
        if (playerMoves[0] + playerMoves[1] + playerMoves[2] == 1):
            if (playerMoves[0] == 1 and boardOvals[1].owner == 0):
                boardOvals[1].owner = 2
                coordinates = '21'
                updateBoardOval(coordinates)
                return
            if (playerMoves[1] == 1 and boardOvals[1].owner == 0):
                boardOvals[2].owner = 2
                coordinates = '31'
                updateBoardOval(coordinates)
                return
            if (playerMoves[2] == 1 and boardOvals[1].owner == 0):
                boardOvals[1].owner = 2
                coordinates = '21'
                updateBoardOval(coordinates)
                return

        #reacts to players first move row two
        if (playerMoves[3] + playerMoves[4] + playerMoves[5] == 1):
            if (playerMoves[3] == 1 and boardOvals[1].owner == 0):
                boardOvals[4].owner = 2
                coordinates = '22'
                updateBoardOval(coordinates)
                return
            if (playerMoves[4] == 1 and boardOvals[1].owner == 0):
                boardOvals[3].owner = 2
                coordinates = '12'
                updateBoardOval(coordinates)
                return
            if (playerMoves[5] == 1 and boardOvals[1].owner == 0):
                boardOvals[4].owner = 2
                coordinates = '22'
                updateBoardOval(coordinates)
                return

        #reacts to players first move row three
        if (playerMoves[6] + playerMoves[7] + playerMoves[8] == 1):
            if (playerMoves[6] == 1 and boardOvals[1].owner == 0):
                boardOvals[7].owner = 2
                coordinates = '23'
                updateBoardOval(coordinates)
                return
            if (playerMoves[7] == 1 and boardOvals[1].owner == 0):
                boardOvals[6].owner = 2
                coordinates = '13'
                updateBoardOval(coordinates)
                return
            if (playerMoves[8] == 1 and boardOvals[1].owner == 0):
                boardOvals[7].owner = 2
                coordinates = '23'
                updateBoardOval(coordinates)
                return

    #checks to block players moves diagonally top left to bottom right
    if (playerMoves[0] + playerMoves[4] + playerMoves[8] >= 2):
        if (playerMoves[0] != 1 and boardOvals[0].owner == 0):
            boardOvals[0].owner = 2
            coordinates = '11'
            updateBoardOval(coordinates)
            return
        if (playerMoves[4] != 1 and boardOvals[4].owner == 0):
            boardOvals[4].owner = 2
            coordinates = '22'
            updateBoardOval(coordinates)
            return
        if (playerMoves[8] != 1 and boardOvals[8].owner == 0):
            boardOvals[8].owner = 2
            coordinates = '33'
            updateBoardOval(coordinates)
            return

    #checks to block players moves diagonally top right to bottom left
    if (playerMoves[2] + playerMoves[4] + playerMoves[6] >= 2):
        if (playerMoves[2] != 1 and boardOvals[2].owner == 0):
            boardOvals[2].owner = 2
            coordinates = '31'
            updateBoardOval(coordinates)
            return
        if (playerMoves[4] != 1 and boardOvals[4].owner == 0):
            boardOvals[4].owner = 2
            coordinates = '22'
            updateBoardOval(coordinates)
            return
        if (playerMoves[6] != 1 and boardOvals[6].owner == 0):
            boardOvals[6].owner = 2
            coordinates = '13'
            updateBoardOval(coordinates)
            return

    #checks to block players moves horizontally top row
    if (playerMoves[0] + playerMoves[1] + playerMoves[2] >= 2):
        if (playerMoves[0] != 1 and boardOvals[0].owner == 0):
            boardOvals[0].owner = 2
            coordinates = '11'
            updateBoardOval(coordinates)
            return
        if (playerMoves[1] != 1 and boardOvals[1].owner == 0):
            boardOvals[1].owner = 2
            coordinates = '21'
            updateBoardOval(coordinates)
            return
        if (playerMoves[2] != 1 and boardOvals[2].owner == 0):
            boardOvals[2].owner = 2
            coordinates = '31'
            updateBoardOval(coordinates)
            return

    #checks to block players moves horizontally middle row
    if (playerMoves[3] + playerMoves[4] + playerMoves[5] >= 2):
        if (playerMoves[3] != 1 and boardOvals[3].owner == 0):
            boardOvals[3].owner = 2
            coordinates = '21'
            updateBoardOval(coordinates)
            return
        if (playerMoves[4] != 1 and boardOvals[4].owner == 0):
            boardOvals[4].owner = 2
            coordinates = '22'
            updateBoardOval(coordinates)
            return
        if (playerMoves[5] != 1 and boardOvals[5].owner == 0):
            boardOvals[5].owner = 2
            coordinates = '32'
            updateBoardOval(coordinates)
            return

    #checks to block players moves horizontally bottom row
    if (playerMoves[6] + playerMoves[7] + playerMoves[8] >= 2):
        if (playerMoves[6] != 1 and boardOvals[6].owner == 0):
            boardOvals[6].owner = 2
            coordinates = '13'
            updateBoardOval(coordinates)
            return
        if (playerMoves[7] != 1 and boardOvals[7].owner == 0):
            boardOvals[7].owner = 2
            coordinates = '23'
            updateBoardOval(coordinates)
            return
        if (playerMoves[8] != 1 and boardOvals[8].owner == 0):
            boardOvals[8].owner = 2
            coordinates = '33'
            updateBoardOval(coordinates)
            return

   #checks to block players moves vertically first row
    if (playerMoves[0] + playerMoves[3] + playerMoves[6] >= 2):
        if (playerMoves[0] != 1 and boardOvals[0].owner == 0):
            boardOvals[0].owner = 2
            coordinates = '11'
            updateBoardOval(coordinates)
            return
        if (playerMoves[3] != 1 and boardOvals[3].owner == 0):
            boardOvals[3].owner = 2
            coordinates = '12'
            updateBoardOval(coordinates)
            return
        if (playerMoves[6] != 1 and boardOvals[6].owner == 0):
            boardOvals[6].owner = 2
            coordinates = '13'
            updateBoardOval(coordinates)
            return

    #checks to block players moves vertically second row
    if (playerMoves[1] + playerMoves[4] + playerMoves[7] >= 2):
        if (playerMoves[1] != 1 and boardOvals[1].owner == 0):
            boardOvals[1].owner = 2
            coordinates = '21'
            updateBoardOval(coordinates)
            return
        if (playerMoves[4] != 1 and boardOvals[4].owner == 0):
            boardOvals[4].owner = 2
            coordinates = '22'
            updateBoardOval(coordinates)
            return
        if (playerMoves[7] != 1 and boardOvals[7].owner == 0):
            boardOvals[7].owner = 2
            coordinates = '23'
            updateBoardOval(coordinates)
            return

    #checks to block players moves vertically last row
    if (playerMoves[2] + playerMoves[5] + playerMoves[8] >= 2):
        if (playerMoves[2] != 1 and boardOvals[2].owner == 0):
            boardOvals[2].owner = 2
            coordinates = '31'
            updateBoardOval(coordinates)
            return
        if (playerMoves[5] != 1 and boardOvals[5].owner == 0):
            boardOvals[5].owner = 2
            coordinates = '32'
            updateBoardOval(coordinates)
            return
        if (playerMoves[8] != 1 and boardOvals[8].owner == 0):
            boardOvals[8].owner = 2
            coordinates = '33'
            updateBoardOval(coordinates)
            return

    i = 0

    #backup possibility incase other statements do not find an answer
    for i in range(0, 8):
        if (boardOvals[i].owner == 0):
            boardOvals[i].owner = 2

            if (i == 0):
                coordinates = '11'
            if (i == 1):
                coordinates = '21'
            if (i == 2):
                coordinates = '31'
            if (i == 3):
                coordinates = '12'
            if (i == 4):
                coordinates = '22'
            if (i == 5):
                coordinates = '32'
            if (i == 6):
                coordinates = '13'
            if (i == 7):
                coordinates = '23'
            if (i == 8):
                coordinates = '33'

            updateBoardOval(coordinates)
            return


import libtcodpy as libtcod
import math
import textwrap
import shelve

#CONSTANTS
LIMIT_FPS = 20

#screen
SCREEN_WIDTH = 80
SCREEN_HEIGHT = 50

#GUI
PANEL_HEIGHT = 7
BAR_WIDTH = 20
PANEL_Y = SCREEN_HEIGHT - PANEL_HEIGHT
MSG_X = BAR_WIDTH + 2
MSG_WIDTH  = SCREEN_WIDTH - BAR_WIDTH - 2
MSG_HEIGHT = PANEL_HEIGHT - 1
INVENTORY_WIDTH = 50
LEVEL_SCREEN_WIDTH = 40
CHARACTER_SCREEN_WIDTH = 30

#map
MAP_WIDTH = 80
MAP_HEIGHT = 43

ROOM_MAX_SIZE = 10
ROOM_MIN_SIZE = 6
MAX_ROOMS = 30

#fov
FOV_ALGO = 0
FOV_LIGHT_WALLS = True
TORCH_RADIUS = 10

#items
HEAL_AMOUNT = 40
LIGHTNING_RANGE = 5
LIGHTNING_DAMAGE = 40
CONFUSE_DURATION = 10
CONFUSE_RANGE = 8
FIREBALL_RADIUS = 3
FIREBALL_DAMAGE = 25

#xp
LEVEL_UP_BASE = 200
LEVEL_UP_FACTOR = 150

#colors
color_dark_wall = libtcod.Color(0, 0, 100)
color_light_wall = libtcod.Color(130, 110, 50)
color_dark_ground = libtcod.Color(50, 50, 150)
color_light_ground = libtcod.Color(200, 180, 50)

#consoles
con = libtcod.console_new(SCREEN_WIDTH, SCREEN_HEIGHT)
panel = libtcod.console_new(SCREEN_WIDTH, PANEL_HEIGHT)

#objects
class Object:
    def __init__(self, x, y, char, name, color, blocks=False, always_visible=False, fighter = None, ai = None, item = None, equipment = None):
        self.x = x
        self.y = y
        self.char = char
        self.color = color
        self.name = name
        self.blocks = blocks
        self.fighter = fighter
        self.always_visible = always_visible
        if self.fighter:
            self.fighter.owner = self

        self.ai = ai
        if self.ai:
            self.ai.owner = self

        self.item = item
        if self.item:
            self.item.owner = self

        self.equipment = equipment
        if self.equipment:
            self.equipment.owner = self
            self.item = Item()
            self.item.owner = self

    def move(self, dx, dy):
        if not is_blocked(self.x + dx, self.y + dy):
            self.x += dx
            self.y += dy

    def move_towards(self, target_x, target_y):
        dx = target_x - self.x
        dy = target_y - self.y
        distance = math.sqrt(dx ** 2 + dy ** 2)
        dx = int(round(dx / distance))
        dy = int(round(dy / distance))
        self.move(dx, dy)

    def distance(self, x, y):
        return math.sqrt((x - self.x) ** 2 + (y- self.y) ** 2)

    def distance_to(self, other):
        dx = other.x - self.x
        dy = other.y - self.y
        return math.sqrt(dx ** 2 + dy ** 2)

    def draw(self):
        if (libtcod.map_is_in_fov(fov_map, self.x, self.y) or (self.always_visible and map[self.x][self.y].explored)):
            libtcod.console_set_default_foreground(con, self.color)
            libtcod.console_put_char(con, self.x, self.y, self.char, libtcod.BKGND_NONE)

    def send_to_back(self):
        global objects
        objects.remove(self)
        objects.insert(0, self)

    def clear(self):
        libtcod.console_put_char(con, self.x, self.y, ' ', libtcod.BKGND_NONE)

class Fighter:
    def __init__(self, hp, defense, power, xp, death_function = None):
        self.base_max_hp = hp
        self.hp = hp
        self.base_defense = defense
        self.base_power = power
        self.xp = xp
        self.death_function = death_function

    @property
    def power(self):
        bonus = sum(equipment.power_bonus for equipment in get_all_equipped(self.owner))
        return self.base_power + bonus

    @property
    def defense(self):
        bonus = sum(equipment.defense_bonus for equipment in get_all_equipped(self.owner))
        return self.base_defense + bonus

    @property
    def max_hp(self):
        bonus = sum(equipment.max_hp_bonus for equipment in get_all_equipped(self.owner))
        return self.base_max_hp + bonus

    def take_damage(self, damage):
        if damage > 0:
            self.hp -= damage
            if self.hp <= 0:
                function = self.death_function
                if function is not None:
                    function(self.owner)
                if self.owner != player:
                    player.fighter.xp += self.xp

    def attack(self, target):
        damage = self.power - target.fighter.defense

        if damage > 0:
            message(self.owner.name.capitalize() + ' attacks ' + target.name + ' for ' + str(damage) + ' hit points.', libtcod.red)
            target.fighter.take_damage(damage)
        else:
            message(self.owner.name.capitalize() + ' misses ' + target.name, libtcod.yellow)

    def heal(self, amount):
        self.hp += amount

        if self.hp > self.max_hp:
            self.hp = self.max_hp

class BasicMonster:
    def take_turn(self):
        monster = self.owner
        if libtcod.map_is_in_fov(fov_map, monster.x, monster.y):
            if monster.distance_to(player) >= 2:
                monster.move_towards(player.x, player.y)
            elif player.fighter.hp > 0:
                monster.fighter.attack(player)

class ConfusedMonster:
    def __init__(self, old_ai, num_turns=CONFUSE_DURATION):
        self.old_ai = old_ai
        self.num_turns = num_turns
    def take_turn(self):
        if self.num_turns > 0:
            self.owner.move(libtcod.random_get_int(0, -1, 1), libtcod.random_get_int(0, -1, 1))
            self.num_turns -= 1
        else:
            self.owner.ai = self.old_ai
            message('The ' + self.owner.name + ' is no longer confused!', libtcod.red)

class Tile:
    def __init__(self, blocked, block_sight = None):
        self.blocked = blocked
        self.explored = False

        if block_sight is None:
            block_sight = blocked
        self.block_sight = block_sight

class Rect:
    def __init__(self, x, y, w, h):
        self.x1 = x
        self.y1 = y
        self.x2 = x + w
        self.y2 = y + h

    def center(self):
        center_x = (self.x1 + self.x2) / 2
        center_y = (self.y1 + self.y2) / 2
        return (center_x, center_y)

    def intersect(self, other):
        return (self.x1 <= other.x2 and self.x2 >= other.x1 and
                self.y1 <= other.y2 and self.y2 >= other.y1)

class Item:
    def __init__(self, use_function=None):
        self.use_function = use_function
    def pick_up(self):
        if len(inventory) >= 26:
            message('Your inventory is full, cannot pick up ' + self.owner.name + '.', libtcod.red)
        else:
            inventory.append(self.owner)
            objects.remove(self.owner)
            message('You picked up a ' + self.owner.name + '!', libtcod.green)
        equipment = self.owner.equipment
        if equipment and get_equipped_in_slot(equipment.slot) is None:
            equipment.equip()

    def use(self):
        if self.owner.equipment:
            self.owner.equipment.toggle_equip()
            return

        if self.use_function is None:
            message('The ' + self.owner.name + ' cannot be used.')
        else:
            if self.use_function() != 'cancelled':
                inventory.remove(self.owner)

    def drop(self):
        objects.append(self.owner)
        inventory.remove(self.owner)
        self.owner.x = player.x
        self.owner.y = player.y
        if self.owner.equipment:
            self.owner.equipment.dequip()
        message('You dropped a ' + self.owner.name + '.', libtcod.yellow)

class Equipment:
    def __init__(self, slot, power_bonus=0, defense_bonus=0, max_hp_bonus=0):
        self.power_bonus = power_bonus
        self.defense_bonus = defense_bonus
        self.max_hp_bonus = max_hp_bonus
        self.slot = slot
        self.is_equipped = False

    def toggle_equip(self):
        if self.is_equipped:
            self.dequip()
        else:
            self.equip()

    def equip(self):
        old_equipment = get_equipped_in_slot(self.slot)
        if old_equipment is not None:
            old_equipment.dequip()
        self.is_equipped = True
        message('Equiped ' + self.owner.name + ' on ' + self.slot + '.', libtcod.light_green)

    def dequip(self):
        if not self.is_equipped:
            return
        self.is_equipped = False
        message('Dequiped ' + self.owner.name + ' from ' + self.slot + '.', libtcod.light_yellow)

#map generation
def create_room(room):
    global map

    for x in range(room.x1 + 1, room.x2):
        for y in range(room.y1 + 1, room.y2):
            map[x][y].blocked = False
            map[x][y].block_sight = False

def create_h_tunnel(x1, x2, y):
    global map
    for x in range(min(x1, x2), max(x1, x2) + 1):
        map[x][y].blocked = False
        map[x][y].block_sight = False

def create_v_tunnel(y1, y2, x):
    global map
    for y in range(min(y1, y2), max(y1, y2) + 1):
        map[x][y].blocked = False
        map[x][y].block_sight = False

def random_choice_index(chances):
    dice = libtcod.random_get_int(0, 1, sum(chances))

    running_sum = 0
    choice = 0
    for chance in chances:
        running_sum += chance

        if dice <= running_sum:
            return choice
        choice += 1

def random_choice(chances_dict):
    chances = chances_dict.values()
    names = chances_dict.keys()
    return names[random_choice_index(chances)]

def from_dungeon_level(table):
    for (value, level) in reversed(table):
        if dungeon_level >= level:
            return value
    return 0

def place_objects(room):
    max_monsters = from_dungeon_level([[2, 1], [3, 4], [5, 6]])
    monster_chances = {}
    monster_chances['orc'] = 80
    monster_chances['troll'] = from_dungeon_level([[15, 3], [30, 5], [60, 7]])

    max_items = from_dungeon_level([[1, 1], [2, 4]])
    item_chances = {}
    item_chances['healing'] = 35
    item_chances['lightning'] =  from_dungeon_level([[25, 4]])
    item_chances['fireball'] = from_dungeon_level([[25, 6]])
    item_chances['confusion'] = from_dungeon_level([[10, 2]])
    item_chances['sword'] = from_dungeon_level([[5, 4]])
    item_chances['shield'] = from_dungeon_level([[15, 8]])

    num_monsters = libtcod.random_get_int(0, 0, max_monsters)
    num_items = libtcod.random_get_int(0, 0, max_items)

    for i in range(num_monsters):
        x = libtcod.random_get_int(0, room.x1+1, room.x2-1)
        y = libtcod.random_get_int(0, room.y1+1, room.y2-1)
        if not is_blocked(x, y):
            choice = random_choice(monster_chances)
            if choice == 'orc':
                fighter_component = Fighter(hp=20, defense=0, power=4, xp=35, death_function=monster_death)
                ai_component = BasicMonster()
                monster = Object(x, y, 'o', 'orc', libtcod.desaturated_green, blocks=True, fighter=fighter_component, ai=ai_component)
            elif choice == 'troll':
                fighter_component = Fighter(hp=30, defense=2, power=8, xp=100, death_function=monster_death)
                ai_component = BasicMonster()
                monster = Object(x, y, 'T', 'troll', libtcod.darker_green, blocks=True, fighter=fighter_component, ai=ai_component)
            objects.append(monster)

    for i in range(num_items):
        x = libtcod.random_get_int(0, room.x1+1, room.x2-1)
        y = libtcod.random_get_int(0, room.y1+1, room.y2-1)
        if not is_blocked(x, y):
            choice = random_choice(item_chances)
            if choice == 'healing':
                item_component = Item(use_function=use_healing_potion)
                item = Object(x, y, '!', 'healing potion', libtcod.violet, item=item_component)
            elif choice == 'lightning':
                item_component = Item(use_function=cast_lightning_bolt)
                item = Object(x, y, '#', 'scroll of lightning bolt', libtcod.light_yellow, item=item_component)
            elif choice == 'fireball':
                item_component = Item(use_function=cast_fireball)
                item = Object(x, y, '#', 'scroll of fireball', libtcod.light_yellow, item=item_component)
            elif choice == 'confusion':
                item_component = Item(use_function=cast_confuse)
                item = Object(x, y, '#', 'scroll of confuse', libtcod.light_yellow, item = item_component)
            elif choice == 'sword':
                equipment_component = Equipment(slot='right hand', power_bonus=3)
                item = Object(x, y, '/', 'sword', libtcod.sky, equipment=equipment_component)
            elif choice == 'shield':
                equipment_component = Equipment(slot='left hand', defense_bonus=1)
                item = Object(x, y, '[', 'shield', libtcod.darker_orange, equipment=equipment_component)

            objects.append(item)
            item.send_to_back()
            item.always_visible = True

def make_map():
    global map, objects, stairs

    objects = [player]

    map = [[ Tile(True)
        for y in range(MAP_HEIGHT) ]
            for x in range(MAP_WIDTH) ]

    rooms = []
    num_rooms = 0
    for r in range(MAX_ROOMS):
        w = libtcod.random_get_int(0, ROOM_MIN_SIZE, ROOM_MAX_SIZE)
        h = libtcod.random_get_int(0, ROOM_MIN_SIZE, ROOM_MAX_SIZE)

        x = libtcod.random_get_int(0, 0, MAP_WIDTH - w - 1)
        y = libtcod.random_get_int(0, 0, MAP_HEIGHT - h - 1)

        new_room = Rect(x, y, w, h)
        failed = False
        for other_room in rooms:
            if new_room.intersect(other_room):
                failed = True
                break
        if not failed:
            create_room(new_room)

            place_objects(new_room)

            (new_x, new_y) = new_room.center()

            if num_rooms == 0:
                player.x = new_x
                player.y = new_y
            else:
                (prev_x, prev_y) = rooms[num_rooms-1].center()

                if libtcod.random_get_int(0, 0, 1) == 1:
                    create_h_tunnel(prev_x, new_x, prev_y)
                    create_v_tunnel(prev_y, new_y, new_x)
                else:
                    create_v_tunnel(prev_y, new_y, prev_x)
                    create_h_tunnel(prev_x, new_x, new_y)

            rooms.append(new_room)
            num_rooms += 1
    stairs = Object(new_x, new_y, '<', 'stairs', libtcod.white)
    objects.append(stairs)
    stairs.send_to_back()

def next_level():
    global dungeon_level
    message('You take a moment to rest and heal your wounds.', libtcod.light_violet)
    player.fighter.heal(player.fighter.max_hp / 2)

    message('After taking a deep breath you descend deeper into the dungeon...', libtcod.red)
    dungeon_level += 1
    make_map()
    initialize_fov()

#gui functions
def render_bar(x, y, total_width, name, value, maximum, bar_color, back_color):
    bar_width = int(float(value) / maximum * total_width)

    libtcod.console_set_default_background(panel, back_color)
    libtcod.console_rect(panel, x, y, total_width, 1, False, libtcod.BKGND_SCREEN)

    libtcod.console_set_default_background(panel, bar_color)
    if bar_width > 0 :
        libtcod.console_rect(panel, x, y, bar_width, 1, False, libtcod.BKGND_SCREEN)

    libtcod.console_set_default_foreground(panel, libtcod.white)
    libtcod.console_print_ex(panel, x + total_width / 2, y, libtcod.BKGND_NONE, libtcod.CENTER, name + ': ' + str(value) + '/' + str(maximum))

def message(new_msg, color = libtcod.white):
    new_msg_lines = textwrap.wrap(new_msg, MSG_WIDTH)

    for line in new_msg_lines:
        if len(game_msgs) == MSG_HEIGHT:
            del(game_msgs[0])
        game_msgs.append( (line, color) )

def menu(header, options, width):
    if len(options) > 26: raise ValueError('Too much options.')
    header_height = libtcod.console_get_height_rect(con, 0, 0, width, SCREEN_HEIGHT, header)
    if header == '':
        header_height = 0
    height = len(options) + header_height

    window = libtcod.console_new(width, height)

    libtcod.console_set_default_foreground(window, libtcod.white)
    libtcod.console_print_rect_ex(window, 0, 0, width, height, libtcod.BKGND_NONE, libtcod.LEFT, header)
    y = header_height
    letter = ord('a')
    for option_text in options:
        text = '(' + chr(letter) + ') ' + option_text
        libtcod.console_print_ex(window, 0, y, libtcod.BKGND_NONE, libtcod.LEFT, text)
        y += 1
        letter += 1

    x = SCREEN_WIDTH/2 - width/2
    y = SCREEN_HEIGHT/2 - height/2
    libtcod.console_blit(window, 0, 0, width, height, 0, x, y, 1.0, 0.7)

    libtcod.console_flush()
    key = libtcod.console_wait_for_keypress(True)

    if key.vk == libtcod.KEY_F5:
        libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

    index = key.c - ord('a')
    if index >= 0 and index < len(options):
        return index
    return None

def inventory_menu(header):
    if len(inventory) == 0:
        options = ['Inventory is empty.']
    else:
        options = []
        for item in inventory:
            text = item.name
            if item.equipment and item.equipment.is_equipped:
                text = text + ' (on ' + item.equipment.slot + ')'
            options.append(text)

    index = menu(header, options, INVENTORY_WIDTH)
    if index is None or len(inventory) == 0:
        return None
    return inventory[index].item

def msgbox(text, width=50):
    menu(text, [], width)

def main_menu():
    while not libtcod.console_is_window_closed():
        libtcod.console_set_default_foreground(0, libtcod.light_yellow)
        libtcod.console_print_ex(0, SCREEN_WIDTH/2, SCREEN_HEIGHT/2 - 4, libtcod.BKGND_NONE, libtcod.CENTER, 'ROGUELIKE OF DOOM')
        choice = menu('', ['New game', 'Continue', 'Quit'], 24)

        if choice == 0:
            new_game()
            play_game()
        elif choice == 1:
            try:
                load_game()
            except:
                msgbox('\n No saved game found!\n', 24)
                continue
            play_game()
        elif choice == 2:
            break

#game behavior and logic
def player_attack_or_move(dx, dy):
    global fov_recompute
    x = player.x + dx
    y = player.y + dy

    target = None
    for object in objects:
        if object.fighter and object.x == x and object.y == y:
            target = object
            break

    if target is not None:
        player.fighter.attack(target)
    else:
        player.move(dx, dy)
        fov_recompute = True

def player_death(player):
    global game_state
    message('You died! Your deeds of valor will be remembered!', libtcod.light_sky)
    game_state = 'dead'

    player.char = '%'
    player.color = libtcod.dark_red

def monster_death(monster):
    message(monster.name.capitalize() + ' leaves a bloody mess! You gain ' + str(monster.fighter.xp) + ' experience!', libtcod.orange)
    monster.char = '%'
    monster.color = libtcod.dark_red
    monster.blocks = False
    monster.fighter = None
    monster.ai = None
    monster.name = 'remains of ' + monster.name
    monster.send_to_back()

def is_blocked(x, y):
    if map[x][y].blocked:
        return True

    for object in objects:
        if object.blocks and object.x == x and object.y == y:
            return True

    return False

def use_healing_potion():
    if player.fighter.hp == player.fighter.max_hp:
        message('You are already at max health.', libtcod.red)
        return 'cancelled'

    message('You wounds are healed!', libtcod.light_violet)
    player.fighter.heal(HEAL_AMOUNT)

def cast_lightning_bolt():
    monster = closest_monster(LIGHTNING_RANGE)
    if monster is None:
        message('No enemy is close to cast spell on.', libtcod.red)
        return 'cancelled'

    message('A lightning bolt strikes ' + monster.name + ' for ' + str(LIGHTNING_DAMAGE) + '!', libtcod.light_blue)
    monster.fighter.take_damage(LIGHTNING_DAMAGE)

def cast_confuse():
    message('Left-click monster to confuse him.', libtcod.light_cyan)
    monster = target_monster()
    if monster is None:
        return 'cancelled'

    old_ai = monster.ai
    monster.ai = ConfusedMonster(old_ai)
    monster.ai.owner = monster
    message(monster.name + ' is confused!', libtcod.light_green)

def cast_fireball():
    message('Left-click a tile to cast fireball or right-click to cancel.', libtcod.light_cyan)
    (x, y) = target_tile()
    if x is None:
        return 'cancelled'
    message('Fireball explodes, burning everything within ' + str(FIREBALL_RADIUS) + ' tiles!', libtcod.orange)

    for object in objects:
        if object.distance(x, y) <= FIREBALL_RADIUS and object.fighter:
            object.fighter.take_damage(FIREBALL_DAMAGE)
            message(object.name + ' takes ' + str(FIREBALL_DAMAGE) + ' from fireball explosion', libtcod.orange)

def closest_monster(max_range):
    closest_enemy = None
    closest_distance = max_range + 1
    for object in objects:
        if object.fighter and not object == player and libtcod.map_is_in_fov(fov_map, object.x, object.y):
            dist = player.distance_to(object)
            if dist < closest_distance:
                closest_enemy = object
                closest_dist = dist
    return closest_enemy

def check_level_up():
    level_up_xp = LEVEL_UP_BASE + player.level * LEVEL_UP_FACTOR
    if player.fighter.xp >= level_up_xp:
        player.level += 1
        player.fighter.xp -= level_up_xp
        message('You feel stronger! You advance to level ' + str(player.level) + '!', libtcod.yellow)
        choice = None
        while choice == None:
            choice = menu('Level up! Choose a stat to increase:\n',
            ['Stamina (+20 HP)', 'Attack (+1 attack)', 'Defense (+1 defense)'],
            LEVEL_SCREEN_WIDTH)

        if choice == 0:
            player.figher.base_max_hp += 20
            player.fighter.hp += 20
        elif choice == 1:
            player.fighter.base_power += 1
        elif choice == 2:
            player.fighter.base_defense += 1

def get_equipped_in_slot(slot):
    for obj in inventory:
        if obj.equipment and obj.equipment.slot == slot and obj.equipment.is_equipped:
            return obj.equipment
    return None

def get_all_equipped(obj):
    if obj == player:
        equipped_list = []
        for item in inventory:
            if item.equipment and item.equipment.is_equipped:
                equipped_list.append(item.equipment)
        return equipped_list
    else:
        return []

#render function(s)
def render_all():
    global color_dark_wall, color_light_wall
    global color_dark_ground, color_light_ground
    global fov_map, fov_recompute

    if fov_recompute:
        fov_recompute = False
        libtcod.map_compute_fov(fov_map, player.x, player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO)

        for y in range(MAP_HEIGHT):
            for x in range(MAP_WIDTH):
                visible = libtcod.map_is_in_fov(fov_map, x, y)
                wall = map[x][y].block_sight
                if not visible:
                    if map[x][y].explored:
                        if wall:
                            libtcod.console_set_char_background(con, x, y, color_dark_wall, libtcod.BKGND_SET)
                        else:
                            libtcod.console_set_char_background(con, x, y, color_dark_ground, libtcod.BKGND_SET)
                else:
                    if wall:
                        libtcod.console_set_char_background(con, x, y, color_light_wall, libtcod.BKGND_SET)
                    else:
                        libtcod.console_set_char_background(con, x, y, color_light_ground, libtcod.BKGND_SET)
                    map[x][y].explored = True

    for object in objects:
        if object != player:
            object.draw()
    player.draw()

    libtcod.console_blit(con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0)
    libtcod.console_set_default_background(panel, libtcod.black)
    libtcod.console_clear(panel)

    y = 1
    for (line, color) in game_msgs:
        libtcod.console_set_default_foreground(panel, color)
        libtcod.console_print_ex(panel, MSG_X, y, libtcod.BKGND_NONE, libtcod.LEFT, line)
        y += 1

    render_bar(1, 1, BAR_WIDTH, 'HP', player.fighter.hp, player.fighter.max_hp, libtcod.light_red, libtcod.darker_red)

    libtcod.console_print_ex(panel, 1, 3, libtcod.BKGND_NONE, libtcod.LEFT, 'Dungeon level ' + str(dungeon_level))

    libtcod.console_set_default_foreground(panel, libtcod.light_gray)
    libtcod.console_print_ex(panel, 1, 0, libtcod.BKGND_NONE, libtcod.LEFT, get_names_under_mouse())

    libtcod.console_blit(panel, 0, 0, SCREEN_WIDTH, PANEL_HEIGHT, 0, 0, PANEL_Y)

#input
def target_monster(max_range = None):
    while True:
        (x, y) = target_tile(max_range)
        if x is None:
            return None

        for object in objects:
            if object.x == x and object.y == y and object.fighter and object != player:
                return object

def target_tile(max_range = None):
    global key, mouse
    while True:
        libtcod.console_flush()
        libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE,key,mouse)
        render_all()

        (x, y) = (mouse.cx, mouse.cy)

        if mouse.rbutton_pressed or key.vk == libtcod.KEY_ESCAPE:
            return (None, None)
        if (mouse.lbutton_pressed and libtcod.map_is_in_fov(fov_map, x, y) and
            (max_range is None or player.distance(x, y) <= max_range)):
            return (x, y)

def get_names_under_mouse():
    global mouse

    (x, y) = (mouse.cx, mouse.cy)

    names = [obj.name for obj in objects
            if obj.x == x and obj.y == y and libtcod.map_is_in_fov(fov_map, obj.x, obj.y)]

    names = ', '.join(names)
    return names.capitalize()

def handle_keys():
    global fov_recompute, key

    if key.vk == libtcod.KEY_F5:
        libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())
    elif key.vk == libtcod.KEY_ESCAPE:
        return 'exit'
    if game_state == 'playing':
        pressed = key.vk
        if key.vk == libtcod.KEY_UP or key.vk == libtcod.KEY_KP8:
            player_attack_or_move(0, -1)
        elif key.vk == libtcod.KEY_DOWN or key.vk == libtcod.KEY_KP2:
            player_attack_or_move(0, 1)
        elif key.vk == libtcod.KEY_LEFT or key.vk == libtcod.KEY_KP4:
            player_attack_or_move(-1, 0)
        elif key.vk == libtcod.KEY_RIGHT or key.vk == libtcod.KEY_KP6:
            player_attack_or_move(1, 0)
        elif key.vk == libtcod.KEY_HOME or key.vk == libtcod.KEY_KP7:
            player_attack_or_move(-1, -1)
        elif key.vk == libtcod.KEY_PAGEUP or key.vk == libtcod.KEY_KP9:
            player_attack_or_move(1, -1)
        elif key.vk == libtcod.KEY_END or key.vk == libtcod.KEY_KP1:
            player_attack_or_move(-1, 1)
        elif key.vk == libtcod.KEY_PAGEDOWN or key.vk == libtcod.KEY_KP3:
            player_attack_or_move(1, 1)
        elif key.vk == libtcod.KEY_KP5:
            pass
        else:
            key_char = chr(key.c)

            if key_char == 'e':
                for object in objects:
                    if object.x == player.x and object.y == player.y and object.item:
                        object.item.pick_up()
                        break

            if key_char == 'q':
                chosen_item = inventory_menu('Press the corresponding key to use item or other to cancel!\n')
                if chosen_item is not None:
                    chosen_item.use()

            if key_char == 'd':
                chosen_item = inventory_menu('Press the corresponding key to drop item!\n')
                if chosen_item is not None:
                    chosen_item.drop()

            if key_char == 'f':
                if stairs.x == player.x and stairs.y == player.y:
                    print("o")
                    next_level()

            if key_char == 'c':
                level_up_xp = LEVEL_UP_BASE + player.level * LEVEL_UP_FACTOR
                msgbox('Character information: \n\nLevel: ' + str(player.level) + '\nExperience: '+ str(player.fighter.xp) + '/' + str(level_up_xp) + '\nAttack: ' +
                str(player.fighter.power) + '\nDefense: ' + str(player.fighter.defense), CHARACTER_SCREEN_WIDTH)

            return 'didnt-take-turn'

#game initialization
def save_game():
    file = shelve.open('savegame', 'n')
    file['map'] = map
    file['objects'] = objects
    file['player_index'] = objects.index(player)
    file['inventory'] = inventory
    file['game_msgs'] = game_msgs
    file['game_state'] = game_state
    file['stairs_index'] = objects.index(stairs)
    file['dungeon_level'] = dungeon_level
    file.close()

def load_game():
    global map, objects, player, inventory, game_msgs, game_state, stairs, dungeon_level

    file = shelve.open('savegame', 'r')
    map = file['map']
    objects = file['objects']
    player = objects[file['player_index']]
    inventory = file['inventory']
    game_msgs = file['game_msgs']
    game_state = file['game_state']
    stairs = objects[file['stairs_index']]
    dungeon_level = file['dungeon_level']
    file.close()

    initialize_fov()

def new_game():
    global player, inventory, game_msgs, game_state, dungeon_level

    dungeon_level = 1

    fighter_component = Fighter(hp=100, defense=2, power=4, xp=0, death_function=player_death)
    player = Object(0, 0, '@', 'player', libtcod.white, blocks=True, fighter=fighter_component)

    player.level = 1

    make_map()
    initialize_fov()

    game_state = 'playing'
    game_msgs = []
    inventory = []

    equipment_component = Equipment(slot='right hand', power_bonus=2)
    obj = Object(0, 0, '-', 'dagger', libtcod.sky, equipment=equipment_component)
    inventory.append(obj)
    equipment_component.equip()
    obj.always_visible = True

    message('Welcome stranger! Prepare to get your ass kicked!', libtcod.red)

def initialize_fov():
    global fov_map, fov_recompute

    fov_recompute = True

    fov_map = libtcod.map_new(MAP_WIDTH, MAP_HEIGHT)
    for y in range(MAP_HEIGHT):
        for x in range(MAP_WIDTH):
            libtcod.map_set_properties(fov_map, x, y, not map[x][y].block_sight, not map[x][y].blocked)

    libtcod.console_clear(con)

def play_game():
    global key, mouse

    mouse = libtcod.Mouse()
    key = libtcod.Key()

    player_action = None

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS|libtcod.EVENT_MOUSE,key,mouse)
        render_all()

        libtcod.console_flush()
        check_level_up()

        for object in objects:
            object.clear()

        player_action = handle_keys()
        if player_action == 'exit':
            save_game()
            break

        if game_state == 'playing' and player_action != 'didnt-take-turn':
            for object in objects:
                if object.ai:
                    object.ai.take_turn()

libtcod.console_set_custom_font('arial10x10.png', libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)
libtcod.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, 'python/libtcod-tutorial', False)
libtcod.sys_set_fps(LIMIT_FPS)
main_menu()


from odoo import fields,models,api,_
from odoo.exceptions import UserError, RedirectWarning, ValidationError

class consignment_notes(models.Model):
    _name = 'consignment.notes'
    _rec_sequence = 'name'

    def _compute_invoice_count(self):
        for inv in self:
            invoice = self.env['account.invoice'].search([('consignment_id','=', inv.id)])
            inv.invoice_count = len(invoice)

    def _compute_delivery_order_count(self):
        for delivery in self:
            order = self.env['stock.picking'].search([('consignment_id','=', delivery.id)])
            delivery.delivery_order_count = len(order)

    name = fields.Char('Consignment Reference' ,readonly="True")
    users_id = fields.Many2one('res.users', string = "Responsible")
    partner_id = fields.Many2one('res.partner',string = "Owner")
    account_analytic_id = fields.Many2one('account.analytic.account',
                                          string='Analytic Account')
    agreement_deadline = fields.Datetime(string="Agreement Deadline")
    source_document = fields.Text(string="Source Document")
    state = fields.Selection([('draft','Draft'),('confirmed','Confirmed'),('done','Done')], string='State', default='draft')
    delivery_order_count = fields.Integer('Delivery Order', compute='_compute_delivery_order_count')
    invoice_count = fields.Integer('Invoice', compute='_compute_invoice_count')
    order_line_ids = fields.One2many('order.lines','consignment_id')
    picking_type_id = fields.Many2one('stock.picking.type' , string="Picking Type")
    account_id = fields.Many2one('account.account','Account')

    @api.multi
    def action_view_delivery(self):
        for rec in self:
            delivery = self.env['stock.picking'].search([('consignment_id', '=', rec.id)])
            # for rec in invoice:
            #     for recode in rec.
            action = self.env.ref('stock.action_picking_tree_all').read()[0]
            if len(delivery) > 1:
                action['domain'] = [('id', 'in', delivery.ids)]
            elif len(delivery) == 1 :
                action['views'] = [(self.env.ref('stock.view_picking_form').id, 'form')]
                action['res_id'] = delivery.ids[0]
            else:
                action = {'type':'ir.actions.act_window_close'}
            return action

    @api.multi
    def action_view_invoice(self):
        for inv in self:
            invoice = self.env['account.invoice'].search([('consignment_id', '=', inv.id)])
            # for rec in invoice:
            #     for recode in rec.
            action = self.env.ref('account.action_invoice_tree1').read()[0]
            if len(invoice) > 1:
                action['domain'] = [('id', 'in', invoice.ids)]
            elif len(invoice) == 1 :
                action['views'] = [(self.env.ref('account.invoice_form').id, 'form')]
                action['res_id'] = invoice.ids[0]
            else:
                action = {'type':'ir.actions.act_window_close'}
            return action

    @api.model
    def create(self, vals):
        vals['name'] = self.env['ir.sequence'].next_by_code('consignment.notes')
        result = super(consignment_notes, self).create(vals)
        return result

    @api.multi
    def create_invoice(self):
        for rec in self :

            invoice_line = []
            for recode in rec.order_line_ids:
                invoice_line.append([0, 0, {
                        'product_id': recode.product_id.id,
                        'product_uom_qty': recode.quantity,
                        'quantity': recode.quantity_sold - recode.quantity_invoiced,
                        'product_uom': recode.uom_id.id,
                        'name': recode.product_id.name,
                        'price_unit': recode.price_unit,
                        'account_id': recode.account_id.id,
                    }
                    ])
            invoices = {
                'partner_id': rec.partner_id.id,
                'date_invoice': rec.agreement_deadline,
                'invoice_line_ids': invoice_line,
                'account_id': rec.account_id.id,
                'user_id' : rec.users_id.id,
                'consignment_id': rec.id,
                'is_consignment': True,
                'type': 'in_invoice',

            }
            create_invoice = self.env['account.invoice'].create(invoices)
            rec.write({'state': 'done'})
        return True

    @api.multi
    def confirm(self):
        for rec in self :

            move = []
            for recode in rec.order_line_ids:

                    move.append([0, 0, {
                        'product_id': recode.product_id.id,
                        'product_uom_qty': recode.quantity,
                        'product_uom': recode.uom_id.id,
                        'name': recode.product_id.name,
                    }
                    ])
            delivery_order = {
                'partner_id': rec.partner_id.id,
                'min_date': rec.agreement_deadline,
                'location_dest_id': self.env.ref('stock.stock_location_stock', raise_if_not_found=False).id,
                'location_id': rec.partner_id.property_stock_supplier.id,
                'picking_type_id': rec.picking_type_id.id,
                'move_lines': move,
                'consignment_id': rec.id,
                'origin': rec.source_document,
            }
            delivery = self.env['stock.picking'].create(delivery_order)
            rec.write({'state':'confirmed'})
        return True
class order_line(models.Model):
    _name = 'order.lines'

    @api.multi
    @api.depends('product_id')
    def _compute_delivery_quantity(self):
        for delivery in self:
            picking_id = self.env['stock.picking'].search([('partner_id','=', delivery.consignment_id.partner_id.id),('state','=','done')])
            if picking_id.picking_type_id.name == 'Receipts':
                for rec in picking_id.move_lines:
                    if rec.product_id.id == delivery.product_id.id:
                        delivery.delivered_quantities = rec.product_uom_qty

    @api.multi
    @api.depends('product_id')
    def _compute_quantity_sold(self):
        for delivery in self:
            picking_id = self.env['stock.picking'].search([('partner_id','=', delivery.consignment_id.partner_id.id),('state','=','done')])
            if picking_id.picking_type_id.name == 'Delivery Orders':
                for rec in picking_id.move_lines:
                    if rec.product_id.id == delivery.product_id.id:
                        delivery.quantity_sold = rec.product_uom_qty

    consignment_id = fields.Many2one('consignment.notes')
    product_id = fields.Many2one('product.product' ,'Product' ,required=True)
    quantity = fields.Float(string = 'Quantity' ,required=True)
    account_analytic_id = fields.Many2one('account.analytic.account',
                                          string='Analytic Account')
    delivered_quantities = fields.Integer('Delivered Quantities', compute='_compute_delivery_quantity')
    quantity_sold = fields.Integer('Quantity Sold', compute='_compute_quantity_sold')
    quantity_invoiced = fields.Integer('Quantity Invoiced')

    uom_id = fields.Many2one('product.uom', string='Unit of Measure',
                              index=True ,required=True)
    price_unit = fields.Float(string='Unit Price' ,required=True)
    account_id = fields.Many2one('account.account', 'Account' ,required=True)

class account_account(models.Model):
    _inherit = 'account.invoice'

    consignment_id = fields.Many2one('consignment.notes', string="Consignment Notes")
    is_consignment = fields.Boolean('Is Consignment')

    @api.multi
    def action_invoice_open(self):
        # lots of duplicate calls to action_invoice_open, so we remove those already open
        to_open_invoices = self.filtered(lambda inv: inv.state != 'open')
        if to_open_invoices.filtered(lambda inv: inv.state not in ['proforma2', 'draft']):
            raise UserError(_("Invoice must be in draft or Pro-forma state in order to validate it."))
        to_open_invoices.action_date_assign()
        to_open_invoices.action_move_create()
        for rec in self:
            if rec.consignment_id:
                for one_line in rec.invoice_line_ids:
                    if one_line.product_id:
                        for one_consignment_line in self.env['order.lines'].sudo().search([('product_id', '=', one_line.product_id.id),('consignment_id', '=', rec.consignment_id.id)]):
                            one_consignment_line.sudo().write({
                                'quantity_invoiced': one_consignment_line.quantity_invoiced + one_line.quantity
                            })
        return to_open_invoices.invoice_validate()

class stock_picking(models.Model):
    _inherit = 'stock.picking'

    consignment_id = fields.Many2one('consignment.notes', string="Consignment Notes")


import collections

def is_merge(s, p1, p2):
    n, n1, n2 = len(s), len(p1), len(p2)
    if n1 + n2 != n:
        return False
    if not p1:
        return s == p2
    if not p2:
        return s == p1
    c, c1, c2 = collections.Counter(s), collections.Counter(p1), collections.Counter(p2)
    for k in c1:
        if k in c:
            c[k] -= c1[k]
    for k in c2:
        if k in c:
            c[k] -= c2[k]
    if any(c[k] != 0 for k in c):
        return False
    j = 0
    for i in range(n):
        if s[i] == p1[j]:
            j += 1
            if j == n1:
                break
    if j < n1:
        return False
    j = 0
    for i in range(n):
        if s[i] == p2[j]:
            j += 1
            if j == n2:
                break
    if j < n2:
        return False
    return True

print(is_merge("Can we merge it? Yes, we can!", "Ca eme ites, we can", "nw erg? Y!"))


#!/bin/python3
from sklearn.linear_model import LinearRegression
import numpy as np
from datasets import DataSet
from sklearn.metrics import mean_squared_error
def to_matrix(data,dim):
	full_train_data = []
	num_examples = len(data['x'])
	for i in range(num_examples):
		row = np.zeros(dim)
		row[train_data['x'][i]] = 1
		full_train_data.append(row)
	return np.array(full_train_data),data['y']

ds = DataSet('./data/','frappe')
train_data = ds.train_data
num_train = len(train_data['y'])
validation_data = ds.validation_data
num_valid = len(validation_data['y'])
test_data = ds.test_data
num_test = len(test_data['y'])
dim = ds.feat_dim
train_x,train_y = to_matrix(train_data,dim)
valid_x,valid_y = to_matrix(validation_data,dim)
test_x,test_y = to_matrix(test_data,dim)
clf = LinearRegression()
clf.fit(train_data,train_y)
train_y_ = clf.predict(train_x)
valid_y_ = clf.predict(valid_x)
test_y_ = clf.predict(test_y_)
train_rmse = mean_squared_error(train_y,train_y_)
valid_rmse = mean_squared_error(valid_y,valid_y_)
test_rmse = mean_squared_error(test_y,test_y_)
print('train rmse:',train_rmse,'validation rmse:',valid_rmse,'test rmse:',test_rmse)