uclaacm / recursion-lab Goto Github PK
View Code? Open in Web Editor NEWRecursion Excursion is a TeachLA web app for CS 31/32 wanting practice with recursion problems.
Home Page: https://recursion-excursion.netlify.app/
License: MIT License
Recursion Excursion is a TeachLA web app for CS 31/32 wanting practice with recursion problems.
Home Page: https://recursion-excursion.netlify.app/
License: MIT License
The current naming of the Recursion steps are as follows:
The wording is a little awkward from the users' perspective.
The first two steps should be changed to as follows:
Please make these changes to Excursion 1, Excursion 2, Excursion 3, Excursion 4
This is a ๐พ Minor Update
Simulate the user searching through an array of words in lexicographical order and them clicking "higher" or "lower" to update what word they are currently searching.
"Understanding the Problem" pt.1 is the case when the element exists in the array (ie. there is an answer):
if (x == arr[mid])
return mid;
It's basically just an array of "Word"
components that render a different color if it's currently selected based on its index.
The "higher"
and "lower"
buttons work by changing what index is currently being selected. At each index change, there should be a function that checks whether or not the "Word"
at that index is correct, and if so, render some sort of "complete" explanation or if left > right (ie. the binary search failed) then show a different "complete" section.
Basically, it is going to just look like the two previous steps (Base Case + Recursive Formula) combined but into one (ie. the entire function). There is an example of using the FinishCode component in the Intro page using factorials, so check that out to see how it is used.
A progress bar is a visual indication of what problem the user is currently working on.
Lets the user know what stage they are on and how many problems there are left.
What it would look like when the user is on the last problem (Binary Search):
Consult with the Figma to find all of the progress bars
Visual animations/images that illustrate the recursive concepts being taught
GIF / JPG / PNG images & animations work
If possible, try to add an interactive component (could be through the animation)
Resource for Recursion Visualization:
Medium Article on Recursion Animation Examples
Example what the "Intro" page might look like as a finished product
Example explaining Recursion while also using Factorial example
Slideshow example for Recursion
KhanCard and FinishCode have different border styling, where KhanCard is flat and bold and FinishCode is rounded and shadowy.
It would be great if they were consistent, and FinishCode looks better.
Find the CSS on FinishCode (the border) and apply it to KhanCard.
This is a ๐พ Minor Update
Use yarn package react-typescript-checkmark
to have a green checkmark animation rather than a static one.
Make book searching look like an actual book
To visually make the book searching simulation more recognizable
Right now, the Bunny KhanCard for "Identifying the Base Case" is not there. Use it and include the correct code for the problem. This KhanCard will take two inputs:
"n <= 1" will use a Dropdown component
"n" should use a KhanInput component
It will look something like this:
if [Dropdown]:
return [KhanInput]
Basically, it is going to just look like the two previous steps (Base Case + Recursive Formula) combined but into one (ie. the entire function). There is an example of using the FinishCode component in the Intro page using factorials, so check that out to see how it is used.
The FinishCode component is at the end of every "Excursion X" page that contains a function (on the left) and an output box (on the right).
The output box of the FinishCode component shrinks indefinitely when shrinking the screen size. Instead, we want it to still be distinguishable as a box and readable comfortably despite screen size.
Give FinishCode component output box a min-width and/or flex-shrink.
Do not worry about the other elements of the FinishCode that may overflow, that would be a future issue revolving around mobile-responsiveness.
This is a ๐พ Minor Update
This slider can be found on Excursion 1, "Staircases", Understand the Problem. Basically, the slider determines how many rows of the triangle there are.
Although there is a variable that does show how many rows there are currently, it would so much more user-friendly to visually see the numbers, like a number line.
Add the numbers 1-9 right beneath the slider tick marks so it looks like a slider number line.
n-input-container
class.<div className="tickmark-container">
<div className="tickmark-label">1</div>
<div className="tickmark-label">2</div>
<div className="tickmark-label">3</div>
<div className="tickmark-label">4</div>
<div className="tickmark-label">5</div>
<div className="tickmark-label">6</div>
<div className="tickmark-label">7</div>
<div className="tickmark-label">8</div>
<div className="tickmark-label">9</div>
</div>
display: flex
and justify-content: space-between
for container cssnumColumns
. You could add a new css class on the tickmark to bold it or just inline style for boldcursor:pointer
This is a ๐พ Minor Update
The KhanInput (src/components/shared/KhanInput.tsx
) and the Dropdown (src/components/shared/Dropdown.tsx
) have a fixed width.
Sometimes, the answer / representation we expect is just one digit or character, so we want the sizing of the input box to reflect that.
Create a prop for both KhanInput and Dropdown called size that takes small
and medium
as values. Note: the current sizing for both of these should correspond to medium
, so define small
as you see fit. Update these components accordingly through conditional operations.
<Dropdown
size="medium"
options={options2}
correct_answer={isCorrect}
index={0}
answer={answerKey.question2}
update_answer={setIsCorrect}
/>
There are a lot of buttons across the site, all implemented using HTML/CSS. Some are part of the KhanCard component and others are part of the interactive visual component of the page, as seen below:
Because everything was implemented in CSS and by different developers, there was no consistency between our design. Thus, each button has a different feel to it, which was not the original intention.
By making a Button
React component, each page can simply import that component and the CSS pertaining to the component will be applied consistency among pages. The end result will model the KhanCard's button styling.
The basic props for Button
are
className
: stringonClick
: handler functionsize
: string (e.g. small, medium, large)color
: string (e.g. red, orange, yellow, green, blue, purple, any-hex-color (#fcba03), etc. -- (have a default color))Disclaimer:
Button
React component. Please change this name to NavButton
and change the component name usage in the pages accordingly.disable
used only in KhanCard. Also note that in the implementation, you will have to render children, which will usually be something like "Check" or "Next".This is a ๐งน Refactor Request
Right now, the sidebar only closes when the user clicks the "X" button. This works, but most people expect to close the sidebar when they click on the outside the sidebar. Therefore, this task is to implement that functionality. After finishing this, refactor Header.tsx.
This link explains the way to use useRef
and eventListeners
for this task (very specific):
https://stackoverflow.com/questions/66626487/hiding-sidebar-component-on-outside-click
(First, check out the Contribution Workflow in this Github README.md: https://github.com/uclaacm/recursion-lab)
The sidebar code can be found in src > components > shared > AppWrapper > Header.tsx
This code here combines both the actual header (ie. the blue header with the menu icon + page title) and the Sidebar data (ie. everything within the nav
tag).
After you finish the outside click feature, you'll want to refactor the Header.tsx code into two files: Header.tsx and a new file, Sidebar.tsx . The path of Sidebar.tsx should be src > components > shared > Sidebar.tsx
. This is because right now, Header.tsx contains both the actual header and the sidebar code, and we want to isolate them. Header.tsx will use Sidebar (found in Sidebar.tsx) as a functional component.
The usage of Sidebar as a functional component will look something like this within Header.tsx:
<Sidebar sidebar={sidebar} setSidebar={setSidebar}>
where the sidebar
and setSidebar
within the brackets are the state in the Header.tsx .
If possible, please have the "X" positioned leftward instead of where it currently is (center). It will require some HTML/CSS reconfiguring, but this would be great.
Update use of Khan Component and other small styling fixes on Problem3.tsx
Check out MarioBaseCase.tsx for help on using the KhanCard component
The idea is to make use of the parent component to manage and handle the state of the child KhanCard/KhanInput
Update Dining Setup text (right underneath the title)
Change Dining Page font to whatโs on the Figma
Style Bunny Page Understand The Problem sectionโs โNextโ button to look nicer [not the navigation buttons on the bottom] Can use MUI buttons
Style Binary Search โNextโ and โGoโ buttons to look nicer [not the navigation buttons on the bottom] Can use MUI buttons
Some ExpandBox(es) have KhanCard(s), such as in the Excursion 1 Identify the Base Case ExpandBox. The KhanCard component takes these two of four props:
correct
prop: string that gives an explanation of the answer once the user gets the question correct or attempts out.
incorrect
prop: string that gives a hint for the answer when the user gets the answer incorrect.
These KhanCards have dummy text:
Write the correct
props (explanations) and incorrect
props (hints) to have actual helpful text.
Right now, the Mario staircase interactive component (found in Problem 1, Understand the Problem) allows the user to type in a number from 1-9 and this input displays the staircase and the corresponding number of steps the user chose.
This is clunky for the user because we want them to see how the staircase changes over time (ie. from 1 to 2 to 3, etc). They could type 1
and then 9
and not necessarily see the gradual changes.
A great solution would be to implement a slider that goes from 1-9 because this inherently moves through the numbers consecutively, showing the staircase changes over time.
This is a ๐ Feature Request
File: src/components/binary-comps/BinaryCode.tsx
Please reference Excursion 1 and Excursion 1's Code the Components Together as an example for how FinishTheCode component is used and its source code (src/components/mario-comps/MarioCode.tsx) for how it is implemented.
The FinishTheCode component is the last component in the Binary Search pages to complete it entirely.
Note that there is a more robust way of creating the chosen_function
than shown in MarioCode. Everything else should be similar.
Right now we are using a dependency to draw a static checkmark on all our pages.
Having unnecessary dependencies, for one, makes our code slower, but also it does not have an interesting animation feedback when the user gets the answer correct.
I would advise to use an existing checkmark SVG found online or through one of these solutions, but for learning purposes, I would definitely understand how the CSS interacts with the SVG (ie. what class corresponds to what and what each CSS property does). You could also look into SVG animations for fun as well before/after this issue.
This is a ๐ Feature Request
** SAME AS #78 **
Right now, the Mario KhanCard for "Identifying the Base Case" is dummy text. Update it to include the correct code for the problem. This KhanCard will take two inputs:
In essence, it will look something like this:
if ([Dropdown]){
return [KhanInput]
}
Right now, the Dining KhanCard for "Identifying the Base Case" is not there. Use one and include the correct code for the problem. This KhanCard will take two inputs:
It will look something like this:
if [KhanInput] is [KhanInput]:
return [KhanInput]
Right now, all the buttons used in the learning lab are coded as raw HTML buttons.
In React, the idea is to wrap commonly used elements as a component since it is easier to read, test, and make changes. Also, we are using one-line css attributes that are not necessary.
The idea is to have a button component as follows:
<CustomButton backgroundColor="some-color" hoverColor="#9500ae">Click me!</CustomButton>
Note that you'll have to use the .shared-button
class, remove the other CSS one-liners, and then inline-style for the correct background color and hover color. For completeness sake, also add an optional disabled prop (defaulted false) so that we can use this component within the KhanCard and FinishCard. Besides those "Check" buttons, the other button usage places are as follows:
Also note that it would be best if you support not only "#[some-alpha-numeric-characters]" but also the generic colors, such as "red", "orange", "yellow", "green", "blue", "purple" as CSS would define them. In other words, both the propr backgroundColor
and hoverColor
should support a hex code string as well as a regular color name string (Think of using a map). This makes the programmers' life easier so they don't have to find the hex code for a simple color every time.
This is a ๐งน Refactor Request
File: ~/src/components/bunny-comps/BunnyCode.tsx
FinishTheCode component works by taking in the correct function in the prop given_function
and taking in the user-defined function in the prop chosen_function
. It also includes the parameters, so it runs the functions in this page. Note that it needs to have a test case value to determine correctness, namely n=7. Example from the page:
given_function={() => recurFib(7)}
chosen_function={() =>
selectedRecurFib(
7,
selectedanswer.question1,
selectedanswer.question2,
selectedanswer.question3
)
}
Although our solution works, we are creating functions for every permutation possible based on user-input. If you were to tell someone that you were dynamically creating a function based on user input and defining functions for every permutation of user input and selecting the chosen user function based on these inputs, they'll look at you crazy. This is because creating all these functions are a waste of memory since we (technically) already have the user function, so all we have to do is execute it.
Think of a code editor... when you write and run the code, the editor is not going to guess which functions you are going to use and then match it with your input function, it'll just run what you gave it. That's what we want to do.
Thankfully, Javascript has a solution for this. Please look into this documentation for Function constructor. It creates a function based on a string. Therefore, if we can get the function into a string format, and run the Function constructor, we can have the function we want without having to case-by-case select the function. THIS IS HUGE!!! (We don't need a Code Editor and we don't have to hard-code anything!)
This is a ๐ Feature Request
Right now, the Mario KhanCard for "Generalize the Pattern: Recursive Formula" is dummy text. Update it to include the correct recursive formula for the problem. This KhanCard will take two inputs:
The final product will look something like this:
return [KhanInput] + [Dropdown]
Right now, the Dining KhanCard for "Generalize the Pattern: Recursive Formula:" is not there. Use one and include the correct code for the problem. This KhanCard will take two inputs:
"Friend.left" will be a KhanInput
"Friend.left" will be a KhanInput
It will look something like this:
left_sum = post_order_sum([KhanInput])
right_sum = post_order_sum([KhanInput])
There is a component FinishCode
found at src/components/shared/FinishCode.tsx
. An example of its usage is in Excursion 2 in the Code the Components Together box:
We want to avoid having the Output box shrink tremendously when the code is long. As you can see, the dark grey output box is practically non-existent. An example of what it should look like is Excursion 1 in the Code the Components Together box:
margin: 5em
on the finish-card-container class. This is way too much. Use margin: 20px
.The KhanCard component (ie. "Fill in the Blank") should have a checkmark next to the words "Fill in the Blank" to indicate whether the user got it correct or not. Moreover, upon correct, the grey checkmark should change to a green one.
To be used in the KhanCard and maybe expanded to the accordion. Many uses.
[EDIT: Maybe try using the CheckCircle from the MUI library first to get the checkmark placed correctly and dynamically render the grey / green color without animations -->
import CheckCircleIcon from '@mui/icons-material/CheckCircle'
]
After the above works, try to use react-checkmark or something similar to make it more visually appealing. Try the command "yarn add react-checkmark" or anything yarn. Do not use the npm command.
Feel free to implement this feature first in the Mario Page's Khan Card component so you have something to work with. KhanCard does have its own state called "correct" so it does know whether the user got the question correct or not. Use this to conditionally render the checkmark type.
The tricky part is working between the KhanCard state and the parent state (ie. MarioBaseCase.tsx). This is because MarioBaseCase knows which questions are correct, not the KhanCard. So, MarioBaseCase is going to have to pass the correct checkmark to KhanCard and KhanCard just has to render it.
No.
KhanCard does not allow for intermixing of Dropdown and KhanInput, specifically when there is one of each.
Both are required for the KhanCard to be correct.
UI and Functionality Updates
UI Changes:
next
and previous
buttonsjustify-content: end
)Functionality Changes:
I noticed that the stack ends with "May is on a call with Lea This call takes 20 minutes." and finally "Lea is on a call with May. This call takes 10 minutes." Notice how this is a cycle. It's supposed to end on Lea having no more calls. In other words, there's a misinterpretation in what this stack possibly represents. Please see the Recursion Lab Notes document for clarification.
Another thing is that technically, this recursion stack is incomplete. Think of it like a post-sum traversal stack (as stated in docs). You traversed the whole way, but we never showed the "backward traversal" back to the root node to show how we computed the root node, where the whole sum is [root.val] + recurse(root.left) + recurse(root.right). Our example just assumes there's only one child for all nodes, but even in this case, there is still backtracking.
Note: make sure nothing is currently in "Understand the Problem" for the Rabbit page. There used to be a KhanCard but it should be moved to "Identifying the Base Case" (ie. run git pull
to get all the new changes)
Also please work on this task only after re-working the previous tasks!
We could use the Fibonacci sequence as our example. We could have 1 1 2 3 5 8
(shown using rabbits) as an animation so they can see that this problem is the Fibonacci sequence. Showing the next sequence could be automatic (as in timed) or manual (with a next button).
So like if we were at the sequence 1 1 2 3
(in terms of rabbits)
Them clicking next
or waiting 1 second
would trigger the next number (of rabbits) 1 1 2 3 5
We could also have a number above the rabbits to indicate how many there are at that current step.
An step-through animation that allows the user to visualize what exactly the code is doing at every step. It's the same idea of a function call stack but putting "Friends"/nodes onto the stack rather than functions. The output box is a verbose version of what's happening in the stack.
The home page is the first page the user sees when opening Recursion Excursion:
It does not currently match the updated version on the Figma:
As we noted, the title styling should stay the same. However, here are the things that should be changed:
Lighter opacity solution:
.element{
background-color:rgba(0,0,0,1); /*where 1 stands for 100% opacity*/
}
.element:hover{
background-color:rgba(0,0,0,0.5); /*where 0.5 stands for 50% opacity*/
}
This is a ๐พ Minor Update
This is adding onto the existing FinishCode component. It is specific to the "Dining" Page in the "Code the Components" section (ie. the Factorial code). (Side note: the Factorial code is simply an example, once we figure out the exact implementation we will expand it to other functions.)
The Output box works like this. As you can see, there are two Dropdown components where the user can choose what specific code they want to use. Once they make their selections, you basically "record" this function and pass it to the FinishCode component so it can execute it. That's the main goal: having the Output box execute the exact code that the user chooses. It may be the correct factorial function, or it may be some other similar function, but run it anyways.
Your goal is to have something like this in the Output box, assuming they wrote a similar but incorrect factorial function:
Correct Output: 120
Your Output: 720
From the user's perspective, these look like test case(s) to help see if they're on the right track or not.
Right now, the Output box is executing the factorial function, but it is running only the correct factorial recursive function and not what the user inputted. Therefore, you must create a "dynamic factorial function" that uses the user's choices from Dropdowns and displays it on the box. Thus, useState and dynamic variables will be your best friend. Possibly useEffect may be necessary.
Allows the user to write code through a "fill in the blank" style of learning.
Basically used on every page to get the user to write code and see the output.
See the KhanCard component for guidance
Right now, we are saving the users' correctness state for each KhanCard in an array in state for every Excursion page, and more than not in every step of each Excursion page.
Once the user refreshes or exists the application, their correctness state resets back to all false (no questions correct). We want the users' correctness information to persist in the browser.
Implement localStorage for each of these correctness arrays.
Great article, but doesn't take into account initial null state for the localStorage keys
This article does, but quite verbose.
Add-on:
This is a ๐ Feature Request
Update the sub-text ("Setup") on the Rabbit Page
This is a sample to help you get started. Feel free to use it and expand on it or come up with something different. Just something to introduce the Fibonacci Sequence in a creative way.
The Binary Search page is the last problem in the Recursion Excursion series of problems.
The current CSS styling for the search array can be improved a bit, animation-wise:
Improve existing CSS implementations to your discretion (it may go beyond the search array)
Note: Please do not improve the styling on the buttons, that is for a different issue.
This is a ๐งน Refactor Request
Lets user select an option from given choices
This will be heavily used in the "Finish the Code" component since we can give options that actually produce working code, albeit correct/incorrect. Using text inputs from the user may result in non-working code, and it is not worth it to parse and fix their inputs.
Right now, the Bunny KhanCard for "Generalize the Pattern: Recursive Formula" is not there. Use it and include the correct code for the problem. This KhanCard will take two inputs:
"fib(n-1)" will use a KhanInput component
"fib(n-2)" will use a KhanInput component
It will look something like this:
fib(n) = [KhanInput] + [KhanInput]
Previously, the KhanCard only took one input in the form of an Input box or a Dropdown menu. While this is fine for some questions, most of the questions in this learning lab require the user to choose 2 or more answers per questions, making this component obsolete.
Instead of KhanCard taking an index (representing one answer per card), it should take as many indices as it needs, or rather, an array of indices. Iterate through this array of indices to determine whether the user got the question correct or incorrect.
In Excursion 2 (Dining Out), the visual image shows the model as a linked list, where Lea calls May who calls Jane, and so on. The call stack in Understand the Problem is based on this image, where Lea knows how long her phone calls based on the people she's calling and their phone call times. Read Recursion Lab Notes to understand the problem itself.
The issue is with the (1) people with phones image and (2) the stack in Understand the Problem. The current implementation treats this problem as a simple list, where one person calls another who calls another, etc. However, the original emphasis of the problem is the binary tree-like nature, where Lea can call May and Jane, not just one other person. This tree representation aligns nicely with the recursive solution, so we want to get rid of the list structure.
Note: just ignore the stack implementation stuff for now (ie. create a new page/component with the tree work, maybe visually on top of the stack stuff).
Node values (in minutes):
Lea: 10
May: 7
Ryan: 5
Jane: 15
Sam: 12
(Future reference:push Lea, push May, push Sam, pop Sam, pop May, push Jane, push Ryan, pop Ryan, pop Jane, pop Lea, display answer.
)
@kesdlvi -- for this upcoming Tuesday, 11/14, I would only expect check points #1,2,3 to be completed. It would be great if you looked into SVG CSS / JavaScript animations, but the animation implementation of that can begin next week.
Interesting JavaScript-focused binary tree animation solution: Youtube Video
Currently, this KhanCard has dummy text for the "correct" and "incorrect" props. Please update these accordingly to make sense for Fibonacci.
<KhanCard
correct="This is an explanation for when you get the answer correct." //explanation for when user gets answer correct
incorrect="This is a hint for when you get the answer incorrect." //hint when user gets answer incorrect
correct_answer={isCorrect} //must pass in correctness state from parent
index={[0]} //index for what KhanCard you are referring to
>
Because the Prev and Next nav buttons are at the bottom of the screen, when the user navigates to the next page, they stay at the bottom of the page.
It should bring them to the top of the page where the start of the next problem will be.
On route change, have the scroll reset back to the top: Dev.to React Scroll Solution
Right now, the Mario section for "Generalize the Pattern: Recursive Formula" is empty. Update it using FinishCode component to simulate a running program from user input. Make sure you create the particular formula correctly, allowing for user input.
Use the FinishCode to finish this section. It is similar to KhanCard but it also requires two functions -- in this case, the "sum of the first n natural numbers" function, and its input from the user, to function. The output box outputs whatever the function would based what dropdowns the user chose.
This is the code:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.