<commit_before>/**
 * Отправляет ajax-запросы и обрабатывает результаты.
 *
 * Добавляет события:
 * form-submit		— срабатывает перед отправкой данных формы
 */
$.ajaxSetup( {
	async : false,
	cache :	false,
	headers : {
		'X-Requested-With' : 'XMLHttpRequest'
	}
} );

var ajaxer = {};
ajaxer.id = 1;

ajaxer.httpRequest = function( url, params, headers ) {

	var data = {};
	if( typeof params == 'undefined' || !params ) {
		data.type = 'GET';
	} else {
		data.type = 'POST';
		data.data = 'json=' + encodeURIComponent( JSON.stringify( params ) );
	}
	if( typeof headers != 'undefined' ) {
		data.headers = headers;
	}
	return $.ajax( url, data ).responseText;
};

ajaxer.sendForm = function( form, event ) {

	var data = {
		form: $( form ).serializeArray()
	};
	//var data = $( event.target ).serialize();
	$( form ).find( '.required' ).fadeOut( 'fast' );
	$( form ).find( '.invalid' ).fadeOut( 'fast' );
	$( form ).find( '.status' ).fadeOut( 'fast' );
	$( form ).find( '.problem' ).removeClass( 'problem' );
	ajaxer.process( this.httpRequest( $( form ).attr( 'action' ), data ), form );
};

ajaxer.query = function( url, data ) {

	ajaxer.process( this.httpRequest( url, data ) );
};

ajaxer.process = function( data, form ) {

	try {
		console.info( 'Server said:', data );
		var data1 = $.parseJSON( data );
		if( !data1.actions ) {
			throw "data error";
		}
		this.clean( form );
		for( var key in data1.actions ) {
			var action = data1.actions[key];
			switch( action.action ) {
			case 'notify':	// сообщение
				this.notify( action.lang, action.message );
				break;
			case 'require':// не заполнено обязательное поле формы
				this.require( form, action.name );
				break;
			case 'invalid':	// не правильное значение поля формы
				this.invalid( form, action.name, action.message );
				break;
			case 'status': // текстовый статус для поля
				this.status( form, action.name, action.message, action.classname );
				break;
			case 'redirect':// перенаправление
				this.redirect( action.url );
				break;
			case 'display':	// показать окно с пришедшим html
				this.display( action.html );
				break;
			case 'reload': // перезагрузить страницу
				this.reload();
				break;
			case 'close':
				this.close( form );
				break;
			case 'error':	// сообщение об ошибке
				this.error( action.lang, action.message );
				break;
			case 'reset':	// сделать форме reset
				this.reset( form );
				break;
			default:
				console.warn( 'Ajaxer action "' + action.action + '" not implemented' );
			}
		}
	} catch( ex ) {
		this.notify( {close:'OK'}, 'Unknown error.' );
		console.warn( 'Server returned:', data );
	}
};

ajaxer.clean = function( form ) {

	$( form ).find( '.problem' ).removeClass( 'problem' );
};

ajaxer.notify = function( lang, message ) {

	$( 'body' ).append(
		'
' +
			'
' +
			'
' +
			'

' +
			'
' + message + '
' +
			'' + ( lang.close ? lang.close : 'OK' ) + '' +
			'
' +
			'
' +
			'
'
	);
	$( '#ajaxer-' + ajaxer.id ).find( '.overlay-inner' ).fadeIn( 'fast' );
	$( window ).resize();
	ajaxer.id++;
};

ajaxer.error = function( lang, message ) {

	ajaxer.notify( lang, message );
};

ajaxer.require = function( form, name ) {

	var el = $( form ).find( '[name=' + name + ']' );
	if( !el.length || el.attr( 'type' ) == 'hidden' ) {
		ajaxer.error( {}, 'Field "' + name + '" is required.' );
		return;
	}
	var cke = $( form ).find( '#cke_' + name );
	if( cke.length ) {
		cke.addClass( 'problem' );
	} else {
		el.addClass( 'problem' );
	}
	var container = el.closest( '.container' );
	if( !container.length ) {
		return;
	}
	cke = $( form ).find( '#cke_' + name );
	if( cke.length ) {
		cke.addClass( 'problem' );
	} else {
		container.addClass( 'problem' );
	}
	var req = container.find( '.required' );
	if( !req.length ) {
		return;
	}
	req.fadeIn();
};

ajaxer.invalid = function( form, name, message ) {

	var el = $( form ).find( '[name=' + name + ']' );
	if( !el.length || el.attr( 'type' ) == 'hidden' ) {
		ajaxer.error( {}, 'Invalid value for field "' + name + '".' );
		return;
	}
	var cke = $( form ).find( '#cke_' + name );
	if( cke.length ) {
		cke.addClass( 'problem' );
	} else {
		el.addClass( 'problem' );
	}
	var container = el.closest( '.container' );
	if( !container.length ) {
		return;
	}
	cke = $( form ).find( '#cke_' + name );
	if( cke.length ) {
		cke.addClass( 'problem' );
	} else {
		container.addClass( 'problem' );
	}
	var req = container.find( '.invalid' );
	if( !req.length ) {
		return;
	}
	if( message ) {
		req.find( '.invalid-text' ).html( message );
	}
	req.fadeIn( 'fast' );
};

ajaxer.status = function( form, name, message, classname ) {

	var status = $( form ).find( '[name=' + name + ']' ).parents( '.container' ).find( '.status' );
	if( status ) {
		status.fadeIn( 'fast' );
		status.attr( 'class', 'status ' + classname );
		status.html( message );
	}
};

ajaxer.redirect = function( url ) {

	if( typeof(switcher) != 'undefined' ) {
		switcher.page( url );
	} else {
		document.location( url );
	}
};

ajaxer.reload = function() {

	window.location.reload();
};

ajaxer.display = function( html ) {

	$( 'body' ).append(
		'
' +
			'
' +
			'
' +
			'

' +
			html +
			'
' +
			'
' +
			'
'
	);
	$( '#ajaxer-' + ajaxer.id ).find( '.overlay-inner' ).fadeIn( 'fast' );
	$( window ).resize();
	ajaxer.id++;
};

ajaxer.close = function( obj ) {

	var el = $( obj ).parents( '.overlay' );
	el.fadeOut( 'fast', function() {
		$( this ).remove();
	} );
};

ajaxer.reset = function( form ) {

	$( form ).get( 0 ).reset();
};

var main = {};
main.httpRequest = ajaxer.httpRequest;

$( document ).delegate( 'form.ajaxer', 'submit', function( event ) {

	var form = $( this );
	$( document ).triggerHandler( 'form-submit' );
	event.preventDefault();
	if( !form.find( 'input[type=file]' ).length ) {
		// serialize method
		ajaxer.sendForm( this, event );
	} else {
		// iframe method
		if( !$( '#ajaxerFrame' ).length ) {
			var frame = $( '' );
			$( 'body' ).append( frame );
			var uuid = '';
			for( var i = 0; i < 32; i++ ) {
				uuid += Math.floor( Math.random() * 16 ).toString( 16 );
			}
			var originalAction = form.attr( 'action' );
			form.attr( 'method', 'post' );
			form.attr( 'enctype', 'multipart/form-data' );
			form.attr( 'action', form.attr( 'action' ) + ( originalAction.indexOf( '?' ) == -1 ? '?' : '&' ) + 'X-Progress-ID=' + uuid );
			form.attr( 'target', 'ajaxerFrame' );
			form.append( '<input type="hidden" name="_method" value="iframe"/>' );
			var loading = $( '#loading' );
			if( !loading.length ) {
				$( 'body' ).append( loading = $( '

' ) );
			}
			loading.fadeIn();
			var interval = window.setInterval(
				function() {
					form.submit();
					frame.load( function() {
						window.clearTimeout( interval );
						ajaxer.fetchProgress( uuid );
						var rawframe = frame.get( 0 );
						if( rawframe.contentDocument ) {
							var val = rawframe.contentDocument.body.innerHTML;
						} else if( rawframe.contentWindow ) {
							val = rawframe.contentWindow.document.body.innerHTML;
						} else if( rawframe.document ) {
							val = rawframe.document.body.innerHTML;
						}
						try {
							var fc = $( val ).text();
							if( fc ) {
								val = fc;
							}
						} catch( e ) {
						}
						form.attr( 'action', originalAction );
						form.find( 'input[name=_method]' ).remove();
						$( 'iframe#ajaxerFrame' ).remove();
						loading.find( 'td1' ).css( 'width', Math.ceil( $( '#upprog' ).width() - 20 ) + 'px' );
						loading.fadeOut( 'slow', function() {
							loading.find( '#upprog' ).remove();
						} );
						ajaxer.process( val, form );
					} );
					interval = window.setInterval(
						function() {
							ajaxer.fetchProgress( uuid );
						},
						1000
					);
				},
				50
			);
		}
	}
} );

ajaxer.fetchProgress = function( uuid ) {

	var res = ajaxer.httpRequest( '/progress', null, { 'X-Progress-ID': uuid } );
	res = $.parseJSON( res );
	if( res.state == 'uploading' ) {
		var progressbar = $( '#upprog' );
		if( !progressbar.length ) {
			$( '#loading' )
				.css( 'background-image', 'none' )
				.append( '

' );
			autocenter();
			progressbar = $( '#upprog' );
		}
		progressbar.find( '.td1' )
			.css( 'width', Math.ceil( ( progressbar.width() - 20 ) * res.received / res.size ) + 'px' );
	}
};

$( 'a.ajaxer' ).live( 'click dblclick', function( e ) {
	var href = $( this ).attr( 'href' );
	if( href && href != '#' ) {
		ajaxer.query( href );
	}
	e.preventDefault();
} );

$( '.ajaxer input' ).live( 'keypress', function( e ) {
	if( e.which == 13 ) {
		$( this ).parents( 'form' ).submit();
		e.preventDefault();
	}
} );

$( '.submit' ).live( 'click dblclick', function( e ) {
	$( this ).parents( 'form' ).submit();
	e.preventDefault();
});

$( '.reset' ).live( 'click dblclick', function( e ) {
	ajaxer.reset( $( this ).parents( 'form' ) );
	e.preventDefault();
} );

ajaxer.watcher = function() {

	var mc = $.cookie( 'query' );
	if( mc ) {
		mc = $.parseJSON( mc );
		ajaxer.query( mc.url );
		$.cookie( 'query', null, { path: "/", domain: config.mainhost ? '.' + config.mainhost : false } );
	}
	mc = $.cookie( 'notify' );
	if( mc ) {
		mc = $.parseJSON( mc );
		if( mc.type == 'error' ) {
			ajaxer.error( mc.lang, mc.message );
		} else {
			ajaxer.notify( mc.lang, mc.message );
		}
		if( config.mainhost ) {
			$.cookie( 'notify', null, { path:"/", domain:'.' + config.mainhost } );
		} else {
			$.cookie( 'notify', null, { path:"/", domain:'.' + window.location.host } );
		}
	}
};

$( document ).ready( ajaxer.watcher );
$( document ).bind( 'construct', ajaxer.watcher );<commit_msg>Пробуем пофиксить баг, возникающий если iframe ajax закачка происходит слишком быстро. (try #4)<commit_after>/**
 * Отправляет ajax-запросы и обрабатывает результаты.
 *
 * Добавляет события:
 * form-submit		— срабатывает перед отправкой данных формы
 */
$.ajaxSetup( {
	async : false,
	cache :	false,
	headers : {
		'X-Requested-With' : 'XMLHttpRequest'
	}
} );

var ajaxer = {};
ajaxer.id = 1;

ajaxer.httpRequest = function( url, params, headers ) {

	var data = {};
	if( typeof params == 'undefined' || !params ) {
		data.type = 'GET';
	} else {
		data.type = 'POST';
		data.data = 'json=' + encodeURIComponent( JSON.stringify( params ) );
	}
	if( typeof headers != 'undefined' ) {
		data.headers = headers;
	}
	return $.ajax( url, data ).responseText;
};

ajaxer.sendForm = function( form, event ) {

	var data = {
		form: $( form ).serializeArray()
	};
	//var data = $( event.target ).serialize();
	$( form ).find( '.required' ).fadeOut( 'fast' );
	$( form ).find( '.invalid' ).fadeOut( 'fast' );
	$( form ).find( '.status' ).fadeOut( 'fast' );
	$( form ).find( '.problem' ).removeClass( 'problem' );
	ajaxer.process( this.httpRequest( $( form ).attr( 'action' ), data ), form );
};

ajaxer.query = function( url, data ) {

	ajaxer.process( this.httpRequest( url, data ) );
};

ajaxer.process = function( data, form ) {

	try {
		console.info( 'Server said:', data );
		var data1 = $.parseJSON( data );
		if( !data1.actions ) {
			throw "data error";
		}
		this.clean( form );
		for( var key in data1.actions ) {
			var action = data1.actions[key];
			switch( action.action ) {
			case 'notify':	// сообщение
				this.notify( action.lang, action.message );
				break;
			case 'require':// не заполнено обязательное поле формы
				this.require( form, action.name );
				break;
			case 'invalid':	// не правильное значение поля формы
				this.invalid( form, action.name, action.message );
				break;
			case 'status': // текстовый статус для поля
				this.status( form, action.name, action.message, action.classname );
				break;
			case 'redirect':// перенаправление
				this.redirect( action.url );
				break;
			case 'display':	// показать окно с пришедшим html
				this.display( action.html );
				break;
			case 'reload': // перезагрузить страницу
				this.reload();
				break;
			case 'close':
				this.close( form );
				break;
			case 'error':	// сообщение об ошибке
				this.error( action.lang, action.message );
				break;
			case 'reset':	// сделать форме reset
				this.reset( form );
				break;
			default:
				console.warn( 'Ajaxer action "' + action.action + '" not implemented' );
			}
		}
	} catch( ex ) {
		this.notify( {close:'OK'}, 'Unknown error.' );
		console.warn( 'Server returned:', data );
	}
};

ajaxer.clean = function( form ) {

	$( form ).find( '.problem' ).removeClass( 'problem' );
};

ajaxer.notify = function( lang, message ) {

	$( 'body' ).append(
		'
' +
			'
' +
			'
' +
			'

' +
			'
' + message + '
' +
			'' + ( lang.close ? lang.close : 'OK' ) + '' +
			'
' +
			'
' +
			'
'
	);
	$( '#ajaxer-' + ajaxer.id ).find( '.overlay-inner' ).fadeIn( 'fast' );
	$( window ).resize();
	ajaxer.id++;
};

ajaxer.error = function( lang, message ) {

	ajaxer.notify( lang, message );
};

ajaxer.require = function( form, name ) {

	var el = $( form ).find( '[name=' + name + ']' );
	if( !el.length || el.attr( 'type' ) == 'hidden' ) {
		ajaxer.error( {}, 'Field "' + name + '" is required.' );
		return;
	}
	var cke = $( form ).find( '#cke_' + name );
	if( cke.length ) {
		cke.addClass( 'problem' );
	} else {
		el.addClass( 'problem' );
	}
	var container = el.closest( '.container' );
	if( !container.length ) {
		return;
	}
	cke = $( form ).find( '#cke_' + name );
	if( cke.length ) {
		cke.addClass( 'problem' );
	} else {
		container.addClass( 'problem' );
	}
	var req = container.find( '.required' );
	if( !req.length ) {
		return;
	}
	req.fadeIn();
};

ajaxer.invalid = function( form, name, message ) {

	var el = $( form ).find( '[name=' + name + ']' );
	if( !el.length || el.attr( 'type' ) == 'hidden' ) {
		ajaxer.error( {}, 'Invalid value for field "' + name + '".' );
		return;
	}
	var cke = $( form ).find( '#cke_' + name );
	if( cke.length ) {
		cke.addClass( 'problem' );
	} else {
		el.addClass( 'problem' );
	}
	var container = el.closest( '.container' );
	if( !container.length ) {
		return;
	}
	cke = $( form ).find( '#cke_' + name );
	if( cke.length ) {
		cke.addClass( 'problem' );
	} else {
		container.addClass( 'problem' );
	}
	var req = container.find( '.invalid' );
	if( !req.length ) {
		return;
	}
	if( message ) {
		req.find( '.invalid-text' ).html( message );
	}
	req.fadeIn( 'fast' );
};

ajaxer.status = function( form, name, message, classname ) {

	var status = $( form ).find( '[name=' + name + ']' ).parents( '.container' ).find( '.status' );
	if( status ) {
		status.fadeIn( 'fast' );
		status.attr( 'class', 'status ' + classname );
		status.html( message );
	}
};

ajaxer.redirect = function( url ) {

	if( typeof(switcher) != 'undefined' ) {
		switcher.page( url );
	} else {
		document.location( url );
	}
};

ajaxer.reload = function() {

	window.location.reload();
};

ajaxer.display = function( html ) {

	$( 'body' ).append(
		'
' +
			'
' +
			'
' +
			'

' +
			html +
			'
' +
			'
' +
			'
'
	);
	$( '#ajaxer-' + ajaxer.id ).find( '.overlay-inner' ).fadeIn( 'fast' );
	$( window ).resize();
	ajaxer.id++;
};

ajaxer.close = function( obj ) {

	var el = $( obj ).parents( '.overlay' );
	el.fadeOut( 'fast', function() {
		$( this ).remove();
	} );
};

ajaxer.reset = function( form ) {

	$( form ).get( 0 ).reset();
};

var main = {};
main.httpRequest = ajaxer.httpRequest;

ajaxer.submitting = false;
$( document ).delegate( 'form.ajaxer', 'submit', function( event ) {

	if( ajaxer.submitting ) {
		return;
	}
	var form = $( this );
	$( document ).triggerHandler( 'form-submit' );
	event.preventDefault();
	if( !form.find( 'input[type=file]' ).length ) {
		// serialize method
		ajaxer.sendForm( this, event );
	} else {
		// iframe method
		if( !$( '#ajaxerFrame' ).length ) {
			var frame = $( '' );
			$( 'body' ).append( frame );
			var uuid = '';
			for( var i = 0; i < 32; i++ ) {
				uuid += Math.floor( Math.random() * 16 ).toString( 16 );
			}
			var originalAction = form.attr( 'action' );
			form.attr( 'method', 'post' );
			form.attr( 'enctype', 'multipart/form-data' );
			form.attr( 'action', form.attr( 'action' ) + ( originalAction.indexOf( '?' ) == -1 ? '?' : '&' ) + 'X-Progress-ID=' + uuid );
			form.attr( 'target', 'ajaxerFrame' );
			form.append( '<input type="hidden" name="_method" value="iframe"/>' );
			var loading = $( '#loading' );
			if( !loading.length ) {
				$( 'body' ).append( loading = $( '

' ) );
			}
			loading.fadeIn();
			var interval = window.setInterval(
				function() {
					ajaxer.submitting = true;
					form.submit();
					ajaxer.submitting = false;
					frame.load( function() {
						window.clearTimeout( interval );
						ajaxer.fetchProgress( uuid );
						var rawframe = frame.get( 0 );
						if( rawframe.contentDocument ) {
							var val = rawframe.contentDocument.body.innerHTML;
						} else if( rawframe.contentWindow ) {
							val = rawframe.contentWindow.document.body.innerHTML;
						} else if( rawframe.document ) {
							val = rawframe.document.body.innerHTML;
						}
						try {
							var fc = $( val ).text();
							if( fc ) {
								val = fc;
							}
						} catch( e ) {
						}
						form.attr( 'action', originalAction );
						form.find( 'input[name=_method]' ).remove();
						$( 'iframe#ajaxerFrame' ).remove();
						loading.find( 'td1' ).css( 'width', Math.ceil( $( '#upprog' ).width() - 20 ) + 'px' );
						loading.fadeOut( 'slow', function() {
							loading.find( '#upprog' ).remove();
						} );
						ajaxer.process( val, form );
					} );
					interval = window.setInterval(
						function() {
							ajaxer.fetchProgress( uuid );
						},
						1000
					);
				},
				50
			);
		}
	}
} );

ajaxer.fetchProgress = function( uuid ) {

	var res = ajaxer.httpRequest( '/progress', null, { 'X-Progress-ID': uuid } );
	res = $.parseJSON( res );
	if( res.state == 'uploading' ) {
		var progressbar = $( '#upprog' );
		if( !progressbar.length ) {
			$( '#loading' )
				.css( 'background-image', 'none' )
				.append( '

' );
			autocenter();
			progressbar = $( '#upprog' );
		}
		progressbar.find( '.td1' )
			.css( 'width', Math.ceil( ( progressbar.width() - 20 ) * res.received / res.size ) + 'px' );
	}
};

$( 'a.ajaxer' ).live( 'click dblclick', function( e ) {
	var href = $( this ).attr( 'href' );
	if( href && href != '#' ) {
		ajaxer.query( href );
	}
	e.preventDefault();
} );

$( '.ajaxer input' ).live( 'keypress', function( e ) {
	if( e.which == 13 ) {
		$( this ).parents( 'form' ).submit();
		e.preventDefault();
	}
} );

$( '.submit' ).live( 'click dblclick', function( e ) {
	$( this ).parents( 'form' ).submit();
	e.preventDefault();
});

$( '.reset' ).live( 'click dblclick', function( e ) {
	ajaxer.reset( $( this ).parents( 'form' ) );
	e.preventDefault();
} );

ajaxer.watcher = function() {

	var mc = $.cookie( 'query' );
	if( mc ) {
		mc = $.parseJSON( mc );
		ajaxer.query( mc.url );
		$.cookie( 'query', null, { path: "/", domain: config.mainhost ? '.' + config.mainhost : false } );
	}
	mc = $.cookie( 'notify' );
	if( mc ) {
		mc = $.parseJSON( mc );
		if( mc.type == 'error' ) {
			ajaxer.error( mc.lang, mc.message );
		} else {
			ajaxer.notify( mc.lang, mc.message );
		}
		if( config.mainhost ) {
			$.cookie( 'notify', null, { path:"/", domain:'.' + config.mainhost } );
		} else {
			$.cookie( 'notify', null, { path:"/", domain:'.' + window.location.host } );
		}
	}
};

$( document ).ready( ajaxer.watcher );
$( document ).bind( 'construct', ajaxer.watcher );<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var Schema = mongoose.Schema;

exports.User = mongoose.model("User",new Schema({
    google_id: String,
    name: String,
    favorites: [String],
    singInDate: Date,
    lastLogin: Date,
    isAdmin: Boolean,
    settings: {
        defaultValues: {
            BATCH_SIZE: Number,
            EFFICIENCY: Number,
            BREWER: String,
            BOIL_TIME: Number,
            GrainTemp: Number,
            WatertoGrainRatio: Number,
            mashTemp: Number,
            lossMashTemp: Number,
            SpargeTempDesired: Number,
            SpargeDeadSpace: Number,
            GrainAbsorbtion: Number,
            PercentEvap: Number,
            LitersEvap: Number,
            TrubChillerLosses: Number,
            isPublic: Boolean,
            pitchRate: Number
        },
        closeUseSurvey: Boolean,
        gotoFanPage: Boolean
    },

}));

exports.WaterReport = mongoose.model("WaterReport",new Schema({
    date: Date,
    name: String,
    owner: {type:String, ref:'User'},
    cations: {
        calcium: {type: Number, default: null},
        magnesium: {type: Number, default: null},
        sodium: {type: Number, default: null},
        potassium: {type: Number, default: null},
        iron: {type: Number, default: null}
    },
    anions: {
        bicarbonate: {type: Number, default: null},
        carbonate: {type: Number, default: null},
        sulfate: {type: Number, default: null},
        chloride: {type: Number, default: null},
        nitrate: {type: Number, default: null},
        nitrite: {type: Number, default: null},
        fluoride: {type: Number, default: null}
    }

}));

exports.Recipe = mongoose.model("Recipe", new Schema({
    _id: String,
    code: String,
    owner: {type:String, ref:'User'},
    collaborators: [{type:String, ref:'User'}],
    GrainCalcMethod: String,
    date: Date,
    modificationDate: Date,
    totalAmount: Number,
    totalAmountMash: Number,
    totalHop: Number,
    NAME: String,
    VERSION: String,
    TYPE: String,
    STYLE: { NAME: String },
    BREWER: String,
    CALCCOLOUR: Number,
    BATCH_SIZE: Number,
    BOIL_SIZE: Number,
    BOIL_TIME: Number,
    ABV: Number,
    BV: Number,
    EFFICIENCY: Number,
    OG: Number,
    OG_exclude: Number,
    CALCIBU: Number,
    FG: Number,
    state: String,
    FERMENTABLES: {
        FERMENTABLE: [ {
            NAME: String,
            VERSION: String,
            AMOUNT: Number,
            TYPE: String,
            YIELD: Number,
            COLOR: Number,
            POTENTIAL: Number,
            PERCENTAGE: Number,
            USE: String,
            excludeIBU: Boolean
        } ]
    },
    HOPS: {
        HOP: [{
            NAME: String,
            VERSION: String,
            ALPHA: Number,
            AMOUNT: Number,
            USE: String,
            TIME: Number,
            FORM: String
        }]
    },
    YEASTS: {
        YEAST: [{
            NAME: String,
            VERSION: String,
            ATTENUATION: Number,
            AMOUNT: Number,
            density: Number,
            packageSize: Number
        }]
    },
    MISCS: {
        MISC: [{
            NAME: String,
            VERSION: String,
            TYPE: String,
            USE: String,
            TIME: Number,
            AMOUNT: Number
        }]
    },
    MASH: {
        MASH_STEPS: {
            MASH_STEP: [ {
                NAME: String,
                TYPE: String, //'Infusion' fijo por ahora
                INFUSE_AMOUNT: Number, //Agua agregada
                INFUSE_TEMP: Number,   //Temp agua agregada
                STEP_TIME: Number,     //Duracion
                STEP_TEMP: Number,     //Temperatura buscada (si pongo INFUSE se calcula sola, pero se puede pisar)
                END_TEMP: Number,      //Temp final de la etapa.
                DESCRIPTION: String,   //texto libre
                WATER_GRAIN_RATIO: Number, //relacion final (calculada, INFUSE_AMOUNT y DECOCTION_AMT)
                decoction: Boolean,
                DECOCTION_AMT: Number,  //cantidad sacada para decocction
                infuse: Boolean,        //Indica si agrega agua o no.
                recirculate: Boolean    //Si recircula o no
            }]
        }
    },
    fermentation: {
        view: String,
        estimateDate: Date,
        alertTime: Number,
        stages: [{
            title: String,
            duration: Number, //In days/hours
            durationMode: String, //'Dias' / 'Horas'
            transferring: Boolean, //In the end of stage
            losses: Number, //Litros perdidos
            temperature: Number,
            temperatureEnd: Number,
            action: String, // 'Inoculacion', 'Dry-Hop', 'Otro'
            alertDone: Boolean
        }]
    },
    bottling: {
        sugar: {
            desiredVol: Number,
            temperature: Number,
            sugarType: String
        },
        must: {
            temperature: Number
        },
        co2: {
            desiredVol: Number,
            temperature: Number
        },
        bottles: [{
            bottleType: String,
            size: Number,
            amount: Number,
            subTotal: Number,
            carbonatationType: String,
            colour: String
        }]
    },
    log: {
       logs: [{
           time: Date,
           detail: String,
           delay: Number,
           delayUnit: String,
           logType: String,
           logRef: String,
           discard: Boolean
       }]
    },
    PRIMARY_TEMP: Number,
    BIAB: String,
    IBUCalcMethod: String,
    StyleNaziMode: String,
    IsNoChill: String,
    GrainUnits: String,
    HopsUnits: String,
    VolumeUnits: String,
    TemperatureUnits: String,
    Colour: String,
    GrainTemp: Number,
    StrikeWater: Number,
    SpargeDeadSpace: Number,
    GrainAbsorbtion: Number,
    WatertoGrainRatio: Number,
    SpargeTempDesired: Number,
    SpargeWhaterDesiredPH: Number,
    MashDesiredPH: Number,
    PercentEvap: Number,
    LitersEvap: Number,
    TrubChillerLosses: Number,
    TopUpWater: Number,
    calendarpressed: String,
    brewdayEnabled: String,
    yeastpitchEnabled: String,
    primaryEnabled: String,
    secondaryEnabled: String,
    keggingEnabled: String,
    serveEnabled: String,
    //Start own properties
    isPublic: Boolean,
    publishDate: Date,
    naziMode: Boolean,
    cloneFrom: {type:String, ref:'Recipe'},
    starredBy: [{_id:Schema.Types.ObjectId,name:String}],
    clonedBy: [{_id:Schema.Types.ObjectId,name:String,recipe_id:{type:String, ref:'Recipe'}}],
    comments:[{
        text: String,
        _id: String,
        user_id: Schema.Types.ObjectId,
        name: String,
        date: Date
    }],
    fixIngredients: String,
    mashTemp: Number,
    lossMashTemp: Number,
    tags: [String],
    beer_id: String, //beer._id from BirrasQueHeTomado.com
    pitchRate: Number,
    version: [{
        number: Number,
        user_id: String,
        timeStamp: Date,
        user_name: String
    }]
},{ _id: false }));

exports.Bottle = mongoose.model("Bottle",new Schema({
    _id: String,
    name: String,
    size: Number,
    colour: String //'Ambar', 'Verde', 'Blanca'
},{ _id: false }));

exports.Grain = mongoose.model("Grain",new Schema({
    "name": String,
    "type": String,
    "colour": Number,
    "potential": Number,
    "use": String,
    "excludeIBU": Boolean
}));

exports.Misc = mongoose.model("Misc",new Schema({
    "name": String,
    "type": String,
    "use": String
}));

exports.Yeast = mongoose.model("Yeast",new Schema({
    "name": String,
    "aa": Number,
    "density": Number,
    "packageSize": Number
}));

exports.Hop = mongoose.model("Hop",new Schema({
    "name": String,
    "alpha": Number
}));

exports.Style = mongoose.model("Style",new Schema({
    "name": String,
    "co2_min": Number,
    "co2_max": Number,
    "OG_Min": Number,
    "OG_Max": Number,
    "FG_Min": Number,
    "FG_Max": Number,
    "IBU_Min": Number,
    "IBU_Max": Number,
    "Colour_Min": Number,
    "Colour_Max": Number,
    "ABV_Min": Number,
    "ABV_Max": Number,
    "link": String,
    "related": String
}));

exports.Action = mongoose.model("Action",new Schema({
    "user_id": {type:String, ref:'User'},
    "date": Date,
    "actionType": String,
    "data": String
}));

exports.Notification = mongoose.model("Notification",new Schema({
    "user_id": {type:String, ref:'User'},
    "date": Date,
    "status": String, //new,unread,read
    "data": String,
    "link": String
}));

exports.Tag = mongoose.model("Tag",new Schema({
    "_id": String
},{ _id: false }));

exports.TempDevice = mongoose.model("TempDevice",new Schema({
    code: String, //idcebada
    name: String,
    owner: {type:String, ref:'User'},
    recipe_id: String
}));

exports.TempDeviceReport = mongoose.model("TempDeviceReport",new Schema({
    code: String, //idcebada
    timestamp: Number, //miliseconds from bla bla bla (date.getTime())
    recipe_id: String, //Receta vinculada
    source: String, //Esto es para cuando vienen datos de mas de 1 fermentador
    temperature: Number, //Temperatura interior medida (del liquido)
    temperatureExt: Number, //Temperatura exterior (opcional)
    temperatureMax: Number, //Temperatura seteada en el dispositivo
    temperatureMin: Number, //Temperatura seteada en el dispositivo
    coldStatus: Boolean, //Satus switch frio
    heatStatus: Boolean //status switch calor
}));
<commit_msg>fix model<commit_after>var mongoose = require('mongoose');
var Schema = mongoose.Schema;

exports.User = mongoose.model("User",new Schema({
    google_id: String,
    name: String,
    favorites: [String],
    singInDate: Date,
    lastLogin: Date,
    isAdmin: Boolean,
    settings: {
        defaultValues: {
            BATCH_SIZE: Number,
            EFFICIENCY: Number,
            BREWER: String,
            BOIL_TIME: Number,
            GrainTemp: Number,
            WatertoGrainRatio: Number,
            mashTemp: Number,
            lossMashTemp: Number,
            SpargeTempDesired: Number,
            SpargeDeadSpace: Number,
            GrainAbsorbtion: Number,
            PercentEvap: Number,
            LitersEvap: Number,
            TrubChillerLosses: Number,
            isPublic: Boolean,
            pitchRate: Number
        },
        closeUseSurvey: Boolean,
        gotoFanPage: Boolean
    },

}));

exports.WaterReport = mongoose.model("WaterReport",new Schema({
    date: Date,
    name: String,
    owner: {type:String, ref:'User'},
    cations: {
        calcium: {type: Number, default: null},
        magnesium: {type: Number, default: null},
        sodium: {type: Number, default: null},
        potassium: {type: Number, default: null},
        iron: {type: Number, default: null}
    },
    anions: {
        bicarbonate: {type: Number, default: null},
        carbonate: {type: Number, default: null},
        sulfate: {type: Number, default: null},
        chloride: {type: Number, default: null},
        nitrate: {type: Number, default: null},
        nitrite: {type: Number, default: null},
        fluoride: {type: Number, default: null}
    }

}));

exports.Recipe = mongoose.model("Recipe", new Schema({
    _id: String,
    code: String,
    owner: {type:String, ref:'User'},
    collaborators: [{type:String, ref:'User'}],
    GrainCalcMethod: String,
    date: Date,
    modificationDate: Date,
    totalAmount: Number,
    totalAmountMash: Number,
    totalHop: Number,
    NAME: String,
    VERSION: String,
    TYPE: String,
    STYLE: { NAME: String },
    BREWER: String,
    CALCCOLOUR: Number,
    BATCH_SIZE: Number,
    BOIL_SIZE: Number,
    BOIL_TIME: Number,
    ABV: Number,
    BV: Number,
    EFFICIENCY: Number,
    OG: Number,
    OG_exclude: Number,
    CALCIBU: Number,
    FG: Number,
    state: String,
    FERMENTABLES: {
        FERMENTABLE: [new Schema({
            NAME: String,
            VERSION: String,
            AMOUNT: Number,
            TYPE: String,
            YIELD: Number,
            COLOR: Number,
            POTENTIAL: Number,
            PERCENTAGE: Number,
            USE: String,
            excludeIBU: Boolean
        }, {_id:true}) ]
    },
    HOPS: {
        HOP: [new Schema({
            NAME: String,
            VERSION: String,
            ALPHA: Number,
            AMOUNT: Number,
            USE: String,
            TIME: Number,
            FORM: String
        }, {_id:true})]
    },
    YEASTS: {
        YEAST: [new Schema({
            NAME: String,
            VERSION: String,
            ATTENUATION: Number,
            AMOUNT: Number,
            density: Number,
            packageSize: Number
        }, {_id:true})]
    },
    MISCS: {
        MISC: [new Schema({
            NAME: String,
            VERSION: String,
            TYPE: String,
            USE: String,
            TIME: Number,
            AMOUNT: Number
        }, {_id:true})]
    },
    MASH: {
        MASH_STEPS: {
            MASH_STEP: [new Schema({
                NAME: String,
                TYPE: String, //'Infusion' fijo por ahora
                INFUSE_AMOUNT: Number, //Agua agregada
                INFUSE_TEMP: Number,   //Temp agua agregada
                STEP_TIME: Number,     //Duracion
                STEP_TEMP: Number,     //Temperatura buscada (si pongo INFUSE se calcula sola, pero se puede pisar)
                END_TEMP: Number,      //Temp final de la etapa.
                DESCRIPTION: String,   //texto libre
                WATER_GRAIN_RATIO: Number, //relacion final (calculada, INFUSE_AMOUNT y DECOCTION_AMT)
                decoction: Boolean,
                DECOCTION_AMT: Number,  //cantidad sacada para decocction
                infuse: Boolean,        //Indica si agrega agua o no.
                recirculate: Boolean    //Si recircula o no
            },{_id:true})]
        }
    },
    fermentation: {
        view: String,
        estimateDate: Date,
        alertTime: Number,
        stages: [new Schema({
            title: String,
            duration: Number, //In days/hours
            durationMode: String, //'Dias' / 'Horas'
            transferring: Boolean, //In the end of stage
            losses: Number, //Litros perdidos
            temperature: Number,
            temperatureEnd: Number,
            action: String, // 'Inoculacion', 'Dry-Hop', 'Otro'
            alertDone: Boolean
        }, {_id:true})]
    },
    bottling: {
        sugar: {
            desiredVol: Number,
            temperature: Number,
            sugarType: String
        },
        must: {
            temperature: Number
        },
        co2: {
            desiredVol: Number,
            temperature: Number
        },
        bottles: [new Schema({
            bottleType: String,
            size: Number,
            amount: Number,
            subTotal: Number,
            carbonatationType: String,
            colour: String
        }, {_id:true})]
    },
    log: {
       logs: [new Schema({
           time: Date,
           detail: String,
           delay: Number,
           delayUnit: String,
           logType: String,
           logRef: String,
           discard: Boolean
       },{_id:true})]
    },
    PRIMARY_TEMP: Number,
    BIAB: String,
    IBUCalcMethod: String,
    StyleNaziMode: String,
    IsNoChill: String,
    GrainUnits: String,
    HopsUnits: String,
    VolumeUnits: String,
    TemperatureUnits: String,
    Colour: String,
    GrainTemp: Number,
    StrikeWater: Number,
    SpargeDeadSpace: Number,
    GrainAbsorbtion: Number,
    WatertoGrainRatio: Number,
    SpargeTempDesired: Number,
    SpargeWhaterDesiredPH: Number,
    MashDesiredPH: Number,
    PercentEvap: Number,
    LitersEvap: Number,
    TrubChillerLosses: Number,
    TopUpWater: Number,
    calendarpressed: String,
    brewdayEnabled: String,
    yeastpitchEnabled: String,
    primaryEnabled: String,
    secondaryEnabled: String,
    keggingEnabled: String,
    serveEnabled: String,
    //Start own properties
    isPublic: Boolean,
    publishDate: Date,
    naziMode: Boolean,
    cloneFrom: {type:String, ref:'Recipe'},
    starredBy: [{_id:Schema.Types.ObjectId,name:String}],
    clonedBy: [{_id:Schema.Types.ObjectId,name:String,recipe_id:{type:String, ref:'Recipe'}}],
    comments:[{
        text: String,
        _id: String,
        user_id: Schema.Types.ObjectId,
        name: String,
        date: Date
    }],
    fixIngredients: String,
    mashTemp: Number,
    lossMashTemp: Number,
    tags: [String],
    beer_id: String, //beer._id from BirrasQueHeTomado.com
    pitchRate: Number,
    version: [{
        number: Number,
        user_id: String,
        timeStamp: Date,
        user_name: String
    }]
},{ _id: false }));

exports.Bottle = mongoose.model("Bottle",new Schema({
    _id: String,
    name: String,
    size: Number,
    colour: String //'Ambar', 'Verde', 'Blanca'
},{ _id: false }));

exports.Grain = mongoose.model("Grain",new Schema({
    "name": String,
    "type": String,
    "colour": Number,
    "potential": Number,
    "use": String,
    "excludeIBU": Boolean
}));

exports.Misc = mongoose.model("Misc",new Schema({
    "name": String,
    "type": String,
    "use": String
}));

exports.Yeast = mongoose.model("Yeast",new Schema({
    "name": String,
    "aa": Number,
    "density": Number,
    "packageSize": Number
}));

exports.Hop = mongoose.model("Hop",new Schema({
    "name": String,
    "alpha": Number
}));

exports.Style = mongoose.model("Style",new Schema({
    "name": String,
    "co2_min": Number,
    "co2_max": Number,
    "OG_Min": Number,
    "OG_Max": Number,
    "FG_Min": Number,
    "FG_Max": Number,
    "IBU_Min": Number,
    "IBU_Max": Number,
    "Colour_Min": Number,
    "Colour_Max": Number,
    "ABV_Min": Number,
    "ABV_Max": Number,
    "link": String,
    "related": String
}));

exports.Action = mongoose.model("Action",new Schema({
    "user_id": {type:String, ref:'User'},
    "date": Date,
    "actionType": String,
    "data": String
}));

exports.Notification = mongoose.model("Notification",new Schema({
    "user_id": {type:String, ref:'User'},
    "date": Date,
    "status": String, //new,unread,read
    "data": String,
    "link": String
}));

exports.Tag = mongoose.model("Tag",new Schema({
    "_id": String
},{ _id: false }));

exports.TempDevice = mongoose.model("TempDevice",new Schema({
    code: String, //idcebada
    name: String,
    owner: {type:String, ref:'User'},
    recipe_id: String
}));

exports.TempDeviceReport = mongoose.model("TempDeviceReport",new Schema({
    code: String, //idcebada
    timestamp: Number, //miliseconds from bla bla bla (date.getTime())
    recipe_id: String, //Receta vinculada
    source: String, //Esto es para cuando vienen datos de mas de 1 fermentador
    temperature: Number, //Temperatura interior medida (del liquido)
    temperatureExt: Number, //Temperatura exterior (opcional)
    temperatureMax: Number, //Temperatura seteada en el dispositivo
    temperatureMin: Number, //Temperatura seteada en el dispositivo
    coldStatus: Boolean, //Satus switch frio
    heatStatus: Boolean //status switch calor
}));
<|endoftext|>


<commit_before>/*
 * DonkeySlider - a jQuery/Hammer based donkey slider
 * Author: Samuel Delesque <hello@samueldelesque.me>
 *
 *
 * Dependencies:
 *
 * jQuery - http://jquery.com/
 * jQuery.Hammer - http://hammerjs.github.io/
 * (jQuery.transform - http://louisremi.github.io/jquery.transform.js/  for old browser support)
 *
 *
 *  example usage:

	$(document).ready(function() {
		window.myDonkey = new DonkeySlider(".slider");
	});

 *
 */

(function(window,$,hammer) {
	if(!$)console.error("jQuery is required for Donkey.");
	if(!hammer)console.error("jQuery.hammer is required for Donkey.");
	$.fn.hammer = hammer;
	window.DonkeySlider = function(selector){
		var Donkey = {
			$el:null,
			w:{},
			activeSlide:null,
			slideWidth:240,
			slideMargin:20,
			offset:0,
			movement:0,
			direction:null,

			//slides fill 90% of window width
			showPercent:0.9,

			//if the slider has margins
			sliderMargin:20,

			init: function(slider,slides,handles){
				//construct the jQuery elements for later use
				Donkey.$w = $(window);

				if(!slider){console.error("Please pass a valid jQuery selector to Donkey.init()");return;}
				Donkey.$slider = $(slider);

				if(!slides){slides = ".slide"}
				Donkey.$slides = $(slides,Donkey.slider);

				if(!handles){handles = ".handles"}
				Donkey.$handles = $(handles,Donkey.slider);

				Donkey.listen();
				return Donkey;
			},

			swiping: function(e){
				switch(e.type){
					case "dragleft":
					case "dragright":
						Donkey.offset = Math.round(e.gesture.deltaX+Donkey.movement);
						Donkey.direction = e.type;
						Donkey.$slider.css({
							transform:"translateX("+Donkey.offset+"px)"
						});
					break;

					case "release":
						var pos = Donkey.offset;
						if(Donkey.direction == "dragleft"){pos-=100;}
						else{pos+=100;}
						var index = -1 * Math.round(pos/(Donkey.slideWidth + Donkey.slideMargin)),
							min = -((Donkey.count-1) * (Donkey.slideWidth + Donkey.slideMargin)),
							max = 0;

						if(pos < min)index = Donkey.count-1;
						if(pos > max)index = 0;
						Donkey.showSlide(index);
					break;
				}
			},

			next: function(){
				var next = Donkey.activeSlide + 1;
				if(next >= Donkey.count)next=0;
				Donkey.showSlide(next);
			},

			prev: function(){
				var prev = Donkey.activeSlide - 1;
				if(prev <= 0)prev=Donkey.count-1;
				Donkey.showSlide(prev);
			},

			showSlide: function(index){
				var offset = -index*(Donkey.slideWidth + Donkey.slideMargin);
				Donkey.$slider.animate({
					transform:"translateX("+offset+"px)"
				});
				Donkey.movement = offset;
				Donkey.activeSlide = index;

				Donkey.$handles.find("span").removeClass("active").eq(index).addClass("active");
			},

			listen: function(){
				Donkey.$w.resize(function(){
					Donkey.slideWidth = Math.round((Donkey.$w.width()-(Donkey.sliderMargin * 2)) * Donkey.showPercent);
					Donkey.$slides.css("width",Donkey.slideWidth);
				});
				Donkey.$w.trigger("resize");

				Donkey.$slider.hammer({drag_lock_to_axis: true}).on("release dragleft dragright swipeleft swiperight", Donkey.swiping);
				Donkey.count = Donkey.$slides.length;
				Donkey.$slider.trigger("release");
			}
		}
		return Donkey.init(selector);
	}
})(window,jQuery,jQuery.fn.hammer);
<commit_msg>minified name in use inside plugin to   "_"<commit_after>/*
 * DonkeySlider - a jQuery/Hammer based donkey slider
 * Author: Samuel Delesque <hello@samueldelesque.me>
 *
 *
 * Dependencies:
 *
 * jQuery - http://jquery.com/
 * jQuery.Hammer - http://hammerjs.github.io/
 * (jQuery.transform - http://louisremi.github.io/jquery.transform.js/  for old browser support)
 *
 *
 *  example usage:

	$(document).ready(function() {
		window.myDonkey = new DonkeySlider(".slider");
	});

 *
 */

(function(window,$,hammer) {
	if(!$)console.error("jQuery is required for Donkey.");
	if(!hammer)console.error("jQuery.hammer is required for Donkey.");
	$.fn.hammer = hammer;
	window.DonkeySlider = function(selector){
		var _ = {
			$el:null,
			w:{},
			activeSlide:null,
			slideWidth:240,
			slideMargin:20,
			offset:0,
			movement:0,
			direction:null,

			//slides fill 90% of window width
			showPercent:0.9,

			//if the slider has margins
			sliderMargin:20,

			init: function(slider,slides,handles){
				//construct the jQuery elements for later use
				_.$w = $(window);

				if(!slider){console.error("Please pass a valid jQuery selector to _.init()");return;}
				_.$slider = $(slider);

				if(!slides){slides = ".slide"}
				_.$slides = $(slides,_.slider);

				if(!handles){handles = ".handles"}
				_.$handles = $(handles,_.slider);

				_.listen();
				return _;
			},

			swiping: function(e){
				switch(e.type){
					case "dragleft":
					case "dragright":
						_.offset = Math.round(e.gesture.deltaX+_.movement);
						_.direction = e.type;
						_.$slider.css({
							transform:"translateX("+_.offset+"px)"
						});
					break;

					case "release":
						var pos = _.offset;
						if(_.direction == "dragleft"){pos-=100;}
						else{pos+=100;}
						var index = -1 * Math.round(pos/(_.slideWidth + _.slideMargin)),
							min = -((_.count-1) * (_.slideWidth + _.slideMargin)),
							max = 0;

						if(pos < min)index = _.count-1;
						if(pos > max)index = 0;
						_.showSlide(index);
					break;
				}
			},

			next: function(){
				var next = _.activeSlide + 1;
				if(next >= _.count)next=0;
				_.showSlide(next);
			},

			prev: function(){
				var prev = _.activeSlide - 1;
				if(prev <= 0)prev=_.count-1;
				_.showSlide(prev);
			},

			showSlide: function(index){
				var offset = -index*(_.slideWidth + _.slideMargin);
				_.$slider.animate({
					transform:"translateX("+offset+"px)"
				});
				_.movement = offset;
				_.activeSlide = index;

				_.$handles.find("span").removeClass("active").eq(index).addClass("active");
			},

			listen: function(){
				_.$w.resize(function(){
					_.slideWidth = Math.round((_.$w.width()-(_.sliderMargin * 2)) * _.showPercent);
					_.$slides.css("width",_.slideWidth);
				});
				_.$w.trigger("resize");

				_.$slider.hammer({drag_lock_to_axis: true}).on("release dragleft dragright swipeleft swiperight", _.swiping);
				_.count = _.$slides.length;
				_.$slider.trigger("release");
			}
		}
		return _.init(selector);
	}
})(window,jQuery,jQuery.fn.hammer);
<|endoftext|>


<commit_before>'use strict';

//GetAttribute() returns "boolean" values and will return either "true" or null
describe('Report', function(){
    var _ = require('lodash');

    var Reports = require('../../app/reports/reports-page');
    var Report = require('../../app/report/report-page');
    var reports = new Reports();
    var report, reportName, conceptName;

    it('Should create a new empty report', function(){
        reports.visitPage();
        reportName = 'HelloWorld' + Math.floor((Math.random() * 10) + 1);
        reports.createReport(reportName);
        reports.getCurrentUrl()
        .then(function(url){
            var id = _.last(url.split('/'));
            report = new Report(id);
            report.visitPage();
            expect(report.searchBox.isPresent()).toBe(true);
            expect(report.label.getText()).toBe(reportName);
        });
    });

    it('Shouldn\'t create a new concept with an invalid name', function(){
        conceptName = 'hello World';
        var concepts = report.taxonomy.concepts;
        concepts.visitPage();
        concepts.createConcept(conceptName);
        expect(concepts.errorMessage.isDisplayed()).toBe(true);
        expect(concepts.errorMessage.getText()).toBe('Invalid Concept Name');
    });

    it('Should create a new concept (1)', function(){
        conceptName = 'h:helloWorldID';
        var concepts = report.taxonomy.concepts;
        concepts.visitPage();
        concepts.createConcept(conceptName);
    });

    it('Should create a new concept (2)', function(){
        conceptName = 'h:assets';
        var concepts = report.taxonomy.concepts;
        concepts.visitPage();
        concepts.createConcept(conceptName);
    });

    it('Creates a new element', function(){
        report.taxonomy.getConcept(conceptName).createElement();
        expect(report.taxonomy.elements.count()).toBe(1);
    });

    it('Renames the concept label', function(){
        var overview = report.taxonomy.getConcept(conceptName).getOverview();
        overview.visitPage();
        expect(overview.form.conceptLabel.getAttribute('value')).toBe('Assets');
        overview.changeLabel('Assets Label');
        expect(overview.form.conceptLabel.getAttribute('value')).toBe('Assets Label');
    });

    it('Creates a us-gaap:Assets synonym', function(){
        var synonyms = report.taxonomy.getConcept(conceptName).getSynonyms();
        synonyms.visitPage();
        expect(synonyms.list.count()).toBe(0);
        synonyms.addSynonym('us-gaap:Assets');
        synonyms.addSynonym('us-gaap:AssetsCurrent');
        synonyms.addSynonym('us-gaap:AssetsCurrent');
        expect(synonyms.list.count()).toBe(2);
        expect(synonyms.getName(synonyms.list.first())).toBe('us-gaap:Assets');
        expect(synonyms.getName(synonyms.list.last())).toBe('us-gaap:AssetsCurrent');
    });

    it('Should display the fact table', function() {
        report.filters.visitPage();
        report.facts.visitPage();
        expect(report.facts.lineCount()).toBeGreaterThan(0);
    });

    it('Should display the preview', function() {
        report.spreadsheet.visitPage();
        expect(report.spreadsheet.getCellValueByCss('.first-row-header-row > td > span')).toBe('Assets Label');
    });

    it('Should delete report', function() {
        reports.visitPage();
        reports.list.count().then(function(count){
            reports.deleteReport(reportName).then(function(){
                expect(reports.list.count()).toBe(count - 1);
            });
        });
    });
});
<commit_msg>Add test for fix #86<commit_after>'use strict';

//GetAttribute() returns "boolean" values and will return either "true" or null
describe('Report', function(){
    var _ = require('lodash');

    var Reports = require('../../app/reports/reports-page');
    var Report = require('../../app/report/report-page');
    var reports = new Reports();
    var report, reportName, conceptName;

    it('Should create a new empty report', function(){
        reports.visitPage();
        reportName = 'HelloWorld' + Math.floor((Math.random() * 10) + 1);
        reports.createReport(reportName);
        reports.getCurrentUrl()
        .then(function(url){
            var id = _.last(url.split('/'));
            report = new Report(id);
            report.visitPage();
            expect(report.searchBox.isPresent()).toBe(true);
            expect(report.label.getText()).toBe(reportName);
        });
    });

    it('Shouldn\'t create a new concept with an invalid name', function(){
        conceptName = 'hello World';
        var concepts = report.taxonomy.concepts;
        concepts.visitPage();
        concepts.createConcept(conceptName);
        expect(concepts.errorMessage.isDisplayed()).toBe(true);
        expect(concepts.errorMessage.getText()).toBe('Invalid Concept Name');
    });

    it('Should create a new concept (1)', function(){
        conceptName = 'h:helloWorldID';
        var concepts = report.taxonomy.concepts;
        concepts.visitPage();
        concepts.createConcept(conceptName);
    });

    it('Should create a new concept (2)', function(){
        conceptName = 'h:assets';
        var concepts = report.taxonomy.concepts;
        concepts.visitPage();
        concepts.createConcept(conceptName);
    });

    it('Creates a new element', function(){
        report.taxonomy.getConcept(conceptName).createElement();
        expect(report.taxonomy.elements.count()).toBe(1);
    });

    it('Renames the concept label', function(){
        var overview = report.taxonomy.getConcept(conceptName).getOverview();
        overview.visitPage();
        expect(overview.form.conceptLabel.getAttribute('value')).toBe('Assets');
        overview.changeLabel('Assets Label');
        expect(overview.form.conceptLabel.getAttribute('value')).toBe('Assets Label');
    });

    it('Creates a us-gaap:Assets synonym', function(){
        var synonyms = report.taxonomy.getConcept(conceptName).getSynonyms();
        synonyms.visitPage();
        expect(synonyms.list.count()).toBe(0);
        synonyms.addSynonym('us-gaap:Assets');
        synonyms.addSynonym('us-gaap:AssetsCurrent');
        synonyms.addSynonym('us-gaap:AssetsCurrent');
        expect(synonyms.list.count()).toBe(2);
        expect(synonyms.getName(synonyms.list.first())).toBe('us-gaap:Assets');
        expect(synonyms.getName(synonyms.list.last())).toBe('us-gaap:AssetsCurrent');
    });

    it('Should display the fact table', function() {
        report.facts.visitPage();
        expect(report.facts.lineCount()).toBeGreaterThan(0);
    });

    it('Should display the preview', function() {
        report.spreadsheet.visitPage();
        expect(report.spreadsheet.getCellValueByCss('.first-row-header-row > td > span')).toBe('Assets Label');
    });

    it('Should delete report', function() {
        reports.visitPage();
        reports.list.count().then(function(count){
            reports.deleteReport(reportName).then(function(){
                expect(reports.list.count()).toBe(count - 1);
            });
        });
    });
});
<|endoftext|>


<commit_before>"use strict";

// you can use: drawLine(ctx, x1, y1, x2, y2);
// you can use: drawLine(ctx, x1, y1, x2, y2);
// you can use: drawCircle(ctx, x, y, radius);

// Export only these methods
var drawCurve, drawConstruction, drawBezierNodes;

(function () {

    function calcBspline(t, nodes, knots) {
        var k = 0;
        for (var l = 3; l < (knots.length - 2); l++) {
            if (knots[l].val() >= t) break;
            k++;
        }
        var u1 = knots[k + 0].val();
        var u2 = knots[k + 1].val();
        var u3 = knots[k + 2].val();
        var u4 = knots[k + 3].val();
        var u5 = knots[k + 4].val();
        var u6 = knots[k + 5].val();

        var p10 = nodes[k + 0].pos();
        var p20 = nodes[k + 1].pos();
        var p30 = nodes[k + 2].pos();
        var p40 = nodes[k + 3].pos();

        var p21 = p10.multiply((u4 - t) / (u4 - u1)).add(p20.multiply((t - u1) / (u4 - u1)));
        var p31 = p20.multiply((u5 - t) / (u5 - u2)).add(p30.multiply((t - u2) / (u5 - u2)));
        var p41 = p30.multiply((u6 - t) / (u6 - u3)).add(p40.multiply((t - u3) / (u6 - u3)));

        var p32 = p21.multiply((u4 - t) / (u4 - u2)).add(p31.multiply((t - u2) / (u4 - u2)));
        var p42 = p31.multiply((u5 - t) / (u5 - u3)).add(p41.multiply((t - u3) / (u5 - u3)));

        return p32.multiply((u4 - t) / (u4 - u3)).add(p42.multiply((t - u3) / (u4 - u3)));
    }

    drawCurve = function (ctx, curve) {
        if (curve.nodes.length < 4) return;

        var lknot = curve.knots[2].val();
        var rknot = curve.knots[curve.knots.length - 3].val();

        var samples = 1000;
        var l = calcBspline(lknot, curve.nodes, curve.knots);

        for (var i = 1; i < samples; i++) {
            var t = lknot + (rknot - lknot) / samples * i;
            var r = calcBspline(t, curve.nodes, curve.knots);
            drawLine(ctx, l.x, l.y, r.x, r.y);
            l = r;
        }
    };

    drawConstruction = function (ctx, curve) {
        var n = curve.nodes.length;
        var m = curve.knots.length;
        var t = curve.timeKnot.val();
        var k = 0;
        for (var l = 3; l < (m - 2); l++) {
            if (curve.knots[l].val() >= t) {
                break;
            }
            k++;
        }

        if (t >= curve.knots[2].val() && t < curve.knots[m - 3].val()) {
            var u1 = curve.knots[k + 0].val();
            var u2 = curve.knots[k + 1].val();
            var u3 = curve.knots[k + 2].val();
            var u4 = curve.knots[k + 3].val();
            var u5 = curve.knots[k + 4].val();
            var u6 = curve.knots[k + 5].val();

            var p10 = curve.nodes[k + 0].pos();
            var p20 = curve.nodes[k + 1].pos();
            var p30 = curve.nodes[k + 2].pos();
            var p40 = curve.nodes[k + 3].pos();

            setColors(ctx, 'yellow', 'cyan');
            drawCircle(ctx, p10.x, p10.y, 4);
            drawCircle(ctx, p20.x, p20.y, 4);
            drawCircle(ctx, p30.x, p30.y, 4);
            drawCircle(ctx, p40.x, p40.y, 4);
            drawLine(ctx, p10.x, p10.y, p20.x, p20.y);
            drawLine(ctx, p20.x, p20.y, p30.x, p30.y);
            drawLine(ctx, p30.x, p30.y, p40.x, p40.y);

            var p21 = p10.multiply((u4 - t) / (u4 - u1)).add(p20.multiply((t - u1) / (u4 - u1)));
            var p31 = p20.multiply((u5 - t) / (u5 - u2)).add(p30.multiply((t - u2) / (u5 - u2)));
            var p41 = p30.multiply((u6 - t) / (u6 - u3)).add(p20.multiply((t - u3) / (u6 - u3)));

            setColors(ctx, 'red', 'orange');
            drawCircle(ctx, p21.x, p21.y, 3);
            drawCircle(ctx, p31.x, p31.y, 3);
            drawCircle(ctx, p41.x, p41.y, 3);
            drawLine(ctx, p21.x, p21.y, p31.x, p31.y);
            drawLine(ctx, p31.x, p31.y, p41.x, p41.y);

            var p32 = p21.multiply((u4 - t) / (u4 - u2)).add(p31.multiply((t - u2) / (u4 - u2)));
            var p42 = p31.multiply((u5 - t) / (u5 - u3)).add(p41.multiply((t - u3) / (u5 - u3)));
            setColors(ctx, 'violet', 'pink');
            drawCircle(ctx, p32.x, p32.y, 2);
            drawCircle(ctx, p42.x, p42.y, 2);
            drawLine(ctx, p32.x, p32.y, p42.x, p42.y);

            var p43 = p32.multiply((u4 - t) / (u4 - u3)).add(p42.multiply((t - u3) / (u4 - u3)));
            setColors(ctx, 'green', 'darkgreen');
            drawCircle(ctx, p43.x, p43.y, 4);
        }
    };

    drawBezierNodes = function (ctx, curve) {
        // TODO: implement this
    };

})();
<commit_msg>construction<commit_after>"use strict";

// you can use: drawLine(ctx, x1, y1, x2, y2);
// you can use: drawLine(ctx, x1, y1, x2, y2);
// you can use: drawCircle(ctx, x, y, radius);

// Export only these methods
var drawCurve, drawConstruction, drawBezierNodes;

(function () {

    function calcBspline(t, nodes, knots) {
        var k = 0;
        for (var l = 3; l < (knots.length - 2); l++) {
            if (knots[l].val() >= t) break;
            k++;
        }
        var u1 = knots[k + 0].val();
        var u2 = knots[k + 1].val();
        var u3 = knots[k + 2].val();
        var u4 = knots[k + 3].val();
        var u5 = knots[k + 4].val();
        var u6 = knots[k + 5].val();

        var p10 = nodes[k + 0].pos();
        var p20 = nodes[k + 1].pos();
        var p30 = nodes[k + 2].pos();
        var p40 = nodes[k + 3].pos();

        var p21 = p10.multiply((u4 - t) / (u4 - u1)).add(p20.multiply((t - u1) / (u4 - u1)));
        var p31 = p20.multiply((u5 - t) / (u5 - u2)).add(p30.multiply((t - u2) / (u5 - u2)));
        var p41 = p30.multiply((u6 - t) / (u6 - u3)).add(p40.multiply((t - u3) / (u6 - u3)));

        var p32 = p21.multiply((u4 - t) / (u4 - u2)).add(p31.multiply((t - u2) / (u4 - u2)));
        var p42 = p31.multiply((u5 - t) / (u5 - u3)).add(p41.multiply((t - u3) / (u5 - u3)));

        var p43 = p32.multiply((u4 - t) / (u4 - u3)).add(p42.multiply((t - u3) / (u4 - u3)));
        return  p43;
    }

    drawCurve = function (ctx, curve) {
        if (curve.nodes.length < 4) return;

        var lknot = curve.knots[2].val();
        var rknot = curve.knots[curve.knots.length - 3].val();

        var samples = 1000;
        var l = calcBspline(lknot, curve.nodes, curve.knots);

        for (var i = 1; i < samples; i++) {
            var t = lknot + (rknot - lknot) / samples * i;
            var r = calcBspline(t, curve.nodes, curve.knots);
            drawLine(ctx, l.x, l.y, r.x, r.y);
            l = r;
        }
    };

    drawConstruction = function (ctx, curve) {
        var n = curve.nodes.length;
        var m = curve.knots.length;
        var t = curve.timeKnot.val();
        var k = 0;
        for (var l = 3; l < (m - 2); l++) {
            if (curve.knots[l].val() >= t) {
                break;
            }
            k++;
        }

        if (t >= curve.knots[2].val() && t < curve.knots[m - 3].val()) {
            var u1 = curve.knots[k + 0].val();
            var u2 = curve.knots[k + 1].val();
            var u3 = curve.knots[k + 2].val();
            var u4 = curve.knots[k + 3].val();
            var u5 = curve.knots[k + 4].val();
            var u6 = curve.knots[k + 5].val();

            var p10 = curve.nodes[k + 0].pos();
            var p20 = curve.nodes[k + 1].pos();
            var p30 = curve.nodes[k + 2].pos();
            var p40 = curve.nodes[k + 3].pos();

            setColors(ctx, 'yellow', 'cyan');
            drawCircle(ctx, p10.x, p10.y, 4);
            drawCircle(ctx, p20.x, p20.y, 4);
            drawCircle(ctx, p30.x, p30.y, 4);
            drawCircle(ctx, p40.x, p40.y, 4);
            drawLine(ctx, p10.x, p10.y, p20.x, p20.y);
            drawLine(ctx, p20.x, p20.y, p30.x, p30.y);
            drawLine(ctx, p30.x, p30.y, p40.x, p40.y);

            var p21 = p10.multiply((u4 - t) / (u4 - u1)).add(p20.multiply((t - u1) / (u4 - u1)));
            var p31 = p20.multiply((u5 - t) / (u5 - u2)).add(p30.multiply((t - u2) / (u5 - u2)));
            var p41 = p30.multiply((u6 - t) / (u6 - u3)).add(p40.multiply((t - u3) / (u6 - u3)));

            setColors(ctx, 'red', 'orange');
            drawCircle(ctx, p21.x, p21.y, 3);
            drawCircle(ctx, p31.x, p31.y, 3);
            drawCircle(ctx, p41.x, p41.y, 3);
            drawLine(ctx, p21.x, p21.y, p31.x, p31.y);
            drawLine(ctx, p31.x, p31.y, p41.x, p41.y);

            var p32 = p21.multiply((u4 - t) / (u4 - u2)).add(p31.multiply((t - u2) / (u4 - u2)));
            var p42 = p31.multiply((u5 - t) / (u5 - u3)).add(p41.multiply((t - u3) / (u5 - u3)));

            setColors(ctx, 'violet', 'pink');
            drawCircle(ctx, p32.x, p32.y, 2);
            drawCircle(ctx, p42.x, p42.y, 2);
            drawLine(ctx, p32.x, p32.y, p42.x, p42.y);

            var p43 = p32.multiply((u4 - t) / (u4 - u3)).add(p42.multiply((t - u3) / (u4 - u3)));
            setColors(ctx, 'green', 'darkgreen');
            drawCircle(ctx, p43.x, p43.y, 4);
        }
    };

    drawBezierNodes = function (ctx, curve) {
        // TODO: implement this
    };

})();
<|endoftext|>


<commit_before>/**
 * @fileoverview Tests for no-empty rule.
 * @author Nicholas C. Zakas
 */

/*jshint node:true*/

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

var vows = require("vows"),
    assert = require("assert"),
    sinon = require("sinon"),
    jscheck = require("../../../lib/jscheck");

//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------

var RULE_ID = "no-empty";

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

vows.describe(RULE_ID).addBatch({

    "when evaluating 'if (foo) {}'": {

        topic: "if (foo) {}",

        "should report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 1);
            assert.equal(messages[0].ruleId, RULE_ID);
            assert.equal(messages[0].message, "Empty block statement.");
            assert.include(messages[0].node.type, "BlockStatement");
        }
    },

    "when evaluating 'if (foo) { bar() }'": {

        topic: "if (foo) { bar() }",

        "should not report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 0);
        }
    },

    "when evaluating 'while (foo) {}'": {

        topic: "while (foo) {}",

        "should report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 1);
            assert.equal(messages[0].ruleId, RULE_ID);
            assert.equal(messages[0].message, "Empty block statement.");
            assert.include(messages[0].node.type, "BlockStatement");
        }
    },

    "when evaluating 'while (foo) { bar() }'": {

        topic: "while (foo) { bar() }",

        "should not report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 0);
        }
    },

    "when evaluating 'for (;foo;) {}'": {

        topic: "for (;foo;) {}",

        "should report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 1);
            assert.equal(messages[0].ruleId, RULE_ID);
            assert.equal(messages[0].message, "Empty block statement.");
            assert.include(messages[0].node.type, "BlockStatement");
        }
    },

    "when evaluating 'for (;foo;) { bar() }'": {

        topic: "for (;foo;) { bar() }",

        "should not report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 0);
        }
    }

}).export(module);
<commit_msg>Added more tests no-empty<commit_after>/**
 * @fileoverview Tests for no-empty rule.
 * @author Nicholas C. Zakas
 */

/*jshint node:true*/

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

var vows = require("vows"),
    assert = require("assert"),
    sinon = require("sinon"),
    jscheck = require("../../../lib/jscheck");

//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------

var RULE_ID = "no-empty";

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

vows.describe(RULE_ID).addBatch({

    "when evaluating 'if (foo) {}'": {

        topic: "if (foo) {}",

        "should report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 1);
            assert.equal(messages[0].ruleId, RULE_ID);
            assert.equal(messages[0].message, "Empty block statement.");
            assert.include(messages[0].node.type, "BlockStatement");
        }
    },

    "when evaluating 'if (foo) { bar() }'": {

        topic: "if (foo) { bar() }",

        "should not report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 0);
        }
    },

    "when evaluating 'while (foo) {}'": {

        topic: "while (foo) {}",

        "should report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 1);
            assert.equal(messages[0].ruleId, RULE_ID);
            assert.equal(messages[0].message, "Empty block statement.");
            assert.include(messages[0].node.type, "BlockStatement");
        }
    },

    "when evaluating 'while (foo) { bar() }'": {

        topic: "while (foo) { bar() }",

        "should not report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 0);
        }
    },

    "when evaluating 'for (;foo;) {}'": {

        topic: "for (;foo;) {}",

        "should report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 1);
            assert.equal(messages[0].ruleId, RULE_ID);
            assert.equal(messages[0].message, "Empty block statement.");
            assert.include(messages[0].node.type, "BlockStatement");
        }
    },

    "when evaluating 'for (;foo;) { bar() }'": {

        topic: "for (;foo;) { bar() }",

        "should not report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 0);
        }
    },

    "when evaluating 'try {} catch (ex) {}'": {

        topic: "try {} catch (ex) {}",

        "should report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 2);
            assert.equal(messages[0].ruleId, RULE_ID);
            assert.equal(messages[0].message, "Empty block statement.");
            assert.include(messages[0].node.type, "BlockStatement");
            assert.equal(messages[1].ruleId, RULE_ID);
            assert.equal(messages[1].message, "Empty block statement.");
            assert.include(messages[1].node.type, "BlockStatement");
        }
    },

    "when evaluating 'try { foo() } catch (ex) {}'": {

        topic: "try { foo() } catch (ex) {}",

        "should report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 1);
            assert.equal(messages[0].ruleId, RULE_ID);
            assert.equal(messages[0].message, "Empty block statement.");
            assert.include(messages[0].node.type, "BlockStatement");
        }
    },

    "when evaluating 'try { foo() } catch (ex) { foo() }'": {

        topic: "try { foo() } catch (ex) { foo() }",

        "should not report a violation": function(topic) {
            var config = { rules: {} };
            config.rules[RULE_ID] = 1;

            var messages = jscheck.verify(topic, config);

            assert.equal(messages.length, 0);
        }
    }

}).export(module);
<|endoftext|>


