So, I recently decided to add a timer command to my discord bot, which takes a specific time and counts down until then. I managed to work that in using something super janky and cobbled together.
This is my code currently:
async def timer(ctx, days, hours, minutes, seconds):
try:
hoursint = int(hours)
daysint = int(days)
minutesint = int(minutes)
secondint = int(seconds)
if daysint < 0:
await ctx.send("I dont think im allowed to do negatives")
raise BaseException
elif hoursint < 0:
await ctx.send("I dont think im allowed to do negatives")
raise BaseException
elif minutesint < 0:
await ctx.send("I dont think im allowed to do negatives")
raise BaseException
elif secondint < 0:
await ctx.send("I dont think im allowed to do negatives")
raise BaseException
elif secondint <= 0 and hoursint <= 0 and daysint <= 0 and minutesint <= 0:
await ctx.send("That's not a time dummy!")
raise BaseException
if secondint >= 60:
secondint = secondint - 60
minutesint += 1
if minutesint >= 60:
minutesint = minutesint - 60
hoursint +=1
if hoursint >= 24:
hoursint = hoursint - 24
daysint += 1
message = await ctx.send("Timer: {seconds}")
if daysint > 0 and hoursint == 0:
hoursint = 23
daysint -= 1
minutesint = 60
secondint = 60
if hoursint > 0 and minutesint == 0:
minutesint = 60
secondint = 60
hoursint -= 1
if secondint == 0 and minutesint > 0:
secondint = 60
minutesint -= 1
while True:
if secondint > 0:
secondint -= 1
if secondint <= 0 and minutesint > 0:
minutesint -=1
secondint = 60
if minutesint <= 0 and hoursint > 0:
hoursint -= 1
minutesint = 60
if hoursint <= 0 and daysint > 0:
daysint -= 1
hoursint = 24
if secondint == 0 and minutesint == 0 and hoursint == 0 and daysint == 0:
await message.edit(content="Ended!")
break
await message.edit(content=f"**Timer: {daysint}:{hoursint}:{minutesint}:{secondint}**")
await asyncio.sleep(1)
await ctx.send(f"{ctx.author.mention} Your countdown Has ended!")
except ValueError:
await ctx.send("Must be a number!")
However, I want to make this a little more intuitive/user friendly. At the moment, it takes inputs only in the "d h m s" format, but I would like it to take a user's date input, I.E "22-2-22, 11:30pm IST" or something similar and set a timer from the current time until that given time.
I haven't been able to figure this out myself and would appreciate any help!
You should use datetime.strptime to work with a datetime object, for which you will have to import from datetime import datetime.
To get all of the user input as string use * before the argument, so it will get the rest of the argument:
async def timer(ctx, *, time):
then you can use datetime.strptime with your format. You can find available "variables" here. In your example, to be able to input 22-02-22, 11:30PM the format would be "%y-%m-%d, %I:%M%p". You can also support multiple formats using try and except:
async def timer(ctx, *, time):
try:
datetime_object = datetime.strptime(time, "%y-%m-%d, %I:%M%p")
except ValueError:
try:
datetime_object = datetime.strptime(time, "second format")
except ValueError:
# And so on
Now you have the time at which the timer finishes, but as it looks like, you want to get how long it takes for it to finish, so you can just subtract the time it ends by the current time:
time_until_timer_end = datetime_object - datetime.now()
and then you can access the days or seconds(which you can then convert to hours) until the timer finishes:
seconds = time_until_timer_end.seconds
total_seconds = time_until_timer_end.total_seconds()
days = time_until_timer_end.days
Related
It seems like with one image - I can create 36 pictures, but for some reason, I cannot create 36 different images and display them on Canvas. Only one random image is shown in position 30, for the reason I do not quite get :)
There will be an image added. It seems like generating a random image in the for loop does not work. I have tried to move it around - does not help.
Here is what I get
from tkinter import *
import math
import random
time_to_remember = 60
suit = ["clubs","diamonds","spades","hearts"]
names_cards = ["6","7","8","9","10","jack","ace","king"]
def countdown(count):
count_min = math.floor(count / 60)
count_sec = math.floor(count % 60)
if count_sec < 10:
count_sec = f"0{math.floor(count % 60)}"
timer_text.config( text=f"{count_min}:{count_sec}")
if count < 10:
timer_text.config( fg ="red")
if count > 0:
global timer
timer = window.after(1000, countdown, count - 1)
print(count)
window = Tk()
window.minsize(1000, 800)
canvas = Canvas(height=1000, width = 1000)
canvas.grid(row = 1, rowspan=6, column=0,columnspan=10 )
b_img = PhotoImage(file= "/Users/oleksandrzozulia/PycharmProjects/memory_project/Images/Screenshot 2022-08-27 at 11.48.49.png",
height=130,
width=80)
y_cor = 20
x_cor = 90
leng = 10
count = 0
ii = []
for i in range(0,4):
if count == 3:
leng = 6
for i in range(0,leng):
i = canvas.create_image(x_cor,y_cor, image=b_img, anchor="ne")
x_cor += 100
count +=1
x_cor = 90
y_cor += 150
#Display Random cards==================================================================
y_n = 20
x_n = 90
leng_n = 10
count_n = 0
for i in range(0,3):
if count_n == 3:
leng_n = 6
for i in range(0,leng_n):
img_n = PhotoImage(
file = f"Images/PNG-cards-1.3/{random.choice(names_cards)}_of_{random.choice(suit)}.png",
height=130,
width = 80)
i = canvas.create_image(x_n,y_n, image=img_n, anchor="ne")
x_n += 100
count +=1
x_n = 90
y_n += 150
I wonder if there is a way to count the number of zero digit in an integer number by using only these operations: +, -, * and /
Others operations such as cast, div, mod, ... are not allowed.
Input: 16085021
Output: 2
It is a major restriction that numbers cannot be compared in a way to know that one is less than the other, and only equality checks can be done.
In my opinion that means there is nothing much else you can do than repeatedly add 1 to a variable until it hits a target (n) and derive from that what the least significant digit is of the original number n. This is of course terribly slow and not scalable, but it works in theory.
Here is a demo in Python using only ==, +, - and /:
n = 16085021
count = 0
while True:
# find out what least significant digit is
digit = 0
i = 0
while True:
if n == i:
break
digit = digit + 1
if digit == 10:
digit = 0
i = i + 1
# count any zero digit
if digit == 0:
count = count + 1
# shift that digit out of n
n = (n - digit) / 10
if n == 0:
break
print(count) # 2
Modulo can be implemented with subtractions: a % b = subtract b from a until you end up with something < b and that's the result. You say we can only use the == comparison operator, but we are only interested in modulo 10, so we can just check equality to 0, 1, ..., 9.
def modulo10WithSubtractions(a):
if a == 0 || a == 1 || ... || a == 9:
return a
while True:
a = a - b
if a == 0 || a == 1 || ... || a == 9:
return a
Integer division by 10 can be implemented in a similar fashion: a // 10 = add 10 to itself as many times as possible without exceeding a.
def div10WithAdditions(a):
if a == 0 || a == 1 || ... || a == 9:
return 0
k = 0
while True:
k += 1
if a - k*10 == 0 || a - k*10 == 1 || ... || a - k*10 == 9:
return k
Then we can basically do the classical algorithm:
count = 0
while True:
lastDigit = modulo10WithSubtractions(a)
if lastDigit == 0:
count += 1
a = div10WithAdditions(a)
if a == 0:
break
Asuuming / means integer division, then this snippet does the job.
int zeros = 0;
while(num > 0){
if(num / 10 == (num + 9) / 10){
zeros++;
}
num /= 10;
}
I'm trying to make a guessing game that allows three tries. So far, it works exactly as I want it to, but the user isn't allowed three tries. After the first, the program just ends and you have to restart it to continue playing. I don't want the program to end until three tries are finished.
How can I do this?
Current code:
from random import randint
guesses = 3
secret = randint(0, 999)
number = 1
PreGuess = input("Enter a number: ")
try:
guess = int(PreGuess)
except:
number = 0
if input:
if number == 1:
if 0 < guesses:
if 0 <= guess <= 999:
if guess < secret:
print("too low")
guesses -= 1
elif guess > secret:
print("too big")
guesses -= 1
elif guess == secret:
print("correct")
else:
print("Number is not in the playable range!")
else:
print("game over")
else:
print("Please enter a number.")
Notice that you only call input() once - at the beginning. You also do not have any loops that make the program jump back to the beginning to allow the player to make another guess.
What you should do is enclose the part that you want repeated in a while loop.
...
while guesses > 0:
PreGuess = input("Enter a number: ")
...
if input:
if number == 1:
if 0 <= guess <= 999:
if guess < secret:
print("too low")
guesses -= 1
elif guess > secret:
print("too big")
guesses -= 1
elif guess == secret:
print("correct")
break
else:
print("Number is not in the playable range!")
else:
print("Please enter a number.")
Then, after the while loop, you can check if the loop was terminated because the user won or if the user made 3 incorrect guesses. If the user made 3 incorrect guesses, guesses would equal 0, and if the user successfully guessed the number, guesses would be greater than 0.
if guesses == 0:
print("game over")
I have 3 variables (ADG,DR,TC) that I want to count for every single time 45 mins and 2.5 hrs pass, respectively for each 3 variable. I have this code to create a 24 hrs timer and I need to add these variables (and their counts) into while when_to_stop > 0: loop. Any recommendations? Thank you!
import time
while True:
uin = input(">>")
try:
when_to_stop = abs(int(uin))
except KeyboardInterrupt:
break
except:
print("Not a number!")
while when_to_stop > 0:
m, s = divmod(when_to_stop, 60)
h, m = divmod(m, 60)
time_left = str(h).zfill(2) + ":" + str(m).zfill(2) + ":" + str(s).zfill(2)
print(time_left + "\r", end="" )
time.sleep(0.001)
when_to_stop -= 1
# ADG - Auto Droplet Generator (45 mins)
# DR - Droplet Reader (time same as TC)
# TC - Ther mal cycler (2.5 hrs)
"""
Added an elapsed seconds counter.
When the amount of elapsed seconds is evenly divisible by (45 * 60 seconds), 45 minutes have passed, and the ADG variable is incremented by one each time this happens.
When the amount of elapsed seconds is evenly divisible by (150 * 60 seconds), 2.5 hours have passed, and the TC variable is incremented by one each time this happens. The DR variable acts the same way (time same as TC) so it has the same value as the TC variable.
import time
elapsed = 0
ADG = 0
DR = 0
TC = 0
while True:
uin = input(">>")
try:
when_to_stop = abs(int(uin))
except KeyboardInterrupt:
break
except:
print("Not a number!")
while when_to_stop > 0:
m, s = divmod(when_to_stop, 60)
h, m = divmod(m, 60)
time_left = str(h).zfill(2) + ":" + str(m).zfill(2) + ":" + str(s).zfill(2)
print(time_left + "\r", end="" )
time.sleep(0.001)
when_to_stop -= 1
elapsed += 1
#Auto Droplet Generator (45 mins)
if (elapsed % (45*60) == 0):
ADG += 1
# DR - Droplet Reader (time same as TC)
if (elapsed % (150*60) == 0):
DR += 1
# TC - Ther mal cycler (2.5 hrs)
if (elapsed % (150*60) == 0):
TC += 1
Hey I'm making this game and i need a 1 or more second delay?
Got any ideas?
heres where i need a delay in between tx3 = 1000 and cheesyx = 1000.
if x < 300 and y < 300 and not duringfight:
win.blit(cheesyt3, (tx3, ty3))
if x < 250 and y < 250 and not duringfight:
tx3 = 1000
cheesyx = 1000
if cheesyx == 1000:
deathx -= 5
if deathx == 600:
deathx += 5
deathmove = False
wmx = 1000
win.blit(deathtext, (dtext, 400))
if x > 400:
dtext = 1000
win.blit(deathhanpup, (deathx, deathy))
deathy = 1000
Since time.sleep doesnt work that well with pygame, you can use the time module to compare the current time with the last execution, and execute your code in a (event)loop only after more than a second has passed.
import time
last_execution = time.time()
if time.time() - last_execution > 1:
last_execution = time.time
execute_code_you_want()
Pygame time
In pygame, time.sleep(1) doesn't work well, so you could do pygame.time.delay(1), that works fine.
Link: https://www.pygame.org/docs/ref/time.html#pygame.time.delay.