<commit_before>
var solve = P(GiacGeneric, function(_, super_) {
	_.klass = ['solve'];
	_.number_of_equations = 1;
	_.ask_initial_guess = false;
	_.helpText = "<<solve <[EXPR]> for <[VARS]>>>\nSolve the expression(s) given (EXPR) for the variable(s) specified in VARS.  Use the 'add another equation' link to solve systems of equations.  When solving for multiple variables, enter as a comma-seperated list.  If an initial guess is requested, enter as a comma-seperated list corresponding to the variable list.\nExample: Solve x^2=4 for x with initial guess 0.2.\nExample: Solve x^2+y=6,x-y^2=-2 for x,y";
	_.savedProperties = ['expectedUnits','approx','factor_expand','outputMode','number_of_equations', 'scoped', 'ask_initial_guess'];

	_.init = function() {
		this.eqFields = [];
		super_.init.call(this);
	}
	_.innerHtml = function() {
		return '<table class="' + css_prefix + 'giac_element"><tbody><tr><td class="' + css_prefix + 'var_store">'
	 	+ '<div class="' + css_prefix + 'focusableItems" data-id="0"><span class="' + css_prefix + 'var_store">' + focusableHTML('MathQuill',  'var_store') + '<span class="equality">&#8801;</span></span>' + focusableHTML('CodeBlock', 'solve') + '</td>'
	 	+ '<td class="' + css_prefix + 'content"><div class="' + css_prefix + 'focusableItems" data-id="0">' + focusableHTML('MathQuill',  'eq0') + helpBlock() + '</div><div><div class="' + css_prefix + 'add_equation ' + css_prefix + 'hide_print">Add another equation</div></div>'
	 	+ '<div class="' + css_prefix + 'focusableItems" data-id="1">for&nbsp;' + focusableHTML('MathQuill',  'var') + '<span class="initial_guess" style="display:none;">&nbsp;with initial guess&nbsp;' + focusableHTML('MathQuill',  'var_guess') + '</span></div>'
	  + '<div class="' + css_prefix + 'focusableItems" data-id="2">using&nbsp;' + focusableHTML('SelectBox',  'solver') + '</div>'
		+ answerSpan() + '</td></tr></tbody></table>';
	}
	_.postInsertHandler = function() {
		this.eqFields[0] = registerFocusable(MathQuill, this, 'eq0', { ghost: 'equation', handlers: {
			enter: this.enterPressed(this),
			blur: this.submissionHandler(this)
		}});
		this.varField = registerFocusable(MathQuill, this, 'var', { ghost: 'variable', handlers: {
			enter: this.enterPressed(this),
			blur: this.submissionHandler(this)
		}});
		this.guessField = registerFocusable(MathQuill, this, 'var_guess', { ghost: '0', handlers: {
			enter: this.enterPressed(this),
			blur: this.submissionHandler(this)
		}});
		this.solver = registerFocusable(SelectBox, this, 'solver', { options: { symbolic: 'Symbolic Solver', newton_solver: 'Newton-Raphson Numeric Solver'}});
		this.eqFields[0].setExpressionMode(true);
		this.command = registerFocusable(CodeBlock, this, 'solve', { });
		this.focusableItems = [[this.command, this.eqFields[0]] , [this.varField], [this.solver]];
		this.needsEvaluation = false;
		super_.postInsertHandler.call(this);
		return this;
	}
  _.parseSavedProperties = function(args) {
  	super_.parseSavedProperties.call(this, args);
  	// After we do this, we want to set up the DOM correctly for the number of equations this block had, before rest of parse completes
  	if(this.ask_initial_guess)
			this.jQ.find('.initial_guess').show();
  	var equations_to_add = this.number_of_equations;
  	this.number_of_equations = 1;
  	for(var i = 1; i < equations_to_add; i++)
  		this.addEquation(false, true);
  	this.redoFocusableList();
  	return this;
  }
  _.eq_id = 1;
  _.addEquation = function(focus, skip_focusable) {
  	// Add a new equation line to the solver list
		var html = '<div class="' + css_prefix + 'focusableItems">' + focusableHTML('MathQuill',  'eq' + this.eq_id) + '&nbsp;<i class="fa fa-remove ' + css_prefix + 'hide_print"></i></div>';
		this.jQ.find('.' + css_prefix + 'add_equation').before(html);
		this.eqFields.push(registerFocusable(MathQuill, this, 'eq' + this.eq_id, { ghost: 'equation', handlers: {
			enter: this.enterPressed(this),
			blur: this.submissionHandler(this)
		}}));
		this.eqFields[this.number_of_equations].setExpressionMode(true);
		this.eq_id++;
		this.number_of_equations++;
		if(!skip_focusable) this.redoFocusableList();
		this.varField.setGhost('variable list');
		if(focus) this.eqFields[this.number_of_equations-1].focus(1);
  }
  _.removeEquation = function(index) {
  	if(this.eqFields[index].touched) this.changed();
  	this.eqFields.splice(index, 1);
  	this.jQ.find('.' + css_prefix + 'content').find('.' + css_prefix + 'focusableItems').each(function() {
  		var el = $(this);
  		if((el.attr('data-id')*1) == index)
  			el.removeClass(css_prefix + 'focusableItems').slideUp({duration: 150, always: function() { el.remove(); } });
  	});
		this.number_of_equations--;
		if(this.number_of_equations == 1)
			this.varField.setGhost('variable');
  	this.redoFocusableList();
  }
  _.redoFocusableList = function() {
  	var id = 0;
  	// Renumber the DOM ids
  	this.jQ.find('.' + css_prefix + 'content').find('.' + css_prefix + 'focusableItems').each(function() {
  		$(this).attr('data-id', id);
  		id++;
  	});
  	// Recreate focusable Items array
  	if(this.scoped)
			this.focusableItems = [[this.varStoreField, this.command, this.eqFields[0]]];
		else
			this.focusableItems = [[this.command, this.eqFields[0]]];
		for(var i = 1; i < this.number_of_equations; i++)
			this.focusableItems.push([this.eqFields[i]])
		if(this.ask_initial_guess)
			this.focusableItems.push([this.varField, this.guessField]);
		else
			this.focusableItems.push([this.varField]);
		this.focusableItems.push([this.solver]);
  }
	_.mouseClick = function(e) {
		var target = $(e.target);
		if(target.hasClass(css_prefix + 'add_equation')) {
			this.addEquation(true);
			return false;
		}
		if(target.hasClass('fa-remove')) {
			this.removeEquation(target.closest('div.' + css_prefix + 'focusableItems').attr('data-id')*1);
			return false;
		}
    if(super_.mouseClick.call(this,e)) return true;
	}

	_.submissionHandler = function(_this) {
		return function(mathField) {
			if((mathField === _this.varStoreField) && _this.varStoreField.empty()) 
				_this.clearVariableStore();
			if(_this.needsEvaluation) {
				// check for anything that is empty
				var errors = [];
				if(_this.scoped && !_this.varStoreField.text().match(/^[a-z][a-z0-9_]*$/i))
					errors.push('Invalid variable name (' + _this.worksheet.latexToHtml(_this.varStoreField.latex()) + ').  Please enter a valid variable name');
				if(!_this.varField.text().match(/^[a-z][a-z0-9_]*(,[a-z][a-z0-9_]*)*$/i))
					errors.push('Invalid variable list (' + _this.worksheet.latexToHtml(_this.varField.latex()) + ').  Please enter a valid comma-seperated list of variables');
				if(_this.ask_initial_guess && !_this.guessField.empty() && (_this.guessField.text().split(',').length !== _this.varField.text().split(',').length))
					errors.push('Invalid guesses.  Please ensure you provide 1 guess for each variable you are solving for (enter as a comma-seperated list)');
				for(var i = 0; i < _this.eqFields.length; i++)
					if(_this.eqFields[i].empty()) errors.push('Equation ' + (i+1) + ' is currently empty.  Please add an equation.');<commit_msg>Add ability to store solver output as function, not just variable<commit_after>
var solve = P(GiacGeneric, function(_, super_) {
	_.klass = ['solve'];
	_.number_of_equations = 1;
	_.ask_initial_guess = false;
	_.helpText = "<<solve <[EXPR]> for <[VARS]>>>\nSolve the expression(s) given (EXPR) for the variable(s) specified in VARS.  Use the 'add another equation' link to solve systems of equations.  When solving for multiple variables, enter as a comma-seperated list.  If an initial guess is requested, enter as a comma-seperated list corresponding to the variable list.\nExample: Solve x^2=4 for x with initial guess 0.2.\nExample: Solve x^2+y=6,x-y^2=-2 for x,y";
	_.savedProperties = ['expectedUnits','approx','factor_expand','outputMode','number_of_equations', 'scoped', 'ask_initial_guess'];

	_.init = function() {
		this.eqFields = [];
		super_.init.call(this);
	}
	_.innerHtml = function() {
		return '<table class="' + css_prefix + 'giac_element"><tbody><tr><td class="' + css_prefix + 'var_store">'
	 	+ '<div class="' + css_prefix + 'focusableItems" data-id="0"><span class="' + css_prefix + 'var_store">' + focusableHTML('MathQuill',  'var_store') + '<span class="equality">&#8801;</span></span>' + focusableHTML('CodeBlock', 'solve') + '</td>'
	 	+ '<td class="' + css_prefix + 'content"><div class="' + css_prefix + 'focusableItems" data-id="0">' + focusableHTML('MathQuill',  'eq0') + helpBlock() + '</div><div><div class="' + css_prefix + 'add_equation ' + css_prefix + 'hide_print">Add another equation</div></div>'
	 	+ '<div class="' + css_prefix + 'focusableItems" data-id="1">for&nbsp;' + focusableHTML('MathQuill',  'var') + '<span class="initial_guess" style="display:none;">&nbsp;with initial guess&nbsp;' + focusableHTML('MathQuill',  'var_guess') + '</span></div>'
	  + '<div class="' + css_prefix + 'focusableItems" data-id="2">using&nbsp;' + focusableHTML('SelectBox',  'solver') + '</div>'
		+ answerSpan() + '</td></tr></tbody></table>';
	}
	_.postInsertHandler = function() {
		this.eqFields[0] = registerFocusable(MathQuill, this, 'eq0', { ghost: 'equation', handlers: {
			enter: this.enterPressed(this),
			blur: this.submissionHandler(this)
		}});
		this.varField = registerFocusable(MathQuill, this, 'var', { ghost: 'variable', handlers: {
			enter: this.enterPressed(this),
			blur: this.submissionHandler(this)
		}});
		this.guessField = registerFocusable(MathQuill, this, 'var_guess', { ghost: '0', handlers: {
			enter: this.enterPressed(this),
			blur: this.submissionHandler(this)
		}});
		this.solver = registerFocusable(SelectBox, this, 'solver', { options: { symbolic: 'Symbolic Solver', newton_solver: 'Newton-Raphson Numeric Solver'}});
		this.eqFields[0].setExpressionMode(true);
		this.command = registerFocusable(CodeBlock, this, 'solve', { });
		this.focusableItems = [[this.command, this.eqFields[0]] , [this.varField], [this.solver]];
		this.needsEvaluation = false;
		super_.postInsertHandler.call(this);
		return this;
	}
  _.parseSavedProperties = function(args) {
  	super_.parseSavedProperties.call(this, args);
  	// After we do this, we want to set up the DOM correctly for the number of equations this block had, before rest of parse completes
  	if(this.ask_initial_guess)
			this.jQ.find('.initial_guess').show();
  	var equations_to_add = this.number_of_equations;
  	this.number_of_equations = 1;
  	for(var i = 1; i < equations_to_add; i++)
  		this.addEquation(false, true);
  	this.redoFocusableList();
  	return this;
  }
  _.eq_id = 1;
  _.addEquation = function(focus, skip_focusable) {
  	// Add a new equation line to the solver list
		var html = '<div class="' + css_prefix + 'focusableItems">' + focusableHTML('MathQuill',  'eq' + this.eq_id) + '&nbsp;<i class="fa fa-remove ' + css_prefix + 'hide_print"></i></div>';
		this.jQ.find('.' + css_prefix + 'add_equation').before(html);
		this.eqFields.push(registerFocusable(MathQuill, this, 'eq' + this.eq_id, { ghost: 'equation', handlers: {
			enter: this.enterPressed(this),
			blur: this.submissionHandler(this)
		}}));
		this.eqFields[this.number_of_equations].setExpressionMode(true);
		this.eq_id++;
		this.number_of_equations++;
		if(!skip_focusable) this.redoFocusableList();
		this.varField.setGhost('variable list');
		if(focus) this.eqFields[this.number_of_equations-1].focus(1);
  }
  _.removeEquation = function(index) {
  	if(this.eqFields[index].touched) this.changed();
  	this.eqFields.splice(index, 1);
  	this.jQ.find('.' + css_prefix + 'content').find('.' + css_prefix + 'focusableItems').each(function() {
  		var el = $(this);
  		if((el.attr('data-id')*1) == index)
  			el.removeClass(css_prefix + 'focusableItems').slideUp({duration: 150, always: function() { el.remove(); } });
  	});
		this.number_of_equations--;
		if(this.number_of_equations == 1)
			this.varField.setGhost('variable');
  	this.redoFocusableList();
  }
  _.redoFocusableList = function() {
  	var id = 0;
  	// Renumber the DOM ids
  	this.jQ.find('.' + css_prefix + 'content').find('.' + css_prefix + 'focusableItems').each(function() {
  		$(this).attr('data-id', id);
  		id++;
  	});
  	// Recreate focusable Items array
  	if(this.scoped)
			this.focusableItems = [[this.varStoreField, this.command, this.eqFields[0]]];
		else
			this.focusableItems = [[this.command, this.eqFields[0]]];
		for(var i = 1; i < this.number_of_equations; i++)
			this.focusableItems.push([this.eqFields[i]])
		if(this.ask_initial_guess)
			this.focusableItems.push([this.varField, this.guessField]);
		else
			this.focusableItems.push([this.varField]);
		this.focusableItems.push([this.solver]);
  }
	_.mouseClick = function(e) {
		var target = $(e.target);
		if(target.hasClass(css_prefix + 'add_equation')) {
			this.addEquation(true);
			return false;
		}
		if(target.hasClass('fa-remove')) {
			this.removeEquation(target.closest('div.' + css_prefix + 'focusableItems').attr('data-id')*1);
			return false;
		}
    if(super_.mouseClick.call(this,e)) return true;
	}

	_.submissionHandler = function(_this) {
		return function(mathField) {
			if((mathField === _this.varStoreField) && _this.varStoreField.empty()) 
				_this.clearVariableStore();
			if(_this.needsEvaluation) {
				// check for anything that is empty
				var errors = [];
				if(_this.scoped && !_this.varStoreField.text().match(/^[a-z][a-z0-9_]*(\([a-z][a-z0-9_,]*\))?$/i))
					errors.push('Invalid variable name (' + _this.worksheet.latexToHtml(_this.varStoreField.latex()) + ').  Please enter a valid variable name');
				if(!_this.varField.text().match(/^[a-z][a-z0-9_]*(,[a-z][a-z0-9_]*)*$/i))
					errors.push('Invalid variable list (' + _this.worksheet.latexToHtml(_this.varField.latex()) + ').  Please enter a valid comma-seperated list of variables');
				if(_this.ask_initial_guess && !_this.guessField.empty() && (_this.guessField.text().split(',').length !== _this.varField.text().split(',').length))
					errors.push('Invalid guesses.  Please ensure you provide 1 guess for each variable you are solving for (enter as a comma-seperated list)');
				for(var i = 0; i < _this.eqFields.length; i++)
					if(_this.eqFields[i].empty()) errors.push('Equation ' + (i+1) + ' is currently empty.  Please add an equation.');
{'fraction_non_alphanumeric': 0.17890772128060264, 'fraction_numerical': 0.006835460696100998, 'mean_word_length': 4.739791833466773, 'pattern_counts': {'":': 0, '<': 79, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2343564', 'n_tokens_mistral': 5330, 'n_tokens_neox': 4947, 'n_words': 977}