Login System - Python - Follow Up - python-3.9

This is a continuation of my Login system/ actual code for my Hotel Booking system. I am not that great at programming so do pardon any mistakes that I did. I did sort out my previous issue but then another issue occurred after that. Here is the link to my previous issue: Login System - Python.
print("WELCOME TO THE MAJESTIC HOTEL lOGIN SYSTEM")
print("************************************************")
account = input("Do you have an account? Yes or No: ")
def MainMenu():
print("WELCOME TO THE MAJESTIC HOTEL\n")
print(" 1 Room Booking\n")
print(" 2 Rooms Info\n")
print(" 3 Payment\n")
print(" 4 Record\n")
print(" 0 Exit\n")
choice = int(input("="))
if choice == 1:
print(" ")
Room_Booking()
if choice == 2:
print(" ")
Room_Info()
if choice == 3:
print(" ")
Payment()
if choice == 4:
print(" ")
Record()
if choice == 0:
print(" ")
Exit()
def Room_Booking():
check_In = str(input(" Enter Check In Date: "))
check_Out = str(input(" Enter Check Out Date: "))
print(" \n")
print(" 1 One Bed AC\n")
print(" 2 One Bed Non-AC\n")
print(" 3 Standard Bed AC\n")
print(" 4 Standard Bed Non-AC\n")
print(" 5 Three Bed AC\n")
print(" 6 Three Bed Non-AC\n")
print(" 7 Four Bed AC\n")
print(" 8 Four Bed Non-AC\n")
Room_Type = int(input(" Choose a room type from above: "))
if Room_Type == 1:
for line in open("rooms.txt", "r").readlines():
x = line.split("-")
if x[1] == 'One Bed AC':
print(x)
def get_existing_users():
with open("login.txt", "r" ) as f:
for line in f.readlines():
# This expects each line of a file to be (name, pass) separated by whitespace.
username, password = line.rstrip("\n").split(',')
yield username, password
def authorised_details(username, password):
return any((user == (username, password) for user in get_existing_users()))
def existing_Users(username):
return any((usr_name == username) for usr_name, _ in get_existing_users())
# above is equivalent of:
#
# for usr_name, _ in get_existing_users():
# if usr_name == username:
# return True
# return False
def login():
count = 0
while count < 3:
username = input("Enter Username: ")
password = input("Enter a Password: ")
if authorised_details(username, password):
print("Welcome to the Majestic Hotel Booking System")
MainMenu()
if existing_Users(username):
print("The password entered is wrong, please try again")
print("The username entered is wrong, please try again")
count = count + 1
def register():
forename = input("Enter forename: ")
surname = input("Enter Surname: ")
year = input("Enter year you are born: ")
if year <= '2004':
print("You are old enough to register yourself")
username = forename[0]+surname[0:3]+year[3:4]
print("Username: ", username)
password = input("Enter a password: ")
file = open("login.txt","a")
file.write(username + "," + password + "\n")
file.close()
MainMenu()
else:
print("Sorry you are not old enough to register by yourself")
if account == "No":
print(register())
if account == "Yes":
print(login())
I am using the details that I created for my previous problem and this was saved in a text file called "login.txt", it was saved like this:
RMoo0,door
I ran the code again and the issue occurred right at the end :
WELCOME TO THE MAJESTIC HOTEL LOGIN SYSTEM
************************************************
Do you have an account? Yes or No: Yes
Enter Username: RMoo0
Enter a Password: door
Welcome to the Majestic Hotel Booking System
WELCOME TO THE MAJESTIC HOTEL
1 Room Booking
2 Rooms Info
3 Payment
4 Record
0 Exit
=1
Enter Check In Date: 22
Enter Check Out Date: 22
1 One Bed AC
2 One Bed Non-AC
3 Standard Bed AC
4 Standard Bed Non-AC
5 Three Bed AC
6 Three Bed Non-AC
7 Four Bed AC
8 Four Bed Non-AC
Choose a room type from above: 1
['01', 'One Bed AC', '£30', 'Y\n']
['09', 'One Bed AC', '£30', 'Y\n']
The password entered is wrong, please try again
The username entered is wrong, please try again
Enter Username:
Can someone please help me out and explain the solution in a way that I will understand.