<commit_before>'use strict';

/* global describe, beforeEach, it, expect */
/* global element, by, browser */

describe('pattyApp', function() {

  beforeEach(function() {
    browser.get('index.html');
  });

  it('should have a title', function() {
    expect(browser.getTitle()).toMatch('AHN2 pointcloud viewer');
  });

  describe('initial state', function() {
    it('should have Welcome dialog shown', function() {
      var results = element(by.css('help-modal-directive'));
      expect(results.isDisplayed()).toBeFalsy();
    });
  });

  describe('closed welcome dialog', function() {
    beforeEach(function() {
      element(by.css('help-modal-directive .glyphicon-remove')).click();
      browser.sleep(200);
    });

    it('should have zero search results', function() {
      expect(element.all(by.css('.search-result')).count()).toBe(0);
    });

    it('should not show settings panel', function() {
      var panel = element(by.css('.settings-panel'));
      expect(panel.isDisplayed()).toBeFalsy();
    });

    it('should not show tools', function() {
      var panel = element(by.css('.toolbox-tools'));
      expect(panel.isDisplayed()).toBeFalsy();
    });

    it('should hide the clear button', function() {
      var results = element(by.css('patty-search-panel .glyphicon-remove'));
      expect(results.isDisplayed()).toBeFalsy();
    });

    describe('searched on "roosendaal"', function() {
      beforeEach(function() {
        element(by.model('sp.query')).sendKeys('roosendaal');
      });

      it('should show the clear button', function() {
        var results = element(by.css('patty-search-panel .glyphicon-remove'));
        expect(results.isDisplayed()).toBeTruthy();
      });
    });

    describe('click on extract icon', function() {
      beforeEach(function() {
        element(by.css('.icon-big.extract-icon')).click();
      });

      it('should show extract panel', function() {
        var panel = element(by.css('.extract-panel'));
        expect(panel.isDisplayed()).toBeTruthy();
      });
    });

    describe('click on settings gear', function() {
      beforeEach(function() {
        element(by.css('.icon-big.gear-icon')).click();
      });

      it('should show settings panel', function() {
        var panel = element(by.css('.settings-panel'));
        expect(panel.isDisplayed()).toBeTruthy();
      });
    });

    describe('click on help icon', function() {
      beforeEach(function() {
        element(by.css('.icon-big.help-icon')).click();
      });

      it('should show help panel', function() {
        var panel = element(by.css('.help-panel'));
        expect(panel.isDisplayed()).toBeTruthy();
      });
    });

    describe('clicking on toolbox icon', function() {
      beforeEach(function() {
        element(by.css('.icon-big.toolbox-icon')).click();
      });

      it('should show tools', function() {
        var panel = element(by.css('.toolbox-tools'));
        expect(panel.isDisplayed()).toBeTruthy();
      });

      describe('and then clicking on bottom toolbox icon', function() {

        beforeEach(function() {
          element(by.css('.icon-big.toolbox-icon')).click();
          // wait for toolbox to close, otherwise it will still be displayed partly
          browser.sleep(200);
        });

        it('should hide tools', function() {
          var panel = element(by.css('.toolbox-tools'));
          expect(panel.isDisplayed()).toBeFalsy();
        });
      });

      describe('and then clicking on top toolbox icon', function() {

        beforeEach(function() {
          // wait for toolbox to open, otherwise icon is moving when click is attempted
          browser.sleep(500);
          element(by.css('.icon-big.toolbox-tray-top-icon')).click();
          // wait for toolbox to close, otherwise it will still be displayed partly
          browser.sleep(200);
        });

        it('should hide tools', function() {
          var panel = element(by.css('.toolbox-tools'));
          expect(panel.isDisplayed()).toBeFalsy();
        });
      });
    });

  });

});
<commit_msg>Fixed more e2e tests<commit_after>'use strict';

