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

#/***************************************************************************
 #*   Copyright (C) 2014-2022 by DTU
 #*   jca@elektro.dtu.dk
 #*
 #*
 #* The MIT License (MIT)  https://mit-license.org/
 #*
 #* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 #* and associated documentation files (the “Software”), to deal in the Software without restriction,
 #* including without limitation the rights to use, copy, modify, merge, publish, distribute,
 #* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
 #* is furnished to do so, subject to the following conditions:
 #*
 #* The above copyright notice and this permission notice shall be included in all copies
 #* or substantial portions of the Software.
 #*
 #* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 #* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 #* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 #* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 #* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #* THE SOFTWARE. */

import threading
import numpy as np
#import pyqtgraph as pg
import time

class ULineSensor(object):
  # line sensor
  lineValue = [0,0,0,0,0,0,0,0]
  lineValN = [0,0,0,0,0,0,0,0]
  lineMaxWhite = [0,0,0,0,0,0,0,0]
  lineMaxBlack = [0,0,0,0,0,0,0,0]
  lineWhite = False
  lineUse = True
  edgeLeft = 0.0
  edgeRight = 0.0
  edgeLeftValid = False
  edgeRightValid = False
  followLeft = True
  wideSensor = False;
  swapLeftRight = False;
  # crossing
  crossingDetectLimit = 4;
  crossingWhite = False
  crossingBlack = False
  crossingWhiteCnt = 0
  #crossingBlackCnt = 0
  power_high = False
  power_auto = True
  # management
  dataReadLiv = False
  dataReadLivn = False
  dataReadLip = False
  dataReadbw = True
  #
  inUpdate = False
  inEdit = False
  nextDataRequest = 1
  lastDataRequestTime = time.time()
  #
  hasFocus = False
  thisTab = -1
  inTimerUpdate = False

  #
  about_box = None
  # resource lock
  lock = threading.RLock()

  def __init__(self, parent):
    self.parent = parent
    self.main = parent.main
    self.ui = parent.ui

  def setup(self):
    # Edge/line sensor
    self.ui.line_disp_max_value.valueChanged.connect(self.max_value_changed)
    self.ui.ls_use_sensor.clicked.connect(self.setWhiteLine)
    self.ui.ls_calibrate_white.clicked.connect(self.calibrateWhite)
    self.ui.ls_calibrate_black.clicked.connect(self.calibrateBlack)
    self.ui.ls_apply.clicked.connect(self.butApply)
    self.ui.ls_cancel.clicked.connect(self.butCancel)
    self.ui.ls_edit.clicked.connect(self.butEdit)
    pass

  def decode(self, gg):
    used = True
    self.lock.acquire()
    try:
      if gg[0] == "liv":
        # actual data
        self.lineValue[0] = int(gg[1],0)
        self.lineValue[1] = int(gg[2],0)
        self.lineValue[2] = int(gg[3],0)
        self.lineValue[3] = int(gg[4],0)
        self.lineValue[4] = int(gg[5],0)
        self.lineValue[5] = int(gg[6],0)
        self.lineValue[6] = int(gg[7],0)
        self.lineValue[7] = int(gg[8],0)
        pass
        self.dataReadLiv = True
      elif gg[0] == "livn":
        # actual data
        self.lineValN[0] = int(gg[1],0)
        self.lineValN[1] = int(gg[2],0)
        self.lineValN[2] = int(gg[3],0)
        self.lineValN[3] = int(gg[4],0)
        self.lineValN[4] = int(gg[5],0)
        self.lineValN[5] = int(gg[6],0)
        self.lineValN[6] = int(gg[7],0)
        self.lineValN[7] = int(gg[8],0)
        pass
        self.dataReadLivN = True
      elif gg[0] == "liw":
        # white calibration
        self.lineMaxWhite[0] = int(gg[1],0)
        self.lineMaxWhite[1] = int(gg[2],0)
        self.lineMaxWhite[2] = int(gg[3],0)
        self.lineMaxWhite[3] = int(gg[4],0)
        self.lineMaxWhite[4] = int(gg[5],0)
        self.lineMaxWhite[5] = int(gg[6],0)
        self.lineMaxWhite[6] = int(gg[7],0)
        self.lineMaxWhite[7] = int(gg[8],0)
        self.dataReadbw = True
      elif gg[0] == "lib":
        # black calibration
        self.lineMaxBlack[0] = int(gg[1],0)
        self.lineMaxBlack[1] = int(gg[2],0)
        self.lineMaxBlack[2] = int(gg[3],0)
        self.lineMaxBlack[3] = int(gg[4],0)
        self.lineMaxBlack[4] = int(gg[5],0)
        self.lineMaxBlack[5] = int(gg[6],0)
        self.lineMaxBlack[6] = int(gg[7],0)
        self.lineMaxBlack[7] = int(gg[8],0)
        self.dataReadbw = True
      elif gg[0] == "lip":
        # derived data
        self.lineUse = int(gg[1],0)
        self.lineWhite = int(gg[2],0)
        self.edgeLeft = float(gg[3])
        self.edgeLeftValid = int(gg[4],0)
        self.edgeRight = float(gg[5])
        self.edgeRightValid = int(gg[6],0)
        self.followLeft = int(gg[7],0)
        self.crossingWhite = int(gg[8],0)
        #self.crossingBlack = int(gg[9],0) # not used anymore
        self.crossingWhiteCnt = int(gg[10],0)
        #self.crossingBlackCnt = int(gg[11],0) # not used anymore
        self.power_high = int(gg[12],0)
        self.power_auto = int(gg[13],0)
        if (len(gg) > 14):
          self.crossingDetectLimit = float(gg[14])
        if (len(gg) > 15):
          self.wideSensor = int(gg[15])
        if (len(gg) > 16):
          self.swapLeftRight = int(gg[16])
        self.dataReadLip = True
      else:
        used = False
    except:
      print("URegLine: data read error - skipped a " + gg[0] + " length=" + str(len(gg)))
      pass
    self.lock.release()
    return used
  #

  def timerUpdate(self, timerCnt, justConnected):
    self.lock.acquire()
    if self.dataReadbw:
      # calibration settings
      self.dataReadbw = False
      self.ui.ls_max_white_1.setText(str(self.lineMaxWhite[0]))
      self.ui.ls_max_white_2.setText(str(self.lineMaxWhite[1]))
      self.ui.ls_max_white_3.setText(str(self.lineMaxWhite[2]))
      self.ui.ls_max_white_4.setText(str(self.lineMaxWhite[3]))
      self.ui.ls_max_white_5.setText(str(self.lineMaxWhite[4]))
      self.ui.ls_max_white_6.setText(str(self.lineMaxWhite[5]))
      self.ui.ls_max_white_7.setText(str(self.lineMaxWhite[6]))
      self.ui.ls_max_white_8.setText(str(self.lineMaxWhite[7]))
      self.ui.ls_max_black_1.setText(str(self.lineMaxBlack[0]))
      self.ui.ls_max_black_2.setText(str(self.lineMaxBlack[1]))
      self.ui.ls_max_black_3.setText(str(self.lineMaxBlack[2]))
      self.ui.ls_max_black_4.setText(str(self.lineMaxBlack[3]))
      self.ui.ls_max_black_5.setText(str(self.lineMaxBlack[4]))
      self.ui.ls_max_black_6.setText(str(self.lineMaxBlack[5]))
      self.ui.ls_max_black_7.setText(str(self.lineMaxBlack[6]))
      self.ui.ls_max_black_8.setText(str(self.lineMaxBlack[7]))
    if (self.dataReadLip):
      self.ui.ls_left_side.setValue(self.edgeLeft)
      self.ui.ls_right_side.setValue(self.edgeRight)
      # Show editable settings
      if (self.dataReadLip and not self.inEdit):
        self.dataReadLip = False
        self.inUpdate = True
        self.ui.ls_use_sensor.setChecked(self.lineUse)
        self.ui.ls_line_white.setChecked(self.lineWhite)
        #self.ui.ls_left_side_valid.setChecked(self.edgeLeftValid)
        #self.ui.ls_right_side_valid.setChecked(self.edgeRightValid)
        ev = 100 - (self.edgeLeft + 2.5) * 20.0
        if (ev < 0):
          ev = 0
        elif ev >100:
          ev = 100
        elif np.isnan(ev):
          ev = 0
        if self.edgeLeftValid:
          self.ui.ls_left_bar.setValue(int(ev))
        else:
          self.ui.ls_left_bar.setValue(-3)
        ev = (self.edgeRight + 2.5) * 20.0
        if (ev < 0):
          ev = 0
        elif ev >100:
          ev = 100
        elif np.isnan(ev):
          ev = 0
        if self.edgeRightValid:
          self.ui.ls_right_bar.setValue(int(ev))
        else:
          self.ui.ls_right_bar.setValue(-3)
        #self.ui.ls_left_bar.setEnabled(self.edgeLeftValid)
        #self.ui.ls_right_bar.setEnabled(self.edgeRightValid)
        #self.ui.ls_follow_left.setChecked(self.followLeft)
        self.ui.ls_crossing_cnt.setText(str(self.crossingWhiteCnt))
        self.ui.ls_line_valid_cnt.setText(str(self.edgeLeftValid))
        #self.ui.ls_crossing_black.setValue(self.crossingBlackCnt)
        #self.ui.frame_ls_crossing_white.setEnabled(self.crossingWhite)
        #self.ui.frame_ls_crossing_black.setEnabled(self.crossingBlack)
        self.ui.ls_power_high.setChecked(self.power_high)
        self.ui.ls_power_auto.setChecked(self.power_auto)
        self.ui.ls_crossing_detect.setValue(self.crossingDetectLimit)
        self.ui.ls_wideSensor.setChecked(self.wideSensor)
        self.ui.ls_swap_left_right.setChecked(self.swapLeftRight)
    # Show line sensor bar values
    mv = self.ui.line_disp_max_value.value() - 1
    if (self.dataReadLiv):
      self.dataReadLiv = False
      self.inUpdate = True
      if self.ui.ls_show_normalized.isChecked():
        val = self.lineValN
      else:
        val = self.lineValue
      if (val[0] > mv):
        self.ui.line_bar_1.setValue(mv)
      elif val[0] < 0:
        self.ui.line_bar_1.setValue(0)
      else:
        self.ui.line_bar_1.setValue(val[0])
      self.ui.ls_actual_1.setText(str(val[0]))
      if (val[1] > mv):
        self.ui.line_bar_2.setValue(mv)
      elif val[1] < 0:
        self.ui.line_bar_2.setValue(0)
      else:
        self.ui.line_bar_2.setValue(val[1])
      self.ui.ls_actual_2.setText(str(val[1]))
      if (val[2] > mv):
        self.ui.line_bar_3.setValue(mv)
      elif val[2] < 0:
        self.ui.line_bar_3.setValue(0)
      else:
        self.ui.line_bar_3.setValue(val[2])
      self.ui.ls_actual_3.setText(str(val[2]))
      if (val[3] > mv):
        self.ui.line_bar_4.setValue(mv)
      elif val[3] < 0:
        self.ui.line_bar_4.setValue(0)
      else:
        self.ui.line_bar_4.setValue(val[3])
      self.ui.ls_actual_4.setText(str(val[3]))
      if (val[4] > mv):
        self.ui.line_bar_5.setValue(mv)
      elif val[4] < 0:
        self.ui.line_bar_5.setValue(0)
      else:
        self.ui.line_bar_5.setValue(val[4])
      self.ui.ls_actual_5.setText(str(val[4]))
      if (val[5] > mv):
        self.ui.line_bar_6.setValue(mv)
      elif val[5] < 0:
        self.ui.line_bar_6.setValue(0)
      else:
        self.ui.line_bar_6.setValue(val[5])
      self.ui.ls_actual_6.setText(str(val[5]))
      if (val[6] > mv):
        self.ui.line_bar_7.setValue(mv)
      elif val[6] < 0:
        self.ui.line_bar_7.setValue(0)
      else:
        self.ui.line_bar_7.setValue(val[6])
      self.ui.ls_actual_7.setText(str(val[6]))
      if (val[7] > mv):
        self.ui.line_bar_8.setValue(mv)
      elif val[7] < 0:
        self.ui.line_bar_8.setValue(0)
      else:
        self.ui.line_bar_8.setValue(val[7])
      self.ui.ls_actual_8.setText(str(val[7]))
    self.inUpdate = False
    # connected to robot
    #self.ui.ls_line_white.setEnabled(self.ui.frame_batt_time.isEnabled())
    self.lock.release()
    #
    thisTab = self.ui.tabPages.indexOf(self.ui.tab_edge)
    if (self.hasFocus or justConnected) and self.ui.tabPages.currentIndex() != thisTab:
      # just switched away from this tab
      self.hasFocus = False
      if self.main.isBridge():
        #print("# Edge talking to bridge")
        # subscribe to bridge data
        self.main.devWrite(":liw subscribe 0\n") # calibrate white
        self.main.devWrite(":lib subscribe 0\n") # calibrate black
        self.main.devWrite(":liv subscribe 0\n") # sensor values
        self.main.devWrite(":livn subscribe 0\n") # sensor values normalized
        self.main.devWrite(":lip subscribe 0\n") # flags and result
        self.main.devWrite("regbot sub liw 0\n") # calibrate white
        self.main.devWrite("regbot sub lib 0\n") # calibrate black
        self.main.devWrite("regbot sub liv 0\n") # sensor values
        self.main.devWrite("regbot sub livn 0\n") # sensor values normalized
        self.main.devWrite("regbot sub lip 0\n") # flags and result
      else:
        #unsubscribe from regbot directly
        self.main.devWrite("sub liw 0\n") # calibrate white
        self.main.devWrite("sub lib 0\n") # calibrate black
        self.main.devWrite("sub liv 0\n") # sensor values
        self.main.devWrite("sub livn 0\n") # sensor values normalized
        self.main.devWrite("sub lip 0\n") # flags and result
    if (not self.hasFocus or justConnected) and self.ui.tabPages.currentIndex() == thisTab:
      # just entering this tab
      self.hasFocus = True
      if self.main.isBridge():
        self.configChanged()
        # subscribe to bridge data
        self.main.devWrite("regbot sub liw 300\n") # calibrate white
        self.main.devWrite("regbot sub lib 301\n") # calibrate black
        self.main.devWrite("regbot sub liv 100\n") # sensor values
        self.main.devWrite("regbot sub lip 104\n") # flags and result
        self.main.devWrite(":liw subscribe -1\n") # calibrate white
        self.main.devWrite(":lib subscribe -1\n") # calibrate black
        self.main.devWrite(":liv subscribe -1\n") # sensor values
        self.main.devWrite(":livn subscribe -1\n") # sensor values normalized
        self.main.devWrite(":lip subscribe -1\n") # flags and result
        self.max_value_changed()
        print("# ULineSensor:: requested data from bridge")
      else:
        self.main.devWrite("sub liw 300\n") # calibrate white
        self.main.devWrite("sub lib 301\n") # calibrate black
        self.main.devWrite("sub liv 100\n") # sensor values
        self.main.devWrite("sub livn 103\n") # sensor values normalized
        self.main.devWrite("sub lip 104\n") # flags and result
        self.max_value_changed()
        print("# ULineSensor:: requested data from Teensy")

  #
  def helpbox(self):
    # QMessageBox.about (QWidget parent, QString caption, QString text)
    if (self.about_box == None):
      self.about_box = QtGui.QMessageBox(self.main.parent)
      self.about_box.setText('''

                Line sensor

                Values are difference between illuminated and not illuminated in A/D units.

                Left and right edge is in meters relative to center of robot.

                ''');
      #about_box.setIconPixmap(QtGui.QPixmap("dtulogo_125x182.png"))
      self.about_box.setWindowTitle("Line sensor help")
      self.about_box.setWindowModality(QtCore.Qt.NonModal)
    self.about_box.show()

  def max_value_changed(self):
    v = self.ui.line_disp_max_value.value()
    self.ui.line_bar_1.setMaximum(v)
    self.ui.line_bar_2.setMaximum(v)
    self.ui.line_bar_3.setMaximum(v)
    self.ui.line_bar_4.setMaximum(v)
    self.ui.line_bar_5.setMaximum(v)
    self.ui.line_bar_6.setMaximum(v)
    self.ui.line_bar_7.setMaximum(v)
    self.ui.line_bar_8.setMaximum(v)

  def configChanged(self):
    # load the right value into step from-to widget
    self.inUpdate = True
    self.ui.ls_right_side.setEnabled(self.ui.ls_use_sensor.isChecked())
    self.ui.ls_left_side.setEnabled(self.ui.ls_use_sensor.isChecked())
    self.max_value_changed()
    self.inUpdate = False
    #pass

  def sensorOnClicked(self):
    self.ui.ls_use_sensor.setChecked(self.ui.ls_sensor_on.isChecked())
    self.setWhiteLine()

  def setWhiteLine(self):
    # send white line assumption to robot
    self.main.devWrite("lip %d %d %d %d %g %d %d\n" % (
            self.ui.ls_use_sensor.isChecked(),
            self.ui.ls_line_white.isChecked(),
            self.ui.ls_power_high.isChecked(),
            self.ui.ls_power_auto.isChecked(),
            self.ui.ls_crossing_detect.value(),
            self.ui.ls_wideSensor.isChecked(),
            self.ui.ls_swap_left_right.isChecked()
            ), True)

  def calibrateWhite(self):
    # send white line assumption to robot
    self.main.devWrite("licw\n", True)

  def calibrateBlack(self):
    # send white line assumption to robot
    self.main.devWrite("licb\n", True)

  def butEdit(self):
    if not self.inTimerUpdate:
      self.lock.acquire()
      self.inEdit = True
      self.lock.release()
  # when any of the parameters are changed - allow apply button to be pressed

  def butCancel(self):
    # cancel button pressed
    self.inEdit = False
  #

  def butApply(self):
    self.setWhiteLine()
    self.inEdit = False


import pytest
import logging
import webtest.app
from horseman.response import Response
from roughrider.application import WrappableApplication

def auth_middleware(app):
    def auth_wrapping(environ, start_response):
        if environ.get('REMOTE_USER') == 'admin':
            return app(environ, start_response)
        return Response(401)(environ, start_response)
    return auth_wrapping

def log_middleware(app):
    def log_wrapping(environ, start_response):
        logging.getLogger().info('logged')
        return app(environ, start_response)
    return log_wrapping

def test_add_duplicate_middleware():
    app = WrappableApplication()
    app.middlewares.add(log_middleware, 10)
    app.middlewares.add(log_middleware, 10)
    assert list(app.middlewares) == [
        (10, log_middleware),
        (10, log_middleware),
    ]
    app.middlewares.remove(log_middleware, 10)
    assert list(app.middlewares) == [
        (10, log_middleware)
    ]

def test_add_remove_middleware():
    app = WrappableApplication()
    assert list(app.middlewares) == []
    app.middlewares.add(log_middleware, 20)
    app.middlewares.add(auth_middleware, 10)
    assert list(app.middlewares) == [
        (10, auth_middleware),
        (20, log_middleware),
    ]
    app.middlewares.add(log_middleware, 0)
    assert list(app.middlewares) == [
        (0, log_middleware),
        (10, auth_middleware),
        (20, log_middleware),
    ]

    app.middlewares.remove(auth_middleware, 10)
    assert list(app.middlewares) == [
        (0, log_middleware),
        (20, log_middleware),
    ]

    with pytest.raises(ValueError):
        app.middlewares.remove(auth_middleware, 10)

    app.middlewares.clear()
    assert list(app.middlewares) == []

def test_middleware_caller(caplog):
    app = WrappableApplication()

    @app.routes.register('/')
    def endpoint(request):
        return Response(200, body=b'Test')

    wsgi = webtest.app.TestApp(app)
    response = wsgi.get("/")
    assert response.body == b'Test'

    app.middlewares.add(auth_middleware, 10)
    response = wsgi.get("/", expect_errors=True)
    assert response.status == '401 Unauthorized'

    app.middlewares.add(log_middleware, 20)
    with caplog.at_level(logging.INFO):
        response = wsgi.get("/", expect_errors=True)
    assert response.status == '401 Unauthorized'

    with caplog.at_level(logging.INFO):
        response = wsgi.get("/", extra_environ={"REMOTE_USER": "admin"})
    assert response.body == b'Test'
    assert caplog.record_tuples == [('root', 20, 'logged')]
    caplog.clear()

    app.middlewares.remove(auth_middleware, 10)
    with caplog.at_level(logging.INFO):
        response = wsgi.get("/")
    assert response.status == '200 OK'
    assert caplog.record_tuples == [('root', 20, 'logged')]
    caplog.clear()

    app.middlewares.remove(log_middleware, 20)
    with caplog.at_level(logging.INFO):
        response = wsgi.get("/")
    assert response.status == '200 OK'
    assert caplog.record_tuples == []


"""
Part 1 Solution: 580
Part 2 Solution: 81972
"""

# Basically a Sum function

def solve_day1_part1():
	fname = "data_day1.txt"
	frequency = 0

	with open(fname) as fp:
		line = fp.readline().rstrip("\n")
		while line:
			i = int(line)
			frequency += i
			# print("{} => {} = {}".format(line, i, total))
			# print("{}".format(frequency))

			line = fp.readline().rstrip("\n")
	return frequency

"""
# Notes
- Must read the data several times until we find a repeated frequency.
- Maybe I should read the data in a list once for performance but what if we have billions of numbers?
"""

def solve_day1_part2(frequency, frequency_count):
	fname = "data_day1.txt"

	# total_count["-17"] = 3
	with open(fname) as fp:
		line = fp.readline().rstrip("\n")
		while line:
			i = int(line)
			frequency += i
			key = str(frequency)

			if key not in frequency_count:
				frequency_count[key] = 1
				# print("Adding T={}\n".format(key))
			else:
				print("Dup T={}".format(key))
				# print("Frequency table: 1".format(total_count))
				return key
			# print("{} => {} = {}".format(line, i, total))
			line = fp.readline().rstrip("\n")
	# print("Once more")
	return solve_day1_part2(frequency, frequency_count)

total = solve_day1_part1()
print("Sum={}".format(total))

# frequency_count = {}
first_repeat = solve_day1_part2(0, {})
print("first repeated ={}".format(first_repeat))


import scipy.io
import keras
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix

from keras.optimizers import Adam
from keras.utils.np_utils import to_categorical
from keras.regularizers import l2
from model import build_model

TRAIN = 1
TEST = 3
VAL = 2

NUM_CLASSES = 2
INPUT_SHAPE = (32,32,1)

# Load data
data = scipy.io.loadmat("data/imdb.mat")
data = data['imdb'][0][0][0][0][0]
ids = data[0].flatten()
images = data[1]
labels = data[2].flatten()-1
dataset = data[4].flatten()
n = len(ids)

