class Test(unittest.TestCase):
    def setUp(self):
        self.mab = MultiArmedBanditBase()
        self.keys = 'abcdefghijklmnopqrstuvwxyz'
        for arm in self.keys:
            self.mab.add(arm, arm)

    def tearDown(self):
        pass

    def test_add(self):
        self.assertRaises(MultiArmedBanditError, self.mab.add)
        self.assertRaises(MultiArmedBanditError,
                          self.mab.add,
                          key=None,
                          obj='obj')
        self.assertRaises(MultiArmedBanditError,
                          self.mab.add,
                          key='key',
                          obj=None)

        self.assertEqual(len(self.keys), len(self.mab.things))
        self.assertEqual(len(self.keys), len(self.mab.arms))
        self.mab.add('foo', 'bar')
        self.assertEqual(len(self.keys) + 1, len(self.mab.things))
        self.assertEqual(len(self.keys) + 1, len(self.mab.arms))
        self.assertEqual(1.0, self.mab.arms['foo'].probability)

    def test_record_result(self):
        self.assertEqual(0, self.mab.successes)
        self.assertEqual(0, self.mab.trials)
        self.mab.record_result('a', 1, 10)
        self.assertEqual(1, self.mab.successes)
        self.assertEqual(10, self.mab.trials)
        self.mab.record_result('b', 11, 100)
        self.assertEqual(12, self.mab.successes)
        self.assertEqual(110, self.mab.trials)

        # make sure the arms are behaving as expected
        self.assertEqual(1, self.mab.arms['a'].successes)
        self.assertEqual(10, self.mab.arms['a'].trials)
        self.assertEqual(11, self.mab.arms['b'].successes)
        self.assertEqual(100, self.mab.arms['b'].trials)
        for x in 'cdefghijklmnopqrstuvwxyz':
            self.assertEqual(0, self.mab.arms[x].successes)
            self.assertEqual(0, self.mab.arms[x].trials)

    def test_trials(self):
        self.assertEqual(0, self.mab.trials)
        count = 0
        for arm in self.mab.arms.values():
            count += 1
            arm.update(trials=1)
            self.assertEqual(count, self.mab.trials)

    def test_successes(self):
        self.assertEqual(0, self.mab.successes)
        count = 0
        for arm in self.mab.arms.values():
            count += 1
            arm.update(successes=1)
            self.assertEqual(count, self.mab.successes)

    def test_total_p(self):
        total = sum(a.probability for a in self.mab.arms.values())
        self.assertEqual(total, self.mab._total_p)

        for a in self.mab.arms.itervalues():
            a.probability = a.probability * 0.5
        self.assertEqual(total * 0.5, self.mab._total_p)

    def test_next(self):
        arms = 'abcdefghijklmnopqrstuvwxyz'
        for arm in arms:
            self.mab.add(arm, arm)

        i = 1
        n = 1000
        limit = n * len(arms)
        from collections import defaultdict
        seen = defaultdict(int)
        for arm in self.mab:
            if i > limit:
                break
            seen[arm] += 1
            i += 1

        for arm in arms:
            # ensure we saw each arm n times
            self.assertEqual(n, seen[arm])
class Test(unittest.TestCase):
    def setUp(self):
        self.mab = MultiArmedBanditBase()
        self.keys = "abcdefghijklmnopqrstuvwxyz"
        for arm in self.keys:
            self.mab.add(arm, arm)

    def tearDown(self):
        pass

    def test_add(self):
        self.assertRaises(MultiArmedBanditError, self.mab.add)
        self.assertRaises(MultiArmedBanditError, self.mab.add, key=None, obj="obj")
        self.assertRaises(MultiArmedBanditError, self.mab.add, key="key", obj=None)

        self.assertEqual(len(self.keys), len(self.mab.things))
        self.assertEqual(len(self.keys), len(self.mab.arms))
        self.mab.add("foo", "bar")
        self.assertEqual(len(self.keys) + 1, len(self.mab.things))
        self.assertEqual(len(self.keys) + 1, len(self.mab.arms))
        self.assertEqual(1.0, self.mab.arms["foo"].probability)

    def test_record_result(self):
        self.assertEqual(0, self.mab.successes)
        self.assertEqual(0, self.mab.trials)
        self.mab.record_result("a", 1, 10)
        self.assertEqual(1, self.mab.successes)
        self.assertEqual(10, self.mab.trials)
        self.mab.record_result("b", 11, 100)
        self.assertEqual(12, self.mab.successes)
        self.assertEqual(110, self.mab.trials)

        # make sure the arms are behaving as expected
        self.assertEqual(1, self.mab.arms["a"].successes)
        self.assertEqual(10, self.mab.arms["a"].trials)
        self.assertEqual(11, self.mab.arms["b"].successes)
        self.assertEqual(100, self.mab.arms["b"].trials)
        for x in "cdefghijklmnopqrstuvwxyz":
            self.assertEqual(0, self.mab.arms[x].successes)
            self.assertEqual(0, self.mab.arms[x].trials)

    def test_trials(self):
        self.assertEqual(0, self.mab.trials)
        count = 0
        for arm in self.mab.arms.values():
            count += 1
            arm.update(trials=1)
            self.assertEqual(count, self.mab.trials)

    def test_successes(self):
        self.assertEqual(0, self.mab.successes)
        count = 0
        for arm in self.mab.arms.values():
            count += 1
            arm.update(successes=1)
            self.assertEqual(count, self.mab.successes)

    def test_total_p(self):
        total = sum(a.probability for a in self.mab.arms.values())
        self.assertEqual(total, self.mab._total_p)

        for a in self.mab.arms.itervalues():
            a.probability = a.probability * 0.5
        self.assertEqual(total * 0.5, self.mab._total_p)

    def test_next(self):
        arms = "abcdefghijklmnopqrstuvwxyz"
        for arm in arms:
            self.mab.add(arm, arm)

        i = 1
        n = 1000
        limit = n * len(arms)
        from collections import defaultdict

        seen = defaultdict(int)
        for arm in self.mab:
            if i > limit:
                break
            seen[arm] += 1
            i += 1

        for arm in arms:
            # ensure we saw each arm n times
            self.assertEqual(n, seen[arm])