> For the complete documentation index, see [llms.txt](https://codefied.gitbook.io/fishcaster/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://codefied.gitbook.io/fishcaster/functional-scope.md).

# Functional Scope

This document explains the backend responsibilities for the Fishing Weather Mobile App, focusing on **API integration**, **data processing**, **scoring logic**, **caching**, and **user management**. Each feature includes **backend tasks**, **conditions**, and **corner cases** to ensure you handle all scenarios correctly. The app helps fishermen predict the best fishing times based on weather forecasts, using **Weatherbit APIs** for data.

***

## 1. Location Selection

### Backend Tasks

* **API Endpoint**: Create an endpoint (e.g., `POST /set-location`) to receive and store the user’s selected location (e.g., city name, ZIP code, or lat/long).
* **Weatherbit API Call**: Convert the location to coordinates (lat/long) if needed (Weatherbit APIs require lat/long). Use Weatherbit’s **Current Weather**, **Hourly Historical**, **Hourly Forecast**, and **Daily Forecast** APIs to fetch weather data for the location.
* **Data Storage**: Store the location in the user’s profile in the database, along with a timestamp of the last API call for that location.

### Conditions

* On first app launch, the user selects a location, triggering an API call.
* Subsequent location changes via the search box trigger new API calls unless cached data is <1 hour old.
* Cache weather data per location to avoid redundant API calls.

### Corner Cases

1. **Invalid Location Input**:
   * If the user enters an invalid location (e.g., gibberish or unsupported format), return a clear error message (e.g., “Invalid location. Please enter a valid city or ZIP code.”).
   * Validate input before calling Weatherbit APIs to avoid unnecessary API costs.
2. **Geocoding Failure**:
   * If Weatherbit’s API cannot resolve the location to lat/long, log the error and return a user-friendly message. Consider integrating a secondary geocoding service (e.g., OpenStreetMap Nominatim) as a fallback.
3. **API Rate Limits**:
   * Weatherbit APIs have rate limits. If exceeded, queue the request and retry after a delay, or return a cached result if available (even if slightly older than 1 hour, but notify the user).
4. **No Cached Data for New Location**:
   * If the user switches to a new location and no cached data exists, immediately trigger API calls for all required data (current, historical, forecast).
5. **User Without Location**:
   * If a user somehow bypasses initial location selection (e.g., app glitch), prompt them to select a location before processing any scoring.

***

## 2. Weather Criteria Selection

### Backend Tasks

* **API Endpoint**: Create endpoints to:
  * Retrieve pre-defined criteria sets (`GET /criteria/predefined`).
  * Save custom criteria sets (`POST /criteria/custom`).
  * List user’s saved criteria (`GET /criteria/user`).
  * Edit/delete custom criteria (`PATCH /criteria/custom/:id`, `DELETE /criteria/custom/:id`).
* **Database Schema**: Store criteria sets in a table/collection with fields:
  * `user_id`: Links to the user.
  * `criteria_id`: Unique identifier.
  * `name`: Criteria name.
  * `type`: “predefined” or “custom”.
  * `variables`: JSON/array of selected variables, criteria ranges, points, and automatic red flags.
* **Scoring Logic**: Calculate the maximum possible points (denominator) for each criteria set based on variable weights.

### Conditions

* Pre-defined criteria (“Best Fishing,” “Comfort and Safety”) have fixed weights (some variables worth 1, 2, or more points).
* Custom criteria allow user-assigned points (1, 2, 3) or automatic red designation.
* Criteria are stored per user and listed in a dropdown for selection.

### Corner Cases

1. **Missing Pre-defined Criteria**:
   * Ensure “Best Fishing” and “Comfort and Safety” are seeded in the database on app setup. If missing, log an error and notify the admin.
2. **Invalid Custom Criteria**:
   * Validate user input (e.g., temperature range must be logical, points must be 1–3). Reject invalid submissions with clear error messages (e.g., “Temperature range must have a valid min and max.”).
3. **Duplicate Criteria Names**:
   * Prevent users from saving multiple criteria with the same name. Check for duplicates per user and return an error (e.g., “Criteria name already exists.”).
4. **Empty Criteria Set**:
   * If a user submits a custom criteria set with no variables selected, reject it with an error (e.g., “At least one variable must be selected.”).
5. **Criteria Deletion Restrictions**:
   * Prevent deletion of pre-defined criteria. Only allow deletion of custom criteria owned by the user.
6. **Points Calculation Error**:
   * If a criteria set has no valid points (e.g., all variables are automatic red), handle gracefully by assigning a default denominator or flagging the set as invalid.

***

## 3. “Hot Fishing” Criteria Creation

### Backend Tasks

* **API Endpoint**: Create an endpoint (`POST /criteria/hot-fishing`) to save current weather conditions as a “Hot Fishing” criteria set.
* **Weatherbit API Call**: Fetch current weather data (unless cached and <1 hour old) to populate the criteria.
* **Data Processing**: Calculate ranges for variables (e.g., ±10°F for temperature, ±40° for wind direction) and store as a criteria set.
* **Database Storage**: Save the criteria with:
  * Default name: Date/time + “Hot Fishing” (e.g., “3/2/25 15:40 Hot Fishing”).
  * User-editable name.
  * Variables and ranges (see document’s “Hot Fishing” table).
* **Deletion Endpoint**: Allow deletion (`DELETE /criteria/hot-fishing/:id`) but not editing.

### Conditions

* Uses Current Weather API data for variables like temperature, barometric pressure, etc.
* Historical Hourly API used for trends (e.g., steady temperature, dropping pressure).
* Only variables met during the “Hot Fishing” moment are included in the denominator for scoring.
* Cached data reused if <1 hour old.

### Corner Cases

1. **Stale Cached Data**:
   * If cached data is >1 hour old, fetch fresh data from Weatherbit. If API call fails, notify the user and fall back to the last cached data (with a warning).
2. **Missing Historical Data**:
   * If Historical Hourly API data is unavailable (e.g., API error), skip trend-based variables (e.g., steady temperature) and exclude them from the denominator.
3. **Invalid Timestamp**:
   * If the phone’s local time is incorrect (e.g., user tampered with device time), use server time for the default name to ensure consistency.
4. **Wind Direction Edge Case**:
   * Wind direction ranges near 0° or 360° (e.g., 30° ± 40° = 350°–70°) require special handling. Add 360° to values as needed to normalize ranges (see document’s wind direction logic).
5. **Duplicate Hot Fishing Names**:
   * Ensure the default name (date/time + “Hot Fishing”) is unique by appending a counter if needed (e.g., “3/2/25 15:40 Hot Fishing #2”).
6. **API Data Gaps**:
   * If Current Weather API returns incomplete data (e.g., missing `wind_dir`), exclude affected variables from the criteria set and log the issue.

***

## 4. Weather Data Integration

### Backend Tasks

* **API Endpoints**: Create endpoints to fetch and cache weather data (`GET /weather/:location`).
* **Weatherbit API Calls**:
  * **Current Weather**: For current period scoring and “Hot Fishing.”
  * **Hourly Historical**: For trends (e.g., previous day’s weather).
  * **Hourly Forecast (240-hour)**: For morning (08:00), mid-day (13:00), evening (18:00) periods.
  * **Daily Forecast (16-day)**: For moonrise, moonset, sunrise, sunset, moon phase.
* **Unit Conversion**:
  * Convert Weatherbit units to app defaults:
    * Temperature: Celsius → Fahrenheit.
    * Barometric pressure: Millibars → Inches of Mercury.
    * Wind speed: Meters/second → MPH.
    * Time: UTC → Local time (based on location’s timezone).
* **Caching**: Store weather data in the database with:
  * `location_id`: Unique identifier for the location.
  * `data_type`: Current, hourly forecast, daily forecast, historical.
  * `timestamp`: When data was fetched.
  * `data`: JSON of Weatherbit response.

### Conditions

* API calls limited to once per hour per location when app is open.
* No API calls when app is closed.
* Optional: Support user-selectable units (e.g., Celsius, km/h) if time permits.

### Corner Cases

1. **API Downtime**:
   * If Weatherbit API is down, use cached data (even if >1 hour old) and notify the user. Log the error for admin review.
2. **Timezone Mismatch**:
   * Ensure UTC-to-local time conversion uses the correct timezone for the location. If timezone data is missing, fall back to a default (e.g., UTC) and log the issue.
3. **Unit Conversion Errors**:
   * Validate Weatherbit data before conversion (e.g., check for null temperature). If invalid, skip the variable and log the error.
4. **Cache Expiry**:
   * If cached data is exactly 1 hour old and the user triggers an update, fetch fresh data but handle partial failures (e.g., only some APIs respond).
5. **Large Data Volume**:
   * Hourly Forecast (240-hour) returns large datasets. Optimize storage by only caching data for 08:00, 13:00, and 18:00 for the next 7 days.
6. **Location Change Mid-Session**:
   * If the user changes location during a session, invalidate old cached data for the previous location and fetch new data, ensuring no stale data is used.

***

## 5. Scoring and Evaluation

### Backend Tasks

* **API Endpoint**: Create an endpoint (`POST /score`) to calculate scores for a given location, criteria set, and time periods (current + 7 days).
* **Scoring Logic**:
  * Fetch weather data (current, forecast, historical) for the location.
  * Compare weather data against criteria variables.
  * Calculate score: `(points_earned / total_possible_points) * 100`.
  * Apply automatic red overrides for safety conditions (e.g., lightning, high winds).
* **Output**: Return scores and color codes for each time period:
  * Score: Integer (e.g., 75 for 75%).
  * Color: Green (≥70%), Yellow (30–69%), Red (<30% or automatic red).
  * Safety Flag: “!” if automatic red.

### Conditions

* Time periods:
  * Current: Uses Current Weather API.
  * Morning: 08:00 hourly forecast.
  * Mid-day: 13:00 hourly forecast.
  * Evening: 18:00 hourly forecast.
* Pre-defined criteria have fixed weights; custom criteria use user-assigned points.
* Historical data required for trends (e.g., temperature change from previous day).
* Denominator excludes variables not applicable (e.g., “Hot Fishing” variables not met at creation).

### Corner Cases

1. **Missing Weather Data**:
   * If a required variable (e.g., `wind_speed`) is missing from Weatherbit, exclude it from scoring and adjust the denominator accordingly.
2. **Automatic Red Override**:
   * If a safety condition (e.g., thunderstorm code 200) is met, set the cell to red with a “!” regardless of the score. Ensure this is checked before finalizing the score.
3. **Zero Denominator**:
   * If no variables are valid (e.g., all excluded due to missing data), return a score of 0% and log the issue.
4. **Historical Data Gaps**:
   * For trends requiring previous day’s data (e.g., steady temperature), if historical data is unavailable, skip the variable and exclude it from the denominator.
5. **Rounding Errors**:
   * Ensure percentage calculations are rounded consistently (e.g., to nearest integer) to avoid UI discrepancies (e.g., 66.7% vs. 67%).
6. **Time Period Misalignment**:
   * If the current time is close to a period boundary (e.g., 07:59 vs. 08:00), ensure the correct period is scored using server time for consistency.

***

## 6. Detailed Score Breakdown

### Backend Tasks

* **API Endpoint**: Create an endpoint (`GET /score-details/:period`) to return detailed scoring data for a specific time period.
* **Data Processing**:
  * Fetch the criteria set and weather data for the period.
  * Generate a table with:
    * Variable name (e.g., “Temperature”).
    * Criteria (e.g., “60–80°F”).
    * Actual weather data (e.g., “75°F”).
    * Match status: True (green font) or False (red font).
    * Safety flag: Red “!” for automatic red variables.
* **Output**: Return the table as JSON for the frontend to render.

### Conditions

* Matches are highlighted in green; non-matches in red.
* Safety-related variables (e.g., thunderstorms) flagged with a red “!” if triggered.

### Corner Cases

1. **Incomplete Weather Data**:
   * If a variable’s weather data is missing, include it in the table with a note (e.g., “Data unavailable”) and mark as non-matching.
2. **Automatic Red Variables**:
   * Ensure safety variables are flagged correctly even if they don’t affect the score (e.g., high winds may not reduce score but still need a “!”).
3. **Criteria Mismatch**:
   * If the criteria set is changed between scoring and requesting details, use the criteria set used for the original score (store score metadata with criteria ID).
4. **Empty Table**:
   * If no variables are applicable (e.g., all excluded), return an empty table with a message (e.g., “No valid criteria for this period.”).

***

## 7. Data Update Mechanism

### Backend Tasks

* **API Endpoint**: Create an endpoint (`POST /update-weather`) to refresh weather data and scores.
* **Logic**:
  * Check the timestamp of cached data for the location.
  * If >1 hour old, fetch fresh data from Weatherbit APIs.
  * If ≤1 hour old, use cached data unless location changed.
  * Recalculate scores for all periods using the selected criteria.

### Conditions

* Updates only triggered by user action (e.g., “Update” button).
* No updates if data is <1 hour old unless location changes.
* Criteria changes use cached data unless >1 hour old.

### Corner Cases

1. **Partial API Failure**:
   * If only some Weatherbit APIs respond (e.g., Current Weather works, but Hourly Forecast fails), cache partial data and use it for scoring, excluding missing variables.
2. **Rapid Update Requests**:
   * If the user spams the “Update” button, throttle requests to prevent multiple simultaneous API calls. Queue or ignore redundant requests.
3. **Location Change During Update**:
   * If the user changes location while an update is processing, cancel the ongoing update and start a new one for the new location.
4. **Cached Data Corruption**:
   * Validate cached data before use. If corrupted (e.g., invalid JSON), fetch fresh data and log the issue.

***

## 8. User-Defined Criteria Interface

### Backend Tasks

* **API Endpoint**: Create an endpoint (`POST /criteria/custom`) to handle form submissions for custom criteria.
* **Validation**:
  * Validate input (e.g., temperature range, points, wind direction selections).
  * Ensure at least one variable is selected.
* **Storage**: Save criteria in the database with user-defined points and automatic red flags.

### Conditions

* Supports variables like temperature, barometric pressure, wind, precipitation, moon phase, etc.
* Users assign points (1, 2, 3) or designate as automatic red.
* Input via sliders, checkboxes, and radio buttons (handled by frontend, validated by backend).

### Corner Cases

1. **Invalid Slider Inputs**:
   * If a slider range is illogical (e.g., max temperature < min), reject with an error (e.g., “Max temperature must be greater than min.”).
2. **Wind Direction Logic**:
   * Validate wind direction selections (e.g., north = 0–23° or 337–360°). Handle edge cases near 0°/360° as described in the document.
3. **Automatic Red Conflicts**:
   * If a variable is marked as automatic red but also assigned points, prioritize the red flag and ignore points for scoring.
4. **Large Criteria Sets**:
   * If a user selects many variables, ensure database storage and scoring performance are optimized (e.g., index criteria fields).
5. **Missing Defaults**:
   * If a radio button (e.g., barometric pressure trend) is not selected, use the default (e.g., steady) and log a warning.

***

## 9. Social Media Sharing

### Backend Tasks

* **API Endpoint**: Create an endpoint (`GET /share`) to generate a shareable snapshot of the main scoring screen.
* **Data Processing**:
  * Fetch current scores and color codes for the user’s location and criteria.
  * Include app download link and website URL (TBD) in the response.
* **Output**: Return JSON with scores, colors, and share template for the frontend to format.

### Conditions

* Triggered by a “Share” button.
* Snapshot includes scores, colors, and promotional content.

### Corner Cases

1. **No Scores Available**:
   * If no scores exist (e.g., user hasn’t selected a location), return an error (e.g., “No data to share. Please select a location and criteria.”).
2. **Missing Website URL**:
   * If the app website URL is TBD, include a placeholder (e.g., “Visit our site for more info”) and log a reminder for admin to update.
3. **Large Data Size**:
   * Ensure the shareable data is compact to avoid issues with social media platforms’ size limits.

***

## 10. User Account Management

### Backend Tasks

* **API Endpoints**:
  * Admin login (`POST /admin/login`).
  * Manage user accounts (`GET /admin/users`, `PATCH /admin/users/:id`, `DELETE /admin/users/:id`).
  * User criteria management (`DELETE /criteria/custom/:id`, `PATCH /criteria/custom/:id`).
* **Authentication**: Implement secure admin authentication (e.g., JWT, OAuth).
* **Database**: Store user accounts with fields:
  * `user_id`: Unique identifier.
  * `email`: For identification.
  * `criteria_sets`: Linked custom criteria.
  * `locations`: Saved locations.

### Conditions

* Admin can view, edit, or delete user accounts.
* Users can delete/rename/modify custom criteria; only delete “Hot Fishing” criteria.

### Corner Cases

1. **Admin Access Abuse**:
   * Restrict admin endpoints to authenticated admin users. Log unauthorized access attempts.
2. **User Data Deletion**:
   * When deleting a user, also delete their custom criteria and cached weather data to free up space.
3. **Concurrent Modifications**:
   * If a user modifies a criteria set while an admin is editing it, use optimistic locking (e.g., version field) to prevent conflicts.
4. **Orphaned Criteria**:
   * If a user is deleted but their criteria remain (e.g., database error), schedule a cleanup job to remove orphaned data.

***

## 11. Information and Support

### Backend Tasks

* **API Endpoint**: Create an endpoint (`GET /info`) to return app instructions, support email, and disclaimer.
* **Storage**: Store static content in the database or a file (provided by app owner).

### Conditions

* Content is static but editable by admin.
* Includes email link for support.

### Corner Cases

1. **Missing Content**:
   * If instructions or disclaimer are missing, return a default message (e.g., “Content under review. Contact support.”) and notify admin.
2. **Large Content Size**:
   * If the disclaimer is lengthy, compress or paginate the response to avoid performance issues.

***

## 12. Data Efficiency

### Backend Tasks

* **Caching Logic**: Implement a caching layer (e.g., Redis, database table) for weather data.
* **API Call Throttling**: Enforce 1-hour minimum between API calls per location.
* **Data Cleanup**: Periodically remove stale cached data (e.g., >24 hours old).

### Conditions

* No API calls when app is closed.
* Cached data reused for criteria changes unless >1 hour old.
* “Hot Fishing” and “Update” use cached data unless >1 hour old.

### Corner Cases

1. **Cache Overload**:
   * If cache grows too large (e.g., many users, locations), implement a least-recently-used (LRU) eviction policy.
2. **Clock Skew**:
   * If server time differs from Weatherbit’s, use server time for caching decisions to ensure consistency.
3. **API Cost Overruns**:
   * Monitor API call frequency. If nearing Weatherbit’s billing limits, alert admin and throttle non-essential calls.
4. **Stale Cache on Restart**:
   * After a server restart, validate cached data timestamps to prevent using outdated data.

***

## 13. Safety Indicators

### Backend Tasks

* **Logic**: Check for automatic red conditions (e.g., thunderstorm codes 200–233, wind speed > threshold) during scoring.
* **Output**: Include safety flags (“!”) in score and detail responses for affected periods/variables.

### Conditions

* Automatic red overrides score-based color (e.g., 75% score but lightning → red).
* Safety variables flagged in detailed breakdown.

### Corner Cases

1. **Mixed Safety Conditions**:
   * If multiple safety conditions are met (e.g., lightning and high winds), ensure all are flagged in the detailed breakdown.
2. **False Negatives**:
   * If Weatherbit data is missing for a safety variable (e.g., no weather code), assume safe unless confirmed otherwise, but log the issue.
3. **User-Defined Safety**:
   * If a user marks a non-safety variable as automatic red (e.g., low temperature), treat it as a safety condition but log for review.

***

## General Backend Guidelines

* **Error Handling**: Always return user-friendly error messages and log detailed errors for debugging.
* **Logging**: Log all API failures, invalid inputs, and unexpected states for admin review.
* **Performance**: Optimize database queries and API calls to handle multiple users/locations.
* **Security**: Sanitize all user inputs to prevent SQL injection or XSS. Use HTTPS for API endpoints.
* **Testing**: Write unit tests for scoring logic, caching, and API integrations. Test corner cases explicitly.

***

## Next Steps

1. **Set Up Environment**: Choose a backend framework (e.g., Node.js Express) and database.
2. **API Integration**: Test Weatherbit API calls and handle authentication (API key).
3. **Implement Caching**: Set up a caching layer (e.g., Redis or database table).
4. **Build Scoring Logic**: Start with pre-defined criteria, then add custom and “Hot Fishing” logic.
5. **Test Corner Cases**: Use mock data to simulate API failures, invalid inputs, and edge cases.
6. **Document APIs**: Create API documentation (e.g., OpenAPI/Swagger) for frontend integration.

If you have questions about any feature or corner case, ask before coding to avoid rework. Let’s review progress after implementing the first endpoint!
