Problem-domain objects to transfer

A RESTful web server works by transferring representations of object state. We'll define a few simple objects to transfer from a RESTful server to a RESTful client. This application serves a collection of tuples that represent dominoes. We'll include a property to discern whether a domino has the same value on both sides; a piece sometimes called a spinner or a double. The core definition of the Domino class is as follows:

from dataclasses import dataclass, asdict, astuple
from typing import List, Dict, Any, Tuple, NamedTuple
import random

@dataclass(frozen=True)
class Domino:
v_0: int
v_1: int

@property
def double(self):
return self.v_0 == self.v_1

def __repr__(self):
if self.double:
return f"Double({self.v_0})"
else:
return f"Domino({self.v_0}, {self.v_1})"

When we play a game of dominoes, the tiles are often shuffled by the players and dealt into hands. The remaining dominoes form a pile sometimes called a boneyard. This is analogous to a deck of cards, but dominoes aren't often stacked, and can instead be left lying in a corner of the table. In some four-player games, all 28 dominoes are used. The Boneyard class definition is as follows:

class Boneyard:

def __init__(self, limit=6):
self._dominoes = [
Domino(x, y) for x in range(0, limit + 1) for y in range(0, x + 1)
]
random.shuffle(self._dominoes)

def deal(self, tiles: int = 7, hands: int = 4) -> List[List[Tuple[int, int]]]:
if tiles * hands > len(self._dominoes):
raise ValueError(f"tiles={tiles}, hands={hands}")
return [self._dominoes[h:h + tiles]
for h in range(0, tiles * hands, tiles)]

The individual Domino instances are created from a rather complex-looking list comprehension. The two for clauses can be transformed into for statements that look like the following:

for x in range(0, limit+1):
for y in range(0, x+1):
Domino(x, y)

This design assures that ; it will generate a Domino(2, 1) instance but will not create a Domino(1, 2) instance. This will create the 28 dominoes in a standard double-six set. 

Once the dominoes are shuffled, then dealing them is a matter of taking slices from the list. When dealing hands of seven tiles, the h variable has values of 0, 7, 14, and 21. This leads to slices as [0: 7], [7: 14], [14: 21], and [21: 28]; this divides the pool into four hands of seven tiles each.

A simple demonstration of how this works is shown as follows:

>>> random.seed(2)
>>> b = Boneyard(limit=6)
>>> b.deal(tiles=7, hands=2)
[[Domino(2, 0), Double(5), Domino(5, 2), Domino(5, 0), Double(0), Domino(6, 3), Domino(2, 1)], [Domino(3, 1), Double(4), Domino(5, 1), Domino(5, 4), Domino(6, 2), Domino(4, 2), Domino(5, 3)]]

First, a Boneyard object is built; the limit value defines this as a double-six set of 28 individual pieces. When two hands of seven tiles are dealt, a predictable pair of hands are created because the random number generator is seeded with a fixed value, two, for the seed.

In some games, the highest double determines who plays first. In these two hands, the player with Double(5) would be the first to play.

Let's look at how we can create a simple application and server.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset