diff --git a/course/sparks-teacher.html b/course/sparks-teacher.html index 97a6220908..29d436c126 100755 --- a/course/sparks-teacher.html +++ b/course/sparks-teacher.html @@ -33,7 +33,7 @@

Teacher Resources

Curriculum Materials

- +
diff --git a/course/sparks.html b/course/sparks.html index b4840b0be4..c43ce1435a 100755 --- a/course/sparks.html +++ b/course/sparks.html @@ -19,7 +19,7 @@

Beauty and Joy of Computing Sparks

- +
diff --git a/img/4-internet/redundancy-simple.gif b/img/4-internet/redundancy-simple.gif new file mode 100644 index 0000000000..909366586a Binary files /dev/null and b/img/4-internet/redundancy-simple.gif differ diff --git a/img/4-internet/redundancy-simple.psd b/img/4-internet/redundancy-simple.psd new file mode 100644 index 0000000000..dcd82003f7 Binary files /dev/null and b/img/4-internet/redundancy-simple.psd differ diff --git a/sparks/img/U2/decision-tree.png b/sparks/img/U2/decision-tree.png index 4c31358d52..352c7c6471 100644 Binary files a/sparks/img/U2/decision-tree.png and b/sparks/img/U2/decision-tree.png differ diff --git a/sparks/img/U2/lab03/Screen Recording 2024-03-13 at 5.38.27 PM.mov b/sparks/img/U2/lab03/Screen Recording 2024-03-13 at 5.38.27 PM.mov new file mode 100644 index 0000000000..0763e969dc Binary files /dev/null and b/sparks/img/U2/lab03/Screen Recording 2024-03-13 at 5.38.27 PM.mov differ diff --git a/sparks/img/U2/lab03/Screen Shot 2024-03-13 at 6.10.27 PM.png b/sparks/img/U2/lab03/Screen Shot 2024-03-13 at 6.10.27 PM.png new file mode 100644 index 0000000000..f9095f9810 Binary files /dev/null and b/sparks/img/U2/lab03/Screen Shot 2024-03-13 at 6.10.27 PM.png differ diff --git a/sparks/img/U2/lab03/duplicate-block-definition.png b/sparks/img/U2/lab03/duplicate-block-definition.png new file mode 100644 index 0000000000..2bdc3f0509 Binary files /dev/null and b/sparks/img/U2/lab03/duplicate-block-definition.png differ diff --git a/sparks/img/U2/lab03/microphone(spectrum)-reporting.png b/sparks/img/U2/lab03/microphone(spectrum)-reporting.png index c61c2fc1ee..8aa798ddbc 100644 Binary files a/sparks/img/U2/lab03/microphone(spectrum)-reporting.png and b/sparks/img/U2/lab03/microphone(spectrum)-reporting.png differ diff --git a/sparks/img/U2/lab03/oscilloscope-core-1.png b/sparks/img/U2/lab03/oscilloscope-core-1.png index d8e0bdc934..f042df6061 100644 Binary files a/sparks/img/U2/lab03/oscilloscope-core-1.png and b/sparks/img/U2/lab03/oscilloscope-core-1.png differ diff --git a/sparks/img/U2/lab03/oscilloscope-core-2.png b/sparks/img/U2/lab03/oscilloscope-core-2.png index 8f5a7c2caa..993301dffe 100644 Binary files a/sparks/img/U2/lab03/oscilloscope-core-2.png and b/sparks/img/U2/lab03/oscilloscope-core-2.png differ diff --git a/sparks/img/U2/lab03/samplex150.png b/sparks/img/U2/lab03/samplex150.png index 61e2f293da..58c7f4880b 100644 Binary files a/sparks/img/U2/lab03/samplex150.png and b/sparks/img/U2/lab03/samplex150.png differ diff --git a/sparks/img/U2/lab03/set-variable-forever-show-volume-samples.png b/sparks/img/U2/lab03/set-variable-forever-show-volume-samples.png new file mode 100644 index 0000000000..58e30f46dc Binary files /dev/null and b/sparks/img/U2/lab03/set-variable-forever-show-volume-samples.png differ diff --git a/sparks/img/U2/lab03/show-frequencies.png b/sparks/img/U2/lab03/show-frequencies.png new file mode 100644 index 0000000000..cb7b236de6 Binary files /dev/null and b/sparks/img/U2/lab03/show-frequencies.png differ diff --git a/sparks/img/U2/lab03/show-volume-samples-code.png b/sparks/img/U2/lab03/show-volume-samples-code.png deleted file mode 100644 index 12157a743a..0000000000 Binary files a/sparks/img/U2/lab03/show-volume-samples-code.png and /dev/null differ diff --git a/sparks/img/U2/lab03/show-volume-samples-comments.png b/sparks/img/U2/lab03/show-volume-samples-comments.png new file mode 100644 index 0000000000..69d300a424 Binary files /dev/null and b/sparks/img/U2/lab03/show-volume-samples-comments.png differ diff --git a/sparks/img/U2/lab03/show-volume-samples-definition.png b/sparks/img/U2/lab03/show-volume-samples-definition.png new file mode 100644 index 0000000000..c1e6cb8602 Binary files /dev/null and b/sparks/img/U2/lab03/show-volume-samples-definition.png differ diff --git a/sparks/img/U2/lab03/show-volume-samples.png b/sparks/img/U2/lab03/show-volume-samples.png new file mode 100644 index 0000000000..052874b052 Binary files /dev/null and b/sparks/img/U2/lab03/show-volume-samples.png differ diff --git a/sparks/img/U2/lab03/sound-visualizer-with-labels.gif b/sparks/img/U2/lab03/sound-visualizer-with-labels.gif new file mode 100644 index 0000000000..c8a824b357 Binary files /dev/null and b/sparks/img/U2/lab03/sound-visualizer-with-labels.gif differ diff --git a/sparks/img/U2/lab03/spectrum-analyzer-core.png b/sparks/img/U2/lab03/spectrum-analyzer-core.png new file mode 100644 index 0000000000..1b87e62bd7 Binary files /dev/null and b/sparks/img/U2/lab03/spectrum-analyzer-core.png differ diff --git a/sparks/img/U2/lab03/spectrum-analyzer-with-labels.gif b/sparks/img/U2/lab03/spectrum-analyzer-with-labels.gif new file mode 100644 index 0000000000..cdb6e975c8 Binary files /dev/null and b/sparks/img/U2/lab03/spectrum-analyzer-with-labels.gif differ diff --git a/sparks/img/U2/lab03/spectrum-analyzer.gif b/sparks/img/U2/lab03/spectrum-analyzer.gif new file mode 100644 index 0000000000..587ad75343 Binary files /dev/null and b/sparks/img/U2/lab03/spectrum-analyzer.gif differ diff --git a/sparks/img/U2/lab04/attack-router.png b/sparks/img/U2/lab04/attack-router.png new file mode 100644 index 0000000000..917952f4ea Binary files /dev/null and b/sparks/img/U2/lab04/attack-router.png differ diff --git a/sparks/img/U2/lab04/cut-cable.png b/sparks/img/U2/lab04/cut-cable.png new file mode 100644 index 0000000000..24ec3d46b4 Binary files /dev/null and b/sparks/img/U2/lab04/cut-cable.png differ diff --git a/sparks/img/U2/lab04/destroy-router.png b/sparks/img/U2/lab04/destroy-router.png new file mode 100644 index 0000000000..f657349e04 Binary files /dev/null and b/sparks/img/U2/lab04/destroy-router.png differ diff --git a/sparks/img/U2/lab04/initialize-routers.png b/sparks/img/U2/lab04/initialize-routers.png new file mode 100644 index 0000000000..f060f02b3f Binary files /dev/null and b/sparks/img/U2/lab04/initialize-routers.png differ diff --git a/sparks/img/U2/lab04/router-setup.png b/sparks/img/U2/lab04/router-setup.png new file mode 100644 index 0000000000..99e791c32b Binary files /dev/null and b/sparks/img/U2/lab04/router-setup.png differ diff --git a/sparks/img/U2/lab04/router.jpg b/sparks/img/U2/lab04/router.jpg new file mode 100644 index 0000000000..51096a598c Binary files /dev/null and b/sparks/img/U2/lab04/router.jpg differ diff --git a/sparks/img/U2/lab04/send-message.png b/sparks/img/U2/lab04/send-message.png new file mode 100644 index 0000000000..f6c9578771 Binary files /dev/null and b/sparks/img/U2/lab04/send-message.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image10.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image10.png new file mode 100644 index 0000000000..8e978cbd50 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image10.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image11.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image11.png new file mode 100644 index 0000000000..57164e455f Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image11.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image13.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image13.png new file mode 100644 index 0000000000..6cc63ca217 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image13.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image15.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image15.png new file mode 100644 index 0000000000..6046a4c682 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image15.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image16.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image16.png new file mode 100644 index 0000000000..a5e39c0941 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image16.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image17.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image17.png new file mode 100644 index 0000000000..dca598124e Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image17.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image18.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image18.png new file mode 100644 index 0000000000..3201420ef8 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image18.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image2.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image2.png new file mode 100644 index 0000000000..cd1317c666 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image2.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image20.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image20.png new file mode 100644 index 0000000000..90d27f9ac8 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image20.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image21.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image21.png new file mode 100644 index 0000000000..b93273a2a2 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image21.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image23.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image23.png new file mode 100644 index 0000000000..47ba5c77ae Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image23.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image24.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image24.png new file mode 100644 index 0000000000..9a3aa52e09 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image24.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image26.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image26.png new file mode 100644 index 0000000000..61ef9596c7 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image26.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image3.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image3.png new file mode 100644 index 0000000000..eb580f103b Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image3.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image5.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image5.png new file mode 100644 index 0000000000..3faacdeddf Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image5.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image6.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image6.png new file mode 100644 index 0000000000..4e0b87e784 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image6.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image8.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image8.png new file mode 100644 index 0000000000..f572fdb80f Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image8.png differ diff --git a/sparks/img/U2/lab05/Lab_ Decision Trees/image9.png b/sparks/img/U2/lab05/Lab_ Decision Trees/image9.png new file mode 100644 index 0000000000..6ca7b7e91d Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Decision Trees/image9.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/LabMachinelearning_Linearregression_.html b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/LabMachinelearning_Linearregression_.html new file mode 100644 index 0000000000..1a2a42e139 --- /dev/null +++ b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/LabMachinelearning_Linearregression_.html @@ -0,0 +1 @@ +

Get data (& exercise!)        1

Split the data        2

Digitize the data        3

Add variables        4

Build the model        5

Visualize!        6

Test the model        7

Make predictions        8

Hula Hoop Data        9

Teachers Resources        10

Lesson Plan        10

Standards        10

Perhaps you've heard of "AI": artificial intelligence. AI describes any strategy that helps a computer make smart decisions, like being able to make predictions about the future or being able to recognize the objects in an image.

One way to make a program smarter is to use machine learning: you feed the computer some data, the program learns from the data to build a model of the world, and then the program can make predictions or classifications based on its model of the world.

It sounds a lot like how humans learn about the world, right? Starting from childhood, we see more and more examples of things ("red apple!" "green apple!"), we start to make connections and form an idea in our head, and then we can apply our knowledge to new examples ("oh, a pink apple!"). Of course, we don't always get it right (a peach can be a very confusing fruit for a toddler who's only ever seen apples!). That's true of machine learning too: it's only as good as the data that goes into it and the algorithm that learns from the data.

In this lab, you'll use machine learning to teach a Snap program about the world, going through these sequence of steps:

Get data (& exercise!)

Here's the question we're hoping our AI can answer: If all the students at your school stood in a line holding hands, how long would it take them to pass a hula hoop from one end of the line to the other?

✏️ First, make your own prediction and write it down on a paper or post-it note. Keep that paper or pass it to your teacher so they can put up all the predictions.

Now you're going to use a computer to answer the question, since it could take a REALLY long time to pass that hula hoop, and you probably can't spend all day in a circle. Plus, if you build a model that answers that question, you could then answer other questions, like other schools, the population of your town, etc.

The plan: You'll do this activity in increasing larger groups in your class, until you have data points for a range of sizes. That will become the input data for the model. The hope is that the model can learn from that data set and make predictions about much larger numbers.

Instructions:

Split the data

Whenever we build a machine learning model, we need some sort of validation: a test of whether the model has correctly learned about the world. One form of validation is to split the original data into training data and test data, and then checking predictions on the test data to see how close the predictions are to the actual data.

So the sequence of steps is actually more like this:

How many data points should you reserve for the test data set? Often, machine learning engineers do an 80/20 split, keeping 80% of the original data as training data and 20% for validation. Mark a few of the rows in your sheet with stars to indicate that they'll be part of the test data set, at least two rows but not more than 20%. You don't have a lot of data to start off with, so if you reserve too much for the test data, there won't be enough training data!

Digitize the data

Download this starter project.

Since your data is just on a piece of paper right now, the first step is to digitize the data.

Your data table is really a collection of data points, where each number of people is the x value and the amount of time taken is the y value. So you'll store it as a list of points in Snap.

Drag a list block into the main area, then drag a point block into the first slot.

Write the data point in that point block, putting the number of people in the first slot and then the time taken in the second slot.

Click on the block and you should see a table that looks like your actual table (but with only one row so far):

By the way, the point block is actually creating a 2-item list (you can peek inside the block definition to see!), but using the point block instead of a list block makes the program much easier to read.

To add the rest of your data, keep following the same process:

  1. Click the outer right arrow to add a new slot to the outer list block, representing a data point.
  2. Drag a point block into the newly created slot.
  3. Type the number of people in the first slot of that block and the time taken in the second slot.

You should only be adding the training data points to this first list. Leave out the rows that you're saving as the test data points.

When you're done, clicking on the block should yield a table that looks familiar, minus the test data rows:

Now make another list for the remaining rows that you've designated as the test data.

Add variables

Oftentimes in programming, we need to be able to reuse a piece of data multiple times. In this case, we're going to be reusing the data points in a few places. Instead of repeating the same list both times, it's more convenient to store the list in a variable. A variable has a name and a value. Once you store some value in a variable, you can simply reference the variable name when you want to use that data again.

To create a variable, click "Make a variable" and type the variable name "training data" in the pop-up. That variable will now show up in the sidebar, so that you can drag its name into any slot. A monitor for that variable will also show up on the stage along with its current value. That can be useful for debugging, but you can also un-select the checkbox to hide the stage monitor.

Now your program has a variable named training data, but it isn't storing any value yet. For that, drag the set variable block into the main area.

Instead of a slot, this block has a dropdown which shows you all the possible variable names in the program. Select "training data" from the dropdown and then drag the list block from earlier into the right-hand slot.

Now do the same for the test data. Make a new variable named "test data", and use another set variable block to store the test data list in that variable.

Build the model

It's machine learning time! Here's a reminder of the process we're following:

Since we now have the training data stored in a variable, let's build a model based on that data.

First though, make a new variable called "model" to store the model. Drag another set variable block and snap it below the first two. Select "model" from the dropdown.

What about the value? That will be the actual model of the world built by the machine learning algorithm. Drag the build model block into the right-hand slot.

That model has a slot for the training data, which you now have stored in a variable. Instead of dragging the whole list into the slot, drag the variable name from the script variables block into the slot instead.

So, a model is now built, but what is a model really? Let's step back and…

Visualize!

The type of machine learning that we're using in this lab is called linear regression. It only works if there is a linear relationship between the data points - i.e. the amount of time increases at the same rate as the number of people. It learns that rate, and uses it for prediction.