/* global describe, beforeEach, it, expect */
/* global element, by, browser */

describe('pattyApp', function() {

  beforeEach(function() {
    browser.get('index.html');
  });

  it('should have a title', function() {
    expect(browser.getTitle()).toMatch('AHN2 pointcloud viewer');
  });

  describe('initial state', function() {
    it('should have Welcome dialog shown', function() {
      var results = element(by.css('help-modal-directive'));
      expect(results.isDisplayed()).toBeTruthy();
    });
  });

  describe('closed welcome dialog', function() {
    beforeEach(function() {
      element(by.css('help-modal-directive .glyphicon-remove')).click();
      browser.sleep(200);
    });

    it('should have zero search results', function() {
      expect(element.all(by.css('.search-result')).count()).toBe(0);
    });

    it('should not show settings panel', function() {
      var panel = element(by.css('.settings-panel'));
      expect(panel.isDisplayed()).toBeFalsy();
    });

    it('should not show tools', function() {
      var panel = element(by.css('.toolbox-tools'));
      expect(panel.isDisplayed()).toBeFalsy();
    });

    it('should hide the clear button', function() {
      var results = element(by.css('patty-search-panel .glyphicon-remove'));
      expect(results.isDisplayed()).toBeFalsy();
    });

    describe('searched on "roosendaal"', function() {
      beforeEach(function() {
        element(by.model('sp.query')).sendKeys('roosendaal');
      });

      it('should show the clear button', function() {
        var results = element(by.css('patty-search-panel .glyphicon-remove'));
        expect(results.isDisplayed()).toBeTruthy();
      });
    });

    describe('click on extract icon', function() {
      beforeEach(function() {
        element(by.css('.icon-big.extract-icon')).click();
      });

      it('should show extract panel', function() {
        var panel = element(by.css('.extract-panel'));
        expect(panel.isDisplayed()).toBeTruthy();
      });
    });

    describe('click on settings gear', function() {
      beforeEach(function() {
        element(by.css('.icon-big.gear-icon')).click();
        browser.sleep(200);
      });

      it('should show settings panel', function() {
        var panel = element(by.css('.settings-panel'));
        expect(panel.isDisplayed()).toBeTruthy();
      });
    });

    describe('click on help icon', function() {
      beforeEach(function() {
        element(by.css('.icon-big.help-icon')).click();
      });

      it('should show help panel', function() {
        var panel = element(by.css('help-modal-directive'));
        expect(panel.isDisplayed()).toBeTruthy();
      });
    });

    describe('clicking on toolbox icon', function() {
      beforeEach(function() {
        element(by.css('.icon-big.toolbox-icon')).click();
        browser.sleep(200);
      });

      describe('and then clicking on top toolbox icon', function() {

        beforeEach(function() {
          // wait for toolbox to open, otherwise icon is moving when click is attempted
          browser.sleep(500);
          element(by.css('.icon-big.toolbox-tray-top-icon')).click();
          // wait for toolbox to close, otherwise it will still be displayed partly
          browser.sleep(200);
        });

        it('should hide tools', function() {
          var panel = element(by.css('.toolbox-tools'));
          expect(panel.isDisplayed()).toBeFalsy();
        });
      });
    });

  });

});
<|endoftext|>


