def sum_of_pairs(x, num):
    y = len(x) // 2
    print(y)
    i = 0
    for m in range(y):
        s = x[i] + x[i+1]
        if s == num:
            return [x[i], x[i+1]]
        i += 2
    return []

#x = [3, 6, 3, 5, 50, 20]
#res = sum_of_pairs(x, 100)
#print(res)

def vowel_count(str1):
    d = {}.fromkeys("aeiou", 0)
    for char in str1.lower():
        if char in "aeiou":
            d[char] += 1
    print(d)
    return {k:v for k,v in d.items() if d[k] > 0}

#ret = vowel_count("awesome")
#print(ret)

def titleize(str1):
    words = str1.split(" ")
    ret = ""
    for word in words:
        astr = word[0].upper() + word[1:]
        ret += astr + " "
    ret = ret[0:len(ret) - 1] # remove last space
    return ret

#ret = titleize("this is a string")
#print(ret)

def find_factors(num):
    return [n for n in range(1, num + 1) if num % n == 0]

#x = find_factors(10)
#print(x)

def search(collection, val, startidx = 0):
    if type(collection) is dict:
        return (val in collection.values())

    return val in collection[startidx:]

#d = {"a": 1, "b":20, "c":200}
#ret = search(d, 200)
#print("value in dictionary: " + str(ret))
#ret = search(d, 'a')
#print("value in dictionary: " + str(ret))

#s = "awesome"
#val = "s"
#ret = search(s, val, 1)
#print(s + " contains " + val + " " + str(ret))

#l = [2, 4, 5, 30, 21]
#val = 30
#ret = search(l, val, 4)
#print("{} contains {}: {}" .format(l, val, ret))

def repeat(str1, num):
    ret = ""
    for n in range(num):
        ret += str1
    return ret

#str1 = "*"
#ret = repeat(str1, 5)
#print(ret)

def truncate(str1, num):
    if num < 3:
        return "Truncation must be at least 3 characters."
    if num > len(str1):
        return str1
    str2 = str1[0:num-3]
    str2 += "..."
    return str2

#str1 = "Super Cool"
#print(truncate(str1,0))
#str1 = "Hello World"
#print(truncate(str1, 6))
#str1 = "Problem Solving is best!"
#print(truncate(str1, 10))
#str1 = "Another test"
#print(truncate(str1, 12))
#str1 = "Woah"
#print(truncate(str1, 4))
#print(truncate(str1, 3))
#str1 = "YO"
#print(truncate(str1, 100))
#str1 = "Holy guacamole!"
#print(truncate(str1, 152))

def two_list_dictionaries(keylist, valuelist):
    ntimes = min(len(keylist), len(valuelist))
    d = {keylist[i]:valuelist[i] for i in range(ntimes) }
    if len(keylist) > len(valuelist):
        rest = {}.fromkeys(keylist[ntimes:], None)
        d.update(rest)
    return d

#keylist = [1,2, 3, 4, 5]
#valuelist = [14,13,12,11,10,9]
#print(two_list_dictionaries(keylist, valuelist))

def range_in_list(alist, startidx = 0, endidx = 0):
    print("start: {} end: {}" .format(startidx, endidx))
    if len(alist) == 0:
        return 0
    if endidx == 0 or endidx > len(alist):
        endidx = len(alist) - 1
    sum = 0
    for i in range(startidx, endidx + 1): sum += alist[i]
    return sum

#l = [1, 2, 3, 4]
#print(range_in_list(l, 0, 2))
#print(range_in_list(l, 0, 3))
#print(range_in_list(l, 1))
#print(range_in_list(l))
#print(range_in_list(l, 0,100))
#print(range_in_list([], 0,1))

def same_frequency(num1, num2):
    snum1 = str(num1)
    snum2 = str(num2)
    if len(snum1) != len(snum2):
        return False

    d1 = {}.fromkeys("0123456789", 0)
    d2 = d1.copy()
    for char in snum1:
        d1[char] += 1
    for char in snum2:
        d2[char] += 1
    for key in d1.keys():
        if d2[key] != d1[key]:
            return False
    return True

#num1 = 551122
#num2 = 221515
#ret = same_frequency(num1, num2)
#print("{} and {} has same frequency? {}" .format(num1,num2, ret))
#num1 = 321142
#num2 = 3212215
#ret = same_frequency(num1, num2)
#print("{} and {} has same frequency? {}" .format(num1,num2, ret))
#num1 = 1212
#num2 = 2211
#ret = same_frequency(num1, num2)
#print("{} and {} has same frequency? {}" .format(num1,num2, ret))

def nth(alist, idx):
    tlist = alist.copy()   # copy otherwise it removes from the list
    elem = tlist.pop(idx)
    return elem

#l = ['a', 'b', 'c', 'd']
#idx = 1
#print("{} {}th element at {}" .format(l, idx, nth(l, idx)))
#idx = -2
#print("{} {}th element at {}" .format(l, idx, nth(l, idx)))
#idx = 0
#print("{} {}th element at {}" .format(l, idx, nth(l, idx)))
#idx = -4
#print("{} {}th element at {}" .format(l, idx, nth(l, idx)))
#idx = -1
#print("{} {}th element at {}" .format(l, idx, nth(l, idx)))
#idx = 3
#print("{} {}th element at {}" .format(l, idx, nth(l, idx)))

def find_the_duplicate(alist):
    for item in alist:
        if alist.count(item) > 1:
            return item
    return None

#l = [1, 2, 3, 1, 4, 7, 9]
#print("{} contains {} more than once" .format(l, find_the_duplicate(l)))
#l = [1, 2, 3, 4]
#print("{} contains {} more than once" .format(l, find_the_duplicate(l)))

def sum_of_diagonals(alist):
    total = 0
    ci = 0
    list1 = []
    for i in range(len(alist)):
        list1.append(alist[i][ci])
        ci+=1
    print(list1)
    list2 = []
    ci = -1
    for i in range(len(alist)):
        list2.append(alist[i][ci])
        ci -= 1
    print(list2)
    total = sum(list1) + sum(list2)
    return total

#l1 = [[1,2], [3,4]]
#print("{} sum is {}" .format(l1, sum_of_diagonals(l1)))
#l2 = [[1,2,3],[4,5,6],[7,8,9]]
#print("{} sum is {}" .format(l2, sum_of_diagonals(l2)))
#l3 = [[4,1,0], [-1,-1,0], [0,0,9]]
#print("{} sum is {}" .format(l3, sum_of_diagonals(l3)))
#l4 = [[1,2,3,4],[5,6,7,8],[9,10,11,12], [13,14,15,16]]
#print("{} sum is {}" .format(l4, sum_of_diagonals(l4)))

def min_max_key_in_dictionary(adict):
    return [min(adict.keys()), max(adict.keys())]

#d1 = {2:"a", 7:"b", 1:"c", 10:"d", 4:"e"}
#print("min max keys in {} are {}" .format(d1, min_max_key_in_dictionary(d1)))
#d2 = {1: "Elie", 4:"Matt", 2:"Tim"}
#print("min max keys in {} are {}" .format(d2, min_max_key_in_dictionary(d2)))

def find_greater_numbers(alist):
    if len(alist) == 0:
        return 0
    total = 0
    l1 = alist.copy()
    num = l1[0]
    while len(l1) != 1:
        for i in range((len(l1) - 1)):
            if num < l1[i+1]:
                total += 1
        x = l1.pop(0)
#        print("poped {}" .format(x))
        num = l1[0]
    return total

#l1 = [1,2,3]
#print("{} total {}" .format(l1, find_greater_numbers(l1)))
#l2 = [6,1,2,7]
#print("{} total {}" .format(l2, find_greater_numbers(l2)))
#l3 = [5, 4, 3, 2, 1]
#print("{} total {}" .format(l3, find_greater_numbers(l3)))
#l4 = []
#print("{} total {}" .format(l4, find_greater_numbers(l4)))

def two_oldest(alist):
    alist.sort()
    return [alist[-2], alist[-1]]

#l1 = [1, 2, 10, 8]
#print("{} 2 oldest items are: {}" .format(l1, two_oldest(l1)))
#l2 = [6, 1, 9, 10, 4]
#print("{} 2 oldest items are: {}" .format(l2, two_oldest(l2)))
#l3 = [4, 25, 3, 20, 19, 5]
#print("{} 2 oldest items are: {}" .format(l3, two_oldest(l3)))

import string
def is_odd_string(str1):
    CHARS = list(string.ascii_lowercase)
    CHARS.insert(0, "X")
    total = 0
    for char in str1:
        total += CHARS.index(char)
    return (total % 2 != 0)

#str1 = 'a'
#print("{} has odd alphabets {}" .format(str1, is_odd_string(str1)))
#str2 = 'aaaa'
#print("{} has odd alphabets {}" .format(str2, is_odd_string(str2)))
#str3 = 'amazing'
#print("{} has odd alphabets {}" .format(str3, is_odd_string(str3)))
#str4 = 'veryfun'
#print("{} has odd alphabets {}" .format(str4, is_odd_string(str4)))
#str5 = 'veryfunny'
#print("{} has odd alphabets {}" .format(str5, is_odd_string(str5)))

def valid_paranthesis(str1):
    if str1[0] == ')' or len(str1) == 1:
        return False
    ocount = str1.count('(')
    ccount = str1.count(')')
    print("open {} close {}" .format(ocount, ccount))
    if ocount != ccount:
        return False
    ocount = 0
    ccount = 0
    for char in str1:
        if char == "(":
            ocount += 1
        if char == ")":
            ccount += 1
        if ccount > ocount:
            return False
    return True

#str1 = "()"
#print("{} has valid paranthesis: {}".format(str1,valid_paranthesis(str1)))
#str1 = ")(()))"
#print("{} has valid paranthesis: {}".format(str1,valid_paranthesis(str1)))
#str1 = "("
#print("{} has valid paranthesis: {}".format(str1,valid_paranthesis(str1)))
#str1 = "(())(())()())"
#print("{} has valid paranthesis: {}".format(str1,valid_paranthesis(str1)))
#str1 = "))(("
#print("{} has valid paranthesis: {}".format(str1,valid_paranthesis(str1)))
#str1 = "())("
#print("{} has valid paranthesis: {}".format(str1,valid_paranthesis(str1)))
#str1 = "()()()()())()("
#print("{} has valid paranthesis: {}".format(str1,valid_paranthesis(str1)))

def reverse_vowels(str1):
    vowels = "aeiouAEIOU"
    x = [char for char in str1 if char in vowels]
    ret = ""
    idx2 = -1
    for char in str1:
        if char not in vowels:
            ret += char
        else:
            ret += x[idx2]
            idx2 -= 1
    return ret

#str1 = 'Hello!'
#print("{} with reversed vowels {}" .format(str1, reverse_vowels(str1)))
#str1 = 'Tomatoes'
#print("{} with reversed vowels {}" .format(str1, reverse_vowels(str1)))
#str1 = 'Reverse Vowels In A String'
#print("{} with reversed vowels {}" .format(str1, reverse_vowels(str1)))
#str1 = 'aeiou'
#print("{} with reversed vowels {}" .format(str1, reverse_vowels(str1)))
#str1 = 'why try, shy fly?'
#print("{} with reversed vowels {}" .format(str1, reverse_vowels(str1)))

def three_odd_numbers(alist):
    ntimes = len(alist)  - 2
    idx = 0
    for i in range(ntimes):
        x = [alist[idx], alist[idx+1], alist[idx+2]]
        if sum(x) % 2 != 0:
            return True
        idx += 1
    return False

#l1 = [1, 2, 3, 4, 5]
#print("{} 3 consecutive numbers are odd {}" .format(l1,three_odd_numbers(l1)))
#l1 = [0,-2,4,1,9,12,4,1,0]
#print("{} 3 consecutive numbers are odd {}" .format(l1,three_odd_numbers(l1)))
#l1 = [5, 2, 1]
#print("{} 3 consecutive numbers are odd {}" .format(l1,three_odd_numbers(l1)))
#l1 = [1, 2, 3, 3, 2]
#print("{} 3 consecutive numbers are odd {}" .format(l1,three_odd_numbers(l1)))

# look for non collection solution in notes
from collections import Counter
def mode(nums):
    cnt = Counter(nums)
    x  = cnt.most_common(1)
    return x[0][0]

#l1 = [2, 4,1,2,3,4,4,5,4,4,6,4,6,7,4]
#print("{} most frequent {}" .format(l1, mode(l1)))

def running_average():
    count = 0
    laverage = 0
    def average(x):
        nonlocal count
        nonlocal laverage
        count += 1
#        print("count {} laverage {} x {}" .format(count, laverage, x))
        laverage += x
        return laverage / count
    return average

#rAvg1 = running_average()
#print(rAvg1(10))
#print(rAvg1(11))
#print(rAvg1(12))

#rAvg2 = running_average()
#print(rAvg2(1))
#print(rAvg2(3))

def letter_counter(str1):
    word = str1
    def counter(x):
        times = word.lower().count(x)
        return times
    return counter

#counter = letter_counter("amazing")
#print(counter('a'))
#print(counter('m'))
#counter1 = letter_counter("This is really fun!")
#print(counter1('i'))
#print(counter1('t'))

def add(a,b):
    return a+b
def once(fn):
    called = False
    def onlyonce(x,y):
        nonlocal called
        if called:
            return None
        called = True
        return fn(x,y)
    return onlyonce

#oneAdd = once(add)
#print(oneAdd(2,4))
#print(oneAdd(2,4))
#print(oneAdd(10,50))

import math
# This is a generator
#def next_prime():
#    prime = 2
#    num = 2
#    while True:
#        yield prime
#        for x in range(1, num+1):
#         for x in range(2, int(math.sqrt(num)) + 1):
#             print(x)
#            print(num)
#            if num % x == 0:
#                num = num + 1
#            else:
#                prime = num

def isPrime(num):
    if num < 2:
        return False
    for x in range(2, int(math.sqrt(num)) + 1):
        if num % x == 0:
            return False
    return True

def next_prime():
    num = 2
    while True:
        if isPrime(num):
            yield num
        num += 1

primes = next_prime()
x = [next(primes) for i in range(30)]
print(x)


# -*- coding: UTF-8 -*-
################################################################################
#
# Copyright (c) 2021 Baidu.com, Inc. All Rights Reserved
#
################################################################################
"""配置读取封装模块"""
import configparser
import os
import logging

import read_urls

class Config(object):
    """配置类"""

    def __int__(self, config_path):
        self.config_path = config_path
        self.cfg = configparser.ConfigParser()

    # get_value获取全部的字符串，section区域名, option选项名
    def get_value(self, section, option):
        self.cfg.read(self.config_path)
        return self.cfg.get(section, option)

    # get_int获取整型，section区域名, option选项名
    def get_int(self, section, option):
        """
        get_int获取整型
        :param section: 区域名
        :param option: 选项名
        :return:
        """
        self.cfg.read(self.config_path)
        return self.cfg.getint(section, option)

    # get_float获取浮点数类型，section区域名, option选项名
    def get_float(self, section, option):
        self.cfg.read(self.config_path)
        return self.cfg.getfloat(section, option)

    # get_boolean获取布尔类型，section区域名, option选项名
    def get_boolean(self, section, option):
        self.cfg.read(self.config_path)
        return self.cfg.getboolean(section, option)

    # get_eval_data获取列表，section区域名, option选项名
    def get_eval_data(self, section, option):
        self.cfg.read(self.config_path)
        return eval(self.cfg.get(section, option))

    @staticmethod
    def write_config(datas, filename):
        """
        写入配置操做
        :param datas: 须要传入写入的数据
        :param filename: 指定文件名
        :return:
        """
        # 作校验，为嵌套字典的字典才能够（意思.隐私.谈.ce)
        if isinstance(datas, dict):  # 在外层判断是否为字典
            # 再来判断内层的 values 是否为字典
            for value in datas.values():  # 先取出value
                if not isinstance(value, dict):  # 在判断
                    return "数据不合法, 应为嵌套字典的字典"

            config = configparser.ConfigParser()  # 1.建立配置解析器---与写入配置操做一致
            for key in datas:  # 写入操做
                config[key] = datas[key]
            with open(filename, "w") as file:  # 保存到哪一个文件filename=须要指定文件名
                config.write(file)
            # return "写入成功"

    @staticmethod
    def conf_load(filepath):
        log = logging.getLogger('Spider.crawler')
        if not os.path.exists(filepath):
            log.error('config file %s not exist' % filepath)
            return None
        conf = {}
        try:
            conf.urls = Config.get_value('spider', 'feed_file')
            conf.output_dir = Config.get_value('spider', 'result')
            conf.mex_depth = Config.get_int('spider', 'max_depth')
            conf.crawl_interval = Config.get_float('spider', 'crawl_interval')
            conf.time_out = Config.get_float('spider', 'crawl_timeout')
            conf.thread_count = Config.get_int('spider', 'thread_count')
            conf.target_url = read_urls.read_file('../urls')
        except IOError as e:
            log.error("failed to open config file: %s, err: %s" % (filepath, e))
            return None
        except configparser.NoSectionError as e:
            log.error("config parser: no section error: %s" % e)
            return None
        except configparser.NoOptionError as e:
            log.error("config parser: no option error: %s" % e)
            return None
        except Exception as e:
            log.error("unknown error: %s" % e)
            return None
        return conf


from django.views.generic import View

from modules.response import Response

from .user_model import UserModel

import sys
sys.path.append("../../modules")
sys.path.append("../models")

class User(View, Response):

    def __init__(self):
        super().__init__()
        User.model = UserModel()

    def post(self, request):

        uuid = request.POST.get("uuid")
        data = self.model.get_user(uuid)

        if not data:
            content = {}
            return self.response(content)

        lab_uuid = data["lab_uuid"]
        data["studentId"] = data["student_id"]

        lab_info = self.model.get_lab_info(lab_uuid)
        print(data)
        content = {
            "user": data,
            "lab_info": lab_info
        }

        return self.response(content)


import bs4
from bs4 import NavigableString

from selenium import webdriver

import sys
import time
import os
import traceback
import logging
import tempfile
import re

from selenium.common.exceptions import NoSuchElementException

import pr_settings
import gmail

logging.basicConfig(format='%(asctime)s %(levelname)s : %(message)s', level=logging.INFO)
slot_container_with_date_regex = re.compile('^slot-container-(\d{4}-\d{2}-\d{2})$')
not_available_text = "No doorstep delivery windows are available".lower()

class HeartBeat:
    def __init__(self, freq_in_secs):
        self.freq_in_sec = freq_in_secs
        self.starting = time.time()

    def check(self):
        elapsed = time.time() - self.starting
        logging.info('elapsed sec : ' + str(elapsed))
        if elapsed > self.freq_in_sec:
            os.system('say "Program still alive"')
            self.starting = time.time()

class Slot:
    def __init__(self, dateStr, slots_open):
        self.dateStr = dateStr
        self.slotsOpen = slots_open

    def __str__(self):
        return "Slot[" + self.dateStr + (" HAS" if self.slotsOpen else " has NO") \
               + " open slots]"

def find_slot_from_slot_container_base(soup):
    """
    :param bs: beautifulsoup object
    :return:
    """
    slot_container_root = soup.find(id="slot-container-root")
    slots = []
    for slot in slot_container_root.findAll('div', id=slot_container_with_date_regex):
        dateStr = slot_container_with_date_regex.match(slot['id']).group(1)
        unattended_container = slot.find('div', id="slot-container-UNATTENDED")
        text = unattended_container.findAll(end_node)[0].text
        logging.debug("Found text : " + text)
        slotsOpen = False
        if (text is not None and text.lower().find(not_available_text) >= 0):
            slotsOpen = False
        else:
            slotsOpen = True
        slots.append(Slot(dateStr, slotsOpen))
    return slots

def alert(open_slots):
    slots_str = "slots : " + str([str(s) for s in open_slots])
    logging.info('SLOTS OPEN!')
    os.system('say "Slots for delivery opened!"')
    send_gmail(slots_str)
    logging.info('email sent')
    time.sleep(1400)

def saveToFile(folder, text):
    f = open(folder + next(tempfile._get_candidate_names())+'.html', "a")
    f.write(text)
    f.close()

def send_gmail(body_text):
    service = gmail.build_service()
    # Call the Gmail API
    msg = gmail.create_message(pr_settings.gmail_from, pr_settings.gmail_to, pr_settings.gmail_subject,
                               pr_settings.gmail_body+" "+body_text)
    gmail.send_message(service, 'me', msg)

def check_slots_algo1(soup):
    """
    :param soup: beautiful soup object representing the whole html
    :return: True if has open slots. False otherwise.
    """
    no_open_slots = True
    try:
        slots = find_slot_from_slot_container_base(soup)
        logging.info("slots : " + str([str(s) for s in slots]))
        open_slots = [sl for sl in slots if sl.slotsOpen]
        if len(open_slots) == 0:
            return False
        else:
            saveToFile(pr_settings.html_file_temp_folder, str(soup))
            alert(open_slots)
            return True
    except NoSuchElementException as e:
        traceback.print_exc(file=sys.stdout)

def end_node(tag):
    """
    Args:
      tag: html element.

    Returns: True if tag is a span and contains text and no other tags inside.
    """
    if tag.name not in ["span"]:
        return False
    if isinstance(tag, NavigableString):  # if str return
        return False
    if not tag.text:  # if no text return false
        return False
    elif len(tag.find_all(text=False)) > 0:  # no other tags inside other than text
        return False
    return True  # if valid it reaches here