We can visualize how the model works by making a graph of the training data.

Drag the make graph block into the main area. This block takes two input parameters: the first is the training data and the second is the model. Conveniently, those are already stored in variables! Drag the variable names into the block.

Click the whole sequence of blocks to build the model and make the graph. You should see a graph in the stage like this one:

This graph shows the data as blue circles, but it also shows a line that fits those points pretty well. That line represents the model, and the equation of the line can be used to predict the amount of time for *any* number of people.

Test the model

How good is the model? How accurately can that line predict times for group sizes that were *not* in the training data?

One way to check the quality of the model is to calculate the average error: how far off the predicted value is from the actual value, on average. Drag the calculate average error block into the main area.

The block takes two input parameters, the test data and the model. You've got both of those stored in variables, so just drag the variable names into the slots. Click the block to see the average error. For the sample test data, I got an average error of 2 seconds, which seems pretty reasonable to me.

🤔  What error did you get? Does it feel like a reasonable error to you? You could compare with other groups in the class. If it's not, you may need more training data. There might have been an issue with the timekeeping in your original data or just not enough data points.

Make predictions

Remember the process? We're at the final step! Our program uses basic machine learning to build a model of the world, and we've tested that model on test data to validate that it has an understanding of the world. It's time to make some predictions...

You can make a prediction for any number of people using the prediction block:

Drag the model variable into the first slot and type any value in the second slot. That slot is called the x value, since that's how the number of people is represented on the graph, but for this situation, you can think of it as the number of people. Click the block to see the prediction.

If that prediction seems reasonable, it's time to answer the original question: how long would it take to pass the hula hoop amongst all the students in your school? Put the number of students in the prediction block and check out the result.

Discuss:


Worksheet: Hula Hoop Data

Number of people

Time (seconds)

2


Teachers Resources

Lesson Plan

Standards

2-DA-09

Refine computational models based on the data they have generated.

A model may be a programmed simulation of events or a representation of how various data is related. In order to refine a model, students need to consider which data points are relevant, how data points relate to each other, and if the data is accurate. For example, students may make a prediction about how far a ball will travel based on a table of data related to the height and angle of a track. The students could then test and refine their model by comparing predicted versus actual results and considering whether other factors are relevant (e.g., size and mass of the ball). Additionally, students could refine game mechanics based on test outcomes in order to make the game more balanced or fair.

Practice(s): Creating Computational Artifacts, Developing and Using Abstractions: 5.3, 4.4

2-AP-11

Create clearly named variables that represent different data types and perform operations on their values.

A variable is like a container with a name, in which the contents may change, but the name (identifier) does not. When planning and developing programs, students should decide when and how to declare and name new variables. Students should use naming conventions to improve program readability. Examples of operations include adding points to the score, combining user input with words to make a sentence, changing the size of a picture, or adding a name to a list of people.

Practice(s): Creating Computational Artifacts: 5.1, 5.2

\ No newline at end of file diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image1.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image1.png new file mode 100644 index 0000000000..95e226ac4f Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image1.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image10.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image10.png new file mode 100644 index 0000000000..04784be990 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image10.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image11.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image11.png new file mode 100644 index 0000000000..a3eb9bd2de Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image11.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image12.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image12.png new file mode 100644 index 0000000000..7cd5ab3717 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image12.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image13.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image13.png new file mode 100644 index 0000000000..5701ceb7e6 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image13.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image14.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image14.png new file mode 100644 index 0000000000..441e8c864a Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image14.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image15.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image15.png new file mode 100644 index 0000000000..0f72cc1c48 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image15.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image16.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image16.png new file mode 100644 index 0000000000..efaeaf3a6a Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image16.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image2.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image2.png new file mode 100644 index 0000000000..94b0b452b8 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image2.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image3.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image3.png new file mode 100644 index 0000000000..96a381d1b5 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image3.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image4.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image4.png new file mode 100644 index 0000000000..17bd9d47a9 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image4.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image5.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image5.png new file mode 100644 index 0000000000..2951b75981 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image5.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image6.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image6.png new file mode 100644 index 0000000000..a93e56ea44 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image6.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image7.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image7.png new file mode 100644 index 0000000000..b9838bff90 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image7.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image8.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image8.png new file mode 100644 index 0000000000..b158daf84e Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image8.png differ diff --git a/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image9.png b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image9.png new file mode 100644 index 0000000000..5918428b58 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Machine learning (Linear regression)/images/image9.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/LabMovierecommender.html b/sparks/img/U2/lab05/Lab_ Movie recommender/LabMovierecommender.html new file mode 100644 index 0000000000..5449770505 --- /dev/null +++ b/sparks/img/U2/lab05/Lab_ Movie recommender/LabMovierecommender.html @@ -0,0 +1 @@ +

Lab: Movie recommender        2

A recommendation algorithm        2

Programming the recommender        3

Looking up movies        3

Recording the genres        4

Counting genres        5

Calculating the top genre        6

Recommending a movie        7

Evaluate the algorithm        7

Brainstorm: New recommendation algorithms        8

Discussion: The impact of recommendations        8

Teacher Resources        9

Lesson Plan        10

Standards        10

Lab: Movie recommender

Have you ever been recommended something by an app? Perhaps it suggested a new product for you to buy, a new song for your playlist, or a video similar to your favorite videos?

Many web applications include recommendations, since they can be both good for the user (finding something new you enjoy!) and good for the application (more usage often means more profit).

In this lab, we'll build a movie recommendation engine, using lots of lists along the way.

A recommendation algorithm

An algorithm is a series of steps to solve a problem. We need to come up with an algorithm to recommend movies to someone.

Watch this video to get an idea for one possible algorithm:

Transcript for video skit:

PF: Hey Dan, I bet I can come up with amazing movie recommendations with you, movies you would have never thought of watching before but you will LOVE.

DG: Oh reallly??

PF: Yep! I just need a list of a few movies you already like. What's your favorite movie?

DG: Toy Story

PF: Okay cool, cool, animated family adventure. What's your next favorite movie?

DG: Toy Story II

PF: Uhh okay, so you definitely like 3d animated movies. What's another movie you love?

DG: Toy Story III

PF: AHGHGHGH DAN! I give up. Go watch Toy Story 4. Hmph.

M: Try it with me!

PF: Okkkay, what's your favorite movie?

M: Toy Story

