(JavaScript) Random Text Output - Suggestions? - javascript

So what I have is http://garrettstelly.com which spits out one of twenty terms at startup. The code is very heavy, and I'm fine with that.
I plan on making a website to spit out a name at random, the problem is that I can have an endless amount of names. For the js that I'm using currently, I'm using a random roll and even portions between 0 and 1 to read the names. The problem with that is that I can't ever add just one phrase, I'll have to add a chunk all at once for the probabilities to be even.
How can I make a script with an endless amount of possibilities to be added one at a time?
here's the javascript for garrettstelly.com:
var roll = Math.random()
if (roll<0.05)
{document.write('Bro-Heem');}
else if (roll<0.10)
{document.write('I am too white for my own good');}
else if (roll<0.15)
{document.write('I love the way you paste those stickers.');}
else if (roll<0.20)
{document.write('You probably were not just thinking about Wichita');}
else if (roll<0.25)
{document.write('Yummy, Adhesive!');}
else if (roll<0.30)
{document.write('Rolex');}
else if (roll<0.35)
{document.write('There is a 5% chance that you will see this when you first visit this website.');}
else if (roll<0.40)
{document.write('Making Money.<br>Choppas How We Do Today.');}
else if (roll<0.45)
{document.write('45, get your bills roll em high.');}
else if (roll<0.50)
{document.write('I WILL teach you how to fish');}
else if (roll<0.55)
{document.write('I am a gangsta.');}
else if (roll<0.60)
{document.write('Please get out of my website');}
else if (roll<0.65)
{document.write('derriere');}
else if (roll<0.70)
{document.write('I think YOU are a Q T PIE');}
else if (roll<0.75)
{document.write('X=Fries');}
else if (roll<0.80)
{document.write("Idle hands are the Devil's playground.<br>The Devil is smaller than hands.");}
else if (roll<0.85)
{document.write('I am about to be late for class');}
else if (roll<0.90)
{document.write('"Hipster"');}
else if (roll<0.95)
{document.write('I am late for class');}
else
{document.write('Please refrain from drinking the water located within the wishing well, thank you.');}

Store the possibilities in an array and get a random element of the array:
Demo
function getRandomName()
{
var names = [
'John',
'Sue',
'Bob',
'Sandeep'
];
return names[Math.floor(Math.random() * names.length)];
}
document.write( getRandomName() );

You should put all the things you want spit out into an array. For example:
var arr = [
'Bro-Heem',
'I am too white for my own good',
// other entries...
'Please refrain from drinking the water located within the wishing well, thank you.'
];
Then your roll should still be Math.random() but multiplied by the length of the array:
var roll = (Math.floor(Math.random()) * arr.length);
Then write your result with the appropriate array index, in your case by using document.write (though there may be better ways):
document.write(arr[roll]);
Now you can add to your array as much as you like.

I would use an array:
var outputTextArr = ['text 1', 'text 2', 'text 3', 'text 4', 'more text', 'some text'];
Then randomly target the items in the array:
function randomRange(from, to){
return Math.floor(Math.random() * (to - from + 1) + from);
}
var outputText = outputTextArr[randomRange(0, outputTextArr.length - 1)];//var output text will have a random item

Something like this should work
var sentences =
[
"I am too white for my own good",
"I love the way you paste those stickers.",
"You probably were not just thinking about Wichita"
// Add more sentences if you want to
];
var index = Math.floor(Math.random() * sentences.length);
alert(sentences[index]); // This will be your random value
CodePen example.

Related

trying to get the most used word using regex

