# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import scipy as sp
import scipy.stats

'''
Git command line:

git add 'baseball_data.py'
git commit -m 'initial commit'
git remote add origin https://github.com/cjpeck/baseball_data.git
git push -u origin master
'''

def get_team_stats(bt, pt, fd, tm):

    tFrame = [1985, 2014]
    years = list(range(tFrame[0], tFrame[1]+1))

    tm_keys = ['G', 'W', 'L', 'DivWin', 'WCWin', 'LgWin', 'WSWin']
    bt_keys = ['AB', 'R', 'H', '2B', '3B', 'HR', 'RBI', 'SB', 'CS', 'BB',
               'SO', 'IBB', 'HBP', 'SH', 'SF', 'GIDP']
    pt_keys = ['CG', 'SHO', 'SV', 'IPouts', 'H', 'ER', 'HR', 'BB',
               'SO',  'BFP', 'R']
    fd_keys = ['E', 'SB', 'CS']
    bt_keys.remove('AB')
    bt_keys.remove('R')
    bt_keys.remove('H')
    pt_keys.remove('IPouts')
    pt_keys.remove('SV')
    pt_keys.remove('R')
    pt_keys.remove('BFP')

    keys = [x + '_bt' for x in bt_keys]
    keys += [x + '_pt' for x in pt_keys]
    keys += [x + '_fd' for x in fd_keys]
    keys += ['salary', 'n_over_2SD', 'n_over_3SD', 'n_over_4SD']

    indices = [[], []]
    remove = []
    for year in years:
        tm_year = tm[str(year)]
        if np.sum(tm_year['G'] < 160):
            print('skipping year ' + str(year))
            remove.append(year)
            continue
        teams = tm_year['teamID']
        #indices.extend([(year, team) for team in teams])
        indices[0].extend([year for _ in teams])
        indices[1].extend([team for team in teams])
    for year in remove:
        years.remove(year)

    dfx = pd.DataFrame(index=indices, columns=keys)
    dfy = pd.DataFrame(index=indices, columns=tm_keys)

    for year in years:
        tm_year = tm[str(year)]
        sal_year =  sal[str(year)]
        bt_year = bt[bt['yearID']==year]
        pt_year = pt[pt['yearID']==year]
        fd_year = fd[fd['yearID']==year]
        teams = tm_year['teamID']

        for team in teams:

            # team results
            team_data = tm_year[tm_year['teamID']==team]
            s = pd.Series(team_data[tm_keys].sum(skipna=True))
            dfy.ix[(year, team)] = s

            #append batting information
            team_data = bt_year[bt_year['teamID']==team]
            s = pd.Series(team_data[bt_keys].sum(skipna=True))
            s.index = [s.index[i] + '_bt' for i in range(len(s))]
            count = len(s)

            #append pitching information
            team_data = pt_year[pt_year['teamID']==team]
            s = s.append(team_data[pt_keys].sum(skipna=True))
            s.index = [s.index[i] + '_pt' if i >= count else s.index[i]
                       for i in range(len(s))]
            count = len(s)

            #append fielding information
            team_data = fd_year[fd_year['teamID']==team]
            s = s.append(team_data[fd_keys].sum(skipna=True))
            s.index = [s.index[i] + '_fd' if i >= count else s.index[i]
                       for i in range(len(s))]
            count = len(s)

            #append salaray information
            team_data = sal_year[sal_year['teamID']==team]['salary']
            salary = float(team_data.sum())
            mean = float(sal[str(year)].mean())
            std = float(sal[str(year)].std())
            n_over_2SD = (team_data >= mean + 2*std).sum()
            n_over_3SD = (team_data >= mean + 3*std).sum()
            n_over_4SD = (team_data >= mean + 4*std).sum()
            s =  s.append(pd.Series([salary, n_over_2SD, n_over_3SD, n_over_4SD],
                                    index=['salary', 'n_over_2SD', 'n_over_3SD', 'n_over_4SD']))

            #append to dataframe
            dfx.ix[(year, team)] = s

    return dfx, dfy

### ANALYSIS OF SALARY PREDICTING WINSS
def salary_figures(dfx, dfy):

    directory = '/Users/cjpeck/Dropbox/spyder2/baseball/figures/'

    # parameters for sliding window regression
    years = dfx.index.levels[0]
    tInt = 10
    tShift = 1
    tStart = []
    tEnd = []
    i = 0
    while i + tInt < len(years):
        tStart.append(years[i])
        tEnd.append(years[i+tInt])
        i += tShift

    #normalize
    dfx_z = dfx.apply(lambda x: (x - dfx.ix[x.name[0]].mean()) /
                                 dfx.ix[x.name[0]].std(), axis=1)

    # overall regression (for all years) and sliding regression
    beta = sp.stats.linregress(dfx_z['salary'], dfy['W'])
    beta_sliding = []
    for t in range(len(tStart)):
        tmp =sp.stats.linregress(dfx_z.ix[tStart[t]:tEnd[t], 'salary'],
                                 dfy.ix[tStart[t]:tEnd[t], 'W'])
        beta_sliding.append(tmp[0])

    # scatter of salary predicting wins
    plt.figure()
    xmin = dfx_z['salary'].min()
    xmax = dfx_z['salary'].max()
    plt.plot((xmin, xmax), (xmin * beta[0] + beta[1], xmax * beta[0] + beta[1]),
                     color='r', linestyle='-')
    plt.scatter(dfx_z['salary'], dfy['W'])
    plt.title('b1=%1.2f, p=%1.4f' % (beta[0], beta[3]))
    plt.savefig(directory + 'salary_wins.eps', bbox_inches='tight')
    plt.show()

    # mean salary as a function of year
    plt.figure()
    plt.plot(years, dfx.mean(axis=0, level=0)/1e6)
    plt.xlabel('Year')
    plt.ylabel('Mean salary (millions $)')
    plt.savefig(directory + 'mean_salary.eps', bbox_inches='tight')
    plt.show()

    # change in z-score as function to time (sliding window regression) to win
    # 'wins_desired' more games
    plt.figure()
    wins_desired = 4
    money_needed = wins_desired / np.array(beta_sliding)
    plt.plot(np.mean(np.c_[tStart, tEnd], 1), money_needed)
    plt.xlabel('Year')
    plt.ylabel('Change in z-score, to get %d wins' % wins_desired)
    plt.savefig(directory + 'year_wins.eps', bbox_inches='tight')
    plt.show()

    # salary as a function of year for common z-scores
    z_vals = np.array([0, 1, 2])
    z_chart = pd.DataFrame()
    for i in z_vals:
        z_chart[i] = (dfx.mean(level=0)['salary'] +
                      dfx.std(level=0)['salary'] * i) / 1e6
    z_chart.plot()
    plt.xlabel('Year')
    plt.ylabel('Salary')
    plt.savefig(directory + 'year_salary.eps', bbox_inches='tight')
    plt.show()

    # how does salary increase predict an increase in probability of winning
    # the World Series
    plt.figure()

    keys = ['DivWin', 'WCWin', 'LgWin', 'WSWin']
    nkeys = ['nDivWin', 'nWCWin', 'nLgWin', 'nWSWin']

    bin_size = 10 # need to be an int divisble by 2 and a factor of 100
    x_vals = list(range(int(bin_size/2), 100, bin_size))
    df = pd.DataFrame(index=x_vals, columns=keys+nkeys)
    for i in range(len(x_vals)):
        lb = np.percentile(dfx_z['salary'], i * bin_size)
        ub = np.percentile(dfx_z['salary'], (i+1) * bin_size)
        winners = dfy.ix[(dfx_z['salary'] > lb) & (dfx_z['salary'] <= ub), keys] == 'Y'
        losers = dfy.ix[(dfx_z['salary'] > lb) & (dfx_z['salary'] <= ub), keys] == 'N'
        n = winners.sum().add(losers.sum())
        df.ix[x_vals[i], keys] = winners.sum().divide(n)
        df.ix[x_vals[i], nkeys] = n.rename({keys[i]: nkeys[i] for i in range(len(n))})
    df[keys].plot(xlim=[0,100])
    plt.savefig(directory + 'playoff_prob.eps', bbox_inches='tight')

    plt.figure()
    x2 = dfx['n_over_2SD'] + (.1 * np.random.random(size=(len(dfx),)) - 0.05)
    x3 = dfx['n_over_3SD'] + (.1 * np.random.random(size=(len(dfx),)) - 0.05)
    x4 = dfx['n_over_4SD'] + (.1 * np.random.random(size=(len(dfx),)) - 0.05)
    plt.scatter(x2, dfy['W'], c='b', s=5)
    plt.scatter(x3, dfy['W'], c='r')
    plt.scatter(x4, dfy['W'], c='g')
    b2 = sp.stats.linregress(x2, dfy['W'])
    b3 = sp.stats.linregress(x3, dfy['W'])
    b4 = sp.stats.linregress(x4, dfy['W'])
    plt.show()

if __name__ == '__main__':

    # Load data
    master_fname = '/Users/cjpeck/Dropbox/spyder2/baseball/lahman-csv_2015-01-24/Master.csv'
    ms = pd.DataFrame.from_csv(master_fname)

    batting_fname = '/Users/cjpeck/Dropbox/spyder2/baseball/lahman-csv_2015-01-24/Batting.csv'
    bt = pd.DataFrame.from_csv(batting_fname)
    bt['AVG'] = bt['H'] / bt['AB']
    bt['SLG'] = (bt['H'] + 1*bt['2B'] + 2*bt['3B'] + 3*bt['HR']) / bt['AB']

    pitching_fname = '/Users/cjpeck/Dropbox/spyder2/baseball/lahman-csv_2015-01-24/Pitching.csv'
    pt = pd.DataFrame.from_csv(pitching_fname)

    fielding_fname = '/Users/cjpeck/Dropbox/spyder2/baseball/lahman-csv_2015-01-24/Fielding.csv'
    fd = pd.DataFrame.from_csv(fielding_fname)

    team_fname = '/Users/cjpeck/Dropbox/spyder2/baseball/lahman-csv_2015-01-24/Teams.csv'
    tm = pd.DataFrame.from_csv(team_fname)

    sal = pd.DataFrame.from_csv(
        '/Users/cjpeck/Dropbox/spyder2/baseball/lahman-csv_2015-01-24/Salaries.csv')

    # error in the salaries CSV which includes teams 'SFG' and 'NYM' which
    # should instead be 'SFN' and 'NYN' - applies to 2014 only
    sal.ix[(sal.index==pd.Timestamp('2014-01-01')) &
           (sal['teamID']=='NYM'), 'teamID'] = 'NYN'
    sal.ix[(sal.index==pd.Timestamp('2014-01-01')) &
           (sal['teamID']=='SFG'), 'teamID'] = 'SFN'

    for year in range(bt['yearID'].min(), bt['yearID'].max() + 1):
        bt_teams = bt.ix[bt['yearID']==year, 'teamID'].unique()
        pt_teams = pt.ix[pt['yearID']==year, 'teamID'].unique()
        fd_teams = fd.ix[fd['yearID']==year, 'teamID'].unique()
        tm_teams = tm.ix[str(year), 'teamID'].unique()
        n_teams = [len(bt_teams), len(pt_teams), len(fd_teams), len(tm_teams)]
        if str(year) in sal.index:
            sal_teams = sal.ix[str(year), 'teamID'].unique()
            n_teams.append(len(sal_teams))
        if len(np.unique(n_teams)) > 1:
            print(str(year), str(n_teams))

    dfx, dfy = get_team_stats(bt, pt, fd, tm)
    salary_figures(dfx, dfy)


from datetime import datetime
from pynput.keyboard import Key, Controller
import time, os
keyboard = Controller()

browser = "google-chrome"     # replace it with your browser
link = "jcx-sgnp-dra"        # set your link here
meet_time = ("12:14:30")   # set your time here

def presstabkey(num, tym, keys):

	time.sleep(tym)
	while num > 0 :
		keyboard.press(keys)
		keyboard.release(keys)
		num = num-1
	keyboard.press(Key.enter)
	keyboard.release(Key.enter)

while True:
	now = datetime.now()
	if now.strftime("%H:%M:%S")  == meet_time:
	    os.system("gnome-terminal -e '"+browser+" http://meet.google.com/"+link+"'")
	    presstabkey(8, 20, Key.tab)
	    break


import grpc
import pytest

from couchers import errors
from couchers.db import session_scope
from couchers.models import Cluster, User
from couchers.servicers.admin import Admin
from proto import admin_pb2, admin_pb2_grpc
from tests.test_fixtures import db, generate_user, get_user_id_and_token, real_session, testconfig  # noqa

@pytest.fixture(autouse=True)
def _(testconfig):
    pass

NORMAL_USER_NAME = "normal_user"
SUPER_USER_NAME = "super_user"
NORMAL_USER_EMAIL = "normal@user.com"
COMMUNITY_NAME = "test community"
COMMUNITY_SLUG = "test-community"
COMMUNITY_DESCRIPTION = "community for testing"
VALID_GEOJSON_MULTIPOLYGON = """
    {
      "type": "MultiPolygon",
      "coordinates":
       [
        [
          [
            [
              -73.98114904754641,
              40.7470284264813
            ],
            [
              -73.98314135177611,
              40.73416844413217
            ],
            [
              -74.00538969848634,
              40.734314779027144
            ],
            [
              -74.00479214294432,
              40.75027851544338
            ],
            [
              -73.98114904754641,
              40.7470284264813
            ]
          ]
        ]
      ]
    }
"""
POINT_GEOJSON = """
{ "type": "Point", "coordinates": [100.0, 0.0] }
"""

def _admin_session(token: str):
    return real_session(token, admin_pb2_grpc.add_AdminServicer_to_server, Admin(), admin_pb2_grpc.AdminStub)

def _get_super_token():
    with session_scope() as session:
        _, super_token = get_user_id_and_token(session, SUPER_USER_NAME)
        return super_token

def _get_normal_user(session):
    return session.query(User).filter(User.username == NORMAL_USER_NAME).one_or_none()

def _get_super_user(session):
    return session.query(User).filter(User.username == SUPER_USER_NAME).one_or_none()

def _generate_normal_user(session):
    generate_user(username=NORMAL_USER_NAME, email=NORMAL_USER_EMAIL)

def _generate_super_user(session):
    generate_user(username=SUPER_USER_NAME, is_superuser=True)

def test_AccessByNormalUser(db):
    with session_scope() as session:
        _generate_normal_user(session)
        normal_user_id, normal_token = get_user_id_and_token(session, NORMAL_USER_NAME)
        with _admin_session(normal_token) as api:

            # all requests to the admin servicer should break when done by a non-super_user
            with pytest.raises(grpc.RpcError) as e:
                api.GetUserEmailById(
                    admin_pb2.GetUserEmailByIdReq(
                        user_id=normal_user_id,
                    )
                )
            assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED

def test_GetEmailByUserId(db):
    with session_scope() as session:
        _generate_normal_user(session)
        _generate_super_user(session)
        normal_user = _get_normal_user(session)
        with _admin_session(_get_super_token()) as api:
            res = api.GetUserEmailById(admin_pb2.GetUserEmailByIdReq(user_id=normal_user.id))
        assert res.email == NORMAL_USER_EMAIL
        assert res.user_id == normal_user.id

def test_GetEmailByUserName(db):
    with session_scope() as session:
        _generate_normal_user(session)
        _generate_super_user(session)
        normal_user = _get_normal_user(session)
        with _admin_session(_get_super_token()) as api:
            res = api.GetUserEmailByUsername(admin_pb2.GetUserEmailByUsernameReq(username=normal_user.username))
            assert res.email == NORMAL_USER_EMAIL
            assert res.user_id == normal_user.id

def test_GetBanUser(db):
    with session_scope() as session:
        _generate_normal_user(session)
        _generate_super_user(session)
        with _admin_session(_get_super_token()) as api:
            normal_user = _get_normal_user(session)
            api.BanUser(admin_pb2.BanUserReq(user_id=normal_user.id))
            session.refresh(normal_user)
            assert normal_user.is_banned

def test_GetDeleteUser(db):
    with session_scope() as session:
        _generate_normal_user(session)
        _generate_super_user(session)
        with _admin_session(_get_super_token()) as api:
            normal_user = _get_normal_user(session)
            api.DeleteUser(admin_pb2.DeleteUserReq(user_id=normal_user.id))
            session.refresh(normal_user)
            assert normal_user.is_deleted

def test_CreateCommunityInvalidGeoJson(db):
    with session_scope() as session:
        _generate_normal_user(session)
        _generate_super_user(session)
        with _admin_session(_get_super_token()) as api:
            with pytest.raises(grpc.RpcError) as e:
                api.CreateCommunity(
                    admin_pb2.CreateCommunityReq(
                        name=COMMUNITY_NAME,
                        slug=COMMUNITY_SLUG,
                        description=COMMUNITY_DESCRIPTION,
                        admin_ids=[],
                        geojson=POINT_GEOJSON,
                    )
                )
            assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
            assert e.value.details() == errors.NO_MULTIPOLYGON

def test_CreateCommunity(db):
    with session_scope() as session:
        _generate_normal_user(session)
        _generate_super_user(session)
        with _admin_session(_get_super_token()) as api:
            api.CreateCommunity(
                admin_pb2.CreateCommunityReq(
                    name=COMMUNITY_NAME,
                    slug=COMMUNITY_SLUG,
                    description=COMMUNITY_DESCRIPTION,
                    admin_ids=[],
                    geojson=VALID_GEOJSON_MULTIPOLYGON,
                )
            )
            community = session.query(Cluster).filter(Cluster.name == COMMUNITY_NAME).one()
            assert community.description == COMMUNITY_DESCRIPTION
            assert community.slug == COMMUNITY_SLUG


#!/usr/bin/env python
import pika

import sys, time, datetime
from pathlib import Path
# Se o cliente for executado no windows ou Visual Studio Code, descomentar a linha abaixo
#sys.path.insert(0, str(Path().resolve()))
# Se o cliente for executado no linux, descomentar a linha abaixo
sys.path.insert(0, str(Path().resolve().parent))
#print Path().resolve()
from data import Data
import util

TAB_1 = '\t - '

class Client():
    _dados = Data()
    startExperimentTS = ''
    channel = ''
    queue = 'tcc_amqp'

    def establishConnection(self, address='localhost', port=5672):
        dataTest = 'Hello World!'
        print('endereco: ' + address)
        print('porta: ' + str(port))
        print('dados: ' + dataTest)

        credentials = pika.PlainCredentials('pi','raspberry')
        connection = pika.BlockingConnection(
            pika.ConnectionParameters(host=address, credentials=credentials))
        self.channel = connection.channel()
        self.channel.queue_declare(self.queue)
        response = self.channel.basic_publish(exchange='', routing_key=self.queue, body=dataTest)
        print(response)

    def startExperiment(self, reps=-1, timePerRep=1):
        """
		Inicia o Experimento
		>>Reps: quantidade de repetições que o experimento terá.
				Cada repetição é igual a 1 pacote enviado.
				Caso seja <= 0 serão enviados todos os dados disponíveis
		>>timePerRep:
				intervalo de tempo entre repetição, em segundos.
				Padrão = 1seg
		"""
        print("\nIniciando o experimento às {0}".format(
            util.getFormattedDatetimeWithMillisec()))

        if (reps <= 0):
            reps = self._dados.length()
        print("Quantidade de pacotes que serão enviados: {}".format(reps))
        duracao = timePerRep * reps
        print("Tempo estimado de duração do experimento: {} ({})\n".format(
            util.getFormattedDateTimeFromSeconds(duracao),
            str(datetime.timedelta(seconds=duracao))))

        for i in range(0, reps):
            print("iniciando repetição {} às {}".format(
                i + 1, str(util.getFormattedDatetimeWithMillisec())))
            self.sendPackage(i)
            time.sleep(timePerRep)
        print('Fechando a conexão...')
        self.channel.connection.close()
        print('Finalizado!')

    def sendPackage(self, index):
        print(TAB_1 + "Enviando pacote ...")
        response = self.channel.basic_publish(
            exchange='',
            routing_key=self.queue,
            body=self._dados.getByIndex(index).encode())
        print(TAB_1 + 'enviado: ' + str(response))

