diff --git a/amd/build/editformhelper.min.js b/amd/build/editformhelper.min.js index d6dc172..74de74b 100644 --- a/amd/build/editformhelper.min.js +++ b/amd/build/editformhelper.min.js @@ -5,6 +5,6 @@ define("qtype_aitext/editformhelper",["exports","core/str","core/ajax","core/log * @module qtype_aitext/editformhelper * @copyright 2024 Justin Hunt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_ajax=_interopRequireDefault(_ajax),_log=_interopRequireDefault(_log),_notification=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(_notification);const Selectors_fields={sampleanswer:"#id_sampleanswer",sampleanswerbtn:"#id_sampleanswerbtn",sampleanswereval:"#id_sampleanswereval",aiprompt:"#id_aiprompt",markscheme:"#id_markscheme",defaultmark:"#id_defaultmark"};_exports.init=contextid=>{var strings={};(0,_str.get_strings)([{key:"prompttester",component:"qtype_aitext"},{key:"sampleanswerempty",component:"qtype_aitext"}]).done((function(s){var i=0;strings.prompttester=s[i++],strings.sampleanswerempty=s[i++]})),document.querySelector(Selectors_fields.sampleanswerbtn).addEventListener("click",(e=>{const form=e.target.closest("form"),sampleanswer=form.querySelector(Selectors_fields.sampleanswer),sampleanswereval=form.querySelector(Selectors_fields.sampleanswereval),aiprompt=form.querySelector(Selectors_fields.aiprompt),marksscheme=form.querySelector(Selectors_fields.markscheme),defaultmark=form.querySelector(Selectors_fields.defaultmark);""!==sampleanswer.value&&""!==aiprompt.value?(sampleanswereval.innerHTML='',_ajax.default.call([{methodname:"qtype_aitext_fetch_ai_grade",args:{response:sampleanswer.value,defaultmark:defaultmark.value,prompt:aiprompt.value,marksscheme:marksscheme.value,contextid:contextid},async:!1}])[0].then((function(airesponse){_log.default.debug(airesponse),airesponse.feedback&&(sampleanswereval.textContent=airesponse.feedback+" (GRADE: "+airesponse.marks+"/"+defaultmark.value+")")})).fail((error=>{(0,_notification.exception)(error),sampleanswereval.innerHTML=""}))):_notification.default.alert(strings.prompttester,strings.sampleanswerempty)}))}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_ajax=_interopRequireDefault(_ajax),_log=_interopRequireDefault(_log),_notification=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(_notification);_exports.init=contextid=>{}})); //# sourceMappingURL=editformhelper.min.js.map \ No newline at end of file diff --git a/amd/build/editformhelper.min.js.map b/amd/build/editformhelper.min.js.map index b36c471..227f4be 100644 --- a/amd/build/editformhelper.min.js.map +++ b/amd/build/editformhelper.min.js.map @@ -1 +1 @@ -{"version":3,"file":"editformhelper.min.js","sources":["../src/editformhelper.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/ //\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\nimport {get_strings} from 'core/str';\nimport Ajax from 'core/ajax';\nimport Log from 'core/log';\nimport Notify from 'core/notification';\nimport {exception as displayException} from 'core/notification';\n\n/**\n * Question AI Text Edit Form Helper\n *\n * @module qtype_aitext/editformhelper\n * @copyright 2024 Justin Hunt \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst Selectors = {\n fields: {\n sampleanswer: '#id_sampleanswer',\n sampleanswerbtn: '#id_sampleanswerbtn',\n sampleanswereval: '#id_sampleanswereval',\n aiprompt: '#id_aiprompt',\n markscheme: '#id_markscheme',\n defaultmark: '#id_defaultmark',\n },\n};\n\n/**\n * Initialise the format chooser.\n */\nexport const init = (contextid) => {\n\n // Set up strings\n var strings={};\n get_strings([\n { \"key\": \"prompttester\", \"component\": 'qtype_aitext'},\n { \"key\": \"sampleanswerempty\", \"component\": 'qtype_aitext'},\n\n ]).done(function (s) {\n var i = 0;\n strings.prompttester = s[i++];\n strings.sampleanswerempty = s[i++];\n });\n\n document.querySelector(Selectors.fields.sampleanswerbtn).addEventListener('click', e => {\n\n const form = e.target.closest('form');\n const sampleanswer = form.querySelector(Selectors.fields.sampleanswer);\n const sampleanswereval = form.querySelector(Selectors.fields.sampleanswereval);\n const aiprompt = form.querySelector(Selectors.fields.aiprompt);\n const marksscheme = form.querySelector(Selectors.fields.markscheme);\n const defaultmark = form.querySelector(Selectors.fields.defaultmark);\n\n if(sampleanswer.value===\"\" || aiprompt.value===\"\"){\n Notify.alert(strings.prompttester, strings.sampleanswerempty);\n return;\n }\n\n //put spinner in place\n sampleanswereval.innerHTML='';\n\n Ajax.call([{\n methodname: 'qtype_aitext_fetch_ai_grade',\n args: {\n response: sampleanswer.value,\n defaultmark: defaultmark.value,\n prompt: aiprompt.value,\n marksscheme: marksscheme.value,\n contextid: contextid\n },\n async: false\n }])[0].then(function(airesponse) {\n Log.debug(airesponse);\n if (airesponse.feedback) {\n sampleanswereval.textContent = airesponse.feedback + ' (GRADE: ' + airesponse.marks + '/' + defaultmark.value + ')';\n }\n }).fail(error => {\n displayException(error);\n sampleanswereval.innerHTML = '';\n });\n });//end of click\n};\n"],"names":["Selectors","sampleanswer","sampleanswerbtn","sampleanswereval","aiprompt","markscheme","defaultmark","contextid","strings","done","s","i","prompttester","sampleanswerempty","document","querySelector","addEventListener","e","form","target","closest","marksscheme","value","innerHTML","call","methodname","args","response","prompt","async","then","airesponse","debug","feedback","textContent","marks","fail","error","alert"],"mappings":";;;;;;;w0BA4BMA,iBACM,CACJC,aAAc,mBACdC,gBAAiB,sBACjBC,iBAAkB,uBAClBC,SAAU,eACVC,WAAY,iBACZC,YAAa,iCAOAC,gBAGbC,QAAQ,wBACA,CACR,KAAS,yBAA6B,gBACtC,KAAS,8BAAkC,kBAE5CC,MAAK,SAAUC,OACVC,EAAI,EACRH,QAAQI,aAAeF,EAAEC,KACzBH,QAAQK,kBAAoBH,EAAEC,QAGlCG,SAASC,cAAcf,iBAAiBE,iBAAiBc,iBAAiB,SAASC,UAEzEC,KAAOD,EAAEE,OAAOC,QAAQ,QACxBnB,aAAeiB,KAAKH,cAAcf,iBAAiBC,cACnDE,iBAAmBe,KAAKH,cAAcf,iBAAiBG,kBACvDC,SAAWc,KAAKH,cAAcf,iBAAiBI,UAC/CiB,YAAcH,KAAKH,cAAcf,iBAAiBK,YAClDC,YAAcY,KAAKH,cAAcf,iBAAiBM,aAEhC,KAArBL,aAAaqB,OAA+B,KAAjBlB,SAASkB,OAMvCnB,iBAAiBoB,UAAU,iEAEtBC,KAAK,CAAC,CACPC,WAAY,8BACZC,KAAM,CACFC,SAAU1B,aAAaqB,MACvBhB,YAAaA,YAAYgB,MACzBM,OAAQxB,SAASkB,MACjBD,YAAaA,YAAYC,MACzBf,UAAWA,WAEfsB,OAAO,KACP,GAAGC,MAAK,SAASC,yBACbC,MAAMD,YACNA,WAAWE,WACX9B,iBAAiB+B,YAAcH,WAAWE,SAAW,YAAcF,WAAWI,MAAQ,IAAM7B,YAAYgB,MAAQ,QAErHc,MAAKC,oCACaA,OACjBlC,iBAAiBoB,UAAY,6BAxBtBe,MAAM9B,QAAQI,aAAcJ,QAAQK"} \ No newline at end of file +{"version":3,"file":"editformhelper.min.js","sources":["../src/editformhelper.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/ //\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\nimport {get_strings} from 'core/str';\nimport Ajax from 'core/ajax';\nimport Log from 'core/log';\nimport Notify from 'core/notification';\nimport {exception as displayException} from 'core/notification';\n\n/**\n * Question AI Text Edit Form Helper\n *\n * @module qtype_aitext/editformhelper\n * @copyright 2024 Justin Hunt \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst Selectors = {\n fields: {\n sampleanswer: '#id_sampleanswer',\n sampleanswerbtn: '#id_sampleanswerbtn',\n sampleanswereval: '#id_sampleanswereval',\n aiprompt: '#id_aiprompt',\n markscheme: '#id_markscheme',\n defaultmark: '#id_defaultmark',\n },\n};\n\n/**\n * Initialise the format chooser.\n */\nexport const init = (contextid) => {\n return;\n\n // Set up strings\n var strings={};\n get_strings([\n { \"key\": \"prompttester\", \"component\": 'qtype_aitext'},\n { \"key\": \"sampleanswerempty\", \"component\": 'qtype_aitext'},\n\n ]).done(function (s) {\n var i = 0;\n strings.prompttester = s[i++];\n strings.sampleanswerempty = s[i++];\n });\n\n document.querySelector(Selectors.fields.sampleanswerbtn).addEventListener('click', e => {\n\n const form = e.target.closest('form');\n const sampleanswer = form.querySelector(Selectors.fields.sampleanswer);\n const sampleanswereval = form.querySelector(Selectors.fields.sampleanswereval);\n const aiprompt = form.querySelector(Selectors.fields.aiprompt);\n const marksscheme = form.querySelector(Selectors.fields.markscheme);\n const defaultmark = form.querySelector(Selectors.fields.defaultmark);\n\n if (sampleanswer.value === \"\" || aiprompt.value === \"\") {\n Notify.alert(strings.prompttester, strings.sampleanswerempty);\n return;\n }\n\n //put spinner in place\n sampleanswereval.innerHTML='';\n\n Ajax.call([{\n methodname: 'qtype_aitext_fetch_ai_grade',\n args: {\n response: sampleanswer.value,\n defaultmark: defaultmark.value,\n prompt: aiprompt.value,\n marksscheme: marksscheme.value,\n contextid: contextid\n },\n async: false\n }])[0].then(function(airesponse) {\n Log.debug(airesponse);\n if (airesponse.feedback) {\n sampleanswereval.textContent = airesponse.feedback + ' (GRADE: ' + airesponse.marks + '/' + defaultmark.value + ')';\n }\n }).fail(error => {\n displayException(error);\n sampleanswereval.innerHTML = '';\n });\n });//end of click\n};\n"],"names":["contextid"],"mappings":";;;;;;;g1BA0CqBA"} \ No newline at end of file diff --git a/amd/build/responserun.min.js b/amd/build/responserun.min.js new file mode 100644 index 0000000..a424a1d --- /dev/null +++ b/amd/build/responserun.min.js @@ -0,0 +1,10 @@ +define("qtype_aitext/responserun",["exports","core/str","core/ajax","core/notification","core/log"],(function(_exports,_str,_ajax,_notification,_log){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} +/** + * Display a button in testing to reveal the prompt that was sent + * + * @module qtype_aitext/responserun + * @copyright 2024 Marcus Green + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_ajax=_interopRequireDefault(_ajax),_notification=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(_notification),_log=_interopRequireDefault(_log);const Selectors_fields={sampleanswer:"#id_sampleanswer",sampleanswerbtn:"#id_sampleanswerbtn",sampleanswereval:"#id_sampleanswereval",spinner:"#id_spinner",aiprompt:"#id_aiprompt",markscheme:"#id_markscheme",defaultmark:"#id_defaultmark"};_exports.init=contextid=>{var strings={};(0,_str.get_strings)([{key:"prompttester",component:"qtype_aitext"},{key:"sampleanswerempty",component:"qtype_aitext"}]).done((function(s){var i=0;strings.prompttester=s[i++],strings.sampleanswerempty=s[i++]})),document.querySelector(Selectors_fields.sampleanswerbtn).addEventListener("click",(e=>{const form=e.target.closest("form"),sampleanswer=form.querySelector(Selectors_fields.sampleanswer),sampleanswereval=form.querySelector(Selectors_fields.sampleanswereval),aiprompt=form.querySelector(Selectors_fields.aiprompt),marksscheme=form.querySelector(Selectors_fields.markscheme),defaultmark=form.querySelector(Selectors_fields.defaultmark),spinner=form.querySelector(Selectors_fields.spinner);""!==sampleanswer.value&&""!==aiprompt.value?(spinner.innerHTML='',spinner.innerHTML+=' ',spinner.innerHTML+="",spinner.classList.remove("hide"),_ajax.default.call([{methodname:"qtype_aitext_fetch_ai_grade",args:{response:sampleanswer.value,defaultmark:defaultmark.value,prompt:aiprompt.value,marksscheme:marksscheme.value,contextid:contextid},async:!1}])[0].then((function(airesponse){return _log.default.debug(airesponse),airesponse.feedback&&(sampleanswereval.textContent=airesponse.feedback+" (GRADE: "+airesponse.marks+"/"+defaultmark.value+")",spinner.classList.add("hide")),!0})).fail((error=>{(0,_notification.exception)(error),sampleanswereval.innerHTML=""}))):_notification.default.alert(strings.prompttester,strings.sampleanswerempty)}))}})); + +//# sourceMappingURL=responserun.min.js.map \ No newline at end of file diff --git a/amd/build/responserun.min.js.map b/amd/build/responserun.min.js.map new file mode 100644 index 0000000..82c0dfc --- /dev/null +++ b/amd/build/responserun.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"responserun.min.js","sources":["../src/responserun.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Display a button in testing to reveal the prompt that was sent\n *\n * @module qtype_aitext/responserun\n * @copyright 2024 Marcus Green\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {get_strings} from 'core/str';\nimport Ajax from 'core/ajax';\nimport Notify from 'core/notification';\nimport Log from 'core/log';\nimport {exception as displayException} from 'core/notification';\n\nconst Selectors = {\n fields: {\n sampleanswer: '#id_sampleanswer',\n sampleanswerbtn: '#id_sampleanswerbtn',\n sampleanswereval: '#id_sampleanswereval',\n spinner: '#id_spinner',\n aiprompt: '#id_aiprompt',\n markscheme: '#id_markscheme',\n defaultmark: '#id_defaultmark',\n },\n};\n\nexport const init = (contextid) => {\n\n // Set up strings\n var strings={};\n get_strings([\n {\"key\": \"prompttester\", \"component\": 'qtype_aitext'},\n {\"key\": \"sampleanswerempty\", \"component\": 'qtype_aitext'},\n\n ]).done(function (s) {\n var i = 0;\n strings.prompttester = s[i++];\n strings.sampleanswerempty = s[i++];\n });\n document.querySelector(Selectors.fields.sampleanswerbtn).addEventListener('click', e => {\n const form = e.target.closest('form');\n const sampleanswer = form.querySelector(Selectors.fields.sampleanswer);\n const sampleanswereval = form.querySelector(Selectors.fields.sampleanswereval);\n\n const aiprompt = form.querySelector(Selectors.fields.aiprompt);\n const marksscheme = form.querySelector(Selectors.fields.markscheme);\n const defaultmark = form.querySelector(Selectors.fields.defaultmark);\n const spinner = form.querySelector(Selectors.fields.spinner);\n\n if (sampleanswer.value === \"\" || aiprompt.value === \"\") {\n Notify.alert(strings.prompttester, strings.sampleanswerempty);\n return;\n }\n // Put spinner in place.\n spinner.innerHTML = '';\n spinner.innerHTML += ' ';\n spinner.innerHTML += '';\n\n spinner.classList.remove('hide');\n Ajax.call([{\n methodname: 'qtype_aitext_fetch_ai_grade',\n args: {\n response: sampleanswer.value,\n defaultmark: defaultmark.value,\n prompt: aiprompt.value,\n marksscheme: marksscheme.value,\n contextid: contextid\n },\n async: false\n }])[0].then(function(airesponse) {\n Log.debug(airesponse);\n if (airesponse.feedback) {\n sampleanswereval.textContent = airesponse.feedback + ' (GRADE: ' + airesponse.marks + '/' + defaultmark.value + ')';\n spinner.classList.add('hide');\n }\n return true;\n }).fail(error => {\n displayException(error);\n sampleanswereval.innerHTML = '';\n });\n\n}); // End of click.\n\n};\n"],"names":["Selectors","sampleanswer","sampleanswerbtn","sampleanswereval","spinner","aiprompt","markscheme","defaultmark","contextid","strings","done","s","i","prompttester","sampleanswerempty","document","querySelector","addEventListener","e","form","target","closest","marksscheme","value","innerHTML","classList","remove","call","methodname","args","response","prompt","async","then","airesponse","debug","feedback","textContent","marks","add","fail","error","alert"],"mappings":";;;;;;;w0BA6BMA,iBACM,CACJC,aAAc,mBACdC,gBAAiB,sBACjBC,iBAAkB,uBAClBC,QAAS,cACTC,SAAU,eACVC,WAAY,iBACZC,YAAa,iCAIAC,gBAGbC,QAAQ,wBACA,CACR,KAAQ,yBAA6B,gBACrC,KAAQ,8BAAkC,kBAE3CC,MAAK,SAAUC,OACVC,EAAI,EACRH,QAAQI,aAAeF,EAAEC,KACzBH,QAAQK,kBAAoBH,EAAEC,QAElCG,SAASC,cAAchB,iBAAiBE,iBAAiBe,iBAAiB,SAASC,UACzEC,KAAOD,EAAEE,OAAOC,QAAQ,QACxBpB,aAAekB,KAAKH,cAAchB,iBAAiBC,cACnDE,iBAAmBgB,KAAKH,cAAchB,iBAAiBG,kBAEvDE,SAAWc,KAAKH,cAAchB,iBAAiBK,UAC/CiB,YAAcH,KAAKH,cAAchB,iBAAiBM,YAClDC,YAAcY,KAAKH,cAAchB,iBAAiBO,aAClDH,QAAUe,KAAKH,cAAchB,iBAAiBI,SAEzB,KAAvBH,aAAasB,OAAmC,KAAnBlB,SAASkB,OAK7CnB,QAAQoB,UAAY,6CACpBpB,QAAQoB,WAAa,sGACrBpB,QAAQoB,WAAa,UAErBpB,QAAQqB,UAAUC,OAAO,sBACpBC,KAAK,CAAC,CACRC,WAAY,8BACZC,KAAM,CACFC,SAAU7B,aAAasB,MACvBhB,YAAaA,YAAYgB,MACzBQ,OAAQ1B,SAASkB,MACjBD,YAAaA,YAAYC,MACzBf,UAAWA,WAEfwB,OAAO,KACP,GAAGC,MAAK,SAASC,gCACbC,MAAMD,YACNA,WAAWE,WACXjC,iBAAiBkC,YAAcH,WAAWE,SAAW,YAAcF,WAAWI,MAAQ,IAAM/B,YAAYgB,MAAQ,IAChHnB,QAAQqB,UAAUc,IAAI,UAEnB,KACRC,MAAKC,oCACaA,OACjBtC,iBAAiBqB,UAAY,6BA5BlBkB,MAAMjC,QAAQI,aAAcJ,QAAQK"} \ No newline at end of file diff --git a/amd/src/editformhelper.js b/amd/src/editformhelper.js.org similarity index 97% rename from amd/src/editformhelper.js rename to amd/src/editformhelper.js.org index 5c67abd..d4889f0 100644 --- a/amd/src/editformhelper.js +++ b/amd/src/editformhelper.js.org @@ -41,6 +41,7 @@ const Selectors = { * Initialise the format chooser. */ export const init = (contextid) => { + return; // Set up strings var strings={}; @@ -63,7 +64,7 @@ export const init = (contextid) => { const marksscheme = form.querySelector(Selectors.fields.markscheme); const defaultmark = form.querySelector(Selectors.fields.defaultmark); - if(sampleanswer.value==="" || aiprompt.value===""){ + if (sampleanswer.value === "" || aiprompt.value === "") { Notify.alert(strings.prompttester, strings.sampleanswerempty); return; } diff --git a/amd/src/responserun.js b/amd/src/responserun.js new file mode 100644 index 0000000..07bbad9 --- /dev/null +++ b/amd/src/responserun.js @@ -0,0 +1,99 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Display a button in testing to reveal the prompt that was sent + * + * @module qtype_aitext/responserun + * @copyright 2024 Marcus Green + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import {get_strings} from 'core/str'; +import Ajax from 'core/ajax'; +import Notify from 'core/notification'; +import Log from 'core/log'; +import {exception as displayException} from 'core/notification'; + +const Selectors = { + fields: { + sampleanswer: '#id_sampleanswer', + sampleanswerbtn: '#id_sampleanswerbtn', + sampleanswereval: '#id_sampleanswereval', + spinner: '#id_spinner', + aiprompt: '#id_aiprompt', + markscheme: '#id_markscheme', + defaultmark: '#id_defaultmark', + }, +}; + +export const init = (contextid) => { + + // Set up strings + var strings={}; + get_strings([ + {"key": "prompttester", "component": 'qtype_aitext'}, + {"key": "sampleanswerempty", "component": 'qtype_aitext'}, + + ]).done(function (s) { + var i = 0; + strings.prompttester = s[i++]; + strings.sampleanswerempty = s[i++]; + }); + document.querySelector(Selectors.fields.sampleanswerbtn).addEventListener('click', e => { + const form = e.target.closest('form'); + const sampleanswer = form.querySelector(Selectors.fields.sampleanswer); + const sampleanswereval = form.querySelector(Selectors.fields.sampleanswereval); + + const aiprompt = form.querySelector(Selectors.fields.aiprompt); + const marksscheme = form.querySelector(Selectors.fields.markscheme); + const defaultmark = form.querySelector(Selectors.fields.defaultmark); + const spinner = form.querySelector(Selectors.fields.spinner); + + if (sampleanswer.value === "" || aiprompt.value === "") { + Notify.alert(strings.prompttester, strings.sampleanswerempty); + return; + } + // Put spinner in place. + spinner.innerHTML = ''; + spinner.innerHTML += ' '; + spinner.innerHTML += ''; + + spinner.classList.remove('hide'); + Ajax.call([{ + methodname: 'qtype_aitext_fetch_ai_grade', + args: { + response: sampleanswer.value, + defaultmark: defaultmark.value, + prompt: aiprompt.value, + marksscheme: marksscheme.value, + contextid: contextid + }, + async: false + }])[0].then(function(airesponse) { + Log.debug(airesponse); + if (airesponse.feedback) { + sampleanswereval.textContent = airesponse.feedback + ' (GRADE: ' + airesponse.marks + '/' + defaultmark.value + ')'; + spinner.classList.add('hide'); + } + return true; + }).fail(error => { + displayException(error); + sampleanswereval.innerHTML = ''; + }); + +}); // End of click. + +}; diff --git a/edit_aitext_form.php b/edit_aitext_form.php index 1767306..df9604b 100755 --- a/edit_aitext_form.php +++ b/edit_aitext_form.php @@ -38,7 +38,6 @@ class qtype_aitext_edit_form extends question_edit_form { */ protected function definition_inner($mform) { global $PAGE; - /** @var qtype_aitext $qtype */ $qtype = question_bank::get_qtype('aitext'); $mform->removeelement('generalfeedback'); @@ -83,15 +82,26 @@ protected function definition_inner($mform) { $mform->addElement('html', ''); $mform->addElement('header', 'prompttester', get_string('prompttester', 'qtype_aitext')); + $mform->addElement('textarea', 'sampleanswer', get_string('sampleanswer', 'qtype_aitext'), ['maxlen' => 50, 'rows' => 6, 'size' => 30]); $mform->setType('sampleanswer', PARAM_RAW); $mform->setDefault('sampleanswer', ''); - $mform->addHelpButton('sampleanswer', 'sampleanswer', 'qtype_aitext'); - $mform->addElement('static', 'sampleanswereval', '', '' - . get_string('sampleanswerevaluate', 'qtype_aitext') . '' . - '
'); + $mform->addElement('static', 'spinner', '', '
'); + + $mform->addElement('button', 'sampleanswerbtn', get_string('sampleanswerevaluate', 'qtype_aitext')); + $mform->registerNoSubmitButton('sampleanswerbtn"'); + + $options = [ + 'cols' => 50, + 'rows' => 5, + 'disabled' => 'disabled', + ]; + + $mform->addElement('textarea', 'sampleanswereval', get_string('sampleanswereval', 'qtype_aitext'), $options); + + $mform->setDefault('element_name', 'The default value'); + $mform->addElement('header', 'responseoptions', get_string('responseoptions', 'qtype_aitext')); $mform->setExpanded('responseoptions'); @@ -135,7 +145,8 @@ protected function definition_inner($mform) { ['rows' => 10], $this->editoroptions); // Load any JS that we need to make things happen, specifically the prompt tester. - $PAGE->requires->js_call_amd('qtype_aitext/editformhelper', 'init', [$this->context->id]); + $PAGE->requires->js_call_amd('qtype_aitext/responserun', 'init', [$this->context->id]); + } /** diff --git a/lang/de/qtype_aitext.php b/lang/de/qtype_aitext.php index 6342787..b8c226f 100644 --- a/lang/de/qtype_aitext.php +++ b/lang/de/qtype_aitext.php @@ -73,7 +73,6 @@ $string['pluginnameediting'] = 'Bearbeiten einer AI-Text-Frage'; $string['pluginnamesummary'] = 'Ermöglicht die Beantwortung eines Datei-Uploads und/oder eines Online-Textes. Die Antwort des Schülers wird vom konfigurierten AI/Large-Sprachmodell verarbeitet, das ein Feedback und optional eine Note zurückgibt.'; $string['privacy::responsefieldlines'] = 'Anzahl der Zeilen, die die Größe des Eingabefeldes (Textarea) angeben.'; -$string['privacy:metadata'] = 'AI Text question type plugin allows question authors to set default options as user preferences.'; $string['privacy:preference:attachments'] = 'Anzahl der erlaubten Anhänge.'; $string['privacy:preference:attachmentsrequired'] = 'Anzahl der erforderlichen Anhänge.'; $string['privacy:preference:defaultmark'] = 'Die Standardmarkierung, die für eine bestimmte Frage gesetzt wurde.'; @@ -95,14 +94,12 @@ $string['showprompt'] = 'Eingabeaufforderung anzeigen'; $string['spellcheck_editor_desc'] = 'Dies ist der Text, in dem die Rechtschreibfehler von der KI korrigiert wurden. Sie können diesen Korrekturvorschlag bearbeiten.'; - $string['spellcheck_prompt'] = 'Gib den Text ohne strukturelle Änderung 1:1 wieder. Verzichte auf ein Feedback. Aber korrigiere alle Rechtschreibfehler im nachfolgenden Text: '; $string['spellcheck_student_anser_desc'] = 'Dies ist die ursprüngliche Antwort des Schülers'; $string['spellcheckedit'] = 'Rechtschreibprüfung bearbeiten'; $string['spellcheckeditor'] = 'Rechtschreibprüfung der KI bearbeiten'; $string['thedefaultmarksscheme'] = 'Ziehe für jeden Grammatik- oder Rechtschreibfehler einen Punkt von der Gesamtpunktzahl ab.'; $string['thedefaultprompt'] = 'Erklären Sie, ob etwas mit der Grammatik und der Rechtschreibung im Text nicht stimmt.'; -$string['untestedquestionbehaviour'] = 'Ungetestetes Frageverhalten'; $string['wordcount'] = 'Wortanzahl: {$a}'; $string['wordcounttoofew'] = 'Wortanzahl: {$a->count}, weniger als die erforderlichen {$a->limit} Wörter.'; $string['wordcounttoomuch'] = 'Wortanzahl: {$a->count}, mehr als das Limit von {$a->limit} Wörtern.'; diff --git a/lang/en/qtype_aitext.php b/lang/en/qtype_aitext.php index d8a1d10..5b3258e 100755 --- a/lang/en/qtype_aitext.php +++ b/lang/en/qtype_aitext.php @@ -24,7 +24,6 @@ */ $string['acceptedfiletypes'] = 'Accepted file types'; - $string['aiprompt'] = 'AI Prompt'; $string['aiprompt_help'] = 'A prompt for the Ai Grader. This is the guideline that AI uses to give feedback on the student response.'; $string['aipromptmissing'] = 'The ai prompt is missing. Please enter a prompt on the basis of which the feedback is generated.'; @@ -105,6 +104,7 @@ $string['sampleanswer_help'] = 'The sample answer can be used to test how the AI grader will respond to a given response.'; $string['sampleanswerempty'] = 'Make sure that you have an AI prompt and sample answer before testing.'; $string['sampleanswerevaluate'] = 'Evaluate Sample Answer'; +$string['sampleanswereval'] = 'Sample Answer Evaluation'; $string['showprompt'] = 'Show prompt'; $string['spellcheck_editor_desc'] = 'This is the text in which the spelling mistakes have been corrected by AI. You can edit this suggested correction.'; $string['spellcheck_prompt'] = 'Reproduce the text 1:1. Give no feedback!. But correct all spelling mistakes in the following text: '; diff --git a/tests/question_test.php b/tests/question_test.php index a17ce96..94d2163 100755 --- a/tests/question_test.php +++ b/tests/question_test.php @@ -44,14 +44,14 @@ final class question_test extends \advanced_testcase { * Instance of the question type class * @var qtype_aitext */ - + public $question; /** * There is a live connection to the External AI system * When run locally it will make a connection. Otherwise the * tests will be skipped * @var bool */ - protected int $islive; + protected bool $islive = false; /** * Config.php should include the apikey and orgid in the form @@ -61,7 +61,7 @@ final class question_test extends \advanced_testcase { * @return void */ protected function setUp(): void { - $this->qtype = new \qtype_aitext(); + $this->question = new \qtype_aitext(); if (defined('TEST_LLM_APIKEY') && defined('TEST_LLM_ORGID')) { set_config('apikey', TEST_LLM_APIKEY, 'aiprovider_openai'); set_config('orgid', TEST_LLM_ORGID, 'aiprovider_openai'); @@ -86,7 +86,23 @@ public function test_perform_request(): void { $response = $aitext->perform_request('What is 2 * 4 only return a single number'); $this->assertEquals('8', $response); } - + /** + * Check the student response gets interprolated into the prompt ready to send + * off to the LLM + * @covers \qtype_aitext\question::build_full_ai_prompt + */ + public function test_build_full_ai_prompt() { + $this->resetAfterTest(true); + $question = qtype_aitext_test_helper::make_aitext_question([]); + $question->questiontext = 'What is 2 * 4?'; + $aiprompt = "Is the a correct response to the question 'What is 2 * 4?"; + $defaultmark = 1; + $markscheme = 'Give one mark if the response is 8'; + $studentresponse = 'It is 8'; + $result = (string) $question->build_full_ai_prompt($studentresponse, $aiprompt, $defaultmark, $markscheme); + $pattern = '/\[\[' . $studentresponse . '\]\]/'; + $this->assertEquals(1, preg_match($pattern, $result)); + } /** * Tests the call to the quesitonbase summary code diff --git a/version.php b/version.php index f657268..012b3df 100755 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'qtype_aitext'; -$plugin->version = 2024051110; +$plugin->version = 2024071892; $plugin->requires = 2020110900; $plugin->release = '0.02'; $plugin->maturity = MATURITY_BETA;