Spaces:
Sleeping
Sleeping
| import os | |
| import random | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| from openai import OpenAI | |
| from Sim_Engine import simulate_period | |
| client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY")) | |
| def summarize_initial_conditions(n_rows, n_cols): | |
| num_parcels = n_rows * n_cols | |
| avg_forage = round(random.uniform(6.5, 8.0), 1) | |
| degraded_pct = round(random.uniform(0.0, 2.0), 1) | |
| riparian_health = random.choice(["excellent", "moderate", "fragile"]) | |
| elk_corridor_status = random.choice([ | |
| "completely intact and lightly used", | |
| "intact but under slight pressure from cattle movement", | |
| "showing signs of fragmentation near key crossings" | |
| ]) | |
| rainfall_outlook = random.choice(["normal", "below average", "above average"]) | |
| return ( | |
| f"There are {num_parcels} parcels in total. Grazing has not yet occurred.\n" | |
| f"Average forage availability is {avg_forage} AUMs per parcel, with about {degraded_pct}% of land already degraded due to prior conditions.\n" | |
| f"Riparian zone condition is {riparian_health}, and the elk movement corridor is {elk_corridor_status}.\n" | |
| f"The seasonal rainfall outlook is {rainfall_outlook}." | |
| ) | |
| def plot_forage_map_to_file(parcel_dict, n_rows, n_cols, title="Forage Map", save_path="forage_map.png"): | |
| forage_map = np.array([ | |
| [parcel_dict[(i, j)]["forage"] for j in range(n_cols)] | |
| for i in range(n_rows) | |
| ]) | |
| fig, ax = plt.subplots(figsize=(8, 6)) | |
| cax = ax.imshow(forage_map, cmap='YlGn', origin='upper') | |
| fig.colorbar(cax, label="Forage AUMs") | |
| ax.set_title(title) | |
| ax.axis('off') | |
| plt.tight_layout() | |
| plt.savefig(save_path) | |
| plt.close(fig) | |
| def elk_feedback(plan_choice, current_summary): | |
| prompt = f""" | |
| You represent a coalition of elk-related interests: conservationists, hunting advocates, and the hospitality/lodging industry. | |
| A student has selected the **'{plan_choice}'** cattle grazing strategy. Below are the current ecological conditions: | |
| ----- | |
| {current_summary} | |
| ----- | |
| Please do the following: | |
| - Explicitly choose **one elk management strategy** from the list: | |
| - **Preserve**: strict elk protections, no hunting, unrestricted movement | |
| - **Cooperate**: shared use corridor, some riparian restrictions, sustainable elk population | |
| - **Exploit**: prioritize hunting/tourism, tolerate reduced elk numbers and access | |
| - Reflect each group's view briefly, but unify the final position. | |
| - Justify your strategy choice based on the above ecological indicators. | |
| """ | |
| response = client.chat.completions.create( | |
| model="gpt-3.5-turbo", | |
| messages=[{"role": "user", "content": prompt}], | |
| temperature=0.8 | |
| ) | |
| return response.choices[0].message.content | |
| def usfs_feedback(plan_choice, student_essay, current_summary): | |
| # Extract the AUM line from the summary | |
| aum_line = "" | |
| for line in current_summary.split("\n"): | |
| if "Average forage availability" in line: | |
| aum_line = line.strip() | |
| break | |
| prompt = f""" | |
| You are a USFS land management agent evaluating a student’s cattle grazing proposal. | |
| The student selected the **'{plan_choice}'** strategy and submitted this justification: | |
| ----- | |
| {student_essay} | |
| ----- | |
| Here are the current rangeland conditions: | |
| ----- | |
| {current_summary} | |
| ----- | |
| 🚨 **Must Include Block**: | |
| You must include this sentence exactly in your response: | |
| → "{aum_line}" | |
| Then provide your evaluation: | |
| - Comment on forage, degradation, riparian and corridor health | |
| - State whether the plan is ecologically sound | |
| - Suggest improvements if needed | |
| - Keep the tone professional, clear, and grounded in the data | |
| """ | |
| response = client.chat.completions.create( | |
| model="gpt-3.5-turbo", | |
| messages=[{"role": "user", "content": prompt}], | |
| temperature=0.7 | |
| ) | |
| return response.choices[0].message.content | |
| def simulate_and_summarizeold(plan_choice, round_counter, parcel_dict, parcel_map, cluster_labels, n_rows, n_cols, elk_pressure): | |
| # Interpret strategy | |
| strategy_map = { | |
| "conservative": "conservative", | |
| "normal": "moderate", | |
| "aggressive": "aggressive" | |
| } | |
| strategy = strategy_map.get(plan_choice.lower(), "moderate") | |
| # ✅ Reuse incoming parcel_dict — do not reset | |
| simulate_period(parcel_dict, grazing_strategy=strategy, elk_pressure=elk_pressure) | |
| # Extract summary | |
| forage_vals = [p["forage"] for p in parcel_dict.values()] | |
| avg_forage = sum(forage_vals) / len(forage_vals) | |
| degraded_pct = 100 * sum(p["health"] < 0.5 for p in parcel_dict.values()) / len(parcel_dict) | |
| summary = ( | |
| f"After Round {round_counter} with the '{plan_choice}' plan:\n" | |
| f"Avg forage: {avg_forage:.1f} AUMs, Parcels with low health (<0.5): {degraded_pct:.1f}%" | |
| ) | |
| # Generate map visuals | |
| from Sim_Engine import get_forage_map, get_health_map, plot_forage_map, plot_health_map | |
| forage_map = get_forage_map(parcel_dict, n_rows, n_cols) | |
| health_map = get_health_map(parcel_dict, n_rows, n_cols) | |
| plot_forage_map(forage_map, title=f"Forage Map (Round {round_counter})", save_path="forage_map.png") | |
| plot_health_map(health_map, title=f"Health Map (Round {round_counter})", save_path="health_map.png") | |
| return summary, "forage_map.png", "health_map.png", round_counter + 1, parcel_dict | |
| def simulate_and_summarize(plan_choice, round_counter, parcel_map, cluster_labels, n_rows, n_cols, run_full_simulation, history): | |
| strategy_map = { | |
| "conservative": "conservative", | |
| "normal": "moderate", | |
| "aggressive": "aggressive" | |
| } | |
| strategy = strategy_map.get(plan_choice.lower()) | |
| parcel_dict = run_full_simulation(parcel_map, cluster_labels, n_rows, n_cols, strategy=strategy) | |
| plot_forage_map_to_file(parcel_dict, n_rows, n_cols, title=f"Round {round_counter} Forage Map") | |
| # ✅ ADD THIS BLOCK | |
| from Sim_Engine import get_health_map, plot_health_map | |
| health_map = get_health_map(parcel_dict, n_rows, n_cols) | |
| plot_health_map(health_map, title=f"Round {round_counter} Health Map", save_path="health_map.png") | |
| forage_vals = [p["forage"] for p in parcel_dict.values()] | |
| avg_forage = sum(forage_vals) / len(forage_vals) | |
| degraded_pct = 100 * sum(p["degraded"] for p in parcel_dict.values()) / len(parcel_dict) | |
| summary = ( | |
| f"After Round {round_counter} with the '{plan_choice}' plan:\n" | |
| f"Avg forage: {avg_forage:.1f} AUMs, Degraded parcels: {degraded_pct:.1f}%" | |
| ) | |
| return summary, "forage_map.png", "health_map.png", round_counter + 1 | |
| def full_response(plan_choice, essay_text, current_summary): | |
| elk_resp = elk_feedback(plan_choice, current_summary) | |
| usfs_resp = usfs_feedback(plan_choice, essay_text, current_summary) | |
| return elk_resp, usfs_resp | |