PF: :( *sigh*grump* Next favorite movie?

M: Back to the Future

PF: *perks up* Okay, now we're getting somewhere. One more?

M: How to Train Your Dragon

PF: Okay, drumroll please! I predict that you would love Howl's Moving Castle.

M: Sweet I'll check it out!

Pamela's movie recommendation algorithm was just in her head, but many computer programs use similar recommendations based on a user's history. Those programs need enough data to make a good suggestion, and that data can't all be basically the same. That's the difference between data and information: data is a bunch of data points that are true about the world, information is what we learn from those data points[a]. A long list of data doesn't always mean a lot of information, but a short list of data might be chock full of information.

So here's a possible way to turn Pamela's algorithm into a computer program:

  1. Get a list of favorite movies from the user (at least 3 movies, but more is better!)
  2. Look up each movie and record its genre.
  3. Count how often the same genre appears across the user's favorite movies.
  4. Calculate the top genre according to the counts
  5. Recommend a movie that has the same genre as the top genre.

Programming the recommender

Looking up movies

Start by downloading the starter project.

First, we need a way to discover information about a movie. Snap doesn't know anything about movies, but there are other websites that specialize in movies. Some of those websites make it possible for other programmers (like us) to request movie information from thei`r server, via an API. That means we can use Snap to look up movies!

[ Diagram of browser -> movie server , movie info? request, movie info! response][b]

We've written a look up movie block that uses the OMDb API. All you need to do is drag the block into the main area and type in a movie title.

When you click on that block, it will show you an empty result if it couldn't find the movie. The title must be spelled correctly. For example, "Toy Story 1" wouldn't find any results since the actual title is "Toy Story 1".

However, a successful movie lookup will show a list of details about the movie - the title, year, rating, duration, and genres.

This is an example of a block that reports a list. In fact, it reports a list of lists, which is presented as a table in the output bubble. Each item in the list has two items, the label for that piece of data, and the value of that piece of data, like "Title" and "Toy Story". All that data came from the OMDb API.

Recording the genres

Now that you've verified you can look up a movie by its title, you can use another block that will report just the genres from that movie's information.

Drag the genres of movie block into the main area, and drag the look up movie block into the input slot.

Viola, another list! This time, the block reports the list of genres, based on the information it got from the OMDb API about the movie.

Counting genres[c]

The next step is to look up multiple movies and count the genres across those movies. There's another block for that, count genres. Drag that into the main area.

Notice something different about this block? Instead of a blank, it has an icon that looks like a list. That indicates that the input parameter must be a list; it can't be a number or text. Drag a list block directly from the sidebar into that icon.

Now drag the previous genres of movie block into that first list slot.

For only one movie, the count should be 1 for every genre, since it can't have seen a genre more than once yet.

Keep adding more movie titles by duplicating the genres of movie block and typing in a different movie title.

Each time you add a movie, click the block and see how the counts change. If they don't change, you may have typed the title incorrectly. You can always double-check your title works by dragging the look up movie block out of that big nested block and seeing what it reports.

Once you've added a bunch of movies, some genres will probably have higher counts than others. (Unless all your favorite movies are just sequels of Toy Story, of course.)

Calculating the top genre

According to our algorithm, we're going to recommend a movie based on the top genre. That's the one that has the highest count in the output from the genre counts block. There's another block that does that calculation: top genre.

This block also takes a list, and that list should be the output of the count genres block that we just used.

Once you've moved the copy into the top genre block, click to make sure it reports the most common genre across those movies.

Recommending a movie

Okay, we're nearly there! Now that we know the top genre, we can recommend a movie based on that genre. That's the job of the recommend movie for genre block! Drag one into the main area.

This block also takes a list input.  Duplicate the list from the last step and drag it over the list icon. Click the block for a movie recommendation.

Click again for another recommendation! The block will suggest a random movie based on the top genre, so you can get a few different suggestions for your movie watching pleasure.

You can also try adding more movies to the original list to see if the recommendations change.

Evaluating the recommender

We were able to build a recommendation algorithm relatively quickly, but how well does it work? In fact, how do we even know how well it works? Here's one approach:

  1. For each recommendation you received, tally whether you were excited by the recommendation and would probably try watching it, or whether you wouldn't even attempt to watch the movie.
  2. Combine your tallies with your classmate's tallies.
  3. Calculate the average percentage across the whole class.

Here's an example:

Classmate

Excited

Meh

Percentage

Your Name

3

2

3/5 = 60%

Their Name

4

1

4/5 = 80%

Average

70%

If the recommendation algorithm generated movie ideas that were exciting 70% of the time, that sounds like a pretty decent algorithm, or at least, better than a completely random movie suggestion.

We'd have an even better idea of the algorithm quality if you could all go watch all the movies and report back whether you actually liked them, but that could take a few weeks, so this will have to be good enough for now.

🤔 YouTube uses a recommendation algorithm to suggest videos to users. How do you think they decide whether their algorithm is working or not?

Brainstorm: New recommendation algorithms

This is definitely not the best movie recommendation algorithm in the world. With a classmate or your whole class, brainstorm more ideas for ways to either improve this genre-based algorithm or to come up with a completely different strategy for recommending movies.

📝 Write out your algorithm idea as a step-by-step list or draw a diagram, whatever you prefer.

Present your algorithm to your classmates and give each other feedback. You might even combine your ideas to create the ultimate algorithm. We won't implement your algorithm today, but one day you could.

Discussion: The impact of recommendations

Recommendations can be a benefit to the user, helping them discover more things they're interested in.

But consider these situations that can arise from recommendations:

More is not always better for the user, even if it means more usage for the app.

An organization actually tracked user happiness based on time spent in mobile apps and made this graph of the results:

For many apps, user happiness was correlated with spending less time on the app, usually between 10-40 minutes each day.

🤔 What do you think? When are recommendations a good thing? Is there a way that apps can present recommendations to users that can help them make healthy decisions about how to spend their time and money? Discuss with your classmates.

Teacher Resources

Lesson Plan


Standards

2-AP-16

Incorporate existing code, media, and libraries into original programs, and give attribution.

Building on the work of others enables students to produce more interesting and powerful creations. Students should use portions of code, algorithms, and/or digital media in their own programs and websites. At this level, they may also import libraries and connect to web application program interfaces (APIs). For example, when creating a side-scrolling game, students may incorporate portions of code that create a realistic jump movement from another person's game, and they may also import Creative Commons-licensed images to use in the background. Students should give attribution to the original creators to acknowledge their contributions.

Practice(s): Developing and Using Abstractions, Creating Computational Artifacts, Communicating About Computing: 4.2, 5.2, 7.3

[a]The point on data vs. information was inspired by a chat with Dan, but I'm not sure if it still flows.

[b]Make this diagram

[c]Dave also has a version here that uses map: https://snap.berkeley.edu/snap/snap.html#present:Username=dcbriccetti&ProjectName=Genre%20Recommender%20FP%2C%20refactored

\ No newline at end of file diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image1.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image1.png new file mode 100644 index 0000000000..9320307372 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image1.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image10.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image10.png new file mode 100644 index 0000000000..3a739f4a35 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image10.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image11.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image11.png new file mode 100644 index 0000000000..b5c61dc024 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image11.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image12.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image12.png new file mode 100644 index 0000000000..1289b30ae1 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image12.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image13.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image13.png new file mode 100644 index 0000000000..83e1e0c59e Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image13.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image14.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image14.png new file mode 100644 index 0000000000..92a850cff3 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image14.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image2.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image2.png new file mode 100644 index 0000000000..b1324b3c78 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image2.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image3.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image3.png new file mode 100644 index 0000000000..d923bfcd4d Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image3.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image4.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image4.png new file mode 100644 index 0000000000..b656390156 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image4.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image5.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image5.png new file mode 100644 index 0000000000..c507574303 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image5.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image6.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image6.png new file mode 100644 index 0000000000..fe620016ad Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image6.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image7.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image7.png new file mode 100644 index 0000000000..a6fba98f19 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image7.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image8.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image8.png new file mode 100644 index 0000000000..3d3267c487 Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image8.png differ diff --git a/sparks/img/U2/lab05/Lab_ Movie recommender/images/image9.png b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image9.png new file mode 100644 index 0000000000..1be0f1e71d Binary files /dev/null and b/sparks/img/U2/lab05/Lab_ Movie recommender/images/image9.png differ diff --git a/sparks/img/U2/lab05/declare-vars.png b/sparks/img/U2/lab05/declare-vars.png new file mode 100644 index 0000000000..1036531d08 Binary files /dev/null and b/sparks/img/U2/lab05/declare-vars.png differ diff --git a/sparks/img/U2/lab05/generator-repeated-short-noise-for-each.png b/sparks/img/U2/lab05/generator-repeated-short-noise-for-each.png new file mode 100644 index 0000000000..7b44b223f1 Binary files /dev/null and b/sparks/img/U2/lab05/generator-repeated-short-noise-for-each.png differ diff --git a/sparks/img/U2/lab05/generator-repeated-short-noise.png b/sparks/img/U2/lab05/generator-repeated-short-noise.png new file mode 100644 index 0000000000..f75caf424c Binary files /dev/null and b/sparks/img/U2/lab05/generator-repeated-short-noise.png differ diff --git a/sparks/img/U2/lab05/generator-sample-rate.png b/sparks/img/U2/lab05/generator-sample-rate.png new file mode 100644 index 0000000000..5d6be0c2e7 Binary files /dev/null and b/sparks/img/U2/lab05/generator-sample-rate.png differ diff --git a/sparks/img/U2/lab05/generator-sawtooth.png b/sparks/img/U2/lab05/generator-sawtooth.png new file mode 100644 index 0000000000..c2eaf52fe4 Binary files /dev/null and b/sparks/img/U2/lab05/generator-sawtooth.png differ diff --git a/sparks/img/U2/lab05/generator-short-noise.png b/sparks/img/U2/lab05/generator-short-noise.png new file mode 100644 index 0000000000..6a7aa4d690 Binary files /dev/null and b/sparks/img/U2/lab05/generator-short-noise.png differ diff --git a/sparks/img/U2/lab05/generator-square.png b/sparks/img/U2/lab05/generator-square.png new file mode 100644 index 0000000000..abc0b5408f Binary files /dev/null and b/sparks/img/U2/lab05/generator-square.png differ diff --git a/sparks/img/U2/lab05/go-play-outside-reporting.png b/sparks/img/U2/lab05/go-play-outside-reporting.png new file mode 100644 index 0000000000..3deda846ed Binary files /dev/null and b/sparks/img/U2/lab05/go-play-outside-reporting.png differ diff --git a/sparks/img/U2/lab05/go-play-outside.png b/sparks/img/U2/lab05/go-play-outside.png new file mode 100644 index 0000000000..1d83cbcc39 Binary files /dev/null and b/sparks/img/U2/lab05/go-play-outside.png differ diff --git a/sparks/img/U2/lab05/input-humidity.png b/sparks/img/U2/lab05/input-humidity.png new file mode 100644 index 0000000000..8adba0a2b0 Binary files /dev/null and b/sparks/img/U2/lab05/input-humidity.png differ diff --git a/sparks/img/U2/lab05/input-outlook-options-popup.png b/sparks/img/U2/lab05/input-outlook-options-popup.png new file mode 100644 index 0000000000..f2cf2cc866 Binary files /dev/null and b/sparks/img/U2/lab05/input-outlook-options-popup.png differ diff --git a/sparks/img/U2/lab05/input-outlook-slot-options.png b/sparks/img/U2/lab05/input-outlook-slot-options.png new file mode 100644 index 0000000000..5ef2bf5b38 Binary files /dev/null and b/sparks/img/U2/lab05/input-outlook-slot-options.png differ diff --git a/sparks/img/U2/lab05/input-windy.png b/sparks/img/U2/lab05/input-windy.png new file mode 100644 index 0000000000..549dbfc1d0 Binary files /dev/null and b/sparks/img/U2/lab05/input-windy.png differ diff --git a/sparks/img/U2/lab05/noise-watcher.png b/sparks/img/U2/lab05/noise-watcher.png new file mode 100644 index 0000000000..9b1f53cb1b Binary files /dev/null and b/sparks/img/U2/lab05/noise-watcher.png differ diff --git a/sparks/img/U2/lab05/pick-random-floats.png b/sparks/img/U2/lab05/pick-random-floats.png new file mode 100644 index 0000000000..759551486b Binary files /dev/null and b/sparks/img/U2/lab05/pick-random-floats.png differ diff --git a/sparks/img/U2/lab05/pick-random-integers.png b/sparks/img/U2/lab05/pick-random-integers.png new file mode 100644 index 0000000000..f5d62460af Binary files /dev/null and b/sparks/img/U2/lab05/pick-random-integers.png differ diff --git a/sparks/img/U2/lab05/play-sound-noise.png b/sparks/img/U2/lab05/play-sound-noise.png new file mode 100644 index 0000000000..08a717b686 Binary files /dev/null and b/sparks/img/U2/lab05/play-sound-noise.png differ diff --git a/sparks/img/U2/lab05/play-sound-repeated-short-noise.png b/sparks/img/U2/lab05/play-sound-repeated-short-noise.png new file mode 100644 index 0000000000..1d2f7ec772 Binary files /dev/null and b/sparks/img/U2/lab05/play-sound-repeated-short-noise.png differ diff --git a/sparks/img/U2/lab05/play-sound-short-noise.png b/sparks/img/U2/lab05/play-sound-short-noise.png new file mode 100644 index 0000000000..6494b43274 Binary files /dev/null and b/sparks/img/U2/lab05/play-sound-short-noise.png differ diff --git a/sparks/img/U2/lab05/repeat-times-repeated-short-noise.png b/sparks/img/U2/lab05/repeat-times-repeated-short-noise.png new file mode 100644 index 0000000000..e9afdaf6ae Binary files /dev/null and b/sparks/img/U2/lab05/repeat-times-repeated-short-noise.png differ diff --git a/sparks/img/U2/lab05/repeated-short-noise.png b/sparks/img/U2/lab05/repeated-short-noise.png new file mode 100644 index 0000000000..8b44543da5 Binary files /dev/null and b/sparks/img/U2/lab05/repeated-short-noise.png differ diff --git a/sparks/img/U2/lab05/repeated-shorter-noise.png b/sparks/img/U2/lab05/repeated-shorter-noise.png new file mode 100644 index 0000000000..4c94b1fe00 Binary files /dev/null and b/sparks/img/U2/lab05/repeated-shorter-noise.png differ diff --git a/sparks/img/U2/lab05/sample-rate-mic-samples-reporting.png b/sparks/img/U2/lab05/sample-rate-mic-samples-reporting.png new file mode 100644 index 0000000000..e237a57698 Binary files /dev/null and b/sparks/img/U2/lab05/sample-rate-mic-samples-reporting.png differ diff --git a/sparks/img/U2/lab05/sawtooth-sample-watcher.png b/sparks/img/U2/lab05/sawtooth-sample-watcher.png new file mode 100644 index 0000000000..271ddd80bc Binary files /dev/null and b/sparks/img/U2/lab05/sawtooth-sample-watcher.png differ diff --git a/sparks/img/U2/lab05/short-noise.png b/sparks/img/U2/lab05/short-noise.png new file mode 100644 index 0000000000..c2c96fa9fb Binary files /dev/null and b/sparks/img/U2/lab05/short-noise.png differ diff --git a/sparks/img/U2/lab05/shorter-noise.png b/sparks/img/U2/lab05/shorter-noise.png new file mode 100644 index 0000000000..b5d10b8ec6 Binary files /dev/null and b/sparks/img/U2/lab05/shorter-noise.png differ diff --git a/sparks/img/U2/lab05/show-repeated-short-noise.png b/sparks/img/U2/lab05/show-repeated-short-noise.png new file mode 100644 index 0000000000..6d5df797cd Binary files /dev/null and b/sparks/img/U2/lab05/show-repeated-short-noise.png differ diff --git a/sparks/img/U2/lab05/show-short-noise.png b/sparks/img/U2/lab05/show-short-noise.png new file mode 100644 index 0000000000..0caf7636ab Binary files /dev/null and b/sparks/img/U2/lab05/show-short-noise.png differ diff --git a/sparks/prog/U2/lab04/routing-protocols.xml b/sparks/prog/U2/lab04/routing-protocols.xml new file mode 100644 index 0000000000..91b76a876d --- /dev/null +++ b/sparks/prog/U2/lab04/routing-protocols.xml @@ -0,0 +1 @@ +data:image/png;base64,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 forward turn turnLeft setHeading doFaceTowards gotoXY doGotoObject doGlide changeXPosition setXPosition changeYPosition setYPosition bounceOffEdge xPosition yPosition direction doSwitchToCostume doWearNextCostume getCostumeIdx reportGetImageAttribute reportNewCostume reportNewCostumeStretched doSayFor bubble doThinkFor doThink changeEffect setEffect getEffect clearEffects changeScale setScale getScale show hide reportShown goToLayer goBack doScreenshot reportGet alert log playSound doPlaySoundUntilDone doPlaySoundAtRate doStopAllSounds reportGetSoundAttribute reportNewSoundFromSamples doRest doPlayNote doPlayFrequency doSetInstrument doChangeTempo doSetTempo getTempo changeVolume setVolume getVolume changePan setPan getPan playFreq stopFreq clear down up getPenDown setColor setPenColorDimension changePenColorDimension getPenAttribute setBackgroundColor setBackgroundColorDimension changeBackgroundColorDimension changeSize setSize doStamp floodFill write reportPenTrailsAsCostume reportPentrailsAsSVG doPasteOn doCutFrom receiveGo receiveKey receiveInteraction receiveMessage receiveCondition doBroadcast doBroadcastAndWait getLastMessage doWait doWaitUntil doForever doRepeat doUntil doFor doIf doIfElse reportIfElse doStopThis doRun fork evaluate doReport doCallCC reportCallCC doTellTo reportAskFor receiveOnClone createClone newClone removeClone doPauseAll doWarp reportTouchingObject reportTouchingColor reportColorIsTouchingColor reportAspect reportStackSize reportFrameCount reportYieldCount reportThreadCount doAsk reportLastAnswer getLastAnswer reportMouseX reportMouseY reportMouseDown reportKeyPressed reportRelationTo doResetTimer reportTimer getTimer reportAttributeOf reportObject reportURL doSetGlobalFlag reportGlobalFlag reportDate reportAudio doSetVideoTransparency reportVideo reportVariadicSum reportDifference reportVariadicProduct reportQuotient reportRound reportMonadic reportPower reportModulus reportAtan2 reportVariadicMin reportVariadicMax reportRandom reportVariadicEquals reportVariadicNotEquals reportVariadicLessThan reportVariadicLessThanOrEquals reportVariadicGreaterThan reportVariadicGreaterThanOrEquals reportVariadicAnd reportVariadicOr reportNot reportBoolean reportJoinWords reportLetter reportTextAttribute reportUnicode reportUnicodeAsLetter reportIsA reportVariadicIsIdentical reportTextSplit reportJSFunction reportTypeOf reportTextFunction reportCompiled reifyScript reifyReporter reifyPredicate doSetVar doChangeVar doShowVar doHideVar doDeleteAttr doDeclareVariables reportNewList reportNumbers reportCONS reportListItem reportCDR reportListAttribute reportListIndex reportConcatenatedLists reportReshape reportListContainsItem reportListIsEmpty doForEach reportMap reportKeep reportFindFirst reportCombine doAddToList doDeleteFromList doInsertInList doReplaceInList reportPipe receiveUserEdit getPosition reportMousePosition doDefineBlock doSetBlockAttribute doDeleteBlock reportBlockAttribute reportEnvironment
closest farthest random lookup
closest farthest random lookuplookup22closestfalsecheck if end router name is in direct connectionsOnly use if its also in direct connections (Its possible that its been cut off!)otherwise check lookup table to decide which connection to use
remove from connections
4draw a white line from midpoint to router data
data:image/png;base64,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
\ No newline at end of file diff --git a/sparks/prog/U2/routing-protocols.xml b/sparks/prog/U2/routing-protocols.xml deleted file mode 100644 index de40250063..0000000000 --- a/sparks/prog/U2/routing-protocols.xml +++ /dev/null @@ -1 +0,0 @@ -data:image/png;base64,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 forward turn turnLeft setHeading doFaceTowards gotoXY doGotoObject doGlide changeXPosition setXPosition changeYPosition setYPosition bounceOffEdge xPosition yPosition direction doSwitchToCostume doWearNextCostume getCostumeIdx reportGetImageAttribute reportNewCostume reportNewCostumeStretched doSayFor bubble doThinkFor doThink changeEffect setEffect getEffect clearEffects changeScale setScale getScale show hide reportShown goToLayer goBack doScreenshot reportCostumes alert log playSound doPlaySoundUntilDone doPlaySoundAtRate doStopAllSounds reportGetSoundAttribute reportNewSoundFromSamples doRest doPlayNote doPlayFrequency doSetInstrument doChangeTempo doSetTempo getTempo changeVolume setVolume getVolume changePan setPan getPan playFreq stopFreq reportSounds clear down up getPenDown setColor setPenHSVA changePenHSVA getPenAttribute setBackgroundColor setBackgroundHSVA changeBackgroundHSVA changeSize setSize doStamp floodFill write reportPenTrailsAsCostume reportPentrailsAsSVG doPasteOn doCutFrom receiveGo receiveKey receiveInteraction receiveMessage receiveCondition doBroadcast doBroadcastAndWait getLastMessage doSend doWait doWaitUntil doForever doRepeat doUntil doFor doIf doIfElse reportIfElse doStopThis doRun fork evaluate doReport doCallCC reportCallCC doTellTo reportAskFor receiveOnClone createClone newClone removeClone doPauseAll doWarp reportTouchingObject reportTouchingColor reportColorIsTouchingColor reportAspect reportStackSize reportFrameCount reportYieldCount reportThreadCount doAsk reportLastAnswer getLastAnswer reportMouseX reportMouseY reportMouseDown reportKeyPressed reportRelationTo doResetTimer reportTimer getTimer reportAttributeOf reportObject reportURL doSetGlobalFlag reportGlobalFlag reportDate reportGet reportAudio doSetVideoTransparency reportVideo reportSum reportDifference reportProduct reportQuotient reportRound reportMonadic reportPower reportModulus reportAtan2 reportMin reportMax reportRandom reportEquals reportNotEquals reportLessThan reportLessThanOrEquals reportGreaterThan reportGreaterThanOrEquals reportAnd reportOr reportNot reportBoolean reportFalse reportJoinWords reportLetter reportStringSize reportUnicode reportUnicodeAsLetter reportIsA reportIsIdentical reportTextSplit reportJSFunction reportTypeOf reportTextFunction reportCompiled reifyScript reifyReporter reifyPredicate doSetVar doChangeVar doShowVar doHideVar doDeleteAttr doDeclareVariables reportNewList reportNumbers reportCONS reportListItem reportCDR reportListAttribute reportListIndex reportConcatenatedLists reportReshape reportListContainsItem reportListIsEmpty doForEach reportMap reportKeep reportFindFirst reportCombine doAddToList doDeleteFromList doInsertInList doReplaceInListgetPosition doDefineBlock doDeleteBlock doSetBlockAttribute reportBlockAttribute reportThisContext reportMousePosition reportCrossproduct
closest farthest random lookup
closest farthest random lookuplookup22closestfalsecheck if end router name is in direct connectionsOnly use if its also in direct connections (Its possible that its been cut off!)otherwise check lookup table to decide which connection to use
remove from connections
4draw a white line from midpoint to router data
data:image/png;base64,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A-1400B,92.19544457292888C,161.24515496597098F,C,BE,C,BD,C,BB-8070A,92.19544457292888C,80.62257748298549D,C,AE,C,AF,C,AC080B,80.62257748298549A,161.24515496597098E,110.45361017187261D,ED-60-50E,72.80109889280519E10-30C,110.45361017187261F,80.62257748298549D,72.80109889280519A,CB,CF5040E,80.62257748298549D,EB,CA,C
diff --git a/sparks/student-pages/U2/L3/01-visualizing-sound-data.html b/sparks/student-pages/U2/L3/01-visualizing-sound-data.html index f495a1b84e..82113eb4ee 100644 --- a/sparks/student-pages/U2/L3/01-visualizing-sound-data.html +++ b/sparks/student-pages/U2/L3/01-visualizing-sound-data.html @@ -29,26 +29,21 @@

Visualizing Sound Data

-
Can we cover this here?
  • 2-CS-02: Design projects that combine hardware and software components to collect and exchange data. Collecting and exchanging data involves input, output, storage, and processing. When possible, students should select the hardware and software components for their project designs by considering factors such as functionality, cost, size, speed, accessibility, and aesthetics. For example, components for a mobile app could include accelerometer, GPS, and speech recognition. The choice of a device that connects wirelessly through a Bluetooth connection versus a physical USB connection involves a tradeoff between mobility and the need for an additional power source for the wireless device.
  • In this activity, you will explore the sound data from your computer's microphone and learn to draw in Snap!.

    Snap! can access your computer's microphone, so you can create a virtual oscilloscope that shows how the volume detected by the microphone changes over time.
    - animation of an oscilloscope in Snap! that looks like a rapidly changing, horizontal wavey line
    + animation of an oscilloscope in Snap! that looks like a rapidly changing, horizontal wavey line; the horizontal axis is labeled 'volume intensity' and the vertical axis is labeled 'time'

    -
    Add axes to this image.
    -
    -
    clarify that here, our intensity is volume/loudness
    -
    Have PG and BH review this sound stuff. Maybe have Jens, BH, and perhaps even Della review the whole lab.

    Sound Waves

    Sound is created by pressure waves traveling through a material (like air or water). When you hear music, an instrument or speaker (think of a vibrating guitar string, a vibrating drum head, or a vibrating speaker) creates waves of pressure that travel through the air to your eardrum, which transmits the signal through your nerves to your brain. Have you ever heard a sound that was so loud you could feel it? Those were pressure waves that were so big you could sense them with more than just your eardrum!

    @@ -92,16 +87,16 @@

    1. - microphone (volume) reports the current volume value detected by the microphone (Try clicking it while you are making a quiet sound, a loud sound, and no sound.)
      + microphone (volume) reports the current volume value detected by the microphone (Try clicking it while you are making a quiet sound, a loud sound, and no sound.)
      microphone (volume) reporting 5.4169...
    2. - microphone (samples) reports a list of current microphone volume values sampled across a small period of time
      + microphone (samples) reports a list of current microphone volume values sampled across a small period of time.
      microphone (samples) reporting
    3. You may get zeros as output at first. It can take a moment for Snap! to tell your browser to tell your computer to listen to the microphone.
    4. - microphone (resolution) reports the number of values in a microphone (samples) list
      + microphone (resolution) reports the number of values in a microphone (samples) list. Notice that this number appears in the upper left corner of microphone (samples) output (shown above).
      microphone (resolution) reporting 512
    @@ -112,27 +107,22 @@

    puts the sprite's pen tip down so it can draw on the stage -
  • pen up picks the sprite's pen tip up so it stops drawing on the stage
  • -
  • clear clears all pen drawings from the stage
  • -
  • glide (1) secs to x: (0) y:(0) moves the sprite to the (x, y) position typed in the input slots
  • +
  • pen down puts the sprite's pen tip down so it can draw on the stage.
  • +
  • pen up picks the sprite's pen tip up so it stops drawing.
  • +
  • clear clears all pen drawings from the stage.
  • + +
  • go to x: (0) y:(0) and glide (1) secs to x: (0) y:(0) move the sprite to the (x, y) position typed in the input slots. (go does it instantly, and glide lets you see the movement.)
  • +

    -
    include a description of how to see the Snap! axes - -
  • go to x: (0) y:(0) moves the sprite to the (x, y) position typed in the input slots
  • - - -
    -
    1. Experiment with drawing on the Snap! stage.
      1. - Make the sprite go to (0,0), clear the stage, put the pen down, and then make the sprite travel to each of these points in a row: + Make the sprite go to (0, 0), clear the stage, put the pen down, and then make the sprite travel to each of these points in a row:
    - - - -
    In this activity, you learned about oscilloscopes, accessed the sound data from your computer's microphone, and learned how to use the sprite to draw.
    diff --git a/sparks/student-pages/U2/L3/02-oscilloscope.html b/sparks/student-pages/U2/L3/02-oscilloscope.html index c8189f5d07..9aff4d0779 100644 --- a/sparks/student-pages/U2/L3/02-oscilloscope.html +++ b/sparks/student-pages/U2/L3/02-oscilloscope.html @@ -10,25 +10,13 @@ -

    Oscilloscope

    +

    Creating an Oscilloscope

    In this activity, you will create an oscilloscope to visualize the sounds detected by your computer's microphone.
    -
    preview the difference between Time Domain and Frequency Domain
    - - - -
    Can we cover this here?
  • 2-CS-02: Design projects that combine hardware and software components to collect and exchange data. Collecting and exchanging data involves input, output, storage, and processing. When possible, students should select the hardware and software components for their project designs by considering factors such as functionality, cost, size, speed, accessibility, and aesthetics. For example, components for a mobile app could include accelerometer, GPS, and speech recognition. The choice of a device that connects wirelessly through a Bluetooth connection versus a physical USB connection involves a tradeoff between mobility and the need for an additional power source for the wireless device.
  • - -
    In this activity, you will explore the sound data from your computer's microphone.
    - - -
    TG: In order to clarify the axes of an oscilloscope plot, you may want to do a quick unplugged activity where you graph volume intensity over time on the board. Draw a coordinate axes on the board with "intensity" as the label on the vertical axis and "time" as the label on the horizontal axis. Try having one student sing a pitch (or just say a vowel for a long time: "oooooooooo") and vary the volume. As they do, draw a plot of their volume intensity over time. (That is, while moving the pen/marker from left to right at a constant speed across the board, draw the line higher when they get louder and draw the line lower when they get quieter.) Then, do the opposite: ask a student (or the class) to sing (or say a vowel) at the volume level you draw on a new graph. Start with your pen at the middle of the vertical-axis and while moving it from left to right, draw the line higher and lower to indicate the volume at which they should vocalize. This help students understand what an oscilloscope shows and also helps to distinguish "higher and lower volume" from "higher and lower frequency" which will become relevant soon. Note: if students struggle (or you expect them to struggle) to understand this activity on a two dimensional plot, try both parts of the activity on a one-dimensinoal vertical intensity plot first. (TODO: move this 1-D thing to the start of the activity for all students and create a pic of both the 1D and 2D coord systems)
    - - -
    Have they learned pen down, yet?? I don't hitink soo.. Maybe in 2.2?? Maybe it should be added here?
    + +

    Writing Code to Draw One Set of Samples

    - There is a for each block is at the core of the oscilloscope code. In order to plot the microphone volume intensity over time, the sprite should go to each For each microphone volume sample, the sprite will move - Discuss why a for each block is needed, and why the sprite will move (using go to) for each volumne sample.
    + There is a for each block at the core of the oscilloscope code. In order to plot the microphone volume intensity (loudness) over time, the sprite should go to each microphone volume sample.
    for each (sample) in (microphone (samples)) {
 go to x: () y: ()
 }

    +

    As you've seen, every time microphone (samples) runs, it reports a set of samples recorded over a brief period of time. For our oscilloscope, we want to plot that set of samples across the stage, then replace it with the next set of sound samples detected, then replace it again, and so on in order to visualize the signal intensity over time.

    +

    Since we'll plot the samples across the stage horizontally, we need to keep track of how much space each sample gets on the stage.

      +
    1. Open your "Sparks-Making-Noise" project if isn't open already.
    2. You learned about global variables in Unit 2 Lab 1 Activity 6: Storing Songs.

      - Create a global variable called time step to store the ( set to the width of the stage divided by the number of values in the microphone sample set (so that the sprite moves horizontally across the whole stage as it goes through the list of samples) (microphone samples will fit acr - oss width of the Snap! stage by dividing the stage width by the microphone resolution.). Set it's value so that the... think about the timestep stuff

      hint

      -

      set (time step) to (width of (Stage) / microphone (resolution))

      -
    3. -
      To see the dimensions of the stage, click the "Stage" icon in the lower right corner of the Snap! window, select "Backgrounds..." from the Snap! file menu, choose the "XY Grid" and click "Import," and then return to this code, by clicking the "Sprite" icon in the lower right corner and selecting the "Scripts" tab at the top of this scripting area. (Instructions like this will be in the Google doc for students; this is just a preview.) :)
      -
    4. build the inputs to the goto block
    5. -
      - for each (sample) in (microphone (samples)) {
-	go to x: (x position + time step) y: (sample ร— 150)
-} + Create a global variable called sample width to store the amount space each sample gets on the stage. Set it to the width of the stage divided by the microphone resolution (the number of values in the sample set). Click for an example of how to set the value of this variable. +

      set (sample width) to (width of (Stage) / microphone (resolution))

      + +
    6. + The sprite needs to draw the set of volume samples across the stage. For each sample, the sprite should move forward horizontally (the width of one sample) and move vertically to the intensity (loudness) of that sample. Create the for each code by copying the code shown above and completing the inputs to the go to block. +
      Since the sprite will move across the stage throughout one whole set of samples, the horizontal movement must be based on where the sprite is already. Since the volume samples are small, you will need to multiply the intensity value by some scaling factor in order to see the values on the stage; how much you need to multiply by depends on your microphone and the sounds you make.
      + Click if you want an example. +
      + for each (volume sample) in (microphone (samples)) {
+		go to x: (x position + sample width) y: (volume sample ร— 150)
+	}
      +
    7. +
    8. You'll need a few more blocks (such as pen down) to make your code draw the samples, but first: Talk with Your Partner Discuss how this for each code will make your sprite draw a set of samples across the stage.
    -
    recap with anotehr preview of the difference between Time Domain and Frequency Domain
    - -
    In this activity, you learned about oscilloscopes, accessed the sound data from your computer's microphone, and started planning the code for an oscilloscopes.
    - -

    - Below is the complete code for oscilloscope, and here is what it does: -

      -
    • This code creates a time step variable and sets its value so that microphone samples will fit across width of the Snap! stage by dividing the stage width by the microphone resolution.
    • -
    • It moves the sprite to the left center of the Snap! stage, clears the stage, and puts the pen down. This sets up the sprite for to draw one set of microphone (samples) data.
    • -
    • Then to draw each sample volume value, it moves the sprite to the left (by adding time step value to the x) position) and to the volume value (by setting the y position to the sample volume value scaled up 150 times).
    • -
    • The forever block makes this code keep drawing the current microphone sample list, and the warp block makes Snap! draw fast.
    • -
    -
    TG: students can also download the image of the oscilloscope code and drag it into snap. There is Snap! code embedded in the image as XML.
    -
    REDO THIS AND OTHER CODE images with updated code version (v2)
    - script variables (time step)