def main():
    client = Client()
    address = input(
        'Digite o endereco do servidor: (ou deixe em branco caso seja "localhost")\n'
    )
    if (address == ''):
        client.establishConnection()
    else:
        client.establishConnection(address=address)

    reps = input(
        '\nDigite a quantidade de pacotes que você deseja enviar: (ou deixe em branco para enviar a quantidade máxima possível )\n'
    )
    try:
        reps = int(reps)
    except ValueError:
        reps = -1

    client.startExperiment(reps)

if __name__ == '__main__':
    main()

# print(" [x] Sent 'Hello World!'")


from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QVBoxLayout

app = QApplication([])
main_win = QWidget()

main_win.setWindowTitle('TRASH')
main_win.resize(400, 250)

label = QLabel("Натисни щоб дізнатись переможця")
result = QLabel("?")
btn = QPushButton('Згенерувати')

line = QVBoxLayout()
line.addWidget(label)
line.addWidget(result)
line.addWidget(btn)

main_win.setLayout(line)
main_win.show()
app.exec_()


import numpy as np
import pandas as pd
import pytest
from sklearn.base import clone
from sklearn.pipeline import Pipeline
from sklearn.utils.estimator_checks import check_estimator

from feature_engine.timeseries.forecasting import (
    ExpandingWindowFeatures,
    LagFeatures,
    WindowFeatures,
)
from tests.estimator_checks.estimator_checks import check_feature_engine_estimator

_estimators = [
    LagFeatures(missing_values="ignore"),
    WindowFeatures(missing_values="ignore"),
    ExpandingWindowFeatures(missing_values="ignore"),
]

@pytest.mark.parametrize("estimator", _estimators)
def test_check_estimator_from_sklearn(estimator):
    return check_estimator(estimator)

@pytest.mark.parametrize("estimator", _estimators)
def test_check_estimator_from_feature_engine(estimator):
    return check_feature_engine_estimator(estimator)

@pytest.mark.parametrize("estimator", _estimators)
def test_error_when_not_unique_values_in_index(df_time, estimator):
    X = df_time.copy()

    # introduce dupes in index
    tmp = X.head(2).copy()
    tmp.iloc[0] = [1, 1, 1, "blue"]
    Xd = pd.concat([X, tmp], axis=0)

    transformer = clone(estimator)

    with pytest.raises(NotImplementedError):
        transformer.fit(Xd)

    transformer.fit(X)
    with pytest.raises(NotImplementedError):
        transformer.transform(Xd)

@pytest.mark.parametrize("estimator", _estimators)
def test_error_when_nan_in_index(df_time, estimator):
    X = df_time.copy()

    # Introduce NaN in index.
    tmp = X.head(1).copy()
    tmp.index = [np.nan]
    Xd = pd.concat([X, tmp], axis=0)

    transformer = clone(estimator)

    with pytest.raises(NotImplementedError):
        transformer.fit(Xd)

    transformer.fit(X)
    with pytest.raises(NotImplementedError):
        transformer.transform(Xd)

@pytest.mark.parametrize("transformer", _estimators)
def test_transformers_in_pipeline_with_set_output_pandas(df_time, transformer):
    X = df_time.copy()

    pipe = Pipeline([("trs", transformer)]).set_output(transform="pandas")

    Xtt = transformer.fit_transform(X)
    Xtp = pipe.fit_transform(X)

    pd.testing.assert_frame_equal(Xtt, Xtp)


import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import Qt
from PyQt5 import uic

import pandas as pd
import openpyxl
import datetime as pydatetime

form_class = uic.loadUiType("ui/main_page_test.ui")[0]

class WindowClass(QMainWindow, form_class) :
    def __init__(self) :
        super().__init__()
        self.initUI()
        self.show()

    def initUI(self):
        self.ts = self.get_now_timestamp()
        self.df = pd.DataFrame([['EXP_START', self.ts, -1, -1]],
                               index=[1], columns=['status', 'ts', 'ans', 'confidence'])

        self.setupUi(self)

        self.expInfoDict = {"name":"", "birth":"", "expCnt":"", "1st_ts":str(self.ts)}

        self.submitBtn.clicked.connect(self.submitBtn_clicked)

    def submitBtn_clicked(self):
        self.expInfoDict['name'] = self.nameLEdit.text()
        self.expInfoDict['birth'] = self.birthLEdit.text()
        self.expInfoDict['expCnt'] = self.expCntLEdit.text()
        self.expInfoDict['2nd_ts'] = str(self.get_now_timestamp())

        print('expInfo', self.expInfoDict)

        nowTime = pydatetime.datetime.today().strftime("%Y%m%d%H%M%S")
        print(nowTime)

        exit(1)
        # fileName = self.expInfoDict['name']+self.expInfoDict['birth']+
        # self.df.to_csv('output/'+self.expInfoDict['name'])

    def get_now(self):
        # 현재 시스템 시간을 datetime형으로 반환
        return pydatetime.datetime.now()

    def get_now_timestamp(self):
        # 현재 시스템 시간을 POSIX timestamp float형으로 반환
        return self.get_now().timestamp()

if __name__ == "__main__" :
    app = QApplication(sys.argv)
    myWindow = WindowClass()
    myWindow.show()
    app.exec_()


import math
import numpy as np
import matplotlib.pyplot as plt
File = open("Galaxy1.txt","r")
next(File)
radius=[]
V=[]
mV=[]
m=[]
DMmassV=[]
CmassV=[]

#m[radius.index(i)]+ 4*math.pi*(100*10**6)*(1.87**2)*(i-1.87*np.arctan(i/1.87))

for i in File.readlines():
    radius.append(float(i.split()[0]))
    V.append(float(i.split()[1]))
    m.append(float(i.split()[4]))

for i in radius:
    DMmassV.append(math.sqrt((4.3*10**-6)*4*math.pi*(100*10**6)*(1.87**2)*(i-1.87*np.arctan(i/1.87))*1/i))
for i in radius:
    CmassV.append(math.sqrt((4.3*10**-6)*(m[radius.index(i)]+4*math.pi*(100*10**6)*(1.87**2)*(i-1.87*np.arctan(i/1.87)))*1/i))
for i in radius:
    mV.append(math.sqrt((4.3*10**-6)*m[radius.index(i)]*1/i))

mV=np.array(mV)
radius = np.array(radius)
y = np.array(DMmassV)
CmassV = np.array(CmassV)
plt.plot(radius,CmassV)#combined DM and Visable mass
plt.plot(radius,mV)#prediction based on mass from data
plt.plot(radius,y)#DM
plt.plot(radius,V)#actual data
plt.xlabel("Radius (kpc)")
plt.ylabel("Velocity (kms^-1)")
plt.axis([0,max(radius),0,max(V)+2])
plt.show()


from enum import IntEnum
import requests
import time
import json
import logging
import os
logger = logging.getLogger('charger')
logger.setLevel(logging.INFO)
from sink import Sink

data_override_file="debug_data.json"

MIN_AMP=6
TIMEOUT_DETECT_VEHICLE = 60
TIMEOUT_WAIT_FOR_PLUG_IN = 12
UPHYSTERESIS = 20
DOWNHYSTERESIS = -20
FINISHEDLIMIT = 100
SWITCHPHASEHYSTERESIS = 300
DEFAULTPHASESWITCHSTEP = 2100000 # just a high number

class Plug_states(IntEnum):
    INITIALIZE_CHARGER = 0
    RESTARTING = 1
    WAITING_FOR_VEHICLE_PLUGGING_IN = 2
    PLUGGED_IN = 3

plug_states=[
    "initialize charger",
    "restarting",
    "waiting for vehicle plugging in",
    "plugged in"
]

class Charge_states(IntEnum):
    UNPLUGGED = 0
    INITIALIZE_VEHICLE = 1
    WAITING_FOR_INITIALIZED_VEHICLE = 2
    CHARGING = 3
    WAITING_FOR_POWER = 4
    FINISHED = 5

charge_states=[
    "unplugged",
    "initialize vehicle",
    "waiting for initialized vehilce",
    "charging",
    "wait for power",
    "finished"
]

class Charger_modes(IntEnum):
    AUTOMATIC = 0 # use self generated power only
    MANUAL = 1 # use at least the amps given by button or app
    AMOUNT = 2 # charge manually given amount of energy and then switch back to automatic
    MARKET = 3 # reserved for later

charger_modes=[
    "automatic",
    "manual",
    "amount",
    "market"
]

class Charger(Sink):
    def __init__(self,name,config):
        super().__init__(name,config)
        self.address=config.get("address")
        self.config=config
        self._charge_state=None
        self._plug_state=None
        self.charge_state=Charge_states.UNPLUGGED
        self.plug_state=Plug_states.INITIALIZE_CHARGER
        self.min_amp=int(config.get("min_amp","6"))
        self.max_amp=int(config.get("max_amp","16"))
        self.amp=-1
        self.override_amp=0
        self._car_phase_count=0
        self._used_phase_count=0
        self.is_pluggedin=False
        self.connected_phase_count=0
        self.voltage=0
        self.charging_power=0
        self.step_power=0
        self.start_power=0
        self.switch_phase_power=DEFAULTPHASESWITCHSTEP
        self.charger_activated=False
        self.phases_set=-1
        #default for start and step power are 230V 3 phases
#        self.voltage=230
#        self.car_phase_count=3
        self.wait_for_kw_stop=False
        self.wait_for_car_timeout=0
        self.statemachine()

    def get_car_phase_count(self):
        return self._car_phase_count
    def set_car_phase_count(self,phases):
        self._car_phase_count=phases
        self.used_phase_count=phases
    car_phase_count=property(get_car_phase_count,set_car_phase_count)

    def get_used_phase_count(self):
        return self._used_phase_count
    def set_used_phase_count(self,phases):
        self._used_phase_count=min(phases,self._car_phase_count)
        self.step_power=int(self._used_phase_count*self.voltage)
        self.start_power=self.min_amp*self.step_power
    used_phase_count=property(get_used_phase_count,set_used_phase_count)

    def update_charge_mode(self,oldmode):
        newmode=self.get_charge_mode()
        if newmode!=oldmode:
            logger.info(self.name+" switched charger mode to "+charger_modes[newmode])

    def get_charge_mode(self):
        if self.wait_for_kw_stop:
            return Charger_modes.AMOUNT
        elif self.override_amp>0:
            return Charger_modes.MANUAL
        else:
            return Charger_modes.AUTOMATIC
    charge_mode=property(get_charge_mode)

    def get_plug_state(self):
        return self._plug_state
    def set_plug_state(self,state):
        if self._plug_state!=state:
            self._plug_state=state
            logger.info(self.name+" Switching to plug state "+plug_states[state])
    plug_state=property(get_plug_state,set_plug_state)

    def get_charge_state(self):
        return self._charge_state
    def set_charge_state(self,state):
        if self._charge_state!=state:
            if state==Charge_states.CHARGING:
                pass
            self._charge_state=state
            logger.info(self.name+" Switching to charge state "+charge_states[state])
    charge_state=property(get_charge_state,set_charge_state)

    def update(self):
        if self.nexttick<time.time():
            self.nextinterval()
