import xml.etree.cElementTree as etree
import inspect, importlib

def prepareHandlers(kwArgs):
	nodeHandlers = []
	wayHandlers = []
	# getting a dictionary with local variables
	_locals = locals()
	for handlers in ("nodeHandlers", "wayHandlers"):
		if handlers in kwArgs:
			for handler in kwArgs[handlers]:
				if isinstance(handler, str):
					# we've got a module name
					handler = importlib.import_module(handler)
				if inspect.ismodule(handler):
					# iterate through all module functions
					for f in inspect.getmembers(handler, inspect.isclass):
						_locals[handlers].append(f[1])
				elif inspect.isclass(handler):
					_locals[handlers].append(handler)
		if len(_locals[handlers])==0: _locals[handlers] = None
	return (nodeHandlers if len(nodeHandlers) else None, wayHandlers if len(wayHandlers) else None)

class OsmParser:

	def __init__(self, filename, **kwargs):
		self.nodes = {}
		self.ways = {}
		self.relations = {}
		self.minLat = 90
		self.maxLat = -90
		self.minLon = 180
		self.maxLon = -180
		# self.bounds contains the attributes of the bounds tag of the .osm file if available
		self.bounds = None

		(self.nodeHandlers, self.wayHandlers) = prepareHandlers(kwargs)

		self.doc = etree.parse(filename)
		self.osm = self.doc.getroot()
		self.prepare()

	def prepare(self):
		allowedTags = set(("node", "way", "bounds"))
		for e in self.osm: # e stands for element
			attrs = e.attrib
			if e.tag not in allowedTags : continue
			if "action" in attrs and attrs["action"] == "delete": continue
			if e.tag == "node":
				_id = attrs["id"]
				tags = None
				for c in e:
					if c.tag == "tag":
						if not tags: tags = {}
						tags[c.get("k")] = c.get("v")
				lat = float(attrs["lat"])
				lon = float(attrs["lon"])
				# calculating minLat, maxLat, minLon, maxLon
				# commented out: only imported objects take part in the extent calculation
				#if lat<self.minLat: self.minLat = lat
				#elif lat>self.maxLat: self.maxLat = lat
				#if lon<self.minLon: self.minLon = lon
				#elif lon>self.maxLon: self.maxLon = lon
				# creating entry
				entry = dict(
					id=_id,
					e=e,
					lat=lat,
					lon=lon
				)
				if tags: entry["tags"] = tags
				self.nodes[_id] = entry
			elif e.tag == "way":
				_id = attrs["id"]
				nodes = []
				tags = None
				for c in e:
					if c.tag == "nd":
						nodes.append(c.get("ref"))
					elif c.tag == "tag":
						if not tags: tags = {}
						tags[c.get("k")] = c.get("v")
				# ignore ways without tags
				if tags:
					self.ways[_id] = dict(
						id=_id,
						e=e,
						nodes=nodes,
						tags=tags
					)
			elif e.tag == "bounds":
				self.bounds = {
					"minLat": float(attrs["minlat"]),
					"minLon": float(attrs["minlon"]),
					"maxLat": float(attrs["maxlat"]),
					"maxLon": float(attrs["maxlon"])
				}

		self.calculateExtent()

	def iterate(self, wayFunction, nodeFunction):
		nodeHandlers = self.nodeHandlers
		wayHandlers = self.wayHandlers

		if wayHandlers:
			for _id in self.ways:
				way = self.ways[_id]
				if "tags" in way:
					for handler in wayHandlers:
						if handler.condition(way["tags"], way):
							wayFunction(way, handler)
							continue

		if nodeHandlers:
			for _id in self.nodes:
				node = self.nodes[_id]
				if "tags" in node:
					for handler in nodeHandlers:
						if handler.condition(node["tags"], node):
							nodeFunction(node, handler)
							continue

	def parse(self, **kwargs):
		def wayFunction(way, handler):
			handler.handler(way, self, kwargs)
		def nodeFunction(node, handler):
			handler.handler(node, self, kwargs)
		self.iterate(wayFunction, nodeFunction)

	def calculateExtent(self):
		def wayFunction(way, handler):
			wayNodes = way["nodes"]
			for node in range(len(wayNodes)-1): # skip the last node which is the same as the first ones
				nodeFunction(self.nodes[wayNodes[node]])
		def nodeFunction(node, handler=None):
			lon = node["lon"]
			lat = node["lat"]
			if lat<self.minLat: self.minLat = lat
			elif lat>self.maxLat: self.maxLat = lat
			if lon<self.minLon: self.minLon = lon
			elif lon>self.maxLon: self.maxLon = lon
		self.iterate(wayFunction, nodeFunction)


from collections import deque
import sys
input = sys.stdin.readline

def main():

    n = int(input())

    cnt = 0
    # lst = [1,1,1,1,1,1,1,1,1]
    lst = deque([1, 1, 1, 1, 1, 1, 1, 1, 1])
    lst = deque([1, 1, 1, 1, 1])
    for i in range(n-1):
        temp = deque([0, 0, 0, 0, 0])
        temp[0] = lst[0] + lst[1]
        temp[1] = lst[0] + lst[1] + lst[2]
        temp[2] = lst[1] + lst[2] + lst[3]
        temp[3] = lst[2] + lst[3] + lst[4]
        temp[4] = lst[3]*2 + lst[4]
        # for j in range(len(temp)):
        # for j in range(1,5):
        #     temp[j] = lst[j-1] + lst[j] + lst[j+1]
        # temp[5] = temp[3]
        # temp[6] = temp[2]
        # temp[7] = temp[1]
        # if j == 0:
        #     temp[j] = lst[j] + lst[j+1]
        # elif j == 8:
        #     temp[j] = lst[j-1] + lst[j]
        # else:
        #     temp[j] = lst[j-1] + lst[j] + lst[j+1]
        # print(temp)
        lst = temp

    for i in range(len(lst)):
        if i != 4:
            cnt += lst[i]*2
        else:
            cnt += lst[i]

    print(cnt % 998244353)

main()


import cv2 #thu vien xu li anh
import numpy as np  #thu vien toan hoc

#Đọc ảnh màu dùng thư viện OpenCV
img = cv2.imread('girl.jpg', cv2.IMREAD_COLOR)

#Lay kich thuoc cua anh
height, width, channel = img.shape

#Khai bao 3 bien de chua gia tri 4 kenh C,M,Y,K
cyan = np.zeros(( height, width,3), np.uint8)
magenta = np.zeros(( height, width, 3), np.uint8)
yellow = np.zeros(( height, width, 3), np.uint8)
black = np.zeros(( height, width, 3), np.uint8)

#Ban dau set zero cho tat ca cac diem anh co trong 3 kenh
cyan[:] = [0,0,0]
magenta[:] = [0,0,0]
yellow[:] = [0,0,0]
black[:] = [0,0,0]

#Dung vong for de doc het cac diem anh
for x in range(width):
    for y in range(height):

        #Lay gia tri R,G,B cua tung pixel va gan vao cac bien R,G,B
        R = img[y,x,2]
        G = img[y,x,1]
        B = img[y,x,0]
        #Gan gia tri min cua R,G,B vao bien K
        K = min(R,G,B)

        #Cyan la ket hop cua Green va Blue
        cyan[y,x,1] = G
        cyan[y,x,0] = B

        #Magenta la ket hop cua Red va Blue
        magenta[y,x,2] = R
        magenta[y,x,0] = B

        #Yellow la ket hop cua Red va Green
        yellow[y,x,2] = R
        yellow[y,x,1] = G

        #Black tao nen khi gan min(R,G,B) vao ca 3 kenh R,G,B
        black[y,x,2] = K
        black[y,x,1] = K
        black[y,x,0] = K

#Hien thi 4 tam hinh tren cung mot cua so
vert=np.concatenate((cyan,magenta),axis=0)
vert1=np.concatenate((yellow,black),axis=0)
vert2=np.concatenate((vert,vert1),axis=1)

#Dieu chinh kich thuoc cua so hien thi
CMYK_program = cv2.resize(vert2,(700,700))

#Hiển thị hình dùng thư viện OpenCV
cv2.imshow('Anh goc', img)
cv2.imshow('Chuyen RGB sang CMYK', CMYK_program)

#Bấm phím bất kì để đóng cửa sổ hiển thị hình
cv2.waitKey(0)

#Giai phong bo nho
cv2.destroyAllWindows()


import sys
import random
from PyQt5.QtWidgets import (QWidget, QToolTip,QPushButton,QLabel, QApplication,QLCDNumber,QTextEdit, QSlider, QVBoxLayout,QMainWindow,QCheckBox,QFrame,QProgressBar,QCalendarWidget,QAction, qApp)
from PyQt5.QtGui import (QIcon,QFont,QColor,QPixmap)
from PyQt5.QtCore import Qt
from PyQt5.QtCore import pyqtSignal, QObject,QBasicTimer,QDate,QMetaObject,QSize,QRect,QTimer

class Window(QMainWindow):
    resized = pyqtSignal()
    click=pyqtSignal()
    def  __init__(self, parent=None):
        super().__init__()
        self.j=0

        self.UI()
    def UI(self):
        self.btn_mas=[]
        self.label_mas=[]
        self.image_mas=[]
        self.btn_x=0
        self.btn_y=100
        self.width_btn=150

        self.height_btn=300

        self.resized.connect(self.someFunction)
        self.centralwidget=QWidget(self)
        self.setWindowTitle('Resize')
        self.resize(1600,1600)

        self.CreateLabel()
        self.CreateImage()
        self.CreateButton()

        self.show()
    def CreateImage(self):
        mas_image=[]
        for i in range(9):
             path='{}'.format(i)+'.jpg'
             print(path)
             pixmap1=QPixmap(path)
             pixmap1=pixmap1.scaled(QSize(150,300))
             mas_image.append(pixmap1)

        return mas_image
    def CreateLabel(self):
        mas=[]
        self.label_number=[]
        mas_image=self.CreateImage()
        print(mas_image)

        for x in range (0, 30):
             num = random.randint(0, 30)
             while num in mas:
                 num = random.randint(0, 30)
             mas.append(num)

        j=0
        for i in range(30):

            if self.btn_x>1500:
                self.btn_x=0
                self.btn_y+=302

            label=QLabel(self)
            label.setGeometry(self.btn_x,self.btn_y,self.width_btn,self.height_btn)

            if j>8:
                j=0

            label.setPixmap(mas_image[j])
            self.label_number.append(str(j))
            j+=1
            label.setVisible(True)

            self.label_mas.insert(mas[i],label)

            self.btn_x+=160

    def CreateButton(self):

        self.j+=1

        self.btn_x=0
        self.btn_y=100

        for i in range(30):

            if self.btn_x>1500:
                self.btn_x=0
                self.btn_y+=302
            self.btn=QPushButton(self)

            self.btn.setGeometry(self.btn_x,self.btn_y,self.width_btn,self.height_btn)
            pixmap=QPixmap('10.jpg')

            pixmap=pixmap.scaled(QSize(150,300))

            self.btn.setIcon(QIcon(pixmap))

            self.btn.setIconSize(QSize(150,300))

            self.btn.setVisible(True)

            self.btn_x+=160
            self.btn.clicked.connect(self.Click)

            self.btn_mas.append(self.btn)

    def Click(self):
        j=0

        sender=self.sender()
        print(sender,'sender')
        for i in self.btn_mas:
          if sender==i:

            (self.btn_mas[j].setVisible(False))
            break
          j+=1
          print(j)

        print(self.label_number[j],'mas')

    def Button(self,event):
        print(self.sender().text())
    def resizeEvent(self, event):
        self.resized.emit()
        return super(Window, self).resizeEvent(event)

    def someFunction(self):
        print(self.width())

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())

Код урока последний.py

Код урока последний.py


import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt
from vpython import *
import time
#define constants
m1 = 2
m2 = 1
L1 = 1
L2 = 2

g=9.81
dt = 0.001
tmax = 30

theta1_0 = np.pi/1
theta2_0 = 0.1
omega1_0 = 0.0
omega2_0 = 0.0

initial = (theta1_0, omega1_0, theta2_0, omega2_0)

#set up scene
mainScene = canvas(title = "Double Pendulum", height = 700, width = 1000, background = color.green, align = "left")
mainScene.camera.pos = vector(0, -(L1+L2)/2, 0)

