Missing Task? Chore Door : Please Help!


#43

It’s fair to say we are all going to be eager to enhance and embellish, but this phase, can we stick to the project and bring in enhancements at the end of this process?

You’ll see I’ve broken the page into three sections, but it is still the one page. We may as well start at the top. It hasn’t come up in the courses but deserves consideration… type="text/css". That used to be a needed attribute to be valid HTML. HTML5 (which is the spec (namespace) declared in the doctype) has de facto adopted CSS style sheets, and JavaScript as the native scripting language. That means we no longer have to specify the MIME type for either.

<link href="styles.css" rel="stylesheet">
<script src="script.js"></script>

Simple, eh? If a future lesson squawks at your about this, just humor the author and toss it in, but don’t think you need to have it in your own projects.

Remember to save your original work on your local machine. All you need is a text editor. In your documents folder, create a cc folder and in that a javascript folder, and finally a choredoor folder. Save all your work there (careful not overwrite past work). Now you can change those three lines.

<link href="https://fonts.googleapis.com/css?family=Work+Sans" rel="stylesheet">
<link href="./style.css" rel="stylesheet">

and at the bottom,

<script src="script.js"></script>

Save and test. Won’t be much to see since it will work and look the same. Save often, and copy iterations over to your local folder so you can go back and see the progression or revert back to earlier versions if something goes wrong.

It’s not likely we will ever need to override a selector rule in the Google font CSS but having our custom CSS load last gives it greatest sway in the imported styles cascade. Always load your CSS after everyone elses.

Couple last things to consider about in the top section… The human readable language, and character encoding. HTML has been encoded as UTF-8 by most text editors (sans Windows Notepad) but we need to tell the user agent what encoding to use on the plain text. If we want international characters to render correctly this will be important (and is the de facto standard).

<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Chore Door!</title>

Make this a template action on all your future HTML projects. The character encoding is declared before the title so special characters are rendered correctly in the title bar or tab.

This page doesn’t have an H1 element, but it does have a header. The header (or headline) should match the title element. Notice what your header reads? Hence the title. We’ll be working with the header next.

In the steps we give this element a background color and text alignment in the style rule for class header.

For now let’s stick to the project and use the header image provided. You can go with your artistic improvements when we’re done here, only with lots more insight cached away in your thinking. I’m all for sticking with the program since it makes it easier for me to explain these things while having a local reference of my own.

<div class="header">
  <img src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/logo.svg">
</div>

As a designer one might want the name of the image file to match the text represented by the image. I would have called it chore_door.svg. That’s me. Don’t let my subjectivity affect your perspective. That is not my goal. Anything I suggest is purely recommendation, not absolute. Rules of thumb are kind of important to have, though.

If you can for now adopt the original code scheme it will make things a pleasure to go forward and will benefit future readers of this topic. Please strip all the embellishments and adjust your HTML as recommended above, Save and test, and post the new HTML in a reply. We can resume at that time.

BTW, we are far from finished with the HTML. This is just the first step that concisely addresses a small number of concerns. That is how we want to approach this process: Extreme objectivity.


#44

For a segue, post the handler code for the startButton. It’s a good place to start in the JS file.


#45

I rewrote the entire html with the revisions suggested:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
    <title>Chore Door!</title>
    <link href="./style.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css?family=Work+Sans" rel="stylesheet">
  </head>
<body>

    <div class="header">
      <img src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/logo.svg">
    </div>

    <div class="first-row">
      <img src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/star.svg">
      <p class="instructions-title">Instructions</p>
      <img src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/star.svg">
    </div>

    <table class="second-row">
      <tbody><tr>
        <td class="instructions-number">1</td>
        <td class="instructions-text">Hiding behind one of these doors is the ChoreBot.</td>
      </tr>
      <tr>
        <td class="instructions-number">2</td>
        <td class="instructions-text">Your mission is to open all of the doors without running into the ChoreBot.</td>
      </tr>
      <tr>
        <td class="instructions-number">3</td>
        <td class="instructions-text">If you manage to avoid the ChoreBot until the very last door, you win!</td>
      </tr>
      <tr>
        <td class="instructions-number">4</td>
        <td class="instructions-text">See if you can score a winning streak!</td>
      </tr>
    </tbody></table>

    <div class="door-row">
      <img class="door-frame" src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg" id="door1">
      <img class="door-frame" src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg" id="door2">
      <img class="door-frame" src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg" id="door3">
    </div>

    <div class="start-row" id="start">Good luck!</div>

    <table class="score-row">
      <tbody><tr>
        <th class="score-text">Current streak:</th>
        <th class="score-text">Best streak:</th>
      </tr>
      <tr>
        <th class="score-box" id="score-number">0</th>
        <th class="score-box" id="high-score-number">0</th>
      </tr><tr>
    </tr></tbody></table>

    <script src="script.js"></script>

