import pandas as pd


class Board(object):
    def __init__(self, match_count, keys=None):
        """Initialize match display board.

        Args:
            match_count (int): Number of matches.
            keys (list[str]): Keys for deciding whether the match is valid.
                Default value is `["club"]`.

        """
        self._upper = []
        self._lower = []

        self.match_count = match_count
        self.keys = keys if keys else ["club"]

    def add(self, player):
        """Add player to board.

        This match-making algorithm acts upon a Guidelines for Caruta
        Competition proposed by All Japan Caruta Association.

        Args:
            player (pd.Series): Player to be added.

        See Also:
            http://www.karuta.or.jp/kitei/kyougikai.pdf

        """
        if self._on_upper():
            self._upper.append(player)
            return

        if self._is_valid(self._single_player, player):
            self._lower.append(player)
            return

        if not self._is_last(self._upper):
            self._upper.append(player)
            return

        if not self._is_last(self._lower):
            self._change_players(player)
            return

        raise ValueError("Match-making is already completed.")

    @property
    def _single_player(self):
        assert len(self._upper) > len(self._lower)
        return self._upper[len(self._lower)]

    def _change_players(self, player):
        opponent = self._single_player
        for i, a, b in enumerate(zip(self._upper, self._lower)):
            if self._is_valid(player, b) and self._is_valid(opponent, a):
                self._upper[i] = player
                self._lower.append(a)
                return

            if self._is_valid(a, player) and self._is_valid(opponent, b):
                self._lower[i] = player
                self._lower.append(b)
                return

        raise ValueError("There is no changeable player.")

    def _is_valid(self, a, b):
        for key in self.keys:
            if a.ix[key] == b.ix[key]:
                return False
        return True

    def _is_last(self, lst):
        return len(lst) >= self.match_count

    def _on_upper(self):
        return len(self._upper) == len(self._lower)

@@ -473,17 +473,20 @@
    def a
-d
+ppen
 d(self, 
@@ -506,17 +506,20 @@
     %22%22%22A
-d
+ppen
 d player
@@ -1218,32 +1218,32 @@
         return%0A%0A
-
         raise Va
@@ -1286,24 +1286,800 @@
 mpleted.%22)%0A%0A
+    def validate(self):%0A        %22%22%22Check all organized matches are valid.%22%22%22%0A        for a, b in zip(self._upper, self._lower):%0A            if not self._is_valid(a, b):%0A                return False%0A%0A        return True%0A%0A    def index(self, player):%0A        return self.all.index(player)%0A%0A    def __contains__(self, item):%0A        return item in self.all%0A%0A    def __getitem__(self, i):%0A        return self.all%5Bi%5D%0A%0A    def __len__(self):%0A        return len(self.all)%0A%0A    @property%0A    def all(self):%0A        return list(sum(zip(self._upper, self._lower), ()))%0A%0A    @property%0A    def completed(self):%0A        %22%22%22Check match-making is completed.%22%22%22%0A        if not self.validate():%0A            return False%0A        return len(self._upper) == len(self._lower) == self.match_count%0A%0A
     @propert

Add hook methods