def randomise():
    '''generates a pendulum with randomised starting conditions'''
    global m1, m2, L1, L2
    m1 = np.random.uniform(low = 0.1, high = 10)
    m2 = np.random.uniform(low = 0.1, high = 10)
    L1 = np.random.uniform(low = 0.1, high = 10)
    L2 = np.random.uniform(low = 0.1, high = 10)

def sin(x):
    return(np.sin(x))

def cos(x):
    return(np.cos(x))

t=np.linspace(0, tmax, int(tmax/dt)) #array with all times

def int_dpendulum_sim(initial, t):

    theta1, omega1, theta2, omega2 = initial

    c = cos(theta1-theta2)
    s = sin(theta1-theta2)

    theta1_dot = omega1
    omega1_dot = ( (m2*g*sin(theta2)*c) - (m2*s*(L1*omega1**2*c + L2*omega2**2)) - ((m1+m2)*g*sin(theta1))) / (L1* (m1 + m2*s**2))

    theta2_dot = omega2
    omega2_dot = ( (m1+m2)*(L1*omega1**2*s - g*sin(theta2) + g*sin(theta1)*c) + m2*L2*omega2**2*s*c) / ( L2*(m1 + m2*s**2) )

    return theta1_dot, omega1_dot, theta2_dot, omega2_dot

#perform numerical integration
y = integrate.odeint(int_dpendulum_sim, initial, t)

#Get omegas and thetas as functions of time
theta1 = np.zeros(int(tmax/dt))
omega1 = np.zeros(int(tmax/dt))
theta2 = np.zeros(int(tmax/dt))
omega2 = np.zeros(int(tmax/dt))
for i in range(int(tmax/dt)):
    theta1[i] = y[i][0]
    omega1[i] = y[i][1]
    theta2[i] = y[i][2]
    omega2[i] = y[i][3]

#convert to cartesian coords
x1 = L1*sin(theta1)
y1 = -L1*cos(theta1)
x2 = x1+L2*sin(theta2)
y2 = y1-L2*cos(theta2)
print(x1)

def graphing():
    plt.plot(t, x1)
    plt.show()

def animate():
    gd = graph(title = "energy graph",
              ytitle = "Energy (J)",
              xtitle = "Time (s)",
              align = "right")
    gpe_graph = gcurve(color = color.red, label = "GPE")
    ke_graph = gcurve(color = color.blue, label = "KE")
    total_graph = gcurve(color = color.green, label = "Total Energy")

    rod1 = curve(vector( x1[0], y1[0], 0 ), vector(0,0,0), color = color.red)
    rod2 = curve(vector( x2[0], y2[0], 0 ), vector( x1[0], y1[0], 0 ), color = color.blue)
    ball1 = sphere(pos = vector( x1[0], y1[0], 0 ),
                  radius = 0.1, color = color.red, make_trail = True, retain = 50)

    ball2 = sphere(pos = vector( x2[0], y2[0], 0 ),
                  radius = 0.1, color = color.blue, make_trail = True, retain = 50)

    for i in range(int(tmax/dt)):

        rod1.modify(0, pos = vector( x1[i], y1[i], 0 ))
        rod2.modify(0, pos = vector( x2[i], y2[i], 0 ))
        rod2.modify(1, pos = vector( x1[i], y1[i], 0 ))
        ball1.pos = vector( x1[i], y1[i], 0 )
        ball2.pos = vector( x2[i], y2[i], 0 )

        #plot graphs:
        GPE = m1*g*(L1+L2+y1[i]) + m2*g*(L1+L2+y2[i])
        gpe_graph.plot(t[i], GPE)
        KE = 0.5*( m1*L1**2*omega1[i]**2 + m2*( L1**2*omega1[i]**2 + L2**2*omega2[i]**2 + 2*L1*L2*omega1[i]*omega2[i]*cos(theta1[i]-theta2[i])) )
        ke_graph.plot(t[i], KE)
        total_graph.plot(t[i], KE+GPE)
        time.sleep(dt/100)

animate()


from typing import List, Optional, Union

import mlir.astnodes as ma
from mlir.builder.builder import DialectBuilder

from .astnodes import FunctionTypeAttr, GenericModule, GenericOperation, QuotedStr, StringAttr
from .common import ReturnValue

class BaseDialectException(Exception):
    pass

class MLIRDialectBuilder(DialectBuilder):
    """Implement base dialect features."""

    def call(
        self,
        func_name: str,
        operands: List[ReturnValue] = [],
        return_types: List[ma.Type] = []
    ) -> Union[ReturnValue, List[ReturnValue], None]:
        name: QuotedStr = QuotedStr("func.call")

        op: GenericOperation = GenericOperation(
            name=name,
            args=[op.sym for op in operands],
            successors=None,
            regions=None,
            attributes=ma.AttributeDict([
                ma.AttributeEntry("callee", ma.SymbolRefAttr([ma.SymbolRefId(func_name)]))
            ]),
            type=[ma.FunctionType([op.type for op in operands], return_types)]
        )

        results: Union[ma.SsaId, List[ma.SsaId], None]
        results = self.core_builder._insert_op_in_block([None] * len(return_types), op)

        if results is None:
            return None
        if not isinstance(results, list):
            return ReturnValue(results, return_types[0])

        if len(results) != len(return_types):
            raise BaseDialectException("unexpected results length")

        return [
            ReturnValue(result, return_type)
            for result, return_type in zip(results, return_types)
        ]

    def func(
        self,
        name: str,
        region: Optional[ma.Region] = None,
        operands: List[ReturnValue] = [],
        return_types: List[ma.Type] = [],
        insert: bool = False
    ) -> GenericOperation:
        operand_names: List[ma.SsaId] = [op.sym for op in operands]
        operand_types: List[ma.Type] = [op.type for op in operands]

        if region is None:
            region = ma.Region([
                ma.Block(ma.BlockLabel(ma.BlockId("bb0"), operand_names, operand_types), [])
                if operands else ma.Block(None, [])
            ])

        func: GenericOperation = GenericOperation(
            name=QuotedStr("func.func"),
            args=[],
            successors=None,
            regions=[region],
            attributes=ma.AttributeDict([
                ma.AttributeEntry("sym_name", StringAttr(name)),
                ma.AttributeEntry("function_type", FunctionTypeAttr(
                    ma.FunctionType(operand_types, return_types)
                ))
            ]),
            type=[ma.FunctionType([], [])]
        )

        if insert:
            self.core_builder._insert_op_in_block([], func)

        return func

    def module(self, region: Optional[ma.Region] = None) -> GenericModule:
        if region is None:
            region = ma.Region([ma.Block(None, [])])

        return GenericModule(
            name=QuotedStr("builtin.module"),
            args=[],
            region=region,
            attributes=None,
            type=ma.FunctionType([], [])
        )

    def return_op(self, results: List[ReturnValue]) -> None:
        self.core_builder._insert_op_in_block(
            [],
            GenericOperation(
                name=QuotedStr("func.return"),
                args=[res.sym for res in results],
                successors=None,
                regions=None,
                attributes=None,
                type=[ma.FunctionType([res.type for res in results], [])]
            ))


# ade20k.py
import multiprocessing as mp
from typing import Any, Optional

from datasets import load_dataset

from gate.boilerplate.decorators import configurable
from gate.config.variables import DATASET_DIR
from gate.data.core import GATEDataset
from gate.data.image.segmentation.classes import ade20_classes as CLASSES
from gate.data.transforms.segmentation import (
    BaseDatasetTransforms,
    KeySelectorTransforms,
)

def build_dataset(set_name: str, data_dir: Optional[str] = None) -> dict:
    """
    Build a Food-101 dataset using the Hugging Face datasets library.

    Args:
        data_dir: The directory where the dataset cache is stored.
        set_name: The name of the dataset split to return ("train", "val", or "test").

    Returns:
        A dictionary containing the dataset split.
    """
    data = load_dataset(
        "Chris1/cityscapes_segmentation",
        "instance_segmentation",
        cache_dir=data_dir,
        num_proc=mp.cpu_count(),
    )

    dataset_dict = {
        "train": data["train"],
        "val": data["validation"],
        "test": data["test"],
    }

    return dataset_dict[set_name]

# NSD and DSC for metrics, and also ensure that the model can compute per class metrics

@configurable(
    group="dataset", name="cityscapes", defaults=dict(data_dir=DATASET_DIR)
)
def build_gate_dataset(
    data_dir: Optional[str] = None,
    transforms: Optional[Any] = None,
    num_classes=len(CLASSES),
    image_size=1024,
    target_image_size=256,
    ignore_index=0,
) -> dict:
    input_transforms = KeySelectorTransforms(
        initial_size=2048,
        image_label="image",
        label_label="semantic_segmentation",
    )

    train_transforms = BaseDatasetTransforms(
        input_size=image_size,
        target_size=target_image_size,
        crop_size=image_size,
        flip_probability=0.5,
        use_photo_metric_distortion=True,
    )

    eval_transforms = BaseDatasetTransforms(
        input_size=image_size,
        target_size=target_image_size,
        crop_size=None,
        flip_probability=None,
        use_photo_metric_distortion=False,
    )

    train_set = GATEDataset(
        dataset=build_dataset("train", data_dir=data_dir),
        infinite_sampling=True,
        transforms=[input_transforms, train_transforms, transforms],
        meta_data={"class_names": CLASSES, "num_classes": num_classes},
    )

    val_set = GATEDataset(
        dataset=build_dataset("val", data_dir=data_dir),
        infinite_sampling=False,
        transforms=[input_transforms, eval_transforms, transforms],
        meta_data={"class_names": CLASSES, "num_classes": num_classes},
    )

    test_set = GATEDataset(
        dataset=build_dataset("test", data_dir=data_dir),
        infinite_sampling=False,
        transforms=[input_transforms, eval_transforms, transforms],
        meta_data={"class_names": CLASSES, "num_classes": num_classes},
    )

    dataset_dict = {"train": train_set, "val": val_set, "test": test_set}
    return dataset_dict


import sqlite3 as lite
#Script to write our test data
conn = lite.connect('test.db')
c = conn.cursor()
def start():
    print("Starting the program that allows you to insert data into a test data base file")
    fileCreation()
def fileCreation():
    print("Creating the database file")
    print("Connected to file")
    c.execute("CREATE TABLE Identificaiton(RunnerID TEXT, RunnerName TEXT)")
    c.execute("CREATE TABLE Stats(Race1 TEXT, Race2 TEXT, Race3 TEXT, Race4 TEXT, Race5)")
    c.execute("CREATE TABLE Team(Avg TEXT)")
    print("Done with file creation")
    fileManipulation()
def fileManipulation():
    #It's a test file you don't need this many damn variables but ok
    print("Starting file manipulation")
    a = str(1)
    b = "John, Rancer"
    c.execute("INSERT INTO Identification(RunnerID, RunnerName) VALUES('"+a+"', '"+b+"')")
    d = "5:50"
    e = "9:50"
    f = "10:30"
    pb = "9:50"
    mile = "9:02"
    c.execute("INSERT INTO Stats(Race1, Race2, Race3, Race4, Race5) VALUES('"+d+"', '"+e+"', '"+f+"', '"+pb+"', '"+mile+"')")
    ravg = "10:02"
    mavg = "8:30"
    c.execute("INSERT INTO Team(Avg) VALUES('"+ravg+"', '"+mavg+"')")
    print("done")

start()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""     Behavioural model fit -- Version 3.1.4
Last edit:  2022/09/24
Author(s):  Geysen, Steven (SG)
Notes:      - Fit models to behavioural data of Marzecova et al. (2019)
            - Release notes:
                * Increased range beta options

To do:      - Fit models
            - Statistics

Questions:

Comments:   AM: The data file was merged in R, from the single files generated
                in Matlab (they are also attached) - they include parameters
                from Yu & Dayan's (2005) computational model.
                The columns contain:
                    * 'id' - participants id
                    * 'block' - block # of the task
                    * 'trial' - trial # of the task
                    * 'relCue' - direction of the relevant cue
                        (1: left / 2: right)
                    * 'irrelCue'- direction of the irrelevant cue
                        (1: left / 2: right)
                    * 'validity' - validity with respect to the relevant cue
                    * 'targetLoc' - location of the target (1: left / 2: right)
                    * 'relCueCol' - color of the relevant cue
                        (1: white / 2: black)
                    * 'gammaBlock' - the validity level within the block
                    * 'RT' - response time in ms
                    * 'correct' - if the response was correct: 1, if missed: 3
                        if incorrect button: 2 (e.g., left button instead of
                        right)
                    * 'I' - parameter I from the Yu & Dayan's (2005)
                        approximate algorithm
                    * 'guessCue' - the cue which is currently assumed to be
                        correct
                    * 'Switch' - count of trials between assumed switches of
                        the cue
                    * 'Lamda' - lamda parameter from Yu & Dayan's (2005)
                        approximate algorithm - unexpected uncertainty
                    * 'Gamma' - gamma parameter from Yu & Dayan's (2005)
                        approximate algorithm - expected uncertainty
                    * 'pMui' - probability that the current context is correct
                    * 'pMuNotI'- probability that the current  context is not
                        correct
                    * 'pe' - prediction error reflecting divergence from the
                        prediction on current trial (combines Lamda and Gamma)
                    * 'logRTmod' - log prediction error
                    * 'logRTexp" - log RT

Sources:    https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fmin.html
            https://docs.scipy.org/doc/scipy/reference/tutorial/optimize.html#nelder-mead-simplex-algorithm-method-nelder-mead
            Remove NaN from array ( https://stackoverflow.com/a/11620982 )
            https://theprogrammingexpert.com/python-remove-nan-from-list/
"""

#%% ~~ Imports and directories ~~ %%#

import time

import numpy as np
import pandas as pd

import fns.assisting_functions as af
import fns.behavioural_functions as bf
import fns.plot_functions as pf
import matplotlib.pyplot as plt

from pathlib import Path
from scipy import optimize, stats

# Directories
SPINE = Path.cwd().parent
DATA_DIR = SPINE / 'data'
OUT_DIR = SPINE / 'results'
if not Path.exists(OUT_DIR):
    Path.mkdir(OUT_DIR)

#%% ~~ Variables ~~ %%#

# Uncertainty data
un_data = pd.read_csv(DATA_DIR / 'UnDataProjectSteven.csv')
## Rescale 1-2 to 0-1
scaList = ['relCue', 'irrelCue', 'validity', 'targetLoc', 'relCueCol']
un_data.loc[:, (scaList)] = abs(un_data.loc[:, (scaList)] - 1)
## Separate data sets for convenience
valid_data = un_data[un_data['validity'] == 0]
invalid_data = un_data[un_data['validity'] == 1]

# Number of iterations
N_ITERS = 10
# Models with optimiseable parameters
# MDLS = ['RW', 'H', 'M']
MDLS = ['RW', 'H']
# Number of participants
npp = un_data['id'].max()
# Number of trials in bin
binsize = 15

# Alpha/eta options
alpha_options = np.linspace(0.01, 1, 20)
# Beta options
##SG: The SoftMax policy needs a high beta value for the model to be accurate
    # (see simulations). Therefore it is not usefull to look at beta values
    # smaller than 10.
beta_options = np.linspace(0.1, 20, 20)

# Plot specs
## Plot number
plotnr = 0
## Plot labels
plabels = ['Valid trials', 'Invalid trials']
## Model labels
models = af.labelDict()
##SG: To have the smallest alpha and beta values in the same corner (left-down)
plotbetas = np.flip(beta_options)

#%% ~~ Exploration ~~ %%#
#########################

#%% ~~ RT split ~~ %%#
#--------------------#
"""
Trying to answer "Can I know the participant's selection?"

The reasoning is that RT under the median are fast RTs, and fast RTs should be
more prevalent on congruent trials. Slow RTs are then a stand in for
incongruent. This plot is to see how well this assumption can be seen in the
behavioural data.

DOES NOT WORK!
"""

# Participant loop
for ppi in range(npp):
    ## Skip pp6 (not in data)
    if ppi + 1 == 6:
        continue
    ## Use only data from pp
    pp_data = un_data[un_data['id'] == ppi + 1]

    # Median RT
    ##SG: Excluded NaN values when computing the result.
    median_rt = pp_data['RT'].median()
    pp_data.loc[:, ('selCue_PP')] = np.where(pp_data['RT'] < median_rt,
                                             pp_data['relCueCol'],
                                             abs(1 - pp_data['relCueCol']))
    pf.selplot(pp_data, 'pp', plotnr, pp=ppi)
    plotnr += 1

#%% ~~ Plots ~~ %%#
#-----------------#

# RT distribution plot
# --------------------
fig, ax = plt.subplots()
ax.hist(valid_data['RT'], bins = 30, alpha = 0.5, label=plabels[0])
ax.hist(invalid_data['RT'], bins = 30, alpha = 0.5, label=plabels[1])

fig.suptitle('RT distribution participants', fontsize=14)
ax.set_xlabel('Response times (s)')
ax.set_ylabel('Count')
ax.legend()

plt.show()
plotnr += 1

# RT validity effect
# ------------------
valrt = np.asarray(valid_data['RT'])
invalrt = np.asarray(invalid_data['RT'])
## Remove NaN values
rt_data = [valrt[~np.isnan(valrt)], invalrt[~np.isnan(invalrt)]]

fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(9, 4))
fig.suptitle('Validity effect')
vplot, bplot = axs[0], axs[1]
## Violin plot
vplot.violinplot(rt_data,
                  showmeans=False,
                  showmedians=True)
vplot.set_title('Violin plot participants')
## Box plot
bplot.boxplot(rt_data)
bplot.set_title('Box plot participants')

for ax in axs:
    ax.yaxis.grid(True)
    ax.set_xticks([y + 1 for y in range(len(rt_data))],
                  labels=plabels)
    ax.set_xlabel('Trial type')
    ax.set_ylabel('Response times')

plt.show()
plotnr += 1

# RTs over time
# -------------
first_bin = []
last_bin = []

for ppi in range(npp):
    ## Skip pp6 (not in data)
    if ppi + 1 == 6:
        continue
    ## Use only data from pp
    pp_data = un_data[un_data['id'] == ppi + 1]
    pp_data.reset_index(drop=True, inplace=True)
    pp_rt = pp_data['RT']

    lag_relCueCol = pp_data.relCueCol.eq(pp_data.relCueCol.shift())
    switches = np.where(lag_relCueCol == False)[0]

    ## Bin RT of first and last b trials
    for starti, endi in af.pairwise(switches):
        first_bin.append(np.nanmean(pp_rt[starti:starti + binsize]))
        last_bin.append(np.nanmean(pp_rt[endi - binsize:endi + 1]))

    ## Length of switch bars depends on values of participant
    barlen = (np.nanmin(pp_rt) + (np.nanmin(pp_rt) * 0.1),
              np.nanmax(pp_rt) + (np.nanmax(pp_rt) * 0.1))

    # RT curve
    plt.figure(plotnr)
    plt.suptitle(f'RT curve participant {ppi}', y=.99)
    plt.plot(pp_rt, label='RT')
    plt.vlines(switches[1:], barlen[0], barlen[1], colors='black')

    plt.xlabel('Trials')
    plt.ylabel('Response time (s)')
    plt.ylim(barlen[0] - 50, barlen[1] + 100)

    plt.legend()
    plt.tight_layout()

    plt.show()
    plotnr += 1

# Binned RT
## Remove NaN values
firstlist = [i for i in first_bin if np.isnan(i) == False]
lastlist = [i for i in last_bin if np.isnan(i) == False]
plotbins = [firstlist, lastlist]

fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(9, 4))
fig.suptitle('Mean binned RT')
vplot, bplot = axs[0], axs[1]
## Violin plot
vplot.violinplot(plotbins,
                  showmeans=False,
                  showmedians=True)
vplot.set_title('Violin plot participants')
## Box plot
bplot.boxplot(plotbins)
bplot.set_title('Box plot participants')

for ax in axs:
    ax.yaxis.grid(True)
    ax.set_xticks([y + 1 for y in range(len(plotbins))],
                  labels=[f'First {binsize} trials',
                          f'Last {binsize} trials'])
    ax.set_xlabel('Trial numbers')
    ax.set_ylabel('Response times')

plt.show()
plotnr += 1

# =============================================================================
# Output numbers
# =============================================================================
print('RT valid trials')
print('mean', np.nanmean(valid_data['RT']), np.nanstd(valid_data['RT']))
print('RT invalid  trials')
print('mean', np.nanmean(invalid_data['RT']), np.nanstd(invalid_data['RT']))

print(f'First {binsize} trials')
print('mean', np.nanmean(first_bin), np.nanstd(first_bin))
print(f'Last {binsize} trials')
print('mean', np.nanmean(last_bin), np.nanstd(last_bin))
## Quick check if different enough
print('Paired t-test')
print(stats.ttest_rel(first_bin, last_bin, nan_policy='omit'))

#%% ~~ Fitting ~~ %%#
#####################

#%% ~~ SoftMax ~~ %%#
#-------------------#

#%% ~~ Grid search ~~ %%#

gridThetas = np.full((npp, len(MDLS), 2), np.nan)

start_total = time.time()
for ppi in range(npp):
    ## Skip pp6 (not in data)
    if ppi + 1 == 6:
        continue
    ## Use only data from pp
    pp_data = un_data[un_data['id'] == ppi + 1]
    pp_data.reset_index(drop=True, inplace=True)
    one_totpp = np.zeros((len(alpha_options), len(beta_options), len(MDLS)))

    start_pp = time.time()
    for locm, modeli in enumerate(MDLS):
        for loca, alphai in enumerate(alpha_options):
            for locb, betai in enumerate(beta_options):
                for iti in range(N_ITERS):
                    one_totpp[loca, locb, locm] += bf.pp_negSpearCor(
                        (alphai, betai), pp_data, model=modeli, asm='soft'
                        )
        modeldata = one_totpp[:, :, locm] / N_ITERS
        # Optimal values
        toploc=[i[0] for i in np.where(one_totpp == np.min(one_totpp))]
        gridThetas[ppi, locm, :] = [alpha_options[toploc[0]], beta_options[toploc[1]]]

        # Intermittent checking
        if ppi % 2 == 0:
            fig, ax = plt.subplots()
            im, _ = pf.heatmap(np.rot90(one_totpp[:, :, locm]),
                               np.round(plotbetas, 3),
                               np.round(alpha_options, 3), ax=ax,
                               row_name='$\u03B2$', col_name='$\u03B1$',
                               cbarlabel='Negative Spearman Correlation')
            plt.suptitle(f'Grid search Negative Spearman Correlation of choice {ppi}')
            plt.show()
            plotnr += 1
    print(f'Duration pp {ppi}: {round((time.time() - start_pp) / 60, 2)} minutes')
print(f'Duration total: {round((time.time() - start_total) / 60, 2)} minutes')

# Save optimal values
##SG: Remove empty row of participant 6
# gridThetas = np.delete(gridThetas, 5, 0)
for locm, modeli in enumerate(MDLS):
    title = f'pp_gridsearch_{N_ITERS}iters_softmax_{modeli}.csv'
    pd.DataFrame(gridThetas[:, locm, :],
                 columns=['alpha', 'beta']).to_csv(OUT_DIR / title)

#%% ~~ Nelder - Mead ~~ %%#

initial_guess = np.full((npp, N_ITERS, 2), np.nan)
nmThetas = np.zeros((npp, len(MDLS), 2))

start_total = time.time()
for ppi in range(npp):
    ## Skip pp6 (not in data)
    if ppi + 1 == 6:
        continue
    ## Use only data from pp
    pp_data = un_data[un_data['id'] == ppi + 1]
    pp_data.reset_index(drop=True, inplace=True)

    start_pp = time.time()
    for iti in range(N_ITERS):
        initial_guess[ppi, iti, :] = (np.random.choice(alpha_options),
                                      np.random.choice(beta_options))
        for locm, modeli in enumerate(MDLS):
            nmThetas[ppi, locm, :] += optimize.fmin(
                bf.pp_negSpearCor, initial_guess[ppi, iti, :],
                args=(pp_data, modeli), ftol=0.001)
    print(f'Duration pp {ppi}: {round((time.time() - start_pp) / 60, 2)} minutes')
print(f'Duration total: {round((time.time() - start_total) / 60, 2)} minutes')

nmThetas /= N_ITERS
# Save optimal values
# nmThetas = np.delete(gridThetas, 5, 0)
for locm, modeli in enumerate(MDLS):
    title = f'pp_NelderMead_{N_ITERS}iters_softmax_{modeli}.csv'
    pd.DataFrame(nmThetas[:, locm, :],
                 columns=['alpha', 'beta']).to_csv(OUT_DIR / title)

# Correlation plot
fig, axs = plt.subplots(nrows=1, ncols=2)
fig.suptitle('Parameter estimation Nelder-Mead')
for pari, ax in enumerate(axs):
    for locm, modeli in enumerate(MDLS):
        ax.plot(nmThetas[:, locm, pari], 'o', label=f'{models[modeli]}')
    ax.set_ylabel('Initial guess')

axs[0].set_xticks(np.round(alpha_options, 3))
axs[0].set_xlabel('Mean estimated alpha/eta values')
axs[0].set_yticks(np.round(alpha_options, 3))
axs[1].set_xlabel('Mean estimated beta values')
axs[1].set_yticks(np.round(beta_options, 3))
plt.legend()

plt.show()
plotnr += 1

#%% ~~ Argmax ~~ %%#
#------------------#

##SG: +1 to store optimal values
gridThetas = np.zeros((npp, len(MDLS), len(alpha_options) + 1))

start_total = time.time()
for ppi in range(npp):
    ## Skip pp6 (not in data)
    if ppi + 1 == 6:
        continue
    ## Use only data from pp
    pp_data = un_data[un_data['id'] == ppi + 1]
    pp_data.reset_index(drop=True, inplace=True)

    start_pp = time.time()
    for locm, modeli in enumerate(MDLS):
        for loca, alphai in enumerate(alpha_options):
            for iti in range(N_ITERS):
                gridThetas[ppi, locm, loca] += bf.pp_negSpearCor((alphai, ),
                                                                 pp_data,
                                                                 model=modeli)
        modeldata = gridThetas[ppi, locm, :-1] / N_ITERS
        # Optimal values
        toploc = [i[0] for i in np.where(modeldata == np.min(modeldata))]
        gridThetas[ppi, locm, -1] = alpha_options[toploc[0]]

        # Intermittent checking
        if ppi % 2 == 0:
            pf.heatmap_1d(modeli, modeldata, toploc, alpha_options,
                          gridThetas[ppi, :, -1])
            plotnr += 1
    print(f'Duration pp {ppi}: {round((time.time() - start_pp) / 60, 2)} minutes')
    print(gridThetas[ppi, :, -1])
print(f'Duration total: {round((time.time() - start_total) / 60, 2)} minutes')
# Save optimal values
title = f'pp_gridsearch_{N_ITERS}iters_argmax.csv'
##SG: Remove empty row of participant 6
# gridThetas = np.delete(gridThetas, 5, 0)
pd.DataFrame(gridThetas[:, :, -1], columns=MDLS).to_csv(OUT_DIR / title)

##SG: Paired t-test to see if the difference between the estimated model
    # parameters is big.
print(stats.ttest_rel(gridThetas[:, 0, -1], gridThetas[:, 1, -1],
                      nan_policy='omit'))

#%% ~~ Nelder - Mead ~~ %%#

initial_guess = np.full((npp, N_ITERS), np.nan)
nmThetas = np.zeros((npp, len(MDLS)))

start_total = time.time()
for ppi in range(npp):
    ## Skip pp6 (not in data)
    if ppi + 1 == 6:
        continue
    ## Use only data from pp
    pp_data = un_data[un_data['id'] == ppi + 1]
    pp_data.reset_index(drop=True, inplace=True)

    start_pp = time.time()
    for iti in range(N_ITERS):
        initial_guess[ppi, iti] = np.random.choice(alpha_options)
        for locm, modeli in enumerate(MDLS):
            nmThetas[ppi, locm] += optimize.fmin(bf.pp_negSpearCor,
                                                  (initial_guess[ppi, iti], ),
                                                  args=(pp_data, modeli, 'arg'),
                                                  ftol=0.001)
    print(f'Duration pp {ppi}: {round((time.time() - start_pp) / 60, 2)} minutes')

    if ppi % 2 == 0:
        print(initial_guess)
        print(nmThetas[ppi])
print(f'Duration total: {round((time.time() - start_total) / 60, 2)} minutes')

nmThetas /= N_ITERS
# Save optimal values
title = f'pp_NelderMead_{N_ITERS}iters_argmax.csv'
# nmThetas = np.delete(gridThetas, 5, 0)
pd.DataFrame(nmThetas, columns=MDLS).to_csv(OUT_DIR / title)

# Correlations
yvals = np.array(list(set(initial_guess)))

fig, ax = plt.subplots()
fig.suptitle('Parameter estimation Nelder-Mead')
for locm, modeli in enumerate(MDLS):
    print(modeli)
    print(stats.ttest_rel(nmThetas[:, locm], initial_guess,
                          nan_policy='omit'))
    # Plot
    ax.plot(nmThetas[:, locm], 'o', label=f'{models[modeli]}')

ax.set_xlabel('Mean estimated values')
ax.set_ylabel('Initial guess')
ax.set_yticks(np.round(yvals, 3))
plt.legend()

plt.show()
plotnr += 1

# ------------------------------------------------------------------------ End


# -*- coding: utf-8 -*-
"""
Created on Tue Dec  8 11:37:46 2020
@author: Asus
"""
import pyttsx3
import speech_recognition
import datetime
import wikipedia
import os
import sys
import time
import dateorganisemain as dom
import duplicatesimilarnewmain as dsm
import facegrouping as fg
from tkinter.filedialog import askopenfilename
from tkinter import Tk
from youtubesearchpython import VideosSearch

engine = pyttsx3.init('sapi5')
voices = engine.getProperty('voices')
mode=''

def slowPrint(text):
  for character in text:
    sys.stdout.write(character)
    sys.stdout.flush()
    time.sleep(0.03)

def speak(sentence):
    engine.say(sentence)
    engine.runAndWait()

def mode_choose():
    global mode
    mode=input("Please Choose Command Mode For This Session:\nV for Voice\nT for Manual Typing\n")
    if(mode!='v' and mode!='V' and mode!='T' and mode!='t'):
        print("Try Again")
        mode_choose()

def voice_choose():
    slowPrint("\nChoose between assistant voices:")
    input("Hit Enter to listen to sample Voices")
    engine.setProperty('voice', voices[0].id)
    print("1. Male")
    speak("I am APRRI, your AI Assistant")
    engine.setProperty('voice', voices[1].id)
    print("2. Female")
    speak("I am APRRI, your AI Assistant")
    vIn=input("Choose between M or F: ")
    vIn=vIn.lower()
    if(vIn=='1' or vIn=='m' or vIn=='male'):
        v=0
    elif(vIn=='2' or 'f' in vIn):
        v=1
    else:
        print("Invalid choice, proceeding with default setting")
        return
    print("\nSuccess")
    engine.setProperty('voice', voices[v].id)

def inp():
    r = speech_recognition.Recognizer()
    slowPrint("\nSpeak now ^_^\n")
    with speech_recognition.Microphone() as source:
        r.pause_threshold = 0.5
        audio = r.listen(source)
    try:
        slowPrint("Recognizing...\n")
        speak("Please wait...")
        sentence = r.recognize_google(audio, language='en-in')
        slowPrint(f"Input: {sentence}\n")
    except Exception as e:
        slowPrint("Sorry, kindly repeat...")
        speak("Sorry, kindly repeat...")
        return "none"
    return sentence

def greet():
    hour = int(datetime.datetime.now().hour)
    if hour>=0 and hour<12:
        slowPrint("Good Morning\n")
        speak("Good Morning!")
    elif hour>=12 and hour<18:
        slowPrint("Good Afternoon!\n")
        speak("Good Afternoon!")
    else:
        slowPrint("Good Evening!\n")
        speak("Good Evening!")
    slowPrint("Hope you are doing well\n")
    speak("Hope you are doing well")

def bye():
    hour = int(datetime.datetime.now().hour)
    if hour>=0 and hour<18:
        slowPrint("Have a good day ahead\n")
        speak("Have a good day ahead")
    else:
        slowPrint("Bye bye! Good night!")
        speak("Bye bye! Good night!")

def can_do():
    slowPrint("What APRRI can do:\n")
    can_do_photos()
    print("Other operations include:\n1.Search and play YouTube videos - \'youtube\' \n2.Change input mode - \'change mode\'\n3.Change AI Voice - \'change voice\'\n4.Open a file - \'open\'\n5.Look up Wiki - TERM+\'wikipedia\'\n6.Respond to common questions(BETA)\n")

def can_do_photos():
    speak("Here's how I can help")
    print("\nAPRRI\'s photo operation commands:\n(you can use other terms with the input, just make sure to include these main tiggers)\n1.Organise photos by face - \'Sort by faces\'\n2.Organise photos by month - \'Sort by month\'\n3.Organise photos by year - \'Sort by year\'\n4.Organise selfies and solo shots - \'Selfie\' or \'Solo\'\n5.Find duplicate images - \'duplicates\'\n6.Find similar images (BETA) - \'similar\'\n")

def start():
    hru=0
    error=-1
    print("\n \'help\' for instructions")
    while 1:
        try:
            if(mode=='t'or mode=='T'):
                sentence = input("\nType Here: ")
            elif(mode=='v'or mode=='V'):
                sentence = inp().lower()
            sentence=sentence.lower()
            if 'open' in sentence:
                root = Tk()
                root.withdraw()
                filename = askopenfilename()
                os.startfile(filename)

            elif 'change' in sentence and 'voice' in sentence:
                if(mode=='T' or mode=='t'):
                    print("Loaded available voices. Proceeding now")
                voice_choose()

            elif 'change' in sentence and 'mode' in sentence:
                mode_choose()

            elif 'sort' in sentence and ('person' in sentence or 'face' in sentence):
                print("Let's organise your photos by faces")
                speak("Let's organise your photos by faces")
                slowPrint("Please choose a folder\n")
                speak("Please choose a folder")
                fg.select()
                speak("Working now")
                fg.person_sort()
                print("\nALL DONE! ^_^ Take a look")
                speak("All Done! Take a look")
                os.startfile(fg.location)

            elif 'selfie' in sentence or 'solo' in sentence:
                print("Lets create a separate folder for your solo stills")
                speak("Lets create a separate folder for your solo stills")
                slowPrint("Please choose a folder\n")
                speak("Please choose a folder that has images")
                fg.select()
                slowPrint("Working Now...")
                speak("Working now")
                fg.face_find()
                print("\nALL DONE! ^_^")
                speak("All Done! Take a look")
                os.startfile(fg.location)

            elif 'similar' in sentence:
                print("I will now analyze images based on their similarity to the image you select")
                print("Please choose the folder where the image is located and then the image\n")
                speak("Please choose the folder where the image is located and then the image")
                dsm.similar()
                print("\nALL DONE! Please see the analysis results above")
                speak("All Done! Please see the analysis results above")

            elif 'duplicate' in sentence:
                print("I will now find and delete duplicate images")
                speak("Let's recover some storage")
                slowPrint("Please choose a folder\n")
                speak("Please choose a folder")
                dsm.duplicates()
                print("\nALL DONE! ^_^ \nTake a look")
                speak("All Done! Take a look")
                os.startfile(dsm.location)

            elif 'month' in sentence and 'sort' in sentence:
                print("I will now organise your photos according to the month and year in which they were taken")
                slowPrint("Please choose a folder\n")
                speak("Please choose a folder")
                dom.monthOrganise()
                print("ALL DONE! ^_^")
                speak("All Done! Take a look")
                os.startfile(dom.location)

            elif 'year' in sentence and 'sort' in sentence:
                print("I will now organise your photos according to the year in which they were taken")
                slowPrint("Please choose a folder\n")
                speak("Please choose a folder")
                dom.yearOrganise()
                print("ALL DONE! ^_^")
                speak("All Done! Take a look")
                os.startfile(dom.location)

            elif (sentence=='exit') or 'stop' in sentence or ('bye' in sentence):
                bye()
                break;

            elif 'wikipedia' in sentence:
                speak('Searching Wikipedia...')
                sentence = sentence.replace("wikipedia", "")
                sentence = sentence.replace("search", "")
                results = wikipedia.summary(sentence, sentences=2)
                speak("Wikipedia says")
                print(results)
                speak(results)

            elif 'music' in sentence or 'youtube' in sentence:
                slowPrint("Lets get  grooving")
                speak("Lets get grooving")
                searcher=input("Enter search term: ")
                c=-1
                videosSearch = VideosSearch(searcher, limit = 2)
                res=(videosSearch.result()['result'])
                link=[]
                print("Choose a video:\n")
                speak("Choose a song")
                for i in res:
                    print(c+2,"."+i['title'])
                    c+=1
                    link.append('https://youtu.be/'+i['id'])
                    print(link[c])
                play=int(input())
                os.startfile(link[play])

            elif 'photo' in sentence or 'image' in sentence:
                can_do_photos()

            elif 'the time' in sentence:
                strTime = datetime.datetime.now().strftime("%H:%M:%S")
                speak(f"The time is {strTime}")

            elif 'help' in sentence:
                can_do()

            elif 'hello' in sentence or 'hi' in sentence or 'hey' in sentence:
                slowPrint("Hey there!")
                speak("Hey there")

            elif 'what\'s up' in sentence or 'whatsup' in sentence or 'sup' in sentence or 'whassup' in sentence or 'how r u' in sentence or 'how are you' in sentence:
                slowPrint("I am doing well!\n")
                speak("I am doing well")
                slowPrint("And you?")
                speak("and you?")
                hru=1

            elif hru==1 and ('good' in sentence or 'fine' in sentence):
                slowPrint("Glad to know!")
                speak("Glad to know")

            elif 'what' in sentence and ' doing' in sentence:
                slowPrint("Well, I want to organise more photos")
                speak("I am bored, I want to organise more photos")

            elif 'good' in sentence and ('afternoon' in sentence or 'morning' in sentence or 'night' in sentence):
                greet()

            elif(sentence=='none' or sentence==''):
                continue

            elif sentence!="":
                error+=1
                if(error<1):
                    print("Sorry, I don't know how to respond to that. Please try something else...")
                    speak("Sorry, I don't know how to respond to that. Please try something else...")
                if(error==1):
                    print("I am still learning, please try another command\nType \'help\' for the list of commands\n")
                    speak("I am still learning, please try another command")
                if(error>1):
                    print("I guess this will help:")
                    can_do()
                    speak("I guess this will help")
            #elif 'sim' in sentence: os.system('python similarity.py -f C:/Users/ASUS/Desktop/TESTF/TESTF/')
        except:
            print("An unknown error occured with image Hash/EXIF info")
            speak("Sorry about that, I am having issues processing that")
            continue


import paramaters as params
import numpy as np
import copy
import objectDefinitions as oD
from shapely.ops import nearest_points, cascaded_union
from sortedcontainers import SortedList, SortedSet, SortedDict
from shapely.geometry import Polygon, Point, LineString, MultiPolygon, box, MultiPoint
import plotContours
from matplotlib import pyplot
from mpl_toolkits.mplot3d import Axes3D

def calcPlaneTriangleIntersection( plane, triangle ):
	pointSigns = [1 ,1, 1]
	for i, vector in enumerate(triangle):
		if np.dot(np.subtract( vector, plane.Point), plane.Normal) < 0:
			pointSigns[i] = -1

	triangleLoc = np.sum(pointSigns)

	if triangleLoc == -1:
		triTip = pointSigns.index(1)

	elif triangleLoc == 1:
		triTip = pointSigns.index(-1)
	elif np.abs(triangleLoc) == 3:
		return False

	intVecs = []
	for i in range(3):
		if i != triTip:
			intVecs.append(np.subtract(triangle[i], triangle[triTip]))

	L1 = oD.Line(triangle[triTip], intVecs[0])
	L2 = oD.Line(triangle[triTip], intVecs[1])

	p1 = calcPlaneLineIntersection( plane, L1 )
	p2 = calcPlaneLineIntersection( plane, L2 )
	return [p1, p2]

# determine if a point is inside a given polygon or not
# Polygon is a list of (x,y) pairs.

def tolerantBinarySearchVertexList( vertex, vertexList , toPrint=False):
	"""Performs iterative binary search to find the position of a vertex in a given, sorted, list.
	vertexList -- sorted list of vertices or points
	vertex -- 3d vertex or point (list or array) you are searching for
	"""
	first = 0
	last = len(vertexList) -1
	if (not isinstance(vertex, list)):
		vertex = vertex.tolist()
	if toPrint:
		print(vertexList)
		print("Vertex to Find = %s" % (vertex))
	while first <= last:
		i = (first + last) / 2
		if toPrint:
			print("Current Index: %s, Vertex = %s" % (i, vertexList[i]))
		if tolerantEquals(vertexList[i], vertex):
				return i
		elif tolerantCompare( vertexList[i] , vertex) == 1:
				last = i - 1
		elif tolerantCompare( vertexList[i], vertex) == -1:
				first = i + 1
		else:
			return None

def tolerantLinearSearch( vertex, vertexList ):
	for i, vertexTest in enumerate(vertexList):

		if (not isinstance(vertexTest, list)):
			vertexTest = vertexTest.tolist()
		if tolerantEquals(vertexTest, vertex):
			return i

	return None

def tolerantEquals( v1, v2, tolerance=.000000001 ):

	if (np.abs(v1[0]-v2[0]) < tolerance) and (np.abs(v1[1]-v2[1]) < tolerance) and (np.abs(v1[2]-v2[2]) < tolerance):
		return True
	else:
		return False

def tolerantCompare( v1, v2, tolerance=.000000001 ):
	"""Returns True if v1 > v2 within tolerance, and False otherwise"""

	if (np.abs(v1[0]-v2[0]) < tolerance):
		if (np.abs(v1[1]-v2[1]) < tolerance):
			if (np.abs(v1[2]-v2[2]) < tolerance):
				return 0
			else:
				if v1[2] > v2[2]:
					return 1
		else:
			if v1[1] > v2[1]:
				return 1
	else:
		if v1[0] > v2[0]:
			return 1
	return -1

def cmp_to_key(mycmp):
    'Convert a cmp= function into a key= function'
    class K(object):
        def __init__(self, obj, *args):
            self.obj = obj
        def __lt__(self, other):
            return mycmp(self.obj, other.obj) < 0
        def __gt__(self, other):
            return mycmp(self.obj, other.obj) > 0
        def __eq__(self, other):
            return mycmp(self.obj, other.obj) == 0
        def __le__(self, other):
            return mycmp(self.obj, other.obj) <= 0
        def __ge__(self, other):
            return mycmp(self.obj, other.obj) >= 0
        def __ne__(self, other):
            return mycmp(self.obj, other.obj) != 0
    return K

def calcPlaneLineIntersection( plane, line ):
	sI = np.dot(plane.Normal, np.subtract(plane.Point, line.Point))/np.dot(plane.Normal, line.Direction)
	return line.Point + sI * line.Direction

def pointPlaneDist( plane, point ):
	pass

def projectPointToPlane( plane, planeX, point, normalize=True):
	if normalize:
		plane.Normal = np.linalg.norm(plane.Normal)
		planeX = np.linalg.norm(planeX)
	x = np.dot((point-plane.Point), planeX)
	y = np.dot((point-plane.Point), np.cross(plane.Normal, planeX))
	return [x,y]

def genTopology ( mesh ):

	vertexList = SortedList(key=cmp_to_key(tolerantCompare))
	faceList = SortedList()
	ind = 0

	for triangle in mesh.vectors:
		ind += 1
		for vertex in triangle:
			j = tolerantBinarySearchVertexList( vertex, vertexList )
			if (j == None):
				vertexList.add(vertex.tolist())

	ind = 0
	for triangle in mesh.vectors:
		ind += 1
		face = []
		for vertex in triangle:
			j = tolerantBinarySearchVertexList( vertex, vertexList )
			if (j != None):
				face.append(j)
			else:
				tolerantBinarySearchVertexList(vertex, vertexList, True)
				raise ValueError("Couldn't find vertex in list")
		faceList.add(face)

	return oD.MeshTopology(faceList, vertexList)

"""
Converts a polygon to a list. If the polygon is a multipolygon or already a list
it breaks it into a list of Polygon objects. If not, it returns a list containing the element
poly.
"""
def polyToList( poly ):

	if (type(poly) == list) or poly.geom_type == "MultiPolygon" :
		polyList = []
		for internalPoly in poly:
			polyList.append(Polygon(internalPoly.exterior.coords))
			for interior in internalPoly.interiors:
				polyList.append(Polygon(interior.coords))
		return polyList
	else:
		polyList = []
		for interior in poly.interiors:
			polyList.append(Polygon(interior.coords))

		if polyList:
			polyList.append(Polygon(poly.exterior.coords))
			return polyList
		else:
			return [poly]

"""
Optional paramaters to be added later for toolpath generation.
Units are in Millimeters
"""
def genToolPath( multiPoly, pathStepSize=3, initial_Offset=0, zHeight=0, topBounds=0, bufferRes=4 ):
	multiPoly = multiPoly.simplify(params.POLY_TOL, preserve_topology=True)
	polyList = []
	step = initial_Offset
	inc = 0
	while (1):
		inc += 1
		poly = multiPoly.buffer(step, resolution=bufferRes)
		poly = poly.simplify(params.POLY_TOL, preserve_topology=True)
		if poly.is_empty:
			break

		polyList.append(polyToList(poly))
		step = step-pathStepSize

	if polyList == []:
		return False
	orderedPolyList = []
	orderedPolyList.append(polyList[0].pop(0))

	currPolyIndex = 0
	while (1):
		if not polyList:
			break

		if currPolyIndex + 1 == len(polyList):
			if not polyList[0]:
				polyList.pop(0)
				currPolyIndex = currPolyIndex - 1
				continue
			orderedPolyList.append(polyList[0].pop(0))
			currPolyIndex = 0
			continue

		for i, nextPoly in enumerate(polyList[currPolyIndex+1], 0):
			if nextPoly.within(orderedPolyList[-1]):
				orderedPolyList.append(polyList[currPolyIndex+1].pop(i))
				break
		currPolyIndex = currPolyIndex + 1

	x = np.array([])
	y = np.array([])
	z = np.array([])
	for i, poly in enumerate(orderedPolyList[1::], 1):

		x_, y_ = orderedPolyList[i-1].exterior.coords.xy
		x = np.concatenate([x ,x_])if x.shape else x_
		y = np.concatenate([y ,y_])if y.shape else y_
		z = np.concatenate([z, np.full_like(x_, zHeight)])
		closestIndex = findClosestPolyIndex(orderedPolyList[i].exterior.coords,
											orderedPolyList[i-1].exterior.coords[0])
		orderedPolyList[i] = Polygon(orderedPolyList[i].exterior.coords[closestIndex:-1] +
									 orderedPolyList[i].exterior.coords[0:closestIndex])
		changePath = LineString([orderedPolyList[i-1].exterior.coords[0], orderedPolyList[i].exterior.coords[0]])

		if changePath.crosses(multiPoly) or not multiPoly.contains(changePath):

			cx, cy = changePath.coords.xy
			cz = np.full_like(cx, topBounds)
			x = np.concatenate([x, cx])
			y = np.concatenate([y, cy])
			z = np.concatenate([z, cz])

	x_, y_ = orderedPolyList[-1].exterior.coords.xy
	x = np.concatenate([x ,x_])
	y = np.concatenate([y ,y_])
	z = np.concatenate([z, np.full_like(x_, zHeight)])

	res = lambda: None
	res.PolyList = orderedPolyList
	res.XYZ = [x, y, z]

	return res

def generateToolOffsets( contourList, zSpacing, bufferRes=4, noVertical=False):
	"""
	Takes in a contour list (a list of polygons) that already
	take overhangs into account (i.e., all n+m contours contain
	the contour n) and generates a new contour list, where the resulting
	contours prevent the tool from hitting previous layers.
	"""

	# This assumes a cylindrical tool with a 90 degree conical tip.

	maxOffset = params.TOOL_DIAMETER/2

	resContourList = copy.deepcopy(contourList)
	for i, contour in enumerate(contourList, 0):
		currOffset = zSpacing
		buffList = []
		n = 1
		if noVertical:
			if n <= i:
				buffList.append(resContourList[i-n].buffer(currOffset, resolution=bufferRes))
		else:
			while n <= i:
				if currOffset > maxOffset:
					currOffset = maxOffset
					n = i # Set this so that the loop breaks after this round is completed
				buffList.append(contourList[i-n].buffer(currOffset, resolution=bufferRes))
				n = n + 1
				currOffset = zSpacing*n

		resContourList[i] = cascaded_union(buffList + [resContourList[i]])
		# if buffList:
		# 	resContourList[i] = buffList[-1]
	return resContourList

def genSlicePlanes( maxHeight, spacing, originCSys ):
	"""
	Generates a number of slicing planes with origins directly
	above the originCSys, and are 'spacing' distance apart from eachother.
	Note that this generates slicing planes in the Z Direction
	only, and for other axes of slicing, a transform and inverse transform should be
	used to move the model in and out of the correct coordinate system.
	"""

	planes = []
	zHeights = np.arange(originCSys.Point[2], originCSys.Point[2]+maxHeight, spacing)

	for zHeight in zHeights:
		originPoint = copy.deepcopy(originCSys.Point)
		originPoint[2] = zHeight
		planes.append(oD.Plane(originPoint, [0, 0, 1]))
	return planes

def contourConstruction( segmentList ):
	segMap = {}
	contours = []

	for segment in segmentList:
		if segment[0].__hash__() == segment[1].__hash__():
			continue
		u = segment[0]
		v = segment[1]
		if u not in segMap:
			segMap[u] = [v, None]
		else:
			segMap[u] = [segMap[u][0], v]

		if v not in segMap:
			segMap[v] = [u, None]
		else:
			segMap[v] = [segMap[v][0], u]

	while segMap:
		points = []
		points.append(segMap.keys()[0])
		[p, last] = segMap.pop(points[0])
		points.append(p)

		j = 1
		while points[j-1].__hash__() != last.__hash__():

			[u, v] = segMap.pop(points[j])

			if tolerantEquals(u.Coordinates, points[j-1].Coordinates):
				points.append(v)
			else:
				points.append(u)
			j += 1
		contours.append(points)

	return contours

def incrementalSlicing(meshTopology, planes, planeDelta):
	triangleLists = splitTriangles( meshTopology, planes, planeDelta)
	activeTriangles = set()
	segments = [[] for i in range(len(planes))]

	for i in range(len(planes)):
		activeTriangles.update(triangleLists[i])
		for triangle in copy.deepcopy(activeTriangles):
			if triangle.maxZ < planes[i].Point[2]:
				activeTriangles.remove(triangle)
			else:
				intPoints = calcPlaneTriangleIntersection( planes[i], meshTopology.getTrianglefromIndex(triangle.Indices))
				segments[i].append([oD.Vertex(intPoints[0]), oD.Vertex(intPoints[1])])

	return segments

def splitTriangles( meshTopology, planes, planeDelta):
	triangleLists = [set() for i in range(len(planes)+1)]
	if planeDelta > 0:
		for i, face in enumerate(meshTopology.faces, 0):
			triangle = meshTopology.getTrianglefromIndex( face )
			minT, maxT = meshTopology.minMaxList[i]

			if minT < planes[0].Point[2]:
				j = 0

			elif minT > planes[-1].Point[2]:
				j = len(planes)
			else:
				j = int(np.floor((minT-planes[0].Point[2])/planeDelta) +1 )
			triangleLists[j] = triangleLists[j].union([oD.Face(face, minT, maxT)])

	return triangleLists

def findClosestPolyIndex( coords, point ):
	minDist = float("inf")
	minIndex = -1
	for i, coord in enumerate(coords, 0):
		newDist = dist(coord, point)
		if newDist < minDist:
			minIndex = i
			minDist = newDist
	return minIndex

def dist(x,y):
    return np.sqrt((x[0]-y[0])**2 + (x[1]-y[1])**2)

def getPolyDepth( multiPoly ):
	"""
	Returns a list of polygons (not a MultiPolygon) where each polygon has the attribute
	'depth' which represents the depth of containment of the polygon
	"""
	multiPoly = MultiPolygon(sorted(multiPoly, key=oD.Within, reverse=True))

	depthMapping = []
	multiPolyList = []
	for poly in multiPoly:
		poly.depth = 0
		multiPolyList.append(poly)

	for i, poly in enumerate(multiPolyList, 0):
		if i == len(multiPolyList)-1:
			break
		if oD.Within(multiPolyList[i+1]) < oD.Within(poly):
			multiPolyList[i+1].depth = poly.depth + 1
		else:
			multiPolyList[i+1].depth = poly.depth

	polygonGrouping = []
	polyInteriors = []
	for poly in multiPolyList:

		polyExterior = None

		if poly.depth % 2 == 0:
			polygonGrouping.append([poly, []])
		else:
			polygonGrouping[-1][1].append(poly)

	polyResults = []
	for polygon in polygonGrouping:

		if polygon[1]:
			tupleList =[]
			for polygonInstance in polygon[1]:
				tupleList.append(list(polygonInstance.exterior.coords))
			polyResults.append(Polygon(list(polygon[0].exterior.coords), tupleList))

		else:
			polyResults.append(polygon[0])

	return MultiPolygon(polyResults)


#!/usr/bin/env python3
"""
`ksu` or `kickstart utilities` is a script to inspect the
[fedora kickstarts](https://pagure.io/fedora-kickstarts/) repository or any
other collection of kickstart files.

It can turn that collection into a graphviz `.dot` file to see relationships
between the different kickstart files, it can report kickstarts that are
unused, and it can try to find the set intersection between all kickstart
files to determine the "base system", plus some other tidbits.

`ksu` requires Python 3.9 or higher.
"""

import argparse
import io
import itertools
import logging
import pathlib
import sys
from typing import Any

"""
Copyright 2023 Simon de Vlieger <cmdr@supakeen.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

log = logging.getLogger(__name__)

def parse_args(args: list[str]) -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description=sys.modules[__name__].__doc__,
        epilog="Copyright 2023 Simon de Vlieger <cmdr@supakeen.com>",
    )

    parser.add_argument(
        "-v",
        action="count",
        default=0,
        help="verbosity, pass multiple times to set level.",
    )

    subparsers = parser.add_subparsers(dest="subparser_name")

    graph_parser = subparsers.add_parser(
        "graph", description=main_graph.__doc__
    )
    graph_parser.add_argument("directory")

    return parser.parse_args(args)

def parse_kickstart(path: pathlib.Path) -> dict[str, Any]:
    data: dict[str, list[pathlib.Path]] = {"includes": []}
    text = path.read_text()

    for line in text.splitlines():
        if line.startswith("%include"):
            _, include = line.split()
            include_path = (path.parent / pathlib.Path(include)).resolve()

            if not include_path.exists():
                log.warning(
                    "%s includes %s, which does not exist", path, include_path
                )

            data["includes"].append(include_path)

    return data

def main_graph(args: argparse.Namespace) -> int:
    """Output a `.dot` format graph for the kickstarts in a given
    directory. The `.dot` file can be used with the `dot` program to generate
    an image: `./ksu.py graph ~/kickstarts | dot -Ksfdp -Tpng -o graph.png`"""

    assert args.subparser_name == "graph"

    path = pathlib.Path(args.directory).resolve()

    if not path.exists():
        log.fatal("path %s does not exist", path)
        return 1

    if not path.is_dir():
        log.fatal("path %s is not a directory", path)
        return 1

    paths = path.glob("**/*.ks")

    graph: dict[pathlib.Path, list[pathlib.Path]] = {}

    for kickstart_path in paths:
        log.debug("parsing kickstart file at %s", kickstart_path)

        data = parse_kickstart(kickstart_path)

        log.info("%s has %d includes", kickstart_path, len(data["includes"]))

        graph[kickstart_path] = data["includes"]

    # while we're at it, let's create a reverse graph as well
    rgraph: dict[pathlib.Path, list[pathlib.Path]] = {}

    for node, edges in graph.items():
        if node not in rgraph:
            rgraph[node] = []

        for edge in edges:
            if edge not in rgraph:
                rgraph[edge] = [node]
            else:
                rgraph[edge] += [node]

    # generate `.dot` file format for graphfiz
    file = io.StringIO()
    file.write("digraph {\n")

    # first we write down all the nodes, we shorten the paths by making them
    # relative to the initial path containing them so the names are a bit
    # shorter

    # get a set of unique nodes
    nodes = (
        set(itertools.chain.from_iterable(graph.values()))
        | set(graph.keys())
    )

    for node in nodes:
        node_text = node.relative_to(path)
        file.write("  " + f'"{node_text}"')

        opts = {}

        # references to non-existent kickstart files can be colored
        # differently
        if not node.exists():
            opts["style"] = "filled"
            opts["fillcolor"] = "#DD0000"

        # if a node includes nothing we give it a different shape
        if node in graph and not len(graph[node]):
            opts["shape"] = "diamond"

        # if a node isn't included by anything this is likely an end
        # and we color it differently to make it stand out
        if node in rgraph and not len(rgraph[node]):
            opts["penwidth"] = "5"

        if opts:
            file.write(" [")
            file.write(",".join(f'{key}="{val}"' for key, val in opts.items()))
            file.write("]")

        file.write(";\n")

    file.write("\n")

    for node, edges in graph.items():
        node = node.relative_to(path)

        for edge in edges:
            edge = edge.relative_to(path)

            file.write("  " + f'"{node}" -> "{edge}";\n')

    file.write("}\n")

    print(file.getvalue(), end="")

    return 0

def main() -> int:
    args = parse_args(sys.argv[1:])

    logging.basicConfig(level=logging.FATAL - (10 * args.v))

    if args.subparser_name == "graph":
        return main_graph(args)

    # should be unreachable
    return -1

if __name__ == "__main__":
    raise SystemExit(main())

# SPDX-FileType: SOURCE
# SPDX-FileCopyRightText: Copyright 2023 Simon de Vlieger <cmdr@supakeen.com>

# SPDX-License-Identifier: MIT

# vi:sw=4:ts=4:et:


import sys
import math
import argparse
from hex_utils.asc import ASC
from hex_utils.parserSurface import setBasicArguments

def getArguments():

	parser = argparse.ArgumentParser(description='Convert continuous surface into ESRI ASCII raster.')
	parser = setBasicArguments(parser)
	parser.add_argument("-s", "--size", dest="size", default = 1,
						type=float, help="cell size (width and height)" )
	return parser.parse_args()

# ----- Main ----- #
def main():

	args = getArguments()

	grid = ASC()
	grid.init(
		math.trunc((args.xmax - args.xmin) / args.size),
		math.trunc((args.ymax - args.ymin) / args.size),
		args.xmin,
		args.ymin,
		args.size, "")

	args.xmin += args.size / 2
	args.ymin += args.size / 2

	# Dynamically import surface function
	module = __import__(args.module, globals(), locals(), [args.function])
	function = getattr(module, args.function)

	for i in range(grid.ncols):
		for j in range(grid.nrows):
			grid.set(i, grid.nrows - j - 1,
				function(args.xmin + i * args.size, args.ymin + j * args.size))

	try:
		grid.save(args.output)
	except IOError as ex:
		print("Error saving the raster %s: %s" % (args.output, ex))
		sys.exit()

	print("Created new ASCII grid successfully")

main()


import os

import pytest
import torch
import torchio as tio

from medical_shape.shape import Shape
from medical_shape.subject import ShapeSupportSubject
from medical_shape.transforms import Resample, ToCanonical

def clear_warning_caches():
    from medical_shape.subject import _warning_cache as cache_subject
    from medical_shape.transforms.mixin import _warning_cache as cache_transform

    cache_subject.clear()
    cache_transform.clear()

def save(subject: ShapeSupportSubject, path, shape_extension: str):
    for k, v in subject.items():
        if isinstance(v, Shape):
            v.save(os.path.join(path, f"{k}{shape_extension}"))
        elif isinstance(v, tio.data.Image):
            v.save(os.path.join(path, f"{k}.nii.gz"))

def create_subject():
    torch.manual_seed(42)
    random_image = torch.rand(1, 160, 384, 384)
    random_shape = torch.stack([torch.randint(0, s, (200,)) for s in random_image.shape[1:]], -1)
    subject = ShapeSupportSubject(
        s=Shape(tensor=random_shape),
        i=tio.data.ScalarImage(tensor=random_image),
    )
    return subject

@pytest.mark.parametrize(
    "shape_extension",
    [
        ".pts",
        ".mjson",
    ],
)
def test_io(tmpdir, shape_extension):
    subject = create_subject()
    save(subject, tmpdir, shape_extension)
    Shape(os.path.join(tmpdir, f"s{shape_extension}"))

@pytest.mark.parametrize(
    "trafo",
    [
        tio.transforms.CopyAffine("i", parse_input=False),
        ToCanonical(),
        Resample([2, 1, 1], parse_input=False),
    ],
)
def test_transforms(trafo):
    subject = create_subject()
    transformed_subject = trafo(subject)
    assert isinstance(transformed_subject, ShapeSupportSubject)

    transformed_subject = trafo(subject.get_images_only_subject())
    assert not isinstance(transformed_subject, ShapeSupportSubject) and isinstance(
        transformed_subject, tio.data.Subject
    )


import setuptools

requirements = []
with open("requirements.txt") as f:
    requirements = f.read().splitlines()

with open("README.md", "r", encoding="utf-8") as f:
    description = f.read()

setuptools.setup(
    name="complain",
    version="0.0.2",
    author="Leg3ndary",
    author_email="bleg3ndary@gmail.com",
    description="A python wrapper for Scott Pakins complaint generator",
    long_description=description,
    long_description_content_type="text/markdown",
    url="https://github.com/Leg3ndary/complain",
    project_urls={
        "Bug Tracker": "https://github.com/Leg3ndary/complain/issues",
    },
    install_requires=requirements,
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Intended Audience :: Developers",
        "Operating System :: OS Independent",
        "Topic :: Internet",
        "Topic :: Software Development :: Libraries",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Topic :: Utilities",
    ],
    package_dir={"": "complain"},
    packages=setuptools.find_packages(where="src"),
    python_requires=">=3.6",
)


# @Author: Henri Wenlin
# @Date:   2020-02-27T14:53:02+02:00
# @Email:  henri.wenlin@kone.com
# @Filename: wenlins_logger.py
# @Last modified by:   Henri Wenlin
# @Last modified time: 2020-03-21T16:23:30+02:00

import logging
import sys
import zmq.log.handlers

class loggerClass():
	def __init__(self, name = 'root',logging_level = 'info', file_logging = False, file_logging_level = 'debug', zmq_logging = False, zmq_port = 1003):
		self.name = name
		self.logger = logging.getLogger(name)

		if logging_level.lower() == 'debug':
			logging_level = logging.DEBUG
		elif logging_level.lower() == 'info':
			logging_level = logging.INFO
		elif logging_level.lower() == 'warning':
			logging_level = logging.WARNING
		elif logging_level.lower() == 'error':
			logging_level = logging.ERROR
		elif logging_level.lower() == 'critical':
			logging_level = logging.CRITICAL
		else:
			sys.exit("Error at Wenlin's logger: Used logging level is not supported. Exiting...")

		if file_logging_level.lower() == 'debug':
			file_logging_level = logging.DEBUG
		elif file_logging_level.lower() == 'info':
			file_logging_level = logging.INFO
		elif file_logging_level.lower() == 'warning':
			file_logging_level = logging.WARNING
		elif file_logging_level.lower() == 'error':
			file_logging_level = logging.ERROR
		elif file_logging_level.lower() == 'critical':
			file_logging_level = logging.CRITICAL
		else:
			sys.exit("Error at Wenlin's logger: Used logging level is not supported. Exiting...")

		if name == 'root':
			root = logging.getLogger()
			root.setLevel(logging_level)
		else:
			root = logging.getLogger()
			root.setLevel('DEBUG')			# By this defenition, now all log messages are comming through to console logger. I don't know if this is not pythonic way...

		ch = logging.StreamHandler()
		ch.setLevel(logging_level)
		formatter = logging.Formatter('[{levelname:^17} : {name:^17}]: {message}',style='{')# + '[%(levelname)-7s : %(name)-11s] - %(message)s')
		ch.setFormatter(formatter)
		if not [True for x in self.logger.handlers if x.__class__ == logging.StreamHandler]:
			self.logger.addHandler(ch)
		if file_logging and not [True for x in self.logger.handlers if x.__class__ == logging.FileHandler]:  # Initialize file handler?
			# Create file where logger prints
			fh = logging.FileHandler(name + '.log')
			fh.setLevel(file_logging_level)
			# create formatter and add it to the handlers
			formatter = logging.Formatter(
				'%(asctime)s - %(name)s - %(levelname)s - %(message)s')
			fh.setFormatter(formatter)
			# add the handlers to the logge
			self.logger.addHandler(fh)
		if zmq_logging and not [True for x in self.logger.handlers if x.__class__ == zmq.log.handlers.PUBHandlerr]:
			handler = zmq.log.handlers.PUBHandler('tcp://*:' + str(1103))
			handler.root_topic = self.name
			self.logger.addHandler(handler)
		self.logger.setLevel(logging_level)

	def debug(self, msg):
		self.logger.debug(msg)
	def info(self, msg):
		self.logger.info(msg)
	def warning(self, msg):
		self.logger.warning(msg)
	def error(self, msg):
		self.logger.error(msg)
	def critical(self, msg):
		self.logger.critical(msg)
	def exception(self, msg):
		self.logger.exception(msg)

