# This file will aim to create the data for the RF model from Predicting Matchability - PM (2014) paper
# It will overwrite existing PM training data (db).
# Note: https://stackoverflow.com/questions/5189997/python-db-api-fetchone-vs-fetchmany-vs-fetchall
# Note: https://stackoverflow.com/questions/41464752/git-rebase-interactive-the-last-n-commits
# 03/11/2022: The official code (random forest) has been compiled,  g++ -O3 -DNDEBUG -Wall -march=native -o rforest rforest.cpp -I. -lboost_serialization -lboost_iostreams
# This file will also produce the training data for the rforest.cpp
# After this file runs, then compile the tool again: g++ -O3 -DNDEBUG -Wall -march=native -o rforest rforest.cpp -I. -lboost_serialization -lboost_iostreams
# just for sanity and train it: ./rforest -t 25 -d 25 -p pos.txt -n neg.txt -f rforest.gz

# To summarise:
# 1 - Run this file to generate the data for your sklearn model (.db) and the original tool rforest (.txt)
# 2 - Run "train_for_predicting_matchability.py"

# NOTE 14/02/2023:
# Removed the original tool as I got same results with python code.

import os
import sys
from database import COLMAPDatabase
from database import pair_id_to_image_ids, image_ids_to_pair_id
import numpy as np
from tqdm import tqdm
from parameters import Parameters
from query_image import get_descriptors

def get_matched_and_unmatched_descs(c, m, db, side=None):
    assert side != None
    pair_id = image_ids_to_pair_id(int(c), int(m))
    pair_data = db.execute("SELECT rows, cols, data FROM two_view_geometries WHERE pair_id = " + "'" + str(pair_id) + "'").fetchone()
    rows = pair_data[0]
    cols = pair_data[1]
    data = pair_data[2]
    zero_based_indices = COLMAPDatabase.blob_to_array(data, np.uint32).reshape([rows, cols])

    zero_based_matched_indices_left = zero_based_indices[:, 0]
    zero_based_matched_indices_right = zero_based_indices[:, 1]
    _, _, descs_left = get_descriptors(db, str(int(c)))
    _, _, descs_right = get_descriptors(db, str(int(m)))
    zero_based_unmatched_indices_left = np.delete(np.arange(descs_left.shape[0]), zero_based_matched_indices_left, axis=0)
    zero_based_unmatched_indices_right = np.delete(np.arange(descs_right.shape[0]), zero_based_matched_indices_right, axis=0)

    if(side=='left'): #central image
        matched = descs_left[zero_based_matched_indices_left]
        unmatched = descs_left[zero_based_unmatched_indices_left]
        matched = np.c_[matched, np.ones([matched[:, 0].shape[0], 1])]
        unmatched = np.c_[unmatched, np.zeros([unmatched[:, 0].shape[0], 1])]
        return matched, unmatched, zero_based_matched_indices_left, zero_based_unmatched_indices_left
    if (side == 'right'): #matched image or right image or m
        matched = descs_right[zero_based_matched_indices_right]
        unmatched = descs_right[zero_based_unmatched_indices_right]
        matched = np.c_[matched, np.ones([matched[:, 0].shape[0], 1])]
        unmatched = np.c_[unmatched, np.zeros([unmatched[:, 0].shape[0], 1])]
        return matched, unmatched, zero_based_matched_indices_right, zero_based_unmatched_indices_right

def gen_training_data(pair_ids, max_neighbours, max_pairs, descs_db):
    print("Getting Training Data..")
    image_ids = pair_id_to_image_ids(np.array(pair_ids))
    left_images_ids = image_ids[0] #can also use image_ids[1] here but it's more or less the same

    if(max_pairs == -1): #just use all UNIQUE pair ids
        max_pairs = len(np.unique(left_images_ids.flatten()))

    # TODO: max_pairs might be > than the number of unique left_images_ids images, so we need to check (rare case)
    rand_images = np.random.choice(np.unique(left_images_ids.flatten()), size=max_pairs, replace=False) #pick 500 random images (or central images) unique

    matched_images = {} #this will contain a random image id and its 13 * 2 (26),
    # This is where the "neighbours" are retrieved
    for rand_img_id in tqdm(rand_images):
        # get the neighbour pairs' image_ids indexes
        # to explain, we get the indexes of the random image id from the left/central image of the left and right images id list.
        # example: if rand_img_id == 4322, then we get the indexes of 4322 from left_images_ids or image_ids[0] and then use them to get
        # their individual pair(s) from image_ids[1]. we call those neighbours / matches_ids (below)
        # example: 4322 can be seen in index position 44 and 900. We pick the image_ids from the right images id list (image_ids[1]) at position 44, and 900.
        matches_ids = image_ids[1][np.where(left_images_ids == rand_img_id)[0]].flatten() #the images ids that are a match with rand_img_id
        # picking 13 neighbours here that are continuous makes no sense
        # so we pick 13 * 2 random images ids that are a match to rand_img_id
        if(len(matches_ids) > max_neighbours * 2):
            match_neighbours = np.random.choice(matches_ids, max_neighbours * 2, replace=False)
        else:
            match_neighbours = matches_ids #pick all, at this point it will be less than 26

        if(len(match_neighbours) == 0): #rand_img_id has no matches at all...sad..
            matched_images[rand_img_id] = 0
            continue

        assert (len(match_neighbours) != 0)
        matched_images[rand_img_id] = match_neighbours

    assert(len(matched_images) == max_pairs)

    print(f"Chose {len(matched_images.keys())} samples, or central images.")
    total_neighbours = 0
    all_ms = []
    for c, ms in tqdm(matched_images.items()):
        for m in ms:
            all_ms.append(m)
        total_neighbours += len(ms)
    print(f"An average of {int(total_neighbours/len(matched_images.keys()))} \"neighbours\" (both back and forward), or matched images, per central image (no: {len(matched_images)}).")
    print(f"A total of unique {np.unique(all_ms).shape[0]} \"neighbours\" (both back and forward), or matched images.")

    # At this point I will assign to each image id an array of positive / matched zero-based descs indices
    print("Getting the positive and negative desc indices for each image ..")
    # this contains all images, central and matches and their unique descs indexes
    tracked_indices = {}
    # Do central ones first
    for c, ms in tqdm(matched_images.items()):
        # for each c we only check with the first match, ms[0], can do other but same thing
        matched, unmatched, matched_indices, unmatched_indices = get_matched_and_unmatched_descs(c, ms[0], descs_db, side='left')
        assert (matched.shape[0] == matched_indices.shape[0])
        assert (unmatched.shape[0] == unmatched_indices.shape[0])
        tracked_indices[c] = matched_indices #c will always be unique as matched_images.keys() only contains unique ids

    assert (len(tracked_indices) == max_pairs)

    # Do matched ones second
    first_seen_matched_images = 0
    for c, ms in tqdm(matched_images.items()):
        for m in ms:
            # a right image (m) is an image that forms a pair with c (central image)
            # we have many c ones (unique) and many m ones. some c's can have the same m's.
            # so it is bound to happen that we will see some m again and again.
            # so make sure to keep their descs that were deemed positive once and not replace them with a negative one
            # as per the paper, "All points that appear in at least one match form the positive class"
            matched, unmatched, matched_indices, unmatched_indices = get_matched_and_unmatched_descs(c, m, descs_db, side='right')
            assert(matched.shape[0] == matched_indices.shape[0])
            assert(unmatched.shape[0] == unmatched_indices.shape[0])

            if(m in tracked_indices):
                # add new matched_indices and remove duplicates
                tracked_indices[m] = np.unique(np.concatenate((tracked_indices[m], matched_indices), 0))
            else:
                first_seen_matched_images +=1
                tracked_indices[m] = matched_indices

    # tracked_indices will contain less neighbours as it already contains central images ids (max_pairs should be the same length as centrals)
    assert (len(tracked_indices) == max_pairs + first_seen_matched_images)

    # at this point for each central and matched image we have the indices of the positive descs
    # we can easily get the negative ones

    # calculate the size of the descs array
    print("Calculating the size of, all_descs ..")
    decs_no = 0
    for image_id, matched_indices_array in tqdm(tracked_indices.items()):
        _, _, descs = get_descriptors(descs_db, str(int(image_id)))
        decs_no += descs.shape[0]
    all_descs = np.empty([decs_no, 129])

    # at this point get the descs using the indices and save them to all_descs
    print("Filling, all_descs ..")
    i = 0
    for image_id, matched_indices_array in tqdm(tracked_indices.items()):
        _, _, descs = get_descriptors(descs_db, str(int(image_id)))

        matched = descs[matched_indices_array]
        unmatched = np.delete(descs, matched_indices_array, axis=0)
        matched = np.c_[matched, np.ones([matched[:, 0].shape[0], 1])]
        unmatched = np.c_[unmatched, np.zeros([unmatched[:, 0].shape[0], 1])]

        assert((matched.shape[0] + unmatched.shape[0]) == descs.shape[0])

        for desc in matched:
            all_descs[i] = desc
            i += 1
        for desc in unmatched:
            all_descs[i] = desc
            i += 1

    assert i == all_descs.shape[0]
    return all_descs

def createDataForPredictingMatchabilityComparison(parameters, db_PM_path, max_neighbours=13, max_pairs=1200):
    db_live = COLMAPDatabase.connect(parameters.live_db_path)
    print("Selecting pair_ids..")
    pair_ids = db_live.execute("SELECT pair_id FROM two_view_geometries WHERE rows > 0 ORDER BY rows DESC").fetchall()

    print("Using pairs from openCV db..")
    openCV_db = COLMAPDatabase.connect(parameters.gt_db_path_mnm)

    print(f"Max pairs: {max_pairs} for this dataset..")

    # The pairs in the openCV gt db are less than the ones in the original gt db, this is because in create_universal_models.py, I pick pairs that only have
    # rows >0 from the gt db.
    # Now to make training fair I need to train on live data only, so I pick the live pairs from the openCV gt db.
    # The pairs in the openCV db are the same as in the original gt db image. Pair 12345 for example is the same in opencv gt and original live/gt db
    # This is because the opencv model was constructed from the original gt db

    # Choosing the pairs from the opencv gt db that are only in the live db, to avoid gt pairs in the training data
    pair_ids_opencv = openCV_db.execute("SELECT pair_id FROM two_view_geometries WHERE rows > 0 AND pair_id IN ({})".format(",".join(["?"] * len(pair_ids))), list(pair_id[0] for pair_id in pair_ids)).fetchall()
    pair_ids = pair_ids_opencv

    file_identifier = f"{max_pairs}_samples_opencv"
    training_data_db_path = os.path.join(db_PM_path, f"training_data_{file_identifier}.db")
    print(f"Creating training data db at {training_data_db_path}.. (will drop table if exists)")
    training_data_db = COLMAPDatabase.create_db_predicting_matchability_data(training_data_db_path)

    training_data_db.execute("BEGIN")
    training_descs = gen_training_data(pair_ids, max_neighbours, max_pairs, openCV_db) #need to pass openCV_db here as we will train on OpenCV descs

    print("Inserting data..")
    for training_desc in tqdm(training_descs):
        desc = training_desc[0:128].astype(np.uint8)
        matched = training_desc[128]
        training_data_db.execute("INSERT INTO data VALUES (?, ?)", (COLMAPDatabase.array_to_blob(desc),) + (matched,))

    print("Committing..")
    training_data_db.commit()
    print("Generating Stats..")
    stats = training_data_db.execute("SELECT * FROM data").fetchall()
    matched = training_data_db.execute("SELECT * FROM data WHERE matched = 1").fetchall()
    unmatched = training_data_db.execute("SELECT * FROM data WHERE matched = 0").fetchall()

    print("Total descs: " + str(len(stats)))
    print("Total matched descs: " + str(len(matched)))
    print("Total unmatched descs: " + str(len(unmatched)))
    print("% of matched decs: " + str(len(matched) * 100 / len(stats)))

    training_data_db.close()
    print("Done!")

root_path = "/media/iNicosiaData/engd_data/"
dataset = sys.argv[1] #HGE, CAB, LIN (or Other for CMU, retail shop)

# Note: Use parameters.predicting_matchability_comparison_data_lamar_no_samples max_pairs for HGE, CAB, LIN and 1200 for CMU

if(dataset == "HGE" or dataset == "CAB" or dataset == "LIN"):
    base_path = os.path.join(root_path, "lamar", f"{dataset}_colmap_model")
    print("Base path: " + base_path)
    parameters = Parameters(base_path)
    output_path = os.path.join(base_path, "predicting_matchability_comparison_data")
    os.makedirs(output_path, exist_ok=True)
    createDataForPredictingMatchabilityComparison(parameters, output_path, max_pairs=parameters.predicting_matchability_comparison_data_lamar_no_samples)

if(dataset == "CMU"):
    slices_names = ["slice2", "slice3", "slice4", "slice5", "slice6", "slice7", "slice8", "slice9", "slice10", "slice11", "slice12", "slice13", "slice14", "slice15",
                    "slice16", "slice17", "slice18", "slice19", "slice20", "slice21", "slice22", "slice23", "slice24", "slice25"]
    for slice_name in slices_names:
        base_path = os.path.join(root_path, "cmu", f"{slice_name}", "exmaps_data")
        print("Base path: " + base_path)
        parameters = Parameters(base_path)
        output_path = os.path.join(base_path, "predicting_matchability_comparison_data")
        os.makedirs(output_path, exist_ok=True)
        createDataForPredictingMatchabilityComparison(parameters, output_path)

if(dataset == "RetailShop"):
    base_path = os.path.join(root_path, "retail_shop", "slice1")
    print("Base path: " + base_path)
    parameters = Parameters(base_path)
    output_path = os.path.join(base_path, "predicting_matchability_comparison_data")
    os.makedirs(output_path, exist_ok=True)
    createDataForPredictingMatchabilityComparison(parameters, output_path)


from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    url(r'^$', 'editor.views.welcome', name='welcome'),
    url(r'^authorize/$', 'editor.views.authorize', name='authorize'),
    url(r'^authorize/callback/$', 'editor.views.authorize_callback', name='authorize_callback'),

    url(r'^home/(?P<key>\w+)/$', 'editor.views.authenticated_home', name='authenticated_home'),
    url(r'^home/(?P<key>\w+)/reports/pie/$', 'editor.views.pie_chart'),
    url(r'^home/(?P<key>\w+)/reports/line/$', 'editor.views.line_chart'),
    url(r'^home/(?P<key>\w+)/reports/counter/$', 'editor.views.report_counter'),

    url(r'^admin/', include(admin.site.urls)),
)


import frappe
from datetime import datetime, date, timedelta
from frappe import _
from itertools import groupby
from frappe.model.document import Document
from frappe.utils.data import getdate

def get_date_grouping(counter_item) -> str:
    return f"{getdate(counter_item.date).year}_{counter_item.counter_number.lower()}"

def get_mounting_date_grouping(counter_item) -> str:
    return f'{getdate(counter_item.mounting_date).strftime("%Y-%m-%d")}'

class Plot(Document):
    def after_insert(self):
        self.update_linked_customer()

    def on_update(self):
        self.update_linked_customer()
        self.add_has_seal_label()
        self.store_tags()

    def store_tags(self):
        if not hasattr(self, "user_tags") or not self.user_tags:
            return

        existing_tags = self.get_tags()
        for tag in self.user_tags.split(","):
            if tag != "" and not any(t == tag for t in existing_tags):
                self.add_tag(tag)

    def isEmptyValue(self, str=None):
        if isinstance(str, datetime) or isinstance(str, date):
            return False
        return not str or str.isspace()

    def add_has_seal_label(self):
        if self.water_meter_table and len(self.water_meter_table) > 0:
            if not any(
                not self.isEmptyValue(row.seal_number) for row in self.water_meter_table
            ):
                return

        existing_tags = self.get_tags()
        tag = _("Has Seal")
        if not any(t == tag for t in existing_tags):
            self.add_tag(tag)

    def clear_customer_backlink(self, customer_name):
        customer = frappe.get_doc("Customer", customer_name)
        if customer and customer.plot_link is not None:
            customer.plot_link = None
            customer.save()

    def clear_obsolete_customer_backlinks(self):
        linked_customers = frappe.get_list("Customer", filters={"plot_link": self.name})
        for customer in filter(
            lambda x: x.name != self.get_value("customer"), linked_customers
        ):
            self.clear_customer_backlink(customer.name)

    def get_teamwork_tasks_as_string(self):
        if not self.teamwork_tasks_table:
            return ""

        result = _("Tasks for teamwork:{0}").format("\n\n")
        for row in self.teamwork_tasks_table:
            hours, remainder = divmod(row.duration, 3600)
            minutes, seconds = divmod(remainder, 60)
            result = result + f"{row.description} - {int(hours)}h {int(minutes)}min\n"

        return result

    def update_linked_customer(self):
        linked_customer = self.get_value("customer")
        if linked_customer:
            customer = frappe.get_doc("Customer", linked_customer)
            store = False
            if customer.plot_link != self.name:
                customer.plot_link = self.name
                store = True

            tasks = self.get_teamwork_tasks_as_string()
            if customer.teamwork_tasks_from_plot != tasks:
                customer.teamwork_tasks_from_plot = tasks
                store = True

            if store:
                customer.save()

        self.clear_obsolete_customer_backlinks()

    def validate(self):
        self.validate_counters()
        self.validate_mounting_dates()
        self.apply_new_tenant_assignment()
        self.validate_former_tenant_table()

    def validate_decreasing_counter_values(self, grouped_by_counter):
        sorted_list = sorted(grouped_by_counter, key=lambda x: x.date)
        last = 0
        for x in sorted_list:
            if last > x.counter_value:
                frappe.throw(
                    _("Counter '{0}' has decresing values").format(x.counter_number)
                )
            last = x.counter_value

    def add_missing_water_meter_values(self, row):
        matching = next(
            filter(
                lambda x: not x.is_new() and x.counter_number == row.counter_number,
                self.water_meter_table,
            ),
            None,
        )

        if not matching:
            return

        if self.isEmptyValue(row.mounting_date):
            row.mounting_date = matching.mounting_date

        if self.isEmptyValue(row.seal_number):
            row.seal_number = matching.seal_number

    def validate_counters(self):
        for row in self.water_meter_table:
            if row.is_new():
                self.add_missing_water_meter_values(row)

        if len(self.water_meter_table) > 0:
            for key, group in groupby(
                self.water_meter_table, lambda x: x.counter_number
            ):
                self.validate_decreasing_counter_values(list(group))

    def validate_mounting_dates(self):
        if len(self.water_meter_table) > 0:
            for key, group in groupby(
                self.water_meter_table, lambda x: x.counter_number
            ):
                grouped = list(group)
                first_date = grouped[0].mounting_date
                if not all(itm.mounting_date == first_date for itm in grouped):
                    frappe.throw(
                        _("Counter Number '{0}' has multiple mounting dates.").format(
                            key
                        )
                    )

    def apply_new_tenant_assignment(self):
        prev_version = self.get_doc_before_save()
        if (
            prev_version
            and prev_version.customer
            and prev_version.customer != self.customer
        ):
            former_tenant = frappe.get_doc("Customer", prev_version.customer)
            former_tenant.customer_group = "Former Tenant"
            former_tenant.save()
            self.finish_history_for(prev_version.customer)

            if self.customer:
                actual_tenant = frappe.get_doc("Customer", self.customer)
                if actual_tenant.customer_group != "Tenant":
                    actual_tenant.customer_group = "Tenant"
                    actual_tenant.save()

        self.add_new_history_entry()

        if self.customer and self.plot_status == "Not under lease":
            self.plot_status = "Under Lease"

        if not self.customer and self.plot_status == "Under Lease":
            self.plot_status = "Not under lease"

    def finish_history_for(self, customer_name):
        if not customer_name:
            return

        matching = next(
            filter(
                lambda x: x.customer_link == customer_name, self.former_tenants_table
            ),
            None,
        )
        if matching and matching.to_date is None:
            matching.to_date = date.today()

    def add_new_history_entry(self):
        if self.customer:
            matching = next(
                filter(
                    lambda x: x.customer_link == self.customer,
                    self.former_tenants_table,
                ),
                None,
            )
            if not matching:
                new_entry = frappe.new_doc("Former Tenant Table")
                new_entry.from_date = date.today()
                new_entry.customer_link = self.customer
                self.append("former_tenants_table", new_entry)

    def validate_former_tenant_table(self):
        if self.former_tenants_table:
            grouped = groupby(
                sorted(self.former_tenants_table, key=lambda x: x.customer_link),
                lambda x: x.customer_link,
            )

            if any(len(list(grp)) > 1 for key, grp in grouped):
                frappe.throw(
                    _(
                        "Plot '{0}' has multiple entries for one customer in the tenant history"
                    ).format(self.plot_number)
                )


import pandas as pd
from scipy import stats

from locan import LocData
from locan.analysis import LocalizationProperty
from locan.analysis.localization_property import _DistributionFits

def test_test_LocalizationProperty_empty(caplog):
    lprop = LocalizationProperty().compute(LocData())
    lprop.fit_distributions()
    lprop.plot()
    lprop.hist()
    assert caplog.record_tuples == [
        ("locan.analysis.localization_property", 30, "Locdata is empty."),
        ("locan.analysis.localization_property", 30, "No results available to fit."),
    ]

def test_DistributionFits(locdata_rapidSTORM_2d):
    lprop = LocalizationProperty().compute(locdata=locdata_rapidSTORM_2d)
    assert repr(lprop) == "LocalizationProperty(loc_property=intensity, index=None)"
    ds = _DistributionFits(lprop)
    ds.fit(distribution=stats.expon)
    # print(ds.parameters)
    # print(ds.__dict__)
    # #print(ds.parameter_dict())
    # ds.plot()
    assert ds.parameters == ["intensity_loc", "intensity_scale"]
    ds.fit(distribution=stats.expon, with_constraints=False, floc=1000)
    assert ds.parameter_dict()["intensity_loc"] == 1000

def test_Localization_property(locdata_rapidSTORM_2d):
    lprop = LocalizationProperty(loc_property="intensity")
    assert not lprop
    lprop.plot()
    lprop.hist()
    lprop.compute(locdata=locdata_rapidSTORM_2d)
    assert lprop
    # print(lprop)
    assert repr(lprop) == "LocalizationProperty(loc_property=intensity, index=None)"
    assert lprop.results.columns == pd.Index(["intensity"], dtype="object")
    assert lprop.distribution_statistics is None
    lprop.plot()
    lprop.hist()
    lprop.fit_distributions()
    assert list(lprop.distribution_statistics.parameter_dict().keys()) == [
        "intensity_loc",
        "intensity_scale",
    ]

    lprop = LocalizationProperty(loc_property="intensity", index="frame").compute(
        locdata=locdata_rapidSTORM_2d
    )
    # print(lprop.results)
    assert lprop.results.index.name == "frame"
    assert lprop.results.columns == pd.Index(["intensity"], dtype="object")


from intcode import Intcode
from aoc import timer, read_program
from collections import defaultdict, deque
from itertools import product

grid = defaultdict(lambda : '?')
robot_x = 0
robot_y = 0
backtrack = deque()
grid[(0,0)] = '.'
steps = 0
paths = {}
minutes = 0
oxygen = None

# moves           = {2: (1, 0), 1: (-1, 0), 4: (0, 1), 3: (0, -1)}
backtrack_moves = {2: (0, -1), 1: (0, 1), 4: (1, 0), 3: (-1, 0)}

