html`. Open your favorite text editor or IDE and create a new file named `program1.html`.
Show more…
Please give Ace some feedback
Your feedback will help us improve your experience
Thanks for your feedback!
Exp1: Simple Calculator using JavaScript
Write a JavaScript program to design a simple calculator to perform the following operations: sum, product, difference, and quotient.
Aim: To write a JavaScript program to design a simple calculator.
Algorithm/Procedure:
1. Create a webpage with the name program1.html.
2. Create a table for the calculator using HTML code.
3. Create an HTML form and input field for each entry.
\n```', 'Step 5: Save your `program1.html` file and open it in a web browser to test your simple calculator. Enter numbers into the input fields and click the operation buttons to see the results displayed below the form.\n\nThis completes your simple calculator using JavaScript. You can further style your calculator using CSS to make it visually appealing.']},
"textbook_answer": ``,
"transcription": `None`,
"curriculum_id": 44,
"source": "pdp",
"instruct_mode": false,
};
const sentencesToRenderLaTex = [];
let wasChatbotClosedPopupShown = false;
const isUserAuthenticated = false;
$('[data-toggle="tooltip"]').tooltip();
const userEvent = new UserEvent({
'apiUrl': '/ace-api/v1/userevents/',
'questionId': 103607711,
'questionType': 'textbook',
'csrfToken': 'K8MQNuri8c5yyrxvi3rUI9FPPuZUBnB0zqPvzlxmwoOh8X1ex9rDWFd2EIELiSk8',
});
const feedbackManager = new FeedbackManager({
thumbImage: 'https://cdn-www.numerade.com/static/icons/thumb-up-icon.f95df33b33e0.svg',
thumbFillImage: 'https://cdn-www.numerade.com/static/icons/thumb-up-filled-icon.ed8121955a51.svg',
feedbackUrl: '/ace-api/v1/feedbacks/',
csrfToken: 'K8MQNuri8c5yyrxvi3rUI9FPPuZUBnB0zqPvzlxmwoOh8X1ex9rDWFd2EIELiSk8',
pdpVersion: '',
});
const speakManager = new SpeakManager({
apiUrl: '/ace-api/v1/audios/',
csrfToken: 'K8MQNuri8c5yyrxvi3rUI9FPPuZUBnB0zqPvzlxmwoOh8X1ex9rDWFd2EIELiSk8',
});
const chatSettings = {
/* */
welcomeMessage: `
Hi ! Need help with
this question?
I know these concepts can sometimes be confusing, but I’ll make it simple.
Just tell me what’s on your mind!`,
welcomeMessageAiVideo: `
Hi ! Need help with
this question?
I know these concepts can sometimes be confusing, but I’ll make it simple.
Just tell me what’s on your mind!`,
chatProfileImage: `https://cdn-www.numerade.com/static/ace/ace-pointing.3010e9e58287.svg`,
userProfileImage: `https://cdn-www.numerade.com/static/ace/ace-profile.aa65e387d7d7.svg`,
typingImage: `https://cdn-www.numerade.com/static/gifs/typing.3210a534764e.png`,
excludedRegex: [
{
regex: /prompts.*:/i, // Regular expression to match "prompts" followed by ":"
excludeNextLines: true, // Exclude next lines after the match. If this is false, exclude only the current line
},
],
millisecondsBetweenWords: 100,
floatingButtonImageOpen: `https://cdn-www.numerade.com/static/ace/ace-pointing.3010e9e58287.svg`,
floatingButtonImageClose: `https://cdn-www.numerade.com/static/icons/close-x.0ceebab0a1bd.svg`,
playAudioImage: 'https://cdn-www.numerade.com/static/icons/play-audio-icon-gray.6397199f5155.svg',
stopAudioImage: 'https://cdn-www.numerade.com/static/icons/mute-audio-icon-gray.10091237464c.svg',
audioEndpointURL: '/ace-api/v1/audios/',
linksPrefix: {
'Concept Definition': 'Give me more information about',
'Common Mistakes': 'Common examples of mistake of',
'default': 'Tell me more about',
},
questionOverrides: {},
feedbackManager,
excludedMessagesFromHistory: ['exampleQuestion'],
onChatEventCallback,
removeFeedbackOnMessage: false,
sleepBetweenWords: true,
subscriptionIsActive: false,
};
chatManager = new ChatManager(chatSettings);
chatManager.showWelcomeMessage();
chatManager._renderedMessages = window.localStorage.getItem('ace_rendered_messages') || 0;
// Check API status every x minutes and update the global variable
const getAPIStatus = async () => {
const apiUrl = '/ace-api/v1/status/';
try {
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error(`There was an error getting the API status.: ${response.statusText}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error(error);
}
};
let APIStatus;
const statusCheckInterval = 2 * 60 * 1000; // x minutes
setInterval(async () => {
APIStatus = await getAPIStatus();
}, statusCheckInterval);
// Start - Upload File Implementation
const FileType = {
NO_SET: 'NO_SET',
PDF: 'PDF',
IMAGE: 'IMAGE',
};
const _uploadBtnId = "#chatbot-upload-btn";
const _dropzoneId = '#chatbot-dropzone';
let _fileType = FileType.NO_SET;
let _uniqueFileId = null;
let _imageUrl = null;
let _questionText = null;
let _questionTitle = null;
let _questionTextError = null;
let _dropzoneInput = null;
const _OCREndpoint = '/ace-api/v1/files/';
const _CSRFToken = 'K8MQNuri8c5yyrxvi3rUI9FPPuZUBnB0zqPvzlxmwoOh8X1ex9rDWFd2EIELiSk8';
function setFileType() {
const uploadedFile = _dropzoneInput.files ? _dropzoneInput.files[0] : null;
if (uploadedFile.type === 'application/pdf') {
this._fileType = FileType.PDF;
} else {
this._fileType = FileType.IMAGE;
}
}
function getThumbnailBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
});
};
function toBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result.split(',')[1]);
reader.onerror = reject;
});
}
function OCRBase64Image(base64Data) {
_uniqueFileId = null;
return new Promise(async (resolve, reject) => {
try {
const formData = new FormData();
const cropData = {
x: 0,
y: 0,
width: 0,
height: 0
};
let naturalHeight, naturalWidth = 0;
formData.append('saveImage', 1);
formData.append('base64Data', base64Data);
formData.append('conversationId', getConversationId());
formData.append('croppedData', JSON.stringify({
left: 0,
top: 0,
width: 0,
height: 0,
}));
const response = await fetch(_OCREndpoint, {
method: 'POST',
headers: {
"X-CSRFToken": _CSRFToken,
},
body: formData,
});
if (!response.ok) {
throw new Error(`There was an error sending image data.: ${response.statusText}`);
}
let data = await response.json();
const chatbotLoadingElement = $("#chatbot-loading");
if (chatbotLoadingElement) chatbotLoadingElement.remove();
chatManager.enableMessageInput();
if (getConversationId() === 0) {
setConversationId(data.conversationId);
}
_uniqueFileId = data.uniqueFileId;
resolve(data);
} catch (error) {
reject(error);
}
});
}
async function sendFileToBackend() {
const uploadedFile = _dropzoneInput.files ? _dropzoneInput.files[0] : null;
if (!uploadedFile)
return;
const formData = new FormData();
formData.append('file', uploadedFile);
formData.append('conversationId', getConversationId())
formData.append('uniqueFileId', _uniqueFileId);
formData.append('fileUploadOrigin', 'PDP');
try {
const response = await fetch(_OCREndpoint, {
headers: {
"X-CSRFToken": _CSRFToken,
},
method: 'POST',
body: formData
});
if (!response.ok) {
console.error('Failed to upload file');
}
} catch (error) {
console.error('Failed to upload file:', error);
}
}
async function convertImageToText(file) {
const base64Data = await toBase64(file);
let imageUrl = null;
try {
const questionText = await OCRBase64Image(base64Data);
imageUrl = questionText.imageUrl;
if (questionText && questionText.hasOwnProperty('data') && questionText.data.trim() !== '') {
_questionText = questionText.data;
_questionTitle = questionText.title;
} else if (questionText && questionText.hasOwnProperty('error') && questionText.error.trim() !== '') {
_questionTextError = questionText.error;
}
sendFileToBackend(); // Send full file to backend in background
} catch (error) {
const chatbotLoadingElement = $("#chatbot-loading");
if (chatbotLoadingElement) chatbotLoadingElement.remove();
chatManager.enableMessageInput();
console.error(error);
}
return imageUrl;
}
async function _onThumbnailCallback(thumbnail) {
if (thumbnail)
chatManager.addImage(thumbnail, "", false);
chatManager.showTyping();
}
function _onSuccessCallback(title, text, isSampleQuestion) {
const messageSource = (isSampleQuestion) ? MessageSource.SAMPLE_QUESTION : MessageSource.IMAGE_OCR;
sendMessage(text, messageSource);
userEvent.send('CBT_ENT');
userEvent.send('CBT_IMAGE_PROCESSED');
}
function _onErrorCallback(error) {
sendMessage('NOT_TEXT_FOUND', MessageSource.IMAGE_OCR);
}
function resetFileInput() {
_dropzoneInput.value = '';
_fileType = FileType.NO_SET;
_uniqueFileId = null;
_imageUrl = null;
_questionText = null;
_questionTitle = null;
_questionTextError = null;
}
function showUpload() {
$(_dropzoneId).show();
}
async function sendMessageFromImage (file) {
const thumbnail = await getThumbnailBase64(file);
await _onThumbnailCallback(thumbnail);
return new Promise(async (resolve, reject) => {
const timer = setInterval(() => {
if (_questionText || _questionTextError) {
clearInterval(timer);
if (_questionText) {
_onSuccessCallback(_questionTitle, _questionText, false);
resetFileInput();
_questionTitle = null;
_questionText = null;
_questionTextError = null;
resolve();
} else if (_questionTextError) {
_onErrorCallback(_questionTextError);
resetFileInput();
_questionTitle = null;
_questionText = null;
_questionTextError = null;
reject();
}
}
}, 100);
});
}
_dropzoneInput = document.querySelector(`${_dropzoneId} input[type=file]`);
$(_uploadBtnId).on('click', () => {
_dropzoneInput.click();
});
$(_dropzoneInput).on('change', async (event) => {
const file = event.target.files[0];
const allowedImageTypes = ['image/jpeg', 'image/png', 'image/webp'];
if (file.size > MAX_FILE_UPLOADSIZE) {
chatManager.addError('Sorry, Ace can only process images less than 5 MBs, please try again with a different image.');
}
else if (!allowedImageTypes.includes(file.type)) {
chatManager.addError('This file type is not supported. Please upload a jpg, png or webp file.')
}
else {
setFileType(); // analog to chatbot-landing-v2 showPreview()
userEvent.send('CBT_BTN_GALLERY');
chatManager.showTyping();
chatManager.disableMessageInput();
_imageUrl = await convertImageToText(file); // Convert image to text
sendMessageFromImage(file);
userEvent.send('CBT_IMAGE_UPLOADED');
}
});
// End - Upload File Implementation
/* Functions */
let trustpilotModalCalled = false;
function trustpilotModal() {
// Shows Trustpilot feedback modal after five messages
const userMessageCount = $('.chatbot__question__text').length;
if (!trustpilotModalCalled && userMessageCount === 5) {
// Ensures we have the Trustpilot modal and its functions loaded
if (typeof showTrustpilotModal !== 'undefined' && typeof showTrustpilotModal === 'function') {
trustpilotModalCalled = true;
setTimeout(showTrustpilotModal, 300, "ACE");
}
}
}
function onChatEventCallback(event, {sentence, messageId, sentenceId, type}) {
if (event === ChatEvent.OPEN_POPUP) {
renderLaTex('chatbot-pinned-text');
userEvent.send('CBT_CLK');
hideWelcomePopup();
hideClosePopup();
} else if (event === ChatEvent.CLOSE_POPUP) {
userEvent.send('CBT_XOUT');
showClosePopup();
} else if (event === ChatEvent.DISPLAY_SENTENCE) {
if (type === MessageType.ANSWER || type === MessageType.QUESTION) {
renderLaTex(messageId);
}
} else if (event === ChatEvent.DISPLAY_MESSAGE) {
renderLaTex(messageId);
window.localStorage.setItem('ace_rendered_messages', chatManager._renderedMessages);
trustpilotModal();
} else if (event === ChatEvent.UPDATE_PINNED_QUESTION) {
renderLaTex('chatbot-pinned-text');
} else if (event === ChatEvent.BUTTON_CLICK || event === ChatEvent.LINK_CLICK) {
if (!this.stoppedRendering()) {
const source = getSourceFromEventType(event);
sendMessage(sentence, source);
userEvent.send(sentence);
} else {
showSubRegModal();
}
} else if (event === ChatEvent.PLAY_AUDIO) {
speakManager.enableAudio();
userEvent.send('CBT_SON');
} else if (event === ChatEvent.STOP_AUDIO) {
speakManager.disableAudio();
userEvent.send('CBT_SOFF');
} else if (event === ChatEvent.SEND_MESSAGE) {
sendMessage(sentence, MessageSource.USER);
userEvent.send('CBT_ENT');
}
}
function removeHtmlAndEmojis(text) {
const emojiRegex = /[\uD800-\uDFFF]|\uD83C[\uDDE0-\uDFFF]|\uD83D[\uDC00-\uDE4F\uDE80-\uDEFF]|\uD83E[\uDD00-\uDDFF]/g;
const htmlRegex = /(<([^>]+)>)/ig;
return text.replace(emojiRegex, '').replace(htmlRegex, '');
}
function getSourceFromEventType(event) {
let source;
if (event === ChatEvent.BUTTON_CLICK) {
source = MessageSource.BUTTON;
} else if (event === ChatEvent.LINK_CLICK) {
source = MessageSource.LINK;
} else {
source = MessageSource.USER;
}
return source;
}
function showClosePopup() {
if (!wasChatbotClosedPopupShown) {
const popup = document.querySelector('#chatbot-onclose-popup');
if (popup) popup.style.display = 'flex';
wasChatbotClosedPopupShown = true;
}
}
function hideClosePopup() {
const popup = document.querySelector('#chatbot-onclose-popup');
if (popup) popup.style.display = 'none';
}
function waitForMathJaxHub(callback) {
if (typeof MathJax !== 'undefined') {
callback();
} else {
document.addEventListener('readystatechange', function() {
if (typeof MathJax !== 'undefined') {
callback();
}
});
}
}
function renderLaTex(id) {
const element = document.getElementById(id);
const elementHTML = (typeof element !== 'undefined' && element !== null) ? element.innerHTML : '';
if (!hasLatexExpression(elementHTML) || sentencesToRenderLaTex.includes(element))
return;
sentencesToRenderLaTex.push(element);
if (sentencesToRenderLaTex.length == 1)
renderLaTexList();
}
function renderLaTexList() {
waitForMathJaxHub(function() {
if (sentencesToRenderLaTex.length == 0)
return;
const firstElement = sentencesToRenderLaTex[0];
MathJax.typesetPromise([firstElement]).then(() => {
// Check if the element was updated in the DOM
if ($(`#${firstElement.id}`).html() != $(firstElement).html()) {
$(`#${firstElement.id}`).html($(firstElement).html())
}
// Check the LaTex notation width, and fix the issue if the width is 0
const mathElement = document.querySelector(`#${firstElement.id} .MathJax .math`);
const mathContentElement = document.querySelector(`#${firstElement.id} .MathJax .math span span`);
if (mathElement && mathContentElement && parseInt(mathElement.style.width) == 0) {
const mathContentWidth = mathContentElement.getClientRects()[0].width;
mathElement.style.width = `${mathContentWidth}px`;
}
const mathJaxSpans = document.querySelectorAll('.chatbot .MathJax span');
mathJaxSpans.forEach(span => {
if (parseFloat(span.style.verticalAlign) < -1) {
span.style.verticalAlign = 'middle';
}
});
})
.catch((error) => {
setTimeout(() => {
const errorId = `#${message[1].MathJax.error?.inputID}-Frame`;
const errorElement = document.querySelector(errorId);
if (!errorElement)
return;
const sentenceId = errorElement.parentElement.id;
renderLaTex(sentenceId);
}, 300);
});
sentencesToRenderLaTex.shift();
renderLaTexList();
});
}
function hasLatexExpression(html) {
if (!html)
return false;
html = html.trim();
const regex = /\\\(.*?\\\)|\\\[(.|\n)*?\\\]|\\begin\{([^}]*)\}((.|\n)*?)\\end\{\1\}|\$([^$]+)\$|MathJax/igm;
return regex.test(html);
}
function getRandomId() {
return (Math.floor(Math.random() * 1000)).toString();
}
async function getQuestionData(questionId, type) {
const apiUrl = '/ace-api/v1/questions/';
return new Promise((resolve, reject) => {
$.ajax({
url: apiUrl,
type: 'POST',
data: {
'question_id': questionId,
'type': type,
'csrfmiddlewaretoken': 'K8MQNuri8c5yyrxvi3rUI9FPPuZUBnB0zqPvzlxmwoOh8X1ex9rDWFd2EIELiSk8',
},
success: data => {
resolve(data);
},
error: error => {
reject(error);
}
});
});
}
function saveMessages(assistantMessage = '', responseTime = 0, source=MessageSource.USER, metadata={}) {
const lastQuestion = chatManager.getLastQuestion();
const apiUrl = '/ace-api/v1/messages/';
$.ajax({
url: apiUrl,
type: 'POST',
data: {
'user_message': lastQuestion.sentence,
'assistant_message': assistantMessage,
'response_time': responseTime,
'conversation_id': getConversationId(),
'metadata': JSON.stringify(metadata),
'question_url': '/ask/question/exp1-simple-calculator-using-java-script-write-a-javascript-to-design-a-simple-calculator-to-perform-the-following-operations-sum-product-difference-and-quotient-aim-to-write-a-javascript-to-80912/',
'csrfmiddlewaretoken': 'K8MQNuri8c5yyrxvi3rUI9FPPuZUBnB0zqPvzlxmwoOh8X1ex9rDWFd2EIELiSk8',
'source': source,
'message_ace_version': '',
'question_id': 103607711,
'title': `Exp1: Simple Calculator using Java script Write a JavaScript to design a simple calculator to perform the
following operations: sum, product, difference and quotient. Aim: To Write a JavaScript to design a
simple calculator Algorithm/Procedure: 1. Create a webpage with the name program1.html. 2. Create
table for Calculator using Html code. 3. Create html form and input field for each entry`,
},
success: data => {
chatManager.setConversationId(data.conversation_id);
const nextAnswer = chatManager.getNextAnswer(lastQuestion.messageId);
if (nextAnswer) {
$(`#${nextAnswer.messageId}[class^="chatbot__message"]`).first().data('dbId', data.message_id); // Used for feedback
}
},
error: error => {
console.error(error);
}
});
}
async function sendMessage(userMessage, source=MessageSource.USER) {
chatManager.setIsAnswering(true);
const questionId = getRandomId();
let answerId = getRandomId();
let messageImage = null;
chatManager.addQuestion(userMessage, `question-${questionId}`, source);
const start = Date.now();
const posterUrl = "https://cdn.numerade.com/project-universal/previews/a4cbb699-e297-4703-8868-95c6ac49fc95.jpg";
const duration = '03:17';
const animationUrl = posterUrl;
const videoUrl = 'https://cdn.numerade.com/project-universal/encoded/.mp4?Expires=1783063922&Signature=FIwaZMynPpbesPhL2JjZX8UI~P~1M96mWAbaab6ZhlnNV51dAzvRYJWpxgtKe6bpyUHK3AyLyAfyo882v7YSs~RL2QrEaEEoOqdPAMYuVJrNZ92RmE0UxwQBJj5KyIBEln19ERiWvWo7FS9Dek8g0NhS-HpHp6UtJe~mNQ8p0n4UBWaoaSo5AaiKLkpRHb0RElYjcHxhoAlVY6rKaoENFMsp8UJDd-KmSolgi3f5q9rXqu8g3bF2mb-u4te28HDGERY9WcSHq3Pzmr-d21CUmOJuBIBNYUBnocbvvonHVe23Q8eO7wDklG3pm7PRg21onKPLt1Z6tXZtHAROZewAfQ__&Key-Pair-Id=K212LANSMWDVO6';
setTimeout(() => {
if (!chatManager.messageExists(`answer-${answerId}`)) {
chatManager.showTyping();
}
}, 300);
// If the API is down, show an error message
if ((typeof APIStatus !== 'undefined') && (await APIStatus.status !== 200)) {
chatManager.addError("You have reached the limit of messages per day. Please try again in few hours.");
setTimeout(() => {
chatManager.setIsAnswering(false);
chatManager.hideTyping();
}, 300);
return;
}
// If the message is comming from Image OCR update the request parameters
let extraParamsOCRRequest = {}
if (source === MessageSource.IMAGE_OCR || source === MessageSource.SAMPLE_QUESTION) {
messageImage = _imageUrl;
requestBodyData['source'] = 'landing_ocr';
requestBodyData['image_url'] = _imageUrl;
requestBodyData['step_by_step_json'] = [];
requestBodyData['question_texts'] = userMessage;
extraParamsOCRRequest = {'messageSource': 'OCR'};
}
if (!requestBodyData.hasOwnProperty('images'))
requestBodyData['images'] = [];
requestBodyData['images'].push(messageImage);
// If this is true, 'subject' field will be added to the response
const requestSubjectDetection = (
[MessageSource.USER, MessageSource.IMAGE_OCR, MessageSource.SAMPLE_QUESTION].includes(source)
);
const apiUrl = 'https://www.numerade.com/chat/v1';
const body = JSON.stringify({
"messages": chatManager.getMessagesHistory(),
...requestBodyData,
...extraParamsOCRRequest,
"subject": requestSubjectDetection,
});
try {
const response = await fetch(apiUrl, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body
});
if (!response.ok) {
chatManager.addError('Sorry, there was a connection issue, please try again.');
const metadata = {
error: `There was an error sending the message. ${response.statusText}}`,
}
saveMessages('', 0, source, metadata);
throw new Error(`There was an error sending the message.: ${response.statusText}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
let assistantMessage = '';
let currentChunk = '';
let currentSentence = '';
let isLaTex = false;
while (true) {
const { value, done } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split("\n");
lines.forEach(async line => {
line = line.trim();
if (line) {
const lineObj = JSON.parse(line);
let content;
if (lineObj?.search_result) {
const questionId = lineObj?.search_result?.question_id;
const questionType = lineObj?.search_result?.type;
const metadata = {
'question_id': questionId,
'question_type': questionType,
}
await getQuestionData(questionId, questionType)
.then(questionData => {
assistantMessage += questionData.text;
const videoEmbedData = {
slug: questionData.slug,
lazyLoadUrl: 'https://cdn-www.numerade.com/static/lazyload.95c829fcfb1f.svg',
videoUrl: questionData.video_url,
posterUrl: questionData.poster_url,
duration: questionData.duration,
animationUrl: questionData.animation_url,
questionType,
text: questionData.text,
}
const videoEmbed = new VideoEmbed(videoEmbedData);
// Update the context with this new question data
requestBodyData.question_texts = questionData.text;
requestBodyData.step_by_step_json = questionData.step_by_step_json;
requestBodyData.textbook_answer = questionData.textbook_answer;
requestBodyData.transcription = questionData.transcription;
chatManager.addAnswer(videoEmbed.getHtml(), `answer-${answerId}`);
chatManager.updatePinnedQuestion(questionData.text);
const responseTime = (Date.now() - start) / 1000;
saveMessages(assistantMessage, responseTime, source, metadata);
})
.catch (error => {
chatManager.addError('Sorry, there was an error getting the suggested video, please try again.');
metadata['error'] = `Sorry, there was an error getting the suggested video.`;
const responseTime = (Date.now() - start) / 1000;
saveMessages('', responseTime, source, metadata);
throw new Error('Sorry, there was an error getting the suggested video.');
});
} else if (lineObj?.assistant_message_delta) {
content = lineObj?.assistant_message_delta?.delta;
if (content) {
if (content == '\r') {
chatManager.addAnswer(currentSentence, `answer-${answerId}`, getRandomId());
currentSentence = '';
answerId = getRandomId();
}
content = content.replaceAll('$$', '$');
assistantMessage += content;
Array.prototype.forEach.call(content, function(ch, index) {
currentChunk += ch;
currentSentence += ch;
if ((['\n',' ','.',','].includes(ch)) && currentChunk != '\n' && currentChunk != '\n\n' ) {
currentChunk = '';
}
let previousCh = (content.length > 1) ? content[index-1] : '';
let nextCh = (content.length > index) ? content[index + 1] : '';
if ((ch === '$' && nextCh == '$') || (ch === '$' && previousCh != '$' && nextCh != '$')) {
isLaTex = !isLaTex;
}
previousCh = (currentSentence.length > 1) ? currentSentence[currentSentence.length-2] : '';
if ((ch === '[' || ch === '(') && previousCh === '\\') {
isLaTex = true;
}
if ((ch === ']' || ch === ')') && previousCh === '\\') {
isLaTex = false;
}
// Remove ++followup_question++ and split in two answers
if (currentSentence.includes('++followup_question++')) {
const regex = /\+\+followup_question\+\+?(:|\s*|\n|W*)/gm;
currentSentence = currentSentence.replace(regex, '');
currentSentence = currentSentence.replaceAll('\n', '').trim();
answerId = getRandomId();
}
if (!isLaTex && ['\n','.'].includes(ch) && currentSentence != '\n' && currentSentence != '\n\n' ) {
/* STU-1282 Disable audio for now
let sentenceId = speakManager.addToSpeakList(`answer-${answerId}`, currentSentence);
*/
let sentenceId;
currentSentence = currentSentence.replaceAll('\n\n\n', '\n\n').replaceAll('\n', '
')
if (sentenceId === undefined) {
// Prevent duplicate sentence ids, which causes multiple empty lines.
sentenceId = getRandomId();
}
chatManager.addAnswer(currentSentence, `answer-${answerId}`, sentenceId)
currentSentence = '';
}
});
}
}
}
});
}
if (currentSentence != '') {
/* STU-1282 Disable audio for now
let sentenceId = speakManager.addToSpeakList(`answer-${answerId}`, currentSentence);
*/
let sentenceId = getRandomId();
currentSentence = currentSentence.replaceAll('\n\n\n', '\n\n').replaceAll('\n', '
');
if (sentenceId === 0 && $(`#answer-${answerId}-sentence-${sentenceId}`).length > 1) {
sentenceId = getRandomId();
}
chatManager.addAnswer(currentSentence, `answer-${answerId}`, sentenceId)
}
try {
if (assistantMessage != '') {
const responseTime = (Date.now() - start) / 1000;
saveMessages(assistantMessage, responseTime, source);
}
} catch (error) {
console.error('Error speaking the text', error);
}
chatManager.setIsAnswering(false);
} catch (error) {
chatManager.addError('Sorry, there was an error processing the message, please try again.');
const responseTime = (Date.now() - start) / 1000;
saveMessages('', responseTime, source, {error: error});
throw new Error(JSON.stringify(error))
chatManager.setIsAnswering(false);
}
}
/* Actions */
$('.chatbot-btn').on('click', (event) => {
chatManager.togglePopup();
const btnId = event.target.id;
if (btnId == 'livechat-button') {
userEvent.send('CBT_CLKBTN_1');
} else if (btnId == 'livechat-button-2') {
userEvent.send('CBT_CLKBTN_2');
}
});
$('#chatbot-welcome-popup-start').on('click', () => {
chatManager.togglePopup();
userEvent.send('CBT_CLKBTN_START');
});
// Fix z-index of Chatbot when menu was opened
$('.navbar-toggler').on('click', () => {
setTimeout(() => {
if ($('.navbar-toggler').hasClass('collapsed')) {
$('.chatbot').css('z-index', '1040');
} else {
$('.chatbot').css('z-index', '1000');
}
}, 200);
});
function showSubRegModal() {
$(isUserAuthenticated ? '#subscribe-modal' : '#register-modal').modal('show');
// userEvent.send();
document.getElementById('chatbot').style.zIndex = '1000';
};
document.addEventListener('click', event => {
if (event.target?.classList?.contains('customContinueButton')) showSubRegModal();
});
function setCookie(name, value, days) {
const expires = new Date();
expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000));
document.cookie = `${name}=${encodeURIComponent(value)};expires=${expires.toUTCString()};path=/`;
};
function getCookie(name) {
const cookieName = `${name}=`;
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
if (cookie.indexOf(cookieName) === 0) {
return decodeURIComponent(cookie.substring(cookieName.length));
}
}
return null;
};
if (getCookie('acechat-welcome-popup') != 'dismissed') {
$('#chatbot-welcome-popup').show();
if (document.getElementById('chatbot-welcome-popup')) $('#chatbot-floating-btn').fadeOut();
}
function hideWelcomePopup() {
$('#chatbot-welcome-popup').fadeOut();
$('#chatbot-floating-btn').fadeIn();
setCookie('acechat-welcome-popup', 'dismissed', 365);
}
$('.dismiss-button, #chatbot-welcome-popup-start').click(() => {
hideWelcomePopup();
});
document.acechat_explain_step = (step, houdini=false) => {
chatManager.togglePopup();
sendMessage('Get more help with step '+step);
if (houdini) {
userEvent.send('CBT_BTN_HOUDINI');
} else {
userEvent.send('CBT_BTN_AI_VIDEO');
}
}
// Check API status and update the global variable
APIStatus = await getAPIStatus();
});