#!/usr/bin/python3

# Ref: https://srome.github.io/Parsing-HTML-Tables-in-Python-with-BeautifulSoup-and-pandas/

from __future__ import absolute_import, division

import sys
import json
import os

from bs4 import BeautifulSoup, NavigableString
import pandas as pd
import requests
from tabulate import tabulate
from collections import OrderedDict
import logging
import time

logger = logging.getLogger('covid19.Scrapper')
TABLE_COLUMNS = ["Country", "Cases", "NCases", "Deaths",
                 "NDeaths", "Recovered", "Active", "Critical",
                 "CPM", "DPM", "Tests", "TPM", "Continents"]

CHART_TYPES = {'coronavirus-cases-linear' : 'Total Cases', # Total coronavirus cases
               'graph-cases-daily' : 'New Cases',        # Daily cases
               'graph-active-cases-total' : 'Active Cases',
               'coronavirus-deaths-linear' : 'Total Deaths', # Total deaths
               'graph-deaths-daily' : 'New Deaths'}        # Daily deaths

class CovidData(object):
    URL = 'https://www.worldometers.info/coronavirus/'
    OUT_FILE = 'worldometer_covid19.json'
    CP_FILE = "cp"

    def __init__(self):
        self.logger = logging.getLogger('covid19.Scrapper.CovidData')
        self.url = CovidData.URL
        self.live_column_names = []

    def __get_gmt_date(self):
        return time.strftime("%d/%m/%Y %Z", time.gmtime())

    def __is_reload_req(self):
        reload = True
        if os.path.isfile(CovidData.CP_FILE):
            with open(CovidData.CP_FILE) as fd:
                reload = (fd.read() != self.__get_gmt_date())
        if not os.path.isfile(CovidData.OUT_FILE):
            reload = True

        return reload

    def __touch_cp_file(self):
        with open(CovidData.CP_FILE, 'w') as fd:
            fd.write(self.__get_gmt_date())

    def __fetch_all_countries_data(self, out_file):
        response = requests.get(self.url)
        soup = BeautifulSoup(response.text, 'lxml')
        countries_url = OrderedDict()
        for a in soup.find_all('a', href=True):
            if a['href'].startswith('country'):
                countries_url[a.text] = os.path.join(self.url, a['href'])
        countries_data = OrderedDict()
        for country, url in countries_url.items():
            countries_data[country] = self.__parse_country_data(url)

        with open(out_file, 'w') as fd:
            json.dump(countries_data, fd)

    def __parse_country_data(self, country_url):
        self.logger.info("Fetching data from %s", country_url)
        soup = BeautifulSoup(requests.get(country_url).text, "lxml")
        all_scripts = soup.find_all('script')
        data = OrderedDict()
        for script in all_scripts:
            script = script.text
            for char_type in CHART_TYPES:
                if char_type in script:
                    chart_name = CHART_TYPES[char_type]
                    self.logger.info("Populating data for %s", chart_name)
                    sys.stdout.flush()
                    #self.logger.info("%s: %s", index, char_type)
                    chart_data = script.split('data: [', 1)[1].split(']', 1)[0]
                    chart_data = '[' + chart_data + ']' # create correct JSON data
                    chart_data = json.loads(chart_data)

                    # Extract dates
                    chart_date = script.split('categories: [', 1)[1].split(']', 1)[0]
                    chart_date = '[' + chart_date + ']' # create correct JSON data
                    chart_date = json.loads(chart_date)

                    for i in range(len(chart_date)):
                        if chart_date[i] not in data:
                            data[chart_date[i]] = dict()

                        data[chart_date[i]][chart_name] = chart_data[i]
                        data[chart_date[i]]['date'] = chart_date[i]
        ret_data = []
        for dt in data:
            ret_data.append(data[dt])

        return ret_data

    def __get_live_stats(self):
        response = requests.get(self.url)
        soup = BeautifulSoup(response.text, 'lxml')
        return [(table['id'], self.__parse_html_table(table))
                for table in soup.find_all('table')]

    def __parse_html_table(self, table):
        self.live_column_names = []

        # get <thead> and extract column names from it
        thead = table.find_all('thead')[0]
        th_tags = thead.find_all('th')

        for th in th_tags:
            col_name = []
            for item in th.contents:
                if isinstance(item, NavigableString):
                    col_name.append(item.strip(',+').strip())
                elif item.get_text().strip():
                    col_name.append(item.get_text().strip())
            self.live_column_names.append(' '.join(col_name))

        # get the first <tbody> and extract data
        tbody = table.find_all('tbody')[0]
        # list of lists from tr/td elements
        data = [
            [td.get_text().strip().replace(',', '').strip('+')
             for td in row.find_all('td')]
            for row in tbody.find_all('tr')]

        df = pd.DataFrame(data, columns=self.live_column_names)

        sorting_allowed = True
        # though we get column names from worldometers, we would like
        # our own compact names to help with display, sorting etc
        if len(df.columns) == len(TABLE_COLUMNS):
            df.columns = TABLE_COLUMNS
        else:
            self.logger.warning("Number of columns is not as expected, sorting will not work.")
            sorting_allowed = False
        # replace empty strings with 0 in all columns
        # (does not impact the 'Country' column as it has data)
        for col in df.columns:
            df[col] = df[col].replace('', 0)

        if sorting_allowed:
            # convert a few columns to 'int'
            for col in ["Cases", "NCases", "Deaths",
                        "NDeaths", "Recovered", "Active",
                        "Critical", "Tests"]:
                try:
                    df[col] = df[col].astype(int)
                except ValueError as ve:
                    self.logger.error("int(col) gave value error for %s, %s", col, str(ve))

            # convert a few columns to 'float'
            for col in ["CPM", "DPM", "TPM"]:
                try:
                    df[col] = df[col].astype(float)
                except ValueError as ve:
                    self.logger.error("float(col) gave value error for %s, %s", col, str(ve))

        return df, sorting_allowed

    def get_live_columns(self):
        if len(self.live_column_names) == 0:
            self.__get_live_stats()
        return TABLE_COLUMNS, self.live_column_names

    def get_todays_stats(self):
        table, _ = self.__get_live_stats()[0][1]
        table = table[table['Country'] != table['Continents']]
        return table.sort_values(by=['Cases'], ascending=False)

    def get_historical_data(self):
        if self.__is_reload_req():
            self.__fetch_all_countries_data(CovidData.OUT_FILE)
            self.__touch_cp_file()

        with open(CovidData.OUT_FILE) as fd:
            data = json.load(fd)

        return data

def display_stats(table):
    print(tabulate(table, headers=["#"] + list(table.columns),
                   tablefmt='psql'))

def main():
    hp = CovidData()
    #print(hp.get_todays_stats())
    print(time.strftime("%d/%m/%Y %I:%M:%S %p %Z", time.gmtime()))

if __name__ == "__main__":
    main()


from django.conf.urls import url,handler404

from promeds.views import menupage, subcategorypage, addtocartpage
from . import views

#import promeds.views

urlpatterns = [
url(r'^myprofile/$', views.ProfileView, name='profile'),
    url(r'^edit/$', views.UserProfileFormView, name='profileedit'),
    url(r'^home/$', views.homepage,name='home'),
    url(r'menu1/$', menupage, name='menu1'),
    url(r'^login/$', views.login, name='login'),
    url(r'^createaccount/$',views.UserFormView.as_view(),name='createaccount'),
    url(r'healthcare/$',views.healthcarepage,name='healthcarepage'),
    url(r'diagnostic/$', views.diagnosticpage, name='diagnosticpage'),

    url(r'^sub/(?P<subcat_id>[0-9]+)$',subcategorypage,name='subcategorypage'),
    url(r'logout/$', views.log_out, name='logoutpage'),
    url(r'^addtocart/(?P<medid>[0-9]+)$', addtocartpage, name='addtocart'),
    url(r'^ordermedicines/$', views.index, name='ordermedicines'),
    url(r'shippingdetail/$', views.shippingdetailspage, name='shippingdetails'),
    url(r'^ordermedicines/(?P<tablet_id>[0-9]+)/$', views.detailTablet, name='detailTablet'),
    url(r'^subtest/$', views.subtest, name='subtest'),
    url(r'^review/$',views.reviewpage,name='review'),
    url(r'^review/(?P<tabb_id>[0-9]+)/$' , views.deleteitem , name='delete'),
    url(r'^bill/$',views.billpage,name ='billpage'),
    url(r'shipping/$', views.shippingdetailspage1, name='shippingdetails1'),
    url(r'^revieworder/$', views.reviewpage1, name='reviewmeds'),
    url(r'^revieworder/(?P<medd_id>[0-9]+)/$',views.deletemed,name='deletemed'),
    url(r'^bills/$', views.billmedpage, name='bill'),
    url(r'^history/$',views.historypage,name='history'),
    url(r'^history/(?P<bill_id>[0-9]+)/(?P<order_id>[0-9]+)/$',views.deleteorder,name='deleteorder'),
    url(r'^time_check/$', views.time, name='time'),
    url(r'^subtest/(?P<test1_id>[0-9]+)/$', views.deletetest, name='deletetest'),
    url(r'^Reviewtest/$', views.createbill, name='Create_bill'),
    url(r'^history1/(?P<bill_id>[0-9]+)/(?P<order_id>[0-9]+)/$',views.deleteorders,name='deleteorders'),
    url(r'^history2/(?P<test_id>[0-9]+)/$', views.deleteorder_test, name='deleteorder_test'),

]


from flask import Flask, flash, redirect, render_template, request, url_for, flash
from flask_sqlalchemy import SQLAlchemy
from ProgramCreator import *
# from Conversions import *
from teams import *

app = Flask(__name__)
app.secret_key = "junge"

########################### DATABASES SETUP ############################
db_name = 'exercises.db'

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + db_name
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

db = SQLAlchemy(app)

class Accessories(db.Model):
    __tablename__ = "accessories"
    id = db.Column(db.Integer, primary_key=True)
    muscle = db.Column(db.String)
    name = db.Column(db.String)

class Competitors(db.Model):
    __tablename__ = "competitors"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    total = db.Column(db.Integer)

    def __init__(self, name, total):
        self.name = name
        self.total = total
########################### END DATABASES SETUP ############################

########## HELPER FUNCTIONS ##########

def compute_teams():    # actually running team generator algorithm
    names = []
    totals = []
    for comp in Competitors.query.all():
        names.append(comp.name)
        totals.append(comp.total)
    teams = arrange_teams(names, totals)
    print(teams)
    return teams

def to_kilo(pound):     # convert pounds into kilos
    return round(0.45359237*float(pound), 1)

def to_pound(kilo):     # convert kilos to pounds
    return round(float(kilo)/0.45359237, 1)

########## END HELPER FUNCTIONS ##########

########## Both lead to default home page ##########
@app.route('/')
def default():
    return redirect(url_for("home"))

@app.route('/home')
def home():
    return render_template("main.html")

########## Show all exercises in database ##########
@app.route('/allexercises')
def all():
    chests = Accessories.query.filter_by(
        muscle="chest").order_by(Accessories.id).all()
    shoulders = Accessories.query.filter_by(
        muscle="shoulders").order_by(Accessories.id).all()
    triceps = Accessories.query.filter_by(
        muscle="triceps").order_by(Accessories.id).all()
    backs = Accessories.query.filter_by(
        muscle="back").order_by(Accessories.id).all()
    biceps = Accessories.query.filter_by(
        muscle="biceps").order_by(Accessories.id).all()
    legs = Accessories.query.filter_by(
        muscle="legs").order_by(Accessories.id).all()

    return render_template("exercises.html", chests=chests, shoulders=shoulders, triceps=triceps,
                           backs=backs, biceps=biceps, legs=legs)

########## About tab ##########

@app.route("/about")
def about():
    return render_template("about.html")

########## Questionnaire required to create a new program ##########

@app.route('/new', methods=["POST", "GET"])
def new():
    if request.method == "POST":
        name = request.form['name']
        days = request.form['days']
        # days not empty and is number between 2 and 6
        if (not (days.isnumeric() and (2 <= int(days) <= 6))):
            flash("Please enter an amount of days from 2 to 6")
            return render_template("questionnaire.html")
        exp = int(request.form['slider'])

        if (int(exp) > 1 and int(days) < 3):
            flash("For beginner or intermediate programs, minimum days per week is 3")
            return render_template("questionnaire.html")

        # determine exp level as string to display later
        if (exp == 1):
            level = "beginner"
        elif (exp == 2):
            level = "intermediate"
        else:
            level = "advanced"
        # make sure name is not empty, is only letters
        if (len(str(name)) == 0 or not str(name).isalpha()):
            flash("Please enter a valid name")
            return render_template("questionnaire.html")
        return redirect(url_for("process", name=str(name), days=int(days), exp=exp, level=level))

    else:
        return render_template("questionnaire.html")

########## Process the info from questionnaire ##########
@app.route("/program_<name>_<days>days_<level><exp>")
def process(name, days, exp, level):
    prog_create(name, days, exp)
    return render_template("program_done.html", name=name, days=days, level=level)

########## Pound to kilogram calculator ##########
@app.route("/poundtokilo", methods=["POST", "GET"])
def convert():
    if request.method == "POST":
        num = request.form['num']
        conv = request.form['conv-type']
        if (num.isnumeric() and int(num) > 0):
            return redirect(url_for("displayConvert", num=num, conv=conv, drop='kilo'))
        flash("Please enter a number greater than 0")
        return redirect(url_for('convert'))
    else:
        return render_template("convert_main.html", drop='pound')

########## Pound to kilogram result display/restart ##########
@app.route("/display_result_<num>_<conv>", methods=["POST", "GET"])
def displayConvert(num, conv):
    if (str(conv) == 'topound'):
        res = to_pound(num)
        return render_template("converted.html", pound=res, kilo=num, drop='kilo')
    res = to_kilo(num)
    return render_template("converted.html", pound=num, kilo=res, drop='pound')

########## Auto team creator start ##########
@app.route("/team_start", methods=["POST", "GET"])
def teams():
    if request.method == "POST":
        num = request.form['num']
        if (num.isnumeric() and 2 <= int(num) <= 9):
            return redirect(url_for("team_input", num=int(num)))
        flash("Enter a number between 2 and 9", "warning")
        return redirect(url_for('teams'))
    else:
        return render_template("teams.html")

########## Auto team creator competitor input ##########
@app.route("/team_input_<num>_competitors", methods=["POST", "GET"])
def team_input(num):
    if request.method == "POST":
        Competitors.query.delete()  # clear all entries from table
        for i in range(1, int(num) + 1):
            name = request.form['competitor' + str(i)]
            total = request.form['total' + str(i)]
            if (total.isnumeric()):
                comp = Competitors(name, total)
                db.session.add(comp)
                db.session.commit()     # add new entries
            else:
                flash(f"Only enter numbers for totals, {total}")
                return render_template("team_input.html", num=int(num))
        return render_template("display_teams.html", best=compute_teams())

    return render_template("team_input.html", num=int(num))

"""     Run app     """
if (__name__ == "__main__"):
    db.create_all()
    app.run(debug=True)


from gettext import gettext as _

from gi.repository import Gtk

class SettingsDialog(Gtk.Dialog):
    SPACING = 5

    def __init__(self, top_window):
        Gtk.Dialog.__init__(self)
        self.set_transient_for(top_window)
        self.set_title(_("Settings"))
        self.props.modal = True

        notebook = Gtk.Notebook()
        notebook.set_size_request(400, 300)
        self.get_content_area().add(notebook)
        notebook.show()

        box = self._create_onionskin_settings()
        label = Gtk.Label()
        label.props.label = _("Onionskin")
        notebook.append_page(box, label)
        box.show()

        box = self._create_metronome_settings()
        label = Gtk.Label()
        label.props.label = _("Metronome")
        notebook.append_page(box, label)
        box.show()

    def _add_label(self, label_text, box, x, y, w=1, h=1):
        alignment = Gtk.Alignment.new(0.0, 0.0, 0.0, 1.0)
        alignment.props.hexpand = True
        alignment.set_padding(self.SPACING, self.SPACING,
                              self.SPACING, self.SPACING)
        box.attach(alignment, x, y, w, h)
        alignment.show()

        label = Gtk.Label()
        label.props.label = label_text
        alignment.add(label)
        label.show()

    def _add_control(self, widget, box, x, y, w=1, h=1, scale_x=0.0):
        alignment = Gtk.Alignment.new(0.0, 0.0, scale_x, 1.0)
        alignment.props.hexpand = True
        alignment.set_padding(self.SPACING, self.SPACING,
                              self.SPACING, self.SPACING)
        box.attach(alignment, x, y, w, h)
        alignment.show()

        alignment.add(widget)
        widget.show()

    def _create_onionskin_settings(self):

        grid = Gtk.Grid()
        grid.props.orientation = Gtk.Orientation.HORIZONTAL

        cur_row = 0

        self._add_label(_("Onionskin:"), grid, 0, cur_row)

        onionskin_switch = Gtk.Switch()
        onionskin_switch.props.active = True
        self._add_control(onionskin_switch, grid, 1, cur_row)

        cur_row += 1

        self._add_label(_("Type:"), grid, 0, cur_row)

        cels_radio = Gtk.RadioButton()
        cels_radio.props.label = _("By Cels")
        self._add_control(cels_radio, grid, 1, cur_row)

        cur_row += 1

        frames_radio = Gtk.RadioButton()
        frames_radio.props.label = _("By Frames")
        frames_radio.join_group(cels_radio)
        self._add_control(frames_radio, grid, 1, cur_row)

        cur_row += 1

        self._add_label(_("Previous range:"), grid, 0, cur_row)

        prev_adj = Gtk.Adjustment(value=0, lower=0, upper=6,
                                  step_incr=1, page_incr=1, page_size=1)

        prev_scale = Gtk.Scale()
        prev_scale.set_adjustment(prev_adj)
        prev_scale.set_digits(0)
        prev_scale.props.orientation = Gtk.Orientation.HORIZONTAL
        self._add_control(prev_scale, grid, 1, cur_row, scale_x=1.0)

        cur_row += 1

        self._add_label(_("Nest range:"), grid, 0, cur_row)

        next_adj = Gtk.Adjustment(value=0, lower=0, upper=6,
                                  step_incr=1, page_incr=1, page_size=1)

        next_scale = Gtk.Scale()
        next_scale.set_adjustment(next_adj)
        next_scale.set_digits(0)
        next_scale.props.orientation = Gtk.Orientation.HORIZONTAL
        self._add_control(next_scale, grid, 1, cur_row, scale_x=1.0)

        cur_row += 1

        return grid

    def _create_metronome_settings(self):

        grid = Gtk.Grid()
        grid.props.orientation = Gtk.Orientation.HORIZONTAL

        cur_row = 0

        self._add_label(_("Metronome:"), grid, 0, cur_row)

        metronome_switch = Gtk.Switch()
        metronome_switch.props.active = True
        self._add_control(metronome_switch, grid, 1, cur_row)

        cur_row += 1

        self._add_label(_("Beats:"), grid, 0, cur_row)

        first_radio = None
        for i, beat in enumerate([_('6'), _('8'), _('12')]):
            radio = Gtk.RadioButton()
            radio.props.label = beat

            if i == 0:
                first_radio = radio
            else:
                radio.join_group(first_radio)

            self._add_control(radio, grid, 1, cur_row)

            cur_row += 1

        return grid


import datetime

AVERAGE_LIFESPAN =  80

SMOKER_PENALIZATION = 10
DRINKER_PENALIZATION = 10
SEDENTARY_PENALIZATION = 20

def print_with_underscores(message):
    print(message)
    print(len(message) * "-")

def ask_yes_or_not(message):
    response = None

    while response != "S" and response != "N":
        response = input(message + "[S/N]")
    return response

print_with_underscores("Averigua cuanto te queda de vida")
print("Completa esta encuesta para saber cuantos años te quedan")

birth_date = input("¿Cual es tu fecha de nacimiento (formato dd/mm/yyyy)?")

birth_date = datetime.datetime.strptime(birth_date, "%d/%m/%Y")

years_losts = 0

if ask_yes_or_not("¿Fumas?"):
    years_losts += SMOKER_PENALIZATION

if ask_yes_or_not("¿Bebes?"):
    years_losts += DRINKER_PENALIZATION

if  not ask_yes_or_not("¿Haces deporte?"):
    years_losts += SEDENTARY_PENALIZATION

lifespan = AVERAGE_LIFESPAN - years_losts

death_day = birth_date + datetime.timedelta(days = lifespan*365)

print("Fecha de muerte: {}".format(death_day.strftime("%d/%m/%Y")))


import subprocess
import os
import unicodedata
import json
import falcon
from datetime import date, datetime
from butterknife.pool import Subvol

class MyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + "Z"
        if isinstance(obj, date):
            return obj.strftime('%Y-%m-%d')
        if isinstance(obj, map):
            return tuple(obj)
        if isinstance(obj, Subvol):
            return obj.version
        return json.JSONEncoder.default(self, obj)

def parse_subvol(func):
    def wrapped(instance, req, resp, subvol, *args, **kwargs):
        return func(instance, req, resp, Subvol("@" + subvol), *args, **kwargs)
    return wrapped

def serialize(func):
    """
    Falcon response serialization
    """
    def wrapped(instance, req, resp, **kwargs):
        assert not req.get_param("unicode") or req.get_param("unicode") == u"✓", "Unicode sanity check failed"
        resp.set_header("Cache-Control", "no-cache, no-store, must-revalidate");
        resp.set_header("Pragma", "no-cache");
        resp.set_header("Expires", "0");
        r = func(instance, req, resp, **kwargs)
        if not resp.body:
            if not req.client_accepts_json:
                raise falcon.HTTPUnsupportedMediaType(
                    'This API only supports the JSON media type.',
                    href='http://docs.examples.com/api/json')
            resp.set_header('Content-Type', 'application/json')
            resp.body = json.dumps(r, cls=MyEncoder)
        return r
    return wrapped

from jinja2 import Environment, PackageLoader, FileSystemLoader
env = Environment(loader=PackageLoader('butterknife', 'templates'))

def templatize(path):
    template = env.get_template(path)
    def wrapper(func):
        def wrapped(instance, req, resp, **kwargs):
            assert not req.get_param("unicode") or req.get_param("unicode") == u"✓", "Unicode sanity check failed"

            r = func(instance, req, resp, **kwargs)
            r.pop("self", None)

            if not resp.body:
                if  req.get_header("Accept") == "application/json":
                    resp.set_header("Cache-Control", "no-cache, no-store, must-revalidate");
                    resp.set_header("Pragma", "no-cache");
                    resp.set_header("Expires", "0");
                    resp.set_header('Content-Type', 'application/json')
                    resp.body = json.dumps(r, cls=MyEncoder)
                    return r
                else:
                    resp.set_header('Content-Type', 'text/html')
                    resp.body = template.render(request=req, **r)
                    return r
        return wrapped
    return wrapper

