-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathpage3.html
337 lines (259 loc) · 12.7 KB
/
page3.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
<!doctype html>
<head>
<title>Curriculum — page 3</title>
<link rel=stylesheet href="http://fonts.googleapis.com/css?family=Averia+Serif+Libre:300,400">
<link rel=stylesheet href=style.css>
<meta http-equiv=Content-Type content="text/html; charset=utf-8">
</head>
<h1>Curriculum: page 3, data</h1>
<p>Inside the computer's world, there is only data. That which is not
data, does not exist. Programs are data. Programs create new data.
It's like some kind of strange, silicon-based cycle of life.</p>
<h2 class=step>Collections</h2>
<h3 class=goal>Goal</h3>
<p>Learn how to group a set of values into a single collection, and
use that collection.</p>
<p>Problem statement: draw a rainbow by drawing seven concentric
circles with the following colors: <em>red, orange, yellow, green,
cyan, purple, white</em>, each smaller than the last.</p>
<h3 class=inst>Instructions</h3>
<p>This is the naive approach:</p>
<pre>function rainbow(x, y) {
color("red");
circle(x, y, 150);
color("orange");
circle(x, y, 145);
color("yellow");
circle(x, y, 140);
color("green");
circle(x, y, 135);
color("cyan");
circle(x, y, 130);
color("purple");
circle(x, y, 125);
color("white");
circle(x, y, 120);
}</pre>
<p>That is not wrong, but it is not right either. It repeats itself a
lot. Here is <a href="sandbox/#rainbow.js" target=_blank>a better version</a>:</p>
<pre>function rainbow(x, y) {
var colors = ["red", "orange", "yellow", "green", "cyan", "purple", "white"];
var count = 0;
while (count < colors.length) {
color(colors[count]);
circle(x, y, 150 - 5 * count);
count = count + 1;
}
}</pre>
<h3 class=ex>Explanation</h3>
<p>The thing with the square brackets (<strong>[</strong>
and <strong>]</strong>) is called an array. An array is a value that
holds other values—in this case, it holds seven strings that name
colors.</p>
<p>The values in an array are called its <em>elements</em>. The elements
in an array are ordered, which means that each element has a position
within the array. Array positions start at zero, so in the above
example, <code>"red"</code> has position zero,
and <code>"white"</code> (the seventh element) has position 6. The
notation <code>colors[1]</code> is used to access the values in an
array—in this case, it'd produce <code>"orange"</code>.</p>
<p>Another new notation, though we've seen it before
in <code>Math.random</code> is the dot in <code>colors.length</code>.
It is used to fetch another kind of sub-value, called property, out of
a value. In the case of <code>Math.random</code>, it is just used for
grouping—a whole bunch of number-related functions are available as
properties of <code>Math</code> (for example <code>Math.round</code>
to round numbers). But in the case of <code>colors.length</code>, it
retrieves a property value that is directly related
to <code>colors</code>: the amount of elements in the array
(seven).</p>
<p>So this typical <code>while</code> loop, using
the <code>count</code> variable to track its progress, goes over the
elements of the array one by one, uses them to set the current color,
and then draws a circle of the right size.</p>
<p>Since this kind of loop is very common (create variable, test it
in <code>while</code> condition, and update it), there is a more
compact way to write it. This program is equivalent to the one
above:</p>
<pre>function rainbow(x, y) {
var colors = ["red", "orange", "yellow", "green", "cyan", "purple", "white"];
for (var count = 0; count < colors.length; count = count + 1) {
color(colors[count]);
circle(x, y, 150 - 5 * count);
}
}</pre>
<p>In a <code>for</code> loop, initializing the loop state, checking
it, and updating it, are all grouped together, to make it easier to
see that they make up a single loop.</p>
<h2 class=step>Named properties</h2>
<h3 class=goal>Goal</h3>
<p>Learn how to create objects, and access their properties.</p>
<h3 class=inst>Instructions</h3>
<p>Open the console again, in case you had closed it.</p>
<p>Create a variable by entering this in the console: <code>var myObject = {name: "Larry", score: 100};</code></p>
<p>Evaluate <code>myObject.name</code> and <code>myObject.score</code>.</p>
<p>Also evaluate <code>myObject["name"]</code> and <code>myObject["sco" + "re"]</code>.</p>
<p>Give the object another property with <code>myObject.color =
"purple"</code>. Then evaluate <code>myObject.color</code>.</p>
<p>Change the <code>score</code> property by doing
<code>myObject.score = 105</code>. Evaluate <code>myObject.score</code>
again to convince yourself that it worked.</p>
<h3 class=ex>Explanation</h3>
<p>Objects are also collections of values. But they require every
value to have a name. Arrays are useful when collecting any number of
values in a homogenous group, whereas objects are more appropriate
when each value has a specific, distinct role. I.e. a big bag of
potatoes is an array, but the parts that make up a car (engine, wheels,
each with their own role) form an object.</p>
<p>The <code>{property1: value1, property2: value2}</code> syntax is
used to create a new object. There are two ways to access the
properties of an object. The <code>object.property</code> way is used
when you know the name of the property in advance.
The <code>object["property"]</code> way allows the property name to be
any expression, and thus is useful when the name needs to be computed
somehow.</p>
<p>Together, objects and arrays provide a way to express a wide
variety of information. For example, a list of players in a game would
typically be an array of objects, where each object represents a
player. If a list of achievements has to be associated with players,
that would be another array inside of each object, and so on.</p>
<p><strong>Exercise:</strong> Figure out a JavaScript representation
for a chess game board. There are multiple good solutions.</p>
<h2 class=step>We've got data</h2>
<h3 class=goal>Goal</h3>
<p>Perform a simple visualization of a dataset.</p>
<h3 class=inst>Instructions</h3>
<p>In our new playground environment, we have a new variable
available, <code>countryData</code>. This contains an array of objects
with information (population, life expectancy) about almost all
countries on earth.</p>
<p>Each object (representing a country), has a <code>name</code>
property containing a string, and <code>population</code>
and <code>life_expectancy</code> properties that hold arrays of
numbers, representing the data points for these statistics from the
year 1960 to 2011.</p>
<p>This program picks a few countries, and plots the trend of their
life expectancy in this period as series of dots.</p>
<pre>var width = 600, height = 300;
function showCountry(country) {
var step = width / country.life_expectancy.length;
for (var pos = 0; pos < country.life_expectancy.length; pos = pos + 1) {
var le = country.life_expectancy[pos];
circle(step * pos, le * height / 100, 2);
}
}
function drawing() {
moveTo(-width / 2, -height / 2);
color("red");
showCountry(countryData[66]); // Germany
color("green");
showCountry(countryData[81]); // India
color("blue");
showCountry(countryData[150]); // Russian Federation
}</pre>
<p>You can see it in action <a href="sandbox/#life_expectancy.js"
target=_blank>here</a>.</p>
<h3 class=ex>Explanation</h3>
<p>In order to be a little disciplined about where we're going to
draw, the program starts by defining the width and the height of the
area it wants to draw in. 600 by 300 units.</p>
<p>The <code>showCountry</code> function takes a country object as its
parameter, and runs a loop over all the life expectancy data points
for that country. It computes the horizontal distance it wants to
leave between dots in the <code>step</code> variable, and, on the
assumption that life expectancy is in the zero to hundred range,
divides the height by 100 to determine the vertical space that
signifies one year of life expectancy.</p>
<p>The <code>drawing</code> function first moves the coordinate system
so that 0,0 is the bottom left corner of our graph, and then
calls <code>showCountry</code> on three different countries, giving
each one a different color.</p>
<p><strong>Exercise:</strong> Having to know a country's position in
the dataset in order to display it is rather silly. Write a
function <code>findCountry</code> that takes a country name as its
only parameter, loops over the <code>countryData</code> array, and
gives back the object for the named country.</p>
<p>In order to do this, you need to know that <code>return</code>
statements can be used in functions to give back a value to the code
that called the function. For example:</p>
<pre>function timesThree(x) {
return x * 3;
}
console.log(timesThree(3)); // Logs 9</pre>
<p><strong>Exercise:</strong> A big problem with our graphs is that
you have no idea what the dots actually mean. Add code that draws gray
horizontal lines (using the <code>line(x1, y1, x2, y2)</code>
function) at ten-year intervals behind the graph. I.e. there is one
line for zero, one for ten, and so on up to one hundred. Use
the <code>width</code> and <code>height</code> variables to place the
lines properly.</p>
<p>If you're feeling motivated, you can also add textual labels (using
the <code>text(x, y, string)</code> function) and/or a horizontal
scale for the years.</p>
<p><strong>Exercise:</strong> Change the <code>showCountry</code>
function to draw a solid line instead of a series of dots.</p>
<h2 class=step>Transforming data</h2>
<h3 class=goal>Goal</h3>
<p>Independently write a program that summarizes a dataset.</p>
<h3 class=inst>Instructions</h3>
<p>In <a href="sandbox/#transform.js" target=_blank>the program for
this step</a>, there is a function <code>visualizeHistory</code>,
which is a lot like the <code>showCountry</code> function we used
before, except that it can be used to plot any data. It takes an array
of values and a vertical scale (the amount of vertical space one unit
of the input data takes up) as parameters.</p>
<p>Finish the <code>showWorldPopulation</code> function. It should
somehow compute the world population for each of the years in the
dataset, put those numbers into an array, and correctly call
the <code>visualizeHistory</code> function on that array.</p>
<p>To build up an array, follow this pattern:</p>
<pre>var newArray = []; // empty
for (var i = 0; i < 10; i = i + 1) {
newArray.push(i);
}</pre>
<p>The <code>push</code> function, which is a property
(<em>method</em>) of every array value, is used to add an element the
array.</p>
<p>To figure out the correct vertical scale for your graph, keep track
of the maximum world population in the whole dataset (either
using <code>if</code> with the <code>></code> operator, or
the <code>Math.max</code> function, which can be given two arguments
and returns the greatest of the two).</p>
<h3 class=ex>Explanation</h3>
<p>The data is not in entirely the most obvious format for the purpose
of summing up population per-year—we'd prefer to be able to
straightforwardly get a collection of all populations for a given
year.</p>
<p>But still, by using a loop inside of a loop, with the outer loop
going over the years (use, for
example, <code>countryData[0].population.length</code> to know the
total amount of years to loop over) and the inner loop going over the
countries. It can then pick out the population for the current year
from each country, and add it to the sum (which should be reset to
zero at the start of every repetition of the outer loop).</p>
<p>Give it a shot. If you get stuck, flag down a coach.</p>
<p>Some other ideas for teasing interesting visualizations out of this
data:</p>
<ul>
<li>Each country also has a <code>region</code> property. These are
three-letter abbreviations that divide the world into seven areas.
(You can get their full name by using the <code>regionName</code>
function that is supplied along with the data.) Try to display a
diagram that shows the percentages of the world population living in
each of these regions, in each year (for example by showing a
vertical stack of colored bars for each year).</li>
<li>The country objects also contain a <code>fertility</code>
property that, for each year, gives the country's fertility rate.
Plot a two-dimensional picture for a certain year, which shows the
correlation between life expectancy and fertility rate (i.e. life
expectancy on the x axis, fertility on the y axis).</li>
<li>Animate some per-year visualization, for example the one
described in the point above this, over time. Use
the <code>setTimeout</code> trick demonstrated
in <a href="sandbox/#drawing_animate.js" target=_blank>this example
from the previous page</a>, cycling through the years and drawing a
new picture (including a call to <code>text</code> to display the
year) every tenth of a second or so.</li>
</ul>
<h3>And so we reach</h3>
<p><a href="page4.html">→ The final page of the day</a>.</p>