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

"""
The WebStats Module
======================

This module makes stats on URL recolted from the web module.
It consider the TLD, Domain and protocol.

"""

import time
import datetime
import redis
import os
from packages import lib_words
from packages.Date import Date
from pubsublogger import publisher
from Helper import Process
from pyfaup.faup import Faup

# Config Var
threshold_total_sum = 200 # Above this value, a keyword is eligible for a progression
threshold_increase = 1.0  # The percentage representing the keyword occurence since num_day_to_look
max_set_cardinality = 10  # The cardinality of the progression set
num_day_to_look = 5       # the detection of the progression start num_day_to_look in the past

def analyse(server, field_name, date, url_parsed):
    field = url_parsed[field_name]
    if field is not None:
        field = field.decode('utf8')
        server.hincrby(field, date, 1)
        if field_name == "domain": #save domain in a set for the monthly plot
            domain_set_name = "domain_set_" + date[0:6]
            server.sadd(domain_set_name, field)
            print("added in " + domain_set_name +": "+ field)

def get_date_range(num_day):
    curr_date = datetime.date.today()
    date = Date(str(curr_date.year)+str(curr_date.month).zfill(2)+str(curr_date.day).zfill(2))
    date_list = []

    for i in range(0, num_day+1):
        date_list.append(date.substract_day(i))
    return date_list

# Compute the progression for one keyword
def compute_progression_word(server, num_day, keyword):
    date_range = get_date_range(num_day)
    # check if this keyword is eligible for progression
    keyword_total_sum = 0
    value_list = []
    for date in date_range: # get value up to date_range
        curr_value = server.hget(keyword, date)
        value_list.append(int(curr_value if curr_value is not None else 0))
        keyword_total_sum += int(curr_value) if curr_value is not None else 0
    oldest_value = value_list[-1] if value_list[-1] != 0 else 1 #Avoid zero division

    # The progression is based on the ratio: value[i] / value[i-1]
    keyword_increase = 0
    value_list_reversed = value_list[:]
    value_list_reversed.reverse()
    for i in range(1, len(value_list_reversed)):
        divisor = value_list_reversed[i-1] if value_list_reversed[i-1] != 0 else 1
        keyword_increase += value_list_reversed[i] / divisor

    return (keyword_increase, keyword_total_sum)

'''
    recompute the set top_progression zset
        - Compute the current field progression
        - re-compute the current progression for each first 2*max_set_cardinality fields in the top_progression_zset
'''
def compute_progression(server, field_name, num_day, url_parsed):
    redis_progression_name_set = "z_top_progression_"+field_name

    keyword = url_parsed[field_name]
    if keyword is not None:

        #compute the progression of the current word
        keyword_increase, keyword_total_sum = compute_progression_word(server, num_day, keyword)

        #re-compute the progression of 2*max_set_cardinality
        current_top = server.zrevrangebyscore(redis_progression_name_set, '+inf', '-inf', withscores=True, start=0, num=2*max_set_cardinality)
        for word, value in current_top:
            word_inc, word_tot_sum = compute_progression_word(server, num_day, word)
            server.zrem(redis_progression_name_set, word)
            if (word_tot_sum > threshold_total_sum) and (word_inc > threshold_increase):
                server.zadd(redis_progression_name_set, float(word_inc), word)

        # filter before adding
        if (keyword_total_sum > threshold_total_sum) and (keyword_increase > threshold_increase):
            server.zadd(redis_progression_name_set, float(keyword_increase), keyword)

if __name__ == '__main__':
    # If you wish to use an other port of channel, do not forget to run a subscriber accordingly (see launch_logs.sh)
    # Port of the redis instance used by pubsublogger
    publisher.port = 6380
    # Script is the default channel used for the modules.
    publisher.channel = 'Script'

    # Section name in bin/packages/modules.cfg
    config_section = 'WebStats'

    # Setup the I/O queues
    p = Process(config_section)

    # Sent to the logging a description of the module
    publisher.info("Makes statistics about valid URL")

    # REDIS #
    r_serv_trend = redis.StrictRedis(
        host=p.config.get("ARDB_Trending", "host"),
        port=p.config.get("ARDB_Trending", "port"),
        db=p.config.get("ARDB_Trending", "db"),
        decode_responses=True)

    # FILE CURVE SECTION #
    csv_path_proto = os.path.join(os.environ['AIL_HOME'],
                                  p.config.get("Directories", "protocolstrending_csv"))
    protocolsfile_path = os.path.join(os.environ['AIL_HOME'],
                                 p.config.get("Directories", "protocolsfile"))

    csv_path_tld = os.path.join(os.environ['AIL_HOME'],
                                p.config.get("Directories", "tldstrending_csv"))
    tldsfile_path = os.path.join(os.environ['AIL_HOME'],
                                 p.config.get("Directories", "tldsfile"))

    csv_path_domain = os.path.join(os.environ['AIL_HOME'],
                                   p.config.get("Directories", "domainstrending_csv"))

    faup = Faup()
    generate_new_graph = False
    # Endless loop getting messages from the input queue
    while True:
        # Get one message from the input queue
        message = p.get_from_set()

        if message is None:
            if generate_new_graph:
                generate_new_graph = False
                today = datetime.date.today()
                year = today.year
                month = today.month

                print('Building protocol graph')
                lib_words.create_curve_with_word_file(r_serv_trend, csv_path_proto,
                                                      protocolsfile_path, year,
                                                      month)

                print('Building tld graph')
                lib_words.create_curve_with_word_file(r_serv_trend, csv_path_tld,
                                                      tldsfile_path, year,
                                                      month)

                print('Building domain graph')
                lib_words.create_curve_from_redis_set(r_serv_trend, csv_path_domain,
                                                      "domain", year,
                                                      month)
                print('end building')

            publisher.debug("{} queue is empty, waiting".format(config_section))
            print('sleeping')
            time.sleep(5*60)
            continue

        else:
            generate_new_graph = True
            # Do something with the message from the queue
            url, date, path = message.split()
            faup.decode(url)
            url_parsed = faup.get()

            # Scheme analysis
            analyse(r_serv_trend, 'scheme', date, url_parsed)
            # Tld analysis
            analyse(r_serv_trend, 'tld', date, url_parsed)
            # Domain analysis
            analyse(r_serv_trend, 'domain', date, url_parsed)

            compute_progression(r_serv_trend, 'scheme', num_day_to_look, url_parsed)
            compute_progression(r_serv_trend, 'tld', num_day_to_look, url_parsed)
            compute_progression(r_serv_trend, 'domain', num_day_to_look, url_parsed)


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

def create_text_handler(key, name, expression, reply_message=False):
	'''create code block from given name and message expression as handler'''
	string = ('@bot.message_handler(regexp="' + expression + '")\n'
						'def ' + name + key + 'Request(message):\n'
						'    if isUserInDB(message) and isUserLoggedIn(message):\n')
	if reply_message:
		string += '        bot.send_message(message.from_user.id, "' + reply_message + '", reply_markup=basicMarkup.' + name_m + 'Menu(message))\n'
	else:
		string += (	'        basicMarkup.' + name + 'Menu(message)\n'
							'    else:\n'
							'        pass\n'
							'    log.logging(message)\n\n')

	return string

def create_text_menu2(name, button_list):
	'''create code block from given name and buttons list as a menu'''
	#button_list: list of tuples, where bl[0] - text, bl[1] - bin location, bl[2] - bin contact
	string = ('def ' + name + 'Menu(self, message):\n'
						'    keyboard = telebot.types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True)\n')
	for i, button_tuple in enumerate(button_list):
		loc = 'True' if button_tuple[2] == '1' else 'False'
		cont = 'True' if button_tuple[3] == '1' else 'False'
		line += '    button'+str(i)+' = telebot.types.KeyboardButton(text="'+button_tuple[1]+'"\n'
		line += '    keyboard.add(button' + str(i) + ')\n'
		string += line

	string += '    return keyboard\n\n'
	return string

def create_text_menu(name, button_list, reply_message):
	'''create code block from given name and buttons list as a menu'''
	if name == 'maps':
		return ''
	#button_list: list of tuples, where bl[0] - text, bl[1] - bin location, bl[2] - bin contact
	string = ('def ' + name + 'Menu(self, message):\n'
						'    keyboard = telebot.types.ReplyKeyboardMarkup(one_time_keyboard=True, resize_keyboard=True)\n')
	for i, button_tuple in enumerate(button_list):
		string += '    keyboard.row("'+button_tuple[1]+'")\n'

	string += '    keyboard.row("Главное меню' + r' \U0001F3E0")' + "\n"

	string += '    self.bot.send_message(message.from_user.id, "' + reply_message + '", reply_markup=keyboard)\n\n'
	return string

def create_answer_menu(name, reply):
	'''create code block from given name and buttons list as a menu'''
	string = ('def ' + name + 'Menu(self, message):\n'
						'    self.bot.send_message(message.from_user.id, "' + reply + '", reply_markup=keyboard)\n\n')
	return string

def parse_file(name):
	'''parsing our menu file'''
	dictionary = {}
	with open(name, 'r', encoding='utf-8') as file:
		for line in file:
			if line.strip():
				line = line.strip('\n')
				split = line.find('|')
				key = line[:split]
				value = line[split + 1:]
				dictionary[key] = value
	return dictionary

def parser_button_list(id, menu):
	'''making a button list for this id'''
	button_list = []
	length = len(id)
	for key in menu.keys():
		if len(key) == length + 1 and key[:length] == id:
			button_list.append(tuple(menu[key].strip().split('|')))
	if button_list:
		return button_list
	else:
		return False

def parse_helper_id(id, name, button_list, menu, reply):
	handlers_code = ''
	menu_code = create_text_menu(name, button_list, reply)
	for i, button in enumerate(button_list):
		handlers_code += create_text_handler(id + str(i), button[0], button[1])
	return menu_code, handlers_code

def parser():
	'''main function'''
	menu = parse_file('menu.txt')
	menu_code = ''
	handlers_code = ''

	button_list = parser_button_list('', menu)
	if button_list:
		m, h = parse_helper_id('', 'main', button_list, menu, '')
		menu_code += m
		handlers_code += h

	for id in menu.keys():
		button_list = parser_button_list(id, menu)
		if button_list:
			name = menu[id].split('|')[0]
			reply = menu[id].split('|')[4]
			m, h = parse_helper_id(id, name, button_list, menu, reply)
			menu_code += m
			handlers_code += h
		else:
			#return_button = ('return', 'Return to start menu', 0, 0)
			name = menu[id].split('|')[0]
			reply = menu[id].split('|')[4]
			#menu_code += create_answer_menu(name + str(id), reply)

	return menu_code, handlers_code

m, h = parser()
with open('test_menu.txt', 'w', encoding='utf-8') as file:
	file.write(m)
with open('test_handler.txt', 'w', encoding='utf-8') as file:
	file.write(h)


import nestpy
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.axes as axes
import os

#Detector identification
detector = nestpy.DetectorExample_XENON10()
# detector = nestpy.VDetector()
# Performing NEST calculations according to the given detector example
nc = nestpy.NESTcalc(detector) #can also be left empty

#GetInteractionObject grabs the number for the interaction you want so you don't have to always reference the dictionary. Just type e.g., 'ion'
#It just changes the name to a number for nestpy to do its work.
def GetInteractionObject(name):
    name = name.lower()

    if name == 'er':
        raise ValueError("For 'er', specify either 'gammaray' or 'beta'")

    nest_interaction_number = dict(
        nr=0,
        wimp=1,
        b8=2,
        dd=3,
        ambe=4,
        cf=5,
        ion=6,
        gammaray=7,
        beta=8,
        ch3t=9,
        c14=10,
        kr83m=11,
        nonetype=12,
    )

    interaction_object = nestpy.INTERACTION_TYPE(nest_interaction_number[name])
    return interaction_object

