2

I'm having the problem that when running this program, no matter what, everything you input are counted as seconds rather than wahtever unit you actually chose.

        __author__ = 'Exanimem'
# Homework Notifier Version 0.1.5 It works a bit better. Kind of.

import time
import threading
import webbrowser
import winsound
import ctypes
import sys
import math
import pyglet

# TO-DO
# NOTE: NOT LISTED IN ORDER OF PRIORITY
# Add months, years, decades, and centuries including system to detect what month, year, decade, and centry it is
# Add ability to remind at a specific time in a unit, like "4:50 in 1 day"
# Detect spelt out numbers as numbers
# Have that you press enter then answer
# Have message box be brought to front of the screen
# Have notifications still come when application closed
# Combine unit and digit function
# User Friendly UI?
# Allow users to input time like "4:30 PM EST"
# Autodetect timezone
# Recorded log to look back on past notifications?
# Configurable beep (with music)
# Restart function (Instead of stopping program at whatever point, have option to create new notification)
# Multiple notifications
# Test stop function further and improve
# Save notification's from last time opened

# KNOWN BUGS
# Everything counted as seconds
# Occasionally message box will not appear

HW = input("What homework should I remind you to do?")
# Enter your homework
remind = input("When would you like me to remind you of this?")
# Enter desired time

remind = float(remind)

unit = input("Will your unit be in seconds, minutes, hours, days, or weeks?")
# Enter correct unit

if unit == "seconds":
    remind*1

    if unit == "minutes":
        remind * 60

    if unit == "hours":
        remind * 3600

    if unit == "days":
        remind * 86400

    if unit == "weeks":
        remind * 604800

continuous = input("Would you like to have the notification be continuous?")

print(
    "You may now leave the application in the background. Closing the application and shutting down your computer will deactivate the notification you have planned.")

while continuous == "yes":

    time.sleep(remind)

    Freq = 2500  # Set Frequency To 2500 Hertz
    Dur = 1000  # Set Duration To 1000 ms == 1 second
    winsound.Beep(Freq, Dur)

    print("The message box has opened, but as another reminder your homework is")

    print(HW)

    ctypes.windll.user32.MessageBoxW(0, HW, "Homework!!!", 1)

    if input("To stop the loop and close the program, please type in 'stop'") == "stop":
        break

if continuous == "no":
    time.sleep(remind)

    Freq = 2500  # Set Frequency To 2500 Hertz
    Dur = 1000  # Set Duration To 1000 ms == 1 second
    winsound.Beep(Freq, Dur)

    print("The message box has opened, but as another reminder your homework is")

    print(HW)

    ctypes.windll.user32.MessageBoxW(0, HW, "Homework!!!", 1)

I first thought the problem was the indentation on the first if, but if it is intended at all, the program ceases to work. I've tried figuring this out for awhile but I can't for the life of me. Help?

2 Answers2

1

You should use what you calculate

Even though you are doing the correct calculation(s), you never update the value of remind — which means that you are effectively calculating something that you then toss away.

Example

remind *  3600 # will simply calculate and discard the value
remind *= 3600 # remind = remind * 3600

The code is confusing—indentation matter!

The indentation level of the ifs after if unit == "seconds" looks like they will only be evaluated if unit is equal to "seconds". This might not be an issue if the whitespace in your code is actually written so that the interpret doesn't read your code that way, but it looks weird and is very error-prone.

Example

if unit == "seconds":
    remind*1

    if unit == "minutes": # this will only execute if "unit == "seconds"
        remind * 60
if unit == "seconds":
  remind *= 1

if unit == "minutes":
  remind *= 60

How to fix the problems

At every point where you are currently doing the "calculate and discard"-dance, update the code so that you actually store the calculated value—making it available for future use.

Also fix the indentation level so that it no longer looks like you are using nested if-conditionals.

if unit == "seconds":
  remind *= 1 # useless

if unit == "minutes":
  remind *= 60

if unit == "hours":
  remind *= 3600

if unit == "days":
  remind *= 86400

if unit == "weeks":
  remind *= 604800

Note: Another point worth raising is that unit could never match more than one of those if-statements, you are better of using if-elif-statements. More information about if-statements can be found here

Filip Roséen - refp
  • 62,493
  • 20
  • 150
  • 196
  • Didn't realize you were still adding it. Lemme check if it works. –  Oct 05 '15 at 21:15
  • So far it works. Just to make sure i'm gonna test it a bit more but thank you! –  Oct 05 '15 at 21:18
  • I was just testing everything again to make sure it works. Thank you so much for all the information your provided about how it works! –  Oct 05 '15 at 21:29
0

As already pointed out, you are not actually updating remind and your if's should not be indented inside the first but a simpler approach to your overall logic would be to use a dict mapping seconds, hours etc.. to the appropriate values:

mapping = {"seconds":60,"hours":3600,"days":86400,"weeks":604800}
unit = input("Will your unit be in seconds, minutes, hours, days, or weeks?")

# do lookup on mapping and increment remind
remind *= mapping.get(unit,1)

All the logic of your if statements are combined in remind *= mapping.get(unit,1), it will pull the appropriate value from the dict or return 1 if the user enters something invalid leaving remind as is.

You may want to actually use a while loop and validate that the user enters some valid input, something like.

mapping = {"seconds":60,"hours":3600,"days":86400,"weeks":604800}
while True:
    unit = input("Will your unit be in seconds, minutes, hours, days, or weeks?")
    if unit in mapping:     
       remind *= mapping[unit]
       break
    print("Invalid option")

If you were using the if logic then use if/elif, a unit cannot be five different things at once, if's are always evaluated but elif's are only evaluated if the previous if or elif evaluated to False:

if unit == "seconds":
  remind *= 1 # useless

elif unit == "minutes":
  remind *= 60

elif unit == "hours":
  remind *= 3600

elif unit == "days":
  remind *= 86400

elif unit == "weeks":
  remind *= 604800

But again that logic does not handle when a user enters no valid input.

Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • Would it also work if I were to put an else statement at the end of the if/elif code for if there's invalid input? –  Oct 05 '15 at 21:36
  • @Zombiex100, indeed it would but without a loop to loop back to the start you would have no way of returning the code back to asking for input again, you could put the if's in a while as the example in my answer, increment and break if input is valid or else print a message and ask again – Padraic Cunningham Oct 05 '15 at 21:38
  • The dict mapping will give you the exact same logic as using a bunch of if/elifs, just a more concise approach. – Padraic Cunningham Oct 05 '15 at 21:45
  • I have `while True: if unit == "seconds": remind *= 1 break elif unit == "minutes": remind *= 60 break elif unit == "hours": remind *= 3600 break elif unit == "days": remind *= 86400 break elif unit == "weeks": remind *= 604800 break else: print("Invalid unit")` But it just repeats "Invalid unit" rather than the code itself –  Oct 05 '15 at 21:55
  • You need to take the input in the loop the same as in my example using the mapping dict! If you don't take the input there you cannot ask the user again – Padraic Cunningham Oct 05 '15 at 21:57
  • No prob, rookie mistake ;) – Padraic Cunningham Oct 05 '15 at 22:00
  • I have one (or two) more questions. Would I be able to put a similar loop where when you have to input a number, that if you don't input a number it would say the same thing (Invalid Answer/whatever)? –  Oct 05 '15 at 22:01
  • Sure but you would need a try/except http://stackoverflow.com/a/29591850/2141635, if you did not your code would error – Padraic Cunningham Oct 05 '15 at 22:06
  • 1
    Looks like that's it. Thank you! –  Oct 05 '15 at 22:42