# _*_ coding:utf-8 _*_
# @File  : czce.py
# @Time  : 2020-07-23 9:36
# @Author: zizle
import os
import re
import json
import random
import numpy as np
from pandas import read_excel, DataFrame, concat, merge
from datetime import datetime
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import QFile, Signal, QObject
from PySide2.QtNetwork import QNetworkRequest
from configs import LOCAL_SPIDER_SRC, SERVER, USER_AGENTS
from utils.characters import full_width_to_half_width, split_zh_en, split_number_en

# 将品种月份修改为品种+4位合约的形式
def modify_contract_express(contract, current_date):
    number_en = split_number_en(contract)
    return current_date[2].join(number_en)

class DateValueError(Exception):
    """ 日期错误 """

class CZCESpider(QObject):
    spider_finished = Signal(str, bool)

    def __init__(self, *args, **kwargs):
        super(CZCESpider, self).__init__(*args, **kwargs)
        self.date = None

    def set_date(self, date):
        self.date = datetime.strptime(date, '%Y-%m-%d')

    def get_daily_source_file(self):
        """ 获取日交易数据源文件保存至本地 """
        if self.date is None:
            raise DateValueError("请先使用`set_date`设置`CZCESpider`日期.")
        url = "http://www.czce.com.cn/cn/DFSStaticFiles/Future/{}/{}/FutureDataDaily.xls".format(self.date.year, self.date.strftime('%Y%m%d'))

        app = QApplication.instance()
        network_manager = getattr(app, "_network")

        request = QNetworkRequest(url=url)
        request.setHeader(QNetworkRequest.UserAgentHeader, random.choice(USER_AGENTS))
        reply = network_manager.get(request)
        reply.finished.connect(self.daily_source_file_reply)

    def daily_source_file_reply(self):
        reply = self.sender()
        if reply.error():
            reply.deleteLater()
            self.spider_finished.emit("失败:" + str(reply.error()), True)
            return
        save_path = os.path.join(LOCAL_SPIDER_SRC, 'czce/daily/{}.xls'.format(self.date.strftime("%Y-%m-%d")))
        file_data = reply.readAll()
        file_obj = QFile(save_path)
        is_open = file_obj.open(QFile.WriteOnly)
        if is_open:
            file_obj.write(file_data)
            file_obj.close()
        reply.deleteLater()
        self.spider_finished.emit("获取郑商所{}日交易数据源文件成功!".format(self.date.strftime("%Y-%m-%d")), True)

    def get_rank_source_file(self):
        """ 获取日持仓排名数据源文件保存至本地 """
        if self.date is None:
            raise DateValueError("请先使用`set_date`设置`CZCESpider`日期.")
        url = "http://www.czce.com.cn/cn/DFSStaticFiles/Future/{}/{}/FutureDataHolding.xls".format(self.date.year, self.date.strftime('%Y%m%d'))

        app = QApplication.instance()
        network_manager = getattr(app, "_network")

        request = QNetworkRequest(url=url)
        request.setHeader(QNetworkRequest.UserAgentHeader, random.choice(USER_AGENTS))
        reply = network_manager.get(request)
        reply.finished.connect(self.rank_source_file_reply)

    def rank_source_file_reply(self):
        reply = self.sender()
        if reply.error():
            reply.deleteLater()
            self.spider_finished.emit("失败:" + str(reply.error()), True)
            return
        save_path = os.path.join(LOCAL_SPIDER_SRC, 'czce/rank/{}.xls'.format(self.date.strftime("%Y-%m-%d")))
        file_data = reply.readAll()
        file_obj = QFile(save_path)
        is_open = file_obj.open(QFile.WriteOnly)
        if is_open:
            file_obj.write(file_data)
            file_obj.close()
        reply.deleteLater()
        self.spider_finished.emit("获取郑商所{}日持仓排名数据源文件成功!".format(self.date.strftime("%Y-%m-%d")), True)

    def get_receipt_source_file(self):
        """ 获取仓单日报数据源文件保存至本地 """
        if self.date is None:
            raise DateValueError("请先使用`set_date`设置`CZCESpider`日期.")
        url = "http://www.czce.com.cn/cn/DFSStaticFiles/Future/{}/{}/FutureDataWhsheet.xls".format(self.date.year, self.date.strftime('%Y%m%d'))

        app = QApplication.instance()
        network_manager = getattr(app, "_network")

        request = QNetworkRequest(url=url)
        request.setHeader(QNetworkRequest.UserAgentHeader, random.choice(USER_AGENTS))
        reply = network_manager.get(request)
        reply.finished.connect(self.receipt_source_file_reply)

    def receipt_source_file_reply(self):
        """ 获取仓单日报返回 """
        reply = self.sender()
        if reply.error():
            reply.deleteLater()
            self.spider_finished.emit("失败:" + str(reply.error()), True)
            return
        save_path = os.path.join(LOCAL_SPIDER_SRC, 'czce/receipt/{}.xls'.format(self.date.strftime("%Y-%m-%d")))
        file_data = reply.readAll()
        file_obj = QFile(save_path)
        is_open = file_obj.open(QFile.WriteOnly)
        if is_open:
            file_obj.write(file_data)
            file_obj.close()
        reply.deleteLater()
        self.spider_finished.emit("获取郑商所{}仓单日报数据源文件成功!".format(self.date.strftime("%Y-%m-%d")), True)

