AlexRaubach / ListFortress

Track X-Wing Second Edition Tournament Results
https://listfortress.com/
MIT License
13 stars 6 forks source link

Allow imports from RollBetter.gg #63

Open ToshioMagic opened 1 year ago

ToshioMagic commented 1 year ago

Hi,

I'm the creator of rollbetter.gg. Where can I find the JSON schema definition for auto-importing?

Would you prefer I do a JSON export, an endpoint you can call, or both?

AlexRaubach commented 1 year ago

Here's a jsonc file showing how the existing system (which was largely inherited from ListJuggler and TTT back in first edition) with example field values and comments describing what each field is. Fields are optional unless stated otherwise but if you have the data, it's nice to have. If you have questions or concerns, please let me know and we can make changes.

{
    "players": [ //an array holding all the player objects
        {
            "name": "Alex R", //player name string. Optional if you're worried about GDPR compliance but one of id or name must be provided.
            "id": "1", //optional string uniquely identifing a player in the context of this tournament export. One of id or name must be provided
      //If an id isn't provided, it'll be impossible to distingish different players with the exact same name in the match data
            "mov": 100, //Value of MoV or now Mission Points
            "score": 4, //Number for what was score but is now 'Event points'
            "sos": 1.5, //Number representing Strength of Schedule. 
            "rank": {
                "swiss": 1, //Number showing the player's performance in the initial swiss (or other system) rounds. 
                "elimination": 2  //If there is a top cut, this number represents a players rank in that part of the bracket. 1,2,4,4,8,8,8,8 etc
            },
                       "list": "" //string containing the player's list as xws json. Can either be json or serialized into a string
        }
    ],
  "rounds": [ //an array with an object for each round played.
    {
      "round-type": "swiss", //Required: One of the two strings, "swiss" or "elimination".
      // If you aren't running a tournament with a top cut, (i.e. maybe you play five rounds and have a winner), use "swiss"
      "round-number": 1, //Required: number representing what round it is. 
      //Swiss rounds go in ascending order (1,2,3,4 etc), elmination round numbers go down and contain the number of players remaining, (16,8,4,2)
      "scenario": "", //string with the name of the scenario played in that round
      "matches": [ //array holding an object for each match in this round
        {
          "player1": "Alex R", //player 1 name
          "player1-id": "1", //optional player 1 id. You must provide either a name or an id to identify which players are in this match
          "player2": "Boba Fett",
          "player2-id": "256",
          "winner": "Alex R", //Name of the winner. Not required but nice to have, otherwise I try to find the winner by comparing the score. 
          // set to nil or exclude if it's a tie
          "winner-id": "1", 
          "player1points": 10, //points scored by player 1
          "player2points": 2 //points scored by player 2
        }
      ]
    }
  ]
}
AlexRaubach commented 1 year ago

To answer your other question, I don't think it matters very much how you expose the json. I do like having users just provide a link to the tournament as part of submitting it to ListFortress. In the past, I've just appended a string to the provided url (so /tournament/15 > /tournament/15/listfortress) but an API might be slightly better, just because it'll more easily give 404 errors when users provide a bad link (like to a tournament that is still locked). Really whatever makes sense to you to offer would be great.

ToshioMagic commented 1 year ago

Thank you! What about lists? Is there a field for that in the player object?

ToshioMagic commented 1 year ago

Also, what if scenario is left up to player choice? Is there a per pairing scenario or is that an invalid tournament?

ToshioMagic commented 1 year ago

Am I putting the total mission points scored across the event as the mov?

AlexRaubach commented 1 year ago

I just forget the list field, edited the example to add it in.

As for the player choice or tournaments without scenarios, the scenario field on rounds is optional and would be excluded in that case. We could have an additional scenario field on the match to cover when it's the players' choice, but I expect that wouldn't be very common and that TOs wouldn't have the time/interest in populating that data in the software but I don't play much theses days.

And yes, I think total missions points across the event (technically only accumulated during swiss rounds if there is a cut) would go under the mov field. I believe it's still a secondary tiebreaker in the unlikely event you have a SoS tie.