#Once you have interaction, you can get yields
#Begin with np.vectorize so that we can get yields over a range of interaction types/energies/drift fields.
@np.vectorize
def GetYieldsVectorized(interaction, yield_type, **kwargs):
    # This function does nc.GetYields for the various interactions and arguments we pass into it
    # TODO: Look at docstrings

    interaction_object = GetInteractionObject(interaction)

    if 'energy' in kwargs.keys():
        if interaction_object == GetInteractionObject('nr') and kwargs['energy'] > 3e2:
            return np.nan
    if interaction_object == GetInteractionObject('gammaray') and kwargs['energy'] > 3e3:
            return np.nan
    if interaction_object == GetInteractionObject('beta') and kwargs['energy'] > 3e3:
            return np.nan
    yield_object = nc.GetYields(interaction = interaction_object, **kwargs)
    #this returns the yields for the type of yield we are considering be it ElectronYield or PhotonYield (an attribute of yield)
    return getattr(yield_object, yield_type)

#Gives us photon yield values
def PhotonYield(**kwargs):
    return GetYieldsVectorized(yield_type = 'PhotonYield', **kwargs)
#Gives electron yields
def ElectronYield(**kwargs):
    return GetYieldsVectorized(yield_type = 'ElectronYield', **kwargs)

def Yield(**kwargs):
    return {'photon' : PhotonYield(**kwargs),
            'electron' : ElectronYield(**kwargs),
           # What is missing?  Aren't there other parts of YieldObject?
           }

#we are able to do nestpy with 13 different interaction types and that's all we're going to use here.
# interaction_types = np.array(['nr','wimp','b8','dd','ambe','cf','ion', 'gammaray', 'beta', 'ch3t', 'c14', 'kr83m', 'nonetype'])

fields = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000]
energies = np.logspace(-1, 4, 2000)
energies = np.broadcast_to(energies, (len(fields), len(energies)))

file_path = './Images/'
directory = os.path.dirname(file_path)
if not os.path.exists(directory):
    os.makedirs(directory)

# ## Nuclear Recoils
def nr_subplot(x, y_photons, y_electrons, driftFields):
    plt.figure(1, figsize=(9,6))
    subplot1 = plt.subplot(111)
    plt.figure(2, figsize=(9,6))
    subplot2 = plt.subplot(111)
    for i in range(0, len(driftFields)-2):
        subplot1.plot(x[i,:], y_photons[i,:], label="{0} V/cm".format(driftFields[i]))
        subplot2.plot(x[i,:], y_electrons[i,:], label="{0} V/cm".format(driftFields[i]))

    #Just formatting to look presentable
    subplot1.set_xscale('log')
    subplot2.set_xscale('log')
    subplot1.set_ylim(bottom=0)
    subplot2.set_ylim(bottom=0)

    subplot1.legend(loc='best', fontsize= 9, ncol=3)
    subplot1.set_xlabel('Recoil Energy [keV]')
    subplot1.set_ylabel('Light Yields [n$_\gamma$/keV]')
    subplot1.set_title('Light Yields for Nuclear Recoils')
    subplot1.margins(0)
    subplot2.legend(loc='best', fontsize= 9, ncol=3)
    subplot2.set_xlabel('Recoil Energy [keV]')
    subplot2.set_title('Charge Yields for Nuclear Recoils')
    subplot2.set_ylabel('Charge Yield [n$_e$/keV]')
    subplot2.margins(0)

    #Here's where we are actually saving our plots!
    plt.figure(1)
    plt.tight_layout()
    plt.savefig(os.path.join(file_path, 'nr_LY.png'))
    plt.figure(2)
    plt.tight_layout()
    plt.savefig(os.path.join(file_path, 'nr_QY.png'))

def beta_subplot(x, y_photons, y_electrons, driftFields):
    plt.figure(3, figsize=(9,6))
    subplot1 = plt.subplot(111)
    plt.figure(4, figsize=(9,6))
    subplot2 = plt.subplot(111)
    for i in range(0, len(driftFields)):
        subplot1.plot(x[i,:], y_photons[i,:], label="{0} V/cm".format(driftFields[i]))
        subplot2.plot(x[i,:], y_electrons[i,:], label="{0} V/cm".format(driftFields[i]))

    #Just formatting to look presentable
    subplot1.set_xscale('log')
    subplot2.set_xscale('log')
    subplot1.set_ylim(bottom=0)
    subplot2.set_ylim(bottom=0)

    subplot1.legend(loc='best', fontsize= 9, ncol=1)
    subplot1.set_xlabel('Energy [keV]')
    subplot1.set_ylabel('Light Yields [n$_\gamma$/keV]')
    subplot1.set_title('Light Yields for $\\beta$ Electron Recoils')
    subplot1.margins(0)
    subplot2.legend(loc='best', fontsize= 9, ncol=1)
    subplot2.set_xlabel('Energy [keV]')
    subplot2.set_title('Charge Yields for $\\beta$ Electron Recoils')
    subplot2.set_ylabel('Charge Yield [n$_e$/keV]')
    subplot2.margins(0)

    #Here's where we are actually saving our plots!
    plt.figure(3)
    plt.tight_layout()
    plt.savefig(os.path.join(file_path, 'beta_LY.png'))
    plt.figure(4)
    plt.tight_layout()
    plt.savefig(os.path.join(file_path, 'beta_QY.png'))

# ## $\gamma$ electron recoils
def gamma_subplot(x, y_photons, y_electrons, driftFields):
    plt.figure(5, figsize=(9,6))
    subplot1 = plt.subplot(111)
    plt.figure(6, figsize=(9,6))
    subplot2 = plt.subplot(111)
    for i in range(0, len(driftFields)):
        subplot1.plot(x[i,:], y_photons[i,:], label="{0} V/cm".format(driftFields[i]))
        subplot2.plot(x[i,:], y_electrons[i,:], label="{0} V/cm".format(driftFields[i]))

    #Just formatting to look presentable
    subplot1.set_xscale('log')
    subplot2.set_xscale('log')
    subplot1.set_ylim(bottom=0)
    subplot2.set_ylim(bottom=0)

    subplot1.legend(loc='best', fontsize= 9, ncol=1)
    subplot1.set_xlabel('Energy [keV]')
    subplot1.set_ylabel('Light Yields [n$_\gamma$/keV]')
    subplot1.set_title('Light Yields for $\\gamma$ Electron Recoils')
    subplot1.margins(0)
    subplot2.legend(loc='best', fontsize= 9, ncol=1)
    subplot2.set_xlabel('Energy [keV]')
    subplot2.set_title('Charge Yields for $\\gamma$ Electron Recoils')
    subplot2.set_ylabel('Charge Yield [n$_e$/keV]')
    subplot2.margins(0)

    #Here's where we are actually saving our plots!
    plt.figure(5)
    plt.tight_layout()
    plt.savefig(os.path.join(file_path, 'gamma_LY.png'))
    plt.figure(6)
    plt.tight_layout()
    plt.savefig(os.path.join(file_path, 'gamma_QY.png'))

# ## $\alpha$-particle recoils
def alpha_subplot(x, y_photons, y_electrons, driftFields):
    plt.figure(7, figsize=(9,6))
    subplot1 = plt.subplot(111)
    plt.figure(8, figsize=(9,6))
    subplot2 = plt.subplot(111)
    for i in range(0, len(driftFields)):
        subplot1.plot(x[i,:], y_photons[i,:], label="{0} V/cm".format(driftFields[i]))
        subplot2.plot(x[i,:], y_electrons[i,:], label="{0} V/cm".format(driftFields[i]))

    #Just formatting to look presentable
    subplot1.set_xscale('log')
    subplot2.set_xscale('log')
    subplot1.set_ylim(bottom=0)
    subplot2.set_ylim(bottom=0)
    subplot1.set_xlim(1, 1e4)
    subplot2.set_xlim(1, 1e4)

    subplot1.legend(loc='best', fontsize= 9, ncol=2)
    subplot1.set_xlabel('Energy [keV]')
    subplot1.set_ylabel('Light Yields [n$_\gamma$/keV]')
    subplot1.set_title('Light Yields for $\\alpha$-Particle Nuclear Recoils')
    subplot1.margins(0)
    subplot2.legend(loc='best', fontsize= 9, ncol=2)
    subplot2.set_xlabel('Energy [keV]')
    subplot2.set_title('Charge Yields for $\\alpha$-Particle Nuclear Recoils')
    subplot2.set_ylabel('Charge Yield [n$_e$/keV]')
    subplot2.margins(0)

    #Here's where we are actually saving our plots!
    plt.figure(7)
    plt.tight_layout()
    plt.savefig(os.path.join(file_path, 'alpha_LY.png'))
    plt.figure(8)
    plt.tight_layout()
    plt.savefig(os.path.join(file_path, 'alpha_QY.png'))

# ## $^{206}$Pb nuclear recoils
def Pb_subplot(x, y_photons, y_electrons, driftFields):
    plt.figure(9, figsize=(9,6))
    subplot1 = plt.subplot(111)
    plt.figure(10, figsize=(9,6))
    subplot2 = plt.subplot(111)
    for i in range(0, len(driftFields)):
        subplot1.plot(x[i,:], y_photons[i,:], label="{0} V/cm".format(driftFields[i]))
        subplot2.plot(x[i,:], y_electrons[i,:], label="{0} V/cm".format(driftFields[i]))

    subplot1.set_xscale('log')
    subplot2.set_xscale('log')
    subplot1.set_ylim(0, 10)
    subplot1.set_xlim(1, 1e2)
    subplot2.set_ylim(bottom=0)
    subplot2.set_xlim(1, 1e2)

    subplot1.legend(loc='best', fontsize= 10, ncol=3)
    subplot1.set_xlabel('Energy [keV]')
    subplot1.set_ylabel('Light Yields [n$_\gamma$/keV]')
    subplot1.set_title('Light Yields for Nuclear Recoils from $^{206}$Pb')
    subplot2.legend(loc='best', fontsize= 10, ncol=3)
    subplot2.set_xlabel('Energy [keV]')
    subplot2.set_title('Charge Yields for Nuclear Recoils from $^{206}$Pb')
    subplot2.set_ylabel('Charge Yield [n$_e$/keV]')

    #Here's where we are actually saving our plots!
    plt.figure(9)
    plt.tight_layout()
    plt.savefig(os.path.join(file_path, '208Pb_LY.png'))
    plt.figure(10)
    plt.tight_layout()
    plt.savefig(os.path.join(file_path, '208Pb_QY.png'))

#Doing the actual functions
# The following are the energy and field ranges for each interaction in the detector we care about showing.
def makeplots():
    num_interactions = 5 #number of types of interactions we're studying, so we can make enough plots.
    nr_electrons = ElectronYield(interaction='nr', energy=energies.T, drift_field = fields).T/energies
    nr_photons = PhotonYield(interaction='nr', energy=energies.T, drift_field = fields).T/energies
    nr_subplot(energies, nr_photons, nr_electrons, fields)

    beta_electrons = ElectronYield(interaction='beta', energy=energies.T, drift_field = fields).T/energies
    beta_photons = PhotonYield(interaction='beta', energy=energies.T, drift_field = fields).T/energies
    beta_subplot(energies, beta_photons, beta_electrons, fields)

    gamma_electrons = ElectronYield(interaction='gammaray', energy=energies.T, drift_field = fields).T/energies
    gamma_photons = PhotonYield(interaction='gammaray', energy=energies.T, drift_field = fields).T/energies
    gamma_subplot(energies, gamma_photons, gamma_electrons, fields)

    alpha_electrons = ElectronYield(interaction='ion', Z=2, A = 4, energy=energies.T, drift_field = fields).T/energies
    alpha_photons = PhotonYield(interaction='ion',Z=2, A=4, energy=energies.T, drift_field = fields).T/energies
    alpha_subplot(energies, alpha_photons, alpha_electrons, fields)

    Pb_electrons = ElectronYield(interaction='ion', Z=82, A = 206, energy=energies.T, drift_field = fields).T/energies
    Pb_photons = PhotonYield(interaction='ion',Z=82, A=206, energy=energies.T, drift_field = fields).T/energies
    Pb_subplot(energies, Pb_photons, Pb_electrons, fields)

# makeplots()


from django.contrib import admin
from django.utils.translation import ugettext_lazy as _

from planfood.common.models import Group
from .models import Dish, Norm, Output

class NormInline(admin.TabularInline):
    model = Norm

class OutputInline(admin.TabularInline):
    model = Output

@admin.register(Dish)
class DishAdmin(admin.ModelAdmin):
    fields = ('name', 'products')
    list_display = ('name', 'products_count', 'outputs_count', 'norms_count')
    filter_horizontal = ('products',)
    inlines = (OutputInline, NormInline)
    actions = ['create_norms_dishes', 'create_outputs_dishes']

    def products_count(self, obj):
        return obj.products.all().count()

    def norms_count(self, obj):
        return '{} ({})'.format(
            obj.norms.all().count(), obj.norms.filter(value=0).count()
        )

    def outputs_count(self, obj):
        return '{} ({})'.format(
            obj.outputs.all().count(), obj.outputs.filter(value='0').count()
        )

    def create_norms_dishes(self, request, queryset):
        groups = Group.objects.all()
        for dish in queryset:
            for group in groups.iterator():
                for product in dish.products.iterator():
                    for age_category in group.age_categories.iterator():
                        has_norm = dish.norms.filter(
                            product=product, group=group, age_category=age_category
                        ).exists()
                        if not has_norm:
                            norm = Norm.objects.create(
                                dish=dish,
                                product=product,
                                group=group,
                                age_category=age_category,
                                value=0.0,
                            )

    def create_outputs_dishes(self, request, queryset):
        groups = Group.objects.all()
        for dish in queryset:
            for group in groups.iterator():
                for age_category in group.age_categories.iterator():
                    has_output = dish.outputs.filter(
                        group=group, age_category=age_category
                    ).exists()
                    if not has_output:
                        output = Output.objects.create(
                            dish=dish, group=group, age_category=age_category, value='0'
                        )

    norms_count.short_description = _('Number of Products Norms')  # type: ignore
    outputs_count.short_description = _('Number of Products Outputs')  # type: ignore
    products_count.short_description = _('Number of Products')  # type: ignore
    create_norms_dishes.short_description = _(  # type: ignore
        'Creates norms for selected dishes'
    )
    create_outputs_dishes.short_description = _(  # type: ignore
        'Creates outputs for selected dishes'
    )


from selenium.webdriver.common.by import By
import allure
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
import selenium
from model.project import Project
from datetime import datetime
import re

class ManageProjectPageHelper:
    def __init__(self, app):
        self.app = app
    def create_new_project(self, project):
        self.init_create_new_project()
        self.fill_project_fields(project)
        self.submit_create_project()

    def init_create_new_project(self):
        wd = self.app.wd
        with allure.step('Нажать Create New Project'):
            wd.find_element(By.XPATH, "//input[@value='Create New Project']").click()
            WebDriverWait(wd, 5).until(expected_conditions.presence_of_element_located((By.XPATH, "//td[contains(text(), 'Add Project')]")))

    def fill_project_fields(self, project):
        wd = self.app.wd
        with allure.step('Ввести уникальный Project Name'):
            wd.find_element(By.NAME, "name").send_keys(project.project_name)

    def submit_create_project(self):
        wd = self.app.wd
        with allure.step('Нажать Create New Project'):
            wd.find_element(By.XPATH, "//input[@type='submit' and @value='Add Project']").click()
            WebDriverWait(wd, 5).until(expected_conditions.invisibility_of_element_located((By.XPATH, "//td[contains(text(), 'Add Project')]")))

    def open_project(self, project_name):
        wd = self.app.wd
        with allure.step('Нажать на ссылку с названием проекта'):
            WebDriverWait(wd, 10).until(expected_conditions.element_to_be_clickable(
                (By.LINK_TEXT, f"{project_name}")))
            wd.find_element(By.LINK_TEXT, f"{project_name}").click()
            WebDriverWait(wd, 10).until(expected_conditions.presence_of_element_located(
                (By.NAME, "project_id")))

    def submit_delete_project(self):
        wd = self.app.wd
        with allure.step('Подтвердить удаление'):
            wd.find_element(By.XPATH, "//form[@action='manage_proj_delete.php']//input[@value='Delete Project']").click()
            WebDriverWait(wd, 10).until(expected_conditions.presence_of_element_located(
                (By.XPATH, "//table[@class='width100']//td[@class='form-title']")))
    def init_delete_project(self):
        wd = self.app.wd
        with allure.step('Нажать кнопку удаления проекта'):
            wd.find_element(By.XPATH, "//input[@value='Delete Project']").click()
            WebDriverWait(wd, 10).until(expected_conditions.element_to_be_clickable(
                (By.XPATH, "//form[@action='manage_proj_delete.php']//input[@value='Delete Project']")))

    def delete_project(self, project):
        self.open_project(project.project_name)
        self.init_delete_project()
        self.submit_delete_project()


import os
import torch
import torchvision
import torchvision.transforms as transforms
import random
import pathlib
import utils
import numpy as np
from PIL import Image
from torch.utils import data

tensor = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
NUM_CLASS = 19

# class CityscapesLoader(data.Dataset):
#     """
#     Load Cityscapes dataset for training and testing
#
#     Dataset augmentations performed in a synchronised manner here.
#     """
#     def __init__(self,
#                  root,
#                  input_res,
#                  split='train',
#                  mode='train',
#                  encoder_only=False,
#                  transform=None,
#                  target_transform=None):
#         """
#         :param root: path to cityscapes folder
#         :param input_res: desired output res of the images and targets
#         :param split: dataset split
#         :param mode: mode of the transformation setup
#         :param transform: final transformation applications
#         """
#         super(CityscapesLoader, self).__init__()
#
#         self.root = pathlib.Path(root)
#         self.split = split
#         self.mode = mode
#         self.transform = transform
#         self.target_transform = target_transform
#         self.input_res = input_res
#         self.encoder_only = encoder_only
#
#         self.images_base = self.root / "leftImg8bit" / self.split
#         self.annotations_base = self.root / "gtFine" / self.split
#         self.files = {}
#         self.files[self.split] = utils.recursive_glob(rootdir=self.images_base, suffix="*.png")
#
#         self.void_classes = [0, 1, 2, 3, 4, 5, 6, 9, 10, 14, 15, 16, 18, 29, 30, -1]
#         self.valid_classes = [
#             7,
#             8,
#             11,
#             12,
#             13,
#             17,
#             19,
#             20,
#             21,
#             22,
#             23,
#             24,
#             25,
#             26,
#             27,
#             28,
#             31,
#             32,
#             33,
#         ]
#         self.class_map = dict(zip(self.valid_classes, range(19)))
#         self.ignore_index = 250
#
#     def __getitem__(self, index):
#         img_path = self.files[self.split][index]
#         img = Image.open(img_path).convert('RGB')
#
#         lbl_basename = pathlib.Path(self.annotations_base) / os.path.basename(os.path.dirname(img_path))
#         lbl_path = lbl_basename / (os.path.basename(img_path)[:-15] + "gtFine_labelIds.png")
#         lbl_gt = lbl_basename / (os.path.basename(img_path)[:-15] + "gtFine_color.png")
#         mask = Image.open(lbl_path)
#         gt = Image.open(lbl_gt).convert('RGB')
#
#         if self.split == 'test' or (self.split == 'val' and self.mode == 'semseg'):
#             gt = transforms.Resize(size=self.input_res, interpolation=Image.NEAREST)(gt)
#             gt = self._img_transform(gt)
#             gt = transforms.ToTensor()(gt)
#
#             img, mask = self.resize_transform(img, mask)
#             img, mask = self._img_transform(img), self._mask_transform(mask)
#             img = self.transform(img) if self.transform is not None else img
#             # img = self.target_transform(img) if self.target_transform is not None else img
#
#         elif self.split == 'train' or self.split == 'val':
#             gt = transforms.ToTensor()(gt)
#             img, mask = self.sync_transform(img, mask)
#             img = self.transform(img) if self.transform is not None else img
#
#         return img, mask, gt
#
#     def sync_transform(self,
#                        img,
#                        mask):
#         """
#         Augmentations to perform simultaneously to the images and its corresponding label
#         """
#         # Resize
#         img, mask = self.resize_transform(img, mask)
#
#         # random crop
#         # if not self.encoder_only:
#         #     rcrop = transforms.RandomCrop(self.input_res)
#         #
#         #     img = rcrop(img)
#         #     mask = rcrop(mask)
#
#         # Random horizontal flip
#         hflip = transforms.RandomHorizontalFlip()
#         img = hflip(img)
#         mask = hflip(mask)
#
#         # final transform
#         img, mask = self._img_transform(img), self._mask_transform(mask)
#
#         return img, mask
#
#     def resize_transform(self, img, mask):
#         """
#         Resize image to desired input res for the model
#         """
#         resize_img = transforms.Resize(self.input_res)
#         if self.encoder_only:
#             input_res = self.train_encoder()
#             resize_mask = transforms.Resize(input_res, interpolation=transforms.InterpolationMode.NEAREST)
#         else:
#             resize_mask = transforms.Resize(self.input_res, interpolation=Image.NEAREST)
#
#         img = resize_img(img)
#         mask = resize_mask(mask)
#
#         return img, mask
#
#     def train_encoder(self):
#         input_width = int(self.input_res[0] / 8)
#         input_height = int(self.input_res[1] / 8)
#
#         return [input_width, input_height]
#
#     def _img_transform(self, img):
#         return np.array(img)
#
#     def _mask_transform(self, mask):
#         target = self.encode_segmap(np.array(mask).astype('int32'))
#
#         return torch.LongTensor(np.array(target).astype('int32'))
#
#     def __len__(self):
#         return len(self.files[self.split])
#
    # @property
    # def num_class(self):
    #     """Number of categories."""
    #     return self.NUM_CLASS
#
#     # @property
#     # def pred_offset(self):
#     #     return 0
#
#     def encode_segmap(self, mask):
#         # Put all void classes to zero
#         for _voidc in self.void_classes:
#             mask[mask == _voidc] = self.ignore_index
#         for _validc in self.valid_classes:
#             mask[mask == _validc] = self.class_map[_validc]
#         return mask
#
    # def load_data(self,
    #               batch_size=1,
    #               num_workers=0,
    #               shuffle=False,
    #               sampler=None):
    #     """
    #     Load the dataset to be ready for use
    #     """
    #     return torch.utils.data.DataLoader(self,
    #                                        batch_size=batch_size,
    #                                        num_workers=num_workers,
    #                                        shuffle=shuffle,
    #                                        sampler=sampler)

class CityscapesLoader(data.Dataset):
    """
    Load Cityscapes dataset for training and testing

    Dataset augmentations performed in a synchronised manner here.
    """
    def __init__(self,
                 root,
                 split="train",
                 is_transform=True,
                 input_res=(1024, 2048),
                 augments=None,
                 test_mode=False,
                 **kwargs):
        """
        :param root: path to cityscapes folder
        :param input_res: desired output res of the images and targets
        :param split: dataset split
        :param is_transform: tag whether or not to apply transformations (normalisation and resizing)
        :param augments: dictionary containing the desired augmentations
        """
        self.root = pathlib.Path(root)
        self.split = split
        self.is_transform = is_transform
        self.augments = augments
        self.n_classes = 19
        self.input_res = tuple(input_res)
        self.test_mode = test_mode

        self.images_base = self.root / "leftImg8bit" / self.split
        self.annotations_base = self.root / "gtFine" / self.split
        self.files = {}
        self.files[self.split] = utils.recursive_glob(rootdir=self.images_base, suffix="*.png")

        self.void_classes = [0, 1, 2, 3, 4, 5, 6, 9, 10, 14, 15, 16, 18, 29, 30, -1]
        self.valid_classes = [
            7,
            8,
            11,
            12,
            13,
            17,
            19,
            20,
            21,
            22,
            23,
            24,
            25,
            26,
            27,
            28,
            31,
            32,
            33,
        ]
        self.class_names = [
            "unlabelled",
            "road",
            "sidewalk",
            "building",
            "wall",
            "fence",
            "pole",
            "traffic_light",
            "traffic_sign",
            "vegetation",
            "terrain",
            "sky",
            "person",
            "rider",
            "car",
            "truck",
            "bus",
            "train",
            "motorcycle",
            "bicycle",
        ]

        self.ignore_index = 250
        self.class_map = dict(zip(self.valid_classes, range(19)))

    def __len__(self):
        """
        __len__
        """
        return len(self.files[self.split])

    def __getitem__(self,
                    index):
        """
        __getitem__
        """
        # Load image
        img_path = self.files[self.split][index]
        img = Image.open(img_path).convert('RGB')
        img = np.array(img, dtype=np.uint8)

        # Load label
        lbl_basename = pathlib.Path(self.annotations_base) / os.path.basename(os.path.dirname(img_path))
        lbl_path = lbl_basename / (os.path.basename(img_path)[:-15] + "gtFine_labelIds.png")
        mask = Image.open(lbl_path)
        mask = self.encode_segmap(np.array(mask, dtype=np.uint8))

        # Load label (colour map)
        lbl_gt = lbl_basename / (os.path.basename(img_path)[:-15] + "gtFine_color.png")
        gt = Image.open(lbl_gt).convert('RGB')
        if not self.test_mode:
           gt = transforms.Resize(size=self.input_res, interpolation=transforms.InterpolationMode.NEAREST)(gt)
        gt = transforms.ToTensor()(np.array(gt))

        # Conduct augmentations on the image and label (hflip and rcrop), usually None for the validation and test set
        if self.augments is not None:
            img, mask = self.augments(img, mask)

        # Conduct transformations on the image and label (resizing, normalisation and toTensor)
        if self.is_transform:
            img, mask = self.transform(img, mask)

        return img, mask, gt

    def transform(self,
                  img,
                  lbl):
        """
        Conduct the transformation on the image and labels
        """
        # img = Image.fromarray(img).resize((self.input_res[1], self.input_res[0]))  # uint8 with RGB mode

        mean = [0.5, 0.5, 0.5]
        std = [0.5, 0.5, 0.5]
        norm = transforms.Normalize(mean=mean,
                                    std=std)
        to_tensor = transforms.ToTensor()

        classes = np.unique(lbl)
        lbl = lbl.astype(float)

        if not self.test_mode:
            lbl = np.array(Image.fromarray(lbl).resize((self.input_res[1], self.input_res[0]), resample=Image.NEAREST))
            img = Image.fromarray(img).resize((self.input_res[1], self.input_res[0]))  # uint8 with RGB mode
        # else:
        #     lbl = np.array(Image.fromarray(lbl))

        lbl = lbl.astype(int)

        # if not np.all(classes == np.unique(lbl)):
        #     print("number of unique classes before resize", classes)
        #     print("number of unique classes after resize", np.unique(lbl))
        #     print("WARN: resizing labels yielded fewer classes")
        #
        # if not np.all(np.unique(lbl[lbl != self.ignore_index]) < self.n_classes):
        #     print("after det", classes, np.unique(lbl))
        #     raise ValueError("Segmentation map contained invalid class values")

        img = to_tensor(img)
        img = norm(img)
        lbl = torch.from_numpy(lbl).long()

        return img, lbl

    def encode_segmap(self,
                      mask):
        """
        Put all void classes to zero (or 250)
        """
        for _voidc in self.void_classes:
            mask[mask == _voidc] = self.ignore_index

        for _validc in self.valid_classes:
            mask[mask == _validc] = self.class_map[_validc]

        return mask

    @property
    def num_class(self):
        """
        Number of categories
        """
        return self.NUM_CLASS

    def load_data(self,
                  batch_size=1,
                  num_workers=0,
                  shuffle=False,
                  sampler=None):
        """
        Load the dataset to be ready for use
        """
        return torch.utils.data.DataLoader(self,
                                           batch_size=batch_size,
                                           num_workers=num_workers,
                                           shuffle=shuffle,
                                           sampler=sampler)


def evenFibonacciNumbers():
    """
    This function return the even numbers into the Fibonacci sequence
    given the number of terms of the sequence
    :return:
    """
    a, b, p, cont, l = 0, 0, 1, 0, []
    num = int(input('How many terms do you want to have the sequence? '))
    for i in range(num):
        a, b, = b, p
        p = a + b
        if a % 2 == 0 and a != 0:
            cont += 1
            l.append(a)
    print(f"The number of even numbers between the first and last term are {cont}.")
    return print(*l)

evenFibonacciNumbers()


import pandas as pd
from PIL import Image
from io import BytesIO
import numpy as np
from abc import ABC, abstractmethod
from datetime import (datetime,
                    timedelta)
from typing import (List,
                    Tuple,
                    Union)

class DataOperations(ABC):
    _heart_rate: Union[List, None] = None
    _data: Union[List, None] = None

    @property
    @abstractmethod
    def data(self): ...

    @data.setter
    @abstractmethod
    def data(self): ...

    def is_data_none_wrapper(func):
        def __is_data_none(self, *args, **kwargs) -> Union[None, NameError]:
            if self.data is None:
                raise NameError(f'data not found. You must set the data before calling the {func.__name__} function')
            return func(self, *args, **kwargs)
        return __is_data_none

    def is_heart_rate_none_wrapper(func):
        def __is_heart_rate_none(self, *args, **kwargs) -> Union[None, NameError]:
            if self.heart_rate is None:
                raise NameError(f'heart_rate data not found. You must call the get_heart_rate function before calling the {func.__name__} function')
            return func(self, *args, **kwargs)
        return __is_heart_rate_none

    @property
    @is_data_none_wrapper
    def heart_rate(self) -> List:
        # sourcery skip: inline-immediately-returned-variable, list-comprehension
        self._heart_rate = []
        for d in self.data:
            if d['type'] == 7:
                self._heart_rate.append(
                    {
                        'rate': float(d['samplePoints'][0]['value']),
                        'time': (datetime.fromtimestamp(
                                    int(str(d['samplePoints'][0]['endTime'])[:10])
                            ) + timedelta(
                                    hours = int(self.data[0]['timeZone'][1:].replace('0', ''))
                                )
                        )
                    }
                )
        return self._heart_rate

    @is_heart_rate_none_wrapper
    def get_heart_rate_for_all_days_as_axis(self) -> Tuple:
        heart_rate = pd.DataFrame(self._heart_rate)
        return (
            list (
                map(
                    lambda t: t.strftime("%d-%m-%Y %X"),
                    heart_rate['time']
                )
            ),
            heart_rate['rate']
        )

    @is_heart_rate_none_wrapper
    def get_average_heart_rate_for_days_as_axis(self) -> Tuple:
        heart_rate_grouped = pd.DataFrame(
            list(
                map(
                    lambda t: {'rate': t['rate'], 'date': t['time'].strftime("%d-%m-%Y")}, self._heart_rate
                )
            )
        ).groupby('date', sort=False).mean()['rate']

        return (heart_rate_grouped.keys(), heart_rate_grouped.values)

    @is_heart_rate_none_wrapper
    def get_heart_rate_for_one_day(self, day) -> Tuple:
        heart_rate = pd.DataFrame(
            list(
                filter(
                    lambda t: t['time'].strftime("%d-%m-%Y") == day, self._heart_rate
                )
            )
        )

        return (
            list (
                map(
                    lambda t: t.strftime("%d-%m-%Y %X"),
                    heart_rate['time']
                )
            ),
            heart_rate['rate']
        )

    def get_averages_of_heart_rates(self, y: pd.Series, average_number: int) -> Tuple:
        heart_rate2 = []
        rates = list(y)

        for i in range(0, len(rates), average_number):
            t = rates[i:i + average_number]
            heart_rate2.append(sum(t) / len(t))

        return (range(len(heart_rate2)), heart_rate2)

    @classmethod
    def __array_to_bytes_image(cls, img_array: np.array) -> bytes:
        buf = BytesIO()
        Image.fromarray(img_array, 'RGB').save(buf, format="PNG")
        return buf.getvalue()

    @staticmethod
    def get_heart_rate_as_img(rates: List) -> bytes:
        rates_len = len(rates)
        old_max = max(rates)
        old_min = min(rates)
        new_max = 255
        new_min = 0

        old_range = (old_max - old_min)
        new_range = (new_max - new_min)

        for max_n in range(rates_len):
            if max_n * max_n > rates_len: break

        img_array = np.full((max_n, max_n, 3), [0, 255, 0], dtype=np.uint8)

        x, y = 0, 0
        for n in rates:
            color = (255 - (((n - old_min) * new_range) / old_range) + new_min)
            img_array[x][y] = [color, color, color]
            if y < max_n-1: y += 1
            else:
                x += 1
                y = 0

        return DataOperations.__array_to_bytes_image(img_array)


# -*- coding: utf-8 -*-
#
# Copyright (c) 2020 Ian Ottoway <ian@ottoway.dev>
# Copyright (c) 2014 Agostino Ruscito <ruscito@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#

import logging
from typing import Union
from reprlib import repr as _r

from . import Packet, DataFormatType
from . import (ResponsePacket, SendUnitDataResponsePacket, ReadTagServiceResponsePacket, RegisterSessionResponsePacket,
               UnRegisterSessionResponsePacket, ListIdentityResponsePacket, SendRRDataResponsePacket,
               MultiServiceResponsePacket, ReadTagFragmentedServiceResponsePacket, WriteTagServiceResponsePacket,
               WriteTagFragmentedServiceResponsePacket, GenericUnconnectedResponsePacket,
               GenericConnectedResponsePacket)
from ..exceptions import CommError, RequestError
from ..bytes_ import Pack, print_bytes_msg
from ..const import (EncapsulationCommand, INSUFFICIENT_PACKETS, DataItem, AddressItem, EXTENDED_SYMBOL, ELEMENT_TYPE,
                     Services, CLASS_TYPE, INSTANCE_TYPE, DataType, DataTypeSize, ConnectionManagerService,
                     ClassCode, Services, STRUCTURE_READ_REPLY, PRIORITY, TIMEOUT_TICKS, ATTRIBUTE_TYPE)