<commit_before>function stringToNumber(str, charset) {
	var len 		= str.length;
	var charset_len = charset.length;
	var ret 		= 0;

	for(var i = 0; i < len; i++) {
		var power 		= len - (i + 1);
		var chr 		= str.charAt(i);
		var chrIndex 	= 1 + charset.indexOf(chr);
		ret += chrIndex * Math.pow(charset_len, power);
	}

	return ret;
}

function numberToString(nbr, charset) {
	if(nbr == 1)
		return charset.charAt(0);

	var charset_len 	= charset.length;
	var str_len  		= 0;
	var str_this_len 	= 0;
	var tmp;

	for(var maxpower = 5; maxpower >= 0; maxpower--) {
		var maxvalue = Math.pow(charset_len, maxpower);
		for(tmp = maxpower - 1; tmp >= 1; tmp--) {
			maxvalue += Math.pow(charset_len, tmp);
		}

		if(maxvalue < nbr) {
			str_len  	 = maxpower + 1;
			str_this_len = (maxvalue + Math.pow(charset_len, maxpower + 1)) - maxvalue;

			break;
		}
	}

	if(str_len === 0)
		return null;

	var str = '';
	while(--str_len >= 0) {
		if(str_len === 0) {
			str += charset.charAt(nbr - 1);
			break;
		}

		str_this_len = Math.pow(charset_len, str_len);
		var initial = 0;
		for(tmp = str_len - 1; tmp >= 1; tmp--) {
			initial += Math.pow(charset_len, tmp);
		}
		for(tmp = charset_len; tmp >= 1; tmp--) {
			var tmp_cmp = initial + (tmp * str_this_len);
			if(tmp_cmp < nbr)
				break;
		}

		nbr -= tmp * str_this_len;
		str += charset.charAt(tmp - 1);
	}

	return str;
}

