1/// <reference path="references.d.ts" /> 2/// <reference path="application.ts" /> 3/// <reference path="AutoSaveHelper.ts" /> 4var __assign = (this && this.__assign) || function () { 5 __assign = Object.assign || function(t) { 6 for (var s, i = 1, n = arguments.length; i < n; i++) { 7 s = arguments[i]; 8 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) 9 t[p] = s[p]; 10 } 11 return t; 12 }; 13 return __assign.apply(this, arguments); 14}; 15var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 16 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 17 return new (P || (P = Promise))(function (resolve, reject) { 18 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 19 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 20 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 21 step((generator = generator.apply(thisArg, _arguments || [])).next()); 22 }); 23}; 24var __generator = (this && this.__generator) || function (thisArg, body) { 25 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 26 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 27 function verb(n) { return function (v) { return step([n, v]); }; } 28 function step(op) { 29 if (f) throw new TypeError("Generator is already executing."); 30 while (g && (g = 0, op[0] && (_ = 0)), _) try { 31 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; 32 if (y = 0, t) op = [op[0] & 2, t.value]; 33 switch (op[0]) { 34 case 0: case 1: t = op; break; 35 case 4: _.label++; return { value: op[1], done: false }; 36 case 5: _.label++; y = op[1]; op = [0]; continue; 37 case 7: op = _.ops.pop(); _.trys.pop(); continue; 38 default: 39 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 40 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 41 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 42 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 43 if (t[2]) _.ops.pop(); 44 _.trys.pop(); continue; 45 } 46 op = body.call(thisArg, _); 47 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 48 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 49 } 50}; 51import { Distiller } from './application.js'; 52import { AutoSave } from './AutoSaveHelper.js'; 53import { hideBayesNetStateTooltip, moveBayesNetStateTooltip, showBayesNetStateTooltip } from './BayesNet/TreeNodeMultiline.js'; 54var BAYES_BOT_HEADER_OPEN = '[['; 55var BAYES_BOT_HEADER_CLOSE = ']]'; 56var BAYES_BOT_CREATE_HEADER_MARKUP = 'Create a [[Bayes net]] out of a description of the future.'; 57var BAYES_BOT_DEFAULT_MODEL = 'gpt-5.6-luna'; 58var BAYES_BOT_MODEL_CHOICES = [ 59 { id: 'gpt-5.6-luna', label: 'GPT-5.6 Luna', disabled: false }, 60 { id: 'gpt-5.6-sol', label: 'GPT-5.6 Sol', disabled: false }, 61 { id: 'gpt-6-astra', label: 'GPT-6 Astra', disabled: true }, 62]; 63function bayesBotIsoDate(value) { 64 if (value == null || value === '') { 65 return ''; 66 } 67 if (value instanceof Date && !isNaN(value.getTime())) { 68 var utcMidnight = value.getUTCHours() === 0 && 69 value.getUTCMinutes() === 0 && 70 value.getUTCSeconds() === 0; 71 var year = utcMidnight ? value.getUTCFullYear() : value.getFullYear(); 72 var month = (utcMidnight ? value.getUTCMonth() : value.getMonth()) + 1; 73 var day = utcMidnight ? value.getUTCDate() : value.getDate(); 74 var pad = function (n) { return (n < 10 ? '0' + n : String(n)); }; 75 return year + '-' + pad(month) + '-' + pad(day); 76 } 77 var match = String(value).trim().match(/^(\d{4}-\d{2}-\d{2})/); 78 return match ? match[1] : ''; 79} 80var BAYES_BOT_BAYES_NET_INFO = '<div style="font-size:13px;line-height:1.5;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;">' 81 + 'A probabilistic model of a forecasting question. Each node is an observable event; ' 82 + 'an arrow means learning the parent should update the child. The graph stays open so later evidence can move the primary forecast.' 83 + '</div>'; 84function isLegacyHormuzPlaceholder(value) { 85 var plain = stripBayesBotHeaderMarkup(String(value || '')).trim().toLowerCase(); 86 return plain.indexOf('strait of hormuz') >= 0 && plain.indexOf('return to normal') >= 0; 87} 88var BAYES_BOT_AGENT_EXAMPLE_PROMPTS = [ 89 'AstraBot go to this link and propose a node that will top the leaderboard. Find a very early, super diagnostic signal. It\'s hard.', 90 'hey claude go to this URL and explain how information flows through the model in plain english.', 91 'FutureSearch go to the URL below and audit the forecasts in this model.' 92]; 93var BAYES_BOT_CREATE_AGENT_EXAMPLE_PROMPTS = [ 94 'AstraBot, go to the following link and convert the attached Dwarkesh podcast transcript into a bayes net.', 95 'FutureSearch please render Cowen\'s argument in the attached article in bayes net form here', 96 'hey claude what\'s a good p(doom) for someone who\'s just getting into dooming? make a bayes net on this site to supp
96ort your view.' 97]; 98var BAYES_BOT_AUTH_PROPOSE_MESSAGE = 'Please sign in or create an account to start contributing to this Bayes net'; 99var BAYES_BOT_AUTH_CREATE_MESSAGE = 'Please sign in or create an account to generate a Bayes net'; 100var BAYES_BOT_AUTH_AGENT_MESSAGE = 'Please sign in or create an account to connect your agent to this session.'; 101var BAYES_BOT_AUTH_BRANCH_MESSAGE = 'Please sign in or create an account to merge or clone a branch'; 102function bayesBotAgentConnectOrigin(hostname, port) { 103 var host = String(hostname || '').trim() || 'localhost'; 104 var hostLower = host.toLowerCase(); 105 var isLocal = hostLower === 'localhost' || 106 hostLower === '127.0.0.1' || 107 hostLower === '[::1]' || 108 hostLower === '::1'; 109 var rawPort = port != null ? String(port) : ''; 110 if (isLocal) { 111 var portPart_1 = rawPort && rawPort !== '80' ? ':' + rawPort : ''; 112 return 'http://' + host + portPart_1; 113 } 114 var portPart = rawPort && rawPort !== '443' ? ':' + rawPort : ''; 115 return 'https://' + host + portPart; 116} 117function stripBayesBotHeaderMarkup(markup) { 118 return String(markup || '').split(BAYES_BOT_HEADER_OPEN).join('').split(BAYES_BOT_HEADER_CLOSE).join(''); 119} 120function parseBayesBotHeaderMarkup(markup) { 121 var parts = []; 122 var remaining = String(markup || ''); 123 while (remaining.length) { 124 var open_1 = remaining.indexOf(BAYES_BOT_HEADER_OPEN); 125 if (open_1 < 0) { 126 parts.push({ text: remaining, clickable: false }); 127 break; 128 } 129 if (open_1 > 0) { 130 parts.push({ text: remaining.slice(0, open_1), clickable: false }); 131 } 132 var close_1 = remaining.indexOf(BAYES_BOT_HEADER_CLOSE, open_1 + BAYES_BOT_HEADER_OPEN.length); 133 if (close_1 < 0) { 134 parts.push({ text: remaining.slice(open_1 + BAYES_BOT_HEADER_OPEN.length), clickable: false }); 135 break; 136 } 137 parts.push({ 138 text: remaining.slice(open_1 + BAYES_BOT_HEADER_OPEN.length, close_1), 139 clickable: true, 140 }); 141 remaining = remaining.slice(close_1 + BAYES_BOT_HEADER_CLOSE.length); 142 } 143 return parts.filter(function (p) { return p.text.length > 0; }); 144} 145function bayesBotHeaderInfoHtml(title, body) { 146 var escapeHtml = function (value) { 147 return String(value == null ? '' : value) 148 .replace(/&/g, '&') 149 .replace(/</g, '<') 150 .replace(/>/g, '>') 151 .replace(/"/g, '"') 152 .replace(/'/g, '''); 153 }; 154 var safeTitle = escapeHtml(title); 155 var safeBody = escapeHtml(body); 156 return '<div style="font-size:13px;line-height:1.5;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;">' 157 + '<span style="font-family:Inter,sans-serif;font-weight:600;color:#3B82F6;">' + safeTitle + '</span> ' 158 + safeBody 159 + '</div>'; 160} 161var BayesBot = /** @class */ (function () { 162 function BayesBot(params) { 163 var _this = this; 164 var _a, _b; 165 this.loadingSteps = ko.observable(false); 166 this.currentStageWorkflow = ko.observable(null); 167 this.questionSet = ko.observable(null); 168 this.workflowUndefined = ko.observable(false); 169 /** BayesBot only renders bayes-net workflow elements (interactive or readonly). */ 170 this.isBayesNetElement = function (element) { 171 var _a, _b; 172 if (!element) { 173 return false; 174 } 175 var view = typeof element.view === 'function' ? element.view() : element.view; 176 if (view === 'bayes-net' || view === 'bayes-net-results') { 177 return true; 178 } 179 if (element.type === 'bayes-net-readonly') { 180 return true; 181 } 182 var generalType = typeof element.generalQuestionType === 'function' 183 ? (_a = element.generalQuestionType()) === null || _a === void 0 ? void 0 : _a.value 184 : (_b = element.generalQuestionType) === null || _b === void 0 ? void 0 : _b.value; 185 return generalType === 'bayesNet'; 186 }; 187 this.nodeProposalText = ko.observable(''); 188 this.nodeProposalSubmitting = ko.observable(false); 189 this.lastBayesBotJobId = ko.observable(null); 190 this.proposalPhase = ko.observable('idle'); 191 this.submittedProposalText = ko.observable(''); 192 this.proposalStatusText = ko.observable(''); 193 this.displayedProposalStatusText = ko.observable(''); 194 this.proposalStatusAnimating = ko.observable(false); 195 this.proposalStatusFreezeWidth = ko.observable(''); 196 this.proposalFinalResponse = ko.observable(''); 197 this.proposalInfoValue = ko.observable(null); 198 this.proposalLifetimeInformation = ko.observable(null); 199 this.proposalSpecNotes = ko.observableArray([]); 200 this.showCreateNetLifetimeScore = ko.observable(false); 201 this.addedSignalExplainerOpen = ko.observable(false); 202 this.addedSignalExplainerRow = ko.observable(null); 203 this.shannonExplainerOpen = ko.observable(false); 204 this.leaderboardPanelTab = ko.observable('leaderboard'); 205 this.specLogRows = ko.observableArray([]); 206 this.leaderboardNodes = ko.observableArray([]); 207 this.leaderboardRankOf = ko.observable(0); 208 this.leaderboardPrimaryNodeId = ko.observable(null); 209 this.selectedCanvasNodeId = ko.observable(null); 210 this.pinnedLeaderboardNodeId = ko.observable(null); 211 this.leaderboardScrollFrame = null; 212 this.workbenchHeightPx = ko.observable(135); 213 this.proposeShare = ko.observable(0.5); 214 this.clearingNet = ko.observable(false); 215 this.showClearNetDevButton = false;
216 this.isCreateMode = ko.observable(false); 217 this.authModalOpen = ko.observable(false); 218 this.authModalMode = ko.observable('signup'); 219 this.authModalContext = ko.observable('header'); 220 this.authUsername = ko.observable(''); 221 this.authEmail = ko.observable(''); 222 this.authPassword = ko.observable(''); 223 this.authError = ko.observable(''); 224 this.authSubmitting = ko.observable(false); 225 this.myModelsMenuOpen = ko.observable(false); 226 this.publicModelsMenuOpen = ko.observable(false); 227 this.myModels = ko.observableArray([]); 228 this.myModelsQuery = ko.observable(''); 229 this.myModelsLoading = ko.observable(false); 230 this.myModelsHasMore = ko.observable(false); 231 this.myModelsLoaded = ko.observable(false); 232 this.publicModelGroups = ko.observableArray([]); 233 this.publicModelsLoading = ko.observable(false); 234 this.publicModelsLoaded = ko.observable(false); 235 this.myModelsOffset = 0; 236 this.myModelsSearchTimer = null; 237 this.myModelsRequestToken = 0; 238 this.topMenuOpen = ko.pureComputed(function () { 239 return _this.myModelsMenuOpen() || _this.publicModelsMenuOpen(); 240 }); 241 this.myModelsEmptyMessage = ko.pureComputed(function () { 242 if (!_this.myModelsLoaded() || _this.myModels().length > 0 || _this.myModelsLoading()) { 243 return ''; 244 } 245 var q = String(_this.myModelsQuery() || '').trim(); 246 if (q) { 247 return 'No models match that search.'; 248 } 249 return "You don't have any models yet."; 250 }); 251 this.isTempVisitor = ko.pureComputed(function () { 252 var user = Distiller.currentUser && Distiller.currentUser(); 253 if (!user) { 254 return false; 255 } 256 if (Distiller.isBayesBotTempUser) { 257 return Distiller.isBayesBotTempUser(); 258 } 259 var email = user.email != null ? String(user.email) : ''; 260 return !email || email.indexOf('@') < 0; 261 }); 262 this.bayesBotModelChoices = BAYES_BOT_MODEL_CHOICES; 263 this.selectedBayesBotModel = ko.observable(BAYES_BOT_DEFAULT_MODEL); 264 this.bayesBotModelMenuOpen = ko.observable(false); 265 this.selectedBayesBotModelLabel = ko.pureComputed(function () { 266 var id = _this.selectedBayesBotModel(); 267 for (var i = 0; i < _this.bayesBotModelChoices.length; i++) { 268 if (_this.bayesBotModelChoices[i].id === id) { 269 return _this.bayesBotModelChoices[i].label; 270 } 271 } 272 return 'GPT-5.6 Luna'; 273 }); 274 this.authContextMessage = ko.pureComputed(function () { 275 var context = _this.authModalContext(); 276 if (context === 'create') { 277 return BAYES_BOT_AUTH_CREATE_MESSAGE; 278 } 279 if (context === 'propose') { 280 return BAYES_BOT_AUTH_PROPOSE_MESSAGE; 281 } 282 if (context === 'agent') { 283 return BAYES_BOT_AUTH_AGENT_MESSAGE; 284 } 285 if (context === 'branch') { 286 return BAYES_BOT_AUTH_BRANCH_MESSAGE; 287 } 288 return ''; 289 }); 290 this.draftProvisioning = ko.observable(false); 291 this.draftProvisionError = ko.observable(''); 292 this.draftNeedsReplacement = ko.observable(false); 293 this.boundCommunityId = ko.observable(null); 294 this.boundQuestionText = ko.observable(''); 295 this.boundResolutionCriteria = ko.observable(''); 296 this.boundResolutionDate = ko.observable(''); 297 this.headerMarkup = ko.observable(''); 298 this.displayedHeaderText = ko.observable(''); 299 this.headerAnimating = ko.observable(false); 300 this.headerAnimationComplete = ko.observable(true); 301 this.headerInfoHtml = ko.observable(''); 302 this.headerTypewriterTimer = null; 303 this.headerTypewriterToken = 0; 304 /** Canvas user. Authors edit the shared template; other visitors get a personal copy on write. */ 305 this.viewerUserId = Distiller.currentUser && Distiller.currentUser() 306 ? Distiller.currentUser().userId 307 : null; 308 this.viewingSharedTemplate = true; 309 this.liveTemplateBuild = false;
310 /** True when this visitor authored the template and should edit it in place. */ 311 this.ownsCanonicalTemplate = false; 312 this.authorOwnsTemplate = ko.observable(false); 313 this.personalCopyNetId = null; 314 this.cloneReady = false; 315 this.clonePromise = null; 316 this.preparingCloneForEdits = false; 317 this.sharedTemplateNetId = ko.observable(null); 318 this.canvasMountedForTemplateNetId = null; 319 this.authorBayesNetSet = ko.observable(null); 320 this.authorBayesNet = null; 321 this.bayesBotEventSource = null; 322 this.bayesBotSseUserId = null; 323 this.bayesBotSseReconnectTimer = null; 324 this.bayesBotPollTimer = null; 325 this.lifetimeInfoChart = null; 326 this.pendingBayesBotGraphEvents = []; 327 this.statusTypewriterTimer = null; 328 this.statusTypewriterToken = 0; 329 this.proposalJobSettled = false; 330 this.proposePanelTab = ko.observable('propose'); 331 this.agentKey = ko.observable(null); 332 this.agentStudyBaseUrl = ko.observable(null); 333 this.agentKeyLoading = ko.observable(false); 334 this.agentConnectCopied = ko.observable(false); 335 this.displayedAgentExampleText = ko.observable(''); 336 this.agentExampleAnimating = ko.observable(false); 337 this.agentActivityLive = ko.observable(false); 338 this.agentIsConnected = ko.observable(false); 339 this.agentActivitySpinning = ko.observable(false); 340 this.agentActivitySpinnerFrame = ko.observable('⣾'); 341 this.agentConnectBrailleCells = ko.observableArray([]); 342 this.agentActivityLatestText = ko.observable(''); 343 this.agentActivityLines = ko.observableArray([]); 344 this.agentKeyReady = null; 345 this.agentConnectCopiedTimer = null; 346 this.agentExampleTimer = null; 347 this.agentExampleToken = 0; 348 this.agentExampleIndex = 0; 349 this.agentActivitySpinnerTimer = null; 350 this.agentActivitySpinnerTick = 0; 351 this.agentTerminalStickToBottom = true; 352 this.isProposalStatusFill = ko.pureComputed(function () { 353 var phase = _this.proposalPhase(); 354 return phase === 'processing' || phase === 'error' || phase === 'complete'; 355 }); 356 this.showProposeComposer = ko.pureComputed(function () { 357 return _this.proposePanelTab() === 'propose' && !_this.isProposalStatusFill(); 358 }); 359 this.showProposalStatusCard = ko.pureComputed(function () { 360 return _this.proposePanelTab() === 'propose' && !!(_this.submittedProposalText() || _this.isProposalStatusFill()); 361 }); 362 this.showAgentConnect = ko.pureComputed(function () { 363 return _this.proposePanelTab() === 'connect'; 364 }); 365 this.showConnectTabSpinner = ko.pureComputed(function () { 366 return _this.agentIsConnected() && _this.proposePanelTab() === 'connect'; 367 }); 368 this.proposePanelTitle = ko.pureComputed(function () { 369 return _this.isCreateMode() ? 'Describe the future' : 'Propose a node'; 370 }); 371 this.selectProposeTab = function () { 372 _this.exitBranchView(); 373 _this.proposePanelTab('propose'); 374 _this.stopAgentExampleRotation(); 375 }; 376 this.selectConnectTab = function () { 377 _this.exitBranchView(); 378 _this.proposePanelTab('connect'); 379 if (!_this.agentActivityLive()) { 380 _this.startAgentExampleRotation(); 381 } 382 }; 383 this.showBranchTab = ko.pureComputed(function () { 384 return !_this.isCreateMode(); 385 }); 386 this.showBranchList = ko.pureComputed(function () { 387 return _this.proposePanelTab() === 'branches'; 388 }); 389 this.branchRows = ko.observableArray([]); 390 this.selectedBranchCopyNetId = ko.observable(null); 391 this.viewingBranchCopyNetId = ko.observable(null); 392 this.canonicalLifetimeInformation = null; 393 this.branchShareCopied = ko.observable(false); 394 this.mergeModalOpen = ko.observable(false); 395 this.branchActionMode = ko.observable('merge'); 396 this.mergePhase = ko.observable('choose'); 397 this.mergeError = ko.observable(''); 398 this.mergeStatusText = ko.observable(''); 399 this.displayedMergeStatusText = ko.observable(''); 400 this.mergeStatusAnimating = ko.observable(false); 401 this.mergeInFlight = ko.observable(false); 402 this.mergeBarAuthorName = ko.observable(''); 403 this.scoresStatus = ko.observable(''); 404 this.mergeDoneTimer = null; 405 this.branchShareCopiedTimer = null; 406 this.mergeForecastPending = false;
407 this.mergeFinishStarted = false; 408 this.mergeStatusJobId = ''; 409 this.pendingMergeResult = null; 410 this.mergeStatusTypewriterToken = 0; 411 this.mergeStatusTypewriterTimer = null; 412 this.viewingBranchAuthorName = ko.pureComputed(function () { 413 var id = _this.selectedBranchCopyNetId(); 414 if (id == null) { 415 return ''; 416 } 417 var rows = _this.branchRows(); 418 for (var i = 0; i < rows.length; i++) { 419 if (rows[i] && rows[i].copyNetId === id) { 420 if (rows[i].isMain) { 421 return 'Main'; 422 } 423 return rows[i].authorName ? String(rows[i].authorName) : 'Unknown'; 424 } 425 } 426 return ''; 427 }); 428 this.showBranchInvite = ko.pureComputed(function () { 429 if (!_this.authorOwnsTemplate()) { 430 return false; 431 } 432 var rows = _this.branchRows(); 433 for (var i = 0; i < rows.length; i++) { 434 if (rows[i] && !rows[i].isMain) { 435 return false; 436 } 437 } 438 return true; 439 }); 440 this.branchCanvasBarAuthorName = ko.pureComputed(function () { 441 var viewing = _this.viewingBranchAuthorName(); 442 if (viewing) { 443 return viewing; 444 } 445 return _this.mergeInFlight() ? _this.mergeBarAuthorName() : ''; 446 }); 447 this.branchCanvasBarVisible = ko.pureComputed(function () { 448 return !!_this.branchCanvasBarAuthorName(); 449 }); 450 this.showMergeBarStatus = ko.pureComputed(function () { 451 return (_this.mergeInFlight() && 452 !_this.mergeModalOpen() && 453 !!(_this.displayedMergeStatusText() || _this.mergeStatusAnimating() || _this.mergeStatusText())); 454 }); 455 this.branchActionTitle = ko.pureComputed(function () { 456 var cloning = _this.branchActionMode() === 'clone'; 457 var phase = _this.mergePhase(); 458 if (phase === 'working') { 459 return cloning ? 'Cloning this branchâ¦' : 'Merging this branchâ¦'; 460 } 461 if (phase === 'done') { 462 return cloning ? 'Cloned.' : 'Merged.'; 463 } 464 return cloning ? 'Clone this branch?' : 'Merge this branch?'; 465 }); 466 this.branchActionExplanation = ko.pureComputed(function () { 467 if (_this.branchActionMode() === 'clone') { 468 return 'Clone gives you a perfect copy of this branch and archives the version you are on. Your current version is replaced by this copy.'; 469 } 470 return 'Merge is strictly additive. It copies your current version, then adds nodes from this branch that you do not already have. It does not remove nodes that exist only on your version.'; 471 }); 472 this.exitBranchView = function () { 473 if (!_this.selectedBranchCopyNetId()) { 474 return; 475 } 476 _this.selectedBranchCopyNetId(null); 477 _this.viewingBranchCopyNetId(null); 478 _this.refreshBranchRowSelection(); 479 _this.restoreOwnNetView(); 480 }; 481 this.branchShareUrl = ko.pureComputed(function () { 482 var sid = _this.resolveBoundCommunityId(); 483 if (!sid) { 484 return ''; 485 } 486 return window.location.origin + '?sid=' + sid; 487 }); 488 this.selectBranchesTab = function () { 489 _this.proposePanelTab('branches'); 490 _this.stopAgentExampleRotation(); 491 _this.loadBranchList(); 492 _this.scheduleBranchListWorkbenchHeight(); 493 }; 494 this.branchTabTooltip = ko.pureComputed(function () { 495 return _this.branchRows().length ? 'Branches' : 'Share this page'; 496 }); 497 this.onBranchIconPointerEnter = function (_data, event) { 498 showBayesNetStateTooltip(_this.branchTabTooltip(), event); 499 }; 500 this.onLogsIconPointerEnter = function (_data, event) { 501 showBayesNetStateTooltip('Logs', event); 502 }; 503 this.onWorkbenchIconPointerMove = function (_data, event) { 504 moveBayesNetStateTooltip(event); 505 }; 506 this.onWorkbenchIconPointerLeave = function () { 507 hideBayesNetStateTooltip(); 508 }; 509 this.branchAvatarColor = function (userId) { 510 var colors = Distiller.colorsArray && Distiller.colorsArray(); 511 if (!colors || !colors.length) { 512 return '#8898AA'; 513 } 514 var id = parseInt(String(userId), 10) || 0; 515 if (id < colors.length) { 516 return colors[id]; 517 } 518 return colors[id % colors.length]; 519 }; 520 this.mapBranchListRow = function (row, selectedId) { 521 var added = parseInt(String(row.addedNodeCount), 10) || 0; 522 var removed = parseInt(String(row.removedNodeCount), 10) || 0; 523 var forecasts = parseInt(String(row.addedForecastCount), 10) || 0;
524 var copyNetId = parseInt(String(row.copyNetId), 10); 525 var copyUserId = parseInt(String(row.copyUserId), 10) || 0; 526 var authorName = row.authorName ? String(row.authorName) : 'Unknown'; 527 var isMain = !!row.isMain; 528 var isCurrent = !!row.isCurrent; 529 return { 530 copyNetId: copyNetId, 531 copyUserId: copyUserId, 532 authorName: authorName, 533 isMain: isMain, 534 isCurrent: isCurrent, 535 showActions: !isCurrent, 536 avatarInitials: Distiller.avatarInitials 537 ? Distiller.avatarInitials(isMain ? 'Main' : authorName) 538 : (isMain ? 'M' : authorName.slice(0, 2).toUpperCase()), 539 avatarColor: _this.branchAvatarColor(copyUserId), 540 addedNodeCount: added, 541 removedNodeCount: removed, 542 addedForecastCount: forecasts, 543 addedLabel: '+' + added + (added === 1 ? ' node' : ' nodes'), 544 removedLabel: '-' + removed + (removed === 1 ? ' node' : ' nodes'), 545 forecastLabel: '+' + forecasts + (forecasts === 1 ? ' forecast' : ' forecasts'), 546 mergedLabel: !isMain && row.lastMergedAt 547 ? 'Merged on ' + _this.formatSpecLogTime(row.lastMergedAt) 548 : '', 549 isSelected: selectedId != null && selectedId === copyNetId, 550 }; 551 }; 552 this.loadBranchList = function () { 553 var currentUser = Distiller.currentUser && Distiller.currentUser(); 554 var userId = currentUser && currentUser.userId; 555 if (!userId || _this.isCreateMode()) { 556 return; 557 } 558 Distiller.httpGetAsync(Distiller.apiEndpoint + '/api/bayesBotBranches/' + userId 559 + '?communityId=' + encodeURIComponent(String(_this.resolveBoundCommunityId())), function (responseText) { 560 try { 561 var parsed = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 562 if (!parsed || parsed.ok === false) { 563 return; 564 } 565 var selectedId = _this.selectedBranchCopyNetId(); 566 var rows = []; 567 if (parsed.main && parsed.main.copyNetId) { 568 rows.push(_this.mapBranchListRow(parsed.main, selectedId)); 569 } 570 var branches = parsed.branches || []; 571 for (var i = 0; i < branches.length; i++) { 572 rows.push(_this.mapBranchListRow(branches[i], selectedId)); 573 } 574 _this.branchRows(rows); 575 _this.scheduleBranchListWorkbenchHeight(); 576 } 577 catch (e) { 578 console.error('BayesBot branch list parse failed:', e); 579 } 580 }); 581 }; 582 this.selectBranchRow = function (row) { 583 var copyNetId = row && row.copyNetId != null ? parseInt(String(row.copyNetId), 10) : NaN; 584 if (!Number.isFinite(copyNetId) || copyNetId <= 0) { 585 return; 586 } 587 if (row.isCurrent) { 588 _this.exitBranchView(); 589 return; 590 } 591 if (_this.selectedBranchCopyNetId() === copyNetId) { 592 _this.exitBranchView(); 593 return; 594 } 595 _this.selectedBranchCopyNetId(copyNetId); 596 _this.refreshBranchRowSelection(); 597 _this.inspectBranch(copyNetId); 598 }; 599 this.refreshBranchRowSelection = function () { 600 var selectedId = _this.selectedBranchCopyNetId(); 601 var rows = _this.branchRows().map(function (row) { return (__assign(__assign({}, row), { isSelected: selectedId != null && row.copyNetId === selectedId })); }); 602 _this.branchRows(rows); 603 }; 604 this.inspectBranch = function (copyNetId) { 605 var currentUser = Distiller.currentUser && Distiller.currentUser(); 606 var userId = currentUser && currentUser.userId; 607 if (!userId) { 608 return; 609 } 610 Distiller.httpGetAsync(Distiller.apiEndpoint + '/api/bayesBotBranchView/' + userId + '/' + copyNetId 611 + '?communityId=' + encodeURIComponent(String(_this.resolveBoundCommunityId())), function (responseText) { 612 try { 613 var parsed = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 614 if (!parsed || parsed.ok === false || !parsed.bayesNet) { 615 return; 616 } 617 _this.rememberCanonicalLifetime(); 618 _this.viewingBranchCopyNetId(copyNetId); 619 var net = _this.authorBayesNet; 620 if (net && typeof net.load === 'function') { 621 net.netId = copyNetId; 622 net.load(parsed.bayesNet); 623 } 624 if (parsed.leaderboard && parsed.leaderboard.ok !== false) { 625 _this.leaderboardPrimaryNodeId(parsed.leaderboard.primaryNodeId || null); 626 _this.applyLeaderboardNodes(parsed.leaderboard.nodes || [], parsed.leaderboard.rankOf); 627 _this.applyPrimaryNodeHighlight(); 628 } 629 else { 630 _this.loadLeaderboard(); 631 } 632 if (_this.lifetimeHasChart(parsed.lifetimeInformation)) { 633 _this.presentPersistedLifetimeInformation(parsed.lifetimeInformation); 634 } 635 } 636 catch (e) { 637 console.error('BayesBot branch view parse failed:', e); 638 } 639 }); 640 }; 641 this.lifetimeHasChart = function (lifetimeInformation) {
642 return !!(lifetimeInformation && 643 Array.isArray(lifetimeInformation.breakpoints) && 644 lifetimeInformation.breakpoints.length); 645 }; 646 this.rememberCanonicalLifetime = function () { 647 if (_this.viewingBranchCopyNetId()) { 648 return; 649 } 650 var current = _this.proposalLifetimeInformation(); 651 if (_this.lifetimeHasChart(current)) { 652 _this.canonicalLifetimeInformation = current; 653 } 654 }; 655 this.restoreOwnNetView = function () { 656 _this.viewingBranchCopyNetId(null); 657 void _this.reloadAuthorBayesNetGraph(); 658 _this.loadLeaderboard(); 659 if (_this.lifetimeHasChart(_this.canonicalLifetimeInformation)) { 660 _this.presentPersistedLifetimeInformation(_this.canonicalLifetimeInformation); 661 } 662 }; 663 this.openMergeModal = function (row, event) { 664 _this.openBranchActionModal(row, event, 'merge'); 665 }; 666 this.openCloneModal = function (row, event) { 667 _this.openBranchActionModal(row, event, 'clone'); 668 }; 669 this.openBranchActionModal = function (row, event, mode) { 670 if (event && event.stopPropagation) { 671 event.stopPropagation(); 672 } 673 if (_this.isTempVisitor()) { 674 _this.openAuthModal('branch'); 675 return; 676 } 677 if (_this.mergeInFlight()) { 678 _this.mergePhase('working'); 679 _this.mergeModalOpen(true); 680 return; 681 } 682 if (row && row.copyNetId != null) { 683 _this.selectedBranchCopyNetId(parseInt(String(row.copyNetId), 10)); 684 _this.refreshBranchRowSelection(); 685 } 686 _this.branchActionMode(mode === 'clone' ? 'clone' : 'merge'); 687 _this.mergePhase('choose'); 688 _this.mergeError(''); 689 _this.clearMergeStatusPresentation(); 690 _this.mergeModalOpen(true); 691 }; 692 this.closeMergeModal = function () { 693 if (_this.mergePhase() === 'done') { 694 return; 695 } 696 if (_this.mergePhase() === 'working' && _this.mergeInFlight()) { 697 _this.mergeModalOpen(false); 698 return; 699 } 700 _this.mergeModalOpen(false); 701 _this.mergePhase('choose'); 702 _this.mergeError(''); 703 _this.clearMergeStatusPresentation(); 704 }; 705 this.clearMergeStatusPresentation = function () { 706 _this.mergeStatusTypewriterToken += 1; 707 if (_this.mergeStatusTypewriterTimer) { 708 clearTimeout(_this.mergeStatusTypewriterTimer); 709 _this.mergeStatusTypewriterTimer = null; 710 } 711 _this.mergeStatusAnimating(false); 712 _this.mergeStatusText(''); 713 _this.displayedMergeStatusText(''); 714 }; 715 this.setMergeStatusText = function (next) { 716 var target = next == null ? '' : String(next); 717 _this.mergeStatusText(target); 718 if (_this.displayedMergeStatusText() === target && !_this.mergeStatusAnimating()) { 719 return; 720 } 721 var token = ++_this.mergeStatusTypewriterToken; 722 if (_this.mergeStatusTypewriterTimer) { 723 clearTimeout(_this.mergeStatusTypewriterTimer); 724 _this.mergeStatusTypewriterTimer = null; 725 } 726 var hadText = _this.displayedMergeStatusText().length > 0; 727 _this.mergeStatusAnimating(hadText); 728 var reveal = function () { 729 if (token !== _this.mergeStatusTypewriterToken) { 730 return; 731 } 732 _this.mergeStatusAnimating(false); 733 _this.displayedMergeStatusText(target); 734 _this.mergeStatusTypewriterTimer = null; 735 }; 736 if (!hadText) { 737 reveal(); 738 return; 739 } 740 var backspace = function () { 741 if (token !== _this.mergeStatusTypewriterToken) { 742 return; 743 } 744 var shown = _this.displayedMergeStatusText(); 745 if (shown.length > 0) { 746 _this.displayedMergeStatusText(shown.slice(0, -1)); 747 _this.mergeStatusTypewriterTimer = setTimeout(backspace, 22); 748 return; 749 } 750 _this.mergeStatusTypewriterTimer = setTimeout(reveal, 80
750); 751 }; 752 backspace(); 753 }; 754 this.mergeResponseStillWorking = function (parsed) { 755 if (!parsed || _this.branchActionMode() === 'clone') { 756 return false; 757 } 758 return parsed.forecastMode === 'generate' || parsed.scoresStatus === 'filling_forecasts'; 759 }; 760 this.rememberPendingMerge = function (parsed) { 761 var prev = _this.pendingMergeResult || {}; 762 _this.pendingMergeResult = Object.assign({}, prev, parsed || {}); 763 if (parsed && parsed.mergeStatusJobId) { 764 _this.mergeStatusJobId = String(parsed.mergeStatusJobId); 765 } 766 _this.mergeForecastPending = true; 767 }; 768 this.holdMergeForForecasts = function (parsed) { 769 _this.rememberPendingMerge(parsed); 770 _this.mergePhase('working'); 771 _this.mergeInFlight(true); 772 }; 773 this.endMergeFlight = function () { 774 _this.mergeInFlight(false); 775 _this.mergeForecastPending = false; 776 _this.mergeFinishStarted = false; 777 _this.mergeStatusJobId = ''; 778 _this.pendingMergeResult = null; 779 _this.mergeBarAuthorName(''); 780 _this.clearMergeStatusPresentation(); 781 }; 782 this.claimMergeFinish = function () { 783 if (!_this.mergeInFlight() || _this.mergeFinishStarted) { 784 return false; 785 } 786 _this.mergeFinishStarted = true; 787 return true; 788 }; 789 this.finishSynchronousMerge = function (parsed) { 790 if (!_this.claimMergeFinish()) { 791 return; 792 } 793 _this.mergePhase('done'); 794 _this.clearMergeStatusPresentation(); 795 if (!_this.mergeModalOpen()) { 796 _this.endMergeFlight(); 797 _this.mergePhase('choose'); 798 _this.applyMergeSuccess(parsed); 799 return; 800 } 801 if (_this.mergeDoneTimer) { 802 clearTimeout(_this.mergeDoneTimer); 803 } 804 _this.mergeDoneTimer = setTimeout(function () { 805 _this.mergeDoneTimer = null; 806 _this.mergeModalOpen(false); 807 _this.mergePhase('choose'); 808 _this.endMergeFlight(); 809 _this.applyMergeSuccess(parsed); 810 }, 700); 811 }; 812 this.completeForecastMerge = function (data) { 813 if (!_this.claimMergeFinish()) { 814 return; 815 } 816 var stashed = _this.pendingMergeResult || {}; 817 var incomingLifetime = data && data.lifetimeInformation ? data.lifetimeInformation : null; 818 var stashedLifetime = stashed.lifetimeInformation && stashed.lifetimeInformation.status !== 'filling_forecasts' 819 ? stashed.lifetimeInformation 820 : null; 821 var parsed = Object.assign({}, stashed, { 822 lifetimeInformation: incomingLifetime || stashedLifetime, 823 scoresStatus: null, 824 }); 825 if (!parsed.templateNetId && parsed.personalCopyNetId == null && data && data.netId != null && parsed.ownsCanonicalTemplate !== false) { 826 parsed.templateNetId = data.netId; 827 } 828 _this.mergeModalOpen(false); 829 _this.mergePhase('choose'); 830 _this.mergeError(''); 831 _this.scoresStatus(''); 832 _this.endMergeFlight(); 833 _this.applyMergeSuccess(parsed); 834 }; 835 this.failForecastMerge = function (data) { 836 if (!_this.claimMergeFinish()) { 837 return; 838 } 839 _this.endMergeFlight(); 840 _this.mergePhase('error'); 841 _this.mergeError((data && data.message) || 'Forecasts could not be incorporated.'); 842 _this.mergeModalOpen(true); 843 }; 844 this.isMergeForecastJob = function (data) { 845 var jobId = data && data.jobId != null ? String(data.jobId) : ''; 846 return jobId.indexOf('merge-forecasts:') === 0; 847 }; 848 this.onBayesBotMergeStatusEvent = function (event) { 849 var data = _this.parseBayesBotSseData(event); 850 if (!data || (!_this.mergeInFlight() && !_this.mergeForecastPending)) { 851 return; 852 } 853 if (data.jobId) { 854 var jobId = String(data.jobId); 855 if (_this.mergeStatusJobId && _this.mergeStatusJobId !== jobId) { 856 return; 857 } 858 _this.mergeStatusJobId = jobId; 859 } 860 if (data.phase === 'complete') { 861 _this.completeForecastMerge(data); 862 return; 863 } 864 if (data.phase === 'failed') { 865 _this.failForecastMerge(data); 866 return; 867 } 868 if (data.message) { 869 _this.setMergeStatusText(String(data.message)); 870 } 871 }; 872 this.applyMergeSuccess = function (parsed) { 873 _this.selectedBranchCopyNetId(null); 874 _this.viewingBranchCopyNetId(null); 875 if (parsed && parsed.lifetimeInformation) { 876 _this.presentPersistedLifetimeInformation(parsed.lifetimeInformation); 877 } 878 else if (parsed && parsed.scoresStatus) { 879 _this.scoresStatus(String(parsed.scoresStatus)); 880 } 881 _this.refreshBranchRowSelection(); 882 var personalCopyNetId = parsed && parsed.personalCopyNetId != null 883 ? parseInt(String(parsed.personalCopyNetId), 10) 884 : NaN; 885 if (Number.isFinite(personalCopyNetId) && personalCopyNetId > 0 && !parsed.ownsCanonicalTemplate) { 886 _this.ownsCanonicalTemplate = false;
887 _this.authorOwnsTemplate(false); 888 void _this.adoptPersonalCopyFromServer(personalCopyNetId, parsed.setId).then(function () { 889 _this.loadBranchList(); 890 _this.loadSpecLogs(true); 891 }); 892 return; 893 } 894 if (parsed && parsed.templateNetId != null) { 895 var templateNetId = parseInt(String(parsed.templateNetId), 10); 896 if (Number.isFinite(templateNetId) && templateNetId > 0) { 897 _this.sharedTemplateNetId(templateNetId); 898 } 899 } 900 _this.restoreOwnNetView(); 901 _this.loadBranchList(); 902 _this.loadSpecLogs(true); 903 }; 904 this.confirmMergeBranch = function (includeForecasts) { 905 var currentUser = Distiller.currentUser && Distiller.currentUser(); 906 var userId = currentUser && currentUser.userId; 907 var copyNetId = _this.selectedBranchCopyNetId(); 908 if (!userId || !copyNetId || _this.mergePhase() === 'working') { 909 return; 910 } 911 _this.mergePhase('working'); 912 _this.mergeError(''); 913 _this.mergeInFlight(true); 914 _this.mergeForecastPending = false; 915 _this.mergeFinishStarted = false; 916 _this.mergeStatusJobId = ''; 917 _this.pendingMergeResult = null; 918 _this.mergeBarAuthorName(_this.viewingBranchAuthorName() || _this.mergeBarAuthorName() || ''); 919 _this.setMergeStatusText('Mergingâ¦'); 920 var xmlHttp = new XMLHttpRequest(); 921 xmlHttp.onreadystatechange = function () { 922 if (xmlHttp.readyState !== 4) { 923 return; 924 } 925 if (!_this.mergeInFlight()) { 926 return; 927 } 928 var parsed = null; 929 try { 930 parsed = xmlHttp.responseText ? JSON.parse(xmlHttp.responseText) : null; 931 } 932 catch (e) { 933 parsed = null; 934 } 935 if (parsed && parsed.code === 'auth_required') { 936 _this.endMergeFlight(); 937 _this.mergePhase('choose'); 938 _this.mergeModalOpen(false); 939 _this.openAuthModal('branch'); 940 return; 941 } 942 if (xmlHttp.status === 200 && parsed && parsed.ok !== false) { 943 if (_this.mergeResponseStillWorking(parsed)) { 944 _this.holdMergeForForecasts(parsed); 945 return; 946 } 947 _this.finishSynchronousMerge(parsed); 948 return; 949 } 950 var dismissed = !_this.mergeModalOpen(); 951 _this.endMergeFlight(); 952 _this.mergePhase('error'); 953 _this.mergeError((parsed && parsed.error) || (_this.branchActionMode() === 'clone' ? 'Clone failed' : 'Merge failed')); 954 if (dismissed) { 955 _this.mergeModalOpen(true); 956 } 957 }; 958 xmlHttp.onerror = function () { 959 if (!_this.mergeInFlight()) { 960 return; 961 } 962 var dismissed = !_this.mergeModalOpen(); 963 _this.endMergeFlight(); 964 _this.mergePhase('error'); 965 _this.mergeError(_this.branchActionMode() === 'clone' ? 'Clone failed' : 'Merge failed'); 966 if (dismissed) { 967 _this.mergeModalOpen(true); 968 } 969 }; 970 var actionPath = _this.branchActionMode() === 'clone' 971 ? '/api/bayesBotCloneBranch/' 972 : '/api/bayesBotMergeBranch/'; 973 xmlHttp.open('POST', Distiller.apiEndpoint + actionPath + userId, true); 974 xmlHttp.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); 975 xmlHttp.send(JSON.stringify({ 976 copyNetId: copyNetId, 977 includeForecasts: !!includeForecasts, 978 communityId: _this.resolveBoundCommunityId(), 979 })); 980 }; 981 this.copyBranchShareUrl = function () { 982 var url = _this.branchShareUrl(); 983 if (!url || !Distiller.copyToClipboard) { 984 return; 985 } 986 Distiller.copyToClipboard(url, true); 987 _this.branchShareCopied(true); 988 if (_this.branchShareCopiedTimer) { 989 clearTimeout(_this.branchShareCopiedTimer); 990 } 991 _this.branchShareCopiedTimer = setTimeout(function () { 992 _this.branchShareCopied(false); 993 _this.branchShareCopiedTimer = null; 994 }, 400); 995 }; 996 this.selectLeaderboardTab = function () { 997 _this.leaderboardPanelTab('leaderboard'); 998 }; 999 this.selectInformationGainTab = function () { 1000 _this.leaderboardPanelTab('informationGain'); 1001 var needed = _this.measureMinWorkbenchHeightForInformationGain(); 1002 if (_this.workbenchHeightPx() < needed) { 1003 _this.workbenchHeightPx(_this.clampWorkbenchHeight(needed)); 1004 } 1005 var self = _this; 1006 setTimeout(function () { 1007 self.renderLifetimeInformationChart(); 1008 }, 50); 1009 }; 1010 this.selectLogsTab = function () { 1011 _this.leaderboardPanelTab('logs'); 1012 _this.loadSpecLogs(true); 1013 }; 1014 this.formatSpecLogTime = function (value) { 1015 if (value == null || value === '') { 1016 return ''; 1017 } 1018 var raw = value instanceof Date ? value : new Date(String(value).replace(' ', 'T')); 1019 if (isNaN(raw.getTime())) { 1020 return String(value); 1021 }
1022 return raw.toLocaleString(undefined, { 1023 month: 'short', 1024 day: 'numeric', 1025 year: 'numeric', 1026 hour: 'numeric', 1027 minute: '2-digit', 1028 }); 1029 }; 1030 this.scrollSpecLogsToBottom = function () { 1031 requestAnimationFrame(function () { 1032 var el = document.querySelector('.bayesBotLogsScroll'); 1033 if (el) { 1034 el.scrollTop = el.scrollHeight; 1035 } 1036 }); 1037 }; 1038 this.loadSpecLogs = function (scrollToBottom) { 1039 var currentUser = Distiller.currentUser && Distiller.currentUser(); 1040 var userId = currentUser && currentUser.userId; 1041 if (!userId) { 1042 return; 1043 } 1044 Distiller.httpGetAsync(Distiller.apiEndpoint + '/api/bayesBotLogs/' + userId 1045 + '?communityId=' + encodeURIComponent(String(_this.resolveBoundCommunityId() || '')), function (responseText) { 1046 try { 1047 var parsed = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 1048 if (!parsed || parsed.ok === false) { 1049 return; 1050 } 1051 var rows = (parsed.logs || []).map(function (row) { return ({ 1052 id: row && row.id != null ? row.id : null, 1053 text: row && row.text != null ? String(row.text) : '', 1054 timeLabel: _this.formatSpecLogTime(row && row.timestamp), 1055 }); }); 1056 _this.specLogRows(rows); 1057 if (scrollToBottom) { 1058 _this.scrollSpecLogsToBottom(); 1059 } 1060 } 1061 catch (e) { 1062 console.error('BayesBot logs parse failed:', e); 1063 } 1064 }); 1065 }; 1066 this.readLifetimeChartMinHeightPx = function () { 1067 var wrap = document.querySelector('.bayesBotLifetimeChartWrap'); 1068 if (wrap) { 1069 var minH = parseFloat(window.getComputedStyle(wrap).minHeight); 1070 if (Number.isFinite(minH) && minH > 0) { 1071 return minH; 1072 } 1073 } 1074 return BayesBot.LIFETIME_CHART_MIN_HEIGHT_PX; 1075 }; 1076 this.readInformationGainChromePx = function () { 1077 var row = document.querySelector('.bayesBotWorkbenchRow'); 1078 var infoPanel = null; 1079 if (row) { 1080 var panels = row.querySelectorAll('.bayesBotPanel'); 1081 for (var i = 0; i < panels.length; i++) { 1082 if (!panels[i].classList.contains('bayesBotProposePanel')) { 1083 infoPanel = panels[i]; 1084 break; 1085 } 1086 } 1087 } 1088 // Tab padding 12+10, ~16px line box, 1px tablist border; body pad 8+8; panel border 1+1. 1089 if (!infoPanel) { 1090 return 12 + 10 + 16 + 1 + 8 + 8 + 1 + 1; 1091 } 1092 var panelStyle = window.getComputedStyle(infoPanel); 1093 var borderY = (parseFloat(panelStyle.borderTopWidth) || 0) + 1094 (parseFloat(panelStyle.borderBottomWidth) || 0); 1095 var tabs = infoPanel.querySelector('.bayesBotProposeTabs'); 1096 var tabH = tabs ? tabs.getBoundingClientRect().height : 12 + 10 + 16 + 1; 1097 var body = infoPanel.querySelector('.bayesBotInformationGainBody'); 1098 var padY = 8 + 8; 1099 if (body) { 1100 var bodyStyle = window.getComputedStyle(body); 1101 padY = 1102 (parseFloat(bodyStyle.paddingTop) || 0) + 1103 (parseFloat(bodyStyle.paddingBottom) || 0); 1104 } 1105 return tabH + padY + borderY; 1106 }; 1107 this.measureMinWorkbenchHeightForInformationGain = function () { 1108 return Math.ceil(_this.readLifetimeChartMinHeightPx() + _this.readInformationGainChromePx()); 1109 }; 1110 this.scheduleBranchListWorkbenchHeight = function () { 1111 var self = _this; 1112 var attempts = 0; 1113 var tick = function () {
1114 if (self.proposePanelTab() !== 'branches') { 1115 return; 1116 } 1117 if (!self.branchRowsAreMeasurable() && attempts < 30) { 1118 attempts += 1; 1119 requestAnimationFrame(tick); 1120 return; 1121 } 1122 self.ensureBranchListWorkbenchHeight(); 1123 }; 1124 requestAnimationFrame(tick); 1125 }; 1126 this.branchRowsAreMeasurable = function () { 1127 var expected = _this.branchRows().length; 1128 if (expected <= 0) { 1129 return false; 1130 } 1131 var rows = document.querySelectorAll('.bayesBotBranchRow'); 1132 if (rows.length < Math.min(expected, 2)) { 1133 return false; 1134 } 1135 return rows[0].getBoundingClientRect().height > 0; 1136 }; 1137 this.ensureBranchListWorkbenchHeight = function () { 1138 if (_this.proposePanelTab() !== 'branches') { 1139 return; 1140 } 1141 var needed = _this.measureMinWorkbenchHeightForBranchList(); 1142 if (_this.workbenchHeightPx() < needed) { 1143 _this.workbenchHeightPx(_this.clampWorkbenchHeight(needed)); 1144 } 1145 }; 1146 this.measureMinWorkbenchHeightForBranchList = function () { 1147 var rows = document.querySelectorAll('.bayesBotBranchRow'); 1148 var visibleCount = Math.min(rows.length, 2); 1149 if (visibleCount < 1) { 1150 return _this.workbenchHeightPx(); 1151 } 1152 var rowBlock = 0; 1153 for (var i = 0; i < visibleCount; i++) { 1154 var rowHeight = rows[i].offsetHeight; 1155 if (!(rowHeight > 0)) { 1156 return _this.workbenchHeightPx(); 1157 } 1158 rowBlock += rowHeight; 1159 } 1160 var panel = document.querySelector('.bayesBotProposePanel'); 1161 var scroll = panel ? panel.querySelector('.bayesBotBranchScroll') : null; 1162 if (!panel || !scroll) { 1163 return rowBlock + BayesBot.BRANCH_ROW_HEIGHT_PX; 1164 } 1165 var chrome = Math.max(0, panel.offsetHeight - scroll.clientHeight); 1166 return Math.ceil(chrome + rowBlock); 1167 }; 1168 this.ensureCreateNetWorkbenchHeight = function () { 1169 _this.workbenchHeightPx(_this.clampWorkbenchHeight(_this.measureMinWorkbenchHeightForInformationGain())); 1170 }; 1171 this.agentExampleTypingDelay = function (ch) { 1172 if (ch === '.' || ch === '?' || ch === '!') { 1173 return 160 + Math.random() * 140; 1174 } 1175 if (ch === ',' || ch === ';') { 1176 return 80 + Math.random() * 70; 1177 } 1178 if (ch === '\n') { 1179 return 200 + Math.random() * 90; 1180 } 1181 if (ch === ' ') { 1182 return 36 + Math.random() * 40; 1183 } 1184 if (Math.random() < 0.05) { 1185 return 120 + Math.random() * 90; 1186 } 1187 return 20 + Math.random() * 32; 1188 }; 1189 this.isAgentTerminalNearBottom = function (el) { 1190 return el.scrollHeight - el.scrollTop - el.clientHeight <= 32; 1191 }; 1192 this.onAgentConnectTerminalScroll = function (_data, event) { 1193 var el = event && event.currentTarget; 1194 if (!el) { 1195 return true; 1196 } 1197 _this.agentTerminalStickToBottom = _this.isAgentTerminalNearBottom(el); 1198 return true; 1199 }; 1200 this.scrollAgentExampleTerminal = function () { 1201 if (!_this.agentTerminalStickToBottom) { 1202 return; 1203 } 1204 var el = document.querySelector('.bayesBotAgentConnectTerminal'); 1205 if (!el) { 1206 return; 1207 } 1208 requestAnimationFrame(function () { 1209 if (!_this.agentTerminalStickToBottom) { 1210 return; 1211 } 1212 el.scrollTop = el.scrollHeight; 1213 }); 1214 }; 1215 this.stopAgentExampleRotation = function () { 1216 _this.agentExampleToken += 1; 1217 if (_this.agentExampleTimer) { 1218 clearTimeout(_this.agentExampleTimer); 1219 _this.agentExampleTimer = null; 1220 } 1221 _this.agentExampleAnimating(false); 1222 _this.displayedAgentExampleText(''); 1223 }; 1224 this.startAgentExampleRotation = function () { 1225 var token = ++_this.agentExampleToken; 1226 if (_this.agentExampleTimer) { 1227 clearTimeout(_this.agentExampleTimer); 1228 _this.agentExampleTimer = null; 1229 } 1230 _this.displayedAgentExampleText(''); 1231 _this.agentExampleAnimating(true); 1232 var typeExample = function () { 1233 if (token !== _this.agentExampleToken) { 1234 return; 1235 } 1236 var prompts = _this.isCreateMode() 1237 ? BAYES_BOT_CREATE_AGENT_EXAMPLE_PROMPTS 1238 : BAYES_BOT_AGENT_EXAMPLE_PROMPTS; 1239 var target = prompts[_this.agentExampleIndex % prompts.length]; 1240 var i = 0; 1241 _this.displayedAgentExampleText(''); 1242 _this.agentExampleAnimating(true); 1243 _this.scrollAgentExampleTerminal(); 1244 var typeNext = function () { 1245 if (token !== _this.agentExampleToken) { 1246 return; 1247 } 1248 if (i >= target.length) { 1249 _this.agentExampleAnimating(true); 1250 _this.scrollAgentExampleTerminal(); 1251 _this.agentExampleTimer = setTimeout(function () { 1252 if (token !== _this.agentExampleToken) { 1253 return; 1254 } 1255 _this.agentExampleIndex = (_this.agentExampleIndex + 1) % prompts.length; 1256 typeExample(); 1257 }, 3400); 1258 return; 1259 } 1260 i += 1; 1261 _this.displayedAgentExampleText(target.slice(0, i)
1261); 1262 _this.scrollAgentExampleTerminal(); 1263 _this.agentExampleTimer = setTimeout(typeNext, _this.agentExampleTypingDelay(target.charAt(i - 1))); 1264 }; 1265 typeNext(); 1266 }; 1267 typeExample(); 1268 }; 1269 this.startAgentActivitySpinner = function () { 1270 _this.agentActivitySpinning(true); 1271 _this.ensureAgentSpinnerRunning(); 1272 }; 1273 this.ensureAgentSpinnerRunning = function () { 1274 if (_this.agentActivitySpinnerTimer) { 1275 return; 1276 } 1277 _this.agentActivitySpinnerTick = 0; 1278 _this.tickAgentSpinner(); 1279 _this.agentActivitySpinnerTimer = setInterval(function () { 1280 _this.agentActivitySpinnerTick += 1; 1281 _this.tickAgentSpinner(); 1282 }, 140); 1283 }; 1284 this.tickAgentSpinner = function () { 1285 var frames = BayesBot.AGENT_ACTIVITY_SPINNER_FRAMES; 1286 var tick = _this.agentActivitySpinnerTick; 1287 _this.agentActivitySpinnerFrame(frames[tick % frames.length]); 1288 var n = BayesBot.BRAILLE_CELL_COUNT; 1289 var last = n - 1; 1290 var period = last * 2; 1291 var t = period === 0 ? 0 : tick % period; 1292 var pos = t <= last ? t : period - t; 1293 var cells = []; 1294 for (var i = 0; i < n; i++) { 1295 cells.push(i === pos); 1296 } 1297 _this.agentConnectBrailleCells(cells); 1298 }; 1299 this.stopAgentActivitySpinner = function () { 1300 _this.agentActivitySpinning(false); 1301 if (_this.agentIsConnected()) { 1302 _this.ensureAgentSpinnerRunning(); 1303 return; 1304 } 1305 if (_this.agentActivitySpinnerTimer) { 1306 clearInterval(_this.agentActivitySpinnerTimer); 1307 _this.agentActivitySpinnerTimer = null; 1308 } 1309 }; 1310 this.markAgentConnected = function () { 1311 if (!_this.agentIsConnected()) { 1312 _this.agentIsConnected(true); 1313 } 1314 _this.ensureAgentSpinnerRunning(); 1315 }; 1316 this.showAgentActivityTerminal = function () { 1317 _this.stopAgentExampleRotation(); 1318 _this.proposePanelTab('connect'); 1319 if (!_this.agentActivityLive()) { 1320 _this.agentTerminalStickToBottom = true; 1321 } 1322 _this.agentActivityLive(true); 1323 _this.scrollAgentExampleTerminal(); 1324 }; 1325 this.appendAgentActivityLine = function (text) { 1326 var next = String(text || '').trim(); 1327 if (!next) { 1328 return; 1329 } 1330 _this.showAgentActivityTerminal(); 1331 _this.stopAgentActivitySpinner(); 1332 var current = String(_this.agentActivityLatestText() || '').trim(); 1333 if (current) { 1334 _this.agentActivityLines.push(current); 1335 } 1336 _this.agentActivityLatestText(next); 1337 _this.scrollAgentExampleTerminal(); 1338 }; 1339 this.resetCanvasObservationsToDefault = function () { 1340 var net = _this.authorBayesNet; 1341 if (net && typeof net.clearAllObservations === 'function') { 1342 net.clearAllObservations(); 1343 } 1344 }; 1345 this.selectCanvasNodeFromActivity = function (data) { 1346 var net = _this.authorBayesNet; 1347 if (!net || !data) { 1348 return; 1349 } 1350 var liveId = _this.resolveCanvasNodeId(data.nodeId, data.nodeTitle); 1351 if (!liveId) { 1352 return; 1353 } 1354 if (typeof net.setPathFocusNodeId === 'function') { 1355 net.setPathFocusNodeId(liveId); 1356 } 1357 if (typeof net.selectNodeById === 'function') { 1358 net.selectNodeById(liveId); 1359 } 1360 }; 1361 this.applyAgentObservationFromActivity = function (data) { 1362 var net = _this.authorBayesNet; 1363 if (!net || !data) { 1364 return; 1365 } 1366 if (data.clearAll) { 1367 if (typeof net.clearAllObservations === 'function') { 1368 net.clearAllObservations(); 1369 } 1370 return; 1371 } 1372 var liveId = _this.resolveCanvasNodeId(data.nodeId, data.nodeTitle); 1373 if (!liveId) { 1374 return; 1375 } 1376 if (data.answerId != null && typeof net.applyObservation === 'function') { 1377 net.applyObservation(liveId, data.answerId); 1378 return; 1379 } 1380 if (typeof net.clearObservation === 'function') { 1381 net.clearObservation(liveId); 1382 } 1383 }; 1384 this.applyAgentForecastFromActivity = function (data) { 1385 if (!data) { 1386 return; 1387 } 1388 var forecastType = String(data.forecastType || ''); 1389 if (forecastType === 'conditional' || (Array.isArray(data.rows) && data.rows.length)) { 1390 _this.applyBayesBotGraphEvent({ 1391 type: 'conditional', 1392 nodeId: data.nodeId, 1393 rows: data.rows || [], 1394 }); 1395 return; 1396 } 1397 if (forecastType === 'prior' || (Array.isArray(data.values) && data.values.length)) { 1398 _this.applyBayesBotGraphEvent({ 1399 type: 'prior', 1400 nodeId: data.nodeId, 1401 values: data.values || [], 1402 }); 1403 } 1404 }; 1405 this.applyAgentGraphMutationFromActivity = function (data) { 1406 if (!data) { 1407 return; 1408 } 1409 var mutationType = String(data.mutationType || ''); 1410 if (mutationType === 'nodeCreated') { 1411 _this.applyBayesBotGraphEvent({ 1412 type: 'node', 1413 node: data.node, 1414 parentNodeId: data.parentNodeId, 1415 }); 1416 _this.selectCanvasNodeFromActivity(data); 1417 return; 1418 } 1419 if (mutationType === 'nodeDeleted' || (data.nodeId != null && !data.parentNodeId && !data.childNodeId)) { 1420 _this.applyBayesBotGraphEvent({ 1421 type: 'nodeDeleted', 1422 nodeId: data.nodeId, 1423 }); 1424 return; 1425 } 1426 if (mutationType === 'connectionRemoved') { 1427 _this.applyBayesBotGraphEvent({ 1428 type: 'connectionRemoved', 1429 parentNodeId: data.parentNodeId, 1430 childNodeId: data.childNodeId, 1431 }); 1432 return; 1433 } 1434 if (mutationType === 'connection') { 1435 _this.applyBayesBotGraphEvent({ 1436 type: 'connection', 1437 parentNodeId: data.parentNodeId, 1438 childNodeId: data.childNodeId, 1439 }); 1440 } 1441 }; 1442 this.adoptAgentJobFromActivity = function (data) { 1443 if (data && data.jobId) { 1444 var incoming = String(data.jobId); 1445 var current = _this.lastBayesBotJobId(); 1446 if (incoming !== String(current || '')) { 1447 _this.proposalJobSettled = false;
1448 } 1449 _this.lastBayesBotJobId(incoming); 1450 } 1451 if (_this.isCreateMode()) { 1452 _this.liveTemplateBuild = true; 1453 _this.ensureCreateCanvasMounted(data); 1454 _this.ensureCreateNetWorkbenchHeight(); 1455 } 1456 }; 1457 this.onBayesBotAgentActivityEvent = function (event) { 1458 var data = _this.parseBayesBotSseData(event); 1459 if (!data || !data.kind) { 1460 return; 1461 } 1462 _this.markAgentConnected(); 1463 _this.adoptAgentJobFromActivity(data); 1464 var kind = String(data.kind); 1465 if (kind === 'connecting') { 1466 _this.showAgentActivityTerminal(); 1467 _this.agentActivityLines([]); 1468 _this.agentActivityLatestText(''); 1469 _this.startAgentActivitySpinner(); 1470 _this.resetCanvasObservationsToDefault(); 1471 return; 1472 } 1473 if (kind === 'connected') { 1474 _this.resetCanvasObservationsToDefault(); 1475 _this.appendAgentActivityLine(data.message || 'agent is connected.'); 1476 return; 1477 } 1478 if (kind === 'proposal_status') { 1479 _this.appendAgentActivityLine(data.message || 'processing proposal...'); 1480 return; 1481 } 1482 if (kind === 'proposal_complete') { 1483 _this.appendAgentActivityLine(data.message || 'proposal finished.'); 1484 var lines = Array.isArray(data.lines) ? data.lines : []; 1485 for (var i = 0; i < lines.length; i++) { 1486 _this.appendAgentActivityLine(String(lines[i])); 1487 } 1488 return; 1489 } 1490 if (kind === 'simulate') { 1491 _this.applyAgentObservationFromActivity(data); 1492 } 1493 if (kind === 'forecast') { 1494 _this.applyAgentForecastFromActivity(data); 1495 _this.selectCanvasNodeFromActivity(data); 1496 } 1497 if (kind === 'graph') { 1498 _this.applyAgentGraphMutationFromActivity(data); 1499 } 1500 if (kind === 'select') { 1501 _this.selectCanvasNodeFromActivity(data); 1502 } 1503 _this.appendAgentActivityLine(data.message || kind); 1504 }; 1505 this.rewriteUrlToCurrentOrigin = function (raw) { 1506 var trimmed = String(raw || '').trim(); 1507 if (!trimmed || typeof window === 'undefined' || !window.location) { 1508 return trimmed; 1509 } 1510 var origin = bayesBotAgentConnectOrigin(window.location.hostname, window.location.port); 1511 try { 1512 var parsed = new URL(trimmed, origin); 1513 return origin + parsed.pathname + parsed.search + parsed.hash; 1514 } 1515 catch (e) { 1516 return trimmed; 1517 } 1518 }; 1519 this.resolvePublicStudyUrl = function () { 1520 var fromStudy = Distiller.studyInView && Distiller.studyInView(); 1521 var studyLink = fromStudy && fromStudy.publicLink && fromStudy.publicLink(); 1522 var studyUrl = studyLink && studyLink.url && studyLink.url(); 1523 if (studyUrl) { 1524 return _this.rewriteUrlToCurrentOrigin(studyUrl); 1525 } 1526 var fromCommunity = Distiller.currentCommunity && Distiller.currentCommunity(); 1527 var communityLink = fromCommunity && fromCommunity.publicLink && fromCommunity.publicLink(); 1528 var communityUrl = communityLink && communityLink.url && communityLink.url(); 1529 if (communityUrl) { 1530 return _this.rewriteUrlToCurrentOrigin(communityUrl); 1531 } 1532 if (_this.agentStudyBaseUrl()) { 1533 return _this.rewriteUrlToCurrentOrigin(_this.agentStudyBaseUrl()); 1534 } 1535 try { 1536 var loc = new URL(window.location.href); 1537 var study = loc.searchParams.get('study'); 1538 var sid = loc.searchParams.get('sid'); 1539 if (study && sid) { 1540 return (bayesBotAgentConnectOrigin(loc.hostname, loc.port) + 1541 '/?&study=' + 1542 encodeURIComponent(study) + 1543 '&sid=' + 1544 encodeURIComponent(sid) + 1545 '&'); 1546 } 1547 } 1548 catch (e) { 1549 // fall through 1550 } 1551 return ''; 1552 }; 1553 this.agentConnectUrl = ko.pureComputed(function () {
1554 var key = _this.agentKey(); 1555 var base = _this.resolvePublicStudyUrl(); 1556 if (!key || !base) { 1557 return ''; 1558 } 1559 var trimmed = String(base); 1560 var joiner = /[?&]$/.test(trimmed) ? '' : (trimmed.indexOf('?') >= 0 ? '&' : '?'); 1561 return trimmed + joiner + 'agent=' + encodeURIComponent(key); 1562 }); 1563 this.copyAgentConnectUrl = function () { 1564 var url = _this.agentConnectUrl(); 1565 if (!url || !Distiller.copyToClipboard) { 1566 return; 1567 } 1568 Distiller.copyToClipboard(url, true); 1569 _this.agentConnectCopied(true); 1570 if (_this.agentConnectCopiedTimer) { 1571 clearTimeout(_this.agentConnectCopiedTimer); 1572 } 1573 _this.agentConnectCopiedTimer = setTimeout(function () { 1574 _this.agentConnectCopied(false); 1575 _this.agentConnectCopiedTimer = null; 1576 }, 400); 1577 }; 1578 this.ensureAgentKey = function () { 1579 if (_this.agentKeyReady) { 1580 return _this.agentKeyReady; 1581 } 1582 var currentUser = Distiller.currentUser && Distiller.currentUser(); 1583 var userId = currentUser && currentUser.userId; 1584 if (!userId) { 1585 return Promise.resolve(); 1586 } 1587 _this.agentKeyLoading(true); 1588 var endpoint = Distiller.apiEndpoint + '/api/getOrCreateAgentKey/' + userId; 1589 _this.agentKeyReady = fetch(endpoint, { credentials: 'same-origin' }) 1590 .then(function (res) { return res.json(); }) 1591 .then(function (response) { 1592 if (response && response.ok && response.key) { 1593 _this.agentKey(response.key); 1594 if (response.studyUrl) { 1595 _this.agentStudyBaseUrl(response.studyUrl); 1596 } 1597 } 1598 else { 1599 console.error('BayesBot ensureAgentKey: unexpected response', response); 1600 } 1601 }) 1602 .catch(function (e) { 1603 console.error('BayesBot ensureAgentKey failed:', e); 1604 }) 1605 .then(function () { 1606 _this.agentKeyLoading(false); 1607 }); 1608 return _this.agentKeyReady; 1609 }; 1610 this.proposePlaceholder = ko.pureComputed(function () { 1611 return _this.isCreateMode() 1612 ? 'Paste a description of the futureâ¦' 1613 : 'Describe an early update signalâ¦'; 1614 }); 1615 this.headerParts = ko.pureComputed(function () { 1616 return parseBayesBotHeaderMarkup(_this.headerMarkup()); 1617 }); 1618 this.resolveBoundCommunityId = function () { 1619 var bound = _this.boundCommunityId(); 1620 if (bound) { 1621 return bound; 1622 } 1623 var community = Distiller.currentCommunity && Distiller.currentCommunity(); 1624 if (community && typeof community.communityId === 'function' && community.communityId()) { 1625 return community.communityId(); 1626 } 1627 var user = Distiller.currentUser && Distiller.currentUser(); 1628 if (user && user.communityId != null) { 1629 var raw = typeof user.communityId === 'function' 1630 ? user.communityId() 1631 : user.communityId; 1632 var parsed = parseInt(String(raw), 10); 1633 if (Number.isFinite(parsed) && parsed > 0) { 1634 return parsed; 1635 } 1636 } 1637 return 661; 1638 }; 1639 this.showHeaderInfo = function (_part, event) { 1640 Distiller.showInfo(_this.headerInfoHtml(), event); 1641 }; 1642 this.presentCreateHeader = function () { 1643 _this.isCreateMode(true); 1644 _this.ensureCreateNetWorkbenchHeight(); 1645 _this.applyHeaderMarkupImmediate(BAYES_BOT_CREATE_HEADER_MARKUP, BAYES_BOT_BAYES_NET_INFO); 1646 }; 1647 this.headerForDisplay = function (markup, infoHtml) { 1648 if (!isLegacyHormuzPlaceholder(markup)) { 1649 return { markup: markup, infoHtml: infoHtml }; 1650 } 1651 _this.isCreateMode(true); 1652 return { markup: BAYES_BOT_CREATE_HEADER_MARKUP, infoHtml: BAYES_BOT_BAYES_NET_INFO }; 1653 }; 1654 this.applyHeaderMarkupImmediate = function (markup, infoHtml) { 1655 var shown = _this.headerForDisplay(markup, infoHtml); 1656 markup = shown.markup; 1657 infoHtml = shown.infoHtml; 1658 _this.headerTypewriterToken += 1; 1659 if (_this.headerTypewriterTimer) { 1660 clearTimeout(_this.headerTypewriterTimer); 1661 _this.headerTypewriterTimer = null; 1662 } 1663 _this.headerMarkup(markup); 1664 _this.displayedHeaderText(stripBayesBotHeaderMarkup(markup)); 1665 _this.headerInfoHtml(infoHtml); 1666 _this.headerAnimating(false); 1667 _this.headerAnimationComplete(true); 1668 }; 1669 this.animateHeaderMarkup = function (markup, infoHtml) { 1670 var shown = _this.headerForDisplay(markup, infoHtml); 1671 markup = shown.markup; 1672 infoHtml = shown.infoHtml; 1673 var token = ++_this.headerTypewriterToken; 1674 if (_this.headerTypewriterTimer) { 1675 clearTimeout(_this.headerTypewriterTimer); 1676 _this.headerTypewriterTimer = null; 1677 }
1678 var targetPlain = stripBayesBotHeaderMarkup(markup); 1679 _this.headerAnimationComplete(false); 1680 _this.headerAnimating(true); 1681 _this.headerInfoHtml(infoHtml); 1682 var reveal = function () { 1683 if (token !== _this.headerTypewriterToken) { 1684 return; 1685 } 1686 _this.displayedHeaderText(targetPlain); 1687 _this.headerMarkup(markup); 1688 _this.headerAnimating(false); 1689 _this.headerAnimationComplete(true); 1690 _this.headerTypewriterTimer = null; 1691 }; 1692 var typeForward = function () { 1693 if (token !== _this.headerTypewriterToken) { 1694 return; 1695 } 1696 var shown = _this.displayedHeaderText(); 1697 if (shown.length >= targetPlain.length) { 1698 reveal(); 1699 return; 1700 } 1701 _this.displayedHeaderText(targetPlain.slice(0, shown.length + 1)); 1702 _this.headerTypewriterTimer = setTimeout(typeForward, 18); 1703 }; 1704 var backspace = function () { 1705 if (token !== _this.headerTypewriterToken) { 1706 return; 1707 } 1708 var shown = _this.displayedHeaderText(); 1709 if (shown.length > 0) { 1710 _this.displayedHeaderText(shown.slice(0, -1)); 1711 _this.headerTypewriterTimer = setTimeout(backspace, 16); 1712 return; 1713 } 1714 _this.headerTypewriterTimer = setTimeout(typeForward, 80); 1715 }; 1716 if (!_this.displayedHeaderText()) { 1717 typeForward(); 1718 return; 1719 } 1720 backspace(); 1721 }; 1722 this.unwrapBayesBotValue = function (value) { 1723 return typeof value === 'function' ? value() : value; 1724 }; 1725 this.makeEmptyAuthorSet = function (setId, setName, type) { 1726 return { 1727 setId: ko.observable(setId), 1728 setName: ko.observable(setName || 'Bayes set'), 1729 setDescription: ko.observable(null), 1730 quillDelta: ko.observable(null), 1731 questions: ko.observableArray([]), 1732 isSelected: ko.observable(false), 1733 images: ko.observableArray([]), 1734 discussionQuestions: ko.observableArray([]), 1735 surveyQuestions: ko.observableArray([]), 1736 hiddenQuestions: ko.observableArray([]), 1737 type: ko.observable(type != null ? type : 16), 1738 parentId: ko.observable(null), 1739 priority: ko.observable(null), 1740 setTags: ko.observableArray([]), 1741 userStage: ko.observable(null), 1742 pages: ko.observableArray([]), 1743 subsets: ko.observableArray([]), 1744 isLive: ko.observable(1), 1745 }; 1746 }; 1747 this.resolveBayesSetIdFromPage = function () { 1748 var pageSet = _this.questionSet(); 1749 if (!pageSet) { 1750 return null; 1751 } 1752 var pageType = _this.unwrapBayesBotValue(pageSet.type); 1753 var pageSetId = _this.unwrapBayesBotValue(pageSet.setId); 1754 if (pageType === 16 && pageSetId) { 1755 return pageSetId; 1756 } 1757 var pages = pageSet.pages && typeof pageSet.pages === 'function' ? pageSet.pages() : []; 1758 for (var p = 0; p < (pages || []).length; p++) { 1759 var workflows = pages[p] && pages[p].stageWorkflows && typeof pages[p].stageWorkflows === 'function' 1760 ? pages[p].stageWorkflows() 1761 : []; 1762 for (var w = 0; w < (workflows || []).length; w++) { 1763 var elements = workflows[w] && workflows[w].elements && typeof workflows[w].elements === 'function' 1764 ? workflows[w].elements() 1765 : []; 1766 for (var i = 0; i < (elements || []).length; i++) { 1767 var el = elements[i]; 1768 if (!_this.isBayesNetElement(el)) { 1769 continue; 1770 } 1771 var fromFlag = _this.unwrapBayesBotValue(el.bayesNetSetId); 1772 if (fromFlag) { 1773 return fromFlag; 1774 } 1775 var nestedSet = _this.unwrapBayesBotValue(el.set); 1776 if (nestedSet && typeof nestedSet === 'object') { 1777 var nestedId = _this.unwrapBayesBotValue(nestedSet.setId); 1778 if (nestedId) { 1779 return nestedId; 1780 } 1781 } 1782 else if (nestedSet) { 1783 return nestedSet; 1784 } 1785 } 1786 } 1787 } 1788 return null; 1789 }; 1790 this.mountCanvasImmediately = function () { 1791 var templateNetId = parseInt(String(_this.sharedTemplateNetId()), 10); 1792 if (!Number.isFinite(templateNetId) || templateNetId <= 0) { 1793 return; 1794 } 1795 var setId = _this.resolveBayesSetIdFromPage() || 'bayes-bot-canvas'; 1796 var existing = _this.authorBayesNetSet(); 1797 if (existing && 1798 existing.setId && 1799 String(existing.setId()) === String(setId) && 1800 _this.canvasMountedForTemplateNetId === templateNetId) { 1801 return; 1802 } 1803 _this.publishAuthorBayesNetSet(setId, 'Bayes set', 16); 1804 }; 1805 this.publishAuthorBayesNetSet = function (setId, setName, type) { 1806 var templateNetId = parseInt(String(_this.sharedTemplateNetId()), 10); 1807 _this.canvasMountedForTemplateNetId = 1808 Number.isFinite(templateNetId) && templateNetId > 0 ? templateNetId : null; 1809 _this.authorBayesNet = null; 1810 // Drop the previous component so Knockout reads templateNetId on a new mount. 1811 _this.authorBayesNetSet(null); 1812 _this.authorBayesNetSet(_this.makeEmptyAuthorSet(setId, setName, type)); 1813 }; 1814 this.mountAuthorBayesNetFromModel = function (data) { 1815 if (!data || !data.setId) { 1816 return; 1817 } 1818 if (data.communityId != null) { 1819 _this.boundCommunityId(parseInt(String(data.communityId), 10)); 1820 } 1821 if (data.questionText && !isLegacyHormuzPlaceholder(data.questionText)) { 1822 _this.boundQuestionText(String(data.questionText)); 1823 } 1824 if (data.resolutionCriteria && !isLegacyHormuzPlaceholder(data.resolutionCriteria)) { 1825 _this.boundResolutionCriteria(String(data.resolutionCriteria)); 1826 } 1827 if (data.resolutionDate) { 1828 _this.boundResolutionDate(bayesBotIsoDate(data.resolutionDate) || _this.boundResolutionDate()); 1829 } 1830 var headerSource = data.headerMarkup || data.questionText; 1831 if (headerSource && !_this.isCreateMode()) { 1832 var infoHtml = data.resolutionCriteria 1833 ? bayesBotHeaderInfoHtml('Resolves Yes', String(data.resolutionCriteria)) 1834 : _this.headerInfoHtml(); 1835 _this.applyHeaderMarkupImmediate(String(headerSource), infoHtml); 1836 } 1837 _this.sharedTemplateNetId(data.templateNetId != null ? parseInt(String(data.templateNetId), 10) : null); 1838 if (data.ownsCanonicalTemplate) { 1839 _this.ownsCanonicalTemplate = true; 1840 _this.authorOwnsTemplate(true); 1841 } 1842 if (data.copyNetId != null && !_this.ownsCanonicalTemplate) { 1843 var existingCopy = parseInt(String(data.copyNetId), 10); 1844 if (Number.isFinite(existingCopy) && existingCopy > 0) { 1845 _this.personalCopyNetId = existingCopy; 1846 } 1847 } 1848 if (data.primaryNodeId || data.endStateNodeId) { 1849 var primaryId = parseInt(String(data.primaryNodeId || data.endStateNodeId), 10); 1850 if (Number.isFinite(primaryId) && primaryId > 0) { 1851 _this.leaderboardPrimaryNodeId(primaryId); 1852 } 1853 } 1854 var templateNetId = _this.sharedTemplateNetId(); 1855 var existing = _this.authorBayesNetSet(); 1856 if (existing && 1857 existing.setId && 1858 String(existing.setId()) === String(data.setId) && 1859 _this.canvasMountedForTemplateNetId === templateNetId) { 1860 return; 1861 } 1862 _this.publishAuthorBayesNetSet(data.setId, data.setName, data.type != null ? data.type : 16); 1863 }; 1864 this.ensureCreateCanvasMounted = function (data) { 1865 _this.liveTemplateBuild = true; 1866 _this.ownsCanonicalTemplate = true; 1867 _this.authorOwnsTemplate(true); 1868 var currentUser = Distiller.currentUser && Distiller.currentUser(); 1869 if (currentUser && currentUser.userId) { 1870 _this.viewerUserId = currentUser.userId; 1871 } 1872 if (data && (data.templateNetId || data.netId)) { 1873 var netId = parseInt(String(data.templateNetId || data.netId), 10); 1874 if (Number.isFinite(netId) && netId > 0) { 1875 _this.sharedTemplateNetId(netId); 1876 } 1877 } 1878 if (data && (data.setId || data.bayesSetId)) { 1879 _this.mountAuthorBayesNetFromModel(__assign(__assign({}, data), { setId: data.setId || data.bayesSetId, setName: data.setName || 'Bayes set', type: data.type != null ? data.type : 16 })); 1880 return; 1881 } 1882 if (_this.authorBayesNetSet()) { 1883 return; 1884 } 1885 void _this.loadAuthorBayesNet(); 1886 }; 1887 this.parseSidFromUrl = function () { 1888 try { 1889 var raw = new URLSearchParams(window.location.search).get('sid'); 1890 var parsed = parseInt(String(raw), 10); 1891 if (Number.isFinite(parsed) && parsed > 0) { 1892 return parsed; 1893 } 1894 } 1895 catch (e) { 1896 /* ignore */ 1897 } 1898 return null; 1899 }; 1900 this.isDraftCreateUrl = function () { 1901 try { 1902 return new URLSearchParams(window.location.search).get('bayesBotDraft')
1902=== '1'; 1903 } 1904 catch (e) { 1905 return false; 1906 } 1907 }; 1908 this.provisionDraftStudy = function () { return __awaiter(_this, void 0, void 0, function () { 1909 var navigating, e_1; 1910 return __generator(this, function (_a) { 1911 switch (_a.label) { 1912 case 0: 1913 this.ensureCreateNetWorkbenchHeight(); 1914 this.draftProvisioning(true); 1915 this.draftProvisionError(''); 1916 this.draftNeedsReplacement(false); 1917 navigating = false; 1918 _a.label = 1; 1919 case 1: 1920 _a.trys.push([1, 3, 4, 5]); 1921 return [4 /*yield*/, Distiller.provisionFreshBayesBotLanding({ forceNew: true })]; 1922 case 2: 1923 _a.sent(); 1924 navigating = true; 1925 return [3 /*break*/, 5]; 1926 case 3: 1927 e_1 = _a.sent(); 1928 console.error('BayesBot provision draft failed:', e_1); 1929 this.draftProvisionError(e_1 && e_1.message 1930 ? String(e_1.message) 1931 : 'Could not create the BayesBot study.'); 1932 return [3 /*break*/, 5]; 1933 case 4: 1934 if (!navigating) { 1935 this.draftProvisioning(false); 1936 if (Distiller.endBayesBotBoot) { 1937 Distiller.endBayesBotBoot(); 1938 } 1939 } 1940 return [7 /*endfinally*/]; 1941 case 5: return [2 /*return*/]; 1942 } 1943 }); 1944 }); }; 1945 this.initializeDraftStudy = function () { return __awaiter(_this, void 0, void 0, function () { 1946 var currentUser, userId, communityId, agentKeyPromise, response, data, isMissingDraft, activeJob, e_2; 1947 return __generator(this, function (_a) { 1948 switch (_a.label) { 1949 case 0: 1950 currentUser = Distiller.currentUser && Distiller.currentUser(); 1951 userId = currentUser && currentUser.userId; 1952 communityId = this.resolveBoundCommunityId(); 1953 if (!userId || !communityId) { 1954 this.draftProvisionError('The BayesBot study identity is incomplete.'); 1955 if (Distiller.isBayesBotUrl && Distiller.isBayesBotUrl()) { 1956 this.presentCreateHeader(); 1957 } 1958 if (Distiller.endBayesBotBoot) { 1959 Distiller.endBayesBotBoot(); 1960 } 1961 return [2 /*return*/]; 1962 } 1963 if (Distiller.beginBayesBotBoot) { 1964 Distiller.beginBayesBotBoot(); 1965 } 1966 this.draftProvisioning(true); 1967 this.draftProvisionError(''); 1968 this.draftNeedsReplacement(false); 1969 agentKeyPromise = this.ensureAgentKey(); 1970 _a.label = 1; 1971 case 1: 1972 _a.trys.push([1, 9, 10, 11]); 1973 return [4 /*yield*/, fetch(Distiller.apiEndpoint + 1974 '/api/bayesBotDraftState/' + 1975 userId + 1976 '/' + 1977 communityId, { credentials: 'same-origin' })]; 1978 case 2: 1979 response = _a.sent(); 1980 return [4 /*yield*/, response.json()]; 1981 case 3: 1982 data = _a.sent(); 1983 isMissingDraft = (data && data.ok === true && data.found === false) || 1984 (response.status === 400 && data && data.error === 'Bayes Bot draft not found'); 1985 if (!isMissingDraft) return [3 /*break*/, 5]; 1986 this.isCreateMode(false); 1987 this.clearDraftCreateUrl(); 1988 return [4 /*yield*/, this.loadAuthorBayesNet()]; 1989 case 4: 1990 _a.sent(); 1991 this.loadLeaderboard(); 1992 if (!stripBayesBotHeaderMarkup(this.headerMarkup() || '').trim()) { 1993 this.presentCreateHeader(); 1994 } 1995 return [2 /*return*/]; 1996 case 5: 1997 if (!response.ok || !data || data.ok === false) { 1998 throw new Error((data && data.error) || 'draft state unavailable'); 1999 }
2000 if (data.agentKey) { 2001 this.agentKey(String(data.agentKey)); 2002 } 2003 if (data.studyUrl) { 2004 this.agentStudyBaseUrl(String(data.studyUrl)); 2005 } 2006 if (!(data.status === 'complete')) return [3 /*break*/, 7]; 2007 this.isCreateMode(false); 2008 this.ownsCanonicalTemplate = true; 2009 this.authorOwnsTemplate(true); 2010 this.clearDraftCreateUrl(); 2011 return [4 /*yield*/, this.loadAuthorBayesNet()]; 2012 case 6: 2013 _a.sent(); 2014 this.loadLeaderboard(); 2015 this.presentPersistedLifetimeInformation(data.lifetimeInformation || this.lifetimeInformationFromJob(data.activeJob)); 2016 return [3 /*break*/, 8]; 2017 case 7: 2018 if (data.status === 'building') { 2019 this.isCreateMode(true); 2020 this.ensureCreateNetWorkbenchHeight(); 2021 activeJob = data.activeJob || null; 2022 this.applyPersistedBuildStatus(__assign(__assign({}, (data.buildStatus || {})), (activeJob 2023 ? { 2024 jobId: activeJob.jobId, 2025 status: activeJob.status, 2026 progress: activeJob.progress, 2027 } 2028 : {}))); 2029 if (!stripBayesBotHeaderMarkup(this.headerMarkup() || '').trim() || isLegacyHormuzPlaceholder(this.headerMarkup())) { 2030 this.presentCreateHeader(); 2031 } 2032 this.ensureCreateCanvasMounted(data); 2033 } 2034 else if (data.status === 'failed') { 2035 this.presentCreateHeader(); 2036 this.draftNeedsReplacement(true); 2037 this.draftProvisionError((data.buildStatus && data.buildStatus.error) || 2038 'This draft could not be completed. Start a new Bayes Bot study to try again.'); 2039 } 2040 else if (data.status === 'draft' || data.createMode) { 2041 this.presentCreateHeader(); 2042 this.ensureCreateCanvasMounted(data); 2043 } 2044 _a.label = 8; 2045 case 8: return [3 /*break*/, 11]; 2046 case 9: 2047 e_2 = _a.sent(); 2048 console.error('BayesBot initialize draft failed:', e_2); 2049 this.draftProvisionError(e_2 && e_2.message 2050 ? String(e_2.message) 2051 : 'Could not load the BayesBot draft.'); 2052 if ((Distiller.isBayesBotUrl && Distiller.isBayesBotUrl()) || 2053 this.isDraftCreateUrl()) { 2054 this.presentCreateHeader(); 2055 } 2056 return [3 /*break*/, 11]; 2057 case 10: 2058 this.draftProvisioning(false); 2059 this.connectBayesBotSse(); 2060 void agentKeyPromise; 2061 if (Distiller.endBayesBotBoot) { 2062 Distiller.endBayesBotBoot(); 2063 } 2064 return [7 /*endfinally*/]; 2065 case 11: return [2 /*return*/]; 2066 } 2067 }); 2068 }); }; 2069 this.retryDraftInitialization = function () { 2070 if (_this.draftNeedsReplacement()) { 2071 void _this.provisionReplacementDraft(); 2072 return; 2073 } 2074 if (_this.parseSidFromUrl()) { 2075 void _this.initializeDraftStudy(); 2076 } 2077 else { 2078 void _this.provisionDraftStudy(); 2079 } 2080 }; 2081 this.provisionReplacementDraft = function () { return __awaiter(_this, void 0, void 0, function () { 2082 var currentUser, userId, communityId, handingOff, responseText, data, e_3; 2083 return __generator(this, function (_a) { 2084 switch (_a.label) { 2085 case 0: 2086 currentUser = Distiller.currentUser && Distiller.currentUser(); 2087 userId = currentUser && currentUser.userId; 2088 communityId = this.resolveBoundCommunityId(); 2089 if (!userId || !communityId) { 2090 this.draftProvisionError('The BayesBot study identity is incomplete.'); 2091 if (Distiller.endBayesBotBoot) { 2092 Distiller.endBayesBotBoot(); 2093 } 2094 return [2 /*return*/]; 2095 } 2096 if (Distiller.beginBayesBotBoot) { 2097 Distiller.beginBayesBotBoot(); 2098 } 2099 this.draftProvisioning(true); 2100 handingOff = false;
2101 _a.label = 1; 2102 case 1: 2103 _a.trys.push([1, 3, 4, 5]); 2104 return [4 /*yield*/, Distiller.httpPostJsonAsync(Distiller.apiEndpoint + 2105 '/api/bayesBotNewDraft/' + 2106 userId + 2107 '/' + 2108 communityId, {})]; 2109 case 2: 2110 responseText = _a.sent(); 2111 data = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 2112 if (!data || data.ok === false || !data.studyUrl) { 2113 throw new Error((data && data.error) || 'new draft unavailable'); 2114 } 2115 this.rememberCreatedStudyMembership(data); 2116 this.applyCreatedStudyToUrl(data); 2117 Distiller.enterProvisionedBayesBotStudy(data); 2118 handingOff = true; 2119 return [3 /*break*/, 5]; 2120 case 3: 2121 e_3 = _a.sent(); 2122 this.draftProvisionError(e_3 && e_3.message 2123 ? String(e_3.message) 2124 : 'Could not create a replacement draft.'); 2125 return [3 /*break*/, 5]; 2126 case 4: 2127 if (!handingOff) { 2128 this.draftProvisioning(false); 2129 if (Distiller.endBayesBotBoot) { 2130 Distiller.endBayesBotBoot(); 2131 } 2132 } 2133 return [7 /*endfinally*/]; 2134 case 5: return [2 /*return*/]; 2135 } 2136 }); 2137 }); }; 2138 this.rememberCreatedStudyMembership = function (data) { 2139 if (Distiller.rememberBayesBotStudyMembership) { 2140 Distiller.rememberBayesBotStudyMembership(data); 2141 return; 2142 } 2143 var communityId = data && data.communityId != null 2144 ? parseInt(String(data.communityId), 10) 2145 : data && data.sid != null 2146 ? parseInt(String(data.sid), 10) 2147 : NaN; 2148 var currentUserId = data && data.currentUserId != null 2149 ? parseInt(String(data.currentUserId), 10) 2150 : data && data.studyUserId != null 2151 ? parseInt(String(data.studyUserId), 10) 2152 : data && data.userId != null 2153 ? parseInt(String(data.userId), 10) 2154 : NaN; 2155 if (!Number.isFinite(communityId) || communityId <= 0 || !Number.isFinite(currentUserId) || currentUserId <= 0) { 2156 console.error('BayesBot rememberCreatedStudyMembership: missing communityId or currentUserId', data); 2157 return; 2158 } 2159 var params = []; 2160 try { 2161 if (localStorage.quorumParams && Distiller.isJsonString && Distiller.isJsonString(localStorage.quorumParams)) { 2162 var parsed = JSON.parse(localStorage.quorumParams); 2163 if (Array.isArray(parsed)) { 2164 params = parsed; 2165 } 2166 } 2167 } 2168 catch (e) { 2169 params = []; 2170 } 2171 var already = params.some(function (row) { return row && String(row.communityId) === String(communityId); }); 2172 if (!already) { 2173 // community.type stays null â do not mark this as the parent admin membership. 2174 params.push({ communityId: communityId, currentUserId: currentUserId, type: null }); 2175 try { 2176 localStorage.setItem('quorumParams', JSON.stringify(params)); 2177 } 2178 catch (e) { 2179 console.error('BayesBot rememberCreatedStudyMembership: failed to write quorumParams', e); 2180 } 2181 } 2182 if (Distiller.memberships && typeof Distiller.memberships === 'function') { 2183 var existing = Distiller.memberships(); 2184 if (Array.isArray(existing) && !existing.some(function (row) { return row && String(row.
2184communityId) === String(communityId); })) { 2185 if (typeof Distiller.memberships.push === 'function') { 2186 Distiller.memberships.push({ communityId: communityId, currentUserId: currentUserId, type: null }); 2187 } 2188 } 2189 } 2190 }; 2191 this.applyCreatedStudyToUrl = function (data) { 2192 if (Distiller.applyBayesBotStudyToUrl) { 2193 Distiller.applyBayesBotStudyToUrl(data); 2194 return; 2195 } 2196 var communityId = data && data.communityId != null 2197 ? parseInt(String(data.communityId), 10) 2198 : data && data.sid != null 2199 ? parseInt(String(data.sid), 10) 2200 : NaN; 2201 if (!Number.isFinite(communityId) || communityId <= 0) { 2202 return; 2203 } 2204 try { 2205 var url = new URL(window.location.href); 2206 url.searchParams.set('sid', String(communityId)); 2207 var linkKey = data && data.linkKey != null ? String(data.linkKey) : ''; 2208 if (linkKey) { 2209 url.searchParams.set('study', linkKey); 2210 } 2211 url.searchParams.set('bayesBotDraft', '1'); 2212 var next = url.toString(); 2213 if (next !== window.location.href) { 2214 window.history.replaceState({ path: next }, '', next); 2215 if (Distiller.urlRevision) { 2216 var revision = Distiller.urlRevision; 2217 revision(revision() + 1); 2218 } 2219 } 2220 } 2221 catch (e) { 2222 console.error('BayesBot applyCreatedStudyToUrl failed:', e); 2223 } 2224 }; 2225 this.clearDraftCreateUrl = function () { 2226 try { 2227 var url = new URL(window.location.href); 2228 if (!url.searchParams.has('bayesBotDraft')) { 2229 return; 2230 } 2231 url.searchParams.delete('bayesBotDraft'); 2232 window.history.replaceState({ path: url.toString() }, '', url.toString()); 2233 if (Distiller.urlRevision) { 2234 var revision = Distiller.urlRevision; 2235 revision(revision() + 1); 2236 } 2237 } 2238 catch (e) { 2239 console.error('BayesBot clear draft URL failed:', e); 2240 } 2241 }; 2242 this.applyPersistedBuildStatus = function (buildStatus) { 2243 if (!buildStatus || typeof buildStatus !== 'object') { 2244 return; 2245 } 2246 if (buildStatus.jobId) { 2247 _this.lastBayesBotJobId(String(buildStatus.jobId)); 2248 } 2249 if (buildStatus.questionText && !isLegacyHormuzPlaceholder(buildStatus.questionText)) { 2250 _this.boundQuestionText(String(buildStatus.questionText)); 2251 } 2252 if (buildStatus.resolutionCriteria && !isLegacyHormuzPlaceholder(buildStatus.resolutionCriteria)) { 2253 _this.boundResolutionCriteria(String(buildStatus.resolutionCriteria)); 2254 } 2255 if (buildStatus.resolutionDate) { 2256 _this.boundResolutionDate(bayesBotIsoDate(buildStatus.resolutionDate) || _this.boundResolutionDate()); 2257 } 2258 if (buildStatus.headerMarkup) { 2259 var criteria = buildStatus.resolutionCriteria 2260 ? String(buildStatus.resolutionCriteria) 2261 : _this.boundResolutionCriteria(); 2262 _this.applyHeaderMarkupImmediate(String(buildStatus.headerMarkup), criteria ? bayesBotHeaderInfoHtml('Resolves Yes', criteria) : _this.headerInfoHtml()); 2263 } 2264 if (buildStatus.lifetimeInformation) { 2265 var lifetimeStatus = buildStatus.lifetimeInformation.status; 2266 var hasChart = Array.isArray(buildStatus.lifetimeInformation.breakpoints) && 2267 buildStatus.lifetimeInformation.breakpoints.length; 2268 if (hasChart || 2269 lifetimeStatus === 'awaiting_author_forecasts' || 2270 lifetimeStatus === 'filling_forecasts') { 2271 _this.presentPersistedLifetimeInformation(buildStatus.lifetimeInformation); 2272 } 2273 } 2274 var status = String(buildStatus.status || ''); 2275 if (status !== 'processing' && status !== 'queued') { 2276 return; 2277 } 2278 _this.proposalJobSettled = false;
2279 _this.nodeProposalSubmitting(true); 2280 _this.liveTemplateBuild = true; 2281 _this.proposalPhase('processing'); 2282 var message = buildStatus.message || 'Workingâ¦'; 2283 _this.proposalStatusText(message); 2284 _this.displayedProposalStatusText(message); 2285 _this.setProposalStatusText(message); 2286 if (buildStatus.jobId) { 2287 _this.pollBayesBotJobUntilDone(String(buildStatus.jobId)); 2288 } 2289 }; 2290 this.clearProposalStatusAnimation = function () { 2291 _this.statusTypewriterToken += 1; 2292 if (_this.statusTypewriterTimer) { 2293 clearTimeout(_this.statusTypewriterTimer); 2294 _this.statusTypewriterTimer = null; 2295 } 2296 _this.proposalStatusAnimating(false); 2297 _this.proposalStatusFreezeWidth(''); 2298 }; 2299 this.measureProposalStatusRowWidth = function () { 2300 var el = document.querySelector('.bayesBotProposalCard.isStatusFill .bayesBotProposalStatus'); 2301 if (!el) { 2302 return 0; 2303 } 2304 var width = el.getBoundingClientRect().width; 2305 var parent = el.parentElement; 2306 var max = parent ? parent.getBoundingClientRect().width : width; 2307 return max > 0 ? Math.min(width, max) : width; 2308 }; 2309 this.freezeProposalStatusRowWidth = function () { 2310 var width = _this.measureProposalStatusRowWidth(); 2311 if (width > 0) { 2312 _this.proposalStatusFreezeWidth(Math.ceil(width) + 'px'); 2313 } 2314 }; 2315 this.lockProposalStatusRowToContent = function () { 2316 _this.proposalStatusFreezeWidth(''); 2317 _this.freezeProposalStatusRowWidth(); 2318 }; 2319 this.setProposalStatusText = function (next, onDone) { 2320 var target = next == null ? '' : String(next); 2321 _this.proposalStatusText(target); 2322 if (_this.displayedProposalStatusText() === target && !_this.proposalStatusAnimating()) { 2323 if (onDone) { 2324 onDone(); 2325 } 2326 return; 2327 } 2328 _this.animateProposalStatusText(target, onDone); 2329 }; 2330 this.animateProposalStatusText = function (target, onDone) { 2331 var token = ++_this.statusTypewriterToken; 2332 if (_this.statusTypewriterTimer) { 2333 clearTimeout(_this.statusTypewriterTimer); 2334 _this.statusTypewriterTimer = null; 2335 } 2336 var hadText = _this.displayedProposalStatusText().length > 0; 2337 if (hadText) { 2338 _this.freezeProposalStatusRowWidth(); 2339 } 2340 _this.proposalStatusAnimating(hadText); 2341 var reveal = function () { 2342 if (token !== _this.statusTypewriterToken) { 2343 return; 2344 } 2345 _this.proposalStatusAnimating(false); 2346 _this.displayedProposalStatusText(target); 2347 _this.proposalStatusFreezeWidth(''); 2348 _this.freezeProposalStatusRowWidth(); 2349 _this.statusTypewriterTimer = null; 2350 if (onDone) { 2351 onDone(); 2352 } 2353 }; 2354 if (!hadText) { 2355 reveal(); 2356 return; 2357 } 2358 var backspace = function () { 2359 if (token !== _this.statusTypewriterToken) { 2360 return; 2361 } 2362 var shown = _this.displayedProposalStatusText(); 2363 if (shown.length > 0) { 2364 _this.displayedProposalStatusText(shown.slice(0, -1)); 2365 _this.statusTypewriterTimer = setTimeout(backspace, 22); 2366 return; 2367 } 2368 _this.statusTypewriterTimer = setTimeout(reveal, hadText ? 80 : 0); 2369 }; 2370 backspace(); 2371 }; 2372 this.lifetimeInformationFromJob = function (job) { 2373 if (!job) { 2374 return null; 2375 } 2376 if (job.results && job.results.lifetimeInformation) { 2377 return job.results.lifetimeInformation; 2378 } 2379 return job.lifetimeInformation || null; 2380 }; 2381 this.presentPersistedLifetimeInformation = function (lifetimeInformation) { 2382 if (!lifetimeInformation) { 2383 return; 2384 } 2385 if (!_this.viewingBranchCopyNetId()) { 2386 _this.canonicalLifetimeInformation = lifetimeInformation; 2387 } 2388 var status = lifetimeInformation && lifetimeInformation.status; 2389 if (status === 'awaiting_author_forecasts' || status === 'filling_forecasts') { 2390 _this.scoresStatus(String(status)); 2391 } 2392 else if (_this.lifetimeHasChart(lifetimeInformation)) { 2393 _this.scoresStatus(''); 2394 } 2395 _this.proposalLifetimeInformation(lifetimeInformation); 2396 var self = _this; 2397 setTimeout(function () {
2398 if (self.leaderboardPanelTab() === 'informationGain') { 2399 self.renderLifetimeInformationChart(); 2400 } 2401 }, 50); 2402 }; 2403 this.lifetimeScoreNetIdOnScreen = function () { 2404 var viewingBranch = _this.viewingBranchCopyNetId(); 2405 if (viewingBranch) { 2406 return viewingBranch; 2407 } 2408 if (!_this.viewingSharedTemplate && _this.personalCopyNetId) { 2409 var copyId = parseInt(String(_this.personalCopyNetId), 10); 2410 if (Number.isFinite(copyId) && copyId > 0) { 2411 return copyId; 2412 } 2413 } 2414 var templateId = _this.sharedTemplateNetId(); 2415 return templateId != null ? templateId : null; 2416 }; 2417 this.dismissProposalResult = function () { 2418 var wasError = _this.proposalPhase() === 'error'; 2419 var prior = _this.submittedProposalText(); 2420 _this.clearProposalStatusAnimation(); 2421 _this.clearBayesBotJobPoll(); 2422 _this.proposalPhase('idle'); 2423 _this.submittedProposalText(''); 2424 _this.proposalStatusText(''); 2425 _this.displayedProposalStatusText(''); 2426 _this.proposalStatusFreezeWidth(''); 2427 _this.proposalFinalResponse(''); 2428 _this.proposalInfoValue(null); 2429 _this.proposalSpecNotes([]); 2430 _this.showCreateNetLifetimeScore(false); 2431 _this.closeAddedSignalExplainer(); 2432 _this.closeShannonExplainer(); 2433 _this.nodeProposalSubmitting(false); 2434 if (wasError && prior) { 2435 _this.nodeProposalText(prior); 2436 } 2437 }; 2438 // STRIPE THEME: remove this dispose + the classList.add in the constructor to revert. 2439 this.dispose = function () { 2440 if (Distiller.bayesBotViewModel === _this) { 2441 Distiller.bayesBotViewModel = null; 2442 } 2443 document.body.classList.remove('bayesBotStripeTheme'); 2444 _this.closeLeaderboardScorePanel(); 2445 _this.closeShannonExplainer(); 2446 _this.clearProposalStatusAnimation(); 2447 _this.destroyLifetimeInformationChart(); 2448 _this.clearBayesBotJobPoll(); 2449 _this.headerTypewriterToken += 1; 2450 if (_this.headerTypewriterTimer) { 2451 clearTimeout(_this.headerTypewriterTimer); 2452 _this.headerTypewriterTimer = null; 2453 } 2454 _this.stopAgentExampleRotation(); 2455 if (_this.leaderboardScrollFrame != null && typeof cancelAnimationFrame === 'function') { 2456 cancelAnimationFrame(_this.leaderboardScrollFrame); 2457 _this.leaderboardScrollFrame = null; 2458 } 2459 }; 2460 this.onAuthorBayesNetReady = function (net) { 2461 _this.authorBayesNet = net; 2462 if (net && typeof net.setOnSelectionChange === 'function') { 2463 net.setOnSelectionChange(function (nodeId) { 2464 _this.selectedCanvasNodeId(nodeId != null ? Number(nodeId) : null); 2465 }); 2466 } 2467 _this.applyPrimaryNodeHighlight(); 2468 if (!_this.ownsCanonicalTemplate && 2469 _this.personalCopyNetId && 2470 _this.viewingSharedTemplate && 2471 !_this.viewingBranchCopyNetId()) { 2472 void _this.adoptPersonalCopyFromServer(_this.personalCopyNetId); 2473 } 2474 var queued = _this.pendingBayesBotGraphEvents.slice(); 2475 _this.pendingBayesBotGraphEvents = []; 2476 for (var i = 0; i < queued.length; i++) { 2477 _this.applyBayesBotGraphEvent(queued[i]); 2478 } 2479 }; 2480 this.applyPrimaryNodeHighlight = function () { 2481 var net = _this.authorBayesNet; 2482 if (!net || typeof net.setPrimaryNodeId !== 'function') { 2483 return; 2484 } 2485 var primaryId = _this.resolvePrimaryNodeId(); 2486 if (primaryId) { 2487 _this.leaderboardPrimaryNodeId(primaryId); 2488 } 2489 net.setPrimaryNodeId(primaryId); 2490 }; 2491 this.applyBayesBotGraphEvent = function (data) { 2492 if (!data || !data.type) { 2493 return; 2494 } 2495 if (!_this.authorBayesNet) { 2496 _this.pendingBayesBotGraphEvents.push(data); 2497 return; 2498 } 2499 if (_this.viewingSharedTemplate && !_this.liveTemplateBuild && !_this.ownsCanonicalTemplate && !_this.agentActivityLive()) { 2500 if (data.type !== 'prior' && 2501 data.type !== 'conditional' && 2502 data.type !== 'node' && 2503 data.type !== 'nodeDeleted' && 2504 data.type !== 'connectionRemoved' && 2505 data.type !== 'connection') { 2506 _this.pendingBayesBotGraphEvents.push(data); 2507 return; 2508 } 2509 } 2510 if (data.type === 'node' && data.node && typeof _this.authorBayesNet.applyRemoteCreatedNode === 'function') { 2511 var applied = _this.authorBayesNet.applyRemoteCreatedNode(data.node, data.parentNodeId); 2512 if (!applied) { 2513 _this.pendingBayesBotGraphEvents.push(data); 2514 return; 2515 } 2516 if (!_this.leaderboardPrimaryNodeId() && data.node.id != null) { 2517 _this.leaderboardPrimaryNodeId(parseInt(String(data.node.id), 10)); 2518 } 2519 _this.applyPrimaryNodeHighlight(); 2520 return; 2521 } 2522 if (data.type === 'nodeDeleted' && typeof _this.authorBayesNet.applyRemoteDeletedNode === 'function') { 2523 _this.authorBayesNet.applyRemoteDeletedNode(data.nodeId); 2524 return; 2525 } 2526 if (data.type === 'connection' && typeof _this.authorBayesNet.applyRemoteConnection === 'function') { 2527 _this.authorBayesNet.applyRemoteConnection(data.parentNodeId, data.childNodeId); 2528 _this.applyPrimaryNodeHighlight(); 2529 return; 2530 } 2531 if (data.type === 'connectionRemoved' && typeof _this.authorBayesNet.applyRemoteDeletedConnection === 'function') { 2532 _this.authorBayesNet.applyRemoteDeletedConnection(data.parentNodeId, data.childNodeId); 2533 return; 2534 } 2535 if (data.type === 'prior' && typeof _this.authorBayesNet.applyRemotePriorForecast === 'function') { 2536 _this.authorBayesNet.applyRemotePriorForecast(data.nodeId, data.values || []); 2537 return; 2538 } 2539 if (data.type === 'conditional' && typeof _this.authorBayesNet.applyRemoteConditionalForecast === 'function') { 2540 _this.authorBayesNet.applyRemoteConditionalForecast(data.nodeId, data.rows || []); 2541 } 2542 }; 2543 this.parseBayesBotSseData = function (event) { 2544 if (!event || event.data == null) { 2545 return null; 2546 } 2547 try { 2548 return typeof event.data === 'string' ? JSON.parse(event.data) : event.data; 2549 } 2550 catch (e) { 2551 console.error('BayesBot SSE parse failed:', e); 2552 return null; 2553 } 2554 }; 2555 this.isCurrentBayesBotJob = function (data) { 2556 if (!data) { 2557 return false;
2558 } 2559 var current = _this.lastBayesBotJobId(); 2560 if (!current) { 2561 return true; 2562 } 2563 return !data.jobId || String(data.jobId) === String(current); 2564 }; 2565 this.onBayesBotStatusEvent = function (event) { 2566 var data = _this.parseBayesBotSseData(event); 2567 if (_this.isMergeForecastJob(data)) { 2568 if ((_this.mergeInFlight() || _this.mergeForecastPending) && data && data.message) { 2569 var jobId = String(data.jobId); 2570 if (!_this.mergeStatusJobId || _this.mergeStatusJobId === jobId) { 2571 _this.mergeStatusJobId = jobId; 2572 _this.setMergeStatusText(String(data.message)); 2573 } 2574 } 2575 return; 2576 } 2577 if (!_this.isCurrentBayesBotJob(data) || _this.proposalPhase() !== 'processing') { 2578 return; 2579 } 2580 if (data && data.message) { 2581 _this.setProposalStatusText(data.message); 2582 } 2583 }; 2584 this.onBayesBotNodeCreatedEvent = function (event) { 2585 var data = _this.parseBayesBotSseData(event); 2586 if (!data || !data.node) { 2587 return; 2588 } 2589 if (!_this.isCurrentBayesBotJob(data) && !_this.agentActivityLive()) { 2590 return; 2591 } 2592 _this.liveTemplateBuild = true; 2593 if (!_this.authorBayesNetSet()) { 2594 _this.ensureCreateCanvasMounted(data); 2595 } 2596 _this.applyBayesBotGraphEvent({ 2597 type: 'node', 2598 node: data.node, 2599 parentNodeId: data.parentNodeId, 2600 }); 2601 }; 2602 this.onBayesBotNodeDeletedEvent = function (event) { 2603 var data = _this.parseBayesBotSseData(event); 2604 if (!data) { 2605 return; 2606 } 2607 if (!_this.isCurrentBayesBotJob(data) && !_this.agentActivityLive()) { 2608 return; 2609 } 2610 _this.applyBayesBotGraphEvent({ 2611 type: 'nodeDeleted', 2612 nodeId: data.nodeId, 2613 }); 2614 }; 2615 this.onBayesBotConnectionAddedEvent = function (event) { 2616 var data = _this.parseBayesBotSseData(event); 2617 if (!data) { 2618 return; 2619 } 2620 if (!_this.isCurrentBayesBotJob(data) && !_this.agentActivityLive()) { 2621 return; 2622 } 2623 _this.applyBayesBotGraphEvent({ 2624 type: 'connection', 2625 parentNodeId: data.parentNodeId, 2626 childNodeId: data.childNodeId, 2627 }); 2628 }; 2629 this.onBayesBotConnectionRemovedEvent = function (event) { 2630 var data = _this.parseBayesBotSseData(event); 2631 if (!data) { 2632 return; 2633 } 2634 if (!_this.isCurrentBayesBotJob(data) && !_this.agentActivityLive()) { 2635 return; 2636 } 2637 _this.applyBayesBotGraphEvent({ 2638 type: 'connectionRemoved', 2639 parentNodeId: data.parentNodeId, 2640 childNodeId: data.childNodeId, 2641 }); 2642 }; 2643 this.onBayesBotPriorForecastEvent = function (event) { 2644 var data = _this.parseBayesBotSseData(event); 2645 if (!data || _this.isMergeForecastJob(data)) { 2646 return; 2647 } 2648 if (!_this.isCurrentBayesBotJob(data) && !_this.agentActivityLive()) { 2649 return; 2650 } 2651 _this.applyBayesBotGraphEvent({ 2652 type: 'prior', 2653 nodeId: data.nodeId, 2654 values: data.values || [], 2655 }); 2656 }; 2657 this.onBayesBotConditionalForecastEvent = function (event) { 2658 var data = _this.parseBayesBotSseData(event); 2659 if (!data || _this.isMergeForecastJob(data)) { 2660 return; 2661 } 2662 if (!_this.isCurrentBayesBotJob(data) && !_this.agentActivityLive()) { 2663 return; 2664 } 2665 _this.applyBayesBotGraphEvent({ 2666 type: 'conditional', 2667 nodeId: data.nodeId, 2668 rows: data.rows || [], 2669 }); 2670 }; 2671 this.shouldAcceptBayesBotComplete = function (data) { 2672 if (!_this.isCurrentBayesBotJob(data) || !data || _this.proposalJobSettled) { 2673 return false;
2674 } 2675 if (_this.proposalPhase() === 'processing') { 2676 return true; 2677 } 2678 var currentJobId = _this.lastBayesBotJobId(); 2679 if (currentJobId && String(data.jobId || '') === String(currentJobId)) { 2680 return true; 2681 } 2682 return !currentJobId && !!(_this.isCreateMode() || _this.agentActivityLive()); 2683 }; 2684 this.onBayesBotCompleteEvent = function (event) { 2685 var data = _this.parseBayesBotSseData(event); 2686 if (!_this.shouldAcceptBayesBotComplete(data)) { 2687 return; 2688 } 2689 _this.proposalJobSettled = true; 2690 var wasCreateMode = _this.isCreateMode(); 2691 var createJobOk = wasCreateMode && 2692 data.status !== 'error' && 2693 data.draftStatus !== 'failed'; 2694 var isHardFailure = !createJobOk && (data.status === 'error' || data.status === 'partial'); 2695 _this.liveTemplateBuild = false; 2696 _this.proposalFinalResponse(data.responseText || data.error || ''); 2697 _this.proposalInfoValue(data.infoValue || null); 2698 var incomingNotes = Array.isArray(data.specNotes) 2699 ? data.specNotes 2700 : Array.isArray(data.warnings) 2701 ? data.warnings 2702 : []; 2703 _this.proposalSpecNotes(incomingNotes.map(function (row) { return String(row || '').trim(); }).filter(function (row) { return !!row; })); 2704 if (_this.leaderboardPanelTab() === 'logs') { 2705 _this.loadSpecLogs(true); 2706 } 2707 if (data.lifetimeInformation && 2708 Array.isArray(data.lifetimeInformation.breakpoints) && 2709 data.lifetimeInformation.breakpoints.length) { 2710 _this.presentPersistedLifetimeInformation(data.lifetimeInformation); 2711 } 2712 _this.showCreateNetLifetimeScore(!!wasCreateMode); 2713 _this.applyLeaderboardFromInfoValue(data.infoValue); 2714 _this.nodeProposalSubmitting(false); 2715 _this.clearBayesBotJobPoll(); 2716 if (isHardFailure) { 2717 _this.proposalPhase('error'); 2718 _this.setProposalStatusText(data.message || 'Something went wrong'); 2719 if (wasCreateMode) { 2720 _this.applyHeaderMarkupImmediate(BAYES_BOT_CREATE_HEADER_MARKUP, BAYES_BOT_BAYES_NET_INFO); 2721 _this.draftNeedsReplacement(true); 2722 _this.draftProvisionError(data.error || 2723 data.message || 2724 'The model could not be built. Start a new draft to retry.'); 2725 } 2726 return; 2727 } 2728 _this.clearProposalStatusAnimation(); 2729 _this.proposalStatusText(''); 2730 _this.displayedProposalStatusText(''); 2731 _this.proposalStatusFreezeWidth(''); 2732 _this.proposalPhase('complete'); 2733 if (wasCreateMode) { 2734 _this.isCreateMode(false); 2735 } 2736 _this.clearDraftCreateUrl(); 2737 if (wasCreateMode) { 2738 _this.ownsCanonicalTemplate = true; 2739 _this.authorOwnsTemplate(true); 2740 } 2741 if (data.copyNetId && !_this.ownsCanonicalTemplate && !_this.isTempVisitor()) { 2742 void _this.adoptPersonalCopyFromServer(data.copyNetId, data.setId).then(function (loadedCopy) { 2743 if (!_this.authorBayesNetSet()) { 2744 void _this.loadAuthorBayesNet(); 2745 return; 2746 } 2747 if (!loadedCopy) { 2748 void _this.reloadAuthorBayesNetGraph(); 2749 } 2750 }); 2751 } 2752 else if (!_this.authorBayesNetSet()) { 2753 void _this.loadAuthorBayesNet(); 2754 } 2755 else { 2756 void _this.reloadAuthorBayesNetGraph(); 2757 } 2758 _this.loadLeaderboard(); 2759 }; 2760 this.clearBayesBotJobPoll = function () { 2761 if (_this.bayesBotPollTimer) { 2762 clearTimeout(_this.bayesBotPollTimer); 2763 _this.bayesBotPollTimer = null; 2764 } 2765 }; 2766 this.collectFinalResponseFromJob = function (job) { 2767 if (!job) { 2768 return ''; 2769 } 2770 if (job.results && job.results.invalid && job.results.message) { 2771 return String(job.results.message); 2772 } 2773 var infoValueSummary = job.results && job.results.infoValueSummary && String(job.results.infoValueSummary).trim() 2774 ? String(job.results.infoValueSummary).trim() 2775 : ''; 2776 if (infoValueSummary) { 2777 return infoValueSummary; 2778 } 2779 var tasks = job.results && (job.results.tasks || job.results.lanes) 2780 ? job.results.tasks || job.results.lanes 2781 : []; 2782 var answers = []; 2783 for (var i = 0; i < tasks.length; i++) { 2784 if (tasks[i] && tasks[i].answer && String(tasks[i].answer).trim()) { 2785 answers.push(String(tasks[i].answer).trim()); 2786 } 2787 } 2788 if (answers.length) { 2789 return answers.join('\n\n'); 2790 } 2791 if (job.error) { 2792 return String(job.error); 2793 } 2794 return 'Proposal processed.'; 2795 }; 2796 this.formatCompactRank = function (rank, rankOf) { 2797 if (rank != null && rankOf > 0) { 2798 return '#' + rank; 2799 } 2800 if (rank != null) { 2801 return '#' + rank; 2802 } 2803 return 'â'; 2804 }; 2805 this.applyLeaderboardNodes = function (nodes, rankOf) { 2806 var list = Array.isArray(nodes) ? nodes.slice() : []; 2807 var ranked = list.filter(function (n) { return n && !n.isEndState; }); 2808 ranked.sort(function (a, b) { 2809 var ar = a.rank != null ? a.rank : Number.MAX_SAFE_INTEGER; 2810 var br = b.rank != null ? b.rank : Number.MAX_SAFE_INTEGER; 2811 if (ar !== br) { 2812 return ar - br; 2813 } 2814 return String(a.title || '').localeCompare(String(b.title || '')); 2815 }); 2816 _this.leaderboardNodes(ranked); 2817 var inferred = rankOf != null && rankOf > 0 2818 ? rankOf 2819 : ranked.reduce(function (max, n) { 2820 var r = n && n.rank != null ? n.rank : 0; 2821 return r > max ? r : max; 2822 }, ranked.length); 2823 _this.leaderboardRankOf(inferred); 2824 }; 2825 this.applyLeaderboardFromInfoValue = function (info) { 2826 if (!info || !Array.isArray(info.nodes) || !info.nodes.length) { 2827 _this.loadLeaderboard(); 2828 return; 2829 } 2830 if (info.endStateNodeId) { 2831 _this.leaderboardPrimaryNodeId(info.endStateNodeId); 2832 } 2833 _this.applyLeaderboardNodes(info.nodes, info.rankOf); 2834 _this.applyPrimaryNodeHighlight(); 2835 }; 2836 this.loadLeaderboard = function () { 2837 var currentUser = Distiller.currentUser && Distiller.currentUser(); 2838 var userId = currentUser && currentUser.userId; 2839 if (!userId) { 2840 return; 2841 } 2842 var onScreenNetId = _this.lifetimeScoreNetIdOnScreen(); 2843 Distiller.httpGetAsync(Distiller.apiEndpoint + '/api/bayesBotLeaderboard/' + userId 2844 + '?communityId=' + encodeURIComponent(String(_this.resolveBoundCommunityId())) 2845 + (onScreenNetId 2846 ? '&netId=' + encodeURIComponent(String(onScreenNetId)) 2847 : ''), function (responseText) { 2848 try { 2849 var parsed = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 2850 if (!parsed || parsed.ok === false) { 2851 return; 2852 } 2853 _this.scoresStatus(parsed.scoresStatus ? String(parsed.scoresStatus) : ''); 2854 _this.leaderboardPrimaryNodeId(parsed.primaryNodeId || null); 2855 _this.applyLeaderboardNodes(parsed.nodes || [], parsed.rankOf); 2856 _this.applyPrimaryNodeHighlight(); 2857 } 2858 catch (e) { 2859 console.error('BayesBot leaderboard parse failed:', e); 2860 } 2861 }); 2862 }; 2863 this.leaderboardRows = ko.pureComputed(function () { 2864 var rankOf = _this.leaderboardRankOf() || 0; 2865 var pinnedId = _this.pinnedLeaderboardNodeId(); 2866 var selectedId = pinnedId != null ? pinnedId : _this.selectedCanvasNodeId(); 2867 return _this.leaderboardNodes().map(function (node) { return ({ 2868 nodeId: node.nodeId, 2869 title: node.title || 'Untitled node', 2870 isNew: !!node.isNew, 2871 isSelected: _this.canvasSelectionMatchesRow(selectedId, node), 2872 metric: _this.enrichLeaderboardMetric(node), 2873 usefulnessScore: _this.formatUsefulnessScore(node.informationValue), 2874 overall: _this.formatCompactRank(node.rank, rankOf), 2875 overallFull: _this.formatInfoValueRank(node.rank, rankOf), 2876 diagnosticity: _this.formatCompactRank(node.diagnosticityRank, rankOf), 2877 diagnosticityFull: _this.formatInfoValueRank(node.diagnosticityRank, rankOf), 2878 timeliness: _this.formatCompactRank(node.timelinessRank, rankOf), 2879 timelinessFull: _this.formatInfoValueRank(node.timelinessRank, rankOf), 2880 }); }); 2881 }); 2882 this.formatUsefulnessScore = function (value) { 2883 if (value == null || !isFinite(Number(value))) { 2884 return 'â'; 2885 } 2886 return Number(value).toFixed(2); 2887 }; 2888 this.formatAddedSignal = function (value) { 2889 if (value == null || !isFinite(Number(value))) { 2890 return 'â'; 2891 } 2892 return Number(value).toFixed(2); 2893 }; 2894 this.enrichLeaderboardMetric = function (node) { 2895 if (!node) { 2896 return node; 2897 } 2898 var metric = Object.assign({}, node); 2899 if (metric.diagnosticityDeltaPrc == null && metric.impactScore != null && isFinite(Number(metric.impactScore))) { 2900 metric.diagnosticityDeltaPrc = Math.round(Number(metric.impactScore) * 1000) / 10; 2901 } 2902 return metric; 2903 }; 2904 this.formatInfoValueRank = function (rank, rankOf) { 2905 if (rank != null && rankOf > 0) { 2906 return '#' + rank + ' of ' + rankOf; 2907 } 2908 return 'unranked'; 2909 }; 2910 this.proposalInfoValueRows = ko.pureComputed(function () { 2911 var info = _this.proposalInfoValue(); 2912 var highlighted = info && Array.isArray(info.highlighted) ? info.highlighted : []; 2913 var many = highlighted.length > 1; 2914 return highlighted.map(function (node) { 2915 var rankOf = node.rankOf != null ? node.rankOf : (info && info.rankOf) || 0; 2916 return { 2917 metric: node, 2918 who: many ? '"' + (node.title || 'This node') + '"' : 'Your node', 2919 overall: _this.formatInfoValueRank(node.rank, rankOf), 2920 diagnosticity: _this.formatInfoValueRank(node.diagnosticityRank, rankOf), 2921 timeliness: _this.formatInfoValueRank(node.timelinessRank, rankOf), 2922 addedSignalLabel: _this.formatAddedSignal(node.addedSignal), 2923 }; 2924 }); 2925 }); 2926 this.missingForecastLeaderboardMessage = ko.pureComputed(function () { 2927 return _this.authorOwnsTemplate() 2928 ? 'You must provide missing forecasts before we can provide a node leaderboard.' 2929 : 'The author of this model must provide missing forecasts before we can provide a node leaderboard.'; 2930 }); 2931 this.missingForecastInformationMessage = ko.pureComputed(function () { 2932 return _this.authorOwnsTemplate() 2933 ? 'You must provide missing forecasts before we can calculate expected information gain over time.' 2934 : 'The author of this model must provide missing forecasts before we can calculate expected information gain over time.'; 2935 }); 2936 this.hasLifetimeChart = ko.pureComputed(function () { 2937 var result = _this.proposalLifetimeInformation(); 2938 return !!(result && Array.isArray(result.breakpoints) && result.breakpoints.length); 2939 }); 2940 this.formatLeadBeforeResolution = function (timeMs, endMs) { 2941 if (timeMs == null || endMs == null || !isFinite(timeMs) || !isFinite(endMs)) { 2942 return 'before resolution'; 2943 } 2944 var ms = endMs - timeMs; 2945 if (ms <= 0) { 2946 return 'at resolution'; 2947 } 2948 var hours = ms / 3600000; 2949 var days = hours / 24; 2950 var weeks = days / 7; 2951 var months = days / 30.437; 2952 var years = days / 365.2425; 2953 var formatCount = function (n, unit) { 2954 var rounded = n >= 10 ? Math.round(n) : Math.round(n * 10) / 10; 2955 var shown = Math.abs(rounded - Math.round(rounded)) < 0.05 ? String(Math.round(rounded)) : rounded.toFixed(1); 2956 var plural = Number(shown) === 1 ? unit : unit + 's'; 2957 return shown + ' ' + plural + ' before resolution'; 2958 }; 2959 if (years >= 1) { 2960 return formatCount(years, 'year'); 2961 } 2962 if (months >= 1) { 2963 return formatCount(months, 'month'); 2964 } 2965 if (weeks >= 1) { 2966 return formatCount(weeks, 'week'); 2967 } 2968 if (days >= 1) { 2969 return formatCount(days, 'day'); 2970 } 2971 return formatCount(Math.max(hours, 1), 'hour'); 2972 }; 2973 this.lifetimeTimepointRows = ko.pureComputed(function () { 2974 var result = _this.proposalLifetimeInformation();
2975 var breakpoints = _this.lifetimeChartBreakpoints(result); 2976 var endMs = result && result.endTimeMs != null 2977 ? Number(result.endTimeMs) 2978 : breakpoints.length 2979 ? breakpoints[breakpoints.length - 1].timeMs 2980 : null; 2981 var rows = []; 2982 for (var i = 0; i < breakpoints.length; i++) { 2983 var bp = breakpoints[i]; 2984 if (!bp || bp.isStart) { 2985 continue; 2986 } 2987 var pct = Math.round(Number(bp.normalizedInformation || 0) * 100); 2988 rows.push({ 2989 label: _this.formatUtcLongDate(bp.timeMs) + 2990 ' (' + 2991 _this.formatLeadBeforeResolution(bp.timeMs, endMs) + 2992 '): ' + 2993 pct + 2994 '%', 2995 }); 2996 } 2997 return rows; 2998 }); 2999 this.shannonBitsLabel = ko.pureComputed(function () { 3000 var result = _this.proposalLifetimeInformation(); 3001 var bits = result && result.h0Bits != null ? Number(result.h0Bits) : NaN; 3002 if (!isFinite(bits)) { 3003 return 'an unknown number of bits of uncertainty'; 3004 } 3005 return (Math.round(bits * 100) / 100).toFixed(2) + ' bits of uncertainty'; 3006 }); 3007 this.shannonExplainerTerms = ko.pureComputed(function () { 3008 var result = _this.proposalLifetimeInformation(); 3009 var states = result && Array.isArray(result.h0States) ? result.h0States : []; 3010 return states.map(function (state) { 3011 var p = Number(state && state.probability); 3012 var name = state && state.name ? String(state.name) : 'State'; 3013 if (!(p > 0)) { 3014 return { name: name, line: 'P = 0 (does not contribute)' }; 3015 } 3016 var term = -(p * (Math.log(p) / Math.log(2))); 3017 return { 3018 name: name, 3019 line: 'P = ' + 3020 p.toFixed(2) + 3021 ', âp logâ(p) = ' + 3022 (Math.round(term * 100) / 100).toFixed(2), 3023 }; 3024 }); 3025 }); 3026 this.shannonExplainerTotal = ko.pureComputed(function () { 3027 var result = _this.proposalLifetimeInformation(); 3028 var bits = result && result.h0Bits != null ? Number(result.h0Bits) : NaN; 3029 if (!isFinite(bits)) { 3030 return 'Hâ is unavailable for this net.'; 3031 } 3032 return '= ' + (Math.round(bits * 100) / 100).toFixed(2) + ' bits'; 3033 }); 3034 this.showShannonExplainer = function (_data, event) { 3035 if (event && typeof event.preventDefault === 'function') { 3036 event.preventDefault(); 3037 event.stopPropagation(); 3038 } 3039 _this.shannonExplainerOpen(true); 3040 }; 3041 this.closeShannonExplainer = function () { 3042 _this.shannonExplainerOpen(false); 3043 }; 3044 this.lifetimeInformationView = ko.pureComputed(function () { 3045 if (_this.proposalPhase() === 'processing' && _this.showCreateNetLifetimeScore()) { 3046 return { 3047 kind: 'loading', 3048 headline: 'Measuring lifetime informationâ¦', 3049 explanation: '', 3050 rawAreaLabel: '', 3051 warningLines: [], 3052 estimated: false, 3053 showChart: false, 3054 percentText: '', 3055 }; 3056 } 3057 if (!_this.showCreateNetLifetimeScore()) { 3058 return null; 3059 } 3060 var result = _this.proposalLifetimeInformation(); 3061 if (!result) { 3062 if (_this.proposalPhase() === 'complete') { 3063 return { 3064 kind: 'loading', 3065 headline: 'Measuring lifetime informationâ¦', 3066 explanation: '', 3067 rawAreaLabel: '', 3068 warningLines: [], 3069 estimated: false, 3070 showChart: false, 3071 percentText: '', 3072 }; 3073 } 3074 return null; 3075 } 3076 return _this.mapLifetimeInformationUi(result); 3077 }); 3078 this.mapLifetimeInformationUi = function (result) { 3079 var exclusions = (result && result.exclusions) || {}; 3080 var warningLines = []; 3081 var undated = exclusions.undatedCount || 0; 3082 var post = exclusions.postPrimaryCount || 0; 3083 if (undated > 0) { 3084 warningLines.push(undated === 1 3085 ? '1 node was excluded because it has no resolution date.' 3086 : String(undated) + ' nodes were excluded because they have no resolution date.'); 3087 } 3088 if (post > 0) { 3089 warningLines.push(post === 1 3090 ? '1 node resolves at or after the primary question and does not contribute early-warning value.' 3091 : String(post) + 3092 ' nodes resolve at or after the primary question and do not contribute early-warning value.'); 3093 } 3094 if (result && result.calculationWarning) { 3095 warningLines.push(String(result.calculationWarning)); 3096 } 3097 if (!result || result.status === 'error') { 3098 return { 3099 kind: 'error', 3100 headline: 'Lifetime Information Score could not be calculated.', 3101 explanation: (result && result.errorMessage) || 3102 'Something went wrong while measuring expected information.', 3103 rawAreaLabel: '', 3104 warningLines: warningLines, 3105 estimated: false, 3106 showChart: false, 3107 percentText: '', 3108 }; 3109 } 3110 if (result.status === 'missingPrimaryDate') { 3111 return { 3112 kind: 'missingPrimaryDate', 3113 headline: 'Lifetime Information Score unavailable: the primary question needs a future resolution date.', 3114 explanation: '', 3115 rawAreaLabel: '', 3116 warningLines: warningLines, 3117 estimated: false, 3118 showChart: false, 3119 percentText: '', 3120 }; 3121 } 3122 if (result.status === 'alreadyCertain') { 3123 return { 3124 kind: 'alreadyCertain', 3125 headline: 'Not applicable: the primary outcome is already certain.', 3126 explanation: 'There is no remaining uncertainty for the net to eliminate.', 3127 rawAreaLabel: 'Information-time value: 0 bit-days', 3128 warningLines: warningLines, 3129 estimated: false, 3130 showChart: false, 3131 percentText: '', 3132 }; 3133 } 3134 var percent = result.lifetimeInformationPercent != null && isFinite(Number(result.lifetimeInformationPercent)) 3135 ? Number(result.lifetimeInformationPercent) 3136 : 0; 3137 var percentText = String(Math.round(percent)) + '%'; 3138 var unit = result.displayUnit || 'bit-days'; 3139 var rawValue = result.rawAreaDisplayValue != null && isFinite(Number(result.rawAreaDisplayValue)) 3140 ? Number(result.rawAreaDisplayValue) 3141 : 0; 3142 var rawRounded = Math.round(rawValue * 10) / 10; 3143 var rawLabel = Math.abs(rawRounded - Math.round(rawRounded)) < 0.05 3144 ? String(Math.round(rawRounded)) 3145 : rawRounded.toFixed(1); 3146 return { 3147 kind: result.status === 'noEligibleNodes' ? 'noEligibleNodes' : 'score', 3148 headline: 'Lifetime Information Score: ' + percentText, 3149 explanation: 'This Bayes net is expected to eliminate an average of ' + 3150 percentText + 3151 " of the primary question's current uncertainty across its remaining lifetime. Information that becomes available earlier contributes more to the score. The shaded area is the Lifetime Information Score.", 3152 rawAreaLabel: 'Information-time value: ' + rawLabel + ' ' + unit, 3153 warningLines: warningLines, 3154 estimated: result.exact === false, 3155 showChart: true, 3156 percentText: percentText, 3157 }; 3158 }; 3159 this.formatUtcLongDate = function (timeMs) { 3160 var months = [ 3161 'January', 'February', 'March', 'April', 'May', 'June', 3162 'July', 'August', 'September', 'October', 'November', 'December', 3163 ]; 3164 var d = new Date(timeMs); 3165 return months[d.getUTCMonth()] + ' ' + d.getUTCDate() + ', ' + d.getUTCFullYear(); 3166 }; 3167 this.destroyLifetimeInformationChart = function () { 3168 if (_this.lifetimeInfoChart && typeof _this.lifetimeInfoChart.destroy === 'function') { 3169 _this.lifetimeInfoChart.destroy(); 3170 } 3171 _this.lifetimeInfoChart = null; 3172 }; 3173 this.renderLifetimeInformationChart = function () { 3174 _this.destroyLifetimeInformationChart();
3175 if (_this.leaderboardPanelTab() !== 'informationGain') { 3176 return; 3177 } 3178 var result = _this.proposalLifetimeInformation(); 3179 if (!result || !Array.isArray(result.breakpoints) || !result.breakpoints.length) { 3180 return; 3181 } 3182 var canvas = document.querySelector('.bayesBotInformationGainBody .bayesBotLifetimeChartCanvas'); 3183 if (!canvas) { 3184 return; 3185 } 3186 var ChartLib = window.Chart; 3187 if (!ChartLib) { 3188 return; 3189 } 3190 var breakpoints = _this.lifetimeChartBreakpoints(result); 3191 var ticks = Array.isArray(result.chartTicks) ? result.chartTicks : []; 3192 var labeledTicks = ticks.length > 1 ? ticks.slice(1) : ticks; 3193 var startMs = result.startTimeMs != null ? result.startTimeMs : breakpoints[0].timeMs; 3194 var endMs = result.endTimeMs != null 3195 ? result.endTimeMs 3196 : breakpoints[breakpoints.length - 1].timeMs; 3197 var axisEndMs = _this.lifetimeChartAxisEndMs(startMs, endMs, ticks); 3198 var dataPoints = breakpoints.map(function (bp) { return ({ 3199 x: bp.timeMs, 3200 y: Number(bp.normalizedInformation || 0) * 100, 3201 }); }); 3202 var self = _this; 3203 var ctx = canvas.getContext('2d'); 3204 _this.lifetimeInfoChart = new ChartLib(ctx, { 3205 type: 'line', 3206 data: { 3207 datasets: [ 3208 { 3209 label: 'Expected Information Gain', 3210 data: dataPoints, 3211 // Chart.js 3: 'before' holds y until the next event, then jumps. 3212 // 'after' applies the next y immediately, which painted the first 3213 // resolution's height from t0. 3214 stepped: 'before', 3215 fill: 'origin', 3216 clip: false, 3217 borderColor: '#2563EB', 3218 backgroundColor: 'rgba(37, 99, 235, 0.18)', 3219 borderWidth: 2, 3220 tension: 0, 3221 pointRadius: function (ctx) { 3222 var bp = breakpoints[ctx.dataIndex]; 3223 if (!bp) { 3224 return 0; 3225 } 3226 if (bp.isPrimaryResolution) { 3227 return 6; 3228 } 3229 if (bp.resolvingNodeIds && bp.resolvingNodeIds.length) { 3230 return 4; 3231 } 3232 if (bp.isStart) { 3233 return 3; 3234 } 3235 return 2; 3236 }, 3237 pointHoverRadius: 7, 3238 pointHitRadius: 10,
3239 pointBackgroundColor: function (ctx) { 3240 var bp = breakpoints[ctx.dataIndex]; 3241 if (bp && bp.isPrimaryResolution) { 3242 return '#2563EB'; 3243 } 3244 return '#06B6D4'; 3245 }, 3246 pointBorderColor: '#172554', 3247 pointBorderWidth: 1, 3248 }, 3249 ], 3250 }, 3251 options: { 3252 responsive: true, 3253 maintainAspectRatio: false, 3254 animation: false, 3255 interaction: { mode: 'point', intersect: true }, 3256 onHover: function (evt, elements) { 3257 var canvasEl = evt && evt.native && evt.native.target; 3258 if (canvasEl && canvasEl.style) { 3259 canvasEl.style.cursor = elements && elements.length ? 'pointer' : 'default'; 3260 } 3261 }, 3262 onClick: function (evt, elements) { 3263 if (!elements || !elements.length) { 3264 return; 3265 } 3266 var idx = elements[0].index; 3267 var bp = breakpoints[idx]; 3268 if (!bp) { 3269 return; 3270 } 3271 var native = (evt && evt.native) || evt; 3272 self.showLifetimeTimepointModal(bp, native); 3273 }, 3274 plugins: { 3275 filler: { propagate: false }, 3276 legend: { display: false }, 3277 tooltip: { 3278 enabled: true, 3279 mode: 'point', 3280 intersect: true, 3281 displayColors: false, 3282 callbacks: { 3283 title: function (items) { 3284 if (!items || !items.length) { 3285 return ''; 3286 } 3287 var x = items[0].parsed && items[0].parsed.x; 3288 var bp = self.closestLifetimeBreakpoint(breakpoints, x); 3289 return bp ? self.formatUtcLongDate(bp.timeMs) : ''; 3290 }, 3291 label: function (item) { 3292 var x = item && item.parsed && item.parsed.x; 3293 var bp = self.closestLifetimeBreakpoint(breakpoints, x); 3294 if (!bp) { 3295 return ''; 3296 } 3297 var pct = Math.round(Number(bp.normalizedInformation || 0) * 100); 3298 return pct + '% information gained'; 3299 }, 3300 afterBody: function () { 3301 return ['Click for details']; 3302 }, 3303 }, 3304 }, 3305 }, 3306 scales: { 3307 x: { 3308 type: 'linear', 3309 min: startMs, 3310 max: axisEndMs, 3311 title: { display: false }, 3312 afterBuildTicks: function (axis) { 3313 if (!labeledTicks.length) { 3314 return; 3315 } 3316 axis.ticks = labeledTicks.map(function (tick) { 3317 return { value: tick.timeMs }; 3318 }); 3319 }, 3320 ticks: { 3321 autoSkip: false, 3322 maxRotation: 45, 3323 minRotation: 0, 3324 callback: function (value) { 3325 var n = Number(value); 3326 for (var i = 0; i < labeledTicks.length; i++) { 3327 if (Math.abs(labeledTicks[i].timeMs - n) < 1) { 3328 return labeledTicks[i].label; 3329 } 3330 } 3331 return ''; 3332 }, 3333 }, 3334 }, 3335 y: { 3336 min: 0, 3337 max: 108, 3338 title: { 3339 display: true, 3340 text: 'Expected Information Gain', 3341 color: '#64748B', 3342 font: { size: 11 },
3343 }, 3344 afterBuildTicks: function (axis) { 3345 axis.ticks = [0, 20, 40, 60, 80, 100].map(function (value) { 3346 return { value: value }; 3347 }); 3348 }, 3349 ticks: { 3350 callback: function (value) { 3351 var n = Number(value); 3352 if (!isFinite(n) || n > 100) { 3353 return ''; 3354 } 3355 return String(n) + '%'; 3356 }, 3357 }, 3358 }, 3359 }, 3360 }, 3361 }); 3362 }; 3363 this.lifetimeChartTickScale = function (startMs, endMs) { 3364 var horizonDays = (endMs - startMs) / 86400000; 3365 var daysPerYear = 365.2425; 3366 if (horizonDays < 90) { 3367 return { 3368 unit: 'day', 3369 step: horizonDays <= 16 ? 1 : Math.max(1, Math.ceil(horizonDays / 10)), 3370 }; 3371 } 3372 if (horizonDays < 2 * daysPerYear) { 3373 if (horizonDays < 180) { 3374 return { unit: 'week', step: horizonDays < 120 ? 1 : 2 }; 3375 } 3376 return { unit: 'month', step: 1 }; 3377 } 3378 if (horizonDays < 8 * daysPerYear) { 3379 return { unit: 'month', step: horizonDays < 4 * daysPerYear ? 3 : 6 }; 3380 } 3381 return { unit: 'year', step: 1 }; 3382 }; 3383 this.addLifetimeAxisPad = function (timeMs, unit, step) { 3384 var d = new Date(timeMs); 3385 var y = d.getUTCFullYear(); 3386 var m = d.getUTCMonth(); 3387 var day = d.getUTCDate(); 3388 if (unit === 'day') { 3389 return Date.UTC(y, m, day + step); 3390 } 3391 if (unit === 'week') { 3392 return Date.UTC(y, m, day + step * 7); 3393 } 3394 if (unit === 'month') { 3395 return Date.UTC(y, m + step, day); 3396 } 3397 return Date.UTC(y + step, m, day); 3398 }; 3399 this.lifetimeChartAxisEndMs = function (startMs, endMs, ticks) { 3400 if (ticks && ticks.length >= 3) { 3401 var gap = Number(ticks[ticks.length - 1].timeMs) - Number(ticks[ticks.length - 2].timeMs); 3402 if (gap > 0 && gap < endMs - startMs) { 3403 return endMs + gap; 3404 } 3405 } 3406 var scale = _this.lifetimeChartTickScale(startMs, endMs); 3407 return _this.addLifetimeAxisPad(endMs, scale.unit, scale.step); 3408 }; 3409 this.lifetimeChartBreakpoints = function (result) { 3410 var rows = result && Array.isArray(result.breakpoints) ? result.breakpoints : []; 3411 var h0 = result && result.h0Bits != null && isFinite(Number(result.h0Bits)) 3412 ? Number(result.h0Bits) 3413 : null; 3414 return rows.map(function (bp) { 3415 if (!bp || !bp.isPrimaryResolution) { 3416 return bp; 3417 } 3418 return __assign(__assign({}, bp), { expectedEntropyBits: 0, informationBits: h0 != null ? h0 : bp.informationBits, normalizedInformation: 1 }); 3419 }); 3420 }; 3421 this.closestLifetimeBreakpoint = function (breakpoints, timeMs) { 3422 if (!breakpoints || !breakpoints.length || timeMs == null || !isFinite(Number(timeMs))) { 3423 return null; 3424 } 3425 var best = breakpoints[0]; 3426 var bestD = Math.abs(best.timeMs - timeMs); 3427 for (var i = 1; i < breakpoints.length; i++) { 3428 var d = Math.abs(breakpoints[i].timeMs - timeMs); 3429 if (d < bestD) { 3430 best = breakpoints[i]; 3431 bestD = d; 3432 } 3433 } 3434 return best; 3435 }; 3436 this.formatPercentagePoints = function (value) { 3437 if (value == null || !isFinite(Number(value))) { 3438 return 'an unknown amount'; 3439 } 3440 var n = Math.round(Number(value) * 10) / 10; 3441 var label = Math.abs(n - Math.round(n)) < 0.05 ? String(Math.round(n)) : n.toFixed(1); 3442 return label + ' percentage point' + (Number(label) === 1 ? '' : 's'); 3443 }; 3444 this.formatLeadDays = function (days) { 3445 if (days == null || !isFinite(Number(days))) { 3446 return null; 3447 } 3448 var n = Math.round(Number(days)); 3449 return String(n) + ' day' + (Math.abs(n) === 1 ? '' : 's'); 3450 }; 3451 this.wrapInfoHtml = function (html) { 3452 return '<div style="font-size:13px;line-height:1.5;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;">' + html + '</div>'; 3453 // ORIGINAL: return '<div style="font-size:12px;line-height:1.45;">
3453' + html + '</div>'; 3454 }; 3455 this.resolvePrimaryNodeId = function () { 3456 var net = _this.authorBayesNet; 3457 var nodes = net && net.nodes ? net.nodes : []; 3458 var liveIds = {}; 3459 for (var i = 0; i < nodes.length; i++) { 3460 liveIds[Number(nodes[i].id)] = true; 3461 } 3462 var stored = _this.leaderboardPrimaryNodeId(); 3463 if (stored && liveIds[Number(stored)]) { 3464 return Number(stored); 3465 } 3466 var question = String(_this.boundQuestionText() || '').trim().toLowerCase(); 3467 var header = stripBayesBotHeaderMarkup(_this.headerMarkup() || '').trim().toLowerCase(); 3468 for (var i = 0; i < nodes.length; i++) { 3469 var title = String(nodes[i].title || '').trim().toLowerCase(); 3470 if (!title) { 3471 continue; 3472 } 3473 if (question && (question.indexOf(title) >= 0 || title.indexOf(question) >= 0)) { 3474 return Number(nodes[i].id); 3475 } 3476 if (header && (header.indexOf(title) >= 0 || title.indexOf(header) >= 0)) { 3477 return Number(nodes[i].id); 3478 } 3479 } 3480 var bestId = null; 3481 var bestCount = 0; 3482 var incoming = {}; 3483 for (var i = 0; i < nodes.length; i++) { 3484 incoming[Number(nodes[i].id)] = incoming[Number(nodes[i].id)] || 0; 3485 var children = nodes[i].childrenIds || []; 3486 for (var c = 0; c < children.length; c++) { 3487 var childId = Number(children[c]); 3488 incoming[childId] = (incoming[childId] || 0) + 1; 3489 } 3490 } 3491 var keys = Object.keys(incoming); 3492 for (var i = 0; i < keys.length; i++) { 3493 var id = Number(keys[i]); 3494 if (incoming[id] > bestCount) { 3495 bestCount = incoming[id]; 3496 bestId = id; 3497 } 3498 } 3499 return bestCount > 0 ? bestId : (stored || null); 3500 }; 3501 this.liveDiagnosticityDeltaPrc = function (signalNodeId) { 3502 var net = _this.authorBayesNet; 3503 var primaryId = _this.resolvePrimaryNodeId(); 3504 var swingFn = net && typeof net.expectedObservationSwingPrc === 'function' 3505 ? net.expectedObservationSwingPrc 3506 : net && typeof net.maxObservationSwingPrc === 'function' 3507 ? net.maxObservationSwingPrc 3508 : null; 3509 if (!net || !primaryId || !signalNodeId || !swingFn) { 3510 return null; 3511 } 3512 var swing = swingFn(signalNodeId, primaryId); 3513 return swing != null && isFinite(Number(swing)) ? Number(swing) : null; 3514 }; 3515 this.diagnosticityInfoHtml = function (node) { 3516 var live = _this.liveDiagnosticityDeltaPrc(node && node.nodeId); 3517 var delta = live != null 3518 ? _this.formatPercentagePoints(live) 3519 : node && node.diagnosticityDeltaPrc != null 3520 ? _this.formatPercentagePoints(node.diagnosticityDeltaPrc) 3521 : 'an unknown amount'; 3522 return _this.wrapInfoHtml('How much is the forecast on the primary question expected to move when this node resolves?' + 3523 '<br><br>Learning this node\'s outcome is expected to move a probability on that question by <span style="font-family:Inter,sans-serif;font-weight:600;color:#3B82F6;">' + 3524 delta + 3525 '</span>. Unlikely states only count in proportion to how likely they are.'); 3526 }; 3527 this.timelinessInfoHtml = function (node) { 3528 var intro = 'How far in advance will we know the outcome to this question? The further in advance we get a signal from your node, the better!'; 3529 var days = node ? _this.formatLeadDays(node.leadDays) : null; 3530 var resolutionDate = node && node.resolutionDate ? String(node.resolutionDate) : ''; 3531 var todayUtc = new Date().toISOString().slice(0, 10); 3532 if (resolutionDate && resolutionDate <= todayUtc) { 3533 return _this.wrapInfoHtml(intro + 3534 '<br><br>This node resolved on <span style="font-family:Inter,sans-serif;font-weight:600;color:#3B82F6;">' + 3535 resolutionDate + 3536 '</span>, so it no longer scores for timeliness.'); 3537 } 3538 if (days == null) { 3539 if (resolutionDate) { 3540 return _this.wrapInfoHtml(intro + 3541 '<br><br>This node is set to resolve on <span style="font-family:Inter,sans-serif;font-weight:600;color:#3B82F6;">' + 3542 resolutionDate + 3543 '</span>.'); 3544 } 3545 return _this.wrapInfoHtml(intro + '<br><br>We could not read a resolution date for this node, so timeliness could not be scored.'); 3546 } 3547 if (node.leadDays <= 0) { 3548 return _this.wrapInfoHtml(intro + 3549 '<br><br>This node is set to resolve on or after the primary question, so it does not provide an early signal.'); 3550 } 3551 return _this.wrapInfoHtml(intro + 3552 '<br><br>We\'ll know this node\'s outcome <span style="font-family:Inter,sans-serif;font-weight:600;color:#3B82F6;">' + 3553 days + 3554 '</span> before the primary question resolves.'); 3555 }; 3556 this.showDiagnosticityInfo = function (row, event) { 3557 Distiller.showInfo(_this.diagnosticityInfoHtml(row && row.metric), event); 3558 }; 3559 this.showTimelinessInfo = function (row, event) { 3560 Distiller.showInfo(_this.timelinessInfoHtml(row && row.metric), event); 3561 }; 3562 this.showAddedSignalExplainer = function (row, event) { 3563 if (event) { 3564 event.preventDefault(); 3565 event.stopPropagation(); 3566 } 3567 Distiller.visibleInfo(null); 3568 _this.addedSignalExplainerRow(row || null); 3569 _this.addedSignalExplainerOpen(true); 3570 }; 3571 this.closeAddedSignalExplainer = function () { 3572 _this.addedSignalExplainerOpen(false); 3573 _this.addedSignalExplainerRow(null); 3574 }; 3575 this.resolveCanvasNodeId = function (nodeId, title) { 3576 var net = _this.authorBayesNet; 3577 var parsed = nodeId != null ? parseInt(String(nodeId), 10) : NaN; 3578 if (net && typeof net.resolveLiveNodeId === 'function' && Number.isFinite(parsed)) { 3579 var live = net.resolveLiveNodeId(parsed); 3580 if (live) { 3581 return live; 3582 } 3583 } 3584 var nodes = net && net.nodes ? net.nodes : []; 3585 if (Number.isFinite(parsed) && nodes.some(function (n) { return Number(n.id) === parsed; })) { 3586 return parsed; 3587 } 3588 var needle = String(title || '').trim().toLowerCase(); 3589 if (needle) { 3590 for (var i = 0; i < nodes.length; i++) { 3591 if (String(nodes[i].title || '').trim().toLowerCase() === needle) { 3592 return Number(nodes[i].id); 3593 } 3594 } 3595 } 3596 return Number.isFinite(parsed) ? parsed : null; 3597 }; 3598 this.canvasSelectionMatchesRow = function (liveId, node) { 3599 if (liveId == null || !node) { 3600 return false;
3601 } 3602 var resolved = _this.resolveCanvasNodeId(node.nodeId, node.title); 3603 return resolved != null && Number(resolved) === Number(liveId); 3604 }; 3605 this.scheduleLeaderboardScrollToSelection = function () { 3606 if (_this.selectedCanvasNodeId() == null && _this.pinnedLeaderboardNodeId() == null) { 3607 return; 3608 } 3609 var run = function () { 3610 _this.leaderboardScrollFrame = null; 3611 _this.scrollLeaderboardToSelectedRow(); 3612 }; 3613 if (typeof requestAnimationFrame === 'function') { 3614 if (_this.leaderboardScrollFrame != null) { 3615 cancelAnimationFrame(_this.leaderboardScrollFrame); 3616 } 3617 _this.leaderboardScrollFrame = requestAnimationFrame(function () { 3618 _this.leaderboardScrollFrame = requestAnimationFrame(run); 3619 }); 3620 return; 3621 } 3622 setTimeout(run, 0); 3623 }; 3624 this.scrollLeaderboardToSelectedRow = function () { 3625 var root = typeof document === 'undefined' ? null : document.querySelector('.bayesBotRoot'); 3626 var scroller = root && root.querySelector('.bayesBotLeaderboardScroll'); 3627 var row = scroller && scroller.querySelector('tr.is-canvas-selected'); 3628 if (!scroller || !row) { 3629 return; 3630 } 3631 var scrollerRect = scroller.getBoundingClientRect(); 3632 var rowRect = row.getBoundingClientRect(); 3633 var rowCenter = rowRect.top - scrollerRect.top + scroller.scrollTop + rowRect.height / 2; 3634 var maxScroll = Math.max(0, scroller.scrollHeight - scroller.clientHeight); 3635 var nextTop = Math.max(0, Math.min(maxScroll, rowCenter - scroller.clientHeight / 2)); 3636 if (Math.abs(nextTop - scroller.scrollTop) < 2) { 3637 return; 3638 } 3639 if (typeof scroller.scrollTo === 'function') { 3640 scroller.scrollTo({ top: nextTop, behavior: 'smooth' }); 3641 } 3642 else { 3643 scroller.scrollTop = nextTop; 3644 } 3645 }; 3646 this.applyPinnedPathFocus = function () { 3647 var net = _this.authorBayesNet; 3648 if (!net || typeof net.setPathFocusNodeId !== 'function') { 3649 return; 3650 } 3651 net.setPathFocusNodeId(_this.pinnedLeaderboardNodeId()); 3652 }; 3653 this.hoverLeaderboardRow = function (row) { 3654 var net = _this.authorBayesNet; 3655 if (!net || typeof net.setPathFocusNodeId !== 'function') { 3656 return; 3657 } 3658 var liveId = _this.resolveCanvasNodeId(row && row.nodeId, row && row.title); 3659 net.setPathFocusNodeId(liveId); 3660 }; 3661 this.clearLeaderboardHover = function () { 3662 if (_this.pinnedLeaderboardNodeId() != null) { 3663 _this.applyPinnedPathFocus(); 3664 return; 3665 } 3666 var net = _this.authorBayesNet; 3667 if (!net || typeof net.setPathFocusNodeId !== 'function') { 3668 return; 3669 } 3670 net.setPathFocusNodeId(null); 3671 }; 3672 this.closeLeaderboardScorePanel = function () { 3673 _this.pinnedLeaderboardNodeId(null); 3674 _this.applyPinnedPathFocus(); 3675 Distiller.visibleInfo(null); 3676 var modal = Distiller.modalInView && Distiller.modalInView(); 3677 if (modal && 3678 (modal.name === 'bayes-bot-node-score-modal' || modal.name === 'bayes-bot-timepoint-modal')) { 3679 Distiller.modalInView(null); 3680 } 3681 }; 3682 this.showLifetimeTimepointModal = function (breakpoint, event) { 3683 if (!breakpoint) { 3684 return; 3685 } 3686 Distiller.visibleInfo(null); 3687 var params = { 3688 breakpoint: breakpoint, 3689 dateLabel: _this.formatUtcLongDate(breakpoint.timeMs), 3690 percentLabel: Math.round(Number(breakpoint.normalizedInformation || 0) * 100) + '%', 3691 resolvingNames: Array.isArray(breakpoint.resolvingNodeNames) 3692 ? breakpoint.resolvingNodeNames.slice() 3693 : [], 3694 isPrimaryResolution: !!breakpoint.isPrimaryResolution, 3695 isStart: !!breakpoint.isStart, 3696 entropyRemainingLabel: breakpoint.expectedEntropyBits != null 3697 ? Number(breakpoint.expectedEntropyBits).toFixed(2) + ' bits' 3698 : 'â', 3699 informationAvailableLabel: breakpoint.informationBits != null 3700 ? Number(breakpoint.informationBits).toFixed(2) + ' bits' 3701 : 'â', 3702 anchorX: event && typeof event.clientX === 'number' ? event.clientX : 80, 3703 anchorY: event && typeof event.clientY === 'number' ? event.clientY : 80, 3704 }; 3705 var open = function () { 3706 Distiller.modalInView({ 3707 name: 'bayes-bot-timepoint-modal', 3708 params: params, 3709 }); 3710 }; 3711 if (Distiller.modalInView()) { 3712 Distiller.modalInView(null); 3713 setTimeout(open, 0); 3714 return; 3715 } 3716 open(); 3717 }; 3718 this.showLeaderboardNodeModal = function (row, event) { 3719 if (event) { 3720 event.preventDefault(); 3721 event.stopPropagation(); 3722 } 3723 var liveId = _this.resolveCanvasNodeId(row && row.nodeId, row && row.title); 3724 if (_this.pinnedLeaderboardNodeId() != null && Number(_this.pinnedLeaderboardNodeId()) === Number(liveId)) { 3725 _this.closeLeaderboardScorePanel(); 3726 return; 3727 } 3728 _this.pinnedLeaderboardNodeId(liveId); 3729 _this.applyPinnedPathFocus(); 3730 Distiller.visibleInfo(null); 3731 Distiller.modalInView({ 3732 name: 'bayes-bot-node-score-modal', 3733 params: { 3734 row: row, 3735 anchorX: event && typeof event.clientX === 'number' ? event.clientX : 80, 3736 anchorY: event && typeof event.clientY === 'number' ? event.clientY : 80, 3737 diagnosticityInfoHtml: _this.diagnosticityInfoHtml, 3738 timelinessInfoHtml: _this.timelinessInfoHtml, 3739 onClose: function () { 3740 _this.pinnedLeaderboardNodeId(null); 3741 _this.applyPinnedPathFocus(); 3742 }, 3743 }, 3744 }); 3745 }; 3746 this.workbenchGridColumns = ko.pureComputed(function () { 3747 var share = Math.max(0.18, Math.min(0.82, _this.proposeShare())); 3748 return 'minmax(160px, ' + share + 'fr) 20px minmax(160px, ' + (1 - share) + 'fr)'; 3749 }); 3750 this.workbenchHeightStyle = ko.pureComputed(function () { return _this.workbenchHeightPx() + 'px'; }); 3751 this.workbenchColDrag = null; 3752 this.workbenchRowDrag = null; 3753 this.clampWorkbenchHeight = function (height) { 3754 var minH = 100; 3755 var maxH = Math.max(minH, Math.min(640, Math.round(window.innerHeight * 0.7))); 3756 return Math.max(minH, Math.min(maxH, Math.round(height))); 3757 }; 3758 this.startWorkbenchColResize = function (_data, event) { 3759 var target = event.currentTarget; 3760 var row = target && target.parentElement; 3761 if (!row) { 3762 return true; 3763 } 3764 event.preventDefault(); 3765 event.stopPropagation(); 3766 var usable = Math.max(1, row.clientWidth - 20); 3767 _this.workbenchColDrag = { 3768 pointerId: event.pointerId, 3769 startX: event.clientX, 3770 startShare: _this.proposeShare(), 3771 usableWidth: usable, 3772 }; 3773 _this.workbenchRowDrag = null; 3774 if (target.setPointerCapture) { 3775 target.setPointerCapture(event.pointerId); 3776 } 3777 document.body.classList.add('bayesBotWorkbenchResizing'); 3778 document.body.classList.add('bayesBotWorkbenchResizingCol'); 3779 return false;
3780 }; 3781 this.startWorkbenchRowResize = function (_data, event) { 3782 var target = event.currentTarget; 3783 event.preventDefault(); 3784 event.stopPropagation(); 3785 _this.workbenchRowDrag = { 3786 pointerId: event.pointerId, 3787 startY: event.clientY, 3788 startHeight: _this.workbenchHeightPx(), 3789 }; 3790 _this.workbenchColDrag = null; 3791 if (target.setPointerCapture) { 3792 target.setPointerCapture(event.pointerId); 3793 } 3794 document.body.classList.add('bayesBotWorkbenchResizing'); 3795 document.body.classList.add('bayesBotWorkbenchResizingRow'); 3796 return false; 3797 }; 3798 this.onWorkbenchResizeMove = function (_data, event) { 3799 if (_this.workbenchColDrag && event.pointerId === _this.workbenchColDrag.pointerId) { 3800 var minPx = 160; 3801 var maxPx = Math.max(minPx, _this.workbenchColDrag.usableWidth - minPx); 3802 var startPx = _this.workbenchColDrag.startShare * _this.workbenchColDrag.usableWidth; 3803 var nextPx = Math.max(minPx, Math.min(maxPx, startPx + (event.clientX - _this.workbenchColDrag.startX))); 3804 _this.proposeShare(nextPx / _this.workbenchColDrag.usableWidth); 3805 } 3806 if (_this.workbenchRowDrag && event.pointerId === _this.workbenchRowDrag.pointerId) { 3807 _this.workbenchHeightPx(_this.clampWorkbenchHeight(_this.workbenchRowDrag.startHeight + (event.clientY - _this.workbenchRowDrag.startY))); 3808 } 3809 return true; 3810 }; 3811 this.endWorkbenchResize = function (_data, event) { 3812 if (event && _this.workbenchColDrag && event.pointerId !== _this.workbenchColDrag.pointerId) { 3813 return true; 3814 } 3815 if (event && _this.workbenchRowDrag && event.pointerId !== _this.workbenchRowDrag.pointerId) { 3816 return true; 3817 } 3818 _this.workbenchColDrag = null; 3819 _this.workbenchRowDrag = null; 3820 document.body.classList.remove('bayesBotWorkbenchResizing'); 3821 document.body.classList.remove('bayesBotWorkbenchResizingCol'); 3822 document.body.classList.remove('bayesBotWorkbenchResizingRow'); 3823 return true; 3824 }; 3825 this.pollBayesBotJobUntilDone = function (jobId) { 3826 _this.clearBayesBotJobPoll(); 3827 var tick = function () { 3828 if (_this.proposalPhase() !== 'processing' || _this.lastBayesBotJobId() !== jobId) { 3829 return; 3830 } 3831 var currentUser = Distiller.currentUser && Distiller.currentUser(); 3832 var userId = currentUser && currentUser.userId; 3833 if (!userId) { 3834 return; 3835 } 3836 Distiller.httpGetAsync(Distiller.apiEndpoint + '/api/bayesBotJob/' + userId + '/' + jobId, function (responseText) { 3837 if (_this.proposalPhase() !== 'processing' || _this.lastBayesBotJobId() !== jobId) { 3838 return; 3839 } 3840 try { 3841 var parsed = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 3842 if (!parsed || parsed.ok === false) { 3843 _this.bayesBotPollTimer = setTimeout(tick, 5000); 3844 return; 3845 } 3846 var terminal = parsed.status === 'complete' || 3847 parsed.status === 'error' || 3848 parsed.status === 'partial'; 3849 if (terminal) { 3850 _this.onBayesBotCompleteEvent({ 3851 data: JSON.stringify({ 3852 jobId: parsed.jobId || jobId, 3853 status: parsed.status, 3854 message: parsed.status === 'error' 3855 ? 'Something went wrong' 3856 : parsed.status === 'partial' 3857 ? 'Finished with some issues' 3858 : 'Done', 3859 responseText: _this.collectFinalResponseFromJob(parsed), 3860 error: parsed.error, 3861 warnings: parsed.results && Array.isArray(parsed.results.warnings) 3862 ? parsed.results.warnings 3863 : [], 3864 specNotes: parsed.results && Array.isArray(parsed.results.specNotes) 3865 ? parsed.results.specNotes 3866 : parsed.results && Array.isArray(parsed.results.warnings) 3867 ? parsed.results.warnings 3868 : [], 3869 draftStatus: parsed.results && parsed.results.draftStatus 3870 ? parsed.results.draftStatus 3871 : null, 3872 primaryNodeId: parsed.results && parsed.results.primaryNodeId != null 3873 ? parsed.results.primaryNodeId 3874 : null, 3875 infoValue: parsed.results && parsed.results.infoValue 3876 ? parsed.results.infoValue 3877 : null, 3878 lifetimeInformation: parsed.results && parsed.results.lifetimeInformation 3879 ? parsed.results.lifetimeInformation 3880 : null, 3881 copyNetId: parsed.copyNetId || null, 3882 setId: parsed.setId || null, 3883 templateNetId: parsed.templateNetId || null, 3884 }), 3885 }); 3886 return; 3887 } 3888 } 3889 catch (e) { 3890 /* keep polling */ 3891 } 3892 _this.bayesBotPollTimer = setTimeout(tick, 5000); 3893 }); 3894 }; 3895 _this.bayesBotPollTimer = setTimeout(tick, 8000); 3896 }; 3897 this.attachBayesBotSseListeners = function (es) { 3898 es.addEventListener('bayesBotStatus', _this.onBayesBotStatusEvent); 3899 es.addEventListener('bayesBotNodeCreated', _this.onBayesBotNodeCreatedEvent); 3900 es.addEventListener('bayesBotNodeDeleted', _this.onBayesBotNodeDeletedEvent); 3901 es.addEventListener('bayesBotConnectionAdded', _this.onBayesBotConnectionAddedEvent); 3902 es.addEventListener('bayesBotConnectionRemoved', _this.onBayesBotConnectionRemovedEvent); 3903 es.addEventListener('bayesBotPriorForecast', _this.onBayesBotPriorForecastEvent); 3904 es.addEventListener('bayesBotConditionalForecast', _this.onBayesBotConditionalForecastEvent); 3905 es.addEventListener('bayesBotComplete', _this.onBayesBotCompleteEvent); 3906 es.addEventListener('bayesBotHeader', _this.onBayesBotHeaderEvent); 3907 es.addEventListener('bayesBotStudyReady', _this.onBayesBotStudyReadyEvent); 3908 es.addEventListener('bayesBotCloneReady', _this.onBayesBotCloneReadyEvent); 3909 es.addEventListener('bayesBotLeaderboard', _this.onBayesBotLeaderboardEvent); 3910 es.addEventListener('bayesBotLifetimeInformation', _this.onBayesBotLifetimeInformationEvent); 3911 es.addEventListener('bayesBotAgentActivity', _this.onBayesBotAgentActivityEvent); 3912 es.addEventListener('bayesBotAuthRequired', _this.onBayesBotAuthRequiredEvent); 3913 es.addEventListener('bayesBotBranchMerged', _this.onBayesBotBranchMergedEvent); 3914 es.addEventListener('bayesBotMergeStatus', _this.onBayesBotMergeStatusEvent); 3915 es.onerror = function () { 3916 if (es.readyState !== EventSource.CLOSED) { 3917 return; 3918 } 3919 try { 3920 es.close(); 3921 } 3922 catch (e) { 3923 /* ignore */ 3924 } 3925 if (_this.bayesBotEventSource === es) { 3926 _this.bayesBotEventSource = null; 3927 } 3928 if (_this.bayesBotSseReconnectTimer) { 3929 return; 3930 } 3931 _this.bayesBotSseReconnectTimer = setTimeout(function () { 3932 _this.bayesBotSseReconnectTimer = null; 3933 _this.connectBayesBotSse(); 3934 }, 2500); 3935 }; 3936 }; 3937 this.onBayesBotHeaderEvent = function (event) { 3938 var data = _this.parseBayesBotSseData(event); 3939 if (!_this.isCurrentBayesBotJob(data) || !data) { 3940 return; 3941 } 3942 var markup = data.headerMarkup != null ? String(data.headerMarkup) : ''; 3943 if (!markup) { 3944 return; 3945 } 3946 var criteria = data.resolutionCriteria != null ? String(data.resolutionCriteria) : ''; 3947 if (data.questionText && !isLegacyHormuzPlaceholder(data.questionText)) { 3948 _this.boundQuestionText(String(data.questionText)); 3949 } 3950 if (criteria && !isLegacyHormuzPlaceholder(criteria)) { 3951 _this.boundResolutionCriteria(criteria); 3952 } 3953 if (data.resolutionDate) { 3954 _this.boundResolutionDate(bayesBotIsoDate(data.resolutionDate) || _this.boundResolutionDate()); 3955 } 3956 var infoHtml = criteria 3957 ? bayesBotHeaderInfoHtml('Resolves Yes', criteria) 3958 : _this.headerInfoHtml(); 3959 _this.animateHeaderMarkup(markup, infoHtml); 3960 }; 3961 this.onBayesBotStudyReadyEvent = function (event) { 3962 var data = _this.parseBayesBotSseData(event); 3963 if (!_this.isCurrentBayesBotJob(data) || !data) { 3964 return; 3965 } 3966 _this.ensureCreateCanvasMounted(data); 3967 }; 3968 this.onBayesBotLeaderboardEvent = function (event) { 3969 var data = _this.parseBayesBotSseData(event); 3970 if (!data) { 3971 return; 3972 } 3973 var fromMerge = data.reason === 'merge'; 3974 if (!fromMerge && !_this.isCurrentBayesBotJob(data) && !_this.agentActivityLive()) { 3975 return; 3976 } 3977 if (data.scoresStatus) { 3978 _this.scoresStatus(String(data.scoresStatus)); 3979 } 3980 else if (fromMerge) { 3981 _this.scoresStatus(''); 3982 } 3983 _this.leaderboardPrimaryNodeId(data.primaryNodeId || null); 3984 _this.applyLeaderboardNodes(data.nodes || [], data.rankOf); 3985 _this.applyPrimaryNodeHighlight(); 3986 }; 3987 this.onBayesBotLifetimeInformationEvent = function (event) { 3988 var data = _this.parseBayesBotSseData(event); 3989 if (!data) { 3990 return; 3991 } 3992 var lifetime = data.lifetimeInformation || null; 3993 if (!lifetime) { 3994 return; 3995 } 3996 if (data.netId != null) { 3997 var incoming = parseInt(String(data.netId), 10); 3998 var onScreen = _this.lifetimeScoreNetIdOnScreen(); 3999 if (Number.isFinite(incoming) && 4000 incoming > 0 && 4001 onScreen != null && 4002 incoming !== onScreen) { 4003 return; 4004 } 4005 } 4006 _this.presentPersistedLifetimeInformation(lifetime); 4007 }; 4008 this.connectBayesBotSse = function () { 4009 var currentUser = Distiller.currentUser && Distiller.currentUser(); 4010 var userId = currentUser && currentUser.userId; 4011 if (!userId) { 4012 return; 4013 } 4014 if (_this.bayesBotEventSource && _this.bayesBotSseUserId === userId) { 4015 return; 4016 } 4017 if (_this.bayesBotEventSource) { 4018 try { 4019 _this.bayesBotEventSource.close(); 4020 } 4021 catch (e) { 4022 /* ignore */ 4023 } 4024 _this.bayesBotEventSource = null; 4025 } 4026 _this.bayesBotSseUserId = userId; 4027 var requestedUserId = userId; 4028 fetch(Distiller.apiEndpoint + '/api/get-bayes-bot-sse-token/' + userId, { 4029 method: 'GET', 4030 headers: { 'Content-Type': 'application/json' }, 4031 credentials: 'same-origin', 4032 }) 4033 .then(function (response) { 4034 if (!response.ok) { 4035 throw new Error('HTTP error! status: ' + response.status); 4036 } 4037 return response.json(); 4038 }) 4039 .then(function (data) { 4040 var current = Distiller.currentUser && Distiller.currentUser(); 4041 if (!current || current.userId !== requestedUserId) { 4042 return; 4043 } 4044 if (_this.bayesBotEventSource) { 4045 return; 4046 } 4047 var token = data && data.token; 4048 if (!token) { 4049 throw new Error('missing SSE token'); 4050 } 4051 var es = new EventSource(Distiller.apiEndpoint + '/api/events?token='
4051+ token); 4052 _this.bayesBotEventSource = es; 4053 _this.attachBayesBotSseListeners(es); 4054 }) 4055 .catch(function (error) { 4056 console.error('Error establishing BayesBot SSE connection:', error); 4057 if (!_this.bayesBotSseReconnectTimer) { 4058 _this.bayesBotSseReconnectTimer = setTimeout(function () { 4059 _this.bayesBotSseReconnectTimer = null; 4060 _this.connectBayesBotSse(); 4061 }, 4000); 4062 } 4063 }); 4064 }; 4065 this.remountAuthorBayesNet = function () { 4066 _this.authorBayesNet = null; 4067 _this.pendingBayesBotGraphEvents = []; 4068 _this.authorBayesNetSet(null); 4069 _this.loadAuthorBayesNet(); 4070 _this.loadLeaderboard(); 4071 }; 4072 this.onBayesBotCloneReadyEvent = function (event) { 4073 if (_this.ownsCanonicalTemplate || _this.isTempVisitor()) { 4074 return; 4075 } 4076 var data = _this.parseBayesBotSseData(event); 4077 if (!data || !data.copyNetId) { 4078 return; 4079 } 4080 if (data.ownsCanonicalTemplate) { 4081 _this.ownsCanonicalTemplate = true; 4082 _this.authorOwnsTemplate(true); 4083 return; 4084 } 4085 _this.adoptPersonalCopyFromServer(data.copyNetId, data.setId); 4086 }; 4087 this.flushQueuedBayesBotGraphEvents = function () { 4088 var queued = _this.pendingBayesBotGraphEvents.slice(); 4089 _this.pendingBayesBotGraphEvents = []; 4090 for (var i = 0; i < queued.length; i++) { 4091 _this.applyBayesBotGraphEvent(queued[i]); 4092 } 4093 }; 4094 this.adoptPersonalCopyFromServer = function (copyNetIdRaw, setIdRaw) { return __awaiter(_this, void 0, void 0, function () { 4095 var copyNetId, currentUser, userId, setId, responseText, parsed, graph, nodes, e_4; 4096 return __generator(this, function (_a) { 4097 switch (_a.label) { 4098 case 0: 4099 copyNetId = parseInt(String(copyNetIdRaw), 10); 4100 if (!Number.isFinite(copyNetId) || copyNetId <= 0) { 4101 return [2 /*return*/, false]; 4102 } 4103 currentUser = Distiller.currentUser && Distiller.currentUser(); 4104 userId = currentUser && currentUser.userId; 4105 setId = setIdRaw != null 4106 ? setIdRaw 4107 : (this.authorBayesNetSet() && this.authorBayesNetSet().setId 4108 ? this.authorBayesNetSet().setId() 4109 : null); 4110 if (!userId || !setId) { 4111 this.personalCopyNetId = copyNetId; 4112 return [2 /*return*/, false]; 4113 } 4114 _a.label = 1; 4115 case 1: 4116 _a.trys.push([1, 3, , 4]); 4117 return [4 /*yield*/, new Promise(function (resolve) { 4118 Distiller.httpGetAsync(Distiller.apiEndpoint + '/api/bayesNets/' + userId + '/' + setId + '/' + copyNetId, resolve); 4119 })]; 4120 case 2: 4121 responseText = _a.sent(); 4122 parsed = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 4123 graph = parsed && parsed.bayesNet ? parsed.bayesNet : null; 4124 nodes = graph && graph.nodes ? graph.nodes : []; 4125 this.personalCopyNetId = copyNetId; 4126 this.viewingSharedTemplate = false; 4127 this.cloneReady = true; 4128 this.liveTemplateBuild = false; 4129 if (this.authorBayesNet && graph && typeof this.authorBayesNet.load === 'function') { 4130 this.authorBayesNet.netId = copyNetId; 4131 this.authorBayesNet.load(graph); 4132 if (this.authorBayesNet.primaryNodeId) { 4133 this.leaderboardPrimaryNodeId(this.authorBayesNet.primaryNodeId); 4134 } 4135 this.applyPrimaryNodeHighlight(); 4136 } 4137 else if (this.authorBayesNet && typeof this.authorBayesNet.adoptCopiedNodeIds === 'function') { 4138 this.applyPrimaryNodeHighlight(); 4139 this.authorBayesNet.adoptCopiedNodeIds(nodes, copyNetId); 4140 if (this.authorBayesNet.primaryNodeId) { 4141 this.leaderboardPrimaryNodeId(this.authorBayesNet.primaryNodeId); 4142 } 4143 this.applyPrimaryNodeHighlight(); 4144 } 4145 this.flushQueuedBayesBotGraphEvents(); 4146 this.loadLeaderboard(); 4147 return [2 /*return*/, true]; 4148 case 3: 4149 e_4 = _a.sent(); 4150 console.error('BayesBot adopt personal copy failed:', e_4); 4151 this.personalCopyNetId = copyNetId; 4152 return [2 /*return*/, false]; 4153 case 4: return [2 /*return*/]; 4154 } 4155 }); 4156 }); }; 4157 this.ensurePersonalCopy = function (opts) { 4158 if (_this.isTempVisitor()) { 4159 var templateNetId = _this.sharedTemplateNetId(); 4160 return Promise.resolve(templateNetId || 0); 4161 } 4162 if (_this.ownsCanonicalTemplate) { 4163 var templateNetId = _this.sharedTemplateNetId(); 4164 if (templateNetId) { 4165 return Promise.resolve(templateNetId); 4166 } 4167 } 4168 if (_this.cloneReady && _this.personalCopyNetId && !_this.viewingSharedTemplate) { 4169 return Promise.resolve(_this.personalCopyNetId); 4170 } 4171 if (_this.clonePromise) { 4172 if (!opts || !opts.silent) { 4173 _this.preparingCloneForEdits = true; 4174 _this.setProposalStatusText('Preparing clone for editingâ¦'); 4175 } 4176 return _this.clonePromise; 4177 } 4178 var showPreparing = !opts || !opts.silent; 4179 if (showPreparing && !_this.cloneReady) { 4180 _this.preparingCloneForEdits = true; 4181 _this.setProposalStatusText('Preparing clone for editingâ¦'); 4182 } 4183 _this.clonePromise = (function () { return __awaiter(_this, void 0, void 0, function () { 4184 var currentUser, userId, responseText, parsed, templateNetId; 4185 return __generator(this, function (_a) { 4186 switch (_a.label) { 4187 case 0: 4188 currentUser = Distiller.currentUser && Distiller.currentUser(); 4189 userId = currentUser && currentUser.userId; 4190 if (!userId) { 4191 throw new Error('missing current user'); 4192 } 4193 if (!(this.personalCopyNetId && this.authorBayesNet && !this.viewingSharedTemplate)) return [3 /*break*/, 2]; 4194 return [4 /*yield*/, this.adoptPersonalCopyFromServer(this.personalCopyNetId, this.authorBayesNetSet() && this.authorBayesNetSet().setId 4195 ? this.authorBayesNetSet().setId() 4196 : null)]; 4197 case 1: 4198 _a.sent(); 4199 if (this.cloneReady && !this.viewingSharedTemplate) { 4200 return [2 /*return*/, this.personalCopyNetId]; 4201 } 4202 _a.label = 2; 4203 case 2: return [4 /*yield*/, Distiller.httpPostJsonAsync(Distiller.apiEndpoint + '/api/bayesBotEnsureCopy/' + userId, { communityId: this.resolveBoundCommunityId() })]; 4204 case 3: 4205 responseText = _a.sent(); 4206 parsed = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 4207 if (parsed && parsed.ownsCanonicalTemplate) { 4208 this.ownsCanonicalTemplate = true; 4209 this.authorOwnsTemplate(true); 4210 if (parsed.templateNetId != null) { 4211 templateNetId = parseInt(String(parsed.templateNetId), 10); 4212 if (Number.isFinite(templateNetId) && templateNetId > 0) { 4213 this.sharedTemplateNetId(templateNetId); 4214 } 4215 } 4216 return [2 /*return*/, this.sharedTemplateNetId() || parseInt(String(parsed.copyNetId), 10)]; 4217 } 4218 if (!parsed || parsed.ok === false || !parsed.copyNetId) { 4219 throw new Error((parsed && parsed.error) || 'failed to prepare clone'); 4220 } 4221 return [4 /*yield*/, this.adoptPersonalCopyFromServer(parsed.copyNetId, parsed.setId)]; 4222 case 4: 4223 _a.sent(); 4224 return [2 /*return*/, parseInt(String(parsed.copyNetId), 10)]; 4225 } 4226 }); 4227 }); })(); 4228 return _this.clonePromise.then(function (copyNetId) { 4229 _this.preparingCloneForEdits = false;
4230 _this.clonePromise = null; 4231 return copyNetId; 4232 }, function (err) { 4233 _this.preparingCloneForEdits = false; 4234 _this.clonePromise = null; 4235 throw err; 4236 }); 4237 }; 4238 this.clearNetForDev = function () { return __awaiter(_this, void 0, void 0, function () { 4239 var currentUser, userId, confirmed, responseText, parsed, e_5; 4240 return __generator(this, function (_a) { 4241 switch (_a.label) { 4242 case 0: 4243 if (!this.showClearNetDevButton || this.clearingNet()) { 4244 return [2 /*return*/]; 4245 } 4246 currentUser = Distiller.currentUser && Distiller.currentUser(); 4247 userId = currentUser && currentUser.userId; 4248 if (!userId) { 4249 console.error('BayesBot clear net: missing current user'); 4250 return [2 /*return*/]; 4251 } 4252 confirmed = window.confirm('Clear the shared net down to the primary node and rebuild your copy? Local development only.'); 4253 if (!confirmed) { 4254 return [2 /*return*/]; 4255 } 4256 this.clearingNet(true); 4257 _a.label = 1; 4258 case 1: 4259 _a.trys.push([1, 3, 4, 5]); 4260 return [4 /*yield*/, Distiller.httpPostJsonAsync(Distiller.apiEndpoint + '/api/bayesBotClearNet/' + userId, { communityId: this.resolveBoundCommunityId() })]; 4261 case 2: 4262 responseText = _a.sent(); 4263 parsed = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 4264 if (!parsed || parsed.ok === false) { 4265 console.error('BayesBot clear net failed:', parsed); 4266 window.alert((parsed && parsed.error) || 'Failed to clear net'); 4267 return [2 /*return*/]; 4268 } 4269 this.dismissProposalResult(); 4270 this.leaderboardNodes([]); 4271 this.leaderboardRankOf(0); 4272 this.leaderboardPrimaryNodeId(parsed.primaryNodeId || null); 4273 this.remountAuthorBayesNet(); 4274 return [3 /*break*/, 5]; 4275 case 3: 4276 e_5 = _a.sent(); 4277 console.error('BayesBot clear net failed:', e_5); 4278 window.alert('Failed to clear net'); 4279 return [3 /*break*/, 5]; 4280 case 4: 4281 this.clearingNet(false); 4282 return [7 /*endfinally*/]; 4283 case 5: return [2 /*return*/]; 4284 } 4285 }); 4286 }); }; 4287 /** 4288 * Load the shared template Bayes set for the bound (or current) BayesBot study. 4289 */ 4290 this.reloadAuthorBayesNetGraph = function () { 4291 var set = _this.authorBayesNetSet(); 4292 var net = _this.authorBayesNet; 4293 var userId = _this.viewerUserId 4294 || (Distiller.currentUser && Distiller.currentUser() && Distiller.currentUser().userId); 4295 if (!set || !net || !userId || typeof net.load !== 'function') { 4296 return _this.loadAuthorBayesNet(); 4297 } 4298 var setId = set.setId && set.setId(); 4299 if (!setId) { 4300 return _this.loadAuthorBayesNet(); 4301 } 4302 if (!_this.viewingSharedTemplate && _this.personalCopyNetId) { 4303 var copyNetId_1 = _this.personalCopyNetId; 4304 return new Promise(function (resolve) { 4305 Distiller.httpGetAsync(Distiller.apiEndpoint + '/api/bayesNets/' + userId + '/' + setId + '/' + copyNetId_1, function (responseText) { 4306 try { 4307 var parsed = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 4308 var graph = parsed && parsed.bayesNet; 4309 if (graph) { 4310 net.netId = copyNetId_1; 4311 net.load(graph); 4312 _this.flushQueuedBayesBotGraphEvents(); 4313 } 4314 } 4315 catch (e) { 4316 console.error('BayesBot reload copy graph failed:', e); 4317 } 4318 resolve(); 4319 }); 4320 }); 4321 } 4322 var query = ['viewSharedTemplate=1']; 4323 var templateNetId = _this.sharedTemplateNetId(); 4324 if (templateNetId) { 4325 query.push('templateNetId=' + encodeURIComponent(String(templateNetId))); 4326 } 4327 return new Promise(function (resolve) { 4328 Distiller.httpGetAsync(Distiller.apiEndpoint + '/api/bayesNets/' + userId + '/' + setId + '?' + query.join('&'), function (responseText) { 4329 try { 4330 var parsed = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 4331 var graph = parsed && parsed.bayesNets && parsed.bayesNets[0]; 4332 if (graph) { 4333 net.load(graph); 4334 _this.flushQueuedBayesBotGraphEvents(); 4335 } 4336 } 4337 catch (e) { 4338 console.error('BayesBot reload graph failed:', e); 4339 } 4340 resolve(); 4341 }); 4342 }); 4343 }; 4344 this.loadAuthorBayesNet = function () { 4345 var currentUser = Distiller.currentUser && Distiller.currentUser(); 4346 var userId = currentUser && currentUser.userId; 4347 if (!userId) { 4348 console.error('BayesBot loadAuthorBayesNet: missing current user'); 4349 _this.loadingSteps(false); 4350 return Promise.resolve(); 4351 } 4352 _this.viewerUserId = userId; 4353 var communityId = _this.resolveBoundCommunityId(); 4354 return new Promise(function (resolve) { 4355 Distiller.httpGetAsync(Distiller.apiEndpoint + '/api/getBayesBotModel/' + userId 4356 + '?communityId=' + encodeURIComponent(String(communityId)), function (responseText) { 4357 try { 4358 var response = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 4359 if (response && !response.err && response.data && response.data.setId) { 4360 _this.mountAuthorBayesNetFromModel(response.data); 4361 _this.applyPersistedBuildStatus(response.data.buildStatus); 4362 var lifetime = !_this.viewingSharedTemplate && response.data.copyLifetimeInformation 4363 ? response.data.copyLifetimeInformation 4364 : response.data.lifetimeInformation; 4365 var usable = lifetime && 4366 Array.isArray(lifetime.breakpoints) && 4367 lifetime.breakpoints.length 4368 ? lifetime 4369 : response.data.lifetimeInformation; 4370 if (usable) { 4371 _this.presentPersistedLifetimeInformation(usable); 4372 } 4373 } 4374 else { 4375 console.error('BayesBot loadAuthorBayesNet: unexpected response', responseText); 4376 } 4377 } 4378 catch (e) { 4379 console.error('BayesBot loadAuthorBayesNet failed:', e); 4380 } 4381 finally { 4382 _this.loadingSteps(false); 4383 resolve(); 4384 } 4385 }); 4386 }); 4387 }; 4388 this.toggleBayesBotModelMenu = function () { 4389 if (_this.requireSignedInForComposer()) { 4390 return; 4391 } 4392 var next = !_this.bayesBotModelMenuOpen(); 4393 _this.bayesBotModelMenuOpen(next); 4394 if (next) { 4395 _this.placeBayesBotModelMenu(); 4396 } 4397 }; 4398 this.placeBayesBotModelMenu = function () { 4399 if (!_this.bayesBotModelMenuOpen()) { 4400 return; 4401 } 4402 var trigger = document.querySelector('.bayesBotModelPickerButton'); 4403 var menu = document.querySelector('.bayesBotModelMenu'); 4404 if (!trigger || !menu) { 4405 return; 4406 } 4407 var rect = trigger.getBoundingClientRect(); 4408 menu.style.top = rect.top + 'px'; 4409 menu.style.left = rect.left + 'px'; 4410 menu.style.width = rect.width + 'px'; 4411 }; 4412 this.selectBayesBotModel = function (choice) { 4413 if (choice && choice.disabled) { 4414 return; 4415 } 4416 if (!choice || _this.requireSignedInForComposer()) { 4417 _this.bayesBotModelMenuOpen(false); 4418 return; 4419 } 4420 _this.bayesBotModelMenuOpen(false); 4421 if (choice.id === _this.selectedBayesBotModel()) { 4422 return; 4423 } 4424 _this.selectedBayesBotModel(choice.id); 4425 void _this.saveBayesBotUserModel(choice.id); 4426 }; 4427 this.loadBayesBotUserModel = function () { return __awaiter(_this, void 0, void 0, function () { 4428 var currentUser, userId, response, data_1, known, e_6; 4429 return __generator(this, function (_a) { 4430 switch (_a.label) { 4431 case 0: 4432 if (this.isTempVisitor()) { 4433 this.selectedBayesBotModel(BAYES_BOT_DEFAULT_MODEL); 4434 this.bayesBotModelMenuOpen(false); 4435 return [2 /*return*/]; 4436 } 4437 currentUser = Distiller.currentUser && Distiller.currentUser(); 4438 userId = currentUser && currentUser.userId; 4439 if (!userId) { 4440 return [2 /*return*/]; 4441 } 4442 _a.label = 1; 4443 case 1: 4444 _a.trys.push([1, 4, , 5]); 4445 return [4 /*yield*/, fetch(Distiller.apiEndpoint + '/api/bayesBotUserModel/' + userId, { credentials: 'same-origin' })]; 4446 case 2: 4447 response = _a.sent(); 4448 return [4 /*yield*/, response.json()]; 4449 case 3: 4450 data_1 = _a.sent(); 4451 if (!response.ok || !data_1 || data_1.ok === false || !data_1.model) { 4452 return [2 /*return*/]; 4453 } 4454 known = this.bayesBotModelChoices.some(function (choice) { return choice.id === data_1.model && !choice.disabled; }); 4455 if (known) { 4456 this.selectedBayesBotModel(data_1.model); 4457 } 4458 return [3 /*break*/, 5]; 4459 case 4: 4460 e_6 = _a.sent(); 4461 console.error('BayesBot model preference load failed', e_6); 4462 return [3 /*break*/, 5]; 4463 case 5: return [2 /*return*/]; 4464 } 4465 }); 4466 }); }; 4467 this.saveBayesBotUserModel = function (model) { return __awaiter(_this, void 0, void 0, function () { 4468 var currentUser, userId, e_7; 4469 return __generator(this, function (_a) { 4470 switch (_a.label) { 4471 case 0: 4472 currentUser = Distiller.currentUser && Distiller.currentUser(); 4473 userId = currentUser && currentUser.userId; 4474 if (!userId) { 4475 return [2 /*return*/]; 4476 } 4477 _a.label = 1; 4478 case 1: 4479 _a.trys.push([1, 3, , 4]); 4480 return [4 /*yield*/, Distiller.httpPostJsonAsync(Distiller.apiEndpoint + '/api/bayesBotUserModel/' + userId, { model: model })]; 4481 case 2: 4482 _a.sent(); 4483 return [3 /*break*/, 4]; 4484 case 3: 4485 e_7 = _a.sent(); 4486 console.error('BayesBot model preference save failed', e_7); 4487 return [3 /*break*/, 4]; 4488 case 4: return [2 /*return*/]; 4489 } 4490 }); 4491 }); }; 4492 this.submitComposer = function () { 4493 if (_this.requireSignedInForComposer()) { 4494 return; 4495 } 4496 if (_this.isCreateMode()) { 4497 _this.submitNetProposal(); 4498 return; 4499 } 4500 _this.submitNodeProposal(); 4501 }; 4502 this.requireSignedInForComposer = function () { 4503 if (!_this.isTempVisitor()) { 4504 return false;
4505 } 4506 _this.openAuthModal(_this.isCreateMode() ? 'create' : 'propose'); 4507 return true; 4508 }; 4509 this.openAuthModal = function (context) { 4510 _this.authModalContext(context || 'header'); 4511 if (_this.authModalMode() !== 'signin') { 4512 _this.authModalMode('signup'); 4513 } 4514 _this.authError(''); 4515 _this.authModalOpen(true); 4516 }; 4517 this.closeTopMenus = function () { 4518 _this.myModelsMenuOpen(false); 4519 _this.publicModelsMenuOpen(false); 4520 }; 4521 this.openTopMenuAuth = function () { 4522 _this.closeTopMenus(); 4523 _this.openAuthModal('header'); 4524 }; 4525 this.bayesBotHostAlreadyIdentifies = function () { 4526 try { 4527 var hostAndPath = (window.location.hostname + window.location.pathname).toLowerCase(); 4528 return hostAndPath.indexOf('bayesbot') > -1; 4529 } 4530 catch (e) { 4531 return false; 4532 } 4533 }; 4534 this.freshBayesBotHref = function () { 4535 var origin = window.location.origin; 4536 if (_this.bayesBotHostAlreadyIdentifies()) { 4537 return origin + '/'; 4538 } 4539 return origin + '/?bayesBot'; 4540 }; 4541 this.communityBayesBotHref = function (communityId) { 4542 var origin = window.location.origin; 4543 var sid = encodeURIComponent(String(communityId)); 4544 if (_this.bayesBotHostAlreadyIdentifies()) { 4545 return origin + '/?sid=' + sid; 4546 } 4547 return origin + '/?bayesBot&sid=' + sid; 4548 }; 4549 this.openNewModel = function () { 4550 window.location.assign(_this.freshBayesBotHref()); 4551 }; 4552 this.openBayesBotCommunity = function (model) { 4553 var communityId = model && model.communityId != null 4554 ? parseInt(String(model.communityId), 10) 4555 : NaN; 4556 if (!Number.isFinite(communityId) || communityId <= 0) { 4557 return; 4558 } 4559 window.location.assign(_this.communityBayesBotHref(communityId)); 4560 }; 4561 this.togglePublicModelsMenu = function () { 4562 var next = !_this.publicModelsMenuOpen(); 4563 _this.myModelsMenuOpen(false); 4564 _this.publicModelsMenuOpen(next); 4565 if (next) { 4566 void _this.loadPublicModels(); 4567 } 4568 }; 4569 this.toggleMyModelsMenu = function () { 4570 var next = !_this.myModelsMenuOpen(); 4571 _this.publicModelsMenuOpen(false); 4572 _this.myModelsMenuOpen(next); 4573 if (next) { 4574 void _this.loadMyModels(true); 4575 } 4576 }; 4577 this.onMyModelsQueryInput = function () { 4578 if (_this.myModelsSearchTimer) { 4579 clearTimeout(_this.myModelsSearchTimer); 4580 } 4581 _this.myModelsSearchTimer = setTimeout(function () { 4582 void _this.loadMyModels(true); 4583 }, 200); 4584 }; 4585 this.loadMoreMyModels = function () { 4586 if (_this.myModelsLoading() || !_this.myModelsHasMore()) { 4587 return; 4588 } 4589 void _this.loadMyModels(false); 4590 }; 4591 this.loadMyModels = function (reset) { return __awaiter(_this, void 0, void 0, function () { 4592 var currentUser, userId, token, offset, q, response, data, models, e_8; 4593 return __generator(this, function (_a) { 4594 switch (_a.label) { 4595 case 0: 4596 currentUser = Distiller.currentUser && Distiller.currentUser(); 4597 userId = currentUser && currentUser.userId; 4598 if (reset) { 4599 this.myModelsOffset = 0; 4600 this.myModels([]); 4601 this.myModelsHasMore(false); 4602 this.myModelsLoaded(false); 4603 } 4604 if (!userId) { 4605 this.myModelsLoading(false); 4606 this.myModelsLoaded(true); 4607 this.myModelsHasMore(false); 4608 return [2 /*return*/]; 4609 } 4610 token = ++this.myModelsRequestToken; 4611 offset = this.myModelsOffset; 4612 q = String(this.myModelsQuery() || '').trim(); 4613 this.myModelsLoading(true); 4614 _a.label = 1; 4615 case 1: 4616 _a.trys.push([1, 4, 5, 6]); 4617 return [4 /*yield*/, fetch(Distiller.apiEndpoint + 4618 '/api/bayesBotMyModels/' + 4619 userId + 4620 '?q=' + 4621 encodeURIComponent(q) + 4622 '&offset=' + 4623 encodeURIComponent(String(offset)) + 4624 '&limit=10', { credentials: 'same-origin' })]; 4625 case 2: 4626 response = _a.sent(); 4627 return [4 /*yield*/, response.json()]; 4628 case 3: 4629 data = _a.sent(); 4630 if (token !== this.myModelsRequestToken) { 4631 return [2 /*return*/]; 4632 } 4633 if (!response.ok || !data || data.ok === false) { 4634 this.myModelsHasMore(false); 4635 return [2 /*return*/]; 4636 } 4637 models = Array.isArray(data.models) ? data.models : []; 4638 if (reset) { 4639 this.myModels(models); 4640 } 4641 else { 4642 this.myModels(this.myModels().concat(models)); 4643 } 4644 this.myModelsOffset = offset + models.length; 4645 this.myModelsHasMore(!!data.hasMore); 4646 return [3 /*break*/, 6]; 4647 case 4: 4648 e_8 = _a.sent(); 4649 if (token !== this.myModelsRequestToken) { 4650 return [2 /*return*/]; 4651 } 4652 console.error('BayesBot my models failed:', e_8); 4653 this.myModelsHasMore(false); 4654 return [3 /*break*/, 6]; 4655 case 5: 4656 if (token === this.myModelsRequestToken) { 4657 this.myModelsLoading(false); 4658 this.myModelsLoaded(true); 4659 } 4660 return [7 /*endfinally*/]; 4661 case 6: return [2 /*return*/]; 4662 } 4663 }); 4664 }); }; 4665 this.loadPublicModels = function () { return __awaiter(_this, void 0, void 0, function () { 4666 var response, data, e_9; 4667 return __generator(this, function (_a) { 4668 switch (_a.label) { 4669 case 0: 4670 this.publicModelsLoading(true); 4671 _a.label = 1; 4672 case 1: 4673 _a.trys.push([1, 4, 5, 6]); 4674 return [4 /*yield*/, fetch(Distiller.apiEndpoint + '/api/bayesBotPublicModels', { credentials: 'same-origin' })]; 4675 case 2: 4676 response = _a.sent(); 4677 return [4 /*yield*/, response.json()]; 4678 case 3: 4679 data = _a.sent(); 4680 if (!response.ok || !data || data.ok === false) { 4681 this.publicModelGroups([]); 4682 return [2 /*return*/]; 4683 } 4684 this.publicModelGroups(Array.isArray(data.groups) ? data.groups : []); 4685 return [3 /*break*/, 6]; 4686 case 4: 4687 e_9 = _a.sent(); 4688 console.error('BayesBot public models failed:', e_9); 4689 this.publicModelGroups([]); 4690 return [3 /*break*/, 6]; 4691 case 5: 4692 this.publicModelsLoading(false); 4693 this.publicModelsLoaded(true); 4694 return [7 /*endfinally*/]; 4695 case 6: return [2 /*return*/]; 4696 } 4697 }); 4698 }); }; 4699 this.closeAuthModal = function () { 4700 _this.authModalOpen(false); 4701 _this.authSubmitting(false); 4702 _this.authError(''); 4703 }; 4704 this.showAuthSignIn = function () { 4705 _this.authModalMode('signin'); 4706 _this.authError(''); 4707 }; 4708 this.showAuthSignUp = function () { 4709 _this.authModalMode('signup'); 4710 _this.authError(''); 4711 }; 4712 this.onBayesBotAuthRequiredEvent = function (event) { 4713 if (!_this.isTempVisitor()) { 4714 return; 4715 } 4716 var data = _this.parseBayesBotSseData(event); 4717 var reason = data && data.reason != null ? String(data.reason) : 'agent'; 4718 _this.openAuthModal(reason === 'create' || reason === 'propose' ? reason : 'agent'); 4719 }; 4720 this.onBayesBotBranchMergedEvent = function (event) { 4721 var data = _this.parseBayesBotSseData(event); 4722 if (_this.mergeInFlight()) { 4723 if (_this.mergeResponseStillWorking(data)) { 4724 _this.holdMergeForForecasts(data); 4725 return; 4726 } 4727 if (!_this.mergeModalOpen()) { 4728 _this.finishSynchronousMerge(data); 4729 } 4730 return; 4731 } 4732 var personalCopyNetId = data && data.personalCopyNetId != null 4733 ? parseInt(String(data.personalCopyNetId), 10) 4734 : NaN; 4735 if (Number.isFinite(personalCopyNetId) && personalCopyNetId > 0 && data.ownsCanonicalTemplate !== true) { 4736 _this.ownsCanonicalTemplate = false;
4737 _this.authorOwnsTemplate(false); 4738 _this.selectedBranchCopyNetId(null); 4739 _this.viewingBranchCopyNetId(null); 4740 _this.mergeModalOpen(false); 4741 if (data.lifetimeInformation) { 4742 _this.presentPersistedLifetimeInformation(data.lifetimeInformation); 4743 } 4744 else if (data.scoresStatus) { 4745 _this.scoresStatus(String(data.scoresStatus)); 4746 } 4747 void _this.adoptPersonalCopyFromServer(personalCopyNetId, data.setId).then(function () { 4748 _this.loadSpecLogs(true); 4749 if (_this.proposePanelTab() === 'branches') { 4750 _this.loadBranchList(); 4751 } 4752 }); 4753 return; 4754 } 4755 if (data && data.templateNetId != null) { 4756 var templateNetId = parseInt(String(data.templateNetId), 10); 4757 if (Number.isFinite(templateNetId) && templateNetId > 0) { 4758 _this.sharedTemplateNetId(templateNetId); 4759 } 4760 } 4761 if (data && data.lifetimeInformation) { 4762 _this.presentPersistedLifetimeInformation(data.lifetimeInformation); 4763 } 4764 else if (data && data.scoresStatus) { 4765 _this.scoresStatus(String(data.scoresStatus)); 4766 } 4767 _this.selectedBranchCopyNetId(null); 4768 _this.viewingBranchCopyNetId(null); 4769 _this.mergeModalOpen(false); 4770 _this.refreshBranchRowSelection(); 4771 _this.restoreOwnNetView(); 4772 _this.loadSpecLogs(true); 4773 if (_this.proposePanelTab() === 'branches') { 4774 _this.loadBranchList(); 4775 } 4776 }; 4777 this.submitAuthModal = function () { return __awaiter(_this, void 0, void 0, function () { 4778 var currentUser, userId, email, password, username, previousUserId, path, response, parsed, identitySwitched, e_10; 4779 return __generator(this, function (_a) { 4780 switch (_a.label) { 4781 case 0: 4782 if (this.authSubmitting()) { 4783 return [2 /*return*/]; 4784 } 4785 currentUser = Distiller.currentUser && Distiller.currentUser(); 4786 userId = currentUser && currentUser.userId; 4787 if (!userId) { 4788 this.authError('Missing current user.'); 4789 return [2 /*return*/]; 4790 } 4791 email = (this.authEmail() || '').trim(); 4792 password = this.authPassword() || ''; 4793 username = (this.authUsername() || '').trim(); 4794 if (this.authModalMode() === 'signup') { 4795 if (!username) { 4796 this.authError('Please enter a username.'); 4797 return [2 /*return*/]; 4798 } 4799 } 4800 if (!email || email.indexOf('@') < 0) { 4801 this.authError('Please enter a valid email address.'); 4802 return [2 /*return*/]; 4803 } 4804 if (!password) { 4805 this.authError('Please enter a password.'); 4806 return [2 /*return*/]; 4807 } 4808 this.authSubmitting(true); 4809 this.authError(''); 4810 previousUserId = userId; 4811 path = this.authModalMode() === 'signin' ? 'bayesBotSignin' : 'bayesBotSignup'; 4812 _a.label = 1; 4813 case 1: 4814 _a.trys.push([1, 5, , 6]); 4815 return [4 /*yield*/, fetch(Distiller.apiEndpoint + '/api/' + path + '/' + userId, { 4816 method: 'POST', 4817 headers: { 'Content-Type': 'application/json' }, 4818 credentials: 'same-origin', 4819 body: JSON.stringify({ 4820 username: username, 4821 email: email, 4822 password: password,
4823 urlParams: Distiller.getUrlMetaParamsToSave ? Distiller.getUrlMetaParamsToSave() : [], 4824 }), 4825 })]; 4826 case 2: 4827 response = _a.sent(); 4828 return [4 /*yield*/, response.json()]; 4829 case 3: 4830 parsed = _a.sent(); 4831 if (parsed && parsed.code === 'email_exists') { 4832 this.authModalMode('signin'); 4833 this.authError('An account with this email already exists. Sign in below.'); 4834 this.authSubmitting(false); 4835 return [2 /*return*/]; 4836 } 4837 if (!parsed || parsed.message !== 'successful login') { 4838 this.authError(parsed && parsed.alertMessage 4839 ? parsed.alertMessage 4840 : (parsed && parsed.error) || 'Could not complete that request.'); 4841 this.authSubmitting(false); 4842 return [2 /*return*/]; 4843 } 4844 identitySwitched = parsed.userId != previousUserId; 4845 if (Distiller.hydrateBayesBotLoginResponse) { 4846 Distiller.hydrateBayesBotLoginResponse(parsed); 4847 } 4848 this.authPassword(''); 4849 this.closeAuthModal(); 4850 return [4 /*yield*/, this.onBayesBotAuthChanged(identitySwitched)]; 4851 case 4: 4852 _a.sent(); 4853 return [3 /*break*/, 6]; 4854 case 5: 4855 e_10 = _a.sent(); 4856 console.error('BayesBot auth modal failed:', e_10); 4857 this.authError('Could not complete that request.'); 4858 this.authSubmitting(false); 4859 return [3 /*break*/, 6]; 4860 case 6: return [2 /*return*/]; 4861 } 4862 }); 4863 }); }; 4864 this.onBayesBotAuthChanged = function (identitySwitched) { return __awaiter(_this, void 0, void 0, function () { 4865 var currentUser, agentKeyPromise, e_11, e_12, e_13; 4866 return __generator(this, function (_a) { 4867 switch (_a.label) { 4868 case 0: 4869 currentUser = Distiller.currentUser && Distiller.currentUser(); 4870 this.viewerUserId = currentUser && currentUser.userId ? currentUser.userId : this.viewerUserId; 4871 if (!identitySwitched) { 4872 return [2 /*return*/]; 4873 } 4874 this.agentKey(null); 4875 this.agentKeyReady = null; 4876 this.cloneReady = false; 4877 this.clonePromise = null; 4878 this.personalCopyNetId = null; 4879 this.connectBayesBotSse(); 4880 _a.label = 1; 4881 case 1: 4882 _a.trys.push([1, 3, , 4]); 4883 agentKeyPromise = this.ensureAgentKey(); 4884 return [4 /*yield*/, agentKeyPromise]; 4885 case 2: 4886 _a.sent(); 4887 return [3 /*break*/, 4]; 4888 case 3: 4889 e_11 = _a.sent(); 4890 console.error('BayesBot auth identity switch: agent key failed', e_11); 4891 return [3 /*break*/, 4]; 4892 case 4: 4893 _a.trys.push([4, 9, , 10]); 4894 if (!this.isCreateMode()) return [3 /*break*/, 6]; 4895 return [4 /*yield*/, this.initializeDraftStudy()]; 4896 case 5: 4897 _a.sent(); 4898 return [3 /*break*/, 8]; 4899 case 6: return [4 /*yield*/, this.loadAuthorBayesNet()]; 4900 case 7: 4901 _a.sent(); 4902 _a.label = 8; 4903 case 8: return [3 /*break*/, 10]; 4904 case 9: 4905 e_12 = _a.sent(); 4906 console.error('BayesBot auth identity switch: model reload failed', e_12); 4907 return [3 /*break*/, 10]; 4908 case 10: 4909 _a.trys.push([10, 12, , 13]); 4910 return [4 /*yield*/, this.loadBayesBotUserModel()]; 4911 case 11: 4912 _a.sent(); 4913 return [3 /*break*/, 13]; 4914 case 12: 4915 e_13 = _a.sent(); 4916 console.error('BayesBot auth identity switch: model preference failed', e_13); 4917 return [3 /*break*/, 13]; 4918 case 13: return [2 /*return*/]; 4919 } 4920 }); 4921 }); }; 4922 this.submitNetProposal = function () { return __awaiter(_this, void 0, void 0, function () { 4923 var text, currentUser, userId, responseText, parsed, e_14; 4924 return __generator(this, function (_a) { 4925 switch (_a.label) { 4926 case 0: 4927 text = (this.nodeProposalText() || '').trim(); 4928 if (!text || this.nodeProposalSubmitting()) { 4929 return [2 /*return*/]; 4930 } 4931 currentUser = Distiller.currentUser && Distiller.currentUser(); 4932 userId = currentUser && currentUser.userId; 4933 if (!userId) { 4934 console.error('BayesBot create-net submit: missing current user'); 4935 return [2 /*return*/]; 4936 } 4937 this.liveTemplateBuild = true; 4938 this.ensureCreateCanvasMounted(); 4939 this.nodeProposalSubmitting(true); 4940 this.proposalJobSettled = false;
4941 this.submittedProposalText(text); 4942 this.proposalFinalResponse(''); 4943 this.proposalInfoValue(null); 4944 this.proposalPhase('processing'); 4945 this.setProposalStatusText('Reading the descriptionâ¦'); 4946 this.nodeProposalText(''); 4947 _a.label = 1; 4948 case 1: 4949 _a.trys.push([1, 3, , 4]); 4950 this.connectBayesBotSse(); 4951 return [4 /*yield*/, Distiller.httpPostJsonAsync(Distiller.apiEndpoint + '/api/bayesBotCreateNet/' + userId, { text: text, communityId: this.resolveBoundCommunityId(), model: this.selectedBayesBotModel() })]; 4952 case 2: 4953 responseText = _a.sent(); 4954 parsed = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 4955 if (parsed && parsed.jobId) { 4956 this.lastBayesBotJobId(parsed.jobId); 4957 this.pollBayesBotJobUntilDone(parsed.jobId); 4958 if (parsed.progress || parsed.status) { 4959 this.setProposalStatusText(parsed.message || 'Reading the descriptionâ¦'); 4960 } 4961 } 4962 else { 4963 console.error('BayesBot create-net unexpected response:', responseText); 4964 this.proposalJobSettled = true; 4965 this.proposalPhase('error'); 4966 this.setProposalStatusText('Something went wrong'); 4967 this.proposalFinalResponse('The description could not be submitted.'); 4968 this.nodeProposalSubmitting(false); 4969 } 4970 return [3 /*break*/, 4]; 4971 case 3: 4972 e_14 = _a.sent(); 4973 console.error('BayesBot create-net submit failed:', e_14); 4974 this.proposalJobSettled = true; 4975 this.proposalPhase('error'); 4976 this.setProposalStatusText('Something went wrong'); 4977 this.proposalFinalResponse('The description could not be submitted.'); 4978 this.nodeProposalSubmitting(false); 4979 return [3 /*break*/, 4]; 4980 case 4: return [2 /*return*/]; 4981 } 4982 }); 4983 }); }; 4984 this.submitNodeProposal = function () { return __awaiter(_this, void 0, void 0, function () { 4985 var text, currentUser, userId, alreadyCloned, e_15, payload, responseText, parsed, queuedLabel, e_16; 4986 return __generator(this, function (_a) { 4987 switch (_a.label) { 4988 case 0: 4989 text = (this.nodeProposalText() || '').trim(); 4990 if (!text || this.nodeProposalSubmitting()) { 4991 return [2 /*return*/]; 4992 } 4993 currentUser = Distiller.currentUser && Distiller.currentUser(); 4994 userId = currentUser && currentUser.userId; 4995 if (!userId) { 4996 console.error('BayesBot submit: missing current user'); 4997 return [2 /*return*/]; 4998 } 4999 this.connectBayesBotSse(); 5000 this.nodeProposalSubmitting(true); 5001 this.proposalJobSettled = false; 5002 this.submittedProposalText(text); 5003 this.proposalFinalResponse(''); 5004 this.proposalInfoValue(null); 5005 this.proposalPhase('processing'); 5006 this.nodeProposalText(''); 5007 _a.label = 1; 5008 case 1: 5009 _a.trys.push([1, 4, , 5]); 5010 alreadyCloned = this.cloneReady && this.personalCopyNetId && !this.viewingSharedTemplate; 5011 if (!(!this.ownsCanonicalTemplate && !alreadyCloned)) return [3 /*break*/, 3]; 5012 this.setProposalStatusText('Preparing clone for editingâ¦'); 5013 return [4 /*yield*/, this.ensurePersonalCopy({ silent: false })]; 5014 case 2: 5015 _a.sent(); 5016 _a.label = 3; 5017 case 3: return [3 /*break*/, 5]; 5018 case 4: 5019 e_15 = _a.sent(); 5020 console.error('BayesBot prepare clone failed:', e_15); 5021 this.proposalJobSettled = true; 5022 this.proposalPhase('error'); 5023 this.setProposalStatusText('Something went wrong'); 5024 this.proposalFinalResponse('Could not prepare your copy of the model.'); 5025 this.nodeProposalSubmitting(false); 5026 return [2 /*return*/]; 5027 case 5: 5028 this.setProposalStatusText('Processing proposal'); 5029 payload = { 5030 text: text, 5031 questionText: this.boundQuestionText() || '', 5032 resolutionCriteria: this.boundResolutionCriteria() || '', 5033 communityId: this.resolveBoundCommunityId(), 5034 model: this.selectedBayesBotModel(), 5035 }; 5036 _a.label = 6; 5037 case 6: 5038 _a.trys.push([6, 8, , 9]); 5039 return [4 /*yield*/, Distiller.httpPostJsonAsync(Distiller.apiEndpoint + '/api/bayesBotSubmit/'
5039+ userId, payload)]; 5040 case 7: 5041 responseText = _a.sent(); 5042 parsed = typeof responseText === 'string' ? JSON.parse(responseText) : responseText; 5043 if (parsed && parsed.jobId) { 5044 this.lastBayesBotJobId(parsed.jobId); 5045 this.pollBayesBotJobUntilDone(parsed.jobId); 5046 if (parsed.progress || parsed.status) { 5047 queuedLabel = parsed.status === 'queued' || parsed.progress === 'queued' 5048 ? 'Processing proposal' 5049 : this.proposalStatusText(); 5050 this.setProposalStatusText(queuedLabel); 5051 } 5052 } 5053 else { 5054 console.error('BayesBot submit unexpected response:', responseText); 5055 this.proposalJobSettled = true; 5056 this.proposalPhase('error'); 5057 this.setProposalStatusText('Something went wrong'); 5058 this.proposalFinalResponse('The proposal could not be submitted.'); 5059 this.nodeProposalSubmitting(false); 5060 } 5061 return [3 /*break*/, 9]; 5062 case 8:
5063 e_16 = _a.sent(); 5064 console.error('BayesBot submit failed:', e_16); 5065 this.proposalJobSettled = true; 5066 this.proposalPhase('error'); 5067 this.setProposalStatusText('Something went wrong'); 5068 this.proposalFinalResponse('The proposal could not be submitted.'); 5069 this.nodeProposalSubmitting(false); 5070 return [3 /*break*/, 9]; 5071 case 9: return [2 /*return*/]; 5072 } 5073 }); 5074 }); }; 5075 this.onNodeProposalKeydown = function (_data, event) { 5076 if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) { 5077 event.preventDefault(); 5078 _this.submitComposer(); 5079 return false; 5080 } 5081 return true; 5082 }; 5083 this.getQuillOptions = function (purpose, index, isReadOnly, parentIndex) { 5084 var outerContainerId = ko.observable('outerQuillContainerFor_' + index); 5085 if (purpose === 'description') { 5086 outerContainerId = ko.observable('outerQuillContainerFor_description'); 5087 } 5088 if (purpose === 'edit-about') { 5089 outerContainerId = ko.observable('outerQuillContainerFor_edit-about'); 5090 } 5091 var atIndex = ko.observable(index); 5092 var idParam = atIndex; 5093 if (parentIndex || parentIndex === 0) { 5094 atIndex = ko.observable(parentIndex); 5095 } 5096 var options = { 5097 isReadOnly: true, 5098 outerContainerId: outerContainerId, 5099 atIndex: atIndex, 5100 idParam: idParam, 5101 }; 5102 if (!isReadOnly) { 5103 options = { 5104 placeholder: 'This is a text block. Add static content here.', 5105 isReadOnly: isReadOnly, 5106 outerContainerId: outerContainerId, 5107 toolbarOptions: [ 5108 ['bold', 'italic', 'underline', 'strike', 'blockquote'], // toggled buttons 5109 // ['blockquote', 'code-block'], 5110 // [{ 'header': 1 }, { 'header': 2 }], // custom button values 5111 [{ 'list': 'ordered' }, { 'list': 'bullet' }], 5112 [{ 'script': 'sub' }, { 'script': 'super' }], // superscript/subscript 5113 [{ 'indent': '-1' }, { 'indent': '+1' }], // outdent/indent 5114 [{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown 5115 // [{ 'header': [1, 2, 3, 4, 5, 6, false] }], 5116 [{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme 5117 // [{ 'font': []}], 5118 [{ 'font': ['montserrat', 'arvo'] }], 5119 [{ 'align': [] }], 5120 ['clean', 'link', 'image', 'video'] 5121 ], 5122 atIndex: atIndex, 5123 idParam: idParam, 5124 }; 5125 return options; 5126 } 5127 if (purpose === 'description') { 5128 options.placeholder = "This text is featured at the top of the page. If you are using this page to ask a forecasting question, this description should contain that forecasting question (and any background you want to include -- links, images, whatever!)."; 5129 } 5130 else if (purpose === 'question') { 5131 options.placeholder = "Write your question here (optional - if your page description contains all the information your users will need, then you can leave this blank)."; 5132 } 5133 else if (purpose === 'graph') { 5134 options.placeholder = "Describe your graph here (optional)."; 5135 } 5136 else if (purpose === 'comment') { 5137 options.placeholder = "Describe the comments that will appear here (optional)."; 5138 } 5139 else if (purpose === 'edit-about') { 5140 options.placeholder = "This is the first page participants see when they register for your study. Describe what they should expect to do here. Add images, videos, as needed!"; 5141 } 5142 return options; 5143 }; 5144 this.updateQuestionWithValues = function (question, values) { 5145 if (!values) { 5146 return question; 5147 } 5148 var keys = Object.keys(values); 5149 if (question.text()) { 5150 for (var i = 0; i < keys.length; i++) { 5151 var key = keys[i]; 5152 var value = values[key]; 5153 question.text(question.text().replace(new RegExp(_this.escapeRegExp(key), 'g'), value)); 5154 } 5155 } 5156 if (question.quillDelta()) { 5157 var quillDelta = question.quillDelta(); 5158 if (typeof quillDelta !== 'string') { 5159 quillDelta = JSON.stringify(quillDelta); 5160 } 5161 for (var i = 0; i < keys.length; i++) { 5162 var key = keys[i]; 5163 var value = values[key]; 5164 quillDelta = quillDelta.replace(new RegExp(_this.escapeRegExp(key), 'g'), value); 5165 } 5166 question.quillDelta(JSON.parse(quillDelta)); 5167 } 5168 if (question.answers().length > 0) { 5169 for (var i = 0; i < question.answers().length; i++) { 5170 var text = question.answers()[i].text(); 5171 var defaultValue = question.answers()[i].defaultValue(); 5172 if (text) { 5173 for (var i_1 = 0; i_1 < keys.length; i_1++) { 5174 var key = keys[i_1]; 5175 var value = values[key]; 5176 text = text.replace(new RegExp(_this.escapeRegExp(key), 'g'), value); 5177 } 5178 question.answers()[i].text(text); 5179 } 5180 if (defaultValue) { 5181 for (var i_2 = 0; i_2 < keys.length; i_2++) { 5182 var key = keys[i_2]; 5183 var value = values[key]; 5184 defaultValue = defaultValue.replace(new RegExp(_this.escapeRegExp(key), 'g'), value); 5185 } 5186 question.answers()[i].defaultValue(defaultValue); 5187 } 5188 } 5189 } 5190 return question; 5191 }; 5192 this.updateTextWithValues = function (text, values) { 5193 if (!values || !text) { 5194 return text; 5195 } 5196 var keys = Object.keys(values); 5197 for (var i = 0; i < keys.length; i++) { 5198 var key = keys[i]; 5199 var value = values[key]; 5200 text = text.replace(new RegExp(_this.escapeRegExp(key), 'g'), value); 5201 } 5202 return text; 5203 }; 5204 this.elementWithOriginalValues = function (element, deepClone) { 5205 element.text(deepClone.text); 5206 element.quillDelta(deepClone.quillDelta); 5207 if (element.variableValues && element.variableValues()) { 5208 element.variableValues(JSON.parse(JSON.stringify(deepClone.variableValues))); 5209 } 5210 if (element.question && element.question()) { 5211 element.question().text(deepClone.question.text); 5212 element.question().quillDelta(deepClone.question.quillDelta); 5213 if (element.question().answers && element.question().answers()) { 5214 for (var i = 0; i < element.question().answers().length; i++) { 5215 element.question().answers()[i].text(deepClone.question.answers[i].text); 5216 } 5217 } 5218 if (element.question().timepointQuestions && element.question().timepointQuestions()) { 5219 for (var i = 0; i < element.question().timepointQuestions().length; i++) { 5220 element.question().timepointQuestions()[i].text(deepClone.question.timepointQuestions[i].text); 5221 if (element.question().timepointQuestions()[i].answers && element.question().timepointQuestions()[i].answers()) { 5222 for (var a = 0; a < element.question().timepointQuestions()[i].answers().length; a++) { 5223 element.question().timepointQuestions()[i].answers()[a].text(deepClone.question.timepointQuestions[i].answers[a].text); 5224 } 5225 } 5226 } 5227 } 5228 } 5229 if (element.subElements && element.subElements().length > 0) { 5230 for (var i = 0; i < element.subElements().length; i++) { 5231 var subElement = _this.elementWithOriginalValues(element.subElements()[i], deepClone.subElements[i]); 5232 element.subElements()[i] = subElement; 5233 } 5234 } 5235 return element; 5236 }; 5237 this.showNextButton = ko.observable(false); 5238 this.showNextButtonComputed = ko.computed(function () { 5239 var _a; 5240 if (!_this.currentStageWorkflow()) { 5241 _this.showNextButton(false); 5242 return; 5243 } 5244 var questionsToExclude = []; 5245 //IF THE ADMIN EXPLICITLY ADDED THE NEXT BUTTON, ALWAYS SHOW IT 5246 if (_this.currentStageWorkflow().elements().find(function (a) { return a.hasOwnProperty('buttonType') && a.buttonType().value === 'nextPage' && !a.isAutoAdded; })) {
5247 if (Distiller.reevaluatingPathFor().length > 0) { 5248 _this.showNextButton(false); 5249 return; 5250 } 5251 _this.showNextButton(true); 5252 return; 5253 } 5254 var _loop_1 = function (i) { 5255 if (_this.currentStageWorkflow().elements()[i].type === 'question' && _this.currentStageWorkflow().elements()[i].question()) { 5256 if (!_this.currentStageWorkflow().elements()[i].generalQuestionType()) { 5257 //this is an edge case where they've added a question element but haven't defined the type 5258 questionsToExclude.push(_this.currentStageWorkflow().elements()[i].question().questionId()); 5259 } 5260 else if (Distiller.showHideIfPayload().find(function (a) { return a.workflowIndex === i; })) { 5261 if (Distiller.showHideIfPayload().find(function (a) { return a.workflowIndex === i && a.action === 'showIf' && a.status() === 0; })) { 5262 questionsToExclude.push(_this.currentStageWorkflow().elements()[i].question().questionId()); 5263 for (var t = 0; t < _this.currentStageWorkflow().elements()[i].question().timepointQuestions().length; t++) { 5264 questionsToExclude.push(_this.currentStageWorkflow().elements()[i].question().timepointQuestions()[t].questionId()); 5265 } 5266 } 5267 else if (Distiller.showHideIfPayload().find(function (a) { return a.workflowIndex === i && a.action === 'hideIf' && a.status() === 1; })) { 5268 questionsToExclude.push(_this.currentStageWorkflow().elements()[i].question().questionId()); 5269 for (var t = 0; t < _this.currentStageWorkflow().elements()[i].question().timepointQuestions().length; t++) { 5270 questionsToExclude.push(_this.currentStageWorkflow().elements()[i].question().timepointQuestions()[t].questionId()); 5271 } 5272 } 5273 } 5274 } 5275 }; 5276 for (var i = 0; i < _this.currentStageWorkflow().elements().length; i++) { 5277 _loop_1(i); 5278 } 5279 if (!_this.questionSet() || Distiller.autoSaving() || Distiller.reevaluatingPathFor().length > 0) { 5280 _this.showNextButton(false); 5281 return; 5282 } 5283 //if they have completed the page AND there are more pages to show 5284 if (Distiller.questionsOnPath().filter(function (a) { var _a; return a.setId === ((_a = _this.questionSet()) === null || _a === void 0 ? void 0 : _a.setId()) && questionsToExclude.indexOf(a.questionId) < 0; }).filter(function (a) { return !a.isComplete(); }).length === 0 5285 && _this.questionSet().setId() !== ((_a = Distiller.questionSets()[Distiller.questionSets().length - 1]) === null || _a === void 0 ? void 0 : _a.setId())) { 5286 _this.showNextButton(true); 5287 return; 5288 } 5289 _this.showNextButton(false); 5290 return; 5291 }); 5292 this.settingVariables = ko.observable(false); 5293 this.subscribeToQuestionReference = function (subscribableRow) { 5294 var questionReferences = subscribableRow.questionSubstrings; 5295 var _loop_2 = function (i) { 5296 var questionId = Distiller.extractNumberAfterPrefix(questionReferences[i], 'QID'); 5297 var answerId = Distiller.extractNumberAfterPrefix(questionReferences[i], 'AID'); 5298 if (!Distiller.variableValueSubscriptions().find(function (a) { return a.questionId === questionId && a.answerId === answerId && a.variableName === subscribableRow.variableName && a.variableValue === subscribableRow.variableValue; })) { 5299 var question = Distiller.allQuestions().find(function (a) { return a.questionId() === parseInt(questionId); }); 5300 if (question) { 5301 var row_1 = { 5302 questionId: questionId, 5303 answerId: answerId, 5304 variableName: subscribableRow.variableName, 5305 variableValue: subscribableRow.variableValue, 5306 subscription: null 5307 }; 5308 row_1.subscription = question.savedCurrentForecast.subscribe(function (a) { 5309 _this.setVariableValuesClientSide(row_1, a); 5310 }); 5311 Distiller.variableValueSubscriptions.push(row_1); 5312 } 5313 } 5314 }; 5315 for (var i = 0; i < questionReferences.length; i++) { 5316 _loop_2(i); 5317 } 5318 };
5319 this.updateVariablesTimeout = null; 5320 this.indexesToUpdate = ko.observableArray([]); 5321 this.highlightRequired = ko.observable(false); 5322 this.setVariableValuesClientSide = function (subscriptionRow, savedCurrentForecast) { 5323 if (_this.updateVariablesTimeout) { 5324 clearTimeout(_this.updateVariablesTimeout); 5325 } 5326 // let requestId = Distiller.fakeNumericId(Distiller.userPathMetadataRequestIds()); 5327 //Distiller.userPathMetadataRequestIds.push(requestId); 5328 var updateableElements = Distiller.updatableElements().filter(function (a) { return a.setId === _this.questionSet().setId(); }); 5329 var indexesToUpdate = []; 5330 for (var i = 0; i < updateableElements.length; i++) { 5331 var elementRow = updateableElements[i]; 5332 var element = elementRow.deepClone; 5333 if ((element.text && element.text.indexOf(subscriptionRow.variableName) > -1) 5334 || (element.quillDelta && JSON.stringify(element.quillDelta).indexOf(subscriptionRow.variableName) > -1)) { 5335 indexesToUpdate.push(elementRow.elementIndex); 5336 } 5337 //updatable elements are PLAIN JS 5338 if (element.question) { 5339 if ((element.question.text && element.question.text.indexOf(subscriptionRow.variableName) > -1) 5340 || (element.question.quillDelta && JSON.stringify(element.question.quillDelta).indexOf(subscriptionRow.variableName) > -1)) { 5341 indexesToUpdate.push(elementRow.elementIndex); 5342 } 5343 for (var j = 0; j < element.question.timepointQuestions.length; j++) { 5344 if ((element.question.timepointQuestions[j].text && element.question.timepointQuestions[j].text.indexOf(subscriptionRow.variableName) > -1) 5345 || (element.question.timepointQuestions[j].quillDelta && JSON.stringify(element.question.timepointQuestions[j].quillDelta).indexOf(subscriptionRow.variableName) > -1)) { 5346 indexesToUpdate.push(elementRow.elementIndex); 5347 } 5348 } 5349 for (var j = 0; j < element.question.answers.length; j++) { 5350 if ((element.question.answers[j].text && element.question.answers[j].text.indexOf(subscriptionRow.variableName) > -1) 5351 || (element.question.answers[j].quillDelta && JSON.stringify(element.question.answers[j].quillDelta).indexOf(subscriptionRow.variableName) > -1)) { 5352 indexesToUpdate.push(elementRow.elementIndex); 5353 } 5354 } 5355 } 5356 } 5357 var self = _this; 5358 if (indexesToUpdate.length > 0) { 5359 for (var i = 0; i < indexesToUpdate.length; i++) { 5360 if (_this.indexesToUpdate().indexOf(indexesToUpdate[i]) < 0) { 5361 _this.indexesToUpdate.push(indexesToUpdate[i]); 5362 } 5363 } 5364 _this.updateVariablesTimeout = setTimeout(function () { 5365 self.updateVariablesTimeout = null; 5366 _this.setVariableValues(_this.indexesToUpdate()); 5367 _this.indexesToUpdate([]); 5368 }, 100); 5369 } 5370 else if (_this.indexesToUpdate().length > 0) { 5371 _this.updateVariablesTimeout = setTimeout(function () { 5372 self.updateVariablesTimeout = null; 5373 _this.setVariableValues(_this.indexesToUpdate()); 5374 _this.indexesToUpdate([]); 5375 }, 100); 5376 } 5377 }; 5378 this.setVariableValues = function (indexesToUpdate) { return __awaiter(_this, void 0, void 0, function () { 5379 var startingVariableValues, _loop_3, this_1, i, i, questionReferences, allVariableValueKeys, _loop_4, this_2, i, uniqueQuestionReferences, arrayOfUniqueReferences, questionReferenceValues, questionRefKeys, i, keys, v, q, text, expressionReferences, i, keys, v, expressionSubstrings, uniqueExpressionReferences, arrayOfUniqueExpressionReferences, expressionReferenceValues, i, expression, expressionValue, expressionRefKeys, i, keys, v, q, text, i, variableValues, newText, quillDelta, j, k, paramValue, newParamValue, question, variableValuesToSave, _loop_5, this_3, i; 5380 var _this = this; 5381 return __generator(this, function (_a) { 5382 switch (_a.label) { 5383 case 0: 5384 startingVariableValues = []; 5385 if (indexesToUpdate && indexesToUpdate.length > 0) { 5386 _loop_3 = function (i) { 5387 var variableNames = Object.keys(this_1.currentStageWorkflow().elements()[indexesToUpdate[i]].variableValues()); 5388 var _loop_6 = function (v) { 5389 if (!startingVariableValues.find(function (a) { return a.name === variableNames[v]; })) { 5390 startingVariableValues.push({ 5391 name: variableNames[v], 5392 value: this_1.currentStageWorkflow().elements()[indexesToUpdate[i]].variableValues()[variableNames[v]] 5393 }); 5394 } 5395 }; 5396 for (var v = 0; v < variableNames.length; v++) { 5397 _loop_6(v); 5398 } 5399 }; 5400 this_1 = this; 5401 for (i = 0; i < indexesToUpdate.length; i++) { 5402 _loop_3(i); 5403 } 5404 } 5405 if (!indexesToUpdate) { 5406 for (i = 0; i < Distiller.variableValueSubscriptions().length; i++) { 5407 Distiller.variableValueSubscriptions()[i].subscription.dispose(); 5408 } 5409 Distiller.variableValueSubscriptions([]); 5410 } 5411 // Distiller.updatableElements([]);
5411 //new june 9 2025 clear out updatable elements 5412 if (!indexesToUpdate) { 5413 this.settingVariables(true); 5414 } 5415 questionReferences = []; 5416 allVariableValueKeys = []; 5417 _loop_4 = function (i) { 5418 if (!indexesToUpdate || indexesToUpdate.indexOf(i) > -1) { 5419 if (this_2.currentStageWorkflow().elements()[i].variableValues && this_2.currentStageWorkflow().elements()[i].variableValues()) { 5420 //if this element is updatable, we need to replace its text, questionText, and answerOption text with the 5421 //values from the deep clone so that the rest of the question reference script below will apply 5422 if (Distiller.updatableElements().find(function (a) { return a.setId === _this.questionSet().setId() && a.elementIndex === i; })) { 5423 this_2.currentStageWorkflow().elements()[i] = this_2.elementWithOriginalValues(this_2.currentStageWorkflow().elements()[i], Distiller.updatableElements().find(function (a) { return a.setId === _this.questionSet().setId() && a.elementIndex === i; }).deepClone); 5424 } 5425 var keys = Object.keys(this_2.currentStageWorkflow().elements()[i].variableValues()); 5426 allVariableValueKeys.push.apply(allVariableValueKeys, keys); 5427 for (var v = 0; v < keys.length; v++) { 5428 var questionSubstrings = Distiller.extractQuestionSubstrings(this_2.currentStageWorkflow().elements()[i].variableValues()[keys[v]]); 5429 if (questionSubstrings.length > 0) { 5430 var row = { 5431 variableName: keys[v], 5432 variableValue: this_2.currentStageWorkflow().elements()[i].variableValues()[keys[v]], 5433 questionSubstrings: questionSubstrings 5434 }; 5435 this_2.subscribeToQuestionReference(row); 5436 } 5437 questionReferences.push.apply(questionReferences, questionSubstrings); 5438 } 5439 //clone elements with question references so we can update them 5440 if (questionReferences.length > 0 && !Distiller.updatableElements().find(function (a) { return a.setId === _this.questionSet().setId() && a.elementIndex === i; })) { 5441 var elementReference = { 5442 setId: this_2.questionSet().setId(), 5443 elementIndex: i, 5444 deepClone: Distiller.deepClone(ko.toJS(this_2.currentStageWorkflow().elements()[i])) 5445 }; 5446 Distiller.updatableElements.push(elementReference); 5447 } 5448 } 5449 } 5450 }; 5451 this_2 = this; 5452 //extract references to questions 5453 //get reference:values pairs from server 5454 //replace reference within value 5455 //do math if applicable 5456 for (i = 0; i < this.currentStageWorkflow().elements().length; i++) { 5457 _loop_4(i); 5458 } 5459 uniqueQuestionReferences = new Set(questionReferences); 5460 arrayOfUniqueReferences = Array.from(uniqueQuestionReferences); 5461 if (!(questionReferences.length > 0)) return [3 /*break*/, 2]; 5462 return [4 /*yield*/, this.getQuestionReferenceValues(arrayOfUniqueReferences)]; 5463 case 1: 5464 questionReferenceValues = _a.sent(); 5465 if (!questionReferenceValues.err) { 5466 questionRefKeys = Object.keys(questionReferenceValues); 5467 for (i = 0; i < this.currentStageWorkflow().elements().length; i++) { 5468 if (!indexesToUpdate || indexesToUpdate.indexOf(i) > -1) { 5469 if (this.currentStageWorkflow().elements()[i].variableValues && this.currentStageWorkflow().elements()[i].variableValues()) { 5470 keys = Object.keys(this.currentStageWorkflow().elements()[i].variableValues()); 5471 for (v = 0; v < keys.length; v++) { 5472 for (q = 0; q < questionRefKeys.length; q++) { 5473 text = this.currentStageWorkflow().elements()[i].variableValues()[keys[v]]; 5474 text = text.replace(new RegExp(this.escapeRegExp(questionRefKeys[q]), 'g'), questionReferenceValues[questionRefKeys[q]]); 5475 this.currentStageWorkflow().elements()[i].variableValues()[keys[v]] = text; 5476 } 5477 } 5478 } 5479 } 5480 } 5481 } 5482 _a.label = 2; 5483 case 2: 5484 expressionReferences = []; 5485 //check for $e{} and extract contents 5486 for (i = 0; i < this.currentStageWorkflow().elements().length; i++) { 5487 if (!indexesToUpdate || indexesToUpdate.indexOf(i) > -1) { 5488 if (this.currentStageWorkflow().elements()[i].variableValues && this.currentStageWorkflow().elements()[i].variableValues()) { 5489 keys = Object.keys(this.currentStageWorkflow().elements()[i].variableValues()); 5490 for (v = 0; v < keys.length; v++) { 5491 expressionSubstrings = this.extractExpressionSubstrings(this.currentStageWorkflow().elements()[i].variableValues()[keys[v]]); 5492 expressionReferences.push.apply(expressionReferences, expressionSubstrings); 5493 } 5494 } 5495 } 5496 } 5497 if (expressionReferences.length > 0) { 5498 uniqueExpressionReferences = new Set(expressionReferences); 5499 arrayOfUniqueExpressionReferences = Array.from(uniqueExpressionReferences); 5500 expressionReferenceValues = {}; 5501 for (i = 0; i < arrayOfUniqueExpressionReferences.length; i++) { 5502 expression = arrayOfUniqueExpressionReferences[i]; 5503 expressionValue = null; 5504 try { 5505 expressionValue = this.evaluateMathExpression(expression); 5506 } 5507 catch (error) { 5508 console.log("error evaluating math expression", error); 5509 expressionValue = 'ERROR'; 5510 } 5511 expressionReferenceValues[expression] = expressionValue; 5512 } 5513 expressionRefKeys = Object.keys(expressionReferenceValues); 5514 for (i = 0; i < this.currentStageWorkflow().elements().length; i++) { 5515 if (!indexesToUpdate || indexesToUpdate.indexOf(i) > -1) { 5516 if (this.currentStageWorkflow().elements()[i].variableValues && this.currentStageWorkflow().elements()[i].variableValues()) { 5517 keys = Object.keys(this.currentStageWorkflow().elements()[i].variableValues()); 5518 for (v = 0; v < keys.length; v++) { 5519 for (q = 0; q < expressionRefKeys.length; q++) { 5520 text = this.currentStageWorkflow().elements()[i].variableValues()[keys[v]]; 5521 text = text.replace(new RegExp(this.escapeRegExp(expressionRefKeys[q]), 'g'), expressionReferenceValues[expressionRefKeys[q]]); 5522 this.currentStageWorkflow().elements()[i].variableValues()[keys[v]] = text; 5523 } 5524 } 5525 } 5526 } 5527 } 5528 } 5529 //evaluate math 5530 for (i = 0; i < this.currentStageWorkflow().elements().length; i++) { 5531 if (!indexesToUpdate || indexesToUpdate.indexOf(i) > -1) { 5532 if (this.currentStageWorkflow().elements()[i].variableValues) { 5533 variableValues = this.currentStageWorkflow().elements()[i].variableValues(); 5534 if (this.currentStageWorkflow().elements()[i].text) { 5535 newText = this.updateTextWithValues(this.currentStageWorkflow().elements()[i].text(), variableValues); 5536 this.currentStageWorkflow().elements()[i].text(newText); 5537 } 5538 if (this.currentStageWorkflow().elements()[i].quillDelta) { 5539 quillDelta = this.currentStageWorkflow().elements()[i].quillDelta(); 5540 if (typeof quillDelta !== 'string') { 5541 quillDelta = JSON.stringify(quillDelta); 5542 } 5543 quillDelta = this.updateTextWithValues(quillDelta, variableValues); 5544 this.currentStageWorkflow().elements()[i].quillDelta(JSON.parse(quillDelta)); 5545 //WHAT THE FUCK IS WRONG WITH THIS 5546 this.currentStageWorkflow().elements()[i].quillDelta.valueHasMutated(); 5547 } 5548 if (this.currentStageWorkflow().elements()[i].uiParams && this.currentStageWorkflow().elements()[i].uiParams() && this.currentStageWorkflow().elements()[i].uiParams().length > 0) { 5549 for (j = 0; j < this.currentStageWorkflow().elements()[i].uiParams().length; j++) { 5550 if (this.currentStageWorkflow().elements()[i].uiParams()[j].hasOwnProperty('customParams') && this.currentStageWorkflow().elements()[i].uiParams()[j].customParams && this.currentStageWorkflow().elements()[i].uiParams()[j].customParams().length > 0) { 5551 for (k = 0; k < this.currentStageWorkflow().elements()[i].uiParams()[j].customParams().length; k++) { 5552 paramValue = this.currentStageWorkflow().elements()[i].uiParams()[j].customParams()[k].value(
5552); 5553 newParamValue = this.updateTextWithValues(paramValue, variableValues); 5554 this.currentStageWorkflow().elements()[i].uiParams()[j].customParams()[k].value(newParamValue); 5555 } 5556 } 5557 } 5558 } 5559 if (this.currentStageWorkflow().elements()[i].question && this.currentStageWorkflow().elements()[i].question()) { 5560 question = this.currentStageWorkflow().elements()[i].question(); 5561 question = this.updateQuestionWithValues(question, variableValues); 5562 this.currentStageWorkflow().elements()[i].question(question); 5563 } 5564 /* if (i === 0) { 5565 console.log("variableValues for element i = ", i, this.currentStageWorkflow().elements()[0].variableValues()); 5566 } */ 5567 } 5568 } 5569 } 5570 variableValuesToSave = []; 5571 if (indexesToUpdate && indexesToUpdate.length > 0) { 5572 _loop_5 = function (i) { 5573 var variableNames = Object.keys(this_3.currentStageWorkflow().elements()[indexesToUpdate[i]].variableValues()); 5574 var _loop_7 = function (v) { 5575 if (!variableValuesToSave.find(function (a) { return a.name === variableNames[v]; }) 5576 && this_3.currentStageWorkflow().elements()[indexesToUpdate[i]].variableValues()[variableNames[v]] !== startingVariableValues.find(function (a) { return a.name === variableNames[v]; }).value) { 5577 variableValuesToSave.push({ 5578 name: variableNames[v], 5579 value: this_3.currentStageWorkflow().elements()[indexesToUpdate[i]].variableValues()[variableNames[v]] 5580 }); 5581 } 5582 }; 5583 for (var v = 0; v < variableNames.length; v++) { 5584 _loop_7(v); 5585 } 5586 }; 5587 this_3 = this; 5588 for (i = 0; i < indexesToUpdate.length; i++) { 5589 _loop_5(i); 5590 } 5591 } 5592 if (!(variableValuesToSave.length > 0)) return [3 /*break*/, 4]; 5593 return [4 /*yield*/, Distiller.updateUserPathMetadata(variableValuesToSave, 'path')]; 5594 case 3: 5595 _a.sent(); 5596 _a.label = 4; 5597 case 4: 5598 this.settingVariables(false); 5599 return [2 /*return*/]; 5600 } 5601 }); 5602 }); }; 5603 this.getQuestionsByTabForTabController = function (tabControllerElementIndex) { 5604 var _a, _b; 5605 var elements = (_a = _this.currentStageWorkflow()) === null || _a === void 0 ? void 0 : _a.elements(); 5606 if (!elements || tabControllerElementIndex < 0 || tabControllerElementIndex >= elements.length) { 5607 return {}; 5608 } 5609 var tabController = elements[tabControllerElementIndex]; 5610 if (!(tabController === null || tabController === void 0 ? void 0 : tabController.tabs)) { 5611 return {}; 5612 } 5613 var tabIds = tabController.tabs().map(function (a) { return a.tabId; }); 5614 var questionsByTab = {}; 5615 for (var i = 0; i < tabIds.length; i++) { 5616 questionsByTab[tabIds[i]] = []; 5617 } 5618 for (var i = 0; i < elements.length; i++) { 5619 var element = elements[i]; 5620 if (element.type === 'question' && element.tabId && tabIds.indexOf(element.tabId) > -1 && ((_b = element.question) === null || _b === void 0 ? void 0 : _b.call(element))) { 5621 questionsByTab[element.tabId].push(element.question().questionId()); 5622 } 5623 } 5624 return questionsByTab; 5625 }; 5626 this.hiddenTabIds = ko.pureComputed(function () { 5627 var _a, _b, _c, _d; 5628 var hiddenTabIds = []; 5629 var _loop_8 = function (i) { 5630 if (this_4.currentStageWorkflow().elements()[i].type === 'tab-controller' || this_4.currentStageWorkflow().elements()[i].type === 'detail-expander') { 5631 if (((_a = Distiller.showHideIfPayload().find(function (a) { return a.workflowIndex === i && a.action === 'showIf'; })) === null || _a === void 0 ? void 0 : _a.status()) !== undefined 5632 && ((_b = Distiller.showHideIfPayload().find(function (a) { return a.workflowIndex === i && a.action === 'showIf'; })) === null || _b === void 0 ? void 0 : _b.status()) !== 1) { 5633 hiddenTabIds.push.apply(hiddenTabIds, this_4.currentStageWorkflow().elements()[i].tabs().map(function (a) { return a.tabId; })); 5634 } 5635 if (((_c = Distiller.showHideIfPayload().find(function (a) { return a.workflowIndex === i && a.action === 'hideIf'; })) === null || _c === void 0 ? void 0 : _c.status()) !== undefined 5636 && ((_d = Distiller.showHideIfPayload().find(function (a) { return a.workflowIndex === i && a.action === 'hideIf'; })) === null || _d === void 0 ? void 0 : _d.status()) === 1) { 5637 hiddenTabIds.push.apply(hiddenTabIds, this_4.currentStageWorkflow().elements()[i].tabs().map(function (a) { return a.tabId; })); 5638 } 5639 } 5640 }; 5641 var this_4 = this; 5642 for (var i = 0; i < this.currentStageWorkflow().elements().length; i++) { 5643 _loop_8(i); 5644 } 5645 return hiddenTabIds; 5646 }, this); 5647 this.allTabs = ko.pureComputed(function () { 5648 var tabControllers = this.currentStageWorkflow().elements().filter(function (a) { return a.hasOwnProperty('tabs'); }); 5649 if (tabControllers.length > 0) { 5650 for (var i = 0; i < tabControllers.length; i++) { 5651 return tabControllers.map(function (a) { return a.tabs(); }).flat().map(function (a) { return a.tabId; }); 5652 } 5653 } 5654 return []; 5655 }, this); 5656 this.isInsideDetailExpander = function (tabId) { 5657 var _a; 5658 if (!tabId) { 5659 return false;
5660 } 5661 var elements = (_a = _this.currentStageWorkflow()) === null || _a === void 0 ? void 0 : _a.elements(); 5662 var parent = elements === null || elements === void 0 ? void 0 : elements.find(function (a) { return a.hasOwnProperty('tabs') && a.tabs().find(function (b) { return b.tabId === tabId; }); }); 5663 return (parent === null || parent === void 0 ? void 0 : parent.type) === 'detail-expander'; 5664 }; 5665 this.selectedTabs = ko.pureComputed(function () { 5666 var selectedTabIdsToReturn = []; 5667 var tabControllers = this.currentStageWorkflow().elements().filter(function (a) { return a.hasOwnProperty('tabs'); }); 5668 if (tabControllers.length > 0) { 5669 for (var _i = 0, tabControllers_1 = tabControllers; _i < tabControllers_1.length; _i++) { 5670 var tabController = tabControllers_1[_i]; 5671 //if it DOES NOT have a parent tab controller, or if it DOES have a parent tab controller and it's selected, 5672 //add its selected tab to the selected tabs 5673 if (!tabController.tabId || (tabController.tabId && (selectedTabIdsToReturn.indexOf(tabController.tabId) > -1) || this.allTabs().indexOf(tabController.tabId) < 0)) { 5674 if (tabController.tabs().find(function (b) { return b.isSelected(); })) { 5675 selectedTabIdsToReturn.push(tabController.tabs().find(function (b) { return b.isSelected(); }).tabId); 5676 } 5677 } 5678 } 5679 return selectedTabIdsToReturn; 5680 } 5681 return []; 5682 }, this); 5683 this.showingWorkflowModal = ko.observable(null); 5684 this.referenceValueForModal = ko.observable(null); 5685 this.firstMatrixQuestions = ko.observableArray([]); 5686 this.confirmMatrixQuestion = ko.observable(null); 5687 this.confirmHighEstimate = function () { 5688 /* for (let i = 0; i < this.firstMatrixQuestions().length; i++) { 5689 this.firstMatrixQuestions()[i].answers()[1].currentUserForecast(1); 5690 } */ 5691 _this.showingWorkflowModal(null); 5692 }; 5693 this.reviseHighEstimate = function () { 5694 if (_this.confirmMatrixQuestion()) { 5695 _this.confirmMatrixQuestion().answers()[0].currentUserForecast(0); 5696 _this.showingWorkflowModal(null); 5697 } 5698 }; 5699 this.setupBindings = function () { 5700 ko.bindingHandlers.viewerJsSrc = { 5701 update: function (element, valueAccessor) { 5702 var value = ko.unwrap(valueAccessor()); // Get the current value of the observable 5703 if (value) { 5704 element.src = "/ts/Vendors/ViewerJS/#/../../../api/file/" + value; 5705 } 5706 } 5707 }; 5708 }; 5709 var self = this; 5710 // STRIPE THEME: remove this classList.add to revert page chrome. 5711 document.body.classList.add('bayesBotStripeTheme'); 5712 Distiller.bayesBotViewModel = this; 5713 this.setupBindings(); 5714 document.addEventListener('click', function (event) { 5715 if (!_this.bayesBotModelMenuOpen()) { 5716 return; 5717 } 5718 var target = event.target; 5719 if (target && target.closest && target.closest('.bayesBotModelPicker')) { 5720 return; 5721 } 5722 _this.bayesBotModelMenuOpen(false); 5723 }); 5724 var repositionModelMenu = function () { return _this.placeBayesBotModelMenu(); }; 5725 document.addEventListener('scroll', repositionModelMenu, true); 5726 window.addEventListener('resize', repositionModelMenu); 5727 void this.loadBayesBotUserModel(); 5728 this.selectedCanvasNodeId.subscribe(function () { return _this.scheduleLeaderboardScrollToSelection(); }); 5729 this.leaderboardPanelTab.subscribe(function () { 5730 if (_this.leaderboardPanelTab() === 'informationGain') { 5731 var self_1 = _this; 5732 setTimeout(function () { 5733 self_1.renderLifetimeInformationChart(); 5734 }, 50); 5735 } 5736 }); 5737 this.proposalLifetimeInformation.subscribe(function () {
5738 if (_this.leaderboardPanelTab() === 'informationGain') { 5739 var self_2 = _this; 5740 setTimeout(function () { 5741 self_2.renderLifetimeInformationChart(); 5742 }, 50); 5743 } 5744 }); 5745 var preloadBranches = function () { 5746 if (_this.showBranchTab()) { 5747 _this.loadBranchList(); 5748 } 5749 }; 5750 this.authorOwnsTemplate.subscribe(preloadBranches); 5751 this.isCreateMode.subscribe(preloadBranches); 5752 self.loadingSteps(false); 5753 var urlSid = this.parseSidFromUrl(); 5754 var bayesBotPage = !!(Distiller.isBayesBotUrl && Distiller.isBayesBotUrl()); 5755 var landingCreate = bayesBotPage && !urlSid; 5756 var draftCreate = !!urlSid && this.isDraftCreateUrl(); 5757 // sid on Bayes Bot is not "published." The URL flag is only an 5758 // optimistic create hint. Draft vs live is decided by draft-state: 5759 // this user owns a draft (including still-building) or they do not. 5760 var draftLifecycleCandidate = !!urlSid && (bayesBotPage || 5761 !!(Distiller.isBayesBotView && Distiller.isBayesBotView())); 5762 this.isCreateMode(landingCreate || draftCreate); 5763 if (landingCreate || draftCreate) { 5764 this.ensureCreateNetWorkbenchHeight(); 5765 } 5766 if (urlSid) { 5767 this.boundCommunityId(urlSid); 5768 } 5769 if (landingCreate || draftCreate) { 5770 this.applyHeaderMarkupImmediate(BAYES_BOT_CREATE_HEADER_MARKUP, BAYES_BOT_BAYES_NET_INFO); 5771 } 5772 if (params && params.questionSet) { 5773 this.questionSet(params.questionSet); 5774 } 5775 this.mountCanvasImmediately(); 5776 Distiller.showHideIfPayload([]); 5777 if (this.questionSet() && this.questionSet().pages && this.questionSet().pages().length > 0) { 5778 if (this.questionSet().pages()[0].stageWorkflows().length > 0) { 5779 if (this.questionSet().pages()[0].stageWorkflows().find(function (a) { return a.stage() == Distiller.currentUser().stageNumber(); })) { 5780 //set the current stage workflow = to the stage workflow that matches the current user's stage number 5781 this.currentStageWorkflow(this.questionSet().pages()[0].stageWorkflows().find(function (a) { return a.stage() == Distiller.currentUser().stageNumber(); })); 5782 } 5783 else if (this.questionSet().pages()[0].stageWorkflows().filter(function (a) { return a.stage() < Distiller.currentUser().stageNumber(); })) { 5784 //if there's not an exact match, present the last stage workflow that is less than the current user's stage number 5785 var latestStageWorkflow = this.questionSet().pages()[0].stageWorkflows().filter(function (a) { return a.stage() < Distiller.currentUser().stageNumber(); })[this.questionSet().pages()[0].stageWorkflows().filter(function (a) { return a.stage() < Distiller.currentUser().stageNumber(); }).length - 1]; 5786 this.currentStageWorkflow(latestStageWorkflow); 5787 } 5788 else { 5789 this.workflowUndefined(true); 5790 } 5791 } 5792 else { 5793 this.workflowUndefined(true); 5794 } 5795 } 5796 if (this.currentStageWorkflow()) { 5797 this.setVariableValues(); 5798 if (this.currentStageWorkflow().elements().filter(function (a) { return a.type === 'question'; }).length > 0) { 5799 AutoSave.addAutoSaveNumericQuestions(this.currentStageWorkflow().elements().filter(function (a) { return a.type === 'question' && a.question && a.question(); })); 5800 } 5801 // if menuItemsVisible is false, we need to add a next button if they don't already have one 5802 var existingNextButton = this.currentStageWorkflow().elements().find(function (a) { return a.type === 'button' && a.buttonType() && a.buttonType().value === 'nextPage'; }); 5803 if (!existingNextButton && Distiller.currentStageFeatures().leftMenuNav !== 'visible') { 5804 //add this even if there isn't a next set because 5805 //the next set can get added by a conditional branch 5806 var newElement = { 5807 type: 'button', 5808 view: ko.observable('button-view'), 5809 text: ko.observable(null), 5810 isUploadingPresentation: ko.observable(false), 5811 presentationUploadError: ko.observable(null), 5812 presentationUrl: ko.observable(null), 5813 quillDelta: ko.observable(null), 5814 uiParams: ko.observableArray([]), 5815 subElements: ko.observableArray([]), 5816 buttonType: ko.observable({ value: 'nextPage' }), 5817 buttonHTML: ko.observable('Next page'), 5818 buttonLink: ko.observable(null), 5819 buttonParams: ko.observableArray([]), 5820 isAutoAdded: 1 5821 }; 5822 this.currentStageWorkflow().elements.push(newElement); 5823 } 5824 var hasShowIfLogic = this.currentStageWorkflow().elements().some(function (a) { return a.uiParams().some(function (b) { return (b.value === 'showIf' || b.value === 'hideIf') && b.apply(); }); }); 5825 if (hasShowIfLogic) { 5826 var showHideIfPayload = []; 5827 var timeSpentThresholds_1 = []; 5828 //build {workflowIndex: index, action: 'showIf'/'hideIf', filtersJson: filtersJson} object 5829 for (var i = 0; i < this.currentStageWorkflow().elements().length; i++) { 5830 if (this.currentStageWorkflow().elements()[i].uiParams().find(function (a) { return a.value === 'showIf' && a.apply(); })) {
5831 var validationQueryData = this.getValidationQuery(this.currentStageWorkflow().elements()[i].uiParams().find(function (a) { return a.value === 'showIf'; }).filtersJson()); 5832 var row = { 5833 questionId: (_a = this.currentStageWorkflow().elements()[i].question()) === null || _a === void 0 ? void 0 : _a.questionId(), 5834 elementType: this.currentStageWorkflow().elements()[i].type, 5835 workflowIndex: i, 5836 action: 'showIf', 5837 filtersJson: this.currentStageWorkflow().elements()[i].uiParams().find(function (a) { return a.value === 'showIf'; }).filtersJson(), 5838 status: ko.observable('loading'), 5839 validationQuery: validationQueryData === null || validationQueryData === void 0 ? void 0 : validationQueryData.query, 5840 validationQuestionIds: validationQueryData === null || validationQueryData === void 0 ? void 0 : validationQueryData.questionIds, 5841 scrollTo: this.currentStageWorkflow().elements()[i].uiParams().find(function (a) { return a.value === 'showIf'; }).scrollTo 5842 }; 5843 if (!row.filtersJson) { 5844 continue; 5845 } 5846 var thresholds = Distiller.extractTimeSpentThresholds(row.filtersJson); 5847 if (thresholds.length > 0) { 5848 timeSpentThresholds_1.push.apply(timeSpentThresholds_1, thresholds); 5849 } 5850 showHideIfPayload.push(row); 5851 } 5852 if (this.currentStageWorkflow().elements()[i].uiParams().find(function (a) { return a.value === 'hideIf' && a.apply(); })) { 5853 var validationQueryData = this.getValidationQuery(this.currentStageWorkflow().elements()[i].uiParams().find(function (a) { return a.value === 'hideIf'; }).filtersJson()); 5854 var row = { 5855 questionId: (_b = this.currentStageWorkflow().elements()[i].question()) === null || _b === void 0 ? void 0 : _b.questionId(), 5856 elementType: this.currentStageWorkflow().elements()[i].type, 5857 workflowIndex: i, 5858 action: 'hideIf', 5859 filtersJson: this.currentStageWorkflow().elements()[i].uiParams().find(function (a) { return a.value === 'hideIf'; }).filtersJson(), 5860 status: ko.observable('loading'), 5861 validationQuery: validationQueryData.query, 5862 validationQuestionIds: validationQueryData.questionIds, 5863 }; 5864 if (!row.filtersJson) { 5865 continue; 5866 } 5867 var thresholds = Distiller.extractTimeSpentThresholds(row.filtersJson); 5868 if (thresholds.length > 0) { 5869 timeSpentThresholds_1.push.apply(timeSpentThresholds_1, thresholds); 5870 } 5871 showHideIfPayload.push(row); 5872 } 5873 } 5874 var uniqueThresholds = timeSpentThresholds_1.filter(function (item, index) { 5875 return timeSpentThresholds_1.indexOf(item) === index; 5876 }); 5877 uniqueThresholds = uniqueThresholds.filter(function (a) { return a >= Distiller.currentUser().totalTimeSpent(); }); 5878 Distiller.showHideIfTimeSpentThresholds(uniqueThresholds); 5879 Distiller.showHideIfPayload(showHideIfPayload); 5880 Distiller.evaluateShowHideIf(); 5881 } 5882 //pavel modal 5883 var matrixTableElements_1 = this.currentStageWorkflow().elements().filter(function (a) { return a.hasOwnProperty('generalQuestionType') && a.generalQuestionType() && a.generalQuestionType().value === 'matrixTable'; }); 5884 if (hasShowIfLogic 5885 && matrixTableElements_1.length > 1 5886 && matrixTableElements_1[0].uiParams().find(function (a) { return a.type === 'validation' && (a.value === 'orderRightMatrix' /* || a.value === 'orderLeftMatrix'*/); }) 5887 && matrixTableElements_1[0].question().answers().length === 2) { 5888 var confirmElement_1 = this.currentStageWorkflow().elements().find(function (a) { return a.generalQuestionType() && a.generalQuestionType().value === 'multipleChoice' && a.uiParams().find(function (b) { return b.value === 'showIf' && b.apply(); }); }); 5889 if (confirmElement_1) { 5890 confirmElement_1.question().answers()[0].currentUserForec
5890ast.subscribe(function (newValue) { 5891 if (newValue === 1) { 5892 if (matrixTableElements_1[0].question().answers()[1].currentUserForecast() === 1) { 5893 var match = matrixTableElements_1[0].question().name().match(/-?\d+(\.\d+)?/); 5894 var firstNumber = match ? parseFloat(match[0]) : null; 5895 if (!isNaN(firstNumber)) { 5896 _this.referenceValueForModal(firstNumber); 5897 var firstMatrixQuestions = [matrixTableElements_1[0].question()]; 5898 for (var i = 0; i < matrixTableElements_1[0].question().timepointQuestions().length; i++) { 5899 firstMatrixQuestions.push(matrixTableElements_1[0].question().timepointQuestions()[i]); 5900 } 5901 _this.firstMatrixQuestions(firstMatrixQuestions); 5902 _this.confirmMatrixQuestion(confirmElement_1.question()); 5903 _this.showingWorkflowModal('menuElicitation1'); 5904 } 5905 } 5906 } 5907 }); 5908 } 5909 } 5910 // if (hasShowIfLogic && this.currentStageWorkflow().elements().find(a => a.generalQuestionType === 'matrixTable') 5911 /* let urlParams = new URLSearchParams(window.location.search); 5912 let devIndices: any = urlParams.get('devIndices'); 5913 if (devIndices && Distiller.isJsonString(devIndices)) { 5914 devIndices = JSON.parse(devIndices); 5915 Distiller.devIndices(devIndices); 5916 } */ 5917 } 5918 this.mountCanvasImmediately(); 5919 var afterAgentKey = function () { 5920 if (!_this.isCreateMode()) { 5921 _this.loadAuthorBayesNet(); 5922 _this.loadLeaderboard(); 5923 } 5924 _this.connectBayesBotSse(); 5925 }; 5926 if (landingCreate) { 5927 if (!Distiller.bayesBotLandingProvisionPromise && 5928 !Distiller.bayesBotLandingHandoff) { 5929 void this.provisionDraftStudy(); 5930 } 5931 } 5932 else if (draftCreate || draftLifecycleCandidate) { 5933 void this.initializeDraftStudy(); 5934 } 5935 else { 5936 var timeout = new Promise(function (resolve) { 5937 setTimeout(resolve, 4000); 5938 }); 5939 Promise.race([this.ensureAgentKey(), timeout]).then(afterAgentKey).catch(afterAgentKey); 5940 } 5941 var loggedInBody = document.getElementById('loggedInBody2'); 5942 if (loggedInBody) { 5943 loggedInBody.scrollTop = 0; 5944 } 5945 window.scrollTo(0, 0); 5946 if (this.currentStageWorkflow()) { 5947 } 5948 //cache whether they're scrolled to bottom here. it should start as false on load of the page. 5949 if (Distiller.setOfVisibleQuestion() && Distiller.setOfVisibleQuestion().highlightRequired()) { 5950 Distiller.scrolledToBottom.subscribe(function (newValue) { 5951 if (newValue) { 5952 _this.highlightRequired(true); 5953 } 5954 }); 5955 } 5956 } 5957 BayesBot.prototype.escapeRegExp = function (string) { 5958 return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 5959 }; 5960 BayesBot.prototype.waitForAutosave = function () { 5961 return __awaiter(this, void 0, void 0, function () { 5962 var _this = this; 5963 return __generator(this, function (_a) { 5964 return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () { 5965 return __generator(this, function (_a) { 5966 if (!Distiller.autoSaving()) { 5967 resolve('done'); 5968 } 5969 else { 5970 Distiller.autoSaving.subscribe(function (newValue) { 5971 if (!newValue) { 5972 resolve('done'); 5973 } 5974 }); 5975 } 5976 return [2 /*return*/]; 5977 }); 5978 }); })]; 5979 }); 5980 }); 5981 }; 5982 BayesBot.prototype.getQuestionReferenceValues = function (questionReferences) { 5983 return __awaiter(this, void 0, void 0, function () { 5984 var self; 5985 var _this = this; 5986 return __generator(this, function (_a) { 5987 self = this; 5988 return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () { 5989 return __generator(this, function (_a) { 5990 switch (_a.label) { 5991 case 0: 5992 if (!Distiller.autoSaving()) return [3 /*break*/, 2]; 5993 return [4 /*yield*/, self.waitForAutosave()]; 5994 case 1: 5995 _a.sent(); 5996 _a.label = 2; 5997 case 2: 5998 Distiller.httpSendAsync(Distiller.apiEndpoint + "/api/getQuestionReferenceValues/" + Distiller.currentUser().userId, JSON.stringify(questionReferences), function (response) { 5999 response = JSON.parse(response); 6000 if (response.err) { 6001 alert("Oops! Something went wrong when we tried to construct these questions. Please email [email protected] to report this error right away."); 6002 resolve(response); 6003 return; 6004 } 6005 resolve(response.data); 6006 }); 6007 return [2 /*return*/]; 6008 } 6009 }); 6010 }); })]; 6011 }); 6012 }); 6013 }; 6014 BayesBot.prototype.extractExpressionSubstrings = function (str) { 6015 var regex = /\$e{[^}]*}/g; 6016 return str.match(regex) || []; 6017 }; 6018 BayesBot.prototype.evaluateMathExpression = function (expression) { 6019 // Remove leading "$e{" and trailing "}" if they exist 6020 expression = expression.replace(/^\$e\{|\}$/g, ''); 6021 var self = this; 6022 // Dynamically evaluate mathematical functions within an expression 6023 function evaluateFunctions(exp) { 6024 // Function to evaluate arguments before applying the outer function 6025 function evaluateArgsAndApplyFunction(args, applyFunction) { 6026 var argsArray = self.splitArgsConsideringNesting(
6026args); 6027 var evaluatedArgs = argsArray.map(function (arg) { return evaluateFunctions(arg); }); 6028 // Apply the function to the evaluated arguments 6029 return applyFunction(evaluatedArgs).toString(); 6030 } 6031 // Iteratively apply patterns to replace mathematical expressions 6032 var modifiedExp = exp, matched; 6033 do { 6034 matched = false; 6035 var hasFunctionsOrCommas = /max|min|sqrt|abs|round|,/.test(modifiedExp); 6036 if (!hasFunctionsOrCommas) { 6037 matched = true; 6038 try { 6039 //fix for Bridget june 6 2025 6040 if (isOnlyMultiplication(modifiedExp)) { 6041 var numberOfDecimalPlaces = sumDecimalPlaces(modifiedExp); 6042 var result = eval(modifiedExp); 6043 return parseFloat(result.toFixed(numberOfDecimalPlaces)); 6044 } 6045 return eval(modifiedExp).toString(); 6046 } 6047 catch (error) { 6048 return 'Error: ' + error.message; 6049 } 6050 } 6051 // Handle max() with proper nested parentheses support 6052 while (modifiedExp.includes('max(')) { 6053 var maxStart = modifiedExp.indexOf('max('); 6054 if (maxStart === -1) 6055 break; 6056 var depth = 1; 6057 var i = maxStart + 4; // Start after 'max(' 6058 var args = ''; 6059 while (depth > 0 && i < modifiedExp.length) { 6060 var char = modifiedExp[i]; 6061 if (char === '(') 6062 depth++; 6063 else if (char === ')') 6064 depth--; 6065 if (depth > 0) 6066 args += char; 6067 i++; 6068 } 6069 var fullMatch = 'max(' + args + ')'; 6070 matched = true; 6071 var replacement = evaluateArgsAndApplyFunction(args, function (evaluatedArgs) { return Math.max.apply(Math, evaluatedArgs.map(parseFloat)); }); 6072 // Replace only the first occurrence to avoid infinite loops 6073 modifiedExp = modifiedExp.substring(0, maxStart) + replacement + modifiedExp.substring(maxStart + fullMatch.length); 6074 } 6075 // Handle min() with proper nested parentheses support 6076 while (modifiedExp.includes('min(')) { 6077 var minStart = modifiedExp.indexOf('min('); 6078 if (minStart === -1) 6079 break; 6080 var depth = 1; 6081 var i = minStart + 4; // Start after 'min(' 6082 var args = ''; 6083 while (depth > 0 && i < modifiedExp.length) { 6084 var char = modifiedExp[i]; 6085 if (char === '(') 6086 depth++; 6087 else if (char === ')') 6088 depth--; 6089 if (depth > 0) 6090 args += char; 6091 i++; 6092 } 6093 var fullMatch = 'min(' + args + ')'; 6094 matched = true; 6095 var replacement = evaluateArgsAndApplyFunction(args, function (evaluatedArgs) { return Math.min.apply(Math, evaluatedArgs.map(parseFloat)); }); 6096 // Replace only the first occurrence to avoid infinite loops 6097 modifiedExp = modifiedExp.substring(0, minStart) + replacement + modifiedExp.substring(minStart + fullMatch.length); 6098 } 6099 // Handle sqrt() with proper nested parentheses support 6100 while (modifiedExp.includes('sqrt(')) { 6101 var sqrtStart = modifiedExp.indexOf('sqrt('); 6102 if (sqrtStart === -1) 6103 break; 6104 var depth = 1; 6105 var i = sqrtStart + 5; // Start after 'sqrt(' 6106 var args = ''; 6107 while (depth > 0 && i < modifiedExp.length) { 6108 var char = modifiedExp[i]; 6109 if (char === '(') 6110 depth++; 6111 else if (char === ')') 6112 depth--; 6113 if (depth > 0) 6114 args += char; 6115 i++; 6116 }
6117 var fullMatch = 'sqrt(' + args + ')'; 6118 matched = true; 6119 var replacement = evaluateArgsAndApplyFunction(args, function (evaluatedArgs) { return Math.sqrt(evaluatedArgs[0]); }); 6120 // Replace only the first occurrence to avoid infinite loops 6121 modifiedExp = modifiedExp.substring(0, sqrtStart) + replacement + modifiedExp.substring(sqrtStart + fullMatch.length); 6122 } 6123 // Handle abs() with proper nested parentheses support 6124 while (modifiedExp.includes('abs(')) { 6125 var absStart = modifiedExp.indexOf('abs('); 6126 if (absStart === -1) 6127 break; 6128 var depth = 1; 6129 var i = absStart + 4; // Start after 'abs(' 6130 var args = ''; 6131 while (depth > 0 && i < modifiedExp.length) { 6132 var char = modifiedExp[i]; 6133 if (char === '(') 6134 depth++; 6135 else if (char === ')') 6136 depth--; 6137 if (depth > 0) 6138 args += char; 6139 i++; 6140 } 6141 var fullMatch = 'abs(' + args + ')'; 6142 matched = true; 6143 var replacement = evaluateArgsAndApplyFunction(args, function (evaluatedArgs) { return Math.abs(evaluatedArgs[0]); }); 6144 // Replace only the first occurrence to avoid infinite loops 6145 modifiedExp = modifiedExp.substring(0, absStart) + replacement + modifiedExp.substring(absStart + fullMatch.length); 6146 } 6147 // Handle round() with proper nested parentheses support 6148 while (modifiedExp.includes('round(')) { 6149 var roundStart = modifiedExp.indexOf('round('); 6150 if (roundStart === -1) 6151 break; 6152 var depth = 1; 6153 var i = roundStart + 6; // Start after 'round(' 6154 var args = ''; 6155 while (depth > 0 && i < modifiedExp.length) { 6156 var char = modifiedExp[i]; 6157 if (char === '(') 6158 depth++; 6159 else if (char === ')') 6160 depth--; 6161 if (depth > 0) 6162 args += char; 6163 i++; 6164 } 6165 var fullMatch = 'round(' + args + ')'; 6166 matched = true; 6167 // Split the arguments considering nesting, and then evaluate them 6168 var arrayOfArgs = self.splitArgsConsideringNesting(args).map(function (arg) { return evaluateFunctions(arg); }); 6169 var replacement = void 0; 6170 if (arrayOfArgs.length > 1) { 6171 // Now, correctly parse the number to round and the decimal places 6172 var numToRound = parseFloat(arrayOfArgs[0]); 6173 var decimalPlaces = parseInt(arrayOfArgs[1]); 6174 var roundedValue = Number(numToRound.toFixed(decimalPlaces)); 6175 replacement = roundedValue.toString(); 6176 } 6177 else { 6178 // If there's only one argument, round it to the nearest integer 6179 var numToRound = parseFloat(arrayOfArgs[0]); 6180 replacement = Math.round(numToRound).toString(); 6181 } 6182 // Replace only the first occurrence to avoid infinite loops 6183 modifiedExp = modifiedExp.substring(0, roundStart) + replacement + modifiedExp.substring(roundStart + fullMatch.length); 6184 } 6185 } while (matched); 6186 return modifiedExp; 6187 } 6188 // Replace "^" with "**" for exponentiation 6189 expression = expression.replace(/\^/g, '**'); 6190 // Dynamically evaluate functions within the expression 6191 expression = evaluateFunctions(expression); 6192 function isOnlyMultiplication(expr) { 6193 // Must only contain numbers, decimal points, whitespace, and single * operators 6194 // Disallow **, /, +, -, %, etc. 6195 var invalidOperators = /[+\-/()%]|[*]{2,}/;
6196 var validCharacters = /^[\d.\s*]+$/; 6197 return validCharacters.test(expr) && !invalidOperators.test(expr); 6198 } 6199 function sumDecimalPlaces(expr) { 6200 // Match all numbers, including those like .5, 0.123, 5., 10.0, etc. 6201 var numberPattern = /(?:\d*\.\d+|\d+\.)/g; 6202 var totalDecimals = 0; 6203 var matches = expr.match(numberPattern); 6204 if (!matches) 6205 return 0; 6206 for (var _i = 0, matches_1 = matches; _i < matches_1.length; _i++) { 6207 var numStr = matches_1[_i]; 6208 var decimalPart = numStr.split('.')[1]; 6209 if (decimalPart) { 6210 totalDecimals += decimalPart.length; 6211 } 6212 } 6213 return totalDecimals; 6214 } 6215 try { 6216 // Use eval to evaluate the simplified expression 6217 var result = eval(expression); 6218 // Check if the result is a finite number 6219 if (typeof result === 'number' && isFinite(result)) { 6220 return result; 6221 } 6222 else { 6223 throw new Error('Invalid result'); 6224 } 6225 } 6226 catch (error) { 6227 return 'Error: ' + error.message; 6228 } 6229 }; 6230 BayesBot.prototype.splitArgsConsideringNesting = function (args) { 6231 var argsArray = []; 6232 var currentArg = ''; 6233 var depth = 0; // Depth of nested parentheses 6234 for (var i = 0; i < args.length; i++) { 6235 var char = args[i]; 6236 if (char === '(') 6237 depth++; 6238 if (char === ')') 6239 depth--; 6240 // If we encounter a comma and are not inside nested parentheses, split here 6241 if (char === ',' && depth === 0) { 6242 argsArray.push(currentArg.trim()); 6243 currentArg = ''; 6244 } 6245 else { 6246 currentArg += char; 6247 } 6248 } 6249 // Add the last argument (or only argument if no commas were found) to the array 6250 if (currentArg !== '') 6251 argsArray.push(currentArg.trim()); 6252 return argsArray; 6253 }; 6254 BayesBot.prototype.getValidationQuery = function (query) { 6255 var response = { 6256 query: undefined, 6257 questionIds: [] 6258 }; 6259 if (!query) { 6260 return undefined; 6261 } 6262 for (var i = 0; i < query.rules.length; i++) { 6263 // console.log("rule " + JSON.stringify(rule)); 6264 if (query.rules[i].id === 'submission' && query.rules[i].value && (query.rules[i].value.includes('_valid') || query.rules[i].value.includes('_invalid'))) { 6265 var params = []; 6266 if (Distiller.isJsonString(query.rules[i].value) && Array.isArray(JSON.parse(query.rules[i].value))) { 6267 params = JSON.parse(query.rules[i].value); 6268 } 6269 else { 6270 params = query.rules[i].value.split('.'); 6271 } 6272 var evaluatingFor = 'valid_submission'; 6273 if (query.rules[i].value.includes('_invalid')) { 6274 evaluatingFor = 'invalid_submission'; 6275 } 6276 if (params.length > 1) { 6277 var newQuestionId = parseInt(params[1]); 6278 if (response.questionIds.indexOf(newQuestionId) < 0) { 6279 response.questionIds.push(newQuestionId); 6280 } 6281 query.rules[i].isValid = ko.observable(-1); //default to incomplete 6282 query.rules[i].evaluatingFor = evaluatingFor; 6283 } 6284 } 6285 else if (query.rules[i].rules && Array.isArray(query.rules[i].rules)) { 6286 var validationSubqueryData = this.getValidationQuery(query.rules[i]); 6287 for (var q = 0; q < validationSubqueryData.questionIds.length; q++) { 6288 if (response.questionIds.indexOf(validationSubqueryData.questionIds[q]) < 0) { 6289 response.questionIds.push(validationSubqueryData.questionIds[q]); 6290 } 6291 } 6292 query.rules[i] = validationSubqueryData.query; 6293 } 6294 } 6295 response.query = query; 6296 return response; 6297 }; 6298 BayesBot.LIFETIME_CHART_MIN_HEIGHT_PX = 200; 6299 BayesBot.BRANCH_ROW_HEIGHT_PX = 39; 6300 BayesBot.AGENT_ACTIVITY_SPINNER_FRAMES = ['⣾', '⣽', '⣻', '⢿', 'â¡¿', 'â£', '⣯', '⣷']; 6301 BayesBot.BRAILLE_CELL_COUNT = 9; 6302 BayesBot.isLocalhostDev = function () { 6303 var href = String((typeof window !== 'undefined' && window.location && window.location.href) || ''); 6304 var host = String((typeof window !== 'undefined' && window.location && window.location.hostname) || '').toLowerCase(); 6305 return (host === 'localhost' || 6306 host === '127.0.0.1' || 6307 host.indexOf('localhost') >= 0 || 6308 href.indexOf('localhost') > -1 || 6309 href.indexOf('127.0.0.1') > -1); 6310 }; 6311 return BayesBot; 6312}()); 6313export default BayesBot;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.