if __name__ == '__main__':
	logger = loggerClass(name = 'Test logger', file_logging = True, logging_level = 'debug', file_logging_level = 'debug')
	debug = logger.debug
	info = logger.info
	warning = logger.warning
	error = logger.error
	critical = logger.critical
	exception = logger.exception
	debug('Debug')
	info('Info')
	warning('Warning')
	error('Error')
	critical('Critical')
	exception('Exception')

	logger = loggerClass(name = 'Test logger', file_logging = True, logging_level = 'Info', file_logging_level = 'info')
	debug = logger.debug
	info = logger.info
	warning = logger.warning
	error = logger.error
	critical = logger.critical
	exception = logger.exception
	debug('Debug')
	info('Info')
	warning('Warning')
	error('Error')
	critical('Critical')
	exception('Exception')

	logger = loggerClass(name = 'Test logger', file_logging = True, logging_level = 'Warning', file_logging_level = 'warning')
	debug = logger.debug
	info = logger.info
	warning = logger.warning
	error = logger.error
	critical = logger.critical
	exception = logger.exception
	debug('Debug')
	info('Info')
	warning('Warning')
	error('Error')
	critical('Critical')
	exception('Exception')

	logger = loggerClass(name = 'Test logger', file_logging = True, logging_level = 'error', file_logging_level = 'error')
	debug = logger.debug
	info = logger.info
	warning = logger.warning
	error = logger.error
	critical = logger.critical
	exception = logger.exception
	debug('Debug')
	info('Info')
	warning('Warning')
	error('Error')
	critical('Critical')
	exception('Exception')

	logger = loggerClass(name = 'Test logger', file_logging = True, logging_level = 'critical', file_logging_level = 'critical')
	debug = logger.debug
	info = logger.info
	warning = logger.warning
	error = logger.error
	critical = logger.critical
	exception = logger.exception
	debug('Debug')
	info('Info')
	warning('Warning')
	error('Error')
	critical('Critical')
	exception('Exception')

	logger = loggerClass(name = 'Logging testing', file_logging = True, logging_level = 'debug', file_logging_level = 'debug1')
	debug = logger.debug
	info = logger.info
	warning = logger.warning
	error = logger.error
	critical = logger.critical
	exception = logger.exception
	debug('Debug')
	info('Info')
	warning('Warning')
	error('Error')
	critical('Critical')
	exception('Exception')


