Jul 31 2008

The first day of Reckoning

Categories: Computers, Programming
Tags: ,

I’ve been poking at Cocoa development for quite a while now. That said, I haven’t finished anything I’ve started as of yet. I start a lot of things and then move to something else. Stacy thinks I have a problem. To that end, I’ve started a small application for Stacy. Nothing special, it’s just designed to do simple tracking of invoices and payments for her freelance business.

Since I’ve actually got someone who wants to use the application I’ve actually got a reason to finish it. I’ve imported the initial application, Reckoning, into GitHub for all the world to marvel over my ability to click icons in Xcode and Interface Builder.

Since I’m working on the application I may as well write about it a bit as well. Hm, I think I mentioned something about not being able to do just one thing?

With that in mind, let’s begin.

As mentioned, Reckoning is a simple application to track invoices and payments. There are four main items that will be tracked: Clients, Invoices, Line Items and Payments. To get this party started fire up Xcode and create a new Core Data Application. (This maybe better as a Core Data Document based Application but I picked Core Data Application.)

I got started by developing the data model (well, developing the data model after reformatting the default code to match my personal style). Double click on the Reckoning_DataModel.xcdatamodel file to launch the data modeling tool.

Before we get into the data model tool I guess I should tell you a bit more about my data. The system will have the following structure:

  • Client

    • name :: string (default: New Client)
    • invoice_period :: integer (default: 30)
    • invoice_notes :: string
    • contact_name :: string
    • contact_email :: string
    • address :: string
    • city :: string (default: Toronto)
    • province :: string (default: Ontario)
    • postal_code :: string
    • country :: string (default: Canada)
    • invoices :: to-many relationship to the Invoice table
  • Invoice

    • date :: date (default: “today”) [note the quotes matter for the date fields]
    • due_date :: date (default: “today”)
    • notes :: string
    • taxes_saved :: float
    • total_invoiced :: float
    • total_received :: float
    • client :: relationship to the Client table
    • line_items :: to-many relationship to the LineItem table
    • payments :: to-many relationship to the Payment table
  • Line Items

    • date :: date (default “today”)
    • description :: string
    • hours_worked :: float
    • rate :: float
    • invoice :: relationship to the Invoice table
  • Payment

    • amount :: float
    • date :: date (default: “today”)
    • invoice :: relationship to the Invoice table

You’ll end up with something similar to the figure below in the data modeler.

Reckoning Data Model

Reckoning Data Model

About the only item not mentioned in the above is the regular expression used to validate the email address. After a bit of Googling I found a great resource on matching email addresses and entered ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$ as the contact_email regular expression.

Simple enough. Although, writing this I realized I forgot the default_rate field in the Client table. Oh well, something to do tomorrow.

The next step in our application is to start the user interface. For the first revision I’ve created the ability to add clients, invoices and payments. You can’t edit many of the details yet but the basic creation is there. (I’ll actually have to write some code to get that part done.)

Closing the data modeler tool we can now click on the MainMenu.xib (or .nib if you’re using an earlier version of Xcode) to launch Interface Builder.

Currently everything happens in the main Reckoning window. I’ll need to add sheets and property dialogs and things as time goes on but for now, one window.

Main Reckoning Window

Main Reckoning Window

The three fields in the Income section are set to non-editable text fields with a number formatter attached. All three number formatters are set to the currency style. (These three boxes do nothing in the current version.) The Due Date and Date columns have a date formatter attached. The Amount column has a currency formatter similar to the Income fields.

About the only other thing that needs explanation is the 7 outstanding invoices. This line will dynamically update in the final version of the app to give information on the outstanding and overdue invoices for each client. I’m also hoping to be able to colour the table cell text differently depending on the invoice status.

The Edit buttons are currently unused. The + and - buttons are used to add and remove items from their section.

Ok, lets see how much of this thing we can hookup without diving into any code.

First up, we need some controllers. We have three Core Data tables we’re going to want to pull data from for this first iteration. To that end we’ll drag three array controllers from the library down to the information window. Set the name of one to Client Controller, one to Invoice Controller and one to Payment Controller.