#            if self.plug_state!=Plug_states.INITIALIZE_CHARGER:
            data=self.http_get("status")
            if not data is None:
                self.data=data
                self.read_data()
                self.statemachine()
            print(self.name+": "+str(self),end="")

    def set_amp(self,newvalue):
        if newvalue<self.min_amp:
            newvalue=self.min_amp
        if newvalue<self.override_amp:
            newvalue=self.override_amp
        if newvalue>self.max_amp:
            newvalue=self.max_amp
        if newvalue!=self.amp:
            cmd="amx" if self.capabilities["amx"] else "amp"
            # update self.amp before a call of read_data to
            # prevent interpretation as override amp
            self.amp=newvalue
            self.data=self.http_get("mqtt?payload="+cmd+"="+str(newvalue))

    def switch_phases(self,phase_count):
        if phase_count>1:
            if self.phases_set!=3:
                data=self.http_get("api/set?psm=2")
                self.phases_set=3
                self.used_phase_count=3
                logger.info(self.name+" switched used phases to "+str(self.used_phase_count))
        else:
            if self.phases_set!=1:
                data=self.http_get("api/set?psm=1")
                self.phases_set=1
                self.used_phase_count=1
                logger.info(self.name+" switched used phases to "+str(self.used_phase_count))

    def activate_charger(self,run):
        alw=int(self.data["alw"])
        if run!=(alw==1):
            self.data=self.http_get("mqtt?payload=alw="+str(1 if run else 0))

    def http_get(self,uri):
        print("trying to get data from", self.address)
        try:
            r = requests.get("http://"+str(self.address)+"/"+uri,timeout=3)
            self.reachable=True
        except:
            self.reachable=False
        if self.reachable:
            if r.status_code==200:
                data=r.text
                try:
                    data=r.json()
                except:
                    pass
                return data
            else:
                return None

    def read_data(self):
        if data_override_file!="":
            try:
                with open(os.path.dirname(os.path.abspath(__file__))+data_override_file) as json_file:
                    override_data = json.load(json_file)
                    res=override_data.get("res")
                    if not res is None:
                        self.reserve=int(res)
            except:
                override_data={}
            self.data={**self.data,**override_data}
        self.is_pluggedin=self.data["car"] in [2,3,4]
        self.connected_phase_count=0
        self.voltage=0
        for phase_number in range(3):
            if self.data["nrg"][phase_number]:
                self.voltage+=self.data["nrg"][phase_number]*self.correction_factor
                self.connected_phase_count+=1
        self.voltage=int(self.voltage//self.connected_phase_count)
        self.current_power=int(round(self.data["nrg"][11]*self.correction_factor*10,0))
        oldmode=self.get_charge_mode()
        if int(self.data["amp"])!=self.amp:
            # amp value was set outside via device button or app and will be used as
            # override value
            self.override_amp=int(self.data["amp"])
            self.wait_for_car_timeout=time.time()+TIMEOUT_WAIT_FOR_PLUG_IN
        # if amount to charge is set via app temporaryly set override_amp to
        # make sure the amount is charged before going back to automatic
        if int(self.data["dwo"])>0 and not self.wait_for_kw_stop:
            self.wait_for_kw_stop=True
            if self.override_amp==0:
                self.override_amp=int(self.data["amp"])
                if int(self.data["car"])==1:
                    # wait 2 minutes for plugin of a car before returning to automatic mode
                    self.wait_for_car_timeout=time.time()+TIMEOUT_WAIT_FOR_PLUG_IN
        if self.wait_for_kw_stop and int(self.data["dwo"])==0:
            self.wait_for_kw_stop=False
            self.override_amp=0
        self.amp=int(self.data["amp"])
        self.car=int(self.data["car"])
        self.charger_activated=int(self.data["alw"])==1
        self.charging_power=int(int(self.data["nrg"][11]*10*self.correction_factor))
        self.update_charge_mode(oldmode)

    def statemachine(self):
        if self.plug_state==Plug_states.INITIALIZE_CHARGER:
            self.reachable=False
            # older chargers tend to measure a too low volate
            # as power is measured voltage*current, power needs same correction
            self.correction_factor=1.05
            self.capabilities={"phaseswitch":False,"amx":False}
            if not self.address is None:
                data=self.http_get("api/status")
                if not data is None:
                    self.capabilities["phaseswitch"]=True
                    #HW3 ist more correct than deviation of 5% from HW2 and bef6ore
                    self.correction_factor=1
                self.correction_factor=float(self.config.get("correction_factor",str(self.correction_factor)))
                self.data=self.http_get("status")
                if not self.data is None:
                    self.set_amp(0)
                    if float(self.data["fwv"])>=40:
                        self.capabilities["amx"]=True
                    self.read_data()
                if self.reachable:
                    self.plug_state=Plug_states.RESTARTING
        if self.plug_state==Plug_states.RESTARTING:
            oldmode=self.get_charge_mode()
            # reset charger mode to automatic
            self.charger_mode=Charger_modes.AUTOMATIC
            self.switch_phase_power=DEFAULTPHASESWITCHSTEP
            # set phases to 3
            if self.connected_phase_count>1 and self.capabilities["phaseswitch"]:
                self.switch_phases(3)
            # reset override_amp if restarting
            self.override_amp=0
            self.wait_for_car_timeout=0
            # set amp to minimum to notice when it was changed
            self.set_amp(MIN_AMP)
            # activate pwm signal to make button work
            self.activate_charger(True)
            # find next state
            self.update_charge_mode(oldmode)
            if self.car==1:
                self.plug_state=Plug_states.WAITING_FOR_VEHICLE_PLUGGING_IN
                self.charge_state=Charge_states.UNPLUGGED
            else:
                self.plug_state=Plug_states.PLUGGED_IN
                self.charge_state=Charge_states.INITIALIZE_VEHICLE
        if self.plug_state==Plug_states.WAITING_FOR_VEHICLE_PLUGGING_IN:
            if self.car!=1:
                self.plug_state=Plug_states.PLUGGED_IN
                self.charge_state=Charge_states.INITIALIZE_VEHICLE
            else:
                if time.time()>self.wait_for_car_timeout:
                    oldmode=self.get_charge_mode()
                    self.override_amp=0
                    self.update_charge_mode(oldmode)
                    self.set_amp(MIN_AMP)
        if self.plug_state==Plug_states.PLUGGED_IN:
            if self.car==1:
                self.plug_state=Plug_states.RESTARTING
            elif self.charge_state==Charge_states.INITIALIZE_VEHICLE:
                #detect vehicle
                if self.connected_phase_count==1:
                    self.car_phase_count=1
                    self.charge_state=Charge_states.CHARGING
                else:
                    self.timeout=time.time()+TIMEOUT_DETECT_VEHICLE # wait 15 seconds to detect number of phases that the car uses
                    self.charge_state=Charge_states.WAITING_FOR_INITIALIZED_VEHICLE
            elif self.charge_state==Charge_states.WAITING_FOR_INITIALIZED_VEHICLE:
                if self.current_power<FINISHEDLIMIT:
                    # reset the timeout as long the vehicle does not draw power,
                    # e.g. because it is fully charged or in sleep mode
                    self.timeout=time.time()+TIMEOUT_DETECT_VEHICLE
                car_phase_count=0
                for index in [7,8,9]:
                    if self.data["nrg"][index]>0:
                        car_phase_count+=1
                # if all three phases are used or timeout is over proceed with charging
                if (car_phase_count>2) or ((time.time()>self.timeout) and (car_phase_count>0)):
                    self.timeout=0
                    self.car_phase_count=car_phase_count
                    self.used_phase_count=car_phase_count
                    self.switch_phase_power=self.start_power+SWITCHPHASEHYSTERESIS
                    self.charge_state=Charge_states.CHARGING
            if self.charge_state==Charge_states.CHARGING:
                if self.reserve<DOWNHYSTERESIS:
                    newamp=max(self.override_amp,self.amp)-1
                    self.set_amp(newamp)
                    if newamp<self.min_amp:
                        # not enough power available
                        # step 1: switch to single phase if possible
                        if self.used_phase_count>1 and self.capabilities["phaseswitch"]:
                            if self.reserve<-SWITCHPHASEHYSTERESIS:
                                self.switch_phases(1)
                        else:
                        # otherwise deactivate charger
                            self.activate_charger(False)
                            self.charge_state=Charge_states.WAITING_FOR_POWER
                    if self.current_power<FINISHEDLIMIT:
                        self.charge_state=Charge_states.FINISHED
                # check if switch to 3 phases is possible
                elif (self.phases_set<3) and ((self.reserve+self.current_power)>self.switch_phase_power):
                    self.set_amp(MIN_AMP)
                    self.switch_phases(3)
                elif (self.reserve>self.step_power+UPHYSTERESIS) and (self.current_power>(self.step_power*(self.amp-1))):
                    self.set_amp(self.amp+1)
            elif self.charge_state==Charge_states.WAITING_FOR_POWER:
                if (self.reserve>self.start_power) or (self.override_amp>0):
                    self.activate_charger(True)
                    self.charge_state=Charge_states.CHARGING
                else:
                    self.activate_charger(False)
            elif self.charge_state==Charge_states.FINISHED:
                if self.current_power>FINISHEDLIMIT:
                    # restart charging
                    self.charge_state=Charge_states.CHARGING

    def __str__(self):
        state=charge_states[self.charge_state] if self.plug_state==Plug_states.PLUGGED_IN else plug_states[self.plug_state]
        return str({
            "reachable":self.reachable,
            "state":state,
            "connected phases":self.connected_phase_count,
            "car_phases":self.car_phase_count,
            "used_phases":self.used_phase_count,
            "amp":self.amp,
            "override":self.override_amp,
            "power":self.charging_power,
            "step_power":self.step_power,
            "start_power":self.start_power,
            "switch_phase_power":self.switch_phase_power,
            "mode":charger_modes[self.charge_mode],
            "alw":self.charger_activated,
            "reserve":self.reserve
        })+"\n"
        """
            "voltage":self.voltage,
            "caps":self.capabilities,
        """


# -*- coding: utf-8 -*-
# https://github.com/latefyr/kicadcreo.git
# MIT license
#
# Parse Creo Schematic cable file and take harness numbers and
# wire/cable lengths back to Kicad schematic.
#
# Do not overwrite the original Schematic.
#
# Copyright (C) LasseFyr 2019.
#
# This has been tested only with Creo 4.0 070
#
"""
    @package
    Generate a net list file.

    Command line:
    Run from Kicad eeschema with default parameters "%I" "%O"

	Changes:
	2023.05.01	Kicad 7.0.2 hierarchical refdes issue patch. Not tested to work with all combinations.
	2022.03.01	Previous update broke V5 operation. Fixed.
	2022.01.01	added preliminary support for KicadV6
"""

from __future__ import print_function
from xml.dom import minidom
import sys
import sch
import glob
import os
import datetime
import shutil
import math
#import sexpdata

class xmlReadCreo:
	def __init__(self):
		self.__infoString = ""
		self.__errorString = ""
		self.__warningString = ""
		self.refDesVals = []
		self.harnessNum = []
		self.wireLength = []
		self.sheets = []
		self.alreadyProsessed = []
		self.prosessedSheets = []
		self.kiCadSch = object()

#-----------------------------------------------------------------------------------------
# Create backup files of the schematic first
#
#-----------------------------------------------------------------------------------------
	def backUpFile( self, fileToBackup ):
		self.fileToProcess = fileToBackup
		self.fileFirstBackup = fileToBackup+".bak"
		self.fileSecondBackup = fileToBackup+".bak2"
		self.returnVal = False

		if os.path.exists( self.fileFirstBackup ):
			shutil.move( self.fileFirstBackup, self.fileSecondBackup)
			self.writeInfoStr("Moved first backup to second backup "+ self.fileSecondBackup + "\n")
			#print( "Moved first backup to second backup "+ self.fileSecondBackup, file=sys.stdout )

		if ( os.path.exists( self.fileToProcess )):
			try:
				os.rename( self.fileToProcess, self.fileFirstBackup )
				self.returnVal = True
			except OSError as error:
				self.writeErrorStr(" Could not create Backupfile: " + self.fileFirstBackup + "\n")
		else:
			self.writeInfoStr( " File " + self.fileToProcess + " does not exist!\n" )

		return self.returnVal

#-----------------------------------------------------------------------------------------
# Write Kicad Schematic Sheet Data
#
#-----------------------------------------------------------------------------------------
	def writeKicadSheet( self, sheetName ):
		for component in sheetName.components:
			for name, value in component.labels.items():
				if value[:1]=="W" or value[:3]=="CBL":
					refDes=value
					for field in component.fields:
						for key in field.keys():
							# Get the component field "Length" and modify
							if field[key] == "\"Length\"":
								thisIsTheLengthParam = key
								try:
									myindex = self.refDesVals.index(refDes)
								except ValueError:
									self.writeErrorStr( "Refdes \""+refDes+"\" does not exist! Not routed yet?\n" )
									continue
								roundedIntLen = math.ceil(float(self.wireLength[myindex]))
								roundedWireLen = str(roundedIntLen).split('.')[0] 				# Round up and no decimal places
								self.writeInfoStr("Name: " + "{0:<6}".format(refDes) + " Harness Name: " + "{0:<15}".format(self.harnessNum[myindex]) + " lenght: " +roundedWireLen + "\n")
								field['ref'] = "\""+roundedWireLen+"mm\""
							if field[key] == "\"Harness_name\"":
								thisIsTheHarnName = key
								try:
									myindex = self.refDesVals.index(refDes)
								except ValueError:
									self.writeErrorStr( "Refdes \""+refDes+"\" does not exist! Not routed yet?\n" )
									continue
								harnessName = self.harnessNum[myindex]
								field['ref'] = "\""+harnessName+"\""

#		print( self.refDesVals )
#		print( self.wireLength )
#		print( self.harnessNum )

#-----------------------------------------------------------------------------------------
# Find the Last refdes from the symbol -> instances-record
# Kicad has an uninvestigated way of storing the visible RefDes-values. This change was
# added to Kicad 7.0.2. Without understanding why I just read the last refdes available...
# In current tests the the recursion count has been 9. Might get bigger
# with deeper hierarchical designs.
#-----------------------------------------------------------------------------------------
#	recursiveCtr = 0
	lastRefDes = ""
	def find_RefDes( self, listItem ):
		from sexpdata import Symbol, car, cdr
		#self.recursiveCtr+=1
		for i, j in  enumerate(listItem):
			if ( not hasattr(j, "__getitem__") ):
				return
			elif ( isinstance( car(j), Symbol ) and ( car(j) != Symbol("reference")) ):
				if( hasattr(j, "__getitem__") ):
					self.find_RefDes( j )
			elif( isinstance( car(j), Symbol) and ( car(j)== Symbol("reference")) ):
				self.lastRefDes = cdr(j)[0]

#-----------------------------------------------------------------------------------------
# Write Kicad V6 Schematic Sheet Data
#
#-----------------------------------------------------------------------------------------
	def writeKicadSch_v6( self ):
		from sexpdata import Symbol, car, cdr
		for i, x in enumerate(self.kiCadSch):
			if ( car(x) == Symbol('symbol') ):
				refDes = ""
				for j, y in enumerate(x):
				#---------------------------------------------------
				# Check if this item is a cable or a wire. If not then continue
				#---------------------------------------------------
					if ( (car(y) == Symbol('property')) and  ( cdr(y)[0]== "Reference" )):
						if( (cdr(y)[1][:1] == 'W') or (cdr(y)[1][:3]=="CBL")):
							refDes = cdr(y)[1]
							# Find instance reference designator
							for d, z in  enumerate(x):
								if ( car(z) == Symbol('instances') ):
									#self.recursiveCtr=0
									self.lastRefDes = ""
									self.find_RefDes( z )
									#print( "FINAL REFDES = "+self.lastRefDes)
									#print( "recursionCount = "+ str(self.recursiveCtr))
									if(self.lastRefDes):
										refDes = self.lastRefDes
						else:
							continue

				#---------------------------------------------------
				# Process the lengths and the Part Numbers
				#---------------------------------------------------
				# Update the Harness Name String if it exists
					if ( car(y) == Symbol('property') ):
						if( cdr(y)[0].lower() == "harness_name" ):		#note - lower case
							try:
								myindex = self.refDesVals.index(refDes)
							except ValueError:
								self.writeErrorStr( "Refdes \""+refDes+"\" does not exist! Not routed yet?\n" )
								continue
							harnessName = self.harnessNum[myindex]
							y[2] = harnessName
					#---------------------------------------------------
					# Update the Harness Length String if it exists
						if( cdr(y)[0].lower() == "length" ):
							try:
								myindex = self.refDesVals.index(refDes)
							except ValueError:
								self.writeErrorStr( "Refdes \""+refDes+"\" does not exist! Not routed yet?\n" )
								continue
							roundedIntLen = math.ceil(float(self.wireLength[myindex]))
							roundedWireLen = str(roundedIntLen).split('.')[0] 				# Round up and no decimal places
							self.writeInfoStr( "Name: " + "{0:<6}".format(refDes) + " Harness Name: " + "{0:<15}".format(self.harnessNum[myindex]) + " lenght: " +roundedWireLen + "\n" )
							y[2] = (roundedWireLen+"mm")

#-----------------------------------------------------------------------------------------
# Read data from Creo xml and store the read lengths, part numbers, and refdes values.
#
#-----------------------------------------------------------------------------------------
	def readCreoPartNumsAndLengths( self, fileName ):
		"""
		This function Reads the wirenames (creo part names) and their lengths.

		Args:
			arg1: Original design name

		Note:
			cables.inf file is used if possible. I now create cables.inf with mapkey
			and read the latest version from the work directory. cables.inf must not be
			older than 1 hour.

		Returns:
			True if succesful
		"""

		file_path = "C:\PTC\work9\cables.inf"  # Replace with the actual path to your text file
		readCblName = ""
		harnessName = ""

		self.refDesVals = []
		self.harnessNum = []
		self.wireLength = []

		self.writeInfoStr( "Creo Back Annotation - Lengths and Harness Names\n" )
		self.writeInfoStr( "------------------------------------------------\n" )

		files = glob.glob( file_path + '.*' )
		sorted_files = sorted(files, key=lambda x: os.path.splitext(x)[1], reverse=True )

		# Test whether the cables.inf.x file exists and is not older than one hour
		# Cables.Inf works also for flat cables. I could not get the length for the ribbon
		# cable when exporting the creo schematic xml.
		if( (sorted_files) and self.is_file_newer_than_one_hour( sorted_files[0] ) ):
			self.writeInfoStr( "Using "+ sorted_files[0] + " for back-annotation\n" )
			with open(sorted_files[0], "r") as file:
				for line in file:
					# Process each line here
					thisLine = line.strip()
					if(thisLine.startswith("HARNESS NAME:")):
						tokens = thisLine.split(":")
						#print("Harness Name = "+tokens[1])
						harnessName = tokens[1]
						continue

					if( thisLine.startswith("W") or thisLine.startswith("CBL") ):
						tokens = thisLine.split()
						if(readCblName == tokens[0].split(":",1)[0]):
							#print("Already read cbl")
							continue

						readCblName =  tokens[0]
						cblLength = tokens[2]

						self.harnessNum.append( harnessName )
						self.refDesVals.append( readCblName )
						self.wireLength.append( cblLength )
		# else continue with the old method of reading _creoin.xml from the current directory

		else:
			self.creoSchXmlName = os.path.splitext(fileName)[0] +"_creoin.xml"
			self.writeInfoStr( "Using "+ self.creoSchXmlName + " for back-annotation\n" )

			if( os.path.isfile(self.creoSchXmlName) ):
				self.writeInfoStr( "Creo Schematic Xml-file OK: " + self.creoSchXmlName + "\n" )
			else:
				self.writeErrorStr( "Creo Schematic Inputfile NOT FOUND: " + self.creoSchXmlName + "\n" )
				self.writeInfoStr( "NOTE:You need to export Creo Schematic xml file with name: " + self.creoSchXmlName + "\n" )
				self.writeInfoStr( "(Cabling -> Logical Data -> Export -> Creo Schematic)\n" )
				return False

			creoXml = minidom.parse( self.creoSchXmlName )
			connections = creoXml.getElementsByTagName("CONNECTION")

			for connection in connections:
				readCblName = connection.getAttribute("name")
				type = connection.getAttribute("type")
				varName = ""
				harnessName = ""
				if readCblName[:1] =="W" or type == "ASSEMBLY":
					self.refDesVals.append(readCblName)
					parameters = connection.getElementsByTagName('PARAMETER')
					for param in parameters:
						varName = param.getAttribute('name')
						harnessName = param.getAttribute('value')
						if( varName == "LENGTH" ):
							self.wireLength.append(harnessName)
						if( varName == "HARNESS_NAME"):
							self.harnessNum.append(harnessName)

		return True

	def is_file_newer_than_one_hour( self, file_path ):
		"""
		This function Checks whether the cables.inf file was generated within the past hour.
		If not then return false.

		Args:
			arg1: Path to the file to check

		Returns:
			The result true if file is generated within the past hour.
			The result is False if file doesn't exist or was generated over an hour ago.
		"""
		if not os.path.isfile(file_path):
			return False  # File doesn't exist

		file_stat = os.stat(file_path)
		modified_time = datetime.datetime.fromtimestamp(file_stat.st_mtime)
		current_time = datetime.datetime.now()

		time_difference = current_time - modified_time
		time_difference_in_hours = time_difference.total_seconds() / 3600

		return time_difference_in_hours < 1

#-----------------------------------------------------------------------------------------
# Read existing sheetnames in the design
#
#-----------------------------------------------------------------------------------------
	def readCreoSheetNames( self, fileName ):
		self.creoSchXmlName = fileName +".xml"

		creoXml = minidom.parse( self.creoSchXmlName )
		sheetNames = creoXml.getElementsByTagName("sheet")

		self.sheets = []
		for mysheet in sheetNames:
			x = mysheet.getElementsByTagName("source")[0]
			y =x.childNodes[0];
			self.sheets.append( y.nodeValue )

		del creoXml

#-----------------------------------------------------------------------------------------
# Read data from Creo Schematic file (Created with Creo)
# and write the cable lengths and part numbers to Kicad Schematic file
#
#
#-----------------------------------------------------------------------------------------
	def backAnnotate( self, fileName ):
		self.creoSchXmlName = fileName +"_creoin.xml"
		self.kiCadOutputName = fileName +"_creo.sch"
		self.kiCadOriginalFile = fileName +".sch"

		self.writeInfoStr( "Creo Back Annotation - Lengths and Harness Names\n" )
		self.writeInfoStr( "------------------------------------------------\n" )

		if( os.path.isfile(self.creoSchXmlName) ):
			self.writeInfoStr( "Creo Schematic Inputfile OK: " + self.creoSchXmlName + "\n" )
		else:
			self.writeErrorStr( "Creo Schematic Inputfile NOT FOUND: " + self.creoSchXmlName + "\n" )
			self.writeInfoStr( "NOTE:You need to export Creo Schematic xml file with name: " + self.creoSchXmlName + "\n" )
			self.writeInfoStr( "(Cabling -> Logical Data -> Export -> Creo Schematic)\n" )
			return False

		if( os.path.isfile(self.kiCadOriginalFile) ):
			self.writeInfoStr( "Kicad Schematic Inputfile OK: " + self.kiCadOriginalFile + "\n" )
		else:
			self.writeErrorStr( "Kicad Schematic Inputfile NOT FOUND: " + self.kiCadOriginalFile + "\n" )
			return False

		creoXml = minidom.parse(self.creoSchXmlName)
		connections = creoXml.getElementsByTagName("CONNECTION")
		self.refDesVals = []
		self.harnessNum = []
		self.wireLength = []
		for connection in connections:
			wireName = connection.getAttribute("name")
			type = connection.getAttribute("type")
			varName = ""
			varValue = ""
			if wireName[:1] =="W" or type == "ASSEMBLY":
				self.refDesVals.append(wireName)
				parameters = connection.getElementsByTagName('PARAMETER')
				for param in parameters:
					varName = param.getAttribute('name')
					varValue = param.getAttribute('value')
					if( varName == "LENGTH" ):
						self.wireLength.append(varValue)
					if( varName == "HARNESS_NAME"):
						self.harnessNum.append(varValue)

		# Put lenghts to Kicad Schematic
		# Do not overwrite the original file
		self.writeInfoStr( "\nProcessing wires and cables:\n" )
		self.writeInfoStr( "----------------------------\n" )
		self.writeInfoStr( str(self.refDesVals) + "\n\n" )

		myvariable = self.backUpFile( self.kiCadOriginalFile )
		kiCadSch = sch.Schematic( self.kiCadOriginalFile+".bak")
		self.writeKicadSheet( kiCadSch )
		kiCadSch.save( self.kiCadOriginalFile )

		# Process subsheets
		self.prosessedSheets = []
		for sheet in kiCadSch.sheets:
			for field in sheet.fields:
				if( field['id'] =="F1" ):
					subSheetFilename = field['value'].replace('"', "")

					if( os.path.exists( subSheetFilename ) ):
						if( subSheetFilename in self.prosessedSheets ):
							self.writeWarningStr( "Child .sch already processed: " + subSheetFilename + "!\n" )
							self.writeWarningStr( "NOTE: Reusing schematic shows the same wire\n" )
							self.writeWarningStr( "lengths and partnames in all instances of the file.\n" )
							self.writeWarningStr( "Copy the .sch to a new name if you need\n" )
							self.writeWarningStr( "to have unique names and wire lengths!\n" )
						else:
							self.writeInfoStr( "\nProcessing child sheet " + subSheetFilename + "\n" )
							myvariable = self.backUpFile( subSheetFilename )
							kicadChildSheet = sch.Schematic(subSheetFilename+".bak")
							self.writeKicadSheet( kicadChildSheet )
							kicadChildSheet.save( subSheetFilename )
							self.prosessedSheets.append(subSheetFilename)
					else:
						self.writeErrorStr( "File does not exist!: " + subSheetFilename + "\n" )
		return True

#-----------------------------------------------------------------------------------------
# Read data from Creo Schematic file (Created with Creo)
# and write the cable lengths and part numbers to Kicad V6 Schematic file
#
#
#-----------------------------------------------------------------------------------------
	def backAnnotateV6( self, fileName ):
		from sexpdata import loads, dumps

		# Put lenghts to Kicad Schematic
		# Do not overwrite the original file
		self.writeInfoStr( "\nProcessing wires and cables:\n" )
		self.writeInfoStr( "----------------------------\n" )
		self.writeInfoStr( str(self.refDesVals) + "\n\n" )

		self.prosessedSheets = []
		currentDirectory = os.path.dirname( fileName )
		for myfilename in self.sheets:
			#------------------------------------------------------------------
			# Error Cheking
			myfilename = os.path.join( currentDirectory, myfilename )
			if( os.path.exists( myfilename ) ):
				if( myfilename in self.prosessedSheets ):
					self.writeWarningStr( "Child .sch already processed: " + myfilename + "!\n" )
					self.writeWarningStr( "NOTE: Reusing schematic shows the same wire\n" )
					self.writeWarningStr( "lengths and partnames in all instances of the file.\n" )
					self.writeWarningStr( "Copy the .sch to a new name if you need\n" )
					self.writeWarningStr( "to have unique names and wire lengths!\n" )
					continue
				elif ( self.backUpFile( myfilename ) ):
					self.writeInfoStr( "\nBacking up " + myfilename + " OK\n" )
				else:
					self.writeErrorStr( "\nBacking up " + myfilename + " FAILED\n" )
					continue
			#------------------------------------------------------------------
			# Process sheet for partnumbers and lengths
				try:
					f = open((myfilename+".bak"),"r")
					self.line = f.read()
				except:
					self.writeErrorStr( "Could not read file: " + myfilename +".bak !\n" )
					continue
				finally:
					self.kiCadSch = loads( self.line )
					self.writeKicadSch_v6( )
					f.close( )
				try:
					f = open( myfilename, "w" )
					f.write(dumps( self.kiCadSch ))
				except:
					self.writeErrorStr( "Could not write file: " + myfilename + "!\n" )
				finally:
					self.writeInfoStr( "Updated file: " + myfilename + " succesfully.\n" )
					f.close( )
				self.prosessedSheets.append( myfilename )

			else:
				self.writeErrorStr( "File does not exist!: " + myfilename + "\n" )
		return True

#-----------------------------------------------------------------------------------------
# Read the correct filename from the .xml file
#
#-----------------------------------------------------------------------------------------
	def getSourceFilenameFromXml( self, xmlFileName ):
		tmpObject = minidom.parse(xmlFileName)
		currentFileName = tmpObject.getElementsByTagName("source")
		del tmpObject
		return( currentFileName[0].firstChild.nodeValue )

#-----------------------------------------------------------------------------------------
# String Logger functions
#
# These fuctions log the strings and outputs data to stdout and stderr
#
#-----------------------------------------------------------------------------------------
	def writeInfoStr( self, iStr ):
		self.__infoString += iStr

	def getInfoStr( self ):
		return self.__infoString

	def writeErrorStr( self, eStr ):
		self.__errorString += eStr

	def getErrorStr( self ):
		if self.__errorString == "":
			self.__errorString="No Errors!"
		return self.__errorString

	def clearErrorStr( self ):
		self.__errorString=""

	def writeWarningStr( self, wStr ):
		self.__warningString += wStr

	def getWarningStr( self ):
		if self.__warningString == "":
			self.__warningString="No Warnigns!"
		return self.__warningString

	def clearWarningStr( self ):
		self.__warningString=""

#-----------------------------------------------------------------------------------------
# If this is called Independently
#
# Create instance and call with parameters
#
#-----------------------------------------------------------------------------------------
if __name__ == '__main__':
	fileToProcess = sys.argv[1]    				# unpack 2 command line arguments

	# Split the file extension away if it exists. This comes from command line
	# fileNameToProcess = os.path.splitext(fileToProcess)[0]

	# Initialize the function instance
	creoCablelengths = xmlReadCreo( )

	# Get the filename from the xml-File
	tempFileName = creoCablelengths.getSourceFilenameFromXml( fileToProcess )
	fileNameToProcess = os.path.splitext(tempFileName)[0]
	fileExtension = os.path.splitext(tempFileName)[1]

	if( fileExtension == ".sch" ):
		creoCablelengths.writeInfoStr( "\nProsess Kicad V5 file.\n")
		if( creoCablelengths.readCreoPartNumsAndLengths( fileToProcess ) ):
			creoCablelengths.readCreoSheetNames( fileNameToProcess )
			creoCablelengths.backAnnotate( fileNameToProcess )
	elif( fileExtension == ".kicad_sch" ):
		creoCablelengths.writeInfoStr( "\nProsess Kicad V6 file.\n")
		if( creoCablelengths.readCreoPartNumsAndLengths( fileToProcess ) ):
			creoCablelengths.readCreoSheetNames( fileNameToProcess )
			creoCablelengths.backAnnotateV6( fileNameToProcess )
	else:
		creoCablelengths.writeInfoStr( "\nNo Valid Filename found " + fileToProcess + "\n" )

	print("Info", file=sys.stdout)
	print( creoCablelengths.getInfoStr(), file=sys.stdout )

	print("Warnigns", file=sys.stdout)
	print( creoCablelengths.getWarningStr(), file=sys.stdout )

	print("Errors", file=sys.stderr)
	print( creoCablelengths.getErrorStr(), file=sys.stderr )
	print( "Please Reload the Kicad Schematic if Operation was Successful", file=sys.stdout )

{'Symbol': 'sexpdata.Symbol', 'car': 'sexpdata.car', 'cdr': 'sexpdata.cdr', 'loads': 'sexpdata.loads', 'dumps': 'sexpdata.dumps'}


from django.shortcuts import render, redirect
from .models import Show
from django.contrib import messages

def shows(request):
    context = {
        "shows":Show.objects.all()
    }
    return render(request, "index.html", context)

def index(request):
    return redirect("/shows")

def new_show(request):
    return render(request, "new_show.html")

def add_new_show(request):
    errors = Show.objects.basic_validator(request.POST)
    if len(errors) > 0:
        for key, value in errors.items():
            messages.error(request, value)
        return redirect(f"/shows/new")
    else:
        new_show = Show.objects.create(title = request.POST['title'],
            description = request.POST['description'],
            network = request.POST['network'],
            release_date = request.POST['release_date']
            )
        return redirect(f"/shows/{new_show.id}")

def show(request, show_id):
    context = {
        "show":Show.objects.get(id = show_id)
    }
    return render(request, "show.html", context)

def edit_show(request, show_id):
    context = {
        "show":Show.objects.get(id = show_id)
    }
    return render(request, "edit_show.html", context)

def update_show(request, show_id):
    errors = Show.objects.basic_validator(request.POST)
    if len(errors) > 0:
        for key, value in errors.items():
            messages.error(request, value)
        return redirect(f"/shows/{show_id}/edit")
    else:
        new_show = Show.objects.get(id = show_id)
        new_show.title = request.POST['title']
        new_show.description = request.POST['description']
        new_show.network = request.POST['network']
        new_show.release_date = request.POST['release_date']
        new_show.save()
        return redirect(f"/shows/{new_show.id}")

def delete_show(request, show_id):
    show = Show.objects.get(id = show_id)
    show.delete()
    return redirect("/shows")


#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
import requests
import os
import base64

#导入thrift的python模块
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
#导入编译生成的hbase 模块
from myThrift.hbase import THBaseService
from myThrift.hbase.ttypes import *

#response =requests.get('http://duanziwang.com/')
#data = response.text
#result = re.findall('(.*?)',data)

def get_page(url):
    try:
        headers = {'User-Agent':'Mozilla/5.0(Windows NT 10.0;Win64; x64) APPleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.75 Safari/537.36'}
        response = requests.get(url, timeout=10)
        data = response.text
        result = re.findall('(.*?)',data)
        #result = re.findall('(.*?)',data)
        #result = re.findall('(.*?)',data)
        return  result
    except:
        return ""
    #/html/body/section/div/div/main
    #//*[@id="1844"]/div[2]
    #//*[@id="1847"]/div[1]/h1/a
    #//*[@id="1845"]/div[1]/h1/a
    #//*[@id="1847"]/div[2]/p/text()
    #//*[@id="1843"]/footer/div/a[2]
def out_write(result):
    with open('areduanzi4.txt','a',encoding='utf-8')as fw:
        for i in result:
            fw.write('\n'+i)
            fw.flush()

def put(url,result):
    #创建Socket连接，到s201:9090
    transport = TSocket.TSocket('192.168.43.155', 9090)
    transport = TTransport.TBufferedTransport(transport)
    protocol = TBinaryProtocol.TBinaryProtocol(transport)
    client = THBaseService.Client(protocol)
    #打开传输端口
    transport.open()
    #对url进行base64编码，形成bytes,作为rowkey
    urlBase64Bytes = url.encode("utf-8")

    #put操作
    table = b'ns01:t4'
    rowkey = urlBase64Bytes

    for i in result:
        #v1 = TColumnValue(rb'f1', b'duanzi',i)
        print(i)
        print("-"*30)
        bytes = i.encode('utf-8')
        tcls = TColumnValue(b'f1', b'content', bytes)
        vals = [tcls]
        put = TPut(rowkey, vals)
        client.put(table, put)
    print("okkkk!!")
    transport.close()

def get(url,d,m):
    #创建Socket连接，到s201:9090
    transport = TSocket.TSocket('192.168.43.155', 9090)
    transport = TTransport.TBufferedTransport(transport)
    protocol = TBinaryProtocol.TBinaryProtocol(transport)
    client = THBaseService.Client(protocol)
    #打开传输端口
    transport.open()
    #对url进行base64编码，形成bytes,作为rowkey
    urlBase64Bytes = url.encode("utf-8")
    #get
    table = b'ns01:t4'
    rowkey=urlBase64Bytes
    col_id = TColumn(b"f1",b'content')
    cols = [col_id]
    get = TGet(rowkey,cols)
    res = client.get(table,get)
    print(bytes.decode(res.columnValues[0].qualifier))
    print(bytes.decode(res.columnValues[0].family))
    print(res.columnValues[0].timestamp)
    print(bytes.decode(res.columnValues[0].value))
    transport.close()
    print("Get data okokok")

def scan():
    #创建Socket连接，到s201:9090
    transport = TSocket.TSocket('192.168.43.155', 9090)
    transport = TTransport.TBufferedTransport(transport)
    protocol = TBinaryProtocol.TBinaryProtocol(transport)
    client = THBaseService.Client(protocol)
    #打开传输端口
    transport.open()

    # scan 全表扫描操作
    table = b'ns01:t4'

    # startRow = b'34,13520401111,20180114152647,0,13269364444,406'
    # stopRow = b'90,15032295555,20180922165903,0,15778421111,298'
    # dur = TColumn(b"f1", b"callDuration")
    # time = TColumn(b"f1", b"callTime")
    # caller = TColumn(b"f1", b"caller")
    # callee = TColumn(b"f1", b"callee")
    # cols = [dur, time,caller,callee]
    #caller = TColumn(b"f1", b"name")

    callee = TColumn(b"f1", b'content')
    cols = [callee]

    scan = TScan(columns=cols,startRow="1".encode(),stopRow="10".encode(),maxVersions=10)
    r = client.getScannerResults(table,scan,10);
    print(len(r))
    for x in r:
        print("============")
        print(bytes.decode(x.columnValues[0].qualifier))
        #print(bytes.decode(x.columnValues[0].family))
      #  print(x.columnValues[0].timestamp)
        print(bytes.decode(x.columnValues[0].value))

        print(x.columnValues[0].value)

    transport.close()
    print("Scan data okokok")

def out_print(data):
    for i in data:
        print(i)

if __name__ == '__main__':
    url = "http://duanziwang.com/"
    #u =get_page(url) #爬取网页
    #out_write(u)#写到文档
   # put(url,u)

#    get(url)
   # out_print(u)#打印到屏幕
    scan()


import requests
from bs4 import BeautifulSoup

products_to_track = [

    {
        "URL":"https://www.nike.com/in/t/air-jordan-1-mid-se-shoes-CQ6f9G/DV1308-104",
        "Price":"12295.00",
        "Target_price":13000.00
    },
    {
        "URL":"https://www.nike.com/in/t/air-jordan-1-mid-shoes-SQf7DM/DQ8426-014",
        "Price":"11495.00",
        "Target_price":10000.00
    },
    {
        "URL":"https://www.nike.com/in/t/air-force-1-07-shoes-WrLlWX/CW2288-111",
        "Price":"7495.00",
        "Target_price":7000.00
    },
    {
        "URL":"https://www.nike.com/in/t/court-vision-low-next-nature-shoes-N2fFHb/DH2987-100",
        "Price":"4995.00",
        "Target_price":4500.00
    },
    {
        "URL":"https://www.nike.com/in/t/nikecourt-royale-2-next-nature-shoes-RRcr20/DH3160-001",
        "Price":"3995.00",
        "Target_price":4000.00
    }
]

def give_product_name(URL):
    headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
    }
    page = requests.get(URL, headers=headers)
    soup = BeautifulSoup(page.content, 'html.parser')
    product_name = soup.find(id="pdp_product_title")
    return product_name.getText()

