{
  "schema_version": 1,
  "line": {
    "id": "lrt2",
    "code": "LRT-2",
    "name": "LRT Line 2",
    "operator": "Light Rail Transit Authority (LRTA)",
    "status": "operational",
    "color": "#7b2d8e"
  },
  "provenance": {
    "generated_on": "2026-10-13",
    "fares_effective_from": "2023-08-02",
    "source_url": "https://www.lrta.gov.ph/tickets-and-fares/",
    "source_note": "Checked against the operator's own published fare matrix; see verified_note.",
    "verified_on": "2026-09-18",
    "verified_note": "All 169 Stored Value cells checked against the LRTA poster effective 2 August 2023; one mismatch found and corrected (Katipunan <-> Santolan, P17 in the scraped candidate, P16 on the poster). The ceil-to-5 Single Journey derivation was checked against all 156 published SJT pairs with 0 mismatches. The poster prints P13 on the diagonal (tap in and out at one station); this dataset stores 0 there and the engine rejects same-station journeys.",
    "confidence": "operator-confirmed (published matrix), spot-verified plus structural validation"
  },
  "validation": {
    "pairs": "78/78",
    "monotonic_along_line": true,
    "single_journey_rule": {
      "rule": "single_journey = ceil(beep / 5) * 5",
      "held_for": "78/78 pairs"
    },
    "corrections_applied": [
      {
        "between": [
          "Katipunan",
          "Santolan"
        ],
        "from": 17,
        "to": 16,
        "reason": "Third-party matrix had P17; the LRTA poster shows P16 both ways.",
        "source_url": "https://www.philippinebeaches.org/wp-content/uploads/2025/11/LRT-2-Fare-Matrix.jpeg"
      }
    ]
  },
  "products": {
    "beep": {
      "label": "Stored Value (beep)",
      "storage": "matrix"
    },
    "single_journey": {
      "label": "Single Journey Ticket",
      "storage": "derived",
      "from": "beep",
      "rule": "ceil(x/5)*5"
    }
  },
  "modifiers": [
    {
      "id": "dotr_50_discount_2026",
      "label": "50% DOTr fare discount",
      "type": "percentage",
      "value": -50,
      "requires_user_selection": false,
      "effective_from": "2026-03-23",
      "effective_until": null,
      "note": "Applied across the board to LRT-2 and MRT-3 from 23 March 2026. Announced as a temporary measure with no published end date, so effective_until is null and must be watched. Modelled as a modifier so the base matrix stays correct when it lapses.",
      "stacks": false,
      "stacking_note": "Replaces rather than compounds with concession_student_senior_pwd: both are 50%, so a senior pays the same half fare as everyone else while this is in force.",
      "source_url": "https://www.pna.gov.ph/articles/1271411",
      "last_confirmed": "2026-09-20"
    },
    {
      "id": "concession_student_senior_pwd",
      "label": "Student / Senior Citizen / PWD",
      "type": "percentage",
      "value": -50,
      "requires_user_selection": true,
      "requires": "white beep card (P30 one-time, valid one year, renewable)",
      "effective_from": "2025-09-20",
      "effective_until": null,
      "applies_to_lines": [
        "lrt1",
        "lrt2",
        "mrt3"
      ],
      "source_url": "https://tribune.net.ph/2025/09/20/marcos-launches-50-discount-beep-cards-for-students-on-lrt-mrt",
      "note": "The white beep card applying an automatic 50% was launched 20 September 2025 and covers LRT-1, LRT-2 and MRT-3 alike. An earlier draft of this data carried it on LRT-1 only and dated it to the April 2025 fare hike; both were wrong.",
      "stacks": false,
      "stacking_note": "Does not compound with dotr_50_discount_2026. The March 2026 announcements state that concession holders 'will still be entitled to their respective 50% discounts' — they keep half price rather than dropping to a quarter, and no operator publishes a 75% fare. The engine applies the single deepest discount.",
      "last_confirmed": "2026-09-20"
    }
  ],
  "stations": [
    {
      "id": "lrt2_recto",
      "slug": "recto",
      "ordinal": 1,
      "name": "Recto",
      "full_name": "Recto",
      "former_names": [],
      "lat": 14.603608,
      "lng": 120.98342,
      "coordinates_source": "legacy-app-2017",
      "coordinates_verified": true,
      "interchanges": [
        {
          "station_id": "lrt1_d_jose",
          "line_id": "lrt1",
          "walk_minutes": 5,
          "walk_note": "Elevated covered walkway directly between the two concourses; the shortest of the three transfers. Published ranges 3-5 and 5-10 minutes.",
          "walk_source_url": "https://3d-universal.com/en/blogs/how-to-transfer-between-mrt-and-lrt-lines.html"
        }
      ],
      "coordinates_verified_on": "2026-09-20",
      "coordinates_verified_against": "wikipedia:Recto station",
      "coordinates_verified_delta_m": 12
    },
    {
      "id": "lrt2_legarda",
      "slug": "legarda",
      "ordinal": 2,
      "name": "Legarda",
      "full_name": "Legarda",
      "former_names": [],
      "lat": 14.600837,
      "lng": 120.992603,
      "coordinates_source": "legacy-app-2017",
      "coordinates_verified": true,
      "interchanges": [],
      "coordinates_verified_on": "2026-09-20",
      "coordinates_verified_against": "wikipedia:Legarda station",
      "coordinates_verified_delta_m": 10
    },
    {
      "id": "lrt2_pureza",
      "slug": "pureza",
      "ordinal": 3,
      "name": "Pureza",
      "full_name": "Pureza",
      "former_names": [],
      "lat": 14.601488,
      "lng": 121.005211,
      "coordinates_source": "legacy-app-2017",
      "coordinates_verified": true,
      "interchanges": [],
      "coordinates_verified_on": "2026-09-20",
      "coordinates_verified_against": "wikipedia:Pureza station",
      "coordinates_verified_delta_m": 20
    },
    {
      "id": "lrt2_v_mapa",
      "slug": "v-mapa",
      "ordinal": 4,
      "name": "V. Mapa",
      "full_name": "V. Mapa",
      "former_names": [],
      "lat": 14.603996,
      "lng": 121.01728,
      "coordinates_source": "legacy-app-2017",
      "coordinates_verified": true,
      "interchanges": [],
      "coordinates_verified_on": "2026-09-20",
      "coordinates_verified_against": "wikipedia:V. Mapa station",
      "coordinates_verified_delta_m": 38
    },
    {
      "id": "lrt2_j_ruiz",
      "slug": "j-ruiz",
      "ordinal": 5,
      "name": "J. Ruiz",
      "full_name": "J. Ruiz",
      "former_names": [],
      "lat": 14.610554,
      "lng": 121.026208,
      "coordinates_source": "legacy-app-2017",
      "coordinates_verified": true,
      "interchanges": [],
      "coordinates_verified_on": "2026-09-20",
      "coordinates_verified_against": "wikipedia:J. Ruiz station",
      "coordinates_verified_delta_m": 10
    },
    {
      "id": "lrt2_gilmore",
      "slug": "gilmore",
      "ordinal": 6,
      "name": "Gilmore",
      "full_name": "Gilmore",
      "former_names": [],
      "lat": 14.613493,
      "lng": 121.034271,
      "coordinates_source": "legacy-app-2017",
      "coordinates_verified": true,
      "interchanges": [],
      "coordinates_verified_on": "2026-09-20",
      "coordinates_verified_against": "wikipedia:Gilmore station (LRT)",
      "coordinates_verified_delta_m": 45
    },
    {
      "id": "lrt2_betty_go_belmonte",
      "slug": "betty-go-belmonte",
      "ordinal": 7,
      "name": "Betty Go-Belmonte",
      "full_name": "Betty Go-Belmonte",
      "former_names": [],
      "lat": 14.618567,
      "lng": 121.042685,
      "coordinates_source": "legacy-app-2017",
      "coordinates_verified": true,
      "interchanges": [],
      "coordinates_verified_on": "2026-09-20",
      "coordinates_verified_against": "wikipedia:Betty Go-Belmonte station",
      "coordinates_verified_delta_m": 33
    },
    {
      "id": "lrt2_araneta_center_cubao",
      "slug": "araneta-center-cubao",
      "ordinal": 8,
      "name": "Araneta Center-Cubao",
      "full_name": "Araneta Center-Cubao",
      "former_names": [],
      "lat": 14.622746,
      "lng": 121.052774,
      "coordinates_source": "legacy-app-2017",
      "coordinates_verified": true,
      "interchanges": [
        {
          "station_id": "mrt3_araneta_cubao",
          "line_id": "mrt3",
          "walk_minutes": 10,
          "walk_note": "Longest transfer of the three: an indoor route through Farmers Plaza and Gateway Mall. Two sources give 8-10 and 10-15 minutes. The mall corridors close overnight, so the late-evening walk is longer and outdoors.",
          "walk_source_url": "https://mappedatlas.com/commute-index/street-logic/cubao-araneta/"
        }
      ],
      "coordinates_verified_on": "2026-09-20",
      "coordinates_verified_against": "wikipedia:Araneta Center–Cubao station (LRT)",
      "coordinates_verified_delta_m": 17
    },
    {
      "id": "lrt2_anonas",
      "slug": "anonas",
      "ordinal": 9,
      "name": "Anonas",
      "full_name": "Anonas",
      "former_names": [],
      "lat": 14.627984,
      "lng": 121.064777,
      "coordinates_source": "legacy-app-2017",
      "coordinates_verified": true,
      "interchanges": [],
      "coordinates_verified_on": "2026-09-20",
      "coordinates_verified_against": "wikipedia:Anonas station",
      "coordinates_verified_delta_m": 9
    },
    {
      "id": "lrt2_katipunan",
      "slug": "katipunan",
      "ordinal": 10,
      "name": "Katipunan",
      "full_name": "Katipunan",
      "former_names": [],
      "lat": 14.630876,
      "lng": 121.073113,
      "coordinates_source": "legacy-app-2017",
      "coordinates_verified": true,
      "interchanges": [],
      "coordinates_verified_on": "2026-09-20",
      "coordinates_verified_against": "wikipedia:Katipunan station",
      "coordinates_verified_delta_m": 30
    },
    {
      "id": "lrt2_santolan",
      "slug": "santolan",
      "ordinal": 11,
      "name": "Santolan",
      "full_name": "Santolan",
      "former_names": [],
      "lat": 14.622095,
      "lng": 121.085981,
      "coordinates_source": "legacy-app-2017",
      "coordinates_verified": true,
      "interchanges": [],
      "coordinates_verified_on": "2026-09-20",
      "coordinates_verified_against": "wikipedia:Santolan station",
      "coordinates_verified_delta_m": 8
    },
    {
      "id": "lrt2_marikina_pasig",
      "slug": "marikina-pasig",
      "ordinal": 12,
      "name": "Marikina-Pasig",
      "full_name": "Marikina-Pasig",
      "former_names": [],
      "lat": 14.62027778,
      "lng": 121.10027778,
      "coordinates_source": "wikipedia-2026",
      "coordinates_verified": true,
      "opened_on": "2021-07-05",
      "interchanges": [],
      "coordinates_verified_on": "2026-09-20",
      "coordinates_verified_against": "wikipedia:Marikina–Pasig station",
      "coordinates_verified_delta_m": 0
    },
    {
      "id": "lrt2_antipolo",
      "slug": "antipolo",
      "ordinal": 13,
      "name": "Antipolo",
      "full_name": "Antipolo",
      "former_names": [],
      "lat": 14.62472222,
      "lng": 121.12111111,
      "coordinates_source": "wikipedia-2026",
      "coordinates_verified": true,
      "opened_on": "2021-07-05",
      "interchanges": [],
      "coordinates_verified_on": "2026-09-20",
      "coordinates_verified_against": "wikipedia:Antipolo station",
      "coordinates_verified_delta_m": 0
    }
  ],
  "fares": {
    "model": "matrix",
    "currency": "PHP",
    "product": "beep",
    "station_order": [
      "Recto",
      "Legarda",
      "Pureza",
      "V. Mapa",
      "J. Ruiz",
      "Gilmore",
      "Betty Go-Belmonte",
      "Araneta Center-Cubao",
      "Anonas",
      "Katipunan",
      "Santolan",
      "Marikina-Pasig",
      "Antipolo"
    ],
    "matrix": [
      [
        0,
        15,
        16,
        18,
        19,
        21,
        22,
        23,
        25,
        26,
        28,
        31,
        33
      ],
      [
        15,
        0,
        15,
        17,
        18,
        19,
        21,
        22,
        24,
        25,
        27,
        29,
        32
      ],
      [
        16,
        15,
        0,
        15,
        16,
        18,
        19,
        20,
        22,
        23,
        26,
        28,
        30
      ],
      [
        18,
        17,
        15,
        0,
        15,
        16,
        17,
        19,
        20,
        22,
        24,
        26,
        29
      ],
      [
        19,
        18,
        16,
        15,
        0,
        14,
        16,
        17,
        19,
        20,
        22,
        24,
        27
      ],
      [
        21,
        19,
        18,
        16,
        14,
        0,
        15,
        16,
        18,
        19,
        21,
        23,
        26
      ],
      [
        22,
        21,
        19,
        17,
        16,
        15,
        0,
        15,
        16,
        18,
        20,
        22,
        25
      ],
      [
        23,
        22,
        20,
        19,
        17,
        16,
        15,
        0,
        15,
        16,
        19,
        21,
        23
      ],
      [
        25,
        24,
        22,
        20,
        19,
        18,
        16,
        15,
        0,
        14,
        17,
        19,
        22
      ],
      [
        26,
        25,
        23,
        22,
        20,
        19,
        18,
        16,
        14,
        0,
        16,
        18,
        21
      ],
      [
        28,
        27,
        26,
        24,
        22,
        21,
        20,
        19,
        17,
        16,
        0,
        15,
        18
      ],
      [
        31,
        29,
        28,
        26,
        24,
        23,
        22,
        21,
        19,
        18,
        15,
        0,
        16
      ],
      [
        33,
        32,
        30,
        29,
        27,
        26,
        25,
        23,
        22,
        21,
        18,
        16,
        0
      ]
    ]
  }
}
