I feel like there’s a more efficient way to do this, and if someone can come up with a great answer hopefully this will help anyone building large repeating groups!
I’m building scrabble - every time a new game is created, 225 empty tiles in a repeating group (RG) are created in a recursive API workflow to form the board:
Call the same API workflow again until tiles > 255.
There have to be empty tiles created because otherwise the RG won’t actually show up (you can’t place a tile on a space that has nothing, the RG just won’t show a cell). Can anyone think of a better way to structure the data/manage the large RG?
One way that you might be able to do this is to have a tile space data object and a tile letter data object. I would recommend that you do the following:
Create the tile space object that has a number field (1-225), and yes/no fields for the double word, triple letter, and other special squares. Then create 225 of them and upload them to your database.
On game creation, do a search for all the tile space objects randomly sorted, and use that to populate your repeating group to make the board. Within the cell of the repeating group, you would have different groups that are shown if the space has a yes for one of the special squares.
Create a custom state for the tile space objects and when a letter is placed on it, add it to state to show that it is filled.
Next, create the tile letters that has a field for what type of letter it is and upload those to your database. When the game is created, do a search for all the tiles and then assign them to your users with custom states.
Now, you have all the pieces to create the board and all the letters are loaded and you don’t have to create them for each game. Then to make the game work, you will have to create two more data types, placed tile and placed word.
When a user drops a tile on a space, create the placed tile object that captures the user, the letter, the space, and the placed word. Add the space to the custom state showing the space is filled, add the letter to a used letter custom state, and use the custom states to show the letter on the space.
Make sure the placed word has a list field for all the placed tiles and that is how you can track the score.
Probably would need to flush out the placed word logic a little more, but I think this approach would be faster and save you considerable server capacity over time. let me know if you have any questions.
Working well so far - one question! Using custom states for the Tile Space to show when a letter has been placed there is problematic because the state is temporary.
Aka - if my connection accidentally drops and I refresh my page, the board would be wiped for me (though the people I’m playing with may still have it…?).
I’ve tried going back to save those state values (is/isn’t empty, what letter was placed, etc.) into the DB but this then again necessitates that I create 255 tile spaces per game in order to change one instead of simply referencing them by using “set list” on the Game’s Board.
Do you know of a way to keep the state persistent without having to create 255 tile spaces per game?
I imagine that you have a database object for the game that is being played that captures you and your opponent, whose turn it is, etc. If you have that object, I think you should look to save the custom state lists to this object. When you create a game, you are calling all the tile spaces in a random order; you want to save that list to the game so if you come back to it, you can load the board as it was when you started the game.
Basically, any custom state lists you are using for game, you should have an exact replica on the game object and update both whenever something happens. That way, if you lose connection, refresh the page, or save the game to play later, you don’t lose it. The only thing you have to do is have a page load workflow to set the list custom states using the game object lists to resume.
The other way you could do it is to have all the lists stored on the game object and then eliminate the custom states. Just send the game object to the page and make changes to the list fields as you play and you should be good. That would be more efficient.
This ends up also changing the original list of Tile Spaces that were supposed to only be used for setting the Game’s Board, instead of only the field on the Game’s Board. The strange thing is, if I remove a thing from the list, it only removes from the Game Board and not the Tile Spaces.
Is this what you meant?
Tile Space objects that are used to populate new games (you can see one was set to no):
You do not want to make any changes to the tile spaces, the data in that table should never be changed. On the game object, you have the list of tile spaces set. Next, you want to create another field on the game object that is a list of tile spaces called “List of Used Spaces”. When a player adds a letter to the space, add the tile space to this list. Then on the board, you can use the conditional when Current Page’s Game’s List of Used Spaces Contains Current Tile Space to show that it is not empty.
For the Tile Spaces, you should only have the 225 rows in it. Every game is using those rows, so you don’t want to change any fields on them. Same thing for the number of tiles that would be available for each game. Then when a player drops a tile on the space, create an object that links the game, the player, the tile, and the space together.
On the game object, you would want to have a list of tiles used field that you update with the dropped tiles. Then to show that the letter is on the board, the group that is inside the repeating group of spaces, use the condition i listed above and then display the value below:
Current Page’s Game’s List of Tiles Played (Object that ties everything together) :Filtered (Tile Space = Current Cell’s Tile Space): First Item’s Tile’s Letter.
That’s a lot to digest, so let me know if you have any questions.
It worked!! Thanks a million. For anyone else reading, here are a few other learnings/footnotes from @jdiaz 's advice:
“Set List” does not create a new list of things, it simply references the original list. AKA if you make changes to a thing in the reference, it also makes changes to the original list.
If you want/need a large list but the list shouldn’t be manipulated, just create a new data type and connect the former and the latter through a third data type that contains fields of both.
Use :filtered on the RG to uniquely identify spaces in RGs without using Current Cell’s X.