feat: Implement full problem generation

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.
This commit is contained in:
2025-05-09 11:56:16 +08:00
parent f1d18ec989
commit f02f848ada
8 changed files with 812 additions and 299 deletions

View File

@@ -1,45 +1,181 @@
{
"actors_person": ["{person_title} {person_first_name} {person_last_name}", "{person_first_name} {person_last_name}", "{person_title} {person_last_name}"],
"actors_company": ["{company_prefix} {company_suffix}", "{company_prefix} {company_industry}"],
"actions_loan_present_singular": ["borrows", "takes out a loan for", "secures financing for", "needs a loan of", "is seeking a loan of"],
"actions_loan_present_plural": ["borrow", "take out a loan for", "secure financing for", "need a loan of", "are seeking a loan of"],
"actions_loan_past_singular": ["borrowed", "took out a loan for", "secured financing for", "received a loan of"],
"actions_loan_past_plural": ["borrowed", "took out a loan for", "secured financing for", "received a loan of"],
"actions_investment_present_singular": ["invests", "deposits", "puts", "plans to invest", "wants to deposit"],
"actions_investment_present_plural": ["invest", "deposit", "put", "plan to invest", "want to deposit"],
"actions_investment_past_singular": ["invested", "deposited", "put", "made an investment of"],
"actions_investment_past_plural": ["invested", "deposited", "put", "made an investment of"],
"actions_repayment_present_singular": ["repays", "settles", "amortizes", "makes a payment on"],
"actions_repayment_present_plural": ["repay", "settle", "amortize", "make a payment on"],
"actions_repayment_past_singular": ["repaid", "settled", "amortized", "made a payment on"],
"actions_repayment_past_plural": ["repaid", "settled", "amortized", "made a payment on"],
"actions_receive_present_singular": ["receives", "obtains", "gets", "is due to receive"],
"actions_receive_present_plural": ["receive", "obtain", "get", "are due to receive"],
"actions_receive_past_singular": ["received", "obtained", "got"],
"actions_receive_past_plural": ["received", "obtained", "got"],
"actions_earn_present_singular": ["earns", "accumulates", "yields"],
"actions_earn_present_plural": ["earn", "accumulate", "yield"],
"actions_earn_past_singular": ["earned", "accumulated", "yielded"],
"actions_earn_past_plural": ["earned", "accumulated", "yielded"],
"time_phrases_duration": ["for a period of", "over", "for", "during"],
"time_phrases_point": ["at the end of", "after", "in"],
"rate_phrases": ["at a rate of", "with an interest of", "at an annual rate of", "earning interest at"],
"compounding_phrases": ["compounded {compounding_frequency_adverb}", "with {compounding_frequency_adverb} compounding"],
"purpose_phrases_loan": ["for {item_loan}", "to finance {item_loan}", "to purchase {item_loan}"],
"purpose_phrases_investment": ["in {item_investment}", "into {item_investment}", "to grow their capital through {item_investment}"],
"question_starters_what_is": ["What is the", "Determine the", "Calculate the", "Find the", "What will be the", "What was the"],
"question_starters_how_much": ["How much is the", "How much will be the", "How much was the", "How much should be"],
"question_starters_how_long": ["How long will it take for", "How many years are needed for", "What is the time period for"],
"actors_person": [
"{person_title} {person_first_name} {person_last_name}",
"{person_first_name} {person_last_name}",
"{person_title} {person_last_name}"
],
"actors_company": [
"{company_prefix} {company_suffix}",
"{company_prefix} {company_industry}"
],
"actions_loan_present_singular": [
"borrows",
"takes out a loan for",
"secures financing for",
"needs a loan of",
"is seeking a loan of"
],
"actions_loan_present_plural": [
"borrow",
"take out a loan for",
"secure financing for",
"need a loan of",
"are seeking a loan of"
],
"actions_loan_past_singular": [
"borrowed",
"took out a loan for",
"secured financing for",
"received a loan of"
],
"actions_loan_past_plural": [
"borrowed",
"took out a loan for",
"secured financing for",
"received a loan of"
],
"actions_investment_present_singular": [
"invests",
"deposits",
"puts",
"plans to invest",
"wants to deposit"
],
"actions_investment_present_plural": [
"invest",
"deposit",
"put",
"plan to invest",
"want to deposit"
],
"actions_investment_past_singular": [
"invested",
"deposited",
"put",
"made an investment of"
],
"actions_investment_past_plural": [
"invested",
"deposited",
"put",
"made an investment of"
],
"actions_repayment_present_singular": [
"repays",
"settles",
"amortizes",
"makes a payment on"
],
"actions_repayment_present_plural": [
"repay",
"settle",
"amortize",
"make a payment on"
],
"actions_repayment_past_singular": [
"repaid",
"settled",
"amortized",
"made a payment on"
],
"actions_repayment_past_plural": [
"repaid",
"settled",
"amortized",
"made a payment on"
],
"actions_receive_present_singular": [
"receives",
"obtains",
"gets",
"is due to receive"
],
"actions_receive_present_plural": [
"receive",
"obtain",
"get",
"are due to receive"
],
"actions_receive_past_singular": [
"received",
"obtained",
"got"
],
"actions_receive_past_plural": [
"received",
"obtained",
"got"
],
"actions_earn_present_singular": [
"earns",
"accumulates",
"yields"
],
"actions_earn_present_plural": [
"earn",
"accumulate",
"yield"
],
"actions_earn_past_singular": [
"earned",
"accumulated",
"yielded"
],
"actions_earn_past_plural": [
"earned",
"accumulated",
"yielded"
],
"time_phrases_duration": [
"for a period of",
"over",
"for",
"during"
],
"time_phrases_point": [
"at the end of",
"after",
"in"
],
"rate_phrases": [
"at a rate of",
"with an interest of",
"at an annual rate of",
"earning interest at"
],
"compounding_phrases": [
"compounded {compounding_frequency_adverb}",
"with {compounding_frequency_adverb} compounding"
],
"purpose_phrases_loan": [
"for {item_loan}",
"to finance {item_loan}",
"to purchase {item_loan}"
],
"purpose_phrases_investment": [
"in {item_investment}",
"into {item_investment}",
"to grow their capital through {item_investment}"
],
"question_starters_what_is": [
"What is the",
"Determine the",
"Calculate the",
"Find the",
"What will be the",
"What was the"
],
"question_starters_how_much": [
"How much is the",
"How much will be the",
"How much was the",
"How much should be"
],
"question_starters_how_long": [
"How long will it take for",
"How many years are needed for",
"What is the time period for"
],
"scenario_introductions": [
"Consider a scenario where {actor}",
"{actor} is planning to",
@@ -57,11 +193,10 @@
"Therefore,",
"With these conditions,"
],
"solution_guidance": {
"identify_knowns": "First, let's identify the given values (knowns) in the problem:",
"state_formula": "The relevant formula for this problem is:",
"substitute_values": "Now, we substitute the known values into the formula:",
"state_formula": "The relevant formula for this problem is: {target_variable_lhs} = {formula_symbolic_rhs}",
"substitute_values": "Now, we substitute the known values: {target_variable_lhs} = {formula_with_values_rhs}",
"perform_calculation": "Performing the calculation:",
"intermediate_step": "The intermediate result for {step_name} is:",
"final_answer_is": "Therefore, the {unknown_variable_description} is:",
@@ -69,9 +204,18 @@
"calculate_interest_rate_per_period": "Calculate the interest rate per compounding period (i): i = r / m = {nominal_rate_decimal} / {compounding_periods_per_year} = {interest_rate_per_period_decimal}.",
"calculate_total_periods": "Calculate the total number of compounding periods (n): n = t * m = {time_in_years} years * {compounding_periods_per_year} = {total_periods} periods.",
"check_leap_year": "{year} is {is_or_is_not} a leap year.",
"days_in_period": "The number of days from {start_date} to {end_date} is {number_of_days} days."
"days_in_period": "The number of days from {start_date} to {end_date} is {number_of_days} days.",
"determine_time_base_exact": "For exact simple interest, the time base is the actual number of days in the reference year ({year}), which is {days_in_year} days.",
"determine_time_base_ordinary": "For ordinary simple interest, the time base is 360 days.",
"calculate_n_time_years_fractional": "Calculate the time as a fraction of a year (t_fractional): t_fractional = number of days / time base = {n_time_days} / {time_base_days} = {n_time_years_fractional_value}.",
"identify_gradient_parameters": "Identify the parameters of the arithmetic gradient series:",
"state_formula_annuity_component": "The formula for the present worth of the base annuity component (P_A) is: P_A = A1 * (P/A, i, N) which is A1 * [((1 + i)^N - 1) / (i * (1 + i)^N)]",
"calculate_pv_annuity_component": "Calculating the present worth of the base annuity component (P_A):",
"state_formula_gradient_component": "The formula for the present worth of the arithmetic gradient component (P_G) is: P_G = G * (P/G, i, N) which is G * [(((1 + i)^N - (i * N) - 1) / (i^2 * (1 + i)^N))]",
"calculate_pv_gradient_component": "Calculating the present worth of the arithmetic gradient component (P_G):",
"state_formula_total_pv": "The total present worth (P_total) is the sum of the present worth of the annuity and gradient components: P_total = P_A + P_G",
"sum_pv_components": "Summing the present worth components:"
},
"variable_descriptions": {
"P": "principal amount",
"F": "future value",
@@ -95,26 +239,23 @@
"start_date": "start date of the period",
"end_date": "end date of the period",
"time_base_days": "day count basis for the year (time base)",
"n_time_years_fractional": "time period as a fraction of a year"
"n_time_years_fractional": "time period as a fraction of a year",
"A1_base_annuity": "base annuity amount",
"G_gradient_amount": "arithmetic gradient amount",
"N_periods": "number of periods",
"P_A_component": "present worth of the annuity component",
"P_G_component": "present worth of the gradient component",
"P_gradient_series": "total present worth of the arithmetic gradient series",
"I_simple": "simple interest amount",
"F_simple": "future value with simple interest",
"F_compound": "future value with compound interest",
"t_years": "time period in years (for compounding)",
"i_simple_equivalent": "equivalent simple interest rate",
"F_maturity": "maturity value (for Banker's Discount)",
"P_proceeds": "proceeds from discounted loan",
"Db_discount_amount": "banker's discount amount",
"F_continuous": "future value with continuous compounding"
},
"solution_guidance": {
"identify_knowns": "First, let's identify the given values (knowns) in the problem:",
"state_formula": "The relevant formula for this problem is:",
"substitute_values": "Now, we substitute the known values into the formula:",
"perform_calculation": "Performing the calculation:",
"intermediate_step": "The intermediate result for {step_name} is:",
"final_answer_is": "Therefore, the {unknown_variable_description} is:",
"convert_time_to_years": "Convert the time period to years: {original_time_value} {original_time_unit} = {converted_time_value_years} years.",
"calculate_interest_rate_per_period": "Calculate the interest rate per compounding period (i): i = r / m = {nominal_rate_decimal} / {compounding_periods_per_year} = {interest_rate_per_period_decimal}.",
"calculate_total_periods": "Calculate the total number of compounding periods (n): n = t * m = {time_in_years} years * {compounding_periods_per_year} = {total_periods} periods.",
"check_leap_year": "{year} is {is_or_is_not} a leap year.",
"days_in_period": "The number of days from {start_date} to {end_date} is {number_of_days} days.",
"determine_time_base_exact": "For exact simple interest, the time base is the actual number of days in the reference year ({year}), which is {days_in_year} days.",
"determine_time_base_ordinary": "For ordinary simple interest, the time base is 360 days.",
"calculate_n_time_years_fractional": "Calculate the time as a fraction of a year (t_fractional): t_fractional = number of days / time base = {n_time_days} / {time_base_days} = {n_time_years_fractional_value}."
},
"compounding_frequency_adverbs": {
"annually": "annually",
"semi-annually": "semi-annually",

View File

@@ -55,6 +55,13 @@
"internal_precision": 8,
"display_precision": 2
},
"interest_rate_per_period_effective": {
"min": 0.005,
"max": 0.05,
"unit_display": "% per period",
"internal_precision": 8,
"display_precision": 3
},
"discount_rate_bankers": {
"min": 0.05,
"max": 0.20,
@@ -83,7 +90,7 @@
},
"number_of_periods_general": {
"min": 2,
"max": 30,
"max": 60,
"unit": "periods",
"integer": true
},
@@ -111,20 +118,24 @@
"description": "General date, used for start_date and end_date generation.",
"type": "date",
"min_year": 1990,
"max_year": 2030
"max_year": 2030
},
"time_days_exact_ordinary": {
"description": "Number of days for exact/ordinary interest calculations (derived from dates).",
"type": "integer",
"min": 30,
"max": 730,
"min": 30,
"max": 730,
"unit": "days",
"display_precision": 0
},
"time_base_days_exact_ordinary": {
"description": "Time base in days for exact (365/366) or ordinary (360) interest.",
"type": "integer",
"options": [360, 365, 366],
"options": [
360,
365,
366
],
"unit": "days",
"display_precision": 0
},
@@ -132,6 +143,13 @@
"description": "Time period as a fraction of a year (calculated).",
"type": "float",
"unit": "years",
"display_precision": 6
"display_precision": 6
},
"date_period_generation": {
"description": "Parameters for generating random date periods.",
"min_days": 30,
"max_days": 730,
"base_year_start": 1990,
"base_year_end": 2030
}
}