I completely understand the need to stick to the basic project. I only embellished for memory and creative purposes.


#46

Couple more points regarding the HTML as it relates to CSS. The order of the attributes is of no importance but from the standpoint of specificity as mentioned in the instruction text, id should come before class so it is clear to the reader which selectors apply to the element.

<img id="door1" class="door-frame" src="#">

TBODY is only really necessary when the table has a THEAD and TFOOT, otherwise it can be left off. The table is its own body.

<table>
  <tr>
    <td></td>
    <td></td>
  </tr>
</table>

A general rule of thumb in markup is to use the least amount of structure so no added meaning is attached. And it makes for easier reading and maintenance.

TH is not a style (presentation) element, though it does have centered and bolded text which writers might find useful and convenient. However that goes against the grain of what markup is meant to convey… meaning. TH has meaning and scope. At the top of a column it is a header row, and down the left side it is a header column.

Table example

Use TD’s on your score-box elements and CSS to center and bold as desired. Never use a tag for the appearance it may offer. This also applies to headlines, which is for another discussion.

Enough nitpicking about markup. Now lets focus on making our markup unobtrusive, starting with the header. What if we were to use a CSS background image on that element? It would allow us to remove the IMG tag and make the HTML very simple.

<div id="header"></div>

Note that I’ve changed class to id. This is because empty elements are not valid HTML, unless they have an ID. I’ve long ago forgotten the reasoning behind this. I’m sure if you scour the Web Accessibility Guidelines it will turn up in there. Mind, a lot has changed these past ten years.

The CSS for this element will be changed from what was earlier mentioned. The selector rule for .header can be removed since neither property applies.

#header {
  height: 66px;
  background: #0ff url(https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/logo.svg) center no-repeat;
}

Everything is contained in the background property except height. The background color, the image url, position, and a no-repeat directive so it doesn’t tile. This is a first step toward unobtrusive markup. Nice and clean. The image will be downloaded as soon as the HTML is parsed into the DOM when the CSS is parsed and applied to the respective nodes.

That takes care of the header. Save your work and test. Voila! Moving down the page, let’s look at the title-row…

    <div class="title-row">
      <p class="instructions-title">Instructions</p>
    </div>

Notice that the IMG tags are removed? That’s because we will handle the stars in the CSS, like above, only with a slight twist… Pseudo-elements, :before and :after. For one, having two IMG tags with the same URL is repetitive and obtrusive. The above markup is just like the header, simple and clean. Here is the CSS that I’ve applied…

.title-row {
  margin: 42px 0 21px 0;
  text-align: center;
}
.instructions-title {
  font-family: 'Work Sans', sans-serif;
  font-size: 18px;
  color: #0ff;
}
.instructions-title:before, 
.instructions-title:after {
  content: url(https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/star.svg);
  margin: 0 0.3em;
}

I made some slight changes to the originally prescribed CSS, but only subtle. We no longer need the display: inline property on the instructions-title and I’ve compressed the margins into a shorthand declaration.

margin: TOP RIGHT BOTTOM LEFT;

always in that order. When applying the same value to both top/bottom and right/left, we write,

margin: top/bottom right/left

as in the pseudo-element rule above.

Be sure that as you learn HTML and CSS you are spending some time every day reading up the documentation on MDN and W3C (not to be confused with W3Schools which has zero affiliation). The specifications are pretty dry reading but invaluable in shaping our minds and thinking.

Your can adjust the positions of the stars by tweaking the margin of the pseudo-element. Notice that there is only one URL in the listing, but we apply it to both selectors in one rule. Comma separated selector lists apply independently to those selectors. Two selectors, one rule. Very simple and clear, and, two more IMG tags removed.

Save and test. Be sure to update your local version of HTML and CSS. As already mentioned, use the class names given in the instructions. You can change whatever you like when we’re through.

    <div id="header"></div>
    <div class="title-row">
      <p class="instructions-title">Instructions</p>
    </div>
    <table class="instructions-row">

Give this a go and we can move onto the last part of the HTML in the next post. Please include once again your updated HTML in your reply, and as we are going to be looking at the script in the next writing, include also the code for #start, including both the node caching statement and the event listener/handler.


#48

I haven’t forgotten about this, I have been busy with work and internet connectivity issues. I haven’t finished yet but I will tonight.


#49

Don’t pressure yourself. I’m still here and ready to continue when you are.

FYI… We won’t be carrying the score in this progression since it is moot, 2:1 odds against. We only have a 1 in 3 chance of choosing the non-robot pair in any one session. The robot has us odds on favorite all the way.


#50

I like the change in the title, it looks much better. I’ve taken the HTML and CSS courses but some details still elude me. Such as Pseudo Elements and display rules. Positioning the elements on the page is a bit challenging as well. Here is the revised HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
    <title>Chore Door!</title>
    <link href="./style.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css?family=Work+Sans" rel="stylesheet">
  </head>
<body>

    <div id="header">
    </div>
    <div class="title-row">
      <p class="instructions-title">Instructions</p>
    </div>

    <table class="instructions-row">
      <tr>
        <td class="instructions-number">1</td>
        <td class="instructions-text">Hiding behind one of these doors is the ChoreBot.</td>
      </tr>
      <tr>
        <td class="instructions-number">2</td>
        <td class="instructions-text">Your mission is to open all of the doors without running into the ChoreBot.</td>
      </tr>
      <tr>
        <td class="instructions-number">3</td>
        <td class="instructions-text">If you manage to avoid the ChoreBot until the very last door, you win!</td>
      </tr>
      <tr>
        <td class="instructions-number">4</td>
        <td class="instructions-text">See if you can score a winning streak!</td>
      </tr>
    </table>

    <div class="door-row">
      <img class="door-frame" src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg" id="door1">
      <img class="door-frame" src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg" id="door2">
      <img class="door-frame" src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg" id="door3">
    </div>

    <div class="start-row" id="start">Good luck!</div>

    <table class="score-row">
      <tr>
        <th class="score-text">Current streak:</th>
        <th class="score-text">Best streak:</th>
      </tr>
      <tr>
        <th class="score-box" id="score-number">0</th>
        <th class="score-box" id="high-score-number">0</th>
      </tr><tr>
    </tr></table>

    <script src="script.js"></script>



</body>
</html>

I wasn’t sure whether I should paste all of it or just the revised part so…all of it.


#51

All the HTML is best. Remember to load your custom CSS after fonts and other style sheets.

  <link href="https://fonts.googleapis.com/css?family=Work+Sans" rel="stylesheet">
  <link href="./style.css" rel="stylesheet">

and as mentioned earlier, let id appear before class in elements that have both. I like to write them both out front (at the start of the attribute list).

<element id="x" class="y" attr="value">

Also as mentioned, we are not going to need to keep score. It’s moot since we know the robot is going to win two-thirds of the time.

CSS, for all its simplicity is still a lot to learn and master. HTML makes our job fairly easy because of what’s known as normal flow, meaning simply that elements are drawn on the page in the order in which they appear in the source document. Block elements are drawn one below the other and span the full width of the display by default.

A good general rule is that the HTML should be composed first, without any style rules. The page will render in rather boring fashion, but we can examine where everything is and make sure all the content is displaying in the order we intended.

As we can see in this project there are very few style rules needed to compose the finished page. Bottom line is to keep things simple and learn to work with the natural behavior of the browser as much as possible. The box model is designed with this in mind, as are the default style rules. By first working with HTML only, we can observe and learn all the built in object behaviors. DIVs have no height, but their width is 100%. UL and OL are similar containers, no height, but 100% width, default margins and padding. LI are similar to P except they do not have top and bottom margins, and they have bullets and padding. These are all block elements that we can predict how they will appear in raw form.

Read up on default styles and play with HTML in small documents just to get familiar with how each element behaves. Set aside an empty template to practice with (spin off a copy of the template for each new project).

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>title after charset</title>
</head>
<body>
</body>
</html>

Set out a plan for each practice project, such as an essay layout with headlines, sections and paragraphs. Or make a list that contains nested lists with still more nested lists. Make a note of their default appearance when no style rules are applied (except the built in styles). For filler text to use in your page go to Lorem Ipsum and grab some fake text. It’s not very imaginative but serves its purpose well. These are things you should do in any free time you have. Don’t look for polish or prettiness. Just compose and remember the behaviors.

Positioning and sizing are normal concerns in a finished web document, but these concerns are built upon a complete understanding of the default rendering. No detail is so small it bears ignoring. Go down the HTML element list and study each and every one of them in detail.

SERP: HTMLElement site:w3.org

The above search result page contains a lot of interesting reading, and it doesn’t end there. This stuff is really hard to teach because there is so much to learn. Study one HTML Element a day and it will still take months to go through the list. The better we are grounded in HTML, the easier it is to learn and implement CSS and later, script behaviors. It takes time, lots of it.

As mentioned earlier, we are going to be working with the script in the next writing, beginning with the start button. You can post your entire script for us to refer to as we go forward.


#52

You see, I’m not very interested in the polish or prettiness. I want to learn design someday but not in the near future. Right now I am interested in exactly what you are explaining. Detail, specifics, structure. My ability to learn fast feeds on detail. I couldn’t have asked for a better person to decide to help me. Thank you.

Now, mushiness aside, here is the revised HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
    <title>Chore Door!</title>
    <link href="https://fonts.googleapis.com/css?family=Work+Sans" rel="stylesheet">
    <link href="./style.css" rel="stylesheet">
  </head>
<body>

    <div id="header">
    </div>
    <div class="title-row">
      <p class="instructions-title">Instructions</p>
    </div>

    <table class="instructions-row">
      <tr>
        <td class="instructions-number">1</td>
        <td class="instructions-text">Hiding behind one of these doors is the ChoreBot.</td>
      </tr>
      <tr>
        <td class="instructions-number">2</td>
        <td class="instructions-text">Your mission is to open all of the doors without running into the ChoreBot.</td>
      </tr>
      <tr>
        <td class="instructions-number">3</td>
        <td class="instructions-text">If you manage to avoid the ChoreBot until the very last door, you win!</td>
      </tr>
      <tr>
        <td class="instructions-number">4</td>
        <td class="instructions-text">See if you can score a winning streak!</td>
      </tr>
    </table>

    <div class="door-row">
      <img id="door1" class="door-frame" src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg">
      <img id="door2" class="door-frame" src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg">
      <img id="door3" class="door-frame" src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg">
    </div>

    <div id="start" class="start-row">Good luck!</div>


    <script src="script.js"></script>



</body>
</html>

As suggested, I removed the score board and placed the attributes in their proper places.

Are the elements in HTML affected by how much space is in between them? For instance, if I wanted a large space between an h2 and p element on the page. Or is that only CSS where you can create space between two elements?


#53

That’s good to know. Really not too sure how well I’m coming across but if you are gleaning details and making sense of them, that is a good thing. Thanks for saying so.

No. HTML ignores whitespace (spaces and line breaks). Printable characters go out to the display as a single line even if we break them up in the source listing.

H2 and P will have a blank line between them as provided for in the default style sheet. The margin around both is 1em above and below. This brings up an interesting concept, though… Collapsing margins. We would expect that the space between H2 and P would be 2em since they both have top and bottom margins.

bottom margin of H2
top margin of P

However, the browser is sensitive to this and will collapse the top margin of the P so that there is only one margin in effect. To adjust the space between them, play with the margin-bottom property on the H2. In the old days before CSS we used to cheat by including empty paragraphs, but remember how I mentioned earlier that empty elements are not valid HTML? We got around this with a simple cheat…

<h2>Section Heading</h2>
<p>&nbsp;</p>
<p>Start of body text</p>

Now it has content… A non-breaking-space character entity. Sure glad those days are behind us but in a pinch, it still comes in handy.

Section Heading

 

Start of body text

Notice the double blank lines?

Your markup looks pristine. Only thing I would change now is,

<div id="header"><div>

A minor detail in the scheme of things that has no effect, just looks clearner.

Now let’s get down to work. We will need your script file this so please post the whole thing in a reply and we can get started.


#54

Here is the script:

