123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- /*
- GROUPS
- Groups are collections of an arbitrary number of Cubelets.
- They have no concept of Cubelet location or orientation
- and therefore are not capable of rotation around any axis.
- */
- export function Group(){
- this.cubelets = []
- this.add( Array.prototype.slice.call( arguments ))
- }
- globalThis.setupTasks = globalThis.setupTasks || []
- globalThis.setupTasks.push( function(){
- globalThis.augment( Group, {
- inspect: function( face ){
- this.cubelets.forEach( function( cubelet ){
- cubelet.inspect( face )
- })
- return this
- },
- add: function(){
- var
- cubeletsToAdd = Array.prototype.slice.call( arguments ),
- that = this
- cubeletsToAdd.forEach( function( cubelet ){
- if( cubelet instanceof Group ) cubelet = cubelet.cubelets
- if( cubelet instanceof Array ) that.add.apply( that, cubelet )
- else that.cubelets.push( cubelet )
- })
- return this
- },
- remove: function( cubeletToRemove ){
- if( cubeletToRemove instanceof Group ) cubeletToRemove = cubeletToRemove.cubelets
- if( cubeletToRemove instanceof Array ){
- var that = this
- cubeletToRemove.forEach( function( c ){
- that.remove( c )
- })
- }
- for( var i = this.cubelets.length - 1; i >= 0; i -- ){
- if( this.cubelets[ i ] === cubeletToRemove )
- this.cubelets.splice( i, 1 )
- }
- return this
- },
- // Boolean checker.
- // Are any Cubelets in this group tweening?
- // Engaged on the Z axis? Etc.
- isFlagged: function( property ){
- var count = 0
- this.cubelets.forEach( function( cubelet ){
- count += cubelet[ property ] ? 1 : 0
- })
- return count
- },
- isTweening: function(){
- return this.isFlagged( 'isTweening' )
- },
- isEngagedX: function(){
- return this.isFlagged( 'isEngagedX' )
- },
- isEngagedY: function(){
- return this.isFlagged( 'isEngagedY' )
- },
- isEngagedZ: function(){
- return this.isFlagged( 'isEngagedZ' )
- },
- isEngaged: function(){
- return this.isEngagedX() + this.isEngagedY() + this.isEngagedZ()
- },
- // Search functions.
- // What Cubelets in this Group have a particular color?
- // How about all of these three colors?
- // And index? address? Solver uses these a lot.
- hasProperty: function( property, value ){
- var
- results = new Group()
- this.cubelets.forEach( function( cubelet ){
- if( cubelet[ property ] === value ) results.add( cubelet )
- })
- return results
- },
- hasId: function( id ){
- return this.hasProperty( 'id', id ).cubelets[ 0 ]// expecting a single return!
- },
- hasAddress: function( address ){
- return this.hasProperty( 'address', address ).cubelets[ 0 ]// expecting a single return!
- },
- hasType: function( type ){
- return this.hasProperty( 'type', type )
- },
- hasColor: function( color ){
- var
- results = new Group()
- this.cubelets.forEach( function( cubelet ){
- if( cubelet.hasColor( color )) results.add( cubelet )
- })
- return results
- },
- hasColors: function(){// this function implies AND rather than OR, XOR, etc.
- var
- results = new Group(),
- colors = Array.prototype.slice.call( arguments )
- this.cubelets.forEach( function( cubelet ){
- if( cubelet.hasColors.apply( cubelet, colors )) results.add( cubelet )
- })
- return results
- },
- // We needed this business in order to deal with partial rotations.
- // A little janky perhaps (grabbing the average, that is)
- // but gets the job done and allows us to do getDistanceToPeg() below.
- getAverageRotation: function( axis ){
- var sum = 0
- this.cubelets.forEach( function( cubelet ){
- sum += cubelet[ axis.toLowerCase() ]
- })
- return sum / this.cubelets.length
- },
- getAverageRotationX: function(){
- return this.getAverageRotation( 'x' )
- },
- getAverageRotationY: function(){
- return this.getAverageRotation( 'y' )
- },
- getAverageRotationZ: function(){
- return this.getAverageRotation( 'z' )
- },
- // What rotation degree are we on right now?
- // What direction are we spinning from here? (Clockwise or anti?)
- // Let's go in that direction until we hit degree % 90 === 0.
- // What's the distance from here to there?
- // Not the prettiest code I've ever written... Sorry.
- getDistanceToPeg: function( axis ){
- var
- current = this.getAverageRotation( axis ),
- direction = axis.toUpperCase() === axis ? 'clockwise' : 'anticlockwise',
- distance = current
- .add( 90 )
- .divide( 90 )
- .roundDown()
- .multiply( 90 )
- .subtract( current ),
- target = current + distance
- if( direction === 'anticlockwise' ){
- distance -= 90
- if( distance === 0 ) distance -= 90
- target = current + distance
- }
- if( Cube.verbosity >= 0.9 ) console.log(
- 'Average rotation for this group about the '+ axis.toUpperCase() +' axis:', current,
- '\nRotation direction:', direction,
- '\nDistance to next peg:', distance,
- '\nTarget rotation:', target
- )
- // We need to return the absolute() value of the distance
- // because the vector (direction) of the twist will be taken into account
- // by cube.twist() or whatever else is calling this function.
- return distance.absolute()
- },
- // cube.front.isSolved( 'front' )
- // cube.front.up.isSolved( 'up' )
- isSolved: function( face ){
- if( face ){
- var
- faceColors = {},
- numberOfColors = 0
- if( face instanceof Direction ) face = face.name
- this.cubelets.forEach( function( cubelet ){
- var color = cubelet[ face ].color.name
- if( faceColors[ color ] === undefined ){
-
- faceColors[ color ] = 1
- numberOfColors ++
- }
- else faceColors[ color ] ++
- })
- return numberOfColors === 1 ? true : false
- }
- else {
-
- console.warn( 'A face [String or Direction] argument must be specified when using Group.isSolved().' )
- return false
- }
- },
- // Visual switches.
- // Take this group and hide all the stickers,
- // turn on wireframe mode, etc.
- show: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.show() })
- return this
- },
- hide: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.hide() })
- return this
- },
- showPlastics: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.showPlastics() })
- return this
- },
- hidePlastics: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.hidePlastics() })
- return this
- },
- showExtroverts: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.showExtroverts() })
- return this
- },
- hideExtroverts: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.hideExtroverts() })
- return this
- },
- showIntroverts: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.showIntroverts() })
- return this
- },
- hideIntroverts: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.hideIntroverts() })
- return this
- },
- showStickers: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.showStickers() })
- return this
- },
- hideStickers: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.hideStickers() })
- return this
- },
- showWireframes: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.showWireframes() })
- return this
- },
- hideWireframes: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.hideWireframes() })
- return this
- },
- showIds: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.showIds() })
- return this
- },
- hideIds: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.hideIds() })
- return this
- },
- showTexts: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.showTexts() })
- return this
- },
- hideTexts: function(){
- this.cubelets.forEach( function( cubelet ){ cubelet.hideTexts() })
- return this
- },
- getOpacity: function(){
- var avg = 0
- this.cubelets.forEach( function( cubelet ){ avg += cubelet.getOpacity() })
- return avg / this.cubelets.length
- },
- setOpacity: function( opacity, onComplete ){
- this.cubelets.forEach( function( cubelet ){ cubelet.setOpacity( opacity, onComplete ) })
- return this
- },
- getRadius: function(){
- var avg = 0
- this.cubelets.forEach( function( cubelet ){ avg += cubelet.getRadius() })
- return avg / this.cubelets.length
- },
- setRadius: function( radius, onComplete ){
- this.cubelets.forEach( function( cubelet ){ cubelet.setRadius( radius, onComplete ) })
- return this
- }
- })
- })
|