/* search-integral.js Integrating functionality - Tests is the query is of the form "integral of expression" and if so use a serverside component (maxima.fcgi) to try to integrate the expression symbolically, displaying the result of success. External objects: IntegralQuery - Namespace for handling integral request queries. IntegralQuery.handle(query) - Test if the query is of the form "integral of expression". If so attempt to integrate it in its free variable using a serverside component. Presenting the result in a box. Semi-external objects: IntegralQuery.server - The URL of the integrating server. IntegralQueryTest - Namespce for testing IntegralQuery. IntegralQueryTest.test() - run all tests. */ var ParseUtils = { regexps_find_match : function (re_exps, query) { for (var i=0; i < re_exps.length; i++) { var re = re_exps[i]; var matches = re.exec(query); if (matches) { return matches; } } return null; } }; var IntegralQuery = { server : "http://192.168.2.40/search/integral-serverside/maxima.fcgi", integral_res : [/^\s*integral\s+of\s+(.*)/, /^\s*integrate\s+(.*)/, /^\s*find\s+the\s+integral\s+of\s+(.*)/, /^\s*what\s+is\s+the\s+integral\s+of\s+(.*)/, /\s*what\'s\s+the\s+integral\s+of\s+(.*)/ ], /* asynchronous - send an integrating query that may respond at some point in the future*/ send_query: function(ptree, success_callback, failure_callback) { var query_url = this.make_query_url(ptree); var success_callback_wrapper = function(response) { var text = response.responseText; try { var data = text.evalJSON(true); } catch(e) { // JSON is mangled - this should probably be logged somewhere. } success_callback(data); }; new Ajax.Request(query_url, { method:'get', onSuccess: success_callback_wrapper, onFeailure: failure_callback}); }, make_query_url: function(ptree) { var expr_string = Calculate.parse_tree_to_string(ptree); var free_variable = Calculate.parse_tree_find_free_variable(ptree); var query_url = this.server + "?action=integrate&expression=#{expr}&free=#{free}".interpolate({'expr':expr_string, 'free': free_variable}); return encodeURI(query_url); }, /* See if we should handle this query - and if we should then handle it.*/ handle: function(query) { var re_groups = ParseUtils.regexps_find_match(this.integral_res, query); if (!re_groups) { this._hide_integral_box(); return false; } var expr_str = re_groups[1]; try { var ptree = Calculate.parse_tree_from_string(expr_str); this.send_query(ptree, this._populate_integral_box); } catch(e) { this._hide_integral_box(); return false; } }, _populate_integral_box : function(data) { $("integral-answer").innerHTML = "The integral of " + data['expression'] + " is " + data['answer']; $("integral-container").style.display = "block"; }, _hide_integral_box: function() { $("integral-container").style.display = "none"; } }; var IntegralQueryTest = { send_cgi_query_test: function() { var s = document.createElement('iframe'); s.src = "http://127.0.0.1/send-query-test.fcgi?test=1&other=hermes%204"; var box = document.getElementById('test-box').appendChild(s); }, make_query_url_test: function () { var test_make_url = function (string, ans_string) { var ptree = Calculate.parse_tree_from_string(string); var returned_url = IntegralQuery.make_query_url(ptree); if (ans_string != returned_url) { throw "Query test failed. Return:'" + returned_url + "'. Expected: '" + ans_string + "'"; } } var server = IntegralQuery.server; test_make_url("sin (x)", server + "?action=integrate&expression=sin%20(x)&free=x"); test_make_url("1+(2*3*(4+x))", server + "?action=integrate&expression=1%20+%20(2%20*%203%20*%20(4%20+%20x))&free=x"); }, handle_test: function() { var test_handled = function(query, ans) { if (IntegralQuery.handle(query) != ans) { var extra = ans? "False negative" : "False positive"; throw "Integral query verify handle test for '" + query + "' failed." + extra; } }; test_handled("integral of sin(x)", true); test_handled("trees", false); test_handled("integral of cos(x)", true); test_handled("cos(x) integral of", false); }, /* Test the serverside integrating component */ maxima_test: function() { var test = function (string, ans_string) { var ptree = Calculate.parse_tree_from_string(string); var success_callback = function(data) { if (!data) { alert ("No data returned to success callback"); } if (data['answer'] != ans_string) { alert( "Server integral test failed. Return:'" + data['answer'] + "'. Expected: '" + ans_string + "'"); } }; var failure_callback = function (data) { alert( "Server integral test - Failed to return ajax response for " + ans_string + " test"); } IntegralQuery.send_query(ptree, success_callback, failure_callback); }; test("sin(x)", "-cos(x)"); test("exp(x)", "e^x"); test("1/x", "log(x)"); }, test: function() { this.make_query_url_test(); this.handle_test(); this.maxima_test(); } }; //IntegralQueryTest.maxima_test();