def get_input():
    global robot_x, robot_y, steps
    # get not visited positions
    #move right
    steps += 1
    if grid.get((robot_x + 1, robot_y), 0) == 0:
        # print('moving right')
        robot_x += 1
        backtrack.append(3)
        return 4
    elif grid.get((robot_x - 1, robot_y), 0) == 0:
        # print('moving left')
        robot_x -= 1
        backtrack.append(4)
        return 3
    elif grid.get((robot_x, robot_y + 1), 0) == 0:
        # print('moving up')
        robot_y += 1
        backtrack.append(2)
        return 1
    elif grid.get((robot_x, robot_y - 1), 0) == 0:
        # print('moving down')
        robot_y -= 1
        backtrack.append(1)
        return 2
    else:
        if not backtrack: return
        back = backtrack.pop() # reverse previous move
        steps -= 2
        if back == 1:
            robot_y += 1
        elif back == 2:
            robot_y -= 1
        elif back == 3:
            robot_x -= 1
        elif back == 4:
            robot_x += 1
        return back

def draw(minutes):
    for y in (range(-20, 22)):
        print(y, '\t', end = '')
        for x in range(-21, 30):
            val = grid.get((x, y), ' ')
            if robot_x == x and robot_y == y:
                val = '0'
            print(val, end='')
        print()
    print('Minutes', minutes - 1)

def process_output(state):
    global robot_x, robot_y, steps, oxygen
    # if state != 0:
    #     move = backtrack[-1]
    #     move = backtrack_moves[move]
    #     steps -= 1
    #     x = robot_x + move[0]
    #     paths.setdefault((x, y), set())
    #     y = robot_y + move[1]
    #     paths[x, y].add((robot_x, robot_y))
    if state == 0:
        grid[(robot_x, robot_y)] = '\u2588'
        move = backtrack.pop()
        move = backtrack_moves[move]
        steps -= 1
        robot_x += move[0]
        robot_y += move[1]
    elif state == 1:
        grid[(robot_x, robot_y)] = '.'
    elif state == 2:
        grid[(robot_x, robot_y)] = '0'
        oxygen = (robot_x, robot_y)
        print('Oxygen at ', robot_x, robot_y)
    else:
        return True

@timer
def part1():
    code = read_program(15)
    p = Intcode(code, [])
    _input = get_input()
    running = True
    while running:
        p.inputs.append(_input)
        p.suspended = False
        running = p.run()
        done = process_output(p.outputs.pop(0))
        if done: break
        # draw(0)
        _input = get_input()
        if _input is None: break
    print('Solution:', steps)

part1()

def neighbours(coords):
    p = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    for delta in p:
        if delta == (0,0):
            continue
        yield (coords[0] + delta[0], coords[1] + delta[1])

@timer
def part2():
    global minutes, grid, oxygen
#     g = """######
# #..###
# #.#..#
# #.O.##
# #####""".split('\n')
#     x = 0
#     y = 0
#     grid = defaultdict(lambda : '#')
#     for l in g:
#         for cell in l.strip():
#             grid[(x, y)] = cell
#             print(cell)
#             x += 1
#         y += 1
#         x = 0
#     print(grid)
#     robot_x = 2
#     robot_y = 3

    minutes = 1
    pos = oxygen
    done = {pos}
    oxygen = [pos]
    while oxygen:
        void = []
        for coords in oxygen:
            # get neighbours
            for cell in neighbours(coords):
                if cell in done:
                    continue
                if grid[cell] != '.':
                    continue
                # print(cell)
                grid[cell] = minutes % 10
                # grid[cell] = 'O'
                # print('O', cell)
                # import time
                # time.sleep(0.3)
                done.add(cell)
                void.append(cell)
        oxygen = void
        # print(void)
        minutes += 1
        draw(minutes)
    print(minutes - 2)
part2()


import Eliana, Renato, Mateus

while True:
    while True:
        try:
            n1 = float(input('Dgite o primeiro numero: '))
            break
        except ValueError:
            print('Digite um valor válido')

    while True:
        try:
            n2 = float(input('Dgite o segundo numero: '))
            break
        except ValueError:
            print('Digite um valor válido')

    while True:
        op = int(input('\n1 - soma\n2 - subtração\n3 - divisão\n4 - multiplicação\n5 - raiz quadrada\n'))
        if op == 1:
            print('O resultado da soma é: ', Eliana.soma(n1, n2))
            break
        elif op == 2:
            print('O resultado da subtração é: ', Renato.menos(n1, n2))
            break
        elif op == 3:
            print('O resultado da divisão é: ', Renato.divisao(n1, n2))
            break
        elif op == 4:
            print('O resultado da multiplicação é: ', Eliana.multiplicacao(n1, n2))
            break
        elif op == 5:
                    print('\nO resultado da Raiz Quadrada é: ', Mateus.raiz(n1, n2))
                    break
        else:
            print('Operação inválida')
            break
    print()


import os
import numpy as np
import signal
import logging

from time import sleep
from typing import Union, Optional
from threading import Lock
from rich.progress import Progress
from multiprocessing import Manager, Process

from spt.config import ForwardModelParams, SamplingParams
from spt.modelling.simulation import Simulator, Status
from spt.load_photometry import save_sim, join_partial_results

status_t = tuple[int, Status, int]  # rank, Status, N

class TSStatus:
    def __init__(self, val: Status = Status.STARTING):
        self._lock = Lock()
        self.value: Status = val
        self.n = 0

    def update(self, new: Status, n: Optional[int] = None):
        self._lock.acquire()
        try:
            self.value = new
            if n is not None:
                self.n = n
        finally:
            self._lock.release()

def sim_func(status, idx: int):
    # status is a ListProxy

    # silence all non-error logs:
    log = logging.getLogger()
    log.setLevel(logging.ERROR)

    sp = SamplingParams()
    N = sp.n_samples // sp.concurrency

    sim = Simulator(ForwardModelParams, sp.observation)

    status[0] = Status.LOADED

    theta = np.zeros((N, sim.dim))
    phot = np.zeros((N, sim.phot_dim))

    for i in range(N):
        theta[i], phot[i] = sim.simulate_sample()
        if i % 10 == 0:
            status[0] = Status.SAMPLED
            status[1] = i

    status[0] = Status.SAVING
    status[1] = N

    save_path = os.path.join(sp.save_dir, f'photometry_sim_{N}_{idx}.h5')
    assert isinstance(sim.obs['phot_wave'], np.ndarray)
    save_sim(save_path, theta, sim.model.free_params, phot, sim.obs['phot_wave'])

    # set the status to done before exiting.
    status[0] = Status.DONE
    status[1] = N

def main():

    from mpi4py import MPI
    from spt.utils import splash_screen

    MPIComm = Union[MPI.Intracomm, MPI.Intercomm]

    def root_func(mpi_comm: MPIComm):

        splash_screen()
        sp = SamplingParams()
        C = sp.concurrency
        N = sp.n_samples // C

        if not os.path.exists(sp.save_dir):
            os.makedirs(sp.save_dir)
            logging.info(f'Created results directory {sp.save_dir}')

        sm = Manager()
        status = sm.list([Status.STARTING, 0])

        p = Process(target=sim_func, args=(status, mpi_comm.Get_rank()))
        p.start()

        def interrupt(signum, _):
            logging.error(f'Rank {mpi_comm.Get_rank} received signal {signum}')
            p.terminate()
            mpi_comm.bcast(True)

        map((lambda x: signal.signal(x, interrupt)),
                [signal.SIGTERM, signal.SIGINT, signal.SIGKILL, signal.SIGTRAP])

        logging.info(f'Creating a dataset of size {sp.n_samples} across {C} workers')

        if not os.path.exists(sp.save_dir):
            os.makedirs(sp.save_dir)
            logging.info(f'Created results directory {sp.save_dir}')

        with Progress() as progress:
            tasks = []
            for t in range(sp.concurrency):
                tasks.append(progress.add_task(f'[red]Starting    {t:02}', total=N, start=False))

            done: int = 0
            while done < sp.concurrency:
                sleep(1)

                mpi_comm.bcast(False)

                done = 0
                # all_status = mpi_comm.gather(None)
                all_status = mpi_comm.gather((0, status[0], status[1]))
                assert isinstance(all_status, list)

                for s in all_status:
                    assert len(s) == 3, "Bad status update"
                    tidx, ts, tn = s
                    if ts == Status.STARTING:
                        progress.update(tasks[tidx], completed=tn,
                                        description= f'[red]Starting    {tidx:02}')
                    elif ts == Status.LOADED:
                        progress.reset(tasks[tidx], completed=tn, start=True,
                                       description=f'[dark_orange]Loading SPS {tidx:02}')
                    elif ts == Status.SAMPLED:
                        progress.update(tasks[tidx], completed=tn,
                                        description=f'[green]Running     {tidx:02}')
                    elif ts == Status.SAVING:
                        progress.update(tasks[tidx], completed=tn,
                                        description=f'[green]Saving       {tidx:02}')
                    elif ts == Status.DONE:
                        progress.update(tasks[tidx], completed=tn,
                                        description=f'[white]Done        {tidx:02}')
                        done += 1

        # send TERM signal
        mpi_comm.bcast(True)

        logging.info(f'Joining {sp.concurrency} partial result files')

        join_partial_results(sp.save_dir, sp.n_samples, sp.concurrency)

    def work_func(mpi_comm: MPIComm):

        sm = Manager()
        status = sm.list([Status.STARTING, 0])

        idx = mpi_comm.Get_rank()
        p = Process(target=sim_func, args=(status, idx))
        p.start()

        TERM = False
        while not TERM:
            # block on poll request from root rank
            TERM = mpi_comm.bcast(None)

            # return the status. Note, we may send DONE multiple times.
            mpi_comm.gather((idx, status[0], status[1]))

        if p.is_alive():
            p.terminate()

    mpi_comm: MPIComm = MPI.COMM_WORLD
    mpi_rank = mpi_comm.Get_rank()
    mpi_size = mpi_comm.Get_size()

    if mpi_size == 1:
        logging.warning((
            'Running MPI with only 1 rank.\n'
            'Try increasing SamplingParams.concurrency or check the mpi launch'
            ' command (e.g. mpirun or similar).'))
        raise RuntimeError('Only one MPI rank.')

    if mpi_rank == 0:
        root_func(mpi_comm)
    else:
        work_func(mpi_comm)

if __name__ == '__main__':

    main()


import os #this library provides an interface between Python and an operating system

def add_preamble(directory):
    for path, names, files in os.walk(directory): #os.walk(directory) returns the path, names of subdirectories and names of files of a directory, creating a directory treee
        if names != 'vendor' or names != 'vendor-local': #files in the vendor and vendor-local directories should not have a preamble
            for afile in files:
                afile_path = os.path.join(path, afile) #concatenates the path returned in os.walk and the filename, resulting in an absolute path
                if afile_path.endswith('.py') and afile != 'addpreamble.py': #add the preamble to all .py files except this one
                    f = open(afile_path, 'r')
                    all_lines = f.readlines()
                    f.close()
                    if all_lines != []:
                        first_line = all_lines[0]
                        if first_line == '#!/usr/bin/env python\n' or first_line == 'coding: utf-8': #these lines need to remain at the top
                            f = open(afile_path, 'w')
                            f.write(first_line)
                            f.write(str(all_lines[1:]))
                            f.write("preamble\n\n")
                            f.close()
                        elif first_line != '#!/usr/bin/env python': #elif is used instead of else here in order not to "catch" too much
                            old_contents = f.read()
                            f = open(afile_path, 'w')
                            f.write("preamble\n\n")
                            f.write(old_contents)
                            f.close()

#--------------------------------------------------------------------------------
add_preamble('.') #calls add_preamble on the directory from which python addpreamble.py is run


from __future__ import division, print_function
from west.we_driver import WEDriver
from west.systems import WESTSystem
from westpa.binning import RectilinearBinMapper
from west.states import TargetState, InitialState
from west import Segment
import numpy

EPS = numpy.finfo(numpy.float64).eps

import nose
import nose.tools