def getWFSlot(productUrl):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36',
    }

    driver = webdriver.Chrome(executable_path=pr_settings.chrome_webdriver_executable_path)
    driver.get(productUrl)
    html = driver.page_source
    soup = bs4.BeautifulSoup(html, features="html.parser")
    time.sleep(60)
    has_open_slots = False
    heart_beat = HeartBeat(600)
    while not has_open_slots:
        heart_beat.check()
        driver.refresh()
        logging.info("refreshed")
        html = driver.page_source
        # saveToFile(pr_settings.html_file_temp_folder,
        #            html)
        soup = bs4.BeautifulSoup(html, features="html.parser")
        has_open_slots = check_slots_algo1(soup)
        if has_open_slots:
            time.sleep(1400)
        else :
            time.sleep(3)
        #
        # try:
        #     open_slots = soup.find('div', class_='orderSlotExists');
        #     if open_slots is not None and open_slots.text() != "false":
        #         no_open_slots = False
        #         alert()
        #     else:
        #         logging.info('Ah! No open slots yet.')
        # except AttributeError as e:
        #     traceback.print_exc(file=sys.stdout)

def main():
    getWFSlot('https://www.amazon.com/gp/buy/shipoptionselect/handlers/display.html?hasWorkingJavascript=1')

if __name__ == '__main__':
    main()


from csv import reader
from collections import Counter
import operator

class Aeroportos:

    def __init__(self, path):
        self.__path = path
        self.__data = self.open()

    def open(self):
        with open(self.__path, encoding="utf8") as arq_csv:
            leitor_csv = reader(arq_csv, delimiter=';')
            lista_csv = list(leitor_csv)
        return lista_csv
    """
    1.2) Extrair número de atrasos, recebendo como parâmetro, o ano de referência,
    e.g.: ./flight-delays -n 2006 deve listar o número de vôos com atraso em 2006.
    def atrasos(self):
    """
    def atrasos(self, ano):
        contador = 0
        len_coluna = len(self.__data[0:])
        if self.__data[1][0] == ano:
            for i in range(1, len_coluna):
                if self.__data[i][14] == 'NA':
                    contador = contador
                elif int(self.__data[i][14]) > 0:
                    contador += 1
        return contador
    """
    1.3) Mostrar lista de companhias aéreas que sofreram atraso, recebendo como parâmetro o ano de referência
    Utilizar o arquivo carriers.csv
    """
    def companhias_atrasos_comprida(self, path_carriers, ano):

        f = open(path_carriers, "r")
        data = f.readlines()
        f.close()

        # Tira as aspas do arquivo carriers e cria uma matriz (data) do conteúdo do arquivo
        # data[i][0] = código da companhia = coluna 'UniqueCarrier' do arquivo 2006.csv
        # data[i][1] = nome da companhia
        for i in range(len(data)):
            data[i] = data[i].replace('\n' , '').replace('"', "").split(",")

        # Cria uma lista (companhias) do conteúdo da coluna 8 = 'UniqueCarrier' do arquivo ano.csv
        # contendo só as COMPANHIAS QUE SOFRERAM ATRASO
        # essa coluna 8 possui o código da companhia
        companhias = []

        len_coluna = len(self.__data[0:])
        # Comprova se o ano ingressado é igual ao ano do arquivo
        if self.__data[1][0] == ano:
            for i in range(1, len_coluna):
                if self.__data[i][14] != 'NA' and int(self.__data[i][14]) > 0:
                    companhias.append(self.__data[i][8])

        # Se o código da companhia que sofreu atraso (companhias) for igual
        # ao código da lista carriers, é adicionado um novo elemento na lista_companhias, contendo
        # o nome do aeroporto que sofreu atraso

        lista_companhias = []

        if len(data) > len(companhias):

            for i in range (len(companhias)):
                for j in range (len(data)):
                    if companhias[i] == data[j][0]:
                        lista_companhias.append(data[j][1])
        else:

            for i in range (len(data)):
                for j in range (len(companhias)):
                    if data[i] == companhias[j][0]:
                        lista_companhias.append(companhias[j][1])

        return lista_companhias

    # Elimina os elementos repetidos da lista_companhias

    def companhias_atrasos_pequena(self, path_carriers, ano):

        x = Aeroportos(self.__path)
        lista_companhias = x.companhias_atrasos_comprida(path_carriers, ano)

        i = 0
        while i < len(lista_companhias):
            j = i + 1
            while j < len(lista_companhias):
                if lista_companhias[j] == lista_companhias[i]:
                    del(lista_companhias[j])
                else:
                   j += 1
            i += 1

        return lista_companhias

    """
    1.4) Mostrar a lista de Aeroportos com atrasos, recevendo como parâmetro o ano de referência
    Utilizar o arquivo airports.csv
    Criar nova issue que altere a funcionalidade de download de dataset para também baixar esse arquivo
    """
    # Quase igual ao exercício 3), diferença: pega a coluna 15 da matriz self.__data em lugar da 14

    def aeroportos_atrasos_comprida(self, path_airports, ano):

        f = open(path_airports, "r")
        data = f.readlines()
        f.close()

        # Tira as aspas do arquivo 'airports' e cria uma matriz (data) do conteúdo do arquivo
        # data[i][0] = iata
        # data[i][1] = airport
        # data[i][2] = city
        # data[i][3] = state
        # ...
        # data[i][6] = long

        for i in range(len(data)):
            data[i] = data[i].replace('\n' , '').replace('"', "").split(",")

        # Cria uma lista (aeroportos) do conteúdo da coluna 16 = 'Origin' do arquivo ano.csv
        # contendo só os códigos dos AEROPORTOS que SOFRERAM ATRASO
        # essa coluna 16 possui o código do aeroporto em que decolou o avião

        aeroportos = []

        len_coluna = len(self.__data[0:])
        # Comprova se o ano ingressado é igual ao ano do arquivo
        if self.__data[1][0] == ano:
            for i in range(1, len_coluna):
                if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0:
                    aeroportos.append(self.__data[i][16])

        # Se o código do aeroporto que sofreu atraso (aeroportos) for igual
        # ao código do aeroporto na lista 'airports' (coluna 0 da matriz data), é adicionado um novo elemento na lista_aeroporots,
        # contendo o nome do aeroporto que sofreu atraso

        lista_aeroportos = []

        if len(data) > len(aeroportos):

            for i in range (len(aeroportos)):
                for j in range (len(data)):
                    if aeroportos[i] == data[j][0]:
                        lista_aeroportos.append(data[j][1])
        else:

            for i in range (len(data)):
                for j in range (len(aeroportos)):
                    if data[i] == aeroportos[j][0]:
                        lista_aeroportos.append(aeroportos[j][1])

        return lista_aeroportos

    # Elimina os elementos repetidos da lista_aeroportos

    def aeroportos_atrasos_pequena (self,path_airports,ano):

        x = Aeroportos(self.__path)

        lista_aeroportos = x.aeroportos_atrasos_comprida(path_airports,ano)

        i = 0
        while i < len(lista_aeroportos):
            j = i + 1
            while j < len(lista_aeroportos):
                if lista_aeroportos[j] == lista_aeroportos[i]:
                    del(lista_aeroportos[j])
                else:
                   j += 1
            i += 1

        return lista_aeroportos

    """
    2.1) Contabilizar o número de atrasos ocorridos em cada aeroporto,
    listando o nome do aeroporto em uma coluna e o número de atrasos na segunda coluna (recebendo como parâmetro o ano base)
    """
    def num_atrasos_aeroporto(self, path_airports, ano):

        #Puxando o resultado do exercício 1.4
        x = Aeroportos(self.__path)
        lista_aeroporotos_comprida = x.aeroportos_atrasos_comprida(path_airports,ano)

        # Conta as ocorrencias de cada aeroporto na lista_aeroportos (versão comprida)
        # e retorna um dicionário

        num_atrasos = dict(Counter(lista_aeroporotos_comprida))

        return num_atrasos
    """
    2.2) Contabilizar o número de atrasos ocorridos em cada companhia aérea,
    listando o nome da companhia em uma coluna e o número de atrasos na segunda coluna (recebendo como parâmetro o ano base)
    """
    def num_atrasos_companhia(self, path_carriers, ano):
        #Puxando o resultado do exercício 1.3
        x = Aeroportos(self.__path)
        lista_companhias_comprida = x.companhias_atrasos_comprida(path_carriers,ano)

        # Conta as ocorrencias de cada companhia na lista_companhias (versão comprida)
        # e retorna um dicionário

        num_atrasos = dict(Counter(lista_companhias_comprida))

        return num_atrasos
    """
    2.3) Listar qual companhia teve o maior número de atrasos (atrasos somente na decolagem).
    """

    """
    extra) Mostra a lista de companhias aéreas que sofreram atraso NO DEPARTURE, recebendo como parâmetro o ano de referência
    Utilizar o arquivo carriers.csv
    """
    def companhias_atrasos_departure(self, path_carriers, ano):

        f = open(path_carriers, "r")
        data = f.readlines()
        f.close()

        # Tira as aspas do arquivo carriers e cria uma matriz (data) do conteudo do arquivo
        # data[i][0] = código da companhia = coluna 'UniqueCarrier' do arquivo 2006.csv
        # data[i][1] = nome da companhia
        for i in range(len(data)):
            data[i] = data[i].replace('\n' , '').replace('"', "").split(",")

        # Cria uma lista (companhias) do conteúdo da coluna 8 = 'UniqueCarrier' do arquivo ano.csv
        # contendo só as COMPANHIAS QUE SOFRERAM ATRASO NO DEPARTURE
        # essa coluna 8 possui o código da companhia
        companhias = []

        len_coluna = len(self.__data[0:])
        # Comprova se o ano ingressado é igual ao ano do arquivo
        if self.__data[1][0] == ano:
            for i in range(1, len_coluna):
                if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0:
                    companhias.append(self.__data[i][8])

        # Se o código da companhia que sofreu atraso NO DEPARTURE (companhias) for igual
        # ao código da lista carriers, é adicionado um novo elemento na lista_companhias, contendo
        # o nome do aeroporto que sofreu atraso

        lista_companhias = []

        if len(data) > len(companhias):

            for i in range (len(companhias)):
                for j in range (len(data)):
                    if companhias[i] == data[j][0]:
                        lista_companhias.append(data[j][1])
        else:

            for i in range (len(data)):
                for j in range (len(companhias)):
                    if data[i] == companhias[j][0]:
                        lista_companhias.append(companhias[j][1])

        return lista_companhias

    def companhia_mais_atrasos(self, path_carriers, ano):

        # Puxando o resultado da função acima
        x = Aeroportos(self.__path)
        companhias_atrasos_departures = x.companhias_atrasos_departure(path_carriers,ano)

        # Conta as ocorrencias de cada aeroporto na lista_aeroportos (versão comprida)
        # e retorna um dicionário ordenado de valores mayores a menores

        num_atrasos = dict(Counter(companhias_atrasos_departures)) # Observe that counts are always displayed in descending order.

        sorted_num_atrasos = dict(sorted(num_atrasos.items(), key=operator.itemgetter(1),reverse=True))

        num_maior_atrasos = list(sorted_num_atrasos.items())

        return num_maior_atrasos[0]
    """
    2.4) Listar qual aeroporto teve o maior número de atrasos (atrasos somente na decolagem).
    """
    def aeroporto_mais_atrasos(self, path_airports, ano):

        #Puxando o resultado do exercício 1.4
        x = Aeroportos(self.__path)
        lista_aeroporotos_comprida = x.aeroportos_atrasos_comprida(path_airports,ano)

        # Conta as ocorrencias de cada aeroporto na lista_aeroportos (versão comprida)
        # e retorna um dicionário

        num_atrasos = dict(Counter(lista_aeroporotos_comprida))

        sorted_num_atrasos = dict(sorted(num_atrasos.items(), key=operator.itemgetter(1),reverse=True))

        num_maior_atrasos = list(sorted_num_atrasos.items())

        return num_maior_atrasos[0]
    """
    2.5) Descobrir a média de atrasos na decolagem de cada voo;
    """
    def media_atrasos_decolagem(self):

        atrasos_decolagem = []
        len_coluna = len(self.__data[0:])
        cont = 0
        soma_atrasos = 0

        for i in range(1,len_coluna):
            if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0:
                atrasos_decolagem.append(self.__data[i][15])
                soma_atrasos += int(self.__data[i][15])
                cont += 1

        media_atrasos = soma_atrasos/cont

        return media_atrasos
    """
    2.6) Descobrir o voo com maior atraso em média e mostrar qual a média de atraso;
    """
    def voo_maior_atraso(self): #na decolagem

        atrasos_decolagem = []
        len_coluna = len(self.__data[0:])
        cont = 0
        soma_atrasos = 0
        maior = 0

        for i in range(1,len_coluna):
            if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0:

                atrasos_decolagem.append(self.__data[i][15])
                soma_atrasos += int(self.__data[i][15])
                cont += 1

                if int(self.__data[i][15]) > maior:
                    maior = int(self.__data[i][15])
                    voo = self.__data[i][9]

        media_atrasos = soma_atrasos/cont

        print(f'O numero do voo com maior atraso na decolagem é {voo} com atraso igual a {maior} minutos')
        print(f'A média de atraso dos voos na decolagem é {media_atrasos}')

        return media_atrasos
    """
    2.7) Descobrir dia da semana com maior número de atrasos e mostrar o número médio de atrasos;
    """
    def dia_mais_atrasos(self):
        # dia da semana com maior número de atrasos
        dia = []
        len_coluna = len(self.__data[0:])

        for i in range(1,len_coluna):
            if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0:
                dia.append(self.__data[i][3])

        dia_atrasos = dict(Counter(dia))
        sorted_dia_atrasos = dict(sorted(dia_atrasos.items(), key=operator.itemgetter(1),reverse=True))
        dia_mais_atrasos = list(sorted_dia_atrasos.items())

        # media de atrados do dia con mais atrasos
        media = 0
        cont = 0

        for i in range(1,len_coluna):
            if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0 and self.__data[i][3] == dia_mais_atrasos[0][0] :
                media += int(self.__data[i][15])
                cont += 1

        print(f'O dia da semana com mais atrasos é o {dia_mais_atrasos[0][0]} com média de atrasos igual a {media/cont} minutos')
        return dia_mais_atrasos[0][0]
    """
    2.8) Descobrir mês do ano com maior número de atrasos e mostrar o número de atrasos;
    """
    def mes_mais_atrasos(self):
        # mes do ano com maior número de atrasos
        mes = []
        len_coluna = len(self.__data[0:])

        for i in range(1,len_coluna):
            if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0:
                mes.append(self.__data[i][1])

        mes_atrasos = dict(Counter(mes))
        sorted_mes_atrasos = dict(sorted(mes_atrasos.items(), key=operator.itemgetter(1),reverse=True))
        mes_mais_atrasos = list(sorted_mes_atrasos.items())

        # media de atrados do dia con mais atrasos
        media = 0
        cont = 0

        for i in range(1,len_coluna):
            if self.__data[i][15] != 'NA' and int(self.__data[i][15]) > 0 and self.__data[i][1] == mes_mais_atrasos[0][0] :
                media += int(self.__data[i][15])
                cont += 1

        print(f'O mes com mais atrasos é o {mes_mais_atrasos[0][0]} com média de atrasos igual a {media/cont} minutos')
        return mes_mais_atrasos[0][0]
    """
    2.9) Listar aeroporto com o maior número de cancelamentos;
    """
    def aeroportos_mais_cancelamentos(self, path_airports, ano):

        f = open(path_airports, "r")
        data = f.readlines()
        f.close()

        # Tira as aspas do arquivo 'airports' e cria uma matriz (data) do conteúdo do arquivo
        # data[i][0] = iata
        # data[i][1] = airport
        # data[i][2] = city
        # data[i][3] = state
        # ...
        # data[i][6] = long

        for i in range(len(data)):
            data[i] = data[i].replace('\n' , '').replace('"', "").split(",")

        # Cria uma lista (aeroportos) do conteúdo da coluna 16 = 'Origin' do arquivo ano.csv
        # contendo só os códigos dos AEROPORTOS que SOFRERAM CANCELAMENTO DE VOOS
        # essa coluna 16 possui o código do aeroporto em que decolou o avião

        aeroportos = []

        len_coluna = len(self.__data[0:])
        # Comprova se o ano ingressado é igual ao ano do arquivo
        if self.__data[1][0] == ano:
            for i in range(1, len_coluna):
                if int(self.__data[i][21]) > 0:
                    aeroportos.append(self.__data[i][16])

        # Se o código do aeroporto que sofreu atraso (aeroportos) for igual
        # ao código do aeroporto na lista 'airports' (coluna 0 da matriz data), é adicionado um novo elemento na lista_aeroporots,
        # contendo o nome do aeroporto que sofreu atraso

        lista_aeroportos = []

        if len(data) > len(aeroportos):

            for i in range (len(aeroportos)):
                for j in range (len(data)):
                    if aeroportos[i] == data[j][0]:
                        lista_aeroportos.append(data[j][1])
        else:

            for i in range (len(data)):
                for j in range (len(aeroportos)):
                    if data[i] == aeroportos[j][0]:
                        lista_aeroportos.append(aeroportos[j][1])

        aeroportos_cancelados = dict(Counter(lista_aeroportos))
        sorted_aeroportos_cancelados = dict(sorted(aeroportos_cancelados.items(), key=operator.itemgetter(1),reverse=True))
        aeroporto_mais_cancelados = list(sorted_aeroportos_cancelados.items())

        return aeroporto_mais_cancelados[0][0]
    """
    2.10) Listar voo com maior número de cancelamentos;
    """
    def voo_mais_cancelamentos(self):

        voos = []
        len_coluna = len(self.__data[0:])

        for i in range(1,len_coluna):
            if int(self.__data[i][21]) > 0:
                voos.append(self.__data[i][9])

        voos_cancelados = dict(Counter(voos))
        sorted_voos_cancelados = dict(sorted(voos_cancelados.items(), key=operator.itemgetter(1),reverse=True))
        voo_mais_cancelado = list(sorted_voos_cancelados.items())

        print(f'O número do voo mais cancelado é {voo_mais_cancelado[0][0]}')

        return voo_mais_cancelado[0][0]

