diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 540a3d2..6457860 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,9 @@ # TODO: Add isort # See: https://github.com/PyCQA/isort/pull/2122 +# Real exports are test data: they must stay byte-for-byte as Lambda Feedback wrote them. +exclude: ^tests/fixtures/exports/ + repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.3.0 diff --git a/tests/fixtures/exports/README.md b/tests/fixtures/exports/README.md new file mode 100644 index 0000000..b98f2a0 --- /dev/null +++ b/tests/fixtures/exports/README.md @@ -0,0 +1,70 @@ +# Real Lambda Feedback exports + +Each folder here is a question set exactly as Lambda Feedback exported it. Do not edit, reformat +or re-save these files: their value is that they are what the platform really produces. To add +coverage, add another export as a new folder. + +## What an export contains + +``` +set_.json +question_000_.json # 000 is the question's orderNumber +question_001_... +media/question_000__0001.png # referenced from the questions by basename +``` + +JSON files are written on a single line. + +## Set + +`name`, `description`, `isSurvey`, `releasedAt`, `manuallyHidden`, and the visibility of final +answers, worked solutions, structured tutorials and the chatbot. + +## Question + +| key | meaning | +|---|---| +| `orderNumber` | position in the set, from 0; matches the filename | +| `title` | shown to students | +| `skill` | difficulty (exports use 1/3 and 2/3) | +| `guidance` | a sentence to students about the question's purpose | +| `durationLowerBound`, `durationUpperBound` | expected minutes | +| `masterContent` | markdown shared by every part: setup, data, figure | +| `publish`, `displayFinalAnswer`, `displayStructuredTutorial`, `displayWorkedSolution`, `displayChatbot` | booleans | +| `parts` | ordered from 0; students see (a), (b), ... | + +## Part + +| key | meaning | +|---|---| +| `content` | markdown for this part | +| `answerContent` | the final answer shown to students, markdown | +| `responseAreas` | the answer boxes; may be empty | +| `workedSolution` | `{"content": ..., "children": []}`; optional. A line containing only `---` (or `***`) splits the content into the steps of the structured tutorial | + +## Response area + +Every area carries the same keys: `orderNumber`, `preResponseText` and `postResponseText` (labels +either side of the box), `contentAfter` (markdown shown after the box, before the next one), +`inputSymbols`, `displayInputSymbols`, `evaluationFunctionName`, `gradeParams`, `livePreview`, +`includeInPdf`, `saveAllowed`, the feedback settings (`separateFeedback` and the colour and +prefix fields), `tests`, `cases` and `response`. + +`response.responseInput` holds `responseType`, the correct `answer`, and a `config`. The pairings +in these exports: + +| responseType | evaluationFunctionName | answer | notes | +|---|---|---|---| +| `MATH_SINGLE_LINE` | `symbolicEqual` | expression, e.g. `(pi/6)*rho*U**2*R**2` | `gradeParams` `{"strict_syntax": false}` | +| `NUMERIC_UNITS` | `comparePhysicalQuantities` | number and unit, e.g. `0.106 kg` | `gradeParams` includes `rtol`; `config` is null | +| `MULTIPLE_CHOICE` | `arrayEqual` | list of booleans, one per option | `config` has `single`, `options`, `randomise`; `gradeParams` null | + +- `inputSymbols`: `{"symbol": "\\(\\rho\\)", "code": "rho", "aliases": [...], "isVisible": true}`. `symbol` is what students see, `code` what the evaluator reads. +- `tests`: `{"id", "payload", "expectedResponse": {"isCorrect"}}`, the author's checks of the marking. +- `cases`: `{"id", "answer", "feedback", "isCorrect", "params"}`. A response matching `answer` is shown `feedback`, and may be marked correct. + +## Markdown + +Maths uses `$...$` inline and `$$` on its own lines for display, rendered by KaTeX: commands +KaTeX lacks do not display (degrees written `^\circ`, for example). Images are written +`![pictureTag](question_000_Title_0001.png){ width=60% }`. diff --git a/tests/fixtures/exports/me2_introduction/media/question_000_Hydraulic_scale_0001.png b/tests/fixtures/exports/me2_introduction/media/question_000_Hydraulic_scale_0001.png new file mode 100644 index 0000000..a8a509c Binary files /dev/null and b/tests/fixtures/exports/me2_introduction/media/question_000_Hydraulic_scale_0001.png differ diff --git a/tests/fixtures/exports/me2_introduction/media/question_001_Friction_on_a_plate_0001.png b/tests/fixtures/exports/me2_introduction/media/question_001_Friction_on_a_plate_0001.png new file mode 100644 index 0000000..4bd774e Binary files /dev/null and b/tests/fixtures/exports/me2_introduction/media/question_001_Friction_on_a_plate_0001.png differ diff --git a/tests/fixtures/exports/me2_introduction/media/question_002_Towing_a_submarine_0001.png b/tests/fixtures/exports/me2_introduction/media/question_002_Towing_a_submarine_0001.png new file mode 100644 index 0000000..7acef10 Binary files /dev/null and b/tests/fixtures/exports/me2_introduction/media/question_002_Towing_a_submarine_0001.png differ diff --git a/tests/fixtures/exports/me2_introduction/question_000_Hydraulic_scale.json b/tests/fixtures/exports/me2_introduction/question_000_Hydraulic_scale.json new file mode 100644 index 0000000..e2f1cc5 --- /dev/null +++ b/tests/fixtures/exports/me2_introduction/question_000_Hydraulic_scale.json @@ -0,0 +1 @@ +{"orderNumber":0,"title":"Hydraulic scale","skill":0.3333333333333333,"guidance":"This is a gentle warm up question to get into the swing of things after a long summer.","durationLowerBound":5,"durationUpperBound":10,"masterContent":"A piston of diameter $D = 0.1\\space\\mathrm{m}$ is fitted inside a U-shaped tube filled with liquid mercury (with density in $\\rho_{\\small \\mathrm{Hg}} = 13,540~\\mathrm{kg/m^{3}}$), as shown by the sketch below. The mercury rises by $h=1\\space\\mathrm{mm}$ under the weight of the piston.\n\n![pictureTag](question_000_Hydraulic_scale_0001.png){ width=30% }","publish":true,"displayFinalAnswer":true,"displayStructuredTutorial":true,"displayWorkedSolution":true,"displayChatbot":true,"parts":[{"orderNumber":0,"content":"What is the mass, $m$, of the piston?","answerContent":"$$\nm = \\boxed{0.106 \\space \\mathrm{kg}}\n$$\n","responseAreas":[{"orderNumber":0,"contentAfter":"","preResponseText":"$m=$","postResponseText":"","inputSymbols":[],"displayInputSymbols":false,"includeInPdf":false,"saveAllowed":false,"evaluationFunctionName":"comparePhysicalQuantities","livePreview":false,"gradeParams":{"rtol":0.05,"strict_syntax":false},"separateFeedback":true,"commonFeedbackColor":"#C4CDD5","correctFeedbackColor":"#22C55E","correctFeedbackPrefix":"Correct","incorrectFeedbackColor":"#ff5630","incorrectFeedbackPrefix":"Incorrect","tests":[{"id":"f3ab583b-87c3-44da-8f9b-b8cba1d03030","payload":"0.106 kg","expectedResponse":{"isCorrect":true}},{"id":"b1241594-b1b9-4f17-ba91-0bd329f45863","payload":"0.105 kilos","expectedResponse":{"isCorrect":true}},{"id":"ba11fe62-a4be-4003-bf1e-7e41bfff4ebf","payload":"0.23369 pound","expectedResponse":{"isCorrect":true}}],"cases":[{"id":"c9900536-fcd6-4cf4-8ec6-c8091574534d","answer":"0.106 kilos","feedback":"'Kilos' is ambiguous in general. Be explicit with units next time.","isCorrect":true,"params":null},{"id":"ac267f59-c6fe-4064-ba55-5758ca1e6b6c","answer":"0.106 Kg","feedback":"This is correct. Note that capital `K` is actually the SI unit for kelvin. In future use a lower case `k` for kilo (1,000).","isCorrect":true,"params":null},{"id":"e863f0dd-e4fa-4702-8fe3-a8d7319bba1f","answer":"1724 kg","feedback":"","isCorrect":false,"params":null},{"id":"921a8452-b8e3-4761-b0dd-f1a524e91cc1","answer":"13.54 Kg","feedback":"","isCorrect":false,"params":null}],"response":{"responseInput":{"responseType":"NUMERIC_UNITS","answer":"0.106 kg","config":null}}}],"workedSolution":{"content":"The weight of the piston applies a pressure $p = 4mg /(\\pi D^2)$. This pressure adds to the atmospheric pressure, so that the pressure on the mercury on the left-hand side of the tube is $p + p_{at}$. Applying the hydrostatic equations (or Bernoulli’s equations for steady, inviscid and irrotational fluids) we find:\n\n---\n\n$$\np+p_{\\mathrm{at}}=p_{\\mathrm{at}}+\\rho_\\mathrm{w}\\sigma_{\\mathrm{Hg}}gh\n$$\n\nwhere $\\sigma$ is 'specific gravity' (density relative to water).\n\n---\n\nHence:\n\n---\n\n$$\n\\begin{aligned}\\frac{4mg}{\\pi D^2} &= \\rho_\\mathrm{w} \\sigma_\\mathrm{\\small Hg} g h.\\\\m &= \\frac{\\pi}{4}\\rho_\\mathrm{w} \\sigma_\\mathrm{\\small Hg} h D^2 \\\\&= \\frac{\\pi}{4}* 1000 * 13.54 * 10^{-3} * 10^{-2} \\\\&= \\boxed{0.106\\,\\mathrm{kg}}\\end{aligned}\n$$","children":[]}},{"orderNumber":1,"content":"If this result is to be used to measure the piston's weight, what would you do to improve the accuracy of the measurement?\n","answerContent":"Selecting a fluid with a smaller specific gravity.\n","responseAreas":[],"workedSolution":{"content":"To improve the accuracy of the measurement, $D$, being fixed by the piston's size, it is best to make $h$ bigger (this is what is read), which translates in **selecting a fluid with a smaller specific gravity.**","children":[]}}]} \ No newline at end of file diff --git a/tests/fixtures/exports/me2_introduction/question_001_Friction_on_a_plate.json b/tests/fixtures/exports/me2_introduction/question_001_Friction_on_a_plate.json new file mode 100644 index 0000000..e081bdc --- /dev/null +++ b/tests/fixtures/exports/me2_introduction/question_001_Friction_on_a_plate.json @@ -0,0 +1 @@ +{"orderNumber":1,"title":"Friction on a plate","skill":0.6666666666666666,"guidance":" This question is to refresh yourself using control volumes, which were used in ME1 and will be used often in ME2.","durationLowerBound":15,"durationUpperBound":20,"masterContent":"A fluid with density $\\rho = 800\\,\\mathrm{kg/m}^3$, flows at $U_0 = 3\\,\\mathrm{m/s}$ over a flat plate of length $L = 1\\,\\mathrm{m}$ and width $W = 1\\,\\mathrm{m}$. At the trailing edge the boundary-layer thickness is $\\delta = 25\\,\\mathrm{mm}$. Assume the velocity profile at the trailing edge to be linear (in the image shown), and the flow to be two-dimensional. \n\n![pictureTag](question_001_Friction_on_a_plate_0001.png){ width=60% }","publish":true,"displayFinalAnswer":true,"displayStructuredTutorial":true,"displayWorkedSolution":true,"displayChatbot":true,"parts":[{"orderNumber":0,"content":"Compute the mass flow rate across the top surface of the control volume (noted ''ab'' in the figure).","answerContent":"$$\n\\dot{m}= \\boxed{30 \\space \\mathrm{kg/s} \\>}\n$$","responseAreas":[{"orderNumber":0,"contentAfter":"","preResponseText":"$ \\dot{m}= $","postResponseText":"","inputSymbols":[],"displayInputSymbols":false,"includeInPdf":false,"saveAllowed":false,"evaluationFunctionName":"comparePhysicalQuantities","livePreview":false,"gradeParams":{"rtol":0.05,"strict_syntax":false},"separateFeedback":true,"commonFeedbackColor":"#C4CDD5","correctFeedbackColor":"#22C55E","correctFeedbackPrefix":"Correct","incorrectFeedbackColor":"#ff5630","incorrectFeedbackPrefix":"Incorrect","tests":[{"id":"673a7103-7930-4b11-8a62-98732b27bb5e","payload":"30 kgs-1","expectedResponse":{"isCorrect":false}}],"cases":[{"id":"092d2819-a2b5-481c-b0f9-dbfecfb176fa","answer":"30 kgs-1","feedback":"To enter a negative exponent, put the exponent in parentheses (e.g. ```kg*s^(-1)``` ). The expression ```kgs-1``` is interpreted differently and is incorrect.. ","isCorrect":false,"params":null}],"response":{"responseInput":{"responseType":"NUMERIC_UNITS","answer":"30 kg/s","config":null}}}],"workedSolution":{"content":"From mass conservation:\n\n---\n\n$\\dot{m}_{ad}=\\dot{m}_{ab}+\\dot{m}_{bc}$\n\n---\n\nThis becomes:\n\n---\n\n$\\rho W\\Large{\\int}_{\\small 0}^{\\small \\delta}\\normalsize{U_0\\space \\mathrm{d}y}=\\dot{m}_{ab}+\\rho W\\Large{\\int}_{\\small 0}^{\\small \\delta}\\normalsize{u(y)\\space\\mathrm{d}y}$\n\n---\n\nSince we know that $u(y)$ is linear, we can express it in terms of $y$ and $U_0$:\n\n---\n\n$$\nu(y)=U_0\\frac{y}{\\delta},\n$$\n\n---\n\nTherefore:\n\n$$\n\\begin{aligned}\\dot{m}_{ab}&=\\rho W U_0\\left(\\Large{\\int}_{\\small 0}^{\\small \\delta}\\normalsize{1-\\frac{y}{\\delta}\\space\\mathrm{d}y} \\right)\\\\\\dot{m}_{ab}&=\\rho W U_0\\frac{\\delta}{2},\\\\\\dot{m}_{ab}&=(800)(1)(3)\\frac{25\\times 10^{-3}}{2}.\\end{aligned}\n$$\n\n---\n\n$$\n\\dot{m}= \\boxed{30 \\space \\mathrm{kg/s} \\>}\n$$","children":[]}},{"orderNumber":1,"content":"Determine the drag force on the plate.","answerContent":"$$\nF_{\\mathrm{plate}}= \\boxed{30\\space \\mathrm{N}\\space}\n$$","responseAreas":[{"orderNumber":0,"contentAfter":"","preResponseText":"$F_D =$","postResponseText":"","inputSymbols":[],"displayInputSymbols":false,"includeInPdf":false,"saveAllowed":false,"evaluationFunctionName":"comparePhysicalQuantities","livePreview":false,"gradeParams":{"rtol":0.05,"strict_syntax":false},"separateFeedback":true,"commonFeedbackColor":"#C4CDD5","correctFeedbackColor":"#22C55E","correctFeedbackPrefix":"Correct","incorrectFeedbackColor":"#ff5630","incorrectFeedbackPrefix":"Incorrect","tests":[],"cases":[],"response":{"responseInput":{"responseType":"NUMERIC_UNITS","answer":"30 N","config":null}}}],"workedSolution":{"content":"From momentum conservation:\n\n***\n\n***\n\n$$\nF_{\\small \\mathrm{fluid}}=M_{ab}+M_{bc}-M_{ad}\n$$\n\n***\n\nSince we are calculating the horizontal resultant force, we need to consider the horizontal momentum in the section \"ab\"; this means that we ignore any vertical velocities. Since the velocity of the fluid at $y=\\delta$ (i.e. at \"ab\") is always $U_0$, we can say:\n\n***\n\n$$\nM_{ab}=U_0\\dot{m}_{ab},\n$$\n\n***\n\nWe then also convert the other momentum flowrate terms into their mathematical forms, and proceed to find the force of the plate on the fluid, as shown below:\n\n***\n\n$$\nF_{\\mathrm{fluid}}=M_{ab}+\\rho W\\Large{\\int}_{\\small 0}^{\\small \\delta}\\normalsize{u(y)^2\\space\\mathrm{dy}}-\\rho W\\Large{\\int}_{\\small 0}^{\\small \\delta}\\normalsize{U_0^2\\space \\mathrm{dy}}\n$$\n\n***\n\n$$\nF_{\\mathrm{fluid}}=U_0\\dot{m}_{ab}+\\rho WU_0^2\\left(\\LARGE{\\int}_{\\small 0}^{\\small \\delta}\\normalsize \\frac{y^2}{\\delta^2}-1\\space\\mathrm{dy} \\right)\n$$\n\n***\n\n$$\nF_{\\mathrm{fluid}}=(3)(30)+(800)(1)(3)^2\\left[ -\\frac{2}{3}(25\\times 10^{-3})\\right]\n$$\n\n***\n\n$$\nF_{\\mathrm{fluid}}=-30 \\space \\mathrm{N}\n$$\n\n***\n\nHowever, the question asks us to find the drag force **of the fluid on the plate**, hence:\n\n***\n\n$$\nF_{\\mathrm{plate}}=-F_{\\mathrm{fluid}}\n$$\n\n***\n\n$$\nF_{\\mathrm{plate}}= \\boxed{30\\space \\mathrm{N}\\space}\n$$\n","children":[]}}]} \ No newline at end of file diff --git a/tests/fixtures/exports/me2_introduction/question_002_Towing_a_submarine.json b/tests/fixtures/exports/me2_introduction/question_002_Towing_a_submarine.json new file mode 100644 index 0000000..c25e2e8 --- /dev/null +++ b/tests/fixtures/exports/me2_introduction/question_002_Towing_a_submarine.json @@ -0,0 +1 @@ +{"orderNumber":2,"title":"Towing a submarine","skill":0.6666666666666666,"guidance":"This is another revision question from ME1, for those who need extra practice. ","durationLowerBound":15,"durationUpperBound":20,"masterContent":"A submerged submarine is towed horizontally at a steady speed $U$ in deep still water. An axially-symmetrical wake is formed behind the submarine in which the water velocity may be assumed to vary linearly from $U$ on the axis to zero at a radius of $R$. The variation of the water pressure with depth may be assumed to be unaffected by the presence of the submarine. The density of the water is $\\rho$. Using a control-volume analysis, we want to find the required power to tow the submarine. For both choices of control volumes (A and B as shown above), derive an expression for:\n\n![pictureTag](question_002_Towing_a_submarine_0001.png){ width=60% }","publish":true,"displayFinalAnswer":true,"displayStructuredTutorial":true,"displayWorkedSolution":true,"displayChatbot":true,"parts":[{"orderNumber":0,"content":"The drag force $F$ of the submarine.","answerContent":"$$\n\\boxed{F = \\frac{\\pi}{6}\\rho U^2 R^2}\n$$","responseAreas":[{"orderNumber":0,"contentAfter":"","preResponseText":"$F=$","postResponseText":"","inputSymbols":[{"symbol":"\\(R\\)","code":"R","aliases":["r"],"isVisible":true},{"symbol":"\\(U\\)","code":"U","aliases":["u","V","v"],"isVisible":true},{"symbol":"\\(\\rho\\)","code":"rho","aliases":["Rho","RHO","ρ"],"isVisible":true},{"symbol":"\\(\\pi\\)","code":"pi","aliases":["Pi","PI","π"],"isVisible":true}],"displayInputSymbols":true,"includeInPdf":false,"saveAllowed":false,"evaluationFunctionName":"symbolicEqual","livePreview":true,"gradeParams":{"strict_syntax":false},"separateFeedback":true,"commonFeedbackColor":"#C4CDD5","correctFeedbackColor":"#22C55E","correctFeedbackPrefix":"Correct","incorrectFeedbackColor":"#ff5630","incorrectFeedbackPrefix":"Incorrect","tests":[{"id":"90a7eac7-8227-43ab-a66b-c84f57031ea4","payload":"(pi/6)*(rho)*(U**2)*(R**2)","expectedResponse":{"isCorrect":true}},{"id":"ffe1668b-50f1-4f72-90c1-afe161af372a","payload":"(pi/6)*(rho)*(u**2)*(R**2)","expectedResponse":{"isCorrect":true}},{"id":"321a8462-6fee-4cf1-bcc3-cea98936a5bd","payload":"(pi/6)*(rho)*(U**2)*(r**2)","expectedResponse":{"isCorrect":true}},{"id":"28ce9bfc-9df5-4621-8975-f67ceb3802aa","payload":"(pi/6)*(Rho)*(U**2)*(R**2)","expectedResponse":{"isCorrect":true}},{"id":"161b92da-e463-4326-9902-4e8859e6fd66","payload":"(Pi/6)*(rho)*(U**2)*(R**2)","expectedResponse":{"isCorrect":true}}],"cases":[{"id":"8ee06968-6616-40d0-87ab-85760d28188f","answer":"(pi)*(rho)*(U**2)*(R**2)","feedback":"The form of your expression looks right, but there's a missing factor.","isCorrect":false,"params":null},{"id":"07de4ed1-e249-4261-a0f7-b70c3c64024e","answer":"pi*rho*U^2*R^2","feedback":"","isCorrect":false,"params":null},{"id":"ffdb14a0-81e9-4fef-9d9a-11e588fb25d2","answer":"pi*rho*U^2*R^2","feedback":"","isCorrect":false,"params":null},{"id":"d2ca95d2-6a51-4d2b-a192-ec60dd5f2cbc","answer":"pi*rho*U^2","feedback":"The submitted expression has some of the components of the correct answer, but is incomplete.","isCorrect":false,"params":null},{"id":"46d5be66-9490-4a8d-9313-685f54dbfd75","answer":"U*U","feedback":"","isCorrect":false,"params":null},{"id":"fbf244a5-ec4f-4511-8c66-932e8e486d5e","answer":"-(pi/6)*(rho)*(U**2)*(R**2)","feedback":"The magnitude is correct. The sign is opposite to the reference answer but as the question did not define the coordinate system explicitly then this is presumably correct.","isCorrect":true,"params":null},{"id":"7d4d7568-51ea-4ca4-9e5b-8beb3888a593","answer":"pi*R**2*U**2*rho/2","feedback":"The form of your expression is correct but the coefficient is incorrect.","isCorrect":false,"params":null},{"id":"5df6185d-0a37-4ed2-91f5-79bcadbfe36a","answer":"-(rho/2U^2piR^2)","feedback":"The form of your expression looks right, but there's a missing factor.","isCorrect":false,"params":null}],"response":{"responseInput":{"responseType":"MATH_SINGLE_LINE","answer":"(pi/6)*(rho)*(U**2)*(R**2)","config":{"allowPhoto":true,"allowHandwrite":true,"enableRefinement":true}}}}],"workedSolution":{"content":"The mass flow rate entering the control volume is\n\n---\n\n$$\n\\dot{m}_{\\mathrm{in}} = \\rho U A_{\\mathrm{disk}} = \\rho U \\pi R^2\n$$\n\n---\n\n(since the velocity is uniform). The mass exiting the control volume on the left (the wake) is:\n\n---\n\n$$\n\\dot{m}_{\\mathrm{wake}} = 2\\pi\\rho \\int_{r=0}^{r=R} r (U r /R)\\mathrm{d}r\n$$\n\n---\n\nHence, the mass flow rate leaving the control volume through the side ($\\dot{m}_{\\mathrm{side}}$) is:\n\n---\n\n$$\n\\begin{aligned}\\dot{m}_{\\mathrm{side}} &= \\dot{m}_{\\mathrm{in}} - \\dot{m}_{\\mathrm{wake}} \\\\&= \\rho U \\pi R^2 - 2\\rho U \\pi \\int_{r=0}^{r=R} \\frac{r^2 }{R}\\mathrm{d}r \\\\&= \\rho U \\pi R^2 - 2\\rho U \\pi \\left[\\frac{1}{3}\\frac{r^3}{R}\\right]_{r=0}^{r=R}\\\\ &= \\rho U \\pi R^2 - \\frac{2}{3}\\rho U \\pi R^2 \\\\&= \\frac{1}{3}\\rho U \\pi R^2\\end{aligned}\n$$\n\n---\n\nForce-momentum equation (FME):\n\n \n\n---\n\nThe momentum flowrate entering the control volume is $M_{\\mathrm{in}} = \\dot{m}_{\\mathrm{in}} U$. The momentum flowrate exiting the control volume on the left (the wake) is\n\n---\n\n$$\nM_{\\mathrm{wake}} = 2\\pi\\rho \\int_{r=0}^{r=R} r (U r /R)^2\\mathrm{d}r.\n$$\n\n---\n\nThe mass leaving the control volume by the side is also contributing to the removal of momentum, $M_{\\mathrm{side}} = \\dot{m}_{\\mathrm{side}} U$. Hence, the momentum leaving the control volume is $M_{out} = M_{\\mathrm{wake}} + M_{\\mathrm{side}}$.\n\n---\n\nThe FME reads:\n\n---\n\n$$\nM_{out} - M_{\\mathrm{in}} = - F + F_p,\n$$\n\n---\n\nwhere $F_p$ represents pressure forces. However, we assume the pressure to be unaffected by the presence of the submarine, which leaves the hydrostatic pressure force. Since the hydrostatic pressure has the same linear profile on both sides of the control volume (front and wake), it contributes nothing to the horizontal force. Hence:\n\n---\n\n$$\n\\begin{aligned}- F &= 2\\pi\\rho \\int_{r=0}^{r=R} r (U r /R)^2\\mathrm{d}r + \\dot{m}_{\\mathrm{side}} U - \\dot{m}_{\\mathrm{in}} U \\\\&= 2\\rho U^2 \\pi \\int_{r=0}^{r=R} (r^3/R^2)\\mathrm{d}r + \\frac{1}{3}\\rho U^2 \\pi R^2 - \\rho U^2\\pi R^2\\\\ &= 2\\rho U^2 \\pi \\left[\\frac{1}{4}\\frac{r^4}{R^2} \\right]_{r=0}^{r=R} - \\frac{2}{3}\\rho U^2 \\pi R^2 \\\\&= \\frac{1}{2}\\rho U^2 \\pi R^2 - \\frac{2}{3}\\rho U^2 \\pi R^2\\end{aligned}\n$$\n\n---\n\nWhich gives:\n\n$$\n\\boxed{F = \\frac{\\pi}{6}\\rho U^2 R^2}\n$$","children":[]}},{"orderNumber":1,"content":"The power $P$ required to tow the submarine.","answerContent":"$$\n\\boxed{P = \\frac{\\pi }{6}\\rho U^3 R^2}\n$$","responseAreas":[{"orderNumber":0,"contentAfter":"","preResponseText":"$P=$","postResponseText":"","inputSymbols":[{"symbol":"\\(U\\)","code":"U","aliases":["u"],"isVisible":true},{"symbol":"\\(\\pi\\)","code":"pi","aliases":["Pi","PI"],"isVisible":true},{"symbol":"\\(\\rho\\)","code":"rho","aliases":["Rho","RHO"],"isVisible":true}],"displayInputSymbols":true,"includeInPdf":false,"saveAllowed":false,"evaluationFunctionName":"symbolicEqual","livePreview":true,"gradeParams":{"strict_syntax":false},"separateFeedback":true,"commonFeedbackColor":"#C4CDD5","correctFeedbackColor":"#22C55E","correctFeedbackPrefix":"Correct","incorrectFeedbackColor":"#ff5630","incorrectFeedbackPrefix":"Incorrect","tests":[{"id":"df9a2784-fff4-4847-b2dd-03b528263bd4","payload":"(pi/6)*(rho)*(U**3)*(R**2)","expectedResponse":{"isCorrect":true}},{"id":"ad2f15c5-50b2-4edd-ae13-1ef0d1220def","payload":"pi/6*rho*U^3R^2","expectedResponse":{"isCorrect":true}},{"id":"156666ef-eec4-4308-bc5e-cc710f217529","payload":"(pi)*(rho)*(U**3)*(R**2)","expectedResponse":{"isCorrect":false}}],"cases":[{"id":"f43bb150-c3d4-4539-9d75-bce08a83a1c3","answer":"(pi)*(rho)*(U**3)*(R**2)","feedback":"This answer is close in form but is incorrect by a numerical factor. ","isCorrect":false,"params":null}],"response":{"responseInput":{"responseType":"MATH_SINGLE_LINE","answer":"(pi/6)*(rho)*(U**3)*(R**2)","config":{"allowPhoto":true,"allowHandwrite":true,"enableRefinement":true}}}}],"workedSolution":{"content":"By definition, the power is $F.U$. Therefore:\n\n***\n\n$$\n\\boxed{P = \\frac{\\pi }{6}\\rho U^3 R^2}\n$$\n","children":[]}}]} \ No newline at end of file diff --git a/tests/fixtures/exports/me2_introduction/question_003_Speed_of_sound.json b/tests/fixtures/exports/me2_introduction/question_003_Speed_of_sound.json new file mode 100644 index 0000000..13a80c3 --- /dev/null +++ b/tests/fixtures/exports/me2_introduction/question_003_Speed_of_sound.json @@ -0,0 +1 @@ +{"orderNumber":3,"title":"Speed of sound","skill":0.6666666666666666,"guidance":"This question applies ME1 methods to a new problem.","durationLowerBound":15,"durationUpperBound":20,"masterContent":"","publish":true,"displayFinalAnswer":true,"displayStructuredTutorial":true,"displayWorkedSolution":true,"displayChatbot":true,"parts":[{"orderNumber":0,"content":"","answerContent":"","responseAreas":[]}]} \ No newline at end of file diff --git a/tests/fixtures/exports/me2_introduction/question_004_Molecules,_particles,_and_continuum.json b/tests/fixtures/exports/me2_introduction/question_004_Molecules,_particles,_and_continuum.json new file mode 100644 index 0000000..0bce085 --- /dev/null +++ b/tests/fixtures/exports/me2_introduction/question_004_Molecules,_particles,_and_continuum.json @@ -0,0 +1 @@ +{"orderNumber":4,"title":"Molecules, particles, and continuum","skill":0.6666666666666666,"guidance":"This question bridges ME1 and ME2, exploring the continuum hypothesis and the definition of a fluid particle.","durationLowerBound":20,"durationUpperBound":25,"masterContent":"Let us consider still air in standard atmospheric conditions at ground level: $T_0 = 273.15\\,\\mathrm{K}$, $p_0 = 1.00\\,\\mathrm{bar}$. For simplicity, we assume air to be made of exactly the same diatomic molecules (a fair assumption) with molar mass $M = 28.8\\,\\mathrm{g/mol}$. Each molecule is modelled as a hard sphere of diameter $\\sigma = 1.54\\times 10^{-10}\\,\\mathrm{m}$. Consequently, air is considered to behave as an ideal gas. The Avogadro number is $\\mathcal{N}_A = 6.02\\times 10^{23}\\,\\mathrm{mol}^{-1}$, and the universal gas constant is $\\tilde{R} = 8.314\\,\\mathrm{J/(mol\\cdot K)}$.","publish":true,"displayFinalAnswer":true,"displayStructuredTutorial":true,"displayWorkedSolution":true,"displayChatbot":true,"parts":[{"orderNumber":0,"content":"Calculate the number of molecules $n_{\\small 0}$ per unit volume.\n\n \n\n(Note that in the response area below you can use exponential notation, e.g. `5.7e13 m^(-3)` is an acceptable input - but an incorrect answer!).\n","answerContent":"$$\nn_{\\small 0}\\approx \\boxed{2.65 \\times 10^{25}\\,\\mathrm{m}^{-3}~\\text{(molecules per metre cubed)} \\space}\n$$\n\nTo enter in the checker, for example:\n\n`2.65e25 m^(-3)`\n","responseAreas":[{"orderNumber":0,"contentAfter":"","preResponseText":"$n_0 \\approx$ ","postResponseText":"","inputSymbols":[],"displayInputSymbols":false,"includeInPdf":false,"saveAllowed":false,"evaluationFunctionName":"comparePhysicalQuantities","livePreview":false,"gradeParams":{"rtol":0.1,"strict_syntax":false},"separateFeedback":true,"commonFeedbackColor":"#C4CDD5","correctFeedbackColor":"#22C55E","correctFeedbackPrefix":"Correct","incorrectFeedbackColor":"#ff5630","incorrectFeedbackPrefix":"Incorrect","tests":[],"cases":[],"response":{"responseInput":{"responseType":"NUMERIC_UNITS","answer":"2.65e+25 m^(-3)","config":null}}}],"workedSolution":{"content":"The fluid density is directly related to the particle density: $\\rho_0 = n_{\\small 0} m /V$ (assuming all molecules to be the same). In this question, we take $V$ to be a cubic meter. Therefore, we need to calculate $\\rho_0$ and $m$ (the mass of one molecule).\n\n***\n\nThe density can be computed from the ideal-gas law (the gas is assumed to be ideal): $\\rho_0 = p_0 / (R T_0)$ where $R = \\tilde{R}/M$.\n\n***\n\nThe mass is directly computed from the Avogadro number and the molecular mass: $m = M/\\mathcal{N}_A$.\n\n***\n\nHence:\n\n***\n\n$$\nn_{\\small 0} = \\frac{p_0 \\mathcal{N}_A V}{\\tilde{R} T_0} = \\frac{(10^5)(6.02\\times 10^{23})(1)}{(8.314)(273.15)} \n$$\n\n\n\n***\n\n$$\nn_{\\small 0}\\approx \\boxed{2.65 \\times 10^{25}\\,\\text{molecules per metre cubed} \\space}\n$$\n","children":[]}},{"orderNumber":1,"content":"It can be shown that the mean-free path in the hard-sphere model is $\\ell = 1/(\\sqrt{2}\\pi \\sigma^2 n)$. Give its numerical value at ground level:","answerContent":"$$\n\\boxed{\\ell_{\\small{0}}\\approx 3.58\\times 10^{-7}\\space\\mathrm{m}\\space},\n$$\n\n$$\n \\space \\boxed{0.1~\\mathrm{mm}< d < 1~\\mathrm{mm}}.\n$$\n","responseAreas":[{"orderNumber":1,"contentAfter":"","preResponseText":"\\(d=\\)","postResponseText":"","inputSymbols":[],"displayInputSymbols":false,"includeInPdf":false,"saveAllowed":false,"evaluationFunctionName":"comparePhysicalQuantities","livePreview":false,"gradeParams":{"rtol":0.85,"strict_syntax":false},"separateFeedback":true,"commonFeedbackColor":"#C4CDD5","correctFeedbackColor":"#22C55E","correctFeedbackPrefix":"Correct","incorrectFeedbackColor":"#ff5630","incorrectFeedbackPrefix":"Incorrect","tests":[],"cases":[],"response":{"responseInput":{"responseType":"NUMERIC_UNITS","answer":"0.541 mm","config":null}}},{"orderNumber":0,"contentAfter":"If we are concerned with an engineering problem with length-scale $L\\approx 1~\\mathrm{m}$, what should the size of a fluid particle be?","preResponseText":"\\(\\ell_0=\\)","postResponseText":"","inputSymbols":[{"symbol":"$\\mu$","code":"mu","aliases":[],"isVisible":true}],"displayInputSymbols":false,"includeInPdf":false,"saveAllowed":false,"evaluationFunctionName":"comparePhysicalQuantities","livePreview":false,"gradeParams":{"rtol":0.00005,"strict_syntax":false},"separateFeedback":true,"commonFeedbackColor":"#C4CDD5","correctFeedbackColor":"#22C55E","correctFeedbackPrefix":"Correct","incorrectFeedbackColor":"#ff5630","incorrectFeedbackPrefix":"Incorrect","tests":[],"cases":[],"response":{"responseInput":{"responseType":"NUMERIC_UNITS","answer":"3.58e-7 m","config":null}}}],"workedSolution":{"content":"$$\n\\ell_0 = \\frac{1}{\\sqrt{2}\\pi\\sigma^2 n_{0}} = \\frac{1}{\\sqrt{2}\\pi (1.54\\times 10^{-10})^2 (2.65 \\times 10^{25})} \\approx 3.58 \\times 10^{-7}\\,\\mathrm{m}\n$$\n\n***\n\nThe fluid particle size $d$ must be such that:\n\n***\n\n$$\n10^{-7}\\ \\mathrm{m} \\ll d \\ll 10^{0}\\ \\mathrm{m} \\quad \\longrightarrow \\quad 0.1\\ \\mathrm{mm} < d < 1\\,\\mathrm{mm}\n$$\n","children":[]}},{"orderNumber":2,"content":"Aircraft designers assume air to be a continuum medium. The density of air decreases with altitude as follows:\n\n$$\n\\\\\\rho(z) = \\rho_0 \\left[1 - \\frac{g}{c_p T_0}z\\right]^{1/(\\gamma-1)}\\\\\n$$\n\nwhere $\\rho_0$, $T_0$ are the density and temperature at ground level and $z$ is the altitude measured from the ground. The gravitational acceleration is $g = 9.8\\,\\mathrm{m/s}^2$, the specific heat at constant pressure is $c_p = 0.83\\,\\mathrm{kJ/(kg \\cdot K)}$ and the heat capacity ratio is $\\gamma = 7/5$.\n\nAs density decreases, the mean-free path is expected to increase. Therefore, there must be a height $H$ from which the continuum assumption is no longer valid. Using the results and assumptions from parts (a) and (b), and assuming that the aircraft designer is concerned with scales of order one meter, is it reasonable to use the continuum model for an airline at 10 km altitude? Show your working.","answerContent":"The designers' assumption appears to be adequate.","responseAreas":[{"orderNumber":0,"contentAfter":"","preResponseText":"","postResponseText":"","inputSymbols":[],"displayInputSymbols":false,"includeInPdf":true,"saveAllowed":false,"evaluationFunctionName":"arrayEqual","livePreview":false,"gradeParams":null,"separateFeedback":true,"commonFeedbackColor":"#C4CDD5","correctFeedbackColor":"#22C55E","correctFeedbackPrefix":"Correct","incorrectFeedbackColor":"#ff5630","incorrectFeedbackPrefix":"Incorrect","tests":[],"cases":[],"response":{"responseInput":{"responseType":"MULTIPLE_CHOICE","answer":[true,false],"config":{"single":true,"options":["Yes","No"],"randomise":false}}}}],"workedSolution":{"content":"First, we show that the density ratio $\\rho/\\rho_0$ can be written in terms of particle densities:\n\n***\n\n$$\n\\frac{\\rho}{\\rho_0} = \\frac{n m}{V}\\cdot\\frac{{V}}{n_{0} m} = \\frac{n}{n_{0}}\n$$\n\n***\n\nFrom part (b) the mean free path is given by $\\ell = 1/(\\sqrt{2}\\pi\\sigma^2 n)$, hence:\n\n***\n\n$$\n\\frac{\\rho}{\\rho_0} = \\frac{n}{n_{0}} = \\frac{\\sqrt{2}\\pi\\sigma^2\\ell_0}{\\sqrt{2}\\pi\\sigma^2\\ell} = \\frac{\\ell_0}{\\ell}\n$$\n\n***\n\nFor an altitude of $H=10~\\mathrm{km}$,\n\n***\n\n$$\n\\frac{\\rho_{\\small{z=H}}}{\\rho_0} = \\frac{\\ell_{\\small 0}}{\\ell_{\\small z=H}} = \\left[1 - \\frac{g}{c_p T_0} H\\right]^{1/(\\gamma-1)}\n$$\n\n***\n\nRearranging for the mean-free path at altitude,\n\n***\n\n$$\n\\begin{aligned} \\ell_{\\small z=H} &= \\ell_{\\small 0}\\left[1 - \\frac{g}{c_p T_0} H\\right]^{-1/(\\gamma-1)}\\\\\\ell_{\\small z=H} &= 3.58\\times 10^{-7}\\left[1 - \\left(\\frac{9.8*10^4}{830*273.15}\\right)\\right]^{(-5/2)} \\\\&= 1.5\\,\\mathrm{\\mu m}.\\space\\space \\end{aligned}\n$$\n\n***\n\nwhere $\\ell_0$ is taken from part (b). For the engineering length scale $L=1~\\mathrm{m}$ a particle size $\\ell \\ll d \\ll L$ is **still (more-or-less!) possible**. The requirement is not a strict ratio of $10^3$ and we must be practical in our decision making. For example, the length scale of 1 m is quite rough; and there are also likely to be much larger sources of error in any computations based on the model - not least the parameters used in the computation. However, for *significantly* smaller engineering scales or higher altitudes, careful attention to the practical accuracy necessary from the computations carried out using the continuum assumption would be required.\n","children":[]}}]} \ No newline at end of file diff --git a/tests/fixtures/exports/me2_introduction/question_005_Frames_of_reference.json b/tests/fixtures/exports/me2_introduction/question_005_Frames_of_reference.json new file mode 100644 index 0000000..0293da9 --- /dev/null +++ b/tests/fixtures/exports/me2_introduction/question_005_Frames_of_reference.json @@ -0,0 +1 @@ +{"orderNumber":5,"title":"Frames of reference","skill":0.3333333333333333,"guidance":"A simple test of your basic understanding of Eulerian and Lagrangian frames of reference (content covered in Lecture 1 in ME2).","durationLowerBound":3,"durationUpperBound":5,"masterContent":"","publish":true,"displayFinalAnswer":true,"displayStructuredTutorial":true,"displayWorkedSolution":true,"displayChatbot":true,"parts":[{"orderNumber":0,"content":"What is $\\vec{\\chi}_\\mathrm{}(t)$?\n","answerContent":"The location of a particle at time, $t$.","responseAreas":[{"orderNumber":0,"contentAfter":"","preResponseText":"","postResponseText":"","inputSymbols":[],"displayInputSymbols":false,"includeInPdf":true,"saveAllowed":false,"evaluationFunctionName":"arrayEqual","livePreview":false,"gradeParams":null,"separateFeedback":true,"commonFeedbackColor":"#C4CDD5","correctFeedbackColor":"#C4CDD5","correctFeedbackPrefix":"Correct","incorrectFeedbackColor":"#ff5630","incorrectFeedbackPrefix":"Incorrect","tests":[],"cases":[],"response":{"responseInput":{"responseType":"MULTIPLE_CHOICE","answer":[false,false,true,false],"config":{"single":true,"options":["A fixed location, $x$, in space for all time, \\(t\\).","The Lagrange multiplier in time, $t$.","The location of a particle, $\\mathrm{p}$, at time, $t$.","The relation between velocity, $\\mathrm{p}$, and space, $x$, at time, $t$."],"randomise":false}}}}]},{"orderNumber":1,"content":"When does $\\vec{u}(\\vec{x},t)=\\frac{\\mathrm{d}\\vec{\\chi}_\\mathrm{p}}{\\mathrm{d}t}$?\n\n \n\nWhen ...\n","answerContent":"$\\vec{x}=\\vec{\\chi}_\\mathrm{p}$.","responseAreas":[{"orderNumber":0,"contentAfter":"","preResponseText":"","postResponseText":"","inputSymbols":[],"displayInputSymbols":false,"includeInPdf":true,"saveAllowed":false,"evaluationFunctionName":"arrayEqual","livePreview":false,"gradeParams":null,"separateFeedback":true,"commonFeedbackColor":"#C4CDD5","correctFeedbackColor":"#C4CDD5","correctFeedbackPrefix":"Correct","incorrectFeedbackColor":"#ff5630","incorrectFeedbackPrefix":"Incorrect","tests":[],"cases":[],"response":{"responseInput":{"responseType":"MULTIPLE_CHOICE","answer":[false,false,false,false,true,false,false],"config":{"single":true,"options":["$t=0$.","$\\vec{x}=0$.","$\\vec{u}=0$.","$\\vec{u}=\\vec{x}$.","$\\vec{x}=\\vec{\\chi}_{\\mathrm{P}}$.","$\\vec{u}=\\vec{\\chi}_{\\mathrm{P}}$.","$t=t_{\\mathrm{P}}$."],"randomise":false}}}}]},{"orderNumber":2,"content":"For a Eulerian velocity field $\\vec{u}(\\vec{x},t)$, which of the following would be sufficient to evaluate a particular value of the field?","answerContent":"A specific particle, $\\vec{\\chi}$, at a specific time, $t$.","responseAreas":[{"orderNumber":0,"contentAfter":"","preResponseText":"","postResponseText":"","inputSymbols":[],"displayInputSymbols":false,"includeInPdf":true,"saveAllowed":false,"evaluationFunctionName":"arrayEqual","livePreview":false,"gradeParams":null,"separateFeedback":true,"commonFeedbackColor":"#C4CDD5","correctFeedbackColor":"#C4CDD5","correctFeedbackPrefix":"Correct","incorrectFeedbackColor":"#ff5630","incorrectFeedbackPrefix":"Incorrect","tests":[],"cases":[],"response":{"responseInput":{"responseType":"MULTIPLE_CHOICE","answer":[false,false,false,false,true,false],"config":{"single":true,"options":["Pressure, $p$, temperature, $T$ and density, $\\rho$.","A Eulerian frame of reference.","A region of space, $\\vec{x}$, and a collection of particles $t$.","The continuum hypothesis.","A specific particle, $\\vec{\\chi}$, at a specific time, $t$.","A specific particle, $\\vec{\\chi}$, and a point in space $\\vec{x}$."],"randomise":false}}}}],"workedSolution":{"content":"In mathematical notation we write\n\n$$\n\\vec{u}(\\vec{x},t),\n$$\n\nmeaning that the Eulerian vector velocity $\\vec{u}$ can be evaluated for a given point in space in a Eulerian frame of reference, $\\vec{x}$, and a point in time, $t$. This option, however, was not in the list.\n\nThere is an alternative definition, which is to choose a specific particle, $\\vec{\\chi}(t)$ and a point in time, $t$, because this definition provides, implicitly, a point in space and time.\n\nIt is not sufficient to define a specific particle and a point in space, firstly because the particle may not ever pass that point in space; and secondly because if it does, we cannot guarantee in general that it should pass that point once and only once, so we have not defined a unique point in time. We awarded half-points for this response because it is also not completely wrong --- it is sufficient to evaluate some values of the Eulerian velocity field, but not necessarily all and not necessary unique values.\n","children":[]}}]} \ No newline at end of file diff --git a/tests/fixtures/exports/me2_introduction/set_Introduction.json b/tests/fixtures/exports/me2_introduction/set_Introduction.json new file mode 100644 index 0000000..d6857fc --- /dev/null +++ b/tests/fixtures/exports/me2_introduction/set_Introduction.json @@ -0,0 +1 @@ +{"name":"Introduction","description":"","isSurvey":false,"releasedAt":"2026-09-28T11:00:00.000Z","manuallyHidden":true,"finalAnswerVisibility":"OPEN_WITH_WARNINGS","workedSolutionVisibility":"OPEN_WITH_WARNINGS","structuredTutorialVisibility":"OPEN","chatbotVisibility":"OPEN"} \ No newline at end of file