in2lambda 0.3.1__py3-none-any.whl → 0.3.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- in2lambda/api/module.py +36 -5
- in2lambda/api/question.py +37 -17
- in2lambda/filters/PartsSepSol/filter.py +5 -3
- in2lambda/filters/markdown.py +4 -1
- in2lambda/json_convert/json_convert.py +1 -1
- in2lambda/json_convert/minimal_template.json +1 -1
- in2lambda/main.py +14 -5
- {in2lambda-0.3.1.dist-info → in2lambda-0.3.2.dist-info}/METADATA +5 -4
- {in2lambda-0.3.1.dist-info → in2lambda-0.3.2.dist-info}/RECORD +12 -16
- {in2lambda-0.3.1.dist-info → in2lambda-0.3.2.dist-info}/WHEEL +1 -1
- in2lambda/example.docx +0 -0
- in2lambda/filters/Table_PartSolPartSol/__init__.py +0 -4
- in2lambda/filters/Table_PartSolPartSol/example.md +0 -195
- in2lambda/filters/Table_PartSolPartSol/filter.py +0 -61
- {in2lambda-0.3.1.dist-info → in2lambda-0.3.2.dist-info}/LICENSE +0 -0
- {in2lambda-0.3.1.dist-info → in2lambda-0.3.2.dist-info}/entry_points.txt +0 -0
in2lambda/api/module.py
CHANGED
|
@@ -6,6 +6,7 @@ from typing import Union
|
|
|
6
6
|
import panflute as pf
|
|
7
7
|
|
|
8
8
|
from in2lambda.api.question import Question
|
|
9
|
+
from in2lambda.json_convert import json_convert
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
@dataclass
|
|
@@ -28,11 +29,11 @@ class Module:
|
|
|
28
29
|
Examples:
|
|
29
30
|
>>> from in2lambda.api.module import Module
|
|
30
31
|
>>> Module().current_question
|
|
31
|
-
Question(title='INVALID', parts=[], images=[],
|
|
32
|
+
Question(title='INVALID', parts=[], images=[], main_text='')
|
|
32
33
|
>>> module = Module()
|
|
33
34
|
>>> module.add_question()
|
|
34
35
|
>>> module.current_question
|
|
35
|
-
Question(title='', parts=[], images=[],
|
|
36
|
+
Question(title='', parts=[], images=[], main_text='')
|
|
36
37
|
"""
|
|
37
38
|
return (
|
|
38
39
|
self.questions[self._current_question_index]
|
|
@@ -56,7 +57,7 @@ class Module:
|
|
|
56
57
|
>>> module = Module()
|
|
57
58
|
>>> module.add_question("Some title", pf.Para(pf.Str("hello"), pf.Space, pf.Str("there")))
|
|
58
59
|
>>> module
|
|
59
|
-
Module(questions=[Question(title='Some title', parts=[], images=[],
|
|
60
|
+
Module(questions=[Question(title='Some title', parts=[], images=[], main_text='hello there')])
|
|
60
61
|
>>> module.add_question(main_text="Normal string text")
|
|
61
62
|
>>> module.questions[1].main_text
|
|
62
63
|
'Normal string text'
|
|
@@ -85,7 +86,37 @@ class Module:
|
|
|
85
86
|
>>> module.increment_current_question()
|
|
86
87
|
>>> module.current_question.add_solution("Question 2 answer")
|
|
87
88
|
>>> module.questions
|
|
88
|
-
[Question(title='Question 1', parts=[Part(text='', worked_solution='Question 1 answer')], images=[],
|
|
89
|
-
Question(title='Question 2', parts=[Part(text='', worked_solution='Question 2 answer')], images=[],
|
|
89
|
+
[Question(title='Question 1', parts=[Part(text='', worked_solution='Question 1 answer')], images=[], main_text=''),\
|
|
90
|
+
Question(title='Question 2', parts=[Part(text='', worked_solution='Question 2 answer')], images=[], main_text='')]
|
|
90
91
|
"""
|
|
91
92
|
self._current_question_index += 1
|
|
93
|
+
|
|
94
|
+
def to_json(self, output_dir: str) -> None:
|
|
95
|
+
"""Turns this module into Lambda Feedback JSON/ZIP files.
|
|
96
|
+
|
|
97
|
+
WARNING: This will overwrite any existing files in the directory.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
output_dir: Where to output the final Lambda Feedback JSON/ZIP files.
|
|
101
|
+
|
|
102
|
+
Examples:
|
|
103
|
+
>>> import tempfile
|
|
104
|
+
>>> import os
|
|
105
|
+
>>> import json
|
|
106
|
+
>>> # Create a module with two questions
|
|
107
|
+
>>> module = Module()
|
|
108
|
+
>>> module.add_question("Question 1")
|
|
109
|
+
>>> module.add_question("Question 2")
|
|
110
|
+
>>> with tempfile.TemporaryDirectory() as temp_dir:
|
|
111
|
+
... # Write the JSON files to the temporary directory
|
|
112
|
+
... module.to_json(temp_dir)
|
|
113
|
+
... # Check the contents of the directory
|
|
114
|
+
... sorted(os.listdir(temp_dir))
|
|
115
|
+
... # Check the title of the first question
|
|
116
|
+
... with open(f"{temp_dir}/question_1/question_1.json") as file:
|
|
117
|
+
... print(f"Question 1's title: {json.load(file)['title']}")
|
|
118
|
+
['question_1', 'question_1.zip', 'question_2', 'question_2.zip']
|
|
119
|
+
Question 1's title: Question 1
|
|
120
|
+
|
|
121
|
+
"""
|
|
122
|
+
json_convert.main(self.questions, output_dir)
|
in2lambda/api/question.py
CHANGED
|
@@ -16,8 +16,8 @@ class Question:
|
|
|
16
16
|
|
|
17
17
|
Examples:
|
|
18
18
|
>>> from in2lambda.api.question import Question
|
|
19
|
-
>>> Question(title="Some title",
|
|
20
|
-
Question(title='Some title', parts=[], images=[],
|
|
19
|
+
>>> Question(title="Some title", main_text="Some text")
|
|
20
|
+
Question(title='Some title', parts=[], images=[], main_text='Some text')
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
23
|
title: str = ""
|
|
@@ -25,7 +25,11 @@ class Question:
|
|
|
25
25
|
parts: list[Part] = field(default_factory=list)
|
|
26
26
|
images: list[str] = field(default_factory=list)
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
# Use getter/setter methods for main_text without exposing private attribute.
|
|
29
|
+
# See https://stackoverflow.com/a/61480946
|
|
30
|
+
main_text: str = ""
|
|
31
|
+
_main_text: str = field(init=False, repr=False, default="")
|
|
32
|
+
|
|
29
33
|
_last_part: dict[str, int] = field(
|
|
30
34
|
default_factory=lambda: {"solution": 0, "text": 0}, repr=False
|
|
31
35
|
)
|
|
@@ -34,15 +38,10 @@ class Question:
|
|
|
34
38
|
|
|
35
39
|
@property
|
|
36
40
|
def main_text(self) -> str:
|
|
37
|
-
"""Main top-level question text.
|
|
38
|
-
return self._main_text
|
|
41
|
+
r"""Main top-level question text.
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
r"""Appends to the top-level main text, which starts off as an empty string.
|
|
43
|
-
|
|
44
|
-
Args:
|
|
45
|
-
value: A panflute element or string denoting what to append to the main text.
|
|
43
|
+
Setting the attribute multiple times appends to the current value with a newline.
|
|
44
|
+
This allows question text to be dynamically appended.
|
|
46
45
|
|
|
47
46
|
Examples:
|
|
48
47
|
>>> from in2lambda.api.question import Question
|
|
@@ -52,7 +51,28 @@ class Question:
|
|
|
52
51
|
>>> question.main_text
|
|
53
52
|
'hello\nthere'
|
|
54
53
|
"""
|
|
55
|
-
|
|
54
|
+
return self._main_text
|
|
55
|
+
|
|
56
|
+
@main_text.setter
|
|
57
|
+
def main_text(self, value: Union[pf.Element, str, property]) -> None:
|
|
58
|
+
r"""Appends to the top-level main text, which starts off as an empty string.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
value: A panflute element or string denoting what to append to the main text.
|
|
62
|
+
|
|
63
|
+
See example in main_text property.
|
|
64
|
+
"""
|
|
65
|
+
# Converts the inputted value into a string, stored in text_value
|
|
66
|
+
match value:
|
|
67
|
+
case str():
|
|
68
|
+
text_value = value
|
|
69
|
+
case property():
|
|
70
|
+
# Use default value when no value set at initialisation.
|
|
71
|
+
# See https://stackoverflow.com/a/61480946
|
|
72
|
+
text_value = self.main_text
|
|
73
|
+
case pf.Element():
|
|
74
|
+
text_value = pf.stringify(value, False)
|
|
75
|
+
|
|
56
76
|
if self._main_text:
|
|
57
77
|
self._main_text += "\n"
|
|
58
78
|
self._main_text += text_value
|
|
@@ -69,7 +89,7 @@ class Question:
|
|
|
69
89
|
>>> question.add_part_text("part a")
|
|
70
90
|
>>> question.add_solution("part a solution")
|
|
71
91
|
>>> question
|
|
72
|
-
Question(title='', parts=[Part(text='part a', worked_solution='part a solution')], images=[],
|
|
92
|
+
Question(title='', parts=[Part(text='part a', worked_solution='part a solution')], images=[], main_text='')
|
|
73
93
|
>>> question.add_part_text("part b")
|
|
74
94
|
>>> question.add_part_text("part c")
|
|
75
95
|
>>> question.add_solution("Solution for b")
|
|
@@ -77,12 +97,12 @@ class Question:
|
|
|
77
97
|
>>> question
|
|
78
98
|
Question(title='', parts=[Part(text='part a', worked_solution='part a solution'), \
|
|
79
99
|
Part(text='part b', worked_solution='Solution for b'), \
|
|
80
|
-
Part(text='part c', worked_solution='Solution for b')], images=[],
|
|
100
|
+
Part(text='part c', worked_solution='Solution for b')], images=[], main_text='')
|
|
81
101
|
>>> question.add_solution("We now have a solution for c!")
|
|
82
102
|
>>> question
|
|
83
103
|
Question(title='', parts=[Part(text='part a', worked_solution='part a solution'), \
|
|
84
104
|
Part(text='part b', worked_solution='Solution for b'), \
|
|
85
|
-
Part(text='part c', worked_solution='We now have a solution for c!')], images=[],
|
|
105
|
+
Part(text='part c', worked_solution='We now have a solution for c!')], images=[], main_text='')
|
|
86
106
|
"""
|
|
87
107
|
elem_text = elem if isinstance(elem, str) else pf.stringify(elem)
|
|
88
108
|
|
|
@@ -111,13 +131,13 @@ Part(text='part c', worked_solution='We now have a solution for c!')], images=[]
|
|
|
111
131
|
>>> question.add_part_text("part a")
|
|
112
132
|
>>> question.add_solution("part a solution")
|
|
113
133
|
>>> question
|
|
114
|
-
Question(title='', parts=[Part(text='part a', worked_solution='part a solution')], images=[],
|
|
134
|
+
Question(title='', parts=[Part(text='part a', worked_solution='part a solution')], images=[], main_text='')
|
|
115
135
|
>>> # Supports adding the answer first.
|
|
116
136
|
>>> question.add_solution("part b solution")
|
|
117
137
|
>>> question.add_part_text("part b")
|
|
118
138
|
>>> question
|
|
119
139
|
Question(title='', parts=[Part(text='part a', worked_solution='part a solution'), \
|
|
120
|
-
Part(text='part b', worked_solution='part b solution')], images=[],
|
|
140
|
+
Part(text='part b', worked_solution='part b solution')], images=[], main_text='')
|
|
121
141
|
"""
|
|
122
142
|
elem_text = elem if isinstance(elem, str) else pf.stringify(elem)
|
|
123
143
|
|
|
@@ -72,7 +72,9 @@ def pandoc_filter(
|
|
|
72
72
|
# Add each part solution/text
|
|
73
73
|
# For the solution, prepend any top level answer text to each part answer
|
|
74
74
|
for part in lettered_parts:
|
|
75
|
-
|
|
76
|
-
spaced_blurb + part
|
|
77
|
-
|
|
75
|
+
(
|
|
76
|
+
module.current_question.add_solution(spaced_blurb + part)
|
|
77
|
+
if parsing_answers
|
|
78
|
+
else module.current_question.add_part_text(part)
|
|
79
|
+
)
|
|
78
80
|
return None
|
in2lambda/filters/markdown.py
CHANGED
|
@@ -120,7 +120,10 @@ def filter(
|
|
|
120
120
|
[pf.Element, pf.elements.Doc, Module, bool],
|
|
121
121
|
Optional[pf.Str],
|
|
122
122
|
]
|
|
123
|
-
) -> Callable[
|
|
123
|
+
) -> Callable[
|
|
124
|
+
[pf.Element, pf.elements.Doc, Module, str, bool],
|
|
125
|
+
Optional[pf.Str],
|
|
126
|
+
]:
|
|
124
127
|
"""Python decorator to make generic LaTeX elements markdown readable.
|
|
125
128
|
|
|
126
129
|
As an example, part of the process involves putting dollar signs around maths
|
in2lambda/main.py
CHANGED
|
@@ -9,7 +9,6 @@ import rich_click as click
|
|
|
9
9
|
|
|
10
10
|
import in2lambda.filters
|
|
11
11
|
from in2lambda.api.module import Module
|
|
12
|
-
from in2lambda.json_convert import json_convert
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
def file_type(file: str) -> str:
|
|
@@ -40,7 +39,17 @@ def file_type(file: str) -> str:
|
|
|
40
39
|
match (extension := file.split(".")[-1].lower()):
|
|
41
40
|
case "tex" | "latex" | "ltx":
|
|
42
41
|
return "latex"
|
|
43
|
-
case
|
|
42
|
+
case (
|
|
43
|
+
"md"
|
|
44
|
+
| "rmd"
|
|
45
|
+
| "markdown"
|
|
46
|
+
| "mdown"
|
|
47
|
+
| "mdwn"
|
|
48
|
+
| "mkd"
|
|
49
|
+
| "mkdn"
|
|
50
|
+
| "text"
|
|
51
|
+
| "txt"
|
|
52
|
+
):
|
|
44
53
|
return "markdown"
|
|
45
54
|
case "docx":
|
|
46
55
|
return "docx" # Pandoc doesn't seem to support doc
|
|
@@ -71,9 +80,9 @@ def runner(
|
|
|
71
80
|
>>> from in2lambda.main import runner
|
|
72
81
|
>>> # Retrieve an example TeX file and run the given filter.
|
|
73
82
|
>>> runner(f"{os.path.dirname(in2lambda.__file__)}/filters/PartsSepSol/example.tex", "PartsSepSol") # doctest: +ELLIPSIS
|
|
74
|
-
Module(questions=[Question(title='', parts=[Part(text=..., worked_solution=''), ...], images=[],
|
|
83
|
+
Module(questions=[Question(title='', parts=[Part(text=..., worked_solution=''), ...], images=[], main_text='This is a sample question\n\n'), ...])
|
|
75
84
|
>>> runner(f"{os.path.dirname(in2lambda.__file__)}/filters/PartsOneSol/example.tex", "PartsOneSol") # doctest: +ELLIPSIS
|
|
76
|
-
Module(questions=[Question(title='', parts=[Part(text='This is part (a)\n\n', worked_solution=''), ...], images=[],
|
|
85
|
+
Module(questions=[Question(title='', parts=[Part(text='This is part (a)\n\n', worked_solution=''), ...], images=[], main_text='Here is some preliminary question information that might be useful.'), ...)
|
|
77
86
|
"""
|
|
78
87
|
# The list of questions for Lambda Feedback as a Python API.
|
|
79
88
|
module = Module()
|
|
@@ -112,7 +121,7 @@ def runner(
|
|
|
112
121
|
|
|
113
122
|
# Read the Python API format and convert to JSON.
|
|
114
123
|
if output_dir is not None:
|
|
115
|
-
|
|
124
|
+
module.to_json(output_dir)
|
|
116
125
|
|
|
117
126
|
return module
|
|
118
127
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: in2lambda
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Converts content ready for import into Lambda Feedback
|
|
5
5
|
Home-page: https://lambda-feedback.github.io/in2lambda
|
|
6
6
|
License: MIT
|
|
@@ -12,11 +12,12 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
16
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
17
|
Classifier: Typing :: Typed
|
|
17
|
-
Requires-Dist: beartype (>=0.
|
|
18
|
-
Requires-Dist: panflute (>=2.3.
|
|
19
|
-
Requires-Dist: rich-click (>=1.7.
|
|
18
|
+
Requires-Dist: beartype (>=0.17.2,<0.18.0)
|
|
19
|
+
Requires-Dist: panflute (>=2.3.1,<3.0.0)
|
|
20
|
+
Requires-Dist: rich-click (>=1.7.4,<2.0.0)
|
|
20
21
|
Project-URL: Bug Tracker, https://github.com/lambda-feedback/in2lambda/issues
|
|
21
22
|
Project-URL: Documentation, https://lambda-feedback.github.io/in2lambda
|
|
22
23
|
Project-URL: Repository, https://github.com/lambda-feedback/in2lambda
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
in2lambda/__init__.py,sha256=VvbVGkrakfqTIqnYUuv95_LFxitkMODRYr161R9128U,492
|
|
2
2
|
in2lambda/api/__init__.py,sha256=uh1WA1JIIYmjaWXms3JR5LOlnizv-ozW4ijBHQxi9QA,103
|
|
3
|
-
in2lambda/api/module.py,sha256=
|
|
3
|
+
in2lambda/api/module.py,sha256=YDV2NWejxg3duEzVjn6er05OiCGBihI7fUDJP16RuD0,5046
|
|
4
4
|
in2lambda/api/part.py,sha256=Y-W0sd5mJQifA8V8nZNTYk_HPhxhRQq5mUCdlYKioXw,204
|
|
5
|
-
in2lambda/api/question.py,sha256=
|
|
6
|
-
in2lambda/example.docx,sha256=EtGDjV3343ev_WKrnkKN5cPG1lGGfMtKZx5k6jyOAvA,32824
|
|
5
|
+
in2lambda/api/question.py,sha256=is-Bmx85GFAV7Jf8mblP2ZtkDgfbRcVbMhh9Tmy2hmk,6173
|
|
7
6
|
in2lambda/example_questions.tex,sha256=kvcuUUoQXTJYqrAlUMfibzGsL9qFgqbKS57JIg1YhkA,9491
|
|
8
7
|
in2lambda/example_solutions.tex,sha256=0idJQV9Q8VhMO_dB5RYzYkZzyEMSA594sqnPdl4wlLA,22164
|
|
9
8
|
in2lambda/filters/PartPartSolSol/__init__.py,sha256=YJCnCoGJfXt7jrMdgcsEfkI7Su9WK-VOvUwwefQ8zog,124
|
|
@@ -17,23 +16,20 @@ in2lambda/filters/PartsOneSol/example.tex,sha256=d45J2goEL_X-otuwtwJwXId1KHTW2sG
|
|
|
17
16
|
in2lambda/filters/PartsOneSol/filter.py,sha256=DLj7DcDt1Aru2B4Tb5rljOFKZ4sXB8UUc4Yd3knnJow,2017
|
|
18
17
|
in2lambda/filters/PartsSepSol/__init__.py,sha256=yAIUC3oJVob1R7Rrvn0sXGpK_-pXfF46DeJ9vaXSNfQ,121
|
|
19
18
|
in2lambda/filters/PartsSepSol/example.tex,sha256=w7mJIcWCqKzJE_sJG4bg0J-V9kXSfe6doKWXgTd1nF8,687
|
|
20
|
-
in2lambda/filters/PartsSepSol/filter.py,sha256=
|
|
21
|
-
in2lambda/filters/Table_PartSolPartSol/__init__.py,sha256=Rf1LgSoGNkkgVN3yt6dbT_UhZs5ngMAPLpOFx2NwCBo,124
|
|
22
|
-
in2lambda/filters/Table_PartSolPartSol/example.md,sha256=1lMw3q_O765kRroohAWnhK_8h4KMKo3Qm7_gYSxDX7A,9213
|
|
23
|
-
in2lambda/filters/Table_PartSolPartSol/filter.py,sha256=AUGWVI4qaQBCbDSXlUgoHKA0WKgJ-7oQjvVTrZHGTEc,2260
|
|
19
|
+
in2lambda/filters/PartsSepSol/filter.py,sha256=9cV6HhSqOQGTk5bIS36pgBbB-5UWO3mPI2s8l9ZsNeE,3206
|
|
24
20
|
in2lambda/filters/__init__.py,sha256=tla_1d85db2MAT-fgc5sNoScuYZJeTgKedzFn3NXT2c,69
|
|
25
|
-
in2lambda/filters/markdown.py,sha256=
|
|
21
|
+
in2lambda/filters/markdown.py,sha256=FhbGHziVCHirhssCpMnSkyC0alMsOIxnInxvLMdaNek,7153
|
|
26
22
|
in2lambda/json_convert/__init__.py,sha256=2X3SLn6H449zXFprtZZU7M20elsOJ09mQr7EDnv04ow,87
|
|
27
|
-
in2lambda/json_convert/json_convert.py,sha256=
|
|
28
|
-
in2lambda/json_convert/minimal_template.json,sha256=
|
|
23
|
+
in2lambda/json_convert/json_convert.py,sha256=VPigakcUYvZCm2PPRm0umrA0BIvEOFNfwl-NLfcr4lM,3625
|
|
24
|
+
in2lambda/json_convert/minimal_template.json,sha256=ctwpbvOqIs_okToSCRkRB3z5CRn1GNbrUegu6PuLngM,551
|
|
29
25
|
in2lambda/katex_convert/__init__.py,sha256=D0X21-NQXNrWwu_klZeCaQaqtV9vHfFv1PlrtuVAHlI,96
|
|
30
26
|
in2lambda/katex_convert/delete_list.txt,sha256=Ywx8ltUbrvSxGaQVoTSXfXAe4FfPSCuRchkSCICYjHU,1753
|
|
31
27
|
in2lambda/katex_convert/katex_convert.py,sha256=3UUw84432lOBnPLJwAw68MMyFPrD6ijxyYR-qVhJhnw,4909
|
|
32
28
|
in2lambda/katex_convert/replace_list.txt,sha256=y5ciG4orj64eqEKsOVaQ95Zx7Xx0y4Awa4JIS27HVSw,611
|
|
33
|
-
in2lambda/main.py,sha256=
|
|
29
|
+
in2lambda/main.py,sha256=RSoHtn9e1y34xHxScwjMUshrP5RAuGJayqX_WXveajA,6006
|
|
34
30
|
in2lambda/py.typed,sha256=gN7aphE6U0Jj-OffDD7hw1OkRs9gg6OPOrVpN5eAnCA,56
|
|
35
|
-
in2lambda-0.3.
|
|
36
|
-
in2lambda-0.3.
|
|
37
|
-
in2lambda-0.3.
|
|
38
|
-
in2lambda-0.3.
|
|
39
|
-
in2lambda-0.3.
|
|
31
|
+
in2lambda-0.3.2.dist-info/LICENSE,sha256=vEyoprnh_ic_ZQ-woDohxEIE8GJOyXqbYZ-5cH42FG4,1072
|
|
32
|
+
in2lambda-0.3.2.dist-info/METADATA,sha256=7DjyXejaoAtbgGr2kItJ-1I_5xHiNv_y8BKrOcODtCE,1833
|
|
33
|
+
in2lambda-0.3.2.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
34
|
+
in2lambda-0.3.2.dist-info/entry_points.txt,sha256=xhkZ_lmsx7SgdhjJC-DvkFFqu-Ff-wD4Poir55bdUSM,48
|
|
35
|
+
in2lambda-0.3.2.dist-info/RECORD,,
|
in2lambda/example.docx
DELETED
|
Binary file
|
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
+-----+----------------------------------------------------------------+
|
|
2
|
-
| Q | A Frahm\'s tachometer for measuring the rotational speed of |
|
|
3
|
-
| 1.1 | machinery consists of many small cantilever spring steel |
|
|
4
|
-
| | strips, each being rigidly fastened to the frame of the |
|
|
5
|
-
| | instrument at one end and having a mass at the other (free) |
|
|
6
|
-
| | end. A strip will vibrate (and so give a visual indication) |
|
|
7
|
-
| | when the speed of the machine is equal to the strip\'s natural |
|
|
8
|
-
| | frequency. One such strip is 1 mm thick, 7 mm wide and 50 mm |
|
|
9
|
-
| | long. Calculate the mass required at the free end so that the |
|
|
10
|
-
| | natural frequency will correspond to 1800 rev/min. |
|
|
11
|
-
| | |
|
|
12
|
-
| | **(0.082 kg)** |
|
|
13
|
-
+=====+================================================================+
|
|
14
|
-
| | Hint: Obtain the cantilever stiffness from data book. |
|
|
15
|
-
+-----+----------------------------------------------------------------+
|
|
16
|
-
| | |
|
|
17
|
-
+-----+----------------------------------------------------------------+
|
|
18
|
-
| | {width="3.9776432633420824in" |
|
|
19
|
-
| | height="2.075301837270341in"} |
|
|
20
|
-
| | |
|
|
21
|
-
| | a\) Cantilever steel strip and b) equivalent mass and spring |
|
|
22
|
-
| | system |
|
|
23
|
-
| | |
|
|
24
|
-
| | Calculate the effective stiffness of the beam by considering |
|
|
25
|
-
| | the standard formula of deflection (Engineering Data and |
|
|
26
|
-
| | Formulae Handbook). |
|
|
27
|
-
| | |
|
|
28
|
-
| | ------------------------- |
|
|
29
|
-
| | -------------------------------------------------------------- |
|
|
30
|
-
| | -------------------------------------------------------------- |
|
|
31
|
-
| | |
|
|
32
|
-
| | $$\mathbf{Stiffness}\mathbf{\ }\left( \mathbf{k} \rig |
|
|
33
|
-
| | ht)\mathbf{=}\frac{\mathbf{Force}}{\mathbf{Displacement}}$$ |
|
|
34
|
-
| | ------------------------- |
|
|
35
|
-
| | ------------------------------------------------------------- |
|
|
36
|
-
| | ----------------------------------------------------- -------- |
|
|
37
|
-
| | |
|
|
38
|
-
| | $\delta = \frac{FL^{3}}{3EI}$ where $I = \frac{bd^{3} |
|
|
39
|
-
| | }{12}$ (from Data and Formulae Handbook) |
|
|
40
|
-
| | |
|
|
41
|
-
| | $$\mathbf{\theref |
|
|
42
|
-
| | ore}$$ $$\ \frac{F}{\delta} = k = \frac{Ebd^{3}}{4L^{3}}$$ |
|
|
43
|
-
| | |
|
|
44
|
-
| | ------------------------- |
|
|
45
|
-
| | -------------------------------------------------------------- |
|
|
46
|
-
| | -------------------------------------------------------------- |
|
|
47
|
-
| | |
|
|
48
|
-
| | The natural frequency is given by, |
|
|
49
|
-
| | |
|
|
50
|
-
| | ------------------------------------ |
|
|
51
|
-
| | -------------------------------------------------------------- |
|
|
52
|
-
| | $$\mathbf{\omega}_{ |
|
|
53
|
-
| | \mathbf{n}}\mathbf{=}\sqrt{\frac{\mathbf{k}}{\mathbf{m}}}$$ |
|
|
54
|
-
| | -------- --------------------------- |
|
|
55
|
-
| | ----------------------------------------------------- -------- |
|
|
56
|
-
| | |
|
|
57
|
-
| | ------------------------------------ |
|
|
58
|
-
| | -------------------------------------------------------------- |
|
|
59
|
-
| | |
|
|
60
|
-
| | so, |
|
|
61
|
-
| | |
|
|
62
|
-
| | ------------------------------------------------------ |
|
|
63
|
-
| | -------------------------------------------------------------- |
|
|
64
|
-
| | -------------------------------------------------------------- |
|
|
65
|
-
| | $$\mathbf{\omega}_{\ |
|
|
66
|
-
| | mathbf{n}}^{\mathbf{2}}\mathbf{=}\frac{\mathbf{Eb}\mathbf{d}^{ |
|
|
67
|
-
| | \mathbf{3}}}{\mathbf{4}\mathbf{L}^{\mathbf{3}}\mathbf{m}}$$ |
|
|
68
|
-
| | ------------------------- ---------------------------- |
|
|
69
|
-
| | -------------------------------------------------------------- |
|
|
70
|
-
| | ----------------------------------------------------- -------- |
|
|
71
|
-
| | $$\mathbf{\therefore}$$ $$m = \frac{Edb^{3}} |
|
|
72
|
-
| | {4L^{3}\omega_{n}^{2}}$$ |
|
|
73
|
-
| | |
|
|
74
|
-
| | |
|
|
75
|
-
| | ------------------------------------------------------ |
|
|
76
|
-
| | -------------------------------------------------------------- |
|
|
77
|
-
| | -------------------------------------------------------------- |
|
|
78
|
-
| | |
|
|
79
|
-
| | Remember to convert from rpm to rad/s: ($\omega_{n}$ = |
|
|
80
|
-
| | 188.5 rad/s) |
|
|
81
|
-
| | |
|
|
82
|
-
| | ------------------- |
|
|
83
|
-
| | -------------------------------------------------------------- |
|
|
84
|
-
| | -------------------------------------------------------------- |
|
|
85
|
-
| | -------------------------------------------------------------- |
|
|
86
|
-
| | -------------------------------------------------------------- |
|
|
87
|
-
| | -------------------------------------------------------------- |
|
|
88
|
-
| | $$\mathbf{\ |
|
|
89
|
-
| | therefore}$$ $$\mathbf{m =}\frac{\mathbf{207 \times 1}\mathb |
|
|
90
|
-
| | f{0}^{\mathbf{9}}\mathbf{\times 7 \times}\mathbf{10}^{\mathbf{ |
|
|
91
|
-
| | - 3}}\mathbf{\times}\left( \mathbf{1 \times 1}\mathbf{0}^{\mat |
|
|
92
|
-
| | hbf{- 3}} \right)^{\mathbf{3}}}{\mathbf{4 \times 0.0}\mathbf{5 |
|
|
93
|
-
| | }^{\mathbf{3}}\mathbf{\times}\mathbf{188.5}^{\mathbf{2}}}$$ |
|
|
94
|
-
| | ------------------- |
|
|
95
|
-
| | ------ ------------------------------------------------------- |
|
|
96
|
-
| | -------------------------------------------------------------- |
|
|
97
|
-
| | -------------------------------------------------------------- |
|
|
98
|
-
| | -------------------------------------------------------------- |
|
|
99
|
-
| | ----------------------------------------------------- -------- |
|
|
100
|
-
| | $$\mathbf{\ |
|
|
101
|
-
| | therefore}$$ $$m\mathbf{=}\boxed{\mathbf{0.082\ kg}}$$ |
|
|
102
|
-
| | |
|
|
103
|
-
| | |
|
|
104
|
-
| | |
|
|
105
|
-
| | |
|
|
106
|
-
| | |
|
|
107
|
-
| | ------------------- |
|
|
108
|
-
| | -------------------------------------------------------------- |
|
|
109
|
-
| | -------------------------------------------------------------- |
|
|
110
|
-
| | -------------------------------------------------------------- |
|
|
111
|
-
| | -------------------------------------------------------------- |
|
|
112
|
-
| | -------------------------------------------------------------- |
|
|
113
|
-
+-----+----------------------------------------------------------------+
|
|
114
|
-
| | |
|
|
115
|
-
+-----+----------------------------------------------------------------+
|
|
116
|
-
| Q | A circular diaphragm, fixed all round its edge, has a natural |
|
|
117
|
-
| 1.2 | frequency of 5000 Hz. When an additional mass of 0.5 kg is |
|
|
118
|
-
| | attached to the centre of the diaphragm, the natural frequency |
|
|
119
|
-
| | is reduced to 4900 Hz. What are the effective mass and |
|
|
120
|
-
| | effective stiffness of the diaphragm, both referred to the |
|
|
121
|
-
| | central point |
|
|
122
|
-
| | |
|
|
123
|
-
| | **(12.14 kg,12.0 GN/m)** |
|
|
124
|
-
+-----+----------------------------------------------------------------+
|
|
125
|
-
| | Hint: Write the natural frequency formula twice, considering |
|
|
126
|
-
| | the cases of with and without added mass. |
|
|
127
|
-
+-----+----------------------------------------------------------------+
|
|
128
|
-
| | The diaphragm has effective mass, $m$ and effective stiffness, |
|
|
129
|
-
| | $k$ which are to be determined. The original natural frequency |
|
|
130
|
-
| | is simply given by $\sqrt{\frac{k}{m}}$ . When a 0.5 kg mass |
|
|
131
|
-
| | is added to the centre of the diaphragm, which is the point of |
|
|
132
|
-
| | maximum motion, the effective mass is increased by 0.5 kg. |
|
|
133
|
-
| | |
|
|
134
|
-
| | {width="2.2402777777777776in" |
|
|
135
|
-
| | height="1.4996205161854768in"} |
|
|
136
|
-
| | |
|
|
137
|
-
| | > Therefore, |
|
|
138
|
-
| | |
|
|
139
|
-
| | ---- |
|
|
140
|
-
| | -------------------------------------------------------------- |
|
|
141
|
-
| | |
|
|
142
|
-
| | $$\omega_{n1} = \sqrt{\frac{k}{m_{1}}}$$ \(1\) |
|
|
143
|
-
| | ---- |
|
|
144
|
-
| | ---- ------------------------------------------------ -------- |
|
|
145
|
-
| | |
|
|
146
|
-
| | $$\omega_{n2} = \sqrt{\frac{k}{m_{1} + 0.5}}$$ \(2\) |
|
|
147
|
-
| | |
|
|
148
|
-
| | ---- |
|
|
149
|
-
| | -------------------------------------------------------------- |
|
|
150
|
-
| | |
|
|
151
|
-
| | The two equations are used to solve for two unknowns, |
|
|
152
|
-
| | |
|
|
153
|
-
| | From equ (1), |
|
|
154
|
-
| | |
|
|
155
|
-
| | ------------------------------------------------------------ |
|
|
156
|
-
| | $$k = \omega_{n1}^{2}m_{1}$$ \(3\) |
|
|
157
|
-
| | -------- ------------------------------------------ -------- |
|
|
158
|
-
| | |
|
|
159
|
-
| | ------------------------------------------------------------ |
|
|
160
|
-
| | |
|
|
161
|
-
| | Substitute equ (3) into equ (2), |
|
|
162
|
-
| | |
|
|
163
|
-
| | ----------------------------------------------- |
|
|
164
|
-
| | -------------------------------------------------------------- |
|
|
165
|
-
| | $$\omega_{n2}^{2} = \frac{\ome |
|
|
166
|
-
| | ga_{n1}^{2}m_{1}}{m_{1} + 0.5}$$ |
|
|
167
|
-
| | -------- -------------------------------------- |
|
|
168
|
-
| | ----------------------------------------------------- -------- |
|
|
169
|
-
| | $$m_{1}\left( \omega_{n1}^{2} |
|
|
170
|
-
| | - \omega_{n2}^{2} \right) + \frac{\omega_{n2}^{2}}{2} = 0$$ |
|
|
171
|
-
| | |
|
|
172
|
-
| | ----------------------------------------------- |
|
|
173
|
-
| | -------------------------------------------------------------- |
|
|
174
|
-
| | |
|
|
175
|
-
| | > Remember to convert Hz to rad/s. |
|
|
176
|
-
| | |
|
|
177
|
-
| | +-------+-----------------------------------------+-------+ |
|
|
178
|
-
| | | | $$m_{1} | | |
|
|
179
|
-
| | | | = \frac{\omega_{n2}^{2}}{2\left( \omeg | | |
|
|
180
|
-
| | | | a_{n1}^{2} - \omega_{n2}^{2} \right)}$$ | | |
|
|
181
|
-
| | | | | | |
|
|
182
|
-
| | | | $$\mat | | |
|
|
183
|
-
| | | | hbf{\ \ \ \ \ \ \ =}\frac{(4900 \times | | |
|
|
184
|
-
| | | | 2\pi)^{2}}{2\left( (5000 \times 2\pi)^ | | |
|
|
185
|
-
| | | | {2} - (4900 \times 2\pi)^{2} \right)}$$ | | |
|
|
186
|
-
| | | | | | |
|
|
187
|
-
| | | | $$\mathbf{\ \ \ | | |
|
|
188
|
-
| | | | \ \ \ \ =}\boxed{\mathbf{12.13\ kg}}$$ | | |
|
|
189
|
-
| | +=======+=========================================+=======+ |
|
|
190
|
-
| | +-------+-----------------------------------------+-------+ |
|
|
191
|
-
| | |
|
|
192
|
-
| | > And from equ (3), $k = \boxed{\mathbf{12.0\ GN/m}}$ |
|
|
193
|
-
+-----+----------------------------------------------------------------+
|
|
194
|
-
| | |
|
|
195
|
-
+-----+----------------------------------------------------------------+
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
"""A solution appears after each individual part."""
|
|
2
|
-
|
|
3
|
-
from collections import deque
|
|
4
|
-
from typing import Optional
|
|
5
|
-
|
|
6
|
-
import panflute as pf
|
|
7
|
-
|
|
8
|
-
from in2lambda.api.module import Module
|
|
9
|
-
from in2lambda.filters.markdown import filter
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@filter
|
|
13
|
-
def pandoc_filter(
|
|
14
|
-
elem: pf.Element,
|
|
15
|
-
doc: pf.elements.Doc,
|
|
16
|
-
module: Module,
|
|
17
|
-
parsing_answers: bool,
|
|
18
|
-
) -> Optional[pf.Str]:
|
|
19
|
-
"""A Pandoc filter that parses and translates various TeX elements.
|
|
20
|
-
|
|
21
|
-
Args:
|
|
22
|
-
elem: The current TeX element being processed. This could be a paragraph,
|
|
23
|
-
ordered list, etc.
|
|
24
|
-
doc: A Pandoc document container - essentially the Pandoc AST.
|
|
25
|
-
module: The Python API that is used to store the result after processing
|
|
26
|
-
the TeX file.
|
|
27
|
-
parsing_answers: Whether an answers-only document is currently being parsed.
|
|
28
|
-
|
|
29
|
-
Returns:
|
|
30
|
-
Converted TeX elements for the AST where required
|
|
31
|
-
e.g. replaces math equations so that they are surrounded by $.
|
|
32
|
-
"""
|
|
33
|
-
# Question text (ListItem -> List -> Doc)
|
|
34
|
-
if isinstance(elem, pf.Table):
|
|
35
|
-
match type(elem):
|
|
36
|
-
case pf.Para:
|
|
37
|
-
pandoc_filter.solutions = deque()
|
|
38
|
-
if hasattr(pandoc_filter, "question"):
|
|
39
|
-
pandoc_filter.question.append(pf.stringify(elem))
|
|
40
|
-
else:
|
|
41
|
-
pandoc_filter.question = [pf.stringify(elem)]
|
|
42
|
-
case pf.OrderedList:
|
|
43
|
-
for listItem in elem.content:
|
|
44
|
-
part = [
|
|
45
|
-
pf.stringify(item)
|
|
46
|
-
for item in listItem.content
|
|
47
|
-
if not isinstance(item, pf.Div)
|
|
48
|
-
]
|
|
49
|
-
module.current_question.add_part_text("\n".join(part))
|
|
50
|
-
module.current_question.add_solution(
|
|
51
|
-
pandoc_filter.solutions.popleft()
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
if isinstance(elem, pf.Div):
|
|
55
|
-
pandoc_filter.solutions.append(pf.stringify(elem))
|
|
56
|
-
if pandoc_filter.question:
|
|
57
|
-
module.add_question(main_text="\n".join(pandoc_filter.question))
|
|
58
|
-
module.current_question.add_solution(pf.stringify(elem))
|
|
59
|
-
module.current_question._last_part["solution"] -= 1
|
|
60
|
-
pandoc_filter.question = []
|
|
61
|
-
return None
|
|
File without changes
|
|
File without changes
|