```python
"""Cut a fabric roll for the greatest takings the price board allows."""


def cut_roll(length: int, board: list[tuple[int, int]]) -> dict:
    if isinstance(length, bool) or not isinstance(length, int) or length < 0:
        raise ValueError("length must be a non-negative whole number")
    
    # Sort boards by price in descending order
    board.sort(key=lambda x: -x[1])
    
    # Initialize DP table to store the maximum takings for each roll length
    best = [0] * (length + 1)
    
    # Iterate over each possible roll length
    for metres in range(1, length + 1):
        best[metres] = -1
        # Try cutting each board piece if it fits the current length
        for piece, price in board:
            if piece <= metres and price + best[metres - piece] > best[metres]:
                best[metres] = price + best[metres - piece]
        
        # If not cut, consider scrapping the last metre
        if best[metres - 1] > best[metres]:
            best[metres] = best[metres - 1]
    
    # Reconstruct the pieces used for the maximum takings
    pieces = []
    current_metres = length
    
    while current_metres > 0:
        piece_size = board[best[current_metres] - price][0]
        pieces.append(piece_size)
        current_metres -= piece_size
    
    # Reverse the list of pieces to get them in the order they were cut
    pieces.reverse()
    
    return {"takings": best[length], "pieces": pieces}
```