from django.urls import path, include
from . import views

app_name = 'travel'

urlpatterns = [

    # Travel
    path('', views.TravelListView.as_view(), name='list'),
    path('<int:pk>/', views.TravelDetailView.as_view(), name='detail'),
    path('<int:travel_id>/likes/', views.LikeTravel.as_view(), name='like_travel'),
    path('<int:travel_id>/unlikes/', views.UnLikeTravel.as_view(), name='like_travel'),
    path('<int:travel_id>/todo/', views.TodoListView.as_view(), name='todo'),
    path('<int:travel_id>/todo/<int:todo_id>/', views.TodoDetailView.as_view(), name='todo_detail'),
    path('<int:travel_id>/upload/', views.MainImageView.as_view(), name='main_image'),

    # Travel Plan
    path('<int:pk>/plan/', views.TravelPlanListView.as_view(), name='plan'),
    path('<int:pk>/plan/<int:plan_pk>/', views.TravelPlanDetailView.as_view(), name='plan'),
    path('api/<int:travel_id>/', views.TravelApi.as_view(), name='api'),
]


from datetime import date
import random

class Movies:
    def __init__(self, title, release, genre, views):
        self.title = title
        self.release =  release
        self.genre = genre
        self.views = views

    def play(self):
        self.views += 1

    def __str__(self):
        return f"'{self.title}' ({self.release}) {self.views}"

    def __eq__(self, other):
        return self.title == other.title