result_file = open('my_result_file.txt','w')

try:
    for every_product in products_to_track:
        Product_name = give_product_name(every_product.get("URL"))
        print(Product_name + "  -  " + every_product.get("Price"))

        if float(every_product.get("Price"))<=every_product.get("Target_price"):
            print("Less than target price")
            result_file.write(Product_name+' - '+'Less than target price.\n'+'Previous price-'+ every_product.get("Price")+'\n')
        else:
            print("Still at current price")

finally:
    result_file.close()


# encoding=utf-8
__author__ = 'YiTao'

import os
import sys
import logging
from datetime import *

class LogHelper:
    def __init__(self):
        self.log = self.getlog()

    def info(self, message):
        self.log.info(message)

    def error(self, message):
        self.log.error(message)

    def getlog(self):
        logger = logging.getLogger("LogHelper")
        formatter = logging.Formatter('%(name)-12s %(asctime)s %(levelname)-8s %(message)s', '%a, %d %b %Y %H:%M:%S', )
        logpath = self.getcurrpath() + "/log"
        if not os.path.exists(logpath):
            os.mkdir(logpath)
        file_handler = logging.FileHandler(logpath + "/%s.log" % date.today())
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)
        logger.setLevel(logging.DEBUG)
        return logger

    def getcurrpath(self):
        #获取脚本路径
        path = sys.path[0]
        ##判断为脚本文件还是py2exe编译后的文件，如果是脚本文件，则返回的是脚本的目录，如果是py2exe编译后的文件，则返回的是编译后的文件路径
        if os.path.isdir(path):
            return path
        elif os.path.isfile(path):
            return os.path.dirname(path)


