import ipywidgets as widgets
from IPython.display import display
from ipywidgets import *
from collections import Counter
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.feature_extraction import DictVectorizer
from pandas import DataFrame

data = pd.read_csv('cs-training.csv', sep=';').drop('Unnamed: 0', axis=1)
collections = 2
# min = pd.Series.min()
Cols = []
for i in range(len(data.columns)):
    Cols.append(data.columns[i].replace('-', ''))
data.columns = Cols
plt.figure(1)
df_data = {"age": 15, "NumberOfTime3059DaysPastDueNotWorse": 20}
df_data.age.plot.box()
Counter(df_data.age)
ind = np.where(df_data.age < 21)
df_data.age[ind[0]] = 21.
ind = np.where(df_data.age > 94)
df_data.age[ind[0]] = 94.
Counter(df_data.NumberOfTime3059DaysPastDueNotWorse)
# Set outlier values to median , that is 0.
ind = np.where(df_data.NumberOfTime3059DaysPastDueNotWorse > 95)
df_data.NumberOfTime3059DaysPastDueNotWorse[ind[0]] = 0.

plt.figure(figsize=(20, 15))
ax = plt.subplot(211)
# ax.set_ylim(0,20)
plt.plot(df_data.DebtRatio, 'bo', df_data.DebtRatio, 'k')
print('Median: %.7f \nMean: %.7f' %
      (np.median(df_data.DebtRatio), np.mean(df_data.DebtRatio)))
# ruoelLt2=len(df_data[df_data.RevolvingUtilizationOfUnsecuredLines < 2])
# ruoelACt=len(df_data.RevolvingUtilizationOfUnsecuredLines)
# print('Values less than 2 : %d in %d. Ratio: %.5f%%' %(ruoelLt2,ruoelACt,100*ruoelLt2/ruoelACt))
ax = sns.countplot(mad_based_outlier(df_data.DebtRatio))
plot_freq(l=len(df_data.DebtRatio))

minUpperBound = min([val for (val, out) in zip(
    df_data.DebtRatio, mad_based_outlier(df_data.DebtRatio)) if out == True])
# Set outlier values to upperbound, that is minUpperBound.
ind = np.where(df_data.DebtRatio > minUpperBound)
df_data.DebtRatio[ind[0]] = minUpperBound

plt.figure(figsize=(20, 15))
ax = plt.subplot(211)
plt.plot(df_data.DebtRatio, 'o')

df_data.DebtRatio.describe()

plt.figure(figsize=(20, 15))
ax = plt.subplot(211)
# ax.set_ylim(0,20)
plt.plot(df_data.MonthlyIncome, 'bo', df_data.MonthlyIncome, 'k')
print('Median: %.7f \nMean: %.7f' %
      (np.median(df_data.MonthlyIncome), np.mean(df_data.MonthlyIncome)))
maxUpperBound = min([val for (val, out) in zip(
    df_data.MonthlyIncome, mad_based_outlier(df_data.MonthlyIncome)) if out == True])
ind = np.where(df_data.MonthlyIncome > maxUpperBound)
df_data.MonthlyIncome[ind[0]] = maxUpperBound
ind = np.where(df_data.MonthlyIncome < 1500)
df_data.MonthlyIncome[ind[0]] = 1500
df_data.MonthlyIncome.describe()
Counter(df_data.NumberRealEstateLoansOrLines)
# Set outlier values to 16.
ind = np.where(df_data.NumberRealEstateLoansOrLines > 16)
df_data.NumberRealEstateLoansOrLines[ind[0]] = 16
Counter(df_data.NumberOfTime6089DaysPastDueNotWorse)
# Set outlier values to 0.
ind = np.where(df_data.NumberOfTime6089DaysPastDueNotWorse > 11)
df_data.NumberOfTime6089DaysPastDueNotWorse[ind[0]] = 0
Counter(df_data.NumberOfDependents)
ind = np.where(df_data.NumberOfDependents > 10)
df_data.NumberOfDependents[ind[0]] = 10

plt.style.use('ggplot')

form_item_layout = widgets.Layout(
    display='flex',
    flex_flow='row',
    justify_content='space-between'
)

