Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multipitch routes #266

Open
musoke opened this issue Apr 19, 2023 · 19 comments
Open

multipitch routes #266

musoke opened this issue Apr 19, 2023 · 19 comments

Comments

@musoke
Copy link
Contributor

musoke commented Apr 19, 2023

Is there a plan for how multi-pitch routes will be handled? I don't see much documentation of this.

#252 has some discussion. The suggestion there is that multipitch routes should get an array of bolt counts, one for each pitch.

Presumably the same would work for grades. Sandbag grades are ordered, so the overall route grade can be calculated as the maximum over the pitches. There will be more subtlety when different pitches have different disciplines (e.g. free and ice on one climb).

What other fields need generalizing?

@bradleyDean asks about variations in #252. Simplest suggestion is to list them as separate routes.

@vnugent vnugent added this to the next milestone Apr 27, 2023
@l4u532
Copy link
Contributor

l4u532 commented Jun 5, 2023

As in #252 I suggest

  • adding new field "bolts" with String array that contains no of bolts per pitch
  • changing "grade" to String array to include difficulty per pitch
  • (and route variants are represented as individual routes, this preserves the option to tick routes)

This should be a user-friendly solution to represent multipitches.

@musoke
Copy link
Contributor Author

musoke commented Jun 5, 2023

  • (and route variants are represented as individual routes, this preserves the option to tick routes)

This is certainly the simplest and most obvious solution. It might get messy in practice though. What if I climb the bottom half of one route and link it into the top half of another? Then I would need to add another route, even though all its pitches already exist elsewhere in the database.

We could instead allow for ticks which mix and match pitches from different routes. Then variations can be listed without duplicating pitches and the user can still tick what they actually climbed.

@l4u532
Copy link
Contributor

l4u532 commented Jun 5, 2023

I guess in that case one multi-pitch route could have several sub-routes, with individual difficulty, bolts, description. Sounds neat. Yet, I have to admit, viewed from my central European climbing perspective, ticking mixed pitches would be a niche feature (the vast majority of climbs are bolted here).

If you don't disagree with points (1) and (2), I'd try implementing them, as I/we need bolt count for a sensible representation in Central Europe and (3) should not be affected by a String array implementation as proposed (1)+(2).

@musoke
Copy link
Contributor Author

musoke commented Jun 5, 2023

Sounds good!

To be clear: when I said "mix" I meant combining pitches from different routes, not mixed protection. I hadn't thought about that.

@vnugent
Copy link
Contributor

vnugent commented Jun 5, 2023

Why would you use string instead of a valid grade that passes openbeta/sandbag validation?

changing "grade" to String array to include difficulty per pitch

@l4u532
Copy link
Contributor

l4u532 commented Jun 11, 2023

Maybe a misunderstanding (I am aware of Climb.grades). Anyway, I have been thinking about this and have come to a different conclusion altogether - I am trying to recap the problem and options:

  • Problem: For a given multi-pitch climb, we want to represent multiple boltsCount and grades, e. g. grade = ["6a", "6c", "5c", "6c"] and boltsCount = [4, 6, 3, 3] for each pitch
  • Options
    • (1) Add Climb.boltsCount and re-define Climb.grades so that its fields (vscale, french, …) accept Arrays of Strings (instead of single Strings); I guess not a good idea since this would break existing implementations that expect a single String value to be returned
    • (2) Add Climb.boltsCount and introduce a new field called Climb.gradesArray; this would not break existing implementations, but bloat the schema
    • (3) introduce type Pitch (with fields parent, type, number, grade, length, boltsCount, description) as a child to climb, so that climb gets an optional Array Climb.pitches containing each pitch; this has the most flexibility and allows for detailed per-pitch data, plus it wouldn't break any existing implementation (I assume)
      • Addendum to (3): add Climb.boltsCount for single-pitch (sport) climbs
    • (4) Add Climb.boltsCount and allow Climb.ancestor to also point to a climb (instead of an area); not sure what problems this would introduce, could be a quick solution
  • I am favoring (3), as it would allow storing consistent, non-messy and detailed multi-pitch for all disciplines (ice, trad, alpine, … - even mixing them) and allow ticking off individual pitches, without - presumably - breaking things

What are your thoughts?

@Silthus
Copy link
Contributor

Silthus commented Jun 11, 2023

How about adding a parentClimb to the Climb type allowing to define climbs that preceed the current climb. Additionally add the new Pitch type to mark climbs that can only be climbed by also climbing their parent (they are pitches >= 2nd pitch).

We could go further and (later) add a Multi-Pitch type that groups together climbs in a route with a name and "default" tick bucket.
This would allow for multiple combinations of multi-pitch routes and leaves flexibility for ticking.

The user could simply tick a "pre-grouped" Multi-Pitch route and then derive and select other pitches if the climb forked in the middle.

@l4u532
Copy link
Contributor

l4u532 commented Jun 11, 2023 via email

