Code, Click, Spin:
Bridging Computer Science, Design, Math, and Physics to build a Digital Spinner
Author: Avi Megiddo
Introduction
Integrating technology in education is about more than just using new tools; it's about enhancing the way we teach and learn. This article focuses on a practical project: creating an interactive spinner that can be used in classrooms or software applications/platforms such as Scratch and other web applications. The spinners themselves, the code that creates them (which can be customized, for example, to someone's color palette/naming/numbering preferences), and the Dynamic Spinner Scratch project offer a wide range of educational applications. Beyond these, the project serves as an interdisciplinary example, integrating elements of math (probability and statistics), computer science (coding and software development), art (design principles and color theory), and even language arts (narrative storytelling through interactive choices).
Other software application/platform ideas where this can be used include games, for example, Scratch games involving prizes), decision-making tools (for example: spinners can serve as impartial decision-makers for group activities, project topic selections, or deciding the order of presentations), and Art and Design; spinners could determine themes, color schemes, or the code can be adapted to produce SVG files for laser cutting.
Each of these applications not only makes learning more interactive and fun but also demonstrates the versatility of coding and design skills in solving real-world problems. By integrating such projects into the curriculum, educators can provide students with meaningful opportunities to apply their knowledge across disciplines, preparing them for the complexities of the modern world.
The tool uses visual programming in Scratch to allow for dynamic interaction, simulating physical forces through variables and loops. It also utilizes a Python function written with ChatGPT to generate the spinners 2 through 40 spinner sectors (wedges or slices) for a range of applications. The function can be run in Google Colab, a cloud-based Python notebook environment that empowers users to execute code, share work, and access a vast array of computational resources — all within a browser.
Using Scratch for the initial design, and then leveraging Python code generated through conversation with ChatGPT, made to run with Google Colab proved successful. This project illustrates how educators can develop/utilize engaging and educational software. It's especially relevant for teachers involved in MYP Design and DP Computer Science, showcasing a blend of programming, design, math, and physics. This article will explore the project from inception to realization, detailing each stage's technical and educational merits.
Making the Spinners
The idea was to converse with ChatGPT to write the code that creates spinners up to 40 slices/sectors/wedges.? This would make the sector size of the 40-participant spinner 360/40 = 9 degrees to work with for adding the number and the virtual spinning peg, represented by a metallic color circle (this circle color is used by the code as a trigger to make the ticking sound as each peg hits the flapper.? More on the Scratch part later. The task was to create the spinners programmatically, with random colors, and get the code to save them to my desktop in a folder, with a consistent file name convention.? If this task proved successful, I could import them into Scratch as spinner sprite costumes, and call them dynamically based on the length of a list of names entered by a user (the participant list).?
The goal was to create a Scratch project in which the teacher/user can simply type or paste a comma or space-delimited list of students,? and Scratch functions would do the rest; parse the input string and convert it to a list, and determine its length, and get a spinner with the corresponding number of sectors.
Colaboratory and ChatGPT
I wanted a function that can be copied + pasted into Colaboratory,? "just press play", and have it generate the spinners from 2 to 40 sectors, with numbers, and dots representing pegs/handles to simulate where the user would hold and spinner if it were real.
Colaboratory, or "Colab" for short, is an educational tool that is particularly useful for coding in Python. It's a free, cloud-based platform that allows users to write and execute Python code through their browser. It is especially beneficial in educational settings for a few key reasons:
Python Function in Colab
Conversing with ChatGPT, I was able to successfully code a Python function that generates my desired range of spinners up to 40 sectors, with different numbers of slices, colors, and metallic pegs, outputting them as PNG files in a zipped folder. Here’s an overview of the function and its components:
import matplotlib.pyplot as plt
import numpy as np
import os
from matplotlib.patches import Wedge, Circle
import matplotlib.patheffects as PathEffects
import shutil
def generate_random_color():
"""Generate a random hex color."""
return "#{:06x}".format(np.random.randint(0, 0xFFFFFF))
def generate_random_metallic_color():
"""Generate a random metallic color (gold, silver, or gray)."""
metallic_colors = ["#ffd700", "#c0c0c0", "#808080"]
return np.random.choice(metallic_colors)
def generate_spinners_png_enhanced(num_slices_start, num_slices_end, filenames_prefix, output_zip):
temp_dir = 'spinners_png_enhanced'
os.makedirs(temp_dir, exist_ok=True)
for num_slices in range(num_slices_start, num_slices_end + 1):
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.axis('off')
fig.set_size_inches(6, 6)
radius = 1 # Standard radius for simplicity
border_width = 0.05 # Width for the border
peg_radius = 0.05 # Radius for the dowel rod peg circle
# Draw the spinner border
border = Circle((0, 0), radius + border_width, color='black')
ax.add_patch(border)
# Generate a random color for the pegs
peg_color = generate_random_metallic_color()
for i in range(num_slices):
color = generate_random_color()
start_angle = i * (360 / num_slices)
end_angle = (i + 1) * (360 / num_slices)
wedge = Wedge(center=(0, 0), r=radius, theta1=start_angle, theta2=end_angle, facecolor=color)
ax.add_patch(wedge)
# Calculate the angle and position for the text
text_angle = np.radians((start_angle + end_angle) / 2)
text_x = 0.85 * radius * np.cos(text_angle)
text_y = 0.85 * radius * np.sin(text_angle)
# Set font size relative to number of slices
min_font_size = 12 # Adjust as needed for visibility in Scratch
font_size = max(min_font_size, radius * 0.1 * 20 / np.sqrt(num_slices))
text = ax.text(text_x, text_y, str(i + 1), ha='center', va='center',
color='white', fontsize=font_size)
# Create a text outline for readability
text.set_path_effects([PathEffects.withStroke(linewidth=3, foreground='black')])
# Add pegs
peg_x = radius * np.cos(text_angle)
peg_y = radius * np.sin(text_angle)
ax.add_patch(Circle((peg_x, peg_y), peg_radius, color=peg_color))
plt.xlim(-1.2, 1.2)
plt.ylim(-1.2, 1.2)
filename = f'{filenames_prefix}_{num_slices}_slices.png'
filepath = os.path.join(temp_dir, filename)
plt.savefig(filepath, bbox_inches='tight', transparent=True)
plt.close()
# Zip all the PNG files
shutil.make_archive(temp_dir, 'zip', temp_dir)
# This function assumes you're using this in a Google Colab environment.
# If you're not, you'll need to find another way to download the files.
try:
from google.colab import files
files.download(temp_dir + '.zip')
except ImportError:
print(f"The zip file is saved as {temp_dir + '.zip'}.")
print("This environment doesn't support automatic downloads.")
# Example usage to generate a zip file of enhanced spinner PNGs
generate_spinners_png_enhanced(2, 40, 'spinner_enhanced', 'spinners_enhanced.zip')
Detailing the Spinner Creation Function
This function is designed to generate an interactive classroom spinner, focusing on practicality for class sizes up to 40 students. Each spinner sector, calculated to be 9 degrees for clear visibility, represents a student with unique colors and pegs for easy identification.
The user interface prioritizes direct interaction, considering enhancements like Scratch's color sensing for dynamic user engagement. Development benefited from iterative conversations with ChatGPT, focusing on refining technical and user experience aspects. The result is a Python function tailored for educational use, facilitating the creation of customizable spinners.
Python Function Breakdown
Here's how the Python function generate_spinners_png_enhanced works, step by step:
Key components of the Python function
Each snippet of code plays a crucial role in the spinner's creation, so we'll explore them with the mindset of teaching and understanding their significance.
Initializing the Environment
import matplotlib.pyplot as plt
import numpy as np
import os
from matplotlib.patches import Wedge, Circle
import matplotlib.patheffects as PathEffects
import shutil
Explanation: Before we start creating anything, we need to prepare our toolbox. This means importing libraries—collections of pre-written code that we can use to perform common tasks. matplotlib is a library for creating visualizations, numpy (abbreviated as np) helps us with mathematical operations, and os and shutil are used for handling files and directories. Think of these imports as gathering your art supplies before you start painting.
Generating Colors
def generate_random_color():
"""Generate a random hex color."""
return "#{:06x}".format(np.random.randint(0, 0xFFFFFF))
Explanation: This function is our paint mixer. Colors on computers are often represented in hexadecimal format (a base-16 number system). This function picks a random number between 0 and 16777215 (which is FFFFFF in hex) and formats it as a hex color string. Each time you call this function, you get a new, random color for a spinner sector.
def generate_random_metallic_color():
"""Generate a random metallic color (gold, silver, or gray)."""
metallic_colors = ["#ffd700", "#c0c0c0", "#808080"]
return np.random.choice(metallic_colors)
Explanation: Here, we're selecting a color for the pegs, but we want them to stand out. We choose from a small list of 'metallic' colors to make them visually distinct from the sectors. Using np.random.choice, we pick one at random each time we generate a spinner.
Main Function to Generate Spinners
def generate_spinners_png_enhanced(num_slices_start, num_slices_end, filenames_prefix, output_zip):
temp_dir = 'spinners_png_enhanced'
os.makedirs(temp_dir, exist_ok=True)
Explanation: This is the starting point where we begin crafting our spinners. We create a temporary directory to store our images. If it doesn't exist, os.makedirs creates it for us. This keeps our files organized and in one place, making cleanup and retrieval straightforward.
Drawing the Spinner
for num_slices in range(num_slices_start, num_slices_end + 1): fig, ax = plt.subplots() ax.set_aspect('equal') ax.axis('off') fig.set_size_inches(6, 6)
for num_slices in range(num_slices_start, num_slices_end + 1):
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.axis('off')
fig.set_size_inches(6, 6)
Explanation: For each spinner, we start by setting up a drawing space (fig) and a drawing surface (ax). We ensure the spinner is drawn in equal proportion (not stretched or squashed) and without any axes for a clean look. The size of the figure is set to be large enough to detail, but not so large it becomes cumbersome to work with.
Creating Each Sector
for i in range(num_slices):
color = generate_random_color()
start_angle = i * (360 / num_slices)
end_angle = (i + 1) * (360 / num_slices)
wedge = Wedge(center=(0, 0), r=radius, theta1=start_angle, theta2=end_angle, facecolor=color)
ax.add_patch(wedge)
Explanation: Here, we're slicing the spinner. Each loop iteration creates a new sector (wedge) with a unique color. The angles are calculated based on the number of slices, ensuring each sector is evenly spaced around the circle. This is a bit like cutting a pie into equal pieces, where each piece gets its own unique flavor (color).
Adding Text and Pegs
text = ax.text(text_x, text_y, str(i + 1), ha='center', va='center',
color='white', fontsize=font_size)
text.set_path_effects([PathEffects.withStroke(linewidth=3, foreground='black')])
Explanation: Each sector gets a number, placed in the center for easy reading. The text function puts a number in each sector, and we use path effects to outline the text, making it stand out against the background. This is akin to labeling each pie piece so everyone knows which piece they're getting.
The placement of the text can be adjusted programmatically here, with larger numbers yielding text closer to the circumference.
text_x = 0.9 * radius * np.cos(text_angle)
text_y = 0.9 * radius * np.sin(text_angle)
Wrapping Up the function
Explanation: Once all spinner images are created, we package them into a zip file:shutil.make_archive(temp_dir, 'zip', temp_dir)shutil.make_archive(temp_dir, 'zip', temp_dir)
shutil.make_archive(temp_dir, 'zip', temp_dir)
Scratch Implementation
In Scratch, I've utilized event listeners, variables, control flow, and broadcasts to create an interactive spinner that responds to user input. The spinner's appearance and behavior change dynamically based on the number of participants, with a visual display of participants' names and a simulated physical interaction of spinning and slowing down due to friction.
The ticking sound and the animation of the spinner's pegs add a layer of realism, and holding down the spacebar or mouse button increases the force on the spinner, which is visualized through a slider on the screen.
User Interaction and Interface
The spinner is designed with a user-friendly interface. Students can add their names to a participant list, which dynamically alters the spinner's sectors. Each sector corresponds to a participant, creating a visual representation of equal opportunities for selection.
A key feature is the force slider, akin to a throttle, allowing students to control the power applied to the spinner. By pressing and holding the spacebar or mouse button, we can simulate adding force to the spinner, as participants rotate the spinner the other way to gain momentum.? This is visually represented by the force slider's increasing value. These three options for tactile interaction enhance engagement, as students can feel the cause-and-effect relationship between their actions and the spinner's motion.??
UI and UX of the Dynamic Spinner
When it comes to user interface (UI) and user experience (UX) in educational tools, it's crucial to create an environment that is not only visually appealing but also intuitive for the users—in this case, the students and teachers. The spinner tool achieves this through interactive elements that respond to user input in a clear and meaningful way.
Dynamic Spinner Selection
Dynamic Spinner's design is not static; it changes based on the number of participants. This is achieved by the ingenious use of Scratch's 'costumes'—essentially different appearances for the spinner. Each costume represents a different number of sectors, and the program switches costumes to match the length of the participant list.
Generating the Correct Spinner
This approach frees us from excess work, leveraging Scratch's capabilities to produce a dynamic, responsive experience; just paste or type the participant list with spaces or commas. Through the Scratch interface, educators can effortlessly generate a spinner tailored to their class size, from 2 to 40 students.
Physics Simulation in Scratch
The Scratch platform is not only a tool for teaching coding but also serves as a virtual laboratory for exploring physical phenomena. In this project, fundamental physics concepts are brought to life through code, allowing students to observe and interact with simulations of force and friction.
Physics Behind the Spinner
The physics simulated in your Scratch project is translated into a visual representation in the Python function. While Scratch allows for interactive manipulation of the spinner with a simulation of force and friction, the Python function creates static images that represent the potential states of the spinner.
Simulating Force
The force applied to the spinner is controlled by user input, either through the spacebar or mouse click. This action increases the 'force' variable within the program, accelerating the spinner. The visual feedback through the force slider allows students to see the direct correlation between the amount of force applied and the speed of the spinner. Letting go of the spacebar, or unclicking the mouse/trackpad releases the spinner. The counter-clockwise turning of .2 degrees is meant to simulate raising the peg up to get a big spin with lots of momentum.
The Force Slider
An integral part of the spinner's UI is the 'force' slider, which visually represents the power being applied to the spinner. Here's how it enhances the UX: users can press and hold the spacebar or mouse button to increase the 'force' variable, with the slider on the screen moving in correspondence. This gives a tangible sense of control over the spinner as if they're physically spinning it in the real world. As the force increases, users see the slider fill up, providing instant visual feedback. This immediate response is gratifying and keeps users engaged in the activity.
Friction and Deceleration
Once the input stops, the spinner doesn't halt abruptly. Instead, it decelerates gradually, simulating the effect of friction. In the code, this is represented by a 'friction' variable, which users can adjust, and a 'force' variable that decreases over time, reducing until the motion ceases. The deceleration process provides an observable phenomenon that educators can use to discuss the principles of friction and its role in motion.
The code snippet is designed to mimic the effect of a decreasing force acting on the spinner as it slows down. Initially, the spinner turns by a number of degrees determined by the 'force' variable. With each iteration, 'friction' reduces the 'force', resulting in smaller turns until the force is insufficient to make another turn, at which point the spinner stops. While this doesn't explicitly calculate angular velocity, it creates a similar effect: as the available force decreases, the rate of turning (akin to angular velocity) also decreases, providing a practical demonstration of deceleration in a physical system.
Visual List of Participants
In addition to the spinner, the tool displays a list of participants on the screen. This not only ensures transparency in the random selection process but also aids in the learning process. As the spinner slows and selects a sector, students can easily map the outcome to a name on the list, reinforcing the connection between visual cues and data.
In the next section, we'll delve into the physics behind the spinner's motion and how it’s simulated in Scratch, providing students with an intuitive understanding of fundamental concepts like force and friction.
Parsing the Participant List
The participant list is another key aspect of the UI, playing a dual role in both the function and appearance of the spinner:
Visual Mapping: On the screen, the list is essential for mapping the outcome of the spinner to a participant's name. For instance, if the spinner lands on number 7, everyone can quickly look at the list and see who is associated with that number. This direct correlation between the spinner and the list ensures transparency and fairness in the selection process.
User-Centric Design: This approach keeps the user's needs at the forefront. Educators don't have to manually adjust the tool for different class sizes; the program automatically presents the appropriate spinner. It's a fine example of user-centered design, where the tool adapts to the user's context without additional effort from them.
The combination of these UI/UX features makes the spinner tool not just a functional accessory for the classroom but also a delightful interactive experience. It demonstrates how thoughtful design considerations can lead to an educational tool that's both useful and engaging.
Sound Interaction with Spinner Movement
The snippet of Scratch code you're referring to seems to control the auditory feedback when the spinner is in motion. Here's a breakdown of the logic based on standard Scratch programming patterns:
Event Listener: The when I receive a spinning block is triggered when the 'spinning' message is broadcasted. This typically occurs when the spinner starts its motion, and it sets the stage for what happens next.
领英推荐
Layer Control: The go to front layer block ensures that the sprite responsible for the sound is visually on top of all others. This is more about visual stacking order than sound, but it's useful if the sprite changes visually when the sound plays.
Continuous Checking: The forever loop suggests that the following checks are continuously performed as long as the spinner is spinning.
Color Touch Detection: The if [touching color] conditional checks seem to monitor whether the sprite is touching a particular color. If the spinner has colored sectors and the sprite (perhaps a pointer or peg) touches one of these colors, it triggers the next actions.
Changing Costume: The next costume block typically changes the sprite's appearance. In the context of sound timing, this could be a visual cue synchronized with the sound effect, like a brief flash or bounce to simulate the peg hitting a divider on the spinner.
Sound Timing: The wait until [not [touching color]] block pauses the script until the sprite is no longer touching the color, which likely corresponds to the peg passing a sector boundary on the spinner.
Once it passes, the start sound block plays a click sound, simulating the tactile feedback of a real spinner peg hitting the flapper.
From a teaching perspective, this code is a perfect demonstration of how to synchronize audio with visual elements, a concept that's common in UI/UX design. It's about timing and feedback—critical components in creating an engaging and interactive experience. For students, understanding these concepts can be quite enlightening, tying together elements of design, user experience, and the technical aspects of programming.
The important part is that if we just check for 'touching' of the peg colors, it will tick the whole time the flapper is touching the virtual pegs that slow these contest/raffle spinners.? However, by using wait until not touching, we only make the sound once a flapper touched AND cleared the stick. This functionality helps simulate a physical spinner's behavior and sound digitally.
Implementing the Spinner Flapper in Scratch
In the context of Scratch, here's how the logic simulates the interaction between the spinner and the flapper:
Wait until not touching color
Realistic Ticking: By waiting until the flapper sprite is not touching the peg's color, you ensure the click sound only plays when a peg goes by the flapper, not while it's still in contact. It's this detail that contributes to a realistic ticking sound, just as you would hear on a physical spinner.
This approach is an excellent practical example of conditional logic in programming and can be a valuable teaching point. It reflects the importance of precise control flow to create desired behaviors in digital simulations. By carefully structuring when and how events are triggered in a program, students can recreate complex real-world interactions, such as the spinner and flapper mechanism, in a virtual setting.
The user experience can be fine-tuned with attention to detail. In this case, getting the timing right for the spinner's clicking sound is a small but significant aspect of making the digital spinner feel more authentic.
Decreasing Force Each Rotation
The first snippet shows a loop where the force is decreased as the spinner rotates:
repeat until (force - friction < 0)
turn (force - friction) / 5 degrees
Set force to force minus friction
Calculating the winner automatically: the math
After some thought and research, it made sense to move the pegs to the start of each sector, multiple reasons for this improvement;? Originally, the pegs were situated at the central dividing line of each sector. They are now repositioned to where the boundary lines between adjacent sectors intersect with the outer edge of the spinner. When a peg passes the flapper, this marks the starting point, or minimum angle of a sector to be the winner.
Calculating the winner by counting pegs
A student asked why we can’t count the pegs that pass by the flapper to determine the winner, instead of calculating degrees rotated.? While in theory, it is an excellent idea, it introduces complexity in terms of programming and may lead to less accurate results. Here’s why:
Data Processing Speed: When a spinner is rotating quickly, the script would need to keep an accurate count of the fast-moving pegs. This requires the program to have a very high refresh rate to capture each peg as it passes by a certain point. If the spinner is moving too fast, it could surpass the processing speed, leading to missed counts and inaccurate results.??
Tracking degrees does not require this, as the degrees are tracked by copying the degrees rotated to make the spinner spin:
There is no need to track each detection of the flapper touching peg color; instead, it is coded in that when the spinner turns (force - friction) / coefficient degrees, the degrees change identically.? So the more precise the spinner costumes are, the more precise the spinner will be.? And they are precise, as they too were made programmatically (no human hand was involved in making lines, measuring, rotating, or adjusting).
Boundary Conditions: When a peg lands exactly on the boundary between two colors, it could be challenging for a simple counting mechanism to determine which color is the winner. The pegs have some diameter and the flapper has some width; the spinner wheel could stop in the middle. A mathematical calculation based on degrees is more precise and can clearly define which sector the flapper points to, even in those boundary cases.
Simplicity and Efficiency: Calculating the winner based on the angle (degrees) is a more straightforward approach. The spinner's final angle can be easily divided by the angle of each sector to determine the winning sector.
Programmatic Consistency: Using angles for calculation ensures consistency and fairness in the result. Each spin will be judged by the same criteria, without the risk of miscounting or the influence of spin speed.
User Experience: For the users, especially in an educational setting, it’s important that the outcome is clear and the process is transparent. The angle-based calculation allows students to easily understand and trust the fairness of the outcome since it can be explained and understood mathematically.
In essence, while the peg-counting method is an interesting concept, it introduces potential inaccuracies and complexities that are efficiently resolved by calculating the winning sector based on the spinner's final resting angle. This method is both precise and straightforward, making it an excellent teaching tool for illustrating probability, randomness, and fairness in games of chance.
Tracking Rotation in Scratch: In Scratch, you can keep track of the degrees rotated during the spin. When the spinning stops, you have a record of the total rotation.
With the known starting orientation and the total degrees rotated, you can calculate which sector the flapper points to when the spinner stops. This can be done by dividing the total rotation by the degrees per sector and then using the modulo operation to get the remainder, which corresponds to the position on the spinner. Scratch has a ‘ceiling’ function that can effectively give the sector number where the flapper is! Here is a preview of the math; more on this later!
Resetting the Spinner: After each spin, you can reset the spinner to its starting orientation, ready for the next spin. This could be simply setting the rotation back to zero or to the initial offset if needed.
The Role of the Interior Angle
In a circle, if you want to divide it into equal sectors for each participant, you calculate the interior angle for each sector. The circle has 360 degrees, so if you divide that by the number of participants, you get the angle for each sector. For example, if you have 10 participants, each sector's interior angle would be 360 / 10=36 degrees.
The Modulo Operation
The modulo operation, represented in mathematics as mod, gives us the remainder after division. In the context of the spinner, we use modulo to disregard full rotations. For instance, if your spinner has rotated 750 degrees, you don't need to account for the full two rotations (ignore the fact that 360 goes into 750 twice before that to yield 720; we don’t care about those 2 full spins of 360); we're only interested in the remaining 30 degrees to determine the winner. So,
750 mod??360 = 30 degrees??
This is the equivalent of saying, "after spinning around completely, how far has it gone past the last full circle?"
Meanwhile, you might ask “why don’t I get 30 when I divide 750 by 360?
750 / 360 = 2.08333333333
That is because mod is a mathematical operation that gives us the remainder after division. But it's specifically talking about the remainder in whole numbers, not the decimal part.? So we need to do one more calculation, and that is multiply .08333… by 360 to see what fraction of 360 is left over:
.08333... x 360 = 30
When you divide one number by another, you get a quotient and sometimes a remainder. If we're using whole numbers, the remainder is what's left over after dividing as many times as you can without going over. For instance, if we divide 10 by 3, we can fit 3 into 10 three times (which is 9), and we have a remainder of 1.
However, when we're dealing with division that results in a decimal (like 5.255444 when you divide 1891.96 by 360), we're looking at it a bit differently:
Here, instead of thinking about how many whole times 360 can fit into 1891.96, we're considering how much of a full rotation (360 degrees) is left after we've done all the whole rotations we can.
So, if you spin a wheel and it turns 5 full times (which would be 5 times 360 degrees), plus a bit more, that "bit more" is the decimal part multiplied by 360. In this case, 0.255444 of another full 360-degree turn.
Now, modulo — often written as mod — is a mathematical operation that gives us the remainder after division. But it's specifically talking about the remainder in whole numbers, not the decimal part. It's like asking, "After turning fully for 5 times, what's the angle for that 'bit more' of the turn?"
So when we do 1891.96 mod 360, we're saying, "If we ignore all the full 360-degree turns, what's the angle that's left over?" And that's 91.96 degrees. It's the angle past the last full turn the spinner made. Here's the math behind it:
When you multiply 0.255444 by 360, you're converting that fraction of a full turn back into degrees, which gives us 91.96 degrees.
That's the actual angle we need to figure out where on the spinner we've landed. It tells us how far past the last full 360-degree turn we've gone.
For a classroom spinner, this matters because it tells us which sector the spinner is pointing to when it stops. If the spinner has, for example, 25 sectors, we'd then divide this remaining angle (91.96 degrees) by the angle for each sector (which would be 360 degrees divided by 25) to figure out the winning sector.
Using mod helps us work with just the relevant part of the spinner's rotation — the part that determines the outcome. It's a practical way to simplify problems that involve repeated actions, like spinning, to find out what's happening at the end of those actions.
Here's how it might look in Scratch pseudocode:
Set total_degrees to 1891.96
Set full_rotations to floor(total_degrees / 360)
Set remaining_degrees to total_degrees - (full_rotations * 360)
Here is the Scratch implementation:
Calculating the Winning Sector
Once we have the final angle after the last complete rotation (using modulo), we need to figure out how many interior angles fit into this final angle. This tells us how many sectors the spinner has passed. Mathematically, if your interior angle is 36 degrees and the final angle is 30 degrees,
30 / 36 ≈ 0.83
This means the first number won since we haven’t passed 36 (the first sector). This is why we use the ceiling function since we need to round up to the nearest whole number.??
The Ceiling Function
The ceiling function comes into play here. It rounds up to the nearest whole number. If the spinner points to any part of the first sector, even if it's only rotated 1 degree, it is still in the first sector, not the zeroeth. So, for our spinner,
?30 / 36? = 1? (“the ceiling of 30 divided by 36 is 1”).
The ceiling function ensures that if the spinner lands anywhere within a sector, it's counted as landing on that sector, and not the previous one, since our first sector is 1, not 0.
Closing Remarks
This is how I implemented a spinner in Scratch that also determines the winner of the spin. It's a clever combination of geometry (with the circle and interior angles), arithmetic (with the division and ceiling function), and number theory (with the modulo operation). By understanding these concepts, you can see how mathematics is not just abstract numbers and figures but can be applied to create useful tools and fun and interactive experiences.
And there you have it! After walking through the function step by step, we've seen how some key lines of code contribute to the creation of a unique and functional classroom tool. It's a vivid reminder that, in programming, our efforts to automate processes can yield incredibly rewarding results. With just a simple click of a button, we're able to generate all 40 spinners with extreme accuracy and precision—a task that, if done by hand, would have required considerable time, effort, and meticulous attention to detail.
This Dynamic Spinner project is a testament to the power of combining creativity with computational thinking. It demonstrates not just the utility of programming in solving real-world problems but also the beauty of turning complex challenges into simple, elegant solutions. For educators and students alike, seeing this application come to life underscores the value of perseverance in coding. The hard work is indeed worth it when you can see your ideas materialize into tools that enhance learning and engagement in the classroom.