module.exports.numberToString = numberToString;
module.exports.stringToNumber = stringToNumber;<commit_msg>trying to please bithound<commit_after>function sumOfPowerFromOne(base, maxpower) {
	var value = 0;
	for(var tmp = maxpower; tmp >= 1; tmp--) {
		value += Math.pow(base, tmp);
	}
	return value;
}

module.exports.stringToNumber = function(str, charset) {
	var len 		= str.length;
	var charset_len = charset.length;
	var ret 		= 0;

	for(var i = 0; i < len; i++) {
		var power 		= len - (i + 1);
		var chr 		= str.charAt(i);
		var chrIndex 	= 1 + charset.indexOf(chr);
		ret += chrIndex * Math.pow(charset_len, power);
	}

	return ret;
}

module.exports.numberToString = function(nbr, charset) {
	var charset_len 	= charset.length;
	var str_len  		= 0;
	var str_this_len 	= 0;
	var tmp;

	for(var maxpower = 20; maxpower >= 0; maxpower--) {
		var maxvalue = sumOfPowerFromOne(charset_len, maxpower);

		if(maxvalue < nbr) {
			str_len  	 = maxpower + 1;
			str_this_len = (maxvalue + Math.pow(charset_len, maxpower + 1)) - maxvalue;

			break;
		}
	}

	if(str_len === 0)
		return null;

	var str = '';
	while(--str_len >= 0) {
		if(str_len === 0) {
			str += charset.charAt(nbr - 1);
			break;
		}

		str_this_len = Math.pow(charset_len, str_len);
		var initial = sumOfPowerFromOne(charset_len, str_len - 1);

		for(tmp = charset_len; tmp >= 1; tmp--) {
			var tmp_cmp = initial + (tmp * str_this_len);
			if(tmp_cmp < nbr)
				break;
		}

		nbr -= tmp * str_this_len;
		str += charset.charAt(tmp - 1);
	}

	return str;
}<|endoftext|>


