Challenge: Silly story generator
In this challenge you are tasked with taking some of the knowledge you've picked up in this module so far and applying it to creating a fun app that generates random silly stories. Along the way, we'll test your knowledge of variables, math, strings, and arrays. Have fun!
Starting point
To begin, click the Play button in one of the code panels below to open the provided example in the MDN Playground. You'll then follow the instructions in the Project brief section to complete the JavaScript functionality.
<div>
<label for="custom-name">Enter custom name:</label>
<input id="custom-name" type="text" placeholder="" />
</div>
<fieldset>
<legend>Choose locale:</legend>
<label for="us">US</label
><input id="us" type="radio" name="uk-us" value="us" checked />
<label for="uk">UK</label
><input id="uk" type="radio" name="uk-us" value="uk" />
</fieldset>
<div>
<button class="generate">Generate random story</button>
</div>
<!-- Thanks a lot to Willy Aguirre for his help with the code for this assessment -->
<p class="story"></p>
// 1. COMPLETE VARIABLE DEFINITIONS AND RANDOM FUNCTION
const customName = document.getElementById("custom-name");
const generateBtn = document.querySelector(".generate");
const story = document.querySelector(".story");
function randomValueFromArray(array) {
const random = Math.floor(Math.random() * array.length);
return array[random];
}
// 2. RAW TEXT STRINGS
// Willy the Goblin
// Big Daddy
// Father Christmas
// the soup kitchen
// Disneyland
// the White House
// spontaneously combusted
// melted into a puddle on the sidewalk
// turned into a slug and slithered away
// 3. PARTIAL RETURN RANDOM STRING FUNCTION
function returnRandomStoryString() {
// It was 94 Fahrenheit outside, so :insertx: went for a walk. When they got to :inserty:, they stared in horror for a few moments, then :insertz:. Bob saw the whole thing, but was not surprised — :insertx: weighs 300 pounds, and it was a hot day.
return storyText;
}
// 4. EVENT LISTENER AND PARTIAL GENERATE FUNCTION DEFINITION
generateBtn.addEventListener("click", generateStory);
function generateStory() {
if (customName.value !== "") {
const name = customName.value;
}
if (document.getElementById("uk").checked) {
const weight = Math.round(300);
const temperature = Math.round(94);
}
// TODO: replace "" with the correct expression
story.textContent = "";
story.style.visibility = "visible";
}
Project brief
You have been provided with a few text strings and JavaScript functions; you need to write the necessary JavaScript to turn this into a working program, which does the following:
- Generates a silly story when the "Generate random story" button is pressed.
- Replaces the default name "Bob" in the story with a custom name, only if a custom name is entered into the "Enter custom name" text field before the generate button is pressed.
- Converts the default US weight and temperature quantities and units in the story into UK equivalents if the UK radio button is checked before the generate button is pressed.
- Generates a new random silly story every time the button is pressed.
Initial variables and functions
In the JavaScript, below the "COMPLETE VARIABLE DEFINITIONS AND RANDOM FUNCTION" comment, you've got three constants that store references to:
- The "Enter custom name" text field:
customName
. - The "Generate random story" button:
generateBtn
. - The
<p>
element at the bottom of the HTML body that the story will be copied into:story
.
In addition, you've got a function called randomValueFromArray()
that takes an array as input and returns one of the items stored inside the array at random.
Below the "RAW TEXT STRINGS" comment, you've got some commented text strings that will act as input into our program. We'd like you to uncomment these strings and store them inside constants like so:
- Store the first set of three strings inside an array called
characters
. - Store the second set of three strings inside an array called
places
. - Store the third set of three strings inside an array called
events
.
Completing the returnRandomStoryString()
function
Below the "PARTIAL RETURN RANDOM STRING FUNCTION" comment you've got a partially-completed returnRandomStoryString()
containing a long, commented string of text and a return
statement that returns a value called storyText
.
To complete this function:
- Uncomment the long string of text and store it inside a variable called
storyText
. This should be a template literal. - Add three constants called
randomCharacter
,randomPlace
, andrandomEvent
just above the template literal. These should be set equal to threerandomValueFromArray()
calls, which should return a random string from thecharacters
,places
, andevents
arrays, respectively. - In the template literal, replace the instances of
:insertx:
,:inserty:
, and:insertz:
with embedded expressions containingrandomCharacter
,randomPlace
, andrandomEvent
, respectively.
Completing the generateStory()
function
Below the "EVENT LISTENER AND PARTIAL GENERATE FUNCTION DEFINITION" comment, you've got a couple of code items:
- A line that adds a
click
event listener to thegenerateBtn
variable so that when the button it represents is clicked, thegenerateStory()
function is run. - A partially-completed
generateStory()
function definition. For the remainder of the challenge, you'll be filling in lines inside this function to complete it and make it work properly.
Follow these steps to complete the function:
- Create a new variable called
newStory
, and set its value to equal areturnRandomStoryString()
call. This function is needed so we can create a new random story each time the button is pressed. If we setnewStory
directly tostoryText
, we'd only be able to generate a new story once. - Inside the first
if
block, add a string replacement method call to replace the nameBob
found in thenewStory
string with thename
variable. In this block we are saying "If a value has been entered into thecustomName
text input, replaceBob
in the story with that custom name." - Inside the second
if
block, we are checking to see if theuk
radio button has been selected. If so, we want to convert the weight and temperature values in the story from pounds and Fahrenheit into stones and Celsius. What you need to do is as follows:- Look up the formulas for converting pounds to stone, and Fahrenheit to Celsius.
- Inside the line that defines the
weight
constant, replace300
with a calculation that converts 300 pounds into stones. Concatenate" stone"
onto the end of the result of the overallMath.round()
call. - Inside the line that defines the
temperature
variable, replace94
with a calculation that converts 94 Fahrenheit into Celsius. Concatenate" Celsius"
onto the end of the result of the overallMath.round()
call. - Just under the two variable definitions, add two more string replacement lines that replace
300 pounds
with the contents of theweight
variable, and94 Fahrenheit
with the contents of thetemperature
variable.
- Finally, in the second-to-last line of the function, make the
textContent
property of thestory
variable (which references the paragraph) equal tonewStory
.
Hints and tips
- You don't need to edit the HTML and CSS in any way.
Math.round()
is a built-in JavaScript method that rounds the result of a calculation to the nearest whole number.- There are three instances of strings that need to be replaced. You could use the
replace()
method, or some other solution.
Example
Your finished app should work like the following live example:
Click here to show the solution
The finished JavaScript should look something like this:
// 1. COMPLETE VARIABLE DEFINITIONS AND RANDOM FUNCTION
const customName = document.getElementById("custom-name");
const generateBtn = document.querySelector(".generate");
const story = document.querySelector(".story");
function randomValueFromArray(array) {
const random = Math.floor(Math.random() * array.length);
return array[random];
}
// 2. RAW TEXT STRINGS
const characters = ["Willy the Goblin", "Big Daddy", "Father Christmas"];
const places = ["the soup kitchen", "Disneyland", "the White House"];
const events = [
"spontaneously combusted",
"melted into a puddle on the sidewalk",
"turned into a slug and slithered away",
];
// 3. PARTIAL RETURN RANDOM STRING FUNCTION
function returnRandomStoryString() {
const randomCharacter = randomValueFromArray(characters);
const randomPlace = randomValueFromArray(places);
const randomEvent = randomValueFromArray(events);
let storyText = `It was 94 Fahrenheit outside, so ${randomCharacter} went for a walk. When they got to ${randomPlace}, they stared in horror for a few moments, then ${randomEvent}. Bob saw the whole thing, but was not surprised — ${randomCharacter} weighs 300 pounds, and it was a hot day.`;
return storyText;
}
// 4. EVENT LISTENER AND PARTIAL GENERATE FUNCTION DEFINITION
generateBtn.addEventListener("click", generateStory);
function generateStory() {
let newStory = returnRandomStoryString();
if (customName.value !== "") {
const name = customName.value;
newStory = newStory.replace("Bob", name);
}
if (document.getElementById("uk").checked) {
const weight = `${Math.round(300 / 14)} stone`;
const temperature = `${Math.round((94 - 32) * (5 / 9))} Celsius`;
newStory = newStory.replace("300 pounds", weight);
newStory = newStory.replace("94 Fahrenheit", temperature);
}
story.textContent = newStory;
story.style.visibility = "visible";
}