time_split = time_input.split(":")
def is_time_valid(time_str: str) -> bool:
hours = len(time_str[0])
minutes = len(time_str[1])
if time_str[0].isdigit() and time_str[1].isdigit():
if hours == 2 and int(time_str[0]) <= 23 and minutes == 2 and int(time_str[1]) <= 59:
joined = ":".join(time_str)
print(f"Start time: {joined}")
return True
else:
print("Invalid time")
return False
else:
print("Invalid time")
return False
while True:
if is_time_valid(time_split):
break ```
I am a beginner in python by the way,
so basically this asks the user to input a time in the format HH:MM, but for some reason when it is invalid (so 9:04 for example) it keeps on looping "invalid time" instead of just once. Does anybody know why?
#π I really need help with a small piece of code
229 messages Β· Page 1 of 1 (latest)
@hollow glacier
Remember to:
- Ask your Python question, not if you can ask or if there's an expert who can help.
- Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
- Explain what you expect to happen and what actually happens.
:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.
Closes after a period of inactivity, or when you send !close.
def is_time_valid(time_str: str) -> bool:
hours = time_str[0]
minutes = time_str[1]
# Check if hours and minutes are valid digits and lengths
if hours.isdigit() and minutes.isdigit():
if len(hours) == 2 and int(hours) <= 23 and len(minutes) == 2 and int(minutes) <= 59:
joined = ":".join(time_str)
print(f"Start time: {joined}")
return True
else:
print("Invalid time")
return False
else:
print("Invalid time")
return False
while True:
time_input = input("Please enter a time (HH:MM): ")
time_split = time_input.split(":")
if len(time_split) == 2 and is_time_valid(time_split):
break
This issue was with your time checking logic
Could you maybe explain it a little more in depth? I am still really confused by the looping stuff
hours = len(time_str[0])
minutes = len(time_str[1])
This part of code is your culprit
See, what you need to do is split the time in two parts from colon.
str.split() function of you is handling that properly and storing it as list of string
You're checking how many characters are in the hour part (time_str[0]) and the minute part (time_str[1]). For example:
If the user enters 9:04, time_str[0] (hours) is "9", and time_str[1] (minutes) is "04".
So len(time_str[0]) is 1 because the hour is just "9" (not "09"), and len(time_str[1]) is 2 because "04" is two characters.
Now, your condition says that the hour must have exactly 2 characters and the minute must also have exactly 2 characters. So when it sees 9:04, it doesn't work because 9 has only 1 character. This is why it's always saying "Invalid time" when you input something like 9:04.
why not do the split and the all the checking inside the function instead and only keep this outside of the function?
while True:
time_input = input("Please enter a time (HH:MM): ")
if is_time_valid(time_input):
break
it would also be advisable to keep printing out of the function to make it more reusable
Is that better?
I mean I do also need to implement an end time and then subtract those two times somehow, so if thats better to do
to demonstrate how it could look if doing it that way
the function could be this simple and small
def is_time_valid(timestamp: str) -> bool:
if ":" not in timestamp:
return False
hours, minutes = timestamp.split(":", 1)
if hours.isdigit() and minutes.isdigit() and len(hours) == 2 and len(minutes) == 2 and int(hours) <= 23 and int(minutes) <= 59:
return True
return False
```but it can be hard to read such long lines, so it might be better to format it on a few more line like:
```py
def is_time_valid(timestamp: str) -> bool:
if not ":" in timestamp:
return False
hours, minutes = timestamp.split(":", 1)
if (
hours.isdigit()
and minutes.isdigit()
and len(hours) == 2
and len(minutes) == 2
and int(hours) <= 23
and int(minutes) <= 59
):
return True
return False
```to make the logic a easier to read and understand
then when calling the function you could do
```py
while True:
start_time = input("Please enter a time (HH:MM): ").strip()
if is_time_valid(start_time):
print(f"Start time: {start_time}")
break
print("Invalid time")
this way you can even ask for the end time before printing the start_time, as you can do that after both getting a valid start_time and end_time by just moving the print() statement that prints the start time to after the two loop for getting the times
Oh wow that is much easier to read
while True:
start_time = input("Please enter a time (HH:MM): ").strip()
end_time = input("Please enter a time (HH:MM): ").strip()
if is_time_valid(start_time) and is_time_valid(end_time):
print(f"Start time: {start_time}")
print(f"Start time: {end_time}")
break
print("Invalid time")
I would do this for the end time right?
it's also fully reusable and customizable if you want different error messages for the two time stamps, for example
while True:
start_time = input("Please enter a start time (HH:MM): ").strip()
if is_time_valid(start_time):
break
print("Invalid start time")
while True:
end_time = input("Please enter an end time (HH:MM): ").strip()
if is_time_valid(end_time):
break
print("Invalid end time")
print(f"Start time: {start_time}")
print(f"End time: {end_time}")
Ahhh alright
thanks a lot for your help
Never knew that you could make the long if statement so easily readable
oops, had a mistake in there that i have now corrected
Yeah I saw it haha
Also,
Do you have a suggestion on how to subtract the end time and start time from each other correctly?
for example 11:05 and 09:05 becomes 02:00
if you are not allowed to use functions from the datetime module/library you would have to do it with some math
I have no clue what the datetime module is, so i definitely am not allowed no
tried to use regular expressions in the first place for this but that isnt allowed either unfortunately
make function that can convert the time stamps to a total number of minutes that the timestamp represents and then just take the end minus the start and then get the duration in the number of minues and have another function that converts the number of minuts back to a proper time stamp in hours and minutes
usually one does the above with seconds, but since you don't concern yourself with seconds you can work in minutes instead
Right
yeah
does python recognize 11 - 09 to be 02?
as each hour is 60 minutes you only have to take the hours * 60 + minutes
or would i have to do that myself
you would need to convert them both to integers before doing the calculation
but why make them all minutes?
because then you can just do end - start and get the duration in minutes, then convert the minutes to hours and minutes again
right
so if the start time were to be 09:05 id have to do
start_time_split = start_time.split(":")
start_time_int = int(start_time_split)
start_time_int[0] * 60 + start_time_int[1]
or is this incorrect
you need to do int() on each value or use map() if you have learned about map yet
it you haven't (which is my guess) it's probably best not to use it
I have seen map fly by when I was trying to fix it myself but I have no clue what it does no
does int(start_time_int[0]) work?
so, you are allowed to use it?
it's one of the python build-ins, so nothing to import to be able to use it
I am basically allowed to use everything but I would have to be able to explain every single thing and be able to use it myself
yes, but you need to assign the result that it returns to a variable
ahh okay
int() doesn't change the value of the variable, it returns the result that you then can do something with
like assign it back to the same or another variable
start_time_split = start_time.split(":")
start_hours = int(start_time_split[0])
start_minutes = int(start_time_split[1])
like this?
or would i have to manually use int(start_time_split[0] for it to work
as this is a function you probably want to keep variable names neutral to reuse the function between both start_time and end_time for example
but yeah, more or less
but there is a different input for both the start and end time, so how would I be able to make a neutral variable for it?
by the way, I really appreciate all the help. I wouldve given up by now if i were on my own
as it is a function the variable can be named something other then the variable that you called it with
look at the example above where i used the same validation function for both start_time and end_time
def time_math(time_change):
time_split = time_change.split(":")
time_int = int(time_split)
def time_math(time_change):
time_split = time_change.split(":")
time_int_hours = int(time_split[0)
time_int_minutes = int(time_split[1])
would either of these be correct?
you can't the above, int() can't operate on a list or tuple or such
de second one would work
the best way to know is if you write the code and try it
if it's a long script you can make a new .py file and just have the minimal code that you want to try and use a string that you set to a variable instead of using input() in such code that you just want to try out different things in
we can try it here in the chat
it is a very long messy script now yeah
not that long now i look at it
#Functions
def is_first_name_valid(name: str) -> bool:
if name.isalpha() and len(name) > 2 and name[0].isupper():
return name
else:
print("Invalid input")
def is_last_name_valid(name: str) -> bool:
if name.isalpha() and len(name) > 2 and name[0].isupper():
return name
else:
print("Invalid input")
while True:
first_name = input("Enter your first name")
if is_first_name_valid(first_name):
break
while True:
last_name = input("Enter your last name")
if is_last_name_valid(last_name):
break
#Testing this version out.
def is_time_valid(time_str: str) -> bool:
if not ":" in time_str:
return False
hours, minutes = time_str.split(":", 1)
if hours.isdigit() and minutes.isdigit() and len(hours) == 2 and len(minutes) == 2 and int(hours) <= 23 and int(minutes) <= 59:
return True
return False
def is_time_valid(time_str: str) -> bool:
if not ":" in time_str:
return False
hours, minutes = time_str.split(":", 1)
if (
hours.isdigit()
and minutes.isdigit()
and len(hours) == 2
and len(minutes) == 2
and int(hours) <= 23
and int(minutes) <= 59
):
return True
return False
while True:
start_time = input("Please enter a time (HH:MM): ").strip()
if is_time_valid(start_time):
print(f"Start time: {start_time}")
break
print("Invalid time")
def time_math(time_change):
time_split = time_change.split(":")
time_int_hours = int(time_split[0])
time_int_minutes = int(time_split[1])
this is it with the comments put away, there was a lot of comments of me trying things
the first part before the comment is something that already works btw,
!e - see how this will fail with errors
time_split = "13:47".split(":")
time_int = int(time_split)
:x: Your 3.13 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File [35m"/home/main.py"[0m, line [35m2[0m, in [35m<module>[0m
003 | time_int = int(time_split)
004 | [1;35mTypeError[0m: [35mint() argument must be a string, a bytes-like object or a real number, not 'list'[0m
π₯
dang
!e
time_split = "13:47".split(":")
time_int_hours = int(time_split[0])
time_int_minutes = int(time_split[1])
print(time_int_hours)
print(time_int_minutes)
:white_check_mark: Your 3.13 eval job has completed with return code 0.
001 | 13
002 | 47
while this works
and even if we didn't print it it would execute without any errors, but we wouldn't get any output either, so it would be hard to know if it gave us the result that we were expecting
Right
this is why it can be good to make a little separate .py file and try small code snippets in in isolation
yeah thats good to know
and then you can integrate it into your code after
I normally use online python for those small things
def time_math(time_change):
time_split = time_change.split(":")
time_int_hours = int(time_split[0])
time_int_minutes = int(time_split[1])
time_total = time_int_hours * 60 + time_int_minutes
print(time_total)
time_math(start_time)
boom
but you don't really want to print it, you want to return it so that you can do things with it, like doing mathematical operations on it
Yeah I printed it to test it out to see if it worked
now I need to get an end time and do the same, subtract it and magically make it into a HH:MM format again
my suggestion would be to return it either way, after your debug print and then remove the debug print line from the code when you have verified it
or in this case as the print happens as the very last thing before you return the same value, you could just call the function within a print() statement instead
so if it returned instead of printing inside the function so that it is in it's final state
you can do
print(time_math(start_time))
that way you don't need to go back and change anything within the function if everything works as expected, then you just change the calling code outside of the function to not print it
ohh alright, didnt know you could print a function
you don't print the function, you print the result of the function
so you can think of it as a variable or the value that the function returns that is getting printed
!gif
Oh wow this gif is very handy
here is a little animation that explains how arguments in a function call and parameters in the function signature and return works
I thought it worked that way but this is a very easy way of explaining
Cant believe its this much trouble for a small assignment πΉ
But I now know what to do thanks to you, thanks a lot
then you need to convert the minutes back to a time stamp if you want to present the duration in that way
should I create a function for that also?
yeah, i would suggest you do that
alright
good to have reusable code
even if you just use it once
it also abstracts the main code so that there isn't to much implementation details in the main body of code
so if i were to have 09:05 it would be 545, i would need to do:
545 / 60
545 % 60
right?
its good practice for me anyway, this week's theme is functions and loops so using it as much as i can is a good way for me to get a grip on it
that way it's easier to follow the main code and the function names can serve as a high level explanation of what is happening and if you want to know the details you can go and look at the implementation in the function
Yeah alright, that is good to know
it's called "extraction" (when you take part of the code and put it in a function that you call from where you took the code) and is a "refactoring" technique (refactoring is the practise of rewriting code to improve it, often restructuring and rewriting parts of it)
then you can try to improve the code in the function to generalize it so it becomes more reusable
yeah makes sense
it also makes the code more manageable by braking it up
but you want to break it up at logical boundaries, if you break it up in the wrong way the code just gets scattered in several places and it instead gets hard to follow the logic of the code and you will have to jump around in the code a lot to where the different functions are defined when reading the code to understand what is happening
so it's important to do it in the right way if applying extraction
isnt a good way of doing that just commenting a section: "Functions" and have all your functions there?
sorry, i had to walk away from the keyboard for a bit
you don't really need to commend a section, just put it in a specific place where you gather your functions
@hollow glacier by the way, you might want explanations for things in the validation function
like how some of it works and why we do certain things in there in a specific way
Oh alright, no worries by the way youβve already helped a ton
Yeah that might be handy, ill add that when im back
so, if you have any questions about the code, please ask them so that you know it properly
I dont really have any questions about the code itself, I do have questions about some things you mentioned earlier, like datetime and map
that got me pretty curious
let's mention map() then if you are present again, because without a interactive conversation it will take a very long time
!d map
map(function, iterable, *iterables)```
Return an iterator that applies *function* to every item of *iterable*, yielding the results. If additional *iterables* arguments are passed, *function* must take that many arguments and is applied to the items from all iterables in parallel. With multiple iterables, the iterator stops when the shortest iterable is exhausted. For cases where the function inputs are already arranged into argument tuples, see [`itertools.starmap()`](https://docs.python.org/3/library/itertools.html#itertools.starmap).
Im here!
that means that it will run a function for every item in an iterable
but when giving it the function it should run you only give it the name, without any parentheses
and the map() function doesn't return a list or tuple but a "map object" that is an iterable that works just like a "generator" that instead of returning all the data all at once instead yields one item at a time on demand, if you want it as a real list with all the data at once you need to enclose it in a list() as well (or do it as a separate operation afterwards)
lets pretend that timestamp is the name of the function parameter for a function in the below examples
earlier you asked about this, that isn't valid since split() returns a list and you can't apply int()on the whole list all at once like this
timestamp = "13:47"
time_split = timestamp.split(":")
time_int = int(time_split)
```that you already seen the error from earlier in this conversation, so i see no need to run the code again
instead, you need to apply the function to each item or element in the list, this a perfect job for `map()`
so for the `int()` function that you have been using we can specify it like this:
!e
timestamp = "13:47"
time_split = timestamp.split(":")
print(time_split)
time_int_generator = map(int, time_split)
print(time_int_generator)
time_int_list = list(time_int_generator)
print(time_int_list)
:white_check_mark: Your 3.13 eval job has completed with return code 0.
001 | ['13', '47']
002 | <map object at 0x7f7ed873be50>
003 | [13, 47]
as you can see from the first output line, after the split we have a list of strings
then we print the map object which isn't very helpful as you can see, you need to use it in an iterator context such as a for loop or similar to make it useful
and when we enclose it in list() we force it to give us all the values one after another until the generator is exhausted and have no more results to give us, and we get that as list that we finally print
!e
timestamp = "13:47"
time_int_list = list(map(int, timestamp.split(":")))
print(time_int_list)
:white_check_mark: Your 3.13 eval job has completed with return code 0.
[13, 47]
we can even combine them all in one line like the above code
you can see that the elements in the list aren't enclosed in any kind of quotes, which means they are proper numbers in both the last line of the last output as well as this output
a more natural fit for this would maybe be together with a for loop like the following
!e
timestamp = "13:47"
for number in map(int, timestamp.split(":")):
print(number)
:white_check_mark: Your 3.13 eval job has completed with return code 0.
001 | 13
002 | 47
there we never need to enclose it in a list() since a for loop can work directly with a iterable like a generator
you see how we specify the function without the parentheses, that gives us a reference (the address of) a callable (code, for example a function) that map() can then call with each item or element one at a time as the argument to that function
it works almost like this code:
!e
timestamp = "13:47"
for item in timestamp.split(":"):
print(int(item))
:white_check_mark: Your 3.13 eval job has completed with return code 0.
001 | 13
002 | 47
Ahh I kind of get it now yeah
but yield each result from the map() function one by one instead of printing them
Damn thats complicated
it can be a complex concept to wrap your head around in the beginning but very useful at times
Yeah it looks useful, is there an example that you can tell me that this can be used for instead of changing numbers into integers?
Mb for the response time im just rereading all this to get a good understanding of it
that's okay, it was kind of a wall of text there π
have you learned about "unpack"ing in python?
Uhh pretty sure I havenβt
have you learned dictionaries?
Yeah Iβve worked with them a couple of times already
it's one of the most common ways where you use unpacking naturally without even thinking much of it
dictionaries (sometimes called a "hash map" in general computer science) and are often used for lookup tables and is a very very useful data structure for solving a lot of different problems in programming
I remember using a dictionary when i had to calculate wheter a position on a chess board was white or black
That was pretty interesting
they have the key and value pairs, where the key must be of a hashable data type, which many immutable (those that can't be changed but instead needs to be replaced in their entirety) data types such as str (text strings), tuple and frozenset
the key can't be something that is internally mutable, as they can't be hashed to a stable value, for example list, dict or a set as all of them has content that can be changed or updated without replacing the whole object
but the value can almost be what ever you want
let's use the following dictionary where the name of each fruit is the key and the color is the value, both being strings, so each key maps to one value here
fruits = {
"banana": "yellow",
"apple": "green",
"cherry": "red",
}
```just for compactness in the following examples we can write them on one line even if it isn't as readable
```py
fruits = {"banana": "yellow", "apple": "green", "cherry": "red"}
```you can ask for a list of only all the keys or only all the values or all of the key value pares as a tuple for each item or pair
!e
fruits = {"banana": "yellow", "apple": "green", "cherry": "red"}
print(fruits.keys())
print(fruits.values())
print(fruits.items())
:white_check_mark: Your 3.13 eval job has completed with return code 0.
001 | dict_keys(['banana', 'apple', 'cherry'])
002 | dict_values(['yellow', 'green', 'red'])
003 | dict_items([('banana', 'yellow'), ('apple', 'green'), ('cherry', 'red')])
Ohh, never knew they consisted out of keys and values
You can also set a string as a key and a int as the value right
yes
and when you just use the dictionary by itself in a iterable context it's the same as doing .keys() on it, like this
!e
fruits = {"banana": "yellow", "apple": "green", "cherry": "red"}
for fruit in fruits:
print(fruit)
:white_check_mark: Your 3.13 eval job has completed with return code 0.
001 | banana
002 | apple
003 | cherry
sorry, print wasn't a good example in this context
you can also access the value for each iteration like this (a bit of a clubsy way, you'll see a better way soon where unpacking comes into play):
!e
fruits = {"banana": "yellow", "apple": "green", "cherry": "red"}
for fruit in fruits:
print(fruit, fruits[fruit])
:white_check_mark: Your 3.13 eval job has completed with return code 0.
001 | banana yellow
002 | apple green
003 | cherry red
This confuses me
as the variable fruit contains the first key "banana" during the first iteration of the loop you can access the value of that key with fruits["banana"] or in this case fruits[fruit]
what does it do exactly when you say fruits[fruit]
so first it's like doing fruits["banana"], the second iteration fruit contains "apple" as that is the second key in the dictionary and is then like doing fruits["apple"] and so on, thus we can access the value and print it as well
but as you can see this is a bit extra work and pretty verbose, so here we can instead use .items() on the dictionary
!e
fruits = {"banana": "yellow", "apple": "green", "cherry": "red"}
for item in fruits.items():
print(item)
:white_check_mark: Your 3.13 eval job has completed with return code 0.
001 | ('banana', 'yellow')
002 | ('apple', 'green')
003 | ('cherry', 'red')
now we get a tuple which is mostly like a list but it's internally immutable (so can't be change the content of the tuple but have to replace) for each item and get the key as the first element in the tuple and the value as the second element
this tuple can be unpacked and then the code looks like this instead
!e
fruits = {"banana": "yellow", "apple": "green", "cherry": "red"}
for key, value in fruits.items():
print(key, value)
:white_check_mark: Your 3.13 eval job has completed with return code 0.
001 | banana yellow
002 | apple green
003 | cherry red
now key contains the first element of the tuple that is returned for each iteration of .items() on the dictionary in the for loop and value contains the second element
now it's much easier to use the value and key together in the loop for different things
in the same way we can "unpack" return values such as tuples or lists that are returned by a function
this is something you already seen me use in the function i wrote to show you a shorter and more readable function for validation in the form of
def is_time_valid(timestamp: str) -> bool:
...
hours, minutes = timestamp.split(":", 1)
...
(unpack in codeblock makes it look like a keyword or function exists which does that)
(okay, noted, i wanted to highlight it as the name of a term or concept, but maybe that is beter then?)
(Yeah quotes are better, or maybe use markdown such as italics)
(Isn't it cool how parentheses make your messages invisible to everyone else?)
@hollow glacier the line with unpacking the list that .split() returns into two variables
hours, minutes = timestamp.split(":", 1)
```it now requires that we get exactly two elements back, not an empty list, or a list with a single element or two or more elements, it will raise an exception in such cases which we don't want
!d str.split
str.split(sep=None, maxsplit=-1)```
Return a list of the words in the string, using *sep* as the delimiter string. If *maxsplit* is given, at most *maxsplit* splits are done (thus, the list will have at most `maxsplit+1` elements). If *maxsplit* is not specified or `-1`, then there is no limit on the number of splits (all possible splits are made).
If *sep* is given, consecutive delimiters are not grouped together and are deemed to delimit empty strings (for example, `'1,,2'.split(',')` returns `['1', '', '2']`). The *sep* argument may consist of multiple characters as a single delimiter (to split with multiple delimiters, use [`re.split()`](https://docs.python.org/3/library/re.html#re.split)). Splitting an empty string with a specified separator returns `['']`.
For example:
to make sure that .split() never returns more then two elements i included a 1 as the second argument to .split() which then becomes the maxsplit parameter and makes it so that it will only split on the first separator (a colon in this cace) that it sees and then stop splitting after that, everything before the colon will end up as a string in the first element and everything after the first colon will end up in the second element which is also a string (which then can contain even colons in the string as .split() will not process them after it has hit the maxsplit limit)
so now that possible error is taken care of, now we need to make sure that we will be able to split it on colon, which we can only do if the string contains at least one colon
My bad im back, im having dinner rn
that is what we check before we try to split it with these two lines
if ":" not in timestamp:
return False
```as that make sure that the string has at least one colon, otherwise we do a "early return" out of the function
so with that check before the split as well as the maxsplit argument of 1 makes sure that the .split() will succeed and give us exactly two elements, which now ends up being unpacked into the variables hours and minutes respectively and will not raise any exceptions/errors as we have done a few things to make sure that will never happen when we get to that point in the code
I will need to reread this as soon as I am in a quieter spot im sorry. Cant really focus and dont want to lie and say that i understand it all
Will this auto close? If i dont respond within an hour
it's okay, just ask questions if have any
Cause i do not want to lose all that valuable info
Thanks again by the way, ill return to you asap
it will automatically be closed by the Python bot when an hour has elapsed after the last message was posted in the thread by anyone (edits or reactions doesn't count to reset the timer, only new when the last original message was posted by someone)
so if someone else writes it will be kept open for longer
Ohh okay
when a thread is closed in any way it is archived as read-only, so all information will remain for posterity on this server π
to find it you can either copy the link to the whole thread under the three dots at the top right of this thread or to a specific message on the three dots to the right of any message
that way you can save it in one way or another and come back to it at a later time, you just won't be able to write or change anything after and will need to open a new thread if you want to continue the conversation at a later time
(not in btw. I believe it's equivalent but it's the proper operator, and slightly less confusing on what the "not" applies to)
(your right, that is better, it was sloppy of my, it's something i had when i was doing two checks at the same time that both was being negated, let me fix that right away)
(yes, that is better, thank you)
(i original, before i posted the code, had the other if statement negated with if not (... and ...):as a guard for early return as well and the return True at the end of the function instead, but decided that i though this way was better or at least clearer in this particular instance)
@hollow glacier "guard clauses" also called "guard statements" or "early return" and sometimes also called "inversion" (but that shouldn't be confused with another common technique called "dependency inversion" which is used for something totally different and isn't of interest right now) is probably a concept you want to read up on, it removes indentation levels and to some extent can also prevent some code duplication
it's what i used in the function i wrote to remove indentation from the previous version of the code that had deep nested if's and quite a few else's (which i don't have a single one of in the new version of the function)
close to the end of this very long article is a short example of "early return" that i link directly to: https://realpython.com/python-control-flow/#hard-to-read-nested-constructs
bump, keeping this thread alive a little bit longer for OP
This help channel has been closed. Feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.