@vnugent
Copy link
Contributor

vnugent commented Jun 12, 2023

I think 3 is a sensible solution. To help us visualize the document schema, @l4u532 can you share a JSON sample of a climb with nested pitch array?

@l4u532
Copy link
Contributor

l4u532 commented Jun 16, 2023

Sure. To recap, a Climb would be extended with pitches of Type Pitch:

type Climb {  
  id: ID!  
  uuid: ID!  
  name: String!  
  ...
  pitches: [Pitch]!  # add this line to include Pitch in the Climb type
}

The Type Pitch would contain:

type Pitch {
  uuid: ID!
  parent: ID!
  number: Int!
  grades: GradeType!
  type: ClimbType!
  length: Int!
  boltsCount: Int
  description: String
}

Simplified example JSON for a trad route:

  "data": {
    "climb": {
      "id": "1",
      "uuid": "123e4567-e89b-12d3-a456-426614174000",
      "name": "The Grand Wall",
      "fa": "John Doe",
      "length": 300,
      "grades": {
        "yds": "5.11"
        ...
      },
      "gradeContext": "USA",
      "type": {
        "trad": true,
        "sport": false
        ...
      },
      "safety": "R",
      "pitches": [
        {
          "uuid": "123e4567-e89b-12d3-a456-426614174001",
          "parent": "123e4567-e89b-12d3-a456-426614174000",
          "number": 1,
          "grades": {
            "yds": "5.10"
            ...
          },
          "type": {
            "trad": true,
            "sport": false
            ...
          },
          "length": 50,
          "boltsCount": 0,
          "description": "A beautiful finger crack leading to a bolted face."
        },
        {
          "uuid": "123e4567-e89b-12d3-a456-426614174002",
          "parent": "123e4567-e89b-12d3-a456-426614174000",
          "number": 2,
          "grades": {
            "yds": "5.11"
            ...
          },
          "type": {
            "trad": true,
            "sport": false
            ...
          },
          "length": 70,
          "boltsCount": 0,
          "description": "A challenging pitch with a tricky roof sequence."
        },
        ...
      ],
      ...
    }
  }
}

And an example for an alpine multi-pitch route typical for Central Europe with bolts.

{
  "data": {
    "climb": {
      "id": "2",
      "uuid": "223e4567-e89b-12d3-a456-426614174000",
      "name": "Alpine Dream",
      "fa": "Jane Doe",
      "length": 350,
      "grades": {
        "french": "7a"
        ...
      },
      "gradeContext": "AUS",
      "type": {
        "alpine": true,
        "sport": false
        ...
      },
      "safety": "R",
      "pitches": [
        {
          "uuid": "223e4567-e89b-12d3-a456-426614174001",
          "parent": "223e4567-e89b-12d3-a456-426614174000",
          "number": 1,
          "grades": {
            "french": "6a",
            ...
          },
          "type": {
            "alpine": true,
            "sport": false,
            ...
          },
          "length": 120,
          "boltsCount": 15,
          "description": "Starts with a steep face climb, bolts are well spaced."
        },
        {
          "uuid": "223e4567-e89b-12d3-a456-426614174002",
          "parent": "223e4567-e89b-12d3-a456-426614174000",
          "number": 2,
          "grades": {
            "french": "6b",
            ...
          },
          "type": {
            "alpine": true,
            "sport": false,
            ...
          },
          "length": 110,
          "boltsCount": 20,
          "description": "A bit more challenging, requires careful route finding."
        },
        {
          "uuid": "223e4567-e89b-12d3-a456-426614174003",
          "parent": "223e4567-e89b-12d3-a456-426614174000",
          "number": 3,
          "grades": {
            "french": "7a",
            ...
          },
          "type": {
            "alpine": true,
            "sport": false,
            ...
          },
          "length": 200,
          "boltsCount": 18,
          "description": "A long pitch with a challenging overhang near the end."
        }
      ],
      ...
    }
  }
}

@musoke
Copy link
Contributor Author

musoke commented Jun 16, 2023 via email

@l4u532
Copy link
Contributor

l4u532 commented Jun 16, 2023

Will the climbs still have a description, or is that moved to the pitches?

Mostly data for multi pitch routes will lack a per-pitch description, so I see those as optional. Consequently, Climbs will still have a description.

@musoke
Copy link
Contributor Author

musoke commented Jun 16, 2023 via email

@musoke
Copy link
Contributor Author

musoke commented Jun 16, 2023 via email

@l4u532
Copy link
Contributor

l4u532 commented Jun 16, 2023

Climb.grade could take the max difficulty of its pitches’ grades. Guidebooks on alpine routes often speak of “obligatory difficulty” one needs to pass. Most often, that's the max grade. In essence, you don’t want to get stuck in a multi-pitch route.

pitches should be an optional array and be left empty for single-pitch routes (aka sport climbing). Only if pitches.length > 1*, a climb would be a multi-pitch climb.