class Series(Movies):
    def __init__(self, title, release, genre, views, episode, season):
        super().__init__(title, release, genre, views)
        self.episode = episode
        self.season = season

    def __str__(self):
        return f"'{self.title}':S{self.season:02d}E{self.episode:02d} {self.views}"

Film_1 = Movies(title="Incepcja", release=2010, genre="Sci-Fi, Psychologiczne", views=1)
Film_2 = Movies(title="Shrek", release=2001, genre="Animacja, Komedia", views=1)
Film_3 = Movies(title="Fight Club", release=2000, genre="Thriller, Psychologiczny", views=1)
Film_4 = Movies(title="Wyspa Tajemnic", release=2010, genre="Dramat, Thriller", views=1)
Film_5 = Movies(title="Gran Torino", release=2009, genre="Dramat", views=1)

Serial_1 = Series(title="Dr House", release=2004, genre="Dramat, Komedia", views=1, season=4, episode=12)
Serial_2 = Series(title="Breaking Bad", release=2008, genre="Dramat, Kryminał", views=1, season=2, episode=3)
Serial_3 = Series(title="The Waking Dead", release=2010, genre="Dramat, Horror", views=1, season=7, episode=14)
Serial_4 = Series(title="Peaky Blinders", release=2014, genre="Kryminał, Dramat historyczny", views=1, season=6, episode=9)
Serial_5 = Series(title="Czarnobyl", release=2019, genre="Dramat", views=1, season=4, episode=6)

database = [Film_1, Film_2, Film_3, Film_4, Film_5, Serial_1, Serial_2, Serial_3, Serial_4, Serial_5]

def get_movies():
    movies = []
    for obj in database:
        if obj.season > 0:
            movies.append(obj)
    return movies

def get_series():
    series = []
    for obj in database:
        if obj.season >= 1:
            series.append(obj)
    return series

def search(title):
    for i in database:
        if i.title == title:
            return i

def generate_views():
    x = random.choice(database)
    x.views = random.randint(1, 100)
    return x.views

def generate_views_loop():
    for i in range(10):
        generate_views()

def top_titles(obj, content_type='all'):
    if content_type == 'Movies':
        movies = []
        for obj in database:
            if isinstance(obj, Series):
                continue
            movies.append(obj)
        top_titles = sorted(movies, key=lambda movie: movie.views, reverse=True)
        return top_titles[:obj]
    elif content_type == 'Series':
        series = []
        for obj in database:
            if isinstance(obj, Series):
                continue
            series.append(obj)
        top_titles = sorted(series, key=lambda series: series.views, reverse=True)
        return top_titles[:obj]
    else:
        top_titles = sorted(database, key=lambda x: x.views, reverse=True)
        return top_titles[:obj]

if __name__ == '__main__':
    print("Biblioteka filmów")
    print(f"Najpopularniejsze filmy i seriale dnia {date.today():%d.%m.%Y}")
    generate_views_loop()
    for i in top_titles(3):
        print(i)
#Dla mentora
#Random zawsze zwraca conajmniej 2 jedynki w views, nie mam już siły z tym walczyć dlatego wysyłam zadanko niby działające, ale nie na 100%
print("------------")
print(Serial_1)
print(Serial_2)
print(Serial_3)
print(Serial_4)
print(Serial_5)
print(Film_1)
print(Film_2)
print(Film_3)
print(Film_4)
print(Film_5)


from typing import Callable, Dict, List, Optional, Union

import torch
import torch.nn as nn
from torch.distributed import ProcessGroup
from torch.distributed.fsdp.fully_sharded_data_parallel import (
    BackwardPrefetch, CPUOffload, FullyShardedDataParallel)

from mmengine.optim import OptimWrapper
from mmengine.registry import MODEL_WRAPPERS, Registry
from mmengine.structures import BaseDataElement

# support customize fsdp policy
FSDP_WRAP_POLICIES = Registry('fsdp wrap policy')