from datetime import datetime

from bson import ObjectId

import ext_requests.mongodb_client as db

def mongo_upsert_cluster(cluster_ip, message):
    db.app.logger.info("MONGODB - upserting cluster...")
    clusters = db.mongo_clusters.db.clusters
    cluster_info = message['cluster_info']
    cluster_name = message['cluster_name']
    cluster_location = message['cluster_location']
    cluster_port = message['manager_port']
    result_obj = clusters.update_one({'cluster_name': cluster_name},
                                     {'$set': {'ip': cluster_ip, 'clusterinfo': cluster_info, 'port': cluster_port,
                                               'cluster_location': cluster_location}},
                                     upsert=True)

    cluster_obj = clusters.find_one({'cluster_name': cluster_name})

    db.app.logger.info("MONGODB - cluster_id: {0}".format(cluster_obj['_id']))
    return cluster_obj['_id']

def mongo_find_cluster_by_id(cluster_id):
    return db.mongo_clusters.db.clusters.find_one(ObjectId(cluster_id))

def mongo_find_cluster_by_ip(cluster_ip):
    return db.mongo_clusters.db.clusters.find_one({'ip': cluster_ip})

def mongo_get_all_clusters():
    return db.mongo_clusters.db.clusters.find()

def mongo_find_one_cluster():
    """Finds first cluster occurrence"""
    return db.mongo_clusters.db.clusters.find_one()