ToshioMagic commented 1 year ago

Is elimination a mandatory field? If there was no cut, or a player did not make cut to the elim stage, what should the elimination field be?

ToshioMagic commented 1 year ago

If a player got a bye, is that excluded from the match results?

ToshioMagic commented 1 year ago

Is this 2.5 only or can 2.0 and 1.0 tournaments be submitted?

AlexRaubach commented 1 year ago

Is elimination a mandatory field? If there was no cut, or a player did not make cut to the elim stage, what should the elimination field be?

No, it's optional. (The swiss rank field is also optional but really should be included in basically all cases imo). If the player didn't make it to the elimination rounds, either they left, were DQ'd or didn't make the cut, you could either exclude that key value pair or set it to null.

If a player got a bye, is that excluded from the match results?

Yes

Is this 2.5 only or can 2.0 and 1.0 tournaments be submitted?

2.0 and 2.5 are supported, when the person entering the tournament puts in the details on LF, there is a format selection where they can pick between 2.5 and 2.0 formats. There is an other option, so you could enter a 1.0 tournament which maybe a couple of people have done over the years.

ToshioMagic commented 1 year ago

Am I correct in pulling schema variables like tournament location from https://github.com/AlexRaubach/ListFortress/tree/master/app/serializers/api/v1 ?

I see here https://github.com/AlexRaubach/ListFortress/blob/master/app/models/tournament.rb that mission points and event points are mapped.

AlexRaubach commented 1 year ago

There is data I'm collecting about the tournament (name, date, location, format) that I'm making the person entering the tournament manually fill in, which you can see if you visit https://listfortress.com/tournaments/new

You don't need to provide that information in the export. When I put together the json schema above, I was really just pulling from the tournament.rb file which is where I have all the methods to import a tournament json.

ToshioMagic commented 1 year ago

Final questions!

1) If a cut is a graduated cut and not a power of 2, say 12 players, what should the elimination value be for those players who are eliminated in the first elimination round? 12 or 16?

2) If a tournament has multiple rounds of swiss, then a cut, then more rounds of swiss, and then an elimination cut

ex: Swiss 100 players > Swiss cut to 20 players > elimination cut to 4 players

how should this be represented or is this unsupported?

3) If a graduated cut is used and the first elim round has only, say, 12 players, in the rounds schema, should I put a cut size of 12 or 16?

4) What is the format for scenario names? Right now I have Chance Engagement. Should it be something else like chance-engagement?

5) What happens if a player does not have a list or they submitted it in text format? Will a non XWS string break the import? Should I exclude?

AlexRaubach commented 1 year ago

If a cut is a graduated cut and not a power of 2, say 12 players, what should the elimination value be for those players who are eliminated in the first elimination round? 12 or 16?

Either works, I'd say 12 would be preferred.

If a tournament has multiple rounds of swiss, then a cut, then more rounds of swiss, and then an elimination cut ex: Swiss 100 players > Swiss cut to 20 players > elimination cut to 4 players how should this be represented or is this unsupported?

The first and last sections of the tournament would be normal, for the middle section I'd say you just report the data you have, so the round would still be a swiss roundType but you'd only have 10 matches for the twenty players.

What is the format for scenario names? Right now I have Chance Engagement. Should it be something else like chance-engagement?

Looks like TTT was using strings like Chance Engagement so sticking with that would be best.

What happens if a player does not have a list or they submitted it in text format? Will a non XWS string break the import? Should I exclude?

I think I handle cases where the xws field isn't json and just discard but valid json with bad xws keys will prevent metawing from loading that tournament's data until I manually fix it. Also because I'm not going to store arbitrary text data, so just exclude it. It'll have to be up to community volunteers to manually remake the lists and load them into the site but not having to manually fill in all the stats is still a big help.

ToshioMagic commented 1 year ago

