-
Notifications
You must be signed in to change notification settings - Fork 351
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Hint Mode: Start Coords] Add start coords UI for quadratic graphs #1469
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@khanacademy/perseus": minor | ||
"@khanacademy/perseus-editor": minor | ||
--- | ||
|
||
[Hint Mode: Start Coords] Add start coords UI for quadratic graphs |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import {View} from "@khanacademy/wonder-blocks-core"; | ||
import {Strut} from "@khanacademy/wonder-blocks-layout"; | ||
import {color, font, spacing} from "@khanacademy/wonder-blocks-tokens"; | ||
import { | ||
BodyMonospace, | ||
LabelLarge, | ||
LabelMedium, | ||
} from "@khanacademy/wonder-blocks-typography"; | ||
import {StyleSheet} from "aphrodite"; | ||
import * as React from "react"; | ||
|
||
import CoordinatePairInput from "./coordinate-pair-input"; | ||
import {getQuadraticEquation} from "./util"; | ||
|
||
import type {Coord, PerseusGraphType} from "@khanacademy/perseus"; | ||
|
||
type Props = { | ||
startCoords: [Coord, Coord, Coord]; | ||
onChange: (startCoords: PerseusGraphType["startCoords"]) => void; | ||
}; | ||
|
||
const StartCoordsQuadratic = (props: Props) => { | ||
const {startCoords, onChange} = props; | ||
|
||
return ( | ||
<> | ||
{/* Current equation */} | ||
<View style={styles.equationSection}> | ||
<LabelMedium>Starting equation:</LabelMedium> | ||
<BodyMonospace style={styles.equationBody}> | ||
{getQuadraticEquation(startCoords)} | ||
</BodyMonospace> | ||
</View> | ||
|
||
{/* Points UI */} | ||
<View style={styles.tile}> | ||
<LabelLarge>Point 1:</LabelLarge> | ||
<Strut size={spacing.small_12} /> | ||
<CoordinatePairInput | ||
coord={startCoords[0]} | ||
labels={["x", "y"]} | ||
onChange={(value) => | ||
onChange([value, startCoords[1], startCoords[2]]) | ||
} | ||
/> | ||
</View> | ||
<View style={styles.tile}> | ||
<LabelLarge>Point 2:</LabelLarge> | ||
<Strut size={spacing.small_12} /> | ||
<CoordinatePairInput | ||
coord={startCoords[1]} | ||
labels={["x", "y"]} | ||
onChange={(value) => | ||
onChange([startCoords[0], value, startCoords[2]]) | ||
} | ||
/> | ||
</View> | ||
<View style={styles.tile}> | ||
<LabelLarge>Point 3:</LabelLarge> | ||
<Strut size={spacing.small_12} /> | ||
<CoordinatePairInput | ||
coord={startCoords[2]} | ||
labels={["x", "y"]} | ||
onChange={(value) => | ||
onChange([startCoords[0], startCoords[1], value]) | ||
} | ||
/> | ||
</View> | ||
</> | ||
); | ||
}; | ||
|
||
const styles = StyleSheet.create({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT: Grrr. Same styling as all the other "start-coords-*" implementations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I did admittedly copy/paste the entire sinusoid file and build off of it. I should probably break out |
||
tile: { | ||
backgroundColor: color.fadedBlue8, | ||
marginTop: spacing.xSmall_8, | ||
padding: spacing.small_12, | ||
borderRadius: spacing.xSmall_8, | ||
flexDirection: "row", | ||
alignItems: "center", | ||
}, | ||
equationSection: { | ||
marginTop: spacing.small_12, | ||
}, | ||
equationBody: { | ||
backgroundColor: color.fadedOffBlack8, | ||
border: `1px solid ${color.fadedOffBlack32}`, | ||
marginTop: spacing.xSmall_8, | ||
paddingLeft: spacing.xSmall_8, | ||
paddingRight: spacing.xSmall_8, | ||
fontSize: font.size.xSmall, | ||
}, | ||
}); | ||
|
||
export default StartCoordsQuadratic; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
getCircleCoords, | ||
getLineCoords, | ||
getLinearSystemCoords, | ||
getQuadraticCoords, | ||
getSegmentCoords, | ||
getSinusoidCoords, | ||
} from "@khanacademy/perseus"; | ||
|
@@ -187,6 +188,12 @@ | |
range, | ||
step, | ||
); | ||
case "quadratic": | ||
return getQuadraticCoords( | ||
{...graph, startCoords: undefined}, | ||
range, | ||
step, | ||
); | ||
default: | ||
return undefined; | ||
} | ||
|
@@ -215,3 +222,34 @@ | |
verticalOffset.toFixed(3) | ||
); | ||
}; | ||
|
||
export const getQuadraticEquation = (startCoords: [Coord, Coord, Coord]) => { | ||
const p1 = startCoords[0]; | ||
const p2 = startCoords[1]; | ||
const p3 = startCoords[2]; | ||
|
||
const denom = (p1[0] - p2[0]) * (p1[0] - p3[0]) * (p2[0] - p3[0]); | ||
if (denom === 0) { | ||
// Many of the callers assume that the return value is always defined. | ||
return "Division by zero error"; | ||
} | ||
const a = | ||
(p3[0] * (p2[1] - p1[1]) + | ||
p2[0] * (p1[1] - p3[1]) + | ||
p1[0] * (p3[1] - p2[1])) / | ||
denom; | ||
const b = | ||
(p3[0] * p3[0] * (p1[1] - p2[1]) + | ||
p2[0] * p2[0] * (p3[1] - p1[1]) + | ||
p1[0] * p1[0] * (p2[1] - p3[1])) / | ||
denom; | ||
const c = | ||
(p2[0] * p3[0] * (p2[0] - p3[0]) * p1[1] + | ||
p3[0] * p1[0] * (p3[0] - p1[0]) * p2[1] + | ||
p1[0] * p2[0] * (p1[0] - p2[0]) * p3[1]) / | ||
denom; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is copied from I wish we had a central place where this logic could live, and both If you don't want to move it in this PR, I can move it once this is landed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that would be awesome! Sorry, I didn't see your comment before landing. |
||
|
||
return ( | ||
"y = " + a.toFixed(3) + "x^2 + " + b.toFixed(3) + "x + " + c.toFixed(3) | ||
); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an interesting case! Thanks for testing it.
I am curious: how does the graph preview render in this case? What happens to the graph when the start coords aren't valid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It just shows all the points where they would be, but the quadratic graph doesn't go through the points. The equation box says "Division by zero error"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not too worried about it because I think this is within the "trust the content authors" territory