I am trying to get 10 most frequent word in the sentence below, I need to use regular expression.
let paragraph = `I love teaching. If you do not love teaching what else can you love. I love Python if you do not love something which can give you all the capabilities to develop an application what else can you love.
I want an output like this
{word:'love', count:6},
{word:'you', count:5},
{word:'can', count:3},
{word:'what', count:2},
{word:'teaching', count:2},
{word:'not', count:2},
{word:'else', count:2},
{word:'do', count:2},
{word:'I', count:2},
{word:'which', count:1},
{word:'to', count:1},
{word:'the', count:1},
{word:'something', count:1},
{word:'if', count:1},
{word:'give', count:1},
{word:'develop',count:1},
{word:'capabilities',count:1},
{word:'application', count:1},
{word:'an',count:1},
{word:'all',count:1},
{word:'Python',count:1},
{word:'If',count:1}]```
This is a solution without regexp, but maybe it is also worth looking at?
const paragraph = `I love teaching. If you do not love teaching what else can you love. I love Python if you do not love something which can give you all the capabilities to develop an application what else can you love.`;
let res=Object.entries(
paragraph.toLowerCase()
.split(/[ .,;-]+/)
.reduce((a,c)=>(a[c]=(a[c]||0)+1,a), {})
).map(([k,v])=>({word:k,count:v})).sort((a,b)=>b.count-a.count)
console.log(res.slice(0,10)) // only get the 10 most frequent words
I have something a bit messy but it uses regex and displays top 10 of the highest occuring results which is what you asked for.
Test it and let me know if it works for you.
let paragraph = "I love teaching. If you do not love teaching what else can you love. I love Python if you do not love something which can give you all the capabilities to develop an application what else can you love.";
//remove periods, because teaching and teaching. will appear as different results set
paragraph = paragraph.split(".").join("");
//results array where results will be stored
var results = []
//separate each string from the paragraph
paragraph.split(" ").forEach((word) => {
const wordCount = paragraph.match(new RegExp(word,"g")).length
//concatenate the word to its occurence:: e.g I:3 ::meaning I has appeared 3 times
const res = word + " : " + wordCount;
//check if the word has been added to results
if(!results.includes(res)){
//if not, push
results.push(res)
}
})
function sortResultsByOccurences(resArray) {
//we use a sort function to sort our results into order: highest occurence to lowest
resArray.sort(function(a, b) {
///\D/g is regex that removes anything that's not a digit, so that we can sort by occurences instead of letters as well
return(parseInt(b.replace(/\D/g, ""), 10) -
parseInt(a.replace(/\D/g, ""), 10));
});
//10 means we are using a decimal number system
return(resArray);
}
//reassign results as sorted
results = sortResultsByOccurences(results);
for(let i = 0; i < 10; i++){//for loop is used to display top 10
console.log(results[i])
}
To get all words in a sentence use regular expressions:
/(\w+)(?=\s)/g.
If you use this in your input string then you get all words without the word which end with full-stop(.) i.e don't match the word "love.".
paragraph.match(/(\w+)(?=(\s|\.|\,|\;|\?))/gi)
So, in this case we have to modify the regex as:
/(\w+)(?=(\s|\.))/g.
Similarly, add the other special(,; ...) character which is end with some word.
This is your solution (please add the other special character if it's required).
let paragraph = `I love teaching. If you do not love teaching what else can you love. I love Python if you do not love something which can give you all the capabilities to develop an application what else can you love.`;
let objArr = [];
[...new Set(paragraph.match(/(\w+)(?=(\s|\.|\,|\;|\?))/gi))].forEach(ele => {
objArr.push({
'word': ele,
'count': paragraph.match(new RegExp(ele+'(?=(\\s|\\.|\\,|\\;|\\?))', 'gi'))?.length
})
});
objArr.sort((x,y) => y.count - x.count);

removeStr.indexOf not removing all requested elements

I am still very much learning Javascript/Google Apps Script, but have created a javascript which takes certain google sheets relating to orders for a business, removes certain data not needed and then creates a list of the remaining ordered items by each item. This has all worked well for the first two of these google sheets, but when I come to the the third, I have an issue in that the removeStr.indexOf is not removing all the data I would expect it too and was therefore hoping someone could tell me where I am going wrong please?
Here is an image of the raw data reduced to fit
From the above the function firstly creates an array which produces the following
Status,NaN,Date Submitted,NaN,Name,NaN,Phone,NaN,Delivery Required?,NaN,Address ,NaN,GLATT SUMMARY,NaN,MH SUMMARY,NaN,GILBERTS SUMMARY,NaN,SMOKED SALMON SUMMARY,NaN,DOVIDS SUMMARY,NaN,Roaster,3,Wrapped Cut Up,1,Wrapped Cut Up Skinned,0,Carcus
,0,Half Hen,0,Mince,0,Lean Mince,2,Chicken Mince,0,Chicken Wings (8),0,Drumsticks (4),1,Thighs (4),0,Breasts (2),4,Pargiot (6),0,Hinds (2),0,Cumberland,2,Burger (4),0,Diced Steak,2,Fairy Steaks (Pack),1,Ribeye Steak,0,Bola,0,Lamb Chops (4),3,Shoulder Chops (2),0,Lamb Shanks (2),0,Shoulder Lamb (off bone),0,Shoulder Lamb (bone in),0,Turkey Thigh,0,Turkey Leg,0,Roaster Crown,0,Roaster in Tin,0,Meatballs 12,0,Meatballs Family,0,Lamb Shwarma,0,Thick Chops (4),0,Salmon 200g,1,Salmon 100g,2,Gefilte,0,Fishball (L),0,Fishball (S),0,ADDITIONAL ITEMS? (subject to availability),NaN
From the above array, the next stage is the to remove the unnecessary elements in two or so stages by firstly removing the not required strings via a removeStr.indexOf and then secondly by removing the NaN's linked to those remove strings. This is done as followed:-
// This array contains strings that needs to be removed from main array for Meat_Fish Order
var removeStr = ['Status' ,'Date Submitted' ,'Name' , 'Phone' , 'Delivery Required?' , 'Address ', 'GLATT SUMMARY' , 'MH SUMMARY' ,'GILBERTS SUMMARY' , 'SMOKED SALMON SUMMARY' , 'DOVIDS SUMMARY' , 'ADDITIONAL ITEMS? (subject to availability)'];
ordered = ordered.filter(function(val){
return (removeStr.indexOf(val) == -1 ? true : false)
});
var ordered = ordered.filter(function(value) {
return !Number.isNaN(value);
});
The above removeStr.indexOf is semi successfully, but for some reason is not removing Address, SMOKED SALMON SUMMARY and DOVIDS SUMMARY, as you can see below.
Address ,SMOKED SALMON SUMMARY,DOVIDS SUMMARY,Roaster,3,Wrapped Cut Up,1,Wrapped Cut Up Skinned,0,Carcus
,0,Half Hen,0,Mince,0,Lean Mince,2,Chicken Mince,0,Chicken Wings (8),0,Drumsticks (4),1,Thighs (4),0,Breasts (2),4,Pargiot (6),0,Hinds (2),0,Cumberland,2,Burger (4),0,Diced Steak,2,Fairy Steaks (Pack),1,Ribeye Steak,0,Bola,0,Lamb Chops (4),3,Shoulder Chops (2),0,Lamb Shanks (2),0,Shoulder Lamb (off bone),0,Shoulder Lamb (bone in),0,Turkey Thigh,0,Turkey Leg,0,Roaster Crown,0,Roaster in Tin,0,Meatballs 12,0,Meatballs Family,0,Lamb Shwarma,0,Thick Chops (4),0,Salmon 200g,1,Salmon 100g,2,Gefilte,0,Fishball (L),0,Fishball (S),0
I thought the issue was down possible to case, additional spacing, or something like that, but have matched exactly and still no joy.
As well as sorting this would be good to know if there is anything within Javascript which is of use to take away an potential issues with case sensitivity and additional spacing. Is there anything?
Big thanks in advance
to correct errors of whitespace and capital letters let's standardize all texts before:
const standardize = val => {
if (typeof val === 'string') return val.replace(/\s/g, '').toLowerCase()
return val
}
const standardizedRemoveStr = removeStr.map(standardize)
const res = ordered.filter(val => {
return !standardizedRemoveStr.includes(standardize(val)) && !Number.isNaN(val)
})

javascript, getting a random number result in each singular array

I'm not sure how to word the question and i'm still quite new at javascript.
So I've got a random quote generator that has each quote result as an array. I'd like to add in two items in the array which I've got so far but having one result be a random number generated eg "2 quote" but having 2 be randomised each time. The end result is for a browser based text game. So it could be "2 zombies attack" or "7 zombies attack." The code I have so far is:
var quotes = [
[x, 'Zombies attack!'],
[x, 'other creatures attack'],
['next line'],
]
function newQuote() {
var randomNumber = Math.floor(Math.random() * (quotes.length));
document.getElementById('quote').innerHTML = quotes[randomNumber];
}
Ideally need x(or i however it's going to work) to be the result of a random number between a set range, each differently each array.
Thank you
p.s I forgot to mention that not all the quotes require a number. Thats why I've done it as a double array.
If I understand your goal correctly, you want to have a set of similar-ish message templates, pick one of them at some point and fill it with data, correct? There's a lot of ways to tackle this problem, depending on how varying can your templates be. For a simple case in my head where you just need to prepend a number to a string I'd do something like this:
var messages = [" zombies attack",
" other creatures attack"], // define your messages
messageIndex = Math.floor(Math.random() * messages.length), // pick one of them
numberOfMonsters = Math.floor(Math.random() * 10 + 1), // get your random number
result = numberOfMonsters + messages[messageIndex]; // construct a resulting message
document.getElementById('quote').textContent = result;
If you'd rather have more complex strings where you don't necessarily add a number (or any string) to the beginning, like ["There's X things in the distance", "X things are somewhere close"], then I'd recommend to either come up with some sort of string formatting of your own or use a library to do that for you. sprintf.js seems to be just right for that, it will let you do things like this:
var messages = ["%d zombies attack",
"A boss with %d minions attacks"], // define your messages
messageIndex = Math.floor(Math.random() * messages.length), // pick one of them
numberOfMonsters = Math.floor(Math.random() * 10 + 1), // get your random number
result = sprintf(messages[messageIndex], numberOfMonsters) // format a final message
document.getElementById('quote').textContent = result;
EDIT: Your task is much more complex than what is described in the original question. You need to think about you code and data organization. You have to outline what is finite and can be enumerated (types of actions are finite: you can loot, fight, move, etc.), and what is arbitrary and dynamic (list of monsters and loot table are arbitrary, you have no idea what type and amount of monsters game designers will come up with). After you've defined your structure you can come up with some quick and dirty message composer, which takes arbitrary entities and puts them into finite amount of contexts, or something. Again, I'm sort of shooting in the dark here, but here's an updated version of the code on plunkr.
I solved it to do what I want and still have the numbers different. The issue was I should have had the number generator within the quote function. Also can create multiple variables to use too for different number generators. The plan is to then integrate it with php to add content dynamically. Which I can do. Thanks Dmitry for guiding me in the right direction.
function newQuote() {
var MonsterOne = Math.floor((Math.random() * 14) + 0);
var MonsterTwo = Math.floor((Math.random() * 14) + 0);
var MonsterThree = Math.floor((Math.random() * 14) + 0);
var MonsterFour = Math.floor((Math.random() * 14) + 0);
var quotes = [
['Test', MonsterOne, 'One'],
['Test', MonsterOne,'Two'],
['Test', MonsterThree, 'Three'],
[MonsterFour, 'Four'],
['Five'],
]
var randomNumber = Math.floor(Math.random() * (quotes.length));
document.getElementById('quote').innerHTML = quotes[randomNumber];
}

Multiple words search and calculation algorithm (Angular/Javascript)

I'm loading json file from database with two fields words and grade. Each word is graded for example true has 1 while lie has -1. Then i take input from text filed and i need to grade it based on grades from JSON file and then calculate score by summarizing the grades, but i just can't seem to find the way to do that. Words that are not in file are not being calculated.
I tried string.search match but it's to complicated and in the end i couldn't get result the way i wanted. I tried array searches same thing. I searched for on line solution, but no one has done anything similar so i can't copy it.
JSON
[
{"word":"true","grade":1},
{"word":"hate","grade":-1},
{"word":"dog","grade":0.8},
{"word":"cat","grade":-0.8}
]
String
"Dogs are wonderful but i prefer cats, cats, i can not lie although dog is a true friend".
The first thing I'd do is turn your JSON data into a map which can easily be searched - key would be the word, and value the grade:
var json = [
{"word":"true","grade":1},
{"word":"hate","grade":-1},
{"word":"dog","grade":0.8},
{"word":"cat","grade":-0.8}
];
var map = json.reduce(function(p,c){
p.set(c.word.toLowerCase(),c.grade);
return p;
}, new Map());
console.log(...map);
Then, its just a case of splitting your string, whilst also calculating the total score - again reduce can be used
var json = [
{"word":"true","grade":1},
{"word":"hate","grade":-1},
{"word":"dog","grade":0.8},
{"word":"cat","grade":-0.8}
];
var map = json.reduce(function(p,c){
p.set(c.word.toLowerCase(),c.grade);
return p;
}, new Map());
var input = "Dogs are wonderful but i prefer cats cats i can not lie although dog is a true friend";
var score = input.split(' ').reduce(function(p,c){
var wordScore = map.get(c.toLowerCase()) || 0;
return p + wordScore;
},0);
console.log(score);
Note that I have manually removed punctuation in the above input - I'll leave that as an exercise for you.
Also note that "cats" != "cat" so some of your words wont be found!
Let's first think of the algorithm. Two options:
Search and count the input string as many times as number of words in your JSON, or
Check each word in your input string against the JSON contents.
Since the JSON length is known and (I presume) shorter than the possible input string, I would tend to prefer option 2.
Now, after selecting option 2, you need to split the input string into words and create an array containing one word each entry of the array.
You can achieve this using the mystring.split(" ") method. This, of course, does not take into account punctuations, but you can handle this using the same method.
Now, you can add to each entry in your JSON a field to count the number of appearances of each entry in the JSON within the string.
Finally, you sum the product of the counters and the grade.
console.log((function(rules, str) {
var sum = 0;
Array.prototype.forEach.call(rules, function(rule) {
var match = str.match(rule.regexp);
match && (sum += str.match(rule.regexp).length * rule.grade);
console.log([rule.regexp, match&&match.length, rule.grade, match&&match.length * rule.grade, sum]);
});
return sum;
})([{
"regexp": /true/g,
"grade": 1
}, {
"regexp": /hate/g,
"grade": -1
}, {
"regexp": /dog/g,
"grade": 0.8
}, {
"regexp": /cat/g,
"grade": -0.8
}], "Dogs are wonderful but i prefer cats, cats, i can not lie although dog is a true friend"));
i use regexp rather than string, u can use string and convert to regex at run time, hope this would help

Tallying incorrect answers for Javascript game

So I am trying to make a javascript game for my geography class but I have run into some trouble, I can ask the questions and tell you if you're wrong or not but I would like to be able to keep track of the wrongs answers. I want to keep track using for loops but I'm not good at them, some help would be greatly appreciated!
This is the basis of what every question looks like, it's just that && is where I need to add a single mark to the incorrect tally which I am sure I need to use for loops for.
var y = "You are correct!!!"
var n = "You are incorrect!!!"
alert("Chapter 1, Human Cultural Connections. 1-10")
//==================================================
var Q1 = prompt("Demographers identify three different stages of life.
They are children, working adults, and older adults. What is the age
range for children? 0-13, 0-15, 0-18")
if (Q1 === "0-13")
{
alert(y)
}
else
{
alert(n) //&& add 1 tally to incorrect list
}
If someone could help me out with this it would be sooo helpful, and don't worry this is past do anyways but I still want to know how to do it for future projects!
p.s. I already have the script HTML so I don't need help with that.
var correct = [], // well store the index of the correctly answered questions here
wrong = [], // well store the index of the incorrectly answered questions here
questions = [
{
"question": "Demographers identify three different stages of life. They are children, working adults, and older adults. What is the age range for children?",
"answers": ["0-13", "0-15", "0-18"],
"correct": 0 // correct answer is item of index 0 in property "answers" (0-13)
},
{
"question": "whats your favorite color?",
"answers": ["red", "yellow", "blue", "purple"],
"correct": 2 // blue
}
];
for (var i in questions){
var answer = prompt(questions[i].question + questions[i].answers.join(','));
if (answer == questions[i].answers[questions[i].correct]){
correct.push(i);
}else{
wrong.push(i);
}
}
alert('wrong number of answers: ' + wrong.length);
alert('correct number of answers: ' + correct.length);
alert('first wrong question: ' + questions[wrong[0]].question);
I know this is practically overwngineering what you asked for but it might give you better flexibility and knowledge as to how js for loops work. Hope it helps.
Add a variable to keep track of incorrect answers:
var y = "You are correct!!!"
var n = "You are incorrect!!!"
var incorrectCount = 0;
alert("Chapter 1, Human Cultural Connections. 1-10")
//==================================================
var Q1 = prompt("Demographers identify three different stages of life.
They are children, working adults, and older adults. What is the age
range for children? 0-13, 0-15, 0-18")
if (Q1 === "0-13")
{
alert(y)
}
else
{
alert(n) //&& add 1 tally to incorrect list
incorrectCount++;
}

Categories