osl-edu-math 0.2.1__tar.gz

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.
Files changed (146) hide show
  1. osl_edu_math-0.2.1/LICENSE +28 -0
  2. osl_edu_math-0.2.1/PKG-INFO +86 -0
  3. osl_edu_math-0.2.1/README.md +47 -0
  4. osl_edu_math-0.2.1/pyproject.toml +119 -0
  5. osl_edu_math-0.2.1/src/edumath/__init__.py +5 -0
  6. osl_edu_math-0.2.1/src/edumath/algebra/__init__.py +34 -0
  7. osl_edu_math-0.2.1/src/edumath/algebra/concepts.py +131 -0
  8. osl_edu_math-0.2.1/src/edumath/algebra/exercises.py +81 -0
  9. osl_edu_math-0.2.1/src/edumath/algebra/plots.py +76 -0
  10. osl_edu_math-0.2.1/src/edumath/algebra/quizes.py +430 -0
  11. osl_edu_math-0.2.1/src/edumath/algebra/quizzes.py +3 -0
  12. osl_edu_math-0.2.1/src/edumath/algebra/validators.py +25 -0
  13. osl_edu_math-0.2.1/src/edumath/analysis/__init__.py +0 -0
  14. osl_edu_math-0.2.1/src/edumath/analysis/concepts.py +0 -0
  15. osl_edu_math-0.2.1/src/edumath/analysis/exercises.py +0 -0
  16. osl_edu_math-0.2.1/src/edumath/analysis/plots.py +0 -0
  17. osl_edu_math-0.2.1/src/edumath/analysis/quizzes.py +0 -0
  18. osl_edu_math-0.2.1/src/edumath/analysis/validators.py +0 -0
  19. osl_edu_math-0.2.1/src/edumath/arithmetic/__init__.py +0 -0
  20. osl_edu_math-0.2.1/src/edumath/arithmetic/concepts.py +0 -0
  21. osl_edu_math-0.2.1/src/edumath/arithmetic/exercises.py +0 -0
  22. osl_edu_math-0.2.1/src/edumath/arithmetic/plots.py +0 -0
  23. osl_edu_math-0.2.1/src/edumath/arithmetic/quizzes.py +0 -0
  24. osl_edu_math-0.2.1/src/edumath/arithmetic/validators.py +0 -0
  25. osl_edu_math-0.2.1/src/edumath/calculus/__init__.py +0 -0
  26. osl_edu_math-0.2.1/src/edumath/calculus/concepts.py +0 -0
  27. osl_edu_math-0.2.1/src/edumath/calculus/derivatives.py +47 -0
  28. osl_edu_math-0.2.1/src/edumath/calculus/exercises.py +0 -0
  29. osl_edu_math-0.2.1/src/edumath/calculus/integrals.py +59 -0
  30. osl_edu_math-0.2.1/src/edumath/calculus/plots.py +0 -0
  31. osl_edu_math-0.2.1/src/edumath/calculus/quizzes.py +0 -0
  32. osl_edu_math-0.2.1/src/edumath/calculus/validators.py +0 -0
  33. osl_edu_math-0.2.1/src/edumath/combinatorics/__init__.py +0 -0
  34. osl_edu_math-0.2.1/src/edumath/combinatorics/concepts.py +0 -0
  35. osl_edu_math-0.2.1/src/edumath/combinatorics/exercises.py +0 -0
  36. osl_edu_math-0.2.1/src/edumath/combinatorics/plots.py +0 -0
  37. osl_edu_math-0.2.1/src/edumath/combinatorics/quizzes.py +0 -0
  38. osl_edu_math-0.2.1/src/edumath/combinatorics/validators.py +0 -0
  39. osl_edu_math-0.2.1/src/edumath/complex_analysis/__init__.py +0 -0
  40. osl_edu_math-0.2.1/src/edumath/complex_analysis/concepts.py +0 -0
  41. osl_edu_math-0.2.1/src/edumath/complex_analysis/exercises.py +0 -0
  42. osl_edu_math-0.2.1/src/edumath/complex_analysis/plots.py +0 -0
  43. osl_edu_math-0.2.1/src/edumath/complex_analysis/quizzes.py +0 -0
  44. osl_edu_math-0.2.1/src/edumath/complex_analysis/validators.py +0 -0
  45. osl_edu_math-0.2.1/src/edumath/core/__init__.py +83 -0
  46. osl_edu_math-0.2.1/src/edumath/core/answers.py +75 -0
  47. osl_edu_math-0.2.1/src/edumath/core/exercises.py +66 -0
  48. osl_edu_math-0.2.1/src/edumath/core/expressions.py +103 -0
  49. osl_edu_math-0.2.1/src/edumath/core/lessons.py +52 -0
  50. osl_edu_math-0.2.1/src/edumath/core/plots.py +245 -0
  51. osl_edu_math-0.2.1/src/edumath/core/quizzes.py +90 -0
  52. osl_edu_math-0.2.1/src/edumath/core/solutions.py +105 -0
  53. osl_edu_math-0.2.1/src/edumath/core/widgets.py +22 -0
  54. osl_edu_math-0.2.1/src/edumath/differential_equations/__init__.py +0 -0
  55. osl_edu_math-0.2.1/src/edumath/differential_equations/concepts.py +0 -0
  56. osl_edu_math-0.2.1/src/edumath/differential_equations/exercises.py +0 -0
  57. osl_edu_math-0.2.1/src/edumath/differential_equations/plots.py +0 -0
  58. osl_edu_math-0.2.1/src/edumath/differential_equations/quizzes.py +0 -0
  59. osl_edu_math-0.2.1/src/edumath/differential_equations/solvers.py +34 -0
  60. osl_edu_math-0.2.1/src/edumath/differential_equations/validators.py +0 -0
  61. osl_edu_math-0.2.1/src/edumath/discrete_math/__init__.py +0 -0
  62. osl_edu_math-0.2.1/src/edumath/discrete_math/concepts.py +0 -0
  63. osl_edu_math-0.2.1/src/edumath/discrete_math/exercises.py +0 -0
  64. osl_edu_math-0.2.1/src/edumath/discrete_math/logic.py +31 -0
  65. osl_edu_math-0.2.1/src/edumath/discrete_math/plots.py +0 -0
  66. osl_edu_math-0.2.1/src/edumath/discrete_math/quizzes.py +0 -0
  67. osl_edu_math-0.2.1/src/edumath/discrete_math/validators.py +0 -0
  68. osl_edu_math-0.2.1/src/edumath/geometry/__init__.py +0 -0
  69. osl_edu_math-0.2.1/src/edumath/geometry/concepts.py +0 -0
  70. osl_edu_math-0.2.1/src/edumath/geometry/exercises.py +0 -0
  71. osl_edu_math-0.2.1/src/edumath/geometry/plots.py +0 -0
  72. osl_edu_math-0.2.1/src/edumath/geometry/quizzes.py +0 -0
  73. osl_edu_math-0.2.1/src/edumath/geometry/validators.py +0 -0
  74. osl_edu_math-0.2.1/src/edumath/graph_theory/__init__.py +0 -0
  75. osl_edu_math-0.2.1/src/edumath/graph_theory/concepts.py +0 -0
  76. osl_edu_math-0.2.1/src/edumath/graph_theory/exercises.py +0 -0
  77. osl_edu_math-0.2.1/src/edumath/graph_theory/plots.py +0 -0
  78. osl_edu_math-0.2.1/src/edumath/graph_theory/quizzes.py +0 -0
  79. osl_edu_math-0.2.1/src/edumath/graph_theory/validators.py +0 -0
  80. osl_edu_math-0.2.1/src/edumath/linear_algebra/__init__.py +0 -0
  81. osl_edu_math-0.2.1/src/edumath/linear_algebra/concepts.py +48 -0
  82. osl_edu_math-0.2.1/src/edumath/linear_algebra/exercises.py +0 -0
  83. osl_edu_math-0.2.1/src/edumath/linear_algebra/plots.py +0 -0
  84. osl_edu_math-0.2.1/src/edumath/linear_algebra/quizzes.py +0 -0
  85. osl_edu_math-0.2.1/src/edumath/linear_algebra/validators.py +0 -0
  86. osl_edu_math-0.2.1/src/edumath/logic/__init__.py +0 -0
  87. osl_edu_math-0.2.1/src/edumath/logic/concepts.py +0 -0
  88. osl_edu_math-0.2.1/src/edumath/logic/exercises.py +0 -0
  89. osl_edu_math-0.2.1/src/edumath/logic/plots.py +0 -0
  90. osl_edu_math-0.2.1/src/edumath/logic/quizzes.py +0 -0
  91. osl_edu_math-0.2.1/src/edumath/logic/validators.py +0 -0
  92. osl_edu_math-0.2.1/src/edumath/number_theory/__init__.py +0 -0
  93. osl_edu_math-0.2.1/src/edumath/number_theory/concepts.py +0 -0
  94. osl_edu_math-0.2.1/src/edumath/number_theory/exercises.py +0 -0
  95. osl_edu_math-0.2.1/src/edumath/number_theory/plots.py +0 -0
  96. osl_edu_math-0.2.1/src/edumath/number_theory/quizzes.py +0 -0
  97. osl_edu_math-0.2.1/src/edumath/number_theory/validators.py +0 -0
  98. osl_edu_math-0.2.1/src/edumath/numerical_methods/__init__.py +0 -0
  99. osl_edu_math-0.2.1/src/edumath/numerical_methods/concepts.py +0 -0
  100. osl_edu_math-0.2.1/src/edumath/numerical_methods/exercises.py +0 -0
  101. osl_edu_math-0.2.1/src/edumath/numerical_methods/plots.py +0 -0
  102. osl_edu_math-0.2.1/src/edumath/numerical_methods/quizzes.py +0 -0
  103. osl_edu_math-0.2.1/src/edumath/numerical_methods/validators.py +0 -0
  104. osl_edu_math-0.2.1/src/edumath/optimization/__init__.py +0 -0
  105. osl_edu_math-0.2.1/src/edumath/optimization/concepts.py +0 -0
  106. osl_edu_math-0.2.1/src/edumath/optimization/exercises.py +0 -0
  107. osl_edu_math-0.2.1/src/edumath/optimization/plots.py +0 -0
  108. osl_edu_math-0.2.1/src/edumath/optimization/quizzes.py +0 -0
  109. osl_edu_math-0.2.1/src/edumath/optimization/validators.py +0 -0
  110. osl_edu_math-0.2.1/src/edumath/probability/__init__.py +0 -0
  111. osl_edu_math-0.2.1/src/edumath/probability/concepts.py +0 -0
  112. osl_edu_math-0.2.1/src/edumath/probability/distributions.py +47 -0
  113. osl_edu_math-0.2.1/src/edumath/probability/exercises.py +0 -0
  114. osl_edu_math-0.2.1/src/edumath/probability/plots.py +0 -0
  115. osl_edu_math-0.2.1/src/edumath/probability/quizzes.py +0 -0
  116. osl_edu_math-0.2.1/src/edumath/probability/validators.py +0 -0
  117. osl_edu_math-0.2.1/src/edumath/py.typed +0 -0
  118. osl_edu_math-0.2.1/src/edumath/python_fundamentals/__init__.py +17 -0
  119. osl_edu_math-0.2.1/src/edumath/python_fundamentals/arrays.py +32 -0
  120. osl_edu_math-0.2.1/src/edumath/python_fundamentals/basics.py +24 -0
  121. osl_edu_math-0.2.1/src/edumath/python_fundamentals/control_flow.py +24 -0
  122. osl_edu_math-0.2.1/src/edumath/python_fundamentals/plots.py +60 -0
  123. osl_edu_math-0.2.1/src/edumath/set_theory/__init__.py +0 -0
  124. osl_edu_math-0.2.1/src/edumath/set_theory/concepts.py +0 -0
  125. osl_edu_math-0.2.1/src/edumath/set_theory/exercises.py +0 -0
  126. osl_edu_math-0.2.1/src/edumath/set_theory/plots.py +0 -0
  127. osl_edu_math-0.2.1/src/edumath/set_theory/quizzes.py +0 -0
  128. osl_edu_math-0.2.1/src/edumath/set_theory/validators.py +0 -0
  129. osl_edu_math-0.2.1/src/edumath/statistics/__init__.py +0 -0
  130. osl_edu_math-0.2.1/src/edumath/statistics/concepts.py +44 -0
  131. osl_edu_math-0.2.1/src/edumath/statistics/exercises.py +0 -0
  132. osl_edu_math-0.2.1/src/edumath/statistics/plots.py +0 -0
  133. osl_edu_math-0.2.1/src/edumath/statistics/quizzes.py +0 -0
  134. osl_edu_math-0.2.1/src/edumath/statistics/validators.py +0 -0
  135. osl_edu_math-0.2.1/src/edumath/topology/__init__.py +0 -0
  136. osl_edu_math-0.2.1/src/edumath/topology/concepts.py +0 -0
  137. osl_edu_math-0.2.1/src/edumath/topology/exercises.py +0 -0
  138. osl_edu_math-0.2.1/src/edumath/topology/plots.py +0 -0
  139. osl_edu_math-0.2.1/src/edumath/topology/quizzes.py +0 -0
  140. osl_edu_math-0.2.1/src/edumath/topology/validators.py +0 -0
  141. osl_edu_math-0.2.1/src/edumath/trigonometry/__init__.py +0 -0
  142. osl_edu_math-0.2.1/src/edumath/trigonometry/concepts.py +26 -0
  143. osl_edu_math-0.2.1/src/edumath/trigonometry/exercises.py +0 -0
  144. osl_edu_math-0.2.1/src/edumath/trigonometry/plots.py +185 -0
  145. osl_edu_math-0.2.1/src/edumath/trigonometry/quizzes.py +0 -0
  146. osl_edu_math-0.2.1/src/edumath/trigonometry/validators.py +0 -0
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Open Science Labs Incubator
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,86 @@
1
+ Metadata-Version: 2.4
2
+ Name: osl-edu-math
3
+ Version: 0.2.1
4
+ Summary: Python tools for math education workflows.
5
+ License-Expression: BSD-3-Clause
6
+ License-File: LICENSE
7
+ Keywords: education,math,python,open-science
8
+ Author: Open Science Labs Incubator
9
+ Requires-Python: >=3.10,<4
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Education
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Education
19
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
20
+ Provides-Extra: dev
21
+ Provides-Extra: docs
22
+ Requires-Dist: ipython (>=7)
23
+ Requires-Dist: ipywidgets (>=6)
24
+ Requires-Dist: makim (==1.29.0) ; extra == "dev"
25
+ Requires-Dist: matplotlib (>=2)
26
+ Requires-Dist: mypy (>=1.10) ; extra == "dev"
27
+ Requires-Dist: numpy (>=2)
28
+ Requires-Dist: pre-commit (>=3) ; extra == "dev"
29
+ Requires-Dist: pytest (>=8) ; extra == "dev"
30
+ Requires-Dist: pytest-cov (>=5) ; extra == "dev"
31
+ Requires-Dist: ruff (>=0.6) ; extra == "dev"
32
+ Requires-Dist: sympy (>=1)
33
+ Project-URL: Documentation, https://osl-incubator.github.io/edu-math/
34
+ Project-URL: Homepage, https://github.com/osl-incubator/edu-math
35
+ Project-URL: Issues, https://github.com/osl-incubator/edu-math/issues
36
+ Project-URL: Repository, https://github.com/osl-incubator/edu-math
37
+ Description-Content-Type: text/markdown
38
+
39
+ # edu-math
40
+
41
+ ![CI](https://img.shields.io/github/actions/workflow/status/osl-incubator/edu-math/ci.yml?logo=github&label=CI)
42
+ [![Python Versions](https://img.shields.io/pypi/pyversions/osl-edu-math)](https://pypi.org/project/osl-edu-math/)
43
+ [![Package Version](https://img.shields.io/pypi/v/osl-edu-math?color=blue)](https://pypi.org/project/osl-edu-math/)
44
+ ![License](https://img.shields.io/pypi/l/osl-edu-math?color=blue)
45
+
46
+ `edu-math` is a Python package for math education workflows.
47
+
48
+ The PyPI distribution is `osl-edu-math`; the import package remains `edumath`.
49
+
50
+ The project is in its initial scaffold stage. The repository includes packaging,
51
+ testing, linting, documentation, release automation, and GitHub workflow
52
+ infrastructure adapted from the Open Science Labs Incubator Python package
53
+ template used by `prisma-flow`.
54
+
55
+ ## Installation
56
+
57
+ ```bash
58
+ pip install osl-edu-math
59
+ ```
60
+
61
+ ## Development
62
+
63
+ ```bash
64
+ conda env create -f conda/dev.yaml
65
+ conda activate edumath
66
+ poetry config virtualenvs.create false
67
+ poetry install --extras "dev"
68
+ ```
69
+
70
+ Run checks through Makim:
71
+
72
+ ```bash
73
+ makim tests.linter
74
+ makim tests.unit
75
+ makim package.build
76
+ makim docs.build
77
+ ```
78
+
79
+ ## Project layout
80
+
81
+ - `src/edumath/`: Python package source
82
+ - `tests/`: pytest test suite
83
+ - `docs/`: Quarto documentation website
84
+ - `conda/`: development and release environment files
85
+ - `.github/`: issue templates and GitHub Actions workflows
86
+
@@ -0,0 +1,47 @@
1
+ # edu-math
2
+
3
+ ![CI](https://img.shields.io/github/actions/workflow/status/osl-incubator/edu-math/ci.yml?logo=github&label=CI)
4
+ [![Python Versions](https://img.shields.io/pypi/pyversions/osl-edu-math)](https://pypi.org/project/osl-edu-math/)
5
+ [![Package Version](https://img.shields.io/pypi/v/osl-edu-math?color=blue)](https://pypi.org/project/osl-edu-math/)
6
+ ![License](https://img.shields.io/pypi/l/osl-edu-math?color=blue)
7
+
8
+ `edu-math` is a Python package for math education workflows.
9
+
10
+ The PyPI distribution is `osl-edu-math`; the import package remains `edumath`.
11
+
12
+ The project is in its initial scaffold stage. The repository includes packaging,
13
+ testing, linting, documentation, release automation, and GitHub workflow
14
+ infrastructure adapted from the Open Science Labs Incubator Python package
15
+ template used by `prisma-flow`.
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install osl-edu-math
21
+ ```
22
+
23
+ ## Development
24
+
25
+ ```bash
26
+ conda env create -f conda/dev.yaml
27
+ conda activate edumath
28
+ poetry config virtualenvs.create false
29
+ poetry install --extras "dev"
30
+ ```
31
+
32
+ Run checks through Makim:
33
+
34
+ ```bash
35
+ makim tests.linter
36
+ makim tests.unit
37
+ makim package.build
38
+ makim docs.build
39
+ ```
40
+
41
+ ## Project layout
42
+
43
+ - `src/edumath/`: Python package source
44
+ - `tests/`: pytest test suite
45
+ - `docs/`: Quarto documentation website
46
+ - `conda/`: development and release environment files
47
+ - `.github/`: issue templates and GitHub Actions workflows
@@ -0,0 +1,119 @@
1
+ [project]
2
+ name = "osl-edu-math"
3
+ version = "0.2.1" # semantic-release
4
+ description = "Python tools for math education workflows."
5
+ readme = "README.md"
6
+ requires-python = ">=3.10,<4"
7
+ license = "BSD-3-Clause"
8
+ authors = [
9
+ { name = "Open Science Labs Incubator" }
10
+ ]
11
+ keywords = [
12
+ "education",
13
+ "math",
14
+ "python",
15
+ "open-science",
16
+ ]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Intended Audience :: Education",
20
+ "Intended Audience :: Science/Research",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Topic :: Education",
27
+ "Topic :: Scientific/Engineering :: Mathematics",
28
+ ]
29
+ dependencies = [
30
+ "matplotlib>=2",
31
+ "numpy>=2",
32
+ "ipywidgets>=6",
33
+ "ipython>=7",
34
+ "sympy>=1"
35
+ ]
36
+
37
+ [project.urls]
38
+ Homepage = "https://github.com/osl-incubator/edu-math"
39
+ Repository = "https://github.com/osl-incubator/edu-math"
40
+ Issues = "https://github.com/osl-incubator/edu-math/issues"
41
+ Documentation = "https://osl-incubator.github.io/edu-math/"
42
+
43
+ [project.optional-dependencies]
44
+ dev = [
45
+ "pytest>=8",
46
+ "pytest-cov>=5",
47
+ "ruff>=0.6",
48
+ "mypy>=1.10",
49
+ "pre-commit>=3",
50
+ "makim==1.29.0",
51
+ ]
52
+ docs = []
53
+
54
+ [tool.poetry.group.dev.dependencies]
55
+ quarto-cli = ">=1.9.0"
56
+ pytest = ">=8"
57
+ pytest-cov = ">=5"
58
+ ruff = ">=0.6"
59
+ mypy = ">=1.10"
60
+ pre-commit = ">=3"
61
+ makim = "==1.29.0"
62
+ click = "^8.4.1"
63
+
64
+ [build-system]
65
+ requires = ["poetry-core>=2"]
66
+ build-backend = "poetry.core.masonry.api"
67
+
68
+ [tool.poetry]
69
+ packages = [
70
+ { include = "edumath", from = "src" },
71
+ ]
72
+ include = [
73
+ "src/edumath/py.typed",
74
+ ]
75
+
76
+ [tool.ruff]
77
+ line-length = 88
78
+ target-version = "py310"
79
+ src = ["src", "tests"]
80
+
81
+ [tool.ruff.lint]
82
+ select = [
83
+ "E",
84
+ "F",
85
+ "I",
86
+ "UP",
87
+ "B",
88
+ "RUF",
89
+ ]
90
+ ignore = [
91
+ "D203",
92
+ "D213",
93
+ ]
94
+
95
+ [tool.ruff.lint.per-file-ignores]
96
+ "tests/**" = ["D"]
97
+
98
+ [tool.ruff.format]
99
+ quote-style = "double"
100
+
101
+ [tool.pytest.ini_options]
102
+ testpaths = ["tests"]
103
+ addopts = "-ra"
104
+
105
+ [tool.mypy]
106
+ python_version = "3.10"
107
+ strict = true
108
+ warn_unused_ignores = true
109
+ warn_redundant_casts = true
110
+ warn_unused_configs = true
111
+ show_error_codes = true
112
+
113
+ [[tool.mypy.overrides]]
114
+ module = [
115
+ "IPython.*",
116
+ "ipywidgets.*",
117
+ "sympy.*",
118
+ ]
119
+ ignore_missing_imports = true
@@ -0,0 +1,5 @@
1
+ """Public package interface for edu-math."""
2
+
3
+ __version__ = "0.2.1" # semantic-release
4
+
5
+ __all__ = ["__version__"]
@@ -0,0 +1,34 @@
1
+ """Algebra learning tools."""
2
+
3
+ from edumath.algebra.concepts import COLLEGE_ALGEBRA_PATH
4
+ from edumath.algebra.exercises import (
5
+ expand_expression_exercise,
6
+ linear_equation_exercise,
7
+ )
8
+ from edumath.algebra.plots import compare_functions_scene, function_scene
9
+ from edumath.algebra.quizes import (
10
+ GuessingQuiz,
11
+ GuessingQuizWidget,
12
+ GuessQuestion,
13
+ GuessResult,
14
+ SympyGuessGame,
15
+ )
16
+ from edumath.algebra.validators import (
17
+ validate_expression_equivalence,
18
+ validate_numeric_solution,
19
+ )
20
+
21
+ __all__ = [
22
+ "COLLEGE_ALGEBRA_PATH",
23
+ "GuessQuestion",
24
+ "GuessResult",
25
+ "GuessingQuiz",
26
+ "GuessingQuizWidget",
27
+ "SympyGuessGame",
28
+ "compare_functions_scene",
29
+ "expand_expression_exercise",
30
+ "function_scene",
31
+ "linear_equation_exercise",
32
+ "validate_expression_equivalence",
33
+ "validate_numeric_solution",
34
+ ]
@@ -0,0 +1,131 @@
1
+ """College algebra concept metadata."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from edumath.core import LearningObjective, Lesson, LessonSection, StudyPath
6
+
7
+ EXPRESSIONS_AND_EQUATIONS = Lesson(
8
+ title="Expressions and equations",
9
+ slug="expressions-and-equations",
10
+ objectives=(
11
+ LearningObjective("Distinguish expressions from equations."),
12
+ LearningObjective("Evaluate algebraic expressions by substitution."),
13
+ LearningObjective("Solve one-variable linear equations."),
14
+ ),
15
+ sections=(
16
+ LessonSection(
17
+ title="Expressions",
18
+ body=(
19
+ "An expression is a mathematical phrase that can be simplified "
20
+ "or evaluated, such as 3*x + 2."
21
+ ),
22
+ ),
23
+ LessonSection(
24
+ title="Equations",
25
+ body=(
26
+ "An equation states that two expressions are equal. Solving an "
27
+ "equation means finding values that make the statement true."
28
+ ),
29
+ ),
30
+ ),
31
+ tags=("algebra", "equations"),
32
+ )
33
+
34
+ FUNCTIONS_AND_GRAPHS = Lesson(
35
+ title="Functions and graphs",
36
+ slug="functions-and-graphs",
37
+ objectives=(
38
+ LearningObjective("Interpret a function as an input-output rule."),
39
+ LearningObjective("Identify slope, intercepts, domain, and range."),
40
+ LearningObjective("Connect symbolic functions to their graphs."),
41
+ ),
42
+ sections=(
43
+ LessonSection(
44
+ title="Functions",
45
+ body="A function assigns each input exactly one output.",
46
+ ),
47
+ LessonSection(
48
+ title="Graphs",
49
+ body=("A graph shows the ordered pairs (x, f(x)) produced by a function."),
50
+ ),
51
+ ),
52
+ tags=("algebra", "functions", "graphs"),
53
+ )
54
+
55
+ POLYNOMIALS = Lesson(
56
+ title="Polynomials",
57
+ slug="polynomials",
58
+ objectives=(
59
+ LearningObjective("Recognize polynomial degree and leading coefficient."),
60
+ LearningObjective("Factor common polynomial forms."),
61
+ LearningObjective("Use roots to interpret polynomial graphs."),
62
+ ),
63
+ sections=(
64
+ LessonSection(
65
+ title="Polynomial structure",
66
+ body=(
67
+ "A polynomial is a sum of constant multiples of non-negative "
68
+ "integer powers of a variable."
69
+ ),
70
+ ),
71
+ ),
72
+ tags=("algebra", "polynomials"),
73
+ )
74
+
75
+ EXPONENTIALS_AND_LOGARITHMS = Lesson(
76
+ title="Exponentials and logarithms",
77
+ slug="exponentials-and-logarithms",
78
+ objectives=(
79
+ LearningObjective("Recognize exponential growth and decay."),
80
+ LearningObjective("Use logarithms as inverse operations for exponentials."),
81
+ LearningObjective("Solve basic exponential and logarithmic equations."),
82
+ ),
83
+ sections=(
84
+ LessonSection(
85
+ title="Inverse relationship",
86
+ body="A logarithm answers the question: what exponent produced this value?",
87
+ ),
88
+ ),
89
+ tags=("algebra", "exponentials", "logarithms"),
90
+ )
91
+
92
+ SYSTEMS_OF_EQUATIONS = Lesson(
93
+ title="Systems of equations",
94
+ slug="systems-of-equations",
95
+ objectives=(
96
+ LearningObjective("Interpret a solution as a point satisfying all equations."),
97
+ LearningObjective("Solve small linear systems by substitution or elimination."),
98
+ LearningObjective("Connect systems to line intersections."),
99
+ ),
100
+ sections=(
101
+ LessonSection(
102
+ title="Shared solutions",
103
+ body=(
104
+ "A system asks for values that make every equation true at the "
105
+ "same time."
106
+ ),
107
+ ),
108
+ ),
109
+ tags=("algebra", "systems"),
110
+ )
111
+
112
+ COLLEGE_ALGEBRA_PATH = StudyPath(
113
+ title="College Algebra",
114
+ lessons=(
115
+ EXPRESSIONS_AND_EQUATIONS,
116
+ FUNCTIONS_AND_GRAPHS,
117
+ POLYNOMIALS,
118
+ EXPONENTIALS_AND_LOGARITHMS,
119
+ SYSTEMS_OF_EQUATIONS,
120
+ ),
121
+ )
122
+
123
+
124
+ __all__ = [
125
+ "COLLEGE_ALGEBRA_PATH",
126
+ "EXPONENTIALS_AND_LOGARITHMS",
127
+ "EXPRESSIONS_AND_EQUATIONS",
128
+ "FUNCTIONS_AND_GRAPHS",
129
+ "POLYNOMIALS",
130
+ "SYSTEMS_OF_EQUATIONS",
131
+ ]
@@ -0,0 +1,81 @@
1
+ """College algebra exercise builders."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from random import Random
6
+ from typing import SupportsFloat, cast
7
+
8
+ import sympy as sp
9
+
10
+ from edumath.core import (
11
+ AnswerCheck,
12
+ Exercise,
13
+ check_expression_answer,
14
+ check_numeric_answer,
15
+ )
16
+
17
+
18
+ def linear_equation_exercise(
19
+ *,
20
+ seed: int | None = None,
21
+ ) -> Exercise:
22
+ """Generate a one-variable linear equation exercise."""
23
+
24
+ rng = Random(seed)
25
+ x = sp.Symbol("x")
26
+ solution = rng.randint(-8, 8)
27
+ coefficient = _nonzero_int(rng, -6, 6)
28
+ constant = rng.randint(-10, 10)
29
+ equation = sp.Eq(coefficient * x + constant, coefficient * solution + constant)
30
+ expected = float(solution)
31
+
32
+ def validator(received: object) -> AnswerCheck:
33
+ return check_numeric_answer(float(cast(SupportsFloat, received)), expected)
34
+
35
+ return Exercise(
36
+ prompt=f"Solve for x: {sp.sstr(equation)}",
37
+ expected=expected,
38
+ validator=validator,
39
+ explanation=(
40
+ "Undo the addition/subtraction first, then divide by the coefficient of x."
41
+ ),
42
+ tags=("algebra", "linear-equations"),
43
+ )
44
+
45
+
46
+ def expand_expression_exercise(
47
+ *,
48
+ seed: int | None = None,
49
+ ) -> Exercise:
50
+ """Generate a polynomial expansion exercise."""
51
+
52
+ rng = Random(seed)
53
+ x = sp.Symbol("x")
54
+ a = _nonzero_int(rng, -5, 5)
55
+ b = rng.randint(-6, 6)
56
+ expression = (x + a) * (x + b)
57
+ expected = sp.expand(expression)
58
+
59
+ return Exercise(
60
+ prompt=f"Expand: {sp.sstr(expression)}",
61
+ expected=expected,
62
+ validator=lambda received: check_expression_answer(
63
+ str(received),
64
+ expected,
65
+ ),
66
+ explanation=(
67
+ "Use distribution: multiply each term in the first factor by each "
68
+ "term in the second."
69
+ ),
70
+ tags=("algebra", "polynomials"),
71
+ )
72
+
73
+
74
+ def _nonzero_int(rng: Random, start: int, stop: int) -> int:
75
+ value = 0
76
+ while value == 0:
77
+ value = rng.randint(start, stop)
78
+ return value
79
+
80
+
81
+ __all__ = ["expand_expression_exercise", "linear_equation_exercise"]
@@ -0,0 +1,76 @@
1
+ """College algebra plotting helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import sympy as sp
6
+
7
+ from edumath.core import (
8
+ ExplicitFunction2D,
9
+ PlotRange,
10
+ PlotScene2D,
11
+ PlotStyle,
12
+ Viewport2D,
13
+ )
14
+
15
+
16
+ def function_scene(
17
+ expression: str | sp.Expr,
18
+ *,
19
+ x_min: float = -10,
20
+ x_max: float = 10,
21
+ y_min: float = -10,
22
+ y_max: float = 10,
23
+ title: str | None = None,
24
+ color: str = "#1a73e8",
25
+ ) -> PlotScene2D:
26
+ """Create a reusable scene for a single algebraic function."""
27
+
28
+ return PlotScene2D(
29
+ elements=(
30
+ ExplicitFunction2D(
31
+ expression,
32
+ domain=PlotRange(x_min, x_max),
33
+ style=PlotStyle(color=color, label=f"y = {expression}"),
34
+ ),
35
+ ),
36
+ viewport=Viewport2D(
37
+ x=PlotRange(x_min, x_max),
38
+ y=PlotRange(y_min, y_max),
39
+ ),
40
+ title=title or f"y = {expression}",
41
+ )
42
+
43
+
44
+ def compare_functions_scene(
45
+ expressions: tuple[str | sp.Expr, ...],
46
+ *,
47
+ x_min: float = -10,
48
+ x_max: float = 10,
49
+ y_min: float = -10,
50
+ y_max: float = 10,
51
+ title: str = "Function comparison",
52
+ ) -> PlotScene2D:
53
+ """Create a scene comparing several functions."""
54
+
55
+ colors = ("#1a73e8", "#d93025", "#137333", "#9334e6")
56
+ return PlotScene2D(
57
+ elements=tuple(
58
+ ExplicitFunction2D(
59
+ expression,
60
+ domain=PlotRange(x_min, x_max),
61
+ style=PlotStyle(
62
+ color=colors[index % len(colors)],
63
+ label=f"y = {expression}",
64
+ ),
65
+ )
66
+ for index, expression in enumerate(expressions)
67
+ ),
68
+ viewport=Viewport2D(
69
+ x=PlotRange(x_min, x_max),
70
+ y=PlotRange(y_min, y_max),
71
+ ),
72
+ title=title,
73
+ )
74
+
75
+
76
+ __all__ = ["compare_functions_scene", "function_scene"]