# displaying the text widget
text = widgets.Text(
    placeholder='Enes',
    disabled=False
)
# display(text)
# add button that updates the graph based on the checkboxes
button = widgets.Button(description="Check credibility")
# display(button)
resultLabel = widgets.Label(
    value="",
    visible=False,
    disabled=True
)
# display(resultLabel)
revolve = widgets.FloatSlider(
    value=df_data.RevolvingUtilizationOfUnsecuredLines.median(),
    min=df_data.RevolvingUtilizationOfUnsecuredLines.min(),
    max=df_data.RevolvingUtilizationOfUnsecuredLines.max(),
    step=0.01,
    disabled=False,
    continuous_update=True,
    orientation='horizontal',
    readout=True,
    readout_format='.4f',
    slider_color='black'
)
age = widgets.IntSlider(
    value=df_data.age.median(),
    min=df_data.age.min(),
    max=df_data.age.max(),
    step=1,
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    slider_color='black'
)
income = widgets.FloatSlider(
    value=df_data.MonthlyIncome.median(),
    min=df_data.MonthlyIncome.min(),
    max=df_data.MonthlyIncome.max(),
    step=0.5,
    disabled=False,
    continuous_update=True,
    orientation='horizontal',
    readout=True,
    readout_format='.1f',
    slider_color='black'
)
debtRatio = widgets.FloatSlider(
    value=df_data.DebtRatio.median(),
    min=df_data.DebtRatio.min(),
    max=df_data.DebtRatio.max(),
    step=0.01,
    disabled=False,
    continuous_update=True,
    orientation='horizontal',
    readout=True,
    readout_format='.4f',
    slider_color='black'
)
NumberOfTime3059DaysPastDueNotWorse = widgets.IntSlider(
    value=df_data.NumberOfTime3059DaysPastDueNotWorse.median(),
    min=df_data.NumberOfTime3059DaysPastDueNotWorse.min(),
    max=df_data.NumberOfTime3059DaysPastDueNotWorse.max(),
    step=1,
    disabled=False,
    continuous_update=True,
    orientation='horizontal',
    readout=True,
    slider_color='black'
)
NumberOfTimes90DaysLate = widgets.IntSlider(
    value=df_data.NumberOfTimes90DaysLate.median(),
    min=df_data.NumberOfTimes90DaysLate.min(),
    max=df_data.NumberOfTimes90DaysLate.max(),
    step=1,
    disabled=False,
    continuous_update=True,
    orientation='horizontal',
    readout=True,
    slider_color='black'
)
NumberRealEstateLoansOrLines = widgets.IntSlider(
    value=df_data.NumberRealEstateLoansOrLines.median(),
    min=df_data.NumberRealEstateLoansOrLines.min(),
    max=df_data.NumberRealEstateLoansOrLines.max(),
    step=1,
    disabled=False,
    continuous_update=True,
    orientation='horizontal',
    readout=True,
    slider_color='black'
)
NumberOfTime6089DaysPastDueNotWorse = widgets.IntSlider(
    value=df_data.NumberOfTime6089DaysPastDueNotWorse.median(),
    min=df_data.NumberOfTime6089DaysPastDueNotWorse.min(),
    max=df_data.NumberOfTime6089DaysPastDueNotWorse.max(),
    step=1,
    disabled=False,
    continuous_update=True,
    orientation='horizontal',
    readout=True,
    slider_color='black'
)
NumberOfOpenCreditLinesAndLoans = widgets.IntSlider(
    value=df_data.NumberOfOpenCreditLinesAndLoans.median(),
    min=df_data.NumberOfOpenCreditLinesAndLoans.min(),
    max=df_data.NumberOfOpenCreditLinesAndLoans.max(),
    step=1,
    disabled=False,
    continuous_update=True,
    orientation='horizontal',
    readout=True,
    slider_color='black'
)

NumberOfDependents = widgets.IntSlider(
    value=df_data.NumberOfDependents.median(),
    min=df_data.NumberOfDependents.min(),
    max=df_data.NumberOfDependents.max(),
    step=1,
    disabled=False,
    continuous_update=True,
    orientation='horizontal',
    readout=True,
    slider_color='black'
)
algos = widgets.Dropdown(
    options=['Decision Tree', 'SVM', 'Logistic Regression', 'GaussianNB', 'MLP'])
# display(revolve)

form_items = [
    Box([Label(value='Please, enter the name:'), text], layout=form_item_layout),
    Box([Label(value='Revolving Util. of Unsecured Lines:'),
         revolve], layout=form_item_layout),
    Box([Label(value='Age:'), age], layout=form_item_layout),
    Box([Label(value='Monthly Income:'), income], layout=form_item_layout),
    Box([Label(value='Dept Ratio:'), debtRatio], layout=form_item_layout),
    Box([Label(value='NumberOfOpenCreditLinesAndLoans:'),
         NumberOfOpenCreditLinesAndLoans], layout=form_item_layout),
    Box([Label(value='NumberOfTime3059DaysPastDueNotWorse:'),
         NumberOfTime3059DaysPastDueNotWorse], layout=form_item_layout),
    Box([Label(value='NumberOfTimes90DaysLate:'),
         NumberOfTimes90DaysLate], layout=form_item_layout),
    Box([Label(value='NumberRealEstateLoansOrLines:'),
         NumberRealEstateLoansOrLines], layout=form_item_layout),
    Box([Label(value='NumberOfTime6089DaysPastDueNotWorse:'),
         NumberOfTime6089DaysPastDueNotWorse], layout=form_item_layout),
    Box([Label(value='NumberOfDependents:'),
         NumberOfDependents], layout=form_item_layout),
    Box([Label(value='Algorithm:'), algos], layout=form_item_layout),
    button,
    Box([Label(value='Result:'), resultLabel], layout=form_item_layout),
]

