Truthy and Falsey

I was originally going to include this topic in the previous post about types and conversion, but I went on so long about that one that I thought this should be separate. This was also semi-related to something I believe I wrote about a few weeks ago. I've had abysmal luck with writing lately, so I'm not sure if it made it past the drafting stage. I typically prefer to write offline, then post the results. The last 3 or 4 times I've tried to do this, I've ended up losing the draft before saving it. A rational person might learn from this example, and perhaps save more often, but I seem immune to that type of rationality. I think it's because these posts are rarely given a lot of thought or planning ahead of time. Something strikes my fancy, then I brain-dump it all into a text editor and paste it here. It works (except, you know, when it doesn't) so why mess with a good thing?

The topic today is truthy and falsey values. Now this sounds like cutesy jargon, but I think it's just the easiest way to refer to these things. This is partly a segue topic to talk about a deeper understanding of programming I think I'm acquiring. Truthy and falsey refer to values that evaluate to true or false, but are not actually compared to anything. 1 == 2 is obviously false, but what if you just evaluate 1? It evaluates to true, which makes it truthy. In JavaScript (and this might hold true for PHP as well) almost everything is truthy. The only stuff that isn't truthy is 0, empty strings, undefined, null, and NaN. This stuff is good for quick tests to see if something you're expecting in the code is actually there. You can do an if test on that variable or object or whatever, and it evaluates to true then it's there and ready for use. If it evaluates to false, then something went wrong. That's a simple example, but it's stuff like this that lets you start to get more clever with your programming. If I'm writing something complex, and I keep in mind that the supporting code should give back a value if it succeeds or nothing if it fails I can easily test that later on. There are probably better examples, but a lot of this is still theoretical for me.

What this leads into is I had a realization that I was doing this already, but I didn't really understand it. I've been trying to think of a way to describe it, but the only thing I can come up with is the difference between using a key to open a lock, and understanding how the tumblers are cut and the lands and grooves on a key make them line up enough to turn the cylinder. I never really needed to know it. I knew it probably from looking at other code when trying to figure out a problem, and it made a certain intuitive sense. It's interesting when these connections happen. It really gives a deeper appreciation for what goes into writing this code. It's also a huge confidence builder when you're not guessing at what something will do. You know how the system works, and you know that if you're doing this thing, it will work like this. And if it doesn't work like that, you know where to look for an error. I've found this a lot when starting a new language, or learning some new technique. This happened with me when I first started adding SQL content to projects, where it took forever to get all the particulars ironed out. But the SECOND it works all that self doubt evaporates. All those pieces that were so confusing click into place and the next time you have to do it the whole process is so much easier.

Now I'm not saying I've had that "it all clicked into place" moment with JS. Far from it. But the truthy and falsey thing is an example of one of those times where a lot of stuff started making more sense. It's a good feeling, and I hope there's more of it coming.


JavaScript Types and Conversions

I figured, when I started on JavaScript, that there would be a point where the familiar turned into the unfamiliar, and I've definitely reached that point. About half of the book I've been using to learn JS has covered the familiar stuff. How to assign values to variables, how to make functions, loops, conditional checks, etc. While I hesitate to call it easy, it's the stuff that seems to be in common with all C-based languages. The syntax might be a little different, but the fundamental concepts are the same. But now I'm getting into new stuff, and I can't tell if this is just new ground for me in general, or if this stuff is unique to JS. I'm suspecting it's a little of both.

I recently finished a chapter that delved into JavaScript' approach to types. I had initially embraced JS partly because it's loosely typed. I can probably attribute that to starting with PHP. I found C# frustrating at times because there was no automatic type conversion, and I would frequently run into errors when trying to run code because I was trying to mix the wrong type. At the time I would admit that there are benefits to the C# approach, but secretly I was like "This is dumb, I miss PHP". Now that I've lifted up the rock, and seen all the creepy crawlies, I'm starting to think maybe a strongly typed system isn't so bad.

I had a thought when I was learning PHP. It was basically that it seemed like several people started working on different parts of the language, and sort of met up in the middle, but they didn't quite match up. So much of the language made good logical sense, except for a few odd patches. Naming is inconsistent, and sometimes built-in functions that seem very similar operate differently. JS seems more consistent, but there is one kind of rough patch, and that's all this types and conversion stuff.