-set (time step) to (width of (Stage) / microphone (resolution))
+		<h3>Drawing Microphone Samples Continuously</h3>
+		
+		<div class= +
      +
    1. + show volume samples + Now finish the oscilloscope. Create a new block called show volume samples that: +
      The warp block runs all of the code inside it quickly without taking the time to draw anything at a speed people can see.
      +
        +
      • Moves the sprite to the middle of the left side of the stage (x = -240, y = 0)
      • +
      • Clears the stage
      • +
      • Puts the pen down
      • +
      • Draws one set of microphone samples across the stage using the for each code you already developed
      • +
      • Lifts the pen up (so you don't draw a line across the stage when you draw the next set of samples)
      • +
      • Does all of these steps quickly. Do this by wrapping all of the show volume samples code inside of a warp block.
      • +
      + Close the block editor, and put a show volume samples block inside a forever block so that not just one set of samples is drawn, but many sets are drawn continuously. +

      Try to build the code yourself, but if you need it, you can see an example here.

      +
      + set (sample width) to (width of (Stage) / microphone (resolution))
 forever {
-	warp {
-		go to x: (-240) y: (0)
-		clear
-		pen down
-		for each (sample) in (microphone (samples)) {
-			go to x: (x position + time step) y: (sample ร— 150)
-		}
-	}
-} + show volume samples:
+warp {
+	go to x: (-240) y: (0)
+	clear
+	pen down
+	for each (volume sample) in (microphone (samples)) {
+		go to x: (x position + sample width) y: (volume sample ร— 150)
 	}
+	pen up
+} -

      - -
      -

      One more time: What's going with the oscilloscope code?

      -
      -

      First, a script variable time step is created and set to the width of the stage divided by the number of values in the microphone sample set (so that the sprite moves horizontally across the whole stage as it goes through the list of samples).

      -

      - Then the following two things happen forever and fast (the wrap block is like a time-warp): -

        -
      • The sprite is moved to the right-hand center of the stage (-240, 0). The stage is cleared from all previous pen drawings. The sprite's pen is put down.
      • -
      • For each sample in the set of microphone samples, the sprite moves to the next x position horizontally and moves to a scaled up version of the current frequency sample vertically.
      • -
      -

      -

      Since the code resets the state of the sprite and the stage and then draws all the samples across the stage again and again forever, and this creates an oscilloscope!

      -
      -
      - -
      -
        -
      1. Build this in Snap!
      2. -
      3. Talk, sing, and make noise! If your computer's microphone is detecting sound and your Snap! code is working, you should see the frequencies displayed on the Snap! stage.
      4. -
      5. Troubleshoot any problems with your code.
      6. -
        You learned about adding comments in Unit 1 Lab 6 Activity 1: Texting Time.
        -
      7. Once your oscilloscope is working, add Snap!comments to your code so you remember how it works.
      8. +
      +
    2. +
    3. + Try out your code, make some noise, watch the results on the stage, and work with your partner and classmates to debug any issues. The oscilloscope should move according to the sounds you make and should look something like this:
      + animation of an oscilloscope in Snap! that looks like a rapidly changing, horizontal wavey line +
    4. +
    5. +
      You learned about adding comments in Unit 1 Lab 6 Activity 1: Texting Time.
      + Once your oscilloscope is working, add Snap! comments to your code so you remember how it works. What kinds of comments should you make? +
      +

      + You don't need comments to say anything that can be read easily from the code (such as, "this CLEAR block will clear the stage"), but it might help to explain why you included some code or what a complicated part of your code does. As an example, these comments explain the warp block for anyone who hasn't used it and describe what that for each code is doing:
      + show volume samples block definition with two comments: 'WARP makes the code run fast' and 'the FOR EACH code moves the sprite for each volume sample: it moves one sample width beyond the current x position and up or down according to the (scaled up) intensity of the sample' +

      +
      +
    6. Now Is a Good Time to Save

    - +
    1. - Predict What Will Happen - Without using Snap!, try to predict what will happen to the oscilloscope if you change the number in the sample ร— 150 input to the go to block? -
    2. -
    3. - Talk with Your Partner - Why do you think that will happen? + Talk with Your Partner + Predict What Will Happen + Without using Snap!, try to predict what will happen to the oscilloscope if you change the number in the sample ร— 150 input to the go to block? Why do you think that will happen?
    4. Try it out in Snap!. Try a larger value (like 1000) and a smaller value (like 25). If your prediction wasn't correct, can you explain why what you see happens?
    -
    In this activity, you coded oscilloscope that displays the intensity of the sound over time.
    +
    In this activity, you built an oscilloscope that displays the intensity of the sounds detected by the microphone over time.
    diff --git a/sparks/student-pages/U2/L3/03-spectrum-analyzer.html b/sparks/student-pages/U2/L3/03-spectrum-analyzer.html index 1737f2a4d8..71d3096500 100644 --- a/sparks/student-pages/U2/L3/03-spectrum-analyzer.html +++ b/sparks/student-pages/U2/L3/03-spectrum-analyzer.html @@ -10,84 +10,80 @@ -

    Spectrum Analyzer

    -
    preview the difference between Time Domain and Frequency Domain
    +

    Creating a Spectrum Analyzer

    In this activity, you will reuse your oscilloscope code to create a spectrum analyzer.
    -

    With a few small edits, this same code can become a spectrum analyzer.

    -

    For the oscilloscope, the horizontal axis showed time and the vertical axis showed intensity (frequency appeared only in the period ofโ€”the spacing betweenโ€”the waves). In the spectrum analyzer, the horizontal access will show intensity and the vertical will show frequency.

    - -
    explain difference between oscilloscope and the spectrum analyzer.
    +

    + For the oscilloscope, the horizontal axis showed time, and the vertical axis showed volume intensity (loudness). + In a spectrum analyzer, the horizontal axis shows intensity, and the vertical axis still shows volume intensity.
    + animation of an oscilloscope in Snap! that looks like a rapidly changing, horizontal wavey line; the horizontal axis is labeled 'volume intensity' and the vertical axis is labeled 'time'
    +

    Creating the Spectrum Analyzer

    • The frequency of a sound is its pitch. High frequencies sound "high" (sharp), and low frequencies sound "low" (boomy).
    • -
    • An spectrum analyzer is an instrument that graphs a signal's intensity at each frequency.
    • +
    • An spectrum analyzer is an instrument that graphs a signal's intensity at each frequency. You'll create a sound spectrum analyzer that shows the volume of each frequency.
    -
    clarify that here, our intensity is volume/loudness
    -
    TG: these two tools are FTs of each other..., volume typically measured on logarithmic scale

    Want to know more about frequency?

    -

    Frequency is how often a repeating sound pressure wave repeats. Music (when its more than just precussion) is about playing different frequencies in a way that other people enjoy hearing.

    +

    Frequency is how often a repeating sound pressure wave repeats. Music (when its more than just percussion) is about playing different frequencies in a way that people enjoy hearing.

    - -
      +
    1. Open your "Sparks-Making-Noise" project if isn't open already.
    2. - Explore the spectrum input to the microphone block by changing its input and clicking the block several times. (Try while you are making noise and while you aren't.)
      + Explore the spectrum input to the microphone block by changing its input and clicking the block several times. (Try it both while you are making noise and while you aren't.)
      microphone (spectrum)
    -

    While microphone (samples) reports a list of current microphone volume values sampled across a small period of time, microphone (spectrum) reports a list of current microphone volume values values across a range of frequencies.

    +

    + The microphone (samples) block reports a list of current microphone volume values sampled across a small period of time, which makes it great for building an oscilloscope.
    + microphone (samples) reporting
    + The microphone (spectrum) block reports a list of current microphone volume values across a range of frequencies, making it great for building a spectrum analyzer.
    + microphone (spectrum) reporting
    +

    -
      -
    1. If your project isn't open already, log in to Snap!, and open your "Sparks-Sound-Visualizer" project.
    2. +
      1. - Since you will reuse your oscilloscope code, preserve it by creating two copies of everything inside the forever block. Put one copy inside a show volume samples command block and one copy inside a show frequencies command block.
        - show volume samples:
-warp {
-	go to x: (-240) y: (0)
-	clear
-	pen down
-	for each (volume sample) in (microphone (samples)) {
-		go to x: (x position + time step) y: (sample ร— 150)
-	}
-	pen up
-} + Since you will reuse your oscilloscope code, find the show volume samples block in the pallete on the left, right-click it, and select "duplicate block definition..."
        + show volume samples block with menu open showing 'duplicate block definition...' option selected
      2. +
      3. Rename the block show frequencies by clicking the name of the block in the Block Editor window and changing or deleting the text in the title.
      4. There are helpful Snap! tricks for a few of these things:
          -
        • To rename a variable and alle the places is appears at the same time, right-click the variable and choose "rename all..."
        • -
        • To change from one block (like ร— (times)) to a similar block (like - (minus) ), right-click the block, choose "relabel..." and choose the new block you want in its place.
        • +
        • To rename a variable and all the places it appears at the same time, right-click the variable and choose "rename all..."
        • +
        • To change from one block (like ร— (times)) to a similar block (like - (minus) ), right-click the block, and choose "relabel..."
        - The show frequencies will have a few critial differences: + Edit the show frequencies block with these critical changes:
          -
        1. The second input to the for each block should be microphone (spectrum) and not microphone (samples).
        2. -
        3. It makes sense to rename the first input from volume sample to frequency. You'll have to change the variable in the y input for the go to block also.
        4. -
        5. The y input to the go to block doesn't need to be scaled up by multiplying by 150, but it should be lowered near the bottom of the stage such as by subtracting 150 instead.
        6. +
        7. The second input to the for each block should be microphone (spectrum) instead of microphone (samples) so that it draws the intensity for each frequency in the spectrum instead of the intensity at each sample over time.
        8. +
        9. Since you'll be plotting frequencies not volume samples, the first input to the for each block should be frequency instead of volume sample. Be sure to change the variable in the y input for the go to block also.
        10. +
        11. Finally, that y input to the go to block doesn't need to be scaled up by multiplying by 150, but the value could be lowered (using subtraction) so the drawing starts near the bottom of the stage (or example, you might subtract by 150 instead). (If you lower the drawing with subtraction, lower the starting y value in the go to block also.)
      5. -
        I need to decide how to handle the timestep variable. Maybe just use a global (then only have to set it once at the beginning).
        -
      6. Put the show volume samples block inside the forever block in your oscilloscope code, and test that it still works. If not, fix it before going on.
      7. -
      8. Replace the show volume samples block with the show frequencies and test that too. Fix, if needed.
      9. -
      10. Turn your vizualizer on, and make some noise while you switch back and forth between the oscilloscope and the spectrum analyzer.
      11. +
      12. + Replace the show volume samples block with the show frequencies inside the forever block, and test your code. Make some noise, watch the results, and work with your partner and classmates to debug any issues. The spectrum analyzer should look something like this:
        + animation of an oscilloscope in Snap! that looks like a rapidly changing, horizontal wavey line
        +
      13. +
      14. Now Is a Good Time to Save
    - -
    Extension: ITIT play a song on your phone
    - - -
    In this activity, you changed your oscilloscope into a spectrum analyzer by graphing the intensity of each frequency instead of the overall intensity at each time.
    +
    +
      +
    1. Try playing a song while you watch your spectrum analyzer.
    2. +
    +
    + +
    In this activity, you changed your oscilloscope into a spectrum analyzer by plotting the intensity of each frequency separately instead of plotting the total intensity across time.
    diff --git a/sparks/student-pages/U2/L3/04-switching.html b/sparks/student-pages/U2/L3/04-switching.html index 807a9e38eb..da32e6e3c9 100644 --- a/sparks/student-pages/U2/L3/04-switching.html +++ b/sparks/student-pages/U2/L3/04-switching.html @@ -10,37 +10,15 @@

    Switching Back and Forth

    In this activity, you will create a way to switch back and forth easily between your oscilloscope and your spectrum analyzer.
    -

    Time Domain and Frequency Domain

    -
    need to sumarize difference between Time Domain and Frequency Domain and to go back and preview it on previous pages
    -
    -
      -
    1. Talk with Your Partner -
    2. -
    -
    - -

    Controling the Display with a Toggle

    - -
    NEED TO TEACH BOOLEANS also need to initialize the toggle.
    +

    The oscilloscope plots signal intensity over time, and the spectrum analyzer plots signal intensity over frequency:
    + animation of an oscilloscope in Snap! that looks like a rapidly changing, horizontal wavey line; the horizontal axis is labeled 'volume intensity' and the vertical axis is labeled 'time' + animation of an oscilloscope in Snap! that looks like a rapidly changing, horizontal wavey line; the horizontal axis is labeled 'volume intensity' and the vertical axis is labeled 'time' +

    -
    : Predicate and Conditional -

    - A predicate is a hexagon-shaped reporter that asks a true/false question such as these examples:
    - 8 > 7 reporting true - 6 > 7 reporting false -

    -

    - A conditional is a block that controls the code based on a true/false condition (the predicate). The if 'predicate input slot' then () else () block is an example of a conditional. -

    -
    - - - - -
    instead of TOGGLE use SHOW SAMPLES?
      +
    1. Open your "Sparks-Making-Noise" project if isn't open already.
    2. Create a way to switch back and forth between the oscilloscope code and the spectrum analyzer:
        @@ -48,11 +26,12 @@

        Controling the Display with a Toggle

        You learned about event blocks in Unit 2 Lab 2 Activity 9: Responding to Events

        You learned about the if else block in Unit 2 Lab 1 Activity 4: Mystery Song Game.

    -
  • Create a global variable (such as toggle) to store a Boolean value that controls whether the programm displays an oscilloscope or a spectrum analyzer.
  • +
  • Create a global variable (such as show volume samples?) that will store a true/false value to control whether the program displays an oscilloscope or a spectrum analyzer, and set the variable to start with the value true.
  • - Use an event block together with an if else block inside the forever block to control which visualizer is displayed by pressing a key (such as the space bar).
    - when (space) key pressed: set (toggle) to (not (toggle)) - forever {
+							Use an event block together with an <code>if else</code> block <em>inside</em> the <code>forever</code> block to control which visualizer is displayed by pressing a key (such as the space bar). <a href=Click for an example. +
    + when (space) key pressed: set (toggle) to (not (toggle)) + forever {
 	if (toggle) {
 		show volume samples
 	} else {
@@ -65,15 +44,15 @@ <h3>Controling the Display with a Toggle</h3>
 		show frewuencies
 	}
 } +
  • -
  • Turn your vizualizer on, and make some noise while you switch back and forth between the oscilloscope and the spectrum analyzer using your toggle.
  • +
  • Turn your vizualizer on, and make some noise while you switch back and forth between the oscilloscope and the spectrum analyzer using your toggle. Fix any issues with your code.
  • +
  • Now Is a Good Time to Save
  • -
    Can they do any other interesting variations?? Oh, maybe have them build a way to turn it off completely
    -
    In this activity, you created a way to switch back and forth easily between your oscilloscope and yout spectrum analyzer by using a key press to toggle between the displays.
    diff --git a/sparks/student-pages/U2/L3/05-making-noise.html b/sparks/student-pages/U2/L3/05-making-noise.html new file mode 100644 index 0000000000..8249672e0e --- /dev/null +++ b/sparks/student-pages/U2/L3/05-making-noise.html @@ -0,0 +1,86 @@ + + + + + + Unit 2 Lab 3: Make Some Noise, Activity 5 + + + +

    Making Noise

    +
    In this activity, you will make a noise sample from scratch by making the computer play a set of random volume intensities.
    +
    +

    Needed for SOUND GENERATOR...

    +
    + SOUND GENERATOR +
      +
    • pick random (1.2.2)
    • +
    • / (1.5.1, where it's introduced and 1.7.6, where they use it to build average)
    • +
    • length of list (1.7.5)
    • +
    • (sample rate) of sound (2.1.1?)
    • +
    • play sound (2.1.1)
    • +
    • repeat (2.1.1)
    • +
    • for each (2.1.2)
    • +
    • show/hide variable (2.1.3?)
    • +
    • set variable (2.1.3?)
    • +
    • global vars (with generator?)
    • +
    • warp (with generator)
    • +
    • add (?)
    • +
    +
    +
    + +

    Sound is pressure waves, and the patterns of those waves determine what the sound sounds like. In Snap!, sounds can be generated as lists of volume intensities. You'll start by creating one second of "noise", which is just random intensities that sound like static.

    + +

    Making Noise

    +
    +
      +
    1. Open your "Sparks-Making-Noise" project if isn't open already.
    2. +
    3. + Create a variable called noise to store the intensity values, and make it start as an empty list.
      + show variable (noise); set (noise) to (list) +
    4. +
    5. + Talk with Your Partner
      + What is the difference between the inputs of the following two expressions? + What is the difference between their outputs?
      + pick random (-1) to (1)
      + pick random (-0.99999) to (1) + +
    6. +
    7. + noise variable watcher showing a list of long decimals between -1 and 1 + Talk with Your Partner What will this code do?
      + warp(repeat((sample rate) of sound (microphone(samples)))(add(pick random (-0.99999) to (1)) to (noise)))
      + Look at the variable watcher on the Snap! stage to confirm. Drag its corner to expand, and then scroll. +
    8. +
      +

      Click for a break-down of how this code works.

      +
      +
        +
      • The above code repeatedly adds a random number between -1 and 1 to the noise variable.
      • +
      • The first input to pick random is -0.99999 instead of -1 to force that block to output decimals rather than only integers.
      • +
      • The add block is repeated sampling rate number of times.
      • +
      • The warp block acts like a time-warp to speed things up.
      • +
      +
      +
      + +
      +

      + The sample rate is how many intensity samples fit in one second of sound samples detected by the microphone.
      + (sample rate) of sound (microphone(samples)) reporting 44100 +

      +
      +
    9. + Set Up Your Headphones or Speakers + Build that code in Snap!, then drag the noise variable into the play block, turn down the volume, and play the noise. Debug your code if needed.
      + play sound (noise) +
    10. +
    11. Now Is a Good Time to Save
    12. +
    +
    +
    In this activity, you created noise by making the computer play a bunch of random volume intensities.
    + + + diff --git a/sparks/student-pages/U2/L3/05-sound-generator.html b/sparks/student-pages/U2/L3/05-sound-generator.html deleted file mode 100644 index 8e67d1d712..0000000000 --- a/sparks/student-pages/U2/L3/05-sound-generator.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - Unit 2 Lab 3: Make Some Noise, Activity 5 - - - -

    Creating Sound Waves

    -
    In this activity, you will...
    -
    - Needed for SOUND GENERATOR: -
      -
    • pick random (1.2.2)
    • -
    • / (1.5.1, where it's introduced and 1.7.6, where they use it to build average)
    • -
    • length of list (1.7.5)
    • -
    • (sample rate) of sound (2.1.1?)
    • -
    • play sound (2.1.1)
    • -
    • repeat (2.1.1)
    • -
    • for each (2.1.2)
    • -
    • show/hide variable (2.1.3?)
    • -
    • set variable (2.1.3?)
    • -
    • global vars (with generator?)
    • -
    • warp (with generator)
    • -
    • add (?)
    • -
    - -
    - -
    Build itin the same project and have them explore the sounds with the osc and freq ana.
    -
    Explain what a sound is and how that's differen than the midi they used in L1
    - -

    Making Noise

    -
    -
      -
    1. -
    -
    - -

    Repeating a Short Noise

    -
    -
      -
    1. -
    -
    - -

    Repeating a Shorter Noise

    -
    -
      -
    1. -
    -
    - -

    Repeating a Square Wave

    -
    Why isn't it square?
    -
    -
      -
    1. -
    -
    - -
    have them try to build other sounds (sine, square, triangular, sawtooth, ramp. maybe even try to identify pitches?????
    - -
    -
      -
    1. Set up
    2. -
    -
    - - - -
    In this activity, you ...
    - - - - diff --git a/sparks/student-pages/U2/L3/06-making-notes.html b/sparks/student-pages/U2/L3/06-making-notes.html new file mode 100644 index 0000000000..cd91d0036e --- /dev/null +++ b/sparks/student-pages/U2/L3/06-making-notes.html @@ -0,0 +1,153 @@ + + + + + + Unit 2 Lab 3: Make Some Noise, Activity 6 + + + +

    Making Notes and Instruments

    +
    In this activity, you will create notes by repeating a set of volume intensities and instruments by changing the intensities that you repeat.
    + +

    + play โ™ช pitch: () beats: () + In Lab 1: Song Player, you used Snap! to play specific pitches. You can create pitches by repeating a sample of noise. The frequency at which the static repeats will determine the pitch of the note you hear. +

    +

    Making a Note

    +
    +
      +
    1. Open your "Sparks-Making-Noise" project if isn't open already.
    2. +
    3. + Now instead of creating a noise with 44100 intensity values, as you did in the previous activity, create a new variable called short noise and load the list with fewer intensity values (such as 240). +
      +

      Click for walk-through images.

      +
      + show variable (short noise) + play sound (short noise) + warp {
+			set (short noise) to (list)
+			repeat (240) {
+				add (pick random (-0.99999) to (1)) to (short noise)
+			}
+		} +

      You'll need to move the watcher on the stage to see all variables at the same time.

      +
      +
      +
    4. +
    5. + Then create another variable called repeated short noise, add enough copies of the intensity values from short noise to make one second of sound, and play repeated short noise. The repeated short noise sample should sound more like a note than the plain noise in the last activity did. + +
    6. +
    +
    +
    +
      +
    1. + Talk with Your Partner + How does the for each loop in this version of the code work to fill up the repeated short noise list?
      + for each (sample) in (short noise) {
+	add (sample) to (repeated short noise)
+} +
    2. +
    3. + Talk with Your Partner + The example code in the walk-through images above uses this expression to determine how many copies short noise to put in repeated short noise. How does this code ensure that repeated short noise contains exactly one second of sound samples?
      + (sample rate) of sound (microphone (samples)) / (length) of (short noise) +
    4. +
    +
    + +

    Making Other Notes

    +
    +
      +
      If your Snap! stage gets too crowded with variable watchers, use the show variable and hide variable blocks to control which watchers are displayed.
      +
    1. Create a two new variables, shorter noise and repeated shorter noise.
    2. +
    3. Load the shorter noise variable with even fewer intensity values (such as 60).
    4. +
    5. Add enough copies of shorter noise to repeated shorter noise to make one second of sound, and play repeated shorter noise. It should sound higher in pitch than the short noise.
    6. +
      A shorter length of repeated sound means that the sound will be repeated more frequently, which makes for a higher frequency.
      +
    +
    + +

    Making Other Instruments

    +
    +
      +
    1. + Change the way the notes sound by changing the signal intensity values in the short sample that gets repeated. For example, you might make square sample and repeated square sample variables and load the sample with 60 negative values followed by 60 positive values to make a "square wave":
      + warp {
+	set (square sample) to (list)
+	repeat (60) {
+		add (-0.5) to (square sample)
+	}
+	repeat (60) {
+		add (0.5) to (square sample)
+	}
+}
      + Or you might have the values in the short sample start negative and then go up slowly.
      + warp {
+	set (sawtooth sample) to (list)
+	for (-50) to (50) {
+		add (i / 100) to (sawtooth sample)
+	}
+} + sawtooth variable watcher showing a list containing 101 items: {-0.5, -0.49, -0.48, -0.47, -0.46, -0.45, -0.44, -0.43, ...} +
    2. +
    +
    + +

    Visualizing Your Own Sounds

    +
    +
      +
    1. + Talk with Your Partner + Run your oscilloscope or the spectrum analyzer while you play some of the notes and instruments you created. How does the visualization correspond with what you hear?
    2. +
    3. Now Is a Good Time to Save
    4. +
    +
    + +
    In this activity, you created your own notes and intruments by creating and repeating a set of sound intensity values, and you used your oscilloscope or the spectrum analyzer to "see" the sounds you created.
    + + + + diff --git a/sparks/student-pages/U2/L4/01-routing.html b/sparks/student-pages/U2/L4/01-routing.html new file mode 100644 index 0000000000..f978f27b53 --- /dev/null +++ b/sparks/student-pages/U2/L4/01-routing.html @@ -0,0 +1,73 @@ + + + + + + Unit 2 Lab 4: Routing Protocols, Activity 1 + + + + + + +

    Finding the Best Routing Strategy

    +
    In this activity, you'll explore how data is sent across the internet and experiment with routing protocols.
    + +
    +

    A router is a special type of computing device that knows how to send messages to other internet-connected devices.

    + image of a router with one line input, 4 ethernet outputs, and a power socket +
    Image by Wikipedia user Asim18.
    +
    +

    The internet is a giant network that enables millions of computing devices to communicate with one another. That communication is possible thanks to routers.

    + +

    + Below is an animation demostrating how a message travels through routers across the internet. Click it to watch it play. +

    + A network of nodes joined with edges, with a sender node and a receiver node. +

    + Your computer sends a request to the nearest router (which you might even be able to see right now, if it's in the same room as your computer). The message then travels from router to router until it finally reaches the destination. There are many possible paths the message can take, including some paths that wouldn't reach the destination.

    +

    Fortunately, internet routing protocols help routers decide how to send a message along.

    +

    A protocol is a standard set of rules for communication that everyone agrees to.

    +

    That means lots of different kinds of computing devices (laptops, desktops, phones, home assistants, etc), can all communicate with each other, because they all follow the same internet protocols.

    + +
    +
      +
    1. Open this Routers project, and save it to your account.
    2. +
    3. + Click the initialize routers command block. It will draw a simple network on the stage.
      + network of routers A-F with some routers most connected than others +
    4. +
    5. + Now you'll send messages between routers A-F. Drag the send message block to the stage.
      + send message from router () to reouter () with strategy ()
      + This block accepts a router name (a letter) in the first blank, a router name (another letter) in the second blank, and an option selected from the strategy dropdown. +
    6. +
    7. + Try sending a message between two routers that aren't directly connected while experimenting with different routing strategies. For each experiment, note the number of routers and distance traveled. Try the experiment again with a different set of routers. +
      +

      + Here's a short description of each strategy: +

        +
      • Closest: Picks the directly connected router that's closest to the current router.
      • +
      • Farthest: Picks the directly connected router that's farther from the current router.
      • +
      • Random: Randomly picks any one of the directly connected routers.
      • +
      • Lookup: Picks a router based on an internally stored table (i.e. for router A, a lookup for router F suggests going through router C).
      • +
      +

      +
      +
    8. +
    9. + Talk with Your Partner
      + Based on your experiments, which do you think is the best routing strategy? Or do you think it depends? Does the strategy always matter, or are there some situations where the result is always the same? +
    10. +
    +
    + +

    The internet uses a strategy most similar to the lookup strategy. When a router receives a message, it checks the destination address of that message, and sees an address like 232.56.13.83. It then looks for that address in its internally stored lookup table. If the router is very close to the destination, it might find the entire address and be able to send it directly to the destination router. However, most likely, it'll find part of the address, like 232.56 and then will send the message to the next router that's best for handling those addresses.

    +

    It's a lot like the postal system; a postal office in Santa Fe, Mexico may not know the exact post office to handle an address in New Jersey, but it knows how to send the mail on a truck headed for a New Jersey post office. Then the New Jersey post office can figure it out from there!

    + +
    In this activity, you learned explore how data is sent across the internet through a network of connected routers accorind to different routing protocols.
    + + + + \ No newline at end of file diff --git a/sparks/student-pages/U2/L4/02-redundancy.html b/sparks/student-pages/U2/L4/02-redundancy.html new file mode 100644 index 0000000000..c1c64b4571 --- /dev/null +++ b/sparks/student-pages/U2/L4/02-redundancy.html @@ -0,0 +1,77 @@ + + + + + + Unit 2 Lab 4: Routing Protocols, Activity 2 + + + +

    Packets and Redundancy

    +
    In this activity, you'll test the strength of a network.
    +

    + An important feature of networks is redundancy. +

    +

    Network redundancy means multiple paths to get to the same place.

    +
    + If one path is no longer available for some reason, a message can travel a different path instead. +

    +

    Consider roads and highways: we might always go to a destination (like a school) using a certain path. However, if one of the roads is under construction one day, we can usually find an alternative way to get to the destination. The alternative route might be slower or more dangerous, but at least we eventually get to the destination. That's the power of redundancy.

    +
    +
      +
    1. In the previous activity, you probably discovered strategies that used different paths between the same set of routers. Those different paths were redundant paths. Circle two redundant paths on your worksheet.
    2. +
    +
    + +

    Break the Network

    +

    + network of routers A-F with some routers most connected than others + More redundancy in a network means more protection in case things go wrong. This network has some redundancy, but not a lot, so there's a lot that can go wrong. You're going to cause some havoc! There are several blocks for taking down parts of the network:
    + cut cable between router () and router () + destroy router () in fire + attack router () with T-Rex +

    +

    The cut cable block simulates something that actually happens a lot, cutting the cables connecting two routers. Many cables are either buried underground or lying on the seafloor, so they can easily be damaged by construction companies or ships that don't realize they're there.

    In 2019, a cut cable resulted in the island nation of Tonga losing it's entire Internet connection!
    +

    The other blocks (destroy router and attack router) simulate taking down individual routers not the cables between them. Natural disasters are a common cause of router loss, since routers can be destroyed or lose power.

    + +
    +
      +
    1. Drag some destruction blocks over to the main area and type router names in the blanks. After you take down part of the network, try sending a message again to see if it can still go through and to see whether it takes an alternate path.
    2. +
    3. + There are currently multiple paths from B to D. +
        +
      1. Can you make it impossible for a message to get sent from B to D just by using a single destroy router or attack router block?
      2. +
      3. Can you do it using a single cut cable block?
      4. +
      +
    4. +
    5. + Try the same from B to E. +
        +
      1. Can you stop a message with a single destroy router or attack router block?
      2. +
      3. What about a single cut cable block?
      4. +
      +
    6. +
    +
    + +

    Spot the SPOF!

    +

    A goal of designing networks is to avoid single points of failure (or SPOFs).

    +
    +

    In a network, a SPOF is any connection that will bring down a piece of the network if it fails.

    +
    +

    As long as a router has multiple cables connecting it to the rest of the network, none of those cables is a single point of failure. However, if a router has only one connection, that one connection is a SPOF.

    + +
    +
      +
    1. + Can you find the SPOF in this network?
      + network of routers A-F with some routers most connected than others +
    2. +
    +
    + +
    In this activity, explored the limitations of a network by destroying cables and routers.
    + + + + \ No newline at end of file diff --git a/sparks/student-pages/U2/L5/01-decision-tree.html b/sparks/student-pages/U2/L5/01-decision-tree.html new file mode 100644 index 0000000000..9635fd651b --- /dev/null +++ b/sparks/student-pages/U2/L5/01-decision-tree.html @@ -0,0 +1,179 @@ + + + + + + Lab 5: Smart Systems and AI + + + +

    Decision Tree

    +
    +

    + One way that a computer program (and a human!) can make a decision is by using a decision tree. Here's an example of a decision tree for going out to play:
    + +

    +

    The decision making process starts at the top. The program checks the outlook (sunny, overcast, or rainy) and follows the path corresponding to each value. If it's sunny, it then checks the humidity level. A high humidity (> 70) results in the decision of staying in, while a lower humidity results in the decision of playing. All of the paths eventually result in either "play!" or "stay in!", so this program will always result in a decision.

    +

    In this lab, you'll code this decision tree, learn about testing your code, and then come up with your own custom decision tree.

    + +

    Coding the Tree

    +

    + We want to turn that decision tree into a block that returns either true or false, like this:
    + +

    +
    +
      +
    1. Download the starter project here. It contains a few blocks we'll use later.
    2. +
    +
    + +

    Block parameters

    +
    +
      +
    1. To get started, click "Make a block" in the sidebar. In the pop-up, type a name like "go play outside?" and select "predicate". A predicate block is a special kind of reporter block that returns either true or false (not text or numbers).
    2. +
    3. + Now add an input parameter by clicking the + sign in the block header. Type "outlook" as the name. There should only be three possible values for that parameter, and we can actually make it into a dropdown by customizing the parameter. Click the arrow in that popup to see more customization options, then click the gear in the bottom right corner for even more options. Select "options" in that gear pop-up. Click for an image.
      +
      +
    4. +
    5. + Type the three options in the popup, separated by new lines. Click for an image.
      +
      +
    6. +
    7. + Add another input parameter and type "humidity" as the name. Click the right arrow again for options, and check the "Number" box in the left column to specify that it's a numeric parameter. Click for an image.
      +
      +
    8. +
    9. + Add one more input parameter and type "windy" as the name. Click the right arrow again for options, and check the "Boolean" box in the right column to specify that it should be either true/false. Click for an image.
      +
      +
    10. +
    11. + Close the block editor and check out your new block.
      +
      + It doesn't do anything yet, but it does have some fancy input parameter types! Specifying the input types makes it easier for users to give the block valid input, so it's always a good thing to do if you can. +
    12. +
    +
    + +

    Block body

    +
    +
      +
    1. + Now let's actually define the block. Right click on the block and click "edit" to go back into the block editor. Here's a reminder of the decision tree that we need to represent in code:
      +
      +
    2. +
    +
    +

    In a decision tree diagram, each diamond represents a question with multiple paths flowing from it. In a Snap program, a diamond can be coded using if/else blocks.

    +

    We'll guide you through coding the first flow, through the sunny part of the tree.

    +
    +
      +
    1. + Drag the if/else block from the Control palette and snap it under the block header.
      + +
    2. +
    3. + All of the arrows coming from the top diagram represent possible values for the outlook parameter. The first arrow represents the outlook being "sunny", so that's what should go in the if condition. Drag the = operator block into the diamond slot next to the if, then drag the outlook parameter into one side and type "sunny" on the other side.
      + +
    4. +
    5. + What goes inside the if? Well, in the diagram, that arrow leads to another diamond! That means another if/else block. Drag another one into that block.
      + +
    6. +
    7. + The next diamond asks the question of humidity level, with different paths depending on whether it's greater than 70 or not. Drag the > operator into that diamond slot, then drag the humidity parameter into one side and type 70 in the other side.
      + +
    8. +
    9. + The arrows from the humidity diamond lead to rectangles, indicating the actual decision, either play (true) or stay in (false). Snap a report block into each of the if/else slots, then drag true/false blocks into each report block and set them to the appropriate value.
      + +
    10. +
    11. + Okay, our block can now make a decision, as long as it's sunny outside! ๐ŸŒž๐ŸŒž๐ŸŒž If you want, you could exit the block editor now and do a few checks to see if the sunny-day decisions make sense.
      + +
    12. +
    13. + Now see if you can code the rest of the decision tree, using the same sort of blocks we used already. +
      Here's a hint to get you started: you'll want to use another if/else inside the currently empty else, since you still have two more outlooks to handle.
      +
    14. +
    +
    + +

    Testing the Tree

    +

    At this point, you've probably done a few checks to see that the block is reporting true/false appropriately. Testing a program for correctness is a very important part of computer programming, since it's very easy to accidentally write buggy code. In fact, most programmers use dedicated tools for testing.

    +

    + We've made two reporter blocks to make it even easier for you to check your decision tree block, inspired by typical program testing tools.
    + + +

    + +
    +
      +
    1. + The first block checks that the value of the first parameter is the same as the value of the second parameter. To use it, drag an already filled out go play outside? block into the first slot, then drag a true/false block into the second slot. That second slot should be true if you expect the result to be true or false otherwise. +
      + For example, when it's sunny and humid outside, it should be false. If the code produces the expected value, you'll see a "Test passed!". +
      + Here's an example of a test for when it's sunny and not that humid. This time, we expect it to be true.
      + +
      +
    2. +
    3. Now go make test blocks for lots more situations. What combinations of parameters should you check for? Where is it likely for your code to have bugs? You should have at least 5 test blocks, but probably even more than that.
    4. +
    5. If you discover a test block that says "Test failed!", first check your test case. Did you really input the parameters you thought you did? Then check your block's code, especially near where it should have made the decision. Did you use the right comparison operator in the if condition? Did you report the correct value?
    6. +
    +
    + +

    All together now

    +
    +
      +
    1. Now that you have a bunch of passing tests, it'd be nice if you could run them all at once instead of having to click a billion times. That's the purpose of the check all tests block! Just drag a test block into the first slot. Then click the right arrow to add a slot for each of your additional tests and drag the rests of your tests in. +
    2. +
    +
    +

    At any point, you can click the block to confirm that all the tests are passing.

    +

    Here's the awesome thing about testing: if you realize there's a better way to code the logic of the block, you can edit the block definition, change the code, and then just click this block to make sure all the tests pass.

    +

    Testing is a great way to make sure that a computer program is actually doing what it's meant to be doing. Many programs have more tests than code, in fact, since it's so important that they work as expected. Consider the software used on a Boeing 747 airplane or on a space shuttle: you wouldn't want to ride on a plane running untested code, right? *Shudder*

    + + +

    Create your own decision tree

    +
    +
      +
    1. + This time, you're going to make your own decision tree. What sort of decisions do you want a computer to make for you? +
      + Here are some ideas to kickstart your brainstorming: +
        +
      • Deciding on the best move to make in a sport. For example, deciding in baseball whether to run to third base depending on parameters about how the ball was hit and whether the bases are full.
      • +
      • Deciding whether to go out to a restaurant for dinner or stay inside, considering parameters like cost, how empty the fridge is, hunger level, etc.
      • +
      • Deciding whether to wear a jacket outside (using similar parameters as the tree you coded, most likely).
      • +
      + You can also have decision trees return a set of values, not just true or false. Consider: +
        +
      • Recommending a sport for someone to play, based on whether they like solo/group activities, how risk averse they are, what weather they like, how much exercise they want, how competitive they are, etc.
      • +
      • Choosing what to eat for breakfast, based on preferences for cold/hot breakfast, how many minutes you have preparation, whether you want to eat healthy, etc.
      • +
      + + +
      +
    2. +
    3. + Work with a Partner + Work with a partner and brainstorm ideas on paper. Write them out as flowcharts just like the one we showed here. Every path should eventually end in a decision. +
    4. +
    5. + Talk with Your Partner + Once you've drawn it on paper, share it with another pair and ask for feedback. Is anything unclear? Do they suggest a different flow? Make a new iteration if you find their feedback useful. +
    6. +
    +
    + +

    Coding your tree

    +

    Now you'll code your own decision tree, just like you coded the one earlier. If it's similar, you can even duplicate the earlier block and start from that, but you can also start from scratch. Feel free to scroll up to see the steps we used for the first block.

    +

    Follow the testing steps too, so that your custom block is just as well-tested.

    +

    Once you're done, share it with the whole class!

    + +
    + + + + \ No newline at end of file diff --git a/sparks/student-pages/U2/L6/02-movie-recommender.html b/sparks/student-pages/U2/L6/02-movie-recommender.html new file mode 100644 index 0000000000..261498f3a9 --- /dev/null +++ b/sparks/student-pages/U2/L6/02-movie-recommender.html @@ -0,0 +1,214 @@ + + + + + + Lab 5: Smart Systems and AI + + + +

    Movie Recommender

    +
    + + Lab: Movie recommender + +Have you ever been recommended something by an app? Perhaps it suggested a new product for you to buy, a new song for your playlist, or a video similar to your favorite videos? + +Many web applications include recommendations, since they can be both good for the user (finding something new you enjoy!) and good for the application (more usage often means more profit). + +In this lab, we'll build a movie recommendation engine, using lots of lists along the way. +A recommendation algorithm + +An algorithm is a series of steps to solve a problem. We need to come up with an algorithm to recommend movies to someone. + +Watch this video to get an idea for one possible algorithm: + +Transcript for video skit: +PF: Hey Dan, I bet I can come up with amazing movie recommendations with you, movies you would have never thought of watching before but you will LOVE. +DG: Oh reallly?? +PF: Yep! I just need a list of a few movies you already like. What's your favorite movie? +DG: Toy Story +PF: Okay cool, cool, animated family adventure. What's your next favorite movie? +DG: Toy Story II +PF: Uhh okay, so you definitely like 3d animated movies. What's another movie you love? +DG: Toy Story III +PF: AHGHGHGH DAN! I give up. Go watch Toy Story 4. Hmph. +M: Try it with me! +PF: Okkkay, what's your favorite movie? +M: Toy Story +PF: :( *sigh*grump* Next favorite movie? +M: Back to the Future +PF: *perks up* Okay, now we're getting somewhere. One more? +M: How to Train Your Dragon +PF: Okay, drumroll please! I predict that you would love Howl's Moving Castle. +M: Sweet I'll check it out! + +Pamela's movie recommendation algorithm was just in her head, but many computer programs use similar recommendations based on a user's history. Those programs need enough data to make a good suggestion, and that data can't all be basically the same. That's the difference between data and information: data is a bunch of data points that are true about the world, information is what we learn from those data points. A long list of data doesn't always mean a lot of information, but a short list of data might be chock full of information. + +So here's a possible way to turn Pamela's algorithm into a computer program: + +Get a list of favorite movies from the user (at least 3 movies, but more is better!) +Look up each movie and record its genre. +Count how often the same genre appears across the user's favorite movies. +Calculate the top genre according to the counts +Recommend a movie that has the same genre as the top genre. + + +Programming the recommender +Looking up movies + +Start by downloading the starter project. + +First, we need a way to discover information about a movie. Snap doesn't know anything about movies, but there are other websites that specialize in movies. Some of those websites make it possible for other programmers (like us) to request movie information from thei`r server, via an API. That means we can use Snap to look up movies! + +[ Diagram of browser -> movie server , movie info? request, movie info! response] + +We've written a look up movie block that uses the OMDb API. All you need to do is drag the block into the main area and type in a movie title. + + + +When you click on that block, it will show you an empty result if it couldn't find the movie. The title must be spelled correctly. For example, "Toy Story 1" wouldn't find any results since the actual title is "Toy Story 1". + + + +However, a successful movie lookup will show a list of details about the movie - the title, year, rating, duration, and genres. + + + + +This is an example of a block that reports a list. In fact, it reports a list of lists, which is presented as a table in the output bubble. Each item in the list has two items, the label for that piece of data, and the value of that piece of data, like "Title" and "Toy Story". All that data came from the OMDb API. + +Recording the genres + +Now that you've verified you can look up a movie by its title, you can use another block that will report just the genres from that movie's information. + +Drag the genres of movie block into the main area, and drag the look up movie block into the input slot. + + + +Viola, another list! This time, the block reports the list of genres, based on the information it got from the OMDb API about the movie. + + +Counting genres + +The next step is to look up multiple movies and count the genres across those movies. There's another block for that, count genres. Drag that into the main area. + + + +Notice something different about this block? Instead of a blank, it has an icon that looks like a list. That indicates that the input parameter must be a list; it can't be a number or text. Drag a list block directly from the sidebar into that icon. + + + +Now drag the previous genres of movie block into that first list slot. + + + + +For only one movie, the count should be 1 for every genre, since it can't have seen a genre more than once yet. + +Keep adding more movie titles by duplicating the genres of movie block and typing in a different movie title. + + +Each time you add a movie, click the block and see how the counts change. If they don't change, you may have typed the title incorrectly. You can always double-check your title works by dragging the look up movie block out of that big nested block and seeing what it reports. + +Once you've added a bunch of movies, some genres will probably have higher counts than others. (Unless all your favorite movies are just sequels of Toy Story, of course.) + + + + +Calculating the top genre + +According to our algorithm, we're going to recommend a movie based on the top genre. That's the one that has the highest count in the output from the genre counts block. There's another block that does that calculation: top genre. + + + +This block also takes a list, and that list should be the output of the count genres block that we just used. + + +Once you've moved the copy into the top genre block, click to make sure it reports the most common genre across those movies. + + + + +Recommending a movie + +Okay, we're nearly there! Now that we know the top genre, we can recommend a movie based on that genre. That's the job of the recommend movie for genre block! Drag one into the main area. + + + +This block also takes a list input. Duplicate the list from the last step and drag it over the list icon. Click the block for a movie recommendation. + + + +Click again for another recommendation! The block will suggest a random movie based on the top genre, so you can get a few different suggestions for your movie watching pleasure. + +You can also try adding more movies to the original list to see if the recommendations change. + + +Evaluating the recommender + +We were able to build a recommendation algorithm relatively quickly, but how well does it work? In fact, how do we even know how well it works? Here's one approach: + +For each recommendation you received, tally whether you were excited by the recommendation and would probably try watching it, or whether you wouldn't even attempt to watch the movie. +Combine your tallies with your classmate's tallies. +Calculate the average percentage across the whole class. + +Here's an example: +Classmate +Excited +Meh +Percentage +Your Name +3 +2 +3/5 = 60% +Their Name +4 +1 +4/5 = 80% + + + + +Average +70% + + +If the recommendation algorithm generated movie ideas that were exciting 70% of the time, that sounds like a pretty decent algorithm, or at least, better than a completely random movie suggestion. + +We'd have an even better idea of the algorithm quality if you could all go watch all the movies and report back whether you actually liked them, but that could take a few weeks, so this will have to be good enough for now. + +๐Ÿค” YouTube uses a recommendation algorithm to suggest videos to users. How do you think they decide whether their algorithm is working or not? + +Brainstorm: New recommendation algorithms + +This is definitely not the best movie recommendation algorithm in the world. With a classmate or your whole class, brainstorm more ideas for ways to either improve this genre-based algorithm or to come up with a completely different strategy for recommending movies. + +๐Ÿ“ Write out your algorithm idea as a step-by-step list or draw a diagram, whatever you prefer. + +Present your algorithm to your classmates and give each other feedback. You might even combine your ideas to create the ultimate algorithm. We won't implement your algorithm today, but one day you could. + +Discussion: The impact of recommendations + +Recommendations can be a benefit to the user, helping them discover more things they're interested in. + +But consider these situations that can arise from recommendations: +Watching hours of YouTube videos related to the original one you watched +Making additional purchases online beyond what you originally planned to buy +Browsing hundreds of popular posts on Instagram when you only meant to check your friend's most recent post + +More is not always better for the user, even if it means more usage for the app. + +An organization actually tracked user happiness based on time spent in mobile apps and made this graph of the results: + +For many apps, user happiness was correlated with spending less time on the app, usually between 10-40 minutes each day. + +๐Ÿค” What do you think? When are recommendations a good thing? Is there a way that apps can present recommendations to users that can help them make healthy decisions about how to spend their time and money? Discuss with your classmates. + + + +
    + + + + \ No newline at end of file diff --git a/sparks/student-pages/U2/L7/03-machine-learning.html b/sparks/student-pages/U2/L7/03-machine-learning.html new file mode 100644 index 0000000000..0ca5a102ff --- /dev/null +++ b/sparks/student-pages/U2/L7/03-machine-learning.html @@ -0,0 +1,176 @@ + + + + + + Lab 5: Smart Systems and AI + + + +

    Machine Learning

    +
    + + Perhaps you've heard of "AI": artificial intelligence. AI describes any strategy that helps a computer make smart decisions, like being able to make predictions about the future or being able to recognize the objects in an image. + +One way to make a program smarter is to use machine learning: you feed the computer some data, the program learns from the data to build a model of the world, and then the program can make predictions or classifications based on its model of the world. + +It sounds a lot like how humans learn about the world, right? Starting from childhood, we see more and more examples of things ("red apple!" "green apple!"), we start to make connections and form an idea in our head, and then we can apply our knowledge to new examples ("oh, a pink apple!"). Of course, we don't always get it right (a peach can be a very confusing fruit for a toddler who's only ever seen apples!). That's true of machine learning too: it's only as good as the data that goes into it and the algorithm that learns from the data. + +In this lab, you'll use machine learning to teach a Snap program about the world, going through these sequence of steps: + + + +Get data (& exercise!) + +Here's the question we're hoping our AI can answer: If all the students at your school stood in a line holding hands, how long would it take them to pass a hula hoop from one end of the line to the other? + +โœ๏ธ First, make your own prediction and write it down on a paper or post-it note. Keep that paper or pass it to your teacher so they can put up all the predictions. + +Now you're going to use a computer to answer the question, since it could take a REALLY long time to pass that hula hoop, and you probably can't spend all day in a circle. Plus, if you build a model that answers that question, you could then answer other questions, like other schools, the population of your town, etc. + +The plan: You'll do this activity in increasing larger groups in your class, until you have data points for a range of sizes. That will become the input data for the model. The hope is that the model can learn from that data set and make predictions about much larger numbers. + +Instructions: +Get into groups of 9-15 people. +Designate someone as the timekeeper with a stopwatch. +Start off with groups of two, with the hula hoop on one student's wrist. +The timekeeper will record the time it takes for the hula hoop to get to the other student's wrist. +Continue adding a student, recording each new time. +Stop once you've run out of group members. + +Split the data + +Whenever we build a machine learning model, we need some sort of validation: a test of whether the model has correctly learned about the world. One form of validation is to split the original data into training data and test data, and then checking predictions on the test data to see how close the predictions are to the actual data. + +So the sequence of steps is actually more like this: + + + +How many data points should you reserve for the test data set? Often, machine learning engineers do an 80/20 split, keeping 80% of the original data as training data and 20% for validation. Mark a few of the rows in your sheet with stars to indicate that they'll be part of the test data set, at least two rows but not more than 20%. You don't have a lot of data to start off with, so if you reserve too much for the test data, there won't be enough training data! +Digitize the data + +Download this starter project. + +Since your data is just on a piece of paper right now, the first step is to digitize the data. + +Your data table is really a collection of data points, where each number of people is the x value and the amount of time taken is the y value. So you'll store it as a list of points in Snap. + +Drag a list block into the main area, then drag a point block into the first slot. + +Write the data point in that point block, putting the number of people in the first slot and then the time taken in the second slot. + +Click on the block and you should see a table that looks like your actual table (but with only one row so far): + + +By the way, the point block is actually creating a 2-item list (you can peek inside the block definition to see!), but using the point block instead of a list block makes the program much easier to read. + +To add the rest of your data, keep following the same process: +Click the outer right arrow to add a new slot to the outer list block, representing a data point. +Drag a point block into the newly created slot. +Type the number of people in the first slot of that block and the time taken in the second slot. + +You should only be adding the training data points to this first list. Leave out the rows that you're saving as the test data points. + +When you're done, clicking on the block should yield a table that looks familiar, minus the test data rows: + + + +Now make another list for the remaining rows that you've designated as the test data. + +Add variables +Oftentimes in programming, we need to be able to reuse a piece of data multiple times. In this case, we're going to be reusing the data points in a few places. Instead of repeating the same list both times, it's more convenient to store the list in a variable. A variable has a name and a value. Once you store some value in a variable, you can simply reference the variable name when you want to use that data again. + +To create a variable, click "Make a variable" and type the variable name "training data" in the pop-up. That variable will now show up in the sidebar, so that you can drag its name into any slot. A monitor for that variable will also show up on the stage along with its current value. That can be useful for debugging, but you can also un-select the checkbox to hide the stage monitor. + + + +Now your program has a variable named training data, but it isn't storing any value yet. For that, drag the set variable block into the main area. + + + +Instead of a slot, this block has a dropdown which shows you all the possible variable names in the program. Select "training data" from the dropdown and then drag the list block from earlier into the right-hand slot. + + + + +Now do the same for the test data. Make a new variable named "test data", and use another set variable block to store the test data list in that variable. + + + + + +Build the model + +It's machine learning time! Here's a reminder of the process we're following: + + + +Since we now have the training data stored in a variable, let's build a model based on that data. + +First though, make a new variable called "model" to store the model. Drag another set variable block and snap it below the first two. Select "model" from the dropdown. + +What about the value? That will be the actual model of the world built by the machine learning algorithm. Drag the build model block into the right-hand slot. + + + +That model has a slot for the training data, which you now have stored in a variable. Instead of dragging the whole list into the slot, drag the variable name from the script variables block into the slot instead. + + + +So, a model is now built, but what is a model really? Let's step back andโ€ฆ + +Visualize! + +The type of machine learning that we're using in this lab is called linear regression. It only works if there is a linear relationship between the data points - i.e. the amount of time increases at the same rate as the number of people. It learns that rate, and uses it for prediction. + +We can visualize how the model works by making a graph of the training data. + +Drag the make graph block into the main area. This block takes two input parameters: the first is the training data and the second is the model. Conveniently, those are already stored in variables! Drag the variable names into the block. + + + +Click the whole sequence of blocks to build the model and make the graph. You should see a graph in the stage like this one: + + +This graph shows the data as blue circles, but it also shows a line that fits those points pretty well. That line represents the model, and the equation of the line can be used to predict the amount of time for *any* number of people. + +Test the model + +How good is the model? How accurately can that line predict times for group sizes that were *not* in the training data? + +One way to check the quality of the model is to calculate the average error: how far off the predicted value is from the actual value, on average. Drag the calculate average error block into the main area. + + + +The block takes two input parameters, the test data and the model. You've got both of those stored in variables, so just drag the variable names into the slots. Click the block to see the average error. For the sample test data, I got an average error of 2 seconds, which seems pretty reasonable to me. + +๐Ÿค” What error did you get? Does it feel like a reasonable error to you? You could compare with other groups in the class. If it's not, you may need more training data. There might have been an issue with the timekeeping in your original data or just not enough data points. + +Make predictions + +Remember the process? We're at the final step! Our program uses basic machine learning to build a model of the world, and we've tested that model on test data to validate that it has an understanding of the world. It's time to make some predictions... + + + +You can make a prediction for any number of people using the prediction block: + + +Drag the model variable into the first slot and type any value in the second slot. That slot is called the x value, since that's how the number of people is represented on the graph, but for this situation, you can think of it as the number of people. Click the block to see the prediction. + +If that prediction seems reasonable, it's time to answer the original question: how long would it take to pass the hula hoop amongst all the students in your school? Put the number of students in the prediction block and check out the result. + +Discuss: +How far off was your prediction from the computer's prediction? +Who got closest in your class? +Do you trust the computer prediction, or do you think some other factors would affect the time taken by an entire school? + + +Worksheet: Hula Hoop Data + + + +
    + + + + \ No newline at end of file diff --git a/sparks/teaching-guide/U2/03-make-some-noise.html b/sparks/teaching-guide/U2/03-make-some-noise.html index 6d630dce06..e0a9db5621 100644 --- a/sparks/teaching-guide/U2/03-make-some-noise.html +++ b/sparks/teaching-guide/U2/03-make-some-noise.html @@ -5,26 +5,31 @@ Sparks Unit 2 Lab 3 Teacher Guide + + +

    Lab 3: Make Some Noise

    -

    Finish after finishing labs
    - This lab covers the basics of visualizing and generating waveforms. In the first activity, students create an oscilloscope (example shown below) to graph sound intensity over time for data picked up by their computer microphone. In the second activity, they build a spectrum analyzer which graphs the intensity of each frequency. - animation of an oscilloscope in Snap! that looks like a rapidly changing, horizontal wavey line
    + This lab covers the basics of visualizing and generating sound waves. Students first create an oscilloscope (first example below) to graph sound intensity over time for data picked up by the computer microphone. They then build a spectrum analyzer (second example below) which graphs the sound intensity of each frequency. + animation of an oscilloscope in Snap! that looks like a rapidly changing, horizontal wavey line; the horizontal axis is labeled 'volume intensity' and the vertical axis is labeled 'time' + animation of an oscilloscope in Snap! that looks like a rapidly changing, horizontal wavey line; the horizontal axis is labeled 'volume intensity' and the vertical axis is labeled 'time'

    +

    Students then create their own sounds first by generating and playing a set of random intensity values to make white noise, then by repeating a short set of random intensity values to make a note (where pitch depends on the set length, which controls the frequency with which the set repeats); and finally (if there is time) by repeating a short set of specific intensity values to make an instrument.

    Pacing

    This lab is designed for X–X class periods (X–X minutes). You may opt to focus on some activities in this lab more than others.

    @@ -33,74 +38,311 @@

    Prepare

    • For a fantastic 5-minute overview of the Snap! projects covered in this lab, see Making a Guzdial Style Uke Demo with Snap! in 5 Minutes by Snap! creator, Jens Mรถnig.
    • -
    • For more technical preparation on the sound science in this lab, check out Electrical & Electronic Waveforms: sine, square, triangular, sawtooth, ramp by ElectronicsNotes. The first 2:32 covers the difference between oscilloscopes and spectrum amalyzers. You can skip the next section called "Sine Wave Mathematical Formula," if you aren't interested in the math. The rest of this 9-minute video covers the basic waveforms: sine, square, triangular, sawtooth, ramp.
    • +
    • For more technical preparation on the sound science in this lab, check out Electrical & Electronic Waveforms: sine, square, triangular, sawtooth, ramp by ElectronicsNotes. The first two and a half minutes covers the difference between oscilloscopes and spectrum analyzers. If you aren't interested in the math, you can skip the next section called "Sine Wave Mathematical Formula." The rest of this 9-minute video covers the basic waveforms: sine, square, triangular, sawtooth, ramp, which are optional extensions for this activity.
    - - -
    ↑ Back to Top

    Activity 1: Visualizing Sound Data. 

    -
    still need to tease out now split Lab 1
    +
    +
      +
    • + Materials: + +
    • +
    • + Prepare: +
        +
      • This lab is all about sound. Each pair of students will need a computer with a microphone for the first 4 lab actives. (Speakers and/or headphones are not needed until Activity 5.
      • +
        You can right-click the microphone block and choose "help..." to learn more about how the Snap! microphone block works.
        +
      • + Before you work on this lab with students, try the work through the first two pages of the lab yourself to check your microphone and familiarize yourself project. You may also want to load your Snap!project on a student computer and to test out the microphone. +
        +

        Trouble-shooting Microphone Issues

        +
        + Your students may be better at troubleshooting microphone issues than you are. If you have issues, here are some things to try: +
          +
        • For external microphones, check the connection of microphone to the computer
        • +
        • Check system settings to see that the microphone works with the computer
        • +
        • Check the browser settings to see that the microphone works with the browser
        • +
        +
        +
      • +
      +
    • +
    • + Learning Goals: +
        +
      • Learn about oscilloscopes.
      • +
      • Access sound data from a microphone.
      • +
      • Learn to use basic Snap! drawing tools.
      • +
      +
    • +
    • + Activity Plan: +
        +
      • Learning about oscilloscopes: Students read about oscilloscopes and sound waves. You may choose to take this introduction further such as by demoing a completed oscilloscope project, sharing online videos, etc. (5–20 minutes)
      • +
      • Exploring the Tools: Students try out the microphone block with various inputs and experiment with Snap! drawing tools. (15–30 minutes)
      • +
      +
    • +
    • + Tips: +
        +
      • If the oscilloscope doesn't appear correctly on the Snap! stage, check that the vertical scale factor (the 150 multiplier in the y input to the goto block) is an appropriate value to make the oscilloscope's oscillations both be visible and fit within the Snap!stage (the idea scale value may be different for different computers and microphones).
      • +
      +
    • +
    • + Standards: +
        +
      • 2-CS-02: Design projects that combine hardware and software components to collect and exchange data.
      • +
      +
    • +
    +
    + + ↑ Back to Top +

    Activity 2: Creating an Oscilloscope. 

    • Materials:
    • Prepare:
        -
      • Before you begin, try the osc code (include link) on one or more school computers to work out any issues. -
        FOR TG: You can right-click the microphone block and choose "help..." to learn more about how it works.
        - Trouble-shooting microphone issues: +
      • In order to clarify the axes of an oscilloscope plot, you may want to do a quick unplugged activity where you graph volume intensity over time on the board. Draw a coordinate axes on the board with "intensity" as the label on the vertical axis and "time" as the label on the horizontal axis. Have one person (a student or you) sing a pitch (or just say a vowel for a long time: "oooooooooo") and vary the volume. As the volume varies, draw a plot of volume intensity over time. (That is, while moving the writing implement from left to right at a constant speed across the board, draw the line higher when the sound is louder and lower when the sound is quieter.) Then, do the opposite: ask a student (or the class) to sing (or say a vowel) at the volume level you draw on a new graph. Start with your pen at the middle of the vertical-axis and while moving it from left to right, draw the line higher and lower to indicate the volume at which they should vocalize. This will help students understand what an oscilloscope shows and also helps to distinguish "higher and lower volume" from "higher and lower frequency" which will become relevant in the next activity.
      • +
      +
    • +
    • + Learning Goals: +
        +
      • Review creating and using global variables.
      • +
      • Review list traversal with the for each block.
      • +
      • Use the Snap! drawing tools to visualize data.
      • +
      +
    • +
    • + Activity Plan: +
        +
      • Writing Code to Draw One Set of Samples: Students create a global variable to store the amount of space each sample gets on the stage, create the for each code that will move the sprite to the correct place on the Snap! stage for each volume sample, and discuss how the for each code works. (10–20 minutes)
      • +
      • Drawing Microphone Samples Continuously: Students build out the rest of the project, troubleshoot any issues with their code, and add comments to help them remember how their code works. (10–20 minutes)
      • +
      • Extensions: Students conduct some simple experiments with the vertical scaling factor. (about 5 minutes)
      • +
      +
    • +
    • + Tips: +
        +
      • The for each block is the core of the code for this algorithm, and specific changes to this code make the difference between an oscilloscope and a spectrum analyzer as students will see in the next activity. You may wish to take extra time to discuss how this code works as a class.
      • +
      +
    • +
    • + Standards: +
        +
      • 2-CS-02: Design projects that combine hardware and software components to collect and exchange data.
      • +
      • 2-AP-11: Create clearly named variables that represent different data types and perform operations on their values.
      • +
      +
    • +
    +
    + + ↑ Back to Top +

    Activity 3: Creating a Spectrum Analyzer. 

    +
    +
      +
    • + Materials: + +
    • +
    • + Prepare: +
        +
      • You may find it helpful to work through the contents of this page by yourself before teaching.
      • +
      • + At a minumum, make sure you understand the differences (and the reason behind the differences) between the for each block for the oscilloscope (shown first below) and for the spectrum analyzer (shown second):
        + for each (volume sample) in (microphone (samples)) {
+		go to x: (x position + sample width) y: (volume sample ร— 150)
+	} + for each (frequency) in (microphone (spectrum)) {
+		go to x: (x position + sample width) y: (frequency - 150)
+	} +
      • +
      +
    • +
    • + Learning Goals: +
        +
      • Understand the difference between an oscilloscope and a spectrum analyzer.
      • +
      • Modify the oscilloscope code to create a spectrum analyzer.
      • +
      +
    • +
    • + Activity Plan: +
        +
      • Reading about spectrum analysis and exploring the microphone block: Students learn the difference between an oscilloscope and a spectrum analyzer and explore the spectrum input to the microphone block. (5–10 minutes)
      • +
      • Re-purposing the code from show volume samples to create a new show frequencies block: Students modify the inputs to the for each block and of the go to block inside it to make their program draw a intensity-over-frequency plot rather than an intensity-over-time plot as they did previously. You may wish to wrap up class with a discussion of these changes to ensure that all students successfully updated their code and understand how it works. (10–20 minutes)
      • +
      • Extension: Students play music while using the spectrum analyzer. (<5 minutes)
      • +
      +
    • +
    • + Tips: +
        +
      • + You may find the following pormpts helpful for class discussion about the difference between the oscilloscope and spectrum analyzer code:
          -
          TG; add trouble shooting tips to TG. connecting the microphone, checking system settings to see that the mic works with the computer; checking the browser settings; check that the oscilloscope scale factor (the 150 multiplier in the y input to the goto block) is an appropriate value to make the oscilloscope's oscillations both be visible and fit within the Snap!stage (if not, have students change theirs; it may be different for different computers).
          -
        • -
        • -
        • +
        • How are an oscilloscope and a spectrum analyzer similar? How are they different?
        • +
        • How do these differences appear in the inputs at the top of the for each block for each visualizer?
        • +
        • How do the differences appear in the inputs to the go to block?
    • +
    • + Standards: +
        +
      • 2-CS-02: Design projects that combine hardware and software components to collect and exchange data.
      • +
      +
    • +
    +
    + + ↑ Back to Top +

    Activity 4: Switching Back and Forth. 

    +
    +
      +
    • + Materials: + +
    • +
    • + Prepare: +
        +
      • +
      +
    • Learning Goals:
        -
      • Learn about oscilloscopes.
      • -
      • Use sound data from a microphone.
      • -
      • Review global vairables.
      • -
      • Review list traversal with for each.
      • +
    • Activity Plan:
        -
      • Exploring the Tools: Students try out the microphone block with various inputs and discuss the core of the oscilloscope code. (15–30 minutes)
    • Tips:
        -
      • +
      • +
      +
    • +
    • + Standards: +
        +
      • +
      +
    • +
    +
    - + ↑ Back to Top +

    Activity 5: Making Noise. 

    +
    +
      +
    • + Materials: + +
    • +
    • + Prepare: +
        +
      • +
      +
    • +
    • + Learning Goals: +
        +
      • +
      +
    • +
    • + Activity Plan: +
        +
      • +
      +
    • +
    • + Tips: +
        +
    • Standards:
        -
        Is this actually reasonably related?
        -
      • 2-CS-02: Design projects that combine hardware and software components to collect and exchange data.
      • -
      • 2-AP-11: Create clearly named variables that represent different data types and perform operations on their values.
      • +
      • +
      +
    • +
    +
    + ↑ Back to Top +

    Activity 6: Making Notes and Instruments. 

    +
    +
      +
    • + Materials: + +
    • +
    • + Prepare: +
        +
      • +
      +
    • +
    • + Learning Goals: +
        +
      • +
      +
    • +
    • + Activity Plan: +
        +
      • +
      +
    • +
    • + Tips: +
        +
      • +
      +
    • +
    • + Standards: +
        +
    @@ -108,7 +350,9 @@

    Activity 1: Visualizing Sound Data. Assignments

    + + + raw-html: Lab 3: Make Some Noise (under development) raw-html:
    • will include activities such as: Sound Visualizer and Sound Generator