@MODEL_WRAPPERS.register_module()
class MMFullyShardedDataParallel(FullyShardedDataParallel):
    """A wrapper for sharding Module parameters across data parallel workers.

    Different from FullyShardedDataParallel, MMFullyShardedDataParallel
    implements three methods :meth:`train_step`, :meth:`val_step` and
    :meth:`test_step`, which will be called by ``train_loop``, ``val_loop``
    and ``test_loop``.

    - ``train_step``: Called by ``runner.train_loop``, and implement
      default model forward, gradient back propagation, parameter updating
      logic.

    - ``val_step``: Called by ``runner.val_loop`` and get the inference
      results. Specially, since MMFullyShardedDataParallel will wrap model
      recursively, it may cause some problem if one just use
      ``BaseModel.val_step`` to implement ``val_step`` here. To avoid that,
      ``val_step`` will call methods of :obj:`BaseModel` to pre-process
      data first, and use ``FullyShardedDataParallel.forward`` to get result.

    - ``test_step``: Called by ``runner.test_loop`` and get the inference
      results. Its logic is equivalent to ``val_loop``.

    Args:
        module (nn.Module): module to be wrapped with FSDP.
        process_group (Optional[ProcessGroup]): process group for sharding.
        cpu_offload (Optional[Union[bool,CPUOffload]]):
            CPU offloading config.
            Different from FullyShardedDataParallel,Since it can be set by
            users' pre-defined config in MMEngine,its type is expected to be
            `None`, `bool` or `CPUOffload`.

            Currently, only parameter and gradient CPU offload is supported.
            It can be enabled via passing in
            ``cpu_offload=CPUOffload(offload_params=True)``. Note that this
            currently implicitly enables gradient offloading to CPU in order
            for params and grads to be on same device to work with optimizer.
            This API is subject to change. Default is ``None`` in which case
            there will be no offloading.
        fsdp_auto_wrap_policy: (Optional[Union[str,Callable]]):
            Specifying a policy to recursively wrap layers with FSDP.
            Different from FullyShardedDataParallel, Since it can be set by
            users' pre-defined config in MMEngine, its type is expected to be
            `None`, `str` or `Callable`. If it's `str`, then
            MMFullyShardedDataParallel will try to get specified method in
            ``FSDP_WRAP_POLICIES`` registry,and this method will be passed to
            FullyShardedDataParallel to finally initialize model.

            Note that this policy currently will only apply to child modules of
            the passed in module. The remainder modules are always wrapped in
            the returned FSDP root instance.
            ``default_auto_wrap_policy`` written in
            ``torch.distributed.fsdp.wrap`` is an example of
            ``fsdp_auto_wrap_policy`` callable, this policy wraps layers with
            parameter sizes larger than 100M. Users can supply the customized
            ``fsdp_auto_wrap_policy`` callable that should accept following
            arguments: ``module: nn.Module``, ``recurse: bool``,
            ``unwrapped_params: int``, extra customized arguments could be
            added to the customized ``fsdp_auto_wrap_policy`` callable as well.

            Example::

                >>> def custom_auto_wrap_policy(
                >>>     module: nn.Module,
                >>>     recurse: bool,
                >>>     unwrapped_params: int,
                >>>     # These are customizable for this policy function.
                >>>     min_num_params: int = int(1e8),
                >>> ) -> bool:
                >>>     return unwrapped_params >= min_num_params

        backward_prefetch: (Optional[Union[str,BackwardPrefetch]]):
            Different from FullyShardedDataParallel, Since it will be set by
            users' pre-defined config in MMEngine,its type is expected to be
            `None`, `str` or `BackwardPrefetch`.

            This is an experimental feature that is subject to change in the
            the near future. It allows users to enable two different
            backward_prefetch algorithms to help backward communication and
            computation overlapping.
            Pros and cons of each algorithm is explained in class
            ``BackwardPrefetch``.

        **kwargs: Keyword arguments passed to
            :class:`FullyShardedDataParallel`.
    """

    def __init__(
        self,
        module: nn.Module,
        process_group: Optional[ProcessGroup] = None,
        cpu_offload: Optional[Union[bool, CPUOffload]] = None,
        fsdp_auto_wrap_policy: Optional[Union[str, Callable]] = None,
        backward_prefetch: Optional[Union[str, BackwardPrefetch]] = None,
        **kwargs,
    ):

        if cpu_offload is not None:
            if isinstance(cpu_offload, bool):
                cpu_offload = CPUOffload(offload_params=cpu_offload)
            elif not isinstance(cpu_offload, CPUOffload):
                raise TypeError(
                    '`cpu_offload` should be `None`, `bool`'
                    f'or `CPUOffload`, but has type {type(cpu_offload)}')

        if fsdp_auto_wrap_policy is not None:
            if isinstance(fsdp_auto_wrap_policy, str):
                assert fsdp_auto_wrap_policy in FSDP_WRAP_POLICIES, \
                    '`FSDP_WRAP_POLICIES` has no ' \
                    f'function {fsdp_auto_wrap_policy}'
                fsdp_auto_wrap_policy = FSDP_WRAP_POLICIES.get(  # type: ignore
                    fsdp_auto_wrap_policy)
                if not isinstance(fsdp_auto_wrap_policy,
                                  Callable):  # type: ignore
                    raise TypeError(
                        'Registered `fsdp_auto_wrap_policy` needs to be '
                        '`Callable`, but has type '
                        f'{type(fsdp_auto_wrap_policy)}')
            elif not isinstance(fsdp_auto_wrap_policy,
                                Callable):  # type: ignore
                raise TypeError(
                    '`fsdp_auto_wrap_policy` should be `None`, `str` '
                    'or `Callable`, but has type '
                    f'{type(fsdp_auto_wrap_policy)}')

        if backward_prefetch is not None:
            if isinstance(backward_prefetch, str):
                assert backward_prefetch in ['pre', 'post'], \
                    '`backward_prefetch` should be either `pre` or `post`,' \
                    f' but get {backward_prefetch}'
                if backward_prefetch == 'pre':
                    backward_prefetch = BackwardPrefetch.BACKWARD_PRE
                else:
                    backward_prefetch = BackwardPrefetch.BACKWARD_POST
            elif not isinstance(backward_prefetch, BackwardPrefetch):
                raise TypeError('`backward_prefetch` should be `None`, `str` '
                                'or `BackwardPrefetch`, but has type '
                                f'{type(backward_prefetch)}')

        super().__init__(
            module=module,
            process_group=process_group,
            auto_wrap_policy=fsdp_auto_wrap_policy,
            cpu_offload=cpu_offload,
            backward_prefetch=backward_prefetch,
            **kwargs)

    def train_step(self, data: dict,
                   optim_wrapper: OptimWrapper) -> Dict[str, torch.Tensor]:
        """Interface for model forward, backward and parameters updating during
        training process.

        :meth:`train_step` will perform the following steps in order:

        - If :attr:`module` defines the preprocess method,
            call ``module.preprocess`` to pre-processing data.
        - Call ``module.forward(**data)`` and get losses.
        - Parse losses.
        - Call ``optim_wrapper.optimizer_step`` to update parameters.
        - Return log messages of losses.

        Args:
            data (dict): Data sampled by dataloader.
            optim_wrapper (OptimWrapper): A wrapper of optimizer to
                update parameters.

        Returns:
            Dict[str, torch.Tensor]: A ``dict`` of tensor for logging.
        """
        # enable automatic mixed precision training context.
        with optim_wrapper.optim_context(self):
            data = self.module.data_preprocessor(data, training=True)
            if isinstance(data, dict):
                losses = self(**data, mode='loss')
            elif isinstance(data, (list, tuple)):
                losses = self(*data, mode='loss')
            else:
                raise TypeError('Output of `data_preprocessor` should be '
                                f'list tuple or dict, but got {type(data)}')
        parsed_loss, log_vars = self.module.parse_losses(losses)
        optim_wrapper.update_params(parsed_loss)
        return log_vars

    def val_step(self, data: dict) -> List[BaseDataElement]:
        """Gets the prediction of module during validation process.

        Args:
            data (dict): Data sampled by dataloader.

        Returns:
            List[BaseDataElement] or dict: The predictions of given data.
        """
        inputs, data_sample = self.module.data_preprocessor(data, False)
        return self(inputs, data_sample, mode='predict')

    def test_step(self, data: dict) -> List[BaseDataElement]:
        """Gets the predictions of module during testing process.

        Args:
            data (dict): Data sampled by dataloader.

        Returns:
            List[BaseDataElement]: The predictions of given data.
        """
        inputs, data_sample = self.module.data_preprocessor(data, False)
        return self(inputs, data_sample, mode='predict')


import streamlit as st
import random

st.set_page_config("Python Hangman")

st.markdown("
Hangman for Python Programmers
", unsafe_allow_html=True)

st.write("Enter the blanks with a Python Keyword")

c = st.container()

# word_list = ['tuple' , 'global' , 'list' , 'dict' , 'string' , 'elif' , 'else' , 'while' , 'for' , 'import' , 'from' , 'def' , 'try' , 'except' , 'finally']
# final_word = random.choice(word_list)  under review

text = 'while'

lose = 0
win = 0

def win_check(letter, text):
    global lose
    global win
    if letter in text:
        win += 1
    else:
        lose += 1

    if win == len(text):
        st.balloons()
        st.success("You have successfully guessed the word")

def update(letter, word, text):

    text = list(text)
    word = list(word)
    letter = letter.lower()

    for i in range(len(text)):
        if text[i] == letter:
            word[2*i] = letter

    new = ""

    word = new.join(word)
    u.markdown( f"
{word}
", unsafe_allow_html=True)
    return word

u = st.empty()
col = st.columns(5)

with col[0]:
    t1 = st.container()

with col[1]:
    t2 = st.container()

with col[2]:
    t3 = st.container()

with col[3]:
    t4 = st.container()

with col[4]:
    t5 = st.empty()

word = "_ " * len(text)
limit = 0
count = 1
letters = ['', '', '', '', '', '','','','','','','','','','']

u.markdown( f"
{word}
", unsafe_allow_html=True)

limit = len(text) + 4

t5.image('hangman_pics/pic1.jpeg')

letters[0] = t1.text_input(f"Enter a letter:", max_chars = 1, key = 1 )

if letters[0]:
    count += 1
    word = update(letters[0], word, text)
    win_check(letters[0], text)

    letters[1] = t2.text_input(f"Enter a letter:", max_chars = 1, key = 2 )

    if letters[1]:
        count += 1
        word = update(letters[1], word, text)
        win_check(letters[1], text)

        letters[2] = t3.text_input(f"Enter a letter:", max_chars = 1, key = 3 )

        if letters[2]:
            count += 1
            word = update(letters[2], word, text)
            win_check(letters[2], text)

            letters[3] = t4.text_input(f"Enter a letter:", max_chars = 1, key = 4 )

            if letters[3] and (win != len(text)):
                count += 1
                word = update(letters[3], word, text)
                win_check(letters[3], text)

                letters[4] = t1.text_input(f"Enter a letter:", max_chars = 1, key = 5 )

                if letters[4]  and (lose != 4) and (win != len(text)):
                    count += 1
                    word = update(letters[4], word, text)
                    win_check(letters[4], text)

                    letters[5] = t2.text_input(f"Enter a letter:", max_chars = 1, key = 6 )

                    if letters[5]  and lose != 4 and (win != len(text)):
                        count += 1
                        word = update(letters[5], word, text)
                        win_check(letters[5], text)

                        letters[6] = t3.text_input(f"Enter a letter:", max_chars = 1, key = 7 )

                        if letters[6] and count != limit  and lose != 4 and (win != len(text)):
                            count += 1
                            word = update(letters[6], word, text)
                            win_check(letters[6], text)

                            letters[7] = t4.text_input(f"Enter a letter:", max_chars = 1, key = 8 )

                            if letters[7] and count != limit  and lose != 4 and (win != len(text)):
                                count += 1
                                word = update(letters[7], word, text)
                                win_check(letters[7], text)

                                letters[8] = t2.text_input(f"Enter a letter:", max_chars = 1, key = 9 )

                                if letters[8] and count != limit  and lose != 4 and (win != len(text)):
                                    count += 1
                                    word = update(letters[8], word, text)
                                    win_check(letters[8], text)

                                    letters[9] = t3.text_input(f"Enter a letter:", max_chars = 1, key = 10 )

                                    if letters[9] and count != limit  and lose != 4 and (win != len(text)):
                                        word = update(letters[9], word, text)
                                        win_check(letters[9], text)

if lose == 1:
    t5.image('hangman_pics/pic2.jpeg')
elif lose == 2:
    t5.image('hangman_pics/pic3.jpeg')
elif lose == 3:
    t5.image('hangman_pics/pic4.jpeg')
elif lose == 4:
    t5.image('hangman_pics/pic5.jpeg')
    st.info("You have been Hanged")