Zendikar Expeditions: Good for the Game or Another WOTC Money Grab?

There are a number of opinions floating around about the Zendikar Expeditions, and for good reason. WOTC doesn’t do this very often. As Magic players, we have come to expect certain things in our packs (I’m still waiting for them to fold the $20 bills right…), and when WOTC doesn’t deliver on that, we begin to get uncomfortable and start complaining, sometimes without even thinking about it.

That was me when the announcement came. I didn’t like it because it meant my parents and other family members who help to feed my Magic addiction would probably have to pay more for the sealed product since that is what I told them I wanted for my birthday. In reality, the thing that is making the fat packs cost more this time around is the pack of full art lands that is included, and less so the Zendikar Expeditions stuff. Now, these I will probably keep sealed and look to sell in a couple of years. I don’t care much for any of the art on the lands, save for one or two, so it doesn’t make sense for me to open them up (yeah, I can get pretty particular about my lands when I want to… If I had all the money in the world, I’d be buying up Beta Islands like nobody’s business).

Now… back to reality. What is the big deal about Zendikar Expeditions? Well, they are exceptionally rare for one–slightly less rare than a foil mythic, according to MARO–which occur 1 in every 216 packs, approximately (here’s a Reddit post that breaks down–and argues in typical Reddit fashion–the numbers). They are foil ‘full-art’ versions of cards that see play in Modern and Legacy–Shocklands and Fetchlands are the big ones people will be after, along with foil versions of cards that occur in the block. My biggest fear was the increased cost of sealed product. Now, this promotion WILL do that. The people who want these premium lands will spend money hand over fist to get them, especially if they plan on dropping some serious money on a couple of cases anyway. Increased demand for the product will invariably mean an increased price. What does this mean for the typical FNM regular? Little to nothing. I MIGHT buy a booster box if I can scrape together enough loose change to do it (i.e. not likely… My LGS would probably ban me for life if I tried to pay for a booster box with loose pennies anyway), but I would not be terribly disappointed if I don’t, and here’s why.

Thanks to this promotion, the full-art basic lands, the new duals, and the new manlands, Battle for Zendikar will be heavily opened. Staples for Standard will be pretty inexpensive in the secondary market unless they have implications for Modern, Legacy, or Vintage (Monastery Swiftspear, I’m looking at you!). It would not be unreasonable to see some tier-1 or 1.5 competitive decks that sit around $100-$150 post-rotation when purchased from sites like TCGPlayer.com.

Many players fear this is a move towards a new Ultra-Rare rarity. This is not the case. All the cards in the Zendikar Expeditions are reprints, or available in other versions. They are not needed to play the game. They are valuable because they are dolled up versions of multi-format staples that are in high demand. Any version of those staples will do what any other version could do.

Some argue that this is Wizards ‘printing money’ with these promotions. Players are upset because this promotion creates artificial demand for the sealed product, which drives up prices of said sealed product. Here, if anywhere, I believe players have reason to be angry. Not being able to easily acquire product at or below MSRP for the first couple of weeks of availability because of speculators and people pre-ordering and then re-selling at a markup could be an issue. Hopefully, the print runs are large enough to account for this, and I suspect they will be. For the first few weeks of availability, expect to pay full-on retail unless you had some stuff on pre-order at a discount or you have special arrangements. As for the secondary market, new set hype should begin to settle down after a few weeks, and the cream of the crop will rise to the top in typical fashion. Aside from the ‘chase’ rares, things should be pretty cheap on the secondary market after that.

Personally, I am looking forward to the new set because I have never had any desire–and probably never will–to drop $300+ on a deck that I can only play for a year or so, and this is shaping up to be the cheapest Standard in recent history.

Ok, I’m convinced… Ember-cli is Awesome! Now, how do I use it? (Part 2)

Our app works now… sort of… but we still need to be able to check off each todo item as it’s completed, make changes to our todo’s, and eliminate our old todo’s with extreme prejudice.

This thing is pretty ugly, I’ll admit–even for a nerd. If you want to take a detour and Bootstrap, Compass, Foundation, or otherwise spiffy up your app, feel free. Details for how to get started doing this can be found at Ember-cli’s asset compilation page here.

As you might guess, we import the necessary assets in the ember-cli-build.js file. If we just wanted to add our own custom css changes, we could do so in app/styles/app.css.

Done yet? Good! Let’s continue.

Let’s add an action to our checkboxes in our todos template and a handler to our ‘todos’ route so we can check off our todos We will also need to add a “checked” attribute to our todo model.

In app/templates/todos.js:

1 <h1>Todos</h1>
2 <div class="nav">{{#link-to "new"}}New Todo{{/link-to}}</div>
3 {{#each model as |todo|}} 
4 {{#if todo.checked }} <label class="strikethrough"><input checked="checked" type="checkbox" />{{#link-to "todo" todo}}{{todo.name}}{{/link-to}}</label>
5 {{else}} 
6 <label><input type="checkbox" />{{#link-to "todo" todo}}{{todo.name}}{{/link-to}}</label>
7 {{/if}} 
8 {{/each}}

In app/routes/todos.hbs:

  1 import Ember from 'ember';                                                                                         
  3 export default Ember.Route.extend({                                                                                
  4         model: function () {                                                                                       
  5                 return this.store.findAll('todo');                                                                 
  6         },                                                                                                         
  7        actions: {                                                                                                  
  9                checkOff: function (todo) {                                                                         
 10                        todo.toggleProperty('checked');                                                             
 11                        todo.save();                                                                                                                                                                                                       
 12                }                                                                                                   
 13        }                                                                                                           
 14 }); 

In app/models/todo.js:

  1 import DS from 'ember-data';                                                                                                                                                                                                              
  3 export default DS.Model.extend({
  4        name: DS.attr('string'),
  5        details: DS.attr('string'),
  6        checked: DS.attr('boolean')
  8 });

Alrighty. Good bit going on here. We have a handlebars if/else block that changes what is displayed based on the truthiness of our model’s checked attribute. There is probably a better way to do that, but finding a more D.R.Y. way to do this is something you can do as a homework exercise. If our todo is checked off, we want the todos route to display a checked checkbox. I also added the ‘strikethrough’ class to the label to add the line-through text decoration. In my app.css, my strikethrough class looks like this:

.strikethrough {
    text-decoration: line-through;

Now, we need to handle editing our todos. We can do this in a separate edit route, or we can go ahead and do it on the todo route. There are probably still more ways we could implement this, but those are the two that come to mind. Let’s go ahead and add our edit feature. We will use an edit button with an ‘edit’ action. We will then redirect to the ‘edit’ route, reusing the ‘new’ template after we make a few minor changes to it. We could have the ‘edit’ action called when the text is clicked on, but then we would need to provide some sort of indication that clicking on the text would allow you to edit it, probably in the form of a :hover CSS rule. You can do whatever you want. We will start in app/templates/todo.hbs:

3 <button {{action 'edit' model}}>Edit</button>

Here, we pass the model to the edit action, and we’ll see why when we get there. But first, we need to create our edit route:

ember g route edit

Now, let’s edit the edit route (app/routes/edit.js):

  1 import Ember from 'ember';
  3 export default Ember.Route.extend({
  4         renderTemplate: function () {
  5                 this.render('new');
  6         },
  7         actions: {
  9                 save: function (todo) {
 10                        var name = $('input').val();
 11                        var details = $('textarea').val();
 12                        var model = this.get('model');
 13                        todo.set('name', name);
 14                        todo.set('details', details);
 15                        todo.save();
 16                        this.transitionTo('todo', todo);                                                                                                                                                                                   
 17                 }
 18         }
 19 });

Notice renderTemplate in the above route. Our ‘edit’ route will reuse our ‘new’ template, with a few minor but important changes. Take a look (app/templates/new.hbs):

1 <h1>Todo</h1>
3 <input type="text" value="{{model.name}}" placeholder="Todo Name" /> 
4 <hr />
5 <textarea placeholder="Todo Details">{{model.details}}</textarea> 
6 <hr />
7 <button>Done</button>

We are passing the model to the save action now. This will not affect how our ‘new’ route handles the save action since it did not receive a model in the first place.

Congrats! We can now edit our todos!

Now, let’s handle deleting checked-off todos. We need to start by editing the todos template and adding a delete checked button with an appropriately-named action handler.

In app/templates/todos.hbs:

  1 <h1>Todos</h1>                                                                                                                                                                                                                            
  2 <div class="nav">{{#link-to "new"}}New Todo{{/link-to}}</div>
  3 {{#each model as |todo|}}
  4 {{#if todo.checked }} <label {{action "checkOff" todo}} class="strikethrough"><input type="checkbox" checked>{{#link-to "todo" todo}}{{todo.name}}{{/link-to}}</label><br>
  5 {{else}}
  6 <label {{action "checkOff" todo}}><input type="checkbox">{{#link-to "todo" todo}}{{todo.name}}{{/link-to}}</label><br>
  7 {{/if}}
  8 {{/each}}
  9 <button {{action 'deleteTodos'}}>Delete checked todos</button>

Nothing we haven’t seen before here. We have a button with an action handler that currently doesn’t have an action to match it. All we have left to do is add another action and we are done. We will get all the todos and loop through them using forEach. If their checked attribute is true, we will delete them (app/routes/todos.js):

  1 import Ember from 'ember';                                                                                                                                                                                                                
  3 export default Ember.Route.extend({                                                                                
  4         model: function () {
  5                 return this.store.findAll('todo');
  6         },
  7        actions: {
  8                checkOff: function (todo) {                                                                         
  9                        todo.toggleProperty('checked');
 10                        todo.save();
 11                },
 12        deleteTodos: function () {
 13                this.store.find('todo').then(function (items) {
 14                        console.log(items);
 15                        items.forEach(function (item) {
 16                                if(item.get('checked')) {
 17                                        item.deleteRecord();
 18                                        item.save();
 19                                }
 20                        });
 21                });
 22        }
 23        }
 24 });

That’s it! We are finished! Congratulations! You are now an Ember master. Go forth and use your powers for good. There are plenty of improvements we could (read: probably should) make to this example, but I will leave that to you. Good luck, have fun, and feel free to ask for help when you need it. If you are stuck, you can get the source code here.

Ok, I’m convinced… Ember-cli is Awesome! Now how do I use it? (Part 1)

I thought you would never ask…

Getting into Ember-cli is easier than one might expect, especially for those who are comfortable with Rails, and are comfortable working in a Unix-based terminal. First, you need to install it, and in order to install it, we will need node and npm. My environment is Linux, so these instructions are heavily biased in that direction. We will need to start off by running these commands as root in the terminal:

apt-get install node
apt-get install npm

Now, the real fun begins. Using the Node Package Manager (npm) that we just installed, we can install Ember-cli:

npm install -g ember-cli

If we wanted Bower (we do, by the way), we could install it too.

npm install -g bower

That should be enough to get started. There are more detailed instructions on how to install Ember-cli available on the user guide here.

Next, we will want to create a new project. Navigate in the terminal to the directory we would like to create our new project in (in my case, it’s ~/MyProjects), and let Ember-cli do all the boilerplating for us:

ember new my-new-app

Navigating into the my-new-app/ directory should reveal a set of directories and a few files. The app/ directory is where we will be spending most, if not all of our time. Let’s go ahead and make sure everything is good to go. Enter the command:

ember serve

Navigating to the URL (by default, it’s http://localhost:4200) that we are directed to in a web browser should show us a “Welcome to Ember” message if everything is working properly. We could stop the server by hitting ctrl+C in the terminal, but let’s just leave it running and open another terminal instead. Hitting File > Open Terminal in the terminal window(or shift+ctrl+N) will open a new terminal in our current working directory.

Now, let’s go ahead and create a resource. Let’s make an awesome and innovative app… why not a todo-list app? I’m sure no one has thought of doing that before! Ember makes this super-easy:

ember g resource todo

The ‘g’ in the previous command stands for generate. We could of course type it out, but why bother with those seven extra keystrokes? There are a few other minor things we need to take care of before we can really get our hands dirty. We need a ‘todos’ route so that we can see all of our todos at once:

ember g route todos

Once we have everything set up properly, we will then be able to go to localhost:4200/todos (well, localhost:4200 once we set the path, but I’m getting ahead of myself) and see all the todos that we have created. Let’s go ahead and create a ‘new’ route as well.

ember g route new

Now, we can get our hands dirty. In app/models/todo.js, let’s go ahead and set up our todo model. We can always go back later and add/remove things as necessary.

  1 import DS from 'ember-data';
  3 export default DS.Model.extend({
  4        name: DS.attr('string'),
  5        details: DS.attr('string')
  7 });

Great job! That should do for now. While we don’t ‘have’ to use Ember Data, it’s pretty sweet. The next step is going to involve router.js. This file will be in the app/ directory. The router handles URL’s for our app. We will want to set up a dynamic route for ‘todo.’ To do this, all we have to do is pass in an id for the todo we want in our path. We also want our base URL to be the ‘todos’ route. We will take care of this in a similar manner–by specifying a path:

  1 import Ember from 'ember';
  2 import config from './config/environment';
  4 var Router = Ember.Router.extend({
  5   location: config.locationType
  6 });
  8 Router.map(function() {
  9   //The only lines we change are the two below
 10   this.route('todo', {path: 'todo/:todo_id'});
 11   this.route('todos', {path: '/'});
 12   this.route('new');
 13 });
 15 export default Router;

Alright. Now, we’re getting somewhere! We’re still a ways away from a working app, though. At this point, we could stop and get the front-end looking acceptable and add a few link-to helpers so everything is interconnected. There would be nothing wrong with that, and it can actually improve our workflow by helping us eliminate cruft from our app. However, since it’s just us and this is a pretty simple example, let’s just skip that until later. Right now, all we have are routes and a model. Unless we want to roll our own adapter or use the default REST adapter, we will need to install an adapter. In our terminal, we need to run:

bower install --save-dev ember-localstorage-adapter

The localstorage adapter will allow our Ember app to make requests for data and save data to our web browser’s localstorage. The setup isn’t too bad. First, in ember-cli-build.js, we need to add an app.import call for the adapter:

  1 /* global require, module */
  2 var EmberApp = require('ember-cli/lib/broccoli/ember-app');
  4 module.exports = function(defaults) {
  5   var app = new EmberApp(defaults, {
  6     // Add options here
  7   });
  8   app.import('bower_components/ember-localstorage-adapter/localstorage_adapter.js');                                                                                                                                                      
 10   // Use `app.import` to add additional libraries to the generated
 11   // output files.
 12   //
 13   // If you need to use different assets in different
 14   // environments, specify an object as the first parameter. That
 15   // object's keys should be the environment name and the values
 16   // should be the asset to use in that environment.
 17   //
 18   // If the library that you are including contains AMD or ES6
 19   // modules that you would like to import into your application
 20   // please specify an object with the list of modules as keys
 21   // along with the exports of each module as its value.
 23   return app.toTree();
 24 };

Next, we have to generate an adapter using the ember generator, and then add a namespace to it.

In the terminal:

ember g adapter application

In app/adapters/application.js:

  1 import DS from 'ember-data';
  3 export default DS.RESTAdapter.extend({
  4         namespace: 'my-new-app'                                    
  5 });

Our adapter is now ready and willing to serve up data for us. We now need to make some templates for that data to go into, and a few ways for the user to interact with said data. Ember leverages the handlebars templating language, so you will see a lot of code in {{curly braces}}. You will also notice that the file extensions for our templates are *.hbs and not *.html. You may notice that syntax highlighting doesn’t work for .hbs files in your text editor of choice. Since we are using Vim as our text editor (ok, you don’t have to use Vim… but if you haven’t, consider this your final warning… It’s addictive), we will probably want to add a line to our .vimrc file to beautify our code a little. This is a workaround, not an ideal fix:

au BufReadPost *.hbs set syntax=html

In app/templates, we see a listing of our templates. Let’s make a few changes to our todos.hbs file. Nothing too fancy. We are all nerds here after all…

  1 <h1>Todos</h1>
  2 <div class="nav">{{#link-to "new"}}New Todo{{/link-to}}</div>                                                                                                                                                                             
  3 {{#each model as |todo|}}
  4 <label><input type="checkbox">{{#link-to "todo" todo}}{{todo.name}}{{/link-to}}</label><br>
  5 {{/each}}

The site should automagically reload after these changes are saved. ‘Hey, where’s mah data?’ Well, there is none… yet. We could add a model hook to our todos route with some dummy data, or add a test that throws in some dummy data just to make sure everything works, but I’m going to skip that for the sake of brevity. Before we move any further, we need to understand what’s going on here. The {{#each}} handlebars helper allows us to loop through the data passed to our route and do awesome stuff with said data. Pretty nifty, huh? The {{#link-to}} helper allows us to add links to our other routes. Since our ‘todo’ route is a dynamic route, we need to specify which todo the link goes to by passing in a todo. Ember will pull the ID from that todo and pass it through whenever we request that route. We need to knock out a few more things before things start working the way one would expect:

(1) add a model hook to our ‘todos’ route
(2) finish our new.hbs template
(3) add an action handler to our ‘new’ route
(4) edit the todo route.

Alright. Let’s start with app/routes/todos.js:

  1 import Ember from 'ember';
  3 export default Ember.Route.extend({
  4         model: function () {
  5                 return this.store.findAll('todo');
  6         }                                                                                                                                                                                                                                 
  7 });

That was pretty straightforward. All we need to do in the ‘todos’ model hook is find all the todo’s and return them. Now, let’s finish our new.hbs template. The full path from within our project directory is app/templates/new.hbs:

  1 <h1>New Todo</h1>                                                                                                                                                                                                                         
  3 <input type="text" placeholder="Todo Name">
  4 <hr>   
  5 <textarea placeholder="Todo Details"></textarea>
  6 <hr>
  7 <button {{action "save"}}>Create Todo</button>

In the button, we see an action handler called “save.”

If we go to our ‘new’ route within our app now, we can’t create a new todo. In our console, we would see an error message stating that nothing handled the action “save” after we click the button. Let’s fix that. We need to open up app/routes/new.js in a text editor.

  1 import Ember from 'ember';                                                                                                                                                                                                                
  3 export default Ember.Route.extend({
  4        actions: {                                                                                                  
  5                save: function () {
  6                        var newtodo = this.store.createRecord('todo',
  7                                {
  8                                        name: $("input").val(),
  9                                        details: $("textarea").val()
 10                                });
 11                        newtodo.save();
 12                        console.log("model saved");
 13                }
 14        }
 15 });

Now, the ‘save’ action creates a new todo for us. We could even make a slight improvement to this. Suppose we wanted the app to redirect us to the ‘todos’ route after a new todo was created. All we need for that is a single line added to the end of our action handler: this.transitionToRoute(‘todos’);

It’s not necessary by any means, but it could be a pretty nice UX feature if our users typically only add one todo at a time. Another addition that may make sense is adding an alert message or some other form of feedback to the user when the new todo is created. It could even be as simple as clearing the input and textarea fields, and focusing on the input field. In fact, that makes a lot of sense. Let’s go ahead and implement that:

  1 import Ember from 'ember';                                                                                         
  3 export default Ember.Route.extend({                                                                                
  4        actions: {                                                                                                  
  5                save: function () {                                                                                 
  6                        var newtodo = this.store.createRecord('todo',                                               
  7                                {                                                                                   
  8                                        name: $("input").val(),                                                     
  9                                        details: $("textarea").val()                                                
 10                                });                                                                                 
 11                        newtodo.save();                                                                             
 12                        $("textarea").val("");                                                                      
 13                        $("input").val("").focus();                                                                                                                                                                                        
 15                }                                                                                                   
 16        }                                                                                                           
 17 });  

That’s a lot better! Now, let’s go ahead and change our todo route and template so we can view each todo we created and read the details from them:


  1 <h1>{{model.name}}</h1>
  3 <h2>Details</h2>                                                                                                                                                                                                                          
  4 <p>{{model.details}}</p>


  1 import Ember from 'ember';
  3 export default Ember.Route.extend({                                                                                                                                                                                                       
  4         model: function (params) {
  5                 this.store.find('todo', params.todo_id);
  6         }
  7 });

Yippie! Once we create a few todos, we can view them! There’s our details, and the name of the todo. We are a lot closer now. Still, there’s the ‘UD’ in our CRUD app to knock out.

This is a good stopping point for now. Next time, we will go over a few possibilities for editing and deleting todos, and implement that functionality. If you would like to access the source code for this project, I will have it up on Github hopefully before the end of the week, along with the second half of this brief introduction to Ember.

How to do Drag and Drop in Ember.js… with Mixins

Implementing drag and drop in Ember has given me headaches, and after finally breaking down and searching hard on the internet, I found a Stack Overflow post that had a pretty good solution.

Unfortunately, I’m still not very good at Ember.  I don’t think it’s an IQ thing.. I think it’s more of an Ember is a different beast thing.  Ember does way more out of the box than I would ever expect, and I end up fighting it a lot.  And losing.  Anyway.

Here’s the mixin I created (i.e. mostly stole from a Stack Overflow answer) for the app I’m working on:

DnD = Ember.Namespace.create();

DnD.cancel = function(event) {
  return false;

DnD.dragStartHandler = function(event) {
  //record the id, alt tag of the element being dragged.
  event.dataTransfer.setData("text/plain", JSON.stringify({alt: this.element.alt, id: this.element.id}));

DnD.Draggable = Ember.Mixin.create({
  attributeBindings: 'draggable',
  draggable: 'true',
  dragStart: DnD.dragStartHandler

DnD.Droppable = Ember.Mixin.create({
  dragEnter: DnD.cancel,
  dragOver: DnD.cancel,
  dragLeave: DnD.cancel,
  drop: function(event) {
    var data = event.dataTransfer.getData("text/plain");
    console.log("data from droppable: " + JSON.parse(data));
    console.log("event.target: " + event.target.id);
    this.sendAction("dropped", event.target.id, JSON.parse(data));

Let’s walk through it piece by piece.

First, I create a namespace.  Here’s the documentation if you’re curious: http://emberjs.com/api/classes/Ember.Namespace.html.

It just makes a nice pretty little object I can dangle things off of.   In truth, I have no idea why you need to use it.  Talk to the Ember faeries.  I’m sure they can help you demystify Ember’s magic.

The cancel function takes care of the ondragenter, ondragover, and ondragleave handler for my use case.  The user doesn’t need any kind of indication that they are over a drop area and nothing happens as a result of being over a drop area.  If you want something to happen in that function, you will need to specify it in between the event.preventDefault() and return false lines, as both of those are required to cancel the default action for drag and drop.

DnD.Draggable is the name of the mixin I am using for anything I make draggable (in this case, a Magic: the Gathering card image built out using an Ember component).  Here, I set draggable to true using an attributeBinding.  dragStart is equivalent to ondragstart=”[some function](event)” on the draggable object in html code, only that would be a pain to write over and over again.  In my implementation of the handler, I’m sending both the alt attribute and the id of the target using dataTransfer by creating a JSON object and stringifying it.

DnD.Draggable = Ember.Mixin.create({
  attributeBindings: 'draggable',
  draggable: 'true',
  dragStart: DnD.dragStartHandler

The other mixin I create  is dubbed DnD.Droppable.  Objects I create with this mixin will be valid drop zones for components with the DnD.Draggable mixin.  The dragEnter event is equivalent to the ondragenter event in HTML 5.  Similar are true for dragOver and dragLeave.  And again, since I do not need to do anything when these events trigger aside from preventing the default action, my DnD.cancel function suffices for my use case.

The drop function is going to be the hardest piece to absorb if you are new to Ember, or to drag and drop.  The first thing I do is retrieve the data being transferred from the object I am dropping using dataTransfer.getData.  Once that’s done, I send the action on using sendAction. The console.log calls were there simply to test the code.

drop: function(event) {
  var data = event.dataTransfer.getData("text/plain");
  console.log("data from droppable: " + JSON.parse(data));
  console.log("event.target: " + event.target.id);
  this.sendAction("dropped", event.target.id, JSON.parse(data));

There are a few reasons for doing this.  The first reason is you aren’t supposed to handle actions on your components in Ember.  It makes Ember angry… and Ember doesn’t like being angry…
Your components are supposed to handle the low-level stuff (e.g. “Hey! a click happened” or “Hey! the user submitted a form” or “Hey! your house is on fire”), and then pass the data to the controllers for processing. Keeps everything nice and neat.

The second reason I do this is so that I can specify what I want to do when a card is dropped on a particular zone.  This is super-handy in my use case, since I will need to do different things depending on where the card is dropped.  Generally speaking, it’s straightforward, but there are a few exceptions that I would like to do something a bit different with.  You may be wondering where my action is going and what it’s doing.  First, we will have to look at the controller using a mixin, and its handlebars implementation.

This is my game zone component and card image component. Notice the DnD.Droppable after Ember.Component.extend below? All the mixin attributes and other stuff are added to this component. Now, any instances of GameZoneComponent I create are a valid dropzone for my CardImgComponent, which have the DnD.Draggable mixin added in the same fashion:

Areas.GameZoneComponent= Ember.Component.extend(DnD.Droppable, {
  classNames: ['zone', 'display-zone'],
  classNameBindings: ['display-zone', 'player', 'location', 'id'],
  displayZone: true,
  player: "p1",
  location: "somelocation"
Areas.CardImgComponent = Ember.Component.extend(DnD.Draggable, {
  classNames: ['card'],
  classNameBindings: ['player', 'location'],
  player: "p1",
  tagName: 'img',
  attributeBindings: ['src', 'alt']

Now, since I am sending an action via the “dropped” attribute on the GameZoneComponent, each time I use the component, I will need to specify an action, as in this one:

{{game-zone cards=lib1 id="lib1" class="zone display-zone p1 library hidden" dropped="moveCard"}}

moveCard is the name of an action on my GameController and it looks like this:

moveCard: function(target, card) {
  var mycard = this.model.filterBy('domid', card.id);
  var domcard = document.getElementById(card.id);
  if(target.indexOf("card") == -1) {
    mycard.objectAt(0).set('zone', target);

This is really where all the magic happens.  I update the data model based on the drop, and then move the object to where it was dropped.  There is probably a more semantically correct way to update the DOM when the underlying data model changes, and I’m guessing it involves observers.  This works, so I’m keeping it as-is for now… unless one of you guys want to share a solution to this problem?

Comments and questions are always welcome.  Hope this helped.  Oh, and before I get flamed for not giving credit where credit is due, here is the Stack Overflow answer that was mostly responsible for this: http://stackoverflow.com/questions/10739322/dragdrop-with-ember-js and was written by pangratz based on a post by Remy Sharp here.

I’ll leave you with another little tidbit of code. These are my game zone component and card image component templates. Ember magic ties them to the code I showed you earlier. GameZoneComponent will look for a handlebars template with the name: “components/game-zone,” and similar is true for CardImgComponent: “components/card-img.”

<!-- 	4. Card-img Component  -->
<script type="text/x-handlebars" data-template-name="components/card-img">
    <img {{action "tap" on='click'}}>

<!--	5. Game-zone Component  -->
<script type="text/x-handlebars" data-template-name="components/game-zone">
	{{#each card in cards}}
		{{card-img card=card draggable="true" class="card" src=card.img elementId=card.domid alt=card.name}}

I’d be willing to make a JSfiddle so you can dig through the code yourself and see it in action. Just let me know in the comments and I’ll toss a link in there.

Re-evaluating your Internet Marketing Strategy in 2015

Much like the world we live in, the Internet is diverse.  It is a place for rich and poor, homemakers and billionaire CEO’s, young and old, citizens and expatriates.  It meets a wide range of needs.  Communication, national security, entertainment, business, and the sharing of ideas are all essential functions performed on the Internet every day.  Without the Internet, we would not know what to do with ourselves as a society.

Businesses and stores run out of homes spring up every day on the Internet, and many of them see success.  Many retailers offer the ability to order things online and have them shipped, rather than having to go to the store to get them.  Many sit-down and high-end restaurants now offer takeout service.  However, the brick-and-mortar model of business is not dead, even in the fast-paced, Buy It Now world we live in.  Many of us (including myself) still want to ‘go for a cup of coffee’ or ‘go do X.’  That isn’t going to die any time soon (and it may never die…).  However, brick-and-mortar establishments still have to compete on a global scale if they want to truly succeed.  Having an online presence is essential to every business’ marketing strategy.

Clearly this means more than doing some keyword research, building a pretty website, and putting it online.  Your customer base will need to dictate how you build your website.  What does Google Analytics have to say about the average person visiting your site?  Are they on a mobile device?  All of these are important questions that demand an answer.

If you see a lot of customers accessing your site from a mobile device, it would behoove you to put in the extra work required to make the site appealing and accessible to mobile users, particularly when considering what some internet usage research reports:

Nearly two-thirds (63%) of cell phone owners now use their phone to go online, according to a new survey by the Pew Research Center’s Internet & American Life Project.  We call them “cell internet users” and define them as anyone who uses their cell phone to access the internet or use email. Because 91% of all Americans now own a cell phone, this means that 57% of all American adults are cell internet users. The proportion of cell owners who use their phone to go online has doubled since 2009.

The research was conducted in 2013 by the Pew Research Center, and can be found here.

That leads into another important question: “What should I have on my website?”  Ultimately, the Internet provides information.  Whether it’s the location and hours of the coffee shop, or the newest funny cat videos complete with comments, people crave information.  Therefore, give it to them.  If you are a brick-and-mortar store, your phone number, address, and hours should be in the description that you submit to Google.  On top of that, the information should be easily accessible on your website, particularly for mobile devices, and here’s why:

We also found that three of four mobile searches trigger additional actions. These range from open-ended actions like additional research (36%) or a website visit (25%), to more concrete conversions like a store visit (17%), a purchase (17%), or a phone call (7%). On average, each mobile search triggers nearly two actions, so in order to understand the full value of mobile, marketers must evaluate the different ways that their customers convert, both online and offline, and measure accordingly.

Mobile searches have an immediate effect.  People looking for you via their phone are frequently also looking to do other things:  buy from you, call, go there, or even research your competition.  Having business information in a form that is legible and accessible to mobile consumers is critical.  You can find out more about the actions taken  by mobile consumers in the article, “Mobile’s immediacy effect: Half of mobile search conversions happen in one hour,” and the source of the information used in the article was: “Google/Nielsen Life360 Mobile Search Moments Q4 2012.”

So what now?  If you are a business owner, you have a vested interest in your company’s success.  With more and more conversions happening as a result of the Internet, having a solid website is a fundamental part of any effective marketing plan.

Contact a digital marketing agency.  They can rework an existing website to look good and be accessible to mobile consumers, or design a new one from scratch.  If you would like more guidance, simply want to talk, or would like to hire me, you can contact me directly from here.




Why I hate MVC’s (and how Ember.js is different)

My experiences with MVC’s (that’s short for model-view-controller, for those who don’t know) have been pretty negative overall.  I started with Ruby on Rails a good while ago.  I got into it and figured I may just make a career out of using it.  Then I started having problems.  Windows has a passive-aggressive hatred for all things Linux, and I experienced this.  There were incompatibilities.  There were things that would have worked fine if I had some clue as to what I was doing (which I didn’t, admittedly), there was the addition of several new skills I had to learn that were more exciting in principle than they were in practice.  Those being command-line generators and the concept of TDD (test-driven development).

For those of you who use it every single day, you probably have no qualms about using generators or TDD.  That’s good for you and I’m very happy that you enjoy those things… but for me, I had built up Ruby on Rails to the point where I expected it to auto-fix bugs and work right out of the box.  I mean, it can generate all this code for me using a single command… why can’t it work without me doing any kind of modification to the controllers, views, and models?

Here’s (in part) what I like about Ember.  You don’t have that ‘auto-generating’ nonsense going on.  There’s no room for me to assume that Ember is going to do everything for me.  It does, however, handle the boilerplate code for me, and allows me to extend the base controllers, models, and views pretty easily.

The javascript files have to be added by hand.  That’s another thing.  The ‘magic’ of having your models automatically loaded because they were all in a particular folder left me feeling like I had less control of the development process than I really did.  Faulty logic, perhaps, but it extends deeper than that.  Again, it became a matter of having unrealistic expectations of the framework.

Comparing Ember to Rails or .NET is like comparing a VW Beetle to a Ford GT.  Both of them are cars, and they can get you where you need to go.  Ember is a client-side MVC.  It does its work in the browser (guess that should go without saying since it’s ‘Ember.js’…).  That will reduce server load, but it may mean your app runs like molasses.  It also means you will be using JSON to model objects, which was a tad clunky for me, as I am accustomed to seeing C, C++, Python, and Ruby.  The nice thing, though, is it doesn’t give a flying something-or-other about what operating system I’m running it on.  Ruby on Rails and .NET is the Ford GT in the metaphor above.  It’s widely used, well-supported, well-documented, has an active and passionate user-base, and people make big money developing in it.  At the end of the day, it’s just more car than I may ever need.

TL; DR:  The MTG webapp I’ve been working on is up and running.  It’s ugly, there are features that don’t work…. and so on.  The code base is to the point where it is getting unmanageable, and I need some structure so it’s more organized, easily maintained, and extensible.  An MVC framework gives me that, and Ember seems like the perfect fit.

So far, learning Ember has been a joy and pleasure…. I hope it stays that way, as I have yet to dive into TDD with it yet.  Thoughts, comments and suggestions are always welcome.

My MTG webapp is almost ready!

I’ve been working on this project for a few weeks now… I’m currently unemployed, so I’ve had plenty of free time.  Probably not the best use of my time, but it has been a pretty good learning experience.

It’s hacked together, it’s not pretty, and the analysis tools are pretty basic, but I’m still pretty excited about it.  I was looking to create a different kind of deckbuilding tool that took into account the result of playtesting.

There are hiccups (like accidental javascript closures that cause some unintended data ‘memory’ that can mess things up), layout issues, and features are not implemented, but have buttons in the menu for them.

Once polished up a bit more, it will be posted on another subdomain of this site (mtgwebapp.wrightonlineworks.com or something similar).

I’d love some feedback and suggestions once it’s up.

The State of Standard–Dec. 2014

The Standard metagame continues to fluctuate.  Decks that were good have continued to evolve–and still show up, and new ones continue to crop up.  Reanimator has come on  strong over the past few tournaments.  Whip of Erebos (no real surprise here) has become an important tool in this strategy.

Jeskai continues to stick around, but what the ‘best Jeskai Ascendancy deck’ is remains to be seen.  Right now, the answer seems to be avoiding going all in on the Ascendancy combo plan, and operate like a tempo deck for the most part.  Since it operates as a tempo deck, Hordeling Outburst has found yet another home.

Many of the successful control decks appear to be UB in construction.  Going 1-for-1, refilling your hand with Jace’s Ingenuity and the like, resetting the board or removing hard-to-deal-with threats using Perilous Vault, and finishing games with Pearl Lake Ancient.  There are plenty of exceptions to the rule, however.

Standard has become quite an open format.  Play any deck type you wish to, and you will have a reasonable chance against anything.  It’s refreshing to see such changes.  Here’s hoping things continue in that direction.

How to play Steam Augury

For starters, let’s break down the card.  Steam Augury is a 4 mana instant that costs 2UR.  Its CMC is the same as one of the most skill intensive cards ever printed: Fact or Fiction, and its similarities to the Extended staple don’t end there.  It digs 5 cards deep, the cards get separated into two piles, and one pile gets chosen over the other.

The primary distinction between this and Fact or Fiction is a pretty big deal, however.  The caster is the one who makes the piles and the other player is the one who chooses the pile to be given to the caster.  This makes getting what you want off a Steam Augury a little tougher than if it were a reprint of Fact or Fiction.

However, the one advantage Steam Augury has is made apparent when multiple cards of the same type are revealed in the five.  If digging for lands and there are 2 lands revealed, the opponent will not be able to force you to choose between lands or spells.  The same is true for removal spells and threats.

In splitting piles, players will typically want to stack the piles such that one of the important cards are in each of the piles.  If there is a card that is overwhelmingly important or just wins the game on the spot in the current boardstate, that card will get put by itself with the other four cards in the other pile.  Pretty self-explanatory.

The card is obviously better when you are ahead, when you are not digging for anything specific, and your opponent doesn’t know what you have in hand.

With the return of the Delve mechanic, Steam Augury provides added value.  Cards like Treasure Cruise, Empty The Pits, and Dig Through Time come online faster, and 4-1 pile splits become a slightly more reasonable option than they would be otherwise.



Happy New Year, everyone!  Hope it’s been a good one so far.  If it hasn’t, you still have 364 days left after today to make it a good one.

Though not in my immediate future, I plan on migrating my blog to a WordPress-based site (details forthcoming).  I have also thought about plying my writing skills on PucaTrade, as my primary goal in Magic: the Gathering is for it to be a financially self-sustaining hobby.

My new site will also provide a place to show off my skills as a front-end web developer and provide a point of contact between me and potential employers.  Something’s gotta give… getting sick of going from temp job to temp job.  Maybe I’ll start streaming full-time?

Yeah right…  I have a growing distaste for MTGO, and I doubt I’ll grow out of it soon… Maybe they’ll fix it before Vintage Masters comes out, and I can pick up some Power 9 and other sweet goodies while face-planting some drafts.

What’s Vintage Masters you ask?  It’s an online-only set on MTGO coming out in June that will cost $6.99 per pack, and will be similar to Modern Masters, except with Vintage staples, including the Power 9 (printed at Mythic obviously).

Anyway, I’m off… Nursing a throbbing headache this afternoon (just kidding!).

Get every new post delivered to your inbox.
Thanks for your interest.
Powered By WPFruits.com