Friday, December 23, 2011

Happy Holidays!

Hey there!  Just wanted to wish all of you a fantastic happy holiday season; it couldn’t be more festive.  For me, Christmas came a little early, though, because of the release of the Unity 3.5 Developer Preview, which is a Beta version of the soon-to-be-released Unity 3.5.  The talk of the town in this grand new release?  The new Flash export feature.
You see, Unity Technologies, the makers of Unity 3D, has added a capability to allow developers to export their games as Flash applications so they can be run without a Unity Web Player plugin or JavaScript activity the browser.  Not only that, web games will run without a plugin in Google Chrome, thanks to Google’s Native Client API.
To quote Unity’s website:
Unity 3.5 is one of our biggest releases to-date. It’s packed full of new features and improvements that we think you are going to love. We can't wait to see what you will create with it, so we've decided to open our 3.5 beta program to the public. Starting today, you can download a time-limited beta version of Unity 3.5.
This release also provides a hands-on preview of Unity's upcoming Flash deployment add-on. Experience first-hand how Flash deployment in Unity opens up new publishing options, by enabling you to push your interactive 3D content to the web through Adobe Flash Player.
Some of those features happen to include a new Particle System (with Legacy particle support included, of course) and a built-in path finding system for Pro license holders (path can be run but not created under Unity Basic).  They’ve re-written the occlusion culling system to allow for doors that open and close, dynamically changing the viewable areas, and has built in LOD support.
They’ve also added multithreaded rendering, which will give a performance boost on multi-core systems.  To see all the new features, check here:  link.  Those of you who want to try the Flash should do it now, because once Unity 3.5 officially ships, you will be forced to upgrade and Flash support will require an additional license like the iOS and Android exports do.
Well, I’ll be playing on 3.5 Beta.  See you soon.
SevenBits

Monday, December 5, 2011

Little Java Neaties–Swing

Today I’m going to show you all the neat little things you can do with Java.  Java is a very versatile programming language, and tonight I’m focusing on Swing.  Included in the package javax.swing and included on all versions of Java, it can be used to create interesting GUI applications.  For those of you who think they know what Java is but are a little sketchy, here’s a small sample to entertain ye:
 
   1:  import java.io.*;
   2:  import java.net.*;
   3:   
   4:  public class RemoteFileCopier {
   5:      public RemoteFileCopier(File name, Socket connection) throws java.io.IOException {
   6:          OutputStream out = connection.getOutputStream();
   7:          InputStream in = new FileInputStream(name);
   8:          
   9:          int ch;
  10:          
  11:          while ((ch = in.read()) != -1)
  12:          out.write(ch);
  13:          
  14:          in.close(); out.close();
  15:      }
  16:  }

Being as it is, I’m not going to explain how to compile or run this code.  If you don’t know how, find yourself a good Java book.  I like Head First Java by Oreilly Publishing, as it includes interesting examples to help you learn Java, including a rudimentary drum beat player.

Anyhow, there are a lot of things Swing can do, namely that it is much simpler than the native Win32 API – heck, I suppose there are WYSIWYG Java GUI builders out there, but Swing (and the AWT) provide an easy way to build complex GUIs in code.  Check this little snippet out, taken from this website.

   1:  // file: EmptyFrame.java
   2:  // Adapted from Core Java, vol.1, by Horstmann & Cornell
   3:      
   4:  import javax.swing.*;
   5:      
   6:  class MyFrame extends JFrame {
   7:    public MyFrame() {
   8:     setTitle("My Empty Frame");
   9:     setSize(300,200); // default size is 0,0
  10:     setLocation(10,200); // default is 0,0 (top left corner)
  11:    }
  12:      
  13:  public static void main(String[] args) {
  14:      JFrame f = new MyFrame();
  15:      f.show();
  16:    }
  17:  }

