Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

backbone version of transaction

  • Loading branch information...
commit 1773f5ea1477da6fb7db62b81f79cd2949b21864 1 parent 43f02b6
@dawicorti authored
Showing with 255 additions and 1 deletion.
  1. +1 −1  Makefile
  2. +132 −0 lib/model/transaction.js
  3. +122 −0 test/transaction.test.js
View
2  Makefile
@@ -1,4 +1,4 @@
test:
- @./node_modules/.bin/mocha
+ @./node_modules/.bin/mocha -b -R spec
.PHONY: test
View
132 lib/model/transaction.js
@@ -0,0 +1,132 @@
+/*
+ * Module dependencies
+ */
+
+var _ = require('underscore');
+var Backbone = require('backbone');
+var StoneGroup = require('./stonegroup');
+
+
+/*
+ * Private StoneGroupArray collection
+ */
+
+var StoneGroupArray = Backbone.Collection.extend({model: StoneGroup});
+
+
+/*
+ * Transaction model
+ *
+ * @key gsize
+ * @key {Collection:StoneGroup} groups
+ * @key {Collection:StoneGroup} attachedTo
+ */
+
+var Transaction = module.exports = Backbone.Model.extend();
+
+
+/* Init the attachedTo Group Array used to concat groups */
+
+Transaction.prototype.initialize = function (opts) {
+ this.set('attachedTo', new StoneGroupArray());
+};
+
+/* Main call: returns the new Group Array, after stone put (or not) */
+
+Transaction.prototype.putStone = function (stone) {
+ if (!(stone instanceof Stone)) stone = new Stone(stone);
+
+ this.set('stone', stone);
+
+ if (this.exists(stone)) return false;
+ this.attachToAll();
+ this.mergeGroups();
+ this.removeDeadGroups();
+ return this.checkLiberties();
+};
+
+/* Returns if stone position already taken by other stone */
+
+Transaction.prototype.exists = function (stone) {
+ var exists = false;
+
+ this.get('groups').every(function (group) {
+ if (group.containsPos(stone)) {
+ exists = true;
+ return false;
+ }
+
+ return true;
+ });
+
+ return exists;
+};
+
+/* Attach the stone to every possible existing groups */
+
+Transaction.prototype.attachToAll = function (next) {
+ this.get('groups').each(function (group) {
+ if (group.attach(this.get('stone'))) this.get('attachedTo').add(group);
+ }, this);
+};
+
+/* A new group is created if the stone cannot be added to a existing one */
+
+Transaction.prototype.newGroup = function () {
+ var uniq = new StoneGroup([this.get('stone')]);
+ this.get('groups').add(uniq);
+ this.get('attachedTo').add(uniq);
+};
+
+/* Merge groups when the stone if the stone is attached to both */
+
+Transaction.prototype.mergeGroups = function () {
+ if (this.get('attachedTo').size() === 1) return;
+ if (this.get('attachedTo').size() === 0) return this.newGroup();
+
+ var eater = this.get('attachedTo').first();
+ var food = this.get('attachedTo').rest();
+
+ _.each(food, function (group) {
+ eater.eat(group);
+ });
+
+ this.set('groups', this.get('groups').filter(function (group) {
+ return group.size() > 0;
+ }));
+
+ this.get('attachedTo').reset([eater]);
+};
+
+/* Return true if the stone is attached to a group with at least one liberty */
+
+Transaction.prototype.checkLiberties = function () {
+ var stones = [];
+
+ _.each(this.groups, function (group) {
+ stones = _.union(stones, group.toStoneArray());
+ });
+
+ return _.size(_.first(this.attachedTo).liberties(stones, this.gsize)) > 0;
+};
+
+/* Remove all groups without a liberty */
+
+Transaction.prototype.removeDeadGroups = function () {
+ var stones = [];
+
+ _.each(this.groups, function (group) {
+ stones = _.union(stones, group.toStoneArray());
+ });
+
+ var groups = [];
+ _.each(this.groups, function (group, index) {
+ if (group.contains(this.stone) || _.size(group.liberties(stones, this.gsize)) > 0) {
+ groups.push(group);
+ } else {
+ this.deadGroups.push(group);
+ }
+ }, this);
+
+ this.groups = groups;
+};
View
122 test/transaction.test.js
@@ -0,0 +1,122 @@
+var assert = require('assert');
+var _ = require('underscore');
+var Backbone = require('backbone');
+var Transaction = require('../lib/model/transaction');
+var Stone = require('../lib/model/stone');
+var StoneGroup = require('../lib/model/stonegroup');
+
+var StoneGroupArray = Backbone.Collection.extend({model: StoneGroup});
+
+describe('Transaction', function () {
+
+ describe('attachToAll()', function () {
+
+ it('should attach to every groups', function () {
+ var transaction = new Transaction({groups: new StoneGroupArray([
+ [
+ {row: 8, col: 8, color: 'black'},
+ {row: 8, col: 9, color: 'black'},
+ {row: 8, col: 10, color: 'black'},
+ ],
+ [
+ {row: 5, col: 5, color: 'black'},
+ {row: 6, col: 5, color: 'black'},
+ {row: 7, col: 5, color: 'black'},
+ ]
+ ]), size: 19});
+
+ transaction.get('groups').at(0).firstOne = true;
+ transaction.set('stone', new Stone({row: 8, col: 11, color: 'black'}));
+ transaction.attachToAll();
+
+ assert.equal(1, transaction.get('attachedTo').size());
+ assert.equal(true, transaction.get('attachedTo').at(0).firstOne);
+ });
+
+ it('should attach to every groups', function () {
+ var transaction = new Transaction({groups: new StoneGroupArray([
+ [
+ {row: 8, col: 9, color: 'black'},
+ {row: 8, col: 10, color: 'black'},
+ ],
+ [
+ {row: 9, col: 8, color: 'black'},
+ {row: 10, col: 8, color: 'black'},
+ {row: 11, col: 8, color: 'black'},
+ ],
+ [
+ {row: 8, col: 7, color: 'black'},
+ {row: 8, col: 6, color: 'black'},
+ {row: 8, col: 5, color: 'black'},
+ ],
+ ]), size: 19});
+
+ transaction.set('stone', new Stone({row: 8, col: 8, color: 'black'}));
+ transaction.attachToAll();
+
+ assert.equal(3, transaction.get('attachedTo').size());
+ });
+
+ });
+
+ describe('mergeGroups()', function () {
+
+ it('should reduce to one big group', function () {
+
+ var transaction = new Transaction({groups: new StoneGroupArray([
+ [
+ {row: 8, col: 9, color: 'black'},
+ {row: 8, col: 10, color: 'black'},
+ ],
+ [
+ {row: 9, col: 8, color: 'black'},
+ {row: 10, col: 8, color: 'black'},
+ {row: 11, col: 8, color: 'black'},
+ ],
+ [
+ {row: 8, col: 7, color: 'black'},
+ {row: 8, col: 6, color: 'black'},
+ {row: 8, col: 5, color: 'black'},
+ ],
+ ]), size: 19});
+
+ transaction.set('stone', new Stone({row: 8, col: 8, color: 'black'}));
+ transaction.attachToAll();
+ transaction.mergeGroups();
+
+ assert.equal(1, transaction.get('attachedTo').size());
+ assert.equal(9, transaction.get('attachedTo').at(0).size());
+ });
+
+ it('should generate a group if no existing can attach', function () {
+
+ var transaction = new Transaction({groups: new StoneGroupArray([
+ [
+ {row: 8, col: 9, color: 'black'},
+ {row: 8, col: 10, color: 'black'},
+ ],
+ [
+ {row: 9, col: 8, color: 'black'},
+ {row: 10, col: 8, color: 'black'},
+ {row: 11, col: 8, color: 'black'},
+ ],
+ [
+ {row: 8, col: 7, color: 'black'},
+ {row: 8, col: 6, color: 'black'},
+ {row: 8, col: 5, color: 'black'},
+ ],
+ ]), size: 19});
+
+ transaction.set('stone', new Stone({row: 1, col: 1, color: 'black'}));
+ transaction.attachToAll();
+ transaction.mergeGroups();
+
+ assert.equal(4, transaction.get('groups').size());
+ assert.equal(1, transaction.get('attachedTo').size());
+ assert.equal(1, transaction.get('attachedTo').at(0).size());
+ });
+
+ });
+
+
+});
Please sign in to comment.
Something went wrong with that request. Please try again.