(*could be enforced , e.g.

      if (args.input.pitches.length <= 1) {
        throw new Error('A multi-pitch climb must have more than one pitch.');
      }

)

It is not hidden from the user, but made explicit via (a) making the pitches array optional and (b) the schema description. For the UI part - which I am not considering here - the pitches.length > 1 could inform about a multi-pitch route. (Also, a boolean flag might be introduced based on this logic).

Your thoughts?

@musoke
Copy link
Contributor Author

musoke commented Jun 17, 2023

Climb.grade could take the max difficulty of its pitches’ grades. Guidebooks on alpine routes often speak of “obligatory difficulty” one needs to pass. Most often, that's the max grade. In essence, you don’t want to get stuck in a multi-pitch route.

That was my initial thought too. Are there any cases or communities that do this differently? The only one that comes to mind for me is climbs where the different pitches have different disciplines - then the grades aren't ordered. For example a free pitch (5.10) and an aid pitch (5.8 A1) should combine to give an aid route with grade 5.10 A1. OpenBeta/sandbag#80 will address that. Generalizing slightly will address routes where pitches are a mix of sport/trad/ice/etc.

I think it should be possible to set a grade that overrides the one calculated from the pitches. This allow a route grade to be recorded even when grades of individual pitches are not known.

single-pitch routes (aka sport climbing)

Do we have different definitions here? I've done multi-pitch sport routes and single pitch non-sport routes.

pitches should be an optional array and be left empty for single-pitch routes (aka sport climbing). Only if pitches.length > 1*, a climb would be a multi-pitch climb.

I would tend to allow single pitch climbs to have a single pitch.

@vnugent
Copy link
Contributor

vnugent commented Jun 17, 2023

@l4u532 I like this approach as it gently introduces multi-pitch data structure as an opt-in. We can even define a convention:

  • For single pitch climbs (regardless of styles, trad/sport/ice, etc.) we can use the existing data structure; The pitches array will be empty.
  • For multipitch climbs we will need to identify them and incrementally introduce pitch data to the pitch array.

@l4u532
Copy link
Contributor

l4u532 commented Jun 19, 2023

Climb.grade could take the max difficulty of its pitches’ grades. Guidebooks on alpine routes often speak of “obligatory difficulty” one needs to pass. Most often, that's the max grade. In essence, you don’t want to get stuck in a multi-pitch route.

That was my initial thought too. Are there any cases or communities that do this differently?

I know the use case that one may skip a difficult pitch by using an alternative route (neighbouring route, a tree, or other part of the rock not defined as part of the route), which would lower the "obligatory grade". Yet I suggest we start by taking the max of the grades and leave such cases for the description fields.

The only one that comes to mind for me is climbs where the different pitches have different disciplines - then the grades aren't ordered. For example a free pitch (5.10) and an aid pitch (5.8 A1) should combine to give an aid route with grade 5.10 A1. OpenBeta/sandbag#80 will address that. Generalizing slightly will address routes where pitches are a mix of sport/trad/ice/etc.

Good point and similar problem as above. I would consider support for independent free/aid grades separate from this issue, though. (btw. climbs that alternative between ice and rock are called Mixed Climbing and difficulties are denominated from MI1-MI14 (see https://en.wikipedia.org/wiki/Mixed_climbing#Grading), so imho no problem of mixing grades there).

I think it should be possible to set a grade that overrides the one calculated from the pitches. This allow a route grade to be recorded even when grades of individual pitches are not known.

Agreed. Auto-calculate the max grade of pitches, but Climb.grades overrides it, if set.

single-pitch routes (aka sport climbing)

Do we have different definitions here? I've done multi-pitch sport routes and single pitch non-sport routes.

Very possible. I haven't found a clear-cut definition. Such definitions also tend to differ between geographies. Let's agree that multi-pitches may be sport-climbing, too. The important differentiator is pitches.length > 1.

pitches should be an optional array and be left empty for single-pitch routes (aka sport climbing). Only if pitches.length > 1*, a climb would be a multi-pitch climb.

I would tend to allow single pitch climbs to have a single pitch.

Also totally fine with me. Again, the important differentiator is pitches.length > 1.

@musoke
Copy link
Contributor Author

musoke commented Jun 20, 2023

I would consider support for independent free/aid grades separate from this issue, though. (btw. climbs that alternative between ice and rock are called Mixed Climbing and difficulties are denominated from MI1-MI14 (see https://en.wikipedia.org/wiki/Mixed_climbing#Grading), so imho no problem of mixing grades there).

I'm thinking of something slightly different: one climb, where the pitches don't all have the same type of climbing.

In anycase, I think what you're proposing will cover this case since you have a "type" field for each pitch.

This was referenced Aug 23, 2023
@vnugent vnugent removed this from the next milestone Nov 27, 2024
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

No branches or pull requests

4 participants