from sqlalchemy.engine import create_engine
from sqlalchemy.orm import sessionmaker, joinedload
from models import Email, Record, Adress, Phone
from sqlalchemy import and_
from sqlalchemy.schema import MetaData
from sqlalchemy import or_

def look_up_DB (text):
    engine = create_engine("sqlite:///cli_bot.db")
    Session = sessionmaker(bind=engine)
    session = Session()

    """
    SELECT r.name, r.created, p.phone_name
    FROM records r
    LEFT JOIN phones p ON r.id = p.rec_id
    """
    # result = session.query\
    #     (Record.name, Record.created, Phone.phone_name, Email.email_name) \
    #     .select_from(Record)\
    #     .join(Email) \
    #     .join(Adress) \
    #     .join(Phone).all()
    #
    # print (result)
    query_list = [(Record.name, Record.id), (Record.created, Record.id), (Email.email_name, Email.rec_id),\
                  (Adress.adress_name, Adress.rec_id), (Phone.phone_name, Phone.rec_id)]
    for item in query_list:

        if session.query(item[0]).all():
            #print(session.query(item[0], item[1]).all())
            rec_id = session.query(item[1]).all()
            #print(f'rec_id = {rec_id}')

            for outer in session.query(item[0], item[1]).all():
                #print (outer[0])

                if type(outer[0]) != str:
                    lookup_res = outer[0].strftime('%A %d %B %Y')
                else:
                    lookup_res = outer[0]

                if lookup_res.lower().find(text.lower()) >= 0:
                    print(
                        f'Looked up text was found in next statement: "{lookup_res}" in record: "{session.query(Record.name).filter(Record.id == outer[1]).first()[0]}"')

"""
    Знайти 5 студентів з найбільшим середнім балом по всім предметам
    :return:
    """
# result = session.query
#     (Student.fullname, func.round(func.avg(Grade.grade), 2).label('avg_grade')) \
#     .select_from(Grade).\
#     join(Student).\
#     group_by(Student.id).\
#     order_by(desc('avg_grade')).\
#     imit(5).all()
# return result

# SELECT s.name_student, round (avg(g.grade), 2) AS avg_grade
# FROM grades g
# LEFT JOIN students s ON s.id = g.student_id
# GROUP BY s.id
# ORDER BY avg_grade DESC
# LIMIT 5;

def add_records_DB(name, phone):
    engine = create_engine("sqlite:///cli_bot.db")
    Session = sessionmaker(bind=engine)
    session = Session()

    phone1 = Phone(phone_name=phone)
    rec1 = Record(name=name, phone=[phone1])
    session.add(rec1)
    session.commit()
    session.close()

def change_phone_DB(name, new_phone):
    engine = create_engine("sqlite:///cli_bot.db")
    Session = sessionmaker(bind=engine)
    session = Session()

    phone1 = session.query(Phone).filter(Phone.rec_id == str(session.query(Record.id).filter(Record.name == name).first()[0]))
    phone1.update({'phone_name': new_phone})
    session.commit()
    session.close()

def add_phone_DB(name, phone):
    engine = create_engine("sqlite:///cli_bot.db")
    Session = sessionmaker(bind=engine)
    session = Session()

    phone1 = Phone(phone_name=phone, rec_id=str(session.query(Record.id).filter(Record.name == name).first()[0]))
    session.add(phone1)
    session.commit()
    session.close()

def del_phone_DB(name, phone):
    engine = create_engine("sqlite:///cli_bot.db")
    Session = sessionmaker(bind=engine)
    session = Session()

    phone1 = session.query(Phone).filter(and_(Phone.phone_name == phone, Phone.rec_id==str(session.query(Record.id).filter(Record.name == name).first()[0])))
    phone1.delete()
    session.commit()
    session.close()

def del_rec_DB(name):
    engine = create_engine("sqlite:///cli_bot.db")
    Session = sessionmaker(bind=engine)
    session = Session()

    rec1 = session.query(Record).filter(Record.name == name)
    rec1.delete()
    session.commit()
    session.close()

def add_email_DB(name, email):
    engine = create_engine("sqlite:///cli_bot.db")
    Session = sessionmaker(bind=engine)
    session = Session()

    email1 = Email(email_name=email, rec_id=str(session.query(Record.id).filter(Record.name == name).first()[0]))
    session.add(email1)
    session.commit()
    session.close()

def change_email_DB(name, new_email):
    engine = create_engine("sqlite:///cli_bot.db")
    Session = sessionmaker(bind=engine)
    session = Session()

    email1 = session.query(Email).filter(Email.rec_id == str(session.query(Record.id).filter(Record.name == name).first()[0]))
    email1.update({'email_name': new_email})
    session.commit()
    session.close()

def add_adress_DB(name, adress):
    engine = create_engine("sqlite:///cli_bot.db")
    Session = sessionmaker(bind=engine)
    session = Session()

    adress1 = Adress(adress_name=adress, rec_id=str(session.query(Record.id).filter(Record.name == name).first()[0]))
    session.add(adress1)
    session.commit()
    session.close()

def change_adress_DB(name, new_adress):
    engine = create_engine("sqlite:///cli_bot.db")
    Session = sessionmaker(bind=engine)
    session = Session()

    adress1 = session.query(Adress).filter(Adress.rec_id == str(session.query(Record.id).filter(Record.name == name).first()[0]))
    adress1.update({'adress_name': new_adress})
    session.commit()
    session.close()

#add Serhii 0675261531
# email1 = Email(email_name='jchild2008@gmail.com')
# adress1 = Adress(adress_name='Kyiv. Zodchih st.')
# phone1 = Phone(phone_name='0675261532')

#TRACK_ACTIONS

# #1 STEP - Create 'Serhii" record and add phone - 0675261531
# phone1 = Phone(phone_name='0675261531')
# rec1 = Record(name="Serhii", phone=[phone1])
# session.add(rec1)
# session.commit()

# #2 STEP - Create 'Serhii" record and add phone - 0675261531
# phone1 = Phone(phone_name='0675261531')
# rec1 = Record(name="Andrii", phone=[phone1])
# session.add(rec1)
# session.commit()

# #3 STEP - add email and adress to Serhii
#
# email1 = Email(email_name='jchild2008@gmail.com', rec_id=str(session.query(Record.id).filter(Record.name == "Serhii").first()[0]))
# adress1 = Adress(adress_name='Kyiv. Zodchih st.', rec_id=str(session.query(Record.id).filter(Record.name == "Serhii").first()[0]))
# session.add(email1)
# session.add(adress1)
# session.commit()

# #4 STEP - add same email to Serhii
#
# email1 = Email(email_name='jchild2008@gmail.com', rec_id=str(session.query(Record.id).filter(Record.name == "Serhii").first()[0]))
# session.add(email1)
# session.commit()

# #5 STEP - delete same email from Serhii
# email1 = session.query(Email).filter(Email.email_name == 'jchild2008@gmail.com')
# email1.delete()
# session.commit()

# #6 STEP - add email to Serhii again
#
# email1 = Email(email_name='jchild2008@gmail.com', rec_id=str(session.query(Record.id).filter(Record.name == "Serhii").first()[0]))
# session.add(email1)
# session.commit()

#6 STEP - update email to Serhii

# email1 = session.query(Email).filter(Email.email_name == 'jchild2008@gmail.com')
# email1.update({'email_name': 'super@gmail.com'})
# session.commit()

if __name__ == '__main__':
    # add_records_DB('Andrii', '888888888')
    # change_phone_DB('Bumba', '111111111')
    # add_phone_DB('Bumba', '2222222222')
    # del_phone_DB('Bumba', '2222222222')
    # del_rec_DB('Andrii')
    # add_email_DB('Bumba', '1@1.1')
    # change_email_DB('Bumba', '2@2.2')
    # add_adress_DB('Bumba', 'Vinica')
    # change_adress_DB('Bumba', 'Lviv')
    look_up_DB ('11')


# EX1
# if x < y:
#     y = 0
#     x = x + 1
# else:
#     x = y

def max(a, b, c):
    if a > b and a > c:
        print(a,' is maximum among all')
    elif b > a and b > c:
        print(b, ' is maximum among all')
    else:
        print(c, ' is maximum among all')

max(30, 28, 18)

# def triangleType(a, b, c):
#     isATriangle = False
#     if (a < b + c) and\
#             (b < a + c) and\
#             (c < a + b):
#         isATriangle = True
#     if isATriangle:
#         if (a == b) and (b == c):
#             print("the triangle was a EQUILATERAL")
#         elif (a != b) and \
#                 (a != c) and \
#                 (b != c):
#             print("the triangle was a SCALENE")
#     else:
#         print("invalid")
#
# triangleType(3, 5, 8)

# def testfunc(x, y):
#     if x >= 0 and y >= 0:
#         if y*y >= x*10 and y <= math.sin(math.radians(x*30))*25:
#             if y >= math.cos(math.radians(x*40))*15:
#                 print('oooookk')
# testfunc(2, 3)

# EX2
# if (x < y):
#     y = 0
#     x = x + 1

# EX3
# if x < y:
#     return
# print(x)
# return

# EX4
# x = 0
# while (x < y):
#     y = f(x,y)
#     x = x + 1

# EX5
# for x in range(10):
#     y = f(x,y)

# a = [2 * x for x in y if x > 0 for y in z if y[0] < 3]

#

# digits = [0, 1, 5]
# a = 0
#
# for i in digits:
#     a += i
#     if i == 5:
#         print("5 in list")
#         break
# else:
#     print("out of the loop")

# try:
#     b = b + 5
# except KeyError:
#     a += 1
# except ZeroDivisionError:
#     a += 2
# else:
#     a += 3
# finally:
#     b += 1
#     a = a - b

#
# x = 0
# while(x < y):
#     y = f(x, y)
#     if(y == 0):
#         break
#     elif(y < 0):
#         y = y * 2
#         continue
#     x = x + 1


import requests
from bs4 import BeautifulSoup
import shutil
import os

res = requests.get("https://www.imdb.com/list/ls050274118/")
res = requests.get("https://www.imdb.com/list/ls063784435/")

#print(res.text)

soup = BeautifulSoup(res.text,features="html.parser")

matches = soup.findAll("div", {"class":"lister-item-image"})
for m in matches:
    print(m)
    children = m.findChildren("img" , recursive=True)
    for child in children:
        print (child['alt'])
        response = requests.get(child['src'], stream=True)
        os.mkdir('knn_examples/train/'+str(child['alt']))
        with open("knn_examples/train/"+str(child['alt']) + "/" + str(child['alt']) +".png", 'wb') as out_file:
            shutil.copyfileobj(response.raw, out_file)
        del response


import sys
import operator
import time
import numpy as np
import psi4
from simtk.openmm.app import *
from simtk.openmm import *
from simtk.unit import *

from psiomm import molecule
from psiomm import psi_omm as po
"""
This is a workflow model for using Psi4 and OpenMM together. It is meant to
represent some of the useful features in the interface.
"""

# Declare geometries
phenol = """ H      1.7344      0.1731      2.1387
  C      1.1780      0.0989      1.1986
  C      1.8626      0.0162     -0.0086
  H      2.9570      0.0254     -0.0180
  C      1.1586     -0.0783     -1.2063
  H      1.7026     -0.1432     -2.1544
  C     -0.2296     -0.0912     -1.2096
  H     -0.7855     -0.1655     -2.1508
  C     -0.9117     -0.0073      0.0125
  C     -0.2116      0.0881      1.2224
  H     -0.7442      0.1538      2.1778
  O     -2.2783     -0.0249     -0.0584
  H -2.6165 0.0372 0.8262
"""

# First, we want to make Psi-OMM Molecules
solute = molecule.Molecule.from_xyz_string(phenol)

# Assign bonds, atom types, charges (using Psi4)
solute.generate_bonds()
solute.generate_atom_types()
solute.generate_charges()

# Start to make the OpenMM objects
# Create an OpenMM topology
topology = po.make_topology(solute)

# Declare the force fields to be used
forcefield = ForceField('gaff2.xml', 'tip3p.xml')

# Generate template for the force field
po.generateTemplate(forcefield, topology, solute)

# Create positions as desired by OpenMM
coords = []
for i in range(len(solute.xyz)):
    coords.append(Vec3(solute.xyz[i][0], solute.xyz[i][1], solute.xyz[i][2]))
positions = coords*angstroms

# Add solvent
modeller = Modeller(topology, positions)
modeller.addSolvent(forcefield, numAdded=50)

# Create the OpenMM System
omm_sys = forcefield.createSystem(modeller.topology)

# Declare the integrator to be used
integrator = LangevinIntegrator(175*kelvin, 1/picosecond, 0.002*picoseconds)

# Create the OpenMM Simulation
# If you have GPUs, you should change 'Reference' to the appropriate platform e.g. 'CUDA'
simulation = Simulation(modeller.topology, omm_sys, integrator, platform=Platform.getPlatformByName('Reference'))

# Set the positions in the simulation so it knows where atoms are located
simulation.context.setPositions(modeller.positions)

# Equilibrate the geometry
simulation.step(500)

# Minimize the energy
simulation.minimizeEnergy(tolerance=2*kilojoule/mole)

# Get the updated geometry
new_z_vals, new_xyz = po.get_atom_positions(simulation.topology, simulation)

# Write the new geometry to an xyz file
po.write_traj('phenol-water_opt_geo_mm.xyz', new_z_vals, new_xyz, comment="Optimized Geometry")

# Calculate the B3LYP single point energy of this new geometry
new_mol = molecule.Molecule(new_z_vals, new_xyz)
# In between Psi4 calculations need to call clean to prevent issues
psi4.core.clean()
psi4.geometry(new_mol.to_xyz_string())
# Uncomment energy call if you want to actually calculate the energy; perhaps change adding 50 waters above to 5 to do the DFT
#psi4.energy('b3lyp-d3/sto-3g')


def get_all_firewalls(self):
        """
            This function returns a list of Firewall objects.
        """
        data = self.get_data("firewalls")
        firewalls = list()
        for jsoned in data['firewalls']:
            firewall = Firewall(**jsoned)
            firewall.token = self.token
            in_rules = list()
            for rule in jsoned['inbound_rules']:
                in_rules.append(InboundRule(**rule))
            firewall.inbound_rules = in_rules
            out_rules = list()
            for rule in jsoned['outbound_rules']:
                out_rules.append(OutboundRule(**rule))
            firewall.outbound_rules = out_rules
            firewalls.append(firewall)
        return firewalls


from PyQt5 import QtWidgets, QtCore, QtGui
Qt = QtCore.Qt

class SnippingArea(QtWidgets.QDialog):
    def __init__(self):
        super().__init__()
        self._mMouseIsDown = False

        self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.ToolTip)
        self.setFixedSize(QtWidgets.QApplication.desktop().size())
        self.setCursor(QtGui.QCursor(Qt.CrossCursor))

        self.accepted.connect(self._grabArea)

        app = QtWidgets.QApplication.instance()
        des = QtWidgets.QApplication.desktop()
        self._desk_rect = des.availableGeometry(self)
        screen = app.screens()[des.screenNumber(QtGui.QCursor.pos())]
        size = screen.geometry().size()
        self._desk_rect.setSize(size)

    def mousePressEvent(self, evt):
        if evt.button() != Qt.LeftButton:
            return
        self._mMouseCurPosition = self._mMouseDownPosition = evt.pos()
        self._mMouseIsDown = True

    def mouseReleaseEvent(self, evt):
        if evt.button() != Qt.LeftButton:
            return
        self._mMouseIsDown = False
        self._mCaptureArea
        self.accept()

    def _grabArea(self):
        app = QtWidgets.QApplication.instance()
        des = QtWidgets.QApplication.desktop()
        screen = app.screens()[des.screenNumber(QtGui.QCursor.pos())]

        m = self._mCaptureArea
        m.moveTo(m.topLeft() + screen.geometry().topLeft())

        self.img = screen.grabWindow(
            des.winId(), m.x(), m.y(), m.width(), m.height())

    def mouseMoveEvent(self, evt):
        if not self._mMouseIsDown:
            return
        self._mMouseCurPosition = evt.pos()
        self.update()
        return super().mouseMoveEvent(evt)

    def paintEvent(self, evt):
        p = QtGui.QPainter(self)
        p.setBrush(QtGui.QColor(0, 0, 0, 150))

        if self._mMouseIsDown:
            self._mCaptureArea = self._calculateArea(
                self._mMouseDownPosition, self._mMouseCurPosition)
            p.setClipRegion(QtGui.QRegion(self._desk_rect).subtracted(
                QtGui.QRegion(self._mCaptureArea)))

            p.drawRect(self._desk_rect)
            p.setPen(QtGui.QPen(Qt.red, 4, Qt.SolidLine,
                                Qt.SquareCap, Qt.MiterJoin))
            p.drawRect(self._mCaptureArea)
        else:
            p.drawRect(self._desk_rect)

        return super().paintEvent(evt)

    @staticmethod
    def _calculateArea(pointA, pointB):
        return QtCore.QRect(QtCore.QPoint(pointA.x() if pointA.x()
                                          <= pointB.x() else pointB.x(),
                                          pointA.y() if pointA.y()
                                          <= pointB.y() else pointB.y()),
                            QtCore.QPoint(pointA.x() if pointA.x()
                                          >= pointB.x() else pointB.x(),
                                          pointA.y() if pointA.y()
                                          >= pointB.y() else pointB.y()))

if __name__ == '__main__':
    import sys
    #######################
    # temporary fix: app crack doesnt through exception
    # https://stackoverflow.com/questions/38020020/pyqt5-app-exits-on-error-where-pyqt4-app-would-not
    sys.excepthook = lambda t, v, b: sys.__excepthook__(t, v, b)
    #######################

    app = QtWidgets.QApplication(sys.argv)

    s = SnippingArea()
    s.exec_()

    lab = QtWidgets.QLabel()
    lab.setPixmap(s.img)
    lab.show()

    app.exec_()


class Solution:
    def minimizeXor(self, num1: int, num2: int) -> int:
        """
        first I count the number of ones I have on nums2

        then starting from the most significant bit I start to assign 1 to 1s and 0 to the zeros

        if I finish my ones before finishing nums1 I fill the rest with 0

        """

        ones = (list(bin(num2)[2:])).count("1")
        num1 =  list('{:032b}'.format(num1))

        for i in range(len(num1)):
            if num1[i] == "1":
                ones -=1
                if ones == 0:
                    for j in range(i+1, len(num1)):
                        num1[j] = "0"
                    return int("".join(num1),2)
        for k in range(len(num1)-1, -1, -1):
            if num1[k] == "0":
                num1[k] = "1"
                ones -=1
            if ones <= 0:
                return int("".join(num1),2)


# На аукцији неке слике учествује n купаца. Сваки купац је понудио извесни износ новца и сви купци су
# понудили различите износе. Написати програм којим се одређује редни број купца који је понудио највећи
# износ.
#
# Улаз: Прва линија стандарног улаза садржи природан број n (1 ≤ n ≤ 1000) који представља број купаца.
# У наредних n линија налази се по један позитиван реалан број, ти бројеви представљају износе новца коју
# су понудио купци редом.
#
# Излаз: У првој линији стандарног излаза приказати редни број купца који је понудио највећи износ новца.
#
# Пример
# Улаз
# 5
# 123.23
# 234.45
# 100.23
# 345.00
# 128.80
# Излаз
# 4

n = int(input("Unesi broj kupaca na aukciji: "))

a=[float(input("Unesi iznos novca koji je ponudi kupac: ")) for i in range(n)]

maksimum =a[0]
k=1

for i in range(1,n):
    if a[i]>maksimum:
        maksimum=a[i]
        k=i+1

print("Redni broj kupca koji je ponudio najveci iznos je: ",k)


f = open("flag", "r")
flag = ""
n=0
while True:
	c = f.read(1)
	if (c == " "):
		n = n+1
		continue
	if (c == "\n"):
		flag += chr(n)
		n = 0
		continue
	break

print(flag)


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

'''
CODE >>> SINCE IN CAIXYPROMISE.
STRIVE FOR EXCELLENT.
CONSTANTLY STRIVING FOR SELF-IMPROVEMENT.

'''

import random
import string
from PIL import Image, ImageFont, ImageDraw

stri = string.ascii_letters + string.digits # creat indentify code
bg = (255,255,255)
width_height = (250,100)
str_num = 8

def get_select_len(lenth):
    content = ""
    for i in range(lenth):
        content += random.choice(stri)
    print(content)
    return content

def get_color():
    R = random.randint(0,255)
    G = random.randint(0,255)
    B = random.randint(0,255)
    return (R,G,B)