Information Window

Information Window

In the inspector set the mode of all three to Entity and set the Entity Name to the corresponding entity name in our data model (Client, Invoice and Payment respectively).

Next up are the bindings for our array controllers. We’ll start with the Client Controller.

Client Controller

Client Controller Bindings

This is the simplest controller to hookup. We just have to tell the controller that it will be getting its Managed Object Context from the Reckoning_AppDelegate using the mangedObjectContext Model Key Path. The Reckoning_AppDelegate was created for us when we created the application.

Next up is the Invoice Controller.

Invoice Controller Bindings

Invoice Controller Bindings

You’ll notice an extra section to our bindings for this one. The bottom, Managed Object Context binding, is setup exactly the same as our Client Controller. The extra binding, the Content Set binding, allows us to bind the content of the Invoice Controller to the currently selected item in the Client Controller. This way we’ll only show the invoices for the selected client. So, you can see we’ve bound to the Client Controller with a Controller Key of selection and a Model Key Path of invoices. What this is doing is taking the current selection from the Client Controller and retrieving the array returned from the invoices method. The invoices method was created for us by Core Data based on the invoices relationship we created in our model.

Finally the Payment Controller.

Payment Controller Binding

Payment Controller Binding

This one is very similar to the Invoice Controller binding. We just bind to the Invoice Controller instead of Client Controller and we want the payments key path in the invoice model.

Sweet, our arrays are now hooked into our Core Data model and are ready to populate our tables. We’ll bind the Clients table first.

Client Table Bindings

Client Table Bindings

Nothing too complicated in there. We want to bind the Value binding for the Table Column (make sure you have the Table Column and not the Table View or Text Field Cell or the Scroll View). We bind to the Client Controller as it’s the client information we want to display. We use the Controller Key of arrangedObjects which will return the objects in the given controller. I setup the cells to display the name of the client so we use the name key path into the Client object. I’ve also checked the Continuously Updates Value field. I’m not sure what this does but one of the tutorials mentioned it so I use it. If you know, please let me know.

We now move onto the Invoicing table.

Invoicing Client Column Bindings

Invoicing Client Column Bindings

This is similar to our Client bindings from above. We want to bind to the Invoice Controller and I’m using a different model key. The model key is set to client.name. This allows me to retrieve the name field of the client associated with this invoice. (Remember we have a relationship from Invoice to Client in our model.) You can use the dot notation to chain these methods together to pull out the exact information you require.

The Due Date column is the same except I bind the model key to due_date.

Finally the Payment table is basically the same bindings. For the Client column I bind the model key to invoice.client.name to pull out the client name for the invoice associated to this payment. The other fields just bind to date and amount respectively.

Cool. Ok, we can now display the data stored in our Core Data model. I guess it would help if we could actually add some data. If you haven’t noticed, pretty much everything we’ve done has been fairly easy (assuming you know the right syntax for the model keys and the controller keys.) Hooking up add and remove is no different.

If you option-click on the + symbol in the Clients section you can drag (and a blue line will appear) down to the Client Controller. Releasing the mouse you’ll see a popup. Select the add: entry. Do the same option-click and drag from the - button and select the remove: entry.

Follow the same procedure for the buttons in the Invoicing and Payments sections.

Save the file in Interface Builder, switch back to Xcode and run the application. You should be able to add clients, invoices and payments and hitting apple-s will save the file. If you close Reckoning and re-open you should see your created data populating the tables.

Not bad for not actually writing a line of code, eh?

Next time we’ll be attempting to hookup the Edit buttons for the client and invoicing information.


Jul 28 2008

Get your game on

Categories: Life
Tags:

A friend of mine has just returned from many moons out in Vancouver working for big game companies to start his own indie company. He’s keeping a blog of the trials and tribulations of starting a company and creating his first game.

It’s been pretty interesting so far. If you’re interested, check it out over at http://streamingcolour.com/blog.