#x = Aeroportos('2006.csv')
y = Aeroportos('teste_2006.csv')
# x.open()
# a = y.atrasos('2006')
# a = y.companhias_atrasos_comprida('carriers.csv', '2006')
# a = y.companhias_atrasos_pequena('carriers.csv', '2006')

# a = y.aeroportos_atrasos_comprida('airports.csv', '2006')
# b = y.aeroportos_atrasos_pequena('airports.csv', '2006')
# print(b)
# a = y.num_atrasos_aeroporto('airports.csv', '2006')
# a = y.num_atrasos_companhia('carriers.csv', '2006')

# a = y.companhias_atrasos_departure('carriers.csv', '2006')
# b = y.companhias_atrasos_comprida('carriers.csv', '2006')
# print(a)
# print(b)
# a = y.companhia_mais_atrasos('carriers.csv', '2006')
# a = y.aeroporto_mais_atrasos('airports.csv', '2006')
# a = y.media_atrasos_decolagem()
# a = y.voo_maior_atraso()
# a = y.dia_mais_atrasos()
# a = y.mes_mais_atrasos()
# a = y.aeroportos_mais_cancelamentos('airports.csv', '2006')
a = y.voo_mais_cancelamentos()
print(a)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License,
    or (at your option) any later version.

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

    You should have received a copy of the GNU General Public License
    along with this program; if not, see <http://www.gnu.org/licenses/>.

    @author: jeix
"""

import re
from pycurl import HTTPHEADER
from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp
from module.common.json_layer import json_loads

class UploadingCom(SimpleHoster):
    __name__ = "UploadingCom"
    __type__ = "hoster"
    __pattern__ = r"http://(?:www\.)?uploading\.com/files/(?:get/)?(?P<ID>[\w\d]+)"
    __version__ = "0.32"
    __description__ = """Uploading.Com File Download Hoster"""
    __author_name__ = ("jeix", "mkaay", "zoidberg")
    __author_mail__ = ("jeix@hasnomail.de", "mkaay@mkaay.de", "zoidberg@mujmail.cz")

    FILE_NAME_PATTERN = r'<title>Download (?P<N>.*?) for free on uploading.com</title>'
    FILE_SIZE_PATTERN = r'File size: (?P<S>.*?)'
    FILE_OFFLINE_PATTERN = r'
The requested file is not found
'

    def process(self, pyfile):
        # set lang to english
        self.req.cj.setCookie("uploading.com", "lang", "1")
        self.req.cj.setCookie("uploading.com", "language", "1")
        self.req.cj.setCookie("uploading.com", "setlang", "en")
        self.req.cj.setCookie("uploading.com", "_lang", "en")

        if not "/get/" in self.pyfile.url:
            self.pyfile.url = self.pyfile.url.replace("/files", "/files/get")

        self.html = self.load(pyfile.url, decode = True)
        self.file_info = self.getFileInfo()

        if self.premium:
            self.handlePremium()
        else:
            self.handleFree()

    def handlePremium(self):
        postData = {'action': 'get_link',
                    'code': self.file_info['ID'],
                    'pass': 'undefined'}

        self.html = self.load('http://uploading.com/files/get/?JsHttpRequest=%d-xml' % timestamp(), post=postData)
        url = re.search(r'"link"\s*:\s*"(.*?)"', self.html)
        if url:
            url = url.group(1).replace("\\/", "/")
            self.download(url)

        raise Exception("Plugin defect.")

    def handleFree(self):
        found = re.search('
((Daily )?Download Limit)
', self.html)
        if found:
            self.pyfile.error = found.group(1)
            self.logWarning(self.pyfile.error)
            self.retry(max_tries=6, wait_time = 21600 if found.group(2) else 900, reason = self.pyfile.error)

        ajax_url = "http://uploading.com/files/get/?ajax"
        self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
        self.req.http.lastURL = self.pyfile.url

        response = json_loads(self.load(ajax_url, post = {'action': 'second_page', 'code': self.file_info['ID']}))
        if 'answer' in response and 'wait_time' in response['answer']:
            wait_time = int(response['answer']['wait_time'])
            self.log.info("%s: Waiting %d seconds." % (self.__name__, wait_time))
            self.setWait(wait_time)
            self.wait()
        else:
            self.pluginParseError("AJAX/WAIT")

        response = json_loads(self.load(ajax_url, post = {'action': 'get_link', 'code': self.file_info['ID'], 'pass': 'false'}))
        if 'answer' in response and 'link' in response['answer']:
            url = response['answer']['link']
        else:
            self.pluginParseError("AJAX/URL")

        self.html = self.load(url)
        found = re.search(r'<form id="file_form" action="(.*?)"', self.html)
        if found:
            url = found.group(1)
        else:
            self.pluginParseError("URL")

        self.download(url)

        check = self.checkDownload({"html" : re.compile("\A<!DOCTYPE html PUBLIC")})
        if check == "html":
            self.logWarning("Redirected to a HTML page, wait 10 minutes and retry")
            self.setWait(600, True)
            self.wait()

getInfo = create_getInfo(UploadingCom)


import pandas as pd, numpy as np
import os, glob
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

path = r"C:\Users\Domen Brunček\Desktop\FRI\4 semester\Data Mining\Project\podatki"

all_files = glob.glob(os.path.join(path, "*.csv"))
df = pd.concat((pd.read_csv(f, header=None, sep='\t', usecols=[1,12,13]) for f in all_files), ignore_index=True)

data = df.loc[df[12] > 0].groupby(1)[[1,13]].mean()
print(data)

dnevi = ['Ponedeljek', 'Torek', 'Sreda', 'Četrtek', 'Petek', 'Sobota', 'Nedelja']
y_pos = np.arange(len(dnevi))
clicks = data.values[:, 1]

ax = plt.axes()
ax.yaxis.set_major_formatter(ticker.PercentFormatter(1.0, decimals=2))

plt.bar(y_pos, clicks, align='center', alpha=0.5)
plt.xticks(y_pos, dnevi)
plt.ylabel('CTR')

plt.show()


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

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('homepage', '0001_initial'),
    ]

    operations = [
        migrations.AlterField(
            model_name='ratings',
            name='feedbackid',
            field=models.ForeignKey(db_column='feedbackid', default='lololol', to='homepage.Feedbacks'),
        ),
    ]


#!/usr/bin/env python3

import warnings
warnings.filterwarnings("ignore", category=FutureWarning)
warnings.filterwarnings("ignore", category=DeprecationWarning)

import os
import random
import argparse
import shutil

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--src', help='Path of source directory', type=str)
    parser.add_argument('--ext', help='Extension of files to move. Default = .png', type=str)
    parser.add_argument('--target', help='Path of target directory', type=str)
    parser.add_argument('--count', help='Number of items to be moved. Default = 1', type=str)
    parser.add_argument('--all', help='Moves all files, overrides random',default=False,action='store_true')
    args = parser.parse_args()

    if args.src is None:
        print("Please specify the source directory")
        exit(1)

    if args.target is None:
        print("Please specify the target directory")
        exit(1)

    if args.ext is None:
        args.ext='.png'

    if args.count is None:
        args.count=1

    print("Moving.. ")

    if args.all:
        print('In args all')
        for file in os.listdir(args.src):
            print(file)
            if file.endswith(args.ext):
                shutil.move(args.src+"\\"+file,args.target+"\\"+file)
    else:
        i=1
        while i <= int(args.count):
            file_name=random.choice(os.listdir(args.src))
            shutil.move(args.src+"\\"+file_name,args.target+"\\"+file_name)
            i+=1

if __name__ == '__main__':
    main()


from django.test import TestCase
from chai import Chai
from models import Poll
import models
import datetime

class PollShowTestCase(Chai, TestCase):

    def test_shows_only_visable_poll(self):
        poll = self.mock()

        self.expect(Poll.objects.get).args(id='1').returns(poll)
        self.expect(poll.is_visable).returns(True)
        res = self.client.get("/poll/show/1/")
        self.assert_equals(res.context['poll'], poll)

    def test_rediects_if_poll_is_not_visiable(self):
        poll = self.mock()

        self.expect(Poll.objects.get).args(id='1').returns(poll)
        self.expect(poll.is_visable).returns(False)
        res = self.client.get("/poll/show/1/")
        self.assert_equals(res.status_code, 302)

class PollModelTestCase(Chai, TestCase):

    def setUp(self):
        super(PollModelTestCase, self).setUp()
        self.subject = Poll()

    def test_is_visable(self):
        now = datetime.datetime.now()

        dt = self.mock()
        mock_dt = self.mock(models, 'datetime')
        self.expect(mock_dt.now).returns(now)
        self.subject.publish_date = now
        assert self.subject.is_visable()

    def test_is_not_visable(self):
        now = datetime.datetime.now()

        dt = self.mock()
        mock_dt = self.mock(models, 'datetime')
        self.expect(mock_dt.now).returns(now)
        self.subject.publish_date =  now - datetime.timedelta(days=10)
        assert not self.subject.is_visable()


# 单个元素
# find_element_by_id
# find_element_by_name
# find_element_by_xpath
# find_element_by_link_text
# find_element_by_partial_link_text
# find_elememt_by_tag_name
# find_elememt_by_class_name
# find_elememt_by_css_selector

# 多个元素
# find_elememts_by_name
# find_elememts_by_xpath
# find_elememts_by_link_text
# find_elememts_by_partial_link_text
# find_elememts_by_tag_name
# find_elememts_by_class_name
# find_elememts_by_css_selector

from selenium import webdriver
import time

driver = webdriver.PhantomJS(executable_path=r"D:\phantomjs\bin\phantomjs.exe")  # 调用phantomJS
driver.get("https://www.python.org/")  # 打开页面的网址
time.sleep(10)

by_id = driver.find_element_by_id('downloads').get_attribute('innerHTML')
print(by_id)
driver.close()

自动化脚本/如何定位元素.py


import deep_ga
import tensorflow as tf
from tensorflow import keras
import os
import matplotlib.pyplot as plt

class AssertWeightsFinite(keras.callbacks.Callback):
    def __init__(self):
        super(AssertWeightsFinite, self).__init__()

    def on_epoch_end(self, epoch, logs=None):
        for weight in self.model.weights:
            if not tf.math.reduce_all(tf.math.is_finite(weight)):
                print(f"Weight {weight.name} not finite, stop training")
                self.model.stop_training = True
                break

class PlotPrediction(keras.callbacks.Callback):
    def __init__(self, folder, tgen, vgen, save=True):
        self.folder = folder
        self.tgen = tgen
        self.vgen = vgen
        self.save = save
        if self.save:
            os.makedirs(folder, exist_ok=True)
        super(PlotPrediction, self).__init__()

    def on_epoch_end(self, epoch, logs=None):
        ylabel = ("Match Probability"
                  if self.model.loss.__name__ == "BCE"
                  else "Predicted distance")
        tx, ty = self.tgen.get_batch(200)
        typ = self.model.predict(tx)[:, 0]
        plt.clf()
        plt.scatter(ty, typ, 2)
        plt.title("Training Data")
        plt.xlabel("Distance between local and global patch")
        plt.xlim(0, plt.xlim()[1])
        plt.ylim(0, plt.ylim()[1])
        if self.model.loss.__name__ == "BCE":
            plt.ylim(0, 1)
        plt.ylabel(ylabel)
        if self.save:
            plt.savefig(os.path.join(self.folder, f"train_{epoch:03}.pdf"))
        else:
            plt.show()

        vx, vy = self.vgen.get_batch(200)
        vyp = self.model.predict(vx)[:, 0]
        plt.clf()
        plt.scatter(vy, vyp, 2)
        plt.title("Validation Data")
        plt.xlabel("Distance between local and global patch")
        plt.xlim(0, plt.xlim()[1])
        plt.ylim(0, plt.ylim()[1])
        if self.model.loss.__name__ == "BCE":
            plt.ylim(0, 1)
        plt.ylabel(ylabel)
        if self.save:
            plt.savefig(os.path.join(self.folder, f"valid_{epoch:03}v.pdf"))
        else:
            plt.show()

class ValidationProgbar(keras.callbacks.Callback):
    def __init__(self, vgen):
        self.pbar = None
        self.N = len(vgen)
        super(ValidationProgbar, self).__init__()

    def on_test_batch_end(self, batch, logs=None):
        if batch == 0:
            print("\nValidation:")
            self.pbar = keras.utils.Progbar(
                self.N, stateful_metrics=logs.keys())
        self.pbar.add(1, values=logs.items())


"""
Infinite evaluation loop going through the checkpoints in the model directory
as they appear and evaluating them. Accuracy and average loss are printed and
added as tensorboard summaries.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from datetime import datetime
import json
import math
import os
import sys
import time

import tensorflow as tf

from pgd.fmnist.model import Model
from pgd.fmnist.pgd_attack import LinfPGDAttack
from torchvision import datasets
from torch.utils.data import DataLoader

from sargan_dep.sargan_models import SARGAN
from sargan_dep.sar_utilities import add_gaussian_noise
from scipy.ndimage.filters import gaussian_filter
import numpy as np
from torchvision.transforms import Compose, ToTensor,  Resize
from PIL import Image
data_root='sar_data/FMNIST'

def cycle(iterable):
    while True:
        for x in iterable:
            yield x
def get_data(train_batch_size):

    data_transform = Compose([ToTensor()])

    train_loader = DataLoader(datasets.FashionMNIST(root=data_root, train=True, transform=data_transform, target_transform=None, download=True),
                              batch_size=train_batch_size, shuffle=True)

    return train_loader
global_step = tf.contrib.framework
# Global constants
with open('pgd/fmnist/config_fmnist.json') as config_file:
  config = json.load(config_file)
num_eval_examples = 64
eval_batch_size = 64
eval_on_cpu = config['eval_on_cpu']

model_dir = config['model_dir-n']
# Set upd the data, hyperparameters, and the model

img_size = [28,28,1]
trained_model_path = 'trained_models/sargan_fmnist-x1-1'
trained_model_path2 = 'trained_models/sargan_fmnist-x2-1'
trained_model_path3 = 'trained_models/sargan_fmnist-x3-1'
trained_model_path4 = 'trained_models/sargan_fmnist-x4-1'
BATCH_SIZE = 64
NOISE_STD_RANGE = [0.0, 0.2]

