Implementing weighted random

This commit is contained in:
David Masad
2021-02-27 13:38:30 -05:00
parent 4aaa247cb3
commit 04f613a5b1
4 changed files with 156 additions and 20 deletions
+37 -3
View File
@@ -123,7 +123,8 @@ StoryManager.getAllStorylets = function(tag=null) {
return allStorylets; return allStorylets;
} }
StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { StoryManager.getStorylets =
function(n=null, tag=null, selection="ordered", respect_interrupt=true) {
/* /*
Get n storylets, prioritizing the highest-priority ones first. Get n storylets, prioritizing the highest-priority ones first.
@@ -143,12 +144,24 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) {
if (allStorylets[i].interrupt) return [allStorylets[i]]; if (allStorylets[i].interrupt) return [allStorylets[i]];
} }
// Get n stories in priority order // Return n or the max
if (n != null) { if (n != null) {
n = Math.min(n, allStorylets.length); n = Math.min(n, allStorylets.length);
if (n == 0) return []; if (n == 0) return [];
} }
else n = allStorylets.length; else n = allStorylets.length;
let selectedStorylets;
if (selection == "ordered")
selectedStorylets = this.sortByPriority(allStorylets, n);
else if (selection == "weighted")
selectedStorylets = this.weightedRandom(allStorylets, n);
return selectedStorylets;
}
// Get storylets strictly by priority
StoryManager.sortByPriority = function(allStorylets, n) {
let selectedStorylets = []; let selectedStorylets = [];
// Select by strict priority; randomize among matching priority. // Select by strict priority; randomize among matching priority.
@@ -166,8 +179,29 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) {
return selectedStorylets; return selectedStorylets;
} }
// Set up macros // Get storylets via weighted random choice
StoryManager.weightedRandom = function(allStorylets, n) {
let selectedStorylets = [];
let sum, counter, index, rand;
while (selectedStorylets.length < n) {
sum = allStorylets.reduce((a, x) => a + x.priority, 0);
counter = 0;
rand = Math.random() * sum;
for (let i=0; i<allStorylets.length; i++) {
if (counter + allStorylets[i].priority) {
selectedStorylets.push(allStorylets.splice(i, 1));
break;
}
counter += allStorylets[i].priority;
}
}
return selectedStorylets;
}
// Set up macros
// ---------------------------------------------------------------
Macro.add("getStoryletLinks", { Macro.add("getStoryletLinks", {
handler: function() { handler: function() {
let n, tag; let n, tag;
+41 -7
View File
@@ -123,7 +123,8 @@ StoryManager.getAllStorylets = function(tag=null) {
return allStorylets; return allStorylets;
} }
StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { StoryManager.getStorylets =
function(n=null, tag=null, selection="ordered", respect_interrupt=true) {
/* /*
Get n storylets, prioritizing the highest-priority ones first. Get n storylets, prioritizing the highest-priority ones first.
@@ -143,12 +144,24 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) {
if (allStorylets[i].interrupt) return [allStorylets[i]]; if (allStorylets[i].interrupt) return [allStorylets[i]];
} }
// Get n stories in priority order // Return n or the max
if (n != null) { if (n != null) {
n = Math.min(n, allStorylets.length); n = Math.min(n, allStorylets.length);
if (n == 0) return []; if (n == 0) return [];
} }
else n = allStorylets.length; else n = allStorylets.length;
let selectedStorylets;
if (selection == "ordered")
selectedStorylets = this.sortByPriority(allStorylets, n);
else if (selection == "weighted")
selectedStorylets = this.weightedRandom(allStorylets, n);
return selectedStorylets;
}
// Get storylets strictly by priority
StoryManager.sortByPriority = function(allStorylets, n) {
let selectedStorylets = []; let selectedStorylets = [];
// Select by strict priority; randomize among matching priority. // Select by strict priority; randomize among matching priority.
@@ -166,19 +179,40 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) {
return selectedStorylets; return selectedStorylets;
} }
// Set up macros // Get storylets via weighted random choice
StoryManager.weightedRandom = function(allStorylets, n) {
let selectedStorylets = [];
let sum, counter, index, rand;
while (selectedStorylets.length < n) {
sum = allStorylets.reduce((a, x) => a + x.priority, 0);
counter = 0;
rand = Math.random() * sum;
for (let i=0; i<allStorylets.length; i++) {
if (counter + allStorylets[i].priority) {
selectedStorylets.push(allStorylets.splice(i, 1));
break;
}
counter += allStorylets[i].priority;
}
}
return selectedStorylets;
}
// Set up macros
// ---------------------------------------------------------------
Macro.add("getStoryletLinks", { Macro.add("getStoryletLinks", {
handler: function() { handler: function() {
let n, tag; let n, tag;
[n=null, tag=null] = this.args; [n=null, tag=null] = this.args;
State.temporary.nextStorylets = StoryManager.getStorylets(n, tag); State.temporary.nextStorylets = StoryManager.getStorylets(n, tag);
$(this.output).wiki(` $(this.output).wiki(`
<<for _storylet range _nextStorylets>> <<for _storylet range _nextStorylets>> \
<<capture _storylet>> <<capture _storylet>> \
[[_storylet.description|_storylet.passage][$currentStorylet=_storylet]]<br> [[_storylet.description|_storylet.passage][$currentStorylet=_storylet]]<br>
<</capture>> <</capture>> \
<</for>> <</for>> \
`); `);
} }
}) })
+41 -7
View File
@@ -123,7 +123,8 @@ StoryManager.getAllStorylets = function(tag=null) {
return allStorylets; return allStorylets;
} }
StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { StoryManager.getStorylets =
function(n=null, tag=null, selection="ordered", respect_interrupt=true) {
/* /*
Get n storylets, prioritizing the highest-priority ones first. Get n storylets, prioritizing the highest-priority ones first.
@@ -143,12 +144,24 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) {
if (allStorylets[i].interrupt) return [allStorylets[i]]; if (allStorylets[i].interrupt) return [allStorylets[i]];
} }
// Get n stories in priority order // Return n or the max
if (n != null) { if (n != null) {
n = Math.min(n, allStorylets.length); n = Math.min(n, allStorylets.length);
if (n == 0) return []; if (n == 0) return [];
} }
else n = allStorylets.length; else n = allStorylets.length;
let selectedStorylets;
if (selection == "ordered")
selectedStorylets = this.sortByPriority(allStorylets, n);
else if (selection == "weighted")
selectedStorylets = this.weightedRandom(allStorylets, n);
return selectedStorylets;
}
// Get storylets strictly by priority
StoryManager.sortByPriority = function(allStorylets, n) {
let selectedStorylets = []; let selectedStorylets = [];
// Select by strict priority; randomize among matching priority. // Select by strict priority; randomize among matching priority.
@@ -166,19 +179,40 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) {
return selectedStorylets; return selectedStorylets;
} }
// Set up macros // Get storylets via weighted random choice
StoryManager.weightedRandom = function(allStorylets, n) {
let selectedStorylets = [];
let sum, counter, index, rand;
while (selectedStorylets.length < n) {
sum = allStorylets.reduce((a, x) => a + x.priority, 0);
counter = 0;
rand = Math.random() * sum;
for (let i=0; i<allStorylets.length; i++) {
if (counter + allStorylets[i].priority) {
selectedStorylets.push(allStorylets.splice(i, 1));
break;
}
counter += allStorylets[i].priority;
}
}
return selectedStorylets;
}
// Set up macros
// ---------------------------------------------------------------
Macro.add("getStoryletLinks", { Macro.add("getStoryletLinks", {
handler: function() { handler: function() {
let n, tag; let n, tag;
[n=null, tag=null] = this.args; [n=null, tag=null] = this.args;
State.temporary.nextStorylets = StoryManager.getStorylets(n, tag); State.temporary.nextStorylets = StoryManager.getStorylets(n, tag);
$(this.output).wiki(` $(this.output).wiki(`
<<for _storylet range _nextStorylets>> <<for _storylet range _nextStorylets>> \
<<capture _storylet>> <<capture _storylet>> \
[[_storylet.description|_storylet.passage][$currentStorylet=_storylet]]<br> [[_storylet.description|_storylet.passage][$currentStorylet=_storylet]]<br>
<</capture>> <</capture>> \
<</for>> <</for>> \
`); `);
} }
}) })
+37 -3
View File
@@ -20,7 +20,8 @@ StoryManager.getAllStorylets = function(tag=null) {
return allStorylets; return allStorylets;
} }
StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) { StoryManager.getStorylets =
function(n=null, tag=null, selection="ordered", respect_interrupt=true) {
/* /*
Get n storylets, prioritizing the highest-priority ones first. Get n storylets, prioritizing the highest-priority ones first.
@@ -40,12 +41,24 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) {
if (allStorylets[i].interrupt) return [allStorylets[i]]; if (allStorylets[i].interrupt) return [allStorylets[i]];
} }
// Get n stories in priority order // Return n or the max
if (n != null) { if (n != null) {
n = Math.min(n, allStorylets.length); n = Math.min(n, allStorylets.length);
if (n == 0) return []; if (n == 0) return [];
} }
else n = allStorylets.length; else n = allStorylets.length;
let selectedStorylets;
if (selection == "ordered")
selectedStorylets = this.sortByPriority(allStorylets, n);
else if (selection == "weighted")
selectedStorylets = this.weightedRandom(allStorylets, n);
return selectedStorylets;
}
// Get storylets strictly by priority
StoryManager.sortByPriority = function(allStorylets, n) {
let selectedStorylets = []; let selectedStorylets = [];
// Select by strict priority; randomize among matching priority. // Select by strict priority; randomize among matching priority.
@@ -63,8 +76,29 @@ StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true) {
return selectedStorylets; return selectedStorylets;
} }
// Set up macros // Get storylets via weighted random choice
StoryManager.weightedRandom = function(allStorylets, n) {
let selectedStorylets = [];
let sum, counter, index, rand;
while (selectedStorylets.length < n) {
sum = allStorylets.reduce((a, x) => a + x.priority, 0);
counter = 0;
rand = Math.random() * sum;
for (let i=0; i<allStorylets.length; i++) {
if (counter + allStorylets[i].priority) {
selectedStorylets.push(allStorylets.splice(i, 1));
break;
}
counter += allStorylets[i].priority;
}
}
return selectedStorylets;
}
// Set up macros
// ---------------------------------------------------------------
Macro.add("getStoryletLinks", { Macro.add("getStoryletLinks", {
handler: function() { handler: function() {
let n, tag; let n, tag;