form = Box(form_items, layout=Layout(
    display='flex',
    flex_flow='column',
    border='dashed 2px',
    align_items='stretch',
    width='70%'
))

display(form)

# function to deal with the checkbox update button

def on_button_clicked(b):
    name = text.value
    roul = revolve.value
    ageV = age.value
    monI = income.value
    dratio = debtRatio.value
    noOpCL = NumberOfOpenCreditLinesAndLoans.value
    noT3059 = NumberOfTime3059DaysPastDueNotWorse.value
    noT90 = NumberOfTimes90DaysLate.value
    nreL = NumberRealEstateLoansOrLines.value
    noT6089 = NumberOfTime6089DaysPastDueNotWorse.value
    noD = NumberOfDependents.value
    algo = algos.value

    testARR = [[dratio, monI, noD, noOpCL,
                noT3059, noT6089, noT90, nreL, roul, ageV]]
    yGuess = []

    if algo == 'Decision Tree':
        yGuess = clf2.predict(testARR)
    elif algo == 'SVM':
        yGuess = clf3.predict(testARR)
    elif algo == 'Logistic Regression':
        yGuess = clf.predict(testARR)
    elif algo == 'GaussianNB':
        yGuess = gnb.predict(testARR)
    else:
        yGuess = clf4.predict(testARR)

    print(name, roul, ageV, monI, dratio, noOpCL, noT3059,
          noT90, nreL, noT6089, noD, algo, yGuess[0])

    if (resultLabel.visible == False and yGuess[0] == 0):
        resultLabel.value = text.value + ' can be provided with the loan.'
    else:
        resultLabel.value = text.value + ' should not be provided with the loan.'

button.on_click(on_button_clicked)
plt.show()

ind = df_data.SeriousDlqin2yrs[df_data.SeriousDlqin2yrs == 1]
ind = ind[1:100]
ind2 = df_data.SeriousDlqin2yrs[df_data.SeriousDlqin2yrs == 0]
ind2 = ind2[1:100]

plt.figure(figsize=(15, 15))
ax = plt.subplot(211)
# ax.set_ylim(0,20)
plt.plot(df_data.MonthlyIncome[ind.index], df_data.age[ind.index],
         'ko', df_data.MonthlyIncome[ind2.index], df_data.age)