class PoolResource(object):
    def __init__(self, pool, subvol_filter):
        self.pool = pool
        self.subvol_filter = subvol_filter

class SubvolResource(PoolResource):
    @templatize("index.html")
    def on_get(self, req, resp):
        def subvol_generator():
            for subvol in sorted(self.pool.subvol_list(), reverse=True):
                if req.get_param("architecture"):
                    if req.get_param("architecture") != subvol.architecture:
                        continue
                yield subvol

        return { "subvolumes": tuple(subvol_generator()) }

class TemplateResource(PoolResource):
    @serialize
    def on_get(self, req, resp):
        return {"templates": map(
            lambda j:{"namespace": j[0], "identifier":j[1], "architectures":j[2]},
            self.pool.template_list(self.subvol_filter))}

class VersionResource(PoolResource):
    @serialize
    def on_get(self, req, resp, name, arch):
        namespace, identifier = name.rsplit(".", 1)
        subset_filter = self.subvol_filter.subset(namespace=namespace,
            identifier=identifier, architecture=arch)
        return { "versions": map(
            lambda v:{"identifier":v, "signed":v.signed},
            sorted(subset_filter.apply(self.pool.subvol_list()), reverse=True, key=lambda j:j.numeric_version)) }

class LegacyStreamingResource(PoolResource):
    def on_get(self, req, resp, name, arch, version):

        parent_version = req.get_param("parent")

        subvol = "@template:%(name)s:%(arch)s:%(version)s" % locals()
        if not self.subvol_filter.match(Subvol(subvol)):
            raise Exception("Not going to happen")

        suggested_filename = "%(name)s:%(arch)s:%(version)s" % locals()
        if parent_version:
            parent_subvol = "@template:%(name)s:%(arch)s:%(parent_version)s" % locals()
            if not self.subvol_filter.match(Subvol(parent_subvol)): raise
            suggested_filename += ":" + parent_version
        else:
            parent_subvol = None
        suggested_filename += ".far"

        resp.set_header("Content-Disposition", "attachment; filename=\"%s\"" % suggested_filename)
        resp.set_header('Content-Type', 'application/btrfs-stream')

        streamer = self.pool.send(subvol, parent_subvol)
        resp.stream = streamer.stdout

        accepted_encodings = req.get_header("Accept-Encoding") or ""
        accepted_encodings = [j.strip() for j in accepted_encodings.lower().split(",")]

        if "gzip" in accepted_encodings:
            for cmd in "/usr/bin/pigz", "/bin/gzip":
                if os.path.exists(cmd):
                    resp.set_header('Content-Encoding', 'gzip')
                    print("Compressing with %s" % cmd)
                    compressor = subprocess.Popen((cmd,"--fast"), bufsize=-1, stdin=streamer.stdout, stdout=subprocess.PIPE)
                    resp.stream = compressor.stdout
                    break
            else:
                print("No gzip compressors found, falling back to no compression")
        else:
            print("Client did not ask for compression")

class StreamResource(PoolResource):
    @parse_subvol
    def on_get(self, req, resp, subvol):
        if not self.subvol_filter.match(subvol):
            resp.body = "Subvolume does not match filter"
            resp.status = falcon.HTTP_403
            return

        format = req.get_param("format") or "btrfs-stream"

        if format == "btrfs-stream":
            parent_slug = req.get_param("parent")
            suggested_filename = "%s.%s-%s-%s" % (subvol.namespace, subvol.identifier, subvol.architecture, subvol.version)

            if parent_slug:
                parent_subvol = Subvol(parent_slug) if parent_slug else None
                if not self.subvol_filter.match(parent_subvol):
                    resp.body = "Subvolume does not match filter"
                    resp.status = falcon.HTTP_403
                    return
                suggested_filename += "-" + parent_subvol.version
            else:
                parent_subvol = None

            suggested_filename += ".far"

            resp.set_header('Content-Type', 'application/btrfs-stream')

            try:
                streamer = self.pool.send(subvol, parent_subvol)
            except SubvolNotFound as e:
                resp.body = "Could not find subvolume %s\n" % str(e)
                resp.status = falcon.HTTP_403
                return
        elif format == "tar":
            suggested_filename = "%s.%s-%s-%s.tar" % (subvol.namespace, subvol.identifier, subvol.architecture, subvol.version)

            try:
                streamer = self.pool.tar(subvol)
            except SubvolNotFound as e:
                resp.body = "Could not find subvolume %s\n" % str(e)
                resp.status = falcon.HTTP_403
                return
        else:
            resp.body = "Requested unknown format"
            resp.status = falcon.HTTP_403
            return

        resp.stream = streamer.stdout

        resp.set_header("Content-Disposition", "attachment; filename=\"%s\"" % suggested_filename)

        accepted_encodings = req.get_header("Accept-Encoding") or ""
        accepted_encodings = [j.strip() for j in accepted_encodings.lower().split(",")]

        if "gzip" in accepted_encodings:
            for cmd in "/usr/bin/pigz", "/bin/gzip":
                if os.path.exists(cmd):
                    resp.set_header('Content-Encoding', 'gzip')
                    print("Compressing with %s" % cmd)
                    compressor = subprocess.Popen((cmd,"--fast"), bufsize=-1, stdin=streamer.stdout, stdout=subprocess.PIPE)
                    resp.stream = compressor.stdout
                    return
            else:
                print("No gzip compressors found, falling back to no compression")
        else:
            print("Client did not ask for compression")

class ManifestResource(PoolResource):
    """
    Generate manifest for a subvolume
    """

    @parse_subvol
    def on_get(self, req, resp, subvol):
        if not self.subvol_filter.match(subvol):
            resp.body = "Subvolume does not match filter"
            resp.status = falcon.HTTP_403
            return
        suggested_filename = "%s.%s-%s-%s.csv" % (subvol.namespace, subvol.identifier, subvol.architecture, subvol.version)
        resp.set_header('Content-Type', 'text/plain')
        resp.stream = self.pool.manifest(subvol)

class KeyringResource(object):
    def __init__(self, filename):
        self.filename = filename

    def on_get(self, req, resp):
        resp.set_header("Content-Type", "application/x-gnupg-keyring")
        resp.set_header("Content-Disposition", "attachment; filename=\"%s.gpg\"" % req.env["SERVER_NAME"].replace(".", "_")) # HTTP_HOST instead? Underscore *should* not be allowed in hostname
        resp.stream = open(self.filename, "rb")

class SignatureResource(PoolResource):
    @parse_subvol
    def on_get(self, req, resp, subvol):
        if not self.subvol_filter.match(subvol):
            resp.body = "Subvolume does not match filter"
            resp.status = falcon.HTTP_403
            return

        try:
            resp.stream = self.pool.signature(subvol)
            suggested_filename = "%s.%s-%s-%s.asc" % (subvol.namespace, subvol.identifier, subvol.architecture, subvol.version)
            resp.set_header('Content-Type', 'text/plain')
            resp.set_header("Cache-Control", "public")
        except FileNotFoundError:
            resp.body = "Signature for %s not found" % subvol
            resp.status = falcon.HTTP_404

class PackageDiff(PoolResource):
    @templatize("packages.html")
    @parse_subvol
    def on_get(self, req, resp, subvol):
        print(subvol.domain)
        if not self.subvol_filter.match(subvol):
            resp.body = "Subvolume does not match filter"
            resp.status = falcon.HTTP_403
            return

        parent_subvol = req.get_param("parent")

        # TODO: Add heuristics to determine package management system,
        #       at least don't die with RPM systems

        def dpkg_list(root):
            """
            Return dict of package names and versions corresponding to a
            Debian/Ubuntu etc root filesystem
            """
            package_name = None
            package_version = None
            versions = {}

            for line in open(os.path.join(root, "var/lib/dpkg/status")):
                line = line[:-1]
                if not line:
                    assert package_name, "No package name specified!"
                    assert package_version, "No package version specified!"
                    versions[package_name] = package_version
                    package_name = None
                    package_version = None
                    continue

                if ": " not in line:
                    continue

                key, value = line.split(": ", 1)

                if key == "Package":
                    package_name = value
                    continue
                if key == "Version":
                    package_version = value
                    continue
            return versions

        new = dpkg_list("/var/lib/butterknife/pool/%s" % subvol)

        if not parent_subvol:
            packages_diff = False
            packages_intact = sorted(new.items())
        else:
            packages_diff = True
            if not self.subvol_filter.match(Subvol(parent_subvol)):
                resp.body = "Parent subvolume does not match filter"
                resp.status = falcon.HTTP_403
                return

            old = dpkg_list("/var/lib/butterknife/pool/%s" % parent_subvol)

            packages_added = []
            packages_removed = []
            packages_updated = []
            packages_intact = []

            for key in sorted(set(new) & set(old)):
                old_version = old[key]
                new_version = new[key]
                if old_version != new_version:
                    packages_updated.append((key, old_version, new_version))
                else:
                    packages_intact.append((key, old_version))

            for key in sorted(set(new) - set(old)):
                packages_added.append((key, new[key]))

            for key in sorted(set(old) - set(new)):
                packages_removed.append((key, old[key]))
        return locals()


"""
@Author: Swapnil Bhoyar
@Date: 2021-06-30 19:00:00
@Last Modified By: Swapnil Bhoyar
@Last Modified Date: 2021-07-01 17:15:00
@Title: Write a Program to implement addressbook.
"""
import logging
import json
from json import JSONEncoder

class LoggerInfo:
    logger = logging.Logger(__name__)
    formatter = logging.Formatter('%(levelname)s:%(name)s:%(message)s')

    file_handler = logging.FileHandler('AddressBook.log')
    logger.addHandler(file_handler)

    logging.basicConfig(filename='addressBookErrors.log',  format='%(asctime)s %(levelname)s %(name)s %(message)s')
    loggerError = logging.getLogger(__name__)

class Contacts:
    def __init__(self, contactData):
        self.firstName = contactData["firstName"]
        self.lastName = contactData["lastName"]
        self.address = contactData["address"]
        self.city = contactData["city"]
        self.state = contactData["state"]
        self.zip = contactData["zip"]
        self.phoneNumber = contactData["phoneNumber"]
        self.email = contactData["email"]

        LoggerInfo.logger.info('Created Contact: {} - {} - {} - {} - {} - {} - {} - {}'.format(self.firstName, self.lastName, self.address, self.city, self.state, self.zip, self.phoneNumber,self.email))

        def __str__(self):
            return "first name = " + self.firstName + \
                " last name = " + self.lastName + \
                " address = " + self.address + \
                " city = " + self.state + \
                " state = " + self.state + \
                " zip = " + self.zip + \
                " phoneNumber = " + self.phoneNumber + \
                " email = " + self.email

class ContactEncoder(JSONEncoder):

    def default(self, object):
        if isinstance(object, Contacts):

            return object.__dict__

        else:

            # call base class implementation which takes care of

            # raising exceptions for unsupported types

            return json.JSONEncoder.default(self, object)