<commit_before>//'use strict';

(function (){
var pk = {};
//to not clutter global namespace. pk picks the rags ;)

function scope_gen(n){
    // for normal sudoku latin square, n is 3
    // a latin square has n^4 cells
   var i, j, r, c, gr, gc, l, p;
   var out = [];

   l=n*n*n*n;
   /* malloc from stdlib.h */
   for (i=0;i<l;i++) {
      var scope = new Array(l);
      r=Math.floor(i/(n*n));
      c=i%(n*n);
      gr=Math.floor(r/n)*n;
      gc=Math.floor(c/n)*n;
      for (j=0; j<n*n; j++) {
         scope[r*n*n+j]=true;
         scope[j*n*n+c]=true;
         scope[(gr+Math.floor(j/n))*n*n+gc+j%n]=true;
      }
      scope[i]=false;
      var eye = [];
      for(j=0; j<l; j++) if (scope[j]) {eye.push(j);}
      out.push(eye);
   }
   return out;
}

//the cell class
pk.cell = function (i) {
    //cell object constructor
    if (i) {
        if (typeof i === "object") {
            this.v = i.v;
        } else {
            var idea = i - 1;
            if ((idea < 9) && (idea >= 0)) {
                this.putIdea(idea);
            } else {
                this.v = 0x7fe7;
            }
        }
    } else {
        this.v = 0x7fe7;
    }
};
pk.cell.prototype.putIdea = function (idea) {
    this.v = (idea | pk.open | pk.may_b[idea]);
};
pk.cell.prototype.copyIn = function (i) {
    this.v = i.v;
};
pk.cell.prototype.txt = function () {
    return this.v.toString();
};
pk.cell.prototype.yo = function (mask) {
    return ((this.v & mask) !== 0);
};
pk.cell.prototype.reset = function (mask) { //reset the mask
    this.v &= ~mask;
};
pk.cell.prototype.value = function () { //value of an open or filled cell
    return (this.v & pk.data);
};
pk.cell.prototype.rm = function (i) { // returns success or failure (false or true respectively)
    if (this.yo(pk.may_b[i])) { //has it in probable
        if (!this.yo(pk.wait)) {
            return true; // it is the only probable!!
        }
        this.reset(pk.may_b[i]);
        this.v -= 1;
        if (this.yo(pk.open)) { // only one probable left now
            for (i = 0; i < 9; i += 1) {
                if (this.yo(pk.may_b[i])) {
                    break;
                }
            }
            this.putIdea(i);
        }
    }
    return false; //removed ok
};
pk.cell.prototype.trial = function (i) { // returns trial value or >=9 if no trial available
    for (;i < 9;i += 1) {
        if (this.yo(pk.may_b[i])) {
            break;
        }
    }
    return i;
};

//the package globals
pk.wait = 0x20;
pk.open = 0x10;
pk.data = 0xf;
pk.may_b = [
    0x4000, 0x2000, 0x1000,
    0x0800, 0x0400, 0x0200,
    0x0100, 0x0080, 0x0040
];
pk.clr =  scope_gen(3);

//the sud class. models a sudoku
pk.sud = function (inp) {
    if (inp) {
        if (typeof inp === "object") {
            this.left = inp.left;
            this.i_v = [];
            for (var i = 0; i < 81; i += 1) {
                this.i_v[i] = new pk.cell(inp.i_v[i]);
            }
            return;
        } else inp = inp.toString()
    } else inp = '123456789'
    var len = inp.length
    this.left = 81
    this.i_v = []
    var i = 0
    for (; i < len && i < 81; i += 1) {
        this.i_v[i] = new pk.cell(inp.charAt(i))
    }
    for (; i < 81; i += 1) this.i_v[i] = new pk.cell()
    arguments.callee.__out__ = []
}
pk.sud.prototype.copyIn = function (t) {
    this.left = t.left;
    for (var i = 0; i < 81; i += 1) this.i_v[i].copyIn(t.i_v[i]);
}
pk.sud.prototype.first = function () {
    // first waiting cell or >=81; for ordered listing of solutions
    var i = 0
    for (; i < 81; i += 1) {
        if (this.i_v[i].yo(pk.wait)) {
            break;
        }
    }
    return i
}
pk.sud.prototype.idea = function () {
    //first open cell or >=81
    var i = 0
    for (; i < 81; i += 1) {
        if (this.i_v[i].yo(pk.open)) {
            break
        }
    }
    return i
}
pk.sud.prototype.toString = function () {
    var buf = ''
    for (var i = 0; i < 81; i += 1) {
        if (this.i_v[i].yo(pk.cell.open)) {
            buf += '?';
        } else {
            buf += (1 + this.i_v[i].value());
        }
    }
    return buf;
}
pk.sud.prototype.hook = function () {
    // returns { wrong, stale, solved, dumping } = -1, 0, 1, 2
    var x, pos, val
    while ((pos = this.idea()) < 81) {
        val = this.i_v[pos].value()
        for (x = 0; x < 20; x += 1) {
            if (this.i_v[pk.clr[pos][x]].rm(val)) {
                return -1;
            }
        }
        this.i_v[pos].reset(pk.open)
        if ((this.left -= 1) === 0) {
            this.constructor.__out__.push(this.toString())
            return this.constructor.__out__.length === this.constructor.__n__ ? 2 : 1;
        }
    }
    return 0
}
pk.sud.prototype.crook = function () {
    var mc, cc, pos, val = 0
    var copy = new pk.sud(this)
    if ((pos = this.first()) < 81) {
        mc = this.i_v[pos]
        cc = copy.i_v[pos]
    } else return 1
    while ((val = mc.trial(val)) < 9) {
        copy.copyIn(this)
        cc.putIdea(val)
        switch (copy.squash()) {
            case 1:
                val += 1
                break
            case 2:
                return 2
            case -1:
                mc.rm(val) // should i check?
                if (((pos = this.idea()) < 81) && (this.i_v[pos].value() > val)) {
                    copy = null
                    return 0
                }
        }
    }
    copy = null
    return 1
}
pk.sud.prototype.squash = function () {
    var ret
    do
        if ((ret = this.hook()) !== 0) return ret;
    while (0 === (ret = this.crook()))
        return ret
}

//the list class. subclass of sud.
//solution lister engine
//an iterator
pk.list = function (inp) {
    // calling superclass constructor
    pk.sud.call(this, inp)
    this.status = function (ls, pos, val) {
        this.l = new pk.list(ls)
        this.p = pos
        this.v = val
    }
    if (typeof inp === 'object') return
    pk.nxt = []
    switch (this.squash()) {
        case -1:
            break
        case 2:
    }
}

// subclass extends superclass
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
pk.list.prototype = Object.create(pk.sud.prototype)
pk.list.prototype.constructor = pk.list

pk.list.prototype.hook = function () {
    // returns { wrong, stale, solved, dumping } = -1, 0, 1, 2
    var x, pos, val
    if (pk.stata) {
        if (pk.stata.length === 0) {
            delete pk.stata
            return 1
        } else return 0
    }
    while ((pos = this.idea()) < 81) {
        val = this.i_v[pos].value()
        for (x = 0; x < 20; x += 1) {
            if (this.i_v[pk.clr[pos][x]].rm(val)) return -1
        } // try removing braces
        this.i_v[pos].reset(pk.open)
        if ((this.left -= 1) === 0) {
            pk.nxt.push(this.toString())
            if (pk.nxt.length === pk.n) {
                pk.stata = [] // i hope empty array is true in js
                return 2
            } else return 1
        }
    }
    return 0
}
pk.list.prototype.crook = function () {
    var mc, cc, pos, val = 0,
        copy
    if (pk.stata) {
        copy = pk.stata.pop();
        mc = this.i_v[copy.p];
        cc = copy.l.i_v[copy.p];
    } else {
        if ((pos = this.first()) >= 81) return 1
        else {
            copy = new this.status(this, pos, 0)
            mc = this.i_v[copy.p]
            cc = copy.l.i_v[copy.p]
        }
    }
    while (pk.stata || ((copy.v = mc.trial(copy.v)) < 9)) {
        if (!pk.stata) {
            copy.l.copyIn(this);
            cc.putIdea(copy.v);
        }
        switch (copy.l.squash()) {
            case 1: copy.v += 1; break;
            case 2: pk.stata.push(copy); return 2;
            case -1: mc.rm(copy.v); /* should i check? */
                if (
                    ((pos = this.idea()) < 81)
                    &&
                    (this.i_v[pos].value() > copy.v)
                ) return 0
        }
    }
    return 1
}
pk.list.prototype.next = function () {
    if (pk.nxt.length === 0) return undefined
    pk.out = pk.nxt
    pk.nxt = []
    this.squash()
    return pk.out
}
pk.list.prototype.hasNext = function () {
    return pk.nxt.length !== 0;
}

//exports
module.exports.iter = function (constraints, n) {
    pk.n = n || 2
    return new pk.list(constraints)
}

module.exports.list = function (constraints, n) {
    var master = new pk.sud(constraints)
    master.constructor.__n__ = n || 2;
    switch (master.squash()) {
        case -1:
            console.log("no solution")
            break
        case 2:
    }
    return master.constructor.__out__
}
})();
/*
TODO:
change pk.nxt pk.out pk.n pk.stata. /pk\.[^.]* /
change /stat/
for class list
use ed
add semicolons to statements
add braces to loop or if/else bodies
use semver.org and publish to npm
*/
<commit_msg>prettify: js-beautify -d -j -w 70<commit_after>//'use strict';
(function () {
    var pk = {};
    //to not clutter global namespace. pk picks the rags ;)
    function scope_gen(n) {
        // for normal sudoku latin square, n is 3
        // a latin square has n^4 cells
        var i, j, r, c, gr, gc, l, p;
        var out = [];
        l = n * n * n * n;
        /* malloc from stdlib.h */
        for (i = 0; i < l; i++) {
            var scope = new Array(l);
            r = Math.floor(i / (n * n));
            c = i % (n * n);
            gr = Math.floor(r / n) * n;
            gc = Math.floor(c / n) * n;
            for (j = 0; j < n * n; j++) {
                scope[r * n * n + j] = true;
                scope[j * n * n + c] = true;
                scope[(gr + Math.floor(j / n)) * n * n + gc + j %
                    n] = true;
            }
            scope[i] = false;
            var eye = [];
            for (j = 0; j < l; j++)
                if (scope[j]) {
                    eye.push(j);
                }
            out.push(eye);
        }
        return out;
    }
    //the cell class
    pk.cell = function (i) {
        //cell object constructor
        if (i) {
            if (typeof i === "object") {
                this.v = i.v;
            } else {
                var idea = i - 1;
                if ((idea < 9) && (idea >= 0)) {
                    this.putIdea(idea);
                } else {
                    this.v = 0x7fe7;
                }
            }
        } else {
            this.v = 0x7fe7;
        }
    };
    pk.cell.prototype.putIdea = function (idea) {
        this.v = (idea | pk.open | pk.may_b[idea]);
    };
    pk.cell.prototype.copyIn = function (i) {
        this.v = i.v;
    };
    pk.cell.prototype.txt = function () {
        return this.v.toString();
    };
    pk.cell.prototype.yo = function (mask) {
        return ((this.v & mask) !== 0);
    };
    pk.cell.prototype.reset = function (mask) { //reset the mask
        this.v &= ~mask;
    };
    pk.cell.prototype.value = function () { //value of an open or filled cell
        return (this.v & pk.data);
    };
    pk.cell.prototype.rm = function (i) { // returns success or failure (false or true respectively)
        if (this.yo(pk.may_b[i])) { //has it in probable
            if (!this.yo(pk.wait)) {
                return true; // it is the only probable!!
            }
            this.reset(pk.may_b[i]);
            this.v -= 1;
            if (this.yo(pk.open)) { // only one probable left now
                for (i = 0; i < 9; i += 1) {
                    if (this.yo(pk.may_b[i])) {
                        break;
                    }
                }
                this.putIdea(i);
            }
        }
        return false; //removed ok
    };
    pk.cell.prototype.trial = function (i) { // returns trial value or >=9 if no trial available
        for (; i < 9; i += 1) {
            if (this.yo(pk.may_b[i])) {
                break;
            }
        }
        return i;
    };
    //the package globals
    pk.wait = 0x20;
    pk.open = 0x10;
    pk.data = 0xf;
    pk.may_b = [
        0x4000, 0x2000, 0x1000,
        0x0800, 0x0400, 0x0200,
        0x0100, 0x0080, 0x0040
    ];
    pk.clr = scope_gen(3);
    //the sud class. models a sudoku
    pk.sud = function (inp) {
        if (inp) {
            if (typeof inp === "object") {
                this.left = inp.left;
                this.i_v = [];
                for (var i = 0; i < 81; i += 1) {
                    this.i_v[i] = new pk.cell(inp.i_v[i]);
                }
                return;
            } else inp = inp.toString()
        } else inp = '123456789'
        var len = inp.length
        this.left = 81
        this.i_v = []
        var i = 0
        for (; i < len && i < 81; i += 1) {
            this.i_v[i] = new pk.cell(inp.charAt(i))
        }
        for (; i < 81; i += 1) this.i_v[i] = new pk.cell()
        arguments.callee.__out__ = []
    }
    pk.sud.prototype.copyIn = function (t) {
        this.left = t.left;
        for (var i = 0; i < 81; i += 1) this.i_v[i].copyIn(t.i_v[
            i]);
    }
    pk.sud.prototype.first = function () {
        // first waiting cell or >=81; for ordered listing of solutions
        var i = 0
        for (; i < 81; i += 1) {
            if (this.i_v[i].yo(pk.wait)) {
                break;
            }
        }
        return i
    }
    pk.sud.prototype.idea = function () {
        //first open cell or >=81
        var i = 0
        for (; i < 81; i += 1) {
            if (this.i_v[i].yo(pk.open)) {
                break
            }
        }
        return i
    }
    pk.sud.prototype.toString = function () {
        var buf = ''
        for (var i = 0; i < 81; i += 1) {
            if (this.i_v[i].yo(pk.cell.open)) {
                buf += '?';
            } else {
                buf += (1 + this.i_v[i].value());
            }
        }
        return buf;
    }
    pk.sud.prototype.hook = function () {
        // returns { wrong, stale, solved, dumping } = -1, 0, 1, 2
        var x, pos, val
        while ((pos = this.idea()) < 81) {
            val = this.i_v[pos].value()
            for (x = 0; x < 20; x += 1) {
                if (this.i_v[pk.clr[pos][x]].rm(val)) {
                    return -1;
                }
            }
            this.i_v[pos].reset(pk.open)
            if ((this.left -= 1) === 0) {
                this.constructor.__out__.push(this.toString())
                return this.constructor.__out__.length === this.constructor
                    .__n__ ? 2 : 1;
            }
        }
        return 0
    }
    pk.sud.prototype.crook = function () {
        var mc, cc, pos, val = 0
        var copy = new pk.sud(this)
        if ((pos = this.first()) < 81) {
            mc = this.i_v[pos]
            cc = copy.i_v[pos]
        } else return 1
        while ((val = mc.trial(val)) < 9) {
            copy.copyIn(this)
            cc.putIdea(val)
            switch (copy.squash()) {
            case 1:
                val += 1
                break
            case 2:
                return 2
            case -1:
                mc.rm(val) // should i check?
                if (((pos = this.idea()) < 81) && (this.i_v[pos].value() >
                    val)) {
                    copy = null
                    return 0
                }
            }
        }
        copy = null
        return 1
    }
    pk.sud.prototype.squash = function () {
        var ret
        do
            if ((ret = this.hook()) !== 0) return ret;
        while (0 === (ret = this.crook())) return ret
    }
    //the list class. subclass of sud.
    //solution lister engine
    //an iterator
    pk.list = function (inp) {
        // calling superclass constructor
        pk.sud.call(this, inp)
        this.status = function (ls, pos, val) {
            this.l = new pk.list(ls)
            this.p = pos
            this.v = val
        }
        if (typeof inp === 'object') return
        pk.nxt = []
        switch (this.squash()) {
        case -1:
            break
        case 2:
        }
    }
    // subclass extends superclass
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
    pk.list.prototype = Object.create(pk.sud.prototype)
    pk.list.prototype.constructor = pk.list
    pk.list.prototype.hook = function () {
        // returns { wrong, stale, solved, dumping } = -1, 0, 1, 2
        var x, pos, val
        if (pk.stata) {
            if (pk.stata.length === 0) {
                delete pk.stata
                return 1
            } else return 0
        }
        while ((pos = this.idea()) < 81) {
            val = this.i_v[pos].value()
            for (x = 0; x < 20; x += 1) {
                if (this.i_v[pk.clr[pos][x]].rm(val)) return -1
            } // try removing braces
            this.i_v[pos].reset(pk.open)
            if ((this.left -= 1) === 0) {
                pk.nxt.push(this.toString())
                if (pk.nxt.length === pk.n) {
                    pk.stata = [] // i hope empty array is true in js
                    return 2
                } else return 1
            }
        }
        return 0
    }
    pk.list.prototype.crook = function () {
        var mc, cc, pos, val = 0,
            copy
        if (pk.stata) {
            copy = pk.stata.pop();
            mc = this.i_v[copy.p];
            cc = copy.l.i_v[copy.p];
        } else {
            if ((pos = this.first()) >= 81) return 1
            else {
                copy = new this.status(this, pos, 0)
                mc = this.i_v[copy.p]
                cc = copy.l.i_v[copy.p]
            }
        }
        while (pk.stata || ((copy.v = mc.trial(copy.v)) < 9)) {
            if (!pk.stata) {
                copy.l.copyIn(this);
                cc.putIdea(copy.v);
            }
            switch (copy.l.squash()) {
            case 1:
                copy.v += 1;
                break;
            case 2:
                pk.stata.push(copy);
                return 2;
            case -1:
                mc.rm(copy.v); /* should i check? */
                if (
                    ((pos = this.idea()) < 81) && (this.i_v[pos].value() >
                        copy.v)) return 0
            }
        }
        return 1
    }
    pk.list.prototype.next = function () {
        if (pk.nxt.length === 0) return undefined
        pk.out = pk.nxt
        pk.nxt = []
        this.squash()
        return pk.out
    }
    pk.list.prototype.hasNext = function () {
        return pk.nxt.length !== 0;
    }
    //exports
    module.exports.iter = function (constraints, n) {
        pk.n = n || 2
        return new pk.list(constraints)
    }
    module.exports.list = function (constraints, n) {
        var master = new pk.sud(constraints)
        master.constructor.__n__ = n || 2;
        switch (master.squash()) {
        case -1:
            console.log("no solution")
            break
        case 2:
        }
        return master.constructor.__out__
    }
})();
/*
TODO:
change pk.nxt pk.out pk.n pk.stata. /pk\.[^.]* /
change /stat/
for class list
use ed
add semicolons to statements
add braces to loop or if/else bodies
use semver.org and publish to npm
*/
<|endoftext|>