UNPKG

@learnlab/datashop-logger

Version:

TypeScript SDK for logging educational data to Carnegie Mellon's DataShop system

2 lines 14.4 kB
"use strict";var A=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var y=(l,t)=>{for(var e in t)A(l,e,{get:t[e],enumerable:!0})},C=(l,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of P(t))!R.call(l,r)&&r!==e&&A(l,r,{get:()=>t[r],enumerable:!(s=I(t,r))||s.enumerable});return l};var b=l=>C(A({},"__esModule",{value:!0}),l);var D={};y(D,{DataShopLogger:()=>_,DataShopLoggerError:()=>d,LogMessageBuilder:()=>u,SAIBuilder:()=>m});module.exports=b(D);var m=class{constructor(t,e,s){this.selectionArray=[];this.actionArray=[];this.inputArray=[];t!==void 0&&this.setSelection(t),e!==void 0&&this.setAction(e),s!==void 0&&this.setInput(s)}setSelection(t){return this.selectionArray=Array.isArray(t)?[...t]:[t],this}setAction(t){return this.actionArray=Array.isArray(t)?[...t]:[t],this}setInput(t){return this.inputArray=Array.isArray(t)?[...t]:[t],this}build(){return{selection:this.selectionArray.length===0?[]:this.selectionArray.length===1?this.selectionArray[0]:this.selectionArray,action:this.actionArray.length===0?[]:this.actionArray.length===1?this.actionArray[0]:this.actionArray,input:this.inputArray.length===0?[]:this.inputArray.length===1?this.inputArray[0]:this.inputArray}}toXMLString(){let t="";for(let e of this.selectionArray)t+=`<selection>${this.escapeXML(e)}</selection>`;for(let e=0;e<this.actionArray.length;e++)e===0?t+=`<action>${this.escapeXML(this.actionArray[e])}`:t+=`</action><action>${this.escapeXML(this.actionArray[e])}`;this.actionArray.length>0&&(t+="</action>");for(let e of this.inputArray)t+=`<input><![CDATA[${e}]]></input>`;return t}escapeXML(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}};var u=class{constructor(t){this.configuration=t;this.xmlProlog='<?xml version="1.0" encoding="UTF-8"?>';this.DTDVersion="4";this.customFields=new Map}resetCustomFields(){this.customFields.clear()}addCustomField(t,e){this.customFields.set(t,e)}addCustomFields(t){if(t)for(let[e,s]of Object.entries(t))s!=null&&this.addCustomField(e,String(s))}formatTimeStamp(t){return t.toISOString().replace("T"," ").replace("Z","")}formatTimeStampOLI(t){let e=t.getUTCFullYear(),s=String(t.getUTCMonth()+1).padStart(2,"0"),r=String(t.getUTCDate()).padStart(2,"0"),n=String(t.getUTCHours()).padStart(2,"0"),a=String(t.getUTCMinutes()).padStart(2,"0"),o=String(t.getUTCSeconds()).padStart(2,"0");return`${e}/${s}/${r} ${n}:${a}:${o}`}createLogSessionStart(){let t=new Date,e=`${this.xmlProlog}<log_session_start `;return e+='timezone="UTC" ',e+=`date_time="${this.formatTimeStampOLI(t)}" `,e+=`auth_token="${this.configuration.auth_token||""}" `,e+=`session_id="${this.configuration.session_id||""}" `,e+=`user_guid="${this.configuration.user_guid||""}" `,e+='class_id="" treatment_id="" assignment_id="" info_type="tutor_message.dtd"/>',e}createContextMessage(){let t=this.configuration,e=new Date,s=`<context_message context_message_id="${t.context_message_id||""}" name="START_PROBLEM">`;s+=this.makeMetaElement(e),t.class_name&&(s+="<class>",s+=`<name>${this.escapeXML(t.class_name)}</name>`,t.school_name&&(s+=`<school>${this.escapeXML(t.school_name)}</school>`),t.period_name&&(s+=`<period>${this.escapeXML(t.period_name)}</period>`),t.class_description&&(s+=`<description>${this.escapeXML(t.class_description)}</description>`),t.instructor_name&&(s+=`<instructor>${this.escapeXML(t.instructor_name)}</instructor>`),s+="</class>"),s+="<dataset>",s+=`<name><![CDATA[${t.dataset_name||"UnassignedDataset"}]]></name>`;let r="",n=0;for(let a=1;a<=10;a++){let o=`dataset_level_name${a}`,g=`dataset_level_type${a}`,i=t[o],c=t[g];if(i&&c)n++,r+=`<level type="${this.escapeXML(String(c))}">`,r+=`<name><![CDATA[${String(i)}]]></name>`;else break}if(n>0){r+='<problem tutorFlag="tutor">',r+=`<name><![CDATA[${t.problem_name||""}]]></name>`,t.problem_context&&(r+=`<context><![CDATA[${t.problem_context}]]></context>`),r+="</problem>";for(let a=0;a<n;a++)r+="</level>";s+=r}else s+='<problem tutorFlag="tutor">',s+=`<name><![CDATA[${t.problem_name||""}]]></name>`,t.problem_context&&(s+=`<context><![CDATA[${t.problem_context}]]></context>`),s+="</problem>";return s+="</dataset>",s+="</context_message>",s}createSemanticEventToolMessage(t,e,s,r,n){let a=new m(t.selection,t.action,t.input),o=`<tool_message context_message_id="${this.configuration.context_message_id||""}">`;o+=this.makeMetaElement(new Date),o+=`<semantic_event transaction_id="${e}" name="${s}"`,r&&(o+=` subtype="${r}"`),n&&(o+=` trigger="${n}"`),o+="/>",o+="<event_descriptor>",o+=a.toXMLString(),o+="</event_descriptor>";for(let[g,i]of this.customFields)o+=`<custom_field><name>${this.escapeXML(g)}</name><value>${this.escapeXML(String(i))}</value></custom_field>`;return o+="</tool_message>",o}createTutorMessage(t,e,s,r,n,a,o){let g=new m(t.selection,t.action,t.input),i=`<tutor_message context_message_id="${this.configuration.context_message_id||""}">`;if(i+=this.makeMetaElement(new Date),i+=`<semantic_event transaction_id="${e}" name="${s}"`,a&&(i+=` subtype="${a}"`),i+="/>",i+="<event_descriptor>",i+=g.toXMLString(),i+="</event_descriptor>",i+="<action_evaluation",r.classification&&(i+=` classification="${r.classification}"`),r.currentHintNumber!==void 0&&(i+=` current_hint_number="${r.currentHintNumber}"`),r.totalHintsAvailable!==void 0&&(i+=` total_hints_available="${r.totalHintsAvailable}"`),i+=`>${r.evaluation}</action_evaluation>`,n&&(i+=`<tutor_advice>${n}</tutor_advice>`),o&&o.length>0){i+="<skills>";for(let c of o)i+="<skill>",i+=`<name>${this.escapeXML(c.name)}</name>`,c.category&&(i+=`<category>${this.escapeXML(c.category)}</category>`),i+="</skill>";i+="</skills>"}for(let[c,h]of this.customFields)i+=`<custom_field><name>${this.escapeXML(c)}</name><value>${this.escapeXML(String(h))}</value></custom_field>`;return i+="</tutor_message>",i}wrapForDataShop(t){return t.includes("<log_session_start")?t:`${this.xmlProlog}<tutor_related_message_sequence version_number="${this.DTDVersion}">${t}</tutor_related_message_sequence>`}wrapForOLI(t){let e=new Date,s=this.configuration,r=encodeURIComponent(t),n=`${this.xmlProlog}<log_action `;return n+=`auth_token="${encodeURIComponent(s.auth_token||"")}" `,n+=`session_id="${s.session_id||""}" `,n+='action_id="EVALUATE_QUESTION" ',n+='user_guid="" ',n+=`date_time="${this.formatTimeStampOLI(e)}" `,n+='timezone="UTC" ',n+=`source_id="${s.source_id||"tutor"}" `,n+=`external_object_id="${s.activity_context_guid||""}" `,n+='info_type="tutor_message.dtd">',n+=r,n+="</log_action>",n}makeMetaElement(t){let e="<meta>";return e+=`<user_id>${this.escapeXML(this.configuration.user_guid||"")}</user_id>`,e+=`<session_id>${this.escapeXML(this.configuration.session_id||"")}</session_id>`,e+=`<time>${this.formatTimeStamp(t)} UTC</time>`,e+="<time_zone>UTC</time_zone>",e+="</meta>",e}escapeXML(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}};function f(){let l=typeof globalThis<"u"&&globalThis.crypto||typeof global<"u"&&global.crypto||typeof window<"u"&&window.crypto;return l&&l.randomUUID?l.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{let e=Math.random()*16|0;return(t==="x"?e:e&3|8).toString(16)})}function L(){return`T${f()}`}function x(){return`C${f()}`}var d=class l extends Error{constructor(t,e,s){super(t),this.name="DataShopLoggerError",this.code=e,this.details=s,Error.captureStackTrace&&Error.captureStackTrace(this,l)}},v=class extends d{constructor(t,e){super(t,"CONFIGURATION_ERROR",e),this.name="ConfigurationError"}},S=class extends d{constructor(t,e){super(t,"NETWORK_ERROR",e),this.name="NetworkError"}};var _=class{constructor(t){this.logFormat="DATASHOP";this.useSessionLog=!0;this.lastTransactionID="";this.lastSAI=null;this.defaultConfiguration={dataset_name:"UnassignedDataset",source_id:"tutor"};this.configuration={...this.defaultConfiguration,...t?.configuration},t?.logFormat&&(this.logFormat=t.logFormat),t?.useSessionLog!==void 0&&(this.useSessionLog=t.useSessionLog),this.messageBuilder=new u(this.configuration),this.initializeSession()}initializeSession(){this.configuration.session_id||(this.configuration.session_id=`ctat_session_${f()}`),this.configuration.context_message_id||(this.configuration.context_message_id=x()),this.configuration.user_guid||(this.configuration.user_guid=f())}start(){if(this.initializeSession(),this.useSessionLog){let e=this.messageBuilder.createLogSessionStart();this.sendMessage(e)}let t=this.messageBuilder.createContextMessage();return this.sendMessage(t),this.configuration.session_id}resume(t){this.configuration.session_id=t;let e=this.messageBuilder.createContextMessage();this.sendMessage(e)}reset(t){let e;t&&typeof t=="object"&&"configuration"in t?e=t.configuration:e=t,this.configuration={...this.defaultConfiguration,...e},this.messageBuilder=new u(this.configuration),this.initializeSession()}logInterfaceAttempt(t,e,s,r){if(typeof t=="object"&&!Array.isArray(t)&&"selection"in t){let n=t,a={selection:n.selection,action:n.action,input:n.input};return this.logInterfaceAttemptSAI({sai:a,customFields:n.customFields})}else{let n={selection:t,action:e,input:s};return this.logInterfaceAttemptSAI({sai:n,customFields:r})}}logInterfaceAttemptSAI(t,e){let s,r;"sai"in t?(s=t.sai,r=t.customFields):(s=t,r=e);let n=L();this.lastTransactionID=n,this.lastSAI=s,this.messageBuilder.resetCustomFields(),this.messageBuilder.addCustomFields(r),this.messageBuilder.addCustomField("tool_event_time",this.messageBuilder.formatTimeStamp(new Date)+" UTC");let a=this.messageBuilder.createSemanticEventToolMessage(s,n,"ATTEMPT",void 0,void 0);return this.sendMessage(a),n}logInterfaceHintRequest(t,e,s,r){let n,a;if(typeof t=="object"&&!Array.isArray(t)&&"selection"in t){let i=t;n={selection:i.selection,action:i.action,input:i.input},a=i.customFields}else n={selection:t,action:e,input:s},a=r;let o=L();this.lastTransactionID=o,this.messageBuilder.resetCustomFields(),this.messageBuilder.addCustomFields(a),this.messageBuilder.addCustomField("tool_event_time",this.messageBuilder.formatTimeStamp(new Date)+" UTC");let g=this.messageBuilder.createSemanticEventToolMessage(n,o,"HINT_REQUEST",void 0,void 0);return this.sendMessage(g),o}logHintResponse(t,e,s,r,n,a,o,g){if(typeof t=="object"&&"transactionId"in t){let i=t,c={evaluation:"HINT",currentHintNumber:i.currentHintNumber,totalHintsAvailable:i.totalHintsAvailable};this.logResponse({transactionId:i.transactionId,selection:i.selection,action:i.action,input:i.input,semanticName:"HINT_MSG",evaluation:c,advice:i.hintText,customFields:i.customFields})}else{let i={evaluation:"HINT",currentHintNumber:n,totalHintsAvailable:a};this.logResponse({transactionId:t,selection:e,action:s,input:r,semanticName:"HINT_MSG",evaluation:i,advice:o,customFields:g})}}logResponse(t,e,s,r,n,a,o,g,i){if(typeof t=="object"&&"transactionId"in t){let c=t,h={selection:c.selection,action:c.action,input:c.input};this.logResponseSAI({transactionId:c.transactionId,sai:h,semanticName:c.semanticName,evaluation:c.evaluation,advice:c.advice,customFields:c.customFields,skills:c.skills})}else{let c={selection:e,action:s,input:r};this.logResponseSAI({transactionId:t,sai:c,semanticName:n,evaluation:a,advice:o,customFields:g,skills:i})}}logResponseSAI(t,e,s,r,n,a,o){let g;typeof t=="object"&&"sai"in t?g=t:g={transactionId:t,sai:e,semanticName:s,evaluation:r,advice:n,customFields:a,skills:o};let i=typeof g.evaluation=="string"?{evaluation:g.evaluation}:g.evaluation;this.lastSAI=g.sai,this.messageBuilder.resetCustomFields(),this.messageBuilder.addCustomFields(g.customFields),this.messageBuilder.addCustomField("tutor_event_time",this.messageBuilder.formatTimeStamp(new Date)+" UTC");let c=g.advice?`<![CDATA[${g.advice}]]>`:"",h=this.messageBuilder.createTutorMessage(g.sai,g.transactionId||this.lastTransactionID,g.semanticName,i,c,void 0,g.skills);this.sendMessage(h)}sendMessage(t){if(this.logFormat==="DATASHOP"){let e;if(t.includes("<log_session_start"))e=t;else{let s=this.messageBuilder.wrapForDataShop(t);e=this.messageBuilder.wrapForOLI(s)}if(!this.configuration.log_service_url)throw new v("log_service_url is not configured");if(typeof navigator<"u"&&navigator.sendBeacon)navigator.sendBeacon(this.configuration.log_service_url,e);else if(typeof fetch<"u")fetch(this.configuration.log_service_url,{method:"POST",body:e,headers:{"Content-Type":"text/plain"},keepalive:!0}).catch(()=>{});else throw new S("No suitable method for sending log messages");this.logListener&&this.logListener(e)}else throw new v(`Unsupported log format: ${this.logFormat}`)}setLogFormat(t){this.logFormat=t.format}getLogFormat(){return this.logFormat}setLoggingURL(t){this.configuration.log_service_url=t.url}setLoggingURLQA(){this.setLoggingURL({url:"https://pslc-qa.andrew.cmu.edu/log/server"})}setLoggingURLProduction(){this.setLoggingURL({url:"https://learnlab.web.cmu.edu/log/server"})}setContextName(t){this.configuration.context_name=t.name}getContextName(){return this.configuration.context_name||"START_PROBLEM"}setContextMessageID(t){this.configuration.context_message_id=t.id}getContextMessageID(){return this.configuration.context_message_id||""}setUserID(t){this.configuration.user_guid=t.id}setProblemName(t){this.configuration.problem_name=t.name}setProblemContext(t){this.configuration.problem_context=t.context}setDatasetName(t){this.configuration.dataset_name=t.name}setSchool(t){this.configuration.school_name=t.school}setPeriod(t){this.configuration.period_name=t.period}setInstructor(t){this.configuration.instructor_name=t.instructor}setDescription(t){this.configuration.class_description=t.description}setLogClassName(t){this.configuration.class_name=t.className}setDatasetLevelName(t){this.configuration[`dataset_level_name${t.level}`]=t.name}setDatasetLevelType(t){this.configuration[`dataset_level_type${t.level}`]=t.type}setUseSessionLog(t){this.useSessionLog=t.use}getLastSAI(){return this.lastSAI}getSessionId(){return this.configuration.session_id}getUserGuid(){return this.configuration.user_guid}getContextMessageId(){return this.configuration.context_message_id}endSession(){this.configuration.session_id=`ctat_session_${f()}`}setLogListener(t){this.logListener=t.listener}};0&&(module.exports={DataShopLogger,DataShopLoggerError,LogMessageBuilder,SAIBuilder}); //# sourceMappingURL=index.js.map