def mongo_find_all_active_clusters():
    db.app.logger.info('Finding the active cluster orchestrators...')
    now_timestamp = datetime.now().timestamp()
    return db.mongo_clusters.db.clusters.find(
        {'last_modified_timestamp': {'$gt': now_timestamp - db.CLUSTERS_FRESHNESS_INTERVAL}})

def mongo_find_cluster_by_id_and_incr_node(c_id):
    return db.mongo_clusters.db.clusters.update_one({'_id': c_id}, {'$inc': {'nodes': 1}}, upsert=True)

def mongo_find_cluster_by_id_and_set_number_of_nodes(c_id, number_of_nodes):
    return db.mongo_clusters.db.clusters.update_one({'_id': c_id}, {'$inc': {'nodes': number_of_nodes}}, upsert=True)

def mongo_find_cluster_by_id_and_decr_node(c_id):
    return db.mongo_clusters.db.clusters.update_one({'_id': c_id}, {'$inc': {'nodes': -1}}, upsert=True)

def mongo_find_cluster_by_location(location):
    try:
        return db.mongo_clusters.db.clusters.find_one({'cluster_location': location})
    except Exception as e:
        return "Error"

def mongo_update_cluster_information(cluster_id, data):
    """Save aggregated Cluster Information"""

    datetime_now = datetime.now()
    datetime_now_timestamp = datetime.timestamp(datetime_now)

    cpu_percent = data.get('cpu_percent')
    cpu_cores = data.get('cpu_cores')
    memory_percent = data.get('memory_percent')
    memory_in_mb = data.get('cumulative_memory_in_mb')
    nodes = data.get('number_of_nodes')
    gpu_cores = data.get('gpu_cores')
    gpu_percent = data.get('gpu_percent')
    # technology = data.get('technology')
    virtualization = data.get('virtualization')
    more = data.get('more')
    worker_groups = data.get('worker_groups')
    cpu_update = {'value': cpu_percent, 'timestamp': datetime_now_timestamp}
    memory_update = {'value': memory_percent, 'timestamp': datetime_now_timestamp}

    db.mongo_clusters.db.clusters.find_one_and_update(
        {'_id': ObjectId(cluster_id)},
        {
            '$push': {
                "cpu_history": {'$each': [cpu_update], '$slice': -100},
                "memory_history": {'$each': [memory_update], '$slice': -100}
            },
            '$set': {'aggregated_cpu_percent': cpu_percent, 'total_cpu_cores': cpu_cores,
                  'total_gpu_cores': gpu_cores, 'total_gpu_percent': gpu_percent,
                  'aggregated_memory_percent': memory_percent, 'memory_in_mb': memory_in_mb,
                  'active_nodes': nodes, 'virtualization': virtualization, 'more': more,
                  'last_modified': datetime_now, 'last_modified_timestamp': datetime_now_timestamp,
                  'worker_groups': worker_groups}},
        upsert=True)