class TestWEDriver:
    def setup(self):
        system = WESTSystem()
        system.bin_mapper = RectilinearBinMapper([[0.0, 1.0, 2.0]])
        system.bin_target_counts = numpy.array([4,4])
        system.pcoord_len = 2
        self.we_driver = WEDriver(system=system)
        self.system = system
        self._seg_id = 0

    def segment(self, init_pcoord, final_pcoord, weight=1.0):
        segment= Segment(n_iter=1, seg_id=self._seg_id,
                         pcoord=self.system.new_pcoord_array(),
                         weight=weight)
        segment.pcoord[0] = init_pcoord
        segment.pcoord[1] = final_pcoord
        self._seg_id += 1
        return segment

    def teardown(self):
        self.we_driver.clear()
        del self.we_driver
        del self.system
        del self._seg_id

    def test_assign(self):
        segments = [self.segment(0.0, 1.5, weight=0.5),
                    self.segment(1.5, 0.5, weight=0.5)]
        self.we_driver.new_iteration()
        n_recycled = self.we_driver.assign(segments)
        assert n_recycled == 0
        assert len(self.we_driver.initial_binning[0]) == 1
        assert len(self.we_driver.initial_binning[1]) == 1
        assert len(self.we_driver.final_binning[0]) == 1
        assert len(self.we_driver.final_binning[1]) == 1
        assert (self.we_driver.flux_matrix == numpy.array([[0.0, 0.5], [0.5,0.0]])).all()

    def test_passthrough(self):
        segments = ([self.segment(0.0, 1.5, weight=0.125) for _i in xrange(4)]
                   +[self.segment(1.5, 0.5, weight=0.125) for _i in xrange(4)])
        segs_by_id = {segment.seg_id: segment for segment in segments}
        self.we_driver.new_iteration()
        self.we_driver.assign(segments)
        self.we_driver.construct_next()
        out_segs = set()
        for bin in self.we_driver.next_iter_binning:
            out_segs.update(bin)
        assert out_segs == set(self.we_driver.next_iter_segments)
        assert abs(sum(seg.weight for seg in self.we_driver.next_iter_segments) - 1.0) < 8*EPS

        for segment in self.we_driver.next_iter_segments:
            # has n_iter been advanced?
            assert segment.n_iter == 2

            # is weight correct?
            assert segment.weight == 0.125 #rigorous floating point comparison okay here because no math was done

            # is parent set correctly?
            assert segment.parent_id is not None

            # was pcoord set correctly?
            assert (segs_by_id[segment.parent_id].pcoord[-1] == segment.pcoord[0]).all()

            # was status set correctly?
            assert segment.status == Segment.SEG_STATUS_PREPARED

        # were parent endpoint types set correctly
        for segment in segments:
            assert segment.endpoint_type == Segment.SEG_ENDPOINT_CONTINUES

    def test_split_by_weight(self):
        segments = [self.segment(1.5, 0.5, weight=0.25),
                    self.segment(0.0, 1.5, weight=0.75)]
        self.we_driver.new_iteration()
        self.we_driver.assign(segments)
        self.we_driver.construct_next()
        assert len(self.we_driver.next_iter_binning[0]) == 4
        assert len(self.we_driver.next_iter_binning[1]) == 4
        assert abs(sum(seg.weight for seg in self.we_driver.next_iter_binning[0]) - 0.25) < 4*EPS
        assert abs(sum(seg.weight for seg in self.we_driver.next_iter_binning[1]) - 0.75) < 4*EPS
        assert numpy.allclose([seg.weight for seg in self.we_driver.next_iter_binning[0]],
                              [0.25/4.0 for _i in xrange(4)])
        assert numpy.allclose([seg.weight for seg in self.we_driver.next_iter_binning[1]],
                              [0.75/4.0 for _i in xrange(4)])

        for ibin in xrange(2):
            for segment in self.we_driver.next_iter_binning[ibin]:
                print(segment)
                assert segment.n_iter == 2
                assert segment.parent_id is not None
                assert segment.parent_id == segments[ibin].seg_id
                assert segment.status == Segment.SEG_STATUS_PREPARED

    # this test will fail up to alpha of the time
    def test_merge_by_weight(self):
        selected_counts = {0: 0, 1: 0}
        alpha = 0.01
        nrounds = 1000
        from scipy.stats import binom
        # lower and upper bounds of 95% CI for selecting the segment with weight 1/3
        lb = binom.ppf(alpha/2.0, nrounds, 1.0/3.0)
        ub = binom.ppf(1.0-alpha/2.0, nrounds, 1.0/3.0)

        system = WESTSystem()
        system.bin_mapper = RectilinearBinMapper([[0.0, 1.0]])
        system.bin_target_counts = numpy.array([1])
        system.pcoord_len = 2
        self.we_driver = WEDriver(system=system)
        self.system = system
        self._seg_id = 0

        segments = [Segment(n_iter=1, seg_id=0, pcoord=numpy.array([[0],[0.25]], dtype=numpy.float32),weight=1.0/3.0),
                    Segment(n_iter=1, seg_id=1, pcoord=numpy.array([[0],[0.75]], dtype=numpy.float32),weight=2.0/3.0)]

        for _iround in xrange(nrounds):
            for segment in segments:
                segment.endpoint_type = Segment.SEG_ENDPOINT_UNSET

            self.we_driver.new_iteration()
            self.we_driver.assign(segments)
            self.we_driver.construct_next()

            assert len(self.we_driver.next_iter_binning[0]) == 1
            newseg = self.we_driver.next_iter_binning[0].pop()

            assert segments[newseg.parent_id].endpoint_type == Segment.SEG_ENDPOINT_CONTINUES
            assert segments[~newseg.parent_id].endpoint_type == Segment.SEG_ENDPOINT_MERGED

            selected_counts[newseg.parent_id] += 1

        print(selected_counts)
        assert lb <= selected_counts[0] <= ub, ('Incorrect proportion of histories selected.'
                                                'this is expected about {:%} of the time; retry test.'.format(alpha))

    def test_split_with_adjust(self):
        # this is a split followed by merge
        self.system.bin_target_counts = numpy.array([5,5])
        segments = [self.segment(1.5, 0.5, weight=0.125), self.segment(1.5, 0.5, weight=0.125),
                    self.segment(0.0, 1.5, weight=0.375), self.segment(0.0, 1.5, weight=0.375)]
        self.we_driver.new_iteration()
        self.we_driver.assign(segments)
        self.we_driver.construct_next()
        assert len(self.we_driver.next_iter_binning[0]) == 5
        assert len(self.we_driver.next_iter_binning[1]) == 5
        assert abs(sum(seg.weight for seg in self.we_driver.next_iter_binning[0]) - 0.25) < 5*EPS
        assert abs(sum(seg.weight for seg in self.we_driver.next_iter_binning[1]) - 0.75) < 5*EPS

        for ibin in xrange(2):
            for segment in self.we_driver.next_iter_binning[ibin]:
                print(segment)
                assert segment.n_iter == 2
                assert segment.parent_id is not None
                assert segment.status == Segment.SEG_STATUS_PREPARED

    def test_split_with_adjust_istates(self):
        # this is a split followed by merge, for segments which are initial states
        # addresses WESTPA issue #8 (https://chong.chem.pitt.edu/redmine/issues/8)
        self.system.bin_target_counts = numpy.array([5,5])
        segments = [self.segment(1.5, 0.5, weight=0.125), self.segment(1.5, 0.5, weight=0.125),
                    self.segment(0.0, 1.5, weight=0.375), self.segment(0.0, 1.5, weight=0.375)]
        self.we_driver.new_iteration()
        self.we_driver._prep_we()
        self.we_driver.used_initial_states[-1] = None
        self.we_driver.used_initial_states[-2] = None

        for ibin,bin in enumerate(self.we_driver.next_iter_binning):
            pc = numpy.array([[0.5+ibin],[0.0]])
            for iseg in xrange(6):
                segment = Segment(n_iter=1, seg_id=None, weight=1.0/12.0,
                                  parent_id=-(ibin+1), pcoord=pc)
                bin.add(segment)

        for ibin in xrange(len(self.we_driver.next_iter_binning)):
            # This will raise KeyError if initial state tracking is done improperly
            self.we_driver._adjust_count(ibin)

        assert len(self.we_driver.next_iter_binning[0]) == 5
        assert len(self.we_driver.next_iter_binning[1]) == 5

    def test_recycle(self):
        segments = [self.segment(0.0, 1.5, weight=0.5),
                    self.segment(0.0, 0.5, weight=0.5)]
        tstate = TargetState('recycle', [1.5], 0)
        istate = InitialState(0, 0, 0, pcoord=[0.0])

        self.we_driver.new_iteration(initial_states=[istate], target_states=[tstate])
        n_needed = self.we_driver.assign(segments)
        assert n_needed == 0
        self.we_driver.construct_next()

        n_recycled = len(list(self.we_driver.recycling_segments))
        assert n_recycled == 1

        assert len(self.we_driver.next_iter_binning[0]) == 4
        assert len(self.we_driver.next_iter_binning[1]) == 0
        assert abs(sum(seg.weight for seg in self.we_driver.next_iter_binning[0]) - 1.0) < 4*EPS
        assert numpy.allclose([seg.weight for seg in self.we_driver.next_iter_binning[0]],
                              [0.25 for _i in xrange(4)])
        assert segments[0].endpoint_type == Segment.SEG_ENDPOINT_RECYCLED

    def test_multiple_merge(self):

        # This weight and count combination is known to trigger a split to 51
        # followed by a count adjustment to 50 (thanks to Josh Adelman)
        segment = self.segment(0.0, 0.5, weight=0.9999999999970001)

        # Initial state ID 0
        segment.parent_id = -1
        segment.wtg_parent_ids = set([-1])
        assert segment.initpoint_type == segment.SEG_INITPOINT_NEWTRAJ

        self.system.bin_target_counts = numpy.array([50,50])
        self.we_driver.new_iteration()
        self.we_driver.assign([segment])
        self.we_driver.construct_next()

        assert len(self.we_driver.next_iter_binning[0]) == 50

    def check_populate_initial(self, prob, target_counts):
        istate = InitialState(0, 0, 0, pcoord=[0.0])
        self.system.bin_target_counts = numpy.array([target_counts, target_counts])

        self.we_driver.populate_initial([istate], [prob], system=self.system)
        assert len(self.we_driver.next_iter_binning[0]) == target_counts

    @nose.SkipTest
    def test_populate_initial(self):
        for prob in [0.1, 1.0 / 3.0, 0.9999999999970001, 1.0]:
            for tcount in xrange(30, 60):
                yield self.check_populate_initial, prob, tcount

    # TODO: add test for seeding the flux matrix based on recycling
    # TODO: add test for split after merge in adjust count


# overview:
    # in part one we are generating a list of all the points (lines that begin with 0)...
    #... and sorting the points with a heirarchy were subpoints are listed
    #... with a 4 space indent from their parent point

    # in part two we are concerned with the tags
    # for part two we need to isolate all the words and run an algorithm to sort info by tags
    # hopefully we can get nested tags working in a reasonable amount of time.

#enter a testScript and tag dictionaries

testScript = """
01 a list is a <def> sequence:  <.def.>
02 <def> I call comma seperated items in a list items, and if items have items, the smallest building blocks of a list are called elements.
<.def.>
03 <syn> the simplest way to make a new list is to enclose the items in square brackets: myList = [10,20,30]
<.syn.>
the items in a list don't have to be the same type

04 <def> a list inside a list is called: nested <.def.>

05 <syn> use myList[0] = 'hello world' to access the first item of a list <.syn.>

06 <syn> recall negative indices, where [-1] is the index of the final item <.syn.>

07 indices can be expressions myList[i+i] , where i = 1

08 <syn> range function: range(5): returns a range object: an interable sequence of indices from 0 to n-1 <.syn.>
to traverse and read the elements is the in operator, to write or update elements use indices

09 hello
010 world
011 this point has three digits
010
01.01 point with one dot
01.01.01 point with two dots

0101 keep coding...end

"""
# tag dictionaries
openTags = {'definitionOpen': '<def>',
            'exampleOpen': '<ex>',
            'questionOpen': '<qst>',
            'starOpen': '<star>',
            'syntaxOpen': '<syn>',
             }

closeTags = {
            'definitionClose': '<.def.>',
            'exampleClose': '<.ex.>',
            'questionClose': '<.qst.>',
            'starClose': '<.star.>',
            'syntaxclose': '<.syn.>',
             }

# Q: How do you count lines of a multi-line string?
# Answering the question: use string.splitlines() to separate the string into a list of lines...
# ... then you use len() function on list of lines

def selectPoints(lineListIn):
    # take in a list of lines that are strings
    # return a list of all the lines / strings that begin with '0'
    linesWithStartingZeros = []
    for i in lineListIn:
        if len(i) > 0:
            if i[0] == '0':
                linesWithStartingZeros.append(i)
                # return a list with entries of all lines that start with a numeric code (points)
    return linesWithStartingZeros # return a list of strings that start with 0 (called points)

# def isSubPoint(lineIn):
#     wordsIn = lineIn.split()
#     print(lineIn)
#     print("number of digits of point-code =")
#     print(len(wordsIn[0]))

# we made a new function, let's test is on list of points (mainPointsList)

# decision for sub-points, all I need to do is count the dots..
# ...it makes it feel kinda like bullet-points

def dotCounter(wordIn):
    #used inside of writeDemo
    dotCount = 0
    for letter in wordIn:
        if letter == '.':
            dotCount += 1
    return dotCount

def writeDemo(listOfPointStrings):
    #the goal of this is to write points to the left and sub-points indented the appropriate amount
    #take in a list of (string) points as input
    for i in listOfPointStrings:
        currentLine = i
        currentWords = currentLine.split() # a list of words from the current line
        currentPointCode = currentWords[0] # the code is the first item in the current words list
        currentDotCount = dotCounter(currentPointCode)
        if currentDotCount == 0:
            print(i)
        elif currentDotCount > 0:
            print('    ' * currentDotCount + i)

# ----------------------------------part one: running code----------------------------------------#=

# here we are verifying we can split a multi-line string into a list of lines
testSplit = testScript.splitlines()
# for i in testSplit:
#     print(i)

# call the select points (returns a list of every line that starts with 0)
# ... function and pass in the note-txt-like-string (aka testString) ...
# ... this returns a list with all the lines that are points as entries
pointsList = selectPoints(testSplit)
# call the writeDemo function on the pointsList
writeDemo(pointsList)

# -------------------------part two dealing with adding hyper markups

# now start writing something to process testScript...word by word
print('=====================Begin part two==============')

def stringToLineList(stringIn):
    #functionizing the splitlines() method
    lineListFromString = stringIn.splitlines()
    return lineListFromString

def lineListToWordList(lineListIn):
    # returns a list of words that was converted from an input list of lines,
    # ... using space as delimiter
    wordListOut = []
    for i in lineListIn:
        if len(i) > 0:
            currentLine = i
            currentLineWordList = currentLine.split()
            # print('currentLineWordList = ')
            # print(currentLineWordList)
            for word in currentLineWordList:
                wordListOut.append(word)
    return wordListOut

testScriptLineList = stringToLineList(testScript)

# demo to print out each individual line from the original multi-line  test string
for i in testScriptLineList:
    print(i)

# call the lineListToWordListFunction to obtain a list of all words
testScriptWordList = lineListToWordList(testScriptLineList)

print(testScriptWordList)

# now we have one list with all the words

# to start the code go through until you find an open tag
print('output from sorter tool')

def tagSorter(wordListIn):
    for word in wordListIn:
        if word in openTags.values():
            print(word)


# -*- coding: utf-8 -*-
"""
Created on Fri Nov 30 23:18:32 2018

@author: Christine, Patrick
"""

import matplotlib.pyplot as plt
import numpy as np
import scipy
import praktikum.cassy as cassy
import praktikum.analyse as analyse

def gauss(x, m, s):
    return 1/np.sqrt(np.pi*2)/s*np.exp(-(x-m)**2/(2*s**2))

def round_good(m,s,err): #für obere Abschätzung der Fehler
    '''
    Passt Mittelwert- und Standardabweichungsnachkommastellen an den Fehler an (2 signifikante Stellen des Fehlers)
    m=mean
    s=std
    err=std/sqrt(len)
    '''
    i=2
    test=list('{:.20f}'.format(err))
    while test[i]=='0':
        i+=1
    return np.round([m,s,err],i)

plt.close('all')

data = cassy.CassyDaten("gekoppelt/Rauschmessung.lab")
t = data.messung(1).datenreihe("t").werte
M = data.messung(1).datenreihe("U_A1").werte #Pendelkörper (Masse)
St = data.messung(1).datenreihe("U_B1").werte #Stange allein

#----------------------------#
#Auswertung der Rauschmessung#
#----------------------------#

#Mittelwerte, Standardabweichungen und Fehler
mM,sM,errM=round_good(np.average(M),np.std(M),np.std(M)/np.sqrt(len(M)))
mSt,sSt,errSt=round_good(np.average(St),np.std(St),np.std(St)/np.sqrt(len(St)))

if __name__ == "__main__":

#------------------------------------------------------------
#Erstes Pendel
    print("Spannungsverteilung 1")
    print('m='+str(mM)+u' V, std='+str(sM)+u' V, err='+str(errM)+u' V')

    #Histogramm
    weightsM=np.ones_like(M)/float(len(M))
    plt.hist(M,7, normed=0, weights=weightsM)
    x=np.arange(np.average(M)-0.03, np.average(M)+0.03, 0.001)
    #plt.plot(x, gauss(x, np.average(M), np.std(M)))
    plt.title(u"Histogramm der Ruhelage der Pendelstange 1 \n $\sigma$=" + str(sM)+"$V$, $\mu$="+str(mM)+ "$V$, $\sigma_{\mu} = $"+str(errM)+"$V$")
    plt.xlabel(u"U/V")
    plt.ylabel('Relatives Vorkommen')
    plt.savefig("Images/Rauschmessung_stange_1_histo.jpg")
    plt.axvline(np.mean(M),color='red',linestyle='--')
    plt.figure()

    #Datenplot
    plt.plot(t, M)
    plt.title(u"Rauschmessung Ruhelage Pendel 1")
    plt.ylabel(u"U/V")
    plt.xlabel('Zeit/s')
    plt.plot(t,np.array([np.mean(M)]*len(t)),color='darkorange')
    plt.savefig("Images/Rauschmessung_stange_1.jpg")
    plt.figure()

#------------------------------------------------------------
#Zweites Pendel
    print("==="*20)
    print("Spannungsverteilung 2")
    print('m='+str(mSt)+' V, std='+str(sSt)+' V, err='+str(errSt)+' V')

    #Histogramm
    weightsSt=np.ones_like(M)/float(len(M))
    plt.hist(St, 7, normed=0,weights=weightsSt)
    x=np.arange(min(St), max(St), 0.0001)
    #plt.plot(x, gauss(x, np.average(St), np.std(St)))
    plt.title(u"Histogramm der Ruhelage der Pendelstange 2 \n $\sigma$=" + str(sSt)+" V, $\mu$="+str(mSt)+" V, $\sigma_{\mu} = $" +str(errSt)+" V")
    plt.xlabel(u"U/V")
    plt.ylabel('Relatives Vorkommen')
    plt.savefig("Images/Rauschmessung_stange_2_hist.jpg")
    plt.axvline(np.mean(St),color='red',linestyle='--')
    plt.figure()

    #Datenplot
    plt.plot(t, St)
    plt.ylabel(u"U/V")
    plt.xlabel('Zeit/s')
    plt.title("Rauschmessung Ruhelage Pendel 2")
    plt.plot(t,np.array([np.mean(St)]*len(t)),color='darkorange')
    plt.savefig("Images/Rauschmessung_stange_2.jpg")


import csv
import html
import re
import glob, os

# clean tweets

class NLP():
    def __init__(self):
        self.getFilesList()
        self.readCsvPerDay()

    def naturalLanguage(self, sentence):
        emoji_pattern = re.compile("["
                u"\U0001F600-\U0001F64F"  # emoticons
                u"\U0001F300-\U0001F5FF"  # symbols & pictographs
                u"\U0001F680-\U0001F6FF"  # transport & map symbols
                u"\U0001F1E0-\U0001F1FF"  # flags (iOS)
                                   "]+", flags=re.UNICODE)
        ch = "\\x"  #replace \xfdsda to @
        sentence = str(sentence.encode('utf-8'))
        sentence = sentence.replace(ch, "@")
        sentence = html.unescape(sentence)  # unescape HTML
        sentence = re.sub(r"http\S+", "", sentence)  # remove normal URLS
        sentence = re.sub(r"pic\.twitter\.com/\S+", "", sentence)  # remove pic.twitter.com URLS
        sentence = re.sub(r"@\S+", "", sentence)  # remove User Tags
        sentence = re.sub(emoji_pattern, '', sentence) #remove emojis
        return sentence[4:]

    # Receive csv file contains all tweet, country name
    # return list of tweet from the specific country
    def create_clean_file_daily(self, csv_fileName):
        list_toRet = []
        diction_set = set()
        with open(csv_fileName, 'r',newline='',encoding="ISO-8859-1") as f:
            reader = list(csv.reader(f))
        for val in reader:
            if len(val) == 2 or len(val) == 3:
                val[1] = self.naturalLanguage(val[1])
                val[1] = val[1].replace('\n',"")
                if not val[1].isspace():
                    if val[1].startswith('. ') or val[1].startswith('\ ') or val[1] == '\\':
                        pass
                    else:
                        if val[1] not in diction_set:
                            list_toRet.append(val)
                            diction_set.add(val[1])
        f.close()
        return list_toRet

    # Receive list of tweet from specific country
    # create csv file for that country
    def create_csv_by_day(self,filename):
        csvData = ['Date', 'Tweet']
        with open(filename, 'w', newline='') as csvFile:
            writer = csv.writer(csvFile)
            writer.writerow(csvData)
            for i, val in enumerate(self.clean_tweets):
                writer.writerow(val)
                if i == 800:
                    break
            csvFile.close()

    def getFilesList(self):
        self.file_list = glob.glob("Tweets By Days/*.csv")

    def readCsvPerDay(self):
        self.createFolders()
        self.clean_file_list = glob.glob("Csv By Days/*.csv")
        diff_num = len(self.file_list) - len(self.clean_file_list)
        for i in range(diff_num):
            file = self.file_list[i + len(self.clean_file_list)]
            print(file)
            self.clean_tweets = self.create_clean_file_daily(file)
            current_date = file[file.find('\\') + 1:]
            self.create_csv_by_day('Csv By Days/' + current_date)

    def createFolders(self):
        path = os.getcwd()
        if self.folderValidation(path + '/Csv By Days') == 0:
            os.mkdir(path + '/Csv By Days')

    def folderValidation(self, path_name):
        if not os.path.isdir(path_name):
            print('Create dir : ' +path_name)
            return 0
        return -1

if __name__ == "__main__":
    window = NLP()


maior = 0
menor = 0

for c in range(1, 6):

    peso = float(input('Digite o {}º peso '.format(c)))
    if c == 1:
        maior = peso
        menor = peso
    else:
        if peso > maior:
            maior = peso
        if peso < menor:
            menor = peso

print('O menor peso digitado é {}kg.'.format(menor))
print('O maior peso digitado é {}kg.'.format(maior))

        #menorpeso = float(peso < c)
        # maiorpeso = float(peso > c)

    #if peso > c:
       # print('O maior peso inserido foi {}'.format(maiorpeso))
    #elif c > peso:
    #   print('O menor peso inserido é {} '.format(menorpeso))

desafios-2mundo-36-71/D055 ANALISE DE PESO.py


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

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('heritage', '0029_auto_20160219_0349'),
    ]

    operations = [
        migrations.RenameField(
            model_name='interview',
            old_name='interviewer',
            new_name='primary_interviewer',
        ),
        migrations.AlterField(
            model_name='interview',
            name='participant_number',
            field=models.IntegerField(verbose_name='Participant number'),
        ),
        migrations.AlterUniqueTogether(
            name='interview',
            unique_together=set([('phase', 'primary_interviewer', 'type', 'participant_number')]),
        ),
    ]