if eval_on_cpu:
  with tf.device("/cpu:0"):
      model = Model()
      attack = LinfPGDAttack(model,
                           .08,#config['epsilon'],
                           config['k'],
                           config['a'],
                           config['random_start'],
                           config['loss_func'])
else:
    model = Model()
    attack = LinfPGDAttack(model,
                         config['epsilon'],
                         config['k'],
                         config['a'],
                         config['random_start'],
                         config['loss_func'])

global_step = tf.contrib.framework.get_or_create_global_step()
# Setting up the Tensorboard and checkpoint outputs
if not os.path.exists(model_dir):
  os.makedirs(model_dir)
eval_dir = os.path.join(model_dir, 'eval')
if not os.path.exists(eval_dir):
  os.makedirs(eval_dir)

last_checkpoint_filename = ''
already_seen_state = False
saver = tf.train.Saver()
#summary_writer = tf.summary.FileWriter(eval_dir)
# A function for evaluating a single checkpoint
# A function for evaluating a single checkpoint
def evaluate_checkpoint(filename):
    #sys.stdout = open(os.devnull, 'w')
    #Different graphs for all the models
    gx1 =tf.Graph()
    gx2 =tf.Graph()
    gx3 =tf.Graph()
    gx4 =tf.Graph()
    with tf.Session() as sess:
    # Restore the checkpoint
        saver.restore(sess, filename);

        # Iterate over the samples batch-by-batch
        #number of batches
        num_batches = int(math.ceil(num_eval_examples / eval_batch_size))

        x_blur_list4=[]
        x_adv_list4=[]
        #Storing y values

        train_loader= get_data(BATCH_SIZE)
        trainiter = iter(cycle(train_loader))
        for ibatch in range(num_batches):

            x_batch2, y_batch = next(trainiter)
            x_batch2 = np.array(x_batch2.data.numpy().transpose(0,2,3,1))
            x_batch=np.zeros([len(x_batch2),img_size[0]*img_size[1]])

            x_batch3=np.zeros([img_size[0],img_size[1]])
            x_batch3[:,:]=x_batch2[0,:,:,0]*255
            nextimage=Image.fromarray(x_batch3.astype(np.uint8))
            nextimage.save("FMNIST_NATURALX0.Jpg","JPEG")

            for i in range(len(x_batch2)):
                x_batch[i]=x_batch2[i].reshape([img_size[0]*img_size[1]])
            x_batch_adv = attack.perturb(x_batch, y_batch, sess)

            x_batch2=np.zeros([len(x_batch),img_size[0],img_size[1],img_size[2]])
            x_batch_adv2=np.zeros([len(x_batch),img_size[0],img_size[1],img_size[2]])
            for k in range(len(x_batch)):
                x_batch2[k]=add_gaussian_noise(x_batch[k].reshape([img_size[0],img_size[1],img_size[2]]), sd=np.random.uniform(NOISE_STD_RANGE[1], NOISE_STD_RANGE[1]))
                x_batch_adv2[k]=add_gaussian_noise(x_batch_adv[k].reshape([img_size[0],img_size[1],img_size[2]]), sd=np.random.uniform(NOISE_STD_RANGE[1], NOISE_STD_RANGE[1]))

            x_blur_list4.append(x_batch2)
            x_adv_list4.append(x_batch_adv2)

            x_batch3=np.zeros([img_size[0],img_size[1]])
            x_batch3[:,:]=x_blur_list4[0][0,:,:,0]*255
            nextimage=Image.fromarray(x_batch3.astype(np.uint8))
            nextimage.save("FMNIST_BLURX0.Jpg","JPEG")
            x_batch3=np.zeros([img_size[0],img_size[1]])
            x_batch3[:,:]=x_adv_list4[0][0,:,:,0]*255
            nextimage=Image.fromarray(x_batch3.astype(np.uint8))
            nextimage.save("FMNIST_ADVX0.Jpg","JPEG")

    #Running through first autoencoder
    with gx1.as_default():
        with tf.Session() as sess2:
            sargan_model=SARGAN(img_size, BATCH_SIZE, img_channel=1)
            sargan_saver= tf.train.Saver()
            sargan_saver = tf.train.import_meta_graph(trained_model_path+'/sargan_mnist.meta');
            sargan_saver.restore(sess2,tf.train.latest_checkpoint(trained_model_path));
            for ibatch in range(num_batches):
                processed_batch=sess2.run(sargan_model.gen_img,feed_dict={sargan_model.image: x_adv_list4[ibatch], sargan_model.cond: x_adv_list4[ibatch]})
                x_adv_list4[ibatch]=processed_batch

                blurred_batch=sess2.run(sargan_model.gen_img,feed_dict={sargan_model.image: x_blur_list4[ibatch], sargan_model.cond: x_blur_list4[ibatch]})
                x_blur_list4[ibatch]=blurred_batch

            x_batch3[:,:]=x_blur_list4[0][0,:,:,0]*255
            nextimage=Image.fromarray(x_batch3.astype(np.uint8))
            nextimage.save("FMNIST_BLURX1.Jpg","JPEG")
            x_batch3=np.zeros([img_size[0],img_size[1]])
            x_batch3[:,:]=x_adv_list4[0][0,:,:,0]*255
            nextimage=Image.fromarray(x_batch3.astype(np.uint8))
            nextimage.save("FMNIST_ADVX1.Jpg","JPEG")

    with gx2.as_default():
        with tf.Session() as sessx2:
            sargan_model2=SARGAN(img_size, BATCH_SIZE, img_channel=1)
            sargan_saver2= tf.train.Saver()
            sargan_saver2 = tf.train.import_meta_graph(trained_model_path2+'/sargan_mnist.meta');
            sargan_saver2.restore(sessx2,tf.train.latest_checkpoint(trained_model_path2));
            for ibatch in range(num_batches):
                processed_batch=sessx2.run(sargan_model2.gen_img,feed_dict={sargan_model2.image: x_adv_list4[ibatch], sargan_model2.cond: x_adv_list4[ibatch]})
                x_adv_list4[ibatch]=(processed_batch)

                blurred_batch=sessx2.run(sargan_model2.gen_img,feed_dict={sargan_model2.image: x_blur_list4[ibatch], sargan_model2.cond: x_blur_list4[ibatch]})
                x_blur_list4[ibatch]=(blurred_batch)
            x_batch3=np.zeros([img_size[0],img_size[1]])
            x_batch3[:,:]=x_blur_list4[0][0,:,:,0]*255
            nextimage=Image.fromarray(x_batch3.astype(np.uint8))
            nextimage.save("FMNIST_BLURX2.Jpg","JPEG")
            x_batch3=np.zeros([img_size[0],img_size[1]])
            x_batch3[:,:]=x_adv_list4[0][0,:,:,0]*255
            nextimage=Image.fromarray(x_batch3.astype(np.uint8))
            nextimage.save("FMNIST_ADVX2.Jpg","JPEG")

    with gx3.as_default():
        with tf.Session() as sessx3:
            sargan_model3=SARGAN(img_size, BATCH_SIZE, img_channel=1)
            sargan_saver3= tf.train.Saver()
            sargan_saver3 = tf.train.import_meta_graph(trained_model_path3+'/sargan_mnist.meta');
            sargan_saver3.restore(sessx3,tf.train.latest_checkpoint(trained_model_path3));
            for ibatch in range(num_batches):
                processed_batch=sessx3.run(sargan_model3.gen_img,feed_dict={sargan_model3.image: x_adv_list4[ibatch], sargan_model3.cond: x_adv_list4[ibatch]})
                x_adv_list4[ibatch]=processed_batch

                blurred_batch=sessx3.run(sargan_model3.gen_img,feed_dict={sargan_model3.image: x_blur_list4[ibatch], sargan_model3.cond: x_blur_list4[ibatch]})
                x_blur_list4[ibatch]=blurred_batch

            x_batch3=np.zeros([img_size[0],img_size[1]])
            x_batch3[:,:]=x_blur_list4[0][0,:,:,0]*255
            nextimage=Image.fromarray(x_batch3.astype(np.uint8))
            nextimage.save("FMNIST_BLURX3.Jpg","JPEG")
            x_batch3=np.zeros([img_size[0],img_size[1]])
            x_batch3[:,:]=x_adv_list4[0][0,:,:,0]*255
            nextimage=Image.fromarray(x_batch3.astype(np.uint8))
            nextimage.save("FMNIST_ADVX3.Jpg","JPEG")

    #Final autoencoder setup
    with gx4.as_default():
        with tf.Session() as sessx4:
            sargan_model4=SARGAN(img_size, BATCH_SIZE, img_channel=1)
            sargan_saver4= tf.train.Saver()
            sargan_saver4 = tf.train.import_meta_graph(trained_model_path4+'/sargan_mnist.meta');
            sargan_saver4.restore(sessx4,tf.train.latest_checkpoint(trained_model_path4));
            for ibatch in range(num_batches):
                processed_batch=sessx4.run(sargan_model4.gen_img,feed_dict={sargan_model4.image: x_adv_list4[ibatch], sargan_model4.cond: x_adv_list4[ibatch]})
                x_adv_list4[ibatch]=processed_batch.reshape([len(x_batch),img_size[0]*img_size[1]])

                x_batch3=np.zeros([img_size[0],img_size[1]])
                x_batch3[:,:]=processed_batch[0,:,:,0]*255
                nextimage=Image.fromarray(x_batch3.astype(np.uint8))
                nextimage.save("FMNIST_ADVX4.Jpg","JPEG")

                blurred_batch=sessx4.run(sargan_model4.gen_img,feed_dict={sargan_model4.image: x_blur_list4[ibatch], sargan_model4.cond: x_blur_list4[ibatch]})
                x_blur_list4[ibatch]=blurred_batch.reshape([len(x_batch),img_size[0]*img_size[1]])

                x_batch3=np.zeros([img_size[0],img_size[1]])
                x_batch3[:,:]=blurred_batch[0,:,:,0]*255
                nextimage=Image.fromarray(x_batch3.astype(np.uint8))
                nextimage.save("FMNIST_BLURX4.Jpg","JPEG")

# eval loop
cur_checkpoint = tf.train.latest_checkpoint(model_dir)
evaluate_checkpoint(cur_checkpoint)
time.sleep(10)


# uncompyle6 version 3.7.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.6.9 (default, Apr 18 2020, 01:56:04)
# [GCC 8.4.0]
# Embedded file name: build/bdist.linux-x86_64/egg/turkish_morphology/validate.py
# Compiled at: 2020-03-21 19:20:28
# Size of source mod 2**32: 4957 bytes
"""Functions to validate structural well-formedness of analysis protobufs."""
from typing import Optional
from turkish_morphology import analysis_pb2
_Affix = analysis_pb2.Affix
_Analysis = analysis_pb2.Analysis
_Feature = analysis_pb2.Feature
_Ig = analysis_pb2.InflectionalGroup
_Root = analysis_pb2.Root