The basic stuff isn't so bad, you just have to keep it in mind. Like with comparisons done using ==, JS will automatically try to convert strings into numbers to compare them. So "5" == 5 is true. The strict equality operator === has no time for such shenanigans. Numbers can only match numbers, strings can only match strings, etc. This is the same in PHP, so this stuff wasn't any big surprise. Booleans will convert to 1 for true, 0 for false, same deal. 1 == true may not look right, but it'll evaluate to true. The math operators are fun too. At least with comparisons you can always use === to suppress that fun conversion, but there's no way to make the math operators strict that I know of. So "8" - 7 will evaluate to 1. That's not so bad, except if you're trying to add. Then it flips and treats everything like a string. So "5" + 5 will evaluate to "55". It'll even work with empty strings. 5 + "" + 5 is 55.

Ok, that stuff is just fun messing around. Why I really wanted to write this was to talk about NaN. I don't think there's a NaN equivalent in PHP. NaN stands for Not a Number, and is used to represent numbers that are unrepresentable. This is all the stuff that would give you the error message on your calculator. 0/0, trying to find the square root of negative numbers, stuff like that (I totally knew that off the top of my head and didn't just peak at the book). The other thing that evaluates to NaN is trying to convert a string that isn't purely numbers into a number. See? Just trying to talk about this stuff is confusing. So "23" is a string because of the quotes, right? But it's all numbers, so that will convert if you try to subtract or multiply with it. Something like "monkey" though, will evaluate to NaN if you try to do math with it.

Now so far I'm with them. There are other ways to handle something like that, but this is the JS approach. That's fine. But then the rough patches start. For one, NaN isn't equal to anything, not even itself. So I wanted to try this for funsies, so I whipped up a quick page and script that would assign 0/0 to a variable, then compare the variable to itself, and spit out true or false. Sure enough, it's false. And that means that you can't even test for it how you normally would. If you need to check for null or undefined, you can just use the comparison operator. If you try that with NaN, you get false, because NaN isn't equal to anything. And the best part of all? If you use a function to test what type NaN is, it's a number. Yes, Not a Number is a number. This actually made me laugh when I read it. I have to admit, though, it does make sense, just not at first. NaN is supposed to numbers that can't be represented, so it makes sense it would be a number. It also makes sense that it can't equal itself because it can't be represented. It can't hold a value for 0/0 because we can't represent that value. And as soon as it does the comparison it's the new value, it doesn't retain the original formula used to derive it. So even if the formulas are identical it can't know that after the conversion. So even though it makes sense, it's counter intuitive enough to make it seem like 2 guys were working on different things, and realized they needed to stitch the whole thing together, and came up with NaN. I don't think that's the real story, but it reminded me of that thought I had about PHP.

Another example of that is null and undefined. Basically, both mean the same thing. "You made a thing, but haven't put anything in it yet". The rule of thumb is undefined is for empty variables, and null is for empty objects. But why have both? It feels like object guy and variable guy had a meeting when they were done and realized they used different words for the same thing. They will even evaluate to true if you compare them with the == operator. I feel like this isn't a huge deal once you're aware of it, but it is an extra pitfall in something that is, quite frankly, hard enough on its own. But then if this stuff easy then everyone would be doing it, right? Part of me writing this out is so I have to put it in my own words, which should hopefully help me remember it. I feel like my teen years of playing D&D and Magic the Gathering have primed me for remembering seemingly arbitrary and obscure rules, so I may even be ahead of the game on this one. But it never hurts to take extra measures, right? Right.


In the Hopper

I've been silent for a while now, so I thought I should post something here. The reason for my silence is I've been shoring up what is now a very obvious hole in my web programming knowledge. That would be JavaScript. I've been giving myself a crash course in JS using the very good Heads First book on the topic. For now I just want to put up a list of stuff I'll be writing about in the next few weeks. I'd like to put up more than just technical stuff, so I'll be adding some other stuff that has caught my attention lately. These are in no particular order.

1 - JavaScript JavaScript JavaScript

This probably goes without saying, but I'll say it anyway. JavaScript has changed a lot from when I first got interested in web coding. Granted, I never got too into it, and I was probably seeing poor examples of its use, but the impression stuck. I'm over my initial prejudice and actually pretty impressed.

2 - Learning

The Heads First approach to learning and how I learn things well are topics I've been thinking about a bit lately. I'd like to explore that in a little more detail

3 - The Thing

The 1982 version, thank you. To say I'm obsessed with this movie might be an understatement. I have it in just about every viable modern format, and went so far as to get the 1938 novella it was based on and the first movie adaptation of it in the 1950s. The pressure on this one has been building for a while.

4 - Conan the Cimmerian

I've been on an old writing kick lately, reading HP Lovecraft, Robert E Howard, re-reading Poe. That Thing novella. Robert E Howard's Conan stories, despite seeming on the surface like the pulpiest of pulp garbage are actually pretty incredible

5 - Robert E Howard in General

This guy was pretty fascinating. All of the Conan collections I've been reading have stuff about his personal life or career, or writing influences. I always roll my eyes when these things start, but I'm always super interested by the time they finish.

6 - General Updates

I have a few plates spinning, project wise. They've been a little wobbly lately, but I think I'm getting to a point where I can get back to work on them more regularly. That means finishing the ones in progress and refining the ones that are done.

7 - Booze

I basically started this thing with 3 goals in mind. One, to establish an online presence since I have so much trouble using social networks. I just can't get past my "who cares about this" reaction. Two, to write about what interests me, whether it's programming, horror movies, video games, whatever. Three, because I can never remember what booze I've tried. I figured I could hop on here and do a quick search if I'm in doubt. I think I'm doing alright on one and two, but I'm woefully behind on three.

8 - Anything Else That Comes To Mind

I'm a fickle creature, I can't be bound by lists. That being said, I will almost certainly stick to the list.


Call Center Recordings Script

One of the conditions of my transfer from medical records to IT all those years ago was that I would manage the phone system. The company I work for is in a weird place, size-wise, where it is typically too expensive to use hosted services, but also too expensive to have specialist employees who know a lot about a given subject and can run them in house. What ends up happening is we do whatever it is in house, and the duty to learn and maintain the thing falls to me or my boss. The particularly unsavory tasks (like managing the phone system) tend to fall to me.

Recently, I got a call from our call center manager asking if we could record all the customer calls for the call center, and hold them for 90 days. Usually we record all the calls for new call center people for a month to make sure they're doing an ok job. The phone server doesn't have the capacity to hold that much (roughly 6GB per month per user), so I started looking for alternatives.

We use Avaya IP Office and Voicemail Pro, and we kind of lucked out because VM Pro stores everything as Windows directories and WAV files. I did a little experimentation, and it didn't seem to harm anything if I manipulated those files through Windows instead of their interfaces, so I knew I could write something to extract the desired files and store them somewhere with enough room.

Here's my list of requirements for the script:

  • Has to differentiate by user
  • Has to store 90 days of recordings for each user

Nothing too difficult, but I wanted to deliver a little something more. So I quietly added, to myself:

  • Has to use familiar names for call center agents instead of the VM account names
  • Has to further differentiate by date of recording
  • Call center manager has to be able to update the Call Center user list
  • Logging

The first requirement is simple, provided the phone server is set up properly. It uses voice mailboxes to store recordings, so I needed unique locations to store each user's recordings. This may be an odd implementation, but I opted to make a hunt group with CCRec and the number of their desk in the call center for the name. This served 2 purposes. 1 - There are far fewer hunt groups than users, so there is little chance these entries in the system will be confused for actual users. Empty hunt groups with a naming convention like that should be pretty obvious to someone familiar with IP Office. 2 - Hunt group mailboxes can be added as additional mailboxes on IP phone units. User mailboxes are restricted to 1. So if the call center manager wanted to access a particular user's recordings as they are happening, they can be set up as alternate mailboxes on the phone.

I say "as they are happening" because the script will only run once a day, after hours. So there will never be access to the current day's recordings, unless they are associated with the phone. I don't think this is likely to happen, but it gives me options.

Once the hunt groups were set up, I got to work on the script. When writing this stuff, I tend to try to make it work first, then refine it later. So I just stuck all the user names in a big array, with a subarray for each user (that way I could keep the user name and the actual person's name together). The script would loop through the large array, extract the necessary user names, and move the files from the server to the computer, creating folders when necessary.

This is one of the things I enjoy about Powershell. I knew what I wanted to do, and more or less how to do it, but I wasn't sure of the specifics. Powershell gives you a lot of tools to extract properties of a file and do stuff with them. I knew I wanted to split the recordings by day, and have it work if a few days were missed for whatever reason, so I knew I wanted to create the day folders using the last write time for the file. Powershell makes it so easy to extract that, and then repurpose it. And since I was grabbing a datetime object, why not use the actual time part to name the file, that way they sort correctly automatically when viewed in the folder?

Computer sorting is fun. Using month names is out, since they don't fit alphabetic sorting conventions. month/day/year is pretty standard for us Americans, but it kind of falls apart if you need multiple years. All your months will sort together, then day and year. If you think you'll need to track years of data, you need to start with the year, then month and day. Since I was naming folders after the date, too, I couldn't use / as delimiter. That's a no-no for Windows file/folder names, so my dates ended up looking like this: 2014-05-16, which would be May 16th, 2014. Using the time for the recording name presented a similar challenge. I didn't realize it at first, but you run into the same problem as starting with month numbers if you start with the hour. Starting with the hour is fine if you're using a 24 hour format, but if you're using 12, then the sorting gets screwed up if you don't put the AM/PM first. Colons are also a no-no for filenames, so I had to resort to hyphens again. So the times look like this: AM-09-22-49 for a recording that happens at 9:22:49 AM. Using the seconds probably wasn't necessary, but I found it easier to understand the time that way. Here's that time without the seconds: AM-09-22. The AM makes it obvious that it's a time, but I think it would be easy to confuse a lot of these with dates.

I was happy with all that, so I moved on to the next thing.

Now I kind of ignored the 90 day limit when writing this script. My plan is to write a separate script that will check for items older than 90 days and delete them. I saw no reason to add that to this particular script. Plus I have 90 days until I REALLY need to worry about it, right? So as far as the call center manager was concerned, I could call it a day. I really wanted to make this thing shine, though, so I kept going.

I had already added the part about using actual names on the recordings copies. Basically it would use the name associated with the user account in the array to name a folder, then create the date folders inside that. So the only things left on my list were logging and giving the manager a way to edit the user list.

Logging was fairly simple. This is not a very critical app, so outputting a success or failure message to a text file was sufficient. I had a little realization while writing this part. This is going to sound ridiculous considering how much time I've spent in the past year or so teaching myself programming, but I don't think I really understood that you can store the boolean result of a function in a variable. I can't remember if this got changed later, but I know at one point I was performing the copy action and saving the result to a variable, and then testing the variable with an if statement to see if it evaluated to true or false. I feel like this is something that should be trivially obvious to anyone into this stuff, but it never quite connected like it did while writing this script. Once done I ran a few tests and was satisfied with the result. I couldn't figure out a way to make it fail. The script gets the names of the files to copy by pulling a list of files from the actual directory, so creating a mismatch between the actual file name and the expected file name is basically impossible. I'll probably mess around with it a bit more before I'm satisfied.

The trickiest part of the script ended up being the ability to let the manager change the names. I knew expecting the manager to open the script file and manually change the names was out of the question. So I switched the users array from being an array of arrays to being a simple text file that the script uses to populate the agents array. This would prevent the manager from screwing up my script (or at least lowered the potential). Even this seemed like a lot to ask for, since they would have to preserve the exact structure I'm using in the script. The next step?

I ended up writing a quick PHP page that would grab the file, extract its contents and stick it in a form, and let the manager change the names using that form. This had its own problems, but nothing worth going into here. I probably should have used C# for the forms page, but for something quick and dirty like this PHP just seems easier to me. I think it might be due to me learning and exclusively using PHP for a good chunk of time before getting into anything else.

After a good amount of testing, I'm happy with the whole thing. I just finished deploying it on Friday, and it is currently set up to only work with the newest agent still on probation. The manager likes to take his time replying to me, so I'm still waiting on the green light to start it for everyone. Probably good to start on a single person anyway, make sure everything is behaving.

If all goes according to plan, this thing could actually be useful to other people (imagine that!) with similar systems. I think the script is sufficiently modular that it would be easy to redeploy on someone else's system. The biggest hassle would probably be setting up the PHP page if the webserver wasn't already set up with it.

I want to write some documentation, and remove the work-specific paths and what not, then I'll probably add it to GitHUb. I have some other powershell scripts that might be useful, maybe I'll make a little powershell collection.


Minor Updates

I'm finally starting to get back into coding again. I don't know what happened, why I stopped for a month. There are excuses I can find, but why bother? I'm only hurting myself the more I procrastinate. Motivation's always been tough for me. But I'm not here to mope (I swear!).

I recently refactored the code a bit on the directory. C# has a very elegant way of dropping in and out of C# code on HTML pages. The rationale being you can write the HTML like you would if it were a plain Jane, static HTML page, and just drop in little bits of C# where necessary. The problem I was running into when making the directory was there were so many of those C# injection points that the whole thing became a big garbled mess. It worked, but I dreaded ever needing to change something.

The solution I came up with was to do all the data manipulation first, and save it all in variables, then insert those variables. So this chunk of code:

<p>Name:    @{result.first_name + " " + result.last_name}</p>

I can't remember if I actually needed the brackets of if it worked in the HTML because of the space. Anyway, I changed that into these two chunks of code:

displayName = result.first_name + " " + result.last_name;

That went up before any of the HTML. Then this became the HTML entry:

<p>Name:    @displayName</p>

Now, admittedly, the name example isn't the greatest as the original version is not terribly complex. They got much worse, but I didn't want to try to illustrate one of the more complex examples here. Suffice it to say that it cut out around 2/3rds of the code that was stuffed in the HTML section, and made all but 2 parts of the directory entry simple, single line HTML with a single C# variable inserted.

I'm still working a little bit on the placement of things, and making sure my changes work for different permutations of employees, names, job roles, etc. Next on the list is going to be a form for adding and modifying directory entries