class AddressBook:
    addressBookData = {}
    def addContact(self, addressBookName, contactList):
        """
        Desciption:
            this function add contact
        Parameter:
            addressBookName: string
            contactList: list
        """
        try:

            contactData = {
                "firstName": input("First name:"),
                "lastName": input("last name:"),
                "address": input("address:"),
                "city":input("city:"),
                "state": input("state:"),
                "zip": input("zip:"),
                "phoneNumber": input("phoneNumber:"),
                "email": input("email:")
            }

            contact = Contacts(contactData)
            contactList.append(contact)
            self.addressBookData = {addressBookName: contactList}

            # Serializing json
            json_string = ContactEncoder().encode(contact)

            with open("contactFile.json", "w") as outfile:
                outfile.write(json_string)

        except Exception as e:
            LoggerInfo.loggerError.error(e)

        finally:
            outfile.close()

    def updateContact(self,addressBookName, contactList):
        """
        Desciption:
            this function update contact
        Parameter:
            contactList: list
        """
        first_name = input("Enter first name to edit:")
        for contact in contactList:
            if contact.firstName == first_name:

                with open('contactFile.json') as data_file:
                    data = json.load(data_file)

                # Iterate through the objects in the JSON

                for element in data:
                    if 'fiestName' in element == first_name:
                        del element

                with open('contactFile.json', 'w') as data_file:
                    data = json.dump(data, data_file)

                contactData = {
                "firstName": input("First name:"),
                "lastName": input("last name:"),
                "address": input("address:"),
                "city":input("city:"),
                "state": input("state:"),
                "zip": input("zip:"),
                "phoneNumber": input("phoneNumber:"),
                "email": input("email:")
            }

            contact = Contacts(contactData)
            contactList.append(contact)
            self.addressBookData = {addressBookName: contactList}

            # Serializing json
            json_string = ContactEncoder().encode(contact)

            with open("contactFile.json", "w") as outfile:
                outfile.write(json_string)

        else:
            print("contact does not exist")

    def removeContact(self, contactList):
        """
        Desciption:
            this function delete contact
        Parameter:
            contactList: list
        """
        try:
            first_name = input("Enter name of contact to remove:")
            index = 0
            for contact in contactList:
                if contact.firstName == first_name:
                    del contactList[index]
                    break
                index += 1

                with open('contactFile.json') as data_file:
                    data = json.load(data_file)

                # Iterate through the objects in the JSON

                for element in data:
                    if 'fiestName' in element == first_name:
                        del element

                with open('contactFile.json', 'w') as data_file:
                    data = json.dump(data, data_file)
        except Exception as e:
            LoggerInfo.loggerError.error(e)

    def contactDataOperations(self, addressBookName, contactList):
        """
        Desciption:
            this function perform contact operations
        Parameter:
            addressBookName: string
            contactList: list
        """
        try:
            status = True
            while status:
                userChoice = int(input("1.ADD CONTACT\n2.UPDATE CONTACT\n3.REMOVE CONTACT\n4.PRINT\n5.EXIT\n"))
                if userChoice == 1:
                    self.addContact(addressBookName, contactList)
                elif userChoice == 2:
                    self.updateContact(contactList)
                elif userChoice == 3:
                    self.removeContact(contactList)
                elif userChoice == 4:
                    # for contact in contactList:
                    #     print(contact)
                    with open('contactFile.json') as data_file:
                        data = json.load(data_file)

                    # Iterate through the objects in the JSON

                    for element in data.values():
                        print(element)
                elif userChoice == 5:
                    status = False
        except Exception as e:
            LoggerInfo.loggerError.error(e)

    def getNewAddressBook(self):
        """
        Desciption:
            this function create addressbook
        """
        contactList = []
        try:
            addressBookName = input("Enter addressbook name:")
            self.addContact(addressBookName, contactList)
            self.contactDataOperations(addressBookName, self.addressBookData[addressBookName])
        except Exception as e:
            LoggerInfo.loggerError.error(e)

    def createAddressBook(self):
        """
        Desciption:
            this function add addressbook
        """
        status = True
        try:
            while status:
                userChoice = int(input("\n1.NEW ADDRESS BOOK\n2. SELECT ADDRESS BOOK\n3. EXIT\n"))
                if userChoice == 1:
                    self.getNewAddressBook()
                elif userChoice == 2:
                    address_book_name = input("Enter addressbook name to access:")
                    for addressbook in self.addressBookData:
                        if addressbook == address_book_name:
                            self.contactDataOperations(addressbook, self.addressBookData[addressbook])
                    else:
                        print("addressbook does not exist")
                else:
                    status = False
        except Exception as e:
            LoggerInfo.loggerError.error(e)

addressBookObj = AddressBook()
addressBookObj.createAddressBook()


from collections import deque
from aiomysql import create_pool
from aiopyql.utilities import flatten, no_blanks, inner, TableColumn
from aiopyql.exceptions import InvalidColumnType
import json, time

row_return_type = tuple

TRANSLATION = {
    'int': int,
    'double': float,
    'integer': int,
    'text': str,
    'real': float,
    'boolean': bool,
    'blob': bytes,
    'varchar': str,
}
def get_table_schema(table):
    constraints = ''
    cols = '('
    for col_name,col in table.columns.items():
        for k,v in TRANSLATION.items():
            if col.type == v:
                if len(cols) > 1:
                    cols = f'{cols}, '
                if col_name == table.prim_key and (k=='text' or k=='blob'):
                    cols = f'{cols}{col.name} VARCHAR(36)'
                else:
                    cols = f'{cols}{col.name} {k.upper()}'
                if col_name == table.prim_key:
                    cols = f'{cols} PRIMARY KEY'
                    if col.mods is not None and 'primary key' in col.mods.lower():
                        cols = f"{cols} {''.join(col.mods.upper().split('PRIMARY KEY'))}"
                    else:
                        cols = f"{cols} {col.mods.upper()}"
                else:
                    if col.mods is not None:
                        cols = f'{cols} {col.mods}'
                break
    if not table.foreign_keys == None:
        for local_key, foreign_key in table.foreign_keys.items():
            comma = ', ' if len(constraints) > 0 else ''
            constraints = f"{constraints}{comma}FOREIGN KEY({local_key}) REFERENCES {foreign_key['table']}({foreign_key['ref']}) {foreign_key['mods']}"
    comma = ', ' if len(constraints) > 0 else ''
    schema = f"CREATE TABLE {table.name} {cols}{comma}{constraints})"
    return schema

def get_db_manager():
    """
    returns async generator which manages context
    of the async db connection
    """
    async def mysql_connect(*args, **kwds):
        pool = await create_pool(*args, **kwds)
        try:
            async with pool.acquire() as conn:
                yield conn
        except Exception as e:
            pass
        pool.close()
        await pool.wait_closed()
    return mysql_connect

def get_cursor_manager(database):
    """
    returns async generator which manages context of cursor
    or passes db connection, as well as processes db commit
    for changes
    """
    async def mysql_cursor(commit=False):
        async for db in database.connect(**database.connect_config):
            async with db.cursor() as c:
                try:
                    yield (c, db)
                except Exception as e:
                    database.log.exception(f"error yielding cursor {repr(e)}")
            if commit:
                await db.commit()
        return
    return mysql_cursor
def show_tables(database):
    pass
async def load_tables(db):
    tables_in_db_coro = await db.get("show tables")
    def describe_table_to_col(column):
        config = []
        for i in ' '.join(column.split(',')).split(' '):
            if not i == '' and not i == '\n':
                config.append(i.rstrip())
        column = config
        field = inner(column[0], '`','`')
        typ = None
        for k, v in TRANSLATION.items():
            if k in column[1]:
                typ = v
                break
        if typ == None:
            raise InvalidColumnType(column[1], f"invalid type provided for column, supported types {list(TRANSLATION.keys())}")
        """
        Null = 'NOT NULL ' if column[2] == 'NO' else ''
        Key = 'PRIMARY KEY ' if column[3] == 'PRI' else ''
        Default = '' # TOODOO - check if this needs implementing
        """
        extra = ' '.join(column[2:])
        return TableColumn(field, typ, extra)
    for table, in tables_in_db_coro:
        cols_in_table = []
        table_schemas = await db.get(f'show create table {table}')
        for _, schema in table_schemas:
            schema = flatten(schema.split(f'CREATE TABLE `{table}`')[1])
            col_config = inner(schema).split(', ')
            cols_in_table = []
            foreign_keys = None
            for cfg in col_config:
                if not 'FOREIGN KEY' in cfg:
                    if not 'PRIMARY KEY' in cfg:
                        if not 'KEY' in cfg:
                            cols_in_table.append(describe_table_to_col(cfg))
                    else:
                        primary_key = inner(inner(cfg.split('PRIMARY KEY')[1]), '`', '`')
                else:
                    if foreign_keys == None:
                        foreign_keys = {}
                    local_key, ref = cfg.split('FOREIGN KEY')[1].split('REFERENCES')
                    local_key = inner(inner(local_key), '`', '`')
                    parent_table, mods = ref.split(')')
                    parent_table, parent_key = parent_table.split('(')
                    foreign_keys[no_blanks(local_key)] = {
                        'table': no_blanks(inner(parent_table, '`', '`')),
                        'ref': no_blanks(inner(parent_key, '`', '`')),
                        'mods': mods.rstrip()
                            }
        table = inner(table, '`', '`')
        await db.create_table(table, cols_in_table, primary_key, foreign_keys=foreign_keys, existing=True)
def validate_where_input(db, tables, where):
    for table in tables:
        for col_name, col in table.columns.items():
            if not col_name in where:
                continue
            if not col.type == bool:
                #JSON handling
                if col.type == str and type(where[col_name]) == dict:
                    where[col_name] = f"'{col.type(json.dumps(where[col_name]))}'"
                    continue
                where[col_name] = col.type(where[col_name]) if not where[col_name] in [None, 'NULL'] else 'NULL'
                continue
            # Bool column Type
            try:
                where[col_name] = col.type(int(where[col_name])) if table.database.type == 'mysql' else int(col.type(int(where[col_name])))
            except Exception as e:
                #Bool Input is string
                if 'true' in where[col_name].lower():
                    where[col_name] = True if table.database.type == 'mysql' else 1
                elif 'false' in where[col_name].lower():
                    where[col_name] = False if table.database.type == 'mysql' else 0
                else:
                    db.log.error(f"Unsupported value {where[col_name]} provide for column type {col.type}")
                    del(where[col_name])
                    continue
    return where
async def process_query_no_commit(db, conn, query_id, query):
    results = []
    db.log.debug(f"{db.db_name} - execute: {query}")
    await conn[0].execute(query)
    result = await conn[0].fetchall()
    for row in result:
        results.append(row)
    return result
def process_query_commit(db, conn, conn_id, query_id, query):
    db.querries_to_commit[conn_id].append(
        (query_id, query, conn[0].execute(query))
    )

async def submit_commit_pool(db, conn, conn_id):
    if len(db.querries_to_commit[conn_id]) > 0:
        db.log.debug(f"queue empty, commiting: {db.querries_to_commit[conn_id]}")
        await db.commit_querries(
            conn[1],
            db.querries_to_commit[conn_id]
        )
        db.querries_to_commit[conn_id] = deque()