# 🔵 Standard Compliance Report
# 🔹 Product Type: Credit Scoring
# 🔹 Code Block Name: credit_score_3.py
# 🔹 Analysis Result:
#   Standard => Credit Information Business Act B.E.2545
#   ⦿ Section: 3
#    ⁃ Count of standard compliance in the code block:
#      ◦ age: 14
#      ◦ NumberOfTime3059DaysPastDueNotWorse: 10
#      ◦ DebtRatio: 15
#      ◦ MonthlyIncome: 16
#      ◦ NumberRealEstateLoansOrLines: 10
#      ◦ NumberOfTime6089DaysPastDueNotWorse: 10
#      ◦ NumberOfDependents: 10
#      ◦ RevolvingUtilizationOfUnsecuredLines: 3
#      ◦ income: 3
#      ◦ debtRatio: 3
#      ◦ NumberOfOpenCreditLinesAndLoans: 7
#      ◦ Lines: 1
#      ◦ Age: 1
#      ◦ Income: 1
#      ◦ ageV: 3
#      ◦ loan: 2
#      Total: 109
#    ⁃ Count of standard violation in the code block: 0
# 🔹 Absent section in the code block:
#  ◦ Credit Information Business Act B.E.2545 at section 10
# 🔹 Reference Number: dbb813beb820f92dc84d74f5bee1b96ec320367e641e38cd8fa8c2ddd16bf9a6
# 🔵 Standard Compliance Report
# 🔹 Product Type: Credit Scoring
# 🔹 Code Block Name: credit_score_3.py
# 🔹 Analysis Result:
#   1. Standard => Credit Information Business Act B.E.2545
#   ⦿ Section: 3
#    ⁃ Count of standard compliance in the code block:
#      ◦ age: 14
#      ◦ NumberOfTime3059DaysPastDueNotWorse: 10
#      ◦ DebtRatio: 15
#      ◦ MonthlyIncome: 16
#      ◦ NumberRealEstateLoansOrLines: 10
#      ◦ NumberOfTime6089DaysPastDueNotWorse: 10
#      ◦ NumberOfDependents: 10
#      ◦ RevolvingUtilizationOfUnsecuredLines: 3
#      ◦ income: 3
#      ◦ debtRatio: 3
#      ◦ NumberOfOpenCreditLinesAndLoans: 7
#      ◦ Lines: 1
#      ◦ Age: 1
#      ◦ Income: 1
#      ◦ ageV: 3
#      ◦ loan: 2
#      Total: 109
#    ⁃ Count of standard violation in the code block: 0
# 🔹 Absent section in the code block:
#  ◦ Credit Information Business Act B.E.2545 at section 10
# 🔹 Reference Number: be52a8d6e1daf9104a1715475cefb4bcdad5b5bf483e9a0019470e58477fd31c
# 🔵 Standard Compliance Report
# 🔹 Product Type: Credit Scoring
# 🔹 Code Block Name: credit_score_3.py
# 🔹 Analysis Result:
#   1. Standard => ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices
#   ⦿ Section: Preparation of Credit Information no.8.2
#    ⁃ Count of standard compliance in the code block:
#      ◦ collections: 1
#      Total: 1
#    ⁃ Count of standard violation in the code block: 0
#   ⦿ Section: Credit Scoring Development
#    ⁃ Count of standard compliance in the code block:
#      ◦ data: 4
#      ◦ df_data: 79
#      Total: 83
#    ⁃ Count of standard violation in the code block: 0
#   ⦿ Section: Preparation of Credit Information no.8.6
#    ⁃ Count of standard compliance in the code block:
#      ◦ training: 1
#      Total: 1
#    ⁃ Count of standard violation in the code block: 0
#   ⦿ Section: Preparation of Credit Information no.8.1
#    ⁃ Count of standard compliance in the code block:
#      ◦ training: 1
#      Total: 1
#    ⁃ Count of standard violation in the code block: 0
#   ⦿ Section: Testing of the Reliability of Separation and/or Accuracy of Prediction Power of Credit Scoring
#    ⁃ Count of standard compliance in the code block:
#      ◦ testARR: 6
#      Total: 6
#    ⁃ Count of standard violation in the code block: 0
# 🔹 Absent section in the code block:
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Implementation of Credit Scoring System I
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Implementation of Credit Scoring System II
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Verification of the Applicant’s Information
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Preparation of Credit Information no.8.3
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Overrides in Credit Approval
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Construction of Credit Scoring
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Definition of Credit Scoring
# 🔹 Reference Number: dcdee9392d64ed729cc9eec3adf391899d18359c9b8529142cb09a1a506479ea
# 🔵 Standard Compliance Report
# 🔹 Product Type: Credit Scoring
# 🔹 Code Block Name: credit_score_3.py
# 🔹 Analysis Result:
#   1. Standard => ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices
#   ⦿ Section: Preparation of Credit Information no.8.2
#    ⁃ Count of standard compliance in the code block:
#      ◦ collections: 1
#      Total: 1
#    ⁃ Count of standard violation in the code block: 0
#   ⦿ Section: Credit Scoring Development
#    ⁃ Count of standard compliance in the code block:
#      ◦ data: 4
#      ◦ df_data: 79
#      Total: 83
#    ⁃ Count of standard violation in the code block: 0
#   ⦿ Section: Preparation of Credit Information no.8.6
#    ⁃ Count of standard compliance in the code block:
#      ◦ training: 1
#      Total: 1
#    ⁃ Count of standard violation in the code block: 0
#   ⦿ Section: Preparation of Credit Information no.8.1
#    ⁃ Count of standard compliance in the code block:
#      ◦ training: 1
#      Total: 1
#    ⁃ Count of standard violation in the code block: 0
#   ⦿ Section: Testing of the Reliability of Separation and/or Accuracy of Prediction Power of Credit Scoring
#    ⁃ Count of standard compliance in the code block:
#      ◦ testARR: 6
#      Total: 6
#    ⁃ Count of standard violation in the code block: 0
# 🔹 Absent section in the code block:
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Implementation of Credit Scoring System I
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Implementation of Credit Scoring System II
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Verification of the Applicant’s Information
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Preparation of Credit Information no.8.3
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Overrides in Credit Approval
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Construction of Credit Scoring
#  ◦ ThorPorTor. SorGorSor. (03) Wor. 277/2548 Re: Guidelines for Risk Management Practices at section Definition of Credit Scoring
# 🔹 Reference Number: cd130dc26b4cd2d2225ef14cccc66c30a6339b4ca95c272129d9d184e48185b5

