+: finales 146-150

This commit is contained in:
devfzn 2023-11-22 11:54:37 -03:00
parent ff699db55a
commit 3ed3f06699
Signed by: devfzn
GPG Key ID: E070ECF4A754FDB1
24 changed files with 870 additions and 96 deletions

View File

@ -4,71 +4,61 @@ Guia interactiva con la resolución de los retos propuestos en el libro
[Python by Example](https://www.google.cl/books/edition/Python_by_Example/gDGdDwAAQBAJ) [Python by Example](https://www.google.cl/books/edition/Python_by_Example/gDGdDwAAQBAJ)
de *Nichola Lacey* de *Nichola Lacey*
![img](./imgs/main_menu.png)
### Retos Básicos ### Retos Básicos
- [001-011](./basic/basic01.py) - [001-011](./basic/basic01.py) | [012-019](./basic/basic02.py) |
- [012-019](./basic/basic02.py) [020-026](./basic/basic03.py) | [027-034](./basic/basic04.py) |
- [020-026](./basic/basic03.py) [035-044](./basic/basic05.py) | [045-051](./basic/basic06.py) |
- [027-034](./basic/basic04.py) [052-059](./basic/basic07.py) ![img](./imgs/basics_001-059.png)
- [035-044](./basic/basic05.py)
- [045-051](./basic/basic06.py)
- [052-059](./basic/basic07.py)
### Retos Turtle ### Retos Turtle
- [060](./trtl/turtle01.py) - [060](./trtl/turtle01.py) | [061](./trtl/turtle02.py) |
- [061](./trtl/turtle02.py) [062](./trtl/turtle03.py) | [063](./trtl/turtle04.py) |
- [062](./trtl/turtle03.py) [064](./trtl/turtle05.py) | [065](./trtl/turtle06.py) |
- [063](./trtl/turtle04.py) [066](./trtl/turtle07.py) | [067](./trtl/turtle08.py) |
- [064](./trtl/turtle05.py) [068](./trtl/turtle09.py) ![img](./imgs/turtle_060-068.png)
- [065](./trtl/turtle06.py)
- [066](./trtl/turtle07.py)
- [067](./trtl/turtle08.py)
- [068](./trtl/turtle09.py)
### Retos Intermedios ### Retos Intermedios
- [069-079](./interm/interm01.py) - [069-079](./interm/interm01.py) | [080-087](./interm/interm02.py) |
- [080-087](./interm/interm02.py) [088-095](./interm/interm03.py) | [096-104](./interm/interm04.py) |
- [088-095](./interm/interm03.py) [105-110](./interm/interm05.py) | [111-117](./interm/interm06.py) |
- [096-104](./interm/interm04.py) [118-123](./interm/interm07.py) ![img](./imgs/interm_069-123.png)
- [105-110](./interm/interm05.py)
- [111-117](./interm/interm06.py)
- [118-123](./interm/interm07.py)
### Retos Tkinter ### Retos Tkinter
- [124](./tkgui/tk01.py) - [124](./tkgui/tk01.py) | [125](./tkgui/tk02.py) | [126](./tkgui/tk03.py) |
- [125](./tkgui/tk02.py) [127](./tkgui/tk04.py) | [128](./tkgui/tk05.py) | [129](./tkgui/tk06.py) |
- [126](./tkgui/tk03.py) [130](./tkgui/tk07.py) | [131](./tkgui/tk08.py) | [132](./tkgui/tk09.py) |
- [127](./tkgui/tk04.py) [133](./tkgui/tk10.py) | [134](./tkgui/tk11.py) | [135](./tkgui/tk12.py) |
- [128](./tkgui/tk05.py) [136](./tkgui/tk13.py) | [137](./tkgui/tk14.py) | [138](./tkgui/tk15.py)
- [129](./tkgui/tk06.py) ![img](./imgs/tkinter_124-138.png)
- [130](./tkgui/tk07.py)
- [131](./tkgui/tk08.py)
- [132](./tkgui/tk09.py)
- [133](./tkgui/tk10.py)
- [134](./tkgui/tk11.py)
- [135](./tkgui/tk12.py)
- [136](./tkgui/tk13.py)
- [137](./tkgui/tk14.py)
- [138](./tkgui/tk15.py)
### Retos SQLite3 ### Retos SQLite3
- [139](./sqlite/sql01.py) - [139](./sqlite/sql01.py) | [140](./sqlite/sql02.py) |
- [140](./sqlite/sql02.py) [141](./sqlite/sql03.py) | [142](./sqlite/sql04.py) |
- [141](./sqlite/sql03.py) [143](./sqlite/sql05.py) | [144](./sqlite/sql06.py) |
- [142](./sqlite/sql04.py) [145](./sqlite/sql07.py)
- [143](./sqlite/sql05.py)
- [144](./sqlite/sql06.py) ### Retos Finales
- [145](./sqlite/sql07.py)
- [146](./final/fin01.py) | [147](./final/fin02.py) | [148](./final/fin03.py) |
[149](./final/fin04.py) | [150](./final/fin05.py)
![img](./imgs/final_146-150.png)
## Uso ## Uso
Requiere **Tkinter** para retos [124-128](./tkgui/)
```sh ```sh
git clone https://gitea.kickto.net/devfzn/python_by_example.git git clone https://gitea.kickto.net/devfzn/python_by_example.git
cd python_by_example cd python_by_example
python main.py python main.py
``` ```
Mas [imagenes](./images.md)

View File

@ -0,0 +1 @@
directorio para creación/lectura/escritura de archivos y bd.

75
final/fin01.py Normal file
View File

@ -0,0 +1,75 @@
from common.common import clear
def fin_01():
"""A shift code is where a message can be easily encoded and is one of the
simplest codes to use. Each letter is moved forwards through the alphabet
a set number of letters to be represented by a new letter. For instance,
'abc' becomes 'bcd' when the code is shifted by one (i.e. each letter in
the alphabet is moved forward one character). You need to create a
program which will display the following menu:
1) Make a code
2) Decode a message
3) Quit
Enter your selection:
If the user selects 1, they should be able to type in a message
(including spaces) and then enter a number. Python should then display
the encoded message once the shift code has been applied. If the user
selects 2, they should enter an encoded message and the correct number
and it should display the decoded message (i.e. move the correct number
of letters backwards through the alphabet). If they select 3 it should
stop the program from running. After they have encoded or decoded a
message the menu should be displayed to them again until they select quit."""
abc = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'ñ', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
def code_msg(msg, steps):
coded_message = ""
for letter in msg:
if letter in abc:
ind = abc.index(letter)
ind += steps
while ind >= len(abc):
ind -= len(abc)
coded_message += abc[ind]
else:
coded_message += letter
print(coded_message)
def decode_msg(msg, steps):
decoded_message = ""
for letter in msg:
if letter in abc:
ind = abc.index(letter)
ind -= steps
while ind < -len(abc):
ind += len(abc)
decoded_message += abc[ind]
else:
decoded_message += letter
print(decoded_message)
while True:
clear()
print("""
1) Codificar mensaje
2) Decodificar mensaje
s) Salir
""")
sel = input("Ingresa una opción: ")
match sel:
case '1':
msg = input("Ingresa el mensaje a codificar: ")
steps = int(input("Ingresa el nro. de pasos: "))
code_msg(msg, steps)
input("\nPresiona Enter para continuar\n")
case '2':
msg = input("Ingresa el mensaje a decodificar: ")
steps = int(input("Ingresa el nro. de pasos: "))
decode_msg(msg, steps)
input("\nPresiona Enter para continuar\n")
case 's':
break
case _:
print("Debes ingresar una opción válida")
input("\nPresiona Enter para continuar\n")

79
final/fin02.py Normal file
View File

@ -0,0 +1,79 @@
from random import choice
from common.common import clear
def fin_02():
"""You are going to make an on-screen version of the board game 'Mastermind'.
The computer will automatically generate four colours from a list of
possible colours (it should be possible for the computer to randomly
select the same colour more than once). For instance, the computer may
choose 'red', 'blue', 'red', 'green'. This sequence should not be
displayed to the user. After this is done the user should enter their
choice of four colours from the same list the computer used. For
instance, they may choose 'pink', 'blue', 'yellow' and 'red'. After the
user has made their selection, the program should display how many
colours they got right in the correct position and how many colours they
got right but in the wrong position. In the example above, it should
display the message 'Correct colour in the correct place: 1' and 'Correct
colour but in the wrong place: 1'. The user continues guessing until they
correctly enter the four colours in the order they should be in. At the
end of the game it should display a suitable message and tell them how
many guesses they took."""
colours = {
'NEGRO': "\033[0;30;1;47m",
'PURPURA': "\033[1;35m",
'CIAN': "\033[0;1;36m",
'ROJO': "\033[1;31m",
'VERDE': "\033[1;32m",
'AMARILLO': "\033[1;33m",
'AZUL': "\033[1;34m",
'BLANCO': "\033[1;37m",
'END': "\033[0m"
}
secrets = []
guesses = []
tries = 0
for _ in range(4):
secrets.append(choice(list(colours.keys())[:-1]))
#print(colours[secrets[i]]+"█████"+secrets[i]+"█████"+colours['END'])
print("\n COLORES\n")
for color in list(colours.keys())[:-1]:
print(' '+color.capitalize(), end=' ')
print()
def guess_colours():
guesses.clear()
print("\nIngresa 4 colores de la lista")
cont = 1
while len(guesses) < 4:
resp = input(f"Ingresa el color nro. {cont}: ").upper()
if resp in list(colours.keys())[:-1]:
guesses.append(resp)
cont += 1
print()
def check_colours():
ok_guess = 0
for i, guess in enumerate(guesses):
if guess in secrets:
print(colours[guess]+f"{guess} está en los colores", end='')
if guess == secrets[i]:
print(", en está misma posición"+colours["END"])
ok_guess +=1
else:
print(", en otra posición"+colours["END"])
else:
print(f"{guess} no está entre los colores")
print()
if ok_guess == 4:
return True
else:
return False
win = False
while not win:
guess_colours()
win = check_colours()
tries += 1
print(f"Ganaste en {tries} intentos")

137
final/fin03.py Normal file
View File

@ -0,0 +1,137 @@
from os import getcwd as pwd
from getpass import getpass
from common.common import clear
import csv
def fin_03():
"""You need to create a program that will store the user ID and passwords
for the users of a system. It should display the following menu:
1) Create a new User ID
2) Change a password
3) Display all User IDs
4) Quit
Enter selection:
If the user selects 1, it should ask them to enter a user ID. It should check
if the user ID is already in the list. If it is, the program should display
a suitable message and ask them to select another user ID. Once a suitable
user ID has been entered it should ask for a password. Passwords should be
scored with 1 point for each of the following:
- it should have at least 8 characters.
- it should include uppercase letters.
- it should include lower case letters.
- it should include numbers.
- it should include at least one special character such as
!, £, $, %, &, <, * or @.
If the password scores only 1 or 2 it should be rejected with a message
saying it is a weak password; if it scores 3 or 4 tell them that "This
password could be improved." Ask them if they want to try again. If it
scores 5 tell them they have selected a strong password. Only acceptable
user IDs and passwords should be added to the end of the .csv file. If they
select 2 from the menu they will need to enter a user ID, check to see if
the user ID exists in the list, and if it does, allow the user to change the
password and save the changes to the .csv file. Make sure the program only
alters the existing password and does not create a new record. If the user
selects 3 from the menu, display all the user IDs but not the passwords. If
the user selects 4 from the menu it should stop the program."""
file_path = f"{pwd()}/final/files/users.csv"
menu = """
Administrador de Usuarios
1) Crear nuevo ID de usuario
2) Cambiar una contraseña
3) Ver todos los ID de usuario
s) Salir
"""
def create_pass():
points = 0
while points < 3:
points = 0
password = getpass("Ingresa la contraseña: ")
if len(password) >= 8:
points += 1
x = len([1 for p in password if p.isupper()])
points += 1 if x > 0 else 0
x = len([1 for p in password if p.islower()])
points += 1 if x > 0 else 0
x = len([1 for p in password if p.isdigit()])
points += 1 if x > 0 else 0
x = len([1 for p in password if p in '!£$%&<*@'])
points += 1 if x > 0 else 0
if points < 3:
print("La contraseña es demasiado debil")
continue
elif 2 < points < 5:
resp = input("El password podría ser mejor, ¿quieres mejorarlo? (S|n): ").lower()
if resp != 'n':
points = 0
continue
repass = getpass("Verificar la contraseña:")
if repass != password:
points = 0
return password
def create_user():
user = input("Ingresa el nombre de usuario: ").strip()
temp_users = get_users()
if temp_users is None or user not in temp_users:
password = create_pass()
with open(file_path, '+a') as file:
file.write(f"{user},{password}\n")
input("Usuario creado, presiona Enter para continuar")
else:
input("Usuario ya existe, presiona Enter para continuar")
def change_pass():
user = input("Ingresa el nombre del usuario a modificar contraseña: ")
temp_users = get_users()
if temp_users is not None and user in temp_users:
password = create_pass()
temp_data = []
with open(file_path, 'r') as file:
reader = csv.reader(file)
for line in reader:
if user in line[0]:
temp_data.append([line[0],password])
else:
temp_data.append([line[0],line[1]])
with open(file_path, 'w') as file:
writer = csv.writer(file)
writer.writerows(temp_data)
print(f"Password actualizado exitosamente")
else:
print("El usuario ingresado no existe")
input("Presiona Enter para continuar")
def get_users():
temp_users = []
try:
with open(file_path, 'r') as file:
read = csv.reader(file)
for r in read:
temp_users.append(r[0])
except FileNotFoundError:
pass
return temp_users
while True:
clear()
print(f"Ruta archivo:\n{file_path}")
print(menu)
sel = input("Ingresa una opción: ")
match sel:
case "1":
create_user()
case "2":
change_pass()
case "3":
users = get_users()
print("\n Usuarios \n----------")
for user in users:
print(" "+user)
input("\nPresiona Enter para continuar")
case "s":
break
case _:
print("Debes ingresar una opción válida")
input("Presiona enter para continuar")

60
final/fin04.py Normal file
View File

@ -0,0 +1,60 @@
import tkinter as tk
def fin_04():
"""Create a program that will display the following screen:
+-------------------------------------------------+
| ___________ ________________ |
| Enter a number: |___________| |View Times Table||
| ___________ |________________||
| | | ________________ |
| | | | Clear ||
| | | |________________||
| | | |
| | | |
| |___________| |
|_________________________________________________|
When the user enters a number in the first box and clicks on the "View
Times Table" button it should show the times table in the list area.
For instance, if the user entered 99 they would see the list as shown
in the example on the right. The "Clear" button should clear both boxes."""
com_bg = "dodger blue"
window = tk.Tk()
window.title("Tablas de Multiplicar")
window.geometry("400x300")
window["bg"] = com_bg
lbl_num = tk.Label(text="Ingresa un número:", font="Verdana 10")
lbl_num["bg"] = com_bg
lbl_num.place(x=20, y=20, width=130, height=30)
txt_in = tk.Entry()
txt_in.place(x=150, y=20, width=120, height=30)
def view():
num = txt_in.get()
clear()
if num.isdigit():
num = int(num)
for i in range(1,13):
lst_table.insert('end', f"{i} x {num} = {i*num}")
else:
clear()
def clear():
lst_table.delete(0, 'end')
txt_in.delete(0, 'end')
txt_in.focus()
btn_view = tk.Button(text="Ver tablas", width=100, height=30, command=view)
btn_view.place(x=280, y=20, width=100, height=30)
lst_table = tk.Listbox()
lst_table["justify"] = "left"
lst_table.place(x=150, y=60, width=120 ,height=230)
btn_clear = tk.Button(text="Limpiar", width=100, height=30, command=clear)
btn_clear.place(x=280, y=60, width=100, height=30)
txt_in.focus()
window.mainloop()

387
final/fin05.py Normal file
View File

@ -0,0 +1,387 @@
from os import getcwd as pwd
import tkinter as tk
import sqlite3
def fin_05():
"""A small art gallery is selling works from different artists and wants to
keep track of the paintings using an SQL database. You need to create a
user-friendly system to keep track of the art. This should include using a
GUI. Below is the current data that needs to be stored in a database.
Artists Contact Details:
ArtistID Name Address Town Country Postcode
1 Martin Leighton 5 Park Place Peterborough Cambridgeshire PE32 5LP
2 Eva Czariecka 77 Warner Close Chelmsford Essex CM22 5FT
3 Roxy Parkin 90 Hindhead Road London SE12 6WM
4 Nigel Farnworth 41 Whitby Road Huntly Aberdeenshire AB54 5PN
5 Teresa Tanner 70 Guild Street London NW7 1SP
PieceID ArtistID Title Medium Price
1 5 Woman with black Labrador Oil 220
2 5 Bees & thistles Watercolour 85
3 2 A stroll to Westminster Ink 190
4 1 African giant Oil 800
5 3 Water daemon Acrylic 1700
6 4 A seagull Watercolour 35
7 1 Three friends Oil 1800
8 2 Summer breeze 1 Acrylic 1350
9 4 Mr Hamster Watercolour 35
10 1 Pulpit Rock, Dorset Oil 600
11 5 Trawler Dungeness beach Oil 195
12 2 Dance in the snow Oil 250
13 4 St Tropez port Ink 45
14 3 Pirate assassin Acrylic 420
15 1 Morning walk Oil 800
16 4 A baby barn swallow Watercolour 35
17 4 The old working mills Ink 395
The art gallery must be able to add new artists and pieces of art. Once a
piece of art has been sold, the data about that art should be removed from
the main SQL database and stored in a separate text file. Users should be
able to search by artist, medium or price."""
db_path = f"{pwd()}/final/files/artgallery.db"
file_path = f"{pwd()}/final/files/art_sales.txt"
def exec_query(query, params=None):
with sqlite3.connect(db_path) as db:
cursor = db.cursor()
if params is not None:
result = cursor.execute(query, params)
else:
result = cursor.execute(query)
db.commit()
return result
def exec_queries(query, params):
with sqlite3.connect(db_path) as db:
cursor = db.cursor()
result = cursor.executemany(query, params)
db.commit()
return result
def create_tables():
query="""CREATE TABLE IF NOT EXISTS artists(
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
address TEXT NOT NULL,
town TEXT,
country TEXT NOT NULL,
postcode TEXT NOT NULL)"""
exec_query(query)
query="""CREATE TABLE IF NOT EXISTS pieces(
id INTEGER PRIMARY KEY,
artistid INTEGER,
title TEXT NOT NULL,
medium TEXT NOT NULL,
price FLOAT,
FOREIGN KEY (artistid) REFERENCES artists(id))"""
exec_query(query)
def populate_tables():
query = """INSERT INTO artists(name, address, town, country, postcode)
VALUES(?,?,?,?,?)"""
artists = [
('Martin Leighton', '5 Park Place', 'Peterborough', 'Cambridgeshire', 'PE32 5LP'),
('Eva Czariecka', '77 Warner Close', 'Chelmsford', 'Essex', 'CM22 5FT'),
('Roxy Parkin', '90 Hindhead Road', None, 'London', 'SE12 6WM'),
('Nigel Farnworth', '41 Whitby Road', 'Huntly', 'Aberdeenshire', 'AB54 5PN'),
('Teresa Tanner', '70 Guild Street', None ,'London', 'NW7 1SP')
]
exec_queries(query, artists)
query = "INSERT INTO pieces(artistid, title, medium, price) VALUES(?,?,?,?)"
pieces = [
('5', 'Woman with black Labrador', 'Oil', 220),
('5', 'Bees & thistles', 'Watercolour', 85),
('2', 'A stroll to Westminster', 'Ink' , 190),
('1', 'African giant', 'Oil', 800),
('3', 'Water daemon', 'Acrylic', 1700),
('4', 'A seagull', 'Watercolour', 35),
('1', 'Three friends', 'Oil', 1800),
('2', 'Summer breeze 1', 'Acrylic', 1350),
('4', 'Mr Hamster', 'Watercolour', 35),
('1', 'Pulpit Rock, Dorset', 'Oil', 600),
('5', 'Trawler Dungeness beach', 'Oil', 195),
('2', 'Dance in the snow', 'Oil', 250),
('4', 'St Tropez port', 'Ink', 45),
('3', 'Pirate assassin', 'Acrylic', 420),
('1', 'Morning walk', 'Oil', 800),
('4', 'A baby barn swallow', 'Watercolour', 35),
('4', 'The old working mills', 'Ink', 395)
]
exec_queries(query, pieces)
def drop_tables():
query = "DROP TABLE IF EXISTS pieces"
exec_query(query)
query = "DROP TABLE IF EXISTS artists"
exec_query(query)
def add_artist(artist):
query = """INSERT INTO artists (name, address, town, country, postcode)
VALUES(?,?,?,?,?)"""
exec_query(query, artist)
def add_piece(piece):
query = """INSERT INTO pieces (artistid, title, medium, price)
VALUES(?,?,?,?)"""
exec_query(query, piece)
def del_piece(piece_id):
query = "DELETE FROM pieces WHERE id=?"
exec_query(query, [piece_id])
def sell_piece():
piece = lst_out.get(tk.ANCHOR)
try:
piece_id = piece.split()[0]
query = "SELECT * FROM pieces WHERE id=?"
result = exec_query(query, [piece_id])
data = result.fetchone()
with open(file_path, 'a+') as file:
file.write(f"{data[0]}, {data[1]}, {data[2]}, {data[3]}, {data[4]}\n")
del_piece(piece_id)
clean_tk()
except IndexError:
return
def search_by_id(artistid):
query = f"SELECT * FROM pieces WHERE artistid = ?"
result = exec_query(query, str(artistid))
data = result.fetchall()
return data
def search_by_medium(medium):
query = f"SELECT * FROM pieces WHERE medium LIKE ?"
result = exec_query(query, ['%'+medium+'%'])
data = result.fetchall()
return data
def search_by_price(price):
query = f"SELECT * FROM pieces WHERE price <= ?"
result = exec_query(query, [price])
data = result.fetchall()
return data
def restart_data():
drop_tables()
create_tables()
populate_tables()
with open(file_path, 'w') as file:
file.write('')
#add_artist(("BOB", "Mi casa", None, "Taiwan", "06660"))
#add_piece((6, "Su Casa", "Bic sobre cuaderno", 6666.666))
#sell_piece(18)
restart_data()
com_bg = "dodger blue"
alt_bg = "deep sky blue"
window = tk.Tk()
window.title("Galeria de Arte")
window.geometry("800x600")
window["bg"] = com_bg
lbl_artist_id = tk.Label(text="Id Artista", font="Verdana 12")
lbl_artist_id.place(x=40, y=230, width=80, height=25)
lbl_artist_id["bg"] = com_bg
txt_artist_id = tk.Entry(font="Verdana 12")
txt_artist_id["justify"] = "center"
txt_artist_id.place(x=120, y=230, width=40, height=25)
lbl_piece_title = tk.Label(text="Titulo", font="Verdana 12")
lbl_piece_title.place(x=40, y=270, width=60, height=25)
lbl_piece_title['bg'] = com_bg
txt_piece_title = tk.Entry(font="Verdana 12")
txt_piece_title.place(x=100, y=270, width=400, height=25)
def add_art_piece():
artist_id = txt_artist_id.get()
if artist_id == '':
txt_artist_id.focus()
return
title = txt_piece_title.get()
if title == '':
txt_piece_title.focus()
return
medium = txt_medium.get()
if medium == '':
txt_medium.focus()
return
price = txt_price.get()
if price == '' or not price.isdigit():
txt_price.delete(0, 'end')
txt_price.focus()
return
clean_tk()
add_piece((artist_id,title,medium,price))
btn_add_piece = tk.Button(text="Agregar Pieza",
font="Verdana 12",
command=add_art_piece)
btn_add_piece['bg'] = alt_bg
btn_add_piece.place(x=510, y=270, width=250, height=25)
def display_artists():
query = "SELECT * FROM artists"
data = exec_query(query)
lst_out.delete(0, 'end')
for art in data:
artist_id = (str(art[0]).rjust(3)).ljust(5)
name = (art[1].rjust(15)).ljust(20)
address = art[2].rjust(20)
town = art[3].rjust(20) if art[3] is not None else " "
country = art[4].rjust(20)
postcode = art[5].rjust(20)
line = artist_id+name+address+town+country+postcode
lst_out.insert('end', line)
def display_pieces(data):
lst_out.delete(0, 'end')
for art in data:
piece_id = (str(art[0]).rjust(5)).ljust(8)
artist_id = (str(art[1]).rjust(5)).ljust(8)
title = art[2].rjust(40)
medium = art[3].rjust(20)
price = str(art[4]).rjust(20)
line = piece_id+artist_id+title+medium+price
lst_out.insert('end', line)
def search():
search_by = sel_by.get()
lst_out.delete(0, 'end')
match search_by:
case 'ID Artista':
artistid = txt_artist_id.get()
if artistid.isdigit():
data = search_by_id(artistid)
display_pieces(data)
case 'Material':
medium = txt_medium.get()
data = search_by_medium(medium)
display_pieces(data)
case 'Precio':
price = txt_price.get()
data = search_by_price(price)
display_pieces(data)
case _:
lst_by.focus()
btn_find = tk.Button(text="Buscar por", font="Verdana 12", command=search)
btn_find.place(x=510, y=230, width=135, height=25)
btn_find['bg'] = alt_bg
sel_by = tk.StringVar(window)
sel_by.set("------------")
by_ops = [ 'ID Artista', 'Material', 'Precio' ]
lst_by = tk.OptionMenu(window, sel_by, *by_ops)
lst_by.place(x=645, y=230, width=115, height=25)
lst_by['bg'] = alt_bg
lbl_medium = tk.Label(text="Material", font="Verdana 12")
lbl_medium['bg'] = com_bg
lbl_medium.place(x=160, y=230, width=80, height=25)
txt_medium = tk.Entry(font="Verdana 12")
txt_medium["justify"] = "center"
txt_medium.place(x=240, y=230, width=120, height=25)
lbl_price = tk.Label(text="Precio <", font="Verdana 12")
lbl_price['bg'] = com_bg
lbl_price.place(x=370, y=230, width=70, height=25)
txt_price = tk.Entry(font="Verdana 12")
txt_price["justify"] = "center"
txt_price.place(x=440, y=230, width=60, height=25)
btn_showall = tk.Button(text="Mostrar todos los artistas",
font="Verdana 12",
command=display_artists)
btn_showall['bg'] = alt_bg
btn_showall.place(x=510, y=190, width=250, height=25)
lst_out = tk.Listbox(font="Verdana 12")
lst_out["justify"] = "left"
lst_out["bg"] = "tomato"
lst_out.place(x=40, y=310, width=720, height=280)
def new_artist():
name = txt_in_name.get()
if name == '':
txt_in_name.focus()
return
addrs = txt_in_adrs.get()
if addrs == '':
txt_in_adrs.focus()
return
town = txt_in_town.get() #opt
country = txt_in_country.get()
if country == '':
txt_in_country.focus()
return
postal = txt_in_code.get()
if country == '':
txt_in_code.focus()
return
new_artist = (name, addrs, town, country, postal)
add_artist(new_artist)
clean_tk()
lbl_title = tk.Label(text="Gestion de Artistas y Obras")
lbl_title['bg'] = com_bg
lbl_title['font'] = "Verdana 30"
lbl_title.place(x=120, y=10, width=550, height=80)
y1 = 100
y2 = y1+(y1/2)
x1 = 40
lbl_art_name = tk.Label(text="Nombre", font="Verdana 12")
lbl_art_name.place(x=x1, y=y1, width=70, height=25)
lbl_art_name['bg'] = com_bg
txt_in_name = tk.Entry(font="Verdana 12")
txt_in_name.place(x=x1+70, y=y1, width=220, height=25)
lbl_art_adrs = tk.Label(text="Dirección", font="Verdana 12")
lbl_art_adrs['bg'] = com_bg
lbl_art_adrs.place(x=340, y=y1, width=70, height=25)
txt_in_adrs = tk.Entry(font="Verdana 12")
txt_in_adrs.place(x=420, y=y1, width=340, height=25)
lbl_art_town = tk.Label(text="Ciudad", font="Verdana 12")
lbl_art_town['bg'] = com_bg
lbl_art_town.place(x=x1, y=y2, width=80, height=25)
txt_in_town = tk.Entry(font="Verdana 12")
txt_in_town.place(x=x1+70, y=y2, width=180, height=25)
lbl_art_country = tk.Label(text="Región", font="Verdana 12")
lbl_art_country['bg'] = com_bg
lbl_art_country.place(x=x1+260, y=y2, width=70, height=25)
txt_in_country = tk.Entry(font="Verdana 12")
txt_in_country.place(x=x1+330, y=y2, width=160, height=25)
lbl_art_code = tk.Label(text="Cod. Postal", font="Verdana 12")
lbl_art_code['bg'] = com_bg
lbl_art_code.place(x=540, y=y2, width=90, height=25)
txt_in_code = tk.Entry(font="Verdana 12")
txt_in_code.place(x=630, y=y2, width=130, height=25)
btn_add_art = tk.Button(text="Agregar artista",
font="Verdana 12",
command=new_artist)
btn_add_art["bg"] = alt_bg
btn_add_art.place(x=x1, y=190, width=250, height=25)
btn_del_art = tk.Button(text="Vender pieza",
font="Verdana 12",
command=sell_piece)
btn_del_art["bg"] = alt_bg
btn_del_art.place(x=280, y=190, width=250, height=25)
def clean_tk():
txt_in_name.delete(0,'end')
txt_in_adrs.delete(0,'end')
txt_in_town.delete(0,'end')
txt_in_country.delete(0,'end')
txt_in_code.delete(0,'end')
lst_out.delete(0, 'end')
txt_artist_id.delete(0,'end')
txt_piece_title.delete(0,'end')
txt_medium.delete(0,'end')
txt_price.delete(0,'end')
window.mainloop()

47
final/final.py Normal file
View File

@ -0,0 +1,47 @@
from . import (
fin01 as ex01,
fin02 as ex02,
fin03 as ex03,
fin04 as ex04,
fin05 as ex05
)
from common.common import (
user_input,
run_func,
print_run_func,
opcs_default,
clear
)
tab = ' '
def challenges():
select_ok = False
while not select_ok:
clear()
print(tab, '1)', "Shift Code #146")
print(tab, '2)', "Mastermind #147")
print(tab, '3)', "Passwords #148")
print(tab, '4)', "Times Tables GUI #149")
print(tab, '5)', "Art Gallery #150")
opcs_default(1)
selection = user_input(9)
match selection:
case 1:
run_func(ex01.fin_01)
case 2:
run_func(ex02.fin_02)
case 3:
print_run_func(ex03.fin_03)
case 4:
print_run_func(ex04.fin_04)
case 5:
print_run_func(ex05.fin_05)
case 'v':
return
case 's':
select_ok = True
exit(0)
case _:
continue

13
images.md Normal file
View File

@ -0,0 +1,13 @@
![img](./imgs/basics_001-059.png)
![img](./imgs/final_146-150.png)
![img](./imgs/final_150.png)
![img](./imgs/interm_069-123.png)
![img](./imgs/main_menu.png)
![img](./imgs/pattern_067.png)
![img](./imgs/sqlite_145.png)
![img](./imgs/tkinter_124-138.png)
![img](./imgs/tkinter125.png)
![img](./imgs/tkinter_128.png)
![img](./imgs/tkinter_134.png)
![img](./imgs/tkinter_138.png)
![img](./imgs/turtle_060-068.png)

BIN
imgs/basics_001-059.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
imgs/final_146-150.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

BIN
imgs/final_150.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
imgs/interm_069-123.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

BIN
imgs/main_menu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

BIN
imgs/sqlite_145.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
imgs/tkinter125.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
imgs/tkinter_124-138.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
imgs/tkinter_128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
imgs/tkinter_134.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
imgs/tkinter_138.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
imgs/turtle_060-068.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 KiB

View File

@ -2,14 +2,12 @@ class interm004:
def two_d(self): def two_d(self):
"""Create the following using a simple 2D list using the standard Python """Create the following using a simple 2D list using the standard Python
indexing indexing - 0 1 2
- 0 1 2
0 2 5 8
0 2 5 8 1 3 7 4
1 3 7 4 2 1 6 9
2 1 6 9 3 4 2 0"""
3 4 2 0
"""
bidims = [[2,5,8],[3,7,4],[1,6,9],[4,2,0]] bidims = [[2,5,8],[3,7,4],[1,6,9],[4,2,0]]
print(" | 0 | 1 | 2 |\n━━━━━━━━━━━━━━━") print(" | 0 | 1 | 2 |\n━━━━━━━━━━━━━━━")
for i in range(len(bidims)): for i in range(len(bidims)):

View File

@ -1,9 +1,9 @@
class interm007: class interm007:
def sub_118(self): def sub_118(self):
"""Define a subprogram that will ask the user to enter a number and """Define a subprogram that will ask the user to enter a number and save
save it as the variable \'num\'. Define another subprogram that will it as the variable 'num'. Define another subprogram that will use 'num'
use \'num\' and count from 1 to that number.""" and count from 1 to that number."""
def save_num(): def save_num():
return int(input("Ingresa un número: ")) return int(input("Ingresa un número: "))
@ -16,15 +16,13 @@ class interm007:
def sub_119(self): def sub_119(self):
"""Define a subprogram that will ask the user to pick a low and a high """Define a subprogram that will ask the user to pick a low and a high
number, and then generate a random number between those two values and number, and then generate a random number between those two values and
store it in a variable called \'comp_num\'. store it in a variable called 'comp_num'. Define another subprogram that
Define another subprogram that will give the instruction \'I am thinking will give the instruction 'I am thinking of a number…' and then ask the
of a number\' and then ask the user to guess the number they are user to guess the number they are thinking of. Define a third subprogram
thinking of. that will check to see if the comp_num is the same as the user's guess.
Define a third subprogram that will check to see if the comp_num is the If it is, it should display the message 'Correct, you win', otherwise it
same as the user's guess. If it is, it should display the message should keep looping, telling the user if they are too low or too high
\'Correct, you win\', otherwise it should keep looping, telling the user and asking them to guess again until they guess correctly."""
if they are too low or too high and asking them to guess again until they
guess correctly."""
from random import randint from random import randint
def num_gen(): def num_gen():
ini = int(input("Ingresa un número inicial: ")) ini = int(input("Ingresa un número inicial: "))
@ -50,25 +48,21 @@ class interm007:
check_nums(secret, guess) check_nums(secret, guess)
def sub_120(self): def sub_120(self):
"""Display the following menu to the user: """Display the following menu to the user: 1) Addition
1) Addition 2) Subtraction
2) Subtraction Enter 1 or 2:
Enter 1 or 2:
If they enter a 1, it should run a subprogram that will generate two If they enter a 1, it should run a subprogram that will generate two
random numbers between 5 and 20, and ask the user to add them together. random numbers between 5 and 20, and ask the user to add them together.
Work out the correct answer and return both the user's answer and the Work out the correct answer and return both the user's answer and the
correct answer. correct answer. If they entered 2 as their selection on the menu, it
If they entered 2 as their selection on the menu, it should run a should run a subprogram that will generate one number between 25 and 50
subprogram that will generate one number between 25 and 50 and another and another number between 1 and 25 and ask them to work out num1 minus
number between 1 and 25 and ask them to work out num1 minus num2. This num2. This way they will not have to worry about negative answers. Return
way they will not have to worry about negative answers. Return both the both the user's answer and the correct answer. Create another subprogram
user's answer and the correct answer. that will check if the user's answer matches the actual answer. If it
Create another subprogram that will check if the user's answer matches does, display 'Correct', otherwise display a message that will say
the actual answer. If it does, display \'Correct\', otherwise display a 'Incorrect, the answer is' and display the real answer. If they do not
message that will say \'Incorrect, the answer is\' and display the real select a relevant option on the menu you should display a suitable message."""
answer.
If they do not select a relevant option on the first menu you should
display a suitable message."""
from random import randint from random import randint
def menu(): def menu():
print( print(
@ -170,11 +164,10 @@ class interm007:
menu() menu()
def sub_122(self): def sub_122(self):
"""Create the following menu: """Create the following menu: 1) Add to file
1) Add to file 2) View all records
2) View all records 3) Quit program
3) Quit program Enter the number of your selection:
Enter the number of your selection:
If the user selects 1, allow them to add to a file called Salaries.csv If the user selects 1, allow them to add to a file called Salaries.csv
which will store their name and salary. If they select 2 it should which will store their name and salary. If they select 2 it should
display all records in the Salaries.csv file. If they select 3 it should display all records in the Salaries.csv file. If they select 3 it should
@ -229,14 +222,8 @@ class interm007:
"""In Python, it is not technically possible to directly delete a record """In Python, it is not technically possible to directly delete a record
from a .csv file. Instead you need to save the file to a temporary list from a .csv file. Instead you need to save the file to a temporary list
in Python, make the changes to the list and then overwrite the original in Python, make the changes to the list and then overwrite the original
file with the temporary list. file with the temporary list. Change the previous program to allow you to
Change the previous program to allow you to do this. Your menu should do this. Your menu should have the new option: 3) Delete a record"""
now look like this:
1) Add to file
2) View all records
3) Delete a record
4) Quit program
Enter the number of your selection:"""
from os import getcwd as pwd from os import getcwd as pwd
from os.path import isfile from os.path import isfile
import csv import csv

View File

@ -5,6 +5,7 @@ from trtl import trtl
from interm import interm from interm import interm
from tkgui import tkgui from tkgui import tkgui
from sqlite import sqlite from sqlite import sqlite
from final import final
from common.common import clear, user_input, opcs_default from common.common import clear, user_input, opcs_default
def toc(): def toc():
@ -147,8 +148,7 @@ def main():
case 5: case 5:
sqlite.challenges() sqlite.challenges()
case 6: case 6:
#final_challenges() final.challenges()
pass
case 's': case 's':
select_ok = True select_ok = True
exit(0) exit(0)