Example #1
0
def add_numbers():
    reqeust_str = request.args.get('requestStr', '', type=str)
    # handler = RequestHandler(MongoDBConnection('test_app', 'test'))
    # handler = RequestHandler(SQLConnection(':memory:', 'test'))
    handler = DiceTablesRequestHandler(max_dice_value=6000)
    table_obj = handler.get_response(reqeust_str)
    # handler.close_connection()
    if 'error' in table_obj:
        return jsonify(table_obj), 400
    return jsonify(table_obj), 200
Example #2
0
 def test_request_dice_table_construction_request_exceeds_max_dice_value(
         self):
     handler = DiceTablesRequestHandler(max_dice_value=12)
     handler.request_dice_table_construction('2*Die(6)')
     handler.request_dice_table_construction('6*WeightedDie({1: 2, 2: 10})')
     with self.assertRaises(ValueError) as cm:
         handler.request_dice_table_construction('1*Die(6)&1*Die(7)')
     self.assertEqual(
         cm.exception.args[0],
         'The sum of all max(die_size, len(die_dict))*die_number must be <= 12'
     )
Example #3
0
    def test_request_dice_table_construction_exceed_max_dice_value_based_on_max_of_dict_len_and_die_size(
            self):
        handler = DiceTablesRequestHandler(max_dice_value=12)

        self.assertEqual(len(Exploding(Die(4)).get_dict()), 10)
        handler.request_dice_table_construction('Exploding(Die(4))')
        self.assertEqual(len(Exploding(Die(5)).get_dict()), 13)
        self.assertEqual(Exploding(Die(5)).get_size(), 5)
        self.assertRaises(ValueError, handler.request_dice_table_construction,
                          'Exploding(Die(5))')

        self.assertEqual(WeightedDie({1: 1, 12: 1}).get_size(), 12)
        handler.request_dice_table_construction('WeightedDie({1: 1, 12: 1})')
        self.assertEqual(len(WeightedDie({1: 1, 13: 1}).get_dict()), 2)
        self.assertEqual(WeightedDie({1: 1, 13: 1}).get_size(), 13)
        self.assertRaises(ValueError, handler.request_dice_table_construction,
                          'WeightedDie({1: 1, 13: 1})')
def create_json_text(number, die_request):
    handler = DiceTablesRequestHandler()
    base_json = json.dumps(handler.get_response(die_request),
                           sort_keys=True,
                           indent=4)
    return 'const {}{} = {};\n'.format(name_base, number, base_json)
Example #5
0
 def test_init_set_max_dice_value(self):
     handler = DiceTablesRequestHandler(2)
     self.assertEqual(handler.max_dice_value, 2)
Example #6
0
 def setUp(self):
     self.handler = DiceTablesRequestHandler()