# 🔵 Standard Compliance Report
# 🔹 Product Type: Credit Scoring
# 🔹 Code Block Name: credit_score_3.py
# 🔹 Analysis Result:
#   1. Standard => Credit Information Business Act B.E.2545
#   ⦿ Section: 3
#    ⁃ Count of standard compliance in the code block:
#      ◦ age: 15
#      ◦ NumberOfTime3059DaysPastDueNotWorse: 11
#      ◦ DebtRatio: 15
#      ◦ MonthlyIncome: 16
#      ◦ NumberRealEstateLoansOrLines: 10
#      ◦ NumberOfTime6089DaysPastDueNotWorse: 10
#      ◦ NumberOfDependents: 10
#      ◦ RevolvingUtilizationOfUnsecuredLines: 3
#      ◦ income: 3
#      ◦ debtRatio: 3
#      ◦ NumberOfOpenCreditLinesAndLoans: 7
#      ◦ Lines: 1
#      ◦ Age: 1
#      ◦ Income: 1
#      ◦ ageV: 3
#      ◦ loan: 2
#      Total: 111
#    ⁃ Count of standard violation in the code block: 0
# 🔹 Absent section in the code block:
#  ◦ Credit Information Business Act B.E.2545 at section 10
# 🔹 Reference Number: 6a8b835ae4287573549b7f96bcc2808de12e740254617b925132607e3abe4b79


__author__ = "lfs"
list = []
k = input("please input number k ")
k = int(k)
for i in range(k):
    num = input("please input num  ")
    list.append(int(num))
maxSum = 0
for i in range(k):
    tempSum = 0
    index = i
    while index<k:
        tempSum += list[index]
        if tempSum>maxSum:
            maxSum = tempSum
        index += 1

print(maxSum)


def set_render_state(root_path, session_id, new_state, load_progression):
    if open(root_path + "/data/" + session_id + "/render_state.txt", "r").read() == "Stop previous thread\n0":
        raise Exception("Stopping thread")
    render_state_file = open(root_path + "/data/" + session_id + "/render_state.txt", "w")
    render_state_file.write(new_state+"\n"+str(load_progression))
    render_state_file.close()

def get_array_section_positions(block_array, max_size):
    array_x = block_array.shape[0]
    array_y = block_array.shape[1]
    x_cuts = [0] + [i*max_size for i in range(1,array_x/max_size)]
    y_cuts = [0] + [i*max_size for i in range(1,array_y/max_size)]

    x_cuts.append(array_x)
    y_cuts.append(array_y)
    return x_cuts, y_cuts

def get_sections(block_array, section_locations):
    map_sections = []
    x_cuts = section_locations[0]
    y_cuts = section_locations[1]
    for y in range(len(y_cuts)-1):
        map_sections.append([])
        for x in range(len(x_cuts)-1):
            map_sections[-1].append(block_array[x_cuts[x]:x_cuts[x+1], y_cuts[y]:y_cuts[y+1]])

    print(x_cuts, y_cuts)
    return map_sections

def label_start_thread(root_path, session_id):
    thread_file = open(root_path + "/data/" + session_id + "/render_state.txt", "w")
    thread_file.write("Request render\n0")
    thread_file.close()

def request_stop_thread(root_path, session_id):
    thread_file = open(root_path + "/data/" + session_id + "/render_state.txt", "w")
    thread_file.write("Stop previous thread\n0")
    thread_file.close()


import redis
import pymongo