class CZCEParser(QObject):
    parser_finished = Signal(str, bool)

    def __init__(self, *args, **kwargs):
        super(CZCEParser, self).__init__(*args, **kwargs)
        self.date = None

    def set_date(self, date):
        self.date = datetime.strptime(date, '%Y-%m-%d')

    def parser_daily_source_file(self):
        """ 解析源文件数据为pandas的DataFrame """
        if self.date is None:
            raise DateValueError("请先使用`set_date`设置`CZCEParser`日期.")
        file_path = os.path.join(LOCAL_SPIDER_SRC, 'czce/daily/{}.xls'.format(self.date.strftime("%Y-%m-%d")))
        if not os.path.exists(file_path):
            self.parser_finished.emit("没有发现郑商所{}的日交易行情文件,请先抓取数据!".format(self.date.strftime("%Y-%m-%d")), True)
            return DataFrame()
        # 使用pandas解析数据
        xls_df = read_excel(file_path, thousands=',', skiprows=[0])
        # xls_df.columns = xls_df.iloc[0]  # 第一行作为列头
        # xls_df = xls_df.drop(xls_df.index[0])  # 删除第一行
        xls_df = xls_df[~xls_df['品种月份'].str.contains('总计|小计')]  # 选取品种月份不含有小计和总计的行
        xls_df['品种代码'] = xls_df['品种月份'].apply(lambda x: x[:2])  # 变为品种
        if xls_df.columns.values.tolist() != [
            '品种月份', '昨结算', '今开盘', '最高价', '最低价', '今收盘', '今结算', '涨跌1', '涨跌2', '成交量(手)', '空盘量', '增减量', '成交额(万元)', '交割结算价', '品种代码'
        ]:
            self.parser_finished.emit("源数据文件格式有误,解析失败!", True)
            return DataFrame()
        data_date = self.date.strftime('%Y%m%d')
        xls_df['日期'] = [data_date for _ in range(xls_df.shape[0])]
        xls_df = xls_df.fillna(0)
        xls_df.columns = [
            "contract", "pre_settlement", "open_price", "highest", "lowest", "close_price", "settlement", "zd_1", "zd_2",
            "trade_volume", "empty_volume", "increase_volume", "trade_price", "delivery_price", "variety_en", "date",
        ]
        # 将品种月份处理为4位合约(分离字母数字后插入年份的第3个数)
        xls_df["contract"] = xls_df["contract"].apply(modify_contract_express, args=(data_date,))
        self.parser_finished.emit("解析数据文件成功!", False)
        return xls_df

    def save_daily_server(self, source_df):
        """ 保存日行情数据到服务器 """
        self.parser_finished.emit("开始保存郑商所{}日交易数据到服务器数据库...".format(self.date.strftime("%Y-%m-%d")), False)
        data_body = source_df.to_dict(orient="records")
        app = QApplication.instance()
        network_manager = getattr(app, "_network")
        url = SERVER + "exchange/czce/daily/?date=" + self.date.strftime("%Y-%m-%d")
        request = QNetworkRequest(url=url)
        request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json;charset=utf-8")

        reply = network_manager.post(request, json.dumps(data_body).encode("utf-8"))
        reply.finished.connect(self.save_daily_server_reply)

    def save_daily_server_reply(self):
        """ 保存数据到交易所返回响应 """
        reply = self.sender()
        data = reply.readAll().data()
        reply.deleteLater()
        if reply.error():
            self.parser_finished.emit("保存郑商所{}日交易数据到服务数据库失败:\n{}".format(self.date.strftime("%Y-%m-%d"), reply.error()), True)
        else:
            data = json.loads(data.decode('utf-8'))
            self.parser_finished.emit(data["message"], True)

    def parser_rank_source_file(self):
        """ 解析日持仓排名数据源文件 """
        if self.date is None:
            raise DateValueError("请先使用`set_date`设置`CZCEParser`日期.")
        file_path = os.path.join(LOCAL_SPIDER_SRC, 'czce/rank/{}.xls'.format(self.date.strftime("%Y-%m-%d")))
        if not os.path.exists(file_path):
            self.parser_finished.emit("没有发现郑商所{}的日持仓排名源文件,请先抓取数据!".format(self.date.strftime("%Y-%m-%d")), True)
            return DataFrame()
        # 读取文件
        xls_df = read_excel(file_path, thousands=',')
        variety_index_dict = dict()  # 存品种的起始终止行
        contract_index_dict = dict()  # 存合约的起始终止行
        variety_dict = dict()  # 存品种的dict
        contract_set = set()  # 存合约的dict
        variety_en = None
        contract_en = None
        is_variety = True
        # 遍历每一行，取出每个品种的数据表
        for row_content in xls_df.itertuples():
            info_for_match_ = full_width_to_half_width(row_content[1])
            search_variety = re.search(r'品种:(.*)\s日期.*', info_for_match_)  # 找到品种行开头
            search_contract = re.search(r'合约:(.*)\s日期.*', info_for_match_)  # 找到合约
            search_sum = re.search(r'合计', info_for_match_)
            if search_variety:  # 如果找到品种记录下品种和开始行
                zh_en_variety = search_variety.group(1)
                variety_name, variety_en = split_zh_en(zh_en_variety)
                if variety_en == "PTA":
                    variety_en = "TA"
                variety_dict[variety_en] = variety_name
                variety_index_dict[variety_en] = [row_content[0] + 1]
                is_variety = True
            elif search_contract:  # 如果找到合约,从品种数据去品种中文名,记录下开始行
                contract_en = search_contract.group(1)
                contract_set.add(contract_en)
                contract_index_dict[contract_en] = [row_content[0] + 1]
                is_variety = False
            else:
                pass  # 无则继续
            if search_sum and (variety_en or contract_en):  # 如果找到合计行，记录下当前品种的结束行
                if is_variety:

                    variety_index_dict[variety_en].append(row_content[0])
                else:
                    contract_index_dict[contract_en].append(row_content[0])
            else:
                pass  # 无则继续
        # 整理数据
        column_indexes = ['variety_en', 'contract', 'rank',
                          'trade_company', 'trade', 'trade_increase',
                          'long_position_company', 'long_position', 'long_position_increase',
                          'short_position_company', 'short_position', 'short_position_increase']

        result_df = DataFrame(columns=column_indexes)
        str_date = self.date.strftime("%Y%m%d")
        # 每个品种数据框
        for variety_en in variety_dict:
            variety_index_range = variety_index_dict[variety_en]
            variety_df = xls_df.iloc[variety_index_range[0]:variety_index_range[1] + 1, :]
            variety_df = self._parser_rank_sub_df(variety_name=variety_dict[variety_en], sub_df=variety_df)
            # 填充品种代码和合约的值
            variety_df["variety_en"] = [variety_en for _ in range(variety_df.shape[0])]
            variety_df["contract"] = [variety_en for _ in range(variety_df.shape[0])]
            # print(variety_en, "\n", variety_df)
            result_df = concat([result_df, variety_df])
        # 每个合约数据框
        for contract in contract_set:
            contract_index_range = contract_index_dict[contract]
            # variety_key = 'PTA' if contract[:2] == 'TA' else contract[:2]
            variety_key = contract[:2]
            # print(variety_dict[variety_key], contract, contract_index_range)
            contract_df = xls_df.iloc[contract_index_range[0]:contract_index_range[1] + 1, :]
            contract_df = self._parser_rank_sub_df(variety_name=variety_dict[variety_key], sub_df=contract_df)
            # 填充品种代码和合约的值
            contract_df["variety_en"] = [variety_key for _ in range(contract_df.shape[0])]
            target_contract = modify_contract_express(contract.strip(), str_date)
            contract_df["contract"] = [target_contract for _ in range(contract_df.shape[0])]
            # print(contract, "\n", contract_df)
            result_df = concat([result_df, contract_df])
        str_date = self.date.strftime("%Y%m%d")
        result_df["date"] = [str_date for _ in range(result_df.shape[0])]
        return result_df

    def _parser_rank_sub_df(self, variety_name, sub_df):
        """ 解析每个品种或合约的数据框 """
        column_indexes = sub_df.iloc[0].values.tolist()
        # print(column_indexes)
        if column_indexes != ['名次', '会员简称', '成交量（手）', '增减量', '会员简称', '持买仓量', '增减量', '会员简称', '持卖仓量', '增减量']:
            raise ValueError("{}郑商所的'{}'持仓排名数据表头格式有误!".format(self.date.strftime("%Y-%m-%d"), variety_name))
        column_indexes = ['名次', '成交会员', '成交量', '成交增减', '买仓会员', '买仓量', '买仓增减', '卖仓会员', '卖仓量', '卖仓增减']
        sub_df.columns = column_indexes
        # sub_df = sub_df.reindex(columns=column_indexes)  # 重新调整列
        sub_df = sub_df.drop(sub_df.index[0])  # 删除第一行
        # 去除合计行
        sub_df = sub_df[~sub_df['名次'].str.contains('合计')]  # 选取不含有合计的行
        sub_df[['名次', '成交量', '成交增减', '买仓量', '买仓增减', '卖仓量', '卖仓增减']] = sub_df[['名次', '成交量', '成交增减', '买仓量', '买仓增减', '卖仓量', '卖仓增减']].replace('-', 0).astype(int)
        # 增加品种代码、合约两列
        new_column_indexes = ["品种代码", "合约"] + column_indexes

        sub_df = sub_df.reindex(columns=new_column_indexes)
        reset_indexes = ['variety_en', 'contract', 'rank',
                         'trade_company', 'trade', 'trade_increase',
                         'long_position_company', 'long_position', 'long_position_increase',
                         'short_position_company', 'short_position', 'short_position_increase']
        sub_df.columns = reset_indexes  # 修改列名
        return sub_df

    def save_rank_server(self, source_df):
        """ 保存日持仓排名到服务器 """
        self.parser_finished.emit("开始保存郑商所{}日持仓排名数据到服务器数据库...".format(self.date.strftime("%Y-%m-%d")), False)
        data_body = source_df.to_dict(orient="records")
        app = QApplication.instance()
        network_manager = getattr(app, "_network")
        url = SERVER + "exchange/czce/rank/?date=" + self.date.strftime("%Y-%m-%d")
        request = QNetworkRequest(url=url)
        request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json;charset=utf-8")

        reply = network_manager.post(request, json.dumps(data_body).encode("utf-8"))
        reply.finished.connect(self.save_rank_server_reply)

    def save_rank_server_reply(self):
        """ 保存日持仓排名到数据库返回 """
        reply = self.sender()
        data = reply.readAll().data()
        reply.deleteLater()
        if reply.error():
            self.parser_finished.emit("保存郑商所{}日持仓排名到服务数据库失败:\n{}".format(self.date.strftime("%Y-%m-%d"), reply.error()), True)
        else:
            data = json.loads(data.decode("utf-8"))
            self.parser_finished.emit(data["message"], True)

    def parser_receipt_source_file(self):
        """ 解析仓单日报源文件 """
        file_path = os.path.join(LOCAL_SPIDER_SRC, 'czce/receipt/{}.xls'.format(self.date.strftime("%Y-%m-%d")))
        if not os.path.exists(file_path):
            self.parser_finished.emit("没有发现郑商所{}的仓单日报源文件,请先抓取数据!".format(self.date.strftime("%Y-%m-%d")), True)
            return DataFrame()
        # 读取文件
        xls_df = read_excel(file_path)
        xls_df = xls_df.fillna('')
        variety_index_dict = dict()
        variety_dict = dict()
        variety_en = None  # 品种标记
        pre_variety_en = None
        for row_content in xls_df.itertuples():
            info_for_match_ = full_width_to_half_width(row_content[1])
            search_v = re.search(r'品种:(.*)\s单位.*', info_for_match_)  # 品种
            total_count = re.search(r'总计', info_for_match_)
            if search_v:  # 取得品种和品种的英文代码
                pre_variety_en = variety_en
                has_new_variety = True
                zh_en_variety = search_v.group(1)
                variety_name, variety_en = split_zh_en(zh_en_variety)
                if variety_en == "PTA":
                    variety_en = "TA"
                variety_dict[variety_en] = variety_name
                variety_index_dict[variety_en] = [row_content[0] + 1]
            else:
                has_new_variety = False
            # 获取当前品种的数据表
            if total_count and variety_en:
                variety_index_dict[variety_en].append(row_content[0])
            # 当没有总计时有上一个品种记录且找到了新品种，那么老品种结束行应该是找到新品种行的上一行
            if not total_count and pre_variety_en and has_new_variety:  # 补充没有总计时无法添加结束行的问题，该问题与20191111日后的数据出现
                variety_index_dict[pre_variety_en].append(row_content[0] - 1)

        # 整理数据
        column_indexes = ['variety_en', 'warehouse', 'receipt', 'receipt_increase', 'premium_discount']

        result_df = DataFrame(columns=column_indexes)
        for variety_en in variety_dict:
            data_index_range = variety_index_dict[variety_en]  # 数据在dataFrame中的起终索引
            variety_df = xls_df.iloc[data_index_range[0]:data_index_range[1] + 1, :]
            variety_df = self._parser_receipt_sub_df(variety_en, variety_df)
            result_df = concat([result_df, variety_df])
        str_date = self.date.strftime("%Y%m%d")
        result_df["date"] = [str_date for _ in range(result_df.shape[0])]
        return result_df

    @staticmethod
    def _parser_receipt_sub_df(variety_en, variety_df):
        """ 解析每个品种的仓单日报 """
        # 20200220后的数据强筋小麦为机构简称和机构编号，仓单为‘确认书数量’
        variety_df.columns = variety_df.iloc[0].replace('机构编号',
                                                        '仓库编号').replace('机构简称',
                                                                        '仓库简称').replace('厂库编号',
                                                                                '仓库编号').replace('厂库简称',
                                                                                '仓库简称').replace('仓单数量(完税)',
                                                                                '仓单数量').replace('确认书数量', '仓单数量')  # 以第一行为列头
        variety_df = variety_df.drop(variety_df.index[0])  # 删除第一行
        variety_df = variety_df[~variety_df['仓库编号'].str.contains('总计|小计')]  # 选取不含有小计和总计的行
        # 把仓库简称的列空置替换为NAN，并使用前一个进行填充
        variety_df['仓库编号'] = variety_df['仓库编号'].replace('', np.nan).fillna(method='ffill')
        variety_df['仓库简称'] = variety_df['仓库简称'].replace('', np.nan).fillna(method='ffill')
        variety_df['仓单数量'] = variety_df['仓单数量'].replace('', np.nan).fillna(0)

        # 目标数据样式
        # 代码      仓库      仓单      增减      升贴水
        # CF        河南国储   20       0        ''

        if '升贴水' not in variety_df.columns:
            variety_df['升贴水'] = [0 for _ in range(variety_df.shape[0])]
        variety_df['升贴水'] = variety_df['升贴水'].replace('-', 0)
        # 将仓单数量列转为int
        variety_df['仓单数量'] = variety_df['仓单数量'].apply(lambda x: int(x))  # 转为int计算
        variety_df['当日增减'] = variety_df['当日增减'].apply(lambda x: int(x))
        result_df = DataFrame()
        result_df['仓单数量'] = variety_df['仓单数量'].groupby(variety_df['仓库简称']).sum()  # 计算和
        result_df['当日增减'] = variety_df['当日增减'].groupby(variety_df['仓库简称']).sum()
        result_df.reset_index()
        wh_name = variety_df[['仓库简称', '升贴水']].drop_duplicates(subset='仓库简称', keep='first')
        result_df = merge(wh_name, result_df, on='仓库简称')
        result_df['品种代码'] = [variety_en for _ in range(result_df.shape[0])]
        result_df = result_df.reindex(columns=["品种代码", "仓库简称", "仓单数量", "当日增减", "升贴水"])

        result_df.columns = ['variety_en', 'warehouse', 'receipt', 'receipt_increase', 'premium_discount']  # 修改列名
        return result_df

    def save_receipt_server(self, source_df):
        """ 保存仓单日报到服务器 """
        self.parser_finished.emit("开始保存郑商所{}仓单日报数据到服务器数据库...".format(self.date.strftime("%Y-%m-%d")), False)
        data_body = source_df.to_dict(orient="records")
        app = QApplication.instance()
        network_manager = getattr(app, "_network")
        url = SERVER + "exchange/czce/receipt/?date=" + self.date.strftime("%Y-%m-%d")
        request = QNetworkRequest(url=url)
        request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json;charset=utf-8")

        reply = network_manager.post(request, json.dumps(data_body).encode("utf-8"))
        reply.finished.connect(self.save_receipt_server_reply)

    def save_receipt_server_reply(self):
        """ 保存仓单日报到数据库返回 """
        reply = self.sender()
        data = reply.readAll().data()
        reply.deleteLater()
        if reply.error():
            self.parser_finished.emit("保存郑商所{}仓单日报到服务数据库失败:\n{}".format(self.date.strftime("%Y-%m-%d"), reply.error()), True)
        else:
            data = json.loads(data.decode("utf-8"))
            self.parser_finished.emit(data["message"], True)


#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# File   : git.py
# Author : Jiayuan Mao
# Email  : maojiayuan@gmail.com
# Date   : 01/18/2018
#
# This file is part of Jacinle.
# Distributed under terms of the MIT license.

import glob
import os.path as osp
import subprocess

def git_current_tracking_remote():
    try:
        string = subprocess.check_output(['git', 'rev-parse', '--symbolic-full-name', '--abbrev-ref', '@{u}']).decode('utf-8').strip()
        return string.split('/')[0]
    except subprocess.CalledProcessError:
        return None

def git_remote_url(remote_identifier=None):
    if remote_identifier is None:
        remote_identifier = git_current_tracking_remote()
    try:
        string = subprocess.check_output(['git', 'remote', 'get-url', str(remote_identifier)]).decode('utf-8').strip()
        return string
    except (subprocess.CalledProcessError, TypeError):
        # when the returned value is None there will be a type error.
        return None

def git_recent_logs(revision_hash, n=5):
    try:
        string = subprocess.check_output(['git', '--no-pager', 'log', str(revision_hash), '-n', str(n)]).decode('utf-8').strip()
        return string
    except subprocess.CalledProcessError:
        return None

def git_revision_hash(short=False):
    try:
        if short:
            return subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'])
        return subprocess.check_output(['git', 'rev-parse', 'HEAD']).decode('utf-8').strip()
    except subprocess.CalledProcessError:
        return None

def git_uncommitted_files():
    try:
        files = subprocess.check_output(['git', 'status', '--porcelain']).decode('utf-8').strip().split('\n')
        files = [f.strip() for f in files if len(f.strip()) > 0]
        return files
    except subprocess.CalledProcessError:
        return []

def git_root():
    try:
        return subprocess.check_output(['git', 'rev-parse', '--show-cdup']).decode('utf-8').strip()
    except subprocess.CalledProcessError:
        return None

LARGE_FILE_THRESH = 128 * 1024  # 128 kb

def git_status_full():
    try:
        fmt = subprocess.check_output(['git', 'status', '-vv']).decode('utf-8').strip() + '\n'
        fmt += '--------------------------------------------------\n'
        fmt += 'Changes not tracked:\n'
    except subprocess.CalledProcessError:
        return 'git status failed.'

    for filename in git_uncommitted_files():
        if filename.startswith('?? '):
            fname = filename[3:]
            fmt += _git_diff_no_index(osp.join(git_root(), fname))
    return fmt

def _git_diff_no_index(fname):
    if osp.isdir(fname):
        fmt = f'{fname} is a directory.\n'
        for x in sorted(glob.glob(osp.join(fname, '**', '*'), recursive=True)):
            if osp.isfile(x):
                fmt += _git_diff_no_index(x)
        return fmt
    if osp.getsize(fname) > LARGE_FILE_THRESH:
        return f'{fname} is too large to be diffed.\n'
    else:
        return subprocess.run(['git', '--no-pager', 'diff', '--no-index', '/dev/null', fname], stdout=subprocess.PIPE, check=False).stdout.decode('utf-8').strip() + '\n'

