diff --git a/app.py b/app.py index 065b0fa..f2787c9 100644 --- a/app.py +++ b/app.py @@ -2,8 +2,9 @@ from flask import Flask from flask_cors import CORS from flask_restx import Api, Resource -from models import dice_model, ability_model, hp_model, character_model, encounter_model, ma_model -from schemas import DiceSchema, CharacterSchema, EncounterSchema, MentalAttackSchema, AbilitySchema +from models import dice_model, ability_model, hp_model, character_model, encounter_model, ma_model, mutation_model +from schemas import DiceSchema, CharacterSchema, EncounterSchema, MentalAttackSchema, AbilitySchema, HPSchema, \ + MutationSchema from encounters import EncounterTable from mentattack import MentalAttackMatrix @@ -23,14 +24,18 @@ dice = api.namespace('dice', description='Dice operations') ability = api.namespace('ability', description='Ability operations') hp = api.namespace('hp', description='HP operations') ma = api.namespace('ma', description='Mental Attack operations') +mut = api.namespace('mut', description='Mutation operations') character = api.namespace('character', description='Character operations') encounter = api.namespace('encounter', description='Encounter operations') ability_model = ability.model('Ability', ability_model) ability_schema = AbilitySchema() +mutation_model = mut.model('Mutation', mutation_model) +mutation_schema = MutationSchema() + hp_model = hp.model('HP', hp_model) -# TODO: Add hitpoint schema +hp_schema = HPSchema() dice_model = dice.model('Dice', dice_model) dice_schema = DiceSchema() @@ -81,6 +86,9 @@ class RollHP(Resource): @hp.expect(hp_model) def post(self): data = api.payload + errors = ability_schema.validate(data) + if errors: + return errors, 400 chartype = data.get('chartype') conscore = data.get('conscore') if conscore is None: @@ -158,23 +166,41 @@ class RollMentalAttack(Resource): @api.route('/roll/tohit', methods=['GET']) class RollToHit(Resource): - def get(self): + @staticmethod + def get(): return roll_dices(1, 20, False), 200 @api.route('/roll/chance', methods=['GET']) class RollChance(Resource): - def get(self): + @staticmethod + def get(): return roll_dices(1, 100, False), 200 @api.route('/coinflip', methods=['GET']) class RollCoinflip(Resource): - def get(self): + @staticmethod + def get(): return random.choice(['Heads', 'Tails']), 200 -@api.route('/character/generate') +@api.route('/roll/mutations', methods=['POST']) +class RollMutations(Resource): + @mut.expect(mutation_model) + def post(self): + data = api.payload + errors = mutation_schema.validate(data) + if errors: + return errors, 400 + + conscore = data.get('conscore') + intscore = data.get('intscore') + + return roll_mutations(conscore, intscore), 200 + + +@api.route('/character/generate', methods=['POST']) class GenerateCharacter(Resource): @character.expect(character_model) def post(self): @@ -337,44 +363,37 @@ def roll_mutations(conscore, intscore): physical_mutations_cnt = roll_dices(1, 4, False).get('result') mutations_table['count'] = {'mental': mental_mutations_cnt, 'physical': physical_mutations_cnt} - mental_mutations_scores = [] - physical_mutations_scores = [] + mental_mutations_scores = get_score_list(mental_mutations_cnt, intscore) + mutations_table['mental'] = get_mutations(mental_mutations_scores) - for _ in range(mental_mutations_cnt): - mscore = roll_dices(1, 100, False).get('result') + intscore - if mscore in mental_mutations_scores: - mscore = roll_dices(1, 100, False).get('result') + intscore - if mscore > 100: - mscore = 100 - mental_mutations_scores.append(mscore) - - for _ in range(physical_mutations_cnt): - pscore = roll_dices(1, 100, False).get('result') + conscore - if pscore in physical_mutations_scores: - pscore = roll_dices(1, 100, False).get('result') + conscore - if pscore > 100: - pscore = 100 - physical_mutations_scores.append(pscore) - - mut = Mutations() - mmut = [] - pmut = [] - - for score in mental_mutations_scores: - mutation = mut.get_mental_mutation(score) - mmut.append(mutation) - - mutations_table['mental'] = mmut - - for score in physical_mutations_scores: - mutation = mut.get_physical_mutation(score) - pmut.append(mutation) - - mutations_table['physical'] = pmut + physical_mutations_scores = get_score_list(physical_mutations_cnt, conscore) + mutations_table['physical'] = get_mutations(physical_mutations_scores) return mutations_table +def get_mutations(scorelist): + mut_table = Mutations() + mut_list = [] + for score in scorelist: + mutation = mut_table.get_mental_mutation(score) + mut_list.append(mutation) + return mut_list + + +def get_score_list(count, modifier): + tmp_scores = [] + for _ in range(count): + roll = roll_dices(1, 100, False).get('result') + modifier + if roll in tmp_scores: + roll = roll_dices(1, 100, False).get('result') + modifier + if roll > 100: + roll = 100 + tmp_scores.append(roll) + + return tmp_scores + + def roll_mutant_animal(): creature = dict() @@ -398,7 +417,6 @@ def roll_mutant_animal(): if creature['posture'] == 'prone': creature['legs'] = random.choice(list(range(4, 8, 2))) # if you're prone, you only get legs - return creature diff --git a/models.py b/models.py index e6a0c93..bf95edb 100644 --- a/models.py +++ b/models.py @@ -2,10 +2,27 @@ from flask_restx import fields # Common fields chartype_field = fields.String( - required=False, + required=True, default="human", description='Character type. Allowed values: "human", "humanoid", "mutant", "cyborg"') +# Mutations Model +mutation_model = { + 'conscore': fields.Integer( + required=True, + default=3, + min=3, + max=18, + description='The characters constitution score' + ), + 'intscore': fields.Integer( + required=True, + default=3, + min=3, + max=21, + description='The characters intelligence score' + ) +} # Dice model dice_model = { 'quantity': fields.Integer(required=True, description='The number of dice to roll'), diff --git a/schemas.py b/schemas.py index 8b70ba5..d92c817 100644 --- a/schemas.py +++ b/schemas.py @@ -7,10 +7,43 @@ chartype_field = fields.String( ) +class MutationSchema(Schema): + conscore = fields.Integer( + required=True, + validate=validate.Range(min=3, max=18), + description='The characters constitution score' + ) + intscore = fields.Integer( + required=True, + validate=validate.Range(min=3, max=21), + description='The characters intelligence score' + ) + + +class HPSchema(Schema): + chartype = chartype_field + conscore = fields.Integer( + required=True, + default=10, + validate=validate.Range(min=3, max=24), + description='The constitution score of the character' + ) + + 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') + quantity = fields.Int( + required=True, + default=1, + validate=validate.Range(min=1), + description='The number of dice to roll' + ) + geometry = fields.Int( + required=True, + default=2, + validate=validate.Range(min=2), + description='The number of sides on each die' + ) + discard_lowest = fields.Bool(required=True, default=False, description='Drop the lowest score') class CharacterSchema(Schema):