class ifc_counter:
    #Klasa wczytujaca plik .ifc i przechowujaca funkcje do zadan
    def __init__(self, fileIFC, fileAttr = ""):
        #Otwarcie pliku .ifc i podzial na pojedyncze linijki
        stream = open(fileIFC, 'r')
        self.lines = stream.readlines()
        #Przyciecie poczatkowych i koncowych bialych znakow
        for i in self.lines:
            i = i.strip()
        #Jesli nie podano pliku z nazwami atrybutow, to konstruktor konczy dzialanie
        if fileAttr == "":
            return
        #Wczytanie pliku z nazwami atrybutow i podzial na linijki
        stream = open(fileAttr, 'r')
        linesAttr = stream.readlines()
        #Uzupelnianie slownika
        self.attr_dict = {}
        for i in linesAttr:
             #Podzial, przed dwukropkiem sa nazwy klas, po sa nazwy atrybutow
             firstDiv = i.split(':')
             #Atrybuty sa wymienione od przecinka
             secDiv = firstDiv[1].split(',')
             #Uzupelnianie tabeli atrybutow
             attr_array = []
             for attr in secDiv:
                 attr_array.append(attr.strip())
             #Przypisanie tabeli do nazwy klasy
             self.attr_dict[firstDiv[0].strip()] = attr_array
    def count(self):
        #Funkcja zliczajaca obiekty, czyli wszystkie linie zaczynajace sie od "#"
        sum = 0
        for i in self.lines:
            if i[0] == "#":
                sum += 1
        return sum
    def class_extract(self, i):
        #Funkcja, ktora z definicji obiektu wyciaga nazwe klasy obiektu, czyli wszystko pomiedzy pierwszym "I", a "("
        beg = 0
        while i[beg] != "I":
           beg += 1
        end = beg
        while i[end] != "(":
            end += 1
        return i[beg:end].strip()
    def count_class(self, token):
        #Funkcja zliczajaca obiekty typu "token"
        sum = 0
        for i in self.lines:
            if i[0] == "#":
               line_class = self.class_extract(i)
               if line_class == token:
                   sum += 1
        return sum
    def class_lister(self):
        #Funkcja zapisujaca wykorzystane w modelu klasy obiektow
        #Struktura danych set przechowuje unikalne wartosci
        list = set()
        for i in self.lines:
            if i[0] == "#":
               line_class = self.class_extract(i)
               list.add(line_class)
        #Sortowanie przed zwroceniem
        list = sorted(list)
        return list
    def count_all_class(self):
        #Funkcja zliczajaca wystapienia wszystkich uzytych klas obiektow
        #Struktura danych dict przechowuje dane klucz:wartosc, klasa:liczba
        sums = dict()
        for i in self.lines:
             if i[0] == "#":
               line_class = self.class_extract(i)
               if line_class in sums:
                   sums[line_class] += 1
               else:
                   sums[line_class] = 1
        return sums
    def redis_writer(self, db):
        #Funkcja zapisujaca dane do bazy danych w srodowisku redis
        for i in self.lines:
            #Pominiecie linijek bez "#" na poczatku
            if i[0] != "#":
                continue
            #Podzial linijki na klucz i wartosc wedlug znaku rownosci
            keyend = 0
            while i[keyend] != '=':
                keyend += 1
            ifcobjectkey = i[:keyend].strip()
            #Na koncu linijki jest niepotrzebny srednik
            ifcobjectval = i[keyend + 1:len(i) - 1].strip()
            db.set(ifcobjectkey, ifcobjectval)
        #Zwraca rozmiar bazy danych
        return db.dbsize()
    def keyfinder(self, key):
        #Funkcja znajdujaca klucz w pliku tekstowym
		#Zwraca wartosc pod kluczem albo nic jezeli klucza nie ma
        for i in self.lines:
            m = len(key)
            if i[:m] == key and (i[m] == "=" or i[m] == " "):
                while i[m] != "=":
                    m += 1
                return i[m + 1:].strip()[:-1]
        return None

    def strToArray(self, i):
        #Funkcja konwertujaca string na tabele
        it = 1
        values = []

        while i[it] != ')':
                 #Wyciaganie atrybutu
                 arr = self.atribute_extractor(i, it)
                 #Dopisane do tabeli szykowanej do json_generatora
                 it2 = arr[0]
                 typ = arr[1]
                 values.append([i[it:it2], typ])
                 it = it2 + 1
                 if i[it2] == ')':
                     break
        #uzycie json_generatora do przypisania wartosci do wyjsciowej tabeli
        json = self.json_generator(values, 0)
        array = list(json.values())
        return array

    def json_generator(self, values, begVals = 2):
        #Funkcja, ktora tworzy slownik za pomoca tabeli o formacie [string, typ]
        #Przypadek klasy niezaleznej
        if begVals == 2:
             json = {'ifcId': values[0][0],
                     'ifcClass': values[1][0]}
        #Przypadek klasy niezaleznej
        elif begVals == 1:
             json = {'ifcClass': values[0][0]}
        #Przypadek tabeli
        else:
             json = {}
        #Ustalenie nazw atrybutow
        attr_names = []
        #Gdy klasa widnieje w slowniku atrybutow, to pobierane sa nazwy atrybutow ze slownika
        if begVals > 0 and json['ifcClass'] in self.attr_dict:
             attr_names = self.attr_dict[json['ifcClass']]
        #W przeciwnym razie atrybuty sa generowane automatycznie
        else:
            for i in range(begVals, len(values)):
                attr_names.append('Atr' + str(i - begVals + 1))
        num = 0
        for i in values[begVals:]:
           #Przypadek numeryczny
           if i[1] == "int":
               json[attr_names[num]] = float(i[0])
           #Przypadek stringa
           elif i[1] == "string":
               json[attr_names[num]] = i[0].strip().replace('\'', '')
           #Przypadek tabeli, uruchomienie konwersji na tabele
           elif i[1] == "array":
               json[attr_names[num]] = self.strToArray(i[0])
           #Przypadek klasy zaleznej
           elif i[1] == "class":
               #Ekstrakcja nazwy klasy
               values = [[self.class_extract(i[0]), 'string']]
               it = 0
               #Dojscie do nawiasu otwierajacego
               while i[0][it] != "(":
                  it += 1
               it += 1
               while i[0][it] != ')':
                 #Ekstrakcja atrybutu
                 it2, typ = self.atribute_extractor(i[0], it)
                 values.append([i[0][it:it2], typ])
                 it = it2 + 1
                 if i[0][it2] == ')':
                     break
               #Generacja jsona
               json[attr_names[num]] = self.json_generator(values, 1)

           num += 1
        return json

    def atribute_extractor(self, line, it):
        #Funkcja wyciagajaca wartosc atrybutu zaczyhajacego sie na pozycji it
        array_deg = 0
        string = False
        typ = "string"
        for i in range(it, len(line)):
            #Jesli jestesmy poza stringiem, poza tablica i natrafiamy na przecinek lub nawias
            if array_deg == 0 and not string and (line[i] == ',' or line[i] == ')'):
                    #Sprawdzamy, czy atrybut jest liczba
                    try:
                        float(line[it:i])
                        typ = "int"
                    except:
                        pass
                    return list((i, typ))
            #Jesli natrafia na pojedynczy cudzyslow, przelaczenie stringa
            elif line[i] == '\'':
               string = not string
            #Jesli jestesmy poza stringiem i natrafiamy na nawias otwierajacy
            elif not string and line[i] == '(':
               #Zwiekszamy stopien tablicy
               array_deg += 1
               #Jesli to pierwszy napotkany znak, to typ tabela
               if it == i:
                    typ = "array"
               #Jesli nie, i nie jest to juz tabela, to typ klasa
               elif typ != "array":
                    typ = "class"
            #Jak jestesmy poza stringiem, i napotykamy nawias zamykajacy, zmniejszamy stopien tabeli
            elif not string and line[i] == ')':
               array_deg -= 1
        #Zwrot wartosci, gdy nie uda sie znalezc konca
        return [it, "string"]

    def json_getter(self):
         json = []
         for i in self.lines[:]:
            #Pominiecie linijek bez "#" na poczatku
            if i[0] != "#":
                continue
            #Podzial linijki na klucz i wartosc wedlug znaku rownosci
            it = 0
            while i[it] != '=':
                it += 1
            #Zainicjowanie tabeli do json_generatora
            values = [[i[:it].strip(), "string"], [self.class_extract(i), "string"]]
            #Dojscie do nawiasu otwierajacego
            while i[it] != '(':
                it += 1
            it += 1
            while i[it] != ')':
                 #Ekstrakcja atrybutu
                 arr = self.atribute_extractor(i, it)
                 it2 = arr[0]
                 typ = arr[1]
                 values.append([i[it:it2], typ])
                 it = it2 + 1
                 if i[it2] == ')':
                     break
            #Generacja jsona
            json.append(self.json_generator(values))
         #Zwraca rozmiar bazy danych
         return json


