7 svar
956 visningar
sandy99 behöver inte mer hjälp
sandy99 42
Postad: 15 mar 2019 14:26

Python: program för bokning

Hej, 

jag försöker göra ett program där man kan boka platser på ett tåg i Python och har kommit rätt långt men det är två grejer där jag inte är 100 på hur jag ska lösa det. Så, det första jag gör i uppgiften är att rita ut tågvagnen med alla platser. När man bokar t.ex. 5 biljetter ska dessa fem platser markeras i bilden när den ritas ut.

Det är det jag inte riktigt vet hur jag ska göra. Har funderat kring att göra varje plats på tåget till en klass, eller om jag borde ha själva "ritningen" i en funktion eller klass som uppdateras.

När man bokar ska man skriva B och sen antalet platser och då ska detta uppdateras i bilden, (jag kommer markera redan bokade platser med * på bägge sidor om siffran, och när man ska avboka skriver man A och platsnummer och så ska detta uppdateras i bilden.

Det är själva denna bokning och avbokning som jag klurat på de senaste dagarna..

Här är min nuvarande kod:

 


print(
"|-------------------------------------|\n"
"| 1 3 5 7 9 11 13 15 17 19 21 23 25 |\n"
"| 2 4 6 8 10 12 14 16 18 20 22 24 26 |\n"
"|-------------------------------------|\n"
"| |\n"
"| Mittgång |\n"
"| |\n"
"| |\n"
"|-------------------------------------|\n"
"| 27 29 31 33 35 37 39 41 43 45 47 49 |\n"
"| 28 30 32 34 36 38 40 42 44 46 48 50 |\n"
"|-------------------------------------|\n"
)

class Platsbiljett:

def __init__(self, plats):
self.plats = plats

def __str__(self):
return "{}".format(self.plats)

def create_biljettfil(self, plats):
f = open("biljettfil.txt", "w+")
f.write("PLATSBILJETT\n"
"Avgång - Destination\n"
"Plats " + str(plats) + "\n"
"Mittgång\n")
f.close()
f = open("biljettfil.txt", "r")
if f.mode == "r":
contents = f.read()

return print(contents)

plats = 19
biljett = Platsbiljett(plats)


# Används i senare metod menu_choice
def get_input(prompt_string):
choice = input(prompt_string)
return choice


# Displayar menyn
def menu():
return print("Vad vill du göra?\n"
"Boka, skriv 'B' följt av antal biljetter.\n"
"Avboka, skriv 'A' följt av platsnummer.\n"
"Skriva ut senast bokade biljetter, skriv 'S'.\n"
"Avsluta, skriv 'Q'.\n")


# Frågar användaren om menyval
def menu_choice():
return get_input("Ditt val: ")


# Returnar beroende på användarens val
# B: Vill ta in 2 parametrar, B och antal platser
# A: Vill ta in 2 parametrar, A och platsnummer
# S: Vill ta in en parameter, S, och kalla på funktionen create_biljettfil i klassen Platsbiljett
# Q: Vill ta in en parameter, Q, printa att programmet avslutas och sedan avsluta (menyn ska inte komma upp igen)

"""def execute1(choice):
if choice == "B":

return print("Bokar...")
# LÄGG TILL UPPDATERING AV BOKNING, BOKA PLATSERNA

if choice == "A":

return print("Avbokar...")
"""


def execute(choice):

if choice == "S":
Platsbiljett.create_biljettfil(biljett, plats)

elif choice == "Q":
print("Avslutar...")
quit()


def main():
choice = ""
while choice != "Q":
menu()
execute(menu_choice())
# execute1(menu_choice())


main()

 

Sen har jag börjat försöka på något sånt här:


# Vill göra så här:
# Om användaren skriver B och antal platser:
# - Att så många platser bokas
# - Att dessa platser markeras med en * på varje sida om platsen
#
# Vill göra sågär:
# Om användaren skriver A och platsnummer:
# - Att denna plats avbokas
# - Att de ** som omgivit platsnumret försvinner

"""
class 1:

def __init__(self, plats):
self.plats = plats

def isbooked():
if plats is booked:
return

 


"""

SeriousCephalopod 2696
Postad: 15 mar 2019 15:29 Redigerad: 15 mar 2019 15:37

Det låter som att du bör använda stringformattering för att bättre definiera hur du går från data till utskrift. 

Med stringformattering så kan du på ett kompakt vis definiera man producerar en sträng utifrån i ett visst format utifrån en samling värden utan att behöva göra en massa konkatenering eller separerade print()-kommandon. Det viktigaste verktyget för stringoformattering är str.format() som kombinerar en formateringssträng som beskriver hur data ska presenteras, och en datatupel som är variablerna som ska injiuceras i strängen. 

"Plats {} har status {}".format(13, "obokad")

>Plats 13 har status obokad

Jag ser att du använt str.format några gånger i din kod men var uppmärksam på att du kan använda detta på mer avancerade vis. 

Det viktiga i det hrä sammanhanget dock är att formatteirngsträngen kan specificera sådant som centrering och padding. Om du skriver ut stängar med element som är olika långa så kan de bli feljusterade i förhållande till varandra. 

print("Rad 1:  1, 2, 3")

print("Rad 2:  *1, 2, *3")

Rad 1:  1, 2, 3

Rad 2:  *1, 2, *3

Där rader kolumner blir hackiga men med stringformattering kan du specificera att en kolumn ska ha en viss bredd och om elementet inte fyller upp hela blocket så lägger python till mellanrum för att få saker att ligga snyggt kant i kant.

print("Rad 1: {:>2}, {:>2}, {:>2}".format("1", "2","3"))
print("Rad 2: {:>2}, {:>2}, {:>2}".format("*1", "2","**3"))

Rad 1:   1, 2,   3

Rad 2: *1, 2, *3

Googlar du python string formatting kommer du få några guider om hur stringformatering kan göras men i för att implementera det hela rekommenderar jag att du helt enkellt tänker dig hur du vill att det ska vara och googlar nyckelorden så kommer stackexchange ha kod att låna.

Verktyg 2. Strängformattering kan sedan kombineras med liskontruktion ("list comprehension") vilket är ett kraftfullt verktyg för att gå från listor till listor av strängar och slutligen listor.

1. Ta en lista med element. 2. Producera en ny lista med formatera strängar för elementen. Sätt ihop strängarna i listan med "".join(list).

Exempel.

",".join(["{:>3}".format(i) for i in range(1,20)])

>>' 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19'

["{:>3}".format(i) for i in range(1,20)] är skapar en lista med strängar ["  1", "  2", "  3", ..., " 19"] där varje sträng har fått padding så att de alla är lika breda. 3 tecken. ",".join(list) sätter sedan ihop stränglistan till en sträng genom att sätta kommatecken mellan dem.

För ditt problem kunde man göra saker ännu mer avancerade. 

Låt seats = [True, False, False, True, False] representera bokningsstatus för säten 1 till 5 och om seats[2] == True så vill du producera "*2*" medan om seats[2] == False" så vill du bara producera " 2 " och sedan slår ihop detta med strängformattering, listcomprehension, och single-line-if

seats = [True, False, False, True, False]

" | ".join([("*{}*".format(i) if val == True else " {} ".format(i)) for i, val in enumerate(seats)])

>[True, False, False, True, False]

>*0* |   1   |  2  | *3* |  4

Sånt är lite overkill men som du ser kan man göra väldigt avancerade saker med väldigt lite kod. 

En enklare version vore

seats = [True, False, False, True, False]

string = ""

for i, value in enumerate(seats):

    if value == True:

      string = string + "*{}*".format(i + 1)

   else:

      string = string + " {} ".format(i + 1)

   string = string + " | "

Rekommenderar alltså att du kollar med på strängformattering och på listkonstruktion för att lättare gå från data till output. Vad du modifierar då hela tiden när användaren gör val är just formatteringssträngarna. 

SeriousCephalopod 2696
Postad: 15 mar 2019 16:34

Ovan är ett konceptinlägg.

Ett mer konkret tips är att göra en formatteringssträng som specificerar hur layouten på planet ska se ut och sedan så använder du str.format för att injicera vad du vill ska stå på varje plats via en lista med den informationen typ något i följande stil layout = 

som alltså specificerar hur datan ska skrivas ut, i det här fallet med en specifikation ^5 om att texten vid varje plats ska vara centrerad och ha padding så att texten är i ett utrymme om 5 tecken. 

Sedan kan du bara köra 

layout.format(*lista_med_sätestext)

för att injicera sätestext som generas på något vis. 

layout.format(*list(range(1,51))

ger

Men sifferelement kan nu lätt ersättas med vadsomhelst säg bokstäver i en nonsensmening

layout.format(*list("vi kan ha bokstäver på sätena istället om vi vill vilket är kul"))

ger istället

Det krävs lite arbete att få till layoutsträngen men därefter så är injektionen av data rak. 

sandy99 42
Postad: 18 mar 2019 20:51

Tack så mycket för hjälpen, ska kolla på det här nu!

sandy99 42
Postad: 19 mar 2019 09:16

Jag har försökt få till tågvagnen med format, har kollat på några videos om det och jag tror att det borde fungera bra för min uppgift, så tack för tipset! 

Såhär har jag gjort nu men får SyntaxError, borde jag göra allt till en lista?

layout = {0:^5}{2:^5}{4:^5}{6:^5}{8:^5}{10:^5}{12:^5}{14:^5}{16:^5}{18:^5}{20:^5}{22:^5}{24:^5}
{1:^5}{3:^5}{5:^5}{7:^5}{9:^5}{11:^5}{13:^5}{15:^5}{17:^5}{19:^5}{21:^5}{23:^5}{25:^5}
"-------------------------------------------------------------------------------------"
"Mittgång"
"-------------------------------------------------------------------------------------"
{26:^5}{28:^5}{30:^5}{32:^5}{34:^5}{36:^5}{38:^5}{40:^5}{42:^5}{44:^5}{46:^5}{48:^5}
{27:^5}{29:^5}{31:^5}{33:^5}{35:^5}{37:^5}{39:^5}{41:^5}{43:^5}{45:^5}{47:^5}{49:^5}

layout.format(range(1,50))

print(layout)

och får när jag kör programmet får jag:

layout = {0:^5}{2:^5}{4:^5}{6:^5}{8:^5}{10:^5}{12:^5}{14:^5}{16:^5}{18:^5}{20:^5}{22:^5}{24:^5}
                      ^
SyntaxError: invalid syntax

Process finished with exit code 1

SeriousCephalopod 2696
Postad: 19 mar 2019 09:31 Redigerad: 19 mar 2019 09:32

Formatteringssträngen ska vara en sträng, hela altet. Rekommenderar att du gör små str.format-kommandon för att förstå hur det fungerar.

sandy99 42
Postad: 19 mar 2019 19:04

nu har jag lagt in det och nu printar den tåget men tar med ':^5' men jag ska nog klura lite till på det, känns som att jag kan fixa det

SeriousCephalopod 2696
Postad: 19 mar 2019 20:05

Layout.format(...) returnerar strängen du vill skriva ut.

Svara
Close