# Puzzle Set Resource
**Status**: Implemented | 2022

## Background

These puzzle sets define a set of puzzles for GNOME Crosswords. Each
puzzle set is stored in a single GResource file, named
`$ID.gresource`, where $ID is a unique id for the puzzle set.

## GResource file structure

The resource MUST have the following structure:

```
/org/gnome/Crosswords/puzzle-set/$ID/puzzle.config
/org/gnome/Crosswords/puzzle-set/$ID/...
```

The $ID of the file is a string that identifies the game. It must be
suitable for being used as a prefix for g_resource
directories/filenames. You cannot have a `/` character embedded within
it.

All resources below are relative to this path. Any resources outside
of this directory path are ignored.

The file `puzzle.config` is required and defined below. Other files
can be stored within the resource and can have arbitrary names. They
must be stored in the same directory as the config file, though.

## puzzle.config
The `puzzle.config` is a Key File and is loaded first. It contains all
the information to define the puzzle set. It must contain the `[Puzzle
Set]` header that defines the overall parameters of the puzzle set. It
contains information used by the reource, as well as any UI elements
internally (such as the Picker or Play widgets).

Additional sections are described below:

### [Puzzle Set]
This section is required, and the same for every resource PuzzleSet.

Fields:
```
ID=$ID
ShortName=Short description
LongName=A longer description of the game
Picker=<picker type>
Locale=<locale>
Disabled=boolean
IconName=<string>
IconText=<string>
ColorName=<color>

```

The `ID` is the same as the directory it's in, and MUST match the
location of this file. It must also be globally unique. We don't have
a registry for these yet, but will look into having one in the future
if we run into collisions.

:::{important}
Any id that's prefixed with `"devel-"` will only be shown
in a development build of Crosswords. This is used for testing
puzzle, and shouldn't be expected to work with any shipping game.
:::

The short and long names are used to display the puzzles to the
user. It is similar to what's seen in a desktop file. The short name
appears in the initial sidebar.

The `Picker` type is the type of display used for portraying a list of
puzzles. Currently picker can only be `list` and `grid`. They are
described in greater deatil below.

The Locale is a fully-qualified locale for the puzzles within the
Puzzle Set. It is used to provide information about the puzzle set and
let the user filter out puzzles they don't understand. Note that we
only support UTF-8 .ipuz files, so we don't honor the codeset
attribute. Similarly, we ignore any modifiers.

If the puzzle set should be included in all languages, then you should
choose the `"C"` locale. In that instance, it's recommended that the
desktop file be translated.

`Disabled` indicates whether to display the puzzle set in the game. This
is useful for developing new puzzle-sets

The `ColorName` optionally is one of:
 * green
 * blue
 * yellow
 * orange
 * red
 * purple

This is used as an accent color for the puzzle. If missing, a color is
picked randomly based on the hash of the ID, and will be stable across
runs. It's recommended to keep this field unset as it will result in a
more consistently random look.

The `IconName` field is a symbolic to put as an icon for the puzzle
set. The game will pick one based on the picker type and downlowder
status, and it's not normally needed in puzzle sets. If a specific
icon is desired, talk to the crosswords team about making sure it's
installed.

The `IconText` field is an alternative to the icon. If set, the
**first character** of this string will be displayed in the
icon. Additional characters will be ignored.

### [Picker Grid]
This section sets up the puzzle for grid-type games. It is only
relevant when `Picker=grid`

Fields:
```
Header=Header text
GridStyle=$STYLE
HeaderFace=font to display the header in
ShowProgress=boolean
PuzzleImage=image-file.png
Width=int
Height=int
```

Notes:
* `Header` is required
* `GridStyle` can be "open", "lock-and-image", or "riddle"
* `Width` and `Height` are required and determine the shape of the
  grid. No more than `Width × Height` puzzle will be loaded
* Grid-style pickers don't have downloaders

### [Picker List]
This section sets up the puzzle for lists of games. It is only relevant when `Picker=list`

Fields:
```
Header=Header text
SubHeader=Sub Header text
HeaderFace=font to display the header in
SubHeaderFace=font to display the sub header in
UseButton=boolean
ShowProgress=boolean
PuzzleImage=image-file.png
URL=url
```

Notes:
* `Header` is required
* If `UseButton` is True, then a separate `[Picker Button]` section is
  loaded to set up the button and its action. This section **must**
  exist.

### [Picker Button]
This section configures the button and its action. Currently, we
support two types of actions for each button. The first is a simple
URI dialog for loading files and copying them to the puzzle-set
directory. The second calls a script with appropriate arguments.

Fields:
```
Label=Label text
Type=$TYPE
```

Notes:
* Type can have two values: `file` or `downloader`.
    * **file**: Brings up a file chooser dialog. It's not expected that other sections will use this, as it's redundant to the default one. It may be useful, though.
    * **downloader**: Runs a separate downloader command in order to download the puzzle. There **must** be a separate `Downloader` section.

### [Downloader]
This section configures both how the downloader behaves, and optionally if there's a dialog displayed for user input. It can be used to customize the dialog.

:::{tip}
More information about the specifics of the downloader can be found in
[puzzle-downloader.md](/designs/crosswords-player/puzzle-downloader.md).
:::

Fields:
```
Type=$TYPE
Command=$COMMAND
PrimaryText=Dialog primary label text
SecondaryText=Dialog secondary label text (optional)
LinkUri=URI (optional)
LinkText=Anchor text for link (optional)
DefaultValue=$DOMAIN|$DATE|$NUMBER (optional)
LowerValue=$DATE|$NUMBER (optional)
UpperValue=$DATE|$NUMBER
TimeZone=$TZ (optional)
ConvertPuzToIpuz=true, if the downloader exports the a .puz file instead of an .ipuz file (optional)
```

Notes:
* `Type` is required and can support five values, `auto`, `date`, `uri`, `number`, and `entry`:
    * **auto**: No user input is requested and the downloader command is run immediately
    * **date**: A dialog is shown with a date selector. The date will be passed to the downloader.
    * **uri**: A dialog is shown with a uri selector. The uri will be validated and passed to the downloader
    * **number**: A dialog is shown with a number selector. The number will be used to pass into the downloader.
    * **entry**: A dialog is shown with an entry for open text. The string will be passed to the downloader with no validation done
* `Command` required. See [puzzle-downloader.md](/designs/crosswords-player/puzzle-downloader.md) for more information on it


## Loading Puzzles
Puzzles can be stored within the resource. When they are stored there, they are read-only and cannot be deleted by the user.

### [Puzzle#]
There are Puzzle sections that define individual puzzles for the game. They must be sequential starting at Puzzle1, and the `PuzzleName` must be found within the resource. Where appropriate, thumbnails can be included as well. They must list .ipuz files, as .puz files are not supported in puzzle sets.

This is supported for both list and grid Pickers, and is required for Grid-style pickers

Fields:
```
PuzzleName=puzzle.ipuz
```
