3

I am having a problem with a script I am writing for my son. My intent is a simple reminder to him to remember his chores. I've just started doing PowerShell recently and I'm really enjoying it. I've bought a couple books and been through numerous other posts.

What I've got so far is below, seems if evaluations aren't working correctly with the -or (or maybe I goofed?)

    ## REMINDERS TO DO CHORES ##

$sun = "Sunday"
$mon = "Monday"
$tue = "Tuesday"
$wed = "Wednesday"
$thu = "Thursday"
$fri = "Friday"
$sat = "Saturday"

$today = (get-date).DayOfWeek

$choreVac = "Vacuum the rooms and stairs"
$choreBath = "Clean the Bathroom Including emptying the garbage"
$choreOther = "No Chores Today -- But keep dishes done up"


if($today -eq $mon -or $wed -or $fri) {
msg /time:2500 * "Today is a Chore Day:  your job is to $choreVac" 
}

elseif ($today -eq $tue -or $sat ) {
msg /time:2500 * "Today is a Chore Day: your job is to $choreBath and PLEASE do a good job"
}
else {
msg /time:2500 * $choreOther
}

The problem is I don't think it's being evaluated correctly on the day, so for today being Tuesday, the evaluated result is $mon -or $wed -or $fri

If I re-code this for each day as follows it works like expected. Why is it not working with the -or?

if($today -eq $tue) {
msg /time:2500 * $choreBath
}
Matt
  • 45,022
  • 8
  • 78
  • 119
PCPaul
  • 73
  • 8
  • Ahh I just figured it out. I have to fully qualify it if ($today -eq $mon -or $today -eq $wed -or $today -eq $fri) { it works – PCPaul Aug 19 '15 at 00:30
  • Feel free to post an answer to your question detailing the solution you found. – Guvante Aug 19 '15 at 00:33
  • You shouldn't provide the answer in the question above :) I have removed that part. – dan-gph Aug 19 '15 at 00:41
  • 1
    @dan-gph Thanks Dan, I don't see to have the ability to up vote your comments yet but no worries. I do appreciate it. – PCPaul Aug 19 '15 at 00:56

3 Answers3

4

Like you discovered yourself PowerShell was not evaluating your if statement how you intended it to be. Your expression could be understood better like this:

if(($today -eq $mon) -or ($wed) -or ($fri))

Just as in your comment the the code you wanted was

$today -eq $mon -or $today -eq $wed -or $today -eq $fri

or another way to look at it.

($today -eq $mon) -or ($today -eq $wed) -or ($today -eq $fri)

PowerShell does not need to brackets but it is good to use them if things are not going your way.

When Non null/zero length strings in PowerShell are true when cast as booleans. Focusing on the second clause it could be rewritten as

"Wednesday" -or "Friday"

Which is always true. That is why your if statement was firing when you didn't expect it to.

What you had coded made some logical sense but it was syntactically incorrect. Another approach I would like to introduce you to, if you are not already familiar with it, is switch. It would help reduce the clutter of all the if statements and would be especially useful if they became more complicated as the chores evolved over time.

$today = (get-date).DayOfWeek

$choreVac = "Vacuum The Apt"
$choreBath = "Clean the Bathroom Including empting the garbage"
$choreOther = "NO CHORES TODAY -- BUT YOU CAN Keep dishes done up, and Keep Garbage from Overflowing AND CLEAN YOUR ROOM and OR Do Laundry!!!. Especially your bedding"

Switch ($today){
    {$_ -in 1,3,5}{$message = "Today is a Chore Day:  Your job is to`r$choreVac"}
    {$_ -in 2,6}{$message = "Today is a Chore Day:  Your job is to`r$choreBath and PLEASE do a good job"}
    default{$message = $choreOther}
}

msg /time:2500 * $message

We removed all the calls to msg into one statement since only the $message changes. If a chore day is not covered with a clause in the switch then the default is simply $choreOther.

Also the days of the week can be represented as integers as well like you see above. This could arguably reduce the readability of the code but I think that is a stretch.

Matt
  • 45,022
  • 8
  • 78
  • 119
  • @Matt Thank you, switch is great. It looks more like a case statement like I've used in PL/SQL or that I've seen in other languages like C/C++ which was also fun. +1 – PCPaul Aug 19 '15 at 10:25
1

Here is the full code corrected and working as I wanted it to.

    ## REMINDERS TO DO CHORES ##

$sun = "Sunday"
$mon = "Monday"
$tue = "Tuesday"
$wed = "Wednesday"
$thu = "Thursday"
$fri = "Friday"
$sat = "Saturday"

$today = (get-date).DayOfWeek

$choreVac = "Vacuum The Apt"
$choreBath = "Clean the Bathroom Including empting the garbage"
$choreOther = "NO CHORES TODAY -- BUT YOU CAN Keep dishes done up, and Keep Garbage from Overflowing AND CLEAN YOUR ROOM and OR Do Laundry!!!. Especially your bedding"

if($today -in ($mon, $wed ,$fri) ) {
msg /time:2500 * "Today is a Chore Day:  your job is to $choreVac" 
}

elseif ($today -in ($tue,$sat)) {
msg /time:2500 * "Today is a Chore Day: your job is to $choreBath and PLEASE do a good job"
}
else {
msg /time:2500 * $choreOther
}
PCPaul
  • 73
  • 8
1

You can also use Hashtables to handle the lists of chores and the associated days. The following will allow you to easily add chores to any given day (or even put multiple chores on a single day)

$chores = @{Vac   = "Vacuum the Appt";
            Bath  = 'Clean the bathroom including emptying the garbage';
            Other = 'Nothing today -- But keep dishes done up'
           }

$day = @{Sunday    = $chores.Other;
         Monday    = $chores.Vac;
         Tuesday   = $chores.Bath;
         Wednesday = @($chores.Vac,$chores.Other);
         Thursday  = $chores.Other;
         Friday    = $chores.Vac;
         Saturday  = $chores.Bath;
        }

$base = "Chores for today: "
$today = (Get-Date).DayOfWeek
if ($day."$today".count -gt 1) {
    $first = "`n    " + $day."$today"[0]
    $rest = for ($i = 1; $i -lt $day."$today".count; $i++) {
        "`n    " + $day."$today"[$i]
    }

    $msg = $base + $first + $rest
} else {
    $msg = $base + "`n    " + $day."$today"
}

msg /time:2500 * $msg

If you don't want to support having multiple chores on a day (which in the above applies for Wednesday), just replace the entire If/Else block with the else clause and it will simply list the chores of the day.

Jonathan Leech-Pepin
  • 7,684
  • 2
  • 29
  • 45