Example #7
0
class TestRequestHandler(unittest.TestCase):
    def setUp(self):
        self.handler = DiceTablesRequestHandler()

    def test_init_default_max_score(self):
        self.assertEqual(self.handler.max_dice_value, 12000)

    def test_init_set_max_dice_value(self):
        handler = DiceTablesRequestHandler(2)
        self.assertEqual(handler.max_dice_value, 2)

    def test_get_table(self):
        self.assertEqual(self.handler.get_table(), DiceTable.new())
        expected = DiceTable.new().add_die(Die(6), 2)
        self.handler.request_dice_table_construction('2*Die(6)')
        self.assertEqual(self.handler.get_table(), expected)

    def test_request_dice_table_empty_string(self):
        self.handler.request_dice_table_construction('')
        self.assertEqual(self.handler.get_table(), DiceTable.new())

    def test_request_dice_table_only_whitespace(self):
        self.handler.request_dice_table_construction('   ')
        self.assertEqual(self.handler.get_table(), DiceTable.new())

    def test_request_dice_table_single_die_no_number(self):
        self.handler.request_dice_table_construction('Die(3)')
        self.assertEqual(self.handler.get_table(),
                         DiceTable.new().add_die(Die(3), 1))

    def test_request_dice_table_single_die_with_number(self):
        self.handler.request_dice_table_construction('2*Die(3)')
        self.assertEqual(self.handler.get_table(),
                         DiceTable.new().add_die(Die(3), 2))

    def test_request_dice_table_multiple_dice_without_number(self):
        self.handler.request_dice_table_construction('Die(3)&Die(2)')
        self.assertEqual(self.handler.get_table(),
                         DiceTable.new().add_die(Die(2)).add_die(Die(3)))

    def test_request_dice_table_multiple_dice_with_number(self):
        self.handler.request_dice_table_construction('2*Die(3) & 2*Die(2)')
        self.assertEqual(self.handler.get_table(),
                         DiceTable.new().add_die(Die(2), 2).add_die(Die(3), 2))

    def test_request_dice_table_construction_request_exceeds_max_dice_value(
            self):
        handler = DiceTablesRequestHandler(max_dice_value=12)
        handler.request_dice_table_construction('2*Die(6)')
        handler.request_dice_table_construction('6*WeightedDie({1: 2, 2: 10})')
        with self.assertRaises(ValueError) as cm:
            handler.request_dice_table_construction('1*Die(6)&1*Die(7)')
        self.assertEqual(
            cm.exception.args[0],
            'The sum of all max(die_size, len(die_dict))*die_number must be <= 12'
        )

    def test_request_dice_table_construction_exceed_max_dice_value_based_on_max_of_dict_len_and_die_size(
            self):
        handler = DiceTablesRequestHandler(max_dice_value=12)

        self.assertEqual(len(Exploding(Die(4)).get_dict()), 10)
        handler.request_dice_table_construction('Exploding(Die(4))')
        self.assertEqual(len(Exploding(Die(5)).get_dict()), 13)
        self.assertEqual(Exploding(Die(5)).get_size(), 5)
        self.assertRaises(ValueError, handler.request_dice_table_construction,
                          'Exploding(Die(5))')

        self.assertEqual(WeightedDie({1: 1, 12: 1}).get_size(), 12)
        handler.request_dice_table_construction('WeightedDie({1: 1, 12: 1})')
        self.assertEqual(len(WeightedDie({1: 1, 13: 1}).get_dict()), 2)
        self.assertEqual(WeightedDie({1: 1, 13: 1}).get_size(), 13)
        self.assertRaises(ValueError, handler.request_dice_table_construction,
                          'WeightedDie({1: 1, 13: 1})')

    def test_request_dice_table_construction_leading_and_trailing_whitespace(
            self):
        self.handler.request_dice_table_construction(
            '   2  *  Die( 5 )   &   1  *  Die( 4 )   ')
        self.assertEqual(self.handler.get_table(),
                         DiceTable.new().add_die(Die(5), 2).add_die(Die(4)))

    def test_request_dice_table_construction_all_dice(self):
        all_dice = [
            Die(die_size=2),
            ModDie(2, modifier=-1),
            WeightedDie(dictionary_input={
                3: 4,
                5: 6,
                7: 8,
                9: 0
            }),
            ModWeightedDie({
                1: 2,
                3: 4
            }, 0),
            StrongDie(input_die=Die(2), multiplier=2),
            Exploding(Die(2), explosions=1),
            ExplodingOn(Die(3), explodes_on=(1, 2)),
            Modifier(modifier=-100),
            BestOfDicePool(Die(2), 2, 1),
            WorstOfDicePool(Die(2), 2, 1),
            UpperMidOfDicePool(Die(2), 2, 1),
            LowerMidOfDicePool(Die(2), 2, 1)
        ]

        for die in all_dice:
            self.handler.request_dice_table_construction(
                '2 * {!r}'.format(die))
            self.assertEqual(self.handler.get_table(),
                             DiceTable.new().add_die(die, 2))

    def test_request_dice_table_construction_with_kwargs(self):
        self.handler.request_dice_table_construction(
            'ModDie(die_size=2, modifier=3)')
        self.assertEqual(self.handler.get_table(),
                         DiceTable.new().add_die(ModDie(2, 3)))

    def test_request_dice_table_construction_mixed_case(self):
        request = 'dIe(DiE_sIzE=3)'
        self.handler.request_dice_table_construction(request)
        self.assertEqual(self.handler.get_table(),
                         DiceTable.new().add_die(Die(3)))

    def test_disallowed_delimiters_raise_value_error(self):
        expected_allowed = "!\"#$%&'*+./;<>?@\\^`|~\t\n\r"
        answer = ""
        for char in string.printable:
            try:
                self.handler.request_dice_table_construction(
                    'Die(6)', num_delimiter=char)
                answer += char
            except ValueError as e:
                self.assertTrue(e.args[0].startswith('Delimiters may not be'))
        self.assertEqual(expected_allowed, answer)

    def test_request_dice_table_construction_with_all_allowed_delimiters(self):
        allowed = "!\"#$%&'*+./;<>?@\\^`|~\t\n\r"

        for index, num_delimiter in enumerate(allowed):
            pairs_delimiter = allowed[index - 1]
            request_str = f'2{num_delimiter}Die(2){pairs_delimiter}Die(3)'
            expected = DiceTable.new().add_die(Die(2), 2).add_die(Die(3))

            self.handler.request_dice_table_construction(
                request_str,
                num_delimiter=num_delimiter,
                pairs_delimiter=pairs_delimiter)
            self.assertEqual(self.handler.get_table(), expected)

    def test_request_dice_table_construction_each_error_raised(self):
        instructions = '2*Die(5) & *Die(4)'
        self.assertRaises(ValueError,
                          self.handler.request_dice_table_construction,
                          instructions)

        instructions = '3 die(3)'
        self.assertRaises(SyntaxError,
                          self.handler.request_dice_table_construction,
                          instructions)

        instructions = '3 * die("a")'
        self.assertRaises(AttributeError,
                          self.handler.request_dice_table_construction,
                          instructions)

        instructions = '3 * moddie(2)'
        self.assertRaises(TypeError,
                          self.handler.request_dice_table_construction,
                          instructions)

        instructions = 'didfde(3)'
        self.assertRaises(ParseError,
                          self.handler.request_dice_table_construction,
                          instructions)

        instructions = 'die(1, 2, 3)'
        self.assertRaises(IndexError,
                          self.handler.request_dice_table_construction,
                          instructions)

        instructions = 'die(30000)'
        self.assertRaises(LimitsError,
                          self.handler.request_dice_table_construction,
                          instructions)

        instructions = 'die(-1)'
        self.assertRaises(InvalidEventsError,
                          self.handler.request_dice_table_construction,
                          instructions)

        instructions = '-2*die(2)'
        self.assertRaises(DiceRecordError,
                          self.handler.request_dice_table_construction,
                          instructions)

    def test_request_dice_table_construction_all_errors_are_caught(self):
        errors = (ValueError, SyntaxError, AttributeError, IndexError,
                  TypeError, ParseError, LimitsError, InvalidEventsError,
                  DiceRecordError)
        instructions = [
            '* Die(4)', '3 die(3)', '3 & die(3)', 'Die(4) * 3 * Die(5)',
            '4 $ die(5)', '2 * die(5) $ 4 * die(6)', 'die("a")', 'die(5',
            'die(5000)', 'notadie(5)', 'die(1, 2, 3)', 'WeightedDie({1, 2})',
            'WeightedDie({-1: 1})', 'Die(-1)', 'WeightedDie({1: -1})',
            '-2*Die(2)', 'ModDie(2)'
        ]
        for instruction in instructions:
            self.assertRaises(errors,
                              self.handler.request_dice_table_construction,
                              instruction)

    def test_make_dict_simple_table(self):
        answer = make_dict(DiceTable.new().add_die(Die(4)))
        expected = {
            'name':
            '<DiceTable containing [1D4]>',
            'diceStr':
            'Die(4): 1',
            'data': {
                'x': (1, 2, 3, 4),
                'y': (25.0, 25.0, 25.0, 25.0)
            },
            'tableString':
            '1: 1\n2: 1\n3: 1\n4: 1\n',
            'forSciNum': [{
                'roll': 1,
                'mantissa': '1.00000',
                'exponent': '0'
            }, {
                'roll': 2,
                'mantissa': '1.00000',
                'exponent': '0'
            }, {
                'roll': 3,
                'mantissa': '1.00000',
                'exponent': '0'
            }, {
                'roll': 4,
                'mantissa': '1.00000',
                'exponent': '0'
            }],
            'range': (1, 4),
            'mean':
            2.5,
            'stddev':
            1.118,
            'roller': {
                'height':
                "4",
                'aliases': [{
                    'primary': "4",
                    'alternate': "4",
                    'primaryHeight': "4"
                }, {
                    'primary': "3",
                    'alternate': "3",
                    'primaryHeight': "4"
                }, {
                    'primary': "2",
                    'alternate': "2",
                    'primaryHeight': "4"
                }, {
                    'primary': "1",
                    'alternate': "1",
                    'primaryHeight': "4"
                }]
            }
        }

        self.assertEqual(answer, expected)

    def test_make_dict_large_number_table(self):
        table = DiceTable({1: 1, 2: 9**351}, DiceRecord.new())
        answer = make_dict(table)
        expected = {
            'data': {
                'x': (1, 2),
                'y': (0.0, 100.0)
            },
            'forSciNum': [{
                'roll': 1,
                'mantissa': '1.00000',
                'exponent': '0'
            }, {
                'roll': 2,
                'mantissa': '8.69202',
                'exponent': '334'
            }],
            'mean':
            2.0,
            'range': (1, 2),
            'name':
            '<DiceTable containing []>',
            'diceStr':
            '',
            'stddev':
            0.0,
            'tableString':
            '1: 1\n2: 8.692e+334\n',
            'roller': {
                'height':
                ('8692021926532582239431197828370635593634075173099158789854434049807997760319275071636088'
                 '5895145922991572345585185250800940116508114750525076655926616148114182143549026229853337'
                 '9940869208919850517403157109776051593152797345404989883632793071982398710942373198113120'
                 '40403122389178667907944352945294284623021821750094845717881664249886010'
                 ),
                'aliases': [{
                    'primary': "1",
                    "alternate": "2",
                    "primaryHeight": "2"
                }, {
                    "primary":
                    "2",
                    "alternate":
                    "2",
                    "primaryHeight":
                    ("8692021926532582239431197828370635593634075173099158789854434049807997760319"
                     "2750716360885895145922991572345585185250800940116508114750525076655926616148"
                     "1141821435490262298533379940869208919850517403157109776051593152797345404989"
                     "8836327930719823987109423731981131204040312238917866790794435294529428462302"
                     "1821750094845717881664249886010")
                }]
            }
        }

        self.assertEqual(answer, expected)

    def test_make_dict_complex_table(self):
        table = DiceTable.new().add_die(WeightedDie({
            1: 1,
            2: 99
        }), 3).add_die(Die(3), 4)
        answer = make_dict(table)
        expected = {
            'name':
            '<DiceTable containing [3D2  W:100, 4D3]>',
            'diceStr':
            'WeightedDie({1: 1, 2: 99}): 3\nDie(3): 4',
            'data': {
                'x': (7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18),
                'y': (1.234567901234568e-06, 0.0003716049382716049,
                      0.03777901234567901, 1.3467864197530863,
                      5.16049012345679, 12.566786419753084, 19.861979012345678,
                      23.34457160493827, 19.53086790123457, 12.124566666666665,
                      4.8279, 1.1978999999999997)
            },
            'tableString':
            (' 7: 1\n' + ' 8: 301\n' + ' 9: 30,601\n' + '10: 1,090,897\n' +
             '11: 4,179,997\n' + '12: 1.018e+7\n' + '13: 1.609e+7\n' +
             '14: 1.891e+7\n' + '15: 1.582e+7\n' + '16: 9,820,899\n' +
             '17: 3,910,599\n' + '18: 970,299\n'),
            'forSciNum': [{
                'roll': 7,
                'mantissa': '1.00000',
                'exponent': '0'
            }, {
                'roll': 8,
                'mantissa': '3.01000',
                'exponent': '2'
            }, {
                'roll': 9,
                'mantissa': '3.06010',
                'exponent': '4'
            }, {
                'roll': 10,
                'mantissa': '1.09090',
                'exponent': '6'
            }, {
                'roll': 11,
                'mantissa': '4.18000',
                'exponent': '6'
            }, {
                'roll': 12,
                'mantissa': '1.01791',
                'exponent': '7'
            }, {
                'roll': 13,
                'mantissa': '1.60882',
                'exponent': '7'
            }, {
                'roll': 14,
                'mantissa': '1.89091',
                'exponent': '7'
            }, {
                'roll': 15,
                'mantissa': '1.58200',
                'exponent': '7'
            }, {
                'roll': 16,
                'mantissa': '9.82090',
                'exponent': '6'
            }, {
                'roll': 17,
                'mantissa': '3.91060',
                'exponent': '6'
            }, {
                'roll': 18,
                'mantissa': '9.70299',
                'exponent': '5'
            }],
            'range': (7, 18),
            'mean':
            13.97,
            'stddev':
            1.642,
            'roller': {
                'aliases': [{
                    'alternate': '16',
                    'primary': '18',
                    'primaryHeight': '11643588'
                }, {
                    'alternate': '15',
                    'primary': '16',
                    'primaryHeight': '48494376'
                }, {
                    'alternate': '15',
                    'primary': '17',
                    'primaryHeight': '46927188'
                }, {
                    'alternate': '15',
                    'primary': '11',
                    'primaryHeight': '50159964'
                }, {
                    'alternate': '15',
                    'primary': '10',
                    'primaryHeight': '13090764'
                }, {
                    'alternate': '14',
                    'primary': '15',
                    'primaryHeight': '24512328'
                }, {
                    'alternate': '14',
                    'primary': '9',
                    'primaryHeight': '367212'
                }, {
                    'alternate': '14',
                    'primary': '8',
                    'primaryHeight': '3612'
                }, {
                    'alternate': '13',
                    'primary': '14',
                    'primaryHeight': '8792388'
                }, {
                    'alternate': '13',
                    'primary': '7',
                    'primaryHeight': '12'
                }, {
                    'alternate': '12',
                    'primary': '13',
                    'primaryHeight': '39850836'
                }, {
                    'alternate': '12',
                    'primary': '12',
                    'primaryHeight': '81000000'
                }],
                'height':
                '81000000',
            },
        }

        self.assertEqual(answer, expected)

    def test_make_dict_mean_and_stddev_rounding(self):
        table = DetailedDiceTable.new().add_die(WeightedDie({1: 1, 2: 2}))
        answer = make_dict(table)
        self.assertEqual(table.calc.mean(), 1.6666666666666667)
        self.assertEqual(answer['mean'], 1.667)

        self.assertEqual(table.calc.stddev(3), 0.471)
        self.assertEqual(answer['stddev'], 0.471)

    def test_make_dict_can_handle_gaps(self):
        table = DiceTable.new().add_die(WeightedDie({1: 1, 3: 1}))
        answer = make_dict(table)
        expected = {
            'name':
            '<DiceTable containing [1D3  W:2]>',
            'diceStr':
            'WeightedDie({1: 1, 2: 0, 3: 1}): 1',
            'data': {
                'x': (1, 2, 3),
                'y': (50.0, 0.0, 50.0)
            },
            'tableString':
            '1: 1\n2: 0\n3: 1\n',
            'forSciNum': [{
                'roll': 1,
                'mantissa': '1.00000',
                'exponent': '0'
            }, {
                'roll': 2,
                'mantissa': '0',
                'exponent': '0'
            }, {
                'roll': 3,
                'mantissa': '1.00000',
                'exponent': '0'
            }],
            'range': (1, 3),
            'mean':
            2,
            'stddev':
            1.0,
            'roller': {
                'height':
                "2",
                'aliases': [{
                    'primary': "3",
                    'alternate': "3",
                    'primaryHeight': "2"
                }, {
                    'primary': "1",
                    'alternate': "1",
                    'primaryHeight': "2"
                }]
            }
        }
        self.assertEqual(answer, expected)

    def test_get_response_empty_string_and_whitespace(self):
        empty_str_answer = self.handler.get_response('')

        empty_response = {
            'data': {
                'x': (0, ),
                'y': (100.0, )
            },
            'forSciNum': [{
                'roll': 0,
                'mantissa': '1.00000',
                'exponent': '0'
            }],
            'mean': 0.0,
            'range': (0, 0),
            'name': '<DiceTable containing []>',
            'diceStr': '',
            'stddev': 0.0,
            'tableString': '0: 1\n',
            'roller': {
                'aliases': [{
                    'alternate': '0',
                    'primary': '0',
                    'primaryHeight': '1'
                }],
                'height':
                '1',
            }
        }
        self.assertEqual(empty_str_answer, empty_response)

        whitespace_str_answer = self.handler.get_response('   ')
        self.assertEqual(whitespace_str_answer, empty_response)

    def test_get_response(self):
        response = self.handler.get_response('Die(2)')
        expected = {
            'diceStr':
            'Die(2): 1',
            'name':
            '<DiceTable containing [1D2]>',
            'data': {
                'x': (1, 2),
                'y': (50.0, 50.0)
            },
            'tableString':
            '1: 1\n2: 1\n',
            'forSciNum': [{
                'roll': 1,
                'mantissa': '1.00000',
                'exponent': '0'
            }, {
                'roll': 2,
                'mantissa': '1.00000',
                'exponent': '0'
            }],
            'range': (1, 2),
            'mean':
            1.5,
            'stddev':
            0.5,
            'roller': {
                'aliases': [{
                    'alternate': '2',
                    'primary': '2',
                    'primaryHeight': '2'
                }, {
                    'alternate': '1',
                    'primary': '1',
                    'primaryHeight': '2'
                }],
                'height':
                '2',
            },
        }
        self.assertEqual(response, expected)

    def test_get_response_error_response_all_errors(self):
        instructions = '2*Die(5) & *Die(4)'
        response = self.handler.get_response(instructions)
        self.assertEqual(
            response, {
                "error": "invalid literal for int() with base 10: ' '",
                "type": "ValueError"
            })

        instructions = '3 die(3)'
        response = self.handler.get_response(instructions)
        self.assertEqual(response, {
            'error': 'invalid syntax',
            'type': 'SyntaxError'
        })

        instructions = '3 * die("a")'
        response = self.handler.get_response(instructions)
        self.assertEqual(response, {
            'error': "'Str' object has no attribute 'n'",
            'type': 'AttributeError'
        })

        instructions = '3 * moddie(1)'
        response = self.handler.get_response(instructions)
        self.assertEqual(
            response, {
                'error':
                "__init__() missing 1 required positional argument: 'modifier'",
                'type': 'TypeError'
            })

        instructions = 'didfde(3)'
        response = self.handler.get_response(instructions)
        self.assertEqual(
            response, {
                'error': 'Die class: <didfde> not recognized by parser.',
                'type': 'ParseError'
            })

        instructions = 'die(1, 2, 3)'
        response = self.handler.get_response(instructions)
        self.assertEqual(response, {
            'error': 'tuple index out of range',
            'type': 'IndexError'
        })

        instructions = 'die(30000)'
        response = self.handler.get_response(instructions)
        self.assertEqual(response, {
            'error': 'Max die_size: 500',
            'type': 'LimitsError'
        })

        instructions = 'die(-1)'
        response = self.handler.get_response(instructions)
        self.assertEqual(
            response, {
                'error':
                'events may not be empty. a good alternative is the identity - {0: 1}.',
                'type': 'InvalidEventsError'
            })

        instructions = '-2*die(2)'
        response = self.handler.get_response(instructions)
        self.assertEqual(
            response, {
                'error':
                'Tried to add_die or remove_die with a negative number.',
                'type': 'DiceRecordError'
            })