beyond-all-reason/maps-metadata

Map team composition metadata

Closed this issue · 11 comments

p2004a commented

SPADs uses the DynamicMapRotation plugin to support next map etc.

There are 2 files in spads:

One related piece of metadata is also selection of startpos for the given team composition.

All this information is related to each other, this issue is for overall:

  • Design how to best store this information in Rowy: we already have e.g. teamcount and playercount because they were in chobby for whatever reason. We also have some metadata dimensions in https://docs.google.com/spreadsheets/d/1rn4kIIc9Nnyv_ZiBxXvNXdhUSnh15aLrLsQXmtUBJt8/edit#gid=0 that are currently not important and ofc in the above mentioned files.
  • Import as much metadata to Rowy as possible
  • Write exporters for the mapLists.conf and DynamicMapRotation.conf: we already have all in place to commit to spads repo, so that part is easy

For FFA metadata, there is a bunch of info linked from https://discord.com/channels/549281623154229250/1108192123829891082

I started looking at this. Trying to add the teamsize data in similar manner that it is in the google spreadsheet and writing a python script to make it into mapLists.conf format. I don't think DynamicMapRotation.conf needs to be updated regularly/automatically.

    teamSize:
      type: array
      items:
        title: TeamSize
        type: string
        enum:
          - 1v1
          - 2v2
          - 3v3
          - 4v4
          - 5v5
          - 6v6
          - 7v7
          - 8v8
          - ffa3
          - ffa4
          - ffa5
          - ffa6
          - ffa7
          - ffa8
          - ffa9
          - ffa10
          - ffa11
          - ffa12
          - ffa13
          - ffa14
          - ffa15
          - ffa16
          - 2v2v2
          - 2v2v2v2
          - 2v2v2v2v2
          - 2v2v2v2v2v2
          - 2v2v2v2v2v2v2
          - 2v2v2v2v2v2v2v2
          - 3v3v3
          - 3v3v3v3
          - 3v3v3v3v3
          - 4v4v4
          - 4v4v4v4
          - 5v5v5
      uniqueItems: true
      default: []
p2004a commented

I don't think DynamicMapRotation.conf needs to be updated regularly/automatically.

Agree

Trying to add the teamsize data in similar manner that it is in the google spreadsheet

I'm not sure if this is the most ergonomic way to represent this information and make it easy to maintain. 33 tags X 165 maps is effectively 5445 boolean fields that need to be maintained manually.

For example, alternative to consider is to derive it automatically from startboxes for team games, and startpos for ffa games:

  • Map supports 3 teams, if there are startboxes defined for 3 teams. Then per startbox we also add one number: information how many people fit in that startbox.
  • For ffa games, we will have beyond-all-reason/Beyond-All-Reason#2041 so when startpos combinations are defined for the map, it can be used to extract the max ffa and team ffa sizes.

This way we reduce the amount of redundant information that need to be added, maintained and keept consistent. That information is also more structured, it's not a collection of strings without meaning, so e.g. lobby could also get this in structured manner, and you can do filtering "Show me maps that support 3 teams, and between 2-4 people per team" without matching some "XvXvX" strings.

That is just one alternative proposal how to maintain it, it might not be the best one, there are probably more alternatives, but I e.g. prefer that to set of 33 tags.

Another question with that approach is if a map can support 8v8 should it still be included in 1v1,2v2,3v3 etc. lists. Probably not in all of them, but definitely in some of them. So maybe instead of [Number of Starting Spots] (or [Player Count]) we should have [Min Player Count] and [Max Player Count].

So maybe we add and [Max Total Player Count] to each Startboxes Set and not Start Box. I think we can assume the boxes are made to be fair so that each box in a set can fit same amount of players. We also add [Min Player Count] to each map (and rename [Player Count] to [Max Player Count]).

Then logic goes like this:

Map has e.g. [Min Player Count] = 8 and it's tagged as Team and FFA.
It has starting boxes for 2 teams with [Max Total Player Count] = 16.
It has starting boxes for 4 teams with [Max Total Player Count] = 12.

It would then be added to all these lists in mapLists.conf: 4v4, 5v5, 6v6, 7v7, 8v8, 2v2v2v2, 3v3v3v3, ffa8, ffa9, ffa10, ffa11, ffa12, ffa13, ffa14, ffa15, ffa16.

The ffa stuff can be refined later when that metadata gets added to rowy.

Does this sound reasonable?

p2004a commented

Another question with that approach is if a map can support 8v8 should it still be included in 1v1,2v2,3v3 etc. lists. Probably not in all of them, but definitely in some of them. So maybe instead of [Number of Starting Spots] (or [Player Count]) we should have [Min Player Count] and [Max Player Count].

Yeah, I was thinking about that too, it's definitely important for the !nextmap. Having additional tunable is probably ok, or we could leave it as "maybe we actually don't need this tunable", and e.g. default like: min_player_count=max(floor(max_player_count/2), 1) is good enough?

But I also see that you propose the min_player_count is per-map. It is some middleground, it's less maintenance this way. Frankly I'm fine with either way personally, this should be easy to change later if we want in either direction. My intuition tells me start with something minimal and apply YANGI principle but maybe there are already some good cases I'm just not aware of that would benefit from dedicated setting.