class IllformedAnalysisError(Exception):
    __doc__ = 'Raised when a human-readable analysis is structurally ill-formed.'

def _root(root: _Root) -> None:
    """Checks if root is structurally well-formed.

  Args:
    root: root analysis.

  Raises:
    IllformedAnalysisError: root is missing the morpheme field, or its
      morpheme field is set as empty string.
  """
    if not root.HasField('morpheme'):
        raise IllformedAnalysisError(f"Root is missing morpheme: '{root}'")
    if not root.morpheme:
        raise IllformedAnalysisError(f"Root morpheme is empty: '{root}'")

def _feature(feature: _Feature) -> None:
    """Checks if feature is structurally well-formed.

  Args:
    feature: morphological analysis feature.

  Raises:
    IllformedAnalysisError: feature is missing category or value field, or
      its category or value field is set as empty string.
  """
    if not feature.HasField('category'):
        raise IllformedAnalysisError(f"Feature is missing category: '{feature}'")
    else:
        if not feature.category:
            raise IllformedAnalysisError(f"Feature category is empty: '{feature}'")
        if not feature.HasField('value'):
            raise IllformedAnalysisError(f"Feature is missing value: '{feature}'")
        assert feature.value, f"Feature value is empty: '{feature}'"

def _affix(affix: _Affix, derivational: Optional[bool]=False) -> None:
    """Checks if affix is structurally well-formed.

  Args:
    affix: affix analysis.
    derivational: if True, affix corresponds to a derivational feature.

  Raises:
    IllformedAnalysisError: affix is missing the feature field, or affix is
      derivational but its meta_morpheme field is missing or its meta_morpheme
      field is set as empty string.
  """
    if not affix.HasField('feature'):
        raise IllformedAnalysisError(f"Affix is missing feature: '{affix}'")
    else:
        _feature(affix.feature)
        if not derivational:
            return
        if not affix.HasField('meta_morpheme'):
            raise IllformedAnalysisError(f"Derivational affix is missing meta-morpheme: '{affix}'")
        assert affix.meta_morpheme, f"Derivational affix meta-morpheme is empty: '{affix}'"

def _inflectional_group(ig: _Ig, position: int) -> None:
    """Checks if inflectional group is structurally well-formed.

  Args:
    ig: inflectional group analysis.
    position: index of the inflectional group w.r.t. the array of inflectional
      groups of the morphological analysis it belongs to.

  Raises:
    IllformedAnalysisError: inflectional group is missing part-of-speech tag,
      or its part-of-speech tag is set as empty string, or inflectional group
      is the first in morphological analysis and it is missing the root field,
      or inflectional group is derived and it is missing the derivation field.
  """
    if not ig.HasField('pos'):
        raise IllformedAnalysisError(f"Inflectional group {position + 1} is missing part-of-speech tag: '{ig}'")
    if not ig.pos:
        raise IllformedAnalysisError(f"Inflectional group {position + 1} part-of-speech tag is empty: '{ig}'")
    if position == 0:
        if not ig.HasField('root'):
            raise IllformedAnalysisError(f"Inflectional group {position + 1} is missing root: '{ig}'")
        _root(ig.root)
    else:
        if not ig.HasField('derivation'):
            raise IllformedAnalysisError(f"Inflectional group {position + 1} is missing derivational affix: '{ig}'")
        _affix((ig.derivation), derivational=True)
    for inflection in ig.inflection:
        _affix(inflection)

def analysis(analysis: _Analysis) -> None:
    """Checks if analysis protobuf is structurally well-formed.

  Args:
    analysis: morphological analysis.

  Raises:
    IllformedAnalysisError: analysis is missing inflectional groups.
  """
    if not analysis.ig:
        raise IllformedAnalysisError("Analysis is missing inflectional groups: 'analysis'")
    for position, ig in enumerate(analysis.ig):
        _inflectional_group(ig, position)


from django.shortcuts import render_to_response, render
from web.models import Items, Apartments, Interests, Notifications
from django.http import HttpResponse
from forms import ItemForm, NotificationForm
from django.http import HttpResponseRedirect
from django.core.context_processors import csrf
from django.contrib.auth.decorators import login_required
from django.db.models import Q

#main view: displays the items available
@login_required
def main(request):
    args = {}
    args.update(csrf(request))
    args['items'] = Items.objects.filter(status="Not Sold")
    args['notifications'] = Notifications.objects.filter(requestedTo=request.user, state="Pending")
    args['notifications_count'] = args['notifications'].count()
    args['transactions'] = Notifications.objects.filter(requestedFrom=request.user).order_by('item', '-bid')
    args['transactions_count'] = args['transactions'].count()
    args['online_user'] = request.user

    return render_to_response('main.html', args)

#showItem view: displays the item that was clicked on
@login_required
def showItem(request, item_id=1):
    if request.POST:
        form = NotificationForm(request.POST)
        if form.is_valid():
            #do not save yet, and add in default owners_id
            obj = form.save(commit=False)
            #add in the creator's id
            obj.requestedFrom = request.user
            obj.requestedTo = Items.objects.get(id=item_id).owners
            obj.item = Items.objects.get(id=item_id)
            obj.state = "Pending"
            #save data
            obj.save()

            return HttpResponseRedirect('/web/main/')
    else:
        form = NotificationForm()

    args = {}
    args.update(csrf(request))

    args['form'] = form
    args['item'] = Items.objects.get(id=item_id)
    args['notifications'] = Notifications.objects.filter(requestedTo=request.user, state="Pending")
    args['notifications_count'] = args['notifications'].count()
    args['transactions'] = Notifications.objects.filter(requestedFrom=request.user).order_by('item', '-bid')
    args['transactions_count'] = args['transactions'].count()
    args['online_user'] = request.user

    return render_to_response('showItem.html', args)

#createItem view: displays a form to add an item
@login_required
def createItem(request):
    if request.POST:
        form = ItemForm(request.POST, request.FILES)
        if form.is_valid():
            #do not save yet, and add in default owners_id
            obj = form.save(commit=False)
            #add in the creator's id
            obj.owners = request.user
            #add item status
            obj.status = "Not Sold"
            #save data
            obj.save()

            return HttpResponseRedirect('/web/main/')
    else:
        form = ItemForm()

    args = {}
    args.update(csrf(request))

    args['form'] = form
    args['notifications'] = Notifications.objects.filter(requestedTo=request.user, state="Pending")
    args['notifications_count'] = args['notifications'].count()
    args['transactions'] = Notifications.objects.filter(requestedFrom=request.user).order_by('item', '-bid')
    args['transactions_count'] = args['transactions'].count()
    args['online_user'] = request.user

    return render_to_response('createItem.html', args)

@login_required
def search_items(request):
    if request.method == 'POST':
        search_text = request.POST['search_text']
    else:
        search_text = ''

    #filter search by ignoring case and finding substring
    items = Items.objects.filter(name__icontains=search_text)

    return render_to_response('ajax_search.html',
                              { 'items': items })

#requests view: displays the users items
@login_required
def requests(request):
    if request.POST:
        notification_id = request.POST["notification_id"]
        item_id = request.POST["item_id"]

        notification = Notifications.objects.get(pk=notification_id)
        notification.state = "Accepted"
        notification.save()
        Notifications.objects.filter(item=notification.item,requestedTo=notification.requestedTo).exclude(pk=notification.id).update(state='Denied')

        Items.objects.filter(pk=item_id).update(status="Sold")

        return HttpResponseRedirect('/web/requests/')

    args = {}
    args.update(csrf(request))
    args['notifications'] = Notifications.objects.filter(requestedTo=request.user, state="Pending").order_by('item', '-bid')
    args['notifications_count'] = args['notifications'].count()
    args['transactions'] = Notifications.objects.filter(requestedFrom=request.user).order_by('item', '-bid')
    args['transactions_count'] = args['transactions'].count()
    args['online_user'] = request.user

    return render_to_response('requests.html', args)

#transactions view: displays the users items
@login_required
def transactions(request):
    args = {}
    args['notifications'] = Notifications.objects.filter(requestedTo=request.user, state="Pending").order_by('item', '-bid')
    args['notifications_count'] = args['notifications'].count()
    args['transactions'] = Notifications.objects.filter(requestedFrom=request.user).order_by('item', '-bid')
    args['transactions_count'] = args['transactions'].count()
    args['online_user'] = request.user

    return render_to_response('transactions.html', args)


"""
Vistas relacionadas con el modelo User (Usuarios)

Vistas
------
- List
- Read
- Create
- Update
- Delete
- ResetPassword
"""
from django.contrib.auth.models import User as main_model
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
from django.views import View

from .user_forms import frmUser as base_form
from .user_forms import frmUserBottom
from .user_forms import frmUserLeft
from .user_forms import frmUserResetPassword
from .user_forms import frmUserRight
from .user_forms import frmUserTop
from .user_forms import frmUserTopMe
from .user_forms import frmUserTopReadUpdate
from .user_forms import frmUserUpdate
from .user_models import UserProfile
from .views import GenericCreate
from .views import GenericDelete
from .views import GenericList
from .views import GenericRead
from .views import GenericUpdate
from zend_django.templatetags.op_helpers import action_label
from zend_django.templatetags.op_helpers import crud_icon
from zend_django.templatetags.op_helpers import crud_label
from zend_django.templatetags.op_helpers import crud_smart_button
from zend_django.templatetags.utils import GenerateReadCRUDToolbar

def template_base_path(file):
    return 'zend_django/user/' + file + ".html"

class List(GenericList):
    html_template = template_base_path("list")
    titulo = "Usuarios"
    titulo_descripcion = ""
    main_data_model = main_model
    model_name = "user"
    tereapp = 'administrar'

    def get_data(self, search_value=''):
        if '' == search_value:
            return list(
                self.main_data_model.objects.all().order_by('username'))
        else:
            return list(self.main_data_model.objects.filter(
                Q(first_name__icontains=search_value) |
                Q(last_name__icontains=search_value) |
                Q(profile__apellido_materno__icontains=search_value) |
                Q(email__icontains=search_value) |
                Q(username__icontains=search_value)).order_by('username'))