import datetime

from django.db import models
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.views.decorators.cache import cache_page

from bios.models import Bio
from competitions.models import Competition
from games.models import Game, GameSource
from goals.models import Goal
from standings.models import Standing
from stats.models import Stat, CareerStat
from teams.models import Team

from collections import defaultdict, Counter
import json

def homepage(request):

    try:
        mls = Competition.objects.get(slug='major-league-soccer')
    except:
        mls = None

    context = {
        'mls': mls,
        }

    return render_to_response("homepage.html",
                              context,
                              context_instance=RequestContext(request))

@cache_page(60 * 60 * 12)
def homepage_old(request):
    """
    The site homepage. Currently badly underperfoming.
    """

    # Homepage fixes.
    # Shrink the size of the On This Day Box, move lower.
    # Add Standings.
    # Add tab for games from different competitions.
    # Add News
    # Add detailed links to different parts of the website.

    # What are the cool things you can get on the site?
    # Player +/-
    # Manager details
    # Career stats
    # Stats across competitions
    # Breadcrumbs?

    today = datetime.date.today()

    game_leaders = CareerStat.objects.exclude(games_played=None).order_by('-games_played')[:10]
    goal_leaders = CareerStat.objects.exclude(goals=None).order_by('-goals')[:10]

    recent_games = Game.objects.exclude(date=None).filter(date__lt=today).exclude(team1_result='').order_by('-date')[:10]

    goals = Goal.objects.count()

    try:
        mls_game = Game.objects.filter(competition__slug='major-league-soccer').order_by('date')[0]
    except:
        mls_game = None

    try:
        oc_game = Game.objects.get(competition__slug='us-open-cup', season__name='1924', round='f')
    except:
        oc_game = None

    context = {
        'today': today,
        'born': Bio.objects.born_on(today.month, today.day),
        'games': recent_games,
        'standings': Standing.objects.filter(season__competition__slug='major-league-soccer').count(),
        'game_leaders': game_leaders,
        'goal_leaders': goal_leaders,
        'game_count': Game.objects.count(),
        'bio_count': Bio.objects.count(),
        'team_count': Team.objects.count(),
        'competition_count': Competition.objects.count(),

        'mls_game': mls_game,
        'oc_game': oc_game,

        }
    return render_to_response("homepage.html",
                              context,
                              context_instance=RequestContext(request))

def bad_games(request):

    context = {
        'duplicate_games': Game.objects.duplicate_games(),
        }

    return render_to_response("games/bad.html",
                              context,
                              context_instance=RequestContext(request)
                              )

def games_index(request):
    # Add a paginator.
    # This is probably unnecesary.
    # Consider turning into a games analysis page.
    # Home/Away advantage, graphs, etc.

    games = Game.objects.order_by("-date").exclude(date=None)
    game_count = games.count()

    by_year = Counter([e.year for e in games.values_list('date', flat=True)])

    #gd = defaultdict(int)
    #ceiling = 8
    #for game in games.exclude(home_team=None).exclude(team1_score=None).exclude(team2_score=None):
    #    gd[(min(game.home_score(), ceiling), min(game.away_score(), ceiling))] += 1

    context = {
        'games': games,
        'game_count': game_count,
        'games_by_year': json.dumps(sorted(by_year.items())),
        'goal_distribution': json.dumps(gd),
        }

    return render_to_response("games/index.html",
                              context,
                              context_instance=RequestContext(request))

    """
    attendance_game_count = 0
    total_attendance = 0

    month_dict = defaultdict(int)
    team_dict = defaultdict(int)
    result_dict = defaultdict(int)

    game_year_dict = defaultdict(int)
    attendance_year_dict = defaultdict(int)

    # Pull this out.
    for date, t1, t2, t1s, t2s, stadium, city, attendance in games.values_list('date', 'team1', 'team2', 'team1_score', 'team2_score', 'stadium', 'city', 'attendance'):
        total_attendance += attendance or 0
        attendance_year_dict[date.year] += attendance or 0
        if attendance is not None:
            attendance_game_count += 1

        game_year_dict[date.year] += 1

        month_dict[date.month] += 1
        team_dict[t1] += 1
        team_dict[t2] += 1
        result = tuple(sorted([t1s, t2s]))
        result_dict[result] += 1
        """

    """{
        'total_attendance': total_attendance,
        'average_attendance': total_attendance / float(attendance_game_count),
        'teams': sorted(team_dict.items(), key=lambda t: -t[1]),
        'results': sorted(result_dict.items(), key=lambda t: t[0]),
        'months': sorted(month_dict.items(), key=lambda t: t[0]),
        'game_years': sorted(game_year_dict.items(), key=lambda t: t[0]),
        'attendance_years': sorted(attendance_year_dict.items(), key=lambda t: t[0]),
        'top_attendance_games': Game.objects.order_by('-attendance')[:20],
        }"""

def game_detail(request, game_id):
    game = get_object_or_404(Game, id=game_id)
    context = {
        'game': game,
        'goals': game.goal_set.order_by('minute'),
        'game_sources': GameSource.objects.filter(game=game),

        }
    return render_to_response("games/detail.html",
                              context,
                              context_instance=RequestContext(request))

def random_game_detail(request):
    import random
    games = Game.objects.count()
    game_id = random.randint(1, games)
    return game_detail(request, game_id)