Jul 28 2008

Delta can bite my shiny metal ass

Categories: Life

So, Stacy and I were planning on going to Seattle this week for a vacation. We wandered off to the airport early this afternoon and arrived at about 2.20 (our flight was for 4.20 so lots of time.)

At this point we ran into what must have been the longest line I’ve seen in an airport. All queued up for the Delta checkin. Ok, fine, I’ve been in lines before, we join the line. We wait. And wait. And wait. Three steps every 10 minutes isn’t much progress. The clock rolls around to 3 and we’re starting to get a bit nervous. You have to check in an hour before your flight so we start looking around for any Delta people on the floor that we could talk to. There was an American Airlines guy but he was just helping his passengers through the Delta line.

At about 3.20 I jumped the line to ask the guy at the Delta counter if we should be moving up as we had the 4.20 flight. I was, tersely, informed that everyone in the line was waiting for the 4.20 flight. Back to the line I went. 3.30. 3.40. 4. 4.10. 4.20. By this point we were about 10 feet from the start of the roped off section marking the beginning of the line. According to the flight board our flight was still on time. 4.30. 4.50. 5. 5.10. Ok, about 10 people left in front of us in line. Well, except for all the people that keep budding into line. And the people that take 45 minutes at the counter. What could you possible be doing that takes 45 minutes and the ticket agent to be on 2 phones at the same time? Yes, she had a phone pressed against each ear.

Keep in mind, in all this time Delta hasn’t said anything to us. There are no Delta agents in sight except for the people behind the counter. The GTAA (Greater Toronto Airport Authority) agents keep telling us that a Delta agent will be out soon to tell us what’s going on. No Delta agent appeared.

5.30 rolls around and an agent stands up and says Ok, everyone in line will have to be rebooked on a flight tomorrow. At which point a lot of people go ape shit. The two ladies in front of us were trying to get a connection so they can get to England. It looked like that managed to brow beat the agent into giving them a ticket.

Stacy and I didn’t bother. I called up Expedia and after an bit time on the phone got a full refund from Delta and most of a refund for the hotel. We’ve got to pay for one night but that’s it. Not too bad. Sounded like she didn’t’ have too much trouble with the Delta office either. Other people in line were calling and Delta was telling them they were still able to get on the flight or it was their problem for being late (not what you want to tell someone after they’ve been in line for 3 hrs at your ticket counter.)

So, kudos to Expedia for getting everything cancelled and the refunds for us. Delta, bite my shiny metal ass. I’ll never book on your airline again.


Jul 27 2008

Edition the 4th. Thoughts.

Categories: Books, Gaming
Tags:

We finally ran it. A few of us got together this weekend to play 4th edition Dungeons and Dragons. We wanted to give the game a fair shake so we played strictly by the rules. (We’ve got so many house rules for DnD that this was almost a challenge, heh.) We also played the adventure in the back of the Dungeons Masters guide as that seemed like a good way to start.

I was Tolvan an Eladrin Rogue. We also had a Dragonborn Warlord, a Dwarven Figher and a Tiefling Warlock. One character short of a full party but we scaled the monsters down as needed. As I mentioned, this was a learning game, there were a lot of combat rules referenced.

So, how did it go? The campaign went well. We accomplished the required quests (although I was an hour late leaving to visit my parents.) I think we got a feel for the game played with a strict adherence to the rules and I think we all got a feel on what we thought of 4th edition.

Now, I know you’re all chomping at the bit to know what I think but, one more interlude. These comments are based on playing with the real rules. Like I said, we never play with the real rules as we’ve house-ruled everything. We’re going to give this another shake at some point to see how it feels with our custom changes attached.

That aside, I was a little disappointed in how the game played. It has been mentioned in several places that 4th gives DnD an feel similar to a massively multiplayer online game. I’d have to agree with this statement. They’ve done a lot of work to simplify things (which, in some cases, makes it more convoluted) and changed the game a lot to cater to new players. Some of this served more to distract me then to add to the game.