async def migrate_table(db, new_table):
    log = db.log

    def get_dependent_tables(table_name):
        dependent_tables = []
        for table in db.tables:
            if db.tables[table].foreign_keys:
                for f_key, f_config in db.tables[table].foreign_keys.items():
                    log.debug(f"{table} get_dependent_tables: fkey_config: {f_config}")
                    if table_name == f_config['table']:
                        dependent_tables.append(table)
        log.debug(f"## dependent_tables: {dependent_tables}")
        for table in dependent_tables:
            dependent_tables += get_dependent_tables(table)
        return dependent_tables
    dependent_tables = get_dependent_tables(new_table.name)
    log.debug(f"dependent_tables: {dependent_tables}")
    tables_to_migrate = [ new_table.name ] + dependent_tables

    table_copies = {}

    # create copies of table & dependent tables
    for table in tables_to_migrate:
        table_copies[table] = await db.tables[table].select('*')

    log.warning(f"migrate table starting on tables {tables_to_migrate} due to '{new_table.name}' schema change")

    backup_name = f"{db.db_name}_backup_{time.time()}"
    log.warning(f"creating backup {backup_name} before migration")

    with open(backup_name, 'w') as backup:
        backup.write(
            json.dumps(table_copies)
        )

    new_table_cols = [col for col in new_table.columns]

    await db.run(
        f'ALTER TABLE {new_table.name} RENAME TO {new_table.name}_old'
    )

    # create new table
    await new_table.create_schema()

    db.tables[new_table.name] = new_table

    try:
        tables_to_migrate.reverse()
        for table in tables_to_migrate:
            if not table == new_table.name:
                await db.run(f'drop table {table}')
                await db.tables[table].create_schema()
        tables_to_migrate.reverse()
        for table in tables_to_migrate:
            for row in table_copies[table]:
                if table == new_table.name:
                    migrated_row = {k: v for k,v in row.items() if k in new_table_cols}
                    await db.tables[table].insert(**migrated_row)
                else:
                    await db.tables[table].insert(**row)

        await db.run(
            f'DROP TABLE {new_table.name}_old'
        )
    except Exception as e:
        log.exception(f"error migrating table {new_table.name} - {repr(e)}")
        raise e


import matplotlib.pyplot as plt
import heartpy as hp
import numpy as np

from scipy.signal import resample

"""
Class: HeartRateHelper

Takes 1D data and returns appropriate data.

"""
class HeartRateHelper:
	def __init__(self, framerate, filter=True, resample=-1, show=False, save_path=''):
		self.show = show
		self.filter = filter
		self.framerate = framerate
		self.resample = resample

		# if save_path is empty, do not save
		self.save_path = save_path

		# saves the last calculated m, wd
		self.m = None
		self.wd = None

	def save_plot(self, data, x_label='', y_label=''):
		x = list(range(0, len(data)))
		plt.close('all')
		plt.figure(figsize=(32, 6))
		plt.plot(x, data, 'r-')
		plt.title(self.save_path)
		plt.xlabel(x_label)
		plt.ylabel(y_label)
		plt.savefig(self.save_path)
		plt.close()

	def get_heartrate_and_breathing(self, data):
		framerate = self.framerate
		if self.resample != -1:
			data = resample(data, (len(data)//self.framerate)*self.resample)
			framerate = self.resample

		if self.filter:
			data = hp.filter_signal(data, [0.7, 3.5], sample_rate=framerate,
							order=3, filtertype='bandpass')
			data = hp.scale_data(data)

		wd, m = hp.process(data, framerate, high_precision = True, clean_rr = True)

		self.m = m
		self.wd = wd
		hr = m["bpm"]
		rr = m["breathingrate"]

		if self.show:
			hp.plotter(wd, m)

		if self.save_path != '':
			save_plot(data, x_label="Time", y_label="BVP Signal")

		return hr, rr * 60


import boto3

def create_sns_subscription(email):

    sns = boto3.client('sns')
    response = sns.subscribe(
        TopicArn='arn:aws:sns:us-east-1:89898989898:task-memo-topic',
        Protocol='email',
        Endpoint=email
    )
    return response

def send_email(email, subject, body):

    sns = boto3.client('sns')
    response = sns.publish(
        TopicArn='arn:aws:sns:us-east-1:89898989898:task-memo-topic',
        Message=body,
        Subject=subject,
        Protocol='email',
        Endpoint=email
    )
    return response


import requests
from bs4 import BeautifulSoup

class WebScraper:
    def __init__(self):
        self.data = list()
        URL = 'https://www.esrl.noaa.gov/gmd/aggi/aggi.html'  # The url to get info
        page = requests.get(URL)
        soup = BeautifulSoup(page.content, 'html.parser')
        table = soup.findAll('table')[1]
        table_rows = table.find_all("tr")
        for tr in table_rows[4:]:
            td = tr.find_all('td')
            row = [i.text for i in td]
            data_tuple = (int(row[0]), row[1],
                          row[2], row[3], row[4], row[5], row[6])
            self.data.append(data_tuple)


from source.checker import checker
from scipy import sqrt

from warnings import warn

## linearized bounds
def lbound(vp,klval):
    """
    linearized bound that approximates the GO divergence when
    the value of the KL divergence is small.

    Arguments::
    klval: the value of the KL divergence
    vp: the corresponding variance of the P distribution
    """

    if klval > 1.0:
        warn("KL value is too large, KL={}.".format(klval))
        warn("The approximation may not be accurate.")

    return sqrt(2*vp*klval)

def lbound_approx(vq, klval):
    """
    An approximation to the linearized bound
    of P by using information from the Q measure.

    Arguments::
    klval: the value of the KL divergence
    vq : the variance of Q
    """
    return sqrt(vq*klval*2)+1/(2*sqrt(vq))*(sqrt(vq+klval*vq*2)*sqrt(2*klval))

## Variants that depend on bounds of the random variable or
## assumptions on the tail behavior (sub-gaussianity).

def BerKontorovich(klval,a,b,mu):
    """
    Berend-Kontorovich exponential bound.

    This is a sharpened sub-gaussian that improves
    on Hoeffding by swapping out the 1/8 part for an
    improved constant.

    Arguments::
    klval: value of KL
    a,b: bounds of the un-centralized random variable
    mu: mean value of the un-centralized random variable

    Example::
    >>> BerKontorovich(0.,-1,1,0)
    (-0.0, 0.0)
    """

    if a>b:
        raise ValueError("a>b")

    d = b-a
    p = (mu-a)/d

    # compute Berend-Kontorovich constant
    if p==0:
        cbk=0
    elif p<0.5:
        cbk = (1-2.0*p)/(4.0*log((1-p)/p))
    else:
        cbk = p*(1-p)/2.0

    upper = 2*sqrt(cbk)*d*sqrt(klval)
    lower = 0 # this bound only works for c>0
    checker(lower, upper)
    return lower, upper

### Hoeffding

def hExp(klval, a,b, opt_tol=1e-5):
    '''Hoeffding exponential bound

    Arguments::
    klval: value of KL
    a,b : upper and lower bound for the X random variable.

    Example ::
    >>> hExp(0, -1,1)
    (-0.0, 0.0)
    >>> hExp(1,0,0)
    (-0.0, 0.0)
    '''

    if a>b:
        raise ValueError("a and b are the bounds of a centralized random variable.")

    # This bound has an explicit solution
    upper = sqrt(2)/2.0*(b-a)*sqrt(klval)
    lower = -upper

    checker(lower,upper)

    return lower, upper

def hExpVar(klval, variance_proxy):
    '''Hoeffding exponential bound with variance proxy.
    This is to be used with bounded random variables.

    Arguments::
    klval: value of KL
    variance_proxy: Either the true variance or an upper bound.

    Example ::
    >>> hExpVar(0,1)
    (-0.0, 0.0)
    >>> hExpVar(0,2)
    (-0.0, 0.0)
    '''

    if variance_proxy<0:
        raise ValueError("variance proxy has to be non-negative.")

    # This bound has an explicit solution
    upper = sqrt(2)*sqrt(variance_proxy*klval)
    lower = -upper

    checker(lower,upper)

    return lower, upper


#!/bin/python
import sys
import notify2
import subprocess
from time import sleep

def notification(message: str):
    """
    Display notification to the desktop
    Task:
        1. show() -> it will generate a complete new pop
        2. update() -> it will update the payload part of same notification pop-up, not issuing any new one.
    Usage : python <filename.py> typeObj:str value:int objective:str
    typeObj: RAM/SWAP/NORMAL
    value: current usage of RAM or SWAP (for NORMAL, the value = 0)
    objective: show/update
    """
    # initialize the notification
    notify2.init("notifywhenLOAD")
    notifyObj = notify2.Notification("Emergency Alert!", message)
    notifyObj.set_timeout(12000)
    return notifyObj

def main():
    a = notification(f"{sys.argv[1]} exceeds {sys.argv[2]}")
    if sys.argv[1] in ["RAM", "SWAP"] and sys.argv[3] == "update":
        a.update(f"{sys.argv[1]} Alert!! Warning for death")
        # a.update('river')
        a.set_urgency(2)
        a.show()
    elif sys.argv[1] in ["RAM", "SWAP"] and sys.argv[3] == "show":
        a.set_timeout(10000)
        a.set_urgency(1)
        a.show()
    elif sys.argv[1] == "NORMAL":
        a.update("ChiLLax!!! Nothing to worry about")
        a.set_urgency(0)
        a.show()

main()


# %%
import os
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from norm import read_norm_data, norm

import argparse

#%%
parser = argparse.ArgumentParser()
parser.add_argument("-p", "--path", type=str, default="output/default")
parser.add_argument("-g", "--gen", type=int, default=-1)
parser.add_argument("-t", "--target", type=str, default=None)
parser.add_argument("-c", "--condition", type=str, default=None)
parser.add_argument("--collect", action="store_true")
args = parser.parse_args()

# %%
path = args.path

if not os.path.exists(path):
    print("Error: path does not exist")
    exit()

if args.collect:
    os.system(f"python collect_data.py {path} -w {os.cpu_count()} -f fits")

norm_df = read_norm_data("data/target_fitness_fn_ranges.csv", "")
conds_dir = os.path.join(args.path, "conditions")

# population_size = 70

os.makedirs(os.path.join(args.path, "plots"), exist_ok=True)

# %%
fits_path = os.path.join(conds_dir, "fits.pkl")

if os.path.exists(args.path) and not os.path.exists(fits_path):
    print("Error: data has not been parsed yet.")
    print("Collect data by using the --collect flag")
    exit()

df = pd.read_pickle(fits_path)

if args.gen is not None and args.gen >= 0:
    df = df[df["gen"] == args.gen]

if args.condition is not None:
    df = df[df["condition"] == args.condition]

if args.target is not None:
    df = df[df["target"] == args.target]

norm(df, norm_df)

mean_df = df.groupby(["gen", "condition", "run"])["fitness"].mean().reset_index()

# %%
# Adjust the Steady State condition to match the Without Steady State condition
use_df = mean_df.copy()

if "without-steady-state" in df["condition"].unique():
    population_size = df[(df["condition"] == "without-steady-state") & (df['run'] ==  df['run'].min())]["cell"].unique().shape[0]
    # split conditions to separate dfs
    df_with = use_df[use_df["condition"] == "with-steady-state"]
    df_without = use_df[use_df["condition"] == "without-steady-state"]
    # keep every 70th gen of df_with
    df_with = df_with[df_with["gen"] % population_size == 0].reset_index()
    # rename gens to match df_without
    df_with["gen"] = df_with["gen"] // population_size
    use_df = pd.concat([df_with, df_without])
# %%
ax = sns.lineplot(x="gen", y="fitness", hue="condition", data=use_df)
plt.savefig(os.path.join(args.path, "plots", "avg_fits_over_time.png"))
plt.show()


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

from urllib.parse import urljoin
from bs4 import BeautifulSoup

from utils import req
from utils.tomongo import insert
from core.crawler import CrawlerBase
from utils.common import format_list
from utils.common import set_data_md5

class SpiderBase(CrawlerBase):
    desc = "spider_netlab360"
    auth = "co0ontty"
    thread = 5

    def get_url_list(self):
        result = []
        for page_num in range(1, 3000):
            url = "https://blog.netlab.360.com/page/{}/".format(page_num)
            res = req.get(url)
            if not res:
                continue
            soup = BeautifulSoup(res, "html5lib").select(
                ".post-card-content-link")
            for info in soup:
                infos = {}
                url = urljoin("https://blog.netlab.360.com/", info['href'])
                if url:
                    title = info.select_one('h2').getText()
                    infos['reference'] = url
                    infos['title'] = title
                    infos['website'] = "netlab360"
                    result.append(infos)
                else:
                    return result

    def get_info(self, infos):
        iocs = []
        url = infos['reference']
        title = infos['title']
        res = req.get(url)
        if not res:
            return

        soup = BeautifulSoup(res, 'html5lib')
        lis = soup.select('li')
        for li in lis:
            text = li.getText()
            result_list = text.replace("：", " ").replace(
                ": ", " ").replace("，", " ").split(" ")
            results = format_list(result_list)
            if results != None:
                for ioc in results:
                    ioc['reference'] = url
                    ioc['title'] = title
                    ioc['website'] = "netlab360"
                    iocs.append(ioc)

                ioc_list = set_data_md5(iocs)
                insert(ioc_list)


import fastText
import numpy as np
from gensim.models import KeyedVectors
from nltk.stem import PorterStemmer, LancasterStemmer, SnowballStemmer

PORTER_STEMMER = PorterStemmer()
LANCASTER_STEMMER = LancasterStemmer()
SNOWBALL_STEMMER = SnowballStemmer("english")

WORD_TRANSFORMERS = [
    lambda x: x.lower(),
    lambda x: x.upper(),
    lambda x: x.capitalize(),
    PORTER_STEMMER.stem,
    LANCASTER_STEMMER.stem,
    SNOWBALL_STEMMER.stem,
]

def word_forms(word):
    """
        Yields different forms of word, one by one
    """
    yield word
    yield from (transformer(word) for transformer in WORD_TRANSFORMERS)

def maybe_get_embedding(word, model):
    for form in word_forms(word):
        if form in model:
            return model[form]

    word = word.strip("-'")
    for form in word_forms(word):
        if form in model:
            return model[form]

    return None

def construct_empty(word2index, dim):
    return np.zeros((max(word2index.values()) + 1, dim), dtype=np.float32)

def gensim_to_embedding_matrix(word2index, path):
    """
        path - path to model obtained with gensim.models.KeyedVectors.save
    """
    model = KeyedVectors.load(path)
    embedding_matrix = construct_empty(word2index, model.vector_size)
    unknown_words = []

    for word, i in word2index.items():
        maybe_embedding = maybe_get_embedding(word, model)
        if maybe_embedding is not None:
            embedding_matrix[i] = maybe_embedding
        else:
            unknown_words.append(word)

    return embedding_matrix, unknown_words

def fasttext_to_embedding_matrix(word2index, path):
    """
        path - path to binary model obtained from fasttext util
    """
    model = fastText.load_model(path)
    embedding_matrix = construct_empty(word2index, model.get_dimension())
    for word, index in word2index.items():
        embedding_matrix[index] = model.get_word_vector(word)
    return embedding_matrix

def one_hot_char_embeddings(word2index, char_vectorizer):
    """
        vectorizer - fitted vectorizer
    """

    words = [""] * (max(word2index.values()) + 1)
    for word, i in word2index.items():
        words[i] = word

    return char_vectorizer.transform(words).toarray().astype(np.float32)


# -*- coding: utf-8 -*-
"""
Created on Tue Dec 20 11:07:37 2022

@author: JGarciaP
"""
import streamlit as st
import pandas as pd
import numpy as np
import joblib

model_filename = 'rf_model.pkl'
loaded_model = joblib.load(model_filename)
print("Modelo Cargado")

st.title('Status Diabetes')
st.header("Consulte su glucosa")
st.subheader("Ingrese los datos para su verificación")

with st.form(key='diabetes-pred-form'):

    col1, col2, col3, col4= st.columns(4)
    embarazos = col1.slider(label='Cuantos embarazos ha tenido:', min_value=0, max_value=20)
    glucosa = col2.slider(label='Ingrese valor de glucosa:', min_value=50, max_value=400)
    diastolica = col3.text_input(label='Ingrese su presión:')
    grosor_piel = col4.text_input(label='Ingrese su grosor de piel:')

    col5, col6, col7, col8= st.columns(4)
    insulina= col5.slider(label='Valor de Insulina:', min_value=20, max_value=400)
    BMI = col6.slider(label='Ingrese valor IMC:', min_value=50, max_value=400)
    diabetes_hereditaria= col7.text_input(label='Ingrese su ascendencia:')
    age= col8.text_input(label='Ingrese su edad:')

    submit = st.form_submit_button(label='Analizar')

    calculo = pd.DataFrame({'Pregnancies':embarazos, 'PlasmaGlucose':glucosa, 'DiastolicBloodPressure':diastolica,
                            'TricepsThickness':grosor_piel, 'SerumInsulin':insulina, 'BMI':BMI,
                            'DiabetesPedigree':diabetes_hereditaria,
                            'Age':age},index=[0])
    predicted_diabetes = loaded_model.predict(calculo)[0]
    print(predicted_diabetes)


from __future__ import division

from django.db import models

from pixelpuncher.item.models import ItemType
from pixelpuncher.player.models import GENDER, AvatarLayer, Player

TRIGGER_TYPE = (
    ("ASK", "Ask about",),
    ("TELL", "Tell about",),
    ("ACK", "Acknowledge",),
    ("GRT", "Greeting")
)

RESPONSE_HANDLER = (
    ('RND', 'Random',),
    ('ORD', 'Ordered',),
)

RELATIONSHIP_TYPE = (
    ('RIVL', 'Rival',),
    ('FRND', 'Friend',),
    ('CUST', 'Customer',),
    ('ROMC', 'Romantic',),
)

RELATIONSHIP_LEVEL = (
    ('BS', 'Best',),
    ('GD', 'Good',),
    ('NT', 'Netural',),
    ('BD', 'Bad',),
    ('HR', 'Horrible',),
)

class ResponseHandlers(object):
    Random = 'RND'
    Ordered = 'ORD'

class RelationshipLevels(object):
    BEST = 'BS'
    GOOD = 'GD'
    NETURAL = 'NT'
    BAD = 'BD'
    HORRIBLE = 'HR'

class Triggers(object):
    ASK = 'ask'
    TELL = 'tell'
    HELP = 'help'
    GREET = 'greet'
    ACKNOWLEDGE = 'ack'

class NPCAvatar(models.Model):
    name = models.CharField(max_length=25)
    body_layer = models.ForeignKey(AvatarLayer, null=True, blank=True, related_name="+")
    hair_layer = models.ForeignKey(AvatarLayer, null=True, blank=True, related_name="+")
    face_layer = models.ForeignKey(AvatarLayer, null=True, blank=True, related_name="+")
    shirt_layer = models.ForeignKey(AvatarLayer, null=True, blank=True, related_name="+")

    def __unicode__(self):
        return self.name

class NPC(models.Model):
    name = models.CharField(max_length=25)
    gender = models.CharField(max_length=1, default="M", choices=GENDER)
    level = models.IntegerField(default=1)

    # Used when creating new relationships between NPC and player
    default_relationship_type = models.CharField(max_length=4, choices=RELATIONSHIP_TYPE, default='CUST')

    total_health = models.IntegerField(default=10)
    total_energy = models.IntegerField(default=10)

    power = models.IntegerField(default=1)
    technique = models.IntegerField(default=1)
    endurance = models.IntegerField(default=1)

    avatar = models.ForeignKey(NPCAvatar, null=True, blank=True)

    def __unicode__(self):
        return self.name

class NPCRelationship(models.Model):
    npc = models.ForeignKey(NPC, related_name="+")
    player = models.ForeignKey(Player, related_name="npcs")

    # Type and level determine how npc treats player
    # Score determines how close level is to going up or down.
    score = models.IntegerField(default=0)
    relationship_type = models.CharField(max_length=4, choices=RELATIONSHIP_TYPE)
    relationship_level = models.CharField(max_length=4, choices=RELATIONSHIP_LEVEL, default='NT')

    current_health = models.IntegerField(default=10)
    current_energy = models.IntegerField(default=10)
    pixels = models.IntegerField(default=0)

    avatar = models.ForeignKey(NPCAvatar, null=True, blank=True)

    def __unicode__(self):
        return self.npc.name

class Response(models.Model):
    text = models.TextField()
    health_change = models.IntegerField(default=0)
    energy_change = models.IntegerField(default=0)
    pixels_change = models.IntegerField(default=0)
    xp_change = models.IntegerField(default=0)
    reward_items = models.ManyToManyField(ItemType, related_name="+", blank=True)
    relationship_points = models.IntegerField(default=0)

    priority = models.IntegerField(default=0)  # determines which response to give first
    frequency = models.IntegerField(default=0)  # how often response can be given in minutes
    # Frequency options: timed, no limit, max number (n times)

    level_requirement = models.IntegerField(default=0)  # zero means no requirement
    required_items = models.ManyToManyField(ItemType, related_name="+", blank=True)

    # Used for when an NPC tells player about a location
    location_unlock = models.ForeignKey("location.Location", related_name="+", null=True, blank=True)

    def __unicode__(self):
        return self.text

class ResponseTrigger(models.Model):
    npcs = models.ManyToManyField(NPC, related_name="triggers")
    responses = models.ManyToManyField(Response, related_name="triggers")
    trigger_text = models.CharField(max_length=30)
    trigger_type = models.CharField(max_length=4, choices=TRIGGER_TYPE)
    response_handler = models.CharField(max_length=3, choices=RESPONSE_HANDLER, default='RND')

    def __unicode__(self):
        return self.trigger_text

class ResponseLog(models.Model):
    # Track responses given to player by NPCs
    player = models.ForeignKey(Player, related_name="+")
    response = models.ForeignKey(Response, related_name="+")
    response_trigger = models.ForeignKey(ResponseTrigger, related_name="+")
    response_date = models.DateTimeField()


import os
import pandas as pd
from nltk.sentiment import SentimentIntensityAnalyzer
from textblob import TextBlob

# Define the path to the input CSV file
input_file = 'Full Comments.csv'

# Create a folder for the sentiment analysis results
output_folder = 'Sentiment Analysis'
if not os.path.exists(output_folder):
    os.makedirs(output_folder)

# Read the input CSV file into a pandas DataFrame
df = pd.read_csv(input_file)

# Initialize the sentiment analysis models
textblob_model = TextBlob
vader_model = SentimentIntensityAnalyzer()

# Perform sentiment analysis and store the results in separate DataFrames
positive_comments_textblob = pd.DataFrame(columns=['Username', 'Comment'])
negative_comments_textblob = pd.DataFrame(columns=['Username', 'Comment'])
positive_comments_vader = pd.DataFrame(columns=['Username', 'Comment'])
negative_comments_vader = pd.DataFrame(columns=['Username', 'Comment'])

for index, row in df.iterrows():
    username = row['Username']
    comment = row['Comment']

    # Sentiment analysis using TextBlob
    textblob_sentiment = textblob_model(comment).sentiment.polarity

    # Sentiment analysis using VADER
    vader_sentiment = vader_model.polarity_scores(comment)['compound']

    if textblob_sentiment >= 0:
        # Positive sentiment according to TextBlob
        positive_comments_textblob = pd.concat([positive_comments_textblob,
                                                pd.DataFrame({'Username': [username], 'Comment': [comment]})],
                                               ignore_index=True)
    else:
        # Negative sentiment according to TextBlob
        negative_comments_textblob = pd.concat([negative_comments_textblob,
                                                pd.DataFrame({'Username': [username], 'Comment': [comment]})],
                                               ignore_index=True)

    if vader_sentiment >= 0:
        # Positive sentiment according to VADER
        positive_comments_vader = pd.concat([positive_comments_vader,
                                             pd.DataFrame({'Username': [username], 'Comment': [comment]})],
                                            ignore_index=True)
    else:
        # Negative sentiment according to VADER
        negative_comments_vader = pd.concat([negative_comments_vader,
                                             pd.DataFrame({'Username': [username], 'Comment': [comment]})],
                                            ignore_index=True)

# Save the positive and negative comments for each model in separate CSV files
textblob_output_folder = os.path.join(output_folder, 'TextBlob')
vader_output_folder = os.path.join(output_folder, 'VADER')

if not os.path.exists(textblob_output_folder):
    os.makedirs(textblob_output_folder)

if not os.path.exists(vader_output_folder):
    os.makedirs(vader_output_folder)

positive_comments_textblob.to_csv(os.path.join(
    textblob_output_folder, 'positive.csv'), index=False)
negative_comments_textblob.to_csv(os.path.join(
    textblob_output_folder, 'negative.csv'), index=False)
positive_comments_vader.to_csv(os.path.join(
    vader_output_folder, 'positive.csv'), index=False)
negative_comments_vader.to_csv(os.path.join(
    vader_output_folder, 'negative.csv'), index=False)

print("Sentiment analysis completed. Results are stored in separate folders for each model.")


import sys

from django.apps import apps as django_apps
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.db.utils import OperationalError, ProgrammingError

from .get_sites_module import get_sites_module
from .single_site import SiteDomainRequiredError

class InvalidSiteError(Exception):
    pass

def add_or_update_django_sites(apps=None, sites=None, verbose=None):
    """Removes default site and adds/updates given `sites`, etc.

    Title is stored in SiteProfile.

    kwargs:
        * sites: format
            sites = (
                (<site_id>, <site_name>, <title>),
                ...)
    """
    all_sites = {}
    if verbose:
        sys.stdout.write("  * updating sites.\n")
    apps = apps or django_apps
    site_model_cls = apps.get_model("sites", "Site")
    site_model_cls.objects.filter(name="example.com").delete()
    if not sites:
        all_sites = get_sites_module().all_sites
    elif isinstance(sites, (list, tuple)):
        all_sites = {"default": sites}

    for sites in all_sites.values():
        for single_site in sites:
            if get_sites_module() and single_site.name == "edcs_sites.sites":
                continue
            if verbose:
                sys.stdout.write(f"  * {single_site.name}.\n")
            site_obj = get_or_create_site_obj(single_site, apps)
            get_or_create_site_profile_obj(single_site, site_obj, apps)
    return all_sites

def get_or_create_site_obj(single_site, apps):
    if "multisite" in settings.INSTALLED_APPS and not single_site.domain:
        raise SiteDomainRequiredError(
            f"Domain required when using `multisite`. Got None for `{single_site.name}`"
        )
    site_model_cls = apps.get_model("sites", "Site")
    try:
        site_obj = site_model_cls.objects.get(pk=single_site.site_id)
    except ObjectDoesNotExist:
        site_obj = site_model_cls.objects.create(
            pk=single_site.site_id, name=single_site.name, domain=single_site.domain
        )
    else:
        site_obj.name = single_site.name
        site_obj.domain = single_site.domain
        site_obj.save()
    return site_obj

def get_or_create_site_profile_obj(single_site, site_obj, apps):
    site_profile_model_cls = apps.get_model("edcs_sites", "SiteProfile")
    opts = dict(
        title=single_site.title,
        country=single_site.country,
        country_code=single_site.country_code,
        description=single_site.description or single_site.title,
    )
    try:
        site_profile = site_profile_model_cls.objects.get(site=site_obj)
    except ObjectDoesNotExist:
        site_profile_model_cls.objects.create(site=site_obj, **opts)
    except (OperationalError, ProgrammingError):
        pass
    else:
        for k, v in opts.items():
            setattr(site_profile, k, v)
        site_profile.save()


from __future__ import with_statement

PKG = 'runtime_monitor'

import roslib
roslib.load_manifest(PKG)

import sys
import rospy

from diagnostic_msgs.msg import DiagnosticArray, DiagnosticStatus, KeyValue

import wx
from wx import xrc
from wx import html

import threading, time
import cStringIO
import copy

class TreeItem(object):
  ##\param status DiagnosticsStatus : Diagnostic data of item
  ##\param tree_id wxTreeItemId : Tree ID of item in display
  ##\param stamp ros::Time : Stamp when message was received
  def __init__(self, status, tree_id, stamp = None):
    self.status = status
    self.mark = False
    self.stale = False
    self.tree_id = tree_id
    self.stamp = stamp

class MonitorPanel(wx.Panel):
  def __init__(self, parent, topic="/diagnostics", rxbag=False):
    wx.Panel.__init__(self, parent, wx.ID_ANY)

    self._mutex = threading.Lock()

    xrc_path = roslib.packages.get_pkg_dir(PKG) + '/xrc/runtime_monitor_generated.xrc'

    self._xrc = xrc.XmlResource(xrc_path)
    self._real_panel = self._xrc.LoadPanel(self, 'RuntimeMonitorInnerPanel')
    sizer = wx.BoxSizer(wx.VERTICAL)
    sizer.Add(self._real_panel, 1, wx.EXPAND)
    self.SetSizer(sizer)

    self._tree_control = xrc.XRCCTRL(self._real_panel, "_tree_control")
    self._html_control = xrc.XRCCTRL(self._real_panel, "_html_control")

    image_list = wx.ImageList(16, 16)
    self._error_image_id = image_list.AddIcon(wx.ArtProvider.GetIcon(wx.ART_ERROR, wx.ART_OTHER, wx.Size(16, 16)))
    self._warning_image_id = image_list.AddIcon(wx.ArtProvider.GetIcon(wx.ART_WARNING, wx.ART_OTHER, wx.Size(16, 16)))
    self._ok_image_id = image_list.AddIcon(wx.ArtProvider.GetIcon(wx.ART_TICK_MARK, wx.ART_OTHER, wx.Size(16, 16)))
    self._tree_control.AssignImageList(image_list)
    self._root_id = self._tree_control.AddRoot("Root")
    self._stale_id = self._tree_control.AppendItem(self._root_id, "Stale (0)", self._error_image_id)
    self._errors_id = self._tree_control.AppendItem(self._root_id, "Errors (0)", self._error_image_id)
    self._warnings_id = self._tree_control.AppendItem(self._root_id, "Warnings (0)", self._warning_image_id)
    self._ok_id = self._tree_control.AppendItem(self._root_id, "Ok (0)", self._ok_image_id)

    if rxbag:
      wx.CallAfter(self._set_splitter_position)

    self._tree_control.Bind(wx.EVT_TREE_SEL_CHANGED, self._on_item_selected)
    self._tree_control.Bind(wx.EVT_TREE_KEY_DOWN, self._on_item_key_down)

    self._name_to_item = {}

    self._new_errors_callback = None

    if not rxbag:
      self._subscriber = rospy.Subscriber(topic, DiagnosticArray, self._diagnostics_callback)
      self._timer = wx.Timer(self)
      self.Bind(wx.EVT_TIMER, self._on_timer)
      self._timer.Start(5000)
    else:
      self._subscriber = None

    self._messages = []
    self._used_items = 0

  def _set_splitter_position(self):
    self._splitter_control = xrc.XRCCTRL(self._real_panel, "m_splitter1")
    self._splitter_control.SetSashPosition(350)

  def __del__(self):
    if self._subscriber is not None:
      self._subscriber.unregister()

  def shutdown(self):
    """
    Unregisters diagnostics subscriber for clean shutdown
    """
    if rospy.is_shutdown():
      return

    if self._subscriber is not None:
      self._subscriber.unregister()
      self._subscriber = None

  def change_diagnostic_topic(self, topic):
    """
    Changes diagnostics topic name. Must be of type diagnostic_msgs/DiagnosticArray
    """
    if len(topic) == 0:
      self.reset_monitor()
      return

    if self._subscriber is not None:
      self._subscriber.unregister()
      self._subscriber = rospy.Subscriber(str(topic), DiagnosticArray, self._diagnostics_callback)
    self.reset_monitor()

  def reset_monitor(self):
    """
    Removes all values from monitor display, resets buffers
    """
    self._name_to_item = {} # Reset all stale topics
    self._messages = []
    self._clear_tree()

  def _clear_tree(self):
    self._tree_control.DeleteChildren(self._stale_id)
    self._tree_control.DeleteChildren(self._errors_id)
    self._tree_control.DeleteChildren(self._warnings_id)
    self._tree_control.DeleteChildren(self._ok_id)
    self._update_root_labels()

  def add_rxbag_msg(self, msg, stamp):
    """
    Add message from rxbag player
    """
    self._messages.append(msg)

    wx.CallAfter(self.new_message, stamp)

    # Clear stale messages
    wx.CallAfter(self._clear_old_rxbag_msgs, stamp)

  def _delete_item(self, item):
    self._tree_control.Delete(item.tree_id)
    del self._name_to_item[item.status.name]

  def _clear_old_rxbag_msgs(self, now_stamp):
    to_delete = []
    for name, item in self._name_to_item.iteritems():
      if (item != None):
        # No future messages
        if item.stamp > now_stamp:
          to_delete.append(item)
          continue

        if (now_stamp - item.stamp).to_sec() > 15.0:
          to_delete.append(item)
          continue

    for item in to_delete:
      self._delete_item(item)

    self._update_root_labels()

  def _diagnostics_callback(self, message):
    with self._mutex:
      self._messages.append(message)

    wx.CallAfter(self.new_message, rospy.get_rostime())

  def new_message(self, stamp = None):
    with self._mutex:
      had_errors = False

      for message in self._messages:
        for status in message.status:
          was_selected = False
          had_item = False
          if (self._name_to_item.has_key(status.name)):
            item = self._name_to_item[status.name]
            had_item = True
            if (self._tree_control.GetSelection() == item.tree_id):
              was_selected = True
            if (item.status.level == 2 and status.level != 2):
              had_errors = True

            self._update_item(item, status, was_selected, stamp)
          else:
            self._create_item(status, was_selected, True, stamp)
            if (status.level == 2):
              had_errors = True

      self._messages = []

    if (had_errors and self._new_errors_callback != None):
      self._new_errors_callback()

    self.Refresh()

  def _update_item(self, item, status, was_selected, stamp):
    change_parent = False
    if (item.status.level != status.level):
      change_parent = True

    if (change_parent):
      self._tree_control.Delete(item.tree_id)

      if (status.level == 0):
        parent_id = self._ok_id
      elif (status.level == 1):
        parent_id = self._warnings_id
      elif (status.level == -1):
        parent_id = self._stale_id
      else:
        parent_id = self._errors_id

      id = self._tree_control.AppendItem(parent_id, status.name + ": " + status.message)
      item.tree_id = id
      item.stamp = stamp
      self._tree_control.SetPyData(id, item)

      if (status.level > 1 or status.level == -1):
        self._tree_control.Expand(parent_id)

      self._tree_control.SortChildren(parent_id)

      if (was_selected):
        self._tree_control.SelectItem(item.tree_id)

    else:
      self._tree_control.SetItemText(item.tree_id, status.name + ": " + status.message)

    item.status = status

    if (was_selected):
      self._fillout_info(item.tree_id)

    item.mark = True

  def _create_item(self, status, select, expand_if_error, stamp):
    if (status.level == 0):
      parent_id = self._ok_id
    elif (status.level == 1):
      parent_id = self._warnings_id
    elif (status.level == -1):
      parent_id = self._stale_id
    else:
      parent_id = self._errors_id

    id = self._tree_control.AppendItem(parent_id, status.name + ": " + status.message)
    item = TreeItem(status, id, stamp)
    self._tree_control.SetPyData(id, item)

    self._name_to_item[status.name] = item

    self._tree_control.SortChildren(parent_id)

    if (select):
      self._tree_control.SelectItem(id)

    if (expand_if_error and (status.level > 1 or status.level == -1)):
      self._tree_control.Expand(parent_id)

    self._update_root_labels()

    item.mark = True

    return item

  def _fillout_info(self, id):
    item = self._tree_control.GetPyData(id)
    if (item == None):
      return

    status = item.status

    self._html_control.Freeze()
    s = cStringIO.StringIO()

    s.write("")
    s.write("Component: %s
\n" % (status.name))
    s.write("Message: %s
\n" % (status.message))
    s.write("Hardware ID: %s

\n\n" % (status.hardware_id))

    s.write('
')
    for value in status.values:
      value.value = value.value.replace("\n", "
")
      s.write("
%s	 %s
\n" % (value.key, value.value))

    s.write("
")

    (x, y) = self._html_control.GetViewStart()
    self._html_control.SetPage(s.getvalue())
    self._html_control.Scroll(x, y)

    self._html_control.Thaw()

  def _on_item_selected(self, event):
    self._fillout_info(event.GetItem())

  def _on_item_key_down(self, event):
    id = self._tree_control.GetSelection()
    if (id == None):
      event.Skip()
      return

    key = event.GetKeyCode()

    if (key == wx.WXK_DELETE):
      item = self._tree_control.GetPyData(id)
      if (item != None):
          self._tree_control.Delete(id)
          del self._name_to_item[item.status.name]
    else:
      event.Skip()

    self._update_root_labels()
    self.Refresh()

  def _on_timer(self, event):
    for name, item in self._name_to_item.iteritems():
      id = item.tree_id
      if (item != None):
        if (not item.mark):
          was_selected = False
          if (self._tree_control.GetSelection() == id):
            was_selected = True

          new_status = copy.deepcopy(item.status)
          new_status.level = -1
          self._update_item(item, new_status, was_selected, item.stamp)

        item.mark = False

    self._update_root_labels()
    self.Refresh()

  def set_new_errors_callback(self, callback):
    self._new_errors_callback = callback

  def get_num_errors(self):
    return self._tree_control.GetChildrenCount(self._errors_id, False) + self._tree_control.GetChildrenCount(self._stale_id, False)

  def get_num_warnings(self):
    return self._tree_control.GetChildrenCount(self._warnings_id, False)

  def get_num_ok(self):
    return self._tree_control.GetChildrenCount(self._ok_id, False)

  def _update_root_labels(self):
    self._tree_control.SetItemText(self._ok_id, "Ok (%s)" % (self._tree_control.GetChildrenCount(self._ok_id, False)))
    self._tree_control.SetItemText(self._warnings_id, "Warnings (%s)" % (self._tree_control.GetChildrenCount(self._warnings_id, False)))
    self._tree_control.SetItemText(self._errors_id, "Errors (%s)" % (self._tree_control.GetChildrenCount(self._errors_id, False)))
    self._tree_control.SetItemText(self._stale_id, "Stale (%s)" % (self._tree_control.GetChildrenCount(self._stale_id, False)))


# Python OOP
from calendar import weekday
from hashlib import new
import datetime
import time

from numpy import ix_
import terminal_formatting as tf
class Employee:         # Class
    numb = 0            # Class variable
    raise_amount = 1.04 # Class variable

    def __init__(self,first,last,pay):                 # self represents the class instance
        self.first = first                             # Assigns function variable to a local variable
        self.last = last                               # Last name variable
        self.email = first + '.' + last + '@email.com' # Creates an email based on the first and last name given
        self.pay = pay                                 # Pay variable

        Employee.numb += 1 # Increases the number variable for each instance of the class

    def fullname(self):                             # Method that returns the first and last name of the Employee instance
        return '{} {}'.format(self.first,self.last) # Returns the full name of the Employee instance

    def apply_raise(self):                           # Method that applies the raise amount to the class instance
        self.pay = int(self.pay * self.raise_amount) # Calculates the pay after the raise is applies for the instance

    @classmethod                   # Alternative constructor
    def set_raise_amt(cls,amount): # cls == class variable name == class
        cls.raise_amount = amount  # Sets the raise amount to the instance amount

    @classmethod                              # Alternative contructor that takes a given string and converts it into a class instance
    def from_string(cls,emp_str):             # inputs instance variable and the given employee string
        first, last, pay = emp_str.split('-') # Parses the string separated by hyphens
        return cls(first,last,pay)            # Returns the parsed variables

    @staticmethod                                    # Does not operate on the instance or the class
    def is_workday(day):                             # Defines is_workday function
        if day.weekday() == 5 or day.weekday() == 6: # 5 == Saturday, 6 == Sunday
            return False                             # False if it is a weekend
        return True                                  # True if it is a weekday

# Inheritance -- Inherits the functionality from the Employee class
class Developer(Employee):                       # Developer class that inherits Employee attributes
    raise_amount = 1.10                          # Developer raise_amount
    def __init__(self,first,last,pay,prog_lang): # Add programming language
        super().__init__(first,last,pay)         # Calls the parent (Employee) __init__ method
        self.prog_lang = prog_lang               # Sets the instance programming language

# Inheritance -- Inherits the functionality from the Employee class
class Manager(Employee):                              # Subclass of Employee
    def __init__(self,first,last,pay,employees=None): # Adds number of employees to a manager
        super().__init__(first,last,pay)              # Calls the parent (Employee) __init__ method
        if employees is None:                         # Redefines employees=None to avoid having an object in the parameters
            self.employees = []                       # Sets employees to an empty list
        else:
            self.employees = employees # Sets employees to the class instance employees

    def add_emp(self,emp):             # Defines the add employee method to the Manager class
        if emp not in self.employees:  # Adds an employee to the class imstance
            self.employees.append(emp) # Appends the emp to the employees list

    def remove_emp(self,emp):          # Defines the remove employee method to the manager class
        if emp in self.employees:      # Revoves the employee from the Manager class instance
            self.employees.remove(emp) # Removes the emp from the employee list

    def print_emps(self):                               # Method to print the employees tied to the manager
        print('\nManager --> ',self.fullname())         # Print manager name
        for emp in self.employees:                      # For each emp in the employees list
            print('\n    Employee --> ',emp.fullname()) # Print the emp's full name from the Employee class

# print(help(Employee))  # Prints information regarding the Employee class
# print(help(Developer)) # Prints information regarding the Developer class
# print(help(Manager))   # Prints information regarding the Manager class

emp_1 = Employee('Dalton','Kipp',50000)             # Employee class instance
emp_2 = Employee('Test','Employee',100000)          # Employee class instance 2
dev_1 = Developer('Bob', 'Jackson', 60000,'Python') # Developer class instance
dev_2 = Developer('Test','Developer',120000,'C++')  # Developer class instance 2
mgr_1 = Manager('Sue','Smith',90000,[dev_1])        # Manager class instance
mgr_2 = Manager('Test','Manager',700000,[emp_2])    # Manager class instance

date = datetime.date(2022,3,10) # Defines date

tf.dl('[ TEST ]','=',':')

print('\nEmployee.is_workday(date) --> ',Employee.is_workday(date)) # Calls static method from the employee class with specified date

Employee.set_raise_amt(1.05) # == Employee.raise_amount = 1.05

emp_str_1 = 'John-Doe-70000'    # Employee String to be put into from_string()
emp_str_2 = 'Steve-Smith-30000' # Employee String to be put into from_string()
emp_str_3 = 'Jane-Doe-90000'    # Employee String to be put into from_string()

new_emp_1 = Employee.from_string(emp_str_1)                 # Creates a class instance from a string
new_emp_2 = Employee.from_string(emp_str_2)                 # Creates a class instance from a string
new_emp_3 = Employee.from_string(emp_str_3)                 # Creates a class instance from a string
print('\nnew_emp_1.email --> ',new_emp_1.email)             # Prints the employee email from emp_str_1
print('\nEmployee.raise_amount --> ',Employee.raise_amount) # Prints the class variable raise_amount
emp_1.raise_amount = 1.25                                   # Defines class instance raise_amount
print('\nemp_1.raise_amount --> ',emp_1.raise_amount)       # Prints the Employee class instance (emp_1) raise_amount
emp_1.apply_raise()                                         # Applies the Employee apply_raise() to emp_1
print('\ndev_1.raise_amount -->',dev_1.raise_amount)        # Prints the Developer class instance (dev_1) raise_amount
dev_1.apply_raise()                                         # Applies the Developer class raise_amount to the Employee class apply_raise
print('\ndev_1.pay --> ',dev_1.pay)                         # Prints the pay of dev_1 with the applied raise from Employee
print('\ndev_1.prog_lang --> ',dev_1.prog_lang)             # Prints dev_1 programming language
print('\nmgr_1.email -->',mgr_1.email)                      # Prints mgr_1 email

print(tf.g('\nisinstance(mgr_1,Employee) --> '),isinstance(mgr_1,Employee))         # Tests if mgr_1 is an instance of the Employee Class
print(tf.y('\nisinstance(mgr_1,Developer) --> '),isinstance(mgr_1,Developer))       # Tests if the mgr_1 is an instance of the Developer class
print('\nissubclass(Developer,Employee) --> ',issubclass(Developer,Employee)) # Tests if the Developer class is a subclass of Employee
print('\nissubclass(Manager,Developer) --> ',issubclass(Manager,Developer))   # Tests if the Manager class is a subclass of Developer
mgr_1.add_emp(dev_2)    # Adds dev_2 to mgr_1 employees
mgr_1.add_emp(emp_1)    # Adds emp_2 to mgr_1 employees
mgr_1.remove_emp(dev_1) # Removes dev_1 from mgr_1 employees
mgr_1.print_emps()      # Prints manager 1 and their employees
mgr_2.print_emps()      # Prints manager 2 and their employees
tf.dl('[ TEST ]','=',':')
tf.nl()