|
11 | 11 | "source": [ |
12 | 12 | "# Initialize Otter\n", |
13 | 13 | "import otter\n", |
14 | | - "grader = otter.Notebook(\"lec_act_10_class_pinball_wall.ipynb\")" |
| 14 | + "grader = otter.Notebook(\"lec_act_10_classes.ipynb\")" |
15 | 15 | ] |
16 | 16 | }, |
17 | 17 | { |
18 | 18 | "cell_type": "markdown", |
19 | 19 | "metadata": {}, |
20 | 20 | "source": [ |
21 | | - "# Creating a pinball wall class\n", |
| 21 | + "# Creating a ground segment class\n", |
22 | 22 | "\n", |
23 | | - "Extend the wall class from the tutorial to do two new things\n", |
24 | | - "- Reflect off of the wall [vertical/horizontal, general is optional]\n", |
25 | | - "- Plot self\n", |
| 23 | + "This is mostly filling in the methods in the class\n", |
26 | 24 | "\n", |
27 | | - "The code is in **pinball_wall.py**" |
| 25 | + "You will have to decide what variables you want to keep in the class" |
28 | 26 | ] |
29 | 27 | }, |
30 | 28 | { |
|
35 | 33 | "source": [ |
36 | 34 | "# Doing the imports for you\n", |
37 | 35 | "import numpy as np\n", |
38 | | - "import matplotlib.pyplot as plt" |
39 | | - ] |
40 | | - }, |
41 | | - { |
42 | | - "cell_type": "code", |
43 | | - "execution_count": null, |
44 | | - "metadata": {}, |
45 | | - "outputs": [], |
46 | | - "source": [ |
47 | | - "# These commands will force JN to actually re-load the external file when you re-execute the import command\n", |
48 | | - "%load_ext autoreload\n", |
49 | | - "%autoreload 2" |
| 36 | + "import matplotlib.pyplot as plt\n", |
| 37 | + "from numpy.polynomial import polynomial\n" |
50 | 38 | ] |
51 | 39 | }, |
52 | 40 | { |
53 | 41 | "cell_type": "markdown", |
54 | | - "metadata": { |
55 | | - "deletable": false, |
56 | | - "editable": false |
57 | | - }, |
| 42 | + "metadata": {}, |
58 | 43 | "source": [ |
59 | | - "# Add reflect to wall code\n", |
| 44 | + "# Ground segment class\n", |
| 45 | + "\n", |
| 46 | + "Note, this is a simplified version of the one in ski_jump.py\n", |
60 | 47 | "\n", |
61 | | - "In this problem, fill in **reflect** method in **PinballWall** in **pinball_wall.py**.\n", |
| 48 | + "In this problem, fill in **init** method and **plot** \n", |
62 | 49 | "\n", |
63 | | - "You're welcome to create more class variables in the **__init__** function or add more methods\n", |
| 50 | + "You're welcome to create more variables in the **__init__** function or add more methods to the class\n", |
64 | 51 | "\n", |
65 | 52 | "TODO: \n", |
66 | | - "- reflect (this question)\n", |
67 | | - "- test_reflect (next question)\n", |
68 | | - "- plot (last question)" |
| 53 | + "- Fill in all of the methods in the class" |
69 | 54 | ] |
70 | 55 | }, |
71 | 56 | { |
|
76 | 61 | }, |
77 | 62 | "outputs": [], |
78 | 63 | "source": [ |
79 | | - "# You can import classes just like you import functions\n", |
80 | | - "from pinball_wall import PinballWall" |
81 | | - ] |
82 | | - }, |
83 | | - { |
84 | | - "cell_type": "code", |
85 | | - "execution_count": null, |
86 | | - "metadata": { |
87 | | - "tags": [] |
88 | | - }, |
89 | | - "outputs": [], |
90 | | - "source": [ |
91 | | - "# Create instances and call test functions\n", |
92 | | - "# Now create two instances of the class\n", |
93 | | - "# Notice that we do NOT pass in a self variable\n", |
94 | | - "my_vert_wall = PinballWall(wall_type=\"Vertical\", intercept_value=.2)\n", |
95 | | - "my_horiz_wall = PinballWall(wall_type=\"Horizontal\", intercept_value=.2)\n", |
| 64 | + "class SimpleGroundSection:\n", |
| 65 | + " def __init__(self, x_start, x_end, polynomial_coefs=(0, 0)):\n", |
| 66 | + " \"\"\"\n", |
| 67 | + " @param x_start What x value to start at\n", |
| 68 | + " @param x_end What x value to end at\n", |
| 69 | + " @param polynomial coeficients for the section y(x) = a0 x^2 + a1 x + a2\n", |
| 70 | + " \"\"\"\n", |
| 71 | + " # TODO - store the start and stop values along with the coefficients\n", |
| 72 | + " ...\n", |
96 | 73 | "\n", |
97 | | - "# Print them both - this will call the string function\n", |
98 | | - "print(f\"Vertical wall: {my_vert_wall}\")\n", |
99 | | - "print(f\"Horizontal wall: {my_horiz_wall}\")\n", |
| 74 | + " def is_between(self, x):\n", |
| 75 | + " \"\"\" Is the x value between the start and end x value?\n", |
| 76 | + " @param x the x value \n", |
| 77 | + " @ return True or False\n", |
| 78 | + " \"\"\"\n", |
| 79 | + " ...\n", |
100 | 80 | "\n", |
101 | | - "# TODO check your reflect function here" |
102 | | - ] |
103 | | - }, |
104 | | - { |
105 | | - "cell_type": "code", |
106 | | - "execution_count": null, |
107 | | - "metadata": { |
108 | | - "deletable": false, |
109 | | - "editable": false |
110 | | - }, |
111 | | - "outputs": [], |
112 | | - "source": [ |
113 | | - "grader.check(\"class_defn\")" |
114 | | - ] |
115 | | - }, |
116 | | - { |
117 | | - "cell_type": "markdown", |
118 | | - "metadata": { |
119 | | - "deletable": false, |
120 | | - "editable": false |
121 | | - }, |
122 | | - "source": [ |
123 | | - "# Write a test reflect function\n", |
| 81 | + " def height(self, x):\n", |
| 82 | + " \"\"\" Return the height, given the x (assumes over the ground)\n", |
| 83 | + " @param x - x value\n", |
| 84 | + " @returns height f(x)\"\"\"\n", |
| 85 | + " ...\n", |
| 86 | + " \n", |
| 87 | + " def plot(self, axs):\n", |
| 88 | + " \"\"\"Plot the section\n", |
| 89 | + " @param axs the figure to plot into\"\"\"\n", |
124 | 90 | "\n", |
125 | | - "TODO: Create some tests in the **test_reflect** method. " |
| 91 | + " ..." |
126 | 92 | ] |
127 | 93 | }, |
128 | 94 | { |
|
133 | 99 | }, |
134 | 100 | "outputs": [], |
135 | 101 | "source": [ |
136 | | - "# Call the test function\n", |
137 | | - "assert my_vert_wall.test_reflect()" |
138 | | - ] |
139 | | - }, |
140 | | - { |
141 | | - "cell_type": "code", |
142 | | - "execution_count": null, |
143 | | - "metadata": { |
144 | | - "deletable": false, |
145 | | - "editable": false |
146 | | - }, |
147 | | - "outputs": [], |
148 | | - "source": [ |
149 | | - "grader.check(\"test_reflect\")" |
150 | | - ] |
151 | | - }, |
152 | | - { |
153 | | - "cell_type": "markdown", |
154 | | - "metadata": { |
155 | | - "deletable": false, |
156 | | - "editable": false |
157 | | - }, |
158 | | - "source": [ |
159 | | - "# Fill in the plot function \n", |
| 102 | + "# Create instances and call test functions\n", |
160 | 103 | "\n", |
161 | | - "TODO: Fill in the plot function\n", |
| 104 | + "# Create and test a single, horizontal linear segment at height 1\n", |
| 105 | + "# polynomial is p0 + p1 x + p2 x^2... etc\n", |
| 106 | + "flat_bit = SimpleGroundSection(-0.5, 1.0, polynomial_coefs=(1, 0))\n", |
| 107 | + "assert not flat_bit.is_between(-0.6)\n", |
| 108 | + "assert flat_bit.is_between(-0.5)\n", |
| 109 | + "assert flat_bit.is_between(0.0) \n", |
| 110 | + "assert flat_bit.is_between(1.0) \n", |
| 111 | + "assert not flat_bit.is_between(1.1)\n", |
| 112 | + "assert flat_bit.is_over(0.1, 1.2)\n", |
| 113 | + "assert np.isclose(flat_bit.height(0.0), 1.0)\n", |
162 | 114 | "\n", |
163 | | - "Slanted lines are optional for this assignment" |
| 115 | + "fig, axs = plt.subplots(1, 1, figsize=(2, 2))\n", |
| 116 | + "flat_bit.plot(axs)\n" |
164 | 117 | ] |
165 | 118 | }, |
166 | 119 | { |
|
171 | 124 | }, |
172 | 125 | "outputs": [], |
173 | 126 | "source": [ |
174 | | - "def plot_check(axs):\n", |
175 | | - " # The values we calculated in calculate_n_time_steps\n", |
176 | | - " left = -4.0\n", |
177 | | - " right = 4.0\n", |
178 | | - " height = 10.0\n", |
179 | | - "\n", |
180 | | - " axs.plot([left, right], [height, height], color='grey', linestyle=\"dotted\")\n", |
181 | | - " axs.plot([left, right], [0, 0], color='grey', linestyle=\"dotted\")\n", |
182 | | - " axs.plot([left, left], [0, height], color='grey', linestyle=\"dotted\")\n", |
183 | | - " axs.plot([right, right], [0, height], color='grey', linestyle=\"dotted\")\n", |
184 | 127 | "\n", |
185 | | - " walls = []\n", |
186 | | - " walls.append(PinballWall(\"Vertical\", -3.0))\n", |
187 | | - " walls.append(PinballWall(\"Vertical\", 3.0))\n", |
188 | | - " walls.append(PinballWall(\"Horizontal\", 8.0))\n", |
189 | | - " walls.append(PinballWall(\"General\", a_b_c=[0.5, 0.5, 1.0]))\n", |
190 | | - " walls.append(PinballWall(\"General\", a_b_c=[-0.5, 0.5, 1.0]))\n", |
191 | | - " for w in walls:\n", |
192 | | - " w.plot(axs, left, right, height)\n", |
| 128 | + "# Create and test a slightly descending straight line\n", |
| 129 | + "# Starts at 1 and drops by 0.25\n", |
| 130 | + "slope_down_bit = SimpleGroundSection(1.0, 1.5, polynomial_coefs=(1.0 + 0.25, -0.25))\n", |
| 131 | + "assert not slope_down_bit.is_between(0.9)\n", |
| 132 | + "assert slope_down_bit.is_between(1.0)\n", |
| 133 | + "assert slope_down_bit.is_between(1.25) \n", |
| 134 | + "assert slope_down_bit.is_between(1.5) \n", |
| 135 | + "assert not slope_down_bit.is_between(1.6)\n", |
| 136 | + "assert slope_down_bit.is_over(1.25, 1.0)\n", |
| 137 | + "assert np.isclose(slope_down_bit.height(1.0), 1.0)\n", |
193 | 138 | "\n", |
194 | | - " axs.axis('equal')\n", |
195 | | - " axs.set_title(f\"Pinball walls\")" |
| 139 | + "fig, axs = plt.subplots(1, 1, figsize=(2, 2))\n", |
| 140 | + "slope_down_bit.plot(axs)\n" |
196 | 141 | ] |
197 | 142 | }, |
198 | 143 | { |
|
203 | 148 | }, |
204 | 149 | "outputs": [], |
205 | 150 | "source": [ |
206 | | - "nrows = 1\n", |
207 | | - "ncols = 1\n", |
208 | | - "fig, axs = plt.subplots(nrows, ncols, figsize=(4, 4))\n", |
209 | 151 | "\n", |
210 | | - "plot_check(axs)" |
| 152 | + "# Create and test a parabola\n", |
| 153 | + "# Interpolates the points (0, 2), (1, 1), (3, 2)\n", |
| 154 | + "parabola = SimpleGroundSection(0.0, 2.0, polynomial_coefs=(2.0, -3.0/2.0, 1.0/2.0))\n", |
| 155 | + "assert not parabola.is_between(-0.1)\n", |
| 156 | + "assert parabola.is_between(1.0)\n", |
| 157 | + "assert not slope_down_bit.is_between(2.1)\n", |
| 158 | + "assert parabola.is_over(1.0, 1.5)\n", |
| 159 | + "assert np.isclose(parabola.height(0.0), 2.0)\n", |
| 160 | + "assert np.isclose(parabola.height(3.0), 2.0)\n", |
| 161 | + "\n", |
| 162 | + "\n", |
| 163 | + "fig, axs = plt.subplots(1, 1, figsize=(2, 2))\n", |
| 164 | + "parabola.plot(axs)\n" |
211 | 165 | ] |
212 | 166 | }, |
213 | 167 | { |
|
219 | 173 | }, |
220 | 174 | "outputs": [], |
221 | 175 | "source": [ |
222 | | - "grader.check(\"Plot_wall\")" |
| 176 | + "grader.check(\"class_defn\")" |
223 | 177 | ] |
224 | 178 | }, |
225 | 179 | { |
|
299 | 253 | "name": "python", |
300 | 254 | "nbconvert_exporter": "python", |
301 | 255 | "pygments_lexer": "ipython3", |
302 | | - "version": "3.11.7" |
| 256 | + "version": "3.12.7" |
303 | 257 | }, |
304 | 258 | "otter": { |
305 | 259 | "OK_FORMAT": true, |
306 | 260 | "tests": { |
307 | | - "Plot_wall": { |
308 | | - "name": "Plot_wall", |
309 | | - "points": 1, |
310 | | - "suites": [ |
311 | | - { |
312 | | - "cases": [ |
313 | | - { |
314 | | - "code": ">>> plot_check(axs)\n", |
315 | | - "hidden": false, |
316 | | - "locked": false |
317 | | - } |
318 | | - ], |
319 | | - "scored": true, |
320 | | - "setup": "", |
321 | | - "teardown": "", |
322 | | - "type": "doctest" |
323 | | - } |
324 | | - ] |
325 | | - }, |
326 | 261 | "class_defn": { |
327 | 262 | "name": "class_defn", |
328 | 263 | "points": 2, |
329 | 264 | "suites": [ |
330 | 265 | { |
331 | 266 | "cases": [ |
332 | 267 | { |
333 | | - "code": ">>> assert my_vert_wall.inside(my_vert_wall.reflect([0.25, 0.0], [1, 0])[0])\n", |
| 268 | + "code": ">>> assert not flat_bit.is_between(-0.6)\n>>> assert flat_bit.is_between(-0.5)\n>>> assert flat_bit.is_between(0.0)\n>>> assert flat_bit.is_between(1.0)\n>>> assert not flat_bit.is_between(1.1)\n>>> assert flat_bit.is_over(0.1, 1.2)\n>>> assert np.isclose(flat_bit.height(0.0), 1.0)\n", |
334 | 269 | "hidden": false, |
335 | 270 | "locked": false |
336 | 271 | }, |
337 | 272 | { |
338 | | - "code": ">>> assert my_vert_wall.reflect([0.25, 0.0], [1, 0])[1][0] < 0\n", |
| 273 | + "code": ">>> assert not slope_down_bit.is_between(0.9)\n>>> assert slope_down_bit.is_between(1.0)\n>>> assert slope_down_bit.is_between(1.25)\n>>> assert slope_down_bit.is_between(1.5)\n>>> assert not slope_down_bit.is_between(1.6)\n>>> assert slope_down_bit.is_over(1.25, 1.0)\n>>> assert np.isclose(slope_down_bit.height(1.0), 1.0)\n", |
| 274 | + "hidden": false, |
| 275 | + "locked": false |
| 276 | + }, |
| 277 | + { |
| 278 | + "code": ">>> assert not parabola.is_between(-0.1)\n>>> assert parabola.is_between(1.0)\n>>> assert not slope_down_bit.is_between(2.1)\n>>> assert parabola.is_over(1.0, 1.5)\n>>> assert np.isclose(parabola.height(0.0), 2.0)\n>>> assert np.isclose(parabola.height(3.0), 2.0)\n", |
339 | 279 | "hidden": false, |
340 | 280 | "locked": false |
341 | 281 | } |
|
375 | 315 | "type": "doctest" |
376 | 316 | } |
377 | 317 | ] |
378 | | - }, |
379 | | - "test_reflect": { |
380 | | - "name": "test_reflect", |
381 | | - "points": 2, |
382 | | - "suites": [ |
383 | | - { |
384 | | - "cases": [ |
385 | | - { |
386 | | - "code": ">>> assert my_vert_wall.test_reflect()\n", |
387 | | - "hidden": false, |
388 | | - "locked": false |
389 | | - } |
390 | | - ], |
391 | | - "scored": true, |
392 | | - "setup": "", |
393 | | - "teardown": "", |
394 | | - "type": "doctest" |
395 | | - } |
396 | | - ] |
397 | 318 | } |
398 | 319 | } |
399 | 320 | } |
|
0 commit comments