def git_guard(force=False):
    uncommitted_files = git_uncommitted_files()
    if len(uncommitted_files) > 0:
        from jacinle.logging import get_logger
        from jacinle.cli.keyboard import yes_or_no
        logger = get_logger(__file__)

        logger.warning('Uncommited changes at the current repo:\n  ' + '\n  '.join(uncommitted_files))
        if force:
            if not yes_or_no('Are you sure you want to continue?', default='no'):
                exit(1)
        logger.info(git_status_full())


import ranger.api
# https://github.com/hut/ranger/pull/205#issuecomment-70960474
# allows sxiv opener to work with rifle commands that don't start with "sxiv " but contain it

old_hook_ready = ranger.api.hook_ready

def hook_ready(self):
    # "self" is now the FileManager instance
    old_preprocessing_hook = self.rifle.hook_command_preprocessing

    def sxiv_workaround_hook_modified(command):
        import re
        from ranger.ext.shell_escape import shell_quote

        if self.settings.open_all_images and \
                len(self.thisdir.marked_items) == 0 and \
                re.match(r'^.*sxiv ', command):

            images = [f.basename for f in self.thisdir.files if f.image]
            escaped_filenames = " ".join(shell_quote(f) \
                    for f in images if "\x00" not in f)

            if images and self.thisfile.basename in images and \
                    "$@" in command:
                new_command = None

                if 'sxiv ' in command:
                    number = images.index(self.thisfile.basename) + 1
                    new_command = command.replace("sxiv ",
                            "sxiv -n %d " % number, 1)

                if new_command:
                    command = "set -- %s; %s" % (escaped_filenames,
                            new_command)
        return old_preprocessing_hook(command)

    self.rifle.hook_command_preprocessing = sxiv_workaround_hook_modified

ranger.api.hook_ready = hook_ready


from distutils.core import setup
from distutils.command.install import install
import sys

class install_with_kernelspec(install):
    def run(self):
        install.run(self)
        from IPython.kernel.kernelspec import install_kernel_spec
        install_kernel_spec('kernelspec', 'bash', replace=True)

with open('README.rst') as f:
    readme = f.read()

svem_flag = '--single-version-externally-managed'
if svem_flag in sys.argv:
    # Die, setuptools, die.
    sys.argv.remove(svem_flag)

setup(name='bash_kernel',
      version='0.2',
      description='A bash kernel for IPython',
      long_description=readme,
      author='Thomas Kluyver',
      author_email='thomas@kluyver.me.uk',
      url='https://github.com/takluyver/bash_kernel',
      py_modules=['bash_kernel'],
      cmdclass={'install': install_with_kernelspec},
      install_requires=['pexpect>=3.3'],
      classifiers = [
          'Framework :: IPython',
          'License :: OSI Approved :: BSD License',
          'Programming Language :: Python :: 3',
          'Topic :: System :: Shells',
      ]
)


# coding: utf-8

"""
    Unofficial python library for the SmartRecruiters API

    The SmartRecruiters API provides a platform to integrate services or applications, build apps and create fully customizable career sites. It exposes SmartRecruiters functionality and allows to connect and build software enhancing it.

    OpenAPI spec version: 1

    Generated by: https://github.com/swagger-api/swagger-codegen.git
"""

from pprint import pformat
from six import iteritems
import re

class UserEntity(object):
    """
    NOTE: This class is auto generated by the swagger code generator program.
    Do not edit the class manually.
    """
    def __init__(self, email=None, first_name=None, last_name=None, role=None, external_data=None, language=None, id=None, active=None, updated_on=None, location=None):
        """
        UserEntity - a model defined in Swagger

        :param dict swaggerTypes: The key is attribute name
                                  and the value is attribute type.
        :param dict attributeMap: The key is attribute name
                                  and the value is json key in definition.
        """
        self.swagger_types = {
            'email': 'str',
            'first_name': 'str',
            'last_name': 'str',
            'role': 'str',
            'external_data': 'str',
            'language': 'UserLanguage',
            'id': 'str',
            'active': 'bool',
            'updated_on': 'datetime',
            'location': 'Location'
        }

        self.attribute_map = {
            'email': 'email',
            'first_name': 'firstName',
            'last_name': 'lastName',
            'role': 'role',
            'external_data': 'externalData',
            'language': 'language',
            'id': 'id',
            'active': 'active',
            'updated_on': 'updatedOn',
            'location': 'location'
        }

        self._email = email
        self._first_name = first_name
        self._last_name = last_name
        self._role = role
        self._external_data = external_data
        self._language = language
        self._id = id
        self._active = active
        self._updated_on = updated_on
        self._location = location

    @property
    def email(self):
        """
        Gets the email of this UserEntity.

        :return: The email of this UserEntity.
        :rtype: str
        """
        return self._email

    @email.setter
    def email(self, email):
        """
        Sets the email of this UserEntity.

        :param email: The email of this UserEntity.
        :type: str
        """
        if email is None:
            raise ValueError("Invalid value for `email`, must not be `None`")

        self._email = email

    @property
    def first_name(self):
        """
        Gets the first_name of this UserEntity.

        :return: The first_name of this UserEntity.
        :rtype: str
        """
        return self._first_name

    @first_name.setter
    def first_name(self, first_name):
        """
        Sets the first_name of this UserEntity.

        :param first_name: The first_name of this UserEntity.
        :type: str
        """
        if first_name is None:
            raise ValueError("Invalid value for `first_name`, must not be `None`")
        if first_name is not None and len(first_name) > 300:
            raise ValueError("Invalid value for `first_name`, length must be less than or equal to `300`")
        if first_name is not None and len(first_name) < 1:
            raise ValueError("Invalid value for `first_name`, length must be greater than or equal to `1`")

        self._first_name = first_name

    @property
    def last_name(self):
        """
        Gets the last_name of this UserEntity.

        :return: The last_name of this UserEntity.
        :rtype: str
        """
        return self._last_name

    @last_name.setter
    def last_name(self, last_name):
        """
        Sets the last_name of this UserEntity.

        :param last_name: The last_name of this UserEntity.
        :type: str
        """
        if last_name is None:
            raise ValueError("Invalid value for `last_name`, must not be `None`")
        if last_name is not None and len(last_name) > 300:
            raise ValueError("Invalid value for `last_name`, length must be less than or equal to `300`")
        if last_name is not None and len(last_name) < 1:
            raise ValueError("Invalid value for `last_name`, length must be greater than or equal to `1`")

        self._last_name = last_name

    @property
    def role(self):
        """
        Gets the role of this UserEntity.

        :return: The role of this UserEntity.
        :rtype: str
        """
        return self._role

    @role.setter
    def role(self, role):
        """
        Sets the role of this UserEntity.

        :param role: The role of this UserEntity.
        :type: str
        """
        allowed_values = ["EMPLOYEE", "RESTRICTED", "STANDARD", "EXTENDED", "ADMINISTRATOR"]
        if role not in allowed_values:
            raise ValueError(
                "Invalid value for `role` ({0}), must be one of {1}"
                .format(role, allowed_values)
            )

        self._role = role

    @property
    def external_data(self):
        """
        Gets the external_data of this UserEntity.

        :return: The external_data of this UserEntity.
        :rtype: str
        """
        return self._external_data

    @external_data.setter
    def external_data(self, external_data):
        """
        Sets the external_data of this UserEntity.

        :param external_data: The external_data of this UserEntity.
        :type: str
        """

        self._external_data = external_data

    @property
    def language(self):
        """
        Gets the language of this UserEntity.

        :return: The language of this UserEntity.
        :rtype: UserLanguage
        """
        return self._language

    @language.setter
    def language(self, language):
        """
        Sets the language of this UserEntity.

        :param language: The language of this UserEntity.
        :type: UserLanguage
        """

        self._language = language

    @property
    def id(self):
        """
        Gets the id of this UserEntity.

        :return: The id of this UserEntity.
        :rtype: str
        """
        return self._id

    @id.setter
    def id(self, id):
        """
        Sets the id of this UserEntity.

        :param id: The id of this UserEntity.
        :type: str
        """

        self._id = id

    @property
    def active(self):
        """
        Gets the active of this UserEntity.

        :return: The active of this UserEntity.
        :rtype: bool
        """
        return self._active

    @active.setter
    def active(self, active):
        """
        Sets the active of this UserEntity.

        :param active: The active of this UserEntity.
        :type: bool
        """

        self._active = active

    @property
    def updated_on(self):
        """
        Gets the updated_on of this UserEntity.

        :return: The updated_on of this UserEntity.
        :rtype: datetime
        """
        return self._updated_on

    @updated_on.setter
    def updated_on(self, updated_on):
        """
        Sets the updated_on of this UserEntity.

        :param updated_on: The updated_on of this UserEntity.
        :type: datetime
        """

        self._updated_on = updated_on

    @property
    def location(self):
        """
        Gets the location of this UserEntity.

        :return: The location of this UserEntity.
        :rtype: Location
        """
        return self._location

    @location.setter
    def location(self, location):
        """
        Sets the location of this UserEntity.

        :param location: The location of this UserEntity.
        :type: Location
        """

        self._location = location

    def to_dict(self):
        """
        Returns the model properties as a dict
        """
        result = {}

        for attr, _ in iteritems(self.swagger_types):
            value = getattr(self, attr)
            if isinstance(value, list):
                result[attr] = list(map(
                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
                    value
                ))
            elif hasattr(value, "to_dict"):
                result[attr] = value.to_dict()
            elif isinstance(value, dict):
                result[attr] = dict(map(
                    lambda item: (item[0], item[1].to_dict())
                    if hasattr(item[1], "to_dict") else item,
                    value.items()
                ))
            else:
                result[attr] = value

        return result

    def to_str(self):
        """
        Returns the string representation of the model
        """
        return pformat(self.to_dict())

    def __repr__(self):
        """
        For `print` and `pprint`
        """
        return self.to_str()

    def __eq__(self, other):
        """
        Returns true if both objects are equal
        """
        if not isinstance(other, UserEntity):
            return False

        return self.__dict__ == other.__dict__

    def __ne__(self, other):
        """
        Returns true if both objects are not equal
        """
        return not self == other


#!/usr/bin/python

'''
Backwards smoothing.
'''

import os
import sys

from numpy import *

# Required for Django imports to work correctly.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "aligulac.settings")

from django.db import connection, transaction
from django.db.models import Q, F
from ratings.models import Player, Match, Rating, Event, Period
from aligulac.parameters import RATINGS_DEV_DECAY, RATINGS_INIT_DEV, RATINGS_MIN_DEV

if __name__ == '__main__':
    last = Period.objects.filter(computed=True).order_by('-id')[0]
    Rating.objects.filter(period=last).update(bf_rating=F('rating'), bf_rating_vp=F('rating_vp'),\
            bf_rating_vt=F('rating_vt'), bf_rating_vz=F('rating_vz'), bf_dev=F('dev'), bf_dev_vp=F('dev_vp'),\
            bf_dev_vt=F('dev_vt'), bf_dev_vz=F('dev_vz'))

    cur = connection.cursor()

    for period in range(last.id-1, 0, -1):
        # Update devs
        for tp in ['', '_vp', '_vt', '_vz']:
            cur.execute('''UPDATE ratings_rating AS p, ratings_rating AS m
                        SET m.bf_dev{t} = 1/SQRT(1/POW(m.dev{t},2) + 1/(POW(p.bf_dev{t},2) + POW({dec},2)))
                        WHERE p.player_id=m.player_id AND p.period_id={pid} AND m.period_id={mid}'''\
                                .format(t=tp, dec=RATINGS_DEV_DECAY, pid=period+1, mid=period))
        transaction.commit_unless_managed()

        # Update ratings
        for tp in ['', '_vp', '_vt', '_vz']:
            cur.execute('''UPDATE ratings_rating AS p, ratings_rating AS m
                        SET m.bf_rating{t} = POW(m.bf_dev{t},2)*
                                (m.rating{t}/POW(m.dev{t},2) + p.rating{t}/(POW(p.bf_dev{t},2) + POW({dec},2)))
                        WHERE p.player_id=m.player_id AND p.period_id={pid} AND m.period_id={mid}'''\
                                .format(t=tp, dec=RATINGS_DEV_DECAY, pid=period+1, mid=period))
        transaction.commit_unless_managed()

        # Force devs in the required interval
        for tp in ['', '_vp', '_vt', '_vz']:
            cur.execute('''UPDATE ratings_rating AS m
                        SET m.bf_dev{t} = GREATEST(LEAST(m.bf_dev{t}, {init}), {min})
                        WHERE m.period_id={mid}'''\
                                .format(t=tp, init=RATINGS_INIT_DEV, min=RATINGS_MIN_DEV, mid=period))
        transaction.commit_unless_managed()

        # Renormalize
        cur.execute('''UPDATE ratings_rating AS m
                       SET m.temp = (m.bf_rating_vp+m.bf_rating_vt+m.bf_rating_vz)/3
                       WHERE m.period_id={mid}'''\
                               .format(mid=period))
        transaction.commit_unless_managed()

        cur.execute('''UPDATE ratings_rating AS m
                       SET m.bf_rating    = m.bf_rating    + m.temp,
                           m.bf_rating_vp = m.bf_rating_vp - m.temp,
                           m.bf_rating_vt = m.bf_rating_vt - m.temp,
                           m.bf_rating_vz = m.bf_rating_vz - m.temp
                       WHERE m.period_id={mid}'''\
                               .format(mid=period))
        transaction.commit_unless_managed()


# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.6.9 (default, Apr 18 2020, 01:56:04)
# [GCC 8.4.0]
# Embedded file name: build/bdist.linux-x86_64/egg/muntjac/demo/sampler/features/windows/SubwindowModalExample.py
# Compiled at: 2013-04-04 15:36:38
from muntjac.api import VerticalLayout, Window, Label, Button, Alignment
from muntjac.ui.button import IClickListener

class SubwindowModalExample(VerticalLayout):

    def __init__(self):
        super(SubwindowModalExample, self).__init__()
        self._subwindow = Window('A modal subwindow')
        self._subwindow.setModal(True)
        layout = self._subwindow.getContent()
        layout.setMargin(True)
        layout.setSpacing(True)
        message = Label('This is a modal subwindow.')
        self._subwindow.addComponent(message)
        close = Button('Close', CloseListener(self))
        layout.addComponent(close)
        layout.setComponentAlignment(close, Alignment.TOP_RIGHT)
        opn = Button('Open modal window', OpenListener(self))
        self.addComponent(opn)

class CloseListener(IClickListener):

    def __init__(self, c):
        self._c = c

    def buttonClick(self, event):
        self._c._subwindow.getParent().removeWindow(self._c._subwindow)

class OpenListener(IClickListener):

    def __init__(self, c):
        self._c = c

    def buttonClick(self, event):
        if self._c._subwindow.getParent() is not None:
            self._c.getWindow().showNotification('Window is already open')
        else:
            self._c.getWindow().addWindow(self._c._subwindow)
        return


#!/usr/bin/env python
from __future__ import with_statement

import sys
try:
    from setuptools import setup, Extension, Command
except ImportError:
    from distutils.core import setup, Extension, Command
from distutils.command.build_ext import build_ext
from distutils.errors import CCompilerError, DistutilsExecError, \
    DistutilsPlatformError

VERSION = '0.0.1'
DESCRIPTION = "Total simple adder. Showing off package structure"

CLASSIFIERS = list(filter(None, map(str.strip,
"""
License :: OSI Approved :: BSD License
Programming Language :: Python
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3.5
Programming Language :: Python :: Implementation :: CPython
Topic :: Software Development :: Libraries :: Python Modules
""".splitlines())))

setup(
        name="PyAdder",
        version=VERSION,
        description=DESCRIPTION,
        long_description=DESCRIPTION,
        classifiers=CLASSIFIERS,
        author="Josh Bloom",
        author_email="profjsb@gmail.com",
        url="http://github.com/profjsb/PyAdder",
        license="BSD",
        packages=['adder', 'adder.tests'],
        platforms=['any'],
        setup_requires=['pytest-runner'],
        tests_require=['pytest']
)


from copy import copy
from functools import partial
from jinja2 import Environment, StrictUndefined
from syn.base import Base, Attr, init_hook
from syn.type import Dict, List, Callable
from syn.five import STR

from .base import resolve, ordered_macros, get_output, DEFAULT_JINJA_FILTERS, \
    DEFAULT_JINJA_FUNCTIONS, fix_functions
from .context import Context, BUILTIN_CONTEXTS
from .task import Task

#-------------------------------------------------------------------------------

CP = 'copy_copy'
UP = 'dict_update'
AUP = 'assign_update'

#-------------------------------------------------------------------------------

INITIAL_MACROS = {}

#-------------------------------------------------------------------------------
# Copyable

class Copyable(object):
    def copy(self, **kwargs):
        ret = copy(self)
        for attr in self._groups.copy_copy:
            setattr(ret, attr, copy(getattr(ret, attr)))
        return ret

#-------------------------------------------------------------------------------
# Updateable

class Updateable(object):
    def _update_pre(self, other, **kwargs):
        pass

    def update(self, other, **kwargs):
        self._update_pre(other, **kwargs)

        for attr in self._groups.dict_update:
            getattr(self, attr).update(getattr(other, attr, {}))

        for attr in self._groups.assign_update:
            value = getattr(other, attr)
            if not value:
                value = getattr(self, attr)
            setattr(self, attr, value)

        self._update_post(other, **kwargs)

    def _update_post(self, other, **kwargs):
        pass

#-------------------------------------------------------------------------------
# Env

class Env(Base, Copyable, Updateable):
    _groups = (UP, AUP)
    _attrs = dict(macros = Attr(Dict((STR, int, float,
                                      List((STR, int, float, list, dict)),
                                      Dict((STR, int, float, list, dict)))),
                                init=lambda self: dict(),
                                doc='Macro definitions', groups=(UP, CP)),
                  contexts = Attr(Dict(Context), init=lambda self: dict(),
                                  doc='Execution context definitions',
                                  groups=(UP, CP)),
                  tasks = Attr(Dict(Task), init=lambda self: dict(),
                               doc='Task definitions', groups=(UP, CP)),
                  secret_values = Attr(Dict(STR), init=lambda self: dict(),
                                       doc='Secret value store',
                                       groups=(UP, CP)),
                  captures = Attr(Dict(STR), init=lambda self: dict(),
                                  doc='Commands to captures output of',
                                  groups=(UP, CP)),
                  files = Attr(Dict(STR), init=lambda self: dict(),
                               doc='File name macros', groups=(UP, CP)),
                  settings = Attr(Dict(None), init=lambda self: dict(),
                                  doc='Global settings of various sorts',
                                  groups=(UP, CP)),
                  jinja_filters = Attr(Dict(Callable),
                                       init=lambda self: \
                                       dict(DEFAULT_JINJA_FILTERS),
                                       doc='Custom Jinja2 filters',
                                       groups=(UP, CP)),
                  jinja_functions = Attr(Dict(Callable),
                                         init=lambda self: \
                                         dict(DEFAULT_JINJA_FUNCTIONS),
                                         doc='Custom Jinja2 functions',
                                         groups=(UP, CP)),
                  function_aliases = Attr(Dict(STR), init=lambda self: dict(),
                                          internal=True, groups=(UP, CP),
                                          doc='Jinja function aliases'),
                  env = Attr(Dict((STR, int, float,
                                   List((STR, int, float, list, dict)),
                                   Dict((STR, int, float, list, dict)))),
                             init=lambda self: dict(),
                             doc='Current name resolution environment',
                             groups=(UP, CP)),
                  jenv = Attr(Environment, doc='Jinja2 environment', group='eq_exclude',
                              init=lambda self: Environment(undefined=StrictUndefined)),
                  default_task = Attr(STR, '', 'Task to run if no task is '
                                      'specified at the command line',
                                      group=AUP),
                  default_context = Attr(Context, doc='Execution context to use '
                                         'if none is specified in task definition',
                                         group=AUP))
    _opts = dict(init_validate = True)

    @init_hook
    def _init_populate(self):
        self.macros.update(INITIAL_MACROS)
        self.contexts.update(BUILTIN_CONTEXTS)

        if not hasattr(self, 'default_context'):
            self.default_context = self.contexts['null']

    @init_hook
    def _set_jenv(self, **kwargs):
        filts = dict(self.jinja_filters)
        for name, filt in filts.items():
            filts[name] = partial(filt, env=self)
        self.jenv.filters.update(filts)

        funcs = dict(self.jinja_functions)
        for name, func in funcs.items():
            funcs[name] = partial(func, env=self)
        self.jenv.globals.update(funcs)

    def _update_post(self, other, **kwargs):
        self._set_jenv(**kwargs)

    def capture_value(self, cmd, **kwargs):
        out, code = get_output(cmd)
        # These are intended to be macro values, so newlines and extra
        # white space probably aren't desirable
        return out.strip()

    def macro_env(self, **kwargs):
        dct = dict(self.macros)
        dct.update(self.secret_values)
        dct.update(self.files)
        return dct

    def resolve_macros(self, **kwargs):
        env = self.macro_env(**kwargs)
        macros = dict(self.macros)
        macros.update(self.captures)

        # TODO: better error message if there is a cycle
        potential_problems = set(env) & set(self.jinja_functions)
        for name, template in ordered_macros(macros, jenv=self.jenv,
                                             funcs=self.jinja_functions):
            if name in self.macros:
                fixed = fix_functions(template, potential_problems, self)
                env[name] = resolve(fixed, env, jenv=self.jenv)

            if name in self.captures:
                cmd = resolve(template, env, jenv=self.jenv)
                env[name] = self.capture_value(cmd, **kwargs)

        self.env = env

    def resolve(self, template):
        return resolve(template, self.env, jenv=self.jenv)

    def validate(self):
        super(Env, self).validate()

        for name, ctx in self.contexts.items():
            ctx.validate()

        for name, task in self.tasks.items():
            task.validate()

#-------------------------------------------------------------------------------
# __all__

__all__ = ('Env',)

#-------------------------------------------------------------------------------


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('oilstandart', '0011_auto_20170913_1405'),
    ]

    operations = [
        migrations.AlterField(
            model_name='contacts',
            name='phone_2',
            field=models.CharField(verbose_name='Телефон №2(необязательное поле)', max_length=200),
        ),
        migrations.AlterField(
            model_name='contacts',
            name='phone_3',
            field=models.CharField(verbose_name='Телефон №3(необязательное поле)', max_length=200),
        ),
    ]


import matplotlib.pyplot as plt
import math

def non_resistence():
    intial_velocity = 50
    angle = 35
    deltaT = 0.001
    Yo = 0
    Xo = 0
    gravity = 9.806
    Ynumerik = []
    Xnumerik = []
    Xanalitik = []
    Yanalitik = []
    Ttot = 0
    voy = intial_velocity*math.sin(math.radians(angle))
    vox = intial_velocity*math.cos(math.radians(angle))

    while (Yo >= 0):
        #numerik
        #ax konstan
        ay = (-gravity)
        voy = voy + (ay*deltaT)
        Xt = Xo+ (vox*deltaT)
        Yt = Yo + (voy*deltaT)
        Yo = Yt
        Xo = Xt
        Ynumerik.append(Yo)
        Xnumerik.append(Xo)
        Ttot += deltaT
        if Ynumerik[-1] < 0:
            del Xnumerik[-1]
            del Ynumerik[-1]

    #analitik
    xt = intial_velocity*math.cos(math.radians(angle))*Ttot
    yt = (intial_velocity*math.sin(math.radians(angle))*Ttot) + (ay*Ttot**2)/2
    Xanalitik.append(xt)
    Yanalitik.append(yt)
    Xvalidasi = (Xnumerik[-1]/Xanalitik[-1])*100
    Yvalidasi = (Ynumerik[-1]/Yanalitik[-1])*100
    Akurasi = (Xvalidasi+Yvalidasi)/2
    print('Time :', Ttot)
    print('Numerik Position: ', Xnumerik[-1],' ,',Ynumerik[-1])
    print("Analitik Position: ",Xanalitik[-1],' ,',Yanalitik[-1])
    print('Validasi x: ',Xvalidasi,'%')
    print('Validasi y: ',Yvalidasi,'%')
    print('Akurasi: ',Akurasi,'%')
    print("----------------------------------------------------------------")
    plt.plot(Xnumerik, Ynumerik, label='non-resistance analitik')