class Read(GenericRead):
    titulo_descripcion = "Usuario"
    model_name = "user"
    base_data_form = base_form
    main_data_model = main_model
    tereapp = 'administrar'

    def get(self, request, pk):
        if not self.main_data_model.objects.filter(pk=pk).exists():
            return HttpResponseRedirect(reverse('item_no_encontrado'))
        obj = self.main_data_model.objects.get(pk=pk)
        try:
            obj.profile
        except ObjectDoesNotExist:
            UserProfile.objects.create(user=obj)
        form = {
            'top': frmUserTopReadUpdate(instance=obj),
            'bottom': frmUserBottom(instance=obj),
            'left': frmUserLeft(instance=obj, initial={
                'apellido_materno': obj.profile.apellido_materno,
                'telefono': obj.profile.telefono,
                'celular': obj.profile.celular,
                'whatsapp': obj.profile.whatsapp,
            }),
            'right': frmUserRight(instance=obj),
        }
        toolbar = GenerateReadCRUDToolbar(
            request, self.model_name, obj, self.main_data_model)
        return render(request, self.html_template, {
            'titulo': obj,
            'titulo_descripcion': self.titulo_descripcion,
            'toolbar': toolbar,
            'footer': False,
            'read_only': True,
            'alertas': [],
            'req_chart': False,
            'search_value': '',
            'forms': {
                'top': [{'form': form['top']}],
                'bottom': [{'form': form['bottom']}],
                'left': [{'form': form['left']}],
                'right': [{'form': form['right']}],
            },
            'tereapp': self.tereapp,
        })

class Create(GenericCreate):
    titulo = "Usuario"
    model_name = "user"
    base_data_form = base_form
    tereapp = 'administrar'

    def get(self, request):
        return self.base_render(request, {
                'top': [{'form': frmUserTop()}],
                'bottom': [{'form': frmUserBottom()}],
                'left': [{'form': frmUserLeft()}],
                'right': [{'form': frmUserRight()}],
            })

    def post(self, request):
        form = self.base_data_form(request.POST)
        form_aux = {
                'top': [{'form': frmUserTop(request.POST)}],
                'bottom': [{'form': frmUserBottom(request.POST)}],
                'left': [{'form': frmUserLeft(request.POST)}],
                'right': [{'form': frmUserRight(request.POST)}],
            }
        if form.is_valid():
            obj = form.save()
            obj.set_password(form.cleaned_data['password'])
            obj.save()
            UserProfile.objects.create(
                apellido_materno=form.cleaned_data['apellido_materno'],
                telefono=form.cleaned_data['telefono'],
                celular=form.cleaned_data['celular'],
                whatsapp=form.cleaned_data['whatsapp'],
                user=obj
            )
            return HttpResponseRedirect(reverse(
                f'{self.model_name}_read',
                kwargs={'pk': obj.pk}))
        return self.base_render(request, form_aux)

class Update(GenericUpdate):
    titulo = "Usuario"
    model_name = "user"
    main_data_model = main_model
    tereapp = 'administrar'

    def base_render(self, request, form):
        return render(request, self.html_template, {
            'titulo': self.titulo,
            'titulo_descripcion': crud_label('update'),
            'toolbar': None,
            'footer': False,
            'read_only': False,
            'alertas': [],
            'req_chart': False,
            'search_value': '',
            'forms': {
                'bottom': [{'form': form['bottom']}],
                'left': [{'form': form['left']}],
                'right': [{'form': form['right']}],
            },
            'tereapp': self.tereapp
        })

    def get(self, request, pk):
        if not self.main_data_model.objects.filter(pk=pk).exists():
            return HttpResponseRedirect(reverse('item_no_encontrado'))
        obj = self.main_data_model.objects.get(pk=pk)
        form = {
            'bottom': frmUserBottom(instance=obj),
            'left': frmUserLeft(instance=obj, initial={
                'apellido_materno': obj.profile.apellido_materno,
                'telefono': obj.profile.telefono,
                'celular': obj.profile.celular,
                'whatsapp': obj.profile.whatsapp,
            }),
            'right': frmUserRight(instance=obj),
        }
        return self.base_render(request, form)

    def post(self, request, pk):
        if not self.main_data_model.objects.filter(pk=pk).exists():
            return HttpResponseRedirect(reverse('item_no_encontrado'))
        obj = self.main_data_model.objects.get(pk=pk)
        form = frmUserUpdate(instance=obj, data=request.POST)
        form_aux = {
            'bottom': frmUserBottom(request.POST),
            'left': frmUserLeft(request.POST),
            'right': frmUserRight(request.POST)
        }
        if form.is_valid():
            obj = form.save()
            obj.profile.apellido_materno = form.cleaned_data[
                'apellido_materno']
            obj.profile.telefono = form.cleaned_data['telefono']
            obj.profile.celular = form.cleaned_data['celular']
            obj.profile.whatsapp = form.cleaned_data['whatsapp']
            obj.profile.save()
            return HttpResponseRedirect(reverse(
                f'{self.model_name}_read',
                kwargs={'pk': obj.pk}))
        return self.base_render(request, form_aux)

class Delete(GenericDelete):
    model_name = "user"
    main_data_model = main_model

class ResetPassword(View):
    """
    Reseteo de contraseñas

    Miembros
    --------
    - main_data_model = User

    Métodos
    -------
    - base_render(request, form)
    - get(request, username='')
    - post(request, username='')
    """
    main_data_model = main_model
    tereapp = 'configuracion'

    def base_render(self, request, form):
        return render(request, "zend_django/html/form.html", {
            'titulo': "Usuario",
            'titulo_descripcion': action_label('reset_password'),
            'toolbar': None,
            'footer': False,
            'read_only': False,
            'alertas': [],
            'req_chart': False,
            'search_value': '',
            'forms': {'top': [{'form': form}]},
            'tereapp': self.tereapp,
        })

    def get(self, request, username=''):
        return self.base_render(request, frmUserResetPassword(
            initial={'username': username}))

    def post(self, request, username=''):
        form = frmUserResetPassword(request.POST)
        if form.is_valid():
            obj = self.main_data_model.objects.filter(
                username=form.cleaned_data['username'])
            if obj.exists():
                obj = obj[0]
                obj.set_password(form.cleaned_data['password'])
                obj.save()
                return render(
                    request,
                    template_base_path('reset_password_ok'), {
                        'titulo': "Usuario",
                        'titulo_descripcion': action_label('reset_password'),
                        'toolbar': None,
                        'footer': False,
                        'read_only': False,
                        'alertas': [],
                        'req_chart': False,
                        'tereapp': self.tereapp,
                    })
            else:
                form.add_error('username', "No existe el usuario")
        return self.base_render(request, form)

class Me(GenericUpdate):
    titulo = "Mi Perfil"
    model_name = "user"
    main_data_model = main_model

    def base_render(self, request, form):
        return render(request, self.html_template, {
            'titulo': self.titulo,
            'titulo_descripcion': None,
            'toolbar': None,
            'footer': False,
            'read_only': False,
            'alertas': [],
            'req_chart': False,
            'search_value': '',
            'forms': {
                'top': [{'title': "Mi acceso", 'form': form['top']}],
                'bottom': [{'title': "Mis datos", 'form': form['bottom']}],
            },
            'tereapp': self.tereapp
        })

    def get(self, request):
        obj = request.user
        form = {
            'bottom': frmUserLeft(instance=obj, initial={
                'apellido_materno': obj.profile.apellido_materno,
                'telefono': obj.profile.telefono,
                'celular': obj.profile.celular,
                'whatsapp': obj.profile.whatsapp,
            }),
            'top': frmUserTopMe(initial={
                'username': obj.username,
            }),
        }
        return self.base_render(request, form)

    def post(self, request):
        obj = request.user
        form = {
            'bottom': frmUserLeft(instance=obj, data=request.POST),
            'top': frmUserTopMe(data=request.POST),
        }
        if form['bottom'].is_valid() and form['top'].is_valid():
            obj = form['bottom'].save()
            obj.username = form['top'].cleaned_data['username']
            if form['top'].cleaned_data['password']:
                obj.set_password(form['top'].cleaned_data['password'])
            obj.save()
            obj.profile.apellido_materno = form['bottom'].cleaned_data[
                'apellido_materno']
            obj.profile.telefono = form['bottom'].cleaned_data['telefono']
            obj.profile.celular = form['bottom'].cleaned_data['celular']
            obj.profile.whatsapp = form['bottom'].cleaned_data['whatsapp']
            obj.profile.save()
        return self.base_render(request, form)


"""Application."""
import logging
import os
from typing import TYPE_CHECKING, Any, List, Type

from ansiblelint import formatters
from ansiblelint.color import console
from ansiblelint.errors import MatchError

if TYPE_CHECKING:
    from argparse import Namespace

_logger = logging.getLogger(__package__)

class App:
    """App class represents an execution of the linter."""

    def __init__(self, options: "Namespace"):
        """Construct app run based on already loaded configuration."""
        options.skip_list = _sanitize_list_options(options.skip_list)
        options.warn_list = _sanitize_list_options(options.warn_list)

        self.options = options

        formatter_factory = choose_formatter_factory(options)
        self.formatter = formatter_factory(options.cwd, options.display_relative_path)

    def render_matches(self, matches: List[MatchError]) -> None:
        """Display given matches."""
        if isinstance(self.formatter, formatters.CodeclimateJSONFormatter):
            # If formatter CodeclimateJSONFormatter is chosen,
            # then print only the matches in JSON
            console.print(
                self.formatter.format_result(matches), markup=False, highlight=False
            )
            return None

        ignored_matches = [match for match in matches if match.ignored]
        fatal_matches = [match for match in matches if not match.ignored]
        # Displayed ignored matches first
        if ignored_matches:
            _logger.warning(
                "Listing %s violation(s) marked as ignored, likely already known",
                len(ignored_matches),
            )
            for match in ignored_matches:
                if match.ignored:
                    # highlight must be off or apostrophes may produce unexpected results
                    console.print(self.formatter.format(match), highlight=False)
        if fatal_matches:
            _logger.warning(
                "Listing %s violation(s) that are fatal", len(fatal_matches)
            )
            for match in fatal_matches:
                if not match.ignored:
                    console.print(self.formatter.format(match), highlight=False)

        # If run under GitHub Actions we also want to emit output recognized by it.
        if os.getenv('GITHUB_ACTIONS') == 'true' and os.getenv('GITHUB_WORKFLOW'):
            formatter = formatters.AnnotationsFormatter(self.options.cwd, True)
            for match in matches:
                console.print(formatter.format(match), markup=False, highlight=False)

def choose_formatter_factory(
    options_list: "Namespace",
) -> Type[formatters.BaseFormatter[Any]]:
    """Select an output formatter based on the incoming command line arguments."""
    r: Type[formatters.BaseFormatter[Any]] = formatters.Formatter
    if options_list.format == 'quiet':
        r = formatters.QuietFormatter
    elif options_list.parseable_severity:
        r = formatters.ParseableSeverityFormatter
    elif options_list.parseable or options_list.format == 'pep8':
        r = formatters.ParseableFormatter
    elif options_list.format == 'codeclimate':
        r = formatters.CodeclimateJSONFormatter
    return r

def _sanitize_list_options(tag_list: List[str]) -> List[str]:
    """Normalize list options."""
    # expand comma separated entries
    tags = set()
    for t in tag_list:
        tags.update(str(t).split(','))
    # remove duplicates, and return as sorted list
    return sorted(set(tags))