diff --git a/app.py b/app.py index 7ae7cd5..ab38793 100644 --- a/app.py +++ b/app.py @@ -1,5 +1,7 @@ from flask import Flask from flask_restx import Api, Resource, fields +from marshmallow import Schema, fields, validate +from models import dice_model, ability_model, hp_model import random app = Flask(__name__) @@ -11,20 +13,18 @@ dice = api.namespace('dice', description='Dice operations') ability = api.namespace('ability', description='Ability operations') hp = api.namespace('hp', description='HP operations') -dice_model = dice.model('Dice', { - 'quantity': fields.Integer(required=True, description='The number of dice to roll'), - 'geometry': fields.Integer(required=True, description='The number of sides on each die'), - 'discard_lowest': fields.Boolean(required=False, default=False, description='Drop the lowest score') -}) +dice_model = dice.model('Dice', dice_model) +ability_model = ability.model('Ability', ability_model) +hp_model = hp.model('HP', hp_model) -ability_model = ability.model('Ability', { - 'chartype': fields.String(required=False, default="human", description='Character type') -}) -hp_model = hp.model('HP', { - 'chartype': fields.String(required=False, default="human", description='Character type'), - 'conscore': fields.Integer(required=True, description='Conscore') -}) +class DiceSchema(Schema): + quantity = fields.Int(required=True, validate=validate.Range(min=1), description='The number of dice to roll') + geometry = fields.Int(required=True, validate=validate.Range(min=2), description='The number of sides on each die') + discard_lowest = fields.Bool(default=False, description='Drop the lowest score') + + +dice_schema = DiceSchema() @api.route('/roll/dice', methods=['POST']) @@ -32,6 +32,9 @@ class RollDice(Resource): @dice.expect(dice_model) def post(self): data = api.payload + errors = dice_schema.validate(data) + if errors: + return errors, 400 quantity = data.get('quantity') geometry = data.get('geometry') discard_lowest = data.get('discard_lowest') @@ -83,16 +86,31 @@ class RollToHit(Resource): def roll_dices(dice_count, dice_sides, discard_lowest): roll_results = [] + discarded = [] for _ in range(dice_count): roll_results.append(random.randint(1, dice_sides)) if discard_lowest and len(roll_results) > 0: + discarded.append(min(roll_results)) roll_results.remove(min(roll_results)) + if discarded: + net_dice_count = dice_count -1 + mnemonic = str(dice_count)+"(-1)d"+str(dice_sides) + else: + mnemonic = str(dice_count)+'d'+str(dice_sides) + net_dice_count = dice_count + result = { - 'die-set': {'quantity': dice_count, 'geometry': dice_sides}, + 'dice-set': { + 'mnemonic': mnemonic, + 'min-roll': net_dice_count, + 'max-roll': dice_sides*net_dice_count + }, 'rolls': roll_results, - 'sum': sum(roll_results) + 'result': sum(roll_results) } + if discarded: + result['discarded'] = discarded return result diff --git a/models.py b/models.py new file mode 100644 index 0000000..37ab988 --- /dev/null +++ b/models.py @@ -0,0 +1,23 @@ +from flask_restx import fields + +# Common fields +chartype_field = fields.String(required=False, default="human", description='Character type. Allowed values: "human", ' + '"mutant", "android", "robot"') + +# Dice model +dice_model = { + 'quantity': fields.Integer(required=True, description='The number of dice to roll'), + 'geometry': fields.Integer(required=True, description='The number of sides on each die'), + 'discard_lowest': fields.Boolean(required=False, default=False, description='Drop the lowest score') +} + +# Ability model +ability_model = { + 'chartype': chartype_field +} + +# Hp model +hp_model = { + 'chartype': chartype_field, + 'conscore': fields.Integer(required=True, description='Conscore') +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..23a2b0e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +Flask~=3.0.3 +flask-restx~=1.3.0 +marshmallow~=3.21.3 \ No newline at end of file