What did I like? Well, I like the new skill combinations. Makes everything a lot simpler and makes a lot of sense. The idea that you just have Perception instead of Search, Spot, Listen and who knows what else is a good abstraction. The fact that you’re either Trained or Un-Trained I’m not so hot on. As well, the fact that you can only learn new skills though a feat? What the duse? (Yes, I know, re-training, but we’ll get to that.) I think the concept of skill points and ranks wasn’t too bad. It let me put points into things that aren’t necessarily combat related (yes, one of my characters has ranks in profession sailing) and the removal of the craft related skills takes something away from the game.

Powers are an interesting one. I’m on the fence about these. I like the idea, I think they add flavor to the game. The fact that I have to make every attack use a power or I’m gimped drives me up the wall. Whatever happened to good old fashioned, I’m hitting that guy? Now it’s I’m using my Sly Flourish power to hit that guy. Damn it, sometimes I just want to hit things and I don’t want to get gimped for it. (I’m also a little bitter in that every time I used my Daily power I missed so it didn’t have any effect.) The other side of powers that I both like and dislike is how they work. Your power will tell you what to roll and what’s used for defense against the power. Say, Dexterity vs Reflex. This is good, this is kinda cool. This gives me a way to hit the fighter with an armor class of 21 but a Reflex save of 10. This also kinda sucks in that it’s a pain in the ass to remember what modifiers you’re adding and what the defense is for that role.

What’s the deal with feats? There aren’t very many and even when you dig into them so many are class specific that there is a very small pool to choose from.

I said I’d get to it, so here we go, re-training. Similar to powers I both like and dislike re-training. Why is it good? Well, there have been several occasions where I get high enough level, pick a prestige class (yes, yes, 3.5 reference but it’s my reference point) and realize I’m missing a simple skill pre-requisite. I then have to wait until I’ve got enough skill points I can use to raise that skill. This always kinda sucks. (I guess if I was really anal I would plan out my character from first to 30th before I start to play but I’m just too lazy. I like the more random approach.)

In this situation re-training would be helpful as I can move the training from a more minor skill into the needed skill.

This also doesn’t make any sense. What, I magically wake up one day and forget about Religion and learn everything there is to know about Nature? Same argument for feats. What, I suddenly forget how to stab someone in the back so my Sneak Attack damage has decreased?

Re-training does make sense for powers as I still think of them similar to spells.

Speaking of spells, personally, I think wizards got gimped. Sure, they get twice as many powers but they still have to pick the same number as everyone else at the start of the day, they just have a wider selection. You can’t memorize the same spell twice, so I can’t cast fly on two characters in the same day? Suck.

As Deacon said, I can’t play this game, there’s no 10 foot pole.

Concluding, I’m going to give 4e another shake. We’ll see what happens when we house rule a few things. I’m leaning towards preferring 3.5 but who knows.


Jul 27 2008

Wanted

Categories: Books
Tags:

I’m sure you’ve all heard about the Wanted movie that’s come out in recent weeks. I’m not here to talk about that. I’m here to talk about the comic that the movie is kinda, sorta, maybe, if you squint enough, based upon.

I picked this one up while on my hunt for the Watchmen last week. It’s pretty short, so I started reading it on the subway on the way home. I finished it off this weekend.

Wanted is excellent. The writing, art and execution are all very well done. Although, if you don’t like mature content, I’d say skip this one.

Wanted is a story about villains. Super-villains to be exact. It’s the story of one mans rise from the drudgery of modern day to being the worlds greatest killer. There are a lot of little references and nods towards real comic book heros and villains but none are mentioned straight out.

I really liked the concept for this book and I’ve always had a soft spot for the villain as the hero (see Villains by Necessity for a great villain as hero novel) so this book appealed to me.

I’ve you’ve read a few graphic novels, maybe cut your teeth on some Preacher, give Wanted a go. You maybe pleasantly surprised. Or, you’ll throw the book across the room, burn it and say 100 Hail Marys to purge yourself after.

One or the other.


Next Page »