# Load images
x_train = np.stack([images[:,:,i,None] for i in range(n) if dataset[i]==TRAIN])
x_val = np.stack([images[:,:,i,None] for i in range(n) if dataset[i]==VAL])
x_test = np.stack([images[:,:,i,None] for i in range(n) if dataset[i]==TEST])

# Load labels
y_train = np.stack([labels[i] for i in range(n) if dataset[i]==TRAIN])
y_val = np.stack([labels[i] for i in range(n) if dataset[i]==VAL])
y_test = np.stack([labels[i] for i in range(n) if dataset[i]==TEST])

print("Loaded {0} training samples".format(len(y_train)))
print("Loaded {0} validation samples".format(len(y_val)))
print("Loaded {0} testing samples".format(len(y_test)))

# encode to one hot
y_train_c = to_categorical(y_train, num_classes=2)
y_val_c = to_categorical(y_val, num_classes=2)
y_test_c = to_categorical(y_test, num_classes=2)

model = build_model(INPUT_SHAPE,flatten=True)
optimizer = Adam(lr=0.001, decay=1e-6)
model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer=optimizer)

for i in range(1000):
	#model.fit(x_train, y_train, batch_size=128, epochs=1)
	model.fit(x_train, y_train_c, batch_size=128, epochs=1)
	y_pred = model.predict(x_test, batch_size=32)
	y_pred = np.argmax(y_pred, axis=1)
	print(confusion_matrix(y_test, y_pred))
	model.save_weights('models/model_%i_weights.h5'%i)


# IMPORT THE LIBRARIES....
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
import warnings

warnings.filterwarnings("ignore")

def prepare_dataset(df):
    #  Selecting line by line from dataframe
    #  Odd rows as input
    #  Close price from even rows as output
    # df = df.reset_index(drop=True)
    # df = dframe.set_index('Open', inplace=True)

    # df.index = df['Open']

    df_1 = df.iloc[range(0, len(df), 2)]
    # df_1 = df_1.drop(df_1.index[-1])

    a = [i for i in range(0, len(df)) if i % 2 != 0]
    df_2 = df.iloc[a]

    if len(df_1) > len(df_2):
        df_1 = df_1.drop(df.tail(1).index)

    if len(df_1) < len(df_2):
        df_2 = df_2.drop(df.tail(1).index)

    # Insert the close price column in the dataframe 'df_1'

    # df_1.insert(6, 'out', df_2['Close'].to_list())

    # #### remove the date column
    #

    df_1.pop('Dividends')
    df_1.pop('Stock Splits')
    df_1.pop('Close')
    # y = df_1.pop('out')
   #  df_2.reset_index(drop=True, inplace=True)
   #  df_1 = df_1.reset_index()
    y = df_2['Close']  # ['Close'].to_list()
    X = df_1

    return X, y

# #### Split data on Train and Test

def split_data(X, y):
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
    return X_train, X_test, y_train, y_test

def train(x_train, y_train):
    poly_feat = PolynomialFeatures(degree=1)
    X_poly = poly_feat.fit_transform(x_train)
    poly_model = LinearRegression(fit_intercept=False).fit(X_poly, y_train)
    return poly_model, poly_feat

# test = poly_feat.fit_transform(X_test)
# poly_model.score(test, y_test)

def predict(data, model, model_feat):
    # data must be a list
    # data = [X_test.iloc[s].to_list()]
    predict_ = model_feat.fit_transform(data)
    predict = model.predict(predict_)
    return predict[0]

def tomorrow_predictions(df):
    data = df.iloc[-1:]
    data = data.iloc[0].to_list()[:-2]
    del data[3]
    input_data, output_data = prepare_dataset(df)
    X_train, X_test, y_train, y_test = split_data(input_data, output_data)
    model, model_feat = train(X_train, y_train)
    return predict([data], model, model_feat)
    #
    # predicted_results = predict(data, model)
    # return predicted_results


from flask import jsonify
from dateutil import parser, tz
import datetime
import requests

from austin import Config

def date_convert(date_time):

    # This assumes datetime is coming from Zulu/UTC zone & convert to EST
    from_zone = tz.gettz('UTC')
    to_zone = tz.gettz('America/New_York')

    # Get Current Time
    time_now = datetime.datetime.now()

    # Parse given time into datetime type, convert to EST time
    old_time = parser.parse(date_time)
    old_time = old_time.replace(tzinfo=from_zone).astimezone(to_zone)

    # Remove the timezone awareness to calculate time difference
    old_time = old_time.replace(tzinfo=None)
    time_difference = (time_now - old_time).total_seconds()

    if time_difference < 60:
        return(str(int(time_difference)) + " seconds ago")

    elif time_difference < 3600:
        if time_difference < 120:
            return(str(int(time_difference / 60)) + " minute ago")
        else:
            return(str(int(time_difference / 60)) + " minutes ago")

    elif time_difference < 86400:
        if time_difference < 7200:
            return(str(int((time_difference / 60) / 60)) + " hour ago")
        else:
            return(str(int((time_difference / 60) / 60)) + " hours ago")
    else:
        if time_difference < 172800:
            return(str(int(((time_difference / 60) / 60) / 24)) + " day ago")
        else:
            return(str(int(((time_difference / 60) / 60) / 24)) + " days ago")

    return dict(date_convert)

def github_feed(limit):
    """ Return # of the most recent Github Actions """

    url = 'https://api.github.com/users/abalarin/events/public'
    token = '?access_token=' + Config.GITHUB_TOKEN

    github_resp = requests.get(url + token + '&per_page=' + str(limit)).json()

    # print(github_resp)
    for event in github_resp:
        if event['type'] == 'WatchEvent':
            event['type'] = ' is watching'
        if event['type'] == 'ForkEvent':
            event['type'] = ' forked'
        if event['type'] == 'PushEvent':
            event['type'] = ' pushed to'
        if event['type'] == 'PullRequestEvent':
            event['type'] = ' pulled from'
        if event['type'] == 'CreateEvent':
            event['type'] = ' created repo'
        if event['type'] == 'DeleteEvent':
            event['type'] = ' deleted repo'
        if event['type'] == 'IssueCommentEvent':
            event['type'] = ' commented on'
        if event['type'] == 'IssuesEvent':
            if event['payload']['action'] == 'closed':
                event['type'] = 'closed out an issue on'
            elif event['payload']['action'] == 'opened':
                event['type'] = 'opened an issue on '

        event['created_at'] = date_convert(event['created_at'])

    return github_resp


from pyrogram import Client, enums, filters
from pyrogram.types import Message
from . import *

@Client.on_message(filters.command("cانضم", [""]) & filters.user(DEVS) & ~filters.me)
@Ubot(["انضم"], "")
async def join(client: Client, message: Message):
    tex = message.command[1] if len(message.command) > 1 else message.chat.id
    g = await message.reply_text("`جاري...`")
    try:
        await client.join_chat(tex)
        await g.edit(f"**تم الانضمام بنجاح ايدي المجموعة* `{tex}`")
    except Exception as ex:
        await g.edit(f"**خطأ:** \n\n{str(ex)}")

@Ubot(["غادر"], "")
async def leave(client: Client, message: Message):
    xd = message.command[1] if len(message.command) > 1 else message.chat.id
    xv = await message.reply_text("`جاري...`")
    try:
        await xv.edit_text(f"{client.me.first_name} غادر القروب, بايي!!")
        await client.leave_chat(xd)
    except Exception as ex:
        await xv.edit_text(f"**خطأ:** \n\n{str(ex)}")

@Ubot(["اطلعر"], "")
async def kickmeall(client: Client, message: Message):
    tex = await message.reply_text("`جاري مغادرة كل المجموعات...`")
    er = 0
    done = 0
    async for dialog in client.get_dialogs():
        if dialog.chat.type in (enums.ChatType.GROUP, enums.ChatType.SUPERGROUP):
            chat = dialog.chat.id
            try:
                done += 1
                await client.leave_chat(chat)
            except BaseException:
                er += 1
    await tex.edit(
        f"**تمت المغادرة من{done} مجموعة, فشل من {er} مجموعة**"
    )

@Ubot(["اطلعق"], "")
async def kickmeallch(client: Client, message: Message):
    ok = await message.reply_text("`جاري مغادرة كل القنوات...`")
    er = 0
    done = 0
    async for dialog in client.get_dialogs():
        if dialog.chat.type in (enums.ChatType.CHANNEL):
            chat = dialog.chat.id
            try:
                done += 1
                await client.leave_chat(chat)
            except BaseException:
                er += 1
    await ok.edit(
        f"**تمت المغادرة من {done} قناة, فشل المغادرة من {er} قناة**"
    )

add_command_help(
    "المغادرة",
    [
        [f"اطلر", "يغادر القروبات."],
        [f"اطلعق", "يغادر القنوات."],
        [f"انضم [Username]", "يضيف المستخدم."],
        [f"غادر [Username]", "يطرد الشخص الي منشنته."],
    ],
)


import json
import pandas
import random

# INSTRUCTIONS FOR CREATING MOCK STUDENTS
# BACKGROUND: this python script allows for the creation of realistic mock students,
# potentially to be used in populating a database.
# The methods of this script use results from a survey given to the UBC student body.
# By doing so, the script is able to produce students that somewhat resemble the surveyed students.

# IF YOU WISH TO CREATE MOCK STUDENTS...,
# scroll down to line "320" to the function call "manufactureStudents(integer)".
# Uncomment this line by deleting the "#" symbol at the start of the line,
# and replace "integer" with the number of students you wish to create.

# then, if you own a Mac, open a terminal at the directory you are storing this file,
# and copy and paste the following command into the terminal: python3 CreateStudents.py
# The terminal should then output a list of student objects.
# You may wish to copy and paste this list into a JSON file.
# NOTE: you must have python downloaded in your system. You may find the latest version
# may be found here: https://www.python.org/downloads/mac-osx/

excel_data_df = pandas.read_excel('SurveyResponses.xlsx', sheet_name='Form Responses 1')

academicYear = pandas.DataFrame(data=excel_data_df, columns=["Academic Year"])
coop = pandas.DataFrame(data=excel_data_df, columns=["Co-op"])
gpa = pandas.DataFrame(data=excel_data_df, columns=["GPA"])
genCSSkills = pandas.DataFrame(data=excel_data_df, columns=["General CS Skills"])
workExperience = pandas.DataFrame(data=excel_data_df, columns=["work experience"])

languages = pandas.DataFrame(data=excel_data_df,
	columns=[
	"Java",
	"Python",
	"C++",
	"C",
	"C#",
	"Javascript",
	"Typescript",
	"HTML",
	"CSS",
	"R",
	"MATLAB",
	"Mathematica",
	"SQL",
	"Other"
	])

frameworks = pandas.DataFrame(data=excel_data_df,
	columns=[
	"React",
	"Node",
	"Angular",
	"Bootstrap",
	"MongoDB",
	"Ruby on Rails",
	"Google Cloud",
	"AWS",
	"Docker",
	"Linux",
	"Unix",
	"Other"
	])

workflowTools = pandas.DataFrame(data=excel_data_df,
	columns= [
	"GitHub",
	"Azure",
	"Jira",
	"Jupyter",
	"Other",
	])

languagesDict = languages.to_dict('index')
frameworksDict = frameworks.to_dict('index')
workflowToolsDict = workflowTools.to_dict('index')
academicYearDict = academicYear.to_dict('index')
coopDict = coop.to_dict('index')
gpaDict = gpa.to_dict('index')
genCSSkillsDict = genCSSkills.to_dict('index')
workExperienceDict = workExperience.to_dict('index')

## Methods from lines 87 through to 275 are used for purposes of synthetically populating fields from realistically weighted pools

cssConcepts = ['Data Structures',
 'Algorithms',
 'Asynchronous programming',
 'Agile Development',
 'Object-Oriented Programming',
 'Functional Programming',
 'web APIs',
 'RESTify services',
 'Computer Networks']

def cssConceptsPopulator():
	studentCSSConcepts = []
	for concept in cssConcepts:
		if (bool(random.getrandbits(1))):
			studentCSSConcepts.append(concept)
	return studentCSSConcepts

def reformatDictionary(dictionary):
	for key in dictionary:
		dictionary[key] = reformatElement(dictionary[key])
	return(dictionary)

def reformatElement(content):
	if (content == '≥ 4 months'):
		return 4
	elif (content == '≥ 8 months'):
		return 8
	elif (content == '≥ 12 months'):
		return 12
	elif (content == '≥ 2 years'):
		return 24
	elif (content == 'None'):
		return 0
	elif (content == 'Below 60%'):
		return random.randint(50, 59)
	elif (content == '60-69%'):
		return random.randint(60, 69)
	elif (content == '70-79%'):
		return random.randint(70, 79)
	elif (content == '80-89%'):
		return random.randint(80, 89)
	elif (content == '90%+'):
		return random.randint(90, 100)
	elif (content == '4th Year+'):
		return 4
	elif (content == '3rd Year'):
		return 3
	elif (content == '2nd Year'):
		return 2
	elif (content == '1st Year'):
		return 1
	elif (content == 'Yes'):
		return True
	elif (content == 'No'):
		return False

def gpaRandomizer(figure):
	if (figure == 50):
		return random.randint(50, 59)
	elif (figure == 60):
		return random.randint(60, 69)
	elif (figure == 70):
		return random.randint(70, 79)
	elif (figure == 80):
		return random.randint(80, 89)
	elif (figure == 90):
		return random.randint(90, 100)

seeking = [True, True, True, True, True, True, True, False, False, False]
coop = [True, True, True, True, True, True, False, False, False, False]
workExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 12, 12, 24]
aYear = [1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4]
sGPA = [50, 60, 60, 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 80, 90, 90, 90]
techExperience = [0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 24, 24, 24, 24, 24]
javaExperience = [0, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 12, 12, 12, 24, 24, 24, 24, 24]
pythonExperience = [0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 12, 24, 24, 24]
cppExperience = [0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, 12, 12, 24]
cExperience = [0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 24, 24]
cppppExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 12, 24]
javascriptExperience = [0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 12, 12, 24, 24, 24, 24, 24]
typescriptExperience = [0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 12, 12, 12, 24]
htmlExperience = [0, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 12, 12, 12, 24, 24, 24, 24, 24]
cssExperience = [0, 4, 4, 4, 4, 4, 4, 4, 8, 12, 12, 12, 12, 12, 12, 24, 24, 24, 24, 24]
rExperience = [0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 24]
matlabExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 8, 12, 24]
mathematicaExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 24]
sqlExperience = [0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 24]
otherExperience = [0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12, 24, 24, 24, 24]
reactExperience = [0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 12, 24, 24, 24]
nodeExperience = [0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 12, 12, 24, 24]
angularExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12, 24]
bootstrapExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 8, 8, 12, 12, 24]
mongodbExperience = [0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 24, 24]
rubyonrailsExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 8, 12]
googlecloudExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 8, 8, 8, 12, 12, 24]
awsExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 8, 8, 8, 12, 12, 24, 24]
dockerExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 8, 8, 8, 12, 12, 24]
linuxExperience = [0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12, 24, 24, 24, 24]
unixExperience = [0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 24, 24]
githubExperience = [0, 4, 8, 8, 12, 12, 12, 12, 12, 12, 12, 24, 24, 24, 24, 24, 24, 24, 24, 24]
azureExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 8, 8, 12, 12, 24]
jiraExperience = [0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 8, 8, 8, 12, 12, 12, 24, 24, 24]
jupyterExperience = [0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 24, 24]
asanaExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 12 ,12, 24]
confluenceExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 12 ,12, 24]
notionExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 12 ,12, 24]
kubernetesExperience = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 12 ,12, 24]
materialuiExperience = [0, 0, 0, 0, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, 12, 12, 24, 24, 24, 24]

location = [
'Canada', 'Canada', 'Canada', 'Canada', 'Canada',
'Canada', 'Canada', 'Canada', 'Canada', 'Canada',
'Canada', 'Canada', 'Canada', 'Canada', 'Canada',
'Canada', 'Canada', 'France', 'China', 'Japan',
'Singapore', 'Russia', 'India', 'Turkey', 'Germany']

degree = [
"BSc", "BSc", "BSc", "BSc", "BSc",
"BSc", "BSc", "BSc", "BSc", "BSc",
"BSc", "BSc", "BSc", "BSc", "BSc",
"MSc", "MSc", "MSc", "MSc", "PhD"]

degreeLocation = [
'University of British Columbia', 'University of British Columbia', 'University of British Columbia',
'University of British Columbia', 'University of British Columbia', 'University of British Columbia',
'University of British Columbia', 'University of British Columbia', 'University of British Columbia',
'University of British Columbia', 'University of British Columbia', 'University of British Columbia',
'University of British Columbia', 'University of British Columbia', 'University of British Columbia',
'University of Waterloo', 'University of Alberta', 'University of Toronto', 'McGill University', 'University of Victoria']

citizenship = ['Citizen', 'Citizen', 'Citizen', 'Citizen', 'Citizen',
'Citizen', 'Citizen', 'International', 'International', 'Permanent Residency']

# Use this method to create student objects from the survey results (62 objects in total)
def createStudents():
	i = 0
	students = []
	print('starting to assemble students')
	for entry in frameworksDict:
		student = {
		'gpaValue': reformatDictionary(gpaDict[i])['GPA'],
		'year': reformatDictionary(academicYearDict[i])['Academic Year'],
		'coOp': reformatDictionary(coopDict[i])['Co-op'],
		'seeking': seeking[random.randint(0, 9)],
		'candidate': citizenship[random.randint(0, 9)],
		'experience': reformatDictionary(workExperienceDict[i])['work experience'],
		'languages': reformatDictionary(languagesDict[i]),
		'frameworks': reformatDictionary(frameworksDict[i]),
		'tools': reformatDictionary(workflowToolsDict[i]),
		'concepts': genCSSkillsDict[i]['General CS Skills'].split(", "),
		'location': location[random.randint(0, 24)],
		'academicReq': {degree[random.randint(0, 19)] : degreeLocation[random.randint(0, 19)]}
		}
		students.append(student)
		i+=1
	print(json.dumps(students))
	print('finished assembling students!!')

# Use this method to synthesize a new, realistic, group of students
def manufactureStudents(numStudents):
	i = 0
	students = []
	print('starting to manufacture students')
	while i < numStudents:
		student = {
		'gpaValue': gpaRandomizer(sGPA[random.randint(0, 19)]),
		'year': aYear[random.randint(0, 19)],
		'coOp': coop[random.randint(0,9)],
		'seeking': seeking[random.randint(0, 9)],
		'candidate': citizenship[random.randint(0, 9)],
		'experience': workExperience[random.randint(0,19)],
		'languages': {
			'Java': javaExperience[random.randint(0,19)],
			'Python': pythonExperience[random.randint(0,19)],
			'C++': cppExperience[random.randint(0,19)],
			'C': cExperience[random.randint(0,19)],
			'C#': cppppExperience[random.randint(0,19)],
			'JavaScript': javascriptExperience[random.randint(0,19)],
			'TypeScript': typescriptExperience[random.randint(0,19)],
			'HTML': htmlExperience[random.randint(0,19)],
			'CSS': cssExperience[random.randint(0,19)],
			'R': rExperience[random.randint(0,19)],
			'MATLAB': matlabExperience[random.randint(0,19)],
			'Mathematica': mathematicaExperience[random.randint(0,19)],
			'SQL': sqlExperience[random.randint(0,19)],
			'Other': otherExperience[random.randint(0,19)]

		},
		'frameworks': {
			'React': reactExperience[random.randint(0,19)],
			'Node': nodeExperience[random.randint(0,19)],
			'Angular': angularExperience[random.randint(0,19)],
			'Bootstrap': bootstrapExperience[random.randint(0,19)],
			'MongoDB': mongodbExperience[random.randint(0,19)],
			'Ruby on Rails': rubyonrailsExperience[random.randint(0,19)],
			'Google Cloud': googlecloudExperience[random.randint(0,19)],
			'AWS': awsExperience[random.randint(0,19)],
			'Docker': dockerExperience[random.randint(0,19)],
			'Linux': linuxExperience[random.randint(0,19)],
			'Unix': unixExperience[random.randint(0,19)],
			'MaterialUI': materialuiExperience[random.randint(0,19)],
			'Other': otherExperience[random.randint(0,19)]

		},
		'tools': {
			'GitHub': githubExperience[random.randint(0,19)],
			'Azure': azureExperience[random.randint(0,19)],
			'Jira': jiraExperience[random.randint(0,19)],
			'Jupyter': jupyterExperience[random.randint(0,19)],
			'Asana': asanaExperience[random.randint(0,19)],
			'Confluence': confluenceExperience[random.randint(0,19)],
			'Notion': notionExperience[random.randint(0,19)],
			'Kubernetes': kubernetesExperience[random.randint(0,19)],
			'Other': otherExperience[random.randint(0,19)]

		},
		'concepts': cssConceptsPopulator(),
		'location': location[random.randint(0, 24)],
		'academicReq': {degree[random.randint(0, 19)] : degreeLocation[random.randint(0, 19)]}

		}
		student['languages']['CSS'] = min(student['languages']['CSS'], student['languages']['HTML'])
		student['frameworks']['React'] = min(student['frameworks']['React'], student['languages']['JavaScript'])
		student['frameworks']['Node'] = min(student['frameworks']['Node'], student['languages']['JavaScript'])
		student['frameworks']['Angular'] = min(student['frameworks']['Angular'], student['languages']['JavaScript'])
		student['frameworks']['MaterialUI'] = min(student['frameworks']['MaterialUI'], student['frameworks']['React'])
		students.append(student)
		i+=1
	print(json.dumps(students))
	print('completed manufacturing students')

# manufactureStudents(integer)


class Repo:
    def __init__(self, url=None, vulnerabilities=None):
        self.url = url
        self.vulnerabilities = vulnerabilities

class Vulnerability:
    def __init__(self):
        self.filename = None
        self.source = None
        self.sink = None
        self.source_line = None
        self.sink_source = None

def parse_vulnerabilities(file_descriptor):
    vulnerabilities = list()
    vulnerability = Vulnerability()
    for line in file_descriptor:
        next_line = next(file_descriptor)
        if line.strip() == '' and 'Vulnerability:' not in next_line:
            return vulnerabilities
        elif line.strip() == '':
            vulnerabilities.append(vulnerability)
            vulnerability = Vulnerability()
        else:
            if 'File:' in line:
                vulnerability.filename = line.split(':')[1].strip()
            elif ' > User input at line' in line:
                vulnerability.source = line.split('"')[-2]
                vulnerability.source_line = next_line
            elif ' > reaches line' in line:
                vulnerability.source = line.split('"')[-2]
                vulnerability.source_line = next_line

def get_repos(filename):
    repos = list()
    repo = Repo()
    previous_line = None
    with open(filename, 'r') as fd:
        for line in fd:
            next_line = next(fd)
            if not line.strip() == '' or 'Vulnera' in next_line:
                if 'https://' in line:
                    repo.url = line.strip()
                elif 'Vulnera' in next_line:
                    repo.vulnerabilities = parse_vulnerabilities(fd)
            elif next_line.strip() == '':
                    continue
            else:
                repos.append(repo)
                repo = Repo()
            previous_line = line
    return repos

def get_urls(filename):
    with open(filename, 'r') as fd:
        return sorted({line for line in fd if 'https' in line})

if __name__ == '__main__':
    filename = 'scan_results/archived_26_10_scan.pyt'
    filename = 'scan_results/test.pyt'
    repos = get_repos(filename)
    print([b.url for b in repos])
    print(len(repos))


import os
import sys
import pathlib
import argparse
import configparser
import numpy as np
from collections import OrderedDict
from meta_cli import log

CONFIG_FILE_NAME = os.path.join(str(pathlib.Path.home()), 'meta.conf')

SECTIONS = OrderedDict()

SECTIONS['general'] = {
    'config': {
        'default': CONFIG_FILE_NAME,
        'type': str,
        'help': "File name of configuration",
        'metavar': 'FILE'},
    'verbose': {
        'default': True,
        'help': 'Verbose output',
        'action': 'store_true'},
    'key': {
        'type': str,
        'default': '',
        'help': "when set only tags containing key are shown"},
    'value': {
        'type': float,
        'default': None,
        'help': "value used by the set function to replace the original key entry"},
        }

SECTIONS['meta'] = {
    'doc-dir': {
        'type': str,
        'default': '.',
        'help': "sphinx/readthedocs documentation directory where the meta data table extracted from the hdf5 file should be saved, e.g. docs/source/..."},
    'doc-file-prefix': {
        'type': str,
        'default': 'log',
        'help': "the sphinx/readthedocs compatible table file name prefix"},
    'file-name': {
        'type': str,
        'default': '.',
        'help': "hdf5 file or directory containing multiple hdf5 files, e.g. /data/sample.h5 or /data/"},
        }

meta_PARAMS = ('meta', )

NICE_NAMES = ('General', 'Meta HDF5')

def get_config_name():
    """Get the command line --config option."""
    name = CONFIG_FILE_NAME
    for i, arg in enumerate(sys.argv):
        if arg.startswith('--config'):
            if arg == '--config':
                return sys.argv[i + 1]
            else:
                name = sys.argv[i].split('--config')[1]
                if name[0] == '=':
                    name = name[1:]
                return name

    return name

def parse_known_args(parser, subparser=False):
    """
    Parse arguments from file and then override by the ones specified on the
    command line. Use *parser* for parsing and is *subparser* is True take into
    account that there is a value on the command line specifying the subparser.
    """
    if len(sys.argv) > 1:
        subparser_value = [sys.argv[1]] if subparser else []
        config_values = config_to_list(config_name=get_config_name())
        values = subparser_value + config_values + sys.argv[1:]
        #print(subparser_value, config_values, values)
    else:
        values = ""

    return parser.parse_known_args(values)[0]

def config_to_list(config_name=CONFIG_FILE_NAME):
    """
    Read arguments from config file and convert them to a list of keys and
    values as sys.argv does when they are specified on the command line.
    *config_name* is the file name of the config file.
    """
    result = []
    config = configparser.ConfigParser()

    if not config.read([config_name]):
        return []

    for section in SECTIONS:
        for name, opts in ((n, o) for n, o in SECTIONS[section].items() if config.has_option(section, n)):
            value = config.get(section, name)

            if value != '' and value != 'None':
                action = opts.get('action', None)

                if action == 'store_true' and value == 'True':
                    # Only the key is on the command line for this action
                    result.append('--{}'.format(name))

                if not action == 'store_true':
                    if opts.get('nargs', None) == '+':
                        result.append('--{}'.format(name))
                        result.extend((v.strip() for v in value.split(',')))
                    else:
                        result.append('--{}={}'.format(name, value))

    return result

class Params(object):
    def __init__(self, sections=()):
        self.sections = sections + ('general', )

    def add_parser_args(self, parser):
        for section in self.sections:
            for name in sorted(SECTIONS[section]):
                opts = SECTIONS[section][name]
                parser.add_argument('--{}'.format(name), **opts)

    def add_arguments(self, parser):
        self.add_parser_args(parser)
        return parser

    def get_defaults(self):
        parser = argparse.ArgumentParser()
        self.add_arguments(parser)

        return parser.parse_args('')

def write(config_file, args=None, sections=None):
    """
    Write *config_file* with values from *args* if they are specified,
    otherwise use the defaults. If *sections* are specified, write values from
    *args* only to those sections, use the defaults on the remaining ones.
    """
    config = configparser.ConfigParser()

    for section in SECTIONS:
        config.add_section(section)
        for name, opts in SECTIONS[section].items():
            if args and sections and section in sections and hasattr(args, name.replace('-', '_')):
                value = getattr(args, name.replace('-', '_'))
                if isinstance(value, list):
                    # print(type(value), value)
                    value = ', '.join(value)
            else:
                value = opts['default'] if opts['default'] is not None else ''

            prefix = '# ' if value == '' else ''

            if name != 'config':
                config.set(section, prefix + name, str(value))
    with open(config_file, 'w') as f:
        config.write(f)

def log_values(args):
    """Log all values set in the args namespace.

    Arguments are grouped according to their section and logged alphabetically
    using the DEBUG log level thus --verbose is required.
    """
    args = args.__dict__

    for section, name in zip(SECTIONS, NICE_NAMES):
        entries = sorted((k for k in args.keys() if k in SECTIONS[section]))
        if entries:
            log.info(name)
            for entry in entries:
                value = args[entry] if args[entry] is not None else "-"
                log.info("  {:<16} {}".format(entry, value))

def show_config(args):
    """Log all values set in the args namespace.

    Arguments are grouped according to their section and logged alphabetically
    using the DEBUG log level thus --verbose is required.
    """
    args = args.__dict__

    log.warning('meta status start')
    for section, name in zip(SECTIONS, NICE_NAMES):
        entries = sorted((k for k in args.keys() if k.replace('_', '-') in SECTIONS[section]))
        if entries:
            for entry in entries:
                value = args[entry] if args[entry] != None else "-"
                log.info("  {:<16} {}".format(entry, value))

    log.warning('meta status end')


from . import views
from django.urls import path
from rest_framework.authtoken import views as auth_token
from .authentication import CustomAuthToken

app_name = 'authorize_users'

urlpatterns = [
    path('create-account/', views.create_account, name='create_account'),
    path('authorize-login/',  CustomAuthToken.as_view(), name='authorize_login'),
    path('authorize-logout/', views.authorize_logout, name='authorize_logout'),
    path('authorize-token/', views.authorize_token, name='authorize_token'),
    path('get-people/', views.get_people, name='get_people'),
    path('send-announcement/', views.send_announcement, name='send_announcement'),
    path('add-subscriber/', views.add_subscriber, name='add_subscriber'),
    path('import-subscriber/', views.import_subscriber, name='import_subscriber'),
    path('edit-subscriber/', views.edit_subscriber, name='edit_subscriber'),
    path('delete-subscriber/', views.delete_subscriber, name='delete_subscriber'),

    # Admin
    path('get-approval/', views.get_approval, name='get_approval'),
    path('authorize-approval/', views.authorize_approval, name='authorize_approval'),
    path('authorize-disapproval/', views.authorize_disapproval, name='authorize_disapproval'),
    path('get-admin-data/', views.get_admin_data, name='get_admin_data'),
    path('authorize-announcements/', views.authorize_announcements, name='authorize_announcements')
]


"""
Adds flags indicating survival risk to the X_test and original dataframes.
Saves all dataframes as csv files for visualization in Tableau.

Files saved include
-- X_test_with_flag.csv
-- original_data_with_flag.csv
"""

import pickle
import pandas as pd

def flag(row):
    """Replaces any value in column 'flag' with flags to indicate prbability
    of survival where
      -- R = high risk of not surviving
      -- Y = medium risk of not surviving
      -- G = low risk of not surviving
    """
    if row['flag'] <= .3:
        val = 'G'
    elif .3 < row['flag'] <= .7:
        val = 'Y'
    elif .7 < row['flag'] <= 1:
        val = 'R'
    return val

def create_flag_column(x_df, saved_model):
    """Adds flags to the X_test dataframe that indicate survival risk level
    where
      -- R = high risk of not surviving
      -- Y = medium risk of not surviving
      -- G = low risk of not surviving

    Args:
    x_df -- the X_test dataframe created in modeling
    saved_model -- the model used to predict surivival probability
    """

    pred_probas = saved_model.predict_proba(x_df)[:, 1]
    pred_proba_df = pd.DataFrame({'pred_proba': pred_probas})

    # Adding flags to indicate risk level. R = high risk, Y = medium, G = low
    X_test_probs = pd.concat((X_test.reset_index(), pred_proba_df), axis=1)
    X_test_probs['flag'] = X_test_probs.pred_proba.apply(flag, axis=1)

    # for the visualization, creating 'patient_id' - hypothetical patient ID numbers.
    X_test_probs = X_test_probs.rename(columns={'index':'patient_id'})

    # Save as csv for visualization in Tableau
    X_test_probs.to_csv('X_test_with_flag.csv')

    return X_test_probs

def flag_original(X_test, original_data, predict_proba_df):
    """Saves the original dataframe with flags appended to any row that was
    included in the X_test set. Dataframe will be used for Tableau
    visualization.
    """

    # Identify the X_test rows within the original dataset
    X_test_indices = list(X_test.index)
    filtered_original = original_data.loc[X_test_indices, :]
    original_flagged = pd.concat((filtered_original.reset_index(),
                                  predict_proba_df), axis=1)
    original_flagged = original_flagged.rename(columns={'index':'patient_id'})

    # Add R, G, Y flags to dataframe
    original_flagged['flag'] = original_flagged.pred_proba.apply(flag, axis=1)

    # Save as csv for Tableau visualization
    original_flagged.to_csv('original_data_with_flag.csv')

def main():
    """Loads necessary files for appending risk flags. Calls functions to
    add survival risk flags to the X_test and original datasets.
    """
    # Load necessary files
    X_test = pd.read_csv('X_test.csv')
    original_dataset = pd.read_csv('original_dataset.csv')
    model = pickle.load(open('icu_survival_model.pkl', 'rb'))

    # Append flags to X_test
    test_pred_proba = create_flag_column(X_test, model)

    # Append flags to original dataset
    flag_original(X_test, original_dataset, test_pred_proba)

main()


import pathlib
import subprocess

recipe_default = "recipe"
experiment_config_default = pathlib.Path("config/experiment.yaml")
options_config_default = pathlib.Path("config/options.yaml")

def weld_pipeline(
    batch_id,
    recipe_folder=recipe_default,
    experiment_config_file=experiment_config_default,
    options_config_file=options_config_default,
    force=False,
):
    """
    Send a series of subprocess jobs to execute the full weld
    """

    payload = [
        "--batch_id",
        str(batch_id),
        "--experiment_config_file",
        experiment_config_file,
        "--options_config_file",
        options_config_default,
    ]

    if force:
        payload += ["--force"]

    # Module 0 - Preprocess Sites
    preprocess_dir = str(pathlib.Path(f"{recipe_folder}/0.preprocess-sites"))

    preprocess_scripts = [
        "0.prefilter-features.py",
        "1.process-spots.py",
        "2.process-cells.py",
        "3.visualize-cell-summary.py",
        "4.image-and-segmentation-qc.py",
    ]

    split_step = ["--split_step", "qc"]
    for script in preprocess_scripts:
        full_script = str(pathlib.Path(f"{preprocess_dir}/{script}"))
        p = subprocess.Popen(
            ["python", full_script] + payload + split_step, shell=False
        )
        p.communicate()

    # Module 1 - Generate Profiles
    profile_dir = str(pathlib.Path(f"{recipe_folder}/1.generate-profiles"))

    profile_scripts = [
        "0.merge-single-cells.py",
        "1.aggregate.py",
        "2.normalize.py",
        "3.feature-select.py",
    ]

    split_step = ["--split_step", "profile"]
    for script in profile_scripts:
        full_script = str(pathlib.Path(f"{profile_dir}/{script}"))
        p = subprocess.Popen(
            ["python", full_script] + payload + split_step, shell=False
        )
        p.communicate()


#!/usr/bin/env python3
import time
from copy import deepcopy
from random import shuffle

class minimax_alphabeta:

    def __init__(self,start_time, time_limit):

        self.INFINITY=float("inf")
		#Set Iteration Depth
        self.init_depth=2
        self.start_time=start_time
        self.time_limit=time_limit

    def alphabeta(self,b,depth,alpha,beta,maximize):

        #minimax algorithm with alpha-betasearch
        c_time= time.time()

		#Check for time limit
        if(float((c_time-self.start_time)) > (float(self.time_limit) -2)):
            self.time_up_flg=1
            return b.heuristic_evaluator()

		#At end of depth
        if(depth==0):
            return b.heuristic_evaluator()

		#Check if current move is making out Kingfisher in danger
        king_check=b.king_in_danger(b.current_player)
        if(king_check):
             return(self.INFINITY)

        if maximize:
            best_value = self.INFINITY
			#Get possible moves for current board
            moves_list=b.get_possible_moves()
            #Shuffle moves so that moves will be picked randomly rather in sequence
			#This will ensure if there is program end due to time limit, we do not always
			#consider start moves all time
            shuffle(moves_list)
            for move in moves_list:
				#Make temporary copy of current board and make move on new temp board
                b_temp1=deepcopy(b)
                b_temp1.make_move(move[0],move[1],move[2])
                score=self.alphabeta(b_temp1,depth,alpha,beta,False)
                best_value=max(best_value,score)
                alpha=max(alpha,best_value)
                if(alpha>beta):
                    break
            return best_value
        else:
            best_value = self.INFINITY
			#Get possible moves for current board
            moves_list=b.get_possible_moves()
			#Shuffle moves so that moves will be picked randomly rather in sequence
			#This will ensure if there is program end due to time limit, we do not always
			#consider start moves all time
            shuffle(moves_list)
            for move in moves_list:
                b_temp1=deepcopy(b)
                b_temp1.make_move(move[0],move[1],move[2])
                score=self.alphabeta(b_temp1,depth-1,alpha,beta,True)
                best_value=min(best_value,score)
                beta=min(beta,best_value)
                if(alpha>beta):
                    break
            return best_value

        return 0

   ####################################################################
    def best_move(self,b):

		#Function to get best move for current board
        self.time_up_flg=0
        self.best_move=None
        min_value=self.INFINITY
        min_move=None

        #Get possible moves for current board
        moves_list=b.get_possible_moves()
		#Check from current moves list, if there is any move which will
		#capture other player's king
        winner_flg, winning_move=  b.winning_move(moves_list,b.current_player)
        if (winner_flg==1) :
            print ("Hurray!!!! Winner!!!!")
            min_move=winning_move
        else :
			#There is no move in current move list which will capture other
			#player's Kingfisher. So We need to iterate each move and identify
			#best move
            shuffle(moves_list)
            for move in moves_list:
                b_temp=deepcopy(b)
                b_temp.make_move(move[0],move[1],move[2])
                value=self.alphabeta(b_temp,self.init_depth,-self.INFINITY,self.INFINITY,False)
                if (value <= min_value and self.time_up_flg ==1 ):
                    #We are out of time, so get best possible move from iterated moves so far
                    min_value = value
                    min_move = move
                    break
                elif (value <= min_value and self.time_up_flg ==0 ):
                    min_value = value
                    min_move = move

        best=min_move
        start_posn=best[0]
        end_posn=best[1]
		#Get Row and Column number for start and end position for given move
        start_row=(b.get_row(int(start_posn))^7)
        start_col=(b.get_col(int(start_posn))^7)
        end_row=(b.get_row(int(end_posn))^7)
        end_col=(b.get_col(int(end_posn))^7)

        print("I would recommend moving the", b.square[start_posn].name, "at row" ,start_row+1, " column", start_col+1 ,"to row", end_row+1," column " ,end_col+1, "...")

		#Make actual move
        b.make_move(min_move[0],min_move[1],min_move[2])
		#Retrun board after move
        return b

   ########################################################################


import numpy as np
import pandas as pd
import tkinter as tk
from tkinter import ttk
from pandastable import Table
from tkinter import *
import tkinter.messagebox as messagebox
import warnings
warnings.filterwarnings("ignore")

data=pd.read_csv('ratings.csv')
#data.head(10)
Movie_genre=pd.read_csv('moviesData.csv')
#Movie_genre.head(10)
data=data.merge(Movie_genre,on='MovieID',how='left')
#data.head(10)
Average_ratings=pd.DataFrame(data.groupby('MovieTitle')['Rating'].mean())
#print(Average_ratings.head(10))
Average_ratings['Total_rating']=pd.DataFrame(data.groupby('MovieTitle')['Rating'].count())
#print(Average_ratings.head(10))
MovieUser=data.pivot_table(index='UserID',columns='MovieTitle',values='Rating')
#print(MovieUser.head(10))

window=tk.Tk()
window.title('Movie Recommendation')
window.geometry('600x600')

df=pd.read_csv('movies.csv')
df.sort_values('MovieTitle',inplace=True)
val=[]
val=df['MovieTitle'].values.tolist()

def selectedFunction():
    l2.configure(text=ComboGrp1.get())
    v=l2.cget('text')
    correlations=MovieUser.corrwith(MovieUser[v])#compute pairwise correlation between rows and columns.
    #print(correlations.head(20))
    recommendation=pd.DataFrame(correlations,columns=['CORRELATION'])
    recommendation.dropna(inplace=True)
    recommendation=recommendation.join(Average_ratings['Total_rating'])
    #print(recommendation.head(10))
    rec=recommendation[recommendation['Total_rating']>100].sort_values('CORRELATION',ascending=False).reset_index()
    rec=rec.merge(Movie_genre,on='MovieTitle',how='left')
    rc=rec.head()

    frame=tk.Frame(window)
    frame.grid()

    pt=Table(frame,dataframe=rc,showstatusbar=True)
    #pt.model.df=rec.head()
    pt.show()
    #print(rec.head(10))

l1=ttk.Label(window,text='select movie name').grid(column=0,row=0)

v=tk.StringVar()
ComboGrp1=ttk.Combobox(window,width=70,textvariable=v)
ComboGrp1.grid(column=0,row=1)
ComboGrp1['values']=(val)
#ComboGrp1.current(0)

btn1=ttk.Button(window,text='submit',command=selectedFunction)
btn1.grid(column=0,row=2)
l2=ttk.Label(window)
l2.grid(column=0,row=3)

#correlations=MovieUser.corrwith(MovieUser[l2])#compute pairwise correlation between rows and columns.
#correlations.head(10)

window.mainloop()


# -*- coding: utf-8 -*-
from setuptools import setup, find_packages

import sys
import os

__version__ = "0.0.1"

# The main interface is through Pybind11Extension.
# * You can add cxx_std=11/14/17, and then build_ext can be removed.
# * You can set include_pybind11=false to add the include directory yourself,
#   say from a submodule.
#
# Note:
#   Sort input source files if you glob sources to ensure bit-for-bit
#   reproducible builds (https://github.com/pybind/python_example/pull/53)

def resolve_requirements(file):
    requirements = []
    with open(file) as f:
        req = f.read().splitlines()
        for r in req:
            if r.startswith("-r"):
                requirements += resolve_requirements(
                    os.path.join(os.path.dirname(file), r.split(" ")[1]))
            else:
                requirements.append(r)
    return requirements

requirements = resolve_requirements(
    os.path.join(os.path.dirname(__file__), "requirements.txt"))

setup(
    name='uroc',
    version='0.1',
    author='Eva-Maria Walz',
    author_email='evamaria.walz@gmx.de',
    description='Generalization of ROC curves and AUC to real-valued prediction problems',
    long_description=open('README.md').read(),
    license='MIT',
    install_requires=requirements,
    url='https://github.com/evwalz/isodisreg',
    packages=find_packages('src'),
    package_dir={'':'src'},
)


import requests
import json
from bs4 import BeautifulSoup
import json
import os
import datetime
import time

data = requests.get('https://www.worldometers.info/coronavirus/country/india/')
time.sleep(2)
soup = BeautifulSoup(data.text,'html.parser')

totalcase = soup.find('div',{'class':'maincounter-number'}).text.strip()
time.sleep(2)
deaths = soup.find_all('div',{'class':'maincounter-number'})[1].text.strip()
time.sleep(2)
recovered = soup.find_all('div',{'class':'maincounter-number'})[2].text.strip()

information = 'Country: India \n\nTotal Cases: {}\nDeaths: {}\nRecovered: {}'.format(totalcase,deaths,recovered)
# print(information)

class telegram_chatbot():

    def __init__(self):
        # self.token = self.read_token_from_config_file(config)
        self.token = '1196686551:AAHg8FCKNLZKePl7sIk0E2hMdBW1sLp3rcU'
        self.base = "https://api.telegram.org/bot{}/".format(self.token)

    def get_updates(self, offset=None):
        url = self.base + "getUpdates?timeout=100"
        if offset:
            url = url + "&offset={}".format(offset + 1)
        r = requests.get(url)
        return json.loads(r.content)

    def send_message(self, msg, chat_id):
        url = self.base + "sendMessage?chat_id={}&text={}".format(chat_id, msg)
        if msg is not None:
            requests.get(url)

    def read_token_from_config_file(self, config):
        parser = cfg.ConfigParser()
        parser.read(config)
        return parser.get('creds', 'token')

bot = telegram_chatbot()

def make_reply(msg):
    # reply = None
    if msg =="/new":
        reply = information
    else:
        reply = "Check your input"
    return reply

update_id = None
while True:
    updates = bot.get_updates(offset=update_id)
    updates = updates["result"]
    if updates:
        for item in updates:
            update_id = item["update_id"]
            try:
                message = str(item["message"]["text"])
            except:
                message = None
            from_ = item["message"]["from"]["id"]
            reply = make_reply(message)
            bot.send_message(reply, from_)