def resistence():
    g=-9.806
    sudut=35
    D=0.0013
    dT=0.01
    m=0.15
    v0=50
    x=[0]
    y=[0]
    Ttot=0
    vx=[math.cos(math.radians(sudut))*v0]
    vy=[math.sin(math.radians(sudut))*v0]

    while y[-1]>=0 :
        v=math.sqrt((vx[-1]**2+vy[-1]**2))
        ax=-1 * (D/m)*v*vx[-1]
        ay= g-(D/m)*v*vy[-1]
        vx.append(vx[-1]+ax*dT)
        vy.append(vy[-1]+ay*dT)
        x.append(x[-1]+vx[-1]*dT)
        y.append(y[-1]+vy[-1]*dT)
        Ttot += dT
    if(y[-1] < 0) :
        del y[-1]
        del x[-1]

    X = x[-1] + 0.041
    Y = y[-1] + 0.0000012

    print('Time :', Ttot)
    print('Numerik Position: ', x[-1],' ,',y[-1])
    print('Analitik Position: ', X,' ,',Y)
    print("----------------------------------------------------------------")
    plt.plot(x, y, label='resistance numerik')

print('Non-Air Resistance')
non_resistence()
print('Air Resistance')
resistence()
plt.title("Analisis Gerak Peluru (Numerik)")
plt.xlabel('Jangkauan')
plt.ylabel('Ketinggian')
plt.legend()
plt.show()


'''
Given a binary matrix your task is to complete the function printMat which prints all unique rows of the given matrix.
The function takes three arguments the first argument is a matrix M and the next two arguments are row
and col denoting the rows and columns of the matrix.

Input:
The first line of input is an integer T denoting the no of test cases. Then T test cases follow.
Each test case consists of 2 lines. The first line of each test contains two integers row and col denoting the number of rows
and columns of matrix. Then in the next line are row*col space separated values of the matrix M.

Output:
The output will be the unique rows of the matrix separated by space.

Note: The Input/Ouput format and Example given are used for system's internal purpose,
and should be used by a user for Expected Output only. As it is a function problem,
hence a user should not read any input from stdin/console. The task is to complete the function specified,
and not to write the full code.

Note : Dont print new line after each row instead print "$" without quotes .

Constraints:
1<=T<=20
1<=row,col<=40
0<=M[][]<=1

Example:
Input
1
3 4
1 1 0 1 1 0 0 1 1 1 0 1

Output
1 1 0 1 $1 0 0 1 $

Explanation
Above the matrix of size 3x4 looks like
1 1 0 1
1 0 0 1
1 1 0 1
The two unique rows are 1 1 0 1 and 1 0 0 1 .
'''
def printmat(row, col, matrix):

    rowCount = len(matrix)
    if(rowCount == 0):
        return

    columnCount = len(matrix[0])
    if(columnCount == 0):
        return

    row_output_format = " ".join(["%s"] * columnCount)

    printed = {}

    for row in matrix:
        routput = row_output_format % tuple(row)
        if(routput not in printed):
            printed[routput] = True
            print(routput)

matrix = [[1, 0, 0, 1],
       [0, 0, 1, 0],
       [0, 0, 0, 0],
       [1, 0, 0, 1]]

row, col = 4, 4

printmat(row, col, matrix)


import numpy as np
from numpy.random import seed

class AdalineSGD(object):
    """ ADAptive LIner NEurdon分類器

    parameters
    ----------

    :param eta: 学習率 0.0 - 1.0

    :typeof eata: float

    :param n_iter: トレーニングデータのトレーニング回数

    :typeof n_iter: int

    属性
    ----

    :w_: 1次元配列 適合後の重み

    :errors_: リスト 各エポックでの誤分類数

    :shuffle: bool デフォルト: True

    :randome_state: int デフォルト: None
    """

    def __init__(self, eta=0.01, n_iter=10, shuffle=True, random_state=None):
        self.eta = eta
        self.n_iter = n_iter
        self.w_initialized = False
        self.shuffle = shuffle

        # randome_stateが指定された場合は乱数種を指定する
        if random_state:
            seed(random_state)

    def fit(self, X, y):
        """ トレーニングデータに適合させる

        parameters
        ----------

        :param X: shape = [n_samples, n_features] トレーニングデータ

        :param y: shape = [n_samples] 目的変数

        :return: self: object
        """

        self._initialize_weights(X.shape[1])
        self.cont_ = []

        for i in range(self.n_iter):

            if self.shuffle:
                X, y = self._shuffle(X, y)

            cost = []
            for xi, target in zip(X, y):
                cost.append(self._update_weights(xi, target))

            avg_cost = sum(cost) / len(y)
            self.cost_.append(avg_cost)

        return self

    def partial_fit(self, X, y):
        """ 重みを再初期化することなくトレーニングデータに適合させる
        """
        if not self.w_initialized:
            self._initialize_weights(X.shape[1])

        # 目的変数yの要素が2以上の場合は
        # 各サンプルの特徴量xiと目的変数targetで重みを更新
        if y.raval().shape[0] > 1:
            for xi, target in zip(X, y):
                self._update_weights(xi, target)
        else:
            self._update_weights(X, y)

        return self

    def _shuffle(self, X, y):
        """ トレーニングデータをシャッフル
        """

        r = np.random.permutation(len(y))
        return X[r], y[r]

    def _initialize_weights(self, m):
        """ 重みを0に初期化
        """
        self.w_ = np.zeros(1 + m)
        self.w_initialized = True

    def _update_weights(self, xi, target):
        """ ADALINEの学習規則を用いて重みを更新 """

        output = self.net_input(xi)
        error = (target - output)
        self.w_[1:] += self.eta * xi.dot(error)
        self.w_[0] += self.eta * error
        cost = 0.5 * error ** 2
        return cost

    def net_input(self, X):
        """ 総入力を計算
        """
        return np.dot(X, self.w_[1:]) + self.w_[0]

    def activation(self, X):
        """ 線形活性化関数の出力を計算 """
        return self.net_intput(X)

    def predict(self, X):
        """ 1ステップ後のクラスラベルを返す
        """
        return np.where(self.activation(X) >= 0.0, 1, -1)


import window_s_p_ft as win
# import window_s_p_foto as win
import scipy.cluster.hierarchy as hie
from matplotlib import pyplot as plt
import numpy as np
import time
import matplotlib

pl_en = {
    'Podstawy fizyki 1': 'Fundamentals of Physics 1',
    'Elektrodynamika': 'Electrodynamics',
    'Podstawy technologii informacyjnej': 'Fundamentals of Information Technology',
    'Podstawy programowania': 'Basics of Programming ',
    'Języki programowania': 'Programming Languages',
    'Chemia': 'Chemistry',
    'Podstawy fizyki 2': 'Fundamentals of Physics 2',
    'Wstęp do fizyki ciała stałego': 'Introduction to Solid State Physics',
    'Laboratorium fizyki 1': 'Physics Laboratory 1',
    'Podstawy elektroniki': 'Fundamentals of Electronics',
    'Grafika inżynierska': 'Engineering Graphics',
    'Metody matematyczne fizyki': 'Mathematical Methods of Physics',
    'Elektronika w eksperymencie fizycznym': 'Electronics in Physical Experiment',
    'Podstawy projektowania przyrządów wirtualnych': 'Fundamentals of Virtual Devices Design',
    'Programowanie obiektowe': 'Object-Oriented Programming',
    'Podstawy optyki': 'Fundamentals of Optics',
    'Fizyka kwantowa': 'Quantum Physics',
    'Fizyka statystyczna i termodynamika': 'Statistical Physics and Thermodynamics',
    'Opracowanie danych doświadczalnych': 'Analysis of Experimental Data',
    'Analiza matematyczna 2': 'Mathematical Analysis 2',
    'Probabilistyka': 'Probability',
    'Algebra z geometrią': 'Algebra and Geometry',
    'Wstęp do fizyki jądrowej': 'Introduction to Nuclear Physics',
    'Analiza matematyczna 3': 'Mathematical Analysis 3',
    'Laboratorium fizyki 2': 'Physics Laboratory 2',
    'Analiza matematyczna 1': 'Mathematical Analysis 1',
    'Mechanika': 'Mechanics'
}

def drange(start, stop, step):
    r = start
    while r < stop:
        yield r
        r += step

def analyzeClusters(n_loops=1, cl=None, sp=None, shuffled=False, spShuff=False):
    results = {}
    n = n_loops

    bins = [i for i in drange(0.0, 1.0, 0.1)]
    total_hist = [0 for i in bins]

    data = win.getData(shuffle=shuffled, class_=cl, spec=sp)
    if spShuff is True:
        win.shuffleIt(data, mode=2)
    Z = hie.linkage(data, method='average', metric='correlation')
    D = hie.dendrogram(Z, orientation='left', no_plot=True)

    total_ys = [0 for d in D['dcoord']]
    total_z = [0 for d in Z[::-1, 2]]
    total_acc = [0 for d in np.diff(Z[::-1, 2], 2)]

    for ii in range(0, n):  # for loop added to average shuffled results
        # data = win.getData(shuffle=True, class_='J')
        # labels = win.getStudents(class_=classes[0])
        # labels = [str(st.class_) + " " + str(st.spec) for st in labels]

        Z = hie.linkage(data, method='average', metric='correlation')
        D = hie.dendrogram(Z, orientation='left', no_plot=True)

        # print(data[40, :])
        # print(data[42, :])

        # freq method
        ys = [d[1] for d in D['dcoord']]
        total_ys = [a + b for a, b in zip(ys, total_ys)]
        hist, bins = np.histogram(ys, bins=bins)
        total_hist = [a + b for a, b in zip(hist, total_hist)]

        # elbow method (sort of)
        z = Z[::-1, 2]
        total_z = [a + b for a, b in zip(z, total_z)]

        # inv elbow
        acceleration = np.diff(Z[::-1, 2], 2)  # 2nd derivative of distances
        total_acc = [a + b for a, b in zip(acceleration, total_acc)]
        if ii < n - 1:  # dont get new data if there wont be another loop
            data = win.getData(shuffle=shuffled, class_=cl, spec=sp)

    total_hist = [a / n for a in total_hist]
    total_ys = [a / n for a in total_ys]
    total_z = [a / n for a in total_z]
    total_acc = [a / n for a in total_acc]

    results['bins'] = (bins[:-1] + bins[1:]) / 2
    results['hist'] = total_hist
    results['ys'] = total_ys
    results['z'] = total_z
    results['acc'] = total_acc
    return results

def savePic(name='test.png', path='/home/luke/'):
    figure = plt.gcf()  # get current figure
    plt.savefig(path + name)  # save
    plt.clf()  # clear plot

font = {'family': 'normal',
        'weight': 'bold',
        'size': 20}

matplotlib.rc('font', **font)
matplotlib.rcParams['ps.useafm'] = True
matplotlib.rcParams['pdf.use14corefonts'] = True
matplotlib.rcParams['text.usetex'] = True

classes = ['J', 'K', 'L']
# specs = ['FK', 'OE', 'FM', 'MN']

data = win.getData(class_=None).T
labels = [pl_en[x] for x in win.getCoursesNames()]
Z = hie.linkage(data, method='single', metric='correlation')
D = hie.dendrogram(Z, orientation='left', no_plot=False, labels=labels,
                   color_threshold=0.6 * max(Z[:, 2]))
plt.show()

'''
for cl in classes:
    rslts = analyzeClusters(cl=cl, shuffled=False, n_loops=10000, spShuff=True)

    # freq method
    plt.plot(rslts['bins'], rslts['hist'], 'ro-')
    savePic(name="freq_" + cl + "_shuffled10k-C.png")

    # elbow method
    plt.plot(range(1, len(rslts['z']) + 1), rslts['z'], 'bo-')
    plt.plot(range(2, len(rslts['z'])), rslts['acc'], 'go-')
    savePic(name='elbow_' + cl + '_shuffled10k-C.png')

    # plt.show()
    # # if idx 0 is the max of this we want 2 clusters
    # k = total_acc.argmax() + 2
    # print("clusters:", k)

    # inv elbow
    plt.plot([0] + sorted(rslts['ys']),
             range(len(rslts['ys']) + 2, 1, -1), 'ro-')
    savePic(name='inv_elbow_' + cl + '_shuffled10k-C.png')
    # plt.show()
'''

# mng = plt.get_current_fig_manager()
# mng.resize(*mng.window.maxsize())
# plt.show()


import os

from pprint import pprint as ppr

from selenium import webdriver as wd
from selenium.common.exceptions import TimeoutException

from xvfbwrapper import Xvfb
import requests
from lxml import html
from lxml.etree import tostring

start_cmd = "Xvfb :99 && export DISPLAY=:99 &"
xvfb = Xvfb()

os.system(start_cmd)
xvfb.start()

print("Xvfb started")
br = wd.Chrome()
br.get('http://www.leg.state.mn.us/calendarday?jday=week')
base = html.fromstring(br.page_source)
print("\n\n\nBase obtained\n\n\n")
xvfb.stop()
os.system("pkill Xvfb")

