I am currently working on a small Python clock. The clock doesn't have anything to do with real time, it was just for a fun side project. After every second, the clock is supposed to save the hour, minute, second, time of day, and other information. It saves the information, but when I restart the program, it doesn't reuse the information. Here is my code:
#Importations
import jsonpickle
import os
import sys
import time
#Setups
SAVEGAME_FILENAME = 'time.json'
game_state = dict()
#Class
class clocktime(object):
def __init__(self, hour, minute, second, timeday, day):
self.hour = hour
self.minute = minute
self.second = second
self.timeday = timeday
self.day = day
#Load Program Save
def load_game():
"""This runs if a .json file IS found"""
with open(SAVEGAME_FILENAME, 'r') as savegame:
state = jsonpickle.decode(savegame.read())
return state
#Save Program to JSON
def save_game():
"""This saves the program to a .json file."""
global game_state
with open(SAVEGAME_FILENAME, 'w') as savegame:
savegame.write(jsonpickle.encode(game_state))
#Initialize Program
def initialize_game():
"""Runs if no AISave is found"""
hour = 1
minute = 0
second = 0
timeday = 1
day = ('am')
the_time = clocktime(hour, minute, second, timeday, day)
state = dict()
state['the_time'] = [the_time]
return state
#Clear Screen
def cls():
os.system('cls')
#Clock Program
def clock():
hour = 1
minute = 0
second = 0
timeday = 1
day = ('am')
global game_state
while True:
print ("The time is: %s" % hour + ":%s" % minute + ":%s" % second + " %s" % day)
print (" H M S")
print ("H = Hour, M = Minute, S = Second")
time.sleep(0.5)
cls()
second += 1
save_game()
if second == 60:
minute += 1
second = 0
if minute == 60:
hour += 1
minute = 0
if hour == 13:
hour = 1
timeday += 1
if timeday == 1:
day = ('am')
if timeday == 2:
day = ('pm')
if timeday == 3:
day = 0
game_state['the_time'][0].hour = hour
game_state['the_time'][0].minute = minute
game_state['the_time'][0].second = second
game_state['the_time'][0].timeday = timeday
#Main Program
def main():
"""Main function. Check if a savegame exists, and if so, load it. Otherwise
initialize the game state with defaults. Finally, start the game."""
global game_state
if not os.path.isfile(SAVEGAME_FILENAME):
game_state = initialize_game()
else:
game_state = load_game()
clock()
#Launch Code
if __name__ == "__main__":
isSaveOn = False
main()
You're overwriting game_state with initial hour/minute/second/timeday values ) at the end of the loop when you save them, and they are always 1/0/0/1 regardless of the game_state. So basically you load game_state and then overwrite it with default values. Replace initializations in clock function to something like this:
# ...
def clock():
# Change to this:
hour = game_state['the_time'][0].hour
minute = game_state['the_time'][0].minute
second = game_state['the_time'][0].second
timeday = game_state['the_time'][0].timeday
while True:
# (displaying time and incrementing values)
game_state['the_time'][0].hour = hour
game_state['the_time'][0].minute = minute
game_state['the_time'][0].second = second
game_state['the_time'][0].timeday = timeday
# Move save_game here (to the end of loop):
save_game()
Related
I am trying to create a little game with python. I already set everything but I would like to set a time limit. I found something on the internet but it is not working with this project but it works with another project.
c.create_text(450, 20, text = 'Time', fill = 'red')
c.create_text(650, 20, text = 'Score', fill = 'red')
time_text = c.create_text(450, 20, text = 'Time', fill = 'red')
score_text = c.create_text(650, 20, text = 'Score', fill = 'red')
def print_score(score) :
c.itemconfig(score_text, text = str(score))
def print_time(time) :
c.itemconfig(time_text, text = str(time))
ENNEMY_CHANCE = 10
TIME_LIMIT = 30
SCORE_BONUS = 1000
score = 0
bonus = 0
end = time() + TIME_LIMIT
#Main
while True :
if randint(1, ENNEMY_CHANCE) == 1:
create_ennemy()
move_ennemies()
hide_ennemies()
score += ennemy_kill()
if(int(score/SCORE_BONUS)) > bonus:
bonus += 1
end += TIME_LIMIT
print_score(score)
print_time(int(end - time()))
window.update()
But I get this:
end = time() + TIME_LIMIT
TypeError: 'int' object is not callable
If you know an easier way to set a time limit that would be super.
Did you import time? I think you used the "time" name as an integer variable somewhere in your code and you have ambiguous code. Try this to get current time:
import time as time_module
now = time_module.time()
Try this
import time
start = time.time() #the variable that holds the starting time
elapsed = 0 #the variable that holds the number of seconds elapsed.
while elapsed < 30: #while less than 30 seconds have elapsed
elapsed = time.time() - start #update the time elapsed
I am trying to swap the outputted time back and forth between 24 and 12 hour formats. The time is ouputted on the gui as text. I have already created my interface, and the button but for some reason my function calls are not responding correctly.
This is my code so far:
import time
from tkinter import *
import os
class ConfigurationManagement():
def __init__(self):
self.__clockMode = 12
self.__clockColor = ''
self.__swapButtonTextColor = ''
self.__swapButtonColor = ''
def readClockSetting(self):
cwd = os.getcwd()
print(cwd)
filename = "clockSetting.txt"
setting = open(filename, 'r')
allSetting = setting.readlines()
setting.close()
return allSetting
def setClockMode(self, clockMode):
self.__clockMode = clockMode
def setClockColor(self, clockColor):
self.__clockColor = clockColor
def setSwapButtonTextColor(self, swapButtonTextColor):
self.__swapButtonTextColor = swapButtonTextColor
def setSwapButtonColor(self, swapButtonColor):
self.__swapButtonColor = swapButtonColor
def getClockMode(self):
return self.__clockMode
def settingUpClockSetting():
global clock
clock = ConfigurationManagement()
allSetting = clock.readClockSetting()
clock.setClockMode(allSetting[3])
clock.setClockColor(allSetting[6])
clock.setSwapButtonTextColor(allSetting[9])
def timeIn24(pastTime=''):
currentTime = time.strftime('%H: %M: %S')
if currentTime != pastTime:
digitalClock.config(text=currentTime)
digitalClock.after(200, timeIn24)
def timeIn12(pastTime=''):
currentTime = time.strftime('%I: %M: %S')
if currentTime != pastTime:
digitalClock.config(text=currentTime)
digitalClock.after(200, timeIn24)
def clockSwap():
print("Cat")
clockMode = clock.getClockMode()
if clockMode == 12:
clock.setClockMode(24)
timeIn24()
elif clockMode == 24:
clock.setClockMode(12)
timeIn12()
settingUpClockSetting()
root = Tk()
topFrame = Frame(root)
topFrame.pack()
bottomFrame = Frame(root).pack(side=BOTTOM)
digitalClock = Label(topFrame, font=('times', 100, 'bold'), bg='black', fg='green')
digitalClock.pack()
timeIn12()
root.geometry('700x500')
timeSwapButton = Button(bottomFrame, text="24/12 Modes", fg="red", bg="black", command=clockSwap).pack()
root.mainloop()
----------Digital Clock Configuration File----------
ClockType[12,24]:
12
ClockColor[The following colors can be handled: ]:
green
SwapButtonTextColor[The following colors can be handled ]:
red
SwapButtonColor[The following colors can be handled: ]:
black
I added the cat print to the clockswap function to make sure my button is actually working , and it for sure is.
It looks like you keep scheduling new clock updates without stopping the old clock updates. Also, timeIn12 uses timeIn24 in the call to after.
You don't need two functions to do the updating. Just have a single function do the updating, and all it needs to do is change the format. For example:
def updateTime(self):
if self.getClockMode() == 12:
currentTime = time.strftime('%I: %M: %S')
else
currentTime = time.strftime('%H: %M: %S')
...
I just got this fixed,
I added the following function:
def clockSwap():
global counter
if counter == 24:
counter = 12
elif counter == 12:
counter += 12
return counter
and added both clocks to the same counter:
def timeIn24Or12(pastTime=''):
if counter == 12:
currentTime = time.strftime('%H: %M: %S')
if currentTime != pastTime:
digitalClock.config(text=currentTime)
digitalClock.after(200, timeIn24Or12)
elif counter == 24:
currentTime = time.strftime('%I: %M: %S')
if currentTime != pastTime:
digitalClock.config(text=currentTime)
digitalClock.after(200, timeIn24Or12)
I have the following code which turns an outlet on/off every 3 seconds.
start_time = time.time()
counter = 0
agent = snmpy4.Agent("192.168.9.50")
while True:
if (counter % 2 == 0):
agent.set("1.3.6.1.4.1.13742.6.4.1.2.1.2.1.1",1)
else:
agent.set("1.3.6.1.4.1.13742.6.4.1.2.1.2.1.1", 0)
time.sleep(3- ((time.time()-start_time) % 3))
counter = counter + 1
Is there a way I can have the loop terminate at any given point if something is entered, (space) for example... while letting the code above run in the mean time
You can put the loop in a thread and use the main thread to wait on the keyboard. If its okay for "something to be entered" can be a line with line feed (e.g., type a command and enter), then this will do
import time
import threading
import sys
def agent_setter(event):
start_time = time.time()
counter = 0
#agent = snmpy4.Agent("192.168.9.50")
while True:
if (counter % 2 == 0):
print('agent.set("1.3.6.1.4.1.13742.6.4.1.2.1.2.1.1",1)')
else:
print('agent.set("1.3.6.1.4.1.13742.6.4.1.2.1.2.1.1", 0)')
if event.wait(3- ((time.time()-start_time) % 3)):
print('got keyboard')
event.clear()
counter = counter + 1
agent_event = threading.Event()
agent_thread = threading.Thread(target=agent_setter, args=(agent_event,))
agent_thread.start()
for line in sys.stdin:
agent_event.set()
So I have this here.
import sys
import os
import time
def clock():
Minutes = 0
Hours = 1
while True:
Minutes += 1
if Minutes == 60:
Minutes = 0
Hours = 2
if Hours == 12:
Hours = 1
Minutes = 0
break
ReadLine = ("\t{0:>2} : {1:>2}\r").format(Hours, Minutes)
sys.stdout.write(ReadLine)
sys.stdout.flush()
time.sleep(60)
clock()
Just for the record, I have made sure that the indentations are correct, they look a little screwy here. And I realize that I have nothing set for A.M./P.M. as of yet.. Any help is appreciated for this noob.
Thank you - Matt.
Edit:
>>> 2: 0 2: 0 2: 0
This is what is printing out now, the minutes have not updated. I'm obviously missing something. Once again thanks for any help, and I am sorry if this is a repeat, I have searched for an answer, but none was found. Thanks - Matt.
Edit #2- I figured it out. I used a bit of both of the answers, and whilst I accept the fact that it will be slow it does what I want it to do.
import sys
import os
import time
def clock():
Minutes = 0
Hours = 1
AM_PM = "AM" if Hours < 12 else "P.M"
while True:
Minutes += 1
if Minutes == 60:
Minutes = 0
Hours += 1
if Hours == 24:
Hours = 1
Minutes = 0
break
ReadLine = ("\t{:>2} : {:>2} {}\r").format(Hours, Minutes, AM_PM)
sys.stdout.write(ReadLine)
sys.stdout.flush()
time.sleep(60)
clock()
You know, it seems no matter how hard I try, I cannot get this darned indentation to look right. Oh well, I hope you can understand it's just tabbed a bit to the right.
your code print nothing because you put the code that print to stdout inside the if statements. so it would print only when Minutes == 60 and Hours == 12 (which will never happend because of you dont increament Hours as meantioned in the comments.
try this:
import sys
import os
import time
def clock():
Minutes = 0
Hours = 1
ampm = "AM"
while True:
Minutes += 1
if Minutes == 60:
Minutes = 0
Hours += 1
if Hours == 12:
Hours = 1
Minutes = 0
ampm = ("AM" if (ampm == "PM") else "PM")
ReadLine = ("\t{0:>2} : {1:>2} {2} \r").format(Hours, Minutes,ampm)
sys.stdout.write(ReadLine)
sys.stdout.flush()
time.sleep(60)
clock()
import datetime
then = now = datetime.datetime.now()
minutes = 0
hours = 0
while True:
now = datetime.datetime.now()
if (now-then).total_seconds() > 60:
then += datetime.timedelta(minutes=1)
minutes += 1
if minutes == 60:
minutes = 0
hours += 1
if hours == 24:
hours = 0
am_pm = "AM" if hours < 12 else "PM"
print("{:>2}:{:>02} {}".format((hours+11)%12+1, minutes, am_pm))
Note that I do away with time.sleep as it's not guaranteed to sleep for exactly the time requested (indeed you will always be running slightly slow by that clock) and instead compare a current time to the last time a minute passed and see if the total seconds are more than 60. If so, increment minutes, if minutes is 60, increment hours and check for rollover and am_pm switch. Afterwards, print the time.
If you're wanting to stretch your legs a little, try implementing it in a class! Ooh ooh, and threading too!
import datetime
import threading
import queue
class Clock(object):
def __init__(self, current_time=None):
if isinstance(current_time, datetime.datetime):
hours, minutes = current_time.hour, current_time.minute
else:
hours = minutes = 0
self.hours = hours
self.minutes = minutes
self.q = queue.Queue()
def checkTime(self):
try:
self.q.get_nowait() # time has updated, or exception thrown
self.updateTime()
self.q.task_done()
except queue.Empty:
pass # time hasn't updated
def updateTime(self, num_mins=1):
self.minutes += 1
if self.minutes == 60:
self.minutes = 0
self.hours += 1
if self.hours == 24:
self.hours = 0
print(self)
def minutePassed(self):
then = datetime.datetime.now()
while True:
now = datetime.datetime.now()
if (now-then).total_seconds() > 60:
then += datetime.timedelta(minutes=1)
self.q.put('_') # put something there, doesn't matter what
def __str__(self):
am_pm = "AM" if self.hours < 12 else "PM"
return "{:>2}:{:>02} {}".format((self.hours+11)%12+1,
self.minutes, am_pm)
def start(self):
t = threading.Thread(target=self.minutePassed)
t.daemon=True
t.start()
while True:
self.checkTime()
clock = Clock(datetime.datetime.now())
clock.start()
I'm trying to create a simple game where the point is to collect as many blocks as you can in a certain amount of time, say 10 seconds. How can I get a timer to begin ticking at the start of the program and when it reaches 10 seconds, do something (in this case, exit a loop)?
import time
now = time.time()
future = now + 10
while time.time() < future:
# do stuff
pass
Alternatively, if you've already got your loop:
while True:
if time.time() > future:
break
# do other stuff
This method works well with pygame, since it pretty much requires you to have a big main loop.
Using time.time()/datetime.datetime.now() will break if the system time is changed (the user changes the time, it is corrected by a timesyncing services such as NTP or switching from/to dayligt saving time!).
time.monotonic() or time.perf_counter() seems to be the correct way to go, however they are only available from python 3.3. Another possibility is using threading.Timer. Whether or not this is more reliable than time.time() and friends depends on the internal implementation. Also note that creating a new thread is not completely free in terms of system resources, so this might be a bad choice in cases where a lot of timers has to be run in parallel.
I use this function in my python programs. The input for the function is as example:
value = time.time()
def stopWatch(value):
'''From seconds to Days;Hours:Minutes;Seconds'''
valueD = (((value/365)/24)/60)
Days = int (valueD)
valueH = (valueD-Days)*365
Hours = int(valueH)
valueM = (valueH - Hours)*24
Minutes = int(valueM)
valueS = (valueM - Minutes)*60
Seconds = int(valueS)
print Days,";",Hours,":",Minutes,";",Seconds
start = time.time() # What in other posts is described is
***your code HERE***
end = time.time()
stopWatch(end-start) #Use then my code
The threading.Timer object (documentation) can count the ten seconds, then get it to set an Event flag indicating that the loop should exit.
The documentation indicates that the timing might not be exact - you'd have to test whether it's accurate enough for your game.
In this example the loop is run every second for ten seconds:
import datetime, time
then = datetime.datetime.now() + datetime.timedelta(seconds=10)
while then > datetime.datetime.now():
print 'sleeping'
time.sleep(1)
For a StopWatch helper class, here is my solution which gives you precision on output and also access to the raw start time:
class StopWatch:
def __init__(self):
self.start()
def start(self):
self._startTime = time.time()
def getStartTime(self):
return self._startTime
def elapsed(self, prec=3):
prec = 3 if prec is None or not isinstance(prec, (int, long)) else prec
diff= time.time() - self._startTime
return round(diff, prec)
def round(n, p=0):
m = 10 ** p
return math.floor(n * m + 0.5) / m
Asks you when to stop [seconds]
Adds '0' at starting [1-9]
import time
import sys
stop = int(input('> '))
second = 0
print('> Stopwatch Started.')
while stop > second:
if second < 9:
second = second + 1
time.sleep(1)
sys.stdout.write('\r> ' + '0' + str(second))
else:
second += 1
time.sleep(1)
sys.stdout.write('\r' + '> ' + str(second))
print('\n> Stopwatch Stopped.')
As a learning exercise for myself, I created a class to be able to create several stopwatch timer instances that you might find useful (I'm sure there are better/simpler versions around in the time modules or similar)
import time as tm
class Watch:
count = 0
description = "Stopwatch class object (default description)"
author = "Author not yet set"
name = "not defined"
instances = []
def __init__(self,name="not defined"):
self.name = name
self.elapsed = 0.
self.mode = 'init'
self.starttime = 0.
self.created = tm.strftime("%Y-%m-%d %H:%M:%S", tm.gmtime())
Watch.count += 1
def __call__(self):
if self.mode == 'running':
return tm.time() - self.starttime
elif self.mode == 'stopped':
return self.elapsed
else:
return 0.
def display(self):
if self.mode == 'running':
self.elapsed = tm.time() - self.starttime
elif self.mode == 'init':
self.elapsed = 0.
elif self.mode == 'stopped':
pass
else:
pass
print "Name: ", self.name
print "Address: ", self
print "Created: ", self.created
print "Start-time: ", self.starttime
print "Mode: ", self.mode
print "Elapsed: ", self.elapsed
print "Description:", self.description
print "Author: ", self.author
def start(self):
if self.mode == 'running':
self.starttime = tm.time()
self.elapsed = tm.time() - self.starttime
elif self.mode == 'init':
self.starttime = tm.time()
self.mode = 'running'
self.elapsed = 0.
elif self.mode == 'stopped':
self.mode = 'running'
#self.elapsed = self.elapsed + tm.time() - self.starttime
self.starttime = tm.time() - self.elapsed
else:
pass
return
def stop(self):
if self.mode == 'running':
self.mode = 'stopped'
self.elapsed = tm.time() - self.starttime
elif self.mode == 'init':
self.mode = 'stopped'
self.elapsed = 0.
elif self.mode == 'stopped':
pass
else:
pass
return self.elapsed
def lap(self):
if self.mode == 'running':
self.elapsed = tm.time() - self.starttime
elif self.mode == 'init':
self.elapsed = 0.
elif self.mode == 'stopped':
pass
else:
pass
return self.elapsed
def reset(self):
self.starttime=0.
self.elapsed=0.
self.mode='init'
return self.elapsed
def WatchList():
return [i for i,j in zip(globals().keys(),globals().values()) if '__main__.Watch instance' in str(j)]
This is the Shortest Way I know of doing it:
def stopWatch():
import time
a = 0
hours = 0
while a < 1:
for minutes in range(0, 60):
for seconds in range(0, 60):
time.sleep(1)
print(hours,":", minutes,":", seconds)
hours = hours + 1
New to the python world!
I need a System Time independent Stopwatch so I did translate my old C++ class into Python:
from ctypes.wintypes import DWORD
import win32api
import datetime
class Stopwatch:
def __init__(self):
self.Restart()
def Restart(self):
self.__ulStartTicks = DWORD(win32api.GetTickCount()).value
def ElapsedMilliSecs(self):
return DWORD(DWORD(win32api.GetTickCount()).value-DWORD(self.__ulStartTicks).value).value
def ElapsedTime(self):
return datetime.timedelta(milliseconds=self.ElapsedMilliSecs())
This has no 49 days run over issue due to DWORD math but NOTICE that GetTickCount has about 15 milliseconds granularity so do not use this class if your need 1-100 milliseconds elapsed time ranges.
Any improvement or feedback is welcome!