Skip to content

AssetTicket

Namespace Nfty.Ticket in assembly Nfty.Ticket.

public sealed record AssetTicket

One roll, complete, costing no pixels: what a server stores and hands a client.

Constructors

AssetTicket(string, string, IReadOnlyList<TicketLayer>)

public AssetTicket(string Dna, string RecipeId, IReadOnlyList<TicketLayer> Layers);

Parameters

  • Dna (string) - The identity this roll produces.
  • RecipeId (string) - The recipe rolled.
  • Layers (IReadOnlyList<TicketLayer>) - The layers that are PRESENT, in layerOrder. An absent layer is omitted entirely.

Properties

Dna

public string Dna { get; init; }

The identity this roll produces.

Layers

public IReadOnlyList<TicketLayer> Layers { get; init; }

The layers that are PRESENT, in layerOrder. An absent layer is omitted entirely.

RecipeId

public string RecipeId { get; init; }

The recipe rolled.

Methods

ComputeDna(string, IReadOnlyList<TicketLayer>)

public static string ComputeDna(string recipeId, IReadOnlyList<TicketLayer> layers);

The DNA a set of layer selections produces.

Parameters

  • recipeId (string) - The recipe rolled.
  • layers (IReadOnlyList<TicketLayer>) - The present layers.

Returns. Lowercase hex SHA-256, identical to what Dna.Compute() produces for the same selection — it IS that function; there is no second definition.

Parse(string)

public static AssetTicket Parse(string wire);

Reads a ticket back from AssetTicket.ToWire().

Parameters

  • wire (string) - The wire form.

Returns. The ticket.

Exceptions

  • FormatException - The wire is malformed (including an enum given by anything but its name, or a figure that is not finite — the message names the layer and the field), is a version this build does not read, or carries a DNA its own contents do not produce.

Remarks

The DNA is recomputed and compared, never trusted. This catches an alteration to the recipe id, an ingredient id, a variant id, or a rolled hue/saturation that moves it to another BUCKET — Dna.Compute hashes the quantized bucket index, so the DNA pins a color only to its bucket, never to a value. Kind, Model and the quantize steps are not pinned by it: the hash never sees the first two, and it sees a quantize step only through the bucket index it produces, so a wire that re-quantizes (hue 100 at step 10 and hue 205 at step 20 are both bucket 10) recomputes to the same DNA and parses successfully. This check cannot catch that and is not meant to: all three are fixed by the book for a given (recipeId, ingredientId) and cannot legitimately vary per asset, so they are verified against the MENU at plating — Plating.Plate takes kind and model from the Menu and refuses a ticket whose quantize differs from it. The ticket says what was rolled; the Menu says what the layer IS.

ToWire()

public string ToWire();

The ticket as one line: what goes in a database column or across a network.

Returns. v1|recipe|ing:var[@hue,sat,model,hq,sq]|...|dna. Every figure is INVARIANT — a comma decimal separator under a European locale would collide with the field separator itself.

Exceptions

  • InvalidOperationException - An id carries a character the wire uses as a separator where AssetTicket.Parse() would read it as one: | in any id, or : in an ingredient id. Validator refuses both in every id, so only a hand-built Menu can reach this; @ is legal and is carried.