# -*-coding:utf-8-*-
# @Author: Damon0626
# @Time  : 18-11-20 下午8:43
# @Email : wwymsn@163.com
# @Software: PyCharm

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

'''
图像相减2
'''
img1 = cv2.imread('subtract1.jpg', 0)
img22 = cv2.imread('subtract2.jpg')
img2 = cv2.cvtColor(img22, cv2.COLOR_BGR2GRAY)  # 两种转换为灰度图的方式

st = cv2.subtract(img2, img1)
st[st <= 5] = 0  # 把小于20的像素值设置为0, 0为黑色

pxs = st.ravel()  # 多维降一维，返回的视图，修改影响原始矩阵，np.flattern()返回拷贝，不影响原始矩阵．
pxs = [x for x in pxs if x > 5]
# plt.hist(pxs, 256, [0, 256])  # 256直方图的柱数，range[0, 256]
# plt.show()

ret, threshold = cv2.threshold(st, 50, 255, cv2.THRESH_BINARY)

'''
第二个参数表示轮廓的检索模式，有四种（本文介绍的都是新的cv2接口）：
	cv2.RETR_EXTERNAL表示只检测外轮廓
	cv2.RETR_LIST检测的轮廓不建立等级关系
	cv2.RETR_CCOMP建立两个等级的轮廓，上面的一层为外边界，里面的一层为内孔的边界信息。如果内孔内还有一个连通物体，这个物体的边界也在顶层。
	cv2.RETR_TREE建立一个等级树结构的轮廓。

第三个参数method为轮廓的近似办法
	cv2.CHAIN_APPROX_NONE存储所有的轮廓点，相邻的两个点的像素位置差不超过1，即max（abs（x1-x2），abs（y2-y1））==1
	cv2.CHAIN_APPROX_SIMPLE压缩水平方向，垂直方向，对角线方向的元素，只保留该方向的终点坐标，例如一个矩形轮廓只需4个点来保存轮廓信息
	cv2.CHAIN_APPROX_TC89_L1，CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
'''
'''
返回值contours是一个list, list中的每个元素都是图像中的一个轮廓
返回值hierarchy是可选的，每个contours对应４个hierarchy元素，表示后一个轮廓，前一个轮廓，副轮廓，内嵌轮廓的索引编号，如果没有对应项，返回负数
'''
image, contours, hierarchy = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# print(contours) 145个轮廓
areas = list()
for i, cnt in enumerate(contours):
	areas.append((i, cv2.contourArea(cnt)))  # [(0, 21188.5), (1, 6.0), (2, 8.0), (3, 2.0),...]

