{
  "agency": {
    "country": "PT",
    "id": "transtejo-soflusa",
    "name": "Transtejo Soflusa (TTSL)",
    "operating_note": "One official ferry feed with five routes connecting Lisboa and Set\u00fabal terminals across the Tagus. Counted as one feed record.",
    "subdivision_code": "PT-11",
    "subdivision_name": "Lisboa"
  },
  "categories": {
    "completeness": {
      "details": {
        "accessibility": {
          "measures": "presence_not_usability",
          "score": 100.0,
          "stops_marked_accessible_pct": 100.0,
          "stops_marked_not_accessible_pct": 0.0,
          "stops_stated_pct": 100.0,
          "trips_stated_pct": 100.0
        },
        "accessibility_measures": "presence_not_usability",
        "cemv": {
          "declared": false,
          "supported": false
        },
        "components": {
          "contact": 15.0,
          "fares": 15.0,
          "headsigns": 15.0,
          "stop_names": 15.0,
          "wheelchair_stops": 25.0,
          "wheelchair_trips": 15.0
        },
        "fare_free": false,
        "fares": {
          "applied": true,
          "has_leg_rules": false,
          "has_products": false,
          "has_transfer_rules": false,
          "model": "legacy",
          "product_count": 0
        },
        "flex": {
          "booking_reachable": false,
          "booking_rule_count": 0,
          "has_booking_rules": false,
          "has_flex": false
        },
        "has_fares": true,
        "headsign_applicable_trips": 938,
        "headsign_loop_exempt_trips": 0,
        "headsign_pct": 100.0,
        "headsign_scored_pct": 100.0,
        "mixed_case_stop_name_pct": 100.0,
        "pathways": {
          "has_entrances": false,
          "has_levels": false,
          "has_pathways": false,
          "has_stations": false,
          "has_step_free": false,
          "pathway_count": 0
        },
        "stops": 10,
        "translations": {
          "feed_lang": "PT",
          "has_translations": false,
          "languages": [],
          "translated_tables": [],
          "translation_count": 0
        },
        "trips": 938,
        "unmeasured_components": [],
        "wheelchair_accessible_pct": 100.0,
        "wheelchair_boarding_pct": 100.0,
        "wheelchair_marked_accessible_pct": 100.0,
        "wheelchair_marked_not_accessible_pct": 0.0
      },
      "findings": [],
      "name": "completeness",
      "score": 100.0,
      "status": "measured",
      "summary": "100% of terminals state wheelchair accessibility (100% marked accessible, 0% marked not accessible). This measures what the feed publishes, not whether a terminal is physically usable. Fare data is published.",
      "weight": 0.25
    },
    "correctness": {
      "details": {
        "distinct_codes": 4,
        "instances_by_severity": {
          "ERROR": 0,
          "INFO": 67,
          "WARNING": 0
        },
        "validator_version": "8.0.1"
      },
      "findings": [
        {
          "code": "service_extends_far_in_the_future",
          "count": 28,
          "effort": "Varies.",
          "fix": "Review the rule documentation for 'service_extends_far_in_the_future' at https://gtfs-validator.mobilitydata.org/rules.html and check the flagged rows in your feed.",
          "owner": "",
          "points": 0.8,
          "severity": "INFO",
          "what": "Service extends far in the future (flagged by the MobilityData validator).",
          "why": "See the linked rule for what this affects."
        },
        {
          "code": "service_window_outside_feed_period",
          "count": 28,
          "effort": "Two fields in feed_info.txt, or one export setting.",
          "fix": "Widen feed_start_date and feed_end_date to cover all service dates, or fix the dates that fall outside.",
          "owner": "Likely your export tool",
          "points": 0.8,
          "severity": "INFO",
          "what": "Some service dates fall outside the date window set in feed_info.txt.",
          "why": "feed_info.txt should span every day your service runs, so apps know when the data applies."
        },
        {
          "code": "unknown_column",
          "count": 10,
          "effort": "A quick look at the flagged files.",
          "fix": "Check the flagged column names for misspellings of standard GTFS fields; remove them if they are vendor extras.",
          "owner": "",
          "points": 0.8,
          "severity": "INFO",
          "what": "Some files contain columns that are not part of the GTFS spec.",
          "why": "Harmless to riders, but apps ignore these columns and they can hide typos in real column names."
        },
        {
          "code": "unknown_file",
          "count": 1,
          "effort": "A quick look at the flagged file.",
          "fix": "Check the flagged file name for a typo of a standard GTFS file. Remove it if it is a vendor extra.",
          "owner": "",
          "points": 0.5,
          "severity": "INFO",
          "what": "The feed includes a file that is not part of the GTFS spec.",
          "why": "Apps ignore files they don't know, and a stray file can hide a misspelled standard file name."
        }
      ],
      "name": "correctness",
      "score": 97.2,
      "status": "measured",
      "summary": "The MobilityData validator flagged 4 kinds of issue across 67 instances (0 error, 0 warning, 67 informational).",
      "weight": 0.35
    },
    "freshness": {
      "details": {
        "days_until_expiry": 335,
        "effective_expiry_date": "2027-08-01",
        "feed_end_date": "2027-08-01",
        "feed_start_date": "2026-08-16",
        "feed_version": "20260816",
        "has_feed_info": true,
        "last_service_date": "2028-12-31",
        "seasonal_boundary": false,
        "service_horizon_review_years": 10,
        "service_horizon_status": "within_review_threshold",
        "service_type": "fixed"
      },
      "findings": [],
      "name": "freshness",
      "score": 100.0,
      "status": "measured",
      "summary": "Service data covers the next 335 days.",
      "weight": 0.2
    },
    "realtime": {
      "name": "realtime",
      "status": "not_yet_measured",
      "summary": "Not scored yet. Nothing here counts against the grade.",
      "weight": 0.2
    }
  },
  "confidence": {
    "feed_age_days": 0,
    "fetch_source": "mirror",
    "level": "provisional",
    "measured_categories": 3,
    "notes": [
      "Realtime quality was not measured this run. It does not count against the grade.",
      "The official feed URL on file was unreachable, so the Mobility Database's hosted mirror copy was scored instead."
    ],
    "rt_windows": 0,
    "total_categories": 4
  },
  "conformance": {
    "awarded": true,
    "criteria": [
      {
        "detail": "Passes validation with no errors.",
        "key": "valid",
        "met": true
      },
      {
        "detail": "Service data covers the next 335 days.",
        "key": "current",
        "met": true
      },
      {
        "detail": "States wheelchair access on 100% of terminals and 100% of trips.",
        "key": "accessible",
        "met": true
      }
    ],
    "status": "awarded",
    "summary": "This feed earns the conformance mark: valid, current, and stating wheelchair access on nearly every terminal and trip.",
    "version": 2
  },
  "feed": {
    "license_note": "CC0 through Portugal's public-administration open-data catalog; attribution is not legally required, but GTFS Scorecard credits TTSL as the source.",
    "reachable": true,
    "sha256": "a897a332ed020f8636784c91a87685174d06d946c95a82dd8c9935634ff0ae8d",
    "size_bytes": 20250,
    "source_provenance": "official",
    "static_url": "https://api.transtejo.pt/files/GTFS.zip"
  },
  "ferry_profile": {
    "accessibility": {
      "measures": "published_values_not_physical_usability",
      "terminals": {
        "allowed_count": 10,
        "allowed_pct": 100.0,
        "not_allowed_count": 0,
        "not_allowed_pct": 0.0,
        "stated_count": 10,
        "stated_pct": 100.0,
        "total_count": 10
      },
      "trips": {
        "allowed_count": 938,
        "allowed_pct": 100.0,
        "not_allowed_count": 0,
        "not_allowed_pct": 0.0,
        "stated_count": 938,
        "stated_pct": 100.0,
        "total_count": 938
      }
    },
    "bikes": {
      "allowed_count": 938,
      "allowed_pct": 100.0,
      "not_allowed_count": 0,
      "not_allowed_pct": 0.0,
      "stated_count": 938,
      "stated_pct": 100.0,
      "total_count": 938
    },
    "cars": {
      "allowed_count": 0,
      "allowed_pct": 0.0,
      "not_allowed_count": 0,
      "not_allowed_pct": 0.0,
      "stated_count": 0,
      "stated_pct": 0.0,
      "total_count": 938
    },
    "fares": {
      "applied": true,
      "fare_free": false,
      "model": "legacy",
      "scope": "whole_feed"
    },
    "graded": false,
    "measured": true,
    "realtime": {
      "configured_kinds": [],
      "kinds_configured": 0,
      "scope": "whole_feed"
    },
    "route_count": 5,
    "scope": "ferry_routes_and_trips",
    "stop_access": {
      "direct_count": 0,
      "eligible_terminal_count": 0,
      "stated_count": 0,
      "stated_pct": null,
      "through_station_count": 0
    },
    "terminal_hierarchy": {
      "boarding_location_count": 10,
      "parented_boarding_location_count": 0,
      "parented_boarding_location_pct": 0.0,
      "referenced_station_count": 0
    },
    "trip_count": 938
  },
  "fetch": {
    "final_url": "https://files.mobilitydatabase.org/mdb-2921/latest.zip",
    "max_attempts": 1,
    "origin_error": "SSLError",
    "reader_archive_profile": "raw-v1",
    "source": "mirror",
    "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
  },
  "generated_at": "2026-08-30T00:00:00+00:00",
  "geo": {
    "bbox": [
      -9.231,
      38.6476,
      -9.006,
      38.707
    ],
    "lat": 38.6911,
    "lon": -9.14675,
    "stop_count": 10
  },
  "mode_profile": {
    "ferry_only": true,
    "graded": false,
    "has_ferry": true,
    "is_multimodal": false,
    "measured": true,
    "modes": [
      {
        "key": "ferry",
        "label": "Ferry",
        "route_count": 5,
        "trip_count": 938,
        "trip_share_pct": 100.0
      }
    ],
    "primary_mode": "ferry",
    "primary_mode_label": "Ferry",
    "route_count": 5,
    "trip_count": 938
  },
  "overall": {
    "grade": "A",
    "margin_to_lower_band": 8.8,
    "margin_to_next_band": null,
    "score": 98.8
  },
  "recommendations": [
    {
      "category": "accessibility",
      "code": "scorecard_route_color_low_contrast",
      "count": 4,
      "effort": "A per-route color setting in your scheduling software.",
      "fix": "Adjust route_color or route_text_color so each pair clears 4.5:1. Often switching the text between black and white is enough.",
      "owner": "Likely your export tool",
      "points": 0.0,
      "severity": "WARNING",
      "what": "4 route badge(s) pair a color and text color below the WCAG 4.5:1 contrast bar (MT, SX, BR, TF).",
      "why": "Riders with low vision struggle to read a low-contrast route badge. It also washes out on a phone screen in sunlight at the stop."
    },
    {
      "category": "accessibility",
      "code": "scorecard_stop_name_needs_tts",
      "count": 1,
      "effort": "A short text field per affected stop; start with the busiest.",
      "fix": "Add tts_stop_name with the spoken form, e.g. 'Main Street and Second Avenue', for the affected stops.",
      "owner": "",
      "points": 0.0,
      "severity": "INFO",
      "what": "1 stop name(s) use abbreviations or symbols a screen reader may mispronounce, with no spoken form set (\"Pedrou\u00e7os/Alg\u00e9s\").",
      "why": "A screen reader speaks the raw name. 'Main St & 2nd Ave' can come out as 'Main saint', or lose the ampersand."
    }
  ],
  "recompute": {
    "as_of": "2026-08-31",
    "feed_fetched_date": "2026-08-30",
    "kind": "freshness"
  },
  "routability": {
    "boardable_stops": 10,
    "findings": [],
    "orphan_stops": 0,
    "single_stop_trips": 0,
    "trips_total": 938
  },
  "route_map": {
    "drawn_route_count": 5,
    "has_shapes": true,
    "path": "data/artifacts/transtejo-soflusa/geometry.geojson",
    "route_count": 5,
    "routes": [
      {
        "color": "E6126C",
        "color_name": "red",
        "has_shape": true,
        "id": "1_0",
        "label": "MT",
        "long": "Montijo - Cais do Sodr\u00e9",
        "short": "MT",
        "text_color": "FFFFFF",
        "type_label": "Ferry"
      },
      {
        "color": "009A9E",
        "color_name": "teal",
        "has_shape": true,
        "id": "3_0",
        "label": "SX",
        "long": "Seixal - Cais do Sodr\u00e9",
        "short": "SX",
        "text_color": "FFFFFF",
        "type_label": "Ferry"
      },
      {
        "color": "FAB900",
        "color_name": "yellow",
        "has_shape": true,
        "id": "5_0",
        "label": "CA",
        "long": "Cacilhas - Cais do Sodr\u00e9",
        "short": "CA",
        "text_color": "000000",
        "type_label": "Ferry"
      },
      {
        "color": "5185C4",
        "color_name": "teal",
        "has_shape": true,
        "id": "7_0",
        "label": "BR",
        "long": "Barreiro - Terreiro do Pa\u00e7o",
        "short": "BR",
        "text_color": "FFFFFF",
        "type_label": "Ferry"
      },
      {
        "color": "ED7402",
        "color_name": "orange",
        "has_shape": true,
        "id": "9_0",
        "label": "TF",
        "long": "Trafaria - Porto Brand\u00e3o - Bel\u00e9m - Alg\u00e9s",
        "short": "TF",
        "text_color": "FFFFFF",
        "type_label": "Ferry"
      }
    ],
    "stop_count": 10,
    "stop_points_capped": false
  },
  "rubric_version": "1.3",
  "schema_version": "1.18",
  "scoring_profile": {
    "id": "gtfs-scorecard-1.3",
    "provenance": "GTFS Scorecard's project-authored weights, deductions, thresholds, grade bands, and fix ranking, informed by the California Transit Data Guidelines and the MobilityData gtfs-validator. It is not a worldwide standard or a compliance determination.",
    "rubric_version": "1.3"
  },
  "snapshot_date": "2026-08-31",
  "top_fixes": [
    {
      "code": "service_extends_far_in_the_future",
      "count": 28,
      "effort": "Varies.",
      "fix": "Review the rule documentation for 'service_extends_far_in_the_future' at https://gtfs-validator.mobilitydata.org/rules.html and check the flagged rows in your feed.",
      "owner": "",
      "points": 0.8,
      "rank": 1,
      "severity": "INFO",
      "what": "Service extends far in the future (flagged by the MobilityData validator).",
      "why": "See the linked rule for what this affects."
    },
    {
      "code": "service_window_outside_feed_period",
      "count": 28,
      "effort": "Two fields in feed_info.txt, or one export setting.",
      "fix": "Widen feed_start_date and feed_end_date to cover all service dates, or fix the dates that fall outside.",
      "owner": "Likely your export tool",
      "points": 0.8,
      "rank": 2,
      "severity": "INFO",
      "what": "Some service dates fall outside the date window set in feed_info.txt.",
      "why": "feed_info.txt should span every day your service runs, so apps know when the data applies."
    },
    {
      "code": "unknown_column",
      "count": 10,
      "effort": "A quick look at the flagged files.",
      "fix": "Check the flagged column names for misspellings of standard GTFS fields; remove them if they are vendor extras.",
      "owner": "",
      "points": 0.8,
      "rank": 3,
      "severity": "INFO",
      "what": "Some files contain columns that are not part of the GTFS spec.",
      "why": "Harmless to riders, but apps ignore these columns and they can hide typos in real column names."
    }
  ],
  "validator_version": "8.0.1"
}