let door1 = document.getElementById('door1');
let door2 = document.getElementById('door2');
let door3 = document.getElementById('door3');
let startButton = document.getElementById('start');
let botDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/robot.svg";
let beachDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/beach.svg";
let spaceDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/space.svg";
let closedDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg"
let numClosedDoors = 3;
let openDoor1;
let openDoor2;
let openDoor3;
let currentlyPlaying = true;
let score = 0;
let highScore = 0;
let currentStreak = document.getElementById('score-number');
let bestStreak = document.getElementById('high-score-number');
currentStreak.innerHTML = score;
bestStreak.innerHTML = highScore;

const isClicked = (door) => {
  if (door.src == closedDoorPath) {
    return false;
  } else {
    return true;
  }
}

const isBot = (door) => {
  if (door.src === botDoorPath) {
    return true;
  } else {
    return false;
  }
}

const playDoor = (door) => {
  numClosedDoors--;
  if (numClosedDoors === 0) {
    gameOver('win');
  } else if (isBot(door)) {
    gameOver('lose');
  }
}


const randomChoreDoorGenerator = () => {
   choreDoor = Math.floor(Math.random() * numClosedDoors);
   if (choreDoor === 0) {
    openDoor1 = botDoorPath;
     openDoor2 = beachDoorPath;
     openDoor3 = spaceDoorPath;
  } else if (choreDoor === 1) {
     openDoor2 = botDoorPath;
     openDoor1 = beachDoorPath;
     openDoor3 = spaceDoorPath;
   } else {
     openDoor3 = botDoorPath;
     openDoor1 = beachDoorPath;
     openDoor2 = spaceDoorPath;
   }
 }


door1.onclick = () => {
  if(currentlyPlaying && !isClicked(door1)) {
    door1.src = openDoor1;
    playDoor(door1);
  }
}

door2.onclick = () => {
  if(currentlyPlaying && !isClicked(door2)) {
    door2.src = openDoor2;
    playDoor(door2);
  }
}

door3.onclick = () => {
  if(currentlyPlaying && !isClicked(door3)) {
    door3.src = openDoor3;
    playDoor(door3);
  }
}

startButton.onclick = () => {
    startRound();
}

const startRound = () => {
  // Reset all the doors
  door1.src = closedDoorPath;
  door2.src = closedDoorPath;
  door3.src = closedDoorPath;
  numClosedDoors = 3;
  currentlyPlaying = true;
  startButton.innerHTML = 'Good luck!';
  randomChoreDoorGenerator();
}

const gameOver = (str) => {
  if(str === 'win') {
    startButton.innerHTML = 'You win! Play again?';
    getYourScore();
  } else {
    startButton.innerHTML = "Game over! Play again?"
    score = 0;
    currentStreak.innerHTML = score;
  }
  currentlyPlaying = false;
}

const getYourScore = () => {
  score++;
  currentStreak.innerHTML = score;
  if (score > highScore) {
    highScore = score;
    bestStreak.innerHTML = highScore;
  }
}


startRound();

Also,

We got around this with a simple cheat…

<h2>Section Heading</h2>
<p>&nbsp;</p>
<p>Start of body text</p>

Cool, what a neat little cheat. What are those group of characters between the first p element called?

Also, as I poured through the html elements on Mozilla (I know that sounds a bit…crammed…but I do that for a reason) and then W3 site, I noticed the button element, which strangely peaked my curiosity about linking different buttons to unique actions. I’ve done that kind of task on a previous course but didn’t really grasp how that worked until I read about it on Mozilla.

I’m kind of a crammer. I skim through an entire document, reading every last word, then, as I’m practicing, go through each part piece by piece and picking up details. It’s a strange way for me to learn things but it’s how I’ve adapted to how fast I learn. Learning fast comes with troublesome side effects. lol


#55

A character entity. That one, the non-breaking-space is for between words we do not want to break apart if word wrap takes effect. When we really want two words to stay on the same line (as in both wrap together) we separate them with that entity…

sand&nbsp;bog

Those two words will always be together. Read up on character entities at W3.org.

On to the start button.

We can see that yours does not have the built in protection to prevent wrongful clicking as recommended in the instructions. What is the condition that permits the button to be clicked?

Aside

Remember to end all assignment statements with a semi-colon. If it’s got an = sign, it gets a ;.


#56

[quote=“lanajames, post:54, topic:359844”]

let door1 = document.getElementById('door1');
let door2 = document.getElementById('door2');
let door3 = document.getElementById('door3');
let startButton = document.getElementById('start');
let botDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/robot.svg";
let beachDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/beach.svg";
let spaceDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/space.svg";
let closedDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg"
let numClosedDoors = 3;
let openDoor1;
let openDoor2;
let openDoor3;
let currentlyPlaying = true;
let score = 0;
let highScore = 0;
let currentStreak = document.getElementById('score-number');
let bestStreak = document.getElementById('high-score-number');
currentStreak.innerHTML = score;
bestStreak.innerHTML = highScore;

const isClicked = (door) => {
  if (door.src == closedDoorPath) {
    return false;
  } else {
    return true;
  }
};

const isBot = (door) => {
  if (door.src === botDoorPath) {
    return true;
  } else {
    return false;
  }
};

const playDoor = (door) => {
  numClosedDoors--;
  if (numClosedDoors === 0) {
    gameOver('win');
  } else if (isBot(door)) {
    gameOver('lose');
  }
};


const randomChoreDoorGenerator = () => {
   choreDoor = Math.floor(Math.random() * numClosedDoors);
   if (choreDoor === 0) {
    openDoor1 = botDoorPath;
     openDoor2 = beachDoorPath;
     openDoor3 = spaceDoorPath;
  } else if (choreDoor === 1) {
     openDoor2 = botDoorPath;
     openDoor1 = beachDoorPath;
     openDoor3 = spaceDoorPath;
   } else {
     openDoor3 = botDoorPath;
     openDoor1 = beachDoorPath;
     openDoor2 = spaceDoorPath;
   }
 };


door1.onclick = () => {
  if(currentlyPlaying && !isClicked(door1)) {
    door1.src = openDoor1;
    playDoor(door1);
  }
};

door2.onclick = () => {
  if(currentlyPlaying && !isClicked(door2)) {
    door2.src = openDoor2;
    playDoor(door2);
  }
};

door3.onclick = () => {
  if(currentlyPlaying && !isClicked(door3)) {
    door3.src = openDoor3;
    playDoor(door3);
  }
};

startButton.onclick = () => {
    startRound();
};

const startRound = () => {
  // Reset all the doors
  door1.src = closedDoorPath;
  door2.src = closedDoorPath;
  door3.src = closedDoorPath;
  numClosedDoors = 3;
  currentlyPlaying = true;
  startButton.innerHTML = 'Good luck!';
  randomChoreDoorGenerator();
};

const gameOver = (str) => {
  if(str === 'win') {
    startButton.innerHTML = 'You win! Play again?';
    getYourScore();
  } else {
    startButton.innerHTML = "Game over! Play again?"
    score = 0;
    currentStreak.innerHTML = score;
  }
  currentlyPlaying = false;
};

const getYourScore = () => {
  score++;
  currentStreak.innerHTML = score;
  if (score > highScore) {
    highScore = score;
    bestStreak.innerHTML = highScore;
  }
};


startRound();

Also,

We can see that yours does not have the built in protection to prevent wrongful clicking as recommended in the instructions. What is the condition that permits the button to be clicked?

I don’t understand the question.


#57

Go back to Step 63 and give it a close read. You have the requisite variable already, and just need a conditional.


#58

Go back to Step 63 and give it a close read. You have the requisite variable already, and just need a conditional.

I’m gonna be honest, I left that part out because I had no idea what condition to put there. Was hoping you’d give a little insight on that…


#59

Okay, consider the variable currentlyPlaying which is set to true in the initialization stage. When it is true we cannot click the button. A logical operator (hint: NOT) will come into play here.

startButton.onclick = () => {
  if ( ... ) {
    startRound();
  }
};

Recall also that we do not compare booleans, just query them.

! (NOT) negates a boolean or casts a truthy/falsy value to its opposite boolean.

! true  => false
! false => true

a = true
if (!a) {
    // this branch will be skipped
}

#60

Took me several minutes of reading your response over and over then searching MDN for me to get it…:triumph:

startButton.onclick = () => {
  if (!currentlyPlaying) {
    startRound();
  }
};

Is that the correct condition?

Also, now none of the clickable elements work. I can’t open the doors or start the game?


#61

That handler looks correct. Symptons like this point to another problem that escaped detection until this constraint was added. Now we get to glean from the code what’s missing or awry.


A word on my terminology…

When I write, query, to me it means, in comparison, whereas poll means accessing.


Oh! The score code is still in the script. We need to get back to what we’re working on, sans all that.


#62

