From ca2026edfed80002608b9f1d2aecca483fe687ff Mon Sep 17 00:00:00 2001 From: dsc Date: Sun, 2 Jan 2011 01:28:34 -0800 Subject: [PATCH] Rock on. Mixins work great. --- src/Y/modules/y.scaffold.cjs | 2 +- src/Y/type.cjs | 2 +- src/Y/types/function.cjs | 33 ++++++++++--- src/Y/types/string.cjs | 53 ++++++++++++++++++++++ src/evt.cjs | 90 +++++++++++++++++++++++------------- src/tanks/effects/buff.cjs | 14 +++++- src/tanks/index.js | 1 + src/tanks/map/level.cjs | 24 ---------- src/tanks/mixins/configurable.cjs | 13 +++++ src/tanks/mixins/index.cjs | 4 ++ src/tanks/mixins/informative.cjs | 19 ++++++++ src/tanks/mixins/meronomic.cjs | 13 +++++ src/tanks/mixins/speciated.cjs | 64 ++++++++++++++++++++++++++ www/deps.html | 3 + 14 files changed, 265 insertions(+), 70 deletions(-) create mode 100644 src/tanks/mixins/index.cjs diff --git a/src/Y/modules/y.scaffold.cjs b/src/Y/modules/y.scaffold.cjs index 09973d7..3f85341 100644 --- a/src/Y/modules/y.scaffold.cjs +++ b/src/Y/modules/y.scaffold.cjs @@ -5,7 +5,7 @@ var Y = require('Y').Y , upperPat = /^[A-Z]+$/ -, symbolPat = /^[^a-zA-Z]+$/ +, symbolPat = /^[^a-zA-Z0-9]+$/ , camelToSpaces = exports['camelToSpaces'] = diff --git a/src/Y/type.cjs b/src/Y/type.cjs index bed850b..a075a8f 100644 --- a/src/Y/type.cjs +++ b/src/Y/type.cjs @@ -42,7 +42,7 @@ function typeName(o){ if (o === undefined || o === null) return String(o); var T = type(o); - return T.className || (T !== Function ? T.name : basicTypeName(o)); + return T.className || (T !== Function ? T.name || "Function" : basicTypeName(o)); } var arrayLike = isArray.types = []; diff --git a/src/Y/types/function.cjs b/src/Y/types/function.cjs index 63ff66c..22143a7 100644 --- a/src/Y/types/function.cjs +++ b/src/Y/types/function.cjs @@ -47,6 +47,27 @@ function unwrap(fn){ return ( fn && isFunction(fn) ) ? unwrap(fn[WRAPS]) || fn : fn; } +/** + * @return {Function} A function which flips the first and second arguments + * before calling the original. + */ +function flip(fn){ + fn = _Function.toFunction(fn); + + var f = fn.__flipped__; + if (f) return f; + + f = fn.__flipped__ = + function flipped(){ + var args = arguments + , hd = args[0]; + args[0] = args[1]; + args[1] = hd; + return fn.apply(this, args); + }; + return wraps(f, fn); +} + function curry(fn){ if (fn.__curried__) return fn.apply(this, slice.call(arguments,1)); @@ -72,7 +93,7 @@ function curry(fn){ function methodize(fn) { - fn = fn.toFunction(); + fn = _Function.toFunction(fn); var g = fn.__genericized__ , m = fn.__methodized__ ; if (m) return m; @@ -86,7 +107,7 @@ function methodize(fn) { } function genericize(fn) { - fn = fn.toFunction(); + fn = _Function.toFunction(fn); var g = fn.__genericized__ , m = fn.__methodized__ ; if (g) return g; @@ -245,11 +266,7 @@ function limit(fn, n){ } -/** - * Filter the arguments passed to the wrapper function - */ -// YF.prototype.mask = mask; -// function mask(){ +// function guard(test, otherwise){ // // } @@ -270,7 +287,7 @@ function getName( fn ){ -[ wraps, unwrap, getName, +[ wraps, unwrap, getName, flip, curry, compose, chain, bind, partial, methodize, genericize, memoize, aritize, limit ].map(function(fn){ diff --git a/src/Y/types/string.cjs b/src/Y/types/string.cjs index 5a82ff5..4680f40 100644 --- a/src/Y/types/string.cjs +++ b/src/Y/types/string.cjs @@ -4,6 +4,9 @@ var YCollection = require('Y/types/collection').YCollection , core = require('Y/core') , del = require('Y/delegate') , slice = core.slice + +, upperPat = /^[A-Z]+$/ +, symbolPat = /^[^a-zA-Z0-9_\$]+$/ ; exports['YString'] = @@ -103,6 +106,56 @@ YCollection.subclass('YString', function(YString){ return s.lastIndexOf(val) === (s.length - val.length); }, + 'capitalize' : function capitalize(){ + var s = this._o+''; + return s.charAt(0).toUpperCase()+s.slice(1); + }, + + /** + * Converts a camelCase string into a snake_case string. + * @param {Boolean} nameSafe If true, keeps only characters valid in function names. + * @return {String} The snake_case string. + * + * Y('petGrumpyCamels').camelToSnake() === 'pet_grumpy_camels' + */ + 'camelToSnake' : function camelToSnake(nameUnsafe){ + return this.reduce( + function(out, ch, i){ + if ( !nameUnsafe && symbolPat.test(ch) ) + return out; + if ( upperPat.test(ch) ) + out += '_'; + return out + ch.toLowerCase(); + }, ''); + }, + + /** + * Converts a snake_case string into a camelCase string. (All non-alphanumeric + * characters are treated as separators for the purposes of camelizing.) + * @param {Boolean} [nameUnsafe=false] Does not strip characters invalid in function names. + * (Underscores are always removed.) + * @return {String} The camelCase string. + * + * Y('feed_happy_snakes').snakeToCamel() === 'feedHappySnakes' + */ + 'snakeToCamel' : function snakeToCamel(nameUnsafe){ + return this.reduce( + function(state, ch, i){ + var isSymbol = symbolPat.test(ch); + if ( ch === '_' ) + isSymbol = true; + else if (!isSymbol || nameUnsafe) + state.out += (state.prev ? ch.toUpperCase() : ch); + state.prev = isSymbol; + return state; + }, + { + out : '', + prev : false + + }).out; + }, + 'compare' : function compare(n){ var m = this._o; return (m > n ? 1 : diff --git a/src/evt.cjs b/src/evt.cjs index 100a51a..f5e84ba 100644 --- a/src/evt.cjs +++ b/src/evt.cjs @@ -40,9 +40,14 @@ var Y = require('Y').Y , objToString = _Object[P].toString , classToString = function toString(){ return this.className+"()"; } -, classMagic = [ '__static__', '__mixins__', '__emitter__', '__bases__', '__initialise__' ] -, mixinSkip = [ '__mixin_skip__', 'onMixin', 'onInit', 'init' ].concat(classMagic) -, classStatics = [ 'instantiate', 'fabricate', 'subclass' ] + +, classStatics = [ 'instantiate', 'fabricate', 'subclass' ] +, classMagic = [ + '__bases__', '__initialise__', '__class__', 'constructor', 'className', + '__emitter__', '__static__', '__mixins__' + ] //.concat(classStatics) +, mixinSkip = [ '__mixin_skip__', '__mixin_skip', 'onMixin', 'onInit', 'init' + ].concat(classMagic) , @@ -189,10 +194,10 @@ function Class(className, Parent, members){ eval(constructor); // Copy Class statics - for (var i=0, L=classStatics.length; i').appendTo('body'); - // E = game.addThing(new Thing(2), 0,0); - // var i = 0; - // function testBulletSpeed(){ - // B = P.shoot(0,475); - // var start = new Date().getTime() - // , startClock = NOW - // , startX = B.loc.x; - // B.bounces = 1; - // console.log(i+' B.movePerMs='+B.movePerMs+', move='+B.stats.move); - // - // B.addEventListener('destroy', function(evt){ - // var elapsed = (new Date().getTime() - start)/1000 - // , clock = (NOW - startClock)/1000 - // , distance = startX - B.loc.x ; - // DATA.text(DATA.text()+elapsed.toFixed(3)+'\t'+clock.toFixed(3)+'\t'+distance.toFixed(3)+'\t'+(distance/elapsed).toFixed(3)+'\n'); - // if (++i < 20) testBulletSpeed(); - // }); - // } - // game.addEventListener('start', function(evt){ - // DATA.text('elapsed\tclock\tpx\tpx/s\n'); - // testBulletSpeed(); - // }); }, addWall : function addWall(x,y, w,h, isBoundary){ diff --git a/src/tanks/mixins/configurable.cjs b/src/tanks/mixins/configurable.cjs index e69de29..2d0f617 100644 --- a/src/tanks/mixins/configurable.cjs +++ b/src/tanks/mixins/configurable.cjs @@ -0,0 +1,13 @@ +var Y = require('Y').Y +, Mixin = require('evt').Mixin +, + +Configurable = +exports['Configurable'] = +Mixin.subclass('Configurable', { + + onInit : function initConfigurable(evt){ + + } + +}); diff --git a/src/tanks/mixins/index.cjs b/src/tanks/mixins/index.cjs new file mode 100644 index 0000000..da70058 --- /dev/null +++ b/src/tanks/mixins/index.cjs @@ -0,0 +1,4 @@ +require('Y').Y.extend(exports, { + 'Speciated' : require('tanks/mixins/speciated').Speciated, + 'Meronomic' : require('tanks/mixins/meronomic').Meronomic +}); diff --git a/src/tanks/mixins/informative.cjs b/src/tanks/mixins/informative.cjs index e69de29..d3e2268 100644 --- a/src/tanks/mixins/informative.cjs +++ b/src/tanks/mixins/informative.cjs @@ -0,0 +1,19 @@ +var Y = require('Y').Y +, Mixin = require('evt').Mixin +, + +Informative = +exports['Informative'] = +Mixin.subclass('Informative', { + + + onInit : function initInformative(evt){ + var instance = evt.data.instance; + + }, + + toString : function(){ + return this.className+'()'; + } + +}); diff --git a/src/tanks/mixins/meronomic.cjs b/src/tanks/mixins/meronomic.cjs index e69de29..0f21048 100644 --- a/src/tanks/mixins/meronomic.cjs +++ b/src/tanks/mixins/meronomic.cjs @@ -0,0 +1,13 @@ +var Y = require('Y').Y +, Mixin = require('evt').Mixin +, + +Meronomic = +exports['Meronomic'] = +Mixin.subclass('Meronomic', { + + onInit : function initMeronomic(evt){ + + } + +}); diff --git a/src/tanks/mixins/speciated.cjs b/src/tanks/mixins/speciated.cjs index e69de29..bb183cd 100644 --- a/src/tanks/mixins/speciated.cjs +++ b/src/tanks/mixins/speciated.cjs @@ -0,0 +1,64 @@ +var Y = require('Y').Y +, Mixin = require('evt').Mixin +, + +Speciated = +exports['Speciated'] = +Mixin.subclass('Speciated', { + + lol : 1, + + __static__ : { + __known__ : null, + + speciate : function speciate(id, props){ + props = props || {}; + props.__species__ = id; + delete props.id; + + var cls = this + , speciesName = Y(Y(id+'').capitalize()).snakeToCamel() + , Species = cls.__known__[id] = cls.subclass(speciesName, props) + ; + Species.__species_props__ = props; + return Species; + }, + + lookupSpecies : function lookupSpecies(id){ + var cls = this; + return cls.__known__[id]; + }, + + createSpeciesInstance : function createSpeciesInstance(id){ + var args = Y(arguments,1) + , cls = this + , Species = cls.__known__[id]; + return Species.instantiate.apply(Species, args); + } + + }, + + onMixin : function mixSpeciated(evt){ + var cls = evt.data.cls; + cls.__known__ = {}; + console.log('mixSpeciated()', 'cls:', cls, 'mxn:', evt.data.mixin); + }, + + // onInit : function initSpeciated(evt){ + // var d = evt.data + // , instance = d.instance + // , Species = d.cls + // , props = Species.__species_props__ + // ; + // // for (var k in props) { + // // var v = props[k]; + // // if ( Y.isArray(v) || typeof v === "object" ) + // // instance[k] = Y(v).clone(); + // // } + // }, + + toString : function(){ + return this.className+'(name='+this.name+', id='+this.id+', tags=['+this.tags+'])'; + } + +}); diff --git a/www/deps.html b/www/deps.html index a8d24b2..6ebf6f0 100644 --- a/www/deps.html +++ b/www/deps.html @@ -57,7 +57,10 @@ + + + -- 1.7.0.4