"""
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
details.

                         Installer for WeeWX-WD

Version: 2.1.3                                          Date: 15 February 2021

Revision History
    15 February 2021    v2.1.3
        - no change, version number change only
    17 November 2020    v2.1.2
        - no change, version number change only
    11 November 2020    v2.1.1
        - no change, version number change only
    1 November 2020     v2.1.0
        - revert required WeeWX version from 4.0.0 to 3.4.0
    30 August 2020      v2.0.1
        - changed 'enabled' config option to 'enabled'
    20 August 2020      v2.0.0
        - WeeWX 3.2+/4.x python2/3 compatible
        - revised Databases and DataBindings config options to support wdSchema
          and wd supp database
        - added new WdSuppArchive service
        - skins now include the enabled config option
        - wdPWS skin disabled by default
        - added sunshine_threshold config option and Supplementary stanza to
          WeeWX-WD config stanza to support WeeWX-WD supplementary data
        - added new file wdschema.py
        - removed no longer used file wd_database
        - renamed various install files
        - reformatted these comments
        - removed SteelGauges skin
        - added new [[[WU]]], [[[DS]]] and [[[File]]] stanzas to [[Supplementary]]

Previous Bitbucket revision history
    31 March 2017       v1.0.3
        - no change, version number change only
    14 December 2016    v1.0.2
        - no change, version number change only
    30 November 2016    v1.0.1
        - minor formatting changes/fix typos
        - add weewx version check
        - add default units and date settings to weewx.conf as applicable
        - added wd_database utility
    10 December 2014    v1.0.0a2
        - set default HTML_ROOT to WD
        - initial cut of readme.txt, added steps to override units, date
          format and HTML_ROOT on a per skin basis in weewx.conf
    8 December 2014     v1.0.0a1
        - initial implementation
"""

# python imports
from distutils.version import StrictVersion

# WeeWX imports
import weewx

from setup import ExtensionInstaller

REQUIRED_VERSION = "3.4.0"
WEEWX_WD_VERSION = "2.1.3"

def loader():
    return WeewxWdInstaller()

class WeewxWdInstaller(ExtensionInstaller):
    def __init__(self):
        if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION):
            msg = "%s requires WeeWX %s or greater, found %s" % ('WeeWX-WD ' + WEEWX_WD_VERSION,
                                                                 REQUIRED_VERSION,
                                                                 weewx.__version__)
            raise weewx.UnsupportedFeature(msg)
        super(WeewxWdInstaller, self).__init__(
            version=WEEWX_WD_VERSION,
            name='WeeWX-WD',
            description='WeeWX support for Weather Display Live and Carter Lake/Saratoga weather web site templates.',
            author="Gary Roderick",
            author_email="gjroderick<@>gmail.com",
            process_services=['user.wd.WdWXCalculate'],
            archive_services=['user.wd.WdArchive',
                              'user.wd.WdSuppArchive'],
            config={
                'StdReport': {
                    'wdPWS': {
                        'enable': 'False',
                        'skin': 'PWS',
                        'HTML_ROOT': 'WD',
                        'Units': {
                            'Groups': {
                                'group_pressure': 'hPa',
                                'group_rain': 'mm',
                                'group_rainrate': 'mm_per_hour',
                                'group_speed': 'km_per_hour',
                                'group_speed2': 'km_per_hour2',
                                'group_temperature': 'degree_C'
                            },
                        },
                    },
                    'wdStackedWindRose': {
                        'skin': 'StackedWindRose',
                        'enable': 'True',
                        'HTML_ROOT': 'WD',
                        'Units': {
                            'Groups': {
                                'group_speed': 'km_per_hour',
                                'group_speed2': 'km_per_hour2'
                            },
                            'TimeFormats': {
                                'date_f': '%d/%m/%Y',
                                'date_time_f': '%d/%m/%Y %H:%M'
                            },
                        },
                    },
                    'wdTesttags': {
                        'skin': 'Testtags',
                        'enable': 'True',
                        'HTML_ROOT': 'WD',
                        'Units': {
                            'Groups': {
                                'group_altitude': 'foot',
                                'group_degree_day': 'degree_C_day',
                                'group_pressure': 'hPa',
                                'group_rain': 'mm',
                                'group_rainrate': 'mm_per_hour',
                                'group_speed': 'km_per_hour',
                                'group_speed2': 'km_per_hour2',
                                'group_temperature': 'degree_C'
                            },
                            'TimeFormats': {
                                'date_f': '%d/%m/%Y',
                                'date_time_f': '%d/%m/%Y %H:%M'
                            },
                        },
                    },
                    'wdClientraw': {
                        'skin': 'Clientraw',
                        'enable': 'True',
                        'HTML_ROOT': 'WD',
                        'Units': {
                            'StringFormats': {
                                'degree_C': '%.1f',
                                'degree_compass': '%.0f',
                                'foot': '%.0f',
                                'hPa': '%.1f',
                                'km': '%.1f',
                                'knot': '%.1f',
                                'mm': '%.1f',
                                'percent': '%.0f',
                                'uv_index': '%.1f',
                                'watt_per_meter_squared': '%.0f',
                                'NONE': '--'
                            },
                        },
                    }
                },
                'DataBindings': {
                    'wd_binding': {
                        'database': 'weewxwd_sqlite',
                        'table_name': 'archive',
                        'manager': 'weewx.manager.DaySummaryManager',
                        'schema': 'user.wdschema.weewxwd_schema'
                    },
                    'wdsupp_binding': {
                        'database': 'wd_supp_sqlite',
                        'table_name': 'supp',
                        'manager': 'weewx.manager.Manager',
                        'schema': 'user.wdschema.wdsupp_schema'
                    }
                },
                'Databases': {
                    'weewxwd_sqlite': {
                        'database_type': 'SQLite',
                        'database_name': 'weewxwd.sdb'
                    },
                    'wd_supp_sqlite': {
                        'database_type': 'SQLite',
                        'database_name': 'wdsupp.sdb'
                    },
                    'weewxwd_mysql': {
                        'database_type': 'MySQL',
                        'database_name': 'weewxwd'
                    },
                    'wd_supp_mysql': {
                        'database_type': 'MySQL',
                        'database_name': 'wdsupp'
                    }
                },
                'Weewx-WD': {
                    'data_binding': 'wd_binding',
                    'sunshine_threshold': '120',
                    'Supplementary': {
                        'data_binding': 'wdsupp_binding',
                        'WU': {
                            'api_key': 'replace_me',
                            'enable': 'False'
                        },
                        'DS': {
                            'api_key': 'replace_me',
                            'enable': 'False'
                        },
                        'File': {
                            'file': '/path/and/filename',
                            'enable': 'False'
                        }
                    }
                }
            },
            files=[('bin/user', ['bin/user/stackedwindrose.py',
                                 'bin/user/wdastro.py',
                                 'bin/user/wdschema.py',
                                 'bin/user/wdsearchlist.py',
                                 'bin/user/wdtaggedstats.py',
                                 'bin/user/wd.py']),
                   ('skins/Clientraw', ['skins/Clientraw/clientraw.txt.tmpl',
                                        'skins/Clientraw/clientrawdaily.txt.tmpl',
                                        'skins/Clientraw/clientrawextra.txt.tmpl',
                                        'skins/Clientraw/clientrawhour.txt.tmpl',
                                        'skins/Clientraw/skin.conf']),
                   ('skins/PWS', ['skins/PWS/weewx_pws.xml.tmpl',
                                  'skins/PWS/skin.conf']),
                   ('skins/StackedWindRose', ['skins/StackedWindRose/skin.conf']),
                   ('skins/Testtags', ['skins/Testtags/skin.conf',
                                       'skins/Testtags/testtags.php.tmpl']),
                   ]
            )


#Exercise 3:
#Cree un hilo que genere números aleatorios entre 1 y 100 y los vaya insertando en una lista,
#y otro que recorra circularmente esa lista y sustituya los números terminados en cero por el valor -1.
#Un tercer hilo abortará los otros dos en el momento en el que la suma de los elementos de la lista
#supere el valor de 20000

import random
import threading
import time

def generate_numbers(lst, stop_event):
    while not stop_event.is_set():
        number = random.randint(1, 100)
        lst.append(number)
        time.sleep(0.1)

def replace_numbers(lst, stop_event):
    index = 0
    while not stop_event.is_set():
        if lst:
            if lst[index] % 10 == 0:
                lst[index] = -1
            index = (index + 1) % len(lst)
        time.sleep(0.1)
def stop_threads(lst, stop_event):
    while not stop_event.is_set():
        if sum(lst) > 20000:
            stop_event.set()
            print(f"Lista: {lst}")
            print("Ya ha llegado a los 20000")

if __name__ == "__main__":
    my_list = []
    stop_event = threading.Event()

    generate_thread = threading.Thread(target=generate_numbers, args=(my_list, stop_event))
    replace_thread = threading.Thread(target=replace_numbers, args=(my_list, stop_event))
    stop_thread = threading.Thread(target=stop_threads, args=(my_list, stop_event))

    generate_thread.start()
    replace_thread.start()
    stop_thread.start()

    generate_thread.join()
    replace_thread.join()
    stop_thread.join()


class Solution:
    def findMedianSortedArrays(self, nums1, nums2) -> float:
        for num in nums2:
            nums1.append(num)
        nums1.sort()

        if len(nums1) > 1:
            x = 0
            for num in nums1:
                x = x + num
            output = x / len(nums1)
        elif len(nums1) == 1:
            output = nums1[0]
        elif len(nums1) == 0:
            output = "Error - no values found."

        print(output)

s = Solution()
s.findMedianSortedArrays([1, 3, 5, 6, 10], [4, 6, 7, 8])


from ..search import Search

import threading
import subprocess
import markdown
import logging

import codecs
import os, json
from datetime import datetime

from werkzeug.contrib.fixers import ProxyFix
from flask import Flask, request, redirect, url_for, render_template, flash, jsonify
from flask import Markup
from flask_dance.contrib.github import make_github_blueprint, github

"""
Centillion Flask: Index Task

Define a class to handle updating the search index.

This class spawns a new thread to collect
information from the respective API and use
it to update the search index in the background.

IMPORTANT: This class is the glue between the
webapp and search submodules.
"""

class UpdateIndexTask(object):
    def __init__(self, app_config, run_which='all'):
        self.run_which = run_which
        self.app_config = app_config
        if self.app_config['FAKEDOCS']:
            logging.info("Found FAKEDOCS = True in config file, running test update index task")
            thread = threading.Thread(target=self.test, args=())
        else:
            logging.info("Found FAKEDOCS = False in config file, running real update index task")
            thread = threading.Thread(target=self.run, args=())
        thread.daemon = True
        thread.start()

    def test(self):
        """
        Run the test update index method to populate the
        search index with fake documents.
        """
        # Load the search index
        search = Search(self.app_config["INDEX_DIR"])

        # Update the index with fake docs
        search.test_update_index(self.run_which,
                                 self.app_config)

    def run(self):
        """Run the actual update index task against live APIs.
        """

        # Load API credentials
        if self.app_config['GOOGLE_DRIVE_ENABLED'] and 'GOOGLE_DRIVE_CREDENTIALS' not in os.environ:
            # path to json file containing google drive credentials
            k = 'GOOGLE_DRIVE_CREDENTIALS_FILE'
            if k in self.app_config.keys():
                self.gdrive_token_path = self.app_config[k]
            else:
                self.gdrive_token_path = 'credentials.json'

        else:
            self.gdrive_token_path = ''

        if self.app_config['GITHUB_ENABLED']:
            self.gh_token = self.app_config['GITHUB_TOKEN']
        else:
            self.gh_token = ''

        if self.app_config['DISQUS_ENABLED']:
            self.disqus_token = self.app_config['DISQUS_TOKEN']
        else:
            self.disqus_token = ''

        # Note that you need SOMETHING enabled...
        if (not self.app_config['GOOGLE_DRIVE_ENABLED'] ) \
            and (not self.app_config['GITHUB_ENABLED'] ) \
            and (not self.app_config['DISQUS_ENABLED'] ):
                raise Exception("Error: Google Drive, Github, and Disqus all disabled.")

        # Load the search index
        search = Search(self.app_config["INDEX_DIR"])

        # Update the index with real docs
        search.update_index(self.gdrive_token_path,
                            self.gh_token,
                            self.disqus_token,
                            self.run_which,
                            self.app_config)


from unittest import TestCase
from PMD.parser.movie_parser import *

class TestMoviesParser(TestCase):
    def test_get_path_name(self):
        self.assertRaises(TypeError, get_path_name, 1)

        file1 = './Epoka Lodowcowa/Epoka Lodowcowa.avi'
        file2 = 'Kły/1x2.mp4'
        file3 = '1x2.mp4'

        self.assertEqual(get_path_name(file1), ('./Epoka Lodowcowa/', 'Epoka Lodowcowa.avi'))
        self.assertEqual(get_path_name(file2), ('Kły/', '1x2.mp4'))
        self.assertEqual(get_path_name(file3), ('/', '1x2.mp4'))

    def test_guessit_parser(self):
        self.assertRaises(TypeError, guessit_parser, 1)

        file1 = './Epoka Lodowcowa/Epoka Lodowcowa.avi'
        file2 = './Kły/Kły.2014.mp4'
        file3 = 'Kły/1x2.mp4'

        dict1 = {'path': './Epoka Lodowcowa/', 'episode': None, 'type': 'movie', 'title': 'Epoka Lodowcowa',
                 'file_name': 'Epoka Lodowcowa.avi', 'series': None, 'season': None, 'year': None}
        dict2 = {'file_name': 'Kły.2014.mp4', 'path': './Kły/', 'title': 'Kły', 'season': None, 'episode': None,
                 'year': 2014, 'type': 'movie', 'series': None}
        dict3 = {'path': 'Kły/', 'file_name': '1x2.mp4', 'title': 'Kły', 'season': 1, 'episode': 2,
                 'year': None, 'type': 'episode', 'series': None}

        self.assertEqual(guessit_parser(file1), Movie(**dict1))
        self.assertEqual(guessit_parser(file2), Movie(**dict2))
        self.assertEqual(guessit_parser(file3), Movie(**dict3))

    def test_movies_parser(self):
        l = ['./Epoka Lodowcowa/Epoka Lodowcowa.avi', './Kły/Kły.2014.mp4']

        dict1 = {'path': './Epoka Lodowcowa/', 'episode': None, 'type': 'movie', 'title': 'Epoka Lodowcowa',
                 'file_name': 'Epoka Lodowcowa.avi', 'series': None, 'season': None, 'year': None}
        dict2 = {'file_name': 'Kły.2014.mp4', 'path': './Kły/', 'title': 'Kły', 'season': None, 'episode': None,
                 'year': 2014, 'type': 'movie', 'series': None}

        par = movies_parser(l)

        self.assertEqual(par[0], Movie(**dict1))
        self.assertEqual(par[1], Movie(**dict2))

        print()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Oct  4 21:18:36 2023

@author: feer
"""

import numpy  as np
#import pandas as pd
from pandas import DataFrame
from IPython.display import HTML
from matplotlib import pyplot as plt
from scipy import signal
#from astropy.stats import mad_std

def periodogram(x_t, fs, N, k):
    df  = fs/N
    f   = np.linspace(0, (N-1)*df, N)
    spec = np.fft.fft( x_t, axis = 0 )
    X_f = 10 * np.log10(np.abs(k/N * spec)**2)
    return f, X_f

def periodogram_welch(x_t, fs, window):
    N = len(x_t)
    L = N//5
    D = L//2 # 50% overlap

    f,Pxx = signal.welch(x_t,
                         fs=fs,
                         window=window,
                         nperseg=L,
                         noverlap=D,
                         nfft=N,
                         average='median',
                         axis=0
                        )
    Pxx[ 0] = Pxx[ 1]
    Pxx[-1] = Pxx[-2]
    return f, Pxx

# def periodogram_smooth(X, fs, window, M, n1=0, n2=None):
#     N = len(X)
#     delta_f = fs/N
#     X = np.reshape(X, -1)
#     if n2 is None:
#         n2 = N

#     R = np.cov(X[n1:n2])
#     r = [np.fliplr(R[0,1:M-1]), R[0,0], R[0,1:M-1]]
#     M = 2*M-1
#     w = np.ones((M,1))
#     match window:
#         case 'hamming':
#             w = signal.windows.hamming(M)
#         case 'hann':
#             w = signal.windows.hann(M)
#         case 'barlett':
#             w = signal.windows.bartlett(M)
#         case 'blackman':
#             w = signal.windows.blackman(M)
#         case _:
#             w = signal.windows.boxcar(M)

#     r = np.transpose(r) * w
#     Px = np.abs(np.fft.fft(r, 1024))
#     Px[0] = Px[1]
#     f = np.arange(start = 0, stop = N, step = delta_f)

#     return f, Px

# ver spectrum psdcorrelogram
# w: ventana que va de -M a +M, con M < N-1
def blackman_tukey(x, fs, window, M = None):
    N,R,Z = x.shape
    delta_f = fs/N

    if M is None:
        M = N//5

    r_len = 2*M-1

    w = signal.windows.get_window(window, r_len)

    Px = np.zeros_like(x)

    for j in range(Z):
        for i in range(R):
            # hay que aplanar los arrays por np.correlate.
            # usaremos el modo same que simplifica el tratamiento
            # de la autocorr
            xx = x[:,i,j].ravel()[:r_len];

            r = np.correlate(xx, xx, mode='same') / r_len

            Px[:,i,j] = np.abs(np.fft.fft(r * w, n = N) ) / N

    f  = np.arange(start = 0, stop = N, step = delta_f)

    return f, Px;

def graficar_espectro(ax, f, X_f, fs, *args, **kwargs):
    bfrec = (f <= fs/2)
#    bfrec.resize(max(len(f), len(X_f)), refcheck=False)
    X_f = 20 * np.log10(np.abs(X_f)) # Lo paso a dB
    return ax.plot(f[bfrec], X_f[bfrec], *args, **kwargs);

# def graficar_espectro(x_t, fs, N, k, *args, **kwargs):
#     df  = fs/N
#     f   = np.linspace(0, (N-1)*df, N)
#     bfrec = (f <= fs/2)
#     X_f = 10 * np.log10(np.abs(k/N * np.fft.fft( x_t, axis = 0 ))**2)

#     plt.plot(f[bfrec], X_f[bfrec], *args, **kwargs)

def vertical_flaten(x):
    return x.reshape(x.shape[0], 1)

#%%
R = 200  # 200 repeticiones o realizaciones
N = 1000 # nº de muestras

# frec. de sampling normalizada
fs = N
delta_f = fs/N

# Desplazamiento en frecuencia de cada realización
fr = np.random.uniform(-1/2, 1/2, size=(1,R,1))

# Frecuencia central normalizada: pi/2 - es equivalente a fs/4
W0 = fs/4
W1 = W0 + fr

snr_dB = np.array([ 3., 10. ], dtype=np.float64)
var_noise  = 10 ** (snr_dB / (-10)) # varianza (potencia)
noise = np.random.normal(loc=0.0, scale=np.sqrt(var_noise), size=(N,R,2))

a1 = np.sqrt(2) # amplitud normalizada

end = N / fs

n = np.linspace(start=0, stop=end, num = N, endpoint = False).reshape((N,1,1))

x  = a1 * np.sin(2*np.pi * W1 * n) + noise

# Espectros
window='bartlett'
f,  X_welch_f = periodogram_welch(x, fs, window=window)
f2, X_BT_f = blackman_tukey(x, fs, window=window)
#f2, X_BT_f = periodogram_smooth(x, fs, window=window, M=N//5)

#%%
#-------------------------------------------------------------------------------

fig = plt.figure(1)
fig.clf()
axis = fig.subplots(2,1, sharex=True)

for i, ax in enumerate(axis):
    #fig.xticks(np.linspace(0, 500, 5), minor=False)
    ax.set_xticks(np.arange(W0-10, W0+10+1), minor=True)
    ax.grid(which='major', alpha=0.7)
    ax.grid(which='minor', alpha=0.3)

    *line, = graficar_espectro(ax, f, X_welch_f[:,:,i], fs, 'o--g', linewidth=1)
    line[0].set_label('welch')

    graficar_espectro(ax, f, np.median(X_welch_f[:,:,i], axis=1), fs, 'b--',
                      linewidth=1, label='welch median')

    *line, = graficar_espectro(ax, f2, X_BT_f[:,:,i], fs, 'x-r', linewidth=1)
    line[0].set_label('blackman tukey')

    ax.set_title('Periodogramas (window='+window+', SNR='+str(int(snr_dB[i]))+')')
    ax.set_ylabel('Amplitud [dB]')
    ax.legend()
    ax.set_ylim([-100,  0])

axis[0].set_xlim([W0-20, W0+20])
axis[1].set_xlabel('f [Hz]')
fig.show()

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

#%%
# Estimacion de frecuencia W1
W1_est_welch = f[  np.argmax(X_welch_f [f  <= fs/2], axis=0) ]
W1_est_BT    = f2[ np.argmax(X_BT_f    [f2 <= fs/2], axis=0) ]

W1_est_welch_median = np.median(W1_est_welch, axis=0)
W1_est_welch_bias   = W1_est_welch_median - np.median(W1)
W1_est_welch_var    = np.var(W1_est_welch, axis=0)

W1_est_BT_median = np.median(W1_est_BT, axis=0)
W1_est_BT_bias   = W1_est_BT_median - np.median(W1)
W1_est_BT_var    = np.var(W1_est_BT, axis=0)

nbins = 5; rang = (W0-2.5,W0+2.5); alpha = 0.5

fig = plt.figure(2)
fig.clf()
axis = fig.subplots(2,1, sharex=True)

for i, ax in enumerate(axis):
    ax.hist(W1_est_welch[:,i], bins=nbins, range=rang, alpha=alpha, label='welch', align='mid')
    ax.hist(W1_est_BT[:,i],    bins=nbins, range=rang, alpha=alpha, label='BT',    align='mid')
    ax.axvline(W0, linestyle='--', color='black', label='real')
    ax.set_title('Histograma para frecuencia, SNR='+str(int(snr_dB[i])))
    ax.set_ylabel('n° de muestras')
    ax.legend();

ax.set_xlabel('Frecuencia [Hz]')
#fig.set_figheight(6)
#fig.set_figwidth(10)
fig.show()

#%%

variability_welch_est = W1_est_welch_var / (W1_est_welch_median**2)
variability_BT_est = W1_est_BT_var / (W1_est_BT_median**2)

variability = np.array((variability_welch_est, variability_BT_est)).T

# L = N//5
# D = L//2
# K = 2*N/L-1
# variability_welch = 9/(8*K)

df = DataFrame(variability, columns=['$i_{W}$', '$i_{BT}$'],
                index=[
                          '3 dB',
                          '10 dB',
                      ])

# # Dict used to center the table headers
# d = dict(selector="th",
#     props=[('text-align', 'center')])

# # Style
# s = df.style.set_properties(**{'width':'10em', 'text-align':'center'})\
#       .set_table_styles([d])

HTML(df.to_html(classes="table",justify="center"))


# author wukat
'''
A googol (10^100) is a massive number: one followed by one-hundred zeros;
100^100 is almost unimaginably large: one followed by two-hundred zeros.
Despite their size, the sum of the digits in each number is only 1.

Considering natural numbers of the form, a^b, where a, b < 100, what
is the maximum digital sum?
'''

def sum_of_digits(num):
	return sum(map(lambda dig: ord(dig) - ord("0"), str(num)))

if __name__ == '__main__':
	max_so_far = 0
	for a in range(1, 100):
		for b in range(1, 100):
			temp = sum_of_digits(a ** b)
			if temp > max_so_far:
				max_so_far = temp
	print(max_so_far)