What you're seeing is exactly what your loop is doing:
while count < 3:
username = input("Enter Username: ")
password = input("Enter a Password: ")
if authorised_details(username, password):
print("Welcome to the Majestic Hotel Booking System")
MainMenu()
if existing_Users(username):
print("The password entered is wrong, please try again")
print("The username entered is wrong, please try again")
count = count + 1
So, after MainMenu() finishes, you do this:
Check if existing_Users(username), and if true print a message.
Print another message, always.
Increment a counter and re-start the loop, the first action of which is to prompt the user for input.
In a comment above, you state:
I want to get rid of the last three lines that were outputted.
So... You don't want to print those last two lines, and you don't want to re-start the loop? In that case, simply remove those print operations and make a loop just a non-looping block of code:
username = input("Enter Username: ")
password = input("Enter a Password: ")
if authorised_details(username, password):
print("Welcome to the Majestic Hotel Booking System")
MainMenu()
That way when MainMenu() completes, the program will simply terminate.
If you also want to add a print operation for when authorised_details(username, password) is false, you can add an else to cover that:
username = input("Enter Username: ")
password = input("Enter a Password: ")
if authorised_details(username, password):
print("Welcome to the Majestic Hotel Booking System")
MainMenu()
else:
print("Login failed, please try again")
Edit: If you do want to loop but only for authentication then you can put this logic back into a loop and perhaps use a break after MainMenu(). Something like this:
while count < 3:
username = input("Enter Username: ")
password = input("Enter a Password: ")
if authorised_details(username, password):
print("Welcome to the Majestic Hotel Booking System")
MainMenu()
break
else:
print("Login failed, please try again")
count = count + 1
This will allow the loop to repeat, but not if the if condition was true. In that case after running MainMenu() the break statement will exit the loop.

Related

This asks the user for username + password and in case user doesnt have one it asks user to create one but gives error -name log4 can be undefined-

username = 'Cube'
pin_code = '1234'
log1 = input('Do you have an account? (Yes/No)\n')
if log1 == 'Yes':
log2 = str(input('Enter your Username: '))
if log2 == username:
log4 = input('Enter 4-Pin Code: ')
elif log2 != username:
print('Username is incorrect, please try again')
if log4 == pin_code:
print('Welcome Back ', username + '!')
else:
print('Password is incorrect, Please try again')
if log1 == 'No':
log3 = input('Would you like to make one? (Yes/No)\n')
if log3 == 'Yes':
log5 = input('Enter a Username: ')
log6 = input('Enter 4-Pin Code: ')
if log3 == 'No':
print(' ')

I am trying to debug this code it is giving me a NameError: name'male_count' is not defined. Here is what I have so far

#allow user to enter data for multiple individuals
name = raw_input("what is your name?: ")
age = raw_input("what is age?: ")
sex = raw_input("Please enter male or female: ")
while name != "":
if sex == "male":
male_count = male_count + 1
male_age = male_age + int(age)
if sex == "female":
female_count = female_count + 1
female_age = female_age + int(age)
print("Please enter male or female")
#calculate average age for males and females
if male_count > 0:
male_avg = male_age / male_count
if female_count > 0:
female_avg = female_age / female_count
print("There are",male_count,"males with an average age of",male_avg)
print("There are",female_count,"females with an average age of",female_avg)
You never declare male_count = 0

User input manipulation

Please I'm in need of a lift right now. I want the user to be able to have the option of re-entering his numerical input if perhaps, he/she entered an alphabet by mistake.
Right now it just loops infinitely on the "Please select a valid option" and "Try again" outputs.
print("\n-----Factorial Calculator------\n")
def option():
opt = (input('Try again? y/n: '))
if option == 'y':
facto(num)
elif option == 'n':
exit()
else:
print("Please select a valid option")
option()
def facto(factorial):
fact = 1
for nums in range(1, num+1):
fact = fact * nums
return fact
try:
num = int(input("Number(Just input the number): "))
except ValueError:
print("Invalid input")
option()
print(f" {num}! = {facto(num)}")
First, rather than calling option recursively, simply put a loop inside it.
Second, when the user enters y into the "Try again?" input, it should not calculate the factorial there, but return the user back to the original input, by breaking out of the loop within the option call.
Putting these two together will fix option:
def option():
while True:
retry = input('Try again? y/n: ')
if retry == 'y':
break
elif retry == 'n':
exit()
else:
print("Please select a valid option")
Third, you need some kind of loop around your initial input, otherwise how will they enter the number again after indicating they want to try again?
Fix this by sticking the initial num assignment and option call in a while loop, with the same try; except statement you had before:
while True:
try:
num = int(input("Number(Just input the number): "))
break
except ValueError:
print("Invalid input")
option()
continue
I see someone else got an answer in ahead of me which identified the bug in option() and the bug which prevents user re-entering the number but I'll post this anyway because there are other ways your code can be restructured.
print("\n-----Factorial Calculator------\n")
# Each function should handle just one thing
# Eg, option() should just handle whether user wants to continue, not try to handle factorial calc
# Also it's best to let the mainline logic decide whether to exit() or not
# This function should just return 'y' or 'n'
# Note that the original code captured the user's option in variable `opt` but then checked variable `option`.
# That's why it looped endlessly
def option():
opt = ' '
while ( opt != 'y' and opt != 'n' ):
opt = (input('Try again? y/n: '))
if opt == 'y':
return opt
elif opt == 'n':
return opt
else:
print("Please select a valid option")
# You specified argument `factorial` in original code but then did not use it.
# It still worked because the variable `num` was defined at the top level in the mainline
# Functions should be self-contained and rely only on the arguments that are passed into them
def facto(n):
fact = 1
for nums in range(1, n+1):
fact = fact * nums
return fact
opt = 'y'
is_print = False
while ( opt == 'y' ):
try:
num = int(input("Number(Just input the number): "))
opt = 'n'
is_print = True
except ValueError:
print("Invalid input")
opt = option()
if ( is_print ):
print(f" {num}! = {facto(num)}")
Thanks everyone for the help, but after struggling with it for a couple of days and taking few days off due to illness, I somehow did it. Eureka!
def facto(n):
fact = 1
for i in range(1, n + 1):
fact = fact * i
return fact
def opt():
option = (input("Do you want to try again? y/n: "))
if option == 'y':
number()
elif option == 'n':
exit()
else:
print("\nPlease select a valid option.")
opt()
def number():
try:
num = int(input("Number: "))
print(f"{num}! = {facto(num)}")
except ValueError:
print("Invalid input! Please input integers only")
opt()
number()