This class extends the JFrame class, so it doesn’t have to create an instance of it and can call its public methods directly.
Deprecation Warning: If your Java compiler complains about line 15 being “deprecated”, and you want to shut it up, change it to   f.setVisible(true);
Now that code snippet created a window with a size of 300 pixels by 200 pixels.  However, it’s rather empty.  Let’s add a small push button.

   1:  // file: EmptyFrame.java
   2:  // Adapted from Core Java, vol.1, by Horstmann & Cornell
   3:      
   4:  import javax.swing.*;
   5:   
   6:  class MyFrame extends JFrame {
   7:    public MyFrame() {
   8:      setTitle("My Empty Frame");
   9:      setSize(300,200); // default size is 0,0
  10:      setLocation(10,200); // default is 0,0 (top left corner)
  11:      Container pane = getContentPane();
  12:      JButton button = new JButton("CHANGE THIS TEXT");
  13:      pane.add(button);
  14:    }
  15:      
  16:    public static void main(String[] args) {
  17:      JFrame f = new MyFrame();
  18:      f.show();
  19:    }
  20:  }

Now the entire window will be filled with a button.  I hope now you see what Swing is capable of – in fact, you can obviously use Swing to create a GUI for a previously command line run application.  And because it’s Java, it’ll work in every operating system that has a JVM, though the controls will look a bit different depending on your OS.

To demonstrate this point, here’s a simple terminal application using two text fields.  It’s actually a small part of a large module I’m writing for yet another project called Tracker.

   1:  import javax.swing.*;
   2:  import java.awt.event.*;
   3:  import java.awt.*;
   4:  import java.util.StringTokenizer;
   5:   
   6:  public class CommandWindowDialog extends JDialog implements ActionListener {
   7:   
   8:      private JTextArea log = new JTextArea(5, 40);
   9:      private JTextField prompt = new JTextField();
  10:      
  11:      private static final String COMMANDS = "help (h) - shows this window.\n" +
  12:          "quit (exit) <exit code> - exit the program with error code.  if error not specified, command ignored.\n" +
  13:          "clear (cls) - clears the screen.\n" +
  14:          "what - displays information.\n" +
  15:          "echo <message> - echos the message.\n" +
  16:          "exec <program name> - executes the specified program.\n";
  17:      
  18:      public CommandWindowDialog(Tracker parent) {
  19:          super(parent, "Command Window", false);
  20:          setSize(500, 250);
  21:          
  22:          log.setText("Type <help> for a list of commands.\n\n");
  23:          log.setEditable(false);
  24:          
  25:          addComponents();
  26:          
  27:          setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
  28:          setVisible(true);
  29:      }
  30:      
  31:      private void addComponents() {
  32:          Container c = getContentPane();
  33:          c.add("Center", new JScrollPane(log));
  34:          c.add("South", prompt);
  35:          
  36:          prompt.addActionListener(this);
  37:      }
  38:      
  39:      public void actionPerformed(ActionEvent e) {
  40:          try {
  41:              CommandWindowDialog.processCommand(prompt.getText(), log);
  42:              prompt.setText("");
  43:          }
  44:          catch (java.io.IOException exec) { JOptionPane.showMessageDialog(this, exec.getMessage()); }
  45:      }
  46:      
  47:      public static void processCommand(String command, JTextArea log) throws java.io.IOException {
  48:          StringTokenizer parser = new StringTokenizer(command);
  49:          
  50:          String head = parser.nextToken();
  51:          
  52:          if (head.equals("quit") || head.equals("exit")) {
  53:              if ((JOptionPane.showConfirmDialog(null, "This will immediatly kill your current connection.  Okay?") == JOptionPane.YES_OPTION)) {
  54:                      System.exit(Integer.parseInt(parser.nextToken()));
  55:              }
  56:          }
  57:          
  58:          if (head.equals("cls") || head.equals("clear")) {
  59:              log.setText("");
  60:          }
  61:          
  62:          if (head.equals("help") || head.equals("h")) {
  63:              log.setText(log.getText() + "Understood Commands:\n" + COMMANDS + "\n");
  64:          }
  65:          
  66:          if (head.equals("what")) {
  67:              log.setText(log.getText() + "This is the Tracker command window.  Here you can see various processes and enter commands.\n");
  68:          }
  69:          
  70:          if (head.equals("echo")) {
  71:              log.setText(log.getText() + command.substring(5) + "\n");
  72:          }
  73:          
  74:          if (head.equals("exec")) {
  75:              Process p = new ProcessBuilder(command.substring(5), null).start();
  76:              p = null; //Prevent memory leaks.
  77:          }
  78:      }
  79:  }

If you strip out the vast majority of the input-processing code, what you’re left with is actually the GUI-building code:

   1:  import javax.swing.*;
   2:  import java.awt.event.*;
   3:  import java.awt.*;
   4:  import java.util.StringTokenizer;
   5:   
   6:  public class CommandWindowDialog extends JDialog implements ActionListener {
   7:   
   8:      private JTextArea log = new JTextArea(5, 40);
   9:      private JTextField prompt = new JTextField();
  10:      
  11:      ...
  12:      
  13:      public CommandWindowDialog(Tracker parent) {
  14:          super(parent, "Command Window", false);
  15:          setSize(500, 250);
  16:          
  17:          log.setText("Type <help> for a list of commands.\n\n");
  18:          log.setEditable(false);
  19:          
  20:          addComponents();
  21:          
  22:          setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
  23:          setVisible(true);
  24:      }
  25:      
  26:      private void addComponents() {
  27:          Container c = getContentPane();
  28:          c.add("Center", new JScrollPane(log));
  29:          c.add("South", prompt);
  30:          
  31:          prompt.addActionListener(this);
  32:      }
  33:      
  34:      ...
  35:   
  36:  }

Although some of you may find this cumbersome, it is certainly much simpler when compared to the native Win32 API, whose code looks like this (when coded in C):

   1:  ...
   2:   
   3:  LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
   4:  {
   5:      switch(Message)
   6:      {
   7:          case WM_CREATE:
   8:          {
   9:              HMENU hMenu, hSubMenu;
  10:              HICON hIcon, hIconSm;
  11:   
  12:              hMenu = CreateMenu();
  13:   
  14:              hSubMenu = CreatePopupMenu();
  15:              AppendMenu(hSubMenu, MF_STRING, ID_FILE_ADD, "&Add File");
  16:              //hSubMenu = CreatePopupMenu();
  17:              //AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
  18:              AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");
  19:   
  20:              hSubMenu = CreatePopupMenu();
  21:              AppendMenu(hSubMenu, MF_STRING, ID_STUFF_GO, "&Go");
  22:              AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Control");
  23:   
  24:              SetMenu(hwnd, hMenu);
  25:   
  26:              hIcon = (HICON)LoadImage(NULL, "menu_two.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
  27:              if(hIcon)
  28:              {
  29:                  SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
  30:              }
  31:              else
  32:              {
  33:                  MessageBox(hwnd, "Failed to load large file icon.  It should be in same directory as program.", "Error", MB_OK | MB_ICONERROR);
  34:              }
  35:   
  36:              hIconSm = (HICON)LoadImage(NULL, "menu_two.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
  37:              if(hIconSm)
  38:              {
  39:                  SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
  40:              }
  41:              else
  42:              {
  43:                  MessageBox(hwnd, "Failed to load small file icon.  It should be in same directory as program.", "Error", MB_OK | MB_ICONERROR);
  44:              }
  45:          }
  46:          break;
  47:          case WM_COMMAND:
  48:              switch(LOWORD(wParam))
  49:              {
  50:                  case ID_FILE_EXIT:
  51:                      PostMessage(hwnd, WM_CLOSE, 0, 0);
  52:                  break;
  53:                  case ID_STUFF_GO:
  54:                      if (strcmp (szFileName,"") != 0) {
  55:                          IncinerateFiles(hwnd); }
  56:                      else {
  57:                          MessageBox(hwnd, "No file selected. Select a file using File > Add File.", "Error", MB_OK | MB_ICONERROR); }
  58:                  break;
  59:                  case ID_FILE_ADD:
  60:                      GetNameOfTarget(hwnd);
  61:                  break;
  62:                  case ID_STUFF_ABOUT:
  63:                      MessageBox(hwnd, "(c) 2011 Subversion Systems.  All rights reserved.\n\nNot responsible for any potential illegal use of program.", "About", MB_OK);
  64:                  break;
  65:              }
  66:          break;
  67:          case WM_CLOSE:
  68:              DestroyWindow(hwnd);
  69:          break;
  70:          case WM_DESTROY:
  71:              PostQuitMessage(0);
  72:          break;
  73:          default:
  74:              return DefWindowProc(hwnd, Message, wParam, lParam);
  75:      }
  76:      return 0;
  77:  }
  78:   
  79:  int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  80:      LPSTR lpCmdLine, int nCmdShow)
  81:  {
  82:      WNDCLASSEX wc;
  83:      HWND hwnd;
  84:      MSG Msg;
  85:   
  86:      wc.cbSize         = sizeof(WNDCLASSEX);
  87:      wc.style         = 0;
  88:      wc.lpfnWndProc     = WndProc;
  89:      wc.cbClsExtra     = 0;
  90:      wc.cbWndExtra     = 0;
  91:      wc.hInstance     = hInstance;
  92:      wc.hIcon         = NULL;
  93:      wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
  94:      wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  95:      wc.lpszMenuName  = NULL;
  96:      wc.lpszClassName = g_szClassName;
  97:      wc.hIconSm         = NULL;
  98:   
  99:      if(!RegisterClassEx(&wc))
 100:      {
 101:          MessageBox(NULL, "Window Registration Failed!", "Error!",
 102:              MB_ICONEXCLAMATION | MB_OK);
 103:          return 0;
 104:      }
 105:   
 106:      hwnd = CreateWindowEx(
 107:          WS_EX_CLIENTEDGE,
 108:          g_szClassName,
 109:          "Incinerator",
 110:          WS_OVERLAPPEDWINDOW,
 111:          CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
 112:          NULL, NULL, hInstance, NULL);
 113:   
 114:      if(hwnd == NULL)
 115:      {
 116:          MessageBox(NULL, "Window Creation Failed!", "Error!",
 117:              MB_ICONEXCLAMATION | MB_OK);
 118:          return 0;
 119:      }
 120:   
 121:      ShowWindow(hwnd, nCmdShow);
 122:      UpdateWindow(hwnd);
 123:   
 124:      while(GetMessage(&Msg, NULL, 0, 0) > 0)
 125:      {
 126:          TranslateMessage(&Msg);
 127:          DispatchMessage(&Msg);
 128:      }
 129:      return Msg.wParam;
 130:  }

Now isn't that a good old fashioned pain in the ass?  So, sure, you could use Visual C, which I hear has a drag and drop GUI builder (correct me if I’m wrong), but that requires .NET, which has dependencies and requires the system to be installed for the end user.  Java, although it requires a JVM, requires no such other dependencies, so you’re set on a new PC install.

Also, you’ll notice just code size.  The C Win32 implementation required 130 lines (the actual code is bigger due to trimming of irrelevant parts).  That’s a lot of code for a programmer to write, debug, and maintain.

So, in essence Swing is a much easier GUI creation tool in nearly every way.  If you want to full API docs, the version 7 link is here.

That’s all for tonight, folks.  You can grab our RSS feed to subscribe and always stay up to date.  Hopefully we’ll have more Java talks in the future!  Thank you, and goodnight.

-SevenBits

Saturday, November 26, 2011

Basic Command Prompt Skills

Believe it or not, computers weren’t always the point-and-click wonders we know now.  No, they used to be giant creatures who’d take their input on punch cards and spit out a result on actual paper.  Almost makes you want to do your math in your head, yes?
Although those days are long over, one fact of those eras remains: the stench of the command line.  Yes, ladies and gentlemen, they still exist in modern computers, and I’m going to explain to you how to use it in your favorite operating system – Mircosoft Windows.
Essentially, there are only two different desktop (to distinguish from iOS or Android) operating systems out there.  Yes, I know that sounds ludicrous, but bare with me, because it’s true.  These two operating systems are MS-DOS (from which Windows is based), and Linux.
Now, hold on, you’re saying.  My nephew has a Mac, my husband uses Ubuntu at work, and surely they fit in somewhere!
They do, actually.  Both those fit into the Unix category.  Ubuntu is a form of Linux, which is a form of Unix written by Linus Torvalds.  And Macs are actually built on top of Linux and utilize a special form of Unix underneath called the Darwin Terminal (I’m sure you Mac diehards will know this already; for everyone else, Unix is a topic for another day).
Now, Windows is based upon MS-DOS.  In the beginning of Windows’s existence, it basically echoed all your commands to DOS which performed the action (to all of you who are wondering – MS-DOS is an acronym for Mircosoft Disc Operating System).  However, in modernity Windows can perform most of its actions itself now, and DOS is provided mainly for compatibly with old programs.
Now, onto using DOS and the terminal in general.  Here we go; here’s how to access the terminal:
  • In Windows: Go to the Start Menu, click All Programs, click Accessories, click Command Prompt.
  • In Mac OS X: Open a Finder window.  Go to your applications folder and find a folder called Utilities.  Open that folder then find the program called Terminal.  Double-click it to start it up.
  • Ubuntu: Use these instructions, taken from the Ubuntu docs:
Unity is the default Desktop Environment used in 11.04. Where systems are not ready for Unity they revert to Gnome which is also used in previous releases such as Ubuntu 10.04 LTS (Lucid), see next sub-section.
The easiest way to open the Terminal is to use the 'search' function on the dash. Or you can click on the 'More Apps' button, click on the 'See more results' by the installed section, and find it in that list of applications. A third way, available after you click on the 'More Apps' button, is to go to the search bar, and see that the far right end of it says 'All Applications'. You then click on that, and you'll see the full list. Then you can go to Accessories > Terminal after that. So, the methods in Unity are:
Dash -> Search for Terminal
Dash -> More Apps -> 'See More Results' -> Terminal
Dash -> More Apps -> Accessories -> Terminal
Keyboard Shortcut: Ctl + Alt + T
Today we’re going to focus on the MS-DOS commands.  In a later post I will cover Linux, which will apply to Mac users as well.

1.  Basics

The most standard thing you can do as simply navigate around your directory file structure.  You can do it by typing each of these commands into the MS-DOS window, then pressing Enter to confirm the command.
command-line-start
  • cd
    Change Directory Access a new directory by typing “cd directory-name”.  Navigate to “..” (that’s two periods), to go up a directory level.
  • dir
    Get a listing of every file and folder on the current directory you are in.
  • type
    Enter the contents of a plain, text (.txt extension) file, and the computer will write it out for you.  If it’s a long file, though, the lines may print so fast you can’t see them.  Also, don’t enter a Mircosoft Word file into this command: you won’t like the result.  Example: “type readme.txt”
Now that you know the three basic commands, try everything out.  Use “dir” to obtain a list of files and folders, “cd” to go to a different folder, and when you see a .txt file, use “type filename.txt” to print it onto the window.
And don’t worry: none of these commands in this section change your computer in any way.  Don’t be afraid to play around.

2. Getting Funky

You can do lots of things in the command prompt.  Things that are difficult, or even impossible, to do using the standard Windows interface.  Just type “help” to see them all.  Some of the commands may sound alien to you, like “mklink”, “icacls”, etc.  Best word of advice: don’t mess around with them.  Until you know what something does, don’t play with it.
We’re going to do something small and neat.  There exists a Windows command called “fc” that examines two files and displays the differences between them.  So go ahead and create two text files with Notepad.  Put anything in them, and save them (be sure with the .txt extension).  Navigate to where you saved them with “cd” then type “fc first-file second-file”.  Be sure to include the .txt extension – if you don’t the computer doesn’t like it.
The computer should spit out some output.  If it doesn’t, check your input, otherwise message me in the comments.  Happy Hunting!

Wednesday, November 23, 2011

Product Review: CCleaner


CCleaner knows what to get rid of!
Hey, everyone!  Welcome to my first product review.  I’m going to start by going over a product I love and use frequently – Piriform’s wonderful CCleaner tool.  I like it because it allows you to clean your computer of unnecessary files and gunk.  For instance, your computer makes frequent use of log files, the order your programs appear in the Start menu and what files you’ve recently opened – and these are all stored in files on your hard disc (yes, I spell ‘disc’ with a ‘c’, for reasons I’ll explain some other time).

The worst case can easily be temporary files – these babies get created all the time by Windows and by programs by use, and they aren’t easy to get rid of because they aren’t easy to find.  Often, they are created in hidden folders like AppData in your user folder (in Windows 7, that is) and aren’t removed.

CCleaner is great about this, and all you have to do is go to the main screen (Cleaner), and press Analyze (Quick Note: If you don’t have admin rights, CCleaner can only look in folders you can access as a standard user).  Then sit back, as in a few moments it will present you with an estimate of how much space it can remove.  Click Run Cleaner, then the fun starts.  CCleaner’s icon of a brush was aptly chosen, as it cleans like your virtual slave.  You can even customize exactly what you want removed:

By choosing aptly about what you want removed, you can control what you do – or don’t – want trashed.

These file cleaning features are not the extent of CCleaner’s interface, no sir!  No, CCleaner can also clean your Windows registry.  The Windows registry, for those of you who don’t know, is a huge database Windows uses to keep track of program data, including settings and file history (a good read up on it can be found on Wikipedia here, but it’s a bit technical).  However, when you install/uninstall a program, your registry can be full of crap (dare I say s***?) from entries the program wrote but didn’t erase on uninstall.

Wow, that computer has a lot of issues…
CCleaner can also be an uninstaller, allowing you to remove programs with the Uninstall option in the Tools category, but this requires admin rights.  You can customize what programs can run when your system starts up, modify/delete system restore points, and wipe the free space of a computer hard drive or thumb/USB drive.

CCleaner also has additional options, such as a whitelist, under its Options panel.  I suggest you basically check it out.  Also, you Mac geeks out there haven’t been left out: Piriform has a public beta for you OS X 10.5 to 10.7 (OS Lion) users, and is downloadable as a DMG archive at this link.
Note:  All pictures in this article are from Piriform’s website for CCleaner.  I do not own these images, and have included them because they will help illustrate the software.  If Piriform does not want these images here, drop me a line on my comments page and I’ll remove them.

Opening

Hello, World!

And what a fine world it is!  Today I’m going to discuss – in my very first blog post EVER – what I’m going to achieve by writing this blog.  First off, this blog is to entertain you.  Well, sort of, I guess.  This blog is really to discuss all kinds of tech things.  If you’re looking for that new cookie recipe, this isn’t the place.  Go find some other blog.

 

But if you want to hear about software I think is neat, new videos games I think are cool, and maybe a short discussion on why my music taste is best, then this is the blog for you.

 

Now, a little about myself.  I’m a software developer living in southern New Hampshire.  My strengths are in Java (though I know enough C and C++) and a small game engine known as Unity 3d.  Unity is an awesome game engine built for speed and can make all kinds of games, and no, I wasn’t paid to say that.  The reason Unity is my favorite is because there was a minimal learning curve and it performs well on my laptop, unlike other engines I’ve tried like UDK, and that out of the box, with the free version, it allows you to create stand-alone applications for Windows and Mac, games that can be played in a web browser using the Unity 3D Plugin, which is available for all major browsers.  But that’s enough singing Unity’s praises, if you to see more you’ll check out the website.  I know you will.

 

What are some of my ongoing projects, you ask?  Well, I’m not going to go into any detail, as there are people about just begging for an idea that they can make, so I’m only going to post completed, copyrighted projects on this blog.  Eventually I’m going to (hopefully) start a small company and give myself a website so I can allow people to buy my work.

 

I also enjoy writing.  I write small little poems and short stories for fun.  Maybe I’ll post one sometime.  You’d all like to see that, right?  Right?

 

I hope someday to get into iOS app development, i.e. for the iPod, iPhone and iPad.  That’s a huge market and a way to earn a little money, yes?  Too bad so many have already had that idea; the competition is huge.

 

Alright, that’s about it for now.  Some more posts will be coming very soon, so just wait!  Also, in the top corner of this screen, just above my logo, you can see the link to the RSS feed.  You can subscribe to this feed if you want to go be alerted of my new blog posts – which I surely hope you do.