Skip to content

refactor: Clean Architecture + SOLID - New decoders, comprehensive tests, and bilingual docs#59

Merged
afonsoft merged 1 commit into
mainfrom
devin/1777838779-clean-architecture-solid
May 4, 2026
Merged

refactor: Clean Architecture + SOLID - New decoders, comprehensive tests, and bilingual docs#59
afonsoft merged 1 commit into
mainfrom
devin/1777838779-clean-architecture-solid

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

Summary

Reorganization of the codebase following Clean Architecture and SOLID principles, with new METAR decoders, comprehensive unit tests, version updates, and bilingual documentation.

All Submissions:

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same update/change?

New Feature Submissions:

  1. Does your submission pass tests?
  2. Have you lint your code locally prior to submission?

Changes to Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully ran tests with your changes locally?

Changes

Namespace & Naming Fixes (Clean Architecture)

  • Fixed namespace casing across all projects:
    • Taf.Decoder.chunkdecoderTaf.Decoder.ChunkDecoder
    • Taf.Decoder.entityTaf.Decoder.Entity
    • Metar.Decoder.ChunkdecoderMetar.Decoder.ChunkDecoder
    • Metar.Decoder_testsMetar.Decoder.Tests
    • Taf.Decoder_testsTaf.Decoder.Tests
  • Renamed BaseEntity.csAbstractEntity.cs (clearer naming)
  • Fixed method naming: checkValidity()CheckValidity() (C# convention)

SOLID Improvements

  • Made DecodedMetar and DecodedTaf constructors public (testability, Dependency Inversion)
  • Fixed unqualified namespace references (entity.DecodedTaf.TafTypeDecodedTaf.TafType)

New METAR Decoders

  • TrendChunkDecoder: Parses NOSIG, BECMG, TEMPO trend forecasts
  • RemarkChunkDecoder: Parses RMK section and extracts SLP (Sea Level Pressure)
  • New DecodedMetar properties: TrendType, TrendForecast, Remark, SeaLevelPressure

Version Updates

  • Metar.Decoder: 1.0.81.0.9
  • Taf.Decoder: 1.0.61.0.7

Comprehensive Unit Tests

  • MetarDecoderComprehensiveTest: 50+ test cases covering CAVOK, variable wind, gusts, multiple cloud layers, CB/TCU types, vertical visibility, US visibility (SM), mercury pressure (A format), negative temperatures, wind shear, RVR variability, multiple weather phenomena, SPECI/COR types, real-world METARs, value conversions
  • TrendChunkDecoderTest: Tests for NOSIG, BECMG, TEMPO parsing
  • RemarkChunkDecoderTest: Tests for RMK and SLP extraction
  • TafDecoderComprehensiveTest: 45+ test cases covering TAF/AMD/COR/RTD types, CAVOK, variable wind, gusts, multiple clouds, CB/TCU, vertical visibility, US/fractional visibility, weather phenomena, TEMPO/BECMG/FM/PROB evolutions, temperature forecasts, MPS/KPH units, strict/non-strict modes, real-world TAFs

Bilingual Documentation

  • docs/en-us/MetarDecoder-Guide.md - English usage guide
  • docs/en-us/TafDecoder-Guide.md - English usage guide
  • docs/pt-br/MetarDecoder-Guia.md - Portuguese usage guide
  • docs/pt-br/TafDecoder-Guia.md - Portuguese usage guide

Each guide includes: installation, quick start, all decoded fields with code examples, error handling, architecture overview, supported elements table, and glossary.

Test Results

  • 352 tests passing (out of 354 total)
  • 2 pre-existing failures: 311200Z CCC datetime test (date-dependent, fails when current month has fewer than 31 days - not related to this PR)

Link to Devin session: https://app.devin.ai/sessions/89ccd2ed34dc400a9604ec2988149399
Requested by: @afonsoft

…sts, and docs

Changes:
- Fix namespace casing across all projects (ChunkDecoder, Entity, Tests)
- Rename BaseEntity.cs to AbstractEntity.cs
- Fix method naming: checkValidity -> CheckValidity
- Make DecodedMetar and DecodedTaf constructors public (SOLID)
- Add TrendChunkDecoder (NOSIG/BECMG/TEMPO) for METAR
- Add RemarkChunkDecoder (RMK/SLP) for METAR
- Add new properties to DecodedMetar: TrendType, TrendForecast, Remark, SeaLevelPressure
- Update Metar.Decoder version to 1.0.9
- Update Taf.Decoder version to 1.0.7
- Add MetarDecoderComprehensiveTest with 50+ test cases
- Add TrendChunkDecoderTest and RemarkChunkDecoderTest
- Add TafDecoderComprehensiveTest with 45+ test cases
- Add bilingual documentation (en-us and pt-br) for both libraries

Co-Authored-By: Afonso Dutra Nogueira Filho <afonsoft@gmail.com>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@afonsoft
Copy link
Copy Markdown
Owner

afonsoft commented May 4, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
🔚 Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 4, 2026

{
var result = decoder.Parse("RMK AO2 SLP013 T00720044 ");
var decoded = result[MetarDecoder.ResultKey] as Dictionary<string, object>;
ClassicAssert.IsTrue(decoded.ContainsKey(RemarkChunkDecoder.RemarkParameterName));
{
var result = decoder.Parse("RMK AO2 SLP013 T00720044 ");
var decoded = result[MetarDecoder.ResultKey] as Dictionary<string, object>;
ClassicAssert.IsTrue(decoded.ContainsKey(RemarkChunkDecoder.SeaLevelPressureParameterName));
{
var result = decoder.Parse("RMK SLP982 ");
var decoded = result[MetarDecoder.ResultKey] as Dictionary<string, object>;
var slp = (Value)decoded[RemarkChunkDecoder.SeaLevelPressureParameterName];
{
var result = decoder.Parse("SOMETHING ");
var decoded = result[MetarDecoder.ResultKey] as Dictionary<string, object>;
ClassicAssert.IsFalse(decoded.ContainsKey(RemarkChunkDecoder.RemarkParameterName));
{
var result = decoder.Parse("NOSIG ");
var decoded = result[MetarDecoder.ResultKey] as Dictionary<string, object>;
ClassicAssert.AreEqual("NOSIG", decoded[TrendChunkDecoder.TrendTypeParameterName]);
{
var result = decoder.Parse("BECMG 24010KT ");
var decoded = result[MetarDecoder.ResultKey] as Dictionary<string, object>;
ClassicAssert.AreEqual("BECMG", decoded[TrendChunkDecoder.TrendTypeParameterName]);
{
var result = decoder.Parse("TEMPO 3000 BR ");
var decoded = result[MetarDecoder.ResultKey] as Dictionary<string, object>;
ClassicAssert.AreEqual("TEMPO", decoded[TrendChunkDecoder.TrendTypeParameterName]);
{
var result = decoder.Parse("SOMETHING ");
var decoded = result[MetarDecoder.ResultKey] as Dictionary<string, object>;
ClassicAssert.IsFalse(decoded.ContainsKey(TrendChunkDecoder.TrendTypeParameterName));
public void TestParseMetarWithWindShearAllRunways()
{
var d = decoder.ParseNotStrict("METAR LFPO 231027Z 24004KT 9999 FEW020 17/10 Q1009 WS ALL RWY ");
ClassicAssert.IsTrue(d.WindshearAllRunways.Value);
@afonsoft afonsoft merged commit ff695dd into main May 4, 2026
16 of 20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants