# SHARK4R 1.2.0

## New features

* Added `calc_zooplankton_dry_weight()` to calculate zooplankton dry weight from `"Length (mean)"` using AphiaID-based taxa-specific coefficients from `inst/extdata/Mesozooplankton_Kattegat_Skagerrak_taxa_and_biomass_calculations.xlsx`. The function uses adult coefficients for non-`NP` stages, taxon-specific nauplii coefficients where available, and otherwise falls back to the general copepod nauplii coefficients.
* Added `calc_zooplankton_biomass()` to calculate zooplankton biomass concentration (`mg/m3`) from `"Abundance"` and integrated biomass (`mg/m2`) from `"Integrated abundance"` by combining abundance with per-individual dry weight on the SHARK observation key (`platform_code`, `station_name`, `sample_date`, `sample_time`, `sample_min_depth_m`, `sample_max_depth_m`, `aphia_id`, `sex_code`, `dev_stage_code`, `size_class`). If dry-weight rows are not present, they are calculated internally via `calc_zooplankton_dry_weight()`.
* Added `create_pie_map()`, a general-purpose pie chart map for station data with automatic pie displacement and leader lines to prevent overlap in crowded regions. Works with any grouping (phytoplankton groups, zooplankton orders, microbial phyla, ...) and any numeric value (biomass, biovolume, abundance, ...). The optional default coastline basemap uses `rnaturalearth` (Suggests); HTML-formatted legend labels use `ggtext` (Suggests).
* The `shark-qc` Shiny app has been rebuilt on `bslib` (Bootstrap 5) for a modernized UI, with improved server-side error handling so transient failures surface as user-facing notifications instead of crashing the session.

## Minor improvements and fixes

* `get_toxin_list()` gains an `insecure` argument (default `FALSE`) to handle periods when the IOC-UNESCO Toxins Database TLS certificate has lapsed. When a certificate error is encountered, an interactive session prompts before retrying without verification, while a non-interactive session aborts with guidance to set `insecure = TRUE`. Disabling verification emits a warning, as it removes protection against tampering.
* All user-facing console output has been migrated from base R (`stop()`, `warning()`, `message()`, `cat()`, `txtProgressBar`) to the `cli` package. Errors use `cli_abort()`, warnings use `cli_warn()`, and informational messages use `cli_inform()`, all with structured bullet lists and inline markup for arguments, values, file paths, and function names. Progress bars in long-running API functions are replaced with `cli_progress_bar()`.
* Threshold values previously defined in `R/zzz.R` are now bundled as `inst/extdata/threshold_values.csv` and loaded at runtime, removing several package-level global variables.
* All internal cache paths now consistently redirect to `tempdir()` during `R CMD check`, extending the `cache_dir()` redirect to the remaining call sites in `R/util.R`.
* Removed unused arguments from defunct functions in `R/defunct.R` and updated their documentation accordingly.
* CI workflow updated to install required spatial libraries and configure PROJ on the macOS runner.
* Bumped GitHub Actions to versions running on Node.js 24 to clear the Node 20 deprecation warnings: `actions/checkout@v6`, `actions/upload-artifact@v7`, `codecov/codecov-action@v6`, and `JamesIves/github-pages-deploy-action@v4.8.0`.

# SHARK4R 1.1.1

## CRAN compliance

* All vignettes that call external APIs now use a hidden availability check followed by `try()`-protected execution chunks, so transient server errors (502, 503, 500) never cause vignette rebuild failures. The user-facing code shown on pkgdown remains clean and uncluttered.
* Added `skip_if_offline()` and `skip_if_resource_unavailable()` guards to previously unprotected tests for deprecated WoRMS wrappers (`match_wormstaxa`, `update_worms_taxonomy`) and the empty/NA input edge case (`match_worms_taxa(c("", NA))`).
* Added `skip_on_cran()` to deprecated WoRMS wrapper tests, since the base-URL availability check can pass while individual API endpoints return server errors.
* Added `skip_if_offline()` to the `"wrong url fails"` test in `test-xylookup.R`.

# SHARK4R 1.1.0

## New features