So maybe we add and [Max Total Player Count] to each Startboxes Set and not Start Box. I think we can assume the boxes are made to be fair so that each box in a set can fit same amount of players. We also add [Min Player Count] to each map (and rename [Player Count] to [Max Player Count]).

Oh yes, sorry for not being precise, or to even be more precise, StartboxesInfo :) that's what I had in mind. For me more logical is also that the max_player_count is per-startbox, not total on map. That way validation is a bit more obvious: you don't need to check "did person specify the count that is divisible by the number of startboxes", we can just constraint field value to be between 1 and 8.

(...)
Does this sound reasonable?

Sounds great to me! And thank you for looking at this issue! 😃

Okay so like this:

    minPlayerCount:
      type: integer
    playerCount:
      type: integer

...

    startboxesSet:
      type: object
      collection: true
      additionalProperties:
        type: object
        title: StartboxesInfo
        properties:
          startboxes:
            type: array
            minItems: 1
            items:
              type: object
              title: Startbox
              properties:
                poly:
                  type: array
                  minItems: 2
                  maxItems: 2
                  items:
                    title: Point
                    type: object
                    properties:
                      x:
                        type: integer
                        minimum: 0
                        maximum: 200
                      y:
                        type: integer
                        minimum: 0
                        maximum: 200
                    additionalProperties: false
                    required:
                      - x
                      - y
              additionalProperties: false
              required:
                - poly
          maxPlayersPerStartBox:
            type: integer
        additionalProperties: false
        required:
          - startboxes
          - maxPlayersPerStartBox

I think minPlayerCount is nice to have, some maps are viable for both 2v2 and 8v8 and some are not. We can default to min_player_count=max(floor(max_player_count/2), 1) if it's empty or missing though. I'll make up some testdata in this format in map_list.yaml and write some python to convert it into mapLists.conf. Not sure what else is needed to make it all automatic after that but I'll think about that once I get there.

p2004a commented

@RebelNode I went ahead and kinda following https://github.com/beyond-all-reason/maps-metadata/wiki/Adding-new-input-dimension:

  • Added the maxPlayersPerStartbox column in Rowy (note that b is lowercase for consistency with rest of the fields
  • Gave you editor access in Rowy (just log in and out) so you can just set those values for testing easily (until they are used, column value doesn't matter)
  • Gave you access to be able to run make update_all_from_rowy so you can test it's properly importing and all that (follow the instructions above to setup your env to correctly authorize to database)

Cool, thanks! I'll see what I can get done.

Okay getting everything setup on WSL just to run the existing code was a bit of a ride. But I managed to succesfully run make update_all_from_rowy and pull some maxPlayersPerStartbox test numbers in. Also had to learn a bunch of stuff about makefiles and whatnot, but I'm somewhat motivated to learn some of that anyway so that's fine.

Here's what I made so far: RebelNode@8f5ca3f. It does what I set out to do, though I am a rather noob-level programmer (I mostly just write SQL for a living) so I'm not sure how pretty or professional it looks. If it's good enough then I just have to fill in all the required maxPlayersPerStartbox metadata for the maps in rowy and then I can make a PR.

Also no idea how to setup the github-actions to commit the mapLists.conf to spads repo, but that probably requires some permissions anyway so maybe @p2004a can do that?

p2004a commented

Great to hear you successfully set up everything and made progress!

If you are happy with how this works, I recommend just opening a PR even without all data in Rowy. We can fill it later as we want: there are a lot of maps and startboxes for many they are not configured correctly (they were imported to rowy from other sources). It's quite some work that we want to do but I wouldn't want to block PR on that.

(...) I'm not sure how pretty or professional it looks (...)

Don't worry, there is going to be some minimal quality bar, and above that I can do review at whatever quality you want (we can stop at minimum quality or I can do more detailed review as learning exercise)

Also no idea how to setup the github-actions to commit the mapLists.conf to spads repo, but that probably requires some permissions anyway so maybe @p2004a can do that?

Sure, that's trivial :). Because we already commit to that repo startboxes, we just need to add one like like this: https://github.com/beyond-all-reason/maps-metadata/blob/main/.github/workflows/ci.yaml#L154

Okay I made it so that empty maplists default to .* which seems to mean "all maps" in mapLists.conf. I also added .* for "[small]", "[medium]", "[large]", "[extraLarge]" and "[misc]" lists. As far as I know dynamic map rotation doesn't use them anyway as they're not mentioned in DynamicMapRotation.conf, but some other legacy thing might so they're there now.

I also went through rowy and added playerCount to all maps that I know or that are popular. The script uses playerCount/2 as a backup for 2-team setups if there's no maxPlayersPerStartbox defined so this way popular maps don't fall off the lists. It also uses playerCount for ffa maps currently as there's no better metadata available.

Also added that one line to ci.yaml as it was pretty trivial now that you pointed me to the right place.

PR is here: #128 . Need to run and commit make update_all_from_rowy after pulling this to prevent some popular maps from falling off the rotation lists.

We now have information in rowy for every single starbox about max number of players etc. The only thing that kinda fits for this issue is getting more information about FFA setup https://github.com/beyond-all-reason/Beyond-All-Reason/blob/master/luarules/configs/ffa_startpoints/README.md but it can be tracked as a separate issue.