class RequestPacket(Packet):
    __log = logging.getLogger(f'{__module__}.{__qualname__}')
    _message_type = None
    _address_type = None
    _timeout = b'\x0a\x00'  # 10
    _encap_command = None
    _response_class = ResponsePacket
    _response_args = ()
    _response_kwargs = {}
    type_ = None
    VERBOSE_DEBUG = False

    def __init__(self, plc):
        super().__init__()
        self._msg = []  # message data
        self._plc = plc
        self.error = None

    def add(self, *value: bytes):
        self._msg.extend(value)
        return self

    @property
    def message(self) -> bytes:
        return b''.join(self._msg)

    def _build_request(self):
        msg = self._build_common_packet_format(addr_data=self._plc._target_cid)
        header = self._build_header(self._encap_command, len(msg))
        return header + msg

    def _build_header(self, command, length) -> bytes:
        """ Build the encapsulate message header

        The header is 24 bytes fixed length, and includes the command and the length of the optional data portion.

         :return: the header
        """
        try:
            return b''.join([
                command,
                Pack.uint(length),  # Length UINT
                Pack.udint(self._plc._session),  # Session Handle UDINT
                b'\x00\x00\x00\x00',  # Status UDINT
                self._plc._cfg['context'],  # Sender Context 8 bytes
                Pack.udint(self._plc._cfg['option']),  # Option UDINT
            ])

        except Exception as err:
            raise CommError('Failed to build request header') from err

    def _build_common_packet_format(self, addr_data=None) -> bytes:
        addr_data = b'\x00\x00' if addr_data is None else Pack.uint(len(addr_data)) + addr_data
        msg = self.message
        return b''.join([
            b'\x00\x00\x00\x00',  # Interface Handle: shall be 0 for CIP
            self._timeout,
            b'\x02\x00',  # Item count: should be at list 2 (Address and Data)
            self._address_type,
            addr_data,
            self._message_type,
            Pack.uint(len(msg)),
            msg
        ])

    def _send(self, message):

        try:
            if self.VERBOSE_DEBUG:
                self.__log.debug(print_bytes_msg(message, '>>> SEND >>>'))
            self._plc._sock.send(message)
        except Exception as err:
            raise CommError('failed to send message') from err

    def _receive(self):
        """
        socket receive
        :return: reply data
        """
        try:
            reply = self._plc._sock.receive()
        except Exception as err:
            raise CommError('failed to receive reply') from err
        else:
            if self.VERBOSE_DEBUG:
                self.__log.debug(print_bytes_msg(reply, '<<< RECEIVE <<<'))
            return reply

    def send(self) -> ResponsePacket:
        if not self.error:
            self._send(self._build_request())
            self.__log.debug(f'Sent: {self!r}')
            reply = self._receive()
            response = self._response_class(reply, *self._response_args, **self._response_kwargs)
        else:
            response = self._response_class(*self._response_args, **self._response_kwargs)
            response._error = self.error
        self.__log.debug(f'Received: {response!r}')
        return response

    def __repr__(self):
        return f'{self.__class__.__name__}(message={_r(self._msg)})'

    __str__ = __repr__

class SendUnitDataRequestPacket(RequestPacket):
    __log = logging.getLogger(f'{__module__}.{__qualname__}')
    _message_type = DataItem.connected
    _address_type = AddressItem.connection
    _response_class = SendUnitDataResponsePacket
    _encap_command = EncapsulationCommand.send_unit_data

    def __init__(self, plc):
        super().__init__(plc)
        self._msg = [Pack.uint(plc._sequence), ]

class ReadTagServiceRequestPacket(SendUnitDataRequestPacket):
    __log = logging.getLogger(f'{__module__}.{__qualname__}')
    type_ = 'read'
    _response_class = ReadTagServiceResponsePacket

    def __init__(self, plc):
        super().__init__(plc)
        self.tag = None
        self.elements = None
        self.tag_info = None
        self.request_id = None

    def add(self, tag, request_path, elements, tag_info, request_id):
        self.tag = tag
        self.elements = elements
        self.tag_info = tag_info
        self.request_id = request_id
        if request_path is None:
            self.error = 'Invalid Tag Request Path'

        super().add(
            Services.read_tag,
            request_path,
            Pack.uint(self.elements),
        )

    def send(self):
        if not self.error:
            self._send(self._build_request())
            self.__log.debug(f'Sent: {self!r}')
            reply = self._receive()
            response = ReadTagServiceResponsePacket(reply, elements=self.elements, tag_info=self.tag_info, tag=self.tag)
        else:
            response = ReadTagServiceResponsePacket(tag=self.tag)
            response._error = self.error
        self.__log.debug(f'Received: {response!r}')
        return response

    def __repr__(self):
        return f'{self.__class__.__name__}(tag={self.tag!r}, elements={self.elements!r})'

class ReadTagFragmentedServiceRequestPacket(SendUnitDataRequestPacket):
    __log = logging.getLogger(f'{__module__}.{__qualname__}')
    type_ = 'read'
    _response_class = ReadTagFragmentedServiceResponsePacket

    def __init__(self, plc):
        super().__init__(plc)
        self.tag = None
        self.elements = None
        self.tag_info = None
        self.request_path = None
        self.request_id = None

    def add(self, tag, request_path, elements, tag_info, request_id):
        self.tag = tag
        self.elements = elements
        self.tag_info = tag_info
        self.request_path = request_path
        self.request_id = request_id
        if self.request_path is None:
            self.error = 'Invalid Tag Request Path'

    def send(self):
        if not self.error:
            offset = 0
            responses = []
            while offset is not None:
                self._msg.extend([Services.read_tag_fragmented,
                                  self.request_path,
                                  Pack.uint(self.elements),
                                  Pack.dint(offset)])
                self._send(self._build_request())
                self.__log.debug(f'Sent: {self!r} (offset={offset})')
                reply = self._receive()
                response = ReadTagFragmentedServiceResponsePacket(reply, self.tag_info, self.elements)
                self.__log.debug(f'Received: {response!r}')
                responses.append(response)
                if response.service_status == INSUFFICIENT_PACKETS:
                    offset += len(response.bytes_)
                    self._msg = [Pack.uint(self._plc._sequence)]
                else:
                    offset = None
            if all(responses):
                final_response = responses[-1]
                final_response.bytes_ = b''.join(resp.bytes_ for resp in responses)
                final_response.parse_bytes()
                self.__log.debug(f'Reassembled Response: {final_response!r}')
                return final_response

        failed_response = ReadTagServiceResponsePacket()
        failed_response._error = self.error or 'One or more fragment responses failed'
        self.__log.debug(f'Reassembled Response: {failed_response!r}')
        return failed_response

    def __repr__(self):
        return f'{self.__class__.__name__}(tag={self.tag!r}, elements={self.elements!r})'

class WriteTagServiceRequestPacket(SendUnitDataRequestPacket):
    __log = logging.getLogger(f'{__module__}.{__qualname__}')
    type_ = 'write'
    _response_class = WriteTagServiceResponsePacket

    def __init__(self, plc):
        super().__init__(plc)
        self.tag = None
        self.elements = None
        self.tag_info = None
        self.value = None
        self.data_type = None
        self.request_id = None

    def add(self, tag, request_path, value, elements, tag_info, request_id, bits_write=None):
        self.tag = tag
        self.elements = elements
        self.tag_info = tag_info
        self.value = value
        self.request_id = request_id
        request_path = request_path
        if request_path is None:
            self.error = 'Invalid Tag Request Path'

        else:
            if bits_write:
                request_path = _make_write_data_bit(tag_info, value, request_path)
                data_type = 'BOOL'
            else:
                request_path, data_type = _make_write_data_tag(tag_info, value, elements, request_path)

            super().add(
                request_path,
            )
            self.data_type = data_type

    def __repr__(self):
        return f'{self.__class__.__name__}(tag={self.tag!r}, value={_r(self.value)}, elements={self.elements!r})'

class WriteTagFragmentedServiceRequestPacket(SendUnitDataRequestPacket):
    __log = logging.getLogger(f'{__module__}.{__qualname__}')
    type_ = 'write'
    _response_class = WriteTagFragmentedServiceResponsePacket

    def __init__(self, plc):
        super().__init__(plc)
        self.tag = None
        self.value = None
        self.elements = None
        self.tag_info = None
        self.request_path = None
        self.data_type = None
        self.segment_size = None
        self.request_id = None
        self._packed_type = None

    def add(self, tag, request_path, value, elements, tag_info, request_id):
        try:
            self.data_type = tag_info['data_type_name']
            self.tag = tag
            self.value = value
            self.elements = elements
            self.tag_info = tag_info
            self.request_path = request_path
            self.request_id = request_id

            if tag_info['tag_type'] == 'struct':
                self._packed_type = STRUCTURE_READ_REPLY + Pack.uint(tag_info['data_type']['template']['structure_handle'])
            else:
                self._packed_type = Pack.uint(DataType[self.data_type])

            if self.request_path is None:
                self.error = 'Invalid Tag Request Path'
        except Exception as err:
            self.__log.exception('Failed adding request')
            self.error = err

    def send(self):
        if not self.error:
            responses = []
            segment_size = self._plc.connection_size - (len(self.request_path) + len(self._packed_type)
                                                        + 9)  # 9 = len of other stuff in the path

            pack_func = Pack[self.data_type] if self.tag_info['tag_type'] == 'atomic' else lambda x: x
            segments = (self.value[i:i+segment_size]
                        for i in range(0, len(self.value), segment_size))

            offset = 0
            elements_packed = Pack.uint(self.elements)

            for i, segment in enumerate(segments, start=1):
                segment_bytes = b''.join(pack_func(s) for s in segment) if not isinstance(segment, bytes) else segment
                self._msg.extend((
                    Services.write_tag_fragmented,
                    self.request_path,
                    self._packed_type,
                    elements_packed,
                    Pack.dint(offset),
                    segment_bytes
                ))

                self._send(self._build_request())
                self.__log.debug(f'Sent: {self!r} (part={i} offset={offset})')
                reply = self._receive()
                response = WriteTagFragmentedServiceResponsePacket(reply)
                self.__log.debug(f'Received: {response!r}')
                responses.append(response)
                offset += len(segment_bytes)
                self._msg = [Pack.uint(self._plc._sequence), ]

            if all(responses):
                final_response = responses[-1]
                self.__log.debug(f'Reassembled Response: {final_response!r}')
                return final_response

        failed_response = WriteTagFragmentedServiceResponsePacket()
        failed_response._error = self.error or 'One or more fragment responses failed'
        self.__log.debug(f'Reassembled Response: {failed_response!r}')
        return failed_response