* Added `get_nua_media_metadata()` to retrieve detailed metadata for media items from Nordic Microalgae
* Added `get_nua_image_labeling_links()` to retrieve media URLs for automated imaging images (e.g., IFCB) from Nordic Microalgae
* Added `get_nua_image_labeling_metadata()` to retrieve detailed metadata for automated imaging images from Nordic Microalgae

## Security improvements

* `load_shark4r_fields()` now downloads field definitions as a binary `.rds` file instead of sourcing a remote R script, eliminating a remote code execution risk.
* `get_shark_data()` now validates that `file_path` does not contain `..` path components, preventing path traversal when used in downstream applications.
* `get_shark_datasets()` now sanitizes dataset names from the API with `basename()` before writing to disk.

## Bug fixes and CRAN compliance

* Fixed species not getting properly matched in `match_algaebase_taxa()`. The join between API results and input data used `left_join(by = c("genus", "species"))`, which silently dropped results when AlgaeBase returned a reclassified genus (e.g., querying "Chlorella" but API returns "Auxenochlorella"). (Part of #47)
* Fixed `match_algaebase_genus()` returning unrelated genera when `exact_matches_only = TRUE`. A variable shadowing bug inside `tibble()` caused the `input_match` column to always equal 1, making the exact match filter ineffective. For example, querying "Nitzschia" returned 7 genera (Cymbellonitzschia, Pseudo-nitzschia, etc.) instead of just Nitzschia. (Part of #47)
* Fixed genus column collision in `match_algaebase_species()`. When higher taxonomy was requested, `genus = genus_taxonomy$genus` was included in the taxonomy tibble, which could overwrite the species-level genus value. (Part of #47)
* Removed genus fallback in `match_algaebase_taxa()` for species-level queries. Previously, when a species was not found in AlgaeBase, the function fell back to a genus-level query. This produced misleading results where a species record linked to an unrelated genus page. Species queries that fail now return NA instead. (Part of #47)
* Fixed `get_dyntaxa_records()` silently returning a character string on API error instead of raising a condition with `stop()`.
* Fixed `get_shark_data()` silently dropping `municipalities`, `waterCategories`, and `typOmraden` parameters when computing the pre-download row count, which could bypass the chunked download path.
* Fixed operator precedence bug `nrow(genus > 0)` to `nrow(genus) > 0` in `construct_dyntaxa_missing_table()`.
* Replaced unsafe `1:length()` and `1:nrow()` loops with `seq_along()` and `seq_len()` in `construct_dyntaxa_missing_table()` and `construct_dyntaxa_table()` to prevent errors on zero-length input.
* Replaced `message("ERROR: ...")` calls with `warning()` in `check_value_logical()`, `check_zero_value()`, `check_zero_positions()`, `check_codes()`, and `read_shark_deliv()` so conditions can be caught programmatically with `tryCatch()`.
* Removed duplicate `cachefile` assignment in `cache_call()` and dead `list.files()` call in `list_cache()`.
* All internal cache paths now use the `cache_dir()` helper, which redirects to `tempdir()` during R CMD check. Previously several functions called `tools::R_user_dir()` directly, which could create `~/.cache/R/SHARK4R` during CRAN checks.
* Fixed evaluation order bug in `clean_shark4r_cache()` where `search_pattern = NULL` (the default) could cause an error.
* Fixed deprecation warning version numbers in algaebase functions (now correctly reference `1.0.0`).
* Fixed spelling of "Microalgae" and other minor typos in `get_hab_list()` documentation.
* `get_hab_list()` updated to wrap inline text with `I()` in `readr::read_delim()` for `readr` ≥ 2.2.0 compatibility and to remove deprecation warnings.
* Tests that depend on the OBIS xylookup API now skip correctly when the endpoint returns a server error. Previously, the availability check targeted the base URL (`https://api.obis.org/`) which could return 200 while the `/xylookup` endpoint itself returned 500.
* All `\donttest{}` examples that call external APIs are now wrapped with `try()` so that transient service outages do not cause `R CMD check --run-donttest` failures.
* The `quality_control` vignette now wraps OBIS-dependent calls (`check_onland()`, `check_depth()`) in `tryCatch()` so the vignette builds even when the API is unavailable.

# SHARK4R 1.0.3

## New features

* Added a new `harmful_non_toxic_only` argument to `get_hab_list()` to download only non-toxigenic harmful microalgal species from the IOC-UNESCO HABs list
* Added a new `species_only` argument to `get_hab_list()` to return only species-level records, which is now also the default option. This filter is ignored when `harmful_non_toxic_only = TRUE`
* Added a new `verbose` argument to `positions_are_near_land()` and `get_hab_list(harmful_non_toxic_only = TRUE)` to enable printing of progress messages during data retrieval

## Minor improvements and fixes

* EEA coastline data are now obtained from EEA map services in `positions_are_near_land()`, replacing direct file server downloads that were unstable
* All data frame outputs are now consistently returned as tibbles
* Documentation updated with minor clarifications and corrections

# SHARK4R 1.0.2

## Bug fixes

* `SHARK4R:::.type_lookup` now includes the missing datatype `Jellyfish` (#39)
* Enhanced documentation and example execution in vignettes - updated examples to run correctly and improved clarity in vignettes and help files
* HTML widgets and interactive objects are now displayed only in pkgdown articles; they are suppressed in CRAN vignettes to reduce size and improve build safety
* Added tests for helper functions – covering `extract_complete_toxins()` and `repair_toxins_json()`
* Cache is now cleared after R CMD check

# SHARK4R 1.0.1

## Bug fixes and CRAN compliance

* Corrected formatting of package and software names throughout the package.
* Fixed broken URL in `README.md`
* Improved examples to run reliably and quickly
* Ensured functions and examples no longer write to the user's home directory
* Added `lon` and `lat` arguments to the `lookup_xy()` function for more flexible lookup options
* Minor documentation improvements throughout the package
* `get_toxin_list()` now handles partial JSON responses

# SHARK4R 1.0.0

## New features
* Add new functions: `get_delivery_template()` and `find_required_fields()` to get SHARK delivery templates and required fields from the web
* Add new function `get_shark_datasets()` to retrieve available SHARK datasets from API
* Add new function `get_nomp_list()` to download and read the latest NOMP biovolume Excel lists
* Add new function `get_peg_list()` to download and read the PEG biovolume Excel list
* Add new function `read_ptbx()` to read Plankton Toolbox files
* Add new function `get_shark_codes()` to download and read the current SHARK code lists
* Add new function `clean_shark4r_cache()` to clear cached files
* Add new function `check_setup()` and `run_qc_app()` to download and run SHARK QC scripts and Shiny App
* Add new function `get_shark_statistics()` to download SHARK data and extract summary statistics for numeric parameters
* Add new function `translate_shark_datatype()` to translate user-facing datatype names to internal SHARK4R names
* Add new function `load_shark4r_stats()` to download and load precomputed SHARK4R statistical datasets (e.g., threshold or summary statistics) from a GitHub repository
* Add new function `load_shark4r_fields()` to download and load fields definitions from a GitHub repository
* Add new function `get_worms_classification()` to retrieve higher taxonomic information from WoRMS records
* Add new function `get_worms_taxonomy_tree()` to retrieve and constructs a hierarchical taxonomy tree from WoRMS records
* Add new function `convert_ddmm_to_dd()` to convert coordinates from DDMM format to decimal degrees

## Enhancements
* Re-export functions from the `iRfcb` package: `which_basin()` and `positions_are_near_land()`
* Cache downloaded DwCA files in `get_dyntaxa_dwca()`, `get_shark_codes()`, `get_nomp_list()` and `get_peg_list()` to avoid repeated downloads
* Add unit tests for the majority of the package functions
* Update and correct `check_depth()`
* Fix bugs in check_* functions
* Fix various documentation issues
* Updated several OBIS-dependent functions using `lookup_xy()`
* Updated `scatterplot()` function to allow plotting of multiple parameters
* Updated `match_worms_taxa()` function to clean taxon names from problematic special characters before being passed to API call
* Added `plot_leaflet` argument to functions `check_station_distance()` and `check_onland()`
* Added `utv` argument to functions `get_shark_options()`, `get_shark_data()`, `get_shark_datasets()` and `get_shark_table_counts()`.
* Added `add_rank_to_hierarchy` argument to the `add_worms_taxonomy()` function
* `match_worms_taxa()` now handles bulk API requests using the `bulk` argument
* Add SHARK4R Bio-QC Tool Shiny App to bundle, with improved performance (initialized by `run_qc_app()`)

## Deprecated
* Deprecated functions: `ifcb_is_near_land()` and `ifcb_which_basin()` (replaced by re-exported functions with improved cache behavior)
* Deprecated functions: `get_algaebase_species()`, `get_algaebase_genus()` and `match_algaebase()` are now replaced by `match_algaebase_species()`, `match_algaebase_genus()` and `match_algaebase_taxa()`
* Deprecated functions: Parameter and datatype-specific `check_*_*_logical()` functions replaced by general functions `check_parameter_rules` and `check_logical_parameter()` function
* Deprecated functions: Datatype-specific field check functions `check_*()` and `check_*_deliv()` replaced by a general `check_fields()` function
* Deprecated functions: Parameter and datatype-specific `check_*_*()` functions to check for outliers replaced by a general `check_outliers()` function
* Deprecated functions: `shark_read_deliv()` and `shark_read_deliv_xls()` are now replaced by `read_shark_deliv()`
* Deprecated functions: `shark_read()` and `shark_read_zip()` are now replaced by `read_shark()`
* Deprecated function: `match_dyntaxa()` is now replaced by `is_in_dyntaxa()`
* Deprecated function: `plot_map_leaflet_deliv()` is now replaced by `plot_map_leaflet()`
* Deprecated function: `check_code_proj()` is now replaced by `check_codes()`
* Deprecated function: `match_taxon_name()` is now replaced by `match_dyntaxa_taxa()`
* Deprecated function: `get_worms_records_name()` is now replaced by `match_worms_taxa()`
* Deprecated function: `nominal_station()` is now replaced by `check_nominal_station()`
* Deprecated function: `match_wormstaxa()` is now replaced by `match_worms_taxa()`
* Deprecated argument: `apikey` replaced by `subscription_key` in `get_algaebase_genus()`, `get_algaebase_species()` and `match_algaebase()`
* Deprecated argument: `aphia_id` replaced by `aphia_ids` in `get_worms_records()` and `add_worms_taxonomy()`
* Deprecated argument: `scientific_name` replaced by `scientific_names` in `add_worms_taxonomy()` and `parse_scientific_names()`
* Deprecated argument: `genus` replaced by `genera` in `match_algaebase_taxa()`

## Defunct / Removed
* Defunct function `get_shark_table()`

## Documentation
* Add `NEWS.md` file
* Add spell check

# SHARK4R 0.1.7

* Add option to specify `row_limits` in `get_shark_data()` to retrieve data in yearly chunks
* Add functions to call APIs to retrieve IOC HAB and IOC IPHAB Toxin lists: `get_hab_list()` and `get_toxin_list()`

# SHARK4R 0.1.6

Patch release

* Fix issue #16
* Add unparsed output option for `get_shark_option()`

# SHARK4R 0.1.5

Patch release

* Fix issues with `construct_dyntaxa_table()`
* Fix parsing issue in `get_shark_data()`
* Add more custom groups to `assign_plankton_group()`
* Add more flexibility to `get_shark_data()` parameters, e.g. boundary and year ranges

# SHARK4R 0.1.4

* Add algaebase API functions
* Defunct sharkdata functions
* Fix parsing issue in shark_data when data are reported as "-", which is now a NA pattern
* Cleanup of large files
* UTF-8 encoding

# SHARK4R 0.1.3

* Minor bug-fixes and updated documentation

# SHARK4R 0.1.2

* Patch release

# SHARK4R 0.1.1

* Fix download of large datasets
* Add more WoRMS functionality, including plankton group assignment

# SHARK4R 0.1.0

* Add SHARK API functionality
* Improve Dyntaxa API functionality
* Fix documentation issues

# SHARK4R 0.0.1

* Initial development version.