My Discord bot's command suddenly stopped listening to my arg hints, then stopped working altogether

I'm trying to write a command to collect free agent offers in our local basketball simulation server into CSV format so we can go through them more quickly and efficiently. I wrote this command to take the offers, but suddenly, my arguments stopped listening to the hints I gave:
async def offer(ctx, firstName: str, lastName: str, amount: float, length: int, option: str='no', ntc: str='no'):
It allows integers to be used for lastName, even though I used these hints here. It was working normally, except that it didn't throw errors if you used the wrong type of input, and then suddenly my Discord bot stops responding to this command altogether. It still responds correctly to other commands, so something is wrong with this command specifically, and I can't figure it out...
Here's the full command:
#bot.command()
async def offer(ctx, firstName: str, lastName: str, amount: float, length: int, option: str='no', ntc: str='no'):
team = ctx.channel.category.name
username = ctx.author.name
usermention = ctx.author.mention
userid = ctx.author.id
if option.lower() == 'po' or option.lower() == 'yes': option = 'yes'
else: option = 'no'
if ntc.lower() == 'ntc' or ntc.lower() == 'yes': ntc = 'yes'
else: ntc = 'no'
offer = (str(team) + ',' + str(username) + ',' + str(userid) + ',' + str(firstName) + ' ' + str(lastName) + ',' + str(amount) + ',' + str(length) + ',' + str(option) + ',' + str(ntc))
offersList.append(offer)
baseText = ('The ' + team + ' (' + usermention + ') offered ' + firstName + ' ' + lastName + ' a $' + str(amount) + ' million contract for ' + str(length) + ' years')
if option == 'no' and ntc == 'no': text = (baseText + '.')
if option == 'no' and ntc == 'yes': text = (baseText + ' with an NTC.')
if option == 'yes' and ntc == 'no': text = (baseText + ' with a player option.')
if option == 'yes' and ntc == 'yes': text = (baseText + ' with a player option and an NTC.')
print(text)
await ctx.send(text)
Please let me know if it's something obvious, or I have to rethink this command altogether... thanks everyone!
Ahmed asked if it executed a print function at the beginning of the command. Once I added this print function, suddenly the whole command started working again. I'm not sure why, but it's working... so I won't touch it. lol. thanks guys.

Computercraft log in system not working with fs API

