This commit marks a major milestone in the problem generator project.
Key systems include:
- Fully functional problem generation for all 23 defined concepts (Simple Interest, Compound Interest, Banker's Discount, Effective Rate, Continuous Compounding, Exact/Ordinary Simple Interest).
- Robust date handling for date-specific interest calculations.
- Improved solution presentation with accurate "Substitute Values" step and complete variable descriptions.
- Interactive problem display in `main.py`: problem statement shown first, question and solution revealed on user input.
- Added plausibility checks for rate calculations to avoid unrealistic negative rates.
- Comprehensive `README.md` update:
- Detailed system architecture (modules, data files, Mermaid diagram).
- List of all currently covered financial concepts.
- Instructions for running and extending the generator.
- Discussion of scope for future enhancements (Equation of Value, Gradients, etc.).
- Refinements to `value_sampler.py` for better formatting and handling of None values.
- Updates to `text_snippets.json` for complete variable descriptions and improved solution step phrasing.
- Updates to `value_ranges.json` for date generation parameters.
- `problem_engine.py` now systematically tests all concepts when run directly.
- Added `uv.lock` to track resolved dependencies.
The system is capable of generating a wide variety of engineering economy problems with detailed, step-by-step solutions and an interactive user experience.
58 lines
2.3 KiB
Python
58 lines
2.3 KiB
Python
import sys
|
|
import os
|
|
|
|
# Ensure the src directory is in the Python path
|
|
# This allows running main.py from the project root (e.g., python main.py)
|
|
# and having imports like 'from src import ...' work correctly.
|
|
project_root = os.path.abspath(os.path.dirname(__file__))
|
|
src_path = os.path.join(project_root, 'src')
|
|
if src_path not in sys.path:
|
|
sys.path.insert(0, src_path)
|
|
if project_root not in sys.path: # Also add project root for 'from src import ...' if main is outside src
|
|
sys.path.insert(0, project_root)
|
|
|
|
|
|
from src.problem_engine import generate_problem
|
|
from src.data_loader import get_text_snippets # For variable descriptions
|
|
# Note: problem_engine.generate_problem() handles caching of all necessary data internally.
|
|
|
|
def main():
|
|
print("Generating a financial problem via main.py...\n")
|
|
|
|
# Load text snippets for variable descriptions
|
|
# generate_problem() will load its own cache, but for descriptions here, we need it too.
|
|
# A more advanced setup might pass TEXT_SNIPPETS_DATA around or make it a singleton.
|
|
text_snippets_data = get_text_snippets()
|
|
if not text_snippets_data:
|
|
print("Error: Failed to load text snippets for main.py. Exiting.")
|
|
return
|
|
|
|
problem = generate_problem()
|
|
|
|
if "error" in problem:
|
|
print(f"Error generating problem: {problem['error']}")
|
|
else:
|
|
print(f"--- Problem ---")
|
|
print(f"Concept ID: {problem['concept_id']}")
|
|
print(f"Topic: {problem['topic']}")
|
|
|
|
print("\nProblem Statement:")
|
|
print(problem['problem_statement'])
|
|
|
|
input("\nPress Enter to see the question and solution...") # Wait for user interaction
|
|
|
|
unknown_key_desc = text_snippets_data.get("variable_descriptions", {}).get(problem['target_unknown_key'], problem['target_unknown_key'])
|
|
print(f"\nQuestion: What is the {unknown_key_desc}?")
|
|
|
|
print("\nGuided Solution:")
|
|
for i, step in enumerate(problem['solution_steps']):
|
|
# The steps from solution_presenter already have numbering.
|
|
# If not, add: print(f" {i+1}. {step}")
|
|
print(step)
|
|
|
|
print(f"\nFinal Answer ({problem['target_unknown_key']}): {problem['calculated_answer_formatted']}")
|
|
print("---------------------------------------\n")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|