import os
import csv

ss = input("input csv file name (without .csv): ")
csvpath = os.path.join('Resources', ss + '.csv')
if not os.path.isfile(csvpath):
	print("That .csv file does not exist")
	quit()

us_state_abbrev = {
    'Alabama': 'AL',
    'Alaska': 'AK',
    'Arizona': 'AZ',
    'Arkansas': 'AR',
    'California': 'CA',
    'Colorado': 'CO',
    'Connecticut': 'CT',
    'Delaware': 'DE',
    'Florida': 'FL',
    'Georgia': 'GA',
    'Hawaii': 'HI',
    'Idaho': 'ID',
    'Illinois': 'IL',
    'Indiana': 'IN',
    'Iowa': 'IA',
    'Kansas': 'KS',
    'Kentucky': 'KY',
    'Louisiana': 'LA',
    'Maine': 'ME',
    'Maryland': 'MD',
    'Massachusetts': 'MA',
    'Michigan': 'MI',
    'Minnesota': 'MN',
    'Mississippi': 'MS',
    'Missouri': 'MO',
    'Montana': 'MT',
    'Nebraska': 'NE',
    'Nevada': 'NV',
    'New Hampshire': 'NH',
    'New Jersey': 'NJ',
    'New Mexico': 'NM',
    'New York': 'NY',
    'North Carolina': 'NC',
    'North Dakota': 'ND',
    'Ohio': 'OH',
    'Oklahoma': 'OK',
    'Oregon': 'OR',
    'Pennsylvania': 'PA',
    'Rhode Island': 'RI',
    'South Carolina': 'SC',
    'South Dakota': 'SD',
    'Tennessee': 'TN',
    'Texas': 'TX',
    'Utah': 'UT',
    'Vermont': 'VT',
    'Virginia': 'VA',
    'Washington': 'WA',
    'West Virginia': 'WV',
    'Wisconsin': 'WI',
    'Wyoming': 'WY',
}

with open(csvpath, newline='') as f:
	reader = csv.reader(f)
	data = [row for row in reader if row[0] !='Emp ID']
	names = [i[1].split(" ") for i in data]
	first = [i[0] for i in names]
	last = [i[1] for i in names]
	dob = ["/".join(i[2].split("-")) for i in data]
	ssn = ["***-**-{}".format(i[3][7:len(i[3])]) for i in data]
	states = [us_state_abbrev[i[4]] for i in data]
	final = zip([i[0] for i in data],first,last,dob,ssn,states)

ssout = input("input output csv name (without .csv): ")
with open(ssout + '.csv', 'w', newline = '') as ff:
	writer = csv.writer(ff, delimiter=",")
	writer.writerow(['Emp ID','First Name','Last Name','DOB','SSN','State'])
	for i in final:
		writer.writerow(i)

print("Please find {}.csv in folder {}".format(ssout,os.path.dirname(os.path.realpath(__file__))))


import typing as _t
from decimal import Decimal
from dataclasses import dataclass
from django.db import models
from django.contrib.contenttypes.models import ContentType
from . import stripe_api

# Abstract Models

class ContentTypeModel(models.Model):
    """An abstract base class for models that need to reference other models
    by their content type.
    """
    content_type = models.ForeignKey(
        ContentType,
        on_delete=models.PROTECT,
        related_name='+'
    )
    object_id = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        abstract = True

    @property
    def object(self) -> models.Model:
        if not hasattr(self, '_object'):
            obj = None
            try:
                obj = self.content_type.get_object_for_this_type(
                    pk=self.object_id
                )
            except models.ObjectDoesNotExist:
                pass
            self._object = obj
        return self._object

    @classmethod
    def get_for_instance(
        cls,
        instance: models.Model
    ) -> _t.Union['PaymentHistory', None]:
        """Retrieves the payment history record for a given instance if it
        exists.

        Args:
            instance (models.Model): The instance for which to retrieve the
                payment history record.
        """
        try:
            return cls.objects.get(
                content_type=ContentType.objects.get_for_model(instance),
                object_id=instance.pk
            )
        except cls.DoesNotExist:
            return None

# Models
class PaymentHistory(ContentTypeModel):
    pay_intent_id = models.CharField(max_length=255, unique=True)
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    card_type = models.CharField(max_length=20)
    last_4_digits = models.CharField(max_length=4)
    exp_month = models.PositiveIntegerField(verbose_name='Expiry month')
    created_on = models.DateTimeField(auto_now_add=True)
    success = models.BooleanField()

    class Meta:
        ordering = ['-created_on']
        verbose_name = 'Payment History'
        verbose_name_plural = 'Payment History'

    @classmethod
    def create_for_instance(
        cls,
        instance: models.Model,
        amount: Decimal
    ) -> 'PaymentHistory':
        """Creates a payment history record for a given instance.

        Args:
            instance (models.Model): The instance for which to create the
                payment history record.
            amount (Decimal): The amount of the payment.
        """
        rec = cls.objects.create(
            content_type=ContentType.objects.get_for_model(instance),
            object_id=instance.pk,
            amount=amount
        )
        rec.save()
        return rec

class Product(ContentTypeModel):
    product_id = models.CharField(
        max_length=255,
        unique=True,
        verbose_name='Stripe Product ID'
    )

class Price(models.Model):

    price_id = models.CharField(
        max_length=255,
        unique=True,
        verbose_name='Stripe Price ID',
    )
    product = models.ForeignKey(
        Product,
        on_delete=models.PROTECT,
        related_name='prices'
    )
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    recurring = models.BooleanField()

    class Meta:
        verbose_name = 'Price'
        verbose_name_plural = 'Prices'

# Model Mixins

class PaymentRecordMixin:
    @property
    def payment_history(self) -> _t.Union['PaymentHistory', None]:
        """Retrieves the payment history record for a given instance if it
        exists.
        """
        return PaymentHistory.get_for_instance(self)

# Data Classes

@dataclass
class ModelInfo:
    app_name: str
    model_name: str
    object_id: int
    content_type_id: int
    amount_attr: str

    def get_object(self) -> models.Model:
        return ContentType.objects.get_for_id(
            self.content_type_id
        ).get_object_for_this_type(
            pk=self.object_id
        )

    def get_amount(self, as_integral: bool = False) -> _t.Union[Decimal, int]:
        """Returns the amount of the instance.
        Args:
            as_integral (bool): Whether to return the amount as an integer. If
                True, the amount will be multiplied by 100.
        """

        amount = getattr(self.get_object(), self.amount_attr)
        if as_integral:
            return int(amount * 100)
        return amount

    @property
    def product(self) -> Product:
        """Retrieves the product for a given instance, otherwise creates a
        new product.
        """

    @property
    def metadata(self) -> _t.Dict[str, str]:
        """Returns the metadata for a given instance to be used in the Stripe
        API.
        """
        return {
            'content_type_id': self.content_type_id,
            'object_id': self.object_id,
        }

    @classmethod
    def from_instance(
        cls,
        model: models.Model,
        amount_attr: str,
    ) -> 'ModelInfo':
        """Creates a ModelInfo object from a model instance.

        Args:
            model (models.Model): The model instance.
            amount_attr (str): The name of the attribute that contains the
                amount.
        """
        return ModelInfo(
            app_name=model._meta.app_label,
            model_name=model._meta.model_name,
            object_id=model.pk,
            content_type_id=ContentType.objects.get_for_model(model).pk,
            amount_attr=amount_attr,
        )


def bocce_score(b):
    c = b.pop()
    a = [x for x in b if x['type'] == 'red']
    b = [x for x in b if x['type'] == 'black']

    def f(x):
        return (x['distance'][0] - c['distance'][0]) ** 2 + (x['distance'][1] - c['distance'][1]) ** 2
    s1 = sum(all(f(x) < f(y) for y in b) for x in a)
    s1 -= sum(all(f(x) < f(y) for y in a) for x in b)
    if s1 == 0: return 'No points scored'
    return f'{"black" if s1 < 0 else "red"} scores {abs(s1)}'


#!/bin/python37

import os
import sys
import time
import random

def child_process(sleep_time):
    pid = os.getpid()
    ppid = os.getppid()
    print(f"Child[{pid}]: I am started. My PID is {pid}. Parent PID is {ppid}.")

    time.sleep(sleep_time)

    exit_status = random.randint(0, 1)
    print(f"Child[{pid}]: I am ended. PID is {pid}. Parent PID is {ppid}.")
    os._exit(exit_status)

def main():
    sleep_time = 5

    if len(sys.argv) > 1 and sys.argv[1].isnumeric():
        sleep_time = int(sys.argv[1])

    child_process(sleep_time)

if __name__ == "__main__":
    main()


import numpy as np
import matplotlib.pyplot as plt

NUM_TRIALS =10000
BANDIT_PROBS = [0.2,0.8,0.6]

class Bandit:
    def __init__(self, p):
        self.p = p
        self.p_mean = 0
        self.p_count =0

    def pullLever(self):
        return np.random.random() < self.p

    def update(self, x):
        self.p_count += 1
        self.p_mean = (x + (self.p_count - 1)* self.p_mean)/self.p_count

def experience():
    rewards = np.zeros(NUM_TRIALS)
    bandits = [Bandit(p) for p in BANDIT_PROBS]

    for i in range(3):
        rewards[i] = bandits[i].pullLever()
        bandits[i].update(bandits[i].pullLever())

    for b in bandits:
        print(f" Bandit mean is: {b.p_mean}")
    for i in range(3, NUM_TRIALS):
        j = np.argmax([(b.p_mean+ np.sqrt((2*np.log(i))/b.p_count))for b in bandits])

        rewards[i] = bandits[j].pullLever()
        bandits[j].update(bandits[j].pullLever())

    for b in bandits:
        print(f" Bandit final mean is: {b.p_mean}")

    cum_sum = np.cumsum(rewards)
    win_rate = rewards.sum()/NUM_TRIALS
    print(f" Total rewards is: {rewards.sum()}")
    print(f" Number of time each bandit is selected: {[b.p_count for b in bandits]}")
    print(f" Win rate: {win_rate}")

if __name__ == "__main__":
    experience()


__author__ = 'GROSSMAN'

import numpy as np
import random
import matplotlib.pyplot as plt

data= np.loadtxt("test_data_1_vs_8.dat")
X=data[:, 1:]
Y=data[:, 0]

#convert to hyperline
for y in range(len(Y)):
    if (Y[y]==8):
        Y[y]=1
    else:
        Y[y]=-1

#initiate w
W=[]
for i in range(len(X[0])):
    W=np.append(W,0)

#perceptron
count=0
for j in range(len(X)):
    #taking randomly an index
    rand=random.randint(0,len(X)-1)
    #goal: (yi<w,xi>) >0 for every i
    if (Y[rand]*np.dot(W,X[rand])<=0):
        #means it's an error,fix it
        count=count+1
        W=W+Y[rand]*X[rand]

tmp = 1/(1+np.exp(-10*W/W.max()))
plt.imshow(tmp.reshape(28,28),cmap="gray")
plt.draw()
plt.savefig("final_weight_vector")
plt.imshow(X[1, :].reshape(28, 28), cmap="gray")
plt.draw()

f = open('perceptron_mistakes.txt','w')
f.write("number of mistakes= "+str(count))
f.close()


# Import modules
import os
import csv

# Specify filepath for data sources: employee_data1.csv OR employee_data2.csv
csvfilepath = os.path.join('raw_data', "employee_data1.csv")