class MultiServiceRequestPacket(SendUnitDataRequestPacket):
    __log = logging.getLogger(f'{__module__}.{__qualname__}')
    type_ = 'multi'
    _response_class = MultiServiceResponsePacket

    def __init__(self, plc):
        super().__init__(plc)
        self.tags = []
        self._msg.extend((
            Services.multiple_service_request,  # the Request Service
            Pack.usint(2),  # the Request Path Size length in word
            CLASS_TYPE["8-bit"],
            ClassCode.message_router,
            INSTANCE_TYPE["8-bit"],
            b'\x01',  # Instance 1
        ))
        self._message = None
        self._msg_errors = None

    @property
    def message(self) -> bytes:
        return self._message

    def build_message(self, tags):
        rp_list, errors = [], []
        for tag in tags:
            if tag['rp'] is None:
                errors.append(f'Unable to create request path {tag["tag"]}')
            else:
                rp_list.append(tag['rp'])

        offset = len(rp_list) * 2 + 2
        offsets = []
        for rp in rp_list:
            offsets.append(Pack.uint(offset))
            offset += len(rp)

        msg = self._msg + [Pack.uint(len(rp_list))] + offsets + rp_list
        return b''.join(msg)

    def add_read(self, tag, request_path, elements, tag_info, request_id):
        if request_path is not None:
            rp = Services.read_tag + request_path + Pack.uint(elements)
            _tag = {
                'tag': tag,
                'elements': elements,
                'tag_info': tag_info,
                'rp': rp,
                'service': 'read',
                'request_id': request_id
            }
            message = self.build_message(self.tags + [_tag])
            if len(message) < self._plc.connection_size:
                self._message = message
                self.tags.append(_tag)
                return True
            else:
                return False
        else:
            self.__log.error(f'Failed to create request path for {tag}')
            raise RequestError('Failed to create request path')

    def add_write(self, tag, request_path, value, elements, tag_info, request_id, bits_write=None):
        if request_path is not None:
            if bits_write:
                data_type = tag_info['data_type']
                request_path = _make_write_data_bit(tag_info, value, request_path)
            else:
                request_path, data_type = _make_write_data_tag(tag_info, value, elements, request_path)

            _tag = {'tag': tag, 'elements': elements, 'tag_info': tag_info, 'rp': request_path, 'service': 'write',
                    'value': value, 'data_type': data_type, 'request_id': request_id}

            message = self.build_message(self.tags + [_tag])
            if len(message) < self._plc.connection_size:
                self._message = message
                self.tags.append(_tag)
                return True
            else:
                return False

        else:
            self.__log.error(f'Failed to create request path for {tag}')
            raise RequestError('Failed to create request path')

    def send(self):
        if not self._msg_errors:
            request = self._build_request()
            self._send(request)
            self.__log.debug(f'Sent: {self!r}')
            reply = self._receive()
            response = MultiServiceResponsePacket(reply, tags=self.tags)
        else:
            self.error = f'Failed to create request path for: {", ".join(self._msg_errors)}'
            response = MultiServiceResponsePacket()
            response._error = self.error

        self.__log.debug(f'Received: {response!r}')
        return response

def _make_write_data_tag(tag_info, value, elements, request_path, fragmented=False):
    data_type = tag_info['data_type']
    if tag_info['tag_type'] == 'struct':
        if not isinstance(value, bytes):
            raise RequestError('Writing UDTs only supports bytes for value')
        _dt_value = b'\xA0\x02' + Pack.uint(tag_info['data_type']['template']['structure_handle'])
        data_type = tag_info['data_type']['name']

    elif data_type not in DataType:
        raise RequestError("Unsupported data type")
    else:
        _dt_value = Pack.uint(DataType[data_type])

    service = Services.write_tag_fragmented if fragmented else Services.write_tag

    rp = b''.join((service,
                   request_path,
                   _dt_value,
                   Pack.uint(elements),
                   value))
    return rp, data_type

def _make_write_data_bit(tag_info, value, request_path):
    mask_size = DataTypeSize.get(tag_info['data_type'])
    if mask_size is None:
        raise RequestError(f'Invalid data type {tag_info["data_type"]} for writing bits')

    or_mask, and_mask = value
    return b''.join((
        Services.read_modify_write,
        request_path,
        Pack.uint(mask_size),
        Pack.ulint(or_mask)[:mask_size],
        Pack.ulint(and_mask)[:mask_size]
        ))

class SendRRDataRequestPacket(RequestPacket):
    __log = logging.getLogger(f'{__module__}.{__qualname__}')
    _message_type = DataItem.unconnected
    _address_type = AddressItem.uccm
    _encap_command = EncapsulationCommand.send_rr_data
    _response_class = SendRRDataResponsePacket

    def _build_common_packet_format(self, addr_data=None) -> bytes:
        return super()._build_common_packet_format(addr_data=None)

class RegisterSessionRequestPacket(RequestPacket):
    __log = logging.getLogger(f'{__module__}.{__qualname__}')
    _encap_command = EncapsulationCommand.register_session
    _response_class = RegisterSessionResponsePacket

    def _build_common_packet_format(self, addr_data=None) -> bytes:
        return self.message

class UnRegisterSessionRequestPacket(RequestPacket):
    __log = logging.getLogger(f'{__module__}.{__qualname__}')
    _encap_command = EncapsulationCommand.unregister_session
    _response_class = UnRegisterSessionResponsePacket

    def _build_common_packet_format(self, addr_data=None) -> bytes:
        return b''

    def _receive(self):
        return b''

class ListIdentityRequestPacket(RequestPacket):
    __log = logging.getLogger(f'{__module__}.{__qualname__}')
    _encap_command = EncapsulationCommand.list_identity
    _response_class = ListIdentityResponsePacket

    def _build_common_packet_format(self, addr_data=None) -> bytes:
        return b''

class GenericConnectedRequestPacket(SendUnitDataRequestPacket):
    __log = logging.getLogger(f'{__module__}.{__qualname__}')
    _response_class = GenericConnectedResponsePacket

    def __init__(self, plc):
        super().__init__(plc)
        self.service = None
        self.class_code = None
        self.instance = None
        self.attribute = None
        self.request_data = None

    def build(self,
              service: bytes,
              class_code: bytes,
              instance: bytes,
              attribute: bytes = b'',
              request_data: bytes = b'',
              data_format: DataFormatType = None):

        self._response_kwargs = {'data_format': data_format}
        self.class_code = class_code
        self.instance = instance
        self.attribute = attribute
        self.service = service
        self.request_data = request_data
        req_path = request_path(class_code, instance, attribute)

        self.add(service, req_path, request_data)

class GenericUnconnectedRequestPacket(SendRRDataRequestPacket):
    __log = logging.getLogger(f'{__module__}.{__qualname__}')
    _response_class = GenericUnconnectedResponsePacket

    def __init__(self, plc):
        super().__init__(plc)
        self.service = None
        self.class_code = None
        self.instance = None
        self.attribute = None
        self.request_data = None

    def build(self,
              service: Union[int, bytes],
              class_code: Union[int, bytes],
              instance: Union[int, bytes],
              attribute: Union[int, bytes] = b'',
              request_data: bytes = b'',
              route_path: bytes = b'',
              unconnected_send: bool = False,
              data_format: DataFormatType = None):
        self._response_kwargs = {'data_format': data_format}
        self.class_code = class_code
        self.instance = instance
        self.attribute = attribute
        self.service = service
        self.request_data = request_data
        req_path = request_path(class_code, instance, attribute)

        if unconnected_send:
            self.add(wrap_unconnected_send(b''.join((service, req_path, request_data)), route_path))
        else:
            self.add(service, req_path, request_data, route_path)

def wrap_unconnected_send(message, route_path):
    rp = request_path(class_code=ClassCode.connection_manager, instance=b'\x01')
    msg_len = len(message)
    return b''.join(
        [
            ConnectionManagerService.unconnected_send,
            rp,
            PRIORITY,
            TIMEOUT_TICKS,
            Pack.uint(msg_len),
            message,
            b'\x00' if msg_len % 2 else b'',
            route_path
        ]
    )

def request_path(class_code: Union[int, bytes], instance: Union[int, bytes],
                 attribute: Union[int, bytes] = b'', data: bytes = b''):

    path = [encode_segment(class_code, CLASS_TYPE), encode_segment(instance, INSTANCE_TYPE)]

    if attribute:
        path.append(encode_segment(attribute, ATTRIBUTE_TYPE))

    if data:
        path.append(data)

    return Pack.epath(b''.join(path))

def encode_segment(segment: Union[bytes, int], segment_types: dict):
    if isinstance(segment, int):
        if segment <= 0xff:
            segment = Pack.usint(segment)
        elif segment <= 0xffff:
            segment = Pack.uint(segment)
        elif segment <= 0xfffffffff:
            segment = Pack.dint(segment)
        else:
            raise RequestError('Invalid segment value')

    _type = segment_types.get(len(segment))

    if _type is None:
        raise RequestError('Segment value not valid for segment type')

    return _type + segment


#! /usr/bin/env python3

from mule_local.JobGeneration import *

from mule.InfoError import *

import glob
import os
import re
import sys

class JobData(InfoError):
	"""
	Load all avialable data within job directory.

	This data in includes
		a) All .pickle files within the directory
		b) All [MULE] prefixed output in the output.out file
	"""

	def __init__(
		self,
		jobdir = None,
		verbosity = 10
	):
		InfoError.__init__(self, 'JobData')

		self.verbosity = verbosity

		# Load raw job data
		self.__load_job_raw_data(jobdir)

		# Create flattened data
		self.__create_flattened_data()

	def __parse_job_output(
		self,
		output_lines
	):
		retdict = {}
		for l in output_lines:
			m=re.match("^\[MULE\] ([^ :]*): (.*)$", l)
			if m != None:
				tag = m.group(1)
				data = m.group(2)
				retdict[tag] = data

		return retdict

	def __load_job_raw_data(
			self,
			jobdir = None
	):
		"""
		Parse all output.out files and extract all kind of job output information

		Return a dictionary with content from the job directories
		{
			#
			# Dictionary with data from job generation
			# (read from [jobdir]/jobgeneration.pickle)
			#
			'jobgeneration':	# From jobgeneration.pickle
			{
				'compile': [...],
				'runtime': [...],
				'parallelization': [...],
				'platforms_platform': [...],
				'platform_resources': [...],
			},
			'output':		# From output.out with prefix [MULE]
			{
				'simulation_benchmark_timings.main': [value],
				'simulation_benchmark_timings.main_simulationLoop': [value],
				[...]
			},
			'[filename(.pickle)]':
			{
				[...]
			}
			},
			'[filename(.pickle)]':
			{
				[...]
			}
		"""

		#
		self.__job_raw_data = {}

		if self.verbosity > 5:
			self.info("")
			self.info("Processing '"+jobdir+"'")

		"""
		* Process 'output.out'
		"""
		if self.verbosity > 5:
			self.info("Loading job output file 'output.out'")
		outfile = jobdir+'/output.out'
		try:
		#if True:
			with open(outfile, 'r') as f:
				content = f.readlines()
				self.__job_raw_data['output'] = self.__parse_job_output(content)

		except Exception as err:
			print("*"*80)
			print("* WARNINNG: opening '"+outfile+"' (ignoring)")
			print("* "+str(err))
			print("*"*80)

		"""
		Process 'jobgeneration.pickle'
		"""
		# Ensure that 'jobgeneration.pickle' exists
		jobgenerationfile = jobdir+'/jobgeneration.pickle'
		if self.verbosity > 5:
			self.info("Loading 'jobgeneration.pickle'")
		j = JobGeneration(dummy_init=True)
		self.__job_raw_data['jobgeneration'] = j.load_attributes_dict(jobgenerationfile)

		"""
		Process other '*.pickle'
		"""
		pickle_files = glob.glob(jobdir+'/*.pickle')

		# Iterate over all found pickle files
		for picklefile in pickle_files:
			filename = os.path.basename(picklefile)
			tag = filename.replace('.pickle', '')
			if tag == 'jobgeneration':
				continue

			if self.verbosity > 5:
				self.info("Loading pickle file '"+filename+"'")

			import pickle
			with open(picklefile, 'rb') as f:
				self.__job_raw_data[tag] = pickle.load(f)

	def get_job_raw_data(self):
		"""
		Return the raw job information data
		Warning: This storage format is likely to change!
		"""
		return self.__job_raw_data

	def __create_flattened_data(self):
		"""
		Return a dictionary with a flattened hierarchy

		This joins all hierarchical structures with a '.'

		E.g. the value
			self.__job_raw_data['jobgeneration'].parallelization.num_cores_per_socket
		is stored in
			self.__flattened_job_data['jobgeneration.parallelization.num_cores_per_socket']
		"""

		self.__flattened_job_data = {}

		# For all raw data
		for raw_key, raw_value in self.__job_raw_data.items():
			if raw_key == 'output':
				for key, data in raw_value.items():
					key = 'output.'+key.lower()
					self.__flattened_job_data[key] = data

			elif raw_key == 'jobgeneration':
				for group_name, group_value in raw_value.items():
					if isinstance(group_value, dict):
						for key, attr in group_value.items():
							key = group_name+"."+key
							self.__flattened_job_data[key] = attr
					elif isinstance(group_value, (int, float, str)):
						self.__flattened_job_data[group_name] = group_value
					else:
						raise Exception("Unknown type in pickled data")

			else:
				for key, data in raw_value.items():
					key = key.lower()
					self.__flattened_job_data[raw_key+'.'+key] = data

	def get_flattened_data(self):
		return self.__flattened_job_data

if __name__ == "__main__":

	verbosity = 0

	jobdirs = []

	if len(sys.argv) > 1:
		jobdirs = sys.argv[1:]
	else:
		print("")
		print("Usage:")
		print("	"+sys.argv[0]+" [jobdir 1] [jobdir 2] ...")
		print("")
		sys.exit(1)

	for j in jobdirs:

		if verbosity > 5:
			print("*"*80)
			print("Job directory: "+j)
			print("*"*80)

		j = JobData(jobdir = j, verbosity=verbosity)
		d = j.get_flattened_data()

		for key, value in d.items():
			print(key+" => "+str(value))
	#			break


class Packet:
    ## the number of bytes used to store packet length
    seq_num_S_length = 10
    length_S_length = 10
    ## length of md5 checksum in hex
    checksum_length = 32

    def __init__(self, seq_num, msg_S):
        self.seq_num = seq_num
        self.msg_S = msg_S

class AckPack(Packet):
    global data
    flag_length = 7

    def __init__(self, seq_num, msg_S, flag):
        Packet.__init__(self, seq_num, msg_S)
        self.flag = flag

msg_S = 'The use of COBOL cripples the mind; its teaching should, therefore, be regarded as a criminal offense. -- Edsgar Dijkstra'
seq_num = 0
pos_ack = bytes([00000000])
#pos = bin(0)
#data = bin(128)
#neg = bin(64)
pos = (1).to_bytes(2, byteorder='big')
neg = (0).to_bytes(2, byteorder='big')
data = (128).to_bytes(2, byteorder='big')
p = AckPack(seq_num, msg_S, data)
#print(type(p.flag))

#neg_ack = bytes([01000000])

#data = bytes([10000000])

def get_bit(byteval,idx):
    return ((byteval&(1<<idx))!=0)

#print(get_bit(data, 6))
#print("Pos: "+ str(len(str(pos))))
#print(len(pos))
print(pos)
#print(len(neg))
#print("Neg: "+ str(len(str(neg))))
print(neg)
#print("Data: "+ str(len(str(data))))
#print(len(data))
print(data)
#print(pos_ack)
#print(data)

print(get_bit(int.from_bytes(pos, byteorder='big'), 0))
print(get_bit(int.from_bytes(neg, byteorder='big'), 0))
print(get_bit(int.from_bytes(data, byteorder='big'), 7))
print(get_bit(int.from_bytes(p.flag, byteorder='big'), 7))

def test(flag):
    if flag is "data":
        print("data")
    else:
        print("wrong")


import urllib.request
import datetime
import argparse
from bs4 import BeautifulSoup
from ics import Calendar, Event

WEBSITE = "https://spaceflightnow.com/launch-schedule/"
MONTHES = {"Jan": 1, "Feb": 2, "March": 3, "April": 4, "May": 5, "June": 6,
           "July": 7, "Aug": 8, "Sept": 9, "Oct": 10, "Nov": 11, "Dec": 12}

CURRENT_YEAR = datetime.datetime.today().year
CURRENT_MONTH = datetime.datetime.today().month

def get_year(datename):
    year = CURRENT_YEAR
    month = get_month(datename)
    if not month:
        return None
    if month < CURRENT_MONTH:
        year += 1

    return year

def get_month(datename):
    date = datename.find('span', attrs={'class': 'launchdate'}).text
    for possible_month in MONTHES:
        if possible_month in date:
            return MONTHES[possible_month]

    #print(date, "has no valid month")
    return None

def get_day(datename, missiondata):
    date = datename.find('span', attrs={'class': 'launchdate'}).text
    day = "".join([letter for letter in date if (letter.isdigit() or letter == "/")])
    if not day:
        return None

    # Now we get the time of the launch
    timetype, _ = missiondata.findAll("span")
    launchtime = timetype.next_sibling

    # If the launch is on different days in different time zones find the day that is on GMT
    if "/" in day:
        day = launchtime.split("GMT on")[1].split("(")[0]
        day = "".join([l for l in day if l.isdigit()])

    day = int(day)
    if day > 31:
        return None

    return day

def get_mission(datename):
    mission = datename.find('span', attrs={'class': 'mission'})
    mission = mission.text.replace(" • ", ": ")
    return mission

def get_location(missiondata):
    _, location = missiondata.findAll("span")
    location = location.next_sibling
    while location[0] == " ":
        location = location[1::]
    return location

def get_launchtime(missiondata):
    # If the time is not yet set, make the event all day
    timetype, _ = missiondata.findAll("span")
    launchtime = timetype.next_sibling

    if "TBD" in launchtime or "GMT" not in launchtime:
        #print(launchtime, "is not a valid time stamp")
        return 0, 0, 0, True

    launchtime = launchtime.split("GMT")[0].replace(" ", "").replace(":", "")

    launchstart = launchtime.split("-")[0]

    if len(launchstart) == 4:
        launchstart += "00"
    if not launchstart.isdigit():
        #print(launchstart, "is not a valid time stamp")
        return 0, 0, 0, True

    assert len(launchstart) == 6

    hour = launchstart[0:2]
    minute = launchstart[2:4]
    second = launchstart[4:6]

    return int(hour), int(minute), int(second), False

def make_ics_timestamp(year, month, day, hour, minute):
    timestamp = str(year)
    timestamp += str(month).zfill(2)
    timestamp += str(day).zfill(2)
    timestamp += "T"
    timestamp += str(hour).zfill(2)
    #timestamp += ":"
    timestamp += str(minute).zfill(2)
    #timestamp += ":"
    #timestamp += str(second).zfill(2)
    return timestamp

def parse_website():
    page = urllib.request.urlopen(WEBSITE)
    soup = BeautifulSoup(page, 'html5lib')

    datename = soup.findAll('div', attrs={'class': 'datename'})
    missiondata = soup.findAll('div', attrs={'class': 'missiondata'})
    missisondescription = soup.findAll('div', attrs={'class': 'missdescrip'})

    return datename, missiondata, missisondescription

def get_full_launchtime(datename, missiondata):
    year = get_year(datename)
    month = get_month(datename)
    day = get_day(datename, missiondata)
    hour, minute, _, is_all_day = get_launchtime(missiondata)

    if not None in [year, month, day]:
        begin = make_ics_timestamp(year, month, day, hour, minute)
    else:
        begin = None

    return begin, is_all_day

def main():
    parser = argparse.Argparser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("-o", "--output-filename", dest="outfile",
                        required=True, type=str)
    args = parser.parse_args()
    run(args.outfile)

def run(output_file):
    calendar = Calendar()
    datenames, missiondatas, descriptions = parse_website()

    for datename, data, desc in zip(datenames, missiondatas, descriptions):
        mission = get_mission(datename)
        location = get_location(data)
        begin, is_all_day = get_full_launchtime(datename, data)

        if begin:
            event = Event()
            event.begin = begin
            event.description = desc.text
            event.name = mission
            if is_all_day:
                event.make_all_day()
            event.location = location
            event.uid = mission.replace(" ", "")

            calendar.events.add(event)

    with open(output_file, "w") as outfile:
        outfile.writelines(calendar)

    print(calendar.events)
    print(len(calendar.events))

if __name__ == "__main__":
    main()


from selenium import webdriver

chrome_driver_path ="C:\\Users\\LadyDeveloper\\Documents\\Projetos\\software\\chromedriver.exe"
driver = webdriver.Chrome(executable_path=chrome_driver_path)

driver.get('https://www.python.org/')

# time = [li.text for li in driver.find_elements_by_tag_name('time')]
time = [li.text for li in driver.find_elements_by_css_selector('.event-widget > div:nth-child(1) > ul:nth-child(3) > li > time')]
events = [li.text for li in driver.find_elements_by_css_selector('.event-widget > div:nth-child(1) > ul:nth-child(3) > li > a')]

dict_events = {}

for item in range(len(events)):
    dict_events[item] = {
        "name": events[item],
        "time": time[item]
    }
print(dict_events)

driver.quit()


import socket
import ipaddress

def get_ip_address():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect(("8.8.8.8", 80))
    return s.getsockname()[0]

def checkCentralRef(ip):
    new_ip = None
    if ip is None:
        new_ip = get_ip_address()
    else:
        try:
            new_ip = ipaddress.ip_address(ip)
            new_ip = ip
        except:
            print('invalid ip, using local ip')

    return new_ip


import os
from http.client import HTTPResponse
from django.shortcuts import render, redirect
from blog.models import Post, Comentario
from blog.forms import ComentarioForm
from django.views.generic import DetailView
from django.contrib import messages
from blog.forms import ComentarioForm, PostearForm
from django.views.generic import DetailView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy

# Create your views here.

def index(request):
    ls = list(Post.objects.all().order_by('-id'))
    context = {'post_list': ls,
                }
    return render(request,'index.html',context=context)

def contacto(request):
    ig = '@instagram'
    fc = 'orquestavientosdecambio'
    tw = 'twitter'
    ubi = 'Roque Sáenz Peña, Chaco, Argentina'
    telhiper = '549'+'03644574664'
    tel = '03644-574664'
    email = 'orquestaescuelavientosdecambio@gmail.com'
    return render(request,'contacto.html',context={'ig':ig,
                                                    'fc':fc,
                                                    'tw':tw,
                                                    'ubi':ubi,
                                                    'telhiper':telhiper,
                                                    'tel':tel,
                                                    'email':email,
                                                    })

def about(request):
    return render(request,'about.html')

def post_list(request):
    ls = list(Post.objects.all().order_by('-id'))
    context = {'post_list': ls,
                }
    return render(request,'test.html',context)

class DetallesPost(DetailView):

    model = Post
    template_name = 'single-post.html'

    def get_context_data(self, **kwargs):
        data = super().get_context_data(**kwargs)

        comentarios_conectados = Comentario.objects.filter(
            post=self.get_object()).order_by('-fecha_publicacion')

        data['comentarios'] = comentarios_conectados

        if self.request.user.is_authenticated:
            data['comentario_form'] = ComentarioForm(instance=self.request.user)

        return data

    def post(self, request, *args, **kwargs):
        nuevo_comentario = Comentario(texto=request.POST.get('texto'),
                                  autor=self.request.user,
                                  post=self.get_object())
        nuevo_comentario.save()
        return self.get(self, request, *args, **kwargs)

'''def single_post(request,postid,slug):

    comentario_form = ComentarioForm()

    context = {
        'post': Post.objects.get(id=postid),
        'comentario_form': comentario_form,

                }
    return render(request,'single-post.html',context)'''

'''def crear_post(request):
    if request.method == "POST":
        form = FormPost(request.POST, request.FILES)
        if form.is_valid():
            post = form.save(commit=False)
            post.author_id = request.user.id
            post.save()
            titulo = form.cleaned_data.get("title")
            messages.success(request, f"El post {titulo} se ha creado correctamente")
            return redirect("post")
        else:
            for msg in form.error_messages:
                messages.error(request, form.error_messages[msg])
    form = FormPost()
    return render(request, "crear_post.html", {"form": form})'''