Roger. I'll exclude non json. Deployment going out now! I am not providing an endpoint but rather exposing a way for tournament admins to copy json to post into List Fortress. Perhaps update the text on the submission page to include JSON export from RollBetter.gg and Cryodex?

AlexRaubach commented 1 year ago

I'd really prefer if you could also make the export available to people aside from the TO, especially if the tournament is complete and public. Frequently, the person entering the tournament on LF is just an interested community member rather than the TO. Also, I'd like to take the json export from an existing tournament and import it on my dev machine just to make sure there aren't any issues which I currently can't do.

ToshioMagic commented 1 year ago

Hmm. Gotcha. How do you handle duplicate entries? Like if two people submit the same tournament?

AlexRaubach commented 1 year ago

It isn't a huge problem but when it happens, someone has to manually delete a duplicate or people consuming the data from LF have to filter for duplicate tournaments.

PiecePaperCode commented 1 year ago

Here's a jsonc file showing how the existing system (which was largely inherited from ListJuggler and TTT back in first edition) with example field values and comments describing what each field is. Fields are optional unless stated otherwise but if you have the data, it's nice to have. If you have questions or concerns, please let me know and we can make changes.

{
  "players": [ //an array holding all the player objects
      {
          "name": "Alex R", //player name string. Optional if you're worried about GDPR compliance but one of id or name must be provided.
          "id": "1", //optional string uniquely identifing a player in the context of this tournament export. One of id or name must be provided
      //If an id isn't provided, it'll be impossible to distingish different players with the exact same name in the match data
          "mov": 100, //Value of MoV or now Mission Points
          "score": 4, //Number for what was score but is now 'Event points'
          "sos": 1.5, //Number representing Strength of Schedule. 
          "rank": {
              "swiss": 1, //Number showing the player's performance in the initial swiss (or other system) rounds. 
              "elimination": 2  //If there is a top cut, this number represents a players rank in that part of the bracket. 1,2,4,4,8,8,8,8 etc
          },
                       "list": "" //string containing the player's list as xws json. Can either be json or serialized into a string
      }
  ],
  "rounds": [ //an array with an object for each round played.
    {
      "round-type": "swiss", //Required: One of the two strings, "swiss" or "elimination".
      // If you aren't running a tournament with a top cut, (i.e. maybe you play five rounds and have a winner), use "swiss"
      "round-number": 1, //Required: number representing what round it is. 
      //Swiss rounds go in ascending order (1,2,3,4 etc), elmination round numbers go down and contain the number of players remaining, (16,8,4,2)
      "scenario": "", //string with the name of the scenario played in that round
      "matches": [ //array holding an object for each match in this round
        {
          "player1": "Alex R", //player 1 name
          "player1-id": "1", //optional player 1 id. You must provide either a name or an id to identify which players are in this match
          "player2": "Boba Fett",
          "player2-id": "256",
          "winner": "Alex R", //Name of the winner. Not required but nice to have, otherwise I try to find the winner by comparing the score. 
          // set to nil or exclude if it's a tie
          "winner-id": "1", 
          "player1points": 10, //points scored by player 1
          "player2points": 2 //points scored by player 2
        }
      ]
    }
  ]
}

We should standardize tournaments export similar to xws. A formal standart for all torunament software in the x-wing space

ToshioMagic commented 1 year ago

List fortress export is now public for RollBetter.gg. You should be able to get some test data. Make sure to search for X-Wing tournaments that are in the Ended state.

AlexRaubach commented 1 year ago

@PiecePaperCode

That's what I was trying to do in this thread. I plan on making a .md file that documents the format required for tournament imports and linking it in my readme and probably somewhere on LF.

This tournament export format existed back in X-Wing 1.0, started with ListJuggler and Cryodex, then TTT became the main tournament management software and kept providing it even after TTT jumped to second edition. I built list fortress and kept using it and now I'm trying to document it and hopefully get other sites to provide compatible data.

If you or anyone else wants to make tournament json available over an endpoint, I'm happy to do some work to allow users to provide a tournament url to ListFortress and I can import it automatically, otherwise they can just paste it in the same box.