# Open the file using dict reader. Specify employeeData variable to hold content.
with open(csvfilepath, newline='') as employeeData:
    csvreader = csv.DictReader(employeeData, delimiter=',')

    # Create lists to capture corresponding data
    IDs = []
    DOBs = []
    SSNs = []
    States = []
    FirstNames = []
    LastNames = []

    # Create ditionary of US State names and corresponding abbreviations
    StateAbbrev = {'Alabama': 'AL',
        'Alaska': 'AK',
        'Arizona': 'AZ',
        'Arkansas': 'AR',
        'California': 'CA',
        'Colorado': 'CO',
        'Connecticut': 'CT',
        'Delaware': 'DE',
        'Florida': 'FL',
        'Georgia': 'GA',
        'Hawaii': 'HI',
        'Idaho': 'ID',
        'Illinois': 'IL',
        'Indiana': 'IN',
        'Iowa': 'IA',
        'Kansas': 'KS',
        'Kentucky': 'KY',
        'Louisiana': 'LA',
        'Maine': 'ME',
        'Maryland': 'MD',
        'Massachusetts': 'MA',
        'Michigan': 'MI',
        'Minnesota': 'MN',
        'Mississippi': 'MS',
        'Missouri': 'MO',
        'Montana': 'MT',
        'Nebraska': 'NE',
        'Nevada': 'NV',
        'New Hampshire': 'NH',
        'New Jersey': 'NJ',
        'New Mexico': 'NM',
        'New York': 'NY',
        'North Carolina': 'NC',
        'North Dakota': 'ND',
        'Ohio': 'OH',
        'Oklahoma': 'OK',
        'Oregon': 'OR',
        'Pennsylvania': 'PA',
        'Rhode Island': 'RI',
        'South Carolina': 'SC',
        'South Dakota': 'SD',
        'Tennessee': 'TN',
        'Texas': 'TX',
        'Utah': 'UT',
        'Vermont': 'VT',
        'Virginia': 'VA',
        'Washington': 'WA',
        'West Virginia': 'WV',
        'Wisconsin': 'WI',
        'Wyoming': 'WY'}

    # Interate through all rows in EmployeeData; Note csv.DictReader skips headers.
    # Add relevant data into corresponding list using append function and format data appropriately.
    for row in csvreader:
        IDs.append(row['Emp ID'])
        FirstNames.append(row['Name'].split(' ')[0])
        LastNames.append(row['Name'].split(' ')[1])
        DOBs.append(row['DOB'].split('-')[1] + '/' + row['DOB'].split('-')[2] + '/' + row['DOB'].split('-')[0])
        SSNs.append('***-**-' + row['SSN'].split('-')[2])
        States.append(StateAbbrev[row['State']])

    # Zip all lists into tuple named nEmployeeData
    nEmployeeData = zip(IDs, FirstNames, LastNames, DOBs, SSNs, States)

 # Specify path for storing the output file
pyBossOutputPath = os.path.join('.', 'pyBossOutput.csv')

# Open the file using "write" mode. Specify csvfile variable to hold content.
with open(pyBossOutputPath, 'w', newline='') as csvfile:
    csvwriter = csv.writer(csvfile, delimiter=',')

    # Write the first row (column headers): Emp ID,First Name,Last Name,DOB,SSN,State
    csvwriter.writerow(["Emp ID", "First Name", "Last Name", "DOB", "SSN", "State"])

    # Write all rows for nEmployeeData
    csvwriter.writerows(nEmployeeData)


from django.shortcuts import render, redirect, get_object_or_404
from django.utils import timezone
from django.contrib.auth.decorators import login_required

from .models import Post, Image
from .forms import PostForm, ImageForm

from django.core.exceptions import ObjectDoesNotExist

def index(request):
	posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('-published_date')
	list = []
	for post in posts:
		image = Image.objects.filter(post_id=post.pk)
		url = ''
		if image.count() != 0:
			url = image[0].image.url
		item = {'post': post, 'image': url}
		list.append(item)
	return render(request, 'index.html', {'list': list})

@login_required
def upload(request):
	if request.method == 'POST':
		form = PostForm(request.POST)
		form_image = ImageForm(request.POST, request.FILES)
		if form.is_valid():
			post = form.save(commit=False)
			post.author = request.user
			post.published_date = timezone.now()
			post.save()
			url = ''
			if form_image.is_valid():
				image = form_image.save(commit=False)
				image.post_id = post
				url = image.image.url
				image.save()
			# post.thumbnail = url
			# post.save()
			return redirect('myapp.views.index')
	return render(request, 'upload.html')

def detail(request, post_id):
	post = get_object_or_404(Post, pk=post_id)
	images = Image.objects.filter(post_id=post_id)
	return render(request, 'detail.html', {'post': post, 'images': images})

def delete(request, post_id):
	post = get_object_or_404(Post, pk=post_id)
	post.delete()
	return redirect('myapp.views.index')


from django import forms
from django.forms.models import modelform_factory
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from django.contrib.auth.forms import UsernameField
from django.utils.translation import ugettext_lazy as _, pgettext_lazy
from django.template.defaultfilters import slugify
from django.utils.crypto import get_random_string

from django_select2.forms import ModelSelect2MultipleWidget

from .models import Participant, Talk, TalkCategory, Track, Tag, \
                    Conference, Room, Volunteer, Activity
from .environment import TalkEnvironment, SpeakerEnvironment, VolunteerEnvironment

ACCEPTATION_CHOICES = [
        ('pending', _('Pending decision')),
        ('accepted', _('Accepted')),
        ('declined', _('Declined')),
]
ACCEPTATION_VALUES = [
        ('pending', None),
        ('accepted', True),
        ('declined', False),
]

CONFIRMATION_CHOICES = [
        ('waiting', _('Waiting')),
        ('confirmed', _('Confirmed')),
        ('cancelled', _('Cancelled')),
]
CONFIRMATION_VALUES = [
        ('waiting', None),
        ('confirmed', True),
        ('cancelled', False),
]

class OnSiteNamedModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        self.conference = kwargs.pop('conference')
        super().__init__(*args, **kwargs)

    # we should manually check (site, name) uniqueness as the site is not part of the form
    def clean_name(self):
        name = self.cleaned_data['name']
        if (not self.instance or self.instance.name != name) \
                and self._meta.model.objects.filter(site=self.conference.site, name=name).exists():
            raise self.instance.unique_error_message(self._meta.model, ['name'])
        return name

    def save(self, commit=True):
        obj = super().save(commit=False)
        obj.site = self.conference.site
        if commit:
            obj.save()
        return obj

class VolunteerFilterForm(forms.Form):
    activity = forms.MultipleChoiceField(
               label=_('Activity'),
               required=False,
               widget=forms.CheckboxSelectMultiple,
               choices=[],
   )

    def __init__(self, *args, **kwargs):
        site = kwargs.pop('site')
        super().__init__(*args, **kwargs)
        activities = Activity.objects.filter(site=site)
        self.fields['activity'].choices = [('none', pgettext_lazy('activity', 'None'))] + list(activities.values_list('slug', 'name'))

class TalkForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        categories = kwargs.pop('categories')
        super().__init__(*args, **kwargs)
        if kwargs.get('instance', None):
            del self.fields['category']
        else:
            self.fields['category'].queryset = categories
        if self.instance and self.instance.accepted is not True:
            del self.fields['materials']

    class Meta:
        model = Talk
        fields = ('category', 'title', 'description', 'notes', 'materials',)

class TalkStaffForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        conference = kwargs.pop('conference')
        super().__init__(*args, **kwargs)
        self.fields['category'].queryset = TalkCategory.objects.filter(site=conference.site)
        self.fields['track'].queryset = Track.objects.filter(site=conference.site)
        self.fields['room'].queryset = Room.objects.filter(site=conference.site)
        if self.instance and self.instance.category and self.instance.category.duration:
            self.fields['duration'].help_text = _('Default duration: %(duration)d min') % {'duration': self.instance.duration}

    class Meta(TalkForm.Meta):
        fields = ('category', 'track', 'title', 'description', 'notes', 'tags', 'start_date', 'duration', 'room', 'materials', 'video', 'speakers')
        widgets = {
            'tags': forms.CheckboxSelectMultiple,
        }
        labels = {
            'category': _('Category'),
            'title': _('Title'),
            'description': _('Description'),
            'notes': _('Notes'),
        }
        help_texts = {
            'notes': _('Visible by speakers'),
        }

class TalkFilterForm(forms.Form):
    category = forms.MultipleChoiceField(
            label=_('Category'),
            required=False,
            widget=forms.CheckboxSelectMultiple,
            choices=[],
    )
    accepted = forms.MultipleChoiceField(
            label=_('Accepted'),
            required=False,
            widget=forms.CheckboxSelectMultiple,
            choices=ACCEPTATION_CHOICES,
    )
    confirmed = forms.MultipleChoiceField(
            label=_('Confirmed'),
            required=False,
            widget=forms.CheckboxSelectMultiple,
            choices=CONFIRMATION_CHOICES,
    )
    track = forms.MultipleChoiceField(
            label=_('Track'),
            required=False,
            widget=forms.CheckboxSelectMultiple,
            choices=[],
    )
    tag = forms.MultipleChoiceField(
            label=_('Tag'),
            required=False,
            widget=forms.CheckboxSelectMultiple,
            choices=[],
    )
    vote = forms.NullBooleanField(
            label=_('Vote'),
            help_text=_('Filter talks you already / not yet voted for'),
    )
    room = forms.NullBooleanField(
            label=_('Room'),
            help_text=_('Filter talks already / not yet affected to a room'),
    )
    scheduled = forms.NullBooleanField(
            label=_('Scheduled'),
            help_text=_('Filter talks already / not yet scheduled'),
    )
    materials = forms.NullBooleanField(
            label=_('Materials'),
            help_text=_('Filter talks with / without materials'),
    )
    video = forms.NullBooleanField(
            label=_('Video'),
            help_text=_('Filter talks with / without video'),
    )

    def __init__(self, *args, **kwargs):
        site = kwargs.pop('site')
        super().__init__(*args, **kwargs)
        categories = TalkCategory.objects.filter(site=site)
        self.fields['category'].choices = categories.values_list('pk', 'name')
        tracks = Track.objects.filter(site=site)
        self.fields['track'].choices = [('none', _('Not assigned'))] + list(tracks.values_list('slug', 'name'))
        self.fields['tag'].choices = Tag.objects.filter(site=site).values_list('slug', 'name')

class TalkActionForm(forms.Form):
    EMAIL_TALKS = 1
    EMAIL_SPEAKERS = 2
    EMAIL_CHOICES = (
        (None, "---------"),
        (EMAIL_TALKS, _('one per speaker and talk combination')),
        (EMAIL_SPEAKERS, _('only one per speaker')),
    )

    talks = forms.MultipleChoiceField(choices=[])
    decision = forms.NullBooleanField(label=_('Accept talk?'))
    track = forms.ChoiceField(required=False, choices=[], label=_('Assign to a track'))
    tag = forms.ChoiceField(required=False, choices=[], label=_('Add a tag'))
    room = forms.ChoiceField(required=False, choices=[], label=_('Put in a room'))
    email = forms.ChoiceField(required=False, choices=EMAIL_CHOICES, label=_('Send an email'))

    def __init__(self, *args, **kwargs):
        site = kwargs.pop('site')
        talks = kwargs.pop('talks')
        super().__init__(*args, **kwargs)
        self.fields['talks'].choices = [(talk.pk, None) for talk in talks.all()]
        tracks = Track.objects.filter(site=site)
        self.fields['track'].choices = [(None, "---------")] + list(tracks.values_list('slug', 'name'))
        tags = Tag.objects.filter(site=site)
        self.fields['tag'].choices = [(None, "---------")] + list(tags.values_list('slug', 'name'))
        rooms = Room.objects.filter(site=site)
        self.fields['room'].choices = [(None, "---------")] + list(rooms.values_list('slug', 'name'))

class SpeakerActionForm(forms.Form):
    speakers = forms.MultipleChoiceField(choices=[])
    email = forms.BooleanField(required=False, label=_('Send an email'))

    def __init__(self, *args, **kwargs):
        speakers = kwargs.pop('speakers')
        super().__init__(*args, **kwargs)
        self.fields['speakers'].choices = [(speaker.pk, None) for speaker in speakers.all()]