def main_photo(size,str_num,bg):

    imageTemp = Image.new("RGB",size,bg)
    font = ImageFont.truetype("font\Font_1.ttf",48)
    draw = ImageDraw.Draw(imageTemp)
    text = get_select_len(str_num)
    width, height = draw.textsize(text, font)

    offset = 2
    for i in range(str_num):
        offset += width//str_num
        position = (offset,(size[1]-height)//2+random.randint(-10,10))
        draw.text(xy = position,text = text[i],font=font,fill =get_color())

    imageFinal = Image.new("RGB",size,bg)
    pixelsFinal = imageFinal.load()
    pixelTemp = imageTemp.load()

    for y in range(0,size[1]):
        offset = random.randint(-1,1)
        for x in range(0,size[0]):
            newx = x+offset
            if newx >= size[0]:
                newx = size[0] - 1
            elif newx < 0:
                newx = 0
            pixelsFinal[newx,y] = pixelTemp[x,y]
    draw = ImageDraw.Draw(imageFinal)

    for i in range(int(size[0]*size[1]*0.07)):
        draw.point((random.randint(0,size[0]),random.randint(0,size[1])),fill=get_color())

    for i in range(8):
        start = (0,random.randint(0,size[1]-1))
        end = (size[0],random.randint(0,size[1]-1))
        draw.line([start,end],fill=get_color(),width = 1)

    for i in range(8):
        start = (-50,-50)
        end = (size[0]+10, random.randint(0,size[1]+10))
        draw.arc(start+end,0,360,fill=get_color())

    imageFinal.save("identify_CODE.jpg")
    imageFinal.show()

if __name__ == '__main__':
    main_photo(width_height,str_num,bg)


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

import urllib.request
import numpy as np
import matplotlib.pyplot as plt

# conversation constants
CELSIUS2KELVIN = 273.15
SECONDS_YEAR = (3600.0 * 24.0 * 365.0)

# constant initial data
INIT_GRAIN_RADIUS = 0.0005
INIT_LIQUID_WATER = 0.0

# constant forcing cata
FORCING_DENSITY      = 360.0
FORCING_LIQUID_ACC   = 0.0
FORCING_GRAIN_RADIUS = 0.0005

# model defintions
SOLVE_DENSITY              = 'herron1980'
SOLVE_TEMPERATURE          = 'true'
SOLVE_HEAT_CAPACITY        = 'paterson1994'
SOLVE_THERMAL_CONDUCTIVITY = 'sturm2007'
SOLVE_LIQUID               = 'bucket'
SOLVE_GRAIN_GROWTH         = 'arthern2010'

FORCING_INPUT_FILE         = './tfm_example_forcing.dat'
INITIAL_INPUT_FILE         = './tfm_example_init.dat'

SPINUP                     = -1.0

# Wilhelms, F. (2007). Density of firn core DML94C07_38. Alfred Wegener
# Institue, Helmholtz Centre for Polar and Marine Research, Bremerhaven,
# PANGAEA, https://doi.org/10.1594/PANGAEA.615180
INIT_DENS_URL = 'https://doi.pangaea.de/10.1594/PANGAEA.615180?format=textfile'
INIT_DENS_FILE = 'init_dens.dat'
INIT_DENS_COLS = [0, 1]

# Fernandoy, F., Meyer, H., Oerter, H., Wilhelms, F., Graf, W., and
# Schwander, J. (2010). Borehole temperature profile of ice core
# DML94C07_38. PANGAEA, https://doi.org/10.1594/PANGAEA.753165
INIT_TEMP_URL = 'https://doi.pangaea.de/10.1594/PANGAEA.753165?format=textfile'
INIT_TEMP_FILE = 'init_temp.dat'
INIT_TEMP_COLS = [0, 2]

# Fernandoay, F., Meyer, H., Oerter, H., Wilhelms, F., Graf, W., and
# Schwander, J. (2008). Annual means of d18O and accumulation rates of
# firn core DML09C07_38. Alfred Wegener Institute, Helmholtz Centre for
# Polar and Marine Research, Bremerhaven, PANGAEA,
# https://doi.org/10.1594/PANGAEA.704480
INIT_AGE_URL = 'https://doi.pangaea.de/10.1594/PANGAEA.704480?format=textfile'
INIT_AGE_FILE = 'init_age.dat'
INIT_AGE_COLS = [0, 2]

# Fernandoy, F., Meyer, H., Oerter, H., Wilhelms, F., Graf, W., and
# Schwander, J. (2010). Monthly mean d18O values of ice core DML94C07_38
# from 1981 to 2007. PANGAEA, https://doi.org/10.1594/PANGAEA.753171
FORCING_TEMP_URL = 'https://doi.pangaea.de/10.1594/PANGAEA.753171?format=textfile'
FORCING_TEMP_FILE = 'forcing_temp.dat'
FORCING_TEMP_COLS = [0, 1]

# Fernandoy, F., Meyer, H., Oerter, H., Wilhelms, F., Graf, W., and
# Schwander, J. (2008). Annual means of d18O and accumulation rates of
# firn core DML94C07_38. Alfred Wegener Institute, Helmholtz Centre for
# Polar and Marine Research, Bremerhaven, PANGAEA,
# https://doi.org/10.1594/PANGAEA.704480
FORCING_ACC_URL = 'https://doi.pangaea.de/10.1594/PANGAEA.704480?format=textfile'
FORCING_ACC_FILE = 'forcing_acc.dat'
FORCING_ACC_COLS = [2, 5]

def data_import(file, cols, dtype=float):

    # header identification
    f = open(file, 'r')
    header_length = 0
    for line in f:
        if ('*/' in line):
            header_length += 2
            break

        header_length += 1

    f.close()

    data = np.genfromtxt(
        file,
        skip_header=header_length,
        dtype=dtype,
        usecols=cols,
        delimiter='\t',
    )

    return data

def fix_temperature_dates(dates):

    dt = (dates[1] - dates[0])

    for n in range(len(dates) - 1):
        if (round((dates[n+1] - dates[n]), 4) != round(dt, 4)):
            dates[n+1] = dates[n] + dt

    return dates

def generate_config(solve_density, solve_temperature, solve_heat_capacity,
    solve_thermal_conductivity, solve_liquid, solve_grain_growth,
    forcing_input_file, initial_input_file, time_step, spinup):

    conf = (
        '&CONFIG\n'
        '  solve_density="%s",\n'
        '  solve_temperature="%s",\n'
        '  solve_heat_capacity="%s",\n'
        '  solve_thermal_conductivity="%s",\n'
        '  solve_liquid="%s",\n'
        '  solve_grain_growth="%s",\n'
        '  forcing_input_file="%s",\n'
        '  initial_input_file="%s",\n'
        '  time_step=%f,\n'
        '  spinup=%f\n'
        ' /\n'
    ) % (
        solve_density,
        solve_temperature,
        solve_heat_capacity,
        solve_thermal_conductivity,
        solve_liquid,
        solve_grain_growth,
        forcing_input_file,
        initial_input_file,
        time_step,
        spinup,
    )

    f = open('tfm.conf', 'w')
    f.write(conf)
    f.close()

if __name__ == '__main__':

    # download data
    urllib.request.urlretrieve(INIT_DENS_URL, INIT_DENS_FILE)
    urllib.request.urlretrieve(INIT_TEMP_URL, INIT_TEMP_FILE)
    urllib.request.urlretrieve(INIT_AGE_URL, INIT_AGE_FILE)
    urllib.request.urlretrieve(FORCING_TEMP_URL, FORCING_TEMP_FILE)
    urllib.request.urlretrieve(FORCING_ACC_URL, FORCING_ACC_FILE)

    # data import
    init_dens = data_import(
        INIT_DENS_FILE,
        cols=INIT_DENS_COLS,
    )[::-1]
    init_temp = data_import(
        INIT_TEMP_FILE,
        cols=INIT_TEMP_COLS,
    )[::-1]
    init_age = data_import(
        INIT_AGE_FILE,
        cols=INIT_AGE_COLS,
    )[::-1]
    forcing_temp = data_import(
        FORCING_TEMP_FILE,
        cols=FORCING_TEMP_COLS,
        dtype=str,
    )[::-1]
    forcing_acc = data_import(
        FORCING_ACC_FILE,
        cols=FORCING_ACC_COLS,
    )[::-1]

    # data conversation initial density
    init_dens[:,0] *= -1.0

    # data conversation initial temperature
    init_temp[:,0] *= -1.0
    init_temp[:,1] += CELSIUS2KELVIN

    # data conversation initial age
    init_age[:,0] *= -1.0
    init_age[:,1] = -(init_age[:,1] - init_age[-1,1]) * SECONDS_YEAR

    # data conversations forcing temperature
    forcing_temp = forcing_temp[1:]

    forcing_temp_date = [date.split('-') for date in forcing_temp[:,0]]
    forcing_temp_date = [
        float(date[0]) + float(date[1]) / 12.0 for date in forcing_temp_date
    ]
    forcing_temp_date = fix_temperature_dates(forcing_temp_date)
    forcing_temp_temp = forcing_temp[:,1].astype(float) + CELSIUS2KELVIN

    forcing_temp = np.array([forcing_temp_date, forcing_temp_temp]).transpose()

    # data conversations forcing accumulation
    forcing_acc[:,1] = forcing_acc[:,1] / 1000.0 / SECONDS_YEAR

    # interpolate inital temperature and age data to inital density data
    min_depth = max([
        min(init_dens[:,0]),
        min(init_temp[:,0]),
        min(init_age[:,0]),
    ])
    max_depth = min([
        max(init_dens[:,0]),
        max(init_temp[:,0]),
        max(init_age[:,0]),
    ])

    mask = np.logical_and(
        (init_dens[:,0] >= min_depth),
        (init_dens[:,0] <= max_depth),
    )
    init_dens = init_dens[mask,:]

    mask = np.logical_and(
        (init_temp[:,0] >= min_depth),
        (init_temp[:,0] <= max_depth),
    )
    init_temp = init_temp[mask,:]
    interp_temp = np.interp(
        init_dens[:,0],
        init_temp[:,0], init_temp[:,1],
    )

    mask = np.logical_and(
        (init_age[:,0] >= min_depth),
        (init_age[:,0] <= max_depth),
    )
    init_age = init_age[mask,:]
    interp_age = np.interp(
        init_dens[:,0],
        init_age[:,0], init_age[:,1],
    )

    # interpolate accumulation data to temperature data
    min_time = max([min(forcing_temp[:,0]), min(forcing_acc[:,0])])
    max_time = min([max(forcing_temp[:,0]), max(forcing_acc[:,0])])

    mask = np.logical_and(
        (forcing_temp[:,0] >= min_time),
        (forcing_temp[:,0] <= max_time),
    )
    forcing_temp = forcing_temp[mask,:]

    mask = np.logical_and(
        (forcing_acc[:,0] >= min_time),
        (forcing_acc[:,0] <= max_time),
    )
    forcing_acc = forcing_acc[mask,:]

    interp_acc = np.interp(
        forcing_temp[:,0],
        forcing_acc[:,0], forcing_acc[:,1],
    )

    # assemble init data
    init_depth        = init_dens[:,0]
    init_dens         = init_dens[:,1]
    init_temp         = interp_temp
    init_grain_radius = np.ones_like(init_depth) * INIT_GRAIN_RADIUS
    init_liquid_water = np.ones_like(init_depth) * INIT_LIQUID_WATER
    init_age          = interp_age

    init = np.array([
        init_depth,
        init_dens,
        init_temp,
        init_grain_radius,
        init_liquid_water,
        init_age,
    ]).transpose()

    np.savetxt(INITIAL_INPUT_FILE, init)

    # assemble final forcing data
    time_step = round(np.mean(abs(np.diff(forcing_temp[:,0]))) * SECONDS_YEAR)

    forcing_world_time   = forcing_temp[:,0]
    forcing_model_time   = np.arange(len(forcing_world_time)) * time_step
    forcing_temp         = forcing_temp[:,1]
    forcing_dens         = np.ones_like(interp_acc) * FORCING_DENSITY
    forcing_solid_acc    = interp_acc
    forcing_liquid_acc   = np.ones_like(interp_acc) * FORCING_LIQUID_ACC
    forcing_grain_radius = np.ones_like(interp_acc) * FORCING_GRAIN_RADIUS

    forcing = np.array([
        forcing_world_time,
        forcing_model_time,
        forcing_temp,
        forcing_dens,
        forcing_solid_acc,
        forcing_liquid_acc,
        forcing_grain_radius,
    ]).transpose()

    np.savetxt(FORCING_INPUT_FILE, forcing)

    # configuration file generation
    generate_config(
        SOLVE_DENSITY,
        SOLVE_TEMPERATURE,
        SOLVE_HEAT_CAPACITY,
        SOLVE_THERMAL_CONDUCTIVITY,
        SOLVE_LIQUID,
        SOLVE_GRAIN_GROWTH,
        FORCING_INPUT_FILE,
        INITIAL_INPUT_FILE,
        time_step,
        SPINUP,
    )


# Реализовать функцию которая возвращает дату недельной давности от текущего момента времени.
from datetime import datetime, timedelta

def date_week_before():
    today = datetime.now()
    week = timedelta(7)
    week_before = today - week
    return week_before

if __name__ == "__main__":
    print(date_week_before())


from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return '''

Hello I'm Saki!

    '''

if __name__ == '__main__':
    app.run(debug=True)


def accueil():
    """ Affiche la page d'accueil du QCM.

    Entrée: Rien
    Sortie: Rien
    """
    print('\

Bonjour !
\r\n\

Veuillez entrer votre nom.
\r\n\
          \
          <form action="/cgi-bin/hello_get.py" method="post">\r\n\
          Prénom: <input type="text" name="prenom">
\r\n\
          Nom: <input type="text" name="nom" />

\r\n\
          \
          <input type="submit" value="Démarrer le QCM" />\r\n\
          </form>\
        ')

def affiche_question(numero):
    """ Affiche la question de numéro donné du QCM.

    Entrée: entier
    Sortie: Rien
    """
    print('\
        ')


import pandas as pd

from typing import Any, Dict, List, Union

def profiler_continuous_variable(series: pd.Series) -> Dict[str, float]:
    """Computes some metadata from the series of values of a continuous variable (i.e., feature/column).

    Parameters
    ----------
    series : pd.Series
        The series of values of a continuous variable (i.e., feature/column).

    Returns
    -------
    Dict[str, float]:
        A dictionary with the minimum, the maximum, the mean, the median, the standard deviation, the skewness, and
        the kurtosis values of the given pandas Series (i.e., variable/feature/column).
    """
    if not str(series.dtypes).startswith("int") and not str(series.dtypes).startswith("float"):
        raise ValueError("Expecting a pandas Series of integers or floating points numbers "
                         f"but got: {series.dtypes}.")
    return {
        "min": series.min(),
        "max": series.max(),
        "mean": series.mean(),
        "median": series.median(),
        "std": series.std(),
        "skewness": series.skew(),
        "kurtosis": series.kurtosis()
    }

def profiler_discrete_variable(series: pd.Series) -> Dict[Any, int]:
    """Computes some metadata from the series of values of a discrete variable (i.e., feature/column).

    Parameters
    ----------
    series : pd.Series
        The series of values of a discrete variable (i.e., feature/column).

    Returns
    -------
    Dict[Any, int]:
        A dictionary with the values counts of the given pandas Series (i.e., variable/feature/column).
    """
    return {value: count for value, count in series.value_counts().items()}

def profiler(
        df: pd.DataFrame,
        discrete_vars: Union[List[str], List[int]] = []) -> Union[Dict[str, Dict[str, Any]], Dict[int, Dict[str, Any]]]:
    """Computes some metadata for each variable (i.e., feature/column) of the given pandas DataFrame (i.e., `df`).

    Parameters
    ----------
    df : pd.DataFrame
        The data from which the metadata will be computed.
    discrete_vars : Union[List[str], List[int]]
        The list of discrete variables (i.e., features/columns) of the given pandas DataFrame (i.e., `df`).

    Returns
    -------
    Union[Dict[str, Dict[str, Any]], Dict[int, Dict[str, Any]]]:
        A dictionary with some metadata concerning the values distribution of each variable (i.e., feature/column)
        of the given pandas DataFrame (i.e., `df`).
    """
    if not set(discrete_vars).issubset(df.columns):
        raise ValueError("At least one variable of the given set of discrete variables (i.e., features/columns) "
                         "is NOT a variable (i.e., is NOT a feature/column) of the given pandas DataFrame.")
    return {
        variable: profiler_discrete_variable(series=df[variable]) if variable in discrete_vars
        else profiler_continuous_variable(series=df[variable]) for variable in df.columns
    }


import random
from transformers import BertTokenizerFast
import sys
import os
import torch
import time
from torch.utils.data import Dataset, DataLoader
import torch.nn as nn
import time
from tqdm import trange, tqdm
from torch.optim import Adam
from transformers import BertModel
from model import MySQUAD
from dataset import BertDataset
import collections
import json
import string
import re
import numpy as np
from validation import model_eval, get_metric_info, get_metrics, print_metrics

def get_data_from_json():
  with open('train-v2.0.json') as f:
    data = json.load(f)
    data = data["data"]
    return data

# preprocessing
def preprocess(data):
  answers = []
  contexts = []
  questions = []
  for article in data:
      for paragraph in article['paragraphs']:
          #looking at each context
          context = paragraph['context']
          for qas in paragraph['qas']:
              question = qas['question']
              #check if question is impossible
              #if not
              if qas['answers']!=[]:
                for answer in qas['answers']:
                    answers.append(answer)
                    contexts.append(context)
                    questions.append(question)
              #if it is impossible
              else:
                answers.append({"text": ""})
                contexts.append(context)
                questions.append(question)

  for answer, context in zip(answers, contexts):
    #if the question is unanswerable
    if len(answer.keys())==1:
      #set the start after the end
      answer['answer_start'] = len(context)-1
      answer['answer_end'] = 0
    else:
      #else get answer start and end
      answer_start = answer['answer_start']
      expected_answer = answer['text']
      answer_end = answer_start + len(expected_answer)

      #took this idea from the huggingface preprocessing
      if context[answer_start:answer_end] == expected_answer:
          answer['answer_end'] = answer_end
      elif context[answer_start-1:answer_end-1] == expected_answer:
          answer['answer_end'] = answer_end - 1
          answer['answer_start'] = answer_start - 1
      elif context[answer_start-2:answer_end-2] == expected_answer:
          answer['answer_end'] = answer_end - 2
          answer['answer_start'] = answer_start - 2
  return answers, contexts, questions

#split into train and val
def split_train_val(answers, contexts, questions, p_used=0.5, p_valid=0.1):
  train_data = []
  valid_data = []
  total = len(answers)

  #only training on half
  want = int(total*p_used)

  #use random sample of indicies
  indicies = random.sample(range(0, total), want)
  num_i = len(indicies)
  num_valid_i = int(num_i*p_valid)

  #seperate
  for i in range(0,num_valid_i):
    valid_data = valid_data + [(answers[indicies[i]], contexts[indicies[i]],
                                questions[indicies[i]])]
  for i in range(num_valid_i, num_i):
    train_data = train_data + [(answers[indicies[i]], contexts[indicies[i]],
                                questions[indicies[i]])]

  train_answers, train_contexts, train_questions = zip(*train_data)
  valid_answers, valid_contexts, valid_questions = zip(*valid_data)

  return [train_answers, train_contexts, train_questions], [valid_answers,
   valid_contexts, valid_questions]

#translate the start and end char position to token position
def include_ans_start_end(tokenized, answers):
  answer_start_token_pos = []
  answer_end_token_pos = []

  #for each answer
  for idx, answer in enumerate(answers):
    a_start = answer['answer_start']
    a_end = answer['answer_end']-1
    if a_end<0: a_end = 0
    #get start and end tokens
    start_p = tokenized.char_to_token(idx, a_start)
    end_p = tokenized.char_to_token(idx, a_end)
    answer_start_token_pos.append(start_p)
    answer_end_token_pos.append(end_p)

    #truncation is true for tokenizer so check for it - huggingface docs
    if answer_end_token_pos[-1] is None:
      answer_end_token_pos[-1] = 511
    if answer_start_token_pos[-1] is None:
      answer_start_token_pos[-1] = 511

  tokenized.update({'answer_start': answer_start_token_pos, 'answer_end': answer_end_token_pos})

def train_epoch(model, train_loader, optimizer, tokenizer):
  model.train()
  total = 0
  loss = 0
  correct = 0
  total_loss = 0

  for batch in tqdm(train_loader, leave=False, desc="Training Batches"):
    #get the context, question, answers for batch
    context_batch = list(batch[0])
    question_batch = list(batch[1])
    answer_text = batch[2]
    answer_start = batch[3]
    answer_end = batch[4]
    answer_batch = [{"text": answer_text[i], "answer_start": answer_start[i]
                     , "answer_end": answer_end[i]} for i in range(len(answer_text))]

    #tokenize and add ans data
    my_batch = tokenizer(context_batch, question_batch, padding='max_length',
                         truncation=True, max_length=512)
    include_ans_start_end(my_batch, answer_batch)

    #zero the gradients
    optimizer.zero_grad()

    #make lists to tensors
    #get the inputs
    input_ids = torch.tensor(my_batch['input_ids']).to(get_device())
    start_positions = torch.tensor(my_batch['answer_start']).to(get_device())
    end_positions = torch.tensor(my_batch['answer_end']).to(get_device())
    token_type_ids = torch.tensor(my_batch['token_type_ids']).to(get_device())
    attention_mask = torch.tensor(my_batch['attention_mask']).to(get_device())

    #get the outputs
    start_output, end_output = model(input_ids, token_type_ids=token_type_ids,
                                     attention_mask = attention_mask)

    #calculate loss
    start_loss = model.compute_loss(start_output, start_positions.to(get_device()))
    end_loss = model.compute_loss(end_output, end_positions.to(get_device()))
    total_loss = start_loss + end_loss #sum the loss??

    #backward and step
    total_loss.backward()
    optimizer.step()

  print("Train Loss: ", total_loss.item())

  #training method
def my_train(epochs, model, train_loader, tokenizer, lr = 1e-4):
  optimizer = Adam(model.parameters(), lr=lr)
  times = []
  for epoch in trange(epochs, desc="Epochs"):
    print("EPOCH: ", epoch)
    train_start = time.process_time()
    train_epoch(model, train_loader, optimizer, tokenizer)
    train_end = time.process_time()
    print("Time: ", train_end - train_start)
    times.append(train_end-train_start)

# Lambda to switch to GPU if available
get_device = lambda : "cuda:0" if torch.cuda.is_available() else "cpu"

data = get_data_from_json()

answers, contexts, questions = preprocess(data)

train_d, valid_d = split_train_val(answers, contexts, questions, p_used = 0.5, p_valid = 0.1)

train_ans, train_cont, train_quest = tuple(train_d)
valid_ans, valid_cont, valid_quest = tuple(valid_d)
del train_d
del valid_d

tokenizer = BertTokenizerFast.from_pretrained('bert-base-uncased')

#get datasets
train_dataset = BertDataset(train_cont, train_quest, train_ans)
valid_dataset = BertDataset(valid_cont, valid_quest, valid_ans)

#get dataloaders
train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True)
val_loader = DataLoader(valid_dataset, batch_size=8, shuffle=True)

#start model
model = MySQUAD().to(get_device())

#train the model
torch.set_grad_enabled(True)
my_train(4, model, train_loader, tokenizer, lr = 3e-5)
torch.set_grad_enabled(False)

#save the model
model_path = os.path.join(os.getcwd(), "my_squad.pth")
model.save_model(model_path)

expected, predicted = model_eval(model, val_loader, tokenizer)

#get info got metric calcualtion
metric_info = get_metric_info(expected, predicted)
tok_info = metric_info[0]
unans_info = metric_info[1]
exact_info = metric_info[2]
num_questions = metric_info[3]

#calculate metrics
tok_metrics, unans_metrics, exact = get_metrics(tok_info, unans_info, exact_info)
tok_precision, tok_recall, tok_f1 = tok_metrics
unans_precision, unans_recal, unans_f1 = unans_metrics

#print metrics
print_metrics(tok_metrics, unans_metrics, exact, unans_info, num_questions)


from PIL import Image
import random

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
from torchvision import datasets, models, transforms
import time
import os
import copy
import logging
import sys
import configparser
import glob
from tqdm import tqdm
from dataset import LabeledDataset
from alexnet_fc7out_badnets_01 import alexnet, NormalizeByChannelMeanStd

os.environ['CUDA_LAUNCH_BLOCKING']='1'

experimentID = "0013"

clean_data_root	= "/opt/data/Imagenet"
poison_root	= "/opt/data/patched_data"
gpu         = int("0")
epochs      = int("12")
patch_size  = int("30")
eps         = int("16")
rand_loc    = "true"
trigger_id  = int("14")
num_poison  = int("400")
num_classes = int("1000")
batch_size  = int("256")
logfile     = "/data/logs/{}/finetune.log".format(experimentID)
lr			= float("0.001")
momentum 	= float("0.9")

#gpu = torch.device("cuda" if torch.cuda.is_available() else "cpu")

checkpointDir = "/scratch/yw3576/{}/finetuned_models_gpu_pretrained_01/normalize".format(experimentID)

if not os.path.exists(os.path.dirname(checkpointDir)):
	os.makedirs(os.path.dirname(checkpointDir))

#logging.info("Experiment ID: {}".format(experimentID))
print("Experiment ID: {}".format(experimentID))

# Models to choose from [resnet, alexnet, vgg, squeezenet, densenet, inception]
model_name = "densenet"

# Flag for feature extracting. When False, we finetune the whole model,
#   when True we only update the reshaped layer params
feature_extract = False

def save_checkpoint(state, filename='checkpoint.pth.tar'):
	if not os.path.exists(os.path.dirname(filename)):
		os.makedirs(os.path.dirname(filename))
	torch.save(state, filename)

trans_trigger = transforms.Compose([transforms.Resize((patch_size, patch_size)),
									transforms.ToTensor(),
									])

trigger = Image.open('/scratch/yw3576/data/triggers/trigger_{}.png'.format(trigger_id)).convert('RGB')
trigger = trans_trigger(trigger).unsqueeze(0).cuda(gpu)

def train_model(model, dataloaders, criterion, optimizer, num_epochs=25, is_inception=False):
	since = time.time()

	best_model_wts = copy.deepcopy(model.state_dict())
	best_acc = 0.0

	test_acc_arr = np.zeros(num_epochs)

	for epoch in range(num_epochs):
		adjust_learning_rate(optimizer, epoch)
		#logging.info('Epoch {}/{}'.format(epoch, num_epochs - 1))
		print('Epoch {}/{}'.format(epoch, num_epochs - 1))

		#logging.info('-' * 10)
		print('-' * 10)

		# Each epoch has a training and validation phase
		for phase in ['train', 'test']:
			if phase == 'train':
				model.train()  # Set model to training mode
			else:
				model.eval()   # Set model to evaluate mode

			running_loss = 0.0
			running_corrects = 0

			for inputs, labels in tqdm(dataloaders[phase]):

				inputs = inputs.cuda(gpu)
				labels = labels.cuda(gpu)
				# zero the parameter gradients
				optimizer.zero_grad()

				# forward
				# track history if only in train
				with torch.set_grad_enabled(phase == 'train'):
					# Get model outputs and calculate loss
					# Special case for inception because in training it has an auxiliary output. In train
					#   mode we calculate the loss by summing the final output and the auxiliary output
					#   but in testing we only consider the final output.
					if is_inception and phase == 'train':
						# From https://discuss.pytorch.org/t/how-to-optimize-inception-model-with-auxiliary-classifiers/7958
						outputs, aux_outputs = model(inputs)
						loss1 = criterion(outputs, labels)
						loss2 = criterion(aux_outputs, labels)
						loss = loss1 + 0.4*loss2
					else:
						outputs = model(inputs)
						loss = criterion(outputs, labels)

					_, preds = torch.max(outputs, 1)

					# backward + optimize only if in training phase
					if phase == 'train':
						loss.backward()
						optimizer.step()

				# statistics
				running_loss += loss.item() * inputs.size(0)
				running_corrects += torch.sum(preds == labels.data)

			epoch_loss = running_loss / len(dataloaders[phase].dataset) / nn
			epoch_acc = running_corrects.double() / len(dataloaders[phase].dataset) / nn

			#logging.info('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))
			print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))

			if phase == 'test':
				test_acc_arr[epoch] = epoch_acc
			# deep copy the model
			if phase == 'test' and (epoch_acc > best_acc):
				logging.info("Better model found!")
				best_acc = epoch_acc
				best_model_wts = copy.deepcopy(model.state_dict())

	time_elapsed = time.time() - since
	#logging.info('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))
	print('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))

	#logging.info('Max Test Acc: {:4f}'.format(best_acc))
	print('Max Test Acc: {:4f}'.format(best_acc))

	#logging.info('Last 10 Epochs Test Acc: Mean {:.3f} Std {:.3f} '
	#			 .format(test_acc_arr[-10:].mean(),test_acc_arr[-10:].std()))
	print('Last 10 Epochs Test Acc: Mean {:.3f} Std {:.3f} '
				 .format(test_acc_arr[-10:].mean(),test_acc_arr[-10:].std()))

	sort_idx = np.argsort(test_acc_arr)
	top10_idx = sort_idx[-10:]
	#logging.info('10 Epochs with Best Acc- Test Acc: Mean {:.3f} Std {:.3f} '
	#			 .format(test_acc_arr[top10_idx].mean(),test_acc_arr[top10_idx].std()))
	print('10 Epochs with Best Acc- Test Acc: Mean {:.3f} Std {:.3f} '
				 .format(test_acc_arr[top10_idx].mean(),test_acc_arr[top10_idx].std()))

	# save meta into pickle
	meta_dict = {'Val_acc': test_acc_arr
				 }

	# load best model weights
	model.load_state_dict(best_model_wts)
	return model, meta_dict

def set_parameter_requires_grad(model, feature_extracting):
	if feature_extracting:
		for param in model.parameters():
			param.requires_grad = False

def initialize_model(model_name, num_classes, feature_extract, use_pretrained=True):
	# Initialize these variables which will be set in this if statement. Each of these
	#   variables is model specific.
	model_ft = None
	input_size = 0

	if model_name == "resnet":
		""" Resnet18
		"""
		model_ft = models.resnet18(pretrained=use_pretrained)
		set_parameter_requires_grad(model_ft, feature_extract)
		num_ftrs = model_ft.fc.in_features
		model_ft.fc = nn.Linear(num_ftrs, num_classes)
		input_size = 224

	elif model_name == "alexnet":
		""" Alexnet
		"""
		model_ft = models.alexnet(pretrained=use_pretrained)
		set_parameter_requires_grad(model_ft, feature_extract)

		num_ftrs = model_ft.classifier[1].in_features
		num_ftrs_out = model_ft.classifier[4].in_features
		model_ft.classifier[1] = nn.Linear(num_ftrs,num_ftrs_out)

		num_ftrs = model_ft.classifier[4].in_features
		num_ftrs_out = model_ft.classifier[6].in_features
		model_ft.classifier[4] = nn.Linear(num_ftrs,num_ftrs_out)

		num_ftrs = model_ft.classifier[6].in_features
		model_ft.classifier[6] = nn.Linear(num_ftrs,num_classes)
		input_size = 224

	elif model_name == "vgg":
		""" VGG11_bn
		"""
		model_ft = models.vgg11_bn(pretrained=use_pretrained)
		set_parameter_requires_grad(model_ft, feature_extract)
		num_ftrs = model_ft.classifier[6].in_features
		model_ft.classifier[6] = nn.Linear(num_ftrs,num_classes)
		input_size = 224

	elif model_name == "squeezenet":
		""" Squeezenet
		"""
		model_ft = models.squeezenet1_0(pretrained=use_pretrained)
		set_parameter_requires_grad(model_ft, feature_extract)
		model_ft.classifier[1] = nn.Conv2d(512, num_classes, kernel_size=(1,1), stride=(1,1))
		model_ft.num_classes = num_classes
		input_size = 224

	elif model_name == "densenet":
		""" Densenet
		"""
		model_ft = models.densenet121(pretrained=use_pretrained)
		set_parameter_requires_grad(model_ft, feature_extract)
		num_ftrs = model_ft.classifier.in_features
		model_ft.classifier = nn.Linear(num_ftrs, num_classes)
		input_size = 224

	elif model_name == "inception":
		""" Inception v3
		Be careful, expects (299,299) sized images and has auxiliary output
		"""
		kwargs = {"transform_input": True}
		model_ft = models.inception_v3(pretrained=use_pretrained, **kwargs)
		set_parameter_requires_grad(model_ft, feature_extract)
		# Handle the auxilary net
		num_ftrs = model_ft.AuxLogits.fc.in_features
		model_ft.AuxLogits.fc = nn.Linear(num_ftrs, num_classes)
		# Handle the primary net
		num_ftrs = model_ft.fc.in_features
		model_ft.fc = nn.Linear(num_ftrs,num_classes)
		input_size = 299

	else:
		logging.info("Invalid model name, exiting...")
		exit()

	return model_ft, input_size

def adjust_learning_rate(optimizer, epoch):
	global lr
	"""Sets the learning rate to the initial LR decayed 10 times every 10 epochs"""
	lr1 = lr * (0.1 ** (epoch // 10))
	for param_group in optimizer.param_groups:
		param_group['lr'] = lr1

# Train poisoned model
print("Training model...")

# Initialize the model for this run
model_ft, input_size = initialize_model(model_name, num_classes, feature_extract, use_pretrained=True)
#logging.info(model_ft)
print(model_ft)

# Transforms
data_transforms = transforms.Compose([
		transforms.Resize((input_size, input_size)),
		transforms.ToTensor(),
		])

#logging.info("Initializing Datasets and Dataloaders...")
print("Initializing Datasets and Dataloaders...")

# Training dataset
# if not os.path.exists("data/{}/finetune_filelist.txt".format(experimentID)):

with open("/scratch/yw3576/data/{}/finetune_filelist.txt".format(experimentID), "w") as f1:

	wnid_mapping = {}
	all_wnids = sorted(glob.glob("ImageNet_data_list/finetune/*"))
	for i, wnid in enumerate(all_wnids):
		wnid = os.path.basename(wnid).split(".")[0]
		wnid_mapping[wnid] = i
		with open("ImageNet_data_list/finetune/" + wnid + ".txt", "r") as f2:
			lines = f2.readlines()
			for line in lines:
				f1.write(line.strip() + " " + str(i) + "\n")

# Test dataset
# if not os.path.exists("data/{}/test_filelist.txt".format(experimentID)):
with open("/scratch/yw3576/data/{}/test_filelist.txt".format(experimentID), "w") as f1:

	all_wnids = sorted(glob.glob("ImageNet_data_list/test/*"))
	for i, wnid in enumerate(all_wnids):
		wnid = os.path.basename(wnid).split(".")[0]
		with open("ImageNet_data_list/test/" + wnid + ".txt", "r") as f2:
			lines = f2.readlines()
			for line in lines:
				f1.write(line.strip() + " " + str(i) + "\n")

# sys.exit()
dataset_clean = LabeledDataset(clean_data_root,
							   "/scratch/yw3576/data/{}/finetune_filelist.txt".format(experimentID), data_transforms)
dataset_test = LabeledDataset(clean_data_root,
							  "/scratch/yw3576/data/{}/test_filelist.txt".format(experimentID), data_transforms)

dataloaders_dict = {}
dataloaders_dict['train'] =  torch.utils.data.DataLoader(dataset_clean, batch_size=batch_size,
														 shuffle=True, num_workers=0)
dataloaders_dict['test'] =  torch.utils.data.DataLoader(dataset_test, batch_size=batch_size,
														shuffle=True, num_workers=0)

#logging.info("Number of clean images: {}".format(len(dataset_clean)))
print("Number of clean images: {}".format(len(dataset_clean)))

# Gather the parameters to be optimized/updated in this run. If we are
#  finetuning we will be updating all parameters. However, if we are
#  doing feature extract method, we will only update the parameters
#  that we have just initialized, i.e. the parameters with requires_grad
#  is True.
params_to_update = model_ft.parameters()
#logging.info("Params to learn:")
print("Params to learn:")

if feature_extract:
	params_to_update = []
	for name,param in model_ft.named_parameters():
		if param.requires_grad == True:
			params_to_update.append(param)
			#logging.info(name)
			print(name)
else:
	for name,param in model_ft.named_parameters():
		if param.requires_grad == True:
			#logging.info(name)
			print(name)

#optimizer_ft = optim.SGD(params_to_update, lr=lr, momentum = momentum)
optimizer_ft = optim.Adam(params_to_update, lr=lr, weight_decay=1e-8)

# Setup the loss fxn
criterion = nn.CrossEntropyLoss()

normalize = NormalizeByChannelMeanStd(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
model = nn.Sequential(normalize, model_ft)
#model = model_ft
#model = nn.DataParallel(model)
model = model.cuda(gpu)

# Train and evaluate
model, meta_dict = train_model(model, dataloaders_dict, criterion, optimizer_ft,
								  num_epochs=epochs, is_inception=(model_name=="inception"))

save_checkpoint({
				'arch': model_name,
				'state_dict': model.state_dict(),
				'meta_dict': meta_dict
				}, filename=os.path.join(checkpointDir, "model_ft.pt"))


#!/bin/python3

import math
import os
import random
import re
import sys

# Complete the maxMin function below.
def maxMin(k, arr, n):
    arr.sort()
    min_unfair = 100000000000
    # take groups of k elements while updating min_unfair
    i = 0
    while i+k-1 < n:
        min_value = arr[i]
        max_value = arr[i+k-1]
        new_unfair = max_value - min_value
        if new_unfair == 0:
            return 0
        if new_unfair < min_unfair:
            min_unfair = new_unfair

        i += 1
    return min_unfair
if __name__ == '__main__':
    fptr = open(os.environ['OUTPUT_PATH'], 'w')

    n = int(input())

    k = int(input())

    arr = []

    for _ in range(n):
        arr_item = int(input())
        arr.append(arr_item)

    result = maxMin(k, arr, n)

    fptr.write(str(result) + '\n')

    fptr.close()


"""
Python implementation of Donald Knuths DLX3 algorithm
By Hayden Goodwin 2020

The following program is an implementation of Donald Knuths DLX3 algorithm.
DLX3 is an extension of DLX1 and DLX 2 where the min an max amount of times
an item is covered can be specified. It also includes the 'colour' of a node
which allows only nodes with like colours to cover the same item.

DLX3 by Knuth:
https://www-cs-faculty.stanford.edu/~knuth/programs/dlx3.w

It is recommended to have a look at the original source as it is very
well documented. Do note that the original is written in cweb and for those
unfamiliar with the language, it is a recommended to read up on it first.

"""
import functools

class Node:
    def __init__(self, up, down, item, colour):
        self.up = up
        self.down = down
        self.itm = item
        self.colour = colour

class Item:
    def __init__(self, name, prev, next, bound, slack, order):
        self.name = name
        self.prev = prev
        self.next = next
        self.bound = bound
        self.slack = slack
        self.order = order

class DLX:

    PRIMARY = 0
    SECONDARY = 1
    INFTY = 100000000
    MAX_LEVEL = 500     # Maximum depth that DLX can search
    MAX_COUNT = 10**10  # Maximum amount of solutions allowed

    def __init__(self, cols, rows):
        """
        Column Formatting:
        cols is a list of item initialising values. Each item is in the form
        of a list and should be formatted:  [name,
                                             order,
                                             lower bound,
                                             upper bound
                                             ]
        name - is a unique object (usually a string)
        order - is a 0 or 1. 0 denotes Primary, 1 denotes Secondary
        lower bound and upper bound are integers which specify the range of
        nodes allowed to cover an item.

        IMPORTANT POINTS
        - All secondary items must be at the end of the cols list
        - Only primary items have bounds
        - Only secondary items have colours
        - Minimum lower bound of 1
        - upper bound can be the same as lowerbound
        - upper bound can never be lower than lower bound

        Row Formatting:
        rows is a list of options/nodes which cover a specific item. Each
        row should be formatted: ["rowname",
                                   [(item, colour), ... ,(item,colour)]
                                   ]

        rowname - a distinct identifiable object (e.g. a string)
        item - an integer corresponding to the index of the item it covers
        colour - any positive integer value (including 0) that isnt 100.

        IMPORTANT POINTS
        - If no colour is being used, it should be specified as None.
        - The 'colour' 100 has been reserved for colourless nodes
        """

        self.updates = 0
        self.cleansings = 0

        self.itms = [Item(None, 0, 0, 0, 0, 0)]
        self.nodes = [Node(0, 0, 0, 0)]
        self.rownames = []
        self.rowid = [None] * (len(cols) + 1)
        self.second = 0 # Location of first secondary item

        # Creating the linked list of items
        cur = 1
        prev = 0
        self.root = 0
        for (name, type, low_bound, up_bound) in cols:
            slack = up_bound - low_bound
            if type == DLX.PRIMARY:   # Only primary items are linked
                self.itms.append(Item(name,
                                      prev,
                                      self.root,
                                      up_bound,
                                      slack, type))
                self.itms[prev].next = cur
                self.itms[self.root].prev = cur
                prev = cur
                self.second = cur + 1
            else:
                self.itms.append(Item(name, cur, cur, up_bound, slack, type))
            self.nodes.append(Node(cur, cur, 0, 0)) # Creating the header nodes
            cur += 1

        # Creating the linked node list
        nnindex = len(self.nodes) # Index where the new nodes will be placed
        i = 0
        j = 0
        prev = 0
        for rowname, row in rows:
            self.rownames.append(rowname)
            if not self.onlySec(row):
                self.rowid.append(j)
                self.nodes.append(Node(prev, nnindex + len(row), -i, 0))
                nnindex += 1
                prev = nnindex
                for (item, colour) in row:
                    item += 1
                    self.rowid.append(j)
                    if self.itms[item].order == DLX.SECONDARY and colour == 0:
                        colour = 100
                    elif colour == None:
                        colour = 0
                    self.nodes[item].itm += 1
                    r = self.nodes[item].up
                    self.nodes.append(Node(r, item, item, colour))
                    self.nodes[item].colour = len(self.nodes) - 1
                    self.nodes[r].down = nnindex
                    self.nodes[item].up = nnindex
                    nnindex += 1
                i+=1
            j+=1
        self.nodes.append(Node(prev, 0,-i,0))

        self.last_itm = len(self.itms)
        self.last_node = len(self.nodes) - 1

        # Other variables used while dancing
        self.partialsolution = []
        self.solutions = []
        self.level = 0
        self.nodect = 0
        self.score = 0
        self.scor = []
        self.first_tweak = []
        self.choice = []
        self.best_s = 0
        self.best_l = 0
        self.best_itm = 0
        self.count = 0
        self.maxl = 0

    def onlySec(self,row):
        for (itm , _) in row:
            if not self.itms[itm + 1].order:
                return False
        return True

    def cover(self, c, deact):
        if deact:
            L = self.itms[c].prev
            r = self.itms[c].next
            self.itms[L].next = r
            self.itms[r].prev = L

        self.updates += 1

        rr = self.nodes[c].down
        while rr >= self.last_itm:

            nn = rr + 1
            while nn != rr:
                if self.nodes[nn].colour >= 0:
                    uu = self.nodes[nn].up
                    dd = self.nodes[nn].down
                    cc = self.nodes[nn].itm

                    if cc <= 0:
                        nn = uu
                        continue

                    self.nodes[uu].down = dd
                    self.nodes[dd].up = uu
                    self.updates += 1
                    self.nodes[cc].itm -= 1
                nn += 1
            rr = self.nodes[rr].down

    def uncover(self, c, react):
        rr = self.nodes[c].down
        while rr >= self.last_itm:
            nn = rr + 1
            while nn != rr:
                if self.nodes[nn].colour >= 0:
                    uu = self.nodes[nn].up
                    dd = self.nodes[nn].down
                    cc = self.nodes[nn].itm

                    if cc <= 0:
                        nn = uu
                        continue

                    self.nodes[uu].down = nn
                    self.nodes[dd].up = nn
                    self.nodes[cc].itm += 1
                nn += 1

            rr = self.nodes[rr].down

        if react:
            L = self.itms[c].prev
            r = self.itms[c].next
            self.itms[L].next = c
            self.itms[r].prev = c

    def purify(self, p):
        cc = self.nodes[p].itm
        x = self.nodes[p].colour
        self.nodes[cc].colour = x
        self.cleansings += 1

        rr = self.nodes[cc].down
        while rr >= self.last_itm:
            if self.nodes[rr].colour != x:
                nn = rr + 1
                while nn != rr:
                    uu = self.nodes[nn].up
                    dd = self.nodes[nn].down
                    cc = self.nodes[nn].itm

                    if cc <= 0:
                        nn = uu
                        continue

                    if self.nodes[nn].colour >= 0:
                        self.nodes[uu].down = dd
                        self.nodes[dd].up = uu
                        self.updates += 1
                        self.nodes[cc].itm -= 1
                    nn += 1
            elif rr != p:
                self.cleansings += 1
                self.nodes[rr].colour = -1

            rr = self.nodes[rr].down

    def unpurify(self, p):
        cc = self.nodes[p].itm
        x = self.nodes[p].colour

        rr= self.nodes[cc].up
        while rr >= self.last_itm:
            if self.nodes[rr].colour < 0:
                self.nodes[rr].colour = x
            elif rr != p:
                nn = rr - 1
                while nn != rr:
                    uu = self.nodes[nn].up
                    dd = self.nodes[nn].down
                    cc = self.nodes[nn].itm

                    if cc <= 0:
                        nn = dd
                        continue

                    if self.nodes[nn].colour >= 0:
                        self.nodes[uu].down = nn
                        self.nodes[dd].up = nn
                        self.nodes[cc].itm += 1
                    nn -= 1
            rr = self.nodes[rr].up

    def tweak(self, n, block):
        if block:
            nn = n + 1
        else:
            nn = n

        while 1:
            if self.nodes[nn].colour >= 0:
                uu = self.nodes[nn].up
                dd = self.nodes[nn].down
                cc = self.nodes[nn].itm

                if cc <= 0:
                    nn = uu
                    continue

                self.nodes[uu].down = dd
                self.nodes[dd].up = uu
                self.updates += 1
                self.nodes[cc].itm -= 1
            if nn == n:
                break
            nn += 1

    def untweak(self, c, x, unblock):
        z = self.nodes[c].down
        self.nodes[c].down = x

        rr = x
        k = 0
        qq = c
        while rr != z:
            self.nodes[rr].up = qq
            k += 1
            if unblock:
                nn = rr + 1
                while nn != rr:
                    if self.nodes[nn].colour >= 0:
                        uu = self.nodes[nn].up
                        dd = self.nodes[nn].down
                        cc = self.nodes[nn].itm

                        if cc <= 0:
                            nn = uu
                            continue

                        self.nodes[uu].down = nn
                        self.nodes[dd].up = nn
                        self.nodes[cc].itm += 1
                    nn += 1
            qq = rr
            rr = self.nodes[rr].down
        self.nodes[rr].up = qq
        self.nodes[c].itm += k

        if not unblock:
            self.uncover(c,0)

    def forward(self):
        self.score = DLX.INFTY

        k = self.itms[self.root].next
        while k != self.root:

            s = self.itms[k].slack
            if s > self.itms[k].bound:
                s = self.itms[k].bound

            t= self.nodes[k].itm + s - self.itms[k].bound + 1
            if t <= self.score:
                if ((t < self.score)
                    or (s < self.best_s)
                    or (s == self.best_s and self.nodes[k].itm > self.best_l)):
                    self.score = t
                    self.best_itm = k
                    self.best_s = s
                    self.best_l = self.nodes[k].itm
            k = self.itms[k].next

        if self.score < DLX.INFTY:
            a =1

        if self.score <= 0:
            return self.backdown

        if self.score == DLX.INFTY:
            # New solution has been found
            self.count += 1
            self.partialsolution = []
            for i in range(self.level):
                pp = self.choice[i]
                cc = pp if pp < self.last_itm else self.nodes[pp].itm

                # Record the partial solution
                if not(pp < self.last_itm
                       or pp >= self.last_node
                       or self.nodes[pp].itm <= 0):
                    self.partialsolution.append(self.rownames[self.rowid[pp]])

            self.solutions.append(self.partialsolution)

            if self.count > DLX.MAX_COUNT:
                # Maximum amount of allowed solutions has been reached
                return None
            return self.backdown

        try:
            self.scor[self.level] = self.score
        except:
            self.scor.append(self.score)

        try:
            self.first_tweak[self.level] = 0
        except:
            self.first_tweak.append(0)

        try:
            self.choice[self.level] = self.nodes[self.best_itm].down
        except:
            self.choice.append(self.nodes[self.best_itm].down)

        self.cur_node = self.nodes[self.best_itm].down

        self.itms[self.best_itm].bound -= 1
        if (self.itms[self.best_itm].bound == 0
            and self.itms[self.best_itm].slack == 0):
            self.cover(self.best_itm,1)
        else:
            self.first_tweak[self.level] = self.cur_node
            if self.itms[self.best_itm].bound == 0:
                self.cover(self.best_itm,1)

        return self.advance

    def advance(self):
        if (self.itms[self.best_itm].bound == 0
            and self.itms[self.best_itm].slack==0):
            if self.cur_node == self.best_itm:
                return self.backup

        elif (self.nodes[self.best_itm].itm
              <= (self.itms[self.best_itm].bound
                  - self.itms[self.best_itm].slack)):
            return self.backup

        elif self.cur_node != self.best_itm:
            self.tweak(self.cur_node, self.itms[self.best_itm].bound)
        elif self.itms[self.best_itm].bound != 0:
            # deactivate best item
            p = self.itms[self.best_itm].prev
            q = self.itms[self.best_itm].next
            self.itms[p].next = q
            self.itms[q].prev = p

        if self.cur_node > self.last_itm:
            pp = self.cur_node + 1
            while pp != self.cur_node:
                cc = self.nodes[pp].itm
                if cc <= 0:
                    pp = self.nodes[pp].up
                else:
                    if cc < self.second:
                        self.itms[cc].bound -= 1
                        if self.itms[cc].bound == 0:
                            self.cover(cc,1)
                    else:
                        if not self.nodes[pp].colour:
                            self.cover(cc,1)
                        elif self.nodes[pp].colour > 0:
                            self.purify(pp)
                    pp += 1

        self.level += 1
        if self.level > self.maxl:
            if self.level >= DLX.MAX_LEVEL:
                # Maximum level has been reached
                return None
            self.maxl = self.level
        return self.forward

    def backup(self):
        if (self.itms[self.best_itm].bound == 0
            and self.itms[self.best_itm].slack == 0):
            self.uncover(self.best_itm,1)
        else:
            self.untweak(
                self.best_itm,
                self.first_tweak[self.level],
                self.itms[self.best_itm].bound
                )
        self.itms[self.best_itm].bound += 1
        return self.backdown

    def backdown(self):

        if self.level == 0:
            # All possible solutions have been found
            return None
        self.level -= 1
        self.cur_node = self.choice[self.level]
        self.best_itm = self.nodes[self.cur_node].itm
        self.score = self.scor[self.level]

        if self.cur_node < self.last_itm:
            self.best_itm = self.cur_node
            p = self.itms[self.best_itm].prev
            q = self.itms[self.best_itm].next
            self.itms[p].next= self.best_itm
            self.itms[q].prev= self.best_itm
            return self.backup

        pp = self.cur_node - 1
        while pp != self.cur_node:
            cc= self.nodes[pp].itm
            if cc <= 0:
                pp = self.nodes[pp].down
            else:
                if cc < self.second:
                    if self.itms[cc].bound == 0:
                        self.uncover(cc,1)
                    self.itms[cc].bound += 1
                else:
                    if not self.nodes[pp].colour:
                        self.uncover(cc,1)
                    elif self.nodes[pp].colour > 0:
                        self.unpurify(pp)
                pp -= 1
        self.choice[self.level] = self.nodes[self.cur_node].down;
        self.cur_node = self.nodes[self.cur_node].down

        return self.advance

    def dance(self):
        """
        Starts the dancing links program and returns a list of solutions.
        The solutions are in the form of a list of 'rownames' so it is best
        to ensure that rownames are unique so solutions are distinguishable.
        """
        def tramampoline(func):
            @functools.wraps(func)
            def g(*args):
                h = func
                while h is not None:
                    h = h(*args)
                return args
            return g()

        tramampoline(self.forward)

        return self.solutions

if __name__ == '__main__':

    items = [[str(i), 0, 1, 2] for i in range(8)]
    options = [['row1', [(0,None),(0,None),(0,None),(0,None)]],
               ['row2', [(1,None),(7,None)]],
               ['row3', [(2,None),(6,None),(1,None),(4,None),(5,None)]],
               ['row4', [(0,None)]],
               ['row5', [(3,None),(4,None),(0,None),(5,None)]],
               ['row6', [(4,None),(2,None),(0,None)]],
               ['row7', [(0,None),(1,None),(7,None),(2,None)]]
               ]

    matrix = DLX(items, options)
    solutions = matrix.dance()

    for solution in solutions:
        print(solution)


'''This actually runs everything'''

import sys, os, time
sys.path.append(os.getcwd()+'/Resources')
import ForumsToCheck, scraper, config, log_it
import necroDetector, profanityDetector, capsDetector, annoyanceAlerts
from multiprocessing import Process

def init(queue):
    global q
    q = queue

def main():
    '''() -> None
    main function, goes through the all the stuff'''
    startTime = time.time() #for science!
    log_it.logg("Starting scraping round", q, genus=["debug"])
    scrapeForums()
    elapsedTime = time.time()-startTime #for science!
    log_it.logg("Scraping round completed successfully", q, genus=["debug"])
    log_it.logg ("Time elapsed in latest scrape: " + str(elapsedTime), q, genus=["benchmarking"])
    if elapsedTime < config.retrieveConfig("Period"): #if the period specified in config hasn't elapsed completely
        log_it.logg("Sleeping",q, genus=["debug"]) #debug
        time.sleep(config.retrieveConfig("Period")-elapsedTime) #sleep until the period time has elapsed

def scrapePost(p, q, check):
    ''' (url : str, Queue object, str)
    scrape post if check is right'''
    startTime = time.time()
    post = scraper.pageClass()
    log_it.logg("Scraping " + p, q, genus=["debug", "verbose"])
    post.ret(p)
    if config.retrieveConfig("NecroDetection")==check:
        if necroDetector.isNecro(post, config.retrieveConfig("NecroTimeDelta")):
            log_it.logg(p + " has been bumped from the dead.", q, genus=["output"])
    if config.retrieveConfig("ProfanityDetection")==check:
        if profanityDetector.isProfanity(post, config.retrieveConfig("SwearThreshold")):
            log_it.logg(p + " has been sworn in a lot.", q, genus=["output"])
    if config.retrieveConfig("CapsTitleDetection")==check:
        if capsDetector.isCapsTitle(post, config.retrieveConfig("CapsTitleThreshold")):
            log_it.logg(p + " has a lot of caps in the title.", q, genus=["output"])
    if config.retrieveConfig("CrusherAlerts")==check:
        if annoyanceAlerts.isCrusher(post):
            log_it.logg("Crusher Alert at " + p)
    if config.retrieveConfig("RotatingPlatformAlerts")==check:
        if annoyanceAlerts.isRotatingPlatforms(post):
            log_it.logg("Rotating Platforms Alert at " + p)

    elapsedTime = time.time()-startTime #for science!
    log_it.logg("Finished scraping " + p + " in " + str(elapsedTime), q, genus=["verbose", "benchmarking"])

def scrapeSection(section, q):
    '''(url : str, Queue object)
    scrape a forum section by creating a thread for every page that needs to be scraped'''
    startTime = time.time()
    page = scraper.pageClass()
    threads = []
    page.ret(section)
    check = "all"
    log_it.logg("Creating post scraping threads for " + section, q, genus=["debug"])
    if config.retrieveConfig("NecroDetection") == check or config.retrieveConfig("ProfanityDetection") == check or config.retrieveConfig("CapsTitleDetection") == check: #don't run if nothing wants it to
        sectionPosts = page.findAllPosts()
        log_it.logg("Found " + str(len(sectionPosts)) + " threads in section " + section, q, genus=["debug", "verbose"])
        for postNum in range(len(sectionPosts)):
            threads.append(Process(target=scrapePost, args=(sectionPosts[postNum], q, check,)))
            threads[postNum].start()
    check = "first"
    if config.retrieveConfig("NecroDetection") == check or config.retrieveConfig("ProfanityDetection") == check or config.retrieveConfig("CapsTitleDetection") == check: #don't run if nothing wants it to
        sectionFirstPost = page.findFirstPost()
        threads.append(Process(target=scrapePost, args=(sectionFirstPost, q, check,)))
        threads[len(threads)].start()

    log_it.logg("Finished creating post scraping threads for " + section, q, genus=["debug"])
    for thread in threads: #wait for all created threads to finish
        thread.join()
    elapsedTime = time.time()-startTime #for science!
    log_it.logg("Time elapsed in scraping section " + section + " : " + str(elapsedTime), q, genus=["verbose", "benchmarking"])

def scrapeForums():
    '''() -> None
    starts the forum section threads'''
    threads=[]
    log_it.logg("Creating section scraping threads", q, genus=["debug"])
    log_it.logg("There are " + str(len(ForumsToCheck.forums)) + " forum sections to scrape", q, genus=["debug", "verbose"])
    for n in range(len(ForumsToCheck.forums)):
        threads.append(Process(target=scrapeSection, args=(ForumsToCheck.forums[n],q,)))
        threads[n].start()
    log_it.logg("Finished creating section scraping threads", q, genus=["debug"])
    for thread in threads: #wait for all created threads to finish
        thread.join()


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

# EASY
# Time: O(n) Space: O(1)
class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        max_d = [0]

        def dfs(root):
            if root is None:
                return 0
            left = self.maxDepth(root.left)
            right = self.maxDepth(root.right)

            depth = max(left, right) + 1
            max_d[0] = max(max_d[0], depth)

            return depth

        dfs(root)
        return max_d[0]

BFS DFS/104. Maximum Depth of Binary Tree.py


from __future__ import absolute_import, division, print_function
from six.moves import range
import sys, os
op = os.path

def exercise_image_simple():
  expected_sum_image_pixels_iter = iter(
      (200, 156) + (400, 308)*2
    + (450, 351) + (900, 693)*2
    + ( 91,  69) + (181, 139)*2
    + (160, 124) + (320, 248)*2
    + (246, 188) + (490, 377)*2)
  from cctbx import uctbx
  unit_cell = uctbx.unit_cell((11,12,13,85,95,105))
  from cctbx.array_family import flex
  miller_indices = flex.miller_index([(-1,2,1)])
  from scitbx.math import euler_angles
  crystal_rotation_matrix = euler_angles.xyz_matrix(80,20,30)
  import rstbx.simage
  from libtbx.test_utils import approx_equal, show_diff
  dpx, dpy = 4, 5
  for ewald_proximity,star in [(0.1, " "), (0.5, "*")]:
    image_lines = []
    for point_spread in range(1,5+1):
      for spot_intensity_factor in [0.5, 1, None]:
        if (spot_intensity_factor is None):
          spot_intensity_factors = None
        else:
          spot_intensity_factors = flex.double([spot_intensity_factor])
        for apply_proximity_factor in [False, True]:
          if (star == "*"):
            expected_sum_image_pixels = next(expected_sum_image_pixels_iter)
          for code in range(16):
            store_miller_index_i_seqs = bool(code & 0x1)
            store_spots = bool(code & 0x2)
            store_signals = bool(code & 0x4)
            set_pixels = bool(code & 0x8)
            image = rstbx.simage.image_simple(
              apply_proximity_factor=apply_proximity_factor,
              store_miller_index_i_seqs=store_miller_index_i_seqs,
              store_spots=store_spots,
              store_signals=store_signals,
              set_pixels=set_pixels).compute(
                unit_cell=unit_cell,
                miller_indices=miller_indices,
                spot_intensity_factors=spot_intensity_factors,
                crystal_rotation_matrix=crystal_rotation_matrix,
                ewald_radius=0.5,
                ewald_proximity=ewald_proximity,
                signal_max=100,
                detector_distance=5,
                detector_size=(10,12),
                detector_pixels=(dpx,dpy),
                point_spread=point_spread,
                gaussian_falloff_scale=4)
            if (store_signals and image.signals.size() == 1):
              partialities = rstbx.simage.image_simple(
                apply_proximity_filter=False,
                apply_proximity_factor=apply_proximity_factor,
                store_signals=True).compute(
                  unit_cell=unit_cell,
                  miller_indices=miller_indices,
                  spot_intensity_factors=None,
                  crystal_rotation_matrix=crystal_rotation_matrix,
                  ewald_radius=0.5,
                  ewald_proximity=ewald_proximity,
                  signal_max=1,
                  detector_distance=5,
                  detector_size=(10,12),
                  detector_pixels=(dpx,dpy),
                  point_spread=point_spread,
                  gaussian_falloff_scale=4).signals
              f = 100
              if (spot_intensity_factor is not None):
                f *= spot_intensity_factor
              assert approx_equal(partialities*f, image.signals)
            if (store_miller_index_i_seqs and star == "*"):
              assert image.miller_index_i_seqs.size() == 1
            else:
              assert image.miller_index_i_seqs.size() == 0
            if (store_spots and star == "*"):
              assert image.spots.size() == 1
            else:
              assert image.spots.size() == 0
            if (store_signals and star == "*"):
              assert image.signals.size() == 1
            else:
              assert image.signals.size() == 0
            if (not set_pixels):
              assert image.pixels.size() == 0
            else:
              assert image.pixels.size() == 20
              sum_image_pixels = flex.sum(image.pixels)
              if (star == "*"):
                assert sum_image_pixels == expected_sum_image_pixels
              else:
                assert sum_image_pixels == 0
      assert image.pixels.all() == (dpx,dpy)
      for i in range(dpx):
        line = []
        for j in range(dpy):
          if (image.pixels[(i,j)]): c = star
          else: c = " "
          line.append(c)
        image_lines.append("|"+"".join(line)+"|")
      image_lines.append("")
    assert not show_diff("\n".join(image_lines), """\
|     |
|     |
|  ** |
|  ** |

|     |
|  ***|
|  ***|
|  ***|

|     |
|  ** |
| *** |
|  ** |

|  *  |
| ****|
| ****|
| ****|

| *** |
|*****|
|*****|
|*****|
""".replace("*", star))

def exercise_combine_rgb_images():
  from rstbx.simage import combine_rgb_images as cri
  assert cri(["de", "*/"]) == "GJ"
  assert cri(["+-", "ac"]) == "FH"

def exercise_create():
  from rstbx.simage import create
  from libtbx.test_utils import block_show_diff
  from libtbx.str_utils import show_string
  from six.moves import cStringIO as StringIO
  #
  def check(args, expected_block):
    sio = StringIO()
    work_params = create.process_args(args=args, out=sio)
    assert not block_show_diff(sio.getvalue(), expected_block)
    pixels = create.compute_image(work_params)
    assert pixels.all() == tuple(work_params.detector.pixels)
  #
  check(args=[], expected_block="""\
detector {
  distance = 180
  size = 200 200
  pixels = 1000 1000
  use_corners = False
}
""")
  #
  relative_path = "phenix_regression/pdb/start.pdb"
  import libtbx.load_env
  full_path = libtbx.env.find_in_repositories(
    relative_path=relative_path, test=op.isfile)
  if (full_path is None):
    print("Skipping some tests due to missing file: %s" % relative_path)
  else:
    check(
      args=["pdb_file="+show_string(full_path)],
      expected_block="""\
change_of_basis_op_to_niggli_cell = "a,b,c"
unit_cell = 32.9 32.9 96.1 90 90 120
intensity_symmetry = "P 3 2 1"
lattice_symmetry = "P 6 2 2"
""")

def exercise_explore_completeness():
  import libtbx.load_env
  if (not libtbx.env.has_module("spotfinder")):
    print("Skipping some tests due to missing module: spotfinder")
    return
  from libtbx.test_utils import contains_substring
  from libtbx import easy_run
  def run(args):
    cmd = " ".join(["rstbx.simage.explore_completeness"] + args)
    print(cmd)
    buf = easy_run.fully_buffered(
      command=cmd, stdout_splitlines=False).raise_if_errors().stdout_buffer
    for key in [
          "Complete with ",
          "Observations per reflection:",
          "  Median: "]:
      assert contains_substring(buf, key)
    return buf
  run(["d_min=10"])
  args = ["d_min=10", "intensity_symmetry=P4", "use_symmetry=True"]
  from libtbx import easy_mp
  if (easy_mp.detect_problem() is None):
    args.append("multiprocessing=True")
  buf = run(args)
  assert contains_substring(buf, 'lattice_symmetry = "P 4 2 2"')

def exercise_solver():
  import libtbx.load_env
  if (not libtbx.env.has_module("spotfinder")):
    print("Skipping some tests due to missing module: spotfinder")
    return
  from libtbx.test_utils import block_show_diff, contains_substring
  from libtbx import easy_run
  def run(args):
    cmd = " ".join(["rstbx.simage.solver"] + args)
    print(cmd)
    buf = easy_run.fully_buffered(
      command=cmd, stdout_splitlines=False).raise_if_errors().stdout_buffer
    for key in [
          "Final:"]:
      assert contains_substring(buf, key)
    return buf
  buf = run(["d_min=5"])
  assert not block_show_diff(buf, """\
input_im0_i_perm: 0

Correlation of input and estimated I-obs:
  i_perm=0:  1.00000 (r1: 0.00000)
""")
  buf = run(["d_min=5", "lattice_symmetry=R32:R", "intensity_symmetry=R3:R"])
  assert not block_show_diff(buf, """\
input_im0_i_perm: 1

Correlation of input and estimated I-obs:
  i_perm=0:  0.06799 (r1: 0.37555)
  i_perm=1:  1.00000 (r1: 0.00000)
""")
  buf = run(["d_min=5", "lattice_symmetry=R32:R", "intensity_symmetry=P1"])
  assert not block_show_diff(buf, """\
input_im0_i_perm: 5

Correlation of input and estimated I-obs:
  i_perm=0:  0.07524 (r1: 0.38937)
  i_perm=1: -0.02385 (r1: 0.40114)
  i_perm=2: -0.04577 (r1: 0.41742)
  i_perm=3: -0.00099 (r1: 0.40390)
  i_perm=4:  0.00764 (r1: 0.39213)
  i_perm=5:  1.00000 (r1: 0.00000)
""")
  if (not libtbx.env.has_module("labelit")):
    print("Skipping some tests due to missing module: labelit")
  else:
    from libtbx import easy_mp
    mp_problem = easy_mp.detect_problem()
    if (mp_problem is not None):
      print("Skipping some tests:", mp_problem)
    else:
      buf = run([
        "d_min=5", "lattice_symmetry=P422", "intensity_symmetry=P4",
        "index_and_integrate=True", "multiprocessing=True"])
      assert contains_substring(buf, "Refined unit cell 9 (")
      assert contains_substring(
        buf, "Correlation of input and estimated I-obs:")
      assert contains_substring(buf, "  Best correlation:  0.999")

def run(args):
  assert len(args) == 0
  from libtbx.utils import show_times_at_exit
  show_times_at_exit()
  exercise_image_simple()
  exercise_combine_rgb_images()
  exercise_create()
  exercise_explore_completeness()
  exercise_solver()
  print("OK")

if (__name__ == "__main__"):
  run(args=sys.argv[1:])


RU = 4110677

print(f'Bem-Vindo a Loja do Elizeu Pinheiro França - {RU}')

#Loop para pegar o valor e a quantidade de produtos
while True:
    try:
        valor = float(input('Digite o valor dos produtos:'))
        quantidade = float(input('Digite a quantidade dos produtos:'))
    except ValueError:
        print('Você não digitou um valor numerico, tente novamente.')
        continue
    break

valor_bruto = valor * quantidade

print(f'O valor do final sem desconto foi de : R$ {valor_bruto}')

# Realiza-a-validação do desconto e mostra em seguida
if quantidade < 10:
    print(f'O valor com desconto foi de: R$ {valor_bruto}  (desconto 0%)')
elif quantidade >= 10 and quantidade < 100:
    print(f'O valor com desconto foi de: R$ {valor_bruto - valor_bruto * 0.05}  (desconto 5%)')
elif quantidade >= 100 and quantidade < 1000:
    print(f'O valor com desconto foi de: R$ {valor_bruto - valor_bruto * 0.10}  (desconto 10%)')
else:
    print(f'O valor com desconto foi de: R$ {valor_bruto - valor_bruto * 0.15}  (desconto 15%)')


import pygame

from economycs import config

KEY_OVERLAY_SIZE = (600, 800)
BORDER_WIDTH = 3

class UI:
    def __init__(self):
        self.font = pygame.font.Font(None, config.FONT_SIZE)
        self.show_keys = False

        # Create key overlay
        self.key_overlay = pygame.Surface(KEY_OVERLAY_SIZE)
        self.key_overlay.fill((0, 0, 0, 200))
        border_rect = (0, 0, KEY_OVERLAY_SIZE[0], KEY_OVERLAY_SIZE[1])
        pygame.draw.rect(self.key_overlay, (200, 200, 200), border_rect,
                         BORDER_WIDTH)

        cur_pos = pygame.Rect(0, 0, 0, 0)
        lines = [
            ('w, a, s, d', 'Move screen'),
            ('q, e', 'Zoom In / Out'),
            ('c', 'Build city'),
            ('x', 'Quit')
        ]
        for keys, label in lines:
            cur_pos.y += 20
            cur_pos.x = 20
            text = self.font.render(keys, True, (255, 255, 255))
            self.key_overlay.blit(text, cur_pos)
            cur_pos.x = 200
            text = self.font.render(label, True, (255, 255, 255))
            self.key_overlay.blit(text, cur_pos)

        # Create help indicator
        self.help_indicator = self.font.render('Press h for help', True,
                                               (255, 255, 255))

    def draw(self, screen):
        if self.show_keys:
            screen_size = screen.get_size()
            x = screen_size[0] / 2 - KEY_OVERLAY_SIZE[0] / 2
            y = screen_size[1] / 2 - KEY_OVERLAY_SIZE[1] / 2
            screen.blit(self.key_overlay, (x, y))

        screen_size = screen.get_size()
        indicator_size = self.help_indicator.get_size()
        x = screen_size[0] - indicator_size[0] - 5
        y = screen_size[1] - indicator_size[1] - 5
        screen.blit(self.help_indicator, (x, y))


"""added document receive record model

Revision ID: 526bfec2f5b8
Revises: a9804c833dc8
Create Date: 2021-05-18 02:44:24.574477

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '526bfec2f5b8'
down_revision = 'a9804c833dc8'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('doc_receive_records',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('doc_id', sa.Integer(), nullable=True),
    sa.Column('staff_id', sa.Integer(), nullable=True),
    sa.Column('viewed_at', sa.DateTime(timezone=True), nullable=True),
    sa.ForeignKeyConstraint(['doc_id'], ['doc_documents.id'], ),
    sa.ForeignKeyConstraint(['staff_id'], ['staff_account.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.add_column(u'doc_documents', sa.Column('comment', sa.Text(), nullable=True))
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column(u'doc_documents', 'comment')
    op.drop_table('doc_receive_records')
    # ### end Alembic commands ###