I'm working on a Windows 8 mock-up OS for Computercraft, and my log in system isn't working. I have been trying to figure it out for the past hour or so and it's really frustrating.
Here's the log in code:
-- Log-in and User Definition Service
--- Variables
userExists = fs.exists("/Users/.config/userConfig.cfg")
termx, termy = term.getSize()
halfx = math.floor(termx*0.5)
halfy = math.floor(termy*0.5)
prompt = "Welcome"
uprompt = "Username: "
pprompt = "Password: "
userConfig = fs.open("/Users/.config/userConfig.cfg", "r")
edituserConfig = fs.open("/Users/.config/userConfig.cfg", "w")
--- Functions
function login(user)
if user == "admin" then
term.setCursorPos(1,1)
term.setTextColor(256)
print (user)
elseif user == "guest" then
print (user)
else
print ("nil")
end
end
function userCheck()
if userExists == true then
term.clear()
term.setBackgroundColor(8)
term.setCursorPos(halfx-0.5*#prompt, halfy - 4)
term.clear()
print (prompt)
term.setCursorPos((halfx-#uprompt), (halfy - 2))
write (uprompt)
term.setCursorPos((halfx-#uprompt), (halfy - 1))
write (pprompt)
term.setCursorPos((halfx), (halfy - 2))
upin = read()
term.setCursorPos((halfx), (halfy - 1))
ppin = read("*")
if upin == userConfig.readLine(21) and ppin == userConfig.readLine(24) then
print ("ADMIN")
elseif upin == userConfig.readLine(33) and ppin == userConfig.readLine(36) then
login("guest")
end
elseif userExists == false then
elseif userExists == nil then
end
end
--- Main
userCheck()
userConfig.cfg:
-- Format as follows:
--
-- (name):
--
-- (prop):
-- "(value)"
--
-- (prop):
-- "(value)"
--
-- (prop):
-- "(value)"
--
--
-- (name):
-- [etc.]
Admin:
user:
"Admin"
pass:
"admin"
auth:
"1"
Guest:
user:
"Admin"
pass:
nil
auth:
"0"
Root:
user:
nil
pass:
nil
auth:
"2"
readLine does not accept arguments and only reads the next line. Your best bet would be to use tables and textutils.serialize to write it all to a file and then when reading use textutils.unserialize to have it inside a table.
Admin:
user:
"Admin"
pass:
"admin"
auth:
"1"
Can be written inside a table such as
{
Admin = {
user = "Admin"
pass = "admin"
auth = "1"
}
Guest = {
user = "Admin"
pass = nil
auth = "0"
}
}
This would work much in the way that you want, and allows for more variability as well as expansion. Of course to read from it is a different story, and i would use a function to find and send either the auth code back, or nil if it didn't work.
Such as
local function findUsers(username,password)
--This will read the file and put all it's data inside a table, and then close it.
local file = fs.open("userConfig.cfg","r")
local userRanks = textutils.unserialize(file.readAll())
file.close()
--To read all the data in a table, i'm going to do this.
for a,v in pairs(userRanks) do
if type(v) == "table" then
if userRanks[a].user == username and userRanks[a].pass == password then
return userRanks[a].auth
end
end
end
--[[If we look through the entire file table, and the username and password aren't the same
as on file, then we say we couldn't find it by returning nil]]--
return nil
end
Now for your input area all you have to do is when they input the username and password just call this afterwards, also if allows you to have the auth code
local auth = findUsers(upin,ppin)
--If they inputted an actual username and password
if auth ~= nil then
--If the auth code from the rank is "1"
if auth == "1" then
--Do whatever stuff you want
elseif auth == "2" then
--Do whatever other stuff for this auth code
end
elseif auth == nil then
print("Oh no you inputted an invalid username and/or password, please try again!"
end
To expand on Dragon53535's answer:
Here's a quick routine I threw together that reads a file into a table:
local function fileToTable(path)
-- first we make sure that the path can be opened
assert(fs.exists(path), path..' does not exist!')
assert(not fs.isDir(path), path..' is a directory!')
local tSrc = {}
local inFile = fs.open(path, 'r')
-- we set line to a non-nil value
local line = ''
-- we continue the loop until line is nil
while line do
-- we read a line from the file
line = inFile.readLine()
-- now we save the value of line to our table
-- line will be nil at EOF
tSrc[#tSrc+1] = line
end
inFile.close()
return tSrc
end
After running userConfig = fileToTable('/Users/.config/userConfig.cfg'), you'd replace something like userConfig.readLine(24) with userConfig[24].
Alternatively, you could check out CC's implementation of the io library. It's a standard Lua library (though in CC it's an fs wrapper), so code can be moved more easily out of CC.
In particular, io.lines() would be helpful here.
The above code rewritten to use io.lines:
local function fileToTable(path)
-- first we make sure that the path can be opened
assert(fs.exists(path), path..' does not exist!')
assert(not fs.isDir(path), path..' is a directory!')
local tSrc = {}
-- iterate over file
-- io.lines is neat, since it opens and closes the file automatically
for line in io.lines(path) do
tSrc[#tSrc+1] = line
end
return tSrc
end
As you can see, this is much smaller (only 9 lines of code!) and more manageable. The reason it's not my preferred solution in CC is that io sits on top of fs, so it's probably better to remove the middleman.
Hope this helps.

Resources