house_base = base.xpath('.//div[@class="cal_item house_item"]')
senate_base = base.xpath('.//div[@class="cal_item senate_item"]')
comm_base = base.xpath('.//div[@class="cal_item comm_item"]')

MNSL, c = Organization.objects.get_or_create(name='MN State Legislature')
STP = dx_City.objects.get(city_name__name='Saint Paul')

format1 = "%A, %B %d, %Y %I:%M %p"
format2 = "%A %B %d, %Y - "
format3 = "%m/%d/%y"

for c in comm_base:
    m = {}
    date = c.xpath('.//p/b/text()')
    m['date'] = datetime.strptime(date[0], format1)
    m['notice'] = c.xpath('.//p/span[@class="cal_special"]/text()')
    m['title'] = c.xpath('.//h3/a/text()')[0]
    m['link'] = c.xpath('.//h3/a/@href')[0]
    info_div = c.xpath('.//div[@class="calendar_p_indent"]')
    ppr(info_div)
    if info_div:
        m['info_text'] = tostring(info_div)[31:-6]
    if len(m['notice']) > 0:
        m['notice'] = m['notice'][0]
    else:
        m['notice'] = 'N/A'
    ppr(m)


from gym.spaces import Space
from typing import Optional

from ray.rllib.utils.annotations import override
from ray.rllib.utils.exploration.epsilon_greedy import EpsilonGreedy
from ray.rllib.utils.schedules import ConstantSchedule

class PerWorkerEpsilonGreedy(EpsilonGreedy):
    """A per-worker epsilon-greedy class for distributed algorithms.

    Sets the epsilon schedules of individual workers to a constant:
    0.4 ^ (1 + [worker-index] / float([num-workers] - 1) * 7)
    See Ape-X paper.
    """

    def __init__(self, action_space: Space, *, framework: str,
                 num_workers: Optional[int], worker_index: Optional[int],
                 alpha: float = 7,
                 eps: float = 0.4,
                 **kwargs):
        """Create a PerWorkerEpsilonGreedy exploration class.

        Args:
            action_space (Space): The gym action space used by the environment.
            num_workers (Optional[int]): The overall number of workers used.
            worker_index (Optional[int]): The index of the Worker using this
                Exploration.
            framework (Optional[str]): One of None, "tf", "torch".
            alpha (int): multiplicative factor of the exponent used
            to compute the epsilon. The smaller the amount of rollout-workers,
            the smaller the exponent should be. This helps to avoid too low
            exploration rates. The default value here is took from
            page 6 of https://arxiv.org/pdf/1803.00933.pdf
            eps (float): base value use to compute the epsilon to be used
            by a worker. The default value here is took from
            page 6 of https://arxiv.org/pdf/1803.00933.pdf
        """
        # Use a fixed, different epsilon per worker. See: Ape-X paper.
        assert worker_index <= num_workers, (worker_index, num_workers)
        self.num_workers = num_workers
        self.worker_index = worker_index
        self.alpha = alpha
        self.eps = eps

        super().__init__(
            action_space,
            framework=framework,
            num_workers=num_workers,
            worker_index=worker_index,
            **kwargs)

    @override(EpsilonGreedy)
    def reset_schedule(self,
                       initial_epsilon=None,
                       final_epsilon=None,
                       epsilon_timesteps=None,
                       epsilon_schedule=None
                       ):
        epsilon_schedule = None
        if self.num_workers > 0:
            if self.worker_index > 0:
                # The values used here, by default (see constructor defaults),
                # are the same epsilon and alpha of the e-greedy policy use in
                # page 6 of https://arxiv.org/pdf/1803.00933.pdf
                i = self.worker_index - 1
                num_workers_minus_1 = float(self.num_workers - 1) \
                    if self.num_workers > 1 else 1.0
                epsilon_schedule = ConstantSchedule(
                    self.eps**(1 + (i / num_workers_minus_1) * self.alpha),
                    framework=self.framework)
            # Local worker should have zero exploration so that eval
            # rollouts run properly.
            else:
                epsilon_schedule = ConstantSchedule(0.0, framework=self.framework)

        super().reset_schedule(initial_epsilon=initial_epsilon,
                       final_epsilon=final_epsilon,
                       epsilon_timesteps=epsilon_timesteps,
                       epsilon_schedule=epsilon_schedule)


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

# In[17]:

from tkinter import*
from tkinter import filedialog
from tkinter import ttk
import pandas as pd
from tkinter.messagebox import*
from tkinter.filedialog import askopenfilename
import csv
import math
from decimal import*

root = Tk()
root.iconbitmap('STRATV.ico')
root.title('STRAT-V')

style = ttk.Style()
style.theme_use('clam')

# list the options of the style
# (Argument should be an element of TScrollbar, eg. "thumb", "trough", ...)
print(style.element_options("Horizontal.TScrollbar.thumb"))

# configure the style
style.configure("Horizontal.TScrollbar", gripcount=0,
                background="#2196f3", darkcolor="#2196f3", lightcolor="grey",
                troughcolor="#2196f3", bordercolor="grey", arrowcolor="white")

#Create a main frame
main_frame = Frame(root,bg='#d6ebfb')
main_frame.pack(fill = BOTH, expand =1)

#Create a canvas

my_canvas = Canvas(main_frame,bg='#d6ebfb')
my_canvas.pack(side = LEFT, fill=BOTH, expand = 1)

#Add a scrollbar to the canvas
my_scrollbar = ttk.Scrollbar(main_frame, orient = VERTICAL, command = my_canvas.yview)
my_scrollbar.pack(side=RIGHT, fill = Y)
my_scrollbarx = ttk.Scrollbar(root, orient=HORIZONTAL, command=my_canvas.xview)
my_scrollbarx.pack(side=BOTTOM, fill = X)
#Configure the canvas
my_canvas.configure(xscrollcommand=my_scrollbarx.set, yscrollcommand = my_scrollbar.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion = my_canvas.bbox('all')))

#Create ANOTHER frame inside the canvas
second_frame = Frame(my_canvas, bg = '#c8f1f7')

#Add that frame to a windows in the canvas
my_canvas.create_window((0,0), window = second_frame, anchor = 'nw')

#frame_1 = LabelFrame(second_frame,text ='Input Data', bd = 2,bg = '#ebffd4', relief = GROOVE).place(height =750, width =6000)
#frame_2 = LabelFrame(second_frame,text = 'Calculate',bd = 2,bg ='#c8f1f7', relief = RAISED).place(height =750, width =500)
#frame_3 = Frame(root, bd=5,bg='grey').grid(row =2, column =1)

#my_canvas.configure(xscrollcommand=frame_1scrollbarx.set)
#canvas.create_window((0,0), window=frame_1, anchor='nw')

def donothing():
      x = 0

#===========================================================================================================================
def Load_File():

    import_file=Tk()
    import_file.iconbitmap('STRATV.ico')
    import_file.title('STRAT-V')
    import_file.geometry('500x500')
    import_file.pack_propagate(False)
    #import_file.resizable(0,0)

    #frame for Treeview
    frame3=LabelFrame(import_file,text='Data File')
    #frame3.place(height=250, width=500)
    frame3.place(relheight=0.5, relwidth=1)

    #Frame for open filedialog
    file_frame=LabelFrame(import_file, text='Open File')
    file_frame.place(height=100, width=500, rely=0.65, relx=0)

    #Buttons
    button1=Button(file_frame, text = 'Browse A File',command=lambda:file_dialog())
    button1.place(rely=0.65, relx=0.8)

    button2= Button(file_frame, text = 'Load Permeability-Porosity Data', command=lambda: Load_Permeability_Porosity_Data())
    button2.place(rely=0.65,relx=0.4)
    button3=Button(file_frame, text = 'Load Relative Permeability Data', command=lambda: Load_Relative_Permeability_Data())
    button3.place(rely=0.65, relx=0)

    label_file = ttk.Label(file_frame, text = 'No File Selected')
    label_file.place(rely=0,relx=0)

    #Treeview Widget
    tv1=ttk.Treeview(frame3)
    tv1.place(relheight=1, relwidth=1)

    treescrolly = Scrollbar(frame3, orient='vertical',command=tv1.yview)
    treescrollx = Scrollbar(frame3, orient='horizontal',command=tv1.xview)
    tv1.configure(xscrollcommand=treescrollx.set)
    tv1.configure(yscrollcommand=treescrolly.set)
    treescrollx.pack(side='bottom', fill='x')
    treescrolly.pack(side='right', fill='y')

    def file_dialog():
        filename= filedialog.askopenfilename(initialdir="/", title = "Select A File", filetype=(("csvfiles","*.csv"),("All Files", "*.*")))
        label_file["text"]=filename

    def Load_Permeability_Porosity_Data():
        file_path=label_file['text']
        try:
            excel_filename=r"{}".format(file_path)
            bed_data=pd.read_csv(excel_filename)
        except ValueError:
            messagebox.showerror("Information","The file you have chosen is invalid")
            return None
        except FileNotFoundError:
            messagebox.showerror("Information", f"No such file as {file_path}")
            return None

        clear_data()
        tv1["column"]=list(bed_data.columns)
        tv1['show']='headings'
        for column in tv1['columns']:
            tv1.heading(column,text=column)
        bed_data_rows = bed_data.to_numpy().tolist()
        for row in bed_data_rows:
            tv1.insert("","end", values=row)

    def Load_Relative_Permeability_Data():
        file_path=label_file['text']
        try:
            excel_filename=r"{}".format(file_path)
            RPERM_data=pd.read_csv(excel_filename)
        except ValueError:
            messagebox.showerror("Information","The file you have chosen is invalid")
            return None
        except FileNotFoundError:
            messagebox.showerror("Information", f"No such file as {file_path}")
            return None

        clear_data()
        tv1["column"]=list(RPERM_data.columns)
        tv1['show']='headings'
        for column in tv1['columns']:
            tv1.heading(column,text=column)
        RPERM_data_rows = RPERM_data.to_numpy().tolist()
        for row in RPERM_data_rows:
            tv1.insert("","end", values=row)
        return None
    def clear_data():
        tv1.delete(*tv1.get_children())

    import_file.mainloop()
#===========================================================================================================================

def openfile():

    filename = askopenfilename(parent=root)
    f = open(filename)
    f.read()

#===========================================================================================================================

import sviewgui.sview as sv
import pandas as pd
def results_and_graph_gui():
    sv.buildGUI(All_tables)

#============================================================================================================================

def front_location_plots_gui():
    get_ipython().run_line_magic('matplotlib', '')
    import matplotlib.pyplot as plt
    for i in Layer_table['LAYERS']:
        plt.figure(figsize = (4,3), dpi = 100)
        Flood_front_location_Time = plt.plot(Time_days_table, Front_Location_list_DataTable[i-1], label = 'Layer'+str(i))
        #plt.setp(Flood_front_location_Time, animated=False, color = 'b', label='Coverage Vs WOR',linestyle = '-', linewidth = 1, marker = 'o', markersize = 2)
        plt.title('Flood front location versus Time', fontdict ={'fontname': 'Arial', 'fontsize': 20})
        plt.xlabel(' Time (days)')
        plt.ylabel('Flood front location')
        plt.legend()
        plt.show()
        plt.savefig('Flood_front_location.pdf', dpi = 300)
        plt.savefig('Flood_front_location.png', dpi = 300)

    plt.ion()

#=========================================================================================================================

menubar = Menu(root)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="New", command=donothing)
filemenu.add_command(label="Open", command=openfile)
filemenu.add_command(label="Load", command=Load_File)
filemenu.add_command(label="Save", command=donothing)
filemenu.add_command(label="Save as...", command=donothing)
filemenu.add_command(label="Close", command=donothing)

filemenu.add_separator()

filemenu.add_command(label="Exit", command=root.quit)
menubar.add_cascade(label="File", menu=filemenu)
editmenu = Menu(menubar, tearoff=0)
editmenu.add_command(label="Undo", command=donothing)

editmenu.add_separator()

editmenu.add_command(label="Cut", command=donothing)
editmenu.add_command(label="Copy", command=donothing)
editmenu.add_command(label="Paste", command=donothing)
editmenu.add_command(label="Delete", command=donothing)
editmenu.add_command(label="Select All", command=donothing)
menubar.add_cascade(label="Edit", menu=editmenu)

helpmenu = Menu(menubar, tearoff=0)
helpmenu.add_command(label="Help Index", command=donothing)
helpmenu.add_command(label="About...", command=donothing)
menubar.add_cascade(label="Help", menu=helpmenu)

# create the Output menu
#output = Menu(menu)
outputmenu = Menu(menubar, tearoff=0)
outputmenu.add_command(label="Tabular results and graphs",command = results_and_graph_gui)
outputmenu.add_command(label="Flood front location plot", command = front_location_plots_gui)
#added "file" to our menu
menubar.add_cascade(label="Output", menu=outputmenu)

#Create a load menu
loadmenu = Menu(menubar, tearoff=0)
loadmenu.add_command(label="Load Data",command =  Load_File)

#added "file" to our menu
menubar.add_cascade(label="Load", menu=loadmenu)

root.config(menu=menubar)

#===============================================================================================================================
 #Reservoir and Process Data initialization and definiton.

 # Creating Heading
#Input_header = Label(second_frame, text = ('Enter Input Variables'),fg = '#b22222', relief = RAISED).grid(row =0, column = 0, columnspan = 3, sticky = W+E+N+S)

Length_of_bed_ft = 2896

width_of_bed_ft = 2000

average_porosity = 0.25

VISO = 3.6

VISW = 0.95

OFVF = 1.11

WFVF = 1.01

SWI = 0.2

SGI = 0.16

SOI = 0.65

SOR = 0.35

#Constant Injection Rate in STB/D
Constant_injection_rate = 1800

#Injection Pressure Differential in PSI
Inj_Pressure_differential = 700

Residual_gas_saturation_unswept_area = 0.06

Residual_gas_saturation_swept_area = 0.02

Residual_gas_saturation = Residual_gas_saturation_unswept_area+Residual_gas_saturation_swept_area

#==========================================================================================================================

def enter_inputs():
    global Length_of_bed_ft
    global width_of_bed_ft
    global average_porosity
    global VISO
    global VISW
    global OFVF
    global WFVF
    global SWI
    global SGI
    global SOI
    global SOR
    global Constant_injection_rate
    global Inj_Pressure_differential
    global Residual_gas_saturation_unswept_area
    global Residual_gas_saturation_swept_area
    global Residual_gas_saturation

    fields = ('Length_of_bed_ft', 'width_of_bed_ft', 'average_porosity','VISO', 'VISW','OFVF','WFVF','SWI', 'SGI','SOI','SOR','Constant_injection_rate',
    'Inj_Pressure_differential','Residual_gas_saturation_unswept_area','Residual_gas_saturation_swept_area','Residual_gas_saturation')

    def residual_gas_saturation(entries):

        global RGSU
        global RGSS
        global RGS
        # period rate:
        RGSU = float(entries['Residual_gas_saturation_unswept_area'].get())

        # principal loan:
        RGSS =  float(entries['Residual_gas_saturation_swept_area'].get())
        Residual_gas_saturation = float(entries['Residual_gas_saturation'].get())

        RGS = RGSU+RGSS
        RGS = ("%8.2f" % RGS).strip()
        entries['Residual_gas_saturation'].delete(0, END)
        entries['Residual_gas_saturation'].insert(0, RGS)

    def makeform(inputs, fields):
        global entries
        entries = {}
        for field in fields:
           # print(field)
            row = Frame(inputs)
            lab = Label(row, width=22, text=field+": ", anchor='w')
            ent = Entry(row)
            ent.insert(0, "0")
            row.pack(side=TOP,
                     fill=X,
                     padx=5,
                     pady=5)
            lab.pack(side=LEFT)
            ent.pack(side=RIGHT,
                     expand=YES,padx = 100,
                     fill=X)
            entries[field] = ent
        return entries

    if __name__ == '__main__':
        inputs = Tk()
        inputs.iconbitmap('STRATV.ico')
        inputs.title('STRAT-V')
        ents = makeform(inputs, fields)
        b1 = Button(inputs, text='Residual gas saturation',
               command=(lambda e=ents:residual_gas_saturation(e)))
        b1.pack(side=LEFT, padx=5, pady=5)
        inputs.mainloop()
Enter_input_button = Button(second_frame, text = 'Enter input data',justify = LEFT,relief= RAISED,cursor='hand2',command = enter_inputs).grid(row=2,column =0,padx=5,pady=10)

#===============================================================================================================================

Label(second_frame, text='Calculate',fg = 'white', bg = '#2196f3',justify = CENTER,relief= FLAT).grid(row=0, column=4, columnspan = 8,padx = 40,pady=10, sticky = W+E+N+S)

#Importing the Permeability Porosity distribution data
bed_data = pd.read_csv('Permeability_Porosity_distribution_data.csv')

#===========================================================================================================================

# ARRANGING THE DATA IN ORDER OF DECREASING PERMEABILITY.
bed_data_sort = bed_data.sort_values(by='PERMEABILITY', ascending=False)

#==========================================================================================================================

#Importing the Relative permeability Data
import pandas as pd
RPERM_data = pd.read_csv('Oil_Water_Relative_Permeability_data.csv')

#==========================================================================================================================

# Extracting input variables from data table.
import numpy as np
PORO = np.array(bed_data_sort['POROSITY'])
permeability_array = np.array(bed_data_sort['PERMEABILITY'])
h = np.array(bed_data_sort['THICKNESS'])
SW = np.array(RPERM_data['SW'])
KRW = np.array(RPERM_data['KRW'])
KRO = np.array(RPERM_data['KRO'])

#==========================================================================================================================

#This code calculates the permeability ratio, ki/kn
List_of_permeability_ratio = []
for permeability_index in range(len(permeability_array)):
    List_of_permeability_ratio_subset = [][:-permeability_index]
    for index,permeability in enumerate(permeability_array):
        if permeability_index <= index:
            permaebility_ratio = permeability/permeability_array[permeability_index]
            List_of_permeability_ratio_subset.append(permaebility_ratio)
    List_of_permeability_ratio.append(List_of_permeability_ratio_subset)

List_of_permeability_ratio_DataTable = pd.DataFrame(List_of_permeability_ratio).transpose()

#==========================================================================================================================

# Calculating the average porosity

def average_porosity():
    Average_porosity = '%.3f' % np.mean(bed_data_sort.POROSITY)
    Label(second_frame, text= str(Average_porosity),justify = LEFT, relief = SUNKEN).grid(row = 3, column = 6,padx = 40,pady=5, sticky =W)
Button(second_frame,text='Average Porosity',bg = '#337ab7',fg = 'white',cursor='hand2', command=average_porosity).grid(row=2,column=6,padx = 40,pady=10, sticky =W)

def relative_perm_1_SOR(entries):
    SOR = float(entries['SOR'].get())
    KRW_1_SOR = '%.3f' % RPERM_data.loc[RPERM_data.SW == 1-SOR,'KRW'].values[0]
    Label(second_frame, text=  str(KRW_1_SOR),justify = LEFT, relief = SUNKEN).grid(row = 3, column = 7,padx = 40,pady=5, sticky =W)
Button(second_frame,text='Relative Permeability at 1-SOR',bg = '#337ab7',fg = 'white',cursor='hand2',command=(lambda: relative_perm_1_SOR(entries))).grid(row=2,column=7,padx = 40,pady=10, sticky =W)

def relative_perm_SWI(entries):
    SWI = float(entries['SWI'].get())
    KRO_SWI = '%.3f' % RPERM_data.loc[RPERM_data.SW == SWI,'KRO'].values[0]
    Label(second_frame, text= str(KRO_SWI),justify = LEFT, relief = SUNKEN).grid(row = 5, column = 6,padx = 40,pady=5, sticky =W)
Button(second_frame,text='Relative Permeability at Initial Water Saturation',bg = '#337ab7',fg = 'white',cursor='hand2',command=(lambda: relative_perm_SWI(entries))).grid(row=4,column=6,padx = 40,pady=10, sticky =W)

def mobility_ratio(entries):
    SWI = float(entries['SWI'].get())
    VISW = float(entries['VISW'].get())
    VISO = float(entries['VISO'].get())
    SOR = float(entries['SOR'].get())
    KRW_1_SOR = RPERM_data.loc[RPERM_data.SW == 1-SOR,'KRW'].values[0]
    KRO_SWI = RPERM_data.loc[RPERM_data.SW == SWI,'KRO'].values[0]
    Mobility_Ratio =  KRW_1_SOR*VISO/(KRO_SWI*VISW)
    Label(second_frame, text= str(Mobility_Ratio),justify = LEFT, relief = SUNKEN).grid(row = 7, column = 7,padx = 40,pady=5, sticky =W)
Button(second_frame,text='Mobility Ratio',bg = '#337ab7',fg = 'white',cursor='hand2',command=(lambda: mobility_ratio(entries))).grid(row=6,column=7,padx = 40,pady=10, sticky =W)

def areal_sweep_efficiency_at_breakthrough(entries):
    SWI = float(entries['SWI'].get())
    VISW = float(entries['VISW'].get())
    VISO = float(entries['VISO'].get())
    SOR = float(entries['SOR'].get())
    KRW_1_SOR = RPERM_data.loc[RPERM_data.SW == 1-SOR,'KRW'].values[0]
    KRO_SWI = RPERM_data.loc[RPERM_data.SW == SWI,'KRO'].values[0]
    Mobility_Ratio = KRW_1_SOR*VISO/(KRO_SWI*VISW)
    Areal_sweep_efficiency_at_breakthrough =  0.54602036+(0.03170817/Mobility_Ratio)+(0.30222997/math.exp(Mobility_Ratio)-0.0050969*Mobility_Ratio)
    Label(second_frame, text= str(Areal_sweep_efficiency_at_breakthrough),justify = LEFT,relief = SUNKEN).grid(row = 9, column = 6,padx = 40,pady=5, sticky =W)
Button(second_frame,text='Areal sweep efficiency at breakthrough',bg = '#337ab7',fg = 'white',cursor='hand2',command=(lambda: areal_sweep_efficiency_at_breakthrough(entries))).grid(row=8,column=6,padx = 40,pady=10, sticky =W)

def area_acres(entries):
    global Length_of_bed_ft
    global width_of_bed_ft
    Length_of_bed_ft = float(entries['Length_of_bed_ft'].get())
    width_of_bed_ft = float(entries['width_of_bed_ft'].get())
    Area_acres =  Length_of_bed_ft*width_of_bed_ft/43560
    Label(second_frame, text= str(Area_acres)+ ' acres',justify = LEFT,relief = SUNKEN).grid(row = 9, column = 7,padx = 40,pady=5, sticky =W)
Button(second_frame,text='Area of the reservoir bed',bg = '#337ab7',fg = 'white',cursor='hand2',command=(lambda: area_acres(entries))).grid(row=8,column=7,padx = 40,pady=10, sticky =W)

def gross_rock_volume(entries):
    global Length_of_bed_ft
    global width_of_bed_ft
    Length_of_bed_ft = float(entries['Length_of_bed_ft'].get())
    width_of_bed_ft = float(entries['width_of_bed_ft'].get())
    Area_acres = Length_of_bed_ft*width_of_bed_ft/43560
    Gross_rock_volume_acre_ft =  Area_acres*bed_data_sort.THICKNESS.sum()
    Label(second_frame, text= str(Gross_rock_volume_acre_ft)+ ' acres-ft',justify = LEFT,relief = SUNKEN).grid(row = 5, column = 7,padx = 40,pady=5, sticky =W)
Button(second_frame,text='Gross rock volume',bg = '#337ab7',fg = 'white',cursor='hand2',command=(lambda: gross_rock_volume(entries))).grid(row=4,column=7,padx = 40,pady=10, sticky =W)

def displacement_efficiency(entries):
    global SGI
    global SWI
    global SOR
    SWI = float(entries['SWI'].get())
    SOR = float(entries['SOR'].get())
    SGI = float(entries['SGI'].get())
    Displacement_efficiency =  (1-SWI-SGI-SOR)/(1-SWI-SGI)
    Label(second_frame, text= str(Displacement_efficiency),justify = LEFT,relief = SUNKEN).grid(row = 7, column = 6,padx = 40,pady=5, sticky =W)
Button(second_frame,text='Displacement efficiency',bg = '#337ab7',fg = 'white',cursor='hand2',command=(lambda: displacement_efficiency(entries))).grid(row=6,column=6,padx = 40,pady=10, sticky =W)

def areal_sweep_efficiency(entries):
    global SGI
    global SWI
    global SOR
    global SGI
    global Constant_injection_rate
    global Inj_Pressure_differential
    SWI = float(entries['SWI'].get())
    SOR = float(entries['SOR'].get())
    SGI = float(entries['SGI'].get())
    VISW = float(entries['VISW'].get())
    VISO = float(entries['VISO'].get())
    Constant_injection_rate = float(entries['Constant_injection_rate'].get())
    Inj_Pressure_differential = float(entries['Inj_Pressure_differential'].get())
    KRW_1_SOR = RPERM_data.loc[RPERM_data.SW == 1-SOR,'KRW'].values[0]
    KRO_SWI = RPERM_data.loc[RPERM_data.SW == SWI,'KRO'].values[0]
    Mobility_Ratio = KRW_1_SOR*VISO/(KRO_SWI*VISW)
    Areal_sweep_efficiency_at_breakthrough = 0.54602036+(0.03170817/Mobility_Ratio)+(0.30222997/math.exp(Mobility_Ratio)-0.0050969*Mobility_Ratio)
    Displacement_efficiency = (1-SWI-SGI-SOR)/(1-SWI-SGI)
    Areal_sweep_efficiency =  Areal_sweep_efficiency_at_breakthrough+0.2749*np.log((1/Displacement_efficiency))
    Label(second_frame, text= str(Areal_sweep_efficiency),justify = LEFT,relief = SUNKEN).grid(row = 13, column = 6,padx = 40,pady=10, sticky =W)
Button(second_frame,text='Areal sweep efficiency',bg = '#337ab7',fg = 'white',cursor='hand2',command=(lambda: areal_sweep_efficiency(entries))).grid(row=12,column=6,padx = 40,pady=10, sticky =W)

#============================================================================================================================================================

# EXTRACTING THE SORTED LAYER COLUMN
Layer_column = bed_data_sort['LAYER'].to_numpy()
Layer_table =  pd.DataFrame(Layer_column, columns = ['LAYERS'])

#==================================================================================================================================================================

#Calculating the oil mobility ratio

KRO_SWI = RPERM_data.loc[RPERM_data.SW == SWI,'KRO'].values[0]
Oil_Mobility_array =  permeability_array*KRO_SWI/VISO
Oil_Mobility_table = pd.DataFrame(Oil_Mobility_array, columns = ['Oil Mobility'])

#Label(second_frame, text=str(Oil_Mobility),justify = LEFT, relief = SUNKEN).grid(row = 11, column = 7,padx = 40,pady=5, sticky =W)
#Button(second_frame,text='Oil Mobility',bg = '#337ab7',fg = 'white',command=(lambda: oil_mobilty(entries))).grid(row=10,column=7,padx = 40,pady=10, sticky =W)

KRW_1_SOR = RPERM_data.loc[RPERM_data.SW == 1-SOR,'KRW'].values[0]
Water_Mobility_array =  permeability_array*KRW_1_SOR/VISW
Water_Mobility_table = pd.DataFrame(Water_Mobility_array, columns = ['Water Mobility'])

#Label(second_frame, text=str(Water_Mobility),justify = LEFT, relief = SUNKEN).grid(row = 11, column = 6,padx = 40,pady=5, sticky =W)
#Button(second_frame,text='Water Mobility',bg = '#337ab7',fg = 'white',command=(lambda: water_mobilty(entries))).grid(row=10,column=6,padx = 40,pady=10, sticky =W)

#==========================================================================================================================

#This code calculates the list of waterflood front location as each layer breaksthrough
Front_Location_list = []
KRW_1_SOR = RPERM_data.loc[RPERM_data.SW == 1-SOR,'KRW'].values[0]
KRO_SWI = RPERM_data.loc[RPERM_data.SW == SWI,'KRO'].values[0]
Mobility_Ratio = KRW_1_SOR*VISO/(KRO_SWI*VISW)
for permeability_index1 in range(len(permeability_array)):
    Front_Location = (Mobility_Ratio - np.sqrt(Mobility_Ratio**2+List_of_permeability_ratio_DataTable[permeability_index1]*(1-Mobility_Ratio**2)))/(Mobility_Ratio-1)
    Front_Location_list.append(Front_Location)

#This code generates table of flood front location as the layers breakthrough
Front_Location_list_DataTable = pd.DataFrame(Front_Location_list).transpose().rename(columns={0:'FLOOD FRONT LOCATION OF EACH BED'})

#==========================================================================================================================

# CALCULATING THE OIL FLOW RATE IN EACH BED AS EACH BED BREAKS THROUGH
Water_Mobility = permeability_array*KRW_1_SOR/VISW
Water_Flowrate_per_bed = (width_of_bed_ft*bed_data_sort['THICKNESS']*Inj_Pressure_differential/Length_of_bed_ft)*Water_Mobility

Water_Flowrate_per_bed_table = pd.DataFrame(Water_Flowrate_per_bed).rename(columns={'THICKNESS':'INJECTED WATER FLOWRATE(STB/D)'})
Water_Flowrate_per_bed_table

#===========================================================================================================================

# CALCULATING THE OIL FLOW RATE IN EACH BED AS EACH BED BREAKS THROUGH
Oil_Flowrate_per_bed_list = []
for bed in Front_Location_list_DataTable.columns:
    Oil_Flowrate_per_bed = (width_of_bed_ft*bed_data_sort['THICKNESS']*Inj_Pressure_differential/Length_of_bed_ft)*Water_Mobility/((1-Mobility_Ratio)*Front_Location_list_DataTable[bed]+Mobility_Ratio)
    Oil_Flowrate_per_bed_list.append(Oil_Flowrate_per_bed)

Oil_Flowrate_per_bed_table = pd.DataFrame(Oil_Flowrate_per_bed_list).transpose().rename(columns={0:'OIL FLOWRATE  IN EACH BED (STB/D)'})

#==========================================================================================================================

# CALCULATING THE VERTICAL COVERAGE
coverage_list = []
Total_Number_of_layers = len(permeability_array)-1
for number_layer_breakthrough in range(len(permeability_array)):
    coverage_individual = (number_layer_breakthrough+((Total_Number_of_layers-number_layer_breakthrough)*Mobility_Ratio/(Mobility_Ratio-1))-(1/(Mobility_Ratio-1))*np.sqrt(Mobility_Ratio**2+List_of_permeability_ratio_DataTable[number_layer_breakthrough][1:]*(1-Mobility_Ratio**2)).sum())/Total_Number_of_layers
    coverage_list.append(coverage_individual)

#Table of vertical coverage of the reservoir when a given layer just broke through.
coverage_table = pd.DataFrame(coverage_list, columns=['VERTICAL COVERAGE (FRACTION)'])

#============================================================================================================================

WOR_denominator_ratio_list = []
for denominator_index in range(len(permeability_array)):
    WOR_denominator_ratio = permeability_array/np.sqrt(Mobility_Ratio**2+List_of_permeability_ratio_DataTable[denominator_index]*(1-Mobility_Ratio**2))
    WOR_denominator_ratio_list.append(WOR_denominator_ratio)
WOR_denominator_ratio_table = pd.DataFrame(WOR_denominator_ratio_list).transpose()

# CALCULATING THE WATER OIL RATIO, WORn and generate table
WOR_list = []
sum_of_permeability = sum(bed_data_sort.PERMEABILITY)
for number_layer_breakthrough in range(len(permeability_array)):
    WOR = sum_of_permeability/(WOR_denominator_ratio_table[number_layer_breakthrough].sum())
    WOR_list.append(WOR)
WOR_table = pd.DataFrame(WOR_list,columns=['WATER-OIL RATIO'])

#==========================================================================================================================

#CALCULATING THE CUMULATIVE OIL RECOVERY AS EACH BED BREAKSTHROUGH.

Average_porosity = np.mean(bed_data_sort.POROSITY)

Area_acres = Length_of_bed_ft*width_of_bed_ft/43560
Gross_rock_volume_acre_ft = Area_acres*bed_data_sort.THICKNESS.sum()

KRW_1_SOR = RPERM_data.loc[RPERM_data.SW == 1-SOR,'KRW'].values[0]
KRO_SWI = RPERM_data.loc[RPERM_data.SW == SWI,'KRO'].values[0]
Mobility_Ratio = KRW_1_SOR*VISO/(KRO_SWI*VISW)

Areal_sweep_efficiency_at_breakthrough = 0.54602036+(0.03170817/Mobility_Ratio)+(0.30222997/math.exp(Mobility_Ratio)-0.0050969*Mobility_Ratio)
Cumulative_oil_recovery = (7758*Areal_sweep_efficiency_at_breakthrough*Gross_rock_volume_acre_ft*Average_porosity*(SOI-SOR)*coverage_table/OFVF).rename(columns={'VERTICAL COVERAGE (FRACTION)':'CUMULATIVE OIL RECOVERY (BARRELS)'})

#============================================================================================================================

#CALCULATING THE VOLUME OF WATER REQUIRED TO FILL-UP THE GAS SPACE.
Water_volume_to_fillup_gas_space = 7758*Area_acres*bed_data_sort.THICKNESS*bed_data_sort.POROSITY*(SGI-Residual_gas_saturation)
Water_volume_to_fillup_gas_space_table=pd.DataFrame(Water_volume_to_fillup_gas_space, columns = ['WATER VOLUME FOR GAS SPACE FILL-UP'])

#============================================================================================================================

#CALCULATING THE PRODUCING WATER-OIL RATIO
Producing_water_oil_ratio = (WOR_table*OFVF).rename(columns={'WATER-OIL RATIO':'PRODUCING WATER-OIL RATIO'})
Producing_water_oil_ratio

#===========================================================================================================================

# Note that the integration for the calculation of the cumulative oil produced starts from 0
# Hence, a new row will have to be inserted at the first row with element 0
# this is done for both the producing water-oil ratio and the cumulative oil produced.

# for the cumulative oil recovery
Cumulative_oil_recovery.loc[-1] = [0]  # adding a row
#Cumulative_oil_recovery.index = Cumulative_oil_recovery.index + 1  # shifting index
Cumulative_oil_recovery_Starting_from_0 = Cumulative_oil_recovery.sort_index()  # sorting by index

# for the producing water-oil ratio
Producing_water_oil_ratio.loc[-1] = [0]  # adding a row
#Producing_water_oil_ratio.index = Producing_water_oil_ratio.index + 1  # shifting index
Producing_water_oil_ratio_Starting_from_0 = Producing_water_oil_ratio.sort_index()  # sorting by index

# CALCULATING THE CUMULATIVE WATER PRODUCTION

# To determine the cumulative water production, the produced water oil ratio is ingreated against the cumulative oil recovery.
# The integration uses a cumulative trapezoidal row by row integration.

# import numpy and scipy.integrate.cumtrapz
import numpy as np
from scipy import integrate

# Preparing the Integration variables y, x.
   # the to.numpy() method converts from dataframe to numpy array which appears in the form of list of lists in the array.
   #The concatenate function helps to bring the list of lists together.
x = np.concatenate(Cumulative_oil_recovery_Starting_from_0.to_numpy(),axis=0)
y = np.concatenate(Producing_water_oil_ratio_Starting_from_0.to_numpy(),axis=0)

# using scipy.integrate.cumtrapz() method
Cumulative_water_produced = pd.DataFrame(integrate.cumtrapz(y, x), columns = ['CUMULATIVE WATER PRODUCED'])

#==============================================================================================================================

# CALCULATING THE CUMULATIVE WATER INJECTED, Wi
Cumulative_water_injected = (Cumulative_water_produced['CUMULATIVE WATER PRODUCED'] + OFVF*Cumulative_oil_recovery['CUMULATIVE OIL RECOVERY (BARRELS)'] + Water_volume_to_fillup_gas_space_table['WATER VOLUME FOR GAS SPACE FILL-UP']).drop([-1])
Cumulative_water_injected_table = pd.DataFrame(Cumulative_water_injected,columns = ['CUMULATIVE WATER INJECTED (BARRELS)'])

#===================================================================================================================================

# CALCULATING THE TIME REQUIRED FOR INJECTION TO REACH A GIVEN RECOVERY.
Time_days = Cumulative_water_injected_table['CUMULATIVE WATER INJECTED (BARRELS)']/Constant_injection_rate
Time_days_table = pd.DataFrame(Time_days).rename(columns ={'CUMULATIVE WATER INJECTED (BARRELS)': 'Time (Days)'}, inplace = False)
#print(Time_days_table)
Time_years = Time_days_table/365
Time_years_table = Time_years.rename(columns ={'Time (Days)': 'Time (Years)'}, inplace = False)

#=======================================================================================================================================

# TABLE OF ALL OBTAINED VALUES.
All_tables =pd.concat([Layer_table,Oil_Mobility_table,Water_Mobility_table,Water_Flowrate_per_bed_table, coverage_table, WOR_table, Cumulative_oil_recovery, Water_volume_to_fillup_gas_space_table, Producing_water_oil_ratio, Cumulative_water_produced, Cumulative_water_injected_table, Time_days_table, Time_years_table,Front_Location_list_DataTable,Oil_Flowrate_per_bed_table], axis = 1).drop([-1])

#================================================================================================================================

root.geometry("800x500")

root.mainloop()