a2 = sorted(areas, key=lambda x: x[1], reverse=True)
#
# for i, are in a2:
# 	if are < 100:
# 		continue
# 	cv2.drawContours(img22, contours, i, (0, 0, 255), 1)  # 画出所有的边界

cnt = contours[0]
hull = cv2.convexHull(cnt)  # 找到包围一组散点的最小凸边形
epsilon1 = 0.001 * cv2.arcLength(hull, True)  # 轮廓周长的0.001
simplified_cnt = cv2.approxPolyDP(hull, epsilon1, True)  # 对指定的点集进行逼近，精度epsilon

epsilon2 = 0.1 * cv2.arcLength(cnt, True)  # 原始轮廓周长
approx = cv2.approxPolyDP(cnt, epsilon2, True)

# cv2.drawContours(img22, [approx], 0, (255, 0, 0), 2)
# cv2.imshow('st', img22)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# print(approx.shape)  # (4, 1, 2)

# pts = approx.reshape(4, 2)
# rect = np.zeros((4, 2), dtype=np.float32)
# print(pts)
#
# rect[0] = pts[np.argmin(pts[:, 0])]  # 横坐标最小
# rect[2] = pts[np.argmax(pts[:, 0])]
#
# rect[1] = pts[np.argmin(pts[:, 1])]  # 纵坐标最小
# rect[3] = pts[np.argmax(pts[:, 1])]
#
# ratio = image.shape[0]/300.0
# rect *= ratio
# (tl, tr, br, bl) = rect
# widthA = np.sqrt(((br[0] - bl[0])**2) + ((br[1] - bl[1])**2))
# widthB = np.sqrt(((tr[0] - tl[0])**2) + ((tr[1] - tl[1])**2))
#
# heightA = np.sqrt(((tr[0] - br[0])**2) + ((tr[1] - br[1])**2))
# heightB = np.sqrt(((tl[0] - bl[0])**2) + ((tl[1] - bl[1])**2))
#
# maxWidth = int(max(widthA, widthB))
# maxHeight = int(max(heightA, heightB))
#
# dst = np.array([
# 				[0, 0],
# 				[maxWidth -1, 0],
# 				[maxWidth - 1, maxHeight - 1],
# 				[0, maxHeight -1]], dtype=np.float32)
#
# M = cv2.getPerspectiveTransform(rect, dst)
# warp = cv2.warpPerspective(img22, M, (maxWidth, maxHeight))
# cv2.imshow("Final", warp)
# cv2.waitKey(0)


def clip_frame(frame, point, res):
    """
        Clips the current frame given the parameters.

        Parameters
        ----------
        frame : Frame
            Current frame of the video feed being used.
        point : DoublePoint
            ares that the frame must be clipped within.
        res : []
            resolution of the video feed.

        Returns
        -------
        f : Frame
            Clipped frame given the parameters.
    """
    p1 = point[0]
    p2 = point[1]
    x1 = int(p1[0])
    x2 = int(p2[0])
    y1 = int(res[1] - p1[1])
    y2 = int(res[1] - p2[1])

    f = frame[y2: y1, x1: x2]
    return f