class Postear(CreateView):
    model = Post
    template_name = 'crear_post.html'
    fields = ('titulo','texto')

    def get_context_data(self, **kwargs):
        data = super().get_context_data(**kwargs)

        if self.request.user.is_authenticated:
            data['post_form'] = PostearForm(instance=self.request.user)

        return data

    def post(self, request, *args, **kwargs):
            nuevo_post = Post(texto=request.POST.get('texto'),
                                    autor=self.request.user,
                                    titulo=self.request.POST.get('titulo')
                                    )
            nuevo_post.save()

            return self.get(self, request, *args, **kwargs)

class EditarPost(UpdateView):
    model = Post
    template_name = 'editar_post.html'
    fields = ('titulo','texto','imagen')

class EliminarPost(DeleteView):
    model = Post
    template_name = 'eliminar_post.html'
    success_url = reverse_lazy('home')


number_of_runs = int(input('Oi, tudo bom, quantas corridas você fez por dia? '))

price = 0

for price in number_of_runs:

    n = float(input('Escreva um valor da corrida: '))
    price += n

uber = price * 0.75
motorista = price * 0.25

print('O valor total arrecadado é {}, o valor arrecadado pelo aplicadivo é {}, e o valor que voçê arrecadou é {}'.format(price, uber, motorista))


import random

palabras = {
    "queso": {
        90: "La palabra es un alimento",
        40: "El alimento es de color amarillo",
        10: "El alimento se derrite"
    },
    "dragon": {
        90: "La palabra es un animal mitologico",
        40: "El animal tiene alas",
        10: "El animal suele exhalar fuego"
    },
    "pescado": {
        90: "La palabra es un animal acuatico",
        40: "El animal puede nadar",
        10: "El animal tiene branquias"
    },
    "gato": {
        90: "La palabra es un animal terrestre",
        40: "El animal tiene 4 patas",
        10: "El animal es domestico"
    },
    "taza": {
        90: "La palabra es un utensilio de cocina",
        40: "El utensilio está relacionado al café",
        10: "El utensilio sirve para beber liquidos"
    },
    "audifonos": {
        90: "La palabra es un objeto electronico",
        40: "El objeto tiene relación con la musica",
        10: "El objeto está asociado a las orejas"
    }
}

eleccion = random.choice(list(palabras.keys()))
elecPlayer = 0
puntuacion = 100

while True:
    try:
        elecPlayer = input("Trata de adivinar la palabra: ").lower()
        if not elecPlayer.isalpha():
            raise TypeError("Debes ingresar una palabra")
    except TypeError as error:
        print(f"Error: {error}")
    else:
        if elecPlayer == eleccion:
            print(f"Ganaste, la palabra correcta era {eleccion} y tu puntuación es: {puntuacion}")
            break
        else:
            puntuacion = puntuacion - 10
            if puntuacion in palabras[eleccion]:
                print(palabras[eleccion][puntuacion])

            if puntuacion == 0:
                print("Perdiste, tu puntuación llegó a 0")
                break


import time
import sys
import os
import os.path
import urllib.request as request
import platform
commands=["cd","burn","delete","append","clear","image","help","python","terminate","os"]
while True:
  my_system = platform.uname()
  thyme=input(f"{my_system.system}"+" Thyme ")
  thyme=thyme.split(" ")
  if thyme[0]=="cd":
    cd=thyme[1:len(thyme)]
    print("You have requested to go into: "+str(cd))
    for x in("Loading...\n"):
      sys.stdout.write(x)
      sys.stdout.flush()
      time.sleep(0.03)
    time.sleep(2)
    thyme=thyme[1:len(thyme)]
    cd=' '.join(thyme)

    if cd.endswith(('.png', '.jpg', '.jpeg',".pdf")):
      print("Cannot open file because the file is an image.")
    else:
      f=open(cd,"r")
      content=f.readlines()
      content=' '.join(content)
      print(content)
      f.close()
    print("\n")
  if thyme[0]=="burn":
    burned_file_name=thyme[1]
    burned=thyme[2:len(thyme)]
    thyme=' '.join(thyme)
    print("You have burned: "+burned_file_name+" to you disk.")
    if os.path.isfile(burned_file_name):
      burned_file_name.write(burned)
    else:
      f=open(burned_file_name,"w")
      burned=' '.join(burned)
      f.write(str(burned))
      f.close()
  if thyme[0]=="delete":
    delete=thyme[1]
    delete=''.join(delete)
    print("You have removed file:"+delete)
    os.remove(delete)
  if thyme[0]=="append":
    first=thyme[1]
    append=thyme[2:len(thyme)]
    append=' '.join(append)
    f=open(first,"a+")
    f=f.write(append)
    print("Appended: "+append+" to file:"+first)
  if thyme[0]=="strip":
    file=thyme[1]
    strip=thyme[2:len(thyme)]
    f=open(file,"w+")

    f.close()
  if thyme[0]=="clear":
    os.system("clear")
  if thyme[0]=="image":
    filename=input("Filename: ")
    imagetype=input("Image type: ")
    image_url=input("Image Url: ")
    file=filename+"."+imagetype
    open(file,"w")
    request.urlretrieve(image_url,file)
  if thyme[0]=="help":
    print("cd\n   Change Files\nburn\n   Create Files\ndelete\n   Delete Files\nappend\n   Add text to files.\nclear\n   Clears the whole screen.\nimage\n   Creates a file with the image.\nhelp\n   Brings up this text.\nreplace\n   Allows you to replace certain text in a file\npython\n   Allows you to run print commands ONLY.\nterminate\n   Does not take arguments, terminates the program.")
  if thyme[0]=="replace":
    file=thyme[1]
    replace=thyme[2]
    will_replace=thyme[3]
    f=open(file,"r")
    content=f.read()
    f.close()
    if replace in content:
      f = open(file,'w')
      content=content.replace(replace,will_replace)
      f.write(content)
      print(content)
      f.close()
    else:
     print("There is no such word or character in this file.")
  if thyme[0]=="python":

    print("NO VARIABLES. SIMPLE PRINT COMMANDS ONLY.")
    while True:
      test=input(">>> ")
      if test=="exit":
        break
      if test=="" or test==" ":
        continue
      else:
        try:
          eval(test)
        except Exception as e:
          print(e)
          continue
  if thyme[0]=="terminate":
    while True:
      terminate=input("Type anything for yes or type NO in all caps with no space.")
      if terminate=="NO":
        break
      else:
        sys.exit()


import numpy as np

class DictVect():
    def __init__(self,features,expected_values):
        self.feature_map={f: idx for idx,f in enumerate(features)}
        self.expected_vals={f:v for f,v in zip(features,expected_values)}
        self.train_vecs=None
        self.labels=None

    def train(self,vec_labels):
        vecs,labels=[],[]
        for vec,label in vec_labels:
            vecs.append(vec)
            labels.append(label)
        self.train_vecs=np.array(vecs)
        self.labels=labels

    def getFeature(self,vec_map,dev):
        """
        if deviation with in or near 1 consider else 0
        """
        size=len(self.feature_map)
        arr=[0]*size
        for k,v in vec_map.items():
            exp_val=self.expected_vals[k]
            if v<= exp_val+dev and v>=exp_val-dev:
                arr[self.feature_map[k]]=1
        return np.array(arr).reshape(1,size)

    def predict(self,vec_map,dev=0.05):
        vec=self.getFeature(vec_map,dev)
        matches=np.dot(self.train_vecs,vec.T)
        matches=matches.ravel()
        best_idx=np.argmax(matches)
        count=np.count_nonzero(self.train_vecs[best_idx])
        score=matches[best_idx]/count
        return self.labels[best_idx],score


import xlrd, json

with open('alumnosIntercambio.json', 'w') as outfile:
    book = xlrd.open_workbook("VacantesIntercambioFeb-16.xls")
    sh = book.sheet_by_index(0)
    carreras = {"Industrial":"ing-industrial", u"Electr\xf3nica":"ing-electronica", u"Inform\u00e1tica":"ing-informatica", u"An\u00e1lisis de Sistemas": "lic-sistemas", "Naval":"ing-naval", u"Qu\u00edmica":"ing-quimica", u"Mec\u00e1nica":"ing-mecanica",  u"Industrial - Mec\xe1nica":"ing-industrial", "Civil":"ing-civil"}
    outfile.write("[")
    for rx in range(1, sh.nrows):
        name = sh.cell_value(rowx=rx, colx=3).encode('utf-8')
        lastName = sh.cell_value(rowx=rx, colx=2).encode('utf-8')
        title = name + " " + lastName
        universidad = sh.cell_value(rowx=rx, colx=0)
        carrera = carreras[sh.cell_value(rowx=rx, colx=1)]
        mail = sh.cell_value(rowx=rx, colx=5)
        data = json.dumps({"title": title, "universidad": universidad, "description": carrera + "; " + mail, "carrera": carrera}, separators=(',',':'))
        outfile.write(data)
        if(rx != sh.nrows-1):
            outfile.write(",")

    outfile.write("]")


from pyfiglet import Figlet
import sys

figlet = Figlet()

fonts = figlet.getFonts()
#check for 0 command line arguments
if len(sys.argv) == 1:
   print('Invalid usage')

#check for only 2 command line arguments
elif len(sys.argv) == 3:

   #check for '-f' or '-font' as first command line argument
   if sys.argv[1] == '-f' or sys.argv[1] == '-font':
      #check for a font as second command line argument
      if sys.argv[2] in fonts:
         figlet.setFont(font = sys.argv[2])
         s = input('Input: ')
         print('Output: ' + figlet.renderText(s))

      #if second command line argument is not a font
      else:
         sys.exit('Invalid usage')

   else:
      sys.exit('Invalid usage')

else:
   sys.exit('Invalid usage')


# Uses Selenium to start the Chrome browser in the background,
# displays the last 56 arrests in Sampson county,
# searches for the perp's name, then displays a dialog if found.

import sys, os
import selenium as se
from selenium 			    import webdriver
from selenium.common.exceptions     import TimeoutException
from selenium.webdriver.common.keys import Keys

# Case Sensitive
criminal_name = 'Firstname Lastname'
arrests_records_url = 'https://northcarolina.arrests.org/index.php?county=862&page=1&results=56'

# Run via the Chrome browser in background
# Running headless also prevents from being blacklisted
options = se.webdriver.ChromeOptions()
options.add_argument('headless')
driver = se.webdriver.Chrome(chrome_options=options)
driver.get(arrests_records_url)

# Get the html source substring of just the arrests
try:
	html_source = driver.page_source
	html_source = html_source.encode('utf-8')
	html_source = html_source[html_source.index('search-results'):html_source.index('arrests-ribbon')]
except:
	print('Error: Couldn\'t get the HTML source')
	quit()

# Search for the name of our perp
if criminal_name in html_source:
    print('Found, displaying dialog')
    os.system('open ./ALERT.app')
else:
    print('No results for ' + criminal_name)


class Solution(object):
    def minCut(self, s):
        """
        :type s: str
        :rtype: int
        """
        # Min cut for s[:i]
        dp = [0] * (len(s)+1)
        dp[0] = -1  # For latter s[j:i] if j == 0, can still use +1.
        for i in range(2, len(dp)):
            min_cut = dp[i-1] + 1 # Add one cut for this single letter.
            for j in range(i-2, -1, -1):
                # Find possible smaller cut.
                if s[j:i] == s[j:i][::-1]:
                    min_cut = min(min_cut, dp[j] + 1)
            dp[i] = min_cut
        return dp[-1]