I’m back!! internet and all! So, what’s next? The score code? I know I shouldn’t just erase all of it so what needs to be deleted and what needs to be kept? I don’t want to assume and mess the whole thing up unnecessarily.

let door2 = document.getElementById('door2');
let door3 = document.getElementById('door3');
let startButton = document.getElementById('start');
let botDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/robot.svg";
let beachDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/beach.svg";
let spaceDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/space.svg";
let closedDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg"
let numClosedDoors = 3;
let openDoor1;
let openDoor2;
let openDoor3;
let currentlyPlaying = true;
let score = 0;
let highScore = 0;
let currentStreak = document.getElementById('score-number');
let bestStreak = document.getElementById('high-score-number');
currentStreak.innerHTML = score;
bestStreak.innerHTML = highScore;

const isClicked = (door) => {
  if (door.src === closedDoorPath) {
    return false;
  } else {
    return true;
  }
};

const isBot = (door) => {
  if (door.src === botDoorPath) {
    return true;
  } else {
    return false;
  }
};

const playDoor = (door) => {
  numClosedDoors--;
  if (numClosedDoors === 0) {
    gameOver('win');
  } else if (isBot(door)) {
    gameOver('lose');
  }
};


const randomChoreDoorGenerator = () => {
   choreDoor = Math.floor(Math.random() * numClosedDoors);
   if (choreDoor === 0) {
    openDoor1 = botDoorPath;
     openDoor2 = beachDoorPath;
     openDoor3 = spaceDoorPath;
  } else if (choreDoor === 1) {
     openDoor2 = botDoorPath;
     openDoor1 = beachDoorPath;
     openDoor3 = spaceDoorPath;
   } else {
     openDoor3 = botDoorPath;
     openDoor1 = beachDoorPath;
     openDoor2 = spaceDoorPath;
   }
 };


door1.onclick = () => {
  if(currentlyPlaying && !isClicked(door1)) {
    door1.src = openDoor1;
    playDoor(door1);
  }
};

door2.onclick = () => {
  if(currentlyPlaying && !isClicked(door2)) {
    door2.src = openDoor2;
    playDoor(door2);
  }
};

door3.onclick = () => {
  if(currentlyPlaying && !isClicked(door3)) {
    door3.src = openDoor3;
    playDoor(door3);
  }
};

startButton.onclick = () => {
  if (!currentlyPlaying) {
    startRound();
  }
};

const startRound = () => {
  // Reset all the doors
  door1.src = closedDoorPath;
  door2.src = closedDoorPath;
  door3.src = closedDoorPath;
  numClosedDoors = 3;
  currentlyPlaying = true;
  startButton.innerHTML = 'Good luck!';
  randomChoreDoorGenerator();
};

const gameOver = (str) => {
  if(str === 'win') {
    startButton.innerHTML = 'You win! Play again?';
    getYourScore();
  } else {
    startButton.innerHTML = "Game over! Play again?"
    score = 0;
    currentStreak.innerHTML = score;
  }
  currentlyPlaying = false;
};

const getYourScore = () => {
  score++;
  currentStreak.innerHTML = score;
  if (score > highScore) {
    highScore = score;
    bestStreak.innerHTML = highScore;
  }
};


startRound();

type or paste code here

Ready when you are…


#63

We don’t need that function, or the init/caching lines at the top. Nobody is saying you cannot have those in your custom project afterwards, just not for the present until we get this finalized so it meets the current spec.

Now that you have a working start button. let’s explore a concept that might be new, or fairly new to you… Ternary expressions. A ternary has three parts, hence the name.

condition or state ? yield if true : default;

Consider,

function oddOrEven(n) {
    return n % 2 ? `${n} is odd` : `${n} is even`;
}

console.log(oddOrEven(42))    //  42 is even
console.log(oddOrEven(99))    //  99 is odd

We’ve touched upon truthy before so that we know any non-zero number to be truthy. When we divide a number by 2 the remainder is either 1 (truthy) or 0 (falsy).

42 % 2 => 0 (not odd)
99 % 2 => 1 (not even)

In the above example we look for odd is true and the default is even. It’s all akin to,

if (n % 2) {
    return `${n} is odd`;
} else {
    return `${n} is even`;
}

Of course a lesson plan might want us to test for evenness

if (n % 2 == 0) {
    return `${n} is even`;
} else {
    return `${n} is odd`;
}

So a ternary is just a refactored if statement when we boil it down. How could we apply a ternary to your start button?