class VolunteerActionForm(forms.Form):
    volunteers = forms.MultipleChoiceField(choices=[])
    email = forms.BooleanField(required=False, label=_('Send an email'))

    def __init__(self, *args, **kwargs):
        volunteers = kwargs.pop('volunteers')
        super().__init__(*args, **kwargs)
        self.fields['volunteers'].choices = [(volunteer.pk, None) for volunteer in volunteers.all()]

class NotifyForm(forms.Form):
    notify = forms.BooleanField(initial=True, required=False, label=_('Notify by mail?'))

class ParticipantForm(OnSiteNamedModelForm):
    SOCIAL_FIELDS = ['twitter', 'linkedin', 'github', 'website', 'facebook', 'mastodon']

    def clean_email(self):
        email = self.cleaned_data['email']
        if (not self.instance or self.instance.email != email) \
                and self._meta.model.objects.filter(site=self.conference.site, email=email).exists():
            raise self.instance.unique_error_message(self._meta.model, ['email'])
        return email

class ParticipantFilterForm(forms.Form):
    category = forms.MultipleChoiceField(
            label=_('Category'),
            required=False,
            widget=forms.CheckboxSelectMultiple,
            choices=[],
    )
    accepted = forms.MultipleChoiceField(
            label=_('Accepted'),
            required=False,
            widget=forms.CheckboxSelectMultiple,
            choices=ACCEPTATION_CHOICES,
    )
    confirmed = forms.MultipleChoiceField(
            label=_('Confirmed'),
            required=False,
            widget=forms.CheckboxSelectMultiple,
            choices=CONFIRMATION_CHOICES,
    )
    track = forms.MultipleChoiceField(
            label=_('Track'),
            required=False,
            widget=forms.CheckboxSelectMultiple,
            choices=[],
    )

    def __init__(self, *args, **kwargs):
        site = kwargs.pop('site')
        super().__init__(*args, **kwargs)
        categories = TalkCategory.objects.filter(site=site)
        self.fields['category'].choices = categories.values_list('pk', 'name')
        tracks = Track.objects.filter(site=site)
        self.fields['track'].choices = [('none', _('Not assigned'))] + list(tracks.values_list('slug', 'name'))

class EmailForm(forms.Form):
    email = forms.EmailField(required=True, label=_('Email'))

class PreviewTalkMailForm(forms.Form):
    speaker = forms.IntegerField()
    talk = forms.IntegerField()
    subject = forms.CharField(required=False, label=_('Subject'))
    body = forms.CharField(required=False, label=_('Body'))

class PreviewSpeakerMailForm(forms.Form):
    speaker = forms.IntegerField()
    subject = forms.CharField(required=False, label=_('Subject'))
    body = forms.CharField(required=False, label=_('Body'))

class PreviewVolunteerMailForm(forms.Form):
    volunteer = forms.IntegerField()
    subject = forms.CharField(required=False, label=_('Subject'))
    body = forms.CharField(required=False, label=_('Body'))

class SendMailForm(forms.Form):
    subject = forms.CharField()
    body = forms.CharField(widget=forms.Textarea)
    confirm = forms.BooleanField(required=False, label=_('I read my self twice, confirm sending'))

    def clean_subject(self):
        return self.clean_template('subject')

    def clean_body(self):
        return self.clean_template('body')

class SendTalkMailForm(SendMailForm):
    def __init__(self, *args, **kwargs):
        self._talks = kwargs.pop('talks')
        super().__init__(*args, **kwargs)
        self._env = dict()

    def clean_template(self, template):
        try:
            for talk in self._talks.all():
                for speaker in talk.speakers.all():
                    env = self._env.get((talk, speaker), TalkEnvironment(talk, speaker))
                    env.from_string(self.cleaned_data.get(template)).render()
        except Exception as e:
            raise forms.ValidationError(_("Your template does not compile (at least) with talk '%(talk)s' and speaker '%(speaker)s'.") %
                        {'talk': talk, 'speaker': speaker})
        return self.cleaned_data.get(template)

class SendSpeakerMailForm(SendMailForm):
    def __init__(self, *args, **kwargs):
        self._speakers = kwargs.pop('speakers')
        super().__init__(*args, **kwargs)
        self._env = dict()

    def clean_template(self, template):
        try:
            for speaker in self._speakers.all():
                env = self._env.get(speaker, SpeakerEnvironment(speaker))
                env.from_string(self.cleaned_data.get(template)).render()
        except Exception as e:
            raise forms.ValidationError(_("Your template does not compile (at least) with speaker '%(speaker)s'.") %
                        {'speaker': speaker})
        return self.cleaned_data.get(template)

class SendVolunteerMailForm(SendMailForm):
    def __init__(self, *args, **kwargs):
        self._volunteers = kwargs.pop('volunteers')
        super().__init__(*args, **kwargs)
        self._env = dict()

    def clean_template(self, template):
        try:
            for volunteer in self._volunteers.all():
                env = self._env.get(volunteer, VolunteerEnvironment(volunteer))
                env.from_string(self.cleaned_data.get(template)).render()
        except Exception as e:
            raise forms.ValidationError(_("Your template does not compile (at least) with volunteer '%(volunteer)s'.") %
                        {'volunteer': volunteer})
        return self.cleaned_data.get(template)

class UsersWidget(ModelSelect2MultipleWidget):
    model = User
    search_fields = [ '%s__icontains' % field for field in UserAdmin.search_fields ]

class ConferenceForm(forms.ModelForm):
    class Meta:
        model = Conference
        fields = [
            'name', 'venue', 'city', 'contact_email', 'acceptances_disclosure_date',
            'schedule_publishing_date', 'schedule_redirection_url',
            'volunteers_opening_date', 'volunteers_closing_date',
            'end_date', 'video_publishing_date',
            'reply_email', 'secure_domain', 'staff',
        ]
        widgets = {
            'staff': UsersWidget(),
        }
        help_texts = {
            'staff': _('New staff members will be informed of their new position by e-mail.'),
        }

class HomepageForm(forms.ModelForm):
    class Meta:
        model = Conference
        fields = ['home']

class CreateUserForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ("first_name", "last_name", "email")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['first_name'].required = True
        self.fields['last_name'].required = True
        self.fields['email'].required = True

    def clean(self):
        super().clean()
        user = User(first_name=self.cleaned_data.get('first_name'), last_name=self.cleaned_data.get('last_name'))
        username = slugify(user.get_full_name())
        if User.objects.filter(username=username).exists():
            raise forms.ValidationError(_('An user with that firstname and that lastname already exists.'))

    def clean_email(self):
        email = self.cleaned_data.get('email')
        if email and User.objects.filter(email=email).exists():
            raise forms.ValidationError(_('A user with that email already exists.'))
        return email

    def save(self, commit=True):
        user = super().save(commit=False)
        user.username = slugify(user.get_full_name())
        user.set_password(get_random_string(length=32))
        if commit:
            user.save()
        return user

class TrackForm(OnSiteNamedModelForm):
    class Meta:
        model = Track
        fields = ['name', 'description']

class TalkCategoryForm(OnSiteNamedModelForm):
    class Meta:
        model = TalkCategory
        fields = ['name', 'duration', 'color', 'label', 'opening_date', 'closing_date']

class RoomForm(OnSiteNamedModelForm):
    class Meta:
        model = Room
        fields = ['name', 'label', 'capacity']

class TagForm(OnSiteNamedModelForm):
    class Meta:
        model = Tag
        fields = ['name', 'color', 'inverted', 'public', 'staff']

class ActivityForm(OnSiteNamedModelForm):
    class Meta:
        model = Activity
        fields = ['name', 'description']

class VolunteerForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        self.conference = kwargs.pop('conference')
        super().__init__(*args, **kwargs)
        activities = Activity.objects.filter(site=self.conference.site)
        if activities.exists():
            self.fields['activities'].queryset = activities
        else:
            del self.fields['activities']

    # we should manually check (site, email) uniqueness as the site is not part of the form
    def clean_email(self):
        email = self.cleaned_data['email']
        if (not self.instance or self.instance.email != email) \
                and self._meta.model.objects.filter(site=self.conference.site, email=email).exists():
            raise self.instance.unique_error_message(self._meta.model, ['email'])
        return email

    def save(self, commit=True):
        obj = super().save(commit=False)
        obj.site = self.conference.site
        if commit:
            obj.save()
        return obj

    class Meta:
        model = Volunteer
        fields = ['name', 'email', 'phone_number', 'sms_prefered', 'activities', 'notes']
        widgets = {
            'activities': forms.CheckboxSelectMultiple,
        }

def get_talk_speaker_form_class(site):
    fields = ['name', 'email', 'twitter', 'linkedin', 'github', 'website', 'facebook', 'mastodon', 'phone_number']
    widget = ModelSelect2MultipleWidget(model=Participant, queryset=Participant.objects.filter(site=site),
                                        search_fields=['%s__icontains' % field for field in fields])
    return modelform_factory(Talk, form=TalkStaffForm, widgets={'speakers': widget})


from turtle import Turtle
ALIGNMENT='center'
FONT= ('Arial', 8, 'normal')
class Scoreboard(Turtle):
    def __init__(self,answer,x,y,color='black'):
        super().__init__()
        self.score=0
        self.hideturtle()
        self.pu()
        self.color(color)
        self.goto(x,y)
        self.write(arg=f"{answer}", move=False, align=ALIGNMENT, font=FONT)


import matplotlib.pyplot as plt
import networkx as nx

class Tree:
    def __init__(self, key, left=None, right=None):
        self.key = key
        self.left = left
        self.right = right

def inorder_layout(tree):
    pos = {}
    def traverse(node, depth=0, pos=pos):
        if node.left:
            traverse(node.left, depth + 1)
        pos[node.key] = (len(pos), -depth)  # horizontal position is number of nodes visited so far
        if node.right:
            traverse(node.right, depth + 1)
    traverse(tree)
    return pos

def build_graph(tree):
    edges = []
    labels = {}
    def traverse(node):
        nonlocal edges, labels
        if node is None:
            return
        if node.left:
            edges.append((node.key, node.left.key))
            labels[(node.key, node.left.key)] = 'yes'
            traverse(node.left)
        if node.right:
            edges.append((node.key, node.right.key))
            labels[(node.key, node.right.key)] = 'not'
            traverse(node.right)
    traverse(tree)
    return edges, labels

# construct a more complicated tree for demonstration
t = Tree('A not match',
         Tree('B not match', Tree('D not match', Tree('H match'), Tree('I match')), Tree('E match', Tree('J match'))),
         Tree('C match', Tree('F match', Tree('K match')), Tree('G match', Tree('L match'),Tree('MD match', Tree('MH match'), Tree('MI match')))))

edges, edge_labels = build_graph(t)
pos = inorder_layout(t)

G = nx.DiGraph()
G.add_edges_from(edges)
plt.figure(figsize=(10, 10))
nx.draw(G, pos, with_labels=True, arrows=False, node_size=3000, node_color='white', font_weight='bold', linewidths=2.0)
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=10)
plt.show()


import string
import random

l= ["postreme", "Verminology", "Palaeophile", "zegedine", "flammulated", "keckle", "Individualism",
"viaggiatory", "Dashpot", "Mecometer", "Zug", "orismology", "beatus", "Unicorn", "Latitudinous"]

while(True):
    try:
        i = input("Enter a letter: ")
        if len(i) > 1:
            print("Wrong input!")
            raise ValueError
        if len(i) < 1:
            print("Wrong input!")
            raise ValueError
        if any(x.isdigit() for x in i):
            print("Wrong input!")
            raise ValueError
    except ValueError:

        continue
    else:
        break
n_l = []
n_l_2 = []
for y in l:
    i = i.lower()
    f_letter = y[0].lower()
    if i!=f_letter:
        n_l_2.append(y)
    if i == f_letter:
        n_l.append(y)
if len(n_l) > 0 and len(n_l)!= 0:
    print("Your input match with these words first letter --> ", end="")
    print(n_l)
elif len(